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.
43 #include <rte_string_fns.h>
44 #include <rte_mempool.h>
45 #include <rte_ethdev.h>
46 #include <rte_cycles.h>
50 #define MAX_PACKET_SZ 2048
51 #define MBUF_DATA_SZ (MAX_PACKET_SZ + 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_MODULE_PATH "/sys/module/rte_kni"
62 #define KNI_MODULE_PARAM_LO KNI_MODULE_PATH"/parameters/lo_mode"
63 #define KNI_TEST_MAX_PORTS 4
64 /* The threshold number of mbufs to be transmitted or received. */
65 #define KNI_NUM_MBUF_THRESHOLD 100
66 static int kni_pkt_mtu = 0;
68 struct test_kni_stats {
69 volatile uint64_t ingress;
70 volatile uint64_t egress;
73 static const struct rte_eth_rxconf rx_conf = {
82 static const struct rte_eth_txconf tx_conf = {
92 static const struct rte_eth_conf port_conf = {
101 .mq_mode = ETH_DCB_NONE,
105 static struct rte_kni_ops kni_ops = {
107 .config_network_if = NULL,
110 static unsigned lcore_master, lcore_ingress, lcore_egress;
111 static struct rte_kni *test_kni_ctx;
112 static struct test_kni_stats stats;
114 static volatile uint32_t test_kni_processing_flag;
116 static struct rte_mempool *
117 test_kni_create_mempool(void)
119 struct rte_mempool * mp;
121 mp = rte_mempool_lookup("kni_mempool");
123 mp = rte_pktmbuf_pool_create("kni_mempool",
125 MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ,
131 static struct rte_mempool *
132 test_kni_lookup_mempool(void)
134 return rte_mempool_lookup("kni_mempool");
136 /* Callback for request of changing MTU */
138 kni_change_mtu(uint8_t port_id, unsigned new_mtu)
140 printf("Change MTU of port %d to %u\n", port_id, new_mtu);
141 kni_pkt_mtu = new_mtu;
142 printf("Change MTU of port %d to %i successfully.\n",
143 port_id, kni_pkt_mtu);
147 * This loop fully tests the basic functions of KNI. e.g. transmitting,
148 * receiving to, from kernel space, and kernel requests.
150 * This is the loop to transmit/receive mbufs to/from kernel interface with
151 * supported by KNI kernel module. The ingress lcore will allocate mbufs and
152 * transmit them to kernel space; while the egress lcore will receive the mbufs
153 * from kernel space and free them.
154 * On the master lcore, several commands will be run to check handling the
155 * kernel requests. And it will finally set the flag to exit the KNI
156 * transmitting/receiving to/from the kernel space.
158 * Note: To support this testing, the KNI kernel module needs to be insmodded
159 * in one of its loopback modes.
162 test_kni_loop(__rte_unused void *arg)
165 unsigned nb_rx, nb_tx, num, i;
166 const unsigned lcore_id = rte_lcore_id();
167 struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
169 if (lcore_id == lcore_master) {
170 rte_delay_ms(KNI_TIMEOUT_MS);
171 /* tests of handling kernel request */
172 if (system(IFCONFIG TEST_KNI_PORT" up") == -1)
174 if (system(IFCONFIG TEST_KNI_PORT" mtu 1400") == -1)
176 if (system(IFCONFIG TEST_KNI_PORT" down") == -1)
178 rte_delay_ms(KNI_TIMEOUT_MS);
179 test_kni_processing_flag = 1;
180 } else if (lcore_id == lcore_ingress) {
181 struct rte_mempool *mp = test_kni_lookup_mempool();
187 if (test_kni_processing_flag)
190 for (nb_rx = 0; nb_rx < PKT_BURST_SZ; nb_rx++) {
191 pkts_burst[nb_rx] = rte_pktmbuf_alloc(mp);
192 if (!pkts_burst[nb_rx])
196 num = rte_kni_tx_burst(test_kni_ctx, pkts_burst,
198 stats.ingress += num;
199 rte_kni_handle_request(test_kni_ctx);
201 for (i = num; i < nb_rx; i++) {
202 rte_pktmbuf_free(pkts_burst[i]);
207 } else if (lcore_id == lcore_egress) {
209 if (test_kni_processing_flag)
211 num = rte_kni_rx_burst(test_kni_ctx, pkts_burst,
214 for (nb_tx = 0; nb_tx < num; nb_tx++)
215 rte_pktmbuf_free(pkts_burst[nb_tx]);
224 test_kni_allocate_lcores(void)
226 unsigned i, count = 0;
228 lcore_master = rte_get_master_lcore();
229 printf("master lcore: %u\n", lcore_master);
230 for (i = 0; i < RTE_MAX_LCORE; i++) {
233 if (rte_lcore_is_enabled(i) && i != lcore_master) {
241 printf("count: %u\n", count);
243 return count == 2 ? 0 : -1;
247 test_kni_register_handler_mp(void)
249 #define TEST_KNI_HANDLE_REQ_COUNT 10 /* 5s */
250 #define TEST_KNI_HANDLE_REQ_INTERVAL 500 /* ms */
251 #define TEST_KNI_MTU 1450
252 #define TEST_KNI_MTU_STR " 1450"
257 printf("Failed to fork a process\n");
259 } else if (pid == 0) {
261 struct rte_kni *kni = rte_kni_get(TEST_KNI_PORT);
262 struct rte_kni_ops ops = {
263 .change_mtu = kni_change_mtu,
264 .config_network_if = NULL,
268 printf("Failed to get KNI named %s\n", TEST_KNI_PORT);
274 /* Check with the invalid parameters */
275 if (rte_kni_register_handlers(kni, NULL) == 0) {
276 printf("Unexpectedly register successuflly "
277 "with NULL ops pointer\n");
280 if (rte_kni_register_handlers(NULL, &ops) == 0) {
281 printf("Unexpectedly register successfully "
282 "to NULL KNI device pointer\n");
286 if (rte_kni_register_handlers(kni, &ops)) {
287 printf("Fail to register ops\n");
291 /* Check registering again after it has been registered */
292 if (rte_kni_register_handlers(kni, &ops) == 0) {
293 printf("Unexpectedly register successfully after "
294 "it has already been registered\n");
299 * Handle the request of setting MTU,
300 * with registered handlers.
302 for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) {
303 rte_kni_handle_request(kni);
304 if (kni_pkt_mtu == TEST_KNI_MTU)
306 rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL);
308 if (i >= TEST_KNI_HANDLE_REQ_COUNT) {
309 printf("MTU has not been set\n");
314 if (rte_kni_unregister_handlers(kni) < 0) {
315 printf("Fail to unregister ops\n");
319 /* Check with invalid parameter */
320 if (rte_kni_unregister_handlers(NULL) == 0) {
325 * Handle the request of setting MTU,
326 * without registered handlers.
328 for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) {
329 rte_kni_handle_request(kni);
330 if (kni_pkt_mtu != 0)
332 rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL);
334 if (kni_pkt_mtu != 0) {
335 printf("MTU shouldn't be set\n");
344 if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR)
349 if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR)
353 p_ret = wait(&status);
354 if (!WIFEXITED(status)) {
355 printf("Child process (%d) exit abnormally\n", p_ret);
358 if (WEXITSTATUS(status) != 0) {
359 printf("Child process exit with failure\n");
368 test_kni_processing(uint8_t port_id, struct rte_mempool *mp)
373 struct rte_kni_conf conf;
374 struct rte_eth_dev_info info;
375 struct rte_kni_ops ops;
380 memset(&conf, 0, sizeof(conf));
381 memset(&info, 0, sizeof(info));
382 memset(&ops, 0, sizeof(ops));
384 rte_eth_dev_info_get(port_id, &info);
385 conf.addr = info.pci_dev->addr;
386 conf.id = info.pci_dev->id;
387 snprintf(conf.name, sizeof(conf.name), TEST_KNI_PORT);
389 /* core id 1 configured for kernel thread */
392 conf.mbuf_size = MAX_PACKET_SZ;
393 conf.group_id = (uint16_t)port_id;
396 ops.port_id = port_id;
398 /* basic test of kni processing */
399 kni = rte_kni_alloc(mp, &conf, &ops);
401 printf("fail to create kni\n");
406 test_kni_processing_flag = 0;
411 * Check multiple processes support on
412 * registerring/unregisterring handlers.
414 if (test_kni_register_handler_mp() < 0) {
415 printf("fail to check multiple process support\n");
420 rte_eal_mp_remote_launch(test_kni_loop, NULL, CALL_MASTER);
421 RTE_LCORE_FOREACH_SLAVE(i) {
422 if (rte_eal_wait_lcore(i) < 0) {
428 * Check if the number of mbufs received from kernel space is equal
429 * to that of transmitted to kernel space
431 if (stats.ingress < KNI_NUM_MBUF_THRESHOLD ||
432 stats.egress < KNI_NUM_MBUF_THRESHOLD) {
433 printf("The ingress/egress number should not be "
434 "less than %u\n", (unsigned)KNI_NUM_MBUF_THRESHOLD);
439 if (rte_kni_release(kni) < 0) {
440 printf("fail to release kni\n");
445 /* test of releasing a released kni device */
446 if (rte_kni_release(kni) == 0) {
447 printf("should not release a released kni device\n");
451 /* test of reusing memzone */
452 kni = rte_kni_alloc(mp, &conf, &ops);
454 printf("fail to create kni\n");
458 /* Release the kni for following testing */
459 if (rte_kni_release(kni) < 0) {
460 printf("fail to release kni\n");
466 if (rte_kni_release(kni) < 0) {
467 printf("fail to release kni\n");
480 struct rte_mempool *mp;
481 struct rte_kni_conf conf;
482 struct rte_eth_dev_info info;
483 struct rte_kni_ops ops;
489 dir = opendir(KNI_MODULE_PATH);
491 if (errno == ENOENT) {
492 printf("Cannot run UT due to missing rte_kni module\n");
495 printf("opendir: %s", strerror(errno));
500 /* Initialize KNI subsytem */
501 rte_kni_init(KNI_TEST_MAX_PORTS);
503 if (test_kni_allocate_lcores() < 0) {
504 printf("No enough lcores for kni processing\n");
508 mp = test_kni_create_mempool();
510 printf("fail to create mempool for kni\n");
514 /* configuring port 0 for the test is enough */
516 ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf);
518 printf("fail to configure port %d\n", port_id);
522 ret = rte_eth_rx_queue_setup(port_id, 0, NB_RXD, SOCKET, &rx_conf, mp);
524 printf("fail to setup rx queue for port %d\n", port_id);
528 ret = rte_eth_tx_queue_setup(port_id, 0, NB_TXD, SOCKET, &tx_conf);
530 printf("fail to setup tx queue for port %d\n", port_id);
534 ret = rte_eth_dev_start(port_id);
536 printf("fail to start port %d\n", port_id);
539 rte_eth_promiscuous_enable(port_id);
541 /* basic test of kni processing */
542 fd = fopen(KNI_MODULE_PARAM_LO, "r");
544 printf("fopen: %s", strerror(errno));
547 memset(&buf, 0, sizeof(buf));
548 if (fgets(buf, sizeof(buf), fd)) {
549 if (!strncmp(buf, "lo_mode_fifo", strlen("lo_mode_fifo")) ||
550 !strncmp(buf, "lo_mode_fifo_skb",
551 strlen("lo_mode_fifo_skb"))) {
552 ret = test_kni_processing(port_id, mp);
558 printf("test_kni_processing skipped because of missing rte_kni module lo_mode argument\n");
562 /* test of allocating KNI with NULL mempool pointer */
563 memset(&info, 0, sizeof(info));
564 memset(&conf, 0, sizeof(conf));
565 memset(&ops, 0, sizeof(ops));
566 rte_eth_dev_info_get(port_id, &info);
567 conf.addr = info.pci_dev->addr;
568 conf.id = info.pci_dev->id;
569 conf.group_id = (uint16_t)port_id;
570 conf.mbuf_size = MAX_PACKET_SZ;
573 ops.port_id = port_id;
574 kni = rte_kni_alloc(NULL, &conf, &ops);
577 printf("unexpectedly creates kni successfully with NULL "
578 "mempool pointer\n");
582 /* test of allocating KNI without configurations */
583 kni = rte_kni_alloc(mp, NULL, NULL);
586 printf("Unexpectedly allocate KNI device successfully "
587 "without configurations\n");
591 /* test of allocating KNI without a name */
592 memset(&conf, 0, sizeof(conf));
593 memset(&info, 0, sizeof(info));
594 memset(&ops, 0, sizeof(ops));
595 rte_eth_dev_info_get(port_id, &info);
596 conf.addr = info.pci_dev->addr;
597 conf.id = info.pci_dev->id;
598 conf.group_id = (uint16_t)port_id;
599 conf.mbuf_size = MAX_PACKET_SZ;
602 ops.port_id = port_id;
603 kni = rte_kni_alloc(mp, &conf, &ops);
606 printf("Unexpectedly allocate a KNI device successfully "
611 /* test of releasing NULL kni context */
612 ret = rte_kni_release(NULL);
615 printf("unexpectedly release kni successfully\n");
619 /* test of handling request on NULL device pointer */
620 ret = rte_kni_handle_request(NULL);
623 printf("Unexpectedly handle request on NULL device pointer\n");
627 /* test of getting KNI device with pointer to NULL */
628 kni = rte_kni_get(NULL);
631 printf("Unexpectedly get a KNI device with "
632 "NULL name pointer\n");
636 /* test of getting KNI device with an zero length name string */
637 memset(&conf, 0, sizeof(conf));
638 kni = rte_kni_get(conf.name);
641 printf("Unexpectedly get a KNI device with "
642 "zero length name string\n");
646 /* test of getting KNI device with an invalid string name */
647 memset(&conf, 0, sizeof(conf));
648 snprintf(conf.name, sizeof(conf.name), "testing");
649 kni = rte_kni_get(conf.name);
652 printf("Unexpectedly get a KNI device with "
653 "a never used name string\n");
659 rte_eth_dev_stop(port_id);
664 REGISTER_TEST_COMMAND(kni_autotest, test_kni);