CNDP  22.08.0
acl_run.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2010-2022 Intel Corporation
3  */
4 
5 #ifndef _ACL_RUN_H_
6 #define _ACL_RUN_H_
7 
13 #include <cne_acl.h>
14 #include "acl.h"
15 
16 #define MAX_SEARCHES_AVX16 16
17 #define MAX_SEARCHES_SSE8 8
18 #define MAX_SEARCHES_ALTIVEC8 8
19 #define MAX_SEARCHES_SSE4 4
20 #define MAX_SEARCHES_ALTIVEC4 4
21 #define MAX_SEARCHES_SCALAR 2
22 
23 #define GET_NEXT_4BYTES(prm, idx) \
24  (*((const int32_t *)((prm)[(idx)].data + *(prm)[idx].data_index++)))
25 
26 #define CNE_ACL_NODE_INDEX ((uint32_t)~CNE_ACL_NODE_TYPE)
27 
28 #define SCALAR_QRANGE_MULT 0x01010101
29 #define SCALAR_QRANGE_MASK 0x7f7f7f7f
30 #define SCALAR_QRANGE_MIN 0x80808080
31 
32 /*
33  * Structure to manage N parallel trie traversals.
34  * The runtime trie traversal routines can process 8, 4, or 2 tries
35  * in parallel. Each packet may require multiple trie traversals (up to 4).
36  * This structure is used to fill the slots (0 to n-1) for parallel processing
37  * with the trie traversals needed for each packet.
38  */
39 struct acl_flow_data {
40  uint32_t num_packets;
41  /* number of packets processed */
42  uint32_t started;
43  /* number of trie traversals in progress */
44  uint32_t trie;
45  /* current trie index (0 to N-1) */
46  uint32_t cmplt_size;
47  /* maximum number of packets to process */
48  uint32_t total_packets;
49  /* number of result categories per packet. */
50  uint32_t categories;
51  const uint64_t *trans;
52  const uint8_t **data;
53  uint32_t *results;
54  struct completion *last_cmplt;
55  struct completion *cmplt_array;
56 };
57 
58 /*
59  * Structure to maintain running results for
60  * a single packet (up to 4 tries).
61  */
62 struct completion {
63  uint32_t *results; /* running results. */
64  int32_t priority[CNE_ACL_MAX_CATEGORIES]; /* running priorities. */
65  uint32_t count; /* num of remaining tries */
66  /* true for allocated struct */
67 } __cne_aligned(XMM_SIZE);
68 
69 /*
70  * One parms structure for each slot in the search engine.
71  */
72 struct parms {
73  const uint8_t *data;
74  /* input data for this packet */
75  const uint32_t *data_index;
76  /* data indirection for this trie */
77  struct completion *cmplt;
78  /* completion data for this packet */
79 };
80 
81 /*
82  * Define an global idle node for unused engine slots
83  */
84 static const uint32_t idle[UINT8_MAX + 1];
85 
86 /*
87  * Allocate a completion structure to manage the tries for a packet.
88  */
89 static inline struct completion *
90 alloc_completion(struct completion *p, uint32_t size, uint32_t tries, uint32_t *results)
91 {
92  uint32_t n;
93 
94  for (n = 0; n < size; n++) {
95 
96  if (p[n].count == 0) {
97 
98  /* mark as allocated and set number of tries. */
99  p[n].count = tries;
100  p[n].results = results;
101  return &(p[n]);
102  }
103  }
104 
105  /* should never get here */
106  return NULL;
107 }
108 
109 /*
110  * Resolve priority for a single result trie.
111  */
112 static inline void
113 resolve_single_priority(uint64_t transition, int n, const struct cne_acl_ctx *ctx,
114  struct parms *parms, const struct cne_acl_match_results *p)
115 {
116  if (parms[n].cmplt->count == ctx->num_tries ||
117  parms[n].cmplt->priority[0] <= p[transition].priority[0]) {
118 
119  parms[n].cmplt->priority[0] = p[transition].priority[0];
120  parms[n].cmplt->results[0] = p[transition].results[0];
121  }
122 }
123 
124 /*
125  * Routine to fill a slot in the parallel trie traversal array (parms) from
126  * the list of packets (flows).
127  */
128 static inline uint64_t
129 acl_start_next_trie(struct acl_flow_data *flows, struct parms *parms, int n,
130  const struct cne_acl_ctx *ctx)
131 {
132  uint64_t transition;
133 
134  /* if there are any more packets to process */
135  if (flows->num_packets < flows->total_packets) {
136  parms[n].data = flows->data[flows->num_packets];
137  parms[n].data_index = ctx->trie[flows->trie].data_index;
138 
139  /* if this is the first trie for this packet */
140  if (flows->trie == 0) {
141  flows->last_cmplt =
142  alloc_completion(flows->cmplt_array, flows->cmplt_size, ctx->num_tries,
143  flows->results + flows->num_packets * flows->categories);
144  }
145 
146  /* set completion parameters and starting index for this slot */
147  parms[n].cmplt = flows->last_cmplt;
148  transition =
149  flows->trans[parms[n].data[*parms[n].data_index++] + ctx->trie[flows->trie].root_index];
150 
151  /*
152  * if this is the last trie for this packet,
153  * then setup next packet.
154  */
155  flows->trie++;
156  if (flows->trie >= ctx->num_tries) {
157  flows->trie = 0;
158  flows->num_packets++;
159  }
160 
161  /* keep track of number of active trie traversals */
162  flows->started++;
163 
164  /* no more tries to process, set slot to an idle position */
165  } else {
166  transition = ctx->idle;
167  parms[n].data = (const uint8_t *)idle;
168  parms[n].data_index = idle;
169  }
170  return transition;
171 }
172 
173 static inline void
174 acl_set_flow(struct acl_flow_data *flows, struct completion *cmplt, uint32_t cmplt_size,
175  const uint8_t **data, uint32_t *results, uint32_t data_num, uint32_t categories,
176  const uint64_t *trans)
177 {
178  flows->num_packets = 0;
179  flows->started = 0;
180  flows->trie = 0;
181  flows->last_cmplt = NULL;
182  flows->cmplt_array = cmplt;
183  flows->total_packets = data_num;
184  flows->categories = categories;
185  flows->cmplt_size = cmplt_size;
186  flows->data = data;
187  flows->results = results;
188  flows->trans = trans;
189 }
190 
191 typedef void (*resolve_priority_t)(uint64_t transition, int n, const struct cne_acl_ctx *ctx,
192  struct parms *parms, const struct cne_acl_match_results *p,
193  uint32_t categories);
194 
195 /*
196  * Detect matches. If a match node transition is found, then this trie
197  * traversal is complete and fill the slot with the next trie
198  * to be processed.
199  */
200 static inline uint64_t
201 acl_match_check(uint64_t transition, int slot, const struct cne_acl_ctx *ctx, struct parms *parms,
202  struct acl_flow_data *flows, resolve_priority_t resolve_priority)
203 {
204  const struct cne_acl_match_results *p;
205 
206  p = (const struct cne_acl_match_results *)(flows->trans + ctx->match_index);
207 
208  if (transition & CNE_ACL_NODE_MATCH) {
209 
210  /* Remove flags from index and decrement active traversals */
211  transition &= (uint64_t)CNE_ACL_NODE_INDEX;
212  flows->started--;
213 
214  /* Resolve priorities for this trie and running results */
215  if (flows->categories == 1)
216  resolve_single_priority(transition, slot, ctx, parms, p);
217  else
218  resolve_priority(transition, slot, ctx, parms, p, flows->categories);
219 
220  /* Count down completed tries for this search request */
221  parms[slot].cmplt->count--;
222 
223  /* Fill the slot with the next trie or idle trie */
224  transition = acl_start_next_trie(flows, parms, slot, ctx);
225  }
226 
227  return transition;
228 }
229 
230 #endif /* _ACL_RUN_H_ */
#define __cne_aligned(a)
Definition: cne_common.h:124