Commit | Line | Data |
---|---|---|
67d63751 SH |
1 | // SPDX-License-Identifier: BSD-3-Clause |
2 | /* Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries. | |
3 | * Microchip VCAP API kunit test suite | |
4 | */ | |
5 | ||
6 | #include <kunit/test.h> | |
7 | #include "vcap_api.h" | |
8 | #include "vcap_api_client.h" | |
9 | #include "vcap_model_kunit.h" | |
10 | ||
11 | /* First we have the test infrastructure that emulates the platform | |
12 | * implementation | |
13 | */ | |
14 | #define TEST_BUF_CNT 100 | |
15 | #define TEST_BUF_SZ 350 | |
16 | #define STREAMWSIZE 64 | |
17 | ||
18 | static u32 test_updateaddr[STREAMWSIZE] = {}; | |
19 | static int test_updateaddridx; | |
20 | static int test_cache_erase_count; | |
21 | static u32 test_init_start; | |
22 | static u32 test_init_count; | |
23 | static u32 test_hw_counter_id; | |
24 | static struct vcap_cache_data test_hw_cache; | |
c956b9b3 | 25 | static struct net_device test_netdev = {}; |
dccc30cc SH |
26 | static int test_move_addr; |
27 | static int test_move_offset; | |
28 | static int test_move_count; | |
67d63751 SH |
29 | |
30 | /* Callback used by the VCAP API */ | |
31 | static enum vcap_keyfield_set test_val_keyset(struct net_device *ndev, | |
32 | struct vcap_admin *admin, | |
33 | struct vcap_rule *rule, | |
34 | struct vcap_keyset_list *kslist, | |
35 | u16 l3_proto) | |
36 | { | |
37 | int idx; | |
38 | ||
39 | if (kslist->cnt > 0) { | |
40 | switch (admin->vtype) { | |
41 | case VCAP_TYPE_IS0: | |
42 | for (idx = 0; idx < kslist->cnt; idx++) { | |
43 | if (kslist->keysets[idx] == VCAP_KFS_ETAG) | |
44 | return kslist->keysets[idx]; | |
45 | if (kslist->keysets[idx] == VCAP_KFS_PURE_5TUPLE_IP4) | |
46 | return kslist->keysets[idx]; | |
47 | if (kslist->keysets[idx] == VCAP_KFS_NORMAL_5TUPLE_IP4) | |
48 | return kslist->keysets[idx]; | |
49 | if (kslist->keysets[idx] == VCAP_KFS_NORMAL_7TUPLE) | |
50 | return kslist->keysets[idx]; | |
51 | } | |
52 | break; | |
53 | case VCAP_TYPE_IS2: | |
54 | for (idx = 0; idx < kslist->cnt; idx++) { | |
55 | if (kslist->keysets[idx] == VCAP_KFS_MAC_ETYPE) | |
56 | return kslist->keysets[idx]; | |
57 | if (kslist->keysets[idx] == VCAP_KFS_ARP) | |
58 | return kslist->keysets[idx]; | |
59 | if (kslist->keysets[idx] == VCAP_KFS_IP_7TUPLE) | |
60 | return kslist->keysets[idx]; | |
61 | } | |
62 | break; | |
63 | default: | |
64 | pr_info("%s:%d: no validation for VCAP %d\n", | |
65 | __func__, __LINE__, admin->vtype); | |
66 | break; | |
67 | } | |
68 | } | |
69 | return -EINVAL; | |
70 | } | |
71 | ||
72 | /* Callback used by the VCAP API */ | |
73 | static void test_add_def_fields(struct net_device *ndev, | |
74 | struct vcap_admin *admin, | |
75 | struct vcap_rule *rule) | |
76 | { | |
77 | if (admin->vinst == 0 || admin->vinst == 2) | |
78 | vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, VCAP_BIT_1); | |
79 | else | |
80 | vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, VCAP_BIT_0); | |
81 | } | |
82 | ||
83 | /* Callback used by the VCAP API */ | |
84 | static void test_cache_erase(struct vcap_admin *admin) | |
85 | { | |
86 | if (test_cache_erase_count) { | |
87 | memset(admin->cache.keystream, 0, test_cache_erase_count); | |
88 | memset(admin->cache.maskstream, 0, test_cache_erase_count); | |
89 | memset(admin->cache.actionstream, 0, test_cache_erase_count); | |
90 | test_cache_erase_count = 0; | |
91 | } | |
92 | } | |
93 | ||
94 | /* Callback used by the VCAP API */ | |
95 | static void test_cache_init(struct net_device *ndev, struct vcap_admin *admin, | |
96 | u32 start, u32 count) | |
97 | { | |
98 | test_init_start = start; | |
99 | test_init_count = count; | |
100 | } | |
101 | ||
102 | /* Callback used by the VCAP API */ | |
103 | static void test_cache_read(struct net_device *ndev, struct vcap_admin *admin, | |
104 | enum vcap_selection sel, u32 start, u32 count) | |
105 | { | |
106 | u32 *keystr, *mskstr, *actstr; | |
107 | int idx; | |
108 | ||
109 | pr_debug("%s:%d: %d %d\n", __func__, __LINE__, start, count); | |
110 | switch (sel) { | |
111 | case VCAP_SEL_ENTRY: | |
112 | keystr = &admin->cache.keystream[start]; | |
113 | mskstr = &admin->cache.maskstream[start]; | |
114 | for (idx = 0; idx < count; ++idx) { | |
115 | pr_debug("%s:%d: keydata[%02d]: 0x%08x\n", __func__, | |
116 | __LINE__, start + idx, keystr[idx]); | |
117 | } | |
118 | for (idx = 0; idx < count; ++idx) { | |
119 | /* Invert the mask before decoding starts */ | |
120 | mskstr[idx] = ~mskstr[idx]; | |
121 | pr_debug("%s:%d: mskdata[%02d]: 0x%08x\n", __func__, | |
122 | __LINE__, start + idx, mskstr[idx]); | |
123 | } | |
124 | break; | |
125 | case VCAP_SEL_ACTION: | |
126 | actstr = &admin->cache.actionstream[start]; | |
127 | for (idx = 0; idx < count; ++idx) { | |
128 | pr_debug("%s:%d: actdata[%02d]: 0x%08x\n", __func__, | |
129 | __LINE__, start + idx, actstr[idx]); | |
130 | } | |
131 | break; | |
132 | case VCAP_SEL_COUNTER: | |
133 | pr_debug("%s:%d\n", __func__, __LINE__); | |
134 | test_hw_counter_id = start; | |
135 | admin->cache.counter = test_hw_cache.counter; | |
136 | admin->cache.sticky = test_hw_cache.sticky; | |
137 | break; | |
138 | case VCAP_SEL_ALL: | |
139 | pr_debug("%s:%d\n", __func__, __LINE__); | |
140 | break; | |
141 | } | |
142 | } | |
143 | ||
144 | /* Callback used by the VCAP API */ | |
145 | static void test_cache_write(struct net_device *ndev, struct vcap_admin *admin, | |
146 | enum vcap_selection sel, u32 start, u32 count) | |
147 | { | |
148 | u32 *keystr, *mskstr, *actstr; | |
149 | int idx; | |
150 | ||
151 | switch (sel) { | |
152 | case VCAP_SEL_ENTRY: | |
153 | keystr = &admin->cache.keystream[start]; | |
154 | mskstr = &admin->cache.maskstream[start]; | |
155 | for (idx = 0; idx < count; ++idx) { | |
156 | pr_debug("%s:%d: keydata[%02d]: 0x%08x\n", __func__, | |
157 | __LINE__, start + idx, keystr[idx]); | |
158 | } | |
159 | for (idx = 0; idx < count; ++idx) { | |
160 | /* Invert the mask before encoding starts */ | |
161 | mskstr[idx] = ~mskstr[idx]; | |
162 | pr_debug("%s:%d: mskdata[%02d]: 0x%08x\n", __func__, | |
163 | __LINE__, start + idx, mskstr[idx]); | |
164 | } | |
165 | break; | |
166 | case VCAP_SEL_ACTION: | |
167 | actstr = &admin->cache.actionstream[start]; | |
168 | for (idx = 0; idx < count; ++idx) { | |
169 | pr_debug("%s:%d: actdata[%02d]: 0x%08x\n", __func__, | |
170 | __LINE__, start + idx, actstr[idx]); | |
171 | } | |
172 | break; | |
173 | case VCAP_SEL_COUNTER: | |
174 | pr_debug("%s:%d\n", __func__, __LINE__); | |
175 | test_hw_counter_id = start; | |
176 | test_hw_cache.counter = admin->cache.counter; | |
177 | test_hw_cache.sticky = admin->cache.sticky; | |
178 | break; | |
179 | case VCAP_SEL_ALL: | |
180 | pr_err("%s:%d: cannot write all streams at once\n", | |
181 | __func__, __LINE__); | |
182 | break; | |
183 | } | |
184 | } | |
185 | ||
186 | /* Callback used by the VCAP API */ | |
187 | static void test_cache_update(struct net_device *ndev, struct vcap_admin *admin, | |
188 | enum vcap_command cmd, | |
189 | enum vcap_selection sel, u32 addr) | |
190 | { | |
191 | if (test_updateaddridx < ARRAY_SIZE(test_updateaddr)) | |
192 | test_updateaddr[test_updateaddridx] = addr; | |
193 | else | |
194 | pr_err("%s:%d: overflow: %d\n", __func__, __LINE__, test_updateaddridx); | |
195 | test_updateaddridx++; | |
196 | } | |
197 | ||
198 | static void test_cache_move(struct net_device *ndev, struct vcap_admin *admin, | |
199 | u32 addr, int offset, int count) | |
200 | { | |
dccc30cc SH |
201 | test_move_addr = addr; |
202 | test_move_offset = offset; | |
203 | test_move_count = count; | |
67d63751 SH |
204 | } |
205 | ||
206 | /* Provide port information via a callback interface */ | |
e0305cc1 SH |
207 | static int vcap_test_port_info(struct net_device *ndev, |
208 | struct vcap_admin *admin, | |
209 | struct vcap_output_print *out) | |
67d63751 SH |
210 | { |
211 | return 0; | |
212 | } | |
213 | ||
8c379e3c | 214 | static const struct vcap_operations test_callbacks = { |
67d63751 SH |
215 | .validate_keyset = test_val_keyset, |
216 | .add_default_fields = test_add_def_fields, | |
217 | .cache_erase = test_cache_erase, | |
218 | .cache_write = test_cache_write, | |
219 | .cache_read = test_cache_read, | |
220 | .init = test_cache_init, | |
221 | .update = test_cache_update, | |
222 | .move = test_cache_move, | |
223 | .port_info = vcap_test_port_info, | |
224 | }; | |
225 | ||
e8572f03 | 226 | static struct vcap_control test_vctrl = { |
67d63751 SH |
227 | .vcaps = kunit_test_vcaps, |
228 | .stats = &kunit_test_vcap_stats, | |
229 | .ops = &test_callbacks, | |
230 | }; | |
231 | ||
232 | static void vcap_test_api_init(struct vcap_admin *admin) | |
233 | { | |
234 | /* Initialize the shared objects */ | |
235 | INIT_LIST_HEAD(&test_vctrl.list); | |
236 | INIT_LIST_HEAD(&admin->list); | |
237 | INIT_LIST_HEAD(&admin->rules); | |
01ef75a2 | 238 | INIT_LIST_HEAD(&admin->enabled); |
595655e0 | 239 | mutex_init(&admin->lock); |
67d63751 SH |
240 | list_add_tail(&admin->list, &test_vctrl.list); |
241 | memset(test_updateaddr, 0, sizeof(test_updateaddr)); | |
242 | test_updateaddridx = 0; | |
243 | } | |
244 | ||
dccc30cc | 245 | /* Helper function to create a rule of a specific size */ |
20146fa7 JR |
246 | static void test_vcap_xn_rule_creator(struct kunit *test, int cid, |
247 | enum vcap_user user, u16 priority, | |
248 | int id, int size, int expected_addr) | |
dccc30cc | 249 | { |
aa5ac4be HV |
250 | struct vcap_rule *rule; |
251 | struct vcap_rule_internal *ri; | |
dccc30cc SH |
252 | enum vcap_keyfield_set keyset = VCAP_KFS_NO_VALUE; |
253 | enum vcap_actionfield_set actionset = VCAP_AFS_NO_VALUE; | |
254 | int ret; | |
255 | ||
256 | /* init before testing */ | |
257 | memset(test_updateaddr, 0, sizeof(test_updateaddr)); | |
258 | test_updateaddridx = 0; | |
259 | test_move_addr = 0; | |
260 | test_move_offset = 0; | |
261 | test_move_count = 0; | |
262 | ||
263 | switch (size) { | |
264 | case 2: | |
265 | keyset = VCAP_KFS_ETAG; | |
266 | actionset = VCAP_AFS_CLASS_REDUCED; | |
267 | break; | |
268 | case 3: | |
269 | keyset = VCAP_KFS_PURE_5TUPLE_IP4; | |
270 | actionset = VCAP_AFS_CLASSIFICATION; | |
271 | break; | |
272 | case 6: | |
273 | keyset = VCAP_KFS_NORMAL_5TUPLE_IP4; | |
274 | actionset = VCAP_AFS_CLASSIFICATION; | |
275 | break; | |
276 | case 12: | |
277 | keyset = VCAP_KFS_NORMAL_7TUPLE; | |
278 | actionset = VCAP_AFS_FULL; | |
279 | break; | |
280 | default: | |
281 | break; | |
282 | } | |
283 | ||
284 | /* Check that a valid size was used */ | |
285 | KUNIT_ASSERT_NE(test, VCAP_KFS_NO_VALUE, keyset); | |
286 | ||
287 | /* Allocate the rule */ | |
288 | rule = vcap_alloc_rule(&test_vctrl, &test_netdev, cid, user, priority, | |
289 | id); | |
290 | KUNIT_EXPECT_PTR_NE(test, NULL, rule); | |
291 | ||
292 | ri = (struct vcap_rule_internal *)rule; | |
293 | ||
294 | /* Override rule keyset */ | |
295 | ret = vcap_set_rule_set_keyset(rule, keyset); | |
296 | ||
297 | /* Add rule actions : there must be at least one action */ | |
f274a659 | 298 | ret = vcap_rule_add_action_u32(rule, VCAP_AF_ISDX_VAL, 0); |
dccc30cc SH |
299 | |
300 | /* Override rule actionset */ | |
301 | ret = vcap_set_rule_set_actionset(rule, actionset); | |
302 | ||
303 | ret = vcap_val_rule(rule, ETH_P_ALL); | |
304 | KUNIT_EXPECT_EQ(test, 0, ret); | |
305 | KUNIT_EXPECT_EQ(test, keyset, rule->keyset); | |
306 | KUNIT_EXPECT_EQ(test, actionset, rule->actionset); | |
307 | KUNIT_EXPECT_EQ(test, size, ri->size); | |
308 | ||
309 | /* Add rule with write callback */ | |
310 | ret = vcap_add_rule(rule); | |
311 | KUNIT_EXPECT_EQ(test, 0, ret); | |
312 | KUNIT_EXPECT_EQ(test, expected_addr, ri->addr); | |
20146fa7 | 313 | vcap_free_rule(rule); |
dccc30cc SH |
314 | } |
315 | ||
316 | /* Prepare testing rule deletion */ | |
317 | static void test_init_rule_deletion(void) | |
318 | { | |
319 | test_move_addr = 0; | |
320 | test_move_offset = 0; | |
321 | test_move_count = 0; | |
322 | test_init_start = 0; | |
323 | test_init_count = 0; | |
324 | } | |
325 | ||
67d63751 SH |
326 | /* Define the test cases. */ |
327 | ||
328 | static void vcap_api_set_bit_1_test(struct kunit *test) | |
329 | { | |
330 | struct vcap_stream_iter iter = { | |
331 | .offset = 35, | |
332 | .sw_width = 52, | |
333 | .reg_idx = 1, | |
334 | .reg_bitpos = 20, | |
aa5ac4be | 335 | .tg = NULL, |
67d63751 SH |
336 | }; |
337 | u32 stream[2] = {0}; | |
338 | ||
339 | vcap_set_bit(stream, &iter, 1); | |
340 | ||
341 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[0]); | |
342 | KUNIT_EXPECT_EQ(test, (u32)BIT(20), stream[1]); | |
343 | } | |
344 | ||
345 | static void vcap_api_set_bit_0_test(struct kunit *test) | |
346 | { | |
347 | struct vcap_stream_iter iter = { | |
348 | .offset = 35, | |
349 | .sw_width = 52, | |
350 | .reg_idx = 2, | |
351 | .reg_bitpos = 11, | |
aa5ac4be | 352 | .tg = NULL, |
67d63751 SH |
353 | }; |
354 | u32 stream[3] = {~0, ~0, ~0}; | |
355 | ||
356 | vcap_set_bit(stream, &iter, 0); | |
357 | ||
358 | KUNIT_EXPECT_EQ(test, (u32)~0, stream[0]); | |
359 | KUNIT_EXPECT_EQ(test, (u32)~0, stream[1]); | |
360 | KUNIT_EXPECT_EQ(test, (u32)~BIT(11), stream[2]); | |
361 | } | |
362 | ||
363 | static void vcap_api_iterator_init_test(struct kunit *test) | |
364 | { | |
365 | struct vcap_stream_iter iter; | |
366 | struct vcap_typegroup typegroups[] = { | |
367 | { .offset = 0, .width = 2, .value = 2, }, | |
368 | { .offset = 156, .width = 1, .value = 0, }, | |
369 | { .offset = 0, .width = 0, .value = 0, }, | |
370 | }; | |
371 | struct vcap_typegroup typegroups2[] = { | |
372 | { .offset = 0, .width = 3, .value = 4, }, | |
373 | { .offset = 49, .width = 2, .value = 0, }, | |
374 | { .offset = 98, .width = 2, .value = 0, }, | |
375 | }; | |
376 | ||
377 | vcap_iter_init(&iter, 52, typegroups, 86); | |
378 | ||
379 | KUNIT_EXPECT_EQ(test, 52, iter.sw_width); | |
380 | KUNIT_EXPECT_EQ(test, 86 + 2, iter.offset); | |
381 | KUNIT_EXPECT_EQ(test, 3, iter.reg_idx); | |
382 | KUNIT_EXPECT_EQ(test, 4, iter.reg_bitpos); | |
383 | ||
384 | vcap_iter_init(&iter, 49, typegroups2, 134); | |
385 | ||
386 | KUNIT_EXPECT_EQ(test, 49, iter.sw_width); | |
387 | KUNIT_EXPECT_EQ(test, 134 + 7, iter.offset); | |
388 | KUNIT_EXPECT_EQ(test, 5, iter.reg_idx); | |
389 | KUNIT_EXPECT_EQ(test, 11, iter.reg_bitpos); | |
390 | } | |
391 | ||
392 | static void vcap_api_iterator_next_test(struct kunit *test) | |
393 | { | |
394 | struct vcap_stream_iter iter; | |
395 | struct vcap_typegroup typegroups[] = { | |
396 | { .offset = 0, .width = 4, .value = 8, }, | |
397 | { .offset = 49, .width = 1, .value = 0, }, | |
398 | { .offset = 98, .width = 2, .value = 0, }, | |
399 | { .offset = 147, .width = 3, .value = 0, }, | |
400 | { .offset = 196, .width = 2, .value = 0, }, | |
401 | { .offset = 245, .width = 1, .value = 0, }, | |
402 | }; | |
403 | int idx; | |
404 | ||
405 | vcap_iter_init(&iter, 49, typegroups, 86); | |
406 | ||
407 | KUNIT_EXPECT_EQ(test, 49, iter.sw_width); | |
408 | KUNIT_EXPECT_EQ(test, 86 + 5, iter.offset); | |
409 | KUNIT_EXPECT_EQ(test, 3, iter.reg_idx); | |
410 | KUNIT_EXPECT_EQ(test, 10, iter.reg_bitpos); | |
411 | ||
412 | vcap_iter_next(&iter); | |
413 | ||
414 | KUNIT_EXPECT_EQ(test, 91 + 1, iter.offset); | |
415 | KUNIT_EXPECT_EQ(test, 3, iter.reg_idx); | |
416 | KUNIT_EXPECT_EQ(test, 11, iter.reg_bitpos); | |
417 | ||
418 | for (idx = 0; idx < 6; idx++) | |
419 | vcap_iter_next(&iter); | |
420 | ||
421 | KUNIT_EXPECT_EQ(test, 92 + 6 + 2, iter.offset); | |
422 | KUNIT_EXPECT_EQ(test, 4, iter.reg_idx); | |
423 | KUNIT_EXPECT_EQ(test, 2, iter.reg_bitpos); | |
424 | } | |
425 | ||
426 | static void vcap_api_encode_typegroups_test(struct kunit *test) | |
427 | { | |
428 | u32 stream[12] = {0}; | |
429 | struct vcap_typegroup typegroups[] = { | |
430 | { .offset = 0, .width = 4, .value = 8, }, | |
431 | { .offset = 49, .width = 1, .value = 1, }, | |
432 | { .offset = 98, .width = 2, .value = 3, }, | |
433 | { .offset = 147, .width = 3, .value = 5, }, | |
434 | { .offset = 196, .width = 2, .value = 2, }, | |
435 | { .offset = 245, .width = 5, .value = 27, }, | |
436 | { .offset = 0, .width = 0, .value = 0, }, | |
437 | }; | |
438 | ||
439 | vcap_encode_typegroups(stream, 49, typegroups, false); | |
440 | ||
441 | KUNIT_EXPECT_EQ(test, (u32)0x8, stream[0]); | |
442 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[1]); | |
443 | KUNIT_EXPECT_EQ(test, (u32)0x1, stream[2]); | |
444 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[3]); | |
445 | KUNIT_EXPECT_EQ(test, (u32)0x3, stream[4]); | |
446 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[5]); | |
447 | KUNIT_EXPECT_EQ(test, (u32)0x5, stream[6]); | |
448 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[7]); | |
449 | KUNIT_EXPECT_EQ(test, (u32)0x2, stream[8]); | |
450 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[9]); | |
451 | KUNIT_EXPECT_EQ(test, (u32)27, stream[10]); | |
452 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[11]); | |
453 | } | |
454 | ||
455 | static void vcap_api_encode_bit_test(struct kunit *test) | |
456 | { | |
457 | struct vcap_stream_iter iter; | |
458 | u32 stream[4] = {0}; | |
459 | struct vcap_typegroup typegroups[] = { | |
460 | { .offset = 0, .width = 4, .value = 8, }, | |
461 | { .offset = 49, .width = 1, .value = 1, }, | |
462 | { .offset = 98, .width = 2, .value = 3, }, | |
463 | { .offset = 147, .width = 3, .value = 5, }, | |
464 | { .offset = 196, .width = 2, .value = 2, }, | |
465 | { .offset = 245, .width = 1, .value = 0, }, | |
466 | }; | |
467 | ||
468 | vcap_iter_init(&iter, 49, typegroups, 44); | |
469 | ||
470 | KUNIT_EXPECT_EQ(test, 48, iter.offset); | |
471 | KUNIT_EXPECT_EQ(test, 1, iter.reg_idx); | |
472 | KUNIT_EXPECT_EQ(test, 16, iter.reg_bitpos); | |
473 | ||
474 | vcap_encode_bit(stream, &iter, 1); | |
475 | ||
476 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[0]); | |
477 | KUNIT_EXPECT_EQ(test, (u32)BIT(16), stream[1]); | |
478 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[2]); | |
479 | } | |
480 | ||
481 | static void vcap_api_encode_field_test(struct kunit *test) | |
482 | { | |
483 | struct vcap_stream_iter iter; | |
484 | u32 stream[16] = {0}; | |
485 | struct vcap_typegroup typegroups[] = { | |
486 | { .offset = 0, .width = 4, .value = 8, }, | |
487 | { .offset = 49, .width = 1, .value = 1, }, | |
488 | { .offset = 98, .width = 2, .value = 3, }, | |
489 | { .offset = 147, .width = 3, .value = 5, }, | |
490 | { .offset = 196, .width = 2, .value = 2, }, | |
491 | { .offset = 245, .width = 5, .value = 27, }, | |
492 | { .offset = 0, .width = 0, .value = 0, }, | |
493 | }; | |
494 | struct vcap_field rf = { | |
495 | .type = VCAP_FIELD_U32, | |
496 | .offset = 86, | |
497 | .width = 4, | |
498 | }; | |
499 | u8 value[] = {0x5}; | |
500 | ||
501 | vcap_iter_init(&iter, 49, typegroups, rf.offset); | |
502 | ||
503 | KUNIT_EXPECT_EQ(test, 91, iter.offset); | |
504 | KUNIT_EXPECT_EQ(test, 3, iter.reg_idx); | |
505 | KUNIT_EXPECT_EQ(test, 10, iter.reg_bitpos); | |
506 | ||
507 | vcap_encode_field(stream, &iter, rf.width, value); | |
508 | ||
509 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[0]); | |
510 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[1]); | |
511 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[2]); | |
512 | KUNIT_EXPECT_EQ(test, (u32)(0x5 << 10), stream[3]); | |
513 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[4]); | |
514 | ||
515 | vcap_encode_typegroups(stream, 49, typegroups, false); | |
516 | ||
517 | KUNIT_EXPECT_EQ(test, (u32)0x8, stream[0]); | |
518 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[1]); | |
519 | KUNIT_EXPECT_EQ(test, (u32)0x1, stream[2]); | |
520 | KUNIT_EXPECT_EQ(test, (u32)(0x5 << 10), stream[3]); | |
521 | KUNIT_EXPECT_EQ(test, (u32)0x3, stream[4]); | |
522 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[5]); | |
523 | KUNIT_EXPECT_EQ(test, (u32)0x5, stream[6]); | |
524 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[7]); | |
525 | KUNIT_EXPECT_EQ(test, (u32)0x2, stream[8]); | |
526 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[9]); | |
527 | KUNIT_EXPECT_EQ(test, (u32)27, stream[10]); | |
528 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[11]); | |
529 | } | |
530 | ||
531 | /* In this testcase the subword is smaller than a register */ | |
532 | static void vcap_api_encode_short_field_test(struct kunit *test) | |
533 | { | |
534 | struct vcap_stream_iter iter; | |
535 | int sw_width = 21; | |
536 | u32 stream[6] = {0}; | |
537 | struct vcap_typegroup tgt[] = { | |
538 | { .offset = 0, .width = 3, .value = 7, }, | |
539 | { .offset = 21, .width = 2, .value = 3, }, | |
540 | { .offset = 42, .width = 1, .value = 1, }, | |
541 | { .offset = 0, .width = 0, .value = 0, }, | |
542 | }; | |
543 | struct vcap_field rf = { | |
544 | .type = VCAP_FIELD_U32, | |
545 | .offset = 25, | |
546 | .width = 4, | |
547 | }; | |
548 | u8 value[] = {0x5}; | |
549 | ||
550 | vcap_iter_init(&iter, sw_width, tgt, rf.offset); | |
551 | ||
552 | KUNIT_EXPECT_EQ(test, 1, iter.regs_per_sw); | |
553 | KUNIT_EXPECT_EQ(test, 21, iter.sw_width); | |
554 | KUNIT_EXPECT_EQ(test, 25 + 3 + 2, iter.offset); | |
555 | KUNIT_EXPECT_EQ(test, 1, iter.reg_idx); | |
556 | KUNIT_EXPECT_EQ(test, 25 + 3 + 2 - sw_width, iter.reg_bitpos); | |
557 | ||
558 | vcap_encode_field(stream, &iter, rf.width, value); | |
559 | ||
560 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[0]); | |
561 | KUNIT_EXPECT_EQ(test, (u32)(0x5 << (25 + 3 + 2 - sw_width)), stream[1]); | |
562 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[2]); | |
563 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[3]); | |
564 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[4]); | |
565 | KUNIT_EXPECT_EQ(test, (u32)0x0, stream[5]); | |
566 | ||
567 | vcap_encode_typegroups(stream, sw_width, tgt, false); | |
568 | ||
569 | KUNIT_EXPECT_EQ(test, (u32)7, stream[0]); | |
570 | KUNIT_EXPECT_EQ(test, (u32)((0x5 << (25 + 3 + 2 - sw_width)) + 3), stream[1]); | |
571 | KUNIT_EXPECT_EQ(test, (u32)1, stream[2]); | |
572 | KUNIT_EXPECT_EQ(test, (u32)0, stream[3]); | |
573 | KUNIT_EXPECT_EQ(test, (u32)0, stream[4]); | |
574 | KUNIT_EXPECT_EQ(test, (u32)0, stream[5]); | |
575 | } | |
576 | ||
577 | static void vcap_api_encode_keyfield_test(struct kunit *test) | |
578 | { | |
579 | u32 keywords[16] = {0}; | |
580 | u32 maskwords[16] = {0}; | |
581 | struct vcap_admin admin = { | |
582 | .vtype = VCAP_TYPE_IS2, | |
583 | .cache = { | |
584 | .keystream = keywords, | |
585 | .maskstream = maskwords, | |
586 | .actionstream = keywords, | |
587 | }, | |
588 | }; | |
589 | struct vcap_rule_internal rule = { | |
590 | .admin = &admin, | |
591 | .data = { | |
592 | .keyset = VCAP_KFS_MAC_ETYPE, | |
593 | }, | |
594 | .vctrl = &test_vctrl, | |
595 | }; | |
596 | struct vcap_client_keyfield ckf = { | |
597 | .ctrl.list = {}, | |
598 | .ctrl.key = VCAP_KF_ISDX_CLS, | |
599 | .ctrl.type = VCAP_FIELD_U32, | |
600 | .data.u32.value = 0xeef014a1, | |
601 | .data.u32.mask = 0xfff, | |
602 | }; | |
603 | struct vcap_field rf = { | |
604 | .type = VCAP_FIELD_U32, | |
605 | .offset = 56, | |
606 | .width = 12, | |
607 | }; | |
608 | struct vcap_typegroup tgt[] = { | |
609 | { .offset = 0, .width = 2, .value = 2, }, | |
610 | { .offset = 156, .width = 1, .value = 1, }, | |
611 | { .offset = 0, .width = 0, .value = 0, }, | |
612 | }; | |
613 | ||
614 | vcap_test_api_init(&admin); | |
615 | vcap_encode_keyfield(&rule, &ckf, &rf, tgt); | |
616 | ||
617 | /* Key */ | |
618 | KUNIT_EXPECT_EQ(test, (u32)0x0, keywords[0]); | |
619 | KUNIT_EXPECT_EQ(test, (u32)0x0, keywords[1]); | |
620 | KUNIT_EXPECT_EQ(test, (u32)(0x04a1 << 6), keywords[2]); | |
621 | KUNIT_EXPECT_EQ(test, (u32)0x0, keywords[3]); | |
622 | KUNIT_EXPECT_EQ(test, (u32)0x0, keywords[4]); | |
623 | KUNIT_EXPECT_EQ(test, (u32)0x0, keywords[5]); | |
624 | KUNIT_EXPECT_EQ(test, (u32)0x0, keywords[6]); | |
625 | ||
626 | /* Mask */ | |
627 | KUNIT_EXPECT_EQ(test, (u32)0x0, maskwords[0]); | |
628 | KUNIT_EXPECT_EQ(test, (u32)0x0, maskwords[1]); | |
629 | KUNIT_EXPECT_EQ(test, (u32)(0x0fff << 6), maskwords[2]); | |
630 | KUNIT_EXPECT_EQ(test, (u32)0x0, maskwords[3]); | |
631 | KUNIT_EXPECT_EQ(test, (u32)0x0, maskwords[4]); | |
632 | KUNIT_EXPECT_EQ(test, (u32)0x0, maskwords[5]); | |
633 | KUNIT_EXPECT_EQ(test, (u32)0x0, maskwords[6]); | |
634 | } | |
635 | ||
636 | static void vcap_api_encode_max_keyfield_test(struct kunit *test) | |
637 | { | |
638 | int idx; | |
639 | u32 keywords[6] = {0}; | |
640 | u32 maskwords[6] = {0}; | |
641 | struct vcap_admin admin = { | |
642 | .vtype = VCAP_TYPE_IS2, | |
643 | /* IS2 sw_width = 52 bit */ | |
644 | .cache = { | |
645 | .keystream = keywords, | |
646 | .maskstream = maskwords, | |
647 | .actionstream = keywords, | |
648 | }, | |
649 | }; | |
650 | struct vcap_rule_internal rule = { | |
651 | .admin = &admin, | |
652 | .data = { | |
653 | .keyset = VCAP_KFS_IP_7TUPLE, | |
654 | }, | |
655 | .vctrl = &test_vctrl, | |
656 | }; | |
657 | struct vcap_client_keyfield ckf = { | |
658 | .ctrl.list = {}, | |
659 | .ctrl.key = VCAP_KF_L3_IP6_DIP, | |
660 | .ctrl.type = VCAP_FIELD_U128, | |
661 | .data.u128.value = { 0xa1, 0xa2, 0xa3, 0xa4, 0, 0, 0x43, 0, | |
662 | 0, 0, 0, 0, 0, 0, 0x78, 0x8e, }, | |
663 | .data.u128.mask = { 0xff, 0xff, 0xff, 0xff, 0, 0, 0xff, 0, | |
664 | 0, 0, 0, 0, 0, 0, 0xff, 0xff }, | |
665 | }; | |
666 | struct vcap_field rf = { | |
667 | .type = VCAP_FIELD_U128, | |
668 | .offset = 0, | |
669 | .width = 128, | |
670 | }; | |
671 | struct vcap_typegroup tgt[] = { | |
672 | { .offset = 0, .width = 2, .value = 2, }, | |
673 | { .offset = 156, .width = 1, .value = 1, }, | |
674 | { .offset = 0, .width = 0, .value = 0, }, | |
675 | }; | |
676 | u32 keyres[] = { | |
677 | 0x928e8a84, | |
678 | 0x000c0002, | |
679 | 0x00000010, | |
680 | 0x00000000, | |
681 | 0x0239e000, | |
682 | 0x00000000, | |
683 | }; | |
684 | u32 mskres[] = { | |
685 | 0xfffffffc, | |
686 | 0x000c0003, | |
687 | 0x0000003f, | |
688 | 0x00000000, | |
689 | 0x03fffc00, | |
690 | 0x00000000, | |
691 | }; | |
692 | ||
693 | vcap_encode_keyfield(&rule, &ckf, &rf, tgt); | |
694 | ||
695 | /* Key */ | |
696 | for (idx = 0; idx < ARRAY_SIZE(keyres); ++idx) | |
697 | KUNIT_EXPECT_EQ(test, keyres[idx], keywords[idx]); | |
698 | /* Mask */ | |
699 | for (idx = 0; idx < ARRAY_SIZE(mskres); ++idx) | |
700 | KUNIT_EXPECT_EQ(test, mskres[idx], maskwords[idx]); | |
701 | } | |
702 | ||
703 | static void vcap_api_encode_actionfield_test(struct kunit *test) | |
704 | { | |
705 | u32 actwords[16] = {0}; | |
706 | int sw_width = 21; | |
707 | struct vcap_admin admin = { | |
708 | .vtype = VCAP_TYPE_ES2, /* act_width = 21 */ | |
709 | .cache = { | |
710 | .actionstream = actwords, | |
711 | }, | |
712 | }; | |
713 | struct vcap_rule_internal rule = { | |
714 | .admin = &admin, | |
715 | .data = { | |
716 | .actionset = VCAP_AFS_BASE_TYPE, | |
717 | }, | |
718 | .vctrl = &test_vctrl, | |
719 | }; | |
720 | struct vcap_client_actionfield caf = { | |
721 | .ctrl.list = {}, | |
722 | .ctrl.action = VCAP_AF_POLICE_IDX, | |
723 | .ctrl.type = VCAP_FIELD_U32, | |
724 | .data.u32.value = 0x67908032, | |
725 | }; | |
726 | struct vcap_field rf = { | |
727 | .type = VCAP_FIELD_U32, | |
728 | .offset = 35, | |
729 | .width = 6, | |
730 | }; | |
731 | struct vcap_typegroup tgt[] = { | |
732 | { .offset = 0, .width = 2, .value = 2, }, | |
733 | { .offset = 21, .width = 1, .value = 1, }, | |
734 | { .offset = 42, .width = 1, .value = 0, }, | |
735 | { .offset = 0, .width = 0, .value = 0, }, | |
736 | }; | |
737 | ||
738 | vcap_encode_actionfield(&rule, &caf, &rf, tgt); | |
739 | ||
740 | /* Action */ | |
741 | KUNIT_EXPECT_EQ(test, (u32)0x0, actwords[0]); | |
742 | KUNIT_EXPECT_EQ(test, (u32)((0x32 << (35 + 2 + 1 - sw_width)) & 0x1fffff), actwords[1]); | |
743 | KUNIT_EXPECT_EQ(test, (u32)((0x32 >> ((2 * sw_width) - 38 - 1))), actwords[2]); | |
744 | KUNIT_EXPECT_EQ(test, (u32)0x0, actwords[3]); | |
745 | KUNIT_EXPECT_EQ(test, (u32)0x0, actwords[4]); | |
746 | KUNIT_EXPECT_EQ(test, (u32)0x0, actwords[5]); | |
747 | KUNIT_EXPECT_EQ(test, (u32)0x0, actwords[6]); | |
748 | } | |
749 | ||
750 | static void vcap_api_keyfield_typegroup_test(struct kunit *test) | |
751 | { | |
752 | const struct vcap_typegroup *tg; | |
753 | ||
754 | tg = vcap_keyfield_typegroup(&test_vctrl, VCAP_TYPE_IS2, VCAP_KFS_MAC_ETYPE); | |
755 | KUNIT_EXPECT_PTR_NE(test, NULL, tg); | |
756 | KUNIT_EXPECT_EQ(test, 0, tg[0].offset); | |
757 | KUNIT_EXPECT_EQ(test, 2, tg[0].width); | |
758 | KUNIT_EXPECT_EQ(test, 2, tg[0].value); | |
759 | KUNIT_EXPECT_EQ(test, 156, tg[1].offset); | |
760 | KUNIT_EXPECT_EQ(test, 1, tg[1].width); | |
761 | KUNIT_EXPECT_EQ(test, 0, tg[1].value); | |
762 | KUNIT_EXPECT_EQ(test, 0, tg[2].offset); | |
763 | KUNIT_EXPECT_EQ(test, 0, tg[2].width); | |
764 | KUNIT_EXPECT_EQ(test, 0, tg[2].value); | |
765 | ||
766 | tg = vcap_keyfield_typegroup(&test_vctrl, VCAP_TYPE_ES2, VCAP_KFS_LL_FULL); | |
767 | KUNIT_EXPECT_PTR_EQ(test, NULL, tg); | |
768 | } | |
769 | ||
770 | static void vcap_api_actionfield_typegroup_test(struct kunit *test) | |
771 | { | |
772 | const struct vcap_typegroup *tg; | |
773 | ||
774 | tg = vcap_actionfield_typegroup(&test_vctrl, VCAP_TYPE_IS0, VCAP_AFS_FULL); | |
775 | KUNIT_EXPECT_PTR_NE(test, NULL, tg); | |
776 | KUNIT_EXPECT_EQ(test, 0, tg[0].offset); | |
777 | KUNIT_EXPECT_EQ(test, 3, tg[0].width); | |
778 | KUNIT_EXPECT_EQ(test, 4, tg[0].value); | |
779 | KUNIT_EXPECT_EQ(test, 110, tg[1].offset); | |
780 | KUNIT_EXPECT_EQ(test, 2, tg[1].width); | |
781 | KUNIT_EXPECT_EQ(test, 0, tg[1].value); | |
782 | KUNIT_EXPECT_EQ(test, 220, tg[2].offset); | |
783 | KUNIT_EXPECT_EQ(test, 2, tg[2].width); | |
784 | KUNIT_EXPECT_EQ(test, 0, tg[2].value); | |
785 | KUNIT_EXPECT_EQ(test, 0, tg[3].offset); | |
786 | KUNIT_EXPECT_EQ(test, 0, tg[3].width); | |
787 | KUNIT_EXPECT_EQ(test, 0, tg[3].value); | |
788 | ||
789 | tg = vcap_actionfield_typegroup(&test_vctrl, VCAP_TYPE_IS2, VCAP_AFS_CLASSIFICATION); | |
790 | KUNIT_EXPECT_PTR_EQ(test, NULL, tg); | |
791 | } | |
792 | ||
793 | static void vcap_api_vcap_keyfields_test(struct kunit *test) | |
794 | { | |
795 | const struct vcap_field *ft; | |
796 | ||
797 | ft = vcap_keyfields(&test_vctrl, VCAP_TYPE_IS2, VCAP_KFS_MAC_ETYPE); | |
798 | KUNIT_EXPECT_PTR_NE(test, NULL, ft); | |
799 | ||
800 | /* Keyset that is not available and within the maximum keyset enum value */ | |
801 | ft = vcap_keyfields(&test_vctrl, VCAP_TYPE_ES2, VCAP_KFS_PURE_5TUPLE_IP4); | |
802 | KUNIT_EXPECT_PTR_EQ(test, NULL, ft); | |
803 | ||
804 | /* Keyset that is not available and beyond the maximum keyset enum value */ | |
805 | ft = vcap_keyfields(&test_vctrl, VCAP_TYPE_ES2, VCAP_KFS_LL_FULL); | |
806 | KUNIT_EXPECT_PTR_EQ(test, NULL, ft); | |
807 | } | |
808 | ||
809 | static void vcap_api_vcap_actionfields_test(struct kunit *test) | |
810 | { | |
811 | const struct vcap_field *ft; | |
812 | ||
813 | ft = vcap_actionfields(&test_vctrl, VCAP_TYPE_IS0, VCAP_AFS_FULL); | |
814 | KUNIT_EXPECT_PTR_NE(test, NULL, ft); | |
815 | ||
816 | ft = vcap_actionfields(&test_vctrl, VCAP_TYPE_IS2, VCAP_AFS_FULL); | |
817 | KUNIT_EXPECT_PTR_EQ(test, NULL, ft); | |
818 | ||
819 | ft = vcap_actionfields(&test_vctrl, VCAP_TYPE_IS2, VCAP_AFS_CLASSIFICATION); | |
820 | KUNIT_EXPECT_PTR_EQ(test, NULL, ft); | |
821 | } | |
822 | ||
823 | static void vcap_api_encode_rule_keyset_test(struct kunit *test) | |
824 | { | |
825 | u32 keywords[16] = {0}; | |
826 | u32 maskwords[16] = {0}; | |
827 | struct vcap_admin admin = { | |
828 | .vtype = VCAP_TYPE_IS2, | |
829 | .cache = { | |
830 | .keystream = keywords, | |
831 | .maskstream = maskwords, | |
832 | }, | |
833 | }; | |
834 | struct vcap_rule_internal rule = { | |
835 | .admin = &admin, | |
836 | .data = { | |
837 | .keyset = VCAP_KFS_MAC_ETYPE, | |
838 | }, | |
839 | .vctrl = &test_vctrl, | |
840 | }; | |
841 | struct vcap_client_keyfield ckf[] = { | |
842 | { | |
843 | .ctrl.key = VCAP_KF_TYPE, | |
844 | .ctrl.type = VCAP_FIELD_U32, | |
845 | .data.u32.value = 0x00, | |
846 | .data.u32.mask = 0x0f, | |
847 | }, | |
848 | { | |
849 | .ctrl.key = VCAP_KF_LOOKUP_FIRST_IS, | |
850 | .ctrl.type = VCAP_FIELD_BIT, | |
851 | .data.u1.value = 0x01, | |
852 | .data.u1.mask = 0x01, | |
853 | }, | |
854 | { | |
855 | .ctrl.key = VCAP_KF_IF_IGR_PORT_MASK_L3, | |
856 | .ctrl.type = VCAP_FIELD_BIT, | |
857 | .data.u1.value = 0x00, | |
858 | .data.u1.mask = 0x01, | |
859 | }, | |
860 | { | |
861 | .ctrl.key = VCAP_KF_IF_IGR_PORT_MASK_RNG, | |
862 | .ctrl.type = VCAP_FIELD_U32, | |
863 | .data.u32.value = 0x00, | |
864 | .data.u32.mask = 0x0f, | |
865 | }, | |
866 | { | |
867 | .ctrl.key = VCAP_KF_IF_IGR_PORT_MASK, | |
868 | .ctrl.type = VCAP_FIELD_U72, | |
869 | .data.u72.value = {0x0, 0x00, 0x00, 0x00}, | |
870 | .data.u72.mask = {0xfd, 0xff, 0xff, 0xff}, | |
871 | }, | |
872 | { | |
873 | .ctrl.key = VCAP_KF_L2_DMAC, | |
874 | .ctrl.type = VCAP_FIELD_U48, | |
875 | /* Opposite endianness */ | |
876 | .data.u48.value = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}, | |
877 | .data.u48.mask = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, | |
878 | }, | |
879 | { | |
880 | .ctrl.key = VCAP_KF_ETYPE_LEN_IS, | |
881 | .ctrl.type = VCAP_FIELD_BIT, | |
882 | .data.u1.value = 0x01, | |
883 | .data.u1.mask = 0x01, | |
884 | }, | |
885 | { | |
886 | .ctrl.key = VCAP_KF_ETYPE, | |
887 | .ctrl.type = VCAP_FIELD_U32, | |
888 | .data.u32.value = 0xaabb, | |
889 | .data.u32.mask = 0xffff, | |
890 | }, | |
891 | }; | |
892 | int idx; | |
893 | int ret; | |
894 | ||
895 | /* Empty entry list */ | |
896 | INIT_LIST_HEAD(&rule.data.keyfields); | |
897 | ret = vcap_encode_rule_keyset(&rule); | |
898 | KUNIT_EXPECT_EQ(test, -EINVAL, ret); | |
899 | ||
900 | for (idx = 0; idx < ARRAY_SIZE(ckf); idx++) | |
901 | list_add_tail(&ckf[idx].ctrl.list, &rule.data.keyfields); | |
902 | ret = vcap_encode_rule_keyset(&rule); | |
903 | KUNIT_EXPECT_EQ(test, 0, ret); | |
904 | ||
905 | /* The key and mask values below are from an actual Sparx5 rule config */ | |
906 | /* Key */ | |
907 | KUNIT_EXPECT_EQ(test, (u32)0x00000042, keywords[0]); | |
908 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, keywords[1]); | |
909 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, keywords[2]); | |
910 | KUNIT_EXPECT_EQ(test, (u32)0x00020100, keywords[3]); | |
911 | KUNIT_EXPECT_EQ(test, (u32)0x60504030, keywords[4]); | |
912 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, keywords[5]); | |
913 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, keywords[6]); | |
914 | KUNIT_EXPECT_EQ(test, (u32)0x0002aaee, keywords[7]); | |
915 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, keywords[8]); | |
916 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, keywords[9]); | |
917 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, keywords[10]); | |
918 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, keywords[11]); | |
919 | ||
920 | /* Mask: they will be inverted when applied to the register */ | |
921 | KUNIT_EXPECT_EQ(test, (u32)~0x00b07f80, maskwords[0]); | |
922 | KUNIT_EXPECT_EQ(test, (u32)~0xfff00000, maskwords[1]); | |
923 | KUNIT_EXPECT_EQ(test, (u32)~0xfffffffc, maskwords[2]); | |
924 | KUNIT_EXPECT_EQ(test, (u32)~0xfff000ff, maskwords[3]); | |
925 | KUNIT_EXPECT_EQ(test, (u32)~0x00000000, maskwords[4]); | |
926 | KUNIT_EXPECT_EQ(test, (u32)~0xfffffff0, maskwords[5]); | |
927 | KUNIT_EXPECT_EQ(test, (u32)~0xfffffffe, maskwords[6]); | |
928 | KUNIT_EXPECT_EQ(test, (u32)~0xfffc0001, maskwords[7]); | |
929 | KUNIT_EXPECT_EQ(test, (u32)~0xffffffff, maskwords[8]); | |
930 | KUNIT_EXPECT_EQ(test, (u32)~0xffffffff, maskwords[9]); | |
931 | KUNIT_EXPECT_EQ(test, (u32)~0xffffffff, maskwords[10]); | |
932 | KUNIT_EXPECT_EQ(test, (u32)~0xffffffff, maskwords[11]); | |
933 | } | |
934 | ||
935 | static void vcap_api_encode_rule_actionset_test(struct kunit *test) | |
936 | { | |
937 | u32 actwords[16] = {0}; | |
938 | struct vcap_admin admin = { | |
939 | .vtype = VCAP_TYPE_IS2, | |
940 | .cache = { | |
941 | .actionstream = actwords, | |
942 | }, | |
943 | }; | |
944 | struct vcap_rule_internal rule = { | |
945 | .admin = &admin, | |
946 | .data = { | |
947 | .actionset = VCAP_AFS_BASE_TYPE, | |
948 | }, | |
949 | .vctrl = &test_vctrl, | |
950 | }; | |
951 | struct vcap_client_actionfield caf[] = { | |
952 | { | |
953 | .ctrl.action = VCAP_AF_MATCH_ID, | |
954 | .ctrl.type = VCAP_FIELD_U32, | |
955 | .data.u32.value = 0x01, | |
956 | }, | |
957 | { | |
958 | .ctrl.action = VCAP_AF_MATCH_ID_MASK, | |
959 | .ctrl.type = VCAP_FIELD_U32, | |
960 | .data.u32.value = 0x01, | |
961 | }, | |
962 | { | |
963 | .ctrl.action = VCAP_AF_CNT_ID, | |
964 | .ctrl.type = VCAP_FIELD_U32, | |
965 | .data.u32.value = 0x64, | |
966 | }, | |
967 | }; | |
968 | int idx; | |
969 | int ret; | |
970 | ||
971 | /* Empty entry list */ | |
972 | INIT_LIST_HEAD(&rule.data.actionfields); | |
973 | ret = vcap_encode_rule_actionset(&rule); | |
974 | /* We allow rules with no actions */ | |
975 | KUNIT_EXPECT_EQ(test, 0, ret); | |
976 | ||
977 | for (idx = 0; idx < ARRAY_SIZE(caf); idx++) | |
978 | list_add_tail(&caf[idx].ctrl.list, &rule.data.actionfields); | |
979 | ret = vcap_encode_rule_actionset(&rule); | |
980 | KUNIT_EXPECT_EQ(test, 0, ret); | |
981 | ||
982 | /* The action values below are from an actual Sparx5 rule config */ | |
983 | KUNIT_EXPECT_EQ(test, (u32)0x00000002, actwords[0]); | |
984 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, actwords[1]); | |
985 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, actwords[2]); | |
986 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, actwords[3]); | |
987 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, actwords[4]); | |
988 | KUNIT_EXPECT_EQ(test, (u32)0x00100000, actwords[5]); | |
989 | KUNIT_EXPECT_EQ(test, (u32)0x06400010, actwords[6]); | |
990 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, actwords[7]); | |
991 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, actwords[8]); | |
992 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, actwords[9]); | |
993 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, actwords[10]); | |
994 | KUNIT_EXPECT_EQ(test, (u32)0x00000000, actwords[11]); | |
995 | } | |
996 | ||
f037fc99 JR |
997 | static void vcap_free_ckf(struct vcap_rule *rule) |
998 | { | |
999 | struct vcap_client_keyfield *ckf, *next_ckf; | |
1000 | ||
1001 | list_for_each_entry_safe(ckf, next_ckf, &rule->keyfields, ctrl.list) { | |
1002 | list_del(&ckf->ctrl.list); | |
1003 | kfree(ckf); | |
1004 | } | |
1005 | } | |
1006 | ||
c956b9b3 SH |
1007 | static void vcap_api_rule_add_keyvalue_test(struct kunit *test) |
1008 | { | |
1009 | struct vcap_admin admin = { | |
1010 | .vtype = VCAP_TYPE_IS2, | |
1011 | }; | |
1012 | struct vcap_rule_internal ri = { | |
1013 | .admin = &admin, | |
1014 | .data = { | |
1015 | .keyset = VCAP_KFS_NO_VALUE, | |
1016 | }, | |
1017 | .vctrl = &test_vctrl, | |
1018 | }; | |
1019 | struct vcap_rule *rule = (struct vcap_rule *)&ri; | |
1020 | struct vcap_client_keyfield *kf; | |
1021 | int ret; | |
1022 | struct vcap_u128_key dip = { | |
1023 | .value = {0x17, 0x26, 0x35, 0x44, 0x63, 0x62, 0x71}, | |
1024 | .mask = {0xf1, 0xf2, 0xf3, 0xf4, 0x4f, 0x3f, 0x2f, 0x1f}, | |
1025 | }; | |
1026 | int idx; | |
1027 | ||
1028 | INIT_LIST_HEAD(&rule->keyfields); | |
1029 | ret = vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, VCAP_BIT_0); | |
1030 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1031 | ret = list_empty(&rule->keyfields); | |
1032 | KUNIT_EXPECT_EQ(test, false, ret); | |
1033 | kf = list_first_entry(&rule->keyfields, struct vcap_client_keyfield, | |
1034 | ctrl.list); | |
1035 | KUNIT_EXPECT_EQ(test, VCAP_KF_LOOKUP_FIRST_IS, kf->ctrl.key); | |
1036 | KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, kf->ctrl.type); | |
1037 | KUNIT_EXPECT_EQ(test, 0x0, kf->data.u1.value); | |
1038 | KUNIT_EXPECT_EQ(test, 0x1, kf->data.u1.mask); | |
f037fc99 | 1039 | vcap_free_ckf(rule); |
c956b9b3 SH |
1040 | |
1041 | INIT_LIST_HEAD(&rule->keyfields); | |
1042 | ret = vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, VCAP_BIT_1); | |
1043 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1044 | ret = list_empty(&rule->keyfields); | |
1045 | KUNIT_EXPECT_EQ(test, false, ret); | |
1046 | kf = list_first_entry(&rule->keyfields, struct vcap_client_keyfield, | |
1047 | ctrl.list); | |
1048 | KUNIT_EXPECT_EQ(test, VCAP_KF_LOOKUP_FIRST_IS, kf->ctrl.key); | |
1049 | KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, kf->ctrl.type); | |
1050 | KUNIT_EXPECT_EQ(test, 0x1, kf->data.u1.value); | |
1051 | KUNIT_EXPECT_EQ(test, 0x1, kf->data.u1.mask); | |
f037fc99 | 1052 | vcap_free_ckf(rule); |
c956b9b3 SH |
1053 | |
1054 | INIT_LIST_HEAD(&rule->keyfields); | |
1055 | ret = vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, | |
1056 | VCAP_BIT_ANY); | |
1057 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1058 | ret = list_empty(&rule->keyfields); | |
1059 | KUNIT_EXPECT_EQ(test, false, ret); | |
1060 | kf = list_first_entry(&rule->keyfields, struct vcap_client_keyfield, | |
1061 | ctrl.list); | |
1062 | KUNIT_EXPECT_EQ(test, VCAP_KF_LOOKUP_FIRST_IS, kf->ctrl.key); | |
1063 | KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, kf->ctrl.type); | |
1064 | KUNIT_EXPECT_EQ(test, 0x0, kf->data.u1.value); | |
1065 | KUNIT_EXPECT_EQ(test, 0x0, kf->data.u1.mask); | |
f037fc99 | 1066 | vcap_free_ckf(rule); |
c956b9b3 SH |
1067 | |
1068 | INIT_LIST_HEAD(&rule->keyfields); | |
1069 | ret = vcap_rule_add_key_u32(rule, VCAP_KF_TYPE, 0x98765432, 0xff00ffab); | |
1070 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1071 | ret = list_empty(&rule->keyfields); | |
1072 | KUNIT_EXPECT_EQ(test, false, ret); | |
1073 | kf = list_first_entry(&rule->keyfields, struct vcap_client_keyfield, | |
1074 | ctrl.list); | |
1075 | KUNIT_EXPECT_EQ(test, VCAP_KF_TYPE, kf->ctrl.key); | |
1076 | KUNIT_EXPECT_EQ(test, VCAP_FIELD_U32, kf->ctrl.type); | |
1077 | KUNIT_EXPECT_EQ(test, 0x98765432, kf->data.u32.value); | |
1078 | KUNIT_EXPECT_EQ(test, 0xff00ffab, kf->data.u32.mask); | |
f037fc99 | 1079 | vcap_free_ckf(rule); |
c956b9b3 SH |
1080 | |
1081 | INIT_LIST_HEAD(&rule->keyfields); | |
1082 | ret = vcap_rule_add_key_u128(rule, VCAP_KF_L3_IP6_SIP, &dip); | |
1083 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1084 | ret = list_empty(&rule->keyfields); | |
1085 | KUNIT_EXPECT_EQ(test, false, ret); | |
1086 | kf = list_first_entry(&rule->keyfields, struct vcap_client_keyfield, | |
1087 | ctrl.list); | |
1088 | KUNIT_EXPECT_EQ(test, VCAP_KF_L3_IP6_SIP, kf->ctrl.key); | |
1089 | KUNIT_EXPECT_EQ(test, VCAP_FIELD_U128, kf->ctrl.type); | |
1090 | for (idx = 0; idx < ARRAY_SIZE(dip.value); ++idx) | |
1091 | KUNIT_EXPECT_EQ(test, dip.value[idx], kf->data.u128.value[idx]); | |
1092 | for (idx = 0; idx < ARRAY_SIZE(dip.mask); ++idx) | |
1093 | KUNIT_EXPECT_EQ(test, dip.mask[idx], kf->data.u128.mask[idx]); | |
f037fc99 | 1094 | vcap_free_ckf(rule); |
c956b9b3 SH |
1095 | } |
1096 | ||
39d0ccc1 JR |
1097 | static void vcap_free_caf(struct vcap_rule *rule) |
1098 | { | |
1099 | struct vcap_client_actionfield *caf, *next_caf; | |
1100 | ||
1101 | list_for_each_entry_safe(caf, next_caf, | |
1102 | &rule->actionfields, ctrl.list) { | |
1103 | list_del(&caf->ctrl.list); | |
1104 | kfree(caf); | |
1105 | } | |
1106 | } | |
1107 | ||
c956b9b3 SH |
1108 | static void vcap_api_rule_add_actionvalue_test(struct kunit *test) |
1109 | { | |
1110 | struct vcap_admin admin = { | |
1111 | .vtype = VCAP_TYPE_IS2, | |
1112 | }; | |
1113 | struct vcap_rule_internal ri = { | |
1114 | .admin = &admin, | |
1115 | .data = { | |
1116 | .actionset = VCAP_AFS_NO_VALUE, | |
1117 | }, | |
1118 | }; | |
1119 | struct vcap_rule *rule = (struct vcap_rule *)&ri; | |
1120 | struct vcap_client_actionfield *af; | |
1121 | int ret; | |
1122 | ||
1123 | INIT_LIST_HEAD(&rule->actionfields); | |
1124 | ret = vcap_rule_add_action_bit(rule, VCAP_AF_POLICE_ENA, VCAP_BIT_0); | |
1125 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1126 | ret = list_empty(&rule->actionfields); | |
1127 | KUNIT_EXPECT_EQ(test, false, ret); | |
1128 | af = list_first_entry(&rule->actionfields, | |
1129 | struct vcap_client_actionfield, ctrl.list); | |
1130 | KUNIT_EXPECT_EQ(test, VCAP_AF_POLICE_ENA, af->ctrl.action); | |
1131 | KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, af->ctrl.type); | |
1132 | KUNIT_EXPECT_EQ(test, 0x0, af->data.u1.value); | |
39d0ccc1 | 1133 | vcap_free_caf(rule); |
c956b9b3 SH |
1134 | |
1135 | INIT_LIST_HEAD(&rule->actionfields); | |
1136 | ret = vcap_rule_add_action_bit(rule, VCAP_AF_POLICE_ENA, VCAP_BIT_1); | |
1137 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1138 | ret = list_empty(&rule->actionfields); | |
1139 | KUNIT_EXPECT_EQ(test, false, ret); | |
1140 | af = list_first_entry(&rule->actionfields, | |
1141 | struct vcap_client_actionfield, ctrl.list); | |
1142 | KUNIT_EXPECT_EQ(test, VCAP_AF_POLICE_ENA, af->ctrl.action); | |
1143 | KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, af->ctrl.type); | |
1144 | KUNIT_EXPECT_EQ(test, 0x1, af->data.u1.value); | |
39d0ccc1 | 1145 | vcap_free_caf(rule); |
c956b9b3 SH |
1146 | |
1147 | INIT_LIST_HEAD(&rule->actionfields); | |
1148 | ret = vcap_rule_add_action_bit(rule, VCAP_AF_POLICE_ENA, VCAP_BIT_ANY); | |
1149 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1150 | ret = list_empty(&rule->actionfields); | |
1151 | KUNIT_EXPECT_EQ(test, false, ret); | |
1152 | af = list_first_entry(&rule->actionfields, | |
1153 | struct vcap_client_actionfield, ctrl.list); | |
1154 | KUNIT_EXPECT_EQ(test, VCAP_AF_POLICE_ENA, af->ctrl.action); | |
1155 | KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, af->ctrl.type); | |
1156 | KUNIT_EXPECT_EQ(test, 0x0, af->data.u1.value); | |
39d0ccc1 | 1157 | vcap_free_caf(rule); |
c956b9b3 SH |
1158 | |
1159 | INIT_LIST_HEAD(&rule->actionfields); | |
1160 | ret = vcap_rule_add_action_u32(rule, VCAP_AF_TYPE, 0x98765432); | |
1161 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1162 | ret = list_empty(&rule->actionfields); | |
1163 | KUNIT_EXPECT_EQ(test, false, ret); | |
1164 | af = list_first_entry(&rule->actionfields, | |
1165 | struct vcap_client_actionfield, ctrl.list); | |
1166 | KUNIT_EXPECT_EQ(test, VCAP_AF_TYPE, af->ctrl.action); | |
1167 | KUNIT_EXPECT_EQ(test, VCAP_FIELD_U32, af->ctrl.type); | |
1168 | KUNIT_EXPECT_EQ(test, 0x98765432, af->data.u32.value); | |
39d0ccc1 | 1169 | vcap_free_caf(rule); |
c956b9b3 SH |
1170 | |
1171 | INIT_LIST_HEAD(&rule->actionfields); | |
1172 | ret = vcap_rule_add_action_u32(rule, VCAP_AF_MASK_MODE, 0xaabbccdd); | |
1173 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1174 | ret = list_empty(&rule->actionfields); | |
1175 | KUNIT_EXPECT_EQ(test, false, ret); | |
1176 | af = list_first_entry(&rule->actionfields, | |
1177 | struct vcap_client_actionfield, ctrl.list); | |
1178 | KUNIT_EXPECT_EQ(test, VCAP_AF_MASK_MODE, af->ctrl.action); | |
1179 | KUNIT_EXPECT_EQ(test, VCAP_FIELD_U32, af->ctrl.type); | |
1180 | KUNIT_EXPECT_EQ(test, 0xaabbccdd, af->data.u32.value); | |
39d0ccc1 | 1181 | vcap_free_caf(rule); |
c956b9b3 SH |
1182 | } |
1183 | ||
1184 | static void vcap_api_rule_find_keyset_basic_test(struct kunit *test) | |
1185 | { | |
1186 | struct vcap_keyset_list matches = {}; | |
1187 | struct vcap_admin admin = { | |
1188 | .vtype = VCAP_TYPE_IS2, | |
1189 | }; | |
1190 | struct vcap_rule_internal ri = { | |
1191 | .admin = &admin, | |
1192 | .vctrl = &test_vctrl, | |
1193 | }; | |
1194 | struct vcap_client_keyfield ckf[] = { | |
1195 | { | |
1196 | .ctrl.key = VCAP_KF_TYPE, | |
1197 | }, { | |
1198 | .ctrl.key = VCAP_KF_LOOKUP_FIRST_IS, | |
1199 | }, { | |
1200 | .ctrl.key = VCAP_KF_IF_IGR_PORT_MASK_L3, | |
1201 | }, { | |
1202 | .ctrl.key = VCAP_KF_IF_IGR_PORT_MASK_RNG, | |
1203 | }, { | |
1204 | .ctrl.key = VCAP_KF_IF_IGR_PORT_MASK, | |
1205 | }, { | |
1206 | .ctrl.key = VCAP_KF_L2_DMAC, | |
1207 | }, { | |
1208 | .ctrl.key = VCAP_KF_ETYPE_LEN_IS, | |
1209 | }, { | |
1210 | .ctrl.key = VCAP_KF_ETYPE, | |
1211 | }, | |
1212 | }; | |
1213 | int idx; | |
1214 | bool ret; | |
1215 | enum vcap_keyfield_set keysets[10] = {}; | |
1216 | ||
1217 | matches.keysets = keysets; | |
1218 | matches.max = ARRAY_SIZE(keysets); | |
1219 | ||
1220 | INIT_LIST_HEAD(&ri.data.keyfields); | |
1221 | for (idx = 0; idx < ARRAY_SIZE(ckf); idx++) | |
1222 | list_add_tail(&ckf[idx].ctrl.list, &ri.data.keyfields); | |
1223 | ||
465a38a2 | 1224 | ret = vcap_rule_find_keysets(&ri.data, &matches); |
c956b9b3 SH |
1225 | |
1226 | KUNIT_EXPECT_EQ(test, true, ret); | |
1227 | KUNIT_EXPECT_EQ(test, 1, matches.cnt); | |
1228 | KUNIT_EXPECT_EQ(test, VCAP_KFS_MAC_ETYPE, matches.keysets[0]); | |
1229 | } | |
1230 | ||
1231 | static void vcap_api_rule_find_keyset_failed_test(struct kunit *test) | |
1232 | { | |
1233 | struct vcap_keyset_list matches = {}; | |
1234 | struct vcap_admin admin = { | |
1235 | .vtype = VCAP_TYPE_IS2, | |
1236 | }; | |
1237 | struct vcap_rule_internal ri = { | |
1238 | .admin = &admin, | |
1239 | .vctrl = &test_vctrl, | |
1240 | }; | |
1241 | struct vcap_client_keyfield ckf[] = { | |
1242 | { | |
1243 | .ctrl.key = VCAP_KF_TYPE, | |
1244 | }, { | |
1245 | .ctrl.key = VCAP_KF_LOOKUP_FIRST_IS, | |
1246 | }, { | |
1247 | .ctrl.key = VCAP_KF_ARP_OPCODE, | |
1248 | }, { | |
1249 | .ctrl.key = VCAP_KF_L3_IP4_SIP, | |
1250 | }, { | |
1251 | .ctrl.key = VCAP_KF_L3_IP4_DIP, | |
1252 | }, { | |
1253 | .ctrl.key = VCAP_KF_8021Q_PCP_CLS, | |
1254 | }, { | |
1255 | .ctrl.key = VCAP_KF_ETYPE_LEN_IS, /* Not with ARP */ | |
1256 | }, { | |
1257 | .ctrl.key = VCAP_KF_ETYPE, /* Not with ARP */ | |
1258 | }, | |
1259 | }; | |
1260 | int idx; | |
1261 | bool ret; | |
1262 | enum vcap_keyfield_set keysets[10] = {}; | |
1263 | ||
1264 | matches.keysets = keysets; | |
1265 | matches.max = ARRAY_SIZE(keysets); | |
1266 | ||
1267 | INIT_LIST_HEAD(&ri.data.keyfields); | |
1268 | for (idx = 0; idx < ARRAY_SIZE(ckf); idx++) | |
1269 | list_add_tail(&ckf[idx].ctrl.list, &ri.data.keyfields); | |
1270 | ||
465a38a2 | 1271 | ret = vcap_rule_find_keysets(&ri.data, &matches); |
c956b9b3 SH |
1272 | |
1273 | KUNIT_EXPECT_EQ(test, false, ret); | |
1274 | KUNIT_EXPECT_EQ(test, 0, matches.cnt); | |
1275 | KUNIT_EXPECT_EQ(test, VCAP_KFS_NO_VALUE, matches.keysets[0]); | |
1276 | } | |
1277 | ||
1278 | static void vcap_api_rule_find_keyset_many_test(struct kunit *test) | |
1279 | { | |
1280 | struct vcap_keyset_list matches = {}; | |
1281 | struct vcap_admin admin = { | |
1282 | .vtype = VCAP_TYPE_IS2, | |
1283 | }; | |
1284 | struct vcap_rule_internal ri = { | |
1285 | .admin = &admin, | |
1286 | .vctrl = &test_vctrl, | |
1287 | }; | |
1288 | struct vcap_client_keyfield ckf[] = { | |
1289 | { | |
1290 | .ctrl.key = VCAP_KF_TYPE, | |
1291 | }, { | |
1292 | .ctrl.key = VCAP_KF_LOOKUP_FIRST_IS, | |
1293 | }, { | |
1294 | .ctrl.key = VCAP_KF_8021Q_DEI_CLS, | |
1295 | }, { | |
1296 | .ctrl.key = VCAP_KF_8021Q_PCP_CLS, | |
1297 | }, { | |
1298 | .ctrl.key = VCAP_KF_8021Q_VID_CLS, | |
1299 | }, { | |
1300 | .ctrl.key = VCAP_KF_ISDX_CLS, | |
1301 | }, { | |
1302 | .ctrl.key = VCAP_KF_L2_MC_IS, | |
1303 | }, { | |
1304 | .ctrl.key = VCAP_KF_L2_BC_IS, | |
1305 | }, | |
1306 | }; | |
1307 | int idx; | |
1308 | bool ret; | |
1309 | enum vcap_keyfield_set keysets[10] = {}; | |
1310 | ||
1311 | matches.keysets = keysets; | |
1312 | matches.max = ARRAY_SIZE(keysets); | |
1313 | ||
1314 | INIT_LIST_HEAD(&ri.data.keyfields); | |
1315 | for (idx = 0; idx < ARRAY_SIZE(ckf); idx++) | |
1316 | list_add_tail(&ckf[idx].ctrl.list, &ri.data.keyfields); | |
1317 | ||
465a38a2 | 1318 | ret = vcap_rule_find_keysets(&ri.data, &matches); |
c956b9b3 SH |
1319 | |
1320 | KUNIT_EXPECT_EQ(test, true, ret); | |
1321 | KUNIT_EXPECT_EQ(test, 6, matches.cnt); | |
1322 | KUNIT_EXPECT_EQ(test, VCAP_KFS_ARP, matches.keysets[0]); | |
1323 | KUNIT_EXPECT_EQ(test, VCAP_KFS_IP4_OTHER, matches.keysets[1]); | |
1324 | KUNIT_EXPECT_EQ(test, VCAP_KFS_IP4_TCP_UDP, matches.keysets[2]); | |
1325 | KUNIT_EXPECT_EQ(test, VCAP_KFS_IP6_STD, matches.keysets[3]); | |
1326 | KUNIT_EXPECT_EQ(test, VCAP_KFS_IP_7TUPLE, matches.keysets[4]); | |
1327 | KUNIT_EXPECT_EQ(test, VCAP_KFS_MAC_ETYPE, matches.keysets[5]); | |
1328 | } | |
1329 | ||
1330 | static void vcap_api_encode_rule_test(struct kunit *test) | |
1331 | { | |
1332 | /* Data used by VCAP Library callback */ | |
1333 | static u32 keydata[32] = {}; | |
1334 | static u32 mskdata[32] = {}; | |
1335 | static u32 actdata[32] = {}; | |
1336 | ||
1337 | struct vcap_admin is2_admin = { | |
1338 | .vtype = VCAP_TYPE_IS2, | |
18a15c76 SH |
1339 | .first_cid = 8000000, |
1340 | .last_cid = 8099999, | |
c956b9b3 SH |
1341 | .lookups = 4, |
1342 | .last_valid_addr = 3071, | |
1343 | .first_valid_addr = 0, | |
1344 | .last_used_addr = 800, | |
1345 | .cache = { | |
1346 | .keystream = keydata, | |
1347 | .maskstream = mskdata, | |
1348 | .actionstream = actdata, | |
1349 | }, | |
1350 | }; | |
aa5ac4be HV |
1351 | struct vcap_rule *rule; |
1352 | struct vcap_rule_internal *ri; | |
18a15c76 | 1353 | int vcap_chain_id = 8000000; |
c956b9b3 SH |
1354 | enum vcap_user user = VCAP_USER_VCAP_UTIL; |
1355 | u16 priority = 10; | |
1356 | int id = 100; | |
1357 | int ret; | |
1358 | struct vcap_u48_key smac = { | |
1359 | .value = { 0x88, 0x75, 0x32, 0x34, 0x9e, 0xb1 }, | |
1360 | .mask = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } | |
1361 | }; | |
1362 | struct vcap_u48_key dmac = { | |
1363 | .value = { 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }, | |
1364 | .mask = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } | |
1365 | }; | |
1366 | u32 port_mask_rng_value = 0x05; | |
1367 | u32 port_mask_rng_mask = 0x0f; | |
1368 | u32 igr_port_mask_value = 0xffabcd01; | |
1369 | u32 igr_port_mask_mask = ~0; | |
d7953da4 SH |
1370 | /* counter is written as the first operation */ |
1371 | u32 expwriteaddr[] = {792, 792, 793, 794, 795, 796, 797}; | |
c956b9b3 SH |
1372 | int idx; |
1373 | ||
1374 | vcap_test_api_init(&is2_admin); | |
1375 | ||
1376 | /* Allocate the rule */ | |
1377 | rule = vcap_alloc_rule(&test_vctrl, &test_netdev, vcap_chain_id, user, | |
1378 | priority, id); | |
1379 | KUNIT_EXPECT_PTR_NE(test, NULL, rule); | |
1380 | ri = (struct vcap_rule_internal *)rule; | |
1381 | ||
1382 | /* Add rule keys */ | |
1383 | ret = vcap_rule_add_key_u48(rule, VCAP_KF_L2_DMAC, &dmac); | |
1384 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1385 | ret = vcap_rule_add_key_u48(rule, VCAP_KF_L2_SMAC, &smac); | |
1386 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1387 | ret = vcap_rule_add_key_bit(rule, VCAP_KF_ETYPE_LEN_IS, VCAP_BIT_1); | |
1388 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1389 | /* Cannot add the same field twice */ | |
1390 | ret = vcap_rule_add_key_bit(rule, VCAP_KF_ETYPE_LEN_IS, VCAP_BIT_1); | |
1391 | KUNIT_EXPECT_EQ(test, -EINVAL, ret); | |
1392 | ret = vcap_rule_add_key_bit(rule, VCAP_KF_IF_IGR_PORT_MASK_L3, | |
1393 | VCAP_BIT_ANY); | |
1394 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1395 | ret = vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK_RNG, | |
1396 | port_mask_rng_value, port_mask_rng_mask); | |
1397 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1398 | ret = vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, | |
1399 | igr_port_mask_value, igr_port_mask_mask); | |
1400 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1401 | ||
1402 | /* Add rule actions */ | |
1403 | ret = vcap_rule_add_action_bit(rule, VCAP_AF_POLICE_ENA, VCAP_BIT_1); | |
1404 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1405 | ret = vcap_rule_add_action_u32(rule, VCAP_AF_CNT_ID, id); | |
1406 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1407 | ret = vcap_rule_add_action_u32(rule, VCAP_AF_MATCH_ID, 1); | |
1408 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1409 | ret = vcap_rule_add_action_u32(rule, VCAP_AF_MATCH_ID_MASK, 1); | |
1410 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1411 | ||
1412 | /* For now the actionset is hardcoded */ | |
1413 | ret = vcap_set_rule_set_actionset(rule, VCAP_AFS_BASE_TYPE); | |
1414 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1415 | ||
1416 | /* Validation with validate keyset callback */ | |
1417 | ret = vcap_val_rule(rule, ETH_P_ALL); | |
1418 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1419 | KUNIT_EXPECT_EQ(test, VCAP_KFS_MAC_ETYPE, rule->keyset); | |
1420 | KUNIT_EXPECT_EQ(test, VCAP_AFS_BASE_TYPE, rule->actionset); | |
1421 | KUNIT_EXPECT_EQ(test, 6, ri->size); | |
1422 | KUNIT_EXPECT_EQ(test, 2, ri->keyset_sw_regs); | |
1423 | KUNIT_EXPECT_EQ(test, 4, ri->actionset_sw_regs); | |
1424 | ||
18a15c76 SH |
1425 | /* Enable lookup, so the rule will be written */ |
1426 | ret = vcap_enable_lookups(&test_vctrl, &test_netdev, 0, | |
1427 | rule->vcap_chain_id, rule->cookie, true); | |
1428 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1429 | ||
c956b9b3 SH |
1430 | /* Add rule with write callback */ |
1431 | ret = vcap_add_rule(rule); | |
1432 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1433 | KUNIT_EXPECT_EQ(test, 792, is2_admin.last_used_addr); | |
1434 | for (idx = 0; idx < ARRAY_SIZE(expwriteaddr); ++idx) | |
1435 | KUNIT_EXPECT_EQ(test, expwriteaddr[idx], test_updateaddr[idx]); | |
1436 | ||
1437 | /* Check that the rule has been added */ | |
1438 | ret = list_empty(&is2_admin.rules); | |
1439 | KUNIT_EXPECT_EQ(test, false, ret); | |
1440 | KUNIT_EXPECT_EQ(test, 0, ret); | |
89e3af02 JR |
1441 | |
1442 | vcap_enable_lookups(&test_vctrl, &test_netdev, 0, 0, | |
1443 | rule->cookie, false); | |
1444 | ||
a3c1e451 JESØ |
1445 | ret = vcap_del_rule(&test_vctrl, &test_netdev, id); |
1446 | KUNIT_EXPECT_EQ(test, 0, ret); | |
c956b9b3 SH |
1447 | } |
1448 | ||
dccc30cc SH |
1449 | static void vcap_api_set_rule_counter_test(struct kunit *test) |
1450 | { | |
1451 | struct vcap_admin is2_admin = { | |
1452 | .cache = { | |
1453 | .counter = 100, | |
1454 | .sticky = true, | |
1455 | }, | |
1456 | }; | |
1457 | struct vcap_rule_internal ri = { | |
1458 | .data = { | |
1459 | .id = 1001, | |
1460 | }, | |
1461 | .addr = 600, | |
1462 | .admin = &is2_admin, | |
1463 | .counter_id = 1002, | |
1464 | .vctrl = &test_vctrl, | |
1465 | }; | |
1466 | struct vcap_rule_internal ri2 = { | |
1467 | .data = { | |
1468 | .id = 2001, | |
1469 | }, | |
1470 | .addr = 700, | |
1471 | .admin = &is2_admin, | |
1472 | .counter_id = 2002, | |
1473 | .vctrl = &test_vctrl, | |
1474 | }; | |
1475 | struct vcap_counter ctr = { .value = 0, .sticky = false}; | |
1476 | struct vcap_counter ctr2 = { .value = 101, .sticky = true}; | |
1477 | int ret; | |
1478 | ||
1479 | vcap_test_api_init(&is2_admin); | |
1480 | list_add_tail(&ri.list, &is2_admin.rules); | |
1481 | list_add_tail(&ri2.list, &is2_admin.rules); | |
1482 | ||
1483 | pr_info("%s:%d\n", __func__, __LINE__); | |
1484 | ret = vcap_rule_set_counter(&ri.data, &ctr); | |
1485 | pr_info("%s:%d\n", __func__, __LINE__); | |
1486 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1487 | ||
1488 | KUNIT_EXPECT_EQ(test, 1002, test_hw_counter_id); | |
1489 | KUNIT_EXPECT_EQ(test, 0, test_hw_cache.counter); | |
1490 | KUNIT_EXPECT_EQ(test, false, test_hw_cache.sticky); | |
1491 | KUNIT_EXPECT_EQ(test, 600, test_updateaddr[0]); | |
1492 | ||
1493 | ret = vcap_rule_set_counter(&ri2.data, &ctr2); | |
1494 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1495 | ||
1496 | KUNIT_EXPECT_EQ(test, 2002, test_hw_counter_id); | |
1497 | KUNIT_EXPECT_EQ(test, 101, test_hw_cache.counter); | |
1498 | KUNIT_EXPECT_EQ(test, true, test_hw_cache.sticky); | |
1499 | KUNIT_EXPECT_EQ(test, 700, test_updateaddr[1]); | |
1500 | } | |
1501 | ||
1502 | static void vcap_api_get_rule_counter_test(struct kunit *test) | |
1503 | { | |
1504 | struct vcap_admin is2_admin = { | |
1505 | .cache = { | |
1506 | .counter = 100, | |
1507 | .sticky = true, | |
1508 | }, | |
1509 | }; | |
1510 | struct vcap_rule_internal ri = { | |
1511 | .data = { | |
1512 | .id = 1010, | |
1513 | }, | |
1514 | .addr = 400, | |
1515 | .admin = &is2_admin, | |
1516 | .counter_id = 1011, | |
1517 | .vctrl = &test_vctrl, | |
1518 | }; | |
1519 | struct vcap_rule_internal ri2 = { | |
1520 | .data = { | |
1521 | .id = 2011, | |
1522 | }, | |
1523 | .addr = 300, | |
1524 | .admin = &is2_admin, | |
1525 | .counter_id = 2012, | |
1526 | .vctrl = &test_vctrl, | |
1527 | }; | |
1528 | struct vcap_counter ctr = {}; | |
1529 | struct vcap_counter ctr2 = {}; | |
1530 | int ret; | |
1531 | ||
1532 | vcap_test_api_init(&is2_admin); | |
1533 | test_hw_cache.counter = 55; | |
1534 | test_hw_cache.sticky = true; | |
1535 | ||
1536 | list_add_tail(&ri.list, &is2_admin.rules); | |
1537 | list_add_tail(&ri2.list, &is2_admin.rules); | |
1538 | ||
1539 | ret = vcap_rule_get_counter(&ri.data, &ctr); | |
1540 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1541 | ||
1542 | KUNIT_EXPECT_EQ(test, 1011, test_hw_counter_id); | |
1543 | KUNIT_EXPECT_EQ(test, 55, ctr.value); | |
1544 | KUNIT_EXPECT_EQ(test, true, ctr.sticky); | |
1545 | KUNIT_EXPECT_EQ(test, 400, test_updateaddr[0]); | |
1546 | ||
1547 | test_hw_cache.counter = 22; | |
1548 | test_hw_cache.sticky = false; | |
1549 | ||
1550 | ret = vcap_rule_get_counter(&ri2.data, &ctr2); | |
1551 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1552 | ||
1553 | KUNIT_EXPECT_EQ(test, 2012, test_hw_counter_id); | |
1554 | KUNIT_EXPECT_EQ(test, 22, ctr2.value); | |
1555 | KUNIT_EXPECT_EQ(test, false, ctr2.sticky); | |
1556 | KUNIT_EXPECT_EQ(test, 300, test_updateaddr[1]); | |
1557 | } | |
1558 | ||
1559 | static void vcap_api_rule_insert_in_order_test(struct kunit *test) | |
1560 | { | |
1561 | /* Data used by VCAP Library callback */ | |
1562 | static u32 keydata[32] = {}; | |
1563 | static u32 mskdata[32] = {}; | |
1564 | static u32 actdata[32] = {}; | |
1565 | ||
1566 | struct vcap_admin admin = { | |
1567 | .vtype = VCAP_TYPE_IS0, | |
1568 | .first_cid = 10000, | |
1569 | .last_cid = 19999, | |
1570 | .lookups = 4, | |
1571 | .last_valid_addr = 3071, | |
1572 | .first_valid_addr = 0, | |
1573 | .last_used_addr = 800, | |
1574 | .cache = { | |
1575 | .keystream = keydata, | |
1576 | .maskstream = mskdata, | |
1577 | .actionstream = actdata, | |
1578 | }, | |
1579 | }; | |
1580 | ||
1581 | vcap_test_api_init(&admin); | |
1582 | ||
1583 | /* Create rules with different sizes and check that they are placed | |
1584 | * at the correct address in the VCAP according to size | |
1585 | */ | |
1586 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 10, 500, 12, 780); | |
1587 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 20, 400, 6, 774); | |
1588 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 30, 300, 3, 771); | |
1589 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 40, 200, 2, 768); | |
2a2dffd9 JR |
1590 | |
1591 | vcap_del_rule(&test_vctrl, &test_netdev, 200); | |
1592 | vcap_del_rule(&test_vctrl, &test_netdev, 300); | |
1593 | vcap_del_rule(&test_vctrl, &test_netdev, 400); | |
1594 | vcap_del_rule(&test_vctrl, &test_netdev, 500); | |
dccc30cc SH |
1595 | } |
1596 | ||
1597 | static void vcap_api_rule_insert_reverse_order_test(struct kunit *test) | |
1598 | { | |
1599 | /* Data used by VCAP Library callback */ | |
1600 | static u32 keydata[32] = {}; | |
1601 | static u32 mskdata[32] = {}; | |
1602 | static u32 actdata[32] = {}; | |
1603 | ||
1604 | struct vcap_admin admin = { | |
1605 | .vtype = VCAP_TYPE_IS0, | |
1606 | .first_cid = 10000, | |
1607 | .last_cid = 19999, | |
1608 | .lookups = 4, | |
1609 | .last_valid_addr = 3071, | |
1610 | .first_valid_addr = 0, | |
1611 | .last_used_addr = 800, | |
1612 | .cache = { | |
1613 | .keystream = keydata, | |
1614 | .maskstream = mskdata, | |
1615 | .actionstream = actdata, | |
1616 | }, | |
1617 | }; | |
1618 | struct vcap_rule_internal *elem; | |
1619 | u32 exp_addr[] = {780, 774, 771, 768, 767}; | |
1620 | int idx; | |
1621 | ||
1622 | vcap_test_api_init(&admin); | |
1623 | ||
1624 | /* Create rules with different sizes and check that they are placed | |
1625 | * at the correct address in the VCAP according to size | |
1626 | */ | |
1627 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 20, 200, 2, 798); | |
1628 | KUNIT_EXPECT_EQ(test, 0, test_move_offset); | |
1629 | KUNIT_EXPECT_EQ(test, 0, test_move_count); | |
1630 | KUNIT_EXPECT_EQ(test, 0, test_move_addr); | |
1631 | ||
1632 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 30, 300, 3, 795); | |
1633 | KUNIT_EXPECT_EQ(test, 6, test_move_offset); | |
1634 | KUNIT_EXPECT_EQ(test, 3, test_move_count); | |
1635 | KUNIT_EXPECT_EQ(test, 798, test_move_addr); | |
1636 | ||
1637 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 40, 400, 6, 792); | |
1638 | KUNIT_EXPECT_EQ(test, 6, test_move_offset); | |
1639 | KUNIT_EXPECT_EQ(test, 6, test_move_count); | |
1640 | KUNIT_EXPECT_EQ(test, 792, test_move_addr); | |
1641 | ||
1642 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 50, 500, 12, 780); | |
1643 | KUNIT_EXPECT_EQ(test, 18, test_move_offset); | |
1644 | KUNIT_EXPECT_EQ(test, 12, test_move_count); | |
1645 | KUNIT_EXPECT_EQ(test, 786, test_move_addr); | |
1646 | ||
1647 | idx = 0; | |
1648 | list_for_each_entry(elem, &admin.rules, list) { | |
1649 | KUNIT_EXPECT_EQ(test, exp_addr[idx], elem->addr); | |
1650 | ++idx; | |
1651 | } | |
1652 | KUNIT_EXPECT_EQ(test, 768, admin.last_used_addr); | |
2a2dffd9 JR |
1653 | |
1654 | vcap_del_rule(&test_vctrl, &test_netdev, 500); | |
1655 | vcap_del_rule(&test_vctrl, &test_netdev, 400); | |
1656 | vcap_del_rule(&test_vctrl, &test_netdev, 300); | |
1657 | vcap_del_rule(&test_vctrl, &test_netdev, 200); | |
dccc30cc SH |
1658 | } |
1659 | ||
1660 | static void vcap_api_rule_remove_at_end_test(struct kunit *test) | |
1661 | { | |
1662 | /* Data used by VCAP Library callback */ | |
1663 | static u32 keydata[32] = {}; | |
1664 | static u32 mskdata[32] = {}; | |
1665 | static u32 actdata[32] = {}; | |
1666 | ||
1667 | struct vcap_admin admin = { | |
1668 | .vtype = VCAP_TYPE_IS0, | |
1669 | .first_cid = 10000, | |
1670 | .last_cid = 19999, | |
1671 | .lookups = 4, | |
1672 | .last_valid_addr = 3071, | |
1673 | .first_valid_addr = 0, | |
1674 | .last_used_addr = 800, | |
1675 | .cache = { | |
1676 | .keystream = keydata, | |
1677 | .maskstream = mskdata, | |
1678 | .actionstream = actdata, | |
1679 | }, | |
1680 | }; | |
1681 | int ret; | |
1682 | ||
1683 | vcap_test_api_init(&admin); | |
1684 | test_init_rule_deletion(); | |
1685 | ||
1686 | /* Create rules with different sizes and check that they are placed | |
1687 | * at the correct address in the VCAP according to size | |
1688 | */ | |
1689 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 10, 500, 12, 780); | |
1690 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 20, 400, 6, 774); | |
1691 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 30, 300, 3, 771); | |
1692 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 40, 200, 2, 768); | |
1693 | ||
1694 | /* Remove rules again from the end */ | |
1695 | ret = vcap_del_rule(&test_vctrl, &test_netdev, 200); | |
1696 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1697 | KUNIT_EXPECT_EQ(test, 0, test_move_addr); | |
1698 | KUNIT_EXPECT_EQ(test, 0, test_move_offset); | |
1699 | KUNIT_EXPECT_EQ(test, 0, test_move_count); | |
1700 | KUNIT_EXPECT_EQ(test, 768, test_init_start); | |
1701 | KUNIT_EXPECT_EQ(test, 2, test_init_count); | |
1702 | KUNIT_EXPECT_EQ(test, 771, admin.last_used_addr); | |
1703 | ||
1704 | ret = vcap_del_rule(&test_vctrl, &test_netdev, 300); | |
1705 | KUNIT_EXPECT_EQ(test, ret, 0); | |
1706 | KUNIT_EXPECT_EQ(test, 0, test_move_addr); | |
1707 | KUNIT_EXPECT_EQ(test, 0, test_move_offset); | |
1708 | KUNIT_EXPECT_EQ(test, 0, test_move_count); | |
1709 | KUNIT_EXPECT_EQ(test, 771, test_init_start); | |
1710 | KUNIT_EXPECT_EQ(test, 3, test_init_count); | |
1711 | KUNIT_EXPECT_EQ(test, 774, admin.last_used_addr); | |
1712 | ||
1713 | ret = vcap_del_rule(&test_vctrl, &test_netdev, 400); | |
1714 | KUNIT_EXPECT_EQ(test, ret, 0); | |
1715 | KUNIT_EXPECT_EQ(test, 0, test_move_addr); | |
1716 | KUNIT_EXPECT_EQ(test, 0, test_move_offset); | |
1717 | KUNIT_EXPECT_EQ(test, 0, test_move_count); | |
1718 | KUNIT_EXPECT_EQ(test, 774, test_init_start); | |
1719 | KUNIT_EXPECT_EQ(test, 6, test_init_count); | |
1720 | KUNIT_EXPECT_EQ(test, 780, admin.last_used_addr); | |
1721 | ||
1722 | ret = vcap_del_rule(&test_vctrl, &test_netdev, 500); | |
1723 | KUNIT_EXPECT_EQ(test, ret, 0); | |
1724 | KUNIT_EXPECT_EQ(test, 0, test_move_addr); | |
1725 | KUNIT_EXPECT_EQ(test, 0, test_move_offset); | |
1726 | KUNIT_EXPECT_EQ(test, 0, test_move_count); | |
1727 | KUNIT_EXPECT_EQ(test, 780, test_init_start); | |
1728 | KUNIT_EXPECT_EQ(test, 12, test_init_count); | |
552b7d13 | 1729 | KUNIT_EXPECT_EQ(test, 3072, admin.last_used_addr); |
dccc30cc SH |
1730 | } |
1731 | ||
1732 | static void vcap_api_rule_remove_in_middle_test(struct kunit *test) | |
1733 | { | |
1734 | /* Data used by VCAP Library callback */ | |
1735 | static u32 keydata[32] = {}; | |
1736 | static u32 mskdata[32] = {}; | |
1737 | static u32 actdata[32] = {}; | |
1738 | ||
1739 | struct vcap_admin admin = { | |
1740 | .vtype = VCAP_TYPE_IS0, | |
1741 | .first_cid = 10000, | |
1742 | .last_cid = 19999, | |
1743 | .lookups = 4, | |
1744 | .first_valid_addr = 0, | |
1745 | .last_used_addr = 800, | |
1746 | .last_valid_addr = 800 - 1, | |
1747 | .cache = { | |
1748 | .keystream = keydata, | |
1749 | .maskstream = mskdata, | |
1750 | .actionstream = actdata, | |
1751 | }, | |
1752 | }; | |
1753 | int ret; | |
1754 | ||
1755 | vcap_test_api_init(&admin); | |
1756 | ||
1757 | /* Create rules with different sizes and check that they are placed | |
1758 | * at the correct address in the VCAP according to size | |
1759 | */ | |
1760 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 10, 500, 12, 780); | |
1761 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 20, 400, 6, 774); | |
1762 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 30, 300, 3, 771); | |
1763 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 40, 200, 2, 768); | |
1764 | ||
1765 | /* Remove rules in the middle */ | |
1766 | test_init_rule_deletion(); | |
1767 | ret = vcap_del_rule(&test_vctrl, &test_netdev, 400); | |
1768 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1769 | KUNIT_EXPECT_EQ(test, 768, test_move_addr); | |
1770 | KUNIT_EXPECT_EQ(test, -6, test_move_offset); | |
1771 | KUNIT_EXPECT_EQ(test, 6, test_move_count); | |
1772 | KUNIT_EXPECT_EQ(test, 768, test_init_start); | |
1773 | KUNIT_EXPECT_EQ(test, 6, test_init_count); | |
1774 | KUNIT_EXPECT_EQ(test, 774, admin.last_used_addr); | |
1775 | ||
1776 | test_init_rule_deletion(); | |
1777 | ret = vcap_del_rule(&test_vctrl, &test_netdev, 300); | |
1778 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1779 | KUNIT_EXPECT_EQ(test, 774, test_move_addr); | |
1780 | KUNIT_EXPECT_EQ(test, -4, test_move_offset); | |
1781 | KUNIT_EXPECT_EQ(test, 2, test_move_count); | |
1782 | KUNIT_EXPECT_EQ(test, 774, test_init_start); | |
1783 | KUNIT_EXPECT_EQ(test, 4, test_init_count); | |
1784 | KUNIT_EXPECT_EQ(test, 778, admin.last_used_addr); | |
1785 | ||
1786 | test_init_rule_deletion(); | |
1787 | ret = vcap_del_rule(&test_vctrl, &test_netdev, 500); | |
1788 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1789 | KUNIT_EXPECT_EQ(test, 778, test_move_addr); | |
1790 | KUNIT_EXPECT_EQ(test, -20, test_move_offset); | |
1791 | KUNIT_EXPECT_EQ(test, 2, test_move_count); | |
1792 | KUNIT_EXPECT_EQ(test, 778, test_init_start); | |
1793 | KUNIT_EXPECT_EQ(test, 20, test_init_count); | |
1794 | KUNIT_EXPECT_EQ(test, 798, admin.last_used_addr); | |
1795 | ||
1796 | test_init_rule_deletion(); | |
1797 | ret = vcap_del_rule(&test_vctrl, &test_netdev, 200); | |
1798 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1799 | KUNIT_EXPECT_EQ(test, 0, test_move_addr); | |
1800 | KUNIT_EXPECT_EQ(test, 0, test_move_offset); | |
1801 | KUNIT_EXPECT_EQ(test, 0, test_move_count); | |
1802 | KUNIT_EXPECT_EQ(test, 798, test_init_start); | |
1803 | KUNIT_EXPECT_EQ(test, 2, test_init_count); | |
552b7d13 | 1804 | KUNIT_EXPECT_EQ(test, 800, admin.last_used_addr); |
dccc30cc SH |
1805 | } |
1806 | ||
1807 | static void vcap_api_rule_remove_in_front_test(struct kunit *test) | |
1808 | { | |
1809 | /* Data used by VCAP Library callback */ | |
1810 | static u32 keydata[32] = {}; | |
1811 | static u32 mskdata[32] = {}; | |
1812 | static u32 actdata[32] = {}; | |
1813 | ||
1814 | struct vcap_admin admin = { | |
1815 | .vtype = VCAP_TYPE_IS0, | |
1816 | .first_cid = 10000, | |
1817 | .last_cid = 19999, | |
1818 | .lookups = 4, | |
1819 | .first_valid_addr = 0, | |
1820 | .last_used_addr = 800, | |
1821 | .last_valid_addr = 800 - 1, | |
1822 | .cache = { | |
1823 | .keystream = keydata, | |
1824 | .maskstream = mskdata, | |
1825 | .actionstream = actdata, | |
1826 | }, | |
1827 | }; | |
1828 | int ret; | |
1829 | ||
1830 | vcap_test_api_init(&admin); | |
1831 | ||
1832 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 10, 500, 12, 780); | |
1833 | KUNIT_EXPECT_EQ(test, 780, admin.last_used_addr); | |
1834 | ||
1835 | test_init_rule_deletion(); | |
1836 | ret = vcap_del_rule(&test_vctrl, &test_netdev, 500); | |
1837 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1838 | KUNIT_EXPECT_EQ(test, 0, test_move_addr); | |
1839 | KUNIT_EXPECT_EQ(test, 0, test_move_offset); | |
1840 | KUNIT_EXPECT_EQ(test, 0, test_move_count); | |
1841 | KUNIT_EXPECT_EQ(test, 780, test_init_start); | |
1842 | KUNIT_EXPECT_EQ(test, 12, test_init_count); | |
552b7d13 | 1843 | KUNIT_EXPECT_EQ(test, 800, admin.last_used_addr); |
dccc30cc SH |
1844 | |
1845 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 20, 400, 6, 792); | |
1846 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 30, 300, 3, 789); | |
1847 | test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 40, 200, 2, 786); | |
1848 | ||
1849 | test_init_rule_deletion(); | |
1850 | ret = vcap_del_rule(&test_vctrl, &test_netdev, 400); | |
1851 | KUNIT_EXPECT_EQ(test, 0, ret); | |
1852 | KUNIT_EXPECT_EQ(test, 786, test_move_addr); | |
1853 | KUNIT_EXPECT_EQ(test, -8, test_move_offset); | |
1854 | KUNIT_EXPECT_EQ(test, 6, test_move_count); | |
1855 | KUNIT_EXPECT_EQ(test, 786, test_init_start); | |
1856 | KUNIT_EXPECT_EQ(test, 8, test_init_count); | |
1857 | KUNIT_EXPECT_EQ(test, 794, admin.last_used_addr); | |
2a2dffd9 JR |
1858 | |
1859 | vcap_del_rule(&test_vctrl, &test_netdev, 200); | |
1860 | vcap_del_rule(&test_vctrl, &test_netdev, 300); | |
dccc30cc SH |
1861 | } |
1862 | ||
1863 | static struct kunit_case vcap_api_rule_remove_test_cases[] = { | |
1864 | KUNIT_CASE(vcap_api_rule_remove_at_end_test), | |
1865 | KUNIT_CASE(vcap_api_rule_remove_in_middle_test), | |
1866 | KUNIT_CASE(vcap_api_rule_remove_in_front_test), | |
1867 | {} | |
1868 | }; | |
1869 | ||
c956b9b3 SH |
1870 | static void vcap_api_next_lookup_basic_test(struct kunit *test) |
1871 | { | |
1872 | struct vcap_admin admin1 = { | |
1873 | .vtype = VCAP_TYPE_IS2, | |
1874 | .vinst = 0, | |
1875 | .first_cid = 8000000, | |
1876 | .last_cid = 8199999, | |
1877 | .lookups = 4, | |
1878 | .lookups_per_instance = 2, | |
1879 | }; | |
1880 | struct vcap_admin admin2 = { | |
1881 | .vtype = VCAP_TYPE_IS2, | |
1882 | .vinst = 1, | |
1883 | .first_cid = 8200000, | |
1884 | .last_cid = 8399999, | |
1885 | .lookups = 4, | |
1886 | .lookups_per_instance = 2, | |
1887 | }; | |
1888 | bool ret; | |
1889 | ||
1890 | vcap_test_api_init(&admin1); | |
1891 | list_add_tail(&admin2.list, &test_vctrl.list); | |
1892 | ||
1893 | ret = vcap_is_next_lookup(&test_vctrl, 8000000, 1001000); | |
1894 | KUNIT_EXPECT_EQ(test, false, ret); | |
1895 | ret = vcap_is_next_lookup(&test_vctrl, 8000000, 8001000); | |
1896 | KUNIT_EXPECT_EQ(test, false, ret); | |
1897 | ret = vcap_is_next_lookup(&test_vctrl, 8000000, 8101000); | |
1898 | KUNIT_EXPECT_EQ(test, true, ret); | |
1899 | ||
1900 | ret = vcap_is_next_lookup(&test_vctrl, 8100000, 8101000); | |
1901 | KUNIT_EXPECT_EQ(test, false, ret); | |
1902 | ret = vcap_is_next_lookup(&test_vctrl, 8100000, 8201000); | |
1903 | KUNIT_EXPECT_EQ(test, true, ret); | |
1904 | ||
1905 | ret = vcap_is_next_lookup(&test_vctrl, 8200000, 8201000); | |
1906 | KUNIT_EXPECT_EQ(test, false, ret); | |
1907 | ret = vcap_is_next_lookup(&test_vctrl, 8200000, 8301000); | |
1908 | KUNIT_EXPECT_EQ(test, true, ret); | |
1909 | ||
1910 | ret = vcap_is_next_lookup(&test_vctrl, 8300000, 8301000); | |
1911 | KUNIT_EXPECT_EQ(test, false, ret); | |
1912 | ret = vcap_is_next_lookup(&test_vctrl, 8300000, 8401000); | |
784c3067 | 1913 | KUNIT_EXPECT_EQ(test, false, ret); |
c956b9b3 SH |
1914 | } |
1915 | ||
1916 | static void vcap_api_next_lookup_advanced_test(struct kunit *test) | |
1917 | { | |
129ff4de AB |
1918 | struct vcap_admin admin[] = { |
1919 | { | |
c956b9b3 SH |
1920 | .vtype = VCAP_TYPE_IS0, |
1921 | .vinst = 0, | |
1922 | .first_cid = 1000000, | |
1923 | .last_cid = 1199999, | |
1924 | .lookups = 6, | |
1925 | .lookups_per_instance = 2, | |
129ff4de | 1926 | }, { |
c956b9b3 SH |
1927 | .vtype = VCAP_TYPE_IS0, |
1928 | .vinst = 1, | |
1929 | .first_cid = 1200000, | |
1930 | .last_cid = 1399999, | |
1931 | .lookups = 6, | |
1932 | .lookups_per_instance = 2, | |
129ff4de | 1933 | }, { |
c956b9b3 SH |
1934 | .vtype = VCAP_TYPE_IS0, |
1935 | .vinst = 2, | |
1936 | .first_cid = 1400000, | |
1937 | .last_cid = 1599999, | |
1938 | .lookups = 6, | |
1939 | .lookups_per_instance = 2, | |
129ff4de | 1940 | }, { |
c956b9b3 SH |
1941 | .vtype = VCAP_TYPE_IS2, |
1942 | .vinst = 0, | |
1943 | .first_cid = 8000000, | |
1944 | .last_cid = 8199999, | |
1945 | .lookups = 4, | |
1946 | .lookups_per_instance = 2, | |
129ff4de | 1947 | }, { |
c956b9b3 SH |
1948 | .vtype = VCAP_TYPE_IS2, |
1949 | .vinst = 1, | |
1950 | .first_cid = 8200000, | |
1951 | .last_cid = 8399999, | |
1952 | .lookups = 4, | |
1953 | .lookups_per_instance = 2, | |
129ff4de | 1954 | } |
c956b9b3 SH |
1955 | }; |
1956 | bool ret; | |
1957 | ||
129ff4de AB |
1958 | vcap_test_api_init(&admin[0]); |
1959 | list_add_tail(&admin[1].list, &test_vctrl.list); | |
1960 | list_add_tail(&admin[2].list, &test_vctrl.list); | |
1961 | list_add_tail(&admin[3].list, &test_vctrl.list); | |
1962 | list_add_tail(&admin[4].list, &test_vctrl.list); | |
c956b9b3 SH |
1963 | |
1964 | ret = vcap_is_next_lookup(&test_vctrl, 1000000, 1001000); | |
1965 | KUNIT_EXPECT_EQ(test, false, ret); | |
1966 | ret = vcap_is_next_lookup(&test_vctrl, 1000000, 1101000); | |
1967 | KUNIT_EXPECT_EQ(test, true, ret); | |
1968 | ||
1969 | ret = vcap_is_next_lookup(&test_vctrl, 1100000, 1201000); | |
1970 | KUNIT_EXPECT_EQ(test, true, ret); | |
1971 | ret = vcap_is_next_lookup(&test_vctrl, 1100000, 1301000); | |
784c3067 | 1972 | KUNIT_EXPECT_EQ(test, true, ret); |
c956b9b3 | 1973 | ret = vcap_is_next_lookup(&test_vctrl, 1100000, 8101000); |
784c3067 | 1974 | KUNIT_EXPECT_EQ(test, true, ret); |
c956b9b3 SH |
1975 | ret = vcap_is_next_lookup(&test_vctrl, 1300000, 1401000); |
1976 | KUNIT_EXPECT_EQ(test, true, ret); | |
1977 | ret = vcap_is_next_lookup(&test_vctrl, 1400000, 1501000); | |
1978 | KUNIT_EXPECT_EQ(test, true, ret); | |
1979 | ret = vcap_is_next_lookup(&test_vctrl, 1500000, 8001000); | |
1980 | KUNIT_EXPECT_EQ(test, true, ret); | |
1981 | ||
1982 | ret = vcap_is_next_lookup(&test_vctrl, 8000000, 8001000); | |
1983 | KUNIT_EXPECT_EQ(test, false, ret); | |
1984 | ret = vcap_is_next_lookup(&test_vctrl, 8000000, 8101000); | |
1985 | KUNIT_EXPECT_EQ(test, true, ret); | |
1986 | ||
1987 | ret = vcap_is_next_lookup(&test_vctrl, 8300000, 8301000); | |
1988 | KUNIT_EXPECT_EQ(test, false, ret); | |
1989 | ret = vcap_is_next_lookup(&test_vctrl, 8300000, 8401000); | |
784c3067 | 1990 | KUNIT_EXPECT_EQ(test, false, ret); |
c956b9b3 SH |
1991 | } |
1992 | ||
22f3c325 SH |
1993 | static void vcap_api_filter_unsupported_keys_test(struct kunit *test) |
1994 | { | |
1995 | struct vcap_admin admin = { | |
1996 | .vtype = VCAP_TYPE_IS2, | |
1997 | }; | |
1998 | struct vcap_rule_internal ri = { | |
1999 | .admin = &admin, | |
2000 | .vctrl = &test_vctrl, | |
2001 | .data.keyset = VCAP_KFS_MAC_ETYPE, | |
2002 | }; | |
2003 | enum vcap_key_field keylist[] = { | |
2004 | VCAP_KF_TYPE, | |
2005 | VCAP_KF_LOOKUP_FIRST_IS, | |
2006 | VCAP_KF_ARP_ADDR_SPACE_OK_IS, /* arp keys are not in keyset */ | |
2007 | VCAP_KF_ARP_PROTO_SPACE_OK_IS, | |
2008 | VCAP_KF_ARP_LEN_OK_IS, | |
2009 | VCAP_KF_ARP_TGT_MATCH_IS, | |
2010 | VCAP_KF_ARP_SENDER_MATCH_IS, | |
2011 | VCAP_KF_ARP_OPCODE_UNKNOWN_IS, | |
2012 | VCAP_KF_ARP_OPCODE, | |
2013 | VCAP_KF_8021Q_DEI_CLS, | |
2014 | VCAP_KF_8021Q_PCP_CLS, | |
2015 | VCAP_KF_8021Q_VID_CLS, | |
2016 | VCAP_KF_L2_MC_IS, | |
2017 | VCAP_KF_L2_BC_IS, | |
2018 | }; | |
2019 | enum vcap_key_field expected[] = { | |
2020 | VCAP_KF_TYPE, | |
2021 | VCAP_KF_LOOKUP_FIRST_IS, | |
2022 | VCAP_KF_8021Q_DEI_CLS, | |
2023 | VCAP_KF_8021Q_PCP_CLS, | |
2024 | VCAP_KF_8021Q_VID_CLS, | |
2025 | VCAP_KF_L2_MC_IS, | |
2026 | VCAP_KF_L2_BC_IS, | |
2027 | }; | |
2028 | struct vcap_client_keyfield *ckf, *next; | |
2029 | bool ret; | |
2030 | int idx; | |
2031 | ||
2032 | /* Add all keys to the rule */ | |
2033 | INIT_LIST_HEAD(&ri.data.keyfields); | |
2034 | for (idx = 0; idx < ARRAY_SIZE(keylist); idx++) { | |
2035 | ckf = kzalloc(sizeof(*ckf), GFP_KERNEL); | |
2036 | if (ckf) { | |
2037 | ckf->ctrl.key = keylist[idx]; | |
2038 | list_add_tail(&ckf->ctrl.list, &ri.data.keyfields); | |
2039 | } | |
2040 | } | |
2041 | ||
2042 | KUNIT_EXPECT_EQ(test, 14, ARRAY_SIZE(keylist)); | |
2043 | ||
2044 | /* Drop unsupported keys from the rule */ | |
2045 | ret = vcap_filter_rule_keys(&ri.data, NULL, 0, true); | |
2046 | ||
2047 | KUNIT_EXPECT_EQ(test, 0, ret); | |
2048 | ||
2049 | /* Check remaining keys in the rule */ | |
2050 | idx = 0; | |
2051 | list_for_each_entry_safe(ckf, next, &ri.data.keyfields, ctrl.list) { | |
2052 | KUNIT_EXPECT_EQ(test, expected[idx], ckf->ctrl.key); | |
2053 | list_del(&ckf->ctrl.list); | |
2054 | kfree(ckf); | |
2055 | ++idx; | |
2056 | } | |
2057 | KUNIT_EXPECT_EQ(test, 7, idx); | |
2058 | } | |
2059 | ||
2060 | static void vcap_api_filter_keylist_test(struct kunit *test) | |
2061 | { | |
2062 | struct vcap_admin admin = { | |
2063 | .vtype = VCAP_TYPE_IS0, | |
2064 | }; | |
2065 | struct vcap_rule_internal ri = { | |
2066 | .admin = &admin, | |
2067 | .vctrl = &test_vctrl, | |
2068 | .data.keyset = VCAP_KFS_NORMAL_7TUPLE, | |
2069 | }; | |
2070 | enum vcap_key_field keylist[] = { | |
2071 | VCAP_KF_TYPE, | |
2072 | VCAP_KF_LOOKUP_FIRST_IS, | |
2073 | VCAP_KF_LOOKUP_GEN_IDX_SEL, | |
2074 | VCAP_KF_LOOKUP_GEN_IDX, | |
2075 | VCAP_KF_IF_IGR_PORT_MASK_SEL, | |
2076 | VCAP_KF_IF_IGR_PORT_MASK, | |
2077 | VCAP_KF_L2_MC_IS, | |
2078 | VCAP_KF_L2_BC_IS, | |
2079 | VCAP_KF_8021Q_VLAN_TAGS, | |
2080 | VCAP_KF_8021Q_TPID0, | |
2081 | VCAP_KF_8021Q_PCP0, | |
2082 | VCAP_KF_8021Q_DEI0, | |
2083 | VCAP_KF_8021Q_VID0, | |
2084 | VCAP_KF_8021Q_TPID1, | |
2085 | VCAP_KF_8021Q_PCP1, | |
2086 | VCAP_KF_8021Q_DEI1, | |
2087 | VCAP_KF_8021Q_VID1, | |
2088 | VCAP_KF_8021Q_TPID2, | |
2089 | VCAP_KF_8021Q_PCP2, | |
2090 | VCAP_KF_8021Q_DEI2, | |
2091 | VCAP_KF_8021Q_VID2, | |
2092 | VCAP_KF_L2_DMAC, | |
2093 | VCAP_KF_L2_SMAC, | |
2094 | VCAP_KF_IP_MC_IS, | |
2095 | VCAP_KF_ETYPE_LEN_IS, | |
2096 | VCAP_KF_ETYPE, | |
2097 | VCAP_KF_IP_SNAP_IS, | |
2098 | VCAP_KF_IP4_IS, | |
2099 | VCAP_KF_L3_FRAGMENT_TYPE, | |
2100 | VCAP_KF_L3_FRAG_INVLD_L4_LEN, | |
2101 | VCAP_KF_L3_OPTIONS_IS, | |
2102 | VCAP_KF_L3_DSCP, | |
2103 | VCAP_KF_L3_IP6_DIP, | |
2104 | VCAP_KF_L3_IP6_SIP, | |
2105 | VCAP_KF_TCP_UDP_IS, | |
2106 | VCAP_KF_TCP_IS, | |
2107 | VCAP_KF_L4_SPORT, | |
2108 | VCAP_KF_L4_RNG, | |
2109 | }; | |
2110 | enum vcap_key_field droplist[] = { | |
2111 | VCAP_KF_8021Q_TPID1, | |
2112 | VCAP_KF_8021Q_PCP1, | |
2113 | VCAP_KF_8021Q_DEI1, | |
2114 | VCAP_KF_8021Q_VID1, | |
2115 | VCAP_KF_8021Q_TPID2, | |
2116 | VCAP_KF_8021Q_PCP2, | |
2117 | VCAP_KF_8021Q_DEI2, | |
2118 | VCAP_KF_8021Q_VID2, | |
2119 | VCAP_KF_L3_IP6_DIP, | |
2120 | VCAP_KF_L3_IP6_SIP, | |
2121 | VCAP_KF_L4_SPORT, | |
2122 | VCAP_KF_L4_RNG, | |
2123 | }; | |
2124 | enum vcap_key_field expected[] = { | |
2125 | VCAP_KF_TYPE, | |
2126 | VCAP_KF_LOOKUP_FIRST_IS, | |
2127 | VCAP_KF_LOOKUP_GEN_IDX_SEL, | |
2128 | VCAP_KF_LOOKUP_GEN_IDX, | |
2129 | VCAP_KF_IF_IGR_PORT_MASK_SEL, | |
2130 | VCAP_KF_IF_IGR_PORT_MASK, | |
2131 | VCAP_KF_L2_MC_IS, | |
2132 | VCAP_KF_L2_BC_IS, | |
2133 | VCAP_KF_8021Q_VLAN_TAGS, | |
2134 | VCAP_KF_8021Q_TPID0, | |
2135 | VCAP_KF_8021Q_PCP0, | |
2136 | VCAP_KF_8021Q_DEI0, | |
2137 | VCAP_KF_8021Q_VID0, | |
2138 | VCAP_KF_L2_DMAC, | |
2139 | VCAP_KF_L2_SMAC, | |
2140 | VCAP_KF_IP_MC_IS, | |
2141 | VCAP_KF_ETYPE_LEN_IS, | |
2142 | VCAP_KF_ETYPE, | |
2143 | VCAP_KF_IP_SNAP_IS, | |
2144 | VCAP_KF_IP4_IS, | |
2145 | VCAP_KF_L3_FRAGMENT_TYPE, | |
2146 | VCAP_KF_L3_FRAG_INVLD_L4_LEN, | |
2147 | VCAP_KF_L3_OPTIONS_IS, | |
2148 | VCAP_KF_L3_DSCP, | |
2149 | VCAP_KF_TCP_UDP_IS, | |
2150 | VCAP_KF_TCP_IS, | |
2151 | }; | |
2152 | struct vcap_client_keyfield *ckf, *next; | |
2153 | bool ret; | |
2154 | int idx; | |
2155 | ||
2156 | /* Add all keys to the rule */ | |
2157 | INIT_LIST_HEAD(&ri.data.keyfields); | |
2158 | for (idx = 0; idx < ARRAY_SIZE(keylist); idx++) { | |
2159 | ckf = kzalloc(sizeof(*ckf), GFP_KERNEL); | |
2160 | if (ckf) { | |
2161 | ckf->ctrl.key = keylist[idx]; | |
2162 | list_add_tail(&ckf->ctrl.list, &ri.data.keyfields); | |
2163 | } | |
2164 | } | |
2165 | ||
2166 | KUNIT_EXPECT_EQ(test, 38, ARRAY_SIZE(keylist)); | |
2167 | ||
2168 | /* Drop listed keys from the rule */ | |
2169 | ret = vcap_filter_rule_keys(&ri.data, droplist, ARRAY_SIZE(droplist), | |
2170 | false); | |
2171 | ||
2172 | KUNIT_EXPECT_EQ(test, 0, ret); | |
2173 | ||
2174 | /* Check remaining keys in the rule */ | |
2175 | idx = 0; | |
2176 | list_for_each_entry_safe(ckf, next, &ri.data.keyfields, ctrl.list) { | |
2177 | KUNIT_EXPECT_EQ(test, expected[idx], ckf->ctrl.key); | |
2178 | list_del(&ckf->ctrl.list); | |
2179 | kfree(ckf); | |
2180 | ++idx; | |
2181 | } | |
2182 | KUNIT_EXPECT_EQ(test, 26, idx); | |
2183 | } | |
2184 | ||
1f741f00 SH |
2185 | static void vcap_api_rule_chain_path_test(struct kunit *test) |
2186 | { | |
2187 | struct vcap_admin admin1 = { | |
2188 | .vtype = VCAP_TYPE_IS0, | |
2189 | .vinst = 0, | |
2190 | .first_cid = 1000000, | |
2191 | .last_cid = 1199999, | |
2192 | .lookups = 6, | |
2193 | .lookups_per_instance = 2, | |
2194 | }; | |
2195 | struct vcap_enabled_port eport3 = { | |
2196 | .ndev = &test_netdev, | |
2197 | .cookie = 0x100, | |
2198 | .src_cid = 0, | |
2199 | .dst_cid = 1000000, | |
2200 | }; | |
2201 | struct vcap_enabled_port eport2 = { | |
2202 | .ndev = &test_netdev, | |
2203 | .cookie = 0x200, | |
2204 | .src_cid = 1000000, | |
2205 | .dst_cid = 1100000, | |
2206 | }; | |
2207 | struct vcap_enabled_port eport1 = { | |
2208 | .ndev = &test_netdev, | |
2209 | .cookie = 0x300, | |
2210 | .src_cid = 1100000, | |
2211 | .dst_cid = 8000000, | |
2212 | }; | |
2213 | bool ret; | |
2214 | int chain; | |
2215 | ||
2216 | vcap_test_api_init(&admin1); | |
2217 | list_add_tail(&eport1.list, &admin1.enabled); | |
2218 | list_add_tail(&eport2.list, &admin1.enabled); | |
2219 | list_add_tail(&eport3.list, &admin1.enabled); | |
2220 | ||
2221 | ret = vcap_path_exist(&test_vctrl, &test_netdev, 1000000); | |
2222 | KUNIT_EXPECT_EQ(test, true, ret); | |
2223 | ||
2224 | ret = vcap_path_exist(&test_vctrl, &test_netdev, 1100000); | |
2225 | KUNIT_EXPECT_EQ(test, true, ret); | |
2226 | ||
2227 | ret = vcap_path_exist(&test_vctrl, &test_netdev, 1200000); | |
2228 | KUNIT_EXPECT_EQ(test, false, ret); | |
2229 | ||
2230 | chain = vcap_get_next_chain(&test_vctrl, &test_netdev, 0); | |
2231 | KUNIT_EXPECT_EQ(test, 1000000, chain); | |
2232 | ||
2233 | chain = vcap_get_next_chain(&test_vctrl, &test_netdev, 1000000); | |
2234 | KUNIT_EXPECT_EQ(test, 1100000, chain); | |
2235 | ||
2236 | chain = vcap_get_next_chain(&test_vctrl, &test_netdev, 1100000); | |
2237 | KUNIT_EXPECT_EQ(test, 8000000, chain); | |
2238 | } | |
2239 | ||
2240 | static struct kunit_case vcap_api_rule_enable_test_cases[] = { | |
2241 | KUNIT_CASE(vcap_api_rule_chain_path_test), | |
2242 | {} | |
2243 | }; | |
2244 | ||
2245 | static struct kunit_suite vcap_api_rule_enable_test_suite = { | |
2246 | .name = "VCAP_API_Rule_Enable_Testsuite", | |
2247 | .test_cases = vcap_api_rule_enable_test_cases, | |
2248 | }; | |
2249 | ||
dccc30cc SH |
2250 | static struct kunit_suite vcap_api_rule_remove_test_suite = { |
2251 | .name = "VCAP_API_Rule_Remove_Testsuite", | |
2252 | .test_cases = vcap_api_rule_remove_test_cases, | |
2253 | }; | |
2254 | ||
2255 | static struct kunit_case vcap_api_rule_insert_test_cases[] = { | |
2256 | KUNIT_CASE(vcap_api_rule_insert_in_order_test), | |
2257 | KUNIT_CASE(vcap_api_rule_insert_reverse_order_test), | |
2258 | {} | |
2259 | }; | |
2260 | ||
2261 | static struct kunit_suite vcap_api_rule_insert_test_suite = { | |
2262 | .name = "VCAP_API_Rule_Insert_Testsuite", | |
2263 | .test_cases = vcap_api_rule_insert_test_cases, | |
2264 | }; | |
2265 | ||
2266 | static struct kunit_case vcap_api_rule_counter_test_cases[] = { | |
2267 | KUNIT_CASE(vcap_api_set_rule_counter_test), | |
2268 | KUNIT_CASE(vcap_api_get_rule_counter_test), | |
2269 | {} | |
2270 | }; | |
2271 | ||
2272 | static struct kunit_suite vcap_api_rule_counter_test_suite = { | |
2273 | .name = "VCAP_API_Rule_Counter_Testsuite", | |
2274 | .test_cases = vcap_api_rule_counter_test_cases, | |
2275 | }; | |
2276 | ||
c956b9b3 SH |
2277 | static struct kunit_case vcap_api_support_test_cases[] = { |
2278 | KUNIT_CASE(vcap_api_next_lookup_basic_test), | |
2279 | KUNIT_CASE(vcap_api_next_lookup_advanced_test), | |
22f3c325 SH |
2280 | KUNIT_CASE(vcap_api_filter_unsupported_keys_test), |
2281 | KUNIT_CASE(vcap_api_filter_keylist_test), | |
c956b9b3 SH |
2282 | {} |
2283 | }; | |
2284 | ||
2285 | static struct kunit_suite vcap_api_support_test_suite = { | |
2286 | .name = "VCAP_API_Support_Testsuite", | |
2287 | .test_cases = vcap_api_support_test_cases, | |
2288 | }; | |
2289 | ||
2290 | static struct kunit_case vcap_api_full_rule_test_cases[] = { | |
2291 | KUNIT_CASE(vcap_api_rule_find_keyset_basic_test), | |
2292 | KUNIT_CASE(vcap_api_rule_find_keyset_failed_test), | |
2293 | KUNIT_CASE(vcap_api_rule_find_keyset_many_test), | |
2294 | KUNIT_CASE(vcap_api_encode_rule_test), | |
2295 | {} | |
2296 | }; | |
2297 | ||
2298 | static struct kunit_suite vcap_api_full_rule_test_suite = { | |
2299 | .name = "VCAP_API_Full_Rule_Testsuite", | |
2300 | .test_cases = vcap_api_full_rule_test_cases, | |
2301 | }; | |
2302 | ||
2303 | static struct kunit_case vcap_api_rule_value_test_cases[] = { | |
2304 | KUNIT_CASE(vcap_api_rule_add_keyvalue_test), | |
2305 | KUNIT_CASE(vcap_api_rule_add_actionvalue_test), | |
2306 | {} | |
2307 | }; | |
2308 | ||
2309 | static struct kunit_suite vcap_api_rule_value_test_suite = { | |
2310 | .name = "VCAP_API_Rule_Value_Testsuite", | |
2311 | .test_cases = vcap_api_rule_value_test_cases, | |
2312 | }; | |
2313 | ||
67d63751 SH |
2314 | static struct kunit_case vcap_api_encoding_test_cases[] = { |
2315 | KUNIT_CASE(vcap_api_set_bit_1_test), | |
2316 | KUNIT_CASE(vcap_api_set_bit_0_test), | |
2317 | KUNIT_CASE(vcap_api_iterator_init_test), | |
2318 | KUNIT_CASE(vcap_api_iterator_next_test), | |
2319 | KUNIT_CASE(vcap_api_encode_typegroups_test), | |
2320 | KUNIT_CASE(vcap_api_encode_bit_test), | |
2321 | KUNIT_CASE(vcap_api_encode_field_test), | |
2322 | KUNIT_CASE(vcap_api_encode_short_field_test), | |
2323 | KUNIT_CASE(vcap_api_encode_keyfield_test), | |
2324 | KUNIT_CASE(vcap_api_encode_max_keyfield_test), | |
2325 | KUNIT_CASE(vcap_api_encode_actionfield_test), | |
2326 | KUNIT_CASE(vcap_api_keyfield_typegroup_test), | |
2327 | KUNIT_CASE(vcap_api_actionfield_typegroup_test), | |
2328 | KUNIT_CASE(vcap_api_vcap_keyfields_test), | |
2329 | KUNIT_CASE(vcap_api_vcap_actionfields_test), | |
2330 | KUNIT_CASE(vcap_api_encode_rule_keyset_test), | |
2331 | KUNIT_CASE(vcap_api_encode_rule_actionset_test), | |
2332 | {} | |
2333 | }; | |
2334 | ||
2335 | static struct kunit_suite vcap_api_encoding_test_suite = { | |
2336 | .name = "VCAP_API_Encoding_Testsuite", | |
2337 | .test_cases = vcap_api_encoding_test_cases, | |
2338 | }; | |
2339 | ||
1f741f00 | 2340 | kunit_test_suite(vcap_api_rule_enable_test_suite); |
dccc30cc SH |
2341 | kunit_test_suite(vcap_api_rule_remove_test_suite); |
2342 | kunit_test_suite(vcap_api_rule_insert_test_suite); | |
2343 | kunit_test_suite(vcap_api_rule_counter_test_suite); | |
c956b9b3 SH |
2344 | kunit_test_suite(vcap_api_support_test_suite); |
2345 | kunit_test_suite(vcap_api_full_rule_test_suite); | |
2346 | kunit_test_suite(vcap_api_rule_value_test_suite); | |
67d63751 | 2347 | kunit_test_suite(vcap_api_encoding_test_suite); |