[dpdk-dev,v1] net/tap: add tun support
Checks
Commit Message
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 <vipin.varghese@intel.com>
---
doc/guides/nics/tap.rst | 15 ++++-
drivers/net/tap/rte_eth_tap.c | 132 +++++++++++++++++++++++++++++++++---------
2 files changed, 118 insertions(+), 29 deletions(-)
Comments
Personally, I'm mostly ok with this.
I added a couple of comments inline.
On 21/02/2018 00:12, Vipin Varghese wrote:
> 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 <vipin.varghese@intel.com>
> ---
> 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.
s/recieve/receive/
> +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;
I'm not a huge fan of considering "tap_type = 1 means it's a TAP device".
Wouldn't it be clearer to have a tuntap_type variable and an enum
TUNTAP_TYPE with the two types;
then checking for tuntap_type == TUN_TYPE or tuntap == TAP_TYPE?
It's not a deal breaker though, just a consideration.
> +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:<iface_idx> */
> - static int iface_idx;
> - char mac[ETHER_ADDR_LEN] = "\0dtap";
> + if (tap_type) {
> + if (fixed_mac_type) {
> + /* fixed mac = 00:64:74:61:70:<iface_idx> */
> + 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 "=<string> "
The rest looks fine.
Regards,
Pascal
Hi Pascal,
Thanks for the comments, Please find my updates inline
> -----Original Message-----
> From: Pascal Mazon [mailto:pascal.mazon@6wind.com]
> Sent: Thursday, February 22, 2018 12:22 PM
> To: Varghese, Vipin <vipin.varghese@intel.com>; dev@dpdk.org; Mcnamara,
> John <john.mcnamara@intel.com>; Yigit, Ferruh <ferruh.yigit@intel.com>
> Cc: Kovacevic, Marko <marko.kovacevic@intel.com>
> Subject: Re: [dpdk-dev,v1] net/tap: add tun support
>
> Personally, I'm mostly ok with this.
> I added a couple of comments inline.
>
<snipped>
> > +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.
> s/recieve/receive/
Thanks, making the changes for the next version
> > +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::
<snipped>
> >
> > static int tap_unit;
> > +static int tun_unit;
> > +
> > +static int tap_type;
> I'm not a huge fan of considering "tap_type = 1 means it's a TAP device".
> Wouldn't it be clearer to have a tuntap_type variable and an enum
> TUNTAP_TYPE with the two types; then checking for tuntap_type ==
> TUN_TYPE or tuntap == TAP_TYPE?
> It's not a deal breaker though, just a consideration.
Thanks, my first idea was use the same. Later argued myself in using 'tap_type' since the check for assigning MAC address goes well. Hence I hope not making the change 'tuntap_type' is ok?
> > +static char tuntap_name[8];
> >
> > static volatile uint32_t tap_trigger; /* Rx trigger */
> >
<snipped>
> > RTE_PMD_REGISTER_PARAM_STRING(net_tap,
> > ETH_TAP_IFACE_ARG "=<string> "
> The rest looks fine.
>
> Regards,
> Pascal
@@ -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
----------------
@@ -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:<iface_idx> */
- static int iface_idx;
- char mac[ETHER_ADDR_LEN] = "\0dtap";
+ if (tap_type) {
+ if (fixed_mac_type) {
+ /* fixed mac = 00:64:74:61:70:<iface_idx> */
+ 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 "=<string> "