]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2010-2014 Intel Corporation | |
7c673cae FG |
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 | } |