Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #include <rte_acl.h>
6 : : #include "acl.h"
7 : : #include "acl_log.h"
8 : :
9 : : #define QRANGE_MIN ((uint8_t)INT8_MIN)
10 : :
11 : : #define RTE_ACL_VERIFY(exp) do { \
12 : : if (!(exp)) \
13 : : rte_panic("line %d\tassert \"" #exp "\" failed\n", __LINE__); \
14 : : } while (0)
15 : :
16 : : struct acl_node_counters {
17 : : int32_t match;
18 : : int32_t match_used;
19 : : int32_t single;
20 : : int32_t quad;
21 : : int32_t quad_vectors;
22 : : int32_t dfa;
23 : : int32_t dfa_gr64;
24 : : };
25 : :
26 : : struct rte_acl_indices {
27 : : int32_t dfa_index;
28 : : int32_t quad_index;
29 : : int32_t single_index;
30 : : int32_t match_index;
31 : : int32_t match_start;
32 : : };
33 : :
34 : : static void
35 : 42 : acl_gen_log_stats(const struct rte_acl_ctx *ctx,
36 : : const struct acl_node_counters *counts,
37 : : const struct rte_acl_indices *indices,
38 : : size_t max_size)
39 : : {
40 : 42 : RTE_LOG(DEBUG, ACL, "Gen phase for ACL \"%s\":\n"
41 : : "runtime memory footprint on socket %d:\n"
42 : : "single nodes/bytes used: %d/%zu\n"
43 : : "quad nodes/vectors/bytes used: %d/%d/%zu\n"
44 : : "DFA nodes/group64/bytes used: %d/%d/%zu\n"
45 : : "match nodes/bytes used: %d/%zu\n"
46 : : "total: %zu bytes\n"
47 : : "max limit: %zu bytes\n",
48 : : ctx->name, ctx->socket_id,
49 : : counts->single, counts->single * sizeof(uint64_t),
50 : : counts->quad, counts->quad_vectors,
51 : : (indices->quad_index - indices->dfa_index) * sizeof(uint64_t),
52 : : counts->dfa, counts->dfa_gr64,
53 : : indices->dfa_index * sizeof(uint64_t),
54 : : counts->match,
55 : : counts->match * sizeof(struct rte_acl_match_results),
56 : : ctx->mem_sz,
57 : : max_size);
58 : 42 : }
59 : :
60 : : static uint64_t
61 : 14531 : acl_dfa_gen_idx(const struct rte_acl_node *node, uint32_t index)
62 : : {
63 : : uint64_t idx;
64 : : uint32_t i;
65 : :
66 : : idx = 0;
67 [ + + ]: 72655 : for (i = 0; i != RTE_DIM(node->dfa_gr64); i++) {
68 [ - + ]: 58124 : RTE_ACL_VERIFY(node->dfa_gr64[i] < RTE_ACL_DFA_GR64_NUM);
69 [ - + ]: 58124 : RTE_ACL_VERIFY(node->dfa_gr64[i] < node->fanout);
70 : 58124 : idx |= (i - node->dfa_gr64[i]) <<
71 : 58124 : (6 + RTE_ACL_DFA_GR64_BIT * i);
72 : : }
73 : :
74 : 14531 : return idx << (CHAR_BIT * sizeof(index)) | index | node->node_type;
75 : : }
76 : :
77 : : static void
78 : 14531 : acl_dfa_fill_gr64(const struct rte_acl_node *node,
79 : : const uint64_t src[RTE_ACL_DFA_SIZE], uint64_t dst[RTE_ACL_DFA_SIZE])
80 : : {
81 : : uint32_t i;
82 : :
83 [ + + ]: 72655 : for (i = 0; i != RTE_DIM(node->dfa_gr64); i++) {
84 : 58124 : memcpy(dst + node->dfa_gr64[i] * RTE_ACL_DFA_GR64_SIZE,
85 : 58124 : src + i * RTE_ACL_DFA_GR64_SIZE,
86 : : RTE_ACL_DFA_GR64_SIZE * sizeof(dst[0]));
87 : : }
88 : 14531 : }
89 : :
90 : : static uint32_t
91 : 14474 : acl_dfa_count_gr64(const uint64_t array_ptr[RTE_ACL_DFA_SIZE],
92 : : uint8_t gr64[RTE_ACL_DFA_GR64_NUM])
93 : : {
94 : : uint32_t i, j, k;
95 : :
96 : : k = 0;
97 [ + + ]: 72370 : for (i = 0; i != RTE_ACL_DFA_GR64_NUM; i++) {
98 : 57896 : gr64[i] = i;
99 [ + + ]: 96851 : for (j = 0; j != i; j++) {
100 : 68730 : if (memcmp(array_ptr + i * RTE_ACL_DFA_GR64_SIZE,
101 [ + + ]: 68730 : array_ptr + j * RTE_ACL_DFA_GR64_SIZE,
102 : : RTE_ACL_DFA_GR64_SIZE *
103 : : sizeof(array_ptr[0])) == 0)
104 : : break;
105 : : }
106 [ + + ]: 57896 : gr64[i] = (j != i) ? gr64[j] : k++;
107 : : }
108 : :
109 : 14474 : return k;
110 : : }
111 : :
112 : : static uint32_t
113 : 157045 : acl_node_fill_dfa(const struct rte_acl_node *node,
114 : : uint64_t dfa[RTE_ACL_DFA_SIZE], uint64_t no_match, int32_t resolved)
115 : : {
116 : : uint32_t n, x;
117 : : uint32_t ranges, last_bit;
118 : : struct rte_acl_node *child;
119 : : struct rte_acl_bitset *bits;
120 : :
121 : : ranges = 0;
122 : : last_bit = 0;
123 : :
124 [ + + ]: 40360565 : for (n = 0; n < RTE_ACL_DFA_SIZE; n++)
125 : 40203520 : dfa[n] = no_match;
126 : :
127 [ + + ]: 632544 : for (x = 0; x < node->num_ptrs; x++) {
128 : :
129 : 475499 : child = node->ptrs[x].ptr;
130 [ + - ]: 475499 : if (child == NULL)
131 : 0 : continue;
132 : :
133 : : bits = &node->ptrs[x].values;
134 [ + + ]: 122203243 : for (n = 0; n < RTE_ACL_DFA_SIZE; n++) {
135 : :
136 : 121727744 : if (bits->bits[n / (sizeof(bits_t) * CHAR_BIT)] &
137 [ + + ]: 121727744 : (1U << (n % (sizeof(bits_t) * CHAR_BIT)))) {
138 : :
139 [ + + ]: 40059250 : dfa[n] = resolved ? child->node_index : x;
140 : 40059250 : ranges += (last_bit == 0);
141 : : last_bit = 1;
142 : : } else {
143 : : last_bit = 0;
144 : : }
145 : : }
146 : : }
147 : :
148 : 157045 : return ranges;
149 : : }
150 : :
151 : : /*
152 : : * Count the number of groups of sequential bits that are either 0 or 1,
153 : : * as specified by the zero_one parameter.
154 : : * This is used to calculate the number of ranges in a node
155 : : * to see if it fits in a quad range node.
156 : : */
157 : : static int
158 : 409036 : acl_count_sequential_groups(struct rte_acl_bitset *bits, int zero_one)
159 : : {
160 : : int n, ranges, last_bit;
161 : :
162 : : ranges = 0;
163 : 409036 : last_bit = zero_one ^ 1;
164 : :
165 [ + + ]: 52765644 : for (n = QRANGE_MIN; n < UINT8_MAX + 1; n++) {
166 : 52356608 : if (bits->bits[n / (sizeof(bits_t) * 8)] &
167 [ + + ]: 52356608 : (1U << (n % (sizeof(bits_t) * 8)))) {
168 [ + + ]: 31897972 : if (zero_one == 1 && last_bit != 1)
169 : 464365 : ranges++;
170 : : last_bit = 1;
171 : : } else {
172 [ + + ]: 20458636 : if (zero_one == 0 && last_bit != 0)
173 : 533 : ranges++;
174 : : last_bit = 0;
175 : : }
176 : : }
177 [ + + ]: 52765644 : for (n = 0; n < QRANGE_MIN; n++) {
178 : 52356608 : if (bits->bits[n / (sizeof(bits_t) * 8)] &
179 [ + + ]: 52356608 : (1U << (n % (sizeof(bits_t) * CHAR_BIT)))) {
180 [ + + ]: 31898880 : if (zero_one == 1 && last_bit != 1)
181 : 461126 : ranges++;
182 : : last_bit = 1;
183 : : } else {
184 [ + + ]: 20457728 : if (zero_one == 0 && last_bit != 0)
185 : 544 : ranges++;
186 : : last_bit = 0;
187 : : }
188 : : }
189 : :
190 : 409036 : return ranges;
191 : : }
192 : :
193 : : /*
194 : : * Count number of ranges spanned by the node's pointers
195 : : */
196 : : static int
197 : 124886 : acl_count_fanout(struct rte_acl_node *node)
198 : : {
199 : : uint32_t n;
200 : : int ranges;
201 : :
202 [ + - ]: 124886 : if (node->fanout != 0)
203 : : return node->fanout;
204 : :
205 : 124886 : ranges = acl_count_sequential_groups(&node->values, 0);
206 : :
207 [ + + ]: 409036 : for (n = 0; n < node->num_ptrs; n++) {
208 [ + - ]: 284150 : if (node->ptrs[n].ptr != NULL)
209 : 284150 : ranges += acl_count_sequential_groups(
210 : : &node->ptrs[n].values, 1);
211 : : }
212 : :
213 : 124886 : node->fanout = ranges;
214 : 124886 : return node->fanout;
215 : : }
216 : :
217 : : /*
218 : : * Determine the type of nodes and count each type
219 : : */
220 : : static void
221 : 284207 : acl_count_trie_types(struct acl_node_counters *counts,
222 : : struct rte_acl_node *node, uint64_t no_match, int force_dfa)
223 : : {
224 : : uint32_t n;
225 : : int num_ptrs;
226 : : uint64_t dfa[RTE_ACL_DFA_SIZE];
227 : :
228 : : /* skip if this node has been counted */
229 [ + + ]: 284207 : if (node->node_type != (uint32_t)RTE_ACL_NODE_UNDEFINED)
230 : 159321 : return;
231 : :
232 [ + + - + ]: 242659 : if (node->match_flag != 0 || node->num_ptrs == 0) {
233 : 117773 : counts->match++;
234 : 117773 : node->node_type = RTE_ACL_NODE_MATCH;
235 : 117773 : return;
236 : : }
237 : :
238 : 124886 : num_ptrs = acl_count_fanout(node);
239 : :
240 : : /* Force type to dfa */
241 [ + + ]: 124886 : if (force_dfa)
242 : : num_ptrs = RTE_ACL_DFA_SIZE;
243 : :
244 : : /* determine node type based on number of ranges */
245 [ + + ]: 124829 : if (num_ptrs == 1) {
246 : 46335 : counts->single++;
247 : 46335 : node->node_type = RTE_ACL_NODE_SINGLE;
248 [ + + ]: 78551 : } else if (num_ptrs <= RTE_ACL_QUAD_MAX) {
249 : 64020 : counts->quad++;
250 : 64020 : counts->quad_vectors += node->fanout;
251 : 64020 : node->node_type = RTE_ACL_NODE_QRANGE;
252 : : } else {
253 : 14531 : counts->dfa++;
254 : 14531 : node->node_type = RTE_ACL_NODE_DFA;
255 [ + + ]: 14531 : if (force_dfa != 0) {
256 : : /* always expand to a max number of nodes. */
257 [ + + ]: 285 : for (n = 0; n != RTE_DIM(node->dfa_gr64); n++)
258 : 228 : node->dfa_gr64[n] = n;
259 : 57 : node->fanout = n;
260 : : } else {
261 : 14474 : acl_node_fill_dfa(node, dfa, no_match, 0);
262 : 14474 : node->fanout = acl_dfa_count_gr64(dfa, node->dfa_gr64);
263 : : }
264 : 14531 : counts->dfa_gr64 += node->fanout;
265 : : }
266 : :
267 : : /*
268 : : * recursively count the types of all children
269 : : */
270 [ + + ]: 409036 : for (n = 0; n < node->num_ptrs; n++) {
271 [ + - ]: 284150 : if (node->ptrs[n].ptr != NULL)
272 : 284150 : acl_count_trie_types(counts, node->ptrs[n].ptr,
273 : : no_match, 0);
274 : : }
275 : : }
276 : :
277 : : static void
278 : 142571 : acl_add_ptrs(struct rte_acl_node *node, uint64_t *node_array, uint64_t no_match,
279 : : int resolved)
280 : : {
281 : : uint32_t x;
282 : : int32_t m;
283 : : uint64_t *node_a, index, dfa[RTE_ACL_DFA_SIZE];
284 : :
285 : 142571 : acl_node_fill_dfa(node, dfa, no_match, resolved);
286 : :
287 : : /*
288 : : * Rather than going from 0 to 256, the range count and
289 : : * the layout are from 80-ff then 0-7f due to signed compare
290 : : * for SSE (cmpgt).
291 : : */
292 [ + + ]: 142571 : if (node->node_type == RTE_ACL_NODE_QRANGE) {
293 : :
294 : : m = 0;
295 : : node_a = node_array;
296 : 128040 : index = dfa[QRANGE_MIN];
297 : 128040 : *node_a++ = index;
298 : :
299 [ + + ]: 16389120 : for (x = QRANGE_MIN + 1; x < UINT8_MAX + 1; x++) {
300 [ + + ]: 16261080 : if (dfa[x] != index) {
301 : : index = dfa[x];
302 : 141190 : *node_a++ = index;
303 : 141190 : node->transitions[m++] = (uint8_t)(x - 1);
304 : : }
305 : : }
306 : :
307 [ + + ]: 16517160 : for (x = 0; x < INT8_MAX + 1; x++) {
308 [ + + ]: 16389120 : if (dfa[x] != index) {
309 : : index = dfa[x];
310 : 253012 : *node_a++ = index;
311 : 253012 : node->transitions[m++] = (uint8_t)(x - 1);
312 : : }
313 : : }
314 : :
315 : : /* fill unused locations with max value - nothing is greater */
316 [ + + ]: 245998 : for (; m < RTE_ACL_QUAD_SIZE; m++)
317 : 117958 : node->transitions[m] = INT8_MAX;
318 : :
319 [ - + ]: 128040 : RTE_ACL_VERIFY(m <= RTE_ACL_QUAD_SIZE);
320 : :
321 [ + - + - ]: 14531 : } else if (node->node_type == RTE_ACL_NODE_DFA && resolved) {
322 : 14531 : acl_dfa_fill_gr64(node, dfa, node_array);
323 : : }
324 : 142571 : }
325 : :
326 : : /*
327 : : * Routine that allocates space for this node and recursively calls
328 : : * to allocate space for each child. Once all the children are allocated,
329 : : * then resolve all transitions for this node.
330 : : */
331 : : static void
332 : 284207 : acl_gen_node(struct rte_acl_node *node, uint64_t *node_array,
333 : : uint64_t no_match, struct rte_acl_indices *index, int num_categories)
334 : : {
335 : : uint32_t n, sz, *qtrp;
336 : : uint64_t *array_ptr;
337 : : struct rte_acl_match_results *match;
338 : :
339 [ + + ]: 284207 : if (node->node_index != RTE_ACL_NODE_UNDEFINED)
340 : : return;
341 : :
342 : : array_ptr = NULL;
343 : :
344 [ + + + + : 242659 : switch (node->node_type) {
- - ]
345 : 14531 : case RTE_ACL_NODE_DFA:
346 : 14531 : array_ptr = &node_array[index->dfa_index];
347 : 14531 : node->node_index = acl_dfa_gen_idx(node, index->dfa_index);
348 : 14531 : sz = node->fanout * RTE_ACL_DFA_GR64_SIZE;
349 : 14531 : index->dfa_index += sz;
350 [ + + ]: 1828867 : for (n = 0; n < sz; n++)
351 : 1814336 : array_ptr[n] = no_match;
352 : : break;
353 : 46335 : case RTE_ACL_NODE_SINGLE:
354 : 46335 : node->node_index = RTE_ACL_QUAD_SINGLE | index->single_index |
355 : : node->node_type;
356 : 46335 : array_ptr = &node_array[index->single_index];
357 : 46335 : index->single_index += 1;
358 : 46335 : array_ptr[0] = no_match;
359 : 46335 : break;
360 : 64020 : case RTE_ACL_NODE_QRANGE:
361 : 64020 : array_ptr = &node_array[index->quad_index];
362 : 64020 : acl_add_ptrs(node, array_ptr, no_match, 0);
363 : : qtrp = (uint32_t *)node->transitions;
364 : 64020 : node->node_index = qtrp[0];
365 : 64020 : node->node_index <<= sizeof(index->quad_index) * CHAR_BIT;
366 : 64020 : node->node_index |= index->quad_index | node->node_type;
367 : 64020 : index->quad_index += node->fanout;
368 : 64020 : break;
369 : 117773 : case RTE_ACL_NODE_MATCH:
370 : 117773 : match = ((struct rte_acl_match_results *)
371 : 117773 : (node_array + index->match_start));
372 [ + + ]: 2002141 : for (n = 0; n != RTE_DIM(match->results); n++)
373 [ - + ]: 1884368 : RTE_ACL_VERIFY(match->results[0] == 0);
374 : 117773 : memcpy(match + index->match_index, node->mrt,
375 : : sizeof(*node->mrt));
376 : 117773 : node->node_index = index->match_index | node->node_type;
377 : 117773 : index->match_index += 1;
378 : 117773 : break;
379 : : case RTE_ACL_NODE_UNDEFINED:
380 : 0 : RTE_ACL_VERIFY(node->node_type !=
381 : : (uint32_t)RTE_ACL_NODE_UNDEFINED);
382 : : break;
383 : : }
384 : :
385 : : /* recursively allocate space for all children */
386 [ + + ]: 526809 : for (n = 0; n < node->num_ptrs; n++) {
387 [ + - ]: 284150 : if (node->ptrs[n].ptr != NULL)
388 : 284150 : acl_gen_node(node->ptrs[n].ptr,
389 : : node_array,
390 : : no_match,
391 : : index,
392 : : num_categories);
393 : : }
394 : :
395 : : /* All children are resolved, resolve this node's pointers */
396 [ + + + - : 242659 : switch (node->node_type) {
+ ]
397 : 14531 : case RTE_ACL_NODE_DFA:
398 : 14531 : acl_add_ptrs(node, array_ptr, no_match, 1);
399 : 14531 : break;
400 : : case RTE_ACL_NODE_SINGLE:
401 [ + + ]: 92670 : for (n = 0; n < node->num_ptrs; n++) {
402 [ + - ]: 46335 : if (node->ptrs[n].ptr != NULL)
403 : 46335 : array_ptr[0] = node->ptrs[n].ptr->node_index;
404 : : }
405 : : break;
406 : 64020 : case RTE_ACL_NODE_QRANGE:
407 : 64020 : acl_add_ptrs(node, array_ptr, no_match, 1);
408 : 64020 : break;
409 : : case RTE_ACL_NODE_MATCH:
410 : : break;
411 : : case RTE_ACL_NODE_UNDEFINED:
412 : 0 : RTE_ACL_VERIFY(node->node_type !=
413 : : (uint32_t)RTE_ACL_NODE_UNDEFINED);
414 : : break;
415 : : }
416 : : }
417 : :
418 : : static void
419 : 42 : acl_calc_counts_indices(struct acl_node_counters *counts,
420 : : struct rte_acl_indices *indices,
421 : : struct rte_acl_bld_trie *node_bld_trie, uint32_t num_tries,
422 : : uint64_t no_match)
423 : : {
424 : : uint32_t n;
425 : :
426 : : memset(indices, 0, sizeof(*indices));
427 : : memset(counts, 0, sizeof(*counts));
428 : :
429 : : /* Get stats on nodes */
430 [ + + ]: 99 : for (n = 0; n < num_tries; n++) {
431 : 57 : acl_count_trie_types(counts, node_bld_trie[n].trie,
432 : : no_match, 1);
433 : : }
434 : :
435 : 42 : indices->dfa_index = RTE_ACL_DFA_SIZE + 1;
436 : 42 : indices->quad_index = indices->dfa_index +
437 : 42 : counts->dfa_gr64 * RTE_ACL_DFA_GR64_SIZE;
438 : 42 : indices->single_index = indices->quad_index + counts->quad_vectors;
439 : 42 : indices->match_start = indices->single_index + counts->single + 1;
440 : 42 : indices->match_start = RTE_ALIGN(indices->match_start,
441 : : (XMM_SIZE / sizeof(uint64_t)));
442 : 42 : indices->match_index = 1;
443 : 42 : }
444 : :
445 : : /*
446 : : * Generate the runtime structure using build structure
447 : : */
448 : : int
449 : 42 : rte_acl_gen(struct rte_acl_ctx *ctx, struct rte_acl_trie *trie,
450 : : struct rte_acl_bld_trie *node_bld_trie, uint32_t num_tries,
451 : : uint32_t num_categories, uint32_t data_index_sz, size_t max_size)
452 : : {
453 : : void *mem;
454 : : size_t total_size;
455 : : uint64_t *node_array, no_match;
456 : : uint32_t n, match_index;
457 : : struct rte_acl_match_results *match;
458 : : struct acl_node_counters counts;
459 : : struct rte_acl_indices indices;
460 : :
461 : : no_match = RTE_ACL_NODE_MATCH;
462 : :
463 : : /* Fill counts and indices arrays from the nodes. */
464 : 42 : acl_calc_counts_indices(&counts, &indices,
465 : : node_bld_trie, num_tries, no_match);
466 : :
467 : : /* Allocate runtime memory (align to cache boundary) */
468 : 42 : total_size = RTE_ALIGN(data_index_sz, RTE_CACHE_LINE_SIZE) +
469 : 42 : indices.match_start * sizeof(uint64_t) +
470 : 42 : (counts.match + 1) * sizeof(struct rte_acl_match_results) +
471 : : XMM_SIZE;
472 : :
473 [ - + ]: 42 : if (total_size > max_size) {
474 : 0 : ACL_LOG(DEBUG,
475 : : "Gen phase for ACL ctx \"%s\" exceeds max_size limit, "
476 : : "bytes required: %zu, allowed: %zu",
477 : : ctx->name, total_size, max_size);
478 : 0 : return -ERANGE;
479 : : }
480 : :
481 : 42 : mem = rte_zmalloc_socket(ctx->name, total_size, RTE_CACHE_LINE_SIZE,
482 : : ctx->socket_id);
483 [ - + ]: 42 : if (mem == NULL) {
484 : 0 : ACL_LOG(ERR,
485 : : "allocation of %zu bytes on socket %d for %s failed",
486 : : total_size, ctx->socket_id, ctx->name);
487 : 0 : return -ENOMEM;
488 : : }
489 : :
490 : : /* Fill the runtime structure */
491 : 42 : match_index = indices.match_start;
492 : 42 : node_array = (uint64_t *)((uintptr_t)mem +
493 : : RTE_ALIGN(data_index_sz, RTE_CACHE_LINE_SIZE));
494 : :
495 : : /*
496 : : * Setup the NOMATCH node (a SINGLE at the
497 : : * highest index, that points to itself)
498 : : */
499 : :
500 : 42 : node_array[RTE_ACL_DFA_SIZE] = RTE_ACL_IDLE_NODE;
501 : :
502 [ + + ]: 10794 : for (n = 0; n < RTE_ACL_DFA_SIZE; n++)
503 : 10752 : node_array[n] = no_match;
504 : :
505 : : /* NOMATCH result at index 0 */
506 : 42 : match = ((struct rte_acl_match_results *)(node_array + match_index));
507 : : memset(match, 0, sizeof(*match));
508 : :
509 [ + + ]: 99 : for (n = 0; n < num_tries; n++) {
510 : :
511 : 57 : acl_gen_node(node_bld_trie[n].trie, node_array, no_match,
512 : : &indices, num_categories);
513 : :
514 [ - + ]: 57 : if (node_bld_trie[n].trie->node_index == no_match)
515 : 0 : trie[n].root_index = 0;
516 : : else
517 : 57 : trie[n].root_index = node_bld_trie[n].trie->node_index;
518 : : }
519 : :
520 : 42 : ctx->mem = mem;
521 : 42 : ctx->mem_sz = total_size;
522 : 42 : ctx->data_indexes = mem;
523 : 42 : ctx->num_tries = num_tries;
524 : 42 : ctx->num_categories = num_categories;
525 : 42 : ctx->match_index = match_index;
526 : 42 : ctx->no_match = no_match;
527 : 42 : ctx->idle = node_array[RTE_ACL_DFA_SIZE];
528 : 42 : ctx->trans_table = node_array;
529 : 42 : memcpy(ctx->trie, trie, sizeof(ctx->trie));
530 : :
531 : 42 : acl_gen_log_stats(ctx, &counts, &indices, max_size);
532 : 42 : return 0;
533 : : }
|