Add TUN PMD validation for create, port setup, tx, rx and stats functions.

Signed-off-by: Vipin Varghese <vipin.vargh...@intel.com>
---
 test/test/Makefile         |   4 +
 test/test/autotest_data.py |  13 ++
 test/test/meson.build      |   4 +
 test/test/test_tun.c       | 333 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 354 insertions(+)
 create mode 100644 test/test/test_tun.c

diff --git a/test/test/Makefile b/test/test/Makefile
index a88cc38..e5d8200 100644
--- a/test/test/Makefile
+++ b/test/test/Makefile
@@ -193,6 +193,10 @@ endif
 
 SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) += test_kvargs.c
 
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_TAP),y)
+SRCS-y += test_tun.c
+endif
+
 CFLAGS += -DALLOW_EXPERIMENTAL_API
 
 CFLAGS += -O3
diff --git a/test/test/autotest_data.py b/test/test/autotest_data.py
index aacfe0a..35f3aab 100644
--- a/test/test/autotest_data.py
+++ b/test/test/autotest_data.py
@@ -357,6 +357,19 @@ def per_sockets(num):
         ]
     },
     {
+        "Prefix":    "tun",
+        "Memory":    "512",
+        "Tests":
+        [
+            {
+                "Name":    "TUN autotest",
+                "Command": "tun_autotest",
+                "Func":    default_autotest,
+                "Report":  None,
+            },
+        ]
+    },
+    {
         "Prefix":    "mempool_perf",
         "Memory":    per_sockets(256),
         "Tests":
diff --git a/test/test/meson.build b/test/test/meson.build
index eb3d87a..fbb4cf7 100644
--- a/test/test/meson.build
+++ b/test/test/meson.build
@@ -93,6 +93,7 @@ test_sources = files('commands.c',
        'test_timer.c',
        'test_timer_perf.c',
        'test_timer_racecond.c',
+       'test_tun.c',
        'test_version.c',
        'virtual_pmd.c'
 )
@@ -227,6 +228,9 @@ endif
 if dpdk_conf.has('RTE_LIBRTE_RING_PMD')
        test_deps += 'pmd_ring'
 endif
+if dpdk_conf.has('RTE_LIBRTE_TAP_PMD')
+       test_deps += 'pmd_tap'
+endif
 if dpdk_conf.has('RTE_LIBRTE_POWER')
        test_deps += 'power'
 endif
diff --git a/test/test/test_tun.c b/test/test/test_tun.c
new file mode 100644
index 0000000..c165a94
--- /dev/null
+++ b/test/test/test_tun.c
@@ -0,0 +1,333 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <net/if.h>
+
+#include "test.h"
+
+#include <rte_string_fns.h>
+#include <rte_mempool.h>
+#include <rte_ethdev.h>
+#include <rte_bus_pci.h>
+#include <rte_cycles.h>
+#include <rte_bus_vdev.h>
+#include <rte_ip.h>
+#include <rte_icmp.h>
+#include <rte_alarm.h>
+
+#define NB_MBUF          8192
+#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 SOCKET           0
+#define NB_RXD           1024
+#define NB_TXD           1024
+#define MAX_PKT_BURST    32
+#define IFCONFIG         "/sbin/ifconfig "
+#define PING             "/bin/ping -qr -c 10 -i 0.2 15.0.0.1 -I "
+
+static int tun_id;
+static int socket_id;
+static uint16_t nb_ports, port_id;
+
+static struct rte_eth_dev_info info;
+static struct rte_eth_stats stats;
+static struct rte_mempool *mp;
+static struct rte_mbuf *mbuf;
+
+static char tun_drv_name[20] = "net_tun";
+static char tun_intf_name[20] = "atest";
+static char tun_intf_cmd[20] = "\0";
+static char portname[25] = "\0";
+static char cmd_exec[70] = "\0";
+
+static const struct rte_eth_rxconf rx_conf = {
+       .rx_thresh = {
+               .pthresh = 8,
+               .hthresh = 8,
+               .wthresh = 4,
+       },
+       .rx_free_thresh = 0,
+};
+
+static const struct rte_eth_txconf tx_conf = {
+       .tx_thresh = {
+               .pthresh = 36,
+               .hthresh = 0,
+               .wthresh = 0,
+       },
+       .tx_free_thresh = 0,
+       .tx_rs_thresh = 0,
+};
+
+static const struct rte_eth_conf port_conf = {
+       .rxmode = {
+               .header_split = 0,
+               .hw_ip_checksum = 0,
+               .hw_vlan_filter = 0,
+               .jumbo_frame = 0,
+               .hw_strip_crc = 0,
+       },
+       .txmode = {
+               .mq_mode = ETH_MQ_TX_NONE | ETH_DCB_NONE,
+       },
+};
+
+static void
+send_ping(void *param)
+{
+       char *tun_intf_name = (char *) param;
+
+       sprintf(cmd_exec, "%s %s &", PING, tun_intf_name);
+       if (system(cmd_exec) != 0)
+               printf("fail to execute (%s)!\n", cmd_exec);
+
+       fflush(stdout);
+}
+
+static int
+tun_port_setup(uint16_t port_id)
+{
+       int ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf);
+       if (ret < 0) {
+               printf("fail to configure port %d\n", port_id);
+               return -1;
+       }
+
+       ret = rte_eth_rx_queue_setup(port_id, 0, NB_RXD, socket_id,
+                       &rx_conf, mp);
+       if (ret < 0) {
+               printf("fail to setup rx queue for port %d\n", port_id);
+               return -1;
+       }
+
+       ret = rte_eth_tx_queue_setup(port_id, 0, NB_TXD, socket_id,
+                       &tx_conf);
+       if (ret < 0) {
+               printf("fail to setup tx queue for port %d\n", port_id);
+               return -1;
+       }
+
+       ret = rte_eth_dev_start(port_id);
+       if (ret < 0) {
+               printf("fail to start port %d\n", port_id);
+               return -2;
+       }
+
+       rte_eth_promiscuous_enable(port_id);
+       return 0;
+}
+
+static int
+setup_interface(char *tun_intf_name)
+{
+       sprintf(cmd_exec, "%s %s 15.0.0.254/24 up", IFCONFIG, tun_intf_name);
+       int ret = system(cmd_exec);
+       if (ret != 0) {
+               printf("fail to execute (%s)!\n", cmd_exec);
+               return -1;
+       }
+
+       printf("Stats after interface config\n");
+       sprintf(cmd_exec, "%s %s | grep packets", IFCONFIG, tun_intf_name);
+       ret = system(cmd_exec);
+       if (ret != 0) {
+               printf("fail to execute (%s)!\n", cmd_exec);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int
+test_tun(void)
+{
+       int ret = -1, i;
+       int8_t count = 10, recv_pkts = 10;
+       uint64_t rx_pkts, tx_pkts, rx_err, tx_err;
+       socket_id = rte_lcore_to_socket_id(rte_lcore_id());
+
+       mp = rte_mempool_lookup("tun_mempool");
+       if (!mp)
+               mp = rte_pktmbuf_pool_create("tun_mempool",
+                               NB_MBUF,
+                               MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ,
+                               socket_id);
+
+       nb_ports = rte_eth_dev_count();
+       printf("Found (%d) ports\n", nb_ports);
+
+       sprintf(tun_drv_name, "%s%d", tun_drv_name, tun_id);
+       sprintf(tun_intf_name, "%s%d", tun_intf_name, tun_id++);
+       sprintf(tun_intf_cmd, "iface=%s", tun_intf_name);
+
+       if (rte_vdev_init(tun_drv_name, tun_intf_cmd) != 0) {
+               printf("failed to add tun device!\n");
+               goto fail;
+       }
+
+       nb_ports = rte_eth_dev_count();
+       printf("Found port (%d) with PMD TUN\n", nb_ports);
+
+       for (i = 0; i < nb_ports; i++) {
+               memset(&info, 0, sizeof(info));
+               rte_eth_dev_info_get(i, &info);
+
+               if_indextoname(info.if_index, portname);
+
+               ret = rte_eth_dev_get_name_by_port(i, portname);
+               if (ret != 0) {
+                       printf("Fail to get port name for (%d)", i);
+                       goto fail;
+               }
+
+               printf("port (%d) driver (%s) interface name (%s)\n",
+                               i, info.driver_name, portname);
+       }
+       port_id = i - 1;
+
+       /* configuring new port for the test is enough */
+       ret = tun_port_setup(port_id);
+       if (ret != 0)
+               goto fail;
+
+       ret = rte_eth_stats_get(port_id, &stats);
+       if (ret != 0)
+               goto port_fail;
+
+       rx_pkts = stats.ipackets;
+       tx_pkts = stats.opackets;
+       rx_err = stats.ierrors;
+       tx_err = stats.oerrors;
+
+       ret = setup_interface(tun_intf_name);
+       if (ret != 0)
+               goto port_fail;
+
+       printf("send 1 packet through tun interface\n");
+       mbuf = rte_pktmbuf_alloc(mp);
+       if (mbuf == NULL) {
+               printf("fail to allocate mbuf!\n");
+               goto port_fail;
+       }
+
+       mbuf->nb_segs = 1;
+       mbuf->next = NULL;
+       mbuf->pkt_len = 64;
+       mbuf->data_len = 64;
+
+       struct ipv4_hdr *v4 = rte_pktmbuf_mtod(mbuf, struct ipv4_hdr *);
+       v4->src_addr = 0x0a0a0a0a;
+       v4->dst_addr = 0x0b0b0b0b;
+       v4->time_to_live = 0x2;
+       v4->fragment_offset = 0x00;
+       v4->version_ihl = 0x45;
+
+       /* sent one pkt out */
+       ret = rte_eth_tx_burst(port_id, 0, &mbuf, 1);
+       if (ret != 1) {
+               printf("fail to send nbuf via tun port!\n");
+               goto port_fail;
+       }
+
+       ret = rte_eth_stats_get(port_id, &stats);
+       if (ret != 0)
+               goto port_fail;
+
+       if (((stats.opackets - tx_pkts) != 1) ||
+                       (stats.ipackets - rx_pkts) ||
+                       (stats.ierrors - rx_err) ||
+                       (stats.oerrors - tx_err)) {
+               printf("Fail to match the expected stats\n");
+               goto port_fail;
+}
+
+       rx_pkts = stats.ipackets;
+       tx_pkts = stats.opackets;
+       rx_err = stats.ierrors;
+       tx_err = stats.oerrors;
+
+       rte_eal_alarm_set(1, send_ping, (void *) tun_intf_name);
+       rte_delay_ms(1000);
+
+       printf("Stats after 1 pkt TX");
+       sprintf(cmd_exec, "%s %s | grep packets", IFCONFIG, tun_intf_name);
+       ret = system(cmd_exec);
+       if (ret != 0) {
+               printf("fail to execute (%s)!\n", cmd_exec);
+               goto port_fail;
+       }
+
+       while ((count > 0) && (recv_pkts > 0)) {
+               struct rte_mbuf *rx_pkts_burst[MAX_PKT_BURST];
+               uint16_t nb_pkts = rte_eth_rx_burst(port_id, 0, rx_pkts_burst,
+                               10);
+
+               if (!nb_pkts) {
+                       rte_delay_ms(500);
+                       count = count - 1;
+               }
+
+               recv_pkts -= nb_pkts;
+
+               for (i = 0; i < nb_pkts; i++) {
+                       struct ipv4_hdr *v4 = rte_pktmbuf_mtod(rx_pkts_burst[i],
+                       struct ipv4_hdr *);
+                       v4->src_addr = v4->src_addr ^ v4->dst_addr;
+                       v4->dst_addr = v4->src_addr ^ v4->dst_addr;
+                       v4->src_addr = v4->src_addr ^ v4->dst_addr;
+
+                       struct icmp_hdr *icmp = (struct icmp_hdr *)(v4 + 1);
+                       icmp->icmp_type = 0x00;
+
+                       /* sent one pkt out */
+                       ret = rte_eth_tx_burst(port_id, 0, &mbuf, 1);
+                       if (ret != 1) {
+                               printf("fail to send nbuf via tun port!\n");
+                               goto port_fail;
+                       }
+               }
+
+               count = count - 1;
+       }
+
+       printf("Stats after ping replies\n");
+       sprintf(cmd_exec, "%s %s | grep packets", IFCONFIG, tun_intf_name);
+       ret = system(cmd_exec);
+       if (ret != 0) {
+               printf("fail to execute (%s)!\n", cmd_exec);
+               goto port_fail;
+       }
+
+       ret = rte_eth_stats_get(port_id, &stats);
+       if (ret != 0)
+               goto port_fail;
+
+       if (((stats.opackets - tx_pkts) != 10) ||
+                       ((stats.ipackets - rx_pkts) != 10) ||
+                       (stats.ierrors - rx_err) ||
+                       (stats.oerrors - tx_err)) {
+               printf("Fail to match the expected stats\n");
+               goto port_fail;
+}
+
+port_fail:
+       rte_eth_dev_stop(port_id);
+
+fail:
+       rte_vdev_uninit(tun_drv_name);
+
+       fflush(stdout);
+
+       rte_delay_ms(2000);
+       return ret;
+}
+
+REGISTER_TEST_COMMAND(tun_autotest, test_tun);
-- 
1.9.1

Reply via email to