199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 599a2dd95SBruce Richardson #include <rte_acl.h> 699a2dd95SBruce Richardson #include "acl.h" 7*73d85848SStephen Hemminger #include "acl_log.h" 899a2dd95SBruce Richardson 999a2dd95SBruce Richardson #define QRANGE_MIN ((uint8_t)INT8_MIN) 1099a2dd95SBruce Richardson 1199a2dd95SBruce Richardson #define RTE_ACL_VERIFY(exp) do { \ 1299a2dd95SBruce Richardson if (!(exp)) \ 1399a2dd95SBruce Richardson rte_panic("line %d\tassert \"" #exp "\" failed\n", __LINE__); \ 1499a2dd95SBruce Richardson } while (0) 1599a2dd95SBruce Richardson 1699a2dd95SBruce Richardson struct acl_node_counters { 1799a2dd95SBruce Richardson int32_t match; 1899a2dd95SBruce Richardson int32_t match_used; 1999a2dd95SBruce Richardson int32_t single; 2099a2dd95SBruce Richardson int32_t quad; 2199a2dd95SBruce Richardson int32_t quad_vectors; 2299a2dd95SBruce Richardson int32_t dfa; 2399a2dd95SBruce Richardson int32_t dfa_gr64; 2499a2dd95SBruce Richardson }; 2599a2dd95SBruce Richardson 2699a2dd95SBruce Richardson struct rte_acl_indices { 2799a2dd95SBruce Richardson int32_t dfa_index; 2899a2dd95SBruce Richardson int32_t quad_index; 2999a2dd95SBruce Richardson int32_t single_index; 3099a2dd95SBruce Richardson int32_t match_index; 3199a2dd95SBruce Richardson int32_t match_start; 3299a2dd95SBruce Richardson }; 3399a2dd95SBruce Richardson 3499a2dd95SBruce Richardson static void 3599a2dd95SBruce Richardson acl_gen_log_stats(const struct rte_acl_ctx *ctx, 3699a2dd95SBruce Richardson const struct acl_node_counters *counts, 3799a2dd95SBruce Richardson const struct rte_acl_indices *indices, 3899a2dd95SBruce Richardson size_t max_size) 3999a2dd95SBruce Richardson { 4099a2dd95SBruce Richardson RTE_LOG(DEBUG, ACL, "Gen phase for ACL \"%s\":\n" 4199a2dd95SBruce Richardson "runtime memory footprint on socket %d:\n" 4299a2dd95SBruce Richardson "single nodes/bytes used: %d/%zu\n" 4399a2dd95SBruce Richardson "quad nodes/vectors/bytes used: %d/%d/%zu\n" 4499a2dd95SBruce Richardson "DFA nodes/group64/bytes used: %d/%d/%zu\n" 4599a2dd95SBruce Richardson "match nodes/bytes used: %d/%zu\n" 4699a2dd95SBruce Richardson "total: %zu bytes\n" 4799a2dd95SBruce Richardson "max limit: %zu bytes\n", 4899a2dd95SBruce Richardson ctx->name, ctx->socket_id, 4999a2dd95SBruce Richardson counts->single, counts->single * sizeof(uint64_t), 5099a2dd95SBruce Richardson counts->quad, counts->quad_vectors, 5199a2dd95SBruce Richardson (indices->quad_index - indices->dfa_index) * sizeof(uint64_t), 5299a2dd95SBruce Richardson counts->dfa, counts->dfa_gr64, 5399a2dd95SBruce Richardson indices->dfa_index * sizeof(uint64_t), 5499a2dd95SBruce Richardson counts->match, 5599a2dd95SBruce Richardson counts->match * sizeof(struct rte_acl_match_results), 5699a2dd95SBruce Richardson ctx->mem_sz, 5799a2dd95SBruce Richardson max_size); 5899a2dd95SBruce Richardson } 5999a2dd95SBruce Richardson 6099a2dd95SBruce Richardson static uint64_t 6199a2dd95SBruce Richardson acl_dfa_gen_idx(const struct rte_acl_node *node, uint32_t index) 6299a2dd95SBruce Richardson { 6399a2dd95SBruce Richardson uint64_t idx; 6499a2dd95SBruce Richardson uint32_t i; 6599a2dd95SBruce Richardson 6699a2dd95SBruce Richardson idx = 0; 6799a2dd95SBruce Richardson for (i = 0; i != RTE_DIM(node->dfa_gr64); i++) { 6899a2dd95SBruce Richardson RTE_ACL_VERIFY(node->dfa_gr64[i] < RTE_ACL_DFA_GR64_NUM); 6999a2dd95SBruce Richardson RTE_ACL_VERIFY(node->dfa_gr64[i] < node->fanout); 7099a2dd95SBruce Richardson idx |= (i - node->dfa_gr64[i]) << 7199a2dd95SBruce Richardson (6 + RTE_ACL_DFA_GR64_BIT * i); 7299a2dd95SBruce Richardson } 7399a2dd95SBruce Richardson 7499a2dd95SBruce Richardson return idx << (CHAR_BIT * sizeof(index)) | index | node->node_type; 7599a2dd95SBruce Richardson } 7699a2dd95SBruce Richardson 7799a2dd95SBruce Richardson static void 7899a2dd95SBruce Richardson acl_dfa_fill_gr64(const struct rte_acl_node *node, 7999a2dd95SBruce Richardson const uint64_t src[RTE_ACL_DFA_SIZE], uint64_t dst[RTE_ACL_DFA_SIZE]) 8099a2dd95SBruce Richardson { 8199a2dd95SBruce Richardson uint32_t i; 8299a2dd95SBruce Richardson 8399a2dd95SBruce Richardson for (i = 0; i != RTE_DIM(node->dfa_gr64); i++) { 8499a2dd95SBruce Richardson memcpy(dst + node->dfa_gr64[i] * RTE_ACL_DFA_GR64_SIZE, 8599a2dd95SBruce Richardson src + i * RTE_ACL_DFA_GR64_SIZE, 8699a2dd95SBruce Richardson RTE_ACL_DFA_GR64_SIZE * sizeof(dst[0])); 8799a2dd95SBruce Richardson } 8899a2dd95SBruce Richardson } 8999a2dd95SBruce Richardson 9099a2dd95SBruce Richardson static uint32_t 9199a2dd95SBruce Richardson acl_dfa_count_gr64(const uint64_t array_ptr[RTE_ACL_DFA_SIZE], 9299a2dd95SBruce Richardson uint8_t gr64[RTE_ACL_DFA_GR64_NUM]) 9399a2dd95SBruce Richardson { 9499a2dd95SBruce Richardson uint32_t i, j, k; 9599a2dd95SBruce Richardson 9699a2dd95SBruce Richardson k = 0; 9799a2dd95SBruce Richardson for (i = 0; i != RTE_ACL_DFA_GR64_NUM; i++) { 9899a2dd95SBruce Richardson gr64[i] = i; 9999a2dd95SBruce Richardson for (j = 0; j != i; j++) { 10099a2dd95SBruce Richardson if (memcmp(array_ptr + i * RTE_ACL_DFA_GR64_SIZE, 10199a2dd95SBruce Richardson array_ptr + j * RTE_ACL_DFA_GR64_SIZE, 10299a2dd95SBruce Richardson RTE_ACL_DFA_GR64_SIZE * 10399a2dd95SBruce Richardson sizeof(array_ptr[0])) == 0) 10499a2dd95SBruce Richardson break; 10599a2dd95SBruce Richardson } 10699a2dd95SBruce Richardson gr64[i] = (j != i) ? gr64[j] : k++; 10799a2dd95SBruce Richardson } 10899a2dd95SBruce Richardson 10999a2dd95SBruce Richardson return k; 11099a2dd95SBruce Richardson } 11199a2dd95SBruce Richardson 11299a2dd95SBruce Richardson static uint32_t 11399a2dd95SBruce Richardson acl_node_fill_dfa(const struct rte_acl_node *node, 11499a2dd95SBruce Richardson uint64_t dfa[RTE_ACL_DFA_SIZE], uint64_t no_match, int32_t resolved) 11599a2dd95SBruce Richardson { 11699a2dd95SBruce Richardson uint32_t n, x; 11799a2dd95SBruce Richardson uint32_t ranges, last_bit; 11899a2dd95SBruce Richardson struct rte_acl_node *child; 11999a2dd95SBruce Richardson struct rte_acl_bitset *bits; 12099a2dd95SBruce Richardson 12199a2dd95SBruce Richardson ranges = 0; 12299a2dd95SBruce Richardson last_bit = 0; 12399a2dd95SBruce Richardson 12499a2dd95SBruce Richardson for (n = 0; n < RTE_ACL_DFA_SIZE; n++) 12599a2dd95SBruce Richardson dfa[n] = no_match; 12699a2dd95SBruce Richardson 12799a2dd95SBruce Richardson for (x = 0; x < node->num_ptrs; x++) { 12899a2dd95SBruce Richardson 12999a2dd95SBruce Richardson child = node->ptrs[x].ptr; 13099a2dd95SBruce Richardson if (child == NULL) 13199a2dd95SBruce Richardson continue; 13299a2dd95SBruce Richardson 13399a2dd95SBruce Richardson bits = &node->ptrs[x].values; 13499a2dd95SBruce Richardson for (n = 0; n < RTE_ACL_DFA_SIZE; n++) { 13599a2dd95SBruce Richardson 13699a2dd95SBruce Richardson if (bits->bits[n / (sizeof(bits_t) * CHAR_BIT)] & 13799a2dd95SBruce Richardson (1U << (n % (sizeof(bits_t) * CHAR_BIT)))) { 13899a2dd95SBruce Richardson 13999a2dd95SBruce Richardson dfa[n] = resolved ? child->node_index : x; 14099a2dd95SBruce Richardson ranges += (last_bit == 0); 14199a2dd95SBruce Richardson last_bit = 1; 14299a2dd95SBruce Richardson } else { 14399a2dd95SBruce Richardson last_bit = 0; 14499a2dd95SBruce Richardson } 14599a2dd95SBruce Richardson } 14699a2dd95SBruce Richardson } 14799a2dd95SBruce Richardson 14899a2dd95SBruce Richardson return ranges; 14999a2dd95SBruce Richardson } 15099a2dd95SBruce Richardson 15199a2dd95SBruce Richardson /* 152d5d13ef9SThomas Monjalon * Count the number of groups of sequential bits that are either 0 or 1, 153d5d13ef9SThomas Monjalon * as specified by the zero_one parameter. 154d5d13ef9SThomas Monjalon * This is used to calculate the number of ranges in a node 155d5d13ef9SThomas Monjalon * to see if it fits in a quad range node. 15699a2dd95SBruce Richardson */ 15799a2dd95SBruce Richardson static int 15899a2dd95SBruce Richardson acl_count_sequential_groups(struct rte_acl_bitset *bits, int zero_one) 15999a2dd95SBruce Richardson { 16099a2dd95SBruce Richardson int n, ranges, last_bit; 16199a2dd95SBruce Richardson 16299a2dd95SBruce Richardson ranges = 0; 16399a2dd95SBruce Richardson last_bit = zero_one ^ 1; 16499a2dd95SBruce Richardson 16599a2dd95SBruce Richardson for (n = QRANGE_MIN; n < UINT8_MAX + 1; n++) { 16699a2dd95SBruce Richardson if (bits->bits[n / (sizeof(bits_t) * 8)] & 16799a2dd95SBruce Richardson (1U << (n % (sizeof(bits_t) * 8)))) { 16899a2dd95SBruce Richardson if (zero_one == 1 && last_bit != 1) 16999a2dd95SBruce Richardson ranges++; 17099a2dd95SBruce Richardson last_bit = 1; 17199a2dd95SBruce Richardson } else { 17299a2dd95SBruce Richardson if (zero_one == 0 && last_bit != 0) 17399a2dd95SBruce Richardson ranges++; 17499a2dd95SBruce Richardson last_bit = 0; 17599a2dd95SBruce Richardson } 17699a2dd95SBruce Richardson } 17799a2dd95SBruce Richardson for (n = 0; n < QRANGE_MIN; n++) { 17899a2dd95SBruce Richardson if (bits->bits[n / (sizeof(bits_t) * 8)] & 17999a2dd95SBruce Richardson (1U << (n % (sizeof(bits_t) * CHAR_BIT)))) { 18099a2dd95SBruce Richardson if (zero_one == 1 && last_bit != 1) 18199a2dd95SBruce Richardson ranges++; 18299a2dd95SBruce Richardson last_bit = 1; 18399a2dd95SBruce Richardson } else { 18499a2dd95SBruce Richardson if (zero_one == 0 && last_bit != 0) 18599a2dd95SBruce Richardson ranges++; 18699a2dd95SBruce Richardson last_bit = 0; 18799a2dd95SBruce Richardson } 18899a2dd95SBruce Richardson } 18999a2dd95SBruce Richardson 19099a2dd95SBruce Richardson return ranges; 19199a2dd95SBruce Richardson } 19299a2dd95SBruce Richardson 19399a2dd95SBruce Richardson /* 19499a2dd95SBruce Richardson * Count number of ranges spanned by the node's pointers 19599a2dd95SBruce Richardson */ 19699a2dd95SBruce Richardson static int 19799a2dd95SBruce Richardson acl_count_fanout(struct rte_acl_node *node) 19899a2dd95SBruce Richardson { 19999a2dd95SBruce Richardson uint32_t n; 20099a2dd95SBruce Richardson int ranges; 20199a2dd95SBruce Richardson 20299a2dd95SBruce Richardson if (node->fanout != 0) 20399a2dd95SBruce Richardson return node->fanout; 20499a2dd95SBruce Richardson 20599a2dd95SBruce Richardson ranges = acl_count_sequential_groups(&node->values, 0); 20699a2dd95SBruce Richardson 20799a2dd95SBruce Richardson for (n = 0; n < node->num_ptrs; n++) { 20899a2dd95SBruce Richardson if (node->ptrs[n].ptr != NULL) 20999a2dd95SBruce Richardson ranges += acl_count_sequential_groups( 21099a2dd95SBruce Richardson &node->ptrs[n].values, 1); 21199a2dd95SBruce Richardson } 21299a2dd95SBruce Richardson 21399a2dd95SBruce Richardson node->fanout = ranges; 21499a2dd95SBruce Richardson return node->fanout; 21599a2dd95SBruce Richardson } 21699a2dd95SBruce Richardson 21799a2dd95SBruce Richardson /* 21899a2dd95SBruce Richardson * Determine the type of nodes and count each type 21999a2dd95SBruce Richardson */ 22099a2dd95SBruce Richardson static void 22199a2dd95SBruce Richardson acl_count_trie_types(struct acl_node_counters *counts, 22299a2dd95SBruce Richardson struct rte_acl_node *node, uint64_t no_match, int force_dfa) 22399a2dd95SBruce Richardson { 22499a2dd95SBruce Richardson uint32_t n; 22599a2dd95SBruce Richardson int num_ptrs; 22699a2dd95SBruce Richardson uint64_t dfa[RTE_ACL_DFA_SIZE]; 22799a2dd95SBruce Richardson 22899a2dd95SBruce Richardson /* skip if this node has been counted */ 22999a2dd95SBruce Richardson if (node->node_type != (uint32_t)RTE_ACL_NODE_UNDEFINED) 23099a2dd95SBruce Richardson return; 23199a2dd95SBruce Richardson 23299a2dd95SBruce Richardson if (node->match_flag != 0 || node->num_ptrs == 0) { 23399a2dd95SBruce Richardson counts->match++; 23499a2dd95SBruce Richardson node->node_type = RTE_ACL_NODE_MATCH; 23599a2dd95SBruce Richardson return; 23699a2dd95SBruce Richardson } 23799a2dd95SBruce Richardson 23899a2dd95SBruce Richardson num_ptrs = acl_count_fanout(node); 23999a2dd95SBruce Richardson 24099a2dd95SBruce Richardson /* Force type to dfa */ 24199a2dd95SBruce Richardson if (force_dfa) 24299a2dd95SBruce Richardson num_ptrs = RTE_ACL_DFA_SIZE; 24399a2dd95SBruce Richardson 24499a2dd95SBruce Richardson /* determine node type based on number of ranges */ 24599a2dd95SBruce Richardson if (num_ptrs == 1) { 24699a2dd95SBruce Richardson counts->single++; 24799a2dd95SBruce Richardson node->node_type = RTE_ACL_NODE_SINGLE; 24899a2dd95SBruce Richardson } else if (num_ptrs <= RTE_ACL_QUAD_MAX) { 24999a2dd95SBruce Richardson counts->quad++; 25099a2dd95SBruce Richardson counts->quad_vectors += node->fanout; 25199a2dd95SBruce Richardson node->node_type = RTE_ACL_NODE_QRANGE; 25299a2dd95SBruce Richardson } else { 25399a2dd95SBruce Richardson counts->dfa++; 25499a2dd95SBruce Richardson node->node_type = RTE_ACL_NODE_DFA; 25599a2dd95SBruce Richardson if (force_dfa != 0) { 25699a2dd95SBruce Richardson /* always expand to a max number of nodes. */ 25799a2dd95SBruce Richardson for (n = 0; n != RTE_DIM(node->dfa_gr64); n++) 25899a2dd95SBruce Richardson node->dfa_gr64[n] = n; 25999a2dd95SBruce Richardson node->fanout = n; 26099a2dd95SBruce Richardson } else { 26199a2dd95SBruce Richardson acl_node_fill_dfa(node, dfa, no_match, 0); 26299a2dd95SBruce Richardson node->fanout = acl_dfa_count_gr64(dfa, node->dfa_gr64); 26399a2dd95SBruce Richardson } 26499a2dd95SBruce Richardson counts->dfa_gr64 += node->fanout; 26599a2dd95SBruce Richardson } 26699a2dd95SBruce Richardson 26799a2dd95SBruce Richardson /* 26899a2dd95SBruce Richardson * recursively count the types of all children 26999a2dd95SBruce Richardson */ 27099a2dd95SBruce Richardson for (n = 0; n < node->num_ptrs; n++) { 27199a2dd95SBruce Richardson if (node->ptrs[n].ptr != NULL) 27299a2dd95SBruce Richardson acl_count_trie_types(counts, node->ptrs[n].ptr, 27399a2dd95SBruce Richardson no_match, 0); 27499a2dd95SBruce Richardson } 27599a2dd95SBruce Richardson } 27699a2dd95SBruce Richardson 27799a2dd95SBruce Richardson static void 27899a2dd95SBruce Richardson acl_add_ptrs(struct rte_acl_node *node, uint64_t *node_array, uint64_t no_match, 27999a2dd95SBruce Richardson int resolved) 28099a2dd95SBruce Richardson { 28199a2dd95SBruce Richardson uint32_t x; 28299a2dd95SBruce Richardson int32_t m; 28399a2dd95SBruce Richardson uint64_t *node_a, index, dfa[RTE_ACL_DFA_SIZE]; 28499a2dd95SBruce Richardson 28599a2dd95SBruce Richardson acl_node_fill_dfa(node, dfa, no_match, resolved); 28699a2dd95SBruce Richardson 28799a2dd95SBruce Richardson /* 28899a2dd95SBruce Richardson * Rather than going from 0 to 256, the range count and 28999a2dd95SBruce Richardson * the layout are from 80-ff then 0-7f due to signed compare 29099a2dd95SBruce Richardson * for SSE (cmpgt). 29199a2dd95SBruce Richardson */ 29299a2dd95SBruce Richardson if (node->node_type == RTE_ACL_NODE_QRANGE) { 29399a2dd95SBruce Richardson 29499a2dd95SBruce Richardson m = 0; 29599a2dd95SBruce Richardson node_a = node_array; 29699a2dd95SBruce Richardson index = dfa[QRANGE_MIN]; 29799a2dd95SBruce Richardson *node_a++ = index; 29899a2dd95SBruce Richardson 29999a2dd95SBruce Richardson for (x = QRANGE_MIN + 1; x < UINT8_MAX + 1; x++) { 30099a2dd95SBruce Richardson if (dfa[x] != index) { 30199a2dd95SBruce Richardson index = dfa[x]; 30299a2dd95SBruce Richardson *node_a++ = index; 30399a2dd95SBruce Richardson node->transitions[m++] = (uint8_t)(x - 1); 30499a2dd95SBruce Richardson } 30599a2dd95SBruce Richardson } 30699a2dd95SBruce Richardson 30799a2dd95SBruce Richardson for (x = 0; x < INT8_MAX + 1; x++) { 30899a2dd95SBruce Richardson if (dfa[x] != index) { 30999a2dd95SBruce Richardson index = dfa[x]; 31099a2dd95SBruce Richardson *node_a++ = index; 31199a2dd95SBruce Richardson node->transitions[m++] = (uint8_t)(x - 1); 31299a2dd95SBruce Richardson } 31399a2dd95SBruce Richardson } 31499a2dd95SBruce Richardson 31599a2dd95SBruce Richardson /* fill unused locations with max value - nothing is greater */ 31699a2dd95SBruce Richardson for (; m < RTE_ACL_QUAD_SIZE; m++) 31799a2dd95SBruce Richardson node->transitions[m] = INT8_MAX; 31899a2dd95SBruce Richardson 31999a2dd95SBruce Richardson RTE_ACL_VERIFY(m <= RTE_ACL_QUAD_SIZE); 32099a2dd95SBruce Richardson 32199a2dd95SBruce Richardson } else if (node->node_type == RTE_ACL_NODE_DFA && resolved) { 32299a2dd95SBruce Richardson acl_dfa_fill_gr64(node, dfa, node_array); 32399a2dd95SBruce Richardson } 32499a2dd95SBruce Richardson } 32599a2dd95SBruce Richardson 32699a2dd95SBruce Richardson /* 32799a2dd95SBruce Richardson * Routine that allocates space for this node and recursively calls 32899a2dd95SBruce Richardson * to allocate space for each child. Once all the children are allocated, 32999a2dd95SBruce Richardson * then resolve all transitions for this node. 33099a2dd95SBruce Richardson */ 33199a2dd95SBruce Richardson static void 33299a2dd95SBruce Richardson acl_gen_node(struct rte_acl_node *node, uint64_t *node_array, 33399a2dd95SBruce Richardson uint64_t no_match, struct rte_acl_indices *index, int num_categories) 33499a2dd95SBruce Richardson { 33599a2dd95SBruce Richardson uint32_t n, sz, *qtrp; 33699a2dd95SBruce Richardson uint64_t *array_ptr; 33799a2dd95SBruce Richardson struct rte_acl_match_results *match; 33899a2dd95SBruce Richardson 33999a2dd95SBruce Richardson if (node->node_index != RTE_ACL_NODE_UNDEFINED) 34099a2dd95SBruce Richardson return; 34199a2dd95SBruce Richardson 34299a2dd95SBruce Richardson array_ptr = NULL; 34399a2dd95SBruce Richardson 34499a2dd95SBruce Richardson switch (node->node_type) { 34599a2dd95SBruce Richardson case RTE_ACL_NODE_DFA: 34699a2dd95SBruce Richardson array_ptr = &node_array[index->dfa_index]; 34799a2dd95SBruce Richardson node->node_index = acl_dfa_gen_idx(node, index->dfa_index); 34899a2dd95SBruce Richardson sz = node->fanout * RTE_ACL_DFA_GR64_SIZE; 34999a2dd95SBruce Richardson index->dfa_index += sz; 35099a2dd95SBruce Richardson for (n = 0; n < sz; n++) 35199a2dd95SBruce Richardson array_ptr[n] = no_match; 35299a2dd95SBruce Richardson break; 35399a2dd95SBruce Richardson case RTE_ACL_NODE_SINGLE: 35499a2dd95SBruce Richardson node->node_index = RTE_ACL_QUAD_SINGLE | index->single_index | 35599a2dd95SBruce Richardson node->node_type; 35699a2dd95SBruce Richardson array_ptr = &node_array[index->single_index]; 35799a2dd95SBruce Richardson index->single_index += 1; 35899a2dd95SBruce Richardson array_ptr[0] = no_match; 35999a2dd95SBruce Richardson break; 36099a2dd95SBruce Richardson case RTE_ACL_NODE_QRANGE: 36199a2dd95SBruce Richardson array_ptr = &node_array[index->quad_index]; 36299a2dd95SBruce Richardson acl_add_ptrs(node, array_ptr, no_match, 0); 36399a2dd95SBruce Richardson qtrp = (uint32_t *)node->transitions; 36499a2dd95SBruce Richardson node->node_index = qtrp[0]; 36599a2dd95SBruce Richardson node->node_index <<= sizeof(index->quad_index) * CHAR_BIT; 36699a2dd95SBruce Richardson node->node_index |= index->quad_index | node->node_type; 36799a2dd95SBruce Richardson index->quad_index += node->fanout; 36899a2dd95SBruce Richardson break; 36999a2dd95SBruce Richardson case RTE_ACL_NODE_MATCH: 37099a2dd95SBruce Richardson match = ((struct rte_acl_match_results *) 37199a2dd95SBruce Richardson (node_array + index->match_start)); 37299a2dd95SBruce Richardson for (n = 0; n != RTE_DIM(match->results); n++) 37399a2dd95SBruce Richardson RTE_ACL_VERIFY(match->results[0] == 0); 37499a2dd95SBruce Richardson memcpy(match + index->match_index, node->mrt, 37599a2dd95SBruce Richardson sizeof(*node->mrt)); 37699a2dd95SBruce Richardson node->node_index = index->match_index | node->node_type; 37799a2dd95SBruce Richardson index->match_index += 1; 37899a2dd95SBruce Richardson break; 37999a2dd95SBruce Richardson case RTE_ACL_NODE_UNDEFINED: 38099a2dd95SBruce Richardson RTE_ACL_VERIFY(node->node_type != 38199a2dd95SBruce Richardson (uint32_t)RTE_ACL_NODE_UNDEFINED); 38299a2dd95SBruce Richardson break; 38399a2dd95SBruce Richardson } 38499a2dd95SBruce Richardson 38599a2dd95SBruce Richardson /* recursively allocate space for all children */ 38699a2dd95SBruce Richardson for (n = 0; n < node->num_ptrs; n++) { 38799a2dd95SBruce Richardson if (node->ptrs[n].ptr != NULL) 38899a2dd95SBruce Richardson acl_gen_node(node->ptrs[n].ptr, 38999a2dd95SBruce Richardson node_array, 39099a2dd95SBruce Richardson no_match, 39199a2dd95SBruce Richardson index, 39299a2dd95SBruce Richardson num_categories); 39399a2dd95SBruce Richardson } 39499a2dd95SBruce Richardson 39599a2dd95SBruce Richardson /* All children are resolved, resolve this node's pointers */ 39699a2dd95SBruce Richardson switch (node->node_type) { 39799a2dd95SBruce Richardson case RTE_ACL_NODE_DFA: 39899a2dd95SBruce Richardson acl_add_ptrs(node, array_ptr, no_match, 1); 39999a2dd95SBruce Richardson break; 40099a2dd95SBruce Richardson case RTE_ACL_NODE_SINGLE: 40199a2dd95SBruce Richardson for (n = 0; n < node->num_ptrs; n++) { 40299a2dd95SBruce Richardson if (node->ptrs[n].ptr != NULL) 40399a2dd95SBruce Richardson array_ptr[0] = node->ptrs[n].ptr->node_index; 40499a2dd95SBruce Richardson } 40599a2dd95SBruce Richardson break; 40699a2dd95SBruce Richardson case RTE_ACL_NODE_QRANGE: 40799a2dd95SBruce Richardson acl_add_ptrs(node, array_ptr, no_match, 1); 40899a2dd95SBruce Richardson break; 40999a2dd95SBruce Richardson case RTE_ACL_NODE_MATCH: 41099a2dd95SBruce Richardson break; 41199a2dd95SBruce Richardson case RTE_ACL_NODE_UNDEFINED: 41299a2dd95SBruce Richardson RTE_ACL_VERIFY(node->node_type != 41399a2dd95SBruce Richardson (uint32_t)RTE_ACL_NODE_UNDEFINED); 41499a2dd95SBruce Richardson break; 41599a2dd95SBruce Richardson } 41699a2dd95SBruce Richardson } 41799a2dd95SBruce Richardson 41899a2dd95SBruce Richardson static void 41999a2dd95SBruce Richardson acl_calc_counts_indices(struct acl_node_counters *counts, 42099a2dd95SBruce Richardson struct rte_acl_indices *indices, 42199a2dd95SBruce Richardson struct rte_acl_bld_trie *node_bld_trie, uint32_t num_tries, 42299a2dd95SBruce Richardson uint64_t no_match) 42399a2dd95SBruce Richardson { 42499a2dd95SBruce Richardson uint32_t n; 42599a2dd95SBruce Richardson 42699a2dd95SBruce Richardson memset(indices, 0, sizeof(*indices)); 42799a2dd95SBruce Richardson memset(counts, 0, sizeof(*counts)); 42899a2dd95SBruce Richardson 42999a2dd95SBruce Richardson /* Get stats on nodes */ 43099a2dd95SBruce Richardson for (n = 0; n < num_tries; n++) { 43199a2dd95SBruce Richardson acl_count_trie_types(counts, node_bld_trie[n].trie, 43299a2dd95SBruce Richardson no_match, 1); 43399a2dd95SBruce Richardson } 43499a2dd95SBruce Richardson 43599a2dd95SBruce Richardson indices->dfa_index = RTE_ACL_DFA_SIZE + 1; 43699a2dd95SBruce Richardson indices->quad_index = indices->dfa_index + 43799a2dd95SBruce Richardson counts->dfa_gr64 * RTE_ACL_DFA_GR64_SIZE; 43899a2dd95SBruce Richardson indices->single_index = indices->quad_index + counts->quad_vectors; 43999a2dd95SBruce Richardson indices->match_start = indices->single_index + counts->single + 1; 44099a2dd95SBruce Richardson indices->match_start = RTE_ALIGN(indices->match_start, 44199a2dd95SBruce Richardson (XMM_SIZE / sizeof(uint64_t))); 44299a2dd95SBruce Richardson indices->match_index = 1; 44399a2dd95SBruce Richardson } 44499a2dd95SBruce Richardson 44599a2dd95SBruce Richardson /* 44699a2dd95SBruce Richardson * Generate the runtime structure using build structure 44799a2dd95SBruce Richardson */ 44899a2dd95SBruce Richardson int 44999a2dd95SBruce Richardson rte_acl_gen(struct rte_acl_ctx *ctx, struct rte_acl_trie *trie, 45099a2dd95SBruce Richardson struct rte_acl_bld_trie *node_bld_trie, uint32_t num_tries, 45199a2dd95SBruce Richardson uint32_t num_categories, uint32_t data_index_sz, size_t max_size) 45299a2dd95SBruce Richardson { 45399a2dd95SBruce Richardson void *mem; 45499a2dd95SBruce Richardson size_t total_size; 45599a2dd95SBruce Richardson uint64_t *node_array, no_match; 45699a2dd95SBruce Richardson uint32_t n, match_index; 45799a2dd95SBruce Richardson struct rte_acl_match_results *match; 45899a2dd95SBruce Richardson struct acl_node_counters counts; 45999a2dd95SBruce Richardson struct rte_acl_indices indices; 46099a2dd95SBruce Richardson 46199a2dd95SBruce Richardson no_match = RTE_ACL_NODE_MATCH; 46299a2dd95SBruce Richardson 46399a2dd95SBruce Richardson /* Fill counts and indices arrays from the nodes. */ 46499a2dd95SBruce Richardson acl_calc_counts_indices(&counts, &indices, 46599a2dd95SBruce Richardson node_bld_trie, num_tries, no_match); 46699a2dd95SBruce Richardson 46799a2dd95SBruce Richardson /* Allocate runtime memory (align to cache boundary) */ 46899a2dd95SBruce Richardson total_size = RTE_ALIGN(data_index_sz, RTE_CACHE_LINE_SIZE) + 46999a2dd95SBruce Richardson indices.match_start * sizeof(uint64_t) + 47099a2dd95SBruce Richardson (counts.match + 1) * sizeof(struct rte_acl_match_results) + 47199a2dd95SBruce Richardson XMM_SIZE; 47299a2dd95SBruce Richardson 47399a2dd95SBruce Richardson if (total_size > max_size) { 47499a2dd95SBruce Richardson RTE_LOG(DEBUG, ACL, 47599a2dd95SBruce Richardson "Gen phase for ACL ctx \"%s\" exceeds max_size limit, " 47699a2dd95SBruce Richardson "bytes required: %zu, allowed: %zu\n", 47799a2dd95SBruce Richardson ctx->name, total_size, max_size); 47899a2dd95SBruce Richardson return -ERANGE; 47999a2dd95SBruce Richardson } 48099a2dd95SBruce Richardson 48199a2dd95SBruce Richardson mem = rte_zmalloc_socket(ctx->name, total_size, RTE_CACHE_LINE_SIZE, 48299a2dd95SBruce Richardson ctx->socket_id); 48399a2dd95SBruce Richardson if (mem == NULL) { 48499a2dd95SBruce Richardson RTE_LOG(ERR, ACL, 48599a2dd95SBruce Richardson "allocation of %zu bytes on socket %d for %s failed\n", 48699a2dd95SBruce Richardson total_size, ctx->socket_id, ctx->name); 48799a2dd95SBruce Richardson return -ENOMEM; 48899a2dd95SBruce Richardson } 48999a2dd95SBruce Richardson 49099a2dd95SBruce Richardson /* Fill the runtime structure */ 49199a2dd95SBruce Richardson match_index = indices.match_start; 49299a2dd95SBruce Richardson node_array = (uint64_t *)((uintptr_t)mem + 49399a2dd95SBruce Richardson RTE_ALIGN(data_index_sz, RTE_CACHE_LINE_SIZE)); 49499a2dd95SBruce Richardson 49599a2dd95SBruce Richardson /* 49699a2dd95SBruce Richardson * Setup the NOMATCH node (a SINGLE at the 49799a2dd95SBruce Richardson * highest index, that points to itself) 49899a2dd95SBruce Richardson */ 49999a2dd95SBruce Richardson 50099a2dd95SBruce Richardson node_array[RTE_ACL_DFA_SIZE] = RTE_ACL_IDLE_NODE; 50199a2dd95SBruce Richardson 50299a2dd95SBruce Richardson for (n = 0; n < RTE_ACL_DFA_SIZE; n++) 50399a2dd95SBruce Richardson node_array[n] = no_match; 50499a2dd95SBruce Richardson 50599a2dd95SBruce Richardson /* NOMATCH result at index 0 */ 50699a2dd95SBruce Richardson match = ((struct rte_acl_match_results *)(node_array + match_index)); 50799a2dd95SBruce Richardson memset(match, 0, sizeof(*match)); 50899a2dd95SBruce Richardson 50999a2dd95SBruce Richardson for (n = 0; n < num_tries; n++) { 51099a2dd95SBruce Richardson 51199a2dd95SBruce Richardson acl_gen_node(node_bld_trie[n].trie, node_array, no_match, 51299a2dd95SBruce Richardson &indices, num_categories); 51399a2dd95SBruce Richardson 51499a2dd95SBruce Richardson if (node_bld_trie[n].trie->node_index == no_match) 51599a2dd95SBruce Richardson trie[n].root_index = 0; 51699a2dd95SBruce Richardson else 51799a2dd95SBruce Richardson trie[n].root_index = node_bld_trie[n].trie->node_index; 51899a2dd95SBruce Richardson } 51999a2dd95SBruce Richardson 52099a2dd95SBruce Richardson ctx->mem = mem; 52199a2dd95SBruce Richardson ctx->mem_sz = total_size; 52299a2dd95SBruce Richardson ctx->data_indexes = mem; 52399a2dd95SBruce Richardson ctx->num_tries = num_tries; 52499a2dd95SBruce Richardson ctx->num_categories = num_categories; 52599a2dd95SBruce Richardson ctx->match_index = match_index; 52699a2dd95SBruce Richardson ctx->no_match = no_match; 52799a2dd95SBruce Richardson ctx->idle = node_array[RTE_ACL_DFA_SIZE]; 52899a2dd95SBruce Richardson ctx->trans_table = node_array; 52999a2dd95SBruce Richardson memcpy(ctx->trie, trie, sizeof(ctx->trie)); 53099a2dd95SBruce Richardson 53199a2dd95SBruce Richardson acl_gen_log_stats(ctx, &counts, &indices, max_size); 53299a2dd95SBruce Richardson return 0; 53399a2dd95SBruce Richardson } 534