1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
13 #include <rte_string_fns.h>
14 #include <rte_mempool.h>
15 #include <rte_ethdev.h>
16 #include <rte_bus_pci.h>
17 #include <rte_cycles.h>
21 #define MAX_PACKET_SZ 2048
22 #define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM)
23 #define PKT_BURST_SZ 32
24 #define MEMPOOL_CACHE_SZ PKT_BURST_SZ
28 #define KNI_TIMEOUT_MS 5000 /* ms */
30 #define IFCONFIG "/sbin/ifconfig "
31 #define TEST_KNI_PORT "test_kni_port"
32 #define KNI_TEST_MAX_PORTS 4
33 /* The threshold number of mbufs to be transmitted or received. */
34 #define KNI_NUM_MBUF_THRESHOLD 100
35 static int kni_pkt_mtu = 0;
37 struct test_kni_stats {
38 volatile uint64_t ingress;
39 volatile uint64_t egress;
42 static const struct rte_eth_rxconf rx_conf = {
51 static const struct rte_eth_txconf tx_conf = {
61 static const struct rte_eth_conf port_conf = {
70 .mq_mode = ETH_DCB_NONE,
74 static struct rte_kni_ops kni_ops = {
76 .config_network_if = NULL,
77 .config_mac_address = NULL,
80 static unsigned lcore_master, lcore_ingress, lcore_egress;
81 static struct rte_kni *test_kni_ctx;
82 static struct test_kni_stats stats;
84 static volatile uint32_t test_kni_processing_flag;
86 static struct rte_mempool *
87 test_kni_create_mempool(void)
89 struct rte_mempool * mp;
91 mp = rte_mempool_lookup("kni_mempool");
93 mp = rte_pktmbuf_pool_create("kni_mempool",
95 MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ,
101 static struct rte_mempool *
102 test_kni_lookup_mempool(void)
104 return rte_mempool_lookup("kni_mempool");
106 /* Callback for request of changing MTU */
108 kni_change_mtu(uint16_t port_id, unsigned int new_mtu)
110 printf("Change MTU of port %d to %u\n", port_id, new_mtu);
111 kni_pkt_mtu = new_mtu;
112 printf("Change MTU of port %d to %i successfully.\n",
113 port_id, kni_pkt_mtu);
117 * This loop fully tests the basic functions of KNI. e.g. transmitting,
118 * receiving to, from kernel space, and kernel requests.
120 * This is the loop to transmit/receive mbufs to/from kernel interface with
121 * supported by KNI kernel module. The ingress lcore will allocate mbufs and
122 * transmit them to kernel space; while the egress lcore will receive the mbufs
123 * from kernel space and free them.
124 * On the master lcore, several commands will be run to check handling the
125 * kernel requests. And it will finally set the flag to exit the KNI
126 * transmitting/receiving to/from the kernel space.
128 * Note: To support this testing, the KNI kernel module needs to be insmodded
129 * in one of its loopback modes.
132 test_kni_loop(__rte_unused void *arg)
135 unsigned nb_rx, nb_tx, num, i;
136 const unsigned lcore_id = rte_lcore_id();
137 struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
139 if (lcore_id == lcore_master) {
140 rte_delay_ms(KNI_TIMEOUT_MS);
141 /* tests of handling kernel request */
142 if (system(IFCONFIG TEST_KNI_PORT" up") == -1)
144 if (system(IFCONFIG TEST_KNI_PORT" mtu 1400") == -1)
146 if (system(IFCONFIG TEST_KNI_PORT" down") == -1)
148 rte_delay_ms(KNI_TIMEOUT_MS);
149 test_kni_processing_flag = 1;
150 } else if (lcore_id == lcore_ingress) {
151 struct rte_mempool *mp = test_kni_lookup_mempool();
157 if (test_kni_processing_flag)
160 for (nb_rx = 0; nb_rx < PKT_BURST_SZ; nb_rx++) {
161 pkts_burst[nb_rx] = rte_pktmbuf_alloc(mp);
162 if (!pkts_burst[nb_rx])
166 num = rte_kni_tx_burst(test_kni_ctx, pkts_burst,
168 stats.ingress += num;
169 rte_kni_handle_request(test_kni_ctx);
171 for (i = num; i < nb_rx; i++) {
172 rte_pktmbuf_free(pkts_burst[i]);
177 } else if (lcore_id == lcore_egress) {
179 if (test_kni_processing_flag)
181 num = rte_kni_rx_burst(test_kni_ctx, pkts_burst,
184 for (nb_tx = 0; nb_tx < num; nb_tx++)
185 rte_pktmbuf_free(pkts_burst[nb_tx]);
194 test_kni_allocate_lcores(void)
196 unsigned i, count = 0;
198 lcore_master = rte_get_master_lcore();
199 printf("master lcore: %u\n", lcore_master);
200 for (i = 0; i < RTE_MAX_LCORE; i++) {
203 if (rte_lcore_is_enabled(i) && i != lcore_master) {
211 printf("count: %u\n", count);
213 return count == 2 ? 0 : -1;
217 test_kni_register_handler_mp(void)
219 #define TEST_KNI_HANDLE_REQ_COUNT 10 /* 5s */
220 #define TEST_KNI_HANDLE_REQ_INTERVAL 500 /* ms */
221 #define TEST_KNI_MTU 1450
222 #define TEST_KNI_MTU_STR " 1450"
227 printf("Failed to fork a process\n");
229 } else if (pid == 0) {
231 struct rte_kni *kni = rte_kni_get(TEST_KNI_PORT);
232 struct rte_kni_ops ops = {
233 .change_mtu = kni_change_mtu,
234 .config_network_if = NULL,
235 .config_mac_address = NULL,
239 printf("Failed to get KNI named %s\n", TEST_KNI_PORT);
245 /* Check with the invalid parameters */
246 if (rte_kni_register_handlers(kni, NULL) == 0) {
247 printf("Unexpectedly register successuflly "
248 "with NULL ops pointer\n");
251 if (rte_kni_register_handlers(NULL, &ops) == 0) {
252 printf("Unexpectedly register successfully "
253 "to NULL KNI device pointer\n");
257 if (rte_kni_register_handlers(kni, &ops)) {
258 printf("Fail to register ops\n");
262 /* Check registering again after it has been registered */
263 if (rte_kni_register_handlers(kni, &ops) == 0) {
264 printf("Unexpectedly register successfully after "
265 "it has already been registered\n");
270 * Handle the request of setting MTU,
271 * with registered handlers.
273 for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) {
274 rte_kni_handle_request(kni);
275 if (kni_pkt_mtu == TEST_KNI_MTU)
277 rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL);
279 if (i >= TEST_KNI_HANDLE_REQ_COUNT) {
280 printf("MTU has not been set\n");
285 if (rte_kni_unregister_handlers(kni) < 0) {
286 printf("Fail to unregister ops\n");
290 /* Check with invalid parameter */
291 if (rte_kni_unregister_handlers(NULL) == 0) {
296 * Handle the request of setting MTU,
297 * without registered handlers.
299 for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) {
300 rte_kni_handle_request(kni);
301 if (kni_pkt_mtu != 0)
303 rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL);
305 if (kni_pkt_mtu != 0) {
306 printf("MTU shouldn't be set\n");
315 if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR)
320 if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR)
324 p_ret = wait(&status);
325 if (!WIFEXITED(status)) {
326 printf("Child process (%d) exit abnormally\n", p_ret);
329 if (WEXITSTATUS(status) != 0) {
330 printf("Child process exit with failure\n");
339 test_kni_processing(uint16_t port_id, struct rte_mempool *mp)
344 struct rte_kni_conf conf;
345 struct rte_eth_dev_info info;
346 struct rte_kni_ops ops;
351 memset(&conf, 0, sizeof(conf));
352 memset(&info, 0, sizeof(info));
353 memset(&ops, 0, sizeof(ops));
355 rte_eth_dev_info_get(port_id, &info);
356 conf.addr = info.pci_dev->addr;
357 conf.id = info.pci_dev->id;
358 snprintf(conf.name, sizeof(conf.name), TEST_KNI_PORT);
360 /* core id 1 configured for kernel thread */
363 conf.mbuf_size = MAX_PACKET_SZ;
364 conf.group_id = port_id;
367 ops.port_id = port_id;
369 /* basic test of kni processing */
370 kni = rte_kni_alloc(mp, &conf, &ops);
372 printf("fail to create kni\n");
377 test_kni_processing_flag = 0;
382 * Check multiple processes support on
383 * registerring/unregisterring handlers.
385 if (test_kni_register_handler_mp() < 0) {
386 printf("fail to check multiple process support\n");
391 rte_eal_mp_remote_launch(test_kni_loop, NULL, CALL_MASTER);
392 RTE_LCORE_FOREACH_SLAVE(i) {
393 if (rte_eal_wait_lcore(i) < 0) {
399 * Check if the number of mbufs received from kernel space is equal
400 * to that of transmitted to kernel space
402 if (stats.ingress < KNI_NUM_MBUF_THRESHOLD ||
403 stats.egress < KNI_NUM_MBUF_THRESHOLD) {
404 printf("The ingress/egress number should not be "
405 "less than %u\n", (unsigned)KNI_NUM_MBUF_THRESHOLD);
410 if (rte_kni_release(kni) < 0) {
411 printf("fail to release kni\n");
416 /* test of releasing a released kni device */
417 if (rte_kni_release(kni) == 0) {
418 printf("should not release a released kni device\n");
422 /* test of reusing memzone */
423 kni = rte_kni_alloc(mp, &conf, &ops);
425 printf("fail to create kni\n");
429 /* Release the kni for following testing */
430 if (rte_kni_release(kni) < 0) {
431 printf("fail to release kni\n");
437 if (rte_kni_release(kni) < 0) {
438 printf("fail to release kni\n");
449 uint16_t nb_ports, port_id;
451 struct rte_mempool *mp;
452 struct rte_kni_conf conf;
453 struct rte_eth_dev_info info;
454 struct rte_kni_ops ops;
456 /* Initialize KNI subsytem */
457 rte_kni_init(KNI_TEST_MAX_PORTS);
459 if (test_kni_allocate_lcores() < 0) {
460 printf("No enough lcores for kni processing\n");
464 mp = test_kni_create_mempool();
466 printf("fail to create mempool for kni\n");
470 nb_ports = rte_eth_dev_count();
472 printf("no supported nic port found\n");
476 /* configuring port 0 for the test is enough */
478 ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf);
480 printf("fail to configure port %d\n", port_id);
484 ret = rte_eth_rx_queue_setup(port_id, 0, NB_RXD, SOCKET, &rx_conf, mp);
486 printf("fail to setup rx queue for port %d\n", port_id);
490 ret = rte_eth_tx_queue_setup(port_id, 0, NB_TXD, SOCKET, &tx_conf);
492 printf("fail to setup tx queue for port %d\n", port_id);
496 ret = rte_eth_dev_start(port_id);
498 printf("fail to start port %d\n", port_id);
501 rte_eth_promiscuous_enable(port_id);
503 /* basic test of kni processing */
504 ret = test_kni_processing(port_id, mp);
508 /* test of allocating KNI with NULL mempool pointer */
509 memset(&info, 0, sizeof(info));
510 memset(&conf, 0, sizeof(conf));
511 memset(&ops, 0, sizeof(ops));
512 rte_eth_dev_info_get(port_id, &info);
513 conf.addr = info.pci_dev->addr;
514 conf.id = info.pci_dev->id;
515 conf.group_id = port_id;
516 conf.mbuf_size = MAX_PACKET_SZ;
519 ops.port_id = port_id;
520 kni = rte_kni_alloc(NULL, &conf, &ops);
523 printf("unexpectedly creates kni successfully with NULL "
524 "mempool pointer\n");
528 /* test of allocating KNI without configurations */
529 kni = rte_kni_alloc(mp, NULL, NULL);
532 printf("Unexpectedly allocate KNI device successfully "
533 "without configurations\n");
537 /* test of allocating KNI without a name */
538 memset(&conf, 0, sizeof(conf));
539 memset(&info, 0, sizeof(info));
540 memset(&ops, 0, sizeof(ops));
541 rte_eth_dev_info_get(port_id, &info);
542 conf.addr = info.pci_dev->addr;
543 conf.id = info.pci_dev->id;
544 conf.group_id = port_id;
545 conf.mbuf_size = MAX_PACKET_SZ;
548 ops.port_id = port_id;
549 kni = rte_kni_alloc(mp, &conf, &ops);
552 printf("Unexpectedly allocate a KNI device successfully "
557 /* test of releasing NULL kni context */
558 ret = rte_kni_release(NULL);
561 printf("unexpectedly release kni successfully\n");
565 /* test of handling request on NULL device pointer */
566 ret = rte_kni_handle_request(NULL);
569 printf("Unexpectedly handle request on NULL device pointer\n");
573 /* test of getting KNI device with pointer to NULL */
574 kni = rte_kni_get(NULL);
577 printf("Unexpectedly get a KNI device with "
578 "NULL name pointer\n");
582 /* test of getting KNI device with an zero length name string */
583 memset(&conf, 0, sizeof(conf));
584 kni = rte_kni_get(conf.name);
587 printf("Unexpectedly get a KNI device with "
588 "zero length name string\n");
592 /* test of getting KNI device with an invalid string name */
593 memset(&conf, 0, sizeof(conf));
594 snprintf(conf.name, sizeof(conf.name), "testing");
595 kni = rte_kni_get(conf.name);
598 printf("Unexpectedly get a KNI device with "
599 "a never used name string\n");
605 rte_eth_dev_stop(port_id);
610 REGISTER_TEST_COMMAND(kni_autotest, test_kni);