blob: 4b2770bb75639fd8c2e7cb009d60b7df3b9af303 [file] [log] [blame]
Florin Coras1c710452017-10-17 00:03:13 -07001/*
Florin Coras288eaab2019-02-03 15:26:14 -08002 * Copyright (c) 2017-2019 Cisco and/or its affiliates.
Florin Coras1c710452017-10-17 00:03:13 -07003 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14*/
15
16#include <vppinfra/error.h>
17
18u8 RT (rule_is_exact_match) (RTT (mma_rule) * key, RTT (mma_rule) * r)
19{
20 int i;
21
22 for (i = 0; i < ARRAY_LEN (key->match.as_u64); i++)
23 {
24 if (key->match.as_u64[i] != r->match.as_u64[i])
25 return 0;
26 }
27 for (i = 0; i < ARRAY_LEN (key->mask.as_u64); i++)
28 {
29 if (key->mask.as_u64[i] != r->mask.as_u64[i])
30 return 0;
31 }
32 return 1;
33}
34
35u8
36RT (rule_is_match_for_key) (RTT (mma_mask_or_match) * key, RTT (mma_rule) * r)
37{
38 RTT (mma_mask_or_match) _tmp_key, *tkp = &_tmp_key;
39 int i;
40
41 *tkp = *key;
42 for (i = 0; i < ARRAY_LEN (tkp->as_u64); i++)
43 tkp->as_u64[i] &= r->mask.as_u64[i];
44 for (i = 0; i < ARRAY_LEN (tkp->as_u64); i++)
45 {
46 if (tkp->as_u64[i] != r->match.as_u64[i])
47 return 0;
48 }
49 return 1;
50}
51
52RTT (mma_rule) * RT (mma_rules_table_rule_alloc) (RTT (mma_rules_table) * srt)
53{
54 RTT (mma_rule) * rule;
55 pool_get (srt->rules, rule);
Dave Barachb7b92992018-10-17 10:38:51 -040056 clib_memset (rule, 0, sizeof (*rule));
Florin Coras1c710452017-10-17 00:03:13 -070057 return rule;
58}
59
60RTT (mma_rule) *
61RT (mma_rule_free) (RTT (mma_rules_table) * srt, RTT (mma_rule) * rule)
62{
Dave Barachb7b92992018-10-17 10:38:51 -040063 clib_memset (rule, 0xfa, sizeof (*rule));
BenoƮt Ganne94d2da02019-10-16 15:11:22 +020064 pool_put (srt->rules, rule);
Florin Coras1c710452017-10-17 00:03:13 -070065 return rule;
66}
67
Nathan Skrzypczakb3ea73e2021-08-05 10:22:52 +020068void RT (mma_rules_table_free) (RTT (mma_rules_table) * srt)
69{
70 pool_free (srt->rules);
71}
72
Florin Coras1c710452017-10-17 00:03:13 -070073RTT (mma_rule) *
74RT (mma_rules_table_get_rule) (RTT (mma_rules_table) * srt, u32 srt_index)
75{
76 if (!pool_is_free_index (srt->rules, srt_index))
77 return (srt->rules + srt_index);
78 return 0;
79}
80
81u32
82RT (mma_rules_table_rule_index) (RTT (mma_rules_table) * srt,
83 RTT (mma_rule) * sr)
84{
85 ASSERT (sr);
86 return (sr - srt->rules);
87}
88
89/**
90 * Lookup key in table
91 *
92 * This should be optimized .. eventually
93 */
94u32
95RT (mma_rules_table_lookup) (RTT (mma_rules_table) * srt,
96 RTT (mma_mask_or_match) * key, u32 rule_index)
97{
98 RTT (mma_rule) * rp;
99 u32 rv;
100 int i;
101
Florin Corasc97a7392017-11-05 23:07:07 -0800102 ASSERT (rule_index != MMA_TABLE_INVALID_INDEX);
Florin Coras1c710452017-10-17 00:03:13 -0700103 rp = RT (mma_rules_table_get_rule) (srt, rule_index);
104 ASSERT (rp);
105
106 if (!RT (rule_is_match_for_key) (key, rp))
Florin Corasc97a7392017-11-05 23:07:07 -0800107 return MMA_TABLE_INVALID_INDEX;
Florin Coras1c710452017-10-17 00:03:13 -0700108 for (i = 0; i < vec_len (rp->next_indices); i++)
109 {
110 rv = RT (mma_rules_table_lookup) (srt, key, rp->next_indices[i]);
Florin Corasc97a7392017-11-05 23:07:07 -0800111 if (rv != MMA_TABLE_INVALID_INDEX)
Florin Coras1c710452017-10-17 00:03:13 -0700112 return (rv);
113 }
114 return (rp->action_index);
115}
116
117u32
118RT (mma_rules_table_lookup_rule) (RTT (mma_rules_table) * srt,
119 RTT (mma_mask_or_match) * key,
120 u32 rule_index)
121{
122 RTT (mma_rule) * rp;
123 u32 rv;
124 int i;
125
Florin Corasc97a7392017-11-05 23:07:07 -0800126 ASSERT (rule_index != MMA_TABLE_INVALID_INDEX);
Florin Coras1c710452017-10-17 00:03:13 -0700127 rp = RT (mma_rules_table_get_rule) (srt, rule_index);
128 ASSERT (rp);
129
130 if (!RT (rule_is_match_for_key) (key, rp))
Florin Corasc97a7392017-11-05 23:07:07 -0800131 return MMA_TABLE_INVALID_INDEX;
Florin Coras1c710452017-10-17 00:03:13 -0700132 for (i = 0; i < vec_len (rp->next_indices); i++)
133 {
134 rv = RT (mma_rules_table_lookup_rule) (srt, key, rp->next_indices[i]);
Florin Corasc97a7392017-11-05 23:07:07 -0800135 if (rv != MMA_TABLE_INVALID_INDEX)
Florin Coras1c710452017-10-17 00:03:13 -0700136 return (rv);
137 }
138 return rule_index;
139}
140
141static
142RTT (mma_rules_table) *
143RTT (sort_srt);
144
145 int RT (mma_sort_indices) (void *e1, void *e2)
146{
147 u32 *ri1 = e1, *ri2 = e2;
148 RTT (mma_rule) * rule1, *rule2;
149 rule1 = RT (mma_rules_table_get_rule) (RTT (sort_srt), *ri1);
150 rule2 = RT (mma_rules_table_get_rule) (RTT (sort_srt), *ri2);
151 return RTT (sort_srt)->rule_cmp_fn (rule1, rule2);
152}
153
154void RT (mma_sort) (RTT (mma_rules_table) * srt, u32 * next_indices)
155{
156 RTT (sort_srt) = srt;
157 vec_sort_with_function (next_indices, RT (mma_sort_indices));
158}
159
160int
161RT (mma_rules_table_add_rule) (RTT (mma_rules_table) * srt,
162 RTT (mma_rule) * rule)
163{
164 u32 parent_index, i, *next_indices = 0, added = 0, rule_index;
165 RTT (mma_rule) * parent, *child;
166
167 rule_index = RT (mma_rules_table_rule_index) (srt, rule);
168 parent_index = RT (mma_rules_table_lookup_rule) (srt, &rule->match,
169 srt->root_index);
170 parent = RT (mma_rules_table_get_rule) (srt, parent_index);
171 if (RT (rule_is_exact_match) (rule, parent))
172 {
173 parent->action_index = rule->action_index;
174 RT (mma_rule_free) (srt, rule);
175 return -1;
176 }
177
178 if (vec_len (parent->next_indices) == 0)
179 {
180 vec_add1 (parent->next_indices, rule_index);
181 return 0;
182 }
183
184 /* Check if new rule is parent of some of the existing children */
185 for (i = 0; i < vec_len (parent->next_indices); i++)
186 {
187 child = RT (mma_rules_table_get_rule) (srt, parent->next_indices[i]);
188 if (RT (rule_is_match_for_key) (&child->match, rule))
189 {
190 vec_add1 (rule->next_indices, parent->next_indices[i]);
191 if (!added)
192 {
193 vec_add1 (next_indices, rule_index);
194 added = 1;
195 }
196 }
197 else
198 {
199 if (!added && srt->rule_cmp_fn (rule, child) < 0)
200 {
201 vec_add1 (next_indices, rule_index);
202 added = 1;
203 }
204 vec_add1 (next_indices, parent->next_indices[i]);
205 }
206 }
207 if (!added)
208 vec_add1 (next_indices, rule_index);
209 vec_free (parent->next_indices);
210 parent->next_indices = next_indices;
211 return 0;
212}
213
214int
215RT (mma_rules_table_del_rule) (RTT (mma_rules_table) * srt,
216 RTT (mma_rule) * rule, u32 rule_index)
217{
218 RTT (mma_rule) * rp;
219 u32 rv;
220 int i;
221
Florin Corasc97a7392017-11-05 23:07:07 -0800222 ASSERT (rule_index != MMA_TABLE_INVALID_INDEX);
Florin Coras1c710452017-10-17 00:03:13 -0700223 rp = RT (mma_rules_table_get_rule) (srt, rule_index);
224
225 if (!RT (rule_is_match_for_key) (&rule->match, rp))
Florin Corasc97a7392017-11-05 23:07:07 -0800226 return MMA_TABLE_INVALID_INDEX;
Florin Coras1c710452017-10-17 00:03:13 -0700227 if (RT (rule_is_exact_match) (rule, rp))
Florin Coras7999e832017-10-31 01:51:04 -0700228 {
229 if (rule_index == srt->root_index)
Florin Corasc97a7392017-11-05 23:07:07 -0800230 rp->action_index = MMA_TABLE_INVALID_INDEX;
Florin Coras7999e832017-10-31 01:51:04 -0700231 return 1;
232 }
Florin Coras1c710452017-10-17 00:03:13 -0700233 for (i = 0; i < vec_len (rp->next_indices); i++)
234 {
235 rv = RT (mma_rules_table_del_rule) (srt, rule, rp->next_indices[i]);
236 if (rv == 1)
237 {
238 RTT (mma_rule) * child;
239 u32 *next_indices = 0, *new_elts, left_to_add;
240 child = RT (mma_rules_table_get_rule) (srt, rp->next_indices[i]);
241 ASSERT (RT (rule_is_exact_match) (rule, child));
242
243 if (i != 0)
244 {
245 vec_add2 (next_indices, new_elts, i);
Dave Barach178cf492018-11-13 16:34:13 -0500246 clib_memcpy_fast (new_elts, rp->next_indices, i * sizeof (u32));
Florin Coras1c710452017-10-17 00:03:13 -0700247 }
248 if (vec_len (child->next_indices))
249 vec_append (next_indices, child->next_indices);
250 left_to_add = vec_len (rp->next_indices) - i - 1;
251 if (left_to_add)
252 {
253 vec_add2 (next_indices, new_elts, left_to_add);
Dave Barach178cf492018-11-13 16:34:13 -0500254 clib_memcpy_fast (new_elts, &rp->next_indices[i + 1],
255 left_to_add * sizeof (u32));
Florin Coras1c710452017-10-17 00:03:13 -0700256 }
257 RT (mma_rule_free) (srt, child);
258 vec_free (rp->next_indices);
259 rp->next_indices = next_indices;
260 return 0;
261 }
262 else if (rv == 0)
263 return rv;
264 }
Florin Corasc97a7392017-11-05 23:07:07 -0800265 return MMA_TABLE_INVALID_INDEX;
Florin Coras1c710452017-10-17 00:03:13 -0700266}
267
268/*
269 * fd.io coding-style-patch-verification: ON
270 *
271 * Local Variables:
272 * eval: (c-set-style "gnu")
273 * End:
274 */