blob: 26a23b2d270abae1d1f9fc6b01aee375274a8a04 [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{
Steven Luong5677c8a2024-06-24 08:18:38 -070070 RTT (mma_rule) * rule;
71
72 pool_flush (rule, srt->rules, ({}));
Nathan Skrzypczakb3ea73e2021-08-05 10:22:52 +020073 pool_free (srt->rules);
74}
75
Florin Coras1c710452017-10-17 00:03:13 -070076RTT (mma_rule) *
77RT (mma_rules_table_get_rule) (RTT (mma_rules_table) * srt, u32 srt_index)
78{
79 if (!pool_is_free_index (srt->rules, srt_index))
80 return (srt->rules + srt_index);
81 return 0;
82}
83
84u32
85RT (mma_rules_table_rule_index) (RTT (mma_rules_table) * srt,
86 RTT (mma_rule) * sr)
87{
88 ASSERT (sr);
89 return (sr - srt->rules);
90}
91
92/**
93 * Lookup key in table
94 *
95 * This should be optimized .. eventually
96 */
97u32
98RT (mma_rules_table_lookup) (RTT (mma_rules_table) * srt,
99 RTT (mma_mask_or_match) * key, u32 rule_index)
100{
101 RTT (mma_rule) * rp;
102 u32 rv;
103 int i;
104
Florin Corasc97a7392017-11-05 23:07:07 -0800105 ASSERT (rule_index != MMA_TABLE_INVALID_INDEX);
Florin Coras1c710452017-10-17 00:03:13 -0700106 rp = RT (mma_rules_table_get_rule) (srt, rule_index);
107 ASSERT (rp);
108
109 if (!RT (rule_is_match_for_key) (key, rp))
Florin Corasc97a7392017-11-05 23:07:07 -0800110 return MMA_TABLE_INVALID_INDEX;
Florin Coras1c710452017-10-17 00:03:13 -0700111 for (i = 0; i < vec_len (rp->next_indices); i++)
112 {
113 rv = RT (mma_rules_table_lookup) (srt, key, rp->next_indices[i]);
Florin Corasc97a7392017-11-05 23:07:07 -0800114 if (rv != MMA_TABLE_INVALID_INDEX)
Florin Coras1c710452017-10-17 00:03:13 -0700115 return (rv);
116 }
117 return (rp->action_index);
118}
119
120u32
121RT (mma_rules_table_lookup_rule) (RTT (mma_rules_table) * srt,
122 RTT (mma_mask_or_match) * key,
123 u32 rule_index)
124{
125 RTT (mma_rule) * rp;
126 u32 rv;
127 int i;
128
Florin Corasc97a7392017-11-05 23:07:07 -0800129 ASSERT (rule_index != MMA_TABLE_INVALID_INDEX);
Florin Coras1c710452017-10-17 00:03:13 -0700130 rp = RT (mma_rules_table_get_rule) (srt, rule_index);
131 ASSERT (rp);
132
133 if (!RT (rule_is_match_for_key) (key, rp))
Florin Corasc97a7392017-11-05 23:07:07 -0800134 return MMA_TABLE_INVALID_INDEX;
Florin Coras1c710452017-10-17 00:03:13 -0700135 for (i = 0; i < vec_len (rp->next_indices); i++)
136 {
137 rv = RT (mma_rules_table_lookup_rule) (srt, key, rp->next_indices[i]);
Florin Corasc97a7392017-11-05 23:07:07 -0800138 if (rv != MMA_TABLE_INVALID_INDEX)
Florin Coras1c710452017-10-17 00:03:13 -0700139 return (rv);
140 }
141 return rule_index;
142}
143
144static
145RTT (mma_rules_table) *
146RTT (sort_srt);
147
148 int RT (mma_sort_indices) (void *e1, void *e2)
149{
150 u32 *ri1 = e1, *ri2 = e2;
151 RTT (mma_rule) * rule1, *rule2;
152 rule1 = RT (mma_rules_table_get_rule) (RTT (sort_srt), *ri1);
153 rule2 = RT (mma_rules_table_get_rule) (RTT (sort_srt), *ri2);
154 return RTT (sort_srt)->rule_cmp_fn (rule1, rule2);
155}
156
157void RT (mma_sort) (RTT (mma_rules_table) * srt, u32 * next_indices)
158{
159 RTT (sort_srt) = srt;
160 vec_sort_with_function (next_indices, RT (mma_sort_indices));
161}
162
163int
164RT (mma_rules_table_add_rule) (RTT (mma_rules_table) * srt,
165 RTT (mma_rule) * rule)
166{
167 u32 parent_index, i, *next_indices = 0, added = 0, rule_index;
168 RTT (mma_rule) * parent, *child;
169
170 rule_index = RT (mma_rules_table_rule_index) (srt, rule);
171 parent_index = RT (mma_rules_table_lookup_rule) (srt, &rule->match,
172 srt->root_index);
173 parent = RT (mma_rules_table_get_rule) (srt, parent_index);
174 if (RT (rule_is_exact_match) (rule, parent))
175 {
176 parent->action_index = rule->action_index;
177 RT (mma_rule_free) (srt, rule);
178 return -1;
179 }
180
181 if (vec_len (parent->next_indices) == 0)
182 {
183 vec_add1 (parent->next_indices, rule_index);
184 return 0;
185 }
186
187 /* Check if new rule is parent of some of the existing children */
188 for (i = 0; i < vec_len (parent->next_indices); i++)
189 {
190 child = RT (mma_rules_table_get_rule) (srt, parent->next_indices[i]);
191 if (RT (rule_is_match_for_key) (&child->match, rule))
192 {
193 vec_add1 (rule->next_indices, parent->next_indices[i]);
194 if (!added)
195 {
196 vec_add1 (next_indices, rule_index);
197 added = 1;
198 }
199 }
200 else
201 {
202 if (!added && srt->rule_cmp_fn (rule, child) < 0)
203 {
204 vec_add1 (next_indices, rule_index);
205 added = 1;
206 }
207 vec_add1 (next_indices, parent->next_indices[i]);
208 }
209 }
210 if (!added)
211 vec_add1 (next_indices, rule_index);
212 vec_free (parent->next_indices);
213 parent->next_indices = next_indices;
214 return 0;
215}
216
217int
218RT (mma_rules_table_del_rule) (RTT (mma_rules_table) * srt,
219 RTT (mma_rule) * rule, u32 rule_index)
220{
221 RTT (mma_rule) * rp;
222 u32 rv;
223 int i;
224
Florin Corasc97a7392017-11-05 23:07:07 -0800225 ASSERT (rule_index != MMA_TABLE_INVALID_INDEX);
Florin Coras1c710452017-10-17 00:03:13 -0700226 rp = RT (mma_rules_table_get_rule) (srt, rule_index);
227
228 if (!RT (rule_is_match_for_key) (&rule->match, rp))
Florin Corasc97a7392017-11-05 23:07:07 -0800229 return MMA_TABLE_INVALID_INDEX;
Florin Coras1c710452017-10-17 00:03:13 -0700230 if (RT (rule_is_exact_match) (rule, rp))
Florin Coras7999e832017-10-31 01:51:04 -0700231 {
232 if (rule_index == srt->root_index)
Florin Corasc97a7392017-11-05 23:07:07 -0800233 rp->action_index = MMA_TABLE_INVALID_INDEX;
Florin Coras7999e832017-10-31 01:51:04 -0700234 return 1;
235 }
Florin Coras1c710452017-10-17 00:03:13 -0700236 for (i = 0; i < vec_len (rp->next_indices); i++)
237 {
238 rv = RT (mma_rules_table_del_rule) (srt, rule, rp->next_indices[i]);
239 if (rv == 1)
240 {
241 RTT (mma_rule) * child;
242 u32 *next_indices = 0, *new_elts, left_to_add;
243 child = RT (mma_rules_table_get_rule) (srt, rp->next_indices[i]);
244 ASSERT (RT (rule_is_exact_match) (rule, child));
245
246 if (i != 0)
247 {
248 vec_add2 (next_indices, new_elts, i);
Dave Barach178cf492018-11-13 16:34:13 -0500249 clib_memcpy_fast (new_elts, rp->next_indices, i * sizeof (u32));
Florin Coras1c710452017-10-17 00:03:13 -0700250 }
251 if (vec_len (child->next_indices))
252 vec_append (next_indices, child->next_indices);
253 left_to_add = vec_len (rp->next_indices) - i - 1;
254 if (left_to_add)
255 {
256 vec_add2 (next_indices, new_elts, left_to_add);
Dave Barach178cf492018-11-13 16:34:13 -0500257 clib_memcpy_fast (new_elts, &rp->next_indices[i + 1],
258 left_to_add * sizeof (u32));
Florin Coras1c710452017-10-17 00:03:13 -0700259 }
260 RT (mma_rule_free) (srt, child);
261 vec_free (rp->next_indices);
262 rp->next_indices = next_indices;
263 return 0;
264 }
265 else if (rv == 0)
266 return rv;
267 }
Florin Corasc97a7392017-11-05 23:07:07 -0800268 return MMA_TABLE_INVALID_INDEX;
Florin Coras1c710452017-10-17 00:03:13 -0700269}
270
271/*
272 * fd.io coding-style-patch-verification: ON
273 *
274 * Local Variables:
275 * eval: (c-set-style "gnu")
276 * End:
277 */