Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #ifndef _ACL_RUN_H_
6 : : #define _ACL_RUN_H_
7 : :
8 : : #include <rte_acl.h>
9 : : #include "acl.h"
10 : :
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
17 : :
18 : : #define GET_NEXT_4BYTES(prm, idx) \
19 : : (*((const int32_t *)((prm)[(idx)].data + *(prm)[idx].data_index++)))
20 : :
21 : :
22 : : #define RTE_ACL_NODE_INDEX ((uint32_t)~RTE_ACL_NODE_TYPE)
23 : :
24 : : #define SCALAR_QRANGE_MULT 0x01010101
25 : : #define SCALAR_QRANGE_MASK 0x7f7f7f7f
26 : : #define SCALAR_QRANGE_MIN 0x80808080
27 : :
28 : : /*
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.
34 : : */
35 : : struct acl_flow_data {
36 : : uint32_t num_packets;
37 : : /* number of packets processed */
38 : : uint32_t started;
39 : : /* number of trie traversals in progress */
40 : : uint32_t trie;
41 : : /* current trie index (0 to N-1) */
42 : : uint32_t cmplt_size;
43 : : /* maximum number of packets to process */
44 : : uint32_t total_packets;
45 : : /* number of result categories per packet. */
46 : : uint32_t categories;
47 : : const uint64_t *trans;
48 : : const uint8_t **data;
49 : : uint32_t *results;
50 : : struct completion *last_cmplt;
51 : : struct completion *cmplt_array;
52 : : };
53 : :
54 : : /*
55 : : * Structure to maintain running results for
56 : : * a single packet (up to 4 tries).
57 : : */
58 : : struct __rte_aligned(XMM_SIZE) completion {
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 : : };
64 : :
65 : : /*
66 : : * One parms structure for each slot in the search engine.
67 : : */
68 : : struct parms {
69 : : const uint8_t *data;
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 */
75 : : };
76 : :
77 : : /*
78 : : * Define an global idle node for unused engine slots
79 : : */
80 : : static const uint32_t idle[UINT8_MAX + 1];
81 : :
82 : : /*
83 : : * Allocate a completion structure to manage the tries for a packet.
84 : : */
85 : : static inline struct completion *
86 : : alloc_completion(struct completion *p, uint32_t size, uint32_t tries,
87 : : uint32_t *results)
88 : : {
89 : : uint32_t n;
90 : :
91 [ + - ]: 118846789 : for (n = 0; n < size; n++) {
92 : :
93 [ + + ]: 118846789 : if (p[n].count == 0) {
94 : :
95 : : /* mark as allocated and set number of tries. */
96 : 26375672 : p[n].count = tries;
97 : 26375672 : p[n].results = results;
98 : 26375672 : return &(p[n]);
99 : : }
100 : : }
101 : :
102 : : /* should never get here */
103 : : return NULL;
104 : : }
105 : :
106 : : /*
107 : : * Resolve priority for a single result trie.
108 : : */
109 : : static inline void
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)
113 : : {
114 [ - + ]: 34 : if (parms[n].cmplt->count == ctx->num_tries ||
115 : 0 : parms[n].cmplt->priority[0] <=
116 [ # # ]: 0 : p[transition].priority[0]) {
117 : :
118 : 34 : parms[n].cmplt->priority[0] = p[transition].priority[0];
119 : 34 : parms[n].cmplt->results[0] = p[transition].results[0];
120 : : }
121 : : }
122 : :
123 : : /*
124 : : * Routine to fill a slot in the parallel trie traversal array (parms) from
125 : : * the list of packets (flows).
126 : : */
127 : : static inline uint64_t
128 : 33014185 : acl_start_next_trie(struct acl_flow_data *flows, struct parms *parms, int n,
129 : : const struct rte_acl_ctx *ctx)
130 : : {
131 : : uint64_t transition;
132 : :
133 : : /* if there are any more packets to process */
134 [ + + ]: 33014185 : if (flows->num_packets < flows->total_packets) {
135 : 26503979 : parms[n].data = flows->data[flows->num_packets];
136 : 26503979 : parms[n].data_index = ctx->trie[flows->trie].data_index;
137 : :
138 : : /* if this is the first trie for this packet */
139 [ + + ]: 26503979 : if (flows->trie == 0) {
140 : 26375672 : flows->last_cmplt = alloc_completion(flows->cmplt_array,
141 : 26375672 : flows->cmplt_size, ctx->num_tries,
142 : 26375672 : flows->results +
143 : 26375672 : flows->num_packets * flows->categories);
144 : : }
145 : :
146 : : /* set completion parameters and starting index for this slot */
147 : 26503979 : parms[n].cmplt = flows->last_cmplt;
148 : 26503979 : transition =
149 : 26503979 : flows->trans[parms[n].data[*parms[n].data_index++] +
150 : 26503979 : ctx->trie[flows->trie].root_index];
151 : :
152 : : /*
153 : : * if this is the last trie for this packet,
154 : : * then setup next packet.
155 : : */
156 : 26503979 : flows->trie++;
157 [ + + ]: 26503979 : if (flows->trie >= ctx->num_tries) {
158 : 26375672 : flows->trie = 0;
159 : 26375672 : flows->num_packets++;
160 : : }
161 : :
162 : : /* keep track of number of active trie traversals */
163 : 26503979 : flows->started++;
164 : :
165 : : /* no more tries to process, set slot to an idle position */
166 : : } else {
167 : 6510206 : transition = ctx->idle;
168 : 6510206 : parms[n].data = (const uint8_t *)idle;
169 : 6510206 : parms[n].data_index = idle;
170 : : }
171 : 33014185 : return transition;
172 : : }
173 : :
174 : : static inline void
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)
178 : : {
179 : : unsigned int i;
180 : :
181 : 874933 : flows->num_packets = 0;
182 : 874933 : flows->started = 0;
183 : 874933 : flows->trie = 0;
184 : 874933 : flows->last_cmplt = NULL;
185 : 874933 : flows->cmplt_array = cmplt;
186 : 874933 : flows->total_packets = data_num;
187 : 874933 : flows->categories = categories;
188 : 874933 : flows->cmplt_size = cmplt_size;
189 : 874933 : flows->data = data;
190 : 874933 : flows->results = results;
191 : 874933 : flows->trans = trans;
192 : :
193 [ + + + + : 7385139 : for (i = 0; i < cmplt_size; i++)
+ + ]
194 : 6510206 : cmplt[i].count = 0;
195 : : }
196 : :
197 : : typedef void (*resolve_priority_t)
198 : : (uint64_t transition, int n, const struct rte_acl_ctx *ctx,
199 : : struct parms *parms, const struct rte_acl_match_results *p,
200 : : uint32_t categories);
201 : :
202 : : /*
203 : : * Detect matches. If a match node transition is found, then this trie
204 : : * traversal is complete and fill the slot with the next trie
205 : : * to be processed.
206 : : */
207 : : static inline uint64_t
208 : 28218428 : acl_match_check(uint64_t transition, int slot,
209 : : const struct rte_acl_ctx *ctx, struct parms *parms,
210 : : struct acl_flow_data *flows, resolve_priority_t resolve_priority)
211 : : {
212 : : const struct rte_acl_match_results *p;
213 : :
214 : 28218428 : p = (const struct rte_acl_match_results *)
215 : 28218428 : (flows->trans + ctx->match_index);
216 : :
217 [ + + ]: 28218428 : if (transition & RTE_ACL_NODE_MATCH) {
218 : :
219 : : /* Remove flags from index and decrement active traversals */
220 : 26503979 : transition &= RTE_ACL_NODE_INDEX;
221 : 26503979 : flows->started--;
222 : :
223 : : /* Resolve priorities for this trie and running results */
224 [ + + ]: 26503979 : if (flows->categories == 1)
225 : : resolve_single_priority(transition, slot, ctx,
226 : : parms, p);
227 : : else
228 : 26503945 : resolve_priority(transition, slot, ctx, parms,
229 : : p, flows->categories);
230 : :
231 : : /* Count down completed tries for this search request */
232 : 26503979 : parms[slot].cmplt->count--;
233 : :
234 : : /* Fill the slot with the next trie or idle trie */
235 : 26503979 : transition = acl_start_next_trie(flows, parms, slot, ctx);
236 : : }
237 : :
238 : 28218428 : return transition;
239 : : }
240 : :
241 : : #endif /* _ACL_RUN_H_ */
|