1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
14 #if !defined(RTE_EXEC_ENV_LINUXAPP) || !defined(RTE_LIBRTE_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 lcore_master, 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 master 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_master) {
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_master = rte_get_master_lcore();
280 printf("master lcore: %u\n", lcore_master);
281 for (i = 0; i < RTE_MAX_LCORE; i++) {
284 if (rte_lcore_is_enabled(i) && i != lcore_master) {
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 rte_eth_dev_info_get(port_id, &info);
441 bus = rte_bus_find_by_device(info.device);
442 if (bus && !strcmp(bus->name, "pci")) {
443 pci_dev = RTE_DEV_TO_PCI(info.device);
444 conf.addr = pci_dev->addr;
445 conf.id = pci_dev->id;
447 snprintf(conf.name, sizeof(conf.name), TEST_KNI_PORT);
449 /* core id 1 configured for kernel thread */
452 conf.mbuf_size = MAX_PACKET_SZ;
453 conf.group_id = port_id;
456 ops.port_id = port_id;
458 /* basic test of kni processing */
459 kni = rte_kni_alloc(mp, &conf, &ops);
461 printf("fail to create kni\n");
466 test_kni_processing_flag = 0;
471 * Check multiple processes support on
472 * registerring/unregisterring handlers.
474 if (test_kni_register_handler_mp() < 0) {
475 printf("fail to check multiple process support\n");
480 ret = test_kni_link_change();
484 rte_eal_mp_remote_launch(test_kni_loop, NULL, CALL_MASTER);
485 RTE_LCORE_FOREACH_SLAVE(i) {
486 if (rte_eal_wait_lcore(i) < 0) {
492 * Check if the number of mbufs received from kernel space is equal
493 * to that of transmitted to kernel space
495 if (stats.ingress < KNI_NUM_MBUF_THRESHOLD ||
496 stats.egress < KNI_NUM_MBUF_THRESHOLD) {
497 printf("The ingress/egress number should not be "
498 "less than %u\n", (unsigned)KNI_NUM_MBUF_THRESHOLD);
503 if (rte_kni_release(kni) < 0) {
504 printf("fail to release kni\n");
509 /* test of reusing memzone */
510 kni = rte_kni_alloc(mp, &conf, &ops);
512 printf("fail to create kni\n");
516 /* Release the kni for following testing */
517 if (rte_kni_release(kni) < 0) {
518 printf("fail to release kni\n");
524 if (rte_kni_release(kni) < 0) {
525 printf("fail to release kni\n");
538 struct rte_mempool *mp;
539 struct rte_kni_conf conf;
540 struct rte_eth_dev_info info;
541 struct rte_kni_ops ops;
542 const struct rte_pci_device *pci_dev;
543 const struct rte_bus *bus;
548 dir = opendir(KNI_MODULE_PATH);
550 if (errno == ENOENT) {
551 printf("Cannot run UT due to missing rte_kni module\n");
554 printf("opendir: %s", strerror(errno));
559 /* Initialize KNI subsytem */
560 rte_kni_init(KNI_TEST_MAX_PORTS);
562 if (test_kni_allocate_lcores() < 0) {
563 printf("No enough lcores for kni processing\n");
567 mp = test_kni_create_mempool();
569 printf("fail to create mempool for kni\n");
573 /* configuring port 0 for the test is enough */
575 ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf);
577 printf("fail to configure port %d\n", port_id);
581 ret = rte_eth_rx_queue_setup(port_id, 0, NB_RXD, SOCKET, &rx_conf, mp);
583 printf("fail to setup rx queue for port %d\n", port_id);
587 ret = rte_eth_tx_queue_setup(port_id, 0, NB_TXD, SOCKET, &tx_conf);
589 printf("fail to setup tx queue for port %d\n", port_id);
593 ret = rte_eth_dev_start(port_id);
595 printf("fail to start port %d\n", port_id);
598 rte_eth_promiscuous_enable(port_id);
600 /* basic test of kni processing */
601 fd = fopen(KNI_MODULE_PARAM_LO, "r");
603 printf("fopen: %s", strerror(errno));
606 memset(&buf, 0, sizeof(buf));
607 if (fgets(buf, sizeof(buf), fd)) {
608 if (!strncmp(buf, "lo_mode_fifo", strlen("lo_mode_fifo")) ||
609 !strncmp(buf, "lo_mode_fifo_skb",
610 strlen("lo_mode_fifo_skb"))) {
611 ret = test_kni_processing(port_id, mp);
617 printf("test_kni_processing skipped because of missing rte_kni module lo_mode argument\n");
621 /* test of allocating KNI with NULL mempool pointer */
622 memset(&info, 0, sizeof(info));
623 memset(&conf, 0, sizeof(conf));
624 memset(&ops, 0, sizeof(ops));
625 rte_eth_dev_info_get(port_id, &info);
627 bus = rte_bus_find_by_device(info.device);
630 if (bus && !strcmp(bus->name, "pci")) {
631 pci_dev = RTE_DEV_TO_PCI(info.device);
632 conf.addr = pci_dev->addr;
633 conf.id = pci_dev->id;
635 conf.group_id = port_id;
636 conf.mbuf_size = MAX_PACKET_SZ;
639 ops.port_id = port_id;
640 kni = rte_kni_alloc(NULL, &conf, &ops);
643 printf("unexpectedly creates kni successfully with NULL "
644 "mempool pointer\n");
648 /* test of allocating KNI without configurations */
649 kni = rte_kni_alloc(mp, NULL, NULL);
652 printf("Unexpectedly allocate KNI device successfully "
653 "without configurations\n");
657 /* test of allocating KNI without a name */
658 memset(&conf, 0, sizeof(conf));
659 memset(&info, 0, sizeof(info));
660 memset(&ops, 0, sizeof(ops));
661 rte_eth_dev_info_get(port_id, &info);
663 bus = rte_bus_find_by_device(info.device);
666 if (bus && !strcmp(bus->name, "pci")) {
667 pci_dev = RTE_DEV_TO_PCI(info.device);
668 conf.addr = pci_dev->addr;
669 conf.id = pci_dev->id;
671 conf.group_id = port_id;
672 conf.mbuf_size = MAX_PACKET_SZ;
675 ops.port_id = port_id;
676 kni = rte_kni_alloc(mp, &conf, &ops);
679 printf("Unexpectedly allocate a KNI device successfully "
684 /* test of releasing NULL kni context */
685 ret = rte_kni_release(NULL);
688 printf("unexpectedly release kni successfully\n");
692 /* test of handling request on NULL device pointer */
693 ret = rte_kni_handle_request(NULL);
696 printf("Unexpectedly handle request on NULL device pointer\n");
700 /* test of getting KNI device with pointer to NULL */
701 kni = rte_kni_get(NULL);
704 printf("Unexpectedly get a KNI device with "
705 "NULL name pointer\n");
709 /* test of getting KNI device with an zero length name string */
710 memset(&conf, 0, sizeof(conf));
711 kni = rte_kni_get(conf.name);
714 printf("Unexpectedly get a KNI device with "
715 "zero length name string\n");
719 /* test of getting KNI device with an invalid string name */
720 memset(&conf, 0, sizeof(conf));
721 snprintf(conf.name, sizeof(conf.name), "testing");
722 kni = rte_kni_get(conf.name);
725 printf("Unexpectedly get a KNI device with "
726 "a never used name string\n");
732 rte_eth_dev_stop(port_id);
739 REGISTER_TEST_COMMAND(kni_autotest, test_kni);