On 4/5/2018 9:31 AM, Vipin Varghese wrote:
> Add TUN PMD validation for create, port setup, tx, rx and stats functions.
>
> Signed-off-by: Vipin Varghese <vipin.varghese@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,
> + },
> + ]
> + },
> + {
Hi Vipin,
Thanks for providing unit test for the feature you have added. *I believe we
need more unit test in DPDK.*
Only a few questions:
1- Should this be part of auto test?
2- Second running of the tun_autotest is failing, exit test and re-run works,
any idea?
Overall I am for merging this unit test if there is no objection.
Thanks,
ferruh
@@ -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
@@ -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":
@@ -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
new file mode 100644
@@ -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);