]> git.proxmox.com Git - ceph.git/blob - ceph/src/dpdk/lib/librte_acl/acl_run.h
bump version to 12.2.12-pve1
[ceph.git] / ceph / src / dpdk / lib / librte_acl / acl_run.h
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #ifndef _ACL_RUN_H_
35 #define _ACL_RUN_H_
36
37 #include <rte_acl.h>
38 #include "acl.h"
39
40 #define MAX_SEARCHES_AVX16 16
41 #define MAX_SEARCHES_SSE8 8
42 #define MAX_SEARCHES_ALTIVEC8 8
43 #define MAX_SEARCHES_SSE4 4
44 #define MAX_SEARCHES_ALTIVEC4 4
45 #define MAX_SEARCHES_SCALAR 2
46
47 #define GET_NEXT_4BYTES(prm, idx) \
48 (*((const int32_t *)((prm)[(idx)].data + *(prm)[idx].data_index++)))
49
50
51 #define RTE_ACL_NODE_INDEX ((uint32_t)~RTE_ACL_NODE_TYPE)
52
53 #define SCALAR_QRANGE_MULT 0x01010101
54 #define SCALAR_QRANGE_MASK 0x7f7f7f7f
55 #define SCALAR_QRANGE_MIN 0x80808080
56
57 /*
58 * Structure to manage N parallel trie traversals.
59 * The runtime trie traversal routines can process 8, 4, or 2 tries
60 * in parallel. Each packet may require multiple trie traversals (up to 4).
61 * This structure is used to fill the slots (0 to n-1) for parallel processing
62 * with the trie traversals needed for each packet.
63 */
64 struct acl_flow_data {
65 uint32_t num_packets;
66 /* number of packets processed */
67 uint32_t started;
68 /* number of trie traversals in progress */
69 uint32_t trie;
70 /* current trie index (0 to N-1) */
71 uint32_t cmplt_size;
72 uint32_t total_packets;
73 uint32_t categories;
74 /* number of result categories per packet. */
75 /* maximum number of packets to process */
76 const uint64_t *trans;
77 const uint8_t **data;
78 uint32_t *results;
79 struct completion *last_cmplt;
80 struct completion *cmplt_array;
81 };
82
83 /*
84 * Structure to maintain running results for
85 * a single packet (up to 4 tries).
86 */
87 struct completion {
88 uint32_t *results; /* running results. */
89 int32_t priority[RTE_ACL_MAX_CATEGORIES]; /* running priorities. */
90 uint32_t count; /* num of remaining tries */
91 /* true for allocated struct */
92 } __attribute__((aligned(XMM_SIZE)));
93
94 /*
95 * One parms structure for each slot in the search engine.
96 */
97 struct parms {
98 const uint8_t *data;
99 /* input data for this packet */
100 const uint32_t *data_index;
101 /* data indirection for this trie */
102 struct completion *cmplt;
103 /* completion data for this packet */
104 };
105
106 /*
107 * Define an global idle node for unused engine slots
108 */
109 static const uint32_t idle[UINT8_MAX + 1];
110
111 /*
112 * Allocate a completion structure to manage the tries for a packet.
113 */
114 static inline struct completion *
115 alloc_completion(struct completion *p, uint32_t size, uint32_t tries,
116 uint32_t *results)
117 {
118 uint32_t n;
119
120 for (n = 0; n < size; n++) {
121
122 if (p[n].count == 0) {
123
124 /* mark as allocated and set number of tries. */
125 p[n].count = tries;
126 p[n].results = results;
127 return &(p[n]);
128 }
129 }
130
131 /* should never get here */
132 return NULL;
133 }
134
135 /*
136 * Resolve priority for a single result trie.
137 */
138 static inline void
139 resolve_single_priority(uint64_t transition, int n,
140 const struct rte_acl_ctx *ctx, struct parms *parms,
141 const struct rte_acl_match_results *p)
142 {
143 if (parms[n].cmplt->count == ctx->num_tries ||
144 parms[n].cmplt->priority[0] <=
145 p[transition].priority[0]) {
146
147 parms[n].cmplt->priority[0] = p[transition].priority[0];
148 parms[n].cmplt->results[0] = p[transition].results[0];
149 }
150 }
151
152 /*
153 * Routine to fill a slot in the parallel trie traversal array (parms) from
154 * the list of packets (flows).
155 */
156 static inline uint64_t
157 acl_start_next_trie(struct acl_flow_data *flows, struct parms *parms, int n,
158 const struct rte_acl_ctx *ctx)
159 {
160 uint64_t transition;
161
162 /* if there are any more packets to process */
163 if (flows->num_packets < flows->total_packets) {
164 parms[n].data = flows->data[flows->num_packets];
165 parms[n].data_index = ctx->trie[flows->trie].data_index;
166
167 /* if this is the first trie for this packet */
168 if (flows->trie == 0) {
169 flows->last_cmplt = alloc_completion(flows->cmplt_array,
170 flows->cmplt_size, ctx->num_tries,
171 flows->results +
172 flows->num_packets * flows->categories);
173 }
174
175 /* set completion parameters and starting index for this slot */
176 parms[n].cmplt = flows->last_cmplt;
177 transition =
178 flows->trans[parms[n].data[*parms[n].data_index++] +
179 ctx->trie[flows->trie].root_index];
180
181 /*
182 * if this is the last trie for this packet,
183 * then setup next packet.
184 */
185 flows->trie++;
186 if (flows->trie >= ctx->num_tries) {
187 flows->trie = 0;
188 flows->num_packets++;
189 }
190
191 /* keep track of number of active trie traversals */
192 flows->started++;
193
194 /* no more tries to process, set slot to an idle position */
195 } else {
196 transition = ctx->idle;
197 parms[n].data = (const uint8_t *)idle;
198 parms[n].data_index = idle;
199 }
200 return transition;
201 }
202
203 static inline void
204 acl_set_flow(struct acl_flow_data *flows, struct completion *cmplt,
205 uint32_t cmplt_size, const uint8_t **data, uint32_t *results,
206 uint32_t data_num, uint32_t categories, const uint64_t *trans)
207 {
208 flows->num_packets = 0;
209 flows->started = 0;
210 flows->trie = 0;
211 flows->last_cmplt = NULL;
212 flows->cmplt_array = cmplt;
213 flows->total_packets = data_num;
214 flows->categories = categories;
215 flows->cmplt_size = cmplt_size;
216 flows->data = data;
217 flows->results = results;
218 flows->trans = trans;
219 }
220
221 typedef void (*resolve_priority_t)
222 (uint64_t transition, int n, const struct rte_acl_ctx *ctx,
223 struct parms *parms, const struct rte_acl_match_results *p,
224 uint32_t categories);
225
226 /*
227 * Detect matches. If a match node transition is found, then this trie
228 * traversal is complete and fill the slot with the next trie
229 * to be processed.
230 */
231 static inline uint64_t
232 acl_match_check(uint64_t transition, int slot,
233 const struct rte_acl_ctx *ctx, struct parms *parms,
234 struct acl_flow_data *flows, resolve_priority_t resolve_priority)
235 {
236 const struct rte_acl_match_results *p;
237
238 p = (const struct rte_acl_match_results *)
239 (flows->trans + ctx->match_index);
240
241 if (transition & RTE_ACL_NODE_MATCH) {
242
243 /* Remove flags from index and decrement active traversals */
244 transition &= RTE_ACL_NODE_INDEX;
245 flows->started--;
246
247 /* Resolve priorities for this trie and running results */
248 if (flows->categories == 1)
249 resolve_single_priority(transition, slot, ctx,
250 parms, p);
251 else
252 resolve_priority(transition, slot, ctx, parms,
253 p, flows->categories);
254
255 /* Count down completed tries for this search request */
256 parms[slot].cmplt->count--;
257
258 /* Fill the slot with the next trie or idle trie */
259 transition = acl_start_next_trie(flows, parms, slot, ctx);
260 }
261
262 return transition;
263 }
264
265 #endif /* _ACL_RUN_H_ */