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