1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
14 #if !defined(RTE_EXEC_ENV_LINUX) || !defined(RTE_LIB_KNI)
19 printf("KNI not supported, skipping test\n");
25 #include <rte_string_fns.h>
26 #include <rte_mempool.h>
27 #include <rte_ethdev.h>
28 #include <rte_bus_pci.h>
29 #include <rte_cycles.h>
33 #define MAX_PACKET_SZ 2048
34 #define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM)
35 #define PKT_BURST_SZ 32
36 #define MEMPOOL_CACHE_SZ PKT_BURST_SZ
40 #define KNI_TIMEOUT_MS 5000 /* ms */
42 #define IFCONFIG "/sbin/ifconfig "
43 #define TEST_KNI_PORT "test_kni_port"
44 #define KNI_MODULE_PATH "/sys/module/rte_kni"
45 #define KNI_MODULE_PARAM_LO KNI_MODULE_PATH"/parameters/lo_mode"
46 #define KNI_TEST_MAX_PORTS 4
47 /* The threshold number of mbufs to be transmitted or received. */
48 #define KNI_NUM_MBUF_THRESHOLD 100
49 static int kni_pkt_mtu = 0;
51 struct test_kni_stats {
52 volatile uint64_t ingress;
53 volatile uint64_t egress;
56 static const struct rte_eth_rxconf rx_conf = {
65 static const struct rte_eth_txconf tx_conf = {
75 static const struct rte_eth_conf port_conf = {
77 .mq_mode = ETH_DCB_NONE,
81 static struct rte_kni_ops kni_ops = {
83 .config_network_if = NULL,
84 .config_mac_address = NULL,
85 .config_promiscusity = NULL,
88 static unsigned int lcore_main, lcore_ingress, lcore_egress;
89 static struct rte_kni *test_kni_ctx;
90 static struct test_kni_stats stats;
92 static volatile uint32_t test_kni_processing_flag;
94 static struct rte_mempool *
95 test_kni_create_mempool(void)
97 struct rte_mempool * mp;
99 mp = rte_mempool_lookup("kni_mempool");
101 mp = rte_pktmbuf_pool_create("kni_mempool",
103 MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ,
109 static struct rte_mempool *
110 test_kni_lookup_mempool(void)
112 return rte_mempool_lookup("kni_mempool");
114 /* Callback for request of changing MTU */
116 kni_change_mtu(uint16_t port_id, unsigned int new_mtu)
118 printf("Change MTU of port %d to %u\n", port_id, new_mtu);
119 kni_pkt_mtu = new_mtu;
120 printf("Change MTU of port %d to %i successfully.\n",
121 port_id, kni_pkt_mtu);
126 test_kni_link_change(void)
133 printf("Error: Failed to fork a process\n");
138 printf("Starting KNI Link status change tests.\n");
139 if (system(IFCONFIG TEST_KNI_PORT" up") == -1) {
144 ret = rte_kni_update_link(test_kni_ctx, 1);
146 printf("Failed to change link state to Up ret=%d.\n",
151 printf("KNI: Set LINKUP, previous state=%d\n", ret);
153 ret = rte_kni_update_link(test_kni_ctx, 0);
156 "Failed! Previous link state should be 1, returned %d.\n",
161 printf("KNI: Set LINKDOWN, previous state=%d\n", ret);
163 ret = rte_kni_update_link(test_kni_ctx, 1);
166 "Failed! Previous link state should be 0, returned %d.\n",
170 printf("KNI: Set LINKUP, previous state=%d\n", ret);
176 if (system(IFCONFIG TEST_KNI_PORT" down") == -1)
179 printf("KNI: Link status change tests: %s.\n",
180 (ret == 0) ? "Passed" : "Failed");
186 p_ret = waitpid(pid, &status, WNOHANG);
188 if (WIFEXITED(status))
189 return WEXITSTATUS(status);
193 rte_kni_handle_request(test_kni_ctx);
198 * This loop fully tests the basic functions of KNI. e.g. transmitting,
199 * receiving to, from kernel space, and kernel requests.
201 * This is the loop to transmit/receive mbufs to/from kernel interface with
202 * supported by KNI kernel module. The ingress lcore will allocate mbufs and
203 * transmit them to kernel space; while the egress lcore will receive the mbufs
204 * from kernel space and free them.
205 * On the main lcore, several commands will be run to check handling the
206 * kernel requests. And it will finally set the flag to exit the KNI
207 * transmitting/receiving to/from the kernel space.
209 * Note: To support this testing, the KNI kernel module needs to be insmodded
210 * in one of its loopback modes.
213 test_kni_loop(__rte_unused void *arg)
216 unsigned nb_rx, nb_tx, num, i;
217 const unsigned lcore_id = rte_lcore_id();
218 struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
220 if (lcore_id == lcore_main) {
221 rte_delay_ms(KNI_TIMEOUT_MS);
222 /* tests of handling kernel request */
223 if (system(IFCONFIG TEST_KNI_PORT" up") == -1)
225 if (system(IFCONFIG TEST_KNI_PORT" mtu 1400") == -1)
227 if (system(IFCONFIG TEST_KNI_PORT" down") == -1)
229 rte_delay_ms(KNI_TIMEOUT_MS);
230 test_kni_processing_flag = 1;
231 } else if (lcore_id == lcore_ingress) {
232 struct rte_mempool *mp = test_kni_lookup_mempool();
238 if (test_kni_processing_flag)
241 for (nb_rx = 0; nb_rx < PKT_BURST_SZ; nb_rx++) {
242 pkts_burst[nb_rx] = rte_pktmbuf_alloc(mp);
243 if (!pkts_burst[nb_rx])
247 num = rte_kni_tx_burst(test_kni_ctx, pkts_burst,
249 stats.ingress += num;
250 rte_kni_handle_request(test_kni_ctx);
252 for (i = num; i < nb_rx; i++) {
253 rte_pktmbuf_free(pkts_burst[i]);
258 } else if (lcore_id == lcore_egress) {
260 if (test_kni_processing_flag)
262 num = rte_kni_rx_burst(test_kni_ctx, pkts_burst,
265 for (nb_tx = 0; nb_tx < num; nb_tx++)
266 rte_pktmbuf_free(pkts_burst[nb_tx]);
275 test_kni_allocate_lcores(void)
277 unsigned i, count = 0;
279 lcore_main = rte_get_main_lcore();
280 printf("main lcore: %u\n", lcore_main);
281 for (i = 0; i < RTE_MAX_LCORE; i++) {
284 if (rte_lcore_is_enabled(i) && i != lcore_main) {
292 printf("count: %u\n", count);
294 return count == 2 ? 0 : -1;
298 test_kni_register_handler_mp(void)
300 #define TEST_KNI_HANDLE_REQ_COUNT 10 /* 5s */
301 #define TEST_KNI_HANDLE_REQ_INTERVAL 500 /* ms */
302 #define TEST_KNI_MTU 1450
303 #define TEST_KNI_MTU_STR " 1450"
308 printf("Failed to fork a process\n");
310 } else if (pid == 0) {
312 struct rte_kni *kni = rte_kni_get(TEST_KNI_PORT);
313 struct rte_kni_ops ops = {
314 .change_mtu = kni_change_mtu,
315 .config_network_if = NULL,
316 .config_mac_address = NULL,
317 .config_promiscusity = NULL,
321 printf("Failed to get KNI named %s\n", TEST_KNI_PORT);
327 /* Check with the invalid parameters */
328 if (rte_kni_register_handlers(kni, NULL) == 0) {
329 printf("Unexpectedly register successuflly "
330 "with NULL ops pointer\n");
333 if (rte_kni_register_handlers(NULL, &ops) == 0) {
334 printf("Unexpectedly register successfully "
335 "to NULL KNI device pointer\n");
339 if (rte_kni_register_handlers(kni, &ops)) {
340 printf("Fail to register ops\n");
344 /* Check registering again after it has been registered */
345 if (rte_kni_register_handlers(kni, &ops) == 0) {
346 printf("Unexpectedly register successfully after "
347 "it has already been registered\n");
352 * Handle the request of setting MTU,
353 * with registered handlers.
355 for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) {
356 rte_kni_handle_request(kni);
357 if (kni_pkt_mtu == TEST_KNI_MTU)
359 rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL);
361 if (i >= TEST_KNI_HANDLE_REQ_COUNT) {
362 printf("MTU has not been set\n");
367 if (rte_kni_unregister_handlers(kni) < 0) {
368 printf("Fail to unregister ops\n");
372 /* Check with invalid parameter */
373 if (rte_kni_unregister_handlers(NULL) == 0) {
378 * Handle the request of setting MTU,
379 * without registered handlers.
381 for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) {
382 rte_kni_handle_request(kni);
383 if (kni_pkt_mtu != 0)
385 rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL);
387 if (kni_pkt_mtu != 0) {
388 printf("MTU shouldn't be set\n");
397 if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR)
402 if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR)
406 p_ret = wait(&status);
407 if (!WIFEXITED(status)) {
408 printf("Child process (%d) exit abnormally\n", p_ret);
411 if (WEXITSTATUS(status) != 0) {
412 printf("Child process exit with failure\n");
421 test_kni_processing(uint16_t port_id, struct rte_mempool *mp)
426 struct rte_kni_conf conf;
427 struct rte_eth_dev_info info;
428 struct rte_kni_ops ops;
429 const struct rte_pci_device *pci_dev;
430 const struct rte_bus *bus = NULL;
435 memset(&conf, 0, sizeof(conf));
436 memset(&info, 0, sizeof(info));
437 memset(&ops, 0, sizeof(ops));
439 ret = rte_eth_dev_info_get(port_id, &info);
441 printf("Error during getting device (port %u) info: %s\n",
442 port_id, strerror(-ret));
447 bus = rte_bus_find_by_device(info.device);
448 if (bus && !strcmp(bus->name, "pci")) {
449 pci_dev = RTE_DEV_TO_PCI(info.device);
450 conf.addr = pci_dev->addr;
451 conf.id = pci_dev->id;
453 snprintf(conf.name, sizeof(conf.name), TEST_KNI_PORT);
455 /* core id 1 configured for kernel thread */
458 conf.mbuf_size = MAX_PACKET_SZ;
459 conf.group_id = port_id;
462 ops.port_id = port_id;
464 /* basic test of kni processing */
465 kni = rte_kni_alloc(mp, &conf, &ops);
467 printf("fail to create kni\n");
472 test_kni_processing_flag = 0;
477 * Check multiple processes support on
478 * registerring/unregisterring handlers.
480 if (test_kni_register_handler_mp() < 0) {
481 printf("fail to check multiple process support\n");
486 ret = test_kni_link_change();
490 rte_eal_mp_remote_launch(test_kni_loop, NULL, CALL_MAIN);
491 RTE_LCORE_FOREACH_WORKER(i) {
492 if (rte_eal_wait_lcore(i) < 0) {
498 * Check if the number of mbufs received from kernel space is equal
499 * to that of transmitted to kernel space
501 if (stats.ingress < KNI_NUM_MBUF_THRESHOLD ||
502 stats.egress < KNI_NUM_MBUF_THRESHOLD) {
503 printf("The ingress/egress number should not be "
504 "less than %u\n", (unsigned)KNI_NUM_MBUF_THRESHOLD);
509 if (rte_kni_release(kni) < 0) {
510 printf("fail to release kni\n");
515 /* test of reusing memzone */
516 kni = rte_kni_alloc(mp, &conf, &ops);
518 printf("fail to create kni\n");
522 /* Release the kni for following testing */
523 if (rte_kni_release(kni) < 0) {
524 printf("fail to release kni\n");
530 if (rte_kni_release(kni) < 0) {
531 printf("fail to release kni\n");
544 struct rte_mempool *mp;
545 struct rte_kni_conf conf;
546 struct rte_eth_dev_info info;
547 struct rte_kni_ops ops;
548 const struct rte_pci_device *pci_dev;
549 const struct rte_bus *bus;
554 dir = opendir(KNI_MODULE_PATH);
556 if (errno == ENOENT) {
557 printf("Cannot run UT due to missing rte_kni module\n");
560 printf("opendir: %s", strerror(errno));
565 /* Initialize KNI subsystem */
566 ret = rte_kni_init(KNI_TEST_MAX_PORTS);
568 printf("fail to initialize KNI subsystem\n");
572 if (test_kni_allocate_lcores() < 0) {
573 printf("No enough lcores for kni processing\n");
577 mp = test_kni_create_mempool();
579 printf("fail to create mempool for kni\n");
583 /* configuring port 0 for the test is enough */
585 ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf);
587 printf("fail to configure port %d\n", port_id);
591 ret = rte_eth_rx_queue_setup(port_id, 0, NB_RXD, SOCKET, &rx_conf, mp);
593 printf("fail to setup rx queue for port %d\n", port_id);
597 ret = rte_eth_tx_queue_setup(port_id, 0, NB_TXD, SOCKET, &tx_conf);
599 printf("fail to setup tx queue for port %d\n", port_id);
603 ret = rte_eth_dev_start(port_id);
605 printf("fail to start port %d\n", port_id);
608 ret = rte_eth_promiscuous_enable(port_id);
610 printf("fail to enable promiscuous mode for port %d: %s\n",
611 port_id, rte_strerror(-ret));
615 /* basic test of kni processing */
616 fd = fopen(KNI_MODULE_PARAM_LO, "r");
618 printf("fopen: %s", strerror(errno));
621 memset(&buf, 0, sizeof(buf));
622 if (fgets(buf, sizeof(buf), fd)) {
623 if (!strncmp(buf, "lo_mode_fifo", strlen("lo_mode_fifo")) ||
624 !strncmp(buf, "lo_mode_fifo_skb",
625 strlen("lo_mode_fifo_skb"))) {
626 ret = test_kni_processing(port_id, mp);
632 printf("test_kni_processing skipped because of missing rte_kni module lo_mode argument\n");
636 /* test of allocating KNI with NULL mempool pointer */
637 memset(&info, 0, sizeof(info));
638 memset(&conf, 0, sizeof(conf));
639 memset(&ops, 0, sizeof(ops));
641 ret = rte_eth_dev_info_get(port_id, &info);
643 printf("Error during getting device (port %u) info: %s\n",
644 port_id, strerror(-ret));
649 bus = rte_bus_find_by_device(info.device);
652 if (bus && !strcmp(bus->name, "pci")) {
653 pci_dev = RTE_DEV_TO_PCI(info.device);
654 conf.addr = pci_dev->addr;
655 conf.id = pci_dev->id;
657 conf.group_id = port_id;
658 conf.mbuf_size = MAX_PACKET_SZ;
661 ops.port_id = port_id;
662 kni = rte_kni_alloc(NULL, &conf, &ops);
665 printf("unexpectedly creates kni successfully with NULL "
666 "mempool pointer\n");
670 /* test of allocating KNI without configurations */
671 kni = rte_kni_alloc(mp, NULL, NULL);
674 printf("Unexpectedly allocate KNI device successfully "
675 "without configurations\n");
679 /* test of allocating KNI without a name */
680 memset(&conf, 0, sizeof(conf));
681 memset(&info, 0, sizeof(info));
682 memset(&ops, 0, sizeof(ops));
684 ret = rte_eth_dev_info_get(port_id, &info);
686 printf("Error during getting device (port %u) info: %s\n",
687 port_id, strerror(-ret));
693 bus = rte_bus_find_by_device(info.device);
696 if (bus && !strcmp(bus->name, "pci")) {
697 pci_dev = RTE_DEV_TO_PCI(info.device);
698 conf.addr = pci_dev->addr;
699 conf.id = pci_dev->id;
701 conf.group_id = port_id;
702 conf.mbuf_size = MAX_PACKET_SZ;
705 ops.port_id = port_id;
706 kni = rte_kni_alloc(mp, &conf, &ops);
709 printf("Unexpectedly allocate a KNI device successfully "
714 /* test of releasing NULL kni context */
715 ret = rte_kni_release(NULL);
718 printf("unexpectedly release kni successfully\n");
722 /* test of handling request on NULL device pointer */
723 ret = rte_kni_handle_request(NULL);
726 printf("Unexpectedly handle request on NULL device pointer\n");
730 /* test of getting KNI device with pointer to NULL */
731 kni = rte_kni_get(NULL);
734 printf("Unexpectedly get a KNI device with "
735 "NULL name pointer\n");
739 /* test of getting KNI device with an zero length name string */
740 memset(&conf, 0, sizeof(conf));
741 kni = rte_kni_get(conf.name);
744 printf("Unexpectedly get a KNI device with "
745 "zero length name string\n");
749 /* test of getting KNI device with an invalid string name */
750 memset(&conf, 0, sizeof(conf));
751 snprintf(conf.name, sizeof(conf.name), "testing");
752 kni = rte_kni_get(conf.name);
755 printf("Unexpectedly get a KNI device with "
756 "a never used name string\n");
762 if (rte_eth_dev_stop(port_id) != 0)
763 printf("Failed to stop port %u\n", port_id);
770 REGISTER_TEST_COMMAND(kni_autotest, test_kni);