xref: /dpdk/app/test/test_ipsec_sad.c (revision 9ac91e2f7339e66658ef55b756a06b328e336fde)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4 
5 #include "test.h"
6 
7 #include <stdio.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #ifdef RTE_EXEC_ENV_WINDOWS
13 static int
14 test_ipsec_sad(void)
15 {
16 	printf("ipsec_sad not supported on Windows, skipping test\n");
17 	return TEST_SKIPPED;
18 }
19 
20 #else
21 
22 #include <rte_ipsec_sad.h>
23 #include <rte_memory.h>
24 
25 #include "test_xmmt_ops.h"
26 
27 typedef int32_t (*rte_ipsec_sad_test)(void);
28 
29 static int32_t test_create_invalid(void);
30 static int32_t test_find_existing(void);
31 static int32_t test_multiple_create(void);
32 static int32_t test_add_invalid(void);
33 static int32_t test_delete_invalid(void);
34 static int32_t test_lookup_invalid(void);
35 static int32_t test_lookup_basic(void);
36 static int32_t test_lookup_adv(void);
37 static int32_t test_lookup_order(void);
38 
39 #define MAX_SA	100000
40 #define PASS 0
41 #define SPI	0xdead	/* spi to install */
42 #define DIP	0xbeef	/* dip to install */
43 #define SIP	0xf00d	/* sip to install */
44 #define BAD	0xbad	/* some random value not installed into the table */
45 
46 /*
47  * Check that rte_ipsec_sad_create fails gracefully for incorrect user input
48  * arguments
49  */
50 int32_t
51 test_create_invalid(void)
52 {
53 	struct rte_ipsec_sad *sad = NULL;
54 	struct rte_ipsec_sad_conf config;
55 
56 	config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
57 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
58 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
59 	config.socket_id = SOCKET_ID_ANY;
60 	config.flags = 0;
61 
62 	/* name == NULL */
63 	sad = rte_ipsec_sad_create(NULL, &config);
64 	RTE_TEST_ASSERT(sad == NULL,
65 		"Call succeeded with invalid parameters\n");
66 
67 	/* max_sa for every type = 0 */
68 	config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = 0;
69 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = 0;
70 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = 0;
71 	sad = rte_ipsec_sad_create(__func__, &config);
72 	RTE_TEST_ASSERT(sad == NULL,
73 		"Call succeeded with invalid parameters\n");
74 	config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
75 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
76 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
77 
78 	/* socket_id < -1 is invalid */
79 	config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
80 	config.socket_id = -2;
81 	sad = rte_ipsec_sad_create(__func__, &config);
82 	RTE_TEST_ASSERT(sad == NULL,
83 		"Call succeeded with invalid parameters\n");
84 	config.socket_id = SOCKET_ID_ANY;
85 
86 	return TEST_SUCCESS;
87 }
88 
89 /*
90  * Test rte_ipsec_sad_find_existing()
91  * Create SAD and try to find it by it's name
92  */
93 int32_t
94 test_find_existing(void)
95 {
96 	const char *name1 = "sad_one";
97 	const char *name2 = "sad_two";
98 	struct rte_ipsec_sad *one, *two, *tmp;
99 	struct rte_ipsec_sad_conf config;
100 
101 	config.socket_id = SOCKET_ID_ANY;
102 	config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
103 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = 0;
104 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = 0;
105 	one = rte_ipsec_sad_create(name1, &config);
106 	RTE_TEST_ASSERT_NOT_NULL(one, "Failed to create SAD\n");
107 	two = rte_ipsec_sad_create(name2, &config);
108 	RTE_TEST_ASSERT_NOT_NULL(two, "Failed to create SAD\n");
109 
110 	/* Find non existing */
111 	tmp = rte_ipsec_sad_find_existing("sad_three");
112 	RTE_TEST_ASSERT(tmp == NULL,
113 		"rte_ipsec_sad_find_existing returns invalid SAD\n");
114 
115 	tmp = rte_ipsec_sad_find_existing(name1);
116 	RTE_TEST_ASSERT(tmp == one,
117 		"rte_ipsec_sad_find_existing returns invalid SAD\n");
118 
119 	tmp = rte_ipsec_sad_find_existing(name2);
120 	RTE_TEST_ASSERT(tmp == two,
121 		"rte_ipsec_sad_find_existing returns invalid SAD\n");
122 
123 	rte_ipsec_sad_destroy(one);
124 	rte_ipsec_sad_destroy(two);
125 	return TEST_SUCCESS;
126 }
127 
128 /*
129  * Create ipsec sad then delete it 10 times
130  * Use a slightly different max_sa each time
131  */
132 int32_t
133 test_multiple_create(void)
134 {
135 	int i;
136 	struct rte_ipsec_sad *sad = NULL;
137 	struct rte_ipsec_sad_conf config;
138 
139 	config.socket_id = SOCKET_ID_ANY;
140 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
141 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
142 
143 	for (i = 0; i < 10; i++) {
144 		config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA - i;
145 		sad = rte_ipsec_sad_create(__func__, &config);
146 		RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
147 		rte_ipsec_sad_destroy(sad);
148 	}
149 	return TEST_SUCCESS;
150 }
151 
152 static int32_t
153 __test_add_invalid(int ipv6, union rte_ipsec_sad_key *tuple)
154 {
155 	int status;
156 	struct rte_ipsec_sad *sad = NULL;
157 	struct rte_ipsec_sad_conf config;
158 	uint64_t tmp;
159 	void *sa = &tmp;
160 
161 	/* sad == NULL*/
162 	status = rte_ipsec_sad_add(NULL, tuple,
163 			RTE_IPSEC_SAD_SPI_DIP_SIP, sa);
164 	RTE_TEST_ASSERT(status < 0,
165 		"Call succeeded with invalid parameters\n");
166 
167 	config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
168 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
169 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
170 	config.socket_id = SOCKET_ID_ANY;
171 	config.flags = 0;
172 	if (ipv6)
173 		config.flags = RTE_IPSEC_SAD_FLAG_IPV6;
174 
175 	sad = rte_ipsec_sad_create(__func__, &config);
176 	RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
177 
178 	/* key == NULL*/
179 	status = rte_ipsec_sad_add(sad, NULL, RTE_IPSEC_SAD_SPI_DIP_SIP, sa);
180 	RTE_TEST_ASSERT(status < 0,
181 		"Call succeeded with invalid parameters\n");
182 
183 	/* len is incorrect*/
184 	status = rte_ipsec_sad_add(sad, tuple,
185 		RTE_IPSEC_SAD_SPI_DIP_SIP + 1, sa);
186 	RTE_TEST_ASSERT(status < 0,
187 		"Call succeeded with invalid parameters\n");
188 
189 	/* sa == NULL*/
190 	status = rte_ipsec_sad_add(sad, tuple,
191 		RTE_IPSEC_SAD_SPI_DIP_SIP, NULL);
192 	RTE_TEST_ASSERT(status < 0,
193 		"Call succeeded with invalid parameters\n");
194 
195 	/* sa is not aligned*/
196 	status = rte_ipsec_sad_add(sad, tuple,
197 	RTE_IPSEC_SAD_SPI_DIP_SIP, (void *)((uint8_t *)sa + 1));
198 	RTE_TEST_ASSERT(status < 0,
199 		"Call succeeded with invalid parameters\n");
200 
201 	rte_ipsec_sad_destroy(sad);
202 
203 	return TEST_SUCCESS;
204 }
205 
206 /*
207  * Check that rte_ipsec_sad_add fails gracefully
208  * for incorrect user input arguments
209  */
210 int32_t
211 test_add_invalid(void)
212 {
213 	int status;
214 	struct rte_ipsec_sadv4_key tuple_v4 = {10, 20, 30};
215 	struct rte_ipsec_sadv6_key tuple_v6 = {10,
216 		RTE_IPV6(0x1400, 0, 0, 0, 0, 0, 0, 0), RTE_IPV6(0x1e00, 0, 0, 0, 0, 0, 0, 0)};
217 
218 	status = __test_add_invalid(0, (union rte_ipsec_sad_key *)&tuple_v4);
219 	if (status != TEST_SUCCESS)
220 		return status;
221 
222 	status = __test_add_invalid(1, (union rte_ipsec_sad_key *)&tuple_v6);
223 
224 	return status;
225 
226 }
227 
228 static int32_t
229 __test_delete_invalid(int ipv6, union rte_ipsec_sad_key *tuple)
230 {
231 	int status;
232 	struct rte_ipsec_sad *sad = NULL;
233 	struct rte_ipsec_sad_conf config;
234 
235 	/* sad == NULL*/
236 	status = rte_ipsec_sad_del(NULL, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP);
237 	RTE_TEST_ASSERT(status < 0,
238 		"Call succeeded with invalid parameters\n");
239 
240 	config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
241 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
242 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
243 	config.socket_id = SOCKET_ID_ANY;
244 	config.flags = 0;
245 	if (ipv6)
246 		config.flags = RTE_IPSEC_SAD_FLAG_IPV6;
247 
248 	sad = rte_ipsec_sad_create(__func__, &config);
249 	RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
250 
251 	/* key == NULL*/
252 	status = rte_ipsec_sad_del(sad, NULL, RTE_IPSEC_SAD_SPI_DIP_SIP);
253 	RTE_TEST_ASSERT(status < 0,
254 		"Call succeeded with invalid parameters\n");
255 
256 	/* len is incorrect */
257 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP + 1);
258 	RTE_TEST_ASSERT(status < 0,
259 		"Call succeeded with invalid parameters\n");
260 
261 	rte_ipsec_sad_destroy(sad);
262 
263 	return TEST_SUCCESS;
264 }
265 
266 /*
267  * Check that rte_ipsec_sad_delete fails gracefully for incorrect user input
268  * arguments
269  */
270 int32_t
271 test_delete_invalid(void)
272 {
273 	int status;
274 	struct rte_ipsec_sadv4_key tuple_v4 = {SPI, DIP, SIP};
275 	struct rte_ipsec_sadv6_key tuple_v6 = {SPI,
276 		RTE_IPV6(0xbeef, 0, 0, 0, 0, 0, 0, 0), RTE_IPV6(0xf00d, 0, 0, 0, 0, 0, 0, 0)};
277 
278 	status = __test_delete_invalid(0, (union rte_ipsec_sad_key *)&tuple_v4);
279 	if (status != TEST_SUCCESS)
280 		return status;
281 
282 	status = __test_delete_invalid(1, (union rte_ipsec_sad_key *)&tuple_v6);
283 
284 	return status;
285 }
286 
287 static int32_t
288 __test_lookup_invalid(int ipv6, union rte_ipsec_sad_key *tuple)
289 {
290 	int status;
291 	struct rte_ipsec_sad *sad = NULL;
292 	struct rte_ipsec_sad_conf config;
293 	const union rte_ipsec_sad_key *key_arr[] = {tuple};
294 	void *sa[1];
295 
296 	status = rte_ipsec_sad_lookup(NULL, key_arr, sa, 1);
297 	RTE_TEST_ASSERT(status < 0,
298 		"Call succeeded with invalid parameters\n");
299 
300 	config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
301 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
302 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
303 	config.socket_id = SOCKET_ID_ANY;
304 	config.flags = 0;
305 	if (ipv6)
306 		config.flags = RTE_IPSEC_SAD_FLAG_IPV6;
307 
308 	sad = rte_ipsec_sad_create(__func__, &config);
309 	RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
310 
311 	status = rte_ipsec_sad_lookup(sad, NULL, sa, 1);
312 	RTE_TEST_ASSERT(status < 0,
313 		"Call succeeded with invalid parameters\n");
314 
315 	status = rte_ipsec_sad_lookup(sad, key_arr, NULL, 1);
316 	RTE_TEST_ASSERT(status < 0,
317 		"Call succeeded with invalid parameters\n");
318 
319 	rte_ipsec_sad_destroy(sad);
320 
321 	return TEST_SUCCESS;
322 }
323 
324 /*
325  * Check that rte_ipsec_sad_lookup fails gracefully for incorrect user input
326  * arguments
327  */
328 int32_t
329 test_lookup_invalid(void)
330 {
331 	int status;
332 	struct rte_ipsec_sadv4_key tuple_v4 = {10, 20, 30};
333 	struct rte_ipsec_sadv6_key tuple_v6 = {10,
334 		RTE_IPV6(0x1400, 0, 0, 0, 0, 0, 0, 0), RTE_IPV6(0x1e00, 0, 0, 0, 0, 0, 0, 0)};
335 
336 	status = __test_lookup_invalid(0,
337 			(union rte_ipsec_sad_key *)&tuple_v4);
338 	if (status != TEST_SUCCESS)
339 		return status;
340 
341 	status = __test_lookup_invalid(1,
342 			(union rte_ipsec_sad_key *)&tuple_v6);
343 
344 	return status;
345 }
346 
347 static int32_t
348 __test_lookup_basic(int ipv6, union rte_ipsec_sad_key *tuple,
349 	union rte_ipsec_sad_key *tuple_1)
350 {
351 	int status;
352 	struct rte_ipsec_sad *sad = NULL;
353 	struct rte_ipsec_sad_conf config;
354 	const union rte_ipsec_sad_key *key_arr[] = {tuple};
355 
356 	uint64_t tmp;
357 	void *sa[1];
358 
359 	config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
360 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
361 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
362 	config.socket_id = SOCKET_ID_ANY;
363 	config.flags = 0;
364 	if (ipv6)
365 		config.flags = RTE_IPSEC_SAD_FLAG_IPV6;
366 
367 	sad = rte_ipsec_sad_create(__func__, &config);
368 	RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
369 
370 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 1);
371 	RTE_TEST_ASSERT((status == 0) && (sa[0] == NULL),
372 		"Lookup returns an unexpected result\n");
373 
374 	sa[0] = &tmp;
375 	status = rte_ipsec_sad_add(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY, sa[0]);
376 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
377 
378 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 1);
379 	RTE_TEST_ASSERT((status == 1) && (sa[0] == &tmp),
380 		"Lookup returns an unexpected result\n");
381 
382 	key_arr[0] = tuple_1;
383 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 1);
384 	RTE_TEST_ASSERT((status == 1) && (sa[0] == &tmp),
385 		"Lookup returns an unexpected result\n");
386 	key_arr[0] = tuple;
387 
388 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY);
389 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
390 
391 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 1);
392 	RTE_TEST_ASSERT((status == 0) && (sa[0] == NULL),
393 		"Lookup returns an unexpected result\n");
394 
395 	rte_ipsec_sad_destroy(sad);
396 
397 	return TEST_SUCCESS;
398 }
399 
400 /*
401  * Lookup missing key, then add it as RTE_IPSEC_SAD_SPI_ONLY, lookup it again,
402  * lookup different key with the same SPI, then delete it and repeat lookup
403  */
404 int32_t
405 test_lookup_basic(void)
406 {
407 	int status;
408 	struct rte_ipsec_sadv4_key tuple_v4 = {SPI, DIP, SIP};
409 	struct rte_ipsec_sadv4_key tuple_v4_1 = {SPI, BAD, BAD};
410 	struct rte_ipsec_sadv6_key tuple_v6 = {SPI,
411 		RTE_IPV6(0xbeef, 0, 0, 0, 0, 0, 0, 0), RTE_IPV6(0xf00d, 0, 0, 0, 0, 0, 0, 0)};
412 	struct rte_ipsec_sadv6_key tuple_v6_1 = {SPI,
413 		RTE_IPV6(0x0bad, 0, 0, 0, 0, 0, 0, 0), RTE_IPV6(0x0bad, 0, 0, 0, 0, 0, 0, 0)};
414 
415 	status = __test_lookup_basic(0, (union rte_ipsec_sad_key *)&tuple_v4,
416 			(union rte_ipsec_sad_key *)&tuple_v4_1);
417 	if (status != TEST_SUCCESS)
418 		return status;
419 
420 	status = __test_lookup_basic(1, (union rte_ipsec_sad_key *)&tuple_v6,
421 			(union rte_ipsec_sad_key *)&tuple_v6_1);
422 
423 	return status;
424 }
425 
426 static int32_t
427 __test_lookup_adv(int ipv6, union rte_ipsec_sad_key *tuple,
428 	const union rte_ipsec_sad_key **key_arr)
429 {
430 	int status;
431 	struct rte_ipsec_sad *sad = NULL;
432 	struct rte_ipsec_sad_conf config;
433 	uint64_t tmp1, tmp2, tmp3;
434 	void *install_sa;
435 	void *sa[4];
436 
437 	config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
438 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
439 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
440 	config.socket_id = SOCKET_ID_ANY;
441 	config.flags = 0;
442 	if (ipv6)
443 		config.flags = RTE_IPSEC_SAD_FLAG_IPV6;
444 	sad = rte_ipsec_sad_create(__func__, &config);
445 	RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
446 
447 	/* lookup with empty table */
448 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
449 	RTE_TEST_ASSERT(status == 0, "Lookup returns an unexpected result\n");
450 	RTE_TEST_ASSERT(sa[0] == NULL,
451 		"Lookup returns an unexpected result\n");
452 	RTE_TEST_ASSERT(sa[1] == NULL,
453 		"Lookup returns an unexpected result\n");
454 	RTE_TEST_ASSERT(sa[2] == NULL,
455 		"Lookup returns an unexpected result\n");
456 	RTE_TEST_ASSERT(sa[3] == NULL,
457 		"Lookup returns an unexpected result\n");
458 
459 	/* lookup with one RTE_IPSEC_SAD_SPI_ONLY rule */
460 	install_sa = &tmp1;
461 	status = rte_ipsec_sad_add(sad, tuple,
462 			RTE_IPSEC_SAD_SPI_ONLY, install_sa);
463 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
464 
465 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
466 	RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
467 	RTE_TEST_ASSERT(sa[0] == &tmp1,
468 		"Lookup returns an unexpected result\n");
469 	RTE_TEST_ASSERT(sa[1] == &tmp1,
470 		"Lookup returns an unexpected result\n");
471 	RTE_TEST_ASSERT(sa[2] == &tmp1,
472 		"Lookup returns an unexpected result\n");
473 	RTE_TEST_ASSERT(sa[3] == NULL,
474 		"Lookup returns an unexpected result\n");
475 
476 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY);
477 	RTE_TEST_ASSERT(status == 0, "Failde to delete a rule\n");
478 
479 	/* lookup with one RTE_IPSEC_SAD_SPI_DIP rule */
480 	install_sa = &tmp2;
481 	status = rte_ipsec_sad_add(sad, tuple,
482 			RTE_IPSEC_SAD_SPI_DIP, install_sa);
483 	RTE_TEST_ASSERT(status == 0, "failed to add a rule\n");
484 
485 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
486 	RTE_TEST_ASSERT(status == 2, "Lookup returns an unexpected result\n");
487 	RTE_TEST_ASSERT(sa[0] == &tmp2,
488 		"Lookup returns an unexpected result\n");
489 	RTE_TEST_ASSERT(sa[1] == &tmp2,
490 		"Lookup returns an unexpected result\n");
491 	RTE_TEST_ASSERT(sa[2] == NULL,
492 		"Lookup returns an unexpected result\n");
493 	RTE_TEST_ASSERT(sa[3] == NULL,
494 		"Lookup returns an unexpected result\n");
495 
496 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP);
497 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
498 
499 	/* lookup with one RTE_IPSEC_SAD_SPI_DIP_SIP rule */
500 	install_sa = &tmp3;
501 	status = rte_ipsec_sad_add(sad, tuple,
502 			RTE_IPSEC_SAD_SPI_DIP_SIP, install_sa);
503 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
504 
505 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
506 	RTE_TEST_ASSERT(status == 1, "Lookup returns an unexpected result\n");
507 	RTE_TEST_ASSERT(sa[0] == &tmp3,
508 		"Lookup returns an unexpected result\n");
509 	RTE_TEST_ASSERT(sa[1] == NULL,
510 		"Lookup returns an unexpected result\n");
511 	RTE_TEST_ASSERT(sa[2] == NULL,
512 		"Lookup returns an unexpected result\n");
513 	RTE_TEST_ASSERT(sa[3] == NULL,
514 		"Lookup returns an unexpected result\n");
515 
516 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP);
517 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
518 
519 	/* lookup with two RTE_IPSEC_SAD_ONLY and RTE_IPSEC_SAD_DIP rules */
520 	install_sa = &tmp1;
521 	status = rte_ipsec_sad_add(sad, tuple,
522 			RTE_IPSEC_SAD_SPI_ONLY, install_sa);
523 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
524 	install_sa = &tmp2;
525 	status = rte_ipsec_sad_add(sad, tuple,
526 			RTE_IPSEC_SAD_SPI_DIP, install_sa);
527 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
528 
529 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
530 	RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
531 	RTE_TEST_ASSERT(sa[0] == &tmp2,
532 		"Lookup returns an unexpected result\n");
533 	RTE_TEST_ASSERT(sa[1] == &tmp2,
534 		"Lookup returns an unexpected result\n");
535 	RTE_TEST_ASSERT(sa[2] == &tmp1,
536 		"Lookup returns an unexpected result\n");
537 	RTE_TEST_ASSERT(sa[3] == NULL,
538 		"Lookup returns an unexpected result\n");
539 
540 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY);
541 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
542 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP);
543 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
544 
545 	/* lookup with two RTE_IPSEC_SAD_ONLY and RTE_IPSEC_SAD_DIP_SIP rules */
546 	install_sa = &tmp1;
547 	status = rte_ipsec_sad_add(sad, tuple,
548 			RTE_IPSEC_SAD_SPI_ONLY, install_sa);
549 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
550 	install_sa = &tmp3;
551 	status = rte_ipsec_sad_add(sad, tuple,
552 			RTE_IPSEC_SAD_SPI_DIP_SIP, install_sa);
553 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
554 
555 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
556 	RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
557 	RTE_TEST_ASSERT(sa[0] == &tmp3,
558 		"Lookup returns an unexpected result\n");
559 	RTE_TEST_ASSERT(sa[1] == &tmp1,
560 		"Lookup returns an unexpected result\n");
561 	RTE_TEST_ASSERT(sa[2] == &tmp1,
562 		"Lookup returns an unexpected result\n");
563 	RTE_TEST_ASSERT(sa[3] == NULL,
564 		"Lookup returns an unexpected result\n");
565 
566 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY);
567 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
568 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP);
569 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
570 
571 	/* lookup with two RTE_IPSEC_SAD_DIP and RTE_IPSEC_SAD_DIP_SIP rules */
572 	install_sa = &tmp2;
573 	status = rte_ipsec_sad_add(sad, tuple,
574 			RTE_IPSEC_SAD_SPI_DIP, install_sa);
575 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
576 	install_sa = &tmp3;
577 	status = rte_ipsec_sad_add(sad, tuple,
578 			RTE_IPSEC_SAD_SPI_DIP_SIP, install_sa);
579 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
580 
581 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
582 	RTE_TEST_ASSERT(status == 2, "Lookup returns an unexpected result\n");
583 	RTE_TEST_ASSERT(sa[0] == &tmp3,
584 		"Lookup returns an unexpected result\n");
585 	RTE_TEST_ASSERT(sa[1] == &tmp2,
586 		"Lookup returns an unexpected result\n");
587 	RTE_TEST_ASSERT(sa[2] == NULL,
588 		"Lookup returns an unexpected result\n");
589 	RTE_TEST_ASSERT(sa[3] == NULL,
590 		"Lookup returns an unexpected result\n");
591 
592 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP);
593 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
594 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP);
595 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
596 
597 	/*
598 	 * lookup with three RTE_IPSEC_SAD_DIP, RTE_IPSEC_SAD_DIP and
599 	 * RTE_IPSEC_SAD_DIP_SIP rules
600 	 */
601 	install_sa = &tmp1;
602 	status = rte_ipsec_sad_add(sad, tuple,
603 			RTE_IPSEC_SAD_SPI_ONLY, install_sa);
604 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
605 	install_sa = &tmp2;
606 	status = rte_ipsec_sad_add(sad, tuple,
607 			RTE_IPSEC_SAD_SPI_DIP, install_sa);
608 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
609 	install_sa = &tmp3;
610 	status = rte_ipsec_sad_add(sad, tuple,
611 			RTE_IPSEC_SAD_SPI_DIP_SIP, install_sa);
612 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
613 
614 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
615 	RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
616 	RTE_TEST_ASSERT(sa[0] == &tmp3,
617 		"Lookup returns an unexpected result\n");
618 	RTE_TEST_ASSERT(sa[1] == &tmp2,
619 		"Lookup returns an unexpected result\n");
620 	RTE_TEST_ASSERT(sa[2] == &tmp1,
621 		"Lookup returns an unexpected result\n");
622 	RTE_TEST_ASSERT(sa[3] == NULL,
623 		"Lookup returns an unexpected result\n");
624 
625 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY);
626 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
627 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP);
628 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
629 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP);
630 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
631 
632 	rte_ipsec_sad_destroy(sad);
633 
634 	return TEST_SUCCESS;
635 }
636 
637 /*
638  * Lookup different keys in a table with:
639  *  - RTE_IPSEC_SAD_SPI_ONLY
640  *  - RTE_IPSEC_SAD_SPI_DIP
641  *  - RTE_IPSEC_SAD_SPI_SIP
642  *  - RTE_IPSEC_SAD_SPI_ONLY/RTE_IPSEC_SAD_SPI_DIP
643  *  - RTE_IPSEC_SAD_SPI_ONLY/RTE_IPSEC_SAD_SPI_DIP_SIP
644  *  - RTE_IPSEC_SAD_SPI_DIP/RTE_IPSEC_SAD_SPI_DIP_SIP
645  *  - RTE_IPSEC_SAD_SPI_ONLY/RTE_IPSEC_SAD_SPI_DIP/RTE_IPSEC_SAD_SPI_DIP_SIP
646  * length of rule installed.
647  */
648 int32_t
649 test_lookup_adv(void)
650 {
651 	int status;
652 	/* key to install*/
653 	struct rte_ipsec_sadv4_key tuple_v4 = {SPI, DIP, SIP};
654 	struct rte_ipsec_sadv4_key tuple_v4_1 = {SPI, DIP, BAD};
655 	struct rte_ipsec_sadv4_key tuple_v4_2 = {SPI, BAD, SIP};
656 	struct rte_ipsec_sadv4_key tuple_v4_3 = {BAD, DIP, SIP};
657 
658 	/* key to install*/
659 	struct rte_ipsec_sadv6_key tuple_v6 = {SPI,
660 		RTE_IPV6(0xbeef, 0, 0, 0, 0, 0, 0, 0), RTE_IPV6(0xf00d, 0, 0, 0, 0, 0, 0, 0)};
661 	struct rte_ipsec_sadv6_key tuple_v6_1 = {SPI,
662 		RTE_IPV6(0xbeef, 0, 0, 0, 0, 0, 0, 0), RTE_IPV6(0x0bad, 0, 0, 0, 0, 0, 0, 0)};
663 	struct rte_ipsec_sadv6_key tuple_v6_2 = {SPI,
664 		RTE_IPV6(0x0bad, 0, 0, 0, 0, 0, 0, 0), RTE_IPV6(0xf00d, 0, 0, 0, 0, 0, 0, 0)};
665 	struct rte_ipsec_sadv6_key tuple_v6_3 = {BAD,
666 		RTE_IPV6(0xbeef, 0, 0, 0, 0, 0, 0, 0), RTE_IPV6(0xf00d, 0, 0, 0, 0, 0, 0, 0)};
667 
668 	const union rte_ipsec_sad_key *key_arr[] = {
669 				(union rte_ipsec_sad_key *)&tuple_v4,
670 				(union rte_ipsec_sad_key *)&tuple_v4_1,
671 				(union rte_ipsec_sad_key *)&tuple_v4_2,
672 				(union rte_ipsec_sad_key *)&tuple_v4_3
673 					};
674 
675 	status = __test_lookup_adv(0, (union rte_ipsec_sad_key *)&tuple_v4,
676 			key_arr);
677 	if (status != TEST_SUCCESS)
678 		return status;
679 	key_arr[0] = (union rte_ipsec_sad_key *)&tuple_v6;
680 	key_arr[1] = (union rte_ipsec_sad_key *)&tuple_v6_1;
681 	key_arr[2] = (union rte_ipsec_sad_key *)&tuple_v6_2;
682 	key_arr[3] = (union rte_ipsec_sad_key *)&tuple_v6_3;
683 	status = __test_lookup_adv(1, (union rte_ipsec_sad_key *)&tuple_v6,
684 			key_arr);
685 
686 	return status;
687 }
688 
689 
690 static int32_t
691 __test_lookup_order(int ipv6, union rte_ipsec_sad_key *tuple,
692 	union rte_ipsec_sad_key *tuple_1, union rte_ipsec_sad_key *tuple_2)
693 {
694 	int status;
695 	struct rte_ipsec_sad *sad = NULL;
696 	struct rte_ipsec_sad_conf config;
697 	const union rte_ipsec_sad_key *key_arr[] = {tuple, tuple_1, tuple_2,};
698 	uint64_t tmp1, tmp2, tmp3;
699 	void *install_sa;
700 	void *sa[3];
701 
702 	config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
703 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
704 	config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
705 	config.socket_id = SOCKET_ID_ANY;
706 	config.flags = 0;
707 	if (ipv6)
708 		config.flags = RTE_IPSEC_SAD_FLAG_IPV6;
709 	sad = rte_ipsec_sad_create(__func__, &config);
710 	RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
711 
712 	/* install RTE_IPSEC_SAD_SPI_ONLY */
713 	install_sa = &tmp1;
714 	status = rte_ipsec_sad_add(sad, tuple,
715 			RTE_IPSEC_SAD_SPI_ONLY, install_sa);
716 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
717 
718 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
719 	RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
720 	RTE_TEST_ASSERT(sa[0] == &tmp1,
721 		"Lookup returns an unexpected result\n");
722 	RTE_TEST_ASSERT(sa[1] == &tmp1,
723 		"Lookup returns an unexpected result\n");
724 	RTE_TEST_ASSERT(sa[2] == &tmp1,
725 		"Lookup returns an unexpected result\n");
726 
727 	/* add RTE_IPSEC_SAD_SPI_DIP */
728 	install_sa = &tmp2;
729 	status = rte_ipsec_sad_add(sad, tuple,
730 			RTE_IPSEC_SAD_SPI_DIP, install_sa);
731 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
732 
733 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
734 	RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
735 	RTE_TEST_ASSERT(sa[0] == &tmp2,
736 		"Lookup returns an unexpected result\n");
737 	RTE_TEST_ASSERT(sa[1] == &tmp2,
738 		"Lookup returns an unexpected result\n");
739 	RTE_TEST_ASSERT(sa[2] == &tmp1,
740 		"Lookup returns an unexpected result\n");
741 
742 	/* add RTE_IPSEC_SAD_SPI_DIP_SIP */
743 	install_sa = &tmp3;
744 	status = rte_ipsec_sad_add(sad, tuple,
745 			RTE_IPSEC_SAD_SPI_DIP_SIP, install_sa);
746 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
747 
748 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
749 	RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
750 	RTE_TEST_ASSERT(sa[0] == &tmp3,
751 		"Lookup returns an unexpected result\n");
752 	RTE_TEST_ASSERT(sa[1] == &tmp2,
753 		"Lookup returns an unexpected result\n");
754 	RTE_TEST_ASSERT(sa[2] == &tmp1,
755 		"Lookup returns an unexpected result\n");
756 
757 	/* delete RTE_IPSEC_SAD_SPI_ONLY */
758 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY);
759 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
760 
761 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
762 	RTE_TEST_ASSERT(status == 2, "Lookup returns an unexpected result\n");
763 	RTE_TEST_ASSERT(sa[0] == &tmp3,
764 		"Lookup returns an unexpected result\n");
765 	RTE_TEST_ASSERT(sa[1] == &tmp2,
766 		"Lookup returns an unexpected result\n");
767 	RTE_TEST_ASSERT(sa[2] == NULL,
768 		"Lookup returns an unexpected result\n");
769 
770 	/* delete RTE_IPSEC_SAD_SPI_DIP */
771 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP);
772 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
773 
774 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
775 	RTE_TEST_ASSERT(status == 1, "Lookup returns an unexpected result\n");
776 	RTE_TEST_ASSERT(sa[0] == &tmp3,
777 		"Lookup returns an unexpected result\n");
778 	RTE_TEST_ASSERT(sa[1] == NULL,
779 		"Lookup returns an unexpected result\n");
780 	RTE_TEST_ASSERT(sa[2] == NULL,
781 		"Lookup returns an unexpected result\n");
782 
783 	/* delete RTE_IPSEC_SAD_SPI_DIP_SIP */
784 	status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP);
785 	RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
786 
787 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
788 	RTE_TEST_ASSERT(status == 0, "Lookup returns an unexpected result\n");
789 	RTE_TEST_ASSERT(sa[0] == NULL,
790 		"Lookup returns an unexpected result\n");
791 	RTE_TEST_ASSERT(sa[1] == NULL,
792 		"Lookup returns an unexpected result\n");
793 	RTE_TEST_ASSERT(sa[2] == NULL,
794 		"Lookup returns an unexpected result\n");
795 
796 	/* add RTE_IPSEC_SAD_SPI_DIP_SIP */
797 	install_sa = &tmp3;
798 	status = rte_ipsec_sad_add(sad, tuple,
799 			RTE_IPSEC_SAD_SPI_DIP_SIP, install_sa);
800 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
801 
802 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
803 	RTE_TEST_ASSERT(status == 1, "Lookup returns an unexpected result\n");
804 	RTE_TEST_ASSERT(sa[0] == &tmp3,
805 		"Lookup returns an unexpected result\n");
806 	RTE_TEST_ASSERT(sa[1] == NULL,
807 		"Lookup returns an unexpected result\n");
808 	RTE_TEST_ASSERT(sa[2] == NULL,
809 		"Lookup returns an unexpected result\n");
810 
811 	/* add RTE_IPSEC_SAD_SPI_DIP */
812 	install_sa = &tmp2;
813 	status = rte_ipsec_sad_add(sad, tuple,
814 			RTE_IPSEC_SAD_SPI_DIP, install_sa);
815 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
816 
817 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
818 	RTE_TEST_ASSERT(status == 2, "Lookup returns an unexpected result\n");
819 	RTE_TEST_ASSERT(sa[0] == &tmp3,
820 		"Lookup returns an unexpected result\n");
821 	RTE_TEST_ASSERT(sa[1] == &tmp2,
822 		"Lookup returns an unexpected result\n");
823 	RTE_TEST_ASSERT(sa[2] == NULL,
824 		"Lookup returns an unexpected result\n");
825 
826 	/* add RTE_IPSEC_SAD_SPI_ONLY */
827 	install_sa = &tmp1;
828 	status = rte_ipsec_sad_add(sad, tuple,
829 			RTE_IPSEC_SAD_SPI_ONLY, install_sa);
830 	RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
831 
832 	status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
833 	RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
834 	RTE_TEST_ASSERT(sa[0] == &tmp3,
835 		"Lookup returns an unexpected result\n");
836 	RTE_TEST_ASSERT(sa[1] == &tmp2,
837 		"Lookup returns an unexpected result\n");
838 	RTE_TEST_ASSERT(sa[2] == &tmp1,
839 		"Lookup returns an unexpected result\n");
840 
841 	rte_ipsec_sad_destroy(sad);
842 	return TEST_SUCCESS;
843 }
844 
845 /*
846  * Check an order of add and delete
847  */
848 int32_t
849 test_lookup_order(void)
850 {
851 	int status;
852 	/* key to install*/
853 	struct rte_ipsec_sadv4_key tuple_v4 = {SPI, DIP, SIP};
854 	struct rte_ipsec_sadv4_key tuple_v4_1 = {SPI, DIP, BAD};
855 	struct rte_ipsec_sadv4_key tuple_v4_2 = {SPI, BAD, SIP};
856 	/* key to install*/
857 	struct rte_ipsec_sadv6_key tuple_v6 = {SPI,
858 		RTE_IPV6(0xbeef, 0, 0, 0, 0, 0, 0, 0), RTE_IPV6(0xf00d, 0, 0, 0, 0, 0, 0, 0)};
859 	struct rte_ipsec_sadv6_key tuple_v6_1 = {SPI,
860 		RTE_IPV6(0xbeef, 0, 0, 0, 0, 0, 0, 0), RTE_IPV6(0x0bad, 0, 0, 0, 0, 0, 0, 0)};
861 	struct rte_ipsec_sadv6_key tuple_v6_2 = {SPI,
862 		RTE_IPV6(0x0bad, 0, 0, 0, 0, 0, 0, 0), RTE_IPV6(0xf00d, 0, 0, 0, 0, 0, 0, 0)};
863 
864 	status = __test_lookup_order(0, (union rte_ipsec_sad_key *)&tuple_v4,
865 			(union rte_ipsec_sad_key *)&tuple_v4_1,
866 			(union rte_ipsec_sad_key *)&tuple_v4_2);
867 	if (status != TEST_SUCCESS)
868 		return status;
869 
870 	status = __test_lookup_order(1, (union rte_ipsec_sad_key *)&tuple_v6,
871 			(union rte_ipsec_sad_key *)&tuple_v6_1,
872 			(union rte_ipsec_sad_key *)&tuple_v6_2);
873 	return status;
874 }
875 
876 static struct unit_test_suite ipsec_sad_tests = {
877 	.suite_name = "ipsec sad autotest",
878 	.setup = NULL,
879 	.teardown = NULL,
880 	.unit_test_cases = {
881 		TEST_CASE(test_create_invalid),
882 		TEST_CASE(test_find_existing),
883 		TEST_CASE(test_multiple_create),
884 		TEST_CASE(test_add_invalid),
885 		TEST_CASE(test_delete_invalid),
886 		TEST_CASE(test_lookup_invalid),
887 		TEST_CASE(test_lookup_basic),
888 		TEST_CASE(test_lookup_adv),
889 		TEST_CASE(test_lookup_order),
890 		TEST_CASES_END()
891 	}
892 };
893 
894 static int
895 test_ipsec_sad(void)
896 {
897 	return unit_test_suite_runner(&ipsec_sad_tests);
898 }
899 
900 #endif /* !RTE_EXEC_ENV_WINDOWS */
901 
902 REGISTER_TEST_COMMAND(ipsec_sad_autotest, test_ipsec_sad);
903