1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include "acl_run.h" 6 7 /* 8 * Resolve priority for multiple results (scalar version). 9 * This consists comparing the priority of the current traversal with the 10 * running set of results for the packet. 11 * For each result, keep a running array of the result (rule number) and 12 * its priority for each category. 13 */ 14 static inline void 15 resolve_priority_scalar(uint64_t transition, int n, 16 const struct rte_acl_ctx *ctx, struct parms *parms, 17 const struct rte_acl_match_results *p, uint32_t categories) 18 { 19 uint32_t i; 20 int32_t *saved_priority; 21 uint32_t *saved_results; 22 const int32_t *priority; 23 const uint32_t *results; 24 25 saved_results = parms[n].cmplt->results; 26 saved_priority = parms[n].cmplt->priority; 27 28 /* results and priorities for completed trie */ 29 results = p[transition].results; 30 priority = p[transition].priority; 31 32 /* if this is not the first completed trie */ 33 if (parms[n].cmplt->count != ctx->num_tries) { 34 for (i = 0; i < categories; i += RTE_ACL_RESULTS_MULTIPLIER) { 35 36 if (saved_priority[i] <= priority[i]) { 37 saved_priority[i] = priority[i]; 38 saved_results[i] = results[i]; 39 } 40 if (saved_priority[i + 1] <= priority[i + 1]) { 41 saved_priority[i + 1] = priority[i + 1]; 42 saved_results[i + 1] = results[i + 1]; 43 } 44 if (saved_priority[i + 2] <= priority[i + 2]) { 45 saved_priority[i + 2] = priority[i + 2]; 46 saved_results[i + 2] = results[i + 2]; 47 } 48 if (saved_priority[i + 3] <= priority[i + 3]) { 49 saved_priority[i + 3] = priority[i + 3]; 50 saved_results[i + 3] = results[i + 3]; 51 } 52 } 53 } else { 54 for (i = 0; i < categories; i += RTE_ACL_RESULTS_MULTIPLIER) { 55 saved_priority[i] = priority[i]; 56 saved_priority[i + 1] = priority[i + 1]; 57 saved_priority[i + 2] = priority[i + 2]; 58 saved_priority[i + 3] = priority[i + 3]; 59 60 saved_results[i] = results[i]; 61 saved_results[i + 1] = results[i + 1]; 62 saved_results[i + 2] = results[i + 2]; 63 saved_results[i + 3] = results[i + 3]; 64 } 65 } 66 } 67 68 static inline uint32_t 69 scan_forward(uint32_t input, uint32_t max) 70 { 71 return (input == 0) ? max : rte_bsf32(input); 72 } 73 74 static inline uint64_t 75 scalar_transition(const uint64_t *trans_table, uint64_t transition, 76 uint8_t input) 77 { 78 uint32_t addr, index, ranges, x, a, b, c; 79 80 /* break transition into component parts */ 81 ranges = transition >> (sizeof(index) * CHAR_BIT); 82 index = transition & ~RTE_ACL_NODE_INDEX; 83 addr = transition ^ index; 84 85 if (index != RTE_ACL_NODE_DFA) { 86 /* calc address for a QRANGE/SINGLE node */ 87 c = (uint32_t)input * SCALAR_QRANGE_MULT; 88 a = ranges | SCALAR_QRANGE_MIN; 89 a -= (c & SCALAR_QRANGE_MASK); 90 b = c & SCALAR_QRANGE_MIN; 91 a &= SCALAR_QRANGE_MIN; 92 a ^= (ranges ^ b) & (a ^ b); 93 x = scan_forward(a, 32) >> 3; 94 } else { 95 /* calc address for a DFA node */ 96 x = ranges >> (input / 97 RTE_ACL_DFA_GR64_SIZE * RTE_ACL_DFA_GR64_BIT); 98 x &= UINT8_MAX; 99 x = input - x; 100 } 101 102 addr += x; 103 104 /* pickup next transition */ 105 transition = *(trans_table + addr); 106 return transition; 107 } 108 109 int 110 rte_acl_classify_scalar(const struct rte_acl_ctx *ctx, const uint8_t **data, 111 uint32_t *results, uint32_t num, uint32_t categories) 112 { 113 int n; 114 uint64_t transition0, transition1; 115 uint32_t input0, input1; 116 struct acl_flow_data flows; 117 uint64_t index_array[MAX_SEARCHES_SCALAR]; 118 struct completion cmplt[MAX_SEARCHES_SCALAR]; 119 struct parms parms[MAX_SEARCHES_SCALAR]; 120 121 acl_set_flow(&flows, cmplt, RTE_DIM(cmplt), data, results, num, 122 categories, ctx->trans_table); 123 124 for (n = 0; n < MAX_SEARCHES_SCALAR; n++) { 125 cmplt[n].count = 0; 126 index_array[n] = acl_start_next_trie(&flows, parms, n, ctx); 127 } 128 129 transition0 = index_array[0]; 130 transition1 = index_array[1]; 131 132 while ((transition0 | transition1) & RTE_ACL_NODE_MATCH) { 133 transition0 = acl_match_check(transition0, 134 0, ctx, parms, &flows, resolve_priority_scalar); 135 transition1 = acl_match_check(transition1, 136 1, ctx, parms, &flows, resolve_priority_scalar); 137 } 138 139 while (flows.started > 0) { 140 141 input0 = GET_NEXT_4BYTES(parms, 0); 142 input1 = GET_NEXT_4BYTES(parms, 1); 143 144 for (n = 0; n < 4; n++) { 145 146 transition0 = scalar_transition(flows.trans, 147 transition0, (uint8_t)input0); 148 input0 >>= CHAR_BIT; 149 150 transition1 = scalar_transition(flows.trans, 151 transition1, (uint8_t)input1); 152 input1 >>= CHAR_BIT; 153 } 154 155 while ((transition0 | transition1) & RTE_ACL_NODE_MATCH) { 156 transition0 = acl_match_check(transition0, 157 0, ctx, parms, &flows, resolve_priority_scalar); 158 transition1 = acl_match_check(transition1, 159 1, ctx, parms, &flows, resolve_priority_scalar); 160 } 161 } 162 return 0; 163 } 164