xref: /dpdk/app/test/test_pdcp.c (revision d010725b397429a56f445ef0b9523e7f26aa4603)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2023 Marvell.
3  */
4 
5 #include <rte_bitmap.h>
6 #include <rte_errno.h>
7 #ifdef RTE_LIB_EVENTDEV
8 #include <rte_eventdev.h>
9 #include <rte_event_timer_adapter.h>
10 #endif /* RTE_LIB_EVENTDEV */
11 #include <rte_malloc.h>
12 #include <rte_pdcp.h>
13 #include <rte_pdcp_hdr.h>
14 #include <rte_timer.h>
15 
16 #include "test.h"
17 #include "test_cryptodev.h"
18 #include "test_cryptodev_security_pdcp_sdap_test_vectors.h"
19 #include "test_cryptodev_security_pdcp_test_vectors.h"
20 
21 #define NSECPERSEC 1E9
22 #define NB_DESC 1024
23 #define TIMER_ADAPTER_ID 0
24 #define TEST_EV_QUEUE_ID 0
25 #define TEST_EV_PORT_ID 0
26 #define CDEV_INVALID_ID UINT8_MAX
27 #define NB_BASIC_TESTS RTE_DIM(pdcp_test_params)
28 #define NB_SDAP_TESTS RTE_DIM(list_pdcp_sdap_tests)
29 #define PDCP_IV_LEN 16
30 #define PDCP_MBUF_SIZE	(sizeof(struct rte_mbuf) + \
31 			 RTE_PKTMBUF_HEADROOM + RTE_PDCP_CTRL_PDU_SIZE_MAX)
32 
33 /* Assert that condition is true, or goto the mark */
34 #define ASSERT_TRUE_OR_GOTO(cond, mark, ...) do {\
35 	if (!(cond)) { \
36 		RTE_LOG(ERR, USER1, "Error at: %s:%d\n", __func__, __LINE__); \
37 		RTE_LOG(ERR, USER1, __VA_ARGS__); \
38 		goto mark; \
39 	} \
40 } while (0)
41 
42 /* According to formula(7.2.a Window_Size) */
43 #define PDCP_WINDOW_SIZE(sn_size) (1 << (sn_size - 1))
44 
45 struct pdcp_testsuite_params {
46 	struct rte_mempool *mbuf_pool;
47 	struct rte_mempool *cop_pool;
48 	struct rte_mempool *sess_pool;
49 	bool cdevs_used[RTE_CRYPTO_MAX_DEVS];
50 	int evdev;
51 #ifdef RTE_LIB_EVENTDEV
52 	struct rte_event_timer_adapter *timdev;
53 #endif /* RTE_LIB_EVENTDEV */
54 	bool timer_is_running;
55 	uint64_t min_resolution_ns;
56 	struct rte_pdcp_up_ctrl_pdu_hdr *status_report;
57 	uint32_t status_report_bitmask_capacity;
58 	uint8_t *ctrl_pdu_buf;
59 };
60 
61 static struct pdcp_testsuite_params testsuite_params;
62 
63 struct test_rte_timer_args {
64 	int status;
65 	struct rte_pdcp_entity *pdcp_entity;
66 };
67 
68 struct pdcp_test_conf {
69 	struct rte_pdcp_entity_conf entity;
70 	struct rte_crypto_sym_xform c_xfrm;
71 	struct rte_crypto_sym_xform a_xfrm;
72 	bool is_integrity_protected;
73 	uint8_t input[RTE_PDCP_CTRL_PDU_SIZE_MAX];
74 	uint32_t input_len;
75 	uint8_t output[RTE_PDCP_CTRL_PDU_SIZE_MAX];
76 	uint32_t output_len;
77 };
78 
79 enum pdcp_test_suite_type {
80 	PDCP_TEST_SUITE_TY_BASIC,
81 	PDCP_TEST_SUITE_TY_SDAP,
82 };
83 
84 static bool silent;
85 
86 static int create_test_conf_from_index(const int index, struct pdcp_test_conf *conf,
87 				       enum pdcp_test_suite_type suite_type);
88 static void test_conf_input_data_modify(struct pdcp_test_conf *conf, int inp_len);
89 
90 typedef int (*test_with_conf_t)(struct pdcp_test_conf *conf);
91 
92 static uint32_t
nb_tests_get(enum pdcp_test_suite_type type)93 nb_tests_get(enum pdcp_test_suite_type type)
94 {
95 	uint32_t ret;
96 
97 	switch (type) {
98 	case PDCP_TEST_SUITE_TY_BASIC:
99 		ret = NB_BASIC_TESTS;
100 		break;
101 	case PDCP_TEST_SUITE_TY_SDAP:
102 		ret = NB_SDAP_TESTS;
103 		break;
104 	default:
105 		return 0;
106 	}
107 
108 	return ret;
109 }
110 
111 static const char*
pdcp_test_name_get(enum pdcp_test_suite_type type,int idx)112 pdcp_test_name_get(enum pdcp_test_suite_type type, int idx)
113 {
114 	const char *test_name = NULL;
115 
116 	switch (type) {
117 	case PDCP_TEST_SUITE_TY_BASIC:
118 		test_name = pdcp_test_params[idx].name;
119 		break;
120 	case PDCP_TEST_SUITE_TY_SDAP:
121 		test_name = list_pdcp_sdap_tests[idx].param.name;
122 		break;
123 	default:
124 		return NULL;
125 	}
126 
127 	return test_name;
128 }
129 
130 static int
run_test_foreach_known_vec(test_with_conf_t test,bool stop_on_first_pass,enum pdcp_test_suite_type suite_type)131 run_test_foreach_known_vec(test_with_conf_t test, bool stop_on_first_pass,
132 			   enum pdcp_test_suite_type suite_type)
133 {
134 	struct pdcp_test_conf test_conf;
135 	bool all_tests_skipped = true;
136 	uint32_t nb_tests = nb_tests_get(suite_type);
137 	uint32_t i;
138 	int ret;
139 
140 	for (i = 0; i < nb_tests; i++) {
141 		create_test_conf_from_index(i, &test_conf, suite_type);
142 		ret = test(&test_conf);
143 
144 		if (ret == TEST_FAILED) {
145 			printf("[%03i] - %s - failed\n", i,
146 			       pdcp_test_name_get(suite_type, i));
147 			return TEST_FAILED;
148 		}
149 
150 		if ((ret == TEST_SKIPPED) || (ret == -ENOTSUP))
151 			continue;
152 
153 		if (stop_on_first_pass)
154 			return TEST_SUCCESS;
155 
156 		all_tests_skipped = false;
157 	}
158 
159 	if (all_tests_skipped)
160 		return TEST_SKIPPED;
161 
162 	return TEST_SUCCESS;
163 }
164 
165 static int
run_test_with_all_known_vec(const void * args)166 run_test_with_all_known_vec(const void *args)
167 {
168 	test_with_conf_t test = args;
169 
170 	return run_test_foreach_known_vec(test, false,
171 					  PDCP_TEST_SUITE_TY_BASIC);
172 }
173 
174 static int
run_test_with_all_sdap_known_vec(const void * args)175 run_test_with_all_sdap_known_vec(const void *args)
176 {
177 	test_with_conf_t test = args;
178 
179 	return run_test_foreach_known_vec(test, false,
180 					  PDCP_TEST_SUITE_TY_SDAP);
181 }
182 
183 static int
run_test_with_all_known_vec_until_first_pass(const void * args)184 run_test_with_all_known_vec_until_first_pass(const void *args)
185 {
186 	test_with_conf_t test = args;
187 
188 	return run_test_foreach_known_vec(test, true,
189 					  PDCP_TEST_SUITE_TY_BASIC);
190 }
191 
192 static inline uint32_t
pdcp_sn_mask_get(enum rte_security_pdcp_sn_size sn_size)193 pdcp_sn_mask_get(enum rte_security_pdcp_sn_size sn_size)
194 {
195 	return (1 << sn_size) - 1;
196 }
197 
198 static inline uint32_t
pdcp_sn_from_count_get(uint32_t count,enum rte_security_pdcp_sn_size sn_size)199 pdcp_sn_from_count_get(uint32_t count, enum rte_security_pdcp_sn_size sn_size)
200 {
201 	return (count & pdcp_sn_mask_get(sn_size));
202 }
203 
204 static inline uint32_t
pdcp_hfn_mask_get(enum rte_security_pdcp_sn_size sn_size)205 pdcp_hfn_mask_get(enum rte_security_pdcp_sn_size sn_size)
206 {
207 	return ~pdcp_sn_mask_get(sn_size);
208 }
209 
210 static inline uint32_t
pdcp_hfn_from_count_get(uint32_t count,enum rte_security_pdcp_sn_size sn_size)211 pdcp_hfn_from_count_get(uint32_t count, enum rte_security_pdcp_sn_size sn_size)
212 {
213 	return (count & pdcp_hfn_mask_get(sn_size)) >> sn_size;
214 }
215 
216 static void
pdcp_timer_start_cb(void * timer,void * args)217 pdcp_timer_start_cb(void *timer, void *args)
218 {
219 	bool *is_timer_running = timer;
220 
221 	RTE_SET_USED(args);
222 	*is_timer_running = true;
223 }
224 
225 static void
pdcp_timer_stop_cb(void * timer,void * args)226 pdcp_timer_stop_cb(void *timer, void *args)
227 {
228 	bool *is_timer_running = timer;
229 
230 	RTE_SET_USED(args);
231 	*is_timer_running = false;
232 }
233 
234 static struct rte_pdcp_t_reordering t_reorder_timer = {
235 	.timer = &testsuite_params.timer_is_running,
236 	.start = pdcp_timer_start_cb,
237 	.stop = pdcp_timer_stop_cb,
238 };
239 
240 static inline void
bitmask_set_bit(uint8_t * mask,uint32_t bit)241 bitmask_set_bit(uint8_t *mask, uint32_t bit)
242 {
243 	mask[bit / 8] |= (1 << bit % 8);
244 }
245 
246 static inline bool
bitmask_is_bit_set(const uint8_t * mask,uint32_t bit)247 bitmask_is_bit_set(const uint8_t *mask, uint32_t bit)
248 {
249 	return mask[bit / 8] & (1 << (bit % 8));
250 }
251 
252 static inline int
pdcp_hdr_size_get(enum rte_security_pdcp_sn_size sn_size)253 pdcp_hdr_size_get(enum rte_security_pdcp_sn_size sn_size)
254 {
255 	return RTE_ALIGN_MUL_CEIL(sn_size, 8) / 8;
256 }
257 
258 static int
pktmbuf_read_into(const struct rte_mbuf * m,void * buf,size_t buf_len)259 pktmbuf_read_into(const struct rte_mbuf *m, void *buf, size_t buf_len)
260 {
261 	if (m->pkt_len > buf_len)
262 		return -ENOMEM;
263 
264 	const void *read = rte_pktmbuf_read(m, 0, m->pkt_len, buf);
265 	if (read != NULL && read != buf)
266 		memcpy(buf, read, m->pkt_len);
267 
268 	return 0;
269 }
270 
271 static int
cryptodev_init(int dev_id)272 cryptodev_init(int dev_id)
273 {
274 	struct pdcp_testsuite_params *ts_params = &testsuite_params;
275 	struct rte_cryptodev_qp_conf qp_conf;
276 	struct rte_cryptodev_info dev_info;
277 	struct rte_cryptodev_config config;
278 	int ret, socket_id;
279 
280 	/* Check if device was already initialized */
281 	if (ts_params->cdevs_used[dev_id])
282 		return 0;
283 
284 	rte_cryptodev_info_get(dev_id, &dev_info);
285 
286 	if (dev_info.max_nb_queue_pairs < 1) {
287 		RTE_LOG(ERR, USER1, "Cryptodev doesn't have sufficient queue pairs available\n");
288 		return -ENODEV;
289 	}
290 
291 	socket_id = rte_socket_id();
292 
293 	memset(&config, 0, sizeof(config));
294 	config.nb_queue_pairs = 1;
295 	config.socket_id = socket_id;
296 
297 	ret = rte_cryptodev_configure(dev_id, &config);
298 	if (ret < 0) {
299 		RTE_LOG(ERR, USER1, "Could not configure cryptodev - %d\n", dev_id);
300 		return -ENODEV;
301 	}
302 
303 	memset(&qp_conf, 0, sizeof(qp_conf));
304 	qp_conf.nb_descriptors = NB_DESC;
305 
306 	ret = rte_cryptodev_queue_pair_setup(dev_id, 0, &qp_conf, socket_id);
307 	if (ret < 0) {
308 		RTE_LOG(ERR, USER1, "Could not configure queue pair\n");
309 		return -ENODEV;
310 	}
311 
312 	ret = rte_cryptodev_start(dev_id);
313 	if (ret < 0) {
314 		RTE_LOG(ERR, USER1, "Could not start cryptodev\n");
315 		return -ENODEV;
316 	}
317 
318 	/* Mark device as initialized */
319 	ts_params->cdevs_used[dev_id] = true;
320 
321 	return 0;
322 }
323 
324 static void
cryptodev_fini(int dev_id)325 cryptodev_fini(int dev_id)
326 {
327 	rte_cryptodev_stop(dev_id);
328 }
329 
330 static unsigned int
cryptodev_sess_priv_max_req_get(void)331 cryptodev_sess_priv_max_req_get(void)
332 {
333 	struct rte_cryptodev_info info;
334 	unsigned int sess_priv_sz;
335 	int i, nb_dev;
336 	void *sec_ctx;
337 
338 	nb_dev = rte_cryptodev_count();
339 
340 	sess_priv_sz = 0;
341 
342 	for (i = 0; i < nb_dev; i++) {
343 		rte_cryptodev_info_get(i, &info);
344 		sess_priv_sz = RTE_MAX(sess_priv_sz, rte_cryptodev_sym_get_private_session_size(i));
345 		if (info.feature_flags & RTE_CRYPTODEV_FF_SECURITY) {
346 			sec_ctx = rte_cryptodev_get_sec_ctx(i);
347 			sess_priv_sz = RTE_MAX(sess_priv_sz,
348 					       rte_security_session_get_size(sec_ctx));
349 		}
350 	}
351 
352 	return sess_priv_sz;
353 }
354 
355 static int
testsuite_setup(void)356 testsuite_setup(void)
357 {
358 	struct pdcp_testsuite_params *ts_params = &testsuite_params;
359 	int nb_cdev, sess_priv_size, nb_sess = 1024;
360 
361 	RTE_SET_USED(pdcp_test_hfn_threshold);
362 
363 	nb_cdev = rte_cryptodev_count();
364 	if (nb_cdev < 1) {
365 		RTE_LOG(ERR, USER1, "No crypto devices found.\n");
366 		return TEST_SKIPPED;
367 	}
368 
369 	memset(ts_params, 0, sizeof(*ts_params));
370 
371 	ts_params->mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NUM_MBUFS, MBUF_CACHE_SIZE, 0,
372 						       PDCP_MBUF_SIZE, SOCKET_ID_ANY);
373 	if (ts_params->mbuf_pool == NULL) {
374 		RTE_LOG(ERR, USER1, "Could not create mbuf pool\n");
375 		return TEST_FAILED;
376 	}
377 
378 	ts_params->cop_pool = rte_crypto_op_pool_create("cop_pool", RTE_CRYPTO_OP_TYPE_SYMMETRIC,
379 							 NUM_MBUFS, MBUF_CACHE_SIZE,
380 							 2 * MAXIMUM_IV_LENGTH, SOCKET_ID_ANY);
381 	if (ts_params->cop_pool == NULL) {
382 		RTE_LOG(ERR, USER1, "Could not create crypto_op pool\n");
383 		goto mbuf_pool_free;
384 	}
385 
386 	/* Get max session priv size required */
387 	sess_priv_size = cryptodev_sess_priv_max_req_get();
388 
389 	ts_params->sess_pool = rte_cryptodev_sym_session_pool_create("sess_pool", nb_sess,
390 								     sess_priv_size,
391 								     RTE_MEMPOOL_CACHE_MAX_SIZE,
392 								     0, SOCKET_ID_ANY);
393 	if (ts_params->sess_pool == NULL) {
394 		RTE_LOG(ERR, USER1, "Could not create session pool\n");
395 		goto cop_pool_free;
396 	}
397 
398 	/* Allocate memory for longest possible status report */
399 	ts_params->status_report_bitmask_capacity = RTE_PDCP_CTRL_PDU_SIZE_MAX -
400 		sizeof(struct rte_pdcp_up_ctrl_pdu_hdr);
401 	ts_params->status_report = rte_zmalloc(NULL, RTE_PDCP_CTRL_PDU_SIZE_MAX, 0);
402 	if (ts_params->status_report == NULL) {
403 		RTE_LOG(ERR, USER1, "Could not allocate status report\n");
404 		goto cop_pool_free;
405 	}
406 
407 	ts_params->ctrl_pdu_buf = rte_zmalloc(NULL, RTE_PDCP_CTRL_PDU_SIZE_MAX, 0);
408 	if (ts_params->ctrl_pdu_buf == NULL) {
409 		RTE_LOG(ERR, USER1, "Could not allocate status report data\n");
410 		goto cop_pool_free;
411 	}
412 
413 	return 0;
414 
415 cop_pool_free:
416 	rte_mempool_free(ts_params->cop_pool);
417 	ts_params->cop_pool = NULL;
418 mbuf_pool_free:
419 	rte_mempool_free(ts_params->mbuf_pool);
420 	ts_params->mbuf_pool = NULL;
421 	rte_free(ts_params->status_report);
422 	rte_free(ts_params->ctrl_pdu_buf);
423 	return TEST_FAILED;
424 }
425 
426 static void
testsuite_teardown(void)427 testsuite_teardown(void)
428 {
429 	struct pdcp_testsuite_params *ts_params = &testsuite_params;
430 	uint8_t dev_id;
431 
432 	for (dev_id = 0; dev_id < RTE_CRYPTO_MAX_DEVS; dev_id++) {
433 		if (ts_params->cdevs_used[dev_id])
434 			cryptodev_fini(dev_id);
435 	}
436 
437 	rte_mempool_free(ts_params->sess_pool);
438 	ts_params->sess_pool = NULL;
439 
440 	rte_mempool_free(ts_params->cop_pool);
441 	ts_params->cop_pool = NULL;
442 
443 	rte_mempool_free(ts_params->mbuf_pool);
444 	ts_params->mbuf_pool = NULL;
445 
446 	rte_free(ts_params->status_report);
447 	rte_free(ts_params->ctrl_pdu_buf);
448 }
449 
450 static int
ut_setup_pdcp(void)451 ut_setup_pdcp(void)
452 {
453 	return 0;
454 }
455 
456 static void
ut_teardown_pdcp(void)457 ut_teardown_pdcp(void)
458 {
459 }
460 
461 static int
crypto_caps_cipher_verify(uint8_t dev_id,const struct rte_crypto_sym_xform * c_xfrm)462 crypto_caps_cipher_verify(uint8_t dev_id, const struct rte_crypto_sym_xform *c_xfrm)
463 {
464 	const struct rte_cryptodev_symmetric_capability *cap;
465 	struct rte_cryptodev_sym_capability_idx cap_idx;
466 	int ret;
467 
468 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
469 	cap_idx.algo.cipher = c_xfrm->cipher.algo;
470 
471 	cap = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);
472 	if (cap == NULL)
473 		return -1;
474 
475 	ret = rte_cryptodev_sym_capability_check_cipher(cap, c_xfrm->cipher.key.length,
476 							c_xfrm->cipher.iv.length);
477 
478 	return ret;
479 }
480 
481 static int
crypto_caps_auth_verify(uint8_t dev_id,const struct rte_crypto_sym_xform * a_xfrm)482 crypto_caps_auth_verify(uint8_t dev_id, const struct rte_crypto_sym_xform *a_xfrm)
483 {
484 	const struct rte_cryptodev_symmetric_capability *cap;
485 	struct rte_cryptodev_sym_capability_idx cap_idx;
486 	int ret;
487 
488 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
489 	cap_idx.algo.auth = a_xfrm->auth.algo;
490 
491 	cap = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);
492 	if (cap == NULL)
493 		return -1;
494 
495 	ret = rte_cryptodev_sym_capability_check_auth(cap, a_xfrm->auth.key.length,
496 						      a_xfrm->auth.digest_length,
497 						      a_xfrm->auth.iv.length);
498 
499 	return ret;
500 }
501 
502 static int
cryptodev_id_get(bool is_integrity_protected,const struct rte_crypto_sym_xform * c_xfrm,const struct rte_crypto_sym_xform * a_xfrm)503 cryptodev_id_get(bool is_integrity_protected, const struct rte_crypto_sym_xform *c_xfrm,
504 		 const struct rte_crypto_sym_xform *a_xfrm)
505 {
506 	int i, nb_devs;
507 
508 	nb_devs = rte_cryptodev_count();
509 
510 	/* Check capabilities */
511 
512 	for (i = 0; i < nb_devs; i++) {
513 		if ((crypto_caps_cipher_verify(i, c_xfrm) == 0) &&
514 		    (!is_integrity_protected || crypto_caps_auth_verify(i, a_xfrm) == 0))
515 			break;
516 	}
517 
518 	if (i == nb_devs)
519 		return -1;
520 
521 	return i;
522 }
523 
524 static int
pdcp_known_vec_verify(struct rte_mbuf * m,const uint8_t * expected,uint32_t expected_pkt_len)525 pdcp_known_vec_verify(struct rte_mbuf *m, const uint8_t *expected, uint32_t expected_pkt_len)
526 {
527 	uint8_t *actual = rte_pktmbuf_mtod(m, uint8_t *);
528 	uint32_t actual_pkt_len = rte_pktmbuf_pkt_len(m);
529 
530 	if (!silent) {
531 		debug_hexdump(stdout, "Received:", actual, actual_pkt_len);
532 		debug_hexdump(stdout, "Expected:", expected, expected_pkt_len);
533 	}
534 
535 	TEST_ASSERT_EQUAL(actual_pkt_len, expected_pkt_len,
536 			  "Mismatch in packet lengths [expected: %d, received: %d]",
537 			  expected_pkt_len, actual_pkt_len);
538 
539 	TEST_ASSERT_BUFFERS_ARE_EQUAL(actual, expected, expected_pkt_len,
540 				     "Generated packet not as expected");
541 
542 	return 0;
543 }
544 
545 static struct rte_crypto_op *
process_crypto_request(uint8_t dev_id,struct rte_crypto_op * op)546 process_crypto_request(uint8_t dev_id, struct rte_crypto_op *op)
547 {
548 	if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
549 		RTE_LOG(ERR, USER1, "Error sending packet to cryptodev\n");
550 		return NULL;
551 	}
552 
553 	op = NULL;
554 
555 	while (rte_cryptodev_dequeue_burst(dev_id, 0, &op, 1) == 0)
556 		rte_pause();
557 
558 	return op;
559 }
560 
561 static uint32_t
pdcp_sn_from_raw_get(const void * data,enum rte_security_pdcp_sn_size size)562 pdcp_sn_from_raw_get(const void *data, enum rte_security_pdcp_sn_size size)
563 {
564 	uint32_t sn = 0;
565 
566 	if (size == RTE_SECURITY_PDCP_SN_SIZE_12) {
567 		sn = rte_cpu_to_be_16(*(const uint16_t *)data);
568 		sn = sn & 0xfff;
569 	} else if (size == RTE_SECURITY_PDCP_SN_SIZE_18) {
570 		sn = rte_cpu_to_be_32(*(const uint32_t *)data);
571 		sn = (sn & 0x3ffff00) >> 8;
572 	}
573 
574 	return sn;
575 }
576 
577 static void
pdcp_sn_to_raw_set(void * data,uint32_t sn,int size)578 pdcp_sn_to_raw_set(void *data, uint32_t sn, int size)
579 {
580 	if (size == RTE_SECURITY_PDCP_SN_SIZE_12) {
581 		struct rte_pdcp_up_data_pdu_sn_12_hdr *pdu_hdr = data;
582 		pdu_hdr->sn_11_8 = ((sn & 0xf00) >> 8);
583 		pdu_hdr->sn_7_0 = (sn & 0xff);
584 	} else if (size == RTE_SECURITY_PDCP_SN_SIZE_18) {
585 		struct rte_pdcp_up_data_pdu_sn_18_hdr *pdu_hdr = data;
586 		pdu_hdr->sn_17_16 = ((sn & 0x30000) >> 16);
587 		pdu_hdr->sn_15_8 = ((sn & 0xff00) >> 8);
588 		pdu_hdr->sn_7_0 = (sn & 0xff);
589 	}
590 }
591 
592 static uint8_t
pdcp_test_bearer_get(enum pdcp_test_suite_type suite_type,const int index)593 pdcp_test_bearer_get(enum pdcp_test_suite_type suite_type, const int index)
594 {
595 	uint8_t ret;
596 
597 	switch (suite_type) {
598 	case PDCP_TEST_SUITE_TY_BASIC:
599 		ret = pdcp_test_bearer[index];
600 		break;
601 	case PDCP_TEST_SUITE_TY_SDAP:
602 		ret = list_pdcp_sdap_tests[index].bearer;
603 		break;
604 	default:
605 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
606 		ret = -1;
607 
608 	}
609 
610 	return ret;
611 }
612 
613 static enum rte_security_pdcp_domain
pdcp_test_param_domain_get(enum pdcp_test_suite_type suite_type,const int index)614 pdcp_test_param_domain_get(enum pdcp_test_suite_type suite_type, const int index)
615 {
616 	enum rte_security_pdcp_domain ret;
617 
618 	switch (suite_type) {
619 	case PDCP_TEST_SUITE_TY_BASIC:
620 		ret = pdcp_test_params[index].domain;
621 		break;
622 	case PDCP_TEST_SUITE_TY_SDAP:
623 		ret = list_pdcp_sdap_tests[index].param.domain;
624 		break;
625 	default:
626 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
627 		ret = -1;
628 	}
629 
630 	return ret;
631 }
632 
633 static uint8_t
pdcp_test_data_sn_size_get(enum pdcp_test_suite_type suite_type,const int index)634 pdcp_test_data_sn_size_get(enum pdcp_test_suite_type suite_type, const int index)
635 {
636 	uint8_t ret;
637 
638 	switch (suite_type) {
639 	case PDCP_TEST_SUITE_TY_BASIC:
640 		ret = pdcp_test_data_sn_size[index];
641 		break;
642 	case PDCP_TEST_SUITE_TY_SDAP:
643 		ret = list_pdcp_sdap_tests[index].sn_size;
644 		break;
645 	default:
646 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
647 		return -1;
648 
649 	}
650 
651 	return ret;
652 }
653 
654 static uint8_t
pdcp_test_packet_direction_get(enum pdcp_test_suite_type suite_type,const int index)655 pdcp_test_packet_direction_get(enum pdcp_test_suite_type suite_type, const int index)
656 {
657 	uint8_t ret;
658 
659 	switch (suite_type) {
660 	case PDCP_TEST_SUITE_TY_BASIC:
661 		ret = pdcp_test_packet_direction[index];
662 		break;
663 	case PDCP_TEST_SUITE_TY_SDAP:
664 		ret = list_pdcp_sdap_tests[index].packet_direction;
665 		break;
666 	default:
667 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
668 		return -1;
669 	}
670 
671 	return ret;
672 }
673 
674 static enum rte_crypto_cipher_algorithm
pdcp_test_param_cipher_alg_get(enum pdcp_test_suite_type suite_type,const int index)675 pdcp_test_param_cipher_alg_get(enum pdcp_test_suite_type suite_type, const int index)
676 {
677 	enum rte_crypto_cipher_algorithm ret;
678 
679 	switch (suite_type) {
680 	case PDCP_TEST_SUITE_TY_BASIC:
681 		ret = pdcp_test_params[index].cipher_alg;
682 		break;
683 	case PDCP_TEST_SUITE_TY_SDAP:
684 		ret = list_pdcp_sdap_tests[index].param.cipher_alg;
685 		break;
686 	default:
687 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
688 		return 0;
689 	}
690 
691 	return ret;
692 }
693 
694 static uint8_t
pdcp_test_param_cipher_key_len_get(enum pdcp_test_suite_type suite_type,const int index)695 pdcp_test_param_cipher_key_len_get(enum pdcp_test_suite_type suite_type, const int index)
696 {
697 	uint8_t ret;
698 
699 	switch (suite_type) {
700 	case PDCP_TEST_SUITE_TY_BASIC:
701 		ret = pdcp_test_params[index].cipher_key_len;
702 		break;
703 	case PDCP_TEST_SUITE_TY_SDAP:
704 		ret = list_pdcp_sdap_tests[index].param.cipher_key_len;
705 		break;
706 	default:
707 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
708 		return -1;
709 	}
710 
711 	return ret;
712 }
713 
714 static const uint8_t*
pdcp_test_crypto_key_get(enum pdcp_test_suite_type suite_type,const int index)715 pdcp_test_crypto_key_get(enum pdcp_test_suite_type suite_type, const int index)
716 {
717 	const uint8_t *ret;
718 
719 	switch (suite_type) {
720 	case PDCP_TEST_SUITE_TY_BASIC:
721 		ret = pdcp_test_crypto_key[index];
722 		break;
723 	case PDCP_TEST_SUITE_TY_SDAP:
724 		ret = list_pdcp_sdap_tests[index].cipher_key;
725 		break;
726 	default:
727 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
728 		return NULL;
729 	}
730 
731 	return ret;
732 }
733 
734 static enum rte_crypto_auth_algorithm
pdcp_test_param_auth_alg_get(enum pdcp_test_suite_type suite_type,const int index)735 pdcp_test_param_auth_alg_get(enum pdcp_test_suite_type suite_type, const int index)
736 {
737 	enum rte_crypto_auth_algorithm ret;
738 
739 	switch (suite_type) {
740 	case PDCP_TEST_SUITE_TY_BASIC:
741 		ret = pdcp_test_params[index].auth_alg;
742 		break;
743 	case PDCP_TEST_SUITE_TY_SDAP:
744 		ret = list_pdcp_sdap_tests[index].param.auth_alg;
745 		break;
746 	default:
747 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
748 		return 0;
749 	}
750 
751 	return ret;
752 }
753 
754 static uint8_t
pdcp_test_param_auth_key_len_get(enum pdcp_test_suite_type suite_type,const int index)755 pdcp_test_param_auth_key_len_get(enum pdcp_test_suite_type suite_type, const int index)
756 {
757 	uint8_t ret;
758 
759 	switch (suite_type) {
760 	case PDCP_TEST_SUITE_TY_BASIC:
761 		ret = pdcp_test_params[index].auth_key_len;
762 		break;
763 	case PDCP_TEST_SUITE_TY_SDAP:
764 		ret = list_pdcp_sdap_tests[index].param.auth_key_len;
765 		break;
766 	default:
767 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
768 		return -1;
769 	}
770 
771 	return ret;
772 }
773 
774 static const uint8_t*
pdcp_test_auth_key_get(enum pdcp_test_suite_type suite_type,const int index)775 pdcp_test_auth_key_get(enum pdcp_test_suite_type suite_type, const int index)
776 {
777 	const uint8_t *ret;
778 
779 	switch (suite_type) {
780 	case PDCP_TEST_SUITE_TY_BASIC:
781 		ret = pdcp_test_auth_key[index];
782 		break;
783 	case PDCP_TEST_SUITE_TY_SDAP:
784 		ret = list_pdcp_sdap_tests[index].auth_key;
785 		break;
786 	default:
787 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
788 		return NULL;
789 	}
790 
791 	return ret;
792 }
793 
794 static const uint8_t*
pdcp_test_data_in_get(enum pdcp_test_suite_type suite_type,const int index)795 pdcp_test_data_in_get(enum pdcp_test_suite_type suite_type, const int index)
796 {
797 	const uint8_t *ret;
798 
799 	switch (suite_type) {
800 	case PDCP_TEST_SUITE_TY_BASIC:
801 		ret = pdcp_test_data_in[index];
802 		break;
803 	case PDCP_TEST_SUITE_TY_SDAP:
804 		ret = list_pdcp_sdap_tests[index].data_in;
805 		break;
806 	default:
807 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
808 		return NULL;
809 	}
810 
811 	return ret;
812 }
813 
814 static uint8_t
pdcp_test_data_in_len_get(enum pdcp_test_suite_type suite_type,const int index)815 pdcp_test_data_in_len_get(enum pdcp_test_suite_type suite_type, const int index)
816 {
817 	uint8_t ret;
818 
819 	switch (suite_type) {
820 	case PDCP_TEST_SUITE_TY_BASIC:
821 		ret = pdcp_test_data_in_len[index];
822 		break;
823 	case PDCP_TEST_SUITE_TY_SDAP:
824 		ret = list_pdcp_sdap_tests[index].in_len;
825 		break;
826 	default:
827 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
828 		return -1;
829 	}
830 
831 	return ret;
832 }
833 
834 static const uint8_t*
pdcp_test_data_out_get(enum pdcp_test_suite_type suite_type,const int index)835 pdcp_test_data_out_get(enum pdcp_test_suite_type suite_type, const int index)
836 {
837 	const uint8_t *ret;
838 
839 	switch (suite_type) {
840 	case PDCP_TEST_SUITE_TY_BASIC:
841 		ret = pdcp_test_data_out[index];
842 		break;
843 	case PDCP_TEST_SUITE_TY_SDAP:
844 		ret = list_pdcp_sdap_tests[index].data_out;
845 		break;
846 	default:
847 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
848 		return NULL;
849 	}
850 
851 	return ret;
852 }
853 
854 static uint32_t
pdcp_test_hfn_get(enum pdcp_test_suite_type suite_type,const int index)855 pdcp_test_hfn_get(enum pdcp_test_suite_type suite_type, const int index)
856 {
857 	uint32_t ret;
858 
859 	switch (suite_type) {
860 	case PDCP_TEST_SUITE_TY_BASIC:
861 		ret = pdcp_test_hfn[index];
862 		break;
863 	case PDCP_TEST_SUITE_TY_SDAP:
864 		ret = list_pdcp_sdap_tests[index].hfn;
865 		break;
866 	default:
867 		RTE_LOG(ERR, USER1, "Invalid suite_type: %d\n", suite_type);
868 		return -1;
869 	}
870 
871 	return ret;
872 }
873 
874 static int
create_test_conf_from_index(const int index,struct pdcp_test_conf * conf,enum pdcp_test_suite_type suite_type)875 create_test_conf_from_index(const int index, struct pdcp_test_conf *conf,
876 			    enum pdcp_test_suite_type suite_type)
877 {
878 	const struct pdcp_testsuite_params *ts_params = &testsuite_params;
879 	struct rte_crypto_sym_xform c_xfrm, a_xfrm;
880 	const uint8_t *data, *expected;
881 	uint32_t sn, expected_len;
882 	int pdcp_hdr_sz;
883 
884 	memset(conf, 0, sizeof(*conf));
885 	memset(&c_xfrm, 0, sizeof(c_xfrm));
886 	memset(&a_xfrm, 0, sizeof(a_xfrm));
887 
888 	conf->entity.sess_mpool = ts_params->sess_pool;
889 	conf->entity.cop_pool = ts_params->cop_pool;
890 	conf->entity.ctrl_pdu_pool = ts_params->mbuf_pool;
891 	conf->entity.pdcp_xfrm.bearer = pdcp_test_bearer_get(suite_type, index);
892 	conf->entity.pdcp_xfrm.en_ordering = 0;
893 	conf->entity.pdcp_xfrm.remove_duplicates = 0;
894 	conf->entity.pdcp_xfrm.domain = pdcp_test_param_domain_get(suite_type, index);
895 	conf->entity.t_reordering = t_reorder_timer;
896 
897 	if (pdcp_test_packet_direction_get(suite_type, index) == PDCP_DIR_UPLINK)
898 		conf->entity.pdcp_xfrm.pkt_dir = RTE_SECURITY_PDCP_UPLINK;
899 	else
900 		conf->entity.pdcp_xfrm.pkt_dir = RTE_SECURITY_PDCP_DOWNLINK;
901 
902 	conf->entity.pdcp_xfrm.sn_size = pdcp_test_data_sn_size_get(suite_type, index);
903 
904 	/* Zero initialize unsupported flags */
905 	conf->entity.pdcp_xfrm.hfn_threshold = 0;
906 	conf->entity.pdcp_xfrm.hfn_ovrd = 0;
907 
908 	conf->entity.pdcp_xfrm.sdap_enabled = (suite_type == PDCP_TEST_SUITE_TY_SDAP);
909 
910 	c_xfrm.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
911 	c_xfrm.cipher.algo = pdcp_test_param_cipher_alg_get(suite_type, index);
912 	c_xfrm.cipher.key.length = pdcp_test_param_cipher_key_len_get(suite_type, index);
913 	c_xfrm.cipher.key.data = pdcp_test_crypto_key_get(suite_type, index);
914 
915 	a_xfrm.type = RTE_CRYPTO_SYM_XFORM_AUTH;
916 
917 	if (pdcp_test_param_auth_alg_get(suite_type, index) == 0) {
918 		conf->is_integrity_protected = false;
919 	} else {
920 		a_xfrm.auth.algo = pdcp_test_param_auth_alg_get(suite_type, index);
921 		a_xfrm.auth.key.data = pdcp_test_auth_key_get(suite_type, index);
922 		a_xfrm.auth.key.length = pdcp_test_param_auth_key_len_get(suite_type, index);
923 		conf->is_integrity_protected = true;
924 	}
925 
926 	pdcp_hdr_sz = pdcp_hdr_size_get(pdcp_test_data_sn_size_get(suite_type, index));
927 
928 	/*
929 	 * Uplink means PDCP entity is configured for transmit. Downlink means PDCP entity is
930 	 * configured for receive. When integrity protecting is enabled, PDCP always performs
931 	 * digest-encrypted or auth-gen-encrypt for uplink (and decrypt-auth-verify for downlink).
932 	 * So for uplink, crypto chain would be auth-cipher while for downlink it would be
933 	 * cipher-auth.
934 	 *
935 	 * When integrity protection is not required, xform would be cipher only.
936 	 */
937 
938 	if (conf->is_integrity_protected) {
939 		if (conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK) {
940 			conf->entity.crypto_xfrm = &conf->a_xfrm;
941 
942 			a_xfrm.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
943 			a_xfrm.next = &conf->c_xfrm;
944 
945 			c_xfrm.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
946 			c_xfrm.next = NULL;
947 		} else {
948 			conf->entity.crypto_xfrm = &conf->c_xfrm;
949 
950 			c_xfrm.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
951 			c_xfrm.next = &conf->a_xfrm;
952 
953 			a_xfrm.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
954 			a_xfrm.next = NULL;
955 		}
956 	} else {
957 		conf->entity.crypto_xfrm = &conf->c_xfrm;
958 		c_xfrm.next = NULL;
959 
960 		if (conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK)
961 			c_xfrm.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
962 		else
963 			c_xfrm.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
964 	}
965 
966 	/* Update xforms to match PDCP requirements */
967 
968 	if ((c_xfrm.cipher.algo == RTE_CRYPTO_CIPHER_AES_CTR) ||
969 	    (c_xfrm.cipher.algo == RTE_CRYPTO_CIPHER_ZUC_EEA3 ||
970 	    (c_xfrm.cipher.algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2)))
971 		c_xfrm.cipher.iv.length = PDCP_IV_LEN;
972 	else
973 		c_xfrm.cipher.iv.length = 0;
974 
975 	if (conf->is_integrity_protected) {
976 		if (a_xfrm.auth.algo == RTE_CRYPTO_AUTH_NULL)
977 			a_xfrm.auth.digest_length = 0;
978 		else
979 			a_xfrm.auth.digest_length = RTE_PDCP_MAC_I_LEN;
980 
981 		if ((a_xfrm.auth.algo == RTE_CRYPTO_AUTH_ZUC_EIA3) ||
982 		    (a_xfrm.auth.algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2))
983 			a_xfrm.auth.iv.length = PDCP_IV_LEN;
984 		else
985 			a_xfrm.auth.iv.length = 0;
986 	}
987 
988 	conf->c_xfrm = c_xfrm;
989 	conf->a_xfrm = a_xfrm;
990 
991 	conf->entity.dev_id = (uint8_t)cryptodev_id_get(conf->is_integrity_protected,
992 			&conf->c_xfrm, &conf->a_xfrm);
993 
994 	if (pdcp_test_param_domain_get(suite_type, index) == RTE_SECURITY_PDCP_MODE_CONTROL ||
995 	    pdcp_test_param_domain_get(suite_type, index) == RTE_SECURITY_PDCP_MODE_DATA) {
996 		data = pdcp_test_data_in_get(suite_type, index);
997 		sn = pdcp_sn_from_raw_get(data, pdcp_test_data_sn_size_get(suite_type, index));
998 		conf->entity.pdcp_xfrm.hfn = pdcp_test_hfn_get(suite_type, index);
999 		conf->entity.sn = sn;
1000 	}
1001 
1002 	if (conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK) {
1003 #ifdef VEC_DUMP
1004 		debug_hexdump(stdout, "Original vector:", pdcp_test_data_in_get(suite_type, index),
1005 				pdcp_test_data_in_len_get(suite_type, index));
1006 #endif
1007 		/* Since the vectors available already have PDCP header, trim the same */
1008 		conf->input_len = pdcp_test_data_in_len_get(suite_type, index) - pdcp_hdr_sz;
1009 		memcpy(conf->input, pdcp_test_data_in_get(suite_type, index) + pdcp_hdr_sz,
1010 		       conf->input_len);
1011 	} else {
1012 		conf->input_len = pdcp_test_data_in_len_get(suite_type, index);
1013 
1014 		if (conf->is_integrity_protected)
1015 			conf->input_len += RTE_PDCP_MAC_I_LEN;
1016 
1017 		memcpy(conf->input, pdcp_test_data_out_get(suite_type, index), conf->input_len);
1018 #ifdef VEC_DUMP
1019 		debug_hexdump(stdout, "Original vector:", conf->input, conf->input_len);
1020 #endif
1021 	}
1022 
1023 	if (conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK)
1024 		expected = pdcp_test_data_out_get(suite_type, index);
1025 	else
1026 		expected = pdcp_test_data_in_get(suite_type, index);
1027 
1028 	/* Calculate expected packet length */
1029 	expected_len = pdcp_test_data_in_len_get(suite_type, index);
1030 
1031 	/* In DL processing, PDCP header would be stripped */
1032 	if (conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) {
1033 		expected += pdcp_hdr_sz;
1034 		expected_len -= pdcp_hdr_sz;
1035 	}
1036 
1037 	/* In UL processing with integrity protection, MAC would be added */
1038 	if (conf->is_integrity_protected &&
1039 	    conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK)
1040 		expected_len += 4;
1041 
1042 	memcpy(conf->output, expected, expected_len);
1043 	conf->output_len = expected_len;
1044 
1045 	return 0;
1046 }
1047 
1048 static void
test_conf_input_data_modify(struct pdcp_test_conf * conf,int inp_len)1049 test_conf_input_data_modify(struct pdcp_test_conf *conf, int inp_len)
1050 {
1051 	conf->input_len = inp_len;
1052 	memset(conf->input, 0xab, inp_len);
1053 }
1054 
1055 static struct rte_pdcp_entity*
test_entity_create(const struct pdcp_test_conf * t_conf,int * rc)1056 test_entity_create(const struct pdcp_test_conf *t_conf, int *rc)
1057 {
1058 	struct rte_pdcp_entity *pdcp_entity;
1059 	int ret;
1060 
1061 	if (t_conf->entity.pdcp_xfrm.sn_size != RTE_SECURITY_PDCP_SN_SIZE_12 &&
1062 	    t_conf->entity.pdcp_xfrm.sn_size != RTE_SECURITY_PDCP_SN_SIZE_18) {
1063 		*rc = -ENOTSUP;
1064 		return NULL;
1065 	}
1066 
1067 	if (t_conf->entity.dev_id == CDEV_INVALID_ID) {
1068 		RTE_LOG(DEBUG, USER1, "Could not find device with required capabilities\n");
1069 		*rc = -ENOTSUP;
1070 		return NULL;
1071 	}
1072 
1073 	ret = cryptodev_init(t_conf->entity.dev_id);
1074 	if (ret) {
1075 		*rc = ret;
1076 		RTE_LOG(DEBUG, USER1, "Could not initialize cryptodev\n");
1077 		return NULL;
1078 	}
1079 
1080 	rte_errno = 0;
1081 
1082 	pdcp_entity = rte_pdcp_entity_establish(&t_conf->entity);
1083 	if (pdcp_entity == NULL) {
1084 		*rc = -rte_errno;
1085 		RTE_LOG(DEBUG, USER1, "Could not establish PDCP entity\n");
1086 		return NULL;
1087 	}
1088 
1089 	return pdcp_entity;
1090 }
1091 
1092 static uint16_t
test_process_packets(const struct rte_pdcp_entity * pdcp_entity,uint8_t cdev_id,struct rte_mbuf * in_mb[],uint16_t nb_in,struct rte_mbuf * out_mb[],uint16_t * nb_err)1093 test_process_packets(const struct rte_pdcp_entity *pdcp_entity, uint8_t cdev_id,
1094 		     struct rte_mbuf *in_mb[], uint16_t nb_in,
1095 		     struct rte_mbuf *out_mb[], uint16_t *nb_err)
1096 {
1097 	struct rte_crypto_op *cop, *cop_out;
1098 	struct rte_pdcp_group grp[1];
1099 	uint16_t nb_success, nb_grp;
1100 	struct rte_mbuf *mbuf, *mb;
1101 
1102 	if (nb_in != 1)
1103 		return -ENOTSUP;
1104 
1105 	mbuf = in_mb[0];
1106 
1107 	nb_success = rte_pdcp_pkt_pre_process(pdcp_entity, &mbuf, &cop_out, 1, nb_err);
1108 	if (nb_success != 1 || *nb_err != 0) {
1109 		RTE_LOG(ERR, USER1, "Could not pre process PDCP packet\n");
1110 		return TEST_FAILED;
1111 	}
1112 
1113 #ifdef VEC_DUMP
1114 	printf("Pre-processed vector:\n");
1115 	rte_pktmbuf_dump(stdout, mbuf, rte_pktmbuf_pkt_len(mbuf));
1116 #endif
1117 
1118 	cop = process_crypto_request(cdev_id, cop_out);
1119 	if (cop == NULL) {
1120 		RTE_LOG(ERR, USER1, "Could not process crypto request\n");
1121 		return -EIO;
1122 	}
1123 
1124 	grp[0].id.val = 0;
1125 
1126 	nb_grp = rte_pdcp_pkt_crypto_group(&cop_out, &mb, grp, 1);
1127 	if (nb_grp != 1 || grp[0].cnt != 1) {
1128 		RTE_LOG(ERR, USER1, "Could not group PDCP crypto results\n");
1129 		return -ENOTRECOVERABLE;
1130 	}
1131 
1132 	if ((uintptr_t)pdcp_entity != grp[0].id.val) {
1133 		RTE_LOG(ERR, USER1, "PDCP entity not matching the one from crypto_op\n");
1134 		return -ENOTRECOVERABLE;
1135 	}
1136 
1137 #ifdef VEC_DUMP
1138 	printf("Crypto processed vector:\n");
1139 	rte_pktmbuf_dump(stdout, cop->sym->m_dst, rte_pktmbuf_pkt_len(mbuf));
1140 #endif
1141 
1142 	return rte_pdcp_pkt_post_process(grp[0].id.ptr, grp[0].m, out_mb, grp[0].cnt, nb_err);
1143 }
1144 
1145 static struct rte_mbuf*
mbuf_from_data_create(uint8_t * data,uint16_t data_len)1146 mbuf_from_data_create(uint8_t *data, uint16_t data_len)
1147 {
1148 	const struct pdcp_testsuite_params *ts_params = &testsuite_params;
1149 	struct rte_mbuf *mbuf;
1150 	uint8_t *input_text;
1151 
1152 	mbuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
1153 	if (mbuf == NULL) {
1154 		RTE_LOG(ERR, USER1, "Could not create mbuf\n");
1155 		return NULL;
1156 	}
1157 
1158 	memset(rte_pktmbuf_mtod(mbuf, uint8_t *), 0, rte_pktmbuf_tailroom(mbuf));
1159 
1160 	input_text = (uint8_t *)rte_pktmbuf_append(mbuf, data_len);
1161 	memcpy(input_text, data, data_len);
1162 
1163 	return mbuf;
1164 }
1165 
1166 static int
test_attempt_single(struct pdcp_test_conf * t_conf)1167 test_attempt_single(struct pdcp_test_conf *t_conf)
1168 {
1169 	struct rte_mbuf *mbuf, **out_mb = NULL;
1170 	struct rte_pdcp_entity *pdcp_entity;
1171 	uint16_t nb_success, nb_err;
1172 	int ret = 0, nb_max_out_mb;
1173 
1174 	pdcp_entity = test_entity_create(t_conf, &ret);
1175 	if (pdcp_entity == NULL)
1176 		goto exit;
1177 
1178 	/* Allocate buffer for holding mbufs returned */
1179 
1180 	/* Max packets that can be cached in entity + burst size */
1181 	nb_max_out_mb = pdcp_entity->max_pkt_cache + 1;
1182 	out_mb = rte_malloc(NULL, nb_max_out_mb * sizeof(uintptr_t), 0);
1183 	if (out_mb == NULL) {
1184 		RTE_LOG(ERR, USER1, "Could not allocate buffer for holding out_mb buffers\n");
1185 		ret = -ENOMEM;
1186 		goto entity_release;
1187 	}
1188 
1189 	mbuf = mbuf_from_data_create(t_conf->input, t_conf->input_len);
1190 	if (mbuf == NULL) {
1191 		ret = -ENOMEM;
1192 		goto entity_release;
1193 	}
1194 
1195 #ifdef VEC_DUMP
1196 	printf("Adjusted vector:\n");
1197 	rte_pktmbuf_dump(stdout, mbuf, t_conf->input_len);
1198 #endif
1199 
1200 	nb_success = test_process_packets(pdcp_entity, t_conf->entity.dev_id, &mbuf, 1, out_mb,
1201 			&nb_err);
1202 	if (nb_success != 1 || nb_err != 0) {
1203 		RTE_LOG(ERR, USER1, "Could not process PDCP packet\n");
1204 		ret = TEST_FAILED;
1205 		goto mbuf_free;
1206 	}
1207 
1208 	/* If expected output provided - verify, else - store for future use */
1209 	if (t_conf->output_len) {
1210 		ret = pdcp_known_vec_verify(mbuf, t_conf->output, t_conf->output_len);
1211 		if (ret)
1212 			goto mbuf_free;
1213 	} else {
1214 		ret = pktmbuf_read_into(mbuf, t_conf->output, RTE_PDCP_CTRL_PDU_SIZE_MAX);
1215 		if (ret)
1216 			goto mbuf_free;
1217 		t_conf->output_len = mbuf->pkt_len;
1218 	}
1219 
1220 	ret = rte_pdcp_entity_suspend(pdcp_entity, out_mb);
1221 	if (ret) {
1222 		RTE_LOG(DEBUG, USER1, "Could not suspend PDCP entity\n");
1223 		goto mbuf_free;
1224 	}
1225 
1226 mbuf_free:
1227 	rte_pktmbuf_free(mbuf);
1228 entity_release:
1229 	rte_pdcp_entity_release(pdcp_entity, out_mb);
1230 	rte_free(out_mb);
1231 exit:
1232 	return ret;
1233 }
1234 
1235 static void
uplink_to_downlink_convert(const struct pdcp_test_conf * ul_cfg,struct pdcp_test_conf * dl_cfg)1236 uplink_to_downlink_convert(const struct pdcp_test_conf *ul_cfg,
1237 			   struct pdcp_test_conf *dl_cfg)
1238 {
1239 	assert(ul_cfg->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK);
1240 
1241 	memcpy(dl_cfg, ul_cfg, sizeof(*dl_cfg));
1242 	dl_cfg->entity.pdcp_xfrm.pkt_dir = RTE_SECURITY_PDCP_DOWNLINK;
1243 	dl_cfg->entity.reverse_iv_direction = false;
1244 
1245 	if (dl_cfg->is_integrity_protected) {
1246 		dl_cfg->entity.crypto_xfrm = &dl_cfg->c_xfrm;
1247 
1248 		dl_cfg->c_xfrm.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
1249 		dl_cfg->c_xfrm.next = &dl_cfg->a_xfrm;
1250 
1251 		dl_cfg->a_xfrm.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
1252 		dl_cfg->a_xfrm.next = NULL;
1253 	} else {
1254 		dl_cfg->entity.crypto_xfrm = &dl_cfg->c_xfrm;
1255 		dl_cfg->c_xfrm.next = NULL;
1256 		dl_cfg->c_xfrm.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
1257 	}
1258 
1259 	dl_cfg->entity.dev_id = (uint8_t)cryptodev_id_get(dl_cfg->is_integrity_protected,
1260 			&dl_cfg->c_xfrm, &dl_cfg->a_xfrm);
1261 
1262 	memcpy(dl_cfg->input, ul_cfg->output, ul_cfg->output_len);
1263 	dl_cfg->input_len = ul_cfg->output_len;
1264 
1265 	memcpy(dl_cfg->output, ul_cfg->input, ul_cfg->input_len);
1266 	dl_cfg->output_len = ul_cfg->input_len;
1267 }
1268 
1269 /*
1270  * According to ETSI TS 138 323 V17.1.0, Section 5.2.2.1,
1271  * SN could be divided into following ranges,
1272  * relatively to current value of RX_DELIV state:
1273  * +-------------+-------------+-------------+-------------+
1274  * |  -Outside   |  -Window    |   +Window   |  +Outside   |
1275  * |   (valid)   |  (Invalid)  |   (Valid)   |  (Invalid)  |
1276  * +-------------+-------------^-------------+-------------+
1277  *                             |
1278  *                             v
1279  *                        SN(RX_DELIV)
1280  */
1281 enum sn_range_type {
1282 	SN_RANGE_MINUS_OUTSIDE,
1283 	SN_RANGE_MINUS_WINDOW,
1284 	SN_RANGE_PLUS_WINDOW,
1285 	SN_RANGE_PLUS_OUTSIDE,
1286 };
1287 
1288 #define PDCP_SET_COUNT(hfn, sn, size) ((hfn << size) | (sn & ((1 << size) - 1)))
1289 
1290 /*
1291  * Take uplink test case as base, modify RX_DELIV in state and SN in input
1292  */
1293 static int
test_sn_range_type(enum sn_range_type type,struct pdcp_test_conf * conf)1294 test_sn_range_type(enum sn_range_type type, struct pdcp_test_conf *conf)
1295 {
1296 	uint32_t rx_deliv_hfn, rx_deliv_sn, new_hfn, new_sn;
1297 	const int domain = conf->entity.pdcp_xfrm.domain;
1298 	struct pdcp_test_conf dl_conf;
1299 	int ret, expected_ret;
1300 
1301 	if (conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK)
1302 		return TEST_SKIPPED;
1303 
1304 	if (domain != RTE_SECURITY_PDCP_MODE_CONTROL && domain != RTE_SECURITY_PDCP_MODE_DATA)
1305 		return TEST_SKIPPED;
1306 
1307 	const uint32_t sn_size = conf->entity.pdcp_xfrm.sn_size;
1308 	const uint32_t window_size = PDCP_WINDOW_SIZE(sn_size);
1309 	/* Max value of SN that could fit in `sn_size` bits */
1310 	const uint32_t max_sn = (1 << sn_size) - 1;
1311 	const uint32_t shift = (max_sn - window_size) / 2;
1312 	/* Could be any number up to `shift` value */
1313 	const uint32_t default_sn = RTE_MIN(2u, shift);
1314 
1315 	/* Initialize HFN as non zero value, to be able check values before */
1316 	rx_deliv_hfn = 0xa;
1317 
1318 	switch (type) {
1319 	case SN_RANGE_PLUS_WINDOW:
1320 		/* Within window size, HFN stay same */
1321 		new_hfn = rx_deliv_hfn;
1322 		rx_deliv_sn = default_sn;
1323 		new_sn = rx_deliv_sn + 1;
1324 		expected_ret = TEST_SUCCESS;
1325 		break;
1326 	case SN_RANGE_MINUS_WINDOW:
1327 		/* Within window size, HFN stay same */
1328 		new_hfn = rx_deliv_hfn;
1329 		rx_deliv_sn = default_sn;
1330 		new_sn = rx_deliv_sn - 1;
1331 		expected_ret = TEST_FAILED;
1332 		break;
1333 	case SN_RANGE_PLUS_OUTSIDE:
1334 		/* RCVD_SN >= SN(RX_DELIV) + Window_Size */
1335 		new_hfn = rx_deliv_hfn - 1;
1336 		rx_deliv_sn = default_sn;
1337 		new_sn = rx_deliv_sn + window_size;
1338 		expected_ret = TEST_FAILED;
1339 		break;
1340 	case SN_RANGE_MINUS_OUTSIDE:
1341 		/* RCVD_SN < SN(RX_DELIV) - Window_Size */
1342 		new_hfn = rx_deliv_hfn + 1;
1343 		rx_deliv_sn = window_size + default_sn;
1344 		new_sn = rx_deliv_sn - window_size - 1;
1345 		expected_ret = TEST_SUCCESS;
1346 		break;
1347 	default:
1348 		return TEST_FAILED;
1349 	}
1350 
1351 	/* Configure Uplink to generate expected, encrypted packet */
1352 	pdcp_sn_to_raw_set(conf->input, new_sn, conf->entity.pdcp_xfrm.sn_size);
1353 	conf->entity.out_of_order_delivery = true;
1354 	conf->entity.reverse_iv_direction = true;
1355 	conf->entity.pdcp_xfrm.hfn = new_hfn;
1356 	conf->entity.sn = new_sn;
1357 	conf->output_len = 0;
1358 	ret = test_attempt_single(conf);
1359 	if (ret != TEST_SUCCESS)
1360 		return ret;
1361 
1362 	/* Flip configuration to downlink */
1363 	uplink_to_downlink_convert(conf, &dl_conf);
1364 
1365 	/* Modify the rx_deliv to verify the expected behaviour */
1366 	dl_conf.entity.pdcp_xfrm.hfn = rx_deliv_hfn;
1367 	dl_conf.entity.sn = rx_deliv_sn;
1368 	ret = test_attempt_single(&dl_conf);
1369 	if ((ret == TEST_SKIPPED) || (ret == -ENOTSUP))
1370 		return ret;
1371 
1372 	TEST_ASSERT_EQUAL(ret, expected_ret, "Unexpected result");
1373 
1374 	return TEST_SUCCESS;
1375 }
1376 
1377 static int
test_sn_plus_window(struct pdcp_test_conf * t_conf)1378 test_sn_plus_window(struct pdcp_test_conf *t_conf)
1379 {
1380 	return test_sn_range_type(SN_RANGE_PLUS_WINDOW, t_conf);
1381 }
1382 
1383 static int
test_sn_minus_window(struct pdcp_test_conf * t_conf)1384 test_sn_minus_window(struct pdcp_test_conf *t_conf)
1385 {
1386 	return test_sn_range_type(SN_RANGE_MINUS_WINDOW, t_conf);
1387 }
1388 
1389 static int
test_sn_plus_outside(struct pdcp_test_conf * t_conf)1390 test_sn_plus_outside(struct pdcp_test_conf *t_conf)
1391 {
1392 	return test_sn_range_type(SN_RANGE_PLUS_OUTSIDE, t_conf);
1393 }
1394 
1395 static int
test_sn_minus_outside(struct pdcp_test_conf * t_conf)1396 test_sn_minus_outside(struct pdcp_test_conf *t_conf)
1397 {
1398 	return test_sn_range_type(SN_RANGE_MINUS_OUTSIDE, t_conf);
1399 }
1400 
1401 static struct rte_mbuf *
generate_packet_for_dl_with_sn(struct pdcp_test_conf ul_conf,uint32_t count)1402 generate_packet_for_dl_with_sn(struct pdcp_test_conf ul_conf, uint32_t count)
1403 {
1404 	enum rte_security_pdcp_sn_size sn_size = ul_conf.entity.pdcp_xfrm.sn_size;
1405 	int ret;
1406 
1407 	ul_conf.entity.pdcp_xfrm.hfn = pdcp_hfn_from_count_get(count, sn_size);
1408 	ul_conf.entity.sn = pdcp_sn_from_count_get(count, sn_size);
1409 	ul_conf.entity.out_of_order_delivery = true;
1410 	ul_conf.entity.reverse_iv_direction = true;
1411 	ul_conf.output_len = 0;
1412 
1413 	ret = test_attempt_single(&ul_conf);
1414 	if (ret != TEST_SUCCESS)
1415 		return NULL;
1416 
1417 	return mbuf_from_data_create(ul_conf.output, ul_conf.output_len);
1418 }
1419 
1420 static bool
array_asc_sorted_check(struct rte_mbuf * m[],uint32_t len,enum rte_security_pdcp_sn_size sn_size)1421 array_asc_sorted_check(struct rte_mbuf *m[], uint32_t len, enum rte_security_pdcp_sn_size sn_size)
1422 {
1423 	uint32_t i;
1424 
1425 	if (len < 2)
1426 		return true;
1427 
1428 	for (i = 0; i < (len - 1); i++) {
1429 		if (pdcp_sn_from_raw_get(rte_pktmbuf_mtod(m[i], void *), sn_size) >
1430 		    pdcp_sn_from_raw_get(rte_pktmbuf_mtod(m[i + 1], void *), sn_size))
1431 			return false;
1432 	}
1433 
1434 	return true;
1435 }
1436 
1437 static int
test_reorder_gap_fill(struct pdcp_test_conf * ul_conf)1438 test_reorder_gap_fill(struct pdcp_test_conf *ul_conf)
1439 {
1440 	const enum rte_security_pdcp_sn_size sn_size = ul_conf->entity.pdcp_xfrm.sn_size;
1441 	struct rte_mbuf *m0 = NULL, *m1 = NULL, *out_mb[2] = {0};
1442 	uint16_t nb_success = 0, nb_err = 0;
1443 	struct rte_pdcp_entity *pdcp_entity;
1444 	struct pdcp_test_conf dl_conf;
1445 	int ret = TEST_FAILED, nb_out;
1446 	uint8_t cdev_id;
1447 
1448 	const int start_count = 0;
1449 
1450 	if (ul_conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK)
1451 		return TEST_SKIPPED;
1452 
1453 	/* Create configuration for actual testing */
1454 	uplink_to_downlink_convert(ul_conf, &dl_conf);
1455 	dl_conf.entity.pdcp_xfrm.hfn = pdcp_hfn_from_count_get(start_count, sn_size);
1456 	dl_conf.entity.sn = pdcp_sn_from_count_get(start_count, sn_size);
1457 
1458 	pdcp_entity = test_entity_create(&dl_conf, &ret);
1459 	if (pdcp_entity == NULL)
1460 		return ret;
1461 
1462 	cdev_id = dl_conf.entity.dev_id;
1463 
1464 	/* Send packet with SN > RX_DELIV to create a gap */
1465 	m1 = generate_packet_for_dl_with_sn(*ul_conf, start_count + 1);
1466 	ASSERT_TRUE_OR_GOTO(m1 != NULL, exit, "Could not allocate buffer for packet\n");
1467 
1468 	/* Buffered packets after insert [NULL, m1] */
1469 	nb_success = test_process_packets(pdcp_entity, cdev_id, &m1, 1, out_mb, &nb_err);
1470 	ASSERT_TRUE_OR_GOTO(nb_err == 0, exit, "Error occurred during packet process\n");
1471 	ASSERT_TRUE_OR_GOTO(nb_success == 0, exit, "Packet was not buffered as expected\n");
1472 	m1 = NULL; /* Packet was moved to PDCP lib */
1473 
1474 	/* Generate packet to fill the existing gap */
1475 	m0 = generate_packet_for_dl_with_sn(*ul_conf, start_count);
1476 	ASSERT_TRUE_OR_GOTO(m0 != NULL, exit, "Could not allocate buffer for packet\n");
1477 
1478 	/*
1479 	 * Buffered packets after insert [m0, m1]
1480 	 * Gap filled, all packets should be returned
1481 	 */
1482 	nb_success = test_process_packets(pdcp_entity, cdev_id, &m0, 1, out_mb, &nb_err);
1483 	ASSERT_TRUE_OR_GOTO(nb_err == 0, exit, "Error occurred during packet process\n");
1484 	ASSERT_TRUE_OR_GOTO(nb_success == 2, exit,
1485 			"Packet count mismatch (received: %i, expected: 2)\n", nb_success);
1486 	m0 = NULL; /* Packet was moved to out_mb */
1487 
1488 	/* Check that packets in correct order */
1489 	ASSERT_TRUE_OR_GOTO(array_asc_sorted_check(out_mb, nb_success, sn_size), exit,
1490 			"Error occurred during packet drain\n");
1491 	ASSERT_TRUE_OR_GOTO(testsuite_params.timer_is_running == false, exit,
1492 			"Timer should be stopped after full drain\n");
1493 
1494 	ret = TEST_SUCCESS;
1495 exit:
1496 	rte_pktmbuf_free(m0);
1497 	rte_pktmbuf_free(m1);
1498 	rte_pktmbuf_free_bulk(out_mb, nb_success);
1499 	nb_out = rte_pdcp_entity_release(pdcp_entity, out_mb);
1500 	rte_pktmbuf_free_bulk(out_mb, nb_out);
1501 	return ret;
1502 }
1503 
1504 static int
test_reorder_gap_in_reorder_buffer(const struct pdcp_test_conf * ul_conf)1505 test_reorder_gap_in_reorder_buffer(const struct pdcp_test_conf *ul_conf)
1506 {
1507 	const enum rte_security_pdcp_sn_size sn_size = ul_conf->entity.pdcp_xfrm.sn_size;
1508 	struct rte_mbuf *m = NULL, *out_mb[2] = {0};
1509 	uint16_t nb_success = 0, nb_err = 0;
1510 	struct rte_pdcp_entity *pdcp_entity;
1511 	int ret = TEST_FAILED, nb_out, i;
1512 	struct pdcp_test_conf dl_conf;
1513 	uint8_t cdev_id;
1514 
1515 	const int start_count = 0;
1516 
1517 	if (ul_conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK)
1518 		return TEST_SKIPPED;
1519 
1520 	/* Create configuration for actual testing */
1521 	uplink_to_downlink_convert(ul_conf, &dl_conf);
1522 	dl_conf.entity.pdcp_xfrm.hfn = pdcp_hfn_from_count_get(start_count, sn_size);
1523 	dl_conf.entity.sn = pdcp_sn_from_count_get(start_count, sn_size);
1524 	pdcp_entity = test_entity_create(&dl_conf, &ret);
1525 	if (pdcp_entity == NULL)
1526 		return ret;
1527 
1528 	cdev_id = dl_conf.entity.dev_id;
1529 
1530 	/* Create two gaps [NULL, m1, NULL, m3]*/
1531 	for (i = 0; i < 2; i++) {
1532 		m = generate_packet_for_dl_with_sn(*ul_conf, start_count + 2 * i + 1);
1533 		ASSERT_TRUE_OR_GOTO(m != NULL, exit, "Could not allocate buffer for packet\n");
1534 		nb_success = test_process_packets(pdcp_entity, cdev_id, &m, 1, out_mb, &nb_err);
1535 		ASSERT_TRUE_OR_GOTO(nb_err == 0, exit, "Error occurred during packet process\n");
1536 		ASSERT_TRUE_OR_GOTO(nb_success == 0, exit, "Packet was not buffered as expected\n");
1537 		m = NULL; /* Packet was moved to PDCP lib */
1538 	}
1539 
1540 	/* Generate packet to fill the first gap */
1541 	m = generate_packet_for_dl_with_sn(*ul_conf, start_count);
1542 	ASSERT_TRUE_OR_GOTO(m != NULL, exit, "Could not allocate buffer for packet\n");
1543 
1544 	/*
1545 	 * Buffered packets after insert [m0, m1, NULL, m3]
1546 	 * Only first gap should be filled, timer should be restarted for second gap
1547 	 */
1548 	nb_success = test_process_packets(pdcp_entity, cdev_id, &m, 1, out_mb, &nb_err);
1549 	ASSERT_TRUE_OR_GOTO(nb_err == 0, exit, "Error occurred during packet process\n");
1550 	ASSERT_TRUE_OR_GOTO(nb_success == 2, exit,
1551 			"Packet count mismatch (received: %i, expected: 2)\n", nb_success);
1552 	m = NULL;
1553 	/* Check that packets in correct order */
1554 	ASSERT_TRUE_OR_GOTO(array_asc_sorted_check(out_mb, nb_success, sn_size),
1555 			exit, "Error occurred during packet drain\n");
1556 	ASSERT_TRUE_OR_GOTO(testsuite_params.timer_is_running == true, exit,
1557 			"Timer should be restarted after partial drain");
1558 
1559 
1560 	ret = TEST_SUCCESS;
1561 exit:
1562 	rte_pktmbuf_free(m);
1563 	rte_pktmbuf_free_bulk(out_mb, nb_success);
1564 	nb_out = rte_pdcp_entity_release(pdcp_entity, out_mb);
1565 	rte_pktmbuf_free_bulk(out_mb, nb_out);
1566 	return ret;
1567 }
1568 
1569 static int
test_reorder_buffer_full_window_size_sn_12(const struct pdcp_test_conf * ul_conf)1570 test_reorder_buffer_full_window_size_sn_12(const struct pdcp_test_conf *ul_conf)
1571 {
1572 	const enum rte_security_pdcp_sn_size sn_size = ul_conf->entity.pdcp_xfrm.sn_size;
1573 	const uint32_t window_size = PDCP_WINDOW_SIZE(sn_size);
1574 	struct rte_mbuf *m1 = NULL, **out_mb = NULL;
1575 	uint16_t nb_success = 0, nb_err = 0;
1576 	struct rte_pdcp_entity *pdcp_entity;
1577 	struct pdcp_test_conf dl_conf;
1578 	const int rx_deliv = 0;
1579 	int ret = TEST_FAILED;
1580 	size_t i, nb_out;
1581 	uint8_t cdev_id;
1582 
1583 	if (ul_conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK ||
1584 		sn_size != RTE_SECURITY_PDCP_SN_SIZE_12)
1585 		return TEST_SKIPPED;
1586 
1587 	/* Create configuration for actual testing */
1588 	uplink_to_downlink_convert(ul_conf, &dl_conf);
1589 	dl_conf.entity.pdcp_xfrm.hfn = pdcp_hfn_from_count_get(rx_deliv, sn_size);
1590 	dl_conf.entity.sn = pdcp_sn_from_count_get(rx_deliv, sn_size);
1591 
1592 	pdcp_entity = test_entity_create(&dl_conf, &ret);
1593 	if (pdcp_entity == NULL)
1594 		return ret;
1595 
1596 	ASSERT_TRUE_OR_GOTO(pdcp_entity->max_pkt_cache >= window_size, exit,
1597 			"PDCP max packet cache is too small");
1598 	cdev_id = dl_conf.entity.dev_id;
1599 	out_mb = rte_zmalloc(NULL, pdcp_entity->max_pkt_cache * sizeof(uintptr_t), 0);
1600 	ASSERT_TRUE_OR_GOTO(out_mb != NULL, exit,
1601 			"Could not allocate buffer for holding out_mb buffers\n");
1602 
1603 	/* Send packets with SN > RX_DELIV to create a gap */
1604 	for (i = rx_deliv + 1; i < window_size; i++) {
1605 		m1 = generate_packet_for_dl_with_sn(*ul_conf, i);
1606 		ASSERT_TRUE_OR_GOTO(m1 != NULL, exit, "Could not allocate buffer for packet\n");
1607 		/* Buffered packets after insert [NULL, m1] */
1608 		nb_success = test_process_packets(pdcp_entity, cdev_id, &m1, 1, out_mb, &nb_err);
1609 		ASSERT_TRUE_OR_GOTO(nb_err == 0, exit, "Error occurred during packet buffering\n");
1610 		ASSERT_TRUE_OR_GOTO(nb_success == 0, exit, "Packet was not buffered as expected\n");
1611 	}
1612 
1613 	m1 = generate_packet_for_dl_with_sn(*ul_conf, rx_deliv);
1614 	ASSERT_TRUE_OR_GOTO(m1 != NULL, exit, "Could not allocate buffer for packet\n");
1615 	/* Insert missing packet */
1616 	nb_success = test_process_packets(pdcp_entity, cdev_id, &m1, 1, out_mb, &nb_err);
1617 	ASSERT_TRUE_OR_GOTO(nb_err == 0, exit, "Error occurred during packet buffering\n");
1618 	ASSERT_TRUE_OR_GOTO(nb_success == window_size, exit,
1619 			"Packet count mismatch (received: %i, expected: %i)\n",
1620 			nb_success, window_size);
1621 	m1 = NULL;
1622 
1623 	ret = TEST_SUCCESS;
1624 exit:
1625 	rte_pktmbuf_free(m1);
1626 	rte_pktmbuf_free_bulk(out_mb, nb_success);
1627 	nb_out = rte_pdcp_entity_release(pdcp_entity, out_mb);
1628 	rte_pktmbuf_free_bulk(out_mb, nb_out);
1629 	rte_free(out_mb);
1630 	return ret;
1631 }
1632 
1633 #ifdef RTE_LIB_EVENTDEV
1634 static void
event_timer_start_cb(void * timer,void * args)1635 event_timer_start_cb(void *timer, void *args)
1636 {
1637 	struct rte_event_timer *evtims = args;
1638 	int ret = 0;
1639 
1640 	ret = rte_event_timer_arm_burst(timer, &evtims, 1);
1641 	assert(ret == 1);
1642 }
1643 #endif /* RTE_LIB_EVENTDEV */
1644 
1645 static int
test_expiry_with_event_timer(const struct pdcp_test_conf * ul_conf)1646 test_expiry_with_event_timer(const struct pdcp_test_conf *ul_conf)
1647 {
1648 #ifdef RTE_LIB_EVENTDEV
1649 	const enum rte_security_pdcp_sn_size sn_size = ul_conf->entity.pdcp_xfrm.sn_size;
1650 	struct rte_mbuf *m1 = NULL, *out_mb[1] = {0};
1651 	uint16_t n = 0, nb_err = 0, nb_try = 5;
1652 	struct rte_pdcp_entity *pdcp_entity;
1653 	struct pdcp_test_conf dl_conf;
1654 	int ret = TEST_FAILED, nb_out;
1655 	struct rte_event event;
1656 
1657 	const int start_count = 0;
1658 	struct rte_event_timer evtim = {
1659 		.ev.op = RTE_EVENT_OP_NEW,
1660 		.ev.queue_id = TEST_EV_QUEUE_ID,
1661 		.ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
1662 		.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
1663 		.ev.event_type =  RTE_EVENT_TYPE_TIMER,
1664 		.state = RTE_EVENT_TIMER_NOT_ARMED,
1665 		.timeout_ticks = 1,
1666 	};
1667 
1668 	if (ul_conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK)
1669 		return TEST_SKIPPED;
1670 
1671 	/* Create configuration for actual testing */
1672 	uplink_to_downlink_convert(ul_conf, &dl_conf);
1673 	dl_conf.entity.pdcp_xfrm.hfn = pdcp_hfn_from_count_get(start_count, sn_size);
1674 	dl_conf.entity.sn = pdcp_sn_from_count_get(start_count, sn_size);
1675 	dl_conf.entity.t_reordering.args = &evtim;
1676 	dl_conf.entity.t_reordering.timer = testsuite_params.timdev;
1677 	dl_conf.entity.t_reordering.start = event_timer_start_cb;
1678 
1679 	pdcp_entity = test_entity_create(&dl_conf, &ret);
1680 	if (pdcp_entity == NULL)
1681 		return ret;
1682 
1683 	evtim.ev.event_ptr = pdcp_entity;
1684 
1685 	/* Send packet with SN > RX_DELIV to create a gap */
1686 	m1 = generate_packet_for_dl_with_sn(*ul_conf, start_count + 1);
1687 	ASSERT_TRUE_OR_GOTO(m1 != NULL, exit, "Could not allocate buffer for packet\n");
1688 
1689 	/* Buffered packets after insert [NULL, m1] */
1690 	n = test_process_packets(pdcp_entity, dl_conf.entity.dev_id, &m1, 1, out_mb, &nb_err);
1691 	ASSERT_TRUE_OR_GOTO(nb_err == 0, exit, "Error occurred during packet buffering\n");
1692 	ASSERT_TRUE_OR_GOTO(n == 0, exit, "Packet was not buffered as expected\n");
1693 
1694 	m1 = NULL; /* Packet was moved to PDCP lib */
1695 
1696 	n = rte_event_dequeue_burst(testsuite_params.evdev, TEST_EV_PORT_ID, &event, 1, 0);
1697 	while (n != 1) {
1698 		rte_delay_us(testsuite_params.min_resolution_ns / 1000);
1699 		n = rte_event_dequeue_burst(testsuite_params.evdev, TEST_EV_PORT_ID, &event, 1, 0);
1700 		ASSERT_TRUE_OR_GOTO(nb_try > 0, exit,
1701 				"Dequeued unexpected timer expiry event: %i\n", n);
1702 		nb_try--;
1703 	}
1704 
1705 	ASSERT_TRUE_OR_GOTO(event.event_type == RTE_EVENT_TYPE_TIMER, exit, "Unexpected event type\n");
1706 
1707 	/* Handle expiry event */
1708 	n = rte_pdcp_t_reordering_expiry_handle(event.event_ptr, out_mb);
1709 	ASSERT_TRUE_OR_GOTO(n == 1, exit, "Unexpected number of expired packets :%i\n", n);
1710 
1711 	ret = TEST_SUCCESS;
1712 exit:
1713 	rte_pktmbuf_free(m1);
1714 	rte_pktmbuf_free_bulk(out_mb, n);
1715 	nb_out = rte_pdcp_entity_release(pdcp_entity, out_mb);
1716 	rte_pktmbuf_free_bulk(out_mb, nb_out);
1717 	return ret;
1718 #else
1719 	RTE_SET_USED(ul_conf);
1720 	return TEST_SKIPPED;
1721 #endif /* RTE_LIB_EVENTDEV */
1722 }
1723 
1724 static void
test_rte_timer_expiry_handle(struct rte_timer * timer_handle,void * arg)1725 test_rte_timer_expiry_handle(struct rte_timer *timer_handle, void *arg)
1726 {
1727 	struct test_rte_timer_args *timer_data = arg;
1728 	struct rte_mbuf *out_mb[1] = {0};
1729 	uint16_t n;
1730 
1731 	RTE_SET_USED(timer_handle);
1732 
1733 	n = rte_pdcp_t_reordering_expiry_handle(timer_data->pdcp_entity, out_mb);
1734 	rte_pktmbuf_free_bulk(out_mb, n);
1735 
1736 	timer_data->status =  n == 1 ? n : -1;
1737 }
1738 
1739 static void
test_rte_timer_start_cb(void * timer,void * args)1740 test_rte_timer_start_cb(void *timer, void *args)
1741 {
1742 	rte_timer_reset_sync(timer, 1, SINGLE, rte_lcore_id(), test_rte_timer_expiry_handle, args);
1743 }
1744 
1745 static int
test_expiry_with_rte_timer(const struct pdcp_test_conf * ul_conf)1746 test_expiry_with_rte_timer(const struct pdcp_test_conf *ul_conf)
1747 {
1748 	const enum rte_security_pdcp_sn_size sn_size = ul_conf->entity.pdcp_xfrm.sn_size;
1749 	struct rte_mbuf *m1 = NULL, *out_mb[1] = {0};
1750 	uint16_t n = 0, nb_err = 0, nb_try = 5;
1751 	struct test_rte_timer_args timer_args;
1752 	struct rte_pdcp_entity *pdcp_entity;
1753 	struct pdcp_test_conf dl_conf;
1754 	int ret = TEST_FAILED, nb_out;
1755 	struct rte_timer timer = {0};
1756 
1757 	const int start_count = 0;
1758 
1759 	if (ul_conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK)
1760 		return TEST_SKIPPED;
1761 
1762 	/* Set up a timer */
1763 	rte_timer_init(&timer);
1764 
1765 	/* Create configuration for actual testing */
1766 	uplink_to_downlink_convert(ul_conf, &dl_conf);
1767 	dl_conf.entity.pdcp_xfrm.hfn = pdcp_hfn_from_count_get(start_count, sn_size);
1768 	dl_conf.entity.sn = pdcp_sn_from_count_get(start_count, sn_size);
1769 	dl_conf.entity.t_reordering.args = &timer_args;
1770 	dl_conf.entity.t_reordering.timer = &timer;
1771 	dl_conf.entity.t_reordering.start = test_rte_timer_start_cb;
1772 
1773 	pdcp_entity = test_entity_create(&dl_conf, &ret);
1774 	if (pdcp_entity == NULL)
1775 		return ret;
1776 
1777 	timer_args.status = 0;
1778 	timer_args.pdcp_entity = pdcp_entity;
1779 
1780 	/* Send packet with SN > RX_DELIV to create a gap */
1781 	m1 = generate_packet_for_dl_with_sn(*ul_conf, start_count + 1);
1782 	ASSERT_TRUE_OR_GOTO(m1 != NULL, exit, "Could not allocate buffer for packet\n");
1783 
1784 	/* Buffered packets after insert [NULL, m1] */
1785 	n = test_process_packets(pdcp_entity, dl_conf.entity.dev_id, &m1, 1, out_mb, &nb_err);
1786 	ASSERT_TRUE_OR_GOTO(nb_err == 0, exit, "Error occurred during packet buffering\n");
1787 	ASSERT_TRUE_OR_GOTO(n == 0, exit, "Packet was not buffered as expected\n");
1788 
1789 	m1 = NULL; /* Packet was moved to PDCP lib */
1790 
1791 	/* Verify that expire was handled correctly */
1792 	rte_timer_manage();
1793 	while (timer_args.status != 1) {
1794 		rte_delay_us(1);
1795 		rte_timer_manage();
1796 		ASSERT_TRUE_OR_GOTO(nb_try > 0, exit, "Bad expire handle status %i\n",
1797 			timer_args.status);
1798 		nb_try--;
1799 	}
1800 
1801 	ret = TEST_SUCCESS;
1802 exit:
1803 	rte_pktmbuf_free(m1);
1804 	rte_pktmbuf_free_bulk(out_mb, n);
1805 	nb_out = rte_pdcp_entity_release(pdcp_entity, out_mb);
1806 	rte_pktmbuf_free_bulk(out_mb, nb_out);
1807 	return ret;
1808 }
1809 
1810 static struct rte_pdcp_up_ctrl_pdu_hdr *
pdcp_status_report_init(uint32_t fmc)1811 pdcp_status_report_init(uint32_t fmc)
1812 {
1813 	struct rte_pdcp_up_ctrl_pdu_hdr *hdr = testsuite_params.status_report;
1814 
1815 	hdr->d_c = RTE_PDCP_PDU_TYPE_CTRL;
1816 	hdr->pdu_type = RTE_PDCP_CTRL_PDU_TYPE_STATUS_REPORT;
1817 	hdr->fmc = rte_cpu_to_be_32(fmc);
1818 	hdr->r = 0;
1819 	memset(hdr->bitmap, 0, testsuite_params.status_report_bitmask_capacity);
1820 
1821 	return hdr;
1822 }
1823 
1824 static uint32_t
pdcp_status_report_len(void)1825 pdcp_status_report_len(void)
1826 {
1827 	struct rte_pdcp_up_ctrl_pdu_hdr *hdr = testsuite_params.status_report;
1828 	uint32_t i;
1829 
1830 	for (i = testsuite_params.status_report_bitmask_capacity; i != 0; i--) {
1831 		if (hdr->bitmap[i - 1])
1832 			return i;
1833 	}
1834 
1835 	return 0;
1836 }
1837 
1838 static int
pdcp_status_report_verify(struct rte_mbuf * status_report,const struct rte_pdcp_up_ctrl_pdu_hdr * expected_hdr,uint32_t expected_len)1839 pdcp_status_report_verify(struct rte_mbuf *status_report,
1840 			 const struct rte_pdcp_up_ctrl_pdu_hdr *expected_hdr, uint32_t expected_len)
1841 {
1842 	uint32_t received_len = rte_pktmbuf_pkt_len(status_report);
1843 	uint8_t *received_buf = testsuite_params.ctrl_pdu_buf;
1844 	int ret;
1845 
1846 	ret = pktmbuf_read_into(status_report, received_buf, RTE_PDCP_CTRL_PDU_SIZE_MAX);
1847 	TEST_ASSERT_SUCCESS(ret, "Failed to copy status report pkt into continuous buffer");
1848 
1849 	debug_hexdump(stdout, "Received:", received_buf, received_len);
1850 	debug_hexdump(stdout, "Expected:", expected_hdr, expected_len);
1851 
1852 	TEST_ASSERT_EQUAL(expected_len, received_len,
1853 			  "Mismatch in packet lengths [expected: %d, received: %d]",
1854 			  expected_len, received_len);
1855 
1856 	TEST_ASSERT_BUFFERS_ARE_EQUAL(received_buf, expected_hdr, expected_len,
1857 				     "Generated packet not as expected");
1858 
1859 	return 0;
1860 }
1861 
1862 static int
test_status_report_gen(const struct pdcp_test_conf * ul_conf,const struct rte_pdcp_up_ctrl_pdu_hdr * hdr,uint32_t bitmap_len)1863 test_status_report_gen(const struct pdcp_test_conf *ul_conf,
1864 		       const struct rte_pdcp_up_ctrl_pdu_hdr *hdr,
1865 		       uint32_t bitmap_len)
1866 {
1867 	const enum rte_security_pdcp_sn_size sn_size = ul_conf->entity.pdcp_xfrm.sn_size;
1868 	struct rte_mbuf *status_report = NULL, **out_mb, *m;
1869 	uint16_t nb_success = 0, nb_err = 0;
1870 	struct rte_pdcp_entity *pdcp_entity;
1871 	struct pdcp_test_conf dl_conf;
1872 	int ret = TEST_FAILED, nb_out;
1873 	uint32_t nb_pkts = 0, i;
1874 	uint8_t cdev_id;
1875 
1876 	const uint32_t start_count = rte_be_to_cpu_32(hdr->fmc);
1877 
1878 	if (ul_conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK)
1879 		return TEST_SKIPPED;
1880 
1881 	/* Create configuration for actual testing */
1882 	uplink_to_downlink_convert(ul_conf, &dl_conf);
1883 	dl_conf.entity.pdcp_xfrm.hfn = pdcp_hfn_from_count_get(start_count, sn_size);
1884 	dl_conf.entity.sn = pdcp_sn_from_count_get(start_count, sn_size);
1885 	dl_conf.entity.status_report_required = true;
1886 
1887 	pdcp_entity = test_entity_create(&dl_conf, &ret);
1888 	if (pdcp_entity == NULL)
1889 		return ret;
1890 
1891 	cdev_id = dl_conf.entity.dev_id;
1892 	out_mb = calloc(pdcp_entity->max_pkt_cache, sizeof(uintptr_t));
1893 
1894 	for (i = 0; i < bitmap_len * 8; i++) {
1895 		if (!bitmask_is_bit_set(hdr->bitmap, i))
1896 			continue;
1897 
1898 		m = generate_packet_for_dl_with_sn(*ul_conf, start_count + i + 1);
1899 		ASSERT_TRUE_OR_GOTO(m != NULL, exit, "Could not allocate buffer for packet\n");
1900 
1901 		nb_success = test_process_packets(pdcp_entity, cdev_id, &m, 1, out_mb, &nb_err);
1902 		ASSERT_TRUE_OR_GOTO(nb_err == 0, exit, "Error occurred during packet buffering\n");
1903 		ASSERT_TRUE_OR_GOTO(nb_success == 0, exit, "Packet was not buffered as expected\n");
1904 
1905 	}
1906 
1907 	m = NULL;
1908 
1909 	/* Check status report */
1910 	status_report = rte_pdcp_control_pdu_create(pdcp_entity,
1911 			RTE_PDCP_CTRL_PDU_TYPE_STATUS_REPORT);
1912 	ASSERT_TRUE_OR_GOTO(status_report != NULL, exit, "Could not generate status report\n");
1913 
1914 	const uint32_t expected_len = sizeof(struct rte_pdcp_up_ctrl_pdu_hdr) + bitmap_len;
1915 
1916 	ASSERT_TRUE_OR_GOTO(pdcp_status_report_verify(status_report, hdr, expected_len) == 0, exit,
1917 			   "Report verification failure\n");
1918 
1919 	ret = TEST_SUCCESS;
1920 exit:
1921 	rte_free(m);
1922 	rte_pktmbuf_free(status_report);
1923 	rte_pktmbuf_free_bulk(out_mb, nb_pkts);
1924 	nb_out = rte_pdcp_entity_release(pdcp_entity, out_mb);
1925 	rte_pktmbuf_free_bulk(out_mb, nb_out);
1926 	free(out_mb);
1927 	return ret;
1928 }
1929 
1930 static void
ctrl_pdu_hdr_packet_set(struct rte_pdcp_up_ctrl_pdu_hdr * hdr,uint32_t pkt_count)1931 ctrl_pdu_hdr_packet_set(struct rte_pdcp_up_ctrl_pdu_hdr *hdr, uint32_t pkt_count)
1932 {
1933 	bitmask_set_bit(hdr->bitmap, pkt_count - rte_be_to_cpu_32(hdr->fmc) - 1);
1934 }
1935 
1936 static int
test_status_report_fmc_only(const struct pdcp_test_conf * ul_conf)1937 test_status_report_fmc_only(const struct pdcp_test_conf *ul_conf)
1938 {
1939 	struct rte_pdcp_up_ctrl_pdu_hdr *hdr = pdcp_status_report_init(42);
1940 
1941 	return test_status_report_gen(ul_conf, hdr, pdcp_status_report_len());
1942 }
1943 
1944 static int
test_status_report_one_pkt_first_slab(const struct pdcp_test_conf * ul_conf)1945 test_status_report_one_pkt_first_slab(const struct pdcp_test_conf *ul_conf)
1946 {
1947 	struct rte_pdcp_up_ctrl_pdu_hdr *hdr = pdcp_status_report_init(0);
1948 
1949 	ctrl_pdu_hdr_packet_set(hdr, RTE_BITMAP_SLAB_BIT_SIZE / 2 + 1);
1950 
1951 	return test_status_report_gen(ul_conf, hdr, pdcp_status_report_len());
1952 }
1953 
1954 static int
test_status_report_one_pkt_second_slab(const struct pdcp_test_conf * ul_conf)1955 test_status_report_one_pkt_second_slab(const struct pdcp_test_conf *ul_conf)
1956 {
1957 	struct rte_pdcp_up_ctrl_pdu_hdr *hdr = pdcp_status_report_init(1);
1958 
1959 	ctrl_pdu_hdr_packet_set(hdr, RTE_BITMAP_SLAB_BIT_SIZE + 1);
1960 
1961 	return test_status_report_gen(ul_conf, hdr, pdcp_status_report_len());
1962 }
1963 
1964 static int
test_status_report_full_slab(const struct pdcp_test_conf * ul_conf)1965 test_status_report_full_slab(const struct pdcp_test_conf *ul_conf)
1966 {
1967 	struct rte_pdcp_up_ctrl_pdu_hdr *hdr = pdcp_status_report_init(1);
1968 	const uint32_t start_offset = RTE_BITMAP_SLAB_BIT_SIZE + 1;
1969 	int i;
1970 
1971 	for (i = 0; i < RTE_BITMAP_SLAB_BIT_SIZE; i++)
1972 		ctrl_pdu_hdr_packet_set(hdr, start_offset + i);
1973 
1974 	return test_status_report_gen(ul_conf, hdr, pdcp_status_report_len());
1975 }
1976 
1977 static int
test_status_report_two_sequential_slabs(const struct pdcp_test_conf * ul_conf)1978 test_status_report_two_sequential_slabs(const struct pdcp_test_conf *ul_conf)
1979 {
1980 	struct rte_pdcp_up_ctrl_pdu_hdr *hdr = pdcp_status_report_init(0);
1981 	const uint32_t start_offset = RTE_BITMAP_SLAB_BIT_SIZE / 2 + 1;
1982 
1983 	ctrl_pdu_hdr_packet_set(hdr, start_offset);
1984 	ctrl_pdu_hdr_packet_set(hdr, start_offset + RTE_BITMAP_SLAB_BIT_SIZE);
1985 
1986 	return test_status_report_gen(ul_conf, hdr, pdcp_status_report_len());
1987 }
1988 
1989 static int
test_status_report_two_non_sequential_slabs(const struct pdcp_test_conf * ul_conf)1990 test_status_report_two_non_sequential_slabs(const struct pdcp_test_conf *ul_conf)
1991 {
1992 	struct rte_pdcp_up_ctrl_pdu_hdr *hdr = pdcp_status_report_init(0);
1993 	const uint32_t start_offset = RTE_BITMAP_SLAB_BIT_SIZE / 2 + 1;
1994 
1995 	ctrl_pdu_hdr_packet_set(hdr, start_offset);
1996 	ctrl_pdu_hdr_packet_set(hdr, start_offset + RTE_BITMAP_SLAB_BIT_SIZE);
1997 	ctrl_pdu_hdr_packet_set(hdr, 3 * RTE_BITMAP_SLAB_BIT_SIZE);
1998 
1999 	return test_status_report_gen(ul_conf, hdr, pdcp_status_report_len());
2000 }
2001 
2002 static int
test_status_report_max_length_sn_12(const struct pdcp_test_conf * ul_conf)2003 test_status_report_max_length_sn_12(const struct pdcp_test_conf *ul_conf)
2004 {
2005 	struct rte_pdcp_up_ctrl_pdu_hdr *hdr;
2006 	const uint32_t fmc = 0;
2007 	uint32_t i;
2008 
2009 	if (ul_conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK ||
2010 		ul_conf->entity.pdcp_xfrm.sn_size != RTE_SECURITY_PDCP_SN_SIZE_12)
2011 		return TEST_SKIPPED;
2012 
2013 	hdr = pdcp_status_report_init(fmc);
2014 
2015 	const uint32_t max_count = RTE_MIN((RTE_PDCP_CTRL_PDU_SIZE_MAX - sizeof(hdr)) * 8,
2016 			(uint32_t)PDCP_WINDOW_SIZE(RTE_SECURITY_PDCP_SN_SIZE_12));
2017 
2018 	i = fmc + 2; /* set first count to have a gap, to enable packet buffering */
2019 
2020 	for (; i < max_count; i++)
2021 		ctrl_pdu_hdr_packet_set(hdr, i);
2022 
2023 	return test_status_report_gen(ul_conf, hdr, pdcp_status_report_len());
2024 }
2025 
2026 static int
test_status_report_overlap_different_slabs(const struct pdcp_test_conf * ul_conf)2027 test_status_report_overlap_different_slabs(const struct pdcp_test_conf *ul_conf)
2028 {
2029 	struct rte_pdcp_up_ctrl_pdu_hdr *hdr = pdcp_status_report_init(63);
2030 	const uint32_t sn_size = 12;
2031 
2032 	ctrl_pdu_hdr_packet_set(hdr, 64 + 1);
2033 	ctrl_pdu_hdr_packet_set(hdr, PDCP_WINDOW_SIZE(sn_size) + 1);
2034 
2035 	return test_status_report_gen(ul_conf, hdr, pdcp_status_report_len());
2036 }
2037 
2038 static int
test_status_report_overlap_same_slab(const struct pdcp_test_conf * ul_conf)2039 test_status_report_overlap_same_slab(const struct pdcp_test_conf *ul_conf)
2040 {
2041 	struct rte_pdcp_up_ctrl_pdu_hdr *hdr = pdcp_status_report_init(2);
2042 	const uint32_t sn_size = 12;
2043 
2044 	ctrl_pdu_hdr_packet_set(hdr, 4);
2045 	ctrl_pdu_hdr_packet_set(hdr, PDCP_WINDOW_SIZE(sn_size) + 1);
2046 
2047 	return test_status_report_gen(ul_conf, hdr, pdcp_status_report_len());
2048 }
2049 
2050 static int
test_combined(struct pdcp_test_conf * ul_conf)2051 test_combined(struct pdcp_test_conf *ul_conf)
2052 {
2053 	struct pdcp_test_conf dl_conf;
2054 	int ret;
2055 
2056 	if (ul_conf->entity.pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK)
2057 		return TEST_SKIPPED;
2058 
2059 	ul_conf->entity.reverse_iv_direction = true;
2060 	ul_conf->output_len = 0;
2061 
2062 	ret = test_attempt_single(ul_conf);
2063 	if (ret != TEST_SUCCESS)
2064 		return ret;
2065 
2066 	uplink_to_downlink_convert(ul_conf, &dl_conf);
2067 	ret = test_attempt_single(&dl_conf);
2068 
2069 	return ret;
2070 }
2071 
2072 #define MIN_DATA_LEN 0
2073 #define MAX_DATA_LEN 9000
2074 
2075 static int
test_combined_data_walkthrough(struct pdcp_test_conf * test_conf)2076 test_combined_data_walkthrough(struct pdcp_test_conf *test_conf)
2077 {
2078 	uint32_t data_len;
2079 	int ret;
2080 
2081 	ret = test_combined(test_conf);
2082 	if (ret != TEST_SUCCESS)
2083 		return ret;
2084 
2085 	if (!silent)
2086 		silent = true;
2087 
2088 	/* With the passing config, perform a data walkthrough test. */
2089 	for (data_len = MIN_DATA_LEN; data_len <= MAX_DATA_LEN; data_len++) {
2090 		test_conf_input_data_modify(test_conf, data_len);
2091 		ret = test_combined(test_conf);
2092 
2093 		if (ret == TEST_FAILED) {
2094 			printf("Data walkthrough failed for input len: %d\n", data_len);
2095 			return TEST_FAILED;
2096 		}
2097 	}
2098 
2099 	silent = false;
2100 
2101 	return TEST_SUCCESS;
2102 }
2103 
2104 #ifdef RTE_LIB_EVENTDEV
2105 static inline void
eventdev_conf_default_set(struct rte_event_dev_config * dev_conf,struct rte_event_dev_info * info)2106 eventdev_conf_default_set(struct rte_event_dev_config *dev_conf, struct rte_event_dev_info *info)
2107 {
2108 	memset(dev_conf, 0, sizeof(struct rte_event_dev_config));
2109 	dev_conf->dequeue_timeout_ns = info->min_dequeue_timeout_ns;
2110 	dev_conf->nb_event_ports = 1;
2111 	dev_conf->nb_event_queues = 1;
2112 	dev_conf->nb_event_queue_flows = info->max_event_queue_flows;
2113 	dev_conf->nb_event_port_dequeue_depth = info->max_event_port_dequeue_depth;
2114 	dev_conf->nb_event_port_enqueue_depth = info->max_event_port_enqueue_depth;
2115 	dev_conf->nb_event_port_enqueue_depth = info->max_event_port_enqueue_depth;
2116 	dev_conf->nb_events_limit = info->max_num_events;
2117 }
2118 
2119 static inline int
eventdev_setup(void)2120 eventdev_setup(void)
2121 {
2122 	struct rte_event_dev_config dev_conf;
2123 	struct rte_event_dev_info info;
2124 	int ret, evdev = 0;
2125 
2126 	if (!rte_event_dev_count())
2127 		return TEST_SKIPPED;
2128 
2129 	ret = rte_event_dev_info_get(evdev, &info);
2130 	TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
2131 	TEST_ASSERT(info.max_num_events < 0 || info.max_num_events >= 1,
2132 			"ERROR max_num_events=%d < max_events=%d", info.max_num_events, 1);
2133 
2134 	eventdev_conf_default_set(&dev_conf, &info);
2135 	ret = rte_event_dev_configure(evdev, &dev_conf);
2136 	TEST_ASSERT_SUCCESS(ret, "Failed to configure eventdev");
2137 
2138 	ret = rte_event_queue_setup(evdev, TEST_EV_QUEUE_ID, NULL);
2139 	TEST_ASSERT_SUCCESS(ret, "Failed to setup queue=%d", TEST_EV_QUEUE_ID);
2140 
2141 	/* Configure event port */
2142 	ret = rte_event_port_setup(evdev, TEST_EV_PORT_ID, NULL);
2143 	TEST_ASSERT_SUCCESS(ret, "Failed to setup port=%d", TEST_EV_PORT_ID);
2144 	ret = rte_event_port_link(evdev, TEST_EV_PORT_ID, NULL, NULL, 0);
2145 	TEST_ASSERT(ret >= 0, "Failed to link all queues port=%d", TEST_EV_PORT_ID);
2146 
2147 	ret = rte_event_dev_start(evdev);
2148 	TEST_ASSERT_SUCCESS(ret, "Failed to start device");
2149 
2150 	testsuite_params.evdev = evdev;
2151 
2152 	return TEST_SUCCESS;
2153 }
2154 
2155 static int
event_timer_setup(void)2156 event_timer_setup(void)
2157 {
2158 	struct rte_event_timer_adapter_info info;
2159 	struct rte_event_timer_adapter *timdev;
2160 	uint32_t caps = 0;
2161 
2162 	struct rte_event_timer_adapter_conf config = {
2163 		.event_dev_id = testsuite_params.evdev,
2164 		.timer_adapter_id = TIMER_ADAPTER_ID,
2165 		.timer_tick_ns = NSECPERSEC,
2166 		.max_tmo_ns = 10 * NSECPERSEC,
2167 		.nb_timers = 10,
2168 		.flags = 0,
2169 	};
2170 
2171 	TEST_ASSERT_SUCCESS(rte_event_timer_adapter_caps_get(testsuite_params.evdev, &caps),
2172 				"Failed to get adapter capabilities");
2173 
2174 	if (!(caps & RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT))
2175 		return TEST_SKIPPED;
2176 
2177 	timdev = rte_event_timer_adapter_create(&config);
2178 
2179 	TEST_ASSERT_NOT_NULL(timdev, "Failed to create event timer ring");
2180 
2181 	testsuite_params.timdev = timdev;
2182 
2183 	TEST_ASSERT_EQUAL(rte_event_timer_adapter_start(timdev), 0,
2184 			"Failed to start event timer adapter");
2185 
2186 	rte_event_timer_adapter_get_info(timdev, &info);
2187 	testsuite_params.min_resolution_ns = info.min_resolution_ns;
2188 
2189 	return TEST_SUCCESS;
2190 }
2191 #endif /* RTE_LIB_EVENTDEV */
2192 
2193 static int
ut_setup_pdcp_event_timer(void)2194 ut_setup_pdcp_event_timer(void)
2195 {
2196 #ifdef RTE_LIB_EVENTDEV
2197 	int ret;
2198 
2199 	ret = eventdev_setup();
2200 	if (ret)
2201 		return ret;
2202 
2203 	return event_timer_setup();
2204 #else
2205 	return TEST_SKIPPED;
2206 #endif /* RTE_LIB_EVENTDEV */
2207 }
2208 
2209 static void
ut_teardown_pdcp_event_timer(void)2210 ut_teardown_pdcp_event_timer(void)
2211 {
2212 #ifdef RTE_LIB_EVENTDEV
2213 	struct rte_event_timer_adapter *timdev = testsuite_params.timdev;
2214 	int evdev = testsuite_params.evdev;
2215 
2216 	rte_event_dev_stop(evdev);
2217 	rte_event_dev_close(evdev);
2218 
2219 	rte_event_timer_adapter_stop(timdev);
2220 	rte_event_timer_adapter_free(timdev);
2221 #endif /* RTE_LIB_EVENTDEV */
2222 }
2223 
2224 static int
run_test_for_one_known_vec(const void * arg)2225 run_test_for_one_known_vec(const void *arg)
2226 {
2227 	struct pdcp_test_conf test_conf;
2228 	int i = *(const uint32_t *)arg;
2229 
2230 	create_test_conf_from_index(i, &test_conf, PDCP_TEST_SUITE_TY_BASIC);
2231 	return test_attempt_single(&test_conf);
2232 }
2233 
2234 static struct unit_test_suite combined_mode_cases  = {
2235 	.suite_name = "PDCP combined mode",
2236 	.unit_test_cases = {
2237 		TEST_CASE_NAMED_WITH_DATA("combined mode", ut_setup_pdcp, ut_teardown_pdcp,
2238 			run_test_with_all_known_vec, test_combined),
2239 		TEST_CASE_NAMED_WITH_DATA("combined mode data walkthrough",
2240 			ut_setup_pdcp, ut_teardown_pdcp,
2241 			run_test_with_all_known_vec, test_combined_data_walkthrough),
2242 		TEST_CASES_END() /**< NULL terminate unit test array */
2243 	}
2244 };
2245 
2246 static struct unit_test_suite hfn_sn_test_cases  = {
2247 	.suite_name = "PDCP HFN/SN",
2248 	.unit_test_cases = {
2249 		TEST_CASE_NAMED_WITH_DATA("SN plus window", ut_setup_pdcp, ut_teardown_pdcp,
2250 			run_test_with_all_known_vec, test_sn_plus_window),
2251 		TEST_CASE_NAMED_WITH_DATA("SN minus window", ut_setup_pdcp, ut_teardown_pdcp,
2252 			run_test_with_all_known_vec, test_sn_minus_window),
2253 		TEST_CASE_NAMED_WITH_DATA("SN plus outside", ut_setup_pdcp, ut_teardown_pdcp,
2254 			run_test_with_all_known_vec, test_sn_plus_outside),
2255 		TEST_CASE_NAMED_WITH_DATA("SN minus outside", ut_setup_pdcp, ut_teardown_pdcp,
2256 			run_test_with_all_known_vec, test_sn_minus_outside),
2257 		TEST_CASES_END() /**< NULL terminate unit test array */
2258 	}
2259 };
2260 
2261 static struct unit_test_suite reorder_test_cases  = {
2262 	.suite_name = "PDCP reorder",
2263 	.unit_test_cases = {
2264 		TEST_CASE_NAMED_WITH_DATA("test_reorder_gap_fill",
2265 			ut_setup_pdcp, ut_teardown_pdcp,
2266 			run_test_with_all_known_vec, test_reorder_gap_fill),
2267 		TEST_CASE_NAMED_WITH_DATA("test_reorder_gap_in_reorder_buffer",
2268 			ut_setup_pdcp, ut_teardown_pdcp,
2269 			run_test_with_all_known_vec, test_reorder_gap_in_reorder_buffer),
2270 		TEST_CASE_NAMED_WITH_DATA("test_reorder_buffer_full_window_size_sn_12",
2271 			ut_setup_pdcp, ut_teardown_pdcp,
2272 			run_test_with_all_known_vec_until_first_pass,
2273 			test_reorder_buffer_full_window_size_sn_12),
2274 		TEST_CASE_NAMED_WITH_DATA("test_expire_with_event_timer",
2275 			ut_setup_pdcp_event_timer, ut_teardown_pdcp_event_timer,
2276 			run_test_with_all_known_vec_until_first_pass,
2277 			test_expiry_with_event_timer),
2278 		TEST_CASE_NAMED_WITH_DATA("test_expire_with_rte_timer",
2279 			ut_setup_pdcp, ut_teardown_pdcp,
2280 			run_test_with_all_known_vec_until_first_pass,
2281 			test_expiry_with_rte_timer),
2282 		TEST_CASES_END() /**< NULL terminate unit test array */
2283 	}
2284 };
2285 
2286 static struct unit_test_suite status_report_test_cases  = {
2287 	.suite_name = "PDCP status report",
2288 	.unit_test_cases = {
2289 		TEST_CASE_NAMED_WITH_DATA("test_status_report_fmc_only",
2290 			ut_setup_pdcp, ut_teardown_pdcp,
2291 			run_test_with_all_known_vec, test_status_report_fmc_only),
2292 		TEST_CASE_NAMED_WITH_DATA("test_status_report_one_pkt_first_slab",
2293 			ut_setup_pdcp, ut_teardown_pdcp,
2294 			run_test_with_all_known_vec, test_status_report_one_pkt_first_slab),
2295 		TEST_CASE_NAMED_WITH_DATA("test_status_report_one_pkt_second_slab",
2296 			ut_setup_pdcp, ut_teardown_pdcp,
2297 			run_test_with_all_known_vec, test_status_report_one_pkt_second_slab),
2298 		TEST_CASE_NAMED_WITH_DATA("test_status_report_full_slab",
2299 			ut_setup_pdcp, ut_teardown_pdcp,
2300 			run_test_with_all_known_vec, test_status_report_full_slab),
2301 		TEST_CASE_NAMED_WITH_DATA("test_status_report_two_sequential_slabs",
2302 			ut_setup_pdcp, ut_teardown_pdcp,
2303 			run_test_with_all_known_vec, test_status_report_two_sequential_slabs),
2304 		TEST_CASE_NAMED_WITH_DATA("test_status_report_two_non_sequential_slabs",
2305 			ut_setup_pdcp, ut_teardown_pdcp,
2306 			run_test_with_all_known_vec, test_status_report_two_non_sequential_slabs),
2307 		TEST_CASE_NAMED_WITH_DATA("test_status_report_max_length_sn_12",
2308 			ut_setup_pdcp, ut_teardown_pdcp,
2309 			run_test_with_all_known_vec_until_first_pass,
2310 			test_status_report_max_length_sn_12),
2311 		TEST_CASE_NAMED_WITH_DATA("test_status_report_overlap_different_slabs",
2312 			ut_setup_pdcp, ut_teardown_pdcp,
2313 			run_test_with_all_known_vec, test_status_report_overlap_different_slabs),
2314 		TEST_CASE_NAMED_WITH_DATA("test_status_report_overlap_same_slab",
2315 			ut_setup_pdcp, ut_teardown_pdcp,
2316 			run_test_with_all_known_vec, test_status_report_overlap_same_slab),
2317 		TEST_CASES_END() /**< NULL terminate unit test array */
2318 	}
2319 };
2320 
2321 static struct unit_test_suite sdap_test_cases  = {
2322 	.suite_name = "PDCP SDAP",
2323 	.unit_test_cases = {
2324 		TEST_CASE_NAMED_WITH_DATA("SDAP Known vector cases",
2325 			ut_setup_pdcp, ut_teardown_pdcp,
2326 			run_test_with_all_sdap_known_vec, test_attempt_single),
2327 		TEST_CASE_NAMED_WITH_DATA("SDAP combined mode",
2328 			ut_setup_pdcp, ut_teardown_pdcp,
2329 			run_test_with_all_sdap_known_vec, test_combined),
2330 		TEST_CASES_END() /**< NULL terminate unit test array */
2331 	}
2332 };
2333 struct unit_test_suite *test_suites[] = {
2334 	NULL, /* Place holder for known_vector_cases */
2335 	&sdap_test_cases,
2336 	&combined_mode_cases,
2337 	&hfn_sn_test_cases,
2338 	&reorder_test_cases,
2339 	&status_report_test_cases,
2340 	NULL /* End of suites list */
2341 };
2342 
2343 static struct unit_test_suite pdcp_testsuite  = {
2344 	.suite_name = "PDCP Unit Test Suite",
2345 	.unit_test_cases = {TEST_CASES_END()},
2346 	.setup = testsuite_setup,
2347 	.teardown = testsuite_teardown,
2348 	.unit_test_suites = test_suites,
2349 };
2350 
2351 static int
test_pdcp(void)2352 test_pdcp(void)
2353 {
2354 	struct unit_test_suite *known_vector_cases;
2355 	uint32_t nb_tests = nb_tests_get(PDCP_TEST_SUITE_TY_BASIC);
2356 	int ret, index[nb_tests];
2357 	uint32_t i, size;
2358 
2359 	size = sizeof(struct unit_test_suite);
2360 	size += (nb_tests + 1) * sizeof(struct unit_test_case);
2361 
2362 	known_vector_cases = rte_zmalloc(NULL, size, 0);
2363 	if (known_vector_cases == NULL)
2364 		return TEST_FAILED;
2365 
2366 	known_vector_cases->suite_name = "Known vector cases";
2367 
2368 	for (i = 0; i < nb_tests; i++) {
2369 		index[i] = i;
2370 		known_vector_cases->unit_test_cases[i].name = pdcp_test_params[i].name;
2371 		known_vector_cases->unit_test_cases[i].data = (void *)&index[i];
2372 		known_vector_cases->unit_test_cases[i].enabled = 1;
2373 		known_vector_cases->unit_test_cases[i].setup = ut_setup_pdcp;
2374 		known_vector_cases->unit_test_cases[i].teardown = ut_teardown_pdcp;
2375 		known_vector_cases->unit_test_cases[i].testcase = NULL;
2376 		known_vector_cases->unit_test_cases[i].testcase_with_data
2377 				= run_test_for_one_known_vec;
2378 	}
2379 
2380 	known_vector_cases->unit_test_cases[i].testcase = NULL;
2381 	known_vector_cases->unit_test_cases[i].testcase_with_data = NULL;
2382 
2383 	test_suites[0] = known_vector_cases;
2384 
2385 	ret = unit_test_suite_runner(&pdcp_testsuite);
2386 
2387 	rte_free(known_vector_cases);
2388 	return ret;
2389 }
2390 
2391 REGISTER_FAST_TEST(pdcp_autotest, false, true, test_pdcp);
2392