1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2a9de470cSBruce Richardson * Copyright(c) 2010-2014 Intel Corporation
3a9de470cSBruce Richardson */
4a9de470cSBruce Richardson
5a9de470cSBruce Richardson #include <stdio.h>
6a9de470cSBruce Richardson #include <stdint.h>
7a9de470cSBruce Richardson #include <stdlib.h>
8a9de470cSBruce Richardson
9a9de470cSBruce Richardson #include <rte_ip.h>
10a9de470cSBruce Richardson #include <rte_lpm.h>
116823fad3SRuifeng Wang #include <rte_malloc.h>
12a9de470cSBruce Richardson
13b90d75a9SStephen Hemminger #include "test.h"
14a9de470cSBruce Richardson #include "test_xmmt_ops.h"
15a9de470cSBruce Richardson
16a9de470cSBruce Richardson #define TEST_LPM_ASSERT(cond) do { \
17a9de470cSBruce Richardson if (!(cond)) { \
18a9de470cSBruce Richardson printf("Error at line %d: \n", __LINE__); \
19a9de470cSBruce Richardson return -1; \
20a9de470cSBruce Richardson } \
21a9de470cSBruce Richardson } while(0)
22a9de470cSBruce Richardson
23a9de470cSBruce Richardson typedef int32_t (*rte_lpm_test)(void);
24a9de470cSBruce Richardson
25a9de470cSBruce Richardson static int32_t test0(void);
26a9de470cSBruce Richardson static int32_t test1(void);
27a9de470cSBruce Richardson static int32_t test2(void);
28a9de470cSBruce Richardson static int32_t test3(void);
29a9de470cSBruce Richardson static int32_t test4(void);
30a9de470cSBruce Richardson static int32_t test5(void);
31a9de470cSBruce Richardson static int32_t test6(void);
32a9de470cSBruce Richardson static int32_t test7(void);
33a9de470cSBruce Richardson static int32_t test8(void);
34a9de470cSBruce Richardson static int32_t test9(void);
35a9de470cSBruce Richardson static int32_t test10(void);
36a9de470cSBruce Richardson static int32_t test11(void);
37a9de470cSBruce Richardson static int32_t test12(void);
38a9de470cSBruce Richardson static int32_t test13(void);
39a9de470cSBruce Richardson static int32_t test14(void);
40a9de470cSBruce Richardson static int32_t test15(void);
41a9de470cSBruce Richardson static int32_t test16(void);
42a9de470cSBruce Richardson static int32_t test17(void);
43a9de470cSBruce Richardson static int32_t test18(void);
446823fad3SRuifeng Wang static int32_t test19(void);
456823fad3SRuifeng Wang static int32_t test20(void);
466823fad3SRuifeng Wang static int32_t test21(void);
47a9de470cSBruce Richardson
48a9de470cSBruce Richardson rte_lpm_test tests[] = {
49a9de470cSBruce Richardson /* Test Cases */
50a9de470cSBruce Richardson test0,
51a9de470cSBruce Richardson test1,
52a9de470cSBruce Richardson test2,
53a9de470cSBruce Richardson test3,
54a9de470cSBruce Richardson test4,
55a9de470cSBruce Richardson test5,
56a9de470cSBruce Richardson test6,
57a9de470cSBruce Richardson test7,
58a9de470cSBruce Richardson test8,
59a9de470cSBruce Richardson test9,
60a9de470cSBruce Richardson test10,
61a9de470cSBruce Richardson test11,
62a9de470cSBruce Richardson test12,
63a9de470cSBruce Richardson test13,
64a9de470cSBruce Richardson test14,
65a9de470cSBruce Richardson test15,
66a9de470cSBruce Richardson test16,
67a9de470cSBruce Richardson test17,
686823fad3SRuifeng Wang test18,
696823fad3SRuifeng Wang test19,
706823fad3SRuifeng Wang test20,
716823fad3SRuifeng Wang test21
72a9de470cSBruce Richardson };
73a9de470cSBruce Richardson
74a9de470cSBruce Richardson #define MAX_DEPTH 32
75a9de470cSBruce Richardson #define MAX_RULES 256
76a9de470cSBruce Richardson #define NUMBER_TBL8S 256
77a9de470cSBruce Richardson #define PASS 0
78a9de470cSBruce Richardson
79a9de470cSBruce Richardson /*
80a9de470cSBruce Richardson * Check that rte_lpm_create fails gracefully for incorrect user input
81a9de470cSBruce Richardson * arguments
82a9de470cSBruce Richardson */
83a9de470cSBruce Richardson int32_t
test0(void)84a9de470cSBruce Richardson test0(void)
85a9de470cSBruce Richardson {
86a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
87a9de470cSBruce Richardson struct rte_lpm_config config;
88a9de470cSBruce Richardson
89a9de470cSBruce Richardson config.max_rules = MAX_RULES;
90a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
91a9de470cSBruce Richardson config.flags = 0;
92a9de470cSBruce Richardson
93a9de470cSBruce Richardson /* rte_lpm_create: lpm name == NULL */
94a9de470cSBruce Richardson lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, &config);
95a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm == NULL);
96a9de470cSBruce Richardson
97a9de470cSBruce Richardson /* rte_lpm_create: max_rules = 0 */
98a9de470cSBruce Richardson /* Note: __func__ inserts the function name, in this case "test0". */
99a9de470cSBruce Richardson config.max_rules = 0;
100a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
101a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm == NULL);
102a9de470cSBruce Richardson
103a9de470cSBruce Richardson /* socket_id < -1 is invalid */
104a9de470cSBruce Richardson config.max_rules = MAX_RULES;
105a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, -2, &config);
106a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm == NULL);
107a9de470cSBruce Richardson
108a9de470cSBruce Richardson return PASS;
109a9de470cSBruce Richardson }
110a9de470cSBruce Richardson
111a9de470cSBruce Richardson /*
112a9de470cSBruce Richardson * Create lpm table then delete lpm table 100 times
113a9de470cSBruce Richardson * Use a slightly different rules size each time
114a9de470cSBruce Richardson * */
115a9de470cSBruce Richardson int32_t
test1(void)116a9de470cSBruce Richardson test1(void)
117a9de470cSBruce Richardson {
118a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
119a9de470cSBruce Richardson struct rte_lpm_config config;
120a9de470cSBruce Richardson
121a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
122a9de470cSBruce Richardson config.flags = 0;
123a9de470cSBruce Richardson int32_t i;
124a9de470cSBruce Richardson
125a9de470cSBruce Richardson /* rte_lpm_free: Free NULL */
126a9de470cSBruce Richardson for (i = 0; i < 100; i++) {
127a9de470cSBruce Richardson config.max_rules = MAX_RULES - i;
128a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
129a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
130a9de470cSBruce Richardson
131a9de470cSBruce Richardson rte_lpm_free(lpm);
132a9de470cSBruce Richardson }
133a9de470cSBruce Richardson
134a9de470cSBruce Richardson /* Can not test free so return success */
135a9de470cSBruce Richardson return PASS;
136a9de470cSBruce Richardson }
137a9de470cSBruce Richardson
138a9de470cSBruce Richardson /*
139a9de470cSBruce Richardson * Call rte_lpm_free for NULL pointer user input. Note: free has no return and
140a9de470cSBruce Richardson * therefore it is impossible to check for failure but this test is added to
141a9de470cSBruce Richardson * increase function coverage metrics and to validate that freeing null does
142a9de470cSBruce Richardson * not crash.
143a9de470cSBruce Richardson */
144a9de470cSBruce Richardson int32_t
test2(void)145a9de470cSBruce Richardson test2(void)
146a9de470cSBruce Richardson {
147a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
148a9de470cSBruce Richardson struct rte_lpm_config config;
149a9de470cSBruce Richardson
150a9de470cSBruce Richardson config.max_rules = MAX_RULES;
151a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
152a9de470cSBruce Richardson config.flags = 0;
153a9de470cSBruce Richardson
154a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
155a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
156a9de470cSBruce Richardson
157a9de470cSBruce Richardson rte_lpm_free(lpm);
158a9de470cSBruce Richardson rte_lpm_free(NULL);
159a9de470cSBruce Richardson return PASS;
160a9de470cSBruce Richardson }
161a9de470cSBruce Richardson
162a9de470cSBruce Richardson /*
163a9de470cSBruce Richardson * Check that rte_lpm_add fails gracefully for incorrect user input arguments
164a9de470cSBruce Richardson */
165a9de470cSBruce Richardson int32_t
test3(void)166a9de470cSBruce Richardson test3(void)
167a9de470cSBruce Richardson {
168a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
169a9de470cSBruce Richardson struct rte_lpm_config config;
170a9de470cSBruce Richardson
171a9de470cSBruce Richardson config.max_rules = MAX_RULES;
172a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
173a9de470cSBruce Richardson config.flags = 0;
1740c9da755SDavid Marchand uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop = 100;
175a9de470cSBruce Richardson uint8_t depth = 24;
176a9de470cSBruce Richardson int32_t status = 0;
177a9de470cSBruce Richardson
178a9de470cSBruce Richardson /* rte_lpm_add: lpm == NULL */
179a9de470cSBruce Richardson status = rte_lpm_add(NULL, ip, depth, next_hop);
180a9de470cSBruce Richardson TEST_LPM_ASSERT(status < 0);
181a9de470cSBruce Richardson
1824a6672c2SStephen Hemminger /*Create valid lpm to use in rest of test. */
183a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
184a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
185a9de470cSBruce Richardson
186a9de470cSBruce Richardson /* rte_lpm_add: depth < 1 */
187a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, 0, next_hop);
188a9de470cSBruce Richardson TEST_LPM_ASSERT(status < 0);
189a9de470cSBruce Richardson
190a9de470cSBruce Richardson /* rte_lpm_add: depth > MAX_DEPTH */
191a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
192a9de470cSBruce Richardson TEST_LPM_ASSERT(status < 0);
193a9de470cSBruce Richardson
194a9de470cSBruce Richardson rte_lpm_free(lpm);
195a9de470cSBruce Richardson
196a9de470cSBruce Richardson return PASS;
197a9de470cSBruce Richardson }
198a9de470cSBruce Richardson
199a9de470cSBruce Richardson /*
200a9de470cSBruce Richardson * Check that rte_lpm_delete fails gracefully for incorrect user input
201a9de470cSBruce Richardson * arguments
202a9de470cSBruce Richardson */
203a9de470cSBruce Richardson int32_t
test4(void)204a9de470cSBruce Richardson test4(void)
205a9de470cSBruce Richardson {
206a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
207a9de470cSBruce Richardson struct rte_lpm_config config;
208a9de470cSBruce Richardson
209a9de470cSBruce Richardson config.max_rules = MAX_RULES;
210a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
211a9de470cSBruce Richardson config.flags = 0;
2120c9da755SDavid Marchand uint32_t ip = RTE_IPV4(0, 0, 0, 0);
213a9de470cSBruce Richardson uint8_t depth = 24;
214a9de470cSBruce Richardson int32_t status = 0;
215a9de470cSBruce Richardson
216a9de470cSBruce Richardson /* rte_lpm_delete: lpm == NULL */
217a9de470cSBruce Richardson status = rte_lpm_delete(NULL, ip, depth);
218a9de470cSBruce Richardson TEST_LPM_ASSERT(status < 0);
219a9de470cSBruce Richardson
2204a6672c2SStephen Hemminger /*Create valid lpm to use in rest of test. */
221a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
222a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
223a9de470cSBruce Richardson
224a9de470cSBruce Richardson /* rte_lpm_delete: depth < 1 */
225a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, 0);
226a9de470cSBruce Richardson TEST_LPM_ASSERT(status < 0);
227a9de470cSBruce Richardson
228a9de470cSBruce Richardson /* rte_lpm_delete: depth > MAX_DEPTH */
229a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, (MAX_DEPTH + 1));
230a9de470cSBruce Richardson TEST_LPM_ASSERT(status < 0);
231a9de470cSBruce Richardson
232a9de470cSBruce Richardson rte_lpm_free(lpm);
233a9de470cSBruce Richardson
234a9de470cSBruce Richardson return PASS;
235a9de470cSBruce Richardson }
236a9de470cSBruce Richardson
237a9de470cSBruce Richardson /*
238a9de470cSBruce Richardson * Check that rte_lpm_lookup fails gracefully for incorrect user input
239a9de470cSBruce Richardson * arguments
240a9de470cSBruce Richardson */
241a9de470cSBruce Richardson int32_t
test5(void)242a9de470cSBruce Richardson test5(void)
243a9de470cSBruce Richardson {
244a9de470cSBruce Richardson #if defined(RTE_LIBRTE_LPM_DEBUG)
245a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
246a9de470cSBruce Richardson struct rte_lpm_config config;
247a9de470cSBruce Richardson
248a9de470cSBruce Richardson config.max_rules = MAX_RULES;
249a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
250a9de470cSBruce Richardson config.flags = 0;
2510c9da755SDavid Marchand uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_return = 0;
252a9de470cSBruce Richardson int32_t status = 0;
253a9de470cSBruce Richardson
254a9de470cSBruce Richardson /* rte_lpm_lookup: lpm == NULL */
255a9de470cSBruce Richardson status = rte_lpm_lookup(NULL, ip, &next_hop_return);
256a9de470cSBruce Richardson TEST_LPM_ASSERT(status < 0);
257a9de470cSBruce Richardson
2584a6672c2SStephen Hemminger /*Create valid lpm to use in rest of test. */
259a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
260a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
261a9de470cSBruce Richardson
262a9de470cSBruce Richardson /* rte_lpm_lookup: depth < 1 */
263a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, NULL);
264a9de470cSBruce Richardson TEST_LPM_ASSERT(status < 0);
265a9de470cSBruce Richardson
266a9de470cSBruce Richardson rte_lpm_free(lpm);
267a9de470cSBruce Richardson #endif
268a9de470cSBruce Richardson return PASS;
269a9de470cSBruce Richardson }
270a9de470cSBruce Richardson
271a9de470cSBruce Richardson
272a9de470cSBruce Richardson
273a9de470cSBruce Richardson /*
274a9de470cSBruce Richardson * Call add, lookup and delete for a single rule with depth <= 24
275a9de470cSBruce Richardson */
276a9de470cSBruce Richardson int32_t
test6(void)277a9de470cSBruce Richardson test6(void)
278a9de470cSBruce Richardson {
279a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
280a9de470cSBruce Richardson struct rte_lpm_config config;
281a9de470cSBruce Richardson
282a9de470cSBruce Richardson config.max_rules = MAX_RULES;
283a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
284a9de470cSBruce Richardson config.flags = 0;
2850c9da755SDavid Marchand uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
286a9de470cSBruce Richardson uint8_t depth = 24;
287a9de470cSBruce Richardson int32_t status = 0;
288a9de470cSBruce Richardson
289a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
290a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
291a9de470cSBruce Richardson
292a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
293a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
294a9de470cSBruce Richardson
295a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
296a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
297a9de470cSBruce Richardson
298a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
299a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
300a9de470cSBruce Richardson
301a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
302a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
303a9de470cSBruce Richardson
304a9de470cSBruce Richardson rte_lpm_free(lpm);
305a9de470cSBruce Richardson
306a9de470cSBruce Richardson return PASS;
307a9de470cSBruce Richardson }
308a9de470cSBruce Richardson
309a9de470cSBruce Richardson /*
310a9de470cSBruce Richardson * Call add, lookup and delete for a single rule with depth > 24
311a9de470cSBruce Richardson */
312a9de470cSBruce Richardson
313a9de470cSBruce Richardson int32_t
test7(void)314a9de470cSBruce Richardson test7(void)
315a9de470cSBruce Richardson {
316a9de470cSBruce Richardson xmm_t ipx4;
317a9de470cSBruce Richardson uint32_t hop[4];
318a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
319a9de470cSBruce Richardson struct rte_lpm_config config;
320a9de470cSBruce Richardson
321a9de470cSBruce Richardson config.max_rules = MAX_RULES;
322a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
323a9de470cSBruce Richardson config.flags = 0;
3240c9da755SDavid Marchand uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
325a9de470cSBruce Richardson uint8_t depth = 32;
326a9de470cSBruce Richardson int32_t status = 0;
327a9de470cSBruce Richardson
328a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
329a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
330a9de470cSBruce Richardson
331a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
332a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
333a9de470cSBruce Richardson
334a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
335a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
336a9de470cSBruce Richardson
337a9de470cSBruce Richardson ipx4 = vect_set_epi32(ip, ip + 0x100, ip - 0x100, ip);
338a9de470cSBruce Richardson rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
339a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[0] == next_hop_add);
340a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
341a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
342a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[3] == next_hop_add);
343a9de470cSBruce Richardson
344a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
345a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
346a9de470cSBruce Richardson
347a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
348a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
349a9de470cSBruce Richardson
350a9de470cSBruce Richardson rte_lpm_free(lpm);
351a9de470cSBruce Richardson
352a9de470cSBruce Richardson return PASS;
353a9de470cSBruce Richardson }
354a9de470cSBruce Richardson
355a9de470cSBruce Richardson /*
356a9de470cSBruce Richardson * Use rte_lpm_add to add rules which effect only the second half of the lpm
357a9de470cSBruce Richardson * table. Use all possible depths ranging from 1..32. Set the next hop = to the
358a9de470cSBruce Richardson * depth. Check lookup hit for on every add and check for lookup miss on the
359a9de470cSBruce Richardson * first half of the lpm table after each add. Finally delete all rules going
360a9de470cSBruce Richardson * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
361a9de470cSBruce Richardson * delete. The lookup should return the next_hop_add value related to the
362a9de470cSBruce Richardson * previous depth value (i.e. depth -1).
363a9de470cSBruce Richardson */
364a9de470cSBruce Richardson int32_t
test8(void)365a9de470cSBruce Richardson test8(void)
366a9de470cSBruce Richardson {
367a9de470cSBruce Richardson xmm_t ipx4;
368a9de470cSBruce Richardson uint32_t hop[4];
369a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
370a9de470cSBruce Richardson struct rte_lpm_config config;
371a9de470cSBruce Richardson
372a9de470cSBruce Richardson config.max_rules = MAX_RULES;
373a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
374a9de470cSBruce Richardson config.flags = 0;
3750c9da755SDavid Marchand uint32_t ip1 = RTE_IPV4(127, 255, 255, 255), ip2 = RTE_IPV4(128, 0, 0, 0);
376a9de470cSBruce Richardson uint32_t next_hop_add, next_hop_return;
377a9de470cSBruce Richardson uint8_t depth;
378a9de470cSBruce Richardson int32_t status = 0;
379a9de470cSBruce Richardson
380a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
381a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
382a9de470cSBruce Richardson
383a9de470cSBruce Richardson /* Loop with rte_lpm_add. */
384a9de470cSBruce Richardson for (depth = 1; depth <= 32; depth++) {
385a9de470cSBruce Richardson /* Let the next_hop_add value = depth. Just for change. */
386a9de470cSBruce Richardson next_hop_add = depth;
387a9de470cSBruce Richardson
388a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip2, depth, next_hop_add);
389a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
390a9de470cSBruce Richardson
391a9de470cSBruce Richardson /* Check IP in first half of tbl24 which should be empty. */
392a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
393a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
394a9de470cSBruce Richardson
395a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
396a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) &&
397a9de470cSBruce Richardson (next_hop_return == next_hop_add));
398a9de470cSBruce Richardson
399a9de470cSBruce Richardson ipx4 = vect_set_epi32(ip2, ip1, ip2, ip1);
400a9de470cSBruce Richardson rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
401a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
402a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[1] == next_hop_add);
403a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
404a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[3] == next_hop_add);
405a9de470cSBruce Richardson }
406a9de470cSBruce Richardson
407a9de470cSBruce Richardson /* Loop with rte_lpm_delete. */
408a9de470cSBruce Richardson for (depth = 32; depth >= 1; depth--) {
409a9de470cSBruce Richardson next_hop_add = (uint8_t) (depth - 1);
410a9de470cSBruce Richardson
411a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip2, depth);
412a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
413a9de470cSBruce Richardson
414a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
415a9de470cSBruce Richardson
416a9de470cSBruce Richardson if (depth != 1) {
417a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) &&
418a9de470cSBruce Richardson (next_hop_return == next_hop_add));
419a9de470cSBruce Richardson } else {
420a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
421a9de470cSBruce Richardson }
422a9de470cSBruce Richardson
423a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
424a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
425a9de470cSBruce Richardson
426a9de470cSBruce Richardson ipx4 = vect_set_epi32(ip1, ip1, ip2, ip2);
427a9de470cSBruce Richardson rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
428a9de470cSBruce Richardson if (depth != 1) {
429a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[0] == next_hop_add);
430a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[1] == next_hop_add);
431a9de470cSBruce Richardson } else {
432a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
433a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
434a9de470cSBruce Richardson }
435a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
436a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[3] == UINT32_MAX);
437a9de470cSBruce Richardson }
438a9de470cSBruce Richardson
439a9de470cSBruce Richardson rte_lpm_free(lpm);
440a9de470cSBruce Richardson
441a9de470cSBruce Richardson return PASS;
442a9de470cSBruce Richardson }
443a9de470cSBruce Richardson
444a9de470cSBruce Richardson /*
445a9de470cSBruce Richardson * - Add & lookup to hit invalid TBL24 entry
446a9de470cSBruce Richardson * - Add & lookup to hit valid TBL24 entry not extended
447a9de470cSBruce Richardson * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
448a9de470cSBruce Richardson * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
449a9de470cSBruce Richardson *
450a9de470cSBruce Richardson */
451a9de470cSBruce Richardson int32_t
test9(void)452a9de470cSBruce Richardson test9(void)
453a9de470cSBruce Richardson {
454a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
455a9de470cSBruce Richardson struct rte_lpm_config config;
456a9de470cSBruce Richardson
457a9de470cSBruce Richardson config.max_rules = MAX_RULES;
458a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
459a9de470cSBruce Richardson config.flags = 0;
460a9de470cSBruce Richardson uint32_t ip, ip_1, ip_2;
461a9de470cSBruce Richardson uint8_t depth, depth_1, depth_2;
462a9de470cSBruce Richardson uint32_t next_hop_add, next_hop_add_1, next_hop_add_2, next_hop_return;
463a9de470cSBruce Richardson int32_t status = 0;
464a9de470cSBruce Richardson
465a9de470cSBruce Richardson /* Add & lookup to hit invalid TBL24 entry */
4660c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
467a9de470cSBruce Richardson depth = 24;
468a9de470cSBruce Richardson next_hop_add = 100;
469a9de470cSBruce Richardson
470a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
471a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
472a9de470cSBruce Richardson
473a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
474a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
475a9de470cSBruce Richardson
476a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
477a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
478a9de470cSBruce Richardson
479a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
480a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
481a9de470cSBruce Richardson
482a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
483a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
484a9de470cSBruce Richardson
485a9de470cSBruce Richardson rte_lpm_delete_all(lpm);
486a9de470cSBruce Richardson
487a9de470cSBruce Richardson /* Add & lookup to hit valid TBL24 entry not extended */
4880c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
489a9de470cSBruce Richardson depth = 23;
490a9de470cSBruce Richardson next_hop_add = 100;
491a9de470cSBruce Richardson
492a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
493a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
494a9de470cSBruce Richardson
495a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
496a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
497a9de470cSBruce Richardson
498a9de470cSBruce Richardson depth = 24;
499a9de470cSBruce Richardson next_hop_add = 101;
500a9de470cSBruce Richardson
501a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
502a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
503a9de470cSBruce Richardson
504a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
505a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
506a9de470cSBruce Richardson
507a9de470cSBruce Richardson depth = 24;
508a9de470cSBruce Richardson
509a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
510a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
511a9de470cSBruce Richardson
512a9de470cSBruce Richardson depth = 23;
513a9de470cSBruce Richardson
514a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
515a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
516a9de470cSBruce Richardson
517a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
518a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
519a9de470cSBruce Richardson
520a9de470cSBruce Richardson rte_lpm_delete_all(lpm);
521a9de470cSBruce Richardson
522a9de470cSBruce Richardson /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
523a9de470cSBruce Richardson * entry */
5240c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
525a9de470cSBruce Richardson depth = 32;
526a9de470cSBruce Richardson next_hop_add = 100;
527a9de470cSBruce Richardson
528a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
529a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
530a9de470cSBruce Richardson
531a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
532a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
533a9de470cSBruce Richardson
5340c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 5);
535a9de470cSBruce Richardson depth = 32;
536a9de470cSBruce Richardson next_hop_add = 101;
537a9de470cSBruce Richardson
538a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
539a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
540a9de470cSBruce Richardson
541a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
542a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
543a9de470cSBruce Richardson
544a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
545a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
546a9de470cSBruce Richardson
547a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
548a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
549a9de470cSBruce Richardson
5500c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
551a9de470cSBruce Richardson depth = 32;
552a9de470cSBruce Richardson next_hop_add = 100;
553a9de470cSBruce Richardson
554a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
555a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
556a9de470cSBruce Richardson
557a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
558a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
559a9de470cSBruce Richardson
560a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
561a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
562a9de470cSBruce Richardson
563a9de470cSBruce Richardson rte_lpm_delete_all(lpm);
564a9de470cSBruce Richardson
565a9de470cSBruce Richardson /* Add & lookup to hit valid extended TBL24 entry with valid TBL8
566a9de470cSBruce Richardson * entry */
5670c9da755SDavid Marchand ip_1 = RTE_IPV4(128, 0, 0, 0);
568a9de470cSBruce Richardson depth_1 = 25;
569a9de470cSBruce Richardson next_hop_add_1 = 101;
570a9de470cSBruce Richardson
5710c9da755SDavid Marchand ip_2 = RTE_IPV4(128, 0, 0, 5);
572a9de470cSBruce Richardson depth_2 = 32;
573a9de470cSBruce Richardson next_hop_add_2 = 102;
574a9de470cSBruce Richardson
575a9de470cSBruce Richardson next_hop_return = 0;
576a9de470cSBruce Richardson
577a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip_1, depth_1, next_hop_add_1);
578a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
579a9de470cSBruce Richardson
580a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
581a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
582a9de470cSBruce Richardson
583a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip_2, depth_2, next_hop_add_2);
584a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
585a9de470cSBruce Richardson
586a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
587a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
588a9de470cSBruce Richardson
589a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip_2, depth_2);
590a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
591a9de470cSBruce Richardson
592a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
593a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
594a9de470cSBruce Richardson
595a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip_1, depth_1);
596a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
597a9de470cSBruce Richardson
598a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
599a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
600a9de470cSBruce Richardson
601a9de470cSBruce Richardson rte_lpm_free(lpm);
602a9de470cSBruce Richardson
603a9de470cSBruce Richardson return PASS;
604a9de470cSBruce Richardson }
605a9de470cSBruce Richardson
606a9de470cSBruce Richardson
607a9de470cSBruce Richardson /*
608a9de470cSBruce Richardson * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
609a9de470cSBruce Richardson * lookup)
610a9de470cSBruce Richardson * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
611a9de470cSBruce Richardson * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
612a9de470cSBruce Richardson * delete & lookup)
613a9de470cSBruce Richardson * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
614a9de470cSBruce Richardson * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
615a9de470cSBruce Richardson * - Delete a rule that is not present in the TBL24 & lookup
616a9de470cSBruce Richardson * - Delete a rule that is not present in the TBL8 & lookup
617a9de470cSBruce Richardson *
618a9de470cSBruce Richardson */
619a9de470cSBruce Richardson int32_t
test10(void)620a9de470cSBruce Richardson test10(void)
621a9de470cSBruce Richardson {
622a9de470cSBruce Richardson
623a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
624a9de470cSBruce Richardson struct rte_lpm_config config;
625a9de470cSBruce Richardson
626a9de470cSBruce Richardson config.max_rules = MAX_RULES;
627a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
628a9de470cSBruce Richardson config.flags = 0;
629a9de470cSBruce Richardson uint32_t ip, next_hop_add, next_hop_return;
630a9de470cSBruce Richardson uint8_t depth;
631a9de470cSBruce Richardson int32_t status = 0;
632a9de470cSBruce Richardson
633a9de470cSBruce Richardson /* Add rule that covers a TBL24 range previously invalid & lookup
634a9de470cSBruce Richardson * (& delete & lookup) */
635a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
636a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
637a9de470cSBruce Richardson
6380c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
639a9de470cSBruce Richardson depth = 16;
640a9de470cSBruce Richardson next_hop_add = 100;
641a9de470cSBruce Richardson
642a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
643a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
644a9de470cSBruce Richardson
645a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
646a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
647a9de470cSBruce Richardson
648a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
649a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
650a9de470cSBruce Richardson
651a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
652a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
653a9de470cSBruce Richardson
654a9de470cSBruce Richardson rte_lpm_delete_all(lpm);
655a9de470cSBruce Richardson
6560c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
657a9de470cSBruce Richardson depth = 25;
658a9de470cSBruce Richardson next_hop_add = 100;
659a9de470cSBruce Richardson
660a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
661a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
662a9de470cSBruce Richardson
663a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
664a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
665a9de470cSBruce Richardson
666a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
667a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
668a9de470cSBruce Richardson
669a9de470cSBruce Richardson rte_lpm_delete_all(lpm);
670a9de470cSBruce Richardson
671a9de470cSBruce Richardson /* Add rule that extends a TBL24 valid entry & lookup for both rules
672a9de470cSBruce Richardson * (& delete & lookup) */
673a9de470cSBruce Richardson
6740c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
675a9de470cSBruce Richardson depth = 24;
676a9de470cSBruce Richardson next_hop_add = 100;
677a9de470cSBruce Richardson
678a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
679a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
680a9de470cSBruce Richardson
6810c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 10);
682a9de470cSBruce Richardson depth = 32;
683a9de470cSBruce Richardson next_hop_add = 101;
684a9de470cSBruce Richardson
685a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
686a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
687a9de470cSBruce Richardson
688a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
689a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
690a9de470cSBruce Richardson
6910c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
692a9de470cSBruce Richardson next_hop_add = 100;
693a9de470cSBruce Richardson
694a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
695a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
696a9de470cSBruce Richardson
6970c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
698a9de470cSBruce Richardson depth = 24;
699a9de470cSBruce Richardson
700a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
701a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
702a9de470cSBruce Richardson
703a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
704a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
705a9de470cSBruce Richardson
7060c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 10);
707a9de470cSBruce Richardson depth = 32;
708a9de470cSBruce Richardson
709a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
710a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
711a9de470cSBruce Richardson
712a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
713a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
714a9de470cSBruce Richardson
715a9de470cSBruce Richardson rte_lpm_delete_all(lpm);
716a9de470cSBruce Richardson
717a9de470cSBruce Richardson /* Add rule that updates the next hop in TBL24 & lookup
718a9de470cSBruce Richardson * (& delete & lookup) */
719a9de470cSBruce Richardson
7200c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
721a9de470cSBruce Richardson depth = 24;
722a9de470cSBruce Richardson next_hop_add = 100;
723a9de470cSBruce Richardson
724a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
725a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
726a9de470cSBruce Richardson
727a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
728a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
729a9de470cSBruce Richardson
730a9de470cSBruce Richardson next_hop_add = 101;
731a9de470cSBruce Richardson
732a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
733a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
734a9de470cSBruce Richardson
735a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
736a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
737a9de470cSBruce Richardson
738a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
739a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
740a9de470cSBruce Richardson
741a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
742a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
743a9de470cSBruce Richardson
744a9de470cSBruce Richardson rte_lpm_delete_all(lpm);
745a9de470cSBruce Richardson
746a9de470cSBruce Richardson /* Add rule that updates the next hop in TBL8 & lookup
747a9de470cSBruce Richardson * (& delete & lookup) */
748a9de470cSBruce Richardson
7490c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
750a9de470cSBruce Richardson depth = 32;
751a9de470cSBruce Richardson next_hop_add = 100;
752a9de470cSBruce Richardson
753a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
754a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
755a9de470cSBruce Richardson
756a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
757a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
758a9de470cSBruce Richardson
759a9de470cSBruce Richardson next_hop_add = 101;
760a9de470cSBruce Richardson
761a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
762a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
763a9de470cSBruce Richardson
764a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
765a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
766a9de470cSBruce Richardson
767a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
768a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
769a9de470cSBruce Richardson
770a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
771a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
772a9de470cSBruce Richardson
773a9de470cSBruce Richardson rte_lpm_delete_all(lpm);
774a9de470cSBruce Richardson
775a9de470cSBruce Richardson /* Delete a rule that is not present in the TBL24 & lookup */
776a9de470cSBruce Richardson
7770c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
778a9de470cSBruce Richardson depth = 24;
779a9de470cSBruce Richardson
780a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
781a9de470cSBruce Richardson TEST_LPM_ASSERT(status < 0);
782a9de470cSBruce Richardson
783a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
784a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
785a9de470cSBruce Richardson
786a9de470cSBruce Richardson rte_lpm_delete_all(lpm);
787a9de470cSBruce Richardson
788a9de470cSBruce Richardson /* Delete a rule that is not present in the TBL8 & lookup */
789a9de470cSBruce Richardson
7900c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
791a9de470cSBruce Richardson depth = 32;
792a9de470cSBruce Richardson
793a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
794a9de470cSBruce Richardson TEST_LPM_ASSERT(status < 0);
795a9de470cSBruce Richardson
796a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
797a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
798a9de470cSBruce Richardson
799a9de470cSBruce Richardson rte_lpm_free(lpm);
800a9de470cSBruce Richardson
801a9de470cSBruce Richardson return PASS;
802a9de470cSBruce Richardson }
803a9de470cSBruce Richardson
804a9de470cSBruce Richardson /*
805a9de470cSBruce Richardson * Add two rules, lookup to hit the more specific one, lookup to hit the less
806a9de470cSBruce Richardson * specific one delete the less specific rule and lookup previous values again;
807a9de470cSBruce Richardson * add a more specific rule than the existing rule, lookup again
808a9de470cSBruce Richardson *
809a9de470cSBruce Richardson * */
810a9de470cSBruce Richardson int32_t
test11(void)811a9de470cSBruce Richardson test11(void)
812a9de470cSBruce Richardson {
813a9de470cSBruce Richardson
814a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
815a9de470cSBruce Richardson struct rte_lpm_config config;
816a9de470cSBruce Richardson
817a9de470cSBruce Richardson config.max_rules = MAX_RULES;
818a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
819a9de470cSBruce Richardson config.flags = 0;
820a9de470cSBruce Richardson uint32_t ip, next_hop_add, next_hop_return;
821a9de470cSBruce Richardson uint8_t depth;
822a9de470cSBruce Richardson int32_t status = 0;
823a9de470cSBruce Richardson
824a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
825a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
826a9de470cSBruce Richardson
8270c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
828a9de470cSBruce Richardson depth = 24;
829a9de470cSBruce Richardson next_hop_add = 100;
830a9de470cSBruce Richardson
831a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
832a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
833a9de470cSBruce Richardson
8340c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 10);
835a9de470cSBruce Richardson depth = 32;
836a9de470cSBruce Richardson next_hop_add = 101;
837a9de470cSBruce Richardson
838a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
839a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
840a9de470cSBruce Richardson
841a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
842a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
843a9de470cSBruce Richardson
8440c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
845a9de470cSBruce Richardson next_hop_add = 100;
846a9de470cSBruce Richardson
847a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
848a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
849a9de470cSBruce Richardson
8500c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
851a9de470cSBruce Richardson depth = 24;
852a9de470cSBruce Richardson
853a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
854a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
855a9de470cSBruce Richardson
856a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
857a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
858a9de470cSBruce Richardson
8590c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 10);
860a9de470cSBruce Richardson depth = 32;
861a9de470cSBruce Richardson
862a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
863a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
864a9de470cSBruce Richardson
865a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
866a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
867a9de470cSBruce Richardson
868a9de470cSBruce Richardson rte_lpm_free(lpm);
869a9de470cSBruce Richardson
870a9de470cSBruce Richardson return PASS;
871a9de470cSBruce Richardson }
872a9de470cSBruce Richardson
873a9de470cSBruce Richardson /*
874a9de470cSBruce Richardson * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
875a9de470cSBruce Richardson * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension
876a9de470cSBruce Richardson * and contraction.
877a9de470cSBruce Richardson *
878a9de470cSBruce Richardson * */
879a9de470cSBruce Richardson
880a9de470cSBruce Richardson int32_t
test12(void)881a9de470cSBruce Richardson test12(void)
882a9de470cSBruce Richardson {
883a9de470cSBruce Richardson xmm_t ipx4;
884a9de470cSBruce Richardson uint32_t hop[4];
885a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
886a9de470cSBruce Richardson struct rte_lpm_config config;
887a9de470cSBruce Richardson
888a9de470cSBruce Richardson config.max_rules = MAX_RULES;
889a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
890a9de470cSBruce Richardson config.flags = 0;
891a9de470cSBruce Richardson uint32_t ip, i, next_hop_add, next_hop_return;
892a9de470cSBruce Richardson uint8_t depth;
893a9de470cSBruce Richardson int32_t status = 0;
894a9de470cSBruce Richardson
895a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
896a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
897a9de470cSBruce Richardson
8980c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
899a9de470cSBruce Richardson depth = 32;
900a9de470cSBruce Richardson next_hop_add = 100;
901a9de470cSBruce Richardson
902a9de470cSBruce Richardson for (i = 0; i < 1000; i++) {
903a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add);
904a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
905a9de470cSBruce Richardson
906a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
907a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) &&
908a9de470cSBruce Richardson (next_hop_return == next_hop_add));
909a9de470cSBruce Richardson
910a9de470cSBruce Richardson ipx4 = vect_set_epi32(ip, ip + 1, ip, ip - 1);
911a9de470cSBruce Richardson rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
912a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
913a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[1] == next_hop_add);
914a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
915a9de470cSBruce Richardson TEST_LPM_ASSERT(hop[3] == next_hop_add);
916a9de470cSBruce Richardson
917a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
918a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
919a9de470cSBruce Richardson
920a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
921a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
922a9de470cSBruce Richardson }
923a9de470cSBruce Richardson
924a9de470cSBruce Richardson rte_lpm_free(lpm);
925a9de470cSBruce Richardson
926a9de470cSBruce Richardson return PASS;
927a9de470cSBruce Richardson }
928a9de470cSBruce Richardson
929a9de470cSBruce Richardson /*
930a9de470cSBruce Richardson * Add a rule to tbl24, lookup (hit), then add a rule that will extend this
931a9de470cSBruce Richardson * tbl24 entry, lookup (hit). delete the rule that caused the tbl24 extension,
932a9de470cSBruce Richardson * lookup (miss) and repeat for loop of 1000 times. This will check tbl8
933a9de470cSBruce Richardson * extension and contraction.
934a9de470cSBruce Richardson *
935a9de470cSBruce Richardson * */
936a9de470cSBruce Richardson
937a9de470cSBruce Richardson int32_t
test13(void)938a9de470cSBruce Richardson test13(void)
939a9de470cSBruce Richardson {
940a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
941a9de470cSBruce Richardson struct rte_lpm_config config;
942a9de470cSBruce Richardson
943a9de470cSBruce Richardson config.max_rules = MAX_RULES;
944a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
945a9de470cSBruce Richardson config.flags = 0;
946a9de470cSBruce Richardson uint32_t ip, i, next_hop_add_1, next_hop_add_2, next_hop_return;
947a9de470cSBruce Richardson uint8_t depth;
948a9de470cSBruce Richardson int32_t status = 0;
949a9de470cSBruce Richardson
950a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
951a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
952a9de470cSBruce Richardson
9530c9da755SDavid Marchand ip = RTE_IPV4(128, 0, 0, 0);
954a9de470cSBruce Richardson depth = 24;
955a9de470cSBruce Richardson next_hop_add_1 = 100;
956a9de470cSBruce Richardson
957a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add_1);
958a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
959a9de470cSBruce Richardson
960a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
961a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
962a9de470cSBruce Richardson
963a9de470cSBruce Richardson depth = 32;
964a9de470cSBruce Richardson next_hop_add_2 = 101;
965a9de470cSBruce Richardson
966a9de470cSBruce Richardson for (i = 0; i < 1000; i++) {
967a9de470cSBruce Richardson status = rte_lpm_add(lpm, ip, depth, next_hop_add_2);
968a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
969a9de470cSBruce Richardson
970a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
971a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) &&
972a9de470cSBruce Richardson (next_hop_return == next_hop_add_2));
973a9de470cSBruce Richardson
974a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
975a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
976a9de470cSBruce Richardson
977a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
978a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) &&
979a9de470cSBruce Richardson (next_hop_return == next_hop_add_1));
980a9de470cSBruce Richardson }
981a9de470cSBruce Richardson
982a9de470cSBruce Richardson depth = 24;
983a9de470cSBruce Richardson
984a9de470cSBruce Richardson status = rte_lpm_delete(lpm, ip, depth);
985a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
986a9de470cSBruce Richardson
987a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
988a9de470cSBruce Richardson TEST_LPM_ASSERT(status == -ENOENT);
989a9de470cSBruce Richardson
990a9de470cSBruce Richardson rte_lpm_free(lpm);
991a9de470cSBruce Richardson
992a9de470cSBruce Richardson return PASS;
993a9de470cSBruce Richardson }
994a9de470cSBruce Richardson
995a9de470cSBruce Richardson /*
996f942122fSRuifeng Wang * For TBL8 extension exhaustion. Add 512 rules that require a tbl8 extension.
997a9de470cSBruce Richardson * No more tbl8 extensions will be allowed. Now add one more rule that required
998a9de470cSBruce Richardson * a tbl8 extension and get fail.
999a9de470cSBruce Richardson * */
1000a9de470cSBruce Richardson int32_t
test14(void)1001a9de470cSBruce Richardson test14(void)
1002a9de470cSBruce Richardson {
1003a9de470cSBruce Richardson
1004a9de470cSBruce Richardson /* We only use depth = 32 in the loop below so we must make sure
1005a9de470cSBruce Richardson * that we have enough storage for all rules at that depth*/
1006a9de470cSBruce Richardson
1007a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
1008a9de470cSBruce Richardson struct rte_lpm_config config;
1009a9de470cSBruce Richardson
1010a9de470cSBruce Richardson config.max_rules = 256 * 32;
1011f942122fSRuifeng Wang config.number_tbl8s = 512;
1012a9de470cSBruce Richardson config.flags = 0;
1013f942122fSRuifeng Wang uint32_t ip, next_hop_base, next_hop_return;
1014a9de470cSBruce Richardson uint8_t depth;
1015a9de470cSBruce Richardson int32_t status = 0;
1016f942122fSRuifeng Wang xmm_t ipx4;
1017f942122fSRuifeng Wang uint32_t hop[4];
1018a9de470cSBruce Richardson
1019a9de470cSBruce Richardson /* Add enough space for 256 rules for every depth */
1020a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1021a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
1022a9de470cSBruce Richardson
1023a9de470cSBruce Richardson depth = 32;
1024f942122fSRuifeng Wang next_hop_base = 100;
10250c9da755SDavid Marchand ip = RTE_IPV4(0, 0, 0, 0);
1026a9de470cSBruce Richardson
1027a9de470cSBruce Richardson /* Add 256 rules that require a tbl8 extension */
1028f942122fSRuifeng Wang for (; ip <= RTE_IPV4(0, 1, 255, 0); ip += 256) {
1029f942122fSRuifeng Wang status = rte_lpm_add(lpm, ip, depth, next_hop_base + ip);
1030a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
1031a9de470cSBruce Richardson
1032a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip, &next_hop_return);
1033a9de470cSBruce Richardson TEST_LPM_ASSERT((status == 0) &&
1034f942122fSRuifeng Wang (next_hop_return == next_hop_base + ip));
1035f942122fSRuifeng Wang
1036f942122fSRuifeng Wang ipx4 = vect_set_epi32(ip + 3, ip + 2, ip + 1, ip);
1037f942122fSRuifeng Wang rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
1038f942122fSRuifeng Wang TEST_LPM_ASSERT(hop[0] == next_hop_base + ip);
1039f942122fSRuifeng Wang TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
1040f942122fSRuifeng Wang TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
1041f942122fSRuifeng Wang TEST_LPM_ASSERT(hop[3] == UINT32_MAX);
1042a9de470cSBruce Richardson }
1043a9de470cSBruce Richardson
1044a9de470cSBruce Richardson /* All tbl8 extensions have been used above. Try to add one more and
1045a9de470cSBruce Richardson * we get a fail */
10460c9da755SDavid Marchand ip = RTE_IPV4(1, 0, 0, 0);
1047a9de470cSBruce Richardson depth = 32;
1048a9de470cSBruce Richardson
1049f942122fSRuifeng Wang status = rte_lpm_add(lpm, ip, depth, next_hop_base + ip);
1050a9de470cSBruce Richardson TEST_LPM_ASSERT(status < 0);
1051a9de470cSBruce Richardson
1052a9de470cSBruce Richardson rte_lpm_free(lpm);
1053a9de470cSBruce Richardson
1054a9de470cSBruce Richardson return PASS;
1055a9de470cSBruce Richardson }
1056a9de470cSBruce Richardson
1057a9de470cSBruce Richardson /*
1058a9de470cSBruce Richardson * Sequence of operations for find existing lpm table
1059a9de470cSBruce Richardson *
1060a9de470cSBruce Richardson * - create table
1061a9de470cSBruce Richardson * - find existing table: hit
1062a9de470cSBruce Richardson * - find non-existing table: miss
1063a9de470cSBruce Richardson *
1064a9de470cSBruce Richardson */
1065a9de470cSBruce Richardson int32_t
test15(void)1066a9de470cSBruce Richardson test15(void)
1067a9de470cSBruce Richardson {
1068a9de470cSBruce Richardson struct rte_lpm *lpm = NULL, *result = NULL;
1069a9de470cSBruce Richardson struct rte_lpm_config config;
1070a9de470cSBruce Richardson
1071a9de470cSBruce Richardson config.max_rules = 256 * 32;
1072a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
1073a9de470cSBruce Richardson config.flags = 0;
1074a9de470cSBruce Richardson
1075a9de470cSBruce Richardson /* Create lpm */
1076a9de470cSBruce Richardson lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, &config);
1077a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
1078a9de470cSBruce Richardson
1079a9de470cSBruce Richardson /* Try to find existing lpm */
1080a9de470cSBruce Richardson result = rte_lpm_find_existing("lpm_find_existing");
1081a9de470cSBruce Richardson TEST_LPM_ASSERT(result == lpm);
1082a9de470cSBruce Richardson
1083a9de470cSBruce Richardson /* Try to find non-existing lpm */
1084a9de470cSBruce Richardson result = rte_lpm_find_existing("lpm_find_non_existing");
1085a9de470cSBruce Richardson TEST_LPM_ASSERT(result == NULL);
1086a9de470cSBruce Richardson
1087a9de470cSBruce Richardson /* Cleanup. */
1088a9de470cSBruce Richardson rte_lpm_delete_all(lpm);
1089a9de470cSBruce Richardson rte_lpm_free(lpm);
1090a9de470cSBruce Richardson
1091a9de470cSBruce Richardson return PASS;
1092a9de470cSBruce Richardson }
1093a9de470cSBruce Richardson
1094a9de470cSBruce Richardson /*
1095a9de470cSBruce Richardson * test failure condition of overloading the tbl8 so no more will fit
1096a9de470cSBruce Richardson * Check we get an error return value in that case
1097a9de470cSBruce Richardson */
1098a9de470cSBruce Richardson int32_t
test16(void)1099a9de470cSBruce Richardson test16(void)
1100a9de470cSBruce Richardson {
1101a9de470cSBruce Richardson uint32_t ip;
1102a9de470cSBruce Richardson struct rte_lpm_config config;
1103a9de470cSBruce Richardson
1104a9de470cSBruce Richardson config.max_rules = 256 * 32;
1105a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
1106a9de470cSBruce Richardson config.flags = 0;
1107a9de470cSBruce Richardson struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1108a9de470cSBruce Richardson
1109a9de470cSBruce Richardson /* ip loops through all possibilities for top 24 bits of address */
1110a9de470cSBruce Richardson for (ip = 0; ip < 0xFFFFFF; ip++) {
1111a9de470cSBruce Richardson /* add an entry within a different tbl8 each time, since
1112a9de470cSBruce Richardson * depth >24 and the top 24 bits are different */
1113a9de470cSBruce Richardson if (rte_lpm_add(lpm, (ip << 8) + 0xF0, 30, 0) < 0)
1114a9de470cSBruce Richardson break;
1115a9de470cSBruce Richardson }
1116a9de470cSBruce Richardson
1117a9de470cSBruce Richardson if (ip != NUMBER_TBL8S) {
1118a9de470cSBruce Richardson printf("Error, unexpected failure with filling tbl8 groups\n");
1119a9de470cSBruce Richardson printf("Failed after %u additions, expected after %u\n",
1120a9de470cSBruce Richardson (unsigned)ip, (unsigned)NUMBER_TBL8S);
1121a9de470cSBruce Richardson }
1122a9de470cSBruce Richardson
1123a9de470cSBruce Richardson rte_lpm_free(lpm);
1124a9de470cSBruce Richardson return 0;
1125a9de470cSBruce Richardson }
1126a9de470cSBruce Richardson
1127a9de470cSBruce Richardson /*
1128a9de470cSBruce Richardson * Test for overwriting of tbl8:
1129a9de470cSBruce Richardson * - add rule /32 and lookup
1130a9de470cSBruce Richardson * - add new rule /24 and lookup
1131a9de470cSBruce Richardson * - add third rule /25 and lookup
1132a9de470cSBruce Richardson * - lookup /32 and /24 rule to ensure the table has not been overwritten.
1133a9de470cSBruce Richardson */
1134a9de470cSBruce Richardson int32_t
test17(void)1135a9de470cSBruce Richardson test17(void)
1136a9de470cSBruce Richardson {
1137a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
1138a9de470cSBruce Richardson struct rte_lpm_config config;
1139a9de470cSBruce Richardson
1140a9de470cSBruce Richardson config.max_rules = MAX_RULES;
1141a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
1142a9de470cSBruce Richardson config.flags = 0;
11430c9da755SDavid Marchand const uint32_t ip_10_32 = RTE_IPV4(10, 10, 10, 2);
11440c9da755SDavid Marchand const uint32_t ip_10_24 = RTE_IPV4(10, 10, 10, 0);
11450c9da755SDavid Marchand const uint32_t ip_20_25 = RTE_IPV4(10, 10, 20, 2);
1146a9de470cSBruce Richardson const uint8_t d_ip_10_32 = 32,
1147a9de470cSBruce Richardson d_ip_10_24 = 24,
1148a9de470cSBruce Richardson d_ip_20_25 = 25;
1149a9de470cSBruce Richardson const uint32_t next_hop_ip_10_32 = 100,
1150a9de470cSBruce Richardson next_hop_ip_10_24 = 105,
1151a9de470cSBruce Richardson next_hop_ip_20_25 = 111;
1152a9de470cSBruce Richardson uint32_t next_hop_return = 0;
1153a9de470cSBruce Richardson int32_t status = 0;
1154a9de470cSBruce Richardson
1155a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1156a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
1157a9de470cSBruce Richardson
1158a9de470cSBruce Richardson if ((status = rte_lpm_add(lpm, ip_10_32, d_ip_10_32,
1159a9de470cSBruce Richardson next_hop_ip_10_32)) < 0)
1160a9de470cSBruce Richardson return -1;
1161a9de470cSBruce Richardson
1162a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
1163a9de470cSBruce Richardson uint32_t test_hop_10_32 = next_hop_return;
1164a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
1165a9de470cSBruce Richardson TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1166a9de470cSBruce Richardson
1167a9de470cSBruce Richardson if ((status = rte_lpm_add(lpm, ip_10_24, d_ip_10_24,
1168a9de470cSBruce Richardson next_hop_ip_10_24)) < 0)
1169a9de470cSBruce Richardson return -1;
1170a9de470cSBruce Richardson
1171a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
1172a9de470cSBruce Richardson uint32_t test_hop_10_24 = next_hop_return;
1173a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
1174a9de470cSBruce Richardson TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1175a9de470cSBruce Richardson
1176a9de470cSBruce Richardson if ((status = rte_lpm_add(lpm, ip_20_25, d_ip_20_25,
1177a9de470cSBruce Richardson next_hop_ip_20_25)) < 0)
1178a9de470cSBruce Richardson return -1;
1179a9de470cSBruce Richardson
1180a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip_20_25, &next_hop_return);
1181a9de470cSBruce Richardson uint32_t test_hop_20_25 = next_hop_return;
1182a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
1183a9de470cSBruce Richardson TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
1184a9de470cSBruce Richardson
1185a9de470cSBruce Richardson if (test_hop_10_32 == test_hop_10_24) {
1186a9de470cSBruce Richardson printf("Next hop return equal\n");
1187a9de470cSBruce Richardson return -1;
1188a9de470cSBruce Richardson }
1189a9de470cSBruce Richardson
1190a9de470cSBruce Richardson if (test_hop_10_24 == test_hop_20_25) {
1191a9de470cSBruce Richardson printf("Next hop return equal\n");
1192a9de470cSBruce Richardson return -1;
1193a9de470cSBruce Richardson }
1194a9de470cSBruce Richardson
1195a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
1196a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
1197a9de470cSBruce Richardson TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1198a9de470cSBruce Richardson
1199a9de470cSBruce Richardson status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
1200a9de470cSBruce Richardson TEST_LPM_ASSERT(status == 0);
1201a9de470cSBruce Richardson TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1202a9de470cSBruce Richardson
1203a9de470cSBruce Richardson rte_lpm_free(lpm);
1204a9de470cSBruce Richardson
1205a9de470cSBruce Richardson return PASS;
1206a9de470cSBruce Richardson }
1207a9de470cSBruce Richardson
1208a9de470cSBruce Richardson /*
1209a9de470cSBruce Richardson * Test for recycle of tbl8
1210a9de470cSBruce Richardson * - step 1: add a rule with depth=28 (> 24)
1211a9de470cSBruce Richardson * - step 2: add a rule with same 24-bit prefix and depth=23 (< 24)
1212a9de470cSBruce Richardson * - step 3: delete the first rule
1213a9de470cSBruce Richardson * - step 4: check tbl8 is freed
1214a9de470cSBruce Richardson * - step 5: add a rule same as the first one (depth=28)
1215a9de470cSBruce Richardson * - step 6: check same tbl8 is allocated
1216a9de470cSBruce Richardson * - step 7: add a rule with same 24-bit prefix and depth=24
1217a9de470cSBruce Richardson * - step 8: delete the rule (depth=28) added in step 5
1218a9de470cSBruce Richardson * - step 9: check tbl8 is freed
1219a9de470cSBruce Richardson * - step 10: add a rule with same 24-bit prefix and depth = 28
1220a9de470cSBruce Richardson * - setp 11: check same tbl8 is allocated again
1221a9de470cSBruce Richardson */
1222a9de470cSBruce Richardson int32_t
test18(void)1223a9de470cSBruce Richardson test18(void)
1224a9de470cSBruce Richardson {
1225a9de470cSBruce Richardson #define group_idx next_hop
1226a9de470cSBruce Richardson struct rte_lpm *lpm = NULL;
1227a9de470cSBruce Richardson struct rte_lpm_config config;
1228a9de470cSBruce Richardson uint32_t ip, next_hop;
1229a9de470cSBruce Richardson uint8_t depth;
1230a9de470cSBruce Richardson uint32_t tbl8_group_index;
1231a9de470cSBruce Richardson
1232a9de470cSBruce Richardson config.max_rules = MAX_RULES;
1233a9de470cSBruce Richardson config.number_tbl8s = NUMBER_TBL8S;
1234a9de470cSBruce Richardson config.flags = 0;
1235a9de470cSBruce Richardson
1236a9de470cSBruce Richardson lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1237a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm != NULL);
1238a9de470cSBruce Richardson
12390c9da755SDavid Marchand ip = RTE_IPV4(192, 168, 100, 100);
1240a9de470cSBruce Richardson depth = 28;
1241a9de470cSBruce Richardson next_hop = 1;
1242a9de470cSBruce Richardson rte_lpm_add(lpm, ip, depth, next_hop);
1243a9de470cSBruce Richardson
1244a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
1245a9de470cSBruce Richardson tbl8_group_index = lpm->tbl24[ip>>8].group_idx;
1246a9de470cSBruce Richardson
1247a9de470cSBruce Richardson depth = 23;
1248a9de470cSBruce Richardson next_hop = 2;
1249a9de470cSBruce Richardson rte_lpm_add(lpm, ip, depth, next_hop);
1250a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
1251a9de470cSBruce Richardson
1252a9de470cSBruce Richardson depth = 28;
1253a9de470cSBruce Richardson rte_lpm_delete(lpm, ip, depth);
1254a9de470cSBruce Richardson
1255a9de470cSBruce Richardson TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid_group);
1256a9de470cSBruce Richardson
1257a9de470cSBruce Richardson next_hop = 3;
1258a9de470cSBruce Richardson rte_lpm_add(lpm, ip, depth, next_hop);
1259a9de470cSBruce Richardson
1260a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
1261a9de470cSBruce Richardson TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl24[ip>>8].group_idx);
1262a9de470cSBruce Richardson
1263a9de470cSBruce Richardson depth = 24;
1264a9de470cSBruce Richardson next_hop = 4;
1265a9de470cSBruce Richardson rte_lpm_add(lpm, ip, depth, next_hop);
1266a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
1267a9de470cSBruce Richardson
1268a9de470cSBruce Richardson depth = 28;
1269a9de470cSBruce Richardson rte_lpm_delete(lpm, ip, depth);
1270a9de470cSBruce Richardson
1271a9de470cSBruce Richardson TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid_group);
1272a9de470cSBruce Richardson
1273a9de470cSBruce Richardson next_hop = 5;
1274a9de470cSBruce Richardson rte_lpm_add(lpm, ip, depth, next_hop);
1275a9de470cSBruce Richardson
1276a9de470cSBruce Richardson TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
1277a9de470cSBruce Richardson TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl24[ip>>8].group_idx);
1278a9de470cSBruce Richardson
1279a9de470cSBruce Richardson rte_lpm_free(lpm);
1280a9de470cSBruce Richardson #undef group_idx
1281a9de470cSBruce Richardson return PASS;
1282a9de470cSBruce Richardson }
1283a9de470cSBruce Richardson
1284a9de470cSBruce Richardson /*
12856823fad3SRuifeng Wang * rte_lpm_rcu_qsbr_add positive and negative tests.
12866823fad3SRuifeng Wang * - Add RCU QSBR variable to LPM
12876823fad3SRuifeng Wang * - Add another RCU QSBR variable to LPM
12886823fad3SRuifeng Wang * - Check returns
12896823fad3SRuifeng Wang */
12906823fad3SRuifeng Wang int32_t
test19(void)12916823fad3SRuifeng Wang test19(void)
12926823fad3SRuifeng Wang {
12936823fad3SRuifeng Wang struct rte_lpm *lpm = NULL;
12946823fad3SRuifeng Wang struct rte_lpm_config config;
12956823fad3SRuifeng Wang size_t sz;
12966823fad3SRuifeng Wang struct rte_rcu_qsbr *qsv;
12976823fad3SRuifeng Wang struct rte_rcu_qsbr *qsv2;
12986823fad3SRuifeng Wang int32_t status;
12996823fad3SRuifeng Wang struct rte_lpm_rcu_config rcu_cfg = {0};
13006823fad3SRuifeng Wang
13016823fad3SRuifeng Wang config.max_rules = MAX_RULES;
13026823fad3SRuifeng Wang config.number_tbl8s = NUMBER_TBL8S;
13036823fad3SRuifeng Wang config.flags = 0;
13046823fad3SRuifeng Wang
13056823fad3SRuifeng Wang lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
13066823fad3SRuifeng Wang TEST_LPM_ASSERT(lpm != NULL);
13076823fad3SRuifeng Wang
13086823fad3SRuifeng Wang /* Create RCU QSBR variable */
13096823fad3SRuifeng Wang sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
13106823fad3SRuifeng Wang qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
13116823fad3SRuifeng Wang RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
13126823fad3SRuifeng Wang TEST_LPM_ASSERT(qsv != NULL);
13136823fad3SRuifeng Wang
13146823fad3SRuifeng Wang status = rte_rcu_qsbr_init(qsv, RTE_MAX_LCORE);
13156823fad3SRuifeng Wang TEST_LPM_ASSERT(status == 0);
13166823fad3SRuifeng Wang
13176823fad3SRuifeng Wang rcu_cfg.v = qsv;
13186823fad3SRuifeng Wang /* Invalid QSBR mode */
13196823fad3SRuifeng Wang rcu_cfg.mode = 2;
13200f392d91SRuifeng Wang status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
13216823fad3SRuifeng Wang TEST_LPM_ASSERT(status != 0);
13226823fad3SRuifeng Wang
13236823fad3SRuifeng Wang rcu_cfg.mode = RTE_LPM_QSBR_MODE_DQ;
13246823fad3SRuifeng Wang /* Attach RCU QSBR to LPM table */
13250f392d91SRuifeng Wang status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
13266823fad3SRuifeng Wang TEST_LPM_ASSERT(status == 0);
13276823fad3SRuifeng Wang
13286823fad3SRuifeng Wang /* Create and attach another RCU QSBR to LPM table */
13296823fad3SRuifeng Wang qsv2 = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
13306823fad3SRuifeng Wang RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
13316823fad3SRuifeng Wang TEST_LPM_ASSERT(qsv2 != NULL);
13326823fad3SRuifeng Wang
13336823fad3SRuifeng Wang rcu_cfg.v = qsv2;
13346823fad3SRuifeng Wang rcu_cfg.mode = RTE_LPM_QSBR_MODE_SYNC;
13350f392d91SRuifeng Wang status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
13366823fad3SRuifeng Wang TEST_LPM_ASSERT(status != 0);
13376823fad3SRuifeng Wang
13386823fad3SRuifeng Wang rte_lpm_free(lpm);
13396823fad3SRuifeng Wang rte_free(qsv);
13406823fad3SRuifeng Wang rte_free(qsv2);
13416823fad3SRuifeng Wang
13426823fad3SRuifeng Wang return PASS;
13436823fad3SRuifeng Wang }
13446823fad3SRuifeng Wang
13456823fad3SRuifeng Wang /*
13466823fad3SRuifeng Wang * rte_lpm_rcu_qsbr_add DQ mode functional test.
13476823fad3SRuifeng Wang * Reader and writer are in the same thread in this test.
13486823fad3SRuifeng Wang * - Create LPM which supports 1 tbl8 group at max
13496823fad3SRuifeng Wang * - Add RCU QSBR variable to LPM
13506823fad3SRuifeng Wang * - Add a rule with depth=28 (> 24)
13516823fad3SRuifeng Wang * - Register a reader thread (not a real thread)
13526823fad3SRuifeng Wang * - Reader lookup existing rule
13536823fad3SRuifeng Wang * - Writer delete the rule
13546823fad3SRuifeng Wang * - Reader lookup the rule
13556823fad3SRuifeng Wang * - Writer re-add the rule (no available tbl8 group)
13566823fad3SRuifeng Wang * - Reader report quiescent state and unregister
13576823fad3SRuifeng Wang * - Writer re-add the rule
13586823fad3SRuifeng Wang * - Reader lookup the rule
13596823fad3SRuifeng Wang */
13606823fad3SRuifeng Wang int32_t
test20(void)13616823fad3SRuifeng Wang test20(void)
13626823fad3SRuifeng Wang {
13636823fad3SRuifeng Wang struct rte_lpm *lpm = NULL;
13646823fad3SRuifeng Wang struct rte_lpm_config config;
13656823fad3SRuifeng Wang size_t sz;
13666823fad3SRuifeng Wang struct rte_rcu_qsbr *qsv;
13676823fad3SRuifeng Wang int32_t status;
13686823fad3SRuifeng Wang uint32_t ip, next_hop, next_hop_return;
13696823fad3SRuifeng Wang uint8_t depth;
13706823fad3SRuifeng Wang struct rte_lpm_rcu_config rcu_cfg = {0};
13716823fad3SRuifeng Wang
13726823fad3SRuifeng Wang config.max_rules = MAX_RULES;
13736823fad3SRuifeng Wang config.number_tbl8s = 1;
13746823fad3SRuifeng Wang config.flags = 0;
13756823fad3SRuifeng Wang
13766823fad3SRuifeng Wang lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
13776823fad3SRuifeng Wang TEST_LPM_ASSERT(lpm != NULL);
13786823fad3SRuifeng Wang
13796823fad3SRuifeng Wang /* Create RCU QSBR variable */
13806823fad3SRuifeng Wang sz = rte_rcu_qsbr_get_memsize(1);
13816823fad3SRuifeng Wang qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
13826823fad3SRuifeng Wang RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
13836823fad3SRuifeng Wang TEST_LPM_ASSERT(qsv != NULL);
13846823fad3SRuifeng Wang
13856823fad3SRuifeng Wang status = rte_rcu_qsbr_init(qsv, 1);
13866823fad3SRuifeng Wang TEST_LPM_ASSERT(status == 0);
13876823fad3SRuifeng Wang
13886823fad3SRuifeng Wang rcu_cfg.v = qsv;
13896823fad3SRuifeng Wang rcu_cfg.mode = RTE_LPM_QSBR_MODE_DQ;
13906823fad3SRuifeng Wang /* Attach RCU QSBR to LPM table */
13910f392d91SRuifeng Wang status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
13926823fad3SRuifeng Wang TEST_LPM_ASSERT(status == 0);
13936823fad3SRuifeng Wang
13946823fad3SRuifeng Wang ip = RTE_IPV4(192, 0, 2, 100);
13956823fad3SRuifeng Wang depth = 28;
13966823fad3SRuifeng Wang next_hop = 1;
13976823fad3SRuifeng Wang status = rte_lpm_add(lpm, ip, depth, next_hop);
13986823fad3SRuifeng Wang TEST_LPM_ASSERT(status == 0);
13996823fad3SRuifeng Wang TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
14006823fad3SRuifeng Wang
14016823fad3SRuifeng Wang /* Register pseudo reader */
14026823fad3SRuifeng Wang status = rte_rcu_qsbr_thread_register(qsv, 0);
14036823fad3SRuifeng Wang TEST_LPM_ASSERT(status == 0);
14046823fad3SRuifeng Wang rte_rcu_qsbr_thread_online(qsv, 0);
14056823fad3SRuifeng Wang
14066823fad3SRuifeng Wang status = rte_lpm_lookup(lpm, ip, &next_hop_return);
14076823fad3SRuifeng Wang TEST_LPM_ASSERT(status == 0);
14086823fad3SRuifeng Wang TEST_LPM_ASSERT(next_hop_return == next_hop);
14096823fad3SRuifeng Wang
14106823fad3SRuifeng Wang /* Writer update */
14116823fad3SRuifeng Wang status = rte_lpm_delete(lpm, ip, depth);
14126823fad3SRuifeng Wang TEST_LPM_ASSERT(status == 0);
14136823fad3SRuifeng Wang TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid);
14146823fad3SRuifeng Wang
14156823fad3SRuifeng Wang status = rte_lpm_lookup(lpm, ip, &next_hop_return);
14166823fad3SRuifeng Wang TEST_LPM_ASSERT(status != 0);
14176823fad3SRuifeng Wang
14186823fad3SRuifeng Wang status = rte_lpm_add(lpm, ip, depth, next_hop);
14196823fad3SRuifeng Wang TEST_LPM_ASSERT(status != 0);
14206823fad3SRuifeng Wang
14216823fad3SRuifeng Wang /* Reader quiescent */
14226823fad3SRuifeng Wang rte_rcu_qsbr_quiescent(qsv, 0);
14236823fad3SRuifeng Wang
14246823fad3SRuifeng Wang status = rte_lpm_add(lpm, ip, depth, next_hop);
14256823fad3SRuifeng Wang TEST_LPM_ASSERT(status == 0);
14266823fad3SRuifeng Wang
14276823fad3SRuifeng Wang rte_rcu_qsbr_thread_offline(qsv, 0);
14286823fad3SRuifeng Wang status = rte_rcu_qsbr_thread_unregister(qsv, 0);
14296823fad3SRuifeng Wang TEST_LPM_ASSERT(status == 0);
14306823fad3SRuifeng Wang
14316823fad3SRuifeng Wang status = rte_lpm_lookup(lpm, ip, &next_hop_return);
14326823fad3SRuifeng Wang TEST_LPM_ASSERT(status == 0);
14336823fad3SRuifeng Wang TEST_LPM_ASSERT(next_hop_return == next_hop);
14346823fad3SRuifeng Wang
14356823fad3SRuifeng Wang rte_lpm_free(lpm);
14366823fad3SRuifeng Wang rte_free(qsv);
14376823fad3SRuifeng Wang
14386823fad3SRuifeng Wang return PASS;
14396823fad3SRuifeng Wang }
14406823fad3SRuifeng Wang
14416823fad3SRuifeng Wang static struct rte_lpm *g_lpm;
14426823fad3SRuifeng Wang static struct rte_rcu_qsbr *g_v;
14436823fad3SRuifeng Wang static uint32_t g_ip = RTE_IPV4(192, 0, 2, 100);
14446823fad3SRuifeng Wang static volatile uint8_t writer_done;
14456823fad3SRuifeng Wang /* Report quiescent state interval every 1024 lookups. Larger critical
14466823fad3SRuifeng Wang * sections in reader will result in writer polling multiple times.
14476823fad3SRuifeng Wang */
14486823fad3SRuifeng Wang #define QSBR_REPORTING_INTERVAL 1024
14496823fad3SRuifeng Wang #define WRITER_ITERATIONS 512
14506823fad3SRuifeng Wang
14516823fad3SRuifeng Wang /*
14526823fad3SRuifeng Wang * Reader thread using rte_lpm data structure with RCU.
14536823fad3SRuifeng Wang */
14546823fad3SRuifeng Wang static int
test_lpm_rcu_qsbr_reader(void * arg)14556823fad3SRuifeng Wang test_lpm_rcu_qsbr_reader(void *arg)
14566823fad3SRuifeng Wang {
14576823fad3SRuifeng Wang int i;
14586823fad3SRuifeng Wang uint32_t next_hop_return = 0;
14596823fad3SRuifeng Wang
14606823fad3SRuifeng Wang RTE_SET_USED(arg);
14616823fad3SRuifeng Wang /* Register this thread to report quiescent state */
14626823fad3SRuifeng Wang rte_rcu_qsbr_thread_register(g_v, 0);
14636823fad3SRuifeng Wang rte_rcu_qsbr_thread_online(g_v, 0);
14646823fad3SRuifeng Wang
14656823fad3SRuifeng Wang do {
14666823fad3SRuifeng Wang for (i = 0; i < QSBR_REPORTING_INTERVAL; i++)
14676823fad3SRuifeng Wang rte_lpm_lookup(g_lpm, g_ip, &next_hop_return);
14686823fad3SRuifeng Wang
14696823fad3SRuifeng Wang /* Update quiescent state */
14706823fad3SRuifeng Wang rte_rcu_qsbr_quiescent(g_v, 0);
14716823fad3SRuifeng Wang } while (!writer_done);
14726823fad3SRuifeng Wang
14736823fad3SRuifeng Wang rte_rcu_qsbr_thread_offline(g_v, 0);
14746823fad3SRuifeng Wang rte_rcu_qsbr_thread_unregister(g_v, 0);
14756823fad3SRuifeng Wang
14766823fad3SRuifeng Wang return 0;
14776823fad3SRuifeng Wang }
14786823fad3SRuifeng Wang
14796823fad3SRuifeng Wang /*
14806823fad3SRuifeng Wang * rte_lpm_rcu_qsbr_add sync mode functional test.
14816823fad3SRuifeng Wang * 1 Reader and 1 writer. They cannot be in the same thread in this test.
14826823fad3SRuifeng Wang * - Create LPM which supports 1 tbl8 group at max
14836823fad3SRuifeng Wang * - Add RCU QSBR variable with sync mode to LPM
14846823fad3SRuifeng Wang * - Register a reader thread. Reader keeps looking up a specific rule.
14856823fad3SRuifeng Wang * - Writer keeps adding and deleting a specific rule with depth=28 (> 24)
14866823fad3SRuifeng Wang */
14876823fad3SRuifeng Wang int32_t
test21(void)14886823fad3SRuifeng Wang test21(void)
14896823fad3SRuifeng Wang {
14906823fad3SRuifeng Wang struct rte_lpm_config config;
14916823fad3SRuifeng Wang size_t sz;
14926823fad3SRuifeng Wang int32_t status;
14936823fad3SRuifeng Wang uint32_t i, next_hop;
14946823fad3SRuifeng Wang uint8_t depth;
14956823fad3SRuifeng Wang struct rte_lpm_rcu_config rcu_cfg = {0};
14966823fad3SRuifeng Wang
14976823fad3SRuifeng Wang if (rte_lcore_count() < 2) {
14986823fad3SRuifeng Wang printf("Not enough cores for %s, expecting at least 2\n",
14996823fad3SRuifeng Wang __func__);
15006823fad3SRuifeng Wang return TEST_SKIPPED;
15016823fad3SRuifeng Wang }
15026823fad3SRuifeng Wang
15036823fad3SRuifeng Wang config.max_rules = MAX_RULES;
15046823fad3SRuifeng Wang config.number_tbl8s = 1;
15056823fad3SRuifeng Wang config.flags = 0;
15066823fad3SRuifeng Wang
15076823fad3SRuifeng Wang g_lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
15086823fad3SRuifeng Wang TEST_LPM_ASSERT(g_lpm != NULL);
15096823fad3SRuifeng Wang
15106823fad3SRuifeng Wang /* Create RCU QSBR variable */
15116823fad3SRuifeng Wang sz = rte_rcu_qsbr_get_memsize(1);
15126823fad3SRuifeng Wang g_v = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
15136823fad3SRuifeng Wang RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
15146823fad3SRuifeng Wang TEST_LPM_ASSERT(g_v != NULL);
15156823fad3SRuifeng Wang
15166823fad3SRuifeng Wang status = rte_rcu_qsbr_init(g_v, 1);
15176823fad3SRuifeng Wang TEST_LPM_ASSERT(status == 0);
15186823fad3SRuifeng Wang
15196823fad3SRuifeng Wang rcu_cfg.v = g_v;
15206823fad3SRuifeng Wang rcu_cfg.mode = RTE_LPM_QSBR_MODE_SYNC;
15216823fad3SRuifeng Wang /* Attach RCU QSBR to LPM table */
15220f392d91SRuifeng Wang status = rte_lpm_rcu_qsbr_add(g_lpm, &rcu_cfg);
15236823fad3SRuifeng Wang TEST_LPM_ASSERT(status == 0);
15246823fad3SRuifeng Wang
15256823fad3SRuifeng Wang writer_done = 0;
15266823fad3SRuifeng Wang /* Launch reader thread */
15276823fad3SRuifeng Wang rte_eal_remote_launch(test_lpm_rcu_qsbr_reader, NULL,
15286823fad3SRuifeng Wang rte_get_next_lcore(-1, 1, 0));
15296823fad3SRuifeng Wang
15306823fad3SRuifeng Wang depth = 28;
15316823fad3SRuifeng Wang next_hop = 1;
15326823fad3SRuifeng Wang status = rte_lpm_add(g_lpm, g_ip, depth, next_hop);
15336823fad3SRuifeng Wang if (status != 0) {
15346823fad3SRuifeng Wang printf("%s: Failed to add rule\n", __func__);
15356823fad3SRuifeng Wang goto error;
15366823fad3SRuifeng Wang }
15376823fad3SRuifeng Wang
15386823fad3SRuifeng Wang /* Writer update */
15396823fad3SRuifeng Wang for (i = 0; i < WRITER_ITERATIONS; i++) {
15406823fad3SRuifeng Wang status = rte_lpm_delete(g_lpm, g_ip, depth);
15416823fad3SRuifeng Wang if (status != 0) {
15426823fad3SRuifeng Wang printf("%s: Failed to delete rule at iteration %d\n",
15436823fad3SRuifeng Wang __func__, i);
15446823fad3SRuifeng Wang goto error;
15456823fad3SRuifeng Wang }
15466823fad3SRuifeng Wang
15476823fad3SRuifeng Wang status = rte_lpm_add(g_lpm, g_ip, depth, next_hop);
15486823fad3SRuifeng Wang if (status != 0) {
15496823fad3SRuifeng Wang printf("%s: Failed to add rule at iteration %d\n",
15506823fad3SRuifeng Wang __func__, i);
15516823fad3SRuifeng Wang goto error;
15526823fad3SRuifeng Wang }
15536823fad3SRuifeng Wang }
15546823fad3SRuifeng Wang
15556823fad3SRuifeng Wang error:
15566823fad3SRuifeng Wang writer_done = 1;
15576823fad3SRuifeng Wang /* Wait until reader exited. */
15586823fad3SRuifeng Wang rte_eal_mp_wait_lcore();
15596823fad3SRuifeng Wang
15606823fad3SRuifeng Wang rte_lpm_free(g_lpm);
15616823fad3SRuifeng Wang rte_free(g_v);
15626823fad3SRuifeng Wang
15636823fad3SRuifeng Wang return (status == 0) ? PASS : -1;
15646823fad3SRuifeng Wang }
15656823fad3SRuifeng Wang
15666823fad3SRuifeng Wang /*
1567a9de470cSBruce Richardson * Do all unit tests.
1568a9de470cSBruce Richardson */
1569a9de470cSBruce Richardson
1570a9de470cSBruce Richardson static int
test_lpm(void)1571a9de470cSBruce Richardson test_lpm(void)
1572a9de470cSBruce Richardson {
1573a9de470cSBruce Richardson unsigned i;
1574a9de470cSBruce Richardson int status, global_status = 0;
1575a9de470cSBruce Richardson
157671bdd8a1SPavan Nikhilesh for (i = 0; i < RTE_DIM(tests); i++) {
1577a9de470cSBruce Richardson status = tests[i]();
1578a9de470cSBruce Richardson if (status < 0) {
1579a9de470cSBruce Richardson printf("ERROR: LPM Test %u: FAIL\n", i);
1580a9de470cSBruce Richardson global_status = status;
1581a9de470cSBruce Richardson }
1582a9de470cSBruce Richardson }
1583a9de470cSBruce Richardson
1584a9de470cSBruce Richardson return global_status;
1585a9de470cSBruce Richardson }
1586a9de470cSBruce Richardson
1587*e0a8442cSBruce Richardson REGISTER_FAST_TEST(lpm_autotest, true, true, test_lpm);
1588