4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 #include <rte_string_fns.h>
43 #include <rte_mempool.h>
44 #include <rte_ethdev.h>
45 #include <rte_cycles.h>
49 #define MAX_PACKET_SZ 2048
51 (MAX_PACKET_SZ + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
52 #define PKT_BURST_SZ 32
53 #define MEMPOOL_CACHE_SZ PKT_BURST_SZ
57 #define KNI_TIMEOUT_MS 5000 /* ms */
59 #define IFCONFIG "/sbin/ifconfig "
60 #define TEST_KNI_PORT "test_kni_port"
61 #define KNI_TEST_MAX_PORTS 4
62 /* The threshold number of mbufs to be transmitted or received. */
63 #define KNI_NUM_MBUF_THRESHOLD 100
64 static int kni_pkt_mtu = 0;
66 struct test_kni_stats {
67 volatile uint64_t ingress;
68 volatile uint64_t egress;
71 static const struct rte_eth_rxconf rx_conf = {
80 static const struct rte_eth_txconf tx_conf = {
90 static const struct rte_eth_conf port_conf = {
99 .mq_mode = ETH_DCB_NONE,
103 static struct rte_kni_ops kni_ops = {
105 .config_network_if = NULL,
108 static unsigned lcore_master, lcore_ingress, lcore_egress;
109 static struct rte_kni *test_kni_ctx;
110 static struct test_kni_stats stats;
112 static volatile uint32_t test_kni_processing_flag;
114 static struct rte_mempool *
115 test_kni_create_mempool(void)
117 struct rte_mempool * mp;
119 mp = rte_mempool_lookup("kni_mempool");
121 mp = rte_mempool_create("kni_mempool",
125 sizeof(struct rte_pktmbuf_pool_private),
126 rte_pktmbuf_pool_init,
136 static struct rte_mempool *
137 test_kni_lookup_mempool(void)
139 return rte_mempool_lookup("kni_mempool");
141 /* Callback for request of changing MTU */
143 kni_change_mtu(uint8_t port_id, unsigned new_mtu)
145 printf("Change MTU of port %d to %u\n", port_id, new_mtu);
146 kni_pkt_mtu = new_mtu;
147 printf("Change MTU of port %d to %i successfully.\n",
148 port_id, kni_pkt_mtu);
152 * This loop fully tests the basic functions of KNI. e.g. transmitting,
153 * receiving to, from kernel space, and kernel requests.
155 * This is the loop to transmit/receive mbufs to/from kernel interface with
156 * supported by KNI kernel module. The ingress lcore will allocate mbufs and
157 * transmit them to kernel space; while the egress lcore will receive the mbufs
158 * from kernel space and free them.
159 * On the master lcore, several commands will be run to check handling the
160 * kernel requests. And it will finally set the flag to exit the KNI
161 * transmitting/receiving to/from the kernel space.
163 * Note: To support this testing, the KNI kernel module needs to be insmodded
164 * in one of its loopback modes.
167 test_kni_loop(__rte_unused void *arg)
170 unsigned nb_rx, nb_tx, num, i;
171 const unsigned lcore_id = rte_lcore_id();
172 struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
174 if (lcore_id == lcore_master) {
175 rte_delay_ms(KNI_TIMEOUT_MS);
176 /* tests of handling kernel request */
177 if (system(IFCONFIG TEST_KNI_PORT" up") == -1)
179 if (system(IFCONFIG TEST_KNI_PORT" mtu 1400") == -1)
181 if (system(IFCONFIG TEST_KNI_PORT" down") == -1)
183 rte_delay_ms(KNI_TIMEOUT_MS);
184 test_kni_processing_flag = 1;
185 } else if (lcore_id == lcore_ingress) {
186 struct rte_mempool *mp = test_kni_lookup_mempool();
192 if (test_kni_processing_flag)
195 for (nb_rx = 0; nb_rx < PKT_BURST_SZ; nb_rx++) {
196 pkts_burst[nb_rx] = rte_pktmbuf_alloc(mp);
197 if (!pkts_burst[nb_rx])
201 num = rte_kni_tx_burst(test_kni_ctx, pkts_burst,
203 stats.ingress += num;
204 rte_kni_handle_request(test_kni_ctx);
206 for (i = num; i < nb_rx; i++) {
207 rte_pktmbuf_free(pkts_burst[i]);
212 } else if (lcore_id == lcore_egress) {
214 if (test_kni_processing_flag)
216 num = rte_kni_rx_burst(test_kni_ctx, pkts_burst,
219 for (nb_tx = 0; nb_tx < num; nb_tx++)
220 rte_pktmbuf_free(pkts_burst[nb_tx]);
229 test_kni_allocate_lcores(void)
231 unsigned i, count = 0;
233 lcore_master = rte_get_master_lcore();
234 printf("master lcore: %u\n", lcore_master);
235 for (i = 0; i < RTE_MAX_LCORE; i++) {
238 if (rte_lcore_is_enabled(i) && i != lcore_master) {
246 printf("count: %u\n", count);
248 return (count == 2 ? 0 : -1);
252 test_kni_register_handler_mp(void)
254 #define TEST_KNI_HANDLE_REQ_COUNT 10 /* 5s */
255 #define TEST_KNI_HANDLE_REQ_INTERVAL 500 /* ms */
256 #define TEST_KNI_MTU 1450
257 #define TEST_KNI_MTU_STR " 1450"
262 printf("Failed to fork a process\n");
264 } else if (pid == 0) {
266 struct rte_kni *kni = rte_kni_get(TEST_KNI_PORT);
267 struct rte_kni_ops ops = {
268 .change_mtu = kni_change_mtu,
269 .config_network_if = NULL,
273 printf("Failed to get KNI named %s\n", TEST_KNI_PORT);
279 /* Check with the invalid parameters */
280 if (rte_kni_register_handlers(kni, NULL) == 0) {
281 printf("Unexpectedly register successuflly "
282 "with NULL ops pointer\n");
285 if (rte_kni_register_handlers(NULL, &ops) == 0) {
286 printf("Unexpectedly register successfully "
287 "to NULL KNI device pointer\n");
291 if (rte_kni_register_handlers(kni, &ops)) {
292 printf("Fail to register ops\n");
296 /* Check registering again after it has been registered */
297 if (rte_kni_register_handlers(kni, &ops) == 0) {
298 printf("Unexpectedly register successfully after "
299 "it has already been registered\n");
304 * Handle the request of setting MTU,
305 * with registered handlers.
307 for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) {
308 rte_kni_handle_request(kni);
309 if (kni_pkt_mtu == TEST_KNI_MTU)
311 rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL);
313 if (i >= TEST_KNI_HANDLE_REQ_COUNT) {
314 printf("MTU has not been set\n");
319 if (rte_kni_unregister_handlers(kni) < 0) {
320 printf("Fail to unregister ops\n");
324 /* Check with invalid parameter */
325 if (rte_kni_unregister_handlers(NULL) == 0) {
330 * Handle the request of setting MTU,
331 * without registered handlers.
333 for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) {
334 rte_kni_handle_request(kni);
335 if (kni_pkt_mtu != 0)
337 rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL);
339 if (kni_pkt_mtu != 0) {
340 printf("MTU shouldn't be set\n");
349 if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR)
354 if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR)
358 p_ret = wait(&status);
359 if (!WIFEXITED(status)) {
360 printf("Child process (%d) exit abnormally\n", p_ret);
363 if (WEXITSTATUS(status) != 0) {
364 printf("Child process exit with failure\n");
373 test_kni_processing(uint8_t port_id, struct rte_mempool *mp)
378 struct rte_kni_conf conf;
379 struct rte_eth_dev_info info;
380 struct rte_kni_ops ops;
385 memset(&conf, 0, sizeof(conf));
386 memset(&info, 0, sizeof(info));
387 memset(&ops, 0, sizeof(ops));
389 rte_eth_dev_info_get(port_id, &info);
390 conf.addr = info.pci_dev->addr;
391 conf.id = info.pci_dev->id;
392 snprintf(conf.name, sizeof(conf.name), TEST_KNI_PORT);
394 /* core id 1 configured for kernel thread */
397 conf.mbuf_size = MAX_PACKET_SZ;
398 conf.group_id = (uint16_t)port_id;
401 ops.port_id = port_id;
403 /* basic test of kni processing */
404 kni = rte_kni_alloc(mp, &conf, &ops);
406 printf("fail to create kni\n");
409 if (rte_kni_get_port_id(kni) != port_id) {
410 printf("fail to get port id\n");
415 if (rte_kni_info_get(RTE_MAX_ETHPORTS)) {
416 printf("Unexpectedly get a KNI successfully\n");
422 test_kni_processing_flag = 0;
427 * Check multiple processes support on
428 * registerring/unregisterring handlers.
430 if (test_kni_register_handler_mp() < 0) {
431 printf("fail to check multiple process support\n");
436 rte_eal_mp_remote_launch(test_kni_loop, NULL, CALL_MASTER);
437 RTE_LCORE_FOREACH_SLAVE(i) {
438 if (rte_eal_wait_lcore(i) < 0) {
444 * Check if the number of mbufs received from kernel space is equal
445 * to that of transmitted to kernel space
447 if (stats.ingress < KNI_NUM_MBUF_THRESHOLD ||
448 stats.egress < KNI_NUM_MBUF_THRESHOLD) {
449 printf("The ingress/egress number should not be "
450 "less than %u\n", (unsigned)KNI_NUM_MBUF_THRESHOLD);
455 if (rte_kni_release(kni) < 0) {
456 printf("fail to release kni\n");
461 /* test of releasing a released kni device */
462 if (rte_kni_release(kni) == 0) {
463 printf("should not release a released kni device\n");
467 /* test of reusing memzone */
468 kni = rte_kni_alloc(mp, &conf, &ops);
470 printf("fail to create kni\n");
474 /* Release the kni for following testing */
475 if (rte_kni_release(kni) < 0) {
476 printf("fail to release kni\n");
482 if (rte_kni_release(kni) < 0) {
483 printf("fail to release kni\n");
494 uint8_t nb_ports, port_id;
496 struct rte_mempool *mp;
497 struct rte_kni_conf conf;
498 struct rte_eth_dev_info info;
499 struct rte_kni_ops ops;
501 /* Initialize KNI subsytem */
502 rte_kni_init(KNI_TEST_MAX_PORTS);
504 if (test_kni_allocate_lcores() < 0) {
505 printf("No enough lcores for kni processing\n");
509 mp = test_kni_create_mempool();
511 printf("fail to create mempool for kni\n");
515 nb_ports = rte_eth_dev_count();
517 printf("no supported nic port found\n");
521 /* configuring port 0 for the test is enough */
523 ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf);
525 printf("fail to configure port %d\n", port_id);
529 ret = rte_eth_rx_queue_setup(port_id, 0, NB_RXD, SOCKET, &rx_conf, mp);
531 printf("fail to setup rx queue for port %d\n", port_id);
535 ret = rte_eth_tx_queue_setup(port_id, 0, NB_TXD, SOCKET, &tx_conf);
537 printf("fail to setup tx queue for port %d\n", port_id);
541 ret = rte_eth_dev_start(port_id);
543 printf("fail to start port %d\n", port_id);
546 rte_eth_promiscuous_enable(port_id);
548 /* basic test of kni processing */
549 ret = test_kni_processing(port_id, mp);
553 /* test of allocating KNI with NULL mempool pointer */
554 memset(&info, 0, sizeof(info));
555 memset(&conf, 0, sizeof(conf));
556 memset(&ops, 0, sizeof(ops));
557 rte_eth_dev_info_get(port_id, &info);
558 conf.addr = info.pci_dev->addr;
559 conf.id = info.pci_dev->id;
560 conf.group_id = (uint16_t)port_id;
561 conf.mbuf_size = MAX_PACKET_SZ;
564 ops.port_id = port_id;
565 kni = rte_kni_alloc(NULL, &conf, &ops);
568 printf("unexpectedly creates kni successfully with NULL "
569 "mempool pointer\n");
573 /* test of allocating KNI without configurations */
574 kni = rte_kni_alloc(mp, NULL, NULL);
577 printf("Unexpectedly allocate KNI device successfully "
578 "without configurations\n");
582 /* test of allocating KNI without a name */
583 memset(&conf, 0, sizeof(conf));
584 memset(&info, 0, sizeof(info));
585 memset(&ops, 0, sizeof(ops));
586 rte_eth_dev_info_get(port_id, &info);
587 conf.addr = info.pci_dev->addr;
588 conf.id = info.pci_dev->id;
589 conf.group_id = (uint16_t)port_id;
590 conf.mbuf_size = MAX_PACKET_SZ;
593 ops.port_id = port_id;
594 kni = rte_kni_alloc(mp, &conf, &ops);
597 printf("Unexpectedly allocate a KNI device successfully "
602 /* test of getting port id according to NULL kni context */
603 if (rte_kni_get_port_id(NULL) < RTE_MAX_ETHPORTS) {
605 printf("unexpectedly get port id successfully by NULL kni "
610 /* test of releasing NULL kni context */
611 ret = rte_kni_release(NULL);
614 printf("unexpectedly release kni successfully\n");
618 /* test of handling request on NULL device pointer */
619 ret = rte_kni_handle_request(NULL);
622 printf("Unexpectedly handle request on NULL device pointer\n");
626 /* test of getting KNI device with pointer to NULL */
627 kni = rte_kni_get(NULL);
630 printf("Unexpectedly get a KNI device with "
631 "NULL name pointer\n");
635 /* test of getting KNI device with an zero length name string */
636 memset(&conf, 0, sizeof(conf));
637 kni = rte_kni_get(conf.name);
640 printf("Unexpectedly get a KNI device with "
641 "zero length name string\n");
645 /* test of getting KNI device with an invalid string name */
646 memset(&conf, 0, sizeof(conf));
647 snprintf(conf.name, sizeof(conf.name), "testing");
648 kni = rte_kni_get(conf.name);
651 printf("Unexpectedly get a KNI device with "
652 "a never used name string\n");
656 /* test the interface of creating a KNI, for backward compatibility */
657 memset(&ops, 0, sizeof(ops));
659 kni = rte_kni_create(port_id, MAX_PACKET_SZ, mp, &ops);
662 printf("Fail to create a KNI device for port %d\n", port_id);
666 ret = rte_kni_release(kni);
668 printf("Fail to release a KNI device\n");
675 rte_eth_dev_stop(port_id);
680 static struct test_command kni_cmd = {
681 .command = "kni_autotest",
682 .callback = test_kni,
684 REGISTER_TEST_COMMAND(kni_cmd);