[dpdk-dev] [PATCH v4] drivers/net:new PMD using tun/tap host interface

2016-10-12 Thread Michał Mirosław
2016-10-11 22:56 GMT+02:00 Wiles, Keith :
>> On Oct 11, 2016, at 6:30 AM, Micha? Miros?aw  wrote:
>>
>> 2016-10-04 16:45 GMT+02:00, Keith Wiles :
>>> The rte_eth_tap.c PMD creates a device using TUN/TAP interfaces
>>> on the local host. The PMD allows for DPDK and the host to
>>> communicate using a raw device interface on the host and in
>>> the DPDK application. The device created is a Tap device with
>>> a L2 packet header.
>> [...]
>>> +static uint16_t
>>> +pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
>>> +{
>>> +int len, n;
>>> +struct rte_mbuf *mbuf;
>>> +struct rx_queue *rxq = queue;
>>> +struct pollfd pfd;
>>> +uint16_t num_rx;
>>> +unsigned long num_rx_bytes = 0;
>>> +
>>> +pfd.events = POLLIN;
>>> +pfd.fd = rxq->fd;
>>> +for (num_rx = 0; num_rx < nb_pkts; ) {
>>> +n = poll(, 1, 0);
>>> +
>>> +if (n <= 0)
>>> +break;
>>> +
>>
>> Considering that syscalls are rather expensive, it would be cheaper to
>> allocate an mbuf here and free it when read() returns -1 instead of
>> calling poll() to check whether a packet is waiting. This way you
>> save a syscall per packet and replace one syscall with one mbuf free
>> per poll.
>
> I made this change, but saw no performance difference in the two methods. 
> Removing poll seems reasonable as it is simpler. TAP is already so slow is 
> why the performance did not change is my guess. Anyone wanting to use TAP as 
> a high performance interface is going to be surprised. I believe the best use 
> case for the TAP interface is for control or exception path.

Agreed, TAP does not look like designed for performance as a first goal.

You could do the same simplification for TX path, BTW.

Best Regards,
Micha? Miros?aw


[dpdk-dev] [PATCH v4] drivers/net:new PMD using tun/tap host interface

2016-10-11 Thread Wiles, Keith

Regards,
Keith

> On Oct 11, 2016, at 6:49 AM, Yigit, Ferruh  wrote:
> 
> On 10/4/2016 3:45 PM, Keith Wiles wrote:
>> The rte_eth_tap.c PMD creates a device using TUN/TAP interfaces
>> on the local host. The PMD allows for DPDK and the host to
>> communicate using a raw device interface on the host and in
>> the DPDK application. The device created is a Tap device with
>> a L2 packet header.
>> 

Will try to ship out a v5 soon.
>> v4 - merge with latest driver changes
>> v3 - fix includes by removing ifdef for other type besides Linux.
>> Fix the copyright notice in the Makefile
>> v2 - merge all of the patches into one patch.
>> Fix a typo on naming the tap device.
>> Update the maintainers list
>> 
>> Signed-off-by: Keith Wiles 
>> ---
>> MAINTAINERS |   5 +
>> config/common_linuxapp  |   2 +
>> doc/guides/nics/tap.rst |  84 
>> drivers/net/Makefile|   1 +
>> drivers/net/tap/Makefile|  57 +++
>> drivers/net/tap/rte_eth_tap.c   | 866 
>> 
>> drivers/net/tap/rte_pmd_tap_version.map |   4 +
>> mk/rte.app.mk   |   1 +
>> 8 files changed, 1020 insertions(+)
>> create mode 100644 doc/guides/nics/tap.rst
>> create mode 100644 drivers/net/tap/Makefile
>> create mode 100644 drivers/net/tap/rte_eth_tap.c
>> create mode 100644 drivers/net/tap/rte_pmd_tap_version.map
>> 
> <>
>> diff --git a/config/common_linuxapp b/config/common_linuxapp
>> index 2483dfa..59a2053 100644
>> --- a/config/common_linuxapp
>> +++ b/config/common_linuxapp
>> @@ -44,3 +44,5 @@ CONFIG_RTE_LIBRTE_PMD_VHOST=y
>> CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
>> CONFIG_RTE_LIBRTE_POWER=y
>> CONFIG_RTE_VIRTIO_USER=y
>> +CONFIG_RTE_LIBRTE_PMD_TAP=y
> 
> According existing config items, a default value of a config option
> should go to config/common_base, and environment specific config file
> overwrites it if required.
> So this option needs to be added into config/common_base too as disabled
> by default.

Add the define to common_base as no, plus a comment for Linux only.

> 
>> +CONFIG_RTE_PMD_TAP_MAX_QUEUES=32

Moved this to the .c file as a define.
> 
> Is the number of max queues really needs to be a config option, I assume
> in normal use case user won't need to update this and will use single
> queue, if that is true what about pushing this into source code to not
> make config file more complex?
> 
>> diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst
> 
> <...>
> 
>> +.. code-block:: console
>> +
>> +   The interfaced name can be changed by adding the iface=foo0
>> +   e.g. --vedv=eth_tap,iface=foo0 --vdev=eth_tap,iface=foo1, ...
> 
> s/vedv/vdev
> eth_tap needs to be net_tap as part of unifying device names work

Fixed.
> 
> <...>
> 
>> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
>> index bc93230..b4afa98 100644
>> --- a/drivers/net/Makefile
>> +++ b/drivers/net/Makefile
>> @@ -55,6 +55,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += thunderx
>> DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio
>> DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3
>> DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += xenvirt
>> +DIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += tap
> 
> Rest of the PMDs sorted alphabetically, please do same.

Done.
> 
>> 
>> ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y)
>> DIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += vhost
> 
> <...>
> 
>> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
> 
> <...>
> 
>> +
>> +static const char *drivername = "Tap PMD";
>> +static int tap_unit = 0;
> 
> No need to initialize to zero.

Fixed
> 
> <...>
> 
>> +
>> +struct pmd_internals {
>> +char name[RTE_ETH_NAME_MAX_LEN];/* Internal Tap device name */
>> +uint16_t nb_queues; /* Number of queues supported */
>> +uint16_t pad0;
> 
> Why this padding? Is it reserved?

Removed pad0. I just like to know about gaps in the structures is the reason.
> 
>> +struct ether_addr eth_addr; /* Mac address of the device port */
>> +
>> +int if_index;   /* IF_INDEX for the port */
>> +int fds[RTE_PMD_TAP_MAX_QUEUES]; /* List of all file descriptors */
>> +
>> +struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES];/* List of RX queues */
>> +struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES];/* List of TX queues */
>> +};
>> +
>> +/*
>> + * Tun/Tap allocation routine
>> + *
>> + * name is the number of the interface to use, unless NULL to take the host
>> + * supplied name.
>> + */
>> +static int
>> +tun_alloc(char * name)
> 
> char *name

Fixed.
> 
> <...>
> 
>> +
>> +/* Always set the fiile descriptor to non-blocking */
> 
> s/fiile/file
> 
>> +if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
>> +RTE_LOG(ERR, PMD, "Unable to set to nonblocking\n");
>> +perror("F_SETFL, NONBLOCK");
>> +goto error;
>> +}
>> +
>> +/* If the name is different that new name as default 

[dpdk-dev] [PATCH v4] drivers/net:new PMD using tun/tap host interface

2016-10-11 Thread Wiles, Keith

Regards,
Keith

> On Oct 11, 2016, at 7:28 AM, Yigit, Ferruh  wrote:
> 
> On 10/4/2016 3:45 PM, Keith Wiles wrote:
>> +/*
>> + * Open a TAP interface device.
>> + */
>> +static int
>> +rte_pmd_tap_devinit(const char *name, const char *params)
>> +{
>> +int ret = 0;
>> +struct rte_kvargs *kvlist;
>> +struct tap_info tap_info;
>> +
>> +/* Setup default values */
>> +memset(_info, 0, sizeof(tap_info));
>> +
>> +tap_info.speed = ETH_SPEED_NUM_10G;
>> +snprintf(tap_info.name, sizeof(tap_info.name), "dtap%d", tap_unit++);
>> +
>> +if ((params == NULL) || (params[0] == '\0')) {
>> +RTE_LOG(INFO, PMD, "Initializing pmd_tap for %s\n", name);
>> +
>> +ret = eth_dev_tap_create(name, _info);
>> +goto leave;
>> +}
>> +
>> +RTE_LOG(INFO, PMD, "Initialize %s with params (%s)\n", name, params);
>> +
>> +kvlist = rte_kvargs_parse(params, valid_arguments);
>> +if (!kvlist) {
>> +ret = eth_dev_tap_create(name, _info);
>> +goto leave;
>> +}
>> +
>> +if (rte_kvargs_count(kvlist, ETH_TAP_SPEED_ARG) == 1) {
>> +ret = rte_kvargs_process(kvlist, ETH_TAP_SPEED_ARG,
>> + _interface_speed, _info);
>> +if (ret < 0)
>> +goto leave;
>> +} else
>> +set_interface_speed(NULL, NULL, _info);
>> +
>> +if (rte_kvargs_count(kvlist, ETH_TAP_IFACE_ARG) == 1) {
>> +ret = rte_kvargs_process(kvlist, ETH_TAP_IFACE_ARG,
>> + _interface_name, _info);
>> +if (ret < 0)
>> +goto leave;
>> +} else
>> +set_interface_name(NULL, NULL, (void *)_info);
> 
> Also there must be a eth_dev_tap_create() call after this point to use
> tap_info struct with custom values, right?
> "--vdev eth_tap0,iface=foo0" parameter shouldn't be working with this
> code, right?

Removed the extra code.

> 
>> +
>> +rte_kvargs_free(kvlist);
>> +
>> +leave:
>> +if (ret == -1)
>> +RTE_LOG(INFO, PMD, "Failed to create pmd_tap for %s\n", name);
>> +
>> +return ret;
>> +}
> 



[dpdk-dev] [PATCH v4] drivers/net:new PMD using tun/tap host interface

2016-10-11 Thread Wiles, Keith

Regards,
Keith

> On Oct 11, 2016, at 6:30 AM, Micha? Miros?aw  wrote:
> 
> 2016-10-04 16:45 GMT+02:00, Keith Wiles :
>> The rte_eth_tap.c PMD creates a device using TUN/TAP interfaces
>> on the local host. The PMD allows for DPDK and the host to
>> communicate using a raw device interface on the host and in
>> the DPDK application. The device created is a Tap device with
>> a L2 packet header.
> [...]
>> +static uint16_t
>> +pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
>> +{
>> +int len, n;
>> +struct rte_mbuf *mbuf;
>> +struct rx_queue *rxq = queue;
>> +struct pollfd pfd;
>> +uint16_t num_rx;
>> +unsigned long num_rx_bytes = 0;
>> +
>> +pfd.events = POLLIN;
>> +pfd.fd = rxq->fd;
>> +for (num_rx = 0; num_rx < nb_pkts; ) {
>> +n = poll(, 1, 0);
>> +
>> +if (n <= 0)
>> +break;
>> +
> 
> Considering that syscalls are rather expensive, it would be cheaper to
> allocate an mbuf here and free it when read() returns -1 instead of
> calling poll() to check whether a packet is waiting. This way you
> save a syscall per packet and replace one syscall with one mbuf free
> per poll.

I made this change, but saw no performance difference in the two methods. 
Removing poll seems reasonable as it is simpler. TAP is already so slow is why 
the performance did not change is my guess. Anyone wanting to use TAP as a high 
performance interface is going to be surprised. I believe the best use case for 
the TAP interface is for control or exception path.

> 
> Best Regards,
> Micha? Miros?aw



[dpdk-dev] [PATCH v4] drivers/net:new PMD using tun/tap host interface

2016-10-11 Thread Michał Mirosław
2016-10-04 16:45 GMT+02:00, Keith Wiles :
> The rte_eth_tap.c PMD creates a device using TUN/TAP interfaces
> on the local host. The PMD allows for DPDK and the host to
> communicate using a raw device interface on the host and in
> the DPDK application. The device created is a Tap device with
> a L2 packet header.
[...]
> +static uint16_t
> +pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
> +{
> + int len, n;
> + struct rte_mbuf *mbuf;
> + struct rx_queue *rxq = queue;
> + struct pollfd pfd;
> + uint16_t num_rx;
> + unsigned long num_rx_bytes = 0;
> +
> + pfd.events = POLLIN;
> + pfd.fd = rxq->fd;
> + for (num_rx = 0; num_rx < nb_pkts; ) {
> + n = poll(, 1, 0);
> +
> + if (n <= 0)
> + break;
> +

Considering that syscalls are rather expensive, it would be cheaper to
allocate an mbuf here and free it when read() returns -1 instead of
calling poll() to check whether a packet is waiting. This way you
save a syscall per packet and replace one syscall with one mbuf free
per poll.

Best Regards,
Micha??Miros?aw


[dpdk-dev] [PATCH v4] drivers/net:new PMD using tun/tap host interface

2016-10-11 Thread Ferruh Yigit
On 10/4/2016 3:45 PM, Keith Wiles wrote:
> +/*
> + * Open a TAP interface device.
> + */
> +static int
> +rte_pmd_tap_devinit(const char *name, const char *params)
> +{
> + int ret = 0;
> + struct rte_kvargs *kvlist;
> + struct tap_info tap_info;
> +
> + /* Setup default values */
> + memset(_info, 0, sizeof(tap_info));
> +
> + tap_info.speed = ETH_SPEED_NUM_10G;
> + snprintf(tap_info.name, sizeof(tap_info.name), "dtap%d", tap_unit++);
> +
> + if ((params == NULL) || (params[0] == '\0')) {
> + RTE_LOG(INFO, PMD, "Initializing pmd_tap for %s\n", name);
> +
> + ret = eth_dev_tap_create(name, _info);
> + goto leave;
> + }
> +
> + RTE_LOG(INFO, PMD, "Initialize %s with params (%s)\n", name, params);
> +
> + kvlist = rte_kvargs_parse(params, valid_arguments);
> + if (!kvlist) {
> + ret = eth_dev_tap_create(name, _info);
> + goto leave;
> + }
> +
> + if (rte_kvargs_count(kvlist, ETH_TAP_SPEED_ARG) == 1) {
> + ret = rte_kvargs_process(kvlist, ETH_TAP_SPEED_ARG,
> +  _interface_speed, _info);
> + if (ret < 0)
> + goto leave;
> + } else
> + set_interface_speed(NULL, NULL, _info);
> +
> + if (rte_kvargs_count(kvlist, ETH_TAP_IFACE_ARG) == 1) {
> + ret = rte_kvargs_process(kvlist, ETH_TAP_IFACE_ARG,
> +  _interface_name, _info);
> + if (ret < 0)
> + goto leave;
> + } else
> + set_interface_name(NULL, NULL, (void *)_info);

Also there must be a eth_dev_tap_create() call after this point to use
tap_info struct with custom values, right?
"--vdev eth_tap0,iface=foo0" parameter shouldn't be working with this
code, right?

> +
> + rte_kvargs_free(kvlist);
> +
> +leave:
> + if (ret == -1)
> + RTE_LOG(INFO, PMD, "Failed to create pmd_tap for %s\n", name);
> +
> + return ret;
> +}



[dpdk-dev] [PATCH v4] drivers/net:new PMD using tun/tap host interface

2016-10-11 Thread Ferruh Yigit
On 10/4/2016 3:45 PM, Keith Wiles wrote:
> The rte_eth_tap.c PMD creates a device using TUN/TAP interfaces
> on the local host. The PMD allows for DPDK and the host to
> communicate using a raw device interface on the host and in
> the DPDK application. The device created is a Tap device with
> a L2 packet header.
> 
> v4 - merge with latest driver changes
> v3 - fix includes by removing ifdef for other type besides Linux.
>  Fix the copyright notice in the Makefile
> v2 - merge all of the patches into one patch.
>  Fix a typo on naming the tap device.
>  Update the maintainers list
> 
> Signed-off-by: Keith Wiles 
> ---
>  MAINTAINERS |   5 +
>  config/common_linuxapp  |   2 +
>  doc/guides/nics/tap.rst |  84 
>  drivers/net/Makefile|   1 +
>  drivers/net/tap/Makefile|  57 +++
>  drivers/net/tap/rte_eth_tap.c   | 866 
> 
>  drivers/net/tap/rte_pmd_tap_version.map |   4 +
>  mk/rte.app.mk   |   1 +
>  8 files changed, 1020 insertions(+)
>  create mode 100644 doc/guides/nics/tap.rst
>  create mode 100644 drivers/net/tap/Makefile
>  create mode 100644 drivers/net/tap/rte_eth_tap.c
>  create mode 100644 drivers/net/tap/rte_pmd_tap_version.map
> 
<>
> diff --git a/config/common_linuxapp b/config/common_linuxapp
> index 2483dfa..59a2053 100644
> --- a/config/common_linuxapp
> +++ b/config/common_linuxapp
> @@ -44,3 +44,5 @@ CONFIG_RTE_LIBRTE_PMD_VHOST=y
>  CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
>  CONFIG_RTE_LIBRTE_POWER=y
>  CONFIG_RTE_VIRTIO_USER=y
> +CONFIG_RTE_LIBRTE_PMD_TAP=y

According existing config items, a default value of a config option
should go to config/common_base, and environment specific config file
overwrites it if required.
So this option needs to be added into config/common_base too as disabled
by default.

> +CONFIG_RTE_PMD_TAP_MAX_QUEUES=32

Is the number of max queues really needs to be a config option, I assume
in normal use case user won't need to update this and will use single
queue, if that is true what about pushing this into source code to not
make config file more complex?

> diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst

<...>

> +.. code-block:: console
> +
> +   The interfaced name can be changed by adding the iface=foo0
> +   e.g. --vedv=eth_tap,iface=foo0 --vdev=eth_tap,iface=foo1, ...

s/vedv/vdev
eth_tap needs to be net_tap as part of unifying device names work

<...>

> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index bc93230..b4afa98 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -55,6 +55,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += thunderx
>  DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio
>  DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3
>  DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += xenvirt
> +DIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += tap

Rest of the PMDs sorted alphabetically, please do same.

>  
>  ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y)
>  DIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += vhost

<...>

> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c

<...>

> +
> +static const char *drivername = "Tap PMD";
> +static int tap_unit = 0;

No need to initialize to zero.

<...>

> +
> +struct pmd_internals {
> + char name[RTE_ETH_NAME_MAX_LEN];/* Internal Tap device name */
> + uint16_t nb_queues; /* Number of queues supported */
> + uint16_t pad0;

Why this padding? Is it reserved?

> + struct ether_addr eth_addr; /* Mac address of the device port */
> +
> + int if_index;   /* IF_INDEX for the port */
> + int fds[RTE_PMD_TAP_MAX_QUEUES]; /* List of all file descriptors */
> +
> + struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES];/* List of RX queues */
> + struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES];/* List of TX queues */
> +};
> +
> +/*
> + * Tun/Tap allocation routine
> + *
> + * name is the number of the interface to use, unless NULL to take the host
> + * supplied name.
> + */
> +static int
> +tun_alloc(char * name)

char *name

<...>

> +
> + /* Always set the fiile descriptor to non-blocking */

s/fiile/file

> + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
> + RTE_LOG(ERR, PMD, "Unable to set to nonblocking\n");
> + perror("F_SETFL, NONBLOCK");
> + goto error;
> + }
> +
> + /* If the name is different that new name as default */
> + if (name && strcmp(name, ifr.ifr_name))
> + strcpy(name, ifr.ifr_name);
What about more secure copy?

> +
> + return fd;
> +
> +error:
> + if (fd > 0)
> + close(fd);
> + return -1;
> +}
> +

<...>

> +
> +static void
> +tap_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
> +{
> + struct pmd_internals *internals = dev->data->dev_private;
> +
> + dev_info->driver_name = drivername;
> + 

[dpdk-dev] [PATCH v4] drivers/net:new PMD using tun/tap host interface

2016-10-11 Thread Ferruh Yigit
Hi Keith,

On 10/4/2016 3:45 PM, Keith Wiles wrote:
> The rte_eth_tap.c PMD creates a device using TUN/TAP interfaces
> on the local host. The PMD allows for DPDK and the host to
> communicate using a raw device interface on the host and in
> the DPDK application. The device created is a Tap device with
> a L2 packet header.
> 
> v4 - merge with latest driver changes
> v3 - fix includes by removing ifdef for other type besides Linux.
>  Fix the copyright notice in the Makefile
> v2 - merge all of the patches into one patch.
>  Fix a typo on naming the tap device.
>  Update the maintainers list
> 
> Signed-off-by: Keith Wiles 
> ---
>  MAINTAINERS |   5 +
>  config/common_linuxapp  |   2 +
>  doc/guides/nics/tap.rst |  84 
>  drivers/net/Makefile|   1 +
>  drivers/net/tap/Makefile|  57 +++
>  drivers/net/tap/rte_eth_tap.c   | 866 
> 
>  drivers/net/tap/rte_pmd_tap_version.map |   4 +
>  mk/rte.app.mk   |   1 +
>  8 files changed, 1020 insertions(+)
>  create mode 100644 doc/guides/nics/tap.rst
>  create mode 100644 drivers/net/tap/Makefile
>  create mode 100644 drivers/net/tap/rte_eth_tap.c
>  create mode 100644 drivers/net/tap/rte_pmd_tap_version.map

This patch needs to be rebased on top of latest next-net, .init &
.uninit are no more used.

Also patch gives a set of checkpatch warnings, fyi.

Thanks,
ferruh


[dpdk-dev] [PATCH v4] drivers/net:new PMD using tun/tap host interface

2016-10-04 Thread Keith Wiles
The rte_eth_tap.c PMD creates a device using TUN/TAP interfaces
on the local host. The PMD allows for DPDK and the host to
communicate using a raw device interface on the host and in
the DPDK application. The device created is a Tap device with
a L2 packet header.

v4 - merge with latest driver changes
v3 - fix includes by removing ifdef for other type besides Linux.
 Fix the copyright notice in the Makefile
v2 - merge all of the patches into one patch.
 Fix a typo on naming the tap device.
 Update the maintainers list

Signed-off-by: Keith Wiles 
---
 MAINTAINERS |   5 +
 config/common_linuxapp  |   2 +
 doc/guides/nics/tap.rst |  84 
 drivers/net/Makefile|   1 +
 drivers/net/tap/Makefile|  57 +++
 drivers/net/tap/rte_eth_tap.c   | 866 
 drivers/net/tap/rte_pmd_tap_version.map |   4 +
 mk/rte.app.mk   |   1 +
 8 files changed, 1020 insertions(+)
 create mode 100644 doc/guides/nics/tap.rst
 create mode 100644 drivers/net/tap/Makefile
 create mode 100644 drivers/net/tap/rte_eth_tap.c
 create mode 100644 drivers/net/tap/rte_pmd_tap_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 7c33ad4..fad74e4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -392,6 +392,11 @@ F: doc/guides/nics/pcap_ring.rst
 F: app/test/test_pmd_ring.c
 F: app/test/test_pmd_ring_perf.c

+Tap PMD
+M: Keith Wiles 
+F: drivers/net/tap
+F: doc/guides/nics/tap.rst
+
 Null Networking PMD
 M: Tetsuya Mukawa 
 F: drivers/net/null/
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 2483dfa..59a2053 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -44,3 +44,5 @@ CONFIG_RTE_LIBRTE_PMD_VHOST=y
 CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
 CONFIG_RTE_LIBRTE_POWER=y
 CONFIG_RTE_VIRTIO_USER=y
+CONFIG_RTE_LIBRTE_PMD_TAP=y
+CONFIG_RTE_PMD_TAP_MAX_QUEUES=32
diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst
new file mode 100644
index 000..072def8
--- /dev/null
+++ b/doc/guides/nics/tap.rst
@@ -0,0 +1,84 @@
+..  BSD LICENSE
+Copyright(c) 2016 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.
+
+Tun/Tap Poll Mode Driver
+
+
+The rte_eth_tap.c PMD creates a device using TUN/TAP interfaces on the local
+host. The PMD allows for DPDK and the host to communicate using a raw device
+interface on the host and in the DPDK application.
+
+The device created is a TAP device, which sends/receives packet in a raw format
+with a L2 header. The usage for a TAP PMD is for connectivity to the local host
+using a TAP interface. When the TAP PMD is initialized it will create a number
+of tap devices in the host accessed via 'ifconfig -a' or 'ip' command. The
+commands can be used to assign and query the virtual like device.
+
+These TAP interfaces can be used with wireshark or tcpdump or Pktgen-DPDK along
+with being able to be used as a network connection to the DPDK application. The
+method enable one or more interfaces is to use the --vdev=eth_tap option on the
+DPDK application  command line. Each --vdev=eth_tap option give will create an
+interface named dtap0, dtap1, ... and so forth.
+
+.. code-block:: console
+
+   The interfaced name can be changed by adding the iface=foo0
+   e.g. --vedv=eth_tap,iface=foo0 --vdev=eth_tap,iface=foo1, ...
+
+.. code-block:: console
+
+   Also the