DPDK patches and discussions
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download: 
* Re: [dpdk-dev] [PATCH 2/2] eal: deprecate 17.08 devargs API/ABI
  @ 2017-08-07 23:03  4%   ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-07 23:03 UTC (permalink / raw)
  To: Jan Blunck; +Cc: dev

09/07/2017 11:28, Jan Blunck:
> Add deprecation notice necessary to do devargs refactoring for 17.11.
> 
> Signed-off-by: Jan Blunck <jblunck@infradead.org>
> ---
> --- a/doc/guides/rel_notes/deprecation.rst
> +++ b/doc/guides/rel_notes/deprecation.rst
> +* devargs: An ABI change is planned for 17.11 for the structure ``rte_devargs``.
> +  The newly introduced devargs ABI in 17.08 is tightly couple to the bus
> +  implementations which will get fixed in 17.11. The following function is
> +  deprecated and will change API in 17.11:
> +
> +  - ``rte_eal_devargs_add``

This deprecation notice is superseded by:
	http://dpdk.org/dev/patchwork/patch/27443/

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH] doc: announce rte_devargs changes in 17.11
  @ 2017-08-07 23:18  0% ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-07 23:18 UTC (permalink / raw)
  To: Gaetan Rivet; +Cc: dev

04/08/2017 15:29, Gaetan Rivet:
> Signed-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>
> ---
> --- a/doc/guides/rel_notes/deprecation.rst
> +++ b/doc/guides/rel_notes/deprecation.rst
> +* eal: several API and ABI changes are planned for ``rte_devargs`` in v17.11.
> +  The format of device command line parameters will change. The bus will need
> +  to be explicitly stated in the device declaration. The enum ``rte_devtype``
> +  was used to identify a bus and will disappear.
> +  The structure ``rte_devargs`` will change.
> +  The ``rte_devargs_list`` will be made private.
> +  The following functions are deprecated starting from 17.08 and will either be
> +  modified or removed in 17.11:
> +
> +  - ``rte_eal_devargs_add``
> +  - ``rte_eal_devargs_type_count``

Acked-by: Thomas Monjalon <thomas@monjalon.net>

This kind of change has already been suggested by Jan Blunck:
	http://dpdk.org/ml/archives/dev/2017-July/070729.html
	http://dpdk.org/ml/archives/dev/2017-July/071054.html

It is very important to continue progressing on device syntax and
bus rework during 17.11.

Applied

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] eal: add notice to make DPDK IOVA aware
  @ 2017-08-08  0:04  0%     ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-08  0:04 UTC (permalink / raw)
  To: Jerin Jacob
  Cc: dev, Olivier MATZ, Hemant Agrawal, santosh, stephen,
	bruce.richardson, shreyansh.jain, gaetan.rivet,
	sergio.gonzalez.monroy, anatoly.burakov

> > > > When we run DPDK on guest or VFIO mode on host,
> > > > the dpdk library or device will not be directly accessing
> > > > the physical address. Instead, the device does go through
> > > > an IO address translation memory management unit. On x86,
> > > > we call it as IOMMU and on ARM as SMMU.
> > > > 
> > > > More details:
> > > > http://osidays.com/osidays/wp-content/uploads/2014/12/Final_OSI2014_IOMMU_DetailedView_Sanil_Anurup.pdf
> > > > 
> > > > Based on discussion in the following thread
> > > > http://dpdk.org/ml/archives/dev/2017-July/070850.html
> > > > 
> > > > We would like to change reference to physical address to more
> > > > appropriate name as with IOMMU/SMMU with
> > > > the device won't be dealing directly with the physical address.
> > > > 
> > > > An ABI change is planned for 17.11 to change following
> > > > data structure or functions to more appropriate name.
> > > > Currently planned to change it iova as instead of phys
> > > > 
> > > > Please note: The change will be only for the name and
> > > > functional aspects of the API will remain same.
> > > > 
> > > > Following functions/data structures name may change.
> > > > This list is based on v17.05-rc1. It may change based on v17.11 code base.
> > > > 
> > > > 
> > > > typedef:
> > > > phys_addr_t
> > > > 
> > > > structures:
> > > > 
> > > > struct rte_memseg::phys_addr
> > > > struct rte_mbuf::buf_physaddr
> > > > 
> > > > functions:
> > > > rte_mempool_populate_phys()
> > > > rte_mempool_populate_phys_tab()
> > > > rte_eal_using_phys_addrs()
> > > > rte_mem_virt2phy()
> > > > rte_dump_physmem_layout()
> > > > rte_eal_get_physmem_layout()
> > > > rte_eal_get_physmem_size()
> > > > rte_malloc_virt2phy()
> > > > rte_mem_phy2mch()
> > > > 
> > > > Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
> > > 
> > > Acked-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
> > > 
> > Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>
> 
> Acked-by: Olivier Matz <olivier.matz@6wind.com>

Acked-by: Thomas Monjalon <thomas@monjalon.net>

The name will probably be discussed.
Applied, thanks

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2] doc: announce API/ABI changes for mempool
  @ 2017-08-08  0:10  4%     ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-08  0:10 UTC (permalink / raw)
  To: Santosh Shukla; +Cc: dev, Olivier MATZ, Jerin Jacob

> > > An API/ABI change is planned for 17.11 to change following
> > > 
> > > * Remove unused flag param from rte_mempool_generic_get and _put.
> > > * Change data type for mempool 'flag' from int to unsigned int.
> > >   Refer [1].
> > > * Add struct rte_mempool * param into func rte_mempool_xmem_size,
> > >   rte_mempool_xmem_usage to make it mempool aware.
> > >   Refer [2].
> > > 
> > > [1] http://dpdk.org/dev/patchwork/patch/25603/
> > > [2] http://dpdk.org/dev/patchwork/patch/25605/
> > > 
> > > Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
> > 
> > Acked-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
> 
> Acked-by: Olivier Matz <olivier.matz@6wind.com>

Applied, thanks

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v3] doc: announce API and ABI change for ethdev
  @ 2017-08-08  4:02  4%   ` Yang, Zhiyong
  2017-08-08  9:35  4%     ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Yang, Zhiyong @ 2017-08-08  4:02 UTC (permalink / raw)
  To: dev; +Cc: Tan, Jianfeng, yliu, jerin.jacob, thomas, Horton, Remy, shahafs


> -----Original Message-----
> From: Yang, Zhiyong
> Sent: Monday, August 7, 2017 8:43 PM
> To: dev@dpdk.org
> Cc: Tan, Jianfeng <jianfeng.tan@intel.com>; yliu@fridaylinux.org;
> jerin.jacob@caviumnetworks.com; thomas@monjalon.net; Horton, Remy
> <remy.horton@intel.com>; Yang, Zhiyong <zhiyong.yang@intel.com>
> Subject: [PATCH v3] doc: announce API and ABI change for ethdev
> 
> This is an API/ABI change notice for DPDK 17.11 announcing the redefinition of
> port_id. port_id is currently defined as uint8_t, which is limited to the range 0 to
> 255. A larger range is required for vdev scalability.
> 
> It is necessary for a redefinition of port_id to extend it from 1 bytes to
> 2 bytes. All ethdev APIs and usages related to port_id will be changed at the
> same time.
> 
> cc: jianfeng.tan@intel.com
> cc: yliu@fridaylinux.org
> cc: jerin.jacob@caviumnetworks.com
> cc: thomas@monjalon.net
> cc: remy.horton@intel.com
> 
> Signed-off-by: Zhiyong Yang <zhiyong.yang@intel.com>
> Acked-by: Jianfeng Tan <jianfeng.tan@intel.com>
> Acked-by: Yuanhan Liu <yliu@fridaylinux.org>
> Acked-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
> Acked-by: Remy Horton <remy.horton@intel.com>
> ---

This ack in v2 is added in v3. Thanks, Shahaf.

Acked-by: Shahaf Shuler <shahafs@mellanox.com>

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH] ethdev: add notice for planned name size change
  @ 2017-08-08  4:56  0%   ` Shahaf Shuler
  2017-08-08  9:47  0%     ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Shahaf Shuler @ 2017-08-08  4:56 UTC (permalink / raw)
  To: Yongseok Koh, Stephen Hemminger; +Cc: dev

Tuesday, August 8, 2017 1:20 AM, Yongseok Koh:
> > On Jul 6, 2017, at 8:07 AM, Stephen Hemminger
> <stephen@networkplumber.org> wrote:
> >
> > VMBUS support will use GUID in eth_dev_data name field which requires
> > at least 37 characters. Plan for increase in size now.
> >
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> > ---
> > doc/guides/rel_notes/deprecation.rst | 4 ++++
> > 1 file changed, 4 insertions(+)
> >
> > diff --git a/doc/guides/rel_notes/deprecation.rst
> > b/doc/guides/rel_notes/deprecation.rst
> > index 2e708dbe0deb..d5b70c50064a 100644
> > --- a/doc/guides/rel_notes/deprecation.rst
> > +++ b/doc/guides/rel_notes/deprecation.rst
> > @@ -95,3 +95,7 @@ Deprecation Notices
> >   The non-"do-sig" versions of the hash tables will be removed
> >   (including the ``signature_offset`` parameter)
> >   and the "do-sig" versions renamed accordingly.
> > +
> > +* ethdev: An ABI change is planned for 17.11 for the structure
> eth_dev_data.
> Isn't it better to use "``rte_eth_dev_data``"?
> 
> > +  The size of the unique name will increase RTE_ETH_NAME_MAX_LEN
> from
> > + 32 to
> > +  64 characters to allow using a globally unique identifier (GUID) in this
> field.
> 
> Except for the small comment above,
> Acked-by: Yongseok Koh <yskoh@mellanox.com>

Acked-by: Shahaf Shuler <shahafs@mellanox.com>

> 
> Thanks,
> Yongseok

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] doc: announce ABI change for cryptodev and ethdev
  @ 2017-08-08  5:03  4%       ` Shahaf Shuler
  2017-08-08 10:00  4%         ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Shahaf Shuler @ 2017-08-08  5:03 UTC (permalink / raw)
  To: Boris Pismenny, Thomas Monjalon, dev
  Cc: Hemant Agrawal, Akhil Goyal, declan.doherty, radu.nicolau,
	Aviad Yehezkel, pablo.de.lara.guarch, Boris Pismenny

Monday, August 7, 2017 9:07 PM, Boris Pismenny:
> > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > 04/08/2017 07:26, Hemant Agrawal:
> > > On 8/3/2017 9:02 PM, Akhil Goyal wrote:
> > > > Support for security operations is planned to be added in ethdev
> > > > and cryptodev for the 17.11 release.
> > > >
> > > > For this following changes are required.
> > > > - rte_cryptodev and rte_eth_dev structures need to be added new
> > > > parameter rte_security_ops which extend support for security ops
> > > > to the corresponding driver.
> > > > - rte_cryptodev_info and rte_ethd_dev_info need to be added with
> > > > rte_security_capabilities to identify the capabilities of the
> > > > corresponding driver.
> >
> > It is not explained what is the fundamental difference between
> > rte_security and rte_crypto?
> > It looks to be just a technical workaround.
> 
> rte_security is a layer between crypto and NIC.
> 
> Today crypto sessions are created exclusively against crypto devices, but
> they don't use network related fields, while the network namespace doesn't
> use crypto related fields. We expect this API to represent crypto sessions
> that combine network fields and allow to add/delete them for all devices.
> 
> For NICs we will use rte_flow with rte_security for inline/full crypto protocol
> offload such as ESP.
> 
> >
> > Why the ABI would be changed by rte_security additions?
> >
> > > > Signed-off-by: Akhil Goyal <akhil.goyal@nxp.com>
> > > >
> > > Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>
> >
> > No more opinions outside of NXP?
> > It seems there is not yet a consensus on how to manage IPsec offloading.
> > I heard there were some phone calls about these stuff but nothing
> > clear appears publicly on the mailing list.
> > Looks to be a community failure.
> 
> We agreed to go ahead with this approach on one such phone call. I hope we
> could use the dpdk github for development.
> 
> Acked-by: Boris Pismenny <borisp@mellanox.com>

Acked-by: Shahaf Shuler <shahafs@mellanox.com>

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH] doc: announce ABI change for cryptodev and ethdev
  @ 2017-08-08  6:54  7%   ` Akhil Goyal
  0 siblings, 0 replies; 200+ results
From: Akhil Goyal @ 2017-08-08  6:54 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, Declan Doherty
  Cc: Nicolau, Radu, aviadye, borisp, hemant.agrawal, Thomas Monjalon, dev

Hi Pablo/Declan,

On 8/4/2017 8:55 PM, De Lara Guarch, Pablo wrote:
> 
> 
>> -----Original Message-----
>> From: Akhil Goyal [mailto:akhil.goyal@nxp.com]
>> Sent: Thursday, August 3, 2017 4:32 PM
>> To: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>;
>> thomas@monjalon.net; Nicolau, Radu <radu.nicolau@intel.com>;
>> aviadye@mellanox.com; borisp@mellanox.com;
>> hemant.agrawal@nxp.com; De Lara Guarch, Pablo
>> <pablo.de.lara.guarch@intel.com>
>> Cc: Akhil Goyal <akhil.goyal@nxp.com>
>> Subject: [PATCH] doc: announce ABI change for cryptodev and ethdev
>>
>> Support for security operations is planned to be added in ethdev and
>> cryptodev for the 17.11 release.
>>
>> For this following changes are required.
>> - rte_cryptodev and rte_eth_dev structures need to be added new
>> parameter rte_security_ops which extend support for security ops to the
>> corresponding driver.
>> - rte_cryptodev_info and rte_ethd_dev_info need to be added with
>> rte_security_capabilities to identify the capabilities of the corresponding
>> driver.
>>
>> Signed-off-by: Akhil Goyal <akhil.goyal@nxp.com>
> 
> Not sure if this needed to be split into two patches, as this affects two libraries.
> At least, from cryptodev side:
> 
> Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
> 

We would be needing one more ABI change, Can I send it now. I discovered 
it after I sent this patch.

In the struct rte_crypto_sym_op, we would need to add a pointer to a 
security session in the union of session and xform.

Also, Do I need to split this patch into two for crypto and eth?

Regards,
Akhil

^ permalink raw reply	[relevance 7%]

* [dpdk-dev] [PATCH v2] doc: announce ABI change for cryptodev and ethdev
      @ 2017-08-08  7:09  7% ` Akhil Goyal
  2017-08-08  8:08  4%   ` De Lara Guarch, Pablo
  2 siblings, 1 reply; 200+ results
From: Akhil Goyal @ 2017-08-08  7:09 UTC (permalink / raw)
  To: dev, declan.doherty, thomas, radu.nicolau, aviadye, borisp,
	hemant.agrawal, pablo.de.lara.guarch
  Cc: shahafs, Akhil Goyal

Support for security operations is planned to be added
in ethdev and cryptodev for the 17.11 release.

For this following changes are required.
- rte_cryptodev and rte_eth_dev structures need to be added
new parameter rte_security_ops which extend support for
security ops to the corresponding driver.
- rte_cryptodev_info and rte_eth_dev_info need to be added
with rte_security_capabilities to identify the capabilities of
the corresponding driver.
- rte_security_session needs to be added in the union inside
structure rte_crypto_sym_op to decide between various types of
sessions

Signed-off-by: Akhil Goyal <akhil.goyal@nxp.com>
Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>
Acked-by: Boris Pismenny <borisp@mellanox.com>
Acked-by: Shahaf Shuler <shahafs@mellanox.com>
Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
---
changes in v2:
Added one more ABI change wrt to security session,
This patch is not split into 3 patches as these all will be implemented
simultaneously with rte_security support.

 doc/guides/rel_notes/deprecation.rst | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 72d1f35..e34a809 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -78,3 +78,18 @@ Deprecation Notices
   be removed in 17.11:
 
   - ``rte_cryptodev_create_vdev``
+
+* cryptodev: new parameters - ``rte_security_capabilities`` and
+  ``rte_security_ops`` will be added to ``rte_cryptodev_info`` and
+  ``rte_cryptodev`` respectively to support security protocol offloaded
+  operations.
+
+* cryptodev: new parameter ``rte_security_session`` will be added in the union
+  of the structure ``rte_crypto_sym_op``, so that the user can choose either to
+  use ``rte_cryptodev_sym_session`` or ``rte_crypto_sym_xform`` or
+  ``rte_security_session``.
+
+* ethdev: new parameters - ``rte_security_capabilities`` and
+  ``rte_security_ops`` will be added to ``rte_eth_dev_info`` and
+  ``rte_eth_dev`` respectively  to support security operations like
+  ipsec inline.
-- 
2.9.3

^ permalink raw reply	[relevance 7%]

* Re: [dpdk-dev] [PATCH v2] doc: announce ABI change for cryptodev and ethdev
  2017-08-08  7:09  7% ` [dpdk-dev] [PATCH v2] " Akhil Goyal
@ 2017-08-08  8:08  4%   ` De Lara Guarch, Pablo
  2017-08-08  8:42  4%     ` Akhil Goyal
  0 siblings, 1 reply; 200+ results
From: De Lara Guarch, Pablo @ 2017-08-08  8:08 UTC (permalink / raw)
  To: Akhil Goyal, dev, Doherty, Declan, thomas, Nicolau, Radu,
	aviadye, borisp, hemant.agrawal
  Cc: shahafs

Hi Akhil,

> -----Original Message-----
> From: Akhil Goyal [mailto:akhil.goyal@nxp.com]
> Sent: Tuesday, August 8, 2017 8:10 AM
> To: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>;
> thomas@monjalon.net; Nicolau, Radu <radu.nicolau@intel.com>;
> aviadye@mellanox.com; borisp@mellanox.com;
> hemant.agrawal@nxp.com; De Lara Guarch, Pablo
> <pablo.de.lara.guarch@intel.com>
> Cc: shahafs@mellanox.com; Akhil Goyal <akhil.goyal@nxp.com>
> Subject: [PATCH v2] doc: announce ABI change for cryptodev and ethdev
> 
> Support for security operations is planned to be added in ethdev and
> cryptodev for the 17.11 release.
> 
> For this following changes are required.
> - rte_cryptodev and rte_eth_dev structures need to be added new
> parameter rte_security_ops which extend support for security ops to the
> corresponding driver.
> - rte_cryptodev_info and rte_eth_dev_info need to be added with
> rte_security_capabilities to identify the capabilities of the corresponding
> driver.
> - rte_security_session needs to be added in the union inside structure
> rte_crypto_sym_op to decide between various types of sessions
> 
> Signed-off-by: Akhil Goyal <akhil.goyal@nxp.com>
> Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>
> Acked-by: Boris Pismenny <borisp@mellanox.com>
> Acked-by: Shahaf Shuler <shahafs@mellanox.com>
> Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
> ---
> changes in v2:
> Added one more ABI change wrt to security session, This patch is not split
> into 3 patches as these all will be implemented simultaneously with
> rte_security support.
> 
>  doc/guides/rel_notes/deprecation.rst | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/doc/guides/rel_notes/deprecation.rst
> b/doc/guides/rel_notes/deprecation.rst
> index 72d1f35..e34a809 100644
> --- a/doc/guides/rel_notes/deprecation.rst
> +++ b/doc/guides/rel_notes/deprecation.rst
> @@ -78,3 +78,18 @@ Deprecation Notices
>    be removed in 17.11:
> 
>    - ``rte_cryptodev_create_vdev``
> +
> +* cryptodev: new parameters - ``rte_security_capabilities`` and
> +  ``rte_security_ops`` will be added to ``rte_cryptodev_info`` and
> +  ``rte_cryptodev`` respectively to support security protocol offloaded
> +  operations.
> +
> +* cryptodev: new parameter ``rte_security_session`` will be added in
> +the union
> +  of the structure ``rte_crypto_sym_op``, so that the user can choose
> +either to
> +  use ``rte_cryptodev_sym_session`` or ``rte_crypto_sym_xform`` or
> +  ``rte_security_session``.

I don't think it is required to have a deprecation notice for this, as it is adding
another element in a union, and it is not changing its size.
However, this would require an addition in rte_crypto_op_sess_type, which,
as long as it is added at the end, should not require a deprecation notice.

About splitting this into two patches, I would do it, as I believe deprecation notices
should target a specific library.

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [RFC] ethdev: add ioctl-like API to control device specific features
  @ 2017-08-08  8:32  0%           ` Ferruh Yigit
  2017-08-08 15:27  3%             ` Stephen Hemminger
  0 siblings, 1 reply; 200+ results
From: Ferruh Yigit @ 2017-08-08  8:32 UTC (permalink / raw)
  To: Bruce Richardson
  Cc: Thomas Monjalon, dev, Stephen Hemminger, Chilikin, Andrey,
	Ananyev, Konstantin, Wu, Jingjing

On 8/4/2017 1:56 PM, Bruce Richardson wrote:
> On Fri, Aug 04, 2017 at 12:58:01PM +0100, Ferruh Yigit wrote:
>> On 8/3/2017 8:53 PM, Thomas Monjalon wrote:
>>> 03/08/2017 18:15, Stephen Hemminger:
>>>> On Thu, 3 Aug 2017 14:21:38 +0100
>>>> Bruce Richardson <bruce.richardson@intel.com> wrote:
>>>>
>>>>> On Thu, Aug 03, 2017 at 01:21:35PM +0100, Chilikin, Andrey wrote:
>>>>>> To control some device-specific features public device-specific functions
>>>>>> rte_pmd_*.h are used.
>>>>>>
>>>>>> But this solution requires applications to distinguish devices at runtime
>>>>>> and, depending on the device type, call corresponding device-specific
>>>>>> functions even if functions' parameters are the same.
>>>>>>
>>>>>> IOCTL-like API can be added to ethdev instead of public device-specific
>>>>>> functions to address the following:
>>>>>>
>>>>>> * allow more usable support of features across a range of NIC from
>>>>>>   one vendor, but not others
>>>>>> * allow features to be implemented by multiple NIC drivers without
>>>>>>   relying on a critical mass to get the functionality in ethdev
>>>>>> * there are a large number of possible device specific functions, and
>>>>>>   creating individual APIs for each one is not a good solution
>>>>>> * IOCTLs are a proven method for solving this problem in other areas,
>>>>>>   i.e. OS kernels.
>>>>>>
>>>>>> Control requests for this API will be globally defined at ethdev level, so
>>>>>> an application will use single API call to control different devices from
>>>>>> one/multiple vendors.
>>>>>>
>>>>>> API call may look like as a classic ioctl with an extra parameter for
>>>>>> argument length for better sanity checks:
>>>>>>
>>>>>> int
>>>>>> rte_eth_dev_ioctl(uint16_t port, uint64_t ctl, void *argp,
>>>>>>         unsigned arg_length);
>>>>>>
>>>>>> Regards,
>>>>>> Andrey  
>>>>>
>>>>> I think we need to start putting in IOCTLs for ethdevs, much as I hate
>>>>> to admit it, since I dislike IOCTLs and other functions with opaque
>>>>> arguments! Having driver specific functions I don't think will scale
>>>>> well as each vendor tries to expose as much of their driver specific
>>>>> functionality as possible.
>>>>>
>>>>> One other additional example: I discovered just this week another issue
>>>>> with driver specific functions and testpmd, when I was working on the
>>>>> meson build rework.
>>>>>
>>>>> * With shared libraries, when we do "ninja install" we want our DPDK
>>>>>   libs moved to e.g. /usr/local/lib, but the drivers moved to a separate
>>>>>   driver folder, so that they can be automatically loaded from that
>>>>>   single location by DPDK apps [== CONFIG_RTE_EAL_PMD_PATH].
>>>>> * However, testpmd, as well as using the drivers as plugins, uses
>>>>>   driver-specific functions, which means that it explicitly links
>>>>>   against the pmd .so files.
>>>>> * Those driver .so files are not in with the other libraries, so ld.so
>>>>>   does not find the pmd, and the installed testpmd fails to run due to
>>>>>   missing library dependencies.
>>>>> * The workaround is to add the drivers path to the ld load path, but we
>>>>>   should not require ld library path changes just to get DPDK apps to
>>>>>   work.
>>>>>
>>>>> Using ioctls instead of driver-specific functions would solve this.
>>>>>
>>>>> My 2c.
>>>>
>>>> My 2c. No.
>>>>
>>>> Short answer:
>>>> Ioctl's were a bad idea in Unix (per Dennis Ritchie et al) and are now
>>>> despised by Linux kernel developers. They provide an unstructured, unsecured,
>>>> back door for device driver abuse. Try to get a new driver in Linux with
>>>> a unique ioctl, and it will be hard to get accepted.
>>>>
>>>> Long answer:
>>>> So far every device specific feature has fit into ethdev model. Doing ioctl
>>>> is admitting "it is too hard to be general, we need need an out". For something
>>>> that is a flag, it should fit into existing config model; ignoring silly ABI constraints.
>>>> For a real feature (think flow direction), we want a first class API for that.
>>>> For a wart, then devargs will do.
>>>>
>>>> Give a good example of something that should be an ioctl. Don't build the
>>>> API first and then let it get cluttered.
>>>
>>> I agree with Stephen.
>>>
>>> And please do not forget that ioctl still requires an API:
>>> the argument that you put in ioctl is the API of the feature.
>>> So it is the same thing as defining a new function.
>>
>> I am also not fan of the ioctl usage. I believe it hides APIs behind ids
>> and prevent argument check by compiler.
>>
>> BUT, the number of the increasing PMD specific APIs are also worrying,
>> it is becoming harder to maintain, and I believe this is something NOT
>> sustainable in long run.
>>
>>
>> What about having *eth_dev_extended_ops* ?
>>
>>
>> As a part of the rte_eth_dev. This can be in the librte_ether library
>> but in a separated file.
>>
>> And the APIs for these ops can be less strict on compatibility, and
>> easier to add.
>>
>> Benefits of having this new dev_ops:
>>
>> * Having an abstraction layer for common checks.
>>
>> * Even feature is not generic for all NICs, still a few NICs can share
>> the ops.
>>
>> * All APIs are in the same file makes it easy to see PMD specific APIs
>> comparing to scattered into various PMDs.
>>
>> * This is very like ioctl approach, but APIs are more clear and
>> arguments can be verified.
>>
> 
> Sounds like an ethdev-staging library, where features can be put until
> such time as they get critical mass for acceptance and promoted to
> ethdev? It's sounds better than IOCTL, while giving the same benefits.
> 
> I'd be happy enough with any solution that allows NIC features to be
> exposed that does not have functions limited to each individual driver,
> so that common functionality can be exposed to apps via an API even if
> only 2 drivers support it.

This is not decided yet, but to enable working on this for next release,
is a deprecation notice required to add a new field to "struct
rte_eth_dev" ?

"struct rte_eth_dev" is marked as "@internal", so I believe deprecation
notice is NOT required, but I would like to confirm.

> 
>> Thanks,
>> ferruh
>>
>>
>>>
>>> The real debate is to decide if we want to continue adding more
>>> control path features in DPDK or focus on Rx/Tx.
> I don't see dropping control path as an option. It would severely limit
> the usefulness of DPDK.
> 
> /Bruce
> 

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2] doc: announce ABI change for cryptodev and ethdev
  2017-08-08  8:08  4%   ` De Lara Guarch, Pablo
@ 2017-08-08  8:42  4%     ` Akhil Goyal
  0 siblings, 0 replies; 200+ results
From: Akhil Goyal @ 2017-08-08  8:42 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, dev, Doherty, Declan, thomas, Nicolau,
	Radu, aviadye, borisp, hemant.agrawal
  Cc: shahafs

Hi Pablo,

On 8/8/2017 1:38 PM, De Lara Guarch, Pablo wrote:
> Hi Akhil,
> 
>> -----Original Message-----
>> From: Akhil Goyal [mailto:akhil.goyal@nxp.com]
>> Sent: Tuesday, August 8, 2017 8:10 AM
>> To: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>;
>> thomas@monjalon.net; Nicolau, Radu <radu.nicolau@intel.com>;
>> aviadye@mellanox.com; borisp@mellanox.com;
>> hemant.agrawal@nxp.com; De Lara Guarch, Pablo
>> <pablo.de.lara.guarch@intel.com>
>> Cc: shahafs@mellanox.com; Akhil Goyal <akhil.goyal@nxp.com>
>> Subject: [PATCH v2] doc: announce ABI change for cryptodev and ethdev
>>
>> Support for security operations is planned to be added in ethdev and
>> cryptodev for the 17.11 release.
>>
>> For this following changes are required.
>> - rte_cryptodev and rte_eth_dev structures need to be added new
>> parameter rte_security_ops which extend support for security ops to the
>> corresponding driver.
>> - rte_cryptodev_info and rte_eth_dev_info need to be added with
>> rte_security_capabilities to identify the capabilities of the corresponding
>> driver.
>> - rte_security_session needs to be added in the union inside structure
>> rte_crypto_sym_op to decide between various types of sessions
>>
>> Signed-off-by: Akhil Goyal <akhil.goyal@nxp.com>
>> Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>
>> Acked-by: Boris Pismenny <borisp@mellanox.com>
>> Acked-by: Shahaf Shuler <shahafs@mellanox.com>
>> Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
>> ---
>> changes in v2:
>> Added one more ABI change wrt to security session, This patch is not split
>> into 3 patches as these all will be implemented simultaneously with
>> rte_security support.
>>
>>   doc/guides/rel_notes/deprecation.rst | 15 +++++++++++++++
>>   1 file changed, 15 insertions(+)
>>
>> diff --git a/doc/guides/rel_notes/deprecation.rst
>> b/doc/guides/rel_notes/deprecation.rst
>> index 72d1f35..e34a809 100644
>> --- a/doc/guides/rel_notes/deprecation.rst
>> +++ b/doc/guides/rel_notes/deprecation.rst
>> @@ -78,3 +78,18 @@ Deprecation Notices
>>     be removed in 17.11:
>>
>>     - ``rte_cryptodev_create_vdev``
>> +
>> +* cryptodev: new parameters - ``rte_security_capabilities`` and
>> +  ``rte_security_ops`` will be added to ``rte_cryptodev_info`` and
>> +  ``rte_cryptodev`` respectively to support security protocol offloaded
>> +  operations.
>> +
>> +* cryptodev: new parameter ``rte_security_session`` will be added in
>> +the union
>> +  of the structure ``rte_crypto_sym_op``, so that the user can choose
>> +either to
>> +  use ``rte_cryptodev_sym_session`` or ``rte_crypto_sym_xform`` or
>> +  ``rte_security_session``.
> 
> I don't think it is required to have a deprecation notice for this, as it is adding
> another element in a union, and it is not changing its size.
> However, this would require an addition in rte_crypto_op_sess_type, which,
> as long as it is added at the end, should not require a deprecation notice.
> 
> About splitting this into two patches, I would do it, as I believe deprecation notices
> should target a specific library.
> 
> 
> 

Thanks for the comments. I have marked the v2 as not applicable and 
marked v1 as in review in the patchwork.

-Akhil

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v3] ethdev: add return code to rte_eth_stats_reset()
  @ 2017-08-08  9:02  5% ` Van Haaren, Harry
  2017-08-08 11:01  0%   ` David Harton (dharton)
  2017-08-08 11:03  4%   ` Christian Ehrhardt
    1 sibling, 2 replies; 200+ results
From: Van Haaren, Harry @ 2017-08-08  9:02 UTC (permalink / raw)
  To: David Harton, thomas; +Cc: dev

> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of David Harton
> Sent: Monday, August 7, 2017 6:39 PM
> To: thomas@monjalon.net
> Cc: dev@dpdk.org; David Harton <dharton@cisco.com>
> Subject: [dpdk-dev] [PATCH v3] ethdev: add return code to rte_eth_stats_reset()
> 
> Some devices do not support reset of eth stats.  An application may
> need to know not to clear shadow stats if the device cannot.
> 
> rte_eth_stats_reset is updated to provide a return code to share
> whether the device supports reset or not.
> 
> Signed-off-by: David Harton <dharton@cisco.com>
> ---

Hi,

As far as I know changing the return type (void to int) of a function does *not* break ABI, but does "break" API as the application code should now check the return value. In theory the application could ignore the return value and current behavior is maintained.

The validate-abi.sh script says "Compatible" with the following item flagged:

Problems with Symbols
High 0
Medium 0
Low	1

Change>> Type of return value has been changed from void to int (4 bytes).
Effect>> Replacement of return type may indicate a change in its semantic meaning.

Perhaps somebody with more ABI expertise than I would double check the return value change?


Some smaller things inline below.

> v3:
> * overcame noob errors and figured out patch challenges
> * this release should finally be clean :)
> 
> v2:
> * fixed soft tab issue inserted while moving changes
> 
>  lib/librte_ether/rte_ethdev.c | 8 +++++---
>  lib/librte_ether/rte_ethdev.h | 4 +++-
>  2 files changed, 8 insertions(+), 4 deletions(-)
> 
> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
> index 0597641..f72cc5a 100644
> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -1341,17 +1341,19 @@ rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats)
>  	return 0;
>  }
> 
> -void
> +int
>  rte_eth_stats_reset(uint8_t port_id)
>  {
>  	struct rte_eth_dev *dev;
> 
> -	RTE_ETH_VALID_PORTID_OR_RET(port_id);
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
>  	dev = &rte_eth_devices[port_id];
> 
> -	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_reset, -ENOTSUP);
>  	(*dev->dev_ops->stats_reset)(dev);
>  	dev->data->rx_mbuf_alloc_failed = 0;
> +
> +	return 0;
>  }
> 
>  static int
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index 0adf327..d8ccd60 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -2246,8 +2246,10 @@ int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats
> *stats);
>   *
>   * @param port_id
>   *   The port identifier of the Ethernet device.
> + * @return
> + *   Zero if successful. Non-zero otherwise.

We should document all return values:

@retval 0 Success
@retval -EINVAL Invalid port_id provided
@retval -ENOTSUP Stats reset functionality not supported by PMD

The API change itself should probably be added to release notes, as
applications may wish to be aware this function has changed.

>   */
> -void rte_eth_stats_reset(uint8_t port_id);
> +int rte_eth_stats_reset(uint8_t port_id);
> 
>  /**
>   * Retrieve names of extended statistics of an Ethernet device.
> --
> 2.10.3.dirty


I'm happy to Ack the code/release-notes with above suggestions, but I'd like a second opinion to Ack ABI.

-Harry

^ permalink raw reply	[relevance 5%]

* Re: [dpdk-dev] [PATCH] ethdev: add notice for planned name size change
  2017-08-08  4:56  0%   ` Shahaf Shuler
@ 2017-08-08  9:47  0%     ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-08  9:47 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev, Shahaf Shuler, Yongseok Koh

> > > VMBUS support will use GUID in eth_dev_data name field which requires
> > > at least 37 characters. Plan for increase in size now.
> > >
> > > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> > > ---
> > > +* ethdev: An ABI change is planned for 17.11 for the structure
> > eth_dev_data.
> > Isn't it better to use "``rte_eth_dev_data``"?
> > 
> > > +  The size of the unique name will increase RTE_ETH_NAME_MAX_LEN
> > from
> > > + 32 to
> > > +  64 characters to allow using a globally unique identifier (GUID) in this
> > field.
> > 
> > Except for the small comment above,
> > Acked-by: Yongseok Koh <yskoh@mellanox.com>
> 
> Acked-by: Shahaf Shuler <shahafs@mellanox.com>

Acked-by: Thomas Monjalon <thomas@monjalon.net>

Applied, thanks

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] doc: announce ABI change for cryptodev and ethdev
  2017-08-08  5:03  4%       ` Shahaf Shuler
@ 2017-08-08 10:00  4%         ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-08 10:00 UTC (permalink / raw)
  To: Akhil Goyal
  Cc: dev, Shahaf Shuler, Boris Pismenny, Hemant Agrawal,
	declan.doherty, radu.nicolau, Aviad Yehezkel,
	pablo.de.lara.guarch, techboard

08/08/2017 07:03, Shahaf Shuler:
> Monday, August 7, 2017 9:07 PM, Boris Pismenny:
> > > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > > 04/08/2017 07:26, Hemant Agrawal:
> > > > On 8/3/2017 9:02 PM, Akhil Goyal wrote:
> > > > > Support for security operations is planned to be added in ethdev
> > > > > and cryptodev for the 17.11 release.
> > > > >
> > > > > For this following changes are required.
> > > > > - rte_cryptodev and rte_eth_dev structures need to be added new
> > > > > parameter rte_security_ops which extend support for security ops
> > > > > to the corresponding driver.
> > > > > - rte_cryptodev_info and rte_ethd_dev_info need to be added with
> > > > > rte_security_capabilities to identify the capabilities of the
> > > > > corresponding driver.
> > >
> > > It is not explained what is the fundamental difference between
> > > rte_security and rte_crypto?
> > > It looks to be just a technical workaround.
> > 
> > rte_security is a layer between crypto and NIC.
> > 
> > Today crypto sessions are created exclusively against crypto devices, but
> > they don't use network related fields, while the network namespace doesn't
> > use crypto related fields. We expect this API to represent crypto sessions
> > that combine network fields and allow to add/delete them for all devices.
> > 
> > For NICs we will use rte_flow with rte_security for inline/full crypto protocol
> > offload such as ESP.
> > 
> > >
> > > Why the ABI would be changed by rte_security additions?
> > >
> > > > > Signed-off-by: Akhil Goyal <akhil.goyal@nxp.com>
> > > > >
> > > > Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>
> > >
> > > No more opinions outside of NXP?
> > > It seems there is not yet a consensus on how to manage IPsec offloading.
> > > I heard there were some phone calls about these stuff but nothing
> > > clear appears publicly on the mailing list.
> > > Looks to be a community failure.
> > 
> > We agreed to go ahead with this approach on one such phone call. I hope we
> > could use the dpdk github for development.
> > 
> > Acked-by: Boris Pismenny <borisp@mellanox.com>
> 
> Acked-by: Shahaf Shuler <shahafs@mellanox.com>

Applied
It means you have a chance to do this change in 17.11.
It does not mean you can be sure that the patches will be accepted.

This is introducing a new complexity.
It must be discussed with the technical board before approving
the final design in 17.11.

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v3] doc: announce API and ABI change for ethdev
  2017-08-08  4:02  4%   ` Yang, Zhiyong
@ 2017-08-08  9:35  4%     ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-08  9:35 UTC (permalink / raw)
  To: Yang, Zhiyong
  Cc: dev, Tan, Jianfeng, yliu, jerin.jacob, Horton, Remy, shahafs

> > This is an API/ABI change notice for DPDK 17.11 announcing the redefinition of
> > port_id. port_id is currently defined as uint8_t, which is limited to the range 0 to
> > 255. A larger range is required for vdev scalability.
> > 
> > It is necessary for a redefinition of port_id to extend it from 1 bytes to
> > 2 bytes. All ethdev APIs and usages related to port_id will be changed at the
> > same time.
> > 
> > cc: jianfeng.tan@intel.com
> > cc: yliu@fridaylinux.org
> > cc: jerin.jacob@caviumnetworks.com
> > cc: thomas@monjalon.net
> > cc: remy.horton@intel.com
> > 
> > Signed-off-by: Zhiyong Yang <zhiyong.yang@intel.com>
> > Acked-by: Jianfeng Tan <jianfeng.tan@intel.com>
> > Acked-by: Yuanhan Liu <yliu@fridaylinux.org>
> > Acked-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
> > Acked-by: Remy Horton <remy.horton@intel.com>
> 
> This ack in v2 is added in v3. Thanks, Shahaf.
> 
> Acked-by: Shahaf Shuler <shahafs@mellanox.com>

Applied, thanks

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v3] ethdev: add return code to rte_eth_stats_reset()
  2017-08-08  9:02  5% ` Van Haaren, Harry
@ 2017-08-08 11:01  0%   ` David Harton (dharton)
  2017-08-08 11:03  4%   ` Christian Ehrhardt
  1 sibling, 0 replies; 200+ results
From: David Harton (dharton) @ 2017-08-08 11:01 UTC (permalink / raw)
  To: Van Haaren, Harry, thomas; +Cc: dev

> -----Original Message-----
> From: Van Haaren, Harry [mailto:harry.van.haaren@intel.com]
> Sent: Tuesday, August 08, 2017 5:03 AM
> To: David Harton (dharton) <dharton@cisco.com>; thomas@monjalon.net
> Cc: dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v3] ethdev: add return code to
> rte_eth_stats_reset()
> 
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of David Harton
> > Sent: Monday, August 7, 2017 6:39 PM
> > To: thomas@monjalon.net
> > Cc: dev@dpdk.org; David Harton <dharton@cisco.com>
> > Subject: [dpdk-dev] [PATCH v3] ethdev: add return code to
> > rte_eth_stats_reset()
> >
> > Some devices do not support reset of eth stats.  An application may
> > need to know not to clear shadow stats if the device cannot.
> >
> > rte_eth_stats_reset is updated to provide a return code to share
> > whether the device supports reset or not.
> >
> > Signed-off-by: David Harton <dharton@cisco.com>
> > ---
> 
> Hi,
> 
> As far as I know changing the return type (void to int) of a function does
> *not* break ABI, but does "break" API as the application code should now
> check the return value. In theory the application could ignore the return
> value and current behavior is maintained.
> 
> The validate-abi.sh script says "Compatible" with the following item
> flagged:
> 
> Problems with Symbols
> High 0
> Medium 0
> Low	1
> 
> Change>> Type of return value has been changed from void to int (4 bytes).
> Effect>> Replacement of return type may indicate a change in its semantic
> meaning.
> 
> Perhaps somebody with more ABI expertise than I would double check the
> return value change?
> 
> 
> Some smaller things inline below.
> 
> > v3:
> > * overcame noob errors and figured out patch challenges
> > * this release should finally be clean :)
> >
> > v2:
> > * fixed soft tab issue inserted while moving changes
> >
> >  lib/librte_ether/rte_ethdev.c | 8 +++++---
> > lib/librte_ether/rte_ethdev.h | 4 +++-
> >  2 files changed, 8 insertions(+), 4 deletions(-)
> >
> > diff --git a/lib/librte_ether/rte_ethdev.c
> > b/lib/librte_ether/rte_ethdev.c index 0597641..f72cc5a 100644
> > --- a/lib/librte_ether/rte_ethdev.c
> > +++ b/lib/librte_ether/rte_ethdev.c
> > @@ -1341,17 +1341,19 @@ rte_eth_stats_get(uint8_t port_id, struct
> rte_eth_stats *stats)
> >  	return 0;
> >  }
> >
> > -void
> > +int
> >  rte_eth_stats_reset(uint8_t port_id)
> >  {
> >  	struct rte_eth_dev *dev;
> >
> > -	RTE_ETH_VALID_PORTID_OR_RET(port_id);
> > +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
> >  	dev = &rte_eth_devices[port_id];
> >
> > -	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
> > +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_reset, -ENOTSUP);
> >  	(*dev->dev_ops->stats_reset)(dev);
> >  	dev->data->rx_mbuf_alloc_failed = 0;
> > +
> > +	return 0;
> >  }
> >
> >  static int
> > diff --git a/lib/librte_ether/rte_ethdev.h
> > b/lib/librte_ether/rte_ethdev.h index 0adf327..d8ccd60 100644
> > --- a/lib/librte_ether/rte_ethdev.h
> > +++ b/lib/librte_ether/rte_ethdev.h
> > @@ -2246,8 +2246,10 @@ int rte_eth_stats_get(uint8_t port_id, struct
> > rte_eth_stats *stats);
> >   *
> >   * @param port_id
> >   *   The port identifier of the Ethernet device.
> > + * @return
> > + *   Zero if successful. Non-zero otherwise.
> 
> We should document all return values:
> 
> @retval 0 Success
> @retval -EINVAL Invalid port_id provided @retval -ENOTSUP Stats reset
> functionality not supported by PMD

Sure.  I was following the convention of function above it
rte_eth_stats_get() but I agree better to advertise externally.
I'll also modify the port number check errval to -ENODEV.

> 
> The API change itself should probably be added to release notes, as
> applications may wish to be aware this function has changed.

Sounds good.

> 
> >   */
> > -void rte_eth_stats_reset(uint8_t port_id);
> > +int rte_eth_stats_reset(uint8_t port_id);
> >
> >  /**
> >   * Retrieve names of extended statistics of an Ethernet device.
> > --
> > 2.10.3.dirty
> 
> 
> I'm happy to Ack the code/release-notes with above suggestions, but I'd
> like a second opinion to Ack ABI.

Thanks for the review,
Dave

> 
> -Harry

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3] ethdev: add return code to rte_eth_stats_reset()
  2017-08-08  9:02  5% ` Van Haaren, Harry
  2017-08-08 11:01  0%   ` David Harton (dharton)
@ 2017-08-08 11:03  4%   ` Christian Ehrhardt
  2017-08-08 13:13  3%     ` Thomas Monjalon
  1 sibling, 1 reply; 200+ results
From: Christian Ehrhardt @ 2017-08-08 11:03 UTC (permalink / raw)
  To: Van Haaren, Harry; +Cc: David Harton, thomas, dev

On Tue, Aug 8, 2017 at 11:02 AM, Van Haaren, Harry <
harry.van.haaren@intel.com> wrote:

> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of David Harton
> > Sent: Monday, August 7, 2017 6:39 PM
> > To: thomas@monjalon.net
> > Cc: dev@dpdk.org; David Harton <dharton@cisco.com>
> > Subject: [dpdk-dev] [PATCH v3] ethdev: add return code to
> rte_eth_stats_reset()
> >
> > Some devices do not support reset of eth stats.  An application may
> > need to know not to clear shadow stats if the device cannot.
> >
> > rte_eth_stats_reset is updated to provide a return code to share
> > whether the device supports reset or not.
> >
> > Signed-off-by: David Harton <dharton@cisco.com>
> > ---
>
> Hi,
>
> As far as I know changing the return type (void to int) of a function does
> *not* break ABI, but does "break" API as the application code should now
> check the return value. In theory the application could ignore the return
> value and current behavior is maintained.
>

After discussing with Harry on IRC it turns out we both ended up checking
the same online sources
to verify our thoughts, like [1].

Given this and several other sources it seems to be as outlined above an
API but not ABI break.
I'm not an expert and this is mostly opinion, but my personal rule mostly
is: "if in doubt bump it".
Running similar issues I was the one providing [2] for a reason, with this
here being a case that
appears safe but there eventually always seems to come up an architecture
or alternative compiler
which does some arcane register juggling differently and makes those "safe"
changes breaking people after the fact.

[1]:
https://stackoverflow.com/questions/15626579/c-abi-is-it-safe-to-change-void-function-to-return-int
[2]:
http://dpdk.org/doc/guides/contributing/versioning.html#setting-a-major-abi-version

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v1] doc: add template release notes for 17.11
@ 2017-08-08 12:31  6% John McNamara
  2017-08-09  8:22  6% ` [dpdk-dev] [PATCH v2] " John McNamara
  0 siblings, 1 reply; 200+ results
From: John McNamara @ 2017-08-08 12:31 UTC (permalink / raw)
  To: dev; +Cc: John McNamara

Add template release notes for DPDK 17.11 with inline
comments and explanations of the various sections.

Signed-off-by: John McNamara <john.mcnamara@intel.com>
---
 doc/guides/rel_notes/index.rst         |   1 +
 doc/guides/rel_notes/release_17_11.rst | 199 +++++++++++++++++++++++++++++++++
 2 files changed, 200 insertions(+)
 create mode 100644 doc/guides/rel_notes/release_17_11.rst

diff --git a/doc/guides/rel_notes/index.rst b/doc/guides/rel_notes/index.rst
index b3c8090..35659d8 100644
--- a/doc/guides/rel_notes/index.rst
+++ b/doc/guides/rel_notes/index.rst
@@ -36,6 +36,7 @@ Release Notes
     :numbered:
 
     rel_description
+    release_17_11
     release_17_08
     release_17_05
     release_17_02
diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
new file mode 100644
index 0000000..6e5768f
--- /dev/null
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -0,0 +1,199 @@
+DPDK Release 17.11
+==================
+
+.. **Read this first.**
+
+   The text in the sections below explains how to update the release notes.
+
+   Use proper spelling, capitalization and punctuation in all sections.
+
+   Variable and config names should be quoted as fixed width text:
+   ``LIKE_THIS``.
+
+   Build the docs and view the output file to ensure the changes are correct::
+
+      make doc-guides-html
+
+      xdg-open build/doc/html/guides/rel_notes/release_17_11.html
+
+
+New Features
+------------
+
+.. This section should contain new features added in this release. Sample
+   format:
+
+   * **Add a title in the past tense with a full stop.**
+
+     Add a short 1-2 sentence description in the past tense. The description
+     should be enough to allow someone scanning the release notes to
+     understand the new feature.
+
+     If the feature adds a lot of sub-features you can use a bullet list like
+     this:
+
+     * Added feature foo to do something.
+     * Enhanced feature bar to do something else.
+
+     Refer to the previous release notes for examples.
+
+     This section is a comment. do not overwrite or remove it.
+     Also, make sure to start the actual text at the margin.
+     =========================================================
+
+
+Resolved Issues
+---------------
+
+.. This section should contain bug fixes added to the relevant
+   sections. Sample format:
+
+   * **code/section Fixed issue in the past tense with a full stop.**
+
+     Add a short 1-2 sentence description of the resolved issue in the past
+     tense.
+
+     The title should contain the code/lib section like a commit message.
+
+     Add the entries in alphabetic order in the relevant sections below.
+
+   This section is a comment. do not overwrite or remove it.
+   Also, make sure to start the actual text at the margin.
+   =========================================================
+
+
+EAL
+~~~
+
+
+Drivers
+~~~~~~~
+
+
+Libraries
+~~~~~~~~~
+
+
+Examples
+~~~~~~~~
+
+
+Other
+~~~~~
+
+
+Known Issues
+------------
+
+.. This section should contain new known issues in this release. Sample format:
+
+   * **Add title in present tense with full stop.**
+
+     Add a short 1-2 sentence description of the known issue in the present
+     tense. Add information on any known workarounds.
+
+   This section is a comment. do not overwrite or remove it.
+   Also, make sure to start the actual text at the margin.
+   =========================================================
+
+
+API Changes
+-----------
+
+.. This section should contain API changes. Sample format:
+
+   * Add a short 1-2 sentence description of the API change. Use fixed width
+     quotes for ``rte_function_names`` or ``rte_struct_names``. Use the past
+     tense.
+
+   This section is a comment. do not overwrite or remove it.
+   Also, make sure to start the actual text at the margin.
+   =========================================================
+
+
+ABI Changes
+-----------
+
+.. This section should contain ABI changes. Sample format:
+
+   * Add a short 1-2 sentence description of the ABI change that was announced
+     in the previous releases and made in this release. Use fixed width quotes
+     for ``rte_function_names`` or ``rte_struct_names``. Use the past tense.
+
+   This section is a comment. do not overwrite or remove it.
+   Also, make sure to start the actual text at the margin.
+   =========================================================
+
+
+
+Shared Library Versions
+-----------------------
+
+.. Update any library version updated in this release and prepend with a ``+``
+   sign, like this:
+
+     librte_acl.so.2
+   + librte_cfgfile.so.2
+     librte_cmdline.so.2
+
+   This section is a comment. do not overwrite or remove it.
+   =========================================================
+
+
+The libraries prepended with a plus sign were incremented in this version.
+
+.. code-block:: diff
+
+     librte_acl.so.2
+     librte_bitratestats.so.1
+     librte_cfgfile.so.2
+     librte_cmdline.so.2
+     librte_cryptodev.so.3
+     librte_distributor.so.1
+     librte_eal.so.4
+     librte_ethdev.so.7
+     librte_gro.so.1
+     librte_hash.so.2
+     librte_ip_frag.so.1
+     librte_jobstats.so.1
+     librte_kni.so.2
+     librte_kvargs.so.1
+     librte_latencystats.so.1
+     librte_lpm.so.2
+     librte_mbuf.so.3
+     librte_mempool.so.2
+     librte_meter.so.1
+     librte_metrics.so.1
+     librte_net.so.1
+     librte_pdump.so.1
+     librte_pipeline.so.3
+     librte_pmd_bond.so.1
+     librte_pmd_ring.so.2
+     librte_port.so.3
+     librte_power.so.1
+     librte_reorder.so.1
+     librte_ring.so.1
+     librte_sched.so.1
+     librte_table.so.2
+     librte_timer.so.1
+     librte_vhost.so.3
+
+
+Tested Platforms
+----------------
+
+.. This section should contain a list of platforms that were tested with this
+   release.
+
+   The format is:
+
+   * <vendor> platform with <vendor> <type of devices> combinations
+
+     * List of CPU
+     * List of OS
+     * List of devices
+     * Other relevant details...
+
+   This section is a comment. do not overwrite or remove it.
+   Also, make sure to start the actual text at the margin.
+   =========================================================
-- 
2.7.4

^ permalink raw reply	[relevance 6%]

* Re: [dpdk-dev] [PATCH v3] ethdev: add return code to rte_eth_stats_reset()
  2017-08-08 11:03  4%   ` Christian Ehrhardt
@ 2017-08-08 13:13  3%     ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-08 13:13 UTC (permalink / raw)
  To: Christian Ehrhardt, David Harton; +Cc: Van Haaren, Harry, dev

08/08/2017 13:03, Christian Ehrhardt:
> On Tue, Aug 8, 2017 at 11:02 AM, Van Haaren, Harry <
> harry.van.haaren@intel.com> wrote:
> > >
> > > Some devices do not support reset of eth stats.  An application may
> > > need to know not to clear shadow stats if the device cannot.
> > >
> > > rte_eth_stats_reset is updated to provide a return code to share
> > > whether the device supports reset or not.
> > >
> > > Signed-off-by: David Harton <dharton@cisco.com>
> > > ---
> >
> > Hi,
> >
> > As far as I know changing the return type (void to int) of a function does
> > *not* break ABI, but does "break" API as the application code should now
> > check the return value. In theory the application could ignore the return
> > value and current behavior is maintained.
> >
> 
> After discussing with Harry on IRC it turns out we both ended up checking
> the same online sources
> to verify our thoughts, like [1].
> 
> Given this and several other sources it seems to be as outlined above an
> API but not ABI break.
> I'm not an expert and this is mostly opinion, but my personal rule mostly
> is: "if in doubt bump it".

Anyway, the ABI will be broken (and bumped) again in 17.11.
This patch will be accepted in 17.11.

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH] eal: bump ABI version for PCI, bus and devargs work
@ 2017-08-08 14:26  4% Gaetan Rivet
  2017-08-08 17:26  4% ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Gaetan Rivet @ 2017-08-08 14:26 UTC (permalink / raw)
  To: dev; +Cc: Gaetan Rivet

1. PCI domain field in PCI address structure grew from 16 to 32 bits.

   From: 463ced957c3f ("pci: increase domain storage to 32 bits")

2. rte_bus structure gaining new ops.

   From: 3a8f0bc68a90 ("bus: add method to find device")
   From: 7c8810f43f6e ("bus: introduce device plug/unplug")
   From: 609eb7dde6d0 ("bus: introduce parsing functionality")
   From: 98eb4b845c1a ("bus: introduce scan policies")

3. rte_devargs structure having been mostly rewritten.

   From: f3a1188cee4a ("devargs: make device representation generic")
   From: 47828c5f3bc3 ("devargs: parse bus info")
   From: 39f403e0d5bb ("devargs: restore device type API")

Signed-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 lib/librte_eal/bsdapp/eal/Makefile   | 2 +-
 lib/librte_eal/linuxapp/eal/Makefile | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index 05517a2..005019e 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -48,7 +48,7 @@ LDLIBS += -lgcc_s
 
 EXPORT_MAP := rte_eal_version.map
 
-LIBABIVER := 4
+LIBABIVER := 5
 
 # specific to bsdapp exec-env
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) := eal.c
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index e6ab6c3..90bca4d 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -37,7 +37,7 @@ ARCH_DIR ?= $(RTE_ARCH)
 EXPORT_MAP := rte_eal_version.map
 VPATH += $(RTE_SDK)/lib/librte_eal/common/arch/$(ARCH_DIR)
 
-LIBABIVER := 4
+LIBABIVER := 5
 
 VPATH += $(RTE_SDK)/lib/librte_eal/common
 
-- 
2.1.4

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH] doc: notify EAL ABI change
@ 2017-08-08 14:26  9% Gaetan Rivet
  2017-08-08 17:27  4% ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Gaetan Rivet @ 2017-08-08 14:26 UTC (permalink / raw)
  To: dev; +Cc: Gaetan Rivet

Signed-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 doc/guides/rel_notes/release_17_08.rst | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_17_08.rst b/doc/guides/rel_notes/release_17_08.rst
index a137aa7..a723252 100644
--- a/doc/guides/rel_notes/release_17_08.rst
+++ b/doc/guides/rel_notes/release_17_08.rst
@@ -343,6 +343,14 @@ ABI Changes
 
 * Removed ``session_mp`` from ``rte_cryptodev_config``.
 
+* Changed type of ``domain`` field in ``rte_pci_addr`` to ``uint32_t``
+  to follow the PCI standard.
+
+* Added new ``rte_bus`` experimental APIs available as operators within the
+  ``rte_bus`` structure.
+
+* Made ``rte_devargs`` structure internal device representation generic to
+  prepare for a bus-agnostic EAL.
 
 Shared Library Versions
 -----------------------
@@ -368,7 +376,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_cmdline.so.2
    + librte_cryptodev.so.3
      librte_distributor.so.1
-     librte_eal.so.4
+   + librte_eal.so.5
    + librte_ethdev.so.7
    + librte_gro.so.1
      librte_hash.so.2
-- 
2.1.4

^ permalink raw reply	[relevance 9%]

* [dpdk-dev]  [PATCH 2/2] eventdev: bump library version
  @ 2017-08-08 14:48  3% ` Jerin Jacob
  2017-08-08 17:45  0%   ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Jerin Jacob @ 2017-08-08 14:48 UTC (permalink / raw)
  To: dev; +Cc: thomas, john.mcnamara, Jerin Jacob

Bumping the library version to reflect the ABI change, where
rte_event_pmd_pci_probe(), rte_event_pmd_pci_remove(),
rte_event_pmd_vdev_init(), rte_event_pmd_vdev_uninit()
functions removed from the library.

Fixes: b1b3d9f90502 ("eventdev: make vdev init and uninit functions optional")
Fixes: 9a8269d56942 ("eventdev: make PCI probe and remove functions optional")

Reported-by: Thomas Monjalon <thomas.monjalon@6wind.com>
Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
---
 doc/guides/rel_notes/release_17_08.rst | 1 +
 lib/librte_eventdev/Makefile           | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_17_08.rst b/doc/guides/rel_notes/release_17_08.rst
index a137aa79f..1c2bc6de9 100644
--- a/doc/guides/rel_notes/release_17_08.rst
+++ b/doc/guides/rel_notes/release_17_08.rst
@@ -370,6 +370,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_distributor.so.1
      librte_eal.so.4
    + librte_ethdev.so.7
+   + librte_eventdev.so.2
    + librte_gro.so.1
      librte_hash.so.2
      librte_ip_frag.so.1
diff --git a/lib/librte_eventdev/Makefile b/lib/librte_eventdev/Makefile
index 64165020a..410578a14 100644
--- a/lib/librte_eventdev/Makefile
+++ b/lib/librte_eventdev/Makefile
@@ -34,7 +34,7 @@ include $(RTE_SDK)/mk/rte.vars.mk
 LIB = librte_eventdev.a
 
 # library version
-LIBABIVER := 1
+LIBABIVER := 2
 
 # build flags
 CFLAGS += -O3
-- 
2.14.0

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC] ethdev: add ioctl-like API to control device specific features
  2017-08-08  8:32  0%           ` Ferruh Yigit
@ 2017-08-08 15:27  3%             ` Stephen Hemminger
  0 siblings, 0 replies; 200+ results
From: Stephen Hemminger @ 2017-08-08 15:27 UTC (permalink / raw)
  To: Ferruh Yigit
  Cc: Bruce Richardson, Thomas Monjalon, dev, Chilikin, Andrey,
	Ananyev, Konstantin, Wu, Jingjing

On Tue, 8 Aug 2017 09:32:07 +0100
Ferruh Yigit <ferruh.yigit@intel.com> wrote:

> On 8/4/2017 1:56 PM, Bruce Richardson wrote:
> > On Fri, Aug 04, 2017 at 12:58:01PM +0100, Ferruh Yigit wrote:  
> >> On 8/3/2017 8:53 PM, Thomas Monjalon wrote:  
> >>> 03/08/2017 18:15, Stephen Hemminger:  
> >>>> On Thu, 3 Aug 2017 14:21:38 +0100
> >>>> Bruce Richardson <bruce.richardson@intel.com> wrote:
> >>>>  
> >>>>> On Thu, Aug 03, 2017 at 01:21:35PM +0100, Chilikin, Andrey wrote:  
> >>>>>> To control some device-specific features public device-specific functions
> >>>>>> rte_pmd_*.h are used.
> >>>>>>
> >>>>>> But this solution requires applications to distinguish devices at runtime
> >>>>>> and, depending on the device type, call corresponding device-specific
> >>>>>> functions even if functions' parameters are the same.
> >>>>>>
> >>>>>> IOCTL-like API can be added to ethdev instead of public device-specific
> >>>>>> functions to address the following:
> >>>>>>
> >>>>>> * allow more usable support of features across a range of NIC from
> >>>>>>   one vendor, but not others
> >>>>>> * allow features to be implemented by multiple NIC drivers without
> >>>>>>   relying on a critical mass to get the functionality in ethdev
> >>>>>> * there are a large number of possible device specific functions, and
> >>>>>>   creating individual APIs for each one is not a good solution
> >>>>>> * IOCTLs are a proven method for solving this problem in other areas,
> >>>>>>   i.e. OS kernels.
> >>>>>>
> >>>>>> Control requests for this API will be globally defined at ethdev level, so
> >>>>>> an application will use single API call to control different devices from
> >>>>>> one/multiple vendors.
> >>>>>>
> >>>>>> API call may look like as a classic ioctl with an extra parameter for
> >>>>>> argument length for better sanity checks:
> >>>>>>
> >>>>>> int
> >>>>>> rte_eth_dev_ioctl(uint16_t port, uint64_t ctl, void *argp,
> >>>>>>         unsigned arg_length);
> >>>>>>
> >>>>>> Regards,
> >>>>>> Andrey    
> >>>>>
> >>>>> I think we need to start putting in IOCTLs for ethdevs, much as I hate
> >>>>> to admit it, since I dislike IOCTLs and other functions with opaque
> >>>>> arguments! Having driver specific functions I don't think will scale
> >>>>> well as each vendor tries to expose as much of their driver specific
> >>>>> functionality as possible.
> >>>>>
> >>>>> One other additional example: I discovered just this week another issue
> >>>>> with driver specific functions and testpmd, when I was working on the
> >>>>> meson build rework.
> >>>>>
> >>>>> * With shared libraries, when we do "ninja install" we want our DPDK
> >>>>>   libs moved to e.g. /usr/local/lib, but the drivers moved to a separate
> >>>>>   driver folder, so that they can be automatically loaded from that
> >>>>>   single location by DPDK apps [== CONFIG_RTE_EAL_PMD_PATH].
> >>>>> * However, testpmd, as well as using the drivers as plugins, uses
> >>>>>   driver-specific functions, which means that it explicitly links
> >>>>>   against the pmd .so files.
> >>>>> * Those driver .so files are not in with the other libraries, so ld.so
> >>>>>   does not find the pmd, and the installed testpmd fails to run due to
> >>>>>   missing library dependencies.
> >>>>> * The workaround is to add the drivers path to the ld load path, but we
> >>>>>   should not require ld library path changes just to get DPDK apps to
> >>>>>   work.
> >>>>>
> >>>>> Using ioctls instead of driver-specific functions would solve this.
> >>>>>
> >>>>> My 2c.  
> >>>>
> >>>> My 2c. No.
> >>>>
> >>>> Short answer:
> >>>> Ioctl's were a bad idea in Unix (per Dennis Ritchie et al) and are now
> >>>> despised by Linux kernel developers. They provide an unstructured, unsecured,
> >>>> back door for device driver abuse. Try to get a new driver in Linux with
> >>>> a unique ioctl, and it will be hard to get accepted.
> >>>>
> >>>> Long answer:
> >>>> So far every device specific feature has fit into ethdev model. Doing ioctl
> >>>> is admitting "it is too hard to be general, we need need an out". For something
> >>>> that is a flag, it should fit into existing config model; ignoring silly ABI constraints.
> >>>> For a real feature (think flow direction), we want a first class API for that.
> >>>> For a wart, then devargs will do.
> >>>>
> >>>> Give a good example of something that should be an ioctl. Don't build the
> >>>> API first and then let it get cluttered.  
> >>>
> >>> I agree with Stephen.
> >>>
> >>> And please do not forget that ioctl still requires an API:
> >>> the argument that you put in ioctl is the API of the feature.
> >>> So it is the same thing as defining a new function.  
> >>
> >> I am also not fan of the ioctl usage. I believe it hides APIs behind ids
> >> and prevent argument check by compiler.
> >>
> >> BUT, the number of the increasing PMD specific APIs are also worrying,
> >> it is becoming harder to maintain, and I believe this is something NOT
> >> sustainable in long run.
> >>
> >>
> >> What about having *eth_dev_extended_ops* ?
> >>
> >>
> >> As a part of the rte_eth_dev. This can be in the librte_ether library
> >> but in a separated file.
> >>
> >> And the APIs for these ops can be less strict on compatibility, and
> >> easier to add.
> >>
> >> Benefits of having this new dev_ops:
> >>
> >> * Having an abstraction layer for common checks.
> >>
> >> * Even feature is not generic for all NICs, still a few NICs can share
> >> the ops.
> >>
> >> * All APIs are in the same file makes it easy to see PMD specific APIs
> >> comparing to scattered into various PMDs.
> >>
> >> * This is very like ioctl approach, but APIs are more clear and
> >> arguments can be verified.
> >>  
> > 
> > Sounds like an ethdev-staging library, where features can be put until
> > such time as they get critical mass for acceptance and promoted to
> > ethdev? It's sounds better than IOCTL, while giving the same benefits.
> > 
> > I'd be happy enough with any solution that allows NIC features to be
> > exposed that does not have functions limited to each individual driver,
> > so that common functionality can be exposed to apps via an API even if
> > only 2 drivers support it.  
> 
> This is not decided yet, but to enable working on this for next release,
> is a deprecation notice required to add a new field to "struct
> rte_eth_dev" ?
> 
> "struct rte_eth_dev" is marked as "@internal", so I believe deprecation
> notice is NOT required, but I would like to confirm.

Increasing the size of a structure used by API calls
will break ABI since the new version
of DPDK will read garbage off the end of the caller's input.
The problem could have been avoided if original DPDK API's had
used configuration structure and size of that struct.

Only structures allocated and only used internally could change.
It looks like rte_eth_dev is safe.

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC] ethdev: add ioctl-like API to control device specific features
    @ 2017-08-08 17:23  2%         ` Wiles, Keith
  2017-08-08 17:28  0%         ` Wiles, Keith
  2 siblings, 0 replies; 200+ results
From: Wiles, Keith @ 2017-08-08 17:23 UTC (permalink / raw)
  To: Yigit, Ferruh
  Cc: Thomas Monjalon, dev, Stephen Hemminger, Richardson, Bruce,
	Chilikin, Andrey, Ananyev, Konstantin, Wu, Jingjing


On Aug 4, 2017, at 6:58 AM, Ferruh Yigit <ferruh.yigit@intel.com<mailto:ferruh.yigit@intel.com>> wrote:

On 8/3/2017 8:53 PM, Thomas Monjalon wrote:
03/08/2017 18:15, Stephen Hemminger:
On Thu, 3 Aug 2017 14:21:38 +0100
Bruce Richardson <bruce.richardson@intel.com<mailto:bruce.richardson@intel.com>> wrote:

On Thu, Aug 03, 2017 at 01:21:35PM +0100, Chilikin, Andrey wrote:
To control some device-specific features public device-specific functions
rte_pmd_*.h are used.

But this solution requires applications to distinguish devices at runtime
and, depending on the device type, call corresponding device-specific
functions even if functions' parameters are the same.

IOCTL-like API can be added to ethdev instead of public device-specific
functions to address the following:

* allow more usable support of features across a range of NIC from
 one vendor, but not others
* allow features to be implemented by multiple NIC drivers without
 relying on a critical mass to get the functionality in ethdev
* there are a large number of possible device specific functions, and
 creating individual APIs for each one is not a good solution
* IOCTLs are a proven method for solving this problem in other areas,
 i.e. OS kernels.

Control requests for this API will be globally defined at ethdev level, so
an application will use single API call to control different devices from
one/multiple vendors.

API call may look like as a classic ioctl with an extra parameter for
argument length for better sanity checks:

int
rte_eth_dev_ioctl(uint16_t port, uint64_t ctl, void *argp,
       unsigned arg_length);

Regards,
Andrey

I think we need to start putting in IOCTLs for ethdevs, much as I hate
to admit it, since I dislike IOCTLs and other functions with opaque
arguments! Having driver specific functions I don't think will scale
well as each vendor tries to expose as much of their driver specific
functionality as possible.

One other additional example: I discovered just this week another issue
with driver specific functions and testpmd, when I was working on the
meson build rework.

* With shared libraries, when we do "ninja install" we want our DPDK
 libs moved to e.g. /usr/local/lib, but the drivers moved to a separate
 driver folder, so that they can be automatically loaded from that
 single location by DPDK apps [== CONFIG_RTE_EAL_PMD_PATH].
* However, testpmd, as well as using the drivers as plugins, uses
 driver-specific functions, which means that it explicitly links
 against the pmd .so files.
* Those driver .so files are not in with the other libraries, so ld.so
 does not find the pmd, and the installed testpmd fails to run due to
 missing library dependencies.
* The workaround is to add the drivers path to the ld load path, but we
 should not require ld library path changes just to get DPDK apps to
 work.

Using ioctls instead of driver-specific functions would solve this.

My 2c.

My 2c. No.

Short answer:
Ioctl's were a bad idea in Unix (per Dennis Ritchie et al) and are now
despised by Linux kernel developers. They provide an unstructured, unsecured,
back door for device driver abuse. Try to get a new driver in Linux with
a unique ioctl, and it will be hard to get accepted.

Long answer:
So far every device specific feature has fit into ethdev model. Doing ioctl
is admitting "it is too hard to be general, we need need an out". For something
that is a flag, it should fit into existing config model; ignoring silly ABI constraints.
For a real feature (think flow direction), we want a first class API for that.
For a wart, then devargs will do.

Give a good example of something that should be an ioctl. Don't build the
API first and then let it get cluttered.

I agree with Stephen.

And please do not forget that ioctl still requires an API:
the argument that you put in ioctl is the API of the feature.
So it is the same thing as defining a new function.

I am also not fan of the ioctl usage. I believe it hides APIs behind ids
and prevent argument check by compiler.

BUT, the number of the increasing PMD specific APIs are also worrying,
it is becoming harder to maintain, and I believe this is something NOT
sustainable in long run.


What about having *eth_dev_extended_ops* ?

We had talk about adding something like device specific APIs to DPDK in the past, which to me are just IOCTL like APIs. The big problem with IOCTLs is trying to cram a bunch of specific requests into a very generic API and I do not like ioctl as defined in Linux/Unix today. The old IOCTLs calls are too opaque and difficult for compilers to test args and many other issues.

We talked about having a single API in rte_eth_dev that would allow a user to ask for and possible get a list of function pointers in a given structure for the requested type. If a user calls this API to get some feature from a given NIC he would get NULL or a pointer to a set of functions. The generic API in rte_eth would allow the user to request what structures or types of APIs it supports.

Using a specific API to get the list of APIs or supported features in a NIC, will allow the developer to request the set of APIs (in an array or some method). Then we have real APIs for specific control or requests and not a generic API like ioctl.

Cristian had suggested an API like this to make it easy to add any IOCTL like needs to a driver. We can define a set of structures that seem generic for some IOCTL like needs or just allow the NIC to define his own structures and APIs. Allowing the developer to define his own structures and APIs is not very generic or usable by the users, so I would lean toward defining structures set need today and expand those structures in the future or add more structures.

int rte_eth_dev_something(uint16_t port_id, const char *feature, void **obj);

Using strings we can define or the NIC vendor can define to ask for a pointer to a structure he knows via a driver header. Strings are good, because we can read them via the debug or print them out quickly instead of trying to use some lookup table. Plus we can have any length or characters for defining the structure request.

Just off the top of my head, but it can be changed if needed.




As a part of the rte_eth_dev. This can be in the librte_ether library
but in a separated file.

And the APIs for these ops can be less strict on compatibility, and
easier to add.

Benefits of having this new dev_ops:

* Having an abstraction layer for common checks.

* Even feature is not generic for all NICs, still a few NICs can share
the ops.

* All APIs are in the same file makes it easy to see PMD specific APIs
comparing to scattered into various PMDs.

* This is very like ioctl approach, but APIs are more clear and
arguments can be verified.

Thanks,
ferruh



The real debate is to decide if we want to continue adding more
control path features in DPDK or focus on Rx/Tx.
But this discussion would be better lead with some examples/requests.

Regards,
Keith

^ permalink raw reply	[relevance 2%]

* Re: [dpdk-dev] [PATCH] eal: bump ABI version for PCI, bus and devargs work
  2017-08-08 14:26  4% [dpdk-dev] [PATCH] eal: bump ABI version for PCI, bus and devargs work Gaetan Rivet
@ 2017-08-08 17:26  4% ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-08 17:26 UTC (permalink / raw)
  To: Gaetan Rivet; +Cc: dev

08/08/2017 16:26, Gaetan Rivet:
> 1. PCI domain field in PCI address structure grew from 16 to 32 bits.
> 
>    From: 463ced957c3f ("pci: increase domain storage to 32 bits")
> 
> 2. rte_bus structure gaining new ops.
> 
>    From: 3a8f0bc68a90 ("bus: add method to find device")
>    From: 7c8810f43f6e ("bus: introduce device plug/unplug")
>    From: 609eb7dde6d0 ("bus: introduce parsing functionality")
>    From: 98eb4b845c1a ("bus: introduce scan policies")
> 
> 3. rte_devargs structure having been mostly rewritten.
> 
>    From: f3a1188cee4a ("devargs: make device representation generic")
>    From: 47828c5f3bc3 ("devargs: parse bus info")
>    From: 39f403e0d5bb ("devargs: restore device type API")
> 
> Signed-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>

Applied and merged with release notes update, thanks

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH] doc: notify EAL ABI change
  2017-08-08 14:26  9% [dpdk-dev] [PATCH] doc: notify EAL ABI change Gaetan Rivet
@ 2017-08-08 17:27  4% ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-08 17:27 UTC (permalink / raw)
  To: Gaetan Rivet; +Cc: dev

08/08/2017 16:26, Gaetan Rivet:
> Signed-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>
> ---
>  doc/guides/rel_notes/release_17_08.rst | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)

Applied and merged with ABIVER bump, thanks

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [RFC] ethdev: add ioctl-like API to control device specific features
      2017-08-08 17:23  2%         ` Wiles, Keith
@ 2017-08-08 17:28  0%         ` Wiles, Keith
  2017-08-08 18:02  0%           ` Stephen Hemminger
  2 siblings, 1 reply; 200+ results
From: Wiles, Keith @ 2017-08-08 17:28 UTC (permalink / raw)
  To: Yigit, Ferruh
  Cc: Thomas Monjalon, DPDK, Stephen Hemminger, Richardson, Bruce,
	Chilikin, Andrey, Ananyev, Konstantin, Wu, Jingjing

Fix format.

> On Aug 4, 2017, at 6:58 AM, Ferruh Yigit <ferruh.yigit@intel.com> wrote:
> 
> On 8/3/2017 8:53 PM, Thomas Monjalon wrote:
>> 03/08/2017 18:15, Stephen Hemminger:
>>> On Thu, 3 Aug 2017 14:21:38 +0100
>>> Bruce Richardson <bruce.richardson@intel.com> wrote:
>>> 
>>>> On Thu, Aug 03, 2017 at 01:21:35PM +0100, Chilikin, Andrey wrote:
>>>>> To control some device-specific features public device-specific functions
>>>>> rte_pmd_*.h are used.
>>>>> 
>>>>> But this solution requires applications to distinguish devices at runtime
>>>>> and, depending on the device type, call corresponding device-specific
>>>>> functions even if functions' parameters are the same.
>>>>> 
>>>>> IOCTL-like API can be added to ethdev instead of public device-specific
>>>>> functions to address the following:
>>>>> 
>>>>> * allow more usable support of features across a range of NIC from
>>>>>  one vendor, but not others
>>>>> * allow features to be implemented by multiple NIC drivers without
>>>>>  relying on a critical mass to get the functionality in ethdev
>>>>> * there are a large number of possible device specific functions, and
>>>>>  creating individual APIs for each one is not a good solution
>>>>> * IOCTLs are a proven method for solving this problem in other areas,
>>>>>  i.e. OS kernels.
>>>>> 
>>>>> Control requests for this API will be globally defined at ethdev level, so
>>>>> an application will use single API call to control different devices from
>>>>> one/multiple vendors.
>>>>> 
>>>>> API call may look like as a classic ioctl with an extra parameter for
>>>>> argument length for better sanity checks:
>>>>> 
>>>>> int
>>>>> rte_eth_dev_ioctl(uint16_t port, uint64_t ctl, void *argp,
>>>>>        unsigned arg_length);
>>>>> 
>>>>> Regards,
>>>>> Andrey  
>>>> 
>>>> I think we need to start putting in IOCTLs for ethdevs, much as I hate
>>>> to admit it, since I dislike IOCTLs and other functions with opaque
>>>> arguments! Having driver specific functions I don't think will scale
>>>> well as each vendor tries to expose as much of their driver specific
>>>> functionality as possible.
>>>> 
>>>> One other additional example: I discovered just this week another issue
>>>> with driver specific functions and testpmd, when I was working on the
>>>> meson build rework.
>>>> 
>>>> * With shared libraries, when we do "ninja install" we want our DPDK
>>>>  libs moved to e.g. /usr/local/lib, but the drivers moved to a separate
>>>>  driver folder, so that they can be automatically loaded from that
>>>>  single location by DPDK apps [== CONFIG_RTE_EAL_PMD_PATH].
>>>> * However, testpmd, as well as using the drivers as plugins, uses
>>>>  driver-specific functions, which means that it explicitly links
>>>>  against the pmd .so files.
>>>> * Those driver .so files are not in with the other libraries, so ld.so
>>>>  does not find the pmd, and the installed testpmd fails to run due to
>>>>  missing library dependencies.
>>>> * The workaround is to add the drivers path to the ld load path, but we
>>>>  should not require ld library path changes just to get DPDK apps to
>>>>  work.
>>>> 
>>>> Using ioctls instead of driver-specific functions would solve this.
>>>> 
>>>> My 2c.
>>> 
>>> My 2c. No.
>>> 
>>> Short answer:
>>> Ioctl's were a bad idea in Unix (per Dennis Ritchie et al) and are now
>>> despised by Linux kernel developers. They provide an unstructured, unsecured,
>>> back door for device driver abuse. Try to get a new driver in Linux with
>>> a unique ioctl, and it will be hard to get accepted.
>>> 
>>> Long answer:
>>> So far every device specific feature has fit into ethdev model. Doing ioctl
>>> is admitting "it is too hard to be general, we need need an out". For something
>>> that is a flag, it should fit into existing config model; ignoring silly ABI constraints.
>>> For a real feature (think flow direction), we want a first class API for that.
>>> For a wart, then devargs will do.
>>> 
>>> Give a good example of something that should be an ioctl. Don't build the
>>> API first and then let it get cluttered.
>> 
>> I agree with Stephen.
>> 
>> And please do not forget that ioctl still requires an API:
>> the argument that you put in ioctl is the API of the feature.
>> So it is the same thing as defining a new function.
> 
> I am also not fan of the ioctl usage. I believe it hides APIs behind ids
> and prevent argument check by compiler.
> 
> BUT, the number of the increasing PMD specific APIs are also worrying,
> it is becoming harder to maintain, and I believe this is something NOT
> sustainable in long run.
> 
> 
> What about having *eth_dev_extended_ops* ?


We had talk about adding something like device specific APIs to DPDK in the past, which to me are just IOCTL like APIs. The big problem with IOCTLs is trying to cram a bunch of specific requests into a very generic API and I do not like ioctl as defined in Linux/Unix today. The old IOCTLs calls are too opaque and difficult for compilers to test args and many other issues.

We talked about having a single API in rte_eth_dev that would allow a user to ask for and possible get a list of function pointers in a given structure for the requested type. If a user calls this API to get some feature from a given NIC he would get NULL or a pointer to a set of functions. The generic API in rte_eth would allow the user to request what structures or types of APIs it supports.

Using a specific API to get the list of APIs or supported features in a NIC, will allow the developer to request the set of APIs (in an array or some method). Then we have real APIs for specific control or requests and not a generic API like ioctl.

Cristian had suggested an API like this to make it easy to add any IOCTL like needs to a driver. We can define a set of structures that seem generic for some IOCTL like needs or just allow the NIC to define his own structures and APIs. Allowing the developer to define his own structures and APIs is not very generic or usable by the users, so I would lean toward defining structures set need today and expand those structures in the future or add more structures.

int rte_eth_dev_something(uint16_t port_id, const char *feature, void **obj);

Using strings we can define or the NIC vendor can define to ask for a pointer to a structure he knows via a driver header. Strings are good, because we can read them via the debug or print them out quickly instead of trying to use some lookup table. Plus we can have any length or characters for defining the structure request.

Just off the top of my head, but it can be changed if needed.


> 
> 
> As a part of the rte_eth_dev. This can be in the librte_ether library
> but in a separated file.
> 
> And the APIs for these ops can be less strict on compatibility, and
> easier to add.
> 
> Benefits of having this new dev_ops:
> 
> * Having an abstraction layer for common checks.
> 
> * Even feature is not generic for all NICs, still a few NICs can share
> the ops.
> 
> * All APIs are in the same file makes it easy to see PMD specific APIs
> comparing to scattered into various PMDs.
> 
> * This is very like ioctl approach, but APIs are more clear and
> arguments can be verified.
> 
> Thanks,
> ferruh
> 
> 
>> 
>> The real debate is to decide if we want to continue adding more
>> control path features in DPDK or focus on Rx/Tx.
>> But this discussion would be better lead with some examples/requests.

Regards,
Keith

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 2/2] eventdev: bump library version
  2017-08-08 14:48  3% ` [dpdk-dev] [PATCH 2/2] eventdev: bump library version Jerin Jacob
@ 2017-08-08 17:45  0%   ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-08 17:45 UTC (permalink / raw)
  To: Jerin Jacob; +Cc: dev, john.mcnamara

08/08/2017 16:48, Jerin Jacob:
> Bumping the library version to reflect the ABI change, where
> rte_event_pmd_pci_probe(), rte_event_pmd_pci_remove(),
> rte_event_pmd_vdev_init(), rte_event_pmd_vdev_uninit()
> functions removed from the library.
> 
> Fixes: b1b3d9f90502 ("eventdev: make vdev init and uninit functions optional")
> Fixes: 9a8269d56942 ("eventdev: make PCI probe and remove functions optional")
> 
> Reported-by: Thomas Monjalon <thomas.monjalon@6wind.com>
> Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>

Series applied, thanks

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC] ethdev: add ioctl-like API to control device specific features
  2017-08-08 17:28  0%         ` Wiles, Keith
@ 2017-08-08 18:02  0%           ` Stephen Hemminger
  2017-08-08 18:21  0%             ` Wiles, Keith
  0 siblings, 1 reply; 200+ results
From: Stephen Hemminger @ 2017-08-08 18:02 UTC (permalink / raw)
  To: Wiles, Keith
  Cc: Yigit, Ferruh, Thomas Monjalon, DPDK, Richardson, Bruce,
	Chilikin, Andrey, Ananyev, Konstantin, Wu, Jingjing

On Tue, 8 Aug 2017 17:28:19 +0000
"Wiles, Keith" <keith.wiles@intel.com> wrote:

> Fix format.
> 
> > On Aug 4, 2017, at 6:58 AM, Ferruh Yigit <ferruh.yigit@intel.com> wrote:
> > 
> > On 8/3/2017 8:53 PM, Thomas Monjalon wrote:  
> >> 03/08/2017 18:15, Stephen Hemminger:  
> >>> On Thu, 3 Aug 2017 14:21:38 +0100
> >>> Bruce Richardson <bruce.richardson@intel.com> wrote:
> >>>   
> >>>> On Thu, Aug 03, 2017 at 01:21:35PM +0100, Chilikin, Andrey wrote:  
> >>>>> To control some device-specific features public device-specific functions
> >>>>> rte_pmd_*.h are used.
> >>>>> 
> >>>>> But this solution requires applications to distinguish devices at runtime
> >>>>> and, depending on the device type, call corresponding device-specific
> >>>>> functions even if functions' parameters are the same.
> >>>>> 
> >>>>> IOCTL-like API can be added to ethdev instead of public device-specific
> >>>>> functions to address the following:
> >>>>> 
> >>>>> * allow more usable support of features across a range of NIC from
> >>>>>  one vendor, but not others
> >>>>> * allow features to be implemented by multiple NIC drivers without
> >>>>>  relying on a critical mass to get the functionality in ethdev
> >>>>> * there are a large number of possible device specific functions, and
> >>>>>  creating individual APIs for each one is not a good solution
> >>>>> * IOCTLs are a proven method for solving this problem in other areas,
> >>>>>  i.e. OS kernels.
> >>>>> 
> >>>>> Control requests for this API will be globally defined at ethdev level, so
> >>>>> an application will use single API call to control different devices from
> >>>>> one/multiple vendors.
> >>>>> 
> >>>>> API call may look like as a classic ioctl with an extra parameter for
> >>>>> argument length for better sanity checks:
> >>>>> 
> >>>>> int
> >>>>> rte_eth_dev_ioctl(uint16_t port, uint64_t ctl, void *argp,
> >>>>>        unsigned arg_length);
> >>>>> 
> >>>>> Regards,
> >>>>> Andrey    
> >>>> 
> >>>> I think we need to start putting in IOCTLs for ethdevs, much as I hate
> >>>> to admit it, since I dislike IOCTLs and other functions with opaque
> >>>> arguments! Having driver specific functions I don't think will scale
> >>>> well as each vendor tries to expose as much of their driver specific
> >>>> functionality as possible.
> >>>> 
> >>>> One other additional example: I discovered just this week another issue
> >>>> with driver specific functions and testpmd, when I was working on the
> >>>> meson build rework.
> >>>> 
> >>>> * With shared libraries, when we do "ninja install" we want our DPDK
> >>>>  libs moved to e.g. /usr/local/lib, but the drivers moved to a separate
> >>>>  driver folder, so that they can be automatically loaded from that
> >>>>  single location by DPDK apps [== CONFIG_RTE_EAL_PMD_PATH].
> >>>> * However, testpmd, as well as using the drivers as plugins, uses
> >>>>  driver-specific functions, which means that it explicitly links
> >>>>  against the pmd .so files.
> >>>> * Those driver .so files are not in with the other libraries, so ld.so
> >>>>  does not find the pmd, and the installed testpmd fails to run due to
> >>>>  missing library dependencies.
> >>>> * The workaround is to add the drivers path to the ld load path, but we
> >>>>  should not require ld library path changes just to get DPDK apps to
> >>>>  work.
> >>>> 
> >>>> Using ioctls instead of driver-specific functions would solve this.
> >>>> 
> >>>> My 2c.  
> >>> 
> >>> My 2c. No.
> >>> 
> >>> Short answer:
> >>> Ioctl's were a bad idea in Unix (per Dennis Ritchie et al) and are now
> >>> despised by Linux kernel developers. They provide an unstructured, unsecured,
> >>> back door for device driver abuse. Try to get a new driver in Linux with
> >>> a unique ioctl, and it will be hard to get accepted.
> >>> 
> >>> Long answer:
> >>> So far every device specific feature has fit into ethdev model. Doing ioctl
> >>> is admitting "it is too hard to be general, we need need an out". For something
> >>> that is a flag, it should fit into existing config model; ignoring silly ABI constraints.
> >>> For a real feature (think flow direction), we want a first class API for that.
> >>> For a wart, then devargs will do.
> >>> 
> >>> Give a good example of something that should be an ioctl. Don't build the
> >>> API first and then let it get cluttered.  
> >> 
> >> I agree with Stephen.
> >> 
> >> And please do not forget that ioctl still requires an API:
> >> the argument that you put in ioctl is the API of the feature.
> >> So it is the same thing as defining a new function.  
> > 
> > I am also not fan of the ioctl usage. I believe it hides APIs behind ids
> > and prevent argument check by compiler.
> > 
> > BUT, the number of the increasing PMD specific APIs are also worrying,
> > it is becoming harder to maintain, and I believe this is something NOT
> > sustainable in long run.
> > 
> > 
> > What about having *eth_dev_extended_ops* ?  
> 
> 
> We had talk about adding something like device specific APIs to DPDK in the past, which to me are just IOCTL like APIs. The big problem with IOCTLs is trying to cram a bunch of specific requests into a very generic API and I do not like ioctl as defined in Linux/Unix today. The old IOCTLs calls are too opaque and difficult for compilers to test args and many other issues.
> 
> We talked about having a single API in rte_eth_dev that would allow a user to ask for and possible get a list of function pointers in a given structure for the requested type. If a user calls this API to get some feature from a given NIC he would get NULL or a pointer to a set of functions. The generic API in rte_eth would allow the user to request what structures or types of APIs it supports.
> 
> Using a specific API to get the list of APIs or supported features in a NIC, will allow the developer to request the set of APIs (in an array or some method). Then we have real APIs for specific control or requests and not a generic API like ioctl.
> 
> Cristian had suggested an API like this to make it easy to add any IOCTL like needs to a driver. We can define a set of structures that seem generic for some IOCTL like needs or just allow the NIC to define his own structures and APIs. Allowing the developer to define his own structures and APIs is not very generic or usable by the users, so I would lean toward defining structures set need today and expand those structures in the future or add more structures.
> 
> int rte_eth_dev_something(uint16_t port_id, const char *feature, void **obj);
> 
> Using strings we can define or the NIC vendor can define to ask for a pointer to a structure he knows via a driver header. Strings are good, because we can read them via the debug or print them out quickly instead of trying to use some lookup table. Plus we can have any length or characters for defining the structure request.
> 
> Just off the top of my head, but it can be changed if needed.
> 
> 
> > 
> > 
> > As a part of the rte_eth_dev. This can be in the librte_ether library
> > but in a separated file.
> > 
> > And the APIs for these ops can be less strict on compatibility, and
> > easier to add.
> > 
> > Benefits of having this new dev_ops:
> > 
> > * Having an abstraction layer for common checks.
> > 
> > * Even feature is not generic for all NICs, still a few NICs can share
> > the ops.
> > 
> > * All APIs are in the same file makes it easy to see PMD specific APIs
> > comparing to scattered into various PMDs.
> > 
> > * This is very like ioctl approach, but APIs are more clear and
> > arguments can be verified.
> > 
> > Thanks,
> > ferruh
> > 
> >   
> >> 
> >> The real debate is to decide if we want to continue adding more
> >> control path features in DPDK or focus on Rx/Tx.
> >> But this discussion would be better lead with some examples/requests.  
> 

The real question is how important is that DPDK is the playground for HW features?
My impression is that the current process is HW supplier driven "we support offload of XYZZY".

The existing control of device model is already a multi-path mess of config API's, device args,
and magic scripts. That needs to be addressed first.

There is very little community input from users, that is the problem.

IMHO if a new hardware feature can't be made to fit into a standard OS model like Linux
because it is too hard then adding it to DPDK is a mistake.

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC] ethdev: add ioctl-like API to control device specific features
  2017-08-08 18:02  0%           ` Stephen Hemminger
@ 2017-08-08 18:21  0%             ` Wiles, Keith
  0 siblings, 0 replies; 200+ results
From: Wiles, Keith @ 2017-08-08 18:21 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Yigit, Ferruh, Thomas Monjalon, DPDK, Richardson, Bruce,
	Chilikin, Andrey, Ananyev, Konstantin, Wu, Jingjing


> On Aug 8, 2017, at 1:02 PM, Stephen Hemminger <stephen@networkplumber.org> wrote:
> 
> On Tue, 8 Aug 2017 17:28:19 +0000
> "Wiles, Keith" <keith.wiles@intel.com> wrote:
> 
>> Fix format.
>> 
>>> On Aug 4, 2017, at 6:58 AM, Ferruh Yigit <ferruh.yigit@intel.com> wrote:
>>> 
>>> On 8/3/2017 8:53 PM, Thomas Monjalon wrote:  
>>>> 03/08/2017 18:15, Stephen Hemminger:  
>>>>> On Thu, 3 Aug 2017 14:21:38 +0100
>>>>> Bruce Richardson <bruce.richardson@intel.com> wrote:
>>>>> 
>>>>>> On Thu, Aug 03, 2017 at 01:21:35PM +0100, Chilikin, Andrey wrote:  
>>>>>>> To control some device-specific features public device-specific functions
>>>>>>> rte_pmd_*.h are used.
>>>>>>> 
>>>>>>> But this solution requires applications to distinguish devices at runtime
>>>>>>> and, depending on the device type, call corresponding device-specific
>>>>>>> functions even if functions' parameters are the same.
>>>>>>> 
>>>>>>> IOCTL-like API can be added to ethdev instead of public device-specific
>>>>>>> functions to address the following:
>>>>>>> 
>>>>>>> * allow more usable support of features across a range of NIC from
>>>>>>> one vendor, but not others
>>>>>>> * allow features to be implemented by multiple NIC drivers without
>>>>>>> relying on a critical mass to get the functionality in ethdev
>>>>>>> * there are a large number of possible device specific functions, and
>>>>>>> creating individual APIs for each one is not a good solution
>>>>>>> * IOCTLs are a proven method for solving this problem in other areas,
>>>>>>> i.e. OS kernels.
>>>>>>> 
>>>>>>> Control requests for this API will be globally defined at ethdev level, so
>>>>>>> an application will use single API call to control different devices from
>>>>>>> one/multiple vendors.
>>>>>>> 
>>>>>>> API call may look like as a classic ioctl with an extra parameter for
>>>>>>> argument length for better sanity checks:
>>>>>>> 
>>>>>>> int
>>>>>>> rte_eth_dev_ioctl(uint16_t port, uint64_t ctl, void *argp,
>>>>>>>       unsigned arg_length);
>>>>>>> 
>>>>>>> Regards,
>>>>>>> Andrey    
>>>>>> 
>>>>>> I think we need to start putting in IOCTLs for ethdevs, much as I hate
>>>>>> to admit it, since I dislike IOCTLs and other functions with opaque
>>>>>> arguments! Having driver specific functions I don't think will scale
>>>>>> well as each vendor tries to expose as much of their driver specific
>>>>>> functionality as possible.
>>>>>> 
>>>>>> One other additional example: I discovered just this week another issue
>>>>>> with driver specific functions and testpmd, when I was working on the
>>>>>> meson build rework.
>>>>>> 
>>>>>> * With shared libraries, when we do "ninja install" we want our DPDK
>>>>>> libs moved to e.g. /usr/local/lib, but the drivers moved to a separate
>>>>>> driver folder, so that they can be automatically loaded from that
>>>>>> single location by DPDK apps [== CONFIG_RTE_EAL_PMD_PATH].
>>>>>> * However, testpmd, as well as using the drivers as plugins, uses
>>>>>> driver-specific functions, which means that it explicitly links
>>>>>> against the pmd .so files.
>>>>>> * Those driver .so files are not in with the other libraries, so ld.so
>>>>>> does not find the pmd, and the installed testpmd fails to run due to
>>>>>> missing library dependencies.
>>>>>> * The workaround is to add the drivers path to the ld load path, but we
>>>>>> should not require ld library path changes just to get DPDK apps to
>>>>>> work.
>>>>>> 
>>>>>> Using ioctls instead of driver-specific functions would solve this.
>>>>>> 
>>>>>> My 2c.  
>>>>> 
>>>>> My 2c. No.
>>>>> 
>>>>> Short answer:
>>>>> Ioctl's were a bad idea in Unix (per Dennis Ritchie et al) and are now
>>>>> despised by Linux kernel developers. They provide an unstructured, unsecured,
>>>>> back door for device driver abuse. Try to get a new driver in Linux with
>>>>> a unique ioctl, and it will be hard to get accepted.
>>>>> 
>>>>> Long answer:
>>>>> So far every device specific feature has fit into ethdev model. Doing ioctl
>>>>> is admitting "it is too hard to be general, we need need an out". For something
>>>>> that is a flag, it should fit into existing config model; ignoring silly ABI constraints.
>>>>> For a real feature (think flow direction), we want a first class API for that.
>>>>> For a wart, then devargs will do.
>>>>> 
>>>>> Give a good example of something that should be an ioctl. Don't build the
>>>>> API first and then let it get cluttered.  
>>>> 
>>>> I agree with Stephen.
>>>> 
>>>> And please do not forget that ioctl still requires an API:
>>>> the argument that you put in ioctl is the API of the feature.
>>>> So it is the same thing as defining a new function.  
>>> 
>>> I am also not fan of the ioctl usage. I believe it hides APIs behind ids
>>> and prevent argument check by compiler.
>>> 
>>> BUT, the number of the increasing PMD specific APIs are also worrying,
>>> it is becoming harder to maintain, and I believe this is something NOT
>>> sustainable in long run.
>>> 
>>> 
>>> What about having *eth_dev_extended_ops* ?  
>> 
>> 
>> We had talk about adding something like device specific APIs to DPDK in the past, which to me are just IOCTL like APIs. The big problem with IOCTLs is trying to cram a bunch of specific requests into a very generic API and I do not like ioctl as defined in Linux/Unix today. The old IOCTLs calls are too opaque and difficult for compilers to test args and many other issues.
>> 
>> We talked about having a single API in rte_eth_dev that would allow a user to ask for and possible get a list of function pointers in a given structure for the requested type. If a user calls this API to get some feature from a given NIC he would get NULL or a pointer to a set of functions. The generic API in rte_eth would allow the user to request what structures or types of APIs it supports.
>> 
>> Using a specific API to get the list of APIs or supported features in a NIC, will allow the developer to request the set of APIs (in an array or some method). Then we have real APIs for specific control or requests and not a generic API like ioctl.
>> 
>> Cristian had suggested an API like this to make it easy to add any IOCTL like needs to a driver. We can define a set of structures that seem generic for some IOCTL like needs or just allow the NIC to define his own structures and APIs. Allowing the developer to define his own structures and APIs is not very generic or usable by the users, so I would lean toward defining structures set need today and expand those structures in the future or add more structures.
>> 
>> int rte_eth_dev_something(uint16_t port_id, const char *feature, void **obj);
>> 
>> Using strings we can define or the NIC vendor can define to ask for a pointer to a structure he knows via a driver header. Strings are good, because we can read them via the debug or print them out quickly instead of trying to use some lookup table. Plus we can have any length or characters for defining the structure request.
>> 
>> Just off the top of my head, but it can be changed if needed.
>> 
>> 
>>> 
>>> 
>>> As a part of the rte_eth_dev. This can be in the librte_ether library
>>> but in a separated file.
>>> 
>>> And the APIs for these ops can be less strict on compatibility, and
>>> easier to add.
>>> 
>>> Benefits of having this new dev_ops:
>>> 
>>> * Having an abstraction layer for common checks.
>>> 
>>> * Even feature is not generic for all NICs, still a few NICs can share
>>> the ops.
>>> 
>>> * All APIs are in the same file makes it easy to see PMD specific APIs
>>> comparing to scattered into various PMDs.
>>> 
>>> * This is very like ioctl approach, but APIs are more clear and
>>> arguments can be verified.
>>> 
>>> Thanks,
>>> ferruh
>>> 
>>> 
>>>> 
>>>> The real debate is to decide if we want to continue adding more
>>>> control path features in DPDK or focus on Rx/Tx.
>>>> But this discussion would be better lead with some examples/requests.  
>> 
> 
> The real question is how important is that DPDK is the playground for HW features?
> My impression is that the current process is HW supplier driven "we support offload of XYZZY”.

It is not really a playground as I see it, but defining clean usable solution for vendors and developers to gain access to HW features. Every vendor loves to expose its features and allowing them to create APIs called directly from an application will make it impossible for a generic application and we need to provide some structure to allow the application to determine what features are supported and how they gain access to those features.

> 
> The existing control of device model is already a multi-path mess of config API's, device args,
> and magic scripts. That needs to be addressed first.

Not sure where the ‘magic scripts’ support comes from :-), but I agree we need to clean up the current configuration of devices. I only really see two methods in the work I have done, which are device args strings and configuration from ethdev. The DPDK configuration is another problem in that it sometimes requires a huge command line to startup an application. I think I saw a patch to add better config file support, but it does not address everything IMO. Which BTW was one of the reasons I wrote the dpdk-run.py script to help solve this problem without having to change the current config file/command line interface.

> 
> There is very little community input from users, that is the problem.

I believe I am a user with Pktgen and my usage of DPDK today, but I maybe a bit more of an expert then most users (I hope). I see these usability problems and I try to address them, but we all need to be aware of the usability aspect of DPDK for the casual user.

> 
> IMHO if a new hardware feature can't be made to fit into a standard OS model like Linux
> because it is too hard then adding it to DPDK is a mistake.

I guess I agree, but what is the Linux model anyway and how does that effect FreeBSD or Windows or name your next OS. We need to provide good hardware support for DPDK and I feel it maybe impossible to always define everything in a super clean generic way, this is why IOCTL were created and I think we can define a better solution then IOCTL as in Linux/Unix.


Regards,
Keith


^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v2] doc: add template release notes for 17.11
  2017-08-08 12:31  6% [dpdk-dev] [PATCH v1] doc: add template release notes for 17.11 John McNamara
@ 2017-08-09  8:22  6% ` John McNamara
  0 siblings, 0 replies; 200+ results
From: John McNamara @ 2017-08-09  8:22 UTC (permalink / raw)
  To: dev; +Cc: John McNamara

Add template release notes for DPDK 17.11 with inline
comments and explanations of the various sections.

Signed-off-by: John McNamara <john.mcnamara@intel.com>
---

V2: Updated library version numbers.


 doc/guides/rel_notes/index.rst         |   1 +
 doc/guides/rel_notes/release_17_11.rst | 200 +++++++++++++++++++++++++++++++++
 2 files changed, 201 insertions(+)
 create mode 100644 doc/guides/rel_notes/release_17_11.rst

diff --git a/doc/guides/rel_notes/index.rst b/doc/guides/rel_notes/index.rst
index b3c8090..35659d8 100644
--- a/doc/guides/rel_notes/index.rst
+++ b/doc/guides/rel_notes/index.rst
@@ -36,6 +36,7 @@ Release Notes
     :numbered:
 
     rel_description
+    release_17_11
     release_17_08
     release_17_05
     release_17_02
diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
new file mode 100644
index 0000000..170f4f9
--- /dev/null
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -0,0 +1,200 @@
+DPDK Release 17.11
+==================
+
+.. **Read this first.**
+
+   The text in the sections below explains how to update the release notes.
+
+   Use proper spelling, capitalization and punctuation in all sections.
+
+   Variable and config names should be quoted as fixed width text:
+   ``LIKE_THIS``.
+
+   Build the docs and view the output file to ensure the changes are correct::
+
+      make doc-guides-html
+
+      xdg-open build/doc/html/guides/rel_notes/release_17_11.html
+
+
+New Features
+------------
+
+.. This section should contain new features added in this release. Sample
+   format:
+
+   * **Add a title in the past tense with a full stop.**
+
+     Add a short 1-2 sentence description in the past tense. The description
+     should be enough to allow someone scanning the release notes to
+     understand the new feature.
+
+     If the feature adds a lot of sub-features you can use a bullet list like
+     this:
+
+     * Added feature foo to do something.
+     * Enhanced feature bar to do something else.
+
+     Refer to the previous release notes for examples.
+
+     This section is a comment. do not overwrite or remove it.
+     Also, make sure to start the actual text at the margin.
+     =========================================================
+
+
+Resolved Issues
+---------------
+
+.. This section should contain bug fixes added to the relevant
+   sections. Sample format:
+
+   * **code/section Fixed issue in the past tense with a full stop.**
+
+     Add a short 1-2 sentence description of the resolved issue in the past
+     tense.
+
+     The title should contain the code/lib section like a commit message.
+
+     Add the entries in alphabetic order in the relevant sections below.
+
+   This section is a comment. do not overwrite or remove it.
+   Also, make sure to start the actual text at the margin.
+   =========================================================
+
+
+EAL
+~~~
+
+
+Drivers
+~~~~~~~
+
+
+Libraries
+~~~~~~~~~
+
+
+Examples
+~~~~~~~~
+
+
+Other
+~~~~~
+
+
+Known Issues
+------------
+
+.. This section should contain new known issues in this release. Sample format:
+
+   * **Add title in present tense with full stop.**
+
+     Add a short 1-2 sentence description of the known issue in the present
+     tense. Add information on any known workarounds.
+
+   This section is a comment. do not overwrite or remove it.
+   Also, make sure to start the actual text at the margin.
+   =========================================================
+
+
+API Changes
+-----------
+
+.. This section should contain API changes. Sample format:
+
+   * Add a short 1-2 sentence description of the API change. Use fixed width
+     quotes for ``rte_function_names`` or ``rte_struct_names``. Use the past
+     tense.
+
+   This section is a comment. do not overwrite or remove it.
+   Also, make sure to start the actual text at the margin.
+   =========================================================
+
+
+ABI Changes
+-----------
+
+.. This section should contain ABI changes. Sample format:
+
+   * Add a short 1-2 sentence description of the ABI change that was announced
+     in the previous releases and made in this release. Use fixed width quotes
+     for ``rte_function_names`` or ``rte_struct_names``. Use the past tense.
+
+   This section is a comment. do not overwrite or remove it.
+   Also, make sure to start the actual text at the margin.
+   =========================================================
+
+
+
+Shared Library Versions
+-----------------------
+
+.. Update any library version updated in this release and prepend with a ``+``
+   sign, like this:
+
+     librte_acl.so.2
+   + librte_cfgfile.so.2
+     librte_cmdline.so.2
+
+   This section is a comment. do not overwrite or remove it.
+   =========================================================
+
+
+The libraries prepended with a plus sign were incremented in this version.
+
+.. code-block:: diff
+
+     librte_acl.so.2
+     librte_bitratestats.so.1
+     librte_cfgfile.so.2
+     librte_cmdline.so.2
+     librte_cryptodev.so.3
+     librte_distributor.so.1
+     librte_eal.so.5
+     librte_ethdev.so.7
+     librte_eventdev.so.2
+     librte_gro.so.1
+     librte_hash.so.2
+     librte_ip_frag.so.1
+     librte_jobstats.so.1
+     librte_kni.so.2
+     librte_kvargs.so.1
+     librte_latencystats.so.1
+     librte_lpm.so.2
+     librte_mbuf.so.3
+     librte_mempool.so.2
+     librte_meter.so.1
+     librte_metrics.so.1
+     librte_net.so.1
+     librte_pdump.so.1
+     librte_pipeline.so.3
+     librte_pmd_bond.so.1
+     librte_pmd_ring.so.2
+     librte_port.so.3
+     librte_power.so.1
+     librte_reorder.so.1
+     librte_ring.so.1
+     librte_sched.so.1
+     librte_table.so.2
+     librte_timer.so.1
+     librte_vhost.so.3
+
+
+Tested Platforms
+----------------
+
+.. This section should contain a list of platforms that were tested with this
+   release.
+
+   The format is:
+
+   * <vendor> platform with <vendor> <type of devices> combinations
+
+     * List of CPU
+     * List of OS
+     * List of devices
+     * Other relevant details...
+
+   This section is a comment. do not overwrite or remove it.
+   Also, make sure to start the actual text at the margin.
+   =========================================================
-- 
2.7.4

^ permalink raw reply	[relevance 6%]

* [dpdk-dev] [PATCH 0/2] increase port_id range
@ 2017-08-09  8:42  3% Zhiyong Yang
  2017-08-09  9:00  4% ` De Lara Guarch, Pablo
  0 siblings, 1 reply; 200+ results
From: Zhiyong Yang @ 2017-08-09  8:42 UTC (permalink / raw)
  To: dev; +Cc: thomas

port_id is currently defined as uint8_t, which is limited to the range 0 to
255. A larger range is required for vdev scalability.

It is necessary for a redefinition of port_id to extend it from 1 bytes to
2 bytes. All ethdev APIs and usages related to port_id will be changed at the
same time.

Below is an API/ABI change notice for DPDK 17.11.
http://www.dpdk.org/dev/patchwork/patch/27475/

Discussion about port_id is the following thread.
http://www.dpdk.org/dev/patchwork/patch/23208/

Zhiyong Yang (2):
  ethdev: increase port_id range
  examples: increase port_id range

 app/pdump/main.c                                |   2 +-
 app/test-pmd/cmdline.c                          |   4 +-
 app/test-pmd/testpmd.c                          |   4 +-
 app/test-pmd/testpmd.h                          |   2 +-
 drivers/net/bonding/rte_eth_bond.h              |  40 ++--
 drivers/net/bonding/rte_eth_bond_8023ad.c       |   6 +-
 drivers/net/bonding/rte_eth_bond_api.c          |  54 +++---
 drivers/net/bonding/rte_eth_bond_pmd.c          |  10 +-
 drivers/net/bonding/rte_eth_bond_private.h      |  36 ++--
 drivers/net/failsafe/failsafe_ether.c           |   4 +-
 drivers/net/failsafe/failsafe_private.h         |   4 +-
 drivers/net/ring/rte_eth_ring.c                 |   2 +-
 examples/bond/main.c                            |   6 +-
 examples/ip_fragmentation/main.c                |   4 +-
 examples/l3fwd-power/main.c                     |   7 +-
 examples/l3fwd/l3fwd.h                          |  10 +-
 examples/l3fwd/l3fwd_em.c                       |   2 +-
 examples/l3fwd/l3fwd_lpm.c                      |   2 +-
 examples/link_status_interrupt/main.c           |   5 +-
 examples/performance-thread/l3fwd-thread/main.c |   7 +-
 examples/rxtx_callbacks/main.c                  |   8 +-
 lib/librte_ether/rte_ethdev.c                   | 231 +++++++++++------------
 lib/librte_ether/rte_ethdev.h                   | 236 ++++++++++++------------
 lib/librte_ether/rte_tm.c                       |  62 +++----
 lib/librte_ether/rte_tm.h                       |  60 +++---
 lib/librte_ether/rte_tm_driver.h                |   2 +-
 lib/librte_latencystats/rte_latencystats.c      |   8 +-
 lib/librte_pdump/rte_pdump.c                    |  16 +-
 lib/librte_pdump/rte_pdump.h                    |   4 +-
 lib/librte_port/rte_port_ethdev.c               |   6 +-
 lib/librte_port/rte_port_ethdev.h               |   6 +-
 31 files changed, 431 insertions(+), 419 deletions(-)

-- 
2.13.3

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH 0/2] increase port_id range
  2017-08-09  8:42  3% [dpdk-dev] [PATCH 0/2] increase port_id range Zhiyong Yang
@ 2017-08-09  9:00  4% ` De Lara Guarch, Pablo
  2017-08-09  9:17  0%   ` Yang, Zhiyong
  0 siblings, 1 reply; 200+ results
From: De Lara Guarch, Pablo @ 2017-08-09  9:00 UTC (permalink / raw)
  To: Yang, Zhiyong, dev; +Cc: thomas

Hi Zhiyong,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Zhiyong Yang
> Sent: Wednesday, August 9, 2017 9:42 AM
> To: dev@dpdk.org
> Cc: thomas@monjalon.net
> Subject: [dpdk-dev] [PATCH 0/2] increase port_id range
> 
> port_id is currently defined as uint8_t, which is limited to the range 0 to
> 255. A larger range is required for vdev scalability.
> 
> It is necessary for a redefinition of port_id to extend it from 1 bytes to
> 2 bytes. All ethdev APIs and usages related to port_id will be changed at the
> same time.
> 
> Below is an API/ABI change notice for DPDK 17.11.
> http://www.dpdk.org/dev/patchwork/patch/27475/
> 
> Discussion about port_id is the following thread.
> http://www.dpdk.org/dev/patchwork/patch/23208/
> 
> Zhiyong Yang (2):
>   ethdev: increase port_id range
>   examples: increase port_id range
> 
>  app/pdump/main.c                                |   2 +-
>  app/test-pmd/cmdline.c                          |   4 +-
>  app/test-pmd/testpmd.c                          |   4 +-
>  app/test-pmd/testpmd.h                          |   2 +-
>  drivers/net/bonding/rte_eth_bond.h              |  40 ++--
>  drivers/net/bonding/rte_eth_bond_8023ad.c       |   6 +-
>  drivers/net/bonding/rte_eth_bond_api.c          |  54 +++---
>  drivers/net/bonding/rte_eth_bond_pmd.c          |  10 +-
>  drivers/net/bonding/rte_eth_bond_private.h      |  36 ++--
>  drivers/net/failsafe/failsafe_ether.c           |   4 +-
>  drivers/net/failsafe/failsafe_private.h         |   4 +-
>  drivers/net/ring/rte_eth_ring.c                 |   2 +-
>  examples/bond/main.c                            |   6 +-
>  examples/ip_fragmentation/main.c                |   4 +-
>  examples/l3fwd-power/main.c                     |   7 +-
>  examples/l3fwd/l3fwd.h                          |  10 +-
>  examples/l3fwd/l3fwd_em.c                       |   2 +-
>  examples/l3fwd/l3fwd_lpm.c                      |   2 +-
>  examples/link_status_interrupt/main.c           |   5 +-
>  examples/performance-thread/l3fwd-thread/main.c |   7 +-
>  examples/rxtx_callbacks/main.c                  |   8 +-
>  lib/librte_ether/rte_ethdev.c                   | 231 +++++++++++------------
>  lib/librte_ether/rte_ethdev.h                   | 236 ++++++++++++------------
>  lib/librte_ether/rte_tm.c                       |  62 +++----
>  lib/librte_ether/rte_tm.h                       |  60 +++---
>  lib/librte_ether/rte_tm_driver.h                |   2 +-
>  lib/librte_latencystats/rte_latencystats.c      |   8 +-
>  lib/librte_pdump/rte_pdump.c                    |  16 +-
>  lib/librte_pdump/rte_pdump.h                    |   4 +-
>  lib/librte_port/rte_port_ethdev.c               |   6 +-
>  lib/librte_port/rte_port_ethdev.h               |   6 +-
>  31 files changed, 431 insertions(+), 419 deletions(-)
> 
> --
> 2.13.3

You should remove the deprecation notice that was sent
for the ABI breakage in this patchset, and add a note in release notes,
documenting the API/ABI changes that you have done.

Thanks,
Pablo

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH 0/2] increase port_id range
  2017-08-09  9:00  4% ` De Lara Guarch, Pablo
@ 2017-08-09  9:17  0%   ` Yang, Zhiyong
  0 siblings, 0 replies; 200+ results
From: Yang, Zhiyong @ 2017-08-09  9:17 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, dev; +Cc: thomas

Hi,Pablo: 

> -----Original Message-----
> From: De Lara Guarch, Pablo
> Sent: Wednesday, August 9, 2017 5:01 PM
> To: Yang, Zhiyong <zhiyong.yang@intel.com>; dev@dpdk.org
> Cc: thomas@monjalon.net
> Subject: RE: [dpdk-dev] [PATCH 0/2] increase port_id range
> 
> Hi Zhiyong,
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Zhiyong Yang
> > Sent: Wednesday, August 9, 2017 9:42 AM
> > To: dev@dpdk.org
> > Cc: thomas@monjalon.net
> > Subject: [dpdk-dev] [PATCH 0/2] increase port_id range
> >
> > port_id is currently defined as uint8_t, which is limited to the range
> > 0 to 255. A larger range is required for vdev scalability.
> >
> > It is necessary for a redefinition of port_id to extend it from 1
> > bytes to
> > 2 bytes. All ethdev APIs and usages related to port_id will be changed
> > at the same time.
> >
> > Below is an API/ABI change notice for DPDK 17.11.
> > http://www.dpdk.org/dev/patchwork/patch/27475/
> >
> > Discussion about port_id is the following thread.
> > http://www.dpdk.org/dev/patchwork/patch/23208/
> >
> > Zhiyong Yang (2):
> >   ethdev: increase port_id range
> >   examples: increase port_id range
> >
> >  app/pdump/main.c                                |   2 +-
> >  app/test-pmd/cmdline.c                          |   4 +-
> >  app/test-pmd/testpmd.c                          |   4 +-
> >  app/test-pmd/testpmd.h                          |   2 +-
> >  drivers/net/bonding/rte_eth_bond.h              |  40 ++--
> >  drivers/net/bonding/rte_eth_bond_8023ad.c       |   6 +-
> >  drivers/net/bonding/rte_eth_bond_api.c          |  54 +++---
> >  drivers/net/bonding/rte_eth_bond_pmd.c          |  10 +-
> >  drivers/net/bonding/rte_eth_bond_private.h      |  36 ++--
> >  drivers/net/failsafe/failsafe_ether.c           |   4 +-
> >  drivers/net/failsafe/failsafe_private.h         |   4 +-
> >  drivers/net/ring/rte_eth_ring.c                 |   2 +-
> >  examples/bond/main.c                            |   6 +-
> >  examples/ip_fragmentation/main.c                |   4 +-
> >  examples/l3fwd-power/main.c                     |   7 +-
> >  examples/l3fwd/l3fwd.h                          |  10 +-
> >  examples/l3fwd/l3fwd_em.c                       |   2 +-
> >  examples/l3fwd/l3fwd_lpm.c                      |   2 +-
> >  examples/link_status_interrupt/main.c           |   5 +-
> >  examples/performance-thread/l3fwd-thread/main.c |   7 +-
> >  examples/rxtx_callbacks/main.c                  |   8 +-
> >  lib/librte_ether/rte_ethdev.c                   | 231 +++++++++++------------
> >  lib/librte_ether/rte_ethdev.h                   | 236 ++++++++++++------------
> >  lib/librte_ether/rte_tm.c                       |  62 +++----
> >  lib/librte_ether/rte_tm.h                       |  60 +++---
> >  lib/librte_ether/rte_tm_driver.h                |   2 +-
> >  lib/librte_latencystats/rte_latencystats.c      |   8 +-
> >  lib/librte_pdump/rte_pdump.c                    |  16 +-
> >  lib/librte_pdump/rte_pdump.h                    |   4 +-
> >  lib/librte_port/rte_port_ethdev.c               |   6 +-
> >  lib/librte_port/rte_port_ethdev.h               |   6 +-
> >  31 files changed, 431 insertions(+), 419 deletions(-)
> >
> > --
> > 2.13.3
> 
> You should remove the deprecation notice that was sent for the ABI breakage in
> this patchset, and add a note in release notes, documenting the API/ABI changes
> that you have done.
> 

Thank you, Pablo. I forget to add a note.  Deprecation notice will be removed if need v2 patch.
It is my first patchset which needs to send deprecation notice firstly. :)

Zhiyong

> Thanks,
> Pablo




^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] kvargs: return error if key not find in kvlist
  @ 2017-08-09 14:35  3%   ` Wiles, Keith
  2017-08-09 14:47  0%     ` Ananyev, Konstantin
  0 siblings, 1 reply; 200+ results
From: Wiles, Keith @ 2017-08-09 14:35 UTC (permalink / raw)
  To: Ananyev, Konstantin; +Cc: dev


> On Aug 9, 2017, at 8:53 AM, Ananyev, Konstantin <konstantin.ananyev@intel.com> wrote:
> 
> 
> 
>> -----Original Message-----
>> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Keith Wiles
>> Sent: Wednesday, August 9, 2017 4:30 PM
>> To: dev@dpdk.org
>> Subject: [dpdk-dev] [PATCH] kvargs: return error if key not find in kvlist
>> 
>> rte_kvargs_process() should return error if the key
>> is not found in the kvlist or kvlist is NULL.
> 
> Looks like an API breakage for me…

To me it is not an ABI breakage only fixing the routine to return the correct status.

> Could you probably explain why do you think it is necessary?

For the no key found surely seems like an error to me, but I guess you can always require someone to call the rte_kvargs_count() API first which is not stated any place.

As for the kvlist being null that is an error IMO and returning success is not valid.

But to save a huge discussion I rejected the patch in patchwork for now.

> Konstantin
> 
>> 
>> Minor documentation changes and update for when an
>> error is returned.
>> 
>> Signed-off-by: Keith Wiles <keith.wiles@intel.com>
>> ---
>> lib/librte_kvargs/rte_kvargs.c | 7 ++++---
>> lib/librte_kvargs/rte_kvargs.h | 7 ++++---
>> 2 files changed, 8 insertions(+), 6 deletions(-)
>> 
>> diff --git a/lib/librte_kvargs/rte_kvargs.c b/lib/librte_kvargs/rte_kvargs.c
>> index 854ac83f5..c8e8f4b28 100755
>> --- a/lib/librte_kvargs/rte_kvargs.c
>> +++ b/lib/librte_kvargs/rte_kvargs.c
>> @@ -158,16 +158,17 @@ rte_kvargs_process(const struct rte_kvargs *kvlist,
>> 		void *opaque_arg)
>> {
>> 	const struct rte_kvargs_pair *pair;
>> -	unsigned i;
>> +	unsigned int i, found = 0;
>> 
>> 	for (i = 0; i < kvlist->count; i++) {
>> 		pair = &kvlist->pairs[i];
>> -		if (key_match == NULL || strcmp(pair->key, key_match) == 0) {
>> +		if (!key_match || strcmp(pair->key, key_match) == 0) {
>> +			found++;
>> 			if ((*handler)(pair->key, pair->value, opaque_arg) < 0)
>> 				return -1;
>> 		}
>> 	}
>> -	return 0;
>> +	return (!found) ? -1 : 0;
>> }
>> 
>> /* free the rte_kvargs structure */
>> diff --git a/lib/librte_kvargs/rte_kvargs.h b/lib/librte_kvargs/rte_kvargs.h
>> index 5821c726a..260d4db5b 100755
>> --- a/lib/librte_kvargs/rte_kvargs.h
>> +++ b/lib/librte_kvargs/rte_kvargs.h
>> @@ -115,9 +115,9 @@ void rte_kvargs_free(struct rte_kvargs *kvlist);
>>  * Call a handler function for each key/value matching the key
>>  *
>>  * For each key/value association that matches the given key, calls the
>> - * handler function with the for a given arg_name passing the value on the
>> + * handler function with the given arg_name passing the value in the
>>  * dictionary for that key and a given extra argument. If *kvlist* is NULL
>> - * function does nothing.
>> + * function does nothing and returns error.
>>  *
>>  * @param kvlist
>>  *   The rte_kvargs structure
>> @@ -131,7 +131,8 @@ void rte_kvargs_free(struct rte_kvargs *kvlist);
>>  *
>>  * @return
>>  *   - 0 on success
>> - *   - Negative on error
>> + *   - Negative on error or
>> + *       if *key_match* does not match an entry in *kvlist*
>>  */
>> int rte_kvargs_process(const struct rte_kvargs *kvlist,
>> 	const char *key_match, arg_handler_t handler, void *opaque_arg);
>> --
>> 2.11.0
> 

Regards,
Keith


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH] kvargs: return error if key not find in kvlist
  2017-08-09 14:35  3%   ` Wiles, Keith
@ 2017-08-09 14:47  0%     ` Ananyev, Konstantin
  0 siblings, 0 replies; 200+ results
From: Ananyev, Konstantin @ 2017-08-09 14:47 UTC (permalink / raw)
  To: Wiles, Keith; +Cc: dev



> -----Original Message-----
> From: Wiles, Keith
> Sent: Wednesday, August 9, 2017 5:36 PM
> To: Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH] kvargs: return error if key not find in kvlist
> 
> 
> > On Aug 9, 2017, at 8:53 AM, Ananyev, Konstantin <konstantin.ananyev@intel.com> wrote:
> >
> >
> >
> >> -----Original Message-----
> >> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Keith Wiles
> >> Sent: Wednesday, August 9, 2017 4:30 PM
> >> To: dev@dpdk.org
> >> Subject: [dpdk-dev] [PATCH] kvargs: return error if key not find in kvlist
> >>
> >> rte_kvargs_process() should return error if the key
> >> is not found in the kvlist or kvlist is NULL.
> >
> > Looks like an API breakage for me…
> 
> To me it is not an ABI breakage only fixing the routine to return the correct status.
> 
> > Could you probably explain why do you think it is necessary?
> 
> For the no key found surely seems like an error to me,

Not necessary, it could be an optional one.

> but I guess you can always require someone to call the rte_kvargs_count() API first

Yep.

> which is not stated any place.

> 
> As for the kvlist being null that is an error IMO and returning success is not valid.
> 
> But to save a huge discussion I rejected the patch in patchwork for now.

Ok.
Konstantin

> 
> > Konstantin
> >
> >>
> >> Minor documentation changes and update for when an
> >> error is returned.
> >>
> >> Signed-off-by: Keith Wiles <keith.wiles@intel.com>
> >> ---
> >> lib/librte_kvargs/rte_kvargs.c | 7 ++++---
> >> lib/librte_kvargs/rte_kvargs.h | 7 ++++---
> >> 2 files changed, 8 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/lib/librte_kvargs/rte_kvargs.c b/lib/librte_kvargs/rte_kvargs.c
> >> index 854ac83f5..c8e8f4b28 100755
> >> --- a/lib/librte_kvargs/rte_kvargs.c
> >> +++ b/lib/librte_kvargs/rte_kvargs.c
> >> @@ -158,16 +158,17 @@ rte_kvargs_process(const struct rte_kvargs *kvlist,
> >> 		void *opaque_arg)
> >> {
> >> 	const struct rte_kvargs_pair *pair;
> >> -	unsigned i;
> >> +	unsigned int i, found = 0;
> >>
> >> 	for (i = 0; i < kvlist->count; i++) {
> >> 		pair = &kvlist->pairs[i];
> >> -		if (key_match == NULL || strcmp(pair->key, key_match) == 0) {
> >> +		if (!key_match || strcmp(pair->key, key_match) == 0) {
> >> +			found++;
> >> 			if ((*handler)(pair->key, pair->value, opaque_arg) < 0)
> >> 				return -1;
> >> 		}
> >> 	}
> >> -	return 0;
> >> +	return (!found) ? -1 : 0;
> >> }
> >>
> >> /* free the rte_kvargs structure */
> >> diff --git a/lib/librte_kvargs/rte_kvargs.h b/lib/librte_kvargs/rte_kvargs.h
> >> index 5821c726a..260d4db5b 100755
> >> --- a/lib/librte_kvargs/rte_kvargs.h
> >> +++ b/lib/librte_kvargs/rte_kvargs.h
> >> @@ -115,9 +115,9 @@ void rte_kvargs_free(struct rte_kvargs *kvlist);
> >>  * Call a handler function for each key/value matching the key
> >>  *
> >>  * For each key/value association that matches the given key, calls the
> >> - * handler function with the for a given arg_name passing the value on the
> >> + * handler function with the given arg_name passing the value in the
> >>  * dictionary for that key and a given extra argument. If *kvlist* is NULL
> >> - * function does nothing.
> >> + * function does nothing and returns error.
> >>  *
> >>  * @param kvlist
> >>  *   The rte_kvargs structure
> >> @@ -131,7 +131,8 @@ void rte_kvargs_free(struct rte_kvargs *kvlist);
> >>  *
> >>  * @return
> >>  *   - 0 on success
> >> - *   - Negative on error
> >> + *   - Negative on error or
> >> + *       if *key_match* does not match an entry in *kvlist*
> >>  */
> >> int rte_kvargs_process(const struct rte_kvargs *kvlist,
> >> 	const char *key_match, arg_handler_t handler, void *opaque_arg);
> >> --
> >> 2.11.0
> >
> 
> Regards,
> Keith


^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v4 2/2] doc: Update ABI Change for rte_eth_stats_reset
  @ 2017-08-10 13:29 13%   ` David Harton
  2017-08-31 22:10  7%     ` Thomas Monjalon
  2017-09-01  2:26  3%   ` [dpdk-dev] [PATCH v5] ethdev: add return code to rte_eth_stats_reset() David Harton
  1 sibling, 1 reply; 200+ results
From: David Harton @ 2017-08-10 13:29 UTC (permalink / raw)
  To: thomas; +Cc: dev, harry.van.haaren, christian.ehrhardt, David Harton

Signed-off-by: David Harton <dharton@cisco.com>
---

v4:
* Added requested release note about ABI change.

 doc/guides/rel_notes/release_17_11.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f9..e329f8a 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -124,6 +124,7 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* Changed return type of ``rte_eth_stats_reset`` from ``void`` to ``int``.
 
 
 Shared Library Versions
-- 
2.10.3.dirty

^ permalink raw reply	[relevance 13%]

* Re: [dpdk-dev] Announcement of SSE requirement change in dpdk
  @ 2017-08-12 18:19  3%   ` Neil Horman
  2017-08-14  9:32  3%     ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2017-08-12 18:19 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev

On Fri, Aug 11, 2017 at 09:29:24PM +0100, Bruce Richardson wrote:
> On Wed, Aug 09, 2017 at 04:21:32PM -0400, Neil Horman wrote:
> > Can anyone point out to me when and where the change to require SSE4.2 was
> > dicussed?  The first I saw of it was when the commit to the release notes went
> > in on August 3, and I can find no prior mention of it, save for the patches that
> > went in separately in the prior weeks.
> > 
> > Neil
> > 
> There was no real widespread discussion of it, if that's what you are
> looking for. I made the proposal via patch, and it was reviewed and
> acked by a number of folks, with nobody raising any objections at the
I had a feeling that was the case, and yes, that does concern me somewhat.  In
this particular case I think its ok, because I can't really imagine anyone using
older atom processors, but I think it could become problematic in the future If
that support line moves too far into territory in which theres downstream
support issues (with things like OVS or other tree-external applications)

> time. Possibly it was a change that should have been more widely
> publicised ahead of time, but I'm not sure what form that publicization
> should have taken, since all tech discussion happens on the dev mailing
> list anyway.
> Not that I'm planning any similar changes, but for the future, what do
> you think the process for changes like this should be - and what changes
> would classify for it? If we have a process problem, let's try and fix
> it.
> 

I don't rightly know, to be honest.  DPDK is a little unique in this situation,
since user libraries are built to just access the lowest common denominator of a
given arch.  And in many ways, so is the kernel.  I'm open to suggestions, but I
think so some sort of plan would be a good idea.  These are just off the top of
my head, and likely have drawbacks, but just to get some conversation started:

1) Use extendend ISA instructions opportunistically
	By this I mean  to say, we could implement an alternatives system,
simmilar to what we have in the kernel, which can do dynamic instruction
replacement based on a run time test.  For example, you can write two versions
of a function, one which impements its method with sse4 and another version
which does the same thing using core isa instructions).  If sse4 is available at
runtime, the sse4 variant is mapped in, else the other version is.
	This is something we sort of talked about before, and while theres been
general support in its philosophy, its the sort of thing that takes alot of
work, and it is only used in those cases where you know you can use the
acceleration.

2) Limit where you introduce hardware deprecation
	Perhaps hardware deprecation can be announced in the same way ABI
deprecation is, and then introduced at a later date (I would make an opening
argument for the next LTS release).  Using the LTS release as a deprecation
point is nice because it lets downstream consumers standardize on a release
without having to worry about hardware support going away.

Just my $0.02.  food for thought
Neil

> Regards,
> /Bruce.
> 

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] Announcement of SSE requirement change in dpdk
  2017-08-12 18:19  3%   ` Neil Horman
@ 2017-08-14  9:32  3%     ` Bruce Richardson
  2017-08-14 10:50  0%       ` Neil Horman
  0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2017-08-14  9:32 UTC (permalink / raw)
  To: Neil Horman; +Cc: dev

On Sat, Aug 12, 2017 at 02:19:45PM -0400, Neil Horman wrote:
> On Fri, Aug 11, 2017 at 09:29:24PM +0100, Bruce Richardson wrote:
> > On Wed, Aug 09, 2017 at 04:21:32PM -0400, Neil Horman wrote:
> > > Can anyone point out to me when and where the change to require SSE4.2 was
> > > dicussed?  The first I saw of it was when the commit to the release notes went
> > > in on August 3, and I can find no prior mention of it, save for the patches that
> > > went in separately in the prior weeks.
> > > 
> > > Neil
> > > 
> > There was no real widespread discussion of it, if that's what you are
> > looking for. I made the proposal via patch, and it was reviewed and
> > acked by a number of folks, with nobody raising any objections at the
> I had a feeling that was the case, and yes, that does concern me somewhat.  In
> this particular case I think its ok, because I can't really imagine anyone using
> older atom processors, but I think it could become problematic in the future If
> that support line moves too far into territory in which theres downstream
> support issues (with things like OVS or other tree-external applications)
> 
> > time. Possibly it was a change that should have been more widely
> > publicised ahead of time, but I'm not sure what form that publicization
> > should have taken, since all tech discussion happens on the dev mailing
> > list anyway.
> > Not that I'm planning any similar changes, but for the future, what do
> > you think the process for changes like this should be - and what changes
> > would classify for it? If we have a process problem, let's try and fix
> > it.
> > 
> 
> I don't rightly know, to be honest.  DPDK is a little unique in this situation,
> since user libraries are built to just access the lowest common denominator of a
> given arch.  And in many ways, so is the kernel.  I'm open to suggestions, but I
> think so some sort of plan would be a good idea.  These are just off the top of
> my head, and likely have drawbacks, but just to get some conversation started:
> 
> 1) Use extendend ISA instructions opportunistically
> 	By this I mean  to say, we could implement an alternatives system,
> simmilar to what we have in the kernel, which can do dynamic instruction
> replacement based on a run time test.  For example, you can write two versions
> of a function, one which impements its method with sse4 and another version
> which does the same thing using core isa instructions).  If sse4 is available at
> runtime, the sse4 variant is mapped in, else the other version is.
> 	This is something we sort of talked about before, and while theres been
> general support in its philosophy, its the sort of thing that takes alot of
> work, and it is only used in those cases where you know you can use the
> acceleration.
> 
> 2) Limit where you introduce hardware deprecation
> 	Perhaps hardware deprecation can be announced in the same way ABI
> deprecation is, and then introduced at a later date (I would make an opening
> argument for the next LTS release).  Using the LTS release as a deprecation
> point is nice because it lets downstream consumers standardize on a release
> without having to worry about hardware support going away.
> 
> Just my $0.02.  food for thought
> Neil
> 
I think the ABI deprecation policy suggestion is a good one, where if we
want to drop support for some HW that was otherwise supported, we should
announce it at least one release in advance to make sure everyone is
aware of it.

/Bruce

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] Announcement of SSE requirement change in dpdk
  2017-08-14  9:32  3%     ` Bruce Richardson
@ 2017-08-14 10:50  0%       ` Neil Horman
  2017-08-14 10:58  0%         ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2017-08-14 10:50 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev

On Mon, Aug 14, 2017 at 10:32:15AM +0100, Bruce Richardson wrote:
> On Sat, Aug 12, 2017 at 02:19:45PM -0400, Neil Horman wrote:
> > On Fri, Aug 11, 2017 at 09:29:24PM +0100, Bruce Richardson wrote:
> > > On Wed, Aug 09, 2017 at 04:21:32PM -0400, Neil Horman wrote:
> > > > Can anyone point out to me when and where the change to require SSE4.2 was
> > > > dicussed?  The first I saw of it was when the commit to the release notes went
> > > > in on August 3, and I can find no prior mention of it, save for the patches that
> > > > went in separately in the prior weeks.
> > > > 
> > > > Neil
> > > > 
> > > There was no real widespread discussion of it, if that's what you are
> > > looking for. I made the proposal via patch, and it was reviewed and
> > > acked by a number of folks, with nobody raising any objections at the
> > I had a feeling that was the case, and yes, that does concern me somewhat.  In
> > this particular case I think its ok, because I can't really imagine anyone using
> > older atom processors, but I think it could become problematic in the future If
> > that support line moves too far into territory in which theres downstream
> > support issues (with things like OVS or other tree-external applications)
> > 
> > > time. Possibly it was a change that should have been more widely
> > > publicised ahead of time, but I'm not sure what form that publicization
> > > should have taken, since all tech discussion happens on the dev mailing
> > > list anyway.
> > > Not that I'm planning any similar changes, but for the future, what do
> > > you think the process for changes like this should be - and what changes
> > > would classify for it? If we have a process problem, let's try and fix
> > > it.
> > > 
> > 
> > I don't rightly know, to be honest.  DPDK is a little unique in this situation,
> > since user libraries are built to just access the lowest common denominator of a
> > given arch.  And in many ways, so is the kernel.  I'm open to suggestions, but I
> > think so some sort of plan would be a good idea.  These are just off the top of
> > my head, and likely have drawbacks, but just to get some conversation started:
> > 
> > 1) Use extendend ISA instructions opportunistically
> > 	By this I mean  to say, we could implement an alternatives system,
> > simmilar to what we have in the kernel, which can do dynamic instruction
> > replacement based on a run time test.  For example, you can write two versions
> > of a function, one which impements its method with sse4 and another version
> > which does the same thing using core isa instructions).  If sse4 is available at
> > runtime, the sse4 variant is mapped in, else the other version is.
> > 	This is something we sort of talked about before, and while theres been
> > general support in its philosophy, its the sort of thing that takes alot of
> > work, and it is only used in those cases where you know you can use the
> > acceleration.
> > 
> > 2) Limit where you introduce hardware deprecation
> > 	Perhaps hardware deprecation can be announced in the same way ABI
> > deprecation is, and then introduced at a later date (I would make an opening
> > argument for the next LTS release).  Using the LTS release as a deprecation
> > point is nice because it lets downstream consumers standardize on a release
> > without having to worry about hardware support going away.
> > 
> > Just my $0.02.  food for thought
> > Neil
> > 
> I think the ABI deprecation policy suggestion is a good one, where if we
> want to drop support for some HW that was otherwise supported, we should
> announce it at least one release in advance to make sure everyone is
> aware of it.
> 

Ok, I can agree with that. Are we also agreed on limiting hardware deprecation
to LTS release points?
Neil

> /Bruce
> 

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] Announcement of SSE requirement change in dpdk
  2017-08-14 10:50  0%       ` Neil Horman
@ 2017-08-14 10:58  0%         ` Bruce Richardson
  2017-08-14 11:23  4%           ` Neil Horman
  0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2017-08-14 10:58 UTC (permalink / raw)
  To: Neil Horman; +Cc: dev, techboard

On Mon, Aug 14, 2017 at 06:50:40AM -0400, Neil Horman wrote:
> On Mon, Aug 14, 2017 at 10:32:15AM +0100, Bruce Richardson wrote:
> > On Sat, Aug 12, 2017 at 02:19:45PM -0400, Neil Horman wrote:
> > > On Fri, Aug 11, 2017 at 09:29:24PM +0100, Bruce Richardson wrote:
> > > > On Wed, Aug 09, 2017 at 04:21:32PM -0400, Neil Horman wrote:
> > > > > Can anyone point out to me when and where the change to require SSE4.2 was
> > > > > dicussed?  The first I saw of it was when the commit to the release notes went
> > > > > in on August 3, and I can find no prior mention of it, save for the patches that
> > > > > went in separately in the prior weeks.
> > > > > 
> > > > > Neil
> > > > > 
> > > > There was no real widespread discussion of it, if that's what you are
> > > > looking for. I made the proposal via patch, and it was reviewed and
> > > > acked by a number of folks, with nobody raising any objections at the
> > > I had a feeling that was the case, and yes, that does concern me somewhat.  In
> > > this particular case I think its ok, because I can't really imagine anyone using
> > > older atom processors, but I think it could become problematic in the future If
> > > that support line moves too far into territory in which theres downstream
> > > support issues (with things like OVS or other tree-external applications)
> > > 
> > > > time. Possibly it was a change that should have been more widely
> > > > publicised ahead of time, but I'm not sure what form that publicization
> > > > should have taken, since all tech discussion happens on the dev mailing
> > > > list anyway.
> > > > Not that I'm planning any similar changes, but for the future, what do
> > > > you think the process for changes like this should be - and what changes
> > > > would classify for it? If we have a process problem, let's try and fix
> > > > it.
> > > > 
> > > 
> > > I don't rightly know, to be honest.  DPDK is a little unique in this situation,
> > > since user libraries are built to just access the lowest common denominator of a
> > > given arch.  And in many ways, so is the kernel.  I'm open to suggestions, but I
> > > think so some sort of plan would be a good idea.  These are just off the top of
> > > my head, and likely have drawbacks, but just to get some conversation started:
> > > 
> > > 1) Use extendend ISA instructions opportunistically
> > > 	By this I mean  to say, we could implement an alternatives system,
> > > simmilar to what we have in the kernel, which can do dynamic instruction
> > > replacement based on a run time test.  For example, you can write two versions
> > > of a function, one which impements its method with sse4 and another version
> > > which does the same thing using core isa instructions).  If sse4 is available at
> > > runtime, the sse4 variant is mapped in, else the other version is.
> > > 	This is something we sort of talked about before, and while theres been
> > > general support in its philosophy, its the sort of thing that takes alot of
> > > work, and it is only used in those cases where you know you can use the
> > > acceleration.
> > > 
> > > 2) Limit where you introduce hardware deprecation
> > > 	Perhaps hardware deprecation can be announced in the same way ABI
> > > deprecation is, and then introduced at a later date (I would make an opening
> > > argument for the next LTS release).  Using the LTS release as a deprecation
> > > point is nice because it lets downstream consumers standardize on a release
> > > without having to worry about hardware support going away.
> > > 
> > > Just my $0.02.  food for thought
> > > Neil
> > > 
> > I think the ABI deprecation policy suggestion is a good one, where if we
> > want to drop support for some HW that was otherwise supported, we should
> > announce it at least one release in advance to make sure everyone is
> > aware of it.
> > 
> 
> Ok, I can agree with that. Are we also agreed on limiting hardware deprecation
> to LTS release points?
> Neil
> 
To be clear, you think any hardware deprecation should be done as part
of the LTS release, rather than just after one? I would have thought the
latter, so as to keep legacy HW support around for as long as possible,
but I won't have a problem either way.

If you think it's a good policy to have a fixed point at which any HW
deprecations happen, I don't have an objection to that, but I'm curious
as to whether others think it may be too restrictive. It's not something
we've had a lot of up till now to know how big a deal such a restriction
might be.

+techboard: I suggest the tech board take an agenda item to ratify and
assign owner to document a HW deprecation policy, based on this thread,
at it's next meeting.

/Bruce

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] Announcement of SSE requirement change in dpdk
  2017-08-14 10:58  0%         ` Bruce Richardson
@ 2017-08-14 11:23  4%           ` Neil Horman
  0 siblings, 0 replies; 200+ results
From: Neil Horman @ 2017-08-14 11:23 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev, techboard

On Mon, Aug 14, 2017 at 11:58:21AM +0100, Bruce Richardson wrote:
> On Mon, Aug 14, 2017 at 06:50:40AM -0400, Neil Horman wrote:
> > On Mon, Aug 14, 2017 at 10:32:15AM +0100, Bruce Richardson wrote:
> > > On Sat, Aug 12, 2017 at 02:19:45PM -0400, Neil Horman wrote:
> > > > On Fri, Aug 11, 2017 at 09:29:24PM +0100, Bruce Richardson wrote:
> > > > > On Wed, Aug 09, 2017 at 04:21:32PM -0400, Neil Horman wrote:
> > > > > > Can anyone point out to me when and where the change to require SSE4.2 was
> > > > > > dicussed?  The first I saw of it was when the commit to the release notes went
> > > > > > in on August 3, and I can find no prior mention of it, save for the patches that
> > > > > > went in separately in the prior weeks.
> > > > > > 
> > > > > > Neil
> > > > > > 
> > > > > There was no real widespread discussion of it, if that's what you are
> > > > > looking for. I made the proposal via patch, and it was reviewed and
> > > > > acked by a number of folks, with nobody raising any objections at the
> > > > I had a feeling that was the case, and yes, that does concern me somewhat.  In
> > > > this particular case I think its ok, because I can't really imagine anyone using
> > > > older atom processors, but I think it could become problematic in the future If
> > > > that support line moves too far into territory in which theres downstream
> > > > support issues (with things like OVS or other tree-external applications)
> > > > 
> > > > > time. Possibly it was a change that should have been more widely
> > > > > publicised ahead of time, but I'm not sure what form that publicization
> > > > > should have taken, since all tech discussion happens on the dev mailing
> > > > > list anyway.
> > > > > Not that I'm planning any similar changes, but for the future, what do
> > > > > you think the process for changes like this should be - and what changes
> > > > > would classify for it? If we have a process problem, let's try and fix
> > > > > it.
> > > > > 
> > > > 
> > > > I don't rightly know, to be honest.  DPDK is a little unique in this situation,
> > > > since user libraries are built to just access the lowest common denominator of a
> > > > given arch.  And in many ways, so is the kernel.  I'm open to suggestions, but I
> > > > think so some sort of plan would be a good idea.  These are just off the top of
> > > > my head, and likely have drawbacks, but just to get some conversation started:
> > > > 
> > > > 1) Use extendend ISA instructions opportunistically
> > > > 	By this I mean  to say, we could implement an alternatives system,
> > > > simmilar to what we have in the kernel, which can do dynamic instruction
> > > > replacement based on a run time test.  For example, you can write two versions
> > > > of a function, one which impements its method with sse4 and another version
> > > > which does the same thing using core isa instructions).  If sse4 is available at
> > > > runtime, the sse4 variant is mapped in, else the other version is.
> > > > 	This is something we sort of talked about before, and while theres been
> > > > general support in its philosophy, its the sort of thing that takes alot of
> > > > work, and it is only used in those cases where you know you can use the
> > > > acceleration.
> > > > 
> > > > 2) Limit where you introduce hardware deprecation
> > > > 	Perhaps hardware deprecation can be announced in the same way ABI
> > > > deprecation is, and then introduced at a later date (I would make an opening
> > > > argument for the next LTS release).  Using the LTS release as a deprecation
> > > > point is nice because it lets downstream consumers standardize on a release
> > > > without having to worry about hardware support going away.
> > > > 
> > > > Just my $0.02.  food for thought
> > > > Neil
> > > > 
> > > I think the ABI deprecation policy suggestion is a good one, where if we
> > > want to drop support for some HW that was otherwise supported, we should
> > > announce it at least one release in advance to make sure everyone is
> > > aware of it.
> > > 
> > 
> > Ok, I can agree with that. Are we also agreed on limiting hardware deprecation
> > to LTS release points?
> > Neil
> > 
> To be clear, you think any hardware deprecation should be done as part
> of the LTS release, rather than just after one? I would have thought the
> latter, so as to keep legacy HW support around for as long as possible,
> but I won't have a problem either way.
> 
Thats what I was proposing, yes, that we should limit HW deprecation to LTS
releases, as that allows people using an LTS release to be guaranteed hardware
support for the lifetime of the release, though I'm not really married to the
idea, I'm just using it as a starting point to discuss the decision.

I do think we need to state that LTS releases maintain hardware compatibility as
well as ABI, but if we're comfortable with just adhering to that statement and
doing the backport work needed if it comes up, I'm also fine with hardware
deprecation on the "one release ahead" ABI schedule.

> If you think it's a good policy to have a fixed point at which any HW
> deprecations happen, I don't have an objection to that, but I'm curious
> as to whether others think it may be too restrictive. It's not something
> we've had a lot of up till now to know how big a deal such a restriction
> might be.
> 
I do think a deprecation schedule is warranted, but I'm flexible on the cadence.
I too was hoping we could get other opinions on the matter regarding how
restrictive this needs to be.

> +techboard: I suggest the tech board take an agenda item to ratify and
> assign owner to document a HW deprecation policy, based on this thread,
> at it's next meeting.
> 
That would be great, please!

Best
Neil

> /Bruce
> 

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v1 4/4] doc: remove dpdk iova aware notice
  @ 2017-08-14 15:15 15% ` Santosh Shukla
    1 sibling, 0 replies; 200+ results
From: Santosh Shukla @ 2017-08-14 15:15 UTC (permalink / raw)
  To: dev; +Cc: olivier.matz, thomas, jerin.jacob, hemant.agrawal, Santosh Shukla

Removed dpdk iova aware ABI deprecation notice,
and updated ABI change details in release_17.11.rst.

Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
---
 doc/guides/rel_notes/deprecation.rst   |  7 -------
 doc/guides/rel_notes/release_17_11.rst | 27 +++++++++++++++++++++++++++
 2 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 3362f3350..6482363bf 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -32,13 +32,6 @@ Deprecation Notices
 * eal: the support of Xen dom0 will be removed from EAL in 17.11; and with
   that, drivers/net/xenvirt and examples/vhost_xen will also be removed.
 
-* eal: An ABI change is planned for 17.11 to make DPDK aware of IOVA address
-  translation scheme.
-  Reference to phys address in EAL data-structure or functions may change to
-  IOVA address or more appropriate name.
-  The change will be only for the name.
-  Functional aspects of the API or data-structure will remain same.
-
 * The mbuf flags PKT_RX_VLAN_PKT and PKT_RX_QINQ_PKT are deprecated and
   are respectively replaced by PKT_RX_VLAN_STRIPPED and
   PKT_RX_QINQ_STRIPPED, that are better described. The old flags and
diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f916..30d0c0229 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -124,7 +124,34 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* **Following datatypes, structure member and function renamed to iova type.**
 
+  * Renamed ``phys_addr_t`` to ``iova_addr_t``.
+  * Renamed ``buf_physaddr`` to ``buf_iovaaddr`` for struct rte_mbuf.
+  * Renamed ``phys_addr`` to ``iova_addr`` for struct rte_memseg.
+  * The Following memory translation api renamed from:
+
+    * ``rte_mempool_populate_phys()``
+    * ``rte_mempool_populate_phys_tab()``
+    * ``rte_eal_using_phys_addrs()``
+    * ``rte_mem_virt2phy()``
+    * ``rte_dump_physmem_layout()``
+    * ``rte_eal_get_physmem_layout()``
+    * ``rte_eal_get_physmem_size()``
+    * ``rte_malloc_virt2phy()``
+    * ``rte_mem_phy2mch()``
+
+  * To the following iova types api:
+
+    * ``rte_mempool_populate_iova()``
+    * ``rte_mempool_populate_iova_tab()``
+    * ``rte_eal_using_iova_addrs()``
+    * ``rte_mem_virt2iova()``
+    * ``rte_dump_iovamem_layout()``
+    * ``rte_eal_get_iovamem_layout()``
+    * ``rte_eal_get_iovamem_size()``
+    * ``rte_malloc_virt2iova()``
+    * ``rte_mem_phy2iova()``
 
 Shared Library Versions
 -----------------------
-- 
2.11.0

^ permalink raw reply	[relevance 15%]

* [dpdk-dev] [PATCH v4 3/7] doc: remove mempool api change notice
  @ 2017-08-15  6:07  4%   ` Santosh Shukla
    1 sibling, 0 replies; 200+ results
From: Santosh Shukla @ 2017-08-15  6:07 UTC (permalink / raw)
  To: olivier.matz, dev; +Cc: thomas, jerin.jacob, hemant.agrawal, Santosh Shukla

Removed mempool api change deprecation notice and
updated change info in release_17.11.

Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
---
 doc/guides/rel_notes/deprecation.rst   | 9 ---------
 doc/guides/rel_notes/release_17_11.rst | 7 +++++++
 2 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 3362f3350..0e4cb1f95 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -44,15 +44,6 @@ Deprecation Notices
   PKT_RX_QINQ_STRIPPED, that are better described. The old flags and
   their behavior will be kept until 17.08 and will be removed in 17.11.
 
-* mempool: The following will be modified in 17.11:
-
-  - ``rte_mempool_xmem_size`` and ``rte_mempool_xmem_usage`` need to know
-    the mempool flag status so adding new param rte_mempool in those API.
-  - Removing __rte_unused int flag param from ``rte_mempool_generic_put``
-    and ``rte_mempool_generic_get`` API.
-  - ``rte_mempool`` flags data type will changed from int to
-    unsigned int.
-
 * ethdev: Tx offloads will no longer be enabled by default in 17.11.
   Instead, the ``rte_eth_txmode`` structure will be extended with
   bit field to enable each Tx offload.
diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f916..055ba10a4 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -110,6 +110,13 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* **The following changes made in mempool library**
+
+  * Moved ``flag`` datatype from int to unsigned int for ``rte_mempool``.
+  * Removed ``__rte_unused int flag`` param from ``rte_mempool_generic_put``
+    and ``rte_mempool_generic_get`` API.
+  * Added ``rte_mempool`` param in ``rte_mempool_xmem_size`` and
+    ``rte_mempool_xmem_usage``.
 
 ABI Changes
 -----------
-- 
2.11.0

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v3] cryptodev: allocate driver structure statically
  @ 2017-08-16  2:41  3% ` Pablo de Lara
  0 siblings, 0 replies; 200+ results
From: Pablo de Lara @ 2017-08-16  2:41 UTC (permalink / raw)
  To: declan.doherty, fiona.trahe, deepak.k.jain, john.griffin,
	jerin.jacob, akhil.goyal, hemant.agrawal
  Cc: dev, Pablo de Lara

When register a crypto driver, a cryptodev driver
structure was being allocated, using malloc.
Since this call may fail, it is safer to allocate
this memory statically in each PMD, so driver registration
will never fail.

Coverity issue: 158645

Fixes: 7a364faef185 ("cryptodev: remove crypto device type enumeration")

Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
---

Changes in v3:

- Added documentation (removed deprecation notice and added API Change)
- Modified title to something more explicit

Changes in v2:

- Allocate statically the cryptodev driver structure,
  instead of using malloc, that can potentially fail.

 doc/guides/rel_notes/deprecation.rst        |  6 ------
 doc/guides/rel_notes/release_17_11.rst      |  5 +++++
 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c    |  5 ++++-
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c  |  6 +++++-
 drivers/crypto/armv8/rte_armv8_pmd.c        |  9 ++++++---
 drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c |  5 ++++-
 drivers/crypto/kasumi/rte_kasumi_pmd.c      |  5 ++++-
 drivers/crypto/null/null_crypto_pmd.c       |  5 ++++-
 drivers/crypto/openssl/rte_openssl_pmd.c    |  5 ++++-
 drivers/crypto/qat/rte_qat_cryptodev.c      |  7 +++++--
 drivers/crypto/scheduler/scheduler_pmd.c    |  5 ++++-
 drivers/crypto/snow3g/rte_snow3g_pmd.c      |  5 ++++-
 drivers/crypto/zuc/rte_zuc_pmd.c            |  5 ++++-
 lib/librte_cryptodev/rte_cryptodev.c        | 18 +++++------------
 lib/librte_cryptodev/rte_cryptodev.h        | 20 -------------------
 lib/librte_cryptodev/rte_cryptodev_pmd.h    | 30 +++++++++++++++++++++++++++++
 16 files changed, 88 insertions(+), 53 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 3362f33..8be626e 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -106,12 +106,6 @@ Deprecation Notices
 
   - ``rte_cryptodev_vdev_pmd_init``
 
-* cryptodev: the following function will have an extra parameter, passing a
-  statically allocated crypto driver structure, instead of calling malloc,
-  in 17.11:
-
-  - ``rte_cryptodev_allocate_driver``
-
 * librte_meter: The API will change to accommodate configuration profiles.
   Most of the API functions will have an additional opaque parameter.
 
diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f9..cdb99f4 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -110,6 +110,11 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* **Modified the rte_cryptodev_allocate_driver function in the cryptodev library.**
+
+  The function ``rte_cryptodev_allocate_driver()`` has been modified.
+  An extra parameter ``struct cryptodev_driver *crypto_drv`` has been added.
+
 
 ABI Changes
 -----------
diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index d9c91d0..b59f399 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -630,10 +630,13 @@ static struct rte_vdev_driver aesni_gcm_pmd_drv = {
 	.remove = aesni_gcm_remove
 };
 
+static struct cryptodev_driver aesni_gcm_crypto_drv;
+
 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_AESNI_GCM_PMD, aesni_gcm_pmd_drv);
 RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_AESNI_GCM_PMD, cryptodev_aesni_gcm_pmd);
 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_AESNI_GCM_PMD,
 	"max_nb_queue_pairs=<int> "
 	"max_nb_sessions=<int> "
 	"socket_id=<int>");
-RTE_PMD_REGISTER_CRYPTO_DRIVER(aesni_gcm_pmd_drv, cryptodev_driver_id);
+RTE_PMD_REGISTER_CRYPTO_DRIVER(aesni_gcm_crypto_drv, aesni_gcm_pmd_drv,
+		cryptodev_driver_id);
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 16e1451..5846bc9 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -823,10 +823,14 @@ static struct rte_vdev_driver cryptodev_aesni_mb_pmd_drv = {
 	.remove = cryptodev_aesni_mb_remove
 };
 
+static struct cryptodev_driver aesni_mb_crypto_drv;
+
 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_AESNI_MB_PMD, cryptodev_aesni_mb_pmd_drv);
 RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_AESNI_MB_PMD, cryptodev_aesni_mb_pmd);
 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_AESNI_MB_PMD,
 	"max_nb_queue_pairs=<int> "
 	"max_nb_sessions=<int> "
 	"socket_id=<int>");
-RTE_PMD_REGISTER_CRYPTO_DRIVER(cryptodev_aesni_mb_pmd_drv, cryptodev_driver_id);
+RTE_PMD_REGISTER_CRYPTO_DRIVER(aesni_mb_crypto_drv,
+		cryptodev_aesni_mb_pmd_drv,
+		cryptodev_driver_id);
diff --git a/drivers/crypto/armv8/rte_armv8_pmd.c b/drivers/crypto/armv8/rte_armv8_pmd.c
index a5c39c9..b0d68d1 100644
--- a/drivers/crypto/armv8/rte_armv8_pmd.c
+++ b/drivers/crypto/armv8/rte_armv8_pmd.c
@@ -882,15 +882,18 @@ cryptodev_armv8_crypto_uninit(struct rte_vdev_device *vdev)
 	return 0;
 }
 
-static struct rte_vdev_driver armv8_crypto_drv = {
+static struct rte_vdev_driver armv8_crypto_pmd_drv = {
 	.probe = cryptodev_armv8_crypto_init,
 	.remove = cryptodev_armv8_crypto_uninit
 };
 
-RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_ARMV8_PMD, armv8_crypto_drv);
+static struct cryptodev_driver armv8_crypto_drv;
+
+RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_ARMV8_PMD, armv8_crypto_pmd_drv);
 RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_ARMV8_PMD, cryptodev_armv8_pmd);
 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_ARMV8_PMD,
 	"max_nb_queue_pairs=<int> "
 	"max_nb_sessions=<int> "
 	"socket_id=<int>");
-RTE_PMD_REGISTER_CRYPTO_DRIVER(armv8_crypto_drv, cryptodev_driver_id);
+RTE_PMD_REGISTER_CRYPTO_DRIVER(armv8_crypto_drv, armv8_crypto_pmd_drv,
+		cryptodev_driver_id);
diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
index e0f6cfc..dae296f 100644
--- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
+++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
@@ -2008,5 +2008,8 @@ static struct rte_dpaa2_driver rte_dpaa2_sec_driver = {
 	.remove = cryptodev_dpaa2_sec_remove,
 };
 
+static struct cryptodev_driver dpaa2_sec_crypto_drv;
+
 RTE_PMD_REGISTER_DPAA2(CRYPTODEV_NAME_DPAA2_SEC_PMD, rte_dpaa2_sec_driver);
-RTE_PMD_REGISTER_CRYPTO_DRIVER(rte_dpaa2_sec_driver, cryptodev_driver_id);
+RTE_PMD_REGISTER_CRYPTO_DRIVER(dpaa2_sec_crypto_drv, rte_dpaa2_sec_driver,
+		cryptodev_driver_id);
diff --git a/drivers/crypto/kasumi/rte_kasumi_pmd.c b/drivers/crypto/kasumi/rte_kasumi_pmd.c
index 38cd8a9..84cce34 100644
--- a/drivers/crypto/kasumi/rte_kasumi_pmd.c
+++ b/drivers/crypto/kasumi/rte_kasumi_pmd.c
@@ -661,10 +661,13 @@ static struct rte_vdev_driver cryptodev_kasumi_pmd_drv = {
 	.remove = cryptodev_kasumi_remove
 };
 
+static struct cryptodev_driver kasumi_crypto_drv;
+
 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_KASUMI_PMD, cryptodev_kasumi_pmd_drv);
 RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_KASUMI_PMD, cryptodev_kasumi_pmd);
 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_KASUMI_PMD,
 	"max_nb_queue_pairs=<int> "
 	"max_nb_sessions=<int> "
 	"socket_id=<int>");
-RTE_PMD_REGISTER_CRYPTO_DRIVER(cryptodev_kasumi_pmd_drv, cryptodev_driver_id);
+RTE_PMD_REGISTER_CRYPTO_DRIVER(kasumi_crypto_drv, cryptodev_kasumi_pmd_drv,
+		cryptodev_driver_id);
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index 2c82725..d5d2bb3 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -286,10 +286,13 @@ static struct rte_vdev_driver cryptodev_null_pmd_drv = {
 	.remove = cryptodev_null_remove_dev,
 };
 
+static struct cryptodev_driver null_crypto_drv;
+
 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_NULL_PMD, cryptodev_null_pmd_drv);
 RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_NULL_PMD, cryptodev_null_pmd);
 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_NULL_PMD,
 	"max_nb_queue_pairs=<int> "
 	"max_nb_sessions=<int> "
 	"socket_id=<int>");
-RTE_PMD_REGISTER_CRYPTO_DRIVER(cryptodev_null_pmd_drv, cryptodev_driver_id);
+RTE_PMD_REGISTER_CRYPTO_DRIVER(null_crypto_drv, cryptodev_null_pmd_drv,
+		cryptodev_driver_id);
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index 0bd5f98..5b863c8 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -1502,10 +1502,13 @@ static struct rte_vdev_driver cryptodev_openssl_pmd_drv = {
 	.remove = cryptodev_openssl_remove
 };
 
+static struct cryptodev_driver openssl_crypto_drv;
+
 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_OPENSSL_PMD,
 	cryptodev_openssl_pmd_drv);
 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_OPENSSL_PMD,
 	"max_nb_queue_pairs=<int> "
 	"max_nb_sessions=<int> "
 	"socket_id=<int>");
-RTE_PMD_REGISTER_CRYPTO_DRIVER(cryptodev_openssl_pmd_drv, cryptodev_driver_id);
+RTE_PMD_REGISTER_CRYPTO_DRIVER(openssl_crypto_drv, cryptodev_openssl_pmd_drv,
+		cryptodev_driver_id);
diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
index 7d56fca..3d9f3c8 100644
--- a/drivers/crypto/qat/rte_qat_cryptodev.c
+++ b/drivers/crypto/qat/rte_qat_cryptodev.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2015-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2015-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -169,6 +169,9 @@ static struct rte_pci_driver rte_qat_pmd = {
 	.remove = crypto_qat_pci_remove
 };
 
+static struct cryptodev_driver qat_crypto_drv;
+
 RTE_PMD_REGISTER_PCI(CRYPTODEV_NAME_QAT_SYM_PMD, rte_qat_pmd);
 RTE_PMD_REGISTER_PCI_TABLE(CRYPTODEV_NAME_QAT_SYM_PMD, pci_id_qat_map);
-RTE_PMD_REGISTER_CRYPTO_DRIVER(rte_qat_pmd, cryptodev_qat_driver_id);
+RTE_PMD_REGISTER_CRYPTO_DRIVER(qat_crypto_drv, rte_qat_pmd,
+		cryptodev_qat_driver_id);
diff --git a/drivers/crypto/scheduler/scheduler_pmd.c b/drivers/crypto/scheduler/scheduler_pmd.c
index 400fc4f..3170f7f 100644
--- a/drivers/crypto/scheduler/scheduler_pmd.c
+++ b/drivers/crypto/scheduler/scheduler_pmd.c
@@ -505,6 +505,8 @@ static struct rte_vdev_driver cryptodev_scheduler_pmd_drv = {
 	.remove = cryptodev_scheduler_remove
 };
 
+static struct cryptodev_driver scheduler_crypto_drv;
+
 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_SCHEDULER_PMD,
 	cryptodev_scheduler_pmd_drv);
 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_SCHEDULER_PMD,
@@ -512,5 +514,6 @@ RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_SCHEDULER_PMD,
 	"max_nb_sessions=<int> "
 	"socket_id=<int> "
 	"slave=<name>");
-RTE_PMD_REGISTER_CRYPTO_DRIVER(cryptodev_scheduler_pmd_drv,
+RTE_PMD_REGISTER_CRYPTO_DRIVER(scheduler_crypto_drv,
+		cryptodev_scheduler_pmd_drv,
 		cryptodev_driver_id);
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index dad4506..b2f6222 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -661,10 +661,13 @@ static struct rte_vdev_driver cryptodev_snow3g_pmd_drv = {
 	.remove = cryptodev_snow3g_remove
 };
 
+static struct cryptodev_driver snow3g_crypto_drv;
+
 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_SNOW3G_PMD, cryptodev_snow3g_pmd_drv);
 RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_SNOW3G_PMD, cryptodev_snow3g_pmd);
 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_SNOW3G_PMD,
 	"max_nb_queue_pairs=<int> "
 	"max_nb_sessions=<int> "
 	"socket_id=<int>");
-RTE_PMD_REGISTER_CRYPTO_DRIVER(cryptodev_snow3g_pmd_drv, cryptodev_driver_id);
+RTE_PMD_REGISTER_CRYPTO_DRIVER(snow3g_crypto_drv, cryptodev_snow3g_pmd_drv,
+		cryptodev_driver_id);
diff --git a/drivers/crypto/zuc/rte_zuc_pmd.c b/drivers/crypto/zuc/rte_zuc_pmd.c
index b301711..70966d4 100644
--- a/drivers/crypto/zuc/rte_zuc_pmd.c
+++ b/drivers/crypto/zuc/rte_zuc_pmd.c
@@ -565,9 +565,12 @@ static struct rte_vdev_driver cryptodev_zuc_pmd_drv = {
 	.remove = cryptodev_zuc_remove
 };
 
+static struct cryptodev_driver zuc_crypto_drv;
+
 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_ZUC_PMD, cryptodev_zuc_pmd_drv);
 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_ZUC_PMD,
 	"max_nb_queue_pairs=<int> "
 	"max_nb_sessions=<int> "
 	"socket_id=<int>");
-RTE_PMD_REGISTER_CRYPTO_DRIVER(cryptodev_zuc_pmd_drv, cryptodev_driver_id);
+RTE_PMD_REGISTER_CRYPTO_DRIVER(zuc_crypto_drv, cryptodev_zuc_pmd_drv,
+		cryptodev_driver_id);
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 327d7e8..a239395 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -1362,12 +1362,6 @@ TAILQ_HEAD(cryptodev_driver_list, cryptodev_driver);
 static struct cryptodev_driver_list cryptodev_driver_list =
 	TAILQ_HEAD_INITIALIZER(cryptodev_driver_list);
 
-struct cryptodev_driver {
-	TAILQ_ENTRY(cryptodev_driver) next; /**< Next in list. */
-	const struct rte_driver *driver;
-	uint8_t id;
-};
-
 int
 rte_cryptodev_driver_id_get(const char *name)
 {
@@ -1399,15 +1393,13 @@ rte_cryptodev_driver_name_get(uint8_t driver_id)
 }
 
 uint8_t
-rte_cryptodev_allocate_driver(const struct rte_driver *drv)
+rte_cryptodev_allocate_driver(struct cryptodev_driver *crypto_drv,
+		const struct rte_driver *drv)
 {
-	struct cryptodev_driver *driver;
-
-	driver = malloc(sizeof(*driver));
-	driver->driver = drv;
-	driver->id = nb_drivers;
+	crypto_drv->driver = drv;
+	crypto_drv->id = nb_drivers;
 
-	TAILQ_INSERT_TAIL(&cryptodev_driver_list, driver, next);
+	TAILQ_INSERT_TAIL(&cryptodev_driver_list, crypto_drv, next);
 
 	return nb_drivers++;
 }
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index 7ec9c4b..5225a5b 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -1025,26 +1025,6 @@ int rte_cryptodev_driver_id_get(const char *name);
  */
 const char *rte_cryptodev_driver_name_get(uint8_t driver_id);
 
-/**
- * @internal
- * Allocate Cryptodev driver.
- *
- * @param driver
- *   Pointer to rte_driver.
- * @return
- *  The driver type identifier
- */
-uint8_t rte_cryptodev_allocate_driver(const struct rte_driver *driver);
-
-
-#define RTE_PMD_REGISTER_CRYPTO_DRIVER(drv, driver_id)\
-RTE_INIT(init_ ##driver_id);\
-static void init_ ##driver_id(void)\
-{\
-	driver_id = rte_cryptodev_allocate_driver(&(drv).driver);\
-}
-
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_cryptodev/rte_cryptodev_pmd.h b/lib/librte_cryptodev/rte_cryptodev_pmd.h
index c983eb2..ba074e1 100644
--- a/lib/librte_cryptodev/rte_cryptodev_pmd.h
+++ b/lib/librte_cryptodev/rte_cryptodev_pmd.h
@@ -65,6 +65,13 @@ struct rte_cryptodev_global {
 	uint8_t max_devs;		/**< Max number of devices */
 };
 
+/* Cryptodev driver, containing the driver ID */
+struct cryptodev_driver {
+	TAILQ_ENTRY(cryptodev_driver) next; /**< Next in list. */
+	const struct rte_driver *driver;
+	uint8_t id;
+};
+
 /** pointer to global crypto devices data structure. */
 extern struct rte_cryptodev_global *rte_cryptodev_globals;
 
@@ -405,6 +412,29 @@ void rte_cryptodev_pmd_callback_process(struct rte_cryptodev *dev,
 int
 rte_cryptodev_pmd_create_dev_name(char *name, const char *dev_name_prefix);
 
+/**
+ * @internal
+ * Allocate Cryptodev driver.
+ *
+ * @param crypto_drv
+ *   Pointer to cryptodev_driver.
+ * @param drv
+ *   Pointer to rte_driver.
+ *
+ * @return
+ *  The driver type identifier
+ */
+uint8_t rte_cryptodev_allocate_driver(struct cryptodev_driver *crypto_drv,
+		const struct rte_driver *drv);
+
+
+#define RTE_PMD_REGISTER_CRYPTO_DRIVER(crypto_drv, drv, driver_id)\
+RTE_INIT(init_ ##driver_id);\
+static void init_ ##driver_id(void)\
+{\
+	driver_id = rte_cryptodev_allocate_driver(&crypto_drv, &(drv).driver);\
+}
+
 static inline void *
 get_session_private_data(const struct rte_cryptodev_sym_session *sess,
 		uint8_t driver_id) {
-- 
2.9.4

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH 0/8] service: rework for usability
  @ 2017-08-16 11:16  3% ` Neil Horman
  2017-08-16 11:31  4%   ` Van Haaren, Harry
    1 sibling, 1 reply; 200+ results
From: Neil Horman @ 2017-08-16 11:16 UTC (permalink / raw)
  To: Harry van Haaren; +Cc: dev

On Tue, Aug 15, 2017 at 01:32:32PM +0100, Harry van Haaren wrote:
> This patchset reworks the service apis to be more user
> friendly. In particular, the various rte_service_* functions
> now take an integer id parameter instead of a service pointer.
> This both reduces the API surface (no service_get_from_id()),
> and allows easier debugging (gdb function calls with integer args),
> and various other benefits (better encapsulation, less pointers :)
> 
> Finally, some APIs are changed or renamed for consistency and
> clarity of what they do. See commit messages for details.
> Note that the service library is merged as EXPERIMENTAL in
> the 17.08 release, allowing API improvements for 17.11 release.
> 
> I hope to merge this patchset early in the 17.11 timeframe,
> so please review ASAP to allow time for other DPDK components
> to utilize services in this release :)
> 
> Feedback and input welcome, -Harry
> 
You need to add a deprecation note in the rel notes area so that people are
aware of the upcomming ABI changes
Neil

> ---
> 
> There is one checkpatch warning: "macro with flow control", however
> this same type of macro is used extensively in Ethdev and others,
> I presume it is a false-positive.
> 
> Harry van Haaren (8):
>   service: rework probe and get name to use ids
>   service: rework lcore to service map functions
>   service: rework register to return service id
>   service: rework service start stop to runstate
>   service: rework service stats functions
>   service: rework unregister api to use integers
>   service: rework get by name function to use id
>   service: clarify documentation for register
> 
>  drivers/event/sw/sw_evdev.c                        |   7 +-
>  drivers/event/sw/sw_evdev.h                        |   1 +
>  lib/librte_eal/bsdapp/eal/rte_eal_version.map      |  11 +-
>  lib/librte_eal/common/include/rte_service.h        | 144 +++++++-----------
>  .../common/include/rte_service_component.h         |  13 +-
>  lib/librte_eal/common/rte_service.c                | 167 +++++++++------------
>  lib/librte_eal/linuxapp/eal/rte_eal_version.map    |  11 +-
>  test/test/test_service_cores.c                     | 123 +++++++--------
>  8 files changed, 215 insertions(+), 262 deletions(-)
> 
> -- 
> 2.7.4
> 
> 

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH 0/8] service: rework for usability
  2017-08-16 11:16  3% ` Neil Horman
@ 2017-08-16 11:31  4%   ` Van Haaren, Harry
  2017-08-16 12:07  0%     ` Van Haaren, Harry
  0 siblings, 1 reply; 200+ results
From: Van Haaren, Harry @ 2017-08-16 11:31 UTC (permalink / raw)
  To: Neil Horman; +Cc: dev

> From: Neil Horman [mailto:nhorman@tuxdriver.com]
> Sent: Wednesday, August 16, 2017 12:16 PM
> To: Van Haaren, Harry <harry.van.haaren@intel.com>
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 0/8] service: rework for usability
> 
> On Tue, Aug 15, 2017 at 01:32:32PM +0100, Harry van Haaren wrote:
> > This patchset reworks the service apis to be more user
> > friendly. In particular, the various rte_service_* functions
> > now take an integer id parameter instead of a service pointer.
> > This both reduces the API surface (no service_get_from_id()),
> > and allows easier debugging (gdb function calls with integer args),
> > and various other benefits (better encapsulation, less pointers :)
> >
> > Finally, some APIs are changed or renamed for consistency and
> > clarity of what they do. See commit messages for details.
> > Note that the service library is merged as EXPERIMENTAL in
> > the 17.08 release, allowing API improvements for 17.11 release.
> >
> > I hope to merge this patchset early in the 17.11 timeframe,
> > so please review ASAP to allow time for other DPDK components
> > to utilize services in this release :)
> >
> > Feedback and input welcome, -Harry
> >
> You need to add a deprecation note in the rel notes area so that people are
> aware of the upcomming ABI changes

Service cores was merged into 17.08 with the EXPERIMENTAL tag, which indicates that the API and ABI are not stable. The version map file has the service cores functions added in the Experimental staging area, instead of in the 17.08 stable ABI[1]. To make this very visible to the users, the documentation has large "Warning: Experimental, this API may change without prior notice" marks[2], and the MAINTAINERS file[3] has the Experimental tag.

As far as I am aware, those are all the requirements to be able to remove / change / update / fix APIs. It was discussed on #IRC that it would be better to merge service-cores as experimental to allow faster iteration, and to get improvements out the door, and I'm still of that opinion.

Given the above, I don't see any issue with merging service-core changes into the 17.11 release.

[1] http://dpdk.org/browse/dpdk/tree/lib/librte_eal/linuxapp/eal/rte_eal_version.map#n212
[2] http://dpdk.org/doc/api/rte__service_8h.html#aea7fce2a101bf2c00194dffb30bfc4ea
[3] http://dpdk.org/browse/dpdk/tree/MAINTAINERS#n138

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH 0/8] service: rework for usability
  2017-08-16 11:31  4%   ` Van Haaren, Harry
@ 2017-08-16 12:07  0%     ` Van Haaren, Harry
  2017-08-16 13:27  0%       ` Neil Horman
  0 siblings, 1 reply; 200+ results
From: Van Haaren, Harry @ 2017-08-16 12:07 UTC (permalink / raw)
  To: Van Haaren, Harry, Neil Horman; +Cc: dev

> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Van Haaren, Harry
> Sent: Wednesday, August 16, 2017 12:32 PM
> To: Neil Horman <nhorman@tuxdriver.com>
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 0/8] service: rework for usability
> 
> > From: Neil Horman [mailto:nhorman@tuxdriver.com]
> > Sent: Wednesday, August 16, 2017 12:16 PM
> > To: Van Haaren, Harry <harry.van.haaren@intel.com>
> > Cc: dev@dpdk.org
> > Subject: Re: [dpdk-dev] [PATCH 0/8] service: rework for usability
> >
> > On Tue, Aug 15, 2017 at 01:32:32PM +0100, Harry van Haaren wrote:
> > > This patchset reworks the service apis to be more user
> > > friendly. In particular, the various rte_service_* functions
> > > now take an integer id parameter instead of a service pointer.
> > > This both reduces the API surface (no service_get_from_id()),
> > > and allows easier debugging (gdb function calls with integer args),
> > > and various other benefits (better encapsulation, less pointers :)
> > >
> > > Finally, some APIs are changed or renamed for consistency and
> > > clarity of what they do. See commit messages for details.
> > > Note that the service library is merged as EXPERIMENTAL in
> > > the 17.08 release, allowing API improvements for 17.11 release.
> > >
> > > I hope to merge this patchset early in the 17.11 timeframe,
> > > so please review ASAP to allow time for other DPDK components
> > > to utilize services in this release :)
> > >
> > > Feedback and input welcome, -Harry
> > >
> > You need to add a deprecation note in the rel notes area so that people are
> > aware of the upcomming ABI changes
> 
> Service cores was merged into 17.08 with the EXPERIMENTAL tag, which indicates that the
> API and ABI are not stable. The version map file has the service cores functions added in
> the Experimental staging area, instead of in the 17.08 stable ABI[1]. To make this very
> visible to the users, the documentation has large "Warning: Experimental, this API may
> change without prior notice" marks[2], and the MAINTAINERS file[3] has the Experimental
> tag.
> 
> As far as I am aware, those are all the requirements to be able to remove / change /
> update / fix APIs. It was discussed on #IRC that it would be better to merge service-cores
> as experimental to allow faster iteration, and to get improvements out the door, and I'm
> still of that opinion.
> 
> Given the above, I don't see any issue with merging service-core changes into the 17.11
> release.
> 
> [1] http://dpdk.org/browse/dpdk/tree/lib/librte_eal/linuxapp/eal/rte_eal_version.map#n212
> [2] http://dpdk.org/doc/api/rte__service_8h.html#aea7fce2a101bf2c00194dffb30bfc4ea
> [3] http://dpdk.org/browse/dpdk/tree/MAINTAINERS#n138

Self-reply;

On re-reading, perhaps I understood you wrong; did you mean that I need to add a section to the Release notes that the service core APIs have been updated in 17.11 itself?

That's a very valid point - and I'll fix that in v2, (some other typo fixes to fix too).

-Harry

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 0/8] service: rework for usability
  2017-08-16 12:07  0%     ` Van Haaren, Harry
@ 2017-08-16 13:27  0%       ` Neil Horman
  0 siblings, 0 replies; 200+ results
From: Neil Horman @ 2017-08-16 13:27 UTC (permalink / raw)
  To: Van Haaren, Harry; +Cc: dev

On Wed, Aug 16, 2017 at 12:07:11PM +0000, Van Haaren, Harry wrote:
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Van Haaren, Harry
> > Sent: Wednesday, August 16, 2017 12:32 PM
> > To: Neil Horman <nhorman@tuxdriver.com>
> > Cc: dev@dpdk.org
> > Subject: Re: [dpdk-dev] [PATCH 0/8] service: rework for usability
> > 
> > > From: Neil Horman [mailto:nhorman@tuxdriver.com]
> > > Sent: Wednesday, August 16, 2017 12:16 PM
> > > To: Van Haaren, Harry <harry.van.haaren@intel.com>
> > > Cc: dev@dpdk.org
> > > Subject: Re: [dpdk-dev] [PATCH 0/8] service: rework for usability
> > >
> > > On Tue, Aug 15, 2017 at 01:32:32PM +0100, Harry van Haaren wrote:
> > > > This patchset reworks the service apis to be more user
> > > > friendly. In particular, the various rte_service_* functions
> > > > now take an integer id parameter instead of a service pointer.
> > > > This both reduces the API surface (no service_get_from_id()),
> > > > and allows easier debugging (gdb function calls with integer args),
> > > > and various other benefits (better encapsulation, less pointers :)
> > > >
> > > > Finally, some APIs are changed or renamed for consistency and
> > > > clarity of what they do. See commit messages for details.
> > > > Note that the service library is merged as EXPERIMENTAL in
> > > > the 17.08 release, allowing API improvements for 17.11 release.
> > > >
> > > > I hope to merge this patchset early in the 17.11 timeframe,
> > > > so please review ASAP to allow time for other DPDK components
> > > > to utilize services in this release :)
> > > >
> > > > Feedback and input welcome, -Harry
> > > >
> > > You need to add a deprecation note in the rel notes area so that people are
> > > aware of the upcomming ABI changes
> > 
> > Service cores was merged into 17.08 with the EXPERIMENTAL tag, which indicates that the
> > API and ABI are not stable. The version map file has the service cores functions added in
> > the Experimental staging area, instead of in the 17.08 stable ABI[1]. To make this very
> > visible to the users, the documentation has large "Warning: Experimental, this API may
> > change without prior notice" marks[2], and the MAINTAINERS file[3] has the Experimental
> > tag.
> > 
> > As far as I am aware, those are all the requirements to be able to remove / change /
> > update / fix APIs. It was discussed on #IRC that it would be better to merge service-cores
> > as experimental to allow faster iteration, and to get improvements out the door, and I'm
> > still of that opinion.
> > 
> > Given the above, I don't see any issue with merging service-core changes into the 17.11
> > release.
> > 
> > [1] http://dpdk.org/browse/dpdk/tree/lib/librte_eal/linuxapp/eal/rte_eal_version.map#n212
> > [2] http://dpdk.org/doc/api/rte__service_8h.html#aea7fce2a101bf2c00194dffb30bfc4ea
> > [3] http://dpdk.org/browse/dpdk/tree/MAINTAINERS#n138
> 
> Self-reply;
> 
> On re-reading, perhaps I understood you wrong; did you mean that I need to add a section to the Release notes that the service core APIs have been updated in 17.11 itself?
> 
> That's a very valid point - and I'll fix that in v2, (some other typo fixes to fix too).
> 
I hadn't noted the experimental tag, so you likely don't need a deprecation
warning, but yes, a release note to indicate the change to the API in 17.11
would be good.

Best
NEil

> -Harry
> 

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2] net/i40e: new API to add VF MAC address from PF
  @ 2017-08-17 13:05  0%   ` Ferruh Yigit
  2017-08-17 13:36  0%     ` Lu, Wenzhuo
  0 siblings, 1 reply; 200+ results
From: Ferruh Yigit @ 2017-08-17 13:05 UTC (permalink / raw)
  To: Wenzhuo Lu, dev; +Cc: jingjing.wu, beilei.xing, Stephen Hurd, Ajit Khaparde

On 7/25/2017 3:09 PM, Wenzhuo Lu wrote:
> Currently, on i40e the parameter 'pool' of API
> rte_eth_dev_mac_addr_add means the VMDq pool, not VF.

The argument "pool" in rte_eth_dev_mac_addr_add() IS VMDq pool.
This is not just for i40e, this is by API definition.

> So, it's wrong to use it to set the VF MAC address.

Agreed, it seems testpmd function cmd_vf_mac_addr_parsed() implemented
wrong.

> As this API is also used by the VMDq example, ideally
> we need a parameter to tell the pool is VMDq or VF.
> But it's hard to change it because of the ABI change
> concern.

I think we shouldn't NOT update rte_eth_dev_mac_addr_add() API, it is
not wrong.

But should fix testpmd ""mac_addr add port <port_id> vf <vf_id>
<mac_addr>" command.

Can you please update this patch as two patches:

1- i40e rte_pmd_i40e_add_vf_mac_addr() API

2- Fix testpmd function, instead of inserting new i40e API replace it
with wrong rte_eth_dev_mac_addr_add() call.
And I guess bnxt driver also has API to add VF MAC, can you add that one
too?

> Now the solution is to provide a new API, users can
> call it to add VF MAC address from PF on i40e.
> 
> Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>

<...>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2] net/i40e: new API to add VF MAC address from PF
  2017-08-17 13:05  0%   ` Ferruh Yigit
@ 2017-08-17 13:36  0%     ` Lu, Wenzhuo
  0 siblings, 0 replies; 200+ results
From: Lu, Wenzhuo @ 2017-08-17 13:36 UTC (permalink / raw)
  To: Yigit, Ferruh, dev
  Cc: Wu, Jingjing, Xing, Beilei, Stephen Hurd, Ajit Khaparde

Hi Ferruh,

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Thursday, August 17, 2017 9:05 AM
> To: Lu, Wenzhuo <wenzhuo.lu@intel.com>; dev@dpdk.org
> Cc: Wu, Jingjing <jingjing.wu@intel.com>; Xing, Beilei <beilei.xing@intel.com>;
> Stephen Hurd <stephen.hurd@broadcom.com>; Ajit Khaparde
> <ajit.khaparde@broadcom.com>
> Subject: Re: [dpdk-dev] [PATCH v2] net/i40e: new API to add VF MAC address
> from PF
> 
> On 7/25/2017 3:09 PM, Wenzhuo Lu wrote:
> > Currently, on i40e the parameter 'pool' of API
> > rte_eth_dev_mac_addr_add means the VMDq pool, not VF.
> 
> The argument "pool" in rte_eth_dev_mac_addr_add() IS VMDq pool.
> This is not just for i40e, this is by API definition.
> 
> > So, it's wrong to use it to set the VF MAC address.
> 
> Agreed, it seems testpmd function cmd_vf_mac_addr_parsed() implemented
> wrong.
> 
> > As this API is also used by the VMDq example, ideally we need a
> > parameter to tell the pool is VMDq or VF.
> > But it's hard to change it because of the ABI change concern.
> 
> I think we shouldn't NOT update rte_eth_dev_mac_addr_add() API, it is not
> wrong.
Agree :)

> 
> But should fix testpmd ""mac_addr add port <port_id> vf <vf_id>
> <mac_addr>" command.
> 
> Can you please update this patch as two patches:
> 
> 1- i40e rte_pmd_i40e_add_vf_mac_addr() API
> 
> 2- Fix testpmd function, instead of inserting new i40e API replace it with
> wrong rte_eth_dev_mac_addr_add() call.
> And I guess bnxt driver also has API to add VF MAC, can you add that one too?
Thanks for the suggestion. Will send a new version.

> 
> > Now the solution is to provide a new API, users can call it to add VF
> > MAC address from PF on i40e.
> >
> > Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> 
> <...>

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH] vhost: added user callbacks for socket open/close
@ 2017-08-21  9:34  3% Dariusz Stojaczyk
  2017-08-21 15:00  0% ` Jens Freimann
  2017-08-22 16:24  3% ` [dpdk-dev] [PATCH v2] " Dariusz Stojaczyk
  0 siblings, 2 replies; 200+ results
From: Dariusz Stojaczyk @ 2017-08-21  9:34 UTC (permalink / raw)
  To: dev; +Cc: Pawel Wodkowski, Dariusz Stojaczyk

When user receives destroy_device signal, he does not know *why* that
event happened. He does not differ between socket shutdown and virtio
processing pause. User could completely delete device during transition
from BIOS to kernel, causing freeze or possibly kernel panic. Instead
of changing new_device/destroy_device callbacks and breaking the ABI,
a set of new functions new_connection/destroy_connection has been added.

Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
---
 lib/librte_vhost/rte_vhost.h |  5 ++++-
 lib/librte_vhost/socket.c    | 23 +++++++++++++++++++----
 2 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h
index 8c974eb..8f86167 100644
--- a/lib/librte_vhost/rte_vhost.h
+++ b/lib/librte_vhost/rte_vhost.h
@@ -107,7 +107,10 @@ struct vhost_device_ops {
 	 */
 	int (*features_changed)(int vid, uint64_t features);
 
-	void *reserved[4]; /**< Reserved for future extension */
+	int (*new_connection)(int vid);		/**< Connect to socket. */
+	void (*destroy_connection)(int vid);	/**< Disconnect from socket */
+
+	void *reserved[2]; /**< Reserved for future extension */
 };
 
 /**
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 41aa3f9..4ab4ff7 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -230,24 +230,36 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 
 	RTE_LOG(INFO, VHOST_CONFIG, "new device, handle is %d\n", vid);
 
+	if (vsocket->notify_ops->new_connection) {
+		ret = vsocket->notify_ops->new_connection(vid);
+		if (ret < 0) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"failed to add vhost user connection with fd %d\n",
+				fd);
+			goto err;
+		}
+	}
+
 	conn->connfd = fd;
 	conn->vsocket = vsocket;
 	conn->vid = vid;
 	ret = fdset_add(&vhost_user.fdset, fd, vhost_user_read_cb,
 			NULL, conn);
 	if (ret < 0) {
-		conn->connfd = -1;
-		free(conn);
-		close(fd);
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"failed to add fd %d into vhost server fdset\n",
 			fd);
-		return;
+		goto err;
 	}
 
 	pthread_mutex_lock(&vsocket->conn_mutex);
 	TAILQ_INSERT_TAIL(&vsocket->conn_list, conn, next);
 	pthread_mutex_unlock(&vsocket->conn_mutex);
+	return;
+
+err:
+	free(conn);
+	close(fd);
 }
 
 /* call back when there is new vhost-user connection from client  */
@@ -277,6 +289,9 @@ vhost_user_read_cb(int connfd, void *dat, int *remove)
 		*remove = 1;
 		vhost_destroy_device(conn->vid);
 
+		if (vsocket->notify_ops->destroy_connection)
+			vsocket->notify_ops->destroy_connection(conn->vid);
+
 		pthread_mutex_lock(&vsocket->conn_mutex);
 		TAILQ_REMOVE(&vsocket->conn_list, conn, next);
 		pthread_mutex_unlock(&vsocket->conn_mutex);
-- 
2.7.4

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v2 15/15] docs: add notes on service cores API updates
  @ 2017-08-21 12:58  4%   ` Harry van Haaren
  0 siblings, 0 replies; 200+ results
From: Harry van Haaren @ 2017-08-21 12:58 UTC (permalink / raw)
  To: dev; +Cc: Harry van Haaren

Add a section on the service cores API changes to 17.11 release notes.

Suggested-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 doc/guides/rel_notes/release_17_11.rst | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 6e6ba1c..8bf91bd 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -117,6 +117,19 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* **Service cores API updated for usability**
+
+  The service cores API has been changed, removing pointers from the API
+  where possible, instead using integer IDs to identify each service. This
+  simplifed application code, aids debugging, and provides better
+  encapsulation. A summary of the main changes made is as follows:
+
+  * Services identified by ID not by ``rte_service_spec`` pointer
+  * Reduced API surface by using ``set`` functions instead of enable/disable
+  * Reworked ``rte_service_register`` to provide the service ID to registrar
+  * Rework start and stop APIs into ``rte_service_runstate_set``
+  * Added API to set runstate of service implementation to indicate readyness
+
 
 ABI Changes
 -----------
-- 
2.7.4

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH] vhost: added user callbacks for socket open/close
  2017-08-21  9:34  3% [dpdk-dev] [PATCH] vhost: added user callbacks for socket open/close Dariusz Stojaczyk
@ 2017-08-21 15:00  0% ` Jens Freimann
  2017-08-22 16:24  3% ` [dpdk-dev] [PATCH v2] " Dariusz Stojaczyk
  1 sibling, 0 replies; 200+ results
From: Jens Freimann @ 2017-08-21 15:00 UTC (permalink / raw)
  To: Dariusz Stojaczyk; +Cc: dev, Pawel Wodkowski, Maxime Coquelin (mcoqueli), yliu

Hi Dariusz,

On Mon, Aug 21, 2017 at 11:34:42AM +0200, Dariusz Stojaczyk wrote:
>When user receives destroy_device signal, he does not know *why* that
>event happened. He does not differ between socket shutdown and virtio
>processing pause. User could completely delete device during transition
>from BIOS to kernel, causing freeze or possibly kernel panic. Instead
>of changing new_device/destroy_device callbacks and breaking the ABI,
>a set of new functions new_connection/destroy_connection has been added.
>
>Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
>---
> lib/librte_vhost/rte_vhost.h |  5 ++++-
> lib/librte_vhost/socket.c    | 23 +++++++++++++++++++----
> 2 files changed, 23 insertions(+), 5 deletions(-)
>
>diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h
>index 8c974eb..8f86167 100644
>--- a/lib/librte_vhost/rte_vhost.h
>+++ b/lib/librte_vhost/rte_vhost.h
>@@ -107,7 +107,10 @@ struct vhost_device_ops {
> 	 */
> 	int (*features_changed)(int vid, uint64_t features);
>
>-	void *reserved[4]; /**< Reserved for future extension */
>+	int (*new_connection)(int vid);		/**< Connect to socket. */
>+	void (*destroy_connection)(int vid);	/**< Disconnect from socket */

I'm a little uncertain but my gut feeling is that in this context a connection is
something between two sockets, not between devices. I would probably
add these callbacks to struct vhost_user_socket. This is also where we
keep the list of connections.

regards,
Jens 

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v2] vhost: added user callbacks for socket open/close
  2017-08-21  9:34  3% [dpdk-dev] [PATCH] vhost: added user callbacks for socket open/close Dariusz Stojaczyk
  2017-08-21 15:00  0% ` Jens Freimann
@ 2017-08-22 16:24  3% ` Dariusz Stojaczyk
  2017-08-25  9:22  0%   ` Jens Freimann
  2017-08-30 10:50  3%   ` [dpdk-dev] [PATCH v3] rte_vhost: " Dariusz Stojaczyk
  1 sibling, 2 replies; 200+ results
From: Dariusz Stojaczyk @ 2017-08-22 16:24 UTC (permalink / raw)
  To: dev; +Cc: Pawel Wodkowski, Dariusz Stojaczyk

When user receives destroy_device signal, he does not know *why* that
event happened. He does not differ between socket shutdown and virtio
processing pause. User could completely delete device during transition
from BIOS to kernel, causing freeze or possibly kernel panic. Instead
of changing new_device/destroy_device callbacks and breaking the ABI,
a set of new functions new_connection/destroy_connection has been added.

Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
---
v2: also updated vhost_lib.rst
 doc/guides/prog_guide/vhost_lib.rst | 15 +++++++++++++--
 lib/librte_vhost/rte_vhost.h        |  5 ++++-
 lib/librte_vhost/socket.c           | 23 +++++++++++++++++++----
 3 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index 5979290..861a0e2 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -129,8 +129,7 @@ The following is an overview of some key Vhost API functions:
 
   * ``destroy_device(int vid)``
 
-    This callback is invoked when a virtio device shuts down (or when the
-    vhost connection is broken).
+    This callback is invoked when a virtio device is paused or shut down.
 
   * ``vring_state_changed(int vid, uint16_t queue_id, int enable)``
 
@@ -143,6 +142,18 @@ The following is an overview of some key Vhost API functions:
     ``VHOST_F_LOG_ALL`` will be set/cleared at the start/end of live
     migration, respectively.
 
+  * ``new_connection(int vid)``
+
+    This callback is invoked on new vhost-user socket connection. If DPDK
+    acts as the server the device should not be deleted before
+     ``destroy_connection`` callback is received.
+
+  * ``destroy_connection(int vid)``
+
+    This callback is invoked when vhost-user socket connection is closed.
+    It indicates that device with id ``vid`` is no longer in use and can be
+    safely deleted.
+
 * ``rte_vhost_driver_disable/enable_features(path, features))``
 
   This function disables/enables some features. For example, it can be used to
diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h
index 8c974eb..8f86167 100644
--- a/lib/librte_vhost/rte_vhost.h
+++ b/lib/librte_vhost/rte_vhost.h
@@ -107,7 +107,10 @@ struct vhost_device_ops {
 	 */
 	int (*features_changed)(int vid, uint64_t features);
 
-	void *reserved[4]; /**< Reserved for future extension */
+	int (*new_connection)(int vid);		/**< Connect to socket. */
+	void (*destroy_connection)(int vid);	/**< Disconnect from socket */
+
+	void *reserved[2]; /**< Reserved for future extension */
 };
 
 /**
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 41aa3f9..4ab4ff7 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -230,24 +230,36 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 
 	RTE_LOG(INFO, VHOST_CONFIG, "new device, handle is %d\n", vid);
 
+	if (vsocket->notify_ops->new_connection) {
+		ret = vsocket->notify_ops->new_connection(vid);
+		if (ret < 0) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"failed to add vhost user connection with fd %d\n",
+				fd);
+			goto err;
+		}
+	}
+
 	conn->connfd = fd;
 	conn->vsocket = vsocket;
 	conn->vid = vid;
 	ret = fdset_add(&vhost_user.fdset, fd, vhost_user_read_cb,
 			NULL, conn);
 	if (ret < 0) {
-		conn->connfd = -1;
-		free(conn);
-		close(fd);
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"failed to add fd %d into vhost server fdset\n",
 			fd);
-		return;
+		goto err;
 	}
 
 	pthread_mutex_lock(&vsocket->conn_mutex);
 	TAILQ_INSERT_TAIL(&vsocket->conn_list, conn, next);
 	pthread_mutex_unlock(&vsocket->conn_mutex);
+	return;
+
+err:
+	free(conn);
+	close(fd);
 }
 
 /* call back when there is new vhost-user connection from client  */
@@ -277,6 +289,9 @@ vhost_user_read_cb(int connfd, void *dat, int *remove)
 		*remove = 1;
 		vhost_destroy_device(conn->vid);
 
+		if (vsocket->notify_ops->destroy_connection)
+			vsocket->notify_ops->destroy_connection(conn->vid);
+
 		pthread_mutex_lock(&vsocket->conn_mutex);
 		TAILQ_REMOVE(&vsocket->conn_list, conn, next);
 		pthread_mutex_unlock(&vsocket->conn_mutex);
-- 
2.7.4

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC PATCH 0/4] ethdev new offloads API
    @ 2017-08-23  6:39  0% ` Shahaf Shuler
  2017-08-25 10:31  0% ` Jerin Jacob
  2 siblings, 0 replies; 200+ results
From: Shahaf Shuler @ 2017-08-23  6:39 UTC (permalink / raw)
  To: Shahaf Shuler, dev, Thomas Monjalon

Hi,

I would like to get some inputs on the below. 
This is a big (and important) work which I want to include on 17.11. I need to understand the current approach is acceptable before I continue.


Monday, August 7, 2017 1:54 PM, Shahaf Shuler:
> Tx offloads configuration is per queue. Tx offloads are enabled by default,
> and can be disabled using ETH_TXQ_FLAGS_NO* flags.
> This behaviour is not consistent with the Rx side where the Rx offloads
> configuration is per port. Rx offloads are disabled by default and enabled
> according to bit field in rte_eth_rxmode structure.
> 
> Moreover, considering more Tx and Rx offloads will be added over time, the
> cost of managing them all inside the PMD will be tremendous, as the PMD
> will need to check the matching for the entire offload set for each mbuf it
> handles.
> In addition, on the current approach each Rx offload added breaks the ABI
> compatibility as it requires to add entries to existing bit-fields.
> 
> The RFC address above issues by defining a new offloads API.
> With the new API, Tx and Rx offloads configuration is per queue.
> The offloads are disabled by default. Each offload can be enabled or disabled
> using the existing DEV_TX_OFFLOADS_* or DEV_RX_OFFLOADS_* flags.
> Such API will enable to easily add or remove offloads, without breaking the
> ABI compatibility.
> 
> The new API does not have an equivalent for the below Tx flags:
> 
> * ETH_TXQ_FLAGS_NOREFCOUNT
> * ETH_TXQ_FLAGS_NOMULTMEMP
> 
> The reason is that those flags are not to manage offloads, rather some
> guarantee from application on the way it uses mbufs, therefore could not be
> present as part of DEV_TX_OFFLOADS_*.
> Such flags are useful only for benchmarks, and therefore provide a non-
> realistic
> performance for DPDK customers using simple benchmarks for evaluation.
> Leveraging the work being done in this series to clean up those flags.
> 
> In order to provide a smooth transition between the APIs the following
> actions were taken:
> *  The old offloads API is kept for the meanwhile.
> *  New capabilities were added for PMD to advertize it has moved to the
> new
>    offloads API.
> *  Helper function which copy from old to new API and vice versa were
> added to ethdev,
>    enabling the PMD to support only one of the APIs, and the application to
> move to
>    the new API regardless the underlying device and without extra branching.
> 



> Shahaf Shuler (4):
>   ethdev: rename Rx and Tx configuration structs
>   ethdev: introduce Rx queue offloads API
>   ethdev: introduce Tx queue offloads API
>   ethdev: add helpers to move to the new offloads API
> 
>  lib/librte_ether/rte_ethdev.c | 144
> ++++++++++++++++++++++++++++++++++++-
>  lib/librte_ether/rte_ethdev.h |  72 +++++++++++++++----
>  2 files changed, 202 insertions(+), 14 deletions(-)
> 
> --
> 2.12.0

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2 1/2] ethdev: stop overriding rx_nombuf by rte_eth_stats_get
  @ 2017-08-23 12:18  4%     ` David Harton (dharton)
  2017-08-23 13:24  0%       ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: David Harton (dharton) @ 2017-08-23 12:18 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev


> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Wednesday, August 23, 2017 3:52 AM
> To: David Harton (dharton) <dharton@cisco.com>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v2 1/2] ethdev: stop overriding rx_nombuf by
> rte_eth_stats_get
> 
> 23/08/2017 04:55, David Harton:
> > rte_eth_stats_get() unconditonally would set rx_nombuf even if the
> > device was setting the value.  A check has been added in
> > rte_eth_stats_get() to leave the device value in-tact when non-zero.
> 
> If we get this counter from stats->rx_nombuf, why keeping
> dev->data->rx_mbuf_alloc_failed ?
> We could rework other PMDs to not use this global variable.
> It is inconsistent to use it for some PMDs but not all.
> And it seems not used outside of PMDs.

Are you also asking to remove dev->data->rx_mbuf_alloc_failed as well since we will have an ABI breakage anyway?

On an somewhat related note, since we are introducing an ABI breakage how do you feel about re-adding the return code for the vlan_offload_set vector?  Some devices conditionally provide the ability to modify some offload and the caller should know.  Since I've got your attention thought I'd ask here before posting the patch.

<soapbox>
In fact, I believe all the API function calls should provide a return code to help mitigate ABI breakages and also provide the ability to let the caller distinguish between - no device, not supported and some other error.  A control plane often needs to understand these distinctions to properly orchestrate the system and/or report real errors.  This is more than I'm willing to take on myself but believe it's a principle I'd like to discuss (can start separate thread if desired).
</soapbox>

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [RFC PATCH 2/4] ethdev: introduce Rx queue offloads API
  @ 2017-08-23 12:21  0%   ` Ananyev, Konstantin
  2017-08-23 13:06  0%     ` Shahaf Shuler
  2017-08-23 21:48  0%   ` Thomas Monjalon
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 200+ results
From: Ananyev, Konstantin @ 2017-08-23 12:21 UTC (permalink / raw)
  To: Shahaf Shuler, dev

Hi,

> Introduce a new API to configure Rx offloads.
> 
> The new API will re-use existing DEV_RX_OFFLOAD_* flags
> to enable the different offloads. This will ease the process
> of adding a new Rx offloads, as no ABI breakage is involved.
> In addition, the offload configuration can be done per queue,
> instead of per port.
> 
> The Rx queue offload API can be used only with devices which advertize
> the RTE_ETH_DEV_RXQ_OFFLOAD capability.

Not sure why do we need that?
Why (till the deprication) user can't use both old rxmode and new offload flags?
I.E. at rte_ethdev_rx_queue_setup() we always convert rxmode to new offload flags
(as I can see you already have a function for it), then we call dev_ops->rx_queue_setup().
That way both new and old ethdev API should work.
Of course that mean that all PMDs have to support new way to setup rx offloads...
But I suppose that have to be done anyway.
Same for TX path.
Konstantin

> 
> The old Rx offloads API is kept for the meanwhile, in order to enable a
> smooth transition for PMDs and application to the new API.
> 
> Signed-off-by: Shahaf Shuler <shahafs@mellanox.com>
> ---
>  lib/librte_ether/rte_ethdev.h | 30 +++++++++++++++++++++++++++++-
>  1 file changed, 29 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index f7a44578c..ce33c61c4 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -357,7 +357,14 @@ struct rte_eth_rxmode {
>  		jumbo_frame      : 1, /**< Jumbo Frame Receipt enable. */
>  		hw_strip_crc     : 1, /**< Enable CRC stripping by hardware. */
>  		enable_scatter   : 1, /**< Enable scatter packets rx handler */
> -		enable_lro       : 1; /**< Enable LRO */
> +		enable_lro       : 1, /**< Enable LRO */
> +		ignore		 : 1;
> +		/**
> +		 * When set the rxmode offloads should be ignored,
> +		 * instead the Rx offloads will be set on rte_eth_rxq_conf.
> +		 * This bit is temporary till rxmode Rx offloads API will
> +		 * be deprecated.
> +		 */
>  };
> 
>  /**
> @@ -691,6 +698,12 @@ struct rte_eth_rxq_conf {
>  	uint16_t rx_free_thresh; /**< Drives the freeing of RX descriptors. */
>  	uint8_t rx_drop_en; /**< Drop packets if no descriptors are available. */
>  	uint8_t rx_deferred_start; /**< Do not start queue with rte_eth_dev_start(). */
> +	uint64_t offloads;
> +	/**
> +	 * Enable Rx offloads using DEV_RX_OFFLOAD_* flags.
> +	 * Supported only for devices which advertize the
> +	 * RTE_ETH_DEV_RXQ_OFFLOAD capability.
> +	 */
>  };
> 
>  #define ETH_TXQ_FLAGS_NOMULTSEGS 0x0001 /**< nb_segs=1 for all mbufs */
> @@ -907,6 +920,19 @@ struct rte_eth_conf {
>  #define DEV_RX_OFFLOAD_QINQ_STRIP  0x00000020
>  #define DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM 0x00000040
>  #define DEV_RX_OFFLOAD_MACSEC_STRIP     0x00000080
> +#define DEV_RX_OFFLOAD_HEADER_SPLIT	0x00000100
> +#define DEV_RX_OFFLOAD_VLAN_FILTER	0x00000200
> +#define DEV_RX_OFFLOAD_VLAN_EXTEND	0x00000400
> +#define DEV_RX_OFFLOAD_JUMBO_FRAME	0x00000800
> +#define DEV_RX_OFFLOAD_CRC_STRIP	0x00001000
> +#define DEV_RX_OFFLOAD_SCATTER		0x00002000
> +#define DEV_RX_OFFLOAD_LRO		0x00004000
> +#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \
> +				 DEV_RX_OFFLOAD_UDP_CKSUM | \
> +				 DEV_RX_OFFLOAD_TCP_CKSUM)
> +#define DEV_RX_OFFLOAD_VLAN (DEV_RX_OFFLOAD_VLAN_STRIP | \
> +			     DEV_RX_OFFLOAD_VLAN_FILTER | \
> +			     DEV_RX_OFFLOAD_VLAN_EXTEND)
> 
>  /**
>   * TX offload capabilities of a device.
> @@ -1723,6 +1749,8 @@ struct rte_eth_dev_data {
>  #define RTE_ETH_DEV_BONDED_SLAVE 0x0004
>  /** Device supports device removal interrupt */
>  #define RTE_ETH_DEV_INTR_RMV     0x0008
> +/** Device supports the rte_eth_rxq_conf offloads API */
> +#define RTE_ETH_DEV_RXQ_OFFLOAD 0x0010
> 
>  /**
>   * @internal
> --
> 2.12.0

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC PATCH 2/4] ethdev: introduce Rx queue offloads API
  2017-08-23 12:21  0%   ` Ananyev, Konstantin
@ 2017-08-23 13:06  0%     ` Shahaf Shuler
  0 siblings, 0 replies; 200+ results
From: Shahaf Shuler @ 2017-08-23 13:06 UTC (permalink / raw)
  To: Ananyev, Konstantin, dev

Wednesday, August 23, 2017 3:21 PM, Ananyev, Konstantin:
> Hi,
> 
> > Introduce a new API to configure Rx offloads.
> >
> > The new API will re-use existing DEV_RX_OFFLOAD_* flags to enable the
> > different offloads. This will ease the process of adding a new Rx
> > offloads, as no ABI breakage is involved.
> > In addition, the offload configuration can be done per queue, instead
> > of per port.
> >
> > The Rx queue offload API can be used only with devices which advertize
> > the RTE_ETH_DEV_RXQ_OFFLOAD capability.
> 
> Not sure why do we need that?
> Why (till the deprication) user can't use both old rxmode and new offload
> flags?
> I.E. at rte_ethdev_rx_queue_setup() we always convert rxmode to new
> offload flags (as I can see you already have a function for it), then we call
> dev_ops->rx_queue_setup().
> That way both new and old ethdev API should work.
> Of course that mean that all PMDs have to support new way to setup rx
> offloads...
> But I suppose that have to be done anyway.
> Same for TX path.

The reason for this capability is to enable the different PMDs to *gradually move* to the new API.
Offloads management on the PMD is complex, it has to deal with the internal of the device on which they work. For example some devices probably
have offloads configuration they can do only per port.  Another example can be that some PMDs enable Tx offloads from the PMD specific parameters (like mlx5). 

This is why I believe that the task to move the PMD to the new API should be done by the PMD developers/maintainers.
This work provides the means (the copy functions and the capability bits) for both APIs to co-exists and to be used on top of PMDs which support either old or new API.

Once the majority of the PMD made the transition, we can remove and deprecate this cap (and the old API).

> Konstantin
> 
> >
> > The old Rx offloads API is kept for the meanwhile, in order to enable
> > a smooth transition for PMDs and application to the new API.
> >
> > Signed-off-by: Shahaf Shuler <shahafs@mellanox.com>
> > ---
> >  lib/librte_ether/rte_ethdev.h | 30 +++++++++++++++++++++++++++++-
> >  1 file changed, 29 insertions(+), 1 deletion(-)
> >
> > diff --git a/lib/librte_ether/rte_ethdev.h
> > b/lib/librte_ether/rte_ethdev.h index f7a44578c..ce33c61c4 100644
> > --- a/lib/librte_ether/rte_ethdev.h
> > +++ b/lib/librte_ether/rte_ethdev.h
> > @@ -357,7 +357,14 @@ struct rte_eth_rxmode {
> >  		jumbo_frame      : 1, /**< Jumbo Frame Receipt enable. */
> >  		hw_strip_crc     : 1, /**< Enable CRC stripping by hardware. */
> >  		enable_scatter   : 1, /**< Enable scatter packets rx handler */
> > -		enable_lro       : 1; /**< Enable LRO */
> > +		enable_lro       : 1, /**< Enable LRO */
> > +		ignore		 : 1;
> > +		/**
> > +		 * When set the rxmode offloads should be ignored,
> > +		 * instead the Rx offloads will be set on rte_eth_rxq_conf.
> > +		 * This bit is temporary till rxmode Rx offloads API will
> > +		 * be deprecated.
> > +		 */
> >  };
> >
> >  /**
> > @@ -691,6 +698,12 @@ struct rte_eth_rxq_conf {
> >  	uint16_t rx_free_thresh; /**< Drives the freeing of RX descriptors.
> */
> >  	uint8_t rx_drop_en; /**< Drop packets if no descriptors are
> available. */
> >  	uint8_t rx_deferred_start; /**< Do not start queue with
> > rte_eth_dev_start(). */
> > +	uint64_t offloads;
> > +	/**
> > +	 * Enable Rx offloads using DEV_RX_OFFLOAD_* flags.
> > +	 * Supported only for devices which advertize the
> > +	 * RTE_ETH_DEV_RXQ_OFFLOAD capability.
> > +	 */
> >  };
> >
> >  #define ETH_TXQ_FLAGS_NOMULTSEGS 0x0001 /**< nb_segs=1 for all
> mbufs
> > */ @@ -907,6 +920,19 @@ struct rte_eth_conf {  #define
> > DEV_RX_OFFLOAD_QINQ_STRIP  0x00000020  #define
> > DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM 0x00000040
> >  #define DEV_RX_OFFLOAD_MACSEC_STRIP     0x00000080
> > +#define DEV_RX_OFFLOAD_HEADER_SPLIT	0x00000100
> > +#define DEV_RX_OFFLOAD_VLAN_FILTER	0x00000200
> > +#define DEV_RX_OFFLOAD_VLAN_EXTEND	0x00000400
> > +#define DEV_RX_OFFLOAD_JUMBO_FRAME	0x00000800
> > +#define DEV_RX_OFFLOAD_CRC_STRIP	0x00001000
> > +#define DEV_RX_OFFLOAD_SCATTER		0x00002000
> > +#define DEV_RX_OFFLOAD_LRO		0x00004000
> > +#define DEV_RX_OFFLOAD_CHECKSUM
> (DEV_RX_OFFLOAD_IPV4_CKSUM | \
> > +				 DEV_RX_OFFLOAD_UDP_CKSUM | \
> > +				 DEV_RX_OFFLOAD_TCP_CKSUM)
> > +#define DEV_RX_OFFLOAD_VLAN (DEV_RX_OFFLOAD_VLAN_STRIP | \
> > +			     DEV_RX_OFFLOAD_VLAN_FILTER | \
> > +			     DEV_RX_OFFLOAD_VLAN_EXTEND)
> >
> >  /**
> >   * TX offload capabilities of a device.
> > @@ -1723,6 +1749,8 @@ struct rte_eth_dev_data {  #define
> > RTE_ETH_DEV_BONDED_SLAVE 0x0004
> >  /** Device supports device removal interrupt */
> >  #define RTE_ETH_DEV_INTR_RMV     0x0008
> > +/** Device supports the rte_eth_rxq_conf offloads API */ #define
> > +RTE_ETH_DEV_RXQ_OFFLOAD 0x0010
> >
> >  /**
> >   * @internal
> > --
> > 2.12.0

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2 1/2] ethdev: stop overriding rx_nombuf by rte_eth_stats_get
  2017-08-23 12:18  4%     ` David Harton (dharton)
@ 2017-08-23 13:24  0%       ` Thomas Monjalon
  2017-08-23 21:27  0%         ` David Harton (dharton)
  0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2017-08-23 13:24 UTC (permalink / raw)
  To: David Harton (dharton); +Cc: dev

23/08/2017 14:18, David Harton (dharton):
> 
> > -----Original Message-----
> > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > Sent: Wednesday, August 23, 2017 3:52 AM
> > To: David Harton (dharton) <dharton@cisco.com>
> > Cc: dev@dpdk.org
> > Subject: Re: [PATCH v2 1/2] ethdev: stop overriding rx_nombuf by
> > rte_eth_stats_get
> > 
> > 23/08/2017 04:55, David Harton:
> > > rte_eth_stats_get() unconditonally would set rx_nombuf even if the
> > > device was setting the value.  A check has been added in
> > > rte_eth_stats_get() to leave the device value in-tact when non-zero.
> > 
> > If we get this counter from stats->rx_nombuf, why keeping
> > dev->data->rx_mbuf_alloc_failed ?
> > We could rework other PMDs to not use this global variable.
> > It is inconsistent to use it for some PMDs but not all.
> > And it seems not used outside of PMDs.
> 
> Are you also asking to remove dev->data->rx_mbuf_alloc_failed as well since we will have an ABI breakage anyway?

Not asking, just giving my thought :)

> On an somewhat related note, since we are introducing an ABI breakage how do you feel about re-adding the return code for the vlan_offload_set vector?  Some devices conditionally provide the ability to modify some offload and the caller should know.  Since I've got your attention thought I'd ask here before posting the patch.

Seems reasonnable

> <soapbox>
> In fact, I believe all the API function calls should provide a return code to help mitigate ABI breakages and also provide the ability to let the caller distinguish between - no device, not supported and some other error.  A control plane often needs to understand these distinctions to properly orchestrate the system and/or report real errors.  This is more than I'm willing to take on myself but believe it's a principle I'd like to discuss (can start separate thread if desired).
> </soapbox>

Yes you're right

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2 1/2] ethdev: stop overriding rx_nombuf by rte_eth_stats_get
  2017-08-23 13:24  0%       ` Thomas Monjalon
@ 2017-08-23 21:27  0%         ` David Harton (dharton)
  2017-08-23 21:35  0%           ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: David Harton (dharton) @ 2017-08-23 21:27 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev



> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Wednesday, August 23, 2017 9:24 AM
> To: David Harton (dharton) <dharton@cisco.com>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v2 1/2] ethdev: stop overriding rx_nombuf by
> rte_eth_stats_get
> 
> 23/08/2017 14:18, David Harton (dharton):
> >
> > > -----Original Message-----
> > > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > > Sent: Wednesday, August 23, 2017 3:52 AM
> > > To: David Harton (dharton) <dharton@cisco.com>
> > > Cc: dev@dpdk.org
> > > Subject: Re: [PATCH v2 1/2] ethdev: stop overriding rx_nombuf by
> > > rte_eth_stats_get
> > >
> > > 23/08/2017 04:55, David Harton:
> > > > rte_eth_stats_get() unconditonally would set rx_nombuf even if the
> > > > device was setting the value.  A check has been added in
> > > > rte_eth_stats_get() to leave the device value in-tact when non-zero.
> > >
> > > If we get this counter from stats->rx_nombuf, why keeping
> > > dev->data->rx_mbuf_alloc_failed ?
> > > We could rework other PMDs to not use this global variable.
> > > It is inconsistent to use it for some PMDs but not all.
> > > And it seems not used outside of PMDs.
> >
> > Are you also asking to remove dev->data->rx_mbuf_alloc_failed as well
> since we will have an ABI breakage anyway?
> 
> Not asking, just giving my thought :)

I did some more digging.  For this count it looks like some devices:
- have their own internal version
- have a count shared with the pf
- rely on this field to maintain the count
- don't count this failure at all :(

With that said I'd like to keep with the requested changes.

Thoughts?
Dave

> 
> > On an somewhat related note, since we are introducing an ABI breakage
> how do you feel about re-adding the return code for the vlan_offload_set
> vector?  Some devices conditionally provide the ability to modify some
> offload and the caller should know.  Since I've got your attention thought
> I'd ask here before posting the patch.
> 
> Seems reasonnable
> 
> > <soapbox>
> > In fact, I believe all the API function calls should provide a return
> code to help mitigate ABI breakages and also provide the ability to let
> the caller distinguish between - no device, not supported and some other
> error.  A control plane often needs to understand these distinctions to
> properly orchestrate the system and/or report real errors.  This is more
> than I'm willing to take on myself but believe it's a principle I'd like
> to discuss (can start separate thread if desired).
> > </soapbox>
> 
> Yes you're right

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2 1/2] ethdev: stop overriding rx_nombuf by rte_eth_stats_get
  2017-08-23 21:27  0%         ` David Harton (dharton)
@ 2017-08-23 21:35  0%           ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-23 21:35 UTC (permalink / raw)
  To: David Harton (dharton); +Cc: dev

23/08/2017 23:27, David Harton (dharton):
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > 23/08/2017 14:18, David Harton (dharton):
> > > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > > > 23/08/2017 04:55, David Harton:
> > > > > rte_eth_stats_get() unconditonally would set rx_nombuf even if the
> > > > > device was setting the value.  A check has been added in
> > > > > rte_eth_stats_get() to leave the device value in-tact when non-zero.
> > > >
> > > > If we get this counter from stats->rx_nombuf, why keeping
> > > > dev->data->rx_mbuf_alloc_failed ?
> > > > We could rework other PMDs to not use this global variable.
> > > > It is inconsistent to use it for some PMDs but not all.
> > > > And it seems not used outside of PMDs.
> > >
> > > Are you also asking to remove dev->data->rx_mbuf_alloc_failed as well
> > since we will have an ABI breakage anyway?
> > 
> > Not asking, just giving my thought :)
> 
> I did some more digging.  For this count it looks like some devices:
> - have their own internal version
> - have a count shared with the pf
> - rely on this field to maintain the count
> - don't count this failure at all :(
> 
> With that said I'd like to keep with the requested changes.
> 
> Thoughts?

I don't see how it is a problem for removing dev->data->rx_mbuf_alloc_failed.
If this field is used, we just have to replace it by a PMD internal variable.
Isn't it?

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC PATCH 2/4] ethdev: introduce Rx queue offloads API
    2017-08-23 12:21  0%   ` Ananyev, Konstantin
@ 2017-08-23 21:48  0%   ` Thomas Monjalon
  2017-08-29 12:50  0%   ` Ferruh Yigit
  2017-08-29 13:11  0%   ` Ferruh Yigit
  3 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-23 21:48 UTC (permalink / raw)
  To: Shahaf Shuler; +Cc: dev

07/08/2017 12:54, Shahaf Shuler:
> Introduce a new API to configure Rx offloads.
> 
> The new API will re-use existing DEV_RX_OFFLOAD_* flags
> to enable the different offloads. This will ease the process
> of adding a new Rx offloads, as no ABI breakage is involved.
> In addition, the offload configuration can be done per queue,
> instead of per port.
> 
> The Rx queue offload API can be used only with devices which advertize
> the RTE_ETH_DEV_RXQ_OFFLOAD capability.
> 
> The old Rx offloads API is kept for the meanwhile, in order to enable a
> smooth transition for PMDs and application to the new API.
> 
> Signed-off-by: Shahaf Shuler <shahafs@mellanox.com>
[...]
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -357,7 +357,14 @@ struct rte_eth_rxmode {
>  		jumbo_frame      : 1, /**< Jumbo Frame Receipt enable. */
>  		hw_strip_crc     : 1, /**< Enable CRC stripping by hardware. */
>  		enable_scatter   : 1, /**< Enable scatter packets rx handler */
> -		enable_lro       : 1; /**< Enable LRO */
> +		enable_lro       : 1, /**< Enable LRO */
> +		ignore		 : 1;
> +		/**
> +		 * When set the rxmode offloads should be ignored,
> +		 * instead the Rx offloads will be set on rte_eth_rxq_conf.
> +		 * This bit is temporary till rxmode Rx offloads API will
> +		 * be deprecated.
> +		 */

Who is responsible to set the "ignore" flag?

Should it be documented in queue config functions?

> +/** Device supports the rte_eth_rxq_conf offloads API */
> +#define RTE_ETH_DEV_RXQ_OFFLOAD 0x0010

Otherwise, looks good

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH 02/16] nfp: add specific pf probe function
  @ 2017-08-24 16:20 10% ` Alejandro Lucero
  2017-08-28 16:42  0%   ` Ferruh Yigit
  2017-08-24 16:20  6% ` [dpdk-dev] [PATCH 11/16] nfp: allocate eth_dev from " Alejandro Lucero
  1 sibling, 1 reply; 200+ results
From: Alejandro Lucero @ 2017-08-24 16:20 UTC (permalink / raw)
  To: dev

Configuring the NFP PMD for using the PF requires access through the
NSPU interface for device configuration. This patch adds a specific probe
function for the PF which uses the NSPU interface. Just basic NSPU access
is done by now reading the NSPU ABI version.

No ethernet port is created yet.

Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
---
 drivers/net/nfp/nfp_net.c | 75 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 69 insertions(+), 6 deletions(-)

diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index a3bf5e1..e2fe83a 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -59,6 +59,8 @@
 #include "nfp_net_logs.h"
 #include "nfp_net_ctrl.h"
 
+#include "nfp_nfpu.h"
+
 /* Prototypes */
 static void nfp_net_close(struct rte_eth_dev *dev);
 static int nfp_net_configure(struct rte_eth_dev *dev);
@@ -2632,12 +2634,63 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
 	return 0;
 }
 
-static const struct rte_pci_id pci_id_nfp_net_map[] = {
+static int nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+			    struct rte_pci_device *dev)
+{
+	nfpu_desc_t *nfpu_desc;
+	nspu_desc_t *nspu_desc;
+	int major, minor;
+
+	if (!dev)
+		return -ENODEV;
+
+	nfpu_desc = rte_malloc("nfp nfpu", sizeof(nfpu_desc_t), 0);
+	if (!nfpu_desc)
+		return -ENOMEM;
+
+	if (nfpu_open(dev, nfpu_desc, 0) < 0) {
+		RTE_LOG(ERR, PMD,
+			"nfpu_open failed\n");
+		goto nfpu_error;
+	}
+
+	nspu_desc = nfpu_desc->nspu;
+
+
+	/* Check NSP ABI version */
+	if (nfp_nsp_get_abi_version(nspu_desc, &major, &minor) < 0) {
+		RTE_LOG(INFO, PMD, "NFP NSP not present\n");
+		goto no_abi;
+	}
+	PMD_INIT_LOG(INFO, "nspu ABI version: %d.%d\n", major, minor);
+
+	if (minor < 20) {
+		RTE_LOG(INFO, PMD, "NFP NSP ABI version too old. Required 0.20 or higher\n");
+		goto no_abi;
+	}
+
+	/* No port is created yet */
+
+no_abi:
+	nfpu_close(nfpu_desc);
+nfpu_error:
+	rte_free(nfpu_desc);
+
+	return -ENODEV;
+}
+
+static const struct rte_pci_id pci_id_nfp_pf_net_map[] = {
 	{
 		RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
 			       PCI_DEVICE_ID_NFP6000_PF_NIC)
 	},
 	{
+		.vendor_id = 0,
+	},
+};
+
+static const struct rte_pci_id pci_id_nfp_vf_net_map[] = {
+	{
 		RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
 			       PCI_DEVICE_ID_NFP6000_VF_NIC)
 	},
@@ -2658,16 +2711,26 @@ static int eth_nfp_pci_remove(struct rte_pci_device *pci_dev)
 	return rte_eth_dev_pci_generic_remove(pci_dev, NULL);
 }
 
-static struct rte_pci_driver rte_nfp_net_pmd = {
-	.id_table = pci_id_nfp_net_map,
+static struct rte_pci_driver rte_nfp_net_pf_pmd = {
+	.id_table = pci_id_nfp_pf_net_map,
+	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
+	.probe = nfp_pf_pci_probe,
+	.remove = eth_nfp_pci_remove,
+};
+
+static struct rte_pci_driver rte_nfp_net_vf_pmd = {
+	.id_table = pci_id_nfp_vf_net_map,
 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 	.probe = eth_nfp_pci_probe,
 	.remove = eth_nfp_pci_remove,
 };
 
-RTE_PMD_REGISTER_PCI(net_nfp, rte_nfp_net_pmd);
-RTE_PMD_REGISTER_PCI_TABLE(net_nfp, pci_id_nfp_net_map);
-RTE_PMD_REGISTER_KMOD_DEP(net_nfp, "* igb_uio | uio_pci_generic | vfio-pci");
+RTE_PMD_REGISTER_PCI(net_nfp_pf, rte_nfp_net_pf_pmd);
+RTE_PMD_REGISTER_PCI(net_nfp_vf, rte_nfp_net_vf_pmd);
+RTE_PMD_REGISTER_PCI_TABLE(net_nfp_pf, pci_id_nfp_pf_net_map);
+RTE_PMD_REGISTER_PCI_TABLE(net_nfp_vf, pci_id_nfp_vf_net_map);
+RTE_PMD_REGISTER_KMOD_DEP(net_nfp_pf, "* igb_uio | uio_pci_generic | vfio");
+RTE_PMD_REGISTER_KMOD_DEP(net_nfp_vf, "* igb_uio | uio_pci_generic | vfio");
 
 /*
  * Local variables:
-- 
1.9.1

^ permalink raw reply	[relevance 10%]

* [dpdk-dev] [PATCH 11/16] nfp: allocate eth_dev from pf probe function
    2017-08-24 16:20 10% ` [dpdk-dev] [PATCH 02/16] nfp: add specific pf probe function Alejandro Lucero
@ 2017-08-24 16:20  6% ` Alejandro Lucero
  1 sibling, 0 replies; 200+ results
From: Alejandro Lucero @ 2017-08-24 16:20 UTC (permalink / raw)
  To: dev

NFP can support several physical ports per PF device. Depending on
firmware info, one or more eth_dev objects will need to be created.

This patch adds the call to create just one eth_dev by now with future
commits supporting the multiport option. Once the eth_dev has been
created, probe function invokes pmd initialization with the new eth_dev.

Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
---
 drivers/net/nfp/nfp_net.c | 50 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 42 insertions(+), 8 deletions(-)

diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index 7c23b7a..6005e41 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -2677,13 +2677,16 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
 static int nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 			    struct rte_pci_device *dev)
 {
+	struct rte_eth_dev *eth_dev;
+	struct nfp_net_hw *hw;
 	nfpu_desc_t *nfpu_desc;
 	nspu_desc_t *nspu_desc;
 	uint64_t offset_symbol;
 	int major, minor;
+	int ret = -ENODEV;
 
 	if (!dev)
-		return -ENODEV;
+		return ret;
 
 	nfpu_desc = rte_malloc("nfp nfpu", sizeof(nfpu_desc_t), 0);
 	if (!nfpu_desc)
@@ -2697,29 +2700,60 @@ static int nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 
 	nspu_desc = nfpu_desc->nspu;
 
-
 	/* Check NSP ABI version */
 	if (nfp_nsp_get_abi_version(nspu_desc, &major, &minor) < 0) {
 		RTE_LOG(INFO, PMD, "NFP NSP not present\n");
-		goto no_abi;
+		goto error;
 	}
 	PMD_INIT_LOG(INFO, "nspu ABI version: %d.%d\n", major, minor);
 
 	if (minor < 20) {
 		RTE_LOG(INFO, PMD, "NFP NSP ABI version too old. Required 0.20 or higher\n");
-		goto no_abi;
+		goto error;
 	}
 
-	nfp_nsp_fw_setup(nspu_desc, "nfd_cfg_pf0_num_ports", &offset_symbol);
+	ret = nfp_nsp_fw_setup(nspu_desc, "nfd_cfg_pf0_num_ports",
+			       &offset_symbol);
+	if (ret)
+		goto error;
 
-	/* No port is created yet */
+	eth_dev = rte_eth_dev_allocate(dev->device.name);
+	if (!eth_dev) {
+		ret = -ENODEV;
+		goto error;
+	}
 
-no_abi:
+	eth_dev->data->dev_private = rte_zmalloc("nfp_pf_port",
+						 sizeof(struct nfp_net_adapter),
+						 RTE_CACHE_LINE_SIZE);
+	if (!eth_dev->data->dev_private) {
+		rte_eth_dev_release_port(eth_dev);
+		ret = -ENODEV;
+		goto error;
+	}
+
+	hw = (struct nfp_net_hw *)(eth_dev->data->dev_private);
+	hw->nspu_desc = nspu_desc;
+	hw->nfpu_desc = nfpu_desc;
+	hw->is_pf = 1;
+
+	eth_dev->device = &dev->device;
+	rte_eth_copy_pci_info(eth_dev, dev);
+
+	ret = nfp_net_init(eth_dev);
+
+	if (!ret)
+		return 0;
+
+	/* something went wrong */
+	rte_eth_dev_release_port(eth_dev);
+
+error:
 	nfpu_close(nfpu_desc);
 nfpu_error:
 	rte_free(nfpu_desc);
 
-	return -ENODEV;
+	return ret;
 }
 
 static const struct rte_pci_id pci_id_nfp_pf_net_map[] = {
-- 
1.9.1

^ permalink raw reply	[relevance 6%]

* [dpdk-dev] [PATCH] ethdev: modifiy vlan_offload_set_t to return int
@ 2017-08-24 23:18  4% David Harton
  2017-08-25 13:33  4% ` [dpdk-dev] [PATCH v2] " David Harton
  0 siblings, 1 reply; 200+ results
From: David Harton @ 2017-08-24 23:18 UTC (permalink / raw)
  To: thomas, ferruh.yigit, stephen.hurd, ajit.khaparde, johndale,
	wenzhuo.lu, konstantin.ananyev, jingjing.wu, beilei.xing,
	jing.d.chen, adrien.mazarguil, nelio.laranjeiro,
	alejandro.lucero, hemant.agrawal, rasesh.mody, harish.patil,
	skhare, yliu, maxime.coquelin, allain.legacy
  Cc: dev, David Harton

Some devices may not support or fail setting VLAN offload
configuration based on dynamic circurmstances so the
vlan_offload_set_t vector is modified to return an int so
the caller can determine success or not.

rte_eth_dev_set_vlan_offload is updated to return the
value provided by the vector when called along with restoring
the original offload configs on failure.

Existing vlan_offload_set_t vectors are modified to return
an int.  Majority of cases return 0 but a few that actually
can fail now return their failure codes.

Finally, a vlan_offload_set_t vector is added to virtio
to facilitate dynamically turning VLAN strip on or off.

This is an ABI breakage that has been previously negotiated
with Thomas and the proposed rel note change is included as well.

Signed-off-by: David Harton <dharton@cisco.com>
---
 doc/guides/rel_notes/release_17_11.rst |  2 +-
 drivers/net/avp/avp_ethdev.c           |  7 ++++---
 drivers/net/bnxt/bnxt_ethdev.c         |  9 ++++++---
 drivers/net/dpaa2/dpaa2_ethdev.c       | 13 ++++++++++---
 drivers/net/e1000/em_ethdev.c          | 12 +++++++++---
 drivers/net/e1000/igb_ethdev.c         | 12 +++++++++---
 drivers/net/enic/enic_ethdev.c         |  8 +++++---
 drivers/net/fm10k/fm10k_ethdev.c       |  3 ++-
 drivers/net/i40e/i40e_ethdev.c         | 11 ++++++++---
 drivers/net/i40e/i40e_ethdev_vf.c      |  9 ++++++---
 drivers/net/ixgbe/ixgbe_ethdev.c       | 14 ++++++++------
 drivers/net/mlx5/mlx5.h                |  2 +-
 drivers/net/mlx5/mlx5_vlan.c           |  3 ++-
 drivers/net/nfp/nfp_net.c              | 13 +++++++------
 drivers/net/qede/qede_ethdev.c         |  6 ++++--
 drivers/net/virtio/virtio_ethdev.c     | 21 +++++++++++++++++++++
 drivers/net/vmxnet3/vmxnet3_ethdev.c   |  8 +++++---
 lib/librte_ether/rte_ethdev.c          | 14 +++++++++++++-
 lib/librte_ether/rte_ethdev.h          |  2 +-
 19 files changed, 122 insertions(+), 47 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f9..e74f70c 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -124,7 +124,7 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
-
+* Changed return type of ``vlan_offload_set_t`` from ``void`` to ``int``.
 
 Shared Library Versions
 -----------------------
diff --git a/drivers/net/avp/avp_ethdev.c b/drivers/net/avp/avp_ethdev.c
index c746a0e..3525e8f 100644
--- a/drivers/net/avp/avp_ethdev.c
+++ b/drivers/net/avp/avp_ethdev.c
@@ -70,7 +70,7 @@ static int avp_dev_create(struct rte_pci_device *pci_dev,
 static void avp_dev_close(struct rte_eth_dev *dev);
 static void avp_dev_info_get(struct rte_eth_dev *dev,
 			     struct rte_eth_dev_info *dev_info);
-static void avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static int avp_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete);
 static void avp_dev_promiscuous_enable(struct rte_eth_dev *dev);
 static void avp_dev_promiscuous_disable(struct rte_eth_dev *dev);
@@ -2031,7 +2031,7 @@ struct avp_queue {
 	mask = (ETH_VLAN_STRIP_MASK |
 		ETH_VLAN_FILTER_MASK |
 		ETH_VLAN_EXTEND_MASK);
-	avp_vlan_offload_set(eth_dev, mask);
+	(void)avp_vlan_offload_set(eth_dev, mask);
 
 	/* update device config */
 	memset(&config, 0, sizeof(config));
@@ -2214,7 +2214,7 @@ struct avp_queue {
 	}
 }
 
-static void
+static int
 avp_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 {
 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
@@ -2239,6 +2239,7 @@ struct avp_queue {
 		if (eth_dev->data->dev_conf.rxmode.hw_vlan_extend)
 			PMD_DRV_LOG(ERR, "VLAN extend offload not supported\n");
 	}
+	return 0;
 }
 
 static void
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index c9d1122..547bd55 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -144,7 +144,7 @@
 	ETH_RSS_NONFRAG_IPV6_TCP |	\
 	ETH_RSS_NONFRAG_IPV6_UDP)
 
-static void bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask);
+static int bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask);
 
 /***********************/
 
@@ -522,7 +522,9 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 		vlan_mask |= ETH_VLAN_FILTER_MASK;
 	if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip)
 		vlan_mask |= ETH_VLAN_STRIP_MASK;
-	bnxt_vlan_offload_set_op(eth_dev, vlan_mask);
+	rc = bnxt_vlan_offload_set_op(eth_dev, vlan_mask);
+	if (rc)
+		goto error;
 
 	return 0;
 
@@ -1275,7 +1277,7 @@ static int bnxt_vlan_filter_set_op(struct rte_eth_dev *eth_dev,
 		return bnxt_del_vlan_filter(bp, vlan_id);
 }
 
-static void
+static int
 bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask)
 {
 	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
@@ -1307,6 +1309,7 @@ static int bnxt_vlan_filter_set_op(struct rte_eth_dev *eth_dev,
 
 	if (mask & ETH_VLAN_EXTEND_MASK)
 		RTE_LOG(ERR, PMD, "Extend VLAN Not supported\n");
+	return 0;
 }
 
 static void
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 429b3a0..3390cb3 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -138,7 +138,7 @@
 	return ret;
 }
 
-static void
+static int
 dpaa2_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
@@ -158,6 +158,7 @@
 			RTE_LOG(ERR, PMD, "Unable to set vlan filter = %d\n",
 				ret);
 	}
+	return 0;
 }
 
 static int
@@ -643,8 +644,14 @@
 		return ret;
 	}
 	/* VLAN Offload Settings */
-	if (priv->max_vlan_filters)
-		dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
+	if (priv->max_vlan_filters) {
+		ret = dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Error to dpaa2_vlan_offload_set:"
+				     "code = %d\n", ret);
+			return ret;
+		}
+	}
 
 	return 0;
 }
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 3d4ab93..51f49d8 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -99,7 +99,7 @@ static int eth_em_interrupt_action(struct rte_eth_dev *dev,
 
 static int eth_em_vlan_filter_set(struct rte_eth_dev *dev,
 		uint16_t vlan_id, int on);
-static void eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void em_vlan_hw_filter_enable(struct rte_eth_dev *dev);
 static void em_vlan_hw_filter_disable(struct rte_eth_dev *dev);
 static void em_vlan_hw_strip_enable(struct rte_eth_dev *dev);
@@ -668,7 +668,12 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
 
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
 			ETH_VLAN_EXTEND_MASK;
-	eth_em_vlan_offload_set(dev, mask);
+	ret = eth_em_vlan_offload_set(dev, mask);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Unable to update vlan offload");
+		em_dev_clear_queues(dev);
+		return ret;
+	}
 
 	/* Set Interrupt Throttling Rate to maximum allowed value. */
 	E1000_WRITE_REG(hw, E1000_ITR, UINT16_MAX);
@@ -1447,7 +1452,7 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
 	E1000_WRITE_REG(hw, E1000_CTRL, reg);
 }
 
-static void
+static int
 eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if(mask & ETH_VLAN_STRIP_MASK){
@@ -1463,6 +1468,7 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
 		else
 			em_vlan_hw_filter_disable(dev);
 	}
+	return 0;
 }
 
 /*
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index e4f7a9f..fa15ee9 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -157,7 +157,7 @@ static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev,
 static int eth_igb_vlan_tpid_set(struct rte_eth_dev *dev,
 				 enum rte_vlan_type vlan_type,
 				 uint16_t tpid_id);
-static void eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 
 static void igb_vlan_hw_filter_enable(struct rte_eth_dev *dev);
 static void igb_vlan_hw_filter_disable(struct rte_eth_dev *dev);
@@ -1400,7 +1400,12 @@ static int eth_igbvf_pci_remove(struct rte_pci_device *pci_dev)
 	 */
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
 			ETH_VLAN_EXTEND_MASK;
-	eth_igb_vlan_offload_set(dev, mask);
+	ret = eth_igb_vlan_offload_set(dev, mask);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Unable to set vlan offload");
+		igb_dev_clear_queues(dev);
+		return ret;
+	}
 
 	if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) {
 		/* Enable VLAN filter since VMDq always use VLAN filter */
@@ -2715,7 +2720,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 						2 * VLAN_TAG_SIZE);
 }
 
-static void
+static int
 eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if(mask & ETH_VLAN_STRIP_MASK){
@@ -2738,6 +2743,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		else
 			igb_vlan_hw_extend_disable(dev);
 	}
+	return 0;
 }
 
 
diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
index da8fec2..fc1eac2 100644
--- a/drivers/net/enic/enic_ethdev.c
+++ b/drivers/net/enic/enic_ethdev.c
@@ -347,7 +347,7 @@ static int enicpmd_vlan_filter_set(struct rte_eth_dev *eth_dev,
 	return err;
 }
 
-static void enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
+static int enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 {
 	struct enic *enic = pmd_priv(eth_dev);
 
@@ -371,6 +371,8 @@ static void enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 		dev_warning(enic,
 			"Configuration of extended VLAN is not supported\n");
 	}
+
+	return 0;
 }
 
 static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev)
@@ -392,9 +394,9 @@ static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev)
 			eth_dev->data->dev_conf.rxmode.split_hdr_size);
 	}
 
-	enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
+	ret = enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
 	enic->hw_ip_checksum = eth_dev->data->dev_conf.rxmode.hw_ip_checksum;
-	return 0;
+	return ret;
 }
 
 /* Start the device.
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index e60d3a3..f4626f7 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1590,7 +1590,7 @@ static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	return 0;
 }
 
-static void
+static int
 fm10k_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if (mask & ETH_VLAN_STRIP_MASK) {
@@ -1609,6 +1609,7 @@ static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		if (!dev->data->dev_conf.rxmode.hw_vlan_filter)
 			PMD_INIT_LOG(ERR, "VLAN filter is always on in fm10k");
 	}
+	return 0;
 }
 
 /* Add/Remove a MAC address, and update filters to main VSI */
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 00b6082..d03a44b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -278,7 +278,7 @@ static int i40e_vlan_filter_set(struct rte_eth_dev *dev,
 static int i40e_vlan_tpid_set(struct rte_eth_dev *dev,
 			      enum rte_vlan_type vlan_type,
 			      uint16_t tpid);
-static void i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void i40e_vlan_strip_queue_set(struct rte_eth_dev *dev,
 				      uint16_t queue,
 				      int on);
@@ -3130,7 +3130,7 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	return ret;
 }
 
-static void
+static int
 i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
@@ -3163,6 +3163,7 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		else
 			i40e_vsi_config_double_vlan(vsi, FALSE);
 	}
+	return 0;
 }
 
 static void
@@ -5216,7 +5217,11 @@ struct i40e_vsi *
 
 	/* Apply vlan offload setting */
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK;
-	i40e_vlan_offload_set(dev, mask);
+	ret = i40e_vlan_offload_set(dev, mask);
+	if (ret) {
+		PMD_DRV_LOG(INFO, "Failed to update vlan offload");
+		return ret;
+	}
 
 	/* Apply double-vlan setting, not implemented yet */
 
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index f6d8293..f7fffc2 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -118,7 +118,7 @@ static int i40evf_dev_xstats_get_names(struct rte_eth_dev *dev,
 static void i40evf_dev_xstats_reset(struct rte_eth_dev *dev);
 static int i40evf_vlan_filter_set(struct rte_eth_dev *dev,
 				  uint16_t vlan_id, int on);
-static void i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static int i40evf_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t pvid,
 				int on);
 static void i40evf_dev_close(struct rte_eth_dev *dev);
@@ -1634,7 +1634,9 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
 	int ret;
 
 	/* Apply vlan offload setting */
-	i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
+	ret = i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
+	if (ret)
+		return ret;
 
 	/* Apply pvid setting */
 	ret = i40evf_vlan_pvid_set(dev, data->dev_conf.txmode.pvid,
@@ -1642,7 +1644,7 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
 	return ret;
 }
 
-static void
+static int
 i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
@@ -1655,6 +1657,7 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
 		else
 			i40evf_disable_vlan_strip(dev);
 	}
+	return 0;
 }
 
 static int
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 22171d8..043a713 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -218,7 +218,7 @@ static void ixgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev,
 		uint16_t queue, bool on);
 static void ixgbe_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue,
 		int on);
-static void ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void ixgbe_vlan_hw_strip_enable(struct rte_eth_dev *dev, uint16_t queue);
 static void ixgbe_vlan_hw_strip_disable(struct rte_eth_dev *dev, uint16_t queue);
 static void ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev);
@@ -274,7 +274,7 @@ static int ixgbevf_vlan_filter_set(struct rte_eth_dev *dev,
 		uint16_t vlan_id, int on);
 static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev,
 		uint16_t queue, int on);
-static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on);
 static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
 					    uint16_t queue_id);
@@ -2125,7 +2125,7 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 	 */
 }
 
-static void
+static int
 ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if (mask & ETH_VLAN_STRIP_MASK) {
@@ -2148,6 +2148,7 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 		else
 			ixgbe_vlan_hw_extend_disable(dev);
 	}
+	return 0;
 }
 
 static void
@@ -2570,7 +2571,7 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 
     mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
 		ETH_VLAN_EXTEND_MASK;
-	ixgbe_vlan_offload_set(dev, mask);
+	(void)ixgbe_vlan_offload_set(dev, mask);
 
 	if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) {
 		/* Enable vlan filtering for VMDq */
@@ -4993,7 +4994,7 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	/* Set HW strip */
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
 		ETH_VLAN_EXTEND_MASK;
-	ixgbevf_vlan_offload_set(dev, mask);
+	(void)ixgbevf_vlan_offload_set(dev, mask);
 
 	ixgbevf_dev_rxtx_start(dev);
 
@@ -5153,7 +5154,7 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
 	ixgbe_vlan_hw_strip_bitmap_set(dev, queue, on);
 }
 
-static void
+static int
 ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct ixgbe_hw *hw =
@@ -5168,6 +5169,7 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
 		for (i = 0; i < hw->mac.max_rx_queues; i++)
 			ixgbevf_vlan_strip_queue_set(dev, i, on);
 	}
+	return 0;
 }
 
 int
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 43c5384..93e71be 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -283,7 +283,7 @@ int mlx5_xstats_get_names(struct rte_eth_dev *,
 /* mlx5_vlan.c */
 
 int mlx5_vlan_filter_set(struct rte_eth_dev *, uint16_t, int);
-void mlx5_vlan_offload_set(struct rte_eth_dev *, int);
+int mlx5_vlan_offload_set(struct rte_eth_dev *, int);
 void mlx5_vlan_strip_queue_set(struct rte_eth_dev *, uint16_t, int);
 
 /* mlx5_trigger.c */
diff --git a/drivers/net/mlx5/mlx5_vlan.c b/drivers/net/mlx5/mlx5_vlan.c
index 1b0fa40..7215909 100644
--- a/drivers/net/mlx5/mlx5_vlan.c
+++ b/drivers/net/mlx5/mlx5_vlan.c
@@ -210,7 +210,7 @@
  * @param mask
  *   VLAN offload bit mask.
  */
-void
+int
 mlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct priv *priv = dev->data->dev_private;
@@ -230,4 +230,5 @@
 			priv_vlan_strip_queue_set(priv, i, hw_vlan_strip);
 		priv_unlock(priv);
 	}
+	return 0;
 }
diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index 92b03c4..6473edc 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -2149,11 +2149,12 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
 	return i;
 }
 
-static void
+static int
 nfp_net_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	uint32_t new_ctrl, update;
 	struct nfp_net_hw *hw;
+	int ret;
 
 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	new_ctrl = 0;
@@ -2174,14 +2175,14 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
 		new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_RXVLAN;
 
 	if (new_ctrl == 0)
-		return;
+		return 0;
 
 	update = NFP_NET_CFG_UPDATE_GEN;
 
-	if (nfp_net_reconfig(hw, new_ctrl, update) < 0)
-		return;
-
-	hw->ctrl = new_ctrl;
+	ret = nfp_net_reconfig(hw, new_ctrl, update);
+	if (!ret)
+		hw->ctrl = new_ctrl;
+	return ret;
 }
 
 /* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device */
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 0e05989..ee29754 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -975,7 +975,7 @@ static int qede_vlan_filter_set(struct rte_eth_dev *eth_dev,
 	return rc;
 }
 
-static void qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
+static int qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 {
 	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
 	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
@@ -1013,6 +1013,8 @@ static void qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 
 	DP_INFO(edev, "vlan offload mask %d vlan-strip %d vlan-filter %d\n",
 		mask, rxmode->hw_vlan_strip, rxmode->hw_vlan_filter);
+
+	return 0;
 }
 
 static void qede_prandom_bytes(uint32_t *buff)
@@ -1237,7 +1239,7 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
 	qdev->enable_lro = rxmode->enable_lro;
 
 	/* Enable VLAN offloads by default */
-	qede_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK  |
+	(void)qede_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK  |
 			ETH_VLAN_FILTER_MASK |
 			ETH_VLAN_EXTEND_MASK);
 
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index e320811..fba92f4 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -72,6 +72,7 @@ static void virtio_dev_info_get(struct rte_eth_dev *dev,
 				struct rte_eth_dev_info *dev_info);
 static int virtio_dev_link_update(struct rte_eth_dev *dev,
 	int wait_to_complete);
+static int virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 
 static void virtio_set_hwaddr(struct virtio_hw *hw);
 static void virtio_get_hwaddr(struct virtio_hw *hw);
@@ -779,6 +780,7 @@ struct rte_virtio_xstats_name_off {
 	.stats_reset             = virtio_dev_stats_reset,
 	.xstats_reset            = virtio_dev_stats_reset,
 	.link_update             = virtio_dev_link_update,
+	.vlan_offload_set        = virtio_dev_vlan_offload_set,
 	.rx_queue_setup          = virtio_dev_rx_queue_setup,
 	.rx_queue_intr_enable    = virtio_dev_rx_queue_intr_enable,
 	.rx_queue_intr_disable   = virtio_dev_rx_queue_intr_disable,
@@ -1875,6 +1877,25 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev)
 	return (old.link_status == link.link_status) ? -1 : 0;
 }
 
+static int
+virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
+{
+	const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
+	struct virtio_hw *hw = dev->data->dev_private;
+
+	if (rxmode->hw_vlan_filter
+	    && !vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) {
+		PMD_DRV_LOG(NOTICE,
+			    "vlan filtering not available on this host");
+		return -ENOTSUP;
+	}
+
+	if (mask & ETH_VLAN_STRIP_MASK)
+		hw->vlan_strip = rxmode->hw_vlan_strip;
+
+	return 0;
+}
+
 static void
 virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 3910991..81ee262 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -100,7 +100,7 @@ static void vmxnet3_dev_info_get(struct rte_eth_dev *dev,
 vmxnet3_dev_supported_ptypes_get(struct rte_eth_dev *dev);
 static int vmxnet3_dev_vlan_filter_set(struct rte_eth_dev *dev,
 				       uint16_t vid, int on);
-static void vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void vmxnet3_mac_addr_set(struct rte_eth_dev *dev,
 				 struct ether_addr *mac_addr);
 static void vmxnet3_interrupt_handler(void *param);
@@ -730,7 +730,7 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
 		devRead->rssConfDesc.confPA  = hw->rss_confPA;
 	}
 
-	vmxnet3_dev_vlan_offload_set(dev,
+	(void)vmxnet3_dev_vlan_offload_set(dev,
 				     ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK);
 
 	vmxnet3_write_mac(hw, dev->data->mac_addrs->addr_bytes);
@@ -1275,7 +1275,7 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
 	return 0;
 }
 
-static void
+static int
 vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct vmxnet3_hw *hw = dev->data->dev_private;
@@ -1301,6 +1301,8 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
 		VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
 				       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
 	}
+
+	return 0;
 }
 
 static void
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 0597641..f13f813 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2049,10 +2049,16 @@ struct rte_eth_dev *
 	int ret = 0;
 	int mask = 0;
 	int cur, org = 0;
+	uint8_t org_strip, org_filter, org_extend;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
 	dev = &rte_eth_devices[port_id];
 
+	/* save original values in case of failure */
+	org_strip = dev->data->dev_conf.rxmode.hw_vlan_strip;
+	org_filter = dev->data->dev_conf.rxmode.hw_vlan_filter;
+	org_extend = dev->data->dev_conf.rxmode.hw_vlan_extend;
+
 	/*check which option changed by application*/
 	cur = !!(offload_mask & ETH_VLAN_STRIP_OFFLOAD);
 	org = !!(dev->data->dev_conf.rxmode.hw_vlan_strip);
@@ -2080,7 +2086,13 @@ struct rte_eth_dev *
 		return ret;
 
 	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_offload_set, -ENOTSUP);
-	(*dev->dev_ops->vlan_offload_set)(dev, mask);
+	ret = (*dev->dev_ops->vlan_offload_set)(dev, mask);
+	if (ret) {
+		/* hit an error restore  original values */
+		dev->data->dev_conf.rxmode.hw_vlan_strip = org_strip;
+		dev->data->dev_conf.rxmode.hw_vlan_filter = org_filter;
+		dev->data->dev_conf.rxmode.hw_vlan_extend = org_extend;
+        }
 
 	return ret;
 }
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 0adf327..7254fd0 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1245,7 +1245,7 @@ typedef int (*vlan_tpid_set_t)(struct rte_eth_dev *dev,
 			       enum rte_vlan_type type, uint16_t tpid);
 /**< @internal set the outer/inner VLAN-TPID by an Ethernet device. */
 
-typedef void (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask);
+typedef int (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask);
 /**< @internal set VLAN offload function by an Ethernet device. */
 
 typedef int (*vlan_pvid_set_t)(struct rte_eth_dev *dev,
-- 
1.8.3.1

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v2] vhost: added user callbacks for socket open/close
  2017-08-22 16:24  3% ` [dpdk-dev] [PATCH v2] " Dariusz Stojaczyk
@ 2017-08-25  9:22  0%   ` Jens Freimann
  2017-08-29  6:08  3%     ` Stojaczyk, DariuszX
  2017-08-30 10:50  3%   ` [dpdk-dev] [PATCH v3] rte_vhost: " Dariusz Stojaczyk
  1 sibling, 1 reply; 200+ results
From: Jens Freimann @ 2017-08-25  9:22 UTC (permalink / raw)
  To: Dariusz Stojaczyk; +Cc: dev, Pawel Wodkowski, maxime.coquelin, yliu


Hi Dariusz,

On Tue, Aug 22, 2017 at 06:24:52PM +0200, Dariusz Stojaczyk wrote:
>When user receives destroy_device signal, he does not know *why* that
>event happened. He does not differ between socket shutdown and virtio
>processing pause. User could completely delete device during transition
>from BIOS to kernel, causing freeze or possibly kernel panic. Instead
>of changing new_device/destroy_device callbacks and breaking the ABI,
>a set of new functions new_connection/destroy_connection has been added.
>
>Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
>---
>v2: also updated vhost_lib.rst
> doc/guides/prog_guide/vhost_lib.rst | 15 +++++++++++++--
> lib/librte_vhost/rte_vhost.h        |  5 ++++-
> lib/librte_vhost/socket.c           | 23 +++++++++++++++++++----
> 3 files changed, 36 insertions(+), 7 deletions(-)

thanks for adding documentation!

I'm still not sure I understand the use case. So just for my
understanding: users need to distinct between "the device is going
away temporarily, keep the connection" and "we're shutting down for good", is that it?
Maybe it's just me or maybe it means you could explain your example in
the commit message a bit more.  I think the code looks sane, so 

Reviewed-by: Jens Freimann <jfreimann@redhat.com> 

Oh, and you should put the maintainers on Cc to get a faster review. 

regards,
Jens 

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC PATCH 0/4] ethdev new offloads API
      2017-08-23  6:39  0% ` [dpdk-dev] [RFC PATCH 0/4] ethdev new " Shahaf Shuler
@ 2017-08-25 10:31  0% ` Jerin Jacob
  2 siblings, 0 replies; 200+ results
From: Jerin Jacob @ 2017-08-25 10:31 UTC (permalink / raw)
  To: Shahaf Shuler; +Cc: dev

-----Original Message-----
> Date: Mon,  7 Aug 2017 13:54:27 +0300
> From: Shahaf Shuler <shahafs@mellanox.com>
> To: dev@dpdk.org
> Subject: [dpdk-dev] [RFC PATCH 0/4] ethdev new offloads API
> X-Mailer: git-send-email 2.12.0
> 
> Tx offloads configuration is per queue. Tx offloads are enabled by default, 
> and can be disabled using ETH_TXQ_FLAGS_NO* flags. 
> This behaviour is not consistent with the Rx side where the Rx offloads
> configuration is per port. Rx offloads are disabled by default and enabled 
> according to bit field in rte_eth_rxmode structure.
> 
> Moreover, considering more Tx and Rx offloads will be added 
> over time, the cost of managing them all inside the PMD will be tremendous,
> as the PMD will need to check the matching for the entire offload set 
> for each mbuf it handles.
> In addition, on the current approach each Rx offload added breaks the
> ABI compatibility as it requires to add entries to existing bit-fields.
>  
> The RFC address above issues by defining a new offloads API.
> With the new API, Tx and Rx offloads configuration is per queue.
> The offloads are disabled by default. Each offload can be enabled or
> disabled using the existing DEV_TX_OFFLOADS_* or DEV_RX_OFFLOADS_* flags.
> Such API will enable to easily add or remove offloads, without breaking the
> ABI compatibility.
> 
> The new API does not have an equivalent for the below Tx flags:
> 
> * ETH_TXQ_FLAGS_NOREFCOUNT
> * ETH_TXQ_FLAGS_NOMULTMEMP

IMO, it make sense to keep those flags as PMD optimization if an application
does not need reference count and multi mempool in the application.
As example, An non trivial application like l3fwd does not need both of them.

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v2] ethdev: modifiy vlan_offload_set_t to return int
  2017-08-24 23:18  4% [dpdk-dev] [PATCH] ethdev: modifiy vlan_offload_set_t to return int David Harton
@ 2017-08-25 13:33  4% ` David Harton
  2017-08-25 13:47  4%   ` [dpdk-dev] [PATCH v3] " David Harton
  0 siblings, 1 reply; 200+ results
From: David Harton @ 2017-08-25 13:33 UTC (permalink / raw)
  To: thomas, ferruh.yigit, stephen.hurd, ajit.khaparde, johndale,
	konstantin.ananyev, jingjing.wu, beilei.xing, jing.d.chen,
	adrien.mazarguil, nelio.laranjeiro, alejandro.lucero,
	hemant.agrawal, rasesh.mody, harish.patil, skhare, yliu,
	maxime.coquelin, allain.legacy
  Cc: dev, David Harton

Some devices may not support or fail setting VLAN offload
configuration based on dynamic circurmstances so the
vlan_offload_set_t vector is modified to return an int so
the caller can determine success or not.

rte_eth_dev_set_vlan_offload is updated to return the
value provided by the vector when called along with restoring
the original offload configs on failure.

Existing vlan_offload_set_t vectors are modified to return
an int.  Majority of cases return 0 but a few that actually
can fail now return their failure codes.

Finally, a vlan_offload_set_t vector is added to virtio
to facilitate dynamically turning VLAN strip on or off.

Signed-off-by: David Harton <dharton@cisco.com>
---

*v2
Fixed a missed format error.
Removed vlan offload vector call casts and replaced with checks 
for return values.

*v1
This is an ABI breakage that has been previously negotiated
with Thomas and the proposed rel note change is included as well.

 doc/guides/rel_notes/release_17_11.rst |  2 +-
 drivers/net/avp/avp_ethdev.c           | 12 +++++++++---
 drivers/net/bnxt/bnxt_ethdev.c         |  9 ++++++---
 drivers/net/dpaa2/dpaa2_ethdev.c       | 13 ++++++++++---
 drivers/net/e1000/em_ethdev.c          | 12 +++++++++---
 drivers/net/e1000/igb_ethdev.c         | 12 +++++++++---
 drivers/net/enic/enic_ethdev.c         |  8 +++++---
 drivers/net/fm10k/fm10k_ethdev.c       |  3 ++-
 drivers/net/i40e/i40e_ethdev.c         | 11 ++++++++---
 drivers/net/i40e/i40e_ethdev_vf.c      |  9 ++++++---
 drivers/net/ixgbe/ixgbe_ethdev.c       | 25 ++++++++++++++++++-------
 drivers/net/mlx5/mlx5.h                |  2 +-
 drivers/net/mlx5/mlx5_vlan.c           |  3 ++-
 drivers/net/nfp/nfp_net.c              | 13 +++++++------
 drivers/net/qede/qede_ethdev.c         |  9 +++++++--
 drivers/net/virtio/virtio_ethdev.c     | 21 +++++++++++++++++++++
 drivers/net/vmxnet3/vmxnet3_ethdev.c   | 10 +++++++---
 lib/librte_ether/rte_ethdev.c          | 14 +++++++++++++-
 lib/librte_ether/rte_ethdev.h          |  2 +-
 19 files changed, 142 insertions(+), 48 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f9..e74f70c 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -124,7 +124,7 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
-
+* Changed return type of ``vlan_offload_set_t`` from ``void`` to ``int``.
 
 Shared Library Versions
 -----------------------
diff --git a/drivers/net/avp/avp_ethdev.c b/drivers/net/avp/avp_ethdev.c
index c746a0e..4011dfa 100644
--- a/drivers/net/avp/avp_ethdev.c
+++ b/drivers/net/avp/avp_ethdev.c
@@ -70,7 +70,7 @@ static int avp_dev_create(struct rte_pci_device *pci_dev,
 static void avp_dev_close(struct rte_eth_dev *dev);
 static void avp_dev_info_get(struct rte_eth_dev *dev,
 			     struct rte_eth_dev_info *dev_info);
-static void avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static int avp_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete);
 static void avp_dev_promiscuous_enable(struct rte_eth_dev *dev);
 static void avp_dev_promiscuous_disable(struct rte_eth_dev *dev);
@@ -2031,7 +2031,12 @@ struct avp_queue {
 	mask = (ETH_VLAN_STRIP_MASK |
 		ETH_VLAN_FILTER_MASK |
 		ETH_VLAN_EXTEND_MASK);
-	avp_vlan_offload_set(eth_dev, mask);
+	ret = avp_vlan_offload_set(eth_dev, mask);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR, "VLAN offload set failed by host, ret=%d\n",
+			    ret);
+		goto unlock;
+	}
 
 	/* update device config */
 	memset(&config, 0, sizeof(config));
@@ -2214,7 +2219,7 @@ struct avp_queue {
 	}
 }
 
-static void
+static int
 avp_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 {
 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
@@ -2239,6 +2244,7 @@ struct avp_queue {
 		if (eth_dev->data->dev_conf.rxmode.hw_vlan_extend)
 			PMD_DRV_LOG(ERR, "VLAN extend offload not supported\n");
 	}
+	return 0;
 }
 
 static void
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index c9d1122..547bd55 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -144,7 +144,7 @@
 	ETH_RSS_NONFRAG_IPV6_TCP |	\
 	ETH_RSS_NONFRAG_IPV6_UDP)
 
-static void bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask);
+static int bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask);
 
 /***********************/
 
@@ -522,7 +522,9 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 		vlan_mask |= ETH_VLAN_FILTER_MASK;
 	if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip)
 		vlan_mask |= ETH_VLAN_STRIP_MASK;
-	bnxt_vlan_offload_set_op(eth_dev, vlan_mask);
+	rc = bnxt_vlan_offload_set_op(eth_dev, vlan_mask);
+	if (rc)
+		goto error;
 
 	return 0;
 
@@ -1275,7 +1277,7 @@ static int bnxt_vlan_filter_set_op(struct rte_eth_dev *eth_dev,
 		return bnxt_del_vlan_filter(bp, vlan_id);
 }
 
-static void
+static int
 bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask)
 {
 	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
@@ -1307,6 +1309,7 @@ static int bnxt_vlan_filter_set_op(struct rte_eth_dev *eth_dev,
 
 	if (mask & ETH_VLAN_EXTEND_MASK)
 		RTE_LOG(ERR, PMD, "Extend VLAN Not supported\n");
+	return 0;
 }
 
 static void
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 429b3a0..3390cb3 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -138,7 +138,7 @@
 	return ret;
 }
 
-static void
+static int
 dpaa2_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
@@ -158,6 +158,7 @@
 			RTE_LOG(ERR, PMD, "Unable to set vlan filter = %d\n",
 				ret);
 	}
+	return 0;
 }
 
 static int
@@ -643,8 +644,14 @@
 		return ret;
 	}
 	/* VLAN Offload Settings */
-	if (priv->max_vlan_filters)
-		dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
+	if (priv->max_vlan_filters) {
+		ret = dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Error to dpaa2_vlan_offload_set:"
+				     "code = %d\n", ret);
+			return ret;
+		}
+	}
 
 	return 0;
 }
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 3d4ab93..51f49d8 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -99,7 +99,7 @@ static int eth_em_interrupt_action(struct rte_eth_dev *dev,
 
 static int eth_em_vlan_filter_set(struct rte_eth_dev *dev,
 		uint16_t vlan_id, int on);
-static void eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void em_vlan_hw_filter_enable(struct rte_eth_dev *dev);
 static void em_vlan_hw_filter_disable(struct rte_eth_dev *dev);
 static void em_vlan_hw_strip_enable(struct rte_eth_dev *dev);
@@ -668,7 +668,12 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
 
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
 			ETH_VLAN_EXTEND_MASK;
-	eth_em_vlan_offload_set(dev, mask);
+	ret = eth_em_vlan_offload_set(dev, mask);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Unable to update vlan offload");
+		em_dev_clear_queues(dev);
+		return ret;
+	}
 
 	/* Set Interrupt Throttling Rate to maximum allowed value. */
 	E1000_WRITE_REG(hw, E1000_ITR, UINT16_MAX);
@@ -1447,7 +1452,7 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
 	E1000_WRITE_REG(hw, E1000_CTRL, reg);
 }
 
-static void
+static int
 eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if(mask & ETH_VLAN_STRIP_MASK){
@@ -1463,6 +1468,7 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
 		else
 			em_vlan_hw_filter_disable(dev);
 	}
+	return 0;
 }
 
 /*
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index e4f7a9f..fa15ee9 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -157,7 +157,7 @@ static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev,
 static int eth_igb_vlan_tpid_set(struct rte_eth_dev *dev,
 				 enum rte_vlan_type vlan_type,
 				 uint16_t tpid_id);
-static void eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 
 static void igb_vlan_hw_filter_enable(struct rte_eth_dev *dev);
 static void igb_vlan_hw_filter_disable(struct rte_eth_dev *dev);
@@ -1400,7 +1400,12 @@ static int eth_igbvf_pci_remove(struct rte_pci_device *pci_dev)
 	 */
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
 			ETH_VLAN_EXTEND_MASK;
-	eth_igb_vlan_offload_set(dev, mask);
+	ret = eth_igb_vlan_offload_set(dev, mask);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Unable to set vlan offload");
+		igb_dev_clear_queues(dev);
+		return ret;
+	}
 
 	if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) {
 		/* Enable VLAN filter since VMDq always use VLAN filter */
@@ -2715,7 +2720,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 						2 * VLAN_TAG_SIZE);
 }
 
-static void
+static int
 eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if(mask & ETH_VLAN_STRIP_MASK){
@@ -2738,6 +2743,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		else
 			igb_vlan_hw_extend_disable(dev);
 	}
+	return 0;
 }
 
 
diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
index da8fec2..fc1eac2 100644
--- a/drivers/net/enic/enic_ethdev.c
+++ b/drivers/net/enic/enic_ethdev.c
@@ -347,7 +347,7 @@ static int enicpmd_vlan_filter_set(struct rte_eth_dev *eth_dev,
 	return err;
 }
 
-static void enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
+static int enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 {
 	struct enic *enic = pmd_priv(eth_dev);
 
@@ -371,6 +371,8 @@ static void enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 		dev_warning(enic,
 			"Configuration of extended VLAN is not supported\n");
 	}
+
+	return 0;
 }
 
 static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev)
@@ -392,9 +394,9 @@ static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev)
 			eth_dev->data->dev_conf.rxmode.split_hdr_size);
 	}
 
-	enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
+	ret = enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
 	enic->hw_ip_checksum = eth_dev->data->dev_conf.rxmode.hw_ip_checksum;
-	return 0;
+	return ret;
 }
 
 /* Start the device.
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index e60d3a3..f4626f7 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1590,7 +1590,7 @@ static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	return 0;
 }
 
-static void
+static int
 fm10k_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if (mask & ETH_VLAN_STRIP_MASK) {
@@ -1609,6 +1609,7 @@ static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		if (!dev->data->dev_conf.rxmode.hw_vlan_filter)
 			PMD_INIT_LOG(ERR, "VLAN filter is always on in fm10k");
 	}
+	return 0;
 }
 
 /* Add/Remove a MAC address, and update filters to main VSI */
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 00b6082..d03a44b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -278,7 +278,7 @@ static int i40e_vlan_filter_set(struct rte_eth_dev *dev,
 static int i40e_vlan_tpid_set(struct rte_eth_dev *dev,
 			      enum rte_vlan_type vlan_type,
 			      uint16_t tpid);
-static void i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void i40e_vlan_strip_queue_set(struct rte_eth_dev *dev,
 				      uint16_t queue,
 				      int on);
@@ -3130,7 +3130,7 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	return ret;
 }
 
-static void
+static int
 i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
@@ -3163,6 +3163,7 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		else
 			i40e_vsi_config_double_vlan(vsi, FALSE);
 	}
+	return 0;
 }
 
 static void
@@ -5216,7 +5217,11 @@ struct i40e_vsi *
 
 	/* Apply vlan offload setting */
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK;
-	i40e_vlan_offload_set(dev, mask);
+	ret = i40e_vlan_offload_set(dev, mask);
+	if (ret) {
+		PMD_DRV_LOG(INFO, "Failed to update vlan offload");
+		return ret;
+	}
 
 	/* Apply double-vlan setting, not implemented yet */
 
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index f6d8293..f7fffc2 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -118,7 +118,7 @@ static int i40evf_dev_xstats_get_names(struct rte_eth_dev *dev,
 static void i40evf_dev_xstats_reset(struct rte_eth_dev *dev);
 static int i40evf_vlan_filter_set(struct rte_eth_dev *dev,
 				  uint16_t vlan_id, int on);
-static void i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static int i40evf_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t pvid,
 				int on);
 static void i40evf_dev_close(struct rte_eth_dev *dev);
@@ -1634,7 +1634,9 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
 	int ret;
 
 	/* Apply vlan offload setting */
-	i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
+	ret = i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
+	if (ret)
+		return ret;
 
 	/* Apply pvid setting */
 	ret = i40evf_vlan_pvid_set(dev, data->dev_conf.txmode.pvid,
@@ -1642,7 +1644,7 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
 	return ret;
 }
 
-static void
+static int
 i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
@@ -1655,6 +1657,7 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
 		else
 			i40evf_disable_vlan_strip(dev);
 	}
+	return 0;
 }
 
 static int
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 22171d8..1ec5aaf 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -218,7 +218,7 @@ static void ixgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev,
 		uint16_t queue, bool on);
 static void ixgbe_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue,
 		int on);
-static void ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void ixgbe_vlan_hw_strip_enable(struct rte_eth_dev *dev, uint16_t queue);
 static void ixgbe_vlan_hw_strip_disable(struct rte_eth_dev *dev, uint16_t queue);
 static void ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev);
@@ -274,7 +274,7 @@ static int ixgbevf_vlan_filter_set(struct rte_eth_dev *dev,
 		uint16_t vlan_id, int on);
 static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev,
 		uint16_t queue, int on);
-static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on);
 static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
 					    uint16_t queue_id);
@@ -2125,7 +2125,7 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 	 */
 }
 
-static void
+static int
 ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if (mask & ETH_VLAN_STRIP_MASK) {
@@ -2148,6 +2148,7 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 		else
 			ixgbe_vlan_hw_extend_disable(dev);
 	}
+	return 0;
 }
 
 static void
@@ -2568,9 +2569,13 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 		goto error;
 	}
 
-    mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
+	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
 		ETH_VLAN_EXTEND_MASK;
-	ixgbe_vlan_offload_set(dev, mask);
+	err = ixgbe_vlan_offload_set(dev, mask);
+	if (err) {
+		PMD_INIT_LOG(ERR, "Unable to set VLAN offload");
+		goto error;
+	}
 
 	if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) {
 		/* Enable vlan filtering for VMDq */
@@ -4993,7 +4998,12 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	/* Set HW strip */
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
 		ETH_VLAN_EXTEND_MASK;
-	ixgbevf_vlan_offload_set(dev, mask);
+	err = ixgbevf_vlan_offload_set(dev, mask);
+	if (err) {
+		PMD_INIT_LOG(ERR, "Unable to set VLAN offload (%d)", err);
+		ixgbe_dev_clear_queues(dev);
+		return err;
+	}
 
 	ixgbevf_dev_rxtx_start(dev);
 
@@ -5153,7 +5163,7 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
 	ixgbe_vlan_hw_strip_bitmap_set(dev, queue, on);
 }
 
-static void
+static int
 ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct ixgbe_hw *hw =
@@ -5168,6 +5178,7 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
 		for (i = 0; i < hw->mac.max_rx_queues; i++)
 			ixgbevf_vlan_strip_queue_set(dev, i, on);
 	}
+	return 0;
 }
 
 int
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 43c5384..93e71be 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -283,7 +283,7 @@ int mlx5_xstats_get_names(struct rte_eth_dev *,
 /* mlx5_vlan.c */
 
 int mlx5_vlan_filter_set(struct rte_eth_dev *, uint16_t, int);
-void mlx5_vlan_offload_set(struct rte_eth_dev *, int);
+int mlx5_vlan_offload_set(struct rte_eth_dev *, int);
 void mlx5_vlan_strip_queue_set(struct rte_eth_dev *, uint16_t, int);
 
 /* mlx5_trigger.c */
diff --git a/drivers/net/mlx5/mlx5_vlan.c b/drivers/net/mlx5/mlx5_vlan.c
index 1b0fa40..7215909 100644
--- a/drivers/net/mlx5/mlx5_vlan.c
+++ b/drivers/net/mlx5/mlx5_vlan.c
@@ -210,7 +210,7 @@
  * @param mask
  *   VLAN offload bit mask.
  */
-void
+int
 mlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct priv *priv = dev->data->dev_private;
@@ -230,4 +230,5 @@
 			priv_vlan_strip_queue_set(priv, i, hw_vlan_strip);
 		priv_unlock(priv);
 	}
+	return 0;
 }
diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index 92b03c4..6473edc 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -2149,11 +2149,12 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
 	return i;
 }
 
-static void
+static int
 nfp_net_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	uint32_t new_ctrl, update;
 	struct nfp_net_hw *hw;
+	int ret;
 
 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	new_ctrl = 0;
@@ -2174,14 +2175,14 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
 		new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_RXVLAN;
 
 	if (new_ctrl == 0)
-		return;
+		return 0;
 
 	update = NFP_NET_CFG_UPDATE_GEN;
 
-	if (nfp_net_reconfig(hw, new_ctrl, update) < 0)
-		return;
-
-	hw->ctrl = new_ctrl;
+	ret = nfp_net_reconfig(hw, new_ctrl, update);
+	if (!ret)
+		hw->ctrl = new_ctrl;
+	return ret;
 }
 
 /* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device */
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 0e05989..c5b1653 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -975,7 +975,7 @@ static int qede_vlan_filter_set(struct rte_eth_dev *eth_dev,
 	return rc;
 }
 
-static void qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
+static int qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 {
 	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
 	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
@@ -1013,6 +1013,8 @@ static void qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 
 	DP_INFO(edev, "vlan offload mask %d vlan-strip %d vlan-filter %d\n",
 		mask, rxmode->hw_vlan_strip, rxmode->hw_vlan_filter);
+
+	return 0;
 }
 
 static void qede_prandom_bytes(uint32_t *buff)
@@ -1157,6 +1159,7 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
 	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
 	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
+        int ret;
 
 	PMD_INIT_FUNC_TRACE(edev);
 
@@ -1237,9 +1240,11 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
 	qdev->enable_lro = rxmode->enable_lro;
 
 	/* Enable VLAN offloads by default */
-	qede_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK  |
+	ret = qede_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK  |
 			ETH_VLAN_FILTER_MASK |
 			ETH_VLAN_EXTEND_MASK);
+	if (ret)
+		return ret;
 
 	DP_INFO(edev, "Device configured with RSS=%d TSS=%d\n",
 			QEDE_RSS_COUNT(qdev), QEDE_TSS_COUNT(qdev));
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index e320811..72b4248 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -72,6 +72,7 @@ static void virtio_dev_info_get(struct rte_eth_dev *dev,
 				struct rte_eth_dev_info *dev_info);
 static int virtio_dev_link_update(struct rte_eth_dev *dev,
 	int wait_to_complete);
+static int virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 
 static void virtio_set_hwaddr(struct virtio_hw *hw);
 static void virtio_get_hwaddr(struct virtio_hw *hw);
@@ -779,6 +780,7 @@ struct rte_virtio_xstats_name_off {
 	.stats_reset             = virtio_dev_stats_reset,
 	.xstats_reset            = virtio_dev_stats_reset,
 	.link_update             = virtio_dev_link_update,
+	.vlan_offload_set        = virtio_dev_vlan_offload_set,
 	.rx_queue_setup          = virtio_dev_rx_queue_setup,
 	.rx_queue_intr_enable    = virtio_dev_rx_queue_intr_enable,
 	.rx_queue_intr_disable   = virtio_dev_rx_queue_intr_disable,
@@ -1875,6 +1877,25 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev)
 	return (old.link_status == link.link_status) ? -1 : 0;
 }
 
+static int
+virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
+{
+	const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
+	struct virtio_hw *hw = dev->data->dev_private;
+
+	if (rxmode->hw_vlan_filter &&
+	    !vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) {
+		PMD_DRV_LOG(NOTICE,
+			    "vlan filtering not available on this host");
+		return -ENOTSUP;
+	}
+
+	if (mask & ETH_VLAN_STRIP_MASK)
+		hw->vlan_strip = rxmode->hw_vlan_strip;
+
+	return 0;
+}
+
 static void
 virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 3910991..06735dd 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -100,7 +100,7 @@ static void vmxnet3_dev_info_get(struct rte_eth_dev *dev,
 vmxnet3_dev_supported_ptypes_get(struct rte_eth_dev *dev);
 static int vmxnet3_dev_vlan_filter_set(struct rte_eth_dev *dev,
 				       uint16_t vid, int on);
-static void vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void vmxnet3_mac_addr_set(struct rte_eth_dev *dev,
 				 struct ether_addr *mac_addr);
 static void vmxnet3_interrupt_handler(void *param);
@@ -730,8 +730,10 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
 		devRead->rssConfDesc.confPA  = hw->rss_confPA;
 	}
 
-	vmxnet3_dev_vlan_offload_set(dev,
+	ret = vmxnet3_dev_vlan_offload_set(dev,
 				     ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK);
+	if (ret)
+		return ret;
 
 	vmxnet3_write_mac(hw, dev->data->mac_addrs->addr_bytes);
 
@@ -1275,7 +1277,7 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
 	return 0;
 }
 
-static void
+static int
 vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct vmxnet3_hw *hw = dev->data->dev_private;
@@ -1301,6 +1303,8 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
 		VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
 				       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
 	}
+
+	return 0;
 }
 
 static void
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 0597641..d592a96 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2049,10 +2049,16 @@ struct rte_eth_dev *
 	int ret = 0;
 	int mask = 0;
 	int cur, org = 0;
+	uint8_t org_strip, org_filter, org_extend;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
 	dev = &rte_eth_devices[port_id];
 
+	/* save original values in case of failure */
+	org_strip = dev->data->dev_conf.rxmode.hw_vlan_strip;
+	org_filter = dev->data->dev_conf.rxmode.hw_vlan_filter;
+	org_extend = dev->data->dev_conf.rxmode.hw_vlan_extend;
+
 	/*check which option changed by application*/
 	cur = !!(offload_mask & ETH_VLAN_STRIP_OFFLOAD);
 	org = !!(dev->data->dev_conf.rxmode.hw_vlan_strip);
@@ -2080,7 +2086,13 @@ struct rte_eth_dev *
 		return ret;
 
 	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_offload_set, -ENOTSUP);
-	(*dev->dev_ops->vlan_offload_set)(dev, mask);
+	ret = (*dev->dev_ops->vlan_offload_set)(dev, mask);
+	if (ret) {
+		/* hit an error restore  original values */
+		dev->data->dev_conf.rxmode.hw_vlan_strip = org_strip;
+		dev->data->dev_conf.rxmode.hw_vlan_filter = org_filter;
+		dev->data->dev_conf.rxmode.hw_vlan_extend = org_extend;
+	}
 
 	return ret;
 }
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 0adf327..7254fd0 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1245,7 +1245,7 @@ typedef int (*vlan_tpid_set_t)(struct rte_eth_dev *dev,
 			       enum rte_vlan_type type, uint16_t tpid);
 /**< @internal set the outer/inner VLAN-TPID by an Ethernet device. */
 
-typedef void (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask);
+typedef int (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask);
 /**< @internal set VLAN offload function by an Ethernet device. */
 
 typedef int (*vlan_pvid_set_t)(struct rte_eth_dev *dev,
-- 
1.8.3.1

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v3] ethdev: modifiy vlan_offload_set_t to return int
  2017-08-25 13:33  4% ` [dpdk-dev] [PATCH v2] " David Harton
@ 2017-08-25 13:47  4%   ` David Harton
  2017-08-31 22:04  3%     ` Thomas Monjalon
  2017-09-01  2:36  7%     ` [dpdk-dev] [PATCH v4] ethdev: allow returning error on VLAN offload configuration David Harton
  0 siblings, 2 replies; 200+ results
From: David Harton @ 2017-08-25 13:47 UTC (permalink / raw)
  To: thomas, ferruh.yigit, ajit.khaparde, johndale,
	konstantin.ananyev, jingjing.wu, beilei.xing, jing.d.chen,
	adrien.mazarguil, nelio.laranjeiro, alejandro.lucero,
	hemant.agrawal, rasesh.mody, harish.patil, skhare, yliu,
	maxime.coquelin, allain.legacy
  Cc: dev, David Harton

Some devices may not support or fail setting VLAN offload
configuration based on dynamic circurmstances so the
vlan_offload_set_t vector is modified to return an int so
the caller can determine success or not.

rte_eth_dev_set_vlan_offload is updated to return the
value provided by the vector when called along with restoring
the original offload configs on failure.

Existing vlan_offload_set_t vectors are modified to return
an int.  Majority of cases return 0 but a few that actually
can fail now return their failure codes.

Finally, a vlan_offload_set_t vector is added to virtio
to facilitate dynamically turning VLAN strip on or off.

Signed-off-by: David Harton <dharton@cisco.com>
---

*v3
Fixed a format error.
Apologies...need to figure out why checkpatches.pl keeps saying
valid patch when I've got soft tabs.

*v2
Fixed a missed format error.
Removed vlan offload vector call casts and replaced with checks 
for return values.

*v1
This is an ABI breakage that has been previously negotiated
with Thomas and the proposed rel note change is included as well.

 doc/guides/rel_notes/release_17_11.rst |  2 +-
 drivers/net/avp/avp_ethdev.c           | 12 +++++++++---
 drivers/net/bnxt/bnxt_ethdev.c         |  9 ++++++---
 drivers/net/dpaa2/dpaa2_ethdev.c       | 13 ++++++++++---
 drivers/net/e1000/em_ethdev.c          | 12 +++++++++---
 drivers/net/e1000/igb_ethdev.c         | 12 +++++++++---
 drivers/net/enic/enic_ethdev.c         |  8 +++++---
 drivers/net/fm10k/fm10k_ethdev.c       |  3 ++-
 drivers/net/i40e/i40e_ethdev.c         | 11 ++++++++---
 drivers/net/i40e/i40e_ethdev_vf.c      |  9 ++++++---
 drivers/net/ixgbe/ixgbe_ethdev.c       | 25 ++++++++++++++++++-------
 drivers/net/mlx5/mlx5.h                |  2 +-
 drivers/net/mlx5/mlx5_vlan.c           |  3 ++-
 drivers/net/nfp/nfp_net.c              | 13 +++++++------
 drivers/net/qede/qede_ethdev.c         |  9 +++++++--
 drivers/net/virtio/virtio_ethdev.c     | 21 +++++++++++++++++++++
 drivers/net/vmxnet3/vmxnet3_ethdev.c   | 10 +++++++---
 lib/librte_ether/rte_ethdev.c          | 14 +++++++++++++-
 lib/librte_ether/rte_ethdev.h          |  2 +-
 19 files changed, 142 insertions(+), 48 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f9..e74f70c 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -124,7 +124,7 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
-
+* Changed return type of ``vlan_offload_set_t`` from ``void`` to ``int``.
 
 Shared Library Versions
 -----------------------
diff --git a/drivers/net/avp/avp_ethdev.c b/drivers/net/avp/avp_ethdev.c
index c746a0e..4011dfa 100644
--- a/drivers/net/avp/avp_ethdev.c
+++ b/drivers/net/avp/avp_ethdev.c
@@ -70,7 +70,7 @@ static int avp_dev_create(struct rte_pci_device *pci_dev,
 static void avp_dev_close(struct rte_eth_dev *dev);
 static void avp_dev_info_get(struct rte_eth_dev *dev,
 			     struct rte_eth_dev_info *dev_info);
-static void avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static int avp_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete);
 static void avp_dev_promiscuous_enable(struct rte_eth_dev *dev);
 static void avp_dev_promiscuous_disable(struct rte_eth_dev *dev);
@@ -2031,7 +2031,12 @@ struct avp_queue {
 	mask = (ETH_VLAN_STRIP_MASK |
 		ETH_VLAN_FILTER_MASK |
 		ETH_VLAN_EXTEND_MASK);
-	avp_vlan_offload_set(eth_dev, mask);
+	ret = avp_vlan_offload_set(eth_dev, mask);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR, "VLAN offload set failed by host, ret=%d\n",
+			    ret);
+		goto unlock;
+	}
 
 	/* update device config */
 	memset(&config, 0, sizeof(config));
@@ -2214,7 +2219,7 @@ struct avp_queue {
 	}
 }
 
-static void
+static int
 avp_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 {
 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
@@ -2239,6 +2244,7 @@ struct avp_queue {
 		if (eth_dev->data->dev_conf.rxmode.hw_vlan_extend)
 			PMD_DRV_LOG(ERR, "VLAN extend offload not supported\n");
 	}
+	return 0;
 }
 
 static void
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index c9d1122..547bd55 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -144,7 +144,7 @@
 	ETH_RSS_NONFRAG_IPV6_TCP |	\
 	ETH_RSS_NONFRAG_IPV6_UDP)
 
-static void bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask);
+static int bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask);
 
 /***********************/
 
@@ -522,7 +522,9 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 		vlan_mask |= ETH_VLAN_FILTER_MASK;
 	if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip)
 		vlan_mask |= ETH_VLAN_STRIP_MASK;
-	bnxt_vlan_offload_set_op(eth_dev, vlan_mask);
+	rc = bnxt_vlan_offload_set_op(eth_dev, vlan_mask);
+	if (rc)
+		goto error;
 
 	return 0;
 
@@ -1275,7 +1277,7 @@ static int bnxt_vlan_filter_set_op(struct rte_eth_dev *eth_dev,
 		return bnxt_del_vlan_filter(bp, vlan_id);
 }
 
-static void
+static int
 bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask)
 {
 	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
@@ -1307,6 +1309,7 @@ static int bnxt_vlan_filter_set_op(struct rte_eth_dev *eth_dev,
 
 	if (mask & ETH_VLAN_EXTEND_MASK)
 		RTE_LOG(ERR, PMD, "Extend VLAN Not supported\n");
+	return 0;
 }
 
 static void
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 429b3a0..3390cb3 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -138,7 +138,7 @@
 	return ret;
 }
 
-static void
+static int
 dpaa2_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
@@ -158,6 +158,7 @@
 			RTE_LOG(ERR, PMD, "Unable to set vlan filter = %d\n",
 				ret);
 	}
+	return 0;
 }
 
 static int
@@ -643,8 +644,14 @@
 		return ret;
 	}
 	/* VLAN Offload Settings */
-	if (priv->max_vlan_filters)
-		dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
+	if (priv->max_vlan_filters) {
+		ret = dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Error to dpaa2_vlan_offload_set:"
+				     "code = %d\n", ret);
+			return ret;
+		}
+	}
 
 	return 0;
 }
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 3d4ab93..51f49d8 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -99,7 +99,7 @@ static int eth_em_interrupt_action(struct rte_eth_dev *dev,
 
 static int eth_em_vlan_filter_set(struct rte_eth_dev *dev,
 		uint16_t vlan_id, int on);
-static void eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void em_vlan_hw_filter_enable(struct rte_eth_dev *dev);
 static void em_vlan_hw_filter_disable(struct rte_eth_dev *dev);
 static void em_vlan_hw_strip_enable(struct rte_eth_dev *dev);
@@ -668,7 +668,12 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
 
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
 			ETH_VLAN_EXTEND_MASK;
-	eth_em_vlan_offload_set(dev, mask);
+	ret = eth_em_vlan_offload_set(dev, mask);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Unable to update vlan offload");
+		em_dev_clear_queues(dev);
+		return ret;
+	}
 
 	/* Set Interrupt Throttling Rate to maximum allowed value. */
 	E1000_WRITE_REG(hw, E1000_ITR, UINT16_MAX);
@@ -1447,7 +1452,7 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
 	E1000_WRITE_REG(hw, E1000_CTRL, reg);
 }
 
-static void
+static int
 eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if(mask & ETH_VLAN_STRIP_MASK){
@@ -1463,6 +1468,7 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
 		else
 			em_vlan_hw_filter_disable(dev);
 	}
+	return 0;
 }
 
 /*
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index e4f7a9f..fa15ee9 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -157,7 +157,7 @@ static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev,
 static int eth_igb_vlan_tpid_set(struct rte_eth_dev *dev,
 				 enum rte_vlan_type vlan_type,
 				 uint16_t tpid_id);
-static void eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 
 static void igb_vlan_hw_filter_enable(struct rte_eth_dev *dev);
 static void igb_vlan_hw_filter_disable(struct rte_eth_dev *dev);
@@ -1400,7 +1400,12 @@ static int eth_igbvf_pci_remove(struct rte_pci_device *pci_dev)
 	 */
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
 			ETH_VLAN_EXTEND_MASK;
-	eth_igb_vlan_offload_set(dev, mask);
+	ret = eth_igb_vlan_offload_set(dev, mask);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Unable to set vlan offload");
+		igb_dev_clear_queues(dev);
+		return ret;
+	}
 
 	if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) {
 		/* Enable VLAN filter since VMDq always use VLAN filter */
@@ -2715,7 +2720,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 						2 * VLAN_TAG_SIZE);
 }
 
-static void
+static int
 eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if(mask & ETH_VLAN_STRIP_MASK){
@@ -2738,6 +2743,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		else
 			igb_vlan_hw_extend_disable(dev);
 	}
+	return 0;
 }
 
 
diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
index da8fec2..fc1eac2 100644
--- a/drivers/net/enic/enic_ethdev.c
+++ b/drivers/net/enic/enic_ethdev.c
@@ -347,7 +347,7 @@ static int enicpmd_vlan_filter_set(struct rte_eth_dev *eth_dev,
 	return err;
 }
 
-static void enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
+static int enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 {
 	struct enic *enic = pmd_priv(eth_dev);
 
@@ -371,6 +371,8 @@ static void enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 		dev_warning(enic,
 			"Configuration of extended VLAN is not supported\n");
 	}
+
+	return 0;
 }
 
 static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev)
@@ -392,9 +394,9 @@ static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev)
 			eth_dev->data->dev_conf.rxmode.split_hdr_size);
 	}
 
-	enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
+	ret = enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
 	enic->hw_ip_checksum = eth_dev->data->dev_conf.rxmode.hw_ip_checksum;
-	return 0;
+	return ret;
 }
 
 /* Start the device.
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index e60d3a3..f4626f7 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1590,7 +1590,7 @@ static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	return 0;
 }
 
-static void
+static int
 fm10k_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if (mask & ETH_VLAN_STRIP_MASK) {
@@ -1609,6 +1609,7 @@ static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		if (!dev->data->dev_conf.rxmode.hw_vlan_filter)
 			PMD_INIT_LOG(ERR, "VLAN filter is always on in fm10k");
 	}
+	return 0;
 }
 
 /* Add/Remove a MAC address, and update filters to main VSI */
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 00b6082..d03a44b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -278,7 +278,7 @@ static int i40e_vlan_filter_set(struct rte_eth_dev *dev,
 static int i40e_vlan_tpid_set(struct rte_eth_dev *dev,
 			      enum rte_vlan_type vlan_type,
 			      uint16_t tpid);
-static void i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void i40e_vlan_strip_queue_set(struct rte_eth_dev *dev,
 				      uint16_t queue,
 				      int on);
@@ -3130,7 +3130,7 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	return ret;
 }
 
-static void
+static int
 i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
@@ -3163,6 +3163,7 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		else
 			i40e_vsi_config_double_vlan(vsi, FALSE);
 	}
+	return 0;
 }
 
 static void
@@ -5216,7 +5217,11 @@ struct i40e_vsi *
 
 	/* Apply vlan offload setting */
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK;
-	i40e_vlan_offload_set(dev, mask);
+	ret = i40e_vlan_offload_set(dev, mask);
+	if (ret) {
+		PMD_DRV_LOG(INFO, "Failed to update vlan offload");
+		return ret;
+	}
 
 	/* Apply double-vlan setting, not implemented yet */
 
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index f6d8293..f7fffc2 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -118,7 +118,7 @@ static int i40evf_dev_xstats_get_names(struct rte_eth_dev *dev,
 static void i40evf_dev_xstats_reset(struct rte_eth_dev *dev);
 static int i40evf_vlan_filter_set(struct rte_eth_dev *dev,
 				  uint16_t vlan_id, int on);
-static void i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static int i40evf_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t pvid,
 				int on);
 static void i40evf_dev_close(struct rte_eth_dev *dev);
@@ -1634,7 +1634,9 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
 	int ret;
 
 	/* Apply vlan offload setting */
-	i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
+	ret = i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
+	if (ret)
+		return ret;
 
 	/* Apply pvid setting */
 	ret = i40evf_vlan_pvid_set(dev, data->dev_conf.txmode.pvid,
@@ -1642,7 +1644,7 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
 	return ret;
 }
 
-static void
+static int
 i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
@@ -1655,6 +1657,7 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
 		else
 			i40evf_disable_vlan_strip(dev);
 	}
+	return 0;
 }
 
 static int
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 22171d8..1ec5aaf 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -218,7 +218,7 @@ static void ixgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev,
 		uint16_t queue, bool on);
 static void ixgbe_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue,
 		int on);
-static void ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void ixgbe_vlan_hw_strip_enable(struct rte_eth_dev *dev, uint16_t queue);
 static void ixgbe_vlan_hw_strip_disable(struct rte_eth_dev *dev, uint16_t queue);
 static void ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev);
@@ -274,7 +274,7 @@ static int ixgbevf_vlan_filter_set(struct rte_eth_dev *dev,
 		uint16_t vlan_id, int on);
 static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev,
 		uint16_t queue, int on);
-static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on);
 static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
 					    uint16_t queue_id);
@@ -2125,7 +2125,7 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 	 */
 }
 
-static void
+static int
 ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if (mask & ETH_VLAN_STRIP_MASK) {
@@ -2148,6 +2148,7 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 		else
 			ixgbe_vlan_hw_extend_disable(dev);
 	}
+	return 0;
 }
 
 static void
@@ -2568,9 +2569,13 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 		goto error;
 	}
 
-    mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
+	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
 		ETH_VLAN_EXTEND_MASK;
-	ixgbe_vlan_offload_set(dev, mask);
+	err = ixgbe_vlan_offload_set(dev, mask);
+	if (err) {
+		PMD_INIT_LOG(ERR, "Unable to set VLAN offload");
+		goto error;
+	}
 
 	if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) {
 		/* Enable vlan filtering for VMDq */
@@ -4993,7 +4998,12 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	/* Set HW strip */
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
 		ETH_VLAN_EXTEND_MASK;
-	ixgbevf_vlan_offload_set(dev, mask);
+	err = ixgbevf_vlan_offload_set(dev, mask);
+	if (err) {
+		PMD_INIT_LOG(ERR, "Unable to set VLAN offload (%d)", err);
+		ixgbe_dev_clear_queues(dev);
+		return err;
+	}
 
 	ixgbevf_dev_rxtx_start(dev);
 
@@ -5153,7 +5163,7 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
 	ixgbe_vlan_hw_strip_bitmap_set(dev, queue, on);
 }
 
-static void
+static int
 ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct ixgbe_hw *hw =
@@ -5168,6 +5178,7 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
 		for (i = 0; i < hw->mac.max_rx_queues; i++)
 			ixgbevf_vlan_strip_queue_set(dev, i, on);
 	}
+	return 0;
 }
 
 int
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 43c5384..93e71be 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -283,7 +283,7 @@ int mlx5_xstats_get_names(struct rte_eth_dev *,
 /* mlx5_vlan.c */
 
 int mlx5_vlan_filter_set(struct rte_eth_dev *, uint16_t, int);
-void mlx5_vlan_offload_set(struct rte_eth_dev *, int);
+int mlx5_vlan_offload_set(struct rte_eth_dev *, int);
 void mlx5_vlan_strip_queue_set(struct rte_eth_dev *, uint16_t, int);
 
 /* mlx5_trigger.c */
diff --git a/drivers/net/mlx5/mlx5_vlan.c b/drivers/net/mlx5/mlx5_vlan.c
index 1b0fa40..7215909 100644
--- a/drivers/net/mlx5/mlx5_vlan.c
+++ b/drivers/net/mlx5/mlx5_vlan.c
@@ -210,7 +210,7 @@
  * @param mask
  *   VLAN offload bit mask.
  */
-void
+int
 mlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct priv *priv = dev->data->dev_private;
@@ -230,4 +230,5 @@
 			priv_vlan_strip_queue_set(priv, i, hw_vlan_strip);
 		priv_unlock(priv);
 	}
+	return 0;
 }
diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index 92b03c4..6473edc 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -2149,11 +2149,12 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
 	return i;
 }
 
-static void
+static int
 nfp_net_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	uint32_t new_ctrl, update;
 	struct nfp_net_hw *hw;
+	int ret;
 
 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	new_ctrl = 0;
@@ -2174,14 +2175,14 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
 		new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_RXVLAN;
 
 	if (new_ctrl == 0)
-		return;
+		return 0;
 
 	update = NFP_NET_CFG_UPDATE_GEN;
 
-	if (nfp_net_reconfig(hw, new_ctrl, update) < 0)
-		return;
-
-	hw->ctrl = new_ctrl;
+	ret = nfp_net_reconfig(hw, new_ctrl, update);
+	if (!ret)
+		hw->ctrl = new_ctrl;
+	return ret;
 }
 
 /* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device */
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 0e05989..644f69d 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -975,7 +975,7 @@ static int qede_vlan_filter_set(struct rte_eth_dev *eth_dev,
 	return rc;
 }
 
-static void qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
+static int qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 {
 	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
 	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
@@ -1013,6 +1013,8 @@ static void qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 
 	DP_INFO(edev, "vlan offload mask %d vlan-strip %d vlan-filter %d\n",
 		mask, rxmode->hw_vlan_strip, rxmode->hw_vlan_filter);
+
+	return 0;
 }
 
 static void qede_prandom_bytes(uint32_t *buff)
@@ -1157,6 +1159,7 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
 	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
 	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
+	int ret;
 
 	PMD_INIT_FUNC_TRACE(edev);
 
@@ -1237,9 +1240,11 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
 	qdev->enable_lro = rxmode->enable_lro;
 
 	/* Enable VLAN offloads by default */
-	qede_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK  |
+	ret = qede_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK  |
 			ETH_VLAN_FILTER_MASK |
 			ETH_VLAN_EXTEND_MASK);
+	if (ret)
+		return ret;
 
 	DP_INFO(edev, "Device configured with RSS=%d TSS=%d\n",
 			QEDE_RSS_COUNT(qdev), QEDE_TSS_COUNT(qdev));
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index e320811..72b4248 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -72,6 +72,7 @@ static void virtio_dev_info_get(struct rte_eth_dev *dev,
 				struct rte_eth_dev_info *dev_info);
 static int virtio_dev_link_update(struct rte_eth_dev *dev,
 	int wait_to_complete);
+static int virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 
 static void virtio_set_hwaddr(struct virtio_hw *hw);
 static void virtio_get_hwaddr(struct virtio_hw *hw);
@@ -779,6 +780,7 @@ struct rte_virtio_xstats_name_off {
 	.stats_reset             = virtio_dev_stats_reset,
 	.xstats_reset            = virtio_dev_stats_reset,
 	.link_update             = virtio_dev_link_update,
+	.vlan_offload_set        = virtio_dev_vlan_offload_set,
 	.rx_queue_setup          = virtio_dev_rx_queue_setup,
 	.rx_queue_intr_enable    = virtio_dev_rx_queue_intr_enable,
 	.rx_queue_intr_disable   = virtio_dev_rx_queue_intr_disable,
@@ -1875,6 +1877,25 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev)
 	return (old.link_status == link.link_status) ? -1 : 0;
 }
 
+static int
+virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
+{
+	const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
+	struct virtio_hw *hw = dev->data->dev_private;
+
+	if (rxmode->hw_vlan_filter &&
+	    !vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) {
+		PMD_DRV_LOG(NOTICE,
+			    "vlan filtering not available on this host");
+		return -ENOTSUP;
+	}
+
+	if (mask & ETH_VLAN_STRIP_MASK)
+		hw->vlan_strip = rxmode->hw_vlan_strip;
+
+	return 0;
+}
+
 static void
 virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 3910991..06735dd 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -100,7 +100,7 @@ static void vmxnet3_dev_info_get(struct rte_eth_dev *dev,
 vmxnet3_dev_supported_ptypes_get(struct rte_eth_dev *dev);
 static int vmxnet3_dev_vlan_filter_set(struct rte_eth_dev *dev,
 				       uint16_t vid, int on);
-static void vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void vmxnet3_mac_addr_set(struct rte_eth_dev *dev,
 				 struct ether_addr *mac_addr);
 static void vmxnet3_interrupt_handler(void *param);
@@ -730,8 +730,10 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
 		devRead->rssConfDesc.confPA  = hw->rss_confPA;
 	}
 
-	vmxnet3_dev_vlan_offload_set(dev,
+	ret = vmxnet3_dev_vlan_offload_set(dev,
 				     ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK);
+	if (ret)
+		return ret;
 
 	vmxnet3_write_mac(hw, dev->data->mac_addrs->addr_bytes);
 
@@ -1275,7 +1277,7 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
 	return 0;
 }
 
-static void
+static int
 vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct vmxnet3_hw *hw = dev->data->dev_private;
@@ -1301,6 +1303,8 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
 		VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
 				       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
 	}
+
+	return 0;
 }
 
 static void
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 0597641..d592a96 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2049,10 +2049,16 @@ struct rte_eth_dev *
 	int ret = 0;
 	int mask = 0;
 	int cur, org = 0;
+	uint8_t org_strip, org_filter, org_extend;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
 	dev = &rte_eth_devices[port_id];
 
+	/* save original values in case of failure */
+	org_strip = dev->data->dev_conf.rxmode.hw_vlan_strip;
+	org_filter = dev->data->dev_conf.rxmode.hw_vlan_filter;
+	org_extend = dev->data->dev_conf.rxmode.hw_vlan_extend;
+
 	/*check which option changed by application*/
 	cur = !!(offload_mask & ETH_VLAN_STRIP_OFFLOAD);
 	org = !!(dev->data->dev_conf.rxmode.hw_vlan_strip);
@@ -2080,7 +2086,13 @@ struct rte_eth_dev *
 		return ret;
 
 	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_offload_set, -ENOTSUP);
-	(*dev->dev_ops->vlan_offload_set)(dev, mask);
+	ret = (*dev->dev_ops->vlan_offload_set)(dev, mask);
+	if (ret) {
+		/* hit an error restore  original values */
+		dev->data->dev_conf.rxmode.hw_vlan_strip = org_strip;
+		dev->data->dev_conf.rxmode.hw_vlan_filter = org_filter;
+		dev->data->dev_conf.rxmode.hw_vlan_extend = org_extend;
+	}
 
 	return ret;
 }
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 0adf327..7254fd0 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1245,7 +1245,7 @@ typedef int (*vlan_tpid_set_t)(struct rte_eth_dev *dev,
 			       enum rte_vlan_type type, uint16_t tpid);
 /**< @internal set the outer/inner VLAN-TPID by an Ethernet device. */
 
-typedef void (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask);
+typedef int (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask);
 /**< @internal set VLAN offload function by an Ethernet device. */
 
 typedef int (*vlan_pvid_set_t)(struct rte_eth_dev *dev,
-- 
1.8.3.1

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH 2/3] ethdev: add new rte_mtr API for traffic metering and policing
  @ 2017-08-26  0:06  2%   ` Cristian Dumitrescu
  2017-09-01  8:09  0%     ` Hemant Agrawal
  0 siblings, 1 reply; 200+ results
From: Cristian Dumitrescu @ 2017-08-26  0:06 UTC (permalink / raw)
  To: dev; +Cc: thomas, adrien.mazarguil, jerin.jacob, hemant.agrawal

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
Changes in v1 (from RFC [1]):
- Added EXPERIMENTAL tag in rte_mtr.h and MANTAINERS for this new API
  (input from Thomas)
- Added more Doxygen comments to re-inforce relationship between MTR and
  flow (input from Adrien)
- Added Doxygen hook in doxy-api-index.md

[1] RFC: http://www.dpdk.org/ml/archives/dev/2017-May/066888.html

 MAINTAINERS                            |   4 +
 doc/api/doxy-api-index.md              |   1 +
 lib/librte_ether/Makefile              |   5 +-
 lib/librte_ether/rte_ether_version.map |  15 ++
 lib/librte_ether/rte_mtr.c             | 184 +++++++++++++
 lib/librte_ether/rte_mtr.h             | 471 +++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_mtr_driver.h      | 188 +++++++++++++
 7 files changed, 867 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_ether/rte_mtr.c
 create mode 100644 lib/librte_ether/rte_mtr.h
 create mode 100644 lib/librte_ether/rte_mtr_driver.h

diff --git a/MAINTAINERS b/MAINTAINERS
index a0cd75e..5491906 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -257,6 +257,10 @@ M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
 T: git://dpdk.org/next/dpdk-next-tm
 F: lib/librte_ether/rte_tm*
 
+Traffic Metering and Policing API - EXPERIMENTAL
+M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
+F: lib/librte_ether/rte_mtr*
+
 Crypto API
 M: Declan Doherty <declan.doherty@intel.com>
 F: lib/librte_cryptodev/
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 19e0d4f..b2342a9 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -41,6 +41,7 @@ The public API headers are grouped by topics:
   [ethctrl]            (@ref rte_eth_ctrl.h),
   [rte_flow]           (@ref rte_flow.h),
   [rte_tm]             (@ref rte_tm.h),
+  [rte_mtr]            (@ref rte_mtr.h),
   [cryptodev]          (@ref rte_cryptodev.h),
   [eventdev]           (@ref rte_eventdev.h),
   [metrics]            (@ref rte_metrics.h),
diff --git a/lib/librte_ether/Makefile b/lib/librte_ether/Makefile
index db692ae..e4e339d 100644
--- a/lib/librte_ether/Makefile
+++ b/lib/librte_ether/Makefile
@@ -41,11 +41,12 @@ CFLAGS += $(WERROR_FLAGS)
 
 EXPORT_MAP := rte_ether_version.map
 
-LIBABIVER := 6
+LIBABIVER := 7
 
 SRCS-y += rte_ethdev.c
 SRCS-y += rte_flow.c
 SRCS-y += rte_tm.c
+SRCS-y += rte_mtr.c
 
 #
 # Export include files
@@ -59,5 +60,7 @@ SYMLINK-y-include += rte_flow.h
 SYMLINK-y-include += rte_flow_driver.h
 SYMLINK-y-include += rte_tm.h
 SYMLINK-y-include += rte_tm_driver.h
+SYMLINK-y-include += rte_mtr.h
+SYMLINK-y-include += rte_mtr_driver.h
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index 4283728..7192664 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -187,3 +187,18 @@ DPDK_17.08 {
 	rte_tm_wred_profile_delete;
 
 } DPDK_17.05;
+
+DPDK_17.11 {
+	global:
+
+	rte_eth_dev_mtr_ops_get;
+	rte_mtr_meter_profile_add;
+	rte_mtr_meter_profile_delete;
+	rte_mtr_create;
+	rte_mtr_destroy;
+	rte_mtr_meter_profile_update;
+	rte_mtr_policer_action_update;
+	rte_mtr_stats_update;
+	rte_mtr_stats_read;
+
+} DPDK_17.08;
diff --git a/lib/librte_ether/rte_mtr.c b/lib/librte_ether/rte_mtr.c
new file mode 100644
index 0000000..efbe7fb
--- /dev/null
+++ b/lib/librte_ether/rte_mtr.c
@@ -0,0 +1,184 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 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 <stdint.h>
+
+#include <rte_errno.h>
+#include "rte_ethdev.h"
+#include "rte_mtr_driver.h"
+#include "rte_mtr.h"
+
+/* Get generic traffic metering and policing operations structure from a port. */
+const struct rte_mtr_ops *
+rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	const struct rte_mtr_ops *ops;
+
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		rte_mtr_error_set(error,
+			ENODEV,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			rte_strerror(ENODEV));
+		return NULL;
+	}
+
+	if ((dev->dev_ops->mtr_ops_get == NULL) ||
+		(dev->dev_ops->mtr_ops_get(dev, &ops) != 0) ||
+		(ops == NULL)) {
+		rte_mtr_error_set(error,
+			ENOSYS,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			rte_strerror(ENOSYS));
+		return NULL;
+	}
+
+	return ops;
+}
+
+#define RTE_MTR_FUNC(port_id, func)			\
+({							\
+	const struct rte_mtr_ops *ops =			\
+		rte_mtr_ops_get(port_id, error);		\
+	if (ops == NULL)					\
+		return -rte_errno;			\
+							\
+	if (ops->func == NULL)				\
+		return -rte_mtr_error_set(error,		\
+			ENOSYS,				\
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,	\
+			NULL,				\
+			rte_strerror(ENOSYS));		\
+							\
+	ops->func;					\
+})
+
+/* MTR meter profile add */
+int
+rte_mtr_meter_profile_add(uint8_t port_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_meter_profile *profile,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_profile_add)(dev,
+		meter_profile_id, profile, error);
+}
+
+/** MTR meter profile delete */
+int
+rte_mtr_meter_profile_delete(uint8_t port_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_profile_delete)(dev,
+		meter_profile_id, error);
+}
+
+/** MTR object create */
+int
+rte_mtr_create(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_params *params,
+	int shared,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, create)(dev,
+		mtr_id, params, shared, error);
+}
+
+/** MTR object destroy */
+int
+rte_mtr_destroy(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, destroy)(dev,
+		mtr_id, error);
+}
+
+/** MTR object meter profile update */
+int
+rte_mtr_meter_profile_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_profile_update)(dev,
+		mtr_id, meter_profile_id, error);
+}
+
+/** MTR object policer action update */
+int
+rte_mtr_policer_action_update(uint8_t port_id,
+	uint32_t mtr_id,
+	enum rte_mtr_color color,
+	enum rte_mtr_policer_action action,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, policer_action_update)(dev,
+		mtr_id, color, action, error);
+}
+
+/** MTR object enabled stats update */
+int
+rte_mtr_stats_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint64_t stats_mask,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, stats_update)(dev,
+		mtr_id, stats_mask, error);
+}
+
+/** MTR object stats read */
+int
+rte_mtr_stats_read(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, stats_read)(dev,
+		mtr_id, stats, stats_mask, clear, error);
+}
diff --git a/lib/librte_ether/rte_mtr.h b/lib/librte_ether/rte_mtr.h
new file mode 100644
index 0000000..d15cb9f
--- /dev/null
+++ b/lib/librte_ether/rte_mtr.h
@@ -0,0 +1,471 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 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.
+ */
+
+#ifndef __INCLUDE_RTE_MTR_H__
+#define __INCLUDE_RTE_MTR_H__
+
+/**
+ * @file
+ * RTE Generic Traffic Metering and Policing API
+ *
+ * This interface provides the ability to configure the traffic metering and
+ * policing (MTR) in a generic way.
+ *
+ * The processing done for each input packet hitting a MTR object is:
+ *    A) Traffic metering: The packet is assigned a color (the meter output
+ *       color), based on the previous history of the flow reflected in the
+ *       current state of the MTR object, according to the specific traffic
+ *       metering algorithm. The traffic metering algorithm can typically work
+ *       in color aware mode, in which case the input packet already has an
+ *       initial color (the input color), or in color blind mode, which is
+ *       equivalent to considering all input packets initially colored as green.
+ *    B) Policing: There is a separate policer action configured for each meter
+ *       output color, which can:
+ *          a) Drop the packet.
+ *          b) Keep the same packet color: the policer output color matches the
+ *             meter output color (essentially a no-op action).
+ *          c) Recolor the packet: the policer output color is different than
+ *             the meter output color.
+ *       The policer output color is the output color of the packet, which is
+ *       set in the packet meta-data (i.e. struct rte_mbuf::sched::color).
+ *    C) Statistics: The set of counters maintained for each MTR object is
+ *       configurable and subject to the implementation support. This set
+ *       includes the number of packets and bytes dropped or passed for each
+ *       output color.
+ *
+ * Once successfully created, an MTR object is linked to one or several flows
+ * through the meter action of the flow API.
+ *    A) Whether an MTR object is private to a flow or potentially shared by
+ *       several flows has to be specified at creation time.
+ *    B) Several meter actions can be potentially registered for the same flow.
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ */
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Color
+ */
+enum rte_mtr_color {
+	RTE_MTR_GREEN = 0, /**< Green */
+	RTE_MTR_YELLOW, /**< Yellow */
+	RTE_MTR_RED, /**< Red */
+	RTE_MTR_COLORS /**< Number of colors */
+};
+
+/**
+ * Statistics counter type
+ */
+enum rte_mtr_stats_type {
+	/**< Number of packets passed as green by the policer.  */
+	RTE_MTR_STATS_N_PKTS_GREEN = 1 << 0,
+
+	/**< Number of bytes passed as green by the policer.  */
+	RTE_MTR_STATS_N_BYTES_GREEN = 1 << 1,
+
+	/**< Number of packets passed as yellow by the policer.  */
+	RTE_MTR_STATS_N_PKTS_YELLOW = 1 << 2,
+
+	/**< Number of bytes passed as yellow by the policer.  */
+	RTE_MTR_STATS_N_BYTES_YELLOW = 1 << 3,
+
+	/**< Number of packets passed as red by the policer.  */
+	RTE_MTR_STATS_N_PKTS_RED = 1 << 4,
+
+	/**< Number of bytes passed as red by the policer.  */
+	RTE_MTR_STATS_N_BYTES_RED = 1 << 5,
+
+	/**< Number of packets dropped by the policer.  */
+	RTE_MTR_STATS_N_PKTS_DROPPED = 1 << 6,
+
+	/**< Number of bytes dropped by the policer.  */
+	RTE_MTR_STATS_N_BYTES_DROPPED = 1 << 7,
+};
+
+/**
+ * Statistics counters
+ */
+struct rte_mtr_stats {
+	/**< Number of packets passed by the policer (per color). */
+	uint64_t n_pkts[RTE_MTR_COLORS];
+
+	/**< Number of bytes passed by the policer (per color). */
+	uint64_t n_bytes[RTE_MTR_COLORS];
+
+	/**< Number of packets dropped by the policer. */
+	uint64_t n_pkts_dropped;
+
+	/**< Number of bytes passed by the policer. */
+	uint64_t n_bytes_dropped;
+};
+
+/**
+ * Traffic metering algorithms
+ */
+enum rte_mtr_algorithm {
+	/**< Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
+	RTE_MTR_SRTCM_RFC2697 = 0,
+
+	/**< Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
+	RTE_MTR_TRTCM_RFC2698,
+};
+
+/**
+ * Meter profile
+ */
+struct rte_mtr_meter_profile {
+	/**<  Traffic metering algorithm. */
+	enum rte_mtr_algorithm alg;
+
+	union {
+		/**< Items only valid when *alg* is set to srTCM - RFC2697. */
+		struct {
+			/**< Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/**< Committed Burst Size (CBS) (bytes). */
+			uint64_t cbs;
+
+			/**< Excess Burst Size (EBS) (bytes). */
+			uint64_t ebs;
+
+			/**< Non-zero for color aware mode, zero for color blind
+			 * mode. In color aware mode, the packet input color is
+			 * read from the IPv4/IPv6 DSCP field, as defined by
+			 * IETF RFC 2597 (low/medium/high drop precedence
+			 * translates to green/yellow/red color respectively).
+			 */
+			int color_aware;
+		} srtcm_rfc2697;
+
+		/**< Items only valid when *alg* is set to trTCM - RFC2698. */
+		struct {
+			/**< Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/**< Peak Information Rate (PIR) (bytes/second). */
+			uint64_t pir;
+
+			/**< Committed Burst Size (CBS) (byes). */
+			uint64_t cbs;
+
+			/**< Peak Burst Size (PBS) (bytes). */
+			uint64_t pbs;
+
+			/**< Non-zero for color aware mode, zero for color blind
+			 * mode. In color aware mode, the packet input color is
+			 * read from the IPv4/IPv6 DSCP field, as defined by
+			 * IETF RFC 2597 (low/medium/high drop precedence
+			 * translates to green/yellow/red color respectively).
+			 */
+			int color_aware;
+		} trtcm_rfc2698;
+	};
+};
+
+/**
+ * Policer actions
+ */
+enum rte_mtr_policer_action {
+	/**< Recolor the packet as green. */
+	e_MTR_POLICER_ACTION_COLOR_GREEN = 0,
+
+	/**< Recolor the packet as yellow. */
+	e_MTR_POLICER_ACTION_COLOR_YELLOW,
+
+	/**< Recolor the packet as red. */
+	e_MTR_POLICER_ACTION_COLOR_RED,
+
+	/**< Drop the packet. */
+	e_MTR_POLICER_ACTION_DROP,
+};
+
+/**
+ * Parameters for each traffic metering & policing object
+ *
+ * @see enum rte_mtr_stats_type
+ */
+struct rte_mtr_params {
+	/**< Meter profile ID. */
+	uint32_t meter_profile_id;
+
+	/**< Policer actions (per meter output color). */
+	enum rte_mtr_policer_action action[RTE_MTR_COLORS];
+
+	/**< Set of stats counters to be enabled. */
+	uint64_t stats_mask;
+};
+
+/**
+ * Verbose error types.
+ *
+ * Most of them provide the type of the object referenced by struct
+ * rte_mtr_error::cause.
+ */
+enum rte_mtr_error_type {
+	RTE_MTR_ERROR_TYPE_NONE, /**< No error. */
+	RTE_MTR_ERROR_TYPE_UNSPECIFIED, /**< Cause unspecified. */
+	RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+	RTE_MTR_ERROR_TYPE_METER_PROFILE,
+	RTE_MTR_ERROR_TYPE_MTR_ID,
+	RTE_MTR_ERROR_TYPE_MTR_PARAMS,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED,
+	RTE_MTR_ERROR_TYPE_STATS_MASK,
+	RTE_MTR_ERROR_TYPE_STATS,
+	RTE_MTR_ERROR_TYPE_SHARED,
+};
+
+/**
+ * Verbose error structure definition.
+ *
+ * This object is normally allocated by applications and set by PMDs, the
+ * message points to a constant string which does not need to be freed by
+ * the application, however its pointer can be considered valid only as long
+ * as its associated DPDK port remains configured. Closing the underlying
+ * device or unloading the PMD invalidates it.
+ *
+ * Both cause and message may be NULL regardless of the error type.
+ */
+struct rte_mtr_error {
+	enum rte_mtr_error_type type; /**< Cause field and error type. */
+	const void *cause; /**< Object responsible for the error. */
+	const char *message; /**< Human-readable error message. */
+};
+
+/**
+ * Meter profile add
+ *
+ * Create a new meter profile with ID set to *meter_profile_id*. The new profile
+ * is used to create one or several MTR objects.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] meter_profile_id
+ *   ID for the new meter profile. Needs to be unused by any of the existing
+ *   meter profiles added for the current port.
+ * @param[in] profile
+ *   Meter profile parameters. Needs to be pre-allocated and valid.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_profile_add(uint8_t port_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_meter_profile *profile,
+	struct rte_mtr_error *error);
+
+/**
+ * Meter profile delete
+ *
+ * Delete an existing meter profile. This operation fails when there is
+ * currently at least one user (i.e. MTR object) of this profile.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] meter_profile_id
+ *   Meter profile ID. Needs to be the valid.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_profile_delete(uint8_t port_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object create
+ *
+ * Create a new MTR object for the current port. This object is run as part of
+ * associated flow action for traffic metering and policing.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be unused by any of the existing MTR objects
+ *   created for the current port.
+ * @param[in] params
+ *   MTR object params. Needs to be pre-allocated and valid.
+ * @param[in] shared
+ *   Non-zero when this MTR object can be shared by multiple flows, zero when
+ *   this MTR object can be used by a single flow.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_flow_action_type::RTE_FLOW_ACTION_TYPE_METER
+ */
+int
+rte_mtr_create(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_params *params,
+	int shared,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object destroy
+ *
+ * Delete an existing MTR object. This operation fails when there is currently
+ * at least one user (i.e. flow) of this MTR object.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be unused by any of the existing MTR objects
+ *   created for the current port.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_destroy(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object meter profile update
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ * @param[in] meter_profile_id
+ *   Meter profile ID for the current MTR object. Needs to be valid.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_profile_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object policer action update for given color
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ * @param[in] color
+ *   Color for which the policer action is updated.
+ * @param[in] action
+ *   Policer action for specified color.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_policer_action_update(uint8_t port_id,
+	uint32_t mtr_id,
+	enum rte_mtr_color color,
+	enum rte_mtr_policer_action action,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object enabled statistics counters update
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ * @param[in] stats_mask
+ *   Mask of statistics counter types to be enabled for the current MTR object.
+ *   Any statistics counter type not included in this set is to be disabled for
+ *   the current MTR object.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_mtr_stats_type
+ */
+int
+rte_mtr_stats_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint64_t stats_mask,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object statistics counters read
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ * @param[out] stats
+ *   When non-NULL, it contains the current value for the statistics counters
+ *   enabled for the current MTR object.
+ * @param[out] stats_mask
+ *   When non-NULL, it contains the mask of statistics counter types that are
+ *   currently enabled for this MTR object, indicating which of the counters
+ *   retrieved with the *stats* structure are valid.
+ * @param[in] clear
+ *   When this parameter has a non-zero value, the statistics counters are
+ *   cleared (i.e. set to zero) immediately after they have been read,
+ *   otherwise the statistics counters are left untouched.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_mtr_stats_type
+ */
+int
+rte_mtr_stats_read(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_MTR_H__ */
diff --git a/lib/librte_ether/rte_mtr_driver.h b/lib/librte_ether/rte_mtr_driver.h
new file mode 100644
index 0000000..3798cf6
--- /dev/null
+++ b/lib/librte_ether/rte_mtr_driver.h
@@ -0,0 +1,188 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 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.
+ */
+
+#ifndef __INCLUDE_RTE_MTR_DRIVER_H__
+#define __INCLUDE_RTE_MTR_DRIVER_H__
+
+/**
+ * @file
+ * RTE Generic Traffic Metering and Policing API (Driver Side)
+ *
+ * This file provides implementation helpers for internal use by PMDs, they
+ * are not intended to be exposed to applications and are not subject to ABI
+ * versioning.
+ */
+
+#include <stdint.h>
+
+#include <rte_errno.h>
+#include "rte_ethdev.h"
+#include "rte_mtr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int (*rte_mtr_meter_profile_add_t)(struct rte_eth_dev *dev,
+	uint32_t meter_profile_id,
+	struct rte_mtr_meter_profile *profile,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter profile add */
+
+typedef int (*rte_mtr_meter_profile_delete_t)(struct rte_eth_dev *dev,
+	uint32_t meter_profile_id,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter profile delete */
+
+typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	struct rte_mtr_params *params,
+	int shared,
+	struct rte_mtr_error *error);
+/**< @internal MTR object create */
+
+typedef int (*rte_mtr_destroy_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error);
+/**< @internal MTR object destroy */
+
+typedef int (*rte_mtr_meter_profile_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_error *error);
+/**< @internal MTR object meter profile update */
+
+typedef int (*rte_mtr_policer_action_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	enum rte_mtr_color color,
+	enum rte_mtr_policer_action action,
+	struct rte_mtr_error *error);
+/**< @internal MTR object policer action update*/
+
+typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	uint64_t stats_mask,
+	struct rte_mtr_error *error);
+/**< @internal MTR object enabled stats update */
+
+typedef int (*rte_mtr_stats_read_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	struct rte_mtr_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error);
+/**< @internal MTR object stats read */
+
+struct rte_mtr_ops {
+	/** MTR meter profile add */
+	rte_mtr_meter_profile_add_t meter_profile_add;
+
+	/** MTR meter profile delete */
+	rte_mtr_meter_profile_delete_t meter_profile_delete;
+
+	/** MTR object create */
+	rte_mtr_create_t create;
+
+	/** MTR object destroy */
+	rte_mtr_destroy_t destroy;
+
+	/** MTR object meter profile update */
+	rte_mtr_meter_profile_update_t meter_profile_update;
+
+	/** MTR object policer action update */
+	rte_mtr_policer_action_update_t policer_action_update;
+
+	/** MTR object enabled stats update */
+	rte_mtr_stats_update_t stats_update;
+
+	/** MTR object stats read */
+	rte_mtr_stats_read_t stats_read;
+};
+
+/**
+ * Initialize generic error structure.
+ *
+ * This function also sets rte_errno to a given value.
+ *
+ * @param[out] error
+ *   Pointer to error structure (may be NULL).
+ * @param[in] code
+ *   Related error code (rte_errno).
+ * @param[in] type
+ *   Cause field and error type.
+ * @param[in] cause
+ *   Object responsible for the error.
+ * @param[in] message
+ *   Human-readable error message.
+ *
+ * @return
+ *   Error code.
+ */
+static inline int
+rte_mtr_error_set(struct rte_mtr_error *error,
+		   int code,
+		   enum rte_mtr_error_type type,
+		   const void *cause,
+		   const char *message)
+{
+	if (error) {
+		*error = (struct rte_mtr_error){
+			.type = type,
+			.cause = cause,
+			.message = message,
+		};
+	}
+	rte_errno = code;
+	return code;
+}
+
+/**
+ * Get generic traffic metering and policing operations structure from a port
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[out] error
+ *   Error details
+ *
+ * @return
+ *   The traffic metering and policing operations structure associated with
+ *   port_id on success, NULL otherwise.
+ */
+const struct rte_mtr_ops *
+rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_MTR_DRIVER_H__ */
-- 
2.7.4

^ permalink raw reply	[relevance 2%]

* Re: [dpdk-dev] [dpdk-techboard]  next techboard meeting (29th, August)
  @ 2017-08-28 15:04  3% ` Bruce Richardson
  2017-08-29 15:30  0%   ` Jerin Jacob
  0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2017-08-28 15:04 UTC (permalink / raw)
  To: Jerin Jacob; +Cc: techboard, dev

On Sun, Aug 27, 2017 at 06:54:35PM +0530, Jerin Jacob wrote:
> Hi All,
> 
> The next meeting of the tech board will happen on IRC #dpdk-board, at 3pm UTC, on 29th of August(Tuesday)
> 
> Agenda:
> 
> 1) Discussion on next tree requests
> a) Next tree for IPSec offload and maintainership
> http://dpdk.org/ml/archives/dev/2017-August/072995.html
> b) Next tree for cli
> http://dpdk.org/ml/archives/dev/2017-August/073343.html
> 
> 2) Approval of a policy for changes to the minimum DPDK requirements.
> e.g. like what was done with bumping IA min to SSE4.2 in last release.
> 

Proposal for a policy for this item, so as to hopefully speed up the
discussion at the meeting:

* Updates to the minimum HW requirements, i.e. those dropping support for
  hardware which was previously supported, should be treated as an ABI
  change, and follow that deprecation policy. Specifically:
  - change announced at least one release in advance
  - patches removing support for the older hardware should have at least
    three ACKs before being applied.

Regards,
/Bruce

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH 02/16] nfp: add specific pf probe function
  2017-08-24 16:20 10% ` [dpdk-dev] [PATCH 02/16] nfp: add specific pf probe function Alejandro Lucero
@ 2017-08-28 16:42  0%   ` Ferruh Yigit
  2017-08-31  9:23  0%     ` Alejandro Lucero
  0 siblings, 1 reply; 200+ results
From: Ferruh Yigit @ 2017-08-28 16:42 UTC (permalink / raw)
  To: Alejandro Lucero, dev

On 8/24/2017 5:20 PM, Alejandro Lucero wrote:
> Configuring the NFP PMD for using the PF requires access through the
> NSPU interface for device configuration. This patch adds a specific probe
> function for the PF which uses the NSPU interface. Just basic NSPU access
> is done by now reading the NSPU ABI version.
> 
> No ethernet port is created yet.
> 
> Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>

<...>

> +	/* Check NSP ABI version */
> +	if (nfp_nsp_get_abi_version(nspu_desc, &major, &minor) < 0) {
> +		RTE_LOG(INFO, PMD, "NFP NSP not present\n");
> +		goto no_abi;
> +	}
> +	PMD_INIT_LOG(INFO, "nspu ABI version: %d.%d\n", major, minor);
> +
> +	if (minor < 20) {
> +		RTE_LOG(INFO, PMD, "NFP NSP ABI version too old. Required 0.20 or higher\n");

I believe it worth documenting this detail in commit log and documentation.

<...>

>  
> -RTE_PMD_REGISTER_PCI(net_nfp, rte_nfp_net_pmd);
> -RTE_PMD_REGISTER_PCI_TABLE(net_nfp, pci_id_nfp_net_map);
> -RTE_PMD_REGISTER_KMOD_DEP(net_nfp, "* igb_uio | uio_pci_generic | vfio-pci");
> +RTE_PMD_REGISTER_PCI(net_nfp_pf, rte_nfp_net_pf_pmd);
> +RTE_PMD_REGISTER_PCI(net_nfp_vf, rte_nfp_net_vf_pmd);

Now pf and vf drivers are separated. For existing drivers this has been
documented in features file as another file (another column in table),
but we are looking for better representation for this.

What do you think, does two drivers has significant enough differences
to be documented as two different drivers?

> +RTE_PMD_REGISTER_PCI_TABLE(net_nfp_pf, pci_id_nfp_pf_net_map);
> +RTE_PMD_REGISTER_PCI_TABLE(net_nfp_vf, pci_id_nfp_vf_net_map);
> +RTE_PMD_REGISTER_KMOD_DEP(net_nfp_pf, "* igb_uio | uio_pci_generic | vfio");
> +RTE_PMD_REGISTER_KMOD_DEP(net_nfp_vf, "* igb_uio | uio_pci_generic | vfio");
>  
>  /*
>   * Local variables:
> 

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2] vhost: added user callbacks for socket open/close
  2017-08-25  9:22  0%   ` Jens Freimann
@ 2017-08-29  6:08  3%     ` Stojaczyk, DariuszX
  2017-08-30  6:33  0%       ` Jens Freimann
  0 siblings, 1 reply; 200+ results
From: Stojaczyk, DariuszX @ 2017-08-29  6:08 UTC (permalink / raw)
  To: 'Jens Freimann'; +Cc: dev, Wodkowski, PawelX, maxime.coquelin, yliu

Hi Jens,

> I'm still not sure I understand the use case. So just for my
> understanding: users need to distinct between "the device is going away
> temporarily, keep the connection" and "we're shutting down for good", is
> that it?

Yes, exactly.

> Maybe it's just me or maybe it means you could explain your example in the
> commit message a bit more.

Ok. How about the following commit message instead:
```
rte_vhost: added user callbacks for socket open/close

Added new callbacks to notify about socket connection status.
As destroy_device is used for virtqueue processing *pause* as
well as connection close, the user has no distinction between those.

Consider the following scenario:
rte_vhost: received SET_VRING_BASE message,
                  calling destroy_device() as usual

user:  end-user asks to remove the device (together with socket file),
          OK, device is not *in use* - that's NOT the behavior we want
          calling rte_vhost_driver_unregister() etc.

Instead of changing new_device/destroy_device callbacks and breaking
the ABI, a set of new functions new_connection/destroy_connection
has been added.
```

> Oh, and you should put the maintainers on Cc to get a faster review.

Thanks, I will!
Regards,
D. 

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC PATCH 2/4] ethdev: introduce Rx queue offloads API
    2017-08-23 12:21  0%   ` Ananyev, Konstantin
  2017-08-23 21:48  0%   ` Thomas Monjalon
@ 2017-08-29 12:50  0%   ` Ferruh Yigit
  2017-08-30  6:22  0%     ` Shahaf Shuler
  2017-08-29 13:11  0%   ` Ferruh Yigit
  3 siblings, 1 reply; 200+ results
From: Ferruh Yigit @ 2017-08-29 12:50 UTC (permalink / raw)
  To: Shahaf Shuler, dev

On 8/7/2017 11:54 AM, Shahaf Shuler wrote:
> Introduce a new API to configure Rx offloads.
> 
> The new API will re-use existing DEV_RX_OFFLOAD_* flags
> to enable the different offloads. This will ease the process
> of adding a new Rx offloads, as no ABI breakage is involved.
> In addition, the offload configuration can be done per queue,
> instead of per port.

If a device doesn't have capability to set the offload per queue how
should it behave, I think it is good to define this.

> 
> The Rx queue offload API can be used only with devices which advertize
> the RTE_ETH_DEV_RXQ_OFFLOAD capability.
> 
> The old Rx offloads API is kept for the meanwhile, in order to enable a
> smooth transition for PMDs and application to the new API.
> 
> Signed-off-by: Shahaf Shuler <shahafs@mellanox.com>

<...>

> @@ -357,7 +357,14 @@ struct rte_eth_rxmode {
>  		jumbo_frame      : 1, /**< Jumbo Frame Receipt enable. */
>  		hw_strip_crc     : 1, /**< Enable CRC stripping by hardware. */
>  		enable_scatter   : 1, /**< Enable scatter packets rx handler */
> -		enable_lro       : 1; /**< Enable LRO */
> +		enable_lro       : 1, /**< Enable LRO */
> +		ignore		 : 1;

what do you think making this variable more verbose, like
"ignore_rx_offloads"

"dev_conf.rxmode.ignore" doesn't say on its own what is ignored.

> +		/**
> +		 * When set the rxmode offloads should be ignored,
> +		 * instead the Rx offloads will be set on rte_eth_rxq_conf.
> +		 * This bit is temporary till rxmode Rx offloads API will
> +		 * be deprecated.
> +		 */
>  };

<...>

> +/** Device supports the rte_eth_rxq_conf offloads API */
> +#define RTE_ETH_DEV_RXQ_OFFLOAD 0x0010
Since this is temporary flag and with current implementation this is
local to library, should we put this into public header?

Later when all PMDs implemented this new method and we want to remove
the flag, can we remove them or do we have to keep them reserved for any
conflict for further new values?

I guess this should be part of missing pmd-ethdev interface file
(rte_ethdev_pmd.h ?).

>  
>  /**
>   * @internal
> 

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 04/12] vdev: move to drivers/bus
  @ 2017-08-29 13:04  3%   ` Gaëtan Rivet
  2017-08-29 22:47  0%     ` Tan, Jianfeng
  0 siblings, 1 reply; 200+ results
From: Gaëtan Rivet @ 2017-08-29 13:04 UTC (permalink / raw)
  To: Jianfeng Tan
  Cc: dev, bruce.richardson, konstantin.ananyev, pablo.de.lara.guarch,
	thomas, yliu, maxime.coquelin, mtetsuyah, ferruh.yigit

On Fri, Aug 25, 2017 at 09:40:44AM +0000, Jianfeng Tan wrote:
> Move the vdev bus from lib/librte_eal to drivers/bus.
> 
> As the crypto vdev helper function refers to data structure
> in rte_vdev.h, so we move those helper function into drivers/bus
> too.
> 
> Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
> ---
>  config/common_base                        |   5 +
>  drivers/bus/Makefile                      |   2 +
>  drivers/bus/vdev/Makefile                 |  57 +++++
>  drivers/bus/vdev/rte_bus_vdev_version.map |  10 +
>  drivers/bus/vdev/rte_cryptodev_vdev.c     | 154 ++++++++++++++
>  drivers/bus/vdev/rte_cryptodev_vdev.h     | 100 +++++++++
>  drivers/bus/vdev/rte_vdev.h               | 153 +++++++++++++
>  drivers/bus/vdev/vdev.c                   | 342 ++++++++++++++++++++++++++++++
>  lib/librte_cryptodev/Makefile             |   2 -
>  lib/librte_cryptodev/rte_cryptodev_vdev.c | 154 --------------
>  lib/librte_cryptodev/rte_cryptodev_vdev.h | 100 ---------
>  lib/librte_eal/bsdapp/eal/Makefile        |   1 -
>  lib/librte_eal/common/Makefile            |   2 +-
>  lib/librte_eal/common/eal_common_vdev.c   | 342 ------------------------------
>  lib/librte_eal/common/include/rte_dev.h   |  24 +--
>  lib/librte_eal/common/include/rte_vdev.h  | 131 ------------
>  lib/librte_eal/linuxapp/eal/Makefile      |   1 -
>  mk/rte.app.mk                             |   1 +
>  18 files changed, 826 insertions(+), 755 deletions(-)
>  create mode 100644 drivers/bus/vdev/Makefile
>  create mode 100644 drivers/bus/vdev/rte_bus_vdev_version.map
>  create mode 100644 drivers/bus/vdev/rte_cryptodev_vdev.c
>  create mode 100644 drivers/bus/vdev/rte_cryptodev_vdev.h
>  create mode 100644 drivers/bus/vdev/rte_vdev.h
>  create mode 100644 drivers/bus/vdev/vdev.c
>  delete mode 100644 lib/librte_cryptodev/rte_cryptodev_vdev.c
>  delete mode 100644 lib/librte_cryptodev/rte_cryptodev_vdev.h
>  delete mode 100644 lib/librte_eal/common/eal_common_vdev.c
>  delete mode 100644 lib/librte_eal/common/include/rte_vdev.h
> 
> diff --git a/config/common_base b/config/common_base
> index 5e97a08..aca0994 100644
> --- a/config/common_base
> +++ b/config/common_base
> @@ -750,3 +750,8 @@ CONFIG_RTE_APP_CRYPTO_PERF=y
>  # Compile the eventdev application
>  #
>  CONFIG_RTE_APP_EVENTDEV=y
> +
> +#
> +# Compile the vdev bus
> +#
> +CONFIG_RTE_LIBRTE_VDEV=y

Why not CONFIG_RTE_LIBRTE_VDEV_BUS?
It would seem more consistent.

> diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
> index 0224214..9b6d45e 100644
> --- a/drivers/bus/Makefile
> +++ b/drivers/bus/Makefile
> @@ -35,4 +35,6 @@ core-libs := librte_eal librte_mbuf librte_mempool librte_ring librte_ether
>  DIRS-$(CONFIG_RTE_LIBRTE_FSLMC_BUS) += fslmc
>  DEPDIRS-fslmc = $(core-libs)
>  
> +DIRS-$(CONFIG_RTE_LIBRTE_VDEV) += vdev
> +
>  include $(RTE_SDK)/mk/rte.subdir.mk
> diff --git a/drivers/bus/vdev/Makefile b/drivers/bus/vdev/Makefile
> new file mode 100644
> index 0000000..30c4813
> --- /dev/null
> +++ b/drivers/bus/vdev/Makefile
> @@ -0,0 +1,57 @@
> +#   BSD LICENSE
> +#
> +#   Copyright(c) 2017 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_SDK)/mk/rte.vars.mk
> +
> +#
> +# library name
> +#
> +LIB = librte_bus_vdev.a
> +
> +CFLAGS += -O3
> +CFLAGS += $(WERROR_FLAGS)
> +
> +# versioning export map
> +EXPORT_MAP := rte_bus_vdev_version.map
> +
> +# library version
> +LIBABIVER := 1
> +
> +SRCS-y += vdev.c
> +SRCS-y += rte_cryptodev_vdev.c
> +
> +#
> +# Export include files
> +#
> +SYMLINK-y-include += rte_vdev.h
> +SYMLINK-y-include += rte_cryptodev_vdev.h
> +

Let's say the cryptodev lib must be updated.
I understand the need to move rte_cryptodev_vdev.h outside
librte_cryptodev, but I guess this exposes the vdev bus to ABI / API
instability due to a third-party subsystem?

I did something somewhat similar for PCI:
http://dpdk.org/ml/archives/dev/2017-August/073525.html

I don't know which solution is best, but something certainly needs to be
done.

---

Beside the `why`, about the `how`: shouldn't this file compilation and
symlink be conditioned to CONFIG_RTE_LIBRTE_CRYPTODEV=y?

i.e.: SYMLINK-$(CONFIG_RTE_LIBRTE_CRYPTODEV)-include += rte_cryptodev_vdev.h

> +include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/drivers/bus/vdev/rte_bus_vdev_version.map b/drivers/bus/vdev/rte_bus_vdev_version.map
> new file mode 100644
> index 0000000..69740c3
> --- /dev/null
> +++ b/drivers/bus/vdev/rte_bus_vdev_version.map
> @@ -0,0 +1,10 @@
> +DPDK_17.11 {
> +	global:
> +
> +	rte_vdev_init;
> +	rte_vdev_register;
> +	rte_vdev_uninit;
> +	rte_vdev_unregister;
> +	rte_cryptodev_vdev_pmd_init
> +	rte_cryptodev_vdev_parse_init_params
> +};
> diff --git a/drivers/bus/vdev/rte_cryptodev_vdev.c b/drivers/bus/vdev/rte_cryptodev_vdev.c
> new file mode 100644
> index 0000000..fd308b4
> --- /dev/null
> +++ b/drivers/bus/vdev/rte_cryptodev_vdev.c
> @@ -0,0 +1,154 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2017 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 the copyright holder 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_cryptodev_vdev.h"
> +#include "rte_cryptodev_pci.h"
> +#include "rte_cryptodev_pmd.h"
> +
> +/**
> + * Parse name from argument
> + */
> +static int
> +rte_cryptodev_vdev_parse_name_arg(const char *key __rte_unused,
> +		const char *value, void *extra_args)
> +{
> +	struct rte_crypto_vdev_init_params *params = extra_args;
> +
> +	if (strlen(value) >= RTE_CRYPTODEV_NAME_MAX_LEN - 1) {
> +		CDEV_LOG_ERR("Invalid name %s, should be less than "
> +				"%u bytes", value,
> +				RTE_CRYPTODEV_NAME_MAX_LEN - 1);
> +		return -1;
> +	}
> +
> +	strncpy(params->name, value, RTE_CRYPTODEV_NAME_MAX_LEN);
> +
> +	return 0;
> +}
> +
> +/**
> + * Parse integer from argument
> + */
> +static int
> +rte_cryptodev_vdev_parse_integer_arg(const char *key __rte_unused,
> +		const char *value, void *extra_args)
> +{
> +	int *i = extra_args;
> +
> +	*i = atoi(value);
> +	if (*i < 0) {
> +		CDEV_LOG_ERR("Argument has to be positive.");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +struct rte_cryptodev *
> +rte_cryptodev_vdev_pmd_init(const char *name, size_t dev_private_size,
> +		int socket_id, struct rte_vdev_device *vdev)
> +{
> +	struct rte_cryptodev *cryptodev;
> +
> +	/* allocate device structure */
> +	cryptodev = rte_cryptodev_pmd_allocate(name, socket_id);
> +	if (cryptodev == NULL)
> +		return NULL;
> +
> +	/* allocate private device structure */
> +	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
> +		cryptodev->data->dev_private =
> +				rte_zmalloc_socket("cryptodev device private",
> +						dev_private_size,
> +						RTE_CACHE_LINE_SIZE,
> +						socket_id);
> +
> +		if (cryptodev->data->dev_private == NULL)
> +			rte_panic("Cannot allocate memzone for private device"
> +					" data");
> +	}
> +
> +	cryptodev->device = &vdev->device;
> +
> +	/* initialise user call-back tail queue */
> +	TAILQ_INIT(&(cryptodev->link_intr_cbs));
> +
> +	return cryptodev;
> +}
> +
> +int
> +rte_cryptodev_vdev_parse_init_params(struct rte_crypto_vdev_init_params *params,
> +		const char *input_args)
> +{
> +	struct rte_kvargs *kvlist = NULL;
> +	int ret = 0;
> +
> +	if (params == NULL)
> +		return -EINVAL;
> +
> +	if (input_args) {
> +		kvlist = rte_kvargs_parse(input_args,
> +				cryptodev_vdev_valid_params);
> +		if (kvlist == NULL)
> +			return -1;
> +
> +		ret = rte_kvargs_process(kvlist,
> +					RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
> +					&rte_cryptodev_vdev_parse_integer_arg,
> +					&params->max_nb_queue_pairs);
> +		if (ret < 0)
> +			goto free_kvlist;
> +
> +		ret = rte_kvargs_process(kvlist,
> +					RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
> +					&rte_cryptodev_vdev_parse_integer_arg,
> +					&params->max_nb_sessions);
> +		if (ret < 0)
> +			goto free_kvlist;
> +
> +		ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_SOCKET_ID,
> +					&rte_cryptodev_vdev_parse_integer_arg,
> +					&params->socket_id);
> +		if (ret < 0)
> +			goto free_kvlist;
> +
> +		ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_NAME,
> +					&rte_cryptodev_vdev_parse_name_arg,
> +					params);
> +		if (ret < 0)
> +			goto free_kvlist;
> +	}
> +
> +free_kvlist:
> +	rte_kvargs_free(kvlist);
> +	return ret;
> +}
> diff --git a/drivers/bus/vdev/rte_cryptodev_vdev.h b/drivers/bus/vdev/rte_cryptodev_vdev.h
> new file mode 100644
> index 0000000..94ab9d3
> --- /dev/null
> +++ b/drivers/bus/vdev/rte_cryptodev_vdev.h
> @@ -0,0 +1,100 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2017 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 the copyright holder 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.
> + */
> +
> +#ifndef _RTE_CRYPTODEV_VDEV_H_
> +#define _RTE_CRYPTODEV_VDEV_H_
> +
> +#include <rte_vdev.h>
> +#include <inttypes.h>
> +
> +#include "rte_cryptodev.h"
> +
> +#define RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_QUEUE_PAIRS	8
> +#define RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_SESSIONS	2048
> +
> +#define RTE_CRYPTODEV_VDEV_NAME				("name")
> +#define RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG		("max_nb_queue_pairs")
> +#define RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG		("max_nb_sessions")
> +#define RTE_CRYPTODEV_VDEV_SOCKET_ID			("socket_id")
> +
> +static const char * const cryptodev_vdev_valid_params[] = {
> +	RTE_CRYPTODEV_VDEV_NAME,
> +	RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
> +	RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
> +	RTE_CRYPTODEV_VDEV_SOCKET_ID
> +};
> +
> +/**
> + * @internal
> + * Initialisation parameters for virtual crypto devices
> + */
> +struct rte_crypto_vdev_init_params {
> +	unsigned int max_nb_queue_pairs;
> +	unsigned int max_nb_sessions;
> +	uint8_t socket_id;
> +	char name[RTE_CRYPTODEV_NAME_MAX_LEN];
> +};
> +
> +/**
> + * @internal
> + * Creates a new virtual crypto device and returns the pointer
> + * to that device.
> + *
> + * @param	name			PMD type name
> + * @param	dev_private_size	Size of crypto PMDs private data
> + * @param	socket_id		Socket to allocate resources on.
> + * @param	vdev			Pointer to virtual device structure.
> + *
> + * @return
> + *   - Cryptodev pointer if device is successfully created.
> + *   - NULL if device cannot be created.
> + */
> +struct rte_cryptodev *
> +rte_cryptodev_vdev_pmd_init(const char *name, size_t dev_private_size,
> +		int socket_id, struct rte_vdev_device *vdev);
> +
> +/**
> + * @internal
> + * Parse virtual device initialisation parameters input arguments
> + *
> + * @params	params		Initialisation parameters with defaults set.
> + * @params	input_args	Command line arguments
> + *
> + * @return
> + * 0 on successful parse
> + * <0 on failure to parse
> + */
> +int
> +rte_cryptodev_vdev_parse_init_params(struct rte_crypto_vdev_init_params *params,
> +		const char *input_args);
> +
> +#endif /* _RTE_CRYPTODEV_VDEV_H_ */
> diff --git a/drivers/bus/vdev/rte_vdev.h b/drivers/bus/vdev/rte_vdev.h
> new file mode 100644
> index 0000000..41762b8
> --- /dev/null
> +++ b/drivers/bus/vdev/rte_vdev.h
> @@ -0,0 +1,153 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2016 RehiveTech. 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 RehiveTech 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.
> + */
> +
> +#ifndef RTE_VDEV_H
> +#define RTE_VDEV_H
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#include <sys/queue.h>
> +#include <rte_dev.h>
> +#include <rte_devargs.h>
> +
> +struct rte_vdev_device {
> +	TAILQ_ENTRY(rte_vdev_device) next;      /**< Next attached vdev */
> +	struct rte_device device;               /**< Inherit core device */
> +};
> +
> +/**
> + * @internal
> + * Helper macro for drivers that need to convert to struct rte_vdev_device.
> + */
> +#define RTE_DEV_TO_VDEV(ptr) \
> +	container_of(ptr, struct rte_vdev_device, device)
> +
> +static inline const char *
> +rte_vdev_device_name(const struct rte_vdev_device *dev)
> +{
> +	if (dev && dev->device.name)
> +		return dev->device.name;
> +	return NULL;
> +}
> +
> +static inline const char *
> +rte_vdev_device_args(const struct rte_vdev_device *dev)
> +{
> +	if (dev && dev->device.devargs)
> +		return dev->device.devargs->args;
> +	return "";
> +}
> +
> +/** Double linked list of virtual device drivers. */
> +TAILQ_HEAD(vdev_driver_list, rte_vdev_driver);
> +
> +/**
> + * Probe function called for each virtual device driver once.
> + */
> +typedef int (rte_vdev_probe_t)(struct rte_vdev_device *dev);
> +
> +/**
> + * Remove function called for each virtual device driver once.
> + */
> +typedef int (rte_vdev_remove_t)(struct rte_vdev_device *dev);
> +
> +/**
> + * A virtual device driver abstraction.
> + */
> +struct rte_vdev_driver {
> +	TAILQ_ENTRY(rte_vdev_driver) next; /**< Next in list. */
> +	struct rte_driver driver;      /**< Inherited general driver. */
> +	rte_vdev_probe_t *probe;       /**< Virtual device probe function. */
> +	rte_vdev_remove_t *remove;     /**< Virtual device remove function. */
> +};
> +
> +/**
> + * Register a virtual device driver.
> + *
> + * @param driver
> + *   A pointer to a rte_vdev_driver structure describing the driver
> + *   to be registered.
> + */
> +void rte_vdev_register(struct rte_vdev_driver *driver);
> +
> +/**
> + * Unregister a virtual device driver.
> + *
> + * @param driver
> + *   A pointer to a rte_vdev_driver structure describing the driver
> + *   to be unregistered.
> + */
> +void rte_vdev_unregister(struct rte_vdev_driver *driver);
> +
> +#define RTE_PMD_REGISTER_VDEV(nm, vdrv)\
> +RTE_INIT(vdrvinitfn_ ##vdrv);\
> +static const char *vdrvinit_ ## nm ## _alias;\
> +static void vdrvinitfn_ ##vdrv(void)\
> +{\
> +	(vdrv).driver.name = RTE_STR(nm);\
> +	(vdrv).driver.alias = vdrvinit_ ## nm ## _alias;\
> +	rte_vdev_register(&vdrv);\
> +} \
> +RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
> +
> +#define RTE_PMD_REGISTER_ALIAS(nm, alias)\
> +static const char *vdrvinit_ ## nm ## _alias = RTE_STR(alias)
> +
> +/**
> + * Initialize a driver specified by name.
> + *
> + * @param name
> + *   The pointer to a driver name to be initialized.
> + * @param args
> + *   The pointer to arguments used by driver initialization.
> + * @return
> + *  0 on success, negative on error
> + */
> +int rte_vdev_init(const char *name, const char *args);
> +
> +/**
> + * Uninitalize a driver specified by name.
> + *
> + * @param name
> + *   The pointer to a driver name to be initialized.
> + * @return
> + *  0 on success, negative on error
> + */
> +int rte_vdev_uninit(const char *name);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/drivers/bus/vdev/vdev.c b/drivers/bus/vdev/vdev.c
> new file mode 100644
> index 0000000..f7e547a
> --- /dev/null
> +++ b/drivers/bus/vdev/vdev.c
> @@ -0,0 +1,342 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2016 RehiveTech. 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 RehiveTech 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 <string.h>
> +#include <inttypes.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stdint.h>
> +#include <stdbool.h>
> +#include <sys/queue.h>
> +
> +#include <rte_eal.h>
> +#include <rte_dev.h>
> +#include <rte_bus.h>
> +#include <rte_vdev.h>
> +#include <rte_common.h>
> +#include <rte_devargs.h>
> +#include <rte_memory.h>
> +#include <rte_errno.h>
> +
> +/* Forward declare to access virtual bus name */
> +static struct rte_bus rte_vdev_bus;
> +
> +/** Double linked list of virtual device drivers. */
> +TAILQ_HEAD(vdev_device_list, rte_vdev_device);
> +
> +static struct vdev_device_list vdev_device_list =
> +	TAILQ_HEAD_INITIALIZER(vdev_device_list);
> +struct vdev_driver_list vdev_driver_list =
> +	TAILQ_HEAD_INITIALIZER(vdev_driver_list);
> +
> +/* register a driver */
> +void
> +rte_vdev_register(struct rte_vdev_driver *driver)
> +{
> +	TAILQ_INSERT_TAIL(&vdev_driver_list, driver, next);
> +}
> +
> +/* unregister a driver */
> +void
> +rte_vdev_unregister(struct rte_vdev_driver *driver)
> +{
> +	TAILQ_REMOVE(&vdev_driver_list, driver, next);
> +}
> +
> +static int
> +vdev_parse(const char *name, void *addr)
> +{
> +	struct rte_vdev_driver **out = addr;
> +	struct rte_vdev_driver *driver = NULL;
> +
> +	TAILQ_FOREACH(driver, &vdev_driver_list, next) {
> +		if (strncmp(driver->driver.name, name,
> +			    strlen(driver->driver.name)) == 0)
> +			break;
> +		if (driver->driver.alias &&
> +		    strncmp(driver->driver.alias, name,
> +			    strlen(driver->driver.alias)) == 0)
> +			break;
> +	}
> +	if (driver != NULL &&
> +	    addr != NULL)
> +		*out = driver;
> +	return driver == NULL;
> +}
> +
> +static int
> +vdev_probe_all_drivers(struct rte_vdev_device *dev)
> +{
> +	const char *name;
> +	struct rte_vdev_driver *driver;
> +	int ret;
> +
> +	name = rte_vdev_device_name(dev);
> +
> +	RTE_LOG(DEBUG, EAL, "Search driver %s to probe device %s\n", name,
> +		rte_vdev_device_name(dev));
> +
> +	if (vdev_parse(name, &driver))
> +		return -1;
> +	dev->device.driver = &driver->driver;
> +	ret = driver->probe(dev);
> +	if (ret)
> +		dev->device.driver = NULL;
> +	return ret;
> +}
> +
> +static struct rte_vdev_device *
> +find_vdev(const char *name)
> +{
> +	struct rte_vdev_device *dev;
> +
> +	if (!name)
> +		return NULL;
> +
> +	TAILQ_FOREACH(dev, &vdev_device_list, next) {
> +		const char *devname = rte_vdev_device_name(dev);
> +		if (!strncmp(devname, name, strlen(name)))
> +			return dev;
> +	}
> +
> +	return NULL;
> +}
> +
> +static struct rte_devargs *
> +alloc_devargs(const char *name, const char *args)
> +{
> +	struct rte_devargs *devargs;
> +	int ret;
> +
> +	devargs = calloc(1, sizeof(*devargs));
> +	if (!devargs)
> +		return NULL;
> +
> +	devargs->bus = &rte_vdev_bus;
> +	if (args)
> +		devargs->args = strdup(args);
> +	else
> +		devargs->args = strdup("");
> +
> +	ret = snprintf(devargs->name, sizeof(devargs->name), "%s", name);
> +	if (ret < 0 || ret >= (int)sizeof(devargs->name)) {
> +		free(devargs->args);
> +		free(devargs);
> +		return NULL;
> +	}
> +
> +	return devargs;
> +}
> +
> +int
> +rte_vdev_init(const char *name, const char *args)
> +{
> +	struct rte_vdev_device *dev;
> +	struct rte_devargs *devargs;
> +	int ret;
> +
> +	if (name == NULL)
> +		return -EINVAL;
> +
> +	dev = find_vdev(name);
> +	if (dev)
> +		return -EEXIST;
> +
> +	devargs = alloc_devargs(name, args);
> +	if (!devargs)
> +		return -ENOMEM;
> +
> +	dev = calloc(1, sizeof(*dev));
> +	if (!dev) {
> +		ret = -ENOMEM;
> +		goto fail;
> +	}
> +
> +	dev->device.devargs = devargs;
> +	dev->device.numa_node = SOCKET_ID_ANY;
> +	dev->device.name = devargs->name;
> +
> +	ret = vdev_probe_all_drivers(dev);
> +	if (ret) {
> +		if (ret > 0)
> +			RTE_LOG(ERR, EAL, "no driver found for %s\n", name);
> +		goto fail;
> +	}
> +
> +	TAILQ_INSERT_TAIL(&devargs_list, devargs, next);
> +
> +	TAILQ_INSERT_TAIL(&vdev_device_list, dev, next);
> +	return 0;
> +
> +fail:
> +	free(devargs->args);
> +	free(devargs);
> +	free(dev);
> +	return ret;
> +}
> +
> +static int
> +vdev_remove_driver(struct rte_vdev_device *dev)
> +{
> +	const char *name = rte_vdev_device_name(dev);
> +	const struct rte_vdev_driver *driver;
> +
> +	if (!dev->device.driver) {
> +		RTE_LOG(DEBUG, EAL, "no driver attach to device %s\n", name);
> +		return 1;
> +	}
> +
> +	driver = container_of(dev->device.driver, const struct rte_vdev_driver,
> +		driver);
> +	return driver->remove(dev);
> +}
> +
> +int
> +rte_vdev_uninit(const char *name)
> +{
> +	struct rte_vdev_device *dev;
> +	struct rte_devargs *devargs;
> +	int ret;
> +
> +	if (name == NULL)
> +		return -EINVAL;
> +
> +	dev = find_vdev(name);
> +	if (!dev)
> +		return -ENOENT;
> +
> +	devargs = dev->device.devargs;
> +
> +	ret = vdev_remove_driver(dev);
> +	if (ret)
> +		return ret;
> +
> +	TAILQ_REMOVE(&vdev_device_list, dev, next);
> +
> +	TAILQ_REMOVE(&devargs_list, devargs, next);
> +
> +	free(devargs->args);
> +	free(devargs);
> +	free(dev);
> +	return 0;
> +}
> +
> +static int
> +vdev_scan(void)
> +{
> +	struct rte_vdev_device *dev;
> +	struct rte_devargs *devargs;
> +
> +	/* for virtual devices we scan the devargs_list populated via cmdline */
> +	TAILQ_FOREACH(devargs, &devargs_list, next) {
> +
> +		if (devargs->bus != &rte_vdev_bus)
> +			continue;
> +
> +		dev = find_vdev(devargs->name);
> +		if (dev)
> +			continue;
> +
> +		dev = calloc(1, sizeof(*dev));
> +		if (!dev)
> +			return -1;
> +
> +		dev->device.devargs = devargs;
> +		dev->device.numa_node = SOCKET_ID_ANY;
> +		dev->device.name = devargs->name;
> +
> +		TAILQ_INSERT_TAIL(&vdev_device_list, dev, next);
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +vdev_probe(void)
> +{
> +	struct rte_vdev_device *dev;
> +
> +	/* call the init function for each virtual device */
> +	TAILQ_FOREACH(dev, &vdev_device_list, next) {
> +
> +		if (dev->device.driver)
> +			continue;
> +
> +		if (vdev_probe_all_drivers(dev)) {
> +			RTE_LOG(ERR, EAL, "failed to initialize %s device\n",
> +				rte_vdev_device_name(dev));
> +			return -1;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static struct rte_device *
> +vdev_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,
> +		 const void *data)
> +{
> +	struct rte_vdev_device *dev;
> +
> +	TAILQ_FOREACH(dev, &vdev_device_list, next) {
> +		if (start && &dev->device == start) {
> +			start = NULL;
> +			continue;
> +		}
> +		if (cmp(&dev->device, data) == 0)
> +			return &dev->device;
> +	}
> +	return NULL;
> +}
> +
> +static int
> +vdev_plug(struct rte_device *dev)
> +{
> +	return vdev_probe_all_drivers(RTE_DEV_TO_VDEV(dev));
> +}
> +
> +static int
> +vdev_unplug(struct rte_device *dev)
> +{
> +	return rte_vdev_uninit(dev->name);
> +}
> +
> +static struct rte_bus rte_vdev_bus = {
> +	.scan = vdev_scan,
> +	.probe = vdev_probe,
> +	.find_device = vdev_find_device,
> +	.plug = vdev_plug,
> +	.unplug = vdev_unplug,
> +	.parse = vdev_parse,
> +};
> +
> +RTE_REGISTER_BUS(vdev, rte_vdev_bus);
> diff --git a/lib/librte_cryptodev/Makefile b/lib/librte_cryptodev/Makefile
> index 301c78d..4f70719 100644
> --- a/lib/librte_cryptodev/Makefile
> +++ b/lib/librte_cryptodev/Makefile
> @@ -42,14 +42,12 @@ CFLAGS += $(WERROR_FLAGS)
>  
>  # library source files
>  SRCS-y += rte_cryptodev.c rte_cryptodev_pmd.c
> -SRCS-y += rte_cryptodev_vdev.c
>  
>  # export include files
>  SYMLINK-y-include += rte_crypto.h
>  SYMLINK-y-include += rte_crypto_sym.h
>  SYMLINK-y-include += rte_cryptodev.h
>  SYMLINK-y-include += rte_cryptodev_pmd.h
> -SYMLINK-y-include += rte_cryptodev_vdev.h
>  SYMLINK-y-include += rte_cryptodev_pci.h
>  
>  # versioning export map
> diff --git a/lib/librte_cryptodev/rte_cryptodev_vdev.c b/lib/librte_cryptodev/rte_cryptodev_vdev.c
> deleted file mode 100644
> index fd308b4..0000000
> --- a/lib/librte_cryptodev/rte_cryptodev_vdev.c
> +++ /dev/null
> @@ -1,154 +0,0 @@
> -/*-
> - *   BSD LICENSE
> - *
> - *   Copyright(c) 2017 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 the copyright holder 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_cryptodev_vdev.h"
> -#include "rte_cryptodev_pci.h"
> -#include "rte_cryptodev_pmd.h"
> -
> -/**
> - * Parse name from argument
> - */
> -static int
> -rte_cryptodev_vdev_parse_name_arg(const char *key __rte_unused,
> -		const char *value, void *extra_args)
> -{
> -	struct rte_crypto_vdev_init_params *params = extra_args;
> -
> -	if (strlen(value) >= RTE_CRYPTODEV_NAME_MAX_LEN - 1) {
> -		CDEV_LOG_ERR("Invalid name %s, should be less than "
> -				"%u bytes", value,
> -				RTE_CRYPTODEV_NAME_MAX_LEN - 1);
> -		return -1;
> -	}
> -
> -	strncpy(params->name, value, RTE_CRYPTODEV_NAME_MAX_LEN);
> -
> -	return 0;
> -}
> -
> -/**
> - * Parse integer from argument
> - */
> -static int
> -rte_cryptodev_vdev_parse_integer_arg(const char *key __rte_unused,
> -		const char *value, void *extra_args)
> -{
> -	int *i = extra_args;
> -
> -	*i = atoi(value);
> -	if (*i < 0) {
> -		CDEV_LOG_ERR("Argument has to be positive.");
> -		return -1;
> -	}
> -
> -	return 0;
> -}
> -
> -struct rte_cryptodev *
> -rte_cryptodev_vdev_pmd_init(const char *name, size_t dev_private_size,
> -		int socket_id, struct rte_vdev_device *vdev)
> -{
> -	struct rte_cryptodev *cryptodev;
> -
> -	/* allocate device structure */
> -	cryptodev = rte_cryptodev_pmd_allocate(name, socket_id);
> -	if (cryptodev == NULL)
> -		return NULL;
> -
> -	/* allocate private device structure */
> -	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
> -		cryptodev->data->dev_private =
> -				rte_zmalloc_socket("cryptodev device private",
> -						dev_private_size,
> -						RTE_CACHE_LINE_SIZE,
> -						socket_id);
> -
> -		if (cryptodev->data->dev_private == NULL)
> -			rte_panic("Cannot allocate memzone for private device"
> -					" data");
> -	}
> -
> -	cryptodev->device = &vdev->device;
> -
> -	/* initialise user call-back tail queue */
> -	TAILQ_INIT(&(cryptodev->link_intr_cbs));
> -
> -	return cryptodev;
> -}
> -
> -int
> -rte_cryptodev_vdev_parse_init_params(struct rte_crypto_vdev_init_params *params,
> -		const char *input_args)
> -{
> -	struct rte_kvargs *kvlist = NULL;
> -	int ret = 0;
> -
> -	if (params == NULL)
> -		return -EINVAL;
> -
> -	if (input_args) {
> -		kvlist = rte_kvargs_parse(input_args,
> -				cryptodev_vdev_valid_params);
> -		if (kvlist == NULL)
> -			return -1;
> -
> -		ret = rte_kvargs_process(kvlist,
> -					RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
> -					&rte_cryptodev_vdev_parse_integer_arg,
> -					&params->max_nb_queue_pairs);
> -		if (ret < 0)
> -			goto free_kvlist;
> -
> -		ret = rte_kvargs_process(kvlist,
> -					RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
> -					&rte_cryptodev_vdev_parse_integer_arg,
> -					&params->max_nb_sessions);
> -		if (ret < 0)
> -			goto free_kvlist;
> -
> -		ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_SOCKET_ID,
> -					&rte_cryptodev_vdev_parse_integer_arg,
> -					&params->socket_id);
> -		if (ret < 0)
> -			goto free_kvlist;
> -
> -		ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_NAME,
> -					&rte_cryptodev_vdev_parse_name_arg,
> -					params);
> -		if (ret < 0)
> -			goto free_kvlist;
> -	}
> -
> -free_kvlist:
> -	rte_kvargs_free(kvlist);
> -	return ret;
> -}
> diff --git a/lib/librte_cryptodev/rte_cryptodev_vdev.h b/lib/librte_cryptodev/rte_cryptodev_vdev.h
> deleted file mode 100644
> index 94ab9d3..0000000
> --- a/lib/librte_cryptodev/rte_cryptodev_vdev.h
> +++ /dev/null
> @@ -1,100 +0,0 @@
> -/*-
> - *   BSD LICENSE
> - *
> - *   Copyright(c) 2017 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 the copyright holder 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.
> - */
> -
> -#ifndef _RTE_CRYPTODEV_VDEV_H_
> -#define _RTE_CRYPTODEV_VDEV_H_
> -
> -#include <rte_vdev.h>
> -#include <inttypes.h>
> -
> -#include "rte_cryptodev.h"
> -
> -#define RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_QUEUE_PAIRS	8
> -#define RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_SESSIONS	2048
> -
> -#define RTE_CRYPTODEV_VDEV_NAME				("name")
> -#define RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG		("max_nb_queue_pairs")
> -#define RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG		("max_nb_sessions")
> -#define RTE_CRYPTODEV_VDEV_SOCKET_ID			("socket_id")
> -
> -static const char * const cryptodev_vdev_valid_params[] = {
> -	RTE_CRYPTODEV_VDEV_NAME,
> -	RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
> -	RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
> -	RTE_CRYPTODEV_VDEV_SOCKET_ID
> -};
> -
> -/**
> - * @internal
> - * Initialisation parameters for virtual crypto devices
> - */
> -struct rte_crypto_vdev_init_params {
> -	unsigned int max_nb_queue_pairs;
> -	unsigned int max_nb_sessions;
> -	uint8_t socket_id;
> -	char name[RTE_CRYPTODEV_NAME_MAX_LEN];
> -};
> -
> -/**
> - * @internal
> - * Creates a new virtual crypto device and returns the pointer
> - * to that device.
> - *
> - * @param	name			PMD type name
> - * @param	dev_private_size	Size of crypto PMDs private data
> - * @param	socket_id		Socket to allocate resources on.
> - * @param	vdev			Pointer to virtual device structure.
> - *
> - * @return
> - *   - Cryptodev pointer if device is successfully created.
> - *   - NULL if device cannot be created.
> - */
> -struct rte_cryptodev *
> -rte_cryptodev_vdev_pmd_init(const char *name, size_t dev_private_size,
> -		int socket_id, struct rte_vdev_device *vdev);
> -
> -/**
> - * @internal
> - * Parse virtual device initialisation parameters input arguments
> - *
> - * @params	params		Initialisation parameters with defaults set.
> - * @params	input_args	Command line arguments
> - *
> - * @return
> - * 0 on successful parse
> - * <0 on failure to parse
> - */
> -int
> -rte_cryptodev_vdev_parse_init_params(struct rte_crypto_vdev_init_params *params,
> -		const char *input_args);
> -
> -#endif /* _RTE_CRYPTODEV_VDEV_H_ */
> diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
> index 005019e..6fee587 100644
> --- a/lib/librte_eal/bsdapp/eal/Makefile
> +++ b/lib/librte_eal/bsdapp/eal/Makefile
> @@ -68,7 +68,6 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_timer.c
>  SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memzone.c
>  SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_log.c
>  SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_launch.c
> -SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_vdev.c
>  SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_pci.c
>  SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_pci_uio.c
>  SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memory.c
> diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
> index e8fd67a..7eeb06a 100644
> --- a/lib/librte_eal/common/Makefile
> +++ b/lib/librte_eal/common/Makefile
> @@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
>  INC += rte_tailq.h rte_interrupts.h rte_alarm.h
>  INC += rte_string_fns.h rte_version.h
>  INC += rte_eal_memconfig.h rte_malloc_heap.h
> -INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
> +INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h
>  INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
>  INC += rte_malloc.h rte_keepalive.h rte_time.h
>  INC += rte_service.h rte_service_component.h
> diff --git a/lib/librte_eal/common/eal_common_vdev.c b/lib/librte_eal/common/eal_common_vdev.c
> deleted file mode 100644
> index f7e547a..0000000
> --- a/lib/librte_eal/common/eal_common_vdev.c
> +++ /dev/null
> @@ -1,342 +0,0 @@
> -/*-
> - *   BSD LICENSE
> - *
> - *   Copyright(c) 2016 RehiveTech. 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 RehiveTech 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 <string.h>
> -#include <inttypes.h>
> -#include <stdio.h>
> -#include <stdlib.h>
> -#include <stdint.h>
> -#include <stdbool.h>
> -#include <sys/queue.h>
> -
> -#include <rte_eal.h>
> -#include <rte_dev.h>
> -#include <rte_bus.h>
> -#include <rte_vdev.h>
> -#include <rte_common.h>
> -#include <rte_devargs.h>
> -#include <rte_memory.h>
> -#include <rte_errno.h>
> -
> -/* Forward declare to access virtual bus name */
> -static struct rte_bus rte_vdev_bus;
> -
> -/** Double linked list of virtual device drivers. */
> -TAILQ_HEAD(vdev_device_list, rte_vdev_device);
> -
> -static struct vdev_device_list vdev_device_list =
> -	TAILQ_HEAD_INITIALIZER(vdev_device_list);
> -struct vdev_driver_list vdev_driver_list =
> -	TAILQ_HEAD_INITIALIZER(vdev_driver_list);
> -
> -/* register a driver */
> -void
> -rte_vdev_register(struct rte_vdev_driver *driver)
> -{
> -	TAILQ_INSERT_TAIL(&vdev_driver_list, driver, next);
> -}
> -
> -/* unregister a driver */
> -void
> -rte_vdev_unregister(struct rte_vdev_driver *driver)
> -{
> -	TAILQ_REMOVE(&vdev_driver_list, driver, next);
> -}
> -
> -static int
> -vdev_parse(const char *name, void *addr)
> -{
> -	struct rte_vdev_driver **out = addr;
> -	struct rte_vdev_driver *driver = NULL;
> -
> -	TAILQ_FOREACH(driver, &vdev_driver_list, next) {
> -		if (strncmp(driver->driver.name, name,
> -			    strlen(driver->driver.name)) == 0)
> -			break;
> -		if (driver->driver.alias &&
> -		    strncmp(driver->driver.alias, name,
> -			    strlen(driver->driver.alias)) == 0)
> -			break;
> -	}
> -	if (driver != NULL &&
> -	    addr != NULL)
> -		*out = driver;
> -	return driver == NULL;
> -}
> -
> -static int
> -vdev_probe_all_drivers(struct rte_vdev_device *dev)
> -{
> -	const char *name;
> -	struct rte_vdev_driver *driver;
> -	int ret;
> -
> -	name = rte_vdev_device_name(dev);
> -
> -	RTE_LOG(DEBUG, EAL, "Search driver %s to probe device %s\n", name,
> -		rte_vdev_device_name(dev));
> -
> -	if (vdev_parse(name, &driver))
> -		return -1;
> -	dev->device.driver = &driver->driver;
> -	ret = driver->probe(dev);
> -	if (ret)
> -		dev->device.driver = NULL;
> -	return ret;
> -}
> -
> -static struct rte_vdev_device *
> -find_vdev(const char *name)
> -{
> -	struct rte_vdev_device *dev;
> -
> -	if (!name)
> -		return NULL;
> -
> -	TAILQ_FOREACH(dev, &vdev_device_list, next) {
> -		const char *devname = rte_vdev_device_name(dev);
> -		if (!strncmp(devname, name, strlen(name)))
> -			return dev;
> -	}
> -
> -	return NULL;
> -}
> -
> -static struct rte_devargs *
> -alloc_devargs(const char *name, const char *args)
> -{
> -	struct rte_devargs *devargs;
> -	int ret;
> -
> -	devargs = calloc(1, sizeof(*devargs));
> -	if (!devargs)
> -		return NULL;
> -
> -	devargs->bus = &rte_vdev_bus;
> -	if (args)
> -		devargs->args = strdup(args);
> -	else
> -		devargs->args = strdup("");
> -
> -	ret = snprintf(devargs->name, sizeof(devargs->name), "%s", name);
> -	if (ret < 0 || ret >= (int)sizeof(devargs->name)) {
> -		free(devargs->args);
> -		free(devargs);
> -		return NULL;
> -	}
> -
> -	return devargs;
> -}
> -
> -int
> -rte_vdev_init(const char *name, const char *args)
> -{
> -	struct rte_vdev_device *dev;
> -	struct rte_devargs *devargs;
> -	int ret;
> -
> -	if (name == NULL)
> -		return -EINVAL;
> -
> -	dev = find_vdev(name);
> -	if (dev)
> -		return -EEXIST;
> -
> -	devargs = alloc_devargs(name, args);
> -	if (!devargs)
> -		return -ENOMEM;
> -
> -	dev = calloc(1, sizeof(*dev));
> -	if (!dev) {
> -		ret = -ENOMEM;
> -		goto fail;
> -	}
> -
> -	dev->device.devargs = devargs;
> -	dev->device.numa_node = SOCKET_ID_ANY;
> -	dev->device.name = devargs->name;
> -
> -	ret = vdev_probe_all_drivers(dev);
> -	if (ret) {
> -		if (ret > 0)
> -			RTE_LOG(ERR, EAL, "no driver found for %s\n", name);
> -		goto fail;
> -	}
> -
> -	TAILQ_INSERT_TAIL(&devargs_list, devargs, next);
> -
> -	TAILQ_INSERT_TAIL(&vdev_device_list, dev, next);
> -	return 0;
> -
> -fail:
> -	free(devargs->args);
> -	free(devargs);
> -	free(dev);
> -	return ret;
> -}
> -
> -static int
> -vdev_remove_driver(struct rte_vdev_device *dev)
> -{
> -	const char *name = rte_vdev_device_name(dev);
> -	const struct rte_vdev_driver *driver;
> -
> -	if (!dev->device.driver) {
> -		RTE_LOG(DEBUG, EAL, "no driver attach to device %s\n", name);
> -		return 1;
> -	}
> -
> -	driver = container_of(dev->device.driver, const struct rte_vdev_driver,
> -		driver);
> -	return driver->remove(dev);
> -}
> -
> -int
> -rte_vdev_uninit(const char *name)
> -{
> -	struct rte_vdev_device *dev;
> -	struct rte_devargs *devargs;
> -	int ret;
> -
> -	if (name == NULL)
> -		return -EINVAL;
> -
> -	dev = find_vdev(name);
> -	if (!dev)
> -		return -ENOENT;
> -
> -	devargs = dev->device.devargs;
> -
> -	ret = vdev_remove_driver(dev);
> -	if (ret)
> -		return ret;
> -
> -	TAILQ_REMOVE(&vdev_device_list, dev, next);
> -
> -	TAILQ_REMOVE(&devargs_list, devargs, next);
> -
> -	free(devargs->args);
> -	free(devargs);
> -	free(dev);
> -	return 0;
> -}
> -
> -static int
> -vdev_scan(void)
> -{
> -	struct rte_vdev_device *dev;
> -	struct rte_devargs *devargs;
> -
> -	/* for virtual devices we scan the devargs_list populated via cmdline */
> -	TAILQ_FOREACH(devargs, &devargs_list, next) {
> -
> -		if (devargs->bus != &rte_vdev_bus)
> -			continue;
> -
> -		dev = find_vdev(devargs->name);
> -		if (dev)
> -			continue;
> -
> -		dev = calloc(1, sizeof(*dev));
> -		if (!dev)
> -			return -1;
> -
> -		dev->device.devargs = devargs;
> -		dev->device.numa_node = SOCKET_ID_ANY;
> -		dev->device.name = devargs->name;
> -
> -		TAILQ_INSERT_TAIL(&vdev_device_list, dev, next);
> -	}
> -
> -	return 0;
> -}
> -
> -static int
> -vdev_probe(void)
> -{
> -	struct rte_vdev_device *dev;
> -
> -	/* call the init function for each virtual device */
> -	TAILQ_FOREACH(dev, &vdev_device_list, next) {
> -
> -		if (dev->device.driver)
> -			continue;
> -
> -		if (vdev_probe_all_drivers(dev)) {
> -			RTE_LOG(ERR, EAL, "failed to initialize %s device\n",
> -				rte_vdev_device_name(dev));
> -			return -1;
> -		}
> -	}
> -
> -	return 0;
> -}
> -
> -static struct rte_device *
> -vdev_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,
> -		 const void *data)
> -{
> -	struct rte_vdev_device *dev;
> -
> -	TAILQ_FOREACH(dev, &vdev_device_list, next) {
> -		if (start && &dev->device == start) {
> -			start = NULL;
> -			continue;
> -		}
> -		if (cmp(&dev->device, data) == 0)
> -			return &dev->device;
> -	}
> -	return NULL;
> -}
> -
> -static int
> -vdev_plug(struct rte_device *dev)
> -{
> -	return vdev_probe_all_drivers(RTE_DEV_TO_VDEV(dev));
> -}
> -
> -static int
> -vdev_unplug(struct rte_device *dev)
> -{
> -	return rte_vdev_uninit(dev->name);
> -}
> -
> -static struct rte_bus rte_vdev_bus = {
> -	.scan = vdev_scan,
> -	.probe = vdev_probe,
> -	.find_device = vdev_find_device,
> -	.plug = vdev_plug,
> -	.unplug = vdev_unplug,
> -	.parse = vdev_parse,
> -};
> -
> -RTE_REGISTER_BUS(vdev, rte_vdev_bus);
> diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
> index 5386d3a..8bfc343 100644
> --- a/lib/librte_eal/common/include/rte_dev.h
> +++ b/lib/librte_eal/common/include/rte_dev.h
> @@ -166,28 +166,6 @@ struct rte_device {
>  };
>  
>  /**
> - * Initialize a driver specified by name.
> - *
> - * @param name
> - *   The pointer to a driver name to be initialized.
> - * @param args
> - *   The pointer to arguments used by driver initialization.
> - * @return
> - *  0 on success, negative on error
> - */
> -int rte_vdev_init(const char *name, const char *args);
> -
> -/**
> - * Uninitalize a driver specified by name.
> - *
> - * @param name
> - *   The pointer to a driver name to be initialized.
> - * @return
> - *  0 on success, negative on error
> - */
> -int rte_vdev_uninit(const char *name);
> -
> -/**
>   * Attach a device to a registered driver.
>   *
>   * @param name
> @@ -312,4 +290,4 @@ __attribute__((used)) = str
>  }
>  #endif
>  
> -#endif /* _RTE_VDEV_H_ */
> +#endif /* _RTE_DEV_H_ */
> diff --git a/lib/librte_eal/common/include/rte_vdev.h b/lib/librte_eal/common/include/rte_vdev.h
> deleted file mode 100644
> index 29f5a52..0000000
> --- a/lib/librte_eal/common/include/rte_vdev.h
> +++ /dev/null
> @@ -1,131 +0,0 @@
> -/*-
> - *   BSD LICENSE
> - *
> - *   Copyright(c) 2016 RehiveTech. 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 RehiveTech 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.
> - */
> -
> -#ifndef RTE_VDEV_H
> -#define RTE_VDEV_H
> -
> -#ifdef __cplusplus
> -extern "C" {
> -#endif
> -
> -#include <sys/queue.h>
> -#include <rte_dev.h>
> -#include <rte_devargs.h>
> -
> -struct rte_vdev_device {
> -	TAILQ_ENTRY(rte_vdev_device) next;      /**< Next attached vdev */
> -	struct rte_device device;               /**< Inherit core device */
> -};
> -
> -/**
> - * @internal
> - * Helper macro for drivers that need to convert to struct rte_vdev_device.
> - */
> -#define RTE_DEV_TO_VDEV(ptr) \
> -	container_of(ptr, struct rte_vdev_device, device)
> -
> -static inline const char *
> -rte_vdev_device_name(const struct rte_vdev_device *dev)
> -{
> -	if (dev && dev->device.name)
> -		return dev->device.name;
> -	return NULL;
> -}
> -
> -static inline const char *
> -rte_vdev_device_args(const struct rte_vdev_device *dev)
> -{
> -	if (dev && dev->device.devargs)
> -		return dev->device.devargs->args;
> -	return "";
> -}
> -
> -/** Double linked list of virtual device drivers. */
> -TAILQ_HEAD(vdev_driver_list, rte_vdev_driver);
> -
> -/**
> - * Probe function called for each virtual device driver once.
> - */
> -typedef int (rte_vdev_probe_t)(struct rte_vdev_device *dev);
> -
> -/**
> - * Remove function called for each virtual device driver once.
> - */
> -typedef int (rte_vdev_remove_t)(struct rte_vdev_device *dev);
> -
> -/**
> - * A virtual device driver abstraction.
> - */
> -struct rte_vdev_driver {
> -	TAILQ_ENTRY(rte_vdev_driver) next; /**< Next in list. */
> -	struct rte_driver driver;      /**< Inherited general driver. */
> -	rte_vdev_probe_t *probe;       /**< Virtual device probe function. */
> -	rte_vdev_remove_t *remove;     /**< Virtual device remove function. */
> -};
> -
> -/**
> - * Register a virtual device driver.
> - *
> - * @param driver
> - *   A pointer to a rte_vdev_driver structure describing the driver
> - *   to be registered.
> - */
> -void rte_vdev_register(struct rte_vdev_driver *driver);
> -
> -/**
> - * Unregister a virtual device driver.
> - *
> - * @param driver
> - *   A pointer to a rte_vdev_driver structure describing the driver
> - *   to be unregistered.
> - */
> -void rte_vdev_unregister(struct rte_vdev_driver *driver);
> -
> -#define RTE_PMD_REGISTER_VDEV(nm, vdrv)\
> -RTE_INIT(vdrvinitfn_ ##vdrv);\
> -static const char *vdrvinit_ ## nm ## _alias;\
> -static void vdrvinitfn_ ##vdrv(void)\
> -{\
> -	(vdrv).driver.name = RTE_STR(nm);\
> -	(vdrv).driver.alias = vdrvinit_ ## nm ## _alias;\
> -	rte_vdev_register(&vdrv);\
> -} \
> -RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
> -
> -#define RTE_PMD_REGISTER_ALIAS(nm, alias)\
> -static const char *vdrvinit_ ## nm ## _alias = RTE_STR(alias)
> -
> -#ifdef __cplusplus
> -}
> -#endif
> -
> -#endif
> diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
> index 90bca4d..33faa18 100644
> --- a/lib/librte_eal/linuxapp/eal/Makefile
> +++ b/lib/librte_eal/linuxapp/eal/Makefile
> @@ -80,7 +80,6 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_timer.c
>  SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memzone.c
>  SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_log.c
>  SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_launch.c
> -SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_vdev.c
>  SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci.c
>  SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci_uio.c
>  SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memory.c
> diff --git a/mk/rte.app.mk b/mk/rte.app.mk
> index c25fdd9..c423bf8 100644
> --- a/mk/rte.app.mk
> +++ b/mk/rte.app.mk
> @@ -97,6 +97,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_MEMPOOL)        += -lrte_mempool
>  _LDLIBS-$(CONFIG_RTE_DRIVER_MEMPOOL_RING)   += -lrte_mempool_ring
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_RING)           += -lrte_ring
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
> +_LDLIBS-$(CONFIG_RTE_LIBRTE_VDEV)           += -lrte_bus_vdev
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER)        += -lrte_reorder
>  
> -- 
> 2.7.4
> 

-- 
Gaëtan Rivet
6WIND

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC PATCH 2/4] ethdev: introduce Rx queue offloads API
                       ` (2 preceding siblings ...)
  2017-08-29 12:50  0%   ` Ferruh Yigit
@ 2017-08-29 13:11  0%   ` Ferruh Yigit
  3 siblings, 0 replies; 200+ results
From: Ferruh Yigit @ 2017-08-29 13:11 UTC (permalink / raw)
  To: Shahaf Shuler, dev

On 8/7/2017 11:54 AM, Shahaf Shuler wrote:
> Introduce a new API to configure Rx offloads.
> 
> The new API will re-use existing DEV_RX_OFFLOAD_* flags
> to enable the different offloads. This will ease the process
> of adding a new Rx offloads, as no ABI breakage is involved.
> In addition, the offload configuration can be done per queue,
> instead of per port.
> 
> The Rx queue offload API can be used only with devices which advertize
> the RTE_ETH_DEV_RXQ_OFFLOAD capability.
> 
> The old Rx offloads API is kept for the meanwhile, in order to enable a
> smooth transition for PMDs and application to the new API.
> 
> Signed-off-by: Shahaf Shuler <shahafs@mellanox.com>

<...>

>  /**
> @@ -691,6 +698,12 @@ struct rte_eth_rxq_conf {
>  	uint16_t rx_free_thresh; /**< Drives the freeing of RX descriptors. */
>  	uint8_t rx_drop_en; /**< Drop packets if no descriptors are available. */
>  	uint8_t rx_deferred_start; /**< Do not start queue with rte_eth_dev_start(). */
> +	uint64_t offloads;

Also there is a documentation aims to help PMDs on developing features
[1], currently for Rx offload features it documents rxmode fields as to
be used.

Can you please update that document too, according new API, new field to
use, both for Rx and Tx.

[1]
doc/guides/nics/features.rst

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [dpdk-techboard]  next techboard meeting (29th, August)
  2017-08-28 15:04  3% ` Bruce Richardson
@ 2017-08-29 15:30  0%   ` Jerin Jacob
  0 siblings, 0 replies; 200+ results
From: Jerin Jacob @ 2017-08-29 15:30 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: techboard, dev

-----Original Message-----
> Date: Mon, 28 Aug 2017 16:04:10 +0100
> From: Bruce Richardson <bruce.richardson@intel.com>
> To: Jerin Jacob <jerin.jacob@caviumnetworks.com>
> CC: techboard@dpdk.org, dev@dpdk.org
> Subject: Re: [dpdk-techboard]  next techboard meeting (29th, August)
> User-Agent: Mutt/1.8.3 (2017-05-23)
> 
> On Sun, Aug 27, 2017 at 06:54:35PM +0530, Jerin Jacob wrote:
> > Hi All,
> > 
> > The next meeting of the tech board will happen on IRC #dpdk-board, at 3pm UTC, on 29th of August(Tuesday)
> > 
> > Agenda:
> > 
> > 1) Discussion on next tree requests
> > a) Next tree for IPSec offload and maintainership
> > http://dpdk.org/ml/archives/dev/2017-August/072995.html
> > b) Next tree for cli
> > http://dpdk.org/ml/archives/dev/2017-August/073343.html
> > 
> > 2) Approval of a policy for changes to the minimum DPDK requirements.
> > e.g. like what was done with bumping IA min to SSE4.2 in last release.
> > 
> 
> Proposal for a policy for this item, so as to hopefully speed up the
> discussion at the meeting:
> 
> * Updates to the minimum HW requirements, i.e. those dropping support for
>   hardware which was previously supported, should be treated as an ABI
>   change, and follow that deprecation policy. Specifically:
>   - change announced at least one release in advance
>   - patches removing support for the older hardware should have at least
>     three ACKs before being applied.


The meeting got canceled due to lack of quorum. Scheduled Again for
tomorrow at the same time.

/Jerin

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 04/12] vdev: move to drivers/bus
  2017-08-29 13:04  3%   ` Gaëtan Rivet
@ 2017-08-29 22:47  0%     ` Tan, Jianfeng
  0 siblings, 0 replies; 200+ results
From: Tan, Jianfeng @ 2017-08-29 22:47 UTC (permalink / raw)
  To: Gaëtan Rivet
  Cc: dev, bruce.richardson, konstantin.ananyev, pablo.de.lara.guarch,
	thomas, yliu, maxime.coquelin, mtetsuyah, ferruh.yigit

Hi Gaetan,


On 8/29/2017 6:04 AM, Gaëtan Rivet wrote:
> On Fri, Aug 25, 2017 at 09:40:44AM +0000, Jianfeng Tan wrote:
>> Move the vdev bus from lib/librte_eal to drivers/bus.
>>
>> As the crypto vdev helper function refers to data structure
>> in rte_vdev.h, so we move those helper function into drivers/bus
>> too.
>>
>> Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
>> ---
>>   config/common_base                        |   5 +
>>   drivers/bus/Makefile                      |   2 +
>>   drivers/bus/vdev/Makefile                 |  57 +++++
>>   drivers/bus/vdev/rte_bus_vdev_version.map |  10 +
>>   drivers/bus/vdev/rte_cryptodev_vdev.c     | 154 ++++++++++++++
>>   drivers/bus/vdev/rte_cryptodev_vdev.h     | 100 +++++++++
>>   drivers/bus/vdev/rte_vdev.h               | 153 +++++++++++++
>>   drivers/bus/vdev/vdev.c                   | 342 ++++++++++++++++++++++++++++++
>>   lib/librte_cryptodev/Makefile             |   2 -
>>   lib/librte_cryptodev/rte_cryptodev_vdev.c | 154 --------------
>>   lib/librte_cryptodev/rte_cryptodev_vdev.h | 100 ---------
>>   lib/librte_eal/bsdapp/eal/Makefile        |   1 -
>>   lib/librte_eal/common/Makefile            |   2 +-
>>   lib/librte_eal/common/eal_common_vdev.c   | 342 ------------------------------
>>   lib/librte_eal/common/include/rte_dev.h   |  24 +--
>>   lib/librte_eal/common/include/rte_vdev.h  | 131 ------------
>>   lib/librte_eal/linuxapp/eal/Makefile      |   1 -
>>   mk/rte.app.mk                             |   1 +
>>   18 files changed, 826 insertions(+), 755 deletions(-)
>>   create mode 100644 drivers/bus/vdev/Makefile
>>   create mode 100644 drivers/bus/vdev/rte_bus_vdev_version.map
>>   create mode 100644 drivers/bus/vdev/rte_cryptodev_vdev.c
>>   create mode 100644 drivers/bus/vdev/rte_cryptodev_vdev.h
>>   create mode 100644 drivers/bus/vdev/rte_vdev.h
>>   create mode 100644 drivers/bus/vdev/vdev.c
>>   delete mode 100644 lib/librte_cryptodev/rte_cryptodev_vdev.c
>>   delete mode 100644 lib/librte_cryptodev/rte_cryptodev_vdev.h
>>   delete mode 100644 lib/librte_eal/common/eal_common_vdev.c
>>   delete mode 100644 lib/librte_eal/common/include/rte_vdev.h
>>
>> diff --git a/config/common_base b/config/common_base
>> index 5e97a08..aca0994 100644
>> --- a/config/common_base
>> +++ b/config/common_base
>> @@ -750,3 +750,8 @@ CONFIG_RTE_APP_CRYPTO_PERF=y
>>   # Compile the eventdev application
>>   #
>>   CONFIG_RTE_APP_EVENTDEV=y
>> +
>> +#
>> +# Compile the vdev bus
>> +#
>> +CONFIG_RTE_LIBRTE_VDEV=y
> Why not CONFIG_RTE_LIBRTE_VDEV_BUS?
> It would seem more consistent.

Was trying to be consistent with the directory name, drivers/bus/vdev. 
Do you think that directory should also be renamed?

>
>> diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
>> index 0224214..9b6d45e 100644
>> --- a/drivers/bus/Makefile
>> +++ b/drivers/bus/Makefile
>> @@ -35,4 +35,6 @@ core-libs := librte_eal librte_mbuf librte_mempool librte_ring librte_ether
>>   DIRS-$(CONFIG_RTE_LIBRTE_FSLMC_BUS) += fslmc
>>   DEPDIRS-fslmc = $(core-libs)
>>   
>> +DIRS-$(CONFIG_RTE_LIBRTE_VDEV) += vdev
>> +
>>   include $(RTE_SDK)/mk/rte.subdir.mk
>> diff --git a/drivers/bus/vdev/Makefile b/drivers/bus/vdev/Makefile
>> new file mode 100644
>> index 0000000..30c4813
>> --- /dev/null
>> +++ b/drivers/bus/vdev/Makefile
>> @@ -0,0 +1,57 @@
>> +#   BSD LICENSE
>> +#
>> +#   Copyright(c) 2017 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_SDK)/mk/rte.vars.mk
>> +
>> +#
>> +# library name
>> +#
>> +LIB = librte_bus_vdev.a
>> +
>> +CFLAGS += -O3
>> +CFLAGS += $(WERROR_FLAGS)
>> +
>> +# versioning export map
>> +EXPORT_MAP := rte_bus_vdev_version.map
>> +
>> +# library version
>> +LIBABIVER := 1
>> +
>> +SRCS-y += vdev.c
>> +SRCS-y += rte_cryptodev_vdev.c
>> +
>> +#
>> +# Export include files
>> +#
>> +SYMLINK-y-include += rte_vdev.h
>> +SYMLINK-y-include += rte_cryptodev_vdev.h
>> +
> Let's say the cryptodev lib must be updated.
> I understand the need to move rte_cryptodev_vdev.h outside
> librte_cryptodev, but I guess this exposes the vdev bus to ABI / API
> instability due to a third-party subsystem?

Thank you for bringing up this question. I really don't want to move 
these crypto-specific files into bus/vdev/. It's just some helper 
functions to be called by crypto vdev drivers. And what's more, the only 
dependence on vdev is that the API rte_cryptodev_vdev_pmd_init() has a 
parameter of struct rte_vdev_device, which is totally not necessary, as 
it only needs a struct rte_device parameter.

In all, I'd prefer to change this specific API and move those 
crypto-specific files back to lib/librte_crypto (just like ether dev and 
eventdev); but it needs API change announcement.

Any thoughts?

>
> I did something somewhat similar for PCI:
> http://dpdk.org/ml/archives/dev/2017-August/073525.html

I prefer your way to move those things to specific dev folder.

>
> I don't know which solution is best, but something certainly needs to be
> done.
>
> ---
>
> Beside the `why`, about the `how`: shouldn't this file compilation and
> symlink be conditioned to CONFIG_RTE_LIBRTE_CRYPTODEV=y?
>
> i.e.: SYMLINK-$(CONFIG_RTE_LIBRTE_CRYPTODEV)-include += rte_cryptodev_vdev.h

Yes, make sense.

Thanks,
Jianfeng


>
>> +include $(RTE_SDK)/mk/rte.lib.mk
>> diff --git a/drivers/bus/vdev/rte_bus_vdev_version.map b/drivers/bus/vdev/rte_bus_vdev_version.map
>> new file mode 100644
>> index 0000000..69740c3
>> --- /dev/null
>> +++ b/drivers/bus/vdev/rte_bus_vdev_version.map
>> @@ -0,0 +1,10 @@
>> +DPDK_17.11 {
>> +	global:
>> +
>> +	rte_vdev_init;
>> +	rte_vdev_register;
>> +	rte_vdev_uninit;
>> +	rte_vdev_unregister;
>> +	rte_cryptodev_vdev_pmd_init
>> +	rte_cryptodev_vdev_parse_init_params
>> +};
>> diff --git a/drivers/bus/vdev/rte_cryptodev_vdev.c b/drivers/bus/vdev/rte_cryptodev_vdev.c
>> new file mode 100644
>> index 0000000..fd308b4
>> --- /dev/null
>> +++ b/drivers/bus/vdev/rte_cryptodev_vdev.c
>> @@ -0,0 +1,154 @@
>> +/*-
>> + *   BSD LICENSE
>> + *
>> + *   Copyright(c) 2017 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 the copyright holder 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_cryptodev_vdev.h"
>> +#include "rte_cryptodev_pci.h"
>> +#include "rte_cryptodev_pmd.h"
>> +
>> +/**
>> + * Parse name from argument
>> + */
>> +static int
>> +rte_cryptodev_vdev_parse_name_arg(const char *key __rte_unused,
>> +		const char *value, void *extra_args)
>> +{
>> +	struct rte_crypto_vdev_init_params *params = extra_args;
>> +
>> +	if (strlen(value) >= RTE_CRYPTODEV_NAME_MAX_LEN - 1) {
>> +		CDEV_LOG_ERR("Invalid name %s, should be less than "
>> +				"%u bytes", value,
>> +				RTE_CRYPTODEV_NAME_MAX_LEN - 1);
>> +		return -1;
>> +	}
>> +
>> +	strncpy(params->name, value, RTE_CRYPTODEV_NAME_MAX_LEN);
>> +
>> +	return 0;
>> +}
>> +
>> +/**
>> + * Parse integer from argument
>> + */
>> +static int
>> +rte_cryptodev_vdev_parse_integer_arg(const char *key __rte_unused,
>> +		const char *value, void *extra_args)
>> +{
>> +	int *i = extra_args;
>> +
>> +	*i = atoi(value);
>> +	if (*i < 0) {
>> +		CDEV_LOG_ERR("Argument has to be positive.");
>> +		return -1;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +struct rte_cryptodev *
>> +rte_cryptodev_vdev_pmd_init(const char *name, size_t dev_private_size,
>> +		int socket_id, struct rte_vdev_device *vdev)
>> +{
>> +	struct rte_cryptodev *cryptodev;
>> +
>> +	/* allocate device structure */
>> +	cryptodev = rte_cryptodev_pmd_allocate(name, socket_id);
>> +	if (cryptodev == NULL)
>> +		return NULL;
>> +
>> +	/* allocate private device structure */
>> +	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
>> +		cryptodev->data->dev_private =
>> +				rte_zmalloc_socket("cryptodev device private",
>> +						dev_private_size,
>> +						RTE_CACHE_LINE_SIZE,
>> +						socket_id);
>> +
>> +		if (cryptodev->data->dev_private == NULL)
>> +			rte_panic("Cannot allocate memzone for private device"
>> +					" data");
>> +	}
>> +
>> +	cryptodev->device = &vdev->device;
>> +
>> +	/* initialise user call-back tail queue */
>> +	TAILQ_INIT(&(cryptodev->link_intr_cbs));
>> +
>> +	return cryptodev;
>> +}
>> +
>> +int
>> +rte_cryptodev_vdev_parse_init_params(struct rte_crypto_vdev_init_params *params,
>> +		const char *input_args)
>> +{
>> +	struct rte_kvargs *kvlist = NULL;
>> +	int ret = 0;
>> +
>> +	if (params == NULL)
>> +		return -EINVAL;
>> +
>> +	if (input_args) {
>> +		kvlist = rte_kvargs_parse(input_args,
>> +				cryptodev_vdev_valid_params);
>> +		if (kvlist == NULL)
>> +			return -1;
>> +
>> +		ret = rte_kvargs_process(kvlist,
>> +					RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
>> +					&rte_cryptodev_vdev_parse_integer_arg,
>> +					&params->max_nb_queue_pairs);
>> +		if (ret < 0)
>> +			goto free_kvlist;
>> +
>> +		ret = rte_kvargs_process(kvlist,
>> +					RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
>> +					&rte_cryptodev_vdev_parse_integer_arg,
>> +					&params->max_nb_sessions);
>> +		if (ret < 0)
>> +			goto free_kvlist;
>> +
>> +		ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_SOCKET_ID,
>> +					&rte_cryptodev_vdev_parse_integer_arg,
>> +					&params->socket_id);
>> +		if (ret < 0)
>> +			goto free_kvlist;
>> +
>> +		ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_NAME,
>> +					&rte_cryptodev_vdev_parse_name_arg,
>> +					params);
>> +		if (ret < 0)
>> +			goto free_kvlist;
>> +	}
>> +
>> +free_kvlist:
>> +	rte_kvargs_free(kvlist);
>> +	return ret;
>> +}
>> diff --git a/drivers/bus/vdev/rte_cryptodev_vdev.h b/drivers/bus/vdev/rte_cryptodev_vdev.h
>> new file mode 100644
>> index 0000000..94ab9d3
>> --- /dev/null
>> +++ b/drivers/bus/vdev/rte_cryptodev_vdev.h
>> @@ -0,0 +1,100 @@
>> +/*-
>> + *   BSD LICENSE
>> + *
>> + *   Copyright(c) 2017 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 the copyright holder 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.
>> + */
>> +
>> +#ifndef _RTE_CRYPTODEV_VDEV_H_
>> +#define _RTE_CRYPTODEV_VDEV_H_
>> +
>> +#include <rte_vdev.h>
>> +#include <inttypes.h>
>> +
>> +#include "rte_cryptodev.h"
>> +
>> +#define RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_QUEUE_PAIRS	8
>> +#define RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_SESSIONS	2048
>> +
>> +#define RTE_CRYPTODEV_VDEV_NAME				("name")
>> +#define RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG		("max_nb_queue_pairs")
>> +#define RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG		("max_nb_sessions")
>> +#define RTE_CRYPTODEV_VDEV_SOCKET_ID			("socket_id")
>> +
>> +static const char * const cryptodev_vdev_valid_params[] = {
>> +	RTE_CRYPTODEV_VDEV_NAME,
>> +	RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
>> +	RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
>> +	RTE_CRYPTODEV_VDEV_SOCKET_ID
>> +};
>> +
>> +/**
>> + * @internal
>> + * Initialisation parameters for virtual crypto devices
>> + */
>> +struct rte_crypto_vdev_init_params {
>> +	unsigned int max_nb_queue_pairs;
>> +	unsigned int max_nb_sessions;
>> +	uint8_t socket_id;
>> +	char name[RTE_CRYPTODEV_NAME_MAX_LEN];
>> +};
>> +
>> +/**
>> + * @internal
>> + * Creates a new virtual crypto device and returns the pointer
>> + * to that device.
>> + *
>> + * @param	name			PMD type name
>> + * @param	dev_private_size	Size of crypto PMDs private data
>> + * @param	socket_id		Socket to allocate resources on.
>> + * @param	vdev			Pointer to virtual device structure.
>> + *
>> + * @return
>> + *   - Cryptodev pointer if device is successfully created.
>> + *   - NULL if device cannot be created.
>> + */
>> +struct rte_cryptodev *
>> +rte_cryptodev_vdev_pmd_init(const char *name, size_t dev_private_size,
>> +		int socket_id, struct rte_vdev_device *vdev);
>> +
>> +/**
>> + * @internal
>> + * Parse virtual device initialisation parameters input arguments
>> + *
>> + * @params	params		Initialisation parameters with defaults set.
>> + * @params	input_args	Command line arguments
>> + *
>> + * @return
>> + * 0 on successful parse
>> + * <0 on failure to parse
>> + */
>> +int
>> +rte_cryptodev_vdev_parse_init_params(struct rte_crypto_vdev_init_params *params,
>> +		const char *input_args);
>> +
>> +#endif /* _RTE_CRYPTODEV_VDEV_H_ */
>> diff --git a/drivers/bus/vdev/rte_vdev.h b/drivers/bus/vdev/rte_vdev.h
>> new file mode 100644
>> index 0000000..41762b8
>> --- /dev/null
>> +++ b/drivers/bus/vdev/rte_vdev.h
>> @@ -0,0 +1,153 @@
>> +/*-
>> + *   BSD LICENSE
>> + *
>> + *   Copyright(c) 2016 RehiveTech. 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 RehiveTech 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.
>> + */
>> +
>> +#ifndef RTE_VDEV_H
>> +#define RTE_VDEV_H
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +#include <sys/queue.h>
>> +#include <rte_dev.h>
>> +#include <rte_devargs.h>
>> +
>> +struct rte_vdev_device {
>> +	TAILQ_ENTRY(rte_vdev_device) next;      /**< Next attached vdev */
>> +	struct rte_device device;               /**< Inherit core device */
>> +};
>> +
>> +/**
>> + * @internal
>> + * Helper macro for drivers that need to convert to struct rte_vdev_device.
>> + */
>> +#define RTE_DEV_TO_VDEV(ptr) \
>> +	container_of(ptr, struct rte_vdev_device, device)
>> +
>> +static inline const char *
>> +rte_vdev_device_name(const struct rte_vdev_device *dev)
>> +{
>> +	if (dev && dev->device.name)
>> +		return dev->device.name;
>> +	return NULL;
>> +}
>> +
>> +static inline const char *
>> +rte_vdev_device_args(const struct rte_vdev_device *dev)
>> +{
>> +	if (dev && dev->device.devargs)
>> +		return dev->device.devargs->args;
>> +	return "";
>> +}
>> +
>> +/** Double linked list of virtual device drivers. */
>> +TAILQ_HEAD(vdev_driver_list, rte_vdev_driver);
>> +
>> +/**
>> + * Probe function called for each virtual device driver once.
>> + */
>> +typedef int (rte_vdev_probe_t)(struct rte_vdev_device *dev);
>> +
>> +/**
>> + * Remove function called for each virtual device driver once.
>> + */
>> +typedef int (rte_vdev_remove_t)(struct rte_vdev_device *dev);
>> +
>> +/**
>> + * A virtual device driver abstraction.
>> + */
>> +struct rte_vdev_driver {
>> +	TAILQ_ENTRY(rte_vdev_driver) next; /**< Next in list. */
>> +	struct rte_driver driver;      /**< Inherited general driver. */
>> +	rte_vdev_probe_t *probe;       /**< Virtual device probe function. */
>> +	rte_vdev_remove_t *remove;     /**< Virtual device remove function. */
>> +};
>> +
>> +/**
>> + * Register a virtual device driver.
>> + *
>> + * @param driver
>> + *   A pointer to a rte_vdev_driver structure describing the driver
>> + *   to be registered.
>> + */
>> +void rte_vdev_register(struct rte_vdev_driver *driver);
>> +
>> +/**
>> + * Unregister a virtual device driver.
>> + *
>> + * @param driver
>> + *   A pointer to a rte_vdev_driver structure describing the driver
>> + *   to be unregistered.
>> + */
>> +void rte_vdev_unregister(struct rte_vdev_driver *driver);
>> +
>> +#define RTE_PMD_REGISTER_VDEV(nm, vdrv)\
>> +RTE_INIT(vdrvinitfn_ ##vdrv);\
>> +static const char *vdrvinit_ ## nm ## _alias;\
>> +static void vdrvinitfn_ ##vdrv(void)\
>> +{\
>> +	(vdrv).driver.name = RTE_STR(nm);\
>> +	(vdrv).driver.alias = vdrvinit_ ## nm ## _alias;\
>> +	rte_vdev_register(&vdrv);\
>> +} \
>> +RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
>> +
>> +#define RTE_PMD_REGISTER_ALIAS(nm, alias)\
>> +static const char *vdrvinit_ ## nm ## _alias = RTE_STR(alias)
>> +
>> +/**
>> + * Initialize a driver specified by name.
>> + *
>> + * @param name
>> + *   The pointer to a driver name to be initialized.
>> + * @param args
>> + *   The pointer to arguments used by driver initialization.
>> + * @return
>> + *  0 on success, negative on error
>> + */
>> +int rte_vdev_init(const char *name, const char *args);
>> +
>> +/**
>> + * Uninitalize a driver specified by name.
>> + *
>> + * @param name
>> + *   The pointer to a driver name to be initialized.
>> + * @return
>> + *  0 on success, negative on error
>> + */
>> +int rte_vdev_uninit(const char *name);
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/drivers/bus/vdev/vdev.c b/drivers/bus/vdev/vdev.c
>> new file mode 100644
>> index 0000000..f7e547a
>> --- /dev/null
>> +++ b/drivers/bus/vdev/vdev.c
>> @@ -0,0 +1,342 @@
>> +/*-
>> + *   BSD LICENSE
>> + *
>> + *   Copyright(c) 2016 RehiveTech. 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 RehiveTech 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 <string.h>
>> +#include <inttypes.h>
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <stdint.h>
>> +#include <stdbool.h>
>> +#include <sys/queue.h>
>> +
>> +#include <rte_eal.h>
>> +#include <rte_dev.h>
>> +#include <rte_bus.h>
>> +#include <rte_vdev.h>
>> +#include <rte_common.h>
>> +#include <rte_devargs.h>
>> +#include <rte_memory.h>
>> +#include <rte_errno.h>
>> +
>> +/* Forward declare to access virtual bus name */
>> +static struct rte_bus rte_vdev_bus;
>> +
>> +/** Double linked list of virtual device drivers. */
>> +TAILQ_HEAD(vdev_device_list, rte_vdev_device);
>> +
>> +static struct vdev_device_list vdev_device_list =
>> +	TAILQ_HEAD_INITIALIZER(vdev_device_list);
>> +struct vdev_driver_list vdev_driver_list =
>> +	TAILQ_HEAD_INITIALIZER(vdev_driver_list);
>> +
>> +/* register a driver */
>> +void
>> +rte_vdev_register(struct rte_vdev_driver *driver)
>> +{
>> +	TAILQ_INSERT_TAIL(&vdev_driver_list, driver, next);
>> +}
>> +
>> +/* unregister a driver */
>> +void
>> +rte_vdev_unregister(struct rte_vdev_driver *driver)
>> +{
>> +	TAILQ_REMOVE(&vdev_driver_list, driver, next);
>> +}
>> +
>> +static int
>> +vdev_parse(const char *name, void *addr)
>> +{
>> +	struct rte_vdev_driver **out = addr;
>> +	struct rte_vdev_driver *driver = NULL;
>> +
>> +	TAILQ_FOREACH(driver, &vdev_driver_list, next) {
>> +		if (strncmp(driver->driver.name, name,
>> +			    strlen(driver->driver.name)) == 0)
>> +			break;
>> +		if (driver->driver.alias &&
>> +		    strncmp(driver->driver.alias, name,
>> +			    strlen(driver->driver.alias)) == 0)
>> +			break;
>> +	}
>> +	if (driver != NULL &&
>> +	    addr != NULL)
>> +		*out = driver;
>> +	return driver == NULL;
>> +}
>> +
>> +static int
>> +vdev_probe_all_drivers(struct rte_vdev_device *dev)
>> +{
>> +	const char *name;
>> +	struct rte_vdev_driver *driver;
>> +	int ret;
>> +
>> +	name = rte_vdev_device_name(dev);
>> +
>> +	RTE_LOG(DEBUG, EAL, "Search driver %s to probe device %s\n", name,
>> +		rte_vdev_device_name(dev));
>> +
>> +	if (vdev_parse(name, &driver))
>> +		return -1;
>> +	dev->device.driver = &driver->driver;
>> +	ret = driver->probe(dev);
>> +	if (ret)
>> +		dev->device.driver = NULL;
>> +	return ret;
>> +}
>> +
>> +static struct rte_vdev_device *
>> +find_vdev(const char *name)
>> +{
>> +	struct rte_vdev_device *dev;
>> +
>> +	if (!name)
>> +		return NULL;
>> +
>> +	TAILQ_FOREACH(dev, &vdev_device_list, next) {
>> +		const char *devname = rte_vdev_device_name(dev);
>> +		if (!strncmp(devname, name, strlen(name)))
>> +			return dev;
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>> +static struct rte_devargs *
>> +alloc_devargs(const char *name, const char *args)
>> +{
>> +	struct rte_devargs *devargs;
>> +	int ret;
>> +
>> +	devargs = calloc(1, sizeof(*devargs));
>> +	if (!devargs)
>> +		return NULL;
>> +
>> +	devargs->bus = &rte_vdev_bus;
>> +	if (args)
>> +		devargs->args = strdup(args);
>> +	else
>> +		devargs->args = strdup("");
>> +
>> +	ret = snprintf(devargs->name, sizeof(devargs->name), "%s", name);
>> +	if (ret < 0 || ret >= (int)sizeof(devargs->name)) {
>> +		free(devargs->args);
>> +		free(devargs);
>> +		return NULL;
>> +	}
>> +
>> +	return devargs;
>> +}
>> +
>> +int
>> +rte_vdev_init(const char *name, const char *args)
>> +{
>> +	struct rte_vdev_device *dev;
>> +	struct rte_devargs *devargs;
>> +	int ret;
>> +
>> +	if (name == NULL)
>> +		return -EINVAL;
>> +
>> +	dev = find_vdev(name);
>> +	if (dev)
>> +		return -EEXIST;
>> +
>> +	devargs = alloc_devargs(name, args);
>> +	if (!devargs)
>> +		return -ENOMEM;
>> +
>> +	dev = calloc(1, sizeof(*dev));
>> +	if (!dev) {
>> +		ret = -ENOMEM;
>> +		goto fail;
>> +	}
>> +
>> +	dev->device.devargs = devargs;
>> +	dev->device.numa_node = SOCKET_ID_ANY;
>> +	dev->device.name = devargs->name;
>> +
>> +	ret = vdev_probe_all_drivers(dev);
>> +	if (ret) {
>> +		if (ret > 0)
>> +			RTE_LOG(ERR, EAL, "no driver found for %s\n", name);
>> +		goto fail;
>> +	}
>> +
>> +	TAILQ_INSERT_TAIL(&devargs_list, devargs, next);
>> +
>> +	TAILQ_INSERT_TAIL(&vdev_device_list, dev, next);
>> +	return 0;
>> +
>> +fail:
>> +	free(devargs->args);
>> +	free(devargs);
>> +	free(dev);
>> +	return ret;
>> +}
>> +
>> +static int
>> +vdev_remove_driver(struct rte_vdev_device *dev)
>> +{
>> +	const char *name = rte_vdev_device_name(dev);
>> +	const struct rte_vdev_driver *driver;
>> +
>> +	if (!dev->device.driver) {
>> +		RTE_LOG(DEBUG, EAL, "no driver attach to device %s\n", name);
>> +		return 1;
>> +	}
>> +
>> +	driver = container_of(dev->device.driver, const struct rte_vdev_driver,
>> +		driver);
>> +	return driver->remove(dev);
>> +}
>> +
>> +int
>> +rte_vdev_uninit(const char *name)
>> +{
>> +	struct rte_vdev_device *dev;
>> +	struct rte_devargs *devargs;
>> +	int ret;
>> +
>> +	if (name == NULL)
>> +		return -EINVAL;
>> +
>> +	dev = find_vdev(name);
>> +	if (!dev)
>> +		return -ENOENT;
>> +
>> +	devargs = dev->device.devargs;
>> +
>> +	ret = vdev_remove_driver(dev);
>> +	if (ret)
>> +		return ret;
>> +
>> +	TAILQ_REMOVE(&vdev_device_list, dev, next);
>> +
>> +	TAILQ_REMOVE(&devargs_list, devargs, next);
>> +
>> +	free(devargs->args);
>> +	free(devargs);
>> +	free(dev);
>> +	return 0;
>> +}
>> +
>> +static int
>> +vdev_scan(void)
>> +{
>> +	struct rte_vdev_device *dev;
>> +	struct rte_devargs *devargs;
>> +
>> +	/* for virtual devices we scan the devargs_list populated via cmdline */
>> +	TAILQ_FOREACH(devargs, &devargs_list, next) {
>> +
>> +		if (devargs->bus != &rte_vdev_bus)
>> +			continue;
>> +
>> +		dev = find_vdev(devargs->name);
>> +		if (dev)
>> +			continue;
>> +
>> +		dev = calloc(1, sizeof(*dev));
>> +		if (!dev)
>> +			return -1;
>> +
>> +		dev->device.devargs = devargs;
>> +		dev->device.numa_node = SOCKET_ID_ANY;
>> +		dev->device.name = devargs->name;
>> +
>> +		TAILQ_INSERT_TAIL(&vdev_device_list, dev, next);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int
>> +vdev_probe(void)
>> +{
>> +	struct rte_vdev_device *dev;
>> +
>> +	/* call the init function for each virtual device */
>> +	TAILQ_FOREACH(dev, &vdev_device_list, next) {
>> +
>> +		if (dev->device.driver)
>> +			continue;
>> +
>> +		if (vdev_probe_all_drivers(dev)) {
>> +			RTE_LOG(ERR, EAL, "failed to initialize %s device\n",
>> +				rte_vdev_device_name(dev));
>> +			return -1;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static struct rte_device *
>> +vdev_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,
>> +		 const void *data)
>> +{
>> +	struct rte_vdev_device *dev;
>> +
>> +	TAILQ_FOREACH(dev, &vdev_device_list, next) {
>> +		if (start && &dev->device == start) {
>> +			start = NULL;
>> +			continue;
>> +		}
>> +		if (cmp(&dev->device, data) == 0)
>> +			return &dev->device;
>> +	}
>> +	return NULL;
>> +}
>> +
>> +static int
>> +vdev_plug(struct rte_device *dev)
>> +{
>> +	return vdev_probe_all_drivers(RTE_DEV_TO_VDEV(dev));
>> +}
>> +
>> +static int
>> +vdev_unplug(struct rte_device *dev)
>> +{
>> +	return rte_vdev_uninit(dev->name);
>> +}
>> +
>> +static struct rte_bus rte_vdev_bus = {
>> +	.scan = vdev_scan,
>> +	.probe = vdev_probe,
>> +	.find_device = vdev_find_device,
>> +	.plug = vdev_plug,
>> +	.unplug = vdev_unplug,
>> +	.parse = vdev_parse,
>> +};
>> +
>> +RTE_REGISTER_BUS(vdev, rte_vdev_bus);
>> diff --git a/lib/librte_cryptodev/Makefile b/lib/librte_cryptodev/Makefile
>> index 301c78d..4f70719 100644
>> --- a/lib/librte_cryptodev/Makefile
>> +++ b/lib/librte_cryptodev/Makefile
>> @@ -42,14 +42,12 @@ CFLAGS += $(WERROR_FLAGS)
>>   
>>   # library source files
>>   SRCS-y += rte_cryptodev.c rte_cryptodev_pmd.c
>> -SRCS-y += rte_cryptodev_vdev.c
>>   
>>   # export include files
>>   SYMLINK-y-include += rte_crypto.h
>>   SYMLINK-y-include += rte_crypto_sym.h
>>   SYMLINK-y-include += rte_cryptodev.h
>>   SYMLINK-y-include += rte_cryptodev_pmd.h
>> -SYMLINK-y-include += rte_cryptodev_vdev.h
>>   SYMLINK-y-include += rte_cryptodev_pci.h
>>   
>>   # versioning export map
>> diff --git a/lib/librte_cryptodev/rte_cryptodev_vdev.c b/lib/librte_cryptodev/rte_cryptodev_vdev.c
>> deleted file mode 100644
>> index fd308b4..0000000
>> --- a/lib/librte_cryptodev/rte_cryptodev_vdev.c
>> +++ /dev/null
>> @@ -1,154 +0,0 @@
>> -/*-
>> - *   BSD LICENSE
>> - *
>> - *   Copyright(c) 2017 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 the copyright holder 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_cryptodev_vdev.h"
>> -#include "rte_cryptodev_pci.h"
>> -#include "rte_cryptodev_pmd.h"
>> -
>> -/**
>> - * Parse name from argument
>> - */
>> -static int
>> -rte_cryptodev_vdev_parse_name_arg(const char *key __rte_unused,
>> -		const char *value, void *extra_args)
>> -{
>> -	struct rte_crypto_vdev_init_params *params = extra_args;
>> -
>> -	if (strlen(value) >= RTE_CRYPTODEV_NAME_MAX_LEN - 1) {
>> -		CDEV_LOG_ERR("Invalid name %s, should be less than "
>> -				"%u bytes", value,
>> -				RTE_CRYPTODEV_NAME_MAX_LEN - 1);
>> -		return -1;
>> -	}
>> -
>> -	strncpy(params->name, value, RTE_CRYPTODEV_NAME_MAX_LEN);
>> -
>> -	return 0;
>> -}
>> -
>> -/**
>> - * Parse integer from argument
>> - */
>> -static int
>> -rte_cryptodev_vdev_parse_integer_arg(const char *key __rte_unused,
>> -		const char *value, void *extra_args)
>> -{
>> -	int *i = extra_args;
>> -
>> -	*i = atoi(value);
>> -	if (*i < 0) {
>> -		CDEV_LOG_ERR("Argument has to be positive.");
>> -		return -1;
>> -	}
>> -
>> -	return 0;
>> -}
>> -
>> -struct rte_cryptodev *
>> -rte_cryptodev_vdev_pmd_init(const char *name, size_t dev_private_size,
>> -		int socket_id, struct rte_vdev_device *vdev)
>> -{
>> -	struct rte_cryptodev *cryptodev;
>> -
>> -	/* allocate device structure */
>> -	cryptodev = rte_cryptodev_pmd_allocate(name, socket_id);
>> -	if (cryptodev == NULL)
>> -		return NULL;
>> -
>> -	/* allocate private device structure */
>> -	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
>> -		cryptodev->data->dev_private =
>> -				rte_zmalloc_socket("cryptodev device private",
>> -						dev_private_size,
>> -						RTE_CACHE_LINE_SIZE,
>> -						socket_id);
>> -
>> -		if (cryptodev->data->dev_private == NULL)
>> -			rte_panic("Cannot allocate memzone for private device"
>> -					" data");
>> -	}
>> -
>> -	cryptodev->device = &vdev->device;
>> -
>> -	/* initialise user call-back tail queue */
>> -	TAILQ_INIT(&(cryptodev->link_intr_cbs));
>> -
>> -	return cryptodev;
>> -}
>> -
>> -int
>> -rte_cryptodev_vdev_parse_init_params(struct rte_crypto_vdev_init_params *params,
>> -		const char *input_args)
>> -{
>> -	struct rte_kvargs *kvlist = NULL;
>> -	int ret = 0;
>> -
>> -	if (params == NULL)
>> -		return -EINVAL;
>> -
>> -	if (input_args) {
>> -		kvlist = rte_kvargs_parse(input_args,
>> -				cryptodev_vdev_valid_params);
>> -		if (kvlist == NULL)
>> -			return -1;
>> -
>> -		ret = rte_kvargs_process(kvlist,
>> -					RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
>> -					&rte_cryptodev_vdev_parse_integer_arg,
>> -					&params->max_nb_queue_pairs);
>> -		if (ret < 0)
>> -			goto free_kvlist;
>> -
>> -		ret = rte_kvargs_process(kvlist,
>> -					RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
>> -					&rte_cryptodev_vdev_parse_integer_arg,
>> -					&params->max_nb_sessions);
>> -		if (ret < 0)
>> -			goto free_kvlist;
>> -
>> -		ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_SOCKET_ID,
>> -					&rte_cryptodev_vdev_parse_integer_arg,
>> -					&params->socket_id);
>> -		if (ret < 0)
>> -			goto free_kvlist;
>> -
>> -		ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_NAME,
>> -					&rte_cryptodev_vdev_parse_name_arg,
>> -					params);
>> -		if (ret < 0)
>> -			goto free_kvlist;
>> -	}
>> -
>> -free_kvlist:
>> -	rte_kvargs_free(kvlist);
>> -	return ret;
>> -}
>> diff --git a/lib/librte_cryptodev/rte_cryptodev_vdev.h b/lib/librte_cryptodev/rte_cryptodev_vdev.h
>> deleted file mode 100644
>> index 94ab9d3..0000000
>> --- a/lib/librte_cryptodev/rte_cryptodev_vdev.h
>> +++ /dev/null
>> @@ -1,100 +0,0 @@
>> -/*-
>> - *   BSD LICENSE
>> - *
>> - *   Copyright(c) 2017 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 the copyright holder 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.
>> - */
>> -
>> -#ifndef _RTE_CRYPTODEV_VDEV_H_
>> -#define _RTE_CRYPTODEV_VDEV_H_
>> -
>> -#include <rte_vdev.h>
>> -#include <inttypes.h>
>> -
>> -#include "rte_cryptodev.h"
>> -
>> -#define RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_QUEUE_PAIRS	8
>> -#define RTE_CRYPTODEV_VDEV_DEFAULT_MAX_NB_SESSIONS	2048
>> -
>> -#define RTE_CRYPTODEV_VDEV_NAME				("name")
>> -#define RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG		("max_nb_queue_pairs")
>> -#define RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG		("max_nb_sessions")
>> -#define RTE_CRYPTODEV_VDEV_SOCKET_ID			("socket_id")
>> -
>> -static const char * const cryptodev_vdev_valid_params[] = {
>> -	RTE_CRYPTODEV_VDEV_NAME,
>> -	RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
>> -	RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
>> -	RTE_CRYPTODEV_VDEV_SOCKET_ID
>> -};
>> -
>> -/**
>> - * @internal
>> - * Initialisation parameters for virtual crypto devices
>> - */
>> -struct rte_crypto_vdev_init_params {
>> -	unsigned int max_nb_queue_pairs;
>> -	unsigned int max_nb_sessions;
>> -	uint8_t socket_id;
>> -	char name[RTE_CRYPTODEV_NAME_MAX_LEN];
>> -};
>> -
>> -/**
>> - * @internal
>> - * Creates a new virtual crypto device and returns the pointer
>> - * to that device.
>> - *
>> - * @param	name			PMD type name
>> - * @param	dev_private_size	Size of crypto PMDs private data
>> - * @param	socket_id		Socket to allocate resources on.
>> - * @param	vdev			Pointer to virtual device structure.
>> - *
>> - * @return
>> - *   - Cryptodev pointer if device is successfully created.
>> - *   - NULL if device cannot be created.
>> - */
>> -struct rte_cryptodev *
>> -rte_cryptodev_vdev_pmd_init(const char *name, size_t dev_private_size,
>> -		int socket_id, struct rte_vdev_device *vdev);
>> -
>> -/**
>> - * @internal
>> - * Parse virtual device initialisation parameters input arguments
>> - *
>> - * @params	params		Initialisation parameters with defaults set.
>> - * @params	input_args	Command line arguments
>> - *
>> - * @return
>> - * 0 on successful parse
>> - * <0 on failure to parse
>> - */
>> -int
>> -rte_cryptodev_vdev_parse_init_params(struct rte_crypto_vdev_init_params *params,
>> -		const char *input_args);
>> -
>> -#endif /* _RTE_CRYPTODEV_VDEV_H_ */
>> diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
>> index 005019e..6fee587 100644
>> --- a/lib/librte_eal/bsdapp/eal/Makefile
>> +++ b/lib/librte_eal/bsdapp/eal/Makefile
>> @@ -68,7 +68,6 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_timer.c
>>   SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memzone.c
>>   SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_log.c
>>   SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_launch.c
>> -SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_vdev.c
>>   SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_pci.c
>>   SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_pci_uio.c
>>   SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memory.c
>> diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
>> index e8fd67a..7eeb06a 100644
>> --- a/lib/librte_eal/common/Makefile
>> +++ b/lib/librte_eal/common/Makefile
>> @@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
>>   INC += rte_tailq.h rte_interrupts.h rte_alarm.h
>>   INC += rte_string_fns.h rte_version.h
>>   INC += rte_eal_memconfig.h rte_malloc_heap.h
>> -INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
>> +INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h
>>   INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
>>   INC += rte_malloc.h rte_keepalive.h rte_time.h
>>   INC += rte_service.h rte_service_component.h
>> diff --git a/lib/librte_eal/common/eal_common_vdev.c b/lib/librte_eal/common/eal_common_vdev.c
>> deleted file mode 100644
>> index f7e547a..0000000
>> --- a/lib/librte_eal/common/eal_common_vdev.c
>> +++ /dev/null
>> @@ -1,342 +0,0 @@
>> -/*-
>> - *   BSD LICENSE
>> - *
>> - *   Copyright(c) 2016 RehiveTech. 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 RehiveTech 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 <string.h>
>> -#include <inttypes.h>
>> -#include <stdio.h>
>> -#include <stdlib.h>
>> -#include <stdint.h>
>> -#include <stdbool.h>
>> -#include <sys/queue.h>
>> -
>> -#include <rte_eal.h>
>> -#include <rte_dev.h>
>> -#include <rte_bus.h>
>> -#include <rte_vdev.h>
>> -#include <rte_common.h>
>> -#include <rte_devargs.h>
>> -#include <rte_memory.h>
>> -#include <rte_errno.h>
>> -
>> -/* Forward declare to access virtual bus name */
>> -static struct rte_bus rte_vdev_bus;
>> -
>> -/** Double linked list of virtual device drivers. */
>> -TAILQ_HEAD(vdev_device_list, rte_vdev_device);
>> -
>> -static struct vdev_device_list vdev_device_list =
>> -	TAILQ_HEAD_INITIALIZER(vdev_device_list);
>> -struct vdev_driver_list vdev_driver_list =
>> -	TAILQ_HEAD_INITIALIZER(vdev_driver_list);
>> -
>> -/* register a driver */
>> -void
>> -rte_vdev_register(struct rte_vdev_driver *driver)
>> -{
>> -	TAILQ_INSERT_TAIL(&vdev_driver_list, driver, next);
>> -}
>> -
>> -/* unregister a driver */
>> -void
>> -rte_vdev_unregister(struct rte_vdev_driver *driver)
>> -{
>> -	TAILQ_REMOVE(&vdev_driver_list, driver, next);
>> -}
>> -
>> -static int
>> -vdev_parse(const char *name, void *addr)
>> -{
>> -	struct rte_vdev_driver **out = addr;
>> -	struct rte_vdev_driver *driver = NULL;
>> -
>> -	TAILQ_FOREACH(driver, &vdev_driver_list, next) {
>> -		if (strncmp(driver->driver.name, name,
>> -			    strlen(driver->driver.name)) == 0)
>> -			break;
>> -		if (driver->driver.alias &&
>> -		    strncmp(driver->driver.alias, name,
>> -			    strlen(driver->driver.alias)) == 0)
>> -			break;
>> -	}
>> -	if (driver != NULL &&
>> -	    addr != NULL)
>> -		*out = driver;
>> -	return driver == NULL;
>> -}
>> -
>> -static int
>> -vdev_probe_all_drivers(struct rte_vdev_device *dev)
>> -{
>> -	const char *name;
>> -	struct rte_vdev_driver *driver;
>> -	int ret;
>> -
>> -	name = rte_vdev_device_name(dev);
>> -
>> -	RTE_LOG(DEBUG, EAL, "Search driver %s to probe device %s\n", name,
>> -		rte_vdev_device_name(dev));
>> -
>> -	if (vdev_parse(name, &driver))
>> -		return -1;
>> -	dev->device.driver = &driver->driver;
>> -	ret = driver->probe(dev);
>> -	if (ret)
>> -		dev->device.driver = NULL;
>> -	return ret;
>> -}
>> -
>> -static struct rte_vdev_device *
>> -find_vdev(const char *name)
>> -{
>> -	struct rte_vdev_device *dev;
>> -
>> -	if (!name)
>> -		return NULL;
>> -
>> -	TAILQ_FOREACH(dev, &vdev_device_list, next) {
>> -		const char *devname = rte_vdev_device_name(dev);
>> -		if (!strncmp(devname, name, strlen(name)))
>> -			return dev;
>> -	}
>> -
>> -	return NULL;
>> -}
>> -
>> -static struct rte_devargs *
>> -alloc_devargs(const char *name, const char *args)
>> -{
>> -	struct rte_devargs *devargs;
>> -	int ret;
>> -
>> -	devargs = calloc(1, sizeof(*devargs));
>> -	if (!devargs)
>> -		return NULL;
>> -
>> -	devargs->bus = &rte_vdev_bus;
>> -	if (args)
>> -		devargs->args = strdup(args);
>> -	else
>> -		devargs->args = strdup("");
>> -
>> -	ret = snprintf(devargs->name, sizeof(devargs->name), "%s", name);
>> -	if (ret < 0 || ret >= (int)sizeof(devargs->name)) {
>> -		free(devargs->args);
>> -		free(devargs);
>> -		return NULL;
>> -	}
>> -
>> -	return devargs;
>> -}
>> -
>> -int
>> -rte_vdev_init(const char *name, const char *args)
>> -{
>> -	struct rte_vdev_device *dev;
>> -	struct rte_devargs *devargs;
>> -	int ret;
>> -
>> -	if (name == NULL)
>> -		return -EINVAL;
>> -
>> -	dev = find_vdev(name);
>> -	if (dev)
>> -		return -EEXIST;
>> -
>> -	devargs = alloc_devargs(name, args);
>> -	if (!devargs)
>> -		return -ENOMEM;
>> -
>> -	dev = calloc(1, sizeof(*dev));
>> -	if (!dev) {
>> -		ret = -ENOMEM;
>> -		goto fail;
>> -	}
>> -
>> -	dev->device.devargs = devargs;
>> -	dev->device.numa_node = SOCKET_ID_ANY;
>> -	dev->device.name = devargs->name;
>> -
>> -	ret = vdev_probe_all_drivers(dev);
>> -	if (ret) {
>> -		if (ret > 0)
>> -			RTE_LOG(ERR, EAL, "no driver found for %s\n", name);
>> -		goto fail;
>> -	}
>> -
>> -	TAILQ_INSERT_TAIL(&devargs_list, devargs, next);
>> -
>> -	TAILQ_INSERT_TAIL(&vdev_device_list, dev, next);
>> -	return 0;
>> -
>> -fail:
>> -	free(devargs->args);
>> -	free(devargs);
>> -	free(dev);
>> -	return ret;
>> -}
>> -
>> -static int
>> -vdev_remove_driver(struct rte_vdev_device *dev)
>> -{
>> -	const char *name = rte_vdev_device_name(dev);
>> -	const struct rte_vdev_driver *driver;
>> -
>> -	if (!dev->device.driver) {
>> -		RTE_LOG(DEBUG, EAL, "no driver attach to device %s\n", name);
>> -		return 1;
>> -	}
>> -
>> -	driver = container_of(dev->device.driver, const struct rte_vdev_driver,
>> -		driver);
>> -	return driver->remove(dev);
>> -}
>> -
>> -int
>> -rte_vdev_uninit(const char *name)
>> -{
>> -	struct rte_vdev_device *dev;
>> -	struct rte_devargs *devargs;
>> -	int ret;
>> -
>> -	if (name == NULL)
>> -		return -EINVAL;
>> -
>> -	dev = find_vdev(name);
>> -	if (!dev)
>> -		return -ENOENT;
>> -
>> -	devargs = dev->device.devargs;
>> -
>> -	ret = vdev_remove_driver(dev);
>> -	if (ret)
>> -		return ret;
>> -
>> -	TAILQ_REMOVE(&vdev_device_list, dev, next);
>> -
>> -	TAILQ_REMOVE(&devargs_list, devargs, next);
>> -
>> -	free(devargs->args);
>> -	free(devargs);
>> -	free(dev);
>> -	return 0;
>> -}
>> -
>> -static int
>> -vdev_scan(void)
>> -{
>> -	struct rte_vdev_device *dev;
>> -	struct rte_devargs *devargs;
>> -
>> -	/* for virtual devices we scan the devargs_list populated via cmdline */
>> -	TAILQ_FOREACH(devargs, &devargs_list, next) {
>> -
>> -		if (devargs->bus != &rte_vdev_bus)
>> -			continue;
>> -
>> -		dev = find_vdev(devargs->name);
>> -		if (dev)
>> -			continue;
>> -
>> -		dev = calloc(1, sizeof(*dev));
>> -		if (!dev)
>> -			return -1;
>> -
>> -		dev->device.devargs = devargs;
>> -		dev->device.numa_node = SOCKET_ID_ANY;
>> -		dev->device.name = devargs->name;
>> -
>> -		TAILQ_INSERT_TAIL(&vdev_device_list, dev, next);
>> -	}
>> -
>> -	return 0;
>> -}
>> -
>> -static int
>> -vdev_probe(void)
>> -{
>> -	struct rte_vdev_device *dev;
>> -
>> -	/* call the init function for each virtual device */
>> -	TAILQ_FOREACH(dev, &vdev_device_list, next) {
>> -
>> -		if (dev->device.driver)
>> -			continue;
>> -
>> -		if (vdev_probe_all_drivers(dev)) {
>> -			RTE_LOG(ERR, EAL, "failed to initialize %s device\n",
>> -				rte_vdev_device_name(dev));
>> -			return -1;
>> -		}
>> -	}
>> -
>> -	return 0;
>> -}
>> -
>> -static struct rte_device *
>> -vdev_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,
>> -		 const void *data)
>> -{
>> -	struct rte_vdev_device *dev;
>> -
>> -	TAILQ_FOREACH(dev, &vdev_device_list, next) {
>> -		if (start && &dev->device == start) {
>> -			start = NULL;
>> -			continue;
>> -		}
>> -		if (cmp(&dev->device, data) == 0)
>> -			return &dev->device;
>> -	}
>> -	return NULL;
>> -}
>> -
>> -static int
>> -vdev_plug(struct rte_device *dev)
>> -{
>> -	return vdev_probe_all_drivers(RTE_DEV_TO_VDEV(dev));
>> -}
>> -
>> -static int
>> -vdev_unplug(struct rte_device *dev)
>> -{
>> -	return rte_vdev_uninit(dev->name);
>> -}
>> -
>> -static struct rte_bus rte_vdev_bus = {
>> -	.scan = vdev_scan,
>> -	.probe = vdev_probe,
>> -	.find_device = vdev_find_device,
>> -	.plug = vdev_plug,
>> -	.unplug = vdev_unplug,
>> -	.parse = vdev_parse,
>> -};
>> -
>> -RTE_REGISTER_BUS(vdev, rte_vdev_bus);
>> diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
>> index 5386d3a..8bfc343 100644
>> --- a/lib/librte_eal/common/include/rte_dev.h
>> +++ b/lib/librte_eal/common/include/rte_dev.h
>> @@ -166,28 +166,6 @@ struct rte_device {
>>   };
>>   
>>   /**
>> - * Initialize a driver specified by name.
>> - *
>> - * @param name
>> - *   The pointer to a driver name to be initialized.
>> - * @param args
>> - *   The pointer to arguments used by driver initialization.
>> - * @return
>> - *  0 on success, negative on error
>> - */
>> -int rte_vdev_init(const char *name, const char *args);
>> -
>> -/**
>> - * Uninitalize a driver specified by name.
>> - *
>> - * @param name
>> - *   The pointer to a driver name to be initialized.
>> - * @return
>> - *  0 on success, negative on error
>> - */
>> -int rte_vdev_uninit(const char *name);
>> -
>> -/**
>>    * Attach a device to a registered driver.
>>    *
>>    * @param name
>> @@ -312,4 +290,4 @@ __attribute__((used)) = str
>>   }
>>   #endif
>>   
>> -#endif /* _RTE_VDEV_H_ */
>> +#endif /* _RTE_DEV_H_ */
>> diff --git a/lib/librte_eal/common/include/rte_vdev.h b/lib/librte_eal/common/include/rte_vdev.h
>> deleted file mode 100644
>> index 29f5a52..0000000
>> --- a/lib/librte_eal/common/include/rte_vdev.h
>> +++ /dev/null
>> @@ -1,131 +0,0 @@
>> -/*-
>> - *   BSD LICENSE
>> - *
>> - *   Copyright(c) 2016 RehiveTech. 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 RehiveTech 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.
>> - */
>> -
>> -#ifndef RTE_VDEV_H
>> -#define RTE_VDEV_H
>> -
>> -#ifdef __cplusplus
>> -extern "C" {
>> -#endif
>> -
>> -#include <sys/queue.h>
>> -#include <rte_dev.h>
>> -#include <rte_devargs.h>
>> -
>> -struct rte_vdev_device {
>> -	TAILQ_ENTRY(rte_vdev_device) next;      /**< Next attached vdev */
>> -	struct rte_device device;               /**< Inherit core device */
>> -};
>> -
>> -/**
>> - * @internal
>> - * Helper macro for drivers that need to convert to struct rte_vdev_device.
>> - */
>> -#define RTE_DEV_TO_VDEV(ptr) \
>> -	container_of(ptr, struct rte_vdev_device, device)
>> -
>> -static inline const char *
>> -rte_vdev_device_name(const struct rte_vdev_device *dev)
>> -{
>> -	if (dev && dev->device.name)
>> -		return dev->device.name;
>> -	return NULL;
>> -}
>> -
>> -static inline const char *
>> -rte_vdev_device_args(const struct rte_vdev_device *dev)
>> -{
>> -	if (dev && dev->device.devargs)
>> -		return dev->device.devargs->args;
>> -	return "";
>> -}
>> -
>> -/** Double linked list of virtual device drivers. */
>> -TAILQ_HEAD(vdev_driver_list, rte_vdev_driver);
>> -
>> -/**
>> - * Probe function called for each virtual device driver once.
>> - */
>> -typedef int (rte_vdev_probe_t)(struct rte_vdev_device *dev);
>> -
>> -/**
>> - * Remove function called for each virtual device driver once.
>> - */
>> -typedef int (rte_vdev_remove_t)(struct rte_vdev_device *dev);
>> -
>> -/**
>> - * A virtual device driver abstraction.
>> - */
>> -struct rte_vdev_driver {
>> -	TAILQ_ENTRY(rte_vdev_driver) next; /**< Next in list. */
>> -	struct rte_driver driver;      /**< Inherited general driver. */
>> -	rte_vdev_probe_t *probe;       /**< Virtual device probe function. */
>> -	rte_vdev_remove_t *remove;     /**< Virtual device remove function. */
>> -};
>> -
>> -/**
>> - * Register a virtual device driver.
>> - *
>> - * @param driver
>> - *   A pointer to a rte_vdev_driver structure describing the driver
>> - *   to be registered.
>> - */
>> -void rte_vdev_register(struct rte_vdev_driver *driver);
>> -
>> -/**
>> - * Unregister a virtual device driver.
>> - *
>> - * @param driver
>> - *   A pointer to a rte_vdev_driver structure describing the driver
>> - *   to be unregistered.
>> - */
>> -void rte_vdev_unregister(struct rte_vdev_driver *driver);
>> -
>> -#define RTE_PMD_REGISTER_VDEV(nm, vdrv)\
>> -RTE_INIT(vdrvinitfn_ ##vdrv);\
>> -static const char *vdrvinit_ ## nm ## _alias;\
>> -static void vdrvinitfn_ ##vdrv(void)\
>> -{\
>> -	(vdrv).driver.name = RTE_STR(nm);\
>> -	(vdrv).driver.alias = vdrvinit_ ## nm ## _alias;\
>> -	rte_vdev_register(&vdrv);\
>> -} \
>> -RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
>> -
>> -#define RTE_PMD_REGISTER_ALIAS(nm, alias)\
>> -static const char *vdrvinit_ ## nm ## _alias = RTE_STR(alias)
>> -
>> -#ifdef __cplusplus
>> -}
>> -#endif
>> -
>> -#endif
>> diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
>> index 90bca4d..33faa18 100644
>> --- a/lib/librte_eal/linuxapp/eal/Makefile
>> +++ b/lib/librte_eal/linuxapp/eal/Makefile
>> @@ -80,7 +80,6 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_timer.c
>>   SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memzone.c
>>   SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_log.c
>>   SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_launch.c
>> -SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_vdev.c
>>   SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci.c
>>   SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci_uio.c
>>   SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memory.c
>> diff --git a/mk/rte.app.mk b/mk/rte.app.mk
>> index c25fdd9..c423bf8 100644
>> --- a/mk/rte.app.mk
>> +++ b/mk/rte.app.mk
>> @@ -97,6 +97,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_MEMPOOL)        += -lrte_mempool
>>   _LDLIBS-$(CONFIG_RTE_DRIVER_MEMPOOL_RING)   += -lrte_mempool_ring
>>   _LDLIBS-$(CONFIG_RTE_LIBRTE_RING)           += -lrte_ring
>>   _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
>> +_LDLIBS-$(CONFIG_RTE_LIBRTE_VDEV)           += -lrte_bus_vdev
>>   _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
>>   _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER)        += -lrte_reorder
>>   
>> -- 
>> 2.7.4
>>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC PATCH 2/4] ethdev: introduce Rx queue offloads API
  2017-08-29 12:50  0%   ` Ferruh Yigit
@ 2017-08-30  6:22  0%     ` Shahaf Shuler
  0 siblings, 0 replies; 200+ results
From: Shahaf Shuler @ 2017-08-30  6:22 UTC (permalink / raw)
  To: Ferruh Yigit, dev

Tuesday, August 29, 2017 3:50 PM, Ferruh Yigit:
> On 8/7/2017 11:54 AM, Shahaf Shuler wrote:
> > Introduce a new API to configure Rx offloads.
> >
> > The new API will re-use existing DEV_RX_OFFLOAD_* flags to enable the
> > different offloads. This will ease the process of adding a new Rx
> > offloads, as no ABI breakage is involved.
> > In addition, the offload configuration can be done per queue, instead
> > of per port.
> 
> If a device doesn't have capability to set the offload per queue how should it
> behave, I think it is good to define this.

Yes, will add documentation. 
How about If device cannot set offloads per queue, then the queue_setup function should return with ENOTSUP ?

> 
> >
> > The Rx queue offload API can be used only with devices which advertize
> > the RTE_ETH_DEV_RXQ_OFFLOAD capability.
> >
> > The old Rx offloads API is kept for the meanwhile, in order to enable
> > a smooth transition for PMDs and application to the new API.
> >
> > Signed-off-by: Shahaf Shuler <shahafs@mellanox.com>
> 
> <...>
> 
> > @@ -357,7 +357,14 @@ struct rte_eth_rxmode {
> >  		jumbo_frame      : 1, /**< Jumbo Frame Receipt enable. */
> >  		hw_strip_crc     : 1, /**< Enable CRC stripping by hardware. */
> >  		enable_scatter   : 1, /**< Enable scatter packets rx handler */
> > -		enable_lro       : 1; /**< Enable LRO */
> > +		enable_lro       : 1, /**< Enable LRO */
> > +		ignore		 : 1;
> 
> what do you think making this variable more verbose, like
> "ignore_rx_offloads"
> 
> "dev_conf.rxmode.ignore" doesn't say on its own what is ignored.

Maybe ignore_offloads ? Rx is quite explicit from rxomde.

> 
> > +		/**
> > +		 * When set the rxmode offloads should be ignored,
> > +		 * instead the Rx offloads will be set on rte_eth_rxq_conf.
> > +		 * This bit is temporary till rxmode Rx offloads API will
> > +		 * be deprecated.
> > +		 */
> >  };
> 
> <...>
> 
> > +/** Device supports the rte_eth_rxq_conf offloads API */ #define
> > +RTE_ETH_DEV_RXQ_OFFLOAD 0x0010
> Since this is temporary flag and with current implementation this is local to
> library, should we put this into public header?
> 
> Later when all PMDs implemented this new method and we want to remove
> the flag, can we remove them or do we have to keep them reserved for any
> conflict for further new values?
> 
> I guess this should be part of missing pmd-ethdev interface file
> (rte_ethdev_pmd.h ?).

Yes it is better fits to inner interface between ethdev and PMDs.
Wondering, do we have other motivation to have such header? 

> 
> >
> >  /**
> >   * @internal
> >


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2] vhost: added user callbacks for socket open/close
  2017-08-29  6:08  3%     ` Stojaczyk, DariuszX
@ 2017-08-30  6:33  0%       ` Jens Freimann
  0 siblings, 0 replies; 200+ results
From: Jens Freimann @ 2017-08-30  6:33 UTC (permalink / raw)
  To: Stojaczyk, DariuszX; +Cc: dev, Wodkowski, PawelX, maxime.coquelin, yliu

On Tue, Aug 29, 2017 at 06:08:45AM +0000, Stojaczyk, DariuszX wrote:
>Hi Jens,
>
>> I'm still not sure I understand the use case. So just for my
>> understanding: users need to distinct between "the device is going away
>> temporarily, keep the connection" and "we're shutting down for good", is
>> that it?
>
>Yes, exactly.
>
>> Maybe it's just me or maybe it means you could explain your example in the
>> commit message a bit more.
>
>Ok. How about the following commit message instead:
>```
>rte_vhost: added user callbacks for socket open/close
>
>Added new callbacks to notify about socket connection status.
>As destroy_device is used for virtqueue processing *pause* as
>well as connection close, the user has no distinction between those.
>
>Consider the following scenario:
>rte_vhost: received SET_VRING_BASE message,
>                  calling destroy_device() as usual
>
>user:  end-user asks to remove the device (together with socket file),
>          OK, device is not *in use* - that's NOT the behavior we want
>          calling rte_vhost_driver_unregister() etc.
>
>Instead of changing new_device/destroy_device callbacks and breaking
>the ABI, a set of new functions new_connection/destroy_connection
>has been added.
>```

Sounds good to me. Thanks!

regards,
Jens 

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v3] rte_vhost: added user callbacks for socket open/close
  2017-08-22 16:24  3% ` [dpdk-dev] [PATCH v2] " Dariusz Stojaczyk
  2017-08-25  9:22  0%   ` Jens Freimann
@ 2017-08-30 10:50  3%   ` Dariusz Stojaczyk
  1 sibling, 0 replies; 200+ results
From: Dariusz Stojaczyk @ 2017-08-30 10:50 UTC (permalink / raw)
  To: dev; +Cc: Pawel Wodkowski, jfreimann, maxime.coquelin, yliu, Dariusz Stojaczyk

Added new callbacks to notify about socket connection status.
As destroy_device is used for virtqueue processing *pause* as well as
connection close, the user has no distinction between those.

Consider the following scenario:
rte_vhost: received SET_VRING_BASE message,
           calling destroy_device() as usual

user:  end-user asks to remove the device (together with socket file),
       OK, device is not *in use* - that's NOT the behavior we want
       calling rte_vhost_driver_unregister() etc.

Instead of changing new_device/destroy_device callbacks and breaking
the ABI, a set of new functions new_connection/destroy_connection
has been added.

Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
---
v3: improved err-handling path and updated commit msg
v2: also updated vhost_lib.rst
 lib/librte_vhost/rte_vhost.h |  5 ++++-
 lib/librte_vhost/socket.c    | 31 ++++++++++++++++++++++++-------
 2 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h
index 8c974eb..fe5c94c 100644
--- a/lib/librte_vhost/rte_vhost.h
+++ b/lib/librte_vhost/rte_vhost.h
@@ -107,7 +107,10 @@ struct vhost_device_ops {
 	 */
 	int (*features_changed)(int vid, uint64_t features);
 
-	void *reserved[4]; /**< Reserved for future extension */
+	int (*new_connection)(int vid);
+	void (*destroy_connection)(int vid);
+
+	void *reserved[2]; /**< Reserved for future extension */
 };
 
 /**
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 41aa3f9..7018150 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -217,9 +217,7 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 
 	vid = vhost_new_device();
 	if (vid == -1) {
-		close(fd);
-		free(conn);
-		return;
+		goto err;
 	}
 
 	size = strnlen(vsocket->path, PATH_MAX);
@@ -230,24 +228,40 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
 
 	RTE_LOG(INFO, VHOST_CONFIG, "new device, handle is %d\n", vid);
 
+	if (vsocket->notify_ops->new_connection) {
+		ret = vsocket->notify_ops->new_connection(vid);
+		if (ret < 0) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"failed to add vhost user connection with fd %d\n",
+				fd);
+			goto err;
+		}
+	}
+
 	conn->connfd = fd;
 	conn->vsocket = vsocket;
 	conn->vid = vid;
 	ret = fdset_add(&vhost_user.fdset, fd, vhost_user_read_cb,
 			NULL, conn);
 	if (ret < 0) {
-		conn->connfd = -1;
-		free(conn);
-		close(fd);
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"failed to add fd %d into vhost server fdset\n",
 			fd);
-		return;
+
+		if (vsocket->notify_ops->destroy_connection)
+			vsocket->notify_ops->destroy_connection(conn->vid);
+
+		goto err;
 	}
 
 	pthread_mutex_lock(&vsocket->conn_mutex);
 	TAILQ_INSERT_TAIL(&vsocket->conn_list, conn, next);
 	pthread_mutex_unlock(&vsocket->conn_mutex);
+	return;
+
+err:
+	free(conn);
+	close(fd);
 }
 
 /* call back when there is new vhost-user connection from client  */
@@ -277,6 +291,9 @@ vhost_user_read_cb(int connfd, void *dat, int *remove)
 		*remove = 1;
 		vhost_destroy_device(conn->vid);
 
+		if (vsocket->notify_ops->destroy_connection)
+			vsocket->notify_ops->destroy_connection(conn->vid);
+
 		pthread_mutex_lock(&vsocket->conn_mutex);
 		TAILQ_REMOVE(&vsocket->conn_list, conn, next);
 		pthread_mutex_unlock(&vsocket->conn_mutex);
-- 
2.7.4

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH] devtools: rework abi checker script
@ 2017-08-30 13:51 27% Olivier Matz
  2017-09-04 16:00  8% ` Bruce Richardson
  2017-09-06 14:51 27% ` [dpdk-dev] [PATCH v2] " Olivier Matz
  0 siblings, 2 replies; 200+ results
From: Olivier Matz @ 2017-08-30 13:51 UTC (permalink / raw)
  To: dev, nhorman

The intiatial version of the script had some limitations:
- cannot work on a non-clean workspace
- environment variables are not documented
- no compilation log in case of failure
- return success even it abi is incompatible

This patch addresses these issues and rework the code.

Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
 devtools/validate-abi.sh | 387 ++++++++++++++++++++++++-----------------------
 1 file changed, 195 insertions(+), 192 deletions(-)

diff --git a/devtools/validate-abi.sh b/devtools/validate-abi.sh
index 0accc99b1..5efcccc90 100755
--- a/devtools/validate-abi.sh
+++ b/devtools/validate-abi.sh
@@ -1,7 +1,8 @@
-#!/bin/sh
+#!/bin/bash -e
 #   BSD LICENSE
 #
 #   Copyright(c) 2015 Neil Horman. All rights reserved.
+#   Copyright(c) 2017 6WIND S.A.
 #   All rights reserved.
 #
 #   Redistribution and use in source and binary forms, with or without
@@ -27,236 +28,238 @@
 #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-TAG1=$1
-TAG2=$2
-TARGET=$3
-ABI_DIR=`mktemp -d -p /tmp ABI.XXXXXX`
+abicheck=abi-compliance-checker
+abidump=abi-dumper
+default_dst=abi-check
+default_target=x86_64-native-linuxapp-gcc
 
-usage() {
-	echo "$0 <REV1> <REV2> <TARGET>"
+# trap on error
+err_report() {
+    echo "$0: error at line $1"
 }
+trap 'err_report $LINENO' ERR
 
-log() {
-	local level=$1
-	shift
-	echo "$*"
-}
+print_usage () {
+	cat <<- END_OF_HELP
+	$(basename $0) [options] <rev1> <rev2>
 
-validate_tags() {
+	This script compares the ABI of 2 git revisions of the current
+	workspace. The output is a html report and a compilation log.
 
-	if [ -z "$HASH1" ]
-	then
-		echo "invalid revision: $TAG1"
-		return
-	fi
-	if [ -z "$HASH2" ]
-	then
-		echo "invalid revision: $TAG2"
-		return
-	fi
+	The objective is to make sure that applications built against
+	DSOs from the first revision can still run when executed using
+	the DSOs built from the second revision.
+
+	<rev1> and <rev2> are git commit id or tags.
+
+	Options:
+	  -h		show this help
+	  -j <num>	enable parallel compilation with <num> threads
+	  -v		show compilation logs on the console
+	  -d <dir>	change working directory (default is ${default_dst})
+	  -t <target>	the dpdk target to use (default is ${default_target})
+	  -f		override existing destination directory
+
+	The script returns 0 on success, or the value of last failing
+	call of ${abicheck} (incompatible abi or the tool has run with errors).
+	The errors returned by ${abidump} are ignored.
+
+	END_OF_HELP
 }
 
-validate_args() {
-	if [ -z "$TAG1" ]
-	then
-		echo "Must Specify REV1"
-		return
-	fi
-	if [ -z "$TAG2" ]
-	then
-		echo "Must Specify REV2"
-		return
-	fi
-	if [ -z "$TARGET" ]
-	then
-		echo "Must Specify a build target"
+# log in the file, and on stdout if verbose
+# $1: level string
+# $2: string to be logged
+log() {
+	echo "$1: $2"
+	if [ "${verbose}" != "true" ]; then
+		echo "$1: $2" >&3
 	fi
 }
 
+# launch a command and log it, taking care of surrounding spaces with quotes
+cmd() {
+	local i s whitespace
+	s=""
+	whitespace="[[:space:]]"
+	for i in "$@"; do
+		if [[ $i =~ $whitespace ]]; then
+			i=\"$i\"
+		fi
+		if [ -z "$s" ]; then
+			s="$i"
+		else
+			s="$s $i"
+		fi
+	done
+
+	log "CMD" "$s"
+	"$@"
+}
 
-cleanup_and_exit() {
-	rm -rf $ABI_DIR
-	git checkout $CURRENT_BRANCH
-	exit $1
+# redirect or copy stderr/stdout to a file
+# the syntax is unfamiliar, but it makes the rest of the
+# code easier to read, avoiding the use of pipes
+set_log_file() {
+	# save original stdout and stderr in fd 3 and 4
+	exec 3>&1
+	exec 4>&2
+	# create a new fd 5 that send to a file
+	exec 5> >(cat > $1)
+	# send stdout and stderr to fd 5
+	if [ "${verbose}" = "true" ]; then
+		exec 1> >(tee /dev/fd/5 >&3)
+		exec 2> >(tee /dev/fd/5 >&4)
+	else
+		exec 1>&5
+		exec 2>&5
+	fi
 }
 
 # Make sure we configure SHARED libraries
 # Also turn off IGB and KNI as those require kernel headers to build
 fixup_config() {
-	sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" config/defconfig_$TARGET
-	sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" config/defconfig_$TARGET
-	sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" config/defconfig_$TARGET
-	sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" config/defconfig_$TARGET
-	sed -i -e"$ a\CONFIG_RTE_KNI_KMOD=n" config/defconfig_$TARGET
+	local conf=config/defconfig_$target
+	cmd sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" $conf
+	cmd sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" $conf
+	cmd sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" $conf
+	cmd sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" $conf
+	cmd sed -i -e"$ a\CONFIG_RTE_KNI_KMOD=n" $conf
 }
 
-###########################################
-#START
-############################################
+# build dpdk for the given tag and dump abi
+# $1: hash of the revision
+gen_abi() {
+	cmd git clone $(dirname $0)/.. ${dst}/${1}
+	cmd cd ${dst}/${1}
+
+	log "INFO" "Checking out version ${1} of the dpdk"
+	# Move to the old version of the tree
+	cmd git checkout ${1}
+
+	fixup_config
+
+	# Now configure the build
+	log "INFO" "Configuring DPDK ${1}"
+	cmd make config T=$target O=$target > ${dst}/log 2>&1
+
+	# Checking abi compliance relies on using the dwarf information in
+	# the shared objects. Build with -g to include them.
+	log "INFO" "Building DPDK ${1}. This might take a moment"
+	cmd make -j$parallel O=$target V=1 EXTRA_CFLAGS="-g -O0" \
+	    EXTRA_LDFLAGS="-g" || log "INFO" "The build failed"
+
+	# Move to the lib directory
+	cmd cd ${PWD}/$target/lib
+	log "INFO" "Collecting ABI information for ${1}"
+	for i in *.so; do
+		[ -e "$i" ] || break
+		cmd $abidump ${i} -o $dst/${1}/${i}.dump -lver ${1} || true
+		# hack to ignore empty SymbolsInfo section (no public ABI)
+		if grep -q "'SymbolInfo' => {}," $dst/${1}/${i}.dump \
+				2> /dev/null; then
+			log "INFO" "${i} has no public ABI, remove dump file"
+			cmd rm -f $dst/${1}/${i}.dump
+		fi
+	done
+	cmd cd ../..
+}
 
-#trap on ctrl-c to clean up
-trap cleanup_and_exit SIGINT
+verbose=false
+parallel=1
+dst=${default_dst}
+target=${default_target}
+force=0
+while getopts j:vd:t:fh ARG ; do
+	case $ARG in
+		j ) parallel=$OPTARG ;;
+		v ) verbose=true ;;
+		d ) dst=$OPTARG ;;
+		t ) target=$OPTARG ;;
+		f ) force=1 ;;
+		h ) print_usage ; exit 0 ;;
+		? ) print_usage ; exit 1 ;;
+	esac
+done
+shift $(($OPTIND - 1))
 
-if [ -z "$DPDK_MAKE_JOBS" ]
-then
-	# This counts the number of cpus on the system
-	if [ -e /usr/bin/lscpu ]
-	then
-		DPDK_MAKE_JOBS=`lscpu -p=cpu | grep -v "#" | wc -l`
-	else
-		DPDK_MAKE_JOBS=1
-	fi
+if [ $# != 2 ]; then
+	print_usage
+	exit 1
 fi
 
-#Save the current branch
-CURRENT_BRANCH=`git branch | grep \* | cut -d' ' -f2`
+tag1=$1
+tag2=$2
 
-if [ -z "$CURRENT_BRANCH" ]
-then
-	CURRENT_BRANCH=`git log --pretty=format:%H HEAD~1..HEAD`
-fi
+# convert path to absolute
+case "${dst}" in
+	/*) ;;
+	*) dst=${PWD}/${dst} ;;
+esac
 
-if [ -n "$VERBOSE" ]
-then
-	export VERBOSE=/dev/stdout
-else
-	export VERBOSE=/dev/null
+if [ -e "${dst}" -a "$force" = 0 ]; then
+	echo "The ${dst} directory is not empty. Remove it, use another"
+	echo "one (-d <dir>), or force overriding (-f)"
+	exit 1
 fi
 
-# Validate that we have all the arguments we need
-res=$(validate_args)
-if [ -n "$res" ]
-then
-	echo $res
-	usage
-	cleanup_and_exit 1
-fi
+rm -rf ${dst}
+mkdir -p ${dst}
+set_log_file ${dst}/abi-check.log
+log "INFO" "Logs available in ${dst}/abi-check.log"
 
-HASH1=$(git show -s --format=%H "$TAG1" -- 2> /dev/null | tail -1)
-HASH2=$(git show -s --format=%H "$TAG2" -- 2> /dev/null | tail -1)
+command -v ${abicheck} || log "INFO" "Can't find ${abicheck} utility"
+command -v ${abidump} || log "INFO" "Can't find ${abidump} utility"
 
-# Make sure our tags exist
-res=$(validate_tags)
-if [ -n "$res" ]
-then
-	echo $res
-	cleanup_and_exit 1
-fi
+hash1=$(git show -s --format=%h "$tag1" -- 2> /dev/null | tail -1)
+hash2=$(git show -s --format=%h "$tag2" -- 2> /dev/null | tail -1)
 
 # Make hashes available in output for non-local reference
-TAG1="$TAG1 ($HASH1)"
-TAG2="$TAG2 ($HASH2)"
-
-ABICHECK=`which abi-compliance-checker 2>/dev/null`
-if [ $? -ne 0 ]
-then
-	log "INFO" "Can't find abi-compliance-checker utility"
-	cleanup_and_exit 1
-fi
-
-ABIDUMP=`which abi-dumper 2>/dev/null`
-if [ $? -ne 0 ]
-then
-	log "INFO" "Can't find abi-dumper utility"
-	cleanup_and_exit 1
-fi
+tag1="$tag1 ($hash1)"
+tag2="$tag2 ($hash2)"
 
-log "INFO" "We're going to check and make sure that applications built"
-log "INFO" "against DPDK DSOs from version $TAG1 will still run when executed"
-log "INFO" "against DPDK DSOs built from version $TAG2."
-log "INFO" ""
-
-# Check to make sure we have a clean tree
-git status | grep -q clean
-if [ $? -ne 0 ]
-then
-	log "WARN" "Working directory not clean, aborting"
-	cleanup_and_exit 1
+if [ "$hash1" = "$hash2" ]; then
+	log "ERROR" "$tag1 and $tag2 are the same revisions"
+	exit 1
 fi
 
-# Move to the root of the git tree
-cd $(dirname $0)/..
+cmd mkdir -p ${dst}
 
-log "INFO" "Checking out version $TAG1 of the dpdk"
-# Move to the old version of the tree
-git checkout $HASH1
+# dump abi for each revision
+gen_abi ${hash1}
+gen_abi ${hash2}
 
-fixup_config
+# compare the abi dumps
+ret=0
+list=""
+for i in ${dst}/${hash2}/*.dump; do
+	name=`basename $i`
+	libname=${name%.dump}
 
-# Checking abi compliance relies on using the dwarf information in
-# The shared objects.  Thats only included in the DSO's if we build
-# with -g
-export EXTRA_CFLAGS="$EXTRA_CFLAGS -g -O0"
-export EXTRA_LDFLAGS="$EXTRA_LDFLAGS -g"
-
-# Now configure the build
-log "INFO" "Configuring DPDK $TAG1"
-make config T=$TARGET O=$TARGET > $VERBOSE 2>&1
-
-log "INFO" "Building DPDK $TAG1. This might take a moment"
-make -j$DPDK_MAKE_JOBS O=$TARGET > $VERBOSE 2>&1
-
-if [ $? -ne 0 ]
-then
-	log "INFO" "THE BUILD FAILED.  ABORTING"
-	cleanup_and_exit 1
-fi
+	if [ ! -f $dst/${hash1}/$name ]; then
+		log "INFO" "$NAME does not exist in $tag1. skipping..."
+		continue
+	fi
 
-# Move to the lib directory
-cd $TARGET/lib
-log "INFO" "COLLECTING ABI INFORMATION FOR $TAG1"
-for i in `ls *.so`
-do
-	$ABIDUMP $i -o $ABI_DIR/$i-ABI-0.dump -lver $HASH1
+	local_ret=0
+	cmd $abicheck -l $libname \
+	    -old $dst/${hash1}/$name -new $dst/${hash2}/$name || local_ret=$?
+	if [ $local_ret != 0 ]; then
+		log "NOTICE" "$abicheck returned $local_ret"
+		ret=$local_ret
+		list="$list $libname"
+	fi
 done
-cd ../..
-
-# Now clean the tree, checkout the second tag, and rebuild
-git clean -f -d
-git reset --hard
-# Move to the new version of the tree
-log "INFO" "Checking out version $TAG2 of the dpdk"
-git checkout $HASH2
-
-fixup_config
-
-# Now configure the build
-log "INFO" "Configuring DPDK $TAG2"
-make config T=$TARGET O=$TARGET > $VERBOSE 2>&1
-
-log "INFO" "Building DPDK $TAG2. This might take a moment"
-make -j$DPDK_MAKE_JOBS O=$TARGET > $VERBOSE 2>&1
 
-if [ $? -ne 0 ]
-then
-	log "INFO" "THE BUILD FAILED.  ABORTING"
-	cleanup_and_exit 1
+if [ $ret != 0 ]; then
+	log "NOTICE" "At least one call to $abicheck returned an error."
+	log "NOTICE" "ABI may be incompatible, please check logs for details."
+	log "NOTICE" "Incompatible list: $list"
+else
+	log "NOTICE" "No error detected, ABI is compatible."
 fi
 
-cd $TARGET/lib
-log "INFO" "COLLECTING ABI INFORMATION FOR $TAG2"
-for i in `ls *.so`
-do
-	$ABIDUMP $i -o $ABI_DIR/$i-ABI-1.dump -lver $HASH2
-done
-cd ../..
-
-# Start comparison of ABI dumps
-for i in `ls $ABI_DIR/*-1.dump`
-do
-	NEWNAME=`basename $i`
-	OLDNAME=`basename $i | sed -e"s/1.dump/0.dump/"`
-	LIBNAME=`basename $i | sed -e"s/-ABI-1.dump//"`
-
-	if [ ! -f $ABI_DIR/$OLDNAME ]
-	then
-		log "INFO" "$OLDNAME DOES NOT EXIST IN $TAG1. SKIPPING..."
-	fi
-
-	#compare the abi dumps
-	$ABICHECK -l $LIBNAME -old $ABI_DIR/$OLDNAME -new $ABI_DIR/$NEWNAME
-done
+log "INFO" "Logs are in ${dst}/abi-check.log"
+log "INFO" "HTML reports are in ${dst}/compat_reports directory"
 
-git reset --hard
-log "INFO" "ABI CHECK COMPLETE.  REPORTS ARE IN compat_report directory"
-cleanup_and_exit 0
+exit $ret
-- 
2.11.0

^ permalink raw reply	[relevance 27%]

* [dpdk-dev] [PATCH 5/6] eal: remove xen dom0 support
  @ 2017-08-30 18:10  1% ` Jianfeng Tan
  2017-09-04 14:43  3%   ` Bruce Richardson
  2017-08-30 18:10  3% ` [dpdk-dev] [PATCH 6/6] eal: remove API rte_mem_phy2mch Jianfeng Tan
  1 sibling, 1 reply; 200+ results
From: Jianfeng Tan @ 2017-08-30 18:10 UTC (permalink / raw)
  To: dev
  Cc: xen-devel, thomas, john.mcnamara, oao.m.martins, jerin.jacob,
	shahafs, Jianfeng Tan

We remove xen-specific code in EAL, including the option --xen-dom0,
memory initialization code, compiling dependency, etc.

Besides, related documents are removed or updated.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 MAINTAINERS                                        |   7 -
 config/common_base                                 |   5 -
 doc/guides/index.rst                               |   1 -
 doc/guides/linux_gsg/build_sample_apps.rst         |   5 +-
 doc/guides/linux_gsg/sys_reqs.rst                  |  53 --
 doc/guides/prog_guide/source_org.rst               |   1 -
 doc/guides/rel_notes/deprecation.rst               |   3 -
 doc/guides/rel_notes/release_17_11.rst             |  12 +
 doc/guides/testpmd_app_ug/run_app.rst              |   4 -
 doc/guides/xen/img/dpdk_xen_pkt_switch.png         | Bin 163842 -> 0 bytes
 doc/guides/xen/img/grant_refs.png                  | Bin 6405 -> 0 bytes
 doc/guides/xen/img/grant_table.png                 | Bin 96762 -> 0 bytes
 doc/guides/xen/index.rst                           |  38 -
 doc/guides/xen/pkt_switch.rst                      | 470 -------------
 .../bsdapp/eal/include/exec-env/rte_dom0_common.h  | 107 ---
 lib/librte_eal/common/eal_common_options.c         |   3 -
 lib/librte_eal/common/eal_internal_cfg.h           |   1 -
 lib/librte_eal/common/eal_options.h                |   2 -
 lib/librte_eal/common/include/rte_memory.h         |  66 --
 lib/librte_eal/linuxapp/Makefile                   |   2 -
 lib/librte_eal/linuxapp/eal/Makefile               |   5 +-
 lib/librte_eal/linuxapp/eal/eal.c                  |  24 -
 lib/librte_eal/linuxapp/eal/eal_memory.c           |  56 --
 lib/librte_eal/linuxapp/eal/eal_xen_memory.c       | 381 ----------
 .../eal/include/exec-env/rte_dom0_common.h         | 108 ---
 lib/librte_eal/linuxapp/igb_uio/igb_uio.c          |  54 --
 lib/librte_eal/linuxapp/xen_dom0/Makefile          |  53 --
 lib/librte_eal/linuxapp/xen_dom0/compat.h          |  15 -
 lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h     | 107 ---
 lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c    | 780 ---------------------
 pkg/dpdk.spec                                      |   3 -
 31 files changed, 14 insertions(+), 2352 deletions(-)
 delete mode 100644 doc/guides/xen/img/dpdk_xen_pkt_switch.png
 delete mode 100644 doc/guides/xen/img/grant_refs.png
 delete mode 100644 doc/guides/xen/img/grant_table.png
 delete mode 100644 doc/guides/xen/index.rst
 delete mode 100644 doc/guides/xen/pkt_switch.rst
 delete mode 100644 lib/librte_eal/bsdapp/eal/include/exec-env/rte_dom0_common.h
 delete mode 100644 lib/librte_eal/linuxapp/eal/eal_xen_memory.c
 delete mode 100644 lib/librte_eal/linuxapp/eal/include/exec-env/rte_dom0_common.h
 delete mode 100644 lib/librte_eal/linuxapp/xen_dom0/Makefile
 delete mode 100644 lib/librte_eal/linuxapp/xen_dom0/compat.h
 delete mode 100644 lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h
 delete mode 100644 lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 003e72e..2af32ff 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -189,13 +189,6 @@ Linux VFIO
 M: Anatoly Burakov <anatoly.burakov@intel.com>
 F: lib/librte_eal/linuxapp/eal/*vfio*
 
-Linux Xen
-M: Jianfeng Tan <jianfeng.tan@intel.com>
-F: lib/librte_eal/linuxapp/xen_dom0/
-F: lib/librte_eal/linuxapp/eal/*xen*
-F: lib/librte_eal/linuxapp/eal/include/exec-env/rte_dom0_common.h
-F: doc/guides/xen/
-
 FreeBSD EAL (with overlaps)
 M: Bruce Richardson <bruce.richardson@intel.com>
 M: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
diff --git a/config/common_base b/config/common_base
index 93928b6..17d3dae 100644
--- a/config/common_base
+++ b/config/common_base
@@ -719,11 +719,6 @@ CONFIG_RTE_LIBRTE_VHOST_DEBUG=n
 CONFIG_RTE_LIBRTE_PMD_VHOST=n
 
 #
-#Compile Xen domain0 support
-#
-CONFIG_RTE_LIBRTE_XEN_DOM0=n
-
-#
 # Compile the test application
 #
 CONFIG_RTE_APP_TEST=y
diff --git a/doc/guides/index.rst b/doc/guides/index.rst
index 63716b0..5b6eb7e 100644
--- a/doc/guides/index.rst
+++ b/doc/guides/index.rst
@@ -44,7 +44,6 @@ DPDK documentation
    nics/index
    cryptodevs/index
    eventdevs/index
-   xen/index
    contributing/index
    rel_notes/index
    faq/index
diff --git a/doc/guides/linux_gsg/build_sample_apps.rst b/doc/guides/linux_gsg/build_sample_apps.rst
index 0cc5fd1..582984d 100644
--- a/doc/guides/linux_gsg/build_sample_apps.rst
+++ b/doc/guides/linux_gsg/build_sample_apps.rst
@@ -116,7 +116,7 @@ The following is the list of options that can be given to the EAL:
 
     ./rte-app [-c COREMASK | -l CORELIST] [-n NUM] [-b <domain:bus:devid.func>] \
               [--socket-mem=MB,...] [-d LIB.so|DIR] [-m MB] [-r NUM] [-v] [--file-prefix] \
-	      [--proc-type <primary|secondary|auto>] [-- xen-dom0]
+	      [--proc-type <primary|secondary|auto>]
 
 The EAL options are as follows:
 
@@ -163,9 +163,6 @@ The EAL options are as follows:
 * ``--proc-type``:
   The type of process instance.
 
-* ``--xen-dom0``:
-  Support application running on Xen Domain0 without hugetlbfs.
-
 * ``--vmware-tsc-map``:
   Use VMware TSC map instead of native RDTSC.
 
diff --git a/doc/guides/linux_gsg/sys_reqs.rst b/doc/guides/linux_gsg/sys_reqs.rst
index eb8442c..3e7fe63 100644
--- a/doc/guides/linux_gsg/sys_reqs.rst
+++ b/doc/guides/linux_gsg/sys_reqs.rst
@@ -228,56 +228,3 @@ The mount point can be made permanent across reboots, by adding the following li
 For 1GB pages, the page size must be specified as a mount option::
 
     nodev /mnt/huge_1GB hugetlbfs pagesize=1GB 0 0
-
-Xen Domain0 Support in the Linux Environment
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The existing memory management implementation is based on the Linux kernel hugepage mechanism.
-On the Xen hypervisor, hugepage support for DomainU (DomU) Guests means that DPDK applications work as normal for guests.
-
-However, Domain0 (Dom0) does not support hugepages.
-To work around this limitation, a new kernel module rte_dom0_mm is added to facilitate the allocation and mapping of memory via
-**IOCTL** (allocation) and **MMAP** (mapping).
-
-Enabling Xen Dom0 Mode in the DPDK
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-By default, Xen Dom0 mode is disabled in the DPDK build configuration files.
-To support Xen Dom0, the CONFIG_RTE_LIBRTE_XEN_DOM0 setting should be changed to “y”, which enables the Xen Dom0 mode at compile time.
-
-Furthermore, the CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID setting should also be changed to “y” in the case of the wrong socket ID being received.
-
-Loading the DPDK rte_dom0_mm Module
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-To run any DPDK application on Xen Dom0, the ``rte_dom0_mm`` module must be loaded into the running kernel with rsv_memsize option.
-The module is found in the kmod sub-directory of the DPDK target directory.
-This module should be loaded using the insmod command as shown below (assuming that the current directory is the DPDK target directory)::
-
-    sudo insmod kmod/rte_dom0_mm.ko rsv_memsize=X
-
-The value X cannot be greater than 4096(MB).
-
-Configuring Memory for DPDK Use
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-After the rte_dom0_mm.ko kernel module has been loaded, the user must configure the memory size for DPDK usage.
-This is done by echoing the memory size to a memsize file in the /sys/devices/ directory.
-Use the following command (assuming that 2048 MB is required)::
-
-    echo 2048 > /sys/kernel/mm/dom0-mm/memsize-mB/memsize
-
-The user can also check how much memory has already been used::
-
-    cat /sys/kernel/mm/dom0-mm/memsize-mB/memsize_rsvd
-
-Xen Domain0 does not support NUMA configuration, as a result the ``--socket-mem`` command line option is invalid for Xen Domain0.
-
-.. note::
-
-    The memsize value cannot be greater than the rsv_memsize value.
-
-Running the DPDK Application on Xen Domain0
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-To run the DPDK application on Xen Domain0, an extra command line option ``--xen-dom0`` is required.
diff --git a/doc/guides/prog_guide/source_org.rst b/doc/guides/prog_guide/source_org.rst
index d5d01f3..7aab4b4 100644
--- a/doc/guides/prog_guide/source_org.rst
+++ b/doc/guides/prog_guide/source_org.rst
@@ -108,7 +108,6 @@ The drivers directory has a *net* subdirectory which contains::
     +-- szedata2           # SZEDATA2 poll mode driver
     +-- virtio             # Virtio poll mode driver
     +-- vmxnet3            # VMXNET3 poll mode driver
-    +-- xenvirt            # Xen virtio poll mode driver
 
 .. note::
 
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 3362f33..7a2d2f2 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -29,9 +29,6 @@ Deprecation Notices
   - ``rte_eal_devargs_type_count``
   - ``rte_eal_parse_devargs_str``, replaced by ``rte_eal_devargs_parse``
 
-* eal: the support of Xen dom0 will be removed from EAL in 17.11; and with
-  that, drivers/net/xenvirt and examples/vhost_xen will also be removed.
-
 * eal: An ABI change is planned for 17.11 to make DPDK aware of IOVA address
   translation scheme.
   Reference to phys address in EAL data-structure or functions may change to
diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f9..d211084 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -124,7 +124,19 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+Removed Items
+-------------
 
+.. This section should contain removed items in this release. Sample format:
+
+   * Add a short 1-2 sentence description of the removed item in the past
+     tense.
+
+   This section is a comment. do not overwrite or remove it.
+   Also, make sure to start the actual text at the margin.
+   =========================================================
+
+   * Xen dom0 in EAL was removed, as well as xenvirt PMD and vhost_xen.
 
 Shared Library Versions
 -----------------------
diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
index e8303f3..bd5ebe6 100644
--- a/doc/guides/testpmd_app_ug/run_app.rst
+++ b/doc/guides/testpmd_app_ug/run_app.rst
@@ -94,10 +94,6 @@ See the DPDK Getting Started Guides for more information on these options.
 
     Display the version information on startup.
 
-*   ``--xen-dom0``
-
-    Support application running on Xen Domain0 without hugetlbfs.
-
 *   ``--syslog``
 
     Set the syslog facility.
diff --git a/doc/guides/xen/img/dpdk_xen_pkt_switch.png b/doc/guides/xen/img/dpdk_xen_pkt_switch.png
deleted file mode 100644
index 32a6d1618820e930b17231f8fe38aab5d5c5d370..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 163842
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

diff --git a/doc/guides/xen/img/grant_refs.png b/doc/guides/xen/img/grant_refs.png
deleted file mode 100644
index baa34e1e3f5e8975ae0516a09f906933b1ac688d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 6405
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
R9${aAy7JpMP(_Qd{{c{~dJX^p

diff --git a/doc/guides/xen/img/grant_table.png b/doc/guides/xen/img/grant_table.png
deleted file mode 100644
index c23e5fa73e660c5be9c7cd01f55ff34e2917632b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 96762
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
Z{{xM~vTICa&vpO+002ovPDHLkV1nHvhjah{

diff --git a/doc/guides/xen/index.rst b/doc/guides/xen/index.rst
deleted file mode 100644
index cb43cd2..0000000
--- a/doc/guides/xen/index.rst
+++ /dev/null
@@ -1,38 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2010-2014 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.
-
-Xen Guide
-=========
-
-.. toctree::
-    :maxdepth: 2
-    :numbered:
-
-    pkt_switch
diff --git a/doc/guides/xen/pkt_switch.rst b/doc/guides/xen/pkt_switch.rst
deleted file mode 100644
index 717a04b..0000000
--- a/doc/guides/xen/pkt_switch.rst
+++ /dev/null
@@ -1,470 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2010-2014 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.
-
-DPDK Xen Based Packet-Switching Solution
-========================================
-
-Introduction
-------------
-
-DPDK provides a para-virtualization packet switching solution, based on the Xen hypervisor's Grant Table, Note 1,
-which provides simple and fast packet switching capability between guest domains and host domain based on MAC address or VLAN tag.
-
-This solution is comprised of two components;
-a Poll Mode Driver (PMD) as the front end in the guest domain and a switching back end in the host domain.
-XenStore is used to exchange configure information between the PMD front end and switching back end,
-including grant reference IDs for shared Virtio RX/TX rings,
-MAC address, device state, and so on. XenStore is an information storage space shared between domains,
-see further information on XenStore below.
-
-The front end PMD can be found in the DPDK directory lib/ librte_pmd_xenvirt and back end example in examples/vhost_xen.
-
-The PMD front end and switching back end use shared Virtio RX/TX rings as para- virtualized interface.
-The Virtio ring is created by the front end, and Grant table references for the ring are passed to host.
-The switching back end maps those grant table references and creates shared rings in a mapped address space.
-
-The following diagram describes the functionality of the DPDK Xen Packet- Switching Solution.
-
-
-.. _figure_dpdk_xen_pkt_switch:
-
-.. figure:: img/dpdk_xen_pkt_switch.*
-
-   Functionality of the DPDK Xen Packet Switching Solution.
-
-
-Note 1 The Xen hypervisor uses a mechanism called a Grant Table to share memory between domains
-(`http://wiki.xen.org/wiki/Grant Table <http://wiki.xen.org/wiki/Grant%20Table>`_).
-
-A diagram of the design is shown below, where "gva" is the Guest Virtual Address,
-which is the data pointer of the mbuf, and "hva" is the Host Virtual Address:
-
-
-.. _figure_grant_table:
-
-.. figure:: img/grant_table.*
-
-   DPDK Xen Layout
-
-
-In this design, a Virtio ring is used as a para-virtualized interface for better performance over a Xen private ring
-when packet switching to and from a VM.
-The additional performance is gained by avoiding a system call and memory map in each memory copy with a XEN private ring.
-
-Device Creation
----------------
-
-Poll Mode Driver Front End
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-*   Mbuf pool allocation:
-
-    To use a Xen switching solution, the DPDK application should use rte_mempool_gntalloc_create()
-    to reserve mbuf pools during initialization.
-    rte_mempool_gntalloc_create() creates a mempool with objects from memory allocated and managed via gntalloc/gntdev.
-
-    The DPDK now supports construction of mempools from allocated virtual memory through the rte_mempool_xmem_create() API.
-
-    This front end constructs mempools based on memory allocated through the xen_gntalloc driver.
-    rte_mempool_gntalloc_create() allocates Grant pages, maps them to continuous virtual address space,
-    and calls rte_mempool_xmem_create() to build mempools.
-    The Grant IDs for all Grant pages are passed to the host through XenStore.
-
-*   Virtio Ring Creation:
-
-    The Virtio queue size is defined as 256 by default in the VQ_DESC_NUM macro.
-    Using the queue setup function,
-    Grant pages are allocated based on ring size and are mapped to continuous virtual address space to form the Virtio ring.
-    Normally, one ring is comprised of several pages.
-    Their Grant IDs are passed to the host through XenStore.
-
-    There is no requirement that this memory be physically continuous.
-
-*   Interrupt and Kick:
-
-    There are no interrupts in DPDK Xen Switching as both front and back ends work in polling mode.
-    There is no requirement for notification.
-
-*   Feature Negotiation:
-
-    Currently, feature negotiation through XenStore is not supported.
-
-*   Packet Reception & Transmission:
-
-    With mempools and Virtio rings created, the front end can operate Virtio devices,
-    as it does in Virtio PMD for KVM Virtio devices with the exception that the host
-    does not require notifications or deal with interrupts.
-
-XenStore is a database that stores guest and host information in the form of (key, value) pairs.
-The following is an example of the information generated during the startup of the front end PMD in a guest VM (domain ID 1):
-
-.. code-block:: console
-
-        xenstore -ls /local/domain/1/control/dpdk
-        0_mempool_gref="3042,3043,3044,3045"
-        0_mempool_va="0x7fcbc6881000"
-        0_tx_vring_gref="3049"
-        0_rx_vring_gref="3053"
-        0_ether_addr="4e:0b:d0:4e:aa:f1"
-        0_vring_flag="3054"
-        ...
-
-Multiple mempools and multiple Virtios may exist in the guest domain, the first number is the index, starting from zero.
-
-The idx#_mempool_va stores the guest virtual address for mempool idx#.
-
-The idx#_ether_adder stores the MAC address of the guest Virtio device.
-
-For idx#_rx_ring_gref, idx#_tx_ring_gref, and idx#_mempool_gref, the value is a list of Grant references.
-Take idx#_mempool_gref node for example, the host maps those Grant references to a continuous virtual address space.
-The real Grant reference information is stored in this virtual address space,
-where (gref, pfn) pairs follow each other with -1 as the terminator.
-
-
-.. _figure_grant_refs:
-
-.. figure:: img/grant_refs.*
-
-   Mapping Grant references to a continuous virtual address space
-
-
-After all gref# IDs are retrieved, the host maps them to a continuous virtual address space.
-With the guest mempool virtual address, the host establishes 1:1 address mapping.
-With multiple guest mempools, the host establishes multiple address translation regions.
-
-Switching Back End
-~~~~~~~~~~~~~~~~~~
-
-The switching back end monitors changes in XenStore.
-When the back end detects that a new Virtio device has been created in a guest domain, it will:
-
-#.  Retrieve Grant and configuration information from XenStore.
-
-#.  Map and create a Virtio ring.
-
-#.  Map mempools in the host and establish address translation between the guest address and host address.
-
-#.  Select a free VMDQ pool, set its affinity with the Virtio device, and set the MAC/ VLAN filter.
-
-Packet Reception
-~~~~~~~~~~~~~~~~
-
-When packets arrive from an external network, the MAC?VLAN filter classifies packets into queues in one VMDQ pool.
-As each pool is bonded to a Virtio device in some guest domain, the switching back end will:
-
-#.  Fetch an available entry from the Virtio RX ring.
-
-#.  Get gva, and translate it to hva.
-
-#.  Copy the contents of the packet to the memory buffer pointed to by gva.
-
-The DPDK application in the guest domain, based on the PMD front end,
-is polling the shared Virtio RX ring for available packets and receives them on arrival.
-
-Packet Transmission
-~~~~~~~~~~~~~~~~~~~
-
-When a Virtio device in one guest domain is to transmit a packet,
-it puts the virtual address of the packet's data area into the shared Virtio TX ring.
-
-The packet switching back end is continuously polling the Virtio TX ring.
-When new packets are available for transmission from a guest, it will:
-
-#.  Fetch an available entry from the Virtio TX ring.
-
-#.  Get gva, and translate it to hva.
-
-#.  Copy the packet from hva to the host mbuf's data area.
-
-#.  Compare the destination MAC address with all the MAC addresses of the Virtio devices it manages.
-    If a match exists, it directly copies the packet to the matched VIrtio RX ring.
-    Otherwise, it sends the packet out through hardware.
-
-.. note::
-
-    The packet switching back end is for demonstration purposes only.
-    The user could implement their switching logic based on this example.
-    In this example, only one physical port on the host is supported.
-    Multiple segments are not supported. The biggest mbuf supported is 4KB.
-    When the back end is restarted, all front ends must also be restarted.
-
-Running the Application
------------------------
-
-The following describes the steps required to run the application.
-
-Validated Environment
-~~~~~~~~~~~~~~~~~~~~~
-
-Host:
-
-    Xen-hypervisor: 4.2.2
-
-    Distribution: Fedora release 18
-
-    Kernel: 3.10.0
-
-    Xen development package (including Xen, Xen-libs, xen-devel): 4.2.3
-
-Guest:
-
-    Distribution: Fedora 16 and 18
-
-    Kernel: 3.6.11
-
-Xen Host Prerequisites
-~~~~~~~~~~~~~~~~~~~~~~
-
-Note that the following commands might not be the same on different Linux* distributions.
-
-*   Install xen-devel package:
-
-    .. code-block:: console
-
-        yum install xen-devel.x86_64
-
-*   Start xend if not already started:
-
-    .. code-block:: console
-
-        /etc/init.d/xend start
-
-*   Mount xenfs if not already mounted:
-
-    .. code-block:: console
-
-        mount -t xenfs none /proc/xen
-
-*   Enlarge the limit for xen_gntdev driver:
-
-    .. code-block:: console
-
-        modprobe -r xen_gntdev
-        modprobe xen_gntdev limit=1000000
-
-.. note::
-
-    The default limit for earlier versions of the xen_gntdev driver is 1024.
-    That is insufficient to support the mapping of multiple Virtio devices into multiple VMs,
-    so it is necessary to enlarge the limit by reloading this module.
-    The default limit of recent versions of xen_gntdev is 1048576.
-    The rough calculation of this limit is:
-
-        limit=nb_mbuf# * VM#.
-
-        In DPDK examples, nb_mbuf# is normally 8192.
-
-Building and Running the Switching Backend
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-#.  Edit config/common_linuxapp, and change the default configuration value for the following two items:
-
-    .. code-block:: console
-
-        CONFIG_RTE_LIBRTE_XEN_DOM0=y
-        CONFIG RTE_LIBRTE_PMD_XENVIRT=n
-
-#.  Build the target:
-
-    .. code-block:: console
-
-        make install T=x86_64-native-linuxapp-gcc
-
-#.  Ensure that RTE_SDK and RTE_TARGET are correctly set. Build the switching example:
-
-    .. code-block:: console
-
-        make -C examples/vhost_xen/
-
-#.  Load the Xen DPDK memory management module and preallocate memory:
-
-    .. code-block:: console
-
-        insmod ./x86_64-native-linuxapp-gcc/build/lib/librte_eal/linuxapp/xen_dom0/rte_dom0_mm.ko
-        echo 2048> /sys/kernel/mm/dom0-mm/memsize-mB/memsize
-
-    .. note::
-
-        On Xen Dom0, there is no hugepage support.
-        Under Xen Dom0, the DPDK uses a special memory management kernel module
-        to allocate chunks of physically continuous memory.
-        Refer to the *DPDK Getting Started Guide* for more information on memory management in the DPDK.
-        In the above command, 4 GB memory is reserved (2048 of 2 MB pages) for DPDK.
-
-#.  Load uio_pci_generic and bind one Intel NIC controller to it:
-
-    .. code-block:: console
-
-        modprobe uio_pci_generic
-        python usertools/dpdk-devbind.py -b uio_pci_generic 0000:09:00:00.0
-
-    In this case, 0000:09:00.0 is the PCI address for the NIC controller.
-
-#.  Run the switching back end example:
-
-    .. code-block:: console
-
-        examples/vhost_xen/build/vhost-switch -l 0-3 -n 3 --xen-dom0 -- -p1
-
-.. note::
-
-    The -xen-dom0 option instructs the DPDK to use the Xen kernel module to allocate memory.
-
-Other Parameters:
-
-*   -vm2vm
-
-    The vm2vm parameter enables/disables packet switching in software.
-    Disabling vm2vm implies that on a VM packet transmission will always go to the Ethernet port
-    and will not be switched to another VM
-
-*   -Stats
-
-    The Stats parameter controls the printing of Virtio-net device statistics.
-    The parameter specifies the interval (in seconds) at which to print statistics,
-    an interval of 0 seconds will disable printing statistics.
-
-Xen PMD Frontend Prerequisites
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-#.  Install xen-devel package for accessing XenStore:
-
-    .. code-block:: console
-
-        yum install xen-devel.x86_64
-
-#.  Mount xenfs, if it is not already mounted:
-
-    .. code-block:: console
-
-        mount -t xenfs none /proc/xen
-
-#.  Enlarge the default limit for xen_gntalloc driver:
-
-    .. code-block:: console
-
-        modprobe -r xen_gntalloc
-        modprobe xen_gntalloc limit=6000
-
-.. note::
-
-    Before the Linux kernel version 3.8-rc5, Jan 15th 2013,
-    a critical defect occurs when a guest is heavily allocating Grant pages.
-    The Grant driver allocates fewer pages than expected which causes kernel memory corruption.
-    This happens, for example, when a guest uses the v1 format of a Grant table entry and allocates
-    more than 8192 Grant pages (this number might be different on different hypervisor versions).
-    To work around this issue, set the limit for gntalloc driver to 6000.
-    (The kernel normally allocates hundreds of Grant pages with one Xen front end per virtualized device).
-    If the kernel allocates a lot of Grant pages, for example, if the user uses multiple net front devices,
-    it is best to upgrade the Grant alloc driver.
-    This defect has been fixed in kernel version 3.8-rc5 and later.
-
-Building and Running the Front End
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-#.  Edit config/common_linuxapp, and change the default configuration value:
-
-    .. code-block:: console
-
-        CONFIG_RTE_LIBRTE_XEN_DOM0=n
-        CONFIG_RTE_LIBRTE_PMD_XENVIRT=y
-
-#.  Build the package:
-
-    .. code-block:: console
-
-        make install T=x86_64-native-linuxapp-gcc
-
-#.  Enable hugepages. Refer to the  *DPDK Getting Started Guide* for instructions on
-    how to use hugepages in the DPDK.
-
-#.  Run TestPMD. Refer to *DPDK TestPMD Application User Guide* for detailed parameter usage.
-
-    .. code-block:: console
-
-        ./x86_64-native-linuxapp-gcc/app/testpmd -l 0-3 -n 4 --vdev="net_xenvirt0,mac=00:00:00:00:00:11"
-        testpmd>set fwd mac
-        testpmd>start
-
-    As an example to run two TestPMD instances over 2 Xen Virtio devices:
-
-    .. code-block:: console
-
-        --vdev="net_xenvirt0,mac=00:00:00:00:00:11" --vdev="net_xenvirt1;mac=00:00:00:00:00:22"
-
-
-Usage Examples: Injecting a Packet Stream Using a Packet Generator
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Loopback Mode
-^^^^^^^^^^^^^
-
-Run TestPMD in a guest VM:
-
-.. code-block:: console
-
-    ./x86_64-native-linuxapp-gcc/app/testpmd -l 0-3 -n 4 --vdev="net_xenvirt0,mac=00:00:00:00:00:11" -- -i --eth-peer=0,00:00:00:00:00:22
-    testpmd> set fwd mac
-    testpmd> start
-
-Example output of the vhost_switch would be:
-
-.. code-block:: console
-
-    DATA:(0) MAC_ADDRESS 00:00:00:00:00:11 and VLAN_TAG 1000 registered.
-
-The above message indicates that device 0 has been registered with MAC address 00:00:00:00:00:11 and VLAN tag 1000.
-Any packets received on the NIC with these values is placed on the device's receive queue.
-
-Configure a packet stream in the packet generator, set the destination MAC address to 00:00:00:00:00:11, and VLAN to 1000,
-the guest Virtio receives these packets and sends them out with destination MAC address 00:00:00:00:00:22.
-
-Inter-VM Mode
-^^^^^^^^^^^^^
-
-Run TestPMD in guest VM1:
-
-.. code-block:: console
-
-    ./x86_64-native-linuxapp-gcc/app/testpmd -l 0-3 -n 4 --vdev="net_xenvirt0,mac=00:00:00:00:00:11" -- -i --eth-peer=0,00:00:00:00:00:22 -- -i
-
-Run TestPMD in guest VM2:
-
-.. code-block:: console
-
-    ./x86_64-native-linuxapp-gcc/app/testpmd -l 0-3 -n 4 --vdev="net_xenvirt0,mac=00:00:00:00:00:22" -- -i --eth-peer=0,00:00:00:00:00:33
-
-Configure a packet stream in the packet generator, and set the destination MAC address to 00:00:00:00:00:11 and VLAN to 1000.
-The packets received in Virtio in guest VM1 will be forwarded to Virtio in guest VM2 and
-then sent out through hardware with destination MAC address 00:00:00:00:00:33.
-
-The packet flow is:
-
-packet generator->Virtio in guest VM1->switching backend->Virtio in guest VM2->switching backend->wire
diff --git a/lib/librte_eal/bsdapp/eal/include/exec-env/rte_dom0_common.h b/lib/librte_eal/bsdapp/eal/include/exec-env/rte_dom0_common.h
deleted file mode 100644
index 99a3343..0000000
--- a/lib/librte_eal/bsdapp/eal/include/exec-env/rte_dom0_common.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*-
- *   This file is provided under a dual BSD/LGPLv2 license.  When using or
- *   redistributing this file, you may do so under either license.
- *
- *   GNU LESSER GENERAL PUBLIC LICENSE
- *
- *   Copyright(c) 2007-2014 Intel Corporation. All rights reserved.
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of version 2.1 of the GNU Lesser General Public License
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   Lesser General Public License for more details.
- *
- *   You should have received a copy of the GNU Lesser General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *   Contact Information:
- *   Intel Corporation
- *
- *
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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.
- *
- */
-
-#ifndef _RTE_DOM0_COMMON_H_
-#define _RTE_DOM0_COMMON_H_
-
-#ifdef __KERNEL__
-#include <linux/if.h>
-#endif
-
-#define DOM0_NAME_MAX   256
-#define DOM0_MM_DEV   "/dev/dom0_mm"
-
-#define DOM0_CONTIG_NUM_ORDER       9       /**< 2M order */
-#define DOM0_NUM_MEMSEG             512     /**< Maximum nb. of memory segment. */
-#define DOM0_MEMBLOCK_SIZE          0x200000 /**< Maximum nb. of memory block(2M). */
-#define DOM0_CONFIG_MEMSIZE         4096     /**< Maximum config memory size(4G). */
-#define DOM0_NUM_MEMBLOCK (DOM0_CONFIG_MEMSIZE / 2) /**< Maximum nb. of 2M memory block. */
-
-#define RTE_DOM0_IOCTL_PREPARE_MEMSEG    _IOWR(0, 1 , struct memory_info)
-#define RTE_DOM0_IOCTL_ATTACH_TO_MEMSEG  _IOWR(0, 2 , char *)
-#define RTE_DOM0_IOCTL_GET_NUM_MEMSEG    _IOWR(0, 3, int)
-#define RTE_DOM0_IOCTL_GET_MEMSEG_INFO   _IOWR(0, 4, void *)
-
-/**
- * A structure used to store memory information.
- */
-struct memory_info {
-	char name[DOM0_NAME_MAX];
-	uint64_t size;
-};
-
-/**
- * A structure used to store memory segment information.
- */
-struct memseg_info {
-	uint32_t idx;
-	uint64_t pfn;
-	uint64_t size;
-	uint64_t mfn[DOM0_NUM_MEMBLOCK];
-};
-
-/**
- * A structure used to store memory block information.
- */
-struct memblock_info {
-	uint8_t  exchange_flag;
-	uint64_t vir_addr;
-	uint64_t pfn;
-	uint64_t mfn;
-};
-#endif /* _RTE_DOM0_COMMON_H_ */
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 1da185e..354cded 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -97,7 +97,6 @@ eal_long_options[] = {
 	{OPT_VDEV,              1, NULL, OPT_VDEV_NUM             },
 	{OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },
 	{OPT_VMWARE_TSC_MAP,    0, NULL, OPT_VMWARE_TSC_MAP_NUM   },
-	{OPT_XEN_DOM0,          0, NULL, OPT_XEN_DOM0_NUM         },
 	{0,                     0, NULL, 0                        }
 };
 
@@ -208,8 +207,6 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
 
 	internal_cfg->syslog_facility = LOG_DAEMON;
 
-	internal_cfg->xen_dom0_support = 0;
-
 	/* if set to NONE, interrupt mode is determined automatically */
 	internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
 
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 7b7e8c8..f7c885f 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -65,7 +65,6 @@ struct internal_config {
 	volatile unsigned force_nrank;    /**< force number of ranks */
 	volatile unsigned no_hugetlbfs;   /**< true to disable hugetlbfs */
 	unsigned hugepage_unlink;         /**< true to unlink backing files */
-	volatile unsigned xen_dom0_support; /**< support app running on Xen Dom0*/
 	volatile unsigned no_pci;         /**< true to disable PCI */
 	volatile unsigned no_hpet;        /**< true to disable HPET */
 	volatile unsigned vmware_tsc_map; /**< true to use VMware TSC mapping
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 439a261..8770b85 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -81,8 +81,6 @@ enum {
 	OPT_VFIO_INTR_NUM,
 #define OPT_VMWARE_TSC_MAP    "vmware-tsc-map"
 	OPT_VMWARE_TSC_MAP_NUM,
-#define OPT_XEN_DOM0          "xen-dom0"
-	OPT_XEN_DOM0_NUM,
 	OPT_LONG_MAX_NUM
 };
 
diff --git a/lib/librte_eal/common/include/rte_memory.h b/lib/librte_eal/common/include/rte_memory.h
index 4aa5d1f..d8543c0 100644
--- a/lib/librte_eal/common/include/rte_memory.h
+++ b/lib/librte_eal/common/include/rte_memory.h
@@ -46,10 +46,6 @@
 
 #include <rte_config.h>
 
-#ifdef RTE_EXEC_ENV_LINUXAPP
-#include <exec-env/rte_dom0_common.h>
-#endif
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -116,10 +112,6 @@ struct rte_memseg {
 	int32_t socket_id;          /**< NUMA socket ID. */
 	uint32_t nchannel;          /**< Number of channels. */
 	uint32_t nrank;             /**< Number of ranks. */
-#ifdef RTE_LIBRTE_XEN_DOM0
-	 /**< store segment MFNs */
-	uint64_t mfn[DOM0_NUM_MEMBLOCK];
-#endif
 } __rte_packed;
 
 /**
@@ -195,69 +187,11 @@ unsigned rte_memory_get_nchannel(void);
  */
 unsigned rte_memory_get_nrank(void);
 
-#ifdef RTE_LIBRTE_XEN_DOM0
-
-/**< Internal use only - should DOM0 memory mapping be used */
-int rte_xen_dom0_supported(void);
-
-/**< Internal use only - phys to virt mapping for xen */
-phys_addr_t rte_xen_mem_phy2mch(int32_t, const phys_addr_t);
-
-/**
- * Return the physical address of elt, which is an element of the pool mp.
- *
- * @param memseg_id
- *   Identifier of the memory segment owning the physical address. If
- *   set to -1, find it automatically.
- * @param phy_addr
- *   physical address of elt.
- *
- * @return
- *   The physical address or RTE_BAD_PHYS_ADDR on error.
- */
-static inline phys_addr_t
-rte_mem_phy2mch(int32_t memseg_id, const phys_addr_t phy_addr)
-{
-	if (rte_xen_dom0_supported())
-		return rte_xen_mem_phy2mch(memseg_id, phy_addr);
-	else
-		return phy_addr;
-}
-
-/**
- * Memory init for supporting application running on Xen domain0.
- *
- * @param void
- *
- * @return
- *       0: successfully
- *	 negative: error
- */
-int rte_xen_dom0_memory_init(void);
-
-/**
- * Attach to memory setments of primary process on Xen domain0.
- *
- * @param void
- *
- * @return
- *       0: successfully
- *       negative: error
- */
-int rte_xen_dom0_memory_attach(void);
-#else
-static inline int rte_xen_dom0_supported(void)
-{
-	return 0;
-}
-
 static inline phys_addr_t
 rte_mem_phy2mch(int32_t memseg_id __rte_unused, const phys_addr_t phy_addr)
 {
 	return phy_addr;
 }
-#endif
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_eal/linuxapp/Makefile b/lib/librte_eal/linuxapp/Makefile
index 4794696..2ebdf31 100644
--- a/lib/librte_eal/linuxapp/Makefile
+++ b/lib/librte_eal/linuxapp/Makefile
@@ -35,7 +35,5 @@ DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal
 DIRS-$(CONFIG_RTE_EAL_IGB_UIO) += igb_uio
 DIRS-$(CONFIG_RTE_KNI_KMOD) += kni
 DEPDIRS-kni := eal
-DIRS-$(CONFIG_RTE_LIBRTE_XEN_DOM0) += xen_dom0
-DEPDIRS-xen_dom0 := eal
 
 include $(RTE_SDK)/mk/rte.subdir.mk
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 90bca4d..d9f9985 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -58,9 +58,6 @@ endif
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) := eal.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_hugepage_info.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_memory.c
-ifeq ($(CONFIG_RTE_LIBRTE_XEN_DOM0),y)
-SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_xen_memory.c
-endif
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_thread.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_log.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_vfio.c
@@ -130,7 +127,7 @@ ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
 CFLAGS_eal_thread.o += -Wno-return-type
 endif
 
-INC := rte_interrupts.h rte_kni_common.h rte_dom0_common.h
+INC := rte_interrupts.h rte_kni_common.h
 
 SYMLINK-$(CONFIG_RTE_EXEC_ENV_LINUXAPP)-include/exec-env := \
 	$(addprefix include/exec-env/,$(INC))
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 48f12f4..d995d03 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -354,7 +354,6 @@ eal_usage(const char *prgname)
 	       "  --"OPT_BASE_VIRTADDR"     Base virtual address\n"
 	       "  --"OPT_CREATE_UIO_DEV"    Create /dev/uioX (usually done by hotplug)\n"
 	       "  --"OPT_VFIO_INTR"         Interrupt mode for VFIO (legacy|msi|msix)\n"
-	       "  --"OPT_XEN_DOM0"          Support running on Xen dom0 without hugetlbfs\n"
 	       "\n");
 	/* Allow the application to print its usage message too if hook is set */
 	if ( rte_application_usage_hook ) {
@@ -555,19 +554,6 @@ eal_parse_args(int argc, char **argv)
 			eal_usage(prgname);
 			exit(EXIT_SUCCESS);
 
-		/* long options */
-		case OPT_XEN_DOM0_NUM:
-#ifdef RTE_LIBRTE_XEN_DOM0
-			internal_config.xen_dom0_support = 1;
-#else
-			RTE_LOG(ERR, EAL, "Can't support DPDK app "
-				"running on Dom0, please configure"
-				" RTE_LIBRTE_XEN_DOM0=y\n");
-			ret = -1;
-			goto out;
-#endif
-			break;
-
 		case OPT_HUGE_DIR_NUM:
 			internal_config.hugepage_dir = optarg;
 			break;
@@ -641,15 +627,6 @@ eal_parse_args(int argc, char **argv)
 		goto out;
 	}
 
-	/* --xen-dom0 doesn't make sense with --socket-mem */
-	if (internal_config.xen_dom0_support && internal_config.force_sockets == 1) {
-		RTE_LOG(ERR, EAL, "Options --"OPT_SOCKET_MEM" cannot be specified "
-			"together with --"OPT_XEN_DOM0"\n");
-		eal_usage(prgname);
-		ret = -1;
-		goto out;
-	}
-
 	if (optind >= 0)
 		argv[optind-1] = prgname;
 	ret = optind-1;
@@ -794,7 +771,6 @@ rte_eal_init(int argc, char **argv)
 
 	if (internal_config.no_hugetlbfs == 0 &&
 			internal_config.process_type != RTE_PROC_SECONDARY &&
-			internal_config.xen_dom0_support == 0 &&
 			eal_hugepage_info_init() < 0) {
 		rte_eal_init_alert("Cannot get hugepage information.");
 		rte_errno = EACCES;
diff --git a/lib/librte_eal/linuxapp/eal/eal_memory.c b/lib/librte_eal/linuxapp/eal/eal_memory.c
index 5279128..087fad4 100644
--- a/lib/librte_eal/linuxapp/eal/eal_memory.c
+++ b/lib/librte_eal/linuxapp/eal/eal_memory.c
@@ -75,13 +75,6 @@
 
 #define PFN_MASK_SIZE	8
 
-#ifdef RTE_LIBRTE_XEN_DOM0
-int rte_xen_dom0_supported(void)
-{
-	return internal_config.xen_dom0_support;
-}
-#endif
-
 /**
  * @file
  * Huge page mapping under linux
@@ -106,10 +99,6 @@ test_phys_addrs_available(void)
 	uint64_t tmp;
 	phys_addr_t physaddr;
 
-	/* For dom0, phys addresses can always be available */
-	if (rte_xen_dom0_supported())
-		return;
-
 	if (!rte_eal_has_hugepages()) {
 		RTE_LOG(ERR, EAL,
 			"Started without hugepages support, physical addresses not available\n");
@@ -139,29 +128,6 @@ rte_mem_virt2phy(const void *virtaddr)
 	int page_size;
 	off_t offset;
 
-	/* when using dom0, /proc/self/pagemap always returns 0, check in
-	 * dpdk memory by browsing the memsegs */
-	if (rte_xen_dom0_supported()) {
-		struct rte_mem_config *mcfg;
-		struct rte_memseg *memseg;
-		unsigned i;
-
-		mcfg = rte_eal_get_configuration()->mem_config;
-		for (i = 0; i < RTE_MAX_MEMSEG; i++) {
-			memseg = &mcfg->memseg[i];
-			if (memseg->addr == NULL)
-				break;
-			if (virtaddr > memseg->addr &&
-					virtaddr < RTE_PTR_ADD(memseg->addr,
-						memseg->len)) {
-				return memseg->phys_addr +
-					RTE_PTR_DIFF(virtaddr, memseg->addr);
-			}
-		}
-
-		return RTE_BAD_PHYS_ADDR;
-	}
-
 	/* Cannot parse /proc/self/pagemap, no need to log errors everywhere */
 	if (!phys_addrs_available)
 		return RTE_BAD_PHYS_ADDR;
@@ -1067,17 +1033,6 @@ rte_eal_hugepage_init(void)
 		return 0;
 	}
 
-/* check if app runs on Xen Dom0 */
-	if (internal_config.xen_dom0_support) {
-#ifdef RTE_LIBRTE_XEN_DOM0
-		/* use dom0_mm kernel driver to init memory */
-		if (rte_xen_dom0_memory_init() < 0)
-			return -1;
-		else
-			return 0;
-#endif
-	}
-
 	/* calculate total number of hugepages available. at this point we haven't
 	 * yet started sorting them so they all are on socket 0 */
 	for (i = 0; i < (int) internal_config.num_hugepage_sizes; i++) {
@@ -1400,17 +1355,6 @@ rte_eal_hugepage_attach(void)
 
 	test_phys_addrs_available();
 
-	if (internal_config.xen_dom0_support) {
-#ifdef RTE_LIBRTE_XEN_DOM0
-		if (rte_xen_dom0_memory_attach() < 0) {
-			RTE_LOG(ERR, EAL, "Failed to attach memory segments of primary "
-					"process\n");
-			return -1;
-		}
-		return 0;
-#endif
-	}
-
 	fd_zero = open("/dev/zero", O_RDONLY);
 	if (fd_zero < 0) {
 		RTE_LOG(ERR, EAL, "Could not open /dev/zero\n");
diff --git a/lib/librte_eal/linuxapp/eal/eal_xen_memory.c b/lib/librte_eal/linuxapp/eal/eal_xen_memory.c
deleted file mode 100644
index 19db1cb..0000000
--- a/lib/librte_eal/linuxapp/eal/eal_xen_memory.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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 <errno.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/queue.h>
-#include <sys/file.h>
-#include <unistd.h>
-#include <limits.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-
-#include <rte_log.h>
-#include <rte_memory.h>
-#include <rte_memzone.h>
-#include <rte_launch.h>
-#include <rte_eal.h>
-#include <rte_eal_memconfig.h>
-#include <rte_per_lcore.h>
-#include <rte_lcore.h>
-#include <rte_common.h>
-#include <rte_string_fns.h>
-
-#include "eal_private.h"
-#include "eal_internal_cfg.h"
-#include "eal_filesystem.h"
-#include <exec-env/rte_dom0_common.h>
-
-#define PAGE_SIZE RTE_PGSIZE_4K
-#define DEFAUL_DOM0_NAME "dom0-mem"
-
-static int xen_fd = -1;
-static const char sys_dir_path[] = "/sys/kernel/mm/dom0-mm/memsize-mB";
-
-/*
- * Try to mmap *size bytes in /dev/zero. If it is successful, return the
- * pointer to the mmap'd area and keep *size unmodified. Else, retry
- * with a smaller zone: decrease *size by mem_size until it reaches
- * 0. In this case, return NULL. Note: this function returns an address
- * which is a multiple of mem_size size.
- */
-static void *
-xen_get_virtual_area(size_t *size, size_t mem_size)
-{
-	void *addr;
-	int fd;
-	long aligned_addr;
-
-	RTE_LOG(DEBUG, EAL, "Ask a virtual area of 0x%zu bytes\n", *size);
-
-	fd = open("/dev/zero", O_RDONLY);
-	if (fd < 0){
-		RTE_LOG(ERR, EAL, "Cannot open /dev/zero\n");
-		return NULL;
-	}
-	do {
-		addr = mmap(NULL, (*size) + mem_size, PROT_READ,
-			MAP_PRIVATE, fd, 0);
-		if (addr == MAP_FAILED)
-			*size -= mem_size;
-	} while (addr == MAP_FAILED && *size > 0);
-
-	if (addr == MAP_FAILED) {
-		close(fd);
-		RTE_LOG(ERR, EAL, "Cannot get a virtual area\n");
-		return NULL;
-	}
-
-	munmap(addr, (*size) + mem_size);
-	close(fd);
-
-	/* align addr to a mem_size boundary */
-	aligned_addr = (uintptr_t)addr;
-	aligned_addr = RTE_ALIGN_CEIL(aligned_addr, mem_size);
-        addr = (void *)(aligned_addr);
-
-	RTE_LOG(DEBUG, EAL, "Virtual area found at %p (size = 0x%zx)\n",
-		addr, *size);
-
-	return addr;
-}
-
-/**
- * Get memory size configuration from /sys/devices/virtual/misc/dom0_mm
- * /memsize-mB/memsize file, and the size unit is mB.
- */
-static int
-get_xen_memory_size(void)
-{
-	char path[PATH_MAX];
-	unsigned long mem_size = 0;
-	static const char *file_name;
-
-	file_name = "memsize";
-	snprintf(path, sizeof(path), "%s/%s",
-			sys_dir_path, file_name);
-
-	if (eal_parse_sysfs_value(path, &mem_size) < 0)
-		return -1;
-
-	if (mem_size == 0)
-		rte_exit(EXIT_FAILURE,"XEN-DOM0:the %s/%s was not"
-			" configured.\n",sys_dir_path, file_name);
-	if (mem_size % 2)
-		rte_exit(EXIT_FAILURE,"XEN-DOM0:the %s/%s must be"
-			" even number.\n",sys_dir_path, file_name);
-
-	if (mem_size > DOM0_CONFIG_MEMSIZE)
-		rte_exit(EXIT_FAILURE,"XEN-DOM0:the %s/%s should not be larger"
-			" than %d mB\n",sys_dir_path, file_name, DOM0_CONFIG_MEMSIZE);
-
-	return mem_size;
-}
-
-/**
- * Based on physical address to caculate MFN in Xen Dom0.
- */
-phys_addr_t
-rte_xen_mem_phy2mch(int32_t memseg_id, const phys_addr_t phy_addr)
-{
-	int mfn_id, i;
-	uint64_t mfn, mfn_offset;
-	struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
-	struct rte_memseg *memseg = mcfg->memseg;
-
-	/* find the memory segment owning the physical address */
-	if (memseg_id == -1) {
-		for (i = 0; i < RTE_MAX_MEMSEG; i++) {
-			if ((phy_addr >= memseg[i].phys_addr) &&
-					(phy_addr < memseg[i].phys_addr +
-						memseg[i].len)) {
-				memseg_id = i;
-				break;
-			}
-		}
-		if (memseg_id == -1)
-			return RTE_BAD_PHYS_ADDR;
-	}
-
-	mfn_id = (phy_addr - memseg[memseg_id].phys_addr) / RTE_PGSIZE_2M;
-
-	/*the MFN is contiguous in 2M */
-	mfn_offset = (phy_addr - memseg[memseg_id].phys_addr) %
-					RTE_PGSIZE_2M / PAGE_SIZE;
-	mfn = mfn_offset + memseg[memseg_id].mfn[mfn_id];
-
-	/** return mechine address */
-	return mfn * PAGE_SIZE + phy_addr % PAGE_SIZE;
-}
-
-int
-rte_xen_dom0_memory_init(void)
-{
-	void *vir_addr, *vma_addr = NULL;
-	int err, ret = 0;
-	uint32_t i, requested, mem_size, memseg_idx, num_memseg = 0;
-	size_t vma_len = 0;
-	struct memory_info meminfo;
-	struct memseg_info seginfo[RTE_MAX_MEMSEG];
-	int flags, page_size = getpagesize();
-	struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
-	struct rte_memseg *memseg = mcfg->memseg;
-	uint64_t total_mem = internal_config.memory;
-
-	memset(seginfo, 0, sizeof(seginfo));
-	memset(&meminfo, 0, sizeof(struct memory_info));
-
-	mem_size = get_xen_memory_size();
-	requested = (unsigned) (total_mem / 0x100000);
-	if (requested > mem_size)
-		/* if we didn't satisfy total memory requirements */
-		rte_exit(EXIT_FAILURE,"Not enough memory available! Requested: %uMB,"
-				" available: %uMB\n", requested, mem_size);
-	else if (total_mem != 0)
-		mem_size = requested;
-
-	/* Check FD and open once */
-	if (xen_fd < 0) {
-		xen_fd = open(DOM0_MM_DEV, O_RDWR);
-		if (xen_fd < 0) {
-			RTE_LOG(ERR, EAL, "Can not open %s\n",DOM0_MM_DEV);
-			return -1;
-		}
-	}
-
-	meminfo.size = mem_size;
-
-	/* construct memory mangement name for Dom0 */
-	snprintf(meminfo.name, DOM0_NAME_MAX, "%s-%s",
-		internal_config.hugefile_prefix, DEFAUL_DOM0_NAME);
-
-	/* Notify kernel driver to allocate memory */
-	ret = ioctl(xen_fd, RTE_DOM0_IOCTL_PREPARE_MEMSEG, &meminfo);
-	if (ret < 0) {
-		RTE_LOG(ERR, EAL, "XEN DOM0:failed to get memory\n");
-		err = -EIO;
-		goto fail;
-	}
-
-	/* Get number of memory segment from driver */
-	ret = ioctl(xen_fd, RTE_DOM0_IOCTL_GET_NUM_MEMSEG, &num_memseg);
-	if (ret < 0) {
-		RTE_LOG(ERR, EAL, "XEN DOM0:failed to get memseg count.\n");
-		err = -EIO;
-		goto fail;
-	}
-
-	if(num_memseg > RTE_MAX_MEMSEG){
-		RTE_LOG(ERR, EAL, "XEN DOM0: the memseg count %d is greater"
-			" than max memseg %d.\n",num_memseg, RTE_MAX_MEMSEG);
-		err = -EIO;
-		goto fail;
-	}
-
-	/* get all memory segements information */
-	ret = ioctl(xen_fd, RTE_DOM0_IOCTL_GET_MEMSEG_INFO, seginfo);
-	if (ret < 0) {
-		RTE_LOG(ERR, EAL, "XEN DOM0:failed to get memseg info.\n");
-		err = -EIO;
-		goto fail;
-	}
-
-	/* map all memory segments to contiguous user space */
-	for (memseg_idx = 0; memseg_idx < num_memseg; memseg_idx++)
-	{
-		vma_len = seginfo[memseg_idx].size;
-
-		/**
-		 * get the biggest virtual memory area up to vma_len. If it fails,
-		 * vma_addr is NULL, so let the kernel provide the address.
-		 */
-		vma_addr = xen_get_virtual_area(&vma_len, RTE_PGSIZE_2M);
-		if (vma_addr == NULL) {
-			flags = MAP_SHARED;
-			vma_len = RTE_PGSIZE_2M;
-		} else
-			flags = MAP_SHARED | MAP_FIXED;
-
-		seginfo[memseg_idx].size = vma_len;
-		vir_addr = mmap(vma_addr, seginfo[memseg_idx].size,
-			PROT_READ|PROT_WRITE, flags, xen_fd,
-			memseg_idx * page_size);
-		if (vir_addr == MAP_FAILED) {
-			RTE_LOG(ERR, EAL, "XEN DOM0:Could not mmap %s\n",
-				DOM0_MM_DEV);
-			err = -EIO;
-			goto fail;
-		}
-
-		memseg[memseg_idx].addr = vir_addr;
-		memseg[memseg_idx].phys_addr = page_size *
-			seginfo[memseg_idx].pfn ;
-		memseg[memseg_idx].len = seginfo[memseg_idx].size;
-		for ( i = 0; i < seginfo[memseg_idx].size / RTE_PGSIZE_2M; i++)
-			memseg[memseg_idx].mfn[i] = seginfo[memseg_idx].mfn[i];
-
-		/* MFNs are continuous in 2M, so assume that page size is 2M */
-		memseg[memseg_idx].hugepage_sz = RTE_PGSIZE_2M;
-
-		memseg[memseg_idx].nchannel = mcfg->nchannel;
-		memseg[memseg_idx].nrank = mcfg->nrank;
-
-		/* NUMA is not suppoted in Xen Dom0, so only set socket 0*/
-		memseg[memseg_idx].socket_id = 0;
-	}
-
-	return 0;
-fail:
-	if (xen_fd > 0) {
-		close(xen_fd);
-		xen_fd = -1;
-	}
-	return err;
-}
-
-/*
- * This creates the memory mappings in the secondary process to match that of
- * the server process. It goes through each memory segment in the DPDK runtime
- * configuration, mapping them in order to form a contiguous block in the
- * virtual memory space
- */
-int
-rte_xen_dom0_memory_attach(void)
-{
-	const struct rte_mem_config *mcfg;
-	unsigned s = 0; /* s used to track the segment number */
-	int xen_fd = -1;
-	int ret = -1;
-	void *vir_addr;
-	char name[DOM0_NAME_MAX] = {0};
-	int page_size = getpagesize();
-
-	mcfg = rte_eal_get_configuration()->mem_config;
-
-	/* Check FD and open once */
-	if (xen_fd < 0) {
-		xen_fd = open(DOM0_MM_DEV, O_RDWR);
-		if (xen_fd < 0) {
-			RTE_LOG(ERR, EAL, "Can not open %s\n",DOM0_MM_DEV);
-			goto error;
-		}
-	}
-
-	/* construct memory mangement name for Dom0 */
-	snprintf(name, DOM0_NAME_MAX, "%s-%s",
-		internal_config.hugefile_prefix, DEFAUL_DOM0_NAME);
-	/* attach to memory segments of primary process */
-	ret = ioctl(xen_fd, RTE_DOM0_IOCTL_ATTACH_TO_MEMSEG, name);
-	if (ret) {
-		RTE_LOG(ERR, EAL,"attach memory segments fail.\n");
-		goto error;
-	}
-
-	/* map all segments into memory to make sure we get the addrs */
-	for (s = 0; s < RTE_MAX_MEMSEG; ++s) {
-
-		/*
-		 * the first memory segment with len==0 is the one that
-		 * follows the last valid segment.
-		 */
-		if (mcfg->memseg[s].len == 0)
-			break;
-
-		vir_addr = mmap(mcfg->memseg[s].addr, mcfg->memseg[s].len,
-				PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, xen_fd,
-				s * page_size);
-		if (vir_addr == MAP_FAILED) {
-			RTE_LOG(ERR, EAL, "Could not mmap %llu bytes "
-				"in %s to requested address [%p]\n",
-				(unsigned long long)mcfg->memseg[s].len, DOM0_MM_DEV,
-				mcfg->memseg[s].addr);
-			goto error;
-		}
-	}
-	return 0;
-
-error:
-	if (xen_fd >= 0) {
-		close(xen_fd);
-		xen_fd = -1;
-	}
-	return -1;
-}
diff --git a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_dom0_common.h b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_dom0_common.h
deleted file mode 100644
index d970778..0000000
--- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_dom0_common.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*-
- *   This file is provided under a dual BSD/LGPLv2 license.  When using or
- *   redistributing this file, you may do so under either license.
- *
- *   GNU LESSER GENERAL PUBLIC LICENSE
- *
- *   Copyright(c) 2007-2014 Intel Corporation. All rights reserved.
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of version 2.1 of the GNU Lesser General Public License
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   Lesser General Public License for more details.
- *
- *   You should have received a copy of the GNU Lesser General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *   Contact Information:
- *   Intel Corporation
- *
- *
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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.
- *
- */
-
-#ifndef _RTE_DOM0_COMMON_H_
-#define _RTE_DOM0_COMMON_H_
-
-#ifdef __KERNEL__
-#include <linux/if.h>
-#endif
-
-#define DOM0_NAME_MAX   256
-#define DOM0_MM_DEV   "/dev/dom0_mm"
-
-#define DOM0_CONTIG_NUM_ORDER       9       /**< order of 2M */
-#define DOM0_NUM_MEMSEG             512     /**< Maximum nb. of memory segment. */
-#define DOM0_MEMBLOCK_SIZE          0x200000 /**< size of memory block(2M). */
-#define DOM0_CONFIG_MEMSIZE         4096     /**< Maximum config memory size(4G). */
-#define DOM0_NUM_MEMBLOCK (DOM0_CONFIG_MEMSIZE / 2) /**< Maximum nb. of 2M memory block. */
-
-#define RTE_DOM0_IOCTL_PREPARE_MEMSEG    _IOWR(0, 1 , struct memory_info)
-#define RTE_DOM0_IOCTL_ATTACH_TO_MEMSEG  _IOWR(0, 2 , char *)
-#define RTE_DOM0_IOCTL_GET_NUM_MEMSEG    _IOWR(0, 3, int)
-#define RTE_DOM0_IOCTL_GET_MEMSEG_INFO   _IOWR(0, 4, void *)
-
-/**
- * A structure used to store memory information.
- */
-struct memory_info {
-	char name[DOM0_NAME_MAX];
-	uint64_t size;
-};
-
-/**
- * A structure used to store memory segment information.
- */
-struct memseg_info {
-	uint32_t idx;
-	uint64_t pfn;
-	uint64_t size;
-	uint64_t mfn[DOM0_NUM_MEMBLOCK];
-};
-
-/**
- * A structure used to store memory block information.
- */
-struct memblock_info {
-	uint8_t exchange_flag;
-	uint8_t used;
-	uint64_t vir_addr;
-	uint64_t pfn;
-	uint64_t mfn;
-};
-#endif /* _RTE_DOM0_COMMON_H_ */
diff --git a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c
index 07a19a3..3d5c2f3 100644
--- a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c
+++ b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c
@@ -33,9 +33,6 @@
 #include <linux/version.h>
 #include <linux/slab.h>
 
-#ifdef CONFIG_XEN_DOM0
-#include <xen/xen.h>
-#endif
 #include <rte_pci_dev_features.h>
 
 #include "compat.h"
@@ -201,52 +198,6 @@ igbuio_pci_release(struct uio_info *info, struct inode *inode)
 	return 0;
 }
 
-#ifdef CONFIG_XEN_DOM0
-static int
-igbuio_dom0_mmap_phys(struct uio_info *info, struct vm_area_struct *vma)
-{
-	int idx;
-
-	idx = (int)vma->vm_pgoff;
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-#ifdef HAVE_PTE_MASK_PAGE_IOMAP
-	vma->vm_page_prot.pgprot |= _PAGE_IOMAP;
-#endif
-
-	return remap_pfn_range(vma,
-			vma->vm_start,
-			info->mem[idx].addr >> PAGE_SHIFT,
-			vma->vm_end - vma->vm_start,
-			vma->vm_page_prot);
-}
-
-/**
- * This is uio device mmap method which will use igbuio mmap for Xen
- * Dom0 environment.
- */
-static int
-igbuio_dom0_pci_mmap(struct uio_info *info, struct vm_area_struct *vma)
-{
-	int idx;
-
-	if (vma->vm_pgoff >= MAX_UIO_MAPS)
-		return -EINVAL;
-
-	if (info->mem[vma->vm_pgoff].size == 0)
-		return -EINVAL;
-
-	idx = (int)vma->vm_pgoff;
-	switch (info->mem[idx].memtype) {
-	case UIO_MEM_PHYS:
-		return igbuio_dom0_mmap_phys(info, vma);
-	case UIO_MEM_LOGICAL:
-	case UIO_MEM_VIRTUAL:
-	default:
-		return -EINVAL;
-	}
-}
-#endif
-
 /* Remap pci resources described by bar #pci_bar in uio resource n. */
 static int
 igbuio_pci_setup_iomem(struct pci_dev *dev, struct uio_info *info,
@@ -405,11 +356,6 @@ igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	udev->info.irqcontrol = igbuio_pci_irqcontrol;
 	udev->info.open = igbuio_pci_open;
 	udev->info.release = igbuio_pci_release;
-#ifdef CONFIG_XEN_DOM0
-	/* check if the driver run on Xen Dom0 */
-	if (xen_initial_domain())
-		udev->info.mmap = igbuio_dom0_pci_mmap;
-#endif
 	udev->info.priv = udev;
 	udev->pdev = dev;
 
diff --git a/lib/librte_eal/linuxapp/xen_dom0/Makefile b/lib/librte_eal/linuxapp/xen_dom0/Makefile
deleted file mode 100644
index be51a82..0000000
--- a/lib/librte_eal/linuxapp/xen_dom0/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-#   BSD LICENSE
-#
-#   Copyright(c) 2010-2014 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_SDK)/mk/rte.vars.mk
-
-#
-# module name and path
-#
-MODULE = rte_dom0_mm
-
-#
-# CFLAGS
-#
-MODULE_CFLAGS += -I$(SRCDIR) --param max-inline-insns-single=50
-MODULE_CFLAGS += -I$(RTE_OUTPUT)/include
-MODULE_CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h
-MODULE_CFLAGS += -Wall -Werror
-
-#
-# all source are stored in SRCS-y
-#
-
-SRCS-y += dom0_mm_misc.c
-
-include $(RTE_SDK)/mk/rte.module.mk
diff --git a/lib/librte_eal/linuxapp/xen_dom0/compat.h b/lib/librte_eal/linuxapp/xen_dom0/compat.h
deleted file mode 100644
index e6eb97f..0000000
--- a/lib/librte_eal/linuxapp/xen_dom0/compat.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Minimal wrappers to allow compiling xen_dom0 on older kernels.
- */
-
-#ifndef RHEL_RELEASE_VERSION
-#define RHEL_RELEASE_VERSION(a, b) (((a) << 8) + (b))
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && \
-	(!(defined(RHEL_RELEASE_CODE) && \
-	 RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6, 4)))
-
-#define kstrtoul strict_strtoul
-
-#endif /* < 2.6.39 */
diff --git a/lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h b/lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h
deleted file mode 100644
index 9d5ffb2..0000000
--- a/lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*-
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- *   redistributing this file, you may do so under either license.
- *
- *   GPL LICENSE SUMMARY
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of version 2 of the GNU General Public License as
- *   published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *   The full GNU General Public License is included in this distribution
- *   in the file called LICENSE.GPL.
- *
- *   Contact Information:
- *   Intel Corporation
- *
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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.
- *
- */
-#ifndef _DOM0_MM_DEV_H_
-#define _DOM0_MM_DEV_H_
-
-#include <linux/wait.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <exec-env/rte_dom0_common.h>
-
-#define NUM_MEM_CTX     256  /**< Maximum number of memory context*/
-#define MAX_EXCHANGE_FAIL_TIME 5  /**< Maximum times of allowing exchange fail .*/
-#define MAX_MEMBLOCK_SIZE (2 * DOM0_MEMBLOCK_SIZE)
-#define MAX_NUM_ORDER     (DOM0_CONTIG_NUM_ORDER + 1)
-#define SIZE_PER_BLOCK    2       /**< Size of memory block (2MB).*/
-
-/**
- * A structure describing the private information for a dom0 device.
- */
-struct dom0_mm_dev {
-	struct miscdevice miscdev;
-	uint8_t fail_times;
-	uint32_t used_memsize;
-	uint32_t num_mem_ctx;
-	uint32_t config_memsize;
-	uint32_t num_bigblock;
-	struct  dom0_mm_data *mm_data[NUM_MEM_CTX];
-	struct mutex data_lock;
-};
-
-struct dom0_mm_data{
-	uint32_t refcnt;
-	uint32_t num_memseg; /**< Number of memory segment. */
-	uint32_t mem_size;   /**< Size of requesting memory. */
-
-	char name[DOM0_NAME_MAX];
-
-	/** Store global memory block IDs used by an instance */
-	uint32_t block_num[DOM0_NUM_MEMBLOCK];
-
-	/** Store memory block information.*/
-	struct memblock_info block_info[DOM0_NUM_MEMBLOCK];
-
-	/** Store memory segment information.*/
-	struct memseg_info  seg_info[DOM0_NUM_MEMSEG];
-};
-
-#define XEN_ERR(args...) printk(KERN_DEBUG "XEN_DOM0: Error: " args)
-#define XEN_PRINT(args...) printk(KERN_DEBUG "XEN_DOM0: " args)
-#endif
diff --git a/lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c b/lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c
deleted file mode 100644
index 79630ba..0000000
--- a/lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c
+++ /dev/null
@@ -1,780 +0,0 @@
-/*-
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- *   redistributing this file, you may do so under either license.
- *
- *   GPL LICENSE SUMMARY
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of version 2 of the GNU General Public License as
- *   published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *   The full GNU General Public License is included in this distribution
- *   in the file called LICENSE.GPL.
- *
- *   Contact Information:
- *   Intel Corporation
- *
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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 <linux/module.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <linux/version.h>
-
-#include <xen/xen.h>
-#include <xen/page.h>
-#include <xen/xen-ops.h>
-#include <xen/interface/memory.h>
-
-#include <exec-env/rte_dom0_common.h>
-
-#include "compat.h"
-#include "dom0_mm_dev.h"
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Kernel Module for supporting DPDK running on Xen Dom0");
-
-static struct dom0_mm_dev dom0_dev;
-static struct kobject *dom0_kobj = NULL;
-
-static struct memblock_info *rsv_mm_info;
-
-/* Default configuration for reserved memory size(2048 MB). */
-static uint32_t rsv_memsize = 2048;
-
-static int dom0_open(struct inode *inode, struct file *file);
-static int dom0_release(struct inode *inode, struct file *file);
-static int dom0_ioctl(struct file *file, unsigned int ioctl_num,
-		unsigned long ioctl_param);
-static int dom0_mmap(struct file *file, struct vm_area_struct *vma);
-static int dom0_memory_free(uint32_t size);
-static int dom0_memory_release(struct dom0_mm_data *mm_data);
-
-static const struct file_operations data_fops = {
-	.owner = THIS_MODULE,
-	.open = dom0_open,
-	.release = dom0_release,
-	.mmap = dom0_mmap,
-	.unlocked_ioctl = (void *)dom0_ioctl,
-};
-
-static ssize_t
-show_memsize_rsvd(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, 10, "%u\n", dom0_dev.used_memsize);
-}
-
-static ssize_t
-show_memsize(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, 10, "%u\n", dom0_dev.config_memsize);
-}
-
-static ssize_t
-store_memsize(struct device *dev, struct device_attribute *attr,
-            const char *buf, size_t count)
-{
-	int err = 0;
-	unsigned long mem_size;
-
-	if (0 != kstrtoul(buf, 0, &mem_size))
-		return  -EINVAL;
-
-	mutex_lock(&dom0_dev.data_lock);
-	if (0 == mem_size) {
-		err = -EINVAL;
-		goto fail;
-	} else if (mem_size > (rsv_memsize - dom0_dev.used_memsize)) {
-		XEN_ERR("configure memory size fail\n");
-		err = -EINVAL;
-		goto fail;
-	} else
-		dom0_dev.config_memsize = mem_size;
-
-fail:
-	mutex_unlock(&dom0_dev.data_lock);
-	return err ? err : count;
-}
-
-static DEVICE_ATTR(memsize, S_IRUGO | S_IWUSR, show_memsize, store_memsize);
-static DEVICE_ATTR(memsize_rsvd, S_IRUGO, show_memsize_rsvd, NULL);
-
-static struct attribute *dev_attrs[] = {
-	&dev_attr_memsize.attr,
-	&dev_attr_memsize_rsvd.attr,
-	NULL,
-};
-
-/* the memory size unit is MB */
-static const struct attribute_group dev_attr_grp = {
-	.name = "memsize-mB",
-	.attrs = dev_attrs,
-};
-
-
-static void
-sort_viraddr(struct memblock_info *mb, int cnt)
-{
-	int i,j;
-	uint64_t tmp_pfn;
-	uint64_t tmp_viraddr;
-
-	/*sort virtual address and pfn */
-	for(i = 0; i < cnt; i ++) {
-		for(j = cnt - 1; j > i; j--) {
-			if(mb[j].pfn < mb[j - 1].pfn) {
-				tmp_pfn = mb[j - 1].pfn;
-				mb[j - 1].pfn = mb[j].pfn;
-				mb[j].pfn = tmp_pfn;
-
-				tmp_viraddr = mb[j - 1].vir_addr;
-				mb[j - 1].vir_addr = mb[j].vir_addr;
-				mb[j].vir_addr = tmp_viraddr;
-			}
-		}
-	}
-}
-
-static int
-dom0_find_memdata(const char * mem_name)
-{
-	unsigned i;
-	int idx = -1;
-	for(i = 0; i< NUM_MEM_CTX; i++) {
-		if(dom0_dev.mm_data[i] == NULL)
-			continue;
-		if (!strncmp(dom0_dev.mm_data[i]->name, mem_name,
-			sizeof(char) * DOM0_NAME_MAX)) {
-			idx = i;
-			break;
-		}
-	}
-
-	return idx;
-}
-
-static int
-dom0_find_mempos(void)
-{
-	unsigned i;
-	int idx = -1;
-
-	for(i = 0; i< NUM_MEM_CTX; i++) {
-		if(dom0_dev.mm_data[i] == NULL){
-			idx = i;
-			break;
-		}
-	}
-
-	return idx;
-}
-
-static int
-dom0_memory_release(struct dom0_mm_data *mm_data)
-{
-	int idx;
-	uint32_t  num_block, block_id;
-
-	/* each memory block is 2M */
-	num_block = mm_data->mem_size / SIZE_PER_BLOCK;
-	if (num_block == 0)
-		return -EINVAL;
-
-	/* reset global memory data */
-	idx = dom0_find_memdata(mm_data->name);
-	if (idx >= 0) {
-		dom0_dev.used_memsize -= mm_data->mem_size;
-		dom0_dev.mm_data[idx] = NULL;
-		dom0_dev.num_mem_ctx--;
-	}
-
-	/* reset these memory blocks status as free */
-	for (idx = 0; idx < num_block; idx++) {
-		block_id = mm_data->block_num[idx];
-		rsv_mm_info[block_id].used = 0;
-	}
-
-	memset(mm_data, 0, sizeof(struct dom0_mm_data));
-	vfree(mm_data);
-	return 0;
-}
-
-static int
-dom0_memory_free(uint32_t rsv_size)
-{
-	uint64_t vstart, vaddr;
-	uint32_t i, num_block, size;
-
-	if (!xen_pv_domain())
-		return -1;
-
-	/* each memory block is 2M */
-	num_block = rsv_size / SIZE_PER_BLOCK;
-	if (num_block == 0)
-		return -EINVAL;
-
-	/* free all memory blocks of size of 4M and destroy contiguous region */
-	for (i = 0; i < dom0_dev.num_bigblock * 2; i += 2) {
-		vstart = rsv_mm_info[i].vir_addr;
-		if (vstart) {
-		#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
-			if (rsv_mm_info[i].exchange_flag)
-				xen_destroy_contiguous_region(vstart,
-						DOM0_CONTIG_NUM_ORDER);
-			if (rsv_mm_info[i + 1].exchange_flag)
-				xen_destroy_contiguous_region(vstart +
-						DOM0_MEMBLOCK_SIZE,
-						DOM0_CONTIG_NUM_ORDER);
-		#else
-			if (rsv_mm_info[i].exchange_flag)
-				xen_destroy_contiguous_region(rsv_mm_info[i].pfn
-					* PAGE_SIZE,
-					DOM0_CONTIG_NUM_ORDER);
-			if (rsv_mm_info[i + 1].exchange_flag)
-				xen_destroy_contiguous_region(rsv_mm_info[i].pfn
-					* PAGE_SIZE + DOM0_MEMBLOCK_SIZE,
-					DOM0_CONTIG_NUM_ORDER);
-		#endif
-
-			size = DOM0_MEMBLOCK_SIZE * 2;
-			vaddr = vstart;
-			while (size > 0) {
-				ClearPageReserved(virt_to_page(vaddr));
-				vaddr += PAGE_SIZE;
-				size -= PAGE_SIZE;
-			}
-			free_pages(vstart, MAX_NUM_ORDER);
-		}
-	}
-
-	/* free all memory blocks size of 2M and destroy contiguous region */
-	for (; i < num_block; i++) {
-		vstart = rsv_mm_info[i].vir_addr;
-		if (vstart) {
-			if (rsv_mm_info[i].exchange_flag)
-				xen_destroy_contiguous_region(vstart,
-					DOM0_CONTIG_NUM_ORDER);
-
-			size = DOM0_MEMBLOCK_SIZE;
-			vaddr = vstart;
-			while (size > 0) {
-				ClearPageReserved(virt_to_page(vaddr));
-				vaddr += PAGE_SIZE;
-				size -= PAGE_SIZE;
-			}
-			free_pages(vstart, DOM0_CONTIG_NUM_ORDER);
-		}
-	}
-
-	memset(rsv_mm_info, 0, sizeof(struct memblock_info) * num_block);
-	vfree(rsv_mm_info);
-	rsv_mm_info = NULL;
-
-	return 0;
-}
-
-static void
-find_free_memory(uint32_t count, struct dom0_mm_data *mm_data)
-{
-	uint32_t i = 0;
-	uint32_t j = 0;
-
-	while ((i < count) && (j < rsv_memsize / SIZE_PER_BLOCK)) {
-		if (rsv_mm_info[j].used == 0) {
-			mm_data->block_info[i].pfn = rsv_mm_info[j].pfn;
-			mm_data->block_info[i].vir_addr =
-				rsv_mm_info[j].vir_addr;
-			mm_data->block_info[i].mfn = rsv_mm_info[j].mfn;
-			mm_data->block_info[i].exchange_flag =
-				rsv_mm_info[j].exchange_flag;
-			mm_data->block_num[i] = j;
-			rsv_mm_info[j].used = 1;
-			i++;
-		}
-		j++;
-	}
-}
-
-/**
- * Find all memory segments in which physical addresses are contiguous.
- */
-static void
-find_memseg(int count, struct dom0_mm_data * mm_data)
-{
-	int i = 0;
-	int j, k, idx = 0;
-	uint64_t zone_len, pfn, num_block;
-
-	while(i < count) {
-		if (mm_data->block_info[i].exchange_flag == 0) {
-			i++;
-			continue;
-		}
-		k = 0;
-		pfn = mm_data->block_info[i].pfn;
-		mm_data->seg_info[idx].pfn = pfn;
-		mm_data->seg_info[idx].mfn[k] = mm_data->block_info[i].mfn;
-
-		for (j = i + 1; j < count; j++) {
-
-			/* ignore exchange fail memory block */
-			if (mm_data->block_info[j].exchange_flag == 0)
-				break;
-
-			if (mm_data->block_info[j].pfn !=
-				(mm_data->block_info[j - 1].pfn +
-					 DOM0_MEMBLOCK_SIZE / PAGE_SIZE))
-			    break;
-			++k;
-			mm_data->seg_info[idx].mfn[k] = mm_data->block_info[j].mfn;
-		}
-
-		num_block = j - i;
-		zone_len = num_block * DOM0_MEMBLOCK_SIZE;
-		mm_data->seg_info[idx].size = zone_len;
-
-		XEN_PRINT("memseg id=%d, size=0x%llx\n", idx, zone_len);
-		i = i+ num_block;
-		idx++;
-		if (idx == DOM0_NUM_MEMSEG)
-			break;
-	}
-	mm_data->num_memseg = idx;
-}
-
-static int
-dom0_memory_reserve(uint32_t rsv_size)
-{
-	uint64_t pfn, vstart, vaddr;
-	uint32_t i, num_block, size, allocated_size = 0;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
-	dma_addr_t dma_handle;
-#endif
-
-	/* 2M as memory block */
-	num_block = rsv_size / SIZE_PER_BLOCK;
-
-	rsv_mm_info = vmalloc(sizeof(struct memblock_info) * num_block);
-	if (!rsv_mm_info) {
-		XEN_ERR("Unable to allocate device memory information\n");
-		return -ENOMEM;
-	}
-	memset(rsv_mm_info, 0, sizeof(struct memblock_info) * num_block);
-
-	/* try alloc size of 4M once */
-	for (i = 0; i < num_block; i += 2) {
-		vstart = (unsigned long)
-			__get_free_pages(GFP_ATOMIC, MAX_NUM_ORDER);
-		if (vstart == 0)
-			break;
-
-		dom0_dev.num_bigblock = i / 2 + 1;
-		allocated_size =  SIZE_PER_BLOCK * (i + 2);
-
-		/* size of 4M */
-		size = DOM0_MEMBLOCK_SIZE * 2;
-
-		vaddr = vstart;
-		while (size > 0) {
-			SetPageReserved(virt_to_page(vaddr));
-			vaddr += PAGE_SIZE;
-			size -= PAGE_SIZE;
-		}
-
-		pfn = virt_to_pfn(vstart);
-		rsv_mm_info[i].pfn = pfn;
-		rsv_mm_info[i].vir_addr = vstart;
-		rsv_mm_info[i + 1].pfn =
-				pfn + DOM0_MEMBLOCK_SIZE / PAGE_SIZE;
-		rsv_mm_info[i + 1].vir_addr =
-				vstart + DOM0_MEMBLOCK_SIZE;
-	}
-
-	/*if it failed to alloc 4M, and continue to alloc 2M once */
-	for (; i < num_block; i++) {
-		vstart = (unsigned long)
-			__get_free_pages(GFP_ATOMIC, DOM0_CONTIG_NUM_ORDER);
-		if (vstart == 0) {
-			XEN_ERR("allocate memory fail.\n");
-			dom0_memory_free(allocated_size);
-			return -ENOMEM;
-		}
-
-		allocated_size += SIZE_PER_BLOCK;
-
-		size = DOM0_MEMBLOCK_SIZE;
-		vaddr = vstart;
-		while (size > 0) {
-			SetPageReserved(virt_to_page(vaddr));
-			vaddr += PAGE_SIZE;
-			size -= PAGE_SIZE;
-		}
-		pfn = virt_to_pfn(vstart);
-		rsv_mm_info[i].pfn = pfn;
-		rsv_mm_info[i].vir_addr = vstart;
-	}
-
-	sort_viraddr(rsv_mm_info, num_block);
-
-	for (i = 0; i< num_block; i++) {
-
-		/*
-		 * This API is used to exchage MFN for getting a block of
-		 * contiguous physical addresses, its maximum size is 2M.
-		 */
-	#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
-		if (xen_create_contiguous_region(rsv_mm_info[i].vir_addr,
-				DOM0_CONTIG_NUM_ORDER, 0) == 0) {
-	#else
-		if (xen_create_contiguous_region(rsv_mm_info[i].pfn * PAGE_SIZE,
-				DOM0_CONTIG_NUM_ORDER, 0, &dma_handle) == 0) {
-	#endif
-			rsv_mm_info[i].exchange_flag = 1;
-			rsv_mm_info[i].mfn =
-				pfn_to_mfn(rsv_mm_info[i].pfn);
-			rsv_mm_info[i].used = 0;
-		} else {
-			XEN_ERR("exchange memeory fail\n");
-			rsv_mm_info[i].exchange_flag = 0;
-			dom0_dev.fail_times++;
-			if (dom0_dev.fail_times > MAX_EXCHANGE_FAIL_TIME) {
-				dom0_memory_free(rsv_size);
-				return  -EFAULT;
-			}
-		}
-	}
-
-	return 0;
-}
-
-static int
-dom0_prepare_memsegs(struct memory_info *meminfo, struct dom0_mm_data *mm_data)
-{
-	uint32_t num_block;
-	int idx;
-
-	/* check if there is a free name buffer */
-	memcpy(mm_data->name, meminfo->name, DOM0_NAME_MAX);
-	mm_data->name[DOM0_NAME_MAX - 1] = '\0';
-	idx = dom0_find_mempos();
-	if (idx < 0)
-		return -1;
-
-	num_block = meminfo->size / SIZE_PER_BLOCK;
-	/* find free memory and new memory segments*/
-	find_free_memory(num_block, mm_data);
-	find_memseg(num_block, mm_data);
-
-	/* update private memory data */
-	mm_data->refcnt++;
-	mm_data->mem_size = meminfo->size;
-
-	/* update global memory data */
-	dom0_dev.mm_data[idx] = mm_data;
-	dom0_dev.num_mem_ctx++;
-	dom0_dev.used_memsize += mm_data->mem_size;
-
-	return 0;
-}
-
-static int
-dom0_check_memory (struct memory_info *meminfo)
-{
-	int idx;
-	uint64_t mem_size;
-
-	/* round memory size to the next even number. */
-	if (meminfo->size % 2)
-		++meminfo->size;
-
-	mem_size = meminfo->size;
-	if (dom0_dev.num_mem_ctx > NUM_MEM_CTX) {
-		XEN_ERR("Memory data space is full in Dom0 driver\n");
-		return -1;
-	}
-	idx = dom0_find_memdata(meminfo->name);
-	if (idx >= 0) {
-		XEN_ERR("Memory data name %s has already exsited in Dom0 driver.\n",
-			meminfo->name);
-		return -1;
-	}
-	if ((dom0_dev.used_memsize + mem_size) > rsv_memsize) {
-		XEN_ERR("Total size can't be larger than reserved size.\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int __init
-dom0_init(void)
-{
-	if (!xen_domain())
-		return -ENODEV;
-
-	if (rsv_memsize > DOM0_CONFIG_MEMSIZE) {
-		XEN_ERR("The reserved memory size cannot be greater than %d\n",
-			DOM0_CONFIG_MEMSIZE);
-		return -EINVAL;
-	}
-
-	/* Setup the misc device */
-	dom0_dev.miscdev.minor = MISC_DYNAMIC_MINOR;
-	dom0_dev.miscdev.name = "dom0_mm";
-	dom0_dev.miscdev.fops = &data_fops;
-
-	/* register misc char device */
-	if (misc_register(&dom0_dev.miscdev) != 0) {
-		XEN_ERR("Misc device registration failed\n");
-		return -EPERM;
-	}
-
-	mutex_init(&dom0_dev.data_lock);
-	dom0_kobj = kobject_create_and_add("dom0-mm", mm_kobj);
-
-	if (!dom0_kobj) {
-		XEN_ERR("dom0-mm object creation failed\n");
-		misc_deregister(&dom0_dev.miscdev);
-		return -ENOMEM;
-	}
-
-	if (sysfs_create_group(dom0_kobj, &dev_attr_grp)) {
-		kobject_put(dom0_kobj);
-		misc_deregister(&dom0_dev.miscdev);
-		return -EPERM;
-	}
-
-	if (dom0_memory_reserve(rsv_memsize) < 0) {
-		sysfs_remove_group(dom0_kobj, &dev_attr_grp);
-		kobject_put(dom0_kobj);
-		misc_deregister(&dom0_dev.miscdev);
-		return -ENOMEM;
-	}
-
-	XEN_PRINT("####### DPDK Xen Dom0 module loaded  #######\n");
-
-	return 0;
-}
-
-static void __exit
-dom0_exit(void)
-{
-	if (rsv_mm_info != NULL)
-		dom0_memory_free(rsv_memsize);
-
-	sysfs_remove_group(dom0_kobj, &dev_attr_grp);
-	kobject_put(dom0_kobj);
-	misc_deregister(&dom0_dev.miscdev);
-
-	XEN_PRINT("####### DPDK Xen Dom0 module unloaded  #######\n");
-}
-
-static int
-dom0_open(struct inode *inode, struct file *file)
-{
-	file->private_data = NULL;
-
-	XEN_PRINT(KERN_INFO "/dev/dom0_mm opened\n");
-	return 0;
-}
-
-static int
-dom0_release(struct inode *inode, struct file *file)
-{
-	int ret = 0;
-	struct dom0_mm_data *mm_data = file->private_data;
-
-	if (mm_data == NULL)
-		return ret;
-
-	mutex_lock(&dom0_dev.data_lock);
-	if (--mm_data->refcnt == 0)
-		ret = dom0_memory_release(mm_data);
-	mutex_unlock(&dom0_dev.data_lock);
-
-	file->private_data = NULL;
-	XEN_PRINT(KERN_INFO "/dev/dom0_mm closed\n");
-	return ret;
-}
-
-static int
-dom0_mmap(struct file *file, struct vm_area_struct *vm)
-{
-	int status = 0;
-	uint32_t idx = vm->vm_pgoff;
-	uint64_t pfn, size = vm->vm_end - vm->vm_start;
-	struct dom0_mm_data *mm_data = file->private_data;
-
-	if(mm_data == NULL)
-		return -EINVAL;
-
-	mutex_lock(&dom0_dev.data_lock);
-	if (idx >= mm_data->num_memseg) {
-		mutex_unlock(&dom0_dev.data_lock);
-		return -EINVAL;
-	}
-
-	if (size > mm_data->seg_info[idx].size){
-		mutex_unlock(&dom0_dev.data_lock);
-		return -EINVAL;
-	}
-
-	XEN_PRINT("mmap memseg idx =%d,size = 0x%llx\n", idx, size);
-
-	pfn = mm_data->seg_info[idx].pfn;
-	mutex_unlock(&dom0_dev.data_lock);
-
-	status = remap_pfn_range(vm, vm->vm_start, pfn, size, PAGE_SHARED);
-
-	return status;
-}
-static int
-dom0_ioctl(struct file *file,
-	unsigned int ioctl_num,
-	unsigned long ioctl_param)
-{
-	int idx, ret;
-	char name[DOM0_NAME_MAX] = {0};
-	struct memory_info meminfo;
-	struct dom0_mm_data *mm_data = file->private_data;
-
-	XEN_PRINT("IOCTL num=0x%0x param=0x%0lx \n", ioctl_num, ioctl_param);
-
-	/**
-	 * Switch according to the ioctl called
-	 */
-	switch _IOC_NR(ioctl_num) {
-	case _IOC_NR(RTE_DOM0_IOCTL_PREPARE_MEMSEG):
-		ret = copy_from_user(&meminfo, (void *)ioctl_param,
-			sizeof(struct memory_info));
-		if (ret)
-			return  -EFAULT;
-
-		if (mm_data != NULL) {
-			XEN_ERR("Cannot create memory segment for the same"
-				" file descriptor\n");
-			return -EINVAL;
-		}
-
-		/* Allocate private data */
-		mm_data = vmalloc(sizeof(struct dom0_mm_data));
-		if (!mm_data) {
-			XEN_ERR("Unable to allocate device private data\n");
-			return -ENOMEM;
-		}
-		memset(mm_data, 0, sizeof(struct dom0_mm_data));
-
-		mutex_lock(&dom0_dev.data_lock);
-		/* check if we can allocate memory*/
-		if (dom0_check_memory(&meminfo) < 0) {
-			mutex_unlock(&dom0_dev.data_lock);
-			vfree(mm_data);
-			return -EINVAL;
-		}
-
-		/* allocate memory and created memory segments*/
-		if (dom0_prepare_memsegs(&meminfo, mm_data) < 0) {
-			XEN_ERR("create memory segment fail.\n");
-			mutex_unlock(&dom0_dev.data_lock);
-			return -EIO;
-		}
-
-		file->private_data = mm_data;
-		mutex_unlock(&dom0_dev.data_lock);
-		break;
-
-	/* support multiple process in term of memory mapping*/
-	case _IOC_NR(RTE_DOM0_IOCTL_ATTACH_TO_MEMSEG):
-		ret = copy_from_user(name, (void *)ioctl_param,
-				sizeof(char) * DOM0_NAME_MAX);
-		if (ret)
-			return -EFAULT;
-
-		mutex_lock(&dom0_dev.data_lock);
-		idx = dom0_find_memdata(name);
-		if (idx < 0) {
-			mutex_unlock(&dom0_dev.data_lock);
-			return -EINVAL;
-		}
-
-		mm_data = dom0_dev.mm_data[idx];
-		mm_data->refcnt++;
-		file->private_data = mm_data;
-		mutex_unlock(&dom0_dev.data_lock);
-		break;
-
-	case _IOC_NR(RTE_DOM0_IOCTL_GET_NUM_MEMSEG):
-		ret = copy_to_user((void *)ioctl_param, &mm_data->num_memseg,
-				sizeof(int));
-		if (ret)
-			return -EFAULT;
-		break;
-
-	case _IOC_NR(RTE_DOM0_IOCTL_GET_MEMSEG_INFO):
-		ret = copy_to_user((void *)ioctl_param,
-				&mm_data->seg_info[0],
-				sizeof(struct memseg_info) *
-				mm_data->num_memseg);
-		if (ret)
-			return -EFAULT;
-		break;
-	default:
-		XEN_PRINT("IOCTL default \n");
-		break;
-	}
-
-	return 0;
-}
-
-module_init(dom0_init);
-module_exit(dom0_exit);
-
-module_param(rsv_memsize, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rsv_memsize, "Xen-dom0 reserved memory size(MB).\n");
diff --git a/pkg/dpdk.spec b/pkg/dpdk.spec
index 95c3335..fd1b5ef 100644
--- a/pkg/dpdk.spec
+++ b/pkg/dpdk.spec
@@ -52,9 +52,6 @@ ExclusiveArch: i686 x86_64 aarch64
 %endif
 
 BuildRequires: kernel-devel, kernel-headers, libpcap-devel
-%ifarch i686 x86_64
-BuildRequires: xen-devel
-%endif
 BuildRequires: doxygen, python-sphinx, inkscape
 BuildRequires: texlive-collection-latexextra
 
-- 
2.7.4

^ permalink raw reply	[relevance 1%]

* [dpdk-dev] [PATCH 6/6] eal: remove API rte_mem_phy2mch
    2017-08-30 18:10  1% ` [dpdk-dev] [PATCH 5/6] eal: remove xen dom0 support Jianfeng Tan
@ 2017-08-30 18:10  3% ` Jianfeng Tan
  1 sibling, 0 replies; 200+ results
From: Jianfeng Tan @ 2017-08-30 18:10 UTC (permalink / raw)
  To: dev
  Cc: xen-devel, thomas, john.mcnamara, oao.m.martins, jerin.jacob,
	shahafs, Jianfeng Tan

Previously, to get MFN address in dom0, this API is a wrapper to
obtain the "physical address".

As we removed xen dom0 support, this API is not necessary.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 doc/guides/rel_notes/release_17_11.rst     | 2 ++
 drivers/net/e1000/em_rxtx.c                | 4 ++--
 drivers/net/e1000/igb_rxtx.c               | 4 ++--
 drivers/net/fm10k/fm10k_ethdev.c           | 4 ++--
 drivers/net/i40e/i40e_ethdev.c             | 2 +-
 drivers/net/i40e/i40e_fdir.c               | 2 +-
 drivers/net/i40e/i40e_rxtx.c               | 8 ++++----
 drivers/net/ixgbe/ixgbe_rxtx.c             | 4 ++--
 drivers/net/sfc/sfc.c                      | 2 +-
 lib/librte_eal/common/include/rte_memory.h | 5 -----
 lib/librte_mempool/rte_mempool.c           | 3 ---
 11 files changed, 17 insertions(+), 23 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index d211084..06c334b 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -110,6 +110,8 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+   * ``rte_mem_phy2mch`` was used in xen dom0 to obtain the physical address;
+     remove this API as xen dom0 support was removed.
 
 ABI Changes
 -----------
diff --git a/drivers/net/e1000/em_rxtx.c b/drivers/net/e1000/em_rxtx.c
index 31819c5..a0f63a7 100644
--- a/drivers/net/e1000/em_rxtx.c
+++ b/drivers/net/e1000/em_rxtx.c
@@ -1289,7 +1289,7 @@ eth_em_tx_queue_setup(struct rte_eth_dev *dev,
 	txq->port_id = dev->data->port_id;
 
 	txq->tdt_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_TDT(queue_idx));
-	txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr);
+	txq->tx_ring_phys_addr = tz->phys_addr;
 	txq->tx_ring = (struct e1000_data_desc *) tz->addr;
 
 	PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%"PRIx64,
@@ -1416,7 +1416,7 @@ eth_em_rx_queue_setup(struct rte_eth_dev *dev,
 
 	rxq->rdt_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_RDT(queue_idx));
 	rxq->rdh_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_RDH(queue_idx));
-	rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr);
+	rxq->rx_ring_phys_addr = rz->phys_addr;
 	rxq->rx_ring = (struct e1000_rx_desc *) rz->addr;
 
 	PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%"PRIx64,
diff --git a/drivers/net/e1000/igb_rxtx.c b/drivers/net/e1000/igb_rxtx.c
index 1c80a2a..0fccb5d 100644
--- a/drivers/net/e1000/igb_rxtx.c
+++ b/drivers/net/e1000/igb_rxtx.c
@@ -1530,7 +1530,7 @@ eth_igb_tx_queue_setup(struct rte_eth_dev *dev,
 	txq->port_id = dev->data->port_id;
 
 	txq->tdt_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_TDT(txq->reg_idx));
-	txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr);
+	txq->tx_ring_phys_addr = tz->phys_addr;
 
 	txq->tx_ring = (union e1000_adv_tx_desc *) tz->addr;
 	/* Allocate software ring */
@@ -1667,7 +1667,7 @@ eth_igb_rx_queue_setup(struct rte_eth_dev *dev,
 	}
 	rxq->rdt_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_RDT(rxq->reg_idx));
 	rxq->rdh_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_RDH(rxq->reg_idx));
-	rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr);
+	rxq->rx_ring_phys_addr = rz->phys_addr;
 	rxq->rx_ring = (union e1000_adv_rx_desc *) rz->addr;
 
 	/* Allocate software ring. */
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index e60d3a3..15ea2a5 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1887,7 +1887,7 @@ fm10k_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id,
 		return -ENOMEM;
 	}
 	q->hw_ring = mz->addr;
-	q->hw_ring_phys_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
+	q->hw_ring_phys_addr = mz->phys_addr;
 
 	/* Check if number of descs satisfied Vector requirement */
 	if (!rte_is_power_of_2(nb_desc)) {
@@ -2047,7 +2047,7 @@ fm10k_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id,
 		return -ENOMEM;
 	}
 	q->hw_ring = mz->addr;
-	q->hw_ring_phys_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
+	q->hw_ring_phys_addr = mz->phys_addr;
 
 	/*
 	 * allocate memory for the RS bit tracker. Enough slots to hold the
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 5f26e24..dc5458d 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -3741,7 +3741,7 @@ i40e_allocate_dma_mem_d(__attribute__((unused)) struct i40e_hw *hw,
 
 	mem->size = size;
 	mem->va = mz->addr;
-	mem->pa = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
+	mem->pa = mz->phys_addr;
 	mem->zone = (const void *)mz;
 	PMD_DRV_LOG(DEBUG,
 		"memzone %s allocated with physical address: %"PRIu64,
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index 8013add..70dae92 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -249,7 +249,7 @@ i40e_fdir_setup(struct i40e_pf *pf)
 		goto fail_mem;
 	}
 	pf->fdir.prg_pkt = mz->addr;
-	pf->fdir.dma_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
+	pf->fdir.dma_addr = mz->phys_addr;
 
 	pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id);
 	PMD_DRV_LOG(INFO, "FDIR setup successfully, with programming queue %u.",
diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c
index f571e79..344c11c 100644
--- a/drivers/net/i40e/i40e_rxtx.c
+++ b/drivers/net/i40e/i40e_rxtx.c
@@ -1822,7 +1822,7 @@ i40e_dev_rx_queue_setup(struct rte_eth_dev *dev,
 	/* Zero all the descriptors in the ring. */
 	memset(rz->addr, 0, ring_size);
 
-	rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr);
+	rxq->rx_ring_phys_addr = rz->phys_addr;
 	rxq->rx_ring = (union i40e_rx_desc *)rz->addr;
 
 	len = (uint16_t)(nb_desc + RTE_PMD_I40E_RX_MAX_BURST);
@@ -2159,7 +2159,7 @@ i40e_dev_tx_queue_setup(struct rte_eth_dev *dev,
 	txq->vsi = vsi;
 	txq->tx_deferred_start = tx_conf->tx_deferred_start;
 
-	txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr);
+	txq->tx_ring_phys_addr = tz->phys_addr;
 	txq->tx_ring = (struct i40e_tx_desc *)tz->addr;
 
 	/* Allocate software ring */
@@ -2671,7 +2671,7 @@ i40e_fdir_setup_tx_resources(struct i40e_pf *pf)
 	txq->reg_idx = pf->fdir.fdir_vsi->base_queue;
 	txq->vsi = pf->fdir.fdir_vsi;
 
-	txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr);
+	txq->tx_ring_phys_addr = tz->phys_addr;
 	txq->tx_ring = (struct i40e_tx_desc *)tz->addr;
 	/*
 	 * don't need to allocate software ring and reset for the fdir
@@ -2727,7 +2727,7 @@ i40e_fdir_setup_rx_resources(struct i40e_pf *pf)
 	rxq->reg_idx = pf->fdir.fdir_vsi->base_queue;
 	rxq->vsi = pf->fdir.fdir_vsi;
 
-	rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr);
+	rxq->rx_ring_phys_addr = rz->phys_addr;
 	rxq->rx_ring = (union i40e_rx_desc *)rz->addr;
 
 	/*
diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c
index 64bff25..ac1415b 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx.c
@@ -2548,7 +2548,7 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
 	else
 		txq->tdt_reg_addr = IXGBE_PCI_REG_ADDR(hw, IXGBE_TDT(txq->reg_idx));
 
-	txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr);
+	txq->tx_ring_phys_addr = tz->phys_addr;
 	txq->tx_ring = (union ixgbe_adv_tx_desc *) tz->addr;
 
 	/* Allocate software ring */
@@ -2850,7 +2850,7 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev,
 			IXGBE_PCI_REG_ADDR(hw, IXGBE_RDH(rxq->reg_idx));
 	}
 
-	rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr);
+	rxq->rx_ring_phys_addr = rz->phys_addr;
 	rxq->rx_ring = (union ixgbe_adv_rx_desc *) rz->addr;
 
 	/*
diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index 6cecfc0..f9e9916 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -61,7 +61,7 @@ sfc_dma_alloc(const struct sfc_adapter *sa, const char *name, uint16_t id,
 		return ENOMEM;
 	}
 
-	esmp->esm_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
+	esmp->esm_addr = mz->phys_addr;
 	if (esmp->esm_addr == RTE_BAD_PHYS_ADDR) {
 		(void)rte_memzone_free(mz);
 		return EFAULT;
diff --git a/lib/librte_eal/common/include/rte_memory.h b/lib/librte_eal/common/include/rte_memory.h
index d8543c0..c545963 100644
--- a/lib/librte_eal/common/include/rte_memory.h
+++ b/lib/librte_eal/common/include/rte_memory.h
@@ -187,11 +187,6 @@ unsigned rte_memory_get_nchannel(void);
  */
 unsigned rte_memory_get_nrank(void);
 
-static inline phys_addr_t
-rte_mem_phy2mch(int32_t memseg_id __rte_unused, const phys_addr_t phy_addr)
-{
-	return phy_addr;
-}
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c
index 6d726ae..892a1ac 100644
--- a/lib/librte_mempool/rte_mempool.c
+++ b/lib/librte_mempool/rte_mempool.c
@@ -473,8 +473,6 @@ rte_mempool_populate_virt(struct rte_mempool *mp, char *addr,
 		     mp->populated_size < mp->size; off += phys_len) {
 
 		paddr = rte_mem_virt2phy(addr + off);
-		/* required for xen_dom0 to get the machine address */
-		paddr = rte_mem_phy2mch(-1, paddr);
 
 		if (paddr == RTE_BAD_PHYS_ADDR && rte_eal_has_hugepages()) {
 			ret = -EINVAL;
@@ -486,7 +484,6 @@ rte_mempool_populate_virt(struct rte_mempool *mp, char *addr,
 			phys_addr_t paddr_tmp;
 
 			paddr_tmp = rte_mem_virt2phy(addr + off + phys_len);
-			paddr_tmp = rte_mem_phy2mch(-1, paddr_tmp);
 
 			if (paddr_tmp != paddr + phys_len)
 				break;
-- 
2.7.4

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v4 2/5] cfgfile: change existing API functions
  @ 2017-08-30 20:07  4%     ` Bruce Richardson
  0 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2017-08-30 20:07 UTC (permalink / raw)
  To: Jacek Piasecki; +Cc: dev, deepak.k.jain, kubax.kozak, michalx.k.jastrzebski

I think the commit title needs rewording. This changes the internals not
the API.

On Mon, Jul 10, 2017 at 02:44:14PM +0200, Jacek Piasecki wrote:
> Change to flat arrays in cfgfile struct force slightly
> diffrent data access for most of cfgfile functions.
> This patch provides necessary changes in existing API.
> 
> Signed-off-by: Jacek Piasecki <jacekx.piasecki@intel.com>
> ---

Some comments below. I believe the change in return value from -1 to
-EINVAL, though a more correct error, actually counts as an ABI change,
so I think that should be removed, i.e. keep errors at -1. Once done:

Acked-by: Bruce Richardon <bruce.richardson@intel.com>

>  lib/librte_cfgfile/rte_cfgfile.c | 120 +++++++++++++++++++--------------------
>  lib/librte_cfgfile/rte_cfgfile.h |   6 +-
>  2 files changed, 62 insertions(+), 64 deletions(-)
> 
> diff --git a/lib/librte_cfgfile/rte_cfgfile.c b/lib/librte_cfgfile/rte_cfgfile.c
> index c6ae3e3..50fe37a 100644
> --- a/lib/librte_cfgfile/rte_cfgfile.c
> +++ b/lib/librte_cfgfile/rte_cfgfile.c
> @@ -35,6 +35,7 @@
>  #include <stdlib.h>
>  #include <string.h>
>  #include <ctype.h>
> +#include <errno.h>
>  #include <rte_common.h>
>  
>  #include "rte_cfgfile.h"
> @@ -42,13 +43,15 @@
>  struct rte_cfgfile_section {
>  	char name[CFG_NAME_LEN];
>  	int num_entries;
> -	struct rte_cfgfile_entry *entries[0];
> +	int allocated_entries;
> +	struct rte_cfgfile_entry *entries;
>  };
>  
>  struct rte_cfgfile {
>  	int flags;
>  	int num_sections;
> -	struct rte_cfgfile_section *sections[0];
> +	int allocated_sections;
> +	struct rte_cfgfile_section *sections;
>  };
> 

These are good changes, allowing us to have the sections array and
entries arrays separate from the basic data structures.

<snip>
> @@ -409,7 +407,7 @@ rte_cfgfile_section_num_entries(struct rte_cfgfile *cfg,
>  {
>  	const struct rte_cfgfile_section *s = _get_section(cfg, sectionname);
>  	if (s == NULL)
> -		return -1;
> +		return -EINVAL;
>  	return s->num_entries;
>  }

I think this change should be dropped for backward compatibility, or
else put in NEXT_ABI #ifdefs and an ABI notice added to the RN.

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH 02/16] nfp: add specific pf probe function
  2017-08-28 16:42  0%   ` Ferruh Yigit
@ 2017-08-31  9:23  0%     ` Alejandro Lucero
  0 siblings, 0 replies; 200+ results
From: Alejandro Lucero @ 2017-08-31  9:23 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev

On Mon, Aug 28, 2017 at 5:42 PM, Ferruh Yigit <ferruh.yigit@intel.com>
wrote:

> On 8/24/2017 5:20 PM, Alejandro Lucero wrote:
> > Configuring the NFP PMD for using the PF requires access through the
> > NSPU interface for device configuration. This patch adds a specific probe
> > function for the PF which uses the NSPU interface. Just basic NSPU access
> > is done by now reading the NSPU ABI version.
> >
> > No ethernet port is created yet.
> >
> > Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
>
> <...>
>
> > +     /* Check NSP ABI version */
> > +     if (nfp_nsp_get_abi_version(nspu_desc, &major, &minor) < 0) {
> > +             RTE_LOG(INFO, PMD, "NFP NSP not present\n");
> > +             goto no_abi;
> > +     }
> > +     PMD_INIT_LOG(INFO, "nspu ABI version: %d.%d\n", major, minor);
> > +
> > +     if (minor < 20) {
> > +             RTE_LOG(INFO, PMD, "NFP NSP ABI version too old. Required
> 0.20 or higher\n");
>
> I believe it worth documenting this detail in commit log and documentation.
>

Ok.


>
> <...>
>
> >
> > -RTE_PMD_REGISTER_PCI(net_nfp, rte_nfp_net_pmd);
> > -RTE_PMD_REGISTER_PCI_TABLE(net_nfp, pci_id_nfp_net_map);
> > -RTE_PMD_REGISTER_KMOD_DEP(net_nfp, "* igb_uio | uio_pci_generic |
> vfio-pci");
> > +RTE_PMD_REGISTER_PCI(net_nfp_pf, rte_nfp_net_pf_pmd);
> > +RTE_PMD_REGISTER_PCI(net_nfp_vf, rte_nfp_net_vf_pmd);
>
> Now pf and vf drivers are separated. For existing drivers this has been
> documented in features file as another file (another column in table),
> but we are looking for better representation for this.
>
> What do you think, does two drivers has significant enough differences
> to be documented as two different drivers?
>
>
At this point PF and VF PMDs are exactly the same except for how
initialization is done. But, this will likely change in the near future.

I did not think about splitting out the features file, but I think it makes
sense. The existing one, just for VFs, has a problem with SRIOV. Obviously
VF support implies SRIOV, but I think the original idea of such a feature
was drivers being able to manage SRIOV, this is, creating and destroying
VFs. Also, firmware upload is just available with the PF, although such a
feature is not in the current features description list.

So, yes, I think I should have a file for the PF PMD and another one for
the VF.

I will add this in next patch set version.

Thanks



> > +RTE_PMD_REGISTER_PCI_TABLE(net_nfp_pf, pci_id_nfp_pf_net_map);
> > +RTE_PMD_REGISTER_PCI_TABLE(net_nfp_vf, pci_id_nfp_vf_net_map);
> > +RTE_PMD_REGISTER_KMOD_DEP(net_nfp_pf, "* igb_uio | uio_pci_generic |
> vfio");
> > +RTE_PMD_REGISTER_KMOD_DEP(net_nfp_vf, "* igb_uio | uio_pci_generic |
> vfio");
> >
> >  /*
> >   * Local variables:
> >
>
>

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] multi-process shared memory on PPC
@ 2017-08-31 14:40  2% Xueming(Steven) Li
  2017-09-12  7:46  0% ` Chao Zhu
  2017-09-12  8:01  0% ` Chao Zhu
  0 siblings, 2 replies; 200+ results
From: Xueming(Steven) Li @ 2017-08-31 14:40 UTC (permalink / raw)
  To: Chao Zhu; +Cc: dev

Hi all,

I'm testing multi-process example on PowerPC system, looks like shared memory not working properly.
Below are the error and debug info of the first multi-process example 'simple_mp' (works as expected on X86):

// Build DPDK, master branch
# make T=ppc_64-power8-linuxapp-gcc -j160 -C examples/multi_process/simple_mp/
# examples/multi_process/simple_mp/build/simple_mp  -w 0:0.0  --proc-type=primary -l 1-2 --socket-mem 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
APP: Finished Process Init.
Starting core 2
simple_mp > 

// Open another terminal and run secondary process
# gdb --args examples/multi_process/simple_mp/build/simple_mp -n 4 -w 0:0.0  --proc-type=secondary -l 3-4 --socket-mem 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "powerpc64le-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from examples/multi_process/simple_mp/build/simple_mp...done.
(gdb) r
Starting program: /home/xueming/mlnx-dpdk.org/examples/multi_process/simple_mp/build/simple_mp -n 4 -w 0:0.0 --proc-type=secondary -l 3-4 --socket-mem 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/powerpc64le-linux-gnu/libthread_db.so.1".
EAL: Detected 144 lcore(s)
EAL: Probing VFIO support...
[New Thread 0x7ffff7a6eff0 (LWP 58811)]
[New Thread 0x7ffff726eff0 (LWP 58812)]

Thread 1 "simple_mp" received signal SIGSEGV, Segmentation fault.
0x00007ffff7d2f3ec in ?? () from /lib/powerpc64le-linux-gnu/libc.so.6
 (gdb) bt full
#0  0x00007ffff7d2f3ec in ?? () from /lib/powerpc64le-linux-gnu/libc.so.6
No symbol table info available.
#1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28 "PRI_2_SEC")
    at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
        te = 0x7ef3eefd5e00
        r = 0x0
        ring_list = 0x7ffff7aa250c
#2  0x0000000010032640 in main (argc=10, argv=0x7ffffffff3e8)
    at /home/xueming/mlnx-dpdk.org/examples/multi_process/simple_mp/main.c:128
        flags = 0
        ring_size = 64
        pool_size = 1024
        pool_cache = 32
        priv_data_sz = 0
        ret = 9
        lcore_id = 32767
        cl = 0x7ffff7fef718 <_dl_argv>
(gdb) f 1
#1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28 "PRI_2_SEC")
    at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
326                     if (strncmp(name, r->name, RTE_RING_NAMESIZE) == 0)
(gdb) l
321
322             rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
323
324             TAILQ_FOREACH(te, ring_list, next) {
325                     r = (struct rte_ring *) te->data;
326                     if (strncmp(name, r->name, RTE_RING_NAMESIZE) == 0)
327                             break;
328             }
329
330             rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
(gdb) p *te
$1 = {next = {tqe_next = 0x0, tqe_prev = 0x0}, data = 0x0}
(gdb) p *ring_list
$2 = {tqh_first = 0x7ef3eefd5e00, tqh_last = 0x7ef3eec6d100}

# uname -a
Linux dragon-power-01 4.13.0-rc2 #1 SMP Tue Aug 29 17:27:05 IDT 2017 ppc64le ppc64le ppc64le GNU/Linux

# cat /etc/issue
Ubuntu 16.04.2 LTS \n \l

# gcc --version
gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

# lscpu
Architecture:          ppc64le
Byte Order:            Little Endian
CPU(s):                144
On-line CPU(s) list:   0-87,96-103,112-159
Thread(s) per core:    8
Core(s) per socket:    4
Socket(s):             4
NUMA node(s):          4
Model:                 2.1 (pvr 004b 0201)
Model name:            POWER8E (raw), altivec supported
CPU max MHz:           3690.0000
CPU min MHz:           2061.0000
L1d cache:             64K
L1i cache:             32K
L2 cache:              512K
L3 cache:              8192K
NUMA node0 CPU(s):     0-39
NUMA node1 CPU(s):     40-79
NUMA node16 CPU(s):    80-87,96-103,112-119
NUMA node17 CPU(s):    120-159

# cat build/.config
# RTE_EXEC_ENV values are the directories in mk/exec-env/
CONFIG_RTE_EXEC_ENV="linuxapp"
# RTE_ARCH values are architecture we compile for. directories in mk/arch/
CONFIG_RTE_ARCH="ppc_64"
# machine can define specific variables or action for a specific board
# RTE_MACHINE values are architecture we compile for. directories in mk/machine/
CONFIG_RTE_MACHINE="power8"
# The compiler we use.
# RTE_TOOLCHAIN values are architecture we compile for. directories in mk/toolchain/
CONFIG_RTE_TOOLCHAIN="gcc"
# Use intrinsics or assembly code for key routines
CONFIG_RTE_FORCE_INTRINSICS=n
# Machine forces strict alignment constraints.
CONFIG_RTE_ARCH_STRICT_ALIGN=n
# Compile to share library
CONFIG_RTE_BUILD_SHARED_LIB=n
# Use newest code breaking previous ABI
CONFIG_RTE_NEXT_ABI=y
# Major ABI to overwrite library specific LIBABIVER
CONFIG_RTE_MAJOR_ABI=
# Machine's cache line size
CONFIG_RTE_CACHE_LINE_SIZE=128
# Compile Environment Abstraction Layer
CONFIG_RTE_LIBRTE_EAL=y
CONFIG_RTE_MAX_LCORE=256
CONFIG_RTE_MAX_NUMA_NODES=32
CONFIG_RTE_MAX_MEMSEG=256
CONFIG_RTE_MAX_MEMZONE=2560
CONFIG_RTE_MAX_TAILQ=32
CONFIG_RTE_LOG_LEVEL=RTE_LOG_INFO
CONFIG_RTE_LOG_DP_LEVEL=RTE_LOG_INFO
CONFIG_RTE_LOG_HISTORY=256
CONFIG_RTE_BACKTRACE=y
CONFIG_RTE_LIBEAL_USE_HPET=n
CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID=n
CONFIG_RTE_EAL_ALWAYS_PANIC_ON_ERROR=n
CONFIG_RTE_EAL_IGB_UIO=y
CONFIG_RTE_EAL_VFIO=y
CONFIG_RTE_MALLOC_DEBUG=n
CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES=y
# Recognize/ignore architecture we compile for. AVX/AVX512 CPU flags for performance/power testing.
# AVX512 is marked as experimental for now, will enable it after enough
# field test and possible optimization.
CONFIG_RTE_ENABLE_AVX=y
CONFIG_RTE_ENABLE_AVX512=n
# Default driver path (or "" to disable)
CONFIG_RTE_EAL_PMD_PATH=""
# Compile Environment Abstraction Layer to support Vmware TSC map
CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=n
# Compile architecture we compile for. argument parser library
CONFIG_RTE_LIBRTE_KVARGS=y
# Compile generic ethernet library
CONFIG_RTE_LIBRTE_ETHER=y
CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n
CONFIG_RTE_MAX_ETHPORTS=32
CONFIG_RTE_MAX_QUEUES_PER_PORT=1024
CONFIG_RTE_LIBRTE_IEEE1588=n
CONFIG_RTE_ETHDEV_QUEUE_STAT_CNTRS=16
CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y
# Turn off Tx preparation stage
# Warning: rte_eth_tx_prepare() can be safely disabled only if using a
# driver which do not implement any Tx preparation.
CONFIG_RTE_ETHDEV_TX_PREPARE_NOOP=n
# Compile burst-oriented Amazon ENA PMD driver
CONFIG_RTE_LIBRTE_ENA_PMD=y
CONFIG_RTE_LIBRTE_ENA_DEBUG_RX=n
CONFIG_RTE_LIBRTE_ENA_DEBUG_TX=n
CONFIG_RTE_LIBRTE_ENA_DEBUG_TX_FREE=n
CONFIG_RTE_LIBRTE_ENA_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_ENA_COM_DEBUG=n
# Compile burst-oriented IGB & EM PMD drivers
CONFIG_RTE_LIBRTE_EM_PMD=y
CONFIG_RTE_LIBRTE_IGB_PMD=y
CONFIG_RTE_LIBRTE_E1000_DEBUG_INIT=n
CONFIG_RTE_LIBRTE_E1000_DEBUG_RX=n
CONFIG_RTE_LIBRTE_E1000_DEBUG_TX=n
CONFIG_RTE_LIBRTE_E1000_DEBUG_TX_FREE=n
CONFIG_RTE_LIBRTE_E1000_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_E1000_PF_DISABLE_STRIP_CRC=n
# Compile burst-oriented IXGBE PMD driver
CONFIG_RTE_LIBRTE_IXGBE_PMD=n
CONFIG_RTE_LIBRTE_IXGBE_DEBUG_INIT=n
CONFIG_RTE_LIBRTE_IXGBE_DEBUG_RX=n
CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX=n
CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX_FREE=n
CONFIG_RTE_LIBRTE_IXGBE_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC=n
CONFIG_RTE_IXGBE_INC_VECTOR=y
CONFIG_RTE_LIBRTE_IXGBE_BYPASS=n
# Compile burst-oriented I40E PMD driver
CONFIG_RTE_LIBRTE_I40E_PMD=y
CONFIG_RTE_LIBRTE_I40E_DEBUG_RX=n
CONFIG_RTE_LIBRTE_I40E_DEBUG_TX=n
CONFIG_RTE_LIBRTE_I40E_DEBUG_TX_FREE=n
CONFIG_RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC=y
CONFIG_RTE_LIBRTE_I40E_INC_VECTOR=y
CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n
CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF=64
CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF=4
CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM=4
# interval up to 8160 us, aligned to 2 (or default value)
CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL=-1
# Compile burst-oriented FM10K PMD
CONFIG_RTE_LIBRTE_FM10K_PMD=n
CONFIG_RTE_LIBRTE_FM10K_DEBUG_INIT=n
CONFIG_RTE_LIBRTE_FM10K_DEBUG_RX=n
CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX=n
CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX_FREE=n
CONFIG_RTE_LIBRTE_FM10K_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE=y
CONFIG_RTE_LIBRTE_FM10K_INC_VECTOR=y
# Compile burst-oriented Mellanox ConnectX-3 (MLX4) PMD
CONFIG_RTE_LIBRTE_MLX4_PMD=n
CONFIG_RTE_LIBRTE_MLX4_DEBUG=n
CONFIG_RTE_LIBRTE_MLX4_DEBUG_BROKEN_VERBS=n
CONFIG_RTE_LIBRTE_MLX4_SGE_WR_N=4
CONFIG_RTE_LIBRTE_MLX4_MAX_INLINE=0
CONFIG_RTE_LIBRTE_MLX4_TX_MP_CACHE=8
CONFIG_RTE_LIBRTE_MLX4_SOFT_COUNTERS=1
# Compile burst-oriented Mellanox ConnectX-4 & ConnectX-5 (MLX5) PMD
CONFIG_RTE_LIBRTE_MLX5_PMD=y
CONFIG_RTE_LIBRTE_MLX5_DEBUG=n
CONFIG_RTE_LIBRTE_MLX5_TX_MP_CACHE=8
# Compile burst-oriented Broadcom PMD driver
CONFIG_RTE_LIBRTE_BNX2X_PMD=n
CONFIG_RTE_LIBRTE_BNX2X_DEBUG=n
CONFIG_RTE_LIBRTE_BNX2X_DEBUG_INIT=n
CONFIG_RTE_LIBRTE_BNX2X_DEBUG_RX=n
CONFIG_RTE_LIBRTE_BNX2X_DEBUG_TX=n
CONFIG_RTE_LIBRTE_BNX2X_MF_SUPPORT=n
CONFIG_RTE_LIBRTE_BNX2X_DEBUG_PERIODIC=n
# Compile burst-oriented Chelsio Terminator (CXGBE) PMD
CONFIG_RTE_LIBRTE_CXGBE_PMD=y
CONFIG_RTE_LIBRTE_CXGBE_DEBUG=n
CONFIG_RTE_LIBRTE_CXGBE_DEBUG_REG=n
CONFIG_RTE_LIBRTE_CXGBE_DEBUG_MBOX=n
CONFIG_RTE_LIBRTE_CXGBE_DEBUG_TX=n
CONFIG_RTE_LIBRTE_CXGBE_DEBUG_RX=n
CONFIG_RTE_LIBRTE_CXGBE_TPUT=y
# Compile burst-oriented Cisco ENIC PMD driver
CONFIG_RTE_LIBRTE_ENIC_PMD=n
CONFIG_RTE_LIBRTE_ENIC_DEBUG=n
CONFIG_RTE_LIBRTE_ENIC_DEBUG_FLOW=n
# Compile burst-oriented Netronome NFP PMD driver
CONFIG_RTE_LIBRTE_NFP_PMD=y
CONFIG_RTE_LIBRTE_NFP_DEBUG=n
# Compile burst-oriented Broadcom BNXT PMD driver
CONFIG_RTE_LIBRTE_BNXT_PMD=y
# Compile burst-oriented Solarflare libefx-based PMD
CONFIG_RTE_LIBRTE_SFC_EFX_PMD=n
CONFIG_RTE_LIBRTE_SFC_EFX_DEBUG=n
# Compile software PMD backed by SZEDATA2 device
CONFIG_RTE_LIBRTE_PMD_SZEDATA2=n
# Defines firmware type address space.
# See documentation for supported values.
# Other values raise compile time error.
CONFIG_RTE_LIBRTE_PMD_SZEDATA2_AS=0
# Compile burst-oriented Cavium Thunderx NICVF PMD driver
CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD=y
CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_INIT=n
CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_RX=n
CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_TX=n
CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_MBOX=n
# Compile burst-oriented Cavium LiquidIO PMD driver
CONFIG_RTE_LIBRTE_LIO_PMD=y
CONFIG_RTE_LIBRTE_LIO_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_LIO_DEBUG_INIT=n
CONFIG_RTE_LIBRTE_LIO_DEBUG_RX=n
CONFIG_RTE_LIBRTE_LIO_DEBUG_TX=n
CONFIG_RTE_LIBRTE_LIO_DEBUG_MBOX=n
CONFIG_RTE_LIBRTE_LIO_DEBUG_REGS=n
# Compile NXP DPAA2 FSL-MC Bus
CONFIG_RTE_LIBRTE_FSLMC_BUS=n
# Compile Support Libraries for NXP DPAA2
CONFIG_RTE_LIBRTE_DPAA2_MEMPOOL=n
CONFIG_RTE_LIBRTE_DPAA2_USE_PHYS_IOVA=y
# Compile burst-oriented NXP DPAA2 PMD driver
CONFIG_RTE_LIBRTE_DPAA2_PMD=n
CONFIG_RTE_LIBRTE_DPAA2_DEBUG_INIT=n
CONFIG_RTE_LIBRTE_DPAA2_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_DPAA2_DEBUG_RX=n
CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX=n
CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX_FREE=n
# Compile burst-oriented VIRTIO PMD driver
CONFIG_RTE_LIBRTE_VIRTIO_PMD=y
CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_INIT=n
CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_RX=n
CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_TX=n
CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DUMP=n
# Compile virtio device emulation inside virtio PMD driver
CONFIG_RTE_VIRTIO_USER=y
# Compile burst-oriented VMXNET3 PMD driver
CONFIG_RTE_LIBRTE_VMXNET3_PMD=n
CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_INIT=n
CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_RX=n
CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX=n
CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX_FREE=n
CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_DRIVER=n
# Compile example software rings based PMD
CONFIG_RTE_LIBRTE_PMD_RING=y
CONFIG_RTE_PMD_RING_MAX_RX_RINGS=16
CONFIG_RTE_PMD_RING_MAX_TX_RINGS=16
# Compile software PMD backed by PCAP files
CONFIG_RTE_LIBRTE_PMD_PCAP=n
# Compile link bonding PMD library
CONFIG_RTE_LIBRTE_PMD_BOND=y
CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB=n
CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB_L1=n
# QLogic 10G/25G/40G/50G/100G PMD
CONFIG_RTE_LIBRTE_QEDE_PMD=y
CONFIG_RTE_LIBRTE_QEDE_DEBUG_INIT=n
CONFIG_RTE_LIBRTE_QEDE_DEBUG_INFO=n
CONFIG_RTE_LIBRTE_QEDE_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_QEDE_DEBUG_TX=n
CONFIG_RTE_LIBRTE_QEDE_DEBUG_RX=n
#Provides abs path/name of architecture we compile for. firmware file.
#Empty string denotes driver will use default firmware
CONFIG_RTE_LIBRTE_QEDE_FW=""
# Compile software PMD backed by AF_PACKET sockets (Linux only)
CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
# Compile ARK PMD
CONFIG_RTE_LIBRTE_ARK_PMD=y
CONFIG_RTE_LIBRTE_ARK_PAD_TX=y
CONFIG_RTE_LIBRTE_ARK_DEBUG_RX=n
CONFIG_RTE_LIBRTE_ARK_DEBUG_TX=n
CONFIG_RTE_LIBRTE_ARK_DEBUG_STATS=n
CONFIG_RTE_LIBRTE_ARK_DEBUG_TRACE=n
# Compile WRS accelerated virtual port (AVP) guest PMD driver
CONFIG_RTE_LIBRTE_AVP_PMD=n
CONFIG_RTE_LIBRTE_AVP_DEBUG_RX=n
CONFIG_RTE_LIBRTE_AVP_DEBUG_TX=n
CONFIG_RTE_LIBRTE_AVP_DEBUG_DRIVER=y
CONFIG_RTE_LIBRTE_AVP_DEBUG_BUFFERS=n
# Compile architecture we compile for. TAP PMD
# It is enabled by default for Linux only.
CONFIG_RTE_LIBRTE_PMD_TAP=y
# Compile Xen PMD
CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
# Compile null PMD
CONFIG_RTE_LIBRTE_PMD_NULL=y
# Compile fail-safe PMD
CONFIG_RTE_LIBRTE_PMD_FAILSAFE=y
# Do prefetch of packet data within PMD driver receive function
CONFIG_RTE_PMD_PACKET_PREFETCH=y
# Compile generic crypto device library
CONFIG_RTE_LIBRTE_CRYPTODEV=y
CONFIG_RTE_LIBRTE_CRYPTODEV_DEBUG=n
CONFIG_RTE_CRYPTO_MAX_DEVS=64
CONFIG_RTE_CRYPTODEV_NAME_LEN=64
# Compile PMD for ARMv8 Crypto device
CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO=n
CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO_DEBUG=n
# Compile NXP DPAA2 crypto sec driver for CAAM HW
CONFIG_RTE_LIBRTE_PMD_DPAA2_SEC=n
CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_INIT=n
CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_RX=n
# Compile PMD for QuickAssist based devices
CONFIG_RTE_LIBRTE_PMD_QAT=n
CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_INIT=n
CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_TX=n
CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_RX=n
CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_DRIVER=n
# Number of sessions to create in architecture we compile for. session memory pool
# on a single QuickAssist device.
CONFIG_RTE_QAT_PMD_MAX_NB_SESSIONS=2048
# Compile PMD for AESNI backed device
CONFIG_RTE_LIBRTE_PMD_AESNI_MB=n
CONFIG_RTE_LIBRTE_PMD_AESNI_MB_DEBUG=n
# Compile PMD for Software backed device
CONFIG_RTE_LIBRTE_PMD_OPENSSL=n
CONFIG_RTE_LIBRTE_PMD_OPENSSL_DEBUG=n
# Compile PMD for AESNI GCM device
CONFIG_RTE_LIBRTE_PMD_AESNI_GCM=n
CONFIG_RTE_LIBRTE_PMD_AESNI_GCM_DEBUG=n
# Compile PMD for SNOW 3G device
CONFIG_RTE_LIBRTE_PMD_SNOW3G=n
CONFIG_RTE_LIBRTE_PMD_SNOW3G_DEBUG=n
# Compile PMD for KASUMI device
CONFIG_RTE_LIBRTE_PMD_KASUMI=n
CONFIG_RTE_LIBRTE_PMD_KASUMI_DEBUG=n
# Compile PMD for ZUC device
CONFIG_RTE_LIBRTE_PMD_ZUC=n
CONFIG_RTE_LIBRTE_PMD_ZUC_DEBUG=n
# Compile PMD for Crypto Scheduler device
CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER=y
CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER_DEBUG=n
# Compile PMD for NULL Crypto device
CONFIG_RTE_LIBRTE_PMD_NULL_CRYPTO=y
# Compile generic event device library
CONFIG_RTE_LIBRTE_EVENTDEV=y
CONFIG_RTE_LIBRTE_EVENTDEV_DEBUG=n
CONFIG_RTE_EVENT_MAX_DEVS=16
CONFIG_RTE_EVENT_MAX_QUEUES_PER_DEV=64
# Compile PMD for skeleton event device
CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV=y
CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV_DEBUG=n
# Compile PMD for software event device
CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV=y
CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV_DEBUG=n
# Compile PMD for octeontx sso event device
CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF=y
CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF_DEBUG=n
# Compile librte_ring
CONFIG_RTE_LIBRTE_RING=y
# Compile librte_mempool
CONFIG_RTE_LIBRTE_MEMPOOL=y
CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE=512
CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG=n
# Compile Mempool drivers
CONFIG_RTE_DRIVER_MEMPOOL_RING=y
CONFIG_RTE_DRIVER_MEMPOOL_STACK=y
# Compile librte_mbuf
CONFIG_RTE_LIBRTE_MBUF=y
CONFIG_RTE_LIBRTE_MBUF_DEBUG=n
CONFIG_RTE_MBUF_DEFAULT_MEMPOOL_OPS="ring_mp_mc"
CONFIG_RTE_MBUF_REFCNT_ATOMIC=y
CONFIG_RTE_PKTMBUF_HEADROOM=128
# Compile librte_timer
CONFIG_RTE_LIBRTE_TIMER=y
CONFIG_RTE_LIBRTE_TIMER_DEBUG=n
# Compile librte_cfgfile
CONFIG_RTE_LIBRTE_CFGFILE=y
# Compile librte_cmdline
CONFIG_RTE_LIBRTE_CMDLINE=y
CONFIG_RTE_LIBRTE_CMDLINE_DEBUG=n
# Compile librte_hash
CONFIG_RTE_LIBRTE_HASH=y
CONFIG_RTE_LIBRTE_HASH_DEBUG=n
# Compile librte_efd
CONFIG_RTE_LIBRTE_EFD=y
# Compile librte_jobstats
CONFIG_RTE_LIBRTE_JOBSTATS=y
# Compile architecture we compile for. device metrics library
CONFIG_RTE_LIBRTE_METRICS=y
# Compile architecture we compile for. bitrate statistics library
CONFIG_RTE_LIBRTE_BITRATE=y
# Compile architecture we compile for. latency statistics library
CONFIG_RTE_LIBRTE_LATENCY_STATS=y
# Compile librte_lpm
CONFIG_RTE_LIBRTE_LPM=y
CONFIG_RTE_LIBRTE_LPM_DEBUG=n
# Compile librte_acl
CONFIG_RTE_LIBRTE_ACL=y
CONFIG_RTE_LIBRTE_ACL_DEBUG=n
# Compile librte_power
CONFIG_RTE_LIBRTE_POWER=y
CONFIG_RTE_LIBRTE_POWER_DEBUG=n
CONFIG_RTE_MAX_LCORE_FREQS=64
# Compile librte_net
CONFIG_RTE_LIBRTE_NET=y
# Compile librte_ip_frag
CONFIG_RTE_LIBRTE_IP_FRAG=y
CONFIG_RTE_LIBRTE_IP_FRAG_DEBUG=n
CONFIG_RTE_LIBRTE_IP_FRAG_MAX_FRAG=4
CONFIG_RTE_LIBRTE_IP_FRAG_TBL_STAT=n
# Compile GRO library
CONFIG_RTE_LIBRTE_GRO=y
# Compile librte_meter
CONFIG_RTE_LIBRTE_METER=y
# Compile librte_sched
CONFIG_RTE_LIBRTE_SCHED=y
CONFIG_RTE_SCHED_DEBUG=n
CONFIG_RTE_SCHED_RED=n
CONFIG_RTE_SCHED_COLLECT_STATS=n
CONFIG_RTE_SCHED_SUBPORT_TC_OV=n
CONFIG_RTE_SCHED_PORT_N_GRINDERS=8
CONFIG_RTE_SCHED_VECTOR=n
# Compile architecture we compile for. distributor library
CONFIG_RTE_LIBRTE_DISTRIBUTOR=y
# Compile architecture we compile for. reorder library
CONFIG_RTE_LIBRTE_REORDER=y
# Compile librte_port
CONFIG_RTE_LIBRTE_PORT=y
CONFIG_RTE_PORT_STATS_COLLECT=n
CONFIG_RTE_PORT_PCAP=n
# Compile librte_table
CONFIG_RTE_LIBRTE_TABLE=y
CONFIG_RTE_TABLE_STATS_COLLECT=n
# Compile librte_pipeline
CONFIG_RTE_LIBRTE_PIPELINE=y
CONFIG_RTE_PIPELINE_STATS_COLLECT=n
# Compile librte_kni
CONFIG_RTE_LIBRTE_KNI=y
CONFIG_RTE_LIBRTE_PMD_KNI=y
CONFIG_RTE_KNI_KMOD=y
CONFIG_RTE_KNI_KMOD_ETHTOOL=n
CONFIG_RTE_KNI_PREEMPT_DEFAULT=y
# Compile architecture we compile for. pdump library
CONFIG_RTE_LIBRTE_PDUMP=y
# Compile vhost user library
CONFIG_RTE_LIBRTE_VHOST=y
CONFIG_RTE_LIBRTE_VHOST_NUMA=y
CONFIG_RTE_LIBRTE_VHOST_DEBUG=n
# Compile vhost PMD
# To compile, CONFIG_RTE_LIBRTE_VHOST should be enabled.
CONFIG_RTE_LIBRTE_PMD_VHOST=y
#Compile Xen domain0 support
CONFIG_RTE_LIBRTE_XEN_DOM0=n
# Compile architecture we compile for. test application
CONFIG_RTE_APP_TEST=y
CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
# Compile architecture we compile for. PMD test application
CONFIG_RTE_TEST_PMD=y
CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
# Compile architecture we compile for. crypto performance application
CONFIG_RTE_APP_CRYPTO_PERF=y
# Compile architecture we compile for. eventdev application
CONFIG_RTE_APP_EVENTDEV=y
CONFIG_RTE_EXEC_ENV_LINUXAPP=y
CONFIG_RTE_ARCH_PPC_64=y
CONFIG_RTE_ARCH_64=y
CONFIG_RTE_TOOLCHAIN_GCC=y
# Note: Power doesn't have this support
# Note: Initially, all of architecture we compile for. PMD drivers compilation are turned off on Power
# Will turn on them only after architecture we compile for. successful testing on Power

Please refer here for more information on running DPDK multi-process examples:
     http://dpdk.org/doc/guides/sample_app_ug/multi_process.html

Best Regards,
Xueming

^ permalink raw reply	[relevance 2%]

* Re: [dpdk-dev] [PATCH v1] net/mlx5: support upstream rdma-core
       [not found]     ` <CGME20170831161745eucas1p112753dbc96b3b209d303b007dda0408b@eucas1p1.samsung.com>
@ 2017-08-31 16:17  3%   ` Alexey Perevalov
  2017-09-04  6:30  0%     ` Shachar Beiser
  0 siblings, 1 reply; 200+ results
From: Alexey Perevalov @ 2017-08-31 16:17 UTC (permalink / raw)
  To: dev

Hello Shachar,

Thank you for the patch.


Please could you specify patch set you used in new version, IIUC,

it's [PATCH 0/5] net/mlx5: cleanups" and [PATCH 0/5] net/mlx5: 
enable/disable vPMD and some cleanups

by Nélio Laranjeiro.

Also rdma-core version, I used HEAD (commit 
202b39622e67b0424b2598fc6dd1c546e42f9edb),

but I had to revert "mlx5: Fix ABI break from revising the UAR pointer".


-- 
Best regards,
Alexey Perevalov

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v3] ethdev: modifiy vlan_offload_set_t to return int
  2017-08-25 13:47  4%   ` [dpdk-dev] [PATCH v3] " David Harton
@ 2017-08-31 22:04  3%     ` Thomas Monjalon
  2017-08-31 22:08  0%       ` Thomas Monjalon
  2017-09-01  0:40  0%       ` David Harton (dharton)
  2017-09-01  2:36  7%     ` [dpdk-dev] [PATCH v4] ethdev: allow returning error on VLAN offload configuration David Harton
  1 sibling, 2 replies; 200+ results
From: Thomas Monjalon @ 2017-08-31 22:04 UTC (permalink / raw)
  To: David Harton
  Cc: dev, ferruh.yigit, ajit.khaparde, johndale, konstantin.ananyev,
	jingjing.wu, beilei.xing, jing.d.chen, adrien.mazarguil,
	nelio.laranjeiro, alejandro.lucero, hemant.agrawal, rasesh.mody,
	harish.patil, skhare, yliu, maxime.coquelin, allain.legacy

Hi,

25/08/2017 15:47, David Harton:
> Some devices may not support or fail setting VLAN offload
> configuration based on dynamic circurmstances so the
> vlan_offload_set_t vector is modified to return an int so
> the caller can determine success or not.

I agree with allowing to return an error.

Comments on details below.

The title could be changed to better reflect the purpose:
	ethdev: allow returning error on VLAN configuration

> --- a/doc/guides/rel_notes/release_17_11.rst
> +++ b/doc/guides/rel_notes/release_17_11.rst
> @@ -124,7 +124,7 @@ ABI Changes
>     Also, make sure to start the actual text at the margin.
>     =========================================================
>  
> -
> +* Changed return type of ``vlan_offload_set_t`` from ``void`` to ``int``.

It should be referenced as an API change (instead of ABI change).
(and line spacing must be kept)

We also need to bump the library version but it can be done with
bigger changes in ethdev.

> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -2049,10 +2049,16 @@ struct rte_eth_dev *
>  	int ret = 0;
>  	int mask = 0;
>  	int cur, org = 0;
> +	uint8_t org_strip, org_filter, org_extend;
>  
>  	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
>  	dev = &rte_eth_devices[port_id];
>  
> +	/* save original values in case of failure */
> +	org_strip = dev->data->dev_conf.rxmode.hw_vlan_strip;
> +	org_filter = dev->data->dev_conf.rxmode.hw_vlan_filter;
> +	org_extend = dev->data->dev_conf.rxmode.hw_vlan_extend;

Please waste one more char to write "orig" instead of "org".

> -	(*dev->dev_ops->vlan_offload_set)(dev, mask);
> +	ret = (*dev->dev_ops->vlan_offload_set)(dev, mask);
> +	if (ret) {
> +		/* hit an error restore  original values */
> +		dev->data->dev_conf.rxmode.hw_vlan_strip = org_strip;
> +		dev->data->dev_conf.rxmode.hw_vlan_filter = org_filter;
> +		dev->data->dev_conf.rxmode.hw_vlan_extend = org_extend;
> +	}

Isn't it the responsibility of the PMD to restore values in case of error?
I understand it is there to factorize error handling code, right?
Do we want to document this behaviour with the ops prototype?

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v3] ethdev: modifiy vlan_offload_set_t to return int
  2017-08-31 22:04  3%     ` Thomas Monjalon
@ 2017-08-31 22:08  0%       ` Thomas Monjalon
  2017-09-01  0:40  0%       ` David Harton (dharton)
  1 sibling, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-31 22:08 UTC (permalink / raw)
  To: David Harton
  Cc: dev, ferruh.yigit, ajit.khaparde, johndale, konstantin.ananyev,
	jingjing.wu, beilei.xing, jing.d.chen, adrien.mazarguil,
	nelio.laranjeiro, alejandro.lucero, hemant.agrawal, rasesh.mody,
	harish.patil, skhare, yliu, maxime.coquelin, allain.legacy

One more comment below

01/09/2017 00:04, Thomas Monjalon:
> Hi,
> 
> 25/08/2017 15:47, David Harton:
> > Some devices may not support or fail setting VLAN offload
> > configuration based on dynamic circurmstances so the
> > vlan_offload_set_t vector is modified to return an int so
> > the caller can determine success or not.
> 
> I agree with allowing to return an error.
> 
> Comments on details below.
> 
> The title could be changed to better reflect the purpose:
> 	ethdev: allow returning error on VLAN configuration
> 
> > --- a/doc/guides/rel_notes/release_17_11.rst
> > +++ b/doc/guides/rel_notes/release_17_11.rst
> > @@ -124,7 +124,7 @@ ABI Changes
> >     Also, make sure to start the actual text at the margin.
> >     =========================================================
> >  
> > -
> > +* Changed return type of ``vlan_offload_set_t`` from ``void`` to ``int``.
> 
> It should be referenced as an API change (instead of ABI change).
> (and line spacing must be kept)
> 
> We also need to bump the library version but it can be done with
> bigger changes in ethdev.
> 
> > --- a/lib/librte_ether/rte_ethdev.c
> > +++ b/lib/librte_ether/rte_ethdev.c
> > @@ -2049,10 +2049,16 @@ struct rte_eth_dev *
> >  	int ret = 0;
> >  	int mask = 0;
> >  	int cur, org = 0;
> > +	uint8_t org_strip, org_filter, org_extend;
> >  
> >  	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> >  	dev = &rte_eth_devices[port_id];
> >  
> > +	/* save original values in case of failure */
> > +	org_strip = dev->data->dev_conf.rxmode.hw_vlan_strip;
> > +	org_filter = dev->data->dev_conf.rxmode.hw_vlan_filter;
> > +	org_extend = dev->data->dev_conf.rxmode.hw_vlan_extend;
> 
> Please waste one more char to write "orig" instead of "org".
> 
> > -	(*dev->dev_ops->vlan_offload_set)(dev, mask);
> > +	ret = (*dev->dev_ops->vlan_offload_set)(dev, mask);

Which error codes can be returned by this op?
It is adding new error codes to rte_eth_dev_set_vlan_offload(),
and they must be documented in the doxygen.

> > +	if (ret) {
> > +		/* hit an error restore  original values */
> > +		dev->data->dev_conf.rxmode.hw_vlan_strip = org_strip;
> > +		dev->data->dev_conf.rxmode.hw_vlan_filter = org_filter;
> > +		dev->data->dev_conf.rxmode.hw_vlan_extend = org_extend;
> > +	}
> 
> Isn't it the responsibility of the PMD to restore values in case of error?
> I understand it is there to factorize error handling code, right?
> Do we want to document this behaviour with the ops prototype?

Thanks

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 2/2] doc: Update ABI Change for rte_eth_stats_reset
  2017-08-10 13:29 13%   ` [dpdk-dev] [PATCH v4 2/2] doc: Update ABI Change for rte_eth_stats_reset David Harton
@ 2017-08-31 22:10  7%     ` Thomas Monjalon
  2017-08-31 22:10  4%       ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2017-08-31 22:10 UTC (permalink / raw)
  To: David Harton; +Cc: dev, harry.van.haaren, christian.ehrhardt

10/08/2017 15:29, David Harton:
> --- a/doc/guides/rel_notes/release_17_11.rst
> +++ b/doc/guides/rel_notes/release_17_11.rst
> @@ -124,6 +124,7 @@ ABI Changes
>     Also, make sure to start the actual text at the margin.
>     =========================================================
>  
> +* Changed return type of ``rte_eth_stats_reset`` from ``void`` to ``int``.

It should be documented in API changes section (not ABI).

^ permalink raw reply	[relevance 7%]

* Re: [dpdk-dev] [PATCH v4 2/2] doc: Update ABI Change for rte_eth_stats_reset
  2017-08-31 22:10  7%     ` Thomas Monjalon
@ 2017-08-31 22:10  4%       ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-08-31 22:10 UTC (permalink / raw)
  To: David Harton; +Cc: dev, harry.van.haaren, christian.ehrhardt

01/09/2017 00:10, Thomas Monjalon:
> 10/08/2017 15:29, David Harton:
> > --- a/doc/guides/rel_notes/release_17_11.rst
> > +++ b/doc/guides/rel_notes/release_17_11.rst
> > @@ -124,6 +124,7 @@ ABI Changes
> >     Also, make sure to start the actual text at the margin.
> >     =========================================================
> >  
> > +* Changed return type of ``rte_eth_stats_reset`` from ``void`` to ``int``.
> 
> It should be documented in API changes section (not ABI).

And it can be squashed with the first patch :)

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v3] ethdev: modifiy vlan_offload_set_t to return int
  2017-08-31 22:04  3%     ` Thomas Monjalon
  2017-08-31 22:08  0%       ` Thomas Monjalon
@ 2017-09-01  0:40  0%       ` David Harton (dharton)
  2017-09-01  8:01  0%         ` Thomas Monjalon
  1 sibling, 1 reply; 200+ results
From: David Harton (dharton) @ 2017-09-01  0:40 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, ferruh.yigit, ajit.khaparde, John Daley (johndale),
	konstantin.ananyev, jingjing.wu, beilei.xing, jing.d.chen,
	adrien.mazarguil, nelio.laranjeiro, alejandro.lucero,
	hemant.agrawal, rasesh.mody, harish.patil, skhare, yliu,
	maxime.coquelin, allain.legacy

Hi Thomas,

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Thursday, August 31, 2017 6:04 PM
> To: David Harton (dharton) <dharton@cisco.com>
> Cc: dev@dpdk.org; ferruh.yigit@intel.com; ajit.khaparde@broadcom.com; John
> Daley (johndale) <johndale@cisco.com>; konstantin.ananyev@intel.com;
> jingjing.wu@intel.com; beilei.xing@intel.com; jing.d.chen@intel.com;
> adrien.mazarguil@6wind.com; nelio.laranjeiro@6wind.com;
> alejandro.lucero@netronome.com; hemant.agrawal@nxp.com;
> rasesh.mody@cavium.com; harish.patil@cavium.com; skhare@vmware.com;
> yliu@fridaylinux.org; maxime.coquelin@redhat.com;
> allain.legacy@windriver.com
> Subject: Re: [dpdk-dev] [PATCH v3] ethdev: modifiy vlan_offload_set_t to
> return int
> 
> Hi,
> 
> 25/08/2017 15:47, David Harton:
> > Some devices may not support or fail setting VLAN offload
> > configuration based on dynamic circurmstances so the
> > vlan_offload_set_t vector is modified to return an int so
> > the caller can determine success or not.
> 
> I agree with allowing to return an error.
> 
> Comments on details below.
> 
> The title could be changed to better reflect the purpose:
> 	ethdev: allow returning error on VLAN configuration

Sure.

> 
> > --- a/doc/guides/rel_notes/release_17_11.rst
> > +++ b/doc/guides/rel_notes/release_17_11.rst
> > @@ -124,7 +124,7 @@ ABI Changes
> >     Also, make sure to start the actual text at the margin.
> >     =========================================================
> >
> > -
> > +* Changed return type of ``vlan_offload_set_t`` from ``void`` to ``int``.
> 
> It should be referenced as an API change (instead of ABI change).
> (and line spacing must be kept)

Sure I'll move it to API.

Line spacing?  You mean 80 char width?  I followed an example from a previous
release so I'm not sure what you mean.

> 
> We also need to bump the library version but it can be done with
> bigger changes in ethdev.

Ok.

> 
> > --- a/lib/librte_ether/rte_ethdev.c
> > +++ b/lib/librte_ether/rte_ethdev.c
> > @@ -2049,10 +2049,16 @@ struct rte_eth_dev *
> >  	int ret = 0;
> >  	int mask = 0;
> >  	int cur, org = 0;
> > +	uint8_t org_strip, org_filter, org_extend;
> >
> >  	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> >  	dev = &rte_eth_devices[port_id];
> >
> > +	/* save original values in case of failure */
> > +	org_strip = dev->data->dev_conf.rxmode.hw_vlan_strip;
> > +	org_filter = dev->data->dev_conf.rxmode.hw_vlan_filter;
> > +	org_extend = dev->data->dev_conf.rxmode.hw_vlan_extend;
> 
> Please waste one more char to write "orig" instead of "org".

Will do.

> 
> > -	(*dev->dev_ops->vlan_offload_set)(dev, mask);
> > +	ret = (*dev->dev_ops->vlan_offload_set)(dev, mask);
> > +	if (ret) {
> > +		/* hit an error restore  original values */
> > +		dev->data->dev_conf.rxmode.hw_vlan_strip = org_strip;
> > +		dev->data->dev_conf.rxmode.hw_vlan_filter = org_filter;
> > +		dev->data->dev_conf.rxmode.hw_vlan_extend = org_extend;
> > +	}
> 
> Isn't it the responsibility of the PMD to restore values in case of error?
> I understand it is there to factorize error handling code, right?

By setting the dev_conf.rxmode.hw_vlan_* fields this function is claiming 
ownership of that data and therefore it should be the one to reset it.

> Do we want to document this behaviour with the ops prototype?

Why?  Shouldn't any function that doesn't do what it was asked to do 
leave the system in its original state and in fact if it doesn't that 
is when it should be documented what the behavior is?  Otherwise every 
caller has to implement some cleanup code and would have to be given 
information to know how to perform that cleanup as well which seems 
more complicated.

Thanks,
Dave

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v5] ethdev: add return code to rte_eth_stats_reset()
    2017-08-10 13:29 13%   ` [dpdk-dev] [PATCH v4 2/2] doc: Update ABI Change for rte_eth_stats_reset David Harton
@ 2017-09-01  2:26  3%   ` David Harton
  2017-09-01  7:47  0%     ` Hemant Agrawal
  1 sibling, 1 reply; 200+ results
From: David Harton @ 2017-09-01  2:26 UTC (permalink / raw)
  To: thomas; +Cc: dev, David Harton

Some devices do not support reset of eth stats.  An application may
need to know not to clear shadow stats if the device cannot.

rte_eth_stats_reset is updated to provide a return code to share
whether the device supports reset or not.

Signed-off-by: David Harton <dharton@cisco.com>
---

v5:
* squashed doc patch
* moved rel_note change from ABI to API section

v4:
* commented return values

v3:
* overcame noob errors and figured out patch challenged

v2:
* fixed soft tab issue inserted while moving changes

 doc/guides/rel_notes/release_17_11.rst | 13 +++++++++++++
 lib/librte_ether/rte_ethdev.c          |  8 +++++---
 lib/librte_ether/rte_ethdev.h          |  6 +++++-
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 22df4fd..6282667 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -110,6 +110,19 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* **Modified the return type of rte_eth_stats_reset.**
+
+  Changed return type of ``rte_eth_stats_reset`` from ``void`` to ``int``
+  so the caller may know whether a device supports the operation or not
+  and if the operation was carried out.
+
+* **Modified the vlan_offload_set_t function prototype in the ethdev library.**
+
+  Changed the function prototype of ``vlan_offload_set_t``.  The return value
+  has been changed from ``void`` to ``int`` so the caller to knows whether
+  the backing device supports the operation or if the operation was
+  successfully performed.
+
 * **Modified the vlan_offload_set_t function prototype in the ethdev library.**
 
   Changed the function prototype of ``vlan_offload_set_t``.  The return value
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 05e52b8..f0f1775 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1341,17 +1341,19 @@ struct rte_eth_dev *
 	return 0;
 }
 
-void
+int
 rte_eth_stats_reset(uint8_t port_id)
 {
 	struct rte_eth_dev *dev;
 
-	RTE_ETH_VALID_PORTID_OR_RET(port_id);
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
 	dev = &rte_eth_devices[port_id];
 
-	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_reset, -ENOTSUP);
 	(*dev->dev_ops->stats_reset)(dev);
 	dev->data->rx_mbuf_alloc_failed = 0;
+
+	return 0;
 }
 
 static int
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 7254fd0..9110725 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -2246,8 +2246,12 @@ int rte_eth_tx_queue_setup(uint8_t port_id, uint16_t tx_queue_id,
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
+ * @return
+ *   - (0) if device notified to reset stats.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
  */
-void rte_eth_stats_reset(uint8_t port_id);
+int rte_eth_stats_reset(uint8_t port_id);
 
 /**
  * Retrieve names of extended statistics of an Ethernet device.
-- 
1.8.3.1

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v4] ethdev: allow returning error on VLAN offload configuration
  2017-08-25 13:47  4%   ` [dpdk-dev] [PATCH v3] " David Harton
  2017-08-31 22:04  3%     ` Thomas Monjalon
@ 2017-09-01  2:36  7%     ` David Harton
  2017-09-01  7:41  0%       ` Hemant Agrawal
  1 sibling, 1 reply; 200+ results
From: David Harton @ 2017-09-01  2:36 UTC (permalink / raw)
  To: thomas, ferruh.yigit, ajit.khaparde, johndale,
	konstantin.ananyev, jingjing.wu, beilei.xing, jing.d.chen,
	adrien.mazarguil, nelio.laranjeiro, alejandro.lucero,
	hemant.agrawal, rasesh.mody, harish.patil, skhare, yliu,
	maxime.coquelin, allain.legacy
  Cc: dev, David Harton

Some devices may not support or fail setting VLAN offload
configuration based on dynamic circurmstances so the
vlan_offload_set_t vector is modified to return an int so
the caller can determine success or not.

rte_eth_dev_set_vlan_offload is updated to return the
value provided by the vector when called along with restoring
the original offload configs on failure.

Existing vlan_offload_set_t vectors are modified to return
an int.  Majority of cases return 0 but a few that actually
can fail now return their failure codes.

Finally, a vlan_offload_set_t vector is added to virtio
to facilitate dynamically turning VLAN strip on or off.

Signed-off-by: David Harton <dharton@cisco.com>
---

v4
* Modified commit message heading
* Moved rel_note comments from ABI to API section
* Renamed locals of rte_eth_dev_set_vlan_offload from 'org*' to 'orig*'

v3
* Fixed a format error.
* Apologies...need to figure out why checkpatches.pl keeps saying
  valid patch when I've got soft tabs.

v2
* Fixed a missed format error.
* Removed vlan offload vector call casts and replaced with checks 
  for return values.

v1
* This is an ABI breakage that has been previously negotiated
  with Thomas and the proposed rel note change is included as well.

 doc/guides/rel_notes/release_17_11.rst |  8 +++++++-
 drivers/net/avp/avp_ethdev.c           | 12 +++++++++---
 drivers/net/bnxt/bnxt_ethdev.c         |  9 ++++++---
 drivers/net/dpaa2/dpaa2_ethdev.c       | 13 ++++++++++---
 drivers/net/e1000/em_ethdev.c          | 12 +++++++++---
 drivers/net/e1000/igb_ethdev.c         | 12 +++++++++---
 drivers/net/enic/enic_ethdev.c         |  8 +++++---
 drivers/net/fm10k/fm10k_ethdev.c       |  3 ++-
 drivers/net/i40e/i40e_ethdev.c         | 11 ++++++++---
 drivers/net/i40e/i40e_ethdev_vf.c      |  9 ++++++---
 drivers/net/ixgbe/ixgbe_ethdev.c       | 25 ++++++++++++++++++-------
 drivers/net/mlx5/mlx5.h                |  2 +-
 drivers/net/mlx5/mlx5_vlan.c           |  3 ++-
 drivers/net/nfp/nfp_net.c              | 13 +++++++------
 drivers/net/qede/qede_ethdev.c         |  9 +++++++--
 drivers/net/virtio/virtio_ethdev.c     | 21 +++++++++++++++++++++
 drivers/net/vmxnet3/vmxnet3_ethdev.c   | 10 +++++++---
 lib/librte_ether/rte_ethdev.c          | 28 ++++++++++++++++++++--------
 lib/librte_ether/rte_ethdev.h          |  2 +-
 19 files changed, 155 insertions(+), 55 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f9..22df4fd 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -110,6 +110,13 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* **Modified the vlan_offload_set_t function prototype in the ethdev library.**
+
+  Changed the function prototype of ``vlan_offload_set_t``.  The return value
+  has been changed from ``void`` to ``int`` so the caller to knows whether
+  the backing device supports the operation or if the operation was
+  successfully performed.
+
 
 ABI Changes
 -----------
@@ -125,7 +132,6 @@ ABI Changes
    =========================================================
 
 
-
 Shared Library Versions
 -----------------------
 
diff --git a/drivers/net/avp/avp_ethdev.c b/drivers/net/avp/avp_ethdev.c
index c746a0e..4011dfa 100644
--- a/drivers/net/avp/avp_ethdev.c
+++ b/drivers/net/avp/avp_ethdev.c
@@ -70,7 +70,7 @@ static int avp_dev_create(struct rte_pci_device *pci_dev,
 static void avp_dev_close(struct rte_eth_dev *dev);
 static void avp_dev_info_get(struct rte_eth_dev *dev,
 			     struct rte_eth_dev_info *dev_info);
-static void avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static int avp_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete);
 static void avp_dev_promiscuous_enable(struct rte_eth_dev *dev);
 static void avp_dev_promiscuous_disable(struct rte_eth_dev *dev);
@@ -2031,7 +2031,12 @@ struct avp_queue {
 	mask = (ETH_VLAN_STRIP_MASK |
 		ETH_VLAN_FILTER_MASK |
 		ETH_VLAN_EXTEND_MASK);
-	avp_vlan_offload_set(eth_dev, mask);
+	ret = avp_vlan_offload_set(eth_dev, mask);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR, "VLAN offload set failed by host, ret=%d\n",
+			    ret);
+		goto unlock;
+	}
 
 	/* update device config */
 	memset(&config, 0, sizeof(config));
@@ -2214,7 +2219,7 @@ struct avp_queue {
 	}
 }
 
-static void
+static int
 avp_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 {
 	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
@@ -2239,6 +2244,7 @@ struct avp_queue {
 		if (eth_dev->data->dev_conf.rxmode.hw_vlan_extend)
 			PMD_DRV_LOG(ERR, "VLAN extend offload not supported\n");
 	}
+	return 0;
 }
 
 static void
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index c9d1122..547bd55 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -144,7 +144,7 @@
 	ETH_RSS_NONFRAG_IPV6_TCP |	\
 	ETH_RSS_NONFRAG_IPV6_UDP)
 
-static void bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask);
+static int bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask);
 
 /***********************/
 
@@ -522,7 +522,9 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 		vlan_mask |= ETH_VLAN_FILTER_MASK;
 	if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip)
 		vlan_mask |= ETH_VLAN_STRIP_MASK;
-	bnxt_vlan_offload_set_op(eth_dev, vlan_mask);
+	rc = bnxt_vlan_offload_set_op(eth_dev, vlan_mask);
+	if (rc)
+		goto error;
 
 	return 0;
 
@@ -1275,7 +1277,7 @@ static int bnxt_vlan_filter_set_op(struct rte_eth_dev *eth_dev,
 		return bnxt_del_vlan_filter(bp, vlan_id);
 }
 
-static void
+static int
 bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask)
 {
 	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
@@ -1307,6 +1309,7 @@ static int bnxt_vlan_filter_set_op(struct rte_eth_dev *eth_dev,
 
 	if (mask & ETH_VLAN_EXTEND_MASK)
 		RTE_LOG(ERR, PMD, "Extend VLAN Not supported\n");
+	return 0;
 }
 
 static void
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 429b3a0..3390cb3 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -138,7 +138,7 @@
 	return ret;
 }
 
-static void
+static int
 dpaa2_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
@@ -158,6 +158,7 @@
 			RTE_LOG(ERR, PMD, "Unable to set vlan filter = %d\n",
 				ret);
 	}
+	return 0;
 }
 
 static int
@@ -643,8 +644,14 @@
 		return ret;
 	}
 	/* VLAN Offload Settings */
-	if (priv->max_vlan_filters)
-		dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
+	if (priv->max_vlan_filters) {
+		ret = dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Error to dpaa2_vlan_offload_set:"
+				     "code = %d\n", ret);
+			return ret;
+		}
+	}
 
 	return 0;
 }
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 3d4ab93..51f49d8 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -99,7 +99,7 @@ static int eth_em_interrupt_action(struct rte_eth_dev *dev,
 
 static int eth_em_vlan_filter_set(struct rte_eth_dev *dev,
 		uint16_t vlan_id, int on);
-static void eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void em_vlan_hw_filter_enable(struct rte_eth_dev *dev);
 static void em_vlan_hw_filter_disable(struct rte_eth_dev *dev);
 static void em_vlan_hw_strip_enable(struct rte_eth_dev *dev);
@@ -668,7 +668,12 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
 
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
 			ETH_VLAN_EXTEND_MASK;
-	eth_em_vlan_offload_set(dev, mask);
+	ret = eth_em_vlan_offload_set(dev, mask);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Unable to update vlan offload");
+		em_dev_clear_queues(dev);
+		return ret;
+	}
 
 	/* Set Interrupt Throttling Rate to maximum allowed value. */
 	E1000_WRITE_REG(hw, E1000_ITR, UINT16_MAX);
@@ -1447,7 +1452,7 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
 	E1000_WRITE_REG(hw, E1000_CTRL, reg);
 }
 
-static void
+static int
 eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if(mask & ETH_VLAN_STRIP_MASK){
@@ -1463,6 +1468,7 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
 		else
 			em_vlan_hw_filter_disable(dev);
 	}
+	return 0;
 }
 
 /*
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index e4f7a9f..fa15ee9 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -157,7 +157,7 @@ static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev,
 static int eth_igb_vlan_tpid_set(struct rte_eth_dev *dev,
 				 enum rte_vlan_type vlan_type,
 				 uint16_t tpid_id);
-static void eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 
 static void igb_vlan_hw_filter_enable(struct rte_eth_dev *dev);
 static void igb_vlan_hw_filter_disable(struct rte_eth_dev *dev);
@@ -1400,7 +1400,12 @@ static int eth_igbvf_pci_remove(struct rte_pci_device *pci_dev)
 	 */
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
 			ETH_VLAN_EXTEND_MASK;
-	eth_igb_vlan_offload_set(dev, mask);
+	ret = eth_igb_vlan_offload_set(dev, mask);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Unable to set vlan offload");
+		igb_dev_clear_queues(dev);
+		return ret;
+	}
 
 	if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) {
 		/* Enable VLAN filter since VMDq always use VLAN filter */
@@ -2715,7 +2720,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 						2 * VLAN_TAG_SIZE);
 }
 
-static void
+static int
 eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if(mask & ETH_VLAN_STRIP_MASK){
@@ -2738,6 +2743,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		else
 			igb_vlan_hw_extend_disable(dev);
 	}
+	return 0;
 }
 
 
diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
index da8fec2..fc1eac2 100644
--- a/drivers/net/enic/enic_ethdev.c
+++ b/drivers/net/enic/enic_ethdev.c
@@ -347,7 +347,7 @@ static int enicpmd_vlan_filter_set(struct rte_eth_dev *eth_dev,
 	return err;
 }
 
-static void enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
+static int enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 {
 	struct enic *enic = pmd_priv(eth_dev);
 
@@ -371,6 +371,8 @@ static void enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 		dev_warning(enic,
 			"Configuration of extended VLAN is not supported\n");
 	}
+
+	return 0;
 }
 
 static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev)
@@ -392,9 +394,9 @@ static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev)
 			eth_dev->data->dev_conf.rxmode.split_hdr_size);
 	}
 
-	enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
+	ret = enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
 	enic->hw_ip_checksum = eth_dev->data->dev_conf.rxmode.hw_ip_checksum;
-	return 0;
+	return ret;
 }
 
 /* Start the device.
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index e60d3a3..f4626f7 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1590,7 +1590,7 @@ static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	return 0;
 }
 
-static void
+static int
 fm10k_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if (mask & ETH_VLAN_STRIP_MASK) {
@@ -1609,6 +1609,7 @@ static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		if (!dev->data->dev_conf.rxmode.hw_vlan_filter)
 			PMD_INIT_LOG(ERR, "VLAN filter is always on in fm10k");
 	}
+	return 0;
 }
 
 /* Add/Remove a MAC address, and update filters to main VSI */
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 00b6082..d03a44b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -278,7 +278,7 @@ static int i40e_vlan_filter_set(struct rte_eth_dev *dev,
 static int i40e_vlan_tpid_set(struct rte_eth_dev *dev,
 			      enum rte_vlan_type vlan_type,
 			      uint16_t tpid);
-static void i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void i40e_vlan_strip_queue_set(struct rte_eth_dev *dev,
 				      uint16_t queue,
 				      int on);
@@ -3130,7 +3130,7 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	return ret;
 }
 
-static void
+static int
 i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
@@ -3163,6 +3163,7 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		else
 			i40e_vsi_config_double_vlan(vsi, FALSE);
 	}
+	return 0;
 }
 
 static void
@@ -5216,7 +5217,11 @@ struct i40e_vsi *
 
 	/* Apply vlan offload setting */
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK;
-	i40e_vlan_offload_set(dev, mask);
+	ret = i40e_vlan_offload_set(dev, mask);
+	if (ret) {
+		PMD_DRV_LOG(INFO, "Failed to update vlan offload");
+		return ret;
+	}
 
 	/* Apply double-vlan setting, not implemented yet */
 
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index f6d8293..f7fffc2 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -118,7 +118,7 @@ static int i40evf_dev_xstats_get_names(struct rte_eth_dev *dev,
 static void i40evf_dev_xstats_reset(struct rte_eth_dev *dev);
 static int i40evf_vlan_filter_set(struct rte_eth_dev *dev,
 				  uint16_t vlan_id, int on);
-static void i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static int i40evf_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t pvid,
 				int on);
 static void i40evf_dev_close(struct rte_eth_dev *dev);
@@ -1634,7 +1634,9 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
 	int ret;
 
 	/* Apply vlan offload setting */
-	i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
+	ret = i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
+	if (ret)
+		return ret;
 
 	/* Apply pvid setting */
 	ret = i40evf_vlan_pvid_set(dev, data->dev_conf.txmode.pvid,
@@ -1642,7 +1644,7 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
 	return ret;
 }
 
-static void
+static int
 i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
@@ -1655,6 +1657,7 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
 		else
 			i40evf_disable_vlan_strip(dev);
 	}
+	return 0;
 }
 
 static int
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 22171d8..1ec5aaf 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -218,7 +218,7 @@ static void ixgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev,
 		uint16_t queue, bool on);
 static void ixgbe_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue,
 		int on);
-static void ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void ixgbe_vlan_hw_strip_enable(struct rte_eth_dev *dev, uint16_t queue);
 static void ixgbe_vlan_hw_strip_disable(struct rte_eth_dev *dev, uint16_t queue);
 static void ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev);
@@ -274,7 +274,7 @@ static int ixgbevf_vlan_filter_set(struct rte_eth_dev *dev,
 		uint16_t vlan_id, int on);
 static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev,
 		uint16_t queue, int on);
-static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on);
 static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
 					    uint16_t queue_id);
@@ -2125,7 +2125,7 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 	 */
 }
 
-static void
+static int
 ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	if (mask & ETH_VLAN_STRIP_MASK) {
@@ -2148,6 +2148,7 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 		else
 			ixgbe_vlan_hw_extend_disable(dev);
 	}
+	return 0;
 }
 
 static void
@@ -2568,9 +2569,13 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 		goto error;
 	}
 
-    mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
+	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
 		ETH_VLAN_EXTEND_MASK;
-	ixgbe_vlan_offload_set(dev, mask);
+	err = ixgbe_vlan_offload_set(dev, mask);
+	if (err) {
+		PMD_INIT_LOG(ERR, "Unable to set VLAN offload");
+		goto error;
+	}
 
 	if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) {
 		/* Enable vlan filtering for VMDq */
@@ -4993,7 +4998,12 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	/* Set HW strip */
 	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
 		ETH_VLAN_EXTEND_MASK;
-	ixgbevf_vlan_offload_set(dev, mask);
+	err = ixgbevf_vlan_offload_set(dev, mask);
+	if (err) {
+		PMD_INIT_LOG(ERR, "Unable to set VLAN offload (%d)", err);
+		ixgbe_dev_clear_queues(dev);
+		return err;
+	}
 
 	ixgbevf_dev_rxtx_start(dev);
 
@@ -5153,7 +5163,7 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
 	ixgbe_vlan_hw_strip_bitmap_set(dev, queue, on);
 }
 
-static void
+static int
 ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct ixgbe_hw *hw =
@@ -5168,6 +5178,7 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
 		for (i = 0; i < hw->mac.max_rx_queues; i++)
 			ixgbevf_vlan_strip_queue_set(dev, i, on);
 	}
+	return 0;
 }
 
 int
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 43c5384..93e71be 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -283,7 +283,7 @@ int mlx5_xstats_get_names(struct rte_eth_dev *,
 /* mlx5_vlan.c */
 
 int mlx5_vlan_filter_set(struct rte_eth_dev *, uint16_t, int);
-void mlx5_vlan_offload_set(struct rte_eth_dev *, int);
+int mlx5_vlan_offload_set(struct rte_eth_dev *, int);
 void mlx5_vlan_strip_queue_set(struct rte_eth_dev *, uint16_t, int);
 
 /* mlx5_trigger.c */
diff --git a/drivers/net/mlx5/mlx5_vlan.c b/drivers/net/mlx5/mlx5_vlan.c
index 1b0fa40..7215909 100644
--- a/drivers/net/mlx5/mlx5_vlan.c
+++ b/drivers/net/mlx5/mlx5_vlan.c
@@ -210,7 +210,7 @@
  * @param mask
  *   VLAN offload bit mask.
  */
-void
+int
 mlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct priv *priv = dev->data->dev_private;
@@ -230,4 +230,5 @@
 			priv_vlan_strip_queue_set(priv, i, hw_vlan_strip);
 		priv_unlock(priv);
 	}
+	return 0;
 }
diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index 92b03c4..6473edc 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -2149,11 +2149,12 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
 	return i;
 }
 
-static void
+static int
 nfp_net_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	uint32_t new_ctrl, update;
 	struct nfp_net_hw *hw;
+	int ret;
 
 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	new_ctrl = 0;
@@ -2174,14 +2175,14 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
 		new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_RXVLAN;
 
 	if (new_ctrl == 0)
-		return;
+		return 0;
 
 	update = NFP_NET_CFG_UPDATE_GEN;
 
-	if (nfp_net_reconfig(hw, new_ctrl, update) < 0)
-		return;
-
-	hw->ctrl = new_ctrl;
+	ret = nfp_net_reconfig(hw, new_ctrl, update);
+	if (!ret)
+		hw->ctrl = new_ctrl;
+	return ret;
 }
 
 /* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device */
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 0e05989..644f69d 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -975,7 +975,7 @@ static int qede_vlan_filter_set(struct rte_eth_dev *eth_dev,
 	return rc;
 }
 
-static void qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
+static int qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 {
 	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
 	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
@@ -1013,6 +1013,8 @@ static void qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 
 	DP_INFO(edev, "vlan offload mask %d vlan-strip %d vlan-filter %d\n",
 		mask, rxmode->hw_vlan_strip, rxmode->hw_vlan_filter);
+
+	return 0;
 }
 
 static void qede_prandom_bytes(uint32_t *buff)
@@ -1157,6 +1159,7 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
 	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
 	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
+	int ret;
 
 	PMD_INIT_FUNC_TRACE(edev);
 
@@ -1237,9 +1240,11 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
 	qdev->enable_lro = rxmode->enable_lro;
 
 	/* Enable VLAN offloads by default */
-	qede_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK  |
+	ret = qede_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK  |
 			ETH_VLAN_FILTER_MASK |
 			ETH_VLAN_EXTEND_MASK);
+	if (ret)
+		return ret;
 
 	DP_INFO(edev, "Device configured with RSS=%d TSS=%d\n",
 			QEDE_RSS_COUNT(qdev), QEDE_TSS_COUNT(qdev));
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index e320811..72b4248 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -72,6 +72,7 @@ static void virtio_dev_info_get(struct rte_eth_dev *dev,
 				struct rte_eth_dev_info *dev_info);
 static int virtio_dev_link_update(struct rte_eth_dev *dev,
 	int wait_to_complete);
+static int virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 
 static void virtio_set_hwaddr(struct virtio_hw *hw);
 static void virtio_get_hwaddr(struct virtio_hw *hw);
@@ -779,6 +780,7 @@ struct rte_virtio_xstats_name_off {
 	.stats_reset             = virtio_dev_stats_reset,
 	.xstats_reset            = virtio_dev_stats_reset,
 	.link_update             = virtio_dev_link_update,
+	.vlan_offload_set        = virtio_dev_vlan_offload_set,
 	.rx_queue_setup          = virtio_dev_rx_queue_setup,
 	.rx_queue_intr_enable    = virtio_dev_rx_queue_intr_enable,
 	.rx_queue_intr_disable   = virtio_dev_rx_queue_intr_disable,
@@ -1875,6 +1877,25 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev)
 	return (old.link_status == link.link_status) ? -1 : 0;
 }
 
+static int
+virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
+{
+	const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
+	struct virtio_hw *hw = dev->data->dev_private;
+
+	if (rxmode->hw_vlan_filter &&
+	    !vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) {
+		PMD_DRV_LOG(NOTICE,
+			    "vlan filtering not available on this host");
+		return -ENOTSUP;
+	}
+
+	if (mask & ETH_VLAN_STRIP_MASK)
+		hw->vlan_strip = rxmode->hw_vlan_strip;
+
+	return 0;
+}
+
 static void
 virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 3910991..06735dd 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -100,7 +100,7 @@ static void vmxnet3_dev_info_get(struct rte_eth_dev *dev,
 vmxnet3_dev_supported_ptypes_get(struct rte_eth_dev *dev);
 static int vmxnet3_dev_vlan_filter_set(struct rte_eth_dev *dev,
 				       uint16_t vid, int on);
-static void vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void vmxnet3_mac_addr_set(struct rte_eth_dev *dev,
 				 struct ether_addr *mac_addr);
 static void vmxnet3_interrupt_handler(void *param);
@@ -730,8 +730,10 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
 		devRead->rssConfDesc.confPA  = hw->rss_confPA;
 	}
 
-	vmxnet3_dev_vlan_offload_set(dev,
+	ret = vmxnet3_dev_vlan_offload_set(dev,
 				     ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK);
+	if (ret)
+		return ret;
 
 	vmxnet3_write_mac(hw, dev->data->mac_addrs->addr_bytes);
 
@@ -1275,7 +1277,7 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
 	return 0;
 }
 
-static void
+static int
 vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct vmxnet3_hw *hw = dev->data->dev_private;
@@ -1301,6 +1303,8 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
 		VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
 				       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
 	}
+
+	return 0;
 }
 
 static void
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 0597641..05e52b8 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2048,29 +2048,35 @@ struct rte_eth_dev *
 	struct rte_eth_dev *dev;
 	int ret = 0;
 	int mask = 0;
-	int cur, org = 0;
+	int cur, orig = 0;
+	uint8_t orig_strip, orig_filter, orig_extend;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
 	dev = &rte_eth_devices[port_id];
 
+	/* save original values in case of failure */
+	orig_strip = dev->data->dev_conf.rxmode.hw_vlan_strip;
+	orig_filter = dev->data->dev_conf.rxmode.hw_vlan_filter;
+	orig_extend = dev->data->dev_conf.rxmode.hw_vlan_extend;
+
 	/*check which option changed by application*/
 	cur = !!(offload_mask & ETH_VLAN_STRIP_OFFLOAD);
-	org = !!(dev->data->dev_conf.rxmode.hw_vlan_strip);
-	if (cur != org) {
+	orig = !!(dev->data->dev_conf.rxmode.hw_vlan_strip);
+	if (cur != orig) {
 		dev->data->dev_conf.rxmode.hw_vlan_strip = (uint8_t)cur;
 		mask |= ETH_VLAN_STRIP_MASK;
 	}
 
 	cur = !!(offload_mask & ETH_VLAN_FILTER_OFFLOAD);
-	org = !!(dev->data->dev_conf.rxmode.hw_vlan_filter);
-	if (cur != org) {
+	orig = !!(dev->data->dev_conf.rxmode.hw_vlan_filter);
+	if (cur != orig) {
 		dev->data->dev_conf.rxmode.hw_vlan_filter = (uint8_t)cur;
 		mask |= ETH_VLAN_FILTER_MASK;
 	}
 
 	cur = !!(offload_mask & ETH_VLAN_EXTEND_OFFLOAD);
-	org = !!(dev->data->dev_conf.rxmode.hw_vlan_extend);
-	if (cur != org) {
+	orig = !!(dev->data->dev_conf.rxmode.hw_vlan_extend);
+	if (cur != orig) {
 		dev->data->dev_conf.rxmode.hw_vlan_extend = (uint8_t)cur;
 		mask |= ETH_VLAN_EXTEND_MASK;
 	}
@@ -2080,7 +2086,13 @@ struct rte_eth_dev *
 		return ret;
 
 	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_offload_set, -ENOTSUP);
-	(*dev->dev_ops->vlan_offload_set)(dev, mask);
+	ret = (*dev->dev_ops->vlan_offload_set)(dev, mask);
+	if (ret) {
+		/* hit an error restore  original values */
+		dev->data->dev_conf.rxmode.hw_vlan_strip = orig_strip;
+		dev->data->dev_conf.rxmode.hw_vlan_filter = orig_filter;
+		dev->data->dev_conf.rxmode.hw_vlan_extend = orig_extend;
+	}
 
 	return ret;
 }
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 0adf327..7254fd0 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1245,7 +1245,7 @@ typedef int (*vlan_tpid_set_t)(struct rte_eth_dev *dev,
 			       enum rte_vlan_type type, uint16_t tpid);
 /**< @internal set the outer/inner VLAN-TPID by an Ethernet device. */
 
-typedef void (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask);
+typedef int (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask);
 /**< @internal set VLAN offload function by an Ethernet device. */
 
 typedef int (*vlan_pvid_set_t)(struct rte_eth_dev *dev,
-- 
1.8.3.1

^ permalink raw reply	[relevance 7%]

* Re: [dpdk-dev] [PATCH v4] ethdev: allow returning error on VLAN offload configuration
  2017-09-01  2:36  7%     ` [dpdk-dev] [PATCH v4] ethdev: allow returning error on VLAN offload configuration David Harton
@ 2017-09-01  7:41  0%       ` Hemant Agrawal
  2017-09-01 12:54  0%         ` David Harton (dharton)
  0 siblings, 1 reply; 200+ results
From: Hemant Agrawal @ 2017-09-01  7:41 UTC (permalink / raw)
  To: David Harton, thomas, ferruh.yigit, ajit.khaparde, johndale,
	konstantin.ananyev, jingjing.wu, beilei.xing, jing.d.chen,
	adrien.mazarguil, nelio.laranjeiro, alejandro.lucero,
	rasesh.mody, harish.patil, skhare, yliu, maxime.coquelin,
	allain.legacy
  Cc: dev

On 9/1/2017 8:06 AM, David Harton wrote:
> Some devices may not support or fail setting VLAN offload
> configuration based on dynamic circurmstances so the
> vlan_offload_set_t vector is modified to return an int so
> the caller can determine success or not.
>
> rte_eth_dev_set_vlan_offload is updated to return the
> value provided by the vector when called along with restoring
> the original offload configs on failure.
>
> Existing vlan_offload_set_t vectors are modified to return
> an int.  Majority of cases return 0 but a few that actually
> can fail now return their failure codes.
>
> Finally, a vlan_offload_set_t vector is added to virtio
> to facilitate dynamically turning VLAN strip on or off.
>
> Signed-off-by: David Harton <dharton@cisco.com>
> ---
>
> v4
> * Modified commit message heading
> * Moved rel_note comments from ABI to API section
> * Renamed locals of rte_eth_dev_set_vlan_offload from 'org*' to 'orig*'
>
> v3
> * Fixed a format error.
> * Apologies...need to figure out why checkpatches.pl keeps saying
>   valid patch when I've got soft tabs.
>
> v2
> * Fixed a missed format error.
> * Removed vlan offload vector call casts and replaced with checks
>   for return values.
>
> v1
> * This is an ABI breakage that has been previously negotiated
>   with Thomas and the proposed rel note change is included as well.
>
>  doc/guides/rel_notes/release_17_11.rst |  8 +++++++-
>  drivers/net/avp/avp_ethdev.c           | 12 +++++++++---
>  drivers/net/bnxt/bnxt_ethdev.c         |  9 ++++++---
>  drivers/net/dpaa2/dpaa2_ethdev.c       | 13 ++++++++++---
>  drivers/net/e1000/em_ethdev.c          | 12 +++++++++---
>  drivers/net/e1000/igb_ethdev.c         | 12 +++++++++---
>  drivers/net/enic/enic_ethdev.c         |  8 +++++---
>  drivers/net/fm10k/fm10k_ethdev.c       |  3 ++-
>  drivers/net/i40e/i40e_ethdev.c         | 11 ++++++++---
>  drivers/net/i40e/i40e_ethdev_vf.c      |  9 ++++++---
>  drivers/net/ixgbe/ixgbe_ethdev.c       | 25 ++++++++++++++++++-------
>  drivers/net/mlx5/mlx5.h                |  2 +-
>  drivers/net/mlx5/mlx5_vlan.c           |  3 ++-
>  drivers/net/nfp/nfp_net.c              | 13 +++++++------
>  drivers/net/qede/qede_ethdev.c         |  9 +++++++--
>  drivers/net/virtio/virtio_ethdev.c     | 21 +++++++++++++++++++++
>  drivers/net/vmxnet3/vmxnet3_ethdev.c   | 10 +++++++---
>  lib/librte_ether/rte_ethdev.c          | 28 ++++++++++++++++++++--------
>  lib/librte_ether/rte_ethdev.h          |  2 +-
>  19 files changed, 155 insertions(+), 55 deletions(-)
>
> diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
> index 170f4f9..22df4fd 100644
> --- a/doc/guides/rel_notes/release_17_11.rst
> +++ b/doc/guides/rel_notes/release_17_11.rst
> @@ -110,6 +110,13 @@ API Changes
>     Also, make sure to start the actual text at the margin.
>     =========================================================
>
> +* **Modified the vlan_offload_set_t function prototype in the ethdev library.**
> +
> +  Changed the function prototype of ``vlan_offload_set_t``.  The return value
> +  has been changed from ``void`` to ``int`` so the caller to knows whether
> +  the backing device supports the operation or if the operation was
> +  successfully performed.
> +
>
>  ABI Changes
>  -----------
> @@ -125,7 +132,6 @@ ABI Changes
>     =========================================================
>
>
> -
>  Shared Library Versions
>  -----------------------
>
> diff --git a/drivers/net/avp/avp_ethdev.c b/drivers/net/avp/avp_ethdev.c
> index c746a0e..4011dfa 100644
> --- a/drivers/net/avp/avp_ethdev.c
> +++ b/drivers/net/avp/avp_ethdev.c
> @@ -70,7 +70,7 @@ static int avp_dev_create(struct rte_pci_device *pci_dev,
>  static void avp_dev_close(struct rte_eth_dev *dev);
>  static void avp_dev_info_get(struct rte_eth_dev *dev,
>  			     struct rte_eth_dev_info *dev_info);
> -static void avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> +static int avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
>  static int avp_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete);
>  static void avp_dev_promiscuous_enable(struct rte_eth_dev *dev);
>  static void avp_dev_promiscuous_disable(struct rte_eth_dev *dev);
> @@ -2031,7 +2031,12 @@ struct avp_queue {
>  	mask = (ETH_VLAN_STRIP_MASK |
>  		ETH_VLAN_FILTER_MASK |
>  		ETH_VLAN_EXTEND_MASK);
> -	avp_vlan_offload_set(eth_dev, mask);
> +	ret = avp_vlan_offload_set(eth_dev, mask);
> +	if (ret < 0) {
> +		PMD_DRV_LOG(ERR, "VLAN offload set failed by host, ret=%d\n",
> +			    ret);
> +		goto unlock;
> +	}
>
>  	/* update device config */
>  	memset(&config, 0, sizeof(config));
> @@ -2214,7 +2219,7 @@ struct avp_queue {
>  	}
>  }
>
> -static void
> +static int
>  avp_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
>  {
>  	struct avp_dev *avp = AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
> @@ -2239,6 +2244,7 @@ struct avp_queue {
>  		if (eth_dev->data->dev_conf.rxmode.hw_vlan_extend)
>  			PMD_DRV_LOG(ERR, "VLAN extend offload not supported\n");
>  	}
> +	return 0;
>  }
>
>  static void
> diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
> index c9d1122..547bd55 100644
> --- a/drivers/net/bnxt/bnxt_ethdev.c
> +++ b/drivers/net/bnxt/bnxt_ethdev.c
> @@ -144,7 +144,7 @@
>  	ETH_RSS_NONFRAG_IPV6_TCP |	\
>  	ETH_RSS_NONFRAG_IPV6_UDP)
>
> -static void bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask);
> +static int bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask);
>
>  /***********************/
>
> @@ -522,7 +522,9 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
>  		vlan_mask |= ETH_VLAN_FILTER_MASK;
>  	if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip)
>  		vlan_mask |= ETH_VLAN_STRIP_MASK;
> -	bnxt_vlan_offload_set_op(eth_dev, vlan_mask);
> +	rc = bnxt_vlan_offload_set_op(eth_dev, vlan_mask);
> +	if (rc)
> +		goto error;
>
>  	return 0;
>
> @@ -1275,7 +1277,7 @@ static int bnxt_vlan_filter_set_op(struct rte_eth_dev *eth_dev,
>  		return bnxt_del_vlan_filter(bp, vlan_id);
>  }
>
> -static void
> +static int
>  bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask)
>  {
>  	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
> @@ -1307,6 +1309,7 @@ static int bnxt_vlan_filter_set_op(struct rte_eth_dev *eth_dev,
>
>  	if (mask & ETH_VLAN_EXTEND_MASK)
>  		RTE_LOG(ERR, PMD, "Extend VLAN Not supported\n");
> +	return 0;
>  }
>
>  static void
> diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
> index 429b3a0..3390cb3 100644
> --- a/drivers/net/dpaa2/dpaa2_ethdev.c
> +++ b/drivers/net/dpaa2/dpaa2_ethdev.c
> @@ -138,7 +138,7 @@
>  	return ret;
>  }
>
> -static void
> +static int
>  dpaa2_vlan_offload_set(struct rte_eth_dev *dev, int mask)
>  {
>  	struct dpaa2_dev_priv *priv = dev->data->dev_private;
> @@ -158,6 +158,7 @@
>  			RTE_LOG(ERR, PMD, "Unable to set vlan filter = %d\n",
>  				ret);
>  	}
> +	return 0;
>  }
>
>  static int
> @@ -643,8 +644,14 @@
>  		return ret;
>  	}
>  	/* VLAN Offload Settings */
> -	if (priv->max_vlan_filters)
> -		dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
> +	if (priv->max_vlan_filters) {
> +		ret = dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
> +		if (ret) {
> +			PMD_INIT_LOG(ERR, "Error to dpaa2_vlan_offload_set:"
> +				     "code = %d\n", ret);
> +			return ret;
> +		}
> +	}
>
>  	return 0;
>  }
> diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
> index 3d4ab93..51f49d8 100644
> --- a/drivers/net/e1000/em_ethdev.c
> +++ b/drivers/net/e1000/em_ethdev.c
> @@ -99,7 +99,7 @@ static int eth_em_interrupt_action(struct rte_eth_dev *dev,
>
>  static int eth_em_vlan_filter_set(struct rte_eth_dev *dev,
>  		uint16_t vlan_id, int on);
> -static void eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> +static int eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask);
>  static void em_vlan_hw_filter_enable(struct rte_eth_dev *dev);
>  static void em_vlan_hw_filter_disable(struct rte_eth_dev *dev);
>  static void em_vlan_hw_strip_enable(struct rte_eth_dev *dev);
> @@ -668,7 +668,12 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
>
>  	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
>  			ETH_VLAN_EXTEND_MASK;
> -	eth_em_vlan_offload_set(dev, mask);
> +	ret = eth_em_vlan_offload_set(dev, mask);
> +	if (ret) {
> +		PMD_INIT_LOG(ERR, "Unable to update vlan offload");
> +		em_dev_clear_queues(dev);
> +		return ret;
> +	}
>
>  	/* Set Interrupt Throttling Rate to maximum allowed value. */
>  	E1000_WRITE_REG(hw, E1000_ITR, UINT16_MAX);
> @@ -1447,7 +1452,7 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
>  	E1000_WRITE_REG(hw, E1000_CTRL, reg);
>  }
>
> -static void
> +static int
>  eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask)
>  {
>  	if(mask & ETH_VLAN_STRIP_MASK){
> @@ -1463,6 +1468,7 @@ static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
>  		else
>  			em_vlan_hw_filter_disable(dev);
>  	}
> +	return 0;
>  }
>
>  /*
> diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
> index e4f7a9f..fa15ee9 100644
> --- a/drivers/net/e1000/igb_ethdev.c
> +++ b/drivers/net/e1000/igb_ethdev.c
> @@ -157,7 +157,7 @@ static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev,
>  static int eth_igb_vlan_tpid_set(struct rte_eth_dev *dev,
>  				 enum rte_vlan_type vlan_type,
>  				 uint16_t tpid_id);
> -static void eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> +static int eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask);
>
>  static void igb_vlan_hw_filter_enable(struct rte_eth_dev *dev);
>  static void igb_vlan_hw_filter_disable(struct rte_eth_dev *dev);
> @@ -1400,7 +1400,12 @@ static int eth_igbvf_pci_remove(struct rte_pci_device *pci_dev)
>  	 */
>  	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
>  			ETH_VLAN_EXTEND_MASK;
> -	eth_igb_vlan_offload_set(dev, mask);
> +	ret = eth_igb_vlan_offload_set(dev, mask);
> +	if (ret) {
> +		PMD_INIT_LOG(ERR, "Unable to set vlan offload");
> +		igb_dev_clear_queues(dev);
> +		return ret;
> +	}
>
>  	if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) {
>  		/* Enable VLAN filter since VMDq always use VLAN filter */
> @@ -2715,7 +2720,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
>  						2 * VLAN_TAG_SIZE);
>  }
>
> -static void
> +static int
>  eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask)
>  {
>  	if(mask & ETH_VLAN_STRIP_MASK){
> @@ -2738,6 +2743,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
>  		else
>  			igb_vlan_hw_extend_disable(dev);
>  	}
> +	return 0;
>  }
>
>
> diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
> index da8fec2..fc1eac2 100644
> --- a/drivers/net/enic/enic_ethdev.c
> +++ b/drivers/net/enic/enic_ethdev.c
> @@ -347,7 +347,7 @@ static int enicpmd_vlan_filter_set(struct rte_eth_dev *eth_dev,
>  	return err;
>  }
>
> -static void enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
> +static int enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
>  {
>  	struct enic *enic = pmd_priv(eth_dev);
>
> @@ -371,6 +371,8 @@ static void enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
>  		dev_warning(enic,
>  			"Configuration of extended VLAN is not supported\n");
>  	}
> +
> +	return 0;
>  }
>
>  static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev)
> @@ -392,9 +394,9 @@ static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev)
>  			eth_dev->data->dev_conf.rxmode.split_hdr_size);
>  	}
>
> -	enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
> +	ret = enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
>  	enic->hw_ip_checksum = eth_dev->data->dev_conf.rxmode.hw_ip_checksum;
> -	return 0;
> +	return ret;
>  }
>
>  /* Start the device.
> diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
> index e60d3a3..f4626f7 100644
> --- a/drivers/net/fm10k/fm10k_ethdev.c
> +++ b/drivers/net/fm10k/fm10k_ethdev.c
> @@ -1590,7 +1590,7 @@ static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
>  	return 0;
>  }
>
> -static void
> +static int
>  fm10k_vlan_offload_set(struct rte_eth_dev *dev, int mask)
>  {
>  	if (mask & ETH_VLAN_STRIP_MASK) {
> @@ -1609,6 +1609,7 @@ static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
>  		if (!dev->data->dev_conf.rxmode.hw_vlan_filter)
>  			PMD_INIT_LOG(ERR, "VLAN filter is always on in fm10k");
>  	}
> +	return 0;
>  }
>
>  /* Add/Remove a MAC address, and update filters to main VSI */
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index 00b6082..d03a44b 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -278,7 +278,7 @@ static int i40e_vlan_filter_set(struct rte_eth_dev *dev,
>  static int i40e_vlan_tpid_set(struct rte_eth_dev *dev,
>  			      enum rte_vlan_type vlan_type,
>  			      uint16_t tpid);
> -static void i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> +static int i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
>  static void i40e_vlan_strip_queue_set(struct rte_eth_dev *dev,
>  				      uint16_t queue,
>  				      int on);
> @@ -3130,7 +3130,7 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
>  	return ret;
>  }
>
> -static void
> +static int
>  i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask)
>  {
>  	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> @@ -3163,6 +3163,7 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
>  		else
>  			i40e_vsi_config_double_vlan(vsi, FALSE);
>  	}
> +	return 0;
>  }
>
>  static void
> @@ -5216,7 +5217,11 @@ struct i40e_vsi *
>
>  	/* Apply vlan offload setting */
>  	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK;
> -	i40e_vlan_offload_set(dev, mask);
> +	ret = i40e_vlan_offload_set(dev, mask);
> +	if (ret) {
> +		PMD_DRV_LOG(INFO, "Failed to update vlan offload");
> +		return ret;
> +	}
>
>  	/* Apply double-vlan setting, not implemented yet */
>
> diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
> index f6d8293..f7fffc2 100644
> --- a/drivers/net/i40e/i40e_ethdev_vf.c
> +++ b/drivers/net/i40e/i40e_ethdev_vf.c
> @@ -118,7 +118,7 @@ static int i40evf_dev_xstats_get_names(struct rte_eth_dev *dev,
>  static void i40evf_dev_xstats_reset(struct rte_eth_dev *dev);
>  static int i40evf_vlan_filter_set(struct rte_eth_dev *dev,
>  				  uint16_t vlan_id, int on);
> -static void i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> +static int i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
>  static int i40evf_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t pvid,
>  				int on);
>  static void i40evf_dev_close(struct rte_eth_dev *dev);
> @@ -1634,7 +1634,9 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
>  	int ret;
>
>  	/* Apply vlan offload setting */
> -	i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
> +	ret = i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
> +	if (ret)
> +		return ret;
>
>  	/* Apply pvid setting */
>  	ret = i40evf_vlan_pvid_set(dev, data->dev_conf.txmode.pvid,
> @@ -1642,7 +1644,7 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
>  	return ret;
>  }
>
> -static void
> +static int
>  i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
>  {
>  	struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
> @@ -1655,6 +1657,7 @@ static int eth_i40evf_pci_remove(struct rte_pci_device *pci_dev)
>  		else
>  			i40evf_disable_vlan_strip(dev);
>  	}
> +	return 0;
>  }
>
>  static int
> diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
> index 22171d8..1ec5aaf 100644
> --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> @@ -218,7 +218,7 @@ static void ixgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev,
>  		uint16_t queue, bool on);
>  static void ixgbe_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue,
>  		int on);
> -static void ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> +static int ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask);
>  static void ixgbe_vlan_hw_strip_enable(struct rte_eth_dev *dev, uint16_t queue);
>  static void ixgbe_vlan_hw_strip_disable(struct rte_eth_dev *dev, uint16_t queue);
>  static void ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev);
> @@ -274,7 +274,7 @@ static int ixgbevf_vlan_filter_set(struct rte_eth_dev *dev,
>  		uint16_t vlan_id, int on);
>  static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev,
>  		uint16_t queue, int on);
> -static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> +static int ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
>  static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on);
>  static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
>  					    uint16_t queue_id);
> @@ -2125,7 +2125,7 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
>  	 */
>  }
>
> -static void
> +static int
>  ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask)
>  {
>  	if (mask & ETH_VLAN_STRIP_MASK) {
> @@ -2148,6 +2148,7 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
>  		else
>  			ixgbe_vlan_hw_extend_disable(dev);
>  	}
> +	return 0;
>  }
>
>  static void
> @@ -2568,9 +2569,13 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
>  		goto error;
>  	}
>
> -    mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
> +	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
>  		ETH_VLAN_EXTEND_MASK;
> -	ixgbe_vlan_offload_set(dev, mask);
> +	err = ixgbe_vlan_offload_set(dev, mask);
> +	if (err) {
> +		PMD_INIT_LOG(ERR, "Unable to set VLAN offload");
> +		goto error;
> +	}
>
>  	if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) {
>  		/* Enable vlan filtering for VMDq */
> @@ -4993,7 +4998,12 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
>  	/* Set HW strip */
>  	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
>  		ETH_VLAN_EXTEND_MASK;
> -	ixgbevf_vlan_offload_set(dev, mask);
> +	err = ixgbevf_vlan_offload_set(dev, mask);
> +	if (err) {
> +		PMD_INIT_LOG(ERR, "Unable to set VLAN offload (%d)", err);
> +		ixgbe_dev_clear_queues(dev);
> +		return err;
> +	}
>
>  	ixgbevf_dev_rxtx_start(dev);
>
> @@ -5153,7 +5163,7 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
>  	ixgbe_vlan_hw_strip_bitmap_set(dev, queue, on);
>  }
>
> -static void
> +static int
>  ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
>  {
>  	struct ixgbe_hw *hw =
> @@ -5168,6 +5178,7 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
>  		for (i = 0; i < hw->mac.max_rx_queues; i++)
>  			ixgbevf_vlan_strip_queue_set(dev, i, on);
>  	}
> +	return 0;
>  }
>
>  int
> diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
> index 43c5384..93e71be 100644
> --- a/drivers/net/mlx5/mlx5.h
> +++ b/drivers/net/mlx5/mlx5.h
> @@ -283,7 +283,7 @@ int mlx5_xstats_get_names(struct rte_eth_dev *,
>  /* mlx5_vlan.c */
>
>  int mlx5_vlan_filter_set(struct rte_eth_dev *, uint16_t, int);
> -void mlx5_vlan_offload_set(struct rte_eth_dev *, int);
> +int mlx5_vlan_offload_set(struct rte_eth_dev *, int);
>  void mlx5_vlan_strip_queue_set(struct rte_eth_dev *, uint16_t, int);
>
>  /* mlx5_trigger.c */
> diff --git a/drivers/net/mlx5/mlx5_vlan.c b/drivers/net/mlx5/mlx5_vlan.c
> index 1b0fa40..7215909 100644
> --- a/drivers/net/mlx5/mlx5_vlan.c
> +++ b/drivers/net/mlx5/mlx5_vlan.c
> @@ -210,7 +210,7 @@
>   * @param mask
>   *   VLAN offload bit mask.
>   */
> -void
> +int
>  mlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask)
>  {
>  	struct priv *priv = dev->data->dev_private;
> @@ -230,4 +230,5 @@
>  			priv_vlan_strip_queue_set(priv, i, hw_vlan_strip);
>  		priv_unlock(priv);
>  	}
> +	return 0;
>  }
> diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
> index 92b03c4..6473edc 100644
> --- a/drivers/net/nfp/nfp_net.c
> +++ b/drivers/net/nfp/nfp_net.c
> @@ -2149,11 +2149,12 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
>  	return i;
>  }
>
> -static void
> +static int
>  nfp_net_vlan_offload_set(struct rte_eth_dev *dev, int mask)
>  {
>  	uint32_t new_ctrl, update;
>  	struct nfp_net_hw *hw;
> +	int ret;
>
>  	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
>  	new_ctrl = 0;
> @@ -2174,14 +2175,14 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
>  		new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_RXVLAN;
>
>  	if (new_ctrl == 0)
> -		return;
> +		return 0;
>
>  	update = NFP_NET_CFG_UPDATE_GEN;
>
> -	if (nfp_net_reconfig(hw, new_ctrl, update) < 0)
> -		return;
> -
> -	hw->ctrl = new_ctrl;
> +	ret = nfp_net_reconfig(hw, new_ctrl, update);
> +	if (!ret)
> +		hw->ctrl = new_ctrl;
> +	return ret;
>  }
>
>  /* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device */
> diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
> index 0e05989..644f69d 100644
> --- a/drivers/net/qede/qede_ethdev.c
> +++ b/drivers/net/qede/qede_ethdev.c
> @@ -975,7 +975,7 @@ static int qede_vlan_filter_set(struct rte_eth_dev *eth_dev,
>  	return rc;
>  }
>
> -static void qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
> +static int qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
>  {
>  	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
>  	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
> @@ -1013,6 +1013,8 @@ static void qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
>
>  	DP_INFO(edev, "vlan offload mask %d vlan-strip %d vlan-filter %d\n",
>  		mask, rxmode->hw_vlan_strip, rxmode->hw_vlan_filter);
> +
> +	return 0;
>  }
>
>  static void qede_prandom_bytes(uint32_t *buff)
> @@ -1157,6 +1159,7 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
>  	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
>  	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
>  	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
> +	int ret;
>
>  	PMD_INIT_FUNC_TRACE(edev);
>
> @@ -1237,9 +1240,11 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
>  	qdev->enable_lro = rxmode->enable_lro;
>
>  	/* Enable VLAN offloads by default */
> -	qede_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK  |
> +	ret = qede_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK  |
>  			ETH_VLAN_FILTER_MASK |
>  			ETH_VLAN_EXTEND_MASK);
> +	if (ret)
> +		return ret;
>
>  	DP_INFO(edev, "Device configured with RSS=%d TSS=%d\n",
>  			QEDE_RSS_COUNT(qdev), QEDE_TSS_COUNT(qdev));
> diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
> index e320811..72b4248 100644
> --- a/drivers/net/virtio/virtio_ethdev.c
> +++ b/drivers/net/virtio/virtio_ethdev.c
> @@ -72,6 +72,7 @@ static void virtio_dev_info_get(struct rte_eth_dev *dev,
>  				struct rte_eth_dev_info *dev_info);
>  static int virtio_dev_link_update(struct rte_eth_dev *dev,
>  	int wait_to_complete);
> +static int virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
>
>  static void virtio_set_hwaddr(struct virtio_hw *hw);
>  static void virtio_get_hwaddr(struct virtio_hw *hw);
> @@ -779,6 +780,7 @@ struct rte_virtio_xstats_name_off {
>  	.stats_reset             = virtio_dev_stats_reset,
>  	.xstats_reset            = virtio_dev_stats_reset,
>  	.link_update             = virtio_dev_link_update,
> +	.vlan_offload_set        = virtio_dev_vlan_offload_set,
>  	.rx_queue_setup          = virtio_dev_rx_queue_setup,
>  	.rx_queue_intr_enable    = virtio_dev_rx_queue_intr_enable,
>  	.rx_queue_intr_disable   = virtio_dev_rx_queue_intr_disable,
> @@ -1875,6 +1877,25 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev)
>  	return (old.link_status == link.link_status) ? -1 : 0;
>  }
>
> +static int
> +virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
> +{
> +	const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
> +	struct virtio_hw *hw = dev->data->dev_private;
> +
> +	if (rxmode->hw_vlan_filter &&
> +	    !vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) {
> +		PMD_DRV_LOG(NOTICE,
> +			    "vlan filtering not available on this host");
> +		return -ENOTSUP;
> +	}
> +
> +	if (mask & ETH_VLAN_STRIP_MASK)
> +		hw->vlan_strip = rxmode->hw_vlan_strip;
> +
> +	return 0;
> +}
> +
>  static void
>  virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
>  {
> diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
> index 3910991..06735dd 100644
> --- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
> +++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
> @@ -100,7 +100,7 @@ static void vmxnet3_dev_info_get(struct rte_eth_dev *dev,
>  vmxnet3_dev_supported_ptypes_get(struct rte_eth_dev *dev);
>  static int vmxnet3_dev_vlan_filter_set(struct rte_eth_dev *dev,
>  				       uint16_t vid, int on);
> -static void vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> +static int vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
>  static void vmxnet3_mac_addr_set(struct rte_eth_dev *dev,
>  				 struct ether_addr *mac_addr);
>  static void vmxnet3_interrupt_handler(void *param);
> @@ -730,8 +730,10 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
>  		devRead->rssConfDesc.confPA  = hw->rss_confPA;
>  	}
>
> -	vmxnet3_dev_vlan_offload_set(dev,
> +	ret = vmxnet3_dev_vlan_offload_set(dev,
>  				     ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK);
> +	if (ret)
> +		return ret;
>
>  	vmxnet3_write_mac(hw, dev->data->mac_addrs->addr_bytes);
>
> @@ -1275,7 +1277,7 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
>  	return 0;
>  }
>
> -static void
> +static int
>  vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
>  {
>  	struct vmxnet3_hw *hw = dev->data->dev_private;
> @@ -1301,6 +1303,8 @@ static int eth_vmxnet3_pci_remove(struct rte_pci_device *pci_dev)
>  		VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
>  				       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
>  	}
> +
> +	return 0;
>  }
>
>  static void
> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
> index 0597641..05e52b8 100644
> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -2048,29 +2048,35 @@ struct rte_eth_dev *
>  	struct rte_eth_dev *dev;
>  	int ret = 0;
>  	int mask = 0;
> -	int cur, org = 0;
> +	int cur, orig = 0;
> +	uint8_t orig_strip, orig_filter, orig_extend;
>
>  	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
>  	dev = &rte_eth_devices[port_id];
>
> +	/* save original values in case of failure */
> +	orig_strip = dev->data->dev_conf.rxmode.hw_vlan_strip;
> +	orig_filter = dev->data->dev_conf.rxmode.hw_vlan_filter;
> +	orig_extend = dev->data->dev_conf.rxmode.hw_vlan_extend;
> +
>  	/*check which option changed by application*/
>  	cur = !!(offload_mask & ETH_VLAN_STRIP_OFFLOAD);
> -	org = !!(dev->data->dev_conf.rxmode.hw_vlan_strip);
> -	if (cur != org) {
> +	orig = !!(dev->data->dev_conf.rxmode.hw_vlan_strip);
> +	if (cur != orig) {
>  		dev->data->dev_conf.rxmode.hw_vlan_strip = (uint8_t)cur;
>  		mask |= ETH_VLAN_STRIP_MASK;
>  	}
>
>  	cur = !!(offload_mask & ETH_VLAN_FILTER_OFFLOAD);
> -	org = !!(dev->data->dev_conf.rxmode.hw_vlan_filter);
> -	if (cur != org) {
> +	orig = !!(dev->data->dev_conf.rxmode.hw_vlan_filter);
> +	if (cur != orig) {
>  		dev->data->dev_conf.rxmode.hw_vlan_filter = (uint8_t)cur;
>  		mask |= ETH_VLAN_FILTER_MASK;
>  	}
>
>  	cur = !!(offload_mask & ETH_VLAN_EXTEND_OFFLOAD);
> -	org = !!(dev->data->dev_conf.rxmode.hw_vlan_extend);
> -	if (cur != org) {
> +	orig = !!(dev->data->dev_conf.rxmode.hw_vlan_extend);
> +	if (cur != orig) {
>  		dev->data->dev_conf.rxmode.hw_vlan_extend = (uint8_t)cur;
>  		mask |= ETH_VLAN_EXTEND_MASK;
>  	}
> @@ -2080,7 +2086,13 @@ struct rte_eth_dev *
>  		return ret;
>
>  	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_offload_set, -ENOTSUP);
> -	(*dev->dev_ops->vlan_offload_set)(dev, mask);
> +	ret = (*dev->dev_ops->vlan_offload_set)(dev, mask);
> +	if (ret) {
> +		/* hit an error restore  original values */
> +		dev->data->dev_conf.rxmode.hw_vlan_strip = orig_strip;
> +		dev->data->dev_conf.rxmode.hw_vlan_filter = orig_filter;
> +		dev->data->dev_conf.rxmode.hw_vlan_extend = orig_extend;
> +	}
>
Currently vlan offload is combining three functions:
strip, filter and extend.

Not all PMDs in DPDK support all of three.
Should not the error we extended to reflect, which of the VLAN offload 
is not supported?

>  	return ret;
>  }
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index 0adf327..7254fd0 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -1245,7 +1245,7 @@ typedef int (*vlan_tpid_set_t)(struct rte_eth_dev *dev,
>  			       enum rte_vlan_type type, uint16_t tpid);
>  /**< @internal set the outer/inner VLAN-TPID by an Ethernet device. */
>
> -typedef void (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask);
> +typedef int (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask);
>  /**< @internal set VLAN offload function by an Ethernet device. */
>
>  typedef int (*vlan_pvid_set_t)(struct rte_eth_dev *dev,
>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v5] ethdev: add return code to rte_eth_stats_reset()
  2017-09-01  2:26  3%   ` [dpdk-dev] [PATCH v5] ethdev: add return code to rte_eth_stats_reset() David Harton
@ 2017-09-01  7:47  0%     ` Hemant Agrawal
  0 siblings, 0 replies; 200+ results
From: Hemant Agrawal @ 2017-09-01  7:47 UTC (permalink / raw)
  To: David Harton, thomas; +Cc: dev

On 9/1/2017 7:56 AM, David Harton wrote:
> Some devices do not support reset of eth stats.  An application may
> need to know not to clear shadow stats if the device cannot.
>
> rte_eth_stats_reset is updated to provide a return code to share
> whether the device supports reset or not.
>
> Signed-off-by: David Harton <dharton@cisco.com>
> ---
>
> v5:
> * squashed doc patch
> * moved rel_note change from ABI to API section
>
> v4:
> * commented return values
>
> v3:
> * overcame noob errors and figured out patch challenged
>
> v2:
> * fixed soft tab issue inserted while moving changes
>
>  doc/guides/rel_notes/release_17_11.rst | 13 +++++++++++++
>  lib/librte_ether/rte_ethdev.c          |  8 +++++---
>  lib/librte_ether/rte_ethdev.h          |  6 +++++-
>  3 files changed, 23 insertions(+), 4 deletions(-)
>
> diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
> index 22df4fd..6282667 100644
> --- a/doc/guides/rel_notes/release_17_11.rst
> +++ b/doc/guides/rel_notes/release_17_11.rst
> @@ -110,6 +110,19 @@ API Changes
>     Also, make sure to start the actual text at the margin.
>     =========================================================
>
> +* **Modified the return type of rte_eth_stats_reset.**
> +
> +  Changed return type of ``rte_eth_stats_reset`` from ``void`` to ``int``
> +  so the caller may know whether a device supports the operation or not
> +  and if the operation was carried out.
> +
> +* **Modified the vlan_offload_set_t function prototype in the ethdev library.**
> +
> +  Changed the function prototype of ``vlan_offload_set_t``.  The return value
> +  has been changed from ``void`` to ``int`` so the caller to knows whether
> +  the backing device supports the operation or if the operation was
> +  successfully performed.
> +
>  * **Modified the vlan_offload_set_t function prototype in the ethdev library.**
>
>    Changed the function prototype of ``vlan_offload_set_t``.  The return value
> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
> index 05e52b8..f0f1775 100644
> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -1341,17 +1341,19 @@ struct rte_eth_dev *
>  	return 0;
>  }
>
> -void
> +int
>  rte_eth_stats_reset(uint8_t port_id)
>  {
>  	struct rte_eth_dev *dev;
>
> -	RTE_ETH_VALID_PORTID_OR_RET(port_id);
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
>  	dev = &rte_eth_devices[port_id];
>
> -	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_reset, -ENOTSUP);
>  	(*dev->dev_ops->stats_reset)(dev);
>  	dev->data->rx_mbuf_alloc_failed = 0;
> +
> +	return 0;
>  }
>
>  static int
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index 7254fd0..9110725 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -2246,8 +2246,12 @@ int rte_eth_tx_queue_setup(uint8_t port_id, uint16_t tx_queue_id,
>   *
>   * @param port_id
>   *   The port identifier of the Ethernet device.
> + * @return
> + *   - (0) if device notified to reset stats.
> + *   - (-ENOTSUP) if hardware doesn't support.
> + *   - (-ENODEV) if *port_id* invalid.
>   */
> -void rte_eth_stats_reset(uint8_t port_id);
> +int rte_eth_stats_reset(uint8_t port_id);
>
>  /**
>   * Retrieve names of extended statistics of an Ethernet device.
>
Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3] ethdev: modifiy vlan_offload_set_t to return int
  2017-09-01  0:40  0%       ` David Harton (dharton)
@ 2017-09-01  8:01  0%         ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-09-01  8:01 UTC (permalink / raw)
  To: David Harton (dharton)
  Cc: dev, ferruh.yigit, ajit.khaparde, johndale, konstantin.ananyev,
	jingjing.wu, beilei.xing, jing.d.chen, adrien.mazarguil,
	nelio.laranjeiro, alejandro.lucero, hemant.agrawal, rasesh.mody,
	harish.patil, skhare, yliu, maxime.coquelin, allain.legacy

01/09/2017 02:40, David Harton (dharton):
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > > --- a/doc/guides/rel_notes/release_17_11.rst
> > > +++ b/doc/guides/rel_notes/release_17_11.rst
> > > @@ -124,7 +124,7 @@ ABI Changes
> > >     Also, make sure to start the actual text at the margin.
> > >     =========================================================
> > >
> > > -
> > > +* Changed return type of ``vlan_offload_set_t`` from ``void`` to ``int``.
> > 
> > It should be referenced as an API change (instead of ABI change).
> > (and line spacing must be kept)
> 
> Sure I'll move it to API.
> 
> Line spacing?  You mean 80 char width?  I followed an example from a previous
> release so I'm not sure what you mean.

I mean you must take care of the number of blank lines to have
before and after a title (2 blank lines before a title).

> > > -	(*dev->dev_ops->vlan_offload_set)(dev, mask);
> > > +	ret = (*dev->dev_ops->vlan_offload_set)(dev, mask);
> > > +	if (ret) {
> > > +		/* hit an error restore  original values */
> > > +		dev->data->dev_conf.rxmode.hw_vlan_strip = org_strip;
> > > +		dev->data->dev_conf.rxmode.hw_vlan_filter = org_filter;
> > > +		dev->data->dev_conf.rxmode.hw_vlan_extend = org_extend;
> > > +	}
> > 
> > Isn't it the responsibility of the PMD to restore values in case of error?
> > I understand it is there to factorize error handling code, right?
> 
> By setting the dev_conf.rxmode.hw_vlan_* fields this function is claiming 
> ownership of that data and therefore it should be the one to reset it.
> 
> > Do we want to document this behaviour with the ops prototype?
> 
> Why?  Shouldn't any function that doesn't do what it was asked to do 
> leave the system in its original state and in fact if it doesn't that 
> is when it should be documented what the behavior is?  Otherwise every 
> caller has to implement some cleanup code and would have to be given 
> information to know how to perform that cleanup as well which seems 
> more complicated.

Sorry I overlooked the function. I thought these data were set by the PMD,
that's why I was telling the cleanup should be done in the PMD.
You can forget this comment :)

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 2/3] ethdev: add new rte_mtr API for traffic metering and policing
  2017-08-26  0:06  2%   ` [dpdk-dev] [PATCH 2/3] ethdev: add new rte_mtr API for traffic " Cristian Dumitrescu
@ 2017-09-01  8:09  0%     ` Hemant Agrawal
  0 siblings, 0 replies; 200+ results
From: Hemant Agrawal @ 2017-09-01  8:09 UTC (permalink / raw)
  To: Cristian Dumitrescu, dev; +Cc: thomas, adrien.mazarguil, jerin.jacob

On 8/26/2017 5:36 AM, Cristian Dumitrescu wrote:
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> ---
> Changes in v1 (from RFC [1]):
> - Added EXPERIMENTAL tag in rte_mtr.h and MANTAINERS for this new API
>   (input from Thomas)
> - Added more Doxygen comments to re-inforce relationship between MTR and
>   flow (input from Adrien)
> - Added Doxygen hook in doxy-api-index.md
>
> [1] RFC: http://www.dpdk.org/ml/archives/dev/2017-May/066888.html
>
>  MAINTAINERS                            |   4 +
>  doc/api/doxy-api-index.md              |   1 +
>  lib/librte_ether/Makefile              |   5 +-
>  lib/librte_ether/rte_ether_version.map |  15 ++
>  lib/librte_ether/rte_mtr.c             | 184 +++++++++++++
>  lib/librte_ether/rte_mtr.h             | 471 +++++++++++++++++++++++++++++++++
>  lib/librte_ether/rte_mtr_driver.h      | 188 +++++++++++++
>  7 files changed, 867 insertions(+), 1 deletion(-)
>  create mode 100644 lib/librte_ether/rte_mtr.c
>  create mode 100644 lib/librte_ether/rte_mtr.h
>  create mode 100644 lib/librte_ether/rte_mtr_driver.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a0cd75e..5491906 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -257,6 +257,10 @@ M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
>  T: git://dpdk.org/next/dpdk-next-tm
>  F: lib/librte_ether/rte_tm*
>
> +Traffic Metering and Policing API - EXPERIMENTAL
> +M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> +F: lib/librte_ether/rte_mtr*
> +
>  Crypto API
>  M: Declan Doherty <declan.doherty@intel.com>
>  F: lib/librte_cryptodev/
> diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
> index 19e0d4f..b2342a9 100644
> --- a/doc/api/doxy-api-index.md
> +++ b/doc/api/doxy-api-index.md
> @@ -41,6 +41,7 @@ The public API headers are grouped by topics:
>    [ethctrl]            (@ref rte_eth_ctrl.h),
>    [rte_flow]           (@ref rte_flow.h),
>    [rte_tm]             (@ref rte_tm.h),
> +  [rte_mtr]            (@ref rte_mtr.h),
>    [cryptodev]          (@ref rte_cryptodev.h),
>    [eventdev]           (@ref rte_eventdev.h),
>    [metrics]            (@ref rte_metrics.h),
> diff --git a/lib/librte_ether/Makefile b/lib/librte_ether/Makefile
> index db692ae..e4e339d 100644
> --- a/lib/librte_ether/Makefile
> +++ b/lib/librte_ether/Makefile
> @@ -41,11 +41,12 @@ CFLAGS += $(WERROR_FLAGS)
>
>  EXPORT_MAP := rte_ether_version.map
>
> -LIBABIVER := 6
> +LIBABIVER := 7
>
>  SRCS-y += rte_ethdev.c
>  SRCS-y += rte_flow.c
>  SRCS-y += rte_tm.c
> +SRCS-y += rte_mtr.c
>
>  #
>  # Export include files
> @@ -59,5 +60,7 @@ SYMLINK-y-include += rte_flow.h
>  SYMLINK-y-include += rte_flow_driver.h
>  SYMLINK-y-include += rte_tm.h
>  SYMLINK-y-include += rte_tm_driver.h
> +SYMLINK-y-include += rte_mtr.h
> +SYMLINK-y-include += rte_mtr_driver.h
>
>  include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
> index 4283728..7192664 100644
> --- a/lib/librte_ether/rte_ether_version.map
> +++ b/lib/librte_ether/rte_ether_version.map
> @@ -187,3 +187,18 @@ DPDK_17.08 {
>  	rte_tm_wred_profile_delete;
>
>  } DPDK_17.05;
> +
> +DPDK_17.11 {
> +	global:
> +
> +	rte_eth_dev_mtr_ops_get;
> +	rte_mtr_meter_profile_add;
> +	rte_mtr_meter_profile_delete;
> +	rte_mtr_create;
> +	rte_mtr_destroy;
> +	rte_mtr_meter_profile_update;
> +	rte_mtr_policer_action_update;
> +	rte_mtr_stats_update;
> +	rte_mtr_stats_read;
> +
> +} DPDK_17.08;
> diff --git a/lib/librte_ether/rte_mtr.c b/lib/librte_ether/rte_mtr.c
> new file mode 100644
> index 0000000..efbe7fb
> --- /dev/null
> +++ b/lib/librte_ether/rte_mtr.c
> @@ -0,0 +1,184 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2017 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 <stdint.h>
> +
> +#include <rte_errno.h>
> +#include "rte_ethdev.h"
> +#include "rte_mtr_driver.h"
> +#include "rte_mtr.h"
> +
> +/* Get generic traffic metering and policing operations structure from a port. */
> +const struct rte_mtr_ops *
> +rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	const struct rte_mtr_ops *ops;
> +
> +	if (!rte_eth_dev_is_valid_port(port_id)) {
> +		rte_mtr_error_set(error,
> +			ENODEV,
> +			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
> +			NULL,
> +			rte_strerror(ENODEV));
> +		return NULL;
> +	}
> +
> +	if ((dev->dev_ops->mtr_ops_get == NULL) ||
> +		(dev->dev_ops->mtr_ops_get(dev, &ops) != 0) ||
> +		(ops == NULL)) {
> +		rte_mtr_error_set(error,
> +			ENOSYS,
> +			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
> +			NULL,
> +			rte_strerror(ENOSYS));
> +		return NULL;
> +	}
> +
> +	return ops;
> +}
> +
> +#define RTE_MTR_FUNC(port_id, func)			\
> +({							\
> +	const struct rte_mtr_ops *ops =			\
> +		rte_mtr_ops_get(port_id, error);		\
> +	if (ops == NULL)					\
> +		return -rte_errno;			\
> +							\
> +	if (ops->func == NULL)				\
> +		return -rte_mtr_error_set(error,		\
> +			ENOSYS,				\
> +			RTE_MTR_ERROR_TYPE_UNSPECIFIED,	\
> +			NULL,				\
> +			rte_strerror(ENOSYS));		\
> +							\
> +	ops->func;					\
> +})
> +
> +/* MTR meter profile add */
> +int
> +rte_mtr_meter_profile_add(uint8_t port_id,
> +	uint32_t meter_profile_id,
> +	struct rte_mtr_meter_profile *profile,
> +	struct rte_mtr_error *error)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	return RTE_MTR_FUNC(port_id, meter_profile_add)(dev,
> +		meter_profile_id, profile, error);
> +}
> +
> +/** MTR meter profile delete */
> +int
> +rte_mtr_meter_profile_delete(uint8_t port_id,
> +	uint32_t meter_profile_id,
> +	struct rte_mtr_error *error)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	return RTE_MTR_FUNC(port_id, meter_profile_delete)(dev,
> +		meter_profile_id, error);
> +}
> +
> +/** MTR object create */
> +int
> +rte_mtr_create(uint8_t port_id,
> +	uint32_t mtr_id,
> +	struct rte_mtr_params *params,
> +	int shared,
> +	struct rte_mtr_error *error)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	return RTE_MTR_FUNC(port_id, create)(dev,
> +		mtr_id, params, shared, error);
> +}
> +
> +/** MTR object destroy */
> +int
> +rte_mtr_destroy(uint8_t port_id,
> +	uint32_t mtr_id,
> +	struct rte_mtr_error *error)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	return RTE_MTR_FUNC(port_id, destroy)(dev,
> +		mtr_id, error);
> +}
> +
> +/** MTR object meter profile update */
> +int
> +rte_mtr_meter_profile_update(uint8_t port_id,
> +	uint32_t mtr_id,
> +	uint32_t meter_profile_id,
> +	struct rte_mtr_error *error)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	return RTE_MTR_FUNC(port_id, meter_profile_update)(dev,
> +		mtr_id, meter_profile_id, error);
> +}
> +
> +/** MTR object policer action update */
> +int
> +rte_mtr_policer_action_update(uint8_t port_id,
> +	uint32_t mtr_id,
> +	enum rte_mtr_color color,
> +	enum rte_mtr_policer_action action,
> +	struct rte_mtr_error *error)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	return RTE_MTR_FUNC(port_id, policer_action_update)(dev,
> +		mtr_id, color, action, error);
> +}
> +
> +/** MTR object enabled stats update */
> +int
> +rte_mtr_stats_update(uint8_t port_id,
> +	uint32_t mtr_id,
> +	uint64_t stats_mask,
> +	struct rte_mtr_error *error)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	return RTE_MTR_FUNC(port_id, stats_update)(dev,
> +		mtr_id, stats_mask, error);
> +}
> +
> +/** MTR object stats read */
> +int
> +rte_mtr_stats_read(uint8_t port_id,
> +	uint32_t mtr_id,
> +	struct rte_mtr_stats *stats,
> +	uint64_t *stats_mask,
> +	int clear,
> +	struct rte_mtr_error *error)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	return RTE_MTR_FUNC(port_id, stats_read)(dev,
> +		mtr_id, stats, stats_mask, clear, error);
> +}
> diff --git a/lib/librte_ether/rte_mtr.h b/lib/librte_ether/rte_mtr.h
> new file mode 100644
> index 0000000..d15cb9f
> --- /dev/null
> +++ b/lib/librte_ether/rte_mtr.h
> @@ -0,0 +1,471 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2017 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.
> + */
> +
> +#ifndef __INCLUDE_RTE_MTR_H__
> +#define __INCLUDE_RTE_MTR_H__
> +
> +/**
> + * @file
> + * RTE Generic Traffic Metering and Policing API
> + *
> + * This interface provides the ability to configure the traffic metering and
> + * policing (MTR) in a generic way.
> + *
> + * The processing done for each input packet hitting a MTR object is:
> + *    A) Traffic metering: The packet is assigned a color (the meter output
> + *       color), based on the previous history of the flow reflected in the
> + *       current state of the MTR object, according to the specific traffic
> + *       metering algorithm. The traffic metering algorithm can typically work
> + *       in color aware mode, in which case the input packet already has an
> + *       initial color (the input color), or in color blind mode, which is
> + *       equivalent to considering all input packets initially colored as green.
> + *    B) Policing: There is a separate policer action configured for each meter
> + *       output color, which can:
> + *          a) Drop the packet.
> + *          b) Keep the same packet color: the policer output color matches the
> + *             meter output color (essentially a no-op action).
> + *          c) Recolor the packet: the policer output color is different than
> + *             the meter output color.
> + *       The policer output color is the output color of the packet, which is
> + *       set in the packet meta-data (i.e. struct rte_mbuf::sched::color).
> + *    C) Statistics: The set of counters maintained for each MTR object is
> + *       configurable and subject to the implementation support. This set
> + *       includes the number of packets and bytes dropped or passed for each
> + *       output color.
> + *
> + * Once successfully created, an MTR object is linked to one or several flows
> + * through the meter action of the flow API.
> + *    A) Whether an MTR object is private to a flow or potentially shared by
> + *       several flows has to be specified at creation time.
> + *    B) Several meter actions can be potentially registered for the same flow.
> + *
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + */
> +#include <stdint.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + * Color
> + */
> +enum rte_mtr_color {
> +	RTE_MTR_GREEN = 0, /**< Green */
> +	RTE_MTR_YELLOW, /**< Yellow */
> +	RTE_MTR_RED, /**< Red */
> +	RTE_MTR_COLORS /**< Number of colors */
> +};
> +
> +/**
> + * Statistics counter type
> + */
> +enum rte_mtr_stats_type {
> +	/**< Number of packets passed as green by the policer.  */
> +	RTE_MTR_STATS_N_PKTS_GREEN = 1 << 0,
> +
> +	/**< Number of bytes passed as green by the policer.  */
> +	RTE_MTR_STATS_N_BYTES_GREEN = 1 << 1,
> +
> +	/**< Number of packets passed as yellow by the policer.  */
> +	RTE_MTR_STATS_N_PKTS_YELLOW = 1 << 2,
> +
> +	/**< Number of bytes passed as yellow by the policer.  */
> +	RTE_MTR_STATS_N_BYTES_YELLOW = 1 << 3,
> +
> +	/**< Number of packets passed as red by the policer.  */
> +	RTE_MTR_STATS_N_PKTS_RED = 1 << 4,
> +
> +	/**< Number of bytes passed as red by the policer.  */
> +	RTE_MTR_STATS_N_BYTES_RED = 1 << 5,
> +
> +	/**< Number of packets dropped by the policer.  */
> +	RTE_MTR_STATS_N_PKTS_DROPPED = 1 << 6,
> +
> +	/**< Number of bytes dropped by the policer.  */
> +	RTE_MTR_STATS_N_BYTES_DROPPED = 1 << 7,
> +};
> +
> +/**
> + * Statistics counters
> + */
> +struct rte_mtr_stats {
> +	/**< Number of packets passed by the policer (per color). */
> +	uint64_t n_pkts[RTE_MTR_COLORS];
> +
> +	/**< Number of bytes passed by the policer (per color). */
> +	uint64_t n_bytes[RTE_MTR_COLORS];
> +
> +	/**< Number of packets dropped by the policer. */
> +	uint64_t n_pkts_dropped;
> +
> +	/**< Number of bytes passed by the policer. */
> +	uint64_t n_bytes_dropped;
> +};
> +
> +/**
> + * Traffic metering algorithms
> + */
> +enum rte_mtr_algorithm {
> +	/**< Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
> +	RTE_MTR_SRTCM_RFC2697 = 0,
> +
> +	/**< Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
> +	RTE_MTR_TRTCM_RFC2698,

will you please also add following here
1. RFC-4115—A differentiated service two-rate three-color marker with 
efficient handling of in-profile traffic
2. Pass Through Mode- This mode does not implement differentiated 
services. It can be used for some applications to block/pass selected 
flows and set a constant color for these flows. The default (disabled) 
mode is color-aware pass-through with no dropping of packets.
- In color-aware mode, packet pre-color is copied to the packet color
– In color-blind mode, the default color is programmable per profile
– Configurable next module and command per packet color. Each color 
action can be programmed to pass or drop the packet.


> +};
> +
> +/**
> + * Meter profile
> + */
> +struct rte_mtr_meter_profile {
> +	/**<  Traffic metering algorithm. */
> +	enum rte_mtr_algorithm alg;
> +
> +	union {
> +		/**< Items only valid when *alg* is set to srTCM - RFC2697. */
> +		struct {
> +			/**< Committed Information Rate (CIR) (bytes/second). */
> +			uint64_t cir;
> +
> +			/**< Committed Burst Size (CBS) (bytes). */
> +			uint64_t cbs;
> +
> +			/**< Excess Burst Size (EBS) (bytes). */
> +			uint64_t ebs;
> +
> +			/**< Non-zero for color aware mode, zero for color blind
> +			 * mode. In color aware mode, the packet input color is
> +			 * read from the IPv4/IPv6 DSCP field, as defined by
> +			 * IETF RFC 2597 (low/medium/high drop precedence
> +			 * translates to green/yellow/red color respectively).
> +			 */
> +			int color_aware;
> +		} srtcm_rfc2697;
> +
> +		/**< Items only valid when *alg* is set to trTCM - RFC2698. */
> +		struct {
> +			/**< Committed Information Rate (CIR) (bytes/second). */
> +			uint64_t cir;
> +
> +			/**< Peak Information Rate (PIR) (bytes/second). */
> +			uint64_t pir;
> +
> +			/**< Committed Burst Size (CBS) (byes). */
> +			uint64_t cbs;
> +
> +			/**< Peak Burst Size (PBS) (bytes). */
> +			uint64_t pbs;
> +
> +			/**< Non-zero for color aware mode, zero for color blind
> +			 * mode. In color aware mode, the packet input color is
> +			 * read from the IPv4/IPv6 DSCP field, as defined by
> +			 * IETF RFC 2597 (low/medium/high drop precedence
> +			 * translates to green/yellow/red color respectively).
> +			 */
> +			int color_aware;
> +		} trtcm_rfc2698;
> +	};
> +};
> +
> +/**
> + * Policer actions
> + */
> +enum rte_mtr_policer_action {
> +	/**< Recolor the packet as green. */
> +	e_MTR_POLICER_ACTION_COLOR_GREEN = 0,
> +
> +	/**< Recolor the packet as yellow. */
> +	e_MTR_POLICER_ACTION_COLOR_YELLOW,
> +
> +	/**< Recolor the packet as red. */
> +	e_MTR_POLICER_ACTION_COLOR_RED,
> +
> +	/**< Drop the packet. */
> +	e_MTR_POLICER_ACTION_DROP,
> +};
> +
> +/**
> + * Parameters for each traffic metering & policing object
> + *
> + * @see enum rte_mtr_stats_type
> + */
> +struct rte_mtr_params {
> +	/**< Meter profile ID. */
> +	uint32_t meter_profile_id;
> +
> +	/**< Policer actions (per meter output color). */
> +	enum rte_mtr_policer_action action[RTE_MTR_COLORS];
> +
> +	/**< Set of stats counters to be enabled. */
> +	uint64_t stats_mask;
> +};
> +
> +/**
> + * Verbose error types.
> + *
> + * Most of them provide the type of the object referenced by struct
> + * rte_mtr_error::cause.
> + */
> +enum rte_mtr_error_type {
> +	RTE_MTR_ERROR_TYPE_NONE, /**< No error. */
> +	RTE_MTR_ERROR_TYPE_UNSPECIFIED, /**< Cause unspecified. */
> +	RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
> +	RTE_MTR_ERROR_TYPE_METER_PROFILE,
> +	RTE_MTR_ERROR_TYPE_MTR_ID,
> +	RTE_MTR_ERROR_TYPE_MTR_PARAMS,
> +	RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
> +	RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW,
> +	RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED,
> +	RTE_MTR_ERROR_TYPE_STATS_MASK,
> +	RTE_MTR_ERROR_TYPE_STATS,
> +	RTE_MTR_ERROR_TYPE_SHARED,
> +};
> +
> +/**
> + * Verbose error structure definition.
> + *
> + * This object is normally allocated by applications and set by PMDs, the
> + * message points to a constant string which does not need to be freed by
> + * the application, however its pointer can be considered valid only as long
> + * as its associated DPDK port remains configured. Closing the underlying
> + * device or unloading the PMD invalidates it.
> + *
> + * Both cause and message may be NULL regardless of the error type.
> + */
> +struct rte_mtr_error {
> +	enum rte_mtr_error_type type; /**< Cause field and error type. */
> +	const void *cause; /**< Object responsible for the error. */
> +	const char *message; /**< Human-readable error message. */
> +};
> +
> +/**
> + * Meter profile add
> + *
> + * Create a new meter profile with ID set to *meter_profile_id*. The new profile
> + * is used to create one or several MTR objects.
> + *
> + * @param[in] port_id
> + *   The port identifier of the Ethernet device.
> + * @param[in] meter_profile_id
> + *   ID for the new meter profile. Needs to be unused by any of the existing
> + *   meter profiles added for the current port.
> + * @param[in] profile
> + *   Meter profile parameters. Needs to be pre-allocated and valid.
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_mtr_meter_profile_add(uint8_t port_id,
> +	uint32_t meter_profile_id,
> +	struct rte_mtr_meter_profile *profile,
> +	struct rte_mtr_error *error);
> +
> +/**
> + * Meter profile delete
> + *
> + * Delete an existing meter profile. This operation fails when there is
> + * currently at least one user (i.e. MTR object) of this profile.
> + *

Do you want to do this checking at library level or at driver level?
Same profile can be used by two distinct drivers!

This is applicable for other APIs as well. Your current API 
implementation is mostly pass-through. A stateful will be better.

> + * @param[in] port_id
> + *   The port identifier of the Ethernet device.
> + * @param[in] meter_profile_id
> + *   Meter profile ID. Needs to be the valid.
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_mtr_meter_profile_delete(uint8_t port_id,
> +	uint32_t meter_profile_id,
> +	struct rte_mtr_error *error);
> +
> +/**
> + * MTR object create
> + *
> + * Create a new MTR object for the current port. This object is run as part of
> + * associated flow action for traffic metering and policing.
> + *
> + * @param[in] port_id
> + *   The port identifier of the Ethernet device.
> + * @param[in] mtr_id
> + *   MTR object ID. Needs to be unused by any of the existing MTR objects
> + *   created for the current port.
> + * @param[in] params
> + *   MTR object params. Needs to be pre-allocated and valid.
> + * @param[in] shared
> + *   Non-zero when this MTR object can be shared by multiple flows, zero when
> + *   this MTR object can be used by a single flow.
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + *
> + * @see enum rte_flow_action_type::RTE_FLOW_ACTION_TYPE_METER
> + */
> +int
> +rte_mtr_create(uint8_t port_id,
> +	uint32_t mtr_id,
> +	struct rte_mtr_params *params,
> +	int shared,
> +	struct rte_mtr_error *error);
> +
> +/**
> + * MTR object destroy
> + *
> + * Delete an existing MTR object. This operation fails when there is currently
> + * at least one user (i.e. flow) of this MTR object.
> + *
> + * @param[in] port_id
> + *   The port identifier of the Ethernet device.
> + * @param[in] mtr_id
> + *   MTR object ID. Needs to be unused by any of the existing MTR objects
> + *   created for the current port.
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_mtr_destroy(uint8_t port_id,
> +	uint32_t mtr_id,
> +	struct rte_mtr_error *error);
> +
> +/**
> + * MTR object meter profile update
> + *
> + * @param[in] port_id
> + *   The port identifier of the Ethernet device.
> + * @param[in] mtr_id
> + *   MTR object ID. Needs to be valid.
> + * @param[in] meter_profile_id
> + *   Meter profile ID for the current MTR object. Needs to be valid.
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_mtr_meter_profile_update(uint8_t port_id,
> +	uint32_t mtr_id,
> +	uint32_t meter_profile_id,
> +	struct rte_mtr_error *error);
> +
> +/**
> + * MTR object policer action update for given color
> + *
> + * @param[in] port_id
> + *   The port identifier of the Ethernet device.
> + * @param[in] mtr_id
> + *   MTR object ID. Needs to be valid.
> + * @param[in] color
> + *   Color for which the policer action is updated.
> + * @param[in] action
> + *   Policer action for specified color.
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_mtr_policer_action_update(uint8_t port_id,
> +	uint32_t mtr_id,
> +	enum rte_mtr_color color,
> +	enum rte_mtr_policer_action action,
> +	struct rte_mtr_error *error);
> +
> +/**
> + * MTR object enabled statistics counters update
> + *
> + * @param[in] port_id
> + *   The port identifier of the Ethernet device.
> + * @param[in] mtr_id
> + *   MTR object ID. Needs to be valid.
> + * @param[in] stats_mask
> + *   Mask of statistics counter types to be enabled for the current MTR object.
> + *   Any statistics counter type not included in this set is to be disabled for
> + *   the current MTR object.
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + *
> + * @see enum rte_mtr_stats_type
> + */
> +int
> +rte_mtr_stats_update(uint8_t port_id,
> +	uint32_t mtr_id,
> +	uint64_t stats_mask,
> +	struct rte_mtr_error *error);
> +
> +/**
> + * MTR object statistics counters read
> + *
> + * @param[in] port_id
> + *   The port identifier of the Ethernet device.
> + * @param[in] mtr_id
> + *   MTR object ID. Needs to be valid.
> + * @param[out] stats
> + *   When non-NULL, it contains the current value for the statistics counters
> + *   enabled for the current MTR object.
> + * @param[out] stats_mask
> + *   When non-NULL, it contains the mask of statistics counter types that are
> + *   currently enabled for this MTR object, indicating which of the counters
> + *   retrieved with the *stats* structure are valid.
> + * @param[in] clear
> + *   When this parameter has a non-zero value, the statistics counters are
> + *   cleared (i.e. set to zero) immediately after they have been read,
> + *   otherwise the statistics counters are left untouched.
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + *
> + * @see enum rte_mtr_stats_type
> + */
> +int
> +rte_mtr_stats_read(uint8_t port_id,
> +	uint32_t mtr_id,
> +	struct rte_mtr_stats *stats,
> +	uint64_t *stats_mask,
> +	int clear,
> +	struct rte_mtr_error *error);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* __INCLUDE_RTE_MTR_H__ */
> diff --git a/lib/librte_ether/rte_mtr_driver.h b/lib/librte_ether/rte_mtr_driver.h
> new file mode 100644
> index 0000000..3798cf6
> --- /dev/null
> +++ b/lib/librte_ether/rte_mtr_driver.h
> @@ -0,0 +1,188 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2017 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.
> + */
> +
> +#ifndef __INCLUDE_RTE_MTR_DRIVER_H__
> +#define __INCLUDE_RTE_MTR_DRIVER_H__
> +
> +/**
> + * @file
> + * RTE Generic Traffic Metering and Policing API (Driver Side)
> + *
> + * This file provides implementation helpers for internal use by PMDs, they
> + * are not intended to be exposed to applications and are not subject to ABI
> + * versioning.
> + */
> +
> +#include <stdint.h>
> +
> +#include <rte_errno.h>
> +#include "rte_ethdev.h"
> +#include "rte_mtr.h"
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +typedef int (*rte_mtr_meter_profile_add_t)(struct rte_eth_dev *dev,
> +	uint32_t meter_profile_id,
> +	struct rte_mtr_meter_profile *profile,
> +	struct rte_mtr_error *error);
> +/**< @internal MTR meter profile add */
> +
> +typedef int (*rte_mtr_meter_profile_delete_t)(struct rte_eth_dev *dev,
> +	uint32_t meter_profile_id,
> +	struct rte_mtr_error *error);
> +/**< @internal MTR meter profile delete */
> +
> +typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
> +	uint32_t mtr_id,
> +	struct rte_mtr_params *params,
> +	int shared,
> +	struct rte_mtr_error *error);
> +/**< @internal MTR object create */
> +
> +typedef int (*rte_mtr_destroy_t)(struct rte_eth_dev *dev,
> +	uint32_t mtr_id,
> +	struct rte_mtr_error *error);
> +/**< @internal MTR object destroy */
> +
> +typedef int (*rte_mtr_meter_profile_update_t)(struct rte_eth_dev *dev,
> +	uint32_t mtr_id,
> +	uint32_t meter_profile_id,
> +	struct rte_mtr_error *error);
> +/**< @internal MTR object meter profile update */
> +
> +typedef int (*rte_mtr_policer_action_update_t)(struct rte_eth_dev *dev,
> +	uint32_t mtr_id,
> +	enum rte_mtr_color color,
> +	enum rte_mtr_policer_action action,
> +	struct rte_mtr_error *error);
> +/**< @internal MTR object policer action update*/
> +
> +typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
> +	uint32_t mtr_id,
> +	uint64_t stats_mask,
> +	struct rte_mtr_error *error);
> +/**< @internal MTR object enabled stats update */
> +
> +typedef int (*rte_mtr_stats_read_t)(struct rte_eth_dev *dev,
> +	uint32_t mtr_id,
> +	struct rte_mtr_stats *stats,
> +	uint64_t *stats_mask,
> +	int clear,
> +	struct rte_mtr_error *error);
> +/**< @internal MTR object stats read */
> +
> +struct rte_mtr_ops {
> +	/** MTR meter profile add */
> +	rte_mtr_meter_profile_add_t meter_profile_add;
> +
> +	/** MTR meter profile delete */
> +	rte_mtr_meter_profile_delete_t meter_profile_delete;
> +
> +	/** MTR object create */
> +	rte_mtr_create_t create;
> +
> +	/** MTR object destroy */
> +	rte_mtr_destroy_t destroy;
> +
> +	/** MTR object meter profile update */
> +	rte_mtr_meter_profile_update_t meter_profile_update;
> +
> +	/** MTR object policer action update */
> +	rte_mtr_policer_action_update_t policer_action_update;
> +
> +	/** MTR object enabled stats update */
> +	rte_mtr_stats_update_t stats_update;
> +
> +	/** MTR object stats read */
> +	rte_mtr_stats_read_t stats_read;
> +};
> +
> +/**
> + * Initialize generic error structure.
> + *
> + * This function also sets rte_errno to a given value.
> + *
> + * @param[out] error
> + *   Pointer to error structure (may be NULL).
> + * @param[in] code
> + *   Related error code (rte_errno).
> + * @param[in] type
> + *   Cause field and error type.
> + * @param[in] cause
> + *   Object responsible for the error.
> + * @param[in] message
> + *   Human-readable error message.
> + *
> + * @return
> + *   Error code.
> + */
> +static inline int
> +rte_mtr_error_set(struct rte_mtr_error *error,
> +		   int code,
> +		   enum rte_mtr_error_type type,
> +		   const void *cause,
> +		   const char *message)
> +{
> +	if (error) {
> +		*error = (struct rte_mtr_error){
> +			.type = type,
> +			.cause = cause,
> +			.message = message,
> +		};
> +	}
> +	rte_errno = code;
> +	return code;
> +}
> +
> +/**
> + * Get generic traffic metering and policing operations structure from a port
> + *
> + * @param[in] port_id
> + *   The port identifier of the Ethernet device.
> + * @param[out] error
> + *   Error details
> + *
> + * @return
> + *   The traffic metering and policing operations structure associated with
> + *   port_id on success, NULL otherwise.
> + */
> +const struct rte_mtr_ops *
> +rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* __INCLUDE_RTE_MTR_DRIVER_H__ */
>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] dev Digest, Vol 159, Issue 119
       [not found]     <mailman.4135.1504256282.5771.dev@dpdk.org>
@ 2017-09-01  9:36  3% ` Pierre
  0 siblings, 0 replies; 200+ results
From: Pierre @ 2017-09-01  9:36 UTC (permalink / raw)
  To: dev

Hi

This might not be a good idea. With these modifications, the functions 
are not inlined any more (attribute inline), and not post-optimized 
either (-f lto)

As per ABI, most of the registers must be saved on the stack before 
invoking a function. This is not noticeable in isolated test/perf code 
where there is not much context to save and restore at each function 
call, but it destroys performance in real heavy application where it is 
expected, for performance reasons, that rte_memcpy is really an inlined 
leaf function and all code can be inlined and optimized at compile time.

The DPDK design logic has always been in the past to provide the most 
efficient implementation for a designated target platform. Else there 
would not be no advantage to provide rte_memcpy() over the standard 
generic memcpy() function.

Such type of code is slowly starting to creep into DPDK codebase. an 
other example is the support for dynamic callbacks in rte_eth_tx_burst().

If multi-platform MUST be supported at run time, the right trade-off 
would be to make-sure this type of code can be compiled out, e.g. add 
something like RTE_ENABLE_RUN_TIME_DISPATCH in the config file.

Regards,

Pierre


On 01/09/17 09:58, dev-request@dpdk.org wrote:
> Send dev mailing list submissions to
> 	dev@dpdk.org
>
> To subscribe or unsubscribe via the World Wide Web, visit
> 	http://dpdk.org/ml/listinfo/dev
> or, via email, send a message with subject or body 'help' to
> 	dev-request@dpdk.org
>
> You can reach the person managing the list at
> 	dev-owner@dpdk.org
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of dev digest..."
>
>
> Today's Topics:
>
>     1. [PATCH v2 0/3] dynamic linking support (Xiaoyun Li)
>     2. [PATCH v2 1/3] eal/x86: run-time dispatch over memcpy (Xiaoyun Li)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Fri,  1 Sep 2017 16:56:59 +0800
> From: Xiaoyun Li <xiaoyun.li@intel.com>
> To: bruce.richardson@intel.com
> Cc: dev@dpdk.org, zhihong.wang@intel.com, qi.z.zhang@intel.com,
> 	wenzhuo.lu@intel.com, Xiaoyun Li <xiaoyun.li@intel.com>
> Subject: [dpdk-dev] [PATCH v2 0/3] dynamic linking support
> Message-ID: <1504256222-32969-1-git-send-email-xiaoyun.li@intel.com>
>
> This patchset dynamically selects functions at run-time based on CPU flags
> that current machine supports. This patchset modifies mempcy, memcpy perf
> test and x86 EFD, using function pointers and bind them at constructor time.
> Then in the cloud environment, users can compiler once for the minimum target
> such as 'haswell'(not 'native') and run on different platforms (equal or above
> haswell) and can get ISA optimization based on running CPU.
>
> Xiaoyun Li (3):
>    eal/x86: run-time dispatch over memcpy
>    app/test: run-time dispatch over memcpy perf test
>    efd: run-time dispatch over x86 EFD functions
>
>   .../common/include/arch/x86/rte_memcpy.h           | 343 +++++++++++++--------
>   lib/librte_efd/rte_efd_x86.h                       |  41 ++-
>   mk/rte.cpuflags.mk                                 |  14 +
>   test/test/test_memcpy_perf.c                       |  40 ++-
>   4 files changed, 296 insertions(+), 142 deletions(-)
>

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH 04/17] build: add DPDK libraries to build
    @ 2017-09-01 10:04  1% ` Bruce Richardson
  2017-09-04 14:08  0%   ` Van Haaren, Harry
  2017-09-01 10:04  3% ` [dpdk-dev] [PATCH 16/17] build: add option to version libs using DPDK version Bruce Richardson
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2017-09-01 10:04 UTC (permalink / raw)
  To: dev; +Cc: Bruce Richardson

Add non-EAL libraries to DPDK build. The compat lib is a special case,
along with the previously-added EAL, but all other libs can be build using
the same set of commands, where the individual meson.build files only need
to specify their dependencies, source files, header files and ABI versions.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 config/rte_config.h                 | 36 ++++++++++++++++++++
 lib/librte_acl/meson.build          | 59 ++++++++++++++++++++++++++++++++
 lib/librte_bitratestats/meson.build | 34 +++++++++++++++++++
 lib/librte_cfgfile/meson.build      | 34 +++++++++++++++++++
 lib/librte_cmdline/meson.build      | 55 ++++++++++++++++++++++++++++++
 lib/librte_compat/meson.build       | 36 ++++++++++++++++++++
 lib/librte_cryptodev/meson.build    | 40 ++++++++++++++++++++++
 lib/librte_distributor/meson.build  | 39 +++++++++++++++++++++
 lib/librte_efd/meson.build          | 34 +++++++++++++++++++
 lib/librte_ether/meson.build        | 45 +++++++++++++++++++++++++
 lib/librte_eventdev/meson.build     | 36 ++++++++++++++++++++
 lib/librte_gro/meson.build          | 34 +++++++++++++++++++
 lib/librte_hash/meson.build         | 45 +++++++++++++++++++++++++
 lib/librte_ip_frag/meson.build      | 39 +++++++++++++++++++++
 lib/librte_jobstats/meson.build     | 33 ++++++++++++++++++
 lib/librte_kni/meson.build          | 38 +++++++++++++++++++++
 lib/librte_kvargs/meson.build       | 34 +++++++++++++++++++
 lib/librte_latencystats/meson.build | 34 +++++++++++++++++++
 lib/librte_lpm/meson.build          | 35 +++++++++++++++++++
 lib/librte_mbuf/meson.build         | 36 ++++++++++++++++++++
 lib/librte_mempool/meson.build      | 35 +++++++++++++++++++
 lib/librte_meter/meson.build        | 33 ++++++++++++++++++
 lib/librte_metrics/meson.build      | 33 ++++++++++++++++++
 lib/librte_net/meson.build          | 45 +++++++++++++++++++++++++
 lib/librte_pdump/meson.build        | 34 +++++++++++++++++++
 lib/librte_pipeline/meson.build     | 35 +++++++++++++++++++
 lib/librte_port/meson.build         | 58 ++++++++++++++++++++++++++++++++
 lib/librte_power/meson.build        | 37 ++++++++++++++++++++
 lib/librte_reorder/meson.build      | 34 +++++++++++++++++++
 lib/librte_ring/meson.build         | 33 ++++++++++++++++++
 lib/librte_sched/meson.build        | 36 ++++++++++++++++++++
 lib/librte_table/meson.build        | 52 ++++++++++++++++++++++++++++
 lib/librte_timer/meson.build        | 33 ++++++++++++++++++
 lib/librte_vhost/meson.build        | 39 +++++++++++++++++++++
 lib/meson.build                     | 67 +++++++++++++++++++++++++++++++++++++
 35 files changed, 1380 insertions(+)
 create mode 100644 lib/librte_acl/meson.build
 create mode 100644 lib/librte_bitratestats/meson.build
 create mode 100644 lib/librte_cfgfile/meson.build
 create mode 100644 lib/librte_cmdline/meson.build
 create mode 100644 lib/librte_compat/meson.build
 create mode 100644 lib/librte_cryptodev/meson.build
 create mode 100644 lib/librte_distributor/meson.build
 create mode 100644 lib/librte_efd/meson.build
 create mode 100644 lib/librte_ether/meson.build
 create mode 100644 lib/librte_eventdev/meson.build
 create mode 100644 lib/librte_gro/meson.build
 create mode 100644 lib/librte_hash/meson.build
 create mode 100644 lib/librte_ip_frag/meson.build
 create mode 100644 lib/librte_jobstats/meson.build
 create mode 100644 lib/librte_kni/meson.build
 create mode 100644 lib/librte_kvargs/meson.build
 create mode 100644 lib/librte_latencystats/meson.build
 create mode 100644 lib/librte_lpm/meson.build
 create mode 100644 lib/librte_mbuf/meson.build
 create mode 100644 lib/librte_mempool/meson.build
 create mode 100644 lib/librte_meter/meson.build
 create mode 100644 lib/librte_metrics/meson.build
 create mode 100644 lib/librte_net/meson.build
 create mode 100644 lib/librte_pdump/meson.build
 create mode 100644 lib/librte_pipeline/meson.build
 create mode 100644 lib/librte_port/meson.build
 create mode 100644 lib/librte_power/meson.build
 create mode 100644 lib/librte_reorder/meson.build
 create mode 100644 lib/librte_ring/meson.build
 create mode 100644 lib/librte_sched/meson.build
 create mode 100644 lib/librte_table/meson.build
 create mode 100644 lib/librte_timer/meson.build
 create mode 100644 lib/librte_vhost/meson.build

diff --git a/config/rte_config.h b/config/rte_config.h
index 252b087ad..7fb6c4cce 100644
--- a/config/rte_config.h
+++ b/config/rte_config.h
@@ -58,4 +58,40 @@
 #define RTE_BACKTRACE 1
 #define RTE_EAL_VFIO 1
 
+/* mempool defines */
+#define RTE_MEMPOOL_CACHE_MAX_SIZE 512
+
+/* mbuf defines */
+#define RTE_MBUF_DEFAULT_MEMPOOL_OPS "ring_mp_mc"
+#define RTE_MBUF_REFCNT_ATOMIC 1
+#define RTE_PKTMBUF_HEADROOM 128
+
+/* ether defines */
+#define RTE_MAX_ETHPORTS 32
+#define RTE_MAX_QUEUES_PER_PORT 1024
+#define RTE_ETHDEV_QUEUE_STAT_CNTRS 16
+#define RTE_ETHDEV_RXTX_CALLBACKS 1
+
+/* cryptodev defines */
+#define RTE_CRYPTO_MAX_DEVS 64
+#define RTE_CRYPTODEV_NAME_LEN 64
+
+/* eventdev defines */
+#define RTE_EVENT_MAX_DEVS 16
+#define RTE_EVENT_MAX_QUEUES_PER_DEV 64
+
+/* ip_fragmentation defines */
+#define RTE_LIBRTE_IP_FRAG_MAX_FRAG 4
+#undef RTE_LIBRTE_IP_FRAG_TBL_STAT
+
+/* rte_power defines */
+#define RTE_MAX_LCORE_FREQS 64
+
+/* rte_sched defines */
+#undef RTE_SCHED_RED
+#undef RTE_SCHED_COLLECT_STATS
+#undef RTE_SCHED_SUBPORT_TC_OV
+#define RTE_SCHED_PORT_N_GRINDERS 8
+#undef RTE_SCHED_VECTOR
+
 #endif /* _RTE_CONFIG_H_ */
diff --git a/lib/librte_acl/meson.build b/lib/librte_acl/meson.build
new file mode 100644
index 000000000..c217d6ffe
--- /dev/null
+++ b/lib/librte_acl/meson.build
@@ -0,0 +1,59 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('acl_bld.c', 'acl_gen.c', 'acl_run_scalar.c',
+		'rte_acl.c', 'tb_mem.c')
+headers = files('rte_acl.h', 'rte_acl_osdep.h')
+
+if arch_subdir == 'x86'
+	sources += files('acl_run_sse.c')
+
+	# compile AVX2 version if either:
+	# a. we have AVX supported in minimum instruction set baseline
+	# b. it's not minimum instruction set, but supported by compiler
+	#
+	# in former case, just add avx2 C file to files list
+	# in latter case, compile c file to static lib, using correct compiler
+	# flags, and then have the .o file from static lib linked into main lib.
+	if dpdk_conf.has('RTE_MACHINE_CPUFLAG_AVX2')
+		sources += files('acl_run_avx2.c')
+		cflags += '-DCC_AVX2_SUPPORT'
+	elif cc.has_argument('-mavx2')
+		avx2_tmplib = static_library('avx2_tmp',
+				'acl_run_avx2.c',
+				dependencies: rte_eal,
+				c_args: '-mavx2')
+		objs += avx2_tmplib.extract_objects('acl_run_avx2.c')
+		cflags += '-DCC_AVX2_SUPPORT'
+	endif
+
+endif
diff --git a/lib/librte_bitratestats/meson.build b/lib/librte_bitratestats/meson.build
new file mode 100644
index 000000000..5adfaf7f3
--- /dev/null
+++ b/lib/librte_bitratestats/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_bitrate.c')
+headers = files('rte_bitrate.h')
+deps += ['ethdev', 'metrics']
diff --git a/lib/librte_cfgfile/meson.build b/lib/librte_cfgfile/meson.build
new file mode 100644
index 000000000..540b47c14
--- /dev/null
+++ b/lib/librte_cfgfile/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('rte_cfgfile.c')
+headers = files('rte_cfgfile.h')
diff --git a/lib/librte_cmdline/meson.build b/lib/librte_cmdline/meson.build
new file mode 100644
index 000000000..c5e01ba21
--- /dev/null
+++ b/lib/librte_cmdline/meson.build
@@ -0,0 +1,55 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('cmdline.c',
+	'cmdline_cirbuf.c',
+	'cmdline_parse.c',
+	'cmdline_parse_etheraddr.c',
+	'cmdline_parse_ipaddr.c',
+	'cmdline_parse_num.c',
+	'cmdline_parse_portlist.c',
+	'cmdline_parse_string.c',
+	'cmdline_rdline.c',
+	'cmdline_socket.c',
+	'cmdline_vt100.c')
+
+headers = files('cmdline.h',
+	'cmdline_parse.h',
+	'cmdline_parse_num.h',
+	'cmdline_parse_ipaddr.h',
+	'cmdline_parse_etheraddr.h',
+	'cmdline_parse_string.h',
+	'cmdline_rdline.h',
+	'cmdline_vt100.h',
+	'cmdline_socket.h',
+	'cmdline_cirbuf.h',
+	'cmdline_parse_portlist.h')
diff --git a/lib/librte_compat/meson.build b/lib/librte_compat/meson.build
new file mode 100644
index 000000000..6773e2203
--- /dev/null
+++ b/lib/librte_compat/meson.build
@@ -0,0 +1,36 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+
+install_headers('rte_compat.h')
+
+set_variable('dep_rte_compat',
+	declare_dependency(include_directories: include_directories('.')))
diff --git a/lib/librte_cryptodev/meson.build b/lib/librte_cryptodev/meson.build
new file mode 100644
index 000000000..9663d8d13
--- /dev/null
+++ b/lib/librte_cryptodev/meson.build
@@ -0,0 +1,40 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 3
+sources = files('rte_cryptodev.c', 'rte_cryptodev_pmd.c')
+headers = files('rte_cryptodev.h',
+	'rte_cryptodev_pci.h',
+	'rte_cryptodev_pmd.h',
+	'rte_cryptodev_vdev.h',
+	'rte_crypto.h',
+	'rte_crypto_sym.h')
+deps += ['kvargs', 'mbuf']
diff --git a/lib/librte_distributor/meson.build b/lib/librte_distributor/meson.build
new file mode 100644
index 000000000..0851d78aa
--- /dev/null
+++ b/lib/librte_distributor/meson.build
@@ -0,0 +1,39 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_distributor.c', 'rte_distributor_v20.c')
+if arch_subdir == 'x86'
+	sources += files('rte_distributor_match_sse.c')
+else
+	sources += files('rte_distributor_match_generic.c')
+endif
+headers = files('rte_distributor.h')
+deps += ['mbuf', 'compat']
diff --git a/lib/librte_efd/meson.build b/lib/librte_efd/meson.build
new file mode 100644
index 000000000..4132d848a
--- /dev/null
+++ b/lib/librte_efd/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_efd.c')
+headers = files('rte_efd.h')
+deps += ['ring', 'hash']
diff --git a/lib/librte_ether/meson.build b/lib/librte_ether/meson.build
new file mode 100644
index 000000000..47f0c0e1b
--- /dev/null
+++ b/lib/librte_ether/meson.build
@@ -0,0 +1,45 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+name = 'ethdev'
+version = 6
+sources = files('rte_ethdev.c', 'rte_flow.c', 'rte_tm.c')
+
+headers = files('rte_ethdev.h',
+	'rte_ethdev_pci.h',
+	'rte_ethdev_vdev.h',
+	'rte_eth_ctrl.h',
+	'rte_dev_info.h',
+	'rte_flow.h',
+	'rte_flow_driver.h',
+	'rte_tm.h')
+
+deps += ['net']
diff --git a/lib/librte_eventdev/meson.build b/lib/librte_eventdev/meson.build
new file mode 100644
index 000000000..e7e32cfe2
--- /dev/null
+++ b/lib/librte_eventdev/meson.build
@@ -0,0 +1,36 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_eventdev.c', 'rte_event_ring.c')
+headers = files('rte_eventdev.h', 'rte_eventdev_pmd.h',
+		'rte_eventdev_pmd_pci.h', 'rte_eventdev_pmd_vdev.h',
+		'rte_event_ring.h')
+deps += ['ring']
diff --git a/lib/librte_gro/meson.build b/lib/librte_gro/meson.build
new file mode 100644
index 000000000..2c62900d0
--- /dev/null
+++ b/lib/librte_gro/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_gro.c', 'gro_tcp4.c')
+headers = files('rte_gro.h')
+deps += ['ethdev']
diff --git a/lib/librte_hash/meson.build b/lib/librte_hash/meson.build
new file mode 100644
index 000000000..f8c6f1452
--- /dev/null
+++ b/lib/librte_hash/meson.build
@@ -0,0 +1,45 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+headers = files('rte_cmp_arm64.h',
+	'rte_cmp_x86.h',
+	'rte_crc_arm64.h',
+	'rte_cuckoo_hash.h',
+	'rte_cuckoo_hash_x86.h',
+	'rte_fbk_hash.h',
+	'rte_hash_crc.h',
+	'rte_hash.h',
+	'rte_jhash.h',
+	'rte_thash.h')
+
+sources = files('rte_cuckoo_hash.c', 'rte_fbk_hash.c')
+deps += ['ring', 'compat']
diff --git a/lib/librte_ip_frag/meson.build b/lib/librte_ip_frag/meson.build
new file mode 100644
index 000000000..4b47664c0
--- /dev/null
+++ b/lib/librte_ip_frag/meson.build
@@ -0,0 +1,39 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_ipv4_fragmentation.c',
+		'rte_ipv6_fragmentation.c',
+		'rte_ipv4_reassembly.c',
+		'rte_ipv6_reassembly.c',
+		'rte_ip_frag_common.c',
+		'ip_frag_internal.c')
+headers = files('rte_ip_frag.h')
+deps += ['ethdev', 'hash']
diff --git a/lib/librte_jobstats/meson.build b/lib/librte_jobstats/meson.build
new file mode 100644
index 000000000..ae8f715ad
--- /dev/null
+++ b/lib/librte_jobstats/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_jobstats.c')
+headers = files('rte_jobstats.h')
diff --git a/lib/librte_kni/meson.build b/lib/librte_kni/meson.build
new file mode 100644
index 000000000..a922a8692
--- /dev/null
+++ b/lib/librte_kni/meson.build
@@ -0,0 +1,38 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+if host_machine.system() != 'linux'
+	build = false
+endif
+version = 2
+sources = files('rte_kni.c')
+headers = files('rte_kni.h')
+deps += ['ethdev']
diff --git a/lib/librte_kvargs/meson.build b/lib/librte_kvargs/meson.build
new file mode 100644
index 000000000..25715d1fa
--- /dev/null
+++ b/lib/librte_kvargs/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 1
+sources = files('rte_kvargs.c')
+headers = files('rte_kvargs.h')
diff --git a/lib/librte_latencystats/meson.build b/lib/librte_latencystats/meson.build
new file mode 100644
index 000000000..05f4c3568
--- /dev/null
+++ b/lib/librte_latencystats/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_latencystats.c')
+headers = files('rte_latencystats.h')
+deps += ['metrics', 'ethdev']
diff --git a/lib/librte_lpm/meson.build b/lib/librte_lpm/meson.build
new file mode 100644
index 000000000..a029c2919
--- /dev/null
+++ b/lib/librte_lpm/meson.build
@@ -0,0 +1,35 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('rte_lpm.c', 'rte_lpm6.c')
+headers = files('rte_lpm.h', 'rte_lpm6.h')
+deps += ['compat']
diff --git a/lib/librte_mbuf/meson.build b/lib/librte_mbuf/meson.build
new file mode 100644
index 000000000..f1724b59e
--- /dev/null
+++ b/lib/librte_mbuf/meson.build
@@ -0,0 +1,36 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 3
+sources = files('rte_mbuf.c', 'rte_mbuf_ptype.c')
+headers = files('rte_mbuf.h', 'rte_mbuf_ptype.h')
+deps += ['mempool']
+
diff --git a/lib/librte_mempool/meson.build b/lib/librte_mempool/meson.build
new file mode 100644
index 000000000..6b660002c
--- /dev/null
+++ b/lib/librte_mempool/meson.build
@@ -0,0 +1,35 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('rte_mempool.c', 'rte_mempool_ops.c')
+headers = files('rte_mempool.h')
+deps += ['ring']
diff --git a/lib/librte_meter/meson.build b/lib/librte_meter/meson.build
new file mode 100644
index 000000000..9b477d53e
--- /dev/null
+++ b/lib/librte_meter/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_meter.c')
+headers = files('rte_meter.h')
diff --git a/lib/librte_metrics/meson.build b/lib/librte_metrics/meson.build
new file mode 100644
index 000000000..218aa6974
--- /dev/null
+++ b/lib/librte_metrics/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_metrics.c')
+headers = files('rte_metrics.h')
diff --git a/lib/librte_net/meson.build b/lib/librte_net/meson.build
new file mode 100644
index 000000000..fc9846947
--- /dev/null
+++ b/lib/librte_net/meson.build
@@ -0,0 +1,45 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 1
+headers = files('rte_ip.h',
+	'rte_tcp.h',
+	'rte_udp.h',
+	'rte_sctp.h',
+	'rte_icmp.h',
+	'rte_arp.h',
+	'rte_ether.h',
+	'rte_gre.h',
+	'rte_net.h',
+	'rte_net_crc.h')
+
+sources = files('rte_net.c', 'rte_net_crc.c')
+deps += ['mbuf']
diff --git a/lib/librte_pdump/meson.build b/lib/librte_pdump/meson.build
new file mode 100644
index 000000000..bafcb3650
--- /dev/null
+++ b/lib/librte_pdump/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_pdump.c')
+headers = files('rte_pdump.h')
+deps += ['ethdev']
diff --git a/lib/librte_pipeline/meson.build b/lib/librte_pipeline/meson.build
new file mode 100644
index 000000000..c76fce149
--- /dev/null
+++ b/lib/librte_pipeline/meson.build
@@ -0,0 +1,35 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 3
+sources = files('rte_pipeline.c')
+headers = files('rte_pipeline.h')
+deps += ['port', 'table']
diff --git a/lib/librte_port/meson.build b/lib/librte_port/meson.build
new file mode 100644
index 000000000..4a78da9bf
--- /dev/null
+++ b/lib/librte_port/meson.build
@@ -0,0 +1,58 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 3
+sources = files(
+	'rte_port_ethdev.c',
+	'rte_port_fd.c',
+	'rte_port_ring.c',
+	'rte_port_sched.c',
+	'rte_port_source_sink.c')
+headers = files(
+	'rte_port_ethdev.h',
+	'rte_port_fd.h',
+	'rte_port.h',
+	'rte_port_ring.h',
+	'rte_port_sched.h',
+	'rte_port_source_sink.h')
+deps += ['ethdev', 'sched']
+
+if dpdk_conf.has('RTE_LIBRTE_IP_FRAG')
+	sources += files('rte_port_frag.c', 'rte_port_ras.c')
+	headers += files('rte_port_frag.h', 'rte_port_ras.h')
+	deps += ['ip_frag']
+endif
+
+if dpdk_conf.has('RTE_LIBRTE_KNI')
+	sources += files('rte_port_kni.c')
+	headers += files('rte_port_kni.h')
+	deps += 'kni'
+endif
diff --git a/lib/librte_power/meson.build b/lib/librte_power/meson.build
new file mode 100644
index 000000000..0b1d74a42
--- /dev/null
+++ b/lib/librte_power/meson.build
@@ -0,0 +1,37 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+if host_machine.system() != 'linux'
+	build = false
+endif
+sources = files('rte_power.c', 'rte_power_acpi_cpufreq.c',
+		'rte_power_kvm_vm.c', 'guest_channel.c')
+headers = files('rte_power.h')
diff --git a/lib/librte_reorder/meson.build b/lib/librte_reorder/meson.build
new file mode 100644
index 000000000..f875befd0
--- /dev/null
+++ b/lib/librte_reorder/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_reorder.c')
+headers = files('rte_reorder.h')
+deps += ['mbuf']
diff --git a/lib/librte_ring/meson.build b/lib/librte_ring/meson.build
new file mode 100644
index 000000000..6f13f4f35
--- /dev/null
+++ b/lib/librte_ring/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_ring.c')
+headers = files('rte_ring.h')
diff --git a/lib/librte_sched/meson.build b/lib/librte_sched/meson.build
new file mode 100644
index 000000000..3e30992c6
--- /dev/null
+++ b/lib/librte_sched/meson.build
@@ -0,0 +1,36 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_sched.c', 'rte_red.c', 'rte_approx.c',
+		'rte_reciprocal.c')
+headers = files('rte_sched.h', 'rte_bitmap.h', 'rte_sched_common.h',
+		'rte_red.h', 'rte_approx.h', 'rte_reciprocal.h')
+deps += ['mbuf', 'meter']
diff --git a/lib/librte_table/meson.build b/lib/librte_table/meson.build
new file mode 100644
index 000000000..a76aad0f2
--- /dev/null
+++ b/lib/librte_table/meson.build
@@ -0,0 +1,52 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('rte_table_lpm.c', 'rte_table_lpm_ipv6.c',
+		'rte_table_hash_cuckoo.c', 'rte_table_hash_key8.c',
+		'rte_table_hash_key16.c', 'rte_table_hash_key32.c',
+		'rte_table_hash_ext.c', 'rte_table_hash_lru.c',
+		'rte_table_array.c', 'rte_table_stub.c')
+headers = files('rte_table.h', 'rte_table_lpm.h',
+		'rte_table_lpm_ipv6.h', 'rte_table_hash.h',
+		'rte_lru.h', 'rte_table_array.h',
+		'rte_table_stub.h')
+deps += ['mbuf', 'port', 'lpm', 'hash']
+
+if arch_subdir == 'x86'
+	headers += files('rte_lru_x86.h')
+endif
+
+if dpdk_conf.has('RTE_LIBRTE_ACL')
+	sources += files('rte_table_acl.c')
+	headers += files('rte_table_acl.h')
+	deps += ['acl']
+endif
diff --git a/lib/librte_timer/meson.build b/lib/librte_timer/meson.build
new file mode 100644
index 000000000..87da309f2
--- /dev/null
+++ b/lib/librte_timer/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_timer.c')
+headers = files('rte_timer.h')
diff --git a/lib/librte_vhost/meson.build b/lib/librte_vhost/meson.build
new file mode 100644
index 000000000..7dfe3fe7a
--- /dev/null
+++ b/lib/librte_vhost/meson.build
@@ -0,0 +1,39 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+if host_machine.system() != 'linux'
+	build = false
+endif
+version = 4
+sources = files('fd_man.c', 'socket.c', 'vhost.c', 'vhost_user.c',
+		'virtio_net.c')
+headers = files('rte_vhost.h')
+deps += ['ethdev']
diff --git a/lib/meson.build b/lib/meson.build
index d478a78c1..b8c4304de 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -29,4 +29,71 @@
 #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# special case for eal, not a simple lib, and compat, just a header
 subdir('librte_eal')
+subdir('librte_compat')
+
+# process all libraries equally, as far as possible
+# "core" libs first, then others alphebetically as far as possible
+# NOTE: for speed of meson runs, the dependencies in the subdirectories
+# sometimes skip deps that would be implied by others, e.g. if mempool is
+# given as a dep, no need to mention ring. This is especially true for the
+# core libs which are widely reused, so their deps are kept to a minimum.
+libraries = ['ring', 'mempool', 'mbuf', 'net', 'ether', # core
+	'metrics', # bitrate/latency stats depends on this
+	'hash',    # efd depends on this
+	'kvargs',  # cryptodev depends on this
+	'acl', 'bitratestats', 'cfgfile', 'cmdline', 'cryptodev',
+	'distributor', 'efd', 'eventdev', 'gro', 'ip_frag', 'jobstats',
+	'kni', 'latencystats', 'lpm', 'meter', 'power', 'pdump',
+	'reorder', 'sched', 'timer', 'vhost',
+	# add pkt framework libs which use other libs from above
+	'port', 'table', 'pipeline']
+
+foreach l:libraries
+	build = true
+	name = l
+	version = 1
+	sources = []
+	headers = []
+	cflags = []
+	objs = [] # other object files to link against, used e.g. for instruction-
+	          # optimized versions of code
+	# use "deps" for internal DPDK dependencies, and "ext_deps" for
+	# external package/library requirements
+	deps = ['eal']
+	ext_deps = []
+
+	dir_name = 'librte_' + l
+	subdir(dir_name)
+
+	if build
+		dpdk_conf.set('RTE_LIBRTE_' + name.to_upper(), 1)
+		install_headers(headers)
+
+		dep_objs = ext_deps
+		foreach d:deps
+			dep_objs += [get_variable('dep_rte_' + d)]
+		endforeach
+
+		version_map = '@0@/@1@/rte_@2@_version.map'.format(
+				meson.current_source_dir(), dir_name, name)
+		libname = 'rte_' + name
+		lib = library(libname,
+				sources,
+				objects: objs,
+				c_args: cflags,
+				dependencies: dep_objs,
+				include_directories: include_directories(dir_name),
+				link_args: '-Wl,--version-script=' + version_map,
+				link_depends: version_map,
+				version: '@0@.1'.format(version),
+				install: true)
+		dep = declare_dependency(link_with: lib,
+				include_directories: include_directories(dir_name),
+				dependencies: dep_objs)
+		set_variable('dep_' + libname, dep)
+
+		dpdk_libraries = [lib] + dpdk_libraries
+	endif
+endforeach
-- 
2.13.5

^ permalink raw reply	[relevance 1%]

* [dpdk-dev] [PATCH 16/17] build: add option to version libs using DPDK version
      2017-09-01 10:04  1% ` [dpdk-dev] [PATCH 04/17] build: add DPDK libraries to build Bruce Richardson
@ 2017-09-01 10:04  3% ` Bruce Richardson
  2017-09-07 17:07  3%   ` [dpdk-dev] [dpdk-dev, " Neil Horman
  2017-09-01 10:04  3% ` [dpdk-dev] [PATCH 17/17] doc: add documentation on how to add new components to DPDK Bruce Richardson
    4 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2017-09-01 10:04 UTC (permalink / raw)
  To: dev; +Cc: Bruce Richardson

Normally, each library has it's own version number based on the ABI.
Add an option to have all libs just use the DPDK version number as the
.so version.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 drivers/meson.build | 8 +++++++-
 lib/meson.build     | 8 +++++++-
 meson_options.txt   | 1 +
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/meson.build b/drivers/meson.build
index d7a614f83..76d610a5b 100644
--- a/drivers/meson.build
+++ b/drivers/meson.build
@@ -92,6 +92,12 @@ foreach class:driver_classes
 						depends: [pmdinfogen, tmp_lib])
 			endforeach
 
+			if get_option('per_library_versions')
+				so_version = '@0@.1'.format(version)
+			else
+				so_version = meson.project_version()
+			endif
+
 			# now build the driver itself, and add to the drivers list
 			lib_name = driver_name_fmt.format(name)
 			version_map = '@0@/@1@/@2@_version.map'.format(
@@ -105,7 +111,7 @@ foreach class:driver_classes
 				c_args: cflags,
 				link_args: '-Wl,--version-script=' + version_map,
 				link_depends: version_map,
-				version: '@0@.1'.format(version),
+				version: so_version,
 				install: true,
 				install_dir: driver_install_path)
 
diff --git a/lib/meson.build b/lib/meson.build
index b8c4304de..e20a9ab59 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -76,6 +76,12 @@ foreach l:libraries
 			dep_objs += [get_variable('dep_rte_' + d)]
 		endforeach
 
+		if get_option('per_library_versions')
+			so_version = '@0@.1'.format(version)
+		else
+			so_version = meson.project_version()
+		endif
+
 		version_map = '@0@/@1@/rte_@2@_version.map'.format(
 				meson.current_source_dir(), dir_name, name)
 		libname = 'rte_' + name
@@ -87,7 +93,7 @@ foreach l:libraries
 				include_directories: include_directories(dir_name),
 				link_args: '-Wl,--version-script=' + version_map,
 				link_depends: version_map,
-				version: '@0@.1'.format(version),
+				version: so_version,
 				install: true)
 		dep = declare_dependency(link_with: lib,
 				include_directories: include_directories(dir_name),
diff --git a/meson_options.txt b/meson_options.txt
index 9c45b8159..636226ce8 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -6,3 +6,4 @@ option('allow_invalid_socket_id', type: 'boolean', value: false,
 	description: 'allow out-of-range NUMA socket id\'s for platforms that don\'t report the value correctly')
 option('enable_kmods', type: 'boolean', value: true, description: 'build kernel modules')
 option('kernel_dir', type: 'string', value: '', description: 'path to the kernel for building kernel modules')
+option('per_library_versions', type: 'boolean', value: true, description: 'true: each lib gets its own version number, false: DPDK version used for each lib')
-- 
2.13.5

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH 17/17] doc: add documentation on how to add new components to DPDK
                     ` (2 preceding siblings ...)
  2017-09-01 10:04  3% ` [dpdk-dev] [PATCH 16/17] build: add option to version libs using DPDK version Bruce Richardson
@ 2017-09-01 10:04  3% ` Bruce Richardson
    4 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2017-09-01 10:04 UTC (permalink / raw)
  To: dev; +Cc: Bruce Richardson

Add to the contributors guide details on how to add libraries and drivers
and integrate them with the DPDK build system(s).

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 doc/guides/contributing/coding_style.rst | 214 +++++++++++++++++++++++++++++++
 1 file changed, 214 insertions(+)

diff --git a/doc/guides/contributing/coding_style.rst b/doc/guides/contributing/coding_style.rst
index d8e4a0f9c..3c59cbca5 100644
--- a/doc/guides/contributing/coding_style.rst
+++ b/doc/guides/contributing/coding_style.rst
@@ -702,3 +702,217 @@ All Python code should work with Python 2.7+ and 3.2+ and be compliant with
 `PEP8 (Style Guide for Python Code) <https://www.python.org/dev/peps/pep-0008/>`_.
 
 The ``pep8`` tool can be used for testing compliance with the guidelines.
+
+Integrating with the Build System
+---------------------------------
+
+DPDK supports being built in two different ways:
+
+* using ``make`` - or more specifically "GNU make", i.e. ``gmake`` on FreeBSD
+* using the tools ``meson`` and ``ninja``
+
+Any new library or driver to be integrated into DPDK should support being
+built with both systems. While building using ``make`` is a legacy approach, and
+most build-system enhancements are being done using ``meson`` and ``ninja``
+there are no plans at this time to deprecate the legacy ``make`` build system.
+
+Therefore all new component additions should include both a ``Makefile`` and a
+``meson.build`` file, and should be added to the component lists in both the
+``Makefile`` and ``meson.build`` files in the relevant top-level directory:
+either ``lib`` directory or a ``driver`` subdirectory.
+
+Makefile Contents
+~~~~~~~~~~~~~~~~~
+
+The ``Makefile`` for the component should be of the following format, where
+``<name>`` corresponds to the name of the library in question, e.g. hash,
+lpm, etc. For drivers, the same format of Makefile is used.
+
+.. code-block:: makefile
+
+	# pull in basic DPDK definitions, including whether library is to be
+	# built or not
+	include $(RTE_SDK)/mk/rte.vars.mk
+
+	# library name
+	LIB = librte_<name>.a
+
+	# any library cflags needed. Generally add "-O3 $(WERROR_FLAGS)"
+	CFLAGS += -O3
+	CFLAGS += $(WERROR_FLAGS)
+
+	# the symbol version information for the library, and .so version
+	EXPORT_MAP := rte_<name>_version.map
+	LIBABIVER := 1
+
+	# all source filenames are stored in SRCS-y
+	SRCS-$(CONFIG_RTE_LIBRTE_<NAME>) += rte_<name>.c
+
+	# install includes
+	SYMLINK-$(CONFIG_RTE_LIBRTE_<NAME>)-include += rte_<name>.h
+
+	# pull in rules to build the library
+	include $(RTE_SDK)/mk/rte.lib.mk
+
+Meson Build File Contents - Libraries
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``meson.build`` file for a new DPDK library should be of the following basic
+format.
+
+.. code-block:: python
+
+	sources = files('file1.c', ...)
+	headers = files('file1.c', ...)
+
+
+The will build based on a number of conventions and assumptions within the DPDK
+itself, for example, that the library name is the same as the directory name in
+which the files are stored.
+
+For a library ``meson.build`` file, there are number of variables which can be
+set, some mandatory, others optional. The mandatory fields are:
+
+sources
+	**Default Value = []**.
+	This variable should list out the files to be compiled up to create the
+	library. Files must be specified using the meson ``files()`` function.
+
+
+The optional fields are:
+
+build
+	**Default Value = true.**
+	Used to optionally compile a library, based on its dependencies or
+	environment. A simple example of use would be:
+
+.. code-block:: python
+
+	if host_machine.system() != 'linux'
+	        build = false
+	endif
+
+
+cflags
+	**Default Value = []**.
+	Used to specify any additional cflags that need to be passed to compile
+	the sources in the library.
+
+deps
+	**Default Value = ['eal']**.
+	Used to list the internal library dependencies of the library. It should
+	be assigned to using ``+=`` rather than overwriting using ``=``.  The
+	dependencies should be specified as strings, each one giving the name of
+	a DPDK library, without the ``librte_`` prefix. Dependencies are handled
+	recursively, so specifying e.g. ``mempool``, will automatically also
+	make the library depend upon the mempool library's dependencies too -
+	``ring`` and ``eal``. For libraries that only depend upon EAL, this
+	variable may be omitted from the ``meson.build`` file.  For example:
+
+.. code-block:: python
+
+	deps += ['ethdev']
+
+
+ext_deps
+	**Default Value = []**.
+	Used to specify external dependencies of this library. They should be
+	returned as dependency objects, as returned from the meson
+	``dependency()`` or ``find_library()`` functions. Before returning
+	these, they should be checked to ensure the dependencies have been
+	found, and, if not, the ``build`` variable should be set to ``false``.
+	For example:
+
+.. code-block:: python
+
+	my_dep = dependency('libX', required: 'false')
+	if my_dep.found()
+		ext_deps += my_dep
+	else
+		build = false
+	endif
+
+
+headers
+	**Default Value = []**.
+	Used to return the list of header files for the library that should be
+	installed to $PREFIX/include when ``ninja install`` is run. As with
+	source files, these should be specified using the meson ``files()``
+	function.
+
+name
+	**Default Value = library name derived from the directory name**.
+	If a library's .so or .a file differs from that given in the directory
+	name, the name should be specified using this variable. In practice,
+	since the convention is that for a library called ``librte_xyz.so``, the
+	sources are stored in a directory ``lib/librte_xyz``, this value should
+	never be needed for new libraries.
+
+.. note::
+
+	The name value also provides the name used to find the function version
+	map file, as part of the build process, so if the directory name and
+	library names differ, the ``version.map`` file should be named
+	consistently with the library, not the directory
+
+objs
+	**Default Value = []**.
+	This variable can be used to pass to the library build some pre-built
+	objects that were compiled up as part of another target given in the
+	included library ``meson.build`` file.
+
+version
+	**Default Value = 1**.
+	Specifies the ABI version of the library, and is used as the major
+	version number of the resulting ``.so`` library.
+
+Meson Build File Contents - Drivers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For drivers, the values are largely the same as for libraries. The variables
+supported are:
+
+build
+	As above.
+
+cflags
+	As above.
+
+deps
+	As above.
+
+ext_deps
+	As above.
+
+includes
+	**Default Value = <driver directory>** Some drivers include a base
+	directory for additional source files and headers, so we have this
+	variable to allow the headers from that base directory to be found when
+	compiling driver sources. Should be appended to using ``+=`` rather than
+	overwritten using ``=``.  The values appended should be meson include
+	objects got using the ``include_directories()`` function. For example:
+
+.. code-block:: python
+
+	includes += include_directories('base')
+
+name
+	As above, though note that each driver class can define it's own naming
+	scheme for the resulting ``.so`` files.
+
+objs
+	As above, generally used for the contents of the ``base`` directory.
+
+pkgconfig_extra_libs
+	**Default Value = []**
+	This variable is used to pass additional library link flags through to
+	the DPDK pkgconfig file generated, for example, to track any additional
+	libraries that may need to be linked into the build - especially when
+	using static libraries. Anything added here will be appended to the end
+	of the ``pkgconfig --libs`` output.
+
+sources [mandatory]
+	As above
+
+version
+	As above
-- 
2.13.5

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v4] ethdev: allow returning error on VLAN offload configuration
  2017-09-01  7:41  0%       ` Hemant Agrawal
@ 2017-09-01 12:54  0%         ` David Harton (dharton)
  0 siblings, 0 replies; 200+ results
From: David Harton (dharton) @ 2017-09-01 12:54 UTC (permalink / raw)
  To: Hemant Agrawal, thomas, ferruh.yigit, ajit.khaparde,
	John Daley (johndale),
	konstantin.ananyev, jingjing.wu, beilei.xing, jing.d.chen,
	adrien.mazarguil, nelio.laranjeiro, alejandro.lucero,
	rasesh.mody, harish.patil, skhare, yliu, maxime.coquelin,
	allain.legacy
  Cc: dev



> -----Original Message-----
> From: Hemant Agrawal [mailto:hemant.agrawal@nxp.com]
> Sent: Friday, September 01, 2017 3:41 AM
> To: David Harton (dharton) <dharton@cisco.com>; thomas@monjalon.net;
> ferruh.yigit@intel.com; ajit.khaparde@broadcom.com; John Daley (johndale)
> <johndale@cisco.com>; konstantin.ananyev@intel.com; jingjing.wu@intel.com;
> beilei.xing@intel.com; jing.d.chen@intel.com; adrien.mazarguil@6wind.com;
> nelio.laranjeiro@6wind.com; alejandro.lucero@netronome.com;
> rasesh.mody@cavium.com; harish.patil@cavium.com; skhare@vmware.com;
> yliu@fridaylinux.org; maxime.coquelin@redhat.com;
> allain.legacy@windriver.com
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v4] ethdev: allow returning error on VLAN offload
> configuration
> 
> On 9/1/2017 8:06 AM, David Harton wrote:
> > Some devices may not support or fail setting VLAN offload
> > configuration based on dynamic circurmstances so the
> > vlan_offload_set_t vector is modified to return an int so the caller
> > can determine success or not.
> >
> > rte_eth_dev_set_vlan_offload is updated to return the value provided
> > by the vector when called along with restoring the original offload
> > configs on failure.
> >
> > Existing vlan_offload_set_t vectors are modified to return an int.
> > Majority of cases return 0 but a few that actually can fail now return
> > their failure codes.
> >
> > Finally, a vlan_offload_set_t vector is added to virtio to facilitate
> > dynamically turning VLAN strip on or off.
> >
> > Signed-off-by: David Harton <dharton@cisco.com>
> > ---
> >
> > v4
> > * Modified commit message heading
> > * Moved rel_note comments from ABI to API section
> > * Renamed locals of rte_eth_dev_set_vlan_offload from 'org*' to 'orig*'
> >
> > v3
> > * Fixed a format error.
> > * Apologies...need to figure out why checkpatches.pl keeps saying
> >   valid patch when I've got soft tabs.
> >
> > v2
> > * Fixed a missed format error.
> > * Removed vlan offload vector call casts and replaced with checks
> >   for return values.
> >
> > v1
> > * This is an ABI breakage that has been previously negotiated
> >   with Thomas and the proposed rel note change is included as well.
> >
> >  doc/guides/rel_notes/release_17_11.rst |  8 +++++++-
> >  drivers/net/avp/avp_ethdev.c           | 12 +++++++++---
> >  drivers/net/bnxt/bnxt_ethdev.c         |  9 ++++++---
> >  drivers/net/dpaa2/dpaa2_ethdev.c       | 13 ++++++++++---
> >  drivers/net/e1000/em_ethdev.c          | 12 +++++++++---
> >  drivers/net/e1000/igb_ethdev.c         | 12 +++++++++---
> >  drivers/net/enic/enic_ethdev.c         |  8 +++++---
> >  drivers/net/fm10k/fm10k_ethdev.c       |  3 ++-
> >  drivers/net/i40e/i40e_ethdev.c         | 11 ++++++++---
> >  drivers/net/i40e/i40e_ethdev_vf.c      |  9 ++++++---
> >  drivers/net/ixgbe/ixgbe_ethdev.c       | 25 ++++++++++++++++++-------
> >  drivers/net/mlx5/mlx5.h                |  2 +-
> >  drivers/net/mlx5/mlx5_vlan.c           |  3 ++-
> >  drivers/net/nfp/nfp_net.c              | 13 +++++++------
> >  drivers/net/qede/qede_ethdev.c         |  9 +++++++--
> >  drivers/net/virtio/virtio_ethdev.c     | 21 +++++++++++++++++++++
> >  drivers/net/vmxnet3/vmxnet3_ethdev.c   | 10 +++++++---
> >  lib/librte_ether/rte_ethdev.c          | 28 ++++++++++++++++++++-------
> -
> >  lib/librte_ether/rte_ethdev.h          |  2 +-
> >  19 files changed, 155 insertions(+), 55 deletions(-)
> >
> > diff --git a/doc/guides/rel_notes/release_17_11.rst
> > b/doc/guides/rel_notes/release_17_11.rst
> > index 170f4f9..22df4fd 100644
> > --- a/doc/guides/rel_notes/release_17_11.rst
> > +++ b/doc/guides/rel_notes/release_17_11.rst
> > @@ -110,6 +110,13 @@ API Changes
> >     Also, make sure to start the actual text at the margin.
> >     =========================================================
> >
> > +* **Modified the vlan_offload_set_t function prototype in the ethdev
> > +library.**
> > +
> > +  Changed the function prototype of ``vlan_offload_set_t``.  The
> > + return value  has been changed from ``void`` to ``int`` so the
> > + caller to knows whether  the backing device supports the operation
> > + or if the operation was  successfully performed.
> > +
> >
> >  ABI Changes
> >  -----------
> > @@ -125,7 +132,6 @@ ABI Changes
> >     =========================================================
> >
> >
> > -
> >  Shared Library Versions
> >  -----------------------
> >
> > diff --git a/drivers/net/avp/avp_ethdev.c
> > b/drivers/net/avp/avp_ethdev.c index c746a0e..4011dfa 100644
> > --- a/drivers/net/avp/avp_ethdev.c
> > +++ b/drivers/net/avp/avp_ethdev.c
> > @@ -70,7 +70,7 @@ static int avp_dev_create(struct rte_pci_device
> > *pci_dev,  static void avp_dev_close(struct rte_eth_dev *dev);  static
> > void avp_dev_info_get(struct rte_eth_dev *dev,
> >  			     struct rte_eth_dev_info *dev_info); -static void
> > avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> > +static int avp_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> >  static int avp_dev_link_update(struct rte_eth_dev *dev, int
> > wait_to_complete);  static void avp_dev_promiscuous_enable(struct
> > rte_eth_dev *dev);  static void avp_dev_promiscuous_disable(struct
> > rte_eth_dev *dev); @@ -2031,7 +2031,12 @@ struct avp_queue {
> >  	mask = (ETH_VLAN_STRIP_MASK |
> >  		ETH_VLAN_FILTER_MASK |
> >  		ETH_VLAN_EXTEND_MASK);
> > -	avp_vlan_offload_set(eth_dev, mask);
> > +	ret = avp_vlan_offload_set(eth_dev, mask);
> > +	if (ret < 0) {
> > +		PMD_DRV_LOG(ERR, "VLAN offload set failed by host, ret=%d\n",
> > +			    ret);
> > +		goto unlock;
> > +	}
> >
> >  	/* update device config */
> >  	memset(&config, 0, sizeof(config));
> > @@ -2214,7 +2219,7 @@ struct avp_queue {
> >  	}
> >  }
> >
> > -static void
> > +static int
> >  avp_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)  {
> >  	struct avp_dev *avp =
> > AVP_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
> > @@ -2239,6 +2244,7 @@ struct avp_queue {
> >  		if (eth_dev->data->dev_conf.rxmode.hw_vlan_extend)
> >  			PMD_DRV_LOG(ERR, "VLAN extend offload not supported\n");
> >  	}
> > +	return 0;
> >  }
> >
> >  static void
> > diff --git a/drivers/net/bnxt/bnxt_ethdev.c
> > b/drivers/net/bnxt/bnxt_ethdev.c index c9d1122..547bd55 100644
> > --- a/drivers/net/bnxt/bnxt_ethdev.c
> > +++ b/drivers/net/bnxt/bnxt_ethdev.c
> > @@ -144,7 +144,7 @@
> >  	ETH_RSS_NONFRAG_IPV6_TCP |	\
> >  	ETH_RSS_NONFRAG_IPV6_UDP)
> >
> > -static void bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int
> > mask);
> > +static int bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int
> > +mask);
> >
> >  /***********************/
> >
> > @@ -522,7 +522,9 @@ static int bnxt_dev_start_op(struct rte_eth_dev
> *eth_dev)
> >  		vlan_mask |= ETH_VLAN_FILTER_MASK;
> >  	if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip)
> >  		vlan_mask |= ETH_VLAN_STRIP_MASK;
> > -	bnxt_vlan_offload_set_op(eth_dev, vlan_mask);
> > +	rc = bnxt_vlan_offload_set_op(eth_dev, vlan_mask);
> > +	if (rc)
> > +		goto error;
> >
> >  	return 0;
> >
> > @@ -1275,7 +1277,7 @@ static int bnxt_vlan_filter_set_op(struct
> rte_eth_dev *eth_dev,
> >  		return bnxt_del_vlan_filter(bp, vlan_id);  }
> >
> > -static void
> > +static int
> >  bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask)  {
> >  	struct bnxt *bp = (struct bnxt *)dev->data->dev_private; @@ -1307,6
> > +1309,7 @@ static int bnxt_vlan_filter_set_op(struct rte_eth_dev
> > *eth_dev,
> >
> >  	if (mask & ETH_VLAN_EXTEND_MASK)
> >  		RTE_LOG(ERR, PMD, "Extend VLAN Not supported\n");
> > +	return 0;
> >  }
> >
> >  static void
> > diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c
> > b/drivers/net/dpaa2/dpaa2_ethdev.c
> > index 429b3a0..3390cb3 100644
> > --- a/drivers/net/dpaa2/dpaa2_ethdev.c
> > +++ b/drivers/net/dpaa2/dpaa2_ethdev.c
> > @@ -138,7 +138,7 @@
> >  	return ret;
> >  }
> >
> > -static void
> > +static int
> >  dpaa2_vlan_offload_set(struct rte_eth_dev *dev, int mask)  {
> >  	struct dpaa2_dev_priv *priv = dev->data->dev_private; @@ -158,6
> > +158,7 @@
> >  			RTE_LOG(ERR, PMD, "Unable to set vlan filter = %d\n",
> >  				ret);
> >  	}
> > +	return 0;
> >  }
> >
> >  static int
> > @@ -643,8 +644,14 @@
> >  		return ret;
> >  	}
> >  	/* VLAN Offload Settings */
> > -	if (priv->max_vlan_filters)
> > -		dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
> > +	if (priv->max_vlan_filters) {
> > +		ret = dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
> > +		if (ret) {
> > +			PMD_INIT_LOG(ERR, "Error to dpaa2_vlan_offload_set:"
> > +				     "code = %d\n", ret);
> > +			return ret;
> > +		}
> > +	}
> >
> >  	return 0;
> >  }
> > diff --git a/drivers/net/e1000/em_ethdev.c
> > b/drivers/net/e1000/em_ethdev.c index 3d4ab93..51f49d8 100644
> > --- a/drivers/net/e1000/em_ethdev.c
> > +++ b/drivers/net/e1000/em_ethdev.c
> > @@ -99,7 +99,7 @@ static int eth_em_interrupt_action(struct
> > rte_eth_dev *dev,
> >
> >  static int eth_em_vlan_filter_set(struct rte_eth_dev *dev,
> >  		uint16_t vlan_id, int on);
> > -static void eth_em_vlan_offload_set(struct rte_eth_dev *dev, int
> > mask);
> > +static int eth_em_vlan_offload_set(struct rte_eth_dev *dev, int
> > +mask);
> >  static void em_vlan_hw_filter_enable(struct rte_eth_dev *dev);
> > static void em_vlan_hw_filter_disable(struct rte_eth_dev *dev);
> > static void em_vlan_hw_strip_enable(struct rte_eth_dev *dev); @@
> > -668,7 +668,12 @@ static int eth_em_pci_remove(struct rte_pci_device
> > *pci_dev)
> >
> >  	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
> >  			ETH_VLAN_EXTEND_MASK;
> > -	eth_em_vlan_offload_set(dev, mask);
> > +	ret = eth_em_vlan_offload_set(dev, mask);
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR, "Unable to update vlan offload");
> > +		em_dev_clear_queues(dev);
> > +		return ret;
> > +	}
> >
> >  	/* Set Interrupt Throttling Rate to maximum allowed value. */
> >  	E1000_WRITE_REG(hw, E1000_ITR, UINT16_MAX); @@ -1447,7 +1452,7 @@
> > static int eth_em_pci_remove(struct rte_pci_device *pci_dev)
> >  	E1000_WRITE_REG(hw, E1000_CTRL, reg);  }
> >
> > -static void
> > +static int
> >  eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask)  {
> >  	if(mask & ETH_VLAN_STRIP_MASK){
> > @@ -1463,6 +1468,7 @@ static int eth_em_pci_remove(struct rte_pci_device
> *pci_dev)
> >  		else
> >  			em_vlan_hw_filter_disable(dev);
> >  	}
> > +	return 0;
> >  }
> >
> >  /*
> > diff --git a/drivers/net/e1000/igb_ethdev.c
> > b/drivers/net/e1000/igb_ethdev.c index e4f7a9f..fa15ee9 100644
> > --- a/drivers/net/e1000/igb_ethdev.c
> > +++ b/drivers/net/e1000/igb_ethdev.c
> > @@ -157,7 +157,7 @@ static int eth_igb_vlan_filter_set(struct
> > rte_eth_dev *dev,  static int eth_igb_vlan_tpid_set(struct rte_eth_dev
> *dev,
> >  				 enum rte_vlan_type vlan_type,
> >  				 uint16_t tpid_id);
> > -static void eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int
> > mask);
> > +static int eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int
> > +mask);
> >
> >  static void igb_vlan_hw_filter_enable(struct rte_eth_dev *dev);
> > static void igb_vlan_hw_filter_disable(struct rte_eth_dev *dev); @@
> > -1400,7 +1400,12 @@ static int eth_igbvf_pci_remove(struct
> rte_pci_device *pci_dev)
> >  	 */
> >  	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
> >  			ETH_VLAN_EXTEND_MASK;
> > -	eth_igb_vlan_offload_set(dev, mask);
> > +	ret = eth_igb_vlan_offload_set(dev, mask);
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR, "Unable to set vlan offload");
> > +		igb_dev_clear_queues(dev);
> > +		return ret;
> > +	}
> >
> >  	if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) {
> >  		/* Enable VLAN filter since VMDq always use VLAN filter */ @@
> > -2715,7 +2720,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused
> struct rte_eth_dev *dev,
> >  						2 * VLAN_TAG_SIZE);
> >  }
> >
> > -static void
> > +static int
> >  eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask)  {
> >  	if(mask & ETH_VLAN_STRIP_MASK){
> > @@ -2738,6 +2743,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused
> struct rte_eth_dev *dev,
> >  		else
> >  			igb_vlan_hw_extend_disable(dev);
> >  	}
> > +	return 0;
> >  }
> >
> >
> > diff --git a/drivers/net/enic/enic_ethdev.c
> > b/drivers/net/enic/enic_ethdev.c index da8fec2..fc1eac2 100644
> > --- a/drivers/net/enic/enic_ethdev.c
> > +++ b/drivers/net/enic/enic_ethdev.c
> > @@ -347,7 +347,7 @@ static int enicpmd_vlan_filter_set(struct
> rte_eth_dev *eth_dev,
> >  	return err;
> >  }
> >
> > -static void enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int
> > mask)
> > +static int enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int
> > +mask)
> >  {
> >  	struct enic *enic = pmd_priv(eth_dev);
> >
> > @@ -371,6 +371,8 @@ static void enicpmd_vlan_offload_set(struct
> rte_eth_dev *eth_dev, int mask)
> >  		dev_warning(enic,
> >  			"Configuration of extended VLAN is not supported\n");
> >  	}
> > +
> > +	return 0;
> >  }
> >
> >  static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev) @@
> > -392,9 +394,9 @@ static int enicpmd_dev_configure(struct rte_eth_dev
> *eth_dev)
> >  			eth_dev->data->dev_conf.rxmode.split_hdr_size);
> >  	}
> >
> > -	enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
> > +	ret = enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
> >  	enic->hw_ip_checksum = eth_dev->data-
> >dev_conf.rxmode.hw_ip_checksum;
> > -	return 0;
> > +	return ret;
> >  }
> >
> >  /* Start the device.
> > diff --git a/drivers/net/fm10k/fm10k_ethdev.c
> > b/drivers/net/fm10k/fm10k_ethdev.c
> > index e60d3a3..f4626f7 100644
> > --- a/drivers/net/fm10k/fm10k_ethdev.c
> > +++ b/drivers/net/fm10k/fm10k_ethdev.c
> > @@ -1590,7 +1590,7 @@ static int fm10k_xstats_get_names(__rte_unused
> struct rte_eth_dev *dev,
> >  	return 0;
> >  }
> >
> > -static void
> > +static int
> >  fm10k_vlan_offload_set(struct rte_eth_dev *dev, int mask)  {
> >  	if (mask & ETH_VLAN_STRIP_MASK) {
> > @@ -1609,6 +1609,7 @@ static int fm10k_xstats_get_names(__rte_unused
> struct rte_eth_dev *dev,
> >  		if (!dev->data->dev_conf.rxmode.hw_vlan_filter)
> >  			PMD_INIT_LOG(ERR, "VLAN filter is always on in fm10k");
> >  	}
> > +	return 0;
> >  }
> >
> >  /* Add/Remove a MAC address, and update filters to main VSI */ diff
> > --git a/drivers/net/i40e/i40e_ethdev.c
> > b/drivers/net/i40e/i40e_ethdev.c index 00b6082..d03a44b 100644
> > --- a/drivers/net/i40e/i40e_ethdev.c
> > +++ b/drivers/net/i40e/i40e_ethdev.c
> > @@ -278,7 +278,7 @@ static int i40e_vlan_filter_set(struct rte_eth_dev
> > *dev,  static int i40e_vlan_tpid_set(struct rte_eth_dev *dev,
> >  			      enum rte_vlan_type vlan_type,
> >  			      uint16_t tpid);
> > -static void i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> > +static int i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> >  static void i40e_vlan_strip_queue_set(struct rte_eth_dev *dev,
> >  				      uint16_t queue,
> >  				      int on);
> > @@ -3130,7 +3130,7 @@ static int i40e_dev_xstats_get_names(__rte_unused
> struct rte_eth_dev *dev,
> >  	return ret;
> >  }
> >
> > -static void
> > +static int
> >  i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask)  {
> >  	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> > @@ -3163,6 +3163,7 @@ static int i40e_dev_xstats_get_names(__rte_unused
> struct rte_eth_dev *dev,
> >  		else
> >  			i40e_vsi_config_double_vlan(vsi, FALSE);
> >  	}
> > +	return 0;
> >  }
> >
> >  static void
> > @@ -5216,7 +5217,11 @@ struct i40e_vsi *
> >
> >  	/* Apply vlan offload setting */
> >  	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK;
> > -	i40e_vlan_offload_set(dev, mask);
> > +	ret = i40e_vlan_offload_set(dev, mask);
> > +	if (ret) {
> > +		PMD_DRV_LOG(INFO, "Failed to update vlan offload");
> > +		return ret;
> > +	}
> >
> >  	/* Apply double-vlan setting, not implemented yet */
> >
> > diff --git a/drivers/net/i40e/i40e_ethdev_vf.c
> > b/drivers/net/i40e/i40e_ethdev_vf.c
> > index f6d8293..f7fffc2 100644
> > --- a/drivers/net/i40e/i40e_ethdev_vf.c
> > +++ b/drivers/net/i40e/i40e_ethdev_vf.c
> > @@ -118,7 +118,7 @@ static int i40evf_dev_xstats_get_names(struct
> > rte_eth_dev *dev,  static void i40evf_dev_xstats_reset(struct
> > rte_eth_dev *dev);  static int i40evf_vlan_filter_set(struct rte_eth_dev
> *dev,
> >  				  uint16_t vlan_id, int on);
> > -static void i40evf_vlan_offload_set(struct rte_eth_dev *dev, int
> > mask);
> > +static int i40evf_vlan_offload_set(struct rte_eth_dev *dev, int
> > +mask);
> >  static int i40evf_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t pvid,
> >  				int on);
> >  static void i40evf_dev_close(struct rte_eth_dev *dev); @@ -1634,7
> > +1634,9 @@ static int eth_i40evf_pci_remove(struct rte_pci_device
> *pci_dev)
> >  	int ret;
> >
> >  	/* Apply vlan offload setting */
> > -	i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
> > +	ret = i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
> > +	if (ret)
> > +		return ret;
> >
> >  	/* Apply pvid setting */
> >  	ret = i40evf_vlan_pvid_set(dev, data->dev_conf.txmode.pvid, @@
> > -1642,7 +1644,7 @@ static int eth_i40evf_pci_remove(struct
> rte_pci_device *pci_dev)
> >  	return ret;
> >  }
> >
> > -static void
> > +static int
> >  i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask)  {
> >  	struct rte_eth_conf *dev_conf = &dev->data->dev_conf; @@ -1655,6
> > +1657,7 @@ static int eth_i40evf_pci_remove(struct rte_pci_device
> *pci_dev)
> >  		else
> >  			i40evf_disable_vlan_strip(dev);
> >  	}
> > +	return 0;
> >  }
> >
> >  static int
> > diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
> > b/drivers/net/ixgbe/ixgbe_ethdev.c
> > index 22171d8..1ec5aaf 100644
> > --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> > +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> > @@ -218,7 +218,7 @@ static void ixgbe_vlan_hw_strip_bitmap_set(struct
> rte_eth_dev *dev,
> >  		uint16_t queue, bool on);
> >  static void ixgbe_vlan_strip_queue_set(struct rte_eth_dev *dev,
> uint16_t queue,
> >  		int on);
> > -static void ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int
> > mask);
> > +static int ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> >  static void ixgbe_vlan_hw_strip_enable(struct rte_eth_dev *dev,
> > uint16_t queue);  static void ixgbe_vlan_hw_strip_disable(struct
> > rte_eth_dev *dev, uint16_t queue);  static void
> > ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev); @@ -274,7 +274,7
> @@ static int ixgbevf_vlan_filter_set(struct rte_eth_dev *dev,
> >  		uint16_t vlan_id, int on);
> >  static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev,
> >  		uint16_t queue, int on);
> > -static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int
> > mask);
> > +static int ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int
> > +mask);
> >  static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on);
> > static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
> >  					    uint16_t queue_id);
> > @@ -2125,7 +2125,7 @@ static int eth_ixgbevf_pci_remove(struct
> rte_pci_device *pci_dev)
> >  	 */
> >  }
> >
> > -static void
> > +static int
> >  ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask)  {
> >  	if (mask & ETH_VLAN_STRIP_MASK) {
> > @@ -2148,6 +2148,7 @@ static int eth_ixgbevf_pci_remove(struct
> rte_pci_device *pci_dev)
> >  		else
> >  			ixgbe_vlan_hw_extend_disable(dev);
> >  	}
> > +	return 0;
> >  }
> >
> >  static void
> > @@ -2568,9 +2569,13 @@ static int eth_ixgbevf_pci_remove(struct
> rte_pci_device *pci_dev)
> >  		goto error;
> >  	}
> >
> > -    mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
> > +	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
> >  		ETH_VLAN_EXTEND_MASK;
> > -	ixgbe_vlan_offload_set(dev, mask);
> > +	err = ixgbe_vlan_offload_set(dev, mask);
> > +	if (err) {
> > +		PMD_INIT_LOG(ERR, "Unable to set VLAN offload");
> > +		goto error;
> > +	}
> >
> >  	if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) {
> >  		/* Enable vlan filtering for VMDq */ @@ -4993,7 +4998,12 @@
> static
> > int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
> >  	/* Set HW strip */
> >  	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
> >  		ETH_VLAN_EXTEND_MASK;
> > -	ixgbevf_vlan_offload_set(dev, mask);
> > +	err = ixgbevf_vlan_offload_set(dev, mask);
> > +	if (err) {
> > +		PMD_INIT_LOG(ERR, "Unable to set VLAN offload (%d)", err);
> > +		ixgbe_dev_clear_queues(dev);
> > +		return err;
> > +	}
> >
> >  	ixgbevf_dev_rxtx_start(dev);
> >
> > @@ -5153,7 +5163,7 @@ static void ixgbevf_set_vfta_all(struct
> rte_eth_dev *dev, bool on)
> >  	ixgbe_vlan_hw_strip_bitmap_set(dev, queue, on);  }
> >
> > -static void
> > +static int
> >  ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask)  {
> >  	struct ixgbe_hw *hw =
> > @@ -5168,6 +5178,7 @@ static void ixgbevf_set_vfta_all(struct
> rte_eth_dev *dev, bool on)
> >  		for (i = 0; i < hw->mac.max_rx_queues; i++)
> >  			ixgbevf_vlan_strip_queue_set(dev, i, on);
> >  	}
> > +	return 0;
> >  }
> >
> >  int
> > diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index
> > 43c5384..93e71be 100644
> > --- a/drivers/net/mlx5/mlx5.h
> > +++ b/drivers/net/mlx5/mlx5.h
> > @@ -283,7 +283,7 @@ int mlx5_xstats_get_names(struct rte_eth_dev *,
> >  /* mlx5_vlan.c */
> >
> >  int mlx5_vlan_filter_set(struct rte_eth_dev *, uint16_t, int); -void
> > mlx5_vlan_offload_set(struct rte_eth_dev *, int);
> > +int mlx5_vlan_offload_set(struct rte_eth_dev *, int);
> >  void mlx5_vlan_strip_queue_set(struct rte_eth_dev *, uint16_t, int);
> >
> >  /* mlx5_trigger.c */
> > diff --git a/drivers/net/mlx5/mlx5_vlan.c
> > b/drivers/net/mlx5/mlx5_vlan.c index 1b0fa40..7215909 100644
> > --- a/drivers/net/mlx5/mlx5_vlan.c
> > +++ b/drivers/net/mlx5/mlx5_vlan.c
> > @@ -210,7 +210,7 @@
> >   * @param mask
> >   *   VLAN offload bit mask.
> >   */
> > -void
> > +int
> >  mlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask)  {
> >  	struct priv *priv = dev->data->dev_private; @@ -230,4 +230,5 @@
> >  			priv_vlan_strip_queue_set(priv, i, hw_vlan_strip);
> >  		priv_unlock(priv);
> >  	}
> > +	return 0;
> >  }
> > diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
> > index 92b03c4..6473edc 100644
> > --- a/drivers/net/nfp/nfp_net.c
> > +++ b/drivers/net/nfp/nfp_net.c
> > @@ -2149,11 +2149,12 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq
> *txq)
> >  	return i;
> >  }
> >
> > -static void
> > +static int
> >  nfp_net_vlan_offload_set(struct rte_eth_dev *dev, int mask)  {
> >  	uint32_t new_ctrl, update;
> >  	struct nfp_net_hw *hw;
> > +	int ret;
> >
> >  	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
> >  	new_ctrl = 0;
> > @@ -2174,14 +2175,14 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq
> *txq)
> >  		new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_RXVLAN;
> >
> >  	if (new_ctrl == 0)
> > -		return;
> > +		return 0;
> >
> >  	update = NFP_NET_CFG_UPDATE_GEN;
> >
> > -	if (nfp_net_reconfig(hw, new_ctrl, update) < 0)
> > -		return;
> > -
> > -	hw->ctrl = new_ctrl;
> > +	ret = nfp_net_reconfig(hw, new_ctrl, update);
> > +	if (!ret)
> > +		hw->ctrl = new_ctrl;
> > +	return ret;
> >  }
> >
> >  /* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet
> device */
> > diff --git a/drivers/net/qede/qede_ethdev.c
> b/drivers/net/qede/qede_ethdev.c
> > index 0e05989..644f69d 100644
> > --- a/drivers/net/qede/qede_ethdev.c
> > +++ b/drivers/net/qede/qede_ethdev.c
> > @@ -975,7 +975,7 @@ static int qede_vlan_filter_set(struct rte_eth_dev
> *eth_dev,
> >  	return rc;
> >  }
> >
> > -static void qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int
> mask)
> > +static int qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
> >  {
> >  	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
> >  	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
> > @@ -1013,6 +1013,8 @@ static void qede_vlan_offload_set(struct
> rte_eth_dev *eth_dev, int mask)
> >
> >  	DP_INFO(edev, "vlan offload mask %d vlan-strip %d vlan-filter %d\n",
> >  		mask, rxmode->hw_vlan_strip, rxmode->hw_vlan_filter);
> > +
> > +	return 0;
> >  }
> >
> >  static void qede_prandom_bytes(uint32_t *buff)
> > @@ -1157,6 +1159,7 @@ static int qede_dev_configure(struct rte_eth_dev
> *eth_dev)
> >  	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
> >  	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
> >  	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
> > +	int ret;
> >
> >  	PMD_INIT_FUNC_TRACE(edev);
> >
> > @@ -1237,9 +1240,11 @@ static int qede_dev_configure(struct rte_eth_dev
> *eth_dev)
> >  	qdev->enable_lro = rxmode->enable_lro;
> >
> >  	/* Enable VLAN offloads by default */
> > -	qede_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK  |
> > +	ret = qede_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK  |
> >  			ETH_VLAN_FILTER_MASK |
> >  			ETH_VLAN_EXTEND_MASK);
> > +	if (ret)
> > +		return ret;
> >
> >  	DP_INFO(edev, "Device configured with RSS=%d TSS=%d\n",
> >  			QEDE_RSS_COUNT(qdev), QEDE_TSS_COUNT(qdev));
> > diff --git a/drivers/net/virtio/virtio_ethdev.c
> b/drivers/net/virtio/virtio_ethdev.c
> > index e320811..72b4248 100644
> > --- a/drivers/net/virtio/virtio_ethdev.c
> > +++ b/drivers/net/virtio/virtio_ethdev.c
> > @@ -72,6 +72,7 @@ static void virtio_dev_info_get(struct rte_eth_dev
> *dev,
> >  				struct rte_eth_dev_info *dev_info);
> >  static int virtio_dev_link_update(struct rte_eth_dev *dev,
> >  	int wait_to_complete);
> > +static int virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int
> mask);
> >
> >  static void virtio_set_hwaddr(struct virtio_hw *hw);
> >  static void virtio_get_hwaddr(struct virtio_hw *hw);
> > @@ -779,6 +780,7 @@ struct rte_virtio_xstats_name_off {
> >  	.stats_reset             = virtio_dev_stats_reset,
> >  	.xstats_reset            = virtio_dev_stats_reset,
> >  	.link_update             = virtio_dev_link_update,
> > +	.vlan_offload_set        = virtio_dev_vlan_offload_set,
> >  	.rx_queue_setup          = virtio_dev_rx_queue_setup,
> >  	.rx_queue_intr_enable    = virtio_dev_rx_queue_intr_enable,
> >  	.rx_queue_intr_disable   = virtio_dev_rx_queue_intr_disable,
> > @@ -1875,6 +1877,25 @@ static void virtio_dev_free_mbufs(struct
> rte_eth_dev *dev)
> >  	return (old.link_status == link.link_status) ? -1 : 0;
> >  }
> >
> > +static int
> > +virtio_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
> > +{
> > +	const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
> > +	struct virtio_hw *hw = dev->data->dev_private;
> > +
> > +	if (rxmode->hw_vlan_filter &&
> > +	    !vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) {
> > +		PMD_DRV_LOG(NOTICE,
> > +			    "vlan filtering not available on this host");
> > +		return -ENOTSUP;
> > +	}
> > +
> > +	if (mask & ETH_VLAN_STRIP_MASK)
> > +		hw->vlan_strip = rxmode->hw_vlan_strip;
> > +
> > +	return 0;
> > +}
> > +
> >  static void
> >  virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info
> *dev_info)
> >  {
> > diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c
> b/drivers/net/vmxnet3/vmxnet3_ethdev.c
> > index 3910991..06735dd 100644
> > --- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
> > +++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
> > @@ -100,7 +100,7 @@ static void vmxnet3_dev_info_get(struct rte_eth_dev
> *dev,
> >  vmxnet3_dev_supported_ptypes_get(struct rte_eth_dev *dev);
> >  static int vmxnet3_dev_vlan_filter_set(struct rte_eth_dev *dev,
> >  				       uint16_t vid, int on);
> > -static void vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int
> mask);
> > +static int vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int
> mask);
> >  static void vmxnet3_mac_addr_set(struct rte_eth_dev *dev,
> >  				 struct ether_addr *mac_addr);
> >  static void vmxnet3_interrupt_handler(void *param);
> > @@ -730,8 +730,10 @@ static int eth_vmxnet3_pci_remove(struct
> rte_pci_device *pci_dev)
> >  		devRead->rssConfDesc.confPA  = hw->rss_confPA;
> >  	}
> >
> > -	vmxnet3_dev_vlan_offload_set(dev,
> > +	ret = vmxnet3_dev_vlan_offload_set(dev,
> >  				     ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK);
> > +	if (ret)
> > +		return ret;
> >
> >  	vmxnet3_write_mac(hw, dev->data->mac_addrs->addr_bytes);
> >
> > @@ -1275,7 +1277,7 @@ static int eth_vmxnet3_pci_remove(struct
> rte_pci_device *pci_dev)
> >  	return 0;
> >  }
> >
> > -static void
> > +static int
> >  vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
> >  {
> >  	struct vmxnet3_hw *hw = dev->data->dev_private;
> > @@ -1301,6 +1303,8 @@ static int eth_vmxnet3_pci_remove(struct
> rte_pci_device *pci_dev)
> >  		VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
> >  				       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
> >  	}
> > +
> > +	return 0;
> >  }
> >
> >  static void
> > diff --git a/lib/librte_ether/rte_ethdev.c
> b/lib/librte_ether/rte_ethdev.c
> > index 0597641..05e52b8 100644
> > --- a/lib/librte_ether/rte_ethdev.c
> > +++ b/lib/librte_ether/rte_ethdev.c
> > @@ -2048,29 +2048,35 @@ struct rte_eth_dev *
> >  	struct rte_eth_dev *dev;
> >  	int ret = 0;
> >  	int mask = 0;
> > -	int cur, org = 0;
> > +	int cur, orig = 0;
> > +	uint8_t orig_strip, orig_filter, orig_extend;
> >
> >  	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> >  	dev = &rte_eth_devices[port_id];
> >
> > +	/* save original values in case of failure */
> > +	orig_strip = dev->data->dev_conf.rxmode.hw_vlan_strip;
> > +	orig_filter = dev->data->dev_conf.rxmode.hw_vlan_filter;
> > +	orig_extend = dev->data->dev_conf.rxmode.hw_vlan_extend;
> > +
> >  	/*check which option changed by application*/
> >  	cur = !!(offload_mask & ETH_VLAN_STRIP_OFFLOAD);
> > -	org = !!(dev->data->dev_conf.rxmode.hw_vlan_strip);
> > -	if (cur != org) {
> > +	orig = !!(dev->data->dev_conf.rxmode.hw_vlan_strip);
> > +	if (cur != orig) {
> >  		dev->data->dev_conf.rxmode.hw_vlan_strip = (uint8_t)cur;
> >  		mask |= ETH_VLAN_STRIP_MASK;
> >  	}
> >
> >  	cur = !!(offload_mask & ETH_VLAN_FILTER_OFFLOAD);
> > -	org = !!(dev->data->dev_conf.rxmode.hw_vlan_filter);
> > -	if (cur != org) {
> > +	orig = !!(dev->data->dev_conf.rxmode.hw_vlan_filter);
> > +	if (cur != orig) {
> >  		dev->data->dev_conf.rxmode.hw_vlan_filter = (uint8_t)cur;
> >  		mask |= ETH_VLAN_FILTER_MASK;
> >  	}
> >
> >  	cur = !!(offload_mask & ETH_VLAN_EXTEND_OFFLOAD);
> > -	org = !!(dev->data->dev_conf.rxmode.hw_vlan_extend);
> > -	if (cur != org) {
> > +	orig = !!(dev->data->dev_conf.rxmode.hw_vlan_extend);
> > +	if (cur != orig) {
> >  		dev->data->dev_conf.rxmode.hw_vlan_extend = (uint8_t)cur;
> >  		mask |= ETH_VLAN_EXTEND_MASK;
> >  	}
> > @@ -2080,7 +2086,13 @@ struct rte_eth_dev *
> >  		return ret;
> >
> >  	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_offload_set, -ENOTSUP);
> > -	(*dev->dev_ops->vlan_offload_set)(dev, mask);
> > +	ret = (*dev->dev_ops->vlan_offload_set)(dev, mask);
> > +	if (ret) {
> > +		/* hit an error restore  original values */
> > +		dev->data->dev_conf.rxmode.hw_vlan_strip = orig_strip;
> > +		dev->data->dev_conf.rxmode.hw_vlan_filter = orig_filter;
> > +		dev->data->dev_conf.rxmode.hw_vlan_extend = orig_extend;
> > +	}
> >
> Currently vlan offload is combining three functions:
> strip, filter and extend.
> 
> Not all PMDs in DPDK support all of three.
> Should not the error we extended to reflect, which of the VLAN offload
> is not supported?

There are many examples of APIs that not all PMDs support.
There are also other APIs that manipulate many attributes but do
not communicate which attribute fails on set.
Solving these issues I believe it outside the scope of this change
and it requires a larger community discussion.

This proposed change at least adheres to the existing paradigm.

> 
> >  	return ret;
> >  }
> > diff --git a/lib/librte_ether/rte_ethdev.h
> b/lib/librte_ether/rte_ethdev.h
> > index 0adf327..7254fd0 100644
> > --- a/lib/librte_ether/rte_ethdev.h
> > +++ b/lib/librte_ether/rte_ethdev.h
> > @@ -1245,7 +1245,7 @@ typedef int (*vlan_tpid_set_t)(struct rte_eth_dev
> *dev,
> >  			       enum rte_vlan_type type, uint16_t tpid);
> >  /**< @internal set the outer/inner VLAN-TPID by an Ethernet device. */
> >
> > -typedef void (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask);
> > +typedef int (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask);
> >  /**< @internal set VLAN offload function by an Ethernet device. */
> >
> >  typedef int (*vlan_pvid_set_t)(struct rte_eth_dev *dev,
> >

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v2 02/18] net/nfp: add specific PF probe function
  @ 2017-09-01 14:12 11% ` Alejandro Lucero
  2017-09-01 14:12  6% ` [dpdk-dev] [PATCH v2 11/18] net/nfp: allocate ethernet device from " Alejandro Lucero
  2017-09-01 14:12  4% ` [dpdk-dev] [PATCH v2 16/18] doc: update NFP with PF support information Alejandro Lucero
  2 siblings, 0 replies; 200+ results
From: Alejandro Lucero @ 2017-09-01 14:12 UTC (permalink / raw)
  To: dev

Configuring the NFP PMD for using the PF requires access through the
NSPU interface for device configuration. This patch adds a specific probe
function for the PF which uses the NSPU interface. Just basic NSPU access
is done by now reading the NSPU ABI version.

NSPU ABI version needs to be greater than 0.19.

No ethernet port is created yet.

Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
---
 drivers/net/nfp/nfp_net.c | 75 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 69 insertions(+), 6 deletions(-)

diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index a3bf5e1..cb48fdc 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -59,6 +59,8 @@
 #include "nfp_net_logs.h"
 #include "nfp_net_ctrl.h"
 
+#include "nfp_nfpu.h"
+
 /* Prototypes */
 static void nfp_net_close(struct rte_eth_dev *dev);
 static int nfp_net_configure(struct rte_eth_dev *dev);
@@ -2632,12 +2634,63 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
 	return 0;
 }
 
-static const struct rte_pci_id pci_id_nfp_net_map[] = {
+static int nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+			    struct rte_pci_device *dev)
+{
+	nfpu_desc_t *nfpu_desc;
+	nspu_desc_t *nspu_desc;
+	int major, minor;
+
+	if (!dev)
+		return -ENODEV;
+
+	nfpu_desc = rte_malloc("nfp nfpu", sizeof(nfpu_desc_t), 0);
+	if (!nfpu_desc)
+		return -ENOMEM;
+
+	if (nfpu_open(dev, nfpu_desc, 0) < 0) {
+		RTE_LOG(ERR, PMD,
+			"nfpu_open failed\n");
+		goto nfpu_error;
+	}
+
+	nspu_desc = nfpu_desc->nspu;
+
+
+	/* Check NSP ABI version */
+	if (nfp_nsp_get_abi_version(nspu_desc, &major, &minor) < 0) {
+		RTE_LOG(INFO, PMD, "NFP NSP not present\n");
+		goto no_abi;
+	}
+	PMD_INIT_LOG(INFO, "nspu ABI version: %d.%d\n", major, minor);
+
+	if ((major == 0) && (minor < 20)) {
+		RTE_LOG(INFO, PMD, "NFP NSP ABI version too old. Required 0.20 or higher\n");
+		goto no_abi;
+	}
+
+	/* No port is created yet */
+
+no_abi:
+	nfpu_close(nfpu_desc);
+nfpu_error:
+	rte_free(nfpu_desc);
+
+	return -ENODEV;
+}
+
+static const struct rte_pci_id pci_id_nfp_pf_net_map[] = {
 	{
 		RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
 			       PCI_DEVICE_ID_NFP6000_PF_NIC)
 	},
 	{
+		.vendor_id = 0,
+	},
+};
+
+static const struct rte_pci_id pci_id_nfp_vf_net_map[] = {
+	{
 		RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
 			       PCI_DEVICE_ID_NFP6000_VF_NIC)
 	},
@@ -2658,16 +2711,26 @@ static int eth_nfp_pci_remove(struct rte_pci_device *pci_dev)
 	return rte_eth_dev_pci_generic_remove(pci_dev, NULL);
 }
 
-static struct rte_pci_driver rte_nfp_net_pmd = {
-	.id_table = pci_id_nfp_net_map,
+static struct rte_pci_driver rte_nfp_net_pf_pmd = {
+	.id_table = pci_id_nfp_pf_net_map,
+	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
+	.probe = nfp_pf_pci_probe,
+	.remove = eth_nfp_pci_remove,
+};
+
+static struct rte_pci_driver rte_nfp_net_vf_pmd = {
+	.id_table = pci_id_nfp_vf_net_map,
 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 	.probe = eth_nfp_pci_probe,
 	.remove = eth_nfp_pci_remove,
 };
 
-RTE_PMD_REGISTER_PCI(net_nfp, rte_nfp_net_pmd);
-RTE_PMD_REGISTER_PCI_TABLE(net_nfp, pci_id_nfp_net_map);
-RTE_PMD_REGISTER_KMOD_DEP(net_nfp, "* igb_uio | uio_pci_generic | vfio-pci");
+RTE_PMD_REGISTER_PCI(net_nfp_pf, rte_nfp_net_pf_pmd);
+RTE_PMD_REGISTER_PCI(net_nfp_vf, rte_nfp_net_vf_pmd);
+RTE_PMD_REGISTER_PCI_TABLE(net_nfp_pf, pci_id_nfp_pf_net_map);
+RTE_PMD_REGISTER_PCI_TABLE(net_nfp_vf, pci_id_nfp_vf_net_map);
+RTE_PMD_REGISTER_KMOD_DEP(net_nfp_pf, "* igb_uio | uio_pci_generic | vfio");
+RTE_PMD_REGISTER_KMOD_DEP(net_nfp_vf, "* igb_uio | uio_pci_generic | vfio");
 
 /*
  * Local variables:
-- 
1.9.1

^ permalink raw reply	[relevance 11%]

* [dpdk-dev] [PATCH v2 11/18] net/nfp: allocate ethernet device from PF probe function
    2017-09-01 14:12 11% ` [dpdk-dev] [PATCH v2 02/18] net/nfp: add specific PF probe function Alejandro Lucero
@ 2017-09-01 14:12  6% ` Alejandro Lucero
  2017-09-01 14:12  4% ` [dpdk-dev] [PATCH v2 16/18] doc: update NFP with PF support information Alejandro Lucero
  2 siblings, 0 replies; 200+ results
From: Alejandro Lucero @ 2017-09-01 14:12 UTC (permalink / raw)
  To: dev

NFP can support several physical ports per PF device. Depending on
firmware info, one or more eth_dev objects will need to be created.

This patch adds the call to create just one eth_dev by now with future
commits supporting the multiport option. Once the eth_dev has been
created, probe function invokes pmd initialization with the new eth_dev.

Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
---
 drivers/net/nfp/nfp_net.c | 49 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 42 insertions(+), 7 deletions(-)

diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index 021b0ea..5b4108a 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -2677,13 +2677,16 @@ uint32_t nfp_net_txq_full(struct nfp_net_txq *txq)
 static int nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 			    struct rte_pci_device *dev)
 {
+	struct rte_eth_dev *eth_dev;
+	struct nfp_net_hw *hw;
 	nfpu_desc_t *nfpu_desc;
 	nspu_desc_t *nspu_desc;
 	uint64_t offset_symbol;
 	int major, minor;
+	int ret = -ENODEV;
 
 	if (!dev)
-		return -ENODEV;
+		return ret;
 
 	nfpu_desc = rte_malloc("nfp nfpu", sizeof(nfpu_desc_t), 0);
 	if (!nfpu_desc)
@@ -2701,25 +2704,57 @@ static int nfp_pf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	/* Check NSP ABI version */
 	if (nfp_nsp_get_abi_version(nspu_desc, &major, &minor) < 0) {
 		RTE_LOG(INFO, PMD, "NFP NSP not present\n");
-		goto no_abi;
+		goto error;
 	}
 	PMD_INIT_LOG(INFO, "nspu ABI version: %d.%d\n", major, minor);
 
 	if ((major == 0) && (minor < 20)) {
 		RTE_LOG(INFO, PMD, "NFP NSP ABI version too old. Required 0.20 or higher\n");
-		goto no_abi;
+		goto error;
+	}
+
+	ret = nfp_nsp_fw_setup(nspu_desc, "nfd_cfg_pf0_num_ports",
+			       &offset_symbol);
+	if (ret)
+		goto error;
+
+	eth_dev = rte_eth_dev_allocate(dev->device.name);
+	if (!eth_dev) {
+		ret = -ENODEV;
+		goto error;
 	}
 
-	nfp_nsp_fw_setup(nspu_desc, "nfd_cfg_pf0_num_ports", &offset_symbol);
+	eth_dev->data->dev_private = rte_zmalloc("nfp_pf_port",
+						 sizeof(struct nfp_net_adapter),
+						 RTE_CACHE_LINE_SIZE);
+	if (!eth_dev->data->dev_private) {
+		rte_eth_dev_release_port(eth_dev);
+		ret = -ENODEV;
+		goto error;
+	}
+
+	hw = (struct nfp_net_hw *)(eth_dev->data->dev_private);
+	hw->nspu_desc = nspu_desc;
+	hw->nfpu_desc = nfpu_desc;
+	hw->is_pf = 1;
 
-	/* No port is created yet */
+	eth_dev->device = &dev->device;
+	rte_eth_copy_pci_info(eth_dev, dev);
 
-no_abi:
+	ret = nfp_net_init(eth_dev);
+
+	if (!ret)
+		return 0;
+
+	/* something went wrong */
+	rte_eth_dev_release_port(eth_dev);
+
+error:
 	nfpu_close(nfpu_desc);
 nfpu_error:
 	rte_free(nfpu_desc);
 
-	return -ENODEV;
+	return ret;
 }
 
 static const struct rte_pci_id pci_id_nfp_pf_net_map[] = {
-- 
1.9.1

^ permalink raw reply	[relevance 6%]

* [dpdk-dev] [PATCH v2 16/18] doc: update NFP with PF support information
    2017-09-01 14:12 11% ` [dpdk-dev] [PATCH v2 02/18] net/nfp: add specific PF probe function Alejandro Lucero
  2017-09-01 14:12  6% ` [dpdk-dev] [PATCH v2 11/18] net/nfp: allocate ethernet device from " Alejandro Lucero
@ 2017-09-01 14:12  4% ` Alejandro Lucero
  2 siblings, 0 replies; 200+ results
From: Alejandro Lucero @ 2017-09-01 14:12 UTC (permalink / raw)
  To: dev

NFP PMD has now support for both, PF and VFs. This patch updates
the guide and give some information about implications.

Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
---
 doc/guides/nics/nfp.rst | 77 +++++++++++++++++++++++++++++++++++++------------
 1 file changed, 58 insertions(+), 19 deletions(-)

diff --git a/doc/guides/nics/nfp.rst b/doc/guides/nics/nfp.rst
index c732fb1..45dbbc3 100644
--- a/doc/guides/nics/nfp.rst
+++ b/doc/guides/nics/nfp.rst
@@ -1,5 +1,5 @@
 ..  BSD LICENSE
-    Copyright(c) 2015 Netronome Systems, Inc. All rights reserved.
+    Copyright(c) 2015-2017 Netronome Systems, Inc. All rights reserved.
     All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
@@ -38,31 +38,32 @@ up to 400 Gbps.
 
 This document explains how to use DPDK with the Netronome Poll Mode
 Driver (PMD) supporting Netronome's Network Flow Processor 6xxx
-(NFP-6xxx).
+(NFP-6xxx) and Netronome's Flow Processor 4xxx (NFP-4xxx).
 
-Currently the driver supports virtual functions (VFs) only.
+NFP is a SRIOV capable device and the PMD driver supports the physical
+function (PF) and virtual functions (VFs).
 
 Dependencies
 ------------
 
-Before using the Netronome's DPDK PMD some NFP-6xxx configuration,
+Before using the Netronome's DPDK PMD some NFP configuration,
 which is not related to DPDK, is required. The system requires
-installation of **Netronome's BSP (Board Support Package)** which includes
-Linux drivers, programs and libraries.
+installation of **Netronome's BSP (Board Support Package)** along
+with some specific NFP firmware application. Netronome's NSP ABI
+version should be 0.20 or higher.
 
-If you have a NFP-6xxx device you should already have the code and
-documentation for doing this configuration. Contact
+If you have a NFP device you should already have the code and
+documentation for doing all this configuration. Contact
 **support@netronome.com** to obtain the latest available firmware.
 
-The NFP Linux kernel drivers (including the required PF driver for the
-NFP) are available on Github at
+The NFP Linux netdev kernel driver for VFs is part of vanilla kernel
+since kernel vesion 4.5, and support for the PF since kernel version
+4.11. Support for older kernels can be obtained on Github at
 **https://github.com/Netronome/nfp-drv-kmods** along with build
 instructions.
 
-DPDK runs in userspace and PMDs uses the Linux kernel UIO interface to
-allow access to physical devices from userspace. The NFP PMD requires
-the **igb_uio** UIO driver, available with DPDK, to perform correct
-initialization.
+NFP PMD needs to be used along with UIO **igb_uio** or VFIO (vfio-pci)
+Linux kernel driver.
 
 Building the software
 ---------------------
@@ -71,7 +72,7 @@ Netronome's PMD code is provided in the **drivers/net/nfp** directory.
 Although NFP PMD has Netronome´s BSP dependencies, it is possible to
 compile it along with other DPDK PMDs even if no BSP was installed before.
 Of course, a DPDK app will require such a BSP installed for using the
-NFP PMD.
+NFP PMD, along with a specific NFP firmware application.
 
 Default PMD configuration is at **common_linuxapp configuration** file:
 
@@ -88,13 +89,51 @@ Refer to the document :ref:`compiling and testing a PMD for a NIC <pmd_build_and
 for details.
 
 
+Using the PF
+------------
+
+NFP PMD has support for using the NFP PF as another DPDK port, but it has not
+any functionality for controlling VFs. In fact, it is not possible to use the
+PMD with the VFs if the PF is being used by DPDK, this is, NFP PF bound to
+igb_uio or vfio-pci kernel drivers. Future DPDK version will have a PMD able
+to work with the PF and VFs at the same time and with the PF implementing VF
+management along wih other PF-only functionalities/offloads.
+
+The PMD PF has extra work to do which will delay the DPDK app initialization
+like checking if a firmware is already available in the device, uploading the
+firmware if necessary, and configure the Link state properly when starting or
+stopping a PF port. Note that firmware upload is not always necessary which is
+the main delay for NFP PF PMD initialization.
+
+Depending on the Netronome's product installed in the system, firmware files
+should be available under /lib/firmware/netronome. DPDK PMD supporting the PF
+requires a specific link, /lib/firmware/netronome/nic_dpdk_default.nffw, which
+should be created automatically with Netronome's Agilio products installation.
+
+PF multiport support
+--------------------
+
+Some NFP cards support several physical ports with just one single PCI device.
+DPDK core is designed with the 1:1 relationship between PCI devices and DPDK
+ports, so NFP PMD PF support requires to handle the multiport case specifically.
+During NFP PF initialization, the PMD will extract the information about the
+number of PF ports from the firmware and will create as many DPDK ports as
+needed.
+
+Because the unusual relationship between a single PCI device and several DPDK
+ports, there are some limitations when using more than one PF DPDK ports: there
+is no support for RX interrrupts and it is not possible either to use those PF
+ports with the device hotplug functionality.
+
 System configuration
 --------------------
 
-#. **Enable SR-IOV on the NFP-6xxx device:** The current NFP PMD works with
-   Virtual Functions (VFs) on a NFP device. Make sure that one of the Physical
-   Function (PF) drivers from the above Github repository is installed and
-   loaded.
+#. **Enable SR-IOV on the NFP device:** The current NFP PMD supports the PF and
+   the VFs on a NFP device. However, it is not possible to work with both at the
+   same time because the VFs require the PF being bound to the NFP PF Linux
+   netdev driver.  Make sure you are working with a kernel with NFP PF support or
+   get the drivers from the above Github repository and follow the instructions
+   for building and installing it.
 
    Virtual Functions need to be enabled before they can be used with the PMD.
    Before enabling the VFs it is useful to obtain information about the
-- 
1.9.1

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v1] net/mlx5: support upstream rdma-core
  2017-08-31 16:17  3%   ` Alexey Perevalov
@ 2017-09-04  6:30  0%     ` Shachar Beiser
  0 siblings, 0 replies; 200+ results
From: Shachar Beiser @ 2017-09-04  6:30 UTC (permalink / raw)
  To: Alexey Perevalov, dev

Yes , off course .
In my next patch the rdma-core is master f11292efd54132e09c9586a72c6c7bd0f341659d.
I will add that to the patch in the cover letter.
         -Shachar Beiser.


shacharbe@pegasus08-006:~/rdma-core$ git remote --v
origin  http://l-gerrit.mtl.labs.mlnx:8080/upstream/rdma-core.git (fetch)
origin  http://l-gerrit.mtl.labs.mlnx:8080/upstream/rdma-core.git (push)
shacharbe@pegasus08-006:~/rdma-core$ git branch
* master
shacharbe@pegasus08-006:~/rdma-core$ git log
commit f11292efd54132e09c9586a72c6c7bd0f341659d
Merge: 1435758 210e715
Author: Doug Ledford <dledford@redhat.com>
Date:   Sat Sep 2 09:06:16 2017 -0400

    Merge pull request #202 from yishaih/mlx5_dv

    mlx5 dv



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Alexey Perevalov
> Sent: Thursday, August 31, 2017 7:18 PM
> To: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v1] net/mlx5: support upstream rdma-core
> 
> Hello Shachar,
> 
> Thank you for the patch.
> 
> 
> Please could you specify patch set you used in new version, IIUC,
> 
> it's [PATCH 0/5] net/mlx5: cleanups" and [PATCH 0/5] net/mlx5:
> enable/disable vPMD and some cleanups
> 
> by Nélio Laranjeiro.
> 
> Also rdma-core version, I used HEAD (commit
> 202b39622e67b0424b2598fc6dd1c546e42f9edb),
> 
> but I had to revert "mlx5: Fix ABI break from revising the UAR pointer".
> 
> 
> --
> Best regards,
> Alexey Perevalov

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH 0/4] ethdev new offloads API
@ 2017-09-04  7:12  3% Shahaf Shuler
  2017-09-04  7:12  2% ` [dpdk-dev] [PATCH 2/4] ethdev: introduce Rx queue " Shahaf Shuler
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Shahaf Shuler @ 2017-09-04  7:12 UTC (permalink / raw)
  To: thomas; +Cc: dev

Tx offloads configuration is per queue. Tx offloads are enabled by default, 
and can be disabled using ETH_TXQ_FLAGS_NO* flags. 
This behaviour is not consistent with the Rx side where the Rx offloads
configuration is per port. Rx offloads are disabled by default and enabled 
according to bit field in rte_eth_rxmode structure.

Moreover, considering more Tx and Rx offloads will be added 
over time, the cost of managing them all inside the PMD will be tremendous,
as the PMD will need to check the matching for the entire offload set 
for each mbuf it handles.
In addition, on the current approach each Rx offload added breaks the
ABI compatibility as it requires to add entries to existing bit-fields.
 
The series address above issues by defining a new offloads API.
With the new API, Tx and Rx offloads configuration is per queue.
The offloads are disabled by default. Each offload can be enabled or
disabled using the existing DEV_TX_OFFLOADS_* or DEV_RX_OFFLOADS_* flags.
Such API will enable to easily add or remove offloads, without breaking the
ABI compatibility.

The new API does not have an equivalent for the below Tx flags:

* ETH_TXQ_FLAGS_NOREFCOUNT
* ETH_TXQ_FLAGS_NOMULTMEMP

The reason is that those flags are not to manage offloads, rather some
guarantee from application on the way it uses mbufs, therefore could not be
present as part of DEV_TX_OFFLOADS_*.
Such flags are useful only for benchmarks, and therefore provide a non-realistic    
performance for DPDK customers using simple benchmarks for evaluation.
Leveraging the work being done in this series to clean up those flags.

In order to provide a smooth transition between the APIs the following actions
were taken:
*  The old offloads API is kept for the meanwhile.
*  New capabilities were added for PMD to advertize it has moved to the new
   offloads API.
*  Helper function which copy from old to new API were added to ethdev,
   enabling the PMD to support only one of the APIs.

Per discussion made on the RFC of this series [1], the integration plan which was
decided is to do the transition in two phases:
* ethdev API will move on 17.11.
* Apps and examples will move on 18.02.

This to enable PMD maintainers sufficient time to adopt the new API.

[1]
http://dpdk.org/ml/archives/dev/2017-August/072643.html


Shahaf Shuler (4):
  ethdev: rename Rx and Tx configuration structs
  ethdev: introduce Rx queue offloads API
  ethdev: introduce Tx queue offloads API
  ethdev: add helpers to move to the new offloads API

 app/test-pmd/config.c                           |   4 +-
 app/test-pmd/testpmd.h                          |   4 +-
 doc/guides/nics/features.rst                    |  27 +++--
 drivers/net/af_packet/rte_eth_af_packet.c       |   4 +-
 drivers/net/ark/ark_ethdev_rx.c                 |   4 +-
 drivers/net/ark/ark_ethdev_rx.h                 |   2 +-
 drivers/net/ark/ark_ethdev_tx.c                 |   2 +-
 drivers/net/ark/ark_ethdev_tx.h                 |   2 +-
 drivers/net/avp/avp_ethdev.c                    |   8 +-
 drivers/net/bnx2x/bnx2x_rxtx.c                  |   4 +-
 drivers/net/bnx2x/bnx2x_rxtx.h                  |   4 +-
 drivers/net/bnxt/bnxt_ethdev.c                  |   4 +-
 drivers/net/bnxt/bnxt_rxq.c                     |   2 +-
 drivers/net/bnxt/bnxt_rxq.h                     |   2 +-
 drivers/net/bnxt/bnxt_txq.c                     |   2 +-
 drivers/net/bnxt/bnxt_txq.h                     |   2 +-
 drivers/net/bonding/rte_eth_bond_pmd.c          |   7 +-
 drivers/net/bonding/rte_eth_bond_private.h      |   4 +-
 drivers/net/cxgbe/cxgbe_ethdev.c                |   4 +-
 drivers/net/dpaa2/dpaa2_ethdev.c                |   4 +-
 drivers/net/e1000/e1000_ethdev.h                |   8 +-
 drivers/net/e1000/em_rxtx.c                     |   4 +-
 drivers/net/e1000/igb_ethdev.c                  |   8 +-
 drivers/net/e1000/igb_rxtx.c                    |   4 +-
 drivers/net/ena/ena_ethdev.c                    |  28 ++---
 drivers/net/enic/enic_ethdev.c                  |   6 +-
 drivers/net/failsafe/failsafe_ops.c             |   4 +-
 drivers/net/fm10k/fm10k_ethdev.c                |  12 +-
 drivers/net/i40e/i40e_ethdev.c                  |   4 +-
 drivers/net/i40e/i40e_ethdev_vf.c               |   4 +-
 drivers/net/i40e/i40e_rxtx.c                    |   4 +-
 drivers/net/i40e/i40e_rxtx.h                    |   4 +-
 drivers/net/ixgbe/ixgbe_ethdev.c                |   8 +-
 drivers/net/ixgbe/ixgbe_ethdev.h                |   4 +-
 drivers/net/ixgbe/ixgbe_rxtx.c                  |   4 +-
 drivers/net/kni/rte_eth_kni.c                   |   4 +-
 drivers/net/liquidio/lio_ethdev.c               |   8 +-
 drivers/net/mlx4/mlx4.c                         |  12 +-
 drivers/net/mlx5/mlx5_rxq.c                     |   4 +-
 drivers/net/mlx5/mlx5_rxtx.h                    |   6 +-
 drivers/net/mlx5/mlx5_txq.c                     |   4 +-
 drivers/net/nfp/nfp_net.c                       |  12 +-
 drivers/net/null/rte_eth_null.c                 |   4 +-
 drivers/net/pcap/rte_eth_pcap.c                 |   4 +-
 drivers/net/qede/qede_ethdev.c                  |   2 +-
 drivers/net/qede/qede_rxtx.c                    |   4 +-
 drivers/net/qede/qede_rxtx.h                    |   4 +-
 drivers/net/ring/rte_eth_ring.c                 |  20 ++--
 drivers/net/sfc/sfc_ethdev.c                    |   4 +-
 drivers/net/sfc/sfc_rx.c                        |   4 +-
 drivers/net/sfc/sfc_rx.h                        |   2 +-
 drivers/net/sfc/sfc_tx.c                        |   4 +-
 drivers/net/sfc/sfc_tx.h                        |   2 +-
 drivers/net/szedata2/rte_eth_szedata2.c         |   4 +-
 drivers/net/tap/rte_eth_tap.c                   |   4 +-
 drivers/net/thunderx/nicvf_ethdev.c             |   8 +-
 drivers/net/vhost/rte_eth_vhost.c               |   4 +-
 drivers/net/virtio/virtio_ethdev.c              |   2 +-
 drivers/net/virtio/virtio_ethdev.h              |   4 +-
 drivers/net/virtio/virtio_rxtx.c                |   8 +-
 drivers/net/vmxnet3/vmxnet3_ethdev.h            |   4 +-
 drivers/net/vmxnet3/vmxnet3_rxtx.c              |   4 +-
 drivers/net/xenvirt/rte_eth_xenvirt.c           |  20 ++--
 examples/ip_fragmentation/main.c                |   2 +-
 examples/ip_pipeline/app.h                      |   4 +-
 examples/ip_reassembly/main.c                   |   2 +-
 examples/ipsec-secgw/ipsec-secgw.c              |   2 +-
 examples/ipv4_multicast/main.c                  |   2 +-
 examples/l3fwd-acl/main.c                       |   2 +-
 examples/l3fwd-power/main.c                     |   2 +-
 examples/l3fwd-vf/main.c                        |   2 +-
 examples/l3fwd/main.c                           |   2 +-
 examples/netmap_compat/lib/compat_netmap.c      |   4 +-
 examples/performance-thread/l3fwd-thread/main.c |   2 +-
 examples/ptpclient/ptpclient.c                  |   2 +-
 examples/qos_sched/init.c                       |   4 +-
 examples/tep_termination/vxlan_setup.c          |   4 +-
 examples/vhost/main.c                           |   4 +-
 examples/vhost_xen/main.c                       |   2 +-
 examples/vmdq/main.c                            |   2 +-
 lib/librte_ether/rte_ethdev.c                   | 115 ++++++++++++++++++-
 lib/librte_ether/rte_ethdev.h                   |  83 +++++++++++--
 test/test-pipeline/init.c                       |   4 +-
 test/test/test_kni.c                            |   4 +-
 test/test/test_link_bonding.c                   |   4 +-
 test/test/test_pmd_perf.c                       |   4 +-
 test/test/virtual_pmd.c                         |   8 +-
 87 files changed, 409 insertions(+), 225 deletions(-)

-- 
2.12.0

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH 2/4] ethdev: introduce Rx queue offloads API
  2017-09-04  7:12  3% [dpdk-dev] [PATCH 0/4] ethdev new offloads API Shahaf Shuler
@ 2017-09-04  7:12  2% ` Shahaf Shuler
  2017-09-04  7:12  2% ` [dpdk-dev] [PATCH 3/4] ethdev: introduce Tx " Shahaf Shuler
  2017-09-10 12:07  4% ` [dpdk-dev] [PATCH v2 0/2] ethdev new " Shahaf Shuler
  2 siblings, 0 replies; 200+ results
From: Shahaf Shuler @ 2017-09-04  7:12 UTC (permalink / raw)
  To: thomas; +Cc: dev

Introduce a new API to configure Rx offloads.

The new API will re-use existing DEV_RX_OFFLOAD_* flags
to enable the different offloads. This will ease the process
of adding a new Rx offloads, as no ABI breakage is involved.
In addition, the offload configuration can be done per queue,
instead of per port.

The Rx queue offload API can be used only with devices which advertize
the RTE_ETH_DEV_RXQ_OFFLOAD capability. Otherwise the device
configuration will return with error.

PMDs which move to the new API however support rx offloads only per
port should return from the queue setup, in case of a mixed configuration,
with error (-ENOTSUP).

The old Rx offloads API is kept for the meanwhile, in order to enable a
smooth transition for PMDs and application to the new API.

Signed-off-by: Shahaf Shuler <shahafs@mellanox.com>
---
 doc/guides/nics/features.rst  | 19 +++++++++++--------
 lib/librte_ether/rte_ethdev.c | 12 ++++++++++++
 lib/librte_ether/rte_ethdev.h | 35 ++++++++++++++++++++++++++++++++++-
 3 files changed, 57 insertions(+), 9 deletions(-)

diff --git a/doc/guides/nics/features.rst b/doc/guides/nics/features.rst
index 37ffbc68c..f2c8497c2 100644
--- a/doc/guides/nics/features.rst
+++ b/doc/guides/nics/features.rst
@@ -179,7 +179,7 @@ Jumbo frame
 
 Supports Rx jumbo frames.
 
-* **[uses]    user config**: ``dev_conf.rxmode.jumbo_frame``,
+* **[uses]    rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_JUMBO_FRAME``.
   ``dev_conf.rxmode.max_rx_pkt_len``.
 * **[related] rte_eth_dev_info**: ``max_rx_pktlen``.
 * **[related] API**: ``rte_eth_dev_set_mtu()``.
@@ -192,7 +192,7 @@ Scattered Rx
 
 Supports receiving segmented mbufs.
 
-* **[uses]       user config**: ``dev_conf.rxmode.enable_scatter``.
+* **[uses]       rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_SCATTER``.
 * **[implements] datapath**: ``Scattered Rx function``.
 * **[implements] rte_eth_dev_data**: ``scattered_rx``.
 * **[provides]   eth_dev_ops**: ``rxq_info_get:scattered_rx``.
@@ -206,7 +206,7 @@ LRO
 
 Supports Large Receive Offload.
 
-* **[uses]       user config**: ``dev_conf.rxmode.enable_lro``.
+* **[uses]       rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_TCP_LRO``.
 * **[implements] datapath**: ``LRO functionality``.
 * **[implements] rte_eth_dev_data**: ``lro``.
 * **[provides]   mbuf**: ``mbuf.ol_flags:PKT_RX_LRO``, ``mbuf.tso_segsz``.
@@ -363,7 +363,7 @@ VLAN filter
 
 Supports filtering of a VLAN Tag identifier.
 
-* **[uses]       user config**: ``dev_conf.rxmode.hw_vlan_filter``.
+* **[uses]       rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_VLAN_FILTER``.
 * **[implements] eth_dev_ops**: ``vlan_filter_set``.
 * **[related]    API**: ``rte_eth_dev_vlan_filter()``.
 
@@ -499,7 +499,7 @@ CRC offload
 
 Supports CRC stripping by hardware.
 
-* **[uses] user config**: ``dev_conf.rxmode.hw_strip_crc``.
+* **[uses] rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_CRC_STRIP``.
 
 
 .. _nic_features_vlan_offload:
@@ -509,8 +509,7 @@ VLAN offload
 
 Supports VLAN offload to hardware.
 
-* **[uses]       user config**: ``dev_conf.rxmode.hw_vlan_strip``,
-  ``dev_conf.rxmode.hw_vlan_filter``, ``dev_conf.rxmode.hw_vlan_extend``.
+* **[uses]       rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_VLAN_STRIP,DEV_RX_OFFLOAD_VLAN_FILTER,DEV_RX_OFFLOAD_VLAN_EXTEND``.
 * **[implements] eth_dev_ops**: ``vlan_offload_set``.
 * **[provides]   mbuf**: ``mbuf.ol_flags:PKT_RX_VLAN_STRIPPED``, ``mbuf.vlan_tci``.
 * **[provides]   rte_eth_dev_info**: ``rx_offload_capa:DEV_RX_OFFLOAD_VLAN_STRIP``,
@@ -526,6 +525,7 @@ QinQ offload
 
 Supports QinQ (queue in queue) offload.
 
+* **[uses]     rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_QINQ_STRIP``.
 * **[uses]     mbuf**: ``mbuf.ol_flags:PKT_TX_QINQ_PKT``.
 * **[provides] mbuf**: ``mbuf.ol_flags:PKT_RX_QINQ_STRIPPED``, ``mbuf.vlan_tci``,
    ``mbuf.vlan_tci_outer``.
@@ -540,7 +540,7 @@ L3 checksum offload
 
 Supports L3 checksum offload.
 
-* **[uses]     user config**: ``dev_conf.rxmode.hw_ip_checksum``.
+* **[uses]     rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_IPV4_CKSUM``.
 * **[uses]     mbuf**: ``mbuf.ol_flags:PKT_TX_IP_CKSUM``,
   ``mbuf.ol_flags:PKT_TX_IPV4`` | ``PKT_TX_IPV6``.
 * **[provides] mbuf**: ``mbuf.ol_flags:PKT_RX_IP_CKSUM_UNKNOWN`` |
@@ -557,6 +557,7 @@ L4 checksum offload
 
 Supports L4 checksum offload.
 
+* **[uses]     rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_UDP_CKSUM,DEV_RX_OFFLOAD_TCP_CKSUM``.
 * **[uses]     mbuf**: ``mbuf.ol_flags:PKT_TX_IPV4`` | ``PKT_TX_IPV6``,
   ``mbuf.ol_flags:PKT_TX_L4_NO_CKSUM`` | ``PKT_TX_TCP_CKSUM`` |
   ``PKT_TX_SCTP_CKSUM`` | ``PKT_TX_UDP_CKSUM``.
@@ -574,6 +575,7 @@ MACsec offload
 
 Supports MACsec.
 
+* **[uses]     rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_MACSEC_STRIP``.
 * **[uses]     mbuf**: ``mbuf.ol_flags:PKT_TX_MACSEC``.
 * **[provides] rte_eth_dev_info**: ``rx_offload_capa:DEV_RX_OFFLOAD_MACSEC_STRIP``,
   ``tx_offload_capa:DEV_TX_OFFLOAD_MACSEC_INSERT``.
@@ -586,6 +588,7 @@ Inner L3 checksum
 
 Supports inner packet L3 checksum.
 
+* **[uses]     rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM``.
 * **[uses]     mbuf**: ``mbuf.ol_flags:PKT_TX_IP_CKSUM``,
   ``mbuf.ol_flags:PKT_TX_IPV4`` | ``PKT_TX_IPV6``,
   ``mbuf.ol_flags:PKT_TX_OUTER_IP_CKSUM``,
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index da2424cc4..50f8aa98d 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -722,6 +722,18 @@ rte_eth_dev_configure(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
 		return -EBUSY;
 	}
 
+	if ((!(dev->data->dev_flags & RTE_ETH_DEV_RXQ_OFFLOAD)) &&
+	     (dev_conf->rxmode.ignore_offloads == 1)) {
+		 /*
+		  * Application uses rte_eth_rxq_conf offloads API
+		  * but PMD not supports it.
+		  */
+		RTE_PMD_DEBUG_TRACE(
+			"port %d not supports rte_eth_rxq_conf offloads API\n",
+			port_id);
+		return -ENOTSUP;
+	}
+
 	/* Copy the dev_conf parameter into the dev structure */
 	memcpy(&dev->data->dev_conf, dev_conf, sizeof(dev->data->dev_conf));
 
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index c40db4ee0..90934418d 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -357,7 +357,14 @@ struct rte_eth_rxmode {
 		jumbo_frame      : 1, /**< Jumbo Frame Receipt enable. */
 		hw_strip_crc     : 1, /**< Enable CRC stripping by hardware. */
 		enable_scatter   : 1, /**< Enable scatter packets rx handler */
-		enable_lro       : 1; /**< Enable LRO */
+		enable_lro       : 1, /**< Enable LRO */
+		ignore_offloads	 : 1;
+		/**
+		 * When set the rxmode offloads should be ignored,
+		 * instead the Rx offloads will be set on rte_eth_rxq_conf.
+		 * This bit is temporary till rxmode Rx offloads API will
+		 * be deprecated.
+		 */
 };
 
 /**
@@ -691,6 +698,12 @@ struct rte_eth_rxq_conf {
 	uint16_t rx_free_thresh; /**< Drives the freeing of RX descriptors. */
 	uint8_t rx_drop_en; /**< Drop packets if no descriptors are available. */
 	uint8_t rx_deferred_start; /**< Do not start queue with rte_eth_dev_start(). */
+	uint64_t offloads;
+	/**
+	 * Enable Rx offloads using DEV_RX_OFFLOAD_* flags.
+	 * Supported only for devices which advertize the
+	 * RTE_ETH_DEV_RXQ_OFFLOAD capability.
+	 */
 };
 
 #define ETH_TXQ_FLAGS_NOMULTSEGS 0x0001 /**< nb_segs=1 for all mbufs */
@@ -907,6 +920,18 @@ struct rte_eth_conf {
 #define DEV_RX_OFFLOAD_QINQ_STRIP  0x00000020
 #define DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM 0x00000040
 #define DEV_RX_OFFLOAD_MACSEC_STRIP     0x00000080
+#define DEV_RX_OFFLOAD_HEADER_SPLIT	0x00000100
+#define DEV_RX_OFFLOAD_VLAN_FILTER	0x00000200
+#define DEV_RX_OFFLOAD_VLAN_EXTEND	0x00000400
+#define DEV_RX_OFFLOAD_JUMBO_FRAME	0x00000800
+#define DEV_RX_OFFLOAD_CRC_STRIP	0x00001000
+#define DEV_RX_OFFLOAD_SCATTER		0x00002000
+#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \
+				 DEV_RX_OFFLOAD_UDP_CKSUM | \
+				 DEV_RX_OFFLOAD_TCP_CKSUM)
+#define DEV_RX_OFFLOAD_VLAN (DEV_RX_OFFLOAD_VLAN_STRIP | \
+			     DEV_RX_OFFLOAD_VLAN_FILTER | \
+			     DEV_RX_OFFLOAD_VLAN_EXTEND)
 
 /**
  * TX offload capabilities of a device.
@@ -1723,6 +1748,8 @@ struct rte_eth_dev_data {
 #define RTE_ETH_DEV_BONDED_SLAVE 0x0004
 /** Device supports device removal interrupt */
 #define RTE_ETH_DEV_INTR_RMV     0x0008
+/** Device supports the rte_eth_rxq_conf offloads API */
+#define RTE_ETH_DEV_RXQ_OFFLOAD 0x0010
 
 /**
  * @internal
@@ -1872,6 +1899,9 @@ uint32_t rte_eth_speed_bitflag(uint32_t speed, int duplex);
  *        each statically configurable offload hardware feature provided by
  *        Ethernet devices, such as IP checksum or VLAN tag stripping for
  *        example.
+ *        This offloads API is obsoleted and will be deprecated. Applications
+ *        should set the ignore_offloads bit on *rxmode* structure and use
+ *        the offloads field on *rte_eth_rxq_conf* structure.
  *     - the Receive Side Scaling (RSS) configuration when using multiple RX
  *         queues per port.
  *
@@ -1925,6 +1955,8 @@ void _rte_eth_dev_reset(struct rte_eth_dev *dev);
  *   The *rx_conf* structure contains an *rx_thresh* structure with the values
  *   of the Prefetch, Host, and Write-Back threshold registers of the receive
  *   ring.
+ *   In addition it contains the hardware offloads features to activate using
+ *   the DEV_RX_OFFLOAD_* flags.
  * @param mb_pool
  *   The pointer to the memory pool from which to allocate *rte_mbuf* network
  *   memory buffers to populate each descriptor of the receive ring.
@@ -1936,6 +1968,7 @@ void _rte_eth_dev_reset(struct rte_eth_dev *dev);
  *   - -ENOMEM: Unable to allocate the receive ring descriptors or to
  *      allocate network memory buffers from the memory pool when
  *      initializing receive descriptors.
+ *   - -ENOTSUP: Device not support the queue configuration.
  */
 int rte_eth_rx_queue_setup(uint8_t port_id, uint16_t rx_queue_id,
 		uint16_t nb_rx_desc, unsigned int socket_id,
-- 
2.12.0

^ permalink raw reply	[relevance 2%]

* [dpdk-dev] [PATCH 3/4] ethdev: introduce Tx queue offloads API
  2017-09-04  7:12  3% [dpdk-dev] [PATCH 0/4] ethdev new offloads API Shahaf Shuler
  2017-09-04  7:12  2% ` [dpdk-dev] [PATCH 2/4] ethdev: introduce Rx queue " Shahaf Shuler
@ 2017-09-04  7:12  2% ` Shahaf Shuler
  2017-09-10 12:07  4% ` [dpdk-dev] [PATCH v2 0/2] ethdev new " Shahaf Shuler
  2 siblings, 0 replies; 200+ results
From: Shahaf Shuler @ 2017-09-04  7:12 UTC (permalink / raw)
  To: thomas; +Cc: dev

Introduce a new API to configure Tx offloads.

The new API will re-use existing DEV_TX_OFFLOAD_* flags
to enable the different offloads. This will ease the process
of adding a new Tx offloads, as no ABI breakage is involved.
In addition, the Tx offloads will be disabled by default and be
enabled per application needs. This will much simplify PMD management of
the different offloads.

The new API does not have an equivalent for the below, benchmark
specific, flags:

	- ETH_TXQ_FLAGS_NOREFCOUNT
	- ETH_TXQ_FLAGS_NOMULTMEMP

The Tx queue offload API can be used only with devices which advertize
the RTE_ETH_DEV_TXQ_OFFLOAD capability.

PMDs which move to the new API however support Tx offloads only per
port should return from the queue setup, in case of a mixed configuration,
with error (-ENOTSUP).

The old Tx offloads API is kept for the meanwhile, in order to enable a
smooth transition for PMDs and application to the new API.

Signed-off-by: Shahaf Shuler <shahafs@mellanox.com>
---
 doc/guides/nics/features.rst  |  8 ++++++++
 lib/librte_ether/rte_ethdev.h | 24 ++++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/doc/guides/nics/features.rst b/doc/guides/nics/features.rst
index f2c8497c2..bb25a1cee 100644
--- a/doc/guides/nics/features.rst
+++ b/doc/guides/nics/features.rst
@@ -131,6 +131,7 @@ Lock-free Tx queue
 If a PMD advertises DEV_TX_OFFLOAD_MT_LOCKFREE capable, multiple threads can
 invoke rte_eth_tx_burst() concurrently on the same Tx queue without SW lock.
 
+* **[uses]    rte_eth_txq_conf**: ``offloads:DEV_TX_OFFLOAD_MT_LOCKFREE``.
 * **[provides] rte_eth_dev_info**: ``tx_offload_capa:DEV_TX_OFFLOAD_MT_LOCKFREE``.
 * **[related]  API**: ``rte_eth_tx_burst()``.
 
@@ -220,6 +221,7 @@ TSO
 
 Supports TCP Segmentation Offloading.
 
+* **[uses]       rte_eth_txq_conf**: ``offloads:DEV_TX_OFFLOAD_TCP_TSO``.
 * **[uses]       rte_eth_desc_lim**: ``nb_seg_max``, ``nb_mtu_seg_max``.
 * **[uses]       mbuf**: ``mbuf.ol_flags:PKT_TX_TCP_SEG``.
 * **[uses]       mbuf**: ``mbuf.tso_segsz``, ``mbuf.l2_len``, ``mbuf.l3_len``, ``mbuf.l4_len``.
@@ -510,6 +512,7 @@ VLAN offload
 Supports VLAN offload to hardware.
 
 * **[uses]       rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_VLAN_STRIP,DEV_RX_OFFLOAD_VLAN_FILTER,DEV_RX_OFFLOAD_VLAN_EXTEND``.
+* **[uses]       rte_eth_txq_conf**: ``offloads:DEV_TX_OFFLOAD_VLAN_INSERT``.
 * **[implements] eth_dev_ops**: ``vlan_offload_set``.
 * **[provides]   mbuf**: ``mbuf.ol_flags:PKT_RX_VLAN_STRIPPED``, ``mbuf.vlan_tci``.
 * **[provides]   rte_eth_dev_info**: ``rx_offload_capa:DEV_RX_OFFLOAD_VLAN_STRIP``,
@@ -526,6 +529,7 @@ QinQ offload
 Supports QinQ (queue in queue) offload.
 
 * **[uses]     rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_QINQ_STRIP``.
+* **[uses]     rte_eth_txq_conf**: ``offloads:DEV_TX_OFFLOAD_QINQ_INSERT``.
 * **[uses]     mbuf**: ``mbuf.ol_flags:PKT_TX_QINQ_PKT``.
 * **[provides] mbuf**: ``mbuf.ol_flags:PKT_RX_QINQ_STRIPPED``, ``mbuf.vlan_tci``,
    ``mbuf.vlan_tci_outer``.
@@ -541,6 +545,7 @@ L3 checksum offload
 Supports L3 checksum offload.
 
 * **[uses]     rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_IPV4_CKSUM``.
+* **[uses]     rte_eth_txq_conf**: ``offloads:DEV_TX_OFFLOAD_IPV4_CKSUM``.
 * **[uses]     mbuf**: ``mbuf.ol_flags:PKT_TX_IP_CKSUM``,
   ``mbuf.ol_flags:PKT_TX_IPV4`` | ``PKT_TX_IPV6``.
 * **[provides] mbuf**: ``mbuf.ol_flags:PKT_RX_IP_CKSUM_UNKNOWN`` |
@@ -558,6 +563,7 @@ L4 checksum offload
 Supports L4 checksum offload.
 
 * **[uses]     rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_UDP_CKSUM,DEV_RX_OFFLOAD_TCP_CKSUM``.
+* **[uses]     rte_eth_txq_conf**: ``offloads:DEV_TX_OFFLOAD_UDP_CKSUM,DEV_TX_OFFLOAD_TCP_CKSUM,DEV_TX_OFFLOAD_SCTP_CKSUM``.
 * **[uses]     mbuf**: ``mbuf.ol_flags:PKT_TX_IPV4`` | ``PKT_TX_IPV6``,
   ``mbuf.ol_flags:PKT_TX_L4_NO_CKSUM`` | ``PKT_TX_TCP_CKSUM`` |
   ``PKT_TX_SCTP_CKSUM`` | ``PKT_TX_UDP_CKSUM``.
@@ -576,6 +582,7 @@ MACsec offload
 Supports MACsec.
 
 * **[uses]     rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_MACSEC_STRIP``.
+* **[uses]     rte_eth_txq_conf**: ``offloads:DEV_TX_OFFLOAD_MACSEC_INSERT``.
 * **[uses]     mbuf**: ``mbuf.ol_flags:PKT_TX_MACSEC``.
 * **[provides] rte_eth_dev_info**: ``rx_offload_capa:DEV_RX_OFFLOAD_MACSEC_STRIP``,
   ``tx_offload_capa:DEV_TX_OFFLOAD_MACSEC_INSERT``.
@@ -589,6 +596,7 @@ Inner L3 checksum
 Supports inner packet L3 checksum.
 
 * **[uses]     rte_eth_rxq_conf**: ``offloads:DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM``.
+* **[uses]     rte_eth_txq_conf**: ``offloads:DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM``.
 * **[uses]     mbuf**: ``mbuf.ol_flags:PKT_TX_IP_CKSUM``,
   ``mbuf.ol_flags:PKT_TX_IPV4`` | ``PKT_TX_IPV6``,
   ``mbuf.ol_flags:PKT_TX_OUTER_IP_CKSUM``,
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 90934418d..1293b9922 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -719,6 +719,14 @@ struct rte_eth_rxq_conf {
 #define ETH_TXQ_FLAGS_NOXSUMS \
 		(ETH_TXQ_FLAGS_NOXSUMSCTP | ETH_TXQ_FLAGS_NOXSUMUDP | \
 		 ETH_TXQ_FLAGS_NOXSUMTCP)
+#define ETH_TXQ_FLAGS_IGNORE	0x8000
+	/**
+	 * When set the txq_flags should be ignored,
+	 * instead the Tx offloads will be set on offloads field
+	 * located on rte_eth_txq_conf struct.
+	 * This flag is temporary till the rte_eth_txq_conf.txq_flags
+	 * API will be deprecated.
+	 */
 /**
  * A structure used to configure a TX ring of an Ethernet port.
  */
@@ -730,6 +738,12 @@ struct rte_eth_txq_conf {
 
 	uint32_t txq_flags; /**< Set flags for the Tx queue */
 	uint8_t tx_deferred_start; /**< Do not start queue with rte_eth_dev_start(). */
+	uint64_t offloads;
+	/**
+	 * Enable Tx offloads using DEV_TX_OFFLOAD_* flags.
+	 * Supported only for devices which advertize the
+	 * RTE_ETH_DEV_TXQ_OFFLOAD capability.
+	 */
 };
 
 /**
@@ -954,6 +968,8 @@ struct rte_eth_conf {
 /**< Multiple threads can invoke rte_eth_tx_burst() concurrently on the same
  * tx queue without SW lock.
  */
+#define DEV_TX_OFFLOAD_MULTI_SEGS	0x00008000
+/**< multi segment send is supported. */
 
 struct rte_pci_device;
 
@@ -1750,6 +1766,8 @@ struct rte_eth_dev_data {
 #define RTE_ETH_DEV_INTR_RMV     0x0008
 /** Device supports the rte_eth_rxq_conf offloads API */
 #define RTE_ETH_DEV_RXQ_OFFLOAD 0x0010
+/** Device supports the rte_eth_txq_conf offloads API */
+#define RTE_ETH_DEV_TXQ_OFFLOAD 0x0020
 
 /**
  * @internal
@@ -2011,12 +2029,18 @@ int rte_eth_rx_queue_setup(uint8_t port_id, uint16_t rx_queue_id,
  *   - The *txq_flags* member contains flags to pass to the TX queue setup
  *     function to configure the behavior of the TX queue. This should be set
  *     to 0 if no special configuration is required.
+ *     This API is obsoleted and will be deprecated. Applications
+ *     should set it to ETH_TXQ_FLAGS_IGNORE and use
+ *     the offloads field below.
+ *   - The *offloads* member contains Tx offloads to be enabled.
+ *     Offloads which are not set cannot be used on the datapath.
  *
  *     Note that setting *tx_free_thresh* or *tx_rs_thresh* value to 0 forces
  *     the transmit function to use default values.
  * @return
  *   - 0: Success, the transmit queue is correctly set up.
  *   - -ENOMEM: Unable to allocate the transmit ring descriptors.
+ *   - -ENOTSUP: Device not support the queue configuration.
  */
 int rte_eth_tx_queue_setup(uint8_t port_id, uint16_t tx_queue_id,
 		uint16_t nb_tx_desc, unsigned int socket_id,
-- 
2.12.0

^ permalink raw reply	[relevance 2%]

* Re: [dpdk-dev] [PATCH v3 2/2] ethdev: allow pmd to advertise pool handle
  @ 2017-09-04 12:11  3%     ` Olivier MATZ
  2017-09-04 13:14  0%       ` santosh
  0 siblings, 1 reply; 200+ results
From: Olivier MATZ @ 2017-09-04 12:11 UTC (permalink / raw)
  To: Santosh Shukla; +Cc: dev, thomas, jerin.jacob, hemant.agrawal

Hi Santosh,

On Tue, Aug 15, 2017 at 01:37:17PM +0530, Santosh Shukla wrote:
> Now that dpdk supports more than one mempool drivers and
> each mempool driver works best for specific PMD, example:
> - sw ring based mempool for Intel PMD drivers
> - dpaa2 HW mempool manager for dpaa2 PMD driver.
> - fpa HW mempool manager for Octeontx PMD driver.
> 
> Application like to know `preferred mempool vs PMD driver`
> information in advance before port setup.
> 
> Introducing rte_eth_dev_get_preferred_pool_ops() API,
> which allows PMD driver to advertise their pool capability to application.
> 
> Application side programing sequence would be:
> 
> char pref_mempool[RTE_MEMPOOL_OPS_NAMESIZE];
> rte_eth_dev_get_preferred_pool_ops(ethdev_port_id, pref_mempoolx /*out*/);
> rte_mempool_create_empty();
> rte_mempool_set_ops_byname( , pref_memppol, );
> rte_mempool_populate_default();
> 
> Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
> ---
> v2 --> v3:
> - Updated version.map entry to DPDK_v17.11.
> 
> v1 --> v2:
> - Renamed _get_preferred_pool to _get_preferred_pool_ops().
> Per v1 review feedback, Olivier suggested to rename api
> to rte_eth_dev_pool_ops_supported(), considering that 2nd param
> for that api will return pool handle 'priority' for that port.
> However, per v1 [1], we're opting for approach 1) where
> ethdev API returns _preferred_ pool handle to application and Its upto
> application to decide on policy - whether application wants to create
> pool with received preferred pool handle or not. For more discussion details
> on this topic refer [1].

Well, I still think it would be more flexible to have an API like
 rte_eth_dev_pool_ops_supported(uint8_t port_id, const char *pool)

It supports the easy case (= one preferred mempool) without much pain,
and provides a more precise manner to describe what is supported or not
by the driver. Example: "pmd_foo" prefers "mempool_foo" (best perf), but
also supporst "mempool_stack" and "mempool_ring", but "mempool_bar"
won't work at all.

Having only one preferred pool_ops also prevents from smoothly renaming
a pool (supporting both during some time) or to have 2 names for
different variants of the same pool_ops (ex: ring_mp_mc, ring_sp_sc).

But if the users (I guess at least Cavium and NXP) are happy with
what you propose, I'm fine with it.

> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -3409,3 +3409,21 @@ rte_eth_dev_adjust_nb_rx_tx_desc(uint8_t port_id,
>  
>  	return 0;
>  }
> +
> +int
> +rte_eth_dev_get_preferred_pool_ops(uint8_t port_id, char *pool)
> +{
> +	struct rte_eth_dev *dev;
> +	const char *tmp;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	dev = &rte_eth_devices[port_id];
> +
> +	if (*dev->dev_ops->get_preferred_pool_ops == NULL) {
> +		tmp = rte_eal_mbuf_default_mempool_ops();
> +		snprintf(pool, RTE_MBUF_POOL_OPS_NAMESIZE, "%s", tmp);
> +		return 0;
> +	}
> +	return (*dev->dev_ops->get_preferred_pool_ops)(dev, pool);
> +}

I think adding the length of the pool buffer to the function arguments
would be better: only documenting that the length is
RTE_MBUF_POOL_OPS_NAMESIZE looks a bit weak to me, because if one day it
changes to another value, the users of the function may not notice it
(no ABI/API change).


One more comment: it would be helpful to have one user of this API in
the example apps or testpmd.

Olivier

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v3 2/2] ethdev: allow pmd to advertise pool handle
  2017-09-04 12:11  3%     ` Olivier MATZ
@ 2017-09-04 13:14  0%       ` santosh
  2017-09-07  9:21  0%         ` Hemant Agrawal
  0 siblings, 1 reply; 200+ results
From: santosh @ 2017-09-04 13:14 UTC (permalink / raw)
  To: Olivier MATZ; +Cc: dev, thomas, jerin.jacob, hemant.agrawal

Hi Olivier,


On Monday 04 September 2017 05:41 PM, Olivier MATZ wrote:
> Hi Santosh,
>
> On Tue, Aug 15, 2017 at 01:37:17PM +0530, Santosh Shukla wrote:
>> Now that dpdk supports more than one mempool drivers and
>> each mempool driver works best for specific PMD, example:
>> - sw ring based mempool for Intel PMD drivers
>> - dpaa2 HW mempool manager for dpaa2 PMD driver.
>> - fpa HW mempool manager for Octeontx PMD driver.
>>
>> Application like to know `preferred mempool vs PMD driver`
>> information in advance before port setup.
>>
>> Introducing rte_eth_dev_get_preferred_pool_ops() API,
>> which allows PMD driver to advertise their pool capability to application.
>>
>> Application side programing sequence would be:
>>
>> char pref_mempool[RTE_MEMPOOL_OPS_NAMESIZE];
>> rte_eth_dev_get_preferred_pool_ops(ethdev_port_id, pref_mempoolx /*out*/);
>> rte_mempool_create_empty();
>> rte_mempool_set_ops_byname( , pref_memppol, );
>> rte_mempool_populate_default();
>>
>> Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
>> ---
>> v2 --> v3:
>> - Updated version.map entry to DPDK_v17.11.
>>
>> v1 --> v2:
>> - Renamed _get_preferred_pool to _get_preferred_pool_ops().
>> Per v1 review feedback, Olivier suggested to rename api
>> to rte_eth_dev_pool_ops_supported(), considering that 2nd param
>> for that api will return pool handle 'priority' for that port.
>> However, per v1 [1], we're opting for approach 1) where
>> ethdev API returns _preferred_ pool handle to application and Its upto
>> application to decide on policy - whether application wants to create
>> pool with received preferred pool handle or not. For more discussion details
>> on this topic refer [1].
> Well, I still think it would be more flexible to have an API like
>  rte_eth_dev_pool_ops_supported(uint8_t port_id, const char *pool)
>
> It supports the easy case (= one preferred mempool) without much pain,
> and provides a more precise manner to describe what is supported or not
> by the driver. Example: "pmd_foo" prefers "mempool_foo" (best perf), but
> also supporst "mempool_stack" and "mempool_ring", but "mempool_bar"
> won't work at all.
>
> Having only one preferred pool_ops also prevents from smoothly renaming
> a pool (supporting both during some time) or to have 2 names for
> different variants of the same pool_ops (ex: ring_mp_mc, ring_sp_sc).
>
> But if the users (I guess at least Cavium and NXP) are happy with
> what you propose, I'm fine with it.

preferred handle based upon real world use-case and same thing raised
at [1].

Hi Hemant, Are you ok with proposed preferred API?

[1] http://dpdk.org/dev/patchwork/patch/24944/

>> --- a/lib/librte_ether/rte_ethdev.c
>> +++ b/lib/librte_ether/rte_ethdev.c
>> @@ -3409,3 +3409,21 @@ rte_eth_dev_adjust_nb_rx_tx_desc(uint8_t port_id,
>>  
>>  	return 0;
>>  }
>> +
>> +int
>> +rte_eth_dev_get_preferred_pool_ops(uint8_t port_id, char *pool)
>> +{
>> +	struct rte_eth_dev *dev;
>> +	const char *tmp;
>> +
>> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
>> +
>> +	dev = &rte_eth_devices[port_id];
>> +
>> +	if (*dev->dev_ops->get_preferred_pool_ops == NULL) {
>> +		tmp = rte_eal_mbuf_default_mempool_ops();
>> +		snprintf(pool, RTE_MBUF_POOL_OPS_NAMESIZE, "%s", tmp);
>> +		return 0;
>> +	}
>> +	return (*dev->dev_ops->get_preferred_pool_ops)(dev, pool);
>> +}
> I think adding the length of the pool buffer to the function arguments
> would be better: only documenting that the length is
> RTE_MBUF_POOL_OPS_NAMESIZE looks a bit weak to me, because if one day it
> changes to another value, the users of the function may not notice it
> (no ABI/API change).
>
>
> One more comment: it would be helpful to have one user of this API in
> the example apps or testpmd.

Yes. I will add in v3. Thanks.

> Olivier

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3 0/2] Dynamically configure mempool handle
  @ 2017-09-04 13:34  4%     ` Olivier MATZ
  2017-09-04 14:24  0%       ` Sergio Gonzalez Monroy
  0 siblings, 1 reply; 200+ results
From: Olivier MATZ @ 2017-09-04 13:34 UTC (permalink / raw)
  To: Sergio Gonzalez Monroy
  Cc: Santosh Shukla, dev, thomas, jerin.jacob, hemant.agrawal

Hi Sergio,

On Mon, Sep 04, 2017 at 10:41:56AM +0100, Sergio Gonzalez Monroy wrote:
> On 15/08/2017 09:07, Santosh Shukla wrote:
> > v3:
> >   - Rebased on top of v17.11-rc0
> >   - Updated version.map entry to v17.11.
> > 
> > v2:
> > 
> > DPDK has support for hw and sw mempool. Those mempool
> > can work optimal for specific PMD's.
> > Example:
> > sw ring based PMD for Intel NICs.
> > HW mempool manager dpaa2 for dpaa2 PMD.
> > HW mempool manager fpa for octeontx PMD.
> > 
> > There could be a use-case where different vendor NIC's used
> > on the same platform and User like to configure mempool in such a way that
> > each of those NIC's should use their preferred mempool(For performance reasons).
> > 
> > Current mempool infrastrucure don't support such use-case.
> > 
> > This patchset tries to address that problem in 2 steps:
> > 
> > 0) Allowing user to dynamically configure mempool handle by
> > passing pool handle as eal arg to `--mbuf-pool-ops=<pool-handle>`.
> > 
> > 1) Allowing PMD's to advertise their preferred pool to an application.
> >  From an application point of view:
> > - The application must ask PMD about their preferred pool.
> > - PMD to respond back with preferred pool otherwise
> >    CONFIG_RTE_MEMPOOL_DEFAULT_OPS will be used for that PMD.
> > 
> > * Application programming sequencing would be
> >      char pref_mempool[RTE_MEMPOOL_OPS_NAMESIZE];
> >      rte_eth_dev_get_preferred_pool_ops(ethdev_port_id, pref_mempool /* out */);
> >      rte_mempool_create_empty();
> >      rte_mempool_set_ops_byname( , pref_memppol, );
> >      rte_mempool_populate_default();
> 
> What about introducing an API like:
> rte_pktmbuf_poll_create_with_ops (..., ops_name, config_pool);
> 
> I think that API would help for the case the application wants an mbuf pool
> with ie. stack handler.
> Sure we can do the empty/set_ops/populate sequence, but the only thing we
> want to change from default pktmbuf_pool_create API is the pool handler.
> 
> Application just needs to decide the ops handler to use, either default or
> one suggested by PMD?
> 
> I think ideally we would have similar APIs:
> - rte_mempool_create_with_ops (...)
> - rte_memppol_xmem_create_with_ops (...)

Today, we may only want to change the mempool handler, but if we
need to change something else tomorrow, we would need to add another
parameter again, breaking the ABI.

If we pass a config structure, adding a new field in it would also break the
ABI, except if the structure is opaque, with accessors. These accessors would be
functions (ex: mempool_cfg_new, mempool_cfg_set_pool_ops, ...). This is not so
much different than what we have now.

The advantage I can see of working on a config structure instead of directly on
a mempool is that the api can be reused to build a default config.

That said, I think it's quite orthogonal to this patch since we still require
the ethdev api.

Olivier

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH 04/17] build: add DPDK libraries to build
  2017-09-01 10:04  1% ` [dpdk-dev] [PATCH 04/17] build: add DPDK libraries to build Bruce Richardson
@ 2017-09-04 14:08  0%   ` Van Haaren, Harry
  2017-09-04 14:55  0%     ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Van Haaren, Harry @ 2017-09-04 14:08 UTC (permalink / raw)
  To: Richardson, Bruce, dev; +Cc: Richardson, Bruce

> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bruce Richardson
> Sent: Friday, September 1, 2017 11:04 AM
> To: dev@dpdk.org
> Cc: Richardson, Bruce <bruce.richardson@intel.com>
> Subject: [dpdk-dev] [PATCH 04/17] build: add DPDK libraries to build
> 
> Add non-EAL libraries to DPDK build. The compat lib is a special case,
> along with the previously-added EAL, but all other libs can be build using
> the same set of commands, where the individual meson.build files only need
> to specify their dependencies, source files, header files and ABI versions.
> 
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>

<snip>

In librte_acl/meson.build:

> +version = 2
> +sources = files('acl_bld.c', 'acl_gen.c', 'acl_run_scalar.c',
> +		'rte_acl.c', 'tb_mem.c')
> +headers = files('rte_acl.h', 'rte_acl_osdep.h')
> +
> +if arch_subdir == 'x86'
> +	sources += files('acl_run_sse.c')
> +
> +	# compile AVX2 version if either:
> +	# a. we have AVX supported in minimum instruction set baseline
> +	# b. it's not minimum instruction set, but supported by compiler
> +	#
> +	# in former case, just add avx2 C file to files list
> +	# in latter case, compile c file to static lib, using correct compiler
> +	# flags, and then have the .o file from static lib linked into main lib.
> +	if dpdk_conf.has('RTE_MACHINE_CPUFLAG_AVX2')
> +		sources += files('acl_run_avx2.c')
> +		cflags += '-DCC_AVX2_SUPPORT'
> +	elif cc.has_argument('-mavx2')
> +		avx2_tmplib = static_library('avx2_tmp',
> +				'acl_run_avx2.c',
> +				dependencies: rte_eal,
> +				c_args: '-mavx2')
> +		objs += avx2_tmplib.extract_objects('acl_run_avx2.c')
> +		cflags += '-DCC_AVX2_SUPPORT'
> +	endif
> +
> +endif

In future this could be split out to some sort of AVX helper, to avoid it
becoming copy/paste prone to detect AVX features from libraries.


<huge snip of almost all libraries meson.build files>

> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -29,4 +29,71 @@
>  #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
>  #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> 
> +# special case for eal, not a simple lib, and compat, just a header
>  subdir('librte_eal')
> +subdir('librte_compat')
> +
> +# process all libraries equally, as far as possible
> +# "core" libs first, then others alphebetically as far as possible
> +# NOTE: for speed of meson runs, the dependencies in the subdirectories
> +# sometimes skip deps that would be implied by others, e.g. if mempool is
> +# given as a dep, no need to mention ring. This is especially true for the
> +# core libs which are widely reused, so their deps are kept to a minimum.
> +libraries = ['ring', 'mempool', 'mbuf', 'net', 'ether', # core
> +	'metrics', # bitrate/latency stats depends on this
> +	'hash',    # efd depends on this
> +	'kvargs',  # cryptodev depends on this
> +	'acl', 'bitratestats', 'cfgfile', 'cmdline', 'cryptodev',
> +	'distributor', 'efd', 'eventdev', 'gro', 'ip_frag', 'jobstats',
> +	'kni', 'latencystats', 'lpm', 'meter', 'power', 'pdump',
> +	'reorder', 'sched', 'timer', 'vhost',
> +	# add pkt framework libs which use other libs from above
> +	'port', 'table', 'pipeline']
> +
> +foreach l:libraries
> +	build = true
> +	name = l
> +	version = 1
> +	sources = []
> +	headers = []
> +	cflags = []
> +	objs = [] # other object files to link against, used e.g. for instruction-
> +	          # optimized versions of code

Nitpick: comment above could be moved to be before the objs[] line, consistent like below.
I'll send a patch once this stuff is in next-build :D

> +	# use "deps" for internal DPDK dependencies, and "ext_deps" for
> +	# external package/library requirements
> +	deps = ['eal']
> +	ext_deps = []
> +
> +	dir_name = 'librte_' + l
> +	subdir(dir_name)
> +
> +	if build
> +		dpdk_conf.set('RTE_LIBRTE_' + name.to_upper(), 1)
> +		install_headers(headers)
> +
> +		dep_objs = ext_deps
> +		foreach d:deps
> +			dep_objs += [get_variable('dep_rte_' + d)]
> +		endforeach
> +
> +		version_map = '@0@/@1@/rte_@2@_version.map'.format(
> +				meson.current_source_dir(), dir_name, name)
> +		libname = 'rte_' + name
> +		lib = library(libname,
> +				sources,
> +				objects: objs,
> +				c_args: cflags,
> +				dependencies: dep_objs,
> +				include_directories: include_directories(dir_name),
> +				link_args: '-Wl,--version-script=' + version_map,
> +				link_depends: version_map,
> +				version: '@0@.1'.format(version),
> +				install: true)
> +		dep = declare_dependency(link_with: lib,
> +				include_directories: include_directories(dir_name),
> +				dependencies: dep_objs)
> +		set_variable('dep_' + libname, dep)
> +
> +		dpdk_libraries = [lib] + dpdk_libraries
> +	endif
> +endforeach
> --
> 2.13.5


Reviewed-by: Harry van Haaren <harry.van.haaren@intel.com>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3 0/2] Dynamically configure mempool handle
  2017-09-04 13:34  4%     ` Olivier MATZ
@ 2017-09-04 14:24  0%       ` Sergio Gonzalez Monroy
  2017-09-05  7:47  0%         ` Olivier MATZ
  0 siblings, 1 reply; 200+ results
From: Sergio Gonzalez Monroy @ 2017-09-04 14:24 UTC (permalink / raw)
  To: Olivier MATZ; +Cc: Santosh Shukla, dev, thomas, jerin.jacob, hemant.agrawal

Hi Olivier,

On 04/09/2017 14:34, Olivier MATZ wrote:
> Hi Sergio,
>
> On Mon, Sep 04, 2017 at 10:41:56AM +0100, Sergio Gonzalez Monroy wrote:
>> On 15/08/2017 09:07, Santosh Shukla wrote:
>>> v3:
>>>    - Rebased on top of v17.11-rc0
>>>    - Updated version.map entry to v17.11.
>>>
>>> v2:
>>>
>>> DPDK has support for hw and sw mempool. Those mempool
>>> can work optimal for specific PMD's.
>>> Example:
>>> sw ring based PMD for Intel NICs.
>>> HW mempool manager dpaa2 for dpaa2 PMD.
>>> HW mempool manager fpa for octeontx PMD.
>>>
>>> There could be a use-case where different vendor NIC's used
>>> on the same platform and User like to configure mempool in such a way that
>>> each of those NIC's should use their preferred mempool(For performance reasons).
>>>
>>> Current mempool infrastrucure don't support such use-case.
>>>
>>> This patchset tries to address that problem in 2 steps:
>>>
>>> 0) Allowing user to dynamically configure mempool handle by
>>> passing pool handle as eal arg to `--mbuf-pool-ops=<pool-handle>`.
>>>
>>> 1) Allowing PMD's to advertise their preferred pool to an application.
>>>   From an application point of view:
>>> - The application must ask PMD about their preferred pool.
>>> - PMD to respond back with preferred pool otherwise
>>>     CONFIG_RTE_MEMPOOL_DEFAULT_OPS will be used for that PMD.
>>>
>>> * Application programming sequencing would be
>>>       char pref_mempool[RTE_MEMPOOL_OPS_NAMESIZE];
>>>       rte_eth_dev_get_preferred_pool_ops(ethdev_port_id, pref_mempool /* out */);
>>>       rte_mempool_create_empty();
>>>       rte_mempool_set_ops_byname( , pref_memppol, );
>>>       rte_mempool_populate_default();
>> What about introducing an API like:
>> rte_pktmbuf_poll_create_with_ops (..., ops_name, config_pool);
>>
>> I think that API would help for the case the application wants an mbuf pool
>> with ie. stack handler.
>> Sure we can do the empty/set_ops/populate sequence, but the only thing we
>> want to change from default pktmbuf_pool_create API is the pool handler.
>>
>> Application just needs to decide the ops handler to use, either default or
>> one suggested by PMD?
>>
>> I think ideally we would have similar APIs:
>> - rte_mempool_create_with_ops (...)
>> - rte_memppol_xmem_create_with_ops (...)
> Today, we may only want to change the mempool handler, but if we
> need to change something else tomorrow, we would need to add another
> parameter again, breaking the ABI.
>
> If we pass a config structure, adding a new field in it would also break the
> ABI, except if the structure is opaque, with accessors. These accessors would be
> functions (ex: mempool_cfg_new, mempool_cfg_set_pool_ops, ...). This is not so
> much different than what we have now.
>
> The advantage I can see of working on a config structure instead of directly on
> a mempool is that the api can be reused to build a default config.
>
> That said, I think it's quite orthogonal to this patch since we still require
> the ethdev api.
>
> Olivier

Fair enough.

Just to double check that we are on the same page:
- rte_mempool_create is just there for backwards compatibility and a 
sequence of create_empty -> set_ops (optional) ->init -> 
populate_default -> obj_iter (optional) is the recommended way of 
creating mempools.
- if application wants to use re_mempool_xmem_create with different pool 
handler needs to replicate function and add set_ops step.

Now if rte_pktmbuf_pool_create is still the preferred mechanism for 
applications to create mbuf pools, wouldn't it make sense to offer the 
option of either pass the ops_name as suggested before or for the 
application to just set a different pool handler? I understand the it is 
either breaking API or introducing a new API, but is the solution to 
basically "copy" the whole function in the application and add an 
optional step (set_ops)?

With these patches we can:
- change the default pool handler with EAL option, which does *not* 
allow for pktmbuf_pool_create with different handlers.
- We can check the PMDs preferred/supported handlers but then we need to 
implement function with whole sequence, cannot use pktmbuf_pool_create.

It looks to me then that any application that wants to use different 
pool handlers than default/ring need to implement their own create_pool 
with set_ops.

Thanks,
Sergio

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 5/6] eal: remove xen dom0 support
  2017-08-30 18:10  1% ` [dpdk-dev] [PATCH 5/6] eal: remove xen dom0 support Jianfeng Tan
@ 2017-09-04 14:43  3%   ` Bruce Richardson
  2017-09-04 14:49  4%     ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2017-09-04 14:43 UTC (permalink / raw)
  To: Jianfeng Tan
  Cc: dev, xen-devel, thomas, john.mcnamara, joao.m.martins,
	jerin.jacob, shahafs

On Wed, Aug 30, 2017 at 06:10:33PM +0000, Jianfeng Tan wrote:
> We remove xen-specific code in EAL, including the option --xen-dom0,
> memory initialization code, compiling dependency, etc.
> 
> Besides, related documents are removed or updated.
> 
> Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
> ---
>  MAINTAINERS                                        |   7 -
>  config/common_base                                 |   5 -
>  doc/guides/index.rst                               |   1 -
>  doc/guides/linux_gsg/build_sample_apps.rst         |   5 +-
>  doc/guides/linux_gsg/sys_reqs.rst                  |  53 --
>  doc/guides/prog_guide/source_org.rst               |   1 -
>  doc/guides/rel_notes/deprecation.rst               |   3 -
>  doc/guides/rel_notes/release_17_11.rst             |  12 +
>  doc/guides/testpmd_app_ug/run_app.rst              |   4 -
>  doc/guides/xen/img/dpdk_xen_pkt_switch.png         | Bin 163842 -> 0 bytes
>  doc/guides/xen/img/grant_refs.png                  | Bin 6405 -> 0 bytes
>  doc/guides/xen/img/grant_table.png                 | Bin 96762 -> 0 bytes
>  doc/guides/xen/index.rst                           |  38 -
>  doc/guides/xen/pkt_switch.rst                      | 470 -------------
>  .../bsdapp/eal/include/exec-env/rte_dom0_common.h  | 107 ---
>  lib/librte_eal/common/eal_common_options.c         |   3 -
>  lib/librte_eal/common/eal_internal_cfg.h           |   1 -
>  lib/librte_eal/common/eal_options.h                |   2 -
>  lib/librte_eal/common/include/rte_memory.h         |  66 --
>  lib/librte_eal/linuxapp/Makefile                   |   2 -
>  lib/librte_eal/linuxapp/eal/Makefile               |   5 +-
>  lib/librte_eal/linuxapp/eal/eal.c                  |  24 -
>  lib/librte_eal/linuxapp/eal/eal_memory.c           |  56 --
>  lib/librte_eal/linuxapp/eal/eal_xen_memory.c       | 381 ----------
>  .../eal/include/exec-env/rte_dom0_common.h         | 108 ---
>  lib/librte_eal/linuxapp/igb_uio/igb_uio.c          |  54 --
>  lib/librte_eal/linuxapp/xen_dom0/Makefile          |  53 --
>  lib/librte_eal/linuxapp/xen_dom0/compat.h          |  15 -
>  lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h     | 107 ---
>  lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c    | 780 ---------------------
>  pkg/dpdk.spec                                      |   3 -

The xen functions that were removed are still listed in the linux/bsd 
version.map files. Not an ABI versioning expert, but I believe they
should be removed as they are no longer present.

Also, I spot a reference to xen still in
doc/guides/contributing/documentation.rst.

/Bruce

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH 5/6] eal: remove xen dom0 support
  2017-09-04 14:43  3%   ` Bruce Richardson
@ 2017-09-04 14:49  4%     ` Bruce Richardson
  2017-09-05  3:41  0%       ` Tan, Jianfeng
  0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2017-09-04 14:49 UTC (permalink / raw)
  To: Jianfeng Tan
  Cc: dev, xen-devel, thomas, john.mcnamara, joao.m.martins,
	jerin.jacob, shahafs

On Mon, Sep 04, 2017 at 03:43:02PM +0100, Bruce Richardson wrote:
> On Wed, Aug 30, 2017 at 06:10:33PM +0000, Jianfeng Tan wrote:
> > We remove xen-specific code in EAL, including the option --xen-dom0,
> > memory initialization code, compiling dependency, etc.
> > 
> > Besides, related documents are removed or updated.
> > 
> > Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
> > ---
> >  MAINTAINERS                                        |   7 -
> >  config/common_base                                 |   5 -
> >  doc/guides/index.rst                               |   1 -
> >  doc/guides/linux_gsg/build_sample_apps.rst         |   5 +-
> >  doc/guides/linux_gsg/sys_reqs.rst                  |  53 --
> >  doc/guides/prog_guide/source_org.rst               |   1 -
> >  doc/guides/rel_notes/deprecation.rst               |   3 -
> >  doc/guides/rel_notes/release_17_11.rst             |  12 +
> >  doc/guides/testpmd_app_ug/run_app.rst              |   4 -
> >  doc/guides/xen/img/dpdk_xen_pkt_switch.png         | Bin 163842 -> 0 bytes
> >  doc/guides/xen/img/grant_refs.png                  | Bin 6405 -> 0 bytes
> >  doc/guides/xen/img/grant_table.png                 | Bin 96762 -> 0 bytes
> >  doc/guides/xen/index.rst                           |  38 -
> >  doc/guides/xen/pkt_switch.rst                      | 470 -------------
> >  .../bsdapp/eal/include/exec-env/rte_dom0_common.h  | 107 ---
> >  lib/librte_eal/common/eal_common_options.c         |   3 -
> >  lib/librte_eal/common/eal_internal_cfg.h           |   1 -
> >  lib/librte_eal/common/eal_options.h                |   2 -
> >  lib/librte_eal/common/include/rte_memory.h         |  66 --
> >  lib/librte_eal/linuxapp/Makefile                   |   2 -
> >  lib/librte_eal/linuxapp/eal/Makefile               |   5 +-
> >  lib/librte_eal/linuxapp/eal/eal.c                  |  24 -
> >  lib/librte_eal/linuxapp/eal/eal_memory.c           |  56 --
> >  lib/librte_eal/linuxapp/eal/eal_xen_memory.c       | 381 ----------
> >  .../eal/include/exec-env/rte_dom0_common.h         | 108 ---
> >  lib/librte_eal/linuxapp/igb_uio/igb_uio.c          |  54 --
> >  lib/librte_eal/linuxapp/xen_dom0/Makefile          |  53 --
> >  lib/librte_eal/linuxapp/xen_dom0/compat.h          |  15 -
> >  lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h     | 107 ---
> >  lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c    | 780 ---------------------
> >  pkg/dpdk.spec                                      |   3 -
> 
> The xen functions that were removed are still listed in the linux/bsd 
> version.map files. Not an ABI versioning expert, but I believe they
> should be removed as they are no longer present.
>
Reading the contributors guide section on ABI, specifically
http://dpdk.org/doc/guides/contributing/versioning.html#deprecating-an-entire-abi-version
it seems like we should collapse down the versions to a single one
following the function removal, and also increment the whole library so
version.

/Bruce

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH 04/17] build: add DPDK libraries to build
  2017-09-04 14:08  0%   ` Van Haaren, Harry
@ 2017-09-04 14:55  0%     ` Bruce Richardson
  0 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2017-09-04 14:55 UTC (permalink / raw)
  To: Van Haaren, Harry; +Cc: dev

On Mon, Sep 04, 2017 at 03:08:50PM +0100, Van Haaren, Harry wrote:
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bruce Richardson
> > Sent: Friday, September 1, 2017 11:04 AM
> > To: dev@dpdk.org
> > Cc: Richardson, Bruce <bruce.richardson@intel.com>
> > Subject: [dpdk-dev] [PATCH 04/17] build: add DPDK libraries to build
> > 
> > Add non-EAL libraries to DPDK build. The compat lib is a special case,
> > along with the previously-added EAL, but all other libs can be build using
> > the same set of commands, where the individual meson.build files only need
> > to specify their dependencies, source files, header files and ABI versions.
> > 
> > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> 
> <snip>
> 
> In librte_acl/meson.build:
> 
> > +version = 2
> > +sources = files('acl_bld.c', 'acl_gen.c', 'acl_run_scalar.c',
> > +		'rte_acl.c', 'tb_mem.c')
> > +headers = files('rte_acl.h', 'rte_acl_osdep.h')
> > +
> > +if arch_subdir == 'x86'
> > +	sources += files('acl_run_sse.c')
> > +
> > +	# compile AVX2 version if either:
> > +	# a. we have AVX supported in minimum instruction set baseline
> > +	# b. it's not minimum instruction set, but supported by compiler
> > +	#
> > +	# in former case, just add avx2 C file to files list
> > +	# in latter case, compile c file to static lib, using correct compiler
> > +	# flags, and then have the .o file from static lib linked into main lib.
> > +	if dpdk_conf.has('RTE_MACHINE_CPUFLAG_AVX2')
> > +		sources += files('acl_run_avx2.c')
> > +		cflags += '-DCC_AVX2_SUPPORT'
> > +	elif cc.has_argument('-mavx2')
> > +		avx2_tmplib = static_library('avx2_tmp',
> > +				'acl_run_avx2.c',
> > +				dependencies: rte_eal,
> > +				c_args: '-mavx2')
> > +		objs += avx2_tmplib.extract_objects('acl_run_avx2.c')
> > +		cflags += '-DCC_AVX2_SUPPORT'
> > +	endif
> > +
> > +endif
> 
> In future this could be split out to some sort of AVX helper, to avoid it
> becoming copy/paste prone to detect AVX features from libraries.
> 
We can indeed look at that in future, using native meson support I hope,
from the SIMD module: http://mesonbuild.com/Simd-module.html

Right now, though, I think this is the only place we need this, so it's
not an issue.

/Bruce

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] devtools: rework abi checker script
  2017-08-30 13:51 27% [dpdk-dev] [PATCH] devtools: rework abi checker script Olivier Matz
@ 2017-09-04 16:00  8% ` Bruce Richardson
  2017-09-04 16:03  8%   ` Bruce Richardson
  2017-09-06 14:51 27% ` [dpdk-dev] [PATCH v2] " Olivier Matz
  1 sibling, 1 reply; 200+ results
From: Bruce Richardson @ 2017-09-04 16:00 UTC (permalink / raw)
  To: Olivier Matz; +Cc: dev, nhorman

On Wed, Aug 30, 2017 at 03:51:54PM +0200, Olivier Matz wrote:
> The intiatial version of the script had some limitations:
> - cannot work on a non-clean workspace
> - environment variables are not documented
> - no compilation log in case of failure
> - return success even it abi is incompatible
> 
> This patch addresses these issues and rework the code.
> 
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>

Giving this a spin to test it out. First impression is good, gives nice
output of what is happening, though perhaps a little verbose by default.

The output finishes though by printing:
	INFO: HTML reports are in /home/bruce/dpdk-clean/abi-check/compat_reports directory

Unfortunately:
	$ ls -l /home/bruce/dpdk-clean/abi-check/compat_reports

/Bruce

^ permalink raw reply	[relevance 8%]

* Re: [dpdk-dev] [PATCH] devtools: rework abi checker script
  2017-09-04 16:00  8% ` Bruce Richardson
@ 2017-09-04 16:03  8%   ` Bruce Richardson
  2017-09-04 16:13  7%     ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2017-09-04 16:03 UTC (permalink / raw)
  To: Olivier Matz; +Cc: dev, nhorman

On Mon, Sep 04, 2017 at 05:00:21PM +0100, Bruce Richardson wrote:
> On Wed, Aug 30, 2017 at 03:51:54PM +0200, Olivier Matz wrote:
> > The intiatial version of the script had some limitations:
> > - cannot work on a non-clean workspace
> > - environment variables are not documented
> > - no compilation log in case of failure
> > - return success even it abi is incompatible
> > 
> > This patch addresses these issues and rework the code.
> > 
> > Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> 
> Giving this a spin to test it out. First impression is good, gives nice
> output of what is happening, though perhaps a little verbose by default.
> 
> The output finishes though by printing:
> 	INFO: HTML reports are in /home/bruce/dpdk-clean/abi-check/compat_reports directory
> 
> Unfortunately:
	$ ls -l /home/bruce/dpdk-clean/abi-check/compat_reports
	ls: cannot access '/home/bruce/dpdk-clean/abi-check/compat_reports': No such file or directory

> 
> /Bruce

^ permalink raw reply	[relevance 8%]

* Re: [dpdk-dev] [PATCH v2 04/15] devargs: deprecate enum rte_devtype based functions
  @ 2017-09-04 16:06  0%     ` Ferruh Yigit
  0 siblings, 0 replies; 200+ results
From: Ferruh Yigit @ 2017-09-04 16:06 UTC (permalink / raw)
  To: Jan Blunck, dev

On 7/14/2017 10:12 PM, Jan Blunck wrote:
> The enum rte_devtype will need to get extended every time we add a bus.
> Mark all related functions as deprecated for 17.11.
> 
> Signed-off-by: Jan Blunck <jblunck@infradead.org>
> ---
>  doc/guides/rel_notes/deprecation.rst        | 7 +++++++
>  lib/librte_eal/common/include/rte_devargs.h | 3 +++
>  2 files changed, 10 insertions(+)
> 
> diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
> index 257dcba32..0c763d522 100644
> --- a/doc/guides/rel_notes/deprecation.rst
> +++ b/doc/guides/rel_notes/deprecation.rst
> @@ -64,3 +64,10 @@ Deprecation Notices
>    be removed in 17.11:
>  
>    - ``rte_eal_parse_devargs_str``, replaced by ``rte_eal_devargs_parse``
> +
> +* devargs: An API/ABI change is planed for 17.11 for ``struct rte_devargs`` to
> +  remove ``enum rte_devtype`` so that starting from 17.08 the following
> +  functions are deprecated:
> +
> +  - ``rte_eal_devargs_add``
> +  - ``rte_eal_devargs_type_count``

This also seems already applied.

> diff --git a/lib/librte_eal/common/include/rte_devargs.h b/lib/librte_eal/common/include/rte_devargs.h
> index 62dd67bff..41db817cc 100644
> --- a/lib/librte_eal/common/include/rte_devargs.h
> +++ b/lib/librte_eal/common/include/rte_devargs.h
> @@ -53,6 +53,7 @@ extern "C" {
>  #include <rte_bus.h>
>  
>  /**
> + * @deprecated

Although these "@deprecated" notes not applied.

>   * Type of generic device
>   */
>  enum rte_devtype {
> @@ -139,6 +140,7 @@ rte_eal_devargs_parse(const char *dev,
>  		      struct rte_devargs *da);
>  
>  /**
> + * @deprecated
>   * Add a device to the user device list
>   *
>   * For PCI devices, the format of arguments string is "PCI_ADDR" or
> @@ -163,6 +165,7 @@ rte_eal_devargs_parse(const char *dev,
>  int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str);
>  
>  /**
> + * @deprecated
>   * Count the number of user devices of a specified type
>   *
>   * @param devtype
> 

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] devtools: rework abi checker script
  2017-09-04 16:03  8%   ` Bruce Richardson
@ 2017-09-04 16:13  7%     ` Bruce Richardson
  0 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2017-09-04 16:13 UTC (permalink / raw)
  To: Olivier Matz; +Cc: dev, nhorman

On Mon, Sep 04, 2017 at 05:03:47PM +0100, Bruce Richardson wrote:
> On Mon, Sep 04, 2017 at 05:00:21PM +0100, Bruce Richardson wrote:
> > On Wed, Aug 30, 2017 at 03:51:54PM +0200, Olivier Matz wrote:
> > > The intiatial version of the script had some limitations:
> > > - cannot work on a non-clean workspace
> > > - environment variables are not documented
> > > - no compilation log in case of failure
> > > - return success even it abi is incompatible
> > > 
> > > This patch addresses these issues and rework the code.
> > > 
> > > Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> > 
> > Giving this a spin to test it out. First impression is good, gives nice
> > output of what is happening, though perhaps a little verbose by default.
> > 
> > The output finishes though by printing:
> > 	INFO: HTML reports are in /home/bruce/dpdk-clean/abi-check/compat_reports directory
> > 
> > Unfortunately:
> 	$ ls -l /home/bruce/dpdk-clean/abi-check/compat_reports
> 	ls: cannot access '/home/bruce/dpdk-clean/abi-check/compat_reports': No such file or directory
> 
> > 
On the plus side, introducing an abi error in a library is detected and
the library in question is reported as part of the output. Still no HTML
reports to be found though.

/Bruce

^ permalink raw reply	[relevance 7%]

* Re: [dpdk-dev] [PATCH 5/6] eal: remove xen dom0 support
  2017-09-04 14:49  4%     ` Bruce Richardson
@ 2017-09-05  3:41  0%       ` Tan, Jianfeng
  2017-09-05  7:31  0%         ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Tan, Jianfeng @ 2017-09-05  3:41 UTC (permalink / raw)
  To: Richardson, Bruce
  Cc: dev, xen-devel, thomas, Mcnamara, John, joao.m.martins,
	jerin.jacob, shahafs



> -----Original Message-----
> From: Richardson, Bruce
> Sent: Monday, September 4, 2017 10:49 PM
> To: Tan, Jianfeng
> Cc: dev@dpdk.org; xen-devel@lists.xenproject.org; thomas@monjalon.net;
> Mcnamara, John; joao.m.martins@oracle.com;
> jerin.jacob@caviumnetworks.com; shahafs@mellanox.com
> Subject: Re: [dpdk-dev] [PATCH 5/6] eal: remove xen dom0 support
> 
> On Mon, Sep 04, 2017 at 03:43:02PM +0100, Bruce Richardson wrote:
> > On Wed, Aug 30, 2017 at 06:10:33PM +0000, Jianfeng Tan wrote:
> > > We remove xen-specific code in EAL, including the option --xen-dom0,
> > > memory initialization code, compiling dependency, etc.
> > >
> > > Besides, related documents are removed or updated.
> > >
> > > Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
> > > ---
> > >  MAINTAINERS                                        |   7 -
> > >  config/common_base                                 |   5 -
> > >  doc/guides/index.rst                               |   1 -
> > >  doc/guides/linux_gsg/build_sample_apps.rst         |   5 +-
> > >  doc/guides/linux_gsg/sys_reqs.rst                  |  53 --
> > >  doc/guides/prog_guide/source_org.rst               |   1 -
> > >  doc/guides/rel_notes/deprecation.rst               |   3 -
> > >  doc/guides/rel_notes/release_17_11.rst             |  12 +
> > >  doc/guides/testpmd_app_ug/run_app.rst              |   4 -
> > >  doc/guides/xen/img/dpdk_xen_pkt_switch.png         | Bin 163842 -> 0
> bytes
> > >  doc/guides/xen/img/grant_refs.png                  | Bin 6405 -> 0 bytes
> > >  doc/guides/xen/img/grant_table.png                 | Bin 96762 -> 0 bytes
> > >  doc/guides/xen/index.rst                           |  38 -
> > >  doc/guides/xen/pkt_switch.rst                      | 470 -------------
> > >  .../bsdapp/eal/include/exec-env/rte_dom0_common.h  | 107 ---
> > >  lib/librte_eal/common/eal_common_options.c         |   3 -
> > >  lib/librte_eal/common/eal_internal_cfg.h           |   1 -
> > >  lib/librte_eal/common/eal_options.h                |   2 -
> > >  lib/librte_eal/common/include/rte_memory.h         |  66 --
> > >  lib/librte_eal/linuxapp/Makefile                   |   2 -
> > >  lib/librte_eal/linuxapp/eal/Makefile               |   5 +-
> > >  lib/librte_eal/linuxapp/eal/eal.c                  |  24 -
> > >  lib/librte_eal/linuxapp/eal/eal_memory.c           |  56 --
> > >  lib/librte_eal/linuxapp/eal/eal_xen_memory.c       | 381 ----------
> > >  .../eal/include/exec-env/rte_dom0_common.h         | 108 ---
> > >  lib/librte_eal/linuxapp/igb_uio/igb_uio.c          |  54 --
> > >  lib/librte_eal/linuxapp/xen_dom0/Makefile          |  53 --
> > >  lib/librte_eal/linuxapp/xen_dom0/compat.h          |  15 -
> > >  lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h     | 107 ---
> > >  lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c    | 780 --------------
> -------
> > >  pkg/dpdk.spec                                      |   3 -
> >
> > The xen functions that were removed are still listed in the linux/bsd
> > version.map files. Not an ABI versioning expert, but I believe they
> > should be removed as they are no longer present.
> >
> Reading the contributors guide section on ABI, specifically
> http://dpdk.org/doc/guides/contributing/versioning.html#deprecating-an-
> entire-abi-version
> it seems like we should collapse down the versions to a single one
> following the function removal, and also increment the whole library so
> version.

So for lib/librte_eal/linuxapp/eal/rte_eal_version.map, we should change it in below way?

DPDK_2.1 {
        {APIs in DPDK_2.0 except xen APIs}
        ...
};

DPDK_16.04 {
        {APIs in DPDK_2.1 except xen APIs}
        ...
} DPDK_2.1;

DPDK_16.07 {
        ...
} DPDK_16.04;
...

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 5/6] eal: remove xen dom0 support
  2017-09-05  3:41  0%       ` Tan, Jianfeng
@ 2017-09-05  7:31  0%         ` Thomas Monjalon
  2017-09-05  8:07  0%           ` Tan, Jianfeng
  0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2017-09-05  7:31 UTC (permalink / raw)
  To: Tan, Jianfeng
  Cc: Richardson, Bruce, dev, xen-devel, Mcnamara, John,
	joao.m.martins, jerin.jacob, shahafs

05/09/2017 05:41, Tan, Jianfeng:
> From: Richardson, Bruce
> > 
> > Reading the contributors guide section on ABI, specifically
> > http://dpdk.org/doc/guides/contributing/versioning.html#deprecating-an-
> > entire-abi-version
> > it seems like we should collapse down the versions to a single one
> > following the function removal, and also increment the whole library so
> > version.
> 
> So for lib/librte_eal/linuxapp/eal/rte_eal_version.map, we should change it in below way?
> 
> DPDK_2.1 {
>         {APIs in DPDK_2.0 except xen APIs}
>         ...
> };
> 
> DPDK_16.04 {
>         {APIs in DPDK_2.1 except xen APIs}
>         ...
> } DPDK_2.1;

No, you don't need to collapse. You can just remove Xen functions.

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3 0/2] Dynamically configure mempool handle
  2017-09-04 14:24  0%       ` Sergio Gonzalez Monroy
@ 2017-09-05  7:47  0%         ` Olivier MATZ
  2017-09-05  8:11  0%           ` Jerin Jacob
  0 siblings, 1 reply; 200+ results
From: Olivier MATZ @ 2017-09-05  7:47 UTC (permalink / raw)
  To: Sergio Gonzalez Monroy
  Cc: Santosh Shukla, dev, thomas, jerin.jacob, hemant.agrawal

On Mon, Sep 04, 2017 at 03:24:38PM +0100, Sergio Gonzalez Monroy wrote:
> Hi Olivier,
> 
> On 04/09/2017 14:34, Olivier MATZ wrote:
> > Hi Sergio,
> > 
> > On Mon, Sep 04, 2017 at 10:41:56AM +0100, Sergio Gonzalez Monroy wrote:
> > > On 15/08/2017 09:07, Santosh Shukla wrote:
> > > > * Application programming sequencing would be
> > > >       char pref_mempool[RTE_MEMPOOL_OPS_NAMESIZE];
> > > >       rte_eth_dev_get_preferred_pool_ops(ethdev_port_id, pref_mempool /* out */);
> > > >       rte_mempool_create_empty();
> > > >       rte_mempool_set_ops_byname( , pref_memppol, );
> > > >       rte_mempool_populate_default();
> > > What about introducing an API like:
> > > rte_pktmbuf_poll_create_with_ops (..., ops_name, config_pool);
> > > 
> > > I think that API would help for the case the application wants an mbuf pool
> > > with ie. stack handler.
> > > Sure we can do the empty/set_ops/populate sequence, but the only thing we
> > > want to change from default pktmbuf_pool_create API is the pool handler.
> > > 
> > > Application just needs to decide the ops handler to use, either default or
> > > one suggested by PMD?
> > > 
> > > I think ideally we would have similar APIs:
> > > - rte_mempool_create_with_ops (...)
> > > - rte_memppol_xmem_create_with_ops (...)
> > Today, we may only want to change the mempool handler, but if we
> > need to change something else tomorrow, we would need to add another
> > parameter again, breaking the ABI.
> > 
> > If we pass a config structure, adding a new field in it would also break the
> > ABI, except if the structure is opaque, with accessors. These accessors would be
> > functions (ex: mempool_cfg_new, mempool_cfg_set_pool_ops, ...). This is not so
> > much different than what we have now.
> > 
> > The advantage I can see of working on a config structure instead of directly on
> > a mempool is that the api can be reused to build a default config.
> > 
> > That said, I think it's quite orthogonal to this patch since we still require
> > the ethdev api.
> 
> Fair enough.
> 
> Just to double check that we are on the same page:
> - rte_mempool_create is just there for backwards compatibility and a
> sequence of create_empty -> set_ops (optional) ->init -> populate_default ->
> obj_iter (optional) is the recommended way of creating mempools.

Yes, I think rte_mempool_create() has too many arguments.

> - if application wants to use rte_mempool_xmem_create with different pool
> handler needs to replicate function and add set_ops step.

Yes. And now that xen support is going to be removed, I'm wondering if
this function is still required, given the API is not that easy to
use. Calling rte_mempool_populate_phys() several times looks more
flexible. But this is also another topic.

> Now if rte_pktmbuf_pool_create is still the preferred mechanism for
> applications to create mbuf pools, wouldn't it make sense to offer the
> option of either pass the ops_name as suggested before or for the
> application to just set a different pool handler? I understand the it is
> either breaking API or introducing a new API, but is the solution to
> basically "copy" the whole function in the application and add an optional
> step (set_ops)?

I was quite reticent about introducing
rte_pktmbuf_pool_create_with_ops() because for the same reasons, we
would also want to introduce functions to create a mempool that use a
different pktmbuf_init() or pool_init() callback, or to create the pool
in external memory, ... and we would end up with a functions with too
many arguments.

I like the approach of having several simple functions, because it's
easier to read (even if the code is longer), and it's easily extensible.

Now if we feel that the mempool ops is more important than the other
parameters, we can consider to add it in rte_pktmbuf_pool_create().

> With these patches we can:
> - change the default pool handler with EAL option, which does *not* allow
> for pktmbuf_pool_create with different handlers.
> - We can check the PMDs preferred/supported handlers but then we need to
> implement function with whole sequence, cannot use pktmbuf_pool_create.
> 
> It looks to me then that any application that wants to use different pool
> handlers than default/ring need to implement their own create_pool with
> set_ops.

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 5/6] eal: remove xen dom0 support
  2017-09-05  7:31  0%         ` Thomas Monjalon
@ 2017-09-05  8:07  0%           ` Tan, Jianfeng
  2017-09-05  8:34  0%             ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Tan, Jianfeng @ 2017-09-05  8:07 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: Richardson, Bruce, dev, xen-devel, Mcnamara, John,
	joao.m.martins, jerin.jacob, shahafs



> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Tuesday, September 5, 2017 3:31 PM
> To: Tan, Jianfeng
> Cc: Richardson, Bruce; dev@dpdk.org; xen-devel@lists.xenproject.org;
> Mcnamara, John; joao.m.martins@oracle.com;
> jerin.jacob@caviumnetworks.com; shahafs@mellanox.com
> Subject: Re: [dpdk-dev] [PATCH 5/6] eal: remove xen dom0 support
> 
> 05/09/2017 05:41, Tan, Jianfeng:
> > From: Richardson, Bruce
> > >
> > > Reading the contributors guide section on ABI, specifically
> > > http://dpdk.org/doc/guides/contributing/versioning.html#deprecating-
> an-
> > > entire-abi-version
> > > it seems like we should collapse down the versions to a single one
> > > following the function removal, and also increment the whole library so
> > > version.
> >
> > So for lib/librte_eal/linuxapp/eal/rte_eal_version.map, we should change
> it in below way?
> >
> > DPDK_2.1 {
> >         {APIs in DPDK_2.0 except xen APIs}
> >         ...
> > };
> >
> > DPDK_16.04 {
> >         {APIs in DPDK_2.1 except xen APIs}
> >         ...
> > } DPDK_2.1;
> 
> No, you don't need to collapse. You can just remove Xen functions.

Thanks.

Besides, two more things: 
1. Shall we increase the so version?
2. This patch is about 8K lines long, do we need to split?

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3 0/2] Dynamically configure mempool handle
  2017-09-05  7:47  0%         ` Olivier MATZ
@ 2017-09-05  8:11  0%           ` Jerin Jacob
  0 siblings, 0 replies; 200+ results
From: Jerin Jacob @ 2017-09-05  8:11 UTC (permalink / raw)
  To: Olivier MATZ
  Cc: Sergio Gonzalez Monroy, Santosh Shukla, dev, thomas, hemant.agrawal

-----Original Message-----
> Date: Tue, 5 Sep 2017 09:47:26 +0200
> From: Olivier MATZ <olivier.matz@6wind.com>
> To: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
> CC: Santosh Shukla <santosh.shukla@caviumnetworks.com>, dev@dpdk.org,
>  thomas@monjalon.net, jerin.jacob@caviumnetworks.com,
>  hemant.agrawal@nxp.com
> Subject: Re: [dpdk-dev] [PATCH v3 0/2] Dynamically configure mempool handle
> User-Agent: NeoMutt/20170113 (1.7.2)
> 
> On Mon, Sep 04, 2017 at 03:24:38PM +0100, Sergio Gonzalez Monroy wrote:
> > Hi Olivier,
> > 
> > On 04/09/2017 14:34, Olivier MATZ wrote:
> > > Hi Sergio,
> > > 
> > > On Mon, Sep 04, 2017 at 10:41:56AM +0100, Sergio Gonzalez Monroy wrote:
> > > > On 15/08/2017 09:07, Santosh Shukla wrote:
> > > > > * Application programming sequencing would be
> > > > >       char pref_mempool[RTE_MEMPOOL_OPS_NAMESIZE];
> > > > >       rte_eth_dev_get_preferred_pool_ops(ethdev_port_id, pref_mempool /* out */);
> > > > >       rte_mempool_create_empty();
> > > > >       rte_mempool_set_ops_byname( , pref_memppol, );
> > > > >       rte_mempool_populate_default();
> > > > What about introducing an API like:
> > > > rte_pktmbuf_poll_create_with_ops (..., ops_name, config_pool);
> > > > 
> > > > I think that API would help for the case the application wants an mbuf pool
> > > > with ie. stack handler.
> > > > Sure we can do the empty/set_ops/populate sequence, but the only thing we
> > > > want to change from default pktmbuf_pool_create API is the pool handler.
> > > > 
> > > > Application just needs to decide the ops handler to use, either default or
> > > > one suggested by PMD?
> > > > 
> > > > I think ideally we would have similar APIs:
> > > > - rte_mempool_create_with_ops (...)
> > > > - rte_memppol_xmem_create_with_ops (...)
> > > Today, we may only want to change the mempool handler, but if we
> > > need to change something else tomorrow, we would need to add another
> > > parameter again, breaking the ABI.
> > > 
> > > If we pass a config structure, adding a new field in it would also break the
> > > ABI, except if the structure is opaque, with accessors. These accessors would be
> > > functions (ex: mempool_cfg_new, mempool_cfg_set_pool_ops, ...). This is not so
> > > much different than what we have now.
> > > 
> > > The advantage I can see of working on a config structure instead of directly on
> > > a mempool is that the api can be reused to build a default config.
> > > 
> > > That said, I think it's quite orthogonal to this patch since we still require
> > > the ethdev api.
> > 
> > Fair enough.
> > 
> > Just to double check that we are on the same page:
> > - rte_mempool_create is just there for backwards compatibility and a
> > sequence of create_empty -> set_ops (optional) ->init -> populate_default ->
> > obj_iter (optional) is the recommended way of creating mempools.
> 
> Yes, I think rte_mempool_create() has too many arguments.
> 
> > - if application wants to use rte_mempool_xmem_create with different pool
> > handler needs to replicate function and add set_ops step.
> 
> Yes. And now that xen support is going to be removed, I'm wondering if
> this function is still required, given the API is not that easy to
> use. Calling rte_mempool_populate_phys() several times looks more
> flexible. But this is also another topic.
> 
> > Now if rte_pktmbuf_pool_create is still the preferred mechanism for
> > applications to create mbuf pools, wouldn't it make sense to offer the
> > option of either pass the ops_name as suggested before or for the
> > application to just set a different pool handler? I understand the it is
> > either breaking API or introducing a new API, but is the solution to
> > basically "copy" the whole function in the application and add an optional
> > step (set_ops)?
> 
> I was quite reticent about introducing
> rte_pktmbuf_pool_create_with_ops() because for the same reasons, we
> would also want to introduce functions to create a mempool that use a
> different pktmbuf_init() or pool_init() callback, or to create the pool
> in external memory, ... and we would end up with a functions with too
> many arguments.
> 
> I like the approach of having several simple functions, because it's
> easier to read (even if the code is longer), and it's easily extensible.
> 
> Now if we feel that the mempool ops is more important than the other
> parameters, we can consider to add it in rte_pktmbuf_pool_create().

Yes. I agree with Sergio here.

Something we could target for v18.02.

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 5/6] eal: remove xen dom0 support
  2017-09-05  8:07  0%           ` Tan, Jianfeng
@ 2017-09-05  8:34  0%             ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2017-09-05  8:34 UTC (permalink / raw)
  To: Tan, Jianfeng
  Cc: Richardson, Bruce, dev, xen-devel, Mcnamara, John,
	joao.m.martins, jerin.jacob, shahafs

05/09/2017 10:07, Tan, Jianfeng:
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > 05/09/2017 05:41, Tan, Jianfeng:
> > > From: Richardson, Bruce
> > > >
> > > > Reading the contributors guide section on ABI, specifically
> > > > http://dpdk.org/doc/guides/contributing/versioning.html#deprecating-
> > an-
> > > > entire-abi-version
> > > > it seems like we should collapse down the versions to a single one
> > > > following the function removal, and also increment the whole library so
> > > > version.
> > >
> > > So for lib/librte_eal/linuxapp/eal/rte_eal_version.map, we should change
> > it in below way?
> > >
> > > DPDK_2.1 {
> > >         {APIs in DPDK_2.0 except xen APIs}
> > >         ...
> > > };
> > >
> > > DPDK_16.04 {
> > >         {APIs in DPDK_2.1 except xen APIs}
> > >         ...
> > > } DPDK_2.1;
> > 
> > No, you don't need to collapse. You can just remove Xen functions.
> 
> Thanks.
> 
> Besides, two more things: 
> 1. Shall we increase the so version?

Yes

> 2. This patch is about 8K lines long, do we need to split?

I do not know how you can split a removal.
If you have ideas, feel free.

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v2 5/5] doc: remove dpdk iova aware notice
  @ 2017-09-05 10:31 15%   ` Santosh Shukla
  0 siblings, 0 replies; 200+ results
From: Santosh Shukla @ 2017-09-05 10:31 UTC (permalink / raw)
  To: dev; +Cc: thomas, jerin.jacob, hemant.agrawal, olivier.matz, Santosh Shukla

Removed dpdk iova aware ABI deprecation notice,
and updated ABI change details in release_17.11.rst.

Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
---
 doc/guides/rel_notes/deprecation.rst   |  7 -------
 doc/guides/rel_notes/release_17_11.rst | 27 +++++++++++++++++++++++++++
 2 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 3362f3350..6482363bf 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -32,13 +32,6 @@ Deprecation Notices
 * eal: the support of Xen dom0 will be removed from EAL in 17.11; and with
   that, drivers/net/xenvirt and examples/vhost_xen will also be removed.
 
-* eal: An ABI change is planned for 17.11 to make DPDK aware of IOVA address
-  translation scheme.
-  Reference to phys address in EAL data-structure or functions may change to
-  IOVA address or more appropriate name.
-  The change will be only for the name.
-  Functional aspects of the API or data-structure will remain same.
-
 * The mbuf flags PKT_RX_VLAN_PKT and PKT_RX_QINQ_PKT are deprecated and
   are respectively replaced by PKT_RX_VLAN_STRIPPED and
   PKT_RX_QINQ_STRIPPED, that are better described. The old flags and
diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f916..30d0c0229 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -124,7 +124,34 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* **Following datatypes, structure member and function renamed to iova type.**
 
+  * Renamed ``phys_addr_t`` to ``iova_addr_t``.
+  * Renamed ``buf_physaddr`` to ``buf_iovaaddr`` for struct rte_mbuf.
+  * Renamed ``phys_addr`` to ``iova_addr`` for struct rte_memseg.
+  * The Following memory translation api renamed from:
+
+    * ``rte_mempool_populate_phys()``
+    * ``rte_mempool_populate_phys_tab()``
+    * ``rte_eal_using_phys_addrs()``
+    * ``rte_mem_virt2phy()``
+    * ``rte_dump_physmem_layout()``
+    * ``rte_eal_get_physmem_layout()``
+    * ``rte_eal_get_physmem_size()``
+    * ``rte_malloc_virt2phy()``
+    * ``rte_mem_phy2mch()``
+
+  * To the following iova types api:
+
+    * ``rte_mempool_populate_iova()``
+    * ``rte_mempool_populate_iova_tab()``
+    * ``rte_eal_using_iova_addrs()``
+    * ``rte_mem_virt2iova()``
+    * ``rte_dump_iovamem_layout()``
+    * ``rte_eal_get_iovamem_layout()``
+    * ``rte_eal_get_iovamem_size()``
+    * ``rte_malloc_virt2iova()``
+    * ``rte_mem_phy2iova()``
 
 Shared Library Versions
 -----------------------
-- 
2.11.0

^ permalink raw reply	[relevance 15%]

* [dpdk-dev] DPDK techboard minutes of August 30
@ 2017-09-06  2:57  3% Jerin Jacob
  0 siblings, 0 replies; 200+ results
From: Jerin Jacob @ 2017-09-06  2:57 UTC (permalink / raw)
  To: dev; +Cc: techboard

Hi all,

Here are the meeting notes for the last DPDK technical board meeting
held on 2017-08-30.

Attendees:
- Bruce Richardson
- Declan Doherty
- Hemant Agrawal
- Jan Blunck
- Jerin Jacob
- Konstantin Ananyev
- Keith Wiles
- Olivier Matz
- Stephen Hemminger
- Thomas Monjalon

1) A "dpdk-draft-ipsec" tree on dpdk.org has been approved for collaborating
the on going IPSec offload work. The committers details for this repo
is not yet finalized. Hemant will send the committer details after
discussing with interested parties.

2) The CLI discussion

Discussed the following aspects of CLI
a) Packaging
- The standalone library vs DPDK specific CLI library. Discussed the pros and cons
of both approaches. But not yet finalized on the particular scheme.
b) DPDK integration
- Removal or improve existing cmdline library vs a new CLI library. Not yet
finalized on this aspect. Keith submitted a presentation for the Dublin user-space summit on CLI.
- In order to complete the integration, The existing dpdk.org applications MUST
convert to use the new the CLI APIs
c) Git hosting
- A "dpdk-draft-cli" tree on dpdk.org has been approved for CLI work.

3) The policy for creating new draft trees on dpdk.org will be discussed at 
Dublin User space summit.

4) There was an agreement on bumping the HW requirement to treat similar to
ABI deprecation process. Bruce will send a patch to update the contributor's guide.

5) Next chair

In alphabetical order, Konstantin Ananyev will chair the next meeting.


Thanks,
Jerin

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v5 4/8] doc: remove mempool notice
  @ 2017-09-06 11:28  4%     ` Santosh Shukla
    1 sibling, 0 replies; 200+ results
From: Santosh Shukla @ 2017-09-06 11:28 UTC (permalink / raw)
  To: olivier.matz, dev; +Cc: thomas, jerin.jacob, hemant.agrawal, Santosh Shukla

Removed mempool deprecation notice and
updated change info in release_17.11.

Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
---
v4 --> v5:
- Since mp param replaced by flags param in patch [03/08], 
  incorporated same change in doc.

 doc/guides/rel_notes/deprecation.rst   | 9 ---------
 doc/guides/rel_notes/release_17_11.rst | 7 +++++++
 2 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 3362f3350..0e4cb1f95 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -44,15 +44,6 @@ Deprecation Notices
   PKT_RX_QINQ_STRIPPED, that are better described. The old flags and
   their behavior will be kept until 17.08 and will be removed in 17.11.
 
-* mempool: The following will be modified in 17.11:
-
-  - ``rte_mempool_xmem_size`` and ``rte_mempool_xmem_usage`` need to know
-    the mempool flag status so adding new param rte_mempool in those API.
-  - Removing __rte_unused int flag param from ``rte_mempool_generic_put``
-    and ``rte_mempool_generic_get`` API.
-  - ``rte_mempool`` flags data type will changed from int to
-    unsigned int.
-
 * ethdev: Tx offloads will no longer be enabled by default in 17.11.
   Instead, the ``rte_eth_txmode`` structure will be extended with
   bit field to enable each Tx offload.
diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f916..6b17af7bc 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -110,6 +110,13 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* **The following changes made in mempool library**
+
+  * Moved ``flags`` datatype from int to unsigned int for ``rte_mempool``.
+  * Removed ``__rte_unused int flag`` param from ``rte_mempool_generic_put``
+    and ``rte_mempool_generic_get`` API.
+  * Added ``flags`` param in ``rte_mempool_xmem_size`` and
+    ``rte_mempool_xmem_usage``.
 
 ABI Changes
 -----------
-- 
2.11.0

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH] eventdev: add dev id checks to config functions
  @ 2017-09-06 14:45  3%   ` Van Haaren, Harry
  2017-09-06 14:57  0%     ` Jerin Jacob
  0 siblings, 1 reply; 200+ results
From: Van Haaren, Harry @ 2017-09-06 14:45 UTC (permalink / raw)
  To: Jerin Jacob; +Cc: dev

> From: Jerin Jacob [mailto:jerin.jacob@caviumnetworks.com]
> Sent: Monday, September 4, 2017 6:21 AM
> To: Van Haaren, Harry <harry.van.haaren@intel.com>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH] eventdev: add dev id checks to config functions
> 
> -----Original Message-----
> > Date: Mon, 24 Jul 2017 13:48:20 +0100
> > From: Harry van Haaren <harry.van.haaren@intel.com>
> > To: dev@dpdk.org
> > CC: jerin.jacob@caviumnetworks.com, Harry van Haaren
> >  <harry.van.haaren@intel.com>
> > Subject: [PATCH] eventdev: add dev id checks to config functions
> > X-Mailer: git-send-email 2.7.4
> >
> > This commit adds checks to verify the device ID is valid
> > to the following functions. Given that they are non-datapath,
> > these checks are always performed.
> 
> Makes sense.

Great - lets discuss implementation ;)


> > This commit also updates the event/octeontx test-cases to
> > have the correct signed-ness, as the API has changes this
> > change is required in order to compile.
> >
> > Suggested-by: Jesse Bruni <jesse.bruni@intel.com>
> > Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
> >
> > ---
> > @@ -1288,9 +1293,10 @@ worker_ordered_flow_producer(void *arg)
> >  static inline int
> >  test_producer_consumer_ingress_order_test(int (*fn)(void *))
> >  {
> > -	uint8_t nr_ports;
> > +	int16_t nr_ports;
> >
> > -	nr_ports = RTE_MIN(rte_event_port_count(evdev), rte_lcore_count() - 1);
> > +	nr_ports = RTE_MIN(rte_event_port_count(evdev),
> > +			(int)rte_lcore_count() - 1);
> 
> While I agree on the problem statement, I am trying to see
> 1/ an API symmetrical to ethdev APIs. Similar problem solved in a differently in
> ethdev. see rte_eth_dev_adjust_nb_rx_tx_desc().
> Just want to make sure, all the APIs across ethdev, eventdev looks same
> 
> 2/ How to get rid of above typecasting
> 
> Considering above two points and following the
> rte_eth_dev_adjust_nb_rx_tx_desc() pattern. How about,
> 
> Removing,
> rte_event_port_dequeue_depth()
> rte_event_port_enqueue_depth()
> rte_event_port_count()
> 
> rte_event_queue_count()
> rte_event_queue_priority()
> 
> and change to,
> 
> int rte_event_port_attr_get(uint8_t dev_id, uint8_t port_id,
> uint8_t *enqueue_depth /*out */, uint8_t *dequeue_depth /* out*/, uin8_t *count /*out*/);
> 
> int rte_event_queue_attr_get(uint8_t dev_id, uint8_t port_id,
> uin8_t *prio /* out */, uint8_t *count /*out */);
> 
> or something similar.

Hmm, I don't like that we'd have to break ABI every time we want to add an item to attr_get().. so adding a parameter "attr_id" would allow adding events in future. This solution feels a bit like a re-implementation of the xstats API..

Thoughts? -H


enum {
  PORT_COUNT,
  PORT_DEQUEUE_DEPTH,
  PORT_ENQUEUE_DEPTH,
}

/* retrieve value of port 
int rte_event_port_attr_get(uint8_t dev_id, uint8_t port_id, uint32_t attr_id, uint32_t *attr_value /* out */);

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v3] doc: update NFP with PF support information
@ 2017-09-06 14:47  4% Alejandro Lucero
  2017-09-06 14:55  0% ` Alejandro Lucero
  0 siblings, 1 reply; 200+ results
From: Alejandro Lucero @ 2017-09-06 14:47 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, john.mcnamara, root

From: root <root@netronome.com>

NFP PMD has now support for both, PF and VFs. This patch updates
the guide and give some information about implications.

Signed-off-by: root <root@netronome.com>
---
 doc/guides/nics/nfp.rst | 78 +++++++++++++++++++++++++++++++++++++------------
 1 file changed, 59 insertions(+), 19 deletions(-)

diff --git a/doc/guides/nics/nfp.rst b/doc/guides/nics/nfp.rst
index c732fb1..99a3b76 100644
--- a/doc/guides/nics/nfp.rst
+++ b/doc/guides/nics/nfp.rst
@@ -1,5 +1,5 @@
 ..  BSD LICENSE
-    Copyright(c) 2015 Netronome Systems, Inc. All rights reserved.
+    Copyright(c) 2015-2017 Netronome Systems, Inc. All rights reserved.
     All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
@@ -38,31 +38,32 @@ up to 400 Gbps.
 
 This document explains how to use DPDK with the Netronome Poll Mode
 Driver (PMD) supporting Netronome's Network Flow Processor 6xxx
-(NFP-6xxx).
+(NFP-6xxx) and Netronome's Flow Processor 4xxx (NFP-4xxx).
 
-Currently the driver supports virtual functions (VFs) only.
+NFP is a SRIOV capable device and the PMD driver supports the physical
+function (PF) and virtual functions (VFs).
 
 Dependencies
 ------------
 
-Before using the Netronome's DPDK PMD some NFP-6xxx configuration,
+Before using the Netronome's DPDK PMD some NFP configuration,
 which is not related to DPDK, is required. The system requires
-installation of **Netronome's BSP (Board Support Package)** which includes
-Linux drivers, programs and libraries.
+installation of **Netronome's BSP (Board Support Package)** along
+with some specific NFP firmware application. Netronome's NSP ABI
+version should be 0.20 or higher.
 
-If you have a NFP-6xxx device you should already have the code and
-documentation for doing this configuration. Contact
+If you have a NFP device you should already have the code and
+documentation for doing all this configuration. Contact
 **support@netronome.com** to obtain the latest available firmware.
 
-The NFP Linux kernel drivers (including the required PF driver for the
-NFP) are available on Github at
+The NFP Linux netdev kernel driver for VFs is part of vanilla kernel
+since kernel version 4.5, and support for the PF since kernel version
+4.11. Support for older kernels can be obtained on Github at
 **https://github.com/Netronome/nfp-drv-kmods** along with build
 instructions.
 
-DPDK runs in userspace and PMDs uses the Linux kernel UIO interface to
-allow access to physical devices from userspace. The NFP PMD requires
-the **igb_uio** UIO driver, available with DPDK, to perform correct
-initialization.
+NFP PMD needs to be used along with UIO ``igb_uio`` or VFIO (``vfio-pci``)
+Linux kernel driver.
 
 Building the software
 ---------------------
@@ -71,7 +72,7 @@ Netronome's PMD code is provided in the **drivers/net/nfp** directory.
 Although NFP PMD has Netronome´s BSP dependencies, it is possible to
 compile it along with other DPDK PMDs even if no BSP was installed before.
 Of course, a DPDK app will require such a BSP installed for using the
-NFP PMD.
+NFP PMD, along with a specific NFP firmware application.
 
 Default PMD configuration is at **common_linuxapp configuration** file:
 
@@ -87,14 +88,53 @@ Driver compilation and testing
 Refer to the document :ref:`compiling and testing a PMD for a NIC <pmd_build_and_test>`
 for details.
 
+Using the PF
+------------
+
+NFP PMD has support for using the NFP PF as another DPDK port, but it does not
+have any functionality for controlling VFs. In fact, it is not possible to use
+the PMD with the VFs if the PF is being used by DPDK, that is, with the NFP PF
+bound to ``igb_uio`` or ``vfio-pci`` kernel drivers. Future DPDK version will
+have a PMD able to work with the PF and VFs at the same time and with the PF
+implementing VF management along with other PF-only functionalities/offloads.
+
+The PMD PF has extra work to do which will delay the DPDK app initialization
+like checking if a firmware is already available in the device, uploading the
+firmware if necessary, and configure the Link state properly when starting or
+stopping a PF port. Note that firmware upload is not always necessary which is
+the main delay for NFP PF PMD initialization.
+
+Depending on the Netronome product installed in the system, firmware files
+should be available under ``/lib/firmware/netronome``. DPDK PMD supporting the
+PF requires a specific link, ``/lib/firmware/netronome/nic_dpdk_default.nffw``,
+which should be created automatically with Netronome's Agilio products
+installation.
+
+PF multiport support
+--------------------
+
+Some NFP cards support several physical ports with just one single PCI device.
+DPDK core is designed with the 1:1 relationship between PCI devices and DPDK
+ports, so NFP PMD PF support requires handling the multiport case specifically.
+During NFP PF initialization, the PMD will extract the information about the
+number of PF ports from the firmware and will create as many DPDK ports as
+needed.
+
+Because the unusual relationship between a single PCI device and several DPDK
+ports, there are some limitations when using more than one PF DPDK ports: there
+is no support for RX interrupts and it is not possible either to use those PF
+ports with the device hotplug functionality.
+
 
 System configuration
 --------------------
 
-#. **Enable SR-IOV on the NFP-6xxx device:** The current NFP PMD works with
-   Virtual Functions (VFs) on a NFP device. Make sure that one of the Physical
-   Function (PF) drivers from the above Github repository is installed and
-   loaded.
+#. **Enable SR-IOV on the NFP device:** The current NFP PMD supports the PF and
+   the VFs on a NFP device. However, it is not possible to work with both at the
+   same time because the VFs require the PF being bound to the NFP PF Linux
+   netdev driver.  Make sure you are working with a kernel with NFP PF support or
+   get the drivers from the above Github repository and follow the instructions
+   for building and installing it.
 
    Virtual Functions need to be enabled before they can be used with the PMD.
    Before enabling the VFs it is useful to obtain information about the
-- 
1.9.1

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v2] devtools: rework abi checker script
  2017-08-30 13:51 27% [dpdk-dev] [PATCH] devtools: rework abi checker script Olivier Matz
  2017-09-04 16:00  8% ` Bruce Richardson
@ 2017-09-06 14:51 27% ` Olivier Matz
  2017-09-08 13:46  9%   ` Neil Horman
  1 sibling, 1 reply; 200+ results
From: Olivier Matz @ 2017-09-06 14:51 UTC (permalink / raw)
  To: dev, nhorman, bruce.richardson

The intiatial version of the script had some limitations:
- cannot work on a non-clean workspace
- environment variables are not documented
- no compilation log in case of failure
- return success even it abi is incompatible

This patch addresses these issues and rework the code.

Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---

v1->v2:
- use /usr/bin/env to find bash (which is required)
- fix displayed path to html reports
- reword help for -f option

 devtools/validate-abi.sh | 389 ++++++++++++++++++++++++-----------------------
 1 file changed, 197 insertions(+), 192 deletions(-)

diff --git a/devtools/validate-abi.sh b/devtools/validate-abi.sh
index 0accc99b1..d747db189 100755
--- a/devtools/validate-abi.sh
+++ b/devtools/validate-abi.sh
@@ -1,7 +1,8 @@
-#!/bin/sh
+#!/usr/bin/env bash
 #   BSD LICENSE
 #
 #   Copyright(c) 2015 Neil Horman. All rights reserved.
+#   Copyright(c) 2017 6WIND S.A.
 #   All rights reserved.
 #
 #   Redistribution and use in source and binary forms, with or without
@@ -27,236 +28,240 @@
 #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-TAG1=$1
-TAG2=$2
-TARGET=$3
-ABI_DIR=`mktemp -d -p /tmp ABI.XXXXXX`
+set -e
 
-usage() {
-	echo "$0 <REV1> <REV2> <TARGET>"
-}
+abicheck=abi-compliance-checker
+abidump=abi-dumper
+default_dst=abi-check
+default_target=x86_64-native-linuxapp-gcc
 
-log() {
-	local level=$1
-	shift
-	echo "$*"
+# trap on error
+err_report() {
+    echo "$0: error at line $1"
 }
+trap 'err_report $LINENO' ERR
 
-validate_tags() {
+print_usage () {
+	cat <<- END_OF_HELP
+	$(basename $0) [options] <rev1> <rev2>
 
-	if [ -z "$HASH1" ]
-	then
-		echo "invalid revision: $TAG1"
-		return
-	fi
-	if [ -z "$HASH2" ]
-	then
-		echo "invalid revision: $TAG2"
-		return
-	fi
+	This script compares the ABI of 2 git revisions of the current
+	workspace. The output is a html report and a compilation log.
+
+	The objective is to make sure that applications built against
+	DSOs from the first revision can still run when executed using
+	the DSOs built from the second revision.
+
+	<rev1> and <rev2> are git commit id or tags.
+
+	Options:
+	  -h		show this help
+	  -j <num>	enable parallel compilation with <num> threads
+	  -v		show compilation logs on the console
+	  -d <dir>	change working directory (default is ${default_dst})
+	  -t <target>	the dpdk target to use (default is ${default_target})
+	  -f		overwrite existing files in destination directory
+
+	The script returns 0 on success, or the value of last failing
+	call of ${abicheck} (incompatible abi or the tool has run with errors).
+	The errors returned by ${abidump} are ignored.
+
+	END_OF_HELP
 }
 
-validate_args() {
-	if [ -z "$TAG1" ]
-	then
-		echo "Must Specify REV1"
-		return
-	fi
-	if [ -z "$TAG2" ]
-	then
-		echo "Must Specify REV2"
-		return
-	fi
-	if [ -z "$TARGET" ]
-	then
-		echo "Must Specify a build target"
+# log in the file, and on stdout if verbose
+# $1: level string
+# $2: string to be logged
+log() {
+	echo "$1: $2"
+	if [ "${verbose}" != "true" ]; then
+		echo "$1: $2" >&3
 	fi
 }
 
+# launch a command and log it, taking care of surrounding spaces with quotes
+cmd() {
+	local i s whitespace
+	s=""
+	whitespace="[[:space:]]"
+	for i in "$@"; do
+		if [[ $i =~ $whitespace ]]; then
+			i=\"$i\"
+		fi
+		if [ -z "$s" ]; then
+			s="$i"
+		else
+			s="$s $i"
+		fi
+	done
+
+	log "CMD" "$s"
+	"$@"
+}
 
-cleanup_and_exit() {
-	rm -rf $ABI_DIR
-	git checkout $CURRENT_BRANCH
-	exit $1
+# redirect or copy stderr/stdout to a file
+# the syntax is unfamiliar, but it makes the rest of the
+# code easier to read, avoiding the use of pipes
+set_log_file() {
+	# save original stdout and stderr in fd 3 and 4
+	exec 3>&1
+	exec 4>&2
+	# create a new fd 5 that send to a file
+	exec 5> >(cat > $1)
+	# send stdout and stderr to fd 5
+	if [ "${verbose}" = "true" ]; then
+		exec 1> >(tee /dev/fd/5 >&3)
+		exec 2> >(tee /dev/fd/5 >&4)
+	else
+		exec 1>&5
+		exec 2>&5
+	fi
 }
 
 # Make sure we configure SHARED libraries
 # Also turn off IGB and KNI as those require kernel headers to build
 fixup_config() {
-	sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" config/defconfig_$TARGET
-	sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" config/defconfig_$TARGET
-	sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" config/defconfig_$TARGET
-	sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" config/defconfig_$TARGET
-	sed -i -e"$ a\CONFIG_RTE_KNI_KMOD=n" config/defconfig_$TARGET
+	local conf=config/defconfig_$target
+	cmd sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" $conf
+	cmd sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" $conf
+	cmd sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" $conf
+	cmd sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" $conf
+	cmd sed -i -e"$ a\CONFIG_RTE_KNI_KMOD=n" $conf
 }
 
-###########################################
-#START
-############################################
+# build dpdk for the given tag and dump abi
+# $1: hash of the revision
+gen_abi() {
+	cmd git clone $(dirname $0)/.. ${dst}/${1}
+	cmd cd ${dst}/${1}
+
+	log "INFO" "Checking out version ${1} of the dpdk"
+	# Move to the old version of the tree
+	cmd git checkout ${1}
+
+	fixup_config
+
+	# Now configure the build
+	log "INFO" "Configuring DPDK ${1}"
+	cmd make config T=$target O=$target > ${dst}/log 2>&1
+
+	# Checking abi compliance relies on using the dwarf information in
+	# the shared objects. Build with -g to include them.
+	log "INFO" "Building DPDK ${1}. This might take a moment"
+	cmd make -j$parallel O=$target V=1 EXTRA_CFLAGS="-g -O0" \
+	    EXTRA_LDFLAGS="-g" || log "INFO" "The build failed"
+
+	# Move to the lib directory
+	cmd cd ${PWD}/$target/lib
+	log "INFO" "Collecting ABI information for ${1}"
+	for i in *.so; do
+		[ -e "$i" ] || break
+		cmd $abidump ${i} -o $dst/${1}/${i}.dump -lver ${1} || true
+		# hack to ignore empty SymbolsInfo section (no public ABI)
+		if grep -q "'SymbolInfo' => {}," $dst/${1}/${i}.dump \
+				2> /dev/null; then
+			log "INFO" "${i} has no public ABI, remove dump file"
+			cmd rm -f $dst/${1}/${i}.dump
+		fi
+	done
+	cmd cd ../..
+}
 
-#trap on ctrl-c to clean up
-trap cleanup_and_exit SIGINT
+verbose=false
+parallel=1
+dst=${default_dst}
+target=${default_target}
+force=0
+while getopts j:vd:t:fh ARG ; do
+	case $ARG in
+		j ) parallel=$OPTARG ;;
+		v ) verbose=true ;;
+		d ) dst=$OPTARG ;;
+		t ) target=$OPTARG ;;
+		f ) force=1 ;;
+		h ) print_usage ; exit 0 ;;
+		? ) print_usage ; exit 1 ;;
+	esac
+done
+shift $(($OPTIND - 1))
 
-if [ -z "$DPDK_MAKE_JOBS" ]
-then
-	# This counts the number of cpus on the system
-	if [ -e /usr/bin/lscpu ]
-	then
-		DPDK_MAKE_JOBS=`lscpu -p=cpu | grep -v "#" | wc -l`
-	else
-		DPDK_MAKE_JOBS=1
-	fi
+if [ $# != 2 ]; then
+	print_usage
+	exit 1
 fi
 
-#Save the current branch
-CURRENT_BRANCH=`git branch | grep \* | cut -d' ' -f2`
+tag1=$1
+tag2=$2
 
-if [ -z "$CURRENT_BRANCH" ]
-then
-	CURRENT_BRANCH=`git log --pretty=format:%H HEAD~1..HEAD`
-fi
+# convert path to absolute
+case "${dst}" in
+	/*) ;;
+	*) dst=${PWD}/${dst} ;;
+esac
 
-if [ -n "$VERBOSE" ]
-then
-	export VERBOSE=/dev/stdout
-else
-	export VERBOSE=/dev/null
+if [ -e "${dst}" -a "$force" = 0 ]; then
+	echo "The ${dst} directory is not empty. Remove it, use another"
+	echo "one (-d <dir>), or force overriding (-f)"
+	exit 1
 fi
 
-# Validate that we have all the arguments we need
-res=$(validate_args)
-if [ -n "$res" ]
-then
-	echo $res
-	usage
-	cleanup_and_exit 1
-fi
+rm -rf ${dst}
+mkdir -p ${dst}
+set_log_file ${dst}/abi-check.log
+log "INFO" "Logs available in ${dst}/abi-check.log"
 
-HASH1=$(git show -s --format=%H "$TAG1" -- 2> /dev/null | tail -1)
-HASH2=$(git show -s --format=%H "$TAG2" -- 2> /dev/null | tail -1)
+command -v ${abicheck} || log "INFO" "Can't find ${abicheck} utility"
+command -v ${abidump} || log "INFO" "Can't find ${abidump} utility"
 
-# Make sure our tags exist
-res=$(validate_tags)
-if [ -n "$res" ]
-then
-	echo $res
-	cleanup_and_exit 1
-fi
+hash1=$(git show -s --format=%h "$tag1" -- 2> /dev/null | tail -1)
+hash2=$(git show -s --format=%h "$tag2" -- 2> /dev/null | tail -1)
 
 # Make hashes available in output for non-local reference
-TAG1="$TAG1 ($HASH1)"
-TAG2="$TAG2 ($HASH2)"
-
-ABICHECK=`which abi-compliance-checker 2>/dev/null`
-if [ $? -ne 0 ]
-then
-	log "INFO" "Can't find abi-compliance-checker utility"
-	cleanup_and_exit 1
-fi
-
-ABIDUMP=`which abi-dumper 2>/dev/null`
-if [ $? -ne 0 ]
-then
-	log "INFO" "Can't find abi-dumper utility"
-	cleanup_and_exit 1
-fi
+tag1="$tag1 ($hash1)"
+tag2="$tag2 ($hash2)"
 
-log "INFO" "We're going to check and make sure that applications built"
-log "INFO" "against DPDK DSOs from version $TAG1 will still run when executed"
-log "INFO" "against DPDK DSOs built from version $TAG2."
-log "INFO" ""
-
-# Check to make sure we have a clean tree
-git status | grep -q clean
-if [ $? -ne 0 ]
-then
-	log "WARN" "Working directory not clean, aborting"
-	cleanup_and_exit 1
+if [ "$hash1" = "$hash2" ]; then
+	log "ERROR" "$tag1 and $tag2 are the same revisions"
+	exit 1
 fi
 
-# Move to the root of the git tree
-cd $(dirname $0)/..
+cmd mkdir -p ${dst}
 
-log "INFO" "Checking out version $TAG1 of the dpdk"
-# Move to the old version of the tree
-git checkout $HASH1
+# dump abi for each revision
+gen_abi ${hash1}
+gen_abi ${hash2}
 
-fixup_config
+# compare the abi dumps
+ret=0
+list=""
+for i in ${dst}/${hash2}/*.dump; do
+	name=`basename $i`
+	libname=${name%.dump}
 
-# Checking abi compliance relies on using the dwarf information in
-# The shared objects.  Thats only included in the DSO's if we build
-# with -g
-export EXTRA_CFLAGS="$EXTRA_CFLAGS -g -O0"
-export EXTRA_LDFLAGS="$EXTRA_LDFLAGS -g"
-
-# Now configure the build
-log "INFO" "Configuring DPDK $TAG1"
-make config T=$TARGET O=$TARGET > $VERBOSE 2>&1
-
-log "INFO" "Building DPDK $TAG1. This might take a moment"
-make -j$DPDK_MAKE_JOBS O=$TARGET > $VERBOSE 2>&1
-
-if [ $? -ne 0 ]
-then
-	log "INFO" "THE BUILD FAILED.  ABORTING"
-	cleanup_and_exit 1
-fi
+	if [ ! -f $dst/${hash1}/$name ]; then
+		log "INFO" "$NAME does not exist in $tag1. skipping..."
+		continue
+	fi
 
-# Move to the lib directory
-cd $TARGET/lib
-log "INFO" "COLLECTING ABI INFORMATION FOR $TAG1"
-for i in `ls *.so`
-do
-	$ABIDUMP $i -o $ABI_DIR/$i-ABI-0.dump -lver $HASH1
+	local_ret=0
+	cmd $abicheck -l $libname \
+	    -old $dst/${hash1}/$name -new $dst/${hash2}/$name || local_ret=$?
+	if [ $local_ret != 0 ]; then
+		log "NOTICE" "$abicheck returned $local_ret"
+		ret=$local_ret
+		list="$list $libname"
+	fi
 done
-cd ../..
-
-# Now clean the tree, checkout the second tag, and rebuild
-git clean -f -d
-git reset --hard
-# Move to the new version of the tree
-log "INFO" "Checking out version $TAG2 of the dpdk"
-git checkout $HASH2
-
-fixup_config
-
-# Now configure the build
-log "INFO" "Configuring DPDK $TAG2"
-make config T=$TARGET O=$TARGET > $VERBOSE 2>&1
-
-log "INFO" "Building DPDK $TAG2. This might take a moment"
-make -j$DPDK_MAKE_JOBS O=$TARGET > $VERBOSE 2>&1
 
-if [ $? -ne 0 ]
-then
-	log "INFO" "THE BUILD FAILED.  ABORTING"
-	cleanup_and_exit 1
+if [ $ret != 0 ]; then
+	log "NOTICE" "At least one call to $abicheck returned an error."
+	log "NOTICE" "ABI may be incompatible, please check logs for details."
+	log "NOTICE" "Incompatible list: $list"
+else
+	log "NOTICE" "No error detected, ABI is compatible."
 fi
 
-cd $TARGET/lib
-log "INFO" "COLLECTING ABI INFORMATION FOR $TAG2"
-for i in `ls *.so`
-do
-	$ABIDUMP $i -o $ABI_DIR/$i-ABI-1.dump -lver $HASH2
-done
-cd ../..
-
-# Start comparison of ABI dumps
-for i in `ls $ABI_DIR/*-1.dump`
-do
-	NEWNAME=`basename $i`
-	OLDNAME=`basename $i | sed -e"s/1.dump/0.dump/"`
-	LIBNAME=`basename $i | sed -e"s/-ABI-1.dump//"`
-
-	if [ ! -f $ABI_DIR/$OLDNAME ]
-	then
-		log "INFO" "$OLDNAME DOES NOT EXIST IN $TAG1. SKIPPING..."
-	fi
-
-	#compare the abi dumps
-	$ABICHECK -l $LIBNAME -old $ABI_DIR/$OLDNAME -new $ABI_DIR/$NEWNAME
-done
+log "INFO" "Logs are in ${dst}/abi-check.log"
+log "INFO" "HTML reports are in ${dst}/${hash2}/compat_reports directory"
 
-git reset --hard
-log "INFO" "ABI CHECK COMPLETE.  REPORTS ARE IN compat_report directory"
-cleanup_and_exit 0
+exit $ret
-- 
2.11.0

^ permalink raw reply	[relevance 27%]

* Re: [dpdk-dev] [PATCH v3] doc: update NFP with PF support information
  2017-09-06 14:47  4% [dpdk-dev] [PATCH v3] doc: update NFP with PF support information Alejandro Lucero
@ 2017-09-06 14:55  0% ` Alejandro Lucero
  0 siblings, 0 replies; 200+ results
From: Alejandro Lucero @ 2017-09-06 14:55 UTC (permalink / raw)
  To: dev; +Cc: Ferruh Yigit, Mcnamara, John, root

It seems I did not commit with the right signature.

I will send it again. Sorry about this.

On Wed, Sep 6, 2017 at 3:47 PM, Alejandro Lucero <
alejandro.lucero@netronome.com> wrote:

> From: root <root@netronome.com>
>
> NFP PMD has now support for both, PF and VFs. This patch updates
> the guide and give some information about implications.
>
> Signed-off-by: root <root@netronome.com>
> ---
>  doc/guides/nics/nfp.rst | 78 ++++++++++++++++++++++++++++++
> +++++++------------
>  1 file changed, 59 insertions(+), 19 deletions(-)
>
> diff --git a/doc/guides/nics/nfp.rst b/doc/guides/nics/nfp.rst
> index c732fb1..99a3b76 100644
> --- a/doc/guides/nics/nfp.rst
> +++ b/doc/guides/nics/nfp.rst
> @@ -1,5 +1,5 @@
>  ..  BSD LICENSE
> -    Copyright(c) 2015 Netronome Systems, Inc. All rights reserved.
> +    Copyright(c) 2015-2017 Netronome Systems, Inc. All rights reserved.
>      All rights reserved.
>
>      Redistribution and use in source and binary forms, with or without
> @@ -38,31 +38,32 @@ up to 400 Gbps.
>
>  This document explains how to use DPDK with the Netronome Poll Mode
>  Driver (PMD) supporting Netronome's Network Flow Processor 6xxx
> -(NFP-6xxx).
> +(NFP-6xxx) and Netronome's Flow Processor 4xxx (NFP-4xxx).
>
> -Currently the driver supports virtual functions (VFs) only.
> +NFP is a SRIOV capable device and the PMD driver supports the physical
> +function (PF) and virtual functions (VFs).
>
>  Dependencies
>  ------------
>
> -Before using the Netronome's DPDK PMD some NFP-6xxx configuration,
> +Before using the Netronome's DPDK PMD some NFP configuration,
>  which is not related to DPDK, is required. The system requires
> -installation of **Netronome's BSP (Board Support Package)** which includes
> -Linux drivers, programs and libraries.
> +installation of **Netronome's BSP (Board Support Package)** along
> +with some specific NFP firmware application. Netronome's NSP ABI
> +version should be 0.20 or higher.
>
> -If you have a NFP-6xxx device you should already have the code and
> -documentation for doing this configuration. Contact
> +If you have a NFP device you should already have the code and
> +documentation for doing all this configuration. Contact
>  **support@netronome.com** to obtain the latest available firmware.
>
> -The NFP Linux kernel drivers (including the required PF driver for the
> -NFP) are available on Github at
> +The NFP Linux netdev kernel driver for VFs is part of vanilla kernel
> +since kernel version 4.5, and support for the PF since kernel version
> +4.11. Support for older kernels can be obtained on Github at
>  **https://github.com/Netronome/nfp-drv-kmods** along with build
>  instructions.
>
> -DPDK runs in userspace and PMDs uses the Linux kernel UIO interface to
> -allow access to physical devices from userspace. The NFP PMD requires
> -the **igb_uio** UIO driver, available with DPDK, to perform correct
> -initialization.
> +NFP PMD needs to be used along with UIO ``igb_uio`` or VFIO (``vfio-pci``)
> +Linux kernel driver.
>
>  Building the software
>  ---------------------
> @@ -71,7 +72,7 @@ Netronome's PMD code is provided in the
> **drivers/net/nfp** directory.
>  Although NFP PMD has Netronome´s BSP dependencies, it is possible to
>  compile it along with other DPDK PMDs even if no BSP was installed before.
>  Of course, a DPDK app will require such a BSP installed for using the
> -NFP PMD.
> +NFP PMD, along with a specific NFP firmware application.
>
>  Default PMD configuration is at **common_linuxapp configuration** file:
>
> @@ -87,14 +88,53 @@ Driver compilation and testing
>  Refer to the document :ref:`compiling and testing a PMD for a NIC
> <pmd_build_and_test>`
>  for details.
>
> +Using the PF
> +------------
> +
> +NFP PMD has support for using the NFP PF as another DPDK port, but it
> does not
> +have any functionality for controlling VFs. In fact, it is not possible
> to use
> +the PMD with the VFs if the PF is being used by DPDK, that is, with the
> NFP PF
> +bound to ``igb_uio`` or ``vfio-pci`` kernel drivers. Future DPDK version
> will
> +have a PMD able to work with the PF and VFs at the same time and with the
> PF
> +implementing VF management along with other PF-only
> functionalities/offloads.
> +
> +The PMD PF has extra work to do which will delay the DPDK app
> initialization
> +like checking if a firmware is already available in the device, uploading
> the
> +firmware if necessary, and configure the Link state properly when
> starting or
> +stopping a PF port. Note that firmware upload is not always necessary
> which is
> +the main delay for NFP PF PMD initialization.
> +
> +Depending on the Netronome product installed in the system, firmware files
> +should be available under ``/lib/firmware/netronome``. DPDK PMD
> supporting the
> +PF requires a specific link, ``/lib/firmware/netronome/nic_
> dpdk_default.nffw``,
> +which should be created automatically with Netronome's Agilio products
> +installation.
> +
> +PF multiport support
> +--------------------
> +
> +Some NFP cards support several physical ports with just one single PCI
> device.
> +DPDK core is designed with the 1:1 relationship between PCI devices and
> DPDK
> +ports, so NFP PMD PF support requires handling the multiport case
> specifically.
> +During NFP PF initialization, the PMD will extract the information about
> the
> +number of PF ports from the firmware and will create as many DPDK ports as
> +needed.
> +
> +Because the unusual relationship between a single PCI device and several
> DPDK
> +ports, there are some limitations when using more than one PF DPDK ports:
> there
> +is no support for RX interrupts and it is not possible either to use
> those PF
> +ports with the device hotplug functionality.
> +
>
>  System configuration
>  --------------------
>
> -#. **Enable SR-IOV on the NFP-6xxx device:** The current NFP PMD works
> with
> -   Virtual Functions (VFs) on a NFP device. Make sure that one of the
> Physical
> -   Function (PF) drivers from the above Github repository is installed and
> -   loaded.
> +#. **Enable SR-IOV on the NFP device:** The current NFP PMD supports the
> PF and
> +   the VFs on a NFP device. However, it is not possible to work with both
> at the
> +   same time because the VFs require the PF being bound to the NFP PF
> Linux
> +   netdev driver.  Make sure you are working with a kernel with NFP PF
> support or
> +   get the drivers from the above Github repository and follow the
> instructions
> +   for building and installing it.
>
>     Virtual Functions need to be enabled before they can be used with the
> PMD.
>     Before enabling the VFs it is useful to obtain information about the
> --
> 1.9.1
>
>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] eventdev: add dev id checks to config functions
  2017-09-06 14:45  3%   ` Van Haaren, Harry
@ 2017-09-06 14:57  0%     ` Jerin Jacob
  0 siblings, 0 replies; 200+ results
From: Jerin Jacob @ 2017-09-06 14:57 UTC (permalink / raw)
  To: Van Haaren, Harry; +Cc: dev

-----Original Message-----
> Date: Wed, 6 Sep 2017 14:45:29 +0000
> From: "Van Haaren, Harry" <harry.van.haaren@intel.com>
> To: Jerin Jacob <jerin.jacob@caviumnetworks.com>
> CC: "dev@dpdk.org" <dev@dpdk.org>
> Subject: RE: [PATCH] eventdev: add dev id checks to config functions
> 
> > From: Jerin Jacob [mailto:jerin.jacob@caviumnetworks.com]
> > Sent: Monday, September 4, 2017 6:21 AM
> > To: Van Haaren, Harry <harry.van.haaren@intel.com>
> > Cc: dev@dpdk.org
> > Subject: Re: [PATCH] eventdev: add dev id checks to config functions
> > 
> > -----Original Message-----
> > > Date: Mon, 24 Jul 2017 13:48:20 +0100
> > > From: Harry van Haaren <harry.van.haaren@intel.com>
> > > To: dev@dpdk.org
> > > CC: jerin.jacob@caviumnetworks.com, Harry van Haaren
> > >  <harry.van.haaren@intel.com>
> > > Subject: [PATCH] eventdev: add dev id checks to config functions
> > > X-Mailer: git-send-email 2.7.4
> > >
> > > This commit adds checks to verify the device ID is valid
> > > to the following functions. Given that they are non-datapath,
> > > these checks are always performed.
> > 
> > Makes sense.
> 
> Great - lets discuss implementation ;)
> 
> 
> > > This commit also updates the event/octeontx test-cases to
> > > have the correct signed-ness, as the API has changes this
> > > change is required in order to compile.
> > >
> > > Suggested-by: Jesse Bruni <jesse.bruni@intel.com>
> > > Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
> > >
> > > ---
> > > @@ -1288,9 +1293,10 @@ worker_ordered_flow_producer(void *arg)
> > >  static inline int
> > >  test_producer_consumer_ingress_order_test(int (*fn)(void *))
> > >  {
> > > -	uint8_t nr_ports;
> > > +	int16_t nr_ports;
> > >
> > > -	nr_ports = RTE_MIN(rte_event_port_count(evdev), rte_lcore_count() - 1);
> > > +	nr_ports = RTE_MIN(rte_event_port_count(evdev),
> > > +			(int)rte_lcore_count() - 1);
> > 
> > While I agree on the problem statement, I am trying to see
> > 1/ an API symmetrical to ethdev APIs. Similar problem solved in a differently in
> > ethdev. see rte_eth_dev_adjust_nb_rx_tx_desc().
> > Just want to make sure, all the APIs across ethdev, eventdev looks same
> > 
> > 2/ How to get rid of above typecasting
> > 
> > Considering above two points and following the
> > rte_eth_dev_adjust_nb_rx_tx_desc() pattern. How about,
> > 
> > Removing,
> > rte_event_port_dequeue_depth()
> > rte_event_port_enqueue_depth()
> > rte_event_port_count()
> > 
> > rte_event_queue_count()
> > rte_event_queue_priority()
> > 
> > and change to,
> > 
> > int rte_event_port_attr_get(uint8_t dev_id, uint8_t port_id,
> > uint8_t *enqueue_depth /*out */, uint8_t *dequeue_depth /* out*/, uin8_t *count /*out*/);
> > 
> > int rte_event_queue_attr_get(uint8_t dev_id, uint8_t port_id,
> > uin8_t *prio /* out */, uint8_t *count /*out */);
> > 
> > or something similar.
> 
> Hmm, I don't like that we'd have to break ABI every time we want to add an item to attr_get().. so adding a parameter "attr_id" would allow adding events in future. This solution feels a bit like a re-implementation of the xstats API..
> 
> Thoughts? -H
> 
> 
> enum {
>   PORT_COUNT,
>   PORT_DEQUEUE_DEPTH,
>   PORT_ENQUEUE_DEPTH,
> }
> 
> /* retrieve value of port 
> int rte_event_port_attr_get(uint8_t dev_id, uint8_t port_id, uint32_t attr_id, uint32_t *attr_value /* out */);

Looks good to me.

> 
> 

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v3] doc: update NFP with PF support information
@ 2017-09-06 15:14  4% Alejandro Lucero
  0 siblings, 0 replies; 200+ results
From: Alejandro Lucero @ 2017-09-06 15:14 UTC (permalink / raw)
  To: dev; +Cc: ferruh.yigit, john.mcnamara

NFP PMD has now support for both, PF and VFs. This patch updates
the guide and give some information about implications.

Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
---
 doc/guides/nics/nfp.rst | 78 +++++++++++++++++++++++++++++++++++++------------
 1 file changed, 59 insertions(+), 19 deletions(-)

diff --git a/doc/guides/nics/nfp.rst b/doc/guides/nics/nfp.rst
index c732fb1..99a3b76 100644
--- a/doc/guides/nics/nfp.rst
+++ b/doc/guides/nics/nfp.rst
@@ -1,5 +1,5 @@
 ..  BSD LICENSE
-    Copyright(c) 2015 Netronome Systems, Inc. All rights reserved.
+    Copyright(c) 2015-2017 Netronome Systems, Inc. All rights reserved.
     All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
@@ -38,31 +38,32 @@ up to 400 Gbps.
 
 This document explains how to use DPDK with the Netronome Poll Mode
 Driver (PMD) supporting Netronome's Network Flow Processor 6xxx
-(NFP-6xxx).
+(NFP-6xxx) and Netronome's Flow Processor 4xxx (NFP-4xxx).
 
-Currently the driver supports virtual functions (VFs) only.
+NFP is a SRIOV capable device and the PMD driver supports the physical
+function (PF) and virtual functions (VFs).
 
 Dependencies
 ------------
 
-Before using the Netronome's DPDK PMD some NFP-6xxx configuration,
+Before using the Netronome's DPDK PMD some NFP configuration,
 which is not related to DPDK, is required. The system requires
-installation of **Netronome's BSP (Board Support Package)** which includes
-Linux drivers, programs and libraries.
+installation of **Netronome's BSP (Board Support Package)** along
+with some specific NFP firmware application. Netronome's NSP ABI
+version should be 0.20 or higher.
 
-If you have a NFP-6xxx device you should already have the code and
-documentation for doing this configuration. Contact
+If you have a NFP device you should already have the code and
+documentation for doing all this configuration. Contact
 **support@netronome.com** to obtain the latest available firmware.
 
-The NFP Linux kernel drivers (including the required PF driver for the
-NFP) are available on Github at
+The NFP Linux netdev kernel driver for VFs is part of vanilla kernel
+since kernel version 4.5, and support for the PF since kernel version
+4.11. Support for older kernels can be obtained on Github at
 **https://github.com/Netronome/nfp-drv-kmods** along with build
 instructions.
 
-DPDK runs in userspace and PMDs uses the Linux kernel UIO interface to
-allow access to physical devices from userspace. The NFP PMD requires
-the **igb_uio** UIO driver, available with DPDK, to perform correct
-initialization.
+NFP PMD needs to be used along with UIO ``igb_uio`` or VFIO (``vfio-pci``)
+Linux kernel driver.
 
 Building the software
 ---------------------
@@ -71,7 +72,7 @@ Netronome's PMD code is provided in the **drivers/net/nfp** directory.
 Although NFP PMD has Netronome´s BSP dependencies, it is possible to
 compile it along with other DPDK PMDs even if no BSP was installed before.
 Of course, a DPDK app will require such a BSP installed for using the
-NFP PMD.
+NFP PMD, along with a specific NFP firmware application.
 
 Default PMD configuration is at **common_linuxapp configuration** file:
 
@@ -87,14 +88,53 @@ Driver compilation and testing
 Refer to the document :ref:`compiling and testing a PMD for a NIC <pmd_build_and_test>`
 for details.
 
+Using the PF
+------------
+
+NFP PMD has support for using the NFP PF as another DPDK port, but it does not
+have any functionality for controlling VFs. In fact, it is not possible to use
+the PMD with the VFs if the PF is being used by DPDK, that is, with the NFP PF
+bound to ``igb_uio`` or ``vfio-pci`` kernel drivers. Future DPDK version will
+have a PMD able to work with the PF and VFs at the same time and with the PF
+implementing VF management along with other PF-only functionalities/offloads.
+
+The PMD PF has extra work to do which will delay the DPDK app initialization
+like checking if a firmware is already available in the device, uploading the
+firmware if necessary, and configure the Link state properly when starting or
+stopping a PF port. Note that firmware upload is not always necessary which is
+the main delay for NFP PF PMD initialization.
+
+Depending on the Netronome product installed in the system, firmware files
+should be available under ``/lib/firmware/netronome``. DPDK PMD supporting the
+PF requires a specific link, ``/lib/firmware/netronome/nic_dpdk_default.nffw``,
+which should be created automatically with Netronome's Agilio products
+installation.
+
+PF multiport support
+--------------------
+
+Some NFP cards support several physical ports with just one single PCI device.
+DPDK core is designed with the 1:1 relationship between PCI devices and DPDK
+ports, so NFP PMD PF support requires handling the multiport case specifically.
+During NFP PF initialization, the PMD will extract the information about the
+number of PF ports from the firmware and will create as many DPDK ports as
+needed.
+
+Because the unusual relationship between a single PCI device and several DPDK
+ports, there are some limitations when using more than one PF DPDK ports: there
+is no support for RX interrupts and it is not possible either to use those PF
+ports with the device hotplug functionality.
+
 
 System configuration
 --------------------
 
-#. **Enable SR-IOV on the NFP-6xxx device:** The current NFP PMD works with
-   Virtual Functions (VFs) on a NFP device. Make sure that one of the Physical
-   Function (PF) drivers from the above Github repository is installed and
-   loaded.
+#. **Enable SR-IOV on the NFP device:** The current NFP PMD supports the PF and
+   the VFs on a NFP device. However, it is not possible to work with both at the
+   same time because the VFs require the PF being bound to the NFP PF Linux
+   netdev driver.  Make sure you are working with a kernel with NFP PF support or
+   get the drivers from the above Github repository and follow the instructions
+   for building and installing it.
 
    Virtual Functions need to be enabled before they can be used with the PMD.
    Before enabling the VFs it is useful to obtain information about the
-- 
1.9.1

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v3 2/2] ethdev: allow pmd to advertise pool handle
  2017-09-04 13:14  0%       ` santosh
@ 2017-09-07  9:21  0%         ` Hemant Agrawal
  2017-09-07 10:06  0%           ` santosh
  0 siblings, 1 reply; 200+ results
From: Hemant Agrawal @ 2017-09-07  9:21 UTC (permalink / raw)
  To: santosh, Olivier MATZ; +Cc: dev, thomas, jerin.jacob

On 9/4/2017 6:44 PM, santosh wrote:
> Hi Olivier,
>
>
> On Monday 04 September 2017 05:41 PM, Olivier MATZ wrote:
>> Hi Santosh,
>>
>> On Tue, Aug 15, 2017 at 01:37:17PM +0530, Santosh Shukla wrote:
>>> Now that dpdk supports more than one mempool drivers and
>>> each mempool driver works best for specific PMD, example:
>>> - sw ring based mempool for Intel PMD drivers
>>> - dpaa2 HW mempool manager for dpaa2 PMD driver.
>>> - fpa HW mempool manager for Octeontx PMD driver.
>>>
>>> Application like to know `preferred mempool vs PMD driver`
>>> information in advance before port setup.
>>>
>>> Introducing rte_eth_dev_get_preferred_pool_ops() API,
>>> which allows PMD driver to advertise their pool capability to application.
>>>
>>> Application side programing sequence would be:
>>>
>>> char pref_mempool[RTE_MEMPOOL_OPS_NAMESIZE];
>>> rte_eth_dev_get_preferred_pool_ops(ethdev_port_id, pref_mempoolx /*out*/);
>>> rte_mempool_create_empty();
>>> rte_mempool_set_ops_byname( , pref_memppol, );
>>> rte_mempool_populate_default();
>>>
>>> Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
>>> ---
>>> v2 --> v3:
>>> - Updated version.map entry to DPDK_v17.11.
>>>
>>> v1 --> v2:
>>> - Renamed _get_preferred_pool to _get_preferred_pool_ops().
>>> Per v1 review feedback, Olivier suggested to rename api
>>> to rte_eth_dev_pool_ops_supported(), considering that 2nd param
>>> for that api will return pool handle 'priority' for that port.
>>> However, per v1 [1], we're opting for approach 1) where
>>> ethdev API returns _preferred_ pool handle to application and Its upto
>>> application to decide on policy - whether application wants to create
>>> pool with received preferred pool handle or not. For more discussion details
>>> on this topic refer [1].
>> Well, I still think it would be more flexible to have an API like
>>  rte_eth_dev_pool_ops_supported(uint8_t port_id, const char *pool)
>>
>> It supports the easy case (= one preferred mempool) without much pain,
>> and provides a more precise manner to describe what is supported or not
>> by the driver. Example: "pmd_foo" prefers "mempool_foo" (best perf), but
>> also supporst "mempool_stack" and "mempool_ring", but "mempool_bar"
>> won't work at all.
>>
>> Having only one preferred pool_ops also prevents from smoothly renaming
>> a pool (supporting both during some time) or to have 2 names for
>> different variants of the same pool_ops (ex: ring_mp_mc, ring_sp_sc).
>>
>> But if the users (I guess at least Cavium and NXP) are happy with
>> what you propose, I'm fine with it.
>
> preferred handle based upon real world use-case and same thing raised
> at [1].
>
> Hi Hemant, Are you ok with proposed preferred API?
>
> [1] http://dpdk.org/dev/patchwork/patch/24944/
>

The current patch is ok, but it is better if you can extend it to 
provide list of preferred pools (in preference order) instead of just 
one pool. This will become helpful. I will avoid providing list of 
not-supported pools etc.

A driver can have more than one preferred pool, depend on the resource 
availability one or other can be used. I am also proposing this in my 
proposal[1].

[1] http://dpdk.org/dev/patchwork/patch/26377/



>>> --- a/lib/librte_ether/rte_ethdev.c
>>> +++ b/lib/librte_ether/rte_ethdev.c
>>> @@ -3409,3 +3409,21 @@ rte_eth_dev_adjust_nb_rx_tx_desc(uint8_t port_id,
>>>
>>>  	return 0;
>>>  }
>>> +
>>> +int
>>> +rte_eth_dev_get_preferred_pool_ops(uint8_t port_id, char *pool)
>>> +{
>>> +	struct rte_eth_dev *dev;
>>> +	const char *tmp;
>>> +
>>> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
>>> +
>>> +	dev = &rte_eth_devices[port_id];
>>> +
>>> +	if (*dev->dev_ops->get_preferred_pool_ops == NULL) {
>>> +		tmp = rte_eal_mbuf_default_mempool_ops();
>>> +		snprintf(pool, RTE_MBUF_POOL_OPS_NAMESIZE, "%s", tmp);
>>> +		return 0;
>>> +	}
>>> +	return (*dev->dev_ops->get_preferred_pool_ops)(dev, pool);
>>> +}
>> I think adding the length of the pool buffer to the function arguments
>> would be better: only documenting that the length is
>> RTE_MBUF_POOL_OPS_NAMESIZE looks a bit weak to me, because if one day it
>> changes to another value, the users of the function may not notice it
>> (no ABI/API change).
>>
>>
>> One more comment: it would be helpful to have one user of this API in
>> the example apps or testpmd.
>
> Yes. I will add in v3. Thanks.
>
>> Olivier
>
>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3 2/2] ethdev: allow pmd to advertise pool handle
  2017-09-07  9:21  0%         ` Hemant Agrawal
@ 2017-09-07 10:06  0%           ` santosh
  2017-09-07 10:11  0%             ` santosh
  0 siblings, 1 reply; 200+ results
From: santosh @ 2017-09-07 10:06 UTC (permalink / raw)
  To: Hemant Agrawal, Olivier MATZ; +Cc: dev, thomas, jerin.jacob

Hi Hemant,


On Thursday 07 September 2017 02:51 PM, Hemant Agrawal wrote:
> On 9/4/2017 6:44 PM, santosh wrote:
>> Hi Olivier,
>>
>>
>> On Monday 04 September 2017 05:41 PM, Olivier MATZ wrote:
>>> Hi Santosh,
>>>
>>> On Tue, Aug 15, 2017 at 01:37:17PM +0530, Santosh Shukla wrote:
>>>> Now that dpdk supports more than one mempool drivers and
>>>> each mempool driver works best for specific PMD, example:
>>>> - sw ring based mempool for Intel PMD drivers
>>>> - dpaa2 HW mempool manager for dpaa2 PMD driver.
>>>> - fpa HW mempool manager for Octeontx PMD driver.
>>>>
>>>> Application like to know `preferred mempool vs PMD driver`
>>>> information in advance before port setup.
>>>>
>>>> Introducing rte_eth_dev_get_preferred_pool_ops() API,
>>>> which allows PMD driver to advertise their pool capability to application.
>>>>
>>>> Application side programing sequence would be:
>>>>
>>>> char pref_mempool[RTE_MEMPOOL_OPS_NAMESIZE];
>>>> rte_eth_dev_get_preferred_pool_ops(ethdev_port_id, pref_mempoolx /*out*/);
>>>> rte_mempool_create_empty();
>>>> rte_mempool_set_ops_byname( , pref_memppol, );
>>>> rte_mempool_populate_default();
>>>>
>>>> Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
>>>> ---
>>>> v2 --> v3:
>>>> - Updated version.map entry to DPDK_v17.11.
>>>>
>>>> v1 --> v2:
>>>> - Renamed _get_preferred_pool to _get_preferred_pool_ops().
>>>> Per v1 review feedback, Olivier suggested to rename api
>>>> to rte_eth_dev_pool_ops_supported(), considering that 2nd param
>>>> for that api will return pool handle 'priority' for that port.
>>>> However, per v1 [1], we're opting for approach 1) where
>>>> ethdev API returns _preferred_ pool handle to application and Its upto
>>>> application to decide on policy - whether application wants to create
>>>> pool with received preferred pool handle or not. For more discussion details
>>>> on this topic refer [1].
>>> Well, I still think it would be more flexible to have an API like
>>>  rte_eth_dev_pool_ops_supported(uint8_t port_id, const char *pool)
>>>
>>> It supports the easy case (= one preferred mempool) without much pain,
>>> and provides a more precise manner to describe what is supported or not
>>> by the driver. Example: "pmd_foo" prefers "mempool_foo" (best perf), but
>>> also supporst "mempool_stack" and "mempool_ring", but "mempool_bar"
>>> won't work at all.
>>>
>>> Having only one preferred pool_ops also prevents from smoothly renaming
>>> a pool (supporting both during some time) or to have 2 names for
>>> different variants of the same pool_ops (ex: ring_mp_mc, ring_sp_sc).
>>>
>>> But if the users (I guess at least Cavium and NXP) are happy with
>>> what you propose, I'm fine with it.
>>
>> preferred handle based upon real world use-case and same thing raised
>> at [1].
>>
>> Hi Hemant, Are you ok with proposed preferred API?
>>
>> [1] http://dpdk.org/dev/patchwork/patch/24944/
>>
>
> The current patch is ok, but it is better if you can extend it to provide list of preferred pools (in preference order) instead of just one pool. This will become helpful. I will avoid providing list of not-supported pools etc.
>
> A driver can have more than one preferred pool, depend on the resource availability one or other can be used. I am also proposing this in my proposal[1].
>
> [1] http://dpdk.org/dev/patchwork/patch/26377/
>
Ok, then sticking to Olivier api but slight change in param,
example:
/** * Get list of supported pools for a port * * @param port_id [in] * Pointer to port identifier of the device. * @param pools [out] * Pointer to the list of supported pools for that port. * Returns with array of pool ops name handler of size * RTE_MEMPOOL_OPS_NAMESIZE. * @return * >=0: Success; PMD has updated supported pool list. * <0: Failure; */ int rte_eth_dev_pools_ops_supported(uint8_t port_id, char **pools) Hemant, Olivier: Does above api make sense? Pl. confirm. Thanks.

>
>
>>>> --- a/lib/librte_ether/rte_ethdev.c
>>>> +++ b/lib/librte_ether/rte_ethdev.c
>>>> @@ -3409,3 +3409,21 @@ rte_eth_dev_adjust_nb_rx_tx_desc(uint8_t port_id,
>>>>
>>>>      return 0;
>>>>  }
>>>> +
>>>> +int
>>>> +rte_eth_dev_get_preferred_pool_ops(uint8_t port_id, char *pool)
>>>> +{
>>>> +    struct rte_eth_dev *dev;
>>>> +    const char *tmp;
>>>> +
>>>> +    RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
>>>> +
>>>> +    dev = &rte_eth_devices[port_id];
>>>> +
>>>> +    if (*dev->dev_ops->get_preferred_pool_ops == NULL) {
>>>> +        tmp = rte_eal_mbuf_default_mempool_ops();
>>>> +        snprintf(pool, RTE_MBUF_POOL_OPS_NAMESIZE, "%s", tmp);
>>>> +        return 0;
>>>> +    }
>>>> +    return (*dev->dev_ops->get_preferred_pool_ops)(dev, pool);
>>>> +}
>>> I think adding the length of the pool buffer to the function arguments
>>> would be better: only documenting that the length is
>>> RTE_MBUF_POOL_OPS_NAMESIZE looks a bit weak to me, because if one day it
>>> changes to another value, the users of the function may not notice it
>>> (no ABI/API change).
>>>
>>>
>>> One more comment: it would be helpful to have one user of this API in
>>> the example apps or testpmd.
>>
>> Yes. I will add in v3. Thanks.
>>
>>> Olivier
>>
>>
>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3 2/2] ethdev: allow pmd to advertise pool handle
  2017-09-07 10:06  0%           ` santosh
@ 2017-09-07 10:11  0%             ` santosh
  2017-09-07 11:08  0%               ` Hemant Agrawal
  0 siblings, 1 reply; 200+ results
From: santosh @ 2017-09-07 10:11 UTC (permalink / raw)
  To: Hemant Agrawal, Olivier MATZ; +Cc: dev, thomas, jerin.jacob



On Thursday 07 September 2017 03:36 PM, santosh wrote:
> Hi Hemant,
>
>
> On Thursday 07 September 2017 02:51 PM, Hemant Agrawal wrote:
>> On 9/4/2017 6:44 PM, santosh wrote:
>>> Hi Olivier,
>>>
>>>
>>> On Monday 04 September 2017 05:41 PM, Olivier MATZ wrote:
>>>> Hi Santosh,
>>>>
>>>> On Tue, Aug 15, 2017 at 01:37:17PM +0530, Santosh Shukla wrote:
>>>>> Now that dpdk supports more than one mempool drivers and
>>>>> each mempool driver works best for specific PMD, example:
>>>>> - sw ring based mempool for Intel PMD drivers
>>>>> - dpaa2 HW mempool manager for dpaa2 PMD driver.
>>>>> - fpa HW mempool manager for Octeontx PMD driver.
>>>>>
>>>>> Application like to know `preferred mempool vs PMD driver`
>>>>> information in advance before port setup.
>>>>>
>>>>> Introducing rte_eth_dev_get_preferred_pool_ops() API,
>>>>> which allows PMD driver to advertise their pool capability to application.
>>>>>
>>>>> Application side programing sequence would be:
>>>>>
>>>>> char pref_mempool[RTE_MEMPOOL_OPS_NAMESIZE];
>>>>> rte_eth_dev_get_preferred_pool_ops(ethdev_port_id, pref_mempoolx /*out*/);
>>>>> rte_mempool_create_empty();
>>>>> rte_mempool_set_ops_byname( , pref_memppol, );
>>>>> rte_mempool_populate_default();
>>>>>
>>>>> Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
>>>>> ---
>>>>> v2 --> v3:
>>>>> - Updated version.map entry to DPDK_v17.11.
>>>>>
>>>>> v1 --> v2:
>>>>> - Renamed _get_preferred_pool to _get_preferred_pool_ops().
>>>>> Per v1 review feedback, Olivier suggested to rename api
>>>>> to rte_eth_dev_pool_ops_supported(), considering that 2nd param
>>>>> for that api will return pool handle 'priority' for that port.
>>>>> However, per v1 [1], we're opting for approach 1) where
>>>>> ethdev API returns _preferred_ pool handle to application and Its upto
>>>>> application to decide on policy - whether application wants to create
>>>>> pool with received preferred pool handle or not. For more discussion details
>>>>> on this topic refer [1].
>>>> Well, I still think it would be more flexible to have an API like
>>>>  rte_eth_dev_pool_ops_supported(uint8_t port_id, const char *pool)
>>>>
>>>> It supports the easy case (= one preferred mempool) without much pain,
>>>> and provides a more precise manner to describe what is supported or not
>>>> by the driver. Example: "pmd_foo" prefers "mempool_foo" (best perf), but
>>>> also supporst "mempool_stack" and "mempool_ring", but "mempool_bar"
>>>> won't work at all.
>>>>
>>>> Having only one preferred pool_ops also prevents from smoothly renaming
>>>> a pool (supporting both during some time) or to have 2 names for
>>>> different variants of the same pool_ops (ex: ring_mp_mc, ring_sp_sc).
>>>>
>>>> But if the users (I guess at least Cavium and NXP) are happy with
>>>> what you propose, I'm fine with it.
>>> preferred handle based upon real world use-case and same thing raised
>>> at [1].
>>>
>>> Hi Hemant, Are you ok with proposed preferred API?
>>>
>>> [1] http://dpdk.org/dev/patchwork/patch/24944/
>>>
>> The current patch is ok, but it is better if you can extend it to provide list of preferred pools (in preference order) instead of just one pool. This will become helpful. I will avoid providing list of not-supported pools etc.
>>
>> A driver can have more than one preferred pool, depend on the resource availability one or other can be used. I am also proposing this in my proposal[1].
>>
>> [1] http://dpdk.org/dev/patchwork/patch/26377/
>>
> Ok, then sticking to Olivier api but slight change in param,
> example:
> /** * Get list of supported pools for a port * * @param port_id [in] * Pointer to port identifier of the device. * @param pools [out] * Pointer to the list of supported pools for that port. * Returns with array of pool ops name handler of size * RTE_MEMPOOL_OPS_NAMESIZE. * @return * >=0: Success; PMD has updated supported pool list. * <0: Failure; */ int rte_eth_dev_pools_ops_supported(uint8_t port_id, char **pools) Hemant, Olivier: Does above api make sense? Pl. confirm. Thanks.

Sorry for the font, resending proposed API:

/** 
 * Get list of supported pools for a port 
 * @param port_id [in] 
 *   Pointer to port identifier of the device. 
 * @param pools [out] 
 * Pointer to the list of supported pools for that port. 
 * Returns with array of pool ops name handler of size 
 * RTE_MEMPOOL_OPS_NAMESIZE. 
 * @return
 * >=0: Success; PMD has updated supported pool list. 
 * <0: Failure; 
 */ 

int rte_eth_dev_pools_ops_supported(uint8_t port_id, char **pools)

Hemant, Olivier: Does above api make sense? Pl. confirm. Thanks.

>>
>>>>> --- a/lib/librte_ether/rte_ethdev.c
>>>>> +++ b/lib/librte_ether/rte_ethdev.c
>>>>> @@ -3409,3 +3409,21 @@ rte_eth_dev_adjust_nb_rx_tx_desc(uint8_t port_id,
>>>>>
>>>>>      return 0;
>>>>>  }
>>>>> +
>>>>> +int
>>>>> +rte_eth_dev_get_preferred_pool_ops(uint8_t port_id, char *pool)
>>>>> +{
>>>>> +    struct rte_eth_dev *dev;
>>>>> +    const char *tmp;
>>>>> +
>>>>> +    RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
>>>>> +
>>>>> +    dev = &rte_eth_devices[port_id];
>>>>> +
>>>>> +    if (*dev->dev_ops->get_preferred_pool_ops == NULL) {
>>>>> +        tmp = rte_eal_mbuf_default_mempool_ops();
>>>>> +        snprintf(pool, RTE_MBUF_POOL_OPS_NAMESIZE, "%s", tmp);
>>>>> +        return 0;
>>>>> +    }
>>>>> +    return (*dev->dev_ops->get_preferred_pool_ops)(dev, pool);
>>>>> +}
>>>> I think adding the length of the pool buffer to the function arguments
>>>> would be better: only documenting that the length is
>>>> RTE_MBUF_POOL_OPS_NAMESIZE looks a bit weak to me, because if one day it
>>>> changes to another value, the users of the function may not notice it
>>>> (no ABI/API change).
>>>>
>>>>
>>>> One more comment: it would be helpful to have one user of this API in
>>>> the example apps or testpmd.
>>> Yes. I will add in v3. Thanks.
>>>
>>>> Olivier
>>>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3 2/2] ethdev: allow pmd to advertise pool handle
  2017-09-07 10:11  0%             ` santosh
@ 2017-09-07 11:08  0%               ` Hemant Agrawal
  0 siblings, 0 replies; 200+ results
From: Hemant Agrawal @ 2017-09-07 11:08 UTC (permalink / raw)
  To: santosh, Olivier MATZ; +Cc: dev, thomas, jerin.jacob

On 9/7/2017 3:41 PM, santosh wrote:
>
>
> On Thursday 07 September 2017 03:36 PM, santosh wrote:
>> Hi Hemant,
>>
>>
>> On Thursday 07 September 2017 02:51 PM, Hemant Agrawal wrote:
>>> On 9/4/2017 6:44 PM, santosh wrote:
>>>> Hi Olivier,
>>>>
>>>>
>>>> On Monday 04 September 2017 05:41 PM, Olivier MATZ wrote:
>>>>> Hi Santosh,
>>>>>
>>>>> On Tue, Aug 15, 2017 at 01:37:17PM +0530, Santosh Shukla wrote:
>>>>>> Now that dpdk supports more than one mempool drivers and
>>>>>> each mempool driver works best for specific PMD, example:
>>>>>> - sw ring based mempool for Intel PMD drivers
>>>>>> - dpaa2 HW mempool manager for dpaa2 PMD driver.
>>>>>> - fpa HW mempool manager for Octeontx PMD driver.
>>>>>>
>>>>>> Application like to know `preferred mempool vs PMD driver`
>>>>>> information in advance before port setup.
>>>>>>
>>>>>> Introducing rte_eth_dev_get_preferred_pool_ops() API,
>>>>>> which allows PMD driver to advertise their pool capability to application.
>>>>>>
>>>>>> Application side programing sequence would be:
>>>>>>
>>>>>> char pref_mempool[RTE_MEMPOOL_OPS_NAMESIZE];
>>>>>> rte_eth_dev_get_preferred_pool_ops(ethdev_port_id, pref_mempoolx /*out*/);
>>>>>> rte_mempool_create_empty();
>>>>>> rte_mempool_set_ops_byname( , pref_memppol, );
>>>>>> rte_mempool_populate_default();
>>>>>>
>>>>>> Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
>>>>>> ---
>>>>>> v2 --> v3:
>>>>>> - Updated version.map entry to DPDK_v17.11.
>>>>>>
>>>>>> v1 --> v2:
>>>>>> - Renamed _get_preferred_pool to _get_preferred_pool_ops().
>>>>>> Per v1 review feedback, Olivier suggested to rename api
>>>>>> to rte_eth_dev_pool_ops_supported(), considering that 2nd param
>>>>>> for that api will return pool handle 'priority' for that port.
>>>>>> However, per v1 [1], we're opting for approach 1) where
>>>>>> ethdev API returns _preferred_ pool handle to application and Its upto
>>>>>> application to decide on policy - whether application wants to create
>>>>>> pool with received preferred pool handle or not. For more discussion details
>>>>>> on this topic refer [1].
>>>>> Well, I still think it would be more flexible to have an API like
>>>>>  rte_eth_dev_pool_ops_supported(uint8_t port_id, const char *pool)
>>>>>
>>>>> It supports the easy case (= one preferred mempool) without much pain,
>>>>> and provides a more precise manner to describe what is supported or not
>>>>> by the driver. Example: "pmd_foo" prefers "mempool_foo" (best perf), but
>>>>> also supporst "mempool_stack" and "mempool_ring", but "mempool_bar"
>>>>> won't work at all.
>>>>>
>>>>> Having only one preferred pool_ops also prevents from smoothly renaming
>>>>> a pool (supporting both during some time) or to have 2 names for
>>>>> different variants of the same pool_ops (ex: ring_mp_mc, ring_sp_sc).
>>>>>
>>>>> But if the users (I guess at least Cavium and NXP) are happy with
>>>>> what you propose, I'm fine with it.
>>>> preferred handle based upon real world use-case and same thing raised
>>>> at [1].
>>>>
>>>> Hi Hemant, Are you ok with proposed preferred API?
>>>>
>>>> [1] http://dpdk.org/dev/patchwork/patch/24944/
>>>>
>>> The current patch is ok, but it is better if you can extend it to provide list of preferred pools (in preference order) instead of just one pool. This will become helpful. I will avoid providing list of not-supported pools etc.
>>>
>>> A driver can have more than one preferred pool, depend on the resource availability one or other can be used. I am also proposing this in my proposal[1].
>>>
>>> [1] http://dpdk.org/dev/patchwork/patch/26377/
>>>
>> Ok, then sticking to Olivier api but slight change in param,
>> example:
>> /** * Get list of supported pools for a port * * @param port_id [in] * Pointer to port identifier of the device. * @param pools [out] * Pointer to the list of supported pools for that port. * Returns with array of pool ops name handler of size * RTE_MEMPOOL_OPS_NAMESIZE. * @return * >=0: Success; PMD has updated supported pool list. * <0: Failure; */ int rte_eth_dev_pools_ops_supported(uint8_t port_id, char **pools) Hemant, Olivier: Does above api make sense? Pl. confirm. Thanks.
>
> Sorry for the font, resending proposed API:
>
> /**
>  * Get list of supported pools for a port
>  * @param port_id [in]
>  *   Pointer to port identifier of the device.
>  * @param pools [out]
>  * Pointer to the list of supported pools for that port.
>  * Returns with array of pool ops name handler of size
>  * RTE_MEMPOOL_OPS_NAMESIZE.
>  * @return
>  * >=0: Success; PMD has updated supported pool list.
>  * <0: Failure;
>  */
>
> int rte_eth_dev_pools_ops_supported(uint8_t port_id, char **pools)
>
> Hemant, Olivier: Does above api make sense? Pl. confirm. Thanks.
>

looks ok to me.


>>>
>>>>>> --- a/lib/librte_ether/rte_ethdev.c
>>>>>> +++ b/lib/librte_ether/rte_ethdev.c
>>>>>> @@ -3409,3 +3409,21 @@ rte_eth_dev_adjust_nb_rx_tx_desc(uint8_t port_id,
>>>>>>
>>>>>>      return 0;
>>>>>>  }
>>>>>> +
>>>>>> +int
>>>>>> +rte_eth_dev_get_preferred_pool_ops(uint8_t port_id, char *pool)
>>>>>> +{
>>>>>> +    struct rte_eth_dev *dev;
>>>>>> +    const char *tmp;
>>>>>> +
>>>>>> +    RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
>>>>>> +
>>>>>> +    dev = &rte_eth_devices[port_id];
>>>>>> +
>>>>>> +    if (*dev->dev_ops->get_preferred_pool_ops == NULL) {
>>>>>> +        tmp = rte_eal_mbuf_default_mempool_ops();
>>>>>> +        snprintf(pool, RTE_MBUF_POOL_OPS_NAMESIZE, "%s", tmp);
>>>>>> +        return 0;
>>>>>> +    }
>>>>>> +    return (*dev->dev_ops->get_preferred_pool_ops)(dev, pool);
>>>>>> +}
>>>>> I think adding the length of the pool buffer to the function arguments
>>>>> would be better: only documenting that the length is
>>>>> RTE_MBUF_POOL_OPS_NAMESIZE looks a bit weak to me, because if one day it
>>>>> changes to another value, the users of the function may not notice it
>>>>> (no ABI/API change).
>>>>>
>>>>>
>>>>> One more comment: it would be helpful to have one user of this API in
>>>>> the example apps or testpmd.
>>>> Yes. I will add in v3. Thanks.
>>>>
>>>>> Olivier
>>>>
>
>

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v6 4/8] doc: remove mempool notice
  @ 2017-09-07 15:30  4%       ` Santosh Shukla
  0 siblings, 0 replies; 200+ results
From: Santosh Shukla @ 2017-09-07 15:30 UTC (permalink / raw)
  To: olivier.matz, dev; +Cc: thomas, jerin.jacob, hemant.agrawal, Santosh Shukla

Removed mempool deprecation notice and
updated change info in release_17.11.

Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
---
 doc/guides/rel_notes/deprecation.rst   | 9 ---------
 doc/guides/rel_notes/release_17_11.rst | 7 +++++++
 2 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 3362f3350..0e4cb1f95 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -44,15 +44,6 @@ Deprecation Notices
   PKT_RX_QINQ_STRIPPED, that are better described. The old flags and
   their behavior will be kept until 17.08 and will be removed in 17.11.
 
-* mempool: The following will be modified in 17.11:
-
-  - ``rte_mempool_xmem_size`` and ``rte_mempool_xmem_usage`` need to know
-    the mempool flag status so adding new param rte_mempool in those API.
-  - Removing __rte_unused int flag param from ``rte_mempool_generic_put``
-    and ``rte_mempool_generic_get`` API.
-  - ``rte_mempool`` flags data type will changed from int to
-    unsigned int.
-
 * ethdev: Tx offloads will no longer be enabled by default in 17.11.
   Instead, the ``rte_eth_txmode`` structure will be extended with
   bit field to enable each Tx offload.
diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f916..6b17af7bc 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -110,6 +110,13 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* **The following changes made in mempool library**
+
+  * Moved ``flags`` datatype from int to unsigned int for ``rte_mempool``.
+  * Removed ``__rte_unused int flag`` param from ``rte_mempool_generic_put``
+    and ``rte_mempool_generic_get`` API.
+  * Added ``flags`` param in ``rte_mempool_xmem_size`` and
+    ``rte_mempool_xmem_usage``.
 
 ABI Changes
 -----------
-- 
2.14.1

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [dpdk-dev, 16/17] build: add option to version libs using DPDK version
  2017-09-01 10:04  3% ` [dpdk-dev] [PATCH 16/17] build: add option to version libs using DPDK version Bruce Richardson
@ 2017-09-07 17:07  3%   ` Neil Horman
  2017-09-08  8:58  0%     ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2017-09-07 17:07 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev

On Fri, Sep 01, 2017 at 11:04:15AM +0100, Bruce Richardson wrote:
> Normally, each library has it's own version number based on the ABI.
> Add an option to have all libs just use the DPDK version number as the
> .so version.
> 
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> ---
>  drivers/meson.build | 8 +++++++-
>  lib/meson.build     | 8 +++++++-
>  meson_options.txt   | 1 +
>  3 files changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/meson.build b/drivers/meson.build
> index d7a614f83..76d610a5b 100644
> --- a/drivers/meson.build
> +++ b/drivers/meson.build
> @@ -92,6 +92,12 @@ foreach class:driver_classes
>  						depends: [pmdinfogen, tmp_lib])
>  			endforeach
>  
> +			if get_option('per_library_versions')
> +				so_version = '@0@.1'.format(version)
> +			else
> +				so_version = meson.project_version()
> +			endif
> +

I'm not sure this is a good idea.  If we default to using the defined project
version number, we commit to, by default incrementing the library version number
on each release, even if the ABI hasn't changed, which means that the purpose of
versioning (creating compatibility between library releases), is rendered
useless.

Neil

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [dpdk-dev, 16/17] build: add option to version libs using DPDK version
  2017-09-07 17:07  3%   ` [dpdk-dev] [dpdk-dev, " Neil Horman
@ 2017-09-08  8:58  0%     ` Bruce Richardson
  0 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2017-09-08  8:58 UTC (permalink / raw)
  To: Neil Horman; +Cc: dev

On Thu, Sep 07, 2017 at 01:07:19PM -0400, Neil Horman wrote:
> On Fri, Sep 01, 2017 at 11:04:15AM +0100, Bruce Richardson wrote:
> > Normally, each library has it's own version number based on the ABI.
> > Add an option to have all libs just use the DPDK version number as
> > the .so version.
> > 
> > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com> ---
> > drivers/meson.build | 8 +++++++- lib/meson.build     | 8 +++++++-
> > meson_options.txt   | 1 + 3 files changed, 15 insertions(+), 2
> > deletions(-)
> > 
> > diff --git a/drivers/meson.build b/drivers/meson.build index
> > d7a614f83..76d610a5b 100644 --- a/drivers/meson.build +++
> > b/drivers/meson.build @@ -92,6 +92,12 @@ foreach
> > class:driver_classes depends: [pmdinfogen, tmp_lib]) endforeach
> >  
> > +			if get_option('per_library_versions') +
> > so_version = '@0@.1'.format(version) +			else +
> > so_version = meson.project_version() +			endif +
> 
> I'm not sure this is a good idea.  If we default to using the defined
> project version number, we commit to, by default incrementing the
> library version number on each release, even if the ABI hasn't
> changed, which means that the purpose of versioning (creating
> compatibility between library releases), is rendered useless.
>
Yes, I agree on the compatibility, so the default for this option is to
have individual .so versions, as right now. This option itself was added
at the request of some distros [1][2], who wanted to just use a single
version number across all DPDK.

/Bruce

[1] http://dpdk.org/ml/archives/dev/2017-August/072969.html
[2] http://dpdk.org/ml/archives/dev/2017-August/072976.html

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2] devtools: rework abi checker script
  2017-09-06 14:51 27% ` [dpdk-dev] [PATCH v2] " Olivier Matz
@ 2017-09-08 13:46  9%   ` Neil Horman
  2017-09-11  8:18  7%     ` Olivier MATZ
  0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2017-09-08 13:46 UTC (permalink / raw)
  To: Olivier Matz; +Cc: dev, bruce.richardson

On Wed, Sep 06, 2017 at 04:51:01PM +0200, Olivier Matz wrote:
> The intiatial version of the script had some limitations:
> - cannot work on a non-clean workspace
> - environment variables are not documented
> - no compilation log in case of failure
> - return success even it abi is incompatible
> 
> This patch addresses these issues and rework the code.
> 
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> ---
> 
> v1->v2:
> - use /usr/bin/env to find bash (which is required)
> - fix displayed path to html reports
> - reword help for -f option
> 
This still doesn't seem to work.  Running the following:
./validate-abi.sh v17.05 v17.08

produces no report, and the end of the abi-check.log file contains:

[nhorman@hmswarspite abi-check]$ tail -n 10 ./abi-check.log 
CMD: abi-dumper librte_vhost.so -o /home/nhorman/git/dpdk/devtools/abi-check/222555480/librte_vhost.so.dump -lver 222555480
Reading debug-info
WARNING: incompatible build option detected: -O0 (required -Og for better analysis)
Creating ABI dump

The object ABI has been dumped to:
  /home/nhorman/git/dpdk/devtools/abi-check/222555480/librte_vhost.so.dump
CMD: cd ../..
CMD: git clone ./.. /home/nhorman/git/dpdk/devtools/abi-check/02657b4ad
fatal: repository './..' does not exist

The warning I assume should be fixed to, but the second clone failing seems to
be the most salient bit here

Neil

>  devtools/validate-abi.sh | 389 ++++++++++++++++++++++++-----------------------
>  1 file changed, 197 insertions(+), 192 deletions(-)
> 
> diff --git a/devtools/validate-abi.sh b/devtools/validate-abi.sh
> index 0accc99b1..d747db189 100755
> --- a/devtools/validate-abi.sh
> +++ b/devtools/validate-abi.sh
> @@ -1,7 +1,8 @@
> -#!/bin/sh
> +#!/usr/bin/env bash
>  #   BSD LICENSE
>  #
>  #   Copyright(c) 2015 Neil Horman. All rights reserved.
> +#   Copyright(c) 2017 6WIND S.A.
>  #   All rights reserved.
>  #
>  #   Redistribution and use in source and binary forms, with or without
> @@ -27,236 +28,240 @@
>  #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
>  #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>  
> -TAG1=$1
> -TAG2=$2
> -TARGET=$3
> -ABI_DIR=`mktemp -d -p /tmp ABI.XXXXXX`
> +set -e
>  
> -usage() {
> -	echo "$0 <REV1> <REV2> <TARGET>"
> -}
> +abicheck=abi-compliance-checker
> +abidump=abi-dumper
> +default_dst=abi-check
> +default_target=x86_64-native-linuxapp-gcc
>  
> -log() {
> -	local level=$1
> -	shift
> -	echo "$*"
> +# trap on error
> +err_report() {
> +    echo "$0: error at line $1"
>  }
> +trap 'err_report $LINENO' ERR
>  
> -validate_tags() {
> +print_usage () {
> +	cat <<- END_OF_HELP
> +	$(basename $0) [options] <rev1> <rev2>
>  
> -	if [ -z "$HASH1" ]
> -	then
> -		echo "invalid revision: $TAG1"
> -		return
> -	fi
> -	if [ -z "$HASH2" ]
> -	then
> -		echo "invalid revision: $TAG2"
> -		return
> -	fi
> +	This script compares the ABI of 2 git revisions of the current
> +	workspace. The output is a html report and a compilation log.
> +
> +	The objective is to make sure that applications built against
> +	DSOs from the first revision can still run when executed using
> +	the DSOs built from the second revision.
> +
> +	<rev1> and <rev2> are git commit id or tags.
> +
> +	Options:
> +	  -h		show this help
> +	  -j <num>	enable parallel compilation with <num> threads
> +	  -v		show compilation logs on the console
> +	  -d <dir>	change working directory (default is ${default_dst})
> +	  -t <target>	the dpdk target to use (default is ${default_target})
> +	  -f		overwrite existing files in destination directory
> +
> +	The script returns 0 on success, or the value of last failing
> +	call of ${abicheck} (incompatible abi or the tool has run with errors).
> +	The errors returned by ${abidump} are ignored.
> +
> +	END_OF_HELP
>  }
>  
> -validate_args() {
> -	if [ -z "$TAG1" ]
> -	then
> -		echo "Must Specify REV1"
> -		return
> -	fi
> -	if [ -z "$TAG2" ]
> -	then
> -		echo "Must Specify REV2"
> -		return
> -	fi
> -	if [ -z "$TARGET" ]
> -	then
> -		echo "Must Specify a build target"
> +# log in the file, and on stdout if verbose
> +# $1: level string
> +# $2: string to be logged
> +log() {
> +	echo "$1: $2"
> +	if [ "${verbose}" != "true" ]; then
> +		echo "$1: $2" >&3
>  	fi
>  }
>  
> +# launch a command and log it, taking care of surrounding spaces with quotes
> +cmd() {
> +	local i s whitespace
> +	s=""
> +	whitespace="[[:space:]]"
> +	for i in "$@"; do
> +		if [[ $i =~ $whitespace ]]; then
> +			i=\"$i\"
> +		fi
> +		if [ -z "$s" ]; then
> +			s="$i"
> +		else
> +			s="$s $i"
> +		fi
> +	done
> +
> +	log "CMD" "$s"
> +	"$@"
> +}
>  
> -cleanup_and_exit() {
> -	rm -rf $ABI_DIR
> -	git checkout $CURRENT_BRANCH
> -	exit $1
> +# redirect or copy stderr/stdout to a file
> +# the syntax is unfamiliar, but it makes the rest of the
> +# code easier to read, avoiding the use of pipes
> +set_log_file() {
> +	# save original stdout and stderr in fd 3 and 4
> +	exec 3>&1
> +	exec 4>&2
> +	# create a new fd 5 that send to a file
> +	exec 5> >(cat > $1)
> +	# send stdout and stderr to fd 5
> +	if [ "${verbose}" = "true" ]; then
> +		exec 1> >(tee /dev/fd/5 >&3)
> +		exec 2> >(tee /dev/fd/5 >&4)
> +	else
> +		exec 1>&5
> +		exec 2>&5
> +	fi
>  }
>  
>  # Make sure we configure SHARED libraries
>  # Also turn off IGB and KNI as those require kernel headers to build
>  fixup_config() {
> -	sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" config/defconfig_$TARGET
> -	sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" config/defconfig_$TARGET
> -	sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" config/defconfig_$TARGET
> -	sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" config/defconfig_$TARGET
> -	sed -i -e"$ a\CONFIG_RTE_KNI_KMOD=n" config/defconfig_$TARGET
> +	local conf=config/defconfig_$target
> +	cmd sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" $conf
> +	cmd sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" $conf
> +	cmd sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" $conf
> +	cmd sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" $conf
> +	cmd sed -i -e"$ a\CONFIG_RTE_KNI_KMOD=n" $conf
>  }
>  
> -###########################################
> -#START
> -############################################
> +# build dpdk for the given tag and dump abi
> +# $1: hash of the revision
> +gen_abi() {
> +	cmd git clone $(dirname $0)/.. ${dst}/${1}
> +	cmd cd ${dst}/${1}
> +
> +	log "INFO" "Checking out version ${1} of the dpdk"
> +	# Move to the old version of the tree
> +	cmd git checkout ${1}
> +
> +	fixup_config
> +
> +	# Now configure the build
> +	log "INFO" "Configuring DPDK ${1}"
> +	cmd make config T=$target O=$target > ${dst}/log 2>&1
> +
> +	# Checking abi compliance relies on using the dwarf information in
> +	# the shared objects. Build with -g to include them.
> +	log "INFO" "Building DPDK ${1}. This might take a moment"
> +	cmd make -j$parallel O=$target V=1 EXTRA_CFLAGS="-g -O0" \
> +	    EXTRA_LDFLAGS="-g" || log "INFO" "The build failed"
> +
> +	# Move to the lib directory
> +	cmd cd ${PWD}/$target/lib
> +	log "INFO" "Collecting ABI information for ${1}"
> +	for i in *.so; do
> +		[ -e "$i" ] || break
> +		cmd $abidump ${i} -o $dst/${1}/${i}.dump -lver ${1} || true
> +		# hack to ignore empty SymbolsInfo section (no public ABI)
> +		if grep -q "'SymbolInfo' => {}," $dst/${1}/${i}.dump \
> +				2> /dev/null; then
> +			log "INFO" "${i} has no public ABI, remove dump file"
> +			cmd rm -f $dst/${1}/${i}.dump
> +		fi
> +	done
> +	cmd cd ../..
> +}
>  
> -#trap on ctrl-c to clean up
> -trap cleanup_and_exit SIGINT
> +verbose=false
> +parallel=1
> +dst=${default_dst}
> +target=${default_target}
> +force=0
> +while getopts j:vd:t:fh ARG ; do
> +	case $ARG in
> +		j ) parallel=$OPTARG ;;
> +		v ) verbose=true ;;
> +		d ) dst=$OPTARG ;;
> +		t ) target=$OPTARG ;;
> +		f ) force=1 ;;
> +		h ) print_usage ; exit 0 ;;
> +		? ) print_usage ; exit 1 ;;
> +	esac
> +done
> +shift $(($OPTIND - 1))
>  
> -if [ -z "$DPDK_MAKE_JOBS" ]
> -then
> -	# This counts the number of cpus on the system
> -	if [ -e /usr/bin/lscpu ]
> -	then
> -		DPDK_MAKE_JOBS=`lscpu -p=cpu | grep -v "#" | wc -l`
> -	else
> -		DPDK_MAKE_JOBS=1
> -	fi
> +if [ $# != 2 ]; then
> +	print_usage
> +	exit 1
>  fi
>  
> -#Save the current branch
> -CURRENT_BRANCH=`git branch | grep \* | cut -d' ' -f2`
> +tag1=$1
> +tag2=$2
>  
> -if [ -z "$CURRENT_BRANCH" ]
> -then
> -	CURRENT_BRANCH=`git log --pretty=format:%H HEAD~1..HEAD`
> -fi
> +# convert path to absolute
> +case "${dst}" in
> +	/*) ;;
> +	*) dst=${PWD}/${dst} ;;
> +esac
>  
> -if [ -n "$VERBOSE" ]
> -then
> -	export VERBOSE=/dev/stdout
> -else
> -	export VERBOSE=/dev/null
> +if [ -e "${dst}" -a "$force" = 0 ]; then
> +	echo "The ${dst} directory is not empty. Remove it, use another"
> +	echo "one (-d <dir>), or force overriding (-f)"
> +	exit 1
>  fi
>  
> -# Validate that we have all the arguments we need
> -res=$(validate_args)
> -if [ -n "$res" ]
> -then
> -	echo $res
> -	usage
> -	cleanup_and_exit 1
> -fi
> +rm -rf ${dst}
> +mkdir -p ${dst}
> +set_log_file ${dst}/abi-check.log
> +log "INFO" "Logs available in ${dst}/abi-check.log"
>  
> -HASH1=$(git show -s --format=%H "$TAG1" -- 2> /dev/null | tail -1)
> -HASH2=$(git show -s --format=%H "$TAG2" -- 2> /dev/null | tail -1)
> +command -v ${abicheck} || log "INFO" "Can't find ${abicheck} utility"
> +command -v ${abidump} || log "INFO" "Can't find ${abidump} utility"
>  
> -# Make sure our tags exist
> -res=$(validate_tags)
> -if [ -n "$res" ]
> -then
> -	echo $res
> -	cleanup_and_exit 1
> -fi
> +hash1=$(git show -s --format=%h "$tag1" -- 2> /dev/null | tail -1)
> +hash2=$(git show -s --format=%h "$tag2" -- 2> /dev/null | tail -1)
>  
>  # Make hashes available in output for non-local reference
> -TAG1="$TAG1 ($HASH1)"
> -TAG2="$TAG2 ($HASH2)"
> -
> -ABICHECK=`which abi-compliance-checker 2>/dev/null`
> -if [ $? -ne 0 ]
> -then
> -	log "INFO" "Can't find abi-compliance-checker utility"
> -	cleanup_and_exit 1
> -fi
> -
> -ABIDUMP=`which abi-dumper 2>/dev/null`
> -if [ $? -ne 0 ]
> -then
> -	log "INFO" "Can't find abi-dumper utility"
> -	cleanup_and_exit 1
> -fi
> +tag1="$tag1 ($hash1)"
> +tag2="$tag2 ($hash2)"
>  
> -log "INFO" "We're going to check and make sure that applications built"
> -log "INFO" "against DPDK DSOs from version $TAG1 will still run when executed"
> -log "INFO" "against DPDK DSOs built from version $TAG2."
> -log "INFO" ""
> -
> -# Check to make sure we have a clean tree
> -git status | grep -q clean
> -if [ $? -ne 0 ]
> -then
> -	log "WARN" "Working directory not clean, aborting"
> -	cleanup_and_exit 1
> +if [ "$hash1" = "$hash2" ]; then
> +	log "ERROR" "$tag1 and $tag2 are the same revisions"
> +	exit 1
>  fi
>  
> -# Move to the root of the git tree
> -cd $(dirname $0)/..
> +cmd mkdir -p ${dst}
>  
> -log "INFO" "Checking out version $TAG1 of the dpdk"
> -# Move to the old version of the tree
> -git checkout $HASH1
> +# dump abi for each revision
> +gen_abi ${hash1}
> +gen_abi ${hash2}
>  
> -fixup_config
> +# compare the abi dumps
> +ret=0
> +list=""
> +for i in ${dst}/${hash2}/*.dump; do
> +	name=`basename $i`
> +	libname=${name%.dump}
>  
> -# Checking abi compliance relies on using the dwarf information in
> -# The shared objects.  Thats only included in the DSO's if we build
> -# with -g
> -export EXTRA_CFLAGS="$EXTRA_CFLAGS -g -O0"
> -export EXTRA_LDFLAGS="$EXTRA_LDFLAGS -g"
> -
> -# Now configure the build
> -log "INFO" "Configuring DPDK $TAG1"
> -make config T=$TARGET O=$TARGET > $VERBOSE 2>&1
> -
> -log "INFO" "Building DPDK $TAG1. This might take a moment"
> -make -j$DPDK_MAKE_JOBS O=$TARGET > $VERBOSE 2>&1
> -
> -if [ $? -ne 0 ]
> -then
> -	log "INFO" "THE BUILD FAILED.  ABORTING"
> -	cleanup_and_exit 1
> -fi
> +	if [ ! -f $dst/${hash1}/$name ]; then
> +		log "INFO" "$NAME does not exist in $tag1. skipping..."
> +		continue
> +	fi
>  
> -# Move to the lib directory
> -cd $TARGET/lib
> -log "INFO" "COLLECTING ABI INFORMATION FOR $TAG1"
> -for i in `ls *.so`
> -do
> -	$ABIDUMP $i -o $ABI_DIR/$i-ABI-0.dump -lver $HASH1
> +	local_ret=0
> +	cmd $abicheck -l $libname \
> +	    -old $dst/${hash1}/$name -new $dst/${hash2}/$name || local_ret=$?
> +	if [ $local_ret != 0 ]; then
> +		log "NOTICE" "$abicheck returned $local_ret"
> +		ret=$local_ret
> +		list="$list $libname"
> +	fi
>  done
> -cd ../..
> -
> -# Now clean the tree, checkout the second tag, and rebuild
> -git clean -f -d
> -git reset --hard
> -# Move to the new version of the tree
> -log "INFO" "Checking out version $TAG2 of the dpdk"
> -git checkout $HASH2
> -
> -fixup_config
> -
> -# Now configure the build
> -log "INFO" "Configuring DPDK $TAG2"
> -make config T=$TARGET O=$TARGET > $VERBOSE 2>&1
> -
> -log "INFO" "Building DPDK $TAG2. This might take a moment"
> -make -j$DPDK_MAKE_JOBS O=$TARGET > $VERBOSE 2>&1
>  
> -if [ $? -ne 0 ]
> -then
> -	log "INFO" "THE BUILD FAILED.  ABORTING"
> -	cleanup_and_exit 1
> +if [ $ret != 0 ]; then
> +	log "NOTICE" "At least one call to $abicheck returned an error."
> +	log "NOTICE" "ABI may be incompatible, please check logs for details."
> +	log "NOTICE" "Incompatible list: $list"
> +else
> +	log "NOTICE" "No error detected, ABI is compatible."
>  fi
>  
> -cd $TARGET/lib
> -log "INFO" "COLLECTING ABI INFORMATION FOR $TAG2"
> -for i in `ls *.so`
> -do
> -	$ABIDUMP $i -o $ABI_DIR/$i-ABI-1.dump -lver $HASH2
> -done
> -cd ../..
> -
> -# Start comparison of ABI dumps
> -for i in `ls $ABI_DIR/*-1.dump`
> -do
> -	NEWNAME=`basename $i`
> -	OLDNAME=`basename $i | sed -e"s/1.dump/0.dump/"`
> -	LIBNAME=`basename $i | sed -e"s/-ABI-1.dump//"`
> -
> -	if [ ! -f $ABI_DIR/$OLDNAME ]
> -	then
> -		log "INFO" "$OLDNAME DOES NOT EXIST IN $TAG1. SKIPPING..."
> -	fi
> -
> -	#compare the abi dumps
> -	$ABICHECK -l $LIBNAME -old $ABI_DIR/$OLDNAME -new $ABI_DIR/$NEWNAME
> -done
> +log "INFO" "Logs are in ${dst}/abi-check.log"
> +log "INFO" "HTML reports are in ${dst}/${hash2}/compat_reports directory"
>  
> -git reset --hard
> -log "INFO" "ABI CHECK COMPLETE.  REPORTS ARE IN compat_report directory"
> -cleanup_and_exit 0
> +exit $ret
> -- 
> 2.11.0
> 
> 

^ permalink raw reply	[relevance 9%]

* [dpdk-dev] [PATCH v2 0/3] eventdev: add attribute based get APIs
    @ 2017-09-08 15:18  4% ` Harry van Haaren
  2017-09-08 15:18  3%   ` [dpdk-dev] [PATCH v2 4/4] eventdev: add device started attribute Harry van Haaren
  2017-09-08 15:36  4%   ` [dpdk-dev] [PATCH v3 0/4] eventdev: add attribute based get APIs Harry van Haaren
  1 sibling, 2 replies; 200+ results
From: Harry van Haaren @ 2017-09-08 15:18 UTC (permalink / raw)
  To: dev; +Cc: jerin.jacob, Harry van Haaren

This patchset refactors the eventdev API to be more flexible
and capable. In particular, the API is capable of returning an
error value if an invalid device, port or attribute ID is passed
in, which was not possible with the previous APIs.

The implementation of this patchset is based on a v1 patch[1],
and after some discussion this API was seen as the best solution.

In terms of flexibility, the attribute id allows addition of new
common eventdev layer attributes without breaking ABI or adding
new functions. Note that these attributes are not data-path, and
that PMDs should continue to use the xstats API for reporting any
unique PMD statistics that are available.

Regarding API/ABI compatibility, I have removed the functions from
the .map files - please review the .map file changes for ABI issues
carefully.

The last patch of this series adds a started attribute to the device,
allowing the application to query if a device is currently running.

-Harry

[1] http://dpdk.org/dev/patchwork/patch/27152/


Harry van Haaren (3):
  eventdev: add port attribute function
  eventdev: add dev attribute get function
  eventdev: add queue attribute function

 lib/librte_eventdev/rte_eventdev.c           |  88 +++++++++++------
 lib/librte_eventdev/rte_eventdev.h           | 115 ++++++++++-----------
 lib/librte_eventdev/rte_eventdev_version.map |  12 ++-
 test/test/test_eventdev.c                    | 132 +++++++++++++++++++------
 test/test/test_eventdev_octeontx.c           | 143 ++++++++++++++++++++-------
 5 files changed, 334 insertions(+), 156 deletions(-)

-- 
2.7.4

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v2 4/4] eventdev: add device started attribute
  2017-09-08 15:18  4% ` [dpdk-dev] [PATCH v2 0/3] eventdev: add attribute based get APIs Harry van Haaren
@ 2017-09-08 15:18  3%   ` Harry van Haaren
  2017-09-08 15:36  4%   ` [dpdk-dev] [PATCH v3 0/4] eventdev: add attribute based get APIs Harry van Haaren
  1 sibling, 0 replies; 200+ results
From: Harry van Haaren @ 2017-09-08 15:18 UTC (permalink / raw)
  To: dev; +Cc: jerin.jacob, Harry van Haaren

This commit adds an attribute to the eventdev, allowing applications
to retrieve if the eventdev is running or stopped. Note that no API
or ABI changes were required in adding the statistic, and code changes
are minimal.

Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 lib/librte_eventdev/rte_eventdev.c | 3 +++
 lib/librte_eventdev/rte_eventdev.h | 4 ++++
 2 files changed, 7 insertions(+)

diff --git a/lib/librte_eventdev/rte_eventdev.c b/lib/librte_eventdev/rte_eventdev.c
index 85c0960..9ec5d42 100644
--- a/lib/librte_eventdev/rte_eventdev.c
+++ b/lib/librte_eventdev/rte_eventdev.c
@@ -740,6 +740,9 @@ rte_event_dev_attr_get(uint8_t dev_id, uint32_t attr_id,
 	case RTE_EVENT_DEV_ATTR_QUEUE_COUNT:
 		*attr_value = dev->data->nb_queues;
 		break;
+	case RTE_EVENT_DEV_ATTR_STARTED:
+		*attr_value = dev->data->dev_started;
+		break;
 	}
 
 	return 0;
diff --git a/lib/librte_eventdev/rte_eventdev.h b/lib/librte_eventdev/rte_eventdev.h
index cd3026d..f76d9f9 100644
--- a/lib/librte_eventdev/rte_eventdev.h
+++ b/lib/librte_eventdev/rte_eventdev.h
@@ -695,6 +695,10 @@ rte_event_port_setup(uint8_t dev_id, uint8_t port_id,
  * The count of queues.
  */
 #define RTE_EVENT_DEV_ATTR_QUEUE_COUNT 1
+/**
+ * The state of the device, returns zero if stopped, non-zero when running.
+ */
+#define RTE_EVENT_DEV_ATTR_STARTED 2
 
 /**
  * Get an attribute from a device.
-- 
2.7.4

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v3 0/4] eventdev: add attribute based get APIs
  2017-09-08 15:18  4% ` [dpdk-dev] [PATCH v2 0/3] eventdev: add attribute based get APIs Harry van Haaren
  2017-09-08 15:18  3%   ` [dpdk-dev] [PATCH v2 4/4] eventdev: add device started attribute Harry van Haaren
@ 2017-09-08 15:36  4%   ` Harry van Haaren
  2017-09-08 15:36  3%     ` [dpdk-dev] [PATCH v3 4/4] eventdev: add device started attribute Harry van Haaren
                       ` (2 more replies)
  1 sibling, 3 replies; 200+ results
From: Harry van Haaren @ 2017-09-08 15:36 UTC (permalink / raw)
  To: dev; +Cc: jerin.jacob, Harry van Haaren

This patchset refactors the eventdev API to be more flexible
and capable. In particular, the API is capable of returning an
error value if an invalid device, port or attribute ID is passed
in, which was not possible with the previous APIs.

The implementation of this patchset is based on a v1 patch[1],
and after some discussion this API was seen as the best solution.

In terms of flexibility, the attribute id allows addition of new
common eventdev layer attributes without breaking ABI or adding
new functions. Note that these attributes are not data-path, and
that PMDs should continue to use the xstats API for reporting any
unique PMD statistics that are available.

Regarding API/ABI compatibility, I have removed the functions from
the .map files - please review the .map file changes for ABI issues
carefully.

The last patch of this series adds a started attribute to the device,
allowing the application to query if a device is currently running.

-Harry

[1] http://dpdk.org/dev/patchwork/patch/27152/

---

v3:
- Fix checkpatch issues... somehow I broke my checkpatch script :/

v2:
- New APIs design based on discussion of initial patch.



Harry van Haaren (4):
  eventdev: add port attribute function
  eventdev: add dev attribute get function
  eventdev: add queue attribute function
  eventdev: add device started attribute

 lib/librte_eventdev/rte_eventdev.c           |  91 +++++++++++------
 lib/librte_eventdev/rte_eventdev.h           | 118 +++++++++++-----------
 lib/librte_eventdev/rte_eventdev_version.map |  12 ++-
 test/test/test_eventdev.c                    | 132 +++++++++++++++++++------
 test/test/test_eventdev_octeontx.c           | 143 ++++++++++++++++++++-------
 5 files changed, 340 insertions(+), 156 deletions(-)

-- 
2.7.4

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v3 4/4] eventdev: add device started attribute
  2017-09-08 15:36  4%   ` [dpdk-dev] [PATCH v3 0/4] eventdev: add attribute based get APIs Harry van Haaren
@ 2017-09-08 15:36  3%     ` Harry van Haaren
  2017-09-11 17:52  0%       ` Jerin Jacob
  2017-09-11 16:16  0%     ` [dpdk-dev] [PATCH v3 0/4] eventdev: add attribute based get APIs Jerin Jacob
  2017-09-14 16:08  4%     ` [dpdk-dev] [PATCH v4 " Harry van Haaren
  2 siblings, 1 reply; 200+ results
From: Harry van Haaren @ 2017-09-08 15:36 UTC (permalink / raw)
  To: dev; +Cc: jerin.jacob, Harry van Haaren

This commit adds an attribute to the eventdev, allowing applications
to retrieve if the eventdev is running or stopped. Note that no API
or ABI changes were required in adding the statistic, and code changes
are minimal.

Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 lib/librte_eventdev/rte_eventdev.c | 3 +++
 lib/librte_eventdev/rte_eventdev.h | 4 ++++
 2 files changed, 7 insertions(+)

diff --git a/lib/librte_eventdev/rte_eventdev.c b/lib/librte_eventdev/rte_eventdev.c
index 3756ec7..87a1e19 100644
--- a/lib/librte_eventdev/rte_eventdev.c
+++ b/lib/librte_eventdev/rte_eventdev.c
@@ -740,6 +740,9 @@ rte_event_dev_attr_get(uint8_t dev_id, uint32_t attr_id,
 	case RTE_EVENT_DEV_ATTR_QUEUE_COUNT:
 		*attr_value = dev->data->nb_queues;
 		break;
+	case RTE_EVENT_DEV_ATTR_STARTED:
+		*attr_value = dev->data->dev_started;
+		break;
 	}
 
 	return 0;
diff --git a/lib/librte_eventdev/rte_eventdev.h b/lib/librte_eventdev/rte_eventdev.h
index cd3026d..f76d9f9 100644
--- a/lib/librte_eventdev/rte_eventdev.h
+++ b/lib/librte_eventdev/rte_eventdev.h
@@ -695,6 +695,10 @@ rte_event_port_setup(uint8_t dev_id, uint8_t port_id,
  * The count of queues.
  */
 #define RTE_EVENT_DEV_ATTR_QUEUE_COUNT 1
+/**
+ * The state of the device, returns zero if stopped, non-zero when running.
+ */
+#define RTE_EVENT_DEV_ATTR_STARTED 2
 
 /**
  * Get an attribute from a device.
-- 
2.7.4

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH 01/17] build: add initial infrastructure for meson & ninja builds
  @ 2017-09-08 16:03  3%   ` Van Haaren, Harry
  0 siblings, 0 replies; 200+ results
From: Van Haaren, Harry @ 2017-09-08 16:03 UTC (permalink / raw)
  To: Richardson, Bruce, dev; +Cc: Richardson, Bruce

> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bruce Richardson
> Sent: Friday, September 1, 2017 11:04 AM
> To: dev@dpdk.org
> Cc: Richardson, Bruce <bruce.richardson@intel.com>
> Subject: [dpdk-dev] [PATCH 01/17] build: add initial infrastructure for meson &
> ninja builds

<snip commit message etc>

> diff --git a/config/meson.build b/config/meson.build
<snip>
> +# set the machine type and cflags for it
> +machine = get_option('machine')
> +dpdk_conf.set('RTE_MACHINE', machine)
> +add_project_arguments('-march=@0@'.format(machine), language: 'c')
> +# some libs depend on maths lib
> +add_project_link_arguments('-lm', language: 'c')
> +
> +# add -include rte_config to cflags
> +add_project_arguments('-include', 'rte_config.h', language: 'c')
> +
> +# disable any unwanted warnings
> +unwanted_warnings = [
> +	'-Wno-address-of-packed-member',
> +	'-Wno-format-truncation'
> +]


Feedback from usage while developing new features;
- Mis-matched integer sign comparison doesn't cause a warning
- And -Werror isn't set by default

Adding these as per below fixes things... but for cleanliness "unwanted warnings" should probably be renamed, we want more warnings! :D

# disable any unwanted warnings
unwanted_warnings = [
	'-Werror',
	'-Wno-address-of-packed-member',
	'-Wno-format-truncation',
	'-Wsign-compare',
]

The performance of Ninja is amazing for testing shared-object builds and version.map changes - feedback is instant. Makes light work of re-checking ABI/API stuff.

> +foreach arg: unwanted_warnings
> +	if cc.has_argument(arg)
> +		add_project_arguments(arg, language: 'c')
> +	endif
> +endforeach
> +

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v2 0/2] ethdev new offloads API
  2017-09-04  7:12  3% [dpdk-dev] [PATCH 0/4] ethdev new offloads API Shahaf Shuler
  2017-09-04  7:12  2% ` [dpdk-dev] [PATCH 2/4] ethdev: introduce Rx queue " Shahaf Shuler
  2017-09-04  7:12  2% ` [dpdk-dev] [PATCH 3/4] ethdev: introduce Tx " Shahaf Shuler
@ 2017-09-10 12:07  4% ` Shahaf Shuler
  2017-09-13  6:37  4%   ` [dpdk-dev] [PATCH v3 " Shahaf Shuler
  2 siblings, 1 reply; 200+ results
From: Shahaf Shuler @ 2017-09-10 12:07 UTC (permalink / raw)
  To: thomas; +Cc: dev

Tx offloads configuration is per queue. Tx offloads are enabled by default, 
and can be disabled using ETH_TXQ_FLAGS_NO* flags. 
This behaviour is not consistent with the Rx side where the Rx offloads
configuration is per port. Rx offloads are disabled by default and enabled 
according to bit field in rte_eth_rxmode structure.

Moreover, considering more Tx and Rx offloads will be added 
over time, the cost of managing them all inside the PMD will be tremendous,
as the PMD will need to check the matching for the entire offload set 
for each mbuf it handles.
In addition, on the current approach each Rx offload added breaks the
ABI compatibility as it requires to add entries to existing bit-fields.
 
The series address above issues by defining a new offloads API.
With the new API, Tx and Rx offloads configuration is per queue.
The offloads are disabled by default. Each offload can be enabled or
disabled using the existing DEV_TX_OFFLOADS_* or DEV_RX_OFFLOADS_* flags.
Such API will enable to easily add or remove offloads, without breaking the
ABI compatibility.

The new API does not have an equivalent for the below Tx flags:

* ETH_TXQ_FLAGS_NOREFCOUNT
* ETH_TXQ_FLAGS_NOMULTMEMP

The reason is that those flags are not to manage offloads, rather some
guarantee from application on the way it uses mbufs, therefore could not be
present as part of DEV_TX_OFFLOADS_*.
Such flags are useful only for benchmarks, and therefore provide a non-realistic    
performance for DPDK customers using simple benchmarks for evaluation.
Leveraging the work being done in this series to clean up those flags.

In order to provide a smooth transition between the APIs the following actions
were taken:
*  The old offloads API is kept for the meanwhile.
*  New capabilities were added for PMD to advertize it has moved to the new
   offloads API.
*  Helper function which copy from old to new API were added to ethdev,
   enabling the PMD to support only one of the APIs.

Per discussion made on the RFC of this series [1], the integration plan which was
decided is to do the transition in two phases:
* ethdev API will move on 17.11.
* Apps and examples will move on 18.02.

This to enable PMD maintainers sufficient time to adopt the new API.

[1]
http://dpdk.org/ml/archives/dev/2017-August/072643.html

on v2:
 - Taking new approach of dividing offloads into per-queue and per-port one.
 - Postpone the Tx/Rx public struct renaming to 18.02
 - squash the helper functions into the Rx/Tx offloads intro patches.

Shahaf Shuler (2):
  ethdev: introduce Rx queue offloads API
  ethdev: introduce Tx queue offloads API

 doc/guides/nics/features.rst  |  27 +++--
 lib/librte_ether/rte_ethdev.c | 215 ++++++++++++++++++++++++++++++++++---
 lib/librte_ether/rte_ethdev.h |  84 ++++++++++++++-
 3 files changed, 301 insertions(+), 25 deletions(-)

-- 
2.12.0

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v2] devtools: rework abi checker script
  2017-09-08 13:46  9%   ` Neil Horman
@ 2017-09-11  8:18  7%     ` Olivier MATZ
  2017-09-11  8:46 26%       ` [dpdk-dev] [PATCH v3] " Olivier Matz
  0 siblings, 1 reply; 200+ results
From: Olivier MATZ @ 2017-09-11  8:18 UTC (permalink / raw)
  To: Neil Horman; +Cc: dev, bruce.richardson

Hello Neil,

On Fri, Sep 08, 2017 at 09:46:49AM -0400, Neil Horman wrote:
> On Wed, Sep 06, 2017 at 04:51:01PM +0200, Olivier Matz wrote:
> > The intiatial version of the script had some limitations:
> > - cannot work on a non-clean workspace
> > - environment variables are not documented
> > - no compilation log in case of failure
> > - return success even it abi is incompatible
> > 
> > This patch addresses these issues and rework the code.
> > 
> > Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> > ---
> > 
> > v1->v2:
> > - use /usr/bin/env to find bash (which is required)
> > - fix displayed path to html reports
> > - reword help for -f option
> > 
> This still doesn't seem to work.  Running the following:
> ./validate-abi.sh v17.05 v17.08
> 
> produces no report, and the end of the abi-check.log file contains:
> 
> [nhorman@hmswarspite abi-check]$ tail -n 10 ./abi-check.log 
> CMD: abi-dumper librte_vhost.so -o /home/nhorman/git/dpdk/devtools/abi-check/222555480/librte_vhost.so.dump -lver 222555480
> Reading debug-info
> WARNING: incompatible build option detected: -O0 (required -Og for better analysis)
> Creating ABI dump
> 
> The object ABI has been dumped to:
>   /home/nhorman/git/dpdk/devtools/abi-check/222555480/librte_vhost.so.dump
> CMD: cd ../..
> CMD: git clone ./.. /home/nhorman/git/dpdk/devtools/abi-check/02657b4ad
> fatal: repository './..' does not exist
> 
> The warning I assume should be fixed to, but the second clone failing seems to
> be the most salient bit here

Thanks for testing. The script was not behaving well when not started
from dpdk root dir. It's fixed, I'm sending a v3.

I changed the -O0 into -Og, and I also had to append -Wno-error because the
compilation fails with -Og (variable may be used uninitialized). I'll send
another patch to fix it.

Some warnings are still displayed: these are false positive from abi-dumper.
The compilation flags are "[...] -O3 [...] -Og [...]". The second -O switch
overrides the first one, but it is not properly detected. It could be
workarounded by setting a global optimization level (which does not exist yet)
instead of overring it through EXTRA_CFLAGS.

Olivier

^ permalink raw reply	[relevance 7%]

* [dpdk-dev] [PATCH v3] devtools: rework abi checker script
  2017-09-11  8:18  7%     ` Olivier MATZ
@ 2017-09-11  8:46 26%       ` Olivier Matz
  2017-09-13 15:00  9%         ` Neil Horman
  0 siblings, 1 reply; 200+ results
From: Olivier Matz @ 2017-09-11  8:46 UTC (permalink / raw)
  To: dev, nhorman, bruce.richardson

The initial version of the script had some limitations:
- cannot work on a non-clean workspace
- environment variables are not documented
- no compilation log in case of failure
- return success even it abi is incompatible

This patch addresses these issues and rework the code.

Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---

v2->v3:
- fix when not launched from dpdk root dir
- use "-Og -Wno-error" instead of "-O0"
- fix typo in commit log

v1->v2:
- use /usr/bin/env to find bash (which is required)
- fix displayed path to html reports
- reword help for -f option

 devtools/validate-abi.sh | 392 ++++++++++++++++++++++++-----------------------
 1 file changed, 200 insertions(+), 192 deletions(-)

diff --git a/devtools/validate-abi.sh b/devtools/validate-abi.sh
index 0accc99b1..8a512aa3b 100755
--- a/devtools/validate-abi.sh
+++ b/devtools/validate-abi.sh
@@ -1,7 +1,8 @@
-#!/bin/sh
+#!/usr/bin/env bash
 #   BSD LICENSE
 #
 #   Copyright(c) 2015 Neil Horman. All rights reserved.
+#   Copyright(c) 2017 6WIND S.A.
 #   All rights reserved.
 #
 #   Redistribution and use in source and binary forms, with or without
@@ -27,236 +28,243 @@
 #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-TAG1=$1
-TAG2=$2
-TARGET=$3
-ABI_DIR=`mktemp -d -p /tmp ABI.XXXXXX`
+set -e
 
-usage() {
-	echo "$0 <REV1> <REV2> <TARGET>"
-}
+abicheck=abi-compliance-checker
+abidump=abi-dumper
+default_dst=abi-check
+default_target=x86_64-native-linuxapp-gcc
 
-log() {
-	local level=$1
-	shift
-	echo "$*"
+# trap on error
+err_report() {
+    echo "$0: error at line $1"
 }
+trap 'err_report $LINENO' ERR
 
-validate_tags() {
+print_usage () {
+	cat <<- END_OF_HELP
+	$(basename $0) [options] <rev1> <rev2>
 
-	if [ -z "$HASH1" ]
-	then
-		echo "invalid revision: $TAG1"
-		return
-	fi
-	if [ -z "$HASH2" ]
-	then
-		echo "invalid revision: $TAG2"
-		return
-	fi
+	This script compares the ABI of 2 git revisions of the current
+	workspace. The output is a html report and a compilation log.
+
+	The objective is to make sure that applications built against
+	DSOs from the first revision can still run when executed using
+	the DSOs built from the second revision.
+
+	<rev1> and <rev2> are git commit id or tags.
+
+	Options:
+	  -h		show this help
+	  -j <num>	enable parallel compilation with <num> threads
+	  -v		show compilation logs on the console
+	  -d <dir>	change working directory (default is ${default_dst})
+	  -t <target>	the dpdk target to use (default is ${default_target})
+	  -f		overwrite existing files in destination directory
+
+	The script returns 0 on success, or the value of last failing
+	call of ${abicheck} (incompatible abi or the tool has run with errors).
+	The errors returned by ${abidump} are ignored.
+
+	END_OF_HELP
 }
 
-validate_args() {
-	if [ -z "$TAG1" ]
-	then
-		echo "Must Specify REV1"
-		return
-	fi
-	if [ -z "$TAG2" ]
-	then
-		echo "Must Specify REV2"
-		return
-	fi
-	if [ -z "$TARGET" ]
-	then
-		echo "Must Specify a build target"
+# log in the file, and on stdout if verbose
+# $1: level string
+# $2: string to be logged
+log() {
+	echo "$1: $2"
+	if [ "${verbose}" != "true" ]; then
+		echo "$1: $2" >&3
 	fi
 }
 
+# launch a command and log it, taking care of surrounding spaces with quotes
+cmd() {
+	local i s whitespace
+	s=""
+	whitespace="[[:space:]]"
+	for i in "$@"; do
+		if [[ $i =~ $whitespace ]]; then
+			i=\"$i\"
+		fi
+		if [ -z "$s" ]; then
+			s="$i"
+		else
+			s="$s $i"
+		fi
+	done
+
+	log "CMD" "$s"
+	"$@"
+}
 
-cleanup_and_exit() {
-	rm -rf $ABI_DIR
-	git checkout $CURRENT_BRANCH
-	exit $1
+# redirect or copy stderr/stdout to a file
+# the syntax is unfamiliar, but it makes the rest of the
+# code easier to read, avoiding the use of pipes
+set_log_file() {
+	# save original stdout and stderr in fd 3 and 4
+	exec 3>&1
+	exec 4>&2
+	# create a new fd 5 that send to a file
+	exec 5> >(cat > $1)
+	# send stdout and stderr to fd 5
+	if [ "${verbose}" = "true" ]; then
+		exec 1> >(tee /dev/fd/5 >&3)
+		exec 2> >(tee /dev/fd/5 >&4)
+	else
+		exec 1>&5
+		exec 2>&5
+	fi
 }
 
 # Make sure we configure SHARED libraries
 # Also turn off IGB and KNI as those require kernel headers to build
 fixup_config() {
-	sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" config/defconfig_$TARGET
-	sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" config/defconfig_$TARGET
-	sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" config/defconfig_$TARGET
-	sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" config/defconfig_$TARGET
-	sed -i -e"$ a\CONFIG_RTE_KNI_KMOD=n" config/defconfig_$TARGET
+	local conf=config/defconfig_$target
+	cmd sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" $conf
+	cmd sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" $conf
+	cmd sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" $conf
+	cmd sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" $conf
+	cmd sed -i -e"$ a\CONFIG_RTE_KNI_KMOD=n" $conf
 }
 
-###########################################
-#START
-############################################
+# build dpdk for the given tag and dump abi
+# $1: hash of the revision
+gen_abi() {
+	local i oldpwd
+
+	oldpwd=${PWD}
+	cmd git clone $(dirname $0)/.. ${dst}/${1}
+	cmd cd ${dst}/${1}
+
+	log "INFO" "Checking out version ${1} of the dpdk"
+	# Move to the old version of the tree
+	cmd git checkout ${1}
+
+	fixup_config
+
+	# Now configure the build
+	log "INFO" "Configuring DPDK ${1}"
+	cmd make config T=$target O=$target > ${dst}/log 2>&1
+
+	# Checking abi compliance relies on using the dwarf information in
+	# the shared objects. Build with -g to include them.
+	log "INFO" "Building DPDK ${1}. This might take a moment"
+	cmd make -j$parallel O=$target V=1 EXTRA_CFLAGS="-g -Og -Wno-error" \
+	    EXTRA_LDFLAGS="-g" || log "INFO" "The build failed"
+
+	# Move to the lib directory
+	cmd cd ${PWD}/$target/lib
+	log "INFO" "Collecting ABI information for ${1}"
+	for i in *.so; do
+		[ -e "$i" ] || break
+		cmd $abidump ${i} -o $dst/${1}/${i}.dump -lver ${1} || true
+		# hack to ignore empty SymbolsInfo section (no public ABI)
+		if grep -q "'SymbolInfo' => {}," $dst/${1}/${i}.dump \
+				2> /dev/null; then
+			log "INFO" "${i} has no public ABI, remove dump file"
+			cmd rm -f $dst/${1}/${i}.dump
+		fi
+	done
+	cmd cd ${oldpwd}
+}
 
-#trap on ctrl-c to clean up
-trap cleanup_and_exit SIGINT
+verbose=false
+parallel=1
+dst=${default_dst}
+target=${default_target}
+force=0
+while getopts j:vd:t:fh ARG ; do
+	case $ARG in
+		j ) parallel=$OPTARG ;;
+		v ) verbose=true ;;
+		d ) dst=$OPTARG ;;
+		t ) target=$OPTARG ;;
+		f ) force=1 ;;
+		h ) print_usage ; exit 0 ;;
+		? ) print_usage ; exit 1 ;;
+	esac
+done
+shift $(($OPTIND - 1))
 
-if [ -z "$DPDK_MAKE_JOBS" ]
-then
-	# This counts the number of cpus on the system
-	if [ -e /usr/bin/lscpu ]
-	then
-		DPDK_MAKE_JOBS=`lscpu -p=cpu | grep -v "#" | wc -l`
-	else
-		DPDK_MAKE_JOBS=1
-	fi
+if [ $# != 2 ]; then
+	print_usage
+	exit 1
 fi
 
-#Save the current branch
-CURRENT_BRANCH=`git branch | grep \* | cut -d' ' -f2`
+tag1=$1
+tag2=$2
 
-if [ -z "$CURRENT_BRANCH" ]
-then
-	CURRENT_BRANCH=`git log --pretty=format:%H HEAD~1..HEAD`
-fi
+# convert path to absolute
+case "${dst}" in
+	/*) ;;
+	*) dst=${PWD}/${dst} ;;
+esac
 
-if [ -n "$VERBOSE" ]
-then
-	export VERBOSE=/dev/stdout
-else
-	export VERBOSE=/dev/null
+if [ -e "${dst}" -a "$force" = 0 ]; then
+	echo "The ${dst} directory is not empty. Remove it, use another"
+	echo "one (-d <dir>), or force overriding (-f)"
+	exit 1
 fi
 
-# Validate that we have all the arguments we need
-res=$(validate_args)
-if [ -n "$res" ]
-then
-	echo $res
-	usage
-	cleanup_and_exit 1
-fi
+rm -rf ${dst}
+mkdir -p ${dst}
+set_log_file ${dst}/abi-check.log
+log "INFO" "Logs available in ${dst}/abi-check.log"
 
-HASH1=$(git show -s --format=%H "$TAG1" -- 2> /dev/null | tail -1)
-HASH2=$(git show -s --format=%H "$TAG2" -- 2> /dev/null | tail -1)
+command -v ${abicheck} || log "INFO" "Can't find ${abicheck} utility"
+command -v ${abidump} || log "INFO" "Can't find ${abidump} utility"
 
-# Make sure our tags exist
-res=$(validate_tags)
-if [ -n "$res" ]
-then
-	echo $res
-	cleanup_and_exit 1
-fi
+hash1=$(git show -s --format=%h "$tag1" -- 2> /dev/null | tail -1)
+hash2=$(git show -s --format=%h "$tag2" -- 2> /dev/null | tail -1)
 
 # Make hashes available in output for non-local reference
-TAG1="$TAG1 ($HASH1)"
-TAG2="$TAG2 ($HASH2)"
-
-ABICHECK=`which abi-compliance-checker 2>/dev/null`
-if [ $? -ne 0 ]
-then
-	log "INFO" "Can't find abi-compliance-checker utility"
-	cleanup_and_exit 1
-fi
-
-ABIDUMP=`which abi-dumper 2>/dev/null`
-if [ $? -ne 0 ]
-then
-	log "INFO" "Can't find abi-dumper utility"
-	cleanup_and_exit 1
-fi
+tag1="$tag1 ($hash1)"
+tag2="$tag2 ($hash2)"
 
-log "INFO" "We're going to check and make sure that applications built"
-log "INFO" "against DPDK DSOs from version $TAG1 will still run when executed"
-log "INFO" "against DPDK DSOs built from version $TAG2."
-log "INFO" ""
-
-# Check to make sure we have a clean tree
-git status | grep -q clean
-if [ $? -ne 0 ]
-then
-	log "WARN" "Working directory not clean, aborting"
-	cleanup_and_exit 1
+if [ "$hash1" = "$hash2" ]; then
+	log "ERROR" "$tag1 and $tag2 are the same revisions"
+	exit 1
 fi
 
-# Move to the root of the git tree
-cd $(dirname $0)/..
+cmd mkdir -p ${dst}
 
-log "INFO" "Checking out version $TAG1 of the dpdk"
-# Move to the old version of the tree
-git checkout $HASH1
+# dump abi for each revision
+gen_abi ${hash1}
+gen_abi ${hash2}
 
-fixup_config
+# compare the abi dumps
+ret=0
+list=""
+for i in ${dst}/${hash2}/*.dump; do
+	name=`basename $i`
+	libname=${name%.dump}
 
-# Checking abi compliance relies on using the dwarf information in
-# The shared objects.  Thats only included in the DSO's if we build
-# with -g
-export EXTRA_CFLAGS="$EXTRA_CFLAGS -g -O0"
-export EXTRA_LDFLAGS="$EXTRA_LDFLAGS -g"
-
-# Now configure the build
-log "INFO" "Configuring DPDK $TAG1"
-make config T=$TARGET O=$TARGET > $VERBOSE 2>&1
-
-log "INFO" "Building DPDK $TAG1. This might take a moment"
-make -j$DPDK_MAKE_JOBS O=$TARGET > $VERBOSE 2>&1
-
-if [ $? -ne 0 ]
-then
-	log "INFO" "THE BUILD FAILED.  ABORTING"
-	cleanup_and_exit 1
-fi
+	if [ ! -f $dst/${hash1}/$name ]; then
+		log "INFO" "$NAME does not exist in $tag1. skipping..."
+		continue
+	fi
 
-# Move to the lib directory
-cd $TARGET/lib
-log "INFO" "COLLECTING ABI INFORMATION FOR $TAG1"
-for i in `ls *.so`
-do
-	$ABIDUMP $i -o $ABI_DIR/$i-ABI-0.dump -lver $HASH1
+	local_ret=0
+	cmd $abicheck -l $libname \
+	    -old $dst/${hash1}/$name -new $dst/${hash2}/$name || local_ret=$?
+	if [ $local_ret != 0 ]; then
+		log "NOTICE" "$abicheck returned $local_ret"
+		ret=$local_ret
+		list="$list $libname"
+	fi
 done
-cd ../..
-
-# Now clean the tree, checkout the second tag, and rebuild
-git clean -f -d
-git reset --hard
-# Move to the new version of the tree
-log "INFO" "Checking out version $TAG2 of the dpdk"
-git checkout $HASH2
-
-fixup_config
-
-# Now configure the build
-log "INFO" "Configuring DPDK $TAG2"
-make config T=$TARGET O=$TARGET > $VERBOSE 2>&1
-
-log "INFO" "Building DPDK $TAG2. This might take a moment"
-make -j$DPDK_MAKE_JOBS O=$TARGET > $VERBOSE 2>&1
 
-if [ $? -ne 0 ]
-then
-	log "INFO" "THE BUILD FAILED.  ABORTING"
-	cleanup_and_exit 1
+if [ $ret != 0 ]; then
+	log "NOTICE" "At least one call to $abicheck returned an error."
+	log "NOTICE" "ABI may be incompatible, please check logs for details."
+	log "NOTICE" "Incompatible list: $list"
+else
+	log "NOTICE" "No error detected, ABI is compatible."
 fi
 
-cd $TARGET/lib
-log "INFO" "COLLECTING ABI INFORMATION FOR $TAG2"
-for i in `ls *.so`
-do
-	$ABIDUMP $i -o $ABI_DIR/$i-ABI-1.dump -lver $HASH2
-done
-cd ../..
-
-# Start comparison of ABI dumps
-for i in `ls $ABI_DIR/*-1.dump`
-do
-	NEWNAME=`basename $i`
-	OLDNAME=`basename $i | sed -e"s/1.dump/0.dump/"`
-	LIBNAME=`basename $i | sed -e"s/-ABI-1.dump//"`
-
-	if [ ! -f $ABI_DIR/$OLDNAME ]
-	then
-		log "INFO" "$OLDNAME DOES NOT EXIST IN $TAG1. SKIPPING..."
-	fi
-
-	#compare the abi dumps
-	$ABICHECK -l $LIBNAME -old $ABI_DIR/$OLDNAME -new $ABI_DIR/$NEWNAME
-done
+log "INFO" "Logs are in ${dst}/abi-check.log"
+log "INFO" "HTML reports are in ${dst}/${hash2}/compat_reports directory"
 
-git reset --hard
-log "INFO" "ABI CHECK COMPLETE.  REPORTS ARE IN compat_report directory"
-cleanup_and_exit 0
+exit $ret
-- 
2.11.0

^ permalink raw reply	[relevance 26%]

* Re: [dpdk-dev] [PATCH v3 1/4] ethdev: increase port_id range
  @ 2017-09-11  9:37  3%     ` Adrien Mazarguil
  2017-09-11 10:51  0%       ` Yang, Zhiyong
  2017-09-11 10:21  4%     ` Ferruh Yigit
  1 sibling, 1 reply; 200+ results
From: Adrien Mazarguil @ 2017-09-11  9:37 UTC (permalink / raw)
  To: Zhiyong Yang; +Cc: dev, thomas, ferruh.yigit, hemant.agrawal, david.hunt

Hi Zhiyong,

On Sat, Sep 09, 2017 at 10:47:24PM +0800, Zhiyong Yang wrote:
> Extend port_id definition from uint8_t to uint16_t in lib and drivers
> data structures, specifically rte_eth_dev_data.
> Modify the APIs, drivers and app using port_id at the same time.
> 
> Fix some checkpatch issues from the original code and remove some
> unnecessary cast operations.
> 
> Signed-off-by: Zhiyong Yang <zhiyong.yang@intel.com>

Thanks for the mlx4/mlx5 update, I have some comments, see below.

By the way, since this commit breaks ABI compatibility for pretty much all
public functions in librte_ether and a few in other places, remember to
update rte_ethdev_version.map and other affected .map files accordingly.
I think this change has to be part of this series.

<snip>
> diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
> index c0ade4f1a..fe911c3a7 100644
> --- a/drivers/net/mlx4/mlx4.h
> +++ b/drivers/net/mlx4/mlx4.h
> @@ -334,7 +334,7 @@ struct priv {
>  	} vlan_filter[MLX4_MAX_VLAN_IDS]; /* VLAN filters table. */
>  	/* Device properties. */
>  	uint16_t mtu; /* Configured MTU. */
> -	uint8_t port; /* Physical port number. */
> +	uint16_t port; /* Physical port number. */
>  	unsigned int started:1; /* Device started, flows enabled. */
>  	unsigned int promisc:1; /* Device in promiscuous mode. */
>  	unsigned int allmulti:1; /* Device receives all multicast packets. */

This is a physical port number internal to the device, not DPDK's. Please
drop this change.

What would need change is struct rxq's port_id field (already large enough)
if you want to enforce uint16_t everywhere.

> diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
> index 43c538419..54a2e8a54 100644
> --- a/drivers/net/mlx5/mlx5.h
> +++ b/drivers/net/mlx5/mlx5.h
> @@ -114,7 +114,7 @@ struct priv {
>  	unsigned int vlan_filter_n; /* Number of configured VLAN filters. */
>  	/* Device properties. */
>  	uint16_t mtu; /* Configured MTU. */
> -	uint8_t port; /* Physical port number. */
> +	uint16_t port; /* Physical port number. */

Same comment here.

>  	unsigned int started:1; /* Device started, flows enabled. */
>  	unsigned int promisc_req:1; /* Promiscuous mode requested. */
>  	unsigned int allmulti_req:1; /* All multicast mode requested. */
> diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c
> index b0eb3cdfc..58e7cf571 100644
> --- a/drivers/net/mlx5/mlx5_ethdev.c
> +++ b/drivers/net/mlx5/mlx5_ethdev.c
> @@ -75,7 +75,7 @@ struct ethtool_link_settings {
>  	uint32_t cmd;
>  	uint32_t speed;
>  	uint8_t duplex;
> -	uint8_t port;
> +	uint16_t port;

This is the ethtool interface from the Linux kernel, again this field has to
remain 8 bits.

That's the kind of mistakes a dedicated type might have prevented by the
way, I'm still not convinced that not adding one was the right decision.

>  	uint8_t phy_address;
>  	uint8_t autoneg;
>  	uint8_t mdio_support;
> diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h
> index 7de1d1086..c47e54fe0 100644
> --- a/drivers/net/mlx5/mlx5_rxtx.h
> +++ b/drivers/net/mlx5/mlx5_rxtx.h
> @@ -112,7 +112,6 @@ struct rxq {
>  	unsigned int sges_n:2; /* Log 2 of SGEs (max buffers per packet). */
>  	unsigned int cqe_n:4; /* Log 2 of CQ elements. */
>  	unsigned int elts_n:4; /* Log 2 of Mbufs. */
> -	unsigned int port_id:8;
>  	unsigned int rss_hash:1; /* RSS hash result is enabled. */
>  	unsigned int mark:1; /* Marked flow available on the queue. */
>  	unsigned int pending_err:1; /* CQE error needs to be handled. */
> @@ -120,6 +119,7 @@ struct rxq {
>  	unsigned int :6; /* Remaining bits. */
>  	volatile uint32_t *rq_db;
>  	volatile uint32_t *cq_db;
> +	uint16_t port_id;
>  	uint16_t rq_ci;
>  	uint16_t rq_pi;
>  	uint16_t cq_ci;

This change might have a performance impact. All important fields are found
at the beginning of this structure for that reason. Since there's not enough
room in the above bit-field (8 + 6), I guess there's no other choice for
now, however you should at least update the "Remaining bits" comment.

<snip>

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v3 1/4] ethdev: increase port_id range
    2017-09-11  9:37  3%     ` Adrien Mazarguil
@ 2017-09-11 10:21  4%     ` Ferruh Yigit
  2017-09-13  2:26  0%       ` Yang, Zhiyong
  1 sibling, 1 reply; 200+ results
From: Ferruh Yigit @ 2017-09-11 10:21 UTC (permalink / raw)
  To: Zhiyong Yang, dev, Declan Doherty, Wenzhuo Lu
  Cc: thomas, hemant.agrawal, david.hunt

On 9/9/2017 3:47 PM, Zhiyong Yang wrote:
> Extend port_id definition from uint8_t to uint16_t in lib and drivers
> data structures, specifically rte_eth_dev_data.
> Modify the APIs, drivers and app using port_id at the same time.
> 
> Fix some checkpatch issues from the original code and remove some
> unnecessary cast operations.
> 
> Signed-off-by: Zhiyong Yang <zhiyong.yang@intel.com>

<...>

> @@ -283,7 +283,7 @@ enum dcb_mode_enable
>  #define MAX_RX_QUEUE_STATS_MAPPINGS 4096 /* MAX_PORT of 32 @ 128 rx_queues/port */
>  
>  struct queue_stats_mappings {
> -	uint8_t port_id;
> +	uint16_t port_id;

Can this be "portid_t port_id;" ? For testpmd, portid_t can be used for
all port_id declarations.

<...>

> --- a/drivers/net/bnx2x/bnx2x.c
> +++ b/drivers/net/bnx2x/bnx2x.c
> @@ -703,7 +703,7 @@ bnx2x_gpio_mult_write(struct bnx2x_softc *sc, uint8_t pins, uint32_t mode)
>  
>  static int
>  bnx2x_gpio_int_write(struct bnx2x_softc *sc, int gpio_num, uint32_t mode,
> -		   uint8_t port)
> +		      uint8_t port)

If port storage type will not change, no need to update this line. It is
good to fix syntax the lines touched, but for the lines not updated
please don't fix the syntax in this patch.

>  {
>  	/* The GPIO should be swapped if swap register is set and active */
>  	int gpio_port = ((REG_RD(sc, NIG_REG_PORT_SWAP) &&
> @@ -749,7 +749,7 @@ bnx2x_gpio_int_write(struct bnx2x_softc *sc, int gpio_num, uint32_t mode,
>  }
>  
>  uint32_t
> -elink_cb_gpio_read(struct bnx2x_softc * sc, uint16_t gpio_num, uint8_t port)
> +elink_cb_gpio_read(struct bnx2x_softc *sc, uint16_t gpio_num, uint8_t port)

Same here.

>  {
>  	return bnx2x_gpio_read(sc, gpio_num, port);
>  }
> diff --git a/drivers/net/bnx2x/bnx2x_rxtx.h b/drivers/net/bnx2x/bnx2x_rxtx.h
> index 2e38ec26a..48d540476 100644
> --- a/drivers/net/bnx2x/bnx2x_rxtx.h
> +++ b/drivers/net/bnx2x/bnx2x_rxtx.h
> @@ -41,7 +41,7 @@ struct bnx2x_rx_queue {
>  	uint16_t                   rx_cq_head;           /**< Index of current rcq bd. */
>  	uint16_t                   rx_cq_tail;           /**< Index of last rcq bd. */
>  	uint16_t                   queue_id;             /**< RX queue index. */
> -	uint8_t                    port_id;              /**< Device port identifier. */
> +	uint16_t                   port_id;	/**< Device port identifier. */

Please fix comment allignment.

>  	struct bnx2x_softc           *sc;                  /**< Ptr to dev_private data. */
>  };

<...>

> @@ -500,7 +501,7 @@ elink_status_t elink_phy_probe(struct elink_params *params);
>  
>  /* Checks if fan failure detection is required on one of the phys on board */
>  uint8_t elink_fan_failure_det_req(struct bnx2x_softc *sc, uint32_t shmem_base,
> -			     uint32_t shmem2_base, uint8_t port);
> +				  uint32_t shmem2_base, uint8_t port);

no change, please drop.

<...>

> @@ -511,7 +511,6 @@ mux_machine(struct bond_dev_private *internals, uint8_t slave_id)
>  		ACTOR_STATE_CLR(port, SYNCHRONIZATION);
>  		MODE4_DEBUG("Out of sync -> ATTACHED\n");
>  	}
> -

Please drop this one.

<...>
> @@ -1022,12 +1022,12 @@ bond_mode_8023ad_activate_slave(struct rte_eth_dev *bond_dev, uint8_t slave_id)
>  
>  int
>  bond_mode_8023ad_deactivate_slave(struct rte_eth_dev *bond_dev,
> -		uint8_t slave_id)
> +				   uint16_t slave_id)

The coding style for multiple lines in a function call is two tabs or
alternatively allign to the paranthesis. Original code synyax looks good
here, no need to update.

<...>

> @@ -1536,17 +1536,12 @@ rte_eth_bond_8023ad_setup_v1708(uint8_t port_id,
>  	return 0;
>  }
>  BIND_DEFAULT_SYMBOL(rte_eth_bond_8023ad_setup, _v1708, 17.08);
> -MAP_STATIC_SYMBOL(int rte_eth_bond_8023ad_setup(uint8_t port_id,
> +MAP_STATIC_SYMBOL(int rte_eth_bond_8023ad_setup(uint16_t port_id,

Hmm, this is tricky!
The macro MAP_STATIC_SYMBOL is used for ABI versioning, but changing the
port_id storage type breaks the ABI already. ABI versioning can be
removed completely. Cc'ed Declan.

Which also reminds me that bonding LIBABIVER needs to be updated. This
is also required for all i40e, ixgbe and bnxt. Please let me know if you
need help here.

<...>

> @@ -1622,12 +1618,13 @@ rte_eth_bond_8023ad_ext_collect(uint8_t port_id, uint8_t slave_id, int enabled)
>  		ACTOR_STATE_SET(port, COLLECTING);
>  	else
>  		ACTOR_STATE_CLR(port, COLLECTING);
> -
> +	printf("enabled  port->actor_state = %d \r\n",  port->actor_state);

Is this a git rebase error ?

<...>

> @@ -586,13 +588,14 @@ rte_eth_bond_active_slaves_get(uint8_t bonded_port_id, uint8_t slaves[],
>  	if (internals->active_slave_count > len)
>  		return -1;
>  
> -	memcpy(slaves, internals->active_slaves, internals->active_slave_count);
> +	memcpy(slaves, internals->active_slaves,
> +	internals->active_slave_count * sizeof(internals->active_slaves[0]));

Good catch!
I wonder if there are more like this, did you traced all memcpy, memset,
etc..  ?

<...>

> --- a/drivers/net/ixgbe/rte_pmd_ixgbe.c
> +++ b/drivers/net/ixgbe/rte_pmd_ixgbe.c
> @@ -38,7 +38,7 @@
>  #include "rte_pmd_ixgbe.h"
>  
>  int
> -rte_pmd_ixgbe_set_vf_mac_addr(uint8_t port, uint16_t vf,
> +rte_pmd_ixgbe_set_vf_mac_addr(uint16_t port, uint16_t vf,
>  			      struct ether_addr *mac_addr)

ixgbe LIBABIVER also needs to be updated.

I have just recognized that release notes missing this library, I will add.

<...>

> --- a/drivers/net/vmxnet3/vmxnet3_ring.h
> +++ b/drivers/net/vmxnet3/vmxnet3_ring.h
> @@ -143,8 +143,8 @@ typedef struct vmxnet3_tx_queue {
>  	struct vmxnet3_txq_stats     stats;
>  	const struct rte_memzone     *mz;
>  	bool                         stopped;
> -	uint16_t                     queue_id;      /**< Device TX queue index. */
> -	uint8_t                      port_id;       /**< Device port identifier. */
> +	uint16_t                     queue_id; /**< Device TX queue index. */

No need to change "queue_id" here, if this is for comment allignment,
please allign the port_id one.

> +	uint16_t                     port_id;  /**< Device port identifier. */
>  	uint16_t		     txdata_desc_size;
>  } vmxnet3_tx_queue_t;
>  
> @@ -178,8 +178,8 @@ typedef struct vmxnet3_rx_queue {
>  	struct vmxnet3_rxq_stats    stats;
>  	const struct rte_memzone    *mz;
>  	bool                        stopped;
> -	uint16_t                    queue_id;      /**< Device RX queue index. */
> -	uint8_t                     port_id;       /**< Device port identifier. */
> +	uint16_t                    queue_id; /**< Device RX queue index. */

same as above.

<...>

> @@ -94,8 +94,7 @@ rte_port_ethdev_reader_create(void *params, int socket_id)
>  static int
>  rte_port_ethdev_reader_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts)
>  {
> -	struct rte_port_ethdev_reader *p =
> -		port;
> +	struct rte_port_ethdev_reader *p = port;

This is a good syntax correction, but this patch is already big, please
drop these ones.

>  	uint16_t rx_pkt_cnt;
>  
>  	rx_pkt_cnt = rte_eth_rx_burst(p->port_id, p->queue_id, pkts, n_pkts);
> @@ -119,8 +118,7 @@ rte_port_ethdev_reader_free(void *port)
>  static int rte_port_ethdev_reader_stats_read(void *port,
>  		struct rte_port_in_stats *stats, int clear)
>  {
> -	struct rte_port_ethdev_reader *p =
> -			port;
> +	struct rte_port_ethdev_reader *p = port;

same as above, and there are few more below.

<...>

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v3 1/4] ethdev: increase port_id range
  2017-09-11  9:37  3%     ` Adrien Mazarguil
@ 2017-09-11 10:51  0%       ` Yang, Zhiyong
  0 siblings, 0 replies; 200+ results
From: Yang, Zhiyong @ 2017-09-11 10:51 UTC (permalink / raw)
  To: Adrien Mazarguil; +Cc: dev, thomas, Yigit, Ferruh, hemant.agrawal, Hunt, David

Hi, Adrien:
	Thanks for your reviews. Reply inline.

> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Monday, September 11, 2017 5:37 PM
> To: Yang, Zhiyong <zhiyong.yang@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net; Yigit, Ferruh
> <ferruh.yigit@intel.com>; hemant.agrawal@nxp.com; Hunt, David
> <david.hunt@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v3 1/4] ethdev: increase port_id range
> 
> Hi Zhiyong,
> 
> On Sat, Sep 09, 2017 at 10:47:24PM +0800, Zhiyong Yang wrote:
> > Extend port_id definition from uint8_t to uint16_t in lib and drivers
> > data structures, specifically rte_eth_dev_data.
> > Modify the APIs, drivers and app using port_id at the same time.
> >
> > Fix some checkpatch issues from the original code and remove some
> > unnecessary cast operations.
> >
> > Signed-off-by: Zhiyong Yang <zhiyong.yang@intel.com>
> 
> Thanks for the mlx4/mlx5 update, I have some comments, see below.
> 
> By the way, since this commit breaks ABI compatibility for pretty much all public
> functions in librte_ether and a few in other places, remember to update
> rte_ethdev_version.map and other affected .map files accordingly.
> I think this change has to be part of this series.

Thanks a lot for your reminder.
> 
> <snip>
> > diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index
> > c0ade4f1a..fe911c3a7 100644
> > --- a/drivers/net/mlx4/mlx4.h
> > +++ b/drivers/net/mlx4/mlx4.h
> > @@ -334,7 +334,7 @@ struct priv {
> >  	} vlan_filter[MLX4_MAX_VLAN_IDS]; /* VLAN filters table. */
> >  	/* Device properties. */
> >  	uint16_t mtu; /* Configured MTU. */
> > -	uint8_t port; /* Physical port number. */
> > +	uint16_t port; /* Physical port number. */
> >  	unsigned int started:1; /* Device started, flows enabled. */
> >  	unsigned int promisc:1; /* Device in promiscuous mode. */
> >  	unsigned int allmulti:1; /* Device receives all multicast packets.
> > */
> 
> This is a physical port number internal to the device, not DPDK's. Please drop this
> change.

My bad.  Drop it.

> 
> What would need change is struct rxq's port_id field (already large enough) if
> you want to enforce uint16_t everywhere.

Ok.

> 
> > diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index
> > 43c538419..54a2e8a54 100644
> > --- a/drivers/net/mlx5/mlx5.h
> > +++ b/drivers/net/mlx5/mlx5.h
> > @@ -114,7 +114,7 @@ struct priv {
> >  	unsigned int vlan_filter_n; /* Number of configured VLAN filters. */
> >  	/* Device properties. */
> >  	uint16_t mtu; /* Configured MTU. */
> > -	uint8_t port; /* Physical port number. */
> > +	uint16_t port; /* Physical port number. */
> 
> Same comment here.

Drop it.

> 
> >  	unsigned int started:1; /* Device started, flows enabled. */
> >  	unsigned int promisc_req:1; /* Promiscuous mode requested. */
> >  	unsigned int allmulti_req:1; /* All multicast mode requested. */
> > diff --git a/drivers/net/mlx5/mlx5_ethdev.c
> > b/drivers/net/mlx5/mlx5_ethdev.c index b0eb3cdfc..58e7cf571 100644
> > --- a/drivers/net/mlx5/mlx5_ethdev.c
> > +++ b/drivers/net/mlx5/mlx5_ethdev.c
> > @@ -75,7 +75,7 @@ struct ethtool_link_settings {
> >  	uint32_t cmd;
> >  	uint32_t speed;
> >  	uint8_t duplex;
> > -	uint8_t port;
> > +	uint16_t port;
> 
> This is the ethtool interface from the Linux kernel, again this field has to remain
> 8 bits.
> 
> That's the kind of mistakes a dedicated type might have prevented by the way,
> I'm still not convinced that not adding one was the right decision.
> 

Ok. I see.

> >  	uint8_t phy_address;
> >  	uint8_t autoneg;
> >  	uint8_t mdio_support;
> > diff --git a/drivers/net/mlx5/mlx5_rxtx.h
> > b/drivers/net/mlx5/mlx5_rxtx.h index 7de1d1086..c47e54fe0 100644
> > --- a/drivers/net/mlx5/mlx5_rxtx.h
> > +++ b/drivers/net/mlx5/mlx5_rxtx.h
> > @@ -112,7 +112,6 @@ struct rxq {
> >  	unsigned int sges_n:2; /* Log 2 of SGEs (max buffers per packet). */
> >  	unsigned int cqe_n:4; /* Log 2 of CQ elements. */
> >  	unsigned int elts_n:4; /* Log 2 of Mbufs. */
> > -	unsigned int port_id:8;
> >  	unsigned int rss_hash:1; /* RSS hash result is enabled. */
> >  	unsigned int mark:1; /* Marked flow available on the queue. */
> >  	unsigned int pending_err:1; /* CQE error needs to be handled. */ @@
> > -120,6 +119,7 @@ struct rxq {
> >  	unsigned int :6; /* Remaining bits. */
> >  	volatile uint32_t *rq_db;
> >  	volatile uint32_t *cq_db;
> > +	uint16_t port_id;
> >  	uint16_t rq_ci;
> >  	uint16_t rq_pi;
> >  	uint16_t cq_ci;
> 
> This change might have a performance impact. All important fields are found at
> the beginning of this structure for that reason. Since there's not enough room in
> the above bit-field (8 + 6), I guess there's no other choice for now, however you
> should at least update the "Remaining bits" comment.
> 

Ok . Thanks again for your pointing out. Adrien.

Zhiyong 

> <snip>
> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH] doc: announce ABI change for ring structure
@ 2017-09-11 13:39  4% Olivier Matz
  2017-09-18  9:16  4% ` Bruce Richardson
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Olivier Matz @ 2017-09-11 13:39 UTC (permalink / raw)
  To: dev; +Cc: bruce.richardson, john.mcnamara, daniel.verkamp, konstantin.ananyev

As discussed on the mailing list, the alignment constraint of
the ring structure can be relaxed.

Link: http://dpdk.org/dev/patchwork/patch/25039
Link: http://dpdk.org/dev/patchwork/patch/26103

Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
 doc/guides/rel_notes/deprecation.rst | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 3362f3350..5a63c0277 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -120,3 +120,9 @@ Deprecation Notices
   The non-"do-sig" versions of the hash tables will be removed
   (including the ``signature_offset`` parameter)
   and the "do-sig" versions renamed accordingly.
+
+* ring: The alignment constraints on the ring structure will be relaxed
+  to one cache line instead of two, and an empty cache line padding will
+  be added between the producer and consumer structures. The size of the
+  structure and the offset of the fields will remain the same on
+  platforms with 64B cache line, but will change on other platforms.
-- 
2.11.0

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH] net/nfp: remove firmware ABI check
@ 2017-09-11 13:44  4% Alejandro Lucero
  0 siblings, 0 replies; 200+ results
From: Alejandro Lucero @ 2017-09-11 13:44 UTC (permalink / raw)
  To: dev

Link speed is not advertised in old firmwares. However, it is safe
to remove the check because reading NFP_NET_CFG_STS returns 0 in
those cases.

Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
---
 drivers/net/nfp/nfp_net.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index 2c288c2..09854a2 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -988,17 +988,10 @@ enum nfp_qcp_ptr {
 	nn_link_status = (nn_link_status >> NFP_NET_CFG_STS_LINK_RATE_SHIFT) &
 			 NFP_NET_CFG_STS_LINK_RATE_MASK;
 
-	if ((NFD_CFG_MAJOR_VERSION_of(hw->ver) < 4) ||
-	    ((NFD_CFG_MINOR_VERSION_of(hw->ver) == 4) &&
-	    (NFD_CFG_MINOR_VERSION_of(hw->ver) == 0)))
-		/* We really do not know the speed wil old firmware */
+	if (nn_link_status >= RTE_DIM(ls_to_ethtool))
 		link.link_speed = ETH_SPEED_NUM_NONE;
-	else {
-		if (nn_link_status >= RTE_DIM(ls_to_ethtool))
-			link.link_speed = ETH_SPEED_NUM_NONE;
-		else
-			link.link_speed = ls_to_ethtool[nn_link_status];
-	}
+	else
+		link.link_speed = ls_to_ethtool[nn_link_status];
 
 	if (old.link_status != link.link_status) {
 		nfp_net_dev_atomic_write_link_status(dev, &link);
-- 
1.9.1

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v3 0/4] eventdev: add attribute based get APIs
  2017-09-08 15:36  4%   ` [dpdk-dev] [PATCH v3 0/4] eventdev: add attribute based get APIs Harry van Haaren
  2017-09-08 15:36  3%     ` [dpdk-dev] [PATCH v3 4/4] eventdev: add device started attribute Harry van Haaren
@ 2017-09-11 16:16  0%     ` Jerin Jacob
  2017-09-14 16:08  4%     ` [dpdk-dev] [PATCH v4 " Harry van Haaren
  2 siblings, 0 replies; 200+ results
From: Jerin Jacob @ 2017-09-11 16:16 UTC (permalink / raw)
  To: Harry van Haaren; +Cc: dev

-----Original Message-----
> Date: Fri, 8 Sep 2017 16:36:51 +0100
> From: Harry van Haaren <harry.van.haaren@intel.com>
> To: dev@dpdk.org
> CC: jerin.jacob@caviumnetworks.com, Harry van Haaren
>  <harry.van.haaren@intel.com>
> Subject: [PATCH v3 0/4] eventdev: add attribute based get APIs
> X-Mailer: git-send-email 2.7.4
> 
> This patchset refactors the eventdev API to be more flexible
> and capable. In particular, the API is capable of returning an
> error value if an invalid device, port or attribute ID is passed
> in, which was not possible with the previous APIs.
> 
> The implementation of this patchset is based on a v1 patch[1],
> and after some discussion this API was seen as the best solution.
> 
> In terms of flexibility, the attribute id allows addition of new
> common eventdev layer attributes without breaking ABI or adding
> new functions. Note that these attributes are not data-path, and
> that PMDs should continue to use the xstats API for reporting any
> unique PMD statistics that are available.
> 
> Regarding API/ABI compatibility, I have removed the functions from
> the .map files - please review the .map file changes for ABI issues
> carefully.

Please update the LIBABIVER in the Makefile.

Reference:

http://dpdk.org/browse/dpdk/commit/?id=945081a76ab0bb481f1d62125aa5b547fcc000bd

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3 4/4] eventdev: add device started attribute
  2017-09-08 15:36  3%     ` [dpdk-dev] [PATCH v3 4/4] eventdev: add device started attribute Harry van Haaren
@ 2017-09-11 17:52  0%       ` Jerin Jacob
  2017-09-12  8:07  0%         ` Van Haaren, Harry
  0 siblings, 1 reply; 200+ results
From: Jerin Jacob @ 2017-09-11 17:52 UTC (permalink / raw)
  To: Harry van Haaren; +Cc: dev

-----Original Message-----
> Date: Fri, 8 Sep 2017 16:36:55 +0100
> From: Harry van Haaren <harry.van.haaren@intel.com>
> To: dev@dpdk.org
> CC: jerin.jacob@caviumnetworks.com, Harry van Haaren
>  <harry.van.haaren@intel.com>
> Subject: [PATCH v3 4/4] eventdev: add device started attribute
> X-Mailer: git-send-email 2.7.4
> 
> This commit adds an attribute to the eventdev, allowing applications
> to retrieve if the eventdev is running or stopped. Note that no API
> or ABI changes were required in adding the statistic, and code changes
> are minimal.
> 
> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
> ---
>  lib/librte_eventdev/rte_eventdev.c | 3 +++
>  lib/librte_eventdev/rte_eventdev.h | 4 ++++
>  2 files changed, 7 insertions(+)
> 
> diff --git a/lib/librte_eventdev/rte_eventdev.c b/lib/librte_eventdev/rte_eventdev.c
> index 3756ec7..87a1e19 100644
> --- a/lib/librte_eventdev/rte_eventdev.c
> +++ b/lib/librte_eventdev/rte_eventdev.c
> @@ -740,6 +740,9 @@ rte_event_dev_attr_get(uint8_t dev_id, uint32_t attr_id,

I think, the new rte_event_dev_attr_get function, we can move up so that
all device specific functions comes back to back in API documentation.

Check the output of "make doc-api-html"

Other than that, it looks good.

Acked-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] multi-process shared memory on PPC
  2017-08-31 14:40  2% [dpdk-dev] multi-process shared memory on PPC Xueming(Steven) Li
@ 2017-09-12  7:46  0% ` Chao Zhu
  2017-09-12  7:54  0%   ` Xueming(Steven) Li
  2017-09-12  8:01  0% ` Chao Zhu
  1 sibling, 1 reply; 200+ results
From: Chao Zhu @ 2017-09-12  7:46 UTC (permalink / raw)
  To: 'Xueming(Steven) Li'; +Cc: dev

Which version are you using?

> -----Original Message-----
> From: Xueming(Steven) Li [mailto:xuemingl@mellanox.com]
> Sent: 2017年8月31日 22:40
> To: Chao Zhu <chaozhu@linux.vnet.ibm.com>
> Cc: dev@dpdk.org
> Subject: multi-process shared memory on PPC
> 
> Hi all,
> 
> I'm testing multi-process example on PowerPC system, looks like shared
> memory not working properly.
> Below are the error and debug info of the first multi-process example
> 'simple_mp' (works as expected on X86):
> 
> // Build DPDK, master branch
> # make T=ppc_64-power8-linuxapp-gcc -j160 -C
> examples/multi_process/simple_mp/ #
> examples/multi_process/simple_mp/build/simple_mp  -w 0:0.0
> --proc-type=primary -l 1-2 --socket-mem
> 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> APP: Finished Process Init.
> Starting core 2
> simple_mp >
> 
> // Open another terminal and run secondary process # gdb --args
> examples/multi_process/simple_mp/build/simple_mp -n 4 -w 0:0.0
> --proc-type=secondary -l 3-4 --socket-mem
> 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1 Copyright (C) 2016 Free
> Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__gnu.org_licenses_gpl.
h
> tml&d=DwIFAg&c=jf_iaSHvJObTbx-siA1ZOg&r=4TYe4NpqlgVi0ArYpZ76FrWp7IE
> w8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-6aTY_jEvDZtMZR0o&s
> =SbDQBN7qJ9z8fWCSePyvm5FFncp2P_9XZm-qs1lH5PE&e= > This is free
> software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
> and "show warranty" for details.
> This GDB was configured as "powerpc64le-linux-gnu".
> Type "show configuration" for configuration details.
> For bug reporting instructions, please see:
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.gnu.org_softwar
> e_gdb_bugs_&d=DwIFAg&c=jf_iaSHvJObTbx-siA1ZOg&r=4TYe4NpqlgVi0ArYpZ
> 76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-6aTY_jEvDZt
> MZR0o&s=GAFKK3jSahAPFXMGcPGbVNTl0CesJy_qfs5TxXfGOX0&e= >.
> Find the GDB manual and other documentation resources online at:
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.gnu.org_softwar
> e_gdb_documentation_&d=DwIFAg&c=jf_iaSHvJObTbx-siA1ZOg&r=4TYe4Npql
> gVi0ArYpZ76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-6a
> TY_jEvDZtMZR0o&s=JdkMMjGGl-3Z3BGnjCkOFP5lI5BIbRNBxH4EVI70YFc&e= >
> .
> For help, type "help".
> Type "apropos word" to search for commands related to "word"...
> Reading symbols from
> examples/multi_process/simple_mp/build/simple_mp...done.
> (gdb) r
> Starting program:
> /home/xueming/mlnx-dpdk.org/examples/multi_process/simple_mp/build/sim
> ple_mp -n 4 -w 0:0.0 --proc-type=secondary -l 3-4 --socket-mem
> 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> [Thread debugging using libthread_db enabled] Using host libthread_db
library
> "/lib/powerpc64le-linux-gnu/libthread_db.so.1".
> EAL: Detected 144 lcore(s)
> EAL: Probing VFIO support...
> [New Thread 0x7ffff7a6eff0 (LWP 58811)]
> [New Thread 0x7ffff726eff0 (LWP 58812)]
> 
> Thread 1 "simple_mp" received signal SIGSEGV, Segmentation fault.
> 0x00007ffff7d2f3ec in ?? () from /lib/powerpc64le-linux-gnu/libc.so.6
>  (gdb) bt full
> #0  0x00007ffff7d2f3ec in ?? () from /lib/powerpc64le-linux-gnu/libc.so.6
> No symbol table info available.
> #1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28
> "PRI_2_SEC")
>     at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
>         te = 0x7ef3eefd5e00
>         r = 0x0
>         ring_list = 0x7ffff7aa250c
> #2  0x0000000010032640 in main (argc=10, argv=0x7ffffffff3e8)
>     at
> /home/xueming/mlnx-dpdk.org/examples/multi_process/simple_mp/main.c:12
> 8
>         flags = 0
>         ring_size = 64
>         pool_size = 1024
>         pool_cache = 32
>         priv_data_sz = 0
>         ret = 9
>         lcore_id = 32767
>         cl = 0x7ffff7fef718 <_dl_argv>
> (gdb) f 1
> #1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28
> "PRI_2_SEC")
>     at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
> 326                     if (strncmp(name, r->name,
> RTE_RING_NAMESIZE) == 0)
> (gdb) l
> 321
> 322             rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
> 323
> 324             TAILQ_FOREACH(te, ring_list, next) {
> 325                     r = (struct rte_ring *) te->data;
> 326                     if (strncmp(name, r->name,
> RTE_RING_NAMESIZE) == 0)
> 327                             break;
> 328             }
> 329
> 330             rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
> (gdb) p *te
> $1 = {next = {tqe_next = 0x0, tqe_prev = 0x0}, data = 0x0}
> (gdb) p *ring_list
> $2 = {tqh_first = 0x7ef3eefd5e00, tqh_last = 0x7ef3eec6d100}
> 
> # uname -a
> Linux dragon-power-01 4.13.0-rc2 #1 SMP Tue Aug 29 17:27:05 IDT 2017
> ppc64le ppc64le ppc64le GNU/Linux
> 
> # cat /etc/issue
> Ubuntu 16.04.2 LTS \n \l
> 
> # gcc --version
> gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 Copyright (C) 2015
> Free Software Foundation, Inc.
> This is free software; see the source for copying conditions.  There is NO
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
> PURPOSE.
> 
> # lscpu
> Architecture:          ppc64le
> Byte Order:            Little Endian
> CPU(s):                144
> On-line CPU(s) list:   0-87,96-103,112-159
> Thread(s) per core:    8
> Core(s) per socket:    4
> Socket(s):             4
> NUMA node(s):          4
> Model:                 2.1 (pvr 004b 0201)
> Model name:            POWER8E (raw), altivec supported
> CPU max MHz:           3690.0000
> CPU min MHz:           2061.0000
> L1d cache:             64K
> L1i cache:             32K
> L2 cache:              512K
> L3 cache:              8192K
> NUMA node0 CPU(s):     0-39
> NUMA node1 CPU(s):     40-79
> NUMA node16 CPU(s):    80-87,96-103,112-119
> NUMA node17 CPU(s):    120-159
> 
> # cat build/.config
> # RTE_EXEC_ENV values are the directories in mk/exec-env/
> CONFIG_RTE_EXEC_ENV="linuxapp"
> # RTE_ARCH values are architecture we compile for. directories in mk/arch/
> CONFIG_RTE_ARCH="ppc_64"
> # machine can define specific variables or action for a specific board #
> RTE_MACHINE values are architecture we compile for. directories in
> mk/machine/ CONFIG_RTE_MACHINE="power8"
> # The compiler we use.
> # RTE_TOOLCHAIN values are architecture we compile for. directories in
> mk/toolchain/ CONFIG_RTE_TOOLCHAIN="gcc"
> # Use intrinsics or assembly code for key routines
> CONFIG_RTE_FORCE_INTRINSICS=n # Machine forces strict alignment
> constraints.
> CONFIG_RTE_ARCH_STRICT_ALIGN=n
> # Compile to share library
> CONFIG_RTE_BUILD_SHARED_LIB=n
> # Use newest code breaking previous ABI
> CONFIG_RTE_NEXT_ABI=y
> # Major ABI to overwrite library specific LIBABIVER CONFIG_RTE_MAJOR_ABI=
> # Machine's cache line size
> CONFIG_RTE_CACHE_LINE_SIZE=128
> # Compile Environment Abstraction Layer
> CONFIG_RTE_LIBRTE_EAL=y
> CONFIG_RTE_MAX_LCORE=256
> CONFIG_RTE_MAX_NUMA_NODES=32
> CONFIG_RTE_MAX_MEMSEG=256
> CONFIG_RTE_MAX_MEMZONE=2560
> CONFIG_RTE_MAX_TAILQ=32
> CONFIG_RTE_LOG_LEVEL=RTE_LOG_INFO
> CONFIG_RTE_LOG_DP_LEVEL=RTE_LOG_INFO
> CONFIG_RTE_LOG_HISTORY=256
> CONFIG_RTE_BACKTRACE=y
> CONFIG_RTE_LIBEAL_USE_HPET=n
> CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID=n
> CONFIG_RTE_EAL_ALWAYS_PANIC_ON_ERROR=n
> CONFIG_RTE_EAL_IGB_UIO=y
> CONFIG_RTE_EAL_VFIO=y
> CONFIG_RTE_MALLOC_DEBUG=n
> CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES=y
> # Recognize/ignore architecture we compile for. AVX/AVX512 CPU flags for
> performance/power testing.
> # AVX512 is marked as experimental for now, will enable it after enough #
field
> test and possible optimization.
> CONFIG_RTE_ENABLE_AVX=y
> CONFIG_RTE_ENABLE_AVX512=n
> # Default driver path (or "" to disable) CONFIG_RTE_EAL_PMD_PATH=""
> # Compile Environment Abstraction Layer to support Vmware TSC map
> CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=n
> # Compile architecture we compile for. argument parser library
> CONFIG_RTE_LIBRTE_KVARGS=y # Compile generic ethernet library
> CONFIG_RTE_LIBRTE_ETHER=y CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n
> CONFIG_RTE_MAX_ETHPORTS=32
> CONFIG_RTE_MAX_QUEUES_PER_PORT=1024
> CONFIG_RTE_LIBRTE_IEEE1588=n
> CONFIG_RTE_ETHDEV_QUEUE_STAT_CNTRS=16
> CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y
> # Turn off Tx preparation stage
> # Warning: rte_eth_tx_prepare() can be safely disabled only if using a #
driver
> which do not implement any Tx preparation.
> CONFIG_RTE_ETHDEV_TX_PREPARE_NOOP=n
> # Compile burst-oriented Amazon ENA PMD driver
> CONFIG_RTE_LIBRTE_ENA_PMD=y CONFIG_RTE_LIBRTE_ENA_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_ENA_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_ENA_DEBUG_TX_FREE=n
> CONFIG_RTE_LIBRTE_ENA_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_ENA_COM_DEBUG=n
> # Compile burst-oriented IGB & EM PMD drivers
> CONFIG_RTE_LIBRTE_EM_PMD=y CONFIG_RTE_LIBRTE_IGB_PMD=y
> CONFIG_RTE_LIBRTE_E1000_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_E1000_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_E1000_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_E1000_DEBUG_TX_FREE=n
> CONFIG_RTE_LIBRTE_E1000_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_E1000_PF_DISABLE_STRIP_CRC=n
> # Compile burst-oriented IXGBE PMD driver
> CONFIG_RTE_LIBRTE_IXGBE_PMD=n
> CONFIG_RTE_LIBRTE_IXGBE_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_IXGBE_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX_FREE=n
> CONFIG_RTE_LIBRTE_IXGBE_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC=n
> CONFIG_RTE_IXGBE_INC_VECTOR=y
> CONFIG_RTE_LIBRTE_IXGBE_BYPASS=n
> # Compile burst-oriented I40E PMD driver CONFIG_RTE_LIBRTE_I40E_PMD=y
> CONFIG_RTE_LIBRTE_I40E_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_I40E_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_I40E_DEBUG_TX_FREE=n
> CONFIG_RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC=y
> CONFIG_RTE_LIBRTE_I40E_INC_VECTOR=y
> CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n
> CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF=64
> CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF=4
> CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM=4
> # interval up to 8160 us, aligned to 2 (or default value)
> CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL=-1
> # Compile burst-oriented FM10K PMD
> CONFIG_RTE_LIBRTE_FM10K_PMD=n
> CONFIG_RTE_LIBRTE_FM10K_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_FM10K_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX_FREE=n
> CONFIG_RTE_LIBRTE_FM10K_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE=y
> CONFIG_RTE_LIBRTE_FM10K_INC_VECTOR=y
> # Compile burst-oriented Mellanox ConnectX-3 (MLX4) PMD
> CONFIG_RTE_LIBRTE_MLX4_PMD=n CONFIG_RTE_LIBRTE_MLX4_DEBUG=n
> CONFIG_RTE_LIBRTE_MLX4_DEBUG_BROKEN_VERBS=n
> CONFIG_RTE_LIBRTE_MLX4_SGE_WR_N=4
> CONFIG_RTE_LIBRTE_MLX4_MAX_INLINE=0
> CONFIG_RTE_LIBRTE_MLX4_TX_MP_CACHE=8
> CONFIG_RTE_LIBRTE_MLX4_SOFT_COUNTERS=1
> # Compile burst-oriented Mellanox ConnectX-4 & ConnectX-5 (MLX5) PMD
> CONFIG_RTE_LIBRTE_MLX5_PMD=y CONFIG_RTE_LIBRTE_MLX5_DEBUG=n
> CONFIG_RTE_LIBRTE_MLX5_TX_MP_CACHE=8
> # Compile burst-oriented Broadcom PMD driver
> CONFIG_RTE_LIBRTE_BNX2X_PMD=n CONFIG_RTE_LIBRTE_BNX2X_DEBUG=n
> CONFIG_RTE_LIBRTE_BNX2X_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_BNX2X_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_BNX2X_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_BNX2X_MF_SUPPORT=n
> CONFIG_RTE_LIBRTE_BNX2X_DEBUG_PERIODIC=n
> # Compile burst-oriented Chelsio Terminator (CXGBE) PMD
> CONFIG_RTE_LIBRTE_CXGBE_PMD=y CONFIG_RTE_LIBRTE_CXGBE_DEBUG=n
> CONFIG_RTE_LIBRTE_CXGBE_DEBUG_REG=n
> CONFIG_RTE_LIBRTE_CXGBE_DEBUG_MBOX=n
> CONFIG_RTE_LIBRTE_CXGBE_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_CXGBE_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_CXGBE_TPUT=y
> # Compile burst-oriented Cisco ENIC PMD driver
> CONFIG_RTE_LIBRTE_ENIC_PMD=n CONFIG_RTE_LIBRTE_ENIC_DEBUG=n
> CONFIG_RTE_LIBRTE_ENIC_DEBUG_FLOW=n
> # Compile burst-oriented Netronome NFP PMD driver
> CONFIG_RTE_LIBRTE_NFP_PMD=y CONFIG_RTE_LIBRTE_NFP_DEBUG=n #
> Compile burst-oriented Broadcom BNXT PMD driver
> CONFIG_RTE_LIBRTE_BNXT_PMD=y # Compile burst-oriented Solarflare
> libefx-based PMD CONFIG_RTE_LIBRTE_SFC_EFX_PMD=n
> CONFIG_RTE_LIBRTE_SFC_EFX_DEBUG=n # Compile software PMD backed by
> SZEDATA2 device CONFIG_RTE_LIBRTE_PMD_SZEDATA2=n # Defines firmware
> type address space.
> # See documentation for supported values.
> # Other values raise compile time error.
> CONFIG_RTE_LIBRTE_PMD_SZEDATA2_AS=0
> # Compile burst-oriented Cavium Thunderx NICVF PMD driver
> CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD=y
> CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_MBOX=n
> # Compile burst-oriented Cavium LiquidIO PMD driver
> CONFIG_RTE_LIBRTE_LIO_PMD=y
> CONFIG_RTE_LIBRTE_LIO_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_LIO_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_LIO_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_LIO_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_LIO_DEBUG_MBOX=n
> CONFIG_RTE_LIBRTE_LIO_DEBUG_REGS=n
> # Compile NXP DPAA2 FSL-MC Bus
> CONFIG_RTE_LIBRTE_FSLMC_BUS=n
> # Compile Support Libraries for NXP DPAA2
> CONFIG_RTE_LIBRTE_DPAA2_MEMPOOL=n
> CONFIG_RTE_LIBRTE_DPAA2_USE_PHYS_IOVA=y
> # Compile burst-oriented NXP DPAA2 PMD driver
> CONFIG_RTE_LIBRTE_DPAA2_PMD=n
> CONFIG_RTE_LIBRTE_DPAA2_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_DPAA2_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_DPAA2_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX_FREE=n
> # Compile burst-oriented VIRTIO PMD driver
> CONFIG_RTE_LIBRTE_VIRTIO_PMD=y
> CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DUMP=n
> # Compile virtio device emulation inside virtio PMD driver
> CONFIG_RTE_VIRTIO_USER=y # Compile burst-oriented VMXNET3 PMD driver
> CONFIG_RTE_LIBRTE_VMXNET3_PMD=n
> CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX_FREE=n
> CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_DRIVER=n
> # Compile example software rings based PMD
> CONFIG_RTE_LIBRTE_PMD_RING=y
> CONFIG_RTE_PMD_RING_MAX_RX_RINGS=16
> CONFIG_RTE_PMD_RING_MAX_TX_RINGS=16
> # Compile software PMD backed by PCAP files
> CONFIG_RTE_LIBRTE_PMD_PCAP=n # Compile link bonding PMD library
> CONFIG_RTE_LIBRTE_PMD_BOND=y
> CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB=n
> CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB_L1=n
> # QLogic 10G/25G/40G/50G/100G PMD
> CONFIG_RTE_LIBRTE_QEDE_PMD=y
> CONFIG_RTE_LIBRTE_QEDE_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_QEDE_DEBUG_INFO=n
> CONFIG_RTE_LIBRTE_QEDE_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_QEDE_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_QEDE_DEBUG_RX=n
> #Provides abs path/name of architecture we compile for. firmware file.
> #Empty string denotes driver will use default firmware
> CONFIG_RTE_LIBRTE_QEDE_FW=""
> # Compile software PMD backed by AF_PACKET sockets (Linux only)
> CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y # Compile ARK PMD
> CONFIG_RTE_LIBRTE_ARK_PMD=y CONFIG_RTE_LIBRTE_ARK_PAD_TX=y
> CONFIG_RTE_LIBRTE_ARK_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_ARK_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_ARK_DEBUG_STATS=n
> CONFIG_RTE_LIBRTE_ARK_DEBUG_TRACE=n
> # Compile WRS accelerated virtual port (AVP) guest PMD driver
> CONFIG_RTE_LIBRTE_AVP_PMD=n CONFIG_RTE_LIBRTE_AVP_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_AVP_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_AVP_DEBUG_DRIVER=y
> CONFIG_RTE_LIBRTE_AVP_DEBUG_BUFFERS=n
> # Compile architecture we compile for. TAP PMD # It is enabled by default
for
> Linux only.
> CONFIG_RTE_LIBRTE_PMD_TAP=y
> # Compile Xen PMD
> CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
> # Compile null PMD
> CONFIG_RTE_LIBRTE_PMD_NULL=y
> # Compile fail-safe PMD
> CONFIG_RTE_LIBRTE_PMD_FAILSAFE=y
> # Do prefetch of packet data within PMD driver receive function
> CONFIG_RTE_PMD_PACKET_PREFETCH=y # Compile generic crypto device
> library CONFIG_RTE_LIBRTE_CRYPTODEV=y
> CONFIG_RTE_LIBRTE_CRYPTODEV_DEBUG=n
> CONFIG_RTE_CRYPTO_MAX_DEVS=64
> CONFIG_RTE_CRYPTODEV_NAME_LEN=64
> # Compile PMD for ARMv8 Crypto device
> CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO=n
> CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO_DEBUG=n
> # Compile NXP DPAA2 crypto sec driver for CAAM HW
> CONFIG_RTE_LIBRTE_PMD_DPAA2_SEC=n
> CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_RX=n
> # Compile PMD for QuickAssist based devices
> CONFIG_RTE_LIBRTE_PMD_QAT=n
> CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_DRIVER=n
> # Number of sessions to create in architecture we compile for. session
memory
> pool # on a single QuickAssist device.
> CONFIG_RTE_QAT_PMD_MAX_NB_SESSIONS=2048
> # Compile PMD for AESNI backed device
> CONFIG_RTE_LIBRTE_PMD_AESNI_MB=n
> CONFIG_RTE_LIBRTE_PMD_AESNI_MB_DEBUG=n
> # Compile PMD for Software backed device
> CONFIG_RTE_LIBRTE_PMD_OPENSSL=n
> CONFIG_RTE_LIBRTE_PMD_OPENSSL_DEBUG=n
> # Compile PMD for AESNI GCM device
> CONFIG_RTE_LIBRTE_PMD_AESNI_GCM=n
> CONFIG_RTE_LIBRTE_PMD_AESNI_GCM_DEBUG=n
> # Compile PMD for SNOW 3G device
> CONFIG_RTE_LIBRTE_PMD_SNOW3G=n
> CONFIG_RTE_LIBRTE_PMD_SNOW3G_DEBUG=n
> # Compile PMD for KASUMI device
> CONFIG_RTE_LIBRTE_PMD_KASUMI=n
> CONFIG_RTE_LIBRTE_PMD_KASUMI_DEBUG=n
> # Compile PMD for ZUC device
> CONFIG_RTE_LIBRTE_PMD_ZUC=n
> CONFIG_RTE_LIBRTE_PMD_ZUC_DEBUG=n
> # Compile PMD for Crypto Scheduler device
> CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER=y
> CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER_DEBUG=n
> # Compile PMD for NULL Crypto device
> CONFIG_RTE_LIBRTE_PMD_NULL_CRYPTO=y
> # Compile generic event device library
> CONFIG_RTE_LIBRTE_EVENTDEV=y
> CONFIG_RTE_LIBRTE_EVENTDEV_DEBUG=n
> CONFIG_RTE_EVENT_MAX_DEVS=16
> CONFIG_RTE_EVENT_MAX_QUEUES_PER_DEV=64
> # Compile PMD for skeleton event device
> CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV=y
> CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV_DEBUG=n
> # Compile PMD for software event device
> CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV=y
> CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV_DEBUG=n
> # Compile PMD for octeontx sso event device
> CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF=y
> CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF_DEBUG=n
> # Compile librte_ring
> CONFIG_RTE_LIBRTE_RING=y
> # Compile librte_mempool
> CONFIG_RTE_LIBRTE_MEMPOOL=y
> CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE=512
> CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG=n
> # Compile Mempool drivers
> CONFIG_RTE_DRIVER_MEMPOOL_RING=y
> CONFIG_RTE_DRIVER_MEMPOOL_STACK=y
> # Compile librte_mbuf
> CONFIG_RTE_LIBRTE_MBUF=y
> CONFIG_RTE_LIBRTE_MBUF_DEBUG=n
> CONFIG_RTE_MBUF_DEFAULT_MEMPOOL_OPS="ring_mp_mc"
> CONFIG_RTE_MBUF_REFCNT_ATOMIC=y
> CONFIG_RTE_PKTMBUF_HEADROOM=128
> # Compile librte_timer
> CONFIG_RTE_LIBRTE_TIMER=y
> CONFIG_RTE_LIBRTE_TIMER_DEBUG=n
> # Compile librte_cfgfile
> CONFIG_RTE_LIBRTE_CFGFILE=y
> # Compile librte_cmdline
> CONFIG_RTE_LIBRTE_CMDLINE=y
> CONFIG_RTE_LIBRTE_CMDLINE_DEBUG=n
> # Compile librte_hash
> CONFIG_RTE_LIBRTE_HASH=y
> CONFIG_RTE_LIBRTE_HASH_DEBUG=n
> # Compile librte_efd
> CONFIG_RTE_LIBRTE_EFD=y
> # Compile librte_jobstats
> CONFIG_RTE_LIBRTE_JOBSTATS=y
> # Compile architecture we compile for. device metrics library
> CONFIG_RTE_LIBRTE_METRICS=y # Compile architecture we compile for.
> bitrate statistics library CONFIG_RTE_LIBRTE_BITRATE=y # Compile
> architecture we compile for. latency statistics library
> CONFIG_RTE_LIBRTE_LATENCY_STATS=y # Compile librte_lpm
> CONFIG_RTE_LIBRTE_LPM=y CONFIG_RTE_LIBRTE_LPM_DEBUG=n # Compile
> librte_acl CONFIG_RTE_LIBRTE_ACL=y CONFIG_RTE_LIBRTE_ACL_DEBUG=n #
> Compile librte_power CONFIG_RTE_LIBRTE_POWER=y
> CONFIG_RTE_LIBRTE_POWER_DEBUG=n
> CONFIG_RTE_MAX_LCORE_FREQS=64
> # Compile librte_net
> CONFIG_RTE_LIBRTE_NET=y
> # Compile librte_ip_frag
> CONFIG_RTE_LIBRTE_IP_FRAG=y
> CONFIG_RTE_LIBRTE_IP_FRAG_DEBUG=n
> CONFIG_RTE_LIBRTE_IP_FRAG_MAX_FRAG=4
> CONFIG_RTE_LIBRTE_IP_FRAG_TBL_STAT=n
> # Compile GRO library
> CONFIG_RTE_LIBRTE_GRO=y
> # Compile librte_meter
> CONFIG_RTE_LIBRTE_METER=y
> # Compile librte_sched
> CONFIG_RTE_LIBRTE_SCHED=y
> CONFIG_RTE_SCHED_DEBUG=n
> CONFIG_RTE_SCHED_RED=n
> CONFIG_RTE_SCHED_COLLECT_STATS=n
> CONFIG_RTE_SCHED_SUBPORT_TC_OV=n
> CONFIG_RTE_SCHED_PORT_N_GRINDERS=8
> CONFIG_RTE_SCHED_VECTOR=n
> # Compile architecture we compile for. distributor library
> CONFIG_RTE_LIBRTE_DISTRIBUTOR=y # Compile architecture we compile for.
> reorder library CONFIG_RTE_LIBRTE_REORDER=y # Compile librte_port
> CONFIG_RTE_LIBRTE_PORT=y CONFIG_RTE_PORT_STATS_COLLECT=n
> CONFIG_RTE_PORT_PCAP=n # Compile librte_table
> CONFIG_RTE_LIBRTE_TABLE=y CONFIG_RTE_TABLE_STATS_COLLECT=n #
> Compile librte_pipeline CONFIG_RTE_LIBRTE_PIPELINE=y
> CONFIG_RTE_PIPELINE_STATS_COLLECT=n
> # Compile librte_kni
> CONFIG_RTE_LIBRTE_KNI=y
> CONFIG_RTE_LIBRTE_PMD_KNI=y
> CONFIG_RTE_KNI_KMOD=y
> CONFIG_RTE_KNI_KMOD_ETHTOOL=n
> CONFIG_RTE_KNI_PREEMPT_DEFAULT=y
> # Compile architecture we compile for. pdump library
> CONFIG_RTE_LIBRTE_PDUMP=y # Compile vhost user library
> CONFIG_RTE_LIBRTE_VHOST=y CONFIG_RTE_LIBRTE_VHOST_NUMA=y
> CONFIG_RTE_LIBRTE_VHOST_DEBUG=n # Compile vhost PMD # To compile,
> CONFIG_RTE_LIBRTE_VHOST should be enabled.
> CONFIG_RTE_LIBRTE_PMD_VHOST=y
> #Compile Xen domain0 support
> CONFIG_RTE_LIBRTE_XEN_DOM0=n
> # Compile architecture we compile for. test application
> CONFIG_RTE_APP_TEST=y CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
> # Compile architecture we compile for. PMD test application
> CONFIG_RTE_TEST_PMD=y
> CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
> CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
> # Compile architecture we compile for. crypto performance application
> CONFIG_RTE_APP_CRYPTO_PERF=y # Compile architecture we compile for.
> eventdev application CONFIG_RTE_APP_EVENTDEV=y
> CONFIG_RTE_EXEC_ENV_LINUXAPP=y CONFIG_RTE_ARCH_PPC_64=y
> CONFIG_RTE_ARCH_64=y CONFIG_RTE_TOOLCHAIN_GCC=y # Note: Power
> doesn't have this support # Note: Initially, all of architecture we
compile for.
> PMD drivers compilation are turned off on Power # Will turn on them only
after
> architecture we compile for. successful testing on Power
> 
> Please refer here for more information on running DPDK multi-process
> examples:
> 
> https://urldefense.proofpoint.com/v2/url?u=http-3A__dpdk.org_doc_guides_s
> ample-5Fapp-5Fug_multi-5Fprocess.html&d=DwIFAg&c=jf_iaSHvJObTbx-siA1Z
> Og&r=4TYe4NpqlgVi0ArYpZ76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwu
> uryoN7QPg9N-6aTY_jEvDZtMZR0o&s=gupwe5WWQ-ap2jObFko6UJymrcy4jTmF
> 2r1dZ2fQN9E&e=
> 
> Best Regards,
> Xueming

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] multi-process shared memory on PPC
  2017-09-12  7:46  0% ` Chao Zhu
@ 2017-09-12  7:54  0%   ` Xueming(Steven) Li
  0 siblings, 0 replies; 200+ results
From: Xueming(Steven) Li @ 2017-09-12  7:54 UTC (permalink / raw)
  To: Chao Zhu; +Cc: dev

Mater branch from GIT.

> -----Original Message-----
> From: Chao Zhu [mailto:chaozhu@linux.vnet.ibm.com]
> Sent: Tuesday, September 12, 2017 3:47 PM
> To: Xueming(Steven) Li <xuemingl@mellanox.com>
> Cc: dev@dpdk.org
> Subject: RE: multi-process shared memory on PPC
> 
> Which version are you using?
> 
> > -----Original Message-----
> > From: Xueming(Steven) Li [mailto:xuemingl@mellanox.com]
> > Sent: 2017年8月31日 22:40
> > To: Chao Zhu <chaozhu@linux.vnet.ibm.com>
> > Cc: dev@dpdk.org
> > Subject: multi-process shared memory on PPC
> >
> > Hi all,
> >
> > I'm testing multi-process example on PowerPC system, looks like shared
> > memory not working properly.
> > Below are the error and debug info of the first multi-process example
> > 'simple_mp' (works as expected on X86):
> >
> > // Build DPDK, master branch
> > # make T=ppc_64-power8-linuxapp-gcc -j160 -C
> > examples/multi_process/simple_mp/ #
> > examples/multi_process/simple_mp/build/simple_mp  -w 0:0.0
> > --proc-type=primary -l 1-2 --socket-mem
> > 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> > APP: Finished Process Init.
> > Starting core 2
> > simple_mp >
> >
> > // Open another terminal and run secondary process # gdb --args
> > examples/multi_process/simple_mp/build/simple_mp -n 4 -w 0:0.0
> > --proc-type=secondary -l 3-4 --socket-mem
> > 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> > GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1 Copyright (C) 2016 Free
> > Software Foundation, Inc.
> > License GPLv3+: GNU GPL version 3 or later
> >
> <https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Furldef
> ense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> 3A__gnu.org_licenses_gpl&data=02%7C01%7Cxuemingl%40mellanox.com%7C
> 28928b49921642d1062a08d4f9b2a39d%7Ca652971c7d2e4d9ba6a4d149256f46
> 1b%7C0%7C0%7C636407993035002193&sdata=KNxpjaC%2FW0TXQxxr1rS%2B
> 81UOKkC3Wz8NiOi2p3Nidbo%3D&reserved=0.
> h
> > tml&d=DwIFAg&c=jf_iaSHvJObTbx-
> siA1ZOg&r=4TYe4NpqlgVi0ArYpZ76FrWp7IE
> > w8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-6aTY_jEvDZtMZR0o&s
> > =SbDQBN7qJ9z8fWCSePyvm5FFncp2P_9XZm-qs1lH5PE&e= > This is free
> > software: you are free to change and redistribute it.
> > There is NO WARRANTY, to the extent permitted by law.  Type "show
> copying"
> > and "show warranty" for details.
> > This GDB was configured as "powerpc64le-linux-gnu".
> > Type "show configuration" for configuration details.
> > For bug reporting instructions, please see:
> > <https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fur
> > ldefense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> 3A__www.gnu.org_softwar&
> >
> data=02%7C01%7Cxuemingl%40mellanox.com%7C28928b49921642d1062a08d
> 4f9b2a
> >
> 39d%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C63640799303500
> 2193&sd
> >
> ata=UWQCUuBC%2ByrBwUFuwlMHXVHE0Dyp6jujtrpPC%2BD8Is8%3D&reserve
> d=0
> > e_gdb_bugs_&d=DwIFAg&c=jf_iaSHvJObTbx-
> siA1ZOg&r=4TYe4NpqlgVi0ArYpZ
> > 76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-
> 6aTY_jEvDZt
> > MZR0o&s=GAFKK3jSahAPFXMGcPGbVNTl0CesJy_qfs5TxXfGOX0&e= >.
> > Find the GDB manual and other documentation resources online at:
> > <https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fur
> > ldefense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> 3A__www.gnu.org_softwar&
> >
> data=02%7C01%7Cxuemingl%40mellanox.com%7C28928b49921642d1062a08d
> 4f9b2a
> >
> 39d%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C63640799303500
> 2193&sd
> >
> ata=UWQCUuBC%2ByrBwUFuwlMHXVHE0Dyp6jujtrpPC%2BD8Is8%3D&reserve
> d=0
> > e_gdb_documentation_&d=DwIFAg&c=jf_iaSHvJObTbx-
> siA1ZOg&r=4TYe4Npql
> > gVi0ArYpZ76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-
> 6a
> > TY_jEvDZtMZR0o&s=JdkMMjGGl-
> 3Z3BGnjCkOFP5lI5BIbRNBxH4EVI70YFc&e= > .
> > For help, type "help".
> > Type "apropos word" to search for commands related to "word"...
> > Reading symbols from
> > examples/multi_process/simple_mp/build/simple_mp...done.
> > (gdb) r
> > Starting program:
> > /home/xueming/mlnx-
> dpdk.org/examples/multi_process/simple_mp/build/sim
> > ple_mp -n 4 -w 0:0.0 --proc-type=secondary -l 3-4 --socket-mem
> > 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> > [Thread debugging using libthread_db enabled] Using host libthread_db
> library
> > "/lib/powerpc64le-linux-gnu/libthread_db.so.1".
> > EAL: Detected 144 lcore(s)
> > EAL: Probing VFIO support...
> > [New Thread 0x7ffff7a6eff0 (LWP 58811)] [New Thread 0x7ffff726eff0
> > (LWP 58812)]
> >
> > Thread 1 "simple_mp" received signal SIGSEGV, Segmentation fault.
> > 0x00007ffff7d2f3ec in ?? () from /lib/powerpc64le-linux-gnu/libc.so.6
> >  (gdb) bt full
> > #0  0x00007ffff7d2f3ec in ?? () from
> > /lib/powerpc64le-linux-gnu/libc.so.6
> > No symbol table info available.
> > #1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28
> > "PRI_2_SEC")
> >     at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
> >         te = 0x7ef3eefd5e00
> >         r = 0x0
> >         ring_list = 0x7ffff7aa250c
> > #2  0x0000000010032640 in main (argc=10, argv=0x7ffffffff3e8)
> >     at
> > /home/xueming/mlnx-
> dpdk.org/examples/multi_process/simple_mp/main.c:12
> > 8
> >         flags = 0
> >         ring_size = 64
> >         pool_size = 1024
> >         pool_cache = 32
> >         priv_data_sz = 0
> >         ret = 9
> >         lcore_id = 32767
> >         cl = 0x7ffff7fef718 <_dl_argv>
> > (gdb) f 1
> > #1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28
> > "PRI_2_SEC")
> >     at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
> > 326                     if (strncmp(name, r->name,
> > RTE_RING_NAMESIZE) == 0)
> > (gdb) l
> > 321
> > 322             rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
> > 323
> > 324             TAILQ_FOREACH(te, ring_list, next) {
> > 325                     r = (struct rte_ring *) te->data;
> > 326                     if (strncmp(name, r->name,
> > RTE_RING_NAMESIZE) == 0)
> > 327                             break;
> > 328             }
> > 329
> > 330             rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
> > (gdb) p *te
> > $1 = {next = {tqe_next = 0x0, tqe_prev = 0x0}, data = 0x0}
> > (gdb) p *ring_list
> > $2 = {tqh_first = 0x7ef3eefd5e00, tqh_last = 0x7ef3eec6d100}
> >
> > # uname -a
> > Linux dragon-power-01 4.13.0-rc2 #1 SMP Tue Aug 29 17:27:05 IDT 2017
> > ppc64le ppc64le ppc64le GNU/Linux
> >
> > # cat /etc/issue
> > Ubuntu 16.04.2 LTS \n \l
> >
> > # gcc --version
> > gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 Copyright (C)
> > 2015 Free Software Foundation, Inc.
> > This is free software; see the source for copying conditions.  There
> > is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
> > PARTICULAR PURPOSE.
> >
> > # lscpu
> > Architecture:          ppc64le
> > Byte Order:            Little Endian
> > CPU(s):                144
> > On-line CPU(s) list:   0-87,96-103,112-159
> > Thread(s) per core:    8
> > Core(s) per socket:    4
> > Socket(s):             4
> > NUMA node(s):          4
> > Model:                 2.1 (pvr 004b 0201)
> > Model name:            POWER8E (raw), altivec supported
> > CPU max MHz:           3690.0000
> > CPU min MHz:           2061.0000
> > L1d cache:             64K
> > L1i cache:             32K
> > L2 cache:              512K
> > L3 cache:              8192K
> > NUMA node0 CPU(s):     0-39
> > NUMA node1 CPU(s):     40-79
> > NUMA node16 CPU(s):    80-87,96-103,112-119
> > NUMA node17 CPU(s):    120-159
> >
> > # cat build/.config
> > # RTE_EXEC_ENV values are the directories in mk/exec-env/
> > CONFIG_RTE_EXEC_ENV="linuxapp"
> > # RTE_ARCH values are architecture we compile for. directories in
> > mk/arch/ CONFIG_RTE_ARCH="ppc_64"
> > # machine can define specific variables or action for a specific board
> > # RTE_MACHINE values are architecture we compile for. directories in
> > mk/machine/ CONFIG_RTE_MACHINE="power8"
> > # The compiler we use.
> > # RTE_TOOLCHAIN values are architecture we compile for. directories in
> > mk/toolchain/ CONFIG_RTE_TOOLCHAIN="gcc"
> > # Use intrinsics or assembly code for key routines
> > CONFIG_RTE_FORCE_INTRINSICS=n # Machine forces strict alignment
> > constraints.
> > CONFIG_RTE_ARCH_STRICT_ALIGN=n
> > # Compile to share library
> > CONFIG_RTE_BUILD_SHARED_LIB=n
> > # Use newest code breaking previous ABI CONFIG_RTE_NEXT_ABI=y # Major
> > ABI to overwrite library specific LIBABIVER CONFIG_RTE_MAJOR_ABI= #
> > Machine's cache line size
> > CONFIG_RTE_CACHE_LINE_SIZE=128
> > # Compile Environment Abstraction Layer CONFIG_RTE_LIBRTE_EAL=y
> > CONFIG_RTE_MAX_LCORE=256
> > CONFIG_RTE_MAX_NUMA_NODES=32
> > CONFIG_RTE_MAX_MEMSEG=256
> > CONFIG_RTE_MAX_MEMZONE=2560
> > CONFIG_RTE_MAX_TAILQ=32
> > CONFIG_RTE_LOG_LEVEL=RTE_LOG_INFO
> > CONFIG_RTE_LOG_DP_LEVEL=RTE_LOG_INFO
> > CONFIG_RTE_LOG_HISTORY=256
> > CONFIG_RTE_BACKTRACE=y
> > CONFIG_RTE_LIBEAL_USE_HPET=n
> > CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID=n
> > CONFIG_RTE_EAL_ALWAYS_PANIC_ON_ERROR=n
> > CONFIG_RTE_EAL_IGB_UIO=y
> > CONFIG_RTE_EAL_VFIO=y
> > CONFIG_RTE_MALLOC_DEBUG=n
> > CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES=y
> > # Recognize/ignore architecture we compile for. AVX/AVX512 CPU flags
> > for performance/power testing.
> > # AVX512 is marked as experimental for now, will enable it after
> > enough #
> field
> > test and possible optimization.
> > CONFIG_RTE_ENABLE_AVX=y
> > CONFIG_RTE_ENABLE_AVX512=n
> > # Default driver path (or "" to disable) CONFIG_RTE_EAL_PMD_PATH=""
> > # Compile Environment Abstraction Layer to support Vmware TSC map
> > CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=n
> > # Compile architecture we compile for. argument parser library
> > CONFIG_RTE_LIBRTE_KVARGS=y # Compile generic ethernet library
> > CONFIG_RTE_LIBRTE_ETHER=y CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n
> > CONFIG_RTE_MAX_ETHPORTS=32
> > CONFIG_RTE_MAX_QUEUES_PER_PORT=1024
> > CONFIG_RTE_LIBRTE_IEEE1588=n
> > CONFIG_RTE_ETHDEV_QUEUE_STAT_CNTRS=16
> > CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y
> > # Turn off Tx preparation stage
> > # Warning: rte_eth_tx_prepare() can be safely disabled only if using a
> > #
> driver
> > which do not implement any Tx preparation.
> > CONFIG_RTE_ETHDEV_TX_PREPARE_NOOP=n
> > # Compile burst-oriented Amazon ENA PMD driver
> > CONFIG_RTE_LIBRTE_ENA_PMD=y CONFIG_RTE_LIBRTE_ENA_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_ENA_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_ENA_DEBUG_TX_FREE=n
> > CONFIG_RTE_LIBRTE_ENA_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_ENA_COM_DEBUG=n
> > # Compile burst-oriented IGB & EM PMD drivers
> > CONFIG_RTE_LIBRTE_EM_PMD=y CONFIG_RTE_LIBRTE_IGB_PMD=y
> > CONFIG_RTE_LIBRTE_E1000_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_E1000_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_E1000_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_E1000_DEBUG_TX_FREE=n
> > CONFIG_RTE_LIBRTE_E1000_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_E1000_PF_DISABLE_STRIP_CRC=n
> > # Compile burst-oriented IXGBE PMD driver
> > CONFIG_RTE_LIBRTE_IXGBE_PMD=n
> CONFIG_RTE_LIBRTE_IXGBE_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX_FREE=n
> > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC=n
> > CONFIG_RTE_IXGBE_INC_VECTOR=y
> > CONFIG_RTE_LIBRTE_IXGBE_BYPASS=n
> > # Compile burst-oriented I40E PMD driver CONFIG_RTE_LIBRTE_I40E_PMD=y
> > CONFIG_RTE_LIBRTE_I40E_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_I40E_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_I40E_DEBUG_TX_FREE=n
> > CONFIG_RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC=y
> > CONFIG_RTE_LIBRTE_I40E_INC_VECTOR=y
> > CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n
> > CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF=64
> > CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF=4
> > CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM=4
> > # interval up to 8160 us, aligned to 2 (or default value)
> > CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL=-1
> > # Compile burst-oriented FM10K PMD
> > CONFIG_RTE_LIBRTE_FM10K_PMD=n
> > CONFIG_RTE_LIBRTE_FM10K_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_FM10K_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX_FREE=n
> > CONFIG_RTE_LIBRTE_FM10K_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE=y
> > CONFIG_RTE_LIBRTE_FM10K_INC_VECTOR=y
> > # Compile burst-oriented Mellanox ConnectX-3 (MLX4) PMD
> > CONFIG_RTE_LIBRTE_MLX4_PMD=n CONFIG_RTE_LIBRTE_MLX4_DEBUG=n
> > CONFIG_RTE_LIBRTE_MLX4_DEBUG_BROKEN_VERBS=n
> > CONFIG_RTE_LIBRTE_MLX4_SGE_WR_N=4
> > CONFIG_RTE_LIBRTE_MLX4_MAX_INLINE=0
> > CONFIG_RTE_LIBRTE_MLX4_TX_MP_CACHE=8
> > CONFIG_RTE_LIBRTE_MLX4_SOFT_COUNTERS=1
> > # Compile burst-oriented Mellanox ConnectX-4 & ConnectX-5 (MLX5) PMD
> > CONFIG_RTE_LIBRTE_MLX5_PMD=y CONFIG_RTE_LIBRTE_MLX5_DEBUG=n
> > CONFIG_RTE_LIBRTE_MLX5_TX_MP_CACHE=8
> > # Compile burst-oriented Broadcom PMD driver
> > CONFIG_RTE_LIBRTE_BNX2X_PMD=n CONFIG_RTE_LIBRTE_BNX2X_DEBUG=n
> > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_BNX2X_MF_SUPPORT=n
> > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_PERIODIC=n
> > # Compile burst-oriented Chelsio Terminator (CXGBE) PMD
> > CONFIG_RTE_LIBRTE_CXGBE_PMD=y
> CONFIG_RTE_LIBRTE_CXGBE_DEBUG=n
> > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_REG=n
> > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_MBOX=n
> > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_CXGBE_TPUT=y
> > # Compile burst-oriented Cisco ENIC PMD driver
> > CONFIG_RTE_LIBRTE_ENIC_PMD=n CONFIG_RTE_LIBRTE_ENIC_DEBUG=n
> > CONFIG_RTE_LIBRTE_ENIC_DEBUG_FLOW=n
> > # Compile burst-oriented Netronome NFP PMD driver
> > CONFIG_RTE_LIBRTE_NFP_PMD=y CONFIG_RTE_LIBRTE_NFP_DEBUG=n #
> Compile
> > burst-oriented Broadcom BNXT PMD driver
> CONFIG_RTE_LIBRTE_BNXT_PMD=y #
> > Compile burst-oriented Solarflare libefx-based PMD
> > CONFIG_RTE_LIBRTE_SFC_EFX_PMD=n
> CONFIG_RTE_LIBRTE_SFC_EFX_DEBUG=n #
> > Compile software PMD backed by
> > SZEDATA2 device CONFIG_RTE_LIBRTE_PMD_SZEDATA2=n # Defines
> firmware
> > type address space.
> > # See documentation for supported values.
> > # Other values raise compile time error.
> > CONFIG_RTE_LIBRTE_PMD_SZEDATA2_AS=0
> > # Compile burst-oriented Cavium Thunderx NICVF PMD driver
> > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD=y
> > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_MBOX=n
> > # Compile burst-oriented Cavium LiquidIO PMD driver
> > CONFIG_RTE_LIBRTE_LIO_PMD=y
> CONFIG_RTE_LIBRTE_LIO_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_LIO_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_LIO_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_LIO_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_LIO_DEBUG_MBOX=n
> > CONFIG_RTE_LIBRTE_LIO_DEBUG_REGS=n
> > # Compile NXP DPAA2 FSL-MC Bus
> > CONFIG_RTE_LIBRTE_FSLMC_BUS=n
> > # Compile Support Libraries for NXP DPAA2
> > CONFIG_RTE_LIBRTE_DPAA2_MEMPOOL=n
> > CONFIG_RTE_LIBRTE_DPAA2_USE_PHYS_IOVA=y
> > # Compile burst-oriented NXP DPAA2 PMD driver
> > CONFIG_RTE_LIBRTE_DPAA2_PMD=n
> CONFIG_RTE_LIBRTE_DPAA2_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX_FREE=n
> > # Compile burst-oriented VIRTIO PMD driver
> > CONFIG_RTE_LIBRTE_VIRTIO_PMD=y
> CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DUMP=n
> > # Compile virtio device emulation inside virtio PMD driver
> > CONFIG_RTE_VIRTIO_USER=y # Compile burst-oriented VMXNET3 PMD
> driver
> > CONFIG_RTE_LIBRTE_VMXNET3_PMD=n
> CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX_FREE=n
> > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_DRIVER=n
> > # Compile example software rings based PMD
> > CONFIG_RTE_LIBRTE_PMD_RING=y
> > CONFIG_RTE_PMD_RING_MAX_RX_RINGS=16
> > CONFIG_RTE_PMD_RING_MAX_TX_RINGS=16
> > # Compile software PMD backed by PCAP files
> > CONFIG_RTE_LIBRTE_PMD_PCAP=n # Compile link bonding PMD library
> > CONFIG_RTE_LIBRTE_PMD_BOND=y
> CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB=n
> > CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB_L1=n
> > # QLogic 10G/25G/40G/50G/100G PMD
> > CONFIG_RTE_LIBRTE_QEDE_PMD=y
> > CONFIG_RTE_LIBRTE_QEDE_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_QEDE_DEBUG_INFO=n
> > CONFIG_RTE_LIBRTE_QEDE_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_QEDE_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_QEDE_DEBUG_RX=n
> > #Provides abs path/name of architecture we compile for. firmware file.
> > #Empty string denotes driver will use default firmware
> > CONFIG_RTE_LIBRTE_QEDE_FW=""
> > # Compile software PMD backed by AF_PACKET sockets (Linux only)
> > CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y # Compile ARK PMD
> > CONFIG_RTE_LIBRTE_ARK_PMD=y CONFIG_RTE_LIBRTE_ARK_PAD_TX=y
> > CONFIG_RTE_LIBRTE_ARK_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_ARK_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_ARK_DEBUG_STATS=n
> > CONFIG_RTE_LIBRTE_ARK_DEBUG_TRACE=n
> > # Compile WRS accelerated virtual port (AVP) guest PMD driver
> > CONFIG_RTE_LIBRTE_AVP_PMD=n CONFIG_RTE_LIBRTE_AVP_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_AVP_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_AVP_DEBUG_DRIVER=y
> > CONFIG_RTE_LIBRTE_AVP_DEBUG_BUFFERS=n
> > # Compile architecture we compile for. TAP PMD # It is enabled by
> > default
> for
> > Linux only.
> > CONFIG_RTE_LIBRTE_PMD_TAP=y
> > # Compile Xen PMD
> > CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
> > # Compile null PMD
> > CONFIG_RTE_LIBRTE_PMD_NULL=y
> > # Compile fail-safe PMD
> > CONFIG_RTE_LIBRTE_PMD_FAILSAFE=y
> > # Do prefetch of packet data within PMD driver receive function
> > CONFIG_RTE_PMD_PACKET_PREFETCH=y # Compile generic crypto device
> > library CONFIG_RTE_LIBRTE_CRYPTODEV=y
> > CONFIG_RTE_LIBRTE_CRYPTODEV_DEBUG=n
> > CONFIG_RTE_CRYPTO_MAX_DEVS=64
> > CONFIG_RTE_CRYPTODEV_NAME_LEN=64
> > # Compile PMD for ARMv8 Crypto device
> > CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO=n
> > CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO_DEBUG=n
> > # Compile NXP DPAA2 crypto sec driver for CAAM HW
> > CONFIG_RTE_LIBRTE_PMD_DPAA2_SEC=n
> > CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_RX=n
> > # Compile PMD for QuickAssist based devices
> > CONFIG_RTE_LIBRTE_PMD_QAT=n
> CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_DRIVER=n
> > # Number of sessions to create in architecture we compile for. session
> memory
> > pool # on a single QuickAssist device.
> > CONFIG_RTE_QAT_PMD_MAX_NB_SESSIONS=2048
> > # Compile PMD for AESNI backed device
> > CONFIG_RTE_LIBRTE_PMD_AESNI_MB=n
> > CONFIG_RTE_LIBRTE_PMD_AESNI_MB_DEBUG=n
> > # Compile PMD for Software backed device
> > CONFIG_RTE_LIBRTE_PMD_OPENSSL=n
> CONFIG_RTE_LIBRTE_PMD_OPENSSL_DEBUG=n
> > # Compile PMD for AESNI GCM device
> > CONFIG_RTE_LIBRTE_PMD_AESNI_GCM=n
> > CONFIG_RTE_LIBRTE_PMD_AESNI_GCM_DEBUG=n
> > # Compile PMD for SNOW 3G device
> > CONFIG_RTE_LIBRTE_PMD_SNOW3G=n
> > CONFIG_RTE_LIBRTE_PMD_SNOW3G_DEBUG=n
> > # Compile PMD for KASUMI device
> > CONFIG_RTE_LIBRTE_PMD_KASUMI=n
> > CONFIG_RTE_LIBRTE_PMD_KASUMI_DEBUG=n
> > # Compile PMD for ZUC device
> > CONFIG_RTE_LIBRTE_PMD_ZUC=n
> > CONFIG_RTE_LIBRTE_PMD_ZUC_DEBUG=n
> > # Compile PMD for Crypto Scheduler device
> > CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER=y
> > CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER_DEBUG=n
> > # Compile PMD for NULL Crypto device
> > CONFIG_RTE_LIBRTE_PMD_NULL_CRYPTO=y
> > # Compile generic event device library CONFIG_RTE_LIBRTE_EVENTDEV=y
> > CONFIG_RTE_LIBRTE_EVENTDEV_DEBUG=n
> > CONFIG_RTE_EVENT_MAX_DEVS=16
> > CONFIG_RTE_EVENT_MAX_QUEUES_PER_DEV=64
> > # Compile PMD for skeleton event device
> > CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV=y
> > CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV_DEBUG=n
> > # Compile PMD for software event device
> > CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV=y
> > CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV_DEBUG=n
> > # Compile PMD for octeontx sso event device
> > CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF=y
> > CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF_DEBUG=n
> > # Compile librte_ring
> > CONFIG_RTE_LIBRTE_RING=y
> > # Compile librte_mempool
> > CONFIG_RTE_LIBRTE_MEMPOOL=y
> > CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE=512
> > CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG=n
> > # Compile Mempool drivers
> > CONFIG_RTE_DRIVER_MEMPOOL_RING=y
> > CONFIG_RTE_DRIVER_MEMPOOL_STACK=y
> > # Compile librte_mbuf
> > CONFIG_RTE_LIBRTE_MBUF=y
> > CONFIG_RTE_LIBRTE_MBUF_DEBUG=n
> > CONFIG_RTE_MBUF_DEFAULT_MEMPOOL_OPS="ring_mp_mc"
> > CONFIG_RTE_MBUF_REFCNT_ATOMIC=y
> > CONFIG_RTE_PKTMBUF_HEADROOM=128
> > # Compile librte_timer
> > CONFIG_RTE_LIBRTE_TIMER=y
> > CONFIG_RTE_LIBRTE_TIMER_DEBUG=n
> > # Compile librte_cfgfile
> > CONFIG_RTE_LIBRTE_CFGFILE=y
> > # Compile librte_cmdline
> > CONFIG_RTE_LIBRTE_CMDLINE=y
> > CONFIG_RTE_LIBRTE_CMDLINE_DEBUG=n
> > # Compile librte_hash
> > CONFIG_RTE_LIBRTE_HASH=y
> > CONFIG_RTE_LIBRTE_HASH_DEBUG=n
> > # Compile librte_efd
> > CONFIG_RTE_LIBRTE_EFD=y
> > # Compile librte_jobstats
> > CONFIG_RTE_LIBRTE_JOBSTATS=y
> > # Compile architecture we compile for. device metrics library
> > CONFIG_RTE_LIBRTE_METRICS=y # Compile architecture we compile for.
> > bitrate statistics library CONFIG_RTE_LIBRTE_BITRATE=y # Compile
> > architecture we compile for. latency statistics library
> > CONFIG_RTE_LIBRTE_LATENCY_STATS=y # Compile librte_lpm
> > CONFIG_RTE_LIBRTE_LPM=y CONFIG_RTE_LIBRTE_LPM_DEBUG=n #
> Compile
> > librte_acl CONFIG_RTE_LIBRTE_ACL=y CONFIG_RTE_LIBRTE_ACL_DEBUG=n
> #
> > Compile librte_power CONFIG_RTE_LIBRTE_POWER=y
> > CONFIG_RTE_LIBRTE_POWER_DEBUG=n
> > CONFIG_RTE_MAX_LCORE_FREQS=64
> > # Compile librte_net
> > CONFIG_RTE_LIBRTE_NET=y
> > # Compile librte_ip_frag
> > CONFIG_RTE_LIBRTE_IP_FRAG=y
> > CONFIG_RTE_LIBRTE_IP_FRAG_DEBUG=n
> > CONFIG_RTE_LIBRTE_IP_FRAG_MAX_FRAG=4
> > CONFIG_RTE_LIBRTE_IP_FRAG_TBL_STAT=n
> > # Compile GRO library
> > CONFIG_RTE_LIBRTE_GRO=y
> > # Compile librte_meter
> > CONFIG_RTE_LIBRTE_METER=y
> > # Compile librte_sched
> > CONFIG_RTE_LIBRTE_SCHED=y
> > CONFIG_RTE_SCHED_DEBUG=n
> > CONFIG_RTE_SCHED_RED=n
> > CONFIG_RTE_SCHED_COLLECT_STATS=n
> > CONFIG_RTE_SCHED_SUBPORT_TC_OV=n
> > CONFIG_RTE_SCHED_PORT_N_GRINDERS=8
> > CONFIG_RTE_SCHED_VECTOR=n
> > # Compile architecture we compile for. distributor library
> > CONFIG_RTE_LIBRTE_DISTRIBUTOR=y # Compile architecture we compile for.
> > reorder library CONFIG_RTE_LIBRTE_REORDER=y # Compile librte_port
> > CONFIG_RTE_LIBRTE_PORT=y CONFIG_RTE_PORT_STATS_COLLECT=n
> > CONFIG_RTE_PORT_PCAP=n # Compile librte_table
> > CONFIG_RTE_LIBRTE_TABLE=y CONFIG_RTE_TABLE_STATS_COLLECT=n #
> Compile
> > librte_pipeline CONFIG_RTE_LIBRTE_PIPELINE=y
> > CONFIG_RTE_PIPELINE_STATS_COLLECT=n
> > # Compile librte_kni
> > CONFIG_RTE_LIBRTE_KNI=y
> > CONFIG_RTE_LIBRTE_PMD_KNI=y
> > CONFIG_RTE_KNI_KMOD=y
> > CONFIG_RTE_KNI_KMOD_ETHTOOL=n
> > CONFIG_RTE_KNI_PREEMPT_DEFAULT=y
> > # Compile architecture we compile for. pdump library
> > CONFIG_RTE_LIBRTE_PDUMP=y # Compile vhost user library
> > CONFIG_RTE_LIBRTE_VHOST=y CONFIG_RTE_LIBRTE_VHOST_NUMA=y
> > CONFIG_RTE_LIBRTE_VHOST_DEBUG=n # Compile vhost PMD # To compile,
> > CONFIG_RTE_LIBRTE_VHOST should be enabled.
> > CONFIG_RTE_LIBRTE_PMD_VHOST=y
> > #Compile Xen domain0 support
> > CONFIG_RTE_LIBRTE_XEN_DOM0=n
> > # Compile architecture we compile for. test application
> > CONFIG_RTE_APP_TEST=y CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
> > # Compile architecture we compile for. PMD test application
> > CONFIG_RTE_TEST_PMD=y
> CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
> > CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
> > # Compile architecture we compile for. crypto performance application
> > CONFIG_RTE_APP_CRYPTO_PERF=y # Compile architecture we compile for.
> > eventdev application CONFIG_RTE_APP_EVENTDEV=y
> > CONFIG_RTE_EXEC_ENV_LINUXAPP=y CONFIG_RTE_ARCH_PPC_64=y
> > CONFIG_RTE_ARCH_64=y CONFIG_RTE_TOOLCHAIN_GCC=y # Note: Power
> doesn't
> > have this support # Note: Initially, all of architecture we
> compile for.
> > PMD drivers compilation are turned off on Power # Will turn on them
> > only
> after
> > architecture we compile for. successful testing on Power
> >
> > Please refer here for more information on running DPDK multi-process
> > examples:
> >
> > https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Furl
> > defense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> 3A__dpdk.org_doc_guides_s
> >
> &data=02%7C01%7Cxuemingl%40mellanox.com%7C28928b49921642d1062a08
> d4f9b2
> >
> a39d%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C6364079930350
> 02193&s
> >
> data=y%2F1xdeUMskuPRIm6sx%2F4Xp6QXmAApyCilhd4kWFHN14%3D&reserve
> d=0
> > ample-5Fapp-5Fug_multi-5Fprocess.html&d=DwIFAg&c=jf_iaSHvJObTbx-
> siA1Z
> >
> Og&r=4TYe4NpqlgVi0ArYpZ76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwu
> > uryoN7QPg9N-6aTY_jEvDZtMZR0o&s=gupwe5WWQ-
> ap2jObFko6UJymrcy4jTmF
> > 2r1dZ2fQN9E&e=
> >
> > Best Regards,
> > Xueming
> 


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] multi-process shared memory on PPC
  2017-08-31 14:40  2% [dpdk-dev] multi-process shared memory on PPC Xueming(Steven) Li
  2017-09-12  7:46  0% ` Chao Zhu
@ 2017-09-12  8:01  0% ` Chao Zhu
  2017-09-12  8:12  0%   ` Xueming(Steven) Li
  1 sibling, 1 reply; 200+ results
From: Chao Zhu @ 2017-09-12  8:01 UTC (permalink / raw)
  To: 'Xueming(Steven) Li'; +Cc: dev

Xueming,

I tried it on my local server, it works fine.
Did you set this value
"/sys/kernel/mm/hugepages/hugepages-16384kB/nr_overcommit_hugepages" ?
It should be the same value as "
/sys/kernel/mm/hugepages/hugepages-16384kB/nr_hugepages" on ppc64le.

> -----Original Message-----
> From: Xueming(Steven) Li [mailto:xuemingl@mellanox.com]
> Sent: 2017年8月31日 22:40
> To: Chao Zhu <chaozhu@linux.vnet.ibm.com>
> Cc: dev@dpdk.org
> Subject: multi-process shared memory on PPC
> 
> Hi all,
> 
> I'm testing multi-process example on PowerPC system, looks like shared
> memory not working properly.
> Below are the error and debug info of the first multi-process example
> 'simple_mp' (works as expected on X86):
> 
> // Build DPDK, master branch
> # make T=ppc_64-power8-linuxapp-gcc -j160 -C
> examples/multi_process/simple_mp/ #
> examples/multi_process/simple_mp/build/simple_mp  -w 0:0.0
> --proc-type=primary -l 1-2 --socket-mem
> 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> APP: Finished Process Init.
> Starting core 2
> simple_mp >
> 
> // Open another terminal and run secondary process # gdb --args
> examples/multi_process/simple_mp/build/simple_mp -n 4 -w 0:0.0
> --proc-type=secondary -l 3-4 --socket-mem
> 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1 Copyright (C) 2016 Free
> Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__gnu.org_licenses_gpl.
h
> tml&d=DwIFAg&c=jf_iaSHvJObTbx-siA1ZOg&r=4TYe4NpqlgVi0ArYpZ76FrWp7IE
> w8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-6aTY_jEvDZtMZR0o&s
> =SbDQBN7qJ9z8fWCSePyvm5FFncp2P_9XZm-qs1lH5PE&e= > This is free
> software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
> and "show warranty" for details.
> This GDB was configured as "powerpc64le-linux-gnu".
> Type "show configuration" for configuration details.
> For bug reporting instructions, please see:
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.gnu.org_softwar
> e_gdb_bugs_&d=DwIFAg&c=jf_iaSHvJObTbx-siA1ZOg&r=4TYe4NpqlgVi0ArYpZ
> 76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-6aTY_jEvDZt
> MZR0o&s=GAFKK3jSahAPFXMGcPGbVNTl0CesJy_qfs5TxXfGOX0&e= >.
> Find the GDB manual and other documentation resources online at:
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.gnu.org_softwar
> e_gdb_documentation_&d=DwIFAg&c=jf_iaSHvJObTbx-siA1ZOg&r=4TYe4Npql
> gVi0ArYpZ76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-6a
> TY_jEvDZtMZR0o&s=JdkMMjGGl-3Z3BGnjCkOFP5lI5BIbRNBxH4EVI70YFc&e= >
> .
> For help, type "help".
> Type "apropos word" to search for commands related to "word"...
> Reading symbols from
> examples/multi_process/simple_mp/build/simple_mp...done.
> (gdb) r
> Starting program:
> /home/xueming/mlnx-dpdk.org/examples/multi_process/simple_mp/build/sim
> ple_mp -n 4 -w 0:0.0 --proc-type=secondary -l 3-4 --socket-mem
> 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> [Thread debugging using libthread_db enabled] Using host libthread_db
library
> "/lib/powerpc64le-linux-gnu/libthread_db.so.1".
> EAL: Detected 144 lcore(s)
> EAL: Probing VFIO support...
> [New Thread 0x7ffff7a6eff0 (LWP 58811)]
> [New Thread 0x7ffff726eff0 (LWP 58812)]
> 
> Thread 1 "simple_mp" received signal SIGSEGV, Segmentation fault.
> 0x00007ffff7d2f3ec in ?? () from /lib/powerpc64le-linux-gnu/libc.so.6
>  (gdb) bt full
> #0  0x00007ffff7d2f3ec in ?? () from /lib/powerpc64le-linux-gnu/libc.so.6
> No symbol table info available.
> #1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28
> "PRI_2_SEC")
>     at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
>         te = 0x7ef3eefd5e00
>         r = 0x0
>         ring_list = 0x7ffff7aa250c
> #2  0x0000000010032640 in main (argc=10, argv=0x7ffffffff3e8)
>     at
> /home/xueming/mlnx-dpdk.org/examples/multi_process/simple_mp/main.c:12
> 8
>         flags = 0
>         ring_size = 64
>         pool_size = 1024
>         pool_cache = 32
>         priv_data_sz = 0
>         ret = 9
>         lcore_id = 32767
>         cl = 0x7ffff7fef718 <_dl_argv>
> (gdb) f 1
> #1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28
> "PRI_2_SEC")
>     at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
> 326                     if (strncmp(name, r->name,
> RTE_RING_NAMESIZE) == 0)
> (gdb) l
> 321
> 322             rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
> 323
> 324             TAILQ_FOREACH(te, ring_list, next) {
> 325                     r = (struct rte_ring *) te->data;
> 326                     if (strncmp(name, r->name,
> RTE_RING_NAMESIZE) == 0)
> 327                             break;
> 328             }
> 329
> 330             rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
> (gdb) p *te
> $1 = {next = {tqe_next = 0x0, tqe_prev = 0x0}, data = 0x0}
> (gdb) p *ring_list
> $2 = {tqh_first = 0x7ef3eefd5e00, tqh_last = 0x7ef3eec6d100}
> 
> # uname -a
> Linux dragon-power-01 4.13.0-rc2 #1 SMP Tue Aug 29 17:27:05 IDT 2017
> ppc64le ppc64le ppc64le GNU/Linux
> 
> # cat /etc/issue
> Ubuntu 16.04.2 LTS \n \l
> 
> # gcc --version
> gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 Copyright (C) 2015
> Free Software Foundation, Inc.
> This is free software; see the source for copying conditions.  There is NO
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
> PURPOSE.
> 
> # lscpu
> Architecture:          ppc64le
> Byte Order:            Little Endian
> CPU(s):                144
> On-line CPU(s) list:   0-87,96-103,112-159
> Thread(s) per core:    8
> Core(s) per socket:    4
> Socket(s):             4
> NUMA node(s):          4
> Model:                 2.1 (pvr 004b 0201)
> Model name:            POWER8E (raw), altivec supported
> CPU max MHz:           3690.0000
> CPU min MHz:           2061.0000
> L1d cache:             64K
> L1i cache:             32K
> L2 cache:              512K
> L3 cache:              8192K
> NUMA node0 CPU(s):     0-39
> NUMA node1 CPU(s):     40-79
> NUMA node16 CPU(s):    80-87,96-103,112-119
> NUMA node17 CPU(s):    120-159
> 
> # cat build/.config
> # RTE_EXEC_ENV values are the directories in mk/exec-env/
> CONFIG_RTE_EXEC_ENV="linuxapp"
> # RTE_ARCH values are architecture we compile for. directories in mk/arch/
> CONFIG_RTE_ARCH="ppc_64"
> # machine can define specific variables or action for a specific board #
> RTE_MACHINE values are architecture we compile for. directories in
> mk/machine/ CONFIG_RTE_MACHINE="power8"
> # The compiler we use.
> # RTE_TOOLCHAIN values are architecture we compile for. directories in
> mk/toolchain/ CONFIG_RTE_TOOLCHAIN="gcc"
> # Use intrinsics or assembly code for key routines
> CONFIG_RTE_FORCE_INTRINSICS=n # Machine forces strict alignment
> constraints.
> CONFIG_RTE_ARCH_STRICT_ALIGN=n
> # Compile to share library
> CONFIG_RTE_BUILD_SHARED_LIB=n
> # Use newest code breaking previous ABI
> CONFIG_RTE_NEXT_ABI=y
> # Major ABI to overwrite library specific LIBABIVER CONFIG_RTE_MAJOR_ABI=
> # Machine's cache line size
> CONFIG_RTE_CACHE_LINE_SIZE=128
> # Compile Environment Abstraction Layer
> CONFIG_RTE_LIBRTE_EAL=y
> CONFIG_RTE_MAX_LCORE=256
> CONFIG_RTE_MAX_NUMA_NODES=32
> CONFIG_RTE_MAX_MEMSEG=256
> CONFIG_RTE_MAX_MEMZONE=2560
> CONFIG_RTE_MAX_TAILQ=32
> CONFIG_RTE_LOG_LEVEL=RTE_LOG_INFO
> CONFIG_RTE_LOG_DP_LEVEL=RTE_LOG_INFO
> CONFIG_RTE_LOG_HISTORY=256
> CONFIG_RTE_BACKTRACE=y
> CONFIG_RTE_LIBEAL_USE_HPET=n
> CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID=n
> CONFIG_RTE_EAL_ALWAYS_PANIC_ON_ERROR=n
> CONFIG_RTE_EAL_IGB_UIO=y
> CONFIG_RTE_EAL_VFIO=y
> CONFIG_RTE_MALLOC_DEBUG=n
> CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES=y
> # Recognize/ignore architecture we compile for. AVX/AVX512 CPU flags for
> performance/power testing.
> # AVX512 is marked as experimental for now, will enable it after enough #
field
> test and possible optimization.
> CONFIG_RTE_ENABLE_AVX=y
> CONFIG_RTE_ENABLE_AVX512=n
> # Default driver path (or "" to disable) CONFIG_RTE_EAL_PMD_PATH=""
> # Compile Environment Abstraction Layer to support Vmware TSC map
> CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=n
> # Compile architecture we compile for. argument parser library
> CONFIG_RTE_LIBRTE_KVARGS=y # Compile generic ethernet library
> CONFIG_RTE_LIBRTE_ETHER=y CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n
> CONFIG_RTE_MAX_ETHPORTS=32
> CONFIG_RTE_MAX_QUEUES_PER_PORT=1024
> CONFIG_RTE_LIBRTE_IEEE1588=n
> CONFIG_RTE_ETHDEV_QUEUE_STAT_CNTRS=16
> CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y
> # Turn off Tx preparation stage
> # Warning: rte_eth_tx_prepare() can be safely disabled only if using a #
driver
> which do not implement any Tx preparation.
> CONFIG_RTE_ETHDEV_TX_PREPARE_NOOP=n
> # Compile burst-oriented Amazon ENA PMD driver
> CONFIG_RTE_LIBRTE_ENA_PMD=y CONFIG_RTE_LIBRTE_ENA_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_ENA_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_ENA_DEBUG_TX_FREE=n
> CONFIG_RTE_LIBRTE_ENA_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_ENA_COM_DEBUG=n
> # Compile burst-oriented IGB & EM PMD drivers
> CONFIG_RTE_LIBRTE_EM_PMD=y CONFIG_RTE_LIBRTE_IGB_PMD=y
> CONFIG_RTE_LIBRTE_E1000_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_E1000_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_E1000_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_E1000_DEBUG_TX_FREE=n
> CONFIG_RTE_LIBRTE_E1000_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_E1000_PF_DISABLE_STRIP_CRC=n
> # Compile burst-oriented IXGBE PMD driver
> CONFIG_RTE_LIBRTE_IXGBE_PMD=n
> CONFIG_RTE_LIBRTE_IXGBE_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_IXGBE_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX_FREE=n
> CONFIG_RTE_LIBRTE_IXGBE_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC=n
> CONFIG_RTE_IXGBE_INC_VECTOR=y
> CONFIG_RTE_LIBRTE_IXGBE_BYPASS=n
> # Compile burst-oriented I40E PMD driver CONFIG_RTE_LIBRTE_I40E_PMD=y
> CONFIG_RTE_LIBRTE_I40E_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_I40E_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_I40E_DEBUG_TX_FREE=n
> CONFIG_RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC=y
> CONFIG_RTE_LIBRTE_I40E_INC_VECTOR=y
> CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n
> CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF=64
> CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF=4
> CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM=4
> # interval up to 8160 us, aligned to 2 (or default value)
> CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL=-1
> # Compile burst-oriented FM10K PMD
> CONFIG_RTE_LIBRTE_FM10K_PMD=n
> CONFIG_RTE_LIBRTE_FM10K_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_FM10K_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX_FREE=n
> CONFIG_RTE_LIBRTE_FM10K_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE=y
> CONFIG_RTE_LIBRTE_FM10K_INC_VECTOR=y
> # Compile burst-oriented Mellanox ConnectX-3 (MLX4) PMD
> CONFIG_RTE_LIBRTE_MLX4_PMD=n CONFIG_RTE_LIBRTE_MLX4_DEBUG=n
> CONFIG_RTE_LIBRTE_MLX4_DEBUG_BROKEN_VERBS=n
> CONFIG_RTE_LIBRTE_MLX4_SGE_WR_N=4
> CONFIG_RTE_LIBRTE_MLX4_MAX_INLINE=0
> CONFIG_RTE_LIBRTE_MLX4_TX_MP_CACHE=8
> CONFIG_RTE_LIBRTE_MLX4_SOFT_COUNTERS=1
> # Compile burst-oriented Mellanox ConnectX-4 & ConnectX-5 (MLX5) PMD
> CONFIG_RTE_LIBRTE_MLX5_PMD=y CONFIG_RTE_LIBRTE_MLX5_DEBUG=n
> CONFIG_RTE_LIBRTE_MLX5_TX_MP_CACHE=8
> # Compile burst-oriented Broadcom PMD driver
> CONFIG_RTE_LIBRTE_BNX2X_PMD=n CONFIG_RTE_LIBRTE_BNX2X_DEBUG=n
> CONFIG_RTE_LIBRTE_BNX2X_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_BNX2X_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_BNX2X_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_BNX2X_MF_SUPPORT=n
> CONFIG_RTE_LIBRTE_BNX2X_DEBUG_PERIODIC=n
> # Compile burst-oriented Chelsio Terminator (CXGBE) PMD
> CONFIG_RTE_LIBRTE_CXGBE_PMD=y CONFIG_RTE_LIBRTE_CXGBE_DEBUG=n
> CONFIG_RTE_LIBRTE_CXGBE_DEBUG_REG=n
> CONFIG_RTE_LIBRTE_CXGBE_DEBUG_MBOX=n
> CONFIG_RTE_LIBRTE_CXGBE_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_CXGBE_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_CXGBE_TPUT=y
> # Compile burst-oriented Cisco ENIC PMD driver
> CONFIG_RTE_LIBRTE_ENIC_PMD=n CONFIG_RTE_LIBRTE_ENIC_DEBUG=n
> CONFIG_RTE_LIBRTE_ENIC_DEBUG_FLOW=n
> # Compile burst-oriented Netronome NFP PMD driver
> CONFIG_RTE_LIBRTE_NFP_PMD=y CONFIG_RTE_LIBRTE_NFP_DEBUG=n #
> Compile burst-oriented Broadcom BNXT PMD driver
> CONFIG_RTE_LIBRTE_BNXT_PMD=y # Compile burst-oriented Solarflare
> libefx-based PMD CONFIG_RTE_LIBRTE_SFC_EFX_PMD=n
> CONFIG_RTE_LIBRTE_SFC_EFX_DEBUG=n # Compile software PMD backed by
> SZEDATA2 device CONFIG_RTE_LIBRTE_PMD_SZEDATA2=n # Defines firmware
> type address space.
> # See documentation for supported values.
> # Other values raise compile time error.
> CONFIG_RTE_LIBRTE_PMD_SZEDATA2_AS=0
> # Compile burst-oriented Cavium Thunderx NICVF PMD driver
> CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD=y
> CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_MBOX=n
> # Compile burst-oriented Cavium LiquidIO PMD driver
> CONFIG_RTE_LIBRTE_LIO_PMD=y
> CONFIG_RTE_LIBRTE_LIO_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_LIO_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_LIO_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_LIO_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_LIO_DEBUG_MBOX=n
> CONFIG_RTE_LIBRTE_LIO_DEBUG_REGS=n
> # Compile NXP DPAA2 FSL-MC Bus
> CONFIG_RTE_LIBRTE_FSLMC_BUS=n
> # Compile Support Libraries for NXP DPAA2
> CONFIG_RTE_LIBRTE_DPAA2_MEMPOOL=n
> CONFIG_RTE_LIBRTE_DPAA2_USE_PHYS_IOVA=y
> # Compile burst-oriented NXP DPAA2 PMD driver
> CONFIG_RTE_LIBRTE_DPAA2_PMD=n
> CONFIG_RTE_LIBRTE_DPAA2_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_DPAA2_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_DPAA2_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX_FREE=n
> # Compile burst-oriented VIRTIO PMD driver
> CONFIG_RTE_LIBRTE_VIRTIO_PMD=y
> CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DUMP=n
> # Compile virtio device emulation inside virtio PMD driver
> CONFIG_RTE_VIRTIO_USER=y # Compile burst-oriented VMXNET3 PMD driver
> CONFIG_RTE_LIBRTE_VMXNET3_PMD=n
> CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX_FREE=n
> CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_DRIVER=n
> # Compile example software rings based PMD
> CONFIG_RTE_LIBRTE_PMD_RING=y
> CONFIG_RTE_PMD_RING_MAX_RX_RINGS=16
> CONFIG_RTE_PMD_RING_MAX_TX_RINGS=16
> # Compile software PMD backed by PCAP files
> CONFIG_RTE_LIBRTE_PMD_PCAP=n # Compile link bonding PMD library
> CONFIG_RTE_LIBRTE_PMD_BOND=y
> CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB=n
> CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB_L1=n
> # QLogic 10G/25G/40G/50G/100G PMD
> CONFIG_RTE_LIBRTE_QEDE_PMD=y
> CONFIG_RTE_LIBRTE_QEDE_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_QEDE_DEBUG_INFO=n
> CONFIG_RTE_LIBRTE_QEDE_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_QEDE_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_QEDE_DEBUG_RX=n
> #Provides abs path/name of architecture we compile for. firmware file.
> #Empty string denotes driver will use default firmware
> CONFIG_RTE_LIBRTE_QEDE_FW=""
> # Compile software PMD backed by AF_PACKET sockets (Linux only)
> CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y # Compile ARK PMD
> CONFIG_RTE_LIBRTE_ARK_PMD=y CONFIG_RTE_LIBRTE_ARK_PAD_TX=y
> CONFIG_RTE_LIBRTE_ARK_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_ARK_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_ARK_DEBUG_STATS=n
> CONFIG_RTE_LIBRTE_ARK_DEBUG_TRACE=n
> # Compile WRS accelerated virtual port (AVP) guest PMD driver
> CONFIG_RTE_LIBRTE_AVP_PMD=n CONFIG_RTE_LIBRTE_AVP_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_AVP_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_AVP_DEBUG_DRIVER=y
> CONFIG_RTE_LIBRTE_AVP_DEBUG_BUFFERS=n
> # Compile architecture we compile for. TAP PMD # It is enabled by default
for
> Linux only.
> CONFIG_RTE_LIBRTE_PMD_TAP=y
> # Compile Xen PMD
> CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
> # Compile null PMD
> CONFIG_RTE_LIBRTE_PMD_NULL=y
> # Compile fail-safe PMD
> CONFIG_RTE_LIBRTE_PMD_FAILSAFE=y
> # Do prefetch of packet data within PMD driver receive function
> CONFIG_RTE_PMD_PACKET_PREFETCH=y # Compile generic crypto device
> library CONFIG_RTE_LIBRTE_CRYPTODEV=y
> CONFIG_RTE_LIBRTE_CRYPTODEV_DEBUG=n
> CONFIG_RTE_CRYPTO_MAX_DEVS=64
> CONFIG_RTE_CRYPTODEV_NAME_LEN=64
> # Compile PMD for ARMv8 Crypto device
> CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO=n
> CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO_DEBUG=n
> # Compile NXP DPAA2 crypto sec driver for CAAM HW
> CONFIG_RTE_LIBRTE_PMD_DPAA2_SEC=n
> CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_DRIVER=n
> CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_RX=n
> # Compile PMD for QuickAssist based devices
> CONFIG_RTE_LIBRTE_PMD_QAT=n
> CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_INIT=n
> CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_DRIVER=n
> # Number of sessions to create in architecture we compile for. session
memory
> pool # on a single QuickAssist device.
> CONFIG_RTE_QAT_PMD_MAX_NB_SESSIONS=2048
> # Compile PMD for AESNI backed device
> CONFIG_RTE_LIBRTE_PMD_AESNI_MB=n
> CONFIG_RTE_LIBRTE_PMD_AESNI_MB_DEBUG=n
> # Compile PMD for Software backed device
> CONFIG_RTE_LIBRTE_PMD_OPENSSL=n
> CONFIG_RTE_LIBRTE_PMD_OPENSSL_DEBUG=n
> # Compile PMD for AESNI GCM device
> CONFIG_RTE_LIBRTE_PMD_AESNI_GCM=n
> CONFIG_RTE_LIBRTE_PMD_AESNI_GCM_DEBUG=n
> # Compile PMD for SNOW 3G device
> CONFIG_RTE_LIBRTE_PMD_SNOW3G=n
> CONFIG_RTE_LIBRTE_PMD_SNOW3G_DEBUG=n
> # Compile PMD for KASUMI device
> CONFIG_RTE_LIBRTE_PMD_KASUMI=n
> CONFIG_RTE_LIBRTE_PMD_KASUMI_DEBUG=n
> # Compile PMD for ZUC device
> CONFIG_RTE_LIBRTE_PMD_ZUC=n
> CONFIG_RTE_LIBRTE_PMD_ZUC_DEBUG=n
> # Compile PMD for Crypto Scheduler device
> CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER=y
> CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER_DEBUG=n
> # Compile PMD for NULL Crypto device
> CONFIG_RTE_LIBRTE_PMD_NULL_CRYPTO=y
> # Compile generic event device library
> CONFIG_RTE_LIBRTE_EVENTDEV=y
> CONFIG_RTE_LIBRTE_EVENTDEV_DEBUG=n
> CONFIG_RTE_EVENT_MAX_DEVS=16
> CONFIG_RTE_EVENT_MAX_QUEUES_PER_DEV=64
> # Compile PMD for skeleton event device
> CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV=y
> CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV_DEBUG=n
> # Compile PMD for software event device
> CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV=y
> CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV_DEBUG=n
> # Compile PMD for octeontx sso event device
> CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF=y
> CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF_DEBUG=n
> # Compile librte_ring
> CONFIG_RTE_LIBRTE_RING=y
> # Compile librte_mempool
> CONFIG_RTE_LIBRTE_MEMPOOL=y
> CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE=512
> CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG=n
> # Compile Mempool drivers
> CONFIG_RTE_DRIVER_MEMPOOL_RING=y
> CONFIG_RTE_DRIVER_MEMPOOL_STACK=y
> # Compile librte_mbuf
> CONFIG_RTE_LIBRTE_MBUF=y
> CONFIG_RTE_LIBRTE_MBUF_DEBUG=n
> CONFIG_RTE_MBUF_DEFAULT_MEMPOOL_OPS="ring_mp_mc"
> CONFIG_RTE_MBUF_REFCNT_ATOMIC=y
> CONFIG_RTE_PKTMBUF_HEADROOM=128
> # Compile librte_timer
> CONFIG_RTE_LIBRTE_TIMER=y
> CONFIG_RTE_LIBRTE_TIMER_DEBUG=n
> # Compile librte_cfgfile
> CONFIG_RTE_LIBRTE_CFGFILE=y
> # Compile librte_cmdline
> CONFIG_RTE_LIBRTE_CMDLINE=y
> CONFIG_RTE_LIBRTE_CMDLINE_DEBUG=n
> # Compile librte_hash
> CONFIG_RTE_LIBRTE_HASH=y
> CONFIG_RTE_LIBRTE_HASH_DEBUG=n
> # Compile librte_efd
> CONFIG_RTE_LIBRTE_EFD=y
> # Compile librte_jobstats
> CONFIG_RTE_LIBRTE_JOBSTATS=y
> # Compile architecture we compile for. device metrics library
> CONFIG_RTE_LIBRTE_METRICS=y # Compile architecture we compile for.
> bitrate statistics library CONFIG_RTE_LIBRTE_BITRATE=y # Compile
> architecture we compile for. latency statistics library
> CONFIG_RTE_LIBRTE_LATENCY_STATS=y # Compile librte_lpm
> CONFIG_RTE_LIBRTE_LPM=y CONFIG_RTE_LIBRTE_LPM_DEBUG=n # Compile
> librte_acl CONFIG_RTE_LIBRTE_ACL=y CONFIG_RTE_LIBRTE_ACL_DEBUG=n #
> Compile librte_power CONFIG_RTE_LIBRTE_POWER=y
> CONFIG_RTE_LIBRTE_POWER_DEBUG=n
> CONFIG_RTE_MAX_LCORE_FREQS=64
> # Compile librte_net
> CONFIG_RTE_LIBRTE_NET=y
> # Compile librte_ip_frag
> CONFIG_RTE_LIBRTE_IP_FRAG=y
> CONFIG_RTE_LIBRTE_IP_FRAG_DEBUG=n
> CONFIG_RTE_LIBRTE_IP_FRAG_MAX_FRAG=4
> CONFIG_RTE_LIBRTE_IP_FRAG_TBL_STAT=n
> # Compile GRO library
> CONFIG_RTE_LIBRTE_GRO=y
> # Compile librte_meter
> CONFIG_RTE_LIBRTE_METER=y
> # Compile librte_sched
> CONFIG_RTE_LIBRTE_SCHED=y
> CONFIG_RTE_SCHED_DEBUG=n
> CONFIG_RTE_SCHED_RED=n
> CONFIG_RTE_SCHED_COLLECT_STATS=n
> CONFIG_RTE_SCHED_SUBPORT_TC_OV=n
> CONFIG_RTE_SCHED_PORT_N_GRINDERS=8
> CONFIG_RTE_SCHED_VECTOR=n
> # Compile architecture we compile for. distributor library
> CONFIG_RTE_LIBRTE_DISTRIBUTOR=y # Compile architecture we compile for.
> reorder library CONFIG_RTE_LIBRTE_REORDER=y # Compile librte_port
> CONFIG_RTE_LIBRTE_PORT=y CONFIG_RTE_PORT_STATS_COLLECT=n
> CONFIG_RTE_PORT_PCAP=n # Compile librte_table
> CONFIG_RTE_LIBRTE_TABLE=y CONFIG_RTE_TABLE_STATS_COLLECT=n #
> Compile librte_pipeline CONFIG_RTE_LIBRTE_PIPELINE=y
> CONFIG_RTE_PIPELINE_STATS_COLLECT=n
> # Compile librte_kni
> CONFIG_RTE_LIBRTE_KNI=y
> CONFIG_RTE_LIBRTE_PMD_KNI=y
> CONFIG_RTE_KNI_KMOD=y
> CONFIG_RTE_KNI_KMOD_ETHTOOL=n
> CONFIG_RTE_KNI_PREEMPT_DEFAULT=y
> # Compile architecture we compile for. pdump library
> CONFIG_RTE_LIBRTE_PDUMP=y # Compile vhost user library
> CONFIG_RTE_LIBRTE_VHOST=y CONFIG_RTE_LIBRTE_VHOST_NUMA=y
> CONFIG_RTE_LIBRTE_VHOST_DEBUG=n # Compile vhost PMD # To compile,
> CONFIG_RTE_LIBRTE_VHOST should be enabled.
> CONFIG_RTE_LIBRTE_PMD_VHOST=y
> #Compile Xen domain0 support
> CONFIG_RTE_LIBRTE_XEN_DOM0=n
> # Compile architecture we compile for. test application
> CONFIG_RTE_APP_TEST=y CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
> # Compile architecture we compile for. PMD test application
> CONFIG_RTE_TEST_PMD=y
> CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
> CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
> # Compile architecture we compile for. crypto performance application
> CONFIG_RTE_APP_CRYPTO_PERF=y # Compile architecture we compile for.
> eventdev application CONFIG_RTE_APP_EVENTDEV=y
> CONFIG_RTE_EXEC_ENV_LINUXAPP=y CONFIG_RTE_ARCH_PPC_64=y
> CONFIG_RTE_ARCH_64=y CONFIG_RTE_TOOLCHAIN_GCC=y # Note: Power
> doesn't have this support # Note: Initially, all of architecture we
compile for.
> PMD drivers compilation are turned off on Power # Will turn on them only
after
> architecture we compile for. successful testing on Power
> 
> Please refer here for more information on running DPDK multi-process
> examples:
> 
> https://urldefense.proofpoint.com/v2/url?u=http-3A__dpdk.org_doc_guides_s
> ample-5Fapp-5Fug_multi-5Fprocess.html&d=DwIFAg&c=jf_iaSHvJObTbx-siA1Z
> Og&r=4TYe4NpqlgVi0ArYpZ76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwu
> uryoN7QPg9N-6aTY_jEvDZtMZR0o&s=gupwe5WWQ-ap2jObFko6UJymrcy4jTmF
> 2r1dZ2fQN9E&e=
> 
> Best Regards,
> Xueming

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3 4/4] eventdev: add device started attribute
  2017-09-11 17:52  0%       ` Jerin Jacob
@ 2017-09-12  8:07  0%         ` Van Haaren, Harry
  0 siblings, 0 replies; 200+ results
From: Van Haaren, Harry @ 2017-09-12  8:07 UTC (permalink / raw)
  To: Jerin Jacob; +Cc: dev

> From: Jerin Jacob [mailto:jerin.jacob@caviumnetworks.com]
> Sent: Monday, September 11, 2017 6:53 PM
> To: Van Haaren, Harry <harry.van.haaren@intel.com>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v3 4/4] eventdev: add device started attribute
> 
> -----Original Message-----
> > Date: Fri, 8 Sep 2017 16:36:55 +0100
> > From: Harry van Haaren <harry.van.haaren@intel.com>
> > To: dev@dpdk.org
> > CC: jerin.jacob@caviumnetworks.com, Harry van Haaren
> >  <harry.van.haaren@intel.com>
> > Subject: [PATCH v3 4/4] eventdev: add device started attribute
> > X-Mailer: git-send-email 2.7.4
> >
> > This commit adds an attribute to the eventdev, allowing applications
> > to retrieve if the eventdev is running or stopped. Note that no API
> > or ABI changes were required in adding the statistic, and code changes
> > are minimal.
> >
> > Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
> > ---
> >  lib/librte_eventdev/rte_eventdev.c | 3 +++
> >  lib/librte_eventdev/rte_eventdev.h | 4 ++++
> >  2 files changed, 7 insertions(+)
> >
> > diff --git a/lib/librte_eventdev/rte_eventdev.c
> b/lib/librte_eventdev/rte_eventdev.c
> > index 3756ec7..87a1e19 100644
> > --- a/lib/librte_eventdev/rte_eventdev.c
> > +++ b/lib/librte_eventdev/rte_eventdev.c
> > @@ -740,6 +740,9 @@ rte_event_dev_attr_get(uint8_t dev_id, uint32_t attr_id,
> 
> I think, the new rte_event_dev_attr_get function, we can move up so that
> all device specific functions comes back to back in API documentation.
> 
> Check the output of "make doc-api-html"
> 
> Other than that, it looks good.
>
> Acked-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>

Thanks for the review - all comments make sense. Will respin with comments addressed, and include Acks.

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] multi-process shared memory on PPC
  2017-09-12  8:01  0% ` Chao Zhu
@ 2017-09-12  8:12  0%   ` Xueming(Steven) Li
  2017-09-12 18:11  0%     ` Xueming(Steven) Li
  0 siblings, 1 reply; 200+ results
From: Xueming(Steven) Li @ 2017-09-12  8:12 UTC (permalink / raw)
  To: Chao Zhu; +Cc: dev

Great, that might be something missing, will update later. Thanks!

> -----Original Message-----
> From: Chao Zhu [mailto:chaozhu@linux.vnet.ibm.com]
> Sent: Tuesday, September 12, 2017 4:02 PM
> To: Xueming(Steven) Li <xuemingl@mellanox.com>
> Cc: dev@dpdk.org
> Subject: RE: multi-process shared memory on PPC
> 
> Xueming,
> 
> I tried it on my local server, it works fine.
> Did you set this value
> "/sys/kernel/mm/hugepages/hugepages-16384kB/nr_overcommit_hugepages" ?
> It should be the same value as "
> /sys/kernel/mm/hugepages/hugepages-16384kB/nr_hugepages" on ppc64le.
> 
> > -----Original Message-----
> > From: Xueming(Steven) Li [mailto:xuemingl@mellanox.com]
> > Sent: 2017年8月31日 22:40
> > To: Chao Zhu <chaozhu@linux.vnet.ibm.com>
> > Cc: dev@dpdk.org
> > Subject: multi-process shared memory on PPC
> >
> > Hi all,
> >
> > I'm testing multi-process example on PowerPC system, looks like shared
> > memory not working properly.
> > Below are the error and debug info of the first multi-process example
> > 'simple_mp' (works as expected on X86):
> >
> > // Build DPDK, master branch
> > # make T=ppc_64-power8-linuxapp-gcc -j160 -C
> > examples/multi_process/simple_mp/ #
> > examples/multi_process/simple_mp/build/simple_mp  -w 0:0.0
> > --proc-type=primary -l 1-2 --socket-mem
> > 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> > APP: Finished Process Init.
> > Starting core 2
> > simple_mp >
> >
> > // Open another terminal and run secondary process # gdb --args
> > examples/multi_process/simple_mp/build/simple_mp -n 4 -w 0:0.0
> > --proc-type=secondary -l 3-4 --socket-mem
> > 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> > GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1 Copyright (C) 2016 Free
> > Software Foundation, Inc.
> > License GPLv3+: GNU GPL version 3 or later
> >
> <https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Furldef
> ense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> 3A__gnu.org_licenses_gpl&data=02%7C01%7Cxuemingl%40mellanox.com%7C
> 9cd11fda7a7f48df7cbd08d4f9b486d8%7Ca652971c7d2e4d9ba6a4d149256f461
> b%7C0%7C0%7C636408001138751301&sdata=bb3hwYz7ehCqt4QA6GGqTDMY
> kY1qAJV%2BCMDBVbXmWzE%3D&reserved=0.
> h
> > tml&d=DwIFAg&c=jf_iaSHvJObTbx-
> siA1ZOg&r=4TYe4NpqlgVi0ArYpZ76FrWp7IE
> > w8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-6aTY_jEvDZtMZR0o&s
> > =SbDQBN7qJ9z8fWCSePyvm5FFncp2P_9XZm-qs1lH5PE&e= > This is free
> > software: you are free to change and redistribute it.
> > There is NO WARRANTY, to the extent permitted by law.  Type "show
> copying"
> > and "show warranty" for details.
> > This GDB was configured as "powerpc64le-linux-gnu".
> > Type "show configuration" for configuration details.
> > For bug reporting instructions, please see:
> > <https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fur
> > ldefense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> 3A__www.gnu.org_softwar&
> >
> data=02%7C01%7Cxuemingl%40mellanox.com%7C9cd11fda7a7f48df7cbd08d4f
> 9b48
> >
> 6d8%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C63640800113875
> 1301&sd
> >
> ata=4DNDTyIcHpTIU60K7FM%2F1zuASSB1IdZDRyOaiVp1Y%2BY%3D&reserved=
> 0
> > e_gdb_bugs_&d=DwIFAg&c=jf_iaSHvJObTbx-
> siA1ZOg&r=4TYe4NpqlgVi0ArYpZ
> > 76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-
> 6aTY_jEvDZt
> > MZR0o&s=GAFKK3jSahAPFXMGcPGbVNTl0CesJy_qfs5TxXfGOX0&e= >.
> > Find the GDB manual and other documentation resources online at:
> > <https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fur
> > ldefense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> 3A__www.gnu.org_softwar&
> >
> data=02%7C01%7Cxuemingl%40mellanox.com%7C9cd11fda7a7f48df7cbd08d4f
> 9b48
> >
> 6d8%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C63640800113875
> 1301&sd
> >
> ata=4DNDTyIcHpTIU60K7FM%2F1zuASSB1IdZDRyOaiVp1Y%2BY%3D&reserved=
> 0
> > e_gdb_documentation_&d=DwIFAg&c=jf_iaSHvJObTbx-
> siA1ZOg&r=4TYe4Npql
> > gVi0ArYpZ76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-
> 6a
> > TY_jEvDZtMZR0o&s=JdkMMjGGl-
> 3Z3BGnjCkOFP5lI5BIbRNBxH4EVI70YFc&e= > .
> > For help, type "help".
> > Type "apropos word" to search for commands related to "word"...
> > Reading symbols from
> > examples/multi_process/simple_mp/build/simple_mp...done.
> > (gdb) r
> > Starting program:
> > /home/xueming/mlnx-
> dpdk.org/examples/multi_process/simple_mp/build/sim
> > ple_mp -n 4 -w 0:0.0 --proc-type=secondary -l 3-4 --socket-mem
> > 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> > [Thread debugging using libthread_db enabled] Using host libthread_db
> library
> > "/lib/powerpc64le-linux-gnu/libthread_db.so.1".
> > EAL: Detected 144 lcore(s)
> > EAL: Probing VFIO support...
> > [New Thread 0x7ffff7a6eff0 (LWP 58811)] [New Thread 0x7ffff726eff0
> > (LWP 58812)]
> >
> > Thread 1 "simple_mp" received signal SIGSEGV, Segmentation fault.
> > 0x00007ffff7d2f3ec in ?? () from /lib/powerpc64le-linux-gnu/libc.so.6
> >  (gdb) bt full
> > #0  0x00007ffff7d2f3ec in ?? () from
> > /lib/powerpc64le-linux-gnu/libc.so.6
> > No symbol table info available.
> > #1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28
> > "PRI_2_SEC")
> >     at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
> >         te = 0x7ef3eefd5e00
> >         r = 0x0
> >         ring_list = 0x7ffff7aa250c
> > #2  0x0000000010032640 in main (argc=10, argv=0x7ffffffff3e8)
> >     at
> > /home/xueming/mlnx-
> dpdk.org/examples/multi_process/simple_mp/main.c:12
> > 8
> >         flags = 0
> >         ring_size = 64
> >         pool_size = 1024
> >         pool_cache = 32
> >         priv_data_sz = 0
> >         ret = 9
> >         lcore_id = 32767
> >         cl = 0x7ffff7fef718 <_dl_argv>
> > (gdb) f 1
> > #1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28
> > "PRI_2_SEC")
> >     at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
> > 326                     if (strncmp(name, r->name,
> > RTE_RING_NAMESIZE) == 0)
> > (gdb) l
> > 321
> > 322             rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
> > 323
> > 324             TAILQ_FOREACH(te, ring_list, next) {
> > 325                     r = (struct rte_ring *) te->data;
> > 326                     if (strncmp(name, r->name,
> > RTE_RING_NAMESIZE) == 0)
> > 327                             break;
> > 328             }
> > 329
> > 330             rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
> > (gdb) p *te
> > $1 = {next = {tqe_next = 0x0, tqe_prev = 0x0}, data = 0x0}
> > (gdb) p *ring_list
> > $2 = {tqh_first = 0x7ef3eefd5e00, tqh_last = 0x7ef3eec6d100}
> >
> > # uname -a
> > Linux dragon-power-01 4.13.0-rc2 #1 SMP Tue Aug 29 17:27:05 IDT 2017
> > ppc64le ppc64le ppc64le GNU/Linux
> >
> > # cat /etc/issue
> > Ubuntu 16.04.2 LTS \n \l
> >
> > # gcc --version
> > gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 Copyright (C)
> > 2015 Free Software Foundation, Inc.
> > This is free software; see the source for copying conditions.  There
> > is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
> > PARTICULAR PURPOSE.
> >
> > # lscpu
> > Architecture:          ppc64le
> > Byte Order:            Little Endian
> > CPU(s):                144
> > On-line CPU(s) list:   0-87,96-103,112-159
> > Thread(s) per core:    8
> > Core(s) per socket:    4
> > Socket(s):             4
> > NUMA node(s):          4
> > Model:                 2.1 (pvr 004b 0201)
> > Model name:            POWER8E (raw), altivec supported
> > CPU max MHz:           3690.0000
> > CPU min MHz:           2061.0000
> > L1d cache:             64K
> > L1i cache:             32K
> > L2 cache:              512K
> > L3 cache:              8192K
> > NUMA node0 CPU(s):     0-39
> > NUMA node1 CPU(s):     40-79
> > NUMA node16 CPU(s):    80-87,96-103,112-119
> > NUMA node17 CPU(s):    120-159
> >
> > # cat build/.config
> > # RTE_EXEC_ENV values are the directories in mk/exec-env/
> > CONFIG_RTE_EXEC_ENV="linuxapp"
> > # RTE_ARCH values are architecture we compile for. directories in
> > mk/arch/ CONFIG_RTE_ARCH="ppc_64"
> > # machine can define specific variables or action for a specific board
> > # RTE_MACHINE values are architecture we compile for. directories in
> > mk/machine/ CONFIG_RTE_MACHINE="power8"
> > # The compiler we use.
> > # RTE_TOOLCHAIN values are architecture we compile for. directories in
> > mk/toolchain/ CONFIG_RTE_TOOLCHAIN="gcc"
> > # Use intrinsics or assembly code for key routines
> > CONFIG_RTE_FORCE_INTRINSICS=n # Machine forces strict alignment
> > constraints.
> > CONFIG_RTE_ARCH_STRICT_ALIGN=n
> > # Compile to share library
> > CONFIG_RTE_BUILD_SHARED_LIB=n
> > # Use newest code breaking previous ABI CONFIG_RTE_NEXT_ABI=y # Major
> > ABI to overwrite library specific LIBABIVER CONFIG_RTE_MAJOR_ABI= #
> > Machine's cache line size
> > CONFIG_RTE_CACHE_LINE_SIZE=128
> > # Compile Environment Abstraction Layer CONFIG_RTE_LIBRTE_EAL=y
> > CONFIG_RTE_MAX_LCORE=256
> > CONFIG_RTE_MAX_NUMA_NODES=32
> > CONFIG_RTE_MAX_MEMSEG=256
> > CONFIG_RTE_MAX_MEMZONE=2560
> > CONFIG_RTE_MAX_TAILQ=32
> > CONFIG_RTE_LOG_LEVEL=RTE_LOG_INFO
> > CONFIG_RTE_LOG_DP_LEVEL=RTE_LOG_INFO
> > CONFIG_RTE_LOG_HISTORY=256
> > CONFIG_RTE_BACKTRACE=y
> > CONFIG_RTE_LIBEAL_USE_HPET=n
> > CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID=n
> > CONFIG_RTE_EAL_ALWAYS_PANIC_ON_ERROR=n
> > CONFIG_RTE_EAL_IGB_UIO=y
> > CONFIG_RTE_EAL_VFIO=y
> > CONFIG_RTE_MALLOC_DEBUG=n
> > CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES=y
> > # Recognize/ignore architecture we compile for. AVX/AVX512 CPU flags
> > for performance/power testing.
> > # AVX512 is marked as experimental for now, will enable it after
> > enough #
> field
> > test and possible optimization.
> > CONFIG_RTE_ENABLE_AVX=y
> > CONFIG_RTE_ENABLE_AVX512=n
> > # Default driver path (or "" to disable) CONFIG_RTE_EAL_PMD_PATH=""
> > # Compile Environment Abstraction Layer to support Vmware TSC map
> > CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=n
> > # Compile architecture we compile for. argument parser library
> > CONFIG_RTE_LIBRTE_KVARGS=y # Compile generic ethernet library
> > CONFIG_RTE_LIBRTE_ETHER=y CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n
> > CONFIG_RTE_MAX_ETHPORTS=32
> > CONFIG_RTE_MAX_QUEUES_PER_PORT=1024
> > CONFIG_RTE_LIBRTE_IEEE1588=n
> > CONFIG_RTE_ETHDEV_QUEUE_STAT_CNTRS=16
> > CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y
> > # Turn off Tx preparation stage
> > # Warning: rte_eth_tx_prepare() can be safely disabled only if using a
> > #
> driver
> > which do not implement any Tx preparation.
> > CONFIG_RTE_ETHDEV_TX_PREPARE_NOOP=n
> > # Compile burst-oriented Amazon ENA PMD driver
> > CONFIG_RTE_LIBRTE_ENA_PMD=y CONFIG_RTE_LIBRTE_ENA_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_ENA_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_ENA_DEBUG_TX_FREE=n
> > CONFIG_RTE_LIBRTE_ENA_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_ENA_COM_DEBUG=n
> > # Compile burst-oriented IGB & EM PMD drivers
> > CONFIG_RTE_LIBRTE_EM_PMD=y CONFIG_RTE_LIBRTE_IGB_PMD=y
> > CONFIG_RTE_LIBRTE_E1000_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_E1000_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_E1000_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_E1000_DEBUG_TX_FREE=n
> > CONFIG_RTE_LIBRTE_E1000_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_E1000_PF_DISABLE_STRIP_CRC=n
> > # Compile burst-oriented IXGBE PMD driver
> > CONFIG_RTE_LIBRTE_IXGBE_PMD=n
> CONFIG_RTE_LIBRTE_IXGBE_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX_FREE=n
> > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC=n
> > CONFIG_RTE_IXGBE_INC_VECTOR=y
> > CONFIG_RTE_LIBRTE_IXGBE_BYPASS=n
> > # Compile burst-oriented I40E PMD driver CONFIG_RTE_LIBRTE_I40E_PMD=y
> > CONFIG_RTE_LIBRTE_I40E_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_I40E_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_I40E_DEBUG_TX_FREE=n
> > CONFIG_RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC=y
> > CONFIG_RTE_LIBRTE_I40E_INC_VECTOR=y
> > CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n
> > CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF=64
> > CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF=4
> > CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM=4
> > # interval up to 8160 us, aligned to 2 (or default value)
> > CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL=-1
> > # Compile burst-oriented FM10K PMD
> > CONFIG_RTE_LIBRTE_FM10K_PMD=n
> > CONFIG_RTE_LIBRTE_FM10K_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_FM10K_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX_FREE=n
> > CONFIG_RTE_LIBRTE_FM10K_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE=y
> > CONFIG_RTE_LIBRTE_FM10K_INC_VECTOR=y
> > # Compile burst-oriented Mellanox ConnectX-3 (MLX4) PMD
> > CONFIG_RTE_LIBRTE_MLX4_PMD=n CONFIG_RTE_LIBRTE_MLX4_DEBUG=n
> > CONFIG_RTE_LIBRTE_MLX4_DEBUG_BROKEN_VERBS=n
> > CONFIG_RTE_LIBRTE_MLX4_SGE_WR_N=4
> > CONFIG_RTE_LIBRTE_MLX4_MAX_INLINE=0
> > CONFIG_RTE_LIBRTE_MLX4_TX_MP_CACHE=8
> > CONFIG_RTE_LIBRTE_MLX4_SOFT_COUNTERS=1
> > # Compile burst-oriented Mellanox ConnectX-4 & ConnectX-5 (MLX5) PMD
> > CONFIG_RTE_LIBRTE_MLX5_PMD=y CONFIG_RTE_LIBRTE_MLX5_DEBUG=n
> > CONFIG_RTE_LIBRTE_MLX5_TX_MP_CACHE=8
> > # Compile burst-oriented Broadcom PMD driver
> > CONFIG_RTE_LIBRTE_BNX2X_PMD=n CONFIG_RTE_LIBRTE_BNX2X_DEBUG=n
> > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_BNX2X_MF_SUPPORT=n
> > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_PERIODIC=n
> > # Compile burst-oriented Chelsio Terminator (CXGBE) PMD
> > CONFIG_RTE_LIBRTE_CXGBE_PMD=y
> CONFIG_RTE_LIBRTE_CXGBE_DEBUG=n
> > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_REG=n
> > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_MBOX=n
> > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_CXGBE_TPUT=y
> > # Compile burst-oriented Cisco ENIC PMD driver
> > CONFIG_RTE_LIBRTE_ENIC_PMD=n CONFIG_RTE_LIBRTE_ENIC_DEBUG=n
> > CONFIG_RTE_LIBRTE_ENIC_DEBUG_FLOW=n
> > # Compile burst-oriented Netronome NFP PMD driver
> > CONFIG_RTE_LIBRTE_NFP_PMD=y CONFIG_RTE_LIBRTE_NFP_DEBUG=n #
> Compile
> > burst-oriented Broadcom BNXT PMD driver
> CONFIG_RTE_LIBRTE_BNXT_PMD=y #
> > Compile burst-oriented Solarflare libefx-based PMD
> > CONFIG_RTE_LIBRTE_SFC_EFX_PMD=n
> CONFIG_RTE_LIBRTE_SFC_EFX_DEBUG=n #
> > Compile software PMD backed by
> > SZEDATA2 device CONFIG_RTE_LIBRTE_PMD_SZEDATA2=n # Defines
> firmware
> > type address space.
> > # See documentation for supported values.
> > # Other values raise compile time error.
> > CONFIG_RTE_LIBRTE_PMD_SZEDATA2_AS=0
> > # Compile burst-oriented Cavium Thunderx NICVF PMD driver
> > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD=y
> > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_MBOX=n
> > # Compile burst-oriented Cavium LiquidIO PMD driver
> > CONFIG_RTE_LIBRTE_LIO_PMD=y
> CONFIG_RTE_LIBRTE_LIO_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_LIO_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_LIO_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_LIO_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_LIO_DEBUG_MBOX=n
> > CONFIG_RTE_LIBRTE_LIO_DEBUG_REGS=n
> > # Compile NXP DPAA2 FSL-MC Bus
> > CONFIG_RTE_LIBRTE_FSLMC_BUS=n
> > # Compile Support Libraries for NXP DPAA2
> > CONFIG_RTE_LIBRTE_DPAA2_MEMPOOL=n
> > CONFIG_RTE_LIBRTE_DPAA2_USE_PHYS_IOVA=y
> > # Compile burst-oriented NXP DPAA2 PMD driver
> > CONFIG_RTE_LIBRTE_DPAA2_PMD=n
> CONFIG_RTE_LIBRTE_DPAA2_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX_FREE=n
> > # Compile burst-oriented VIRTIO PMD driver
> > CONFIG_RTE_LIBRTE_VIRTIO_PMD=y
> CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DUMP=n
> > # Compile virtio device emulation inside virtio PMD driver
> > CONFIG_RTE_VIRTIO_USER=y # Compile burst-oriented VMXNET3 PMD
> driver
> > CONFIG_RTE_LIBRTE_VMXNET3_PMD=n
> CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX_FREE=n
> > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_DRIVER=n
> > # Compile example software rings based PMD
> > CONFIG_RTE_LIBRTE_PMD_RING=y
> > CONFIG_RTE_PMD_RING_MAX_RX_RINGS=16
> > CONFIG_RTE_PMD_RING_MAX_TX_RINGS=16
> > # Compile software PMD backed by PCAP files
> > CONFIG_RTE_LIBRTE_PMD_PCAP=n # Compile link bonding PMD library
> > CONFIG_RTE_LIBRTE_PMD_BOND=y
> CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB=n
> > CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB_L1=n
> > # QLogic 10G/25G/40G/50G/100G PMD
> > CONFIG_RTE_LIBRTE_QEDE_PMD=y
> > CONFIG_RTE_LIBRTE_QEDE_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_QEDE_DEBUG_INFO=n
> > CONFIG_RTE_LIBRTE_QEDE_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_QEDE_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_QEDE_DEBUG_RX=n
> > #Provides abs path/name of architecture we compile for. firmware file.
> > #Empty string denotes driver will use default firmware
> > CONFIG_RTE_LIBRTE_QEDE_FW=""
> > # Compile software PMD backed by AF_PACKET sockets (Linux only)
> > CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y # Compile ARK PMD
> > CONFIG_RTE_LIBRTE_ARK_PMD=y CONFIG_RTE_LIBRTE_ARK_PAD_TX=y
> > CONFIG_RTE_LIBRTE_ARK_DEBUG_RX=n
> CONFIG_RTE_LIBRTE_ARK_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_ARK_DEBUG_STATS=n
> > CONFIG_RTE_LIBRTE_ARK_DEBUG_TRACE=n
> > # Compile WRS accelerated virtual port (AVP) guest PMD driver
> > CONFIG_RTE_LIBRTE_AVP_PMD=n CONFIG_RTE_LIBRTE_AVP_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_AVP_DEBUG_TX=n
> CONFIG_RTE_LIBRTE_AVP_DEBUG_DRIVER=y
> > CONFIG_RTE_LIBRTE_AVP_DEBUG_BUFFERS=n
> > # Compile architecture we compile for. TAP PMD # It is enabled by
> > default
> for
> > Linux only.
> > CONFIG_RTE_LIBRTE_PMD_TAP=y
> > # Compile Xen PMD
> > CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
> > # Compile null PMD
> > CONFIG_RTE_LIBRTE_PMD_NULL=y
> > # Compile fail-safe PMD
> > CONFIG_RTE_LIBRTE_PMD_FAILSAFE=y
> > # Do prefetch of packet data within PMD driver receive function
> > CONFIG_RTE_PMD_PACKET_PREFETCH=y # Compile generic crypto device
> > library CONFIG_RTE_LIBRTE_CRYPTODEV=y
> > CONFIG_RTE_LIBRTE_CRYPTODEV_DEBUG=n
> > CONFIG_RTE_CRYPTO_MAX_DEVS=64
> > CONFIG_RTE_CRYPTODEV_NAME_LEN=64
> > # Compile PMD for ARMv8 Crypto device
> > CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO=n
> > CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO_DEBUG=n
> > # Compile NXP DPAA2 crypto sec driver for CAAM HW
> > CONFIG_RTE_LIBRTE_PMD_DPAA2_SEC=n
> > CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_DRIVER=n
> > CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_RX=n
> > # Compile PMD for QuickAssist based devices
> > CONFIG_RTE_LIBRTE_PMD_QAT=n
> CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_INIT=n
> > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_DRIVER=n
> > # Number of sessions to create in architecture we compile for. session
> memory
> > pool # on a single QuickAssist device.
> > CONFIG_RTE_QAT_PMD_MAX_NB_SESSIONS=2048
> > # Compile PMD for AESNI backed device
> > CONFIG_RTE_LIBRTE_PMD_AESNI_MB=n
> > CONFIG_RTE_LIBRTE_PMD_AESNI_MB_DEBUG=n
> > # Compile PMD for Software backed device
> > CONFIG_RTE_LIBRTE_PMD_OPENSSL=n
> CONFIG_RTE_LIBRTE_PMD_OPENSSL_DEBUG=n
> > # Compile PMD for AESNI GCM device
> > CONFIG_RTE_LIBRTE_PMD_AESNI_GCM=n
> > CONFIG_RTE_LIBRTE_PMD_AESNI_GCM_DEBUG=n
> > # Compile PMD for SNOW 3G device
> > CONFIG_RTE_LIBRTE_PMD_SNOW3G=n
> > CONFIG_RTE_LIBRTE_PMD_SNOW3G_DEBUG=n
> > # Compile PMD for KASUMI device
> > CONFIG_RTE_LIBRTE_PMD_KASUMI=n
> > CONFIG_RTE_LIBRTE_PMD_KASUMI_DEBUG=n
> > # Compile PMD for ZUC device
> > CONFIG_RTE_LIBRTE_PMD_ZUC=n
> > CONFIG_RTE_LIBRTE_PMD_ZUC_DEBUG=n
> > # Compile PMD for Crypto Scheduler device
> > CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER=y
> > CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER_DEBUG=n
> > # Compile PMD for NULL Crypto device
> > CONFIG_RTE_LIBRTE_PMD_NULL_CRYPTO=y
> > # Compile generic event device library CONFIG_RTE_LIBRTE_EVENTDEV=y
> > CONFIG_RTE_LIBRTE_EVENTDEV_DEBUG=n
> > CONFIG_RTE_EVENT_MAX_DEVS=16
> > CONFIG_RTE_EVENT_MAX_QUEUES_PER_DEV=64
> > # Compile PMD for skeleton event device
> > CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV=y
> > CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV_DEBUG=n
> > # Compile PMD for software event device
> > CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV=y
> > CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV_DEBUG=n
> > # Compile PMD for octeontx sso event device
> > CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF=y
> > CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF_DEBUG=n
> > # Compile librte_ring
> > CONFIG_RTE_LIBRTE_RING=y
> > # Compile librte_mempool
> > CONFIG_RTE_LIBRTE_MEMPOOL=y
> > CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE=512
> > CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG=n
> > # Compile Mempool drivers
> > CONFIG_RTE_DRIVER_MEMPOOL_RING=y
> > CONFIG_RTE_DRIVER_MEMPOOL_STACK=y
> > # Compile librte_mbuf
> > CONFIG_RTE_LIBRTE_MBUF=y
> > CONFIG_RTE_LIBRTE_MBUF_DEBUG=n
> > CONFIG_RTE_MBUF_DEFAULT_MEMPOOL_OPS="ring_mp_mc"
> > CONFIG_RTE_MBUF_REFCNT_ATOMIC=y
> > CONFIG_RTE_PKTMBUF_HEADROOM=128
> > # Compile librte_timer
> > CONFIG_RTE_LIBRTE_TIMER=y
> > CONFIG_RTE_LIBRTE_TIMER_DEBUG=n
> > # Compile librte_cfgfile
> > CONFIG_RTE_LIBRTE_CFGFILE=y
> > # Compile librte_cmdline
> > CONFIG_RTE_LIBRTE_CMDLINE=y
> > CONFIG_RTE_LIBRTE_CMDLINE_DEBUG=n
> > # Compile librte_hash
> > CONFIG_RTE_LIBRTE_HASH=y
> > CONFIG_RTE_LIBRTE_HASH_DEBUG=n
> > # Compile librte_efd
> > CONFIG_RTE_LIBRTE_EFD=y
> > # Compile librte_jobstats
> > CONFIG_RTE_LIBRTE_JOBSTATS=y
> > # Compile architecture we compile for. device metrics library
> > CONFIG_RTE_LIBRTE_METRICS=y # Compile architecture we compile for.
> > bitrate statistics library CONFIG_RTE_LIBRTE_BITRATE=y # Compile
> > architecture we compile for. latency statistics library
> > CONFIG_RTE_LIBRTE_LATENCY_STATS=y # Compile librte_lpm
> > CONFIG_RTE_LIBRTE_LPM=y CONFIG_RTE_LIBRTE_LPM_DEBUG=n #
> Compile
> > librte_acl CONFIG_RTE_LIBRTE_ACL=y CONFIG_RTE_LIBRTE_ACL_DEBUG=n
> #
> > Compile librte_power CONFIG_RTE_LIBRTE_POWER=y
> > CONFIG_RTE_LIBRTE_POWER_DEBUG=n
> > CONFIG_RTE_MAX_LCORE_FREQS=64
> > # Compile librte_net
> > CONFIG_RTE_LIBRTE_NET=y
> > # Compile librte_ip_frag
> > CONFIG_RTE_LIBRTE_IP_FRAG=y
> > CONFIG_RTE_LIBRTE_IP_FRAG_DEBUG=n
> > CONFIG_RTE_LIBRTE_IP_FRAG_MAX_FRAG=4
> > CONFIG_RTE_LIBRTE_IP_FRAG_TBL_STAT=n
> > # Compile GRO library
> > CONFIG_RTE_LIBRTE_GRO=y
> > # Compile librte_meter
> > CONFIG_RTE_LIBRTE_METER=y
> > # Compile librte_sched
> > CONFIG_RTE_LIBRTE_SCHED=y
> > CONFIG_RTE_SCHED_DEBUG=n
> > CONFIG_RTE_SCHED_RED=n
> > CONFIG_RTE_SCHED_COLLECT_STATS=n
> > CONFIG_RTE_SCHED_SUBPORT_TC_OV=n
> > CONFIG_RTE_SCHED_PORT_N_GRINDERS=8
> > CONFIG_RTE_SCHED_VECTOR=n
> > # Compile architecture we compile for. distributor library
> > CONFIG_RTE_LIBRTE_DISTRIBUTOR=y # Compile architecture we compile for.
> > reorder library CONFIG_RTE_LIBRTE_REORDER=y # Compile librte_port
> > CONFIG_RTE_LIBRTE_PORT=y CONFIG_RTE_PORT_STATS_COLLECT=n
> > CONFIG_RTE_PORT_PCAP=n # Compile librte_table
> > CONFIG_RTE_LIBRTE_TABLE=y CONFIG_RTE_TABLE_STATS_COLLECT=n #
> Compile
> > librte_pipeline CONFIG_RTE_LIBRTE_PIPELINE=y
> > CONFIG_RTE_PIPELINE_STATS_COLLECT=n
> > # Compile librte_kni
> > CONFIG_RTE_LIBRTE_KNI=y
> > CONFIG_RTE_LIBRTE_PMD_KNI=y
> > CONFIG_RTE_KNI_KMOD=y
> > CONFIG_RTE_KNI_KMOD_ETHTOOL=n
> > CONFIG_RTE_KNI_PREEMPT_DEFAULT=y
> > # Compile architecture we compile for. pdump library
> > CONFIG_RTE_LIBRTE_PDUMP=y # Compile vhost user library
> > CONFIG_RTE_LIBRTE_VHOST=y CONFIG_RTE_LIBRTE_VHOST_NUMA=y
> > CONFIG_RTE_LIBRTE_VHOST_DEBUG=n # Compile vhost PMD # To compile,
> > CONFIG_RTE_LIBRTE_VHOST should be enabled.
> > CONFIG_RTE_LIBRTE_PMD_VHOST=y
> > #Compile Xen domain0 support
> > CONFIG_RTE_LIBRTE_XEN_DOM0=n
> > # Compile architecture we compile for. test application
> > CONFIG_RTE_APP_TEST=y CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
> > # Compile architecture we compile for. PMD test application
> > CONFIG_RTE_TEST_PMD=y
> CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
> > CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
> > # Compile architecture we compile for. crypto performance application
> > CONFIG_RTE_APP_CRYPTO_PERF=y # Compile architecture we compile for.
> > eventdev application CONFIG_RTE_APP_EVENTDEV=y
> > CONFIG_RTE_EXEC_ENV_LINUXAPP=y CONFIG_RTE_ARCH_PPC_64=y
> > CONFIG_RTE_ARCH_64=y CONFIG_RTE_TOOLCHAIN_GCC=y # Note: Power
> doesn't
> > have this support # Note: Initially, all of architecture we
> compile for.
> > PMD drivers compilation are turned off on Power # Will turn on them
> > only
> after
> > architecture we compile for. successful testing on Power
> >
> > Please refer here for more information on running DPDK multi-process
> > examples:
> >
> > https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Furl
> > defense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> 3A__dpdk.org_doc_guides_s
> >
> &data=02%7C01%7Cxuemingl%40mellanox.com%7C9cd11fda7a7f48df7cbd08d
> 4f9b4
> >
> 86d8%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C6364080011387
> 51301&s
> > data=4n76ha0PmSr3wP2c0MAo3PEVYRMKjJVcU9o5xETqhBc%3D&reserved=0
> > ample-5Fapp-5Fug_multi-5Fprocess.html&d=DwIFAg&c=jf_iaSHvJObTbx-
> siA1Z
> >
> Og&r=4TYe4NpqlgVi0ArYpZ76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwu
> > uryoN7QPg9N-6aTY_jEvDZtMZR0o&s=gupwe5WWQ-
> ap2jObFko6UJymrcy4jTmF
> > 2r1dZ2fQN9E&e=
> >
> > Best Regards,
> > Xueming
> 


^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v2 04/17] build: add DPDK libraries to build
  @ 2017-09-12 10:37  1%   ` Bruce Richardson
  2017-09-12 10:38  3%   ` [dpdk-dev] [PATCH v2 16/17] build: add option to version libs using DPDK version Bruce Richardson
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2017-09-12 10:37 UTC (permalink / raw)
  To: dev; +Cc: nhorman, luca.boccassi, harry.van.haaren, Bruce Richardson

Add non-EAL libraries to DPDK build. The compat lib is a special case,
along with the previously-added EAL, but all other libs can be build using
the same set of commands, where the individual meson.build files only need
to specify their dependencies, source files, header files and ABI versions.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Reviewed-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 config/rte_config.h                 | 36 ++++++++++++++++++++
 lib/librte_acl/meson.build          | 59 ++++++++++++++++++++++++++++++++
 lib/librte_bitratestats/meson.build | 34 +++++++++++++++++++
 lib/librte_cfgfile/meson.build      | 34 +++++++++++++++++++
 lib/librte_cmdline/meson.build      | 55 ++++++++++++++++++++++++++++++
 lib/librte_compat/meson.build       | 36 ++++++++++++++++++++
 lib/librte_cryptodev/meson.build    | 40 ++++++++++++++++++++++
 lib/librte_distributor/meson.build  | 39 +++++++++++++++++++++
 lib/librte_efd/meson.build          | 34 +++++++++++++++++++
 lib/librte_ether/meson.build        | 45 +++++++++++++++++++++++++
 lib/librte_eventdev/meson.build     | 36 ++++++++++++++++++++
 lib/librte_gro/meson.build          | 34 +++++++++++++++++++
 lib/librte_hash/meson.build         | 45 +++++++++++++++++++++++++
 lib/librte_ip_frag/meson.build      | 39 +++++++++++++++++++++
 lib/librte_jobstats/meson.build     | 33 ++++++++++++++++++
 lib/librte_kni/meson.build          | 38 +++++++++++++++++++++
 lib/librte_kvargs/meson.build       | 34 +++++++++++++++++++
 lib/librte_latencystats/meson.build | 34 +++++++++++++++++++
 lib/librte_lpm/meson.build          | 35 +++++++++++++++++++
 lib/librte_mbuf/meson.build         | 35 +++++++++++++++++++
 lib/librte_mempool/meson.build      | 35 +++++++++++++++++++
 lib/librte_meter/meson.build        | 33 ++++++++++++++++++
 lib/librte_metrics/meson.build      | 33 ++++++++++++++++++
 lib/librte_net/meson.build          | 45 +++++++++++++++++++++++++
 lib/librte_pdump/meson.build        | 34 +++++++++++++++++++
 lib/librte_pipeline/meson.build     | 35 +++++++++++++++++++
 lib/librte_port/meson.build         | 58 ++++++++++++++++++++++++++++++++
 lib/librte_power/meson.build        | 37 ++++++++++++++++++++
 lib/librte_reorder/meson.build      | 34 +++++++++++++++++++
 lib/librte_ring/meson.build         | 33 ++++++++++++++++++
 lib/librte_sched/meson.build        | 36 ++++++++++++++++++++
 lib/librte_table/meson.build        | 52 ++++++++++++++++++++++++++++
 lib/librte_timer/meson.build        | 33 ++++++++++++++++++
 lib/librte_vhost/meson.build        | 39 +++++++++++++++++++++
 lib/meson.build                     | 67 +++++++++++++++++++++++++++++++++++++
 35 files changed, 1379 insertions(+)
 create mode 100644 lib/librte_acl/meson.build
 create mode 100644 lib/librte_bitratestats/meson.build
 create mode 100644 lib/librte_cfgfile/meson.build
 create mode 100644 lib/librte_cmdline/meson.build
 create mode 100644 lib/librte_compat/meson.build
 create mode 100644 lib/librte_cryptodev/meson.build
 create mode 100644 lib/librte_distributor/meson.build
 create mode 100644 lib/librte_efd/meson.build
 create mode 100644 lib/librte_ether/meson.build
 create mode 100644 lib/librte_eventdev/meson.build
 create mode 100644 lib/librte_gro/meson.build
 create mode 100644 lib/librte_hash/meson.build
 create mode 100644 lib/librte_ip_frag/meson.build
 create mode 100644 lib/librte_jobstats/meson.build
 create mode 100644 lib/librte_kni/meson.build
 create mode 100644 lib/librte_kvargs/meson.build
 create mode 100644 lib/librte_latencystats/meson.build
 create mode 100644 lib/librte_lpm/meson.build
 create mode 100644 lib/librte_mbuf/meson.build
 create mode 100644 lib/librte_mempool/meson.build
 create mode 100644 lib/librte_meter/meson.build
 create mode 100644 lib/librte_metrics/meson.build
 create mode 100644 lib/librte_net/meson.build
 create mode 100644 lib/librte_pdump/meson.build
 create mode 100644 lib/librte_pipeline/meson.build
 create mode 100644 lib/librte_port/meson.build
 create mode 100644 lib/librte_power/meson.build
 create mode 100644 lib/librte_reorder/meson.build
 create mode 100644 lib/librte_ring/meson.build
 create mode 100644 lib/librte_sched/meson.build
 create mode 100644 lib/librte_table/meson.build
 create mode 100644 lib/librte_timer/meson.build
 create mode 100644 lib/librte_vhost/meson.build

diff --git a/config/rte_config.h b/config/rte_config.h
index c94704cfe..b47cfabae 100644
--- a/config/rte_config.h
+++ b/config/rte_config.h
@@ -58,4 +58,40 @@
 #define RTE_BACKTRACE 1
 #define RTE_EAL_VFIO 1
 
+/* mempool defines */
+#define RTE_MEMPOOL_CACHE_MAX_SIZE 512
+
+/* mbuf defines */
+#define RTE_MBUF_DEFAULT_MEMPOOL_OPS "ring_mp_mc"
+#define RTE_MBUF_REFCNT_ATOMIC 1
+#define RTE_PKTMBUF_HEADROOM 128
+
+/* ether defines */
+#define RTE_MAX_ETHPORTS 32
+#define RTE_MAX_QUEUES_PER_PORT 1024
+#define RTE_ETHDEV_QUEUE_STAT_CNTRS 16
+#define RTE_ETHDEV_RXTX_CALLBACKS 1
+
+/* cryptodev defines */
+#define RTE_CRYPTO_MAX_DEVS 64
+#define RTE_CRYPTODEV_NAME_LEN 64
+
+/* eventdev defines */
+#define RTE_EVENT_MAX_DEVS 16
+#define RTE_EVENT_MAX_QUEUES_PER_DEV 64
+
+/* ip_fragmentation defines */
+#define RTE_LIBRTE_IP_FRAG_MAX_FRAG 4
+#undef RTE_LIBRTE_IP_FRAG_TBL_STAT
+
+/* rte_power defines */
+#define RTE_MAX_LCORE_FREQS 64
+
+/* rte_sched defines */
+#undef RTE_SCHED_RED
+#undef RTE_SCHED_COLLECT_STATS
+#undef RTE_SCHED_SUBPORT_TC_OV
+#define RTE_SCHED_PORT_N_GRINDERS 8
+#undef RTE_SCHED_VECTOR
+
 #endif /* _RTE_CONFIG_H_ */
diff --git a/lib/librte_acl/meson.build b/lib/librte_acl/meson.build
new file mode 100644
index 000000000..b81b74468
--- /dev/null
+++ b/lib/librte_acl/meson.build
@@ -0,0 +1,59 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('acl_bld.c', 'acl_gen.c', 'acl_run_scalar.c',
+		'rte_acl.c', 'tb_mem.c')
+headers = files('rte_acl.h', 'rte_acl_osdep.h')
+
+if arch_subdir == 'x86'
+	sources += files('acl_run_sse.c')
+
+	# compile AVX2 version if either:
+	# a. we have AVX supported in minimum instruction set baseline
+	# b. it's not minimum instruction set, but supported by compiler
+	#
+	# in former case, just add avx2 C file to files list
+	# in latter case, compile c file to static lib, using correct compiler
+	# flags, and then have the .o file from static lib linked into main lib.
+	if dpdk_conf.has('RTE_MACHINE_CPUFLAG_AVX2')
+		sources += files('acl_run_avx2.c')
+		cflags += '-DCC_AVX2_SUPPORT'
+	elif cc.has_argument('-mavx2')
+		avx2_tmplib = static_library('avx2_tmp',
+				'acl_run_avx2.c',
+				dependencies: rte_eal,
+				c_args: '-mavx2')
+		objs += avx2_tmplib.extract_objects('acl_run_avx2.c')
+		cflags += '-DCC_AVX2_SUPPORT'
+	endif
+
+endif
diff --git a/lib/librte_bitratestats/meson.build b/lib/librte_bitratestats/meson.build
new file mode 100644
index 000000000..dcf6070bf
--- /dev/null
+++ b/lib/librte_bitratestats/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_bitrate.c')
+headers = files('rte_bitrate.h')
+deps += ['ethdev', 'metrics']
diff --git a/lib/librte_cfgfile/meson.build b/lib/librte_cfgfile/meson.build
new file mode 100644
index 000000000..1a4992ff3
--- /dev/null
+++ b/lib/librte_cfgfile/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('rte_cfgfile.c')
+headers = files('rte_cfgfile.h')
diff --git a/lib/librte_cmdline/meson.build b/lib/librte_cmdline/meson.build
new file mode 100644
index 000000000..80fbe5d07
--- /dev/null
+++ b/lib/librte_cmdline/meson.build
@@ -0,0 +1,55 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('cmdline.c',
+	'cmdline_cirbuf.c',
+	'cmdline_parse.c',
+	'cmdline_parse_etheraddr.c',
+	'cmdline_parse_ipaddr.c',
+	'cmdline_parse_num.c',
+	'cmdline_parse_portlist.c',
+	'cmdline_parse_string.c',
+	'cmdline_rdline.c',
+	'cmdline_socket.c',
+	'cmdline_vt100.c')
+
+headers = files('cmdline.h',
+	'cmdline_parse.h',
+	'cmdline_parse_num.h',
+	'cmdline_parse_ipaddr.h',
+	'cmdline_parse_etheraddr.h',
+	'cmdline_parse_string.h',
+	'cmdline_rdline.h',
+	'cmdline_vt100.h',
+	'cmdline_socket.h',
+	'cmdline_cirbuf.h',
+	'cmdline_parse_portlist.h')
diff --git a/lib/librte_compat/meson.build b/lib/librte_compat/meson.build
new file mode 100644
index 000000000..3b911dfff
--- /dev/null
+++ b/lib/librte_compat/meson.build
@@ -0,0 +1,36 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+
+install_headers('rte_compat.h')
+
+set_variable('dep_rte_compat',
+	declare_dependency(include_directories: include_directories('.')))
diff --git a/lib/librte_cryptodev/meson.build b/lib/librte_cryptodev/meson.build
new file mode 100644
index 000000000..e45e7098a
--- /dev/null
+++ b/lib/librte_cryptodev/meson.build
@@ -0,0 +1,40 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 3
+sources = files('rte_cryptodev.c', 'rte_cryptodev_pmd.c')
+headers = files('rte_cryptodev.h',
+	'rte_cryptodev_pci.h',
+	'rte_cryptodev_pmd.h',
+	'rte_cryptodev_vdev.h',
+	'rte_crypto.h',
+	'rte_crypto_sym.h')
+deps += ['kvargs', 'mbuf']
diff --git a/lib/librte_distributor/meson.build b/lib/librte_distributor/meson.build
new file mode 100644
index 000000000..6118c5f50
--- /dev/null
+++ b/lib/librte_distributor/meson.build
@@ -0,0 +1,39 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_distributor.c', 'rte_distributor_v20.c')
+if arch_subdir == 'x86'
+	sources += files('rte_distributor_match_sse.c')
+else
+	sources += files('rte_distributor_match_generic.c')
+endif
+headers = files('rte_distributor.h')
+deps += ['mbuf', 'compat']
diff --git a/lib/librte_efd/meson.build b/lib/librte_efd/meson.build
new file mode 100644
index 000000000..73c004e70
--- /dev/null
+++ b/lib/librte_efd/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_efd.c')
+headers = files('rte_efd.h')
+deps += ['ring', 'hash']
diff --git a/lib/librte_ether/meson.build b/lib/librte_ether/meson.build
new file mode 100644
index 000000000..d10bd37d5
--- /dev/null
+++ b/lib/librte_ether/meson.build
@@ -0,0 +1,45 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+name = 'ethdev'
+version = 6
+sources = files('rte_ethdev.c', 'rte_flow.c', 'rte_tm.c')
+
+headers = files('rte_ethdev.h',
+	'rte_ethdev_pci.h',
+	'rte_ethdev_vdev.h',
+	'rte_eth_ctrl.h',
+	'rte_dev_info.h',
+	'rte_flow.h',
+	'rte_flow_driver.h',
+	'rte_tm.h')
+
+deps += ['net']
diff --git a/lib/librte_eventdev/meson.build b/lib/librte_eventdev/meson.build
new file mode 100644
index 000000000..60d5f4e89
--- /dev/null
+++ b/lib/librte_eventdev/meson.build
@@ -0,0 +1,36 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_eventdev.c', 'rte_event_ring.c')
+headers = files('rte_eventdev.h', 'rte_eventdev_pmd.h',
+		'rte_eventdev_pmd_pci.h', 'rte_eventdev_pmd_vdev.h',
+		'rte_event_ring.h')
+deps += ['ring']
diff --git a/lib/librte_gro/meson.build b/lib/librte_gro/meson.build
new file mode 100644
index 000000000..f6848c42b
--- /dev/null
+++ b/lib/librte_gro/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_gro.c', 'gro_tcp4.c')
+headers = files('rte_gro.h')
+deps += ['ethdev']
diff --git a/lib/librte_hash/meson.build b/lib/librte_hash/meson.build
new file mode 100644
index 000000000..1df383f4b
--- /dev/null
+++ b/lib/librte_hash/meson.build
@@ -0,0 +1,45 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+headers = files('rte_cmp_arm64.h',
+	'rte_cmp_x86.h',
+	'rte_crc_arm64.h',
+	'rte_cuckoo_hash.h',
+	'rte_cuckoo_hash_x86.h',
+	'rte_fbk_hash.h',
+	'rte_hash_crc.h',
+	'rte_hash.h',
+	'rte_jhash.h',
+	'rte_thash.h')
+
+sources = files('rte_cuckoo_hash.c', 'rte_fbk_hash.c')
+deps += ['ring', 'compat']
diff --git a/lib/librte_ip_frag/meson.build b/lib/librte_ip_frag/meson.build
new file mode 100644
index 000000000..11523badf
--- /dev/null
+++ b/lib/librte_ip_frag/meson.build
@@ -0,0 +1,39 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_ipv4_fragmentation.c',
+		'rte_ipv6_fragmentation.c',
+		'rte_ipv4_reassembly.c',
+		'rte_ipv6_reassembly.c',
+		'rte_ip_frag_common.c',
+		'ip_frag_internal.c')
+headers = files('rte_ip_frag.h')
+deps += ['ethdev', 'hash']
diff --git a/lib/librte_jobstats/meson.build b/lib/librte_jobstats/meson.build
new file mode 100644
index 000000000..97cf01cad
--- /dev/null
+++ b/lib/librte_jobstats/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_jobstats.c')
+headers = files('rte_jobstats.h')
diff --git a/lib/librte_kni/meson.build b/lib/librte_kni/meson.build
new file mode 100644
index 000000000..25934a46d
--- /dev/null
+++ b/lib/librte_kni/meson.build
@@ -0,0 +1,38 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+if host_machine.system() != 'linux'
+	build = false
+endif
+version = 2
+sources = files('rte_kni.c')
+headers = files('rte_kni.h')
+deps += ['ethdev']
diff --git a/lib/librte_kvargs/meson.build b/lib/librte_kvargs/meson.build
new file mode 100644
index 000000000..2962fc370
--- /dev/null
+++ b/lib/librte_kvargs/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 1
+sources = files('rte_kvargs.c')
+headers = files('rte_kvargs.h')
diff --git a/lib/librte_latencystats/meson.build b/lib/librte_latencystats/meson.build
new file mode 100644
index 000000000..10a778433
--- /dev/null
+++ b/lib/librte_latencystats/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_latencystats.c')
+headers = files('rte_latencystats.h')
+deps += ['metrics', 'ethdev']
diff --git a/lib/librte_lpm/meson.build b/lib/librte_lpm/meson.build
new file mode 100644
index 000000000..af88a97ec
--- /dev/null
+++ b/lib/librte_lpm/meson.build
@@ -0,0 +1,35 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('rte_lpm.c', 'rte_lpm6.c')
+headers = files('rte_lpm.h', 'rte_lpm6.h')
+deps += ['compat']
diff --git a/lib/librte_mbuf/meson.build b/lib/librte_mbuf/meson.build
new file mode 100644
index 000000000..96856e231
--- /dev/null
+++ b/lib/librte_mbuf/meson.build
@@ -0,0 +1,35 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 3
+sources = files('rte_mbuf.c', 'rte_mbuf_ptype.c')
+headers = files('rte_mbuf.h', 'rte_mbuf_ptype.h')
+deps += ['mempool']
diff --git a/lib/librte_mempool/meson.build b/lib/librte_mempool/meson.build
new file mode 100644
index 000000000..96e582deb
--- /dev/null
+++ b/lib/librte_mempool/meson.build
@@ -0,0 +1,35 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('rte_mempool.c', 'rte_mempool_ops.c')
+headers = files('rte_mempool.h')
+deps += ['ring']
diff --git a/lib/librte_meter/meson.build b/lib/librte_meter/meson.build
new file mode 100644
index 000000000..debcebcc1
--- /dev/null
+++ b/lib/librte_meter/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_meter.c')
+headers = files('rte_meter.h')
diff --git a/lib/librte_metrics/meson.build b/lib/librte_metrics/meson.build
new file mode 100644
index 000000000..c820503f0
--- /dev/null
+++ b/lib/librte_metrics/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_metrics.c')
+headers = files('rte_metrics.h')
diff --git a/lib/librte_net/meson.build b/lib/librte_net/meson.build
new file mode 100644
index 000000000..62bbf4c22
--- /dev/null
+++ b/lib/librte_net/meson.build
@@ -0,0 +1,45 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 1
+headers = files('rte_ip.h',
+	'rte_tcp.h',
+	'rte_udp.h',
+	'rte_sctp.h',
+	'rte_icmp.h',
+	'rte_arp.h',
+	'rte_ether.h',
+	'rte_gre.h',
+	'rte_net.h',
+	'rte_net_crc.h')
+
+sources = files('rte_net.c', 'rte_net_crc.c')
+deps += ['mbuf']
diff --git a/lib/librte_pdump/meson.build b/lib/librte_pdump/meson.build
new file mode 100644
index 000000000..94a92b677
--- /dev/null
+++ b/lib/librte_pdump/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_pdump.c')
+headers = files('rte_pdump.h')
+deps += ['ethdev']
diff --git a/lib/librte_pipeline/meson.build b/lib/librte_pipeline/meson.build
new file mode 100644
index 000000000..54e34fc62
--- /dev/null
+++ b/lib/librte_pipeline/meson.build
@@ -0,0 +1,35 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 3
+sources = files('rte_pipeline.c')
+headers = files('rte_pipeline.h')
+deps += ['port', 'table']
diff --git a/lib/librte_port/meson.build b/lib/librte_port/meson.build
new file mode 100644
index 000000000..a0d3a8c07
--- /dev/null
+++ b/lib/librte_port/meson.build
@@ -0,0 +1,58 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 3
+sources = files(
+	'rte_port_ethdev.c',
+	'rte_port_fd.c',
+	'rte_port_ring.c',
+	'rte_port_sched.c',
+	'rte_port_source_sink.c')
+headers = files(
+	'rte_port_ethdev.h',
+	'rte_port_fd.h',
+	'rte_port.h',
+	'rte_port_ring.h',
+	'rte_port_sched.h',
+	'rte_port_source_sink.h')
+deps += ['ethdev', 'sched']
+
+if dpdk_conf.has('RTE_LIBRTE_IP_FRAG')
+	sources += files('rte_port_frag.c', 'rte_port_ras.c')
+	headers += files('rte_port_frag.h', 'rte_port_ras.h')
+	deps += ['ip_frag']
+endif
+
+if dpdk_conf.has('RTE_LIBRTE_KNI')
+	sources += files('rte_port_kni.c')
+	headers += files('rte_port_kni.h')
+	deps += 'kni'
+endif
diff --git a/lib/librte_power/meson.build b/lib/librte_power/meson.build
new file mode 100644
index 000000000..541efa6a4
--- /dev/null
+++ b/lib/librte_power/meson.build
@@ -0,0 +1,37 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+if host_machine.system() != 'linux'
+	build = false
+endif
+sources = files('rte_power.c', 'rte_power_acpi_cpufreq.c',
+		'rte_power_kvm_vm.c', 'guest_channel.c')
+headers = files('rte_power.h')
diff --git a/lib/librte_reorder/meson.build b/lib/librte_reorder/meson.build
new file mode 100644
index 000000000..456e83f02
--- /dev/null
+++ b/lib/librte_reorder/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_reorder.c')
+headers = files('rte_reorder.h')
+deps += ['mbuf']
diff --git a/lib/librte_ring/meson.build b/lib/librte_ring/meson.build
new file mode 100644
index 000000000..8c102fe6a
--- /dev/null
+++ b/lib/librte_ring/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_ring.c')
+headers = files('rte_ring.h')
diff --git a/lib/librte_sched/meson.build b/lib/librte_sched/meson.build
new file mode 100644
index 000000000..c4badb211
--- /dev/null
+++ b/lib/librte_sched/meson.build
@@ -0,0 +1,36 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_sched.c', 'rte_red.c', 'rte_approx.c',
+		'rte_reciprocal.c')
+headers = files('rte_sched.h', 'rte_bitmap.h', 'rte_sched_common.h',
+		'rte_red.h', 'rte_approx.h', 'rte_reciprocal.h')
+deps += ['mbuf', 'meter']
diff --git a/lib/librte_table/meson.build b/lib/librte_table/meson.build
new file mode 100644
index 000000000..2fb3ec804
--- /dev/null
+++ b/lib/librte_table/meson.build
@@ -0,0 +1,52 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('rte_table_lpm.c', 'rte_table_lpm_ipv6.c',
+		'rte_table_hash_cuckoo.c', 'rte_table_hash_key8.c',
+		'rte_table_hash_key16.c', 'rte_table_hash_key32.c',
+		'rte_table_hash_ext.c', 'rte_table_hash_lru.c',
+		'rte_table_array.c', 'rte_table_stub.c')
+headers = files('rte_table.h', 'rte_table_lpm.h',
+		'rte_table_lpm_ipv6.h', 'rte_table_hash.h',
+		'rte_lru.h', 'rte_table_array.h',
+		'rte_table_stub.h')
+deps += ['mbuf', 'port', 'lpm', 'hash']
+
+if arch_subdir == 'x86'
+	headers += files('rte_lru_x86.h')
+endif
+
+if dpdk_conf.has('RTE_LIBRTE_ACL')
+	sources += files('rte_table_acl.c')
+	headers += files('rte_table_acl.h')
+	deps += ['acl']
+endif
diff --git a/lib/librte_timer/meson.build b/lib/librte_timer/meson.build
new file mode 100644
index 000000000..0edc45772
--- /dev/null
+++ b/lib/librte_timer/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_timer.c')
+headers = files('rte_timer.h')
diff --git a/lib/librte_vhost/meson.build b/lib/librte_vhost/meson.build
new file mode 100644
index 000000000..5482169ca
--- /dev/null
+++ b/lib/librte_vhost/meson.build
@@ -0,0 +1,39 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+if host_machine.system() != 'linux'
+	build = false
+endif
+version = 4
+sources = files('fd_man.c', 'socket.c', 'vhost.c', 'vhost_user.c',
+		'virtio_net.c')
+headers = files('rte_vhost.h')
+deps += ['ethdev']
diff --git a/lib/meson.build b/lib/meson.build
index 7cafe6666..d814721de 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -29,4 +29,71 @@
 #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# special case for eal, not a simple lib, and compat, just a header
 subdir('librte_eal')
+subdir('librte_compat')
+
+# process all libraries equally, as far as possible
+# "core" libs first, then others alphebetically as far as possible
+# NOTE: for speed of meson runs, the dependencies in the subdirectories
+# sometimes skip deps that would be implied by others, e.g. if mempool is
+# given as a dep, no need to mention ring. This is especially true for the
+# core libs which are widely reused, so their deps are kept to a minimum.
+libraries = ['ring', 'mempool', 'mbuf', 'net', 'ether', # core
+	'metrics', # bitrate/latency stats depends on this
+	'hash',    # efd depends on this
+	'kvargs',  # cryptodev depends on this
+	'acl', 'bitratestats', 'cfgfile', 'cmdline', 'cryptodev',
+	'distributor', 'efd', 'eventdev', 'gro', 'ip_frag', 'jobstats',
+	'kni', 'latencystats', 'lpm', 'meter', 'power', 'pdump',
+	'reorder', 'sched', 'timer', 'vhost',
+	# add pkt framework libs which use other libs from above
+	'port', 'table', 'pipeline']
+
+foreach l:libraries
+	build = true
+	name = l
+	version = 1
+	sources = []
+	headers = []
+	cflags = []
+	objs = [] # other object files to link against, used e.g. for instruction-
+	          # optimized versions of code
+	# use "deps" for internal DPDK dependencies, and "ext_deps" for
+	# external package/library requirements
+	deps = ['eal']
+	ext_deps = []
+
+	dir_name = 'librte_' + l
+	subdir(dir_name)
+
+	if build
+		dpdk_conf.set('RTE_LIBRTE_' + name.to_upper(), 1)
+		install_headers(headers)
+
+		dep_objs = ext_deps
+		foreach d:deps
+			dep_objs += [get_variable('dep_rte_' + d)]
+		endforeach
+
+		version_map = '@0@/@1@/rte_@2@_version.map'.format(
+				meson.current_source_dir(), dir_name, name)
+		libname = 'rte_' + name
+		lib = library(libname,
+				sources,
+				objects: objs,
+				c_args: cflags,
+				dependencies: dep_objs,
+				include_directories: include_directories(dir_name),
+				link_args: '-Wl,--version-script=' + version_map,
+				link_depends: version_map,
+				version: '@0@.1'.format(version),
+				install: true)
+		dep = declare_dependency(link_with: lib,
+				include_directories: include_directories(dir_name),
+				dependencies: dep_objs)
+		set_variable('dep_' + libname, dep)
+
+		dpdk_libraries = [lib] + dpdk_libraries
+	endif
+endforeach
-- 
2.13.5

^ permalink raw reply	[relevance 1%]

* [dpdk-dev] [PATCH v2 16/17] build: add option to version libs using DPDK version
    2017-09-12 10:37  1%   ` [dpdk-dev] [PATCH v2 04/17] build: add DPDK libraries to build Bruce Richardson
@ 2017-09-12 10:38  3%   ` Bruce Richardson
  2017-09-13 11:32  5%     ` Luca Boccassi
  2017-09-12 10:38  3%   ` [dpdk-dev] [PATCH v2 17/17] doc: add documentation on how to add new components to DPDK Bruce Richardson
    3 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2017-09-12 10:38 UTC (permalink / raw)
  To: dev; +Cc: nhorman, luca.boccassi, harry.van.haaren, Bruce Richardson

Normally, each library has it's own version number based on the ABI.
Add an option to have all libs just use the DPDK version number as the
.so version.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Reviewed-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 drivers/meson.build | 8 +++++++-
 lib/meson.build     | 8 +++++++-
 meson_options.txt   | 1 +
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/meson.build b/drivers/meson.build
index f19da16fb..0c251bd61 100644
--- a/drivers/meson.build
+++ b/drivers/meson.build
@@ -92,6 +92,12 @@ foreach class:driver_classes
 						depends: [pmdinfogen, tmp_lib])
 			endforeach
 
+			if get_option('per_library_versions')
+				so_version = '@0@.1'.format(version)
+			else
+				so_version = meson.project_version()
+			endif
+
 			# now build the driver itself, and add to the drivers list
 			lib_name = driver_name_fmt.format(name)
 			version_map = '@0@/@1@/@2@_version.map'.format(
@@ -105,7 +111,7 @@ foreach class:driver_classes
 				c_args: cflags,
 				link_args: '-Wl,--version-script=' + version_map,
 				link_depends: version_map,
-				version: '@0@.1'.format(version),
+				version: so_version,
 				install: true,
 				install_dir: driver_install_path)
 
diff --git a/lib/meson.build b/lib/meson.build
index d814721de..36652cfe1 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -76,6 +76,12 @@ foreach l:libraries
 			dep_objs += [get_variable('dep_rte_' + d)]
 		endforeach
 
+		if get_option('per_library_versions')
+			so_version = '@0@.1'.format(version)
+		else
+			so_version = meson.project_version()
+		endif
+
 		version_map = '@0@/@1@/rte_@2@_version.map'.format(
 				meson.current_source_dir(), dir_name, name)
 		libname = 'rte_' + name
@@ -87,7 +93,7 @@ foreach l:libraries
 				include_directories: include_directories(dir_name),
 				link_args: '-Wl,--version-script=' + version_map,
 				link_depends: version_map,
-				version: '@0@.1'.format(version),
+				version: so_version,
 				install: true)
 		dep = declare_dependency(link_with: lib,
 				include_directories: include_directories(dir_name),
diff --git a/meson_options.txt b/meson_options.txt
index 9c45b8159..636226ce8 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -6,3 +6,4 @@ option('allow_invalid_socket_id', type: 'boolean', value: false,
 	description: 'allow out-of-range NUMA socket id\'s for platforms that don\'t report the value correctly')
 option('enable_kmods', type: 'boolean', value: true, description: 'build kernel modules')
 option('kernel_dir', type: 'string', value: '', description: 'path to the kernel for building kernel modules')
+option('per_library_versions', type: 'boolean', value: true, description: 'true: each lib gets its own version number, false: DPDK version used for each lib')
-- 
2.13.5

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v2 17/17] doc: add documentation on how to add new components to DPDK
    2017-09-12 10:37  1%   ` [dpdk-dev] [PATCH v2 04/17] build: add DPDK libraries to build Bruce Richardson
  2017-09-12 10:38  3%   ` [dpdk-dev] [PATCH v2 16/17] build: add option to version libs using DPDK version Bruce Richardson
@ 2017-09-12 10:38  3%   ` Bruce Richardson
    3 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2017-09-12 10:38 UTC (permalink / raw)
  To: dev; +Cc: nhorman, luca.boccassi, harry.van.haaren, Bruce Richardson

Add to the contributors guide details on how to add libraries and drivers
and integrate them with the DPDK build system(s).

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Reviewed-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 doc/guides/contributing/coding_style.rst | 214 +++++++++++++++++++++++++++++++
 1 file changed, 214 insertions(+)

diff --git a/doc/guides/contributing/coding_style.rst b/doc/guides/contributing/coding_style.rst
index d8e4a0f9c..3c59cbca5 100644
--- a/doc/guides/contributing/coding_style.rst
+++ b/doc/guides/contributing/coding_style.rst
@@ -702,3 +702,217 @@ All Python code should work with Python 2.7+ and 3.2+ and be compliant with
 `PEP8 (Style Guide for Python Code) <https://www.python.org/dev/peps/pep-0008/>`_.
 
 The ``pep8`` tool can be used for testing compliance with the guidelines.
+
+Integrating with the Build System
+---------------------------------
+
+DPDK supports being built in two different ways:
+
+* using ``make`` - or more specifically "GNU make", i.e. ``gmake`` on FreeBSD
+* using the tools ``meson`` and ``ninja``
+
+Any new library or driver to be integrated into DPDK should support being
+built with both systems. While building using ``make`` is a legacy approach, and
+most build-system enhancements are being done using ``meson`` and ``ninja``
+there are no plans at this time to deprecate the legacy ``make`` build system.
+
+Therefore all new component additions should include both a ``Makefile`` and a
+``meson.build`` file, and should be added to the component lists in both the
+``Makefile`` and ``meson.build`` files in the relevant top-level directory:
+either ``lib`` directory or a ``driver`` subdirectory.
+
+Makefile Contents
+~~~~~~~~~~~~~~~~~
+
+The ``Makefile`` for the component should be of the following format, where
+``<name>`` corresponds to the name of the library in question, e.g. hash,
+lpm, etc. For drivers, the same format of Makefile is used.
+
+.. code-block:: makefile
+
+	# pull in basic DPDK definitions, including whether library is to be
+	# built or not
+	include $(RTE_SDK)/mk/rte.vars.mk
+
+	# library name
+	LIB = librte_<name>.a
+
+	# any library cflags needed. Generally add "-O3 $(WERROR_FLAGS)"
+	CFLAGS += -O3
+	CFLAGS += $(WERROR_FLAGS)
+
+	# the symbol version information for the library, and .so version
+	EXPORT_MAP := rte_<name>_version.map
+	LIBABIVER := 1
+
+	# all source filenames are stored in SRCS-y
+	SRCS-$(CONFIG_RTE_LIBRTE_<NAME>) += rte_<name>.c
+
+	# install includes
+	SYMLINK-$(CONFIG_RTE_LIBRTE_<NAME>)-include += rte_<name>.h
+
+	# pull in rules to build the library
+	include $(RTE_SDK)/mk/rte.lib.mk
+
+Meson Build File Contents - Libraries
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``meson.build`` file for a new DPDK library should be of the following basic
+format.
+
+.. code-block:: python
+
+	sources = files('file1.c', ...)
+	headers = files('file1.c', ...)
+
+
+The will build based on a number of conventions and assumptions within the DPDK
+itself, for example, that the library name is the same as the directory name in
+which the files are stored.
+
+For a library ``meson.build`` file, there are number of variables which can be
+set, some mandatory, others optional. The mandatory fields are:
+
+sources
+	**Default Value = []**.
+	This variable should list out the files to be compiled up to create the
+	library. Files must be specified using the meson ``files()`` function.
+
+
+The optional fields are:
+
+build
+	**Default Value = true.**
+	Used to optionally compile a library, based on its dependencies or
+	environment. A simple example of use would be:
+
+.. code-block:: python
+
+	if host_machine.system() != 'linux'
+	        build = false
+	endif
+
+
+cflags
+	**Default Value = []**.
+	Used to specify any additional cflags that need to be passed to compile
+	the sources in the library.
+
+deps
+	**Default Value = ['eal']**.
+	Used to list the internal library dependencies of the library. It should
+	be assigned to using ``+=`` rather than overwriting using ``=``.  The
+	dependencies should be specified as strings, each one giving the name of
+	a DPDK library, without the ``librte_`` prefix. Dependencies are handled
+	recursively, so specifying e.g. ``mempool``, will automatically also
+	make the library depend upon the mempool library's dependencies too -
+	``ring`` and ``eal``. For libraries that only depend upon EAL, this
+	variable may be omitted from the ``meson.build`` file.  For example:
+
+.. code-block:: python
+
+	deps += ['ethdev']
+
+
+ext_deps
+	**Default Value = []**.
+	Used to specify external dependencies of this library. They should be
+	returned as dependency objects, as returned from the meson
+	``dependency()`` or ``find_library()`` functions. Before returning
+	these, they should be checked to ensure the dependencies have been
+	found, and, if not, the ``build`` variable should be set to ``false``.
+	For example:
+
+.. code-block:: python
+
+	my_dep = dependency('libX', required: 'false')
+	if my_dep.found()
+		ext_deps += my_dep
+	else
+		build = false
+	endif
+
+
+headers
+	**Default Value = []**.
+	Used to return the list of header files for the library that should be
+	installed to $PREFIX/include when ``ninja install`` is run. As with
+	source files, these should be specified using the meson ``files()``
+	function.
+
+name
+	**Default Value = library name derived from the directory name**.
+	If a library's .so or .a file differs from that given in the directory
+	name, the name should be specified using this variable. In practice,
+	since the convention is that for a library called ``librte_xyz.so``, the
+	sources are stored in a directory ``lib/librte_xyz``, this value should
+	never be needed for new libraries.
+
+.. note::
+
+	The name value also provides the name used to find the function version
+	map file, as part of the build process, so if the directory name and
+	library names differ, the ``version.map`` file should be named
+	consistently with the library, not the directory
+
+objs
+	**Default Value = []**.
+	This variable can be used to pass to the library build some pre-built
+	objects that were compiled up as part of another target given in the
+	included library ``meson.build`` file.
+
+version
+	**Default Value = 1**.
+	Specifies the ABI version of the library, and is used as the major
+	version number of the resulting ``.so`` library.
+
+Meson Build File Contents - Drivers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For drivers, the values are largely the same as for libraries. The variables
+supported are:
+
+build
+	As above.
+
+cflags
+	As above.
+
+deps
+	As above.
+
+ext_deps
+	As above.
+
+includes
+	**Default Value = <driver directory>** Some drivers include a base
+	directory for additional source files and headers, so we have this
+	variable to allow the headers from that base directory to be found when
+	compiling driver sources. Should be appended to using ``+=`` rather than
+	overwritten using ``=``.  The values appended should be meson include
+	objects got using the ``include_directories()`` function. For example:
+
+.. code-block:: python
+
+	includes += include_directories('base')
+
+name
+	As above, though note that each driver class can define it's own naming
+	scheme for the resulting ``.so`` files.
+
+objs
+	As above, generally used for the contents of the ``base`` directory.
+
+pkgconfig_extra_libs
+	**Default Value = []**
+	This variable is used to pass additional library link flags through to
+	the DPDK pkgconfig file generated, for example, to track any additional
+	libraries that may need to be linked into the build - especially when
+	using static libraries. Anything added here will be appended to the end
+	of the ``pkgconfig --libs`` output.
+
+sources [mandatory]
+	As above
+
+version
+	As above
-- 
2.13.5

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] multi-process shared memory on PPC
  2017-09-12  8:12  0%   ` Xueming(Steven) Li
@ 2017-09-12 18:11  0%     ` Xueming(Steven) Li
  2017-09-13  8:56  0%       ` Xueming(Steven) Li
  0 siblings, 1 reply; 200+ results
From: Xueming(Steven) Li @ 2017-09-12 18:11 UTC (permalink / raw)
  To: Xueming(Steven) Li, Chao Zhu; +Cc: dev

It works for me after setting nr_overcommit_hugepages correctly, thanks again.

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Xueming(Steven) Li
> Sent: Tuesday, September 12, 2017 4:13 PM
> To: Chao Zhu <chaozhu@linux.vnet.ibm.com>
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] multi-process shared memory on PPC
> 
> Great, that might be something missing, will update later. Thanks!
> 
> > -----Original Message-----
> > From: Chao Zhu [mailto:chaozhu@linux.vnet.ibm.com]
> > Sent: Tuesday, September 12, 2017 4:02 PM
> > To: Xueming(Steven) Li <xuemingl@mellanox.com>
> > Cc: dev@dpdk.org
> > Subject: RE: multi-process shared memory on PPC
> >
> > Xueming,
> >
> > I tried it on my local server, it works fine.
> > Did you set this value
> > "/sys/kernel/mm/hugepages/hugepages-
> 16384kB/nr_overcommit_hugepages" ?
> > It should be the same value as "
> > /sys/kernel/mm/hugepages/hugepages-16384kB/nr_hugepages" on ppc64le.
> >
> > > -----Original Message-----
> > > From: Xueming(Steven) Li [mailto:xuemingl@mellanox.com]
> > > Sent: 2017年8月31日 22:40
> > > To: Chao Zhu <chaozhu@linux.vnet.ibm.com>
> > > Cc: dev@dpdk.org
> > > Subject: multi-process shared memory on PPC
> > >
> > > Hi all,
> > >
> > > I'm testing multi-process example on PowerPC system, looks like
> > > shared memory not working properly.
> > > Below are the error and debug info of the first multi-process
> > > example 'simple_mp' (works as expected on X86):
> > >
> > > // Build DPDK, master branch
> > > # make T=ppc_64-power8-linuxapp-gcc -j160 -C
> > > examples/multi_process/simple_mp/ #
> > > examples/multi_process/simple_mp/build/simple_mp  -w 0:0.0
> > > --proc-type=primary -l 1-2 --socket-mem
> > > 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> > > APP: Finished Process Init.
> > > Starting core 2
> > > simple_mp >
> > >
> > > // Open another terminal and run secondary process # gdb --args
> > > examples/multi_process/simple_mp/build/simple_mp -n 4 -w 0:0.0
> > > --proc-type=secondary -l 3-4 --socket-mem
> > > 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> > > GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1 Copyright (C) 2016
> > > Free Software Foundation, Inc.
> > > License GPLv3+: GNU GPL version 3 or later
> > >
> > <https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fur
> > ldef
> > ense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> >
> 3A__gnu.org_licenses_gpl&data=02%7C01%7Cxuemingl%40mellanox.com%7C
> >
> 9cd11fda7a7f48df7cbd08d4f9b486d8%7Ca652971c7d2e4d9ba6a4d149256f461
> >
> b%7C0%7C0%7C636408001138751301&sdata=bb3hwYz7ehCqt4QA6GGqTDMY
> > kY1qAJV%2BCMDBVbXmWzE%3D&reserved=0.
> > h
> > > tml&d=DwIFAg&c=jf_iaSHvJObTbx-
> > siA1ZOg&r=4TYe4NpqlgVi0ArYpZ76FrWp7IE
> > > w8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-
> 6aTY_jEvDZtMZR0o&s
> > > =SbDQBN7qJ9z8fWCSePyvm5FFncp2P_9XZm-qs1lH5PE&e= > This is free
> > > software: you are free to change and redistribute it.
> > > There is NO WARRANTY, to the extent permitted by law.  Type "show
> > copying"
> > > and "show warranty" for details.
> > > This GDB was configured as "powerpc64le-linux-gnu".
> > > Type "show configuration" for configuration details.
> > > For bug reporting instructions, please see:
> > > <https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2F
> > > ur
> > > ldefense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> > 3A__www.gnu.org_softwar&
> > >
> >
> data=02%7C01%7Cxuemingl%40mellanox.com%7C9cd11fda7a7f48df7cbd08d4f
> > 9b48
> > >
> >
> 6d8%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C63640800113875
> > 1301&sd
> > >
> >
> ata=4DNDTyIcHpTIU60K7FM%2F1zuASSB1IdZDRyOaiVp1Y%2BY%3D&reserved=
> > 0
> > > e_gdb_bugs_&d=DwIFAg&c=jf_iaSHvJObTbx-
> > siA1ZOg&r=4TYe4NpqlgVi0ArYpZ
> > > 76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-
> > 6aTY_jEvDZt
> > > MZR0o&s=GAFKK3jSahAPFXMGcPGbVNTl0CesJy_qfs5TxXfGOX0&e= >.
> > > Find the GDB manual and other documentation resources online at:
> > > <https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2F
> > > ur
> > > ldefense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> > 3A__www.gnu.org_softwar&
> > >
> >
> data=02%7C01%7Cxuemingl%40mellanox.com%7C9cd11fda7a7f48df7cbd08d4f
> > 9b48
> > >
> >
> 6d8%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C63640800113875
> > 1301&sd
> > >
> >
> ata=4DNDTyIcHpTIU60K7FM%2F1zuASSB1IdZDRyOaiVp1Y%2BY%3D&reserved=
> > 0
> > > e_gdb_documentation_&d=DwIFAg&c=jf_iaSHvJObTbx-
> > siA1ZOg&r=4TYe4Npql
> > >
> gVi0ArYpZ76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-
> > 6a
> > > TY_jEvDZtMZR0o&s=JdkMMjGGl-
> > 3Z3BGnjCkOFP5lI5BIbRNBxH4EVI70YFc&e= > .
> > > For help, type "help".
> > > Type "apropos word" to search for commands related to "word"...
> > > Reading symbols from
> > > examples/multi_process/simple_mp/build/simple_mp...done.
> > > (gdb) r
> > > Starting program:
> > > /home/xueming/mlnx-
> > dpdk.org/examples/multi_process/simple_mp/build/sim
> > > ple_mp -n 4 -w 0:0.0 --proc-type=secondary -l 3-4 --socket-mem
> > > 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> > > [Thread debugging using libthread_db enabled] Using host
> > > libthread_db
> > library
> > > "/lib/powerpc64le-linux-gnu/libthread_db.so.1".
> > > EAL: Detected 144 lcore(s)
> > > EAL: Probing VFIO support...
> > > [New Thread 0x7ffff7a6eff0 (LWP 58811)] [New Thread 0x7ffff726eff0
> > > (LWP 58812)]
> > >
> > > Thread 1 "simple_mp" received signal SIGSEGV, Segmentation fault.
> > > 0x00007ffff7d2f3ec in ?? () from
> > > /lib/powerpc64le-linux-gnu/libc.so.6
> > >  (gdb) bt full
> > > #0  0x00007ffff7d2f3ec in ?? () from
> > > /lib/powerpc64le-linux-gnu/libc.so.6
> > > No symbol table info available.
> > > #1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28
> > > "PRI_2_SEC")
> > >     at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
> > >         te = 0x7ef3eefd5e00
> > >         r = 0x0
> > >         ring_list = 0x7ffff7aa250c
> > > #2  0x0000000010032640 in main (argc=10, argv=0x7ffffffff3e8)
> > >     at
> > > /home/xueming/mlnx-
> > dpdk.org/examples/multi_process/simple_mp/main.c:12
> > > 8
> > >         flags = 0
> > >         ring_size = 64
> > >         pool_size = 1024
> > >         pool_cache = 32
> > >         priv_data_sz = 0
> > >         ret = 9
> > >         lcore_id = 32767
> > >         cl = 0x7ffff7fef718 <_dl_argv>
> > > (gdb) f 1
> > > #1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28
> > > "PRI_2_SEC")
> > >     at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
> > > 326                     if (strncmp(name, r->name,
> > > RTE_RING_NAMESIZE) == 0)
> > > (gdb) l
> > > 321
> > > 322             rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
> > > 323
> > > 324             TAILQ_FOREACH(te, ring_list, next) {
> > > 325                     r = (struct rte_ring *) te->data;
> > > 326                     if (strncmp(name, r->name,
> > > RTE_RING_NAMESIZE) == 0)
> > > 327                             break;
> > > 328             }
> > > 329
> > > 330             rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
> > > (gdb) p *te
> > > $1 = {next = {tqe_next = 0x0, tqe_prev = 0x0}, data = 0x0}
> > > (gdb) p *ring_list
> > > $2 = {tqh_first = 0x7ef3eefd5e00, tqh_last = 0x7ef3eec6d100}
> > >
> > > # uname -a
> > > Linux dragon-power-01 4.13.0-rc2 #1 SMP Tue Aug 29 17:27:05 IDT 2017
> > > ppc64le ppc64le ppc64le GNU/Linux
> > >
> > > # cat /etc/issue
> > > Ubuntu 16.04.2 LTS \n \l
> > >
> > > # gcc --version
> > > gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 Copyright (C)
> > > 2015 Free Software Foundation, Inc.
> > > This is free software; see the source for copying conditions.  There
> > > is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
> > > PARTICULAR PURPOSE.
> > >
> > > # lscpu
> > > Architecture:          ppc64le
> > > Byte Order:            Little Endian
> > > CPU(s):                144
> > > On-line CPU(s) list:   0-87,96-103,112-159
> > > Thread(s) per core:    8
> > > Core(s) per socket:    4
> > > Socket(s):             4
> > > NUMA node(s):          4
> > > Model:                 2.1 (pvr 004b 0201)
> > > Model name:            POWER8E (raw), altivec supported
> > > CPU max MHz:           3690.0000
> > > CPU min MHz:           2061.0000
> > > L1d cache:             64K
> > > L1i cache:             32K
> > > L2 cache:              512K
> > > L3 cache:              8192K
> > > NUMA node0 CPU(s):     0-39
> > > NUMA node1 CPU(s):     40-79
> > > NUMA node16 CPU(s):    80-87,96-103,112-119
> > > NUMA node17 CPU(s):    120-159
> > >
> > > # cat build/.config
> > > # RTE_EXEC_ENV values are the directories in mk/exec-env/
> > > CONFIG_RTE_EXEC_ENV="linuxapp"
> > > # RTE_ARCH values are architecture we compile for. directories in
> > > mk/arch/ CONFIG_RTE_ARCH="ppc_64"
> > > # machine can define specific variables or action for a specific
> > > board # RTE_MACHINE values are architecture we compile for.
> > > directories in mk/machine/ CONFIG_RTE_MACHINE="power8"
> > > # The compiler we use.
> > > # RTE_TOOLCHAIN values are architecture we compile for. directories
> > > in mk/toolchain/ CONFIG_RTE_TOOLCHAIN="gcc"
> > > # Use intrinsics or assembly code for key routines
> > > CONFIG_RTE_FORCE_INTRINSICS=n # Machine forces strict alignment
> > > constraints.
> > > CONFIG_RTE_ARCH_STRICT_ALIGN=n
> > > # Compile to share library
> > > CONFIG_RTE_BUILD_SHARED_LIB=n
> > > # Use newest code breaking previous ABI CONFIG_RTE_NEXT_ABI=y #
> > > Major ABI to overwrite library specific LIBABIVER
> > > CONFIG_RTE_MAJOR_ABI= # Machine's cache line size
> > > CONFIG_RTE_CACHE_LINE_SIZE=128
> > > # Compile Environment Abstraction Layer CONFIG_RTE_LIBRTE_EAL=y
> > > CONFIG_RTE_MAX_LCORE=256
> > > CONFIG_RTE_MAX_NUMA_NODES=32
> > > CONFIG_RTE_MAX_MEMSEG=256
> > > CONFIG_RTE_MAX_MEMZONE=2560
> > > CONFIG_RTE_MAX_TAILQ=32
> > > CONFIG_RTE_LOG_LEVEL=RTE_LOG_INFO
> > > CONFIG_RTE_LOG_DP_LEVEL=RTE_LOG_INFO
> > > CONFIG_RTE_LOG_HISTORY=256
> > > CONFIG_RTE_BACKTRACE=y
> > > CONFIG_RTE_LIBEAL_USE_HPET=n
> > > CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID=n
> > > CONFIG_RTE_EAL_ALWAYS_PANIC_ON_ERROR=n
> > > CONFIG_RTE_EAL_IGB_UIO=y
> > > CONFIG_RTE_EAL_VFIO=y
> > > CONFIG_RTE_MALLOC_DEBUG=n
> > > CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES=y
> > > # Recognize/ignore architecture we compile for. AVX/AVX512 CPU flags
> > > for performance/power testing.
> > > # AVX512 is marked as experimental for now, will enable it after
> > > enough #
> > field
> > > test and possible optimization.
> > > CONFIG_RTE_ENABLE_AVX=y
> > > CONFIG_RTE_ENABLE_AVX512=n
> > > # Default driver path (or "" to disable) CONFIG_RTE_EAL_PMD_PATH=""
> > > # Compile Environment Abstraction Layer to support Vmware TSC map
> > > CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=n
> > > # Compile architecture we compile for. argument parser library
> > > CONFIG_RTE_LIBRTE_KVARGS=y # Compile generic ethernet library
> > > CONFIG_RTE_LIBRTE_ETHER=y CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n
> > > CONFIG_RTE_MAX_ETHPORTS=32
> > > CONFIG_RTE_MAX_QUEUES_PER_PORT=1024
> > > CONFIG_RTE_LIBRTE_IEEE1588=n
> > > CONFIG_RTE_ETHDEV_QUEUE_STAT_CNTRS=16
> > > CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y
> > > # Turn off Tx preparation stage
> > > # Warning: rte_eth_tx_prepare() can be safely disabled only if using
> > > a #
> > driver
> > > which do not implement any Tx preparation.
> > > CONFIG_RTE_ETHDEV_TX_PREPARE_NOOP=n
> > > # Compile burst-oriented Amazon ENA PMD driver
> > > CONFIG_RTE_LIBRTE_ENA_PMD=y
> CONFIG_RTE_LIBRTE_ENA_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_ENA_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_ENA_DEBUG_TX_FREE=n
> > > CONFIG_RTE_LIBRTE_ENA_DEBUG_DRIVER=n
> > > CONFIG_RTE_LIBRTE_ENA_COM_DEBUG=n
> > > # Compile burst-oriented IGB & EM PMD drivers
> > > CONFIG_RTE_LIBRTE_EM_PMD=y CONFIG_RTE_LIBRTE_IGB_PMD=y
> > > CONFIG_RTE_LIBRTE_E1000_DEBUG_INIT=n
> > > CONFIG_RTE_LIBRTE_E1000_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_E1000_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_E1000_DEBUG_TX_FREE=n
> > > CONFIG_RTE_LIBRTE_E1000_DEBUG_DRIVER=n
> > > CONFIG_RTE_LIBRTE_E1000_PF_DISABLE_STRIP_CRC=n
> > > # Compile burst-oriented IXGBE PMD driver
> > > CONFIG_RTE_LIBRTE_IXGBE_PMD=n
> > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_INIT=n
> > > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX_FREE=n
> > > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_DRIVER=n
> > > CONFIG_RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC=n
> > > CONFIG_RTE_IXGBE_INC_VECTOR=y
> > > CONFIG_RTE_LIBRTE_IXGBE_BYPASS=n
> > > # Compile burst-oriented I40E PMD driver
> > > CONFIG_RTE_LIBRTE_I40E_PMD=y
> CONFIG_RTE_LIBRTE_I40E_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_I40E_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_I40E_DEBUG_TX_FREE=n
> > > CONFIG_RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC=y
> > > CONFIG_RTE_LIBRTE_I40E_INC_VECTOR=y
> > > CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n
> > > CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF=64
> > > CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF=4
> > > CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM=4
> > > # interval up to 8160 us, aligned to 2 (or default value)
> > > CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL=-1
> > > # Compile burst-oriented FM10K PMD
> > > CONFIG_RTE_LIBRTE_FM10K_PMD=n
> > > CONFIG_RTE_LIBRTE_FM10K_DEBUG_INIT=n
> > > CONFIG_RTE_LIBRTE_FM10K_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX_FREE=n
> > > CONFIG_RTE_LIBRTE_FM10K_DEBUG_DRIVER=n
> > > CONFIG_RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE=y
> > > CONFIG_RTE_LIBRTE_FM10K_INC_VECTOR=y
> > > # Compile burst-oriented Mellanox ConnectX-3 (MLX4) PMD
> > > CONFIG_RTE_LIBRTE_MLX4_PMD=n CONFIG_RTE_LIBRTE_MLX4_DEBUG=n
> > > CONFIG_RTE_LIBRTE_MLX4_DEBUG_BROKEN_VERBS=n
> > > CONFIG_RTE_LIBRTE_MLX4_SGE_WR_N=4
> > > CONFIG_RTE_LIBRTE_MLX4_MAX_INLINE=0
> > > CONFIG_RTE_LIBRTE_MLX4_TX_MP_CACHE=8
> > > CONFIG_RTE_LIBRTE_MLX4_SOFT_COUNTERS=1
> > > # Compile burst-oriented Mellanox ConnectX-4 & ConnectX-5 (MLX5) PMD
> > > CONFIG_RTE_LIBRTE_MLX5_PMD=y CONFIG_RTE_LIBRTE_MLX5_DEBUG=n
> > > CONFIG_RTE_LIBRTE_MLX5_TX_MP_CACHE=8
> > > # Compile burst-oriented Broadcom PMD driver
> > > CONFIG_RTE_LIBRTE_BNX2X_PMD=n
> CONFIG_RTE_LIBRTE_BNX2X_DEBUG=n
> > > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_INIT=n
> > > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_BNX2X_MF_SUPPORT=n
> > > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_PERIODIC=n
> > > # Compile burst-oriented Chelsio Terminator (CXGBE) PMD
> > > CONFIG_RTE_LIBRTE_CXGBE_PMD=y
> > CONFIG_RTE_LIBRTE_CXGBE_DEBUG=n
> > > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_REG=n
> > > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_MBOX=n
> > > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_CXGBE_TPUT=y
> > > # Compile burst-oriented Cisco ENIC PMD driver
> > > CONFIG_RTE_LIBRTE_ENIC_PMD=n CONFIG_RTE_LIBRTE_ENIC_DEBUG=n
> > > CONFIG_RTE_LIBRTE_ENIC_DEBUG_FLOW=n
> > > # Compile burst-oriented Netronome NFP PMD driver
> > > CONFIG_RTE_LIBRTE_NFP_PMD=y CONFIG_RTE_LIBRTE_NFP_DEBUG=n #
> > Compile
> > > burst-oriented Broadcom BNXT PMD driver
> > CONFIG_RTE_LIBRTE_BNXT_PMD=y #
> > > Compile burst-oriented Solarflare libefx-based PMD
> > > CONFIG_RTE_LIBRTE_SFC_EFX_PMD=n
> > CONFIG_RTE_LIBRTE_SFC_EFX_DEBUG=n #
> > > Compile software PMD backed by
> > > SZEDATA2 device CONFIG_RTE_LIBRTE_PMD_SZEDATA2=n # Defines
> > firmware
> > > type address space.
> > > # See documentation for supported values.
> > > # Other values raise compile time error.
> > > CONFIG_RTE_LIBRTE_PMD_SZEDATA2_AS=0
> > > # Compile burst-oriented Cavium Thunderx NICVF PMD driver
> > > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD=y
> > > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_INIT=n
> > > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_DRIVER=n
> > > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_MBOX=n
> > > # Compile burst-oriented Cavium LiquidIO PMD driver
> > > CONFIG_RTE_LIBRTE_LIO_PMD=y
> > CONFIG_RTE_LIBRTE_LIO_DEBUG_DRIVER=n
> > > CONFIG_RTE_LIBRTE_LIO_DEBUG_INIT=n
> > > CONFIG_RTE_LIBRTE_LIO_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_LIO_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_LIO_DEBUG_MBOX=n
> > > CONFIG_RTE_LIBRTE_LIO_DEBUG_REGS=n
> > > # Compile NXP DPAA2 FSL-MC Bus
> > > CONFIG_RTE_LIBRTE_FSLMC_BUS=n
> > > # Compile Support Libraries for NXP DPAA2
> > > CONFIG_RTE_LIBRTE_DPAA2_MEMPOOL=n
> > > CONFIG_RTE_LIBRTE_DPAA2_USE_PHYS_IOVA=y
> > > # Compile burst-oriented NXP DPAA2 PMD driver
> > > CONFIG_RTE_LIBRTE_DPAA2_PMD=n
> > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_INIT=n
> > > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_DRIVER=n
> > > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX_FREE=n
> > > # Compile burst-oriented VIRTIO PMD driver
> > > CONFIG_RTE_LIBRTE_VIRTIO_PMD=y
> > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_INIT=n
> > > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DRIVER=n
> > > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DUMP=n
> > > # Compile virtio device emulation inside virtio PMD driver
> > > CONFIG_RTE_VIRTIO_USER=y # Compile burst-oriented VMXNET3 PMD
> > driver
> > > CONFIG_RTE_LIBRTE_VMXNET3_PMD=n
> > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_INIT=n
> > > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX_FREE=n
> > > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_DRIVER=n
> > > # Compile example software rings based PMD
> > > CONFIG_RTE_LIBRTE_PMD_RING=y
> > > CONFIG_RTE_PMD_RING_MAX_RX_RINGS=16
> > > CONFIG_RTE_PMD_RING_MAX_TX_RINGS=16
> > > # Compile software PMD backed by PCAP files
> > > CONFIG_RTE_LIBRTE_PMD_PCAP=n # Compile link bonding PMD library
> > > CONFIG_RTE_LIBRTE_PMD_BOND=y
> > CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB=n
> > > CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB_L1=n
> > > # QLogic 10G/25G/40G/50G/100G PMD
> > > CONFIG_RTE_LIBRTE_QEDE_PMD=y
> > > CONFIG_RTE_LIBRTE_QEDE_DEBUG_INIT=n
> > > CONFIG_RTE_LIBRTE_QEDE_DEBUG_INFO=n
> > > CONFIG_RTE_LIBRTE_QEDE_DEBUG_DRIVER=n
> > > CONFIG_RTE_LIBRTE_QEDE_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_QEDE_DEBUG_RX=n
> > > #Provides abs path/name of architecture we compile for. firmware file.
> > > #Empty string denotes driver will use default firmware
> > > CONFIG_RTE_LIBRTE_QEDE_FW=""
> > > # Compile software PMD backed by AF_PACKET sockets (Linux only)
> > > CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y # Compile ARK PMD
> > > CONFIG_RTE_LIBRTE_ARK_PMD=y CONFIG_RTE_LIBRTE_ARK_PAD_TX=y
> > > CONFIG_RTE_LIBRTE_ARK_DEBUG_RX=n
> > CONFIG_RTE_LIBRTE_ARK_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_ARK_DEBUG_STATS=n
> > > CONFIG_RTE_LIBRTE_ARK_DEBUG_TRACE=n
> > > # Compile WRS accelerated virtual port (AVP) guest PMD driver
> > > CONFIG_RTE_LIBRTE_AVP_PMD=n
> CONFIG_RTE_LIBRTE_AVP_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_AVP_DEBUG_TX=n
> > CONFIG_RTE_LIBRTE_AVP_DEBUG_DRIVER=y
> > > CONFIG_RTE_LIBRTE_AVP_DEBUG_BUFFERS=n
> > > # Compile architecture we compile for. TAP PMD # It is enabled by
> > > default
> > for
> > > Linux only.
> > > CONFIG_RTE_LIBRTE_PMD_TAP=y
> > > # Compile Xen PMD
> > > CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
> > > # Compile null PMD
> > > CONFIG_RTE_LIBRTE_PMD_NULL=y
> > > # Compile fail-safe PMD
> > > CONFIG_RTE_LIBRTE_PMD_FAILSAFE=y
> > > # Do prefetch of packet data within PMD driver receive function
> > > CONFIG_RTE_PMD_PACKET_PREFETCH=y # Compile generic crypto device
> > > library CONFIG_RTE_LIBRTE_CRYPTODEV=y
> > > CONFIG_RTE_LIBRTE_CRYPTODEV_DEBUG=n
> > > CONFIG_RTE_CRYPTO_MAX_DEVS=64
> > > CONFIG_RTE_CRYPTODEV_NAME_LEN=64
> > > # Compile PMD for ARMv8 Crypto device
> > > CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO=n
> > > CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO_DEBUG=n
> > > # Compile NXP DPAA2 crypto sec driver for CAAM HW
> > > CONFIG_RTE_LIBRTE_PMD_DPAA2_SEC=n
> > > CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_INIT=n
> > > CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_DRIVER=n
> > > CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_RX=n
> > > # Compile PMD for QuickAssist based devices
> > > CONFIG_RTE_LIBRTE_PMD_QAT=n
> > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_INIT=n
> > > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_DRIVER=n
> > > # Number of sessions to create in architecture we compile for.
> > > session
> > memory
> > > pool # on a single QuickAssist device.
> > > CONFIG_RTE_QAT_PMD_MAX_NB_SESSIONS=2048
> > > # Compile PMD for AESNI backed device
> > > CONFIG_RTE_LIBRTE_PMD_AESNI_MB=n
> > > CONFIG_RTE_LIBRTE_PMD_AESNI_MB_DEBUG=n
> > > # Compile PMD for Software backed device
> > > CONFIG_RTE_LIBRTE_PMD_OPENSSL=n
> > CONFIG_RTE_LIBRTE_PMD_OPENSSL_DEBUG=n
> > > # Compile PMD for AESNI GCM device
> > > CONFIG_RTE_LIBRTE_PMD_AESNI_GCM=n
> > > CONFIG_RTE_LIBRTE_PMD_AESNI_GCM_DEBUG=n
> > > # Compile PMD for SNOW 3G device
> > > CONFIG_RTE_LIBRTE_PMD_SNOW3G=n
> > > CONFIG_RTE_LIBRTE_PMD_SNOW3G_DEBUG=n
> > > # Compile PMD for KASUMI device
> > > CONFIG_RTE_LIBRTE_PMD_KASUMI=n
> > > CONFIG_RTE_LIBRTE_PMD_KASUMI_DEBUG=n
> > > # Compile PMD for ZUC device
> > > CONFIG_RTE_LIBRTE_PMD_ZUC=n
> > > CONFIG_RTE_LIBRTE_PMD_ZUC_DEBUG=n
> > > # Compile PMD for Crypto Scheduler device
> > > CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER=y
> > > CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER_DEBUG=n
> > > # Compile PMD for NULL Crypto device
> > > CONFIG_RTE_LIBRTE_PMD_NULL_CRYPTO=y
> > > # Compile generic event device library CONFIG_RTE_LIBRTE_EVENTDEV=y
> > > CONFIG_RTE_LIBRTE_EVENTDEV_DEBUG=n
> > > CONFIG_RTE_EVENT_MAX_DEVS=16
> > > CONFIG_RTE_EVENT_MAX_QUEUES_PER_DEV=64
> > > # Compile PMD for skeleton event device
> > > CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV=y
> > > CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV_DEBUG=n
> > > # Compile PMD for software event device
> > > CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV=y
> > > CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV_DEBUG=n
> > > # Compile PMD for octeontx sso event device
> > > CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF=y
> > > CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF_DEBUG=n
> > > # Compile librte_ring
> > > CONFIG_RTE_LIBRTE_RING=y
> > > # Compile librte_mempool
> > > CONFIG_RTE_LIBRTE_MEMPOOL=y
> > > CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE=512
> > > CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG=n
> > > # Compile Mempool drivers
> > > CONFIG_RTE_DRIVER_MEMPOOL_RING=y
> > > CONFIG_RTE_DRIVER_MEMPOOL_STACK=y
> > > # Compile librte_mbuf
> > > CONFIG_RTE_LIBRTE_MBUF=y
> > > CONFIG_RTE_LIBRTE_MBUF_DEBUG=n
> > > CONFIG_RTE_MBUF_DEFAULT_MEMPOOL_OPS="ring_mp_mc"
> > > CONFIG_RTE_MBUF_REFCNT_ATOMIC=y
> > > CONFIG_RTE_PKTMBUF_HEADROOM=128
> > > # Compile librte_timer
> > > CONFIG_RTE_LIBRTE_TIMER=y
> > > CONFIG_RTE_LIBRTE_TIMER_DEBUG=n
> > > # Compile librte_cfgfile
> > > CONFIG_RTE_LIBRTE_CFGFILE=y
> > > # Compile librte_cmdline
> > > CONFIG_RTE_LIBRTE_CMDLINE=y
> > > CONFIG_RTE_LIBRTE_CMDLINE_DEBUG=n
> > > # Compile librte_hash
> > > CONFIG_RTE_LIBRTE_HASH=y
> > > CONFIG_RTE_LIBRTE_HASH_DEBUG=n
> > > # Compile librte_efd
> > > CONFIG_RTE_LIBRTE_EFD=y
> > > # Compile librte_jobstats
> > > CONFIG_RTE_LIBRTE_JOBSTATS=y
> > > # Compile architecture we compile for. device metrics library
> > > CONFIG_RTE_LIBRTE_METRICS=y # Compile architecture we compile for.
> > > bitrate statistics library CONFIG_RTE_LIBRTE_BITRATE=y # Compile
> > > architecture we compile for. latency statistics library
> > > CONFIG_RTE_LIBRTE_LATENCY_STATS=y # Compile librte_lpm
> > > CONFIG_RTE_LIBRTE_LPM=y CONFIG_RTE_LIBRTE_LPM_DEBUG=n #
> > Compile
> > > librte_acl CONFIG_RTE_LIBRTE_ACL=y
> CONFIG_RTE_LIBRTE_ACL_DEBUG=n
> > #
> > > Compile librte_power CONFIG_RTE_LIBRTE_POWER=y
> > > CONFIG_RTE_LIBRTE_POWER_DEBUG=n
> > > CONFIG_RTE_MAX_LCORE_FREQS=64
> > > # Compile librte_net
> > > CONFIG_RTE_LIBRTE_NET=y
> > > # Compile librte_ip_frag
> > > CONFIG_RTE_LIBRTE_IP_FRAG=y
> > > CONFIG_RTE_LIBRTE_IP_FRAG_DEBUG=n
> > > CONFIG_RTE_LIBRTE_IP_FRAG_MAX_FRAG=4
> > > CONFIG_RTE_LIBRTE_IP_FRAG_TBL_STAT=n
> > > # Compile GRO library
> > > CONFIG_RTE_LIBRTE_GRO=y
> > > # Compile librte_meter
> > > CONFIG_RTE_LIBRTE_METER=y
> > > # Compile librte_sched
> > > CONFIG_RTE_LIBRTE_SCHED=y
> > > CONFIG_RTE_SCHED_DEBUG=n
> > > CONFIG_RTE_SCHED_RED=n
> > > CONFIG_RTE_SCHED_COLLECT_STATS=n
> > > CONFIG_RTE_SCHED_SUBPORT_TC_OV=n
> > > CONFIG_RTE_SCHED_PORT_N_GRINDERS=8
> > > CONFIG_RTE_SCHED_VECTOR=n
> > > # Compile architecture we compile for. distributor library
> > > CONFIG_RTE_LIBRTE_DISTRIBUTOR=y # Compile architecture we compile
> for.
> > > reorder library CONFIG_RTE_LIBRTE_REORDER=y # Compile librte_port
> > > CONFIG_RTE_LIBRTE_PORT=y CONFIG_RTE_PORT_STATS_COLLECT=n
> > > CONFIG_RTE_PORT_PCAP=n # Compile librte_table
> > > CONFIG_RTE_LIBRTE_TABLE=y CONFIG_RTE_TABLE_STATS_COLLECT=n #
> > Compile
> > > librte_pipeline CONFIG_RTE_LIBRTE_PIPELINE=y
> > > CONFIG_RTE_PIPELINE_STATS_COLLECT=n
> > > # Compile librte_kni
> > > CONFIG_RTE_LIBRTE_KNI=y
> > > CONFIG_RTE_LIBRTE_PMD_KNI=y
> > > CONFIG_RTE_KNI_KMOD=y
> > > CONFIG_RTE_KNI_KMOD_ETHTOOL=n
> > > CONFIG_RTE_KNI_PREEMPT_DEFAULT=y
> > > # Compile architecture we compile for. pdump library
> > > CONFIG_RTE_LIBRTE_PDUMP=y # Compile vhost user library
> > > CONFIG_RTE_LIBRTE_VHOST=y CONFIG_RTE_LIBRTE_VHOST_NUMA=y
> > > CONFIG_RTE_LIBRTE_VHOST_DEBUG=n # Compile vhost PMD # To compile,
> > > CONFIG_RTE_LIBRTE_VHOST should be enabled.
> > > CONFIG_RTE_LIBRTE_PMD_VHOST=y
> > > #Compile Xen domain0 support
> > > CONFIG_RTE_LIBRTE_XEN_DOM0=n
> > > # Compile architecture we compile for. test application
> > > CONFIG_RTE_APP_TEST=y CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
> > > # Compile architecture we compile for. PMD test application
> > > CONFIG_RTE_TEST_PMD=y
> > CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
> > > CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
> > > # Compile architecture we compile for. crypto performance
> > > application CONFIG_RTE_APP_CRYPTO_PERF=y # Compile architecture we
> compile for.
> > > eventdev application CONFIG_RTE_APP_EVENTDEV=y
> > > CONFIG_RTE_EXEC_ENV_LINUXAPP=y CONFIG_RTE_ARCH_PPC_64=y
> > > CONFIG_RTE_ARCH_64=y CONFIG_RTE_TOOLCHAIN_GCC=y # Note: Power
> > doesn't
> > > have this support # Note: Initially, all of architecture we
> > compile for.
> > > PMD drivers compilation are turned off on Power # Will turn on them
> > > only
> > after
> > > architecture we compile for. successful testing on Power
> > >
> > > Please refer here for more information on running DPDK multi-process
> > > examples:
> > >
> > > https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fu
> > > rl
> > > defense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> > 3A__dpdk.org_doc_guides_s
> > >
> >
> &data=02%7C01%7Cxuemingl%40mellanox.com%7C9cd11fda7a7f48df7cbd08d
> > 4f9b4
> > >
> >
> 86d8%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C6364080011387
> > 51301&s
> > >
> data=4n76ha0PmSr3wP2c0MAo3PEVYRMKjJVcU9o5xETqhBc%3D&reserved=0
> > > ample-5Fapp-5Fug_multi-5Fprocess.html&d=DwIFAg&c=jf_iaSHvJObTbx-
> > siA1Z
> > >
> >
> Og&r=4TYe4NpqlgVi0ArYpZ76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwu
> > > uryoN7QPg9N-6aTY_jEvDZtMZR0o&s=gupwe5WWQ-
> > ap2jObFko6UJymrcy4jTmF
> > > 2r1dZ2fQN9E&e=
> > >
> > > Best Regards,
> > > Xueming
> >


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3 1/4] ethdev: increase port_id range
  2017-09-11 10:21  4%     ` Ferruh Yigit
@ 2017-09-13  2:26  0%       ` Yang, Zhiyong
  2017-09-14 12:49  4%         ` Ferruh Yigit
  0 siblings, 1 reply; 200+ results
From: Yang, Zhiyong @ 2017-09-13  2:26 UTC (permalink / raw)
  To: Yigit, Ferruh, dev, Doherty, Declan, Lu, Wenzhuo
  Cc: thomas, hemant.agrawal, Hunt, David, Richardson, Bruce, Ananyev,
	Konstantin

Hi Ferruh,

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Monday, September 11, 2017 6:22 PM
> To: Yang, Zhiyong <zhiyong.yang@intel.com>; dev@dpdk.org; Doherty, Declan
> <declan.doherty@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>
> Cc: thomas@monjalon.net; hemant.agrawal@nxp.com; Hunt, David
> <david.hunt@intel.com>
> Subject: Re: [PATCH v3 1/4] ethdev: increase port_id range
> 
> On 9/9/2017 3:47 PM, Zhiyong Yang wrote:
> > Extend port_id definition from uint8_t to uint16_t in lib and drivers
> > data structures, specifically rte_eth_dev_data.
> > Modify the APIs, drivers and app using port_id at the same time.
> >
> > Fix some checkpatch issues from the original code and remove some
> > unnecessary cast operations.
> >
> > Signed-off-by: Zhiyong Yang <zhiyong.yang@intel.com>
> 
> <...>
> 
> > @@ -283,7 +283,7 @@ enum dcb_mode_enable  #define
> > MAX_RX_QUEUE_STATS_MAPPINGS 4096 /* MAX_PORT of 32 @ 128
> > rx_queues/port */
> >
> >  struct queue_stats_mappings {
> > -	uint8_t port_id;
> > +	uint16_t port_id;
> 
> Can this be "portid_t port_id;" ? For testpmd, portid_t can be used for all port_id
> declarations.
> 

Ferruh, the suggestion has been discussed in the following thread. Most of people agree on
The basic type uint16_t. :).  Your suggestion was my preference  previously.
At last, I make this decision to use uint16_t.  You know, whatever I use, some ones will stand out and
Say the other is better.  :)
http://www.dpdk.org/dev/patchwork/patch/23208/

> <...>
> 
> > --- a/drivers/net/bnx2x/bnx2x.c
> > +++ b/drivers/net/bnx2x/bnx2x.c
> > @@ -703,7 +703,7 @@ bnx2x_gpio_mult_write(struct bnx2x_softc *sc,
> > uint8_t pins, uint32_t mode)
> >
> >  static int
> >  bnx2x_gpio_int_write(struct bnx2x_softc *sc, int gpio_num, uint32_t mode,
> > -		   uint8_t port)
> > +		      uint8_t port)
> 
> If port storage type will not change, no need to update this line. It is good to fix
> syntax the lines touched, but for the lines not updated please don't fix the syntax
> in this patch.

Ok
> 
> >  {
> >  	/* The GPIO should be swapped if swap register is set and active */
> >  	int gpio_port = ((REG_RD(sc, NIG_REG_PORT_SWAP) && @@ -749,7
> +749,7
> > @@ bnx2x_gpio_int_write(struct bnx2x_softc *sc, int gpio_num, uint32_t
> > mode,  }
> >
> >  uint32_t
> > -elink_cb_gpio_read(struct bnx2x_softc * sc, uint16_t gpio_num,
> > uint8_t port)
> > +elink_cb_gpio_read(struct bnx2x_softc *sc, uint16_t gpio_num, uint8_t
> > +port)
> 
> Same here.

Ok.

> 
> >  {
> >  	return bnx2x_gpio_read(sc, gpio_num, port);  } diff --git
> > a/drivers/net/bnx2x/bnx2x_rxtx.h b/drivers/net/bnx2x/bnx2x_rxtx.h
> > index 2e38ec26a..48d540476 100644
> > --- a/drivers/net/bnx2x/bnx2x_rxtx.h
> > +++ b/drivers/net/bnx2x/bnx2x_rxtx.h
> > @@ -41,7 +41,7 @@ struct bnx2x_rx_queue {
> >  	uint16_t                   rx_cq_head;           /**< Index of current rcq bd. */
> >  	uint16_t                   rx_cq_tail;           /**< Index of last rcq bd. */
> >  	uint16_t                   queue_id;             /**< RX queue index. */
> > -	uint8_t                    port_id;              /**< Device port identifier. */
> > +	uint16_t                   port_id;	/**< Device port identifier. */
> 
> Please fix comment allignment.
> 

Ok.

> >  	struct bnx2x_softc           *sc;                  /**< Ptr to dev_private data. */
> >  };
> 
> <...>
> 
> > @@ -500,7 +501,7 @@ elink_status_t elink_phy_probe(struct elink_params
> > *params);
> >
> >  /* Checks if fan failure detection is required on one of the phys on
> > board */  uint8_t elink_fan_failure_det_req(struct bnx2x_softc *sc, uint32_t
> shmem_base,
> > -			     uint32_t shmem2_base, uint8_t port);
> > +				  uint32_t shmem2_base, uint8_t port);
> 
> no change, please drop.
> 

Ok

> <...>
> 
> > @@ -511,7 +511,6 @@ mux_machine(struct bond_dev_private *internals,
> uint8_t slave_id)
> >  		ACTOR_STATE_CLR(port, SYNCHRONIZATION);
> >  		MODE4_DEBUG("Out of sync -> ATTACHED\n");
> >  	}
> > -
> 
> Please drop this one.

Ok
> 
> <...>
> > @@ -1022,12 +1022,12 @@ bond_mode_8023ad_activate_slave(struct
> > rte_eth_dev *bond_dev, uint8_t slave_id)
> >
> >  int
> >  bond_mode_8023ad_deactivate_slave(struct rte_eth_dev *bond_dev,
> > -		uint8_t slave_id)
> > +				   uint16_t slave_id)
> 
> The coding style for multiple lines in a function call is two tabs or alternatively
> allign to the paranthesis. Original code synyax looks good here, no need to
> update.
> 

Ok

> <...>
> 
> > @@ -1536,17 +1536,12 @@ rte_eth_bond_8023ad_setup_v1708(uint8_t
> port_id,
> >  	return 0;
> >  }
> >  BIND_DEFAULT_SYMBOL(rte_eth_bond_8023ad_setup, _v1708, 17.08);
> > -MAP_STATIC_SYMBOL(int rte_eth_bond_8023ad_setup(uint8_t port_id,
> > +MAP_STATIC_SYMBOL(int rte_eth_bond_8023ad_setup(uint16_t port_id,
> 
> Hmm, this is tricky!
> The macro MAP_STATIC_SYMBOL is used for ABI versioning, but changing the
> port_id storage type breaks the ABI already. ABI versioning can be removed
> completely. Cc'ed Declan.
> 
Do you mean that I should remove 
> > -MAP_STATIC_SYMBOL(int rte_eth_bond_8023ad_setup(uint8_t port_id, ?

> Which also reminds me that bonding LIBABIVER needs to be updated. This is also
> required for all i40e, ixgbe and bnxt. Please let me know if you need help here.
> 
Yes. I'm not clear about it. Need help Ferruh.

> <...>
> 
> > @@ -1622,12 +1618,13 @@ rte_eth_bond_8023ad_ext_collect(uint8_t
> port_id, uint8_t slave_id, int enabled)
> >  		ACTOR_STATE_SET(port, COLLECTING);
> >  	else
> >  		ACTOR_STATE_CLR(port, COLLECTING);
> > -
> > +	printf("enabled  port->actor_state = %d \r\n",  port->actor_state);
> 
> Is this a git rebase error ?
> 

My bad.  Remove it.
 
> <...>
> 
> > @@ -586,13 +588,14 @@ rte_eth_bond_active_slaves_get(uint8_t
> bonded_port_id, uint8_t slaves[],
> >  	if (internals->active_slave_count > len)
> >  		return -1;
> >
> > -	memcpy(slaves, internals->active_slaves, internals->active_slave_count);
> > +	memcpy(slaves, internals->active_slaves,
> > +	internals->active_slave_count *
> > +sizeof(internals->active_slaves[0]));
> 
> Good catch!
> I wonder if there are more like this, did you traced all memcpy, memset, etc..  ?
> 

The code caused failures when I test bonding driver in test code. and I will fix them if I trace. 

> <...>
> 
> > --- a/drivers/net/ixgbe/rte_pmd_ixgbe.c
> > +++ b/drivers/net/ixgbe/rte_pmd_ixgbe.c
> > @@ -38,7 +38,7 @@
> >  #include "rte_pmd_ixgbe.h"
> >
> >  int
> > -rte_pmd_ixgbe_set_vf_mac_addr(uint8_t port, uint16_t vf,
> > +rte_pmd_ixgbe_set_vf_mac_addr(uint16_t port, uint16_t vf,
> >  			      struct ether_addr *mac_addr)
> 
> ixgbe LIBABIVER also needs to be updated.
> 
> I have just recognized that release notes missing this library, I will add.
> 
thanks
> <...>
> 
> > --- a/drivers/net/vmxnet3/vmxnet3_ring.h
> > +++ b/drivers/net/vmxnet3/vmxnet3_ring.h
> > @@ -143,8 +143,8 @@ typedef struct vmxnet3_tx_queue {
> >  	struct vmxnet3_txq_stats     stats;
> >  	const struct rte_memzone     *mz;
> >  	bool                         stopped;
> > -	uint16_t                     queue_id;      /**< Device TX queue index. */
> > -	uint8_t                      port_id;       /**< Device port identifier. */
> > +	uint16_t                     queue_id; /**< Device TX queue index. */
> 
> No need to change "queue_id" here, if this is for comment allignment, please
> allign the port_id one.
> 

Ok.

> > +	uint16_t                     port_id;  /**< Device port identifier. */
> >  	uint16_t		     txdata_desc_size;
> >  } vmxnet3_tx_queue_t;
> >
> > @@ -178,8 +178,8 @@ typedef struct vmxnet3_rx_queue {
> >  	struct vmxnet3_rxq_stats    stats;
> >  	const struct rte_memzone    *mz;
> >  	bool                        stopped;
> > -	uint16_t                    queue_id;      /**< Device RX queue index. */
> > -	uint8_t                     port_id;       /**< Device port identifier. */
> > +	uint16_t                    queue_id; /**< Device RX queue index. */
> 
> same as above.
> 
Ok.

> <...>
> 
> > @@ -94,8 +94,7 @@ rte_port_ethdev_reader_create(void *params, int
> > socket_id)  static int  rte_port_ethdev_reader_rx(void *port, struct
> > rte_mbuf **pkts, uint32_t n_pkts)  {
> > -	struct rte_port_ethdev_reader *p =
> > -		port;
> > +	struct rte_port_ethdev_reader *p = port;
> 
> This is a good syntax correction, but this patch is already big, please drop these
> ones.

 Ok. I should focus on port id range increase .  :)

> 
> >  	uint16_t rx_pkt_cnt;
> >
> >  	rx_pkt_cnt = rte_eth_rx_burst(p->port_id, p->queue_id, pkts,
> > n_pkts); @@ -119,8 +118,7 @@ rte_port_ethdev_reader_free(void *port)
> > static int rte_port_ethdev_reader_stats_read(void *port,
> >  		struct rte_port_in_stats *stats, int clear)  {
> > -	struct rte_port_ethdev_reader *p =
> > -			port;
> > +	struct rte_port_ethdev_reader *p = port;
> 
> same as above, and there are few more below.
> 
Ok
> <...>

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v3 0/2] ethdev new offloads API
  2017-09-10 12:07  4% ` [dpdk-dev] [PATCH v2 0/2] ethdev new " Shahaf Shuler
@ 2017-09-13  6:37  4%   ` Shahaf Shuler
  2017-09-13  9:10  0%     ` Andrew Rybchenko
  2017-09-17  6:54  4%     ` [dpdk-dev] [PATCH v4 0/3] " Shahaf Shuler
  0 siblings, 2 replies; 200+ results
From: Shahaf Shuler @ 2017-09-13  6:37 UTC (permalink / raw)
  To: thomas; +Cc: dev

Tx offloads configuration is per queue. Tx offloads are enabled by default, 
and can be disabled using ETH_TXQ_FLAGS_NO* flags. 
This behaviour is not consistent with the Rx side where the Rx offloads
configuration is per port. Rx offloads are disabled by default and enabled 
according to bit field in rte_eth_rxmode structure.

Moreover, considering more Tx and Rx offloads will be added 
over time, the cost of managing them all inside the PMD will be tremendous,
as the PMD will need to check the matching for the entire offload set 
for each mbuf it handles.
In addition, on the current approach each Rx offload added breaks the
ABI compatibility as it requires to add entries to existing bit-fields.
 
The series address above issues by defining a new offloads API.
With the new API, Tx and Rx offloads configuration is per queue.
The offloads are disabled by default. Each offload can be enabled or
disabled using the existing DEV_TX_OFFLOADS_* or DEV_RX_OFFLOADS_* flags.
Such API will enable to easily add or remove offloads, without breaking the
ABI compatibility.

The new API does not have an equivalent for the below Tx flags:

* ETH_TXQ_FLAGS_NOREFCOUNT
* ETH_TXQ_FLAGS_NOMULTMEMP

The reason is that those flags are not to manage offloads, rather some
guarantee from application on the way it uses mbufs, therefore could not be
present as part of DEV_TX_OFFLOADS_*.
Such flags are useful only for benchmarks, and therefore provide a non-realistic    
performance for DPDK customers using simple benchmarks for evaluation.
Leveraging the work being done in this series to clean up those flags.

In order to provide a smooth transition between the APIs the following actions
were taken:
*  The old offloads API is kept for the meanwhile.
*  New capabilities were added for PMD to advertize it has moved to the new
   offloads API.
*  Helper function which copy from old to new API were added to ethdev,
   enabling the PMD to support only one of the APIs.

Per discussion made on the RFC of this series [1], the integration plan which was
decided is to do the transition in two phases:
* ethdev API will move on 17.11.
* Apps and examples will move on 18.02.

This to enable PMD maintainers sufficient time to adopt the new API.

[1]
http://dpdk.org/ml/archives/dev/2017-August/072643.html

on v3:
 - Introduce the DEV_TX_OFFLOAD_MBUF_FAST_FREE to act as an equivalent
   for the no refcnt and single mempool flags.
 - Fix features documentation.
 - Fix commnet style.

on v2:
 - Taking new approach of dividing offloads into per-queue and per-port one.
 - Postpone the Tx/Rx public struct renaming to 18.02
 - squash the helper functions into the Rx/Tx offloads intro patches.

Shahaf Shuler (2):
  ethdev: introduce Rx queue offloads API
  ethdev: introduce Tx queue offloads API

 doc/guides/nics/features.rst  |  66 +++++++----
 lib/librte_ether/rte_ethdev.c | 220 ++++++++++++++++++++++++++++++++++---
 lib/librte_ether/rte_ethdev.h |  89 ++++++++++++++-
 3 files changed, 335 insertions(+), 40 deletions(-)

-- 
2.12.0

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] multi-process shared memory on PPC
  2017-09-12 18:11  0%     ` Xueming(Steven) Li
@ 2017-09-13  8:56  0%       ` Xueming(Steven) Li
  0 siblings, 0 replies; 200+ results
From: Xueming(Steven) Li @ 2017-09-13  8:56 UTC (permalink / raw)
  To: Chao Zhu; +Cc: dev

HI Chao,

Found a mmap MAP_SHARED issue in multi-process, the address returned seems to be a local malloc address, conflicts with other variable in secondary process, code:

Mmap in primary process initiates a shared address:
	addr = mmap(NULL, page_size, PROT_WRITE, MAP_SHARED, cmd_fd, offset);
At secondary process, the remapping of primary address with same offset and length succeed, but it corrupted a local variable allocated by calloc():
	addr = mmap((void *)pri_addr, page_size, PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, offset);

Gdb log of secondary process, comments inside. Hope I'm wrong somewhere:

Thread 1 "symmetric_mp" hit Breakpoint 1, mlx5_init_context (vdev=0x10430c00, ctx=0x7ffff72200b8, cmd_fd=7)
    at /home/xueming/rdma-core/providers/mlx5/mlx5.c:888
888             gross_uuars = context->tot_uuars / MLX5_NUM_NON_FP_BFREGS_PER_UAR * NUM_BFREGS_PER_UAR;
(gdb) p context
$1 = (struct mlx5_context *) 0x7ffff72200b8
(gdb) p *context
$2 = {ibv_ctx = {device = 0x0, ops = {query_device = 0x0, query_port = 0x0, alloc_pd = 0x0, dealloc_pd = 0x0, reg_mr = 0x0, rereg_mr = 0x0, dereg_mr = 0x0,
...
/////////// the local variable "context" allocated by calloc() works well before mmap ///////////
 (gdb) c
Continuing.
Thread 1 "symmetric_mp" received signal SIGSEGV, Segmentation fault.
0x00007ffff7d06340 in free () from /lib/powerpc64le-linux-gnu/libc.so.6
(gdb) bt
#0  0x00007ffff7d06340 in free () from /lib/powerpc64le-linux-gnu/libc.so.6
#1  0x00007ffff7efd92c in mlx5_cleanup_context (device=0x10430c00, ibctx=0x7ffff72200b8) at /home/xueming/rdma-core/providers/mlx5/mlx5.c:1008
#2  0x00007ffff7f3cc74 in __ibv_close_device_1_1 (context=0x7ffff72200b8) at /home/xueming/rdma-core/libibverbs/device.c:285
#3  0x00000000101d8118 in mlx5_pci_probe (pci_drv=0x103345a8 <mlx5_driver>, pci_dev=0x10440510) at /home/xueming/mlnx-dpdk.org/drivers/net/mlx5/mlx5.c:925
...
(gdb) f 1
#1  0x00007ffff7efd92c in mlx5_cleanup_context (device=0x10430c00, ibctx=0x7ffff72200b8) at /home/xueming/rdma-core/providers/mlx5/mlx5.c:1008
1008            free(context->bfs);
(gdb) p context
$3 = (struct mlx5_context *) 0x7ffff72200b8
////////////same address///////////////
 (gdb) p *context
Cannot access memory at address 0x7ffff7250000
////////// This is the address returned by mmap() of primary address, conflicted here. /////////////////
(gdb) p sizeof(struct mlx5_context)
$5 = 199408
 (gdb) p/x  0x7ffff72200b8 + 199408
$7 = 0x7ffff7250ba8

Best Regards,
Xueming


> -----Original Message-----
> From: Xueming(Steven) Li
> Sent: Wednesday, September 13, 2017 2:11 AM
> To: Xueming(Steven) Li <xuemingl@mellanox.com>; Chao Zhu
> <chaozhu@linux.vnet.ibm.com>
> Cc: dev@dpdk.org
> Subject: RE: multi-process shared memory on PPC
> 
> It works for me after setting nr_overcommit_hugepages correctly, thanks again.
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Xueming(Steven)
> > Li
> > Sent: Tuesday, September 12, 2017 4:13 PM
> > To: Chao Zhu <chaozhu@linux.vnet.ibm.com>
> > Cc: dev@dpdk.org
> > Subject: Re: [dpdk-dev] multi-process shared memory on PPC
> >
> > Great, that might be something missing, will update later. Thanks!
> >
> > > -----Original Message-----
> > > From: Chao Zhu [mailto:chaozhu@linux.vnet.ibm.com]
> > > Sent: Tuesday, September 12, 2017 4:02 PM
> > > To: Xueming(Steven) Li <xuemingl@mellanox.com>
> > > Cc: dev@dpdk.org
> > > Subject: RE: multi-process shared memory on PPC
> > >
> > > Xueming,
> > >
> > > I tried it on my local server, it works fine.
> > > Did you set this value
> > > "/sys/kernel/mm/hugepages/hugepages-
> > 16384kB/nr_overcommit_hugepages" ?
> > > It should be the same value as "
> > > /sys/kernel/mm/hugepages/hugepages-16384kB/nr_hugepages" on
> ppc64le.
> > >
> > > > -----Original Message-----
> > > > From: Xueming(Steven) Li [mailto:xuemingl@mellanox.com]
> > > > Sent: 2017年8月31日 22:40
> > > > To: Chao Zhu <chaozhu@linux.vnet.ibm.com>
> > > > Cc: dev@dpdk.org
> > > > Subject: multi-process shared memory on PPC
> > > >
> > > > Hi all,
> > > >
> > > > I'm testing multi-process example on PowerPC system, looks like
> > > > shared memory not working properly.
> > > > Below are the error and debug info of the first multi-process
> > > > example 'simple_mp' (works as expected on X86):
> > > >
> > > > // Build DPDK, master branch
> > > > # make T=ppc_64-power8-linuxapp-gcc -j160 -C
> > > > examples/multi_process/simple_mp/ #
> > > > examples/multi_process/simple_mp/build/simple_mp  -w 0:0.0
> > > > --proc-type=primary -l 1-2 --socket-mem
> > > > 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> > > > APP: Finished Process Init.
> > > > Starting core 2
> > > > simple_mp >
> > > >
> > > > // Open another terminal and run secondary process # gdb --args
> > > > examples/multi_process/simple_mp/build/simple_mp -n 4 -w 0:0.0
> > > > --proc-type=secondary -l 3-4 --socket-mem
> > > > 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> > > > GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1 Copyright (C) 2016
> > > > Free Software Foundation, Inc.
> > > > License GPLv3+: GNU GPL version 3 or later
> > > >
> > > <https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2F
> > > ur
> > > ldef
> > > ense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> > >
> >
> 3A__gnu.org_licenses_gpl&data=02%7C01%7Cxuemingl%40mellanox.com%7C
> > >
> >
> 9cd11fda7a7f48df7cbd08d4f9b486d8%7Ca652971c7d2e4d9ba6a4d149256f461
> > >
> >
> b%7C0%7C0%7C636408001138751301&sdata=bb3hwYz7ehCqt4QA6GGqTDMY
> > > kY1qAJV%2BCMDBVbXmWzE%3D&reserved=0.
> > > h
> > > > tml&d=DwIFAg&c=jf_iaSHvJObTbx-
> > > siA1ZOg&r=4TYe4NpqlgVi0ArYpZ76FrWp7IE
> > > > w8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-
> > 6aTY_jEvDZtMZR0o&s
> > > > =SbDQBN7qJ9z8fWCSePyvm5FFncp2P_9XZm-qs1lH5PE&e= > This is free
> > > > software: you are free to change and redistribute it.
> > > > There is NO WARRANTY, to the extent permitted by law.  Type "show
> > > copying"
> > > > and "show warranty" for details.
> > > > This GDB was configured as "powerpc64le-linux-gnu".
> > > > Type "show configuration" for configuration details.
> > > > For bug reporting instructions, please see:
> > > > <https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%
> > > > 2F
> > > > ur
> > > > ldefense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> > > 3A__www.gnu.org_softwar&
> > > >
> > >
> >
> data=02%7C01%7Cxuemingl%40mellanox.com%7C9cd11fda7a7f48df7cbd08d4f
> > > 9b48
> > > >
> > >
> >
> 6d8%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C63640800113875
> > > 1301&sd
> > > >
> > >
> >
> ata=4DNDTyIcHpTIU60K7FM%2F1zuASSB1IdZDRyOaiVp1Y%2BY%3D&reserved=
> > > 0
> > > > e_gdb_bugs_&d=DwIFAg&c=jf_iaSHvJObTbx-
> > > siA1ZOg&r=4TYe4NpqlgVi0ArYpZ
> > > > 76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-
> > > 6aTY_jEvDZt
> > > > MZR0o&s=GAFKK3jSahAPFXMGcPGbVNTl0CesJy_qfs5TxXfGOX0&e= >.
> > > > Find the GDB manual and other documentation resources online at:
> > > > <https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%
> > > > 2F
> > > > ur
> > > > ldefense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> > > 3A__www.gnu.org_softwar&
> > > >
> > >
> >
> data=02%7C01%7Cxuemingl%40mellanox.com%7C9cd11fda7a7f48df7cbd08d4f
> > > 9b48
> > > >
> > >
> >
> 6d8%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C63640800113875
> > > 1301&sd
> > > >
> > >
> >
> ata=4DNDTyIcHpTIU60K7FM%2F1zuASSB1IdZDRyOaiVp1Y%2BY%3D&reserved=
> > > 0
> > > > e_gdb_documentation_&d=DwIFAg&c=jf_iaSHvJObTbx-
> > > siA1ZOg&r=4TYe4Npql
> > > >
> > gVi0ArYpZ76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwuuryoN7QPg9N-
> > > 6a
> > > > TY_jEvDZtMZR0o&s=JdkMMjGGl-
> > > 3Z3BGnjCkOFP5lI5BIbRNBxH4EVI70YFc&e= > .
> > > > For help, type "help".
> > > > Type "apropos word" to search for commands related to "word"...
> > > > Reading symbols from
> > > > examples/multi_process/simple_mp/build/simple_mp...done.
> > > > (gdb) r
> > > > Starting program:
> > > > /home/xueming/mlnx-
> > > dpdk.org/examples/multi_process/simple_mp/build/sim
> > > > ple_mp -n 4 -w 0:0.0 --proc-type=secondary -l 3-4 --socket-mem
> > > > 256,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,256,256
> > > > [Thread debugging using libthread_db enabled] Using host
> > > > libthread_db
> > > library
> > > > "/lib/powerpc64le-linux-gnu/libthread_db.so.1".
> > > > EAL: Detected 144 lcore(s)
> > > > EAL: Probing VFIO support...
> > > > [New Thread 0x7ffff7a6eff0 (LWP 58811)] [New Thread 0x7ffff726eff0
> > > > (LWP 58812)]
> > > >
> > > > Thread 1 "simple_mp" received signal SIGSEGV, Segmentation fault.
> > > > 0x00007ffff7d2f3ec in ?? () from
> > > > /lib/powerpc64le-linux-gnu/libc.so.6
> > > >  (gdb) bt full
> > > > #0  0x00007ffff7d2f3ec in ?? () from
> > > > /lib/powerpc64le-linux-gnu/libc.so.6
> > > > No symbol table info available.
> > > > #1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28
> > > > "PRI_2_SEC")
> > > >     at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
> > > >         te = 0x7ef3eefd5e00
> > > >         r = 0x0
> > > >         ring_list = 0x7ffff7aa250c
> > > > #2  0x0000000010032640 in main (argc=10, argv=0x7ffffffff3e8)
> > > >     at
> > > > /home/xueming/mlnx-
> > > dpdk.org/examples/multi_process/simple_mp/main.c:12
> > > > 8
> > > >         flags = 0
> > > >         ring_size = 64
> > > >         pool_size = 1024
> > > >         pool_cache = 32
> > > >         priv_data_sz = 0
> > > >         ret = 9
> > > >         lcore_id = 32767
> > > >         cl = 0x7ffff7fef718 <_dl_argv>
> > > > (gdb) f 1
> > > > #1  0x0000000010077d54 in rte_ring_lookup (name=0x102a4e28
> > > > "PRI_2_SEC")
> > > >     at /home/xueming/mlnx-dpdk.org/lib/librte_ring/rte_ring.c:326
> > > > 326                     if (strncmp(name, r->name,
> > > > RTE_RING_NAMESIZE) == 0)
> > > > (gdb) l
> > > > 321
> > > > 322             rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
> > > > 323
> > > > 324             TAILQ_FOREACH(te, ring_list, next) {
> > > > 325                     r = (struct rte_ring *) te->data;
> > > > 326                     if (strncmp(name, r->name,
> > > > RTE_RING_NAMESIZE) == 0)
> > > > 327                             break;
> > > > 328             }
> > > > 329
> > > > 330             rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
> > > > (gdb) p *te
> > > > $1 = {next = {tqe_next = 0x0, tqe_prev = 0x0}, data = 0x0}
> > > > (gdb) p *ring_list
> > > > $2 = {tqh_first = 0x7ef3eefd5e00, tqh_last = 0x7ef3eec6d100}
> > > >
> > > > # uname -a
> > > > Linux dragon-power-01 4.13.0-rc2 #1 SMP Tue Aug 29 17:27:05 IDT
> > > > 2017 ppc64le ppc64le ppc64le GNU/Linux
> > > >
> > > > # cat /etc/issue
> > > > Ubuntu 16.04.2 LTS \n \l
> > > >
> > > > # gcc --version
> > > > gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 Copyright
> > > > (C)
> > > > 2015 Free Software Foundation, Inc.
> > > > This is free software; see the source for copying conditions.
> > > > There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR
> > > > A PARTICULAR PURPOSE.
> > > >
> > > > # lscpu
> > > > Architecture:          ppc64le
> > > > Byte Order:            Little Endian
> > > > CPU(s):                144
> > > > On-line CPU(s) list:   0-87,96-103,112-159
> > > > Thread(s) per core:    8
> > > > Core(s) per socket:    4
> > > > Socket(s):             4
> > > > NUMA node(s):          4
> > > > Model:                 2.1 (pvr 004b 0201)
> > > > Model name:            POWER8E (raw), altivec supported
> > > > CPU max MHz:           3690.0000
> > > > CPU min MHz:           2061.0000
> > > > L1d cache:             64K
> > > > L1i cache:             32K
> > > > L2 cache:              512K
> > > > L3 cache:              8192K
> > > > NUMA node0 CPU(s):     0-39
> > > > NUMA node1 CPU(s):     40-79
> > > > NUMA node16 CPU(s):    80-87,96-103,112-119
> > > > NUMA node17 CPU(s):    120-159
> > > >
> > > > # cat build/.config
> > > > # RTE_EXEC_ENV values are the directories in mk/exec-env/
> > > > CONFIG_RTE_EXEC_ENV="linuxapp"
> > > > # RTE_ARCH values are architecture we compile for. directories in
> > > > mk/arch/ CONFIG_RTE_ARCH="ppc_64"
> > > > # machine can define specific variables or action for a specific
> > > > board # RTE_MACHINE values are architecture we compile for.
> > > > directories in mk/machine/ CONFIG_RTE_MACHINE="power8"
> > > > # The compiler we use.
> > > > # RTE_TOOLCHAIN values are architecture we compile for.
> > > > directories in mk/toolchain/ CONFIG_RTE_TOOLCHAIN="gcc"
> > > > # Use intrinsics or assembly code for key routines
> > > > CONFIG_RTE_FORCE_INTRINSICS=n # Machine forces strict alignment
> > > > constraints.
> > > > CONFIG_RTE_ARCH_STRICT_ALIGN=n
> > > > # Compile to share library
> > > > CONFIG_RTE_BUILD_SHARED_LIB=n
> > > > # Use newest code breaking previous ABI CONFIG_RTE_NEXT_ABI=y #
> > > > Major ABI to overwrite library specific LIBABIVER
> > > > CONFIG_RTE_MAJOR_ABI= # Machine's cache line size
> > > > CONFIG_RTE_CACHE_LINE_SIZE=128
> > > > # Compile Environment Abstraction Layer CONFIG_RTE_LIBRTE_EAL=y
> > > > CONFIG_RTE_MAX_LCORE=256
> > > > CONFIG_RTE_MAX_NUMA_NODES=32
> > > > CONFIG_RTE_MAX_MEMSEG=256
> > > > CONFIG_RTE_MAX_MEMZONE=2560
> > > > CONFIG_RTE_MAX_TAILQ=32
> > > > CONFIG_RTE_LOG_LEVEL=RTE_LOG_INFO
> > > > CONFIG_RTE_LOG_DP_LEVEL=RTE_LOG_INFO
> > > > CONFIG_RTE_LOG_HISTORY=256
> > > > CONFIG_RTE_BACKTRACE=y
> > > > CONFIG_RTE_LIBEAL_USE_HPET=n
> > > > CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID=n
> > > > CONFIG_RTE_EAL_ALWAYS_PANIC_ON_ERROR=n
> > > > CONFIG_RTE_EAL_IGB_UIO=y
> > > > CONFIG_RTE_EAL_VFIO=y
> > > > CONFIG_RTE_MALLOC_DEBUG=n
> > > > CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES=y
> > > > # Recognize/ignore architecture we compile for. AVX/AVX512 CPU
> > > > flags for performance/power testing.
> > > > # AVX512 is marked as experimental for now, will enable it after
> > > > enough #
> > > field
> > > > test and possible optimization.
> > > > CONFIG_RTE_ENABLE_AVX=y
> > > > CONFIG_RTE_ENABLE_AVX512=n
> > > > # Default driver path (or "" to disable) CONFIG_RTE_EAL_PMD_PATH=""
> > > > # Compile Environment Abstraction Layer to support Vmware TSC map
> > > > CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=n
> > > > # Compile architecture we compile for. argument parser library
> > > > CONFIG_RTE_LIBRTE_KVARGS=y # Compile generic ethernet library
> > > > CONFIG_RTE_LIBRTE_ETHER=y CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n
> > > > CONFIG_RTE_MAX_ETHPORTS=32
> > > > CONFIG_RTE_MAX_QUEUES_PER_PORT=1024
> > > > CONFIG_RTE_LIBRTE_IEEE1588=n
> > > > CONFIG_RTE_ETHDEV_QUEUE_STAT_CNTRS=16
> > > > CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y
> > > > # Turn off Tx preparation stage
> > > > # Warning: rte_eth_tx_prepare() can be safely disabled only if
> > > > using a #
> > > driver
> > > > which do not implement any Tx preparation.
> > > > CONFIG_RTE_ETHDEV_TX_PREPARE_NOOP=n
> > > > # Compile burst-oriented Amazon ENA PMD driver
> > > > CONFIG_RTE_LIBRTE_ENA_PMD=y
> > CONFIG_RTE_LIBRTE_ENA_DEBUG_RX=n
> > > > CONFIG_RTE_LIBRTE_ENA_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_ENA_DEBUG_TX_FREE=n
> > > > CONFIG_RTE_LIBRTE_ENA_DEBUG_DRIVER=n
> > > > CONFIG_RTE_LIBRTE_ENA_COM_DEBUG=n
> > > > # Compile burst-oriented IGB & EM PMD drivers
> > > > CONFIG_RTE_LIBRTE_EM_PMD=y CONFIG_RTE_LIBRTE_IGB_PMD=y
> > > > CONFIG_RTE_LIBRTE_E1000_DEBUG_INIT=n
> > > > CONFIG_RTE_LIBRTE_E1000_DEBUG_RX=n
> > > > CONFIG_RTE_LIBRTE_E1000_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_E1000_DEBUG_TX_FREE=n
> > > > CONFIG_RTE_LIBRTE_E1000_DEBUG_DRIVER=n
> > > > CONFIG_RTE_LIBRTE_E1000_PF_DISABLE_STRIP_CRC=n
> > > > # Compile burst-oriented IXGBE PMD driver
> > > > CONFIG_RTE_LIBRTE_IXGBE_PMD=n
> > > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_INIT=n
> > > > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_RX=n
> > > > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX_FREE=n
> > > > CONFIG_RTE_LIBRTE_IXGBE_DEBUG_DRIVER=n
> > > > CONFIG_RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC=n
> > > > CONFIG_RTE_IXGBE_INC_VECTOR=y
> > > > CONFIG_RTE_LIBRTE_IXGBE_BYPASS=n
> > > > # Compile burst-oriented I40E PMD driver
> > > > CONFIG_RTE_LIBRTE_I40E_PMD=y
> > CONFIG_RTE_LIBRTE_I40E_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_I40E_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_I40E_DEBUG_TX_FREE=n
> > > > CONFIG_RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC=y
> > > > CONFIG_RTE_LIBRTE_I40E_INC_VECTOR=y
> > > > CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n
> > > > CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF=64
> > > > CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF=4
> > > > CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM=4
> > > > # interval up to 8160 us, aligned to 2 (or default value)
> > > > CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL=-1
> > > > # Compile burst-oriented FM10K PMD
> CONFIG_RTE_LIBRTE_FM10K_PMD=n
> > > > CONFIG_RTE_LIBRTE_FM10K_DEBUG_INIT=n
> > > > CONFIG_RTE_LIBRTE_FM10K_DEBUG_RX=n
> > > > CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX_FREE=n
> > > > CONFIG_RTE_LIBRTE_FM10K_DEBUG_DRIVER=n
> > > > CONFIG_RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE=y
> > > > CONFIG_RTE_LIBRTE_FM10K_INC_VECTOR=y
> > > > # Compile burst-oriented Mellanox ConnectX-3 (MLX4) PMD
> > > > CONFIG_RTE_LIBRTE_MLX4_PMD=n
> CONFIG_RTE_LIBRTE_MLX4_DEBUG=n
> > > > CONFIG_RTE_LIBRTE_MLX4_DEBUG_BROKEN_VERBS=n
> > > > CONFIG_RTE_LIBRTE_MLX4_SGE_WR_N=4
> > > > CONFIG_RTE_LIBRTE_MLX4_MAX_INLINE=0
> > > > CONFIG_RTE_LIBRTE_MLX4_TX_MP_CACHE=8
> > > > CONFIG_RTE_LIBRTE_MLX4_SOFT_COUNTERS=1
> > > > # Compile burst-oriented Mellanox ConnectX-4 & ConnectX-5 (MLX5)
> > > > PMD CONFIG_RTE_LIBRTE_MLX5_PMD=y
> CONFIG_RTE_LIBRTE_MLX5_DEBUG=n
> > > > CONFIG_RTE_LIBRTE_MLX5_TX_MP_CACHE=8
> > > > # Compile burst-oriented Broadcom PMD driver
> > > > CONFIG_RTE_LIBRTE_BNX2X_PMD=n
> > CONFIG_RTE_LIBRTE_BNX2X_DEBUG=n
> > > > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_INIT=n
> > > > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_RX=n
> > > > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_BNX2X_MF_SUPPORT=n
> > > > CONFIG_RTE_LIBRTE_BNX2X_DEBUG_PERIODIC=n
> > > > # Compile burst-oriented Chelsio Terminator (CXGBE) PMD
> > > > CONFIG_RTE_LIBRTE_CXGBE_PMD=y
> > > CONFIG_RTE_LIBRTE_CXGBE_DEBUG=n
> > > > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_REG=n
> > > > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_MBOX=n
> > > > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_CXGBE_DEBUG_RX=n
> > > > CONFIG_RTE_LIBRTE_CXGBE_TPUT=y
> > > > # Compile burst-oriented Cisco ENIC PMD driver
> > > > CONFIG_RTE_LIBRTE_ENIC_PMD=n CONFIG_RTE_LIBRTE_ENIC_DEBUG=n
> > > > CONFIG_RTE_LIBRTE_ENIC_DEBUG_FLOW=n
> > > > # Compile burst-oriented Netronome NFP PMD driver
> > > > CONFIG_RTE_LIBRTE_NFP_PMD=y CONFIG_RTE_LIBRTE_NFP_DEBUG=n #
> > > Compile
> > > > burst-oriented Broadcom BNXT PMD driver
> > > CONFIG_RTE_LIBRTE_BNXT_PMD=y #
> > > > Compile burst-oriented Solarflare libefx-based PMD
> > > > CONFIG_RTE_LIBRTE_SFC_EFX_PMD=n
> > > CONFIG_RTE_LIBRTE_SFC_EFX_DEBUG=n #
> > > > Compile software PMD backed by
> > > > SZEDATA2 device CONFIG_RTE_LIBRTE_PMD_SZEDATA2=n # Defines
> > > firmware
> > > > type address space.
> > > > # See documentation for supported values.
> > > > # Other values raise compile time error.
> > > > CONFIG_RTE_LIBRTE_PMD_SZEDATA2_AS=0
> > > > # Compile burst-oriented Cavium Thunderx NICVF PMD driver
> > > > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD=y
> > > > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_INIT=n
> > > > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_RX=n
> > > > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_DRIVER=n
> > > > CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_MBOX=n
> > > > # Compile burst-oriented Cavium LiquidIO PMD driver
> > > > CONFIG_RTE_LIBRTE_LIO_PMD=y
> > > CONFIG_RTE_LIBRTE_LIO_DEBUG_DRIVER=n
> > > > CONFIG_RTE_LIBRTE_LIO_DEBUG_INIT=n
> > > > CONFIG_RTE_LIBRTE_LIO_DEBUG_RX=n
> > > > CONFIG_RTE_LIBRTE_LIO_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_LIO_DEBUG_MBOX=n
> > > > CONFIG_RTE_LIBRTE_LIO_DEBUG_REGS=n
> > > > # Compile NXP DPAA2 FSL-MC Bus
> > > > CONFIG_RTE_LIBRTE_FSLMC_BUS=n
> > > > # Compile Support Libraries for NXP DPAA2
> > > > CONFIG_RTE_LIBRTE_DPAA2_MEMPOOL=n
> > > > CONFIG_RTE_LIBRTE_DPAA2_USE_PHYS_IOVA=y
> > > > # Compile burst-oriented NXP DPAA2 PMD driver
> > > > CONFIG_RTE_LIBRTE_DPAA2_PMD=n
> > > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_INIT=n
> > > > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_DRIVER=n
> > > > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_RX=n
> > > > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_DPAA2_DEBUG_TX_FREE=n
> > > > # Compile burst-oriented VIRTIO PMD driver
> > > > CONFIG_RTE_LIBRTE_VIRTIO_PMD=y
> > > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_INIT=n
> > > > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_RX=n
> > > > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DRIVER=n
> > > > CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DUMP=n
> > > > # Compile virtio device emulation inside virtio PMD driver
> > > > CONFIG_RTE_VIRTIO_USER=y # Compile burst-oriented VMXNET3 PMD
> > > driver
> > > > CONFIG_RTE_LIBRTE_VMXNET3_PMD=n
> > > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_INIT=n
> > > > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_RX=n
> > > > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX_FREE=n
> > > > CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_DRIVER=n
> > > > # Compile example software rings based PMD
> > > > CONFIG_RTE_LIBRTE_PMD_RING=y
> > > > CONFIG_RTE_PMD_RING_MAX_RX_RINGS=16
> > > > CONFIG_RTE_PMD_RING_MAX_TX_RINGS=16
> > > > # Compile software PMD backed by PCAP files
> > > > CONFIG_RTE_LIBRTE_PMD_PCAP=n # Compile link bonding PMD library
> > > > CONFIG_RTE_LIBRTE_PMD_BOND=y
> > > CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB=n
> > > > CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB_L1=n
> > > > # QLogic 10G/25G/40G/50G/100G PMD
> > > > CONFIG_RTE_LIBRTE_QEDE_PMD=y
> > > > CONFIG_RTE_LIBRTE_QEDE_DEBUG_INIT=n
> > > > CONFIG_RTE_LIBRTE_QEDE_DEBUG_INFO=n
> > > > CONFIG_RTE_LIBRTE_QEDE_DEBUG_DRIVER=n
> > > > CONFIG_RTE_LIBRTE_QEDE_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_QEDE_DEBUG_RX=n
> > > > #Provides abs path/name of architecture we compile for. firmware file.
> > > > #Empty string denotes driver will use default firmware
> > > > CONFIG_RTE_LIBRTE_QEDE_FW=""
> > > > # Compile software PMD backed by AF_PACKET sockets (Linux only)
> > > > CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y # Compile ARK PMD
> > > > CONFIG_RTE_LIBRTE_ARK_PMD=y CONFIG_RTE_LIBRTE_ARK_PAD_TX=y
> > > > CONFIG_RTE_LIBRTE_ARK_DEBUG_RX=n
> > > CONFIG_RTE_LIBRTE_ARK_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_ARK_DEBUG_STATS=n
> > > > CONFIG_RTE_LIBRTE_ARK_DEBUG_TRACE=n
> > > > # Compile WRS accelerated virtual port (AVP) guest PMD driver
> > > > CONFIG_RTE_LIBRTE_AVP_PMD=n
> > CONFIG_RTE_LIBRTE_AVP_DEBUG_RX=n
> > > > CONFIG_RTE_LIBRTE_AVP_DEBUG_TX=n
> > > CONFIG_RTE_LIBRTE_AVP_DEBUG_DRIVER=y
> > > > CONFIG_RTE_LIBRTE_AVP_DEBUG_BUFFERS=n
> > > > # Compile architecture we compile for. TAP PMD # It is enabled by
> > > > default
> > > for
> > > > Linux only.
> > > > CONFIG_RTE_LIBRTE_PMD_TAP=y
> > > > # Compile Xen PMD
> > > > CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
> > > > # Compile null PMD
> > > > CONFIG_RTE_LIBRTE_PMD_NULL=y
> > > > # Compile fail-safe PMD
> > > > CONFIG_RTE_LIBRTE_PMD_FAILSAFE=y
> > > > # Do prefetch of packet data within PMD driver receive function
> > > > CONFIG_RTE_PMD_PACKET_PREFETCH=y # Compile generic crypto
> device
> > > > library CONFIG_RTE_LIBRTE_CRYPTODEV=y
> > > > CONFIG_RTE_LIBRTE_CRYPTODEV_DEBUG=n
> > > > CONFIG_RTE_CRYPTO_MAX_DEVS=64
> > > > CONFIG_RTE_CRYPTODEV_NAME_LEN=64
> > > > # Compile PMD for ARMv8 Crypto device
> > > > CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO=n
> > > > CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO_DEBUG=n
> > > > # Compile NXP DPAA2 crypto sec driver for CAAM HW
> > > > CONFIG_RTE_LIBRTE_PMD_DPAA2_SEC=n
> > > > CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_INIT=n
> > > > CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_DRIVER=n
> > > > CONFIG_RTE_LIBRTE_DPAA2_SEC_DEBUG_RX=n
> > > > # Compile PMD for QuickAssist based devices
> > > > CONFIG_RTE_LIBRTE_PMD_QAT=n
> > > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_INIT=n
> > > > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_TX=n
> > > > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_RX=n
> > > > CONFIG_RTE_LIBRTE_PMD_QAT_DEBUG_DRIVER=n
> > > > # Number of sessions to create in architecture we compile for.
> > > > session
> > > memory
> > > > pool # on a single QuickAssist device.
> > > > CONFIG_RTE_QAT_PMD_MAX_NB_SESSIONS=2048
> > > > # Compile PMD for AESNI backed device
> > > > CONFIG_RTE_LIBRTE_PMD_AESNI_MB=n
> > > > CONFIG_RTE_LIBRTE_PMD_AESNI_MB_DEBUG=n
> > > > # Compile PMD for Software backed device
> > > > CONFIG_RTE_LIBRTE_PMD_OPENSSL=n
> > > CONFIG_RTE_LIBRTE_PMD_OPENSSL_DEBUG=n
> > > > # Compile PMD for AESNI GCM device
> > > > CONFIG_RTE_LIBRTE_PMD_AESNI_GCM=n
> > > > CONFIG_RTE_LIBRTE_PMD_AESNI_GCM_DEBUG=n
> > > > # Compile PMD for SNOW 3G device
> > > > CONFIG_RTE_LIBRTE_PMD_SNOW3G=n
> > > > CONFIG_RTE_LIBRTE_PMD_SNOW3G_DEBUG=n
> > > > # Compile PMD for KASUMI device
> > > > CONFIG_RTE_LIBRTE_PMD_KASUMI=n
> > > > CONFIG_RTE_LIBRTE_PMD_KASUMI_DEBUG=n
> > > > # Compile PMD for ZUC device
> > > > CONFIG_RTE_LIBRTE_PMD_ZUC=n
> > > > CONFIG_RTE_LIBRTE_PMD_ZUC_DEBUG=n
> > > > # Compile PMD for Crypto Scheduler device
> > > > CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER=y
> > > > CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER_DEBUG=n
> > > > # Compile PMD for NULL Crypto device
> > > > CONFIG_RTE_LIBRTE_PMD_NULL_CRYPTO=y
> > > > # Compile generic event device library
> > > > CONFIG_RTE_LIBRTE_EVENTDEV=y
> CONFIG_RTE_LIBRTE_EVENTDEV_DEBUG=n
> > > > CONFIG_RTE_EVENT_MAX_DEVS=16
> > > > CONFIG_RTE_EVENT_MAX_QUEUES_PER_DEV=64
> > > > # Compile PMD for skeleton event device
> > > > CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV=y
> > > > CONFIG_RTE_LIBRTE_PMD_SKELETON_EVENTDEV_DEBUG=n
> > > > # Compile PMD for software event device
> > > > CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV=y
> > > > CONFIG_RTE_LIBRTE_PMD_SW_EVENTDEV_DEBUG=n
> > > > # Compile PMD for octeontx sso event device
> > > > CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF=y
> > > > CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF_DEBUG=n
> > > > # Compile librte_ring
> > > > CONFIG_RTE_LIBRTE_RING=y
> > > > # Compile librte_mempool
> > > > CONFIG_RTE_LIBRTE_MEMPOOL=y
> > > > CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE=512
> > > > CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG=n
> > > > # Compile Mempool drivers
> > > > CONFIG_RTE_DRIVER_MEMPOOL_RING=y
> > > > CONFIG_RTE_DRIVER_MEMPOOL_STACK=y
> > > > # Compile librte_mbuf
> > > > CONFIG_RTE_LIBRTE_MBUF=y
> > > > CONFIG_RTE_LIBRTE_MBUF_DEBUG=n
> > > > CONFIG_RTE_MBUF_DEFAULT_MEMPOOL_OPS="ring_mp_mc"
> > > > CONFIG_RTE_MBUF_REFCNT_ATOMIC=y
> > > > CONFIG_RTE_PKTMBUF_HEADROOM=128
> > > > # Compile librte_timer
> > > > CONFIG_RTE_LIBRTE_TIMER=y
> > > > CONFIG_RTE_LIBRTE_TIMER_DEBUG=n
> > > > # Compile librte_cfgfile
> > > > CONFIG_RTE_LIBRTE_CFGFILE=y
> > > > # Compile librte_cmdline
> > > > CONFIG_RTE_LIBRTE_CMDLINE=y
> > > > CONFIG_RTE_LIBRTE_CMDLINE_DEBUG=n
> > > > # Compile librte_hash
> > > > CONFIG_RTE_LIBRTE_HASH=y
> > > > CONFIG_RTE_LIBRTE_HASH_DEBUG=n
> > > > # Compile librte_efd
> > > > CONFIG_RTE_LIBRTE_EFD=y
> > > > # Compile librte_jobstats
> > > > CONFIG_RTE_LIBRTE_JOBSTATS=y
> > > > # Compile architecture we compile for. device metrics library
> > > > CONFIG_RTE_LIBRTE_METRICS=y # Compile architecture we compile for.
> > > > bitrate statistics library CONFIG_RTE_LIBRTE_BITRATE=y # Compile
> > > > architecture we compile for. latency statistics library
> > > > CONFIG_RTE_LIBRTE_LATENCY_STATS=y # Compile librte_lpm
> > > > CONFIG_RTE_LIBRTE_LPM=y CONFIG_RTE_LIBRTE_LPM_DEBUG=n #
> > > Compile
> > > > librte_acl CONFIG_RTE_LIBRTE_ACL=y
> > CONFIG_RTE_LIBRTE_ACL_DEBUG=n
> > > #
> > > > Compile librte_power CONFIG_RTE_LIBRTE_POWER=y
> > > > CONFIG_RTE_LIBRTE_POWER_DEBUG=n
> > > > CONFIG_RTE_MAX_LCORE_FREQS=64
> > > > # Compile librte_net
> > > > CONFIG_RTE_LIBRTE_NET=y
> > > > # Compile librte_ip_frag
> > > > CONFIG_RTE_LIBRTE_IP_FRAG=y
> > > > CONFIG_RTE_LIBRTE_IP_FRAG_DEBUG=n
> > > > CONFIG_RTE_LIBRTE_IP_FRAG_MAX_FRAG=4
> > > > CONFIG_RTE_LIBRTE_IP_FRAG_TBL_STAT=n
> > > > # Compile GRO library
> > > > CONFIG_RTE_LIBRTE_GRO=y
> > > > # Compile librte_meter
> > > > CONFIG_RTE_LIBRTE_METER=y
> > > > # Compile librte_sched
> > > > CONFIG_RTE_LIBRTE_SCHED=y
> > > > CONFIG_RTE_SCHED_DEBUG=n
> > > > CONFIG_RTE_SCHED_RED=n
> > > > CONFIG_RTE_SCHED_COLLECT_STATS=n
> > > > CONFIG_RTE_SCHED_SUBPORT_TC_OV=n
> > > > CONFIG_RTE_SCHED_PORT_N_GRINDERS=8
> > > > CONFIG_RTE_SCHED_VECTOR=n
> > > > # Compile architecture we compile for. distributor library
> > > > CONFIG_RTE_LIBRTE_DISTRIBUTOR=y # Compile architecture we compile
> > for.
> > > > reorder library CONFIG_RTE_LIBRTE_REORDER=y # Compile librte_port
> > > > CONFIG_RTE_LIBRTE_PORT=y CONFIG_RTE_PORT_STATS_COLLECT=n
> > > > CONFIG_RTE_PORT_PCAP=n # Compile librte_table
> > > > CONFIG_RTE_LIBRTE_TABLE=y CONFIG_RTE_TABLE_STATS_COLLECT=n #
> > > Compile
> > > > librte_pipeline CONFIG_RTE_LIBRTE_PIPELINE=y
> > > > CONFIG_RTE_PIPELINE_STATS_COLLECT=n
> > > > # Compile librte_kni
> > > > CONFIG_RTE_LIBRTE_KNI=y
> > > > CONFIG_RTE_LIBRTE_PMD_KNI=y
> > > > CONFIG_RTE_KNI_KMOD=y
> > > > CONFIG_RTE_KNI_KMOD_ETHTOOL=n
> > > > CONFIG_RTE_KNI_PREEMPT_DEFAULT=y
> > > > # Compile architecture we compile for. pdump library
> > > > CONFIG_RTE_LIBRTE_PDUMP=y # Compile vhost user library
> > > > CONFIG_RTE_LIBRTE_VHOST=y CONFIG_RTE_LIBRTE_VHOST_NUMA=y
> > > > CONFIG_RTE_LIBRTE_VHOST_DEBUG=n # Compile vhost PMD # To
> compile,
> > > > CONFIG_RTE_LIBRTE_VHOST should be enabled.
> > > > CONFIG_RTE_LIBRTE_PMD_VHOST=y
> > > > #Compile Xen domain0 support
> > > > CONFIG_RTE_LIBRTE_XEN_DOM0=n
> > > > # Compile architecture we compile for. test application
> > > > CONFIG_RTE_APP_TEST=y CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
> > > > # Compile architecture we compile for. PMD test application
> > > > CONFIG_RTE_TEST_PMD=y
> > > CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
> > > > CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
> > > > # Compile architecture we compile for. crypto performance
> > > > application CONFIG_RTE_APP_CRYPTO_PERF=y # Compile architecture
> we
> > compile for.
> > > > eventdev application CONFIG_RTE_APP_EVENTDEV=y
> > > > CONFIG_RTE_EXEC_ENV_LINUXAPP=y CONFIG_RTE_ARCH_PPC_64=y
> > > > CONFIG_RTE_ARCH_64=y CONFIG_RTE_TOOLCHAIN_GCC=y # Note:
> Power
> > > doesn't
> > > > have this support # Note: Initially, all of architecture we
> > > compile for.
> > > > PMD drivers compilation are turned off on Power # Will turn on
> > > > them only
> > > after
> > > > architecture we compile for. successful testing on Power
> > > >
> > > > Please refer here for more information on running DPDK
> > > > multi-process
> > > > examples:
> > > >
> > > > https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2
> > > > Fu
> > > > rl
> > > > defense.proofpoint.com%2Fv2%2Furl%3Fu%3Dhttp-
> > > 3A__dpdk.org_doc_guides_s
> > > >
> > >
> >
> &data=02%7C01%7Cxuemingl%40mellanox.com%7C9cd11fda7a7f48df7cbd08d
> > > 4f9b4
> > > >
> > >
> >
> 86d8%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C6364080011387
> > > 51301&s
> > > >
> > data=4n76ha0PmSr3wP2c0MAo3PEVYRMKjJVcU9o5xETqhBc%3D&reserved=0
> > > > ample-5Fapp-5Fug_multi-5Fprocess.html&d=DwIFAg&c=jf_iaSHvJObTbx-
> > > siA1Z
> > > >
> > >
> >
> Og&r=4TYe4NpqlgVi0ArYpZ76FrWp7IEw8gfzq7k4itCX_Mg&m=lz_1z0LzwjqjIwu
> > > > uryoN7QPg9N-6aTY_jEvDZtMZR0o&s=gupwe5WWQ-
> > > ap2jObFko6UJymrcy4jTmF
> > > > 2r1dZ2fQN9E&e=
> > > >
> > > > Best Regards,
> > > > Xueming
> > >


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3 0/2] ethdev new offloads API
  2017-09-13  6:37  4%   ` [dpdk-dev] [PATCH v3 " Shahaf Shuler
@ 2017-09-13  9:10  0%     ` Andrew Rybchenko
  2017-09-17  6:54  4%     ` [dpdk-dev] [PATCH v4 0/3] " Shahaf Shuler
  1 sibling, 0 replies; 200+ results
From: Andrew Rybchenko @ 2017-09-13  9:10 UTC (permalink / raw)
  To: Shahaf Shuler, thomas; +Cc: dev

On 09/13/2017 09:37 AM, Shahaf Shuler wrote:
> Tx offloads configuration is per queue. Tx offloads are enabled by default,
> and can be disabled using ETH_TXQ_FLAGS_NO* flags.
> This behaviour is not consistent with the Rx side where the Rx offloads
> configuration is per port. Rx offloads are disabled by default and enabled
> according to bit field in rte_eth_rxmode structure.
>
> Moreover, considering more Tx and Rx offloads will be added
> over time, the cost of managing them all inside the PMD will be tremendous,
> as the PMD will need to check the matching for the entire offload set
> for each mbuf it handles.
> In addition, on the current approach each Rx offload added breaks the
> ABI compatibility as it requires to add entries to existing bit-fields.
>   
> The series address above issues by defining a new offloads API.
> With the new API, Tx and Rx offloads configuration is per queue.
> The offloads are disabled by default. Each offload can be enabled or
> disabled using the existing DEV_TX_OFFLOADS_* or DEV_RX_OFFLOADS_* flags.
> Such API will enable to easily add or remove offloads, without breaking the
> ABI compatibility.

It should be updated since offloads are configured now per-port and 
per-queue.

> The new API does not have an equivalent for the below Tx flags:
>
> * ETH_TXQ_FLAGS_NOREFCOUNT
> * ETH_TXQ_FLAGS_NOMULTMEMP
>
> The reason is that those flags are not to manage offloads, rather some
> guarantee from application on the way it uses mbufs, therefore could not be
> present as part of DEV_TX_OFFLOADS_*.
> Such flags are useful only for benchmarks, and therefore provide a non-realistic
> performance for DPDK customers using simple benchmarks for evaluation.
> Leveraging the work being done in this series to clean up those flags.

It should be updated since now you care about these flags as well.

> In order to provide a smooth transition between the APIs the following actions
> were taken:
> *  The old offloads API is kept for the meanwhile.
> *  New capabilities were added for PMD to advertize it has moved to the new
>     offloads API.
> *  Helper function which copy from old to new API were added to ethdev,
>     enabling the PMD to support only one of the APIs.
>
> Per discussion made on the RFC of this series [1], the integration plan which was
> decided is to do the transition in two phases:
> * ethdev API will move on 17.11.
> * Apps and examples will move on 18.02.
>
> This to enable PMD maintainers sufficient time to adopt the new API.
>
> [1]
> http://dpdk.org/ml/archives/dev/2017-August/072643.html
>
> on v3:
>   - Introduce the DEV_TX_OFFLOAD_MBUF_FAST_FREE to act as an equivalent
>     for the no refcnt and single mempool flags.
>   - Fix features documentation.
>   - Fix commnet style.
>
> on v2:
>   - Taking new approach of dividing offloads into per-queue and per-port one.
>   - Postpone the Tx/Rx public struct renaming to 18.02
>   - squash the helper functions into the Rx/Tx offloads intro patches.
>
> Shahaf Shuler (2):
>    ethdev: introduce Rx queue offloads API
>    ethdev: introduce Tx queue offloads API
>
>   doc/guides/nics/features.rst  |  66 +++++++----
>   lib/librte_ether/rte_ethdev.c | 220 ++++++++++++++++++++++++++++++++++---
>   lib/librte_ether/rte_ethdev.h |  89 ++++++++++++++-
>   3 files changed, 335 insertions(+), 40 deletions(-)

Many thanks for your work on this patch series.

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2 16/17] build: add option to version libs using DPDK version
  2017-09-12 10:38  3%   ` [dpdk-dev] [PATCH v2 16/17] build: add option to version libs using DPDK version Bruce Richardson
@ 2017-09-13 11:32  5%     ` Luca Boccassi
  2017-09-13 13:11  0%       ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Luca Boccassi @ 2017-09-13 11:32 UTC (permalink / raw)
  To: Bruce Richardson, dev; +Cc: nhorman, harry.van.haaren, Christian Ehrhardt

On Tue, 2017-09-12 at 11:38 +0100, Bruce Richardson wrote:
> Normally, each library has it's own version number based on the ABI.
> Add an option to have all libs just use the DPDK version number as
> the
> .so version.
> 
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> Reviewed-by: Harry van Haaren <harry.van.haaren@intel.com>
> ---
>  drivers/meson.build | 8 +++++++-
>  lib/meson.build     | 8 +++++++-
>  meson_options.txt   | 1 +
>  3 files changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/meson.build b/drivers/meson.build
> index f19da16fb..0c251bd61 100644
> --- a/drivers/meson.build
> +++ b/drivers/meson.build
> @@ -92,6 +92,12 @@ foreach class:driver_classes
>  						depends:
> [pmdinfogen, tmp_lib])
>  			endforeach
>  
> +			if get_option('per_library_versions')
> +				so_version = '@0@.1'.format(version)
> +			else
> +				so_version = meson.project_version()
> +			endif
> +
>  			# now build the driver itself, and add to
> the drivers list
>  			lib_name = driver_name_fmt.format(name)
>  			version_map = '@0@/@1@/@2@_version.map'.form
> at(
> @@ -105,7 +111,7 @@ foreach class:driver_classes
>  				c_args: cflags,
>  				link_args: '-Wl,--version-script=' +
> version_map,
>  				link_depends: version_map,
> -				version: '@0@.1'.format(version),
> +				version: so_version,
>  				install: true,
>  				install_dir: driver_install_path)
>  
> diff --git a/lib/meson.build b/lib/meson.build
> index d814721de..36652cfe1 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -76,6 +76,12 @@ foreach l:libraries
>  			dep_objs += [get_variable('dep_rte_' + d)]
>  		endforeach
>  
> +		if get_option('per_library_versions')
> +			so_version = '@0@.1'.format(version)
> +		else
> +			so_version = meson.project_version()
> +		endif
> +
>  		version_map = '@0@/@1@/rte_@2@_version.map'.format(
>  				meson.current_source_dir(),
> dir_name, name)
>  		libname = 'rte_' + name
> @@ -87,7 +93,7 @@ foreach l:libraries
>  				include_directories:
> include_directories(dir_name),
>  				link_args: '-Wl,--version-script=' +
> version_map,
>  				link_depends: version_map,
> -				version: '@0@.1'.format(version),
> +				version: so_version,
>  				install: true)
>  		dep = declare_dependency(link_with: lib,
>  				include_directories:
> include_directories(dir_name),
> diff --git a/meson_options.txt b/meson_options.txt
> index 9c45b8159..636226ce8 100644
> --- a/meson_options.txt
> +++ b/meson_options.txt
> @@ -6,3 +6,4 @@ option('allow_invalid_socket_id', type: 'boolean',
> value: false,
>  	description: 'allow out-of-range NUMA socket id\'s for
> platforms that don\'t report the value correctly')
>  option('enable_kmods', type: 'boolean', value: true, description:
> 'build kernel modules')
>  option('kernel_dir', type: 'string', value: '', description: 'path
> to the kernel for building kernel modules')
> +option('per_library_versions', type: 'boolean', value: true,
> description: 'true: each lib gets its own version number, false: DPDK
> version used for each lib')

Hi Bruce,

First of all thanks for implementing this option, and sorry for the
delay.

A couple of minor things:

1) The project version has 3 digits, but the ABI version should have 2
- eg: should be 17.08 but right now it's 17.08.0 - given point releases
will be ABI compatible so they must not change the ABI version. In the
packaging code we use cut to chop it off:

DPDK_ABI := $(shell echo $(DEB_VERSION_UPSTREAM) | cut -d '.'  -f1-2)

Not sure how to achieve the same in a Meson script though (can it shell
out? or are there string manipulation built-ins?), sorry - just
starting to look at it.

Right now the rte_config option allows the user to completely override
the version - I'm fine with having a single boolean provided this
change is applied, it simplifies packaging a bit, but if it's easier
for you to just accepted a version instead of a boolean it's fine as
well, as you prefer

2) When the option is true, it should not generate a symlink with the
ABI "revision", as the first digit is really not the revision, so it
does not make much sense. Worse, it will stop 2 versions being co-
installable (which was the whole point :-) ), as, eg, 17.02, 17.05 and
17.08 will all ship a libfoo.so.17 symlink. I can fix it in the
packaging, but I don't think it should be generated upstream at all
when this option is enabled.

IOW, the following is the current result:

$ ls -l debian/librte-ethdev17.08/usr/lib/x86_64-linux-gnu/
total 72
lrwxrwxrwx 1 lboccass lboccass    24 Sep 13 11:50 librte_ethdev.so.17 -> librte_ethdev.so.17.08.0
-rw-r--r-- 1 lboccass lboccass 71672 Sep 13 11:50 librte_ethdev.so.17.08.0

The expected result would be to create a single file "librte_ethdev.so.17.08" instead.

-- 
Kind regards,
Luca Boccassi

^ permalink raw reply	[relevance 5%]

* Re: [dpdk-dev] [PATCH v2 16/17] build: add option to version libs using DPDK version
  2017-09-13 11:32  5%     ` Luca Boccassi
@ 2017-09-13 13:11  0%       ` Bruce Richardson
  2017-09-13 17:02  0%         ` Luca Boccassi
  0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2017-09-13 13:11 UTC (permalink / raw)
  To: Luca Boccassi; +Cc: dev, nhorman, harry.van.haaren, Christian Ehrhardt

On Wed, Sep 13, 2017 at 12:32:24PM +0100, Luca Boccassi wrote:
> On Tue, 2017-09-12 at 11:38 +0100, Bruce Richardson wrote:
> > Normally, each library has it's own version number based on the ABI.
> > Add an option to have all libs just use the DPDK version number as
> > the
> > .so version.
> > 
> > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > Reviewed-by: Harry van Haaren <harry.van.haaren@intel.com>
> > ---
> >  drivers/meson.build | 8 +++++++-
> >  lib/meson.build     | 8 +++++++-
> >  meson_options.txt   | 1 +
> >  3 files changed, 15 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/meson.build b/drivers/meson.build
> > index f19da16fb..0c251bd61 100644
> > --- a/drivers/meson.build
> > +++ b/drivers/meson.build
> > @@ -92,6 +92,12 @@ foreach class:driver_classes
> >  						depends:
> > [pmdinfogen, tmp_lib])
> >  			endforeach
> >  
> > +			if get_option('per_library_versions')
> > +				so_version = '@0@.1'.format(version)
> > +			else
> > +				so_version = meson.project_version()
> > +			endif
> > +
> >  			# now build the driver itself, and add to
> > the drivers list
> >  			lib_name = driver_name_fmt.format(name)
> >  			version_map = '@0@/@1@/@2@_version.map'.form
> > at(
> > @@ -105,7 +111,7 @@ foreach class:driver_classes
> >  				c_args: cflags,
> >  				link_args: '-Wl,--version-script=' +
> > version_map,
> >  				link_depends: version_map,
> > -				version: '@0@.1'.format(version),
> > +				version: so_version,
> >  				install: true,
> >  				install_dir: driver_install_path)
> >  
> > diff --git a/lib/meson.build b/lib/meson.build
> > index d814721de..36652cfe1 100644
> > --- a/lib/meson.build
> > +++ b/lib/meson.build
> > @@ -76,6 +76,12 @@ foreach l:libraries
> >  			dep_objs += [get_variable('dep_rte_' + d)]
> >  		endforeach
> >  
> > +		if get_option('per_library_versions')
> > +			so_version = '@0@.1'.format(version)
> > +		else
> > +			so_version = meson.project_version()
> > +		endif
> > +
> >  		version_map = '@0@/@1@/rte_@2@_version.map'.format(
> >  				meson.current_source_dir(),
> > dir_name, name)
> >  		libname = 'rte_' + name
> > @@ -87,7 +93,7 @@ foreach l:libraries
> >  				include_directories:
> > include_directories(dir_name),
> >  				link_args: '-Wl,--version-script=' +
> > version_map,
> >  				link_depends: version_map,
> > -				version: '@0@.1'.format(version),
> > +				version: so_version,
> >  				install: true)
> >  		dep = declare_dependency(link_with: lib,
> >  				include_directories:
> > include_directories(dir_name),
> > diff --git a/meson_options.txt b/meson_options.txt
> > index 9c45b8159..636226ce8 100644
> > --- a/meson_options.txt
> > +++ b/meson_options.txt
> > @@ -6,3 +6,4 @@ option('allow_invalid_socket_id', type: 'boolean',
> > value: false,
> >  	description: 'allow out-of-range NUMA socket id\'s for
> > platforms that don\'t report the value correctly')
> >  option('enable_kmods', type: 'boolean', value: true, description:
> > 'build kernel modules')
> >  option('kernel_dir', type: 'string', value: '', description: 'path
> > to the kernel for building kernel modules')
> > +option('per_library_versions', type: 'boolean', value: true,
> > description: 'true: each lib gets its own version number, false: DPDK
> > version used for each lib')
> 
> Hi Bruce,
> 
> First of all thanks for implementing this option, and sorry for the
> delay.
> 
> A couple of minor things:
> 
> 1) The project version has 3 digits, but the ABI version should have 2
> - eg: should be 17.08 but right now it's 17.08.0 - given point releases
> will be ABI compatible so they must not change the ABI version. In the
> packaging code we use cut to chop it off:
> 
> DPDK_ABI := $(shell echo $(DEB_VERSION_UPSTREAM) | cut -d '.'  -f1-2)
> 
> Not sure how to achieve the same in a Meson script though (can it shell
> out? or are there string manipulation built-ins?), sorry - just
> starting to look at it.
> 
That should be easy enough to do. It's 3-digits because I'm just pulling
the project version unmodified from the initial project definition. I'd
say I can manage to strip off one digit as part of the build.

> Right now the rte_config option allows the user to completely override
> the version - I'm fine with having a single boolean provided this
> change is applied, it simplifies packaging a bit, but if it's easier
> for you to just accepted a version instead of a boolean it's fine as
> well, as you prefer

If there is a case where we might want to provide a particular version,
I'm happy to edit the option, but if not I'll keep it as-is, because it
will ensure all users of the option get the exact same behaviour, and
means I only have two possibilities to test.

> 
> 2) When the option is true, it should not generate a symlink with the
> ABI "revision", as the first digit is really not the revision, so it
> does not make much sense. Worse, it will stop 2 versions being co-
> installable (which was the whole point :-) ), as, eg, 17.02, 17.05 and
> 17.08 will all ship a libfoo.so.17 symlink. I can fix it in the
> packaging, but I don't think it should be generated upstream at all
> when this option is enabled.

Not exactly sure how to fix this, but I think it may work by using
soversion as well as version in the library() calls.

> 
> IOW, the following is the current result:
> 
> $ ls -l debian/librte-ethdev17.08/usr/lib/x86_64-linux-gnu/
> total 72
> lrwxrwxrwx 1 lboccass lboccass    24 Sep 13 11:50 librte_ethdev.so.17 -> librte_ethdev.so.17.08.0
> -rw-r--r-- 1 lboccass lboccass 71672 Sep 13 11:50 librte_ethdev.so.17.08.0
> 
> The expected result would be to create a single file "librte_ethdev.so.17.08" instead.
> 

Let me see what I can do :-)

/Bruce

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v3] devtools: rework abi checker script
  2017-09-11  8:46 26%       ` [dpdk-dev] [PATCH v3] " Olivier Matz
@ 2017-09-13 15:00  9%         ` Neil Horman
  0 siblings, 0 replies; 200+ results
From: Neil Horman @ 2017-09-13 15:00 UTC (permalink / raw)
  To: Olivier Matz; +Cc: dev, bruce.richardson

On Mon, Sep 11, 2017 at 10:46:35AM +0200, Olivier Matz wrote:
> The initial version of the script had some limitations:
> - cannot work on a non-clean workspace
> - environment variables are not documented
> - no compilation log in case of failure
> - return success even it abi is incompatible
> 
> This patch addresses these issues and rework the code.
> 
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> ---
> 
> v2->v3:
> - fix when not launched from dpdk root dir
> - use "-Og -Wno-error" instead of "-O0"
> - fix typo in commit log
> 
> v1->v2:
> - use /usr/bin/env to find bash (which is required)
> - fix displayed path to html reports
> - reword help for -f option
> 
>  devtools/validate-abi.sh | 392 ++++++++++++++++++++++++-----------------------
>  1 file changed, 200 insertions(+), 192 deletions(-)
> 

This is alot closer, I think theres just a little wierdness left.  When running
this checker script, the end of the log shows this:

CMD: abi-compliance-checker -l librte_vhost.so -old /home/nhorman/git/dpdk/devtools/abi-check/222555480/librte_vhost.so.dump -new /home/nhorman/git/dpdk/devtools/abi-check/02657b4ad/librte_vhost.so.dump
NOTICE: At least one call to abi-compliance-checker returned an error.
NOTICE: ABI may be incompatible, please check logs for details.
NOTICE: Incompatible list:  librte_cryptodev.so librte_eal.so librte_efd.so librte_ethdev.so librte_eventdev.so librte_hash.so librte_pdump.so librte_pmd_crypto_scheduler.so librte_pmd_ring.so librte_ring.so

Which I think is something of a false positive.  The line:
NOTICE: At least one call to abi-compliance-checker returned an error.

I think is emitted simply because abi-compilance-checker returns non-zero and
reports that error if it finds any incompatibilities.  I'm not sure we want to
flag that as an error per se.  It gives the impression something has gone wrong,
rather than correctly identifying that there are incompatibilities.

Though on the other hand, maybe we do want to set that red flag so people look
at what the incompatibilities are.  As I say it out loud, perhaps that
preferable.

Thoughts
Neil

^ permalink raw reply	[relevance 9%]

* [dpdk-dev] [PATCH v3 04/17] build: add DPDK libraries to build
  @ 2017-09-13 14:12  1%     ` Bruce Richardson
  2017-09-13 14:12  3%     ` [dpdk-dev] [PATCH v3 16/17] build: add option to version libs using DPDK version Bruce Richardson
  2017-09-13 14:12  3%     ` [dpdk-dev] [PATCH v3 17/17] doc: add documentation on how to add new components to DPDK Bruce Richardson
  2 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2017-09-13 14:12 UTC (permalink / raw)
  To: dev
  Cc: nhorman, luca.boccassi, harry.van.haaren, keith.wiles, Bruce Richardson

Add non-EAL libraries to DPDK build. The compat lib is a special case,
along with the previously-added EAL, but all other libs can be build using
the same set of commands, where the individual meson.build files only need
to specify their dependencies, source files, header files and ABI versions.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 config/rte_config.h                 | 36 ++++++++++++++++++++
 lib/librte_acl/meson.build          | 59 ++++++++++++++++++++++++++++++++
 lib/librte_bitratestats/meson.build | 34 +++++++++++++++++++
 lib/librte_cfgfile/meson.build      | 34 +++++++++++++++++++
 lib/librte_cmdline/meson.build      | 55 ++++++++++++++++++++++++++++++
 lib/librte_compat/meson.build       | 36 ++++++++++++++++++++
 lib/librte_cryptodev/meson.build    | 40 ++++++++++++++++++++++
 lib/librte_distributor/meson.build  | 39 +++++++++++++++++++++
 lib/librte_efd/meson.build          | 34 +++++++++++++++++++
 lib/librte_ether/meson.build        | 45 +++++++++++++++++++++++++
 lib/librte_eventdev/meson.build     | 36 ++++++++++++++++++++
 lib/librte_gro/meson.build          | 34 +++++++++++++++++++
 lib/librte_hash/meson.build         | 45 +++++++++++++++++++++++++
 lib/librte_ip_frag/meson.build      | 39 +++++++++++++++++++++
 lib/librte_jobstats/meson.build     | 33 ++++++++++++++++++
 lib/librte_kni/meson.build          | 38 +++++++++++++++++++++
 lib/librte_kvargs/meson.build       | 34 +++++++++++++++++++
 lib/librte_latencystats/meson.build | 34 +++++++++++++++++++
 lib/librte_lpm/meson.build          | 35 +++++++++++++++++++
 lib/librte_mbuf/meson.build         | 35 +++++++++++++++++++
 lib/librte_mempool/meson.build      | 35 +++++++++++++++++++
 lib/librte_meter/meson.build        | 33 ++++++++++++++++++
 lib/librte_metrics/meson.build      | 33 ++++++++++++++++++
 lib/librte_net/meson.build          | 45 +++++++++++++++++++++++++
 lib/librte_pdump/meson.build        | 34 +++++++++++++++++++
 lib/librte_pipeline/meson.build     | 35 +++++++++++++++++++
 lib/librte_port/meson.build         | 58 ++++++++++++++++++++++++++++++++
 lib/librte_power/meson.build        | 37 ++++++++++++++++++++
 lib/librte_reorder/meson.build      | 34 +++++++++++++++++++
 lib/librte_ring/meson.build         | 33 ++++++++++++++++++
 lib/librte_sched/meson.build        | 36 ++++++++++++++++++++
 lib/librte_table/meson.build        | 52 ++++++++++++++++++++++++++++
 lib/librte_timer/meson.build        | 33 ++++++++++++++++++
 lib/librte_vhost/meson.build        | 39 +++++++++++++++++++++
 lib/meson.build                     | 67 +++++++++++++++++++++++++++++++++++++
 35 files changed, 1379 insertions(+)
 create mode 100644 lib/librte_acl/meson.build
 create mode 100644 lib/librte_bitratestats/meson.build
 create mode 100644 lib/librte_cfgfile/meson.build
 create mode 100644 lib/librte_cmdline/meson.build
 create mode 100644 lib/librte_compat/meson.build
 create mode 100644 lib/librte_cryptodev/meson.build
 create mode 100644 lib/librte_distributor/meson.build
 create mode 100644 lib/librte_efd/meson.build
 create mode 100644 lib/librte_ether/meson.build
 create mode 100644 lib/librte_eventdev/meson.build
 create mode 100644 lib/librte_gro/meson.build
 create mode 100644 lib/librte_hash/meson.build
 create mode 100644 lib/librte_ip_frag/meson.build
 create mode 100644 lib/librte_jobstats/meson.build
 create mode 100644 lib/librte_kni/meson.build
 create mode 100644 lib/librte_kvargs/meson.build
 create mode 100644 lib/librte_latencystats/meson.build
 create mode 100644 lib/librte_lpm/meson.build
 create mode 100644 lib/librte_mbuf/meson.build
 create mode 100644 lib/librte_mempool/meson.build
 create mode 100644 lib/librte_meter/meson.build
 create mode 100644 lib/librte_metrics/meson.build
 create mode 100644 lib/librte_net/meson.build
 create mode 100644 lib/librte_pdump/meson.build
 create mode 100644 lib/librte_pipeline/meson.build
 create mode 100644 lib/librte_port/meson.build
 create mode 100644 lib/librte_power/meson.build
 create mode 100644 lib/librte_reorder/meson.build
 create mode 100644 lib/librte_ring/meson.build
 create mode 100644 lib/librte_sched/meson.build
 create mode 100644 lib/librte_table/meson.build
 create mode 100644 lib/librte_timer/meson.build
 create mode 100644 lib/librte_vhost/meson.build

diff --git a/config/rte_config.h b/config/rte_config.h
index c94704cfe..b47cfabae 100644
--- a/config/rte_config.h
+++ b/config/rte_config.h
@@ -58,4 +58,40 @@
 #define RTE_BACKTRACE 1
 #define RTE_EAL_VFIO 1
 
+/* mempool defines */
+#define RTE_MEMPOOL_CACHE_MAX_SIZE 512
+
+/* mbuf defines */
+#define RTE_MBUF_DEFAULT_MEMPOOL_OPS "ring_mp_mc"
+#define RTE_MBUF_REFCNT_ATOMIC 1
+#define RTE_PKTMBUF_HEADROOM 128
+
+/* ether defines */
+#define RTE_MAX_ETHPORTS 32
+#define RTE_MAX_QUEUES_PER_PORT 1024
+#define RTE_ETHDEV_QUEUE_STAT_CNTRS 16
+#define RTE_ETHDEV_RXTX_CALLBACKS 1
+
+/* cryptodev defines */
+#define RTE_CRYPTO_MAX_DEVS 64
+#define RTE_CRYPTODEV_NAME_LEN 64
+
+/* eventdev defines */
+#define RTE_EVENT_MAX_DEVS 16
+#define RTE_EVENT_MAX_QUEUES_PER_DEV 64
+
+/* ip_fragmentation defines */
+#define RTE_LIBRTE_IP_FRAG_MAX_FRAG 4
+#undef RTE_LIBRTE_IP_FRAG_TBL_STAT
+
+/* rte_power defines */
+#define RTE_MAX_LCORE_FREQS 64
+
+/* rte_sched defines */
+#undef RTE_SCHED_RED
+#undef RTE_SCHED_COLLECT_STATS
+#undef RTE_SCHED_SUBPORT_TC_OV
+#define RTE_SCHED_PORT_N_GRINDERS 8
+#undef RTE_SCHED_VECTOR
+
 #endif /* _RTE_CONFIG_H_ */
diff --git a/lib/librte_acl/meson.build b/lib/librte_acl/meson.build
new file mode 100644
index 000000000..b81b74468
--- /dev/null
+++ b/lib/librte_acl/meson.build
@@ -0,0 +1,59 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('acl_bld.c', 'acl_gen.c', 'acl_run_scalar.c',
+		'rte_acl.c', 'tb_mem.c')
+headers = files('rte_acl.h', 'rte_acl_osdep.h')
+
+if arch_subdir == 'x86'
+	sources += files('acl_run_sse.c')
+
+	# compile AVX2 version if either:
+	# a. we have AVX supported in minimum instruction set baseline
+	# b. it's not minimum instruction set, but supported by compiler
+	#
+	# in former case, just add avx2 C file to files list
+	# in latter case, compile c file to static lib, using correct compiler
+	# flags, and then have the .o file from static lib linked into main lib.
+	if dpdk_conf.has('RTE_MACHINE_CPUFLAG_AVX2')
+		sources += files('acl_run_avx2.c')
+		cflags += '-DCC_AVX2_SUPPORT'
+	elif cc.has_argument('-mavx2')
+		avx2_tmplib = static_library('avx2_tmp',
+				'acl_run_avx2.c',
+				dependencies: rte_eal,
+				c_args: '-mavx2')
+		objs += avx2_tmplib.extract_objects('acl_run_avx2.c')
+		cflags += '-DCC_AVX2_SUPPORT'
+	endif
+
+endif
diff --git a/lib/librte_bitratestats/meson.build b/lib/librte_bitratestats/meson.build
new file mode 100644
index 000000000..dcf6070bf
--- /dev/null
+++ b/lib/librte_bitratestats/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_bitrate.c')
+headers = files('rte_bitrate.h')
+deps += ['ethdev', 'metrics']
diff --git a/lib/librte_cfgfile/meson.build b/lib/librte_cfgfile/meson.build
new file mode 100644
index 000000000..1a4992ff3
--- /dev/null
+++ b/lib/librte_cfgfile/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('rte_cfgfile.c')
+headers = files('rte_cfgfile.h')
diff --git a/lib/librte_cmdline/meson.build b/lib/librte_cmdline/meson.build
new file mode 100644
index 000000000..80fbe5d07
--- /dev/null
+++ b/lib/librte_cmdline/meson.build
@@ -0,0 +1,55 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('cmdline.c',
+	'cmdline_cirbuf.c',
+	'cmdline_parse.c',
+	'cmdline_parse_etheraddr.c',
+	'cmdline_parse_ipaddr.c',
+	'cmdline_parse_num.c',
+	'cmdline_parse_portlist.c',
+	'cmdline_parse_string.c',
+	'cmdline_rdline.c',
+	'cmdline_socket.c',
+	'cmdline_vt100.c')
+
+headers = files('cmdline.h',
+	'cmdline_parse.h',
+	'cmdline_parse_num.h',
+	'cmdline_parse_ipaddr.h',
+	'cmdline_parse_etheraddr.h',
+	'cmdline_parse_string.h',
+	'cmdline_rdline.h',
+	'cmdline_vt100.h',
+	'cmdline_socket.h',
+	'cmdline_cirbuf.h',
+	'cmdline_parse_portlist.h')
diff --git a/lib/librte_compat/meson.build b/lib/librte_compat/meson.build
new file mode 100644
index 000000000..3b911dfff
--- /dev/null
+++ b/lib/librte_compat/meson.build
@@ -0,0 +1,36 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+
+install_headers('rte_compat.h')
+
+set_variable('dep_rte_compat',
+	declare_dependency(include_directories: include_directories('.')))
diff --git a/lib/librte_cryptodev/meson.build b/lib/librte_cryptodev/meson.build
new file mode 100644
index 000000000..e45e7098a
--- /dev/null
+++ b/lib/librte_cryptodev/meson.build
@@ -0,0 +1,40 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 3
+sources = files('rte_cryptodev.c', 'rte_cryptodev_pmd.c')
+headers = files('rte_cryptodev.h',
+	'rte_cryptodev_pci.h',
+	'rte_cryptodev_pmd.h',
+	'rte_cryptodev_vdev.h',
+	'rte_crypto.h',
+	'rte_crypto_sym.h')
+deps += ['kvargs', 'mbuf']
diff --git a/lib/librte_distributor/meson.build b/lib/librte_distributor/meson.build
new file mode 100644
index 000000000..6118c5f50
--- /dev/null
+++ b/lib/librte_distributor/meson.build
@@ -0,0 +1,39 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_distributor.c', 'rte_distributor_v20.c')
+if arch_subdir == 'x86'
+	sources += files('rte_distributor_match_sse.c')
+else
+	sources += files('rte_distributor_match_generic.c')
+endif
+headers = files('rte_distributor.h')
+deps += ['mbuf', 'compat']
diff --git a/lib/librte_efd/meson.build b/lib/librte_efd/meson.build
new file mode 100644
index 000000000..73c004e70
--- /dev/null
+++ b/lib/librte_efd/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_efd.c')
+headers = files('rte_efd.h')
+deps += ['ring', 'hash']
diff --git a/lib/librte_ether/meson.build b/lib/librte_ether/meson.build
new file mode 100644
index 000000000..d10bd37d5
--- /dev/null
+++ b/lib/librte_ether/meson.build
@@ -0,0 +1,45 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+name = 'ethdev'
+version = 6
+sources = files('rte_ethdev.c', 'rte_flow.c', 'rte_tm.c')
+
+headers = files('rte_ethdev.h',
+	'rte_ethdev_pci.h',
+	'rte_ethdev_vdev.h',
+	'rte_eth_ctrl.h',
+	'rte_dev_info.h',
+	'rte_flow.h',
+	'rte_flow_driver.h',
+	'rte_tm.h')
+
+deps += ['net']
diff --git a/lib/librte_eventdev/meson.build b/lib/librte_eventdev/meson.build
new file mode 100644
index 000000000..60d5f4e89
--- /dev/null
+++ b/lib/librte_eventdev/meson.build
@@ -0,0 +1,36 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_eventdev.c', 'rte_event_ring.c')
+headers = files('rte_eventdev.h', 'rte_eventdev_pmd.h',
+		'rte_eventdev_pmd_pci.h', 'rte_eventdev_pmd_vdev.h',
+		'rte_event_ring.h')
+deps += ['ring']
diff --git a/lib/librte_gro/meson.build b/lib/librte_gro/meson.build
new file mode 100644
index 000000000..f6848c42b
--- /dev/null
+++ b/lib/librte_gro/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_gro.c', 'gro_tcp4.c')
+headers = files('rte_gro.h')
+deps += ['ethdev']
diff --git a/lib/librte_hash/meson.build b/lib/librte_hash/meson.build
new file mode 100644
index 000000000..1df383f4b
--- /dev/null
+++ b/lib/librte_hash/meson.build
@@ -0,0 +1,45 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+headers = files('rte_cmp_arm64.h',
+	'rte_cmp_x86.h',
+	'rte_crc_arm64.h',
+	'rte_cuckoo_hash.h',
+	'rte_cuckoo_hash_x86.h',
+	'rte_fbk_hash.h',
+	'rte_hash_crc.h',
+	'rte_hash.h',
+	'rte_jhash.h',
+	'rte_thash.h')
+
+sources = files('rte_cuckoo_hash.c', 'rte_fbk_hash.c')
+deps += ['ring', 'compat']
diff --git a/lib/librte_ip_frag/meson.build b/lib/librte_ip_frag/meson.build
new file mode 100644
index 000000000..11523badf
--- /dev/null
+++ b/lib/librte_ip_frag/meson.build
@@ -0,0 +1,39 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_ipv4_fragmentation.c',
+		'rte_ipv6_fragmentation.c',
+		'rte_ipv4_reassembly.c',
+		'rte_ipv6_reassembly.c',
+		'rte_ip_frag_common.c',
+		'ip_frag_internal.c')
+headers = files('rte_ip_frag.h')
+deps += ['ethdev', 'hash']
diff --git a/lib/librte_jobstats/meson.build b/lib/librte_jobstats/meson.build
new file mode 100644
index 000000000..97cf01cad
--- /dev/null
+++ b/lib/librte_jobstats/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_jobstats.c')
+headers = files('rte_jobstats.h')
diff --git a/lib/librte_kni/meson.build b/lib/librte_kni/meson.build
new file mode 100644
index 000000000..25934a46d
--- /dev/null
+++ b/lib/librte_kni/meson.build
@@ -0,0 +1,38 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+if host_machine.system() != 'linux'
+	build = false
+endif
+version = 2
+sources = files('rte_kni.c')
+headers = files('rte_kni.h')
+deps += ['ethdev']
diff --git a/lib/librte_kvargs/meson.build b/lib/librte_kvargs/meson.build
new file mode 100644
index 000000000..2962fc370
--- /dev/null
+++ b/lib/librte_kvargs/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 1
+sources = files('rte_kvargs.c')
+headers = files('rte_kvargs.h')
diff --git a/lib/librte_latencystats/meson.build b/lib/librte_latencystats/meson.build
new file mode 100644
index 000000000..10a778433
--- /dev/null
+++ b/lib/librte_latencystats/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_latencystats.c')
+headers = files('rte_latencystats.h')
+deps += ['metrics', 'ethdev']
diff --git a/lib/librte_lpm/meson.build b/lib/librte_lpm/meson.build
new file mode 100644
index 000000000..af88a97ec
--- /dev/null
+++ b/lib/librte_lpm/meson.build
@@ -0,0 +1,35 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('rte_lpm.c', 'rte_lpm6.c')
+headers = files('rte_lpm.h', 'rte_lpm6.h')
+deps += ['compat']
diff --git a/lib/librte_mbuf/meson.build b/lib/librte_mbuf/meson.build
new file mode 100644
index 000000000..96856e231
--- /dev/null
+++ b/lib/librte_mbuf/meson.build
@@ -0,0 +1,35 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 3
+sources = files('rte_mbuf.c', 'rte_mbuf_ptype.c')
+headers = files('rte_mbuf.h', 'rte_mbuf_ptype.h')
+deps += ['mempool']
diff --git a/lib/librte_mempool/meson.build b/lib/librte_mempool/meson.build
new file mode 100644
index 000000000..96e582deb
--- /dev/null
+++ b/lib/librte_mempool/meson.build
@@ -0,0 +1,35 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('rte_mempool.c', 'rte_mempool_ops.c')
+headers = files('rte_mempool.h')
+deps += ['ring']
diff --git a/lib/librte_meter/meson.build b/lib/librte_meter/meson.build
new file mode 100644
index 000000000..debcebcc1
--- /dev/null
+++ b/lib/librte_meter/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_meter.c')
+headers = files('rte_meter.h')
diff --git a/lib/librte_metrics/meson.build b/lib/librte_metrics/meson.build
new file mode 100644
index 000000000..c820503f0
--- /dev/null
+++ b/lib/librte_metrics/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_metrics.c')
+headers = files('rte_metrics.h')
diff --git a/lib/librte_net/meson.build b/lib/librte_net/meson.build
new file mode 100644
index 000000000..62bbf4c22
--- /dev/null
+++ b/lib/librte_net/meson.build
@@ -0,0 +1,45 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 1
+headers = files('rte_ip.h',
+	'rte_tcp.h',
+	'rte_udp.h',
+	'rte_sctp.h',
+	'rte_icmp.h',
+	'rte_arp.h',
+	'rte_ether.h',
+	'rte_gre.h',
+	'rte_net.h',
+	'rte_net_crc.h')
+
+sources = files('rte_net.c', 'rte_net_crc.c')
+deps += ['mbuf']
diff --git a/lib/librte_pdump/meson.build b/lib/librte_pdump/meson.build
new file mode 100644
index 000000000..94a92b677
--- /dev/null
+++ b/lib/librte_pdump/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_pdump.c')
+headers = files('rte_pdump.h')
+deps += ['ethdev']
diff --git a/lib/librte_pipeline/meson.build b/lib/librte_pipeline/meson.build
new file mode 100644
index 000000000..54e34fc62
--- /dev/null
+++ b/lib/librte_pipeline/meson.build
@@ -0,0 +1,35 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 3
+sources = files('rte_pipeline.c')
+headers = files('rte_pipeline.h')
+deps += ['port', 'table']
diff --git a/lib/librte_port/meson.build b/lib/librte_port/meson.build
new file mode 100644
index 000000000..a0d3a8c07
--- /dev/null
+++ b/lib/librte_port/meson.build
@@ -0,0 +1,58 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 3
+sources = files(
+	'rte_port_ethdev.c',
+	'rte_port_fd.c',
+	'rte_port_ring.c',
+	'rte_port_sched.c',
+	'rte_port_source_sink.c')
+headers = files(
+	'rte_port_ethdev.h',
+	'rte_port_fd.h',
+	'rte_port.h',
+	'rte_port_ring.h',
+	'rte_port_sched.h',
+	'rte_port_source_sink.h')
+deps += ['ethdev', 'sched']
+
+if dpdk_conf.has('RTE_LIBRTE_IP_FRAG')
+	sources += files('rte_port_frag.c', 'rte_port_ras.c')
+	headers += files('rte_port_frag.h', 'rte_port_ras.h')
+	deps += ['ip_frag']
+endif
+
+if dpdk_conf.has('RTE_LIBRTE_KNI')
+	sources += files('rte_port_kni.c')
+	headers += files('rte_port_kni.h')
+	deps += 'kni'
+endif
diff --git a/lib/librte_power/meson.build b/lib/librte_power/meson.build
new file mode 100644
index 000000000..541efa6a4
--- /dev/null
+++ b/lib/librte_power/meson.build
@@ -0,0 +1,37 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+if host_machine.system() != 'linux'
+	build = false
+endif
+sources = files('rte_power.c', 'rte_power_acpi_cpufreq.c',
+		'rte_power_kvm_vm.c', 'guest_channel.c')
+headers = files('rte_power.h')
diff --git a/lib/librte_reorder/meson.build b/lib/librte_reorder/meson.build
new file mode 100644
index 000000000..456e83f02
--- /dev/null
+++ b/lib/librte_reorder/meson.build
@@ -0,0 +1,34 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_reorder.c')
+headers = files('rte_reorder.h')
+deps += ['mbuf']
diff --git a/lib/librte_ring/meson.build b/lib/librte_ring/meson.build
new file mode 100644
index 000000000..8c102fe6a
--- /dev/null
+++ b/lib/librte_ring/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_ring.c')
+headers = files('rte_ring.h')
diff --git a/lib/librte_sched/meson.build b/lib/librte_sched/meson.build
new file mode 100644
index 000000000..c4badb211
--- /dev/null
+++ b/lib/librte_sched/meson.build
@@ -0,0 +1,36 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_sched.c', 'rte_red.c', 'rte_approx.c',
+		'rte_reciprocal.c')
+headers = files('rte_sched.h', 'rte_bitmap.h', 'rte_sched_common.h',
+		'rte_red.h', 'rte_approx.h', 'rte_reciprocal.h')
+deps += ['mbuf', 'meter']
diff --git a/lib/librte_table/meson.build b/lib/librte_table/meson.build
new file mode 100644
index 000000000..2fb3ec804
--- /dev/null
+++ b/lib/librte_table/meson.build
@@ -0,0 +1,52 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+version = 2
+sources = files('rte_table_lpm.c', 'rte_table_lpm_ipv6.c',
+		'rte_table_hash_cuckoo.c', 'rte_table_hash_key8.c',
+		'rte_table_hash_key16.c', 'rte_table_hash_key32.c',
+		'rte_table_hash_ext.c', 'rte_table_hash_lru.c',
+		'rte_table_array.c', 'rte_table_stub.c')
+headers = files('rte_table.h', 'rte_table_lpm.h',
+		'rte_table_lpm_ipv6.h', 'rte_table_hash.h',
+		'rte_lru.h', 'rte_table_array.h',
+		'rte_table_stub.h')
+deps += ['mbuf', 'port', 'lpm', 'hash']
+
+if arch_subdir == 'x86'
+	headers += files('rte_lru_x86.h')
+endif
+
+if dpdk_conf.has('RTE_LIBRTE_ACL')
+	sources += files('rte_table_acl.c')
+	headers += files('rte_table_acl.h')
+	deps += ['acl']
+endif
diff --git a/lib/librte_timer/meson.build b/lib/librte_timer/meson.build
new file mode 100644
index 000000000..0edc45772
--- /dev/null
+++ b/lib/librte_timer/meson.build
@@ -0,0 +1,33 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+sources = files('rte_timer.c')
+headers = files('rte_timer.h')
diff --git a/lib/librte_vhost/meson.build b/lib/librte_vhost/meson.build
new file mode 100644
index 000000000..5482169ca
--- /dev/null
+++ b/lib/librte_vhost/meson.build
@@ -0,0 +1,39 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 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.
+
+if host_machine.system() != 'linux'
+	build = false
+endif
+version = 4
+sources = files('fd_man.c', 'socket.c', 'vhost.c', 'vhost_user.c',
+		'virtio_net.c')
+headers = files('rte_vhost.h')
+deps += ['ethdev']
diff --git a/lib/meson.build b/lib/meson.build
index 7cafe6666..d814721de 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -29,4 +29,71 @@
 #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# special case for eal, not a simple lib, and compat, just a header
 subdir('librte_eal')
+subdir('librte_compat')
+
+# process all libraries equally, as far as possible
+# "core" libs first, then others alphebetically as far as possible
+# NOTE: for speed of meson runs, the dependencies in the subdirectories
+# sometimes skip deps that would be implied by others, e.g. if mempool is
+# given as a dep, no need to mention ring. This is especially true for the
+# core libs which are widely reused, so their deps are kept to a minimum.
+libraries = ['ring', 'mempool', 'mbuf', 'net', 'ether', # core
+	'metrics', # bitrate/latency stats depends on this
+	'hash',    # efd depends on this
+	'kvargs',  # cryptodev depends on this
+	'acl', 'bitratestats', 'cfgfile', 'cmdline', 'cryptodev',
+	'distributor', 'efd', 'eventdev', 'gro', 'ip_frag', 'jobstats',
+	'kni', 'latencystats', 'lpm', 'meter', 'power', 'pdump',
+	'reorder', 'sched', 'timer', 'vhost',
+	# add pkt framework libs which use other libs from above
+	'port', 'table', 'pipeline']
+
+foreach l:libraries
+	build = true
+	name = l
+	version = 1
+	sources = []
+	headers = []
+	cflags = []
+	objs = [] # other object files to link against, used e.g. for instruction-
+	          # optimized versions of code
+	# use "deps" for internal DPDK dependencies, and "ext_deps" for
+	# external package/library requirements
+	deps = ['eal']
+	ext_deps = []
+
+	dir_name = 'librte_' + l
+	subdir(dir_name)
+
+	if build
+		dpdk_conf.set('RTE_LIBRTE_' + name.to_upper(), 1)
+		install_headers(headers)
+
+		dep_objs = ext_deps
+		foreach d:deps
+			dep_objs += [get_variable('dep_rte_' + d)]
+		endforeach
+
+		version_map = '@0@/@1@/rte_@2@_version.map'.format(
+				meson.current_source_dir(), dir_name, name)
+		libname = 'rte_' + name
+		lib = library(libname,
+				sources,
+				objects: objs,
+				c_args: cflags,
+				dependencies: dep_objs,
+				include_directories: include_directories(dir_name),
+				link_args: '-Wl,--version-script=' + version_map,
+				link_depends: version_map,
+				version: '@0@.1'.format(version),
+				install: true)
+		dep = declare_dependency(link_with: lib,
+				include_directories: include_directories(dir_name),
+				dependencies: dep_objs)
+		set_variable('dep_' + libname, dep)
+
+		dpdk_libraries = [lib] + dpdk_libraries
+	endif
+endforeach
-- 
2.13.5

^ permalink raw reply	[relevance 1%]

* [dpdk-dev] [PATCH v3 16/17] build: add option to version libs using DPDK version
    2017-09-13 14:12  1%     ` [dpdk-dev] [PATCH v3 04/17] build: add DPDK libraries to build Bruce Richardson
@ 2017-09-13 14:12  3%     ` Bruce Richardson
  2017-09-13 14:12  3%     ` [dpdk-dev] [PATCH v3 17/17] doc: add documentation on how to add new components to DPDK Bruce Richardson
  2 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2017-09-13 14:12 UTC (permalink / raw)
  To: dev
  Cc: nhorman, luca.boccassi, harry.van.haaren, keith.wiles, Bruce Richardson

Normally, each library has it's own version number based on the ABI.
Add an option to have all libs just use the DPDK version number as the
.so version.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 drivers/meson.build                     | 13 ++++++++++++-
 lib/librte_eal/bsdapp/eal/meson.build   | 12 +++++++++++-
 lib/librte_eal/linuxapp/eal/meson.build | 12 +++++++++++-
 lib/meson.build                         | 12 +++++++++++-
 meson_options.txt                       |  1 +
 5 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/drivers/meson.build b/drivers/meson.build
index f19da16fb..3ea42b04b 100644
--- a/drivers/meson.build
+++ b/drivers/meson.build
@@ -92,6 +92,16 @@ foreach class:driver_classes
 						depends: [pmdinfogen, tmp_lib])
 			endforeach
 
+			if get_option('per_library_versions')
+				lib_version = '@0@.1'.format(version)
+				so_version = '@0@'.format(version)
+			else
+				pver = meson.project_version().split('.')
+				lib_version = '@0@.@1@'.format(pver.get(0),
+						pver.get(1))
+				so_version = lib_version
+			endif
+
 			# now build the driver itself, and add to the drivers list
 			lib_name = driver_name_fmt.format(name)
 			version_map = '@0@/@1@/@2@_version.map'.format(
@@ -105,7 +115,8 @@ foreach class:driver_classes
 				c_args: cflags,
 				link_args: '-Wl,--version-script=' + version_map,
 				link_depends: version_map,
-				version: '@0@.1'.format(version),
+				version: lib_version,
+				soversion: so_version,
 				install: true,
 				install_dir: driver_install_path)
 
diff --git a/lib/librte_eal/bsdapp/eal/meson.build b/lib/librte_eal/bsdapp/eal/meson.build
index 00973122a..f6c43fd44 100644
--- a/lib/librte_eal/bsdapp/eal/meson.build
+++ b/lib/librte_eal/bsdapp/eal/meson.build
@@ -46,11 +46,21 @@ sources = ['eal_alarm.c',
 
 eal_extra_link_arg = '-lexecinfo'
 
+if get_option('per_library_versions')
+	lib_version = '@0@.1'.format(version)
+	so_version = '@0@'.format(version)
+else
+	pver = meson.project_version().split('.')
+	lib_version = '@0@.@1@'.format(pver.get(0), pver.get(1))
+	so_version = lib_version
+endif
+
 version_map = join_paths(meson.current_source_dir(), 'rte_eal_version.map')
 eal_lib = library('rte_eal', sources, eal_common_sources, eal_common_arch_sources,
 			dependencies: dependency('threads'),
 			include_directories : eal_inc,
-			version: '@0@.1'.format(version),
+			version: lib_version,
+			soversion: so_version,
 			c_args: '-D_GNU_SOURCE',
 			link_depends: version_map,
 			link_args: [eal_extra_link_arg,
diff --git a/lib/librte_eal/linuxapp/eal/meson.build b/lib/librte_eal/linuxapp/eal/meson.build
index e7daed499..bffbd7e66 100644
--- a/lib/librte_eal/linuxapp/eal/meson.build
+++ b/lib/librte_eal/linuxapp/eal/meson.build
@@ -51,11 +51,21 @@ sources = ['eal_alarm.c',
 
 eal_extra_link_arg = '-ldl'
 
+if get_option('per_library_versions')
+	lib_version = '@0@.1'.format(version)
+	so_version = '@0@'.format(version)
+else
+	pver = meson.project_version().split('.')
+	lib_version = '@0@.@1@'.format(pver.get(0), pver.get(1))
+	so_version = lib_version
+endif
+
 version_map = join_paths(meson.current_source_dir(), 'rte_eal_version.map')
 eal_lib = library('rte_eal', sources, eal_common_sources, eal_common_arch_sources,
 			dependencies: dependency('threads'),
 			include_directories : eal_inc,
-			version: '@0@.1'.format(version),
+			version: lib_version,
+			soversion: so_version,
 			c_args: '-D_GNU_SOURCE',
 			link_depends: version_map,
 			link_args: [eal_extra_link_arg,
diff --git a/lib/meson.build b/lib/meson.build
index d814721de..5244fe4a5 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -76,6 +76,15 @@ foreach l:libraries
 			dep_objs += [get_variable('dep_rte_' + d)]
 		endforeach
 
+		if get_option('per_library_versions')
+			lib_version = '@0@.1'.format(version)
+			so_version = '@0@'.format(version)
+		else
+			pver = meson.project_version().split('.')
+			lib_version = '@0@.@1@'.format(pver.get(0), pver.get(1))
+			so_version = lib_version
+		endif
+
 		version_map = '@0@/@1@/rte_@2@_version.map'.format(
 				meson.current_source_dir(), dir_name, name)
 		libname = 'rte_' + name
@@ -87,7 +96,8 @@ foreach l:libraries
 				include_directories: include_directories(dir_name),
 				link_args: '-Wl,--version-script=' + version_map,
 				link_depends: version_map,
-				version: '@0@.1'.format(version),
+				version: lib_version,
+				soversion: so_version,
 				install: true)
 		dep = declare_dependency(link_with: lib,
 				include_directories: include_directories(dir_name),
diff --git a/meson_options.txt b/meson_options.txt
index 9c45b8159..636226ce8 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -6,3 +6,4 @@ option('allow_invalid_socket_id', type: 'boolean', value: false,
 	description: 'allow out-of-range NUMA socket id\'s for platforms that don\'t report the value correctly')
 option('enable_kmods', type: 'boolean', value: true, description: 'build kernel modules')
 option('kernel_dir', type: 'string', value: '', description: 'path to the kernel for building kernel modules')
+option('per_library_versions', type: 'boolean', value: true, description: 'true: each lib gets its own version number, false: DPDK version used for each lib')
-- 
2.13.5

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v3 17/17] doc: add documentation on how to add new components to DPDK
    2017-09-13 14:12  1%     ` [dpdk-dev] [PATCH v3 04/17] build: add DPDK libraries to build Bruce Richardson
  2017-09-13 14:12  3%     ` [dpdk-dev] [PATCH v3 16/17] build: add option to version libs using DPDK version Bruce Richardson
@ 2017-09-13 14:12  3%     ` Bruce Richardson
  2 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2017-09-13 14:12 UTC (permalink / raw)
  To: dev
  Cc: nhorman, luca.boccassi, harry.van.haaren, keith.wiles, Bruce Richardson

Add to the contributors guide details on how to add libraries and drivers
and integrate them with the DPDK build system(s).

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 doc/guides/contributing/coding_style.rst | 214 +++++++++++++++++++++++++++++++
 1 file changed, 214 insertions(+)

diff --git a/doc/guides/contributing/coding_style.rst b/doc/guides/contributing/coding_style.rst
index d8e4a0f9c..3c59cbca5 100644
--- a/doc/guides/contributing/coding_style.rst
+++ b/doc/guides/contributing/coding_style.rst
@@ -702,3 +702,217 @@ All Python code should work with Python 2.7+ and 3.2+ and be compliant with
 `PEP8 (Style Guide for Python Code) <https://www.python.org/dev/peps/pep-0008/>`_.
 
 The ``pep8`` tool can be used for testing compliance with the guidelines.
+
+Integrating with the Build System
+---------------------------------
+
+DPDK supports being built in two different ways:
+
+* using ``make`` - or more specifically "GNU make", i.e. ``gmake`` on FreeBSD
+* using the tools ``meson`` and ``ninja``
+
+Any new library or driver to be integrated into DPDK should support being
+built with both systems. While building using ``make`` is a legacy approach, and
+most build-system enhancements are being done using ``meson`` and ``ninja``
+there are no plans at this time to deprecate the legacy ``make`` build system.
+
+Therefore all new component additions should include both a ``Makefile`` and a
+``meson.build`` file, and should be added to the component lists in both the
+``Makefile`` and ``meson.build`` files in the relevant top-level directory:
+either ``lib`` directory or a ``driver`` subdirectory.
+
+Makefile Contents
+~~~~~~~~~~~~~~~~~
+
+The ``Makefile`` for the component should be of the following format, where
+``<name>`` corresponds to the name of the library in question, e.g. hash,
+lpm, etc. For drivers, the same format of Makefile is used.
+
+.. code-block:: makefile
+
+	# pull in basic DPDK definitions, including whether library is to be
+	# built or not
+	include $(RTE_SDK)/mk/rte.vars.mk
+
+	# library name
+	LIB = librte_<name>.a
+
+	# any library cflags needed. Generally add "-O3 $(WERROR_FLAGS)"
+	CFLAGS += -O3
+	CFLAGS += $(WERROR_FLAGS)
+
+	# the symbol version information for the library, and .so version
+	EXPORT_MAP := rte_<name>_version.map
+	LIBABIVER := 1
+
+	# all source filenames are stored in SRCS-y
+	SRCS-$(CONFIG_RTE_LIBRTE_<NAME>) += rte_<name>.c
+
+	# install includes
+	SYMLINK-$(CONFIG_RTE_LIBRTE_<NAME>)-include += rte_<name>.h
+
+	# pull in rules to build the library
+	include $(RTE_SDK)/mk/rte.lib.mk
+
+Meson Build File Contents - Libraries
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``meson.build`` file for a new DPDK library should be of the following basic
+format.
+
+.. code-block:: python
+
+	sources = files('file1.c', ...)
+	headers = files('file1.c', ...)
+
+
+The will build based on a number of conventions and assumptions within the DPDK
+itself, for example, that the library name is the same as the directory name in
+which the files are stored.
+
+For a library ``meson.build`` file, there are number of variables which can be
+set, some mandatory, others optional. The mandatory fields are:
+
+sources
+	**Default Value = []**.
+	This variable should list out the files to be compiled up to create the
+	library. Files must be specified using the meson ``files()`` function.
+
+
+The optional fields are:
+
+build
+	**Default Value = true.**
+	Used to optionally compile a library, based on its dependencies or
+	environment. A simple example of use would be:
+
+.. code-block:: python
+
+	if host_machine.system() != 'linux'
+	        build = false
+	endif
+
+
+cflags
+	**Default Value = []**.
+	Used to specify any additional cflags that need to be passed to compile
+	the sources in the library.
+
+deps
+	**Default Value = ['eal']**.
+	Used to list the internal library dependencies of the library. It should
+	be assigned to using ``+=`` rather than overwriting using ``=``.  The
+	dependencies should be specified as strings, each one giving the name of
+	a DPDK library, without the ``librte_`` prefix. Dependencies are handled
+	recursively, so specifying e.g. ``mempool``, will automatically also
+	make the library depend upon the mempool library's dependencies too -
+	``ring`` and ``eal``. For libraries that only depend upon EAL, this
+	variable may be omitted from the ``meson.build`` file.  For example:
+
+.. code-block:: python
+
+	deps += ['ethdev']
+
+
+ext_deps
+	**Default Value = []**.
+	Used to specify external dependencies of this library. They should be
+	returned as dependency objects, as returned from the meson
+	``dependency()`` or ``find_library()`` functions. Before returning
+	these, they should be checked to ensure the dependencies have been
+	found, and, if not, the ``build`` variable should be set to ``false``.
+	For example:
+
+.. code-block:: python
+
+	my_dep = dependency('libX', required: 'false')
+	if my_dep.found()
+		ext_deps += my_dep
+	else
+		build = false
+	endif
+
+
+headers
+	**Default Value = []**.
+	Used to return the list of header files for the library that should be
+	installed to $PREFIX/include when ``ninja install`` is run. As with
+	source files, these should be specified using the meson ``files()``
+	function.
+
+name
+	**Default Value = library name derived from the directory name**.
+	If a library's .so or .a file differs from that given in the directory
+	name, the name should be specified using this variable. In practice,
+	since the convention is that for a library called ``librte_xyz.so``, the
+	sources are stored in a directory ``lib/librte_xyz``, this value should
+	never be needed for new libraries.
+
+.. note::
+
+	The name value also provides the name used to find the function version
+	map file, as part of the build process, so if the directory name and
+	library names differ, the ``version.map`` file should be named
+	consistently with the library, not the directory
+
+objs
+	**Default Value = []**.
+	This variable can be used to pass to the library build some pre-built
+	objects that were compiled up as part of another target given in the
+	included library ``meson.build`` file.
+
+version
+	**Default Value = 1**.
+	Specifies the ABI version of the library, and is used as the major
+	version number of the resulting ``.so`` library.
+
+Meson Build File Contents - Drivers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For drivers, the values are largely the same as for libraries. The variables
+supported are:
+
+build
+	As above.
+
+cflags
+	As above.
+
+deps
+	As above.
+
+ext_deps
+	As above.
+
+includes
+	**Default Value = <driver directory>** Some drivers include a base
+	directory for additional source files and headers, so we have this
+	variable to allow the headers from that base directory to be found when
+	compiling driver sources. Should be appended to using ``+=`` rather than
+	overwritten using ``=``.  The values appended should be meson include
+	objects got using the ``include_directories()`` function. For example:
+
+.. code-block:: python
+
+	includes += include_directories('base')
+
+name
+	As above, though note that each driver class can define it's own naming
+	scheme for the resulting ``.so`` files.
+
+objs
+	As above, generally used for the contents of the ``base`` directory.
+
+pkgconfig_extra_libs
+	**Default Value = []**
+	This variable is used to pass additional library link flags through to
+	the DPDK pkgconfig file generated, for example, to track any additional
+	libraries that may need to be linked into the build - especially when
+	using static libraries. Anything added here will be appended to the end
+	of the ``pkgconfig --libs`` output.
+
+sources [mandatory]
+	As above
+
+version
+	As above
-- 
2.13.5

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v2 16/17] build: add option to version libs using DPDK version
  2017-09-13 13:11  0%       ` Bruce Richardson
@ 2017-09-13 17:02  0%         ` Luca Boccassi
  0 siblings, 0 replies; 200+ results
From: Luca Boccassi @ 2017-09-13 17:02 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev, nhorman, harry.van.haaren, Christian Ehrhardt

On Wed, 2017-09-13 at 14:11 +0100, Bruce Richardson wrote:
> On Wed, Sep 13, 2017 at 12:32:24PM +0100, Luca Boccassi wrote:
> > On Tue, 2017-09-12 at 11:38 +0100, Bruce Richardson wrote:
> > > Normally, each library has it's own version number based on the
> > > ABI.
> > > Add an option to have all libs just use the DPDK version number
> > > as
> > > the
> > > .so version.
> > > 
> > > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > > Reviewed-by: Harry van Haaren <harry.van.haaren@intel.com>
> > > ---
> > >  drivers/meson.build | 8 +++++++-
> > >  lib/meson.build     | 8 +++++++-
> > >  meson_options.txt   | 1 +
> > >  3 files changed, 15 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/meson.build b/drivers/meson.build
> > > index f19da16fb..0c251bd61 100644
> > > --- a/drivers/meson.build
> > > +++ b/drivers/meson.build
> > > @@ -92,6 +92,12 @@ foreach class:driver_classes
> > >  						depends:
> > > [pmdinfogen, tmp_lib])
> > >  			endforeach
> > >  
> > > +			if get_option('per_library_versions')
> > > +				so_version = '@0@.1'.format(vers
> > > ion)
> > > +			else
> > > +				so_version =
> > > meson.project_version()
> > > +			endif
> > > +
> > >  			# now build the driver itself, and add
> > > to
> > > the drivers list
> > >  			lib_name = driver_name_fmt.format(name)
> > >  			version_map = '@0@/@1@/@2@_version.map'.
> > > form
> > > at(
> > > @@ -105,7 +111,7 @@ foreach class:driver_classes
> > >  				c_args: cflags,
> > >  				link_args: '-Wl,--version-
> > > script=' +
> > > version_map,
> > >  				link_depends: version_map,
> > > -				version: '@0@.1'.format(version)
> > > ,
> > > +				version: so_version,
> > >  				install: true,
> > >  				install_dir:
> > > driver_install_path)
> > >  
> > > diff --git a/lib/meson.build b/lib/meson.build
> > > index d814721de..36652cfe1 100644
> > > --- a/lib/meson.build
> > > +++ b/lib/meson.build
> > > @@ -76,6 +76,12 @@ foreach l:libraries
> > >  			dep_objs += [get_variable('dep_rte_' +
> > > d)]
> > >  		endforeach
> > >  
> > > +		if get_option('per_library_versions')
> > > +			so_version = '@0@.1'.format(version)
> > > +		else
> > > +			so_version = meson.project_version()
> > > +		endif
> > > +
> > >  		version_map = '@0@/@1@/rte_@2@_version.map'.form
> > > at(
> > >  				meson.current_source_dir(),
> > > dir_name, name)
> > >  		libname = 'rte_' + name
> > > @@ -87,7 +93,7 @@ foreach l:libraries
> > >  				include_directories:
> > > include_directories(dir_name),
> > >  				link_args: '-Wl,--version-
> > > script=' +
> > > version_map,
> > >  				link_depends: version_map,
> > > -				version: '@0@.1'.format(version)
> > > ,
> > > +				version: so_version,
> > >  				install: true)
> > >  		dep = declare_dependency(link_with: lib,
> > >  				include_directories:
> > > include_directories(dir_name),
> > > diff --git a/meson_options.txt b/meson_options.txt
> > > index 9c45b8159..636226ce8 100644
> > > --- a/meson_options.txt
> > > +++ b/meson_options.txt
> > > @@ -6,3 +6,4 @@ option('allow_invalid_socket_id', type:
> > > 'boolean',
> > > value: false,
> > >  	description: 'allow out-of-range NUMA socket id\'s for
> > > platforms that don\'t report the value correctly')
> > >  option('enable_kmods', type: 'boolean', value: true,
> > > description:
> > > 'build kernel modules')
> > >  option('kernel_dir', type: 'string', value: '', description:
> > > 'path
> > > to the kernel for building kernel modules')
> > > +option('per_library_versions', type: 'boolean', value: true,
> > > description: 'true: each lib gets its own version number, false:
> > > DPDK
> > > version used for each lib')
> > 
> > Hi Bruce,
> > 
> > First of all thanks for implementing this option, and sorry for the
> > delay.
> > 
> > A couple of minor things:
> > 
> > 1) The project version has 3 digits, but the ABI version should
> > have 2
> > - eg: should be 17.08 but right now it's 17.08.0 - given point
> > releases
> > will be ABI compatible so they must not change the ABI version. In
> > the
> > packaging code we use cut to chop it off:
> > 
> > DPDK_ABI := $(shell echo $(DEB_VERSION_UPSTREAM) | cut -d '.'  -f1-
> > 2)
> > 
> > Not sure how to achieve the same in a Meson script though (can it
> > shell
> > out? or are there string manipulation built-ins?), sorry - just
> > starting to look at it.
> > 
> 
> That should be easy enough to do. It's 3-digits because I'm just
> pulling
> the project version unmodified from the initial project definition.
> I'd
> say I can manage to strip off one digit as part of the build.
> 
> > Right now the rte_config option allows the user to completely
> > override
> > the version - I'm fine with having a single boolean provided this
> > change is applied, it simplifies packaging a bit, but if it's
> > easier
> > for you to just accepted a version instead of a boolean it's fine
> > as
> > well, as you prefer
> 
> If there is a case where we might want to provide a particular
> version,
> I'm happy to edit the option, but if not I'll keep it as-is, because
> it
> will ensure all users of the option get the exact same behaviour, and
> means I only have two possibilities to test.

I agree, it looks fine as it is right now - I'm not aware of any other
use case at the moment.

> > 
> > 2) When the option is true, it should not generate a symlink with
> > the
> > ABI "revision", as the first digit is really not the revision, so
> > it
> > does not make much sense. Worse, it will stop 2 versions being co-
> > installable (which was the whole point :-) ), as, eg, 17.02, 17.05
> > and
> > 17.08 will all ship a libfoo.so.17 symlink. I can fix it in the
> > packaging, but I don't think it should be generated upstream at all
> > when this option is enabled.
> 
> Not exactly sure how to fix this, but I think it may work by using
> soversion as well as version in the library() calls.
> 
> > 
> > IOW, the following is the current result:
> > 
> > $ ls -l debian/librte-ethdev17.08/usr/lib/x86_64-linux-gnu/
> > total 72
> > lrwxrwxrwx 1 lboccass lboccass    24 Sep 13 11:50
> > librte_ethdev.so.17 -> librte_ethdev.so.17.08.0
> > -rw-r--r-- 1 lboccass lboccass 71672 Sep 13 11:50
> > librte_ethdev.so.17.08.0
> > 
> > The expected result would be to create a single file
> > "librte_ethdev.so.17.08" instead.
> > 
> 
> Let me see what I can do :-)
> 
> /Bruce

Now it works as expected, thanks!

-- 
Kind regards,
Luca Boccassi

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v3 3/3] doc: update timer lib docs
  @ 2017-09-13 22:05  3%   ` Erik Gabriel Carrillo
  0 siblings, 0 replies; 200+ results
From: Erik Gabriel Carrillo @ 2017-09-13 22:05 UTC (permalink / raw)
  To: rsanford; +Cc: dev, konstantin.ananyev, stephen, keith.wiles, narender.vangati

This change updates the timer library documentation to
reflect a change to the organization of the skiplists
in the implementation.

Signed-off-by: Erik Gabriel Carrillo <erik.g.carrillo@intel.com>
---
v3
* Updated implementation details section of timer_lib.rst to reflect the 
  addition of the option to use multiple pending timer lists per lcore.
* Updated release notes to reflect the addition of new function in timer
  lib API.

 doc/guides/prog_guide/timer_lib.rst    | 27 +++++++++++++++++----------
 doc/guides/rel_notes/release_17_11.rst |  7 +++++++
 2 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/doc/guides/prog_guide/timer_lib.rst b/doc/guides/prog_guide/timer_lib.rst
index f437417..dfabf24 100644
--- a/doc/guides/prog_guide/timer_lib.rst
+++ b/doc/guides/prog_guide/timer_lib.rst
@@ -1,5 +1,5 @@
 ..  BSD LICENSE
-    Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+    Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
     All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
@@ -53,16 +53,19 @@ Refer to the `callout manual <http://www.daemon-systems.org/man/callout.9.html>`
 Implementation Details
 ----------------------
 
-Timers are tracked on a per-lcore basis,
-with all pending timers for a core being maintained in order of timer expiry in a skiplist data structure.
-The skiplist used has ten levels and each entry in the table appears in each level with probability ¼^level.
+Timers are tracked on a per-lcore basis, with all pending timers for a core being maintained in order of timer
+expiry in either a single skiplist data structure or an array of skiplists, depending on whether
+the lcore has been configured for multiple pending lists. Multiple pending lists can be enabled when an
+application experiences contention for a single list for that lcore; skiplists corresponding to every other
+enabled lcore will be created.
+Each skiplist data structure has ten levels and each entry in the table appears in each level with probability ¼^level.
 This means that all entries are present in level 0, 1 in every 4 entries is present at level 1,
 one in every 16 at level 2 and so on up to level 9.
 This means that adding and removing entries from the timer list for a core can be done in log(n) time,
 up to 4^10 entries, that is, approximately 1,000,000 timers per lcore.
 
 A timer structure contains a special field called status,
-which is a union of a timer state (stopped, pending, running, config) and an owner (lcore id).
+which is a union of a timer state (stopped, pending, running, config), an installer (lcore id), and an owner (lcore id).
 Depending on the timer state, we know if a timer is present in a list or not:
 
 *   STOPPED: no owner, not in a list
@@ -77,17 +80,21 @@ Resetting or stopping a timer while it is in a CONFIG or RUNNING state is not al
 When modifying the state of a timer,
 a Compare And Swap instruction should be used to guarantee that the status (state+owner) is modified atomically.
 
-Inside the rte_timer_manage() function,
-the skiplist is used as a regular list by iterating along the level 0 list, which contains all timer entries,
-until an entry which has not yet expired has been encountered.
-To improve performance in the case where there are entries in the timer list but none of those timers have yet expired,
+Inside the rte_timer_manage() function, the timer lists are processed.
+If multiple pending lists have been enabled for an lcore, then each skiplist will
+be traversed sequentially, and run lists will be broken out and then processed.
+If multiple pending lists are not enabled for an lcore, then only a single skiplist will be traversed.
+A skiplist is used as a regular list by iterating along the level
+0 list, which contains all timer entries, until an entry which has not yet expired has been encountered.
+To improve performance in the case where there are entries in a skiplist but none of those timers have yet expired,
 the expiry time of the first list entry is maintained within the per-core timer list structure itself.
 On 64-bit platforms, this value can be checked without the need to take a lock on the overall structure.
 (Since expiry times are maintained as 64-bit values,
 a check on the value cannot be done on 32-bit platforms without using either a compare-and-swap (CAS) instruction or using a lock,
 so this additional check is skipped in favor of checking as normal once the lock has been taken.)
 On both 64-bit and 32-bit platforms,
-a call to rte_timer_manage() returns without taking a lock in the case where the timer list for the calling core is empty.
+rte_timer_manage() can either return or continue on to an lcore's next skiplist without taking a lock in the case where a timer list is empty,
+depending on whether or not the lcore has multiple pending lists.
 
 Use Cases
 ---------
diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f9..4683cbe 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -110,6 +110,13 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* **Updated timer library.**
+
+  The timer library has been updated; it can now support multiple timer lists
+  per lcore where it previously only had one.  This functionality is off by
+  default but can be enabled in cases where contention for a single list is
+  an issue with the new function ``rte_timer_subsystem_set_multi_pendlists()``.
+
 
 ABI Changes
 -----------
-- 
2.6.4

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v2 5/6] eal: remove API rte_mem_phy2mch
  @ 2017-09-14  2:40  3% ` Jianfeng Tan
  2017-09-14  2:40  1% ` [dpdk-dev] [PATCH v2 6/6] eal: remove xen dom0 support Jianfeng Tan
  1 sibling, 0 replies; 200+ results
From: Jianfeng Tan @ 2017-09-14  2:40 UTC (permalink / raw)
  To: dev
  Cc: xen-devel, thomas, john.mcnamara, jerin.jacob, shahafs, wei.liu2,
	joao.m.martins, bruce.richardson, Jianfeng Tan

Previously, to get MFN address in dom0, this API is a wrapper to
obtain the "physical address".

As we will removed xen dom0 support, this API is not necessary.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 doc/guides/rel_notes/release_17_11.rst     |  2 ++
 drivers/net/e1000/em_rxtx.c                |  4 ++--
 drivers/net/e1000/igb_rxtx.c               |  4 ++--
 drivers/net/fm10k/fm10k_ethdev.c           |  4 ++--
 drivers/net/i40e/i40e_ethdev.c             |  2 +-
 drivers/net/i40e/i40e_fdir.c               |  2 +-
 drivers/net/i40e/i40e_rxtx.c               |  8 ++++----
 drivers/net/ixgbe/ixgbe_rxtx.c             |  4 ++--
 drivers/net/sfc/sfc.c                      |  2 +-
 lib/librte_eal/common/include/rte_memory.h | 30 ------------------------------
 lib/librte_mempool/rte_mempool.c           |  3 ---
 11 files changed, 17 insertions(+), 48 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 170f4f9..8534947 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -110,6 +110,8 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+   * ``rte_mem_phy2mch`` was used in xen dom0 to obtain the physical address;
+     remove this API as xen dom0 support was removed.
 
 ABI Changes
 -----------
diff --git a/drivers/net/e1000/em_rxtx.c b/drivers/net/e1000/em_rxtx.c
index 31819c5..a0f63a7 100644
--- a/drivers/net/e1000/em_rxtx.c
+++ b/drivers/net/e1000/em_rxtx.c
@@ -1289,7 +1289,7 @@ eth_em_tx_queue_setup(struct rte_eth_dev *dev,
 	txq->port_id = dev->data->port_id;
 
 	txq->tdt_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_TDT(queue_idx));
-	txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr);
+	txq->tx_ring_phys_addr = tz->phys_addr;
 	txq->tx_ring = (struct e1000_data_desc *) tz->addr;
 
 	PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%"PRIx64,
@@ -1416,7 +1416,7 @@ eth_em_rx_queue_setup(struct rte_eth_dev *dev,
 
 	rxq->rdt_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_RDT(queue_idx));
 	rxq->rdh_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_RDH(queue_idx));
-	rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr);
+	rxq->rx_ring_phys_addr = rz->phys_addr;
 	rxq->rx_ring = (struct e1000_rx_desc *) rz->addr;
 
 	PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%"PRIx64,
diff --git a/drivers/net/e1000/igb_rxtx.c b/drivers/net/e1000/igb_rxtx.c
index 1c80a2a..0fccb5d 100644
--- a/drivers/net/e1000/igb_rxtx.c
+++ b/drivers/net/e1000/igb_rxtx.c
@@ -1530,7 +1530,7 @@ eth_igb_tx_queue_setup(struct rte_eth_dev *dev,
 	txq->port_id = dev->data->port_id;
 
 	txq->tdt_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_TDT(txq->reg_idx));
-	txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr);
+	txq->tx_ring_phys_addr = tz->phys_addr;
 
 	txq->tx_ring = (union e1000_adv_tx_desc *) tz->addr;
 	/* Allocate software ring */
@@ -1667,7 +1667,7 @@ eth_igb_rx_queue_setup(struct rte_eth_dev *dev,
 	}
 	rxq->rdt_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_RDT(rxq->reg_idx));
 	rxq->rdh_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_RDH(rxq->reg_idx));
-	rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr);
+	rxq->rx_ring_phys_addr = rz->phys_addr;
 	rxq->rx_ring = (union e1000_adv_rx_desc *) rz->addr;
 
 	/* Allocate software ring. */
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index e60d3a3..15ea2a5 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1887,7 +1887,7 @@ fm10k_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id,
 		return -ENOMEM;
 	}
 	q->hw_ring = mz->addr;
-	q->hw_ring_phys_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
+	q->hw_ring_phys_addr = mz->phys_addr;
 
 	/* Check if number of descs satisfied Vector requirement */
 	if (!rte_is_power_of_2(nb_desc)) {
@@ -2047,7 +2047,7 @@ fm10k_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id,
 		return -ENOMEM;
 	}
 	q->hw_ring = mz->addr;
-	q->hw_ring_phys_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
+	q->hw_ring_phys_addr = mz->phys_addr;
 
 	/*
 	 * allocate memory for the RS bit tracker. Enough slots to hold the
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index f12aefa..f30b4f5 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -3769,7 +3769,7 @@ i40e_allocate_dma_mem_d(__attribute__((unused)) struct i40e_hw *hw,
 
 	mem->size = size;
 	mem->va = mz->addr;
-	mem->pa = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
+	mem->pa = mz->phys_addr;
 	mem->zone = (const void *)mz;
 	PMD_DRV_LOG(DEBUG,
 		"memzone %s allocated with physical address: %"PRIu64,
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index 8013add..70dae92 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -249,7 +249,7 @@ i40e_fdir_setup(struct i40e_pf *pf)
 		goto fail_mem;
 	}
 	pf->fdir.prg_pkt = mz->addr;
-	pf->fdir.dma_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
+	pf->fdir.dma_addr = mz->phys_addr;
 
 	pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id);
 	PMD_DRV_LOG(INFO, "FDIR setup successfully, with programming queue %u.",
diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c
index f571e79..344c11c 100644
--- a/drivers/net/i40e/i40e_rxtx.c
+++ b/drivers/net/i40e/i40e_rxtx.c
@@ -1822,7 +1822,7 @@ i40e_dev_rx_queue_setup(struct rte_eth_dev *dev,
 	/* Zero all the descriptors in the ring. */
 	memset(rz->addr, 0, ring_size);
 
-	rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr);
+	rxq->rx_ring_phys_addr = rz->phys_addr;
 	rxq->rx_ring = (union i40e_rx_desc *)rz->addr;
 
 	len = (uint16_t)(nb_desc + RTE_PMD_I40E_RX_MAX_BURST);
@@ -2159,7 +2159,7 @@ i40e_dev_tx_queue_setup(struct rte_eth_dev *dev,
 	txq->vsi = vsi;
 	txq->tx_deferred_start = tx_conf->tx_deferred_start;
 
-	txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr);
+	txq->tx_ring_phys_addr = tz->phys_addr;
 	txq->tx_ring = (struct i40e_tx_desc *)tz->addr;
 
 	/* Allocate software ring */
@@ -2671,7 +2671,7 @@ i40e_fdir_setup_tx_resources(struct i40e_pf *pf)
 	txq->reg_idx = pf->fdir.fdir_vsi->base_queue;
 	txq->vsi = pf->fdir.fdir_vsi;
 
-	txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr);
+	txq->tx_ring_phys_addr = tz->phys_addr;
 	txq->tx_ring = (struct i40e_tx_desc *)tz->addr;
 	/*
 	 * don't need to allocate software ring and reset for the fdir
@@ -2727,7 +2727,7 @@ i40e_fdir_setup_rx_resources(struct i40e_pf *pf)
 	rxq->reg_idx = pf->fdir.fdir_vsi->base_queue;
 	rxq->vsi = pf->fdir.fdir_vsi;
 
-	rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr);
+	rxq->rx_ring_phys_addr = rz->phys_addr;
 	rxq->rx_ring = (union i40e_rx_desc *)rz->addr;
 
 	/*
diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c
index 64bff25..ac1415b 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx.c
@@ -2548,7 +2548,7 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev,
 	else
 		txq->tdt_reg_addr = IXGBE_PCI_REG_ADDR(hw, IXGBE_TDT(txq->reg_idx));
 
-	txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr);
+	txq->tx_ring_phys_addr = tz->phys_addr;
 	txq->tx_ring = (union ixgbe_adv_tx_desc *) tz->addr;
 
 	/* Allocate software ring */
@@ -2850,7 +2850,7 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev,
 			IXGBE_PCI_REG_ADDR(hw, IXGBE_RDH(rxq->reg_idx));
 	}
 
-	rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr);
+	rxq->rx_ring_phys_addr = rz->phys_addr;
 	rxq->rx_ring = (union ixgbe_adv_rx_desc *) rz->addr;
 
 	/*
diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index 6cecfc0..f9e9916 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -61,7 +61,7 @@ sfc_dma_alloc(const struct sfc_adapter *sa, const char *name, uint16_t id,
 		return ENOMEM;
 	}
 
-	esmp->esm_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
+	esmp->esm_addr = mz->phys_addr;
 	if (esmp->esm_addr == RTE_BAD_PHYS_ADDR) {
 		(void)rte_memzone_free(mz);
 		return EFAULT;
diff --git a/lib/librte_eal/common/include/rte_memory.h b/lib/librte_eal/common/include/rte_memory.h
index 4aa5d1f..8d3960d 100644
--- a/lib/librte_eal/common/include/rte_memory.h
+++ b/lib/librte_eal/common/include/rte_memory.h
@@ -200,30 +200,6 @@ unsigned rte_memory_get_nrank(void);
 /**< Internal use only - should DOM0 memory mapping be used */
 int rte_xen_dom0_supported(void);
 
-/**< Internal use only - phys to virt mapping for xen */
-phys_addr_t rte_xen_mem_phy2mch(int32_t, const phys_addr_t);
-
-/**
- * Return the physical address of elt, which is an element of the pool mp.
- *
- * @param memseg_id
- *   Identifier of the memory segment owning the physical address. If
- *   set to -1, find it automatically.
- * @param phy_addr
- *   physical address of elt.
- *
- * @return
- *   The physical address or RTE_BAD_PHYS_ADDR on error.
- */
-static inline phys_addr_t
-rte_mem_phy2mch(int32_t memseg_id, const phys_addr_t phy_addr)
-{
-	if (rte_xen_dom0_supported())
-		return rte_xen_mem_phy2mch(memseg_id, phy_addr);
-	else
-		return phy_addr;
-}
-
 /**
  * Memory init for supporting application running on Xen domain0.
  *
@@ -250,12 +226,6 @@ static inline int rte_xen_dom0_supported(void)
 {
 	return 0;
 }
-
-static inline phys_addr_t
-rte_mem_phy2mch(int32_t memseg_id __rte_unused, const phys_addr_t phy_addr)
-{
-	return phy_addr;
-}
 #endif
 
 #ifdef __cplusplus
diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c
index 6d726ae..892a1ac 100644
--- a/lib/librte_mempool/rte_mempool.c
+++ b/lib/librte_mempool/rte_mempool.c
@@ -473,8 +473,6 @@ rte_mempool_populate_virt(struct rte_mempool *mp, char *addr,
 		     mp->populated_size < mp->size; off += phys_len) {
 
 		paddr = rte_mem_virt2phy(addr + off);
-		/* required for xen_dom0 to get the machine address */
-		paddr = rte_mem_phy2mch(-1, paddr);
 
 		if (paddr == RTE_BAD_PHYS_ADDR && rte_eal_has_hugepages()) {
 			ret = -EINVAL;
@@ -486,7 +484,6 @@ rte_mempool_populate_virt(struct rte_mempool *mp, char *addr,
 			phys_addr_t paddr_tmp;
 
 			paddr_tmp = rte_mem_virt2phy(addr + off + phys_len);
-			paddr_tmp = rte_mem_phy2mch(-1, paddr_tmp);
 
 			if (paddr_tmp != paddr + phys_len)
 				break;
-- 
2.7.4

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v2 6/6] eal: remove xen dom0 support
    2017-09-14  2:40  3% ` [dpdk-dev] [PATCH v2 5/6] eal: remove API rte_mem_phy2mch Jianfeng Tan
@ 2017-09-14  2:40  1% ` Jianfeng Tan
  1 sibling, 0 replies; 200+ results
From: Jianfeng Tan @ 2017-09-14  2:40 UTC (permalink / raw)
  To: dev
  Cc: xen-devel, thomas, john.mcnamara, jerin.jacob, shahafs, wei.liu2,
	joao.m.martins, bruce.richardson, Jianfeng Tan

We remove xen-specific code in EAL, including the option --xen-dom0,
memory initialization code, compiling dependency, etc.

Related documents are removed or updated, and bump the eal library
version.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 MAINTAINERS                                        |   7 -
 config/common_base                                 |   5 -
 doc/guides/contributing/documentation.rst          |   1 -
 doc/guides/index.rst                               |   1 -
 doc/guides/linux_gsg/build_sample_apps.rst         |   5 +-
 doc/guides/linux_gsg/sys_reqs.rst                  |  53 --
 doc/guides/prog_guide/env_abstraction_layer.rst    |  11 -
 doc/guides/prog_guide/source_org.rst               |   1 -
 doc/guides/rel_notes/deprecation.rst               |   3 -
 doc/guides/rel_notes/release_17_11.rst             |  12 +
 doc/guides/testpmd_app_ug/run_app.rst              |   4 -
 doc/guides/xen/img/dpdk_xen_pkt_switch.png         | Bin 163842 -> 0 bytes
 doc/guides/xen/img/grant_refs.png                  | Bin 6405 -> 0 bytes
 doc/guides/xen/img/grant_table.png                 | Bin 96762 -> 0 bytes
 doc/guides/xen/index.rst                           |  38 -
 doc/guides/xen/pkt_switch.rst                      | 470 -------------
 lib/librte_eal/bsdapp/eal/Makefile                 |   2 +-
 .../bsdapp/eal/include/exec-env/rte_dom0_common.h  | 107 ---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map      |   3 -
 lib/librte_eal/common/eal_common_options.c         |   3 -
 lib/librte_eal/common/eal_internal_cfg.h           |   1 -
 lib/librte_eal/common/eal_options.h                |   2 -
 lib/librte_eal/common/include/rte_memory.h         |  41 --
 lib/librte_eal/linuxapp/Makefile                   |   2 -
 lib/librte_eal/linuxapp/eal/Makefile               |   7 +-
 lib/librte_eal/linuxapp/eal/eal.c                  |  24 -
 lib/librte_eal/linuxapp/eal/eal_memory.c           |  56 --
 lib/librte_eal/linuxapp/eal/eal_xen_memory.c       | 381 ----------
 .../eal/include/exec-env/rte_dom0_common.h         | 108 ---
 lib/librte_eal/linuxapp/eal/rte_eal_version.map    |   4 -
 lib/librte_eal/linuxapp/igb_uio/igb_uio.c          |  54 --
 lib/librte_eal/linuxapp/xen_dom0/Makefile          |  53 --
 lib/librte_eal/linuxapp/xen_dom0/compat.h          |  15 -
 lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h     | 107 ---
 lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c    | 780 ---------------------
 pkg/dpdk.spec                                      |   3 -
 36 files changed, 16 insertions(+), 2348 deletions(-)
 delete mode 100644 doc/guides/xen/img/dpdk_xen_pkt_switch.png
 delete mode 100644 doc/guides/xen/img/grant_refs.png
 delete mode 100644 doc/guides/xen/img/grant_table.png
 delete mode 100644 doc/guides/xen/index.rst
 delete mode 100644 doc/guides/xen/pkt_switch.rst
 delete mode 100644 lib/librte_eal/bsdapp/eal/include/exec-env/rte_dom0_common.h
 delete mode 100644 lib/librte_eal/linuxapp/eal/eal_xen_memory.c
 delete mode 100644 lib/librte_eal/linuxapp/eal/include/exec-env/rte_dom0_common.h
 delete mode 100644 lib/librte_eal/linuxapp/xen_dom0/Makefile
 delete mode 100644 lib/librte_eal/linuxapp/xen_dom0/compat.h
 delete mode 100644 lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h
 delete mode 100644 lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 003e72e..2af32ff 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -189,13 +189,6 @@ Linux VFIO
 M: Anatoly Burakov <anatoly.burakov@intel.com>
 F: lib/librte_eal/linuxapp/eal/*vfio*
 
-Linux Xen
-M: Jianfeng Tan <jianfeng.tan@intel.com>
-F: lib/librte_eal/linuxapp/xen_dom0/
-F: lib/librte_eal/linuxapp/eal/*xen*
-F: lib/librte_eal/linuxapp/eal/include/exec-env/rte_dom0_common.h
-F: doc/guides/xen/
-
 FreeBSD EAL (with overlaps)
 M: Bruce Richardson <bruce.richardson@intel.com>
 M: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
diff --git a/config/common_base b/config/common_base
index 93928b6..17d3dae 100644
--- a/config/common_base
+++ b/config/common_base
@@ -719,11 +719,6 @@ CONFIG_RTE_LIBRTE_VHOST_DEBUG=n
 CONFIG_RTE_LIBRTE_PMD_VHOST=n
 
 #
-#Compile Xen domain0 support
-#
-CONFIG_RTE_LIBRTE_XEN_DOM0=n
-
-#
 # Compile the test application
 #
 CONFIG_RTE_APP_TEST=y
diff --git a/doc/guides/contributing/documentation.rst b/doc/guides/contributing/documentation.rst
index cddbd7b..170dacd 100644
--- a/doc/guides/contributing/documentation.rst
+++ b/doc/guides/contributing/documentation.rst
@@ -34,7 +34,6 @@ The main directories that contain files related to documentation are shown below
        |-- testpmd_app_ug
        |-- rel_notes
        |-- nics
-       |-- xen
        |-- ...
 
 
diff --git a/doc/guides/index.rst b/doc/guides/index.rst
index 63716b0..5b6eb7e 100644
--- a/doc/guides/index.rst
+++ b/doc/guides/index.rst
@@ -44,7 +44,6 @@ DPDK documentation
    nics/index
    cryptodevs/index
    eventdevs/index
-   xen/index
    contributing/index
    rel_notes/index
    faq/index
diff --git a/doc/guides/linux_gsg/build_sample_apps.rst b/doc/guides/linux_gsg/build_sample_apps.rst
index 0cc5fd1..582984d 100644
--- a/doc/guides/linux_gsg/build_sample_apps.rst
+++ b/doc/guides/linux_gsg/build_sample_apps.rst
@@ -116,7 +116,7 @@ The following is the list of options that can be given to the EAL:
 
     ./rte-app [-c COREMASK | -l CORELIST] [-n NUM] [-b <domain:bus:devid.func>] \
               [--socket-mem=MB,...] [-d LIB.so|DIR] [-m MB] [-r NUM] [-v] [--file-prefix] \
-	      [--proc-type <primary|secondary|auto>] [-- xen-dom0]
+	      [--proc-type <primary|secondary|auto>]
 
 The EAL options are as follows:
 
@@ -163,9 +163,6 @@ The EAL options are as follows:
 * ``--proc-type``:
   The type of process instance.
 
-* ``--xen-dom0``:
-  Support application running on Xen Domain0 without hugetlbfs.
-
 * ``--vmware-tsc-map``:
   Use VMware TSC map instead of native RDTSC.
 
diff --git a/doc/guides/linux_gsg/sys_reqs.rst b/doc/guides/linux_gsg/sys_reqs.rst
index eb8442c..3e7fe63 100644
--- a/doc/guides/linux_gsg/sys_reqs.rst
+++ b/doc/guides/linux_gsg/sys_reqs.rst
@@ -228,56 +228,3 @@ The mount point can be made permanent across reboots, by adding the following li
 For 1GB pages, the page size must be specified as a mount option::
 
     nodev /mnt/huge_1GB hugetlbfs pagesize=1GB 0 0
-
-Xen Domain0 Support in the Linux Environment
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The existing memory management implementation is based on the Linux kernel hugepage mechanism.
-On the Xen hypervisor, hugepage support for DomainU (DomU) Guests means that DPDK applications work as normal for guests.
-
-However, Domain0 (Dom0) does not support hugepages.
-To work around this limitation, a new kernel module rte_dom0_mm is added to facilitate the allocation and mapping of memory via
-**IOCTL** (allocation) and **MMAP** (mapping).
-
-Enabling Xen Dom0 Mode in the DPDK
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-By default, Xen Dom0 mode is disabled in the DPDK build configuration files.
-To support Xen Dom0, the CONFIG_RTE_LIBRTE_XEN_DOM0 setting should be changed to “y”, which enables the Xen Dom0 mode at compile time.
-
-Furthermore, the CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID setting should also be changed to “y” in the case of the wrong socket ID being received.
-
-Loading the DPDK rte_dom0_mm Module
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-To run any DPDK application on Xen Dom0, the ``rte_dom0_mm`` module must be loaded into the running kernel with rsv_memsize option.
-The module is found in the kmod sub-directory of the DPDK target directory.
-This module should be loaded using the insmod command as shown below (assuming that the current directory is the DPDK target directory)::
-
-    sudo insmod kmod/rte_dom0_mm.ko rsv_memsize=X
-
-The value X cannot be greater than 4096(MB).
-
-Configuring Memory for DPDK Use
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-After the rte_dom0_mm.ko kernel module has been loaded, the user must configure the memory size for DPDK usage.
-This is done by echoing the memory size to a memsize file in the /sys/devices/ directory.
-Use the following command (assuming that 2048 MB is required)::
-
-    echo 2048 > /sys/kernel/mm/dom0-mm/memsize-mB/memsize
-
-The user can also check how much memory has already been used::
-
-    cat /sys/kernel/mm/dom0-mm/memsize-mB/memsize_rsvd
-
-Xen Domain0 does not support NUMA configuration, as a result the ``--socket-mem`` command line option is invalid for Xen Domain0.
-
-.. note::
-
-    The memsize value cannot be greater than the rsv_memsize value.
-
-Running the DPDK Application on Xen Domain0
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-To run the DPDK application on Xen Domain0, an extra command line option ``--xen-dom0`` is required.
diff --git a/doc/guides/prog_guide/env_abstraction_layer.rst b/doc/guides/prog_guide/env_abstraction_layer.rst
index fff1c06..4775eb3 100644
--- a/doc/guides/prog_guide/env_abstraction_layer.rst
+++ b/doc/guides/prog_guide/env_abstraction_layer.rst
@@ -117,17 +117,6 @@ The physical address of the reserved memory for that memory zone is also returne
 
     Memory reservations done using the APIs provided by rte_malloc are also backed by pages from the hugetlbfs filesystem.
 
-Xen Dom0 support without hugetbls
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The existing memory management implementation is based on the Linux kernel hugepage mechanism.
-However, Xen Dom0 does not support hugepages, so a new Linux kernel module rte_dom0_mm is added to workaround this limitation.
-
-The EAL uses IOCTL interface to notify the Linux kernel module rte_dom0_mm to allocate memory of specified size,
-and get all memory segments information from the module,
-and the EAL uses MMAP interface to map the allocated memory.
-For each memory segment, the physical addresses are contiguous within it but actual hardware addresses are contiguous within 2MB.
-
 PCI Access
 ~~~~~~~~~~
 
diff --git a/doc/guides/prog_guide/source_org.rst b/doc/guides/prog_guide/source_org.rst
index d5d01f3..7aab4b4 100644
--- a/doc/guides/prog_guide/source_org.rst
+++ b/doc/guides/prog_guide/source_org.rst
@@ -108,7 +108,6 @@ The drivers directory has a *net* subdirectory which contains::
     +-- szedata2           # SZEDATA2 poll mode driver
     +-- virtio             # Virtio poll mode driver
     +-- vmxnet3            # VMXNET3 poll mode driver
-    +-- xenvirt            # Xen virtio poll mode driver
 
 .. note::
 
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 3362f33..7a2d2f2 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -29,9 +29,6 @@ Deprecation Notices
   - ``rte_eal_devargs_type_count``
   - ``rte_eal_parse_devargs_str``, replaced by ``rte_eal_devargs_parse``
 
-* eal: the support of Xen dom0 will be removed from EAL in 17.11; and with
-  that, drivers/net/xenvirt and examples/vhost_xen will also be removed.
-
 * eal: An ABI change is planned for 17.11 to make DPDK aware of IOVA address
   translation scheme.
   Reference to phys address in EAL data-structure or functions may change to
diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 8534947..06c334b 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -126,7 +126,19 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+Removed Items
+-------------
 
+.. This section should contain removed items in this release. Sample format:
+
+   * Add a short 1-2 sentence description of the removed item in the past
+     tense.
+
+   This section is a comment. do not overwrite or remove it.
+   Also, make sure to start the actual text at the margin.
+   =========================================================
+
+   * Xen dom0 in EAL was removed, as well as xenvirt PMD and vhost_xen.
 
 Shared Library Versions
 -----------------------
diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
index e8303f3..bd5ebe6 100644
--- a/doc/guides/testpmd_app_ug/run_app.rst
+++ b/doc/guides/testpmd_app_ug/run_app.rst
@@ -94,10 +94,6 @@ See the DPDK Getting Started Guides for more information on these options.
 
     Display the version information on startup.
 
-*   ``--xen-dom0``
-
-    Support application running on Xen Domain0 without hugetlbfs.
-
 *   ``--syslog``
 
     Set the syslog facility.
diff --git a/doc/guides/xen/img/dpdk_xen_pkt_switch.png b/doc/guides/xen/img/dpdk_xen_pkt_switch.png
deleted file mode 100644
index 32a6d1618820e930b17231f8fe38aab5d5c5d370..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 163842
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

diff --git a/doc/guides/xen/img/grant_refs.png b/doc/guides/xen/img/grant_refs.png
deleted file mode 100644
index baa34e1e3f5e8975ae0516a09f906933b1ac688d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 6405
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
R9${aAy7JpMP(_Qd{{c{~dJX^p

diff --git a/doc/guides/xen/img/grant_table.png b/doc/guides/xen/img/grant_table.png
deleted file mode 100644
index c23e5fa73e660c5be9c7cd01f55ff34e2917632b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 96762
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
Z{{xM~vTICa&vpO+002ovPDHLkV1nHvhjah{

diff --git a/doc/guides/xen/index.rst b/doc/guides/xen/index.rst
deleted file mode 100644
index cb43cd2..0000000
--- a/doc/guides/xen/index.rst
+++ /dev/null
@@ -1,38 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2010-2014 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.
-
-Xen Guide
-=========
-
-.. toctree::
-    :maxdepth: 2
-    :numbered:
-
-    pkt_switch
diff --git a/doc/guides/xen/pkt_switch.rst b/doc/guides/xen/pkt_switch.rst
deleted file mode 100644
index 717a04b..0000000
--- a/doc/guides/xen/pkt_switch.rst
+++ /dev/null
@@ -1,470 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2010-2014 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.
-
-DPDK Xen Based Packet-Switching Solution
-========================================
-
-Introduction
-------------
-
-DPDK provides a para-virtualization packet switching solution, based on the Xen hypervisor's Grant Table, Note 1,
-which provides simple and fast packet switching capability between guest domains and host domain based on MAC address or VLAN tag.
-
-This solution is comprised of two components;
-a Poll Mode Driver (PMD) as the front end in the guest domain and a switching back end in the host domain.
-XenStore is used to exchange configure information between the PMD front end and switching back end,
-including grant reference IDs for shared Virtio RX/TX rings,
-MAC address, device state, and so on. XenStore is an information storage space shared between domains,
-see further information on XenStore below.
-
-The front end PMD can be found in the DPDK directory lib/ librte_pmd_xenvirt and back end example in examples/vhost_xen.
-
-The PMD front end and switching back end use shared Virtio RX/TX rings as para- virtualized interface.
-The Virtio ring is created by the front end, and Grant table references for the ring are passed to host.
-The switching back end maps those grant table references and creates shared rings in a mapped address space.
-
-The following diagram describes the functionality of the DPDK Xen Packet- Switching Solution.
-
-
-.. _figure_dpdk_xen_pkt_switch:
-
-.. figure:: img/dpdk_xen_pkt_switch.*
-
-   Functionality of the DPDK Xen Packet Switching Solution.
-
-
-Note 1 The Xen hypervisor uses a mechanism called a Grant Table to share memory between domains
-(`http://wiki.xen.org/wiki/Grant Table <http://wiki.xen.org/wiki/Grant%20Table>`_).
-
-A diagram of the design is shown below, where "gva" is the Guest Virtual Address,
-which is the data pointer of the mbuf, and "hva" is the Host Virtual Address:
-
-
-.. _figure_grant_table:
-
-.. figure:: img/grant_table.*
-
-   DPDK Xen Layout
-
-
-In this design, a Virtio ring is used as a para-virtualized interface for better performance over a Xen private ring
-when packet switching to and from a VM.
-The additional performance is gained by avoiding a system call and memory map in each memory copy with a XEN private ring.
-
-Device Creation
----------------
-
-Poll Mode Driver Front End
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-*   Mbuf pool allocation:
-
-    To use a Xen switching solution, the DPDK application should use rte_mempool_gntalloc_create()
-    to reserve mbuf pools during initialization.
-    rte_mempool_gntalloc_create() creates a mempool with objects from memory allocated and managed via gntalloc/gntdev.
-
-    The DPDK now supports construction of mempools from allocated virtual memory through the rte_mempool_xmem_create() API.
-
-    This front end constructs mempools based on memory allocated through the xen_gntalloc driver.
-    rte_mempool_gntalloc_create() allocates Grant pages, maps them to continuous virtual address space,
-    and calls rte_mempool_xmem_create() to build mempools.
-    The Grant IDs for all Grant pages are passed to the host through XenStore.
-
-*   Virtio Ring Creation:
-
-    The Virtio queue size is defined as 256 by default in the VQ_DESC_NUM macro.
-    Using the queue setup function,
-    Grant pages are allocated based on ring size and are mapped to continuous virtual address space to form the Virtio ring.
-    Normally, one ring is comprised of several pages.
-    Their Grant IDs are passed to the host through XenStore.
-
-    There is no requirement that this memory be physically continuous.
-
-*   Interrupt and Kick:
-
-    There are no interrupts in DPDK Xen Switching as both front and back ends work in polling mode.
-    There is no requirement for notification.
-
-*   Feature Negotiation:
-
-    Currently, feature negotiation through XenStore is not supported.
-
-*   Packet Reception & Transmission:
-
-    With mempools and Virtio rings created, the front end can operate Virtio devices,
-    as it does in Virtio PMD for KVM Virtio devices with the exception that the host
-    does not require notifications or deal with interrupts.
-
-XenStore is a database that stores guest and host information in the form of (key, value) pairs.
-The following is an example of the information generated during the startup of the front end PMD in a guest VM (domain ID 1):
-
-.. code-block:: console
-
-        xenstore -ls /local/domain/1/control/dpdk
-        0_mempool_gref="3042,3043,3044,3045"
-        0_mempool_va="0x7fcbc6881000"
-        0_tx_vring_gref="3049"
-        0_rx_vring_gref="3053"
-        0_ether_addr="4e:0b:d0:4e:aa:f1"
-        0_vring_flag="3054"
-        ...
-
-Multiple mempools and multiple Virtios may exist in the guest domain, the first number is the index, starting from zero.
-
-The idx#_mempool_va stores the guest virtual address for mempool idx#.
-
-The idx#_ether_adder stores the MAC address of the guest Virtio device.
-
-For idx#_rx_ring_gref, idx#_tx_ring_gref, and idx#_mempool_gref, the value is a list of Grant references.
-Take idx#_mempool_gref node for example, the host maps those Grant references to a continuous virtual address space.
-The real Grant reference information is stored in this virtual address space,
-where (gref, pfn) pairs follow each other with -1 as the terminator.
-
-
-.. _figure_grant_refs:
-
-.. figure:: img/grant_refs.*
-
-   Mapping Grant references to a continuous virtual address space
-
-
-After all gref# IDs are retrieved, the host maps them to a continuous virtual address space.
-With the guest mempool virtual address, the host establishes 1:1 address mapping.
-With multiple guest mempools, the host establishes multiple address translation regions.
-
-Switching Back End
-~~~~~~~~~~~~~~~~~~
-
-The switching back end monitors changes in XenStore.
-When the back end detects that a new Virtio device has been created in a guest domain, it will:
-
-#.  Retrieve Grant and configuration information from XenStore.
-
-#.  Map and create a Virtio ring.
-
-#.  Map mempools in the host and establish address translation between the guest address and host address.
-
-#.  Select a free VMDQ pool, set its affinity with the Virtio device, and set the MAC/ VLAN filter.
-
-Packet Reception
-~~~~~~~~~~~~~~~~
-
-When packets arrive from an external network, the MAC?VLAN filter classifies packets into queues in one VMDQ pool.
-As each pool is bonded to a Virtio device in some guest domain, the switching back end will:
-
-#.  Fetch an available entry from the Virtio RX ring.
-
-#.  Get gva, and translate it to hva.
-
-#.  Copy the contents of the packet to the memory buffer pointed to by gva.
-
-The DPDK application in the guest domain, based on the PMD front end,
-is polling the shared Virtio RX ring for available packets and receives them on arrival.
-
-Packet Transmission
-~~~~~~~~~~~~~~~~~~~
-
-When a Virtio device in one guest domain is to transmit a packet,
-it puts the virtual address of the packet's data area into the shared Virtio TX ring.
-
-The packet switching back end is continuously polling the Virtio TX ring.
-When new packets are available for transmission from a guest, it will:
-
-#.  Fetch an available entry from the Virtio TX ring.
-
-#.  Get gva, and translate it to hva.
-
-#.  Copy the packet from hva to the host mbuf's data area.
-
-#.  Compare the destination MAC address with all the MAC addresses of the Virtio devices it manages.
-    If a match exists, it directly copies the packet to the matched VIrtio RX ring.
-    Otherwise, it sends the packet out through hardware.
-
-.. note::
-
-    The packet switching back end is for demonstration purposes only.
-    The user could implement their switching logic based on this example.
-    In this example, only one physical port on the host is supported.
-    Multiple segments are not supported. The biggest mbuf supported is 4KB.
-    When the back end is restarted, all front ends must also be restarted.
-
-Running the Application
------------------------
-
-The following describes the steps required to run the application.
-
-Validated Environment
-~~~~~~~~~~~~~~~~~~~~~
-
-Host:
-
-    Xen-hypervisor: 4.2.2
-
-    Distribution: Fedora release 18
-
-    Kernel: 3.10.0
-
-    Xen development package (including Xen, Xen-libs, xen-devel): 4.2.3
-
-Guest:
-
-    Distribution: Fedora 16 and 18
-
-    Kernel: 3.6.11
-
-Xen Host Prerequisites
-~~~~~~~~~~~~~~~~~~~~~~
-
-Note that the following commands might not be the same on different Linux* distributions.
-
-*   Install xen-devel package:
-
-    .. code-block:: console
-
-        yum install xen-devel.x86_64
-
-*   Start xend if not already started:
-
-    .. code-block:: console
-
-        /etc/init.d/xend start
-
-*   Mount xenfs if not already mounted:
-
-    .. code-block:: console
-
-        mount -t xenfs none /proc/xen
-
-*   Enlarge the limit for xen_gntdev driver:
-
-    .. code-block:: console
-
-        modprobe -r xen_gntdev
-        modprobe xen_gntdev limit=1000000
-
-.. note::
-
-    The default limit for earlier versions of the xen_gntdev driver is 1024.
-    That is insufficient to support the mapping of multiple Virtio devices into multiple VMs,
-    so it is necessary to enlarge the limit by reloading this module.
-    The default limit of recent versions of xen_gntdev is 1048576.
-    The rough calculation of this limit is:
-
-        limit=nb_mbuf# * VM#.
-
-        In DPDK examples, nb_mbuf# is normally 8192.
-
-Building and Running the Switching Backend
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-#.  Edit config/common_linuxapp, and change the default configuration value for the following two items:
-
-    .. code-block:: console
-
-        CONFIG_RTE_LIBRTE_XEN_DOM0=y
-        CONFIG RTE_LIBRTE_PMD_XENVIRT=n
-
-#.  Build the target:
-
-    .. code-block:: console
-
-        make install T=x86_64-native-linuxapp-gcc
-
-#.  Ensure that RTE_SDK and RTE_TARGET are correctly set. Build the switching example:
-
-    .. code-block:: console
-
-        make -C examples/vhost_xen/
-
-#.  Load the Xen DPDK memory management module and preallocate memory:
-
-    .. code-block:: console
-
-        insmod ./x86_64-native-linuxapp-gcc/build/lib/librte_eal/linuxapp/xen_dom0/rte_dom0_mm.ko
-        echo 2048> /sys/kernel/mm/dom0-mm/memsize-mB/memsize
-
-    .. note::
-
-        On Xen Dom0, there is no hugepage support.
-        Under Xen Dom0, the DPDK uses a special memory management kernel module
-        to allocate chunks of physically continuous memory.
-        Refer to the *DPDK Getting Started Guide* for more information on memory management in the DPDK.
-        In the above command, 4 GB memory is reserved (2048 of 2 MB pages) for DPDK.
-
-#.  Load uio_pci_generic and bind one Intel NIC controller to it:
-
-    .. code-block:: console
-
-        modprobe uio_pci_generic
-        python usertools/dpdk-devbind.py -b uio_pci_generic 0000:09:00:00.0
-
-    In this case, 0000:09:00.0 is the PCI address for the NIC controller.
-
-#.  Run the switching back end example:
-
-    .. code-block:: console
-
-        examples/vhost_xen/build/vhost-switch -l 0-3 -n 3 --xen-dom0 -- -p1
-
-.. note::
-
-    The -xen-dom0 option instructs the DPDK to use the Xen kernel module to allocate memory.
-
-Other Parameters:
-
-*   -vm2vm
-
-    The vm2vm parameter enables/disables packet switching in software.
-    Disabling vm2vm implies that on a VM packet transmission will always go to the Ethernet port
-    and will not be switched to another VM
-
-*   -Stats
-
-    The Stats parameter controls the printing of Virtio-net device statistics.
-    The parameter specifies the interval (in seconds) at which to print statistics,
-    an interval of 0 seconds will disable printing statistics.
-
-Xen PMD Frontend Prerequisites
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-#.  Install xen-devel package for accessing XenStore:
-
-    .. code-block:: console
-
-        yum install xen-devel.x86_64
-
-#.  Mount xenfs, if it is not already mounted:
-
-    .. code-block:: console
-
-        mount -t xenfs none /proc/xen
-
-#.  Enlarge the default limit for xen_gntalloc driver:
-
-    .. code-block:: console
-
-        modprobe -r xen_gntalloc
-        modprobe xen_gntalloc limit=6000
-
-.. note::
-
-    Before the Linux kernel version 3.8-rc5, Jan 15th 2013,
-    a critical defect occurs when a guest is heavily allocating Grant pages.
-    The Grant driver allocates fewer pages than expected which causes kernel memory corruption.
-    This happens, for example, when a guest uses the v1 format of a Grant table entry and allocates
-    more than 8192 Grant pages (this number might be different on different hypervisor versions).
-    To work around this issue, set the limit for gntalloc driver to 6000.
-    (The kernel normally allocates hundreds of Grant pages with one Xen front end per virtualized device).
-    If the kernel allocates a lot of Grant pages, for example, if the user uses multiple net front devices,
-    it is best to upgrade the Grant alloc driver.
-    This defect has been fixed in kernel version 3.8-rc5 and later.
-
-Building and Running the Front End
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-#.  Edit config/common_linuxapp, and change the default configuration value:
-
-    .. code-block:: console
-
-        CONFIG_RTE_LIBRTE_XEN_DOM0=n
-        CONFIG_RTE_LIBRTE_PMD_XENVIRT=y
-
-#.  Build the package:
-
-    .. code-block:: console
-
-        make install T=x86_64-native-linuxapp-gcc
-
-#.  Enable hugepages. Refer to the  *DPDK Getting Started Guide* for instructions on
-    how to use hugepages in the DPDK.
-
-#.  Run TestPMD. Refer to *DPDK TestPMD Application User Guide* for detailed parameter usage.
-
-    .. code-block:: console
-
-        ./x86_64-native-linuxapp-gcc/app/testpmd -l 0-3 -n 4 --vdev="net_xenvirt0,mac=00:00:00:00:00:11"
-        testpmd>set fwd mac
-        testpmd>start
-
-    As an example to run two TestPMD instances over 2 Xen Virtio devices:
-
-    .. code-block:: console
-
-        --vdev="net_xenvirt0,mac=00:00:00:00:00:11" --vdev="net_xenvirt1;mac=00:00:00:00:00:22"
-
-
-Usage Examples: Injecting a Packet Stream Using a Packet Generator
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Loopback Mode
-^^^^^^^^^^^^^
-
-Run TestPMD in a guest VM:
-
-.. code-block:: console
-
-    ./x86_64-native-linuxapp-gcc/app/testpmd -l 0-3 -n 4 --vdev="net_xenvirt0,mac=00:00:00:00:00:11" -- -i --eth-peer=0,00:00:00:00:00:22
-    testpmd> set fwd mac
-    testpmd> start
-
-Example output of the vhost_switch would be:
-
-.. code-block:: console
-
-    DATA:(0) MAC_ADDRESS 00:00:00:00:00:11 and VLAN_TAG 1000 registered.
-
-The above message indicates that device 0 has been registered with MAC address 00:00:00:00:00:11 and VLAN tag 1000.
-Any packets received on the NIC with these values is placed on the device's receive queue.
-
-Configure a packet stream in the packet generator, set the destination MAC address to 00:00:00:00:00:11, and VLAN to 1000,
-the guest Virtio receives these packets and sends them out with destination MAC address 00:00:00:00:00:22.
-
-Inter-VM Mode
-^^^^^^^^^^^^^
-
-Run TestPMD in guest VM1:
-
-.. code-block:: console
-
-    ./x86_64-native-linuxapp-gcc/app/testpmd -l 0-3 -n 4 --vdev="net_xenvirt0,mac=00:00:00:00:00:11" -- -i --eth-peer=0,00:00:00:00:00:22 -- -i
-
-Run TestPMD in guest VM2:
-
-.. code-block:: console
-
-    ./x86_64-native-linuxapp-gcc/app/testpmd -l 0-3 -n 4 --vdev="net_xenvirt0,mac=00:00:00:00:00:22" -- -i --eth-peer=0,00:00:00:00:00:33
-
-Configure a packet stream in the packet generator, and set the destination MAC address to 00:00:00:00:00:11 and VLAN to 1000.
-The packets received in Virtio in guest VM1 will be forwarded to Virtio in guest VM2 and
-then sent out through hardware with destination MAC address 00:00:00:00:00:33.
-
-The packet flow is:
-
-packet generator->Virtio in guest VM1->switching backend->Virtio in guest VM2->switching backend->wire
diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index 005019e..317a75e 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -48,7 +48,7 @@ LDLIBS += -lgcc_s
 
 EXPORT_MAP := rte_eal_version.map
 
-LIBABIVER := 5
+LIBABIVER := 6
 
 # specific to bsdapp exec-env
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) := eal.c
diff --git a/lib/librte_eal/bsdapp/eal/include/exec-env/rte_dom0_common.h b/lib/librte_eal/bsdapp/eal/include/exec-env/rte_dom0_common.h
deleted file mode 100644
index 99a3343..0000000
--- a/lib/librte_eal/bsdapp/eal/include/exec-env/rte_dom0_common.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*-
- *   This file is provided under a dual BSD/LGPLv2 license.  When using or
- *   redistributing this file, you may do so under either license.
- *
- *   GNU LESSER GENERAL PUBLIC LICENSE
- *
- *   Copyright(c) 2007-2014 Intel Corporation. All rights reserved.
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of version 2.1 of the GNU Lesser General Public License
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   Lesser General Public License for more details.
- *
- *   You should have received a copy of the GNU Lesser General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *   Contact Information:
- *   Intel Corporation
- *
- *
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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.
- *
- */
-
-#ifndef _RTE_DOM0_COMMON_H_
-#define _RTE_DOM0_COMMON_H_
-
-#ifdef __KERNEL__
-#include <linux/if.h>
-#endif
-
-#define DOM0_NAME_MAX   256
-#define DOM0_MM_DEV   "/dev/dom0_mm"
-
-#define DOM0_CONTIG_NUM_ORDER       9       /**< 2M order */
-#define DOM0_NUM_MEMSEG             512     /**< Maximum nb. of memory segment. */
-#define DOM0_MEMBLOCK_SIZE          0x200000 /**< Maximum nb. of memory block(2M). */
-#define DOM0_CONFIG_MEMSIZE         4096     /**< Maximum config memory size(4G). */
-#define DOM0_NUM_MEMBLOCK (DOM0_CONFIG_MEMSIZE / 2) /**< Maximum nb. of 2M memory block. */
-
-#define RTE_DOM0_IOCTL_PREPARE_MEMSEG    _IOWR(0, 1 , struct memory_info)
-#define RTE_DOM0_IOCTL_ATTACH_TO_MEMSEG  _IOWR(0, 2 , char *)
-#define RTE_DOM0_IOCTL_GET_NUM_MEMSEG    _IOWR(0, 3, int)
-#define RTE_DOM0_IOCTL_GET_MEMSEG_INFO   _IOWR(0, 4, void *)
-
-/**
- * A structure used to store memory information.
- */
-struct memory_info {
-	char name[DOM0_NAME_MAX];
-	uint64_t size;
-};
-
-/**
- * A structure used to store memory segment information.
- */
-struct memseg_info {
-	uint32_t idx;
-	uint64_t pfn;
-	uint64_t size;
-	uint64_t mfn[DOM0_NUM_MEMBLOCK];
-};
-
-/**
- * A structure used to store memory block information.
- */
-struct memblock_info {
-	uint8_t  exchange_flag;
-	uint64_t vir_addr;
-	uint64_t pfn;
-	uint64_t mfn;
-};
-#endif /* _RTE_DOM0_COMMON_H_ */
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index aac6fd7..431d872 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -87,8 +87,6 @@ DPDK_2.0 {
 	rte_thread_get_affinity;
 	rte_thread_set_affinity;
 	rte_vlog;
-	rte_xen_dom0_memory_attach;
-	rte_xen_dom0_memory_init;
 	rte_zmalloc;
 	rte_zmalloc_socket;
 
@@ -115,7 +113,6 @@ DPDK_2.2 {
 	rte_keepalive_dispatch_pings;
 	rte_keepalive_mark_alive;
 	rte_keepalive_register_core;
-	rte_xen_dom0_supported;
 
 } DPDK_2.1;
 
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 1da185e..354cded 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -97,7 +97,6 @@ eal_long_options[] = {
 	{OPT_VDEV,              1, NULL, OPT_VDEV_NUM             },
 	{OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },
 	{OPT_VMWARE_TSC_MAP,    0, NULL, OPT_VMWARE_TSC_MAP_NUM   },
-	{OPT_XEN_DOM0,          0, NULL, OPT_XEN_DOM0_NUM         },
 	{0,                     0, NULL, 0                        }
 };
 
@@ -208,8 +207,6 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
 
 	internal_cfg->syslog_facility = LOG_DAEMON;
 
-	internal_cfg->xen_dom0_support = 0;
-
 	/* if set to NONE, interrupt mode is determined automatically */
 	internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
 
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 7b7e8c8..f7c885f 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -65,7 +65,6 @@ struct internal_config {
 	volatile unsigned force_nrank;    /**< force number of ranks */
 	volatile unsigned no_hugetlbfs;   /**< true to disable hugetlbfs */
 	unsigned hugepage_unlink;         /**< true to unlink backing files */
-	volatile unsigned xen_dom0_support; /**< support app running on Xen Dom0*/
 	volatile unsigned no_pci;         /**< true to disable PCI */
 	volatile unsigned no_hpet;        /**< true to disable HPET */
 	volatile unsigned vmware_tsc_map; /**< true to use VMware TSC mapping
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 439a261..8770b85 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -81,8 +81,6 @@ enum {
 	OPT_VFIO_INTR_NUM,
 #define OPT_VMWARE_TSC_MAP    "vmware-tsc-map"
 	OPT_VMWARE_TSC_MAP_NUM,
-#define OPT_XEN_DOM0          "xen-dom0"
-	OPT_XEN_DOM0_NUM,
 	OPT_LONG_MAX_NUM
 };
 
diff --git a/lib/librte_eal/common/include/rte_memory.h b/lib/librte_eal/common/include/rte_memory.h
index 8d3960d..c545963 100644
--- a/lib/librte_eal/common/include/rte_memory.h
+++ b/lib/librte_eal/common/include/rte_memory.h
@@ -46,10 +46,6 @@
 
 #include <rte_config.h>
 
-#ifdef RTE_EXEC_ENV_LINUXAPP
-#include <exec-env/rte_dom0_common.h>
-#endif
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -116,10 +112,6 @@ struct rte_memseg {
 	int32_t socket_id;          /**< NUMA socket ID. */
 	uint32_t nchannel;          /**< Number of channels. */
 	uint32_t nrank;             /**< Number of ranks. */
-#ifdef RTE_LIBRTE_XEN_DOM0
-	 /**< store segment MFNs */
-	uint64_t mfn[DOM0_NUM_MEMBLOCK];
-#endif
 } __rte_packed;
 
 /**
@@ -195,39 +187,6 @@ unsigned rte_memory_get_nchannel(void);
  */
 unsigned rte_memory_get_nrank(void);
 
-#ifdef RTE_LIBRTE_XEN_DOM0
-
-/**< Internal use only - should DOM0 memory mapping be used */
-int rte_xen_dom0_supported(void);
-
-/**
- * Memory init for supporting application running on Xen domain0.
- *
- * @param void
- *
- * @return
- *       0: successfully
- *	 negative: error
- */
-int rte_xen_dom0_memory_init(void);
-
-/**
- * Attach to memory setments of primary process on Xen domain0.
- *
- * @param void
- *
- * @return
- *       0: successfully
- *       negative: error
- */
-int rte_xen_dom0_memory_attach(void);
-#else
-static inline int rte_xen_dom0_supported(void)
-{
-	return 0;
-}
-#endif
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_eal/linuxapp/Makefile b/lib/librte_eal/linuxapp/Makefile
index 4794696..2ebdf31 100644
--- a/lib/librte_eal/linuxapp/Makefile
+++ b/lib/librte_eal/linuxapp/Makefile
@@ -35,7 +35,5 @@ DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal
 DIRS-$(CONFIG_RTE_EAL_IGB_UIO) += igb_uio
 DIRS-$(CONFIG_RTE_KNI_KMOD) += kni
 DEPDIRS-kni := eal
-DIRS-$(CONFIG_RTE_LIBRTE_XEN_DOM0) += xen_dom0
-DEPDIRS-xen_dom0 := eal
 
 include $(RTE_SDK)/mk/rte.subdir.mk
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 90bca4d..21e0b4a 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -37,7 +37,7 @@ ARCH_DIR ?= $(RTE_ARCH)
 EXPORT_MAP := rte_eal_version.map
 VPATH += $(RTE_SDK)/lib/librte_eal/common/arch/$(ARCH_DIR)
 
-LIBABIVER := 5
+LIBABIVER := 6
 
 VPATH += $(RTE_SDK)/lib/librte_eal/common
 
@@ -58,9 +58,6 @@ endif
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) := eal.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_hugepage_info.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_memory.c
-ifeq ($(CONFIG_RTE_LIBRTE_XEN_DOM0),y)
-SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_xen_memory.c
-endif
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_thread.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_log.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_vfio.c
@@ -130,7 +127,7 @@ ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
 CFLAGS_eal_thread.o += -Wno-return-type
 endif
 
-INC := rte_interrupts.h rte_kni_common.h rte_dom0_common.h
+INC := rte_interrupts.h rte_kni_common.h
 
 SYMLINK-$(CONFIG_RTE_EXEC_ENV_LINUXAPP)-include/exec-env := \
 	$(addprefix include/exec-env/,$(INC))
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 48f12f4..d995d03 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -354,7 +354,6 @@ eal_usage(const char *prgname)
 	       "  --"OPT_BASE_VIRTADDR"     Base virtual address\n"
 	       "  --"OPT_CREATE_UIO_DEV"    Create /dev/uioX (usually done by hotplug)\n"
 	       "  --"OPT_VFIO_INTR"         Interrupt mode for VFIO (legacy|msi|msix)\n"
-	       "  --"OPT_XEN_DOM0"          Support running on Xen dom0 without hugetlbfs\n"
 	       "\n");
 	/* Allow the application to print its usage message too if hook is set */
 	if ( rte_application_usage_hook ) {
@@ -555,19 +554,6 @@ eal_parse_args(int argc, char **argv)
 			eal_usage(prgname);
 			exit(EXIT_SUCCESS);
 
-		/* long options */
-		case OPT_XEN_DOM0_NUM:
-#ifdef RTE_LIBRTE_XEN_DOM0
-			internal_config.xen_dom0_support = 1;
-#else
-			RTE_LOG(ERR, EAL, "Can't support DPDK app "
-				"running on Dom0, please configure"
-				" RTE_LIBRTE_XEN_DOM0=y\n");
-			ret = -1;
-			goto out;
-#endif
-			break;
-
 		case OPT_HUGE_DIR_NUM:
 			internal_config.hugepage_dir = optarg;
 			break;
@@ -641,15 +627,6 @@ eal_parse_args(int argc, char **argv)
 		goto out;
 	}
 
-	/* --xen-dom0 doesn't make sense with --socket-mem */
-	if (internal_config.xen_dom0_support && internal_config.force_sockets == 1) {
-		RTE_LOG(ERR, EAL, "Options --"OPT_SOCKET_MEM" cannot be specified "
-			"together with --"OPT_XEN_DOM0"\n");
-		eal_usage(prgname);
-		ret = -1;
-		goto out;
-	}
-
 	if (optind >= 0)
 		argv[optind-1] = prgname;
 	ret = optind-1;
@@ -794,7 +771,6 @@ rte_eal_init(int argc, char **argv)
 
 	if (internal_config.no_hugetlbfs == 0 &&
 			internal_config.process_type != RTE_PROC_SECONDARY &&
-			internal_config.xen_dom0_support == 0 &&
 			eal_hugepage_info_init() < 0) {
 		rte_eal_init_alert("Cannot get hugepage information.");
 		rte_errno = EACCES;
diff --git a/lib/librte_eal/linuxapp/eal/eal_memory.c b/lib/librte_eal/linuxapp/eal/eal_memory.c
index 5279128..087fad4 100644
--- a/lib/librte_eal/linuxapp/eal/eal_memory.c
+++ b/lib/librte_eal/linuxapp/eal/eal_memory.c
@@ -75,13 +75,6 @@
 
 #define PFN_MASK_SIZE	8
 
-#ifdef RTE_LIBRTE_XEN_DOM0
-int rte_xen_dom0_supported(void)
-{
-	return internal_config.xen_dom0_support;
-}
-#endif
-
 /**
  * @file
  * Huge page mapping under linux
@@ -106,10 +99,6 @@ test_phys_addrs_available(void)
 	uint64_t tmp;
 	phys_addr_t physaddr;
 
-	/* For dom0, phys addresses can always be available */
-	if (rte_xen_dom0_supported())
-		return;
-
 	if (!rte_eal_has_hugepages()) {
 		RTE_LOG(ERR, EAL,
 			"Started without hugepages support, physical addresses not available\n");
@@ -139,29 +128,6 @@ rte_mem_virt2phy(const void *virtaddr)
 	int page_size;
 	off_t offset;
 
-	/* when using dom0, /proc/self/pagemap always returns 0, check in
-	 * dpdk memory by browsing the memsegs */
-	if (rte_xen_dom0_supported()) {
-		struct rte_mem_config *mcfg;
-		struct rte_memseg *memseg;
-		unsigned i;
-
-		mcfg = rte_eal_get_configuration()->mem_config;
-		for (i = 0; i < RTE_MAX_MEMSEG; i++) {
-			memseg = &mcfg->memseg[i];
-			if (memseg->addr == NULL)
-				break;
-			if (virtaddr > memseg->addr &&
-					virtaddr < RTE_PTR_ADD(memseg->addr,
-						memseg->len)) {
-				return memseg->phys_addr +
-					RTE_PTR_DIFF(virtaddr, memseg->addr);
-			}
-		}
-
-		return RTE_BAD_PHYS_ADDR;
-	}
-
 	/* Cannot parse /proc/self/pagemap, no need to log errors everywhere */
 	if (!phys_addrs_available)
 		return RTE_BAD_PHYS_ADDR;
@@ -1067,17 +1033,6 @@ rte_eal_hugepage_init(void)
 		return 0;
 	}
 
-/* check if app runs on Xen Dom0 */
-	if (internal_config.xen_dom0_support) {
-#ifdef RTE_LIBRTE_XEN_DOM0
-		/* use dom0_mm kernel driver to init memory */
-		if (rte_xen_dom0_memory_init() < 0)
-			return -1;
-		else
-			return 0;
-#endif
-	}
-
 	/* calculate total number of hugepages available. at this point we haven't
 	 * yet started sorting them so they all are on socket 0 */
 	for (i = 0; i < (int) internal_config.num_hugepage_sizes; i++) {
@@ -1400,17 +1355,6 @@ rte_eal_hugepage_attach(void)
 
 	test_phys_addrs_available();
 
-	if (internal_config.xen_dom0_support) {
-#ifdef RTE_LIBRTE_XEN_DOM0
-		if (rte_xen_dom0_memory_attach() < 0) {
-			RTE_LOG(ERR, EAL, "Failed to attach memory segments of primary "
-					"process\n");
-			return -1;
-		}
-		return 0;
-#endif
-	}
-
 	fd_zero = open("/dev/zero", O_RDONLY);
 	if (fd_zero < 0) {
 		RTE_LOG(ERR, EAL, "Could not open /dev/zero\n");
diff --git a/lib/librte_eal/linuxapp/eal/eal_xen_memory.c b/lib/librte_eal/linuxapp/eal/eal_xen_memory.c
deleted file mode 100644
index 19db1cb..0000000
--- a/lib/librte_eal/linuxapp/eal/eal_xen_memory.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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 <errno.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/queue.h>
-#include <sys/file.h>
-#include <unistd.h>
-#include <limits.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-
-#include <rte_log.h>
-#include <rte_memory.h>
-#include <rte_memzone.h>
-#include <rte_launch.h>
-#include <rte_eal.h>
-#include <rte_eal_memconfig.h>
-#include <rte_per_lcore.h>
-#include <rte_lcore.h>
-#include <rte_common.h>
-#include <rte_string_fns.h>
-
-#include "eal_private.h"
-#include "eal_internal_cfg.h"
-#include "eal_filesystem.h"
-#include <exec-env/rte_dom0_common.h>
-
-#define PAGE_SIZE RTE_PGSIZE_4K
-#define DEFAUL_DOM0_NAME "dom0-mem"
-
-static int xen_fd = -1;
-static const char sys_dir_path[] = "/sys/kernel/mm/dom0-mm/memsize-mB";
-
-/*
- * Try to mmap *size bytes in /dev/zero. If it is successful, return the
- * pointer to the mmap'd area and keep *size unmodified. Else, retry
- * with a smaller zone: decrease *size by mem_size until it reaches
- * 0. In this case, return NULL. Note: this function returns an address
- * which is a multiple of mem_size size.
- */
-static void *
-xen_get_virtual_area(size_t *size, size_t mem_size)
-{
-	void *addr;
-	int fd;
-	long aligned_addr;
-
-	RTE_LOG(DEBUG, EAL, "Ask a virtual area of 0x%zu bytes\n", *size);
-
-	fd = open("/dev/zero", O_RDONLY);
-	if (fd < 0){
-		RTE_LOG(ERR, EAL, "Cannot open /dev/zero\n");
-		return NULL;
-	}
-	do {
-		addr = mmap(NULL, (*size) + mem_size, PROT_READ,
-			MAP_PRIVATE, fd, 0);
-		if (addr == MAP_FAILED)
-			*size -= mem_size;
-	} while (addr == MAP_FAILED && *size > 0);
-
-	if (addr == MAP_FAILED) {
-		close(fd);
-		RTE_LOG(ERR, EAL, "Cannot get a virtual area\n");
-		return NULL;
-	}
-
-	munmap(addr, (*size) + mem_size);
-	close(fd);
-
-	/* align addr to a mem_size boundary */
-	aligned_addr = (uintptr_t)addr;
-	aligned_addr = RTE_ALIGN_CEIL(aligned_addr, mem_size);
-        addr = (void *)(aligned_addr);
-
-	RTE_LOG(DEBUG, EAL, "Virtual area found at %p (size = 0x%zx)\n",
-		addr, *size);
-
-	return addr;
-}
-
-/**
- * Get memory size configuration from /sys/devices/virtual/misc/dom0_mm
- * /memsize-mB/memsize file, and the size unit is mB.
- */
-static int
-get_xen_memory_size(void)
-{
-	char path[PATH_MAX];
-	unsigned long mem_size = 0;
-	static const char *file_name;
-
-	file_name = "memsize";
-	snprintf(path, sizeof(path), "%s/%s",
-			sys_dir_path, file_name);
-
-	if (eal_parse_sysfs_value(path, &mem_size) < 0)
-		return -1;
-
-	if (mem_size == 0)
-		rte_exit(EXIT_FAILURE,"XEN-DOM0:the %s/%s was not"
-			" configured.\n",sys_dir_path, file_name);
-	if (mem_size % 2)
-		rte_exit(EXIT_FAILURE,"XEN-DOM0:the %s/%s must be"
-			" even number.\n",sys_dir_path, file_name);
-
-	if (mem_size > DOM0_CONFIG_MEMSIZE)
-		rte_exit(EXIT_FAILURE,"XEN-DOM0:the %s/%s should not be larger"
-			" than %d mB\n",sys_dir_path, file_name, DOM0_CONFIG_MEMSIZE);
-
-	return mem_size;
-}
-
-/**
- * Based on physical address to caculate MFN in Xen Dom0.
- */
-phys_addr_t
-rte_xen_mem_phy2mch(int32_t memseg_id, const phys_addr_t phy_addr)
-{
-	int mfn_id, i;
-	uint64_t mfn, mfn_offset;
-	struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
-	struct rte_memseg *memseg = mcfg->memseg;
-
-	/* find the memory segment owning the physical address */
-	if (memseg_id == -1) {
-		for (i = 0; i < RTE_MAX_MEMSEG; i++) {
-			if ((phy_addr >= memseg[i].phys_addr) &&
-					(phy_addr < memseg[i].phys_addr +
-						memseg[i].len)) {
-				memseg_id = i;
-				break;
-			}
-		}
-		if (memseg_id == -1)
-			return RTE_BAD_PHYS_ADDR;
-	}
-
-	mfn_id = (phy_addr - memseg[memseg_id].phys_addr) / RTE_PGSIZE_2M;
-
-	/*the MFN is contiguous in 2M */
-	mfn_offset = (phy_addr - memseg[memseg_id].phys_addr) %
-					RTE_PGSIZE_2M / PAGE_SIZE;
-	mfn = mfn_offset + memseg[memseg_id].mfn[mfn_id];
-
-	/** return mechine address */
-	return mfn * PAGE_SIZE + phy_addr % PAGE_SIZE;
-}
-
-int
-rte_xen_dom0_memory_init(void)
-{
-	void *vir_addr, *vma_addr = NULL;
-	int err, ret = 0;
-	uint32_t i, requested, mem_size, memseg_idx, num_memseg = 0;
-	size_t vma_len = 0;
-	struct memory_info meminfo;
-	struct memseg_info seginfo[RTE_MAX_MEMSEG];
-	int flags, page_size = getpagesize();
-	struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
-	struct rte_memseg *memseg = mcfg->memseg;
-	uint64_t total_mem = internal_config.memory;
-
-	memset(seginfo, 0, sizeof(seginfo));
-	memset(&meminfo, 0, sizeof(struct memory_info));
-
-	mem_size = get_xen_memory_size();
-	requested = (unsigned) (total_mem / 0x100000);
-	if (requested > mem_size)
-		/* if we didn't satisfy total memory requirements */
-		rte_exit(EXIT_FAILURE,"Not enough memory available! Requested: %uMB,"
-				" available: %uMB\n", requested, mem_size);
-	else if (total_mem != 0)
-		mem_size = requested;
-
-	/* Check FD and open once */
-	if (xen_fd < 0) {
-		xen_fd = open(DOM0_MM_DEV, O_RDWR);
-		if (xen_fd < 0) {
-			RTE_LOG(ERR, EAL, "Can not open %s\n",DOM0_MM_DEV);
-			return -1;
-		}
-	}
-
-	meminfo.size = mem_size;
-
-	/* construct memory mangement name for Dom0 */
-	snprintf(meminfo.name, DOM0_NAME_MAX, "%s-%s",
-		internal_config.hugefile_prefix, DEFAUL_DOM0_NAME);
-
-	/* Notify kernel driver to allocate memory */
-	ret = ioctl(xen_fd, RTE_DOM0_IOCTL_PREPARE_MEMSEG, &meminfo);
-	if (ret < 0) {
-		RTE_LOG(ERR, EAL, "XEN DOM0:failed to get memory\n");
-		err = -EIO;
-		goto fail;
-	}
-
-	/* Get number of memory segment from driver */
-	ret = ioctl(xen_fd, RTE_DOM0_IOCTL_GET_NUM_MEMSEG, &num_memseg);
-	if (ret < 0) {
-		RTE_LOG(ERR, EAL, "XEN DOM0:failed to get memseg count.\n");
-		err = -EIO;
-		goto fail;
-	}
-
-	if(num_memseg > RTE_MAX_MEMSEG){
-		RTE_LOG(ERR, EAL, "XEN DOM0: the memseg count %d is greater"
-			" than max memseg %d.\n",num_memseg, RTE_MAX_MEMSEG);
-		err = -EIO;
-		goto fail;
-	}
-
-	/* get all memory segements information */
-	ret = ioctl(xen_fd, RTE_DOM0_IOCTL_GET_MEMSEG_INFO, seginfo);
-	if (ret < 0) {
-		RTE_LOG(ERR, EAL, "XEN DOM0:failed to get memseg info.\n");
-		err = -EIO;
-		goto fail;
-	}
-
-	/* map all memory segments to contiguous user space */
-	for (memseg_idx = 0; memseg_idx < num_memseg; memseg_idx++)
-	{
-		vma_len = seginfo[memseg_idx].size;
-
-		/**
-		 * get the biggest virtual memory area up to vma_len. If it fails,
-		 * vma_addr is NULL, so let the kernel provide the address.
-		 */
-		vma_addr = xen_get_virtual_area(&vma_len, RTE_PGSIZE_2M);
-		if (vma_addr == NULL) {
-			flags = MAP_SHARED;
-			vma_len = RTE_PGSIZE_2M;
-		} else
-			flags = MAP_SHARED | MAP_FIXED;
-
-		seginfo[memseg_idx].size = vma_len;
-		vir_addr = mmap(vma_addr, seginfo[memseg_idx].size,
-			PROT_READ|PROT_WRITE, flags, xen_fd,
-			memseg_idx * page_size);
-		if (vir_addr == MAP_FAILED) {
-			RTE_LOG(ERR, EAL, "XEN DOM0:Could not mmap %s\n",
-				DOM0_MM_DEV);
-			err = -EIO;
-			goto fail;
-		}
-
-		memseg[memseg_idx].addr = vir_addr;
-		memseg[memseg_idx].phys_addr = page_size *
-			seginfo[memseg_idx].pfn ;
-		memseg[memseg_idx].len = seginfo[memseg_idx].size;
-		for ( i = 0; i < seginfo[memseg_idx].size / RTE_PGSIZE_2M; i++)
-			memseg[memseg_idx].mfn[i] = seginfo[memseg_idx].mfn[i];
-
-		/* MFNs are continuous in 2M, so assume that page size is 2M */
-		memseg[memseg_idx].hugepage_sz = RTE_PGSIZE_2M;
-
-		memseg[memseg_idx].nchannel = mcfg->nchannel;
-		memseg[memseg_idx].nrank = mcfg->nrank;
-
-		/* NUMA is not suppoted in Xen Dom0, so only set socket 0*/
-		memseg[memseg_idx].socket_id = 0;
-	}
-
-	return 0;
-fail:
-	if (xen_fd > 0) {
-		close(xen_fd);
-		xen_fd = -1;
-	}
-	return err;
-}
-
-/*
- * This creates the memory mappings in the secondary process to match that of
- * the server process. It goes through each memory segment in the DPDK runtime
- * configuration, mapping them in order to form a contiguous block in the
- * virtual memory space
- */
-int
-rte_xen_dom0_memory_attach(void)
-{
-	const struct rte_mem_config *mcfg;
-	unsigned s = 0; /* s used to track the segment number */
-	int xen_fd = -1;
-	int ret = -1;
-	void *vir_addr;
-	char name[DOM0_NAME_MAX] = {0};
-	int page_size = getpagesize();
-
-	mcfg = rte_eal_get_configuration()->mem_config;
-
-	/* Check FD and open once */
-	if (xen_fd < 0) {
-		xen_fd = open(DOM0_MM_DEV, O_RDWR);
-		if (xen_fd < 0) {
-			RTE_LOG(ERR, EAL, "Can not open %s\n",DOM0_MM_DEV);
-			goto error;
-		}
-	}
-
-	/* construct memory mangement name for Dom0 */
-	snprintf(name, DOM0_NAME_MAX, "%s-%s",
-		internal_config.hugefile_prefix, DEFAUL_DOM0_NAME);
-	/* attach to memory segments of primary process */
-	ret = ioctl(xen_fd, RTE_DOM0_IOCTL_ATTACH_TO_MEMSEG, name);
-	if (ret) {
-		RTE_LOG(ERR, EAL,"attach memory segments fail.\n");
-		goto error;
-	}
-
-	/* map all segments into memory to make sure we get the addrs */
-	for (s = 0; s < RTE_MAX_MEMSEG; ++s) {
-
-		/*
-		 * the first memory segment with len==0 is the one that
-		 * follows the last valid segment.
-		 */
-		if (mcfg->memseg[s].len == 0)
-			break;
-
-		vir_addr = mmap(mcfg->memseg[s].addr, mcfg->memseg[s].len,
-				PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, xen_fd,
-				s * page_size);
-		if (vir_addr == MAP_FAILED) {
-			RTE_LOG(ERR, EAL, "Could not mmap %llu bytes "
-				"in %s to requested address [%p]\n",
-				(unsigned long long)mcfg->memseg[s].len, DOM0_MM_DEV,
-				mcfg->memseg[s].addr);
-			goto error;
-		}
-	}
-	return 0;
-
-error:
-	if (xen_fd >= 0) {
-		close(xen_fd);
-		xen_fd = -1;
-	}
-	return -1;
-}
diff --git a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_dom0_common.h b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_dom0_common.h
deleted file mode 100644
index d970778..0000000
--- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_dom0_common.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*-
- *   This file is provided under a dual BSD/LGPLv2 license.  When using or
- *   redistributing this file, you may do so under either license.
- *
- *   GNU LESSER GENERAL PUBLIC LICENSE
- *
- *   Copyright(c) 2007-2014 Intel Corporation. All rights reserved.
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of version 2.1 of the GNU Lesser General Public License
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   Lesser General Public License for more details.
- *
- *   You should have received a copy of the GNU Lesser General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *   Contact Information:
- *   Intel Corporation
- *
- *
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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.
- *
- */
-
-#ifndef _RTE_DOM0_COMMON_H_
-#define _RTE_DOM0_COMMON_H_
-
-#ifdef __KERNEL__
-#include <linux/if.h>
-#endif
-
-#define DOM0_NAME_MAX   256
-#define DOM0_MM_DEV   "/dev/dom0_mm"
-
-#define DOM0_CONTIG_NUM_ORDER       9       /**< order of 2M */
-#define DOM0_NUM_MEMSEG             512     /**< Maximum nb. of memory segment. */
-#define DOM0_MEMBLOCK_SIZE          0x200000 /**< size of memory block(2M). */
-#define DOM0_CONFIG_MEMSIZE         4096     /**< Maximum config memory size(4G). */
-#define DOM0_NUM_MEMBLOCK (DOM0_CONFIG_MEMSIZE / 2) /**< Maximum nb. of 2M memory block. */
-
-#define RTE_DOM0_IOCTL_PREPARE_MEMSEG    _IOWR(0, 1 , struct memory_info)
-#define RTE_DOM0_IOCTL_ATTACH_TO_MEMSEG  _IOWR(0, 2 , char *)
-#define RTE_DOM0_IOCTL_GET_NUM_MEMSEG    _IOWR(0, 3, int)
-#define RTE_DOM0_IOCTL_GET_MEMSEG_INFO   _IOWR(0, 4, void *)
-
-/**
- * A structure used to store memory information.
- */
-struct memory_info {
-	char name[DOM0_NAME_MAX];
-	uint64_t size;
-};
-
-/**
- * A structure used to store memory segment information.
- */
-struct memseg_info {
-	uint32_t idx;
-	uint64_t pfn;
-	uint64_t size;
-	uint64_t mfn[DOM0_NUM_MEMBLOCK];
-};
-
-/**
- * A structure used to store memory block information.
- */
-struct memblock_info {
-	uint8_t exchange_flag;
-	uint8_t used;
-	uint64_t vir_addr;
-	uint64_t pfn;
-	uint64_t mfn;
-};
-#endif /* _RTE_DOM0_COMMON_H_ */
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 3a8f154..17c8984 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -87,8 +87,6 @@ DPDK_2.0 {
 	rte_thread_get_affinity;
 	rte_thread_set_affinity;
 	rte_vlog;
-	rte_xen_dom0_memory_attach;
-	rte_xen_dom0_memory_init;
 	rte_zmalloc;
 	rte_zmalloc_socket;
 
@@ -118,8 +116,6 @@ DPDK_2.2 {
 	rte_keepalive_dispatch_pings;
 	rte_keepalive_mark_alive;
 	rte_keepalive_register_core;
-	rte_xen_dom0_supported;
-	rte_xen_mem_phy2mch;
 
 } DPDK_2.1;
 
diff --git a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c
index 07a19a3..3d5c2f3 100644
--- a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c
+++ b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c
@@ -33,9 +33,6 @@
 #include <linux/version.h>
 #include <linux/slab.h>
 
-#ifdef CONFIG_XEN_DOM0
-#include <xen/xen.h>
-#endif
 #include <rte_pci_dev_features.h>
 
 #include "compat.h"
@@ -201,52 +198,6 @@ igbuio_pci_release(struct uio_info *info, struct inode *inode)
 	return 0;
 }
 
-#ifdef CONFIG_XEN_DOM0
-static int
-igbuio_dom0_mmap_phys(struct uio_info *info, struct vm_area_struct *vma)
-{
-	int idx;
-
-	idx = (int)vma->vm_pgoff;
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-#ifdef HAVE_PTE_MASK_PAGE_IOMAP
-	vma->vm_page_prot.pgprot |= _PAGE_IOMAP;
-#endif
-
-	return remap_pfn_range(vma,
-			vma->vm_start,
-			info->mem[idx].addr >> PAGE_SHIFT,
-			vma->vm_end - vma->vm_start,
-			vma->vm_page_prot);
-}
-
-/**
- * This is uio device mmap method which will use igbuio mmap for Xen
- * Dom0 environment.
- */
-static int
-igbuio_dom0_pci_mmap(struct uio_info *info, struct vm_area_struct *vma)
-{
-	int idx;
-
-	if (vma->vm_pgoff >= MAX_UIO_MAPS)
-		return -EINVAL;
-
-	if (info->mem[vma->vm_pgoff].size == 0)
-		return -EINVAL;
-
-	idx = (int)vma->vm_pgoff;
-	switch (info->mem[idx].memtype) {
-	case UIO_MEM_PHYS:
-		return igbuio_dom0_mmap_phys(info, vma);
-	case UIO_MEM_LOGICAL:
-	case UIO_MEM_VIRTUAL:
-	default:
-		return -EINVAL;
-	}
-}
-#endif
-
 /* Remap pci resources described by bar #pci_bar in uio resource n. */
 static int
 igbuio_pci_setup_iomem(struct pci_dev *dev, struct uio_info *info,
@@ -405,11 +356,6 @@ igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	udev->info.irqcontrol = igbuio_pci_irqcontrol;
 	udev->info.open = igbuio_pci_open;
 	udev->info.release = igbuio_pci_release;
-#ifdef CONFIG_XEN_DOM0
-	/* check if the driver run on Xen Dom0 */
-	if (xen_initial_domain())
-		udev->info.mmap = igbuio_dom0_pci_mmap;
-#endif
 	udev->info.priv = udev;
 	udev->pdev = dev;
 
diff --git a/lib/librte_eal/linuxapp/xen_dom0/Makefile b/lib/librte_eal/linuxapp/xen_dom0/Makefile
deleted file mode 100644
index be51a82..0000000
--- a/lib/librte_eal/linuxapp/xen_dom0/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-#   BSD LICENSE
-#
-#   Copyright(c) 2010-2014 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_SDK)/mk/rte.vars.mk
-
-#
-# module name and path
-#
-MODULE = rte_dom0_mm
-
-#
-# CFLAGS
-#
-MODULE_CFLAGS += -I$(SRCDIR) --param max-inline-insns-single=50
-MODULE_CFLAGS += -I$(RTE_OUTPUT)/include
-MODULE_CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h
-MODULE_CFLAGS += -Wall -Werror
-
-#
-# all source are stored in SRCS-y
-#
-
-SRCS-y += dom0_mm_misc.c
-
-include $(RTE_SDK)/mk/rte.module.mk
diff --git a/lib/librte_eal/linuxapp/xen_dom0/compat.h b/lib/librte_eal/linuxapp/xen_dom0/compat.h
deleted file mode 100644
index e6eb97f..0000000
--- a/lib/librte_eal/linuxapp/xen_dom0/compat.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Minimal wrappers to allow compiling xen_dom0 on older kernels.
- */
-
-#ifndef RHEL_RELEASE_VERSION
-#define RHEL_RELEASE_VERSION(a, b) (((a) << 8) + (b))
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && \
-	(!(defined(RHEL_RELEASE_CODE) && \
-	 RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6, 4)))
-
-#define kstrtoul strict_strtoul
-
-#endif /* < 2.6.39 */
diff --git a/lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h b/lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h
deleted file mode 100644
index 9d5ffb2..0000000
--- a/lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*-
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- *   redistributing this file, you may do so under either license.
- *
- *   GPL LICENSE SUMMARY
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of version 2 of the GNU General Public License as
- *   published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *   The full GNU General Public License is included in this distribution
- *   in the file called LICENSE.GPL.
- *
- *   Contact Information:
- *   Intel Corporation
- *
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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.
- *
- */
-#ifndef _DOM0_MM_DEV_H_
-#define _DOM0_MM_DEV_H_
-
-#include <linux/wait.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <exec-env/rte_dom0_common.h>
-
-#define NUM_MEM_CTX     256  /**< Maximum number of memory context*/
-#define MAX_EXCHANGE_FAIL_TIME 5  /**< Maximum times of allowing exchange fail .*/
-#define MAX_MEMBLOCK_SIZE (2 * DOM0_MEMBLOCK_SIZE)
-#define MAX_NUM_ORDER     (DOM0_CONTIG_NUM_ORDER + 1)
-#define SIZE_PER_BLOCK    2       /**< Size of memory block (2MB).*/
-
-/**
- * A structure describing the private information for a dom0 device.
- */
-struct dom0_mm_dev {
-	struct miscdevice miscdev;
-	uint8_t fail_times;
-	uint32_t used_memsize;
-	uint32_t num_mem_ctx;
-	uint32_t config_memsize;
-	uint32_t num_bigblock;
-	struct  dom0_mm_data *mm_data[NUM_MEM_CTX];
-	struct mutex data_lock;
-};
-
-struct dom0_mm_data{
-	uint32_t refcnt;
-	uint32_t num_memseg; /**< Number of memory segment. */
-	uint32_t mem_size;   /**< Size of requesting memory. */
-
-	char name[DOM0_NAME_MAX];
-
-	/** Store global memory block IDs used by an instance */
-	uint32_t block_num[DOM0_NUM_MEMBLOCK];
-
-	/** Store memory block information.*/
-	struct memblock_info block_info[DOM0_NUM_MEMBLOCK];
-
-	/** Store memory segment information.*/
-	struct memseg_info  seg_info[DOM0_NUM_MEMSEG];
-};
-
-#define XEN_ERR(args...) printk(KERN_DEBUG "XEN_DOM0: Error: " args)
-#define XEN_PRINT(args...) printk(KERN_DEBUG "XEN_DOM0: " args)
-#endif
diff --git a/lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c b/lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c
deleted file mode 100644
index 79630ba..0000000
--- a/lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c
+++ /dev/null
@@ -1,780 +0,0 @@
-/*-
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- *   redistributing this file, you may do so under either license.
- *
- *   GPL LICENSE SUMMARY
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of version 2 of the GNU General Public License as
- *   published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *   The full GNU General Public License is included in this distribution
- *   in the file called LICENSE.GPL.
- *
- *   Contact Information:
- *   Intel Corporation
- *
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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 <linux/module.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <linux/version.h>
-
-#include <xen/xen.h>
-#include <xen/page.h>
-#include <xen/xen-ops.h>
-#include <xen/interface/memory.h>
-
-#include <exec-env/rte_dom0_common.h>
-
-#include "compat.h"
-#include "dom0_mm_dev.h"
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Kernel Module for supporting DPDK running on Xen Dom0");
-
-static struct dom0_mm_dev dom0_dev;
-static struct kobject *dom0_kobj = NULL;
-
-static struct memblock_info *rsv_mm_info;
-
-/* Default configuration for reserved memory size(2048 MB). */
-static uint32_t rsv_memsize = 2048;
-
-static int dom0_open(struct inode *inode, struct file *file);
-static int dom0_release(struct inode *inode, struct file *file);
-static int dom0_ioctl(struct file *file, unsigned int ioctl_num,
-		unsigned long ioctl_param);
-static int dom0_mmap(struct file *file, struct vm_area_struct *vma);
-static int dom0_memory_free(uint32_t size);
-static int dom0_memory_release(struct dom0_mm_data *mm_data);
-
-static const struct file_operations data_fops = {
-	.owner = THIS_MODULE,
-	.open = dom0_open,
-	.release = dom0_release,
-	.mmap = dom0_mmap,
-	.unlocked_ioctl = (void *)dom0_ioctl,
-};
-
-static ssize_t
-show_memsize_rsvd(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, 10, "%u\n", dom0_dev.used_memsize);
-}
-
-static ssize_t
-show_memsize(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, 10, "%u\n", dom0_dev.config_memsize);
-}
-
-static ssize_t
-store_memsize(struct device *dev, struct device_attribute *attr,
-            const char *buf, size_t count)
-{
-	int err = 0;
-	unsigned long mem_size;
-
-	if (0 != kstrtoul(buf, 0, &mem_size))
-		return  -EINVAL;
-
-	mutex_lock(&dom0_dev.data_lock);
-	if (0 == mem_size) {
-		err = -EINVAL;
-		goto fail;
-	} else if (mem_size > (rsv_memsize - dom0_dev.used_memsize)) {
-		XEN_ERR("configure memory size fail\n");
-		err = -EINVAL;
-		goto fail;
-	} else
-		dom0_dev.config_memsize = mem_size;
-
-fail:
-	mutex_unlock(&dom0_dev.data_lock);
-	return err ? err : count;
-}
-
-static DEVICE_ATTR(memsize, S_IRUGO | S_IWUSR, show_memsize, store_memsize);
-static DEVICE_ATTR(memsize_rsvd, S_IRUGO, show_memsize_rsvd, NULL);
-
-static struct attribute *dev_attrs[] = {
-	&dev_attr_memsize.attr,
-	&dev_attr_memsize_rsvd.attr,
-	NULL,
-};
-
-/* the memory size unit is MB */
-static const struct attribute_group dev_attr_grp = {
-	.name = "memsize-mB",
-	.attrs = dev_attrs,
-};
-
-
-static void
-sort_viraddr(struct memblock_info *mb, int cnt)
-{
-	int i,j;
-	uint64_t tmp_pfn;
-	uint64_t tmp_viraddr;
-
-	/*sort virtual address and pfn */
-	for(i = 0; i < cnt; i ++) {
-		for(j = cnt - 1; j > i; j--) {
-			if(mb[j].pfn < mb[j - 1].pfn) {
-				tmp_pfn = mb[j - 1].pfn;
-				mb[j - 1].pfn = mb[j].pfn;
-				mb[j].pfn = tmp_pfn;
-
-				tmp_viraddr = mb[j - 1].vir_addr;
-				mb[j - 1].vir_addr = mb[j].vir_addr;
-				mb[j].vir_addr = tmp_viraddr;
-			}
-		}
-	}
-}
-
-static int
-dom0_find_memdata(const char * mem_name)
-{
-	unsigned i;
-	int idx = -1;
-	for(i = 0; i< NUM_MEM_CTX; i++) {
-		if(dom0_dev.mm_data[i] == NULL)
-			continue;
-		if (!strncmp(dom0_dev.mm_data[i]->name, mem_name,
-			sizeof(char) * DOM0_NAME_MAX)) {
-			idx = i;
-			break;
-		}
-	}
-
-	return idx;
-}
-
-static int
-dom0_find_mempos(void)
-{
-	unsigned i;
-	int idx = -1;
-
-	for(i = 0; i< NUM_MEM_CTX; i++) {
-		if(dom0_dev.mm_data[i] == NULL){
-			idx = i;
-			break;
-		}
-	}
-
-	return idx;
-}
-
-static int
-dom0_memory_release(struct dom0_mm_data *mm_data)
-{
-	int idx;
-	uint32_t  num_block, block_id;
-
-	/* each memory block is 2M */
-	num_block = mm_data->mem_size / SIZE_PER_BLOCK;
-	if (num_block == 0)
-		return -EINVAL;
-
-	/* reset global memory data */
-	idx = dom0_find_memdata(mm_data->name);
-	if (idx >= 0) {
-		dom0_dev.used_memsize -= mm_data->mem_size;
-		dom0_dev.mm_data[idx] = NULL;
-		dom0_dev.num_mem_ctx--;
-	}
-
-	/* reset these memory blocks status as free */
-	for (idx = 0; idx < num_block; idx++) {
-		block_id = mm_data->block_num[idx];
-		rsv_mm_info[block_id].used = 0;
-	}
-
-	memset(mm_data, 0, sizeof(struct dom0_mm_data));
-	vfree(mm_data);
-	return 0;
-}
-
-static int
-dom0_memory_free(uint32_t rsv_size)
-{
-	uint64_t vstart, vaddr;
-	uint32_t i, num_block, size;
-
-	if (!xen_pv_domain())
-		return -1;
-
-	/* each memory block is 2M */
-	num_block = rsv_size / SIZE_PER_BLOCK;
-	if (num_block == 0)
-		return -EINVAL;
-
-	/* free all memory blocks of size of 4M and destroy contiguous region */
-	for (i = 0; i < dom0_dev.num_bigblock * 2; i += 2) {
-		vstart = rsv_mm_info[i].vir_addr;
-		if (vstart) {
-		#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
-			if (rsv_mm_info[i].exchange_flag)
-				xen_destroy_contiguous_region(vstart,
-						DOM0_CONTIG_NUM_ORDER);
-			if (rsv_mm_info[i + 1].exchange_flag)
-				xen_destroy_contiguous_region(vstart +
-						DOM0_MEMBLOCK_SIZE,
-						DOM0_CONTIG_NUM_ORDER);
-		#else
-			if (rsv_mm_info[i].exchange_flag)
-				xen_destroy_contiguous_region(rsv_mm_info[i].pfn
-					* PAGE_SIZE,
-					DOM0_CONTIG_NUM_ORDER);
-			if (rsv_mm_info[i + 1].exchange_flag)
-				xen_destroy_contiguous_region(rsv_mm_info[i].pfn
-					* PAGE_SIZE + DOM0_MEMBLOCK_SIZE,
-					DOM0_CONTIG_NUM_ORDER);
-		#endif
-
-			size = DOM0_MEMBLOCK_SIZE * 2;
-			vaddr = vstart;
-			while (size > 0) {
-				ClearPageReserved(virt_to_page(vaddr));
-				vaddr += PAGE_SIZE;
-				size -= PAGE_SIZE;
-			}
-			free_pages(vstart, MAX_NUM_ORDER);
-		}
-	}
-
-	/* free all memory blocks size of 2M and destroy contiguous region */
-	for (; i < num_block; i++) {
-		vstart = rsv_mm_info[i].vir_addr;
-		if (vstart) {
-			if (rsv_mm_info[i].exchange_flag)
-				xen_destroy_contiguous_region(vstart,
-					DOM0_CONTIG_NUM_ORDER);
-
-			size = DOM0_MEMBLOCK_SIZE;
-			vaddr = vstart;
-			while (size > 0) {
-				ClearPageReserved(virt_to_page(vaddr));
-				vaddr += PAGE_SIZE;
-				size -= PAGE_SIZE;
-			}
-			free_pages(vstart, DOM0_CONTIG_NUM_ORDER);
-		}
-	}
-
-	memset(rsv_mm_info, 0, sizeof(struct memblock_info) * num_block);
-	vfree(rsv_mm_info);
-	rsv_mm_info = NULL;
-
-	return 0;
-}
-
-static void
-find_free_memory(uint32_t count, struct dom0_mm_data *mm_data)
-{
-	uint32_t i = 0;
-	uint32_t j = 0;
-
-	while ((i < count) && (j < rsv_memsize / SIZE_PER_BLOCK)) {
-		if (rsv_mm_info[j].used == 0) {
-			mm_data->block_info[i].pfn = rsv_mm_info[j].pfn;
-			mm_data->block_info[i].vir_addr =
-				rsv_mm_info[j].vir_addr;
-			mm_data->block_info[i].mfn = rsv_mm_info[j].mfn;
-			mm_data->block_info[i].exchange_flag =
-				rsv_mm_info[j].exchange_flag;
-			mm_data->block_num[i] = j;
-			rsv_mm_info[j].used = 1;
-			i++;
-		}
-		j++;
-	}
-}
-
-/**
- * Find all memory segments in which physical addresses are contiguous.
- */
-static void
-find_memseg(int count, struct dom0_mm_data * mm_data)
-{
-	int i = 0;
-	int j, k, idx = 0;
-	uint64_t zone_len, pfn, num_block;
-
-	while(i < count) {
-		if (mm_data->block_info[i].exchange_flag == 0) {
-			i++;
-			continue;
-		}
-		k = 0;
-		pfn = mm_data->block_info[i].pfn;
-		mm_data->seg_info[idx].pfn = pfn;
-		mm_data->seg_info[idx].mfn[k] = mm_data->block_info[i].mfn;
-
-		for (j = i + 1; j < count; j++) {
-
-			/* ignore exchange fail memory block */
-			if (mm_data->block_info[j].exchange_flag == 0)
-				break;
-
-			if (mm_data->block_info[j].pfn !=
-				(mm_data->block_info[j - 1].pfn +
-					 DOM0_MEMBLOCK_SIZE / PAGE_SIZE))
-			    break;
-			++k;
-			mm_data->seg_info[idx].mfn[k] = mm_data->block_info[j].mfn;
-		}
-
-		num_block = j - i;
-		zone_len = num_block * DOM0_MEMBLOCK_SIZE;
-		mm_data->seg_info[idx].size = zone_len;
-
-		XEN_PRINT("memseg id=%d, size=0x%llx\n", idx, zone_len);
-		i = i+ num_block;
-		idx++;
-		if (idx == DOM0_NUM_MEMSEG)
-			break;
-	}
-	mm_data->num_memseg = idx;
-}
-
-static int
-dom0_memory_reserve(uint32_t rsv_size)
-{
-	uint64_t pfn, vstart, vaddr;
-	uint32_t i, num_block, size, allocated_size = 0;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
-	dma_addr_t dma_handle;
-#endif
-
-	/* 2M as memory block */
-	num_block = rsv_size / SIZE_PER_BLOCK;
-
-	rsv_mm_info = vmalloc(sizeof(struct memblock_info) * num_block);
-	if (!rsv_mm_info) {
-		XEN_ERR("Unable to allocate device memory information\n");
-		return -ENOMEM;
-	}
-	memset(rsv_mm_info, 0, sizeof(struct memblock_info) * num_block);
-
-	/* try alloc size of 4M once */
-	for (i = 0; i < num_block; i += 2) {
-		vstart = (unsigned long)
-			__get_free_pages(GFP_ATOMIC, MAX_NUM_ORDER);
-		if (vstart == 0)
-			break;
-
-		dom0_dev.num_bigblock = i / 2 + 1;
-		allocated_size =  SIZE_PER_BLOCK * (i + 2);
-
-		/* size of 4M */
-		size = DOM0_MEMBLOCK_SIZE * 2;
-
-		vaddr = vstart;
-		while (size > 0) {
-			SetPageReserved(virt_to_page(vaddr));
-			vaddr += PAGE_SIZE;
-			size -= PAGE_SIZE;
-		}
-
-		pfn = virt_to_pfn(vstart);
-		rsv_mm_info[i].pfn = pfn;
-		rsv_mm_info[i].vir_addr = vstart;
-		rsv_mm_info[i + 1].pfn =
-				pfn + DOM0_MEMBLOCK_SIZE / PAGE_SIZE;
-		rsv_mm_info[i + 1].vir_addr =
-				vstart + DOM0_MEMBLOCK_SIZE;
-	}
-
-	/*if it failed to alloc 4M, and continue to alloc 2M once */
-	for (; i < num_block; i++) {
-		vstart = (unsigned long)
-			__get_free_pages(GFP_ATOMIC, DOM0_CONTIG_NUM_ORDER);
-		if (vstart == 0) {
-			XEN_ERR("allocate memory fail.\n");
-			dom0_memory_free(allocated_size);
-			return -ENOMEM;
-		}
-
-		allocated_size += SIZE_PER_BLOCK;
-
-		size = DOM0_MEMBLOCK_SIZE;
-		vaddr = vstart;
-		while (size > 0) {
-			SetPageReserved(virt_to_page(vaddr));
-			vaddr += PAGE_SIZE;
-			size -= PAGE_SIZE;
-		}
-		pfn = virt_to_pfn(vstart);
-		rsv_mm_info[i].pfn = pfn;
-		rsv_mm_info[i].vir_addr = vstart;
-	}
-
-	sort_viraddr(rsv_mm_info, num_block);
-
-	for (i = 0; i< num_block; i++) {
-
-		/*
-		 * This API is used to exchage MFN for getting a block of
-		 * contiguous physical addresses, its maximum size is 2M.
-		 */
-	#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
-		if (xen_create_contiguous_region(rsv_mm_info[i].vir_addr,
-				DOM0_CONTIG_NUM_ORDER, 0) == 0) {
-	#else
-		if (xen_create_contiguous_region(rsv_mm_info[i].pfn * PAGE_SIZE,
-				DOM0_CONTIG_NUM_ORDER, 0, &dma_handle) == 0) {
-	#endif
-			rsv_mm_info[i].exchange_flag = 1;
-			rsv_mm_info[i].mfn =
-				pfn_to_mfn(rsv_mm_info[i].pfn);
-			rsv_mm_info[i].used = 0;
-		} else {
-			XEN_ERR("exchange memeory fail\n");
-			rsv_mm_info[i].exchange_flag = 0;
-			dom0_dev.fail_times++;
-			if (dom0_dev.fail_times > MAX_EXCHANGE_FAIL_TIME) {
-				dom0_memory_free(rsv_size);
-				return  -EFAULT;
-			}
-		}
-	}
-
-	return 0;
-}
-
-static int
-dom0_prepare_memsegs(struct memory_info *meminfo, struct dom0_mm_data *mm_data)
-{
-	uint32_t num_block;
-	int idx;
-
-	/* check if there is a free name buffer */
-	memcpy(mm_data->name, meminfo->name, DOM0_NAME_MAX);
-	mm_data->name[DOM0_NAME_MAX - 1] = '\0';
-	idx = dom0_find_mempos();
-	if (idx < 0)
-		return -1;
-
-	num_block = meminfo->size / SIZE_PER_BLOCK;
-	/* find free memory and new memory segments*/
-	find_free_memory(num_block, mm_data);
-	find_memseg(num_block, mm_data);
-
-	/* update private memory data */
-	mm_data->refcnt++;
-	mm_data->mem_size = meminfo->size;
-
-	/* update global memory data */
-	dom0_dev.mm_data[idx] = mm_data;
-	dom0_dev.num_mem_ctx++;
-	dom0_dev.used_memsize += mm_data->mem_size;
-
-	return 0;
-}
-
-static int
-dom0_check_memory (struct memory_info *meminfo)
-{
-	int idx;
-	uint64_t mem_size;
-
-	/* round memory size to the next even number. */
-	if (meminfo->size % 2)
-		++meminfo->size;
-
-	mem_size = meminfo->size;
-	if (dom0_dev.num_mem_ctx > NUM_MEM_CTX) {
-		XEN_ERR("Memory data space is full in Dom0 driver\n");
-		return -1;
-	}
-	idx = dom0_find_memdata(meminfo->name);
-	if (idx >= 0) {
-		XEN_ERR("Memory data name %s has already exsited in Dom0 driver.\n",
-			meminfo->name);
-		return -1;
-	}
-	if ((dom0_dev.used_memsize + mem_size) > rsv_memsize) {
-		XEN_ERR("Total size can't be larger than reserved size.\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int __init
-dom0_init(void)
-{
-	if (!xen_domain())
-		return -ENODEV;
-
-	if (rsv_memsize > DOM0_CONFIG_MEMSIZE) {
-		XEN_ERR("The reserved memory size cannot be greater than %d\n",
-			DOM0_CONFIG_MEMSIZE);
-		return -EINVAL;
-	}
-
-	/* Setup the misc device */
-	dom0_dev.miscdev.minor = MISC_DYNAMIC_MINOR;
-	dom0_dev.miscdev.name = "dom0_mm";
-	dom0_dev.miscdev.fops = &data_fops;
-
-	/* register misc char device */
-	if (misc_register(&dom0_dev.miscdev) != 0) {
-		XEN_ERR("Misc device registration failed\n");
-		return -EPERM;
-	}
-
-	mutex_init(&dom0_dev.data_lock);
-	dom0_kobj = kobject_create_and_add("dom0-mm", mm_kobj);
-
-	if (!dom0_kobj) {
-		XEN_ERR("dom0-mm object creation failed\n");
-		misc_deregister(&dom0_dev.miscdev);
-		return -ENOMEM;
-	}
-
-	if (sysfs_create_group(dom0_kobj, &dev_attr_grp)) {
-		kobject_put(dom0_kobj);
-		misc_deregister(&dom0_dev.miscdev);
-		return -EPERM;
-	}
-
-	if (dom0_memory_reserve(rsv_memsize) < 0) {
-		sysfs_remove_group(dom0_kobj, &dev_attr_grp);
-		kobject_put(dom0_kobj);
-		misc_deregister(&dom0_dev.miscdev);
-		return -ENOMEM;
-	}
-
-	XEN_PRINT("####### DPDK Xen Dom0 module loaded  #######\n");
-
-	return 0;
-}
-
-static void __exit
-dom0_exit(void)
-{
-	if (rsv_mm_info != NULL)
-		dom0_memory_free(rsv_memsize);
-
-	sysfs_remove_group(dom0_kobj, &dev_attr_grp);
-	kobject_put(dom0_kobj);
-	misc_deregister(&dom0_dev.miscdev);
-
-	XEN_PRINT("####### DPDK Xen Dom0 module unloaded  #######\n");
-}
-
-static int
-dom0_open(struct inode *inode, struct file *file)
-{
-	file->private_data = NULL;
-
-	XEN_PRINT(KERN_INFO "/dev/dom0_mm opened\n");
-	return 0;
-}
-
-static int
-dom0_release(struct inode *inode, struct file *file)
-{
-	int ret = 0;
-	struct dom0_mm_data *mm_data = file->private_data;
-
-	if (mm_data == NULL)
-		return ret;
-
-	mutex_lock(&dom0_dev.data_lock);
-	if (--mm_data->refcnt == 0)
-		ret = dom0_memory_release(mm_data);
-	mutex_unlock(&dom0_dev.data_lock);
-
-	file->private_data = NULL;
-	XEN_PRINT(KERN_INFO "/dev/dom0_mm closed\n");
-	return ret;
-}
-
-static int
-dom0_mmap(struct file *file, struct vm_area_struct *vm)
-{
-	int status = 0;
-	uint32_t idx = vm->vm_pgoff;
-	uint64_t pfn, size = vm->vm_end - vm->vm_start;
-	struct dom0_mm_data *mm_data = file->private_data;
-
-	if(mm_data == NULL)
-		return -EINVAL;
-
-	mutex_lock(&dom0_dev.data_lock);
-	if (idx >= mm_data->num_memseg) {
-		mutex_unlock(&dom0_dev.data_lock);
-		return -EINVAL;
-	}
-
-	if (size > mm_data->seg_info[idx].size){
-		mutex_unlock(&dom0_dev.data_lock);
-		return -EINVAL;
-	}
-
-	XEN_PRINT("mmap memseg idx =%d,size = 0x%llx\n", idx, size);
-
-	pfn = mm_data->seg_info[idx].pfn;
-	mutex_unlock(&dom0_dev.data_lock);
-
-	status = remap_pfn_range(vm, vm->vm_start, pfn, size, PAGE_SHARED);
-
-	return status;
-}
-static int
-dom0_ioctl(struct file *file,
-	unsigned int ioctl_num,
-	unsigned long ioctl_param)
-{
-	int idx, ret;
-	char name[DOM0_NAME_MAX] = {0};
-	struct memory_info meminfo;
-	struct dom0_mm_data *mm_data = file->private_data;
-
-	XEN_PRINT("IOCTL num=0x%0x param=0x%0lx \n", ioctl_num, ioctl_param);
-
-	/**
-	 * Switch according to the ioctl called
-	 */
-	switch _IOC_NR(ioctl_num) {
-	case _IOC_NR(RTE_DOM0_IOCTL_PREPARE_MEMSEG):
-		ret = copy_from_user(&meminfo, (void *)ioctl_param,
-			sizeof(struct memory_info));
-		if (ret)
-			return  -EFAULT;
-
-		if (mm_data != NULL) {
-			XEN_ERR("Cannot create memory segment for the same"
-				" file descriptor\n");
-			return -EINVAL;
-		}
-
-		/* Allocate private data */
-		mm_data = vmalloc(sizeof(struct dom0_mm_data));
-		if (!mm_data) {
-			XEN_ERR("Unable to allocate device private data\n");
-			return -ENOMEM;
-		}
-		memset(mm_data, 0, sizeof(struct dom0_mm_data));
-
-		mutex_lock(&dom0_dev.data_lock);
-		/* check if we can allocate memory*/
-		if (dom0_check_memory(&meminfo) < 0) {
-			mutex_unlock(&dom0_dev.data_lock);
-			vfree(mm_data);
-			return -EINVAL;
-		}
-
-		/* allocate memory and created memory segments*/
-		if (dom0_prepare_memsegs(&meminfo, mm_data) < 0) {
-			XEN_ERR("create memory segment fail.\n");
-			mutex_unlock(&dom0_dev.data_lock);
-			return -EIO;
-		}
-
-		file->private_data = mm_data;
-		mutex_unlock(&dom0_dev.data_lock);
-		break;
-
-	/* support multiple process in term of memory mapping*/
-	case _IOC_NR(RTE_DOM0_IOCTL_ATTACH_TO_MEMSEG):
-		ret = copy_from_user(name, (void *)ioctl_param,
-				sizeof(char) * DOM0_NAME_MAX);
-		if (ret)
-			return -EFAULT;
-
-		mutex_lock(&dom0_dev.data_lock);
-		idx = dom0_find_memdata(name);
-		if (idx < 0) {
-			mutex_unlock(&dom0_dev.data_lock);
-			return -EINVAL;
-		}
-
-		mm_data = dom0_dev.mm_data[idx];
-		mm_data->refcnt++;
-		file->private_data = mm_data;
-		mutex_unlock(&dom0_dev.data_lock);
-		break;
-
-	case _IOC_NR(RTE_DOM0_IOCTL_GET_NUM_MEMSEG):
-		ret = copy_to_user((void *)ioctl_param, &mm_data->num_memseg,
-				sizeof(int));
-		if (ret)
-			return -EFAULT;
-		break;
-
-	case _IOC_NR(RTE_DOM0_IOCTL_GET_MEMSEG_INFO):
-		ret = copy_to_user((void *)ioctl_param,
-				&mm_data->seg_info[0],
-				sizeof(struct memseg_info) *
-				mm_data->num_memseg);
-		if (ret)
-			return -EFAULT;
-		break;
-	default:
-		XEN_PRINT("IOCTL default \n");
-		break;
-	}
-
-	return 0;
-}
-
-module_init(dom0_init);
-module_exit(dom0_exit);
-
-module_param(rsv_memsize, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rsv_memsize, "Xen-dom0 reserved memory size(MB).\n");
diff --git a/pkg/dpdk.spec b/pkg/dpdk.spec
index 95c3335..fd1b5ef 100644
--- a/pkg/dpdk.spec
+++ b/pkg/dpdk.spec
@@ -52,9 +52,6 @@ ExclusiveArch: i686 x86_64 aarch64
 %endif
 
 BuildRequires: kernel-devel, kernel-headers, libpcap-devel
-%ifarch i686 x86_64
-BuildRequires: xen-devel
-%endif
 BuildRequires: doxygen, python-sphinx, inkscape
 BuildRequires: texlive-collection-latexextra
 
-- 
2.7.4

^ permalink raw reply	[relevance 1%]

* Re: [dpdk-dev] [PATCH v3 1/4] ethdev: increase port_id range
  2017-09-13  2:26  0%       ` Yang, Zhiyong
@ 2017-09-14 12:49  4%         ` Ferruh Yigit
  2017-09-15  5:11  0%           ` Yang, Zhiyong
  0 siblings, 1 reply; 200+ results
From: Ferruh Yigit @ 2017-09-14 12:49 UTC (permalink / raw)
  To: Yang, Zhiyong, dev, Doherty, Declan, Lu, Wenzhuo
  Cc: thomas, hemant.agrawal, Hunt, David, Richardson, Bruce, Ananyev,
	Konstantin

On 9/13/2017 3:26 AM, Yang, Zhiyong wrote:
> Hi Ferruh,
> 
>> -----Original Message-----
>> From: Yigit, Ferruh
>> Sent: Monday, September 11, 2017 6:22 PM
>> To: Yang, Zhiyong <zhiyong.yang@intel.com>; dev@dpdk.org; Doherty, Declan
>> <declan.doherty@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>
>> Cc: thomas@monjalon.net; hemant.agrawal@nxp.com; Hunt, David
>> <david.hunt@intel.com>
>> Subject: Re: [PATCH v3 1/4] ethdev: increase port_id range
>>
>> On 9/9/2017 3:47 PM, Zhiyong Yang wrote:
>>> Extend port_id definition from uint8_t to uint16_t in lib and drivers
>>> data structures, specifically rte_eth_dev_data.
>>> Modify the APIs, drivers and app using port_id at the same time.
>>>
>>> Fix some checkpatch issues from the original code and remove some
>>> unnecessary cast operations.
>>>
>>> Signed-off-by: Zhiyong Yang <zhiyong.yang@intel.com>
>>

<...>

>>> @@ -1536,17 +1536,12 @@ rte_eth_bond_8023ad_setup_v1708(uint8_t
>> port_id,
>>>  	return 0;
>>>  }
>>>  BIND_DEFAULT_SYMBOL(rte_eth_bond_8023ad_setup, _v1708, 17.08);
>>> -MAP_STATIC_SYMBOL(int rte_eth_bond_8023ad_setup(uint8_t port_id,
>>> +MAP_STATIC_SYMBOL(int rte_eth_bond_8023ad_setup(uint16_t port_id,
>>
>> Hmm, this is tricky!
>> The macro MAP_STATIC_SYMBOL is used for ABI versioning, but changing the
>> port_id storage type breaks the ABI already. ABI versioning can be removed
>> completely. Cc'ed Declan.
>>
> Do you mean that I should remove 
>>> -MAP_STATIC_SYMBOL(int rte_eth_bond_8023ad_setup(uint8_t port_id, ?
> 
>> Which also reminds me that bonding LIBABIVER needs to be updated. This is also
>> required for all i40e, ixgbe and bnxt. Please let me know if you need help here.
>>
> Yes. I'm not clear about it. Need help Ferruh.

There are two bonding APIs [1] using ABI versioning [2], and both have
port_id as parameter. Since we are already breaking ABI, no need to keep
older versions of APIs.

So what needs to be done is, in .c file, remove those APIs and
versioning macros [3], rename latest version of API [6] and update .map
file [4] to remove exposed ABIs [5] from _older_ versions, only keep
latest ones.

I believe ideally these updates should be in this patch, but this patch
is big and no need to make it more confusing, I would suggest making
these changes _before_ this patch, so get rid of unnecessary update in
this patch.


[1]
rte_eth_bond_8023ad_conf_get_v20()
rte_eth_bond_8023ad_conf_get_v1607()
rte_eth_bond_8023ad_setup_v20()
rte_eth_bond_8023ad_setup_v1607()

[2]
http://dpdk.org/doc/guides/contributing/versioning.html

[3]
VERSION_SYMBOL, MAP_STATIC_SYMBOL, BIND_DEFAULT_SYMBOL

[4]
rte_eth_bond_version.map

[5]
rte_eth_bond_8023ad_setup
rte_eth_bond_8023ad_conf_get

[6]
rte_eth_bond_8023ad_conf_get_v1708 -->
	rte_eth_bond_8023ad_conf_get
rte_eth_bond_8023ad_setup_v1708 --->
	rte_eth_bond_8023ad_setup

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v3 3/4] examples: increase port_id range
  @ 2017-09-14 14:41  3%     ` Ferruh Yigit
  0 siblings, 0 replies; 200+ results
From: Ferruh Yigit @ 2017-09-14 14:41 UTC (permalink / raw)
  To: Zhiyong Yang, dev; +Cc: thomas, hemant.agrawal, david.hunt

On 9/9/2017 3:47 PM, Zhiyong Yang wrote:
> Modify port_id related code in examples accordingly since port_id
> definition in lib and pmd changes.
>
> Fix some original checkpatch issues and remove some unnecessary
> cast at the same time.
>
> Signed-off-by: Zhiyong Yang <zhiyong.yang@intel.com>
> ---

<...>

>
> diff --git a/doc/guides/rel_notes/release_17_11.rst
b/doc/guides/rel_notes/release_17_11.rst
> index 170f4f916..98fd7cb23 100644
> --- a/doc/guides/rel_notes/release_17_11.rst
> +++ b/doc/guides/rel_notes/release_17_11.rst
> @@ -41,6 +41,10 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =========================================================
>
> +* **Extended port_id range from uint8_t to uint16_t.**
> +
> +  Extended port_id range from 8 bits to 16 bits in order to support
more than
> +  256 ports in dpdk.
>
>  Resolved Issues
>  ---------------
There was a LIBABIVER update comment in patch 1/4, let me continue it here.

First lets extract documentation on its own patch, instead of being part
of "examples" update.

And update it a little more:

1- Remove deprecation notice.
Each patch implements a deprecation notice also should remove the
notice. rel_notes/deprecation.rst should be updated to remove port_id
related paragraph.


2- LIBABIVER values of increased libraries should be increased.

LIBABIVER is defined in each library Makefile, and set to the value of
current version of the library.

The libraries breaking ABI/API should increase this by one.

So for this patch, following libraries should be updated:
drivers/net/bnxt
drivers/net/bonding
drivers/net/i40e
drivers/net/ixgbe
lib/librte_ether
lib/librte_bitratestats
lib/librte_pdump

Please double check the list the libraries in case I missed.

And it seems we are breaking more API than initially intended. Should we
highlight this more?


3- Document updated library versions in release notes
in release notes, there is a "Shared Library Versions" section. This
section lists all libraries with their versions, like:

"   librte_ethdev.so.7" [1]

This should be updates as:

"   librte_ethdev.so.8"


[1]
It seems I have selected wrong sample :(, there is a mismatch in
Makefile LIBABIVER value and release notes version for librte_ethdev, I
will send a patch for it.

<...>

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v4 0/4] eventdev: add attribute based get APIs
  2017-09-08 15:36  4%   ` [dpdk-dev] [PATCH v3 0/4] eventdev: add attribute based get APIs Harry van Haaren
  2017-09-08 15:36  3%     ` [dpdk-dev] [PATCH v3 4/4] eventdev: add device started attribute Harry van Haaren
  2017-09-11 16:16  0%     ` [dpdk-dev] [PATCH v3 0/4] eventdev: add attribute based get APIs Jerin Jacob
@ 2017-09-14 16:08  4%     ` Harry van Haaren
  2017-09-14 16:09  3%       ` [dpdk-dev] [PATCH v4 4/4] eventdev: add device started attribute Harry van Haaren
                         ` (2 more replies)
  2 siblings, 3 replies; 200+ results
From: Harry van Haaren @ 2017-09-14 16:08 UTC (permalink / raw)
  To: dev; +Cc: jerin.jacob, Harry van Haaren

This patchset refactors the eventdev API to be more flexible
and capable. In particular, the API is capable of returning an
error value if an invalid device, port or attribute ID is passed
in, which was not possible with the previous APIs.

The implementation of this patchset is based on a v1 patch[1],
and after some discussion this API was seen as the best solution.

In terms of flexibility, the attribute id allows addition of new
common eventdev layer attributes without breaking ABI or adding
new functions. Note that these attributes are not data-path, and
that PMDs should continue to use the xstats API for reporting any
unique PMD statistics that are available.

Regarding API/ABI compatibility, I have removed the functions from
the .map files - please review the .map file changes for ABI issues
carefully.

The last patch of this series adds a started attribute to the device,
allowing the application to query if a device is currently running.

-Harry

[1] http://dpdk.org/dev/patchwork/patch/27152/

---

v4:
- Rework based on review by Jerin
  - default: cases into switches
  - Remove old functions from .map file
  - Remove /* out */ parameters
  - Rework header file definitions to match logical order
- Rework patch split
  - Cleaner removal of queue_count() function

v3:
- Fix checkpatch issues... somehow I broke my checkpatch script :/

v2:
- New APIs design based on discussion of initial patch.



Harry van Haaren (4):
  eventdev: add port attribute function
  eventdev: add dev attribute get function
  eventdev: add queue attribute function
  eventdev: add device started attribute

 lib/librte_eventdev/rte_eventdev.c           |  97 ++++++++++++------
 lib/librte_eventdev/rte_eventdev.h           | 115 +++++++++++----------
 lib/librte_eventdev/rte_eventdev_version.map |  14 ++-
 test/test/test_eventdev.c                    | 132 +++++++++++++++++++------
 test/test/test_eventdev_octeontx.c           | 143 ++++++++++++++++++++-------
 5 files changed, 345 insertions(+), 156 deletions(-)

-- 
2.7.4

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v4 4/4] eventdev: add device started attribute
  2017-09-14 16:08  4%     ` [dpdk-dev] [PATCH v4 " Harry van Haaren
@ 2017-09-14 16:09  3%       ` Harry van Haaren
  2017-09-15  6:14  0%       ` [dpdk-dev] [PATCH v4 0/4] eventdev: add attribute based get APIs Nipun Gupta
  2017-09-15 12:33  0%       ` Jerin Jacob
  2 siblings, 0 replies; 200+ results
From: Harry van Haaren @ 2017-09-14 16:09 UTC (permalink / raw)
  To: dev; +Cc: jerin.jacob, Harry van Haaren

This commit adds an attribute to the eventdev, allowing applications
to retrieve if the eventdev is running or stopped. Note that no API
or ABI changes were required in adding the statistic, and code changes
are minimal.

Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
Acked-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
---
 lib/librte_eventdev/rte_eventdev.c | 3 +++
 lib/librte_eventdev/rte_eventdev.h | 4 ++++
 2 files changed, 7 insertions(+)

diff --git a/lib/librte_eventdev/rte_eventdev.c b/lib/librte_eventdev/rte_eventdev.c
index 73e1df0..480b26e 100644
--- a/lib/librte_eventdev/rte_eventdev.c
+++ b/lib/librte_eventdev/rte_eventdev.c
@@ -740,6 +740,9 @@ rte_event_dev_attr_get(uint8_t dev_id, uint32_t attr_id,
 	case RTE_EVENT_DEV_ATTR_QUEUE_COUNT:
 		*attr_value = dev->data->nb_queues;
 		break;
+	case RTE_EVENT_DEV_ATTR_STARTED:
+		*attr_value = dev->data->dev_started;
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/lib/librte_eventdev/rte_eventdev.h b/lib/librte_eventdev/rte_eventdev.h
index 3fd447a..1b629fc 100644
--- a/lib/librte_eventdev/rte_eventdev.h
+++ b/lib/librte_eventdev/rte_eventdev.h
@@ -407,6 +407,10 @@ rte_event_dev_info_get(uint8_t dev_id, struct rte_event_dev_info *dev_info);
  * The count of queues.
  */
 #define RTE_EVENT_DEV_ATTR_QUEUE_COUNT 1
+/**
+ * The status of the device, zero for stopped, non-zero for started.
+ */
+#define RTE_EVENT_DEV_ATTR_STARTED 2
 
 /**
  * Get an attribute from a device.
-- 
2.7.4

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v3 1/4] ethdev: increase port_id range
  2017-09-14 12:49  4%         ` Ferruh Yigit
@ 2017-09-15  5:11  0%           ` Yang, Zhiyong
  0 siblings, 0 replies; 200+ results
From: Yang, Zhiyong @ 2017-09-15  5:11 UTC (permalink / raw)
  To: Yigit, Ferruh, dev, Doherty, Declan, Lu, Wenzhuo
  Cc: thomas, hemant.agrawal, Hunt, David, Richardson, Bruce, Ananyev,
	Konstantin

Hi Ferruh:

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Thursday, September 14, 2017 8:50 PM
> To: Yang, Zhiyong <zhiyong.yang@intel.com>; dev@dpdk.org; Doherty, Declan
> <declan.doherty@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>
> Cc: thomas@monjalon.net; hemant.agrawal@nxp.com; Hunt, David
> <david.hunt@intel.com>; Richardson, Bruce <bruce.richardson@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Subject: Re: [PATCH v3 1/4] ethdev: increase port_id range
> 

> >>>  }
> >>>  BIND_DEFAULT_SYMBOL(rte_eth_bond_8023ad_setup, _v1708, 17.08);
> >>> -MAP_STATIC_SYMBOL(int rte_eth_bond_8023ad_setup(uint8_t port_id,
> >>> +MAP_STATIC_SYMBOL(int rte_eth_bond_8023ad_setup(uint16_t port_id,
> >>
> >> Hmm, this is tricky!
> >> The macro MAP_STATIC_SYMBOL is used for ABI versioning, but changing
> >> the port_id storage type breaks the ABI already. ABI versioning can
> >> be removed completely. Cc'ed Declan.
> >>
> > Do you mean that I should remove
> >>> -MAP_STATIC_SYMBOL(int rte_eth_bond_8023ad_setup(uint8_t port_id, ?
> >
> >> Which also reminds me that bonding LIBABIVER needs to be updated.
> >> This is also required for all i40e, ixgbe and bnxt. Please let me know if you
> need help here.
> >>
> > Yes. I'm not clear about it. Need help Ferruh.
> 
> There are two bonding APIs [1] using ABI versioning [2], and both have port_id
> as parameter. Since we are already breaking ABI, no need to keep older versions
> of APIs.
> 
> So what needs to be done is, in .c file, remove those APIs and versioning macros
> [3], rename latest version of API [6] and update .map file [4] to remove exposed
> ABIs [5] from _older_ versions, only keep latest ones.
> 
> I believe ideally these updates should be in this patch, but this patch is big and no
> need to make it more confusing, I would suggest making these changes
> _before_ this patch, so get rid of unnecessary update in this patch.
> 
> 
> [1]
> rte_eth_bond_8023ad_conf_get_v20()
> rte_eth_bond_8023ad_conf_get_v1607()
> rte_eth_bond_8023ad_setup_v20()
> rte_eth_bond_8023ad_setup_v1607()
> 
> [2]
> http://dpdk.org/doc/guides/contributing/versioning.html
> 
> [3]
> VERSION_SYMBOL, MAP_STATIC_SYMBOL, BIND_DEFAULT_SYMBOL
> 
> [4]
> rte_eth_bond_version.map
> 
> [5]
> rte_eth_bond_8023ad_setup
> rte_eth_bond_8023ad_conf_get
> 
> [6]
> rte_eth_bond_8023ad_conf_get_v1708 -->
> 	rte_eth_bond_8023ad_conf_get
> rte_eth_bond_8023ad_setup_v1708 --->
> 	rte_eth_bond_8023ad_setup
> 

Thanks so much for detailed guide. If no objection, I will do it as you say.
Add it as the first patch in the patchset next version. I will send it out  very soon.

Zhiyong 

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 0/4] eventdev: add attribute based get APIs
  2017-09-14 16:08  4%     ` [dpdk-dev] [PATCH v4 " Harry van Haaren
  2017-09-14 16:09  3%       ` [dpdk-dev] [PATCH v4 4/4] eventdev: add device started attribute Harry van Haaren
@ 2017-09-15  6:14  0%       ` Nipun Gupta
  2017-09-15 12:33  0%       ` Jerin Jacob
  2 siblings, 0 replies; 200+ results
From: Nipun Gupta @ 2017-09-15  6:14 UTC (permalink / raw)
  To: Harry van Haaren, dev; +Cc: jerin.jacob



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Harry van Haaren
> Sent: Thursday, September 14, 2017 21:39
> To: dev@dpdk.org
> Cc: jerin.jacob@caviumnetworks.com; Harry van Haaren
> <harry.van.haaren@intel.com>
> Subject: [dpdk-dev] [PATCH v4 0/4] eventdev: add attribute based get APIs
> 
> This patchset refactors the eventdev API to be more flexible
> and capable. In particular, the API is capable of returning an
> error value if an invalid device, port or attribute ID is passed
> in, which was not possible with the previous APIs.
> 
> The implementation of this patchset is based on a v1 patch[1],
> and after some discussion this API was seen as the best solution.
> 
> In terms of flexibility, the attribute id allows addition of new
> common eventdev layer attributes without breaking ABI or adding
> new functions. Note that these attributes are not data-path, and
> that PMDs should continue to use the xstats API for reporting any
> unique PMD statistics that are available.
> 
> Regarding API/ABI compatibility, I have removed the functions from
> the .map files - please review the .map file changes for ABI issues
> carefully.
> 
> The last patch of this series adds a started attribute to the device,
> allowing the application to query if a device is currently running.
> 
> -Harry
> 
> [1] http://dpdk.org/dev/patchwork/patch/27152/
> 
> ---
> 
> v4:
> - Rework based on review by Jerin
>   - default: cases into switches
>   - Remove old functions from .map file
>   - Remove /* out */ parameters
>   - Rework header file definitions to match logical order
> - Rework patch split
>   - Cleaner removal of queue_count() function
> 
> v3:
> - Fix checkpatch issues... somehow I broke my checkpatch script :/
> 
> v2:
> - New APIs design based on discussion of initial patch.
> 
> 
> 
> Harry van Haaren (4):
>   eventdev: add port attribute function
>   eventdev: add dev attribute get function
>   eventdev: add queue attribute function
>   eventdev: add device started attribute
> 
>  lib/librte_eventdev/rte_eventdev.c           |  97 ++++++++++++------
>  lib/librte_eventdev/rte_eventdev.h           | 115 +++++++++++----------
>  lib/librte_eventdev/rte_eventdev_version.map |  14 ++-
>  test/test/test_eventdev.c                    | 132 +++++++++++++++++++------
>  test/test/test_eventdev_octeontx.c           | 143 ++++++++++++++++++++-------
>  5 files changed, 345 insertions(+), 156 deletions(-)
> 
> --
> 2.7.4

Changes look good.
Series Acked-by: Nipun Gupta <Nipun.gupta@nxp.com>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 0/4] eventdev: add attribute based get APIs
  2017-09-14 16:08  4%     ` [dpdk-dev] [PATCH v4 " Harry van Haaren
  2017-09-14 16:09  3%       ` [dpdk-dev] [PATCH v4 4/4] eventdev: add device started attribute Harry van Haaren
  2017-09-15  6:14  0%       ` [dpdk-dev] [PATCH v4 0/4] eventdev: add attribute based get APIs Nipun Gupta
@ 2017-09-15 12:33  0%       ` Jerin Jacob
  2 siblings, 0 replies; 200+ results
From: Jerin Jacob @ 2017-09-15 12:33 UTC (permalink / raw)
  To: Harry van Haaren; +Cc: dev

-----Original Message-----
> Date: Thu, 14 Sep 2017 17:08:59 +0100
> From: Harry van Haaren <harry.van.haaren@intel.com>
> To: dev@dpdk.org
> CC: jerin.jacob@caviumnetworks.com, Harry van Haaren
>  <harry.van.haaren@intel.com>
> Subject: [PATCH v4 0/4] eventdev: add attribute based get APIs
> X-Mailer: git-send-email 2.7.4
> 
> This patchset refactors the eventdev API to be more flexible
> and capable. In particular, the API is capable of returning an
> error value if an invalid device, port or attribute ID is passed
> in, which was not possible with the previous APIs.
> 
> The implementation of this patchset is based on a v1 patch[1],
> and after some discussion this API was seen as the best solution.
> 
> In terms of flexibility, the attribute id allows addition of new
> common eventdev layer attributes without breaking ABI or adding
> new functions. Note that these attributes are not data-path, and
> that PMDs should continue to use the xstats API for reporting any
> unique PMD statistics that are available.
> 
> Regarding API/ABI compatibility, I have removed the functions from
> the .map files - please review the .map file changes for ABI issues
> carefully.
> 
> The last patch of this series adds a started attribute to the device,
> allowing the application to query if a device is currently running.
> 
> -Harry
> 
> [1] http://dpdk.org/dev/patchwork/patch/27152/
> 
> ---
> 
> v4:
> - Rework based on review by Jerin
>   - default: cases into switches
>   - Remove old functions from .map file
>   - Remove /* out */ parameters
>   - Rework header file definitions to match logical order
> - Rework patch split
>   - Cleaner removal of queue_count() function

The changes looks good.

Since the functions are removed, we need to update .so version.
Please update LIBABIVER(file: lib/librte_eventdev/Makefile) and  update
the release notes

reference to the similar change:
http://dpdk.org/browse/dpdk/commit/?id=945081a76ab0bb481f1d62125aa5b547fcc000bd

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH] doc: add note on hardware support deprecation
@ 2017-09-15 13:41 21% Bruce Richardson
  0 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2017-09-15 13:41 UTC (permalink / raw)
  To: dev; +Cc: Bruce Richardson

Following agreement at the DPDK Technical Board meeting [1], the policy
that hardware support deprecation should be treated as though it were an
ABI break needs to be documented in the contributors guide.

[1] http://dpdk.org/ml/archives/dev/2017-September/074613.html

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 doc/guides/contributing/versioning.rst | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/doc/guides/contributing/versioning.rst b/doc/guides/contributing/versioning.rst
index 8aaf370da..2ec561647 100644
--- a/doc/guides/contributing/versioning.rst
+++ b/doc/guides/contributing/versioning.rst
@@ -18,6 +18,8 @@ General Guidelines
 #. The modification of symbols can generally be managed with versioning
 #. The removal of symbols generally is an ABI break and requires bumping of the
    LIBABIVER macro
+#. Updates to the minimum HW requirements, which drop support for hardware which
+   was previously supported, should be treated as an ABI change.
 
 What is an ABI
 --------------
@@ -77,6 +79,13 @@ for significant reasons, such as performance enhancements. ABI breakage due to
 changes such as reorganizing public structure fields for aesthetic or
 readability purposes should be avoided.
 
+.. note::
+
+        Updates to the minimum HW requirements, which drop support for hardware
+        which was previously supported, should be treated as an ABI change, and
+        follow the relevant deprecation policy procedures as above: 3 acks and
+        announcement at least one release in advance.
+
 Examples of Deprecation Notices
 -------------------------------
 
-- 
2.13.5

^ permalink raw reply	[relevance 21%]

* [dpdk-dev] [PATCH v4 0/3] ethdev new offloads API
  2017-09-13  6:37  4%   ` [dpdk-dev] [PATCH v3 " Shahaf Shuler
  2017-09-13  9:10  0%     ` Andrew Rybchenko
@ 2017-09-17  6:54  4%     ` Shahaf Shuler
  2017-09-18  7:51  0%       ` Andrew Rybchenko
  1 sibling, 1 reply; 200+ results
From: Shahaf Shuler @ 2017-09-17  6:54 UTC (permalink / raw)
  To: thomas, jerin.jacob, konstantin.ananyev, arybchenko; +Cc: dev

Tx offloads configuration is per queue. Tx offloads are enabled by default, 
and can be disabled using ETH_TXQ_FLAGS_NO* flags. 
This behaviour is not consistent with the Rx side where the Rx offloads
configuration is per port. Rx offloads are disabled by default and enabled 
according to bit field in rte_eth_rxmode structure.

Moreover, considering more Tx and Rx offloads will be added 
over time, the cost of managing them all inside the PMD will be tremendous,
as the PMD will need to check the matching for the entire offload set 
for each mbuf it handles.
In addition, on the current approach each Rx offload added breaks the
ABI compatibility as it requires to add entries to existing bit-fields.
 
The series address above issues by defining a new offloads API.
In the new API, offloads are divided into per-port and per-queue offloads,
with a corresponding capability for each.
The offloads are disabled by default. Each offload can be enabled or
disabled using the existing DEV_TX_OFFLOADS_* or DEV_RX_OFFLOADS_* flags.
Such API will enable to easily add or remove offloads, without breaking the
ABI compatibility.

In order to provide a smooth transition between the APIs the following actions
were taken:
*  The old offloads API is kept for the meanwhile.
*  Helper function which copy from old to new API were added to ethdev,
   enabling the PMD to support only one of the APIs.

Per discussion made on the RFC of this series [1], the integration plan which was
decided is to do the transition in two phases:
* ethdev API will move on 17.11.
* Apps and examples will move on 18.02.

This to enable PMD maintainers sufficient time to adopt the new API.

[1]
http://dpdk.org/ml/archives/dev/2017-August/072643.html

on v4:
 - Added another patch for documentation.
 - Fixed ETH_TXQ_FLAGS_IGNORE flag override.
 - clarify the description of DEV_TX_OFFLOAD_MBUF_FAST_FREE offload.

on v3:
 - Introduce the DEV_TX_OFFLOAD_MBUF_FAST_FREE to act as an equivalent
   for the no refcnt and single mempool flags.
 - Fix features documentation.
 - Fix comment style.

on v2:
 - Taking new approach of dividing offloads into per-queue and per-port one.
 - Postpone the Tx/Rx public struct renaming to 18.02
 - squash the helper functions into the Rx/Tx offloads intro patches.

Shahaf Shuler (3):
  ethdev: introduce Rx queue offloads API
  ethdev: introduce Tx queue offloads API
  doc: add details on ethdev offloads API

 doc/guides/nics/features.rst            |  66 +++++---
 doc/guides/prog_guide/poll_mode_drv.rst |  17 ++
 lib/librte_ether/rte_ethdev.c           | 223 +++++++++++++++++++++++++--
 lib/librte_ether/rte_ethdev.h           |  89 ++++++++++-
 4 files changed, 355 insertions(+), 40 deletions(-)

-- 
2.12.0

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v4 0/3] ethdev new offloads API
  2017-09-17  6:54  4%     ` [dpdk-dev] [PATCH v4 0/3] " Shahaf Shuler
@ 2017-09-18  7:51  0%       ` Andrew Rybchenko
  0 siblings, 0 replies; 200+ results
From: Andrew Rybchenko @ 2017-09-18  7:51 UTC (permalink / raw)
  To: Shahaf Shuler, thomas, jerin.jacob, konstantin.ananyev; +Cc: dev

On 09/17/2017 09:54 AM, Shahaf Shuler wrote:
> Tx offloads configuration is per queue. Tx offloads are enabled by default,
> and can be disabled using ETH_TXQ_FLAGS_NO* flags.
> This behaviour is not consistent with the Rx side where the Rx offloads
> configuration is per port. Rx offloads are disabled by default and enabled
> according to bit field in rte_eth_rxmode structure.
>
> Moreover, considering more Tx and Rx offloads will be added
> over time, the cost of managing them all inside the PMD will be tremendous,
> as the PMD will need to check the matching for the entire offload set
> for each mbuf it handles.
> In addition, on the current approach each Rx offload added breaks the
> ABI compatibility as it requires to add entries to existing bit-fields.
>   
> The series address above issues by defining a new offloads API.
> In the new API, offloads are divided into per-port and per-queue offloads,
> with a corresponding capability for each.
> The offloads are disabled by default. Each offload can be enabled or
> disabled using the existing DEV_TX_OFFLOADS_* or DEV_RX_OFFLOADS_* flags.
> Such API will enable to easily add or remove offloads, without breaking the
> ABI compatibility.
>
> In order to provide a smooth transition between the APIs the following actions
> were taken:
> *  The old offloads API is kept for the meanwhile.
> *  Helper function which copy from old to new API were added to ethdev,
>     enabling the PMD to support only one of the APIs.

As I understand there is an API to copy from a new to old API as well, 
allowing
applications to use the new API and work fine with PMD which supports an 
old API only.

> Per discussion made on the RFC of this series [1], the integration plan which was
> decided is to do the transition in two phases:
> * ethdev API will move on 17.11.
> * Apps and examples will move on 18.02.
>
> This to enable PMD maintainers sufficient time to adopt the new API.
>
> [1]
> http://dpdk.org/ml/archives/dev/2017-August/072643.html
>
> on v4:
>   - Added another patch for documentation.
>   - Fixed ETH_TXQ_FLAGS_IGNORE flag override.
>   - clarify the description of DEV_TX_OFFLOAD_MBUF_FAST_FREE offload.
>
> on v3:
>   - Introduce the DEV_TX_OFFLOAD_MBUF_FAST_FREE to act as an equivalent
>     for the no refcnt and single mempool flags.
>   - Fix features documentation.
>   - Fix comment style.
>
> on v2:
>   - Taking new approach of dividing offloads into per-queue and per-port one.
>   - Postpone the Tx/Rx public struct renaming to 18.02
>   - squash the helper functions into the Rx/Tx offloads intro patches.
>
> Shahaf Shuler (3):
>    ethdev: introduce Rx queue offloads API
>    ethdev: introduce Tx queue offloads API
>    doc: add details on ethdev offloads API
>
>   doc/guides/nics/features.rst            |  66 +++++---
>   doc/guides/prog_guide/poll_mode_drv.rst |  17 ++
>   lib/librte_ether/rte_ethdev.c           | 223 +++++++++++++++++++++++++--
>   lib/librte_ether/rte_ethdev.h           |  89 ++++++++++-
>   4 files changed, 355 insertions(+), 40 deletions(-)

Series-reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] doc: announce ABI change for ring structure
  2017-09-11 13:39  4% [dpdk-dev] [PATCH] doc: announce ABI change for ring structure Olivier Matz
@ 2017-09-18  9:16  4% ` Bruce Richardson
  2017-09-18  9:24  4% ` Mcnamara, John
  2017-09-18  9:30  4% ` Burakov, Anatoly
  2 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2017-09-18  9:16 UTC (permalink / raw)
  To: Olivier Matz; +Cc: dev, john.mcnamara, daniel.verkamp, konstantin.ananyev

On Mon, Sep 11, 2017 at 03:39:13PM +0200, Olivier Matz wrote:
> As discussed on the mailing list, the alignment constraint of
> the ring structure can be relaxed.
> 
> Link: http://dpdk.org/dev/patchwork/patch/25039
> Link: http://dpdk.org/dev/patchwork/patch/26103
> 
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> ---
Acked-by: Bruce Richardson <bruce.richardson@intel.com>

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH] doc: announce ABI change for ring structure
  2017-09-11 13:39  4% [dpdk-dev] [PATCH] doc: announce ABI change for ring structure Olivier Matz
  2017-09-18  9:16  4% ` Bruce Richardson
@ 2017-09-18  9:24  4% ` Mcnamara, John
  2017-09-18  9:30  4% ` Burakov, Anatoly
  2 siblings, 0 replies; 200+ results
From: Mcnamara, John @ 2017-09-18  9:24 UTC (permalink / raw)
  To: Olivier Matz, dev; +Cc: Richardson, Bruce, Verkamp, Daniel, Ananyev, Konstantin



> -----Original Message-----
> From: Olivier Matz [mailto:olivier.matz@6wind.com]
> Sent: Monday, September 11, 2017 2:39 PM
> To: dev@dpdk.org
> Cc: Richardson, Bruce <bruce.richardson@intel.com>; Mcnamara, John
> <john.mcnamara@intel.com>; Verkamp, Daniel <daniel.verkamp@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Subject: [PATCH] doc: announce ABI change for ring structure
> 
> As discussed on the mailing list, the alignment constraint of the ring
> structure can be relaxed.
> 
> Link: http://dpdk.org/dev/patchwork/patch/25039
> Link: http://dpdk.org/dev/patchwork/patch/26103
> 
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>

Acked-by: John McNamara <john.mcnamara@intel.com>

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH] doc: announce ABI change for ring structure
  2017-09-11 13:39  4% [dpdk-dev] [PATCH] doc: announce ABI change for ring structure Olivier Matz
  2017-09-18  9:16  4% ` Bruce Richardson
  2017-09-18  9:24  4% ` Mcnamara, John
@ 2017-09-18  9:30  4% ` Burakov, Anatoly
  2 siblings, 0 replies; 200+ results
From: Burakov, Anatoly @ 2017-09-18  9:30 UTC (permalink / raw)
  To: Olivier Matz, dev
  Cc: Richardson, Bruce, Mcnamara, John, Verkamp, Daniel, Ananyev, Konstantin

> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Olivier Matz
> Sent: Monday, September 11, 2017 2:39 PM
> To: dev@dpdk.org
> Cc: Richardson, Bruce <bruce.richardson@intel.com>; Mcnamara, John
> <john.mcnamara@intel.com>; Verkamp, Daniel
> <daniel.verkamp@intel.com>; Ananyev, Konstantin
> <konstantin.ananyev@intel.com>
> Subject: [dpdk-dev] [PATCH] doc: announce ABI change for ring structure
> 
> As discussed on the mailing list, the alignment constraint of the ring structure
> can be relaxed.
> 
> Link: http://dpdk.org/dev/patchwork/patch/25039
> Link: http://dpdk.org/dev/patchwork/patch/26103
> 
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>

Acked-by: Anatoly Burakov <anatoly.burakov@intel.com>

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v2 14/14] doc: add notes on EAL PCI API update
  @ 2017-09-18  9:31  4%   ` Gaetan Rivet
  0 siblings, 0 replies; 200+ results
From: Gaetan Rivet @ 2017-09-18  9:31 UTC (permalink / raw)
  To: dev; +Cc: Gaetan Rivet

Add a section related to EAL API changes to 17.11 release notes.

Signed-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 doc/guides/rel_notes/release_17_11.rst | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/doc/guides/rel_notes/release_17_11.rst b/doc/guides/rel_notes/release_17_11.rst
index 8bf91bd..d5546ba 100644
--- a/doc/guides/rel_notes/release_17_11.rst
+++ b/doc/guides/rel_notes/release_17_11.rst
@@ -130,6 +130,34 @@ API Changes
   * Rework start and stop APIs into ``rte_service_runstate_set``
   * Added API to set runstate of service implementation to indicate readyness
 
+* **PCI bus API moved outside of the EAL**
+
+  The PCI bus previously implemented within the EAL has been moved.
+  A first part has been added as an RTE library providing PCI helpers to
+  parse device locations or other such utilities.
+  A second part consisting in the actual bus driver has been moved to its
+  proper subdirectory, without changing its functionalities.
+
+  As such, several PCI-related functions are not proposed by the EAL anymore:
+
+  * rte_pci_detach
+  * rte_pci_dump
+  * rte_pci_ioport_map
+  * rte_pci_ioport_read
+  * rte_pci_ioport_unmap
+  * rte_pci_ioport_write
+  * rte_pci_map_device
+  * rte_pci_probe
+  * rte_pci_probe_one
+  * rte_pci_read_config
+  * rte_pci_register
+  * rte_pci_scan
+  * rte_pci_unmap_device
+  * rte_pci_unregister
+  * rte_pci_write_config
+
+  These functions are made available either as part of ``librte_pci`` or
+  ``librte_bus_pci``.
 
 ABI Changes
 -----------
-- 
2.1.4

^ permalink raw reply	[relevance 4%]

Results 3201-3400 of ~18000   |  | reverse | sort options + mbox downloads above
-- links below jump to the message on this page --
2017-05-30 16:44     [dpdk-dev] [RFC 2/3] ethdev: add new rte_mtr API for traffic metering and policing Cristian Dumitrescu
2017-08-26  0:06     ` [dpdk-dev] [PATCH 0/3] rte_mtr: generic ethdev API for " Cristian Dumitrescu
2017-08-26  0:06  2%   ` [dpdk-dev] [PATCH 2/3] ethdev: add new rte_mtr API for traffic " Cristian Dumitrescu
2017-09-01  8:09  0%     ` Hemant Agrawal
2017-06-27 10:52     [dpdk-dev] [PATCH v3 1/3] eal: add functions parsing EAL arguments Jacek Piasecki
2017-07-10 12:44     ` [dpdk-dev] [PATCH v4 0/5] Rework cfgfile API to enable apps config file support Jacek Piasecki
2017-07-10 12:44       ` [dpdk-dev] [PATCH v4 2/5] cfgfile: change existing API functions Jacek Piasecki
2017-08-30 20:07  4%     ` Bruce Richardson
2017-07-09  9:28     [dpdk-dev] [PATCH 0/2] devargs changes / deprecation notice Jan Blunck
2017-07-09  9:28     ` [dpdk-dev] [PATCH 2/2] eal: deprecate 17.08 devargs API/ABI Jan Blunck
2017-08-07 23:03  4%   ` Thomas Monjalon
2017-07-11 10:01     [dpdk-dev] [PATCH] eal: add notice to make DPDK IOVA aware Jerin Jacob
2017-08-04  5:25     ` Hemant Agrawal
2017-08-06 21:22       ` Olivier MATZ
2017-08-08  0:04  0%     ` Thomas Monjalon
2017-07-11 23:24     [dpdk-dev] [PATCH 00/13] devargs fixes Jan Blunck
2017-07-14 21:11     ` [dpdk-dev] [PATCH v2 00/15] " Jan Blunck
2017-07-14 21:12       ` [dpdk-dev] [PATCH v2 04/15] devargs: deprecate enum rte_devtype based functions Jan Blunck
2017-09-04 16:06  0%     ` Ferruh Yigit
2017-07-13  9:12     [dpdk-dev] [PATCH] mempool: add notice to change mempool API/ABI Santosh Shukla
2017-08-03 14:21     ` [dpdk-dev] [PATCH v2] doc: announce API/ABI changes for mempool Jerin Jacob
2017-08-05 20:24       ` Olivier MATZ
2017-08-08  0:10  4%     ` Thomas Monjalon
2017-07-20  7:06     [dpdk-dev] [PATCH v2 1/2] eal: allow user to override default pool handle Santosh Shukla
2017-08-15  8:07     ` [dpdk-dev] [PATCH v3 0/2] Dynamically configure mempool handle Santosh Shukla
2017-08-15  8:07       ` [dpdk-dev] [PATCH v3 2/2] ethdev: allow pmd to advertise pool handle Santosh Shukla
2017-09-04 12:11  3%     ` Olivier MATZ
2017-09-04 13:14  0%       ` santosh
2017-09-07  9:21  0%         ` Hemant Agrawal
2017-09-07 10:06  0%           ` santosh
2017-09-07 10:11  0%             ` santosh
2017-09-07 11:08  0%               ` Hemant Agrawal
2017-09-04  9:41       ` [dpdk-dev] [PATCH v3 0/2] Dynamically configure mempool handle Sergio Gonzalez Monroy
2017-09-04 13:34  4%     ` Olivier MATZ
2017-09-04 14:24  0%       ` Sergio Gonzalez Monroy
2017-09-05  7:47  0%         ` Olivier MATZ
2017-09-05  8:11  0%           ` Jerin Jacob
2017-07-20 13:47     [dpdk-dev] [PATCH v3 0/6] Infrastructure to support octeontx HW mempool manager Santosh Shukla
2017-08-15  6:07     ` [dpdk-dev] [PATCH v4 0/7] " Santosh Shukla
2017-08-15  6:07  4%   ` [dpdk-dev] [PATCH v4 3/7] doc: remove mempool api change notice Santosh Shukla
2017-09-06 11:28       ` [dpdk-dev] [PATCH v5 0/8] Infrastructure to support octeontx HW mempool manager Santosh Shukla
2017-09-06 11:28  4%     ` [dpdk-dev] [PATCH v5 4/8] doc: remove mempool notice Santosh Shukla
2017-09-07 15:30         ` [dpdk-dev] [PATCH v6 0/8] Infrastructure to support octeontx HW mempool manager Santosh Shukla
2017-09-07 15:30  4%       ` [dpdk-dev] [PATCH v6 4/8] doc: remove mempool notice Santosh Shukla
2017-07-24 12:48     [dpdk-dev] [PATCH] eventdev: add dev id checks to config functions Harry van Haaren
2017-09-04  5:20     ` Jerin Jacob
2017-09-06 14:45  3%   ` Van Haaren, Harry
2017-09-06 14:57  0%     ` Jerin Jacob
2017-09-08 15:18  4% ` [dpdk-dev] [PATCH v2 0/3] eventdev: add attribute based get APIs Harry van Haaren
2017-09-08 15:18  3%   ` [dpdk-dev] [PATCH v2 4/4] eventdev: add device started attribute Harry van Haaren
2017-09-08 15:36  4%   ` [dpdk-dev] [PATCH v3 0/4] eventdev: add attribute based get APIs Harry van Haaren
2017-09-08 15:36  3%     ` [dpdk-dev] [PATCH v3 4/4] eventdev: add device started attribute Harry van Haaren
2017-09-11 17:52  0%       ` Jerin Jacob
2017-09-12  8:07  0%         ` Van Haaren, Harry
2017-09-11 16:16  0%     ` [dpdk-dev] [PATCH v3 0/4] eventdev: add attribute based get APIs Jerin Jacob
2017-09-14 16:08  4%     ` [dpdk-dev] [PATCH v4 " Harry van Haaren
2017-09-14 16:09  3%       ` [dpdk-dev] [PATCH v4 4/4] eventdev: add device started attribute Harry van Haaren
2017-09-15  6:14  0%       ` [dpdk-dev] [PATCH v4 0/4] eventdev: add attribute based get APIs Nipun Gupta
2017-09-15 12:33  0%       ` Jerin Jacob
2017-07-24 20:51     [dpdk-dev] [PATCH] net/i40e: new API to add VF MAC address from PF Wenzhuo Lu
2017-07-25 14:09     ` [dpdk-dev] [PATCH v2] " Wenzhuo Lu
2017-08-17 13:05  0%   ` Ferruh Yigit
2017-08-17 13:36  0%     ` Lu, Wenzhuo
2017-07-31  9:18     [dpdk-dev] [PATCH v2] cryptodev: fix NULL pointer dereference Pablo de Lara
2017-08-16  2:41  3% ` [dpdk-dev] [PATCH v3] cryptodev: allocate driver structure statically Pablo de Lara
2017-08-03 12:21     [dpdk-dev] [RFC] ethdev: add ioctl-like API to control device specific features Chilikin, Andrey
2017-08-03 13:21     ` Bruce Richardson
2017-08-03 16:15       ` Stephen Hemminger
2017-08-03 19:53         ` Thomas Monjalon
2017-08-04 11:58           ` Ferruh Yigit
2017-08-04 12:56             ` Bruce Richardson
2017-08-08  8:32  0%           ` Ferruh Yigit
2017-08-08 15:27  3%             ` Stephen Hemminger
2017-08-08 17:23  2%         ` Wiles, Keith
2017-08-08 17:28  0%         ` Wiles, Keith
2017-08-08 18:02  0%           ` Stephen Hemminger
2017-08-08 18:21  0%             ` Wiles, Keith
2017-08-03 15:32     [dpdk-dev] [PATCH] doc: announce ABI change for cryptodev and ethdev Akhil Goyal
2017-08-04  5:26     ` Hemant Agrawal
2017-08-07 17:41       ` Thomas Monjalon
2017-08-07 18:07         ` Boris Pismenny
2017-08-08  5:03  4%       ` Shahaf Shuler
2017-08-08 10:00  4%         ` Thomas Monjalon
2017-08-04 15:25     ` De Lara Guarch, Pablo
2017-08-08  6:54  7%   ` Akhil Goyal
2017-08-08  7:09  7% ` [dpdk-dev] [PATCH v2] " Akhil Goyal
2017-08-08  8:08  4%   ` De Lara Guarch, Pablo
2017-08-08  8:42  4%     ` Akhil Goyal
2017-08-04  5:27     [dpdk-dev] [PATCH v2] doc: announce API and ABI change for ethdev Zhiyong Yang
2017-08-07 12:42     ` [dpdk-dev] [PATCH v3] " Zhiyong Yang
2017-08-08  4:02  4%   ` Yang, Zhiyong
2017-08-08  9:35  4%     ` Thomas Monjalon
2017-08-04 13:29     [dpdk-dev] [PATCH] doc: announce rte_devargs changes in 17.11 Gaetan Rivet
2017-08-07 23:18  0% ` Thomas Monjalon
2017-08-07 10:54     [dpdk-dev] [RFC PATCH 0/4] ethdev new offloads API Shahaf Shuler
2017-08-07 10:54     ` [dpdk-dev] [RFC PATCH 2/4] ethdev: introduce Rx queue " Shahaf Shuler
2017-08-23 12:21  0%   ` Ananyev, Konstantin
2017-08-23 13:06  0%     ` Shahaf Shuler
2017-08-23 21:48  0%   ` Thomas Monjalon
2017-08-29 12:50  0%   ` Ferruh Yigit
2017-08-30  6:22  0%     ` Shahaf Shuler
2017-08-29 13:11  0%   ` Ferruh Yigit
2017-08-23  6:39  0% ` [dpdk-dev] [RFC PATCH 0/4] ethdev new " Shahaf Shuler
2017-08-25 10:31  0% ` Jerin Jacob
2017-08-07 17:39     [dpdk-dev] [PATCH v3] ethdev: add return code to rte_eth_stats_reset() David Harton
2017-08-08  9:02  5% ` Van Haaren, Harry
2017-08-08 11:01  0%   ` David Harton (dharton)
2017-08-08 11:03  4%   ` Christian Ehrhardt
2017-08-08 13:13  3%     ` Thomas Monjalon
2017-08-10 13:29     ` [dpdk-dev] [PATCH v4 1/2] " David Harton
2017-08-10 13:29 13%   ` [dpdk-dev] [PATCH v4 2/2] doc: Update ABI Change for rte_eth_stats_reset David Harton
2017-08-31 22:10  7%     ` Thomas Monjalon
2017-08-31 22:10  4%       ` Thomas Monjalon
2017-09-01  2:26  3%   ` [dpdk-dev] [PATCH v5] ethdev: add return code to rte_eth_stats_reset() David Harton
2017-09-01  7:47  0%     ` Hemant Agrawal
     [not found]     <20170706150751.27251-1-stephen@networkplumber.org>
2017-08-07 22:19     ` [dpdk-dev] [PATCH] ethdev: add notice for planned name size change Yongseok Koh
2017-08-08  4:56  0%   ` Shahaf Shuler
2017-08-08  9:47  0%     ` Thomas Monjalon
2017-08-08 12:31  6% [dpdk-dev] [PATCH v1] doc: add template release notes for 17.11 John McNamara
2017-08-09  8:22  6% ` [dpdk-dev] [PATCH v2] " John McNamara
2017-08-08 14:26  4% [dpdk-dev] [PATCH] eal: bump ABI version for PCI, bus and devargs work Gaetan Rivet
2017-08-08 17:26  4% ` Thomas Monjalon
2017-08-08 14:26  9% [dpdk-dev] [PATCH] doc: notify EAL ABI change Gaetan Rivet
2017-08-08 17:27  4% ` Thomas Monjalon
2017-08-08 14:48     [dpdk-dev] [PATCH 1/2] doc: fix v17.05 release note Jerin Jacob
2017-08-08 14:48  3% ` [dpdk-dev] [PATCH 2/2] eventdev: bump library version Jerin Jacob
2017-08-08 17:45  0%   ` Thomas Monjalon
2017-08-09  8:42  3% [dpdk-dev] [PATCH 0/2] increase port_id range Zhiyong Yang
2017-08-09  9:00  4% ` De Lara Guarch, Pablo
2017-08-09  9:17  0%   ` Yang, Zhiyong
2017-08-09 13:30     [dpdk-dev] [PATCH] kvargs: return error if key not find in kvlist Keith Wiles
2017-08-09 13:53     ` Ananyev, Konstantin
2017-08-09 14:35  3%   ` Wiles, Keith
2017-08-09 14:47  0%     ` Ananyev, Konstantin
2017-08-09 20:21     [dpdk-dev] Announcement of SSE requirement change in dpdk Neil Horman
2017-08-11 20:29     ` Bruce Richardson
2017-08-12 18:19  3%   ` Neil Horman
2017-08-14  9:32  3%     ` Bruce Richardson
2017-08-14 10:50  0%       ` Neil Horman
2017-08-14 10:58  0%         ` Bruce Richardson
2017-08-14 11:23  4%           ` Neil Horman
2017-08-14 15:15     [dpdk-dev] [PATCH v1 0/4] make dpdk iova aware Santosh Shukla
2017-08-14 15:15 15% ` [dpdk-dev] [PATCH v1 4/4] doc: remove dpdk iova aware notice Santosh Shukla
2017-09-05 10:31     ` [dpdk-dev] [PATCH v2 0/5] make dpdk iova aware Santosh Shukla
2017-09-05 10:31 15%   ` [dpdk-dev] [PATCH v2 5/5] doc: remove dpdk iova aware notice Santosh Shukla
2017-08-15 12:32     [dpdk-dev] [PATCH 0/8] service: rework for usability Harry van Haaren
2017-08-16 11:16  3% ` Neil Horman
2017-08-16 11:31  4%   ` Van Haaren, Harry
2017-08-16 12:07  0%     ` Van Haaren, Harry
2017-08-16 13:27  0%       ` Neil Horman
2017-08-21 12:58     ` [dpdk-dev] [PATCH v2 00/15] service: API improvements and updates Harry van Haaren
2017-08-21 12:58  4%   ` [dpdk-dev] [PATCH v2 15/15] docs: add notes on service cores API updates Harry van Haaren
2017-08-21  9:34  3% [dpdk-dev] [PATCH] vhost: added user callbacks for socket open/close Dariusz Stojaczyk
2017-08-21 15:00  0% ` Jens Freimann
2017-08-22 16:24  3% ` [dpdk-dev] [PATCH v2] " Dariusz Stojaczyk
2017-08-25  9:22  0%   ` Jens Freimann
2017-08-29  6:08  3%     ` Stojaczyk, DariuszX
2017-08-30  6:33  0%       ` Jens Freimann
2017-08-30 10:50  3%   ` [dpdk-dev] [PATCH v3] rte_vhost: " Dariusz Stojaczyk
2017-08-23  1:19     [dpdk-dev] [PATCH] ethdev: stop overriding rx_nombuf by rte_eth_stats_get David Harton
2017-08-23  2:55     ` [dpdk-dev] [PATCH v2 1/2] " David Harton
2017-08-23  7:51       ` Thomas Monjalon
2017-08-23 12:18  4%     ` David Harton (dharton)
2017-08-23 13:24  0%       ` Thomas Monjalon
2017-08-23 21:27  0%         ` David Harton (dharton)
2017-08-23 21:35  0%           ` Thomas Monjalon
2017-08-24 12:23     [dpdk-dev] [PATCH v1] net/mlx5: support upstream rdma-core Shachar Beiser
     [not found]     ` <CGME20170831161745eucas1p112753dbc96b3b209d303b007dda0408b@eucas1p1.samsung.com>
2017-08-31 16:17  3%   ` Alexey Perevalov
2017-09-04  6:30  0%     ` Shachar Beiser
2017-08-24 16:20     [dpdk-dev] [PATCH 00/16] nfp: add pf support Alejandro Lucero
2017-08-24 16:20 10% ` [dpdk-dev] [PATCH 02/16] nfp: add specific pf probe function Alejandro Lucero
2017-08-28 16:42  0%   ` Ferruh Yigit
2017-08-31  9:23  0%     ` Alejandro Lucero
2017-08-24 16:20  6% ` [dpdk-dev] [PATCH 11/16] nfp: allocate eth_dev from " Alejandro Lucero
2017-08-24 23:18  4% [dpdk-dev] [PATCH] ethdev: modifiy vlan_offload_set_t to return int David Harton
2017-08-25 13:33  4% ` [dpdk-dev] [PATCH v2] " David Harton
2017-08-25 13:47  4%   ` [dpdk-dev] [PATCH v3] " David Harton
2017-08-31 22:04  3%     ` Thomas Monjalon
2017-08-31 22:08  0%       ` Thomas Monjalon
2017-09-01  0:40  0%       ` David Harton (dharton)
2017-09-01  8:01  0%         ` Thomas Monjalon
2017-09-01  2:36  7%     ` [dpdk-dev] [PATCH v4] ethdev: allow returning error on VLAN offload configuration David Harton
2017-09-01  7:41  0%       ` Hemant Agrawal
2017-09-01 12:54  0%         ` David Harton (dharton)
2017-08-25  9:04     [dpdk-dev] [PATCH 00/13] Move PCI away from the EAL Gaetan Rivet
2017-09-18  9:31     ` [dpdk-dev] [PATCH v2 00/14] " Gaetan Rivet
2017-09-18  9:31  4%   ` [dpdk-dev] [PATCH v2 14/14] doc: add notes on EAL PCI API update Gaetan Rivet
2017-08-25  9:40     [dpdk-dev] [PATCH 00/12] support to run vdev in the secondary process Jianfeng Tan
2017-08-25  9:40     ` [dpdk-dev] [PATCH 04/12] vdev: move to drivers/bus Jianfeng Tan
2017-08-29 13:04  3%   ` Gaëtan Rivet
2017-08-29 22:47  0%     ` Tan, Jianfeng
2017-08-25 20:26     [dpdk-dev] [PATCH v2 0/3] *** timer library enhancements *** Gabriel Carrillo
2017-09-13 22:05     ` [dpdk-dev] [PATCH v3 0/3] timer library enhancement Erik Gabriel Carrillo
2017-09-13 22:05  3%   ` [dpdk-dev] [PATCH v3 3/3] doc: update timer lib docs Erik Gabriel Carrillo
2017-08-27 13:24     [dpdk-dev] [dpdk-techboard] next techboard meeting (29th, August) Jerin Jacob
2017-08-28 15:04  3% ` Bruce Richardson
2017-08-29 15:30  0%   ` Jerin Jacob
2017-08-30 13:51 27% [dpdk-dev] [PATCH] devtools: rework abi checker script Olivier Matz
2017-09-04 16:00  8% ` Bruce Richardson
2017-09-04 16:03  8%   ` Bruce Richardson
2017-09-04 16:13  7%     ` Bruce Richardson
2017-09-06 14:51 27% ` [dpdk-dev] [PATCH v2] " Olivier Matz
2017-09-08 13:46  9%   ` Neil Horman
2017-09-11  8:18  7%     ` Olivier MATZ
2017-09-11  8:46 26%       ` [dpdk-dev] [PATCH v3] " Olivier Matz
2017-09-13 15:00  9%         ` Neil Horman
2017-08-30 18:10     [dpdk-dev] [PATCH 0/6] remove xen dom0 support in DPDK Jianfeng Tan
2017-08-30 18:10  1% ` [dpdk-dev] [PATCH 5/6] eal: remove xen dom0 support Jianfeng Tan
2017-09-04 14:43  3%   ` Bruce Richardson
2017-09-04 14:49  4%     ` Bruce Richardson
2017-09-05  3:41  0%       ` Tan, Jianfeng
2017-09-05  7:31  0%         ` Thomas Monjalon
2017-09-05  8:07  0%           ` Tan, Jianfeng
2017-09-05  8:34  0%             ` Thomas Monjalon
2017-08-30 18:10  3% ` [dpdk-dev] [PATCH 6/6] eal: remove API rte_mem_phy2mch Jianfeng Tan
2017-08-31 14:40  2% [dpdk-dev] multi-process shared memory on PPC Xueming(Steven) Li
2017-09-12  7:46  0% ` Chao Zhu
2017-09-12  7:54  0%   ` Xueming(Steven) Li
2017-09-12  8:01  0% ` Chao Zhu
2017-09-12  8:12  0%   ` Xueming(Steven) Li
2017-09-12 18:11  0%     ` Xueming(Steven) Li
2017-09-13  8:56  0%       ` Xueming(Steven) Li
     [not found]     <mailman.4135.1504256282.5771.dev@dpdk.org>
2017-09-01  9:36  3% ` [dpdk-dev] dev Digest, Vol 159, Issue 119 Pierre
2017-09-01 10:03     [dpdk-dev] [PATCH 00/17] build DPDK libs and some drivers with meson/ninja Bruce Richardson
2017-09-01 10:04     ` [dpdk-dev] [PATCH 01/17] build: add initial infrastructure for meson & ninja builds Bruce Richardson
2017-09-08 16:03  3%   ` Van Haaren, Harry
2017-09-01 10:04  1% ` [dpdk-dev] [PATCH 04/17] build: add DPDK libraries to build Bruce Richardson
2017-09-04 14:08  0%   ` Van Haaren, Harry
2017-09-04 14:55  0%     ` Bruce Richardson
2017-09-01 10:04  3% ` [dpdk-dev] [PATCH 16/17] build: add option to version libs using DPDK version Bruce Richardson
2017-09-07 17:07  3%   ` [dpdk-dev] [dpdk-dev, " Neil Horman
2017-09-08  8:58  0%     ` Bruce Richardson
2017-09-01 10:04  3% ` [dpdk-dev] [PATCH 17/17] doc: add documentation on how to add new components to DPDK Bruce Richardson
2017-09-12 10:37     ` [dpdk-dev] [PATCH v2 00/17] build DPDK libs and some drivers with meson/ninja Bruce Richardson
2017-09-12 10:37  1%   ` [dpdk-dev] [PATCH v2 04/17] build: add DPDK libraries to build Bruce Richardson
2017-09-12 10:38  3%   ` [dpdk-dev] [PATCH v2 16/17] build: add option to version libs using DPDK version Bruce Richardson
2017-09-13 11:32  5%     ` Luca Boccassi
2017-09-13 13:11  0%       ` Bruce Richardson
2017-09-13 17:02  0%         ` Luca Boccassi
2017-09-12 10:38  3%   ` [dpdk-dev] [PATCH v2 17/17] doc: add documentation on how to add new components to DPDK Bruce Richardson
2017-09-13 14:12       ` [dpdk-dev] [PATCH v3 00/17] build DPDK libs and some drivers with meson/ninja Bruce Richardson
2017-09-13 14:12  1%     ` [dpdk-dev] [PATCH v3 04/17] build: add DPDK libraries to build Bruce Richardson
2017-09-13 14:12  3%     ` [dpdk-dev] [PATCH v3 16/17] build: add option to version libs using DPDK version Bruce Richardson
2017-09-13 14:12  3%     ` [dpdk-dev] [PATCH v3 17/17] doc: add documentation on how to add new components to DPDK Bruce Richardson
2017-09-01 14:12     [dpdk-dev] [PATCH v2 00/18] net/nfp: add PF support Alejandro Lucero
2017-09-01 14:12 11% ` [dpdk-dev] [PATCH v2 02/18] net/nfp: add specific PF probe function Alejandro Lucero
2017-09-01 14:12  6% ` [dpdk-dev] [PATCH v2 11/18] net/nfp: allocate ethernet device from " Alejandro Lucero
2017-09-01 14:12  4% ` [dpdk-dev] [PATCH v2 16/18] doc: update NFP with PF support information Alejandro Lucero
2017-09-04  5:57     [dpdk-dev] [PATCH v2 0/4] increase port_id range Zhiyong Yang
2017-09-09 14:47     ` [dpdk-dev] [PATCH v3 " Zhiyong Yang
2017-09-09 14:47       ` [dpdk-dev] [PATCH v3 1/4] ethdev: " Zhiyong Yang
2017-09-11  9:37  3%     ` Adrien Mazarguil
2017-09-11 10:51  0%       ` Yang, Zhiyong
2017-09-11 10:21  4%     ` Ferruh Yigit
2017-09-13  2:26  0%       ` Yang, Zhiyong
2017-09-14 12:49  4%         ` Ferruh Yigit
2017-09-15  5:11  0%           ` Yang, Zhiyong
2017-09-09 14:47       ` [dpdk-dev] [PATCH v3 3/4] examples: " Zhiyong Yang
2017-09-14 14:41  3%     ` Ferruh Yigit
2017-09-04  7:12  3% [dpdk-dev] [PATCH 0/4] ethdev new offloads API Shahaf Shuler
2017-09-04  7:12  2% ` [dpdk-dev] [PATCH 2/4] ethdev: introduce Rx queue " Shahaf Shuler
2017-09-04  7:12  2% ` [dpdk-dev] [PATCH 3/4] ethdev: introduce Tx " Shahaf Shuler
2017-09-10 12:07  4% ` [dpdk-dev] [PATCH v2 0/2] ethdev new " Shahaf Shuler
2017-09-13  6:37  4%   ` [dpdk-dev] [PATCH v3 " Shahaf Shuler
2017-09-13  9:10  0%     ` Andrew Rybchenko
2017-09-17  6:54  4%     ` [dpdk-dev] [PATCH v4 0/3] " Shahaf Shuler
2017-09-18  7:51  0%       ` Andrew Rybchenko
2017-09-06  2:57  3% [dpdk-dev] DPDK techboard minutes of August 30 Jerin Jacob
2017-09-06 14:47  4% [dpdk-dev] [PATCH v3] doc: update NFP with PF support information Alejandro Lucero
2017-09-06 14:55  0% ` Alejandro Lucero
2017-09-06 15:14  4% Alejandro Lucero
2017-09-11 13:39  4% [dpdk-dev] [PATCH] doc: announce ABI change for ring structure Olivier Matz
2017-09-18  9:16  4% ` Bruce Richardson
2017-09-18  9:24  4% ` Mcnamara, John
2017-09-18  9:30  4% ` Burakov, Anatoly
2017-09-11 13:44  4% [dpdk-dev] [PATCH] net/nfp: remove firmware ABI check Alejandro Lucero
2017-09-14  2:40     [dpdk-dev] [PATCH v2 0/6] remove xen dom0 support in DPDK Jianfeng Tan
2017-09-14  2:40  3% ` [dpdk-dev] [PATCH v2 5/6] eal: remove API rte_mem_phy2mch Jianfeng Tan
2017-09-14  2:40  1% ` [dpdk-dev] [PATCH v2 6/6] eal: remove xen dom0 support Jianfeng Tan
2017-09-15 13:41 21% [dpdk-dev] [PATCH] doc: add note on hardware support deprecation Bruce Richardson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).