From: Marc Sune <marc.s...@bisdn.de>

Add a basic test for pktdev non-buffered API for pktdev types:

* ethdev
* ring
* kni

Signed-off-by: Marc Sune <marc.sune at bisdn.de>
Signed-off-by: Bruce Richardson <bruce.richardson at intel.com>
---
 app/test/Makefile      |   4 +
 app/test/test_pktdev.c | 440 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 444 insertions(+)
 create mode 100644 app/test/test_pktdev.c

diff --git a/app/test/Makefile b/app/test/Makefile
index 3c777bf..77e48c1 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -58,6 +58,10 @@ SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c

+ifeq ($(CONFIG_RTE_LIBRTE_PKTDEV),y)
+SRCS-y += test_pktdev.c
+endif
+
 ifeq ($(CONFIG_RTE_LIBRTE_TABLE),y)
 SRCS-y += test_table.c
 SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += test_table_pipeline.c
diff --git a/app/test/test_pktdev.c b/app/test/test_pktdev.c
new file mode 100644
index 0000000..e24fd78
--- /dev/null
+++ b/app/test/test_pktdev.c
@@ -0,0 +1,440 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <unistd.h>
+#include <rte_cycles.h>
+#include <rte_errno.h>
+#include <rte_ethdev.h>
+#include <rte_ether.h>
+#include <rte_kni.h>
+#include <rte_byteorder.h>
+#include <rte_atomic.h>
+#include <rte_malloc.h>
+#include <rte_pktdev.h>
+
+#include "packet_burst_generator.h"
+#include "test.h"
+
+/* General test constants */
+#define MAX_PKTDEVS 4
+#define NB_MBUF 8192
+#define SOCKET 0
+#define MAX_PACKET_SZ 2048
+#define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM)
+#define PKT_BURST_SZ 32
+#define MEMPOOL_CACHE_SZ PKT_BURST_SZ
+#define RING_SIZE 128
+
+#define RING_NAME "test-pktdev"
+#define KNI_NAME "kni-pktdev"
+#define MEMPOOL_NAME "pkdev-mempool"
+
+/* Shared mempool */
+struct rte_mempool* mp;
+
+/* We use port_id 0 */
+static uint8_t port_id = 0;
+
+/* Device specific contexts*/
+static struct rte_ring* r = NULL;
+#ifdef RTE_LIBRTE_KNI
+static struct rte_kni* kni = NULL;
+#endif
+
+/* pktdev handles */
+static struct rte_pktdev* ring_dev = NULL;
+#ifdef RTE_LIBRTE_KNI
+static struct rte_pktdev* kni_dev = NULL;
+#endif
+static struct rte_pktdev* eth_dev = NULL;
+
+static int
+setup_mempool(void)
+{
+       mp = rte_mempool_lookup(MEMPOOL_NAME);
+       if (!mp)
+               mp = rte_pktmbuf_pool_create(MEMPOOL_NAME,
+                               NB_MBUF,
+                               MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ,
+                               SOCKET);
+
+       if (!mp){
+               printf( "Could not create mempool!\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int
+setup_ring(void)
+{
+       r = rte_ring_lookup(RING_NAME);
+
+       if (r == NULL)
+               r = rte_ring_create(RING_NAME, RING_SIZE, SOCKET_ID_ANY, 0);
+
+       if (r == NULL) {
+               printf( "ERROR: unable to create rte_ring '" RING_NAME "' 
required for the pktdev device!\n");
+               return -1;
+       }
+
+       /* Check NULL ring */
+       if (rte_pktdev_from_ring(NULL) != NULL) {
+               printf( "ERROR: invalid behaviour of rte_pktdev_from_ring() for 
NULL rings!\n");
+               return -1;
+       }
+
+       /* Create the pktdev device */
+       ring_dev = rte_pktdev_from_ring(r);
+
+       if (ring_dev == NULL) {
+               printf( "ERROR: could not create pktdev from rte_ring '" 
RING_NAME "'!\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+#ifdef RTE_LIBRTE_KNI
+static int
+setup_kni(void)
+{
+       struct rte_kni_conf conf;
+       struct rte_kni_ops ops;
+
+       memset(&conf, 0, sizeof(conf));
+       memset(&ops, 0, sizeof(ops));
+       sprintf(conf.name,"%s", KNI_NAME);
+       conf.mbuf_size = MAX_PACKET_SZ;
+
+       /* Initialize KNI subsystem */
+       rte_kni_init(1);
+
+       /* Allocate KNI interface */
+       kni = rte_kni_get(KNI_NAME);
+
+       if (kni == NULL)
+               kni = rte_kni_alloc(mp, &conf, &ops);
+
+       if (kni == NULL) {
+               printf( "ERROR: could not allocate KNI interface '" KNI_NAME 
"'!\n");
+               return -1;
+       }
+
+       /* Check NULL CTX */
+       if (rte_pktdev_from_kni(NULL) != NULL) {
+               printf( "ERROR: invalid behaviour of rte_pktdev_from_kni() for 
NULL KNI context!\n");
+               return -1;
+       }
+
+       kni_dev = rte_pktdev_from_kni(kni);
+
+       if (kni_dev == NULL) {
+               printf( "ERROR: could not create pktdev from KNI interface '" 
KNI_NAME "'\n");
+               return -1;
+       }
+
+       return 0;
+}
+#endif /* RTE_LIBRTE_KNI */
+
+
+static struct rte_eth_conf port_conf = {
+       .rxmode = {
+               .mq_mode = ETH_MQ_RX_NONE,
+               .max_rx_pkt_len = MAX_PACKET_SZ,
+               .split_hdr_size = 0,
+               .header_split   = 0, /**< Header Split disabled */
+               .hw_ip_checksum = 0, /**< IP checksum offload enabled */
+               .hw_vlan_filter = 0, /**< VLAN filtering disabled */
+               .hw_vlan_strip  = 0, /**< VLAN strip enabled. */
+               .hw_vlan_extend = 0, /**< Extended VLAN disabled. */
+               .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
+               .hw_strip_crc   = 0, /**< CRC stripped by hardware */
+               .enable_scatter = 0, /**< scatter rx disabled */
+       },
+       .txmode = {
+               .mq_mode = ETH_MQ_TX_NONE,
+       },
+       .lpbk_mode = 1,  /* enable loopback */
+};
+
+static int
+setup_ethdev(void)
+{
+       uint16_t nb_rx_queue = 1, nb_tx_queue = 1;
+       int ret;
+
+       if (rte_eth_dev_count() == 0 ) {
+               printf( "ERROR: pktdev test requires at least one ethdev!\n");
+               return -1;
+       }
+
+       /* Check NULL CTX */
+       if (rte_pktdev_from_ethport(255, 0, 0) != NULL) {
+               printf( "ERROR: invalid behaviour of rte_pktdev_from_ethport() 
for invalid port id!\n");
+               return -1;
+       }
+
+       /* port configure */
+       ret = rte_eth_dev_configure(port_id, nb_rx_queue, nb_tx_queue,
+                                                               &port_conf);
+       if (ret < 0) {
+               printf( "ERROR: unable to configure port 0 '%s'.\n",
+                                                       rte_strerror(ret));
+               return -1;
+       }
+
+       /* tx queue setup */
+       ret = rte_eth_tx_queue_setup(port_id, 0, PKT_BURST_SZ, 0, NULL);
+       if (ret < 0) {
+               printf( "ERROR: unable to setup TX queue '%s'.\n",
+                                                       rte_strerror(ret));
+               return -1;
+       }
+
+       /* rx queue steup */
+       ret = rte_eth_rx_queue_setup(port_id, 0, PKT_BURST_SZ, 0, NULL, mp);
+       if (ret < 0) {
+               printf( "ERROR: unable to setup RX queue '%s'.\n",
+                                                       rte_strerror(ret));
+               return -1;
+       }
+
+       /* Start device */
+       ret = rte_eth_dev_start(port_id);
+       if (ret < 0) {
+               printf( "ERROR: unable to start eth_dev '%s'.\n",
+                                                       rte_strerror(ret));
+               return -1;
+       }
+
+       /* Enable promiscuous */
+       rte_eth_promiscuous_enable(port_id);
+
+       /* Create eth_dev */
+       eth_dev = rte_pktdev_from_ethport(0, 0, 0);
+       if (eth_dev == NULL) {
+               printf( "ERROR: could not create pktdev from ethdev'\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+static void
+stop_ethdev(void)
+{
+       rte_eth_dev_stop(port_id);
+}
+
+/* I/O loop stop flag */
+static bool keep_running = true;
+
+/* Intialize as an ARP pkt */
+static void
+init_pkt(struct rte_mbuf *mbuf)
+{
+       struct ether_hdr *eth;
+
+       /* Set length */
+       rte_pktmbuf_reset(mbuf);
+       rte_ctrlmbuf_len(mbuf) = ETHER_MIN_LEN;
+       eth = (struct ether_hdr*)rte_ctrlmbuf_data(mbuf);
+
+       /* Set mac addresses & ethtype */
+       memset(eth, 0, sizeof(*eth));
+       eth->d_addr.addr_bytes[0] = 0x2;
+       eth->d_addr.addr_bytes[0] = 0x1;
+       eth->ether_type = ETHER_TYPE_ARP;
+}
+
+/*
+ * Injects a pkt through the rte_ring pkt dev, and the packet
+ * has to travel back and forth through the chain (eth_dev in loopback)
+ */
+static int
+io_loop(void* not_used)
+{
+       (void)not_used;
+       unsigned int len;
+       struct rte_mbuf *burst[PKT_BURST_SZ];
+       struct rte_mbuf *mbuf = NULL;
+
+       /* Get an mbuf */
+       rte_mempool_get(mp, (void**)&mbuf);
+       if (mbuf == NULL) {
+               printf("Unable to allocate an mbuf\n");
+               return -1;
+       }
+
+       /* Prepare packet */
+       init_pkt(mbuf);
+
+       /* Test ring dev */
+       printf("Testing ring pktdev...\n");
+       burst[0] = mbuf;
+       len = rte_pkt_tx_burst(ring_dev, burst, 1);
+
+       if (len != 1) {
+               printf("TX through ring pktdev failed (len:%u)\n", len);
+               return -1;
+       }
+       if (ring_dev->tx_count != 1) {
+               printf("TX through ring pktdev stats check failed (len:%u)\n",  
                                                                        len);
+               return -1;
+       }
+
+       len = rte_pkt_rx_burst(ring_dev, burst, PKT_BURST_SZ);
+       if (len != 1) {
+               printf("RX through ring pktdev failed (len:%u), ring count: 
%u\n",
+                                                       len,
+                                                       rte_ring_count(r));
+               return -1;
+       }
+       if (ring_dev->rx_count != 1) {
+               printf("TX through ring pktdev stats check failed (len:%u)\n",  
                                                                        len);
+               return -1;
+       }
+
+
+
+#ifdef RTE_LIBRTE_KNI
+       /* Test KNI dev. TODO: check stats and RX */
+       printf("Testing KNI pktdev...\n");
+       rte_mempool_get(mp, (void**)&mbuf);
+       if (mbuf == NULL) {
+               printf("Unable to allocate an mbuf (len:%u)\n", len);
+               return -1;
+       }
+
+       init_pkt(mbuf);
+       burst[0] = mbuf;
+
+       len = rte_pkt_tx_burst(kni_dev, burst, 1);
+       if (len != 1) {
+               printf("TX through kni pktdev failed (len:%u)\n", len);
+               return -1;
+       }
+       if (kni_dev->tx_count != 1) {
+               printf("TX through KNI pktdev stats check failed (len:%u)\n",   
                                                                        len);
+               return -1;
+       }
+#endif /* RTE_LIBRTE_KNI */
+
+       /* Test eth dev. TODO: check RX */
+       printf("Testing ethdev pktdev...\n");
+       rte_mempool_get(mp, (void**)&mbuf);
+       if (mbuf == NULL) {
+               printf("Unable to allocate an mbuf (len:%u)\n", len);
+               return -1;
+       }
+
+       init_pkt(mbuf);
+       burst[0] = mbuf;
+
+       len = rte_pkt_tx_burst(eth_dev, burst, 1);
+       if (len != 1) {
+               printf("TX through eth pktdev failed\n");
+               return -1;
+       }
+       if (eth_dev->tx_count != 1) {
+               printf("TX through eth pktdev stats check failed (len:%u)\n",   
                                                                        len);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int
+test_pktdev(void)
+{
+       unsigned int lcore_id;
+
+       /* Get lcore id */
+       for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
+               if (lcore_id == rte_get_master_lcore())
+                       continue;
+               if ( rte_lcore_is_enabled(lcore_id) == 1)
+                       break;
+       }
+
+       if (lcore_id == RTE_MAX_LCORE) {
+               printf("No available lcores to run I/O loop. This test requires 
at least 2 lcores\n");
+               return -1;
+       }
+
+       printf("Initializing devices...\n");
+
+       if(setup_mempool() < 0)
+               return -1;
+       if(setup_ring() < 0)
+               return -1;
+#ifdef RTE_LIBRTE_KNI
+       if(setup_kni() < 0)
+               return -1;
+#endif /* RTE_LIBRTE_KNI */
+
+       if(setup_ethdev() < 0)
+               return -1;
+
+       printf("Launching I/O core and testing devs...\n");
+       rte_eal_remote_launch(io_loop, NULL, lcore_id);
+
+       /* Wait */
+       sleep(1);
+
+       /* Stop lcore */
+       keep_running = false;
+       rte_eal_wait_lcore(lcore_id);
+
+       printf("Cleaning the house...\n");
+
+       stop_ethdev();
+
+       return 0;
+}
+
+
+static struct test_command pktdev_cmd = {
+       .command = "pktdev_autotest",
+       .callback = test_pktdev,
+};
+
+REGISTER_TEST_COMMAND(pktdev_cmd);
-- 
2.4.2

Reply via email to