1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
11 #define MAX_SEARCHES_AVX16 16
12 #define MAX_SEARCHES_SSE8 8
13 #define MAX_SEARCHES_ALTIVEC8 8
14 #define MAX_SEARCHES_SSE4 4
15 #define MAX_SEARCHES_ALTIVEC4 4
16 #define MAX_SEARCHES_SCALAR 2
18 #define GET_NEXT_4BYTES(prm, idx) \
19 (*((const int32_t *)((prm)[(idx)].data + *(prm)[idx].data_index++)))
22 #define RTE_ACL_NODE_INDEX ((uint32_t)~RTE_ACL_NODE_TYPE)
24 #define SCALAR_QRANGE_MULT 0x01010101
25 #define SCALAR_QRANGE_MASK 0x7f7f7f7f
26 #define SCALAR_QRANGE_MIN 0x80808080
29 * Structure to manage N parallel trie traversals.
30 * The runtime trie traversal routines can process 8, 4, or 2 tries
31 * in parallel. Each packet may require multiple trie traversals (up to 4).
32 * This structure is used to fill the slots (0 to n-1) for parallel processing
33 * with the trie traversals needed for each packet.
35 struct acl_flow_data
{
37 /* number of packets processed */
39 /* number of trie traversals in progress */
41 /* current trie index (0 to N-1) */
43 /* maximum number of packets to process */
44 uint32_t total_packets
;
45 /* number of result categories per packet. */
47 const uint64_t *trans
;
50 struct completion
*last_cmplt
;
51 struct completion
*cmplt_array
;
55 * Structure to maintain running results for
56 * a single packet (up to 4 tries).
59 uint32_t *results
; /* running results. */
60 int32_t priority
[RTE_ACL_MAX_CATEGORIES
]; /* running priorities. */
61 uint32_t count
; /* num of remaining tries */
62 /* true for allocated struct */
63 } __rte_aligned(XMM_SIZE
);
66 * One parms structure for each slot in the search engine.
70 /* input data for this packet */
71 const uint32_t *data_index
;
72 /* data indirection for this trie */
73 struct completion
*cmplt
;
74 /* completion data for this packet */
78 * Define an global idle node for unused engine slots
80 static const uint32_t idle
[UINT8_MAX
+ 1];
83 * Allocate a completion structure to manage the tries for a packet.
85 static inline struct completion
*
86 alloc_completion(struct completion
*p
, uint32_t size
, uint32_t tries
,
91 for (n
= 0; n
< size
; n
++) {
93 if (p
[n
].count
== 0) {
95 /* mark as allocated and set number of tries. */
97 p
[n
].results
= results
;
102 /* should never get here */
107 * Resolve priority for a single result trie.
110 resolve_single_priority(uint64_t transition
, int n
,
111 const struct rte_acl_ctx
*ctx
, struct parms
*parms
,
112 const struct rte_acl_match_results
*p
)
114 if (parms
[n
].cmplt
->count
== ctx
->num_tries
||
115 parms
[n
].cmplt
->priority
[0] <=
116 p
[transition
].priority
[0]) {
118 parms
[n
].cmplt
->priority
[0] = p
[transition
].priority
[0];
119 parms
[n
].cmplt
->results
[0] = p
[transition
].results
[0];
124 * Routine to fill a slot in the parallel trie traversal array (parms) from
125 * the list of packets (flows).
127 static inline uint64_t
128 acl_start_next_trie(struct acl_flow_data
*flows
, struct parms
*parms
, int n
,
129 const struct rte_acl_ctx
*ctx
)
133 /* if there are any more packets to process */
134 if (flows
->num_packets
< flows
->total_packets
) {
135 parms
[n
].data
= flows
->data
[flows
->num_packets
];
136 parms
[n
].data_index
= ctx
->trie
[flows
->trie
].data_index
;
138 /* if this is the first trie for this packet */
139 if (flows
->trie
== 0) {
140 flows
->last_cmplt
= alloc_completion(flows
->cmplt_array
,
141 flows
->cmplt_size
, ctx
->num_tries
,
143 flows
->num_packets
* flows
->categories
);
146 /* set completion parameters and starting index for this slot */
147 parms
[n
].cmplt
= flows
->last_cmplt
;
149 flows
->trans
[parms
[n
].data
[*parms
[n
].data_index
++] +
150 ctx
->trie
[flows
->trie
].root_index
];
153 * if this is the last trie for this packet,
154 * then setup next packet.
157 if (flows
->trie
>= ctx
->num_tries
) {
159 flows
->num_packets
++;
162 /* keep track of number of active trie traversals */
165 /* no more tries to process, set slot to an idle position */
167 transition
= ctx
->idle
;
168 parms
[n
].data
= (const uint8_t *)idle
;
169 parms
[n
].data_index
= idle
;
175 acl_set_flow(struct acl_flow_data
*flows
, struct completion
*cmplt
,
176 uint32_t cmplt_size
, const uint8_t **data
, uint32_t *results
,
177 uint32_t data_num
, uint32_t categories
, const uint64_t *trans
)
179 flows
->num_packets
= 0;
182 flows
->last_cmplt
= NULL
;
183 flows
->cmplt_array
= cmplt
;
184 flows
->total_packets
= data_num
;
185 flows
->categories
= categories
;
186 flows
->cmplt_size
= cmplt_size
;
188 flows
->results
= results
;
189 flows
->trans
= trans
;
192 typedef void (*resolve_priority_t
)
193 (uint64_t transition
, int n
, const struct rte_acl_ctx
*ctx
,
194 struct parms
*parms
, const struct rte_acl_match_results
*p
,
195 uint32_t categories
);
198 * Detect matches. If a match node transition is found, then this trie
199 * traversal is complete and fill the slot with the next trie
202 static inline uint64_t
203 acl_match_check(uint64_t transition
, int slot
,
204 const struct rte_acl_ctx
*ctx
, struct parms
*parms
,
205 struct acl_flow_data
*flows
, resolve_priority_t resolve_priority
)
207 const struct rte_acl_match_results
*p
;
209 p
= (const struct rte_acl_match_results
*)
210 (flows
->trans
+ ctx
->match_index
);
212 if (transition
& RTE_ACL_NODE_MATCH
) {
214 /* Remove flags from index and decrement active traversals */
215 transition
&= RTE_ACL_NODE_INDEX
;
218 /* Resolve priorities for this trie and running results */
219 if (flows
->categories
== 1)
220 resolve_single_priority(transition
, slot
, ctx
,
223 resolve_priority(transition
, slot
, ctx
, parms
,
224 p
, flows
->categories
);
226 /* Count down completed tries for this search request */
227 parms
[slot
].cmplt
->count
--;
229 /* Fill the slot with the next trie or idle trie */
230 transition
= acl_start_next_trie(flows
, parms
, slot
, ctx
);
236 #endif /* _ACL_RUN_H_ */