DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v2 1/5] ethdev: add firmware version get
From: Yang, Qiming @ 2016-12-12  1:28 UTC (permalink / raw)
  To: Yigit, Ferruh, dev@dpdk.org; +Cc: Thomas Monjalon, Horton, Remy
In-Reply-To: <4177103b-21af-403c-ad3f-6ab1fac94903@intel.com>

Hi, Yigit
Yes, we had planned to add  fw_version in rte_eth_dev_info_get(). But Remy think we should better to implement this feature through a way don't break the original ABI. So I change the implement.

-----Original Message-----
From: Yigit, Ferruh 
Sent: Thursday, December 8, 2016 7:07 PM
To: Yang, Qiming <qiming.yang@intel.com>; dev@dpdk.org
Cc: Thomas Monjalon <thomas.monjalon@6wind.com>
Subject: Re: [dpdk-dev] [PATCH v2 1/5] ethdev: add firmware version get

Hi Qiming,

On 12/6/2016 7:16 AM, Qiming Yang wrote:
> This patch adds a new API 'rte_eth_dev_fwver_get' for fetching 
> firmware version by a given device.
> 
> Signed-off-by: Qiming Yang <qiming.yang@intel.com>

<...>

> @@ -1444,6 +1448,7 @@ struct eth_dev_ops {
>  	/**< Get names of extended statistics. */
>  	eth_queue_stats_mapping_set_t queue_stats_mapping_set;
>  	/**< Configure per queue stat counter mapping. */
> +	eth_fw_version_get_t       fw_version_get; /**< Get firmware version. */

Hi Qiming,

Not sure if I am missing something but this change is for following [1] deprecation notice, right?
If so, notice suggest updating rte_eth_dev_info_get() to include fw_version, but this patch adds a new eth_dev_ops.

Is it agreed to add a new eth_dev_ops for this?


[1]
* In 17.02 ABI change is planned: the ``rte_eth_dev_info`` structure
  will be extended with a new member ``fw_version`` in order to store
  the NIC firmware version.



>  	eth_dev_infos_get_t        dev_infos_get; /**< Get device info. */
>  	eth_dev_supported_ptypes_get_t dev_supported_ptypes_get;
>  	/**< Get packet types supported and identified by device*/

<...>

^ permalink raw reply

* Re: [PATCH v2 0/5] example/ethtool: add bus info and fw version get
From: Yang, Qiming @ 2016-12-12  1:43 UTC (permalink / raw)
  To: Horton, Remy, dev@dpdk.org
In-Reply-To: <b556bf81-e70a-9e5a-2db0-f52fe180ac51@intel.com>

Hi, Remy
I'll add this update in v3 patch, thank you for your remind.
BTW, It looks like Yigit don't agree the implement we used, he think we'd better not add a new ops to get this info.

-----Original Message-----
From: Horton, Remy 
Sent: Thursday, December 8, 2016 4:34 PM
To: Yang, Qiming <qiming.yang@intel.com>; dev@dpdk.org
Subject: Re: [dpdk-dev] [PATCH v2 0/5] example/ethtool: add bus info and fw version get


On 06/12/2016 15:16, Qiming Yang wrote:
[..]
> Qiming Yang (5):
>   ethdev: add firmware version get
>   net/e1000: add firmware version get
>   net/ixgbe: add firmware version get
>   net/i40e: add firmware version get
>   ethtool: dispaly bus info and firmware version

s/dispaly/display

doc/guides/rel_notes/release_17_02.rst ought to be updated as well. Code itself looks ok though..

Acked-by: Remy Horton <remy.horton@intel.com>

^ permalink raw reply

* Does DPDK i40e driver support 'Toeplitz hash'
From: ALeX Wang @ 2016-12-12  6:31 UTC (permalink / raw)
  To: dev; +Cc: Keith Amidon

Hi,

We want to use 'Toeplitz hash' for RSS hash on our server equipped with
'Intel X710-DA4' card.

However, seemed that we hit the exact same issue as this:

   Why only rx queue "0" can receive network packet by i40e NIC
   http://dpdk.org/ml/archives/dev/2015-July/022453.html

...
We are using the v16.11 release and would like to confirm if the issue above
has been address.  If so, could anyone post here how to configure?

Appreciate,
Alex Wang,

^ permalink raw reply

* [PATCH v2] vmxnet3: fix Rx deadlock
From: Stefan Puiu @ 2016-12-12  8:21 UTC (permalink / raw)
  To: dev; +Cc: yongwang, mac_leehk, Stefan Puiu
In-Reply-To: <1479120376-48723-1-git-send-email-stefan.puiu@gmail.com>

Our use case is that we have an app that needs to keep mbufs around
for a while. We've seen cases when calling vmxnet3_post_rx_bufs() from
vmxet3_recv_pkts(), it might not succeed to add any mbufs to any RX
descriptors (where it returns -err). Since there are no mbufs that the
virtual hardware can use, no packets will be received after this;
nobody retries this later, so the driver gets stuck in this state. I
call this a deadlock for lack of a better term - the virtual HW waits
for free mbufs, while the app waits for the hardware to notify it for
data. Note that after this, the app can't recover.

This fix is a rework of this patch by Marco Lee:
http://dpdk.org/dev/patchwork/patch/6575/. I had to forward port it,
address review comments and also reverted the allocation failure
handing to the first version of the patch
(http://dpdk.org/ml/archives/dev/2015-July/022079.html), since that's
the only approach that seems to work, and seems to be what other
drivers are doing (I checked ixgbe and em). Reusing the mbuf that's
getting passed to the application doesn't seem to make sense, and it
was causing weird issues in our app. Also, reusing rxm without
checking if it's NULL could cause the code to crash.

v2:
- address review comments, reworded description a bit
---
 drivers/net/vmxnet3/vmxnet3_rxtx.c | 39 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/net/vmxnet3/vmxnet3_rxtx.c b/drivers/net/vmxnet3/vmxnet3_rxtx.c
index b109168..93db10f 100644
--- a/drivers/net/vmxnet3/vmxnet3_rxtx.c
+++ b/drivers/net/vmxnet3/vmxnet3_rxtx.c
@@ -518,6 +518,32 @@
 	return nb_tx;
 }
 
+static inline void
+vmxnet3_renew_desc(vmxnet3_rx_queue_t *rxq, uint8_t ring_id,
+		   struct rte_mbuf *mbuf)
+{
+	uint32_t val = 0;
+	struct vmxnet3_cmd_ring *ring = &rxq->cmd_ring[ring_id];
+	struct Vmxnet3_RxDesc *rxd =
+		(struct Vmxnet3_RxDesc *)(ring->base + ring->next2fill);
+	vmxnet3_buf_info_t *buf_info = &ring->buf_info[ring->next2fill];
+
+	if (ring_id == 0)
+		val = VMXNET3_RXD_BTYPE_HEAD;
+	else
+		val = VMXNET3_RXD_BTYPE_BODY;
+
+	buf_info->m = mbuf;
+	buf_info->len = (uint16_t)(mbuf->buf_len - RTE_PKTMBUF_HEADROOM);
+	buf_info->bufPA = rte_mbuf_data_dma_addr_default(mbuf);
+
+	rxd->addr = buf_info->bufPA;
+	rxd->btype = val;
+	rxd->len = buf_info->len;
+	rxd->gen = ring->gen;
+
+	vmxnet3_cmd_ring_adv_next2fill(ring);
+}
 /*
  *  Allocates mbufs and clusters. Post rx descriptors with buffer details
  *  so that device can receive packets in those buffers.
@@ -657,9 +683,18 @@
 	}
 
 	while (rcd->gen == rxq->comp_ring.gen) {
+		struct rte_mbuf *newm;
+
 		if (nb_rx >= nb_pkts)
 			break;
 
+		newm = rte_mbuf_raw_alloc(rxq->mp);
+		if (unlikely(newm == NULL)) {
+			PMD_RX_LOG(ERR, "Error allocating mbuf");
+			rxq->stats.rx_buf_alloc_failure++;
+			break;
+		}
+
 		idx = rcd->rxdIdx;
 		ring_idx = (uint8_t)((rcd->rqID == rxq->qid1) ? 0 : 1);
 		rxd = (Vmxnet3_RxDesc *)rxq->cmd_ring[ring_idx].base + idx;
@@ -759,8 +794,8 @@
 		VMXNET3_INC_RING_IDX_ONLY(rxq->cmd_ring[ring_idx].next2comp,
 					  rxq->cmd_ring[ring_idx].size);
 
-		/* It's time to allocate some new buf and renew descriptors */
-		vmxnet3_post_rx_bufs(rxq, ring_idx);
+		/* It's time to renew descriptors */
+		vmxnet3_renew_desc(rxq, ring_idx, newm);
 		if (unlikely(rxq->shared->ctrl.updateRxProd)) {
 			VMXNET3_WRITE_BAR0_REG(hw, rxprod_reg[ring_idx] + (rxq->queue_id * VMXNET3_REG_ALIGN),
 					       rxq->cmd_ring[ring_idx].next2fill);
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH] vmxnet3: fix Rx deadlock
From: Stefan Puiu @ 2016-12-12  8:27 UTC (permalink / raw)
  To: Yong Wang; +Cc: dev@dpdk.org, mac_leehk@yahoo.com.hk
In-Reply-To: <BY2PR05MB2359E5B448AFCF17B7713738AF8C0@BY2PR05MB2359.namprd05.prod.outlook.com>

Hello and thanks for reviewing the patch.

On Wed, Nov 30, 2016 at 6:59 AM, Yong Wang <yongwang@vmware.com> wrote:
[...]
> I think a more accurate description is that the particular descriptor's generation bit never got flipped properly when an mbuf failed to be refilled which caused the rx stuck, rather than vmxnet3_post_rx_bufs() not being called afterwards.
>

Not sure if this kind of level of detail is useful, but if you can
think of a better explanation to put in the changelist, I can add it.
I see the generation bit not flipping as a symptom, while the core
problem is the hardware can't write to the descriptor. I felt the
explanation was going into too much detail anyway, so I've reworded it
a bit for v2. Let me know what you think.

Thanks,
Stefan.

^ permalink raw reply

* Re: [PATCH 3/4] crypto: add sgl support for sw PMDs
From: Kulasek, TomaszX @ 2016-12-12 10:01 UTC (permalink / raw)
  To: Michał Mirosław; +Cc: dev@dpdk.org
In-Reply-To: <CAHXqBFKvvV5JjScuoVH=6dE1YUw39RwwwSEQ4sRA=1aGHMQ9QQ@mail.gmail.com>

Hi Michał,

> -----Original Message-----
> From: Michał Mirosław [mailto:mirqus@gmail.com]
> Sent: Saturday, December 3, 2016 09:28
> To: Kulasek, TomaszX <tomaszx.kulasek@intel.com>
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 3/4] crypto: add sgl support for sw PMDs
> 
> 2016-12-02 18:07 GMT+01:00 Tomasz Kulasek <tomaszx.kulasek@intel.com>:
> > This patch introduces RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER feature
> > flag informing that selected crypto device supports segmented mbufs
> > natively and doesn't need to be coalesced before crypto operation.
> >
> > While using segmented buffers in crypto devices may have unpredictable
> > results, for PMDs which doesn't support it natively, additional check
> > is made for debug compilation.
> >
> [...]
> > +#ifdef RTE_LIBRTE_PMD_AESNI_GCM_DEBUG
> > +               if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
> > +                               (ops[i]->sym->m_dst != NULL &&
> > +                               !rte_pktmbuf_is_contiguous(
> > +                                               ops[i]->sym->m_dst))) {
> > +                       ops[i]->status =
> RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
> > +                       GCM_LOG_ERR("PMD supports only contiguous mbufs,
> "
> > +                               "op (%p) provides noncontiguous mbuf as
> "
> > +                               "source/destination buffer.\n", ops[i]);
> > +                       qp->qp_stats.enqueue_err_count++;
> > +                       break;
> > +               }
> > +#endif
> [...]
> 
> Why are there so many copies of this code?
> 
> Best Regards,
> Michał Mirosław

This is one check per crypto PMD: aesni-gcm, aesni-mb, openssl and so on, enabled per PMD.

Tomasz

^ permalink raw reply

* Re: [PATCH 01/22] ethdev: introduce generic flow API
From: Chandran, Sugesh @ 2016-12-12 10:20 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: Kevin Traynor, dev@dpdk.org, Thomas Monjalon,
	De Lara Guarch, Pablo, Olivier Matz
In-Reply-To: <20161209163846.GN10340@6wind.com>

Hi Adrien,

Regards
_Sugesh

> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Friday, December 9, 2016 4:39 PM
> To: Chandran, Sugesh <sugesh.chandran@intel.com>
> Cc: Kevin Traynor <ktraynor@redhat.com>; dev@dpdk.org; Thomas
> Monjalon <thomas.monjalon@6wind.com>; De Lara Guarch, Pablo
> <pablo.de.lara.guarch@intel.com>; Olivier Matz <olivier.matz@6wind.com>;
> sugesh.chandran@intel.comn
> Subject: Re: [dpdk-dev] [PATCH 01/22] ethdev: introduce generic flow API
> 
> Hi Sugesh,
> 
> On Fri, Dec 09, 2016 at 12:18:03PM +0000, Chandran, Sugesh wrote:
> [...]
> > > > Are you going to provide any control over the initialization of
> > > > NIC to define the capability matrices For eg; To operate in a L3
> > > > router mode,
> > > software wanted to initialize the NIC port only to consider the L2
> > > and L3 fields.
> > > > I assume the initialization is done based on the first rules that
> > > > are
> > > programmed into the NIC.?
> > >
> > > Precisely, PMDs are supposed to determine the most appropriate
> > > device mode to use in order to handle the requested rules. They may
> > > even switch to another mode if necessary assuming this does not
> > > break existing constraints.
> > >
> > > I think we've discussed an atomic (commit-based) mode of operation
> > > through separate functions as well, where the application would
> > > attempt to create a bunch of rules at once, possibly making it
> > > easier for PMDs to determine the most appropriate mode of operation
> for the device.
> > >
> > > All of these may be added later according to users feedback once the
> > > basic API has settled.
> > [Sugesh] Yes , we discussed about this before. However I feel that, it
> > make sense to provide some flexibility to the user/application to define a
> profile/mode of the device.
> > This way the complexity of determining the mode by itself will be taken
> away from PMD.
> > Looking at the P4 enablement patches in OVS, the mode definition APIs
> > can be used in conjunction
> > P4 behavioral model.
> > For eg: A P4 model for a L2 switch operate OVS as a L2 switch. Using
> > the mode definition APIs Its possible to impose the same behavioral model
> in the hardware too.
> > This way its simple, clean and very predictive though it needs to define an
> additional profile_define APIs.
> > I am sorry to provide the comment at this stage,  However looking at
> > the adoption of ebpf, P4 make me to think this way.
> > What do you think?
> 
> What you suggest (device profile configuration) would be done by a separate
> function in any case, so as long as everyone agrees on a generic method to
> do so, no problem with extending rte_flow. By default in the meantime we'll
> have to rely on PMDs to make the right decision.
[Sugesh] I am fine with PMD is making the decision on profile/mode selection in
Default case. However we must provide an option for the application to define a mode
and PMD must honor with it to avoid making an invalid mode change.
> 
> Do you think it has to be defined from the beginning?
[Sugesh] I feel it's going to be another big topic to decide how proposed mode implementation will be looks like,
What should be available modes and etc.  So I am OK to consider as its not part of this flow API definition for now.
However its good to mention that in the API comments section to be aware. Do you agree that?

> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply

* Re: [PATCH v3 00/31] net/i40e: base code update
From: Ferruh Yigit @ 2016-12-12 10:32 UTC (permalink / raw)
  To: Jingjing Wu, dev; +Cc: helin.zhang
In-Reply-To: <1481369093-102492-1-git-send-email-jingjing.wu@intel.com>

On 12/10/2016 11:24 AM, Jingjing Wu wrote:
> i40e base code upate. The main changes are:
>  - add clause22 and clause45 implementation for PHY registers accessing
>  - replace existing legacy memcpy() calls with i40e_memcpy() calls.
>  - use BIT() macro instead of bit fields
>  - add clear all WoL filters implementation
>  - add ERROR state for NVM update state machine
>  - add broadcast promiscuous control per VLAN
>  - remove unused X722_SUPPORT and I40E_NDIS_SUPPORT MARCOs
> 
> v3:
>  * update commit log of few patches as issue fix
> 
> v2:
>  * comments rework
>  * complie issue fix
>  * rebase to dpdk-next-net
> 
> Jingjing Wu (31):
>   net/i40e/base: add encap csum VF offload flag
>   net/i40e/base: fix flow control set for 25G
>   net/i40e/base: remove unnecessary code
>   net/i40e/base: fix bit test mask
>   net/i40e/base: group base mode VF offload flags
>   net/i40e/base: fix long link down notification time
>   net/i40e/base: add media type detection for 25G link
>   net/i40e/base: add clause22 and clause45 implementation
>   net/i40e/base: add bus number info
>   net/i40e/base: add protocols when discover capabilities
>   net/i40e/base: fix unknown PHYs incorrect identification
>   net/i40e/base: replace memcpy
>   net/i40e/base: deprecating unused macro
>   net/i40e/base: remove FPK HyperV VF device ID
>   net/i40e/base: add FEC bits to PHY capabilities
>   net/i40e/base: use BIT() macro instead of bit fields
>   net/i40e/base: adjust 25G PHY type values
>   net/i40e/base: implement clear all WoL filters
>   net/i40e/base: implement set VSI full promisc mode
>   net/i40e/base: fix wol failure on PF reset
>   net/i40e/base: save link FEC info from link up event
>   net/i40e/base: fix NVM access intefering
>   net/i40e/base: change shift values to hex
>   net/i40e/base: comment that udp port must be in Host order
>   net/i40e/base: remove duplicate definitions
>   net/i40e/base: add ERROR state for NVM update state machine
>   net/i40e/base: add broadcast promiscuous control per VLAN
>   net/i40e/base: fix division by zero
>   net/i40e/base: fix byte order
>   net/i40e/base: remove unused macro
>   net/i40e: remove unused macro from PMD
> 
<...>

Series applied to dpdk-next-net/master, thanks.

^ permalink raw reply

* Re: [PATCH 02/32] drivers/common: introducing dpaa2 mc driver
From: Hemant Agrawal @ 2016-12-12 10:32 UTC (permalink / raw)
  To: Ferruh Yigit, dev
  Cc: thomas.monjalon, bruce.richardson, shreyansh.jain,
	Cristian Sovaiala
In-Reply-To: <f3ba1542-3868-fea2-d030-bf22766a63fc@intel.com>

On 12/7/2016 1:18 AM, Ferruh Yigit wrote:
> On 12/4/2016 6:16 PM, Hemant Agrawal wrote:
>> This patch intoduces the DPAA2 MC(Management complex Driver)
>>
>> This driver is common to be used by various DPAA2 net, crypto
>> and other drivers
>>
>> Signed-off-by: Cristian Sovaiala <cristian.sovaiala@nxp.com>
>> [Hemant:rebase and conversion to library for DPDK]
>
> Is this note about how work share done? Do we need this in the history?

Yes! We can avoid it.

>> Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
>> ---
>>  config/defconfig_arm64-dpaa2-linuxapp-gcc    |   7 +-
>>  drivers/Makefile                             |   1 +
>>  drivers/common/Makefile                      |  36 +++++
>>  drivers/common/dpaa2/Makefile                |  36 +++++
>>  drivers/common/dpaa2/mc/Makefile             |  53 ++++++
>>  drivers/common/dpaa2/mc/dpaa2_mc_version.map |   4 +
>>  drivers/common/dpaa2/mc/fsl_mc_cmd.h         | 231 +++++++++++++++++++++++++++
>>  drivers/common/dpaa2/mc/fsl_mc_sys.h         |  98 ++++++++++++
>>  drivers/common/dpaa2/mc/mc_sys.c             | 126 +++++++++++++++
>
> Are drivers/common/dpaa2/* files are shared code or implemented for
> DPDK, I can see Linux version is different.
>
> If these are re-implemented for DPDK, let's follow DPDK coding rules for
> a clean start, what do you think?
>

It is not a re-implementation. We do minor changes to make the common 
library work in user space with DPDK.
The deviation from kernel is because it is still a work in progress 
there. Once it stable there, we will pull in the changes.

>>  9 files changed, 591 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/common/Makefile
>>  create mode 100644 drivers/common/dpaa2/Makefile
>>  create mode 100644 drivers/common/dpaa2/mc/Makefile
>>  create mode 100644 drivers/common/dpaa2/mc/dpaa2_mc_version.map
>>  create mode 100644 drivers/common/dpaa2/mc/fsl_mc_cmd.h
>>  create mode 100644 drivers/common/dpaa2/mc/fsl_mc_sys.h
>>  create mode 100644 drivers/common/dpaa2/mc/mc_sys.c
>>
>> diff --git a/config/defconfig_arm64-dpaa2-linuxapp-gcc b/config/defconfig_arm64-dpaa2-linuxapp-gcc
>> index 66df54c..00f207e 100644
>> --- a/config/defconfig_arm64-dpaa2-linuxapp-gcc
>> +++ b/config/defconfig_arm64-dpaa2-linuxapp-gcc
>> @@ -1,6 +1,7 @@
>>  #   BSD LICENSE
>>  #
>> -#   Copyright(c) 2016 Freescale Semiconductor, Inc. All rights reserved.
>> +#   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
>> +#   Copyright (c) 2016 NXP. All rights reserved.
>>  #
>>  #   Redistribution and use in source and binary forms, with or without
>>  #   modification, are permitted provided that the following conditions
>> @@ -40,3 +41,7 @@ CONFIG_RTE_ARCH_ARM_TUNE="cortex-a57+fp+simd"
>>  #
>>  CONFIG_RTE_MAX_LCORE=8
>>  CONFIG_RTE_MAX_NUMA_NODES=1
>> +
>> +# Compile software PMD backed by NXP DPAA2 files
>> +#
>> +CONFIG_RTE_LIBRTE_DPAA2_PMD=y
>
> Currently how it works is, default value of the config in "common_base"
> and it is overwritten in specific config files.
> So this config option also should go to "common_base" as disabled by
> default.
>
> And the other config option too, mentioned in the documentation.
>

OK

>> diff --git a/drivers/Makefile b/drivers/Makefile
>> index 81c03a8..d5580f6 100644
>> --- a/drivers/Makefile
>> +++ b/drivers/Makefile
>> @@ -31,6 +31,7 @@
>>
>>  include $(RTE_SDK)/mk/rte.vars.mk
>>
>> +DIRS-y += common
>>  DIRS-y += net
>>  DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += crypto
>>
>> diff --git a/drivers/common/Makefile b/drivers/common/Makefile
>> new file mode 100644
>> index 0000000..0c3f35f
>> --- /dev/null
>> +++ b/drivers/common/Makefile
>> @@ -0,0 +1,36 @@
>> +#   BSD LICENSE
>> +#
>> +#   Copyright(c) 2016 NXP. 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 NXP 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.
>> +
>> +include $(RTE_SDK)/mk/rte.vars.mk
>> +
>> +DIRS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += dpaa2
>> +
>> +include $(RTE_SDK)/mk/rte.subdir.mk
>> diff --git a/drivers/common/dpaa2/Makefile b/drivers/common/dpaa2/Makefile
>> new file mode 100644
>> index 0000000..a4f80c1
>> --- /dev/null
>> +++ b/drivers/common/dpaa2/Makefile
>> @@ -0,0 +1,36 @@
>> +#   BSD LICENSE
>> +#
>> +#   Copyright(c) 2016 NXP. 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 NXP 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.
>> +
>> +include $(RTE_SDK)/mk/rte.vars.mk
>> +
>> +DIRS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += mc
>> +
>> +include $(RTE_SDK)/mk/rte.subdir.mk
>> diff --git a/drivers/common/dpaa2/mc/Makefile b/drivers/common/dpaa2/mc/Makefile
>> new file mode 100644
>> index 0000000..9632168
>> --- /dev/null
>> +++ b/drivers/common/dpaa2/mc/Makefile
>> @@ -0,0 +1,53 @@
>> +#   BSD LICENSE
>> +#
>> +#   Copyright(c) 2016 NXP. 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 NXP 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.
>> +
>> +include $(RTE_SDK)/mk/rte.vars.mk
>> +RTE_SDK_MC=$(RTE_SDK)/drivers/common/dpaa2
>> +
>> +#
>> +# library name
>> +#
>> +LIB = libdpaa2_mc.a
>
> Not sure about this name, what do you think sticking the name used for
> pmd, like: librte_pmd_dpaa2_mc.a ?

We can do it. however dpaa2_mc is not a pmd in itself. It is library for 
dpaa2 PMDs (net and crypto).

We did this to distinguish from a regular PMD. Do you suggest something 
else?

>> +
>> +CFLAGS += -O3
>> +CFLAGS += $(WERROR_FLAGS)
>> +CFLAGS +=-Wno-strict-aliasing
>> +
>> +CFLAGS += -I$(RTE_SDK_MC)/mc
>> +EXPORT_MAP := dpaa2_mc_version.map
>
> Same comment for version file naming, rte_pmd_dpaa2_mc_version.map ?
>
>> +
>> +LIBABIVER := 1
>> +
>> +SRCS-y += \
>> +	mc_sys.c
>
> Also this is fine, since this folder included only if
> CONFIG_RTE_LIBRTE_DPAA2_PMD=y, to be consistent for rest of the Makefiles:
> SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += mc_sys.c
>

OK

>> +
>> +
>> +include $(RTE_SDK)/mk/rte.lib.mk
>> diff --git a/drivers/common/dpaa2/mc/dpaa2_mc_version.map b/drivers/common/dpaa2/mc/dpaa2_mc_version.map
>> new file mode 100644
>> index 0000000..31eca32
>> --- /dev/null
>> +++ b/drivers/common/dpaa2/mc/dpaa2_mc_version.map
>> @@ -0,0 +1,4 @@
>> +DPDK_17.02 {
>> +
>> +	local: *;
>> +};
>> diff --git a/drivers/common/dpaa2/mc/fsl_mc_cmd.h b/drivers/common/dpaa2/mc/fsl_mc_cmd.h
>> new file mode 100644
>> index 0000000..cbd3995
>> --- /dev/null
>> +++ b/drivers/common/dpaa2/mc/fsl_mc_cmd.h
>> @@ -0,0 +1,231 @@
>> +/* Copyright 2013-2016 Freescale Semiconductor Inc.
>> + * Copyright (c) 2016 NXP.
>> + *
>> + * 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 the above-listed copyright holders nor the
>> + * names of any contributors may be used to endorse or promote products
>> + * derived from this software without specific prior written permission.
>> + *
>> + *
>> + * ALTERNATIVELY, this software may be distributed under the terms of the
>> + * GNU General Public License ("GPL") as published by the Free Software
>> + * Foundation, either version 2 of that License or (at your option) any
>> + * later version.
>> + *
>> + * 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 HOLDERS 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.
>> + */
>> +#ifndef __FSL_MC_CMD_H
>> +#define __FSL_MC_CMD_H
>> +
>> +#define MC_CMD_NUM_OF_PARAMS	7
>> +
>> +#define MAKE_UMASK64(_width) \
>> +	((uint64_t)((_width) < 64 ? ((uint64_t)1 << (_width)) - 1 : \
>> +		       (uint64_t)-1))
>> +
>> +static inline uint64_t mc_enc(int lsoffset, int width, uint64_t val)
>> +{
>> +	return (uint64_t)(((uint64_t)val & MAKE_UMASK64(width)) << lsoffset);
>> +}
>> +
>> +static inline uint64_t mc_dec(uint64_t val, int lsoffset, int width)
>> +{
>> +	return (uint64_t)((val >> lsoffset) & MAKE_UMASK64(width));
>> +}
>> +
>> +struct mc_command {
>> +	uint64_t header;
>> +	uint64_t params[MC_CMD_NUM_OF_PARAMS];
>> +};
>> +
>> +/**
>> + * enum mc_cmd_status - indicates MC status at command response
>> + * @MC_CMD_STATUS_OK: Completed successfully
>> + * @MC_CMD_STATUS_READY: Ready to be processed
>> + * @MC_CMD_STATUS_AUTH_ERR: Authentication error
>> + * @MC_CMD_STATUS_NO_PRIVILEGE: No privilege
>> + * @MC_CMD_STATUS_DMA_ERR: DMA or I/O error
>> + * @MC_CMD_STATUS_CONFIG_ERR: Configuration error
>> + * @MC_CMD_STATUS_TIMEOUT: Operation timed out
>> + * @MC_CMD_STATUS_NO_RESOURCE: No resources
>> + * @MC_CMD_STATUS_NO_MEMORY: No memory available
>> + * @MC_CMD_STATUS_BUSY: Device is busy
>> + * @MC_CMD_STATUS_UNSUPPORTED_OP: Unsupported operation
>> + * @MC_CMD_STATUS_INVALID_STATE: Invalid state
>> + */
>> +enum mc_cmd_status {
>> +	MC_CMD_STATUS_OK = 0x0,
>> +	MC_CMD_STATUS_READY = 0x1,
>> +	MC_CMD_STATUS_AUTH_ERR = 0x3,
>> +	MC_CMD_STATUS_NO_PRIVILEGE = 0x4,
>> +	MC_CMD_STATUS_DMA_ERR = 0x5,
>> +	MC_CMD_STATUS_CONFIG_ERR = 0x6,
>> +	MC_CMD_STATUS_TIMEOUT = 0x7,
>> +	MC_CMD_STATUS_NO_RESOURCE = 0x8,
>> +	MC_CMD_STATUS_NO_MEMORY = 0x9,
>> +	MC_CMD_STATUS_BUSY = 0xA,
>> +	MC_CMD_STATUS_UNSUPPORTED_OP = 0xB,
>> +	MC_CMD_STATUS_INVALID_STATE = 0xC
>> +};
>> +
>> +/*  MC command flags */
>> +
>> +/**
>> + * High priority flag
>> + */
>> +#define MC_CMD_FLAG_PRI		0x00008000
>> +/**
>> + * Command completion flag
>> + */
>> +#define MC_CMD_FLAG_INTR_DIS	0x01000000
>> +
>> +/**
>> + * Command ID field offset
>> + */
>> +#define MC_CMD_HDR_CMDID_O	48
>> +/**
>> + * Command ID field size
>> + */
>> +#define MC_CMD_HDR_CMDID_S	16
>> +/**
>> + * Token field offset
>> + */
>> +#define MC_CMD_HDR_TOKEN_O	32
>> +/**
>> + * Token field size
>> + */
>> +#define MC_CMD_HDR_TOKEN_S	16
>> +/**
>> + * Status field offset
>> + */
>> +#define MC_CMD_HDR_STATUS_O	16
>> +/**
>> + * Status field size
>> + */
>> +#define MC_CMD_HDR_STATUS_S	8
>> +/**
>> + * Flags field offset
>> + */
>> +#define MC_CMD_HDR_FLAGS_O	0
>> +/**
>> + * Flags field size
>> + */
>> +#define MC_CMD_HDR_FLAGS_S	32
>> +/**
>> + *  Command flags mask
>> + */
>> +#define MC_CMD_HDR_FLAGS_MASK	0xFF00FF00
>> +
>> +#define MC_CMD_HDR_READ_STATUS(_hdr) \
>> +	((enum mc_cmd_status)mc_dec((_hdr), \
>> +		MC_CMD_HDR_STATUS_O, MC_CMD_HDR_STATUS_S))
>> +
>> +#define MC_CMD_HDR_READ_TOKEN(_hdr) \
>> +	((uint16_t)mc_dec((_hdr), MC_CMD_HDR_TOKEN_O, MC_CMD_HDR_TOKEN_S))
>> +
>> +#define MC_PREP_OP(_ext, _param, _offset, _width, _type, _arg) \
>> +	((_ext)[_param] |= cpu_to_le64(mc_enc((_offset), (_width), _arg)))
>> +
>> +#define MC_EXT_OP(_ext, _param, _offset, _width, _type, _arg) \
>> +	(_arg = (_type)mc_dec(cpu_to_le64(_ext[_param]), (_offset), (_width)))
>> +
>> +#define MC_CMD_OP(_cmd, _param, _offset, _width, _type, _arg) \
>> +	((_cmd).params[_param] |= mc_enc((_offset), (_width), _arg))
>> +
>> +#define MC_RSP_OP(_cmd, _param, _offset, _width, _type, _arg) \
>> +	(_arg = (_type)mc_dec(_cmd.params[_param], (_offset), (_width)))
>> +
>> +/* cmd, param, offset, width, type, arg_name */
>> +#define CMD_CREATE_RSP_GET_OBJ_ID_PARAM0(cmd, object_id) \
>> +	MC_RSP_OP(cmd, 0, 0,  32, uint32_t, object_id)
>> +
>> +/* cmd, param, offset, width, type, arg_name */
>> +#define CMD_DESTROY_SET_OBJ_ID_PARAM0(cmd, object_id) \
>> +	MC_CMD_OP(cmd, 0, 0,  32,  uint32_t,  object_id)
>> +
>> +static inline uint64_t mc_encode_cmd_header(uint16_t cmd_id,
>> +					    uint32_t cmd_flags,
>> +					    uint16_t token)
>> +{
>> +	uint64_t hdr;
>> +
>> +	hdr = mc_enc(MC_CMD_HDR_CMDID_O, MC_CMD_HDR_CMDID_S, cmd_id);
>> +	hdr |= mc_enc(MC_CMD_HDR_FLAGS_O, MC_CMD_HDR_FLAGS_S,
>> +		       (cmd_flags & MC_CMD_HDR_FLAGS_MASK));
>> +	hdr |= mc_enc(MC_CMD_HDR_TOKEN_O, MC_CMD_HDR_TOKEN_S, token);
>> +	hdr |= mc_enc(MC_CMD_HDR_STATUS_O, MC_CMD_HDR_STATUS_S,
>> +		       MC_CMD_STATUS_READY);
>> +
>> +	return hdr;
>> +}
>> +
>> +/**
>> + * mc_write_command - writes a command to a Management Complex (MC) portal
>> + *
>> + * @portal: pointer to an MC portal
>> + * @cmd: pointer to a filled command
>> + */
>> +static inline void mc_write_command(struct mc_command __iomem *portal,
>> +				    struct mc_command *cmd)
>> +{
>> +	int i;
>> +	uint32_t word;
>> +
>> +	/* copy command parameters into the portal */
>> +	for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
>> +		iowrite64(cmd->params[i], &portal->params[i]);
>> +
>> +	/* submit the command by writing the header */
>> +	word = (uint32_t)mc_dec(cmd->header, 32, 32);
>> +	iowrite32(word, (((uint32_t *)&portal->header) + 1));
>> +
>> +	word = (uint32_t)mc_dec(cmd->header, 0, 32);
>> +	iowrite32(word, (uint32_t *)&portal->header);
>> +}
>> +
>> +/**
>> + * mc_read_response - reads the response for the last MC command from a
>> + * Management Complex (MC) portal
>> + *
>> + * @portal: pointer to an MC portal
>> + * @resp: pointer to command response buffer
>> + *
>> + * Returns MC_CMD_STATUS_OK on Success; Error code otherwise.
>> + */
>> +static inline enum mc_cmd_status mc_read_response(
>> +					struct mc_command __iomem *portal,
>> +					struct mc_command *resp)
>> +{
>> +	int i;
>> +	enum mc_cmd_status status;
>> +
>> +	/* Copy command response header from MC portal: */
>> +	resp->header = ioread64(&portal->header);
>> +	status = MC_CMD_HDR_READ_STATUS(resp->header);
>> +	if (status != MC_CMD_STATUS_OK)
>> +		return status;
>> +
>> +	/* Copy command response data from MC portal: */
>> +	for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
>> +		resp->params[i] = ioread64(&portal->params[i]);
>> +
>> +	return status;
>> +}
>> +
>> +#endif /* __FSL_MC_CMD_H */
>> diff --git a/drivers/common/dpaa2/mc/fsl_mc_sys.h b/drivers/common/dpaa2/mc/fsl_mc_sys.h
>> new file mode 100644
>> index 0000000..d9d43e5
>> --- /dev/null
>> +++ b/drivers/common/dpaa2/mc/fsl_mc_sys.h
>> @@ -0,0 +1,98 @@
>> +/* Copyright 2013-2015 Freescale Semiconductor Inc.
>> + *
>> + * 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 the above-listed copyright holders nor the
>> + * names of any contributors may be used to endorse or promote products
>> + * derived from this software without specific prior written permission.
>> + *
>> + *
>> + * ALTERNATIVELY, this software may be distributed under the terms of the
>> + * GNU General Public License ("GPL") as published by the Free Software
>> + * Foundation, either version 2 of that License or (at your option) any
>> + * later version.
>> + *
>> + * 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 HOLDERS 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.
>> + */
>> +#ifndef _FSL_MC_SYS_H
>> +#define _FSL_MC_SYS_H
>> +
>> +#ifdef __linux_driver__
>> +
>> +#include <linux/errno.h>
>> +#include <asm/io.h>
>> +#include <linux/slab.h>
>> +
>> +struct fsl_mc_io {
>> +	void *regs;
>> +};
>> +
>> +#ifndef ENOTSUP
>> +#define ENOTSUP		95
>> +#endif
>> +
>> +#define ioread64(_p)	    readq(_p)
>> +#define iowrite64(_v, _p)   writeq(_v, _p)
>> +
>> +#else /* __linux_driver__ */
>> +
>> +#include <stdio.h>
>> +#include <libio.h>
>> +#include <stdint.h>
>> +#include <errno.h>
>> +#include <sys/uio.h>
>> +#include <linux/byteorder/little_endian.h>
>> +
>> +#define cpu_to_le64(x) __cpu_to_le64(x)
>> +#ifndef dmb
>> +#define dmb() {__asm__ __volatile__("" : : : "memory"); }
>> +#endif
>> +#define __iormb()       dmb()
>> +#define __iowmb()       dmb()
>> +#define __arch_getq(a)                  (*(volatile unsigned long *)(a))
>> +#define __arch_putq(v, a)                (*(volatile unsigned long *)(a) = (v))
>> +#define __arch_putq32(v, a)                (*(volatile unsigned int *)(a) = (v))
>> +#define readq(c)        \
>> +	({ uint64_t __v = __arch_getq(c); __iormb(); __v; })
>> +#define writeq(v, c)     \
>> +	({ uint64_t __v = v; __iowmb(); __arch_putq(__v, c); __v; })
>> +#define writeq32(v, c) \
>> +	({ uint32_t __v = v; __iowmb(); __arch_putq32(__v, c); __v; })
>> +#define ioread64(_p)	    readq(_p)
>> +#define iowrite64(_v, _p)   writeq(_v, _p)
>> +#define iowrite32(_v, _p)   writeq32(_v, _p)
>> +#define __iomem
>> +
>> +struct fsl_mc_io {
>> +	void *regs;
>> +};
>> +
>> +#ifndef ENOTSUP
>> +#define ENOTSUP		95
>> +#endif
>> +
>> +/*GPP is supposed to use MC commands with low priority*/
>> +#define CMD_PRI_LOW          0 /*!< Low Priority command indication */
>> +
>> +struct mc_command;
>> +
>> +int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd);
>> +
>> +#endif /* __linux_driver__ */
>> +
>> +#endif /* _FSL_MC_SYS_H */
>> diff --git a/drivers/common/dpaa2/mc/mc_sys.c b/drivers/common/dpaa2/mc/mc_sys.c
>> new file mode 100644
>> index 0000000..e12a18b
>> --- /dev/null
>> +++ b/drivers/common/dpaa2/mc/mc_sys.c
>> @@ -0,0 +1,126 @@
>> +/* Copyright 2013-2015 Freescale Semiconductor Inc.
>> + *
>> + * 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 the above-listed copyright holders nor the
>> + * names of any contributors may be used to endorse or promote products
>> + * derived from this software without specific prior written permission.
>> + *
>> + *
>> + * ALTERNATIVELY, this software may be distributed under the terms of the
>> + * GNU General Public License ("GPL") as published by the Free Software
>> + * Foundation, either version 2 of that License or (at your option) any
>> + * later version.
>> + *
>> + * 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 HOLDERS 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.
>> + */
>> +#include <fsl_mc_sys.h>
>> +#include <fsl_mc_cmd.h>
>> +
>> +/** User space framework uses MC Portal in shared mode. Following change
>> +* introduces lock in MC FLIB
>> +*/
>> +
>> +/**
>> +* The mc_spinlock_t type.
>> +*/
>> +typedef struct {
>> +	volatile int locked; /**< lock status 0 = unlocked, 1 = locked */
>> +} mc_spinlock_t;
>> +
>> +/**
>> +* A static spinlock initializer.
>> +*/
>> +static mc_spinlock_t mc_portal_lock = { 0 };
>> +
>> +static inline void mc_pause(void) {}
>> +
>> +static inline void mc_spinlock_lock(mc_spinlock_t *sl)
>> +{
>> +	while (__sync_lock_test_and_set(&sl->locked, 1))
>> +		while (sl->locked)
>> +			mc_pause();
>> +}
>> +
>> +static inline void mc_spinlock_unlock(mc_spinlock_t *sl)
>> +{
>> +	__sync_lock_release(&sl->locked);
>> +}
>> +
>> +static int mc_status_to_error(enum mc_cmd_status status)
>> +{
>> +	switch (status) {
>> +	case MC_CMD_STATUS_OK:
>> +		return 0;
>> +	case MC_CMD_STATUS_AUTH_ERR:
>> +		return -EACCES; /* Token error */
>> +	case MC_CMD_STATUS_NO_PRIVILEGE:
>> +		return -EPERM; /* Permission denied */
>> +	case MC_CMD_STATUS_DMA_ERR:
>> +		return -EIO; /* Input/Output error */
>> +	case MC_CMD_STATUS_CONFIG_ERR:
>> +		return -EINVAL; /* Device not configured */
>> +	case MC_CMD_STATUS_TIMEOUT:
>> +		return -ETIMEDOUT; /* Operation timed out */
>> +	case MC_CMD_STATUS_NO_RESOURCE:
>> +		return -ENAVAIL; /* Resource temporarily unavailable */
>> +	case MC_CMD_STATUS_NO_MEMORY:
>> +		return -ENOMEM; /* Cannot allocate memory */
>> +	case MC_CMD_STATUS_BUSY:
>> +		return -EBUSY; /* Device busy */
>> +	case MC_CMD_STATUS_UNSUPPORTED_OP:
>> +		return -ENOTSUP; /* Operation not supported by device */
>> +	case MC_CMD_STATUS_INVALID_STATE:
>> +		return -ENODEV; /* Invalid device state */
>> +	default:
>> +		break;
>> +	}
>> +
>> +	/* Not expected to reach here */
>> +	return -EINVAL;
>> +}
>> +
>> +int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd)
>> +{
>> +	enum mc_cmd_status status;
>> +
>> +	if (!mc_io || !mc_io->regs)
>> +		return -EACCES;
>> +
>> +	/* --- Call lock function here in case portal is shared --- */
>> +	mc_spinlock_lock(&mc_portal_lock);
>> +
>> +	mc_write_command(mc_io->regs, cmd);
>> +
>> +	/* Spin until status changes */
>> +	do {
>> +		status = MC_CMD_HDR_READ_STATUS(ioread64(mc_io->regs));
>> +
>> +		/* --- Call wait function here to prevent blocking ---
>> +		 * Change the loop condition accordingly to exit on timeout.
>> +		 */
>> +	} while (status == MC_CMD_STATUS_READY);
>> +
>> +	/* Read the response back into the command buffer */
>> +	mc_read_response(mc_io->regs, cmd);
>> +
>> +	/* --- Call unlock function here in case portal is shared --- */
>> +	mc_spinlock_unlock(&mc_portal_lock);
>> +
>> +	return mc_status_to_error(status);
>> +}
>>
>
>

^ permalink raw reply

* Re: [PATCH 01/22] ethdev: introduce generic flow API
From: Adrien Mazarguil @ 2016-12-12 11:17 UTC (permalink / raw)
  To: Chandran, Sugesh
  Cc: Kevin Traynor, dev@dpdk.org, Thomas Monjalon,
	De Lara Guarch, Pablo, Olivier Matz
In-Reply-To: <2EF2F5C0CC56984AA024D0B180335FCB13EC4F76@IRSMSX102.ger.corp.intel.com>

Hi Sugesh,

On Mon, Dec 12, 2016 at 10:20:18AM +0000, Chandran, Sugesh wrote:
> Hi Adrien,
> 
> Regards
> _Sugesh
> 
> > -----Original Message-----
> > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > Sent: Friday, December 9, 2016 4:39 PM
> > To: Chandran, Sugesh <sugesh.chandran@intel.com>
> > Cc: Kevin Traynor <ktraynor@redhat.com>; dev@dpdk.org; Thomas
> > Monjalon <thomas.monjalon@6wind.com>; De Lara Guarch, Pablo
> > <pablo.de.lara.guarch@intel.com>; Olivier Matz <olivier.matz@6wind.com>;
> > sugesh.chandran@intel.comn
> > Subject: Re: [dpdk-dev] [PATCH 01/22] ethdev: introduce generic flow API
> > 
> > Hi Sugesh,
> > 
> > On Fri, Dec 09, 2016 at 12:18:03PM +0000, Chandran, Sugesh wrote:
> > [...]
> > > > > Are you going to provide any control over the initialization of
> > > > > NIC to define the capability matrices For eg; To operate in a L3
> > > > > router mode,
> > > > software wanted to initialize the NIC port only to consider the L2
> > > > and L3 fields.
> > > > > I assume the initialization is done based on the first rules that
> > > > > are
> > > > programmed into the NIC.?
> > > >
> > > > Precisely, PMDs are supposed to determine the most appropriate
> > > > device mode to use in order to handle the requested rules. They may
> > > > even switch to another mode if necessary assuming this does not
> > > > break existing constraints.
> > > >
> > > > I think we've discussed an atomic (commit-based) mode of operation
> > > > through separate functions as well, where the application would
> > > > attempt to create a bunch of rules at once, possibly making it
> > > > easier for PMDs to determine the most appropriate mode of operation
> > for the device.
> > > >
> > > > All of these may be added later according to users feedback once the
> > > > basic API has settled.
> > > [Sugesh] Yes , we discussed about this before. However I feel that, it
> > > make sense to provide some flexibility to the user/application to define a
> > profile/mode of the device.
> > > This way the complexity of determining the mode by itself will be taken
> > away from PMD.
> > > Looking at the P4 enablement patches in OVS, the mode definition APIs
> > > can be used in conjunction
> > > P4 behavioral model.
> > > For eg: A P4 model for a L2 switch operate OVS as a L2 switch. Using
> > > the mode definition APIs Its possible to impose the same behavioral model
> > in the hardware too.
> > > This way its simple, clean and very predictive though it needs to define an
> > additional profile_define APIs.
> > > I am sorry to provide the comment at this stage,  However looking at
> > > the adoption of ebpf, P4 make me to think this way.
> > > What do you think?
> > 
> > What you suggest (device profile configuration) would be done by a separate
> > function in any case, so as long as everyone agrees on a generic method to
> > do so, no problem with extending rte_flow. By default in the meantime we'll
> > have to rely on PMDs to make the right decision.
> [Sugesh] I am fine with PMD is making the decision on profile/mode selection in
> Default case. However we must provide an option for the application to define a mode
> and PMD must honor with it to avoid making an invalid mode change.
> > 
> > Do you think it has to be defined from the beginning?
> [Sugesh] I feel it's going to be another big topic to decide how proposed mode implementation will be looks like,
> What should be available modes and etc.  So I am OK to consider as its not part of this flow API definition for now.
> However its good to mention that in the API comments section to be aware. Do you agree that?

Will do, I'll mention it in the "future evolutions" section.

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply

* Re: [PATCH v12 1/6] ethdev: add Tx preparation
From: Ananyev, Konstantin @ 2016-12-12 11:51 UTC (permalink / raw)
  To: Kulasek, TomaszX, Olivier Matz; +Cc: Thomas Monjalon, dev@dpdk.org
In-Reply-To: <3042915272161B4EB253DA4D77EB373A14F5A409@IRSMSX102.ger.corp.intel.com>

Hi Olivier and Tomasz,

> -----Original Message-----
> From: Kulasek, TomaszX
> Sent: Friday, December 9, 2016 5:19 PM
> To: Olivier Matz <olivier.matz@6wind.com>; Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Cc: Thomas Monjalon <thomas.monjalon@6wind.com>; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v12 1/6] ethdev: add Tx preparation
> 
> Hi Oliver,
> 
> My 5 cents below:
> 
> > -----Original Message-----
> > From: Olivier Matz [mailto:olivier.matz@6wind.com]
> > Sent: Thursday, December 8, 2016 18:24
> > To: Ananyev, Konstantin <konstantin.ananyev@intel.com>
> > Cc: Thomas Monjalon <thomas.monjalon@6wind.com>; Kulasek, TomaszX
> > <tomaszx.kulasek@intel.com>; dev@dpdk.org
> > Subject: Re: [dpdk-dev] [PATCH v12 1/6] ethdev: add Tx preparation
> >
> > Hi Konstantin,
> >
> > On Fri, 2 Dec 2016 16:17:51 +0000, "Ananyev, Konstantin"
> > <konstantin.ananyev@intel.com> wrote:
> > > Hi Olivier,
> > >
> > > > -----Original Message-----
> > > > From: Olivier Matz [mailto:olivier.matz@6wind.com]
> > > > Sent: Friday, December 2, 2016 8:24 AM
> > > > To: Ananyev, Konstantin <konstantin.ananyev@intel.com>
> > > > Cc: Thomas Monjalon <thomas.monjalon@6wind.com>; Kulasek, TomaszX
> > > > <tomaszx.kulasek@intel.com>; dev@dpdk.org Subject: Re: [dpdk-dev]
> > > > [PATCH v12 1/6] ethdev: add Tx preparation
> > > >
> > > > Hi Konstantin,
> > > >
> > > > On Fri, 2 Dec 2016 01:06:30 +0000, "Ananyev, Konstantin"
> > > > <konstantin.ananyev@intel.com> wrote:
> > > > > >
> > > > > > 2016-11-23 18:36, Tomasz Kulasek:
> > > > > > > +/**
> > > > > > > + * Process a burst of output packets on a transmit queue of
> > > > > > > an Ethernet device.
> > > > > > > + *
> > > > > > > + * The rte_eth_tx_prepare() function is invoked to prepare
> > > > > > > output packets to be
> > > > > > > + * transmitted on the output queue *queue_id* of the Ethernet
> > > > > > > device designated
> > > > > > > + * by its *port_id*.
> > > > > > > + * The *nb_pkts* parameter is the number of packets to be
> > > > > > > prepared which are
> > > > > > > + * supplied in the *tx_pkts* array of *rte_mbuf* structures,
> > > > > > > each of them
> > > > > > > + * allocated from a pool created with
> > > > > > > rte_pktmbuf_pool_create().
> > > > > > > + * For each packet to send, the rte_eth_tx_prepare() function
> > > > > > > performs
> > > > > > > + * the following operations:
> > > > > > > + *
> > > > > > > + * - Check if packet meets devices requirements for tx
> > > > > > > offloads.
> > > > > > > + *
> > > > > > > + * - Check limitations about number of segments.
> > > > > > > + *
> > > > > > > + * - Check additional requirements when debug is enabled.
> > > > > > > + *
> > > > > > > + * - Update and/or reset required checksums when tx offload
> > > > > > > is set for packet.
> > > > > > > + *
> > > > > > > + * Since this function can modify packet data, provided mbufs
> > > > > > > must be safely
> > > > > > > + * writable (e.g. modified data cannot be in shared
> > > > > > > segment).
> > > > > >
> > > > > > I think we will have to remove this limitation in next releases.
> > > > > > As we don't know how it could affect the API, I suggest to
> > > > > > declare this API EXPERIMENTAL.
> > > > >
> > > > > While I don't really mind to mart it as experimental, I don't
> > > > > really understand the reasoning: Why " this function can modify
> > > > > packet data, provided mbufs must be safely writable" suddenly
> > > > > becomes a problem? That seems like and obvious limitation to me
> > > > > and let say tx_burst() has the same one. Second, I don't see how
> > > > > you are going to remove it without introducing a heavy performance
> > > > > impact. Konstantin
> > > >
> > > > About tx_burst(), I don't think we should force the user to provide
> > > > a writable mbuf. There are many use cases where passing a clone
> > > > already works as of today and it avoids duplicating the mbuf data.
> > > > For instance: traffic generator, multicast, bridging/tap, etc...
> > > >
> > > > Moreover, this requirement would be inconsistent with the model you
> > > > are proposing in case of pipeline:
> > > >  - tx_prepare() on core X, may update the data
> > > >  - tx_burst() on core Y, should not touch the data to avoid cache
> > > > misses
> > >
> > > Probably I wasn't very clear in my previous mail.
> > > I am not saying that we should force the user to pass a writable mbuf.
> > > What I am saying that for tx_burst() current expectation is that after
> > > mbuf is handled to tx_burst() user shouldn't try to modify its buffer
> > > contents till TX engine is done with the buffer (mbuf_free() is called
> > > by TX func for it). For tx_prep(), I think, it is the same though
> > > restrictions are a bit more strict: user should not try to read/write
> > > to the mbuf while tx_prep() is not finished with it. What puzzles me
> > > is that why that should be the reason to mark tx_prep() as
> > > experimental. Konstantin
> >
> > To be sure we're on the same page, let me reword:
> >
> > - mbufs passed to tx_prepare() by the application must have their
> >   headers (l2_len + l3_len + l4_len) writable because the phdr checksum
> >   can be replaced. It could be precised in the api comment.
> >
> > - mbufs passed to tx_burst() must not be modified by the driver/hw, nor
> >   by the application.

Yes, agree with both.

> >
> >
> > About the API itself, I have one more question. I know you've already
> > discussed this a bit with Adrien, I don't want to spawn a new big thread
> > from here ;)
> >
> > The API provides tx_prepare() to check the packets have the proper format,
> > and possibly modify them (ex: csum offload / tso) to match hw
> > requirements. So it does both checks (number of segments) and fixes
> > (csum/tso). What determines things that should be checked and things that
> > should be fixed?
> >

Just to echo Tomasz detailed reply below: I think right now tx_prepare()
doesn't make any fixing.
It just: checks that packet satisfies PMD/HW requirements, if not returns
an error without trying to fix anything/
If the  packet seems valid - calculates and fills L4 cksum to fulfill HW reqs . 
About the question what should be checked - as usual there is a tradeoff between 
additional checks and performance.
As Tomasz stated below right now in non-debug mode we do checks only for things
that can have a critical impact on HW itself (tx hang, etc.).
All extra checks are implemented only in DEBUG mode right now.  

> 
> 1) Performance -- we may assume that packets are created with the common rules (e.g. doesn't tries to count IP checksum for IPv6
> packet, sets all required fields, etc.). For now, additional checks are done only in DEBUG mode.
> 
> 2) Uncommon requirements, such a number of segments for TSO/non-TSO, where invalid values can cause unexpected results (or
> even hang device on burst), so it is critical (at least for ixgbe and i40e) and must be checked.
> 
> 3) Checksum field must be initialized in a hardware specific way to count it properly.
> 
> 4) If packet is invalid its content isn't modified nor restored.

> 
> > The application gets few information from tx_prepare() about what should
> > be done to make the packet accepted by the hw, and the actions will
> > probably be different depending on hardware.

That's true.
I am open to suggestions how in future to provide extra information to the upper layer.
Set rte_errno to different values depending on type of error,
OR extra parameter in tx_prepare() that will provide more detailed error information,
OR something else?

> So could we imagine that in
> > the future the function also tries to fix the packet? I've seen your
> > comment saying that it has to be an application decision, so what about
> > having a parameter saying "fix the packet" or "don't fix it"?
> >

While I am not directly opposed to that idea, I am a bit skeptical
that it could be implemented in useful and effective way.    
As I said before it may be fixed in different ways:
coalesce mbufs, split mbuf chain into multiple ones,
might be some sort of combination of these 2 approaches.
Again it seems a bit ineffective from performance point of view:
form packet first then check and re-adjust it again.
Seems more plausible to have it formed in a right way straightway.
Also it would mean that we'll need to pass to tx_prepare() information
about which mempool to use for new mbufs, probably some extra information. 
That's why I think it might be better to do a proper (re)formatting of the packet
before passing it down to tx_prepare().
Might be some sort of generic helper function in rte_net that would use information
from rte_eth_desc_lim and could be called by upper layer before tx_prepare().
But if you think it could be merged into tx_prepare() into some smart and effective way -     
sure thing, let's look at particular implementation ideas you have. 

> 
> The main question here is how invasive in packet data tx_prepare should be.
> 
> If I understand you correctly, you're talking about the situation when tx_prepare will try to restore packet internally, e.g. linearize data
> for i40e to meet number of segments requirements, split mbufs, when are too large, maybe someone will wanted to have full
> software checksum computation fallback for devices which doesn't support it, and so on? And then this parameter will indicate "do
> the required work for me", or "just check, initialize what should be initialized, if fails, let me decide"?
> 
> Implemented model is quite simple and clear:
> 
> 1) Validate uncommon requirements which may cause a problem and let application to deal with it.
> 2) If packet is valid, initialize required fields according to the hardware requirements.
> 
> In fact, it doesn't fix anything for now, but initializes checksums, and the main reason why it is done here, is the fact that it cannot be
> done in a trivial way in the application itself.
> 
> IMHO, we should to keep this API as simple as it possible and not let it grow in unexpected way (also for performance reason).
> 
> > About rte_eth_desc_lim->nb_seg_max and
> > rte_eth_desc_lim->nb_mtu_seg_max, I'm still quite reserved, especially for
> > the 2nd one, because I don't see how it can be used by the application.
> > Well, it does not hurt to have them, but for me it looks a bit useless.
> >
> 
> * "nb_seg_max": Maximum number of segments per whole packet.
> * "nb_mtu_seg_max": Maximum number of segments per one MTU.
> 
> Application can use provided values in a fallowed way:
> 
> * For non-TSO packet, a single transmit packet may span up to "nb_mtu_seg_max" buffers.
> * For TSO packet the total number of data descriptors is "nb_seg_max", and each segment within the TSO may span up to
> "nb_mtu_seg_max".

I suppose these fields will be useful.
Let say you are about to form and send packets.
Right now, how would you know what are HW limitations on number of segments per packet?  

> 
> > Last thing, I think this API should become the default in the future.
> > For instance, it would prevent the application to calculate a phdr csum
> > that will not be used by the hw. Not calling tx_prepare() would require
> > the user/application to exactly knows the underlying hw and the kind of
> > packet that are generated. So for me it means we'll need to also update
> > other examples (other testpmd engines, l2fwd, ...). Do you agree?
> >
> 
> Most of sample applications doesn't use TX offloads at all and doesn't count checksums. So the question is "should tx_prepare be
> used even if not required?"

I suppose it wouldn't be a big harm to add tx_prepare() into sample apps when appropriate.
In most cases (when simple TS path used) it will be NOP anyway.

Konstantin

^ permalink raw reply

* Re: [PATCH v11] drivers/net:new TUN/TAP device PMD
From: Vasily Philipov @ 2016-12-12 12:39 UTC (permalink / raw)
  To: Keith Wiles, dev@dpdk.org
  Cc: pmatilai@redhat.com, yuanhan.liu@linux.intel.com,
	ferruh.yigit@intel.com, john.mcnamara@intel.com
In-Reply-To: <20161209190519.2390-1-keith.wiles@intel.com>



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Keith Wiles
> Sent: Friday, December 09, 2016 21:05
> To: dev@dpdk.org
> Cc: pmatilai@redhat.com; yuanhan.liu@linux.intel.com;
> ferruh.yigit@intel.com; john.mcnamara@intel.com
> Subject: [dpdk-dev] [PATCH v11] drivers/net:new TUN/TAP device PMD
> 
> 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.
> 
> v11- Add the tap.rst to the nic/index.rst file
> v10- Change the string name used to allow for multiple devices.
> v9 - Fix up the docs to use correct syntax
> v8 - Fix issue with tap_tx_queue_setup() not return zero on success.
> v7 - Reword the comment in common_base and fix the data->name issue
> v6 - fixed the checkpatch issues
> v5 - merge in changes from list review see related emails
>      fixed many minor edits
> 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 <keith.wiles@intel.com>
> ---
>  MAINTAINERS                             |   5 +
>  config/common_base                      |   9 +
>  config/common_linuxapp                  |   1 +
>  doc/guides/nics/index.rst               |   1 +
>  doc/guides/nics/tap.rst                 | 136 ++++++
>  drivers/net/Makefile                    |   1 +
>  drivers/net/tap/Makefile                |  57 +++
>  drivers/net/tap/rte_eth_tap.c           | 765
> ++++++++++++++++++++++++++++++++
>  drivers/net/tap/rte_pmd_tap_version.map |   4 +
>  mk/rte.app.mk                           |   1 +
>  10 files changed, 980 insertions(+)

Tested-by: Vasily Philipov <vasilyf@mellanox.com>

^ permalink raw reply

* [PATCH v3 0/9] net/ixgbe: move set VF functions.
From: Bernard Iremonger @ 2016-12-12 13:50 UTC (permalink / raw)
  To: thomas.monjalon, dev; +Cc: Bernard Iremonger
In-Reply-To: <1481304361-16032-1-git-send-email-bernard.iremonger@intel.com>

This patchset implements the following deprecation notice:
[PATCH v1] doc: announce API and ABI change for librte_ether

Changes in V3:
Updated LIBABIVER in Makefile in librte_ether patch.
Updated rte_ethdev.h and ret_ether_version.map in librte_ether patch.
Squashed deprecation notice patch into librte_ether patch.
Added release_note patch.

Changes in V2:
Update testpmd set vf commands help messages.
Updated ethtool to use the ixgbe public API's.
Removed the ixgbe_set_pool_* and ixgbe_set_vf_rate_limit functions.
Removed the rte_eth_dev_set_vf_* API's
Removed the deprecation notice.

Changes in V1:
The following functions from eth_dev_ops have been moved to the ixgbe PMD
and renamed:

ixgbe_set_pool_rx_mode
ixgbe_set_pool_rx
ixgbe_set_pool_tx
ixgbe_set_pool_vlan_filter
ixgbe_set_vf_rate_limit

Renamed the functions to the following:

rte_pmd_ixgbe_set_vf_rxmode
rte_pmd_ixgbe_set_vf_rx
rte_pmd_ixgbe_set_vf_tx
rte_pmd_ixgbe_set_vf_vlan_filter
rte_pmd_ixgbe_set_vf_rate_limit

Testpmd has been modified to use the following functions:
rte_pmd_ixgbe_set_vf_rxmode
rte_pmd_ixgbe_set_vf_rate_limit

New testpmd commands have been added to test the following functions:
rte_pmd_ixgbe_set_vf_rx
rte_pmd_ixgbe_set_vf_tx
rte_pmd_ixgbe_set_vf_vlan_filter

The testpmd user guide has been updated for the new commands.

Bernard Iremonger (9):
  net/ixgbe: move set VF functions from the ethdev
  app/testpmd: use ixgbe public functions
  app/testpmd: add command for set VF VLAN filter
  app/testpmd: add command for set VF receive
  app/testpmd: add command for set VF transmit
  examples/ethtool: use ixgbe public function
  net/ixgbe: remove static set VF functions
  librte_ether: remove the set VF API's
  doc: update release notes

 app/test-pmd/cmdline.c                      | 270 +++++++++++++++-
 app/test-pmd/config.c                       |  31 +-
 doc/guides/rel_notes/deprecation.rst        |  13 -
 doc/guides/rel_notes/release_17_02.rst      |  20 ++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  21 ++
 drivers/net/ixgbe/ixgbe_ethdev.c            | 459 ++++++++++++++++------------
 drivers/net/ixgbe/rte_pmd_ixgbe.h           | 104 +++++++
 drivers/net/ixgbe/rte_pmd_ixgbe_version.map |  10 +
 examples/ethtool/lib/rte_ethtool.c          |   5 +-
 lib/librte_ether/Makefile                   |   4 +-
 lib/librte_ether/rte_ethdev.c               | 129 --------
 lib/librte_ether/rte_ethdev.h               | 140 ---------
 lib/librte_ether/rte_ether_version.map      |   7 +-
 13 files changed, 706 insertions(+), 507 deletions(-)

-- 
2.10.1

^ permalink raw reply

* [PATCH v3 1/9] net/ixgbe: move set VF functions from the ethdev
From: Bernard Iremonger @ 2016-12-12 13:50 UTC (permalink / raw)
  To: thomas.monjalon, dev; +Cc: Bernard Iremonger
In-Reply-To: <1481304361-16032-1-git-send-email-bernard.iremonger@intel.com>

Move the following functions from eth_dev_ops to the ixgbe PMD and rename:

ixgbe_set_pool_rx_mode
ixgbe_set_pool_rx
ixgbe_set_pool_tx
ixgbe_set_pool_vlan_filter
ixgbe_set_vf_rate_limit

Rename the functions to the following:

rte_pmd_ixgbe_set_vf_rxmode
rte_pmd_ixgbe_set_vf_rx
rte_pmd_ixgbe_set_vf_tx
rte_pmd_ixgbe_set_vf_vlan_filter
rte_pmd_ixgbe_set_vf_rate_limit

Use public function internally

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c            | 266 +++++++++++++++++++++++++++-
 drivers/net/ixgbe/rte_pmd_ixgbe.h           | 104 +++++++++++
 drivers/net/ixgbe/rte_pmd_ixgbe_version.map |  10 ++
 3 files changed, 379 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index edc9b22..37b82a4 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -2294,7 +2294,8 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 		for (vf = 0; vf < dev->pci_dev->max_vfs; vf++)
 			for (idx = 0; idx < IXGBE_MAX_QUEUE_NUM_PER_VF; idx++)
 				if (vfinfo[vf].tx_rate[idx] != 0)
-					ixgbe_set_vf_rate_limit(dev, vf,
+					rte_pmd_ixgbe_set_vf_rate_limit(
+						dev->data->port_id, vf,
 						vfinfo[vf].tx_rate[idx],
 						1 << idx);
 	}
@@ -4883,6 +4884,269 @@ rte_pmd_ixgbe_set_vf_vlan_stripq(uint8_t port, uint16_t vf, uint8_t on)
 	return 0;
 }
 
+int
+rte_pmd_ixgbe_set_vf_rxmode(uint8_t port, uint16_t vf, uint16_t rx_mask, uint8_t on)
+{
+	int val = 0;
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+	struct ixgbe_hw *hw;
+	uint32_t vmolr;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	rte_eth_dev_info_get(port, &dev_info);
+
+	if (strstr(dev_info.driver_name, "ixgbe_vf"))
+		return -ENOTSUP;
+
+	if (vf >= dev_info.max_vfs)
+		return -EINVAL;
+
+	if (on > 1)
+		return -EINVAL;
+
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
+
+	if (hw->mac.type == ixgbe_mac_82598EB) {
+		PMD_INIT_LOG(ERR, "setting VF receive mode set should be done"
+			     " on 82599 hardware and newer");
+		return -ENOTSUP;
+	}
+	if (ixgbe_vmdq_mode_check(hw) < 0)
+		return -ENOTSUP;
+
+	val = ixgbe_convert_vm_rx_mask_to_val(rx_mask, val);
+
+	if (on)
+		vmolr |= val;
+	else
+		vmolr &= ~val;
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
+
+	return 0;
+}
+
+int
+rte_pmd_ixgbe_set_vf_rx(uint8_t port, uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+	uint32_t reg, addr;
+	uint32_t val;
+	const uint8_t bit1 = 0x1;
+	struct ixgbe_hw *hw;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	rte_eth_dev_info_get(port, &dev_info);
+
+	if (strstr(dev_info.driver_name, "ixgbe_vf"))
+		return -ENOTSUP;
+
+	if (vf >= dev_info.max_vfs)
+		return -EINVAL;
+
+	if (on > 1)
+		return -EINVAL;
+
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (ixgbe_vmdq_mode_check(hw) < 0)
+		return -ENOTSUP;
+
+	/* for vf >= 32, set bit in PFVFRE[1], otherwise PFVFRE[0] */
+	if (vf >= 32) {
+		addr = IXGBE_VFRE(1);
+		val = bit1 << (vf - 32);
+	} else {
+		addr = IXGBE_VFRE(0);
+		val = bit1 << vf;
+	}
+
+	reg = IXGBE_READ_REG(hw, addr);
+
+	if (on)
+		reg |= val;
+	else
+		reg &= ~val;
+
+	IXGBE_WRITE_REG(hw, addr, reg);
+
+	return 0;
+}
+
+int
+rte_pmd_ixgbe_set_vf_tx(uint8_t port, uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+	uint32_t reg, addr;
+	uint32_t val;
+	const uint8_t bit1 = 0x1;
+
+	struct ixgbe_hw *hw;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	rte_eth_dev_info_get(port, &dev_info);
+
+	if (strstr(dev_info.driver_name, "ixgbe_vf"))
+		return -ENOTSUP;
+
+	if (vf >= dev_info.max_vfs)
+		return -EINVAL;
+
+	if (on > 1)
+		return -EINVAL;
+
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	if (ixgbe_vmdq_mode_check(hw) < 0)
+		return -ENOTSUP;
+
+	/* for vf >= 32, set bit in PFVFTE[1], otherwise PFVFTE[0] */
+	if (vf >= 32) {
+		addr = IXGBE_VFTE(1);
+		val = bit1 << (vf - 32);
+	} else {
+		addr = IXGBE_VFTE(0);
+		val = bit1 << vf;
+	}
+
+	reg = IXGBE_READ_REG(hw, addr);
+
+	if (on)
+		reg |= val;
+	else
+		reg &= ~val;
+
+	IXGBE_WRITE_REG(hw, addr, reg);
+
+	return 0;
+}
+
+int
+rte_pmd_ixgbe_set_vf_vlan_filter(uint8_t port, uint16_t vlan,
+			uint64_t vf_mask, uint8_t vlan_on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+	int ret = 0;
+	uint16_t vf_idx;
+	struct ixgbe_hw *hw;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	rte_eth_dev_info_get(port, &dev_info);
+
+	if (strstr(dev_info.driver_name, "ixgbe_vf"))
+		return -ENOTSUP;
+
+	if ((vlan > ETHER_MAX_VLAN_ID) || (vf_mask == 0))
+		return -EINVAL;
+
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	if (ixgbe_vmdq_mode_check(hw) < 0)
+		return -ENOTSUP;
+
+	for (vf_idx = 0; vf_idx < 64; vf_idx++) {
+		if (vf_mask & ((uint64_t)(1ULL << vf_idx))) {
+			ret = hw->mac.ops.set_vfta(hw, vlan, vf_idx,
+						   vlan_on, false);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	return ret;
+}
+
+int rte_pmd_ixgbe_set_vf_rate_limit(uint8_t port, uint16_t vf,
+	uint16_t tx_rate, uint64_t q_msk)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+	struct ixgbe_hw *hw;
+	struct ixgbe_vf_info *vfinfo;
+	struct rte_eth_link link;
+	uint8_t  nb_q_per_pool;
+	uint32_t queue_stride;
+	uint32_t queue_idx, idx = 0, vf_idx;
+	uint32_t queue_end;
+	uint16_t total_rate = 0;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	rte_eth_dev_info_get(port, &dev_info);
+	rte_eth_link_get_nowait(port, &link);
+
+	if (strstr(dev_info.driver_name, "ixgbe_vf"))
+		return -ENOTSUP;
+
+	if (vf >= dev_info.max_vfs)
+		return -EINVAL;
+
+	if (tx_rate > link.link_speed)
+		return -EINVAL;
+
+	if (q_msk == 0)
+		return 0;
+
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	vfinfo = *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
+	nb_q_per_pool = RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool;
+	queue_stride = IXGBE_MAX_RX_QUEUE_NUM / RTE_ETH_DEV_SRIOV(dev).active;
+	queue_idx = vf * queue_stride;
+	queue_end = queue_idx + nb_q_per_pool - 1;
+	if (queue_end >= hw->mac.max_tx_queues)
+		return -EINVAL;
+
+	if (vfinfo) {
+		for (vf_idx = 0; vf_idx < dev->pci_dev->max_vfs; vf_idx++) {
+			if (vf_idx == vf)
+				continue;
+			for (idx = 0; idx < RTE_DIM(vfinfo[vf_idx].tx_rate);
+				idx++)
+				total_rate += vfinfo[vf_idx].tx_rate[idx];
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	/* Store tx_rate for this vf. */
+	for (idx = 0; idx < nb_q_per_pool; idx++) {
+		if (((uint64_t)0x1 << idx) & q_msk) {
+			if (vfinfo[vf].tx_rate[idx] != tx_rate)
+				vfinfo[vf].tx_rate[idx] = tx_rate;
+			total_rate += tx_rate;
+		}
+	}
+
+	if (total_rate > dev->data->dev_link.link_speed) {
+		/* Reset stored TX rate of the VF if it causes exceed
+		 * link speed.
+		 */
+		memset(vfinfo[vf].tx_rate, 0, sizeof(vfinfo[vf].tx_rate));
+		return -EINVAL;
+	}
+
+	/* Set RTTBCNRC of each queue/pool for vf X  */
+	for (; queue_idx <= queue_end; queue_idx++) {
+		if (0x1 & q_msk)
+			ixgbe_set_queue_rate_limit(dev, queue_idx, tx_rate);
+		q_msk = q_msk >> 1;
+	}
+
+	return 0;
+}
+
 #define IXGBE_MRCTL_VPME  0x01 /* Virtual Pool Mirroring. */
 #define IXGBE_MRCTL_UPME  0x02 /* Uplink Port Mirroring. */
 #define IXGBE_MRCTL_DPME  0x04 /* Downlink Port Mirroring. */
diff --git a/drivers/net/ixgbe/rte_pmd_ixgbe.h b/drivers/net/ixgbe/rte_pmd_ixgbe.h
index c2fb826..4eb0c9a 100644
--- a/drivers/net/ixgbe/rte_pmd_ixgbe.h
+++ b/drivers/net/ixgbe/rte_pmd_ixgbe.h
@@ -183,6 +183,110 @@ int
 rte_pmd_ixgbe_set_vf_vlan_stripq(uint8_t port, uint16_t vf, uint8_t on);
 
 /**
+* Set RX L2 Filtering mode of a VF of an Ethernet device.
+*
+* @param port
+*   The port identifier of the Ethernet device.
+* @param vf
+*   VF id.
+* @param rx_mode
+*    The RX mode mask, which is one or more of accepting Untagged Packets,
+*    packets that match the PFUTA table, Broadcast and Multicast Promiscuous.
+*    ETH_VMDQ_ACCEPT_UNTAG,ETH_VMDQ_ACCEPT_HASH_UC,
+*    ETH_VMDQ_ACCEPT_BROADCAST and ETH_VMDQ_ACCEPT_MULTICAST will be used
+*    in rx_mode.
+* @param on
+*    1 - Enable a VF RX mode.
+*    0 - Disable a VF RX mode.
+* @return
+*   - (0) if successful.
+*   - (-ENOTSUP) if hardware doesn't support.
+*   - (-ENODEV) if *port_id* invalid.
+*   - (-EINVAL) if bad parameter.
+*/
+int
+rte_pmd_ixgbe_set_vf_rxmode(uint8_t port, uint16_t vf, uint16_t rx_mask, uint8_t on);
+
+/**
+* Enable or disable a VF traffic receive of an Ethernet device.
+*
+* @param port
+*   The port identifier of the Ethernet device.
+* @param vf
+*   VF id.
+* @param on
+*    1 - Enable a VF traffic receive.
+*    0 - Disable a VF traffic receive.
+* @return
+*   - (0) if successful.
+*   - (-ENOTSUP) if hardware doesn't support.
+*   - (-ENODEV) if *port_id* invalid.
+*   - (-EINVAL) if bad parameter.
+*/
+int
+rte_pmd_ixgbe_set_vf_rx(uint8_t port, uint16_t vf, uint8_t on);
+
+/**
+* Enable or disable a VF traffic transmit of the Ethernet device.
+*
+* @param port
+*   The port identifier of the Ethernet device.
+* @param vf
+*   VF id.
+* @param on
+*    1 - Enable a VF traffic transmit.
+*    0 - Disable a VF traffic transmit.
+* @return
+*   - (0) if successful.
+*   - (-ENODEV) if *port_id* invalid.
+*   - (-ENOTSUP) if hardware doesn't support.
+*   - (-EINVAL) if bad parameter.
+*/
+int
+rte_pmd_ixgbe_set_vf_tx(uint8_t port, uint16_t vf, uint8_t on);
+
+/**
+* Enable/Disable hardware VF VLAN filtering by an Ethernet device of
+* received VLAN packets tagged with a given VLAN Tag Identifier.
+*
+* @param port id
+*   The port identifier of the Ethernet device.
+* @param vlan_id
+*   The VLAN Tag Identifier whose filtering must be enabled or disabled.
+* @param vf_mask
+*    Bitmap listing which VFs participate in the VLAN filtering.
+* @param vlan_on
+*    1 - Enable VFs VLAN filtering.
+*    0 - Disable VFs VLAN filtering.
+* @return
+*   - (0) if successful.
+*   - (-ENOTSUP) if hardware doesn't support.
+*   - (-ENODEV) if *port_id* invalid.
+*   - (-EINVAL) if bad parameter.
+*/
+int
+rte_pmd_ixgbe_set_vf_vlan_filter(uint8_t port, uint16_t vlan, uint64_t vf_mask, uint8_t vlan_on);
+
+/**
+ * Set the rate limitation for a vf on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param vf
+ *   VF id.
+ * @param tx_rate
+ *   The tx rate allocated from the total link speed for this VF id.
+ * @param q_msk
+ *   The queue mask which need to set the rate.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_ixgbe_set_vf_rate_limit(uint8_t port, uint16_t vf, uint16_t tx_rate, uint64_t q_msk);
+
+/**
  * Response sent back to ixgbe driver from user app after callback
  */
 enum rte_pmd_ixgbe_mb_event_rsp {
diff --git a/drivers/net/ixgbe/rte_pmd_ixgbe_version.map b/drivers/net/ixgbe/rte_pmd_ixgbe_version.map
index 92434f3..5252bc2 100644
--- a/drivers/net/ixgbe/rte_pmd_ixgbe_version.map
+++ b/drivers/net/ixgbe/rte_pmd_ixgbe_version.map
@@ -15,3 +15,13 @@ DPDK_16.11 {
 	rte_pmd_ixgbe_set_vf_vlan_insert;
 	rte_pmd_ixgbe_set_vf_vlan_stripq;
 } DPDK_2.0;
+
+DPDK_17.02 {
+	global:
+
+	rte_pmd_ixgbe_set_vf_rate_limit;
+	rte_pmd_ixgbe_set_vf_rx;
+	rte_pmd_ixgbe_set_vf_rxmode;
+	rte_pmd_ixgbe_set_vf_tx;
+	rte_pmd_ixgbe_set_vf_vlan_filter;
+} DPDK_16.11;
\ No newline at end of file
-- 
2.10.1

^ permalink raw reply related

* [PATCH v3 2/9] app/testpmd: use ixgbe public functions
From: Bernard Iremonger @ 2016-12-12 13:50 UTC (permalink / raw)
  To: thomas.monjalon, dev; +Cc: Bernard Iremonger
In-Reply-To: <1481304361-16032-1-git-send-email-bernard.iremonger@intel.com>

Use the the following ixgbe public functions:

rte_pmd_ixgbe_set_vf_rate_limit
rte_pmd_ixgbe_set_vf_rx
rte_pmd_ixgbe_set_vf_rxmode
rte_pmd_ixgbe_set_vf_tx
rte_pmd_ixgbe_set_vf_vlan_filter

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 app/test-pmd/cmdline.c |  2 +-
 app/test-pmd/config.c  | 31 +++++++++++--------------------
 2 files changed, 12 insertions(+), 21 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index d03a592..12f799b 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -6708,7 +6708,7 @@ cmd_set_vf_rxmode_parsed(void *parsed_result,
 			rx_mode |= ETH_VMDQ_ACCEPT_MULTICAST;
 	}
 
-	ret = rte_eth_dev_set_vf_rxmode(res->port_id,res->vf_id,rx_mode,(uint8_t)is_on);
+	ret = rte_pmd_ixgbe_set_vf_rxmode(res->port_id, res->vf_id, rx_mode, (uint8_t)is_on);
 	if (ret < 0)
 		printf("bad VF receive mode parameter, return code = %d \n",
 		ret);
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 8cf537d..ea129db 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -92,6 +92,9 @@
 #include <rte_ethdev.h>
 #include <rte_string_fns.h>
 #include <rte_cycles.h>
+#ifdef RTE_LIBRTE_IXGBE_PMD
+#include <rte_pmd_ixgbe.h>
+#endif
 
 #include "testpmd.h"
 
@@ -2332,16 +2335,16 @@ set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on)
 	if (port_id_is_invalid(port_id, ENABLED_WARN))
 		return;
 	if (is_rx)
-		diag = rte_eth_dev_set_vf_rx(port_id,vf,on);
+		diag = rte_pmd_ixgbe_set_vf_rx(port_id, vf, on);
 	else
-		diag = rte_eth_dev_set_vf_tx(port_id,vf,on);
+		diag = rte_pmd_ixgbe_set_vf_tx(port_id, vf, on);
 	if (diag == 0)
 		return;
 	if(is_rx)
-		printf("rte_eth_dev_set_vf_rx for port_id=%d failed "
+		printf("rte_pmd_ixgbe_set_vf_rx for port_id=%d failed "
 	       		"diag=%d\n", port_id, diag);
 	else
-		printf("rte_eth_dev_set_vf_tx for port_id=%d failed "
+		printf("rte_pmd_ixgbe_set_vf_tx for port_id=%d failed "
 	       		"diag=%d\n", port_id, diag);
 
 }
@@ -2355,10 +2358,10 @@ set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on)
 		return;
 	if (vlan_id_is_invalid(vlan_id))
 		return;
-	diag = rte_eth_dev_set_vf_vlan_filter(port_id, vlan_id, vf_mask, on);
+	diag = rte_pmd_ixgbe_set_vf_vlan_filter(port_id, vlan_id, vf_mask, on);
 	if (diag == 0)
 		return;
-	printf("rte_eth_dev_set_vf_vlan_filter for port_id=%d failed "
+	printf("rte_pmd_ixgbe_set_vf_vlan_filter for port_id=%d failed "
 	       "diag=%d\n", port_id, diag);
 }
 
@@ -2388,23 +2391,11 @@ int
 set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk)
 {
 	int diag;
-	struct rte_eth_link link;
-
-	if (q_msk == 0)
-		return 0;
 
-	if (port_id_is_invalid(port_id, ENABLED_WARN))
-		return 1;
-	rte_eth_link_get_nowait(port_id, &link);
-	if (rate > link.link_speed) {
-		printf("Invalid rate value:%u bigger than link speed: %u\n",
-			rate, link.link_speed);
-		return 1;
-	}
-	diag = rte_eth_set_vf_rate_limit(port_id, vf, rate, q_msk);
+	diag = rte_pmd_ixgbe_set_vf_rate_limit(port_id, vf, rate, q_msk);
 	if (diag == 0)
 		return diag;
-	printf("rte_eth_set_vf_rate_limit for port_id=%d failed diag=%d\n",
+	printf("rte_pmd_ixgbe_set_vf_rate_limit for port_id=%d failed diag=%d\n",
 		port_id, diag);
 	return diag;
 }
-- 
2.10.1

^ permalink raw reply related

* [PATCH v3 3/9] app/testpmd: add command for set VF VLAN filter
From: Bernard Iremonger @ 2016-12-12 13:50 UTC (permalink / raw)
  To: thomas.monjalon, dev; +Cc: Bernard Iremonger
In-Reply-To: <1481304361-16032-1-git-send-email-bernard.iremonger@intel.com>

Add the following command to testpmd:
set vf vlan filter <port_id> <vlan_id> <vf_mask> on|off

Add command to the testpmd user guide.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 app/test-pmd/cmdline.c                      | 98 +++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  7 +++
 2 files changed, 105 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 12f799b..947c698 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -291,6 +291,9 @@ static void cmd_help_long_parsed(void *parsed_result,
 
 			"set vf vlan antispoof (port_id) (vf_id) (on|off)\n"
 			"    Set VLAN antispoof for a VF from the PF.\n\n"
+
+			"set vf vlan filter (port_id) (vlan_id) (vf_mask) (on|off)\n"
+			"    Set VLAN filter for a VF pool from the PF.\n\n"
 #endif
 
 			"vlan set filter (on|off) (port_id)\n"
@@ -11139,6 +11142,100 @@ cmdline_parse_inst_t cmd_set_vf_vlan_insert = {
 	},
 };
 
+
+/* vf vlan filter configuration */
+
+/* Common result structure for vf vlan filter */
+struct cmd_vf_vlan_filter_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t filter;
+	uint8_t port_id;
+	uint16_t vlan_id;
+	uint16_t vf_mask;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan filter enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_filter_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_filter_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_filter_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_filter_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_filter_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_filter_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_filter_filter =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_filter_result,
+		 filter, "filter");
+cmdline_parse_token_num_t cmd_vf_vlan_filter_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_filter_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_filter_vlan_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_filter_result,
+		 vlan_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_vlan_filter_vf_mask =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_filter_result,
+		 vf_mask, UINT16);
+cmdline_parse_token_string_t cmd_vf_vlan_filter_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_filter_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_filter_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_filter_result *res = parsed_result;
+	int ret;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	ret = rte_pmd_ixgbe_set_vf_vlan_filter(res->port_id, res->vlan_id, res->vf_mask, is_on);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		printf("invalid vf_mask %d or vlan_id %d\n", res->vf_mask, res->vlan_id);
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", res->port_id);
+		break;
+	case -ENOTSUP:
+		printf("not supported on vf port %d\n", res->port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_filter = {
+	.f = cmd_set_vf_vlan_filter_parsed,
+	.data = NULL,
+	.help_str = "set vf vlan filter <port_id> <vlan_id> <vf_mask> on|off",
+	.tokens = {
+		(void *)&cmd_vf_vlan_filter_set,
+		(void *)&cmd_vf_vlan_filter_vf,
+		(void *)&cmd_vf_vlan_filter_vlan,
+		(void *)&cmd_vf_vlan_filter_filter,
+		(void *)&cmd_vf_vlan_filter_port_id,
+		(void *)&cmd_vf_vlan_filter_vlan_id,
+		(void *)&cmd_vf_vlan_filter_vf_mask,
+		(void *)&cmd_vf_vlan_filter_on_off,
+		NULL,
+	},
+};
+
 /* tx loopback configuration */
 
 /* Common result structure for tx loopback */
@@ -11620,6 +11717,7 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_vf_mac_anti_spoof,
 	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_stripq,
 	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_insert,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_filter,
 	(cmdline_parse_inst_t *)&cmd_set_tx_loopback,
 	(cmdline_parse_inst_t *)&cmd_set_all_queues_drop_en,
 	(cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f1c269a..60dcd91 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -535,6 +535,13 @@ Set VLAN insert for a VF from the PF::
 
    testpmd> set vf vlan insert (port_id) (vf_id) (vlan_id)
 
+vlan set filter (for VF pool)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN filter for a VF pool from the PF::
+
+   testpmd> set vf vlan filter (port_id) (vlan_id) (vf_mask) (on|off)
+
 vlan set antispoof (for VF)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-- 
2.10.1

^ permalink raw reply related

* [PATCH v3 4/9] app/testpmd: add command for set VF receive
From: Bernard Iremonger @ 2016-12-12 13:50 UTC (permalink / raw)
  To: thomas.monjalon, dev; +Cc: Bernard Iremonger
In-Reply-To: <1481304361-16032-1-git-send-email-bernard.iremonger@intel.com>

add the following command to testpmd:

set vf rx <port_id> <vf_id> on|off

add command to the testpmd user guide.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 app/test-pmd/cmdline.c                      | 85 +++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  7 +++
 2 files changed, 92 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 947c698..4424c0a 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -274,6 +274,9 @@ static void cmd_help_long_parsed(void *parsed_result,
 
 			"set vf mac antispoof (port_id) (vf_id) (on|off).\n"
 			"    Set MAC antispoof for a VF from the PF.\n\n"
+
+			"set vf rx (port_id) (vf_id) (on|off).\n"
+			"    Enable or disable RX for a VF from the PF.\n\n"
 #endif
 
 			"vlan set strip (on|off) (port_id)\n"
@@ -11236,6 +11239,87 @@ cmdline_parse_inst_t cmd_set_vf_vlan_filter = {
 	},
 };
 
+/* vf rx configuration */
+
+/* Common result structure for vf rx */
+struct cmd_vf_rx_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t rx;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf rx enable disable */
+cmdline_parse_token_string_t cmd_vf_rx_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_rx_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_rx_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_rx_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_rx_rx =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_rx_result,
+		 rx, "rx");
+cmdline_parse_token_num_t cmd_vf_rx_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_rx_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_rx_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_rx_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_rx_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_rx_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_rx_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_rx_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	ret = rte_pmd_ixgbe_set_vf_rx(res->port_id, res->vf_id, is_on);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", res->port_id);
+		break;
+	case -ENOTSUP:
+		printf("not supported on vf port %d\n", res->port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_vf_rx = {
+	.f = cmd_set_vf_rx_parsed,
+	.data = NULL,
+	.help_str = "set vf rx <port_id> <vf_id> on|off",
+	.tokens = {
+		(void *)&cmd_vf_rx_set,
+		(void *)&cmd_vf_rx_vf,
+		(void *)&cmd_vf_rx_rx,
+		(void *)&cmd_vf_rx_port_id,
+		(void *)&cmd_vf_rx_vf_id,
+		(void *)&cmd_vf_rx_on_off,
+		NULL,
+	},
+};
+
 /* tx loopback configuration */
 
 /* Common result structure for tx loopback */
@@ -11722,6 +11806,7 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_all_queues_drop_en,
 	(cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
 	(cmdline_parse_inst_t *)&cmd_set_vf_mac_addr,
+	(cmdline_parse_inst_t *)&cmd_set_vf_rx,
 #endif
 	NULL,
 };
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 60dcd91..6a058e9 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -507,6 +507,13 @@ Set mac antispoof for a VF from the PF::
 
    testpmd> set vf mac antispoof  (port_id) (vf_id) (on|off)
 
+set rx (for VF)
+~~~~~~~~~~~~~~~
+
+Enable/disable rx for a VF from the PF::
+
+   testpmd> set vf rx (port_id) (vf_id) (on|off)
+
 vlan set strip
 ~~~~~~~~~~~~~~
 
-- 
2.10.1

^ permalink raw reply related

* [PATCH v3 5/9] app/testpmd: add command for set VF transmit
From: Bernard Iremonger @ 2016-12-12 13:50 UTC (permalink / raw)
  To: thomas.monjalon, dev; +Cc: Bernard Iremonger
In-Reply-To: <1481304361-16032-1-git-send-email-bernard.iremonger@intel.com>

add the following command to testpmd:

set vf tx <port_id> <vf_id> on|off

add command to the testpmd user guide.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 app/test-pmd/cmdline.c                      | 85 +++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  7 +++
 2 files changed, 92 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 4424c0a..e385732 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -277,6 +277,9 @@ static void cmd_help_long_parsed(void *parsed_result,
 
 			"set vf rx (port_id) (vf_id) (on|off).\n"
 			"    Enable or disable RX for a VF from the PF.\n\n"
+
+			"set vf tx (port_id) (vf_id) (on|off).\n"
+			"    Enable or disable TX for a VF from the PF.\n\n"
 #endif
 
 			"vlan set strip (on|off) (port_id)\n"
@@ -11320,6 +11323,87 @@ cmdline_parse_inst_t cmd_set_vf_rx = {
 	},
 };
 
+/* vf tx configuration */
+
+/* Common result structure for vf tx */
+struct cmd_vf_tx_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t tx;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf tx enable disable */
+cmdline_parse_token_string_t cmd_vf_tx_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_tx_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_tx_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_tx_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_tx_tx =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_tx_result,
+		 tx, "tx");
+cmdline_parse_token_num_t cmd_vf_tx_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_tx_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_tx_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_tx_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_tx_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_tx_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_tx_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_tx_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	ret = rte_pmd_ixgbe_set_vf_tx(res->port_id, res->vf_id, is_on);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", res->port_id);
+		break;
+	case -ENOTSUP:
+		printf("not supported on vf port %d\n", res->port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_vf_tx = {
+	.f = cmd_set_vf_tx_parsed,
+	.data = NULL,
+	.help_str = "set vf tx <port_id> <vf_id> on|off",
+	.tokens = {
+		(void *)&cmd_vf_tx_set,
+		(void *)&cmd_vf_tx_vf,
+		(void *)&cmd_vf_tx_tx,
+		(void *)&cmd_vf_tx_port_id,
+		(void *)&cmd_vf_tx_vf_id,
+		(void *)&cmd_vf_tx_on_off,
+		NULL,
+	},
+};
+
 /* tx loopback configuration */
 
 /* Common result structure for tx loopback */
@@ -11807,6 +11891,7 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
 	(cmdline_parse_inst_t *)&cmd_set_vf_mac_addr,
 	(cmdline_parse_inst_t *)&cmd_set_vf_rx,
+	(cmdline_parse_inst_t *)&cmd_set_vf_tx,
 #endif
 	NULL,
 };
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 6a058e9..1de4c5f 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -514,6 +514,13 @@ Enable/disable rx for a VF from the PF::
 
    testpmd> set vf rx (port_id) (vf_id) (on|off)
 
+set tx (for VF)
+~~~~~~~~~~~~~~~
+
+Enable/disable tx for a VF from the PF::
+
+   testpmd> set vf tx (port_id) (vf_id) (on|off)
+
 vlan set strip
 ~~~~~~~~~~~~~~
 
-- 
2.10.1

^ permalink raw reply related

* [PATCH v3 6/9] examples/ethtool: use ixgbe public function
From: Bernard Iremonger @ 2016-12-12 13:50 UTC (permalink / raw)
  To: thomas.monjalon, dev; +Cc: Bernard Iremonger
In-Reply-To: <1481304361-16032-1-git-send-email-bernard.iremonger@intel.com>

Replace rte_eth_dev_set_vf_rxmode with rte_pmd_ixgbe_set_vf_rx_mode.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 examples/ethtool/lib/rte_ethtool.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/examples/ethtool/lib/rte_ethtool.c b/examples/ethtool/lib/rte_ethtool.c
index a1f91d4..0e539f7 100644
--- a/examples/ethtool/lib/rte_ethtool.c
+++ b/examples/ethtool/lib/rte_ethtool.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -36,6 +36,7 @@
 #include <rte_version.h>
 #include <rte_ethdev.h>
 #include <rte_ether.h>
+#include <rte_pmd_ixgbe.h>
 #include "rte_ethtool.h"
 
 #define PKTPOOL_SIZE 512
@@ -354,7 +355,7 @@ rte_ethtool_net_set_rx_mode(uint8_t port_id)
 
 	/* Set VF vf_rx_mode, VF unsupport status is discard */
 	for (vf = 0; vf < num_vfs; vf++)
-		rte_eth_dev_set_vf_rxmode(port_id, vf,
+		rte_pmd_ixgbe_set_vf_rxmode(port_id, vf,
 			ETH_VMDQ_ACCEPT_UNTAG, 0);
 
 	/* Enable Rx vlan filter, VF unspport status is discard */
-- 
2.10.1

^ permalink raw reply related

* [PATCH v3 7/9] net/ixgbe: remove static set VF functions
From: Bernard Iremonger @ 2016-12-12 13:50 UTC (permalink / raw)
  To: thomas.monjalon, dev; +Cc: Bernard Iremonger
In-Reply-To: <1481304361-16032-1-git-send-email-bernard.iremonger@intel.com>

remove the following static functions:

ixgbe_set_pool_rx_mode
ixgbe_set_pool_rx
ixgbe_set_pool_tx
ixgbe_set_pool_vlan_filter
ixgbe_set_vf_rate_limit

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 193 ---------------------------------------
 1 file changed, 193 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 37b82a4..8db1410 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -276,12 +276,6 @@ static void ixgbevf_dev_allmulticast_disable(struct rte_eth_dev *dev);
 static int ixgbe_uc_hash_table_set(struct rte_eth_dev *dev, struct
 		ether_addr * mac_addr, uint8_t on);
 static int ixgbe_uc_all_hash_table_set(struct rte_eth_dev *dev, uint8_t on);
-static int  ixgbe_set_pool_rx_mode(struct rte_eth_dev *dev,  uint16_t pool,
-		uint16_t rx_mask, uint8_t on);
-static int ixgbe_set_pool_rx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on);
-static int ixgbe_set_pool_tx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on);
-static int ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
-		uint64_t pool_mask, uint8_t vlan_on);
 static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
 		struct rte_eth_mirror_conf *mirror_conf,
 		uint8_t rule_id, uint8_t on);
@@ -297,8 +291,6 @@ static void ixgbe_configure_msix(struct rte_eth_dev *dev);
 
 static int ixgbe_set_queue_rate_limit(struct rte_eth_dev *dev,
 		uint16_t queue_idx, uint16_t tx_rate);
-static int ixgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf,
-		uint16_t tx_rate, uint64_t q_msk);
 
 static void ixgbevf_add_mac_addr(struct rte_eth_dev *dev,
 				 struct ether_addr *mac_addr,
@@ -568,12 +560,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.uc_all_hash_table_set  = ixgbe_uc_all_hash_table_set,
 	.mirror_rule_set      = ixgbe_mirror_rule_set,
 	.mirror_rule_reset    = ixgbe_mirror_rule_reset,
-	.set_vf_rx_mode       = ixgbe_set_pool_rx_mode,
-	.set_vf_rx            = ixgbe_set_pool_rx,
-	.set_vf_tx            = ixgbe_set_pool_tx,
-	.set_vf_vlan_filter   = ixgbe_set_pool_vlan_filter,
 	.set_queue_rate_limit = ixgbe_set_queue_rate_limit,
-	.set_vf_rate_limit    = ixgbe_set_vf_rate_limit,
 	.reta_update          = ixgbe_dev_rss_reta_update,
 	.reta_query           = ixgbe_dev_rss_reta_query,
 #ifdef RTE_NIC_BYPASS
@@ -4547,132 +4534,6 @@ ixgbe_convert_vm_rx_mask_to_val(uint16_t rx_mask, uint32_t orig_val)
 	return new_val;
 }
 
-static int
-ixgbe_set_pool_rx_mode(struct rte_eth_dev *dev, uint16_t pool,
-			       uint16_t rx_mask, uint8_t on)
-{
-	int val = 0;
-
-	struct ixgbe_hw *hw =
-		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint32_t vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(pool));
-
-	if (hw->mac.type == ixgbe_mac_82598EB) {
-		PMD_INIT_LOG(ERR, "setting VF receive mode set should be done"
-			     " on 82599 hardware and newer");
-		return -ENOTSUP;
-	}
-	if (ixgbe_vmdq_mode_check(hw) < 0)
-		return -ENOTSUP;
-
-	val = ixgbe_convert_vm_rx_mask_to_val(rx_mask, val);
-
-	if (on)
-		vmolr |= val;
-	else
-		vmolr &= ~val;
-
-	IXGBE_WRITE_REG(hw, IXGBE_VMOLR(pool), vmolr);
-
-	return 0;
-}
-
-static int
-ixgbe_set_pool_rx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on)
-{
-	uint32_t reg, addr;
-	uint32_t val;
-	const uint8_t bit1 = 0x1;
-
-	struct ixgbe_hw *hw =
-		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-	if (ixgbe_vmdq_mode_check(hw) < 0)
-		return -ENOTSUP;
-
-	if (pool >= ETH_64_POOLS)
-		return -EINVAL;
-
-	/* for pool >= 32, set bit in PFVFRE[1], otherwise PFVFRE[0] */
-	if (pool >= 32) {
-		addr = IXGBE_VFRE(1);
-		val = bit1 << (pool - 32);
-	} else {
-		addr = IXGBE_VFRE(0);
-		val = bit1 << pool;
-	}
-
-	reg = IXGBE_READ_REG(hw, addr);
-
-	if (on)
-		reg |= val;
-	else
-		reg &= ~val;
-
-	IXGBE_WRITE_REG(hw, addr, reg);
-
-	return 0;
-}
-
-static int
-ixgbe_set_pool_tx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on)
-{
-	uint32_t reg, addr;
-	uint32_t val;
-	const uint8_t bit1 = 0x1;
-
-	struct ixgbe_hw *hw =
-		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-	if (ixgbe_vmdq_mode_check(hw) < 0)
-		return -ENOTSUP;
-
-	if (pool >= ETH_64_POOLS)
-		return -EINVAL;
-
-	/* for pool >= 32, set bit in PFVFTE[1], otherwise PFVFTE[0] */
-	if (pool >= 32) {
-		addr = IXGBE_VFTE(1);
-		val = bit1 << (pool - 32);
-	} else {
-		addr = IXGBE_VFTE(0);
-		val = bit1 << pool;
-	}
-
-	reg = IXGBE_READ_REG(hw, addr);
-
-	if (on)
-		reg |= val;
-	else
-		reg &= ~val;
-
-	IXGBE_WRITE_REG(hw, addr, reg);
-
-	return 0;
-}
-
-static int
-ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
-			uint64_t pool_mask, uint8_t vlan_on)
-{
-	int ret = 0;
-	uint16_t pool_idx;
-	struct ixgbe_hw *hw =
-		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-	if (ixgbe_vmdq_mode_check(hw) < 0)
-		return -ENOTSUP;
-	for (pool_idx = 0; pool_idx < ETH_64_POOLS; pool_idx++) {
-		if (pool_mask & ((uint64_t)(1ULL << pool_idx))) {
-			ret = hw->mac.ops.set_vfta(hw, vlan, pool_idx,
-						   vlan_on, false);
-			if (ret < 0)
-				return ret;
-		}
-	}
-
-	return ret;
-}
 
 int
 rte_pmd_ixgbe_set_vf_vlan_anti_spoof(uint8_t port, uint16_t vf, uint8_t on)
@@ -5628,60 +5489,6 @@ static int ixgbe_set_queue_rate_limit(struct rte_eth_dev *dev,
 	return 0;
 }
 
-static int ixgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf,
-	uint16_t tx_rate, uint64_t q_msk)
-{
-	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct ixgbe_vf_info *vfinfo =
-		*(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
-	uint8_t  nb_q_per_pool = RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool;
-	uint32_t queue_stride =
-		IXGBE_MAX_RX_QUEUE_NUM / RTE_ETH_DEV_SRIOV(dev).active;
-	uint32_t queue_idx = vf * queue_stride, idx = 0, vf_idx;
-	uint32_t queue_end = queue_idx + nb_q_per_pool - 1;
-	uint16_t total_rate = 0;
-
-	if (queue_end >= hw->mac.max_tx_queues)
-		return -EINVAL;
-
-	if (vfinfo != NULL) {
-		for (vf_idx = 0; vf_idx < dev->pci_dev->max_vfs; vf_idx++) {
-			if (vf_idx == vf)
-				continue;
-			for (idx = 0; idx < RTE_DIM(vfinfo[vf_idx].tx_rate);
-				idx++)
-				total_rate += vfinfo[vf_idx].tx_rate[idx];
-		}
-	} else
-		return -EINVAL;
-
-	/* Store tx_rate for this vf. */
-	for (idx = 0; idx < nb_q_per_pool; idx++) {
-		if (((uint64_t)0x1 << idx) & q_msk) {
-			if (vfinfo[vf].tx_rate[idx] != tx_rate)
-				vfinfo[vf].tx_rate[idx] = tx_rate;
-			total_rate += tx_rate;
-		}
-	}
-
-	if (total_rate > dev->data->dev_link.link_speed) {
-		/*
-		 * Reset stored TX rate of the VF if it causes exceed
-		 * link speed.
-		 */
-		memset(vfinfo[vf].tx_rate, 0, sizeof(vfinfo[vf].tx_rate));
-		return -EINVAL;
-	}
-
-	/* Set RTTBCNRC of each queue/pool for vf X  */
-	for (; queue_idx <= queue_end; queue_idx++) {
-		if (0x1 & q_msk)
-			ixgbe_set_queue_rate_limit(dev, queue_idx, tx_rate);
-		q_msk = q_msk >> 1;
-	}
-
-	return 0;
-}
 
 static void
 ixgbevf_add_mac_addr(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
-- 
2.10.1

^ permalink raw reply related

* [PATCH v3 8/9] librte_ether: remove the set VF API's
From: Bernard Iremonger @ 2016-12-12 13:50 UTC (permalink / raw)
  To: thomas.monjalon, dev; +Cc: Bernard Iremonger
In-Reply-To: <1481304361-16032-1-git-send-email-bernard.iremonger@intel.com>

remove the following API's:

rte_eth_dev_set_vf_rxmode
rte_eth_dev_set_vf_rx
rte_eth_dev_set_vf_tx
rte_eth_dev_set_vf_vlan_filter
rte_eth_dev_set_vf_rate_limit

Increment LIBABIVER in Makefile
Remove deprecation notice for removing rte_eth_dev_set_vf_* API's.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 doc/guides/rel_notes/deprecation.rst   |  13 ---
 lib/librte_ether/Makefile              |   4 +-
 lib/librte_ether/rte_ethdev.c          | 129 ------------------------------
 lib/librte_ether/rte_ethdev.h          | 140 ---------------------------------
 lib/librte_ether/rte_ether_version.map |   7 +-
 5 files changed, 3 insertions(+), 290 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 2d17bc6..c897c18 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -38,19 +38,6 @@ Deprecation Notices
   ``_rte_eth_dev_callback_process``. In 17.02 the function will return an ``int``
   instead of ``void`` and a fourth parameter ``void *ret_param`` will be added.
 
-* ethdev: for 17.02 it is planned to deprecate the following five functions
-  and move them in ixgbe:
-
-  ``rte_eth_dev_set_vf_rxmode``
-
-  ``rte_eth_dev_set_vf_rx``
-
-  ``rte_eth_dev_set_vf_tx``
-
-  ``rte_eth_dev_set_vf_vlan_filter``
-
-  ``rte_eth_set_vf_rate_limit``
-
 * ABI changes are planned for 17.02 in the ``rte_mbuf`` structure: some fields
   may be reordered to facilitate the writing of ``data_off``, ``refcnt``, and
   ``nb_segs`` in one operation, because some platforms have an overhead if the
diff --git a/lib/librte_ether/Makefile b/lib/librte_ether/Makefile
index efe1e5f..d23015c 100644
--- a/lib/librte_ether/Makefile
+++ b/lib/librte_ether/Makefile
@@ -1,6 +1,6 @@
 #   BSD LICENSE
 #
-#   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+#   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
 #   All rights reserved.
 #
 #   Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@ CFLAGS += $(WERROR_FLAGS)
 
 EXPORT_MAP := rte_ether_version.map
 
-LIBABIVER := 5
+LIBABIVER := 6
 
 SRCS-y += rte_ethdev.c
 
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 1e0f206..6a93014 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2137,32 +2137,6 @@ rte_eth_dev_default_mac_addr_set(uint8_t port_id, struct ether_addr *addr)
 	return 0;
 }
 
-int
-rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf,
-				uint16_t rx_mode, uint8_t on)
-{
-	uint16_t num_vfs;
-	struct rte_eth_dev *dev;
-	struct rte_eth_dev_info dev_info;
-
-	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
-
-	dev = &rte_eth_devices[port_id];
-	rte_eth_dev_info_get(port_id, &dev_info);
-
-	num_vfs = dev_info.max_vfs;
-	if (vf > num_vfs) {
-		RTE_PMD_DEBUG_TRACE("set VF RX mode:invalid VF id %d\n", vf);
-		return -EINVAL;
-	}
-
-	if (rx_mode == 0) {
-		RTE_PMD_DEBUG_TRACE("set VF RX mode:mode mask ca not be zero\n");
-		return -EINVAL;
-	}
-	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_rx_mode, -ENOTSUP);
-	return (*dev->dev_ops->set_vf_rx_mode)(dev, vf, rx_mode, on);
-}
 
 /*
  * Returns index into MAC address array of addr. Use 00:00:00:00:00:00 to find
@@ -2252,76 +2226,6 @@ rte_eth_dev_uc_all_hash_table_set(uint8_t port_id, uint8_t on)
 	return (*dev->dev_ops->uc_all_hash_table_set)(dev, on);
 }
 
-int
-rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf, uint8_t on)
-{
-	uint16_t num_vfs;
-	struct rte_eth_dev *dev;
-	struct rte_eth_dev_info dev_info;
-
-	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
-
-	dev = &rte_eth_devices[port_id];
-	rte_eth_dev_info_get(port_id, &dev_info);
-
-	num_vfs = dev_info.max_vfs;
-	if (vf > num_vfs) {
-		RTE_PMD_DEBUG_TRACE("port %d: invalid vf id\n", port_id);
-		return -EINVAL;
-	}
-
-	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_rx, -ENOTSUP);
-	return (*dev->dev_ops->set_vf_rx)(dev, vf, on);
-}
-
-int
-rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf, uint8_t on)
-{
-	uint16_t num_vfs;
-	struct rte_eth_dev *dev;
-	struct rte_eth_dev_info dev_info;
-
-	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
-
-	dev = &rte_eth_devices[port_id];
-	rte_eth_dev_info_get(port_id, &dev_info);
-
-	num_vfs = dev_info.max_vfs;
-	if (vf > num_vfs) {
-		RTE_PMD_DEBUG_TRACE("set pool tx:invalid pool id=%d\n", vf);
-		return -EINVAL;
-	}
-
-	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_tx, -ENOTSUP);
-	return (*dev->dev_ops->set_vf_tx)(dev, vf, on);
-}
-
-int
-rte_eth_dev_set_vf_vlan_filter(uint8_t port_id, uint16_t vlan_id,
-			       uint64_t vf_mask, uint8_t vlan_on)
-{
-	struct rte_eth_dev *dev;
-
-	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
-
-	dev = &rte_eth_devices[port_id];
-
-	if (vlan_id > ETHER_MAX_VLAN_ID) {
-		RTE_PMD_DEBUG_TRACE("VF VLAN filter:invalid VLAN id=%d\n",
-			vlan_id);
-		return -EINVAL;
-	}
-
-	if (vf_mask == 0) {
-		RTE_PMD_DEBUG_TRACE("VF VLAN filter:pool_mask can not be 0\n");
-		return -EINVAL;
-	}
-
-	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_filter, -ENOTSUP);
-	return (*dev->dev_ops->set_vf_vlan_filter)(dev, vlan_id,
-						   vf_mask, vlan_on);
-}
-
 int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx,
 					uint16_t tx_rate)
 {
@@ -2352,39 +2256,6 @@ int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx,
 	return (*dev->dev_ops->set_queue_rate_limit)(dev, queue_idx, tx_rate);
 }
 
-int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf, uint16_t tx_rate,
-				uint64_t q_msk)
-{
-	struct rte_eth_dev *dev;
-	struct rte_eth_dev_info dev_info;
-	struct rte_eth_link link;
-
-	if (q_msk == 0)
-		return 0;
-
-	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
-
-	dev = &rte_eth_devices[port_id];
-	rte_eth_dev_info_get(port_id, &dev_info);
-	link = dev->data->dev_link;
-
-	if (vf > dev_info.max_vfs) {
-		RTE_PMD_DEBUG_TRACE("set VF rate limit:port %d: "
-				"invalid vf id=%d\n", port_id, vf);
-		return -EINVAL;
-	}
-
-	if (tx_rate > link.link_speed) {
-		RTE_PMD_DEBUG_TRACE("set VF rate limit:invalid tx_rate=%d, "
-				"bigger than link speed= %d\n",
-				tx_rate, link.link_speed);
-		return -EINVAL;
-	}
-
-	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_rate_limit, -ENOTSUP);
-	return (*dev->dev_ops->set_vf_rate_limit)(dev, vf, tx_rate, q_msk);
-}
-
 int
 rte_eth_mirror_rule_set(uint8_t port_id,
 			struct rte_eth_mirror_conf *mirror_conf,
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 9678179..c602d7d 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1249,39 +1249,11 @@ typedef int (*eth_uc_all_hash_table_set_t)(struct rte_eth_dev *dev,
 				  uint8_t on);
 /**< @internal Set all Unicast Hash bitmap */
 
-typedef int (*eth_set_vf_rx_mode_t)(struct rte_eth_dev *dev,
-				  uint16_t vf,
-				  uint16_t rx_mode,
-				  uint8_t on);
-/**< @internal Set a VF receive mode */
-
-typedef int (*eth_set_vf_rx_t)(struct rte_eth_dev *dev,
-				uint16_t vf,
-				uint8_t on);
-/**< @internal Set a VF receive  mode */
-
-typedef int (*eth_set_vf_tx_t)(struct rte_eth_dev *dev,
-				uint16_t vf,
-				uint8_t on);
-/**< @internal Enable or disable a VF transmit   */
-
-typedef int (*eth_set_vf_vlan_filter_t)(struct rte_eth_dev *dev,
-				  uint16_t vlan,
-				  uint64_t vf_mask,
-				  uint8_t vlan_on);
-/**< @internal Set VF VLAN pool filter */
-
 typedef int (*eth_set_queue_rate_limit_t)(struct rte_eth_dev *dev,
 				uint16_t queue_idx,
 				uint16_t tx_rate);
 /**< @internal Set queue TX rate */
 
-typedef int (*eth_set_vf_rate_limit_t)(struct rte_eth_dev *dev,
-				uint16_t vf,
-				uint16_t tx_rate,
-				uint64_t q_msk);
-/**< @internal Set VF TX rate */
-
 typedef int (*eth_mirror_rule_set_t)(struct rte_eth_dev *dev,
 				  struct rte_eth_mirror_conf *mirror_conf,
 				  uint8_t rule_id,
@@ -1479,16 +1451,11 @@ struct eth_dev_ops {
 	eth_uc_all_hash_table_set_t uc_all_hash_table_set;  /**< Set Unicast hash bitmap */
 	eth_mirror_rule_set_t	   mirror_rule_set;  /**< Add a traffic mirror rule.*/
 	eth_mirror_rule_reset_t	   mirror_rule_reset;  /**< reset a traffic mirror rule.*/
-	eth_set_vf_rx_mode_t       set_vf_rx_mode;   /**< Set VF RX mode */
-	eth_set_vf_rx_t            set_vf_rx;  /**< enable/disable a VF receive */
-	eth_set_vf_tx_t            set_vf_tx;  /**< enable/disable a VF transmit */
-	eth_set_vf_vlan_filter_t   set_vf_vlan_filter;  /**< Set VF VLAN filter */
 	/** Add UDP tunnel port. */
 	eth_udp_tunnel_port_add_t udp_tunnel_port_add;
 	/** Del UDP tunnel port. */
 	eth_udp_tunnel_port_del_t udp_tunnel_port_del;
 	eth_set_queue_rate_limit_t set_queue_rate_limit;   /**< Set queue rate limit */
-	eth_set_vf_rate_limit_t    set_vf_rate_limit;   /**< Set VF rate limit */
 	/** Update redirection table. */
 	reta_update_t reta_update;
 	/** Query redirection table. */
@@ -3403,93 +3370,6 @@ int rte_eth_dev_uc_hash_table_set(uint8_t port,struct ether_addr *addr,
  */
 int rte_eth_dev_uc_all_hash_table_set(uint8_t port,uint8_t on);
 
- /**
- * Set RX L2 Filtering mode of a VF of an Ethernet device.
- *
- * @param port
- *   The port identifier of the Ethernet device.
- * @param vf
- *   VF id.
- * @param rx_mode
- *    The RX mode mask, which  is one or more of  accepting Untagged Packets,
- *    packets that match the PFUTA table, Broadcast and Multicast Promiscuous.
- *    ETH_VMDQ_ACCEPT_UNTAG,ETH_VMDQ_ACCEPT_HASH_UC,
- *    ETH_VMDQ_ACCEPT_BROADCAST and ETH_VMDQ_ACCEPT_MULTICAST will be used
- *    in rx_mode.
- * @param on
- *    1 - Enable a VF RX mode.
- *    0 - Disable a VF RX mode.
- * @return
- *   - (0) if successful.
- *   - (-ENOTSUP) if hardware doesn't support.
- *   - (-ENOTSUP) if hardware doesn't support.
- *   - (-EINVAL) if bad parameter.
- */
-int rte_eth_dev_set_vf_rxmode(uint8_t port, uint16_t vf, uint16_t rx_mode,
-				uint8_t on);
-
-/**
-* Enable or disable a VF traffic transmit of the Ethernet device.
-*
-* @param port
-*   The port identifier of the Ethernet device.
-* @param vf
-*   VF id.
-* @param on
-*    1 - Enable a VF traffic transmit.
-*    0 - Disable a VF traffic transmit.
-* @return
-*   - (0) if successful.
-*   - (-ENODEV) if *port_id* invalid.
-*   - (-ENOTSUP) if hardware doesn't support.
-*   - (-EINVAL) if bad parameter.
-*/
-int
-rte_eth_dev_set_vf_tx(uint8_t port,uint16_t vf, uint8_t on);
-
-/**
-* Enable or disable a VF traffic receive of an Ethernet device.
-*
-* @param port
-*   The port identifier of the Ethernet device.
-* @param vf
-*   VF id.
-* @param on
-*    1 - Enable a VF traffic receive.
-*    0 - Disable a VF traffic receive.
-* @return
-*   - (0) if successful.
-*   - (-ENOTSUP) if hardware doesn't support.
-*   - (-ENODEV) if *port_id* invalid.
-*   - (-EINVAL) if bad parameter.
-*/
-int
-rte_eth_dev_set_vf_rx(uint8_t port,uint16_t vf, uint8_t on);
-
-/**
-* Enable/Disable hardware VF VLAN filtering by an Ethernet device of
-* received VLAN packets tagged with a given VLAN Tag Identifier.
-*
-* @param port id
-*   The port identifier of the Ethernet device.
-* @param vlan_id
-*   The VLAN Tag Identifier whose filtering must be enabled or disabled.
-* @param vf_mask
-*    Bitmap listing which VFs participate in the VLAN filtering.
-* @param vlan_on
-*    1 - Enable VFs VLAN filtering.
-*    0 - Disable VFs VLAN filtering.
-* @return
-*   - (0) if successful.
-*   - (-ENOTSUP) if hardware doesn't support.
-*   - (-ENODEV) if *port_id* invalid.
-*   - (-EINVAL) if bad parameter.
-*/
-int
-rte_eth_dev_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
-				uint64_t vf_mask,
-				uint8_t vlan_on);
-
 /**
  * Set a traffic mirroring rule on an Ethernet device
  *
@@ -3551,26 +3431,6 @@ int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx,
 			uint16_t tx_rate);
 
 /**
- * Set the rate limitation for a vf on an Ethernet device.
- *
- * @param port_id
- *   The port identifier of the Ethernet device.
- * @param vf
- *   VF id.
- * @param tx_rate
- *   The tx rate allocated from the total link speed for this VF id.
- * @param q_msk
- *   The queue mask which need to set the rate.
- * @return
- *   - (0) if successful.
- *   - (-ENOTSUP) if hardware doesn't support this feature.
- *   - (-ENODEV) if *port_id* invalid.
- *   - (-EINVAL) if bad parameter.
- */
-int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf,
-			uint16_t tx_rate, uint64_t q_msk);
-
-/**
  * Initialize bypass logic. This function needs to be called before
  * executing any other bypass API.
  *
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index 72be66d..7594416 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -61,10 +61,6 @@ DPDK_2.2 {
 	rte_eth_dev_set_mtu;
 	rte_eth_dev_set_rx_queue_stats_mapping;
 	rte_eth_dev_set_tx_queue_stats_mapping;
-	rte_eth_dev_set_vf_rx;
-	rte_eth_dev_set_vf_rxmode;
-	rte_eth_dev_set_vf_tx;
-	rte_eth_dev_set_vf_vlan_filter;
 	rte_eth_dev_set_vlan_offload;
 	rte_eth_dev_set_vlan_pvid;
 	rte_eth_dev_set_vlan_strip_on_queue;
@@ -94,7 +90,6 @@ DPDK_2.2 {
 	rte_eth_rx_queue_info_get;
 	rte_eth_rx_queue_setup;
 	rte_eth_set_queue_rate_limit;
-	rte_eth_set_vf_rate_limit;
 	rte_eth_stats;
 	rte_eth_stats_get;
 	rte_eth_stats_reset;
@@ -146,4 +141,4 @@ DPDK_16.11 {
 	rte_eth_dev_pci_probe;
 	rte_eth_dev_pci_remove;
 
-} DPDK_16.07;
+} DPDK_16.07;
\ No newline at end of file
-- 
2.10.1

^ permalink raw reply related

* [PATCH v3 9/9] doc: update release notes
From: Bernard Iremonger @ 2016-12-12 13:50 UTC (permalink / raw)
  To: thomas.monjalon, dev; +Cc: Bernard Iremonger
In-Reply-To: <1481304361-16032-1-git-send-email-bernard.iremonger@intel.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1364 bytes --]

Add release note for removing set VF API's from the ethdev,
renaming the API's and moving them to the ixgbe PMD.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 doc/guides/rel_notes/release_17_02.rst | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 3b65038..d30b258 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -38,6 +38,26 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **Moved five APIs for VF management from the ethdev to the ixgbe PMD.**
+
+  The following five APIs for VF management from the PF have been removed from the ethdev,
+  renamed and added to the ixgbe PMD::
+
+    rte_eth_dev_set_vf_rate_limit
+    rte_eth_dev_set_vf_rx
+    rte_eth_dev_set_vf_rxmode
+    rte_eth_dev_set_vf_tx
+    rte_eth_dev_set_vf_vlan_filter
+
+  The API's have been renamed to the following::
+
+    rte_pmd_ixgbe_set_vf_rate_limit
+    rte_pmd_ixgbe_set_vf_rx
+    rte_pmd_ixgbe_set_vf_rxmode
+    rte_pmd_ixgbe_set_vf_tx
+    rte_pmd_ixgbe_set_vf_vlan_filter
+
+  The declarations for the API’s can be found in ``rte_pmd_ixgbe.h``.
 
 Resolved Issues
 ---------------
-- 
2.10.1

^ permalink raw reply related

* [PATCH v12] net/tap: new TUN/TAP device PMD
From: Keith Wiles @ 2016-12-12 14:24 UTC (permalink / raw)
  To: dev; +Cc: pmatilai, yuanhan.liu, ferruh.yigit, john.mcnamara
In-Reply-To: <1476396234-44694-1-git-send-email-keith.wiles@intel.com>

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.

v12- Fixup minor changes for driver_name and version number
v11- Add the tap.rst to the nic/index.rst file
v10- Change the string name used to allow for multiple devices.
v9 - Fix up the docs to use correct syntax
v8 - Fix issue with tap_tx_queue_setup() not return zero on success.
v7 - Reword the comment in common_base and fix the data->name issue
v6 - fixed the checkpatch issues
v5 - merge in changes from list review see related emails
     fixed many minor edits
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 <keith.wiles@intel.com>
---
 MAINTAINERS                             |   5 +
 config/common_base                      |   9 +
 config/common_linuxapp                  |   1 +
 doc/guides/nics/index.rst               |   1 +
 doc/guides/nics/tap.rst                 | 136 ++++++
 drivers/net/Makefile                    |   1 +
 drivers/net/tap/Makefile                |  57 +++
 drivers/net/tap/rte_eth_tap.c           | 765 ++++++++++++++++++++++++++++++++
 drivers/net/tap/rte_pmd_tap_version.map |   4 +
 mk/rte.app.mk                           |   1 +
 10 files changed, 980 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 26d9590..842fb6d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -398,6 +398,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 <keith.wiles@intel.com>
+F: drivers/net/tap
+F: doc/guides/nics/tap.rst
+
 Null Networking PMD
 M: Tetsuya Mukawa <mtetsuyah@gmail.com>
 F: drivers/net/null/
diff --git a/config/common_base b/config/common_base
index 652a839..eb51cdb 100644
--- a/config/common_base
+++ b/config/common_base
@@ -590,3 +590,12 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
 CONFIG_RTE_TEST_PMD=y
 CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
 CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the TAP PMD
+#
+# The TAP PMD is currently only built for Linux and the
+# option is enabled by default in common_linuxapp file,
+# set to 'n' in the common_base file.
+#
+CONFIG_RTE_LIBRTE_PMD_TAP=n
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 2483dfa..782b503 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -44,3 +44,4 @@ 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
diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst
index 92d56a5..af92529 100644
--- a/doc/guides/nics/index.rst
+++ b/doc/guides/nics/index.rst
@@ -51,6 +51,7 @@ Network Interface Controller Drivers
     nfp
     qede
     szedata2
+    tap
     thunderx
     virtio
     vhost
diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst
new file mode 100644
index 0000000..622b9e7
--- /dev/null
+++ b/doc/guides/nics/tap.rst
@@ -0,0 +1,136 @@
+..  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=net_tap`` option on the DPDK application command line. Each
+``--vdev=net_tap`` option give will create an interface named dtap0, dtap1,
+and so on.
+
+The interfaced name can be changed by adding the ``iface=foo0``, for example::
+
+   --vdev=net_tap,iface=foo0 --vdev=net_tap,iface=foo1, ...
+
+Also the speed of the interface can be changed from 10G to whatever number
+needed, but the interface does not enforce that speed, for example::
+
+   --vdev=net_tap,iface=foo0,speed=25000
+
+After the DPDK application is started you can send and receive packets on the
+interface using the standard rx_burst/tx_burst APIs in DPDK. From the host
+point of view you can use any host tool like tcpdump, Wireshark, ping, Pktgen
+and others to communicate with the DPDK application. The DPDK application may
+not understand network protocols like IPv4/6, UDP or TCP unless the
+application has been written to understand these protocols.
+
+If you need the interface as a real network interface meaning running and has
+a valid IP address then you can do this with the following commands::
+
+   sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0
+   sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1
+
+Please change the IP addresses as you see fit.
+
+If routing is enabled on the host you can also communicate with the DPDK App
+over the internet via a standard socket layer application as long as you
+account for the protocol handing in the application.
+
+If you have a Network Stack in your DPDK application or something like it you
+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.
+
+Example
+-------
+
+The following is a simple example of using the TUN/TAP PMD with the Pktgen
+packet generator. It requires that the ``socat`` utility is installed on the
+test system.
+
+Build DPDK, then pull down Pktgen and build pktgen using the DPDK SDK/Target
+used to build the dpdk you pulled down.
+
+Run pktgen from the pktgen directory in a terminal with a commandline like the
+following::
+
+    sudo ./app/app/x86_64-native-linuxapp-gcc/app/pktgen -l 1-5 -n 4        \
+     --proc-type auto --log-level 8 --socket-mem 512,512 --file-prefix pg   \
+     --vdev=net_tap --vdev=net_tap -b 05:00.0 -b 05:00.1                    \
+     -b 04:00.0 -b 04:00.1 -b 04:00.2 -b 04:00.3                            \
+     -b 81:00.0 -b 81:00.1 -b 81:00.2 -b 81:00.3                            \
+     -b 82:00.0 -b 83:00.0 -- -T -P -m [2:3].0 -m [4:5].1                   \
+     -f themes/black-yellow.theme
+
+.. Note:
+
+   Change the ``-b`` options to blacklist all of your physical ports. The
+   following command line is all one line.
+
+   Also, ``-f themes/black-yellow.theme`` is optional if the default colors
+   work on your system configuration. See the Pktgen docs for more
+   information.
+
+Verify with ``ifconfig -a`` command in a different xterm window, should have a
+``dtap0`` and ``dtap1`` interfaces created.
+
+Next set the links for the two interfaces to up via the commands below::
+
+    sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0
+    sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1
+
+Then use socat to create a loopback for the two interfaces::
+
+    sudo socat interface:dtap0 interface:dtap1
+
+Then on the Pktgen command line interface you can start sending packets using
+the commands ``start 0`` and ``start 1`` or you can start both at the same
+time with ``start all``. The command ``str`` is an alias for ``start all`` and
+``stp`` is an alias for ``stop all``.
+
+While running you should see the 64 byte counters increasing to verify the
+traffic is being looped back. You can use ``set all size XXX`` to change the
+size of the packets after you stop the traffic. Use the pktgen ``help``
+command to see a list of all commands. You can also use the ``-f`` option to
+load commands at startup.
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index bc93230..e366a85 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -51,6 +51,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += pcap
 DIRS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += ring
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += szedata2
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += tap
 DIRS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += thunderx
 DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3
diff --git a/drivers/net/tap/Makefile b/drivers/net/tap/Makefile
new file mode 100644
index 0000000..e18f30c
--- /dev/null
+++ b/drivers/net/tap/Makefile
@@ -0,0 +1,57 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 Intel Corporation. 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.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_tap.a
+
+EXPORT_MAP := rte_pmd_tap_version.map
+
+LIBABIVER := 1
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += rte_eth_tap.c
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mempool
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
new file mode 100644
index 0000000..d5e2fc3
--- /dev/null
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -0,0 +1,765 @@
+/*-
+ *   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.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_vdev.h>
+#include <rte_kvargs.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <poll.h>
+#include <arpa/inet.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <linux/if_ether.h>
+#include <fcntl.h>
+
+/* Linux based path to the TUN device */
+#define TUN_TAP_DEV_PATH        "/dev/net/tun"
+#define DEFAULT_TAP_NAME        "dtap"
+
+#define ETH_TAP_IFACE_ARG       "iface"
+#define ETH_TAP_SPEED_ARG       "speed"
+
+#define RTE_PMD_TAP_MAX_QUEUES	16
+
+static const char *valid_arguments[] = {
+	ETH_TAP_IFACE_ARG,
+	ETH_TAP_SPEED_ARG,
+	NULL
+};
+
+static const char *drivername = "Tap PMD";
+static int tap_unit;
+
+static struct rte_eth_link pmd_link = {
+	.link_speed = ETH_SPEED_NUM_10G,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = ETH_LINK_DOWN,
+	.link_autoneg = ETH_LINK_SPEED_AUTONEG
+};
+
+struct pkt_stats {
+	uint64_t opackets;		/* Number of output packets */
+	uint64_t ipackets;		/* Number of input packets */
+	uint64_t obytes;		/* Number of bytes on output */
+	uint64_t ibytes;		/* Number of bytes on input */
+	uint64_t errs;			/* Number of error packets */
+};
+
+struct rx_queue {
+	struct rte_mempool *mp;		/* Mempool for RX packets */
+	uint16_t in_port;		/* Port ID */
+	int fd;
+
+	struct pkt_stats stats;		/* Stats for this RX queue */
+};
+
+struct tx_queue {
+	int fd;
+	struct pkt_stats stats;		/* Stats for this TX queue */
+};
+
+struct pmd_internals {
+	char name[RTE_ETH_NAME_MAX_LEN];	/* Internal Tap device name */
+	uint16_t nb_queues;		/* Number of queues supported */
+	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)
+{
+	struct ifreq ifr;
+	unsigned int features;
+	int fd;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+
+	ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+	if (name && name[0])
+		strncpy(ifr.ifr_name, name, IFNAMSIZ);
+
+	fd = open(TUN_TAP_DEV_PATH, O_RDWR);
+	if (fd < 0) {
+		RTE_LOG(ERR, PMD, "Unable to create TAP interface");
+		goto error;
+	}
+
+	/* Grab the TUN features to verify we can work */
+	if (ioctl(fd, TUNGETFEATURES, &features) < 0) {
+		RTE_LOG(ERR, PMD, "Unable to get TUN/TAP features\n");
+		goto error;
+	}
+	RTE_LOG(DEBUG, PMD, "TUN/TAP Features %08x\n", features);
+
+	if (!(features & IFF_MULTI_QUEUE) && (RTE_PMD_TAP_MAX_QUEUES > 1)) {
+		RTE_LOG(DEBUG, PMD, "TUN/TAP device only one queue\n");
+		goto error;
+	} else if ((features & IFF_ONE_QUEUE) &&
+			(RTE_PMD_TAP_MAX_QUEUES == 1)) {
+		ifr.ifr_flags |= IFF_ONE_QUEUE;
+		RTE_LOG(DEBUG, PMD, "Single queue only support\n");
+	} else {
+		ifr.ifr_flags |= IFF_MULTI_QUEUE;
+		RTE_LOG(DEBUG, PMD, "Multi-queue support for %d queues\n",
+			RTE_PMD_TAP_MAX_QUEUES);
+	}
+
+	/* Set the TUN/TAP configuration and get the name if needed */
+	if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) {
+		RTE_LOG(ERR, PMD, "Unable to set TUNSETIFF for %s\n",
+			ifr.ifr_name);
+		perror("TUNSETIFF");
+		goto error;
+	}
+
+	/* Always set the file descriptor to non-blocking */
+	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))
+		snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", ifr.ifr_name);
+
+	return fd;
+
+error:
+	if (fd > 0)
+		close(fd);
+	return -1;
+}
+
+/* Callback to handle the rx burst of packets to the correct interface and
+ * file descriptor(s) in a multi-queue setup.
+ */
+static uint16_t
+pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+	int len;
+	struct rte_mbuf *mbuf;
+	struct rx_queue *rxq = queue;
+	uint16_t num_rx;
+	unsigned long num_rx_bytes = 0;
+
+	for (num_rx = 0; num_rx < nb_pkts; ) {
+		/* allocate the next mbuf */
+		mbuf = rte_pktmbuf_alloc(rxq->mp);
+		if (unlikely(!mbuf)) {
+			RTE_LOG(WARNING, PMD, "Unable to allocate mbuf\n");
+			break;
+		}
+
+		len = read(rxq->fd, rte_pktmbuf_mtod(mbuf, char *),
+			   rte_pktmbuf_tailroom(mbuf));
+		if (len <= 0) {
+			rte_pktmbuf_free(mbuf);
+			break;
+		}
+
+		mbuf->data_len = len;
+		mbuf->pkt_len = len;
+		mbuf->port = rxq->in_port;
+
+		/* account for the receive frame */
+		bufs[num_rx++] = mbuf;
+		num_rx_bytes += mbuf->pkt_len;
+	}
+	rxq->stats.ipackets += num_rx;
+	rxq->stats.ibytes += num_rx_bytes;
+
+	return num_rx;
+}
+
+/* Callback to handle sending packets from the tap interface
+ */
+static uint16_t
+pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+	struct rte_mbuf *mbuf;
+	struct tx_queue *txq = queue;
+	struct pollfd pfd;
+	uint16_t num_tx = 0;
+	unsigned long num_tx_bytes = 0;
+	int i, n;
+
+	if (unlikely(nb_pkts == 0))
+		return 0;
+
+	pfd.events = POLLOUT;
+	pfd.fd = txq->fd;
+	for (i = 0; i < nb_pkts; i++) {
+		n = poll(&pfd, 1, 0);
+
+		if (n <= 0)
+			break;
+
+		if (pfd.revents & POLLOUT) {
+			/* copy the tx frame data */
+			mbuf = bufs[num_tx];
+			n = write(pfd.fd, rte_pktmbuf_mtod(mbuf, void*),
+				  rte_pktmbuf_pkt_len(mbuf));
+			if (n <= 0)
+				break;
+
+			num_tx++;
+			num_tx_bytes += mbuf->pkt_len;
+			rte_pktmbuf_free(mbuf);
+		}
+	}
+
+	txq->stats.opackets += num_tx;
+	txq->stats.errs += nb_pkts - num_tx;
+	txq->stats.obytes += num_tx_bytes;
+
+	return num_tx;
+}
+
+static int
+tap_dev_start(struct rte_eth_dev *dev)
+{
+	/* Force the Link up */
+	dev->data->dev_link.link_status = ETH_LINK_UP;
+
+	return 0;
+}
+
+/* This function gets called when the current port gets stopped.
+ */
+static void
+tap_dev_stop(struct rte_eth_dev *dev)
+{
+	int i;
+	struct pmd_internals *internals = dev->data->dev_private;
+
+	for (i = 0; i < internals->nb_queues; i++)
+		if (internals->fds[i] != -1)
+			close(internals->fds[i]);
+
+	dev->data->dev_link.link_status = ETH_LINK_DOWN;
+}
+
+static int
+tap_dev_configure(struct rte_eth_dev *dev __rte_unused)
+{
+	return 0;
+}
+
+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;
+	dev_info->if_index = internals->if_index;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)ETHER_MAX_VLAN_FRAME_LEN;
+	dev_info->max_rx_queues = internals->nb_queues;
+	dev_info->max_tx_queues = internals->nb_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+tap_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *tap_stats)
+{
+	unsigned int i, imax;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	unsigned long rx_bytes_total = 0, tx_bytes_total = 0;
+	const struct pmd_internals *pmd = dev->data->dev_private;
+
+	imax = (pmd->nb_queues < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
+		pmd->nb_queues : RTE_ETHDEV_QUEUE_STAT_CNTRS;
+
+	for (i = 0; i < imax; i++) {
+		tap_stats->q_ipackets[i] = pmd->rxq[i].stats.ipackets;
+		tap_stats->q_ibytes[i] = pmd->rxq[i].stats.ibytes;
+		rx_total += tap_stats->q_ipackets[i];
+		rx_bytes_total += tap_stats->q_ibytes[i];
+	}
+
+	for (i = 0; i < imax; i++) {
+		tap_stats->q_opackets[i] = pmd->txq[i].stats.opackets;
+		tap_stats->q_errors[i] = pmd->txq[i].stats.errs;
+		tap_stats->q_obytes[i] = pmd->txq[i].stats.obytes;
+		tx_total += tap_stats->q_opackets[i];
+		tx_err_total += tap_stats->q_errors[i];
+		tx_bytes_total += tap_stats->q_obytes[i];
+	}
+
+	tap_stats->ipackets = rx_total;
+	tap_stats->ibytes = rx_bytes_total;
+	tap_stats->opackets = tx_total;
+	tap_stats->oerrors = tx_err_total;
+	tap_stats->obytes = tx_bytes_total;
+}
+
+static void
+tap_stats_reset(struct rte_eth_dev *dev)
+{
+	int i;
+	struct pmd_internals *pmd = dev->data->dev_private;
+
+	for (i = 0; i < pmd->nb_queues; i++) {
+		pmd->rxq[i].stats.ipackets = 0;
+		pmd->rxq[i].stats.ibytes = 0;
+	}
+
+	for (i = 0; i < pmd->nb_queues; i++) {
+		pmd->txq[i].stats.opackets = 0;
+		pmd->txq[i].stats.errs = 0;
+		pmd->txq[i].stats.obytes = 0;
+	}
+}
+
+static void
+tap_dev_close(struct rte_eth_dev *dev __rte_unused)
+{
+}
+
+static void
+tap_rx_queue_release(void *queue)
+{
+	struct rx_queue *rxq = queue;
+
+	if (rxq && (rxq->fd > 0)) {
+		close(rxq->fd);
+		rxq->fd = -1;
+	}
+}
+
+static void
+tap_tx_queue_release(void *queue)
+{
+	struct tx_queue *txq = queue;
+
+	if (txq && (txq->fd > 0)) {
+		close(txq->fd);
+		txq->fd = -1;
+	}
+}
+
+static int
+tap_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused)
+{
+	return 0;
+}
+
+static int
+tap_setup_queue(struct rte_eth_dev *dev,
+		struct pmd_internals *internals,
+		uint16_t qid)
+{
+	struct rx_queue *rx = &internals->rxq[qid];
+	struct tx_queue *tx = &internals->txq[qid];
+	int fd;
+
+	fd = rx->fd;
+	if (fd < 0) {
+		fd = tx->fd;
+		if (fd < 0) {
+			RTE_LOG(INFO, PMD, "Add queue to TAP %s for qid %d\n",
+				dev->data->name, qid);
+			fd = tun_alloc(dev->data->name);
+			if (fd < 0) {
+				RTE_LOG(ERR, PMD, "tun_alloc(%s) failed\n",
+					dev->data->name);
+				return -1;
+			}
+		}
+	}
+	dev->data->rx_queues[qid] = rx;
+	dev->data->tx_queues[qid] = tx;
+
+	rx->fd = fd;
+	tx->fd = fd;
+
+	return fd;
+}
+
+static int
+tap_rx_queue_setup(struct rte_eth_dev *dev,
+		   uint16_t rx_queue_id,
+		   uint16_t nb_rx_desc __rte_unused,
+		   unsigned int socket_id __rte_unused,
+		   const struct rte_eth_rxconf *rx_conf __rte_unused,
+		   struct rte_mempool *mp)
+{
+	struct pmd_internals *internals = dev->data->dev_private;
+	uint16_t buf_size;
+	int fd;
+
+	if ((rx_queue_id >= internals->nb_queues) || !mp) {
+		RTE_LOG(ERR, PMD, "nb_queues %d mp %p\n",
+			internals->nb_queues, mp);
+		return -1;
+	}
+
+	internals->rxq[rx_queue_id].mp = mp;
+	internals->rxq[rx_queue_id].in_port = dev->data->port_id;
+
+	/* Now get the space available for data in the mbuf */
+	buf_size = (uint16_t)(rte_pktmbuf_data_room_size(mp) -
+				RTE_PKTMBUF_HEADROOM);
+
+	if (buf_size < ETH_FRAME_LEN) {
+		RTE_LOG(ERR, PMD,
+			"%s: %d bytes will not fit in mbuf (%d bytes)\n",
+			dev->data->name, ETH_FRAME_LEN, buf_size);
+		return -ENOMEM;
+	}
+
+	fd = tap_setup_queue(dev, internals, rx_queue_id);
+	if (fd == -1)
+		return -1;
+
+	internals->fds[rx_queue_id] = fd;
+	RTE_LOG(INFO, PMD, "RX TAP device name %s, qid %d on fd %d\n",
+		dev->data->name, rx_queue_id, internals->rxq[rx_queue_id].fd);
+
+	return 0;
+}
+
+static int
+tap_tx_queue_setup(struct rte_eth_dev *dev,
+		   uint16_t tx_queue_id,
+		   uint16_t nb_tx_desc __rte_unused,
+		   unsigned int socket_id __rte_unused,
+		   const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct pmd_internals *internals = dev->data->dev_private;
+	int ret;
+
+	if (tx_queue_id >= internals->nb_queues)
+		return -1;
+
+	ret = tap_setup_queue(dev, internals, tx_queue_id);
+	if (ret == -1)
+		return -1;
+
+	RTE_LOG(INFO, PMD, "TX TAP device name %s, qid %d on fd %d\n",
+		dev->data->name, tx_queue_id, internals->txq[tx_queue_id].fd);
+
+	return 0;
+}
+
+static const struct eth_dev_ops ops = {
+	.dev_start              = tap_dev_start,
+	.dev_stop               = tap_dev_stop,
+	.dev_close              = tap_dev_close,
+	.dev_configure          = tap_dev_configure,
+	.dev_infos_get          = tap_dev_info,
+	.rx_queue_setup         = tap_rx_queue_setup,
+	.tx_queue_setup         = tap_tx_queue_setup,
+	.rx_queue_release       = tap_rx_queue_release,
+	.tx_queue_release       = tap_tx_queue_release,
+	.link_update            = tap_link_update,
+	.stats_get              = tap_stats_get,
+	.stats_reset            = tap_stats_reset,
+};
+
+static int
+pmd_mac_address(int fd, struct rte_eth_dev *dev, struct ether_addr *addr)
+{
+	struct ifreq ifr;
+
+	if ((fd <= 0) || !dev || !addr)
+		return -1;
+
+	memset(&ifr, 0, sizeof(ifr));
+
+	if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
+		RTE_LOG(ERR, PMD, "ioctl failed (SIOCGIFHWADDR) (%s)\n",
+			ifr.ifr_name);
+		return -1;
+	}
+
+	/* Set the host based MAC address to this special MAC format */
+	ifr.ifr_hwaddr.sa_data[0] = 'T';
+	ifr.ifr_hwaddr.sa_data[1] = 'a';
+	ifr.ifr_hwaddr.sa_data[2] = 'p';
+	ifr.ifr_hwaddr.sa_data[3] = '-';
+	ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
+	ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
+	if (ioctl(fd, SIOCSIFHWADDR, &ifr) == -1) {
+		RTE_LOG(ERR, PMD, "%s: ioctl failed (SIOCSIFHWADDR) (%s)\n",
+			dev->data->name, ifr.ifr_name);
+		return -1;
+	}
+
+	/* Set the local application MAC address, needs to be different then
+	 * the host based MAC address.
+	 */
+	ifr.ifr_hwaddr.sa_data[0] = 'd';
+	ifr.ifr_hwaddr.sa_data[1] = 'n';
+	ifr.ifr_hwaddr.sa_data[2] = 'e';
+	ifr.ifr_hwaddr.sa_data[3] = 't';
+	ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
+	ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
+	rte_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+
+	return 0;
+}
+
+static int
+eth_dev_tap_create(const char *name, char *tap_name)
+{
+	int numa_node = rte_socket_id();
+	struct rte_eth_dev *dev = NULL;
+	struct pmd_internals *pmd = NULL;
+	struct rte_eth_dev_data *data = NULL;
+	int i, fd = -1;
+
+	RTE_LOG(INFO, PMD,
+		"%s: Create TAP Ethernet device with %d queues on numa %u\n",
+		 name, RTE_PMD_TAP_MAX_QUEUES, rte_socket_id());
+
+	data = rte_zmalloc_socket(tap_name, sizeof(*data), 0, numa_node);
+	if (!data) {
+		RTE_LOG(INFO, PMD, "Failed to allocate data\n");
+		goto error_exit;
+	}
+
+	pmd = rte_zmalloc_socket(tap_name, sizeof(*pmd), 0, numa_node);
+	if (!pmd) {
+		RTE_LOG(INFO, PMD, "Unable to allocate internal struct\n");
+		goto error_exit;
+	}
+
+	/* Use the name and not the tap_name */
+	dev = rte_eth_dev_allocate(tap_name);
+	if (!dev) {
+		RTE_LOG(INFO, PMD, "Unable to allocate device struct\n");
+		goto error_exit;
+	}
+
+	snprintf(pmd->name, sizeof(pmd->name), "%s", tap_name);
+
+	pmd->nb_queues = RTE_PMD_TAP_MAX_QUEUES;
+
+	/* Setup some default values */
+	data->dev_private = pmd;
+	data->port_id = dev->data->port_id;
+	data->dev_flags = RTE_ETH_DEV_DETACHABLE;
+	data->kdrv = RTE_KDRV_NONE;
+	data->drv_name = drivername;
+	data->numa_node = numa_node;
+
+	data->dev_link = pmd_link;
+	data->mac_addrs = &pmd->eth_addr;
+	data->nb_rx_queues = pmd->nb_queues;
+	data->nb_tx_queues = pmd->nb_queues;
+	data->drv_name = drivername;
+
+	dev->data = data;
+	dev->dev_ops = &ops;
+	dev->driver = NULL;
+	dev->rx_pkt_burst = pmd_rx_burst;
+	dev->tx_pkt_burst = pmd_tx_burst;
+	snprintf(dev->data->name, sizeof(dev->data->name), "%s", name);
+
+	/* Create the first Tap device */
+	fd = tun_alloc(tap_name);
+	if (fd < 0) {
+		RTE_LOG(INFO, PMD, "tun_alloc() failed\n");
+		goto error_exit;
+	}
+
+	/* Presetup the fds to -1 as being not working */
+	for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) {
+		pmd->fds[i] = -1;
+		pmd->rxq[i].fd = -1;
+		pmd->txq[i].fd = -1;
+	}
+
+	/* Take the TUN/TAP fd and place in the first location */
+	pmd->rxq[0].fd = fd;
+	pmd->txq[0].fd = fd;
+	pmd->fds[0] = fd;
+
+	if (pmd_mac_address(fd, dev, &pmd->eth_addr) < 0) {
+		RTE_LOG(INFO, PMD, "Unable to get MAC address\n");
+		goto error_exit;
+	}
+
+	return 0;
+
+error_exit:
+	RTE_PMD_DEBUG_TRACE("Unable to initialize %s\n", name);
+
+	rte_free(data);
+	rte_free(pmd);
+
+	rte_eth_dev_release_port(dev);
+
+	return -EINVAL;
+}
+
+static int
+set_interface_name(const char *key __rte_unused,
+		   const char *value,
+		   void *extra_args)
+{
+	char *name = (char *)extra_args;
+
+	if (value)
+		snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", value);
+	else
+		snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s%d",
+			 DEFAULT_TAP_NAME, (tap_unit - 1));
+
+	return 0;
+}
+
+static int
+set_interface_speed(const char *key __rte_unused,
+		    const char *value,
+		    void *extra_args)
+{
+	*(int *)extra_args = (value) ? atoi(value) : ETH_SPEED_NUM_10G;
+
+	return 0;
+}
+
+/* Open a TAP interface device.
+ */
+static int
+rte_pmd_tap_probe(const char *name, const char *params)
+{
+	int ret;
+	struct rte_kvargs *kvlist = NULL;
+	int speed;
+	char tap_name[RTE_ETH_NAME_MAX_LEN];
+
+	speed = ETH_SPEED_NUM_10G;
+	snprintf(tap_name, sizeof(tap_name), "%s%d",
+		 DEFAULT_TAP_NAME, tap_unit++);
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_tap for %s as %s\n",
+		name, tap_name);
+
+	if (params && (params[0] != '\0')) {
+		RTE_LOG(INFO, PMD, "paramaters (%s)\n", params);
+
+		kvlist = rte_kvargs_parse(params, valid_arguments);
+		if (kvlist) {
+			if (rte_kvargs_count(kvlist, ETH_TAP_SPEED_ARG) == 1) {
+				ret = rte_kvargs_process(kvlist,
+							 ETH_TAP_SPEED_ARG,
+							 &set_interface_speed,
+							 &speed);
+				if (ret == -1)
+					goto leave;
+			}
+
+			if (rte_kvargs_count(kvlist, ETH_TAP_IFACE_ARG) == 1) {
+				ret = rte_kvargs_process(kvlist,
+							 ETH_TAP_IFACE_ARG,
+							 &set_interface_name,
+							 tap_name);
+				if (ret == -1)
+					goto leave;
+			}
+		}
+	}
+	pmd_link.link_speed = speed;
+
+	ret = eth_dev_tap_create(name, tap_name);
+
+leave:
+	if (ret == -1) {
+		RTE_LOG(INFO, PMD, "Failed to create pmd for %s as %s\n",
+			name, tap_name);
+		tap_unit--;		/* Restore the unit number */
+	}
+	rte_kvargs_free(kvlist);
+
+	return ret;
+}
+
+/* detach a TAP device.
+ */
+static int
+rte_pmd_tap_remove(const char *name)
+{
+	struct rte_eth_dev *eth_dev = NULL;
+	struct pmd_internals *internals;
+	int i;
+
+	RTE_LOG(INFO, PMD, "Closing TUN/TAP Ethernet device on numa %u\n",
+		rte_socket_id());
+
+	/* find the ethdev entry */
+	eth_dev = rte_eth_dev_allocated(name);
+	if (!eth_dev)
+		return 0;
+
+	internals = eth_dev->data->dev_private;
+	for (i = 0; i < internals->nb_queues; i++)
+		if (internals->fds[i] != -1)
+			close(internals->fds[i]);
+
+	rte_free(eth_dev->data->dev_private);
+	rte_free(eth_dev->data);
+
+	rte_eth_dev_release_port(eth_dev);
+
+	return 0;
+}
+
+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_PARAM_STRING(net_tap, "iface=<string>,speed=N");
diff --git a/drivers/net/tap/rte_pmd_tap_version.map b/drivers/net/tap/rte_pmd_tap_version.map
new file mode 100644
index 0000000..61463bf
--- /dev/null
+++ b/drivers/net/tap/rte_pmd_tap_version.map
@@ -0,0 +1,4 @@
+DPDK_16.11 {
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index f75f0e2..02c32ae 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -124,6 +124,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP)       += -lrte_pmd_pcap -lpcap
 _LDLIBS-$(CONFIG_RTE_LIBRTE_QEDE_PMD)       += -lrte_pmd_qede
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_RING)       += -lrte_pmd_ring
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2)   += -lrte_pmd_szedata2 -lsze2
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_TAP)        += -lrte_pmd_tap
 _LDLIBS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += -lrte_pmd_thunderx_nicvf -lm
 _LDLIBS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD)     += -lrte_pmd_virtio
 ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y)
-- 
2.8.0.GIT

^ permalink raw reply related

* Re: [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
From: Jianbo Liu @ 2016-12-12 14:35 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: David Marchand, dev@dpdk.org, Thomas Monjalon
In-Reply-To: <1697fe66-962d-0848-5e68-615249b52dad@nxp.com>

Hi Shreyansh,

On 7 December 2016 at 21:10, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> On Wednesday 07 December 2016 05:47 PM, David Marchand wrote:
>>
>> Hello Shreyansh,
>>
>> On Wed, Dec 7, 2016 at 10:55 AM, Shreyansh Jain <shreyansh.jain@nxp.com>
>> wrote:
>>>
>>> On Wednesday 07 December 2016 02:22 AM, David Marchand wrote:
>>>>>
>>>>> 0002~0003: Introducing the basic Bus model and associated test case
>>>>> 0005:      Support insertion of device rather than addition to tail
>>>>
>>>>
>>>>
>>>> Patch 2 and 5 could be squashed.
>>>
>>>
>>>
>>> I deliberately kept them separate. I intent to extend the Patch 5 for
>>> hotplugging. But, if I don't end up adding support for that in this
>>> series,
>>> I will merge these two.
>>
>>
>> Fine.
>>
>>
>>>> The constructor priority stuff seems unneeded as long as we use
>>>> explicit reference to a global (or local, did not check) bus symbol
>>>> rather than a runtime lookup.
>>>
>>>
>>>
>>> I didn't understand your point here.
>>> IMO, constructor priority (or some other way to handle this) is
>>> important. I
>>> faced this issue while verifying it at my end when the drivers were
>>> getting
>>> registered before the bus.
>>>
>>> Can you elaborate more on '..use explicit reference to a global...'?
>>
>>
>> The drivers register themselves to a bus using this bus specific api.
>>
>> For pci, this is rte_eal_pci_register().
>> The pci_bus object must be moved to eal_common_pci.c (we can stil
>> internally expose for bsd / linux specific implementations).
>> Then, rte_eal_pci_register() can add the pci driver to the pci_bus
>> drivers list even if this pci_bus object is not registered yet to the
>> buses list.
>
>
> So, in eal_common_bus.c
>
> --->8---
>
> struct rte_bus *global_ptr_to_pci_bus = NULL;
>
> struct rte_bus pci_bus = { ... };
>
> rte_eal_pci_register() {
>     if (global_ptr_to_pci_bus == NULL)
>         rte_eal_bus_register(&pci_bus)
>     else
>        // continue as if PCI bus is registered
> }
>
> --->8---
>
> so, no RTE_REGISTER_BUS()?
>
> If yes, then RTE_REGISTER_BUS() should also check for an existing
> registration for duplication.
>
> I was banking on a model where bus handlers (or bus drivers) are independent
> entities, just like PMDs. So, we have a bus XYZ without any drivers
> necessarily based on it.
>
> By making registration dependent on driver registration, it becomes implicit
> that buses don't exist without drivers.
> I am not in favor of this - or maybe I lack enough reason for this (about
> how it will make framework/PMD life better).
>
>>
>> And no constructor order issue ?
>>
>>
>>>>
>>>>
>>>>> 0004:      Add scan and match callbacks for the Bus and updated test
>>>>> case
>>>>
>>>>
>>>>
>>>> Why do you push back the bus object in the 'scan' method ?
>>>> This method is bus specific which means that the code "knows" the
>>>> object registered with the callback.
>>>
>>>
>>>
>>> This 'knows' is the grey area for me.
>>> The bus (for example, PCI) after scanning needs to call
>>> rte_eal_bus_add_device() to link the device in bus's device_list.
>>>
>>> Two options:
>>> 1. Have a global reference to "pci" bus (rte_bus) somewhere in eal_pci.c
>>> 2. Call rte_eal_get_bus() every time someone needs the reference.
>>> 3. C++ style, 'this->'.
>>>
>>> I have taken the 3rd path. It simplifies my code to not assume a handle
>>> as
>>> well as not allow for reference fetch calls every now and then.
>>>
>>> As a disadvantage: it means passing this as argument - and some cases
>>> maintaining it as __rte_unused.
>>>
>>> Taking (1) or (2) is not advantageous than this approach.
>>
>>
>> 1) is the simplest one.
>>
>> When you write a pci_scan method and embed it in you pci_bus object,
>> but this pci_scan method still wonders which bus object it is supposed
>> to work on, this is a bit like Schizophrenia ;-).
>
>
> :)
> This now is linked to the above issue of constructor priority and having a
> global bus reference. I don't personally prefer it.
> I will still give this a serious thought, though.
>

I'm also in favor of (3).

>>
>>
>>>> Is is that you want to have a single scan method used by multiple buses
>>>> ?
>>>
>>>
>>>
>>> Yes, but only as a use case. For example, platform devices are of various
>>> types - what if we have a south-bound bus over a platform bus. In which
>>> case, a hierarchical bus layout is possible.
>>> But, this is far-fetched idea for now.
>>

How to express the hierarchical bus layout as the bus in your design
is more like independent objects to hold drivers and their devices?

>>
>> Well, if you have no usecase at the moment, let's keep it simple, please.
>>
>
> Ok.
>
>>
>>>>
>>>>> 0006:      Integrate bus scan/match with EAL, without any effective
>>>>> driver
>>>>
>>>>
>>>>
>>>> Hard to find a right balance in patch splittng, but patch 4 and 6 are
>>>> linked, I would squash them into one.
>>>
>>>
>>>
>>> Yes, it is hard and sometimes there is simply no strong rationale for
>>> splitting or merging. This is one of those cases.
>>> My idea was that one patch _only_ introduces Bus services (structures,
>>> functions etc) and another should enable the calls to it from EAL.
>>> In that sense, I still think 4 and 6 should remain separate, may be
>>> consecutive, though.
>>
>>
>> Ok, will see in next version of the patchset.
>
>
> Is there anything specific that you are looking for in patchset v2?
> I was thinking of:
> 0. fixing BSD compilation issue reported by CI
> 1. improving the test_pci.c
> 2. hotplugging
> 3. trying to move PCI to drives/bus/pci/linux/* and resolving how drivers
> link to it, and how EAL resources like devargs are consumed.
>
> Anything else?
>
>>
>>
>>>>
>>>>> 0007:      rte_pci_driver->probe replaced with rte_driver->probe
>>>>
>>>>
>>>>
>>>> This patch is too big, please separate in two patches: eal changes
>>>> then ethdev/driver changes.
>>>
>>>
>>>
>>> I don't think that can be done. One change is incomplete without the
>>> other.
>>>
>>> Changes to all files are only for rte_pci_driver->probe to
>>> rte_driver->probe
>>> movement. EAL changes is to allow rte_eth_dev_pci_probe function after
>>> such
>>> a change as rte_driver->probe has different arguments as compared to
>>> rte_pci_driver->probe. The patches won't compile if I split.
>>>
>>> Am I missing something?
>>>>
>>>>
>>>> Why do you push back the driver object in the 'probe' method ? (idem
>>>> rte_bus->scan).
>>>
>>>
>>>
>>> I am assuming you are referring to rte_driver->probe().
>>> This is being done so that implementations (specific to drivers on a
>>> particular bus) can start extracting the rte_xxx_driver, if need be.
>>>
>>> For example, for e1000/em_ethdev.c, rte_driver->probe() have been set to
>>> rte_eth_dev_pci_probe() which requires rte_pci_driver to work with. In
>>> absence of the rte_driver object, this function cannot call
>>> rte_pci_driver->probe (for example) for driver specific operations.
>>
>>
>> Sorry, I am thinking a step ahead with eth_driver out of the picture.
>> But once eth_driver disappears, I can see no reason to keep this
>> driver in the probe method (Schizophrenia again).
>
>
> When eth_driver disappears, i was thinking of accomodating the eth_dev_init
> into the rte_pci_driver->probe/init.
> But, this is still a nascent thought.
> I am yet to start working on eth_driver.
>
>>
>>
>>
>

^ permalink raw reply

* [PATCH v12] net/tap: new TUN/TAP device PMD
From: Keith Wiles @ 2016-12-12 14:38 UTC (permalink / raw)
  To: dev; +Cc: pmatilai, yuanhan.liu, ferruh.yigit, john.mcnamara
In-Reply-To: <1476396234-44694-1-git-send-email-keith.wiles@intel.com>

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.

v12- Fixup minor changes for driver_name and version number
v11- Add the tap.rst to the nic/index.rst file
v10- Change the string name used to allow for multiple devices.
v9 - Fix up the docs to use correct syntax
v8 - Fix issue with tap_tx_queue_setup() not return zero on success.
v7 - Reword the comment in common_base and fix the data->name issue
v6 - fixed the checkpatch issues
v5 - merge in changes from list review see related emails
     fixed many minor edits
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 <keith.wiles@intel.com>
---
 MAINTAINERS                             |   5 +
 config/common_base                      |   9 +
 config/common_linuxapp                  |   1 +
 doc/guides/nics/index.rst               |   1 +
 doc/guides/nics/tap.rst                 | 136 ++++++
 drivers/net/Makefile                    |   1 +
 drivers/net/tap/Makefile                |  57 +++
 drivers/net/tap/rte_eth_tap.c           | 765 ++++++++++++++++++++++++++++++++
 drivers/net/tap/rte_pmd_tap_version.map |   4 +
 mk/rte.app.mk                           |   1 +
 10 files changed, 980 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 26d9590..842fb6d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -398,6 +398,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 <keith.wiles@intel.com>
+F: drivers/net/tap
+F: doc/guides/nics/tap.rst
+
 Null Networking PMD
 M: Tetsuya Mukawa <mtetsuyah@gmail.com>
 F: drivers/net/null/
diff --git a/config/common_base b/config/common_base
index 652a839..eb51cdb 100644
--- a/config/common_base
+++ b/config/common_base
@@ -590,3 +590,12 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
 CONFIG_RTE_TEST_PMD=y
 CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
 CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the TAP PMD
+#
+# The TAP PMD is currently only built for Linux and the
+# option is enabled by default in common_linuxapp file,
+# set to 'n' in the common_base file.
+#
+CONFIG_RTE_LIBRTE_PMD_TAP=n
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 2483dfa..782b503 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -44,3 +44,4 @@ 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
diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst
index 92d56a5..af92529 100644
--- a/doc/guides/nics/index.rst
+++ b/doc/guides/nics/index.rst
@@ -51,6 +51,7 @@ Network Interface Controller Drivers
     nfp
     qede
     szedata2
+    tap
     thunderx
     virtio
     vhost
diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst
new file mode 100644
index 0000000..622b9e7
--- /dev/null
+++ b/doc/guides/nics/tap.rst
@@ -0,0 +1,136 @@
+..  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=net_tap`` option on the DPDK application command line. Each
+``--vdev=net_tap`` option give will create an interface named dtap0, dtap1,
+and so on.
+
+The interfaced name can be changed by adding the ``iface=foo0``, for example::
+
+   --vdev=net_tap,iface=foo0 --vdev=net_tap,iface=foo1, ...
+
+Also the speed of the interface can be changed from 10G to whatever number
+needed, but the interface does not enforce that speed, for example::
+
+   --vdev=net_tap,iface=foo0,speed=25000
+
+After the DPDK application is started you can send and receive packets on the
+interface using the standard rx_burst/tx_burst APIs in DPDK. From the host
+point of view you can use any host tool like tcpdump, Wireshark, ping, Pktgen
+and others to communicate with the DPDK application. The DPDK application may
+not understand network protocols like IPv4/6, UDP or TCP unless the
+application has been written to understand these protocols.
+
+If you need the interface as a real network interface meaning running and has
+a valid IP address then you can do this with the following commands::
+
+   sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0
+   sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1
+
+Please change the IP addresses as you see fit.
+
+If routing is enabled on the host you can also communicate with the DPDK App
+over the internet via a standard socket layer application as long as you
+account for the protocol handing in the application.
+
+If you have a Network Stack in your DPDK application or something like it you
+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.
+
+Example
+-------
+
+The following is a simple example of using the TUN/TAP PMD with the Pktgen
+packet generator. It requires that the ``socat`` utility is installed on the
+test system.
+
+Build DPDK, then pull down Pktgen and build pktgen using the DPDK SDK/Target
+used to build the dpdk you pulled down.
+
+Run pktgen from the pktgen directory in a terminal with a commandline like the
+following::
+
+    sudo ./app/app/x86_64-native-linuxapp-gcc/app/pktgen -l 1-5 -n 4        \
+     --proc-type auto --log-level 8 --socket-mem 512,512 --file-prefix pg   \
+     --vdev=net_tap --vdev=net_tap -b 05:00.0 -b 05:00.1                    \
+     -b 04:00.0 -b 04:00.1 -b 04:00.2 -b 04:00.3                            \
+     -b 81:00.0 -b 81:00.1 -b 81:00.2 -b 81:00.3                            \
+     -b 82:00.0 -b 83:00.0 -- -T -P -m [2:3].0 -m [4:5].1                   \
+     -f themes/black-yellow.theme
+
+.. Note:
+
+   Change the ``-b`` options to blacklist all of your physical ports. The
+   following command line is all one line.
+
+   Also, ``-f themes/black-yellow.theme`` is optional if the default colors
+   work on your system configuration. See the Pktgen docs for more
+   information.
+
+Verify with ``ifconfig -a`` command in a different xterm window, should have a
+``dtap0`` and ``dtap1`` interfaces created.
+
+Next set the links for the two interfaces to up via the commands below::
+
+    sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0
+    sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1
+
+Then use socat to create a loopback for the two interfaces::
+
+    sudo socat interface:dtap0 interface:dtap1
+
+Then on the Pktgen command line interface you can start sending packets using
+the commands ``start 0`` and ``start 1`` or you can start both at the same
+time with ``start all``. The command ``str`` is an alias for ``start all`` and
+``stp`` is an alias for ``stop all``.
+
+While running you should see the 64 byte counters increasing to verify the
+traffic is being looped back. You can use ``set all size XXX`` to change the
+size of the packets after you stop the traffic. Use the pktgen ``help``
+command to see a list of all commands. You can also use the ``-f`` option to
+load commands at startup.
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index bc93230..e366a85 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -51,6 +51,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += pcap
 DIRS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += ring
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += szedata2
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += tap
 DIRS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += thunderx
 DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3
diff --git a/drivers/net/tap/Makefile b/drivers/net/tap/Makefile
new file mode 100644
index 0000000..e18f30c
--- /dev/null
+++ b/drivers/net/tap/Makefile
@@ -0,0 +1,57 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 Intel Corporation. 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.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_tap.a
+
+EXPORT_MAP := rte_pmd_tap_version.map
+
+LIBABIVER := 1
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += rte_eth_tap.c
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mempool
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
new file mode 100644
index 0000000..976f2d9
--- /dev/null
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -0,0 +1,765 @@
+/*-
+ *   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.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_vdev.h>
+#include <rte_kvargs.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <poll.h>
+#include <arpa/inet.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <linux/if_ether.h>
+#include <fcntl.h>
+
+/* Linux based path to the TUN device */
+#define TUN_TAP_DEV_PATH        "/dev/net/tun"
+#define DEFAULT_TAP_NAME        "dtap"
+
+#define ETH_TAP_IFACE_ARG       "iface"
+#define ETH_TAP_SPEED_ARG       "speed"
+
+#define RTE_PMD_TAP_MAX_QUEUES	16
+
+static struct rte_vdev_driver pmd_tap_drv;
+
+static const char *valid_arguments[] = {
+	ETH_TAP_IFACE_ARG,
+	ETH_TAP_SPEED_ARG,
+	NULL
+};
+
+static int tap_unit;
+
+static struct rte_eth_link pmd_link = {
+	.link_speed = ETH_SPEED_NUM_10G,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = ETH_LINK_DOWN,
+	.link_autoneg = ETH_LINK_SPEED_AUTONEG
+};
+
+struct pkt_stats {
+	uint64_t opackets;		/* Number of output packets */
+	uint64_t ipackets;		/* Number of input packets */
+	uint64_t obytes;		/* Number of bytes on output */
+	uint64_t ibytes;		/* Number of bytes on input */
+	uint64_t errs;			/* Number of error packets */
+};
+
+struct rx_queue {
+	struct rte_mempool *mp;		/* Mempool for RX packets */
+	uint16_t in_port;		/* Port ID */
+	int fd;
+
+	struct pkt_stats stats;		/* Stats for this RX queue */
+};
+
+struct tx_queue {
+	int fd;
+	struct pkt_stats stats;		/* Stats for this TX queue */
+};
+
+struct pmd_internals {
+	char name[RTE_ETH_NAME_MAX_LEN];	/* Internal Tap device name */
+	uint16_t nb_queues;		/* Number of queues supported */
+	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)
+{
+	struct ifreq ifr;
+	unsigned int features;
+	int fd;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+
+	ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+	if (name && name[0])
+		strncpy(ifr.ifr_name, name, IFNAMSIZ);
+
+	fd = open(TUN_TAP_DEV_PATH, O_RDWR);
+	if (fd < 0) {
+		RTE_LOG(ERR, PMD, "Unable to create TAP interface");
+		goto error;
+	}
+
+	/* Grab the TUN features to verify we can work */
+	if (ioctl(fd, TUNGETFEATURES, &features) < 0) {
+		RTE_LOG(ERR, PMD, "Unable to get TUN/TAP features\n");
+		goto error;
+	}
+	RTE_LOG(DEBUG, PMD, "TUN/TAP Features %08x\n", features);
+
+	if (!(features & IFF_MULTI_QUEUE) && (RTE_PMD_TAP_MAX_QUEUES > 1)) {
+		RTE_LOG(DEBUG, PMD, "TUN/TAP device only one queue\n");
+		goto error;
+	} else if ((features & IFF_ONE_QUEUE) &&
+			(RTE_PMD_TAP_MAX_QUEUES == 1)) {
+		ifr.ifr_flags |= IFF_ONE_QUEUE;
+		RTE_LOG(DEBUG, PMD, "Single queue only support\n");
+	} else {
+		ifr.ifr_flags |= IFF_MULTI_QUEUE;
+		RTE_LOG(DEBUG, PMD, "Multi-queue support for %d queues\n",
+			RTE_PMD_TAP_MAX_QUEUES);
+	}
+
+	/* Set the TUN/TAP configuration and get the name if needed */
+	if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) {
+		RTE_LOG(ERR, PMD, "Unable to set TUNSETIFF for %s\n",
+			ifr.ifr_name);
+		perror("TUNSETIFF");
+		goto error;
+	}
+
+	/* Always set the file descriptor to non-blocking */
+	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))
+		snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", ifr.ifr_name);
+
+	return fd;
+
+error:
+	if (fd > 0)
+		close(fd);
+	return -1;
+}
+
+/* Callback to handle the rx burst of packets to the correct interface and
+ * file descriptor(s) in a multi-queue setup.
+ */
+static uint16_t
+pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+	int len;
+	struct rte_mbuf *mbuf;
+	struct rx_queue *rxq = queue;
+	uint16_t num_rx;
+	unsigned long num_rx_bytes = 0;
+
+	for (num_rx = 0; num_rx < nb_pkts; ) {
+		/* allocate the next mbuf */
+		mbuf = rte_pktmbuf_alloc(rxq->mp);
+		if (unlikely(!mbuf)) {
+			RTE_LOG(WARNING, PMD, "Unable to allocate mbuf\n");
+			break;
+		}
+
+		len = read(rxq->fd, rte_pktmbuf_mtod(mbuf, char *),
+			   rte_pktmbuf_tailroom(mbuf));
+		if (len <= 0) {
+			rte_pktmbuf_free(mbuf);
+			break;
+		}
+
+		mbuf->data_len = len;
+		mbuf->pkt_len = len;
+		mbuf->port = rxq->in_port;
+
+		/* account for the receive frame */
+		bufs[num_rx++] = mbuf;
+		num_rx_bytes += mbuf->pkt_len;
+	}
+	rxq->stats.ipackets += num_rx;
+	rxq->stats.ibytes += num_rx_bytes;
+
+	return num_rx;
+}
+
+/* Callback to handle sending packets from the tap interface
+ */
+static uint16_t
+pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+	struct rte_mbuf *mbuf;
+	struct tx_queue *txq = queue;
+	struct pollfd pfd;
+	uint16_t num_tx = 0;
+	unsigned long num_tx_bytes = 0;
+	int i, n;
+
+	if (unlikely(nb_pkts == 0))
+		return 0;
+
+	pfd.events = POLLOUT;
+	pfd.fd = txq->fd;
+	for (i = 0; i < nb_pkts; i++) {
+		n = poll(&pfd, 1, 0);
+
+		if (n <= 0)
+			break;
+
+		if (pfd.revents & POLLOUT) {
+			/* copy the tx frame data */
+			mbuf = bufs[num_tx];
+			n = write(pfd.fd, rte_pktmbuf_mtod(mbuf, void*),
+				  rte_pktmbuf_pkt_len(mbuf));
+			if (n <= 0)
+				break;
+
+			num_tx++;
+			num_tx_bytes += mbuf->pkt_len;
+			rte_pktmbuf_free(mbuf);
+		}
+	}
+
+	txq->stats.opackets += num_tx;
+	txq->stats.errs += nb_pkts - num_tx;
+	txq->stats.obytes += num_tx_bytes;
+
+	return num_tx;
+}
+
+static int
+tap_dev_start(struct rte_eth_dev *dev)
+{
+	/* Force the Link up */
+	dev->data->dev_link.link_status = ETH_LINK_UP;
+
+	return 0;
+}
+
+/* This function gets called when the current port gets stopped.
+ */
+static void
+tap_dev_stop(struct rte_eth_dev *dev)
+{
+	int i;
+	struct pmd_internals *internals = dev->data->dev_private;
+
+	for (i = 0; i < internals->nb_queues; i++)
+		if (internals->fds[i] != -1)
+			close(internals->fds[i]);
+
+	dev->data->dev_link.link_status = ETH_LINK_DOWN;
+}
+
+static int
+tap_dev_configure(struct rte_eth_dev *dev __rte_unused)
+{
+	return 0;
+}
+
+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->if_index = internals->if_index;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)ETHER_MAX_VLAN_FRAME_LEN;
+	dev_info->max_rx_queues = internals->nb_queues;
+	dev_info->max_tx_queues = internals->nb_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+tap_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *tap_stats)
+{
+	unsigned int i, imax;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	unsigned long rx_bytes_total = 0, tx_bytes_total = 0;
+	const struct pmd_internals *pmd = dev->data->dev_private;
+
+	imax = (pmd->nb_queues < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
+		pmd->nb_queues : RTE_ETHDEV_QUEUE_STAT_CNTRS;
+
+	for (i = 0; i < imax; i++) {
+		tap_stats->q_ipackets[i] = pmd->rxq[i].stats.ipackets;
+		tap_stats->q_ibytes[i] = pmd->rxq[i].stats.ibytes;
+		rx_total += tap_stats->q_ipackets[i];
+		rx_bytes_total += tap_stats->q_ibytes[i];
+	}
+
+	for (i = 0; i < imax; i++) {
+		tap_stats->q_opackets[i] = pmd->txq[i].stats.opackets;
+		tap_stats->q_errors[i] = pmd->txq[i].stats.errs;
+		tap_stats->q_obytes[i] = pmd->txq[i].stats.obytes;
+		tx_total += tap_stats->q_opackets[i];
+		tx_err_total += tap_stats->q_errors[i];
+		tx_bytes_total += tap_stats->q_obytes[i];
+	}
+
+	tap_stats->ipackets = rx_total;
+	tap_stats->ibytes = rx_bytes_total;
+	tap_stats->opackets = tx_total;
+	tap_stats->oerrors = tx_err_total;
+	tap_stats->obytes = tx_bytes_total;
+}
+
+static void
+tap_stats_reset(struct rte_eth_dev *dev)
+{
+	int i;
+	struct pmd_internals *pmd = dev->data->dev_private;
+
+	for (i = 0; i < pmd->nb_queues; i++) {
+		pmd->rxq[i].stats.ipackets = 0;
+		pmd->rxq[i].stats.ibytes = 0;
+	}
+
+	for (i = 0; i < pmd->nb_queues; i++) {
+		pmd->txq[i].stats.opackets = 0;
+		pmd->txq[i].stats.errs = 0;
+		pmd->txq[i].stats.obytes = 0;
+	}
+}
+
+static void
+tap_dev_close(struct rte_eth_dev *dev __rte_unused)
+{
+}
+
+static void
+tap_rx_queue_release(void *queue)
+{
+	struct rx_queue *rxq = queue;
+
+	if (rxq && (rxq->fd > 0)) {
+		close(rxq->fd);
+		rxq->fd = -1;
+	}
+}
+
+static void
+tap_tx_queue_release(void *queue)
+{
+	struct tx_queue *txq = queue;
+
+	if (txq && (txq->fd > 0)) {
+		close(txq->fd);
+		txq->fd = -1;
+	}
+}
+
+static int
+tap_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused)
+{
+	return 0;
+}
+
+static int
+tap_setup_queue(struct rte_eth_dev *dev,
+		struct pmd_internals *internals,
+		uint16_t qid)
+{
+	struct rx_queue *rx = &internals->rxq[qid];
+	struct tx_queue *tx = &internals->txq[qid];
+	int fd;
+
+	fd = rx->fd;
+	if (fd < 0) {
+		fd = tx->fd;
+		if (fd < 0) {
+			RTE_LOG(INFO, PMD, "Add queue to TAP %s for qid %d\n",
+				dev->data->name, qid);
+			fd = tun_alloc(dev->data->name);
+			if (fd < 0) {
+				RTE_LOG(ERR, PMD, "tun_alloc(%s) failed\n",
+					dev->data->name);
+				return -1;
+			}
+		}
+	}
+	dev->data->rx_queues[qid] = rx;
+	dev->data->tx_queues[qid] = tx;
+
+	rx->fd = fd;
+	tx->fd = fd;
+
+	return fd;
+}
+
+static int
+tap_rx_queue_setup(struct rte_eth_dev *dev,
+		   uint16_t rx_queue_id,
+		   uint16_t nb_rx_desc __rte_unused,
+		   unsigned int socket_id __rte_unused,
+		   const struct rte_eth_rxconf *rx_conf __rte_unused,
+		   struct rte_mempool *mp)
+{
+	struct pmd_internals *internals = dev->data->dev_private;
+	uint16_t buf_size;
+	int fd;
+
+	if ((rx_queue_id >= internals->nb_queues) || !mp) {
+		RTE_LOG(ERR, PMD, "nb_queues %d mp %p\n",
+			internals->nb_queues, mp);
+		return -1;
+	}
+
+	internals->rxq[rx_queue_id].mp = mp;
+	internals->rxq[rx_queue_id].in_port = dev->data->port_id;
+
+	/* Now get the space available for data in the mbuf */
+	buf_size = (uint16_t)(rte_pktmbuf_data_room_size(mp) -
+				RTE_PKTMBUF_HEADROOM);
+
+	if (buf_size < ETH_FRAME_LEN) {
+		RTE_LOG(ERR, PMD,
+			"%s: %d bytes will not fit in mbuf (%d bytes)\n",
+			dev->data->name, ETH_FRAME_LEN, buf_size);
+		return -ENOMEM;
+	}
+
+	fd = tap_setup_queue(dev, internals, rx_queue_id);
+	if (fd == -1)
+		return -1;
+
+	internals->fds[rx_queue_id] = fd;
+	RTE_LOG(INFO, PMD, "RX TAP device name %s, qid %d on fd %d\n",
+		dev->data->name, rx_queue_id, internals->rxq[rx_queue_id].fd);
+
+	return 0;
+}
+
+static int
+tap_tx_queue_setup(struct rte_eth_dev *dev,
+		   uint16_t tx_queue_id,
+		   uint16_t nb_tx_desc __rte_unused,
+		   unsigned int socket_id __rte_unused,
+		   const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct pmd_internals *internals = dev->data->dev_private;
+	int ret;
+
+	if (tx_queue_id >= internals->nb_queues)
+		return -1;
+
+	ret = tap_setup_queue(dev, internals, tx_queue_id);
+	if (ret == -1)
+		return -1;
+
+	RTE_LOG(INFO, PMD, "TX TAP device name %s, qid %d on fd %d\n",
+		dev->data->name, tx_queue_id, internals->txq[tx_queue_id].fd);
+
+	return 0;
+}
+
+static const struct eth_dev_ops ops = {
+	.dev_start              = tap_dev_start,
+	.dev_stop               = tap_dev_stop,
+	.dev_close              = tap_dev_close,
+	.dev_configure          = tap_dev_configure,
+	.dev_infos_get          = tap_dev_info,
+	.rx_queue_setup         = tap_rx_queue_setup,
+	.tx_queue_setup         = tap_tx_queue_setup,
+	.rx_queue_release       = tap_rx_queue_release,
+	.tx_queue_release       = tap_tx_queue_release,
+	.link_update            = tap_link_update,
+	.stats_get              = tap_stats_get,
+	.stats_reset            = tap_stats_reset,
+};
+
+static int
+pmd_mac_address(int fd, struct rte_eth_dev *dev, struct ether_addr *addr)
+{
+	struct ifreq ifr;
+
+	if ((fd <= 0) || !dev || !addr)
+		return -1;
+
+	memset(&ifr, 0, sizeof(ifr));
+
+	if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
+		RTE_LOG(ERR, PMD, "ioctl failed (SIOCGIFHWADDR) (%s)\n",
+			ifr.ifr_name);
+		return -1;
+	}
+
+	/* Set the host based MAC address to this special MAC format */
+	ifr.ifr_hwaddr.sa_data[0] = 'T';
+	ifr.ifr_hwaddr.sa_data[1] = 'a';
+	ifr.ifr_hwaddr.sa_data[2] = 'p';
+	ifr.ifr_hwaddr.sa_data[3] = '-';
+	ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
+	ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
+	if (ioctl(fd, SIOCSIFHWADDR, &ifr) == -1) {
+		RTE_LOG(ERR, PMD, "%s: ioctl failed (SIOCSIFHWADDR) (%s)\n",
+			dev->data->name, ifr.ifr_name);
+		return -1;
+	}
+
+	/* Set the local application MAC address, needs to be different then
+	 * the host based MAC address.
+	 */
+	ifr.ifr_hwaddr.sa_data[0] = 'd';
+	ifr.ifr_hwaddr.sa_data[1] = 'n';
+	ifr.ifr_hwaddr.sa_data[2] = 'e';
+	ifr.ifr_hwaddr.sa_data[3] = 't';
+	ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
+	ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
+	rte_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+
+	return 0;
+}
+
+static int
+eth_dev_tap_create(const char *name, char *tap_name)
+{
+	int numa_node = rte_socket_id();
+	struct rte_eth_dev *dev = NULL;
+	struct pmd_internals *pmd = NULL;
+	struct rte_eth_dev_data *data = NULL;
+	int i, fd = -1;
+
+	RTE_LOG(INFO, PMD,
+		"%s: Create TAP Ethernet device with %d queues on numa %u\n",
+		 name, RTE_PMD_TAP_MAX_QUEUES, rte_socket_id());
+
+	data = rte_zmalloc_socket(tap_name, sizeof(*data), 0, numa_node);
+	if (!data) {
+		RTE_LOG(INFO, PMD, "Failed to allocate data\n");
+		goto error_exit;
+	}
+
+	pmd = rte_zmalloc_socket(tap_name, sizeof(*pmd), 0, numa_node);
+	if (!pmd) {
+		RTE_LOG(INFO, PMD, "Unable to allocate internal struct\n");
+		goto error_exit;
+	}
+
+	/* Use the name and not the tap_name */
+	dev = rte_eth_dev_allocate(tap_name);
+	if (!dev) {
+		RTE_LOG(INFO, PMD, "Unable to allocate device struct\n");
+		goto error_exit;
+	}
+
+	snprintf(pmd->name, sizeof(pmd->name), "%s", tap_name);
+
+	pmd->nb_queues = RTE_PMD_TAP_MAX_QUEUES;
+
+	/* Setup some default values */
+	data->dev_private = pmd;
+	data->port_id = dev->data->port_id;
+	data->dev_flags = RTE_ETH_DEV_DETACHABLE;
+	data->kdrv = RTE_KDRV_NONE;
+	data->drv_name = pmd_tap_drv.driver.name;
+	data->numa_node = numa_node;
+
+	data->dev_link = pmd_link;
+	data->mac_addrs = &pmd->eth_addr;
+	data->nb_rx_queues = pmd->nb_queues;
+	data->nb_tx_queues = pmd->nb_queues;
+
+	dev->data = data;
+	dev->dev_ops = &ops;
+	dev->driver = NULL;
+	dev->rx_pkt_burst = pmd_rx_burst;
+	dev->tx_pkt_burst = pmd_tx_burst;
+	snprintf(dev->data->name, sizeof(dev->data->name), "%s", name);
+
+	/* Create the first Tap device */
+	fd = tun_alloc(tap_name);
+	if (fd < 0) {
+		RTE_LOG(INFO, PMD, "tun_alloc() failed\n");
+		goto error_exit;
+	}
+
+	/* Presetup the fds to -1 as being not working */
+	for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) {
+		pmd->fds[i] = -1;
+		pmd->rxq[i].fd = -1;
+		pmd->txq[i].fd = -1;
+	}
+
+	/* Take the TUN/TAP fd and place in the first location */
+	pmd->rxq[0].fd = fd;
+	pmd->txq[0].fd = fd;
+	pmd->fds[0] = fd;
+
+	if (pmd_mac_address(fd, dev, &pmd->eth_addr) < 0) {
+		RTE_LOG(INFO, PMD, "Unable to get MAC address\n");
+		goto error_exit;
+	}
+
+	return 0;
+
+error_exit:
+	RTE_PMD_DEBUG_TRACE("Unable to initialize %s\n", name);
+
+	rte_free(data);
+	rte_free(pmd);
+
+	rte_eth_dev_release_port(dev);
+
+	return -EINVAL;
+}
+
+static int
+set_interface_name(const char *key __rte_unused,
+		   const char *value,
+		   void *extra_args)
+{
+	char *name = (char *)extra_args;
+
+	if (value)
+		snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", value);
+	else
+		snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s%d",
+			 DEFAULT_TAP_NAME, (tap_unit - 1));
+
+	return 0;
+}
+
+static int
+set_interface_speed(const char *key __rte_unused,
+		    const char *value,
+		    void *extra_args)
+{
+	*(int *)extra_args = (value) ? atoi(value) : ETH_SPEED_NUM_10G;
+
+	return 0;
+}
+
+/* Open a TAP interface device.
+ */
+static int
+rte_pmd_tap_probe(const char *name, const char *params)
+{
+	int ret;
+	struct rte_kvargs *kvlist = NULL;
+	int speed;
+	char tap_name[RTE_ETH_NAME_MAX_LEN];
+
+	speed = ETH_SPEED_NUM_10G;
+	snprintf(tap_name, sizeof(tap_name), "%s%d",
+		 DEFAULT_TAP_NAME, tap_unit++);
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_tap for %s as %s\n",
+		name, tap_name);
+
+	if (params && (params[0] != '\0')) {
+		RTE_LOG(INFO, PMD, "paramaters (%s)\n", params);
+
+		kvlist = rte_kvargs_parse(params, valid_arguments);
+		if (kvlist) {
+			if (rte_kvargs_count(kvlist, ETH_TAP_SPEED_ARG) == 1) {
+				ret = rte_kvargs_process(kvlist,
+							 ETH_TAP_SPEED_ARG,
+							 &set_interface_speed,
+							 &speed);
+				if (ret == -1)
+					goto leave;
+			}
+
+			if (rte_kvargs_count(kvlist, ETH_TAP_IFACE_ARG) == 1) {
+				ret = rte_kvargs_process(kvlist,
+							 ETH_TAP_IFACE_ARG,
+							 &set_interface_name,
+							 tap_name);
+				if (ret == -1)
+					goto leave;
+			}
+		}
+	}
+	pmd_link.link_speed = speed;
+
+	ret = eth_dev_tap_create(name, tap_name);
+
+leave:
+	if (ret == -1) {
+		RTE_LOG(INFO, PMD, "Failed to create pmd for %s as %s\n",
+			name, tap_name);
+		tap_unit--;		/* Restore the unit number */
+	}
+	rte_kvargs_free(kvlist);
+
+	return ret;
+}
+
+/* detach a TAP device.
+ */
+static int
+rte_pmd_tap_remove(const char *name)
+{
+	struct rte_eth_dev *eth_dev = NULL;
+	struct pmd_internals *internals;
+	int i;
+
+	RTE_LOG(INFO, PMD, "Closing TUN/TAP Ethernet device on numa %u\n",
+		rte_socket_id());
+
+	/* find the ethdev entry */
+	eth_dev = rte_eth_dev_allocated(name);
+	if (!eth_dev)
+		return 0;
+
+	internals = eth_dev->data->dev_private;
+	for (i = 0; i < internals->nb_queues; i++)
+		if (internals->fds[i] != -1)
+			close(internals->fds[i]);
+
+	rte_free(eth_dev->data->dev_private);
+	rte_free(eth_dev->data);
+
+	rte_eth_dev_release_port(eth_dev);
+
+	return 0;
+}
+
+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_ALIAS(net_tap, eth_tap);
+RTE_PMD_REGISTER_PARAM_STRING(net_tap, "iface=<string>,speed=N");
diff --git a/drivers/net/tap/rte_pmd_tap_version.map b/drivers/net/tap/rte_pmd_tap_version.map
new file mode 100644
index 0000000..31eca32
--- /dev/null
+++ b/drivers/net/tap/rte_pmd_tap_version.map
@@ -0,0 +1,4 @@
+DPDK_17.02 {
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index f75f0e2..02c32ae 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -124,6 +124,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP)       += -lrte_pmd_pcap -lpcap
 _LDLIBS-$(CONFIG_RTE_LIBRTE_QEDE_PMD)       += -lrte_pmd_qede
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_RING)       += -lrte_pmd_ring
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2)   += -lrte_pmd_szedata2 -lsze2
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_TAP)        += -lrte_pmd_tap
 _LDLIBS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += -lrte_pmd_thunderx_nicvf -lm
 _LDLIBS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD)     += -lrte_pmd_virtio
 ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y)
-- 
2.8.0.GIT

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox