New upstream version 18.02
[deb_dpdk.git] / lib / librte_acl / acl_run_scalar.c
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 }