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_ */