From patchwork Tue Feb 20 23:12:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Varghese, Vipin" X-Patchwork-Id: 35313 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 6CA0F1B1B4; Tue, 20 Feb 2018 18:31:13 +0100 (CET) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by dpdk.org (Postfix) with ESMTP id 816D01B1A5 for ; Tue, 20 Feb 2018 18:31:11 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Feb 2018 09:31:10 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.46,540,1511856000"; d="scan'208";a="205661315" Received: from unknown (HELO localhost.localdomain) ([10.224.122.203]) by fmsmga006.fm.intel.com with ESMTP; 20 Feb 2018 09:31:08 -0800 From: Vipin Varghese To: dev@dpdk.org, john.mcnamara@intel.com, ferruh.yigit@intel.com Cc: marko.kovacevic@intel.com, Vipin Varghese Date: Wed, 21 Feb 2018 04:42:44 +0530 Message-Id: <1519168364-23787-1-git-send-email-vipin.varghese@intel.com> X-Mailer: git-send-email 1.9.1 Subject: [dpdk-dev] [PATCH v1] net/tap: add tun support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The change adds TUN PMD logic to the existing TAP PMD. TUN PMD can be initialized with 'net_tunX' where 'X' represents unique id. PMD supports argument interface, while MAC address and remote are not supported. Signed-off-by: Vipin Varghese --- doc/guides/nics/tap.rst | 15 ++++- drivers/net/tap/rte_eth_tap.c | 132 +++++++++++++++++++++++++++++++++--------- 2 files changed, 118 insertions(+), 29 deletions(-) diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst index ea61be3..fe337c3 100644 --- a/doc/guides/nics/tap.rst +++ b/doc/guides/nics/tap.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: BSD-3-Clause Copyright(c) 2016 Intel Corporation. -Tap Poll Mode Driver -==================== +Tun|Tap Poll Mode Driver +======================== The ``rte_eth_tap.c`` PMD creates a device using TAP interfaces on the local host. The PMD allows for DPDK and the host to communicate using a raw @@ -77,6 +77,17 @@ can utilize that stack to handle the network protocols. Plus you would be able to address the interface using an IP address assigned to the internal interface. +The TUN PMD allows user to create a TUN device on host. The PMD allows user +to transmit and recieve packets via DPDK API calls with L3 header and payload. +The devices in host can be accessed via ``ifconfig`` or ``ip`` command. TUN +interfaces are passed to DPDK ``rte_eal_init`` arguments as ``--vdev=net_tunX``, +where X stands for unique id, example:: + + --vdev=net_tun0 --vdev=net_tun1,iface=foo1, ... + +Unlike TAP PMD, TUN PMD does not support user arguments as ``MAC`` or ``remote`` user +options. Default interface name is ``dtunX``, where X stands for unique id. + Flow API support ---------------- diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index f09db0e..42c9db4 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -42,6 +42,7 @@ /* Linux based path to the TUN device */ #define TUN_TAP_DEV_PATH "/dev/net/tun" #define DEFAULT_TAP_NAME "dtap" +#define DEFAULT_TUN_NAME "dtun" #define ETH_TAP_IFACE_ARG "iface" #define ETH_TAP_REMOTE_ARG "remote" @@ -49,6 +50,7 @@ #define ETH_TAP_MAC_FIXED "fixed" static struct rte_vdev_driver pmd_tap_drv; +static struct rte_vdev_driver pmd_tun_drv; static const char *valid_arguments[] = { ETH_TAP_IFACE_ARG, @@ -58,6 +60,10 @@ }; static int tap_unit; +static int tun_unit; + +static int tap_type; +static char tuntap_name[8]; static volatile uint32_t tap_trigger; /* Rx trigger */ @@ -104,24 +110,26 @@ enum ioctl_mode { * Do not set IFF_NO_PI as packet information header will be needed * to check if a received packet has been truncated. */ - ifr.ifr_flags = IFF_TAP; + ifr.ifr_flags = (tap_type) ? IFF_TAP : IFF_TUN; snprintf(ifr.ifr_name, IFNAMSIZ, "%s", pmd->name); RTE_LOG(DEBUG, PMD, "ifr_name '%s'\n", ifr.ifr_name); fd = open(TUN_TAP_DEV_PATH, O_RDWR); if (fd < 0) { - RTE_LOG(ERR, PMD, "Unable to create TAP interface\n"); + RTE_LOG(ERR, PMD, "Unable to create %s interface\n", + tuntap_name); goto error; } #ifdef IFF_MULTI_QUEUE /* Grab the TUN features to verify we can work multi-queue */ if (ioctl(fd, TUNGETFEATURES, &features) < 0) { - RTE_LOG(ERR, PMD, "TAP unable to get TUN/TAP features\n"); + RTE_LOG(ERR, PMD, "%s unable to get TUN/TAP features\n", + tuntap_name); goto error; } - RTE_LOG(DEBUG, PMD, " TAP Features %08x\n", features); + RTE_LOG(DEBUG, PMD, " %s Features %08x\n", tuntap_name, features); if (features & IFF_MULTI_QUEUE) { RTE_LOG(DEBUG, PMD, " Multi-queue support for %d queues\n", @@ -1108,7 +1116,7 @@ enum ioctl_mode { tmp = &(*tmp)->next; } - RTE_LOG(DEBUG, PMD, " RX TAP device name %s, qid %d on fd %d\n", + RTE_LOG(DEBUG, PMD, " RX TUNTAP device name %s, qid %d on fd %d\n", internals->name, rx_queue_id, internals->rxq[rx_queue_id].fd); return 0; @@ -1163,7 +1171,7 @@ enum ioctl_mode { if (ret == -1) return -1; RTE_LOG(DEBUG, PMD, - " TX TAP device name %s, qid %d on fd %d csum %s\n", + " TX TUNTAP device name %s, qid %d on fd %d csum %s\n", internals->name, tx_queue_id, internals->txq[tx_queue_id].fd, txq->csum ? "on" : "off"); @@ -1346,17 +1354,19 @@ enum ioctl_mode { struct ifreq ifr; int i; - RTE_LOG(DEBUG, PMD, " TAP device on numa %u\n", rte_socket_id()); + RTE_LOG(DEBUG, PMD, " %s device on numa %u\n", + tuntap_name, rte_socket_id()); data = rte_zmalloc_socket(tap_name, sizeof(*data), 0, numa_node); if (!data) { - RTE_LOG(ERR, PMD, "TAP Failed to allocate data\n"); + RTE_LOG(ERR, PMD, "%s Failed to allocate data\n", tuntap_name); goto error_exit_nodev; } dev = rte_eth_vdev_allocate(vdev, sizeof(*pmd)); if (!dev) { - RTE_LOG(ERR, PMD, "TAP Unable to allocate device struct\n"); + RTE_LOG(ERR, PMD, "%s Unable to allocate device struct\n", + tuntap_name); goto error_exit_nodev; } @@ -1367,8 +1377,8 @@ enum ioctl_mode { pmd->ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); if (pmd->ioctl_sock == -1) { RTE_LOG(ERR, PMD, - "TAP Unable to get a socket for management: %s\n", - strerror(errno)); + "%s Unable to get a socket for management: %s\n", + tuntap_name, strerror(errno)); goto error_exit; } @@ -1399,15 +1409,17 @@ enum ioctl_mode { pmd->txq[i].fd = -1; } - if (fixed_mac_type) { - /* fixed mac = 00:64:74:61:70: */ - static int iface_idx; - char mac[ETHER_ADDR_LEN] = "\0dtap"; + if (tap_type) { + if (fixed_mac_type) { + /* fixed mac = 00:64:74:61:70: */ + static int iface_idx; + char mac[ETHER_ADDR_LEN] = "\0dtap"; - mac[ETHER_ADDR_LEN - 1] = iface_idx++; - rte_memcpy(&pmd->eth_addr, mac, ETHER_ADDR_LEN); - } else { - eth_random_addr((uint8_t *)&pmd->eth_addr); + mac[ETHER_ADDR_LEN - 1] = iface_idx++; + rte_memcpy(&pmd->eth_addr, mac, ETHER_ADDR_LEN); + } else { + eth_random_addr((uint8_t *)&pmd->eth_addr); + } } /* Immediately create the netdevice (this will create the 1st queue). */ @@ -1422,11 +1434,13 @@ enum ioctl_mode { if (tap_ioctl(pmd, SIOCSIFMTU, &ifr, 1, LOCAL_AND_REMOTE) < 0) goto error_exit; - memset(&ifr, 0, sizeof(struct ifreq)); - ifr.ifr_hwaddr.sa_family = AF_LOCAL; - rte_memcpy(ifr.ifr_hwaddr.sa_data, &pmd->eth_addr, ETHER_ADDR_LEN); - if (tap_ioctl(pmd, SIOCSIFHWADDR, &ifr, 0, LOCAL_ONLY) < 0) - goto error_exit; + if (tap_type) { + memset(&ifr, 0, sizeof(struct ifreq)); + ifr.ifr_hwaddr.sa_family = AF_LOCAL; + rte_memcpy(ifr.ifr_hwaddr.sa_data, &pmd->eth_addr, ETHER_ADDR_LEN); + if (tap_ioctl(pmd, SIOCSIFHWADDR, &ifr, 0, LOCAL_ONLY) < 0) + goto error_exit; + } /* * Set up everything related to rte_flow: @@ -1533,8 +1547,8 @@ enum ioctl_mode { rte_eth_dev_release_port(dev); error_exit_nodev: - RTE_LOG(ERR, PMD, "TAP Unable to initialize %s\n", - rte_vdev_device_name(vdev)); + RTE_LOG(ERR, PMD, "%s Unable to initialize %s\n", + tuntap_name, rte_vdev_device_name(vdev)); rte_free(data); return -EINVAL; @@ -1580,6 +1594,61 @@ enum ioctl_mode { return 0; } +/* Open a TUN interface device. + */ +static int +rte_pmd_tun_probe(struct rte_vdev_device *dev) +{ + const char *name, *params; + int ret; + struct rte_kvargs *kvlist = NULL; + char tun_name[RTE_ETH_NAME_MAX_LEN]; + char remote_iface[RTE_ETH_NAME_MAX_LEN]; + + tap_type = 0; + strcpy(tuntap_name, "TUN"); + + name = rte_vdev_device_name(dev); + params = rte_vdev_device_args(dev); + + memset(remote_iface, 0, RTE_ETH_NAME_MAX_LEN); + snprintf(tun_name, sizeof(tun_name), "%s%d", + DEFAULT_TUN_NAME, tun_unit++); + + if (params && (params[0] != '\0')) { + RTE_LOG(DEBUG, PMD, "parameters (%s)\n", params); + + kvlist = rte_kvargs_parse(params, valid_arguments); + if (kvlist) { + if (rte_kvargs_count(kvlist, ETH_TAP_IFACE_ARG) == 1) { + ret = rte_kvargs_process(kvlist, + ETH_TAP_IFACE_ARG, + &set_interface_name, + tun_name); + + if (ret == -1) + goto leave; + } + } + } + pmd_link.link_speed = ETH_SPEED_NUM_10G; + + RTE_LOG(NOTICE, PMD, "Initializing pmd_tun for %s as %s\n", + name, tun_name); + + ret = eth_dev_tap_create(dev, tun_name, remote_iface, 0); + +leave: + if (ret == -1) { + RTE_LOG(ERR, PMD, "Failed to create pmd for %s as %s\n", + name, tun_name); + tun_unit--; /* Restore the unit number */ + } + rte_kvargs_free(kvlist); + + return ret; +} + /* Open a TAP interface device. */ static int @@ -1593,6 +1662,9 @@ enum ioctl_mode { char remote_iface[RTE_ETH_NAME_MAX_LEN]; int fixed_mac_type = 0; + tap_type = 1; + strcpy(tuntap_name, "TAP"); + name = rte_vdev_device_name(dev); params = rte_vdev_device_args(dev); @@ -1652,7 +1724,7 @@ enum ioctl_mode { return ret; } -/* detach a TAP device. +/* detach a TUNTAP device. */ static int rte_pmd_tap_remove(struct rte_vdev_device *dev) @@ -1695,11 +1767,17 @@ enum ioctl_mode { return 0; } +static struct rte_vdev_driver pmd_tun_drv = { + .probe = rte_pmd_tun_probe, + .remove = rte_pmd_tap_remove, +}; + static struct rte_vdev_driver pmd_tap_drv = { .probe = rte_pmd_tap_probe, .remove = rte_pmd_tap_remove, }; RTE_PMD_REGISTER_VDEV(net_tap, pmd_tap_drv); +RTE_PMD_REGISTER_VDEV(net_tun, pmd_tun_drv); RTE_PMD_REGISTER_ALIAS(net_tap, eth_tap); RTE_PMD_REGISTER_PARAM_STRING(net_tap, ETH_TAP_IFACE_ARG "= "