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
test_kni(void)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 *
test_kni_create_mempool(void)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 *
test_kni_lookup_mempool(void)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
kni_change_mtu(uint16_t port_id,unsigned int new_mtu)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
test_kni_link_change(void)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
test_kni_loop(__rte_unused void * arg)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
test_kni_allocate_lcores(void)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
test_kni_register_handler_mp(void)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
test_kni_processing(uint16_t port_id,struct rte_mempool * mp)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
test_kni(void)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