1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include "test.h" 6 7 #include <stdio.h> 8 #include <stdint.h> 9 #include <unistd.h> 10 #include <string.h> 11 #if !defined(RTE_EXEC_ENV_LINUX) || !defined(RTE_LIB_KNI) 12 13 static int 14 test_kni(void) 15 { 16 printf("KNI not supported, skipping test\n"); 17 return TEST_SKIPPED; 18 } 19 20 #else 21 22 #include <sys/wait.h> 23 #include <dirent.h> 24 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> 30 #include <rte_kni.h> 31 32 #define NB_MBUF 8192 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 37 #define SOCKET 0 38 #define NB_RXD 1024 39 #define NB_TXD 1024 40 #define KNI_TIMEOUT_MS 5000 /* ms */ 41 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; 50 51 struct test_kni_stats { 52 volatile uint64_t ingress; 53 volatile uint64_t egress; 54 }; 55 56 static const struct rte_eth_rxconf rx_conf = { 57 .rx_thresh = { 58 .pthresh = 8, 59 .hthresh = 8, 60 .wthresh = 4, 61 }, 62 .rx_free_thresh = 0, 63 }; 64 65 static const struct rte_eth_txconf tx_conf = { 66 .tx_thresh = { 67 .pthresh = 36, 68 .hthresh = 0, 69 .wthresh = 0, 70 }, 71 .tx_free_thresh = 0, 72 .tx_rs_thresh = 0, 73 }; 74 75 static const struct rte_eth_conf port_conf = { 76 .txmode = { 77 .mq_mode = RTE_ETH_MQ_TX_NONE, 78 }, 79 }; 80 81 static struct rte_kni_ops kni_ops = { 82 .change_mtu = NULL, 83 .config_network_if = NULL, 84 .config_mac_address = NULL, 85 .config_promiscusity = NULL, 86 }; 87 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; 91 92 static volatile uint32_t test_kni_processing_flag; 93 94 static struct rte_mempool * 95 test_kni_create_mempool(void) 96 { 97 struct rte_mempool * mp; 98 99 mp = rte_mempool_lookup("kni_mempool"); 100 if (!mp) 101 mp = rte_pktmbuf_pool_create("kni_mempool", 102 NB_MBUF, 103 MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, 104 SOCKET); 105 106 return mp; 107 } 108 109 static struct rte_mempool * 110 test_kni_lookup_mempool(void) 111 { 112 return rte_mempool_lookup("kni_mempool"); 113 } 114 /* Callback for request of changing MTU */ 115 static int 116 kni_change_mtu(uint16_t port_id, unsigned int new_mtu) 117 { 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); 122 return 0; 123 } 124 125 static int 126 test_kni_link_change(void) 127 { 128 int ret; 129 int pid; 130 131 pid = fork(); 132 if (pid < 0) { 133 printf("Error: Failed to fork a process\n"); 134 return -1; 135 } 136 137 if (pid == 0) { 138 printf("Starting KNI Link status change tests.\n"); 139 if (system(IFCONFIG TEST_KNI_PORT" up") == -1) { 140 ret = -1; 141 goto error; 142 } 143 144 ret = rte_kni_update_link(test_kni_ctx, 1); 145 if (ret < 0) { 146 printf("Failed to change link state to Up ret=%d.\n", 147 ret); 148 goto error; 149 } 150 rte_delay_ms(1000); 151 printf("KNI: Set LINKUP, previous state=%d\n", ret); 152 153 ret = rte_kni_update_link(test_kni_ctx, 0); 154 if (ret != 1) { 155 printf( 156 "Failed! Previous link state should be 1, returned %d.\n", 157 ret); 158 goto error; 159 } 160 rte_delay_ms(1000); 161 printf("KNI: Set LINKDOWN, previous state=%d\n", ret); 162 163 ret = rte_kni_update_link(test_kni_ctx, 1); 164 if (ret != 0) { 165 printf( 166 "Failed! Previous link state should be 0, returned %d.\n", 167 ret); 168 goto error; 169 } 170 printf("KNI: Set LINKUP, previous state=%d\n", ret); 171 172 ret = 0; 173 rte_delay_ms(1000); 174 175 error: 176 if (system(IFCONFIG TEST_KNI_PORT" down") == -1) 177 ret = -1; 178 179 printf("KNI: Link status change tests: %s.\n", 180 (ret == 0) ? "Passed" : "Failed"); 181 exit(ret); 182 } else { 183 int p_ret, status; 184 185 while (1) { 186 p_ret = waitpid(pid, &status, WNOHANG); 187 if (p_ret != 0) { 188 if (WIFEXITED(status)) 189 return WEXITSTATUS(status); 190 return -1; 191 } 192 rte_delay_ms(10); 193 rte_kni_handle_request(test_kni_ctx); 194 } 195 } 196 } 197 /** 198 * This loop fully tests the basic functions of KNI. e.g. transmitting, 199 * receiving to, from kernel space, and kernel requests. 200 * 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. 208 * 209 * Note: To support this testing, the KNI kernel module needs to be insmodded 210 * in one of its loopback modes. 211 */ 212 static int 213 test_kni_loop(__rte_unused void *arg) 214 { 215 int ret = 0; 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]; 219 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) 224 ret = -1; 225 if (system(IFCONFIG TEST_KNI_PORT" mtu 1400") == -1) 226 ret = -1; 227 if (system(IFCONFIG TEST_KNI_PORT" down") == -1) 228 ret = -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(); 233 234 if (mp == NULL) 235 return -1; 236 237 while (1) { 238 if (test_kni_processing_flag) 239 break; 240 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]) 244 break; 245 } 246 247 num = rte_kni_tx_burst(test_kni_ctx, pkts_burst, 248 nb_rx); 249 stats.ingress += num; 250 rte_kni_handle_request(test_kni_ctx); 251 if (num < nb_rx) { 252 for (i = num; i < nb_rx; i++) { 253 rte_pktmbuf_free(pkts_burst[i]); 254 } 255 } 256 rte_delay_ms(10); 257 } 258 } else if (lcore_id == lcore_egress) { 259 while (1) { 260 if (test_kni_processing_flag) 261 break; 262 num = rte_kni_rx_burst(test_kni_ctx, pkts_burst, 263 PKT_BURST_SZ); 264 stats.egress += num; 265 for (nb_tx = 0; nb_tx < num; nb_tx++) 266 rte_pktmbuf_free(pkts_burst[nb_tx]); 267 rte_delay_ms(10); 268 } 269 } 270 271 return ret; 272 } 273 274 static int 275 test_kni_allocate_lcores(void) 276 { 277 unsigned i, count = 0; 278 279 lcore_main = rte_get_main_lcore(); 280 printf("main lcore: %u\n", lcore_main); 281 for (i = 0; i < RTE_MAX_LCORE; i++) { 282 if (count >=2 ) 283 break; 284 if (rte_lcore_is_enabled(i) && i != lcore_main) { 285 count ++; 286 if (count == 1) 287 lcore_ingress = i; 288 else if (count == 2) 289 lcore_egress = i; 290 } 291 } 292 printf("count: %u\n", count); 293 294 return count == 2 ? 0 : -1; 295 } 296 297 static int 298 test_kni_register_handler_mp(void) 299 { 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" 304 int pid; 305 306 pid = fork(); 307 if (pid < 0) { 308 printf("Failed to fork a process\n"); 309 return -1; 310 } else if (pid == 0) { 311 int i; 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, 318 }; 319 320 if (!kni) { 321 printf("Failed to get KNI named %s\n", TEST_KNI_PORT); 322 exit(-1); 323 } 324 325 kni_pkt_mtu = 0; 326 327 /* Check with the invalid parameters */ 328 if (rte_kni_register_handlers(kni, NULL) == 0) { 329 printf("Unexpectedly register successfully " 330 "with NULL ops pointer\n"); 331 exit(-1); 332 } 333 if (rte_kni_register_handlers(NULL, &ops) == 0) { 334 printf("Unexpectedly register successfully " 335 "to NULL KNI device pointer\n"); 336 exit(-1); 337 } 338 339 if (rte_kni_register_handlers(kni, &ops)) { 340 printf("Fail to register ops\n"); 341 exit(-1); 342 } 343 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"); 348 exit(-1); 349 } 350 351 /** 352 * Handle the request of setting MTU, 353 * with registered handlers. 354 */ 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) 358 break; 359 rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL); 360 } 361 if (i >= TEST_KNI_HANDLE_REQ_COUNT) { 362 printf("MTU has not been set\n"); 363 exit(-1); 364 } 365 366 kni_pkt_mtu = 0; 367 if (rte_kni_unregister_handlers(kni) < 0) { 368 printf("Fail to unregister ops\n"); 369 exit(-1); 370 } 371 372 /* Check with invalid parameter */ 373 if (rte_kni_unregister_handlers(NULL) == 0) { 374 exit(-1); 375 } 376 377 /** 378 * Handle the request of setting MTU, 379 * without registered handlers. 380 */ 381 for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) { 382 rte_kni_handle_request(kni); 383 if (kni_pkt_mtu != 0) 384 break; 385 rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL); 386 } 387 if (kni_pkt_mtu != 0) { 388 printf("MTU shouldn't be set\n"); 389 exit(-1); 390 } 391 392 exit(0); 393 } else { 394 int p_ret, status; 395 396 rte_delay_ms(1000); 397 if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR) 398 == -1) 399 return -1; 400 401 rte_delay_ms(1000); 402 if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR) 403 == -1) 404 return -1; 405 406 p_ret = wait(&status); 407 if (!WIFEXITED(status)) { 408 printf("Child process (%d) exit abnormally\n", p_ret); 409 return -1; 410 } 411 if (WEXITSTATUS(status) != 0) { 412 printf("Child process exit with failure\n"); 413 return -1; 414 } 415 } 416 417 return 0; 418 } 419 420 static int 421 test_kni_processing(uint16_t port_id, struct rte_mempool *mp) 422 { 423 int ret = 0; 424 unsigned i; 425 struct rte_kni *kni; 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; 431 432 if (!mp) 433 return -1; 434 435 memset(&conf, 0, sizeof(conf)); 436 memset(&info, 0, sizeof(info)); 437 memset(&ops, 0, sizeof(ops)); 438 439 ret = rte_eth_dev_info_get(port_id, &info); 440 if (ret != 0) { 441 printf("Error during getting device (port %u) info: %s\n", 442 port_id, strerror(-ret)); 443 return -1; 444 } 445 446 if (info.device) 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; 452 } 453 snprintf(conf.name, sizeof(conf.name), TEST_KNI_PORT); 454 455 /* core id 1 configured for kernel thread */ 456 conf.core_id = 1; 457 conf.force_bind = 1; 458 conf.mbuf_size = MAX_PACKET_SZ; 459 conf.group_id = port_id; 460 461 ops = kni_ops; 462 ops.port_id = port_id; 463 464 /* basic test of kni processing */ 465 kni = rte_kni_alloc(mp, &conf, &ops); 466 if (!kni) { 467 printf("fail to create kni\n"); 468 return -1; 469 } 470 471 test_kni_ctx = kni; 472 test_kni_processing_flag = 0; 473 stats.ingress = 0; 474 stats.egress = 0; 475 476 /** 477 * Check multiple processes support on 478 * registering/unregistering handlers. 479 */ 480 if (test_kni_register_handler_mp() < 0) { 481 printf("fail to check multiple process support\n"); 482 ret = -1; 483 goto fail_kni; 484 } 485 486 ret = test_kni_link_change(); 487 if (ret != 0) 488 goto fail_kni; 489 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) { 493 ret = -1; 494 goto fail_kni; 495 } 496 } 497 /** 498 * Check if the number of mbufs received from kernel space is equal 499 * to that of transmitted to kernel space 500 */ 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); 505 ret = -1; 506 goto fail_kni; 507 } 508 509 if (rte_kni_release(kni) < 0) { 510 printf("fail to release kni\n"); 511 return -1; 512 } 513 test_kni_ctx = NULL; 514 515 /* test of reusing memzone */ 516 kni = rte_kni_alloc(mp, &conf, &ops); 517 if (!kni) { 518 printf("fail to create kni\n"); 519 return -1; 520 } 521 522 /* Release the kni for following testing */ 523 if (rte_kni_release(kni) < 0) { 524 printf("fail to release kni\n"); 525 return -1; 526 } 527 528 return ret; 529 fail_kni: 530 if (rte_kni_release(kni) < 0) { 531 printf("fail to release kni\n"); 532 ret = -1; 533 } 534 535 return ret; 536 } 537 538 static int 539 test_kni(void) 540 { 541 int ret = -1; 542 uint16_t port_id; 543 struct rte_kni *kni; 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; 550 FILE *fd; 551 DIR *dir; 552 char buf[16]; 553 554 dir = opendir(KNI_MODULE_PATH); 555 if (!dir) { 556 if (errno == ENOENT) { 557 printf("Cannot run UT due to missing rte_kni module\n"); 558 return TEST_SKIPPED; 559 } 560 printf("opendir: %s", strerror(errno)); 561 return -1; 562 } 563 closedir(dir); 564 565 /* Initialize KNI subsystem */ 566 ret = rte_kni_init(KNI_TEST_MAX_PORTS); 567 if (ret < 0) { 568 printf("fail to initialize KNI subsystem\n"); 569 return -1; 570 } 571 572 if (test_kni_allocate_lcores() < 0) { 573 printf("No enough lcores for kni processing\n"); 574 return -1; 575 } 576 577 mp = test_kni_create_mempool(); 578 if (!mp) { 579 printf("fail to create mempool for kni\n"); 580 return -1; 581 } 582 583 /* configuring port 0 for the test is enough */ 584 port_id = 0; 585 ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf); 586 if (ret < 0) { 587 printf("fail to configure port %d\n", port_id); 588 return -1; 589 } 590 591 ret = rte_eth_rx_queue_setup(port_id, 0, NB_RXD, SOCKET, &rx_conf, mp); 592 if (ret < 0) { 593 printf("fail to setup rx queue for port %d\n", port_id); 594 return -1; 595 } 596 597 ret = rte_eth_tx_queue_setup(port_id, 0, NB_TXD, SOCKET, &tx_conf); 598 if (ret < 0) { 599 printf("fail to setup tx queue for port %d\n", port_id); 600 return -1; 601 } 602 603 ret = rte_eth_dev_start(port_id); 604 if (ret < 0) { 605 printf("fail to start port %d\n", port_id); 606 return -1; 607 } 608 ret = rte_eth_promiscuous_enable(port_id); 609 if (ret != 0) { 610 printf("fail to enable promiscuous mode for port %d: %s\n", 611 port_id, rte_strerror(-ret)); 612 return -1; 613 } 614 615 /* basic test of kni processing */ 616 fd = fopen(KNI_MODULE_PARAM_LO, "r"); 617 if (fd == NULL) { 618 printf("fopen: %s", strerror(errno)); 619 return -1; 620 } 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); 627 if (ret < 0) { 628 fclose(fd); 629 goto fail; 630 } 631 } else 632 printf("test_kni_processing skipped because of missing rte_kni module lo_mode argument\n"); 633 } 634 fclose(fd); 635 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)); 640 641 ret = rte_eth_dev_info_get(port_id, &info); 642 if (ret != 0) { 643 printf("Error during getting device (port %u) info: %s\n", 644 port_id, strerror(-ret)); 645 return -1; 646 } 647 648 if (info.device) 649 bus = rte_bus_find_by_device(info.device); 650 else 651 bus = NULL; 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; 656 } 657 conf.group_id = port_id; 658 conf.mbuf_size = MAX_PACKET_SZ; 659 660 ops = kni_ops; 661 ops.port_id = port_id; 662 kni = rte_kni_alloc(NULL, &conf, &ops); 663 if (kni) { 664 ret = -1; 665 printf("unexpectedly creates kni successfully with NULL " 666 "mempool pointer\n"); 667 goto fail; 668 } 669 670 /* test of allocating KNI without configurations */ 671 kni = rte_kni_alloc(mp, NULL, NULL); 672 if (kni) { 673 ret = -1; 674 printf("Unexpectedly allocate KNI device successfully " 675 "without configurations\n"); 676 goto fail; 677 } 678 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)); 683 684 ret = rte_eth_dev_info_get(port_id, &info); 685 if (ret != 0) { 686 printf("Error during getting device (port %u) info: %s\n", 687 port_id, strerror(-ret)); 688 ret = -1; 689 goto fail; 690 } 691 692 if (info.device) 693 bus = rte_bus_find_by_device(info.device); 694 else 695 bus = NULL; 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; 700 } 701 conf.group_id = port_id; 702 conf.mbuf_size = MAX_PACKET_SZ; 703 704 ops = kni_ops; 705 ops.port_id = port_id; 706 kni = rte_kni_alloc(mp, &conf, &ops); 707 if (kni) { 708 ret = -1; 709 printf("Unexpectedly allocate a KNI device successfully " 710 "without a name\n"); 711 goto fail; 712 } 713 714 /* test of releasing NULL kni context */ 715 ret = rte_kni_release(NULL); 716 if (ret == 0) { 717 ret = -1; 718 printf("unexpectedly release kni successfully\n"); 719 goto fail; 720 } 721 722 /* test of handling request on NULL device pointer */ 723 ret = rte_kni_handle_request(NULL); 724 if (ret == 0) { 725 ret = -1; 726 printf("Unexpectedly handle request on NULL device pointer\n"); 727 goto fail; 728 } 729 730 /* test of getting KNI device with pointer to NULL */ 731 kni = rte_kni_get(NULL); 732 if (kni) { 733 ret = -1; 734 printf("Unexpectedly get a KNI device with " 735 "NULL name pointer\n"); 736 goto fail; 737 } 738 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); 742 if (kni) { 743 ret = -1; 744 printf("Unexpectedly get a KNI device with " 745 "zero length name string\n"); 746 goto fail; 747 } 748 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); 753 if (kni) { 754 ret = -1; 755 printf("Unexpectedly get a KNI device with " 756 "a never used name string\n"); 757 goto fail; 758 } 759 ret = 0; 760 761 fail: 762 if (rte_eth_dev_stop(port_id) != 0) 763 printf("Failed to stop port %u\n", port_id); 764 765 return ret; 766 } 767 768 #endif 769 770 REGISTER_TEST_COMMAND(kni_autotest, test_kni); 771