xref: /dpdk/lib/acl/acl_run_scalar.c (revision 99a2dd955fba6e4cc23b77d590a033650ced9c45)
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