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] ethdev: extend flow metadata
  2019-07-10 12:01  4%         ` Bruce Richardson
@ 2019-07-10 12:26  3%           ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2019-07-10 12:26 UTC (permalink / raw)
  To: Bruce Richardson, Olivier Matz, arybchenko, adrien.mazarguil
  Cc: Yongseok Koh, shahafs, ferruh.yigit, dev, viacheslavo

10/07/2019 14:01, Bruce Richardson:
> On Wed, Jul 10, 2019 at 12:07:43PM +0200, Olivier Matz wrote:
> > On Wed, Jul 10, 2019 at 10:55:34AM +0100, Bruce Richardson wrote:
> > > On Wed, Jul 10, 2019 at 11:31:56AM +0200, Olivier Matz wrote:
> > > > On Thu, Jul 04, 2019 at 04:21:22PM -0700, Yongseok Koh wrote:
> > > > > Currently, metadata can be set on egress path via mbuf tx_meatadata field
> > > > > with PKT_TX_METADATA flag and RTE_FLOW_ITEM_TYPE_RX_META matches metadata.
> > > > > 
> > > > > This patch extends the usability.
> > > > > 
> > > > > 1) RTE_FLOW_ACTION_TYPE_SET_META
> > > > > 
> > > > > When supporting multiple tables, Tx metadata can also be set by a rule and
> > > > > matched by another rule. This new action allows metadata to be set as a
> > > > > result of flow match.
> > > > > 
> > > > > 2) Metadata on ingress
> > > > > 
> > > > > There's also need to support metadata on packet Rx. Metadata can be set by
> > > > > SET_META action and matched by META item like Tx. The final value set by
> > > > > the action will be delivered to application via mbuf metadata field with
> > > > > PKT_RX_METADATA ol_flag.
> > > > > 
> > > > > For this purpose, mbuf->tx_metadata is moved as a separate new field and
> > > > > renamed to 'metadata' to support both Rx and Tx metadata.
> > > > > 
> > > > > For loopback/hairpin packet, metadata set on Rx/Tx may or may not be
> > > > > propagated to the other path depending on HW capability.
> > > > > 
> > > > > Signed-off-by: Yongseok Koh <yskoh@mellanox.com>
> > > > 
> > > > > --- a/lib/librte_mbuf/rte_mbuf.h
> > > > > +++ b/lib/librte_mbuf/rte_mbuf.h
> > > > > @@ -648,17 +653,6 @@ struct rte_mbuf {
> > > > >  			/**< User defined tags. See rte_distributor_process() */
> > > > >  			uint32_t usr;
> > > > >  		} hash;                   /**< hash information */
> > > > > -		struct {
> > > > > -			/**
> > > > > -			 * Application specific metadata value
> > > > > -			 * for egress flow rule match.
> > > > > -			 * Valid if PKT_TX_METADATA is set.
> > > > > -			 * Located here to allow conjunct use
> > > > > -			 * with hash.sched.hi.
> > > > > -			 */
> > > > > -			uint32_t tx_metadata;
> > > > > -			uint32_t reserved;
> > > > > -		};
> > > > >  	};
> > > > >  
> > > > >  	/** Outer VLAN TCI (CPU order), valid if PKT_RX_QINQ is set. */
> > > > > @@ -727,6 +721,11 @@ struct rte_mbuf {
> > > > >  	 */
> > > > >  	struct rte_mbuf_ext_shared_info *shinfo;
> > > > >  
> > > > > +	/** Application specific metadata value for flow rule match.
> > > > > +	 * Valid if PKT_RX_METADATA or PKT_TX_METADATA is set.
> > > > > +	 */
> > > > > +	uint32_t metadata;
> > > > > +
> > > > >  } __rte_cache_aligned;
> > > > 
> > > > This will break the ABI, so we cannot put it in 19.08, and we need a
> > > > deprecation notice.
> > > > 
> > > Does it actually break the ABI? Adding a new field to the mbuf should only
> > > break the ABI if it either causes new fields to move or changes the
> > > structure size. Since this is at the end, it's not going to move any older
> > > fields, and since everything is cache-aligned I don't think the structure
> > > size changes either.
> > 
> > I think it does break the ABI: in previous version, when the PKT_TX_METADATA
> > flag is set, the associated value is put in m->tx_metadata (offset 44 on
> > x86-64), and in the next version, it will be in m->metadata (offset 112). So,
> > these 2 versions are not binary compatible.
> > 
> > Anyway, at least it breaks the API.
> 
> Ok, I misunderstood. I thought it was the structure change itself you were
> saying broke the ABI. Yes, putting the data in a different place is indeed
> an ABI break.

We could add the new field and keep the old one unused,
so it does not break the ABI.
However I suppose everybody will prefer a version using dynamic fields.
Is someone against using dynamic field for such usage?



^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH] ethdev: extend flow metadata
  2019-07-10 10:07  3%       ` Olivier Matz
@ 2019-07-10 12:01  4%         ` Bruce Richardson
  2019-07-10 12:26  3%           ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2019-07-10 12:01 UTC (permalink / raw)
  To: Olivier Matz
  Cc: Yongseok Koh, shahafs, thomas, ferruh.yigit, arybchenko,
	adrien.mazarguil, dev, viacheslavo

On Wed, Jul 10, 2019 at 12:07:43PM +0200, Olivier Matz wrote:
> On Wed, Jul 10, 2019 at 10:55:34AM +0100, Bruce Richardson wrote:
> > On Wed, Jul 10, 2019 at 11:31:56AM +0200, Olivier Matz wrote:
> > > Hi Yongseok,
> > > 
> > > On Thu, Jul 04, 2019 at 04:21:22PM -0700, Yongseok Koh wrote:
> > > > Currently, metadata can be set on egress path via mbuf tx_meatadata field
> > > > with PKT_TX_METADATA flag and RTE_FLOW_ITEM_TYPE_RX_META matches metadata.
> > > > 
> > > > This patch extends the usability.
> > > > 
> > > > 1) RTE_FLOW_ACTION_TYPE_SET_META
> > > > 
> > > > When supporting multiple tables, Tx metadata can also be set by a rule and
> > > > matched by another rule. This new action allows metadata to be set as a
> > > > result of flow match.
> > > > 
> > > > 2) Metadata on ingress
> > > > 
> > > > There's also need to support metadata on packet Rx. Metadata can be set by
> > > > SET_META action and matched by META item like Tx. The final value set by
> > > > the action will be delivered to application via mbuf metadata field with
> > > > PKT_RX_METADATA ol_flag.
> > > > 
> > > > For this purpose, mbuf->tx_metadata is moved as a separate new field and
> > > > renamed to 'metadata' to support both Rx and Tx metadata.
> > > > 
> > > > For loopback/hairpin packet, metadata set on Rx/Tx may or may not be
> > > > propagated to the other path depending on HW capability.
> > > > 
> > > > Signed-off-by: Yongseok Koh <yskoh@mellanox.com>
> > > 
> > > (...)
> > > 
> > > > --- a/lib/librte_mbuf/rte_mbuf.h
> > > > +++ b/lib/librte_mbuf/rte_mbuf.h
> > > > @@ -200,6 +200,11 @@ extern "C" {
> > > >  
> > > >  /* add new RX flags here */
> > > >  
> > > > +/**
> > > > + * Indicate that mbuf has metadata from device.
> > > > + */
> > > > +#define PKT_RX_METADATA	(1ULL << 23)
> > > > +
> > > >  /* add new TX flags here */
> > > >  
> > > >  /**
> > > > @@ -648,17 +653,6 @@ struct rte_mbuf {
> > > >  			/**< User defined tags. See rte_distributor_process() */
> > > >  			uint32_t usr;
> > > >  		} hash;                   /**< hash information */
> > > > -		struct {
> > > > -			/**
> > > > -			 * Application specific metadata value
> > > > -			 * for egress flow rule match.
> > > > -			 * Valid if PKT_TX_METADATA is set.
> > > > -			 * Located here to allow conjunct use
> > > > -			 * with hash.sched.hi.
> > > > -			 */
> > > > -			uint32_t tx_metadata;
> > > > -			uint32_t reserved;
> > > > -		};
> > > >  	};
> > > >  
> > > >  	/** Outer VLAN TCI (CPU order), valid if PKT_RX_QINQ is set. */
> > > > @@ -727,6 +721,11 @@ struct rte_mbuf {
> > > >  	 */
> > > >  	struct rte_mbuf_ext_shared_info *shinfo;
> > > >  
> > > > +	/** Application specific metadata value for flow rule match.
> > > > +	 * Valid if PKT_RX_METADATA or PKT_TX_METADATA is set.
> > > > +	 */
> > > > +	uint32_t metadata;
> > > > +
> > > >  } __rte_cache_aligned;
> > > 
> > > This will break the ABI, so we cannot put it in 19.08, and we need a
> > > deprecation notice.
> > > 
> > Does it actually break the ABI? Adding a new field to the mbuf should only
> > break the ABI if it either causes new fields to move or changes the
> > structure size. Since this is at the end, it's not going to move any older
> > fields, and since everything is cache-aligned I don't think the structure
> > size changes either.
> 
> I think it does break the ABI: in previous version, when the PKT_TX_METADATA
> flag is set, the associated value is put in m->tx_metadata (offset 44 on
> x86-64), and in the next version, it will be in m->metadata (offset 112). So,
> these 2 versions are not binary compatible.
> 
> Anyway, at least it breaks the API.

Ok, I misunderstood. I thought it was the structure change itself you were
saying broke the ABI. Yes, putting the data in a different place is indeed
an ABI break.

/Bruce

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] devtools: fix symbol change file matching
  @ 2019-07-10 11:10  0% ` Neil Horman
  0 siblings, 0 replies; 200+ results
From: Neil Horman @ 2019-07-10 11:10 UTC (permalink / raw)
  To: Bing Zhao; +Cc: dev, stable

On Wed, Jul 10, 2019 at 05:57:14PM +0800, Bing Zhao wrote:
> The previous regex miss a situation that a new file is added after
> the map file. It will starts with '/dev/null' instead of 'a /', so
> all the content in the patch file after 'map' will be considered in
> the symbol map file. Also, a second regex matching is used for map
> and other files, the '^map' in square brackets is not quite exact
> the same with the design even if it works.
> 
> Fixes: 4bec48184e33 ("devtools: add checks for ABI symbol addition")
> Cc: nhorman@tuxdriver.com
> 
> Signed-off-by: Bing Zhao <bingz@mellanox.com>
> ---
>  devtools/check-symbol-change.sh | 21 +++++++++++++++++----
>  1 file changed, 17 insertions(+), 4 deletions(-)
> 
> diff --git a/devtools/check-symbol-change.sh b/devtools/check-symbol-change.sh
> index c5434f3..eac71f3 100755
> --- a/devtools/check-symbol-change.sh
> +++ b/devtools/check-symbol-change.sh
> @@ -11,19 +11,32 @@ build_map_changes()
>  		# Initialize our variables
>  		BEGIN {map="";sym="";ar="";sec=""; in_sec=0; in_map=0}
>  
> -		# Anything that starts with + or -, followed by an a
> +		# Anything that starts with + or -, followed by an a or b
>  		# and ends in the string .map is the name of our map file
>  		# This may appear multiple times in a patch if multiple
>  		# map files are altered, and all section/symbol names
>  		# appearing between a triggering of this rule and the
>  		# next trigger of this rule are associated with this file
> -		/[-+] a\/.*\.map/ {map=$2; in_map=1}
>  
>  		# Same pattern as above, only it matches on anything that
> -		# does not end in 'map', indicating we have left the map chunk.
> +		# does not end in "map", indicating we have left the map chunk.
>  		# When we hit this, turn off the in_map variable, which
>  		# supresses the subordonate rules below
> -		/[-+] a\/.*\.[^map]/ {in_map=0}
> +		# Currently, using the same pattern for all the files matching,
> +		# and a second RE matching is used to distinguish map files from
> +		# other types of files
> +		/[-+] [ab]\/.*\.[[:alnum:]]+$/ {
> +			if ($2 ~ /\.map$/) {
> +				if (in_map == 0) {in_map = 1}
> +			} else {
> +				if (in_map == 1) {in_map = 0}
> +			}
> +		}
> +
> +		# Indeed, this RE matching has no use. The only purpose here
> +		# is to remind that the git will have a third file pattern
> +		# "-+ /dev/null" besides "-a /" and "+b /"
> +		/[-+] \/dev\/null$/ {next}
>  
>  		# Triggering this rule, which starts a line and ends it
>  		# with a { identifies a versioned section.  The section name is
> -- 
> 1.8.3.1
> 
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] ethdev: extend flow metadata
  2019-07-10  9:55  4%     ` Bruce Richardson
@ 2019-07-10 10:07  3%       ` Olivier Matz
  2019-07-10 12:01  4%         ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Olivier Matz @ 2019-07-10 10:07 UTC (permalink / raw)
  To: Bruce Richardson
  Cc: Yongseok Koh, shahafs, thomas, ferruh.yigit, arybchenko,
	adrien.mazarguil, dev, viacheslavo

On Wed, Jul 10, 2019 at 10:55:34AM +0100, Bruce Richardson wrote:
> On Wed, Jul 10, 2019 at 11:31:56AM +0200, Olivier Matz wrote:
> > Hi Yongseok,
> > 
> > On Thu, Jul 04, 2019 at 04:21:22PM -0700, Yongseok Koh wrote:
> > > Currently, metadata can be set on egress path via mbuf tx_meatadata field
> > > with PKT_TX_METADATA flag and RTE_FLOW_ITEM_TYPE_RX_META matches metadata.
> > > 
> > > This patch extends the usability.
> > > 
> > > 1) RTE_FLOW_ACTION_TYPE_SET_META
> > > 
> > > When supporting multiple tables, Tx metadata can also be set by a rule and
> > > matched by another rule. This new action allows metadata to be set as a
> > > result of flow match.
> > > 
> > > 2) Metadata on ingress
> > > 
> > > There's also need to support metadata on packet Rx. Metadata can be set by
> > > SET_META action and matched by META item like Tx. The final value set by
> > > the action will be delivered to application via mbuf metadata field with
> > > PKT_RX_METADATA ol_flag.
> > > 
> > > For this purpose, mbuf->tx_metadata is moved as a separate new field and
> > > renamed to 'metadata' to support both Rx and Tx metadata.
> > > 
> > > For loopback/hairpin packet, metadata set on Rx/Tx may or may not be
> > > propagated to the other path depending on HW capability.
> > > 
> > > Signed-off-by: Yongseok Koh <yskoh@mellanox.com>
> > 
> > (...)
> > 
> > > --- a/lib/librte_mbuf/rte_mbuf.h
> > > +++ b/lib/librte_mbuf/rte_mbuf.h
> > > @@ -200,6 +200,11 @@ extern "C" {
> > >  
> > >  /* add new RX flags here */
> > >  
> > > +/**
> > > + * Indicate that mbuf has metadata from device.
> > > + */
> > > +#define PKT_RX_METADATA	(1ULL << 23)
> > > +
> > >  /* add new TX flags here */
> > >  
> > >  /**
> > > @@ -648,17 +653,6 @@ struct rte_mbuf {
> > >  			/**< User defined tags. See rte_distributor_process() */
> > >  			uint32_t usr;
> > >  		} hash;                   /**< hash information */
> > > -		struct {
> > > -			/**
> > > -			 * Application specific metadata value
> > > -			 * for egress flow rule match.
> > > -			 * Valid if PKT_TX_METADATA is set.
> > > -			 * Located here to allow conjunct use
> > > -			 * with hash.sched.hi.
> > > -			 */
> > > -			uint32_t tx_metadata;
> > > -			uint32_t reserved;
> > > -		};
> > >  	};
> > >  
> > >  	/** Outer VLAN TCI (CPU order), valid if PKT_RX_QINQ is set. */
> > > @@ -727,6 +721,11 @@ struct rte_mbuf {
> > >  	 */
> > >  	struct rte_mbuf_ext_shared_info *shinfo;
> > >  
> > > +	/** Application specific metadata value for flow rule match.
> > > +	 * Valid if PKT_RX_METADATA or PKT_TX_METADATA is set.
> > > +	 */
> > > +	uint32_t metadata;
> > > +
> > >  } __rte_cache_aligned;
> > 
> > This will break the ABI, so we cannot put it in 19.08, and we need a
> > deprecation notice.
> > 
> Does it actually break the ABI? Adding a new field to the mbuf should only
> break the ABI if it either causes new fields to move or changes the
> structure size. Since this is at the end, it's not going to move any older
> fields, and since everything is cache-aligned I don't think the structure
> size changes either.

I think it does break the ABI: in previous version, when the PKT_TX_METADATA
flag is set, the associated value is put in m->tx_metadata (offset 44 on
x86-64), and in the next version, it will be in m->metadata (offset 112). So,
these 2 versions are not binary compatible.

Anyway, at least it breaks the API.

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH] ethdev: extend flow metadata
  2019-07-10  9:31  3%   ` Olivier Matz
@ 2019-07-10  9:55  4%     ` Bruce Richardson
  2019-07-10 10:07  3%       ` Olivier Matz
  0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2019-07-10  9:55 UTC (permalink / raw)
  To: Olivier Matz
  Cc: Yongseok Koh, shahafs, thomas, ferruh.yigit, arybchenko,
	adrien.mazarguil, dev, viacheslavo

On Wed, Jul 10, 2019 at 11:31:56AM +0200, Olivier Matz wrote:
> Hi Yongseok,
> 
> On Thu, Jul 04, 2019 at 04:21:22PM -0700, Yongseok Koh wrote:
> > Currently, metadata can be set on egress path via mbuf tx_meatadata field
> > with PKT_TX_METADATA flag and RTE_FLOW_ITEM_TYPE_RX_META matches metadata.
> > 
> > This patch extends the usability.
> > 
> > 1) RTE_FLOW_ACTION_TYPE_SET_META
> > 
> > When supporting multiple tables, Tx metadata can also be set by a rule and
> > matched by another rule. This new action allows metadata to be set as a
> > result of flow match.
> > 
> > 2) Metadata on ingress
> > 
> > There's also need to support metadata on packet Rx. Metadata can be set by
> > SET_META action and matched by META item like Tx. The final value set by
> > the action will be delivered to application via mbuf metadata field with
> > PKT_RX_METADATA ol_flag.
> > 
> > For this purpose, mbuf->tx_metadata is moved as a separate new field and
> > renamed to 'metadata' to support both Rx and Tx metadata.
> > 
> > For loopback/hairpin packet, metadata set on Rx/Tx may or may not be
> > propagated to the other path depending on HW capability.
> > 
> > Signed-off-by: Yongseok Koh <yskoh@mellanox.com>
> 
> (...)
> 
> > --- a/lib/librte_mbuf/rte_mbuf.h
> > +++ b/lib/librte_mbuf/rte_mbuf.h
> > @@ -200,6 +200,11 @@ extern "C" {
> >  
> >  /* add new RX flags here */
> >  
> > +/**
> > + * Indicate that mbuf has metadata from device.
> > + */
> > +#define PKT_RX_METADATA	(1ULL << 23)
> > +
> >  /* add new TX flags here */
> >  
> >  /**
> > @@ -648,17 +653,6 @@ struct rte_mbuf {
> >  			/**< User defined tags. See rte_distributor_process() */
> >  			uint32_t usr;
> >  		} hash;                   /**< hash information */
> > -		struct {
> > -			/**
> > -			 * Application specific metadata value
> > -			 * for egress flow rule match.
> > -			 * Valid if PKT_TX_METADATA is set.
> > -			 * Located here to allow conjunct use
> > -			 * with hash.sched.hi.
> > -			 */
> > -			uint32_t tx_metadata;
> > -			uint32_t reserved;
> > -		};
> >  	};
> >  
> >  	/** Outer VLAN TCI (CPU order), valid if PKT_RX_QINQ is set. */
> > @@ -727,6 +721,11 @@ struct rte_mbuf {
> >  	 */
> >  	struct rte_mbuf_ext_shared_info *shinfo;
> >  
> > +	/** Application specific metadata value for flow rule match.
> > +	 * Valid if PKT_RX_METADATA or PKT_TX_METADATA is set.
> > +	 */
> > +	uint32_t metadata;
> > +
> >  } __rte_cache_aligned;
> 
> This will break the ABI, so we cannot put it in 19.08, and we need a
> deprecation notice.
> 
Does it actually break the ABI? Adding a new field to the mbuf should only
break the ABI if it either causes new fields to move or changes the
structure size. Since this is at the end, it's not going to move any older
fields, and since everything is cache-aligned I don't think the structure
size changes either.

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH] ethdev: extend flow metadata
  @ 2019-07-10  9:31  3%   ` Olivier Matz
  2019-07-10  9:55  4%     ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Olivier Matz @ 2019-07-10  9:31 UTC (permalink / raw)
  To: Yongseok Koh
  Cc: shahafs, thomas, ferruh.yigit, arybchenko, adrien.mazarguil, dev,
	viacheslavo

Hi Yongseok,

On Thu, Jul 04, 2019 at 04:21:22PM -0700, Yongseok Koh wrote:
> Currently, metadata can be set on egress path via mbuf tx_meatadata field
> with PKT_TX_METADATA flag and RTE_FLOW_ITEM_TYPE_RX_META matches metadata.
> 
> This patch extends the usability.
> 
> 1) RTE_FLOW_ACTION_TYPE_SET_META
> 
> When supporting multiple tables, Tx metadata can also be set by a rule and
> matched by another rule. This new action allows metadata to be set as a
> result of flow match.
> 
> 2) Metadata on ingress
> 
> There's also need to support metadata on packet Rx. Metadata can be set by
> SET_META action and matched by META item like Tx. The final value set by
> the action will be delivered to application via mbuf metadata field with
> PKT_RX_METADATA ol_flag.
> 
> For this purpose, mbuf->tx_metadata is moved as a separate new field and
> renamed to 'metadata' to support both Rx and Tx metadata.
> 
> For loopback/hairpin packet, metadata set on Rx/Tx may or may not be
> propagated to the other path depending on HW capability.
> 
> Signed-off-by: Yongseok Koh <yskoh@mellanox.com>

(...)

> --- a/lib/librte_mbuf/rte_mbuf.h
> +++ b/lib/librte_mbuf/rte_mbuf.h
> @@ -200,6 +200,11 @@ extern "C" {
>  
>  /* add new RX flags here */
>  
> +/**
> + * Indicate that mbuf has metadata from device.
> + */
> +#define PKT_RX_METADATA	(1ULL << 23)
> +
>  /* add new TX flags here */
>  
>  /**
> @@ -648,17 +653,6 @@ struct rte_mbuf {
>  			/**< User defined tags. See rte_distributor_process() */
>  			uint32_t usr;
>  		} hash;                   /**< hash information */
> -		struct {
> -			/**
> -			 * Application specific metadata value
> -			 * for egress flow rule match.
> -			 * Valid if PKT_TX_METADATA is set.
> -			 * Located here to allow conjunct use
> -			 * with hash.sched.hi.
> -			 */
> -			uint32_t tx_metadata;
> -			uint32_t reserved;
> -		};
>  	};
>  
>  	/** Outer VLAN TCI (CPU order), valid if PKT_RX_QINQ is set. */
> @@ -727,6 +721,11 @@ struct rte_mbuf {
>  	 */
>  	struct rte_mbuf_ext_shared_info *shinfo;
>  
> +	/** Application specific metadata value for flow rule match.
> +	 * Valid if PKT_RX_METADATA or PKT_TX_METADATA is set.
> +	 */
> +	uint32_t metadata;
> +
>  } __rte_cache_aligned;

This will break the ABI, so we cannot put it in 19.08, and we need a
deprecation notice.

That said, it shows again that we need something to make the addition of
fields in mbufs more flexible. Knowing that Thomas will present
something about it at next userspace [1], I drafted something in a RFC
[2]. It is simpler than I expected, and I think your commit could be
a good candidate for a first user. Do you mind having a try? Feedback
and comment is of course welcome.

If it fits your needs, we can target its introduction for 19.11. Having
a user for this new feature would be a plus for its introduction :)

Thanks,
Olivier

[1] https://dpdkbordeaux2019.sched.com/
[2] http://mails.dpdk.org/archives/dev/2019-July/137772.html

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [RFC] mbuf: support dynamic fields and flags
@ 2019-07-10  9:29  4% Olivier Matz
  0 siblings, 0 replies; 200+ results
From: Olivier Matz @ 2019-07-10  9:29 UTC (permalink / raw)
  To: dev

Many features require to store data inside the mbuf. As the room in mbuf
structure is limited, it is not possible to have a field for each
feature. Also, changing fields in the mbuf structure can break the API
or ABI.

This commit addresses these issues, by enabling the dynamic registration
of fields or flags:

- a dynamic field is a named area in the rte_mbuf structure, with a
  given size (>= 1 byte) and alignment constraint.
- a dynamic flag is a named bit in the rte_mbuf structure.

The typical use case is a PMD that registers space for an offload
feature, when the application requests to enable this feature.  As
the space in mbuf is limited, the space should only be reserved if it
is going to be used (i.e when the application explicitly asks for it).

The registration can be done at any moment, but it is not possible
to unregister fields or flags for now.

Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
 app/test/test_mbuf.c                 |  83 +++++++-
 lib/librte_mbuf/Makefile             |   2 +
 lib/librte_mbuf/meson.build          |   6 +-
 lib/librte_mbuf/rte_mbuf.h           |  25 ++-
 lib/librte_mbuf/rte_mbuf_dyn.c       | 373 +++++++++++++++++++++++++++++++++++
 lib/librte_mbuf/rte_mbuf_dyn.h       | 119 +++++++++++
 lib/librte_mbuf/rte_mbuf_version.map |   4 +
 7 files changed, 607 insertions(+), 5 deletions(-)
 create mode 100644 lib/librte_mbuf/rte_mbuf_dyn.c
 create mode 100644 lib/librte_mbuf/rte_mbuf_dyn.h

diff --git a/app/test/test_mbuf.c b/app/test/test_mbuf.c
index 2a97afe20..8008cc766 100644
--- a/app/test/test_mbuf.c
+++ b/app/test/test_mbuf.c
@@ -28,6 +28,7 @@
 #include <rte_random.h>
 #include <rte_cycles.h>
 #include <rte_malloc.h>
+#include <rte_mbuf_dyn.h>
 
 #include "test.h"
 
@@ -502,7 +503,6 @@ test_attach_from_different_pool(struct rte_mempool *pktmbuf_pool,
 		rte_pktmbuf_free(clone2);
 	return -1;
 }
-#undef GOTO_FAIL
 
 /*
  * test allocation and free of mbufs
@@ -1122,6 +1122,81 @@ test_tx_offload(void)
 }
 
 static int
+test_mbuf_dyn(struct rte_mempool *pktmbuf_pool)
+{
+	struct rte_mbuf *m = NULL;
+	int offset, offset2;
+	int flag, flag2;
+
+	offset = rte_mbuf_dynfield_register("test-dynfield", sizeof(uint8_t),
+					__alignof__(uint8_t), 0);
+	if (offset == -1)
+		GOTO_FAIL("failed to register dynamic field, offset=%d: %s",
+			offset, strerror(errno));
+
+	offset2 = rte_mbuf_dynfield_register("test-dynfield", sizeof(uint8_t),
+					__alignof__(uint8_t), 0);
+	if (offset2 != offset)
+		GOTO_FAIL("failed to lookup dynamic field, offset=%d, offset2=%d: %s",
+			offset, offset2, strerror(errno));
+
+	offset2 = rte_mbuf_dynfield_register("test-dynfield2", sizeof(uint16_t),
+					__alignof__(uint16_t), 0);
+	if (offset2 == -1 || offset2 == offset || (offset & 1))
+		GOTO_FAIL("failed to register dynfield field 2, offset=%d, offset2=%d: %s",
+			offset, offset2, strerror(errno));
+
+	printf("offset = %d, offset2 = %d\n", offset, offset2);
+
+	offset = rte_mbuf_dynfield_register("test-dynfield-fail", 256, 1, 0);
+	if (offset != -1)
+		GOTO_FAIL("dynamic field creation should fail (too big)");
+
+	offset = rte_mbuf_dynfield_register("test-dynfield-fail", 1, 3, 0);
+	if (offset != -1)
+		GOTO_FAIL("dynamic field creation should fail (bad alignment)");
+
+	flag = rte_mbuf_dynflag_register("test-dynflag");
+	if (flag == -1)
+		GOTO_FAIL("failed to register dynamic field, flag=%d: %s",
+			flag, strerror(errno));
+
+	flag2 = rte_mbuf_dynflag_register("test-dynflag");
+	if (flag2 != flag)
+		GOTO_FAIL("failed to lookup dynamic field, flag=%d, flag2=%d: %s",
+			flag, flag2, strerror(errno));
+
+	flag2 = rte_mbuf_dynflag_register("test-dynflag2");
+	if (flag2 == -1 || flag2 == flag)
+		GOTO_FAIL("failed to register dynflag field 2, flag=%d, flag2=%d: %s",
+			flag, flag2, strerror(errno));
+
+	printf("flag = %d, flag2 = %d\n", flag, flag2);
+
+	/* set, get dynamic field */
+	m = rte_pktmbuf_alloc(pktmbuf_pool);
+	if (m == NULL)
+		GOTO_FAIL("Cannot allocate mbuf");
+
+	*RTE_MBUF_DYNFIELD(m, offset, uint8_t *) = 1;
+	if (*RTE_MBUF_DYNFIELD(m, offset, uint8_t *) != 1)
+		GOTO_FAIL("failed to read dynamic field");
+	*RTE_MBUF_DYNFIELD(m, offset2, uint16_t *) = 1000;
+	if (*RTE_MBUF_DYNFIELD(m, offset2, uint16_t *) != 1000)
+		GOTO_FAIL("failed to read dynamic field");
+
+	/* set a dynamic flag */
+	m->ol_flags |= (1ULL << flag);
+
+	rte_pktmbuf_free(m);
+	return 0;
+fail:
+	rte_pktmbuf_free(m);
+	return -1;
+}
+#undef GOTO_FAIL
+
+static int
 test_mbuf(void)
 {
 	int ret = -1;
@@ -1140,6 +1215,12 @@ test_mbuf(void)
 		goto err;
 	}
 
+	/* test registration of dynamic fields and flags */
+	if (test_mbuf_dyn(pktmbuf_pool) < 0) {
+		printf("mbuf dynflag test failed\n");
+		goto err;
+	}
+
 	/* create a specific pktmbuf pool with a priv_size != 0 and no data
 	 * room size */
 	pktmbuf_pool2 = rte_pktmbuf_pool_create("test_pktmbuf_pool2",
diff --git a/lib/librte_mbuf/Makefile b/lib/librte_mbuf/Makefile
index c8f6d2689..5a9bcee73 100644
--- a/lib/librte_mbuf/Makefile
+++ b/lib/librte_mbuf/Makefile
@@ -17,8 +17,10 @@ LIBABIVER := 5
 
 # all source are stored in SRCS-y
 SRCS-$(CONFIG_RTE_LIBRTE_MBUF) := rte_mbuf.c rte_mbuf_ptype.c rte_mbuf_pool_ops.c
+SRCS-$(CONFIG_RTE_LIBRTE_MBUF) += rte_mbuf_dyn.c
 
 # install includes
 SYMLINK-$(CONFIG_RTE_LIBRTE_MBUF)-include := rte_mbuf.h rte_mbuf_ptype.h rte_mbuf_pool_ops.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_MBUF)-include += rte_mbuf_dyn.h
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_mbuf/meson.build b/lib/librte_mbuf/meson.build
index 6cc11ebb4..9137e8f26 100644
--- a/lib/librte_mbuf/meson.build
+++ b/lib/librte_mbuf/meson.build
@@ -2,8 +2,10 @@
 # Copyright(c) 2017 Intel Corporation
 
 version = 5
-sources = files('rte_mbuf.c', 'rte_mbuf_ptype.c', 'rte_mbuf_pool_ops.c')
-headers = files('rte_mbuf.h', 'rte_mbuf_ptype.h', 'rte_mbuf_pool_ops.h')
+sources = files('rte_mbuf.c', 'rte_mbuf_ptype.c', 'rte_mbuf_pool_ops.c',
+	'rte_mbuf_dyn.c')
+headers = files('rte_mbuf.h', 'rte_mbuf_ptype.h', 'rte_mbuf_pool_ops.h',
+	'rte_mbuf_dyn.h')
 deps += ['mempool']
 
 allow_experimental_apis = true
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 98225ec80..ef588cd54 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -198,9 +198,12 @@ extern "C" {
 #define PKT_RX_OUTER_L4_CKSUM_GOOD	(1ULL << 22)
 #define PKT_RX_OUTER_L4_CKSUM_INVALID	((1ULL << 21) | (1ULL << 22))
 
-/* add new RX flags here */
+/* add new RX flags here, don't forget to update PKT_FIRST_FREE */
 
-/* add new TX flags here */
+#define PKT_FIRST_FREE (1ULL << 23)
+#define PKT_LAST_FREE (1ULL << 39)
+
+/* add new TX flags here, don't forget to update PKT_LAST_FREE  */
 
 /**
  * Indicate that the metadata field in the mbuf is in use.
@@ -738,6 +741,8 @@ struct rte_mbuf {
 	 */
 	struct rte_mbuf_ext_shared_info *shinfo;
 
+	uint64_t dynfield1; /**< Reserved for dynamic fields. */
+	uint64_t dynfield2; /**< Reserved for dynamic fields. */
 } __rte_cache_aligned;
 
 /**
@@ -1685,6 +1690,21 @@ rte_pktmbuf_attach_extbuf(struct rte_mbuf *m, void *buf_addr,
 #define rte_pktmbuf_detach_extbuf(m) rte_pktmbuf_detach(m)
 
 /**
+ * Copy dynamic fields from m_src to m_dst.
+ *
+ * @param m_dst
+ *   The destination mbuf.
+ * @param m_src
+ *   The source mbuf.
+ */
+static inline void
+rte_mbuf_dynfield_copy(struct rte_mbuf *m_dst, const struct rte_mbuf *m_src)
+{
+	m_dst->dynfield1 = m_src->dynfield1;
+	m_dst->dynfield2 = m_src->dynfield2;
+}
+
+/**
  * Attach packet mbuf to another packet mbuf.
  *
  * If the mbuf we are attaching to isn't a direct buffer and is attached to
@@ -1732,6 +1752,7 @@ static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m)
 	mi->vlan_tci_outer = m->vlan_tci_outer;
 	mi->tx_offload = m->tx_offload;
 	mi->hash = m->hash;
+	rte_mbuf_dynfield_copy(mi, m);
 
 	mi->next = NULL;
 	mi->pkt_len = mi->data_len;
diff --git a/lib/librte_mbuf/rte_mbuf_dyn.c b/lib/librte_mbuf/rte_mbuf_dyn.c
new file mode 100644
index 000000000..6a96a43da
--- /dev/null
+++ b/lib/librte_mbuf/rte_mbuf_dyn.c
@@ -0,0 +1,373 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2019 6WIND S.A.
+ */
+
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_eal.h>
+#include <rte_eal_memconfig.h>
+#include <rte_tailq.h>
+#include <rte_errno.h>
+#include <rte_malloc.h>
+#include <rte_string_fns.h>
+#include <rte_mbuf.h>
+#include <rte_mbuf_dyn.h>
+
+#define RTE_MBUF_DYN_MZNAME "rte_mbuf_dyn"
+
+struct mbuf_dynfield {
+	TAILQ_ENTRY(mbuf_dynfield) next;
+	char name[RTE_MBUF_DYN_NAMESIZE];
+	size_t size;
+	size_t align;
+	unsigned int flags;
+	int offset;
+};
+TAILQ_HEAD(mbuf_dynfield_list, rte_tailq_entry);
+
+static struct rte_tailq_elem mbuf_dynfield_tailq = {
+	.name = "RTE_MBUF_DYNFIELD",
+};
+EAL_REGISTER_TAILQ(mbuf_dynfield_tailq);
+
+struct mbuf_dynflag {
+	TAILQ_ENTRY(mbuf_dynflag) next;
+	char name[RTE_MBUF_DYN_NAMESIZE];
+	int bitnum;
+};
+TAILQ_HEAD(mbuf_dynflag_list, rte_tailq_entry);
+
+static struct rte_tailq_elem mbuf_dynflag_tailq = {
+	.name = "RTE_MBUF_DYNFLAG",
+};
+EAL_REGISTER_TAILQ(mbuf_dynflag_tailq);
+
+struct mbuf_dyn_shm {
+	/** For each mbuf byte, free_space[i] == 1 if space is free. */
+	uint8_t free_space[sizeof(struct rte_mbuf)];
+	/** Bitfield of available flags. */
+	uint64_t free_flags;
+};
+static struct mbuf_dyn_shm *shm;
+
+/* allocate and initialize the shared memory */
+static int
+init_shared_mem(void)
+{
+	const struct rte_memzone *mz;
+	uint64_t mask;
+
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		mz = rte_memzone_reserve_aligned(RTE_MBUF_DYN_MZNAME,
+						sizeof(struct mbuf_dyn_shm),
+						SOCKET_ID_ANY, 0,
+						RTE_CACHE_LINE_SIZE);
+	} else {
+		mz = rte_memzone_lookup(RTE_MBUF_DYN_MZNAME);
+	}
+	if (mz == NULL)
+		return -1;
+
+	shm = mz->addr;
+
+#define mark_free(field)						\
+	memset(&shm->free_space[offsetof(struct rte_mbuf, field)],	\
+		0xff, sizeof(((struct rte_mbuf *)0)->field))
+
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		/* init free_space, keep it sync'd with
+		 * rte_mbuf_dynfield_copy().
+		 */
+		memset(shm, 0, sizeof(*shm));
+		mark_free(dynfield1);
+		mark_free(dynfield2);
+
+		/* init free_flags */
+		for (mask = PKT_FIRST_FREE; mask <= PKT_LAST_FREE; mask <<= 1)
+			shm->free_flags |= mask;
+	}
+#undef mark_free
+
+	return 0;
+}
+
+/* check if this offset can be used */
+static int
+check_offset(size_t offset, size_t size, size_t align, unsigned int flags)
+{
+	size_t i;
+
+	(void)flags;
+
+	if ((offset & (align - 1)) != 0)
+		return -1;
+	if (offset + size > sizeof(struct rte_mbuf))
+		return -1;
+
+	for (i = 0; i < size; i++) {
+		if (!shm->free_space[i + offset])
+			return -1;
+	}
+
+	return 0;
+}
+
+/* assume tailq is locked */
+static struct mbuf_dynfield *
+__mbuf_dynfield_lookup(const char *name)
+{
+	struct mbuf_dynfield_list *mbuf_dynfield_list;
+	struct mbuf_dynfield *mbuf_dynfield;
+	struct rte_tailq_entry *te;
+
+	mbuf_dynfield_list = RTE_TAILQ_CAST(
+		mbuf_dynfield_tailq.head, mbuf_dynfield_list);
+
+	TAILQ_FOREACH(te, mbuf_dynfield_list, next) {
+		mbuf_dynfield = (struct mbuf_dynfield *)te->data;
+		if (strncmp(name, mbuf_dynfield->name,
+				RTE_MBUF_DYN_NAMESIZE) == 0)
+			break;
+	}
+
+	if (te == NULL) {
+		rte_errno = ENOENT;
+		return NULL;
+	}
+
+	return mbuf_dynfield;
+}
+
+int
+rte_mbuf_dynfield_lookup(const char *name, size_t *size, size_t *align)
+{
+	struct mbuf_dynfield *mbuf_dynfield;
+
+	if (shm == NULL) {
+		rte_errno = ENOENT;
+		return -1;
+	}
+
+	rte_mcfg_tailq_read_lock();
+	mbuf_dynfield = __mbuf_dynfield_lookup(name);
+	rte_mcfg_tailq_read_unlock();
+
+	if (mbuf_dynfield == NULL) {
+		rte_errno = ENOENT;
+		return -1;
+	}
+
+	if (size != NULL)
+		*size = mbuf_dynfield->size;
+	if (align != NULL)
+		*align = mbuf_dynfield->align;
+
+	return mbuf_dynfield->offset;
+}
+
+int
+rte_mbuf_dynfield_register(const char *name, size_t size, size_t align,
+			unsigned int flags)
+{
+	struct mbuf_dynfield_list *mbuf_dynfield_list;
+	struct mbuf_dynfield *mbuf_dynfield = NULL;
+	struct rte_tailq_entry *te = NULL;
+	int offset, ret;
+	size_t i;
+
+	if (shm == NULL && init_shared_mem() < 0)
+		goto fail;
+	if (size >= sizeof(struct rte_mbuf)) {
+		rte_errno = EINVAL;
+		goto fail;
+	}
+	if (!rte_is_power_of_2(align)) {
+		rte_errno = EINVAL;
+		goto fail;
+	}
+
+	rte_mcfg_tailq_write_lock();
+
+	mbuf_dynfield = __mbuf_dynfield_lookup(name);
+	if (mbuf_dynfield != NULL) {
+		if (mbuf_dynfield->size != size ||
+				mbuf_dynfield->align != align ||
+				mbuf_dynfield->flags != flags) {
+			rte_errno = EEXIST;
+			goto fail_unlock;
+		}
+		offset = mbuf_dynfield->offset;
+		goto out_unlock;
+	}
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+		rte_errno = EPERM;
+		goto fail_unlock;
+	}
+
+	for (offset = 0;
+	     offset < (int)sizeof(struct rte_mbuf);
+	     offset++) {
+		if (check_offset(offset, size, align, flags) == 0)
+			break;
+	}
+
+	if (offset == sizeof(struct rte_mbuf)) {
+		rte_errno = ENOENT;
+		goto fail_unlock;
+	}
+
+	mbuf_dynfield_list = RTE_TAILQ_CAST(
+		mbuf_dynfield_tailq.head, mbuf_dynfield_list);
+
+	te = rte_zmalloc("MBUF_DYNFIELD_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL)
+		goto fail_unlock;
+
+	mbuf_dynfield = rte_zmalloc("mbuf_dynfield", sizeof(*mbuf_dynfield), 0);
+	if (mbuf_dynfield == NULL)
+		goto fail_unlock;
+
+	ret = strlcpy(mbuf_dynfield->name, name, sizeof(mbuf_dynfield->name));
+	if (ret < 0 || ret >= (int)sizeof(mbuf_dynfield->name)) {
+		rte_errno = ENAMETOOLONG;
+		goto fail_unlock;
+	}
+	mbuf_dynfield->size = size;
+	mbuf_dynfield->align = align;
+	mbuf_dynfield->flags = flags;
+	mbuf_dynfield->offset = offset;
+	te->data = mbuf_dynfield;
+
+	TAILQ_INSERT_TAIL(mbuf_dynfield_list, te, next);
+
+	for (i = offset; i < offset + size; i++)
+		shm->free_space[i] = 0;
+
+out_unlock:
+	rte_mcfg_tailq_write_unlock();
+
+	return offset;
+
+fail_unlock:
+	rte_mcfg_tailq_write_unlock();
+fail:
+	rte_free(mbuf_dynfield);
+	rte_free(te);
+	return -1;
+}
+
+/* assume tailq is locked */
+static struct mbuf_dynflag *
+__mbuf_dynflag_lookup(const char *name)
+{
+	struct mbuf_dynflag_list *mbuf_dynflag_list;
+	struct mbuf_dynflag *mbuf_dynflag;
+	struct rte_tailq_entry *te;
+
+	mbuf_dynflag_list = RTE_TAILQ_CAST(
+		mbuf_dynflag_tailq.head, mbuf_dynflag_list);
+
+	TAILQ_FOREACH(te, mbuf_dynflag_list, next) {
+		mbuf_dynflag = (struct mbuf_dynflag *)te->data;
+		if (strncmp(name, mbuf_dynflag->name,
+				RTE_MBUF_DYN_NAMESIZE) == 0)
+			break;
+	}
+
+	if (te == NULL) {
+		rte_errno = ENOENT;
+		return NULL;
+	}
+
+	return mbuf_dynflag;
+}
+
+int
+rte_mbuf_dynflag_lookup(const char *name)
+{
+	struct mbuf_dynflag *mbuf_dynflag;
+
+	if (shm == NULL) {
+		rte_errno = ENOENT;
+		return -1;
+	}
+
+	rte_mcfg_tailq_read_lock();
+	mbuf_dynflag = __mbuf_dynflag_lookup(name);
+	rte_mcfg_tailq_read_unlock();
+
+	if (mbuf_dynflag == NULL) {
+		rte_errno = ENOENT;
+		return -1;
+	}
+
+	return mbuf_dynflag->bitnum;
+}
+
+int
+rte_mbuf_dynflag_register(const char *name)
+{
+	struct mbuf_dynflag_list *mbuf_dynflag_list;
+	struct mbuf_dynflag *mbuf_dynflag = NULL;
+	struct rte_tailq_entry *te = NULL;
+	int bitnum, ret;
+
+	if (shm == NULL && init_shared_mem() < 0)
+		goto fail;
+
+	rte_mcfg_tailq_write_lock();
+
+	mbuf_dynflag = __mbuf_dynflag_lookup(name);
+	if (mbuf_dynflag != NULL) {
+		bitnum = mbuf_dynflag->bitnum;
+		goto out_unlock;
+	}
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+		rte_errno = EPERM;
+		goto fail_unlock;
+	}
+
+	if (shm->free_flags == 0) {
+		rte_errno = ENOENT;
+		goto fail_unlock;
+	}
+	bitnum = rte_bsf64(shm->free_flags);
+
+	mbuf_dynflag_list = RTE_TAILQ_CAST(
+		mbuf_dynflag_tailq.head, mbuf_dynflag_list);
+
+	te = rte_zmalloc("MBUF_DYNFLAG_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL)
+		goto fail_unlock;
+
+	mbuf_dynflag = rte_zmalloc("mbuf_dynflag", sizeof(*mbuf_dynflag), 0);
+	if (mbuf_dynflag == NULL)
+		goto fail_unlock;
+
+	ret = strlcpy(mbuf_dynflag->name, name, sizeof(mbuf_dynflag->name));
+	if (ret < 0 || ret >= (int)sizeof(mbuf_dynflag->name)) {
+		rte_errno = ENAMETOOLONG;
+		goto fail_unlock;
+	}
+	mbuf_dynflag->bitnum = bitnum;
+	te->data = mbuf_dynflag;
+
+	TAILQ_INSERT_TAIL(mbuf_dynflag_list, te, next);
+
+	shm->free_flags &= ~(1ULL << bitnum);
+
+out_unlock:
+	rte_mcfg_tailq_write_unlock();
+
+	return bitnum;
+
+fail_unlock:
+	rte_mcfg_tailq_write_unlock();
+fail:
+	rte_free(mbuf_dynflag);
+	rte_free(te);
+	return -1;
+}
diff --git a/lib/librte_mbuf/rte_mbuf_dyn.h b/lib/librte_mbuf/rte_mbuf_dyn.h
new file mode 100644
index 000000000..a86986a0f
--- /dev/null
+++ b/lib/librte_mbuf/rte_mbuf_dyn.h
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2019 6WIND S.A.
+ */
+
+#ifndef _RTE_MBUF_DYN_H_
+#define _RTE_MBUF_DYN_H_
+
+/**
+ * @file
+ * RTE Mbuf dynamic fields and flags
+ *
+ * Many features require to store data inside the mbuf. As the room in
+ * mbuf structure is limited, it is not possible to have a field for
+ * each feature. Also, changing fields in the mbuf structure can break
+ * the API or ABI.
+ *
+ * This module addresses this issue, by enabling the dynamic
+ * registration of fields or flags:
+ *
+ * - a dynamic field is a named area in the rte_mbuf structure, with a
+ *   given size (>= 1 byte) and alignment constraint.
+ * - a dynamic flag is a named bit in the rte_mbuf structure.
+ *
+ * The typical use case is a PMD that registers space for an offload
+ * feature, when the application requests to enable this feature.  As
+ * the space in mbuf is limited, the space should only be reserved if it
+ * is going to be used (i.e when the application explicitly asks for it).
+ *
+ * The registration can be done at any moment, but it is not possible
+ * to unregister fields or flags for now.
+ *
+ * Example of use:
+ *
+ * - RTE_MBUF_DYN_<feature>_(ID|SIZE|ALIGN) are defined in this file
+ * - If the application asks for the feature, the PMD use
+ *   rte_mbuf_dynfield_register() to get the dynamic offset and stores
+ *   in a global variable.
+ * - The application also calls rte_mbuf_dynfield_register() to get the
+ *   dynamic offset and stores it in a global variable.
+ * - When the field must be used by the PMD or the application, they
+ *   use the RTE_MBUF_DYNFIELD() helper.
+ */
+
+struct rte_mbuf;
+
+/**
+ * Register space for a dynamic field in the mbuf structure.
+ *
+ * @param name
+ *   A string identifying the dynamic field. External applications or
+ *   libraries must not define identifers prefixed with "rte_", which
+ *   are reserved for standard features.
+ * @param size
+ *   The number of bytes to reserve.
+ * @param align
+ *   The alignment constraint, which must be a power of 2.
+ * @param flags
+ *   Reserved for future use.
+ * @return
+ *   The offset in the mbuf structure, or -1 on error (rte_errno is set).
+ */
+__rte_experimental
+int rte_mbuf_dynfield_register(const char *name, size_t size, size_t align,
+			unsigned int flags);
+
+/**
+ * Lookup for a registered dynamic mbuf field.
+ *
+ * @param name
+ *   A string identifying the dynamic field.
+ * @param size
+ *   If not NULL, the number of reserved bytes for this field is stored
+ *   at this address.
+ * @param align
+ *   If not NULL, the alignement constraint for this field is stored
+ *   at this address.
+ * @return
+ *   The offset of this field in the mbuf structure, or -1 on error
+ *   (rte_errno is set).
+ */
+__rte_experimental
+int rte_mbuf_dynfield_lookup(const char *name, size_t *size, size_t *align);
+
+/**
+ * Register a dynamic flag in the mbuf structure.
+ *
+ * @param name
+ *   A string identifying the dynamic flag. External applications or
+ *   libraries must not define identifers prefixed with "rte_", which
+ *   are reserved for standard features.
+ * @return
+ *   The number of the reserved bit, or -1 on error (rte_errno is set).
+ */
+__rte_experimental
+int rte_mbuf_dynflag_register(const char *name);
+
+/**
+ * Lookup for a registered dynamic mbuf flag.
+ *
+ * @param name
+ *   A string identifying the dynamic flag.
+ * @return
+ *   The offset of this flag in the mbuf structure, or -1 on error
+ *   (rte_errno is set).
+ */
+__rte_experimental
+int rte_mbuf_dynflag_lookup(const char *name);
+
+/**
+ * Helper macro to access to a dynamic field.
+ */
+#define RTE_MBUF_DYNFIELD(m, offset, type) ((type)((char *)(m) + (offset)))
+
+/**
+ * Maximum length of the dynamic field or flag string.
+ */
+#define RTE_MBUF_DYN_NAMESIZE 32
+
+#endif
diff --git a/lib/librte_mbuf/rte_mbuf_version.map b/lib/librte_mbuf/rte_mbuf_version.map
index 2662a37bf..a98310570 100644
--- a/lib/librte_mbuf/rte_mbuf_version.map
+++ b/lib/librte_mbuf/rte_mbuf_version.map
@@ -50,4 +50,8 @@ EXPERIMENTAL {
 	global:
 
 	rte_mbuf_check;
+	rte_mbuf_dynfield_lookup;
+	rte_mbuf_dynfield_register;
+	rte_mbuf_dynflag_lookup;
+	rte_mbuf_dynflag_register;
 } DPDK_18.08;
-- 
2.11.0


^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH] doc: deprecation notice for change of ether struct alignment
  2019-07-09 14:59  0% ` Stephen Hemminger
@ 2019-07-09 15:02  0%   ` Bruce Richardson
  0 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2019-07-09 15:02 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev, thomas, olivier.matz

On Tue, Jul 09, 2019 at 07:59:53AM -0700, Stephen Hemminger wrote:
> On Tue,  9 Jul 2019 15:58:36 +0100
> Bruce Richardson <bruce.richardson@intel.com> wrote:
> 
> > The ethernet address structure alignment will be changed to 2B alignment in
> > 19.11. Flag this to users.
> > 
> > Impact is expected to be minimal for this change since ethernet addresses
> > are generally 2B aligned anyway.
> > 
> > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > ---
> >  doc/guides/rel_notes/deprecation.rst | 5 +++++
> >  1 file changed, 5 insertions(+)
> > 
> > diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
> > index a7796f49b..7a04b9b09 100644
> > --- a/doc/guides/rel_notes/deprecation.rst
> > +++ b/doc/guides/rel_notes/deprecation.rst
> > @@ -11,6 +11,11 @@ API and ABI deprecation notices are to be posted here.
> >  Deprecation Notices
> >  -------------------
> >  
> > +* net: The alignment of the ethernet address structure in DPDK,
> > +  ``rte_ether_addr`` will be increased to two, i.e. 16-bit aligned, in the
> > +  19.11 release. This will only affect any data structures where an ethernet
> > +  address is currently aligned on a single byte boundary.
> > +
> >  * meson: The minimum supported version of meson for configuring and building
> >    DPDK will be increased to v0.47.1 (from 0.41) from DPDK 19.05 onwards. For
> >    those users with a version earlier than 0.47.1, an updated copy of meson
> 
> We should also take the packed off of ether_header and ether_addr.
> Packed is meaningless on ether_addr anyway.

Agreed. However, I don't think that needs to be called out here as it's a
code change with zero impact. The user-impacting change is the alignment
one.

/Bruce

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] doc: deprecation notice for change of ether struct alignment
  2019-07-09 14:58  5% [dpdk-dev] [PATCH] doc: deprecation notice for change of ether struct alignment Bruce Richardson
@ 2019-07-09 14:59  0% ` Stephen Hemminger
  2019-07-09 15:02  0%   ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Stephen Hemminger @ 2019-07-09 14:59 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev, thomas, olivier.matz

On Tue,  9 Jul 2019 15:58:36 +0100
Bruce Richardson <bruce.richardson@intel.com> wrote:

> The ethernet address structure alignment will be changed to 2B alignment in
> 19.11. Flag this to users.
> 
> Impact is expected to be minimal for this change since ethernet addresses
> are generally 2B aligned anyway.
> 
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> ---
>  doc/guides/rel_notes/deprecation.rst | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
> index a7796f49b..7a04b9b09 100644
> --- a/doc/guides/rel_notes/deprecation.rst
> +++ b/doc/guides/rel_notes/deprecation.rst
> @@ -11,6 +11,11 @@ API and ABI deprecation notices are to be posted here.
>  Deprecation Notices
>  -------------------
>  
> +* net: The alignment of the ethernet address structure in DPDK,
> +  ``rte_ether_addr`` will be increased to two, i.e. 16-bit aligned, in the
> +  19.11 release. This will only affect any data structures where an ethernet
> +  address is currently aligned on a single byte boundary.
> +
>  * meson: The minimum supported version of meson for configuring and building
>    DPDK will be increased to v0.47.1 (from 0.41) from DPDK 19.05 onwards. For
>    those users with a version earlier than 0.47.1, an updated copy of meson

We should also take the packed off of ether_header and ether_addr.
Packed is meaningless on ether_addr anyway.

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH] doc: deprecation notice for change of ether struct alignment
@ 2019-07-09 14:58  5% Bruce Richardson
  2019-07-09 14:59  0% ` Stephen Hemminger
  0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2019-07-09 14:58 UTC (permalink / raw)
  To: dev; +Cc: thomas, stephen, olivier.matz, Bruce Richardson

The ethernet address structure alignment will be changed to 2B alignment in
19.11. Flag this to users.

Impact is expected to be minimal for this change since ethernet addresses
are generally 2B aligned anyway.

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

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index a7796f49b..7a04b9b09 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -11,6 +11,11 @@ API and ABI deprecation notices are to be posted here.
 Deprecation Notices
 -------------------
 
+* net: The alignment of the ethernet address structure in DPDK,
+  ``rte_ether_addr`` will be increased to two, i.e. 16-bit aligned, in the
+  19.11 release. This will only affect any data structures where an ethernet
+  address is currently aligned on a single byte boundary.
+
 * meson: The minimum supported version of meson for configuring and building
   DPDK will be increased to v0.47.1 (from 0.41) from DPDK 19.05 onwards. For
   those users with a version earlier than 0.47.1, an updated copy of meson
-- 
2.21.0


^ permalink raw reply	[relevance 5%]

* Re: [dpdk-dev] [PATCH v2] devtools: better freebsd support
  2019-07-05 13:58  6% ` [dpdk-dev] [PATCH v2] " Olivier Matz
@ 2019-07-09 11:05  0%   ` Musatescu, Flavia
  0 siblings, 0 replies; 200+ results
From: Musatescu, Flavia @ 2019-07-09 11:05 UTC (permalink / raw)
  To: Olivier Matz, dev; +Cc: Thomas Monjalon, David Marchand, Bruce Richardson


On 05/07/2019 14:58, Olivier Matz wrote:
> - As "readlink -e" and "readlink -m" do not exist on freebsd,
>    use "readlink -f", it should not have any impact in these cases.
> - "sed -ri" is invalid on freebsd and should be replaced by
>    "sed -ri=''"
> - Use gmake instead of make.
>
> This fixes the following command:
>    SYSDIR=/usr/src/sys ./devtools/test-build.sh \
>      -j4 x86_64-native-freebsd-gcc
>
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> ---
>
> v2:
> - remove sed_ri() function and use 'sed -ri=""' as suggested by Bruce
>
>   devtools/check-dup-includes.sh |  2 +-
>   devtools/checkpatches.sh       |  8 ++--
>   devtools/get-maintainer.sh     |  2 +-
>   devtools/load-devel-config     |  4 +-
>   devtools/test-build.sh         | 94 ++++++++++++++++++++++--------------------
>   devtools/validate-abi.sh       |  2 +-
>   6 files changed, 58 insertions(+), 54 deletions(-)
>
> diff --git a/devtools/check-dup-includes.sh b/devtools/check-dup-includes.sh
> index e4c2748c6..591599949 100755
> --- a/devtools/check-dup-includes.sh
> +++ b/devtools/check-dup-includes.sh
> @@ -5,7 +5,7 @@
>   # Check C files in git repository for duplicated includes.
>   # Usage: devtools/check-dup-includes.sh [directory]
>   
> -dir=${1:-$(dirname $(readlink -m $0))/..}
> +dir=${1:-$(dirname $(readlink -f $0))/..}
>   cd $dir
>   
>   # speed up by ignoring Unicode details
> diff --git a/devtools/checkpatches.sh b/devtools/checkpatches.sh
> index 560e6ce93..8e2beee16 100755
> --- a/devtools/checkpatches.sh
> +++ b/devtools/checkpatches.sh
> @@ -7,9 +7,9 @@
>   # - DPDK_CHECKPATCH_CODESPELL
>   # - DPDK_CHECKPATCH_LINE_LENGTH
>   # - DPDK_CHECKPATCH_OPTIONS
> -. $(dirname $(readlink -e $0))/load-devel-config
> +. $(dirname $(readlink -f $0))/load-devel-config
>   
> -VALIDATE_NEW_API=$(dirname $(readlink -e $0))/check-symbol-change.sh
> +VALIDATE_NEW_API=$(dirname $(readlink -f $0))/check-symbol-change.sh
>   
>   # Enable codespell by default. This can be overwritten from a config file.
>   # Codespell can also be enabled by setting DPDK_CHECKPATCH_CODESPELL to a valid path
> @@ -66,7 +66,7 @@ check_forbidden_additions() { # <patch>
>   		-v EXPRESSIONS="rte_panic\\\( rte_exit\\\(" \
>   		-v RET_ON_FAIL=1 \
>   		-v MESSAGE='Using rte_panic/rte_exit' \
> -		-f $(dirname $(readlink -e $0))/check-forbidden-tokens.awk \
> +		-f $(dirname $(readlink -f $0))/check-forbidden-tokens.awk \
>   		"$1" || res=1
>   
>   	# svg figures must be included with wildcard extension
> @@ -75,7 +75,7 @@ check_forbidden_additions() { # <patch>
>   		-v EXPRESSIONS='::[[:space:]]*[^[:space:]]*\\.svg' \
>   		-v RET_ON_FAIL=1 \
>   		-v MESSAGE='Using explicit .svg extension instead of .*' \
> -		-f $(dirname $(readlink -e $0))/check-forbidden-tokens.awk \
> +		-f $(dirname $(readlink -f $0))/check-forbidden-tokens.awk \
>   		"$1" || res=1
>   
>   	return $res
> diff --git a/devtools/get-maintainer.sh b/devtools/get-maintainer.sh
> index b9160486a..85740f5af 100755
> --- a/devtools/get-maintainer.sh
> +++ b/devtools/get-maintainer.sh
> @@ -5,7 +5,7 @@
>   
>   # Load config options:
>   # - DPDK_GETMAINTAINER_PATH
> -. $(dirname $(readlink -e $0))/load-devel-config
> +. $(dirname $(readlink -f $0))/load-devel-config
>   
>   options="--no-git-fallback"
>   options="$options --no-rolestats"
> diff --git a/devtools/load-devel-config b/devtools/load-devel-config
> index 4f43cb352..380c79db4 100644
> --- a/devtools/load-devel-config
> +++ b/devtools/load-devel-config
> @@ -6,7 +6,7 @@ test ! -r /etc/dpdk/devel.config ||
>   test ! -r ~/.config/dpdk/devel.config ||
>           . ~/.config/dpdk/devel.config
>   # from local file
> -test ! -r $(dirname $(readlink -m $0))/../.develconfig ||
> -        . $(dirname $(readlink -m $0))/../.develconfig
> +test ! -r $(dirname $(readlink -f $0))/../.develconfig ||
> +        . $(dirname $(readlink -f $0))/../.develconfig
>   
>   # The config files must export variables in the shell style
> diff --git a/devtools/test-build.sh b/devtools/test-build.sh
> index 9b50bf73d..22d409bb0 100755
> --- a/devtools/test-build.sh
> +++ b/devtools/test-build.sh
> @@ -28,7 +28,7 @@ default_path=$PATH
>   # - LIBSSO_SNOW3G_PATH
>   # - LIBSSO_KASUMI_PATH
>   # - LIBSSO_ZUC_PATH
> -. $(dirname $(readlink -e $0))/load-devel-config
> +. $(dirname $(readlink -f $0))/load-devel-config
>   
>   print_usage () {
>   	echo "usage: $(basename $0) [-h] [-jX] [-s] [config1 [config2] ...]]"
> @@ -57,6 +57,10 @@ print_help () {
>   	END_OF_HELP
>   }
>   
> +[ -z $MAKE ] && command -v gmake > /dev/null && MAKE=gmake
> +[ -z $MAKE ] && command -v make > /dev/null && MAKE=make
> +[ -z $MAKE ] && echo "Cannot find make or gmake" && exit 1
> +
>   J=$DPDK_MAKE_JOBS
>   short=false
>   unset verbose
> @@ -90,7 +94,7 @@ trap "signal=INT ; trap - INT ; kill -INT $$" INT
>   # notify result on exit
>   trap on_exit EXIT
>   
> -cd $(dirname $(readlink -m $0))/..
> +cd $(dirname $(readlink -f $0))/..
>   
>   reset_env ()
>   {
> @@ -127,83 +131,83 @@ config () # <directory> <target> <options>
>   	fi
>   	if [ ! -e $1/.config ] || $reconfig ; then
>   		echo "================== Configure $1"
> -		make T=$2 O=$1 config
> +		${MAKE} T=$2 O=$1 config
>   
>   		echo 'Customize configuration'
>   		# Built-in options (lowercase)
>   		! echo $3 | grep -q '+default' || \
> -		sed -ri 's,(RTE_MACHINE=")native,\1default,' $1/.config
> +		sed -ri="" 's,(RTE_MACHINE=")native,\1default,' $1/.config
>   		echo $3 | grep -q '+next' || \
> -		sed -ri           's,(NEXT_ABI=)y,\1n,' $1/.config
> +		sed -ri=""           's,(NEXT_ABI=)y,\1n,' $1/.config
>   		! echo $3 | grep -q '+shared' || \
> -		sed -ri         's,(SHARED_LIB=)n,\1y,' $1/.config
> +		sed -ri=""         's,(SHARED_LIB=)n,\1y,' $1/.config
>   		! echo $3 | grep -q '+debug' || ( \
> -		sed -ri  's,(RTE_LOG_DP_LEVEL=).*,\1RTE_LOG_DEBUG,' $1/.config
> -		sed -ri           's,(_DEBUG.*=)n,\1y,' $1/.config
> -		sed -ri            's,(_STAT.*=)n,\1y,' $1/.config
> -		sed -ri 's,(TEST_PMD_RECORD_.*=)n,\1y,' $1/.config )
> +		sed -ri=""  's,(RTE_LOG_DP_LEVEL=).*,\1RTE_LOG_DEBUG,' $1/.config
> +		sed -ri=""           's,(_DEBUG.*=)n,\1y,' $1/.config
> +		sed -ri=""            's,(_STAT.*=)n,\1y,' $1/.config
> +		sed -ri="" 's,(TEST_PMD_RECORD_.*=)n,\1y,' $1/.config )
>   
>   		# Automatic configuration
>   		test "$DPDK_DEP_NUMA" != n || \
> -		sed -ri             's,(NUMA.*=)y,\1n,' $1/.config
> -		sed -ri    's,(LIBRTE_IEEE1588=)n,\1y,' $1/.config
> -		sed -ri             's,(BYPASS=)n,\1y,' $1/.config
> +		sed -ri=""             's,(NUMA.*=)y,\1n,' $1/.config
> +		sed -ri=""    's,(LIBRTE_IEEE1588=)n,\1y,' $1/.config
> +		sed -ri=""             's,(BYPASS=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_ARCHIVE" != y || \
> -		sed -ri       's,(RESOURCE_TAR=)n,\1y,' $1/.config
> +		sed -ri=""       's,(RESOURCE_TAR=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_ISAL" != y || \
> -		sed -ri           's,(PMD_ISAL=)n,\1y,' $1/.config
> +		sed -ri=""           's,(PMD_ISAL=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_MLX" != y || \
> -		sed -ri           's,(MLX._PMD=)n,\1y,' $1/.config
> +		sed -ri=""           's,(MLX._PMD=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_SZE" != y || \
> -		sed -ri       's,(PMD_SZEDATA2=)n,\1y,' $1/.config
> +		sed -ri=""       's,(PMD_SZEDATA2=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_ZLIB" != y || \
> -		sed -ri          's,(BNX2X_PMD=)n,\1y,' $1/.config
> +		sed -ri=""          's,(BNX2X_PMD=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_ZLIB" != y || \
> -		sed -ri           's,(PMD_ZLIB=)n,\1y,' $1/.config
> +		sed -ri=""           's,(PMD_ZLIB=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_ZLIB" != y || \
> -		sed -ri   's,(COMPRESSDEV_TEST=)n,\1y,' $1/.config
> +		sed -ri=""   's,(COMPRESSDEV_TEST=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_PCAP" != y || \
> -		sed -ri               's,(PCAP=)n,\1y,' $1/.config
> +		sed -ri=""               's,(PCAP=)n,\1y,' $1/.config
>   		test -z "$ARMV8_CRYPTO_LIB_PATH" || \
> -		sed -ri   's,(PMD_ARMV8_CRYPTO=)n,\1y,' $1/.config
> +		sed -ri=""   's,(PMD_ARMV8_CRYPTO=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_IPSEC_MB" != y || \
> -		sed -ri       's,(PMD_AESNI_MB=)n,\1y,' $1/.config
> +		sed -ri=""       's,(PMD_AESNI_MB=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_IPSEC_MB" != y || \
> -		sed -ri      's,(PMD_AESNI_GCM=)n,\1y,' $1/.config
> +		sed -ri=""      's,(PMD_AESNI_GCM=)n,\1y,' $1/.config
>   		test -z "$LIBSSO_SNOW3G_PATH" || \
> -		sed -ri         's,(PMD_SNOW3G=)n,\1y,' $1/.config
> +		sed -ri=""         's,(PMD_SNOW3G=)n,\1y,' $1/.config
>   		test -z "$LIBSSO_KASUMI_PATH" || \
> -		sed -ri         's,(PMD_KASUMI=)n,\1y,' $1/.config
> +		sed -ri=""         's,(PMD_KASUMI=)n,\1y,' $1/.config
>   		test -z "$LIBSSO_ZUC_PATH" || \
> -		sed -ri            's,(PMD_ZUC=)n,\1y,' $1/.config
> +		sed -ri=""            's,(PMD_ZUC=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_SSL" != y || \
> -		sed -ri            's,(PMD_CCP=)n,\1y,' $1/.config
> +		sed -ri=""            's,(PMD_CCP=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_SSL" != y || \
> -		sed -ri        's,(PMD_OPENSSL=)n,\1y,' $1/.config
> +		sed -ri=""        's,(PMD_OPENSSL=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_SSL" != y || \
> -		sed -ri            's,(QAT_SYM=)n,\1y,' $1/.config
> +		sed -ri=""            's,(QAT_SYM=)n,\1y,' $1/.config
>   		test -z "$FLEXRAN_SDK" || \
> -		sed -ri     's,(BBDEV_TURBO_SW=)n,\1y,' $1/.config
> -		sed -ri           's,(SCHED_.*=)n,\1y,' $1/.config
> +		sed -ri=""     's,(BBDEV_TURBO_SW=)n,\1y,' $1/.config
> +		sed -ri=""           's,(SCHED_.*=)n,\1y,' $1/.config
>   		test -z "$LIBMUSDK_PATH" || \
> -		sed -ri   's,(PMD_MVSAM_CRYPTO=)n,\1y,' $1/.config
> +		sed -ri=""   's,(PMD_MVSAM_CRYPTO=)n,\1y,' $1/.config
>   		test -z "$LIBMUSDK_PATH" || \
> -		sed -ri          's,(MVPP2_PMD=)n,\1y,' $1/.config
> +		sed -ri=""          's,(MVPP2_PMD=)n,\1y,' $1/.config
>   		test -z "$LIBMUSDK_PATH" || \
> -		sed -ri         's,(MVNETA_PMD=)n,\1y,' $1/.config
> +		sed -ri=""         's,(MVNETA_PMD=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_ELF" != y || \
> -		sed -ri            's,(BPF_ELF=)n,\1y,' $1/.config
> +		sed -ri=""            's,(BPF_ELF=)n,\1y,' $1/.config
>   		test "$DPDK_DEP_JSON" != y || \
> -		sed -ri          's,(TELEMETRY=)n,\1y,' $1/.config
> +		sed -ri=""          's,(TELEMETRY=)n,\1y,' $1/.config
>   		build_config_hook $1 $2 $3
>   
>   		# Explicit enabler/disabler (uppercase)
>   		for option in $(echo $3 | sed 's,[~+], &,g') ; do
>   			pattern=$(echo $option | cut -c2-)
>   			if echo $option | grep -q '^~' ; then
> -				sed -ri "s,($pattern=)y,\1n," $1/.config
> +				sed -ri="" "s,($pattern=)y,\1n," $1/.config
>   			elif echo $option | grep -q '^+' ; then
> -				sed -ri "s,($pattern=)n,\1y," $1/.config
> +				sed -ri="" "s,($pattern=)n,\1y," $1/.config
>   			fi
>   		done
>   	fi
> @@ -220,22 +224,22 @@ for conf in $configs ; do
>   	# reload config with DPDK_TARGET set
>   	DPDK_TARGET=$target
>   	reset_env
> -	. $(dirname $(readlink -e $0))/load-devel-config
> +	. $(dirname $(readlink -f $0))/load-devel-config
>   
>   	options=$(echo $conf | sed 's,[^~+]*,,')
>   	dir=$conf
>   	config $dir $target $options
>   
>   	echo "================== Build $dir"
> -	make -j$J EXTRA_CFLAGS="$maxerr $DPDK_DEP_CFLAGS" \
> +	${MAKE} -j$J EXTRA_CFLAGS="$maxerr $DPDK_DEP_CFLAGS" \
>   		EXTRA_LDFLAGS="$DPDK_DEP_LDFLAGS" $verbose O=$dir
>   	! $short || break
>   	echo "================== Build examples for $dir"
>   	export RTE_SDK=$(pwd)
>   	export RTE_TARGET=$dir
> -	make -j$J -sC examples \
> +	${MAKE} -j$J -sC examples \
>   		EXTRA_LDFLAGS="$DPDK_DEP_LDFLAGS" $verbose \
> -		O=$(readlink -m $dir/examples)
> +		O=$(readlink -f $dir/examples)
>   	unset RTE_TARGET
>   	echo "################## $dir done."
>   	unset dir
> @@ -244,9 +248,9 @@ done
>   if ! $short ; then
>   	mkdir -p .check
>   	echo "================== Build doxygen HTML API"
> -	make doc-api-html >/dev/null 2>.check/doc.txt
> +	${MAKE} doc-api-html >/dev/null 2>.check/doc.txt
>   	echo "================== Build sphinx HTML guides"
> -	make doc-guides-html >/dev/null 2>>.check/doc.txt
> +	${MAKE} doc-guides-html >/dev/null 2>>.check/doc.txt
>   	echo "================== Check docs"
>   	diff -u /dev/null .check/doc.txt
>   fi
> diff --git a/devtools/validate-abi.sh b/devtools/validate-abi.sh
> index 138436d93..f64e19d38 100755
> --- a/devtools/validate-abi.sh
> +++ b/devtools/validate-abi.sh
> @@ -181,7 +181,7 @@ case "${dst}" in
>   	/*) ;;
>   	*) dst=${PWD}/${dst} ;;
>   esac
> -dpdkroot=$(readlink -e $(dirname $0)/..)
> +dpdkroot=$(readlink -f $(dirname $0)/..)
>   
>   if [ -e "${dst}" -a "$force" = 0 ]; then
>   	echo "The ${dst} directory is not empty. Remove it, use another


The example applications are being built in a wrong location when using 
the test-build.sh script on FreeBSD 
(“/app_name/x86_64-native-freebsd-gcc/” instead of 
“$(dpdk_path)/x86_64-native-freebsd-gcc/examples/app_name/x86_64-native-freebsd-gcc/”. 


The output build directory for the example applications is specified by 
O=$(readlink -f $dir/examples) variable inside the test-build.sh script. 
On FreeBSD "readlink -f" prints nothing when the file path doesn't 
exist, so the output build directory for each application ends up being 
configured to "/./app_name/x86_64-native-freebsd-gcc" (this is done 
inside the mk/rte.extsubdir.mk file).

A possible solution for this could be to modify the output directory to 
O=$(readlink -f $dir)/examples.

Best Regards,

Flavia



^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2 1/1] fbarray: get fbarrays from containerized secondary
  @ 2019-07-09 10:26  4%           ` Burakov, Anatoly
  0 siblings, 0 replies; 200+ results
From: Burakov, Anatoly @ 2019-07-09 10:26 UTC (permalink / raw)
  To: Yasufumi Ogawa; +Cc: dev, stable

On 09-Jul-19 11:24 AM, Burakov, Anatoly wrote:
> On 09-Jul-19 11:22 AM, Yasufumi Ogawa wrote:
>> Hi Anatoly,
>>
>> On 2019/07/05 17:53, Burakov, Anatoly wrote:
>>> On 16-Apr-19 4:43 AM, ogawa.yasufumi@lab.ntt.co.jp wrote:
>>>> From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
>>>>
>>>> In secondary_msl_create_walk(), it creates a file for fbarrays with its
>>>> PID for reserving unique name among secondary processes. However, it
>>>> does not work if secondary is run as app container because each of
>>>> containerized secondary has PID 1. To reserve unique name, use hostname
>>>> instead of PID if the value is 1.
>>>>
>>>> Cc: stable@dpdk.org
>>>>
>>>> Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
>>>> ---
>>>
>>> I'm not too well versed in containers - is this hostname 1) always 
>>> set, and 2) always unique?
>> For docker, 1) hostname is always set. 2) The hostname is decided as 
>> short form of container ID, so it might not be unique even though very 
>> low possibility.
>>
>> I found that we can get whole container ID in `/proc/self/cgroup` as 
>> discussed [1]. I think using hostname is reasonable way without 
>> running many secondary processes. However, it might be better to use 
>> 64 digits full container ID instead of 12 digits short ID if ensure 
>> uniqueness strongly. What do yo think?
>>
>> [1] 
>> https://forums.docker.com/t/get-a-containers-full-id-from-inside-of-itself/37237 
>>
> 
> I think it's better to err on the side of caution and guarantee better 
> uniqueness. This code will get into an LTS and will be used for years to 
> come :)
> 

...however, i think a full 64-digit ID won't even fit into the fbarray 
filename, as i believe it's limited to something like 64 chars. Perhaps 
hostname would be enough after all... or we can increase fbarray name 
length - that would require ABI breakage but the ABI is already broken 
in this release, so it's OK i think.

-- 
Thanks,
Anatoly

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [RFC] ethdev: support input set change by RSS action
  2019-07-09  5:41  3%       ` Zhang, Qi Z
@ 2019-07-09  8:19  0%         ` Jerin Jacob Kollanukkaran
  0 siblings, 0 replies; 200+ results
From: Jerin Jacob Kollanukkaran @ 2019-07-09  8:19 UTC (permalink / raw)
  To: Zhang, Qi Z, Adrien Mazarguil
  Cc: Su, Simei, Wu, Jingjing, Xing, Beilei, Yang, Qiming, dev

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Zhang, Qi Z
> Sent: Tuesday, July 9, 2019 11:11 AM
> To: Adrien Mazarguil <adrien.mazarguil@6wind.com>
> Cc: Su, Simei <simei.su@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>;
> Xing, Beilei <beilei.xing@intel.com>; Yang, Qiming <qiming.yang@intel.com>;
> dev@dpdk.org
> Subject: Re: [dpdk-dev] [RFC] ethdev: support input set change by RSS action
> > Right, I had symmetric Toeplitz in mind and wondered what would happen
> > when users would not select the required fields. I guess the PMD would
> > have to reject unsupported combinations.
> >
> > > anything I missed, would you share more insight?
> >
> > No, that answers the question, thanks.
> >
> > Now what about my suggestion below? In short: extending ETH_RSS_*
> > assuming there's enough bits left in there, instead of adding a whole
> > new framework and breaking ABI in the process.
> 
> Since the hardware can support any combination of input set (not just 5
> tuples), we'd like to make it more generic.
> Those will be some pain due to ABI break, but we think its worth for long
> term.

# IMO, The decided method should be compatible with normal RSS(without rte_flow) case 
as well(Currently is struct rte_eth_conf.rx_adv_conf.rss_conf.rss_hf used 
in the dev_configure()) as from HW perspective it will be same  the HW block which does 
both.
# From Marvell HW point of view, We can support any combination of input set.
But it is more of a micro code(i.e need to first provide the list protocol supported to HW)
and then use it latter. So, I think, extending the ETH_RSS_* would be more portable
approach __without loosing__ the functionality. Since there is around 40 bits are left, I think
more standard protocol can fit in the 40 bits. 





^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC] ethdev: support input set change by RSS action
  2019-07-04 14:08  3%     ` Adrien Mazarguil
@ 2019-07-09  5:41  3%       ` Zhang, Qi Z
  2019-07-09  8:19  0%         ` Jerin Jacob Kollanukkaran
  0 siblings, 1 reply; 200+ results
From: Zhang, Qi Z @ 2019-07-09  5:41 UTC (permalink / raw)
  To: Adrien Mazarguil; +Cc: Su, Simei, Wu, Jingjing, Xing, Beilei, Yang, Qiming, dev

Hi Adrien:

> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Thursday, July 4, 2019 10:09 PM
> To: Zhang, Qi Z <qi.z.zhang@intel.com>
> Cc: Su, Simei <simei.su@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>;
> Xing, Beilei <beilei.xing@intel.com>; Yang, Qiming <qiming.yang@intel.com>;
> dev@dpdk.org
> Subject: Re: [dpdk-dev] [RFC] ethdev: support input set change by RSS action
> 
> On Thu, Jul 04, 2019 at 01:55:14PM +0000, Zhang, Qi Z wrote:
> >
> >
> > > -----Original Message-----
> > > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > > Sent: Thursday, July 4, 2019 5:07 PM
> > > To: Su, Simei <simei.su@intel.com>
> > > Cc: Zhang, Qi Z <qi.z.zhang@intel.com>; Wu, Jingjing
> > > <jingjing.wu@intel.com>; Xing, Beilei <beilei.xing@intel.com>; Yang,
> > > Qiming <qiming.yang@intel.com>; dev@dpdk.org
> > > Subject: Re: [dpdk-dev] [RFC] ethdev: support input set change by
> > > RSS action
> > >
> > > On Thu, Jul 04, 2019 at 12:47:09PM +0800, simei wrote:
> > > > From: Simei Su <simei.su@intel.com>
> > > >
> > > > This RFC introduces inputset structure to rte_flow_action_rss to
> > > > support input set specific configuration by rte_flow RSS action.
> > > >
> > > > We can give an testpmd command line example to make it more clear.
> > > >
> > > > For example, below flow selects the l4 port as inputset for any
> > > > eth/ipv4/tcp packet: #flow create 0 ingress pattern eth / ipv4 /
> > > > tcp / end actions rss inputset tcp src mask 0xffff dst mask 0xffff
> > > > /end
> > > >
> > > > Signed-off-by: Simei Su <simei.su@intel.com>
> > > > ---
> > > >  lib/librte_ethdev/rte_flow.h | 3 +++
> > > >  1 file changed, 3 insertions(+)
> > > >
> > > > diff --git a/lib/librte_ethdev/rte_flow.h
> > > > b/lib/librte_ethdev/rte_flow.h index f3a8fb1..2a455b6 100644
> > > > --- a/lib/librte_ethdev/rte_flow.h
> > > > +++ b/lib/librte_ethdev/rte_flow.h
> > > > @@ -1796,6 +1796,9 @@ struct rte_flow_action_rss {
> > > >  	uint32_t queue_num; /**< Number of entries in @p queue. */
> > > >  	const uint8_t *key; /**< Hash key. */
> > > >  	const uint16_t *queue; /**< Queue indices to use. */
> > > > +	struct rte_flow_item *inputset; /** Provide more specific
> > > > +inputset
> > > configuration.
> > > > +					 * ignore spec, only mask.
> > > > +					 */
> > > >  };
> > > >
> > > >  /**
> > >
> > > To make sure I understand, is this kind of a more flexible version
> > > of rte_flow_action_rss.types?
> >
> > Yes
> > >
> > > For instance while specifying .types = ETH_RSS_IPV4 normally covers
> > > both source and destination addresses, does this approach enable
> > > users to perform RSS on source IP only?
> >
> > Yes, .it is the case to select any subset of 5 tuples or even tunnel
> > header's id for hash
> >
> > > In which case, what value does the Toeplitz algorithm assume for the
> > > destination, 0x0? (note: must be documented)
> >
> > My understanding is src/dst pair is only required for a symmetric case
> > But for Toeplitz, it is just a hash function, it process a serial of
> > data with specific algorithm, have no idea about which part is src and dst , So
> for ip src only with Toeplitz, dst is not required to be a placeholder..
> 
> Right, I had symmetric Toeplitz in mind and wondered what would happen
> when users would not select the required fields. I guess the PMD would have
> to reject unsupported combinations.
> 
> > anything I missed, would you share more insight?
> 
> No, that answers the question, thanks.
> 
> Now what about my suggestion below? In short: extending ETH_RSS_*
> assuming there's enough bits left in there, instead of adding a whole new
> framework and breaking ABI in the process.

Since the hardware can support any combination of input set (not just 5 tuples), we'd like to make it more generic.
Those will be some pain due to ABI break, but we think its worth for long term.

Thanks
Qi

> 
> > > My opinion is that, unless you know of a hardware which can perform
> > > RSS on random bytes of a packet, this approach is a bit overkill at this
> point.
> > >
> > > How about simply adding the needed ETH_RSS_* definitions (e.g.
> > > ETH_RSS_IPV4_(SRC|DST))? How many are needed?
> > >
> > > There are currently 20 used bits and struct
> > > rte_flow_action_rss.types is 64-bit wide. I'm sure we can manage
> > > something without harming the ABI. Even better, you wouldn't need a
> deprecation notice.
> > >
> > > If you use the suggested approach, please update testpmd and its
> > > documentation as part of the same patch, thanks.
> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v8 4/7] app/test-compress-perf: add benchmark test case
  @ 2019-07-08 18:16  3%   ` Artur Trybula
  0 siblings, 0 replies; 200+ results
From: Artur Trybula @ 2019-07-08 18:16 UTC (permalink / raw)
  To: dev, fiona.trahe, shallyv, adamx.dybkowski, arturx.trybula, akhil.goyal
  Cc: Tomasz Jozwiak, Tomasz Jozwiak

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 13608 bytes --]

From: Tomasz Jozwiak <tomaszx.jozwiak@intel.com>

This patch adds a benchmark part to
compression-perf-tool as a separate test case, which can be
executed multi-threaded.
Also updates release notes.

Signed-off-by: Tomasz Jozwiak <tjozwiakgm@gmail.com>
Signed-off-by: Tomasz Jozwiak <tomaszx.jozwiak@intel.com>
Acked-by: Artur Trybula <arturx.trybula@intel.com>
---
 app/test-compress-perf/Makefile               |   1 +
 .../comp_perf_test_benchmark.c                | 140 +++++++++++++-----
 .../comp_perf_test_benchmark.h                |  25 +++-
 app/test-compress-perf/main.c                 |   1 +
 app/test-compress-perf/meson.build            |   1 +
 doc/guides/rel_notes/release_19_08.rst        |  27 ++++
 6 files changed, 157 insertions(+), 38 deletions(-)

diff --git a/app/test-compress-perf/Makefile b/app/test-compress-perf/Makefile
index f54d9a4dd..d1a6820e6 100644
--- a/app/test-compress-perf/Makefile
+++ b/app/test-compress-perf/Makefile
@@ -13,6 +13,7 @@ CFLAGS += -O3
 SRCS-y := main.c
 SRCS-y += comp_perf_options_parse.c
 SRCS-y += comp_perf_test_verify.c
+SRCS-y += comp_perf_test_benchmark.c
 SRCS-y += comp_perf_test_common.c
 
 include $(RTE_SDK)/mk/rte.app.mk
diff --git a/app/test-compress-perf/comp_perf_test_benchmark.c b/app/test-compress-perf/comp_perf_test_benchmark.c
index 5752906b3..e0f852bf0 100644
--- a/app/test-compress-perf/comp_perf_test_benchmark.c
+++ b/app/test-compress-perf/comp_perf_test_benchmark.c
@@ -10,11 +10,46 @@
 
 #include "comp_perf_test_benchmark.h"
 
+void
+cperf_benchmark_test_destructor(void *arg)
+{
+	if (arg) {
+		comp_perf_free_memory(
+				&((struct cperf_benchmark_ctx *)arg)->ver.mem);
+		rte_free(arg);
+	}
+}
+
+void *
+cperf_benchmark_test_constructor(uint8_t dev_id, uint16_t qp_id,
+		struct comp_test_data *options)
+{
+	struct cperf_benchmark_ctx *ctx = NULL;
+
+	ctx = rte_malloc(NULL, sizeof(struct cperf_benchmark_ctx), 0);
+
+	if (ctx == NULL)
+		return NULL;
+
+	ctx->ver.mem.dev_id = dev_id;
+	ctx->ver.mem.qp_id = qp_id;
+	ctx->ver.options = options;
+	ctx->ver.silent = 1; /* ver. part will be silent */
+
+	if (!comp_perf_allocate_memory(ctx->ver.options, &ctx->ver.mem)
+			&& !prepare_bufs(ctx->ver.options, &ctx->ver.mem))
+		return ctx;
+
+	cperf_benchmark_test_destructor(ctx);
+	return NULL;
+}
+
 static int
-main_loop(struct comp_test_data *test_data, uint8_t level,
-			enum rte_comp_xform_type type)
+main_loop(struct cperf_benchmark_ctx *ctx, enum rte_comp_xform_type type)
 {
-	uint8_t dev_id = test_data->cdev_id;
+	struct comp_test_data *test_data = ctx->ver.options;
+	struct cperf_mem_resources *mem = &ctx->ver.mem;
+	uint8_t dev_id = mem->dev_id;
 	uint32_t i, iter, num_iter;
 	struct rte_comp_op **ops, **deq_ops;
 	void *priv_xform = NULL;
@@ -31,7 +66,7 @@ main_loop(struct comp_test_data *test_data, uint8_t level,
 	}
 
 	ops = rte_zmalloc_socket(NULL,
-		2 * test_data->total_bufs * sizeof(struct rte_comp_op *),
+		2 * mem->total_bufs * sizeof(struct rte_comp_op *),
 		0, rte_socket_id());
 
 	if (ops == NULL) {
@@ -40,7 +75,7 @@ main_loop(struct comp_test_data *test_data, uint8_t level,
 		return -1;
 	}
 
-	deq_ops = &ops[test_data->total_bufs];
+	deq_ops = &ops[mem->total_bufs];
 
 	if (type == RTE_COMP_COMPRESS) {
 		xform = (struct rte_comp_xform) {
@@ -48,14 +83,14 @@ main_loop(struct comp_test_data *test_data, uint8_t level,
 			.compress = {
 				.algo = RTE_COMP_ALGO_DEFLATE,
 				.deflate.huffman = test_data->huffman_enc,
-				.level = level,
+				.level = test_data->level,
 				.window_size = test_data->window_sz,
 				.chksum = RTE_COMP_CHECKSUM_NONE,
 				.hash_algo = RTE_COMP_HASH_ALGO_NONE
 			}
 		};
-		input_bufs = test_data->decomp_bufs;
-		output_bufs = test_data->comp_bufs;
+		input_bufs = mem->decomp_bufs;
+		output_bufs = mem->comp_bufs;
 		out_seg_sz = test_data->out_seg_sz;
 	} else {
 		xform = (struct rte_comp_xform) {
@@ -67,8 +102,8 @@ main_loop(struct comp_test_data *test_data, uint8_t level,
 				.hash_algo = RTE_COMP_HASH_ALGO_NONE
 			}
 		};
-		input_bufs = test_data->comp_bufs;
-		output_bufs = test_data->decomp_bufs;
+		input_bufs = mem->comp_bufs;
+		output_bufs = mem->decomp_bufs;
 		out_seg_sz = test_data->seg_sz;
 	}
 
@@ -82,13 +117,13 @@ main_loop(struct comp_test_data *test_data, uint8_t level,
 
 	uint64_t tsc_start, tsc_end, tsc_duration;
 
-	tsc_start = tsc_end = tsc_duration = 0;
-	tsc_start = rte_rdtsc();
 	num_iter = test_data->num_iter;
+	tsc_start = tsc_end = tsc_duration = 0;
+	tsc_start = rte_rdtsc_precise();
 
 	for (iter = 0; iter < num_iter; iter++) {
-		uint32_t total_ops = test_data->total_bufs;
-		uint32_t remaining_ops = test_data->total_bufs;
+		uint32_t total_ops = mem->total_bufs;
+		uint32_t remaining_ops = mem->total_bufs;
 		uint32_t total_deq_ops = 0;
 		uint32_t total_enq_ops = 0;
 		uint16_t ops_unused = 0;
@@ -113,7 +148,7 @@ main_loop(struct comp_test_data *test_data, uint8_t level,
 
 			/* Allocate compression operations */
 			if (ops_needed && !rte_comp_op_bulk_alloc(
-						test_data->op_pool,
+						mem->op_pool,
 						&ops[ops_unused],
 						ops_needed)) {
 				RTE_LOG(ERR, USER1,
@@ -149,7 +184,8 @@ main_loop(struct comp_test_data *test_data, uint8_t level,
 				ops[op_id]->private_xform = priv_xform;
 			}
 
-			num_enq = rte_compressdev_enqueue_burst(dev_id, 0, ops,
+			num_enq = rte_compressdev_enqueue_burst(dev_id,
+								mem->qp_id, ops,
 								num_ops);
 			if (num_enq == 0) {
 				struct rte_compressdev_stats stats;
@@ -165,7 +201,8 @@ main_loop(struct comp_test_data *test_data, uint8_t level,
 			remaining_ops -= num_enq;
 			total_enq_ops += num_enq;
 
-			num_deq = rte_compressdev_dequeue_burst(dev_id, 0,
+			num_deq = rte_compressdev_dequeue_burst(dev_id,
+							   mem->qp_id,
 							   deq_ops,
 							   test_data->burst_sz);
 			total_deq_ops += num_deq;
@@ -177,7 +214,7 @@ main_loop(struct comp_test_data *test_data, uint8_t level,
 					if (op->status !=
 						RTE_COMP_OP_STATUS_SUCCESS) {
 						RTE_LOG(ERR, USER1,
-							"Some operations were not successful\n");
+				       "Some operations were not successful\n");
 						goto end;
 					}
 
@@ -198,15 +235,17 @@ main_loop(struct comp_test_data *test_data, uint8_t level,
 					}
 				}
 			}
-			rte_mempool_put_bulk(test_data->op_pool,
+			rte_mempool_put_bulk(mem->op_pool,
 					     (void **)deq_ops, num_deq);
 			allocated -= num_deq;
 		}
 
 		/* Dequeue the last operations */
 		while (total_deq_ops < total_ops) {
-			num_deq = rte_compressdev_dequeue_burst(dev_id, 0,
-						deq_ops, test_data->burst_sz);
+			num_deq = rte_compressdev_dequeue_burst(dev_id,
+							   mem->qp_id,
+							   deq_ops,
+							   test_data->burst_sz);
 			if (num_deq == 0) {
 				struct rte_compressdev_stats stats;
 
@@ -226,7 +265,7 @@ main_loop(struct comp_test_data *test_data, uint8_t level,
 					if (op->status !=
 						RTE_COMP_OP_STATUS_SUCCESS) {
 						RTE_LOG(ERR, USER1,
-							"Some operations were not successful\n");
+				       "Some operations were not successful\n");
 						goto end;
 					}
 
@@ -247,65 +286,92 @@ main_loop(struct comp_test_data *test_data, uint8_t level,
 					}
 				}
 			}
-			rte_mempool_put_bulk(test_data->op_pool,
+			rte_mempool_put_bulk(mem->op_pool,
 					     (void **)deq_ops, num_deq);
 			allocated -= num_deq;
 		}
 	}
 
-	tsc_end = rte_rdtsc();
+	tsc_end = rte_rdtsc_precise();
 	tsc_duration = tsc_end - tsc_start;
 
 	if (type == RTE_COMP_COMPRESS)
-		test_data->comp_tsc_duration[level] =
+		ctx->comp_tsc_duration[test_data->level] =
 				tsc_duration / num_iter;
 	else
-		test_data->decomp_tsc_duration[level] =
+		ctx->decomp_tsc_duration[test_data->level] =
 				tsc_duration / num_iter;
 
 end:
-	rte_mempool_put_bulk(test_data->op_pool, (void **)ops, allocated);
+	rte_mempool_put_bulk(mem->op_pool, (void **)ops, allocated);
 	rte_compressdev_private_xform_free(dev_id, priv_xform);
 	rte_free(ops);
 	return res;
 }
 
 int
-cperf_benchmark(struct comp_test_data *test_data, uint8_t level)
+cperf_benchmark_test_runner(void *test_ctx)
 {
+	struct cperf_benchmark_ctx *ctx = test_ctx;
+	struct comp_test_data *test_data = ctx->ver.options;
+	uint32_t lcore = rte_lcore_id();
+	static rte_atomic16_t display_once = RTE_ATOMIC16_INIT(0);
+
+	ctx->ver.mem.lcore_id = lcore;
 	int i, ret = EXIT_SUCCESS;
 
+	/*
+	 * First the verification part is needed
+	 */
+	if (cperf_verify_test_runner(&ctx->ver)) {
+		ret =  EXIT_FAILURE;
+		goto end;
+	}
+
 	/*
 	 * Run the tests twice, discarding the first performance
 	 * results, before the cache is warmed up
 	 */
 	for (i = 0; i < 2; i++) {
-		if (main_loop(test_data, level, RTE_COMP_COMPRESS) < 0) {
+		if (main_loop(ctx, RTE_COMP_COMPRESS) < 0) {
 			ret = EXIT_FAILURE;
 			goto end;
 		}
 	}
 
 	for (i = 0; i < 2; i++) {
-		if (main_loop(test_data, level, RTE_COMP_DECOMPRESS) < 0) {
+		if (main_loop(ctx, RTE_COMP_DECOMPRESS) < 0) {
 			ret = EXIT_FAILURE;
 			goto end;
 		}
 	}
 
-	test_data->comp_tsc_byte =
-			(double)(test_data->comp_tsc_duration[level]) /
+	ctx->comp_tsc_byte =
+			(double)(ctx->comp_tsc_duration[test_data->level]) /
 					test_data->input_data_sz;
 
-	test_data->decomp_tsc_byte =
-			(double)(test_data->decomp_tsc_duration[level]) /
+	ctx->decomp_tsc_byte =
+			(double)(ctx->decomp_tsc_duration[test_data->level]) /
 					test_data->input_data_sz;
 
-	test_data->comp_gbps = rte_get_tsc_hz() / test_data->comp_tsc_byte * 8 /
+	ctx->comp_gbps = rte_get_tsc_hz() / ctx->comp_tsc_byte * 8 /
+			1000000000;
+
+	ctx->decomp_gbps = rte_get_tsc_hz() / ctx->decomp_tsc_byte * 8 /
 			1000000000;
 
-	test_data->decomp_gbps = rte_get_tsc_hz() / test_data->decomp_tsc_byte
-			* 8 / 1000000000;
+	if (rte_atomic16_test_and_set(&display_once)) {
+		printf("%12s%6s%12s%17s%15s%16s\n",
+			"lcore id", "Level", "Comp size", "Comp ratio [%]",
+			"Comp [Gbps]", "Decomp [Gbps]");
+	}
+
+	printf("%12u%6u%12zu%17.2f%15.2f%16.2f\n",
+		ctx->ver.mem.lcore_id,
+		test_data->level, ctx->ver.comp_data_sz, ctx->ver.ratio,
+		ctx->comp_gbps,
+		ctx->decomp_gbps);
+
 end:
 	return ret;
 }
diff --git a/app/test-compress-perf/comp_perf_test_benchmark.h b/app/test-compress-perf/comp_perf_test_benchmark.h
index b193445a3..d9b2694b8 100644
--- a/app/test-compress-perf/comp_perf_test_benchmark.h
+++ b/app/test-compress-perf/comp_perf_test_benchmark.h
@@ -5,9 +5,32 @@
 #ifndef _COMP_PERF_TEST_BENCHMARK_
 #define _COMP_PERF_TEST_BENCHMARK_
 
+#include <stdint.h>
+
 #include "comp_perf_options.h"
+#include "comp_perf_test_common.h"
+#include "comp_perf_test_verify.h"
+
+struct cperf_benchmark_ctx {
+	struct cperf_verify_ctx ver;
+
+	/* Store TSC duration for all levels (including level 0) */
+	uint64_t comp_tsc_duration[RTE_COMP_LEVEL_MAX + 1];
+	uint64_t decomp_tsc_duration[RTE_COMP_LEVEL_MAX + 1];
+	double comp_gbps;
+	double decomp_gbps;
+	double comp_tsc_byte;
+	double decomp_tsc_byte;
+};
+
+void
+cperf_benchmark_test_destructor(void *arg);
 
 int
-cperf_benchmark(struct comp_test_data *test_data, uint8_t level);
+cperf_benchmark_test_runner(void *test_ctx);
+
+void *
+cperf_benchmark_test_constructor(uint8_t dev_id, uint16_t qp_id,
+		struct comp_test_data *options);
 
 #endif
diff --git a/app/test-compress-perf/main.c b/app/test-compress-perf/main.c
index 51ca9f5b7..dd6ef9a6d 100644
--- a/app/test-compress-perf/main.c
+++ b/app/test-compress-perf/main.c
@@ -9,6 +9,7 @@
 
 #include "comp_perf_options.h"
 #include "comp_perf_test_verify.h"
+#include "comp_perf_test_benchmark.h"
 #include "comp_perf.h"
 #include "comp_perf_test_common.h"
 
diff --git a/app/test-compress-perf/meson.build b/app/test-compress-perf/meson.build
index c6246e503..1136f04bc 100644
--- a/app/test-compress-perf/meson.build
+++ b/app/test-compress-perf/meson.build
@@ -5,5 +5,6 @@ allow_experimental_apis = true
 sources = files('comp_perf_options_parse.c',
 		'main.c',
 		'comp_perf_test_verify.c',
+		'comp_perf_test_benchmark.c',
 		'comp_perf_test_common.c')
 deps = ['compressdev']
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 8480112b9..ed7f6e250 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -190,6 +190,29 @@ New Features
   Added telemetry mode to l3fwd-power application to report
   application level busyness, empty and full polls of rte_eth_rx_burst().
 
+* **Updated the QuickAssist Technology (QAT) symmetric crypto PMD.**
+
+  Added support for digest-encrypted cases where digest is appended
+  to the data.
+
+* **Added a FPGA_LTE_FEC bbdev PMD.**
+
+  Added the new ``fpga_lte_fec`` bbdev driver for the Intel® FPGA PAC
+  (Programmable  Acceleration Card) N3000.  See the
+  :doc:`../bbdevs/fpga_lte_fec` BBDEV guide for more details on this new driver.
+
+* **Updated TURBO_SW bbdev PMD.**
+
+  Updated the ``turbo_sw`` bbdev driver with changes including:
+
+  * Added option to build the driver with or without dependency of external
+    SDK libraries.
+  * Added support for 5GNR encode/decode operations.
+
+* **Updated test-compress-perf tool application.**
+
+  Added multiple cores feature to compression perf tool application.
+
 
 Removed Items
 -------------
@@ -259,6 +282,10 @@ API Changes
   offload flag from the library. The application must set this flag if it is
   supported by the platform and application wishes to use it.
 
+* cryptodev: the ``uint8_t *data`` member of ``key`` structure in the xforms
+  structure (``rte_crypto_cipher_xform``, ``rte_crypto_auth_xform``, and
+  ``rte_crypto_aead_xform``) have been changed to ``const uint8_t *data``.
+
 
 ABI Changes
 -----------
-- 
2.17.1


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v4 1/3] lib/librte_ip_frag: remove IP checkum offload flag
  2019-07-08  4:32  9% ` [dpdk-dev] [PATCH v4 1/3] lib/librte_ip_frag: remove IP checkum offload flag jerinj
@ 2019-07-08  9:07  3%   ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2019-07-08  9:07 UTC (permalink / raw)
  To: jerinj, Sunil Kumar Kori
  Cc: dev, John McNamara, Marko Kovacevic, Konstantin Ananyev

08/07/2019 06:32, jerinj@marvell.com:
> From: Sunil Kumar Kori <skori@marvell.com>
> 
> Currently PKT_TX_IP_CKSUM is being set into mbuf->ol_flags
> during fragmentation and reassemble operation implicitly.
> Because of this, application is forced to use checksum offload
> whether it is supported by platform or not.
> 
> Also documentation does not provide any expected value of ol_flags
> in returned mbuf (reassembled or fragmented) so application will never
> come to know that which offloads are enabled. So transmission may be failed
> for the platforms which does not support checksum offload.
> 
> Also, IPv6 does not contain any checksum field in header so setting
> mbuf->ol_flags with PKT_TX_IP_CKSUM is itself invalid.
> 
> So removing mentioned flag from the library.
> 
> Signed-off-by: Sunil Kumar Kori <skori@marvell.com>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

Applied, thanks

PS: I move the release notes from ABI to API changes
as it is an API behaviour change.



^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v4] net/i40e: i40e get link status update from ipn3ke
  @ 2019-07-08  7:27  3%   ` Zhang, Qi Z
  0 siblings, 0 replies; 200+ results
From: Zhang, Qi Z @ 2019-07-08  7:27 UTC (permalink / raw)
  To: Pei, Andy, dev
  Cc: Wu, Jingjing, Xing, Beilei, Yigit, Ferruh, Xu, Rosen, Ye,
	Xiaolong, Zhang, Roy Fan, stable



> -----Original Message-----
> From: Pei, Andy
> Sent: Monday, July 8, 2019 11:03 AM
> To: dev@dpdk.org
> Cc: Pei, Andy <andy.pei@intel.com>; Zhang, Qi Z <qi.z.zhang@intel.com>; Wu,
> Jingjing <jingjing.wu@intel.com>; Xing, Beilei <beilei.xing@intel.com>; Yigit,
> Ferruh <ferruh.yigit@intel.com>; Xu, Rosen <rosen.xu@intel.com>; Ye,
> Xiaolong <xiaolong.ye@intel.com>; Zhang, Roy Fan
> <roy.fan.zhang@intel.com>; stable@dpdk.org
> Subject: [PATCH v4] net/i40e: i40e get link status update from ipn3ke
> 
> Add switch_mode argument for i40e PF to specify the specific FPGA that i40e
> PF is connected to. i40e PF get link status update via the connected FPGA.
> Add switch_ethdev to rte_eth_dev_data to track the bind switch device.
> Try to bind i40e pf to switch device when i40e device is probed. If it fail to find
> correct switch device, bind will occur again when update i40e device link
> status.
> 
> Signed-off-by: Andy Pei <andy.pei@intel.com>
.....
> diff --git a/lib/librte_ethdev/rte_ethdev_core.h
> b/lib/librte_ethdev/rte_ethdev_core.h
> index 2922d5b..62adc5c 100644
> --- a/lib/librte_ethdev/rte_ethdev_core.h
> +++ b/lib/librte_ethdev/rte_ethdev_core.h
> @@ -635,6 +635,10 @@ struct rte_eth_dev_data {
>  			/**< Switch-specific identifier.
>  			 *   Valid if RTE_ETH_DEV_REPRESENTOR in dev_flags.
>  			 */
> +	struct rte_eth_dev *switch_ethdev;
> +			/* point to switch_ethdev specific by "switch_mode" in
> +			 * devargs
> +			 */
>  } __rte_cache_aligned;

Missing below comment in previous review.

No need to add new field in rte_eth_dev_data to break ABI, you can just add to i40e specific structure: i40e_pf.

> 
>  /**
> --
> 1.8.3.1


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH] [v1]vhost: support inflight share memory protocol feature
  2019-07-05  8:47  3% ` Maxime Coquelin
@ 2019-07-08  7:23  0%   ` Yu, Jin
  0 siblings, 0 replies; 200+ results
From: Yu, Jin @ 2019-07-08  7:23 UTC (permalink / raw)
  To: Maxime Coquelin, dev; +Cc: Liu, Changpeng, LinLi, XunNi, YuZhang, Bie, Tiwei

> From: Maxime Coquelin [mailto:maxime.coquelin@redhat.com]
> Sent: Friday, July 5, 2019 4:47 PM
> To: Yu, Jin <jin.yu@intel.com>; dev@dpdk.org
> Cc: Liu, Changpeng <changpeng.liu@intel.com>; LinLi <lilin24@baidu.com>;
> XunNi <nixun@baidu.com>; YuZhang <zhangyu31@baidu.com>; Bie, Tiwei
> <tiwei.bie@intel.com>
> Subject: Re: [dpdk-dev] [PATCH] [v1]vhost: support inflight share memory
> protocol feature
> 
> Hi Jin,
> 
> On 6/26/19 6:38 PM, JinYu wrote:
> > This patch introduces two new messages VHOST_USER_GET_INFLIGHT_FD
> and
> > VHOST_USER_SET_INFLIGHT_FD to support transferring a shared buffer
> > between qemu and backend.
> >
> > Firstly, qemu uses VHOST_USER_GET_INFLIGHT_FD to get the shared buffer
> > from backend. Then qemu should send it back through
> > VHOST_USER_SET_INFLIGHT_FD each time we start vhost-user.
> >
> > This shared buffer is used to process inflight I/O when backend
> > reconnect.
> >
> > Signed-off-by: LinLi <lilin24@baidu.com>
> > Signed-off-by: XunNi <nixun@baidu.com>
> > Signed-off-by: YuZhang <zhangyu31@baidu.com>
> > Signed-off-by: JinYu <jin.yu@intel.com>
> > ---
> > V1 - specify the APIs are split-ring only
> > ---
> >   lib/librte_vhost/rte_vhost.h           |  99 +++++++++
> >   lib/librte_vhost/rte_vhost_version.map |   4 +
> >   lib/librte_vhost/vhost.c               | 135 ++++++++++++
> >   lib/librte_vhost/vhost.h               |  12 +
> >   lib/librte_vhost/vhost_user.c          | 292 +++++++++++++++++++++++++
> >   lib/librte_vhost/vhost_user.h          |  13 +-
> >   6 files changed, 554 insertions(+), 1 deletion(-)
> >
> > diff --git a/lib/librte_vhost/rte_vhost.h
> > b/lib/librte_vhost/rte_vhost.h index 0226b3eff..c9959c15a 100644
> > --- a/lib/librte_vhost/rte_vhost.h
> > +++ b/lib/librte_vhost/rte_vhost.h
> > @@ -71,6 +71,10 @@ extern "C" {
> >   #define VHOST_USER_PROTOCOL_F_HOST_NOTIFIER 11
> >   #endif
> >
> > +#ifndef VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD
> > +#define VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD 12 #endif
> > +
> >   /** Indicate whether protocol features negotiation is supported. */
> >   #ifndef VHOST_USER_F_PROTOCOL_FEATURES
> >   #define VHOST_USER_F_PROTOCOL_FEATURES	30
> > @@ -98,12 +102,41 @@ struct rte_vhost_memory {
> >   	struct rte_vhost_mem_region regions[];
> >   };
> >
> > +struct inflight_desc_split {
> > +	uint8_t		inflight;
> > +	uint8_t		padding[5];
> > +	uint16_t	next;
> > +	uint64_t	counter;
> > +};
> > +
> > +struct inflight_info_split {
> > +	uint64_t		features;
> > +	uint16_t		version;
> > +	uint16_t		desc_num;
> > +	uint16_t		last_inflight_io;
> > +	uint16_t		used_idx;
> > +	struct inflight_desc_split desc[0];
> > +};
> > +
> > +struct resubmit_desc {
> > +	uint16_t index;
> > +	uint64_t counter;
> > +};
> > +
> > +struct resubmit_info {
> > +	struct resubmit_desc	*resubmit_list;
> > +	uint16_t		resubmit_num;
> > +};
> > +
> >   struct rte_vhost_vring {
> >   	struct vring_desc	*desc;
> >   	struct vring_avail	*avail;
> >   	struct vring_used	*used;
> >   	uint64_t		log_guest_addr;
> >
> > +	struct inflight_info_split *inflight;
> > +	struct resubmit_info	*resubmit_inflight;
> > +
> 
> This is breaking the ABI, and discussing with Tiwei, we think it could be
> avoided by defining its own structure of inflight and inflight resubmit
> pointers. More below:
So you means that define a new struct such as struct rte_vhost_inflight_ring?
> 
> >   	/** Deprecated, use rte_vhost_vring_call() instead. */
> >   	int			callfd;
> >
> > @@ -603,6 +636,22 @@ uint16_t rte_vhost_dequeue_burst(int vid,
> uint16_t queue_id,
> >    */
> >   int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
> >
> > +/**
> > + * Get guest vring info, including the vring address, vring size, inflight, etc.
> > + *
> > + * @param vid
> > + *  vhost device ID
> > + * @param vring_idx
> > + *  vring index
> > + * @param vring
> > + *  the structure to hold the requested vring info
> > + * @return
> > + *  0 on success, -1 on failure
> > + */
> > +int __rte_experimental
> > +rte_vhost_get_vhost_vring_with_inflight_split(int vid, uint16_t vring_idx,
> > +			      struct rte_vhost_vring *vring);
> 
> Here a new API is introduced to get vting info with inflight.
> It could be just changed to get only the inflight info. It means the caller would
> first call rte_vhost_get_vhost_vring() and then the new function, which I
> guess may be renamed to:
> 
> rte_vhost_get_vhost_vring_inflight_split
Got It.
> 
> Other than that, the patch looks good to me.
> 
> (Next time, please run get_maintainer.sh script so that all the maintainers
> are in Cc:).
> 
> Thanks,
> Maxime
Thanks Maxime, also I will submit an example code of vhost_user_blk  which support the inflight feature.
It can show how these APIs work.

Thanks
Jin


^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v4 1/3] lib/librte_ip_frag: remove IP checkum offload flag
  @ 2019-07-08  4:32  9% ` jerinj
  2019-07-08  9:07  3%   ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: jerinj @ 2019-07-08  4:32 UTC (permalink / raw)
  To: dev, John McNamara, Marko Kovacevic, Konstantin Ananyev
  Cc: thomas, Sunil Kumar Kori

From: Sunil Kumar Kori <skori@marvell.com>

Currently PKT_TX_IP_CKSUM is being set into mbuf->ol_flags
during fragmentation and reassemble operation implicitly.
Because of this, application is forced to use checksum offload
whether it is supported by platform or not.

Also documentation does not provide any expected value of ol_flags
in returned mbuf (reassembled or fragmented) so application will never
come to know that which offloads are enabled. So transmission may be failed
for the platforms which does not support checksum offload.

Also, IPv6 does not contain any checksum field in header so setting
mbuf->ol_flags with PKT_TX_IP_CKSUM is itself invalid.

So removing mentioned flag from the library.

Signed-off-by: Sunil Kumar Kori <skori@marvell.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
v4:
- Update release notes

---
 doc/guides/rel_notes/release_19_08.rst   | 15 +++++++++++++++
 lib/librte_ip_frag/rte_ipv4_reassembly.c |  3 ---
 lib/librte_ip_frag/rte_ipv6_reassembly.c |  3 ---
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index defbc5e27..ad9cbf4a2 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -281,6 +281,21 @@ ABI Changes
 * bbdev: New operations and parameters added to support new 5GNR operations.
   The bbdev ABI is still kept experimental.
 
+* ip_fragmentation: IP fragmentation library converts input mbuf into fragments
+  using input MTU size via ``rte_ipv4_fragment_packet`` interface.
+  Once fragmentation is done, each ``mbuf->ol_flags`` are set to enable IP
+  checksum H/W offload irrespective of the platform capability.
+  Cleared IP checksum H/W offload flag from the library. The application must
+  set this flag if it is supported by the platform and application wishes to
+  use it.
+
+* ip_reassembly: IP reassembly library converts the list of fragments into a
+  reassembled packet via ``rte_ipv4_frag_reassemble_packet`` interface.
+  Once reassembly is done, ``mbuf->ol_flags`` are set to enable IP checksum H/W
+  offload irrespective of the platform capability. Cleared IP checksum H/W
+  offload flag from the library. The application must set this flag if it is
+  supported by the platform and application wishes to use it.
+
 
 Shared Library Versions
 -----------------------
diff --git a/lib/librte_ip_frag/rte_ipv4_reassembly.c b/lib/librte_ip_frag/rte_ipv4_reassembly.c
index b7b92ed28..1dda8aca0 100644
--- a/lib/librte_ip_frag/rte_ipv4_reassembly.c
+++ b/lib/librte_ip_frag/rte_ipv4_reassembly.c
@@ -66,9 +66,6 @@ ipv4_frag_reassemble(struct ip_frag_pkt *fp)
 	m = fp->frags[IP_FIRST_FRAG_IDX].mb;
 	fp->frags[IP_FIRST_FRAG_IDX].mb = NULL;
 
-	/* update mbuf fields for reassembled packet. */
-	m->ol_flags |= PKT_TX_IP_CKSUM;
-
 	/* update ipv4 header for the reassembled packet */
 	ip_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, m->l2_len);
 
diff --git a/lib/librte_ip_frag/rte_ipv6_reassembly.c b/lib/librte_ip_frag/rte_ipv6_reassembly.c
index 169b01a5d..ad0105518 100644
--- a/lib/librte_ip_frag/rte_ipv6_reassembly.c
+++ b/lib/librte_ip_frag/rte_ipv6_reassembly.c
@@ -89,9 +89,6 @@ ipv6_frag_reassemble(struct ip_frag_pkt *fp)
 	m = fp->frags[IP_FIRST_FRAG_IDX].mb;
 	fp->frags[IP_FIRST_FRAG_IDX].mb = NULL;
 
-	/* update mbuf fields for reassembled packet. */
-	m->ol_flags |= PKT_TX_IP_CKSUM;
-
 	/* update ipv6 header for the reassembled datagram */
 	ip_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *, m->l2_len);
 
-- 
2.22.0


^ permalink raw reply	[relevance 9%]

* [dpdk-dev] [PATCH v5 9/9] eal: prevent different primary/secondary process versions
      2019-07-05 17:26  7%   ` [dpdk-dev] [PATCH v5 4/9] " Anatoly Burakov
@ 2019-07-05 17:26  3%   ` Anatoly Burakov
  2 siblings, 0 replies; 200+ results
From: Anatoly Burakov @ 2019-07-05 17:26 UTC (permalink / raw)
  To: dev; +Cc: Bruce Richardson, thomas, david.marchand, stephen

Currently, nothing stops DPDK to attempt to run primary and
secondary processes while having different versions. This
can lead to all sorts of weird behavior and makes it harder
to maintain compatibility without breaking ABI every once
in a while.

Fix it by explicitly disallowing running different DPDK
versions as primary and secondary processes.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
Acked-by: David Marchand <david.marchand@redhat.com>
---
 lib/librte_eal/common/eal_common_mcfg.c | 15 +++++++++++++++
 lib/librte_eal/common/eal_memcfg.h      |  6 ++++++
 lib/librte_eal/freebsd/eal/eal.c        |  4 ++++
 lib/librte_eal/linux/eal/eal.c          |  4 ++++
 4 files changed, 29 insertions(+)

diff --git a/lib/librte_eal/common/eal_common_mcfg.c b/lib/librte_eal/common/eal_common_mcfg.c
index fe8d2b726..1825d9083 100644
--- a/lib/librte_eal/common/eal_common_mcfg.c
+++ b/lib/librte_eal/common/eal_common_mcfg.c
@@ -4,6 +4,7 @@
 
 #include <rte_config.h>
 #include <rte_eal_memconfig.h>
+#include <rte_version.h>
 
 #include "eal_internal_cfg.h"
 #include "eal_memcfg.h"
@@ -31,6 +32,18 @@ eal_mcfg_wait_complete(void)
 		rte_pause();
 }
 
+int
+eal_mcfg_check_version(void)
+{
+	struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+
+	/* check if version from memconfig matches compiled in macro */
+	if (mcfg->version != RTE_VERSION)
+		return -1;
+
+	return 0;
+}
+
 void
 eal_mcfg_update_internal(void)
 {
@@ -47,6 +60,8 @@ eal_mcfg_update_from_internal(void)
 
 	mcfg->legacy_mem = internal_config.legacy_mem;
 	mcfg->single_file_segments = internal_config.single_file_segments;
+	/* record current DPDK version */
+	mcfg->version = RTE_VERSION;
 }
 
 void
diff --git a/lib/librte_eal/common/eal_memcfg.h b/lib/librte_eal/common/eal_memcfg.h
index 573233896..030f903ad 100644
--- a/lib/librte_eal/common/eal_memcfg.h
+++ b/lib/librte_eal/common/eal_memcfg.h
@@ -19,6 +19,8 @@
  */
 struct rte_mem_config {
 	volatile uint32_t magic;   /**< Magic number - sanity check. */
+	uint32_t version;
+	/**< Prevent secondary processes using different DPDK versions. */
 
 	/* memory topology */
 	uint32_t nchannel;    /**< Number of channels (0 if unknown). */
@@ -81,6 +83,10 @@ eal_mcfg_update_from_internal(void);
 void
 eal_mcfg_wait_complete(void);
 
+/* check if DPDK version of current process matches one stored in the config */
+int
+eal_mcfg_check_version(void);
+
 /* set mem config as complete */
 void
 eal_mcfg_complete(void);
diff --git a/lib/librte_eal/freebsd/eal/eal.c b/lib/librte_eal/freebsd/eal/eal.c
index ec1650c43..139d021d9 100644
--- a/lib/librte_eal/freebsd/eal/eal.c
+++ b/lib/librte_eal/freebsd/eal/eal.c
@@ -385,6 +385,10 @@ rte_config_init(void)
 		if (rte_eal_config_attach() < 0)
 			return -1;
 		eal_mcfg_wait_complete();
+		if (eal_mcfg_check_version() < 0) {
+			RTE_LOG(ERR, EAL, "Primary and secondary process DPDK version mismatch\n");
+			return -1;
+		}
 		if (rte_eal_config_reattach() < 0)
 			return -1;
 		eal_mcfg_update_internal();
diff --git a/lib/librte_eal/linux/eal/eal.c b/lib/librte_eal/linux/eal/eal.c
index 445d72f0c..47ac3b025 100644
--- a/lib/librte_eal/linux/eal/eal.c
+++ b/lib/librte_eal/linux/eal/eal.c
@@ -489,6 +489,10 @@ rte_config_init(void)
 		if (rte_eal_config_attach() < 0)
 			return -1;
 		eal_mcfg_wait_complete();
+		if (eal_mcfg_check_version() < 0) {
+			RTE_LOG(ERR, EAL, "Primary and secondary process DPDK version mismatch\n");
+			return -1;
+		}
 		if (rte_eal_config_reattach() < 0)
 			return -1;
 		eal_mcfg_update_internal();
-- 
2.17.1

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v5 4/9] eal: hide shared memory config
    @ 2019-07-05 17:26  7%   ` Anatoly Burakov
  2019-07-05 17:26  3%   ` [dpdk-dev] [PATCH v5 9/9] eal: prevent different primary/secondary process versions Anatoly Burakov
  2 siblings, 0 replies; 200+ results
From: Anatoly Burakov @ 2019-07-05 17:26 UTC (permalink / raw)
  To: dev
  Cc: Neil Horman, John McNamara, Marko Kovacevic, Konstantin Ananyev,
	David Hunt, Bruce Richardson, Byron Marohn, Pablo de Lara Guarch,
	Yipeng Wang, Sameh Gobriel, Vladimir Medvedkin, Olivier Matz,
	Andrew Rybchenko, Honnappa Nagarahalli, Reshma Pattan, thomas,
	david.marchand, stephen

Now that everything that has ever accessed the shared memory
config is doing so through the public API's, we can make it
internal. Since we're removing quite a few headers from
rte_eal_memconfig.h, we need to add them back in places
where this header is used.

This bumps the ABI, so also change all build files and make
update documentation.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
Acked-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: David Marchand <david.marchand@redhat.com>
---
 app/test/test_fbarray.c                       |  1 +
 app/test/test_memzone.c                       |  1 +
 app/test/test_tailq.c                         |  1 +
 doc/guides/rel_notes/deprecation.rst          |  3 -
 doc/guides/rel_notes/release_19_08.rst        |  8 +-
 drivers/bus/pci/linux/pci_vfio.c              |  1 +
 lib/librte_acl/rte_acl.c                      |  2 +
 lib/librte_distributor/rte_distributor.c      |  1 +
 lib/librte_distributor/rte_distributor_v20.c  |  1 +
 lib/librte_eal/common/eal_common_mcfg.c       |  2 +
 lib/librte_eal/common/eal_common_memory.c     |  1 +
 lib/librte_eal/common/eal_common_memzone.c    |  1 +
 lib/librte_eal/common/eal_common_tailqs.c     |  1 +
 lib/librte_eal/common/eal_memcfg.h            | 80 ++++++++++++++++
 .../common/include/rte_eal_memconfig.h        | 95 +------------------
 lib/librte_eal/common/include/rte_fbarray.h   |  1 -
 lib/librte_eal/common/include/rte_memory.h    | 24 ++++-
 lib/librte_eal/common/malloc_heap.c           |  2 +
 lib/librte_eal/common/malloc_mp.c             |  1 +
 lib/librte_eal/common/rte_malloc.c            |  1 +
 lib/librte_eal/freebsd/eal/Makefile           |  2 +-
 lib/librte_eal/freebsd/eal/eal_memory.c       |  1 +
 lib/librte_eal/linux/eal/Makefile             |  2 +-
 lib/librte_eal/linux/eal/eal.c                |  1 +
 lib/librte_eal/linux/eal/eal_memalloc.c       |  1 +
 lib/librte_eal/linux/eal/eal_memory.c         |  1 +
 lib/librte_eal/linux/eal/eal_vfio.c           |  1 +
 lib/librte_eal/meson.build                    |  2 +-
 lib/librte_efd/rte_efd.c                      |  1 +
 lib/librte_hash/rte_cuckoo_hash.c             |  1 +
 lib/librte_hash/rte_fbk_hash.c                |  1 +
 lib/librte_lpm/rte_lpm.c                      |  1 +
 lib/librte_lpm/rte_lpm6.c                     |  1 +
 lib/librte_member/rte_member.c                |  1 +
 lib/librte_mempool/rte_mempool.c              |  1 +
 lib/librte_rcu/rte_rcu_qsbr.h                 |  1 +
 lib/librte_reorder/rte_reorder.c              |  1 +
 lib/librte_ring/rte_ring.c                    |  1 +
 38 files changed, 148 insertions(+), 101 deletions(-)
 create mode 100644 lib/librte_eal/common/eal_memcfg.h

diff --git a/app/test/test_fbarray.c b/app/test/test_fbarray.c
index d2b041887..a691bf445 100644
--- a/app/test/test_fbarray.c
+++ b/app/test/test_fbarray.c
@@ -2,6 +2,7 @@
  * Copyright(c) 2010-2014 Intel Corporation
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <limits.h>
diff --git a/app/test/test_memzone.c b/app/test/test_memzone.c
index 9fe465e62..7501b63c5 100644
--- a/app/test/test_memzone.c
+++ b/app/test/test_memzone.c
@@ -19,6 +19,7 @@
 #include <rte_errno.h>
 #include <rte_malloc.h>
 #include "../../lib/librte_eal/common/malloc_elem.h"
+#include "../../lib/librte_eal/common/eal_memcfg.h"
 
 #include "test.h"
 
diff --git a/app/test/test_tailq.c b/app/test/test_tailq.c
index a4ecea2d8..7c9b69fdb 100644
--- a/app/test/test_tailq.c
+++ b/app/test/test_tailq.c
@@ -12,6 +12,7 @@
 #include <rte_eal.h>
 #include <rte_eal_memconfig.h>
 #include <rte_string_fns.h>
+#include <rte_tailq.h>
 
 #include "test.h"
 
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index e2721fad6..583217da8 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -23,9 +23,6 @@ Deprecation Notices
 * eal: The function ``rte_eal_remote_launch`` will return new error codes
   after read or write error on the pipe, instead of calling ``rte_panic``.
 
-* eal: the ``rte_mem_config`` struct will be made private to remove it from the
-  externally visible ABI and allow it to be updated in the future.
-
 * eal: both declaring and identifying devices will be streamlined in v18.11.
   New functions will appear to query a specific port from buses, classes of
   device and device drivers. Device declaration will be made coherent with the
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 21934bf01..cc6dfa33f 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -172,6 +172,10 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* The ``rte_mem_config`` structure has been made private. The new accessor
+  ``rte_mcfg_*`` functions were introduced to provide replacement for direct
+  access to the shared mem config.
+
 * The network structures, definitions and functions have
   been prefixed by ``rte_`` to resolve conflicts with libc headers.
 
@@ -201,6 +205,8 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* The ``rte_mem_config`` structure has been made private.
+
 * eventdev: Event based Rx adapter callback
 
   The mbuf pointer array in the event eth Rx adapter callback
@@ -246,7 +252,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_compressdev.so.1
      librte_cryptodev.so.7
      librte_distributor.so.1
-     librte_eal.so.10
+   + librte_eal.so.11
      librte_efd.so.1
      librte_ethdev.so.12
    + librte_eventdev.so.7
diff --git a/drivers/bus/pci/linux/pci_vfio.c b/drivers/bus/pci/linux/pci_vfio.c
index ebf6ccd3c..1ceb1c07b 100644
--- a/drivers/bus/pci/linux/pci_vfio.c
+++ b/drivers/bus/pci/linux/pci_vfio.c
@@ -20,6 +20,7 @@
 #include <rte_eal.h>
 #include <rte_bus.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "eal_filesystem.h"
 
diff --git a/lib/librte_acl/rte_acl.c b/lib/librte_acl/rte_acl.c
index 7ff11d25f..bd7247cc3 100644
--- a/lib/librte_acl/rte_acl.c
+++ b/lib/librte_acl/rte_acl.c
@@ -4,6 +4,8 @@
 
 #include <rte_string_fns.h>
 #include <rte_acl.h>
+#include <rte_tailq.h>
+
 #include "acl.h"
 
 TAILQ_HEAD(rte_acl_list, rte_tailq_entry);
diff --git a/lib/librte_distributor/rte_distributor.c b/lib/librte_distributor/rte_distributor.c
index 9eb78b330..0a3213bbf 100644
--- a/lib/librte_distributor/rte_distributor.c
+++ b/lib/librte_distributor/rte_distributor.c
@@ -14,6 +14,7 @@
 #include <rte_string_fns.h>
 #include <rte_eal_memconfig.h>
 #include <rte_pause.h>
+#include <rte_tailq.h>
 
 #include "rte_distributor_private.h"
 #include "rte_distributor.h"
diff --git a/lib/librte_distributor/rte_distributor_v20.c b/lib/librte_distributor/rte_distributor_v20.c
index 1fc03b971..cdc0969a8 100644
--- a/lib/librte_distributor/rte_distributor_v20.c
+++ b/lib/librte_distributor/rte_distributor_v20.c
@@ -13,6 +13,7 @@
 #include <rte_string_fns.h>
 #include <rte_eal_memconfig.h>
 #include <rte_pause.h>
+#include <rte_tailq.h>
 
 #include "rte_distributor_v20.h"
 #include "rte_distributor_private.h"
diff --git a/lib/librte_eal/common/eal_common_mcfg.c b/lib/librte_eal/common/eal_common_mcfg.c
index ba2bc37b7..337890a61 100644
--- a/lib/librte_eal/common/eal_common_mcfg.c
+++ b/lib/librte_eal/common/eal_common_mcfg.c
@@ -5,6 +5,8 @@
 #include <rte_config.h>
 #include <rte_eal_memconfig.h>
 
+#include "eal_memcfg.h"
+
 void
 rte_mcfg_mem_read_lock(void)
 {
diff --git a/lib/librte_eal/common/eal_common_memory.c b/lib/librte_eal/common/eal_common_memory.c
index fe22b139b..19ea47570 100644
--- a/lib/librte_eal/common/eal_common_memory.c
+++ b/lib/librte_eal/common/eal_common_memory.c
@@ -24,6 +24,7 @@
 #include "eal_memalloc.h"
 #include "eal_private.h"
 #include "eal_internal_cfg.h"
+#include "eal_memcfg.h"
 #include "malloc_heap.h"
 
 /*
diff --git a/lib/librte_eal/common/eal_common_memzone.c b/lib/librte_eal/common/eal_common_memzone.c
index 521ad7ca1..ef6c909cb 100644
--- a/lib/librte_eal/common/eal_common_memzone.c
+++ b/lib/librte_eal/common/eal_common_memzone.c
@@ -24,6 +24,7 @@
 #include "malloc_heap.h"
 #include "malloc_elem.h"
 #include "eal_private.h"
+#include "eal_memcfg.h"
 
 static inline const struct rte_memzone *
 memzone_lookup_thread_unsafe(const char *name)
diff --git a/lib/librte_eal/common/eal_common_tailqs.c b/lib/librte_eal/common/eal_common_tailqs.c
index dc2c13caa..ead06897b 100644
--- a/lib/librte_eal/common/eal_common_tailqs.c
+++ b/lib/librte_eal/common/eal_common_tailqs.c
@@ -23,6 +23,7 @@
 #include <rte_debug.h>
 
 #include "eal_private.h"
+#include "eal_memcfg.h"
 
 TAILQ_HEAD(rte_tailq_elem_head, rte_tailq_elem);
 /* local tailq list */
diff --git a/lib/librte_eal/common/eal_memcfg.h b/lib/librte_eal/common/eal_memcfg.h
new file mode 100644
index 000000000..74f6159c6
--- /dev/null
+++ b/lib/librte_eal/common/eal_memcfg.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef EAL_MEMCFG_H
+#define EAL_MEMCFG_H
+
+#include <rte_config.h>
+#include <rte_eal_memconfig.h>
+#include <rte_malloc_heap.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_pause.h>
+#include <rte_rwlock.h>
+#include <rte_tailq.h>
+
+/**
+ * Memory configuration shared across multiple processes.
+ */
+struct rte_mem_config {
+	volatile uint32_t magic;   /**< Magic number - sanity check. */
+
+	/* memory topology */
+	uint32_t nchannel;    /**< Number of channels (0 if unknown). */
+	uint32_t nrank;       /**< Number of ranks (0 if unknown). */
+
+	/**
+	 * current lock nest order
+	 *  - qlock->mlock (ring/hash/lpm)
+	 *  - mplock->qlock->mlock (mempool)
+	 * Notice:
+	 *  *ALWAYS* obtain qlock first if having to obtain both qlock and mlock
+	 */
+	rte_rwlock_t mlock;   /**< used by memzones for thread safety. */
+	rte_rwlock_t qlock;   /**< used by tailqs for thread safety. */
+	rte_rwlock_t mplock;  /**< used by mempool library for thread safety. */
+
+	rte_rwlock_t memory_hotplug_lock;
+	/**< Indicates whether memory hotplug request is in progress. */
+
+	/* memory segments and zones */
+	struct rte_fbarray memzones; /**< Memzone descriptors. */
+
+	struct rte_memseg_list memsegs[RTE_MAX_MEMSEG_LISTS];
+	/**< List of dynamic arrays holding memsegs */
+
+	struct rte_tailq_head tailq_head[RTE_MAX_TAILQ];
+	/**< Tailqs for objects */
+
+	struct malloc_heap malloc_heaps[RTE_MAX_HEAPS];
+	/**< DPDK malloc heaps */
+
+	int next_socket_id; /**< Next socket ID for external malloc heap */
+
+	/* rte_mem_config has to be mapped at the exact same address in all
+	 * processes, so we need to store it.
+	 */
+	uint64_t mem_cfg_addr; /**< Address of this structure in memory. */
+
+	/* Primary and secondary processes cannot run with different legacy or
+	 * single file segments options, so to avoid having to specify these
+	 * options to all processes, store them in shared config and update the
+	 * internal config at init time.
+	 */
+	uint32_t legacy_mem; /**< stored legacy mem parameter. */
+	uint32_t single_file_segments;
+	/**< stored single file segments parameter. */
+
+	uint8_t dma_maskbits; /**< Keeps the more restricted dma mask. */
+} __attribute__((packed));
+
+static inline void
+rte_eal_mcfg_wait_complete(struct rte_mem_config *mcfg)
+{
+	/* wait until shared mem_config finish initialising */
+	while (mcfg->magic != RTE_MAGIC)
+		rte_pause();
+}
+
+#endif /* EAL_MEMCFG_H */
diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
index 58dcbb96d..dc61a6fed 100644
--- a/lib/librte_eal/common/include/rte_eal_memconfig.h
+++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
@@ -5,101 +5,16 @@
 #ifndef _RTE_EAL_MEMCONFIG_H_
 #define _RTE_EAL_MEMCONFIG_H_
 
-#include <rte_config.h>
-#include <rte_tailq.h>
-#include <rte_memory.h>
-#include <rte_memzone.h>
-#include <rte_malloc_heap.h>
-#include <rte_rwlock.h>
-#include <rte_pause.h>
-#include <rte_fbarray.h>
+/**
+ * @file
+ *
+ * This API allows access to EAL shared memory configuration through an API.
+ */
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/**
- * memseg list is a special case as we need to store a bunch of other data
- * together with the array itself.
- */
-struct rte_memseg_list {
-	RTE_STD_C11
-	union {
-		void *base_va;
-		/**< Base virtual address for this memseg list. */
-		uint64_t addr_64;
-		/**< Makes sure addr is always 64-bits */
-	};
-	uint64_t page_sz; /**< Page size for all memsegs in this list. */
-	int socket_id; /**< Socket ID for all memsegs in this list. */
-	volatile uint32_t version; /**< version number for multiprocess sync. */
-	size_t len; /**< Length of memory area covered by this memseg list. */
-	unsigned int external; /**< 1 if this list points to external memory */
-	struct rte_fbarray memseg_arr;
-};
-
-/**
- * the structure for the memory configuration for the RTE.
- * Used by the rte_config structure. It is separated out, as for multi-process
- * support, the memory details should be shared across instances
- */
-struct rte_mem_config {
-	volatile uint32_t magic;   /**< Magic number - Sanity check. */
-
-	/* memory topology */
-	uint32_t nchannel;    /**< Number of channels (0 if unknown). */
-	uint32_t nrank;       /**< Number of ranks (0 if unknown). */
-
-	/**
-	 * current lock nest order
-	 *  - qlock->mlock (ring/hash/lpm)
-	 *  - mplock->qlock->mlock (mempool)
-	 * Notice:
-	 *  *ALWAYS* obtain qlock first if having to obtain both qlock and mlock
-	 */
-	rte_rwlock_t mlock;   /**< only used by memzone LIB for thread-safe. */
-	rte_rwlock_t qlock;   /**< used for tailq operation for thread safe. */
-	rte_rwlock_t mplock;  /**< only used by mempool LIB for thread-safe. */
-
-	rte_rwlock_t memory_hotplug_lock;
-	/**< indicates whether memory hotplug request is in progress. */
-
-	/* memory segments and zones */
-	struct rte_fbarray memzones; /**< Memzone descriptors. */
-
-	struct rte_memseg_list memsegs[RTE_MAX_MEMSEG_LISTS];
-	/**< list of dynamic arrays holding memsegs */
-
-	struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**< Tailqs for objects */
-
-	/* Heaps of Malloc */
-	struct malloc_heap malloc_heaps[RTE_MAX_HEAPS];
-
-	/* next socket ID for external malloc heap */
-	int next_socket_id;
-
-	/* address of mem_config in primary process. used to map shared config into
-	 * exact same address the primary process maps it.
-	 */
-	uint64_t mem_cfg_addr;
-
-	/* legacy mem and single file segments options are shared */
-	uint32_t legacy_mem;
-	uint32_t single_file_segments;
-
-	/* keeps the more restricted dma mask */
-	uint8_t dma_maskbits;
-} __attribute__((__packed__));
-
-
-inline static void
-rte_eal_mcfg_wait_complete(struct rte_mem_config* mcfg)
-{
-	/* wait until shared mem_config finish initialising */
-	while(mcfg->magic != RTE_MAGIC)
-		rte_pause();
-}
-
 /**
  * Lock the internal EAL shared memory configuration for shared access.
  */
diff --git a/lib/librte_eal/common/include/rte_fbarray.h b/lib/librte_eal/common/include/rte_fbarray.h
index d0af2d8c7..6dccdbec9 100644
--- a/lib/librte_eal/common/include/rte_fbarray.h
+++ b/lib/librte_eal/common/include/rte_fbarray.h
@@ -34,7 +34,6 @@
 extern "C" {
 #endif
 
-#include <stdbool.h>
 #include <stdio.h>
 
 #include <rte_compat.h>
diff --git a/lib/librte_eal/common/include/rte_memory.h b/lib/librte_eal/common/include/rte_memory.h
index 44cbe6fd2..ca34a10c3 100644
--- a/lib/librte_eal/common/include/rte_memory.h
+++ b/lib/librte_eal/common/include/rte_memory.h
@@ -22,9 +22,7 @@ extern "C" {
 #include <rte_common.h>
 #include <rte_compat.h>
 #include <rte_config.h>
-
-/* forward declaration for pointers */
-struct rte_memseg_list;
+#include <rte_fbarray.h>
 
 __extension__
 enum rte_page_sizes {
@@ -104,6 +102,26 @@ struct rte_memseg {
 	uint32_t flags;             /**< Memseg-specific flags */
 } __rte_packed;
 
+/**
+ * memseg list is a special case as we need to store a bunch of other data
+ * together with the array itself.
+ */
+struct rte_memseg_list {
+	RTE_STD_C11
+	union {
+		void *base_va;
+		/**< Base virtual address for this memseg list. */
+		uint64_t addr_64;
+		/**< Makes sure addr is always 64-bits */
+	};
+	uint64_t page_sz; /**< Page size for all memsegs in this list. */
+	int socket_id; /**< Socket ID for all memsegs in this list. */
+	volatile uint32_t version; /**< version number for multiprocess sync. */
+	size_t len; /**< Length of memory area covered by this memseg list. */
+	unsigned int external; /**< 1 if this list points to external memory */
+	struct rte_fbarray memseg_arr;
+};
+
 /**
  * Lock page in physical memory and prevent from swapping.
  *
diff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c
index f1d31de0d..634ca212f 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -20,11 +20,13 @@
 #include <rte_string_fns.h>
 #include <rte_spinlock.h>
 #include <rte_memcpy.h>
+#include <rte_memzone.h>
 #include <rte_atomic.h>
 #include <rte_fbarray.h>
 
 #include "eal_internal_cfg.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 #include "malloc_elem.h"
 #include "malloc_heap.h"
 #include "malloc_mp.h"
diff --git a/lib/librte_eal/common/malloc_mp.c b/lib/librte_eal/common/malloc_mp.c
index 7c6112c4e..1f212f834 100644
--- a/lib/librte_eal/common/malloc_mp.c
+++ b/lib/librte_eal/common/malloc_mp.c
@@ -10,6 +10,7 @@
 #include <rte_string_fns.h>
 
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 
 #include "malloc_elem.h"
 #include "malloc_mp.h"
diff --git a/lib/librte_eal/common/rte_malloc.c b/lib/librte_eal/common/rte_malloc.c
index 2cad7beaa..fecd9a964 100644
--- a/lib/librte_eal/common/rte_malloc.c
+++ b/lib/librte_eal/common/rte_malloc.c
@@ -25,6 +25,7 @@
 #include "malloc_elem.h"
 #include "malloc_heap.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 
 
 /* Free the memory space back to heap */
diff --git a/lib/librte_eal/freebsd/eal/Makefile b/lib/librte_eal/freebsd/eal/Makefile
index eb921275e..89131ea89 100644
--- a/lib/librte_eal/freebsd/eal/Makefile
+++ b/lib/librte_eal/freebsd/eal/Makefile
@@ -22,7 +22,7 @@ LDLIBS += -lrte_kvargs
 
 EXPORT_MAP := ../../rte_eal_version.map
 
-LIBABIVER := 10
+LIBABIVER := 11
 
 # specific to freebsd exec-env
 SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) := eal.c
diff --git a/lib/librte_eal/freebsd/eal/eal_memory.c b/lib/librte_eal/freebsd/eal/eal_memory.c
index 4b092e1f2..9b9a0577a 100644
--- a/lib/librte_eal/freebsd/eal/eal_memory.c
+++ b/lib/librte_eal/freebsd/eal/eal_memory.c
@@ -18,6 +18,7 @@
 #include "eal_private.h"
 #include "eal_internal_cfg.h"
 #include "eal_filesystem.h"
+#include "eal_memcfg.h"
 
 #define EAL_PAGE_SIZE (sysconf(_SC_PAGESIZE))
 
diff --git a/lib/librte_eal/linux/eal/Makefile b/lib/librte_eal/linux/eal/Makefile
index dfe8e9a49..0f5725e64 100644
--- a/lib/librte_eal/linux/eal/Makefile
+++ b/lib/librte_eal/linux/eal/Makefile
@@ -10,7 +10,7 @@ ARCH_DIR ?= $(RTE_ARCH)
 EXPORT_MAP := ../../rte_eal_version.map
 VPATH += $(RTE_SDK)/lib/librte_eal/common/arch/$(ARCH_DIR)
 
-LIBABIVER := 10
+LIBABIVER := 11
 
 VPATH += $(RTE_SDK)/lib/librte_eal/common
 
diff --git a/lib/librte_eal/linux/eal/eal.c b/lib/librte_eal/linux/eal/eal.c
index 8a0b387ce..f974cec1c 100644
--- a/lib/librte_eal/linux/eal/eal.c
+++ b/lib/librte_eal/linux/eal/eal.c
@@ -57,6 +57,7 @@
 #include "eal_internal_cfg.h"
 #include "eal_filesystem.h"
 #include "eal_hugepages.h"
+#include "eal_memcfg.h"
 #include "eal_options.h"
 #include "eal_vfio.h"
 #include "hotplug_mp.h"
diff --git a/lib/librte_eal/linux/eal/eal_memalloc.c b/lib/librte_eal/linux/eal/eal_memalloc.c
index 2019636fb..1f6a7c18f 100644
--- a/lib/librte_eal/linux/eal/eal_memalloc.c
+++ b/lib/librte_eal/linux/eal/eal_memalloc.c
@@ -44,6 +44,7 @@
 #include "eal_filesystem.h"
 #include "eal_internal_cfg.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 #include "eal_private.h"
 
 const int anonymous_hugepages_supported =
diff --git a/lib/librte_eal/linux/eal/eal_memory.c b/lib/librte_eal/linux/eal/eal_memory.c
index 1853acea5..9c948a374 100644
--- a/lib/librte_eal/linux/eal/eal_memory.c
+++ b/lib/librte_eal/linux/eal/eal_memory.c
@@ -46,6 +46,7 @@
 
 #include "eal_private.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 #include "eal_internal_cfg.h"
 #include "eal_filesystem.h"
 #include "eal_hugepages.h"
diff --git a/lib/librte_eal/linux/eal/eal_vfio.c b/lib/librte_eal/linux/eal/eal_vfio.c
index 96a03a657..fdc884f70 100644
--- a/lib/librte_eal/linux/eal/eal_vfio.c
+++ b/lib/librte_eal/linux/eal/eal_vfio.c
@@ -15,6 +15,7 @@
 #include <rte_vfio.h>
 
 #include "eal_filesystem.h"
+#include "eal_memcfg.h"
 #include "eal_vfio.h"
 #include "eal_private.h"
 
diff --git a/lib/librte_eal/meson.build b/lib/librte_eal/meson.build
index ccd5b85b8..2751023a9 100644
--- a/lib/librte_eal/meson.build
+++ b/lib/librte_eal/meson.build
@@ -12,7 +12,7 @@ subdir('common') # defines common_sources, common_objs, etc.
 dpdk_conf.set('RTE_EXEC_ENV_' + exec_env.to_upper(), 1)
 subdir(exec_env + '/eal')
 
-version = 10  # the version of the EAL API
+version = 11  # the version of the EAL API
 allow_experimental_apis = true
 deps += 'kvargs'
 if dpdk_conf.has('RTE_USE_LIBBSD')
diff --git a/lib/librte_efd/rte_efd.c b/lib/librte_efd/rte_efd.c
index b808ce99f..d3d019578 100644
--- a/lib/librte_efd/rte_efd.c
+++ b/lib/librte_efd/rte_efd.c
@@ -20,6 +20,7 @@
 #include <rte_ring.h>
 #include <rte_jhash.h>
 #include <rte_hash_crc.h>
+#include <rte_tailq.h>
 
 #include "rte_efd.h"
 #if defined(RTE_ARCH_X86)
diff --git a/lib/librte_hash/rte_cuckoo_hash.c b/lib/librte_hash/rte_cuckoo_hash.c
index 47cd0da5b..74d5bbd99 100644
--- a/lib/librte_hash/rte_cuckoo_hash.c
+++ b/lib/librte_hash/rte_cuckoo_hash.c
@@ -27,6 +27,7 @@
 #include <rte_ring.h>
 #include <rte_compat.h>
 #include <rte_vect.h>
+#include <rte_tailq.h>
 
 #include "rte_hash.h"
 #include "rte_cuckoo_hash.h"
diff --git a/lib/librte_hash/rte_fbk_hash.c b/lib/librte_hash/rte_fbk_hash.c
index db118c930..576e8e666 100644
--- a/lib/librte_hash/rte_fbk_hash.c
+++ b/lib/librte_hash/rte_fbk_hash.c
@@ -20,6 +20,7 @@
 #include <rte_cpuflags.h>
 #include <rte_log.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_fbk_hash.h"
 
diff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c
index b91f74216..70c24ac1f 100644
--- a/lib/librte_lpm/rte_lpm.c
+++ b/lib/librte_lpm/rte_lpm.c
@@ -21,6 +21,7 @@
 #include <rte_errno.h>
 #include <rte_rwlock.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_lpm.h"
 
diff --git a/lib/librte_lpm/rte_lpm6.c b/lib/librte_lpm/rte_lpm6.c
index 5af74a539..9b8aeb972 100644
--- a/lib/librte_lpm/rte_lpm6.c
+++ b/lib/librte_lpm/rte_lpm6.c
@@ -24,6 +24,7 @@
 #include <rte_hash.h>
 #include <assert.h>
 #include <rte_jhash.h>
+#include <rte_tailq.h>
 
 #include "rte_lpm6.h"
 
diff --git a/lib/librte_member/rte_member.c b/lib/librte_member/rte_member.c
index efed28dd9..e0e7f127e 100644
--- a/lib/librte_member/rte_member.c
+++ b/lib/librte_member/rte_member.c
@@ -10,6 +10,7 @@
 #include <rte_memory.h>
 #include <rte_malloc.h>
 #include <rte_errno.h>
+#include <rte_tailq.h>
 
 #include "rte_member.h"
 #include "rte_member_ht.h"
diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c
index 5c688d456..7260ce0be 100644
--- a/lib/librte_mempool/rte_mempool.c
+++ b/lib/librte_mempool/rte_mempool.c
@@ -30,6 +30,7 @@
 #include <rte_errno.h>
 #include <rte_string_fns.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_mempool.h"
 
diff --git a/lib/librte_rcu/rte_rcu_qsbr.h b/lib/librte_rcu/rte_rcu_qsbr.h
index 53a5a7165..c80f15c00 100644
--- a/lib/librte_rcu/rte_rcu_qsbr.h
+++ b/lib/librte_rcu/rte_rcu_qsbr.h
@@ -24,6 +24,7 @@
 extern "C" {
 #endif
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <inttypes.h>
diff --git a/lib/librte_reorder/rte_reorder.c b/lib/librte_reorder/rte_reorder.c
index ae6e3f578..3c9f0e2d0 100644
--- a/lib/librte_reorder/rte_reorder.c
+++ b/lib/librte_reorder/rte_reorder.c
@@ -11,6 +11,7 @@
 #include <rte_eal_memconfig.h>
 #include <rte_errno.h>
 #include <rte_malloc.h>
+#include <rte_tailq.h>
 
 #include "rte_reorder.h"
 
diff --git a/lib/librte_ring/rte_ring.c b/lib/librte_ring/rte_ring.c
index 9ea26a631..b30b2aa7b 100644
--- a/lib/librte_ring/rte_ring.c
+++ b/lib/librte_ring/rte_ring.c
@@ -30,6 +30,7 @@
 #include <rte_errno.h>
 #include <rte_string_fns.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_ring.h"
 
-- 
2.17.1

^ permalink raw reply	[relevance 7%]

* [dpdk-dev] [PATCH v3 0/1] Fix timer resource leak
  2019-07-05 13:20  4%     ` [dpdk-dev] [PATCH v2 0/1] " Anatoly Burakov
@ 2019-07-05 17:22  4%       ` Anatoly Burakov
  0 siblings, 0 replies; 200+ results
From: Anatoly Burakov @ 2019-07-05 17:22 UTC (permalink / raw)
  To: dev

Previous attempts [1] at fixing the resource leak have been
deemed unsuccessful because of limitations around what
can be done without breaking the ABI. Now that we've
broken the EAL ABI, we can fix this issue properly.

This patchset is adding a new lock API, as well as fixes the
actual issue.

The patchset depends on mem config patchset [2].

v3:
- Accidentally squashed with previous patch, reverted

v2:
- Addressed review comments and squashed patches

[1] http://patches.dpdk.org/patch/53334/
[2] http://patches.dpdk.org/project/dpdk/list/?series=5369

Anatoly Burakov (1):
  timer: fix resource leak in finalize

 lib/librte_eal/common/eal_common_mcfg.c       | 14 +++++++
 lib/librte_eal/common/eal_memcfg.h            |  2 +
 .../common/include/rte_eal_memconfig.h        | 22 ++++++++++
 lib/librte_eal/rte_eal_version.map            |  2 +
 lib/librte_timer/rte_timer.c                  | 41 +++++++++++++------
 lib/librte_timer/rte_timer.h                  |  5 ++-
 6 files changed, 71 insertions(+), 15 deletions(-)

-- 
2.17.1

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v7 05/12] net/ether: mark ethernet addresses as being 2-byte aligned
  2019-07-05 14:34  3%     ` Olivier Matz
@ 2019-07-05 15:45  0%       ` Richardson, Bruce
  0 siblings, 0 replies; 200+ results
From: Richardson, Bruce @ 2019-07-05 15:45 UTC (permalink / raw)
  To: Olivier Matz, Stephen Hemminger; +Cc: dev, Andrew Rybchenko



> -----Original Message-----
> From: Olivier Matz [mailto:olivier.matz@6wind.com]
> Sent: Friday, July 5, 2019 3:34 PM
> To: Stephen Hemminger <stephen@networkplumber.org>
> Cc: dev@dpdk.org; Richardson, Bruce <bruce.richardson@intel.com>; Andrew
> Rybchenko <arybchenko@solarflare.com>
> Subject: Re: [dpdk-dev] [PATCH v7 05/12] net/ether: mark ethernet
> addresses as being 2-byte aligned
> 
> On Tue, Jul 02, 2019 at 03:12:40PM -0700, Stephen Hemminger wrote:
> > From: Bruce Richardson <bruce.richardson@intel.com>
> >
> > When including the rte_ether.h header in applications with warnings
> > enabled, a warning was given because of the assumption of 2-byte
> > alignment of ethernet addresses when processing them.
> >
> > .../include/rte_ether.h:149:2: warning: converting a packed ‘const
> >   struct ether_addr’ pointer (alignment 1) to a ‘unaligned_uint16_t’
> >   {aka ‘const short unsigned int’} pointer (alignment 2) may result in
> >   an unaligned pointer value [-Waddress-of-packed-member]
> > 149 |  const unaligned_uint16_t *ea_words = (const unaligned_uint16_t
> *)ea;
> >     |  ^~~~~
> >
> > Since ethernet addresses should always be aligned on a two-byte
> > boundary, we can just inform the compiler of this assumption to remove
> > the warnings and allow us to always access the addresses using 16-bit
> operations.
> >
> > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> > Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
> > ---
> >  lib/librte_net/rte_ether.h | 11 ++++++-----
> >  1 file changed, 6 insertions(+), 5 deletions(-)
> >
> > diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
> > index feb35a33c94b..d7b76ddf63eb 100644
> > --- a/lib/librte_net/rte_ether.h
> > +++ b/lib/librte_net/rte_ether.h
> > @@ -58,7 +58,8 @@ extern "C" {
> >   * See http://standards.ieee.org/regauth/groupmac/tutorial.html
> >   */
> >  struct rte_ether_addr {
> > -	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN]; /**< Addr bytes in tx order
> */
> > +	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN] __rte_aligned(2);
> > +	/**< Addr bytes in tx order */
> >  } __attribute__((__packed__));
> >
> >  #define RTE_ETHER_LOCAL_ADMIN_ADDR 0x02 /**< Locally assigned Eth.
> > address. */ @@ -81,8 +82,8 @@ struct rte_ether_addr {  static inline
> > int rte_is_same_ether_addr(const struct rte_ether_addr *ea1,
> >  				     const struct rte_ether_addr *ea2)  {
> > -	const unaligned_uint16_t *w1 = (const uint16_t *)ea1;
> > -	const unaligned_uint16_t *w2 = (const uint16_t *)ea2;
> > +	const uint16_t *w1 = (const uint16_t *)ea1;
> > +	const uint16_t *w2 = (const uint16_t *)ea2;
> >
> >  	return ((w1[0] ^ w2[0]) | (w1[1] ^ w2[1]) | (w1[2] ^ w2[2])) == 0;
> > } @@ -99,7 +100,7 @@ static inline int rte_is_same_ether_addr(const
> > struct rte_ether_addr *ea1,
> >   */
> >  static inline int rte_is_zero_ether_addr(const struct rte_ether_addr
> > *ea)  {
> > -	const unaligned_uint16_t *w = (const uint16_t *)ea;
> > +	const uint16_t *w = (const uint16_t *)ea;
> >
> >  	return (w[0] | w[1] | w[2]) == 0;
> >  }
> > @@ -146,7 +147,7 @@ static inline int rte_is_multicast_ether_addr(const
> struct rte_ether_addr *ea)
> >   */
> >  static inline int rte_is_broadcast_ether_addr(const struct
> > rte_ether_addr *ea)  {
> > -	const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea;
> > +	const uint16_t *ea_words = (const uint16_t *)ea;
> >
> >  	return (ea_words[0] == 0xFFFF && ea_words[1] == 0xFFFF &&
> >  		ea_words[2] == 0xFFFF);
> > --
> > 2.20.1
> >
> 
> Following this discussion:
> https://mails.dpdk.org/archives/dev/2019-July/136590.html
> 
> I still think that changing the ABI without deprecation notice
> is not a good idea.
> 
I'm ok with that. Let's put in a deprecation notice and take this
patch in 19.11.

> The warning issued by the compiler makes me think that the definition of
> unaligned_uint16_t is wrong on intel arch. I made a quick test, and it
> seems that in this particular case, the generated code is the same with
> or without __attribute__((aligned(1))). See: https://godbolt.org/z/NjBNQk
> 
> But changing the definition of unaligned_uint16_t without a deprecation
> notice is not an option either.
> 
> What do you think about using a specific typedef similar to
> unaligned_uint16_t in rte_ether, that has the __attribute__((aligned(1)))
> ?
> It would avoid to change the alignment of struct rte_ether_addr.
> 

I'd like the alignment changed. Since the existing warnings about alignment don’t
seem to be causing anyone any real problems, I suggest we just leave them for
now and fix them by changing the alignment setting for 19.11.

> In parallel, we can talk about changing unaligned_uint16_t for intel
> in another patchset.
> 

Yes, let's fix the broken unaligned definition as a separate issue.

/Bruce

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v7 05/12] net/ether: mark ethernet addresses as being 2-byte aligned
  @ 2019-07-05 14:34  3%     ` Olivier Matz
  2019-07-05 15:45  0%       ` Richardson, Bruce
  0 siblings, 1 reply; 200+ results
From: Olivier Matz @ 2019-07-05 14:34 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev, Bruce Richardson, Andrew Rybchenko

On Tue, Jul 02, 2019 at 03:12:40PM -0700, Stephen Hemminger wrote:
> From: Bruce Richardson <bruce.richardson@intel.com>
> 
> When including the rte_ether.h header in applications with warnings
> enabled, a warning was given because of the assumption of 2-byte alignment
> of ethernet addresses when processing them.
> 
> .../include/rte_ether.h:149:2: warning: converting a packed ‘const
>   struct ether_addr’ pointer (alignment 1) to a ‘unaligned_uint16_t’
>   {aka ‘const short unsigned int’} pointer (alignment 2) may result in
>   an unaligned pointer value [-Waddress-of-packed-member]
> 149 |  const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea;
>     |  ^~~~~
> 
> Since ethernet addresses should always be aligned on a two-byte boundary,
> we can just inform the compiler of this assumption to remove the warnings
> and allow us to always access the addresses using 16-bit operations.
> 
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
> ---
>  lib/librte_net/rte_ether.h | 11 ++++++-----
>  1 file changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
> index feb35a33c94b..d7b76ddf63eb 100644
> --- a/lib/librte_net/rte_ether.h
> +++ b/lib/librte_net/rte_ether.h
> @@ -58,7 +58,8 @@ extern "C" {
>   * See http://standards.ieee.org/regauth/groupmac/tutorial.html
>   */
>  struct rte_ether_addr {
> -	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN]; /**< Addr bytes in tx order */
> +	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN] __rte_aligned(2);
> +	/**< Addr bytes in tx order */
>  } __attribute__((__packed__));
>  
>  #define RTE_ETHER_LOCAL_ADMIN_ADDR 0x02 /**< Locally assigned Eth. address. */
> @@ -81,8 +82,8 @@ struct rte_ether_addr {
>  static inline int rte_is_same_ether_addr(const struct rte_ether_addr *ea1,
>  				     const struct rte_ether_addr *ea2)
>  {
> -	const unaligned_uint16_t *w1 = (const uint16_t *)ea1;
> -	const unaligned_uint16_t *w2 = (const uint16_t *)ea2;
> +	const uint16_t *w1 = (const uint16_t *)ea1;
> +	const uint16_t *w2 = (const uint16_t *)ea2;
>  
>  	return ((w1[0] ^ w2[0]) | (w1[1] ^ w2[1]) | (w1[2] ^ w2[2])) == 0;
>  }
> @@ -99,7 +100,7 @@ static inline int rte_is_same_ether_addr(const struct rte_ether_addr *ea1,
>   */
>  static inline int rte_is_zero_ether_addr(const struct rte_ether_addr *ea)
>  {
> -	const unaligned_uint16_t *w = (const uint16_t *)ea;
> +	const uint16_t *w = (const uint16_t *)ea;
>  
>  	return (w[0] | w[1] | w[2]) == 0;
>  }
> @@ -146,7 +147,7 @@ static inline int rte_is_multicast_ether_addr(const struct rte_ether_addr *ea)
>   */
>  static inline int rte_is_broadcast_ether_addr(const struct rte_ether_addr *ea)
>  {
> -	const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea;
> +	const uint16_t *ea_words = (const uint16_t *)ea;
>  
>  	return (ea_words[0] == 0xFFFF && ea_words[1] == 0xFFFF &&
>  		ea_words[2] == 0xFFFF);
> -- 
> 2.20.1
> 

Following this discussion:
https://mails.dpdk.org/archives/dev/2019-July/136590.html

I still think that changing the ABI without deprecation notice
is not a good idea.

The warning issued by the compiler makes me think that the definition of
unaligned_uint16_t is wrong on intel arch. I made a quick test, and it
seems that in this particular case, the generated code is the same with
or without __attribute__((aligned(1))). See: https://godbolt.org/z/NjBNQk

But changing the definition of unaligned_uint16_t without a deprecation
notice is not an option either.

What do you think about using a specific typedef similar to
unaligned_uint16_t in rte_ether, that has the __attribute__((aligned(1))) ?
It would avoid to change the alignment of struct rte_ether_addr.

In parallel, we can talk about changing unaligned_uint16_t for intel
in another patchset.

Olivier

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v2] devtools: better freebsd support
  @ 2019-07-05 13:58  6% ` Olivier Matz
  2019-07-09 11:05  0%   ` Musatescu, Flavia
  0 siblings, 1 reply; 200+ results
From: Olivier Matz @ 2019-07-05 13:58 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon, David Marchand, Bruce Richardson

- As "readlink -e" and "readlink -m" do not exist on freebsd,
  use "readlink -f", it should not have any impact in these cases.
- "sed -ri" is invalid on freebsd and should be replaced by
  "sed -ri=''"
- Use gmake instead of make.

This fixes the following command:
  SYSDIR=/usr/src/sys ./devtools/test-build.sh \
    -j4 x86_64-native-freebsd-gcc

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

v2:
- remove sed_ri() function and use 'sed -ri=""' as suggested by Bruce

 devtools/check-dup-includes.sh |  2 +-
 devtools/checkpatches.sh       |  8 ++--
 devtools/get-maintainer.sh     |  2 +-
 devtools/load-devel-config     |  4 +-
 devtools/test-build.sh         | 94 ++++++++++++++++++++++--------------------
 devtools/validate-abi.sh       |  2 +-
 6 files changed, 58 insertions(+), 54 deletions(-)

diff --git a/devtools/check-dup-includes.sh b/devtools/check-dup-includes.sh
index e4c2748c6..591599949 100755
--- a/devtools/check-dup-includes.sh
+++ b/devtools/check-dup-includes.sh
@@ -5,7 +5,7 @@
 # Check C files in git repository for duplicated includes.
 # Usage: devtools/check-dup-includes.sh [directory]
 
-dir=${1:-$(dirname $(readlink -m $0))/..}
+dir=${1:-$(dirname $(readlink -f $0))/..}
 cd $dir
 
 # speed up by ignoring Unicode details
diff --git a/devtools/checkpatches.sh b/devtools/checkpatches.sh
index 560e6ce93..8e2beee16 100755
--- a/devtools/checkpatches.sh
+++ b/devtools/checkpatches.sh
@@ -7,9 +7,9 @@
 # - DPDK_CHECKPATCH_CODESPELL
 # - DPDK_CHECKPATCH_LINE_LENGTH
 # - DPDK_CHECKPATCH_OPTIONS
-. $(dirname $(readlink -e $0))/load-devel-config
+. $(dirname $(readlink -f $0))/load-devel-config
 
-VALIDATE_NEW_API=$(dirname $(readlink -e $0))/check-symbol-change.sh
+VALIDATE_NEW_API=$(dirname $(readlink -f $0))/check-symbol-change.sh
 
 # Enable codespell by default. This can be overwritten from a config file.
 # Codespell can also be enabled by setting DPDK_CHECKPATCH_CODESPELL to a valid path
@@ -66,7 +66,7 @@ check_forbidden_additions() { # <patch>
 		-v EXPRESSIONS="rte_panic\\\( rte_exit\\\(" \
 		-v RET_ON_FAIL=1 \
 		-v MESSAGE='Using rte_panic/rte_exit' \
-		-f $(dirname $(readlink -e $0))/check-forbidden-tokens.awk \
+		-f $(dirname $(readlink -f $0))/check-forbidden-tokens.awk \
 		"$1" || res=1
 
 	# svg figures must be included with wildcard extension
@@ -75,7 +75,7 @@ check_forbidden_additions() { # <patch>
 		-v EXPRESSIONS='::[[:space:]]*[^[:space:]]*\\.svg' \
 		-v RET_ON_FAIL=1 \
 		-v MESSAGE='Using explicit .svg extension instead of .*' \
-		-f $(dirname $(readlink -e $0))/check-forbidden-tokens.awk \
+		-f $(dirname $(readlink -f $0))/check-forbidden-tokens.awk \
 		"$1" || res=1
 
 	return $res
diff --git a/devtools/get-maintainer.sh b/devtools/get-maintainer.sh
index b9160486a..85740f5af 100755
--- a/devtools/get-maintainer.sh
+++ b/devtools/get-maintainer.sh
@@ -5,7 +5,7 @@
 
 # Load config options:
 # - DPDK_GETMAINTAINER_PATH
-. $(dirname $(readlink -e $0))/load-devel-config
+. $(dirname $(readlink -f $0))/load-devel-config
 
 options="--no-git-fallback"
 options="$options --no-rolestats"
diff --git a/devtools/load-devel-config b/devtools/load-devel-config
index 4f43cb352..380c79db4 100644
--- a/devtools/load-devel-config
+++ b/devtools/load-devel-config
@@ -6,7 +6,7 @@ test ! -r /etc/dpdk/devel.config ||
 test ! -r ~/.config/dpdk/devel.config ||
         . ~/.config/dpdk/devel.config
 # from local file
-test ! -r $(dirname $(readlink -m $0))/../.develconfig ||
-        . $(dirname $(readlink -m $0))/../.develconfig
+test ! -r $(dirname $(readlink -f $0))/../.develconfig ||
+        . $(dirname $(readlink -f $0))/../.develconfig
 
 # The config files must export variables in the shell style
diff --git a/devtools/test-build.sh b/devtools/test-build.sh
index 9b50bf73d..22d409bb0 100755
--- a/devtools/test-build.sh
+++ b/devtools/test-build.sh
@@ -28,7 +28,7 @@ default_path=$PATH
 # - LIBSSO_SNOW3G_PATH
 # - LIBSSO_KASUMI_PATH
 # - LIBSSO_ZUC_PATH
-. $(dirname $(readlink -e $0))/load-devel-config
+. $(dirname $(readlink -f $0))/load-devel-config
 
 print_usage () {
 	echo "usage: $(basename $0) [-h] [-jX] [-s] [config1 [config2] ...]]"
@@ -57,6 +57,10 @@ print_help () {
 	END_OF_HELP
 }
 
+[ -z $MAKE ] && command -v gmake > /dev/null && MAKE=gmake
+[ -z $MAKE ] && command -v make > /dev/null && MAKE=make
+[ -z $MAKE ] && echo "Cannot find make or gmake" && exit 1
+
 J=$DPDK_MAKE_JOBS
 short=false
 unset verbose
@@ -90,7 +94,7 @@ trap "signal=INT ; trap - INT ; kill -INT $$" INT
 # notify result on exit
 trap on_exit EXIT
 
-cd $(dirname $(readlink -m $0))/..
+cd $(dirname $(readlink -f $0))/..
 
 reset_env ()
 {
@@ -127,83 +131,83 @@ config () # <directory> <target> <options>
 	fi
 	if [ ! -e $1/.config ] || $reconfig ; then
 		echo "================== Configure $1"
-		make T=$2 O=$1 config
+		${MAKE} T=$2 O=$1 config
 
 		echo 'Customize configuration'
 		# Built-in options (lowercase)
 		! echo $3 | grep -q '+default' || \
-		sed -ri 's,(RTE_MACHINE=")native,\1default,' $1/.config
+		sed -ri="" 's,(RTE_MACHINE=")native,\1default,' $1/.config
 		echo $3 | grep -q '+next' || \
-		sed -ri           's,(NEXT_ABI=)y,\1n,' $1/.config
+		sed -ri=""           's,(NEXT_ABI=)y,\1n,' $1/.config
 		! echo $3 | grep -q '+shared' || \
-		sed -ri         's,(SHARED_LIB=)n,\1y,' $1/.config
+		sed -ri=""         's,(SHARED_LIB=)n,\1y,' $1/.config
 		! echo $3 | grep -q '+debug' || ( \
-		sed -ri  's,(RTE_LOG_DP_LEVEL=).*,\1RTE_LOG_DEBUG,' $1/.config
-		sed -ri           's,(_DEBUG.*=)n,\1y,' $1/.config
-		sed -ri            's,(_STAT.*=)n,\1y,' $1/.config
-		sed -ri 's,(TEST_PMD_RECORD_.*=)n,\1y,' $1/.config )
+		sed -ri=""  's,(RTE_LOG_DP_LEVEL=).*,\1RTE_LOG_DEBUG,' $1/.config
+		sed -ri=""           's,(_DEBUG.*=)n,\1y,' $1/.config
+		sed -ri=""            's,(_STAT.*=)n,\1y,' $1/.config
+		sed -ri="" 's,(TEST_PMD_RECORD_.*=)n,\1y,' $1/.config )
 
 		# Automatic configuration
 		test "$DPDK_DEP_NUMA" != n || \
-		sed -ri             's,(NUMA.*=)y,\1n,' $1/.config
-		sed -ri    's,(LIBRTE_IEEE1588=)n,\1y,' $1/.config
-		sed -ri             's,(BYPASS=)n,\1y,' $1/.config
+		sed -ri=""             's,(NUMA.*=)y,\1n,' $1/.config
+		sed -ri=""    's,(LIBRTE_IEEE1588=)n,\1y,' $1/.config
+		sed -ri=""             's,(BYPASS=)n,\1y,' $1/.config
 		test "$DPDK_DEP_ARCHIVE" != y || \
-		sed -ri       's,(RESOURCE_TAR=)n,\1y,' $1/.config
+		sed -ri=""       's,(RESOURCE_TAR=)n,\1y,' $1/.config
 		test "$DPDK_DEP_ISAL" != y || \
-		sed -ri           's,(PMD_ISAL=)n,\1y,' $1/.config
+		sed -ri=""           's,(PMD_ISAL=)n,\1y,' $1/.config
 		test "$DPDK_DEP_MLX" != y || \
-		sed -ri           's,(MLX._PMD=)n,\1y,' $1/.config
+		sed -ri=""           's,(MLX._PMD=)n,\1y,' $1/.config
 		test "$DPDK_DEP_SZE" != y || \
-		sed -ri       's,(PMD_SZEDATA2=)n,\1y,' $1/.config
+		sed -ri=""       's,(PMD_SZEDATA2=)n,\1y,' $1/.config
 		test "$DPDK_DEP_ZLIB" != y || \
-		sed -ri          's,(BNX2X_PMD=)n,\1y,' $1/.config
+		sed -ri=""          's,(BNX2X_PMD=)n,\1y,' $1/.config
 		test "$DPDK_DEP_ZLIB" != y || \
-		sed -ri           's,(PMD_ZLIB=)n,\1y,' $1/.config
+		sed -ri=""           's,(PMD_ZLIB=)n,\1y,' $1/.config
 		test "$DPDK_DEP_ZLIB" != y || \
-		sed -ri   's,(COMPRESSDEV_TEST=)n,\1y,' $1/.config
+		sed -ri=""   's,(COMPRESSDEV_TEST=)n,\1y,' $1/.config
 		test "$DPDK_DEP_PCAP" != y || \
-		sed -ri               's,(PCAP=)n,\1y,' $1/.config
+		sed -ri=""               's,(PCAP=)n,\1y,' $1/.config
 		test -z "$ARMV8_CRYPTO_LIB_PATH" || \
-		sed -ri   's,(PMD_ARMV8_CRYPTO=)n,\1y,' $1/.config
+		sed -ri=""   's,(PMD_ARMV8_CRYPTO=)n,\1y,' $1/.config
 		test "$DPDK_DEP_IPSEC_MB" != y || \
-		sed -ri       's,(PMD_AESNI_MB=)n,\1y,' $1/.config
+		sed -ri=""       's,(PMD_AESNI_MB=)n,\1y,' $1/.config
 		test "$DPDK_DEP_IPSEC_MB" != y || \
-		sed -ri      's,(PMD_AESNI_GCM=)n,\1y,' $1/.config
+		sed -ri=""      's,(PMD_AESNI_GCM=)n,\1y,' $1/.config
 		test -z "$LIBSSO_SNOW3G_PATH" || \
-		sed -ri         's,(PMD_SNOW3G=)n,\1y,' $1/.config
+		sed -ri=""         's,(PMD_SNOW3G=)n,\1y,' $1/.config
 		test -z "$LIBSSO_KASUMI_PATH" || \
-		sed -ri         's,(PMD_KASUMI=)n,\1y,' $1/.config
+		sed -ri=""         's,(PMD_KASUMI=)n,\1y,' $1/.config
 		test -z "$LIBSSO_ZUC_PATH" || \
-		sed -ri            's,(PMD_ZUC=)n,\1y,' $1/.config
+		sed -ri=""            's,(PMD_ZUC=)n,\1y,' $1/.config
 		test "$DPDK_DEP_SSL" != y || \
-		sed -ri            's,(PMD_CCP=)n,\1y,' $1/.config
+		sed -ri=""            's,(PMD_CCP=)n,\1y,' $1/.config
 		test "$DPDK_DEP_SSL" != y || \
-		sed -ri        's,(PMD_OPENSSL=)n,\1y,' $1/.config
+		sed -ri=""        's,(PMD_OPENSSL=)n,\1y,' $1/.config
 		test "$DPDK_DEP_SSL" != y || \
-		sed -ri            's,(QAT_SYM=)n,\1y,' $1/.config
+		sed -ri=""            's,(QAT_SYM=)n,\1y,' $1/.config
 		test -z "$FLEXRAN_SDK" || \
-		sed -ri     's,(BBDEV_TURBO_SW=)n,\1y,' $1/.config
-		sed -ri           's,(SCHED_.*=)n,\1y,' $1/.config
+		sed -ri=""     's,(BBDEV_TURBO_SW=)n,\1y,' $1/.config
+		sed -ri=""           's,(SCHED_.*=)n,\1y,' $1/.config
 		test -z "$LIBMUSDK_PATH" || \
-		sed -ri   's,(PMD_MVSAM_CRYPTO=)n,\1y,' $1/.config
+		sed -ri=""   's,(PMD_MVSAM_CRYPTO=)n,\1y,' $1/.config
 		test -z "$LIBMUSDK_PATH" || \
-		sed -ri          's,(MVPP2_PMD=)n,\1y,' $1/.config
+		sed -ri=""          's,(MVPP2_PMD=)n,\1y,' $1/.config
 		test -z "$LIBMUSDK_PATH" || \
-		sed -ri         's,(MVNETA_PMD=)n,\1y,' $1/.config
+		sed -ri=""         's,(MVNETA_PMD=)n,\1y,' $1/.config
 		test "$DPDK_DEP_ELF" != y || \
-		sed -ri            's,(BPF_ELF=)n,\1y,' $1/.config
+		sed -ri=""            's,(BPF_ELF=)n,\1y,' $1/.config
 		test "$DPDK_DEP_JSON" != y || \
-		sed -ri          's,(TELEMETRY=)n,\1y,' $1/.config
+		sed -ri=""          's,(TELEMETRY=)n,\1y,' $1/.config
 		build_config_hook $1 $2 $3
 
 		# Explicit enabler/disabler (uppercase)
 		for option in $(echo $3 | sed 's,[~+], &,g') ; do
 			pattern=$(echo $option | cut -c2-)
 			if echo $option | grep -q '^~' ; then
-				sed -ri "s,($pattern=)y,\1n," $1/.config
+				sed -ri="" "s,($pattern=)y,\1n," $1/.config
 			elif echo $option | grep -q '^+' ; then
-				sed -ri "s,($pattern=)n,\1y," $1/.config
+				sed -ri="" "s,($pattern=)n,\1y," $1/.config
 			fi
 		done
 	fi
@@ -220,22 +224,22 @@ for conf in $configs ; do
 	# reload config with DPDK_TARGET set
 	DPDK_TARGET=$target
 	reset_env
-	. $(dirname $(readlink -e $0))/load-devel-config
+	. $(dirname $(readlink -f $0))/load-devel-config
 
 	options=$(echo $conf | sed 's,[^~+]*,,')
 	dir=$conf
 	config $dir $target $options
 
 	echo "================== Build $dir"
-	make -j$J EXTRA_CFLAGS="$maxerr $DPDK_DEP_CFLAGS" \
+	${MAKE} -j$J EXTRA_CFLAGS="$maxerr $DPDK_DEP_CFLAGS" \
 		EXTRA_LDFLAGS="$DPDK_DEP_LDFLAGS" $verbose O=$dir
 	! $short || break
 	echo "================== Build examples for $dir"
 	export RTE_SDK=$(pwd)
 	export RTE_TARGET=$dir
-	make -j$J -sC examples \
+	${MAKE} -j$J -sC examples \
 		EXTRA_LDFLAGS="$DPDK_DEP_LDFLAGS" $verbose \
-		O=$(readlink -m $dir/examples)
+		O=$(readlink -f $dir/examples)
 	unset RTE_TARGET
 	echo "################## $dir done."
 	unset dir
@@ -244,9 +248,9 @@ done
 if ! $short ; then
 	mkdir -p .check
 	echo "================== Build doxygen HTML API"
-	make doc-api-html >/dev/null 2>.check/doc.txt
+	${MAKE} doc-api-html >/dev/null 2>.check/doc.txt
 	echo "================== Build sphinx HTML guides"
-	make doc-guides-html >/dev/null 2>>.check/doc.txt
+	${MAKE} doc-guides-html >/dev/null 2>>.check/doc.txt
 	echo "================== Check docs"
 	diff -u /dev/null .check/doc.txt
 fi
diff --git a/devtools/validate-abi.sh b/devtools/validate-abi.sh
index 138436d93..f64e19d38 100755
--- a/devtools/validate-abi.sh
+++ b/devtools/validate-abi.sh
@@ -181,7 +181,7 @@ case "${dst}" in
 	/*) ;;
 	*) dst=${PWD}/${dst} ;;
 esac
-dpdkroot=$(readlink -e $(dirname $0)/..)
+dpdkroot=$(readlink -f $(dirname $0)/..)
 
 if [ -e "${dst}" -a "$force" = 0 ]; then
 	echo "The ${dst} directory is not empty. Remove it, use another"
-- 
2.11.0


^ permalink raw reply	[relevance 6%]

* [dpdk-dev] [PATCH v2 0/1] Fix timer resource leak
  2019-06-25 16:11  4%   ` [dpdk-dev] [PATCH 0/2] Fix timer resource leak Anatoly Burakov
@ 2019-07-05 13:20  4%     ` Anatoly Burakov
  2019-07-05 17:22  4%       ` [dpdk-dev] [PATCH v3 " Anatoly Burakov
  0 siblings, 1 reply; 200+ results
From: Anatoly Burakov @ 2019-07-05 13:20 UTC (permalink / raw)
  To: dev

Previous attempts [1] at fixing the resource leak have been
deemed unsuccessful because of limitations around what
can be done without breaking the ABI. Now that we've
broken the EAL ABI, we can fix this issue properly.

This patchset is adding a new lock API, as well as fixes the
actual issue.

The patchset depends on mem config patchset [2].

[1] http://patches.dpdk.org/patch/53334/
[2] http://patches.dpdk.org/project/dpdk/list/?series=5369

Anatoly Burakov (1):
  timer: fix resource leak in finalize

 lib/librte_eal/common/eal_common_mcfg.c       | 29 +++++++++++++
 lib/librte_eal/common/eal_memcfg.h            |  8 ++++
 .../common/include/rte_eal_memconfig.h        | 22 ++++++++++
 lib/librte_eal/freebsd/eal/eal.c              |  5 ++-
 lib/librte_eal/linux/eal/eal.c                |  5 ++-
 lib/librte_eal/rte_eal_version.map            |  2 +
 lib/librte_timer/rte_timer.c                  | 41 +++++++++++++------
 lib/librte_timer/rte_timer.h                  |  5 ++-
 8 files changed, 100 insertions(+), 17 deletions(-)

-- 
2.17.1

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v4 4/8] eal: hide shared memory config
      @ 2019-07-05 13:10  7%     ` Anatoly Burakov
  2 siblings, 0 replies; 200+ results
From: Anatoly Burakov @ 2019-07-05 13:10 UTC (permalink / raw)
  To: dev
  Cc: Neil Horman, John McNamara, Marko Kovacevic, Konstantin Ananyev,
	David Hunt, Bruce Richardson, Byron Marohn, Pablo de Lara Guarch,
	Yipeng Wang, Sameh Gobriel, Vladimir Medvedkin, Olivier Matz,
	Andrew Rybchenko, Honnappa Nagarahalli, Reshma Pattan, thomas,
	david.marchand, stephen

Now that everything that has ever accessed the shared memory
config is doing so through the public API's, we can make it
internal. Since we're removing quite a few headers from
rte_eal_memconfig.h, we need to add them back in places
where this header is used.

This bumps the ABI, so also change all build files and make
update documentation.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
Acked-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test/test_fbarray.c                       |  1 +
 app/test/test_memzone.c                       |  1 +
 app/test/test_tailq.c                         |  1 +
 doc/guides/rel_notes/deprecation.rst          |  3 -
 doc/guides/rel_notes/release_19_08.rst        |  8 +-
 drivers/bus/pci/linux/pci_vfio.c              |  1 +
 lib/librte_acl/rte_acl.c                      |  2 +
 lib/librte_distributor/rte_distributor.c      |  1 +
 lib/librte_distributor/rte_distributor_v20.c  |  1 +
 lib/librte_eal/common/eal_common_mcfg.c       |  2 +
 lib/librte_eal/common/eal_common_memory.c     |  1 +
 lib/librte_eal/common/eal_common_memzone.c    |  1 +
 lib/librte_eal/common/eal_common_tailqs.c     |  1 +
 lib/librte_eal/common/eal_memcfg.h            | 80 ++++++++++++++++
 .../common/include/rte_eal_memconfig.h        | 95 +------------------
 lib/librte_eal/common/include/rte_fbarray.h   |  1 -
 lib/librte_eal/common/include/rte_memory.h    | 24 ++++-
 lib/librte_eal/common/malloc_heap.c           |  2 +
 lib/librte_eal/common/malloc_mp.c             |  1 +
 lib/librte_eal/common/rte_malloc.c            |  1 +
 lib/librte_eal/freebsd/eal/Makefile           |  2 +-
 lib/librte_eal/freebsd/eal/eal_memory.c       |  1 +
 lib/librte_eal/linux/eal/Makefile             |  2 +-
 lib/librte_eal/linux/eal/eal.c                |  1 +
 lib/librte_eal/linux/eal/eal_memalloc.c       |  1 +
 lib/librte_eal/linux/eal/eal_memory.c         |  1 +
 lib/librte_eal/linux/eal/eal_vfio.c           |  1 +
 lib/librte_eal/meson.build                    |  2 +-
 lib/librte_efd/rte_efd.c                      |  1 +
 lib/librte_hash/rte_cuckoo_hash.c             |  1 +
 lib/librte_hash/rte_fbk_hash.c                |  1 +
 lib/librte_lpm/rte_lpm.c                      |  1 +
 lib/librte_lpm/rte_lpm6.c                     |  1 +
 lib/librte_member/rte_member.c                |  1 +
 lib/librte_mempool/rte_mempool.c              |  1 +
 lib/librte_rcu/rte_rcu_qsbr.h                 |  1 +
 lib/librte_reorder/rte_reorder.c              |  1 +
 lib/librte_ring/rte_ring.c                    |  1 +
 38 files changed, 148 insertions(+), 101 deletions(-)
 create mode 100644 lib/librte_eal/common/eal_memcfg.h

diff --git a/app/test/test_fbarray.c b/app/test/test_fbarray.c
index d2b041887..a691bf445 100644
--- a/app/test/test_fbarray.c
+++ b/app/test/test_fbarray.c
@@ -2,6 +2,7 @@
  * Copyright(c) 2010-2014 Intel Corporation
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <limits.h>
diff --git a/app/test/test_memzone.c b/app/test/test_memzone.c
index 9fe465e62..7501b63c5 100644
--- a/app/test/test_memzone.c
+++ b/app/test/test_memzone.c
@@ -19,6 +19,7 @@
 #include <rte_errno.h>
 #include <rte_malloc.h>
 #include "../../lib/librte_eal/common/malloc_elem.h"
+#include "../../lib/librte_eal/common/eal_memcfg.h"
 
 #include "test.h"
 
diff --git a/app/test/test_tailq.c b/app/test/test_tailq.c
index a4ecea2d8..7c9b69fdb 100644
--- a/app/test/test_tailq.c
+++ b/app/test/test_tailq.c
@@ -12,6 +12,7 @@
 #include <rte_eal.h>
 #include <rte_eal_memconfig.h>
 #include <rte_string_fns.h>
+#include <rte_tailq.h>
 
 #include "test.h"
 
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index e2721fad6..583217da8 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -23,9 +23,6 @@ Deprecation Notices
 * eal: The function ``rte_eal_remote_launch`` will return new error codes
   after read or write error on the pipe, instead of calling ``rte_panic``.
 
-* eal: the ``rte_mem_config`` struct will be made private to remove it from the
-  externally visible ABI and allow it to be updated in the future.
-
 * eal: both declaring and identifying devices will be streamlined in v18.11.
   New functions will appear to query a specific port from buses, classes of
   device and device drivers. Device declaration will be made coherent with the
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 21934bf01..cc6dfa33f 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -172,6 +172,10 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* The ``rte_mem_config`` structure has been made private. The new accessor
+  ``rte_mcfg_*`` functions were introduced to provide replacement for direct
+  access to the shared mem config.
+
 * The network structures, definitions and functions have
   been prefixed by ``rte_`` to resolve conflicts with libc headers.
 
@@ -201,6 +205,8 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* The ``rte_mem_config`` structure has been made private.
+
 * eventdev: Event based Rx adapter callback
 
   The mbuf pointer array in the event eth Rx adapter callback
@@ -246,7 +252,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_compressdev.so.1
      librte_cryptodev.so.7
      librte_distributor.so.1
-     librte_eal.so.10
+   + librte_eal.so.11
      librte_efd.so.1
      librte_ethdev.so.12
    + librte_eventdev.so.7
diff --git a/drivers/bus/pci/linux/pci_vfio.c b/drivers/bus/pci/linux/pci_vfio.c
index ebf6ccd3c..1ceb1c07b 100644
--- a/drivers/bus/pci/linux/pci_vfio.c
+++ b/drivers/bus/pci/linux/pci_vfio.c
@@ -20,6 +20,7 @@
 #include <rte_eal.h>
 #include <rte_bus.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "eal_filesystem.h"
 
diff --git a/lib/librte_acl/rte_acl.c b/lib/librte_acl/rte_acl.c
index 7ff11d25f..bd7247cc3 100644
--- a/lib/librte_acl/rte_acl.c
+++ b/lib/librte_acl/rte_acl.c
@@ -4,6 +4,8 @@
 
 #include <rte_string_fns.h>
 #include <rte_acl.h>
+#include <rte_tailq.h>
+
 #include "acl.h"
 
 TAILQ_HEAD(rte_acl_list, rte_tailq_entry);
diff --git a/lib/librte_distributor/rte_distributor.c b/lib/librte_distributor/rte_distributor.c
index 9eb78b330..0a3213bbf 100644
--- a/lib/librte_distributor/rte_distributor.c
+++ b/lib/librte_distributor/rte_distributor.c
@@ -14,6 +14,7 @@
 #include <rte_string_fns.h>
 #include <rte_eal_memconfig.h>
 #include <rte_pause.h>
+#include <rte_tailq.h>
 
 #include "rte_distributor_private.h"
 #include "rte_distributor.h"
diff --git a/lib/librte_distributor/rte_distributor_v20.c b/lib/librte_distributor/rte_distributor_v20.c
index 1fc03b971..cdc0969a8 100644
--- a/lib/librte_distributor/rte_distributor_v20.c
+++ b/lib/librte_distributor/rte_distributor_v20.c
@@ -13,6 +13,7 @@
 #include <rte_string_fns.h>
 #include <rte_eal_memconfig.h>
 #include <rte_pause.h>
+#include <rte_tailq.h>
 
 #include "rte_distributor_v20.h"
 #include "rte_distributor_private.h"
diff --git a/lib/librte_eal/common/eal_common_mcfg.c b/lib/librte_eal/common/eal_common_mcfg.c
index ba2bc37b7..337890a61 100644
--- a/lib/librte_eal/common/eal_common_mcfg.c
+++ b/lib/librte_eal/common/eal_common_mcfg.c
@@ -5,6 +5,8 @@
 #include <rte_config.h>
 #include <rte_eal_memconfig.h>
 
+#include "eal_memcfg.h"
+
 void
 rte_mcfg_mem_read_lock(void)
 {
diff --git a/lib/librte_eal/common/eal_common_memory.c b/lib/librte_eal/common/eal_common_memory.c
index fe22b139b..19ea47570 100644
--- a/lib/librte_eal/common/eal_common_memory.c
+++ b/lib/librte_eal/common/eal_common_memory.c
@@ -24,6 +24,7 @@
 #include "eal_memalloc.h"
 #include "eal_private.h"
 #include "eal_internal_cfg.h"
+#include "eal_memcfg.h"
 #include "malloc_heap.h"
 
 /*
diff --git a/lib/librte_eal/common/eal_common_memzone.c b/lib/librte_eal/common/eal_common_memzone.c
index 521ad7ca1..ef6c909cb 100644
--- a/lib/librte_eal/common/eal_common_memzone.c
+++ b/lib/librte_eal/common/eal_common_memzone.c
@@ -24,6 +24,7 @@
 #include "malloc_heap.h"
 #include "malloc_elem.h"
 #include "eal_private.h"
+#include "eal_memcfg.h"
 
 static inline const struct rte_memzone *
 memzone_lookup_thread_unsafe(const char *name)
diff --git a/lib/librte_eal/common/eal_common_tailqs.c b/lib/librte_eal/common/eal_common_tailqs.c
index dc2c13caa..ead06897b 100644
--- a/lib/librte_eal/common/eal_common_tailqs.c
+++ b/lib/librte_eal/common/eal_common_tailqs.c
@@ -23,6 +23,7 @@
 #include <rte_debug.h>
 
 #include "eal_private.h"
+#include "eal_memcfg.h"
 
 TAILQ_HEAD(rte_tailq_elem_head, rte_tailq_elem);
 /* local tailq list */
diff --git a/lib/librte_eal/common/eal_memcfg.h b/lib/librte_eal/common/eal_memcfg.h
new file mode 100644
index 000000000..74f6159c6
--- /dev/null
+++ b/lib/librte_eal/common/eal_memcfg.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef EAL_MEMCFG_H
+#define EAL_MEMCFG_H
+
+#include <rte_config.h>
+#include <rte_eal_memconfig.h>
+#include <rte_malloc_heap.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_pause.h>
+#include <rte_rwlock.h>
+#include <rte_tailq.h>
+
+/**
+ * Memory configuration shared across multiple processes.
+ */
+struct rte_mem_config {
+	volatile uint32_t magic;   /**< Magic number - sanity check. */
+
+	/* memory topology */
+	uint32_t nchannel;    /**< Number of channels (0 if unknown). */
+	uint32_t nrank;       /**< Number of ranks (0 if unknown). */
+
+	/**
+	 * current lock nest order
+	 *  - qlock->mlock (ring/hash/lpm)
+	 *  - mplock->qlock->mlock (mempool)
+	 * Notice:
+	 *  *ALWAYS* obtain qlock first if having to obtain both qlock and mlock
+	 */
+	rte_rwlock_t mlock;   /**< used by memzones for thread safety. */
+	rte_rwlock_t qlock;   /**< used by tailqs for thread safety. */
+	rte_rwlock_t mplock;  /**< used by mempool library for thread safety. */
+
+	rte_rwlock_t memory_hotplug_lock;
+	/**< Indicates whether memory hotplug request is in progress. */
+
+	/* memory segments and zones */
+	struct rte_fbarray memzones; /**< Memzone descriptors. */
+
+	struct rte_memseg_list memsegs[RTE_MAX_MEMSEG_LISTS];
+	/**< List of dynamic arrays holding memsegs */
+
+	struct rte_tailq_head tailq_head[RTE_MAX_TAILQ];
+	/**< Tailqs for objects */
+
+	struct malloc_heap malloc_heaps[RTE_MAX_HEAPS];
+	/**< DPDK malloc heaps */
+
+	int next_socket_id; /**< Next socket ID for external malloc heap */
+
+	/* rte_mem_config has to be mapped at the exact same address in all
+	 * processes, so we need to store it.
+	 */
+	uint64_t mem_cfg_addr; /**< Address of this structure in memory. */
+
+	/* Primary and secondary processes cannot run with different legacy or
+	 * single file segments options, so to avoid having to specify these
+	 * options to all processes, store them in shared config and update the
+	 * internal config at init time.
+	 */
+	uint32_t legacy_mem; /**< stored legacy mem parameter. */
+	uint32_t single_file_segments;
+	/**< stored single file segments parameter. */
+
+	uint8_t dma_maskbits; /**< Keeps the more restricted dma mask. */
+} __attribute__((packed));
+
+static inline void
+rte_eal_mcfg_wait_complete(struct rte_mem_config *mcfg)
+{
+	/* wait until shared mem_config finish initialising */
+	while (mcfg->magic != RTE_MAGIC)
+		rte_pause();
+}
+
+#endif /* EAL_MEMCFG_H */
diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
index 58dcbb96d..dc61a6fed 100644
--- a/lib/librte_eal/common/include/rte_eal_memconfig.h
+++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
@@ -5,101 +5,16 @@
 #ifndef _RTE_EAL_MEMCONFIG_H_
 #define _RTE_EAL_MEMCONFIG_H_
 
-#include <rte_config.h>
-#include <rte_tailq.h>
-#include <rte_memory.h>
-#include <rte_memzone.h>
-#include <rte_malloc_heap.h>
-#include <rte_rwlock.h>
-#include <rte_pause.h>
-#include <rte_fbarray.h>
+/**
+ * @file
+ *
+ * This API allows access to EAL shared memory configuration through an API.
+ */
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/**
- * memseg list is a special case as we need to store a bunch of other data
- * together with the array itself.
- */
-struct rte_memseg_list {
-	RTE_STD_C11
-	union {
-		void *base_va;
-		/**< Base virtual address for this memseg list. */
-		uint64_t addr_64;
-		/**< Makes sure addr is always 64-bits */
-	};
-	uint64_t page_sz; /**< Page size for all memsegs in this list. */
-	int socket_id; /**< Socket ID for all memsegs in this list. */
-	volatile uint32_t version; /**< version number for multiprocess sync. */
-	size_t len; /**< Length of memory area covered by this memseg list. */
-	unsigned int external; /**< 1 if this list points to external memory */
-	struct rte_fbarray memseg_arr;
-};
-
-/**
- * the structure for the memory configuration for the RTE.
- * Used by the rte_config structure. It is separated out, as for multi-process
- * support, the memory details should be shared across instances
- */
-struct rte_mem_config {
-	volatile uint32_t magic;   /**< Magic number - Sanity check. */
-
-	/* memory topology */
-	uint32_t nchannel;    /**< Number of channels (0 if unknown). */
-	uint32_t nrank;       /**< Number of ranks (0 if unknown). */
-
-	/**
-	 * current lock nest order
-	 *  - qlock->mlock (ring/hash/lpm)
-	 *  - mplock->qlock->mlock (mempool)
-	 * Notice:
-	 *  *ALWAYS* obtain qlock first if having to obtain both qlock and mlock
-	 */
-	rte_rwlock_t mlock;   /**< only used by memzone LIB for thread-safe. */
-	rte_rwlock_t qlock;   /**< used for tailq operation for thread safe. */
-	rte_rwlock_t mplock;  /**< only used by mempool LIB for thread-safe. */
-
-	rte_rwlock_t memory_hotplug_lock;
-	/**< indicates whether memory hotplug request is in progress. */
-
-	/* memory segments and zones */
-	struct rte_fbarray memzones; /**< Memzone descriptors. */
-
-	struct rte_memseg_list memsegs[RTE_MAX_MEMSEG_LISTS];
-	/**< list of dynamic arrays holding memsegs */
-
-	struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**< Tailqs for objects */
-
-	/* Heaps of Malloc */
-	struct malloc_heap malloc_heaps[RTE_MAX_HEAPS];
-
-	/* next socket ID for external malloc heap */
-	int next_socket_id;
-
-	/* address of mem_config in primary process. used to map shared config into
-	 * exact same address the primary process maps it.
-	 */
-	uint64_t mem_cfg_addr;
-
-	/* legacy mem and single file segments options are shared */
-	uint32_t legacy_mem;
-	uint32_t single_file_segments;
-
-	/* keeps the more restricted dma mask */
-	uint8_t dma_maskbits;
-} __attribute__((__packed__));
-
-
-inline static void
-rte_eal_mcfg_wait_complete(struct rte_mem_config* mcfg)
-{
-	/* wait until shared mem_config finish initialising */
-	while(mcfg->magic != RTE_MAGIC)
-		rte_pause();
-}
-
 /**
  * Lock the internal EAL shared memory configuration for shared access.
  */
diff --git a/lib/librte_eal/common/include/rte_fbarray.h b/lib/librte_eal/common/include/rte_fbarray.h
index d0af2d8c7..6dccdbec9 100644
--- a/lib/librte_eal/common/include/rte_fbarray.h
+++ b/lib/librte_eal/common/include/rte_fbarray.h
@@ -34,7 +34,6 @@
 extern "C" {
 #endif
 
-#include <stdbool.h>
 #include <stdio.h>
 
 #include <rte_compat.h>
diff --git a/lib/librte_eal/common/include/rte_memory.h b/lib/librte_eal/common/include/rte_memory.h
index 44cbe6fd2..ca34a10c3 100644
--- a/lib/librte_eal/common/include/rte_memory.h
+++ b/lib/librte_eal/common/include/rte_memory.h
@@ -22,9 +22,7 @@ extern "C" {
 #include <rte_common.h>
 #include <rte_compat.h>
 #include <rte_config.h>
-
-/* forward declaration for pointers */
-struct rte_memseg_list;
+#include <rte_fbarray.h>
 
 __extension__
 enum rte_page_sizes {
@@ -104,6 +102,26 @@ struct rte_memseg {
 	uint32_t flags;             /**< Memseg-specific flags */
 } __rte_packed;
 
+/**
+ * memseg list is a special case as we need to store a bunch of other data
+ * together with the array itself.
+ */
+struct rte_memseg_list {
+	RTE_STD_C11
+	union {
+		void *base_va;
+		/**< Base virtual address for this memseg list. */
+		uint64_t addr_64;
+		/**< Makes sure addr is always 64-bits */
+	};
+	uint64_t page_sz; /**< Page size for all memsegs in this list. */
+	int socket_id; /**< Socket ID for all memsegs in this list. */
+	volatile uint32_t version; /**< version number for multiprocess sync. */
+	size_t len; /**< Length of memory area covered by this memseg list. */
+	unsigned int external; /**< 1 if this list points to external memory */
+	struct rte_fbarray memseg_arr;
+};
+
 /**
  * Lock page in physical memory and prevent from swapping.
  *
diff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c
index f1d31de0d..634ca212f 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -20,11 +20,13 @@
 #include <rte_string_fns.h>
 #include <rte_spinlock.h>
 #include <rte_memcpy.h>
+#include <rte_memzone.h>
 #include <rte_atomic.h>
 #include <rte_fbarray.h>
 
 #include "eal_internal_cfg.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 #include "malloc_elem.h"
 #include "malloc_heap.h"
 #include "malloc_mp.h"
diff --git a/lib/librte_eal/common/malloc_mp.c b/lib/librte_eal/common/malloc_mp.c
index 7c6112c4e..1f212f834 100644
--- a/lib/librte_eal/common/malloc_mp.c
+++ b/lib/librte_eal/common/malloc_mp.c
@@ -10,6 +10,7 @@
 #include <rte_string_fns.h>
 
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 
 #include "malloc_elem.h"
 #include "malloc_mp.h"
diff --git a/lib/librte_eal/common/rte_malloc.c b/lib/librte_eal/common/rte_malloc.c
index 2cad7beaa..fecd9a964 100644
--- a/lib/librte_eal/common/rte_malloc.c
+++ b/lib/librte_eal/common/rte_malloc.c
@@ -25,6 +25,7 @@
 #include "malloc_elem.h"
 #include "malloc_heap.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 
 
 /* Free the memory space back to heap */
diff --git a/lib/librte_eal/freebsd/eal/Makefile b/lib/librte_eal/freebsd/eal/Makefile
index eb921275e..89131ea89 100644
--- a/lib/librte_eal/freebsd/eal/Makefile
+++ b/lib/librte_eal/freebsd/eal/Makefile
@@ -22,7 +22,7 @@ LDLIBS += -lrte_kvargs
 
 EXPORT_MAP := ../../rte_eal_version.map
 
-LIBABIVER := 10
+LIBABIVER := 11
 
 # specific to freebsd exec-env
 SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) := eal.c
diff --git a/lib/librte_eal/freebsd/eal/eal_memory.c b/lib/librte_eal/freebsd/eal/eal_memory.c
index 4b092e1f2..9b9a0577a 100644
--- a/lib/librte_eal/freebsd/eal/eal_memory.c
+++ b/lib/librte_eal/freebsd/eal/eal_memory.c
@@ -18,6 +18,7 @@
 #include "eal_private.h"
 #include "eal_internal_cfg.h"
 #include "eal_filesystem.h"
+#include "eal_memcfg.h"
 
 #define EAL_PAGE_SIZE (sysconf(_SC_PAGESIZE))
 
diff --git a/lib/librte_eal/linux/eal/Makefile b/lib/librte_eal/linux/eal/Makefile
index dfe8e9a49..0f5725e64 100644
--- a/lib/librte_eal/linux/eal/Makefile
+++ b/lib/librte_eal/linux/eal/Makefile
@@ -10,7 +10,7 @@ ARCH_DIR ?= $(RTE_ARCH)
 EXPORT_MAP := ../../rte_eal_version.map
 VPATH += $(RTE_SDK)/lib/librte_eal/common/arch/$(ARCH_DIR)
 
-LIBABIVER := 10
+LIBABIVER := 11
 
 VPATH += $(RTE_SDK)/lib/librte_eal/common
 
diff --git a/lib/librte_eal/linux/eal/eal.c b/lib/librte_eal/linux/eal/eal.c
index 8a0b387ce..f974cec1c 100644
--- a/lib/librte_eal/linux/eal/eal.c
+++ b/lib/librte_eal/linux/eal/eal.c
@@ -57,6 +57,7 @@
 #include "eal_internal_cfg.h"
 #include "eal_filesystem.h"
 #include "eal_hugepages.h"
+#include "eal_memcfg.h"
 #include "eal_options.h"
 #include "eal_vfio.h"
 #include "hotplug_mp.h"
diff --git a/lib/librte_eal/linux/eal/eal_memalloc.c b/lib/librte_eal/linux/eal/eal_memalloc.c
index 2019636fb..1f6a7c18f 100644
--- a/lib/librte_eal/linux/eal/eal_memalloc.c
+++ b/lib/librte_eal/linux/eal/eal_memalloc.c
@@ -44,6 +44,7 @@
 #include "eal_filesystem.h"
 #include "eal_internal_cfg.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 #include "eal_private.h"
 
 const int anonymous_hugepages_supported =
diff --git a/lib/librte_eal/linux/eal/eal_memory.c b/lib/librte_eal/linux/eal/eal_memory.c
index 1853acea5..9c948a374 100644
--- a/lib/librte_eal/linux/eal/eal_memory.c
+++ b/lib/librte_eal/linux/eal/eal_memory.c
@@ -46,6 +46,7 @@
 
 #include "eal_private.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 #include "eal_internal_cfg.h"
 #include "eal_filesystem.h"
 #include "eal_hugepages.h"
diff --git a/lib/librte_eal/linux/eal/eal_vfio.c b/lib/librte_eal/linux/eal/eal_vfio.c
index 96a03a657..fdc884f70 100644
--- a/lib/librte_eal/linux/eal/eal_vfio.c
+++ b/lib/librte_eal/linux/eal/eal_vfio.c
@@ -15,6 +15,7 @@
 #include <rte_vfio.h>
 
 #include "eal_filesystem.h"
+#include "eal_memcfg.h"
 #include "eal_vfio.h"
 #include "eal_private.h"
 
diff --git a/lib/librte_eal/meson.build b/lib/librte_eal/meson.build
index ccd5b85b8..2751023a9 100644
--- a/lib/librte_eal/meson.build
+++ b/lib/librte_eal/meson.build
@@ -12,7 +12,7 @@ subdir('common') # defines common_sources, common_objs, etc.
 dpdk_conf.set('RTE_EXEC_ENV_' + exec_env.to_upper(), 1)
 subdir(exec_env + '/eal')
 
-version = 10  # the version of the EAL API
+version = 11  # the version of the EAL API
 allow_experimental_apis = true
 deps += 'kvargs'
 if dpdk_conf.has('RTE_USE_LIBBSD')
diff --git a/lib/librte_efd/rte_efd.c b/lib/librte_efd/rte_efd.c
index b808ce99f..d3d019578 100644
--- a/lib/librte_efd/rte_efd.c
+++ b/lib/librte_efd/rte_efd.c
@@ -20,6 +20,7 @@
 #include <rte_ring.h>
 #include <rte_jhash.h>
 #include <rte_hash_crc.h>
+#include <rte_tailq.h>
 
 #include "rte_efd.h"
 #if defined(RTE_ARCH_X86)
diff --git a/lib/librte_hash/rte_cuckoo_hash.c b/lib/librte_hash/rte_cuckoo_hash.c
index 47cd0da5b..74d5bbd99 100644
--- a/lib/librte_hash/rte_cuckoo_hash.c
+++ b/lib/librte_hash/rte_cuckoo_hash.c
@@ -27,6 +27,7 @@
 #include <rte_ring.h>
 #include <rte_compat.h>
 #include <rte_vect.h>
+#include <rte_tailq.h>
 
 #include "rte_hash.h"
 #include "rte_cuckoo_hash.h"
diff --git a/lib/librte_hash/rte_fbk_hash.c b/lib/librte_hash/rte_fbk_hash.c
index db118c930..576e8e666 100644
--- a/lib/librte_hash/rte_fbk_hash.c
+++ b/lib/librte_hash/rte_fbk_hash.c
@@ -20,6 +20,7 @@
 #include <rte_cpuflags.h>
 #include <rte_log.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_fbk_hash.h"
 
diff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c
index b91f74216..70c24ac1f 100644
--- a/lib/librte_lpm/rte_lpm.c
+++ b/lib/librte_lpm/rte_lpm.c
@@ -21,6 +21,7 @@
 #include <rte_errno.h>
 #include <rte_rwlock.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_lpm.h"
 
diff --git a/lib/librte_lpm/rte_lpm6.c b/lib/librte_lpm/rte_lpm6.c
index 5af74a539..9b8aeb972 100644
--- a/lib/librte_lpm/rte_lpm6.c
+++ b/lib/librte_lpm/rte_lpm6.c
@@ -24,6 +24,7 @@
 #include <rte_hash.h>
 #include <assert.h>
 #include <rte_jhash.h>
+#include <rte_tailq.h>
 
 #include "rte_lpm6.h"
 
diff --git a/lib/librte_member/rte_member.c b/lib/librte_member/rte_member.c
index efed28dd9..e0e7f127e 100644
--- a/lib/librte_member/rte_member.c
+++ b/lib/librte_member/rte_member.c
@@ -10,6 +10,7 @@
 #include <rte_memory.h>
 #include <rte_malloc.h>
 #include <rte_errno.h>
+#include <rte_tailq.h>
 
 #include "rte_member.h"
 #include "rte_member_ht.h"
diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c
index 5c688d456..7260ce0be 100644
--- a/lib/librte_mempool/rte_mempool.c
+++ b/lib/librte_mempool/rte_mempool.c
@@ -30,6 +30,7 @@
 #include <rte_errno.h>
 #include <rte_string_fns.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_mempool.h"
 
diff --git a/lib/librte_rcu/rte_rcu_qsbr.h b/lib/librte_rcu/rte_rcu_qsbr.h
index 53a5a7165..c80f15c00 100644
--- a/lib/librte_rcu/rte_rcu_qsbr.h
+++ b/lib/librte_rcu/rte_rcu_qsbr.h
@@ -24,6 +24,7 @@
 extern "C" {
 #endif
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <inttypes.h>
diff --git a/lib/librte_reorder/rte_reorder.c b/lib/librte_reorder/rte_reorder.c
index ae6e3f578..3c9f0e2d0 100644
--- a/lib/librte_reorder/rte_reorder.c
+++ b/lib/librte_reorder/rte_reorder.c
@@ -11,6 +11,7 @@
 #include <rte_eal_memconfig.h>
 #include <rte_errno.h>
 #include <rte_malloc.h>
+#include <rte_tailq.h>
 
 #include "rte_reorder.h"
 
diff --git a/lib/librte_ring/rte_ring.c b/lib/librte_ring/rte_ring.c
index 9ea26a631..b30b2aa7b 100644
--- a/lib/librte_ring/rte_ring.c
+++ b/lib/librte_ring/rte_ring.c
@@ -30,6 +30,7 @@
 #include <rte_errno.h>
 #include <rte_string_fns.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_ring.h"
 
-- 
2.17.1

^ permalink raw reply	[relevance 7%]

* Re: [dpdk-dev] [PATCH v4] cryptodev: make xform key pointer constant
  2019-06-25 12:46  4%   ` Akhil Goyal
@ 2019-07-05 12:30  0%     ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2019-07-05 12:30 UTC (permalink / raw)
  To: Akhil Goyal, Fan Zhang; +Cc: dev, pablo.de.lara.guarch

25/06/2019 14:46, Akhil Goyal:
> 
> > 
> > This patch changes the key pointer data types in cipher, auth,
> > and aead xforms from "uint8_t *" to "const uint8_t *" for a
> > more intuitive and safe sessionn creation.
> > 
> > Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
> > Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
> > Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
> > ---
> > v4:
> > - Removed deprecation notice and updated release note.
> > - Updated ABI version.
> > 
> > v3:
> > - rebased on top of latest dpdk-next-crypto
> > 
> > v2:
> > - fixed a missed memory free for ixgbe ipsec
> 
> Applied to dpdk-next-crypto
> The changes related to update for ABI version were incomplete in this patch, so they were dropped. Another patch from Anoob was also updating the ABI version, so not required in this patch.


I think this patch is not complete, because there is a compilation issue
with mvsam PMD when compiling arm64-thunderx-linux-gcc:

	drivers/crypto/mvsam/rte_mrvl_pmd.c:260:35: error:
	assignment discards 'const' qualifier from pointer target type




^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] [v1]vhost: support inflight share memory protocol feature
  @ 2019-07-05  8:47  3% ` Maxime Coquelin
  2019-07-08  7:23  0%   ` Yu, Jin
  0 siblings, 1 reply; 200+ results
From: Maxime Coquelin @ 2019-07-05  8:47 UTC (permalink / raw)
  To: JinYu, dev; +Cc: changpeng.liu, LinLi, XunNi, YuZhang, Tiwei Bie

Hi Jin,

On 6/26/19 6:38 PM, JinYu wrote:
> This patch introduces two new messages VHOST_USER_GET_INFLIGHT_FD
> and VHOST_USER_SET_INFLIGHT_FD to support transferring a shared
> buffer between qemu and backend.
> 
> Firstly, qemu uses VHOST_USER_GET_INFLIGHT_FD to get the
> shared buffer from backend. Then qemu should send it back
> through VHOST_USER_SET_INFLIGHT_FD each time we start vhost-user.
> 
> This shared buffer is used to process inflight I/O when backend
> reconnect.
> 
> Signed-off-by: LinLi <lilin24@baidu.com>
> Signed-off-by: XunNi <nixun@baidu.com>
> Signed-off-by: YuZhang <zhangyu31@baidu.com>
> Signed-off-by: JinYu <jin.yu@intel.com>
> ---
> V1 - specify the APIs are split-ring only
> ---
>   lib/librte_vhost/rte_vhost.h           |  99 +++++++++
>   lib/librte_vhost/rte_vhost_version.map |   4 +
>   lib/librte_vhost/vhost.c               | 135 ++++++++++++
>   lib/librte_vhost/vhost.h               |  12 +
>   lib/librte_vhost/vhost_user.c          | 292 +++++++++++++++++++++++++
>   lib/librte_vhost/vhost_user.h          |  13 +-
>   6 files changed, 554 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h
> index 0226b3eff..c9959c15a 100644
> --- a/lib/librte_vhost/rte_vhost.h
> +++ b/lib/librte_vhost/rte_vhost.h
> @@ -71,6 +71,10 @@ extern "C" {
>   #define VHOST_USER_PROTOCOL_F_HOST_NOTIFIER 11
>   #endif
>   
> +#ifndef VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD
> +#define VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD 12
> +#endif
> +
>   /** Indicate whether protocol features negotiation is supported. */
>   #ifndef VHOST_USER_F_PROTOCOL_FEATURES
>   #define VHOST_USER_F_PROTOCOL_FEATURES	30
> @@ -98,12 +102,41 @@ struct rte_vhost_memory {
>   	struct rte_vhost_mem_region regions[];
>   };
>   
> +struct inflight_desc_split {
> +	uint8_t		inflight;
> +	uint8_t		padding[5];
> +	uint16_t	next;
> +	uint64_t	counter;
> +};
> +
> +struct inflight_info_split {
> +	uint64_t		features;
> +	uint16_t		version;
> +	uint16_t		desc_num;
> +	uint16_t		last_inflight_io;
> +	uint16_t		used_idx;
> +	struct inflight_desc_split desc[0];
> +};
> +
> +struct resubmit_desc {
> +	uint16_t index;
> +	uint64_t counter;
> +};
> +
> +struct resubmit_info {
> +	struct resubmit_desc	*resubmit_list;
> +	uint16_t		resubmit_num;
> +};
> +
>   struct rte_vhost_vring {
>   	struct vring_desc	*desc;
>   	struct vring_avail	*avail;
>   	struct vring_used	*used;
>   	uint64_t		log_guest_addr;
>   
> +	struct inflight_info_split *inflight;
> +	struct resubmit_info	*resubmit_inflight;
> +

This is breaking the ABI, and discussing with Tiwei, we think it could
be avoided by defining its own structure of inflight and inflight
resubmit pointers. More below:

>   	/** Deprecated, use rte_vhost_vring_call() instead. */
>   	int			callfd;
>   
> @@ -603,6 +636,22 @@ uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
>    */
>   int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
>   
> +/**
> + * Get guest vring info, including the vring address, vring size, inflight, etc.
> + *
> + * @param vid
> + *  vhost device ID
> + * @param vring_idx
> + *  vring index
> + * @param vring
> + *  the structure to hold the requested vring info
> + * @return
> + *  0 on success, -1 on failure
> + */
> +int __rte_experimental
> +rte_vhost_get_vhost_vring_with_inflight_split(int vid, uint16_t vring_idx,
> +			      struct rte_vhost_vring *vring);

Here a new API is introduced to get vting info with inflight.
It could be just changed to get only the inflight info. It means the
caller would first call rte_vhost_get_vhost_vring() and then the new
function, which I guess may be renamed to:

rte_vhost_get_vhost_vring_inflight_split

Other than that, the patch looks good to me.

(Next time, please run get_maintainer.sh script so that all the
maintainers are in Cc:).

Thanks,
Maxime

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v3 00/14] Make shared memory config non-public
  2019-07-04  8:09  3%       ` David Marchand
@ 2019-07-04 19:52  0%         ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2019-07-04 19:52 UTC (permalink / raw)
  To: David Marchand, Anatoly Burakov; +Cc: dev, Stephen Hemminger

04/07/2019 10:09, David Marchand:
> I just want to state two approaches to merge these changes:
> - the first one would be to split this series in two
>   - take the first part of this series now, but mark the new API
> "experimental"
>   - postpone the merge to 19.11 of the second part, which starts at the
> hiding rte_mem_config patch
> - the second one is taking these changes in one go
> 
> The second one is the quicker and the more straightforward but it leaves
> the risk of having missed something and we must break the ABI again in
> 19.11.
> The risk is quite low, given the changes.
> 
> 
> Thomas, comments?

OK to merge it in one go.
Please, can we merge it tomorrow?





^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v7 1/2] ring: add reset API to flush the ring when not in use
  @ 2019-07-04 14:42  0%     ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2019-07-04 14:42 UTC (permalink / raw)
  To: Gavin Hu
  Cc: dev, Olivier Matz, nd, jerinj, hemant.agrawal, nipun.gupta,
	Honnappa.Nagarahalli, i.maximets, stable

29/03/2019 15:17, Olivier Matz:
> Hi,
> 
> On Fri, Mar 15, 2019 at 11:31:25AM +0800, Gavin Hu wrote:
> > Currently, the flush is done by dequeuing the ring in a while loop. It is
> > much simpler to flush the queue by resetting the head and tail indices.
> > 
> > Fixes: af75078fece3 ("first public release")
> > Cc: stable@dpdk.org
> > 
> > Signed-off-by: Gavin Hu <gavin.hu@arm.com>
> > Reviewed-by: Ruifeng Wang <ruifeng.wang@arm.com>
> > Reviewed-by: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>
> > ---
> > --- a/lib/librte_ring/rte_ring_version.map
> > +++ b/lib/librte_ring/rte_ring_version.map
> > @@ -17,3 +17,10 @@ DPDK_2.2 {
> >  	rte_ring_free;
> >  
> >  } DPDK_2.0;
> > +
> > +EXPERIMENTAL {
> > +    global:
> > +
> > +	rte_ring_reset;
> > +
> > +};
> 
> To me, a static inline function does not need to be added in
> rte_ring_version.map (or is it due to a check script checking the
> __rte_experimental tag ?). I found at least one commit where it
> is not the case:
> c277b34c1b3b ("mbuf: add function returning buffer address")
> 
> There are 2 options:
> 1- remove the rte_ring_version.map part of the patch.
> 2- change the static inline function into a standard function.
> 
> I would prefer 2-, because it allows to keep an api/abi compat
> layer in the future.

There are no news about this patch.
I classify it as changes requested.




^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC] ethdev: support input set change by RSS action
  2019-07-04 13:55  0%   ` Zhang, Qi Z
@ 2019-07-04 14:08  3%     ` Adrien Mazarguil
  2019-07-09  5:41  3%       ` Zhang, Qi Z
  0 siblings, 1 reply; 200+ results
From: Adrien Mazarguil @ 2019-07-04 14:08 UTC (permalink / raw)
  To: Zhang, Qi Z; +Cc: Su, Simei, Wu, Jingjing, Xing, Beilei, Yang, Qiming, dev

On Thu, Jul 04, 2019 at 01:55:14PM +0000, Zhang, Qi Z wrote:
> 
> 
> > -----Original Message-----
> > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > Sent: Thursday, July 4, 2019 5:07 PM
> > To: Su, Simei <simei.su@intel.com>
> > Cc: Zhang, Qi Z <qi.z.zhang@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>;
> > Xing, Beilei <beilei.xing@intel.com>; Yang, Qiming <qiming.yang@intel.com>;
> > dev@dpdk.org
> > Subject: Re: [dpdk-dev] [RFC] ethdev: support input set change by RSS action
> > 
> > On Thu, Jul 04, 2019 at 12:47:09PM +0800, simei wrote:
> > > From: Simei Su <simei.su@intel.com>
> > >
> > > This RFC introduces inputset structure to rte_flow_action_rss to
> > > support input set specific configuration by rte_flow RSS action.
> > >
> > > We can give an testpmd command line example to make it more clear.
> > >
> > > For example, below flow selects the l4 port as inputset for any
> > > eth/ipv4/tcp packet: #flow create 0 ingress pattern eth / ipv4 / tcp /
> > > end actions rss inputset tcp src mask 0xffff dst mask 0xffff /end
> > >
> > > Signed-off-by: Simei Su <simei.su@intel.com>
> > > ---
> > >  lib/librte_ethdev/rte_flow.h | 3 +++
> > >  1 file changed, 3 insertions(+)
> > >
> > > diff --git a/lib/librte_ethdev/rte_flow.h
> > > b/lib/librte_ethdev/rte_flow.h index f3a8fb1..2a455b6 100644
> > > --- a/lib/librte_ethdev/rte_flow.h
> > > +++ b/lib/librte_ethdev/rte_flow.h
> > > @@ -1796,6 +1796,9 @@ struct rte_flow_action_rss {
> > >  	uint32_t queue_num; /**< Number of entries in @p queue. */
> > >  	const uint8_t *key; /**< Hash key. */
> > >  	const uint16_t *queue; /**< Queue indices to use. */
> > > +	struct rte_flow_item *inputset; /** Provide more specific inputset
> > configuration.
> > > +					 * ignore spec, only mask.
> > > +					 */
> > >  };
> > >
> > >  /**
> > 
> > To make sure I understand, is this kind of a more flexible version of
> > rte_flow_action_rss.types?
> 
> Yes
> > 
> > For instance while specifying .types = ETH_RSS_IPV4 normally covers both
> > source and destination addresses, does this approach enable users to perform
> > RSS on source IP only? 
> 
> Yes, .it is the case to select any subset of 5 tuples or even tunnel header's id for hash
> 
> > In which case, what value does the Toeplitz algorithm
> > assume for the destination, 0x0? (note: must be documented)
> 
> My understanding is src/dst pair is only required for a symmetric case
> But for Toeplitz, it is just a hash function, it process a serial of data with specific algorithm, have no idea about which part is src and dst , 
> So for ip src only with Toeplitz, dst is not required to be a placeholder..

Right, I had symmetric Toeplitz in mind and wondered what would happen when
users would not select the required fields. I guess the PMD would have to
reject unsupported combinations.

> anything I missed, would you share more insight?

No, that answers the question, thanks.

Now what about my suggestion below? In short: extending ETH_RSS_* assuming
there's enough bits left in there, instead of adding a whole new framework
and breaking ABI in the process.

> > My opinion is that, unless you know of a hardware which can perform RSS on
> > random bytes of a packet, this approach is a bit overkill at this point.
> > 
> > How about simply adding the needed ETH_RSS_* definitions (e.g.
> > ETH_RSS_IPV4_(SRC|DST))? How many are needed?
> > 
> > There are currently 20 used bits and struct rte_flow_action_rss.types is 64-bit
> > wide. I'm sure we can manage something without harming the ABI. Even
> > better, you wouldn't need a deprecation notice.
> > 
> > If you use the suggested approach, please update testpmd and its
> > documentation as part of the same patch, thanks.

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC] ethdev: support input set change by RSS action
  2019-07-04  9:07  3% ` Adrien Mazarguil
@ 2019-07-04 13:55  0%   ` Zhang, Qi Z
  2019-07-04 14:08  3%     ` Adrien Mazarguil
  0 siblings, 1 reply; 200+ results
From: Zhang, Qi Z @ 2019-07-04 13:55 UTC (permalink / raw)
  To: Adrien Mazarguil, Su, Simei; +Cc: Wu, Jingjing, Xing, Beilei, Yang, Qiming, dev



> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Thursday, July 4, 2019 5:07 PM
> To: Su, Simei <simei.su@intel.com>
> Cc: Zhang, Qi Z <qi.z.zhang@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>;
> Xing, Beilei <beilei.xing@intel.com>; Yang, Qiming <qiming.yang@intel.com>;
> dev@dpdk.org
> Subject: Re: [dpdk-dev] [RFC] ethdev: support input set change by RSS action
> 
> On Thu, Jul 04, 2019 at 12:47:09PM +0800, simei wrote:
> > From: Simei Su <simei.su@intel.com>
> >
> > This RFC introduces inputset structure to rte_flow_action_rss to
> > support input set specific configuration by rte_flow RSS action.
> >
> > We can give an testpmd command line example to make it more clear.
> >
> > For example, below flow selects the l4 port as inputset for any
> > eth/ipv4/tcp packet: #flow create 0 ingress pattern eth / ipv4 / tcp /
> > end actions rss inputset tcp src mask 0xffff dst mask 0xffff /end
> >
> > Signed-off-by: Simei Su <simei.su@intel.com>
> > ---
> >  lib/librte_ethdev/rte_flow.h | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/lib/librte_ethdev/rte_flow.h
> > b/lib/librte_ethdev/rte_flow.h index f3a8fb1..2a455b6 100644
> > --- a/lib/librte_ethdev/rte_flow.h
> > +++ b/lib/librte_ethdev/rte_flow.h
> > @@ -1796,6 +1796,9 @@ struct rte_flow_action_rss {
> >  	uint32_t queue_num; /**< Number of entries in @p queue. */
> >  	const uint8_t *key; /**< Hash key. */
> >  	const uint16_t *queue; /**< Queue indices to use. */
> > +	struct rte_flow_item *inputset; /** Provide more specific inputset
> configuration.
> > +					 * ignore spec, only mask.
> > +					 */
> >  };
> >
> >  /**
> 
> To make sure I understand, is this kind of a more flexible version of
> rte_flow_action_rss.types?

Yes
> 
> For instance while specifying .types = ETH_RSS_IPV4 normally covers both
> source and destination addresses, does this approach enable users to perform
> RSS on source IP only? 

Yes, .it is the case to select any subset of 5 tuples or even tunnel header's id for hash

> In which case, what value does the Toeplitz algorithm
> assume for the destination, 0x0? (note: must be documented)

My understanding is src/dst pair is only required for a symmetric case
But for Toeplitz, it is just a hash function, it process a serial of data with specific algorithm, have no idea about which part is src and dst , 
So for ip src only with Toeplitz, dst is not required to be a placeholder..
anything I missed, would you share more insight?

Thanks
Qi

> 
> My opinion is that, unless you know of a hardware which can perform RSS on
> random bytes of a packet, this approach is a bit overkill at this point.
> 
> How about simply adding the needed ETH_RSS_* definitions (e.g.
> ETH_RSS_IPV4_(SRC|DST))? How many are needed?
> 
> There are currently 20 used bits and struct rte_flow_action_rss.types is 64-bit
> wide. I'm sure we can manage something without harming the ABI. Even
> better, you wouldn't need a deprecation notice.
> 
> If you use the suggested approach, please update testpmd and its
> documentation as part of the same patch, thanks.
> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC] ethdev: support symmetric hash function
  2019-07-04 12:48  3%   ` Zhang, Qi Z
@ 2019-07-04 13:19  3%     ` Adrien Mazarguil
  0 siblings, 0 replies; 200+ results
From: Adrien Mazarguil @ 2019-07-04 13:19 UTC (permalink / raw)
  To: Zhang, Qi Z
  Cc: Su, Simei, Wu, Jingjing, Xing, Beilei, Yang, Qiming, dev,
	Shahaf Shuler, Yongseok Koh

On Thu, Jul 04, 2019 at 12:48:25PM +0000, Zhang, Qi Z wrote:
> 
> 
> > -----Original Message-----
> > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > Sent: Thursday, July 4, 2019 5:07 PM
> > To: Su, Simei <simei.su@intel.com>
> > Cc: Zhang, Qi Z <qi.z.zhang@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>;
> > Xing, Beilei <beilei.xing@intel.com>; Yang, Qiming <qiming.yang@intel.com>;
> > dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Yongseok Koh
> > <yskoh@mellanox.com>
> > Subject: Re: [dpdk-dev] [RFC] ethdev: support symmetric hash function
> > 
> > On Thu, Jul 04, 2019 at 12:46:07PM +0800, simei wrote:
> > > From: Simei Su <simei.su@intel.com>
> > >
> > > Currently, there are DEFAULT,TOEPLITZ and SIMPLE_XOR hash funtion.
> > > To support symmetric hash by rte_flow RSS action, this RFC introduces
> > > SYMMETRIC_TOEPLITZ to rte_eth_hash_function.
> > >
> > > Signed-off-by: Simei Su <simei.su@intel.com>
> > > ---
> > >  lib/librte_ethdev/rte_flow.h | 1 +
> > >  1 file changed, 1 insertion(+)
> > >
> > > diff --git a/lib/librte_ethdev/rte_flow.h
> > > b/lib/librte_ethdev/rte_flow.h index f3a8fb1..e3c4fe5 100644
> > > --- a/lib/librte_ethdev/rte_flow.h
> > > +++ b/lib/librte_ethdev/rte_flow.h
> > > @@ -1744,6 +1744,7 @@ enum rte_eth_hash_function {
> > >  	RTE_ETH_HASH_FUNCTION_DEFAULT = 0,
> > >  	RTE_ETH_HASH_FUNCTION_TOEPLITZ, /**< Toeplitz */
> > >  	RTE_ETH_HASH_FUNCTION_SIMPLE_XOR, /**< Simple XOR */
> > > +	RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ, /**< Symmetric
> > TOEPLITZ */
> > 
> > "Symmetric TOEPLITZ" => "Symmetric Toeplitz."
> > 
> > >  	RTE_ETH_HASH_FUNCTION_MAX,
> > >  };
> > 
> > Other than that, no problem with this change (no ABI impact, no need for
> > deprecation). Please update testpmd a part of the same patch:
> 
> Is it still ABI break but just with little risk? 
> RTE_ETH_HASH_FUNCTION_MAX's value is changed anyway.
> Should we just remove it, if no one use it?

Indeed, it will update RTE_ETH_HASH_FUNCTION_MAX so you're technically
right, and the fact it's unused in DPDK is doesn't mean applications are not
using it for something.

However for this specific case, the intent behind RTE_ETH_HASH_FUNCTION_MAX
is clearly to give out the number of enum entries, applications are not
supposed to use it for anything other than determining if an arbitrary
integer value corresponds to a valid hash function.

And this is the reason we could say it's OK ABI-wise to increase it (not
ideal but acceptable): a binary application has a fixed idea of
RTE_ETH_HASH_FUNCTION_MAX, it doesn't know the entries you're about to add
yet. To such an application, those will exceed RTE_ETH_HASH_FUNCTION_MAX and
should be rejected accordingly.

A more conservative approach would be to mark RTE_ETH_HASH_FUNCTION_MAX as
deprecated (in a separate patch) and schedule it for removal while adding
new entries after it. Its position in the enum could be recycled once
removed.

If you want to remove RTE_ETH_HASH_FUNCTION_MAX directly, do it in a
separate RFC/patch as it will otherwise block the rest of your submission
for something like 2 releases after deprecation.

It's up to you. I'm fine with any of these approaches.

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC] ethdev: support symmetric hash function
  2019-07-04  9:06  3% ` Adrien Mazarguil
@ 2019-07-04 12:48  3%   ` Zhang, Qi Z
  2019-07-04 13:19  3%     ` Adrien Mazarguil
  0 siblings, 1 reply; 200+ results
From: Zhang, Qi Z @ 2019-07-04 12:48 UTC (permalink / raw)
  To: Adrien Mazarguil, Su, Simei
  Cc: Wu, Jingjing, Xing, Beilei, Yang, Qiming, dev, Shahaf Shuler,
	Yongseok Koh



> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Thursday, July 4, 2019 5:07 PM
> To: Su, Simei <simei.su@intel.com>
> Cc: Zhang, Qi Z <qi.z.zhang@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>;
> Xing, Beilei <beilei.xing@intel.com>; Yang, Qiming <qiming.yang@intel.com>;
> dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Yongseok Koh
> <yskoh@mellanox.com>
> Subject: Re: [dpdk-dev] [RFC] ethdev: support symmetric hash function
> 
> On Thu, Jul 04, 2019 at 12:46:07PM +0800, simei wrote:
> > From: Simei Su <simei.su@intel.com>
> >
> > Currently, there are DEFAULT,TOEPLITZ and SIMPLE_XOR hash funtion.
> > To support symmetric hash by rte_flow RSS action, this RFC introduces
> > SYMMETRIC_TOEPLITZ to rte_eth_hash_function.
> >
> > Signed-off-by: Simei Su <simei.su@intel.com>
> > ---
> >  lib/librte_ethdev/rte_flow.h | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/lib/librte_ethdev/rte_flow.h
> > b/lib/librte_ethdev/rte_flow.h index f3a8fb1..e3c4fe5 100644
> > --- a/lib/librte_ethdev/rte_flow.h
> > +++ b/lib/librte_ethdev/rte_flow.h
> > @@ -1744,6 +1744,7 @@ enum rte_eth_hash_function {
> >  	RTE_ETH_HASH_FUNCTION_DEFAULT = 0,
> >  	RTE_ETH_HASH_FUNCTION_TOEPLITZ, /**< Toeplitz */
> >  	RTE_ETH_HASH_FUNCTION_SIMPLE_XOR, /**< Simple XOR */
> > +	RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ, /**< Symmetric
> TOEPLITZ */
> 
> "Symmetric TOEPLITZ" => "Symmetric Toeplitz."
> 
> >  	RTE_ETH_HASH_FUNCTION_MAX,
> >  };
> 
> Other than that, no problem with this change (no ABI impact, no need for
> deprecation). Please update testpmd a part of the same patch:

Is it still ABI break but just with little risk? 
RTE_ETH_HASH_FUNCTION_MAX's value is changed anyway.
Should we just remove it, if no one use it?

Regards
Qi
> 
> - Wherever "toeplitz" is mentioned in test-pmd/cmdline.c.
> 
> - Ditto for flow command, i.e. add ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ
> to
>   test-pmd/cmdline_flow.c.
> 
> - Update "set_hash_global_config" documentation section in
>   testpmd_app_ug/testpmd_funcs.rst.
> 
> Note to Shahaf/Yongseok, since mlx5 supports both but defaults to symmetric
> Toeplitz on vanilla Linux and standard Toeplitz when using OFED, how about
> using this chance to make the algorithm configurable as well?
> 
> Thanks.
> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH] doc: Changes to ABI Policy introducing major ABI versions
  2019-07-04 12:26 11% [dpdk-dev] [PATCH] Changes to ABI Policy introducing major ABI versions Ray Kinsella
@ 2019-07-04 12:26 31% ` Ray Kinsella
  0 siblings, 0 replies; 200+ results
From: Ray Kinsella @ 2019-07-04 12:26 UTC (permalink / raw)
  To: dev; +Cc: mdr

This policy change introduces major ABI versions, these are
declared every two years, typically aligned with the LTS release
and are supported by subsequent releases for the next two years.
This change is intended to improve ABI stabilty for those projects
consuming DPDK.

Signed-off-by: Ray Kinsella <mdr@ashroe.eu>
---
 doc/guides/contributing/stable.rst     |  10 +-
 doc/guides/contributing/versioning.rst | 462 ++++++++++++++++++++++-----------
 2 files changed, 314 insertions(+), 158 deletions(-)

diff --git a/doc/guides/contributing/stable.rst b/doc/guides/contributing/stable.rst
index 6a5eee9..0a678be 100644
--- a/doc/guides/contributing/stable.rst
+++ b/doc/guides/contributing/stable.rst
@@ -53,6 +53,9 @@ year's November (X.11) release will be maintained as an LTS for 2 years.
 After the X.11 release, an LTS branch will be created for it at
 http://git.dpdk.org/dpdk-stable where bugfixes will be backported to.
 
+A LTS release may align with the declaration of a new major ABI version,
+please read the `DPDK ABI/API policy`_ for more information. 
+
 It is anticipated that there will be at least 4 releases per year of the LTS
 or approximately 1 every 3 months. However, the cadence can be shorter or
 longer depending on the number and criticality of the backported
@@ -119,10 +122,3 @@ A Stable Release will be released by:
   list.
 
 Stable releases are available on the `dpdk.org download page <http://core.dpdk.org/download/>`_.
-
-
-ABI
----
-
-The Stable Release should not be seen as a way of breaking or circumventing
-the DPDK ABI policy.
diff --git a/doc/guides/contributing/versioning.rst b/doc/guides/contributing/versioning.rst
index 3ab2c43..b7b5514 100644
--- a/doc/guides/contributing/versioning.rst
+++ b/doc/guides/contributing/versioning.rst
@@ -12,20 +12,23 @@ This document details some methods for handling ABI management in the DPDK.
 General Guidelines
 ------------------
 
-#. Whenever possible, ABI should be preserved
-#. ABI/API may be changed with a deprecation process
-#. The modification of symbols can generally be managed with versioning
-#. Libraries or APIs marked in ``experimental`` state may change without constraint
-#. New APIs will be marked as ``experimental`` for at least one release to allow
-   any issues found by users of the new API to be fixed quickly
-#. The addition of symbols is generally not problematic
-#. The removal of symbols generally is an ABI break and requires bumping of the
-   LIBABIVER macro
-#. Updates to the minimum hardware requirements, which drop support for hardware which
-   was previously supported, should be treated as an ABI change.
-
-What is an ABI
-~~~~~~~~~~~~~~
+#. Major ABI versions are declared every **two years** and are then supported
+   for two years, typically aligned with the LTS release.
+#. ABI versioning is managed at a project level in DPDK, with the supported ABI
+   version reflected in all library's soname.
+#. The ABI should be preserved and not changed lightly. The ABI may be changed
+   following the outlined deprecation process.
+#. The addition of symbols is generally not problematic. The modification of
+   symbols should be managed with ABI versioning.
+#. The removal of symbols is considered an ABI breakage, once approved these
+   will form part of the next ABI version.
+#. Libraries or APIs marked as ``experimental`` are not considered part of the
+   major ABI version and may change without constraint.
+#. Updates to the minimum hardware requirements, which drop support for hardware
+   which was previously supported, should be treated as an ABI change.
+
+What is an ABI?
+~~~~~~~~~~~~~~~
 
 An ABI (Application Binary Interface) is the set of runtime interfaces exposed
 by a library. It is similar to an API (Application Programming Interface) but
@@ -37,30 +40,55 @@ Therefore, in the case of dynamic linking, it is critical that an ABI is
 preserved, or (when modified), done in such a way that the application is unable
 to behave improperly or in an unexpected fashion.
 
+What is a library's soname?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+System libraries usually adopt the familiar major and minor version naming
+convention, where major versions (e.g. ``librte_a 1.x, 2.x``) are presumed to be
+ABI incompatible with each other and minor versions (e.g. ``librte_a 2.11,
+2.12``) are presumed to be ABI compatible. A library's `soname
+<https://en.wikipedia.org/wiki/Soname>`_. is typically used to provide backward
+compatibility information about a given library, describing the lowest common
+denominator ABI supported by the library. The soname is typically comprised of
+the library's name and major version e.g. ``librte_a.so.20``.
+
+During an application's build process, a library's soname is noted as a runtime
+dependency of the application. This information is then used by the `dynamic
+linker <https://en.wikipedia.org/wiki/Dynamic_linker>`_ when resolving the
+applications dependencies at runtime, to load a library supporting the correct
+ABI version. The library loaded at runtime therefore, may be a minor revision
+supporting the same major abi version (e.g. ``librte_a 20.12``), as the library
+used to link the application (e.g ``librte_a 20.0``).
 
-ABI/API Deprecation
+The DPDK ABI policy
 -------------------
 
-The DPDK ABI policy
-~~~~~~~~~~~~~~~~~~~
+A major ABI version is declared every two years, aligned with that years LTS
+release, e.g. v19.11 . This ABI version is then supported for two years by all
+subsequent releases within that time period, typically including the next LTS
+release, e.g. v20.11.
+
+At the declaration of a major ABI version, major version numbers encoded in
+libraries soname's are bumped to indicate the new version, with minor version
+reset to 0. An example would be ``librte_a.so.20.5`` would become
+``librte_a.so.21.0``
 
-ABI versions are set at the time of major release labeling, and the ABI may
-change multiple times, without warning, between the last release label and the
-HEAD label of the git tree.
+The ABI may change then multiple times, without warning, between the last major
+ABI version increment and the HEAD label of the git tree, with the condition
+that ABI compatibility with the major ABI version is preserved and therefore
+soname's do not change.
 
-ABI versions, once released, are available until such time as their
-deprecation has been noted in the Release Notes for at least one major release
-cycle. For example consider the case where the ABI for DPDK 2.0 has been
-shipped and then a decision is made to modify it during the development of
-DPDK 2.1. The decision will be recorded in the Release Notes for the DPDK 2.1
-release and the modification will be made available in the DPDK 2.2 release.
+ABI versions, are supported by each release until such time as the next major
+ABI version is declared. At that time, the deprecation of the previous major ABI
+version will be noted in the Release Notes with guidance on individual symbol
+depreciation and upgrade notes provided.
 
-ABI versions may be deprecated in whole or in part as needed by a given
-update.
+ABI Changes
+~~~~~~~~~~~
 
-Some ABI changes may be too significant to reasonably maintain multiple
-versions. In those cases ABI's may be updated without backward compatibility
-being provided. The requirements for doing so are:
+The ABI may still change after the declaration of a major ABI version, that is
+new APIs may be still added or existing APIs may be modified. The requirements
+for doing so are:
 
 #. At least 3 acknowledgments of the need to do so must be made on the
    dpdk.org mailing list.
@@ -69,81 +97,156 @@ being provided. The requirements for doing so are:
      no maintainer is available for the component, the tree/sub-tree maintainer
      for that component must acknowledge the ABI change instead.
 
+   - The acknowledgment of a member of the technical board, as a delegate of the
+     `technical board <https://core.dpdk.org/techboard/>`_ acknowledging the
+     need for the ABI change, is also mandatory.
+
    - It is also recommended that acknowledgments from different "areas of
      interest" be sought for each deprecation, for example: from NIC vendors,
      CPU vendors, end-users, etc.
 
-#. The changes (including an alternative map file) can be included with
-   deprecation notice, in wrapped way by the ``RTE_NEXT_ABI`` option,
-   to provide more details about oncoming changes.
-   ``RTE_NEXT_ABI`` wrapper will be removed when it become the default ABI.
-   More preferred way to provide this information is sending the feature
-   as a separate patch and reference it in deprecation notice.
+#. Backward compatibly with the major ABI version must be maintained through
+   `ABI versioning`_, with forward-only compatibility offered for any ABI
+   changes that are indicated to be part of the next ABI version.
+
+   - In situations where backward compatibility is not possible, read the
+     section `ABI  Breakages`_.
+
+   - No backward or forward compatibility is offered for API changes marked as
+     ``experimental``, as described in the section `Experimental APIs`_.
+
+#. If a newly proposed API functionally replaces an existing one, when the new
+   API becomes non-experimental then the old one is marked with
+   ``__rte_deprecated``.
+
+    - The depreciated API should follow the notification process to be removed,
+      see `Examples of Deprecation Notices`_;
+
+    - At the declaration of the next major ABI version, those ABI changes then
+      become a formal part of the new ABI and the requirement to preserve ABI
+      compatibility with the last major ABI version is then dropped.
 
-#. A full deprecation cycle, as explained above, must be made to offer
-   downstream consumers sufficient warning of the change.
+.. note::
 
-Note that the above process for ABI deprecation should not be undertaken
-lightly. ABI stability is extremely important for downstream consumers of the
-DPDK, especially when distributed in shared object form. Every effort should
-be made to preserve the ABI whenever possible. The ABI should only be changed
-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 that the above process for ABI deprecation should not be undertaken
+   lightly. ABI stability is extremely important for downstream consumers of the
+   DPDK, especially when distributed in shared object form. Every effort should
+   be made to preserve the ABI whenever possible. The ABI should only be changed
+   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::
+
+   Note that forward-only compatibility is offered for those changes made
+   between major ABI versions. The soname however only describes compatibility
+   with the last major ABI version and until the next major ABI version is
+   declared, these changes therefore cannot be resolved as a runtime dependency
+   through the soname. Therefore any application wishing to make use of these
+   ABI changes can only ensure that it's runtime dependencies are met through
+   Operating System package versioning.
 
 .. note::
 
    Updates to the minimum hardware 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.
+   follow the relevant deprecation policy procedures as above: 3 acks, technical
+   board approval and announcement at least one release in advance.
+
+
+ABI Breakages
+^^^^^^^^^^^^^
+
+For those ABI changes that may be too significant to reasonably maintain
+multiple versions. In those cases, ABIs may be updated without backward
+compatibility being provided.
+
+The additional requirements to approve an ABI breakage, on top of those
+described in the section `ABI Changes`_ are:
+
+#. ABI breaking changes (including an alternative map file) can be included with
+   deprecation notice, in wrapped way by the ``RTE_NEXT_ABI`` option, to provide
+   more details about oncoming changes. ``RTE_NEXT_ABI`` wrapper will be removed
+   at the declaration of the next major ABI version.
+
+#. Once approved and after the depreciation notice has been observed these
+   changes will form part of the next declared major ABI version.
+
+Examples of ABI Changes
+^^^^^^^^^^^^^^^^^^^^^^^
+
+The following are examples of allowable ABI changes occurring between
+declarations of major ABI versions.
+
+* DPDK 20.0 release defines the function ``rte_foo()``, and ``rte_foo()``
+  is part of the major ABI version DPDK 20.0.
+
+* DPDK 20.2 release defines a new function ``rte_foo(uint8_t bar)``, and
+  this is not a problem as long as the symbol ``rte_foo@DPDK20.0`` is
+  preserved through `ABI versioning`_.
+
+  - The new function may be marked with the ``__rte_experimental`` tag for a
+    number of releases, as described in the section `Experimental APIs`_;
+
+  - Once ``rte_foo(uint8_t bar)`` becomes non-experimental ``rte_foo()`` is then
+    declared as ``__rte_depreciated``, with an associated deprecation notice
+    provided.
+
+* DPDK 20.1 is not re-released to include ``rte_foo(uint8_t bar)``, the new
+  version of ``rte_foo`` only exists from DPDK 20.2 onwards (forward-only
+  compatibility).
+
+* DPDK 20.1 release defines the experimental function ``__rte_experimental
+  rte_baz()``. This function may or may not exist in DPDK 20.2 and DPDK 21.0
+  releases.
+
+* An application ``dPacket`` wishes to use ``rte_foo(uint8_t bar)``, before the
+  declaration of the DPDK 21.0 major API version. The application can only
+  ensure it's runtime dependencies are met by specifying ``DPDK (>= 20.2)`` as
+  an explicit package dependency, as the soname only may only indicate the
+  supporting major ABI version.
+
+* At DPDK 21.0 release the function ``rte_foo(uint8_t bar)`` becomes
+  formally part of the major ABI version DPDK 21.0 and ``rte_foo()`` may be
+  removed.
+
 
 Examples of Deprecation Notices
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 The following are some examples of ABI deprecation notices which would be
 added to the Release Notes:
 
-* The Macro ``#RTE_FOO`` is deprecated and will be removed with version 2.0,
+* The Macro ``#RTE_FOO`` is deprecated and will be removed with version 21.0,
   to be replaced with the inline function ``rte_foo()``.
 
 * The function ``rte_mbuf_grok()`` has been updated to include a new parameter
-  in version 2.0. Backwards compatibility will be maintained for this function
-  until the release of version 2.1
+  in version 20.2. Backwards compatibility will be maintained for this function
+  until the release of DPDK version 21.0
 
-* The members of ``struct rte_foo`` have been reorganized in release 2.0 for
+* The members of ``struct rte_foo`` have been reorganized in release 20.1 for
   performance reasons. Existing binary applications will have backwards
-  compatibility in release 2.0, while newly built binaries will need to
+  compatibility in release 20.1, while newly built binaries will need to
   reference the new structure variant ``struct rte_foo2``. Compatibility will
-  be removed in release 2.2, and all applications will require updating and
+  be removed in release 21.0, and all applications will require updating and
   rebuilding to the new structure at that time, which will be renamed to the
   original ``struct rte_foo``.
 
 * Significant ABI changes are planned for the ``librte_dostuff`` library. The
-  upcoming release 2.0 will not contain these changes, but release 2.1 will,
+  upcoming release 20.1 will not contain these changes, but release 21.0 will,
   and no backwards compatibility is planned due to the extensive nature of
-  these changes. Binaries using this library built prior to version 2.1 will
+  these changes. Binaries using this library built prior to version 21.0 will
   require updating and recompilation.
 
-New API replacing previous one
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If a new API proposed functionally replaces an existing one, when the new API
-becomes non-experimental then the old one is marked with ``__rte_deprecated``.
-Deprecated APIs are removed completely just after the next LTS.
-
-Reminder that old API should follow deprecation process to be removed.
-
-
 Experimental APIs
 -----------------
 
-APIs marked as ``experimental`` are not considered part of the ABI and may
-change without warning at any time.  Since changes to APIs are most likely
-immediately after their introduction, as users begin to take advantage of
-those new APIs and start finding issues with them, new DPDK APIs will be
-automatically marked as ``experimental`` to allow for a period of stabilization
-before they become part of a tracked ABI.
+APIs marked as ``experimental`` are not considered part of an ABI version and
+may change without warning at any time. Since changes to APIs are most likely
+immediately after their introduction, as users begin to take advantage of those
+new APIs and start finding issues with them, new DPDK APIs will be automatically
+marked as ``experimental`` to allow for a period of stabilization before they
+become part of a tracked ABI version.
 
 Note that marking an API as experimental is a multi step process.
 To mark an API as experimental, the symbols which are desired to be exported
@@ -167,34 +270,97 @@ one release. Thereafter, normal process of posting patch for review to mailing
 list can be followed.
 
 
-Library versioning
-------------------
+ABI Versioning
+--------------
 
-Downstreams might want to provide different DPDK releases at the same time to
-support multiple consumers of DPDK linked against older and newer sonames.
+Major ABI versions
+~~~~~~~~~~~~~~~~~~
 
-Also due to the interdependencies that DPDK libraries can have applications
-might end up with an executable space in which multiple versions of a library
-are mapped by ld.so.
+An ABI version change to a given library, especially in core libraries such as
+``librte_mbuf``, may cause an implicit ripple effect on the ABI of it's
+dependent libraries, causing ABI breakages. There may however be no explicit
+reason to bump a dependent libraries ABI version, as there may have been no
+obvious change to the dependent library's API, even though the library's ABI
+compatibility will have been broken.
 
-Think of LibA that got an ABI bump and LibB that did not get an ABI bump but is
-depending on LibA.
+This interdependence of libraries, means that ABI versioning of libraries is
+more manageable at a project level, with all project libraries sharing a
+**single ABI version**. In addition, the need to maintain a stable ABI for some
+number of releases as described in the section `The DPDK ABI policy`_, means
+that ABI version increments need to carefully planned and managed at a project
+level.
 
-.. note::
+Major ABI versions are therefore declared every two years and are then supported
+for two years, typically aligned with the LTS release and are shared across all
+libraries. This means that a single project level ABI version, reflected in all
+individual library's soname, filename and version maps persists for two years.
 
-    Application
-    \-> LibA.old
-    \-> LibB.new -> LibA.new
+.. code-block:: none
 
-That is a conflict which can be avoided by setting ``CONFIG_RTE_MAJOR_ABI``.
-If set, the value of ``CONFIG_RTE_MAJOR_ABI`` overwrites all - otherwise per
-library - versions defined in the libraries ``LIBABIVER``.
-An example might be ``CONFIG_RTE_MAJOR_ABI=16.11`` which will make all libraries
-``librte<?>.so.16.11`` instead of ``librte<?>.so.<LIBABIVER>``.
+ $ head ./lib/librte_acl/rte_acl_version.map
+ DPDK_20.0 {
+        global:
+ ...
 
+ $ head ./lib/librte_eal/rte_eal_version.map
+ DPDK_20.0 {
+        global:
+ ...
+
+When an ABI change is made between major ABI versions to a given library, a new
+section is added to that library's version map describing the impending new ABI
+version, as described in the section `Examples of ABI Macro use`_. The
+libraries soname and filename however do not change, e.g. ``libacl.so.20``, as
+ABI compatibility with the last major ABI version continues to be preserved for
+that library.
+
+.. code-block:: none
+
+ $ head ./lib/librte_acl/rte_acl_version.map
+ DPDK_20.0 {
+        global:
+ ...
+
+ DPDK_21.0 {
+        global:
+
+ } DPDK_20.0;
+ ...
+
+ $ head ./lib/librte_eal/rte_eal_version.map
+ DPDK_20.0 {
+        global:
+ ...
+
+
+However when a new ABI version is declared, for example DPDK 21.0, old
+depreciated functions may be safely removed at this point and the entire old
+major ABI version removed, see section `Deprecating an entire ABI version`_ on
+how this may be done.
+
+.. code-block:: none
+
+ $ head ./lib/librte_acl/rte_acl_version.map
+ DPDK_21.0 {
+        global:
+ ...
+
+ $ head -n 3 ./lib/librte_eal/rte_eal_version.map
+ DPDK_21.0 {
+        global:
+ ...
+
+At the same time, the major ABI version is changed atomically across all
+libraries by incrementing the major version in individual library's soname, e.g.
+``libacl.so.21``. This is done by bumping the LIBABIVER number in the libraries
+Makefile to indicate to dynamic linking applications that this is a later, and
+possibly incompatible library version:
+
+.. code-block:: c
+
+   -LIBABIVER := 20
+   +LIBABIVER := 21
 
-ABI versioning
---------------
 
 Versioning Macros
 ~~~~~~~~~~~~~~~~~
@@ -202,7 +368,7 @@ Versioning Macros
 When a symbol is exported from a library to provide an API, it also provides a
 calling convention (ABI) that is embodied in its name, return type and
 arguments. Occasionally that function may need to change to accommodate new
-functionality or behavior. When that occurs, it is desirable to allow for
+functionality or behavior. When that occurs, it is may be required to allow for
 backward compatibility for a time with older binaries that are dynamically
 linked to the DPDK.
 
@@ -270,16 +436,16 @@ maintain previous ABI versions that are accessible only to previously compiled
 binaries
 
 The addition of a parameter to the function is ABI breaking as the function is
-public, and existing application may use it in its current form.  However, the
+public, and existing application may use it in its current form. However, the
 compatibility macros in DPDK allow a developer to use symbol versioning so that
 multiple functions can be mapped to the same public symbol based on when an
-application was linked to it.  To see how this is done, we start with the
-requisite libraries version map file.  Initially the version map file for the
-acl library looks like this
+application was linked to it. To see how this is done, we start with the
+requisite libraries version map file. Initially the version map file for the acl
+library looks like this
 
 .. code-block:: none
 
-   DPDK_2.0 {
+   DPDK_20.0 {
         global:
 
         rte_acl_add_rules;
@@ -305,7 +471,7 @@ This file needs to be modified as follows
 
 .. code-block:: none
 
-   DPDK_2.0 {
+   DPDK_20.0 {
         global:
 
         rte_acl_add_rules;
@@ -327,16 +493,16 @@ This file needs to be modified as follows
         local: *;
    };
 
-   DPDK_2.1 {
+   DPDK_21.0 {
         global:
         rte_acl_create;
 
-   } DPDK_2.0;
+   } DPDK_20.0;
 
 The addition of the new block tells the linker that a new version node is
-available (DPDK_2.1), which contains the symbol rte_acl_create, and inherits the
-symbols from the DPDK_2.0 node.  This list is directly translated into a list of
-exported symbols when DPDK is compiled as a shared library
+available (DPDK_21.0), which contains the symbol rte_acl_create, and inherits
+the symbols from the DPDK_20.0 node. This list is directly translated into a
+list of exported symbols when DPDK is compiled as a shared library
 
 Next, we need to specify in the code which function map to the rte_acl_create
 symbol at which versions.  First, at the site of the initial symbol definition,
@@ -355,22 +521,22 @@ with the public symbol name
 
 Note that the base name of the symbol was kept intact, as this is conducive to
 the macros used for versioning symbols.  That is our next step, mapping this new
-symbol name to the initial symbol name at version node 2.0.  Immediately after
+symbol name to the initial symbol name at version node 20.0.  Immediately after
 the function, we add this line of code
 
 .. code-block:: c
 
-   VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
+   VERSION_SYMBOL(rte_acl_create, _v20, 20.0);
 
 Remembering to also add the rte_compat.h header to the requisite c file where
-these changes are being made.  The above macro instructs the linker to create a
-new symbol ``rte_acl_create@DPDK_2.0``, which matches the symbol created in older
-builds, but now points to the above newly named function.  We have now mapped
-the original rte_acl_create symbol to the original function (but with a new
-name)
+these changes are being made. The above macro instructs the linker to create a
+new symbol ``rte_acl_create@DPDK_20.0``, which matches the symbol created in
+older builds, but now points to the above newly named function. We have now
+mapped the original rte_acl_create symbol to the original function (but with a
+new name)
 
-Next, we need to create the 2.1 version of the symbol.  We create a new function
-name, with a different suffix, and  implement it appropriately
+Next, we need to create the 21.0 version of the symbol. We create a new function
+name, with a different suffix, and implement it appropriately
 
 .. code-block:: c
 
@@ -384,12 +550,12 @@ name, with a different suffix, and  implement it appropriately
         return ctx;
    }
 
-This code serves as our new API call.  Its the same as our old call, but adds
-the new parameter in place.  Next we need to map this function to the symbol
-``rte_acl_create@DPDK_2.1``.  To do this, we modify the public prototype of the call
-in the header file, adding the macro there to inform all including applications,
-that on re-link, the default rte_acl_create symbol should point to this
-function.  Note that we could do this by simply naming the function above
+This code serves as our new API call. Its the same as our old call, but adds the
+new parameter in place. Next we need to map this function to the symbol
+``rte_acl_create@DPDK_21.0``. To do this, we modify the public prototype of the
+call in the header file, adding the macro there to inform all including
+applications, that on re-link, the default rte_acl_create symbol should point to
+this function. Note that we could do this by simply naming the function above
 rte_acl_create, and the linker would chose the most recent version tag to apply
 in the version script, but we can also do this in the header file
 
@@ -397,11 +563,11 @@ in the version script, but we can also do this in the header file
 
    struct rte_acl_ctx *
    -rte_acl_create(const struct rte_acl_param *param);
-   +rte_acl_create(const struct rte_acl_param *param, int debug);
-   +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
+   +rte_acl_create_v21(const struct rte_acl_param *param, int debug);
+   +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 21.0);
 
 The BIND_DEFAULT_SYMBOL macro explicitly tells applications that include this
-header, to link to the rte_acl_create_v21 function and apply the DPDK_2.1
+header, to link to the rte_acl_create_v21 function and apply the DPDK_21.0
 version node to it.  This method is more explicit and flexible than just
 re-implementing the exact symbol name, and allows for other features (such as
 linking to the old symbol version by default, when the new ABI is to be opt-in
@@ -421,6 +587,7 @@ assumption is that the most recent version of the symbol is the one you want to
 map.  So, back in the C file where, immediately after ``rte_acl_create_v21`` is
 defined, we add this
 
+
 .. code-block:: c
 
    struct rte_acl_ctx *
@@ -434,21 +601,22 @@ That tells the compiler that, when building a static library, any calls to the
 symbol ``rte_acl_create`` should be linked to ``rte_acl_create_v21``
 
 That's it, on the next shared library rebuild, there will be two versions of
-rte_acl_create, an old DPDK_2.0 version, used by previously built applications,
-and a new DPDK_2.1 version, used by future built applications.
+rte_acl_create, an old DPDK_20.0 version, used by previously built applications,
+and a new DPDK_21.0 version, used by future built applications.
 
 
 Deprecating part of a public API
 ________________________________
 
-Lets assume that you've done the above update, and after a few releases have
-passed you decide you would like to retire the old version of the function.
-After having gone through the ABI deprecation announcement process, removal is
-easy.  Start by removing the symbol from the requisite version map file:
+Lets assume that you've done the above update, and in preparation for the next
+major ABI version you decide you would like to retire the old version of the
+function. After having gone through the ABI deprecation announcement process,
+removal is easy. Start by removing the symbol from the requisite version map
+file:
 
 .. code-block:: none
 
-   DPDK_2.0 {
+   DPDK_20.0 {
         global:
 
         rte_acl_add_rules;
@@ -470,10 +638,10 @@ easy.  Start by removing the symbol from the requisite version map file:
         local: *;
    };
 
-   DPDK_2.1 {
+   DPDK_21.0 {
         global:
         rte_acl_create;
-   } DPDK_2.0;
+   } DPDK_20.0;
 
 
 Next remove the corresponding versioned export.
@@ -484,34 +652,26 @@ Next remove the corresponding versioned export.
 
 
 Note that the internal function definition could also be removed, but its used
-in our example by the newer version _v21, so we leave it in place.  This is a
-coding style choice.
-
-Lastly, we need to bump the LIBABIVER number for this library in the Makefile to
-indicate to applications doing dynamic linking that this is a later, and
-possibly incompatible library version:
-
-.. code-block:: c
-
-   -LIBABIVER := 1
-   +LIBABIVER := 2
+in our example by the newer version _v21, so we leave it in place and declare it
+as static. This is a coding style choice.
 
 Deprecating an entire ABI version
 _________________________________
 
-While removing a symbol from and ABI may be useful, it is often more practical
-to remove an entire version node at once.  If a version node completely
-specifies an API, then removing part of it, typically makes it incomplete.  In
-those cases it is better to remove the entire node
+While removing a symbol from an ABI may be useful, it is more practical to
+remove an entire version node at once, as is typically done at the declaration
+of a major ABI version. If a version node completely specifies an API, then
+removing part of it, typically makes it incomplete. In those cases it is better
+to remove the entire node.
 
 To do this, start by modifying the version map file, such that all symbols from
-the node to be removed are merged into the next node in the map
+the node to be removed are merged into the next node in the map.
 
 In the case of our map above, it would transform to look as follows
 
 .. code-block:: none
 
-   DPDK_2.1 {
+   DPDK_21.0 {
         global:
 
         rte_acl_add_rules;
@@ -539,8 +699,8 @@ symbols.
 
 .. code-block:: c
 
- -BIND_DEFAULT_SYMBOL(rte_acl_create, _v20, 2.0);
- +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
+ -BIND_DEFAULT_SYMBOL(rte_acl_create, _v20, 20.0);
+ +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 21.0);
 
 Lastly, any VERSION_SYMBOL macros that point to the old version node should be
 removed, taking care to keep, where need old code in place to support newer
-- 
2.7.4


^ permalink raw reply	[relevance 31%]

* [dpdk-dev] [PATCH] Changes to ABI Policy introducing major ABI versions
@ 2019-07-04 12:26 11% Ray Kinsella
  2019-07-04 12:26 31% ` [dpdk-dev] [PATCH] doc: " Ray Kinsella
  0 siblings, 1 reply; 200+ results
From: Ray Kinsella @ 2019-07-04 12:26 UTC (permalink / raw)
  To: dev; +Cc: mdr

TL;DR Abbreviation:
A major ABI version that all DPDK releases during a two year period
support. ABI versioning is managed at a project-level, in place of library-level
management. ABI changes to add new features are permitted, as long as ABI
compatibility with the major ABI version is maintained.

Detail:
This patch introduces a two year major ABI version, aligned with the LTS release
and supported by all subsequent releases within that two year period, including
the subsequent LTS release.

ABI changes that preserve ABI compatibility with the major ABI version are
permitted in subsequent releases. ABI changes, follow similar approval rules as
before with the additional gate of now requiring technical board approval. The
merging and release of ABI breaking changes would now be pushed to the
declaration of the next major ABI version.

This change encourages developers to maintain ABI compatibility with the
major ABI version, by promoting a permissive culture around those changes
that preserve ABI compatibility. This approach aligns DPDK with those projects
that declare major ABI versions (e.g. version 2.x, 3.x) and support those
versions for some period, typically two years or more.

To provide an example of how this might work in practice:

 * DPDK v20 is declared as the supported ABI version for two years, aligned with
   the DPDK v19.11 (LTS) release. All library sonames are updated to reflect the
   new ABI version, e.g. librte_eal.so.20, librte_acl.so.20...
 * DPDK v20.02 .. v21.08 releases are ABI compatible with the DPDK v20 ABI. ABI
   changes are permitted from DPDK v20.02 onwards, with the condition that ABI
   compatibility with DPDK v20 is preserved.
 * DPDK v21 is declared as the new supported ABI version for two years, aligned
   with the DPDK v21.11 (LTS) release. The DPDK v20 ABI is now depreciated,
   library sonames are updated to v21 and ABI compatibility breaking changes may
   be introduced.

Ray Kinsella (1):
  doc: Changes to ABI Policy introducing major ABI versions

 doc/guides/contributing/stable.rst     |  10 +-
 doc/guides/contributing/versioning.rst | 462 ++++++++++++++++++++++-----------
 2 files changed, 314 insertions(+), 158 deletions(-)

-- 
2.7.4


^ permalink raw reply	[relevance 11%]

* Re: [dpdk-dev] [PATCH v2 4/4] rawdev: pass device id as parameter to selftest
  2019-06-21 15:56  3%   ` [dpdk-dev] [PATCH v2 4/4] rawdev: pass device id as parameter to selftest Bruce Richardson
@ 2019-07-04  9:33  0%     ` Shreyansh Jain
  0 siblings, 0 replies; 200+ results
From: Shreyansh Jain @ 2019-07-04  9:33 UTC (permalink / raw)
  To: Bruce Richardson, dev

> -----Original Message-----
> From: Bruce Richardson <bruce.richardson@intel.com>
> Sent: Friday, June 21, 2019 9:27 PM
> To: dev@dpdk.org
> Cc: Bruce Richardson <bruce.richardson@intel.com>; Shreyansh Jain
> <shreyansh.jain@nxp.com>
> Subject: [PATCH v2 4/4] rawdev: pass device id as parameter to selftest
> 
> When running self-tests, the driver needs to know the device on which to
> run the tests, so we need to take the device ID as parameter. Only the
> skeleton driver is providing this selftest capability right now, so we
> can
> easily update it for this change.
> 
> Cc: shreyansh.jain@nxp.com
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> ---
> 
> Since this change only affects the internals of the drivers, it's not an
> ABI or API change
> 
> ---

Sorry for delay in responding to this. If not already merged:

Acked-by: Shreyansh Jain <shreyansh.jain@nxp.com>


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC] ethdev: support input set change by RSS action
  @ 2019-07-04  9:07  3% ` Adrien Mazarguil
  2019-07-04 13:55  0%   ` Zhang, Qi Z
  0 siblings, 1 reply; 200+ results
From: Adrien Mazarguil @ 2019-07-04  9:07 UTC (permalink / raw)
  To: simei; +Cc: qi.z.zhang, jingjing.wu, beilei.xing, qiming.yang, dev

On Thu, Jul 04, 2019 at 12:47:09PM +0800, simei wrote:
> From: Simei Su <simei.su@intel.com>
> 
> This RFC introduces inputset structure to rte_flow_action_rss to
> support input set specific configuration by rte_flow RSS action.
> 
> We can give an testpmd command line example to make it more clear.
> 
> For example, below flow selects the l4 port as inputset for any
> eth/ipv4/tcp packet: #flow create 0 ingress pattern eth / ipv4 / tcp /
> end actions rss inputset tcp src mask 0xffff dst mask 0xffff /end
> 
> Signed-off-by: Simei Su <simei.su@intel.com>
> ---
>  lib/librte_ethdev/rte_flow.h | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
> index f3a8fb1..2a455b6 100644
> --- a/lib/librte_ethdev/rte_flow.h
> +++ b/lib/librte_ethdev/rte_flow.h
> @@ -1796,6 +1796,9 @@ struct rte_flow_action_rss {
>  	uint32_t queue_num; /**< Number of entries in @p queue. */
>  	const uint8_t *key; /**< Hash key. */
>  	const uint16_t *queue; /**< Queue indices to use. */
> +	struct rte_flow_item *inputset; /** Provide more specific inputset configuration.
> +					 * ignore spec, only mask.
> +					 */
>  };
>  
>  /**

To make sure I understand, is this kind of a more flexible version of
rte_flow_action_rss.types?

For instance while specifying .types = ETH_RSS_IPV4 normally covers both
source and destination addresses, does this approach enable users to perform
RSS on source IP only? In which case, what value does the Toeplitz algorithm
assume for the destination, 0x0? (note: must be documented)

My opinion is that, unless you know of a hardware which can perform RSS on
random bytes of a packet, this approach is a bit overkill at this point.

How about simply adding the needed ETH_RSS_* definitions
(e.g. ETH_RSS_IPV4_(SRC|DST))? How many are needed?

There are currently 20 used bits and struct rte_flow_action_rss.types is
64-bit wide. I'm sure we can manage something without harming the ABI. Even
better, you wouldn't need a deprecation notice.

If you use the suggested approach, please update testpmd and its
documentation as part of the same patch, thanks.

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC] ethdev: support symmetric hash function
  @ 2019-07-04  9:06  3% ` Adrien Mazarguil
  2019-07-04 12:48  3%   ` Zhang, Qi Z
  0 siblings, 1 reply; 200+ results
From: Adrien Mazarguil @ 2019-07-04  9:06 UTC (permalink / raw)
  To: simei
  Cc: qi.z.zhang, jingjing.wu, beilei.xing, qiming.yang, dev,
	Shahaf Shuler, Yongseok Koh

On Thu, Jul 04, 2019 at 12:46:07PM +0800, simei wrote:
> From: Simei Su <simei.su@intel.com>
> 
> Currently, there are DEFAULT,TOEPLITZ and SIMPLE_XOR hash funtion.
> To support symmetric hash by rte_flow RSS action, this RFC introduces
> SYMMETRIC_TOEPLITZ to rte_eth_hash_function.
> 
> Signed-off-by: Simei Su <simei.su@intel.com>
> ---
>  lib/librte_ethdev/rte_flow.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
> index f3a8fb1..e3c4fe5 100644
> --- a/lib/librte_ethdev/rte_flow.h
> +++ b/lib/librte_ethdev/rte_flow.h
> @@ -1744,6 +1744,7 @@ enum rte_eth_hash_function {
>  	RTE_ETH_HASH_FUNCTION_DEFAULT = 0,
>  	RTE_ETH_HASH_FUNCTION_TOEPLITZ, /**< Toeplitz */
>  	RTE_ETH_HASH_FUNCTION_SIMPLE_XOR, /**< Simple XOR */
> +	RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ, /**< Symmetric TOEPLITZ */

"Symmetric TOEPLITZ" => "Symmetric Toeplitz."

>  	RTE_ETH_HASH_FUNCTION_MAX,
>  };

Other than that, no problem with this change (no ABI impact, no need for
deprecation). Please update testpmd a part of the same patch:

- Wherever "toeplitz" is mentioned in test-pmd/cmdline.c.

- Ditto for flow command, i.e. add ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ to
  test-pmd/cmdline_flow.c.

- Update "set_hash_global_config" documentation section in
  testpmd_app_ug/testpmd_funcs.rst.

Note to Shahaf/Yongseok, since mlx5 supports both but defaults to symmetric
Toeplitz on vanilla Linux and standard Toeplitz when using OFED, how about
using this chance to make the algorithm configurable as well?

Thanks.

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v3 00/14] Make shared memory config non-public
  @ 2019-07-04  8:09  3%       ` David Marchand
  2019-07-04 19:52  0%         ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: David Marchand @ 2019-07-04  8:09 UTC (permalink / raw)
  To: Anatoly Burakov; +Cc: dev, Thomas Monjalon, Stephen Hemminger

On Wed, Jul 3, 2019 at 11:38 AM David Marchand <david.marchand@redhat.com>
wrote:

> Hello Anatoly,
>
> On Thu, Jun 27, 2019 at 1:39 PM Anatoly Burakov <anatoly.burakov@intel.com>
> wrote:
>
>> This patchset removes the shared memory config from public
>> API, and replaces all usages of said config with new API
>> calls.
>>
>> A lot of the patchset is a search-and-replace job and should
>> be pretty easy to review. The rest are pretty trivial EAL
>> changes.
>>
>> This patchset depends on FreeBSD fixes patchset:
>>
>> http://patches.dpdk.org/project/dpdk/list/?series=5196
>>
>> v3:
>> - Rebase on top of latest master
>>
>> v2:
>> - Collapsed all changes into fewer patches
>> - Addressed review comments
>> - Created a new file to store the code
>> - Changed namespace to "rte_mcfg_"
>> - Added some unification around config init
>> - Removed "packed" attribute from mem config
>> - Removed unnecessary inlining
>> - Added a check to explicitly forbid running multiprocess
>>   applications that differ in their DPDK versions
>>
>
>
> For the parts I already had a look at, I still think the changes are in
> too many patches.
> A lot of this is just search/replace we can have it with the patch that
> introduces it.
> - patch 1, 2 and 3 could be squashed as a single one (plus removing the
> unused macro from patch 8)
> - idem with patch 4 and 5
> - idem with patch 6 and 7 (plus removing the unused macro from patch 8)
>
>
Overall, I am ok with the changes, once the patch 13 is fixed.
You can add my ack on the n+1 patchset.


I just want to state two approaches to merge these changes:
- the first one would be to split this series in two
  - take the first part of this series now, but mark the new API
"experimental"
  - postpone the merge to 19.11 of the second part, which starts at the
hiding rte_mem_config patch
- the second one is taking these changes in one go

The second one is the quicker and the more straightforward but it leaves
the risk of having missed something and we must break the ABI again in
19.11.
The risk is quite low, given the changes.


Thomas, comments?

-- 
David Marchand

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH] doc: announce ABI change for rte flow RSS action
@ 2019-07-04  4:46  4% simei
  0 siblings, 0 replies; 200+ results
From: simei @ 2019-07-04  4:46 UTC (permalink / raw)
  To: qi.z.zhang, jingjing.wu, beilei.xing, qiming.yang; +Cc: dev, simei.su

From: Simei Su <simei.su@intel.com>

Add new structure inputset in rte_flow_action_rss. This
can support input set configuration by rte_flow RSS action.

Signed-off-by: Simei Su <simei.su@intel.com>
---
 doc/guides/rel_notes/deprecation.rst | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index e2721fa..5cd360c 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -99,3 +99,6 @@ Deprecation Notices
   to set new power environment if power environment was already initialized.
   In this case the function will return -1 unless the environment is unset first
   (using ``rte_power_unset_env``). Other function usage scenarios will not change.
+
+* ethdev: New member in ``rte_flow_action_rss`` to support input set change
+  by rte_flow RSS action. It ignores spec and focuses on mask only.
-- 
1.8.3.1


^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH] doc: announce ABI change for RSS hash funtion
@ 2019-07-04  4:43  4% simei
  0 siblings, 0 replies; 200+ results
From: simei @ 2019-07-04  4:43 UTC (permalink / raw)
  To: qi.z.zhang, jingjing.wu, beilei.xing, qiming.yang; +Cc: dev, simei.su

From: Simei Su <simei.su@intel.com>

Add new field SYMMETRIC_TOEPLITZ in rte_eth_hash_function. This
can support symmetric hash function by rte_flow RSS action.

Signed-off-by: Simei Su <simei.su@intel.com>
---
 doc/guides/rel_notes/deprecation.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index e2721fa..540285b 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -99,3 +99,5 @@ Deprecation Notices
   to set new power environment if power environment was already initialized.
   In this case the function will return -1 unless the environment is unset first
   (using ``rte_power_unset_env``). Other function usage scenarios will not change.
+
+* ethdev: New member in ``rte_eth_hash_funtion`` to support symmetric hash funtion.
-- 
1.8.3.1


^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v1 1/2] lib/ring: add enqueue-dequeue callabck
  2019-06-11  4:17  0%     ` Honnappa Nagarahalli
@ 2019-07-04  5:04  0%       ` Varghese, Vipin
  0 siblings, 0 replies; 200+ results
From: Varghese, Vipin @ 2019-07-04  5:04 UTC (permalink / raw)
  To: Honnappa Nagarahalli, olivier.matz, Pattan, Reshma, Wiles, Keith, dev
  Cc: Padubidri, Sanjay A, nd, nd

Thanks Honnappa, will work on the changes suggested.

> -----Original Message-----
> From: Honnappa Nagarahalli <Honnappa.Nagarahalli@arm.com>
> Sent: Tuesday, June 11, 2019 9:48 AM
> To: Varghese, Vipin <vipin.varghese@intel.com>; olivier.matz@6wind.com;
> Pattan, Reshma <reshma.pattan@intel.com>; Wiles, Keith
> <keith.wiles@intel.com>; dev@dpdk.org
> Cc: Padubidri, Sanjay A <sanjay.padubidri@intel.com>; Honnappa Nagarahalli
> <Honnappa.Nagarahalli@arm.com>; nd <nd@arm.com>; nd <nd@arm.com>
> Subject: RE: [dpdk-dev] [PATCH v1 1/2] lib/ring: add enqueue-dequeue callabck
> 
> >
> > Hi Honnappa,
> >
> > snipped
> > > >
> > > > Add callback event handler for enqueue dequeue operation on ring.
> > > > The pre-enqueue and post-dequeue operation on ring is selected to
> > > > invoke user callback handler.
> > > Can you provide a use case for this to better understand the need?
> > Use cases:
> >  - allow user to investigate the contents pre-enqueue.
> >  - allow user to investigate the contents post-dequeue.
> >  - modify pre-enqueue and post-dequeue stage content.
> >  - investigate PMD meta data for debug in field nodes.
> >
> > snipped
> > > > +	struct rte_ring_enq_cb_list enq_cbs;
> > > > +	struct rte_ring_deq_cb_list deq_cbs; };
> > > This breaks ABI compatibility
> > Can you help me understand this more clearly?
> 'struct rte_ring' is exposed to the application. It is possible that the application has
> declared a variable of type 'struct rte_ring'. Any addition to this structure will
> increase the size of 'struct rte_ring'. Hence, it won't be compatible.
> 
> >
> > snipped
> > > > -rte_ring_enqueue_burst(struct rte_ring *r, void * const
> > > > *obj_table,
> > > > +rte_ring_enqueue_burst(struct rte_ring *r, void **obj_table,
> > > >  		      unsigned int n, unsigned int *free_space)  {
> > > > +#ifdef RTE_RING_ENQDEQ_CALLBACKS
> > > > +	struct rte_ring_callback *cb = NULL;
> > > > +
> > > > +	TAILQ_FOREACH(cb, &(r->enq_cbs), next) {
> > > Need to take the TAILQ lock before this. For ex: what happens if a
> > > un-register is called concurrently?
> > Let me check this, using rx|tx callback as reference.
> >
> > > Also, traversing a linked list for every enqueue call would be too
> > > costly. May be, understanding the use case will help.
> > Internal testing with SP-SC is 0.1% (with extra cost of user
> > function). But I will try to explore other alternatives too.
> >
> > Snipped

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 1/4] ethdev: add GRE key field to flow API
  2019-07-03 15:25  4%     ` Adrien Mazarguil
@ 2019-07-04  2:43  0%       ` Jack Min
  0 siblings, 0 replies; 200+ results
From: Jack Min @ 2019-07-04  2:43 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: Ori Kam, John McNamara, Marko Kovacevic, Thomas Monjalon,
	Ferruh Yigit, Andrew Rybchenko, dev

On Wed, 19-07-03, 17:25, Adrien Mazarguil wrote:
> On Tue, Jul 02, 2019 at 05:45:52PM +0800, Xiaoyu Min wrote:
> > Add new rte_flow_item_gre_key in order to match the optional key field.
> > 
> > Signed-off-by: Xiaoyu Min <jackmin@mellanox.com>
> 
> OK with adding this feature, however I still have a bunch of comments below.
> 
> > ---
> >  doc/guides/prog_guide/rte_flow.rst | 8 ++++++++
> >  lib/librte_ethdev/rte_flow.c       | 1 +
> >  lib/librte_ethdev/rte_flow.h       | 7 +++++++
> >  3 files changed, 16 insertions(+)
> > 
> > diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
> > index a34d012e55..f4b7baa3c3 100644
> > --- a/doc/guides/prog_guide/rte_flow.rst
> > +++ b/doc/guides/prog_guide/rte_flow.rst
> > @@ -980,6 +980,14 @@ Matches a GRE header.
> >  - ``protocol``: protocol type.
> >  - Default ``mask`` matches protocol only.
> >  
> > +Item: ``GRE_KEY``
> > +^^^^^^^^^^^^^^^^^
> > +
> > +Matches a GRE key field.
> > +This should be preceded by item ``GRE``
> 
> Nit: missing ending "."
> 

Ok, I'll add it.

> > +
> > +- Value to be matched is a big-endian 32 bit integer
> > +
> >  Item: ``FUZZY``
> >  ^^^^^^^^^^^^^^^
> >  
> > diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c
> > index 3277be1edb..f3e56d0bbe 100644
> > --- a/lib/librte_ethdev/rte_flow.c
> > +++ b/lib/librte_ethdev/rte_flow.c
> > @@ -55,6 +55,7 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
> >  	MK_FLOW_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
> >  	MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
> >  	MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
> > +	MK_FLOW_ITEM(GRE_KEY, sizeof(rte_be32_t)),
> 
> Hmm? Adding a new item in the middle?
> 

I'll add it at the end.

> >  	MK_FLOW_ITEM(FUZZY, sizeof(struct rte_flow_item_fuzzy)),
> >  	MK_FLOW_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
> >  	MK_FLOW_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
> > diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
> > index f3a8fb103f..5d3702a44c 100644
> > --- a/lib/librte_ethdev/rte_flow.h
> > +++ b/lib/librte_ethdev/rte_flow.h
> > @@ -289,6 +289,13 @@ enum rte_flow_item_type {
> >  	 */
> >  	RTE_FLOW_ITEM_TYPE_GRE,
> >  
> > +	/**
> > +	 * Matches a GRE optional key field.
> > +	 *
> > +	 * The value should a big-endian 32bit integer.
> > +	 */
> > +	RTE_FLOW_ITEM_TYPE_GRE_KEY,
> > +
> 
> Same comment. While I understand the intent to group GRE and GRE_KEY, doing
> so causes ABI breakage by shifting the value of all subsequent pattern
> items (see IPV6 and IPV6_EXT for instance).
> 

Oh, I was't aware of this. Thank you for explaination.

> We could later decide to sort them while knowingly breaking ABI on purpose,
> however right now there's no choice but adding new pattern items and actions
> at the end of their respective enums, please do that.
> 

Yes, I'll do this.

> -- 
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v6 4/7] baseband/turbo_sw: extension of turbosw PMD for 5G
    2019-07-03 15:24  3%   ` [dpdk-dev] [PATCH v6 2/7] bbdev: extension of BBDEV API for 5G FEC Nicolas Chautru
@ 2019-07-03 15:24  2%   ` Nicolas Chautru
  1 sibling, 0 replies; 200+ results
From: Nicolas Chautru @ 2019-07-03 15:24 UTC (permalink / raw)
  To: akhil.goyal, dev
  Cc: ferruh.yigit, thomas, amr.mokhtar, kamilx.chalupnik, Nicolas Chautru

Implementation still based on Intel SDK libraries
optimized for AVX512 instructions set and 5GNR.
This can be also build for AVX2 for 4G capability or
without SDK dependency for maintenance.

Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
Acked-by: Amr Mokhtar <amr.mokhtar@intel.com>
---
 config/common_base                               |   1 +
 doc/guides/rel_notes/release_19_08.rst           |  15 +-
 drivers/baseband/turbo_sw/Makefile               |  15 +-
 drivers/baseband/turbo_sw/bbdev_turbo_software.c | 677 ++++++++++++++++++++++-
 drivers/baseband/turbo_sw/meson.build            |  10 +
 mk/rte.app.mk                                    |   8 +-
 6 files changed, 715 insertions(+), 11 deletions(-)

diff --git a/config/common_base b/config/common_base
index e5a4ebf..c2551b1 100644
--- a/config/common_base
+++ b/config/common_base
@@ -536,6 +536,7 @@ CONFIG_RTE_LIBRTE_BBDEV_DEBUG=n
 CONFIG_RTE_BBDEV_MAX_DEVS=128
 CONFIG_RTE_BBDEV_OFFLOAD_COST=y
 CONFIG_RTE_BBDEV_SDK_AVX2=n
+CONFIG_RTE_BBDEV_SDK_AVX512=n
 
 #
 # Compile PMD for NULL bbdev device
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 55ae8ee..7c508fc 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -126,6 +126,20 @@ New Features
   Added telemetry mode to l3fwd-power application to report
   application level busyness, empty and full polls of rte_eth_rx_burst().
 
+* **Added a FPGA_LTE_FEC bbdev PMD.**
+
+  Added the new ``fpga_lte_fec`` bbdev driver for the Intel® FPGA PAC
+  (Programmable  Acceleration Card) N3000.  See the
+  :doc:`../bbdevs/fpga_lte_fec` BBDEV guide for more details on this new driver.
+
+* **Updated TURBO_SW bbdev PMD.**
+
+  Updated the ``turbo_sw`` bbdev driver with changes including:
+
+  * Added option to build the driver with or without dependency of external
+    SDK libraries.
+  * Added support for 5GNR encode/decode operations.
+
 Removed Items
 -------------
 
@@ -165,7 +179,6 @@ API Changes
   structure (``rte_crypto_cipher_xform``, ``rte_crypto_auth_xform``, and
   ``rte_crypto_aead_xform``) have been changed to ``const uint8_t *data``.
 
-
 ABI Changes
 -----------
 
diff --git a/drivers/baseband/turbo_sw/Makefile b/drivers/baseband/turbo_sw/Makefile
index 414d0d9..4aa05d2 100644
--- a/drivers/baseband/turbo_sw/Makefile
+++ b/drivers/baseband/turbo_sw/Makefile
@@ -3,7 +3,6 @@
 
 include $(RTE_SDK)/mk/rte.vars.mk
 
-
 # library name
 LIB = librte_pmd_bbdev_turbo_sw.a
 
@@ -34,6 +33,20 @@ LDLIBS += -L$(FLEXRAN_SDK)/lib_common -lcommon
 LDLIBS += -lstdc++ -lirc -limf -lipps -lsvml
 endif
 
+ifeq ($(CONFIG_RTE_BBDEV_SDK_AVX512),y)
+ifeq ($(CONFIG_RTE_BBDEV_SDK_AVX2),n)
+$(error "CONFIG_RTE_BBDEV_SDK_AVX512 requires CONFIG_RTE_BBDEV_SDK_AVX2 set")
+endif
+CFLAGS += -I$(FLEXRAN_SDK)/lib_ldpc_encoder_5gnr
+CFLAGS += -I$(FLEXRAN_SDK)/lib_ldpc_decoder_5gnr
+CFLAGS += -I$(FLEXRAN_SDK)/lib_LDPC_ratematch_5gnr
+CFLAGS += -I$(FLEXRAN_SDK)/lib_rate_dematching_5gnr
+LDLIBS += -L$(FLEXRAN_SDK)/lib_ldpc_encoder_5gnr -lldpc_encoder_5gnr
+LDLIBS += -L$(FLEXRAN_SDK)/lib_ldpc_decoder_5gnr -lldpc_decoder_5gnr
+LDLIBS += -L$(FLEXRAN_SDK)/lib_LDPC_ratematch_5gnr -lLDPC_ratematch_5gnr
+LDLIBS += -L$(FLEXRAN_SDK)/lib_rate_dematching_5gnr -lrate_dematching_5gnr
+endif
+
 # library version
 LIBABIVER := 1
 
diff --git a/drivers/baseband/turbo_sw/bbdev_turbo_software.c b/drivers/baseband/turbo_sw/bbdev_turbo_software.c
index 5551f84..2f06369 100644
--- a/drivers/baseband/turbo_sw/bbdev_turbo_software.c
+++ b/drivers/baseband/turbo_sw/bbdev_turbo_software.c
@@ -14,11 +14,24 @@
 #include <rte_bbdev.h>
 #include <rte_bbdev_pmd.h>
 
+#include <rte_common.h>
+#include <rte_hexdump.h>
+#include <rte_log.h>
+
 #ifdef RTE_BBDEV_SDK_AVX2
+#include <ipp.h>
+#include <ipps.h>
 #include <phy_turbo.h>
 #include <phy_crc.h>
 #include <phy_rate_match.h>
 #endif
+#ifdef RTE_BBDEV_SDK_AVX512
+#include <bit_reverse.h>
+#include <phy_ldpc_encoder_5gnr.h>
+#include <phy_ldpc_decoder_5gnr.h>
+#include <phy_LDPC_ratematch_5gnr.h>
+#include <phy_rate_dematching_5gnr.h>
+#endif
 
 #define DRIVER_NAME baseband_turbo_sw
 
@@ -84,6 +97,7 @@ struct turbo_sw_queue {
 	enum rte_bbdev_op_type type;
 } __rte_cache_aligned;
 
+
 #ifdef RTE_BBDEV_SDK_AVX2
 static inline char *
 mbuf_append(struct rte_mbuf *m_head, struct rte_mbuf *m, uint16_t len)
@@ -180,20 +194,53 @@ struct turbo_sw_queue {
 			}
 		},
 #endif
+#ifdef RTE_BBDEV_SDK_AVX512
+		{
+			.type   = RTE_BBDEV_OP_LDPC_ENC,
+			.cap.ldpc_enc = {
+				.capability_flags =
+						RTE_BBDEV_LDPC_RATE_MATCH |
+						RTE_BBDEV_LDPC_CRC_24A_ATTACH |
+						RTE_BBDEV_LDPC_CRC_24B_ATTACH,
+				.num_buffers_src =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+				.num_buffers_dst =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			}
+		},
+		{
+		.type   = RTE_BBDEV_OP_LDPC_DEC,
+		.cap.ldpc_dec = {
+			.capability_flags =
+					RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK |
+					RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK |
+					RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP |
+					RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE |
+					RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE |
+					RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE,
+			.llr_size = 8,
+			.llr_decimals = 2,
+			.harq_memory_size = 0,
+			.num_buffers_src =
+					RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			.num_buffers_hard_out =
+					RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			.num_buffers_soft_out = 0,
+		}
+		},
+#endif
 		RTE_BBDEV_END_OF_CAPABILITIES_LIST()
 	};
 
 	static struct rte_bbdev_queue_conf default_queue_conf = {
 		.queue_size = RTE_BBDEV_QUEUE_SIZE_LIMIT,
 	};
-
 #ifdef RTE_BBDEV_SDK_AVX2
 	static const enum rte_cpu_flag_t cpu_flag = RTE_CPUFLAG_SSE4_2;
 	dev_info->cpu_flag_reqs = &cpu_flag;
 #else
 	dev_info->cpu_flag_reqs = NULL;
 #endif
-
 	default_queue_conf.socket = dev->data->socket_id;
 
 	dev_info->driver_name = RTE_STR(DRIVER_NAME);
@@ -280,7 +327,7 @@ struct turbo_sw_queue {
 		return -ENAMETOOLONG;
 	}
 	q->enc_in = rte_zmalloc_socket(name,
-			(RTE_BBDEV_TURBO_MAX_CB_SIZE >> 3) * sizeof(*q->enc_in),
+			(RTE_BBDEV_LDPC_MAX_CB_SIZE >> 3) * sizeof(*q->enc_in),
 			RTE_CACHE_LINE_SIZE, queue_conf->socket);
 	if (q->enc_in == NULL) {
 		rte_bbdev_log(ERR,
@@ -288,7 +335,7 @@ struct turbo_sw_queue {
 		goto free_q;
 	}
 
-	/* Allocate memory for Aplha Gamma temp buffer. */
+	/* Allocate memory for Alpha Gamma temp buffer. */
 	ret = snprintf(name, RTE_RING_NAMESIZE, RTE_STR(DRIVER_NAME)"_ag%u:%u",
 			dev->data->dev_id, q_id);
 	if ((ret < 0) || (ret >= (int)RTE_RING_NAMESIZE)) {
@@ -423,6 +470,7 @@ struct turbo_sw_queue {
 };
 
 #ifdef RTE_BBDEV_SDK_AVX2
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
 /* Checks if the encoder input buffer is correct.
  * Returns 0 if it's valid, -1 otherwise.
  */
@@ -478,16 +526,21 @@ struct turbo_sw_queue {
 	return 0;
 }
 #endif
+#endif
 
 static inline void
 process_enc_cb(struct turbo_sw_queue *q, struct rte_bbdev_enc_op *op,
 		uint8_t r, uint8_t c, uint16_t k, uint16_t ncb,
 		uint32_t e, struct rte_mbuf *m_in, struct rte_mbuf *m_out_head,
-		struct rte_mbuf *m_out, uint16_t in_offset, uint16_t out_offset,
+		struct rte_mbuf *m_out,	uint16_t in_offset, uint16_t out_offset,
 		uint16_t in_length, struct rte_bbdev_stats *q_stats)
 {
 #ifdef RTE_BBDEV_SDK_AVX2
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
 	int ret;
+#else
+	RTE_SET_USED(in_length);
+#endif
 	int16_t k_idx;
 	uint16_t m;
 	uint8_t *in, *out0, *out1, *out2, *tmp_out, *rm_out;
@@ -511,11 +564,14 @@ struct turbo_sw_queue {
 	/* CRC24A (for TB) */
 	if ((enc->op_flags & RTE_BBDEV_TURBO_CRC_24A_ATTACH) &&
 		(enc->code_block_mode == 1)) {
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
 		ret = is_enc_input_valid(k - 24, k_idx, in_length);
 		if (ret != 0) {
 			op->status |= 1 << RTE_BBDEV_DATA_ERROR;
 			return;
 		}
+#endif
+
 		crc_req.data = in;
 		crc_req.len = k - 24;
 		/* Check if there is a room for CRC bits if not use
@@ -544,11 +600,14 @@ struct turbo_sw_queue {
 #endif
 	} else if (enc->op_flags & RTE_BBDEV_TURBO_CRC_24B_ATTACH) {
 		/* CRC24B */
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
 		ret = is_enc_input_valid(k - 24, k_idx, in_length);
 		if (ret != 0) {
 			op->status |= 1 << RTE_BBDEV_DATA_ERROR;
 			return;
 		}
+#endif
+
 		crc_req.data = in;
 		crc_req.len = k - 24;
 		/* Check if there is a room for CRC bits if this is the last
@@ -575,13 +634,16 @@ struct turbo_sw_queue {
 #ifdef RTE_BBDEV_OFFLOAD_COST
 		q_stats->acc_offload_cycles += rte_rdtsc_precise() - start_time;
 #endif
-	} else {
+	}
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	else {
 		ret = is_enc_input_valid(k, k_idx, in_length);
 		if (ret != 0) {
 			op->status |= 1 << RTE_BBDEV_DATA_ERROR;
 			return;
 		}
 	}
+#endif
 
 	/* Turbo encoder */
 
@@ -757,6 +819,143 @@ struct turbo_sw_queue {
 #endif
 }
 
+
+static inline void
+process_ldpc_enc_cb(struct turbo_sw_queue *q, struct rte_bbdev_enc_op *op,
+		uint32_t e, struct rte_mbuf *m_in, struct rte_mbuf *m_out_head,
+		struct rte_mbuf *m_out,	uint16_t in_offset, uint16_t out_offset,
+		uint16_t seg_total_left, struct rte_bbdev_stats *q_stats)
+{
+#ifdef RTE_BBDEV_SDK_AVX512
+	RTE_SET_USED(seg_total_left);
+	uint8_t *in, *rm_out;
+	struct rte_bbdev_op_ldpc_enc *enc = &op->ldpc_enc;
+	struct bblib_ldpc_encoder_5gnr_request ldpc_req;
+	struct bblib_ldpc_encoder_5gnr_response ldpc_resp;
+	struct bblib_LDPC_ratematch_5gnr_request rm_req;
+	struct bblib_LDPC_ratematch_5gnr_response rm_resp;
+	struct bblib_crc_request crc_req;
+	struct bblib_crc_response crc_resp;
+	uint16_t msgLen, puntBits, parity_offset, out_len;
+	uint16_t K = (enc->basegraph == 1 ? 22 : 10) * enc->z_c;
+	uint16_t in_length_in_bits = K - enc->n_filler;
+	uint16_t in_length_in_bytes = (in_length_in_bits + 7) >> 3;
+
+#ifdef RTE_BBDEV_OFFLOAD_COST
+	uint64_t start_time = rte_rdtsc_precise();
+#else
+	RTE_SET_USED(q_stats);
+#endif
+
+	in = rte_pktmbuf_mtod_offset(m_in, uint8_t *, in_offset);
+
+	/* Masking the Filler bits explicitly */
+	memset(q->enc_in  + (in_length_in_bytes - 3), 0,
+			((K + 7) >> 3) - (in_length_in_bytes - 3));
+	/* CRC Generation */
+	if (enc->op_flags & RTE_BBDEV_LDPC_CRC_24A_ATTACH) {
+		rte_memcpy(q->enc_in, in, in_length_in_bytes - 3);
+		crc_req.data = in;
+		crc_req.len = in_length_in_bits - 24;
+		crc_resp.data = q->enc_in;
+		bblib_lte_crc24a_gen(&crc_req, &crc_resp);
+	} else if (enc->op_flags & RTE_BBDEV_LDPC_CRC_24B_ATTACH) {
+		rte_memcpy(q->enc_in, in, in_length_in_bytes - 3);
+		crc_req.data = in;
+		crc_req.len = in_length_in_bits - 24;
+		crc_resp.data = q->enc_in;
+		bblib_lte_crc24b_gen(&crc_req, &crc_resp);
+	} else
+		rte_memcpy(q->enc_in, in, in_length_in_bytes);
+
+	/* LDPC Encoding */
+	ldpc_req.Zc = enc->z_c;
+	ldpc_req.baseGraph = enc->basegraph;
+	/* Number of rows set to maximum */
+	ldpc_req.nRows = ldpc_req.baseGraph == 1 ? 46 : 42;
+	ldpc_req.numberCodeblocks = 1;
+	ldpc_req.input[0] = (int8_t *) q->enc_in;
+	ldpc_resp.output[0] = (int8_t *) q->enc_out;
+
+	bblib_bit_reverse(ldpc_req.input[0], in_length_in_bytes << 3);
+
+	if (bblib_ldpc_encoder_5gnr(&ldpc_req, &ldpc_resp) != 0) {
+		op->status |= 1 << RTE_BBDEV_DRV_ERROR;
+		rte_bbdev_log(ERR, "LDPC Encoder failed");
+		return;
+	}
+
+	/*
+	 * Systematic + Parity : Recreating stream with filler bits, ideally
+	 * the bit select could handle this in the RM SDK
+	 */
+	msgLen = (ldpc_req.baseGraph == 1 ? 22 : 10) * ldpc_req.Zc;
+	puntBits = 2 * ldpc_req.Zc;
+	parity_offset = msgLen - puntBits;
+	ippsCopyBE_1u(((uint8_t *) ldpc_req.input[0]) + (puntBits / 8),
+			puntBits%8, q->adapter_output, 0, parity_offset);
+	ippsCopyBE_1u(q->enc_out, 0, q->adapter_output + (parity_offset / 8),
+			parity_offset % 8, ldpc_req.nRows * ldpc_req.Zc);
+
+	out_len = (e + 7) >> 3;
+	/* get output data starting address */
+	rm_out = (uint8_t *)mbuf_append(m_out_head, m_out, out_len);
+	if (rm_out == NULL) {
+		op->status |= 1 << RTE_BBDEV_DATA_ERROR;
+		rte_bbdev_log(ERR,
+				"Too little space in output mbuf");
+		return;
+	}
+	/*
+	 * rte_bbdev_op_data.offset can be different than the offset
+	 * of the appended bytes
+	 */
+	rm_out = rte_pktmbuf_mtod_offset(m_out, uint8_t *, out_offset);
+
+	/* Rate-Matching */
+	rm_req.E = e;
+	rm_req.Ncb = enc->n_cb;
+	rm_req.Qm = enc->q_m;
+	rm_req.Zc = enc->z_c;
+	rm_req.baseGraph = enc->basegraph;
+	rm_req.input = q->adapter_output;
+	rm_req.nLen = enc->n_filler;
+	rm_req.nullIndex = parity_offset - enc->n_filler;
+	rm_req.rvidx = enc->rv_index;
+	rm_resp.output = q->deint_output;
+
+	if (bblib_LDPC_ratematch_5gnr(&rm_req, &rm_resp) != 0) {
+		op->status |= 1 << RTE_BBDEV_DRV_ERROR;
+		rte_bbdev_log(ERR, "Rate matching failed");
+		return;
+	}
+
+	/* RM SDK may provide non zero bits on last byte */
+	if ((e % 8) != 0)
+		q->deint_output[out_len-1] &= (1 << (e % 8)) - 1;
+
+	bblib_bit_reverse((int8_t *) q->deint_output, out_len << 3);
+
+	rte_memcpy(rm_out, q->deint_output, out_len);
+	enc->output.length += out_len;
+
+#ifdef RTE_BBDEV_OFFLOAD_COST
+	q_stats->acc_offload_cycles += rte_rdtsc_precise() - start_time;
+#endif
+#else
+	RTE_SET_USED(q);
+	RTE_SET_USED(op);
+	RTE_SET_USED(e);
+	RTE_SET_USED(m_in);
+	RTE_SET_USED(m_out_head);
+	RTE_SET_USED(m_out);
+	RTE_SET_USED(in_offset);
+	RTE_SET_USED(out_offset);
+	RTE_SET_USED(seg_total_left);
+	RTE_SET_USED(q_stats);
+#endif
+}
+
 static inline void
 enqueue_enc_one_op(struct turbo_sw_queue *q, struct rte_bbdev_enc_op *op,
 		struct rte_bbdev_stats *queue_stats)
@@ -850,6 +1049,93 @@ struct turbo_sw_queue {
 	}
 }
 
+
+static inline void
+enqueue_ldpc_enc_one_op(struct turbo_sw_queue *q, struct rte_bbdev_enc_op *op,
+		struct rte_bbdev_stats *queue_stats)
+{
+	uint8_t c, r, crc24_bits = 0;
+	uint32_t e;
+	struct rte_bbdev_op_ldpc_enc *enc = &op->ldpc_enc;
+	uint16_t in_offset = enc->input.offset;
+	uint16_t out_offset = enc->output.offset;
+	struct rte_mbuf *m_in = enc->input.data;
+	struct rte_mbuf *m_out = enc->output.data;
+	struct rte_mbuf *m_out_head = enc->output.data;
+	uint32_t in_length, mbuf_total_left = enc->input.length;
+
+	uint16_t seg_total_left;
+
+	/* Clear op status */
+	op->status = 0;
+
+	if (mbuf_total_left > RTE_BBDEV_TURBO_MAX_TB_SIZE >> 3) {
+		rte_bbdev_log(ERR, "TB size (%u) is too big, max: %d",
+				mbuf_total_left, RTE_BBDEV_TURBO_MAX_TB_SIZE);
+		op->status = 1 << RTE_BBDEV_DATA_ERROR;
+		return;
+	}
+
+	if (m_in == NULL || m_out == NULL) {
+		rte_bbdev_log(ERR, "Invalid mbuf pointer");
+		op->status = 1 << RTE_BBDEV_DATA_ERROR;
+		return;
+	}
+
+	if ((enc->op_flags & RTE_BBDEV_TURBO_CRC_24B_ATTACH) ||
+		(enc->op_flags & RTE_BBDEV_TURBO_CRC_24A_ATTACH))
+		crc24_bits = 24;
+
+	if (enc->code_block_mode == 0) { /* For Transport Block mode */
+		c = enc->tb_params.c;
+		r = enc->tb_params.r;
+	} else { /* For Code Block mode */
+		c = 1;
+		r = 0;
+	}
+
+	while (mbuf_total_left > 0 && r < c) {
+
+		seg_total_left = rte_pktmbuf_data_len(m_in) - in_offset;
+
+		if (enc->code_block_mode == 0) {
+			e = (r < enc->tb_params.cab) ?
+				enc->tb_params.ea : enc->tb_params.eb;
+		} else {
+			e = enc->cb_params.e;
+		}
+
+		process_ldpc_enc_cb(q, op, e, m_in, m_out_head,
+				m_out, in_offset, out_offset, seg_total_left,
+				queue_stats);
+		/* Update total_left */
+		in_length = (enc->basegraph == 1 ? 22 : 10) * enc->z_c;
+		in_length = ((in_length - crc24_bits - enc->n_filler) >> 3);
+		mbuf_total_left -= in_length;
+		/* Update offsets for next CBs (if exist) */
+		in_offset += in_length;
+		out_offset += (e + 7) >> 3;
+
+		/* Update offsets */
+		if (seg_total_left == in_length) {
+			/* Go to the next mbuf */
+			m_in = m_in->next;
+			m_out = m_out->next;
+			in_offset = 0;
+			out_offset = 0;
+		}
+		r++;
+	}
+
+	/* check if all input data was processed */
+	if (mbuf_total_left != 0) {
+		op->status |= 1 << RTE_BBDEV_DATA_ERROR;
+		rte_bbdev_log(ERR,
+				"Mismatch between mbuf length and included CBs sizes %d",
+				mbuf_total_left);
+	}
+}
+
 static inline uint16_t
 enqueue_enc_all_ops(struct turbo_sw_queue *q, struct rte_bbdev_enc_op **ops,
 		uint16_t nb_ops, struct rte_bbdev_stats *queue_stats)
@@ -866,6 +1152,23 @@ struct turbo_sw_queue {
 			NULL);
 }
 
+static inline uint16_t
+enqueue_ldpc_enc_all_ops(struct turbo_sw_queue *q,
+		struct rte_bbdev_enc_op **ops,
+		uint16_t nb_ops, struct rte_bbdev_stats *queue_stats)
+{
+	uint16_t i;
+#ifdef RTE_BBDEV_OFFLOAD_COST
+	queue_stats->acc_offload_cycles = 0;
+#endif
+
+	for (i = 0; i < nb_ops; ++i)
+		enqueue_ldpc_enc_one_op(q, ops[i], queue_stats);
+
+	return rte_ring_enqueue_burst(q->processed_pkts, (void **)ops, nb_ops,
+			NULL);
+}
+
 #ifdef RTE_BBDEV_SDK_AVX2
 static inline void
 move_padding_bytes(const uint8_t *in, uint8_t *out, uint16_t k,
@@ -890,7 +1193,11 @@ struct turbo_sw_queue {
 		struct rte_bbdev_stats *q_stats)
 {
 #ifdef RTE_BBDEV_SDK_AVX2
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
 	int ret;
+#else
+	RTE_SET_USED(in_length);
+#endif
 	int32_t k_idx;
 	int32_t iter_cnt;
 	uint8_t *in, *out, *adapter_input;
@@ -908,11 +1215,13 @@ struct turbo_sw_queue {
 
 	k_idx = compute_idx(k);
 
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
 	ret = is_dec_input_valid(k_idx, kw, in_length);
 	if (ret != 0) {
 		op->status |= 1 << RTE_BBDEV_DATA_ERROR;
 		return;
 	}
+#endif
 
 	in = rte_pktmbuf_mtod_offset(m_in, uint8_t *, in_offset);
 	ncb = kw;
@@ -928,11 +1237,12 @@ struct turbo_sw_queue {
 		deint_resp.pinteleavebuffer = q->deint_output;
 
 #ifdef RTE_BBDEV_OFFLOAD_COST
-		start_time = rte_rdtsc_precise();
+	start_time = rte_rdtsc_precise();
 #endif
+		/* Sub-block De-Interleaving */
 		bblib_deinterleave_ul(&deint_req, &deint_resp);
 #ifdef RTE_BBDEV_OFFLOAD_COST
-		q_stats->acc_offload_cycles += rte_rdtsc_precise() - start_time;
+	q_stats->acc_offload_cycles += rte_rdtsc_precise() - start_time;
 #endif
 	} else
 		move_padding_bytes(in, q->deint_output, k, ncb);
@@ -1025,6 +1335,202 @@ struct turbo_sw_queue {
 }
 
 static inline void
+process_ldpc_dec_cb(struct turbo_sw_queue *q, struct rte_bbdev_dec_op *op,
+		uint8_t c, uint16_t out_length, uint16_t e,
+		struct rte_mbuf *m_in,
+		struct rte_mbuf *m_out_head, struct rte_mbuf *m_out,
+		struct rte_mbuf *m_harq_in,
+		struct rte_mbuf *m_harq_out_head, struct rte_mbuf *m_harq_out,
+		uint16_t in_offset, uint16_t out_offset,
+		uint16_t harq_in_offset, uint16_t harq_out_offset,
+		bool check_crc_24b,
+		uint16_t crc24_overlap, uint16_t in_length,
+		struct rte_bbdev_stats *q_stats)
+{
+#ifdef RTE_BBDEV_SDK_AVX512
+	RTE_SET_USED(in_length);
+	RTE_SET_USED(c);
+	uint8_t *in, *out, *harq_in, *harq_out, *adapter_input;
+	struct bblib_rate_dematching_5gnr_request derm_req;
+	struct bblib_rate_dematching_5gnr_response derm_resp;
+	struct bblib_ldpc_decoder_5gnr_request dec_req;
+	struct bblib_ldpc_decoder_5gnr_response dec_resp;
+	struct bblib_crc_request crc_req;
+	struct bblib_crc_response crc_resp;
+	struct rte_bbdev_op_ldpc_dec *dec = &op->ldpc_dec;
+	uint16_t K, parity_offset, sys_cols, outLenWithCrc;
+	int16_t deRmOutSize, numRows;
+
+	/* Compute some LDPC BG lengths */
+	outLenWithCrc = out_length + (crc24_overlap >> 3);
+	sys_cols = (dec->basegraph == 1) ? 22 : 10;
+	K = sys_cols * dec->z_c;
+	parity_offset = K - 2 * dec->z_c;
+
+#ifdef RTE_BBDEV_OFFLOAD_COST
+	uint64_t start_time = rte_rdtsc_precise();
+#else
+	RTE_SET_USED(q_stats);
+#endif
+
+	in = rte_pktmbuf_mtod_offset(m_in, uint8_t *, in_offset);
+
+	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) {
+		/**
+		 *  Single contiguous block from the first LLR of the
+		 *  circular buffer.
+		 */
+		harq_in = NULL;
+		if (m_harq_in != NULL)
+			harq_in = rte_pktmbuf_mtod_offset(m_harq_in,
+				uint8_t *, harq_in_offset);
+		if (harq_in == NULL) {
+			op->status |= 1 << RTE_BBDEV_DATA_ERROR;
+			rte_bbdev_log(ERR, "No space in harq input mbuf");
+			return;
+		}
+		uint16_t harq_in_length = RTE_MIN(
+				dec->harq_combined_input.length,
+				(uint32_t) dec->n_cb);
+		memset(q->ag + harq_in_length, 0,
+				dec->n_cb - harq_in_length);
+		rte_memcpy(q->ag, harq_in, harq_in_length);
+	}
+
+	derm_req.p_in = (int8_t *) in;
+	derm_req.p_harq = q->ag; /* This doesn't include the filler bits */
+	derm_req.base_graph = dec->basegraph;
+	derm_req.zc = dec->z_c;
+	derm_req.ncb = dec->n_cb;
+	derm_req.e = e;
+	derm_req.k0 = 0; /* Actual output from SDK */
+	derm_req.isretx = check_bit(dec->op_flags,
+			RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE);
+	derm_req.rvid = dec->rv_index;
+	derm_req.modulation_order = dec->q_m;
+	derm_req.start_null_index = parity_offset - dec->n_filler;
+	derm_req.num_of_null = dec->n_filler;
+
+	bblib_rate_dematching_5gnr(&derm_req, &derm_resp);
+
+	/* Compute RM out size and number of rows */
+	deRmOutSize = RTE_MIN(
+			derm_req.k0 + derm_req.e -
+			((derm_req.k0 < derm_req.start_null_index) ?
+					0 : dec->n_filler),
+			dec->n_cb - dec->n_filler);
+	if (m_harq_in != NULL)
+		deRmOutSize = RTE_MAX(deRmOutSize,
+				RTE_MIN(dec->n_cb - dec->n_filler,
+						m_harq_in->data_len));
+	numRows = ((deRmOutSize + dec->n_filler + dec->z_c - 1) / dec->z_c)
+			- sys_cols + 2;
+	numRows = RTE_MAX(4, numRows);
+
+	/* get output data starting address */
+	out = (uint8_t *)mbuf_append(m_out_head, m_out, out_length);
+	if (out == NULL) {
+		op->status |= 1 << RTE_BBDEV_DATA_ERROR;
+		rte_bbdev_log(ERR,
+				"Too little space in LDPC decoder output mbuf");
+		return;
+	}
+
+	/* rte_bbdev_op_data.offset can be different than the offset
+	 * of the appended bytes
+	 */
+	out = rte_pktmbuf_mtod_offset(m_out, uint8_t *, out_offset);
+	adapter_input = q->enc_out;
+
+	dec_req.Zc = dec->z_c;
+	dec_req.baseGraph = dec->basegraph;
+	dec_req.nRows = numRows;
+	dec_req.numChannelLlrs = deRmOutSize;
+	dec_req.varNodes = derm_req.p_harq;
+	dec_req.numFillerBits = dec->n_filler;
+	dec_req.maxIterations = dec->iter_max;
+	dec_req.enableEarlyTermination = check_bit(dec->op_flags,
+			RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE);
+	dec_resp.varNodes = (int16_t *) q->adapter_output;
+	dec_resp.compactedMessageBytes = q->enc_out;
+
+	bblib_ldpc_decoder_5gnr(&dec_req, &dec_resp);
+
+	dec->iter_count = RTE_MAX(dec_resp.iterationAtTermination,
+			dec->iter_count);
+	if (!dec_resp.parityPassedAtTermination)
+		op->status |= 1 << RTE_BBDEV_SYNDROME_ERROR;
+
+	bblib_bit_reverse((int8_t *) q->enc_out, outLenWithCrc << 3);
+
+	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK) ||
+			check_bit(dec->op_flags,
+					RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK)) {
+		crc_req.data = adapter_input;
+		crc_req.len  = K - dec->n_filler - 24;
+		crc_resp.check_passed = false;
+		crc_resp.data = adapter_input;
+		if (check_crc_24b)
+			bblib_lte_crc24b_check(&crc_req, &crc_resp);
+		else
+			bblib_lte_crc24a_check(&crc_req, &crc_resp);
+		if (!crc_resp.check_passed)
+			op->status |= 1 << RTE_BBDEV_CRC_ERROR;
+	}
+
+#ifdef RTE_BBDEV_OFFLOAD_COST
+	q_stats->acc_offload_cycles += rte_rdtsc_precise() - start_time;
+#endif
+	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE)) {
+		harq_out = NULL;
+		if (m_harq_out != NULL) {
+			/* Initialize HARQ data length since we overwrite */
+			m_harq_out->data_len = 0;
+			/* Check there is enough space
+			 * in the HARQ outbound buffer
+			 */
+			harq_out = (uint8_t *)mbuf_append(m_harq_out_head,
+					m_harq_out, deRmOutSize);
+		}
+		if (harq_out == NULL) {
+			op->status |= 1 << RTE_BBDEV_DATA_ERROR;
+			rte_bbdev_log(ERR, "No space in HARQ output mbuf");
+			return;
+		}
+		/* get output data starting address and overwrite the data */
+		harq_out = rte_pktmbuf_mtod_offset(m_harq_out, uint8_t *,
+				harq_out_offset);
+		rte_memcpy(harq_out, derm_req.p_harq, deRmOutSize);
+		dec->harq_combined_output.length += deRmOutSize;
+	}
+
+	rte_memcpy(out, adapter_input, out_length);
+	dec->hard_output.length += out_length;
+#else
+	RTE_SET_USED(q);
+	RTE_SET_USED(op);
+	RTE_SET_USED(c);
+	RTE_SET_USED(out_length);
+	RTE_SET_USED(e);
+	RTE_SET_USED(m_in);
+	RTE_SET_USED(m_out_head);
+	RTE_SET_USED(m_out);
+	RTE_SET_USED(m_harq_in);
+	RTE_SET_USED(m_harq_out_head);
+	RTE_SET_USED(m_harq_out);
+	RTE_SET_USED(harq_in_offset);
+	RTE_SET_USED(harq_out_offset);
+	RTE_SET_USED(in_offset);
+	RTE_SET_USED(out_offset);
+	RTE_SET_USED(check_crc_24b);
+	RTE_SET_USED(crc24_overlap);
+	RTE_SET_USED(in_length);
+	RTE_SET_USED(q_stats);
+#endif
+}
+
+
+static inline void
 enqueue_dec_one_op(struct turbo_sw_queue *q, struct rte_bbdev_dec_op *op,
 		struct rte_bbdev_stats *queue_stats)
 {
@@ -1083,6 +1589,7 @@ struct turbo_sw_queue {
 				in_offset, out_offset, check_bit(dec->op_flags,
 				RTE_BBDEV_TURBO_CRC_TYPE_24B), crc24_overlap,
 				seg_total_left, queue_stats);
+
 		/* To keep CRC24 attached to end of Code block, use
 		 * RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP flag as it
 		 * removed by default once verified.
@@ -1104,6 +1611,103 @@ struct turbo_sw_queue {
 		}
 		r++;
 	}
+
+	if (mbuf_total_left != 0) {
+		op->status |= 1 << RTE_BBDEV_DATA_ERROR;
+		rte_bbdev_log(ERR,
+				"Mismatch between mbuf length and included Circular buffer sizes");
+	}
+}
+
+static inline void
+enqueue_ldpc_dec_one_op(struct turbo_sw_queue *q, struct rte_bbdev_dec_op *op,
+		struct rte_bbdev_stats *queue_stats)
+{
+	uint8_t c, r = 0;
+	uint16_t e, out_length;
+	uint16_t crc24_overlap = 0;
+	struct rte_bbdev_op_ldpc_dec *dec = &op->ldpc_dec;
+	struct rte_mbuf *m_in = dec->input.data;
+	struct rte_mbuf *m_harq_in = dec->harq_combined_input.data;
+	struct rte_mbuf *m_harq_out = dec->harq_combined_output.data;
+	struct rte_mbuf *m_harq_out_head = dec->harq_combined_output.data;
+	struct rte_mbuf *m_out = dec->hard_output.data;
+	struct rte_mbuf *m_out_head = dec->hard_output.data;
+	uint16_t in_offset = dec->input.offset;
+	uint16_t harq_in_offset = dec->harq_combined_input.offset;
+	uint16_t harq_out_offset = dec->harq_combined_output.offset;
+	uint16_t out_offset = dec->hard_output.offset;
+	uint32_t mbuf_total_left = dec->input.length;
+	uint16_t seg_total_left;
+
+	/* Clear op status */
+	op->status = 0;
+
+	if (m_in == NULL || m_out == NULL) {
+		rte_bbdev_log(ERR, "Invalid mbuf pointer");
+		op->status = 1 << RTE_BBDEV_DATA_ERROR;
+		return;
+	}
+
+	if (dec->code_block_mode == 0) { /* For Transport Block mode */
+		c = dec->tb_params.c;
+		e = dec->tb_params.ea;
+	} else { /* For Code Block mode */
+		c = 1;
+		e = dec->cb_params.e;
+	}
+
+	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP))
+		crc24_overlap = 24;
+
+	out_length = (dec->basegraph == 1 ? 22 : 10) * dec->z_c; /* K */
+	out_length = ((out_length - crc24_overlap - dec->n_filler) >> 3);
+
+	while (mbuf_total_left > 0) {
+		if (dec->code_block_mode == 0)
+			e = (r < dec->tb_params.cab) ?
+				dec->tb_params.ea : dec->tb_params.eb;
+
+		seg_total_left = rte_pktmbuf_data_len(m_in) - in_offset;
+
+		process_ldpc_dec_cb(q, op, c, out_length, e,
+				m_in, m_out_head, m_out,
+				m_harq_in, m_harq_out_head, m_harq_out,
+				in_offset, out_offset, harq_in_offset,
+				harq_out_offset,
+				check_bit(dec->op_flags,
+				RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK),
+				crc24_overlap,
+				seg_total_left, queue_stats);
+
+		/* To keep CRC24 attached to end of Code block, use
+		 * RTE_BBDEV_LDPC_DEC_TB_CRC_24B_KEEP flag as it
+		 * removed by default once verified.
+		 */
+
+		mbuf_total_left -= e;
+
+		/* Update offsets */
+		if (seg_total_left == e) {
+			/* Go to the next mbuf */
+			m_in = m_in->next;
+			m_out = m_out->next;
+			if (m_harq_in != NULL)
+				m_harq_in = m_harq_in->next;
+			if (m_harq_out != NULL)
+				m_harq_out = m_harq_out->next;
+			in_offset = 0;
+			out_offset = 0;
+			harq_in_offset = 0;
+			harq_out_offset = 0;
+		} else {
+			/* Update offsets for next CBs (if exist) */
+			in_offset += e;
+			out_offset += out_length;
+		}
+		r++;
+	}
+
 	if (mbuf_total_left != 0) {
 		op->status |= 1 << RTE_BBDEV_DATA_ERROR;
 		rte_bbdev_log(ERR,
@@ -1127,6 +1731,23 @@ struct turbo_sw_queue {
 			NULL);
 }
 
+static inline uint16_t
+enqueue_ldpc_dec_all_ops(struct turbo_sw_queue *q,
+		struct rte_bbdev_dec_op **ops,
+		uint16_t nb_ops, struct rte_bbdev_stats *queue_stats)
+{
+	uint16_t i;
+#ifdef RTE_BBDEV_OFFLOAD_COST
+	queue_stats->acc_offload_cycles = 0;
+#endif
+
+	for (i = 0; i < nb_ops; ++i)
+		enqueue_ldpc_dec_one_op(q, ops[i], queue_stats);
+
+	return rte_ring_enqueue_burst(q->processed_pkts, (void **)ops, nb_ops,
+			NULL);
+}
+
 /* Enqueue burst */
 static uint16_t
 enqueue_enc_ops(struct rte_bbdev_queue_data *q_data,
@@ -1146,6 +1767,24 @@ struct turbo_sw_queue {
 
 /* Enqueue burst */
 static uint16_t
+enqueue_ldpc_enc_ops(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_enc_op **ops, uint16_t nb_ops)
+{
+	void *queue = q_data->queue_private;
+	struct turbo_sw_queue *q = queue;
+	uint16_t nb_enqueued = 0;
+
+	nb_enqueued = enqueue_ldpc_enc_all_ops(
+			q, ops, nb_ops, &q_data->queue_stats);
+
+	q_data->queue_stats.enqueue_err_count += nb_ops - nb_enqueued;
+	q_data->queue_stats.enqueued_count += nb_enqueued;
+
+	return nb_enqueued;
+}
+
+/* Enqueue burst */
+static uint16_t
 enqueue_dec_ops(struct rte_bbdev_queue_data *q_data,
 		 struct rte_bbdev_dec_op **ops, uint16_t nb_ops)
 {
@@ -1161,6 +1800,24 @@ struct turbo_sw_queue {
 	return nb_enqueued;
 }
 
+/* Enqueue burst */
+static uint16_t
+enqueue_ldpc_dec_ops(struct rte_bbdev_queue_data *q_data,
+		 struct rte_bbdev_dec_op **ops, uint16_t nb_ops)
+{
+	void *queue = q_data->queue_private;
+	struct turbo_sw_queue *q = queue;
+	uint16_t nb_enqueued = 0;
+
+	nb_enqueued = enqueue_ldpc_dec_all_ops(q, ops, nb_ops,
+			&q_data->queue_stats);
+
+	q_data->queue_stats.enqueue_err_count += nb_ops - nb_enqueued;
+	q_data->queue_stats.enqueued_count += nb_enqueued;
+
+	return nb_enqueued;
+}
+
 /* Dequeue decode burst */
 static uint16_t
 dequeue_dec_ops(struct rte_bbdev_queue_data *q_data,
@@ -1273,6 +1930,10 @@ struct turbo_sw_queue {
 	bbdev->dequeue_dec_ops = dequeue_dec_ops;
 	bbdev->enqueue_enc_ops = enqueue_enc_ops;
 	bbdev->enqueue_dec_ops = enqueue_dec_ops;
+	bbdev->dequeue_ldpc_enc_ops = dequeue_enc_ops;
+	bbdev->dequeue_ldpc_dec_ops = dequeue_dec_ops;
+	bbdev->enqueue_ldpc_enc_ops = enqueue_ldpc_enc_ops;
+	bbdev->enqueue_ldpc_dec_ops = enqueue_ldpc_dec_ops;
 	((struct bbdev_private *) bbdev->data->dev_private)->max_nb_queues =
 			init_params->queues_num;
 
diff --git a/drivers/baseband/turbo_sw/meson.build b/drivers/baseband/turbo_sw/meson.build
index 438b5a7..33345aa 100644
--- a/drivers/baseband/turbo_sw/meson.build
+++ b/drivers/baseband/turbo_sw/meson.build
@@ -23,6 +23,16 @@ if dpdk_conf.has('RTE_BBDEV_SDK_AVX2')
 		includes += include_directories(path + '/lib_common')
 	endif
 endif
+if dpdk_conf.has('RTE_BBDEV_SDK_AVX512')
+	ext_deps += cc.find_library('libldpc_encoder_5gnr', dirs: [path + '/lib_ldpc_encoder_5gnr'], required: true)
+	ext_deps += cc.find_library('libldpc_decoder_5gnr', dirs: [path + '/lib_ldpc_decoder_5gnr'], required: true)
+	ext_deps += cc.find_library('libLDPC_ratematch_5gnr', dirs: [path + '/lib_LDPC_ratematch_5gnr'], required: true)
+	ext_deps += cc.find_library('librate_dematching_5gnr', dirs: [path + '/lib_rate_dematching_5gnr'], required: true)
+	includes += include_directories(path + '/lib_ldpc_encoder_5gnr')
+	includes += include_directories(path + '/lib_ldpc_decoder_5gnr')
+	includes += include_directories(path + '/lib_LDPC_ratematch_5gnr')
+	includes += include_directories(path + '/lib_rate_dematching_5gnr')
+endif
 
 deps += ['bbdev', 'bus_vdev', 'ring']
 name = 'bbdev_turbo_sw'
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index c9fbdd6..1036df7 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -232,7 +232,13 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_crc -lcr
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_turbo -lturbo
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_rate_matching -lrate_matching
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_common -lcommon
-_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -lirc -limf -lstdc++ -lipps
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -lirc -limf -lstdc++ -lipps -lsvml
+ifeq ($(CONFIG_RTE_BBDEV_SDK_AVX512),y)
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_LDPC_ratematch_5gnr -lLDPC_ratematch_5gnr
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_ldpc_encoder_5gnr -lldpc_encoder_5gnr
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_ldpc_decoder_5gnr -lldpc_decoder_5gnr
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_rate_dematching_5gnr -lrate_dematching_5gnr
+endif # CONFIG_RTE_BBDEV_SDK_AVX512
 endif # CONFIG_RTE_BBDEV_SDK_AVX2
 endif # CONFIG_RTE_LIBRTE_BBDEV
 
-- 
1.8.3.1


^ permalink raw reply	[relevance 2%]

* [dpdk-dev] [PATCH v6 2/7] bbdev: extension of BBDEV API for 5G FEC
  @ 2019-07-03 15:24  3%   ` Nicolas Chautru
  2019-07-03 15:24  2%   ` [dpdk-dev] [PATCH v6 4/7] baseband/turbo_sw: extension of turbosw PMD for 5G Nicolas Chautru
  1 sibling, 0 replies; 200+ results
From: Nicolas Chautru @ 2019-07-03 15:24 UTC (permalink / raw)
  To: akhil.goyal, dev
  Cc: ferruh.yigit, thomas, amr.mokhtar, kamilx.chalupnik, Nicolas Chautru

Extension to BBDEV operations to support 5G
on top of existing 4G operations.

Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
Acked-by: Amr Mokhtar <amr.mokhtar@intel.com>
---
 doc/guides/rel_notes/release_19_08.rst |   4 +-
 lib/librte_bbdev/rte_bbdev.c           |  22 +-
 lib/librte_bbdev/rte_bbdev.h           | 138 +++++++-
 lib/librte_bbdev/rte_bbdev_op.h        | 567 ++++++++++++++++++++++++++-------
 4 files changed, 608 insertions(+), 123 deletions(-)

diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 335d24a..55ae8ee 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -126,7 +126,6 @@ New Features
   Added telemetry mode to l3fwd-power application to report
   application level busyness, empty and full polls of rte_eth_rx_burst().
 
-
 Removed Items
 -------------
 
@@ -192,6 +191,9 @@ ABI Changes
 
   Disabling unused features would facilitate efficient usage of HW/SW offload.
 
+* bbdev: New operations and parameters added to support new 5GNR operations.
+  The bbdev ABI is still kept experimental.
+
 Shared Library Versions
 -----------------------
 
diff --git a/lib/librte_bbdev/rte_bbdev.c b/lib/librte_bbdev/rte_bbdev.c
index 0c35480..f6fe05a 100644
--- a/lib/librte_bbdev/rte_bbdev.c
+++ b/lib/librte_bbdev/rte_bbdev.c
@@ -6,7 +6,6 @@
 #include <string.h>
 #include <stdbool.h>
 
-#include <rte_string_fns.h>
 #include <rte_compat.h>
 #include <rte_common.h>
 #include <rte_errno.h>
@@ -215,7 +214,7 @@ struct rte_bbdev *
 	bbdev->data->dev_id = dev_id;
 	bbdev->state = RTE_BBDEV_INITIALIZED;
 
-	ret = strlcpy(bbdev->data->name, name, RTE_BBDEV_NAME_MAX_LEN);
+	ret = snprintf(bbdev->data->name, RTE_BBDEV_NAME_MAX_LEN, "%s", name);
 	if ((ret < 0) || (ret >= RTE_BBDEV_NAME_MAX_LEN)) {
 		rte_bbdev_log(ERR, "Copying device name \"%s\" failed", name);
 		return NULL;
@@ -499,7 +498,7 @@ struct rte_bbdev *
 		if (conf->op_type == RTE_BBDEV_OP_TURBO_DEC &&
 			conf->priority > dev_info.max_ul_queue_priority) {
 			rte_bbdev_log(ERR,
-					"Priority (%u) of queue %u of bdev %u must be <= %u",
+					"Priority (%u) of queue %u of bbdev %u must be <= %u",
 					conf->priority, queue_id, dev_id,
 					dev_info.max_ul_queue_priority);
 			return -EINVAL;
@@ -507,7 +506,7 @@ struct rte_bbdev *
 		if (conf->op_type == RTE_BBDEV_OP_TURBO_ENC &&
 			conf->priority > dev_info.max_dl_queue_priority) {
 			rte_bbdev_log(ERR,
-					"Priority (%u) of queue %u of bdev %u must be <= %u",
+					"Priority (%u) of queue %u of bbdev %u must be <= %u",
 					conf->priority, queue_id, dev_id,
 					dev_info.max_dl_queue_priority);
 			return -EINVAL;
@@ -796,7 +795,7 @@ struct rte_bbdev *
 	memset(dev_info, 0, sizeof(*dev_info));
 	dev_info->dev_name = dev->data->name;
 	dev_info->num_queues = dev->data->num_queues;
-	dev_info->bus = rte_bus_find_by_device(dev->device);
+	dev_info->device = dev->device;
 	dev_info->socket_id = dev->data->socket_id;
 	dev_info->started = dev->data->started;
 
@@ -847,6 +846,12 @@ struct rte_bbdev *
 	case RTE_BBDEV_OP_TURBO_ENC:
 		result = sizeof(struct rte_bbdev_enc_op);
 		break;
+	case RTE_BBDEV_OP_LDPC_DEC:
+		result = sizeof(struct rte_bbdev_dec_op);
+		break;
+	case RTE_BBDEV_OP_LDPC_ENC:
+		result = sizeof(struct rte_bbdev_enc_op);
+		break;
 	default:
 		break;
 	}
@@ -861,11 +866,12 @@ struct rte_bbdev *
 {
 	enum rte_bbdev_op_type type = *(enum rte_bbdev_op_type *)arg;
 
-	if (type == RTE_BBDEV_OP_TURBO_DEC) {
+	if (type == RTE_BBDEV_OP_TURBO_DEC || type == RTE_BBDEV_OP_LDPC_DEC) {
 		struct rte_bbdev_dec_op *op = element;
 		memset(op, 0, mempool->elt_size);
 		op->mempool = mempool;
-	} else if (type == RTE_BBDEV_OP_TURBO_ENC) {
+	} else if (type == RTE_BBDEV_OP_TURBO_ENC ||
+			type == RTE_BBDEV_OP_LDPC_ENC) {
 		struct rte_bbdev_enc_op *op = element;
 		memset(op, 0, mempool->elt_size);
 		op->mempool = mempool;
@@ -1117,6 +1123,8 @@ struct rte_mempool *
 		"RTE_BBDEV_OP_NONE",
 		"RTE_BBDEV_OP_TURBO_DEC",
 		"RTE_BBDEV_OP_TURBO_ENC",
+		"RTE_BBDEV_OP_LDPC_DEC",
+		"RTE_BBDEV_OP_LDPC_ENC",
 	};
 
 	if (op_type < RTE_BBDEV_OP_TYPE_COUNT)
diff --git a/lib/librte_bbdev/rte_bbdev.h b/lib/librte_bbdev/rte_bbdev.h
index c5175cc..591fb79 100644
--- a/lib/librte_bbdev/rte_bbdev.h
+++ b/lib/librte_bbdev/rte_bbdev.h
@@ -167,7 +167,7 @@ struct rte_bbdev_queue_conf {
 
 /**
  * Start a device.
- * This is the last step needed before enqueuing operations is possible.
+ * This is the last step needed before enqueueing operations is possible.
  *
  * @param dev_id
  *   The identifier of the device.
@@ -326,7 +326,7 @@ struct rte_bbdev_driver_info {
 struct rte_bbdev_info {
 	int socket_id;  /**< NUMA socket that device is on */
 	const char *dev_name;  /**< Unique device name */
-	const struct rte_bus *bus;  /**< Bus information */
+	const struct rte_device *device; /**< Device Information */
 	uint16_t num_queues;  /**< Number of queues currently configured */
 	bool started;  /**< Set if device is currently started */
 	struct rte_bbdev_driver_info drv;  /**< Info from device driver */
@@ -448,6 +448,14 @@ struct __rte_cache_aligned rte_bbdev {
 	rte_bbdev_dequeue_enc_ops_t dequeue_enc_ops;
 	/**< Dequeue decode function */
 	rte_bbdev_dequeue_dec_ops_t dequeue_dec_ops;
+	/**< Enqueue encode function */
+	rte_bbdev_enqueue_enc_ops_t enqueue_ldpc_enc_ops;
+	/**< Enqueue decode function */
+	rte_bbdev_enqueue_dec_ops_t enqueue_ldpc_dec_ops;
+	/**< Dequeue encode function */
+	rte_bbdev_dequeue_enc_ops_t dequeue_ldpc_enc_ops;
+	/**< Dequeue decode function */
+	rte_bbdev_dequeue_dec_ops_t dequeue_ldpc_dec_ops;
 	const struct rte_bbdev_ops *dev_ops;  /**< Functions exported by PMD */
 	struct rte_bbdev_data *data;  /**< Pointer to device data */
 	enum rte_bbdev_state state;  /**< If device is currently used or not */
@@ -523,6 +531,69 @@ struct __rte_cache_aligned rte_bbdev {
 }
 
 /**
+ * Enqueue a burst of processed encode operations to a queue of the device.
+ * This functions only enqueues as many operations as currently possible and
+ * does not block until @p num_ops entries in the queue are available.
+ * This function does not provide any error notification to avoid the
+ * corresponding overhead.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param queue_id
+ *   The index of the queue.
+ * @param ops
+ *   Pointer array containing operations to be enqueued Must have at least
+ *   @p num_ops entries
+ * @param num_ops
+ *   The maximum number of operations to enqueue.
+ *
+ * @return
+ *   The number of operations actually enqueued (this is the number of processed
+ *   entries in the @p ops array).
+ */
+__rte_experimental
+static inline uint16_t
+rte_bbdev_enqueue_ldpc_enc_ops(uint16_t dev_id, uint16_t queue_id,
+		struct rte_bbdev_enc_op **ops, uint16_t num_ops)
+{
+	struct rte_bbdev *dev = &rte_bbdev_devices[dev_id];
+	struct rte_bbdev_queue_data *q_data = &dev->data->queues[queue_id];
+	return dev->enqueue_ldpc_enc_ops(q_data, ops, num_ops);
+}
+
+/**
+ * Enqueue a burst of processed decode operations to a queue of the device.
+ * This functions only enqueues as many operations as currently possible and
+ * does not block until @p num_ops entries in the queue are available.
+ * This function does not provide any error notification to avoid the
+ * corresponding overhead.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param queue_id
+ *   The index of the queue.
+ * @param ops
+ *   Pointer array containing operations to be enqueued Must have at least
+ *   @p num_ops entries
+ * @param num_ops
+ *   The maximum number of operations to enqueue.
+ *
+ * @return
+ *   The number of operations actually enqueued (this is the number of processed
+ *   entries in the @p ops array).
+ */
+__rte_experimental
+static inline uint16_t
+rte_bbdev_enqueue_ldpc_dec_ops(uint16_t dev_id, uint16_t queue_id,
+		struct rte_bbdev_dec_op **ops, uint16_t num_ops)
+{
+	struct rte_bbdev *dev = &rte_bbdev_devices[dev_id];
+	struct rte_bbdev_queue_data *q_data = &dev->data->queues[queue_id];
+	return dev->enqueue_ldpc_dec_ops(q_data, ops, num_ops);
+}
+
+
+/**
  * Dequeue a burst of processed encode operations from a queue of the device.
  * This functions returns only the current contents of the queue, and does not
  * block until @ num_ops is available.
@@ -585,6 +656,69 @@ struct __rte_cache_aligned rte_bbdev {
 	return dev->dequeue_dec_ops(q_data, ops, num_ops);
 }
 
+
+/**
+ * Dequeue a burst of processed encode operations from a queue of the device.
+ * This functions returns only the current contents of the queue, and does not
+ * block until @ num_ops is available.
+ * This function does not provide any error notification to avoid the
+ * corresponding overhead.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param queue_id
+ *   The index of the queue.
+ * @param ops
+ *   Pointer array where operations will be dequeued to. Must have at least
+ *   @p num_ops entries
+ * @param num_ops
+ *   The maximum number of operations to dequeue.
+ *
+ * @return
+ *   The number of operations actually dequeued (this is the number of entries
+ *   copied into the @p ops array).
+ */
+__rte_experimental
+static inline uint16_t
+rte_bbdev_dequeue_ldpc_enc_ops(uint16_t dev_id, uint16_t queue_id,
+		struct rte_bbdev_enc_op **ops, uint16_t num_ops)
+{
+	struct rte_bbdev *dev = &rte_bbdev_devices[dev_id];
+	struct rte_bbdev_queue_data *q_data = &dev->data->queues[queue_id];
+	return dev->dequeue_ldpc_enc_ops(q_data, ops, num_ops);
+}
+
+/**
+ * Dequeue a burst of processed decode operations from a queue of the device.
+ * This functions returns only the current contents of the queue, and does not
+ * block until @ num_ops is available.
+ * This function does not provide any error notification to avoid the
+ * corresponding overhead.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param queue_id
+ *   The index of the queue.
+ * @param ops
+ *   Pointer array where operations will be dequeued to. Must have at least
+ *   @p num_ops entries
+ * @param num_ops
+ *   The maximum number of operations to dequeue.
+ *
+ * @return
+ *   The number of operations actually dequeued (this is the number of entries
+ *   copied into the @p ops array).
+ */
+__rte_experimental
+static inline uint16_t
+rte_bbdev_dequeue_ldpc_dec_ops(uint16_t dev_id, uint16_t queue_id,
+		struct rte_bbdev_dec_op **ops, uint16_t num_ops)
+{
+	struct rte_bbdev *dev = &rte_bbdev_devices[dev_id];
+	struct rte_bbdev_queue_data *q_data = &dev->data->queues[queue_id];
+	return dev->dequeue_ldpc_dec_ops(q_data, ops, num_ops);
+}
+
 /** Definitions of device event types */
 enum rte_bbdev_event_type {
 	RTE_BBDEV_EVENT_UNKNOWN,  /**< unknown event type */
diff --git a/lib/librte_bbdev/rte_bbdev_op.h b/lib/librte_bbdev/rte_bbdev_op.h
index d860989..1e119a7 100644
--- a/lib/librte_bbdev/rte_bbdev_op.h
+++ b/lib/librte_bbdev/rte_bbdev_op.h
@@ -31,57 +31,61 @@
 #define RTE_BBDEV_TURBO_MAX_TB_SIZE (391656)
 /* Maximum size of Code Block (36.212, Table 5.1.3-3) */
 #define RTE_BBDEV_TURBO_MAX_CB_SIZE (6144)
+/* Maximum size of Code Block  */
+#define RTE_BBDEV_LDPC_MAX_CB_SIZE (8448)
 /* Minimum size of Code Block (36.212, Table 5.1.3-3) */
 #define RTE_BBDEV_TURBO_MIN_CB_SIZE (40)
 /* Maximum size of circular buffer */
 #define RTE_BBDEV_TURBO_MAX_KW (18528)
 /*
- * Maximum number of Code Blocks in Transport Block. It is calculated based on
- * maximum size of one Code Block and one Transport Block (considering CRC24A
- * and CRC24B):
+ * Turbo: Maximum number of Code Blocks in Transport Block. It is calculated
+ * based on maximum size of one Code Block and one Transport Block
+ * (considering CRC24A and CRC24B):
  * (391656 + 24) / (6144 - 24) = 64
  */
 #define RTE_BBDEV_TURBO_MAX_CODE_BLOCKS (64)
+/* LDPC:  Maximum number of Code Blocks in Transport Block.*/
+#define RTE_BBDEV_LDPC_MAX_CODE_BLOCKS (256)
 
 /** Flags for turbo decoder operation and capability structure */
 enum rte_bbdev_op_td_flag_bitmasks {
-	/**< If sub block de-interleaving is to be performed. */
+	/** If sub block de-interleaving is to be performed. */
 	RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE = (1ULL << 0),
-	/**< To use CRC Type 24B (otherwise use CRC Type 24A). */
+	/** To use CRC Type 24B (otherwise use CRC Type 24A). */
 	RTE_BBDEV_TURBO_CRC_TYPE_24B = (1ULL << 1),
-	/**< If turbo equalization is to be performed. */
+	/** If turbo equalization is to be performed. */
 	RTE_BBDEV_TURBO_EQUALIZER = (1ULL << 2),
-	/**< If set, saturate soft output to +/-127 */
+	/** If set, saturate soft output to +/-127 */
 	RTE_BBDEV_TURBO_SOFT_OUT_SATURATE = (1ULL << 3),
-	/**< Set to 1 to start iteration from even, else odd; one iteration =
+	/** Set to 1 to start iteration from even, else odd; one iteration =
 	 * max_iteration + 0.5
 	 */
 	RTE_BBDEV_TURBO_HALF_ITERATION_EVEN = (1ULL << 4),
-	/**< If 0, TD stops after CRC matches; else if 1, runs to end of next
+	/** If 0, TD stops after CRC matches; else if 1, runs to end of next
 	 * odd iteration after CRC matches
 	 */
 	RTE_BBDEV_TURBO_CONTINUE_CRC_MATCH = (1ULL << 5),
-	/**< Set if soft output is required to be output  */
+	/** Set if soft output is required to be output  */
 	RTE_BBDEV_TURBO_SOFT_OUTPUT = (1ULL << 6),
-	/**< Set to enable early termination mode */
+	/** Set to enable early termination mode */
 	RTE_BBDEV_TURBO_EARLY_TERMINATION = (1ULL << 7),
-	/**< Set if a device supports decoder dequeue interrupts */
+	/** Set if a device supports decoder dequeue interrupts */
 	RTE_BBDEV_TURBO_DEC_INTERRUPTS = (1ULL << 9),
-	/**< Set if positive LLR encoded input is supported. Positive LLR value
+	/** Set if positive LLR encoded input is supported. Positive LLR value
 	 * represents the level of confidence for bit '1', and vice versa for
 	 * bit '0'.
 	 * This is mutually exclusive with RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN
 	 * when used to formalize the input data format.
 	 */
 	RTE_BBDEV_TURBO_POS_LLR_1_BIT_IN = (1ULL << 10),
-	/**< Set if negative LLR encoded input is supported. Negative LLR value
+	/** Set if negative LLR encoded input is supported. Negative LLR value
 	 * represents the level of confidence for bit '1', and vice versa for
 	 * bit '0'.
 	 * This is mutually exclusive with RTE_BBDEV_TURBO_POS_LLR_1_BIT_IN
 	 * when used to formalize the input data format.
 	 */
 	RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN = (1ULL << 11),
-	/**< Set if positive LLR soft output is supported. Positive LLR value
+	/** Set if positive LLR soft output is supported. Positive LLR value
 	 * represents the level of confidence for bit '1', and vice versa for
 	 * bit '0'.
 	 * This is mutually exclusive with
@@ -89,7 +93,7 @@ enum rte_bbdev_op_td_flag_bitmasks {
 	 * the input data format.
 	 */
 	RTE_BBDEV_TURBO_POS_LLR_1_BIT_SOFT_OUT = (1ULL << 12),
-	/**< Set if negative LLR soft output is supported. Negative LLR value
+	/** Set if negative LLR soft output is supported. Negative LLR value
 	 * represents the level of confidence for bit '1', and vice versa for
 	 * bit '0'.
 	 * This is mutually exclusive with
@@ -97,43 +101,114 @@ enum rte_bbdev_op_td_flag_bitmasks {
 	 * input data format.
 	 */
 	RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT = (1ULL << 13),
-	/**< Set if driver supports flexible parallel MAP engine decoding. If
+	/** Set if driver supports flexible parallel MAP engine decoding. If
 	 * not supported, num_maps (number of MAP engines) argument is unusable.
 	 */
 	RTE_BBDEV_TURBO_MAP_DEC = (1ULL << 14),
-	/**< Set if a device supports scatter-gather functionality */
+	/** Set if a device supports scatter-gather functionality */
 	RTE_BBDEV_TURBO_DEC_SCATTER_GATHER = (1ULL << 15),
-	/**< Set to keep CRC24B bits appended while decoding. Only usable when
+	/** Set to keep CRC24B bits appended while decoding. Only usable when
 	 * decoding Transport Blocks (code_block_mode = 0).
 	 */
 	RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP = (1ULL << 16)
 };
 
+
 /** Flags for turbo encoder operation and capability structure */
 enum rte_bbdev_op_te_flag_bitmasks {
-	/**< Ignore rv_index and set K0 = 0 */
+	/** Ignore rv_index and set K0 = 0 */
 	RTE_BBDEV_TURBO_RV_INDEX_BYPASS = (1ULL << 0),
-	/**< If rate matching is to be performed */
+	/** If rate matching is to be performed */
 	RTE_BBDEV_TURBO_RATE_MATCH = (1ULL << 1),
-	/**< This bit must be set to enable CRC-24B generation */
+	/** This bit must be set to enable CRC-24B generation */
 	RTE_BBDEV_TURBO_CRC_24B_ATTACH = (1ULL << 2),
-	/**< This bit must be set to enable CRC-24A generation */
+	/** This bit must be set to enable CRC-24A generation */
 	RTE_BBDEV_TURBO_CRC_24A_ATTACH = (1ULL << 3),
-	/**< Set if a device supports encoder dequeue interrupts */
+	/** Set if a device supports encoder dequeue interrupts */
 	RTE_BBDEV_TURBO_ENC_INTERRUPTS = (1ULL << 4),
-	/**< Set if a device supports scatter-gather functionality */
+	/** Set if a device supports scatter-gather functionality */
 	RTE_BBDEV_TURBO_ENC_SCATTER_GATHER = (1ULL << 5)
 };
 
-/**< Data input and output buffer for BBDEV operations */
+/** Flags for LDPC decoder operation and capability structure */
+enum rte_bbdev_op_ldpcdec_flag_bitmasks {
+	/** Set for transport block CRC-24A checking */
+	RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK = (1ULL << 0),
+	/** Set for code block CRC-24B checking */
+	RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK = (1ULL << 1),
+	/** Set to drop the last CRC bits decoding output */
+	RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP = (1ULL << 2),
+	/** Set for bit-level de-interleaver bypass on Rx stream. */
+	RTE_BBDEV_LDPC_DEINTERLEAVER_BYPASS = (1ULL << 3),
+	/** Set for HARQ combined input stream enable. */
+	RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE = (1ULL << 4),
+	/** Set for HARQ combined output stream enable. */
+	RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE = (1ULL << 5),
+	/** Set for LDPC decoder bypass.
+	 *  RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE must be set.
+	 */
+	RTE_BBDEV_LDPC_DECODE_BYPASS = (1ULL << 6),
+	/** Set for soft-output stream enable */
+	RTE_BBDEV_LDPC_SOFT_OUT_ENABLE = (1ULL << 7),
+	/** Set for Rate-Matching bypass on soft-out stream. */
+	RTE_BBDEV_LDPC_SOFT_OUT_RM_BYPASS = (1ULL << 8),
+	/** Set for bit-level de-interleaver bypass on soft-output stream. */
+	RTE_BBDEV_LDPC_SOFT_OUT_DEINTERLEAVER_BYPASS = (1ULL << 9),
+	/** Set for iteration stopping on successful decode condition
+	 *  i.e. a successful syndrome check.
+	 */
+	RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE = (1ULL << 10),
+	/** Set if a device supports decoder dequeue interrupts. */
+	RTE_BBDEV_LDPC_DEC_INTERRUPTS = (1ULL << 11),
+	/** Set if a device supports scatter-gather functionality. */
+	RTE_BBDEV_LDPC_DEC_SCATTER_GATHER = (1ULL << 12),
+	/** Set if a device supports input/output HARQ compression. */
+	RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION = (1ULL << 13),
+	/** Set if a device supports input LLR compression. */
+	RTE_BBDEV_LDPC_LLR_COMPRESSION = (1ULL << 14),
+	/** Set if a device supports HARQ input from
+	 *  device's internal memory.
+	 */
+	RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE = (1ULL << 15),
+	/** Set if a device supports HARQ output to
+	 *  device's internal memory.
+	 */
+	RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE = (1ULL << 16),
+	/** Set if a device supports loop-back access to
+	 *  HARQ internal memory. Intended for troubleshooting.
+	 */
+	RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK = (1ULL << 17)
+};
+
+/** Flags for LDPC encoder operation and capability structure */
+enum rte_bbdev_op_ldpcenc_flag_bitmasks {
+	/** Set for bit-level interleaver bypass on output stream. */
+	RTE_BBDEV_LDPC_INTERLEAVER_BYPASS = (1ULL << 0),
+	/** If rate matching is to be performed */
+	RTE_BBDEV_LDPC_RATE_MATCH = (1ULL << 1),
+	/** Set for transport block CRC-24A attach */
+	RTE_BBDEV_LDPC_CRC_24A_ATTACH = (1ULL << 2),
+	/** Set for code block CRC-24B attach */
+	RTE_BBDEV_LDPC_CRC_24B_ATTACH = (1ULL << 3),
+	/** Set for code block CRC-16 attach */
+	RTE_BBDEV_LDPC_CRC_16_ATTACH = (1ULL << 4),
+	/** Set if a device supports encoder dequeue interrupts. */
+	RTE_BBDEV_LDPC_ENC_INTERRUPTS = (1ULL << 5),
+	/** Set if a device supports scatter-gather functionality. */
+	RTE_BBDEV_LDPC_ENC_SCATTER_GATHER = (1ULL << 6),
+	/** Set if a device supports concatenation of non byte aligned output */
+	RTE_BBDEV_LDPC_ENC_CONCATENATION = (1ULL << 7)
+};
+
+/** Data input and output buffer for BBDEV operations */
 struct rte_bbdev_op_data {
-	/**< The mbuf data structure representing the data for BBDEV operation.
+	/** The mbuf data structure representing the data for BBDEV operation.
 	 *
 	 * This mbuf pointer can point to one Code Block (CB) data buffer or
 	 * multiple CBs contiguously located next to each other.
 	 * A Transport Block (TB) represents a whole piece of data that is
 	 * divided into one or more CBs. Maximum number of CBs can be contained
-	 * in one TB is defined by RTE_BBDEV_TURBO_MAX_CODE_BLOCKS.
+	 * in one TB is defined by RTE_BBDEV_(TURBO/LDPC)_MAX_CODE_BLOCKS.
 	 *
 	 * An mbuf data structure cannot represent more than one TB. The
 	 * smallest piece of data that can be contained in one mbuf is one CB.
@@ -145,8 +220,8 @@ struct rte_bbdev_op_data {
 	 * then it is capable of collecting (gathering) non-contiguous
 	 * (scattered) data from multiple locations in the memory.
 	 * This capability is reported by the capability flags:
-	 * - RTE_BBDEV_TURBO_ENC_SCATTER_GATHER and
-	 * - RTE_BBDEV_TURBO_DEC_SCATTER_GATHER.
+	 * - RTE_BBDEV_(TURBO/LDPC)_ENC_SCATTER_GATHER and
+	 * - RTE_BBDEV_(TURBO/LDPC)_DEC_SCATTER_GATHER.
 	 * Only if a BBDEV PMD supports this feature, chained mbuf data
 	 * structures are accepted. A chained mbuf can represent one
 	 * non-contiguous CB or multiple non-contiguous CBs.
@@ -157,7 +232,7 @@ struct rte_bbdev_op_data {
 	 * was a chained mbuf.
 	 */
 	struct rte_mbuf *data;
-	/**< The starting point of the BBDEV (encode/decode) operation,
+	/** The starting point of the BBDEV (encode/decode) operation,
 	 * in bytes.
 	 *
 	 * BBDEV starts to read data past this offset.
@@ -165,13 +240,13 @@ struct rte_bbdev_op_data {
 	 * segment.
 	 */
 	uint32_t offset;
-	/**< The total data length to be processed in one operation, in bytes.
+	/** The total data length to be processed in one operation, in bytes.
 	 *
 	 * In case the mbuf data is representing one CB, this is the length of
 	 * the CB undergoing the operation.
 	 * If it's for multiple CBs, this is the total length of those CBs
 	 * undergoing the operation.
-	 * If it's for one TB, this is the total length of the TB under
+	 * If it is for one TB, this is the total length of the TB under
 	 * operation.
 	 *
 	 * In case of chained mbuf, this data length includes the lengths of the
@@ -180,51 +255,83 @@ struct rte_bbdev_op_data {
 	uint32_t length;
 };
 
-struct rte_bbdev_op_dec_cb_params {
-	/**< The K size of the input CB, in bits [40:6144], as specified in
+/** Turbo decode code block parameters */
+struct rte_bbdev_op_dec_turbo_cb_params {
+	/** The K size of the input CB, in bits [40:6144], as specified in
 	 * 3GPP TS 36.212.
 	 * This size is inclusive of CRC bits, regardless whether it was
 	 * pre-calculated by the application or not.
 	 */
 	uint16_t k;
-	/**< The E length of the CB rate matched LLR output, in bytes, as in
+	/** The E length of the CB rate matched LLR output, in bytes, as in
 	 * 3GPP TS 36.212.
 	 */
 	uint32_t e;
 };
 
-struct rte_bbdev_op_dec_tb_params {
-	/**< The K- size of the input CB, in bits [40:6144], that is in the
+/** LDPC decode code block parameters */
+struct rte_bbdev_op_dec_ldpc_cb_params {
+	/** Rate matching output sequence length in bits or LLRs.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint32_t e;
+};
+
+/** Turbo decode transport block parameters */
+struct rte_bbdev_op_dec_turbo_tb_params {
+	/** The K- size of the input CB, in bits [40:6144], that is in the
 	 * Turbo operation when r < C-, as in 3GPP TS 36.212.
 	 */
 	uint16_t k_neg;
-	/**< The K+ size of the input CB, in bits [40:6144], that is in the
+	/** The K+ size of the input CB, in bits [40:6144], that is in the
 	 * Turbo operation when r >= C-, as in 3GPP TS 36.212.
 	 */
 	uint16_t k_pos;
-	/**< The number of CBs that have K- size, [0:63] */
+	/** The number of CBs that have K- size, [0:63] */
 	uint8_t c_neg;
-	/**< The total number of CBs in the TB, [1:RTE_BBDEV_TURBO_MAX_CODE_BLOCKS] */
+	/** The total number of CBs in the TB,
+	 * [1:RTE_BBDEV_TURBO_MAX_CODE_BLOCKS]
+	 */
 	uint8_t c;
-	/**< The number of CBs that uses Ea before switching to Eb, [0:63] */
+	/** The number of CBs that uses Ea before switching to Eb, [0:63] */
 	uint8_t cab;
-	/**< The E size of the CB rate matched output to use in the Turbo
+	/** The E size of the CB rate matched output to use in the Turbo
 	 * operation when r < cab
 	 */
 	uint32_t ea;
-	/**< The E size of the CB rate matched output to use in the Turbo
+	/** The E size of the CB rate matched output to use in the Turbo
 	 * operation when r >= cab
 	 */
 	uint32_t eb;
-	/**< The index of the first CB in the inbound mbuf data, default is 0 */
+	/** The index of the first CB in the inbound mbuf data, default is 0 */
 	uint8_t r;
 };
 
-/**< Operation structure for Turbo decode.
- * An operation can perform on one CB at a time "CB-mode".
- * An operation can perform on one or multiple CBs that are logically belonging
- * to one TB "TB-mode".
- * The provided K size parameter of the CB is its size out coming from the
+/** LDPC decode transport block parameters */
+struct rte_bbdev_op_dec_ldpc_tb_params {
+	/** Ea, length after rate matching in bits, r < cab.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint32_t ea;
+	/** Eb, length after rate matching in bits, r >= cab.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint32_t eb;
+	/** The total number of CBs in the TB or partial TB
+	 * [1:RTE_BBDEV_LDPC_MAX_CODE_BLOCKS]
+	 */
+	uint8_t c;
+	/** The index of the first CB in the inbound mbuf data, default is 0 */
+	uint8_t r;
+	/** The number of CBs that use Ea before switching to Eb, [0:63] */
+	uint8_t cab;
+};
+
+/** Operation structure for Turbo decode.
+ * An operation can be performed on one CB at a time "CB-mode".
+ * An operation can be performed on one or multiple CBs that logically
+ * belong to one TB "TB-mode".
+ * The provided K size parameter of the CB is its size coming from the
  * decode operation.
  * CRC24A/B check is requested by the application by setting the flag
  * RTE_BBDEV_TURBO_CRC_TYPE_24B for CRC24B check or CRC24A otherwise.
@@ -249,94 +356,192 @@ struct rte_bbdev_op_dec_tb_params {
  * application with enough room for the output data.
  */
 struct rte_bbdev_op_turbo_dec {
-	/**< The Virtual Circular Buffer, wk, size 3*Kpi for each CB */
+	/** The Virtual Circular Buffer, wk, size 3*Kpi for each CB */
 	struct rte_bbdev_op_data input;
-	/**< The hard decisions buffer for the decoded output,
+	/** The hard decisions buffer for the decoded output,
 	 * size K for each CB
 	 */
 	struct rte_bbdev_op_data hard_output;
-	/**< The soft LLR output buffer - optional */
+	/** The soft LLR output buffer - optional */
 	struct rte_bbdev_op_data soft_output;
 
-	uint32_t op_flags;  /**< Flags from rte_bbdev_op_td_flag_bitmasks */
-	uint8_t rv_index;  /**< Rv index for rate matching [0:3] */
-	/**< The minimum number of iterations to perform in decoding all CBs in
+	/** Flags from rte_bbdev_op_td_flag_bitmasks */
+	uint32_t op_flags;
+
+	/** Rv index for rate matching [0:3] */
+	uint8_t rv_index;
+	/** The minimum number of iterations to perform in decoding all CBs in
 	 * this operation - input
 	 */
 	uint8_t iter_min:4;
-	/**< The maximum number of iterations to perform in decoding all CBs in
+	/** The maximum number of iterations to perform in decoding all CBs in
 	 * this operation - input
 	 */
 	uint8_t iter_max:4;
-	/**< The maximum number of iterations that were perform in decoding all
-	 * CBs in this decode operation - output
+	/** The maximum number of iterations that were performed in decoding
+	 * all CBs in this decode operation - output
 	 */
 	uint8_t iter_count;
-	/**< 5 bit extrinsic scale (scale factor on extrinsic info) */
+	/** 5 bit extrinsic scale (scale factor on extrinsic info) */
 	uint8_t ext_scale;
-	/**< Number of MAP engines to use in decode,
-	 * must be power of 2 (or 0 to auto-select)
+	/** Number of MAP engines to use in decode,
+	 *  must be power of 2 (or 0 to auto-select)
 	 */
 	uint8_t num_maps;
 
-	uint8_t code_block_mode; /**< [0 - TB : 1 - CB] */
+	/**< [0 - TB : 1 - CB] */
+	uint8_t code_block_mode;
 	union {
 		/**< Struct which stores Code Block specific parameters */
-		struct rte_bbdev_op_dec_cb_params cb_params;
+		struct rte_bbdev_op_dec_turbo_cb_params cb_params;
 		/**< Struct which stores Transport Block specific parameters */
-		struct rte_bbdev_op_dec_tb_params tb_params;
+		struct rte_bbdev_op_dec_turbo_tb_params tb_params;
 	};
 };
 
+/** Operation structure for LDPC decode.
+ *
+ * An operation can be performed on one CB at a time "CB-mode".
+ * An operation can also be performed on one or multiple CBs that logically
+ * belong to a TB "TB-mode" (Currently not supported).
+ *
+ * The input encoded CB data is the Virtual Circular Buffer data stream.
+ *
+ * Each byte in the input circular buffer is the LLR value of each bit of the
+ * original CB.
+ *
+ * Hard output is a mandatory capability that all BBDEV PMDs support. This is
+ * the decoded CBs (CRC24A/B is the last 24-bit in each decoded CB).
+ *
+ * Soft output is an optional capability for BBDEV PMDs. If supported, an LLR
+ * rate matched output is computed in the soft_output buffer structure.
+ * These are A Posteriori Probabilities (APP) LLR samples for coded bits.
+ *
+ * HARQ combined output is an optional capability for BBDEV PMDs.
+ * If supported, a LLR output is streamed to the harq_combined_output
+ * buffer.
+ *
+ * HARQ combined input is an optional capability for BBDEV PMDs.
+ * If supported, a LLR input is streamed from the harq_combined_input
+ * buffer.
+ *
+ * The output mbuf data structure is expected to be allocated by the
+ * application with enough room for the output data.
+ */
+struct rte_bbdev_op_ldpc_dec {
+	/** The Virtual Circular Buffer for this code block, one LLR
+	 * per bit of the original CB.
+	 */
+	struct rte_bbdev_op_data input;
+	/** The hard decisions buffer for the decoded output,
+	 * size K for each CB
+	 */
+	struct rte_bbdev_op_data hard_output;
+	/** The soft LLR output LLR stream buffer - optional */
+	struct rte_bbdev_op_data soft_output;
+	/** The HARQ combined LLR stream input buffer - optional */
+	struct rte_bbdev_op_data harq_combined_input;
+	/** The HARQ combined LLR stream output buffer - optional */
+	struct rte_bbdev_op_data harq_combined_output;
+
+	/** Flags from rte_bbdev_op_ldpcdec_flag_bitmasks */
+	uint32_t op_flags;
+
+	/** Rate matching redundancy version
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint8_t rv_index;
+	/** The maximum number of iterations to perform in decoding CB in
+	 *  this operation - input
+	 */
+	uint8_t iter_max;
+	/** The number of iterations that were performed in decoding
+	 * CB in this decode operation - output
+	 */
+	uint8_t iter_count;
+	/** 1: LDPC Base graph 1, 2: LDPC Base graph 2.
+	 * [3GPP TS38.212, section 5.2.2]
+	 */
+	uint8_t basegraph;
+	/** Zc, LDPC lifting size.
+	 *  [3GPP TS38.212, section 5.2.2]
+	 */
+	uint16_t z_c;
+	/** Ncb, length of the circular buffer in bits.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint16_t n_cb;
+	/** Qm, modulation order {1,2,4,6,8}.
+	 *  [3GPP TS38.212, section 5.4.2.2]
+	 */
+	uint8_t q_m;
+	/** Number of Filler bits, n_filler = K – K’
+	 *  [3GPP TS38.212 section 5.2.2]
+	 */
+	uint16_t n_filler;
+	/** [0 - TB : 1 - CB] */
+	uint8_t code_block_mode;
+	union {
+		/** Struct which stores Code Block specific parameters */
+		struct rte_bbdev_op_dec_ldpc_cb_params cb_params;
+		/** Struct which stores Transport Block specific parameters */
+		struct rte_bbdev_op_dec_ldpc_tb_params tb_params;
+	};
+};
+
+/** Turbo encode code block parameters */
 struct rte_bbdev_op_enc_turbo_cb_params {
-	/**< The K size of the input CB, in bits [40:6144], as specified in
+	/** The K size of the input CB, in bits [40:6144], as specified in
 	 * 3GPP TS 36.212.
 	 * This size is inclusive of CRC24A, regardless whether it was
 	 * pre-calculated by the application or not.
 	 */
 	uint16_t k;
-	/**< The E length of the CB rate matched output, in bits, as in
+	/** The E length of the CB rate matched output, in bits, as in
 	 * 3GPP TS 36.212.
 	 */
 	uint32_t e;
-	/**< The Ncb soft buffer size of the CB rate matched output [K:3*Kpi],
+	/** The Ncb soft buffer size of the CB rate matched output [K:3*Kpi],
 	 * in bits, as specified in 3GPP TS 36.212.
 	 */
 	uint16_t ncb;
 };
 
+/** Turbo encode transport block parameters */
 struct rte_bbdev_op_enc_turbo_tb_params {
-	/**< The K- size of the input CB, in bits [40:6144], that is in the
+	/** The K- size of the input CB, in bits [40:6144], that is in the
 	 * Turbo operation when r < C-, as in 3GPP TS 36.212.
 	 * This size is inclusive of CRC24B, regardless whether it was
 	 * pre-calculated and appended by the application or not.
 	 */
 	uint16_t k_neg;
-	/**< The K+ size of the input CB, in bits [40:6144], that is in the
+	/** The K+ size of the input CB, in bits [40:6144], that is in the
 	 * Turbo operation when r >= C-, as in 3GPP TS 36.212.
 	 * This size is inclusive of CRC24B, regardless whether it was
 	 * pre-calculated and appended by the application or not.
 	 */
 	uint16_t k_pos;
-	/**< The number of CBs that have K- size, [0:63] */
+	/** The number of CBs that have K- size, [0:63] */
 	uint8_t c_neg;
-	/**< The total number of CBs in the TB, [1:RTE_BBDEV_TURBO_MAX_CODE_BLOCKS] */
+	/** The total number of CBs in the TB,
+	 * [1:RTE_BBDEV_TURBO_MAX_CODE_BLOCKS]
+	 */
 	uint8_t c;
-	/**< The number of CBs that uses Ea before switching to Eb, [0:63] */
+	/** The number of CBs that uses Ea before switching to Eb, [0:63] */
 	uint8_t cab;
-	/**< The E size of the CB rate matched output to use in the Turbo
+	/** The E size of the CB rate matched output to use in the Turbo
 	 * operation when r < cab
 	 */
 	uint32_t ea;
-	/**< The E size of the CB rate matched output to use in the Turbo
+	/** The E size of the CB rate matched output to use in the Turbo
 	 * operation when r >= cab
 	 */
 	uint32_t eb;
-	/**< The Ncb soft buffer size for the rate matched CB that is used in
+	/** The Ncb soft buffer size for the rate matched CB that is used in
 	 * the Turbo operation when r < C-, [K:3*Kpi]
 	 */
 	uint16_t ncb_neg;
-	/**< The Ncb soft buffer size for the rate matched CB that is used in
+	/** The Ncb soft buffer size for the rate matched CB that is used in
 	 * the Turbo operation when r >= C-, [K:3*Kpi]
 	 */
 	uint16_t ncb_pos;
@@ -344,10 +549,38 @@ struct rte_bbdev_op_enc_turbo_tb_params {
 	uint8_t r;
 };
 
-/**< Operation structure for Turbo encode.
- * An operation can perform on one CB at a time "CB-mode".
- * An operation can perform on one or multiple CBs that are logically
- * belonging to one TB "TB-mode".
+/** LDPC encode code block parameters */
+struct rte_bbdev_op_enc_ldpc_cb_params {
+	/** E, length after rate matching in bits.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint32_t e;
+};
+
+/** LDPC encode transport block parameters */
+struct rte_bbdev_op_enc_ldpc_tb_params {
+	/** Ea, length after rate matching in bits, r < cab.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint32_t ea;
+	/** Eb, length after rate matching in bits, r >= cab.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint32_t eb;
+	/** The total number of CBs in the TB or partial TB
+	 * [1:RTE_BBDEV_LDPC_MAX_CODE_BLOCKS]
+	 */
+	uint8_t c;
+	/** The index of the first CB in the inbound mbuf data, default is 0 */
+	uint8_t r;
+	/** The number of CBs that use Ea before switching to Eb, [0:63] */
+	uint8_t cab;
+};
+
+/** Operation structure for Turbo encode.
+ * An operation can be performed on one CB at a time "CB-mode".
+ * An operation can pbe erformd on one or multiple CBs that logically
+ * belong to one TB "TB-mode".
  *
  * In CB-mode, CRC24A/B is an optional operation. K size parameter is not
  * affected by CRC24A/B inclusion, this only affects the inbound mbuf data
@@ -364,44 +597,131 @@ struct rte_bbdev_op_enc_turbo_tb_params {
  * application with enough room for the output data.
  */
 struct rte_bbdev_op_turbo_enc {
-	/**< The input CB or TB data */
+	/** The input CB or TB data */
 	struct rte_bbdev_op_data input;
-	/**< The rate matched CB or TB output buffer */
+	/** The rate matched CB or TB output buffer */
 	struct rte_bbdev_op_data output;
+	/** Flags from rte_bbdev_op_te_flag_bitmasks */
+	uint32_t op_flags;
 
-	uint32_t op_flags;  /**< Flags from rte_bbdev_op_te_flag_bitmasks */
-	uint8_t rv_index;  /**< Rv index for rate matching [0:3] */
-
-	uint8_t code_block_mode; /**< [0 - TB : 1 - CB] */
+	/** Rv index for rate matching [0:3] */
+	uint8_t rv_index;
+	/** [0 - TB : 1 - CB] */
+	uint8_t code_block_mode;
 	union {
-		/**< Struct which stores Code Block specific parameters */
+		/** Struct which stores Code Block specific parameters */
 		struct rte_bbdev_op_enc_turbo_cb_params cb_params;
-		/**< Struct which stores Transport Block specific parameters */
+		/** Struct which stores Transport Block specific parameters */
 		struct rte_bbdev_op_enc_turbo_tb_params tb_params;
 	};
 };
 
-/**< List of the capabilities for the Turbo Decoder */
+/** Operation structure for LDPC encode.
+ * An operation can be performed on one CB at a time "CB-mode".
+ * An operation can be performed on one or multiple CBs that logically
+ * belong to a TB "TB-mode".
+ *
+ * The input data is the CB or TB input to the decoder.
+ *
+ * The output data is the ratematched CB or TB data, or the output after
+ * bit-selection if RTE_BBDEV_LDPC_INTERLEAVER_BYPASS is set.
+ *
+ * The output mbuf data structure is expected to be allocated by the
+ * application with enough room for the output data.
+ */
+struct rte_bbdev_op_ldpc_enc {
+	/** The input TB or CB data */
+	struct rte_bbdev_op_data input;
+	/** The rate matched TB or CB output buffer */
+	struct rte_bbdev_op_data output;
+
+	/** Flags from rte_bbdev_op_ldpcenc_flag_bitmasks */
+	uint32_t op_flags;
+
+	/** Rate matching redundancy version */
+	uint8_t rv_index;
+	/** 1: LDPC Base graph 1, 2: LDPC Base graph 2.
+	 *  [3GPP TS38.212, section 5.2.2]
+	 */
+	uint8_t basegraph;
+	/** Zc, LDPC lifting size.
+	 *  [3GPP TS38.212, section 5.2.2]
+	 */
+	uint16_t z_c;
+	/** Ncb, length of the circular buffer in bits.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint16_t n_cb;
+	/** Qm, modulation order {2,4,6,8,10}.
+	 *  [3GPP TS38.212, section 5.4.2.2]
+	 */
+	uint8_t q_m;
+	/** Number of Filler bits, n_filler = K – K’
+	 *  [3GPP TS38.212 section 5.2.2]
+	 */
+	uint16_t n_filler;
+	/** [0 - TB : 1 - CB] */
+	uint8_t code_block_mode;
+	union {
+		/** Struct which stores Code Block specific parameters */
+		struct rte_bbdev_op_enc_ldpc_cb_params cb_params;
+		/** Struct which stores Transport Block specific parameters */
+		struct rte_bbdev_op_enc_ldpc_tb_params tb_params;
+	};
+};
+
+/** List of the capabilities for the Turbo Decoder */
 struct rte_bbdev_op_cap_turbo_dec {
-	/**< Flags from rte_bbdev_op_td_flag_bitmasks */
+	/** Flags from rte_bbdev_op_td_flag_bitmasks */
 	uint32_t capability_flags;
 	/** Maximal LLR absolute value. Acceptable LLR values lie in range
 	 * [-max_llr_modulus, max_llr_modulus].
 	 */
 	int8_t max_llr_modulus;
+	/** Num input code block buffers */
 	uint8_t num_buffers_src;  /**< Num input code block buffers */
-	/**< Num hard output code block buffers */
+	/** Num hard output code block buffers */
 	uint8_t num_buffers_hard_out;
-	/**< Num soft output code block buffers if supported by the driver */
+	/** Num soft output code block buffers if supported by the driver */
 	uint8_t num_buffers_soft_out;
 };
 
-/**< List of the capabilities for the Turbo Encoder */
+/** List of the capabilities for the Turbo Encoder */
 struct rte_bbdev_op_cap_turbo_enc {
-	/**< Flags from rte_bbdev_op_te_flag_bitmasks */
+	/** Flags from rte_bbdev_op_te_flag_bitmasks */
 	uint32_t capability_flags;
-	uint8_t num_buffers_src;  /**< Num input code block buffers */
-	uint8_t num_buffers_dst;  /**< Num output code block buffers */
+	/** Num input code block buffers */
+	uint8_t num_buffers_src;
+	/** Num output code block buffers */
+	uint8_t num_buffers_dst;
+};
+
+/** List of the capabilities for the LDPC Decoder */
+struct rte_bbdev_op_cap_ldpc_dec {
+	/** Flags from rte_bbdev_op_ldpcdec_flag_bitmasks */
+	uint32_t capability_flags;
+	/** LLR size in bits. LLR is a two’s complement number. */
+	int8_t llr_size;
+	/** LLR numbers of decimals bit for arithmetic representation */
+	int8_t llr_decimals;
+	/** Amount of memory for HARQ in external DDR in MB */
+	uint16_t harq_memory_size;
+	/** Num input code block buffers */
+	uint16_t num_buffers_src;
+	/** Num hard output code block buffers */
+	uint16_t num_buffers_hard_out;
+	/** Num soft output code block buffers if supported by the driver */
+	uint16_t num_buffers_soft_out;
+};
+
+/** List of the capabilities for the LDPC Encoder */
+struct rte_bbdev_op_cap_ldpc_enc {
+	/** Flags from rte_bbdev_op_ldpcenc_flag_bitmasks */
+	uint32_t capability_flags;
+	/** Num input code block buffers */
+	uint16_t num_buffers_src;
+	/** Num output code block buffers */
+	uint16_t num_buffers_dst;
 };
 
 /** Different operation types supported by the device */
@@ -409,40 +729,59 @@ enum rte_bbdev_op_type {
 	RTE_BBDEV_OP_NONE,  /**< Dummy operation that does nothing */
 	RTE_BBDEV_OP_TURBO_DEC,  /**< Turbo decode */
 	RTE_BBDEV_OP_TURBO_ENC,  /**< Turbo encode */
+	RTE_BBDEV_OP_LDPC_DEC,  /**< LDPC decode */
+	RTE_BBDEV_OP_LDPC_ENC,  /**< LDPC encode */
 	RTE_BBDEV_OP_TYPE_COUNT,  /**< Count of different op types */
 };
 
-/**< Bit indexes of possible errors reported through status field */
+/** Bit indexes of possible errors reported through status field */
 enum {
 	RTE_BBDEV_DRV_ERROR,
 	RTE_BBDEV_DATA_ERROR,
 	RTE_BBDEV_CRC_ERROR,
+	RTE_BBDEV_SYNDROME_ERROR
 };
 
-/**< Structure specifying a single encode operation */
+/** Structure specifying a single encode operation */
 struct rte_bbdev_enc_op {
-	int status;  /**< Status of operation that was performed */
-	struct rte_mempool *mempool;  /**< Mempool which op instance is in */
-	void *opaque_data;  /**< Opaque pointer for user data */
-	/**< Contains encoder specific parameters */
-	struct rte_bbdev_op_turbo_enc turbo_enc;
+	/**< Status of operation that was performed */
+	int status;
+	/**< Mempool which op instance is in */
+	struct rte_mempool *mempool;
+	/**< Opaque pointer for user data */
+	void *opaque_data;
+	union {
+		/** Contains turbo decoder specific parameters */
+		struct rte_bbdev_op_turbo_enc turbo_enc;
+		/** Contains LDPC decoder specific parameters */
+		struct rte_bbdev_op_ldpc_enc ldpc_enc;
+	};
 };
 
-/**< Structure specifying a single decode operation */
+/** Structure specifying a single decode operation */
 struct rte_bbdev_dec_op {
-	int status;  /**< Status of operation that was performed */
-	struct rte_mempool *mempool;  /**< Mempool which op instance is in */
-	void *opaque_data;  /**< Opaque pointer for user data */
-	/**< Contains decoder specific parameters */
-	struct rte_bbdev_op_turbo_dec turbo_dec;
+	/** Status of operation that was performed */
+	int status;
+	/** Mempool which op instance is in */
+	struct rte_mempool *mempool;
+	/** Opaque pointer for user data */
+	void *opaque_data;
+	union {
+		/** Contains turbo decoder specific parameters */
+		struct rte_bbdev_op_turbo_dec turbo_dec;
+		/** Contains LDPC decoder specific parameters */
+		struct rte_bbdev_op_ldpc_dec ldpc_dec;
+	};
 };
 
-/**< Operation capabilities supported by a device */
+/** Operation capabilities supported by a device */
 struct rte_bbdev_op_cap {
 	enum rte_bbdev_op_type type;  /**< Type of operation */
 	union {
 		struct rte_bbdev_op_cap_turbo_dec turbo_dec;
 		struct rte_bbdev_op_cap_turbo_enc turbo_enc;
+		struct rte_bbdev_op_cap_ldpc_dec ldpc_dec;
+		struct rte_bbdev_op_cap_ldpc_enc ldpc_enc;
 	} cap;  /**< Operation-type specific capabilities */
 };
 
@@ -516,7 +855,8 @@ struct rte_mempool *
 	/* Check type */
 	priv = (struct rte_bbdev_op_pool_private *)
 			rte_mempool_get_priv(mempool);
-	if (unlikely(priv->type != RTE_BBDEV_OP_TURBO_ENC))
+	if (unlikely((priv->type != RTE_BBDEV_OP_TURBO_ENC) &&
+					(priv->type != RTE_BBDEV_OP_LDPC_ENC)))
 		return -EINVAL;
 
 	/* Get elements */
@@ -552,7 +892,8 @@ struct rte_mempool *
 	/* Check type */
 	priv = (struct rte_bbdev_op_pool_private *)
 			rte_mempool_get_priv(mempool);
-	if (unlikely(priv->type != RTE_BBDEV_OP_TURBO_DEC))
+	if (unlikely((priv->type != RTE_BBDEV_OP_TURBO_DEC) &&
+					(priv->type != RTE_BBDEV_OP_LDPC_DEC)))
 		return -EINVAL;
 
 	/* Get elements */
-- 
1.8.3.1


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v4 1/4] ethdev: add GRE key field to flow API
  @ 2019-07-03 15:25  4%     ` Adrien Mazarguil
  2019-07-04  2:43  0%       ` Jack Min
  0 siblings, 1 reply; 200+ results
From: Adrien Mazarguil @ 2019-07-03 15:25 UTC (permalink / raw)
  To: Xiaoyu Min
  Cc: orika, John McNamara, Marko Kovacevic, Thomas Monjalon,
	Ferruh Yigit, Andrew Rybchenko, dev

On Tue, Jul 02, 2019 at 05:45:52PM +0800, Xiaoyu Min wrote:
> Add new rte_flow_item_gre_key in order to match the optional key field.
> 
> Signed-off-by: Xiaoyu Min <jackmin@mellanox.com>

OK with adding this feature, however I still have a bunch of comments below.

> ---
>  doc/guides/prog_guide/rte_flow.rst | 8 ++++++++
>  lib/librte_ethdev/rte_flow.c       | 1 +
>  lib/librte_ethdev/rte_flow.h       | 7 +++++++
>  3 files changed, 16 insertions(+)
> 
> diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
> index a34d012e55..f4b7baa3c3 100644
> --- a/doc/guides/prog_guide/rte_flow.rst
> +++ b/doc/guides/prog_guide/rte_flow.rst
> @@ -980,6 +980,14 @@ Matches a GRE header.
>  - ``protocol``: protocol type.
>  - Default ``mask`` matches protocol only.
>  
> +Item: ``GRE_KEY``
> +^^^^^^^^^^^^^^^^^
> +
> +Matches a GRE key field.
> +This should be preceded by item ``GRE``

Nit: missing ending "."

> +
> +- Value to be matched is a big-endian 32 bit integer
> +
>  Item: ``FUZZY``
>  ^^^^^^^^^^^^^^^
>  
> diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c
> index 3277be1edb..f3e56d0bbe 100644
> --- a/lib/librte_ethdev/rte_flow.c
> +++ b/lib/librte_ethdev/rte_flow.c
> @@ -55,6 +55,7 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
>  	MK_FLOW_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
>  	MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
>  	MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
> +	MK_FLOW_ITEM(GRE_KEY, sizeof(rte_be32_t)),

Hmm? Adding a new item in the middle?

>  	MK_FLOW_ITEM(FUZZY, sizeof(struct rte_flow_item_fuzzy)),
>  	MK_FLOW_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
>  	MK_FLOW_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
> diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
> index f3a8fb103f..5d3702a44c 100644
> --- a/lib/librte_ethdev/rte_flow.h
> +++ b/lib/librte_ethdev/rte_flow.h
> @@ -289,6 +289,13 @@ enum rte_flow_item_type {
>  	 */
>  	RTE_FLOW_ITEM_TYPE_GRE,
>  
> +	/**
> +	 * Matches a GRE optional key field.
> +	 *
> +	 * The value should a big-endian 32bit integer.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_GRE_KEY,
> +

Same comment. While I understand the intent to group GRE and GRE_KEY, doing
so causes ABI breakage by shifting the value of all subsequent pattern
items (see IPV6 and IPV6_EXT for instance).

We could later decide to sort them while knowingly breaking ABI on purpose,
however right now there's no choice but adding new pattern items and actions
at the end of their respective enums, please do that.

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v3 2/8] cryptodev: add digest encrypted feature flag
  @ 2019-07-03 11:15  4%     ` Damian Nowak
  0 siblings, 0 replies; 200+ results
From: Damian Nowak @ 2019-07-03 11:15 UTC (permalink / raw)
  To: dev; +Cc: akhil.goyal, fiona.trahe, arkadiuszx.kusztal, Damian Nowak

Some PMDs can only support digest being
encrypted separately in auth-cipher operations.
Thus it is required to add feature flag in PMD
to reflect if it does support digest-appended
both: digest generation with encryption and
decryption with digest verification.
This patch also adds information about new
feature flag to the release notes.

Signed-off-by: Damian Nowak <damianx.nowak@intel.com>
---
 doc/guides/cryptodevs/features/default.ini | 1 +
 doc/guides/cryptodevs/overview.rst         | 3 +++
 doc/guides/rel_notes/release_19_08.rst     | 3 +++
 lib/librte_cryptodev/rte_cryptodev.c       | 2 ++
 lib/librte_cryptodev/rte_cryptodev.h       | 2 ++
 5 files changed, 11 insertions(+)

diff --git a/doc/guides/cryptodevs/features/default.ini b/doc/guides/cryptodevs/features/default.ini
index 0e06261..d3ee1af 100644
--- a/doc/guides/cryptodevs/features/default.ini
+++ b/doc/guides/cryptodevs/features/default.ini
@@ -25,6 +25,7 @@ OOP LB  In SGL Out     =
 OOP LB  In LB  Out     =
 RSA PRIV OP KEY EXP    =
 RSA PRIV OP KEY QT     =
+Digest encrypted       =
 
 ;
 ; Supported crypto algorithms of a default crypto driver.
diff --git a/doc/guides/cryptodevs/overview.rst b/doc/guides/cryptodevs/overview.rst
index a972c79..e2a1e08 100644
--- a/doc/guides/cryptodevs/overview.rst
+++ b/doc/guides/cryptodevs/overview.rst
@@ -43,6 +43,9 @@ Supported Feature Flags
    - "RSA PRIV OP KEY QT" feature flag means PMD support RSA private key
      operation (Sign and Decrypt) using quintuple (crt) type key only.
 
+   - "Digest encrypted" feature flag means PMD support hash-cipher cases,
+     where generated digest is appended to and encrypted with the data.
+
 
 Supported Cipher Algorithms
 ---------------------------
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 644a74b..c82b7f5 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -169,6 +169,9 @@ API Changes
   structure (``rte_crypto_cipher_xform``, ``rte_crypto_auth_xform``, and
   ``rte_crypto_aead_xform``) have been changed to ``const uint8_t *data``.
 
+* cryptodev: ``RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED`` feature flag
+  has been introduced.
+
 
 ABI Changes
 -----------
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 240b849..43bc335 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -490,6 +490,8 @@ rte_cryptodev_get_feature_name(uint64_t flag)
 		return "RSA_PRIV_OP_KEY_EXP";
 	case RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT:
 		return "RSA_PRIV_OP_KEY_QT";
+	case RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED:
+		return "DIGEST_ENCRYPTED";
 	default:
 		return NULL;
 	}
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index d701eea..e175b83 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -446,6 +446,8 @@ rte_cryptodev_asym_get_xform_enum(enum rte_crypto_asym_xform_type *xform_enum,
 /**< Support RSA Private Key OP with exponent */
 #define RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT		(1ULL << 18)
 /**< Support RSA Private Key OP with CRT (quintuple) Keys */
+#define RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED		(1ULL << 19)
+/**< Support encrypted-digest operations where digest is appended to data */
 
 
 /**
-- 
2.7.4


^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [RFC PATCH] bus/pci: avoid depending on private value in kernel source
  2019-07-03  9:10  0%                 ` David Marchand
@ 2019-07-03  9:25  0%                   ` Tiwei Bie
  0 siblings, 0 replies; 200+ results
From: Tiwei Bie @ 2019-07-03  9:25 UTC (permalink / raw)
  To: David Marchand; +Cc: dev, Burakov, Anatoly

On Wed, Jul 03, 2019 at 11:10:21AM +0200, David Marchand wrote:
> 
> On Wed, Jul 3, 2019 at 11:01 AM Tiwei Bie <tiwei.bie@intel.com> wrote:
> 
>     On Wed, Jul 03, 2019 at 10:26:39AM +0200, David Marchand wrote:
>     > This patch breaks the ABI by extending rte_pci_device.
>     > You must rework it to avoid this break.
> 
>     I didn't expect it to be merged in this release. I just want
>     to draw other's attention on this and kick off the discussion
>     (it would be great if you would like to share your thoughts
>     on this). If there is a way to avoid extending rte_pci_device,
>     it would be definitely great. But if we have to break it, then
>     we would want to send out the announce as early as possible.
> 
> 
> What we have here is a vfio private thing, we don't need it to be exposed.
> 
> Did not think it through yet.
> How about having an internal (as in, in the pci driver code) representation of
> the pci devices?
> This internal structure would embed the rte_pci_device exposed to the others
> subsystems and the applications and the vfio code would just get what it wants
> by using offsetof?

I think it's a good idea! I'll give it a try.

Thanks!
Tiwei

> 
> 
> --
> David Marchand

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC PATCH] bus/pci: avoid depending on private value in kernel source
  2019-07-03  8:59  0%               ` Tiwei Bie
@ 2019-07-03  9:10  0%                 ` David Marchand
  2019-07-03  9:25  0%                   ` Tiwei Bie
  0 siblings, 1 reply; 200+ results
From: David Marchand @ 2019-07-03  9:10 UTC (permalink / raw)
  To: Tiwei Bie; +Cc: dev, Burakov, Anatoly

On Wed, Jul 3, 2019 at 11:01 AM Tiwei Bie <tiwei.bie@intel.com> wrote:

> On Wed, Jul 03, 2019 at 10:26:39AM +0200, David Marchand wrote:
> > This patch breaks the ABI by extending rte_pci_device.
> > You must rework it to avoid this break.
>
> I didn't expect it to be merged in this release. I just want
> to draw other's attention on this and kick off the discussion
> (it would be great if you would like to share your thoughts
> on this). If there is a way to avoid extending rte_pci_device,
> it would be definitely great. But if we have to break it, then
> we would want to send out the announce as early as possible.
>

What we have here is a vfio private thing, we don't need it to be exposed.

Did not think it through yet.
How about having an internal (as in, in the pci driver code) representation
of the pci devices?
This internal structure would embed the rte_pci_device exposed to the
others subsystems and the applications and the vfio code would just get
what it wants by using offsetof?


-- 
David Marchand

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC PATCH] bus/pci: avoid depending on private value in kernel source
  2019-07-03  8:26  3%             ` David Marchand
@ 2019-07-03  8:59  0%               ` Tiwei Bie
  2019-07-03  9:10  0%                 ` David Marchand
  0 siblings, 1 reply; 200+ results
From: Tiwei Bie @ 2019-07-03  8:59 UTC (permalink / raw)
  To: David Marchand; +Cc: dev, Burakov, Anatoly

On Wed, Jul 03, 2019 at 10:26:39AM +0200, David Marchand wrote:
> On Wed, Jul 3, 2019 at 10:17 AM Tiwei Bie <tiwei.bie@intel.com> wrote:
> 
>     On Wed, Jul 03, 2019 at 10:01:44AM +0200, David Marchand wrote:
>     > On Wed, Jul 3, 2019 at 9:58 AM Tiwei Bie <tiwei.bie@intel.com> wrote:
>     >
>     >     On Wed, Jul 03, 2019 at 09:36:26AM +0200, David Marchand wrote:
>     >     > On Wed, Jul 3, 2019 at 9:35 AM Tiwei Bie <tiwei.bie@intel.com>
>     wrote:
>     >     >
>     >     >     Hi David,
>     >     >
>     >     >     On Wed, Jul 03, 2019 at 09:02:59AM +0200, David Marchand wrote:
>     >     >     > Hello,
>     >     >     >
>     >     >     > On Wed, Jul 3, 2019 at 7:47 AM Tiwei Bie <tiwei.bie@intel.com
>     >
>     >     wrote:
>     >     >     >
>     >     >     >     The value 40 used in VFIO_GET_REGION_ADDR() is a private
>     value
>     >     >     >     (VFIO_PCI_OFFSET_SHIFT) defined in Linux kernel source
>     [1]. It
>     >     >     >     is not part of VFIO API, and we should not depend on it.
>     >     >     >
>     >     >     >     [1] https://github.com/torvalds/linux/blob/6fbc7275c7a9/
>     drivers
>     >     /vfio/
>     >     >     pci/
>     >     >     >     vfio_pci_private.h#L19
>     >     >     >
>     >     >     >
>     >     >     >
>     >     >     > I did not follow linux kernel changes, is there something
>     that
>     >     would
>     >     >     change
>     >     >     > this offset?
>     >     >     > It looks like a cleanup (did not look into the details yet),
>     do we
>     >     need
>     >     >     this
>     >     >     > now?
>     >     >
>     >     >     In VFIO/mdev [1], the offset can be something different. It
>     depends
>     >     >     on the parent device. It's not just a cleanup. It's a
>     preparation
>     >     >     for the mdev support in DPDK.
>     >     >
>     >     >     [1] https://github.com/torvalds/linux/blob/master/Documentation
>     /
>     >     >     vfio-mediated-device.txt
>     >     >
>     >     >
>     >     >
>     >     > Ok, thanks.
>     >     > So we can wait for mdev to be ready before working on this.
>     >
>     >     What do you mean by "mdev to be ready"? RFC ready? I don't see
>     >     anything blocking the discussion on this now.
>     >
>     >     PS. I already sent a RFC series of the mdev support in DPDK
>     >         to the mailing list 3 month ago.
>     >
>     >
>     > If you need it and the mdev support has been posted already, why not send
>     a n+1
>     > patchset with this patch in it?
>     >
>     > This patch alone looked odd to me.
> 
>     That series was using the old API which assumes the shift
>     is 40 which may not work in some cases. And this patch is
>     to fix the API. I think this patch is actually trying to
>     fix a relatively independent issue -- i.e. switching to using
>     the proper VFIO API to get the region offsets instead of
>     depending on kernel code's internal value.
> 
> 
> 
> Fix, then there is something broken ?

I should use "fix" (with "") actually :)

> You said this is for mdev support which is not currently part of the features
> supported by DPDK.
> 
> 
> This patch breaks the ABI by extending rte_pci_device.
> You must rework it to avoid this break.

I didn't expect it to be merged in this release. I just want
to draw other's attention on this and kick off the discussion
(it would be great if you would like to share your thoughts
on this). If there is a way to avoid extending rte_pci_device,
it would be definitely great. But if we have to break it, then
we would want to send out the announce as early as possible.

Thanks,
Tiwei

> 
> 
> --
> David Marchand

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC PATCH] bus/pci: avoid depending on private value in kernel source
  @ 2019-07-03  8:26  3%             ` David Marchand
  2019-07-03  8:59  0%               ` Tiwei Bie
  0 siblings, 1 reply; 200+ results
From: David Marchand @ 2019-07-03  8:26 UTC (permalink / raw)
  To: Tiwei Bie; +Cc: dev, Burakov, Anatoly

On Wed, Jul 3, 2019 at 10:17 AM Tiwei Bie <tiwei.bie@intel.com> wrote:

> On Wed, Jul 03, 2019 at 10:01:44AM +0200, David Marchand wrote:
> > On Wed, Jul 3, 2019 at 9:58 AM Tiwei Bie <tiwei.bie@intel.com> wrote:
> >
> >     On Wed, Jul 03, 2019 at 09:36:26AM +0200, David Marchand wrote:
> >     > On Wed, Jul 3, 2019 at 9:35 AM Tiwei Bie <tiwei.bie@intel.com>
> wrote:
> >     >
> >     >     Hi David,
> >     >
> >     >     On Wed, Jul 03, 2019 at 09:02:59AM +0200, David Marchand wrote:
> >     >     > Hello,
> >     >     >
> >     >     > On Wed, Jul 3, 2019 at 7:47 AM Tiwei Bie <
> tiwei.bie@intel.com>
> >     wrote:
> >     >     >
> >     >     >     The value 40 used in VFIO_GET_REGION_ADDR() is a private
> value
> >     >     >     (VFIO_PCI_OFFSET_SHIFT) defined in Linux kernel source
> [1]. It
> >     >     >     is not part of VFIO API, and we should not depend on it.
> >     >     >
> >     >     >     [1]
> https://github.com/torvalds/linux/blob/6fbc7275c7a9/drivers
> >     /vfio/
> >     >     pci/
> >     >     >     vfio_pci_private.h#L19
> >     >     >
> >     >     >
> >     >     >
> >     >     > I did not follow linux kernel changes, is there something
> that
> >     would
> >     >     change
> >     >     > this offset?
> >     >     > It looks like a cleanup (did not look into the details yet),
> do we
> >     need
> >     >     this
> >     >     > now?
> >     >
> >     >     In VFIO/mdev [1], the offset can be something different. It
> depends
> >     >     on the parent device. It's not just a cleanup. It's a
> preparation
> >     >     for the mdev support in DPDK.
> >     >
> >     >     [1]
> https://github.com/torvalds/linux/blob/master/Documentation/
> >     >     vfio-mediated-device.txt
> >     >
> >     >
> >     >
> >     > Ok, thanks.
> >     > So we can wait for mdev to be ready before working on this.
> >
> >     What do you mean by "mdev to be ready"? RFC ready? I don't see
> >     anything blocking the discussion on this now.
> >
> >     PS. I already sent a RFC series of the mdev support in DPDK
> >         to the mailing list 3 month ago.
> >
> >
> > If you need it and the mdev support has been posted already, why not
> send a n+1
> > patchset with this patch in it?
> >
> > This patch alone looked odd to me.
>
> That series was using the old API which assumes the shift
> is 40 which may not work in some cases. And this patch is
> to fix the API. I think this patch is actually trying to
> fix a relatively independent issue -- i.e. switching to using
> the proper VFIO API to get the region offsets instead of
> depending on kernel code's internal value.
>
>
Fix, then there is something broken ?
You said this is for mdev support which is not currently part of the
features supported by DPDK.


This patch breaks the ABI by extending rte_pci_device.
You must rework it to avoid this break.


-- 
David Marchand

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v2 4/5] examples/vdpa: support building from pkg-config info
  2019-07-02  7:57  3%     ` Thomas Monjalon
@ 2019-07-02 14:35  0%       ` Bruce Richardson
  0 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2019-07-02 14:35 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev, bluca

On Tue, Jul 02, 2019 at 09:57:48AM +0200, Thomas Monjalon wrote:
> 17/05/2019 13:47, Bruce Richardson:
> > The vdpa example app did not check for a libdpdk pkg-config file and
> > attempt to build using that. Add support for that method of compile to
> > align the app with the other examples.
> 
> I see an issue with the experimental tag:
> 
> clang -Wp,-MD,./.main.o.d.tmp  -m64 -pthread -fPIC -Ilib/librte_eal/linux/eal/include  -march=native -DRTE_MACHINE_CPUFLAG_SSE -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3 -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1 -DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES -DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX -DRTE_MACHINE_CPUFLAG_RDRAND -DRTE_MACHINE_CPUFLAG_RDSEED -DRTE_MACHINE_CPUFLAG_FSGSBASE -DRTE_MACHINE_CPUFLAG_F16C -DRTE_MACHINE_CPUFLAG_AVX2  -Ix86_64-native-linux-clang+shared+next+debug+ASSERT/examples/vdpa/x86_64-native-linux-clang+shared+next+debug+ASSERT/include -Ix86_64-native-linux-clang+shared+next+debug+ASSERT/include -include x86_64-native-linux-clang+shared+next+debug+ASSERT/include/rte_config.h -D_GNU_SOURCE -O2 -D_FILE_OFFSET_BITS=64 -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wold-style-definition -Wpointer-arith -Wnested-externs -Wcast-qual -Wformat-nonliteral -Wformat-security -Wundef -Wwrite-strings -Wdeprecated -Werror -Wno-missing-field-initializers -Wno-address-of-packed-member -D_GNU_SOURCE    -o main.o -c examples/vdpa/main.c 
> examples/vdpa/main.c:172:8: error: 'rte_vhost_driver_attach_vdpa_device' is deprecated: Symbol is not yet part of stable ABI [-Werror,-Wdeprecated-declarations]
> 
> It seems "CFLAGS += -DALLOW_EXPERIMENTAL_API"
> is reset by the call to pkg-config.
>

No, it's not, it's reset by the call to the DPDK make build system in
the other leg of the code. I'll fix this in the Makefile in v3.
 
> > +build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
> 
> Better to use the real directory name as prerequisite,
> instead of "build".
> 
Not sure what you mean here, build is the name of the directory. [This is
also consistent with what is done in all the other example makefiles. If it
needs updating, then it should be done as a general patch to all examples
in 19.11 release timeframe.]

/Bruce

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [EXT] Re: [PATCH 00/39] adding eventmode helper library
  2019-07-02 14:17  0%         ` Anoob Joseph
@ 2019-07-02 14:26  0%           ` Jerin Jacob Kollanukkaran
  0 siblings, 0 replies; 200+ results
From: Jerin Jacob Kollanukkaran @ 2019-07-02 14:26 UTC (permalink / raw)
  To: Anoob Joseph, Thomas Monjalon
  Cc: dev, Mattias Rönnblom, Nikhil Rao, Erik Gabriel Carrillo,
	Abhinandan Gujjar, Bruce Richardson, Pablo de Lara,
	Narayana Prasad Raju Athreya, Lukas Bartosik,
	Pavan Nikhilesh Bhagavatula, Hemant Agrawal, Nipun Gupta,
	Harry van Haaren, Liang Ma, techboard

> -----Original Message-----
> From: Anoob Joseph
> Sent: Tuesday, July 2, 2019 7:47 PM
> To: Thomas Monjalon <thomas@monjalon.net>; Jerin Jacob Kollanukkaran
> <jerinj@marvell.com>
> Cc: dev@dpdk.org; Mattias Rönnblom <mattias.ronnblom@ericsson.com>;
> Nikhil Rao <nikhil.rao@intel.com>; Erik Gabriel Carrillo
> <erik.g.carrillo@intel.com>; Abhinandan Gujjar <abhinandan.gujjar@intel.com>;
> Bruce Richardson <bruce.richardson@intel.com>; Pablo de Lara
> <pablo.de.lara.guarch@intel.com>; Narayana Prasad Raju Athreya
> <pathreya@marvell.com>; Lukas Bartosik <lbartosik@marvell.com>; Pavan
> Nikhilesh Bhagavatula <pbhagavatula@marvell.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>; Nipun Gupta <nipun.gupta@nxp.com>; Harry van
> Haaren <harry.van.haaren@intel.com>; Liang Ma <liang.j.ma@intel.com>;
> techboard@dpdk.org
> Subject: RE: [dpdk-dev] [EXT] Re: [PATCH 00/39] adding eventmode helper
> library
> 
> Hi Thomas, Jerin,
> 
> Is there any consensus on how we should proceed? Can this be taken up by
> techboard?

For me it make sense to  move these helper functions to examples/.. and make it as standalone(not as library)
Suggested directory(In the order of my preference). No strong preference on the directory name though
1) examples/helper  or
2) examples/common or
3) examples/utils

Thomas? Bruce?


> 
> Thanks,
> Anoob
> 
> > -----Original Message-----
> > From: dev <dev-bounces@dpdk.org> On Behalf Of Anoob Joseph
> > Sent: Friday, June 28, 2019 5:04 PM
> > To: Thomas Monjalon <thomas@monjalon.net>; Jerin Jacob Kollanukkaran
> > <jerinj@marvell.com>
> > Cc: dev@dpdk.org; Mattias Rönnblom <mattias.ronnblom@ericsson.com>;
> > Nikhil Rao <nikhil.rao@intel.com>; Erik Gabriel Carrillo
> > <erik.g.carrillo@intel.com>; Abhinandan Gujjar
> > <abhinandan.gujjar@intel.com>; Bruce Richardson
> > <bruce.richardson@intel.com>; Pablo de Lara
> > <pablo.de.lara.guarch@intel.com>; Narayana Prasad Raju Athreya
> > <pathreya@marvell.com>; Lukas Bartosik <lbartosik@marvell.com>; Pavan
> > Nikhilesh Bhagavatula <pbhagavatula@marvell.com>; Hemant Agrawal
> > <hemant.agrawal@nxp.com>; Nipun Gupta <nipun.gupta@nxp.com>; Harry
> van
> > Haaren <harry.van.haaren@intel.com>; Liang Ma <liang.j.ma@intel.com>;
> > techboard@dpdk.org
> > Subject: Re: [dpdk-dev] [EXT] Re: [PATCH 00/39] adding eventmode
> > helper library
> >
> > Hi Thomas, Jerin,
> >
> > > -----Original Message-----
> > > From: dev <dev-bounces@dpdk.org> On Behalf Of Thomas Monjalon
> > > Sent: Friday, June 28, 2019 2:10 PM
> > > To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Anoob Joseph
> > > <anoobj@marvell.com>
> > > Cc: dev@dpdk.org; Mattias Rönnblom <mattias.ronnblom@ericsson.com>;
> > > Nikhil Rao <nikhil.rao@intel.com>; Erik Gabriel Carrillo
> > > <erik.g.carrillo@intel.com>; Abhinandan Gujjar
> > > <abhinandan.gujjar@intel.com>; Bruce Richardson
> > > <bruce.richardson@intel.com>; Pablo de Lara
> > > <pablo.de.lara.guarch@intel.com>; Narayana Prasad Raju Athreya
> > > <pathreya@marvell.com>; Lukas Bartosik <lbartosik@marvell.com>;
> > > Pavan Nikhilesh Bhagavatula <pbhagavatula@marvell.com>; Hemant
> > > Agrawal <hemant.agrawal@nxp.com>; Nipun Gupta
> <nipun.gupta@nxp.com>;
> > > Harry
> > van
> > > Haaren <harry.van.haaren@intel.com>; Liang Ma
> > > <liang.j.ma@intel.com>; techboard@dpdk.org
> > > Subject: [EXT] Re: [dpdk-dev] [PATCH 00/39] adding eventmode helper
> > > library
> > >
> > > External Email
> > >
> > > --------------------------------------------------------------------
> > > --
> > > 28/06/2019 05:37, Jerin Jacob Kollanukkaran:
> > > > From: Anoob Joseph
> > > > > From: Jerin Jacob Kollanukkaran
> > > > > > From: Anoob Joseph
> > > > > > > The helper library will be experimental while we add
> > > > > > > event-mode support for other applications like l3fwd &
> > > > > > > ipsec-secgw. I expect the helper library to be complete over
> > > > > > > the course of those applications also using the helper library.
> > >
> > > You are doing a copy of l2fwd example to add event mode.
> > > It was the decision from the techboard to not complicate the original l2fwd.
> > > But it makes me nervous to see some code duplicated, especially if
> > > you plan to do the same for l3fwd and ipsec-secgw.
> > > We are not going to duplicate every examples. We should re-consider.
> > >
> >
> > [Anoob] For l3fwd & ipsec-secgw, the plan is to add eventmode in the
> > original application itself. If you have concerns about code
> > duplication in l2fwd-event, the changes can be added to l2fwd itself. Please
> advise on how to proceed.
> >
> > > > > > I have only concern about moving this as library inside
> > > > > > eventdev that till we have mature version of helper library
> > > > > > the eventdev library ABI will not stable(i.e .so file version
> > > > > > needs to be incremented as when a change needed). Which align
> > > > > > with Mattias thoughts for some other reason:. How about moving
> > > > > > this code to
> > > > > > 1) example/common or
> > > > > > 2) to specific application itself, once at least two
> > > > > > applications starts using it then move to Eventdev library.
> > > > > >
> > > > > > Thoughts?
> > > > >
> > > > > [Anoob] Either location is not a problem if there is a consensus.
> > > > > Earlier the suggestion was to move it to library (when the patch
> > > > > was submitted with changes added in app).
> > >
> > > If there is only one user, making it grow in the application looks
> > > to be the best thing to do.
> > > Should we use it in more applications before it is more mature?
> > > If not, we could move the code in eventdev library when we will use
> > > it in more examples.
> > >
> >
> > [Anoob] The proposal with l2fwd-event was to present an easy enough
> > example so that the APIs can be decided before moving onto complex
> examples.
> > Additions to l3fwd & ipsec-secgw is in the pipeline.
> >
> > > > If there NO objections then lets move to example/common.
> > >
> > > If we really want to have this library standalone in examples, I
> > > suggest to give it a name and not use a "common" directory.
> > >
> >
> > [Anoob] I would suggest to add the eventmode code in 'examples/utils'.
> >
> > What is being added here can be treated as a utility library. Almost
> > all examples have duplicated code for the entire conf parsing, ethdev
> > init etc. Anyone who would attempt a new application will have to
> > duplicate lot of code. So a similar exercise with regular poll mode is also
> possible.
> >
> > As for build, we will have the following options,
> >
> > 1. From the examples/<example>/Makefile, build *helper*.o files (
> > '../utils/eventmode_helper.o') and prepare the binary. So each
> > application will build its own version of *helper*.c
> >     +SRCS-y += ../utils/eventmode_helper.c
> >
> > 2. Make 'examples/utils' a separate library. This way, all
> > applications can directly link without having to build separately.
> >
> > Please do suggest on which would be a good way to execute.
> >
> > Thanks,
> > Anoob

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [EXT] Re: [PATCH 00/39] adding eventmode helper library
  2019-06-28 11:34  0%       ` [dpdk-dev] [EXT] " Anoob Joseph
@ 2019-07-02 14:17  0%         ` Anoob Joseph
  2019-07-02 14:26  0%           ` Jerin Jacob Kollanukkaran
  0 siblings, 1 reply; 200+ results
From: Anoob Joseph @ 2019-07-02 14:17 UTC (permalink / raw)
  To: Thomas Monjalon, Jerin Jacob Kollanukkaran
  Cc: dev, Mattias Rönnblom, Nikhil Rao, Erik Gabriel Carrillo,
	Abhinandan Gujjar, Bruce Richardson, Pablo de Lara,
	Narayana Prasad Raju Athreya, Lukas Bartosik,
	Pavan Nikhilesh Bhagavatula, Hemant Agrawal, Nipun Gupta,
	Harry van Haaren, Liang Ma, techboard

Hi Thomas, Jerin,

Is there any consensus on how we should proceed? Can this be taken up by techboard?

Thanks,
Anoob

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Anoob Joseph
> Sent: Friday, June 28, 2019 5:04 PM
> To: Thomas Monjalon <thomas@monjalon.net>; Jerin Jacob Kollanukkaran
> <jerinj@marvell.com>
> Cc: dev@dpdk.org; Mattias Rönnblom <mattias.ronnblom@ericsson.com>;
> Nikhil Rao <nikhil.rao@intel.com>; Erik Gabriel Carrillo
> <erik.g.carrillo@intel.com>; Abhinandan Gujjar <abhinandan.gujjar@intel.com>;
> Bruce Richardson <bruce.richardson@intel.com>; Pablo de Lara
> <pablo.de.lara.guarch@intel.com>; Narayana Prasad Raju Athreya
> <pathreya@marvell.com>; Lukas Bartosik <lbartosik@marvell.com>; Pavan
> Nikhilesh Bhagavatula <pbhagavatula@marvell.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>; Nipun Gupta <nipun.gupta@nxp.com>; Harry van
> Haaren <harry.van.haaren@intel.com>; Liang Ma <liang.j.ma@intel.com>;
> techboard@dpdk.org
> Subject: Re: [dpdk-dev] [EXT] Re: [PATCH 00/39] adding eventmode helper
> library
> 
> Hi Thomas, Jerin,
> 
> > -----Original Message-----
> > From: dev <dev-bounces@dpdk.org> On Behalf Of Thomas Monjalon
> > Sent: Friday, June 28, 2019 2:10 PM
> > To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Anoob Joseph
> > <anoobj@marvell.com>
> > Cc: dev@dpdk.org; Mattias Rönnblom <mattias.ronnblom@ericsson.com>;
> > Nikhil Rao <nikhil.rao@intel.com>; Erik Gabriel Carrillo
> > <erik.g.carrillo@intel.com>; Abhinandan Gujjar
> > <abhinandan.gujjar@intel.com>; Bruce Richardson
> > <bruce.richardson@intel.com>; Pablo de Lara
> > <pablo.de.lara.guarch@intel.com>; Narayana Prasad Raju Athreya
> > <pathreya@marvell.com>; Lukas Bartosik <lbartosik@marvell.com>; Pavan
> > Nikhilesh Bhagavatula <pbhagavatula@marvell.com>; Hemant Agrawal
> > <hemant.agrawal@nxp.com>; Nipun Gupta <nipun.gupta@nxp.com>; Harry
> van
> > Haaren <harry.van.haaren@intel.com>; Liang Ma <liang.j.ma@intel.com>;
> > techboard@dpdk.org
> > Subject: [EXT] Re: [dpdk-dev] [PATCH 00/39] adding eventmode helper
> > library
> >
> > External Email
> >
> > ----------------------------------------------------------------------
> > 28/06/2019 05:37, Jerin Jacob Kollanukkaran:
> > > From: Anoob Joseph
> > > > From: Jerin Jacob Kollanukkaran
> > > > > From: Anoob Joseph
> > > > > > The helper library will be experimental while we add
> > > > > > event-mode support for other applications like l3fwd &
> > > > > > ipsec-secgw. I expect the helper library to be complete over
> > > > > > the course of those applications also using the helper library.
> >
> > You are doing a copy of l2fwd example to add event mode.
> > It was the decision from the techboard to not complicate the original l2fwd.
> > But it makes me nervous to see some code duplicated, especially if you
> > plan to do the same for l3fwd and ipsec-secgw.
> > We are not going to duplicate every examples. We should re-consider.
> >
> 
> [Anoob] For l3fwd & ipsec-secgw, the plan is to add eventmode in the original
> application itself. If you have concerns about code duplication in l2fwd-event,
> the changes can be added to l2fwd itself. Please advise on how to proceed.
> 
> > > > > I have only concern about moving this as library inside eventdev
> > > > > that till we have mature version of helper library the eventdev
> > > > > library ABI will not stable(i.e .so file version needs to be
> > > > > incremented as when a change needed). Which align with Mattias
> > > > > thoughts for some other reason:. How about moving this code to
> > > > > 1) example/common or
> > > > > 2) to specific application itself, once at least two
> > > > > applications starts using it then move to Eventdev library.
> > > > >
> > > > > Thoughts?
> > > >
> > > > [Anoob] Either location is not a problem if there is a consensus.
> > > > Earlier the suggestion was to move it to library (when the patch
> > > > was submitted with changes added in app).
> >
> > If there is only one user, making it grow in the application looks to
> > be the best thing to do.
> > Should we use it in more applications before it is more mature?
> > If not, we could move the code in eventdev library when we will use it
> > in more examples.
> >
> 
> [Anoob] The proposal with l2fwd-event was to present an easy enough example
> so that the APIs can be decided before moving onto complex examples.
> Additions to l3fwd & ipsec-secgw is in the pipeline.
> 
> > > If there NO objections then lets move to example/common.
> >
> > If we really want to have this library standalone in examples, I
> > suggest to give it a name and not use a "common" directory.
> >
> 
> [Anoob] I would suggest to add the eventmode code in 'examples/utils'.
> 
> What is being added here can be treated as a utility library. Almost all examples
> have duplicated code for the entire conf parsing, ethdev init etc. Anyone who
> would attempt a new application will have to duplicate lot of code. So a similar
> exercise with regular poll mode is also possible.
> 
> As for build, we will have the following options,
> 
> 1. From the examples/<example>/Makefile, build *helper*.o files (
> '../utils/eventmode_helper.o') and prepare the binary. So each application will
> build its own version of *helper*.c
>     +SRCS-y += ../utils/eventmode_helper.c
> 
> 2. Make 'examples/utils' a separate library. This way, all applications can directly
> link without having to build separately.
> 
> Please do suggest on which would be a good way to execute.
> 
> Thanks,
> Anoob

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2 4/5] examples/vdpa: support building from pkg-config info
  @ 2019-07-02  7:57  3%     ` Thomas Monjalon
  2019-07-02 14:35  0%       ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2019-07-02  7:57 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev, bluca

17/05/2019 13:47, Bruce Richardson:
> The vdpa example app did not check for a libdpdk pkg-config file and
> attempt to build using that. Add support for that method of compile to
> align the app with the other examples.

I see an issue with the experimental tag:

clang -Wp,-MD,./.main.o.d.tmp  -m64 -pthread -fPIC -Ilib/librte_eal/linux/eal/include  -march=native -DRTE_MACHINE_CPUFLAG_SSE -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3 -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1 -DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES -DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX -DRTE_MACHINE_CPUFLAG_RDRAND -DRTE_MACHINE_CPUFLAG_RDSEED -DRTE_MACHINE_CPUFLAG_FSGSBASE -DRTE_MACHINE_CPUFLAG_F16C -DRTE_MACHINE_CPUFLAG_AVX2  -Ix86_64-native-linux-clang+shared+next+debug+ASSERT/examples/vdpa/x86_64-native-linux-clang+shared+next+debug+ASSERT/include -Ix86_64-native-linux-clang+shared+next+debug+ASSERT/include -include x86_64-native-linux-clang+shared+next+debug+ASSERT/include/rte_config.h -D_GNU_SOURCE -O2 -D_FILE_OFFSET_BITS=64 -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wold-style-definition -Wpointer-arith -Wnested-externs -Wcast-qual -Wformat-nonliteral -Wformat-security -Wundef -Wwrite-strings -Wdeprecated -Werror -Wno-missing-field-initializers -Wno-address-of-packed-member -D_GNU_SOURCE    -o main.o -c examples/vdpa/main.c 
examples/vdpa/main.c:172:8: error: 'rte_vhost_driver_attach_vdpa_device' is deprecated: Symbol is not yet part of stable ABI [-Werror,-Wdeprecated-declarations]

It seems "CFLAGS += -DALLOW_EXPERIMENTAL_API"
is reset by the call to pkg-config.

> +build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build

Better to use the real directory name as prerequisite,
instead of "build".




^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v3] eventdev: change Rx adapter callback and stats structure
@ 2019-07-02  4:52  0% Jerin Jacob Kollanukkaran
  0 siblings, 0 replies; 200+ results
From: Jerin Jacob Kollanukkaran @ 2019-07-02  4:52 UTC (permalink / raw)
  To: Nikhil Rao; +Cc: dev



> -----Original Message-----
> From: Nikhil Rao <nikhil.rao@intel.com>
> Sent: Tuesday, June 25, 2019 4:46 AM
> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> Cc: nikhil.rao@intel.com; dev@dpdk.org
> Subject: [EXT] [PATCH v3] eventdev: change Rx adapter callback and stats
> structure
> 
> External Email
> 
> ----------------------------------------------------------------------
> Replace the mbuf pointer array in the event eth Rx adapter callback with an
> event array. Using an event array allows the application to change attributes
> of the events enqueued by the SW adapter.
> 
> The callback can drop packets and populate a callback argument with the
> number of dropped packets. Add a Rx adapter stats field to keep track of the
> total number of dropped packets.
> 
> This commit removes the experimental tags from the callback and stats APIs,
> the experimental tag from eventdev is also removed and eventdev functions
> become part of the main DPDK API/ABI.
> 
> Signed-off-by: Nikhil Rao <nikhil.rao@intel.com>
> ---
>  lib/librte_eventdev/rte_event_eth_rx_adapter.h | 82 +++++++++++++-----
> --------  lib/librte_eventdev/rte_event_eth_rx_adapter.c | 34 ++++++-----
>  MAINTAINERS                                    |  2 +-
>  doc/guides/rel_notes/release_19_08.rst         | 20 ++++++-
>  lib/librte_eventdev/Makefile                   |  2 +-
>  lib/librte_eventdev/meson.build                |  2 +-
>  lib/librte_eventdev/rte_eventdev_version.map   |  4 +-
>  7 files changed, 83 insertions(+), 63 deletions(-)
> 
> v1:
> * add implementation to RFC
> 
> v2:
> * Bump library version
> * Combine patch 1 & 2 into a single patch (single library version bump)
> * Mention API change in release notes
> * Remove __rte_experimental tag
> * Remove EXPERIMENTAL status for eventdev
> 
> v3:
> * Update version = 7 in lib/librte_eventdev/meson.build
> * Update the "git comment and release notes" to mention the removal of
>   experimental status
> * Reduce rte_event_eth_rx_adapter.c line count

Acked-by: Jerin Jacob <jerinj@marvell.com>

Applied to dpdk-next-eventdev/master. Thanks.


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 10/10] doc: announce bbdev changes
  2019-07-01 20:27  4%           ` Chautru, Nicolas
@ 2019-07-01 20:38  3%             ` Bruce Richardson
  0 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2019-07-01 20:38 UTC (permalink / raw)
  To: Chautru, Nicolas
  Cc: Thomas Monjalon, Akhil Goyal, dev, Yigit, Ferruh, Mokhtar, Amr

On Mon, Jul 01, 2019 at 09:27:56PM +0100, Chautru, Nicolas wrote:
> 
> >-----Original Message-----
> >From: Thomas Monjalon [mailto:thomas@monjalon.net] 
> >Sent: Monday, July 1, 2019 12:18 PM
> >To: Chautru, Nicolas <nicolas.chautru@intel.com>
> >Cc: Akhil Goyal <akhil.goyal@nxp.com>; dev@dpdk.org; Yigit, Ferruh <ferruh.yigit@intel.com>; Mokhtar, Amr <amr.mokhtar@intel.com>
> >Subject: Re: [PATCH v4 10/10] doc: announce bbdev changes
> >
> >01/07/2019 20:14, Chautru, Nicolas:
> >> 
> >> >One more thing, if there is a change in ABI, should you also increment the bbdev ABI version?
> >> 
> >> The bbdev ABI is still marked as __rte_experimental hence I don't believe we have yet to increment it.
> >
> >ABI version and experimental state are two different things.
> >I think we should upgrade the version even for experimental libraries.
> 
> Thanks Thomas. 
> 
> Bruce, Ferruh can you comment whether bumping ABI version is required for __rte_experimental API? Arguably the documentation may be interpreted either way : https://doc.dpdk.org/guides-18.08/contributing/versioning.html 
> 
> In the specific case of bbdev change in that serie, note that only new operations (for 5GNR signal processing) and related symbols are being added. 
> Previous releases included BBDEV API changes without updating ABI version number ( librte_bbdev.so.1). 
> 
> Thanks for letting me know, in both cases we may make it more explicit on the versioning page. 
> Nic

I think there may be some misunderstanding here, so long as no existing
APIs are changed or removed, we don't bump the ABI version.

/Bruce

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v4 10/10] doc: announce bbdev changes
  2019-07-01 19:17  3%         ` Thomas Monjalon
@ 2019-07-01 20:27  4%           ` Chautru, Nicolas
  2019-07-01 20:38  3%             ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Chautru, Nicolas @ 2019-07-01 20:27 UTC (permalink / raw)
  To: Thomas Monjalon, Richardson, Bruce
  Cc: Akhil Goyal, dev, Yigit,  Ferruh, Mokhtar, Amr


>-----Original Message-----
>From: Thomas Monjalon [mailto:thomas@monjalon.net] 
>Sent: Monday, July 1, 2019 12:18 PM
>To: Chautru, Nicolas <nicolas.chautru@intel.com>
>Cc: Akhil Goyal <akhil.goyal@nxp.com>; dev@dpdk.org; Yigit, Ferruh <ferruh.yigit@intel.com>; Mokhtar, Amr <amr.mokhtar@intel.com>
>Subject: Re: [PATCH v4 10/10] doc: announce bbdev changes
>
>01/07/2019 20:14, Chautru, Nicolas:
>> 
>> >One more thing, if there is a change in ABI, should you also increment the bbdev ABI version?
>> 
>> The bbdev ABI is still marked as __rte_experimental hence I don't believe we have yet to increment it.
>
>ABI version and experimental state are two different things.
>I think we should upgrade the version even for experimental libraries.

Thanks Thomas. 

Bruce, Ferruh can you comment whether bumping ABI version is required for __rte_experimental API? Arguably the documentation may be interpreted either way : https://doc.dpdk.org/guides-18.08/contributing/versioning.html 

In the specific case of bbdev change in that serie, note that only new operations (for 5GNR signal processing) and related symbols are being added. 
Previous releases included BBDEV API changes without updating ABI version number ( librte_bbdev.so.1). 

Thanks for letting me know, in both cases we may make it more explicit on the versioning page. 
Nic


^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v4 10/10] doc: announce bbdev changes
  2019-07-01 18:14  3%       ` Chautru, Nicolas
@ 2019-07-01 19:17  3%         ` Thomas Monjalon
  2019-07-01 20:27  4%           ` Chautru, Nicolas
  0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2019-07-01 19:17 UTC (permalink / raw)
  To: Chautru, Nicolas; +Cc: Akhil Goyal, dev, Yigit, Ferruh, Mokhtar, Amr

01/07/2019 20:14, Chautru, Nicolas:
> 
> >One more thing, if there is a change in ABI, should you also increment the bbdev ABI version?
> 
> The bbdev ABI is still marked as __rte_experimental hence I don't believe we have yet to increment it.

ABI version and experimental state are two different things.
I think we should upgrade the version even for experimental libraries.




^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v4 10/10] doc: announce bbdev changes
  2019-07-01 11:14  4%     ` Akhil Goyal
@ 2019-07-01 18:14  3%       ` Chautru, Nicolas
  2019-07-01 19:17  3%         ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Chautru, Nicolas @ 2019-07-01 18:14 UTC (permalink / raw)
  To: Akhil Goyal, dev; +Cc: thomas, Yigit, Ferruh, Mokhtar, Amr

Hi Akhil,

>> 
>> Update of the release notes for BBDEV features add and extension of 
>> ABI in previous commit.
>> 
>> Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
>> ---
>>  doc/guides/rel_notes/release_19_08.rst | 15 +++++++++++++++
>>  1 file changed, 15 insertions(+)
>> 
>> diff --git a/doc/guides/rel_notes/release_19_08.rst
>> b/doc/guides/rel_notes/release_19_08.rst
>> index 8c3932d..35d3a09 100644
>> --- a/doc/guides/rel_notes/release_19_08.rst
>> +++ b/doc/guides/rel_notes/release_19_08.rst
>> @@ -88,6 +88,19 @@ New Features
>>    * Added multi-queue support to allow one af_xdp vdev with multiple netdev
>>      queues
>> 
>> +* **Added a FPGA_LTE_FEC bbdev PMD.**
>> +
>> +  Added the new ``fpga_lte_fec`` bbdev driver for the Intel® FPGA 
>> + PAC  (Programmable  Acceleration Card) N3000.  See the  
>> + :doc:`../bbdevs/fpga_lte_fec` BBDEV guide for more details on this new driver.
>> +
>> +* **Updated TURBO_SW bbdev PMD.**
>> +
>> +  Updated the ``turbo_sw`` bbdev driver with changes including:
>> +
>> +  * Added option to build the driver with or without dependency of external
>> +    SDK libraries.
>> +  * Added support for 5GNR encode/decode operations.
>> 
>>  Removed Items
>>  -------------
>> @@ -140,6 +153,8 @@ ABI Changes
>>     Also, make sure to start the actual text at the margin.
>>     =========================================================
>> 
>> +* bbdev: New parameters added to support 5GNR operations.
>> +
>> 
>>  Shared Library Versions
>>  -----------------------
>> --
>> 1.8.3.1
>
>Release note changes should be part of the same patch which is adding that change.

No problem, I am pushing an updated serie :  https://patches.dpdk.org/project/dpdk/list/?series=5259

>One more thing, if there is a change in ABI, should you also increment the bbdev ABI version?

The bbdev ABI is still marked as __rte_experimental hence I don't believe we have yet to increment it. 

>Please also send a rebased version of your patchset, so that builds can be verified by CI. The dependent patches are applied on the sub-tree.

OK, I did this on the serie above. Note that the previous was already verified with CI since I kept the dependency within the previous serie. Still cleaner now, you should just have to apply the serie as is now. 

Thanks!
Nic






^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v5 4/7] baseband/turbo_sw: extension of turbosw PMD for 5G
    2019-07-01 18:06  3%   ` [dpdk-dev] [PATCH v5 2/7] bbdev: extension of BBDEV API for 5G FEC Nicolas Chautru
@ 2019-07-01 18:06  2%   ` Nicolas Chautru
  1 sibling, 0 replies; 200+ results
From: Nicolas Chautru @ 2019-07-01 18:06 UTC (permalink / raw)
  To: akhil.goyal, dev
  Cc: ferruh.yigit, thomas, amr.mokhtar, kamilx.chalupnik, Nicolas Chautru

Implementation still based on Intel SDK libraries
optimized for AVX512 instructions set and 5GNR.
This can be also build for AVX2 for 4G capability or
without SDK dependency for maintenance.

Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
Acked-by: Amr Mokhtar <amr.mokhtar@intel.com>
---
 config/common_base                               |   1 +
 doc/guides/rel_notes/release_19_08.rst           |  15 +-
 drivers/baseband/turbo_sw/Makefile               |  15 +-
 drivers/baseband/turbo_sw/bbdev_turbo_software.c | 677 ++++++++++++++++++++++-
 drivers/baseband/turbo_sw/meson.build            |  10 +
 mk/rte.app.mk                                    |   8 +-
 6 files changed, 715 insertions(+), 11 deletions(-)

diff --git a/config/common_base b/config/common_base
index e5a4ebf..c2551b1 100644
--- a/config/common_base
+++ b/config/common_base
@@ -536,6 +536,7 @@ CONFIG_RTE_LIBRTE_BBDEV_DEBUG=n
 CONFIG_RTE_BBDEV_MAX_DEVS=128
 CONFIG_RTE_BBDEV_OFFLOAD_COST=y
 CONFIG_RTE_BBDEV_SDK_AVX2=n
+CONFIG_RTE_BBDEV_SDK_AVX512=n
 
 #
 # Compile PMD for NULL bbdev device
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 55ae8ee..7c508fc 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -126,6 +126,20 @@ New Features
   Added telemetry mode to l3fwd-power application to report
   application level busyness, empty and full polls of rte_eth_rx_burst().
 
+* **Added a FPGA_LTE_FEC bbdev PMD.**
+
+  Added the new ``fpga_lte_fec`` bbdev driver for the Intel® FPGA PAC
+  (Programmable  Acceleration Card) N3000.  See the
+  :doc:`../bbdevs/fpga_lte_fec` BBDEV guide for more details on this new driver.
+
+* **Updated TURBO_SW bbdev PMD.**
+
+  Updated the ``turbo_sw`` bbdev driver with changes including:
+
+  * Added option to build the driver with or without dependency of external
+    SDK libraries.
+  * Added support for 5GNR encode/decode operations.
+
 Removed Items
 -------------
 
@@ -165,7 +179,6 @@ API Changes
   structure (``rte_crypto_cipher_xform``, ``rte_crypto_auth_xform``, and
   ``rte_crypto_aead_xform``) have been changed to ``const uint8_t *data``.
 
-
 ABI Changes
 -----------
 
diff --git a/drivers/baseband/turbo_sw/Makefile b/drivers/baseband/turbo_sw/Makefile
index 414d0d9..4aa05d2 100644
--- a/drivers/baseband/turbo_sw/Makefile
+++ b/drivers/baseband/turbo_sw/Makefile
@@ -3,7 +3,6 @@
 
 include $(RTE_SDK)/mk/rte.vars.mk
 
-
 # library name
 LIB = librte_pmd_bbdev_turbo_sw.a
 
@@ -34,6 +33,20 @@ LDLIBS += -L$(FLEXRAN_SDK)/lib_common -lcommon
 LDLIBS += -lstdc++ -lirc -limf -lipps -lsvml
 endif
 
+ifeq ($(CONFIG_RTE_BBDEV_SDK_AVX512),y)
+ifeq ($(CONFIG_RTE_BBDEV_SDK_AVX2),n)
+$(error "CONFIG_RTE_BBDEV_SDK_AVX512 requires CONFIG_RTE_BBDEV_SDK_AVX2 set")
+endif
+CFLAGS += -I$(FLEXRAN_SDK)/lib_ldpc_encoder_5gnr
+CFLAGS += -I$(FLEXRAN_SDK)/lib_ldpc_decoder_5gnr
+CFLAGS += -I$(FLEXRAN_SDK)/lib_LDPC_ratematch_5gnr
+CFLAGS += -I$(FLEXRAN_SDK)/lib_rate_dematching_5gnr
+LDLIBS += -L$(FLEXRAN_SDK)/lib_ldpc_encoder_5gnr -lldpc_encoder_5gnr
+LDLIBS += -L$(FLEXRAN_SDK)/lib_ldpc_decoder_5gnr -lldpc_decoder_5gnr
+LDLIBS += -L$(FLEXRAN_SDK)/lib_LDPC_ratematch_5gnr -lLDPC_ratematch_5gnr
+LDLIBS += -L$(FLEXRAN_SDK)/lib_rate_dematching_5gnr -lrate_dematching_5gnr
+endif
+
 # library version
 LIBABIVER := 1
 
diff --git a/drivers/baseband/turbo_sw/bbdev_turbo_software.c b/drivers/baseband/turbo_sw/bbdev_turbo_software.c
index 5551f84..2f06369 100644
--- a/drivers/baseband/turbo_sw/bbdev_turbo_software.c
+++ b/drivers/baseband/turbo_sw/bbdev_turbo_software.c
@@ -14,11 +14,24 @@
 #include <rte_bbdev.h>
 #include <rte_bbdev_pmd.h>
 
+#include <rte_common.h>
+#include <rte_hexdump.h>
+#include <rte_log.h>
+
 #ifdef RTE_BBDEV_SDK_AVX2
+#include <ipp.h>
+#include <ipps.h>
 #include <phy_turbo.h>
 #include <phy_crc.h>
 #include <phy_rate_match.h>
 #endif
+#ifdef RTE_BBDEV_SDK_AVX512
+#include <bit_reverse.h>
+#include <phy_ldpc_encoder_5gnr.h>
+#include <phy_ldpc_decoder_5gnr.h>
+#include <phy_LDPC_ratematch_5gnr.h>
+#include <phy_rate_dematching_5gnr.h>
+#endif
 
 #define DRIVER_NAME baseband_turbo_sw
 
@@ -84,6 +97,7 @@ struct turbo_sw_queue {
 	enum rte_bbdev_op_type type;
 } __rte_cache_aligned;
 
+
 #ifdef RTE_BBDEV_SDK_AVX2
 static inline char *
 mbuf_append(struct rte_mbuf *m_head, struct rte_mbuf *m, uint16_t len)
@@ -180,20 +194,53 @@ struct turbo_sw_queue {
 			}
 		},
 #endif
+#ifdef RTE_BBDEV_SDK_AVX512
+		{
+			.type   = RTE_BBDEV_OP_LDPC_ENC,
+			.cap.ldpc_enc = {
+				.capability_flags =
+						RTE_BBDEV_LDPC_RATE_MATCH |
+						RTE_BBDEV_LDPC_CRC_24A_ATTACH |
+						RTE_BBDEV_LDPC_CRC_24B_ATTACH,
+				.num_buffers_src =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+				.num_buffers_dst =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			}
+		},
+		{
+		.type   = RTE_BBDEV_OP_LDPC_DEC,
+		.cap.ldpc_dec = {
+			.capability_flags =
+					RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK |
+					RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK |
+					RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP |
+					RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE |
+					RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE |
+					RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE,
+			.llr_size = 8,
+			.llr_decimals = 2,
+			.harq_memory_size = 0,
+			.num_buffers_src =
+					RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			.num_buffers_hard_out =
+					RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			.num_buffers_soft_out = 0,
+		}
+		},
+#endif
 		RTE_BBDEV_END_OF_CAPABILITIES_LIST()
 	};
 
 	static struct rte_bbdev_queue_conf default_queue_conf = {
 		.queue_size = RTE_BBDEV_QUEUE_SIZE_LIMIT,
 	};
-
 #ifdef RTE_BBDEV_SDK_AVX2
 	static const enum rte_cpu_flag_t cpu_flag = RTE_CPUFLAG_SSE4_2;
 	dev_info->cpu_flag_reqs = &cpu_flag;
 #else
 	dev_info->cpu_flag_reqs = NULL;
 #endif
-
 	default_queue_conf.socket = dev->data->socket_id;
 
 	dev_info->driver_name = RTE_STR(DRIVER_NAME);
@@ -280,7 +327,7 @@ struct turbo_sw_queue {
 		return -ENAMETOOLONG;
 	}
 	q->enc_in = rte_zmalloc_socket(name,
-			(RTE_BBDEV_TURBO_MAX_CB_SIZE >> 3) * sizeof(*q->enc_in),
+			(RTE_BBDEV_LDPC_MAX_CB_SIZE >> 3) * sizeof(*q->enc_in),
 			RTE_CACHE_LINE_SIZE, queue_conf->socket);
 	if (q->enc_in == NULL) {
 		rte_bbdev_log(ERR,
@@ -288,7 +335,7 @@ struct turbo_sw_queue {
 		goto free_q;
 	}
 
-	/* Allocate memory for Aplha Gamma temp buffer. */
+	/* Allocate memory for Alpha Gamma temp buffer. */
 	ret = snprintf(name, RTE_RING_NAMESIZE, RTE_STR(DRIVER_NAME)"_ag%u:%u",
 			dev->data->dev_id, q_id);
 	if ((ret < 0) || (ret >= (int)RTE_RING_NAMESIZE)) {
@@ -423,6 +470,7 @@ struct turbo_sw_queue {
 };
 
 #ifdef RTE_BBDEV_SDK_AVX2
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
 /* Checks if the encoder input buffer is correct.
  * Returns 0 if it's valid, -1 otherwise.
  */
@@ -478,16 +526,21 @@ struct turbo_sw_queue {
 	return 0;
 }
 #endif
+#endif
 
 static inline void
 process_enc_cb(struct turbo_sw_queue *q, struct rte_bbdev_enc_op *op,
 		uint8_t r, uint8_t c, uint16_t k, uint16_t ncb,
 		uint32_t e, struct rte_mbuf *m_in, struct rte_mbuf *m_out_head,
-		struct rte_mbuf *m_out, uint16_t in_offset, uint16_t out_offset,
+		struct rte_mbuf *m_out,	uint16_t in_offset, uint16_t out_offset,
 		uint16_t in_length, struct rte_bbdev_stats *q_stats)
 {
 #ifdef RTE_BBDEV_SDK_AVX2
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
 	int ret;
+#else
+	RTE_SET_USED(in_length);
+#endif
 	int16_t k_idx;
 	uint16_t m;
 	uint8_t *in, *out0, *out1, *out2, *tmp_out, *rm_out;
@@ -511,11 +564,14 @@ struct turbo_sw_queue {
 	/* CRC24A (for TB) */
 	if ((enc->op_flags & RTE_BBDEV_TURBO_CRC_24A_ATTACH) &&
 		(enc->code_block_mode == 1)) {
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
 		ret = is_enc_input_valid(k - 24, k_idx, in_length);
 		if (ret != 0) {
 			op->status |= 1 << RTE_BBDEV_DATA_ERROR;
 			return;
 		}
+#endif
+
 		crc_req.data = in;
 		crc_req.len = k - 24;
 		/* Check if there is a room for CRC bits if not use
@@ -544,11 +600,14 @@ struct turbo_sw_queue {
 #endif
 	} else if (enc->op_flags & RTE_BBDEV_TURBO_CRC_24B_ATTACH) {
 		/* CRC24B */
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
 		ret = is_enc_input_valid(k - 24, k_idx, in_length);
 		if (ret != 0) {
 			op->status |= 1 << RTE_BBDEV_DATA_ERROR;
 			return;
 		}
+#endif
+
 		crc_req.data = in;
 		crc_req.len = k - 24;
 		/* Check if there is a room for CRC bits if this is the last
@@ -575,13 +634,16 @@ struct turbo_sw_queue {
 #ifdef RTE_BBDEV_OFFLOAD_COST
 		q_stats->acc_offload_cycles += rte_rdtsc_precise() - start_time;
 #endif
-	} else {
+	}
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	else {
 		ret = is_enc_input_valid(k, k_idx, in_length);
 		if (ret != 0) {
 			op->status |= 1 << RTE_BBDEV_DATA_ERROR;
 			return;
 		}
 	}
+#endif
 
 	/* Turbo encoder */
 
@@ -757,6 +819,143 @@ struct turbo_sw_queue {
 #endif
 }
 
+
+static inline void
+process_ldpc_enc_cb(struct turbo_sw_queue *q, struct rte_bbdev_enc_op *op,
+		uint32_t e, struct rte_mbuf *m_in, struct rte_mbuf *m_out_head,
+		struct rte_mbuf *m_out,	uint16_t in_offset, uint16_t out_offset,
+		uint16_t seg_total_left, struct rte_bbdev_stats *q_stats)
+{
+#ifdef RTE_BBDEV_SDK_AVX512
+	RTE_SET_USED(seg_total_left);
+	uint8_t *in, *rm_out;
+	struct rte_bbdev_op_ldpc_enc *enc = &op->ldpc_enc;
+	struct bblib_ldpc_encoder_5gnr_request ldpc_req;
+	struct bblib_ldpc_encoder_5gnr_response ldpc_resp;
+	struct bblib_LDPC_ratematch_5gnr_request rm_req;
+	struct bblib_LDPC_ratematch_5gnr_response rm_resp;
+	struct bblib_crc_request crc_req;
+	struct bblib_crc_response crc_resp;
+	uint16_t msgLen, puntBits, parity_offset, out_len;
+	uint16_t K = (enc->basegraph == 1 ? 22 : 10) * enc->z_c;
+	uint16_t in_length_in_bits = K - enc->n_filler;
+	uint16_t in_length_in_bytes = (in_length_in_bits + 7) >> 3;
+
+#ifdef RTE_BBDEV_OFFLOAD_COST
+	uint64_t start_time = rte_rdtsc_precise();
+#else
+	RTE_SET_USED(q_stats);
+#endif
+
+	in = rte_pktmbuf_mtod_offset(m_in, uint8_t *, in_offset);
+
+	/* Masking the Filler bits explicitly */
+	memset(q->enc_in  + (in_length_in_bytes - 3), 0,
+			((K + 7) >> 3) - (in_length_in_bytes - 3));
+	/* CRC Generation */
+	if (enc->op_flags & RTE_BBDEV_LDPC_CRC_24A_ATTACH) {
+		rte_memcpy(q->enc_in, in, in_length_in_bytes - 3);
+		crc_req.data = in;
+		crc_req.len = in_length_in_bits - 24;
+		crc_resp.data = q->enc_in;
+		bblib_lte_crc24a_gen(&crc_req, &crc_resp);
+	} else if (enc->op_flags & RTE_BBDEV_LDPC_CRC_24B_ATTACH) {
+		rte_memcpy(q->enc_in, in, in_length_in_bytes - 3);
+		crc_req.data = in;
+		crc_req.len = in_length_in_bits - 24;
+		crc_resp.data = q->enc_in;
+		bblib_lte_crc24b_gen(&crc_req, &crc_resp);
+	} else
+		rte_memcpy(q->enc_in, in, in_length_in_bytes);
+
+	/* LDPC Encoding */
+	ldpc_req.Zc = enc->z_c;
+	ldpc_req.baseGraph = enc->basegraph;
+	/* Number of rows set to maximum */
+	ldpc_req.nRows = ldpc_req.baseGraph == 1 ? 46 : 42;
+	ldpc_req.numberCodeblocks = 1;
+	ldpc_req.input[0] = (int8_t *) q->enc_in;
+	ldpc_resp.output[0] = (int8_t *) q->enc_out;
+
+	bblib_bit_reverse(ldpc_req.input[0], in_length_in_bytes << 3);
+
+	if (bblib_ldpc_encoder_5gnr(&ldpc_req, &ldpc_resp) != 0) {
+		op->status |= 1 << RTE_BBDEV_DRV_ERROR;
+		rte_bbdev_log(ERR, "LDPC Encoder failed");
+		return;
+	}
+
+	/*
+	 * Systematic + Parity : Recreating stream with filler bits, ideally
+	 * the bit select could handle this in the RM SDK
+	 */
+	msgLen = (ldpc_req.baseGraph == 1 ? 22 : 10) * ldpc_req.Zc;
+	puntBits = 2 * ldpc_req.Zc;
+	parity_offset = msgLen - puntBits;
+	ippsCopyBE_1u(((uint8_t *) ldpc_req.input[0]) + (puntBits / 8),
+			puntBits%8, q->adapter_output, 0, parity_offset);
+	ippsCopyBE_1u(q->enc_out, 0, q->adapter_output + (parity_offset / 8),
+			parity_offset % 8, ldpc_req.nRows * ldpc_req.Zc);
+
+	out_len = (e + 7) >> 3;
+	/* get output data starting address */
+	rm_out = (uint8_t *)mbuf_append(m_out_head, m_out, out_len);
+	if (rm_out == NULL) {
+		op->status |= 1 << RTE_BBDEV_DATA_ERROR;
+		rte_bbdev_log(ERR,
+				"Too little space in output mbuf");
+		return;
+	}
+	/*
+	 * rte_bbdev_op_data.offset can be different than the offset
+	 * of the appended bytes
+	 */
+	rm_out = rte_pktmbuf_mtod_offset(m_out, uint8_t *, out_offset);
+
+	/* Rate-Matching */
+	rm_req.E = e;
+	rm_req.Ncb = enc->n_cb;
+	rm_req.Qm = enc->q_m;
+	rm_req.Zc = enc->z_c;
+	rm_req.baseGraph = enc->basegraph;
+	rm_req.input = q->adapter_output;
+	rm_req.nLen = enc->n_filler;
+	rm_req.nullIndex = parity_offset - enc->n_filler;
+	rm_req.rvidx = enc->rv_index;
+	rm_resp.output = q->deint_output;
+
+	if (bblib_LDPC_ratematch_5gnr(&rm_req, &rm_resp) != 0) {
+		op->status |= 1 << RTE_BBDEV_DRV_ERROR;
+		rte_bbdev_log(ERR, "Rate matching failed");
+		return;
+	}
+
+	/* RM SDK may provide non zero bits on last byte */
+	if ((e % 8) != 0)
+		q->deint_output[out_len-1] &= (1 << (e % 8)) - 1;
+
+	bblib_bit_reverse((int8_t *) q->deint_output, out_len << 3);
+
+	rte_memcpy(rm_out, q->deint_output, out_len);
+	enc->output.length += out_len;
+
+#ifdef RTE_BBDEV_OFFLOAD_COST
+	q_stats->acc_offload_cycles += rte_rdtsc_precise() - start_time;
+#endif
+#else
+	RTE_SET_USED(q);
+	RTE_SET_USED(op);
+	RTE_SET_USED(e);
+	RTE_SET_USED(m_in);
+	RTE_SET_USED(m_out_head);
+	RTE_SET_USED(m_out);
+	RTE_SET_USED(in_offset);
+	RTE_SET_USED(out_offset);
+	RTE_SET_USED(seg_total_left);
+	RTE_SET_USED(q_stats);
+#endif
+}
+
 static inline void
 enqueue_enc_one_op(struct turbo_sw_queue *q, struct rte_bbdev_enc_op *op,
 		struct rte_bbdev_stats *queue_stats)
@@ -850,6 +1049,93 @@ struct turbo_sw_queue {
 	}
 }
 
+
+static inline void
+enqueue_ldpc_enc_one_op(struct turbo_sw_queue *q, struct rte_bbdev_enc_op *op,
+		struct rte_bbdev_stats *queue_stats)
+{
+	uint8_t c, r, crc24_bits = 0;
+	uint32_t e;
+	struct rte_bbdev_op_ldpc_enc *enc = &op->ldpc_enc;
+	uint16_t in_offset = enc->input.offset;
+	uint16_t out_offset = enc->output.offset;
+	struct rte_mbuf *m_in = enc->input.data;
+	struct rte_mbuf *m_out = enc->output.data;
+	struct rte_mbuf *m_out_head = enc->output.data;
+	uint32_t in_length, mbuf_total_left = enc->input.length;
+
+	uint16_t seg_total_left;
+
+	/* Clear op status */
+	op->status = 0;
+
+	if (mbuf_total_left > RTE_BBDEV_TURBO_MAX_TB_SIZE >> 3) {
+		rte_bbdev_log(ERR, "TB size (%u) is too big, max: %d",
+				mbuf_total_left, RTE_BBDEV_TURBO_MAX_TB_SIZE);
+		op->status = 1 << RTE_BBDEV_DATA_ERROR;
+		return;
+	}
+
+	if (m_in == NULL || m_out == NULL) {
+		rte_bbdev_log(ERR, "Invalid mbuf pointer");
+		op->status = 1 << RTE_BBDEV_DATA_ERROR;
+		return;
+	}
+
+	if ((enc->op_flags & RTE_BBDEV_TURBO_CRC_24B_ATTACH) ||
+		(enc->op_flags & RTE_BBDEV_TURBO_CRC_24A_ATTACH))
+		crc24_bits = 24;
+
+	if (enc->code_block_mode == 0) { /* For Transport Block mode */
+		c = enc->tb_params.c;
+		r = enc->tb_params.r;
+	} else { /* For Code Block mode */
+		c = 1;
+		r = 0;
+	}
+
+	while (mbuf_total_left > 0 && r < c) {
+
+		seg_total_left = rte_pktmbuf_data_len(m_in) - in_offset;
+
+		if (enc->code_block_mode == 0) {
+			e = (r < enc->tb_params.cab) ?
+				enc->tb_params.ea : enc->tb_params.eb;
+		} else {
+			e = enc->cb_params.e;
+		}
+
+		process_ldpc_enc_cb(q, op, e, m_in, m_out_head,
+				m_out, in_offset, out_offset, seg_total_left,
+				queue_stats);
+		/* Update total_left */
+		in_length = (enc->basegraph == 1 ? 22 : 10) * enc->z_c;
+		in_length = ((in_length - crc24_bits - enc->n_filler) >> 3);
+		mbuf_total_left -= in_length;
+		/* Update offsets for next CBs (if exist) */
+		in_offset += in_length;
+		out_offset += (e + 7) >> 3;
+
+		/* Update offsets */
+		if (seg_total_left == in_length) {
+			/* Go to the next mbuf */
+			m_in = m_in->next;
+			m_out = m_out->next;
+			in_offset = 0;
+			out_offset = 0;
+		}
+		r++;
+	}
+
+	/* check if all input data was processed */
+	if (mbuf_total_left != 0) {
+		op->status |= 1 << RTE_BBDEV_DATA_ERROR;
+		rte_bbdev_log(ERR,
+				"Mismatch between mbuf length and included CBs sizes %d",
+				mbuf_total_left);
+	}
+}
+
 static inline uint16_t
 enqueue_enc_all_ops(struct turbo_sw_queue *q, struct rte_bbdev_enc_op **ops,
 		uint16_t nb_ops, struct rte_bbdev_stats *queue_stats)
@@ -866,6 +1152,23 @@ struct turbo_sw_queue {
 			NULL);
 }
 
+static inline uint16_t
+enqueue_ldpc_enc_all_ops(struct turbo_sw_queue *q,
+		struct rte_bbdev_enc_op **ops,
+		uint16_t nb_ops, struct rte_bbdev_stats *queue_stats)
+{
+	uint16_t i;
+#ifdef RTE_BBDEV_OFFLOAD_COST
+	queue_stats->acc_offload_cycles = 0;
+#endif
+
+	for (i = 0; i < nb_ops; ++i)
+		enqueue_ldpc_enc_one_op(q, ops[i], queue_stats);
+
+	return rte_ring_enqueue_burst(q->processed_pkts, (void **)ops, nb_ops,
+			NULL);
+}
+
 #ifdef RTE_BBDEV_SDK_AVX2
 static inline void
 move_padding_bytes(const uint8_t *in, uint8_t *out, uint16_t k,
@@ -890,7 +1193,11 @@ struct turbo_sw_queue {
 		struct rte_bbdev_stats *q_stats)
 {
 #ifdef RTE_BBDEV_SDK_AVX2
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
 	int ret;
+#else
+	RTE_SET_USED(in_length);
+#endif
 	int32_t k_idx;
 	int32_t iter_cnt;
 	uint8_t *in, *out, *adapter_input;
@@ -908,11 +1215,13 @@ struct turbo_sw_queue {
 
 	k_idx = compute_idx(k);
 
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
 	ret = is_dec_input_valid(k_idx, kw, in_length);
 	if (ret != 0) {
 		op->status |= 1 << RTE_BBDEV_DATA_ERROR;
 		return;
 	}
+#endif
 
 	in = rte_pktmbuf_mtod_offset(m_in, uint8_t *, in_offset);
 	ncb = kw;
@@ -928,11 +1237,12 @@ struct turbo_sw_queue {
 		deint_resp.pinteleavebuffer = q->deint_output;
 
 #ifdef RTE_BBDEV_OFFLOAD_COST
-		start_time = rte_rdtsc_precise();
+	start_time = rte_rdtsc_precise();
 #endif
+		/* Sub-block De-Interleaving */
 		bblib_deinterleave_ul(&deint_req, &deint_resp);
 #ifdef RTE_BBDEV_OFFLOAD_COST
-		q_stats->acc_offload_cycles += rte_rdtsc_precise() - start_time;
+	q_stats->acc_offload_cycles += rte_rdtsc_precise() - start_time;
 #endif
 	} else
 		move_padding_bytes(in, q->deint_output, k, ncb);
@@ -1025,6 +1335,202 @@ struct turbo_sw_queue {
 }
 
 static inline void
+process_ldpc_dec_cb(struct turbo_sw_queue *q, struct rte_bbdev_dec_op *op,
+		uint8_t c, uint16_t out_length, uint16_t e,
+		struct rte_mbuf *m_in,
+		struct rte_mbuf *m_out_head, struct rte_mbuf *m_out,
+		struct rte_mbuf *m_harq_in,
+		struct rte_mbuf *m_harq_out_head, struct rte_mbuf *m_harq_out,
+		uint16_t in_offset, uint16_t out_offset,
+		uint16_t harq_in_offset, uint16_t harq_out_offset,
+		bool check_crc_24b,
+		uint16_t crc24_overlap, uint16_t in_length,
+		struct rte_bbdev_stats *q_stats)
+{
+#ifdef RTE_BBDEV_SDK_AVX512
+	RTE_SET_USED(in_length);
+	RTE_SET_USED(c);
+	uint8_t *in, *out, *harq_in, *harq_out, *adapter_input;
+	struct bblib_rate_dematching_5gnr_request derm_req;
+	struct bblib_rate_dematching_5gnr_response derm_resp;
+	struct bblib_ldpc_decoder_5gnr_request dec_req;
+	struct bblib_ldpc_decoder_5gnr_response dec_resp;
+	struct bblib_crc_request crc_req;
+	struct bblib_crc_response crc_resp;
+	struct rte_bbdev_op_ldpc_dec *dec = &op->ldpc_dec;
+	uint16_t K, parity_offset, sys_cols, outLenWithCrc;
+	int16_t deRmOutSize, numRows;
+
+	/* Compute some LDPC BG lengths */
+	outLenWithCrc = out_length + (crc24_overlap >> 3);
+	sys_cols = (dec->basegraph == 1) ? 22 : 10;
+	K = sys_cols * dec->z_c;
+	parity_offset = K - 2 * dec->z_c;
+
+#ifdef RTE_BBDEV_OFFLOAD_COST
+	uint64_t start_time = rte_rdtsc_precise();
+#else
+	RTE_SET_USED(q_stats);
+#endif
+
+	in = rte_pktmbuf_mtod_offset(m_in, uint8_t *, in_offset);
+
+	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) {
+		/**
+		 *  Single contiguous block from the first LLR of the
+		 *  circular buffer.
+		 */
+		harq_in = NULL;
+		if (m_harq_in != NULL)
+			harq_in = rte_pktmbuf_mtod_offset(m_harq_in,
+				uint8_t *, harq_in_offset);
+		if (harq_in == NULL) {
+			op->status |= 1 << RTE_BBDEV_DATA_ERROR;
+			rte_bbdev_log(ERR, "No space in harq input mbuf");
+			return;
+		}
+		uint16_t harq_in_length = RTE_MIN(
+				dec->harq_combined_input.length,
+				(uint32_t) dec->n_cb);
+		memset(q->ag + harq_in_length, 0,
+				dec->n_cb - harq_in_length);
+		rte_memcpy(q->ag, harq_in, harq_in_length);
+	}
+
+	derm_req.p_in = (int8_t *) in;
+	derm_req.p_harq = q->ag; /* This doesn't include the filler bits */
+	derm_req.base_graph = dec->basegraph;
+	derm_req.zc = dec->z_c;
+	derm_req.ncb = dec->n_cb;
+	derm_req.e = e;
+	derm_req.k0 = 0; /* Actual output from SDK */
+	derm_req.isretx = check_bit(dec->op_flags,
+			RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE);
+	derm_req.rvid = dec->rv_index;
+	derm_req.modulation_order = dec->q_m;
+	derm_req.start_null_index = parity_offset - dec->n_filler;
+	derm_req.num_of_null = dec->n_filler;
+
+	bblib_rate_dematching_5gnr(&derm_req, &derm_resp);
+
+	/* Compute RM out size and number of rows */
+	deRmOutSize = RTE_MIN(
+			derm_req.k0 + derm_req.e -
+			((derm_req.k0 < derm_req.start_null_index) ?
+					0 : dec->n_filler),
+			dec->n_cb - dec->n_filler);
+	if (m_harq_in != NULL)
+		deRmOutSize = RTE_MAX(deRmOutSize,
+				RTE_MIN(dec->n_cb - dec->n_filler,
+						m_harq_in->data_len));
+	numRows = ((deRmOutSize + dec->n_filler + dec->z_c - 1) / dec->z_c)
+			- sys_cols + 2;
+	numRows = RTE_MAX(4, numRows);
+
+	/* get output data starting address */
+	out = (uint8_t *)mbuf_append(m_out_head, m_out, out_length);
+	if (out == NULL) {
+		op->status |= 1 << RTE_BBDEV_DATA_ERROR;
+		rte_bbdev_log(ERR,
+				"Too little space in LDPC decoder output mbuf");
+		return;
+	}
+
+	/* rte_bbdev_op_data.offset can be different than the offset
+	 * of the appended bytes
+	 */
+	out = rte_pktmbuf_mtod_offset(m_out, uint8_t *, out_offset);
+	adapter_input = q->enc_out;
+
+	dec_req.Zc = dec->z_c;
+	dec_req.baseGraph = dec->basegraph;
+	dec_req.nRows = numRows;
+	dec_req.numChannelLlrs = deRmOutSize;
+	dec_req.varNodes = derm_req.p_harq;
+	dec_req.numFillerBits = dec->n_filler;
+	dec_req.maxIterations = dec->iter_max;
+	dec_req.enableEarlyTermination = check_bit(dec->op_flags,
+			RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE);
+	dec_resp.varNodes = (int16_t *) q->adapter_output;
+	dec_resp.compactedMessageBytes = q->enc_out;
+
+	bblib_ldpc_decoder_5gnr(&dec_req, &dec_resp);
+
+	dec->iter_count = RTE_MAX(dec_resp.iterationAtTermination,
+			dec->iter_count);
+	if (!dec_resp.parityPassedAtTermination)
+		op->status |= 1 << RTE_BBDEV_SYNDROME_ERROR;
+
+	bblib_bit_reverse((int8_t *) q->enc_out, outLenWithCrc << 3);
+
+	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK) ||
+			check_bit(dec->op_flags,
+					RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK)) {
+		crc_req.data = adapter_input;
+		crc_req.len  = K - dec->n_filler - 24;
+		crc_resp.check_passed = false;
+		crc_resp.data = adapter_input;
+		if (check_crc_24b)
+			bblib_lte_crc24b_check(&crc_req, &crc_resp);
+		else
+			bblib_lte_crc24a_check(&crc_req, &crc_resp);
+		if (!crc_resp.check_passed)
+			op->status |= 1 << RTE_BBDEV_CRC_ERROR;
+	}
+
+#ifdef RTE_BBDEV_OFFLOAD_COST
+	q_stats->acc_offload_cycles += rte_rdtsc_precise() - start_time;
+#endif
+	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE)) {
+		harq_out = NULL;
+		if (m_harq_out != NULL) {
+			/* Initialize HARQ data length since we overwrite */
+			m_harq_out->data_len = 0;
+			/* Check there is enough space
+			 * in the HARQ outbound buffer
+			 */
+			harq_out = (uint8_t *)mbuf_append(m_harq_out_head,
+					m_harq_out, deRmOutSize);
+		}
+		if (harq_out == NULL) {
+			op->status |= 1 << RTE_BBDEV_DATA_ERROR;
+			rte_bbdev_log(ERR, "No space in HARQ output mbuf");
+			return;
+		}
+		/* get output data starting address and overwrite the data */
+		harq_out = rte_pktmbuf_mtod_offset(m_harq_out, uint8_t *,
+				harq_out_offset);
+		rte_memcpy(harq_out, derm_req.p_harq, deRmOutSize);
+		dec->harq_combined_output.length += deRmOutSize;
+	}
+
+	rte_memcpy(out, adapter_input, out_length);
+	dec->hard_output.length += out_length;
+#else
+	RTE_SET_USED(q);
+	RTE_SET_USED(op);
+	RTE_SET_USED(c);
+	RTE_SET_USED(out_length);
+	RTE_SET_USED(e);
+	RTE_SET_USED(m_in);
+	RTE_SET_USED(m_out_head);
+	RTE_SET_USED(m_out);
+	RTE_SET_USED(m_harq_in);
+	RTE_SET_USED(m_harq_out_head);
+	RTE_SET_USED(m_harq_out);
+	RTE_SET_USED(harq_in_offset);
+	RTE_SET_USED(harq_out_offset);
+	RTE_SET_USED(in_offset);
+	RTE_SET_USED(out_offset);
+	RTE_SET_USED(check_crc_24b);
+	RTE_SET_USED(crc24_overlap);
+	RTE_SET_USED(in_length);
+	RTE_SET_USED(q_stats);
+#endif
+}
+
+
+static inline void
 enqueue_dec_one_op(struct turbo_sw_queue *q, struct rte_bbdev_dec_op *op,
 		struct rte_bbdev_stats *queue_stats)
 {
@@ -1083,6 +1589,7 @@ struct turbo_sw_queue {
 				in_offset, out_offset, check_bit(dec->op_flags,
 				RTE_BBDEV_TURBO_CRC_TYPE_24B), crc24_overlap,
 				seg_total_left, queue_stats);
+
 		/* To keep CRC24 attached to end of Code block, use
 		 * RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP flag as it
 		 * removed by default once verified.
@@ -1104,6 +1611,103 @@ struct turbo_sw_queue {
 		}
 		r++;
 	}
+
+	if (mbuf_total_left != 0) {
+		op->status |= 1 << RTE_BBDEV_DATA_ERROR;
+		rte_bbdev_log(ERR,
+				"Mismatch between mbuf length and included Circular buffer sizes");
+	}
+}
+
+static inline void
+enqueue_ldpc_dec_one_op(struct turbo_sw_queue *q, struct rte_bbdev_dec_op *op,
+		struct rte_bbdev_stats *queue_stats)
+{
+	uint8_t c, r = 0;
+	uint16_t e, out_length;
+	uint16_t crc24_overlap = 0;
+	struct rte_bbdev_op_ldpc_dec *dec = &op->ldpc_dec;
+	struct rte_mbuf *m_in = dec->input.data;
+	struct rte_mbuf *m_harq_in = dec->harq_combined_input.data;
+	struct rte_mbuf *m_harq_out = dec->harq_combined_output.data;
+	struct rte_mbuf *m_harq_out_head = dec->harq_combined_output.data;
+	struct rte_mbuf *m_out = dec->hard_output.data;
+	struct rte_mbuf *m_out_head = dec->hard_output.data;
+	uint16_t in_offset = dec->input.offset;
+	uint16_t harq_in_offset = dec->harq_combined_input.offset;
+	uint16_t harq_out_offset = dec->harq_combined_output.offset;
+	uint16_t out_offset = dec->hard_output.offset;
+	uint32_t mbuf_total_left = dec->input.length;
+	uint16_t seg_total_left;
+
+	/* Clear op status */
+	op->status = 0;
+
+	if (m_in == NULL || m_out == NULL) {
+		rte_bbdev_log(ERR, "Invalid mbuf pointer");
+		op->status = 1 << RTE_BBDEV_DATA_ERROR;
+		return;
+	}
+
+	if (dec->code_block_mode == 0) { /* For Transport Block mode */
+		c = dec->tb_params.c;
+		e = dec->tb_params.ea;
+	} else { /* For Code Block mode */
+		c = 1;
+		e = dec->cb_params.e;
+	}
+
+	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP))
+		crc24_overlap = 24;
+
+	out_length = (dec->basegraph == 1 ? 22 : 10) * dec->z_c; /* K */
+	out_length = ((out_length - crc24_overlap - dec->n_filler) >> 3);
+
+	while (mbuf_total_left > 0) {
+		if (dec->code_block_mode == 0)
+			e = (r < dec->tb_params.cab) ?
+				dec->tb_params.ea : dec->tb_params.eb;
+
+		seg_total_left = rte_pktmbuf_data_len(m_in) - in_offset;
+
+		process_ldpc_dec_cb(q, op, c, out_length, e,
+				m_in, m_out_head, m_out,
+				m_harq_in, m_harq_out_head, m_harq_out,
+				in_offset, out_offset, harq_in_offset,
+				harq_out_offset,
+				check_bit(dec->op_flags,
+				RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK),
+				crc24_overlap,
+				seg_total_left, queue_stats);
+
+		/* To keep CRC24 attached to end of Code block, use
+		 * RTE_BBDEV_LDPC_DEC_TB_CRC_24B_KEEP flag as it
+		 * removed by default once verified.
+		 */
+
+		mbuf_total_left -= e;
+
+		/* Update offsets */
+		if (seg_total_left == e) {
+			/* Go to the next mbuf */
+			m_in = m_in->next;
+			m_out = m_out->next;
+			if (m_harq_in != NULL)
+				m_harq_in = m_harq_in->next;
+			if (m_harq_out != NULL)
+				m_harq_out = m_harq_out->next;
+			in_offset = 0;
+			out_offset = 0;
+			harq_in_offset = 0;
+			harq_out_offset = 0;
+		} else {
+			/* Update offsets for next CBs (if exist) */
+			in_offset += e;
+			out_offset += out_length;
+		}
+		r++;
+	}
+
 	if (mbuf_total_left != 0) {
 		op->status |= 1 << RTE_BBDEV_DATA_ERROR;
 		rte_bbdev_log(ERR,
@@ -1127,6 +1731,23 @@ struct turbo_sw_queue {
 			NULL);
 }
 
+static inline uint16_t
+enqueue_ldpc_dec_all_ops(struct turbo_sw_queue *q,
+		struct rte_bbdev_dec_op **ops,
+		uint16_t nb_ops, struct rte_bbdev_stats *queue_stats)
+{
+	uint16_t i;
+#ifdef RTE_BBDEV_OFFLOAD_COST
+	queue_stats->acc_offload_cycles = 0;
+#endif
+
+	for (i = 0; i < nb_ops; ++i)
+		enqueue_ldpc_dec_one_op(q, ops[i], queue_stats);
+
+	return rte_ring_enqueue_burst(q->processed_pkts, (void **)ops, nb_ops,
+			NULL);
+}
+
 /* Enqueue burst */
 static uint16_t
 enqueue_enc_ops(struct rte_bbdev_queue_data *q_data,
@@ -1146,6 +1767,24 @@ struct turbo_sw_queue {
 
 /* Enqueue burst */
 static uint16_t
+enqueue_ldpc_enc_ops(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_enc_op **ops, uint16_t nb_ops)
+{
+	void *queue = q_data->queue_private;
+	struct turbo_sw_queue *q = queue;
+	uint16_t nb_enqueued = 0;
+
+	nb_enqueued = enqueue_ldpc_enc_all_ops(
+			q, ops, nb_ops, &q_data->queue_stats);
+
+	q_data->queue_stats.enqueue_err_count += nb_ops - nb_enqueued;
+	q_data->queue_stats.enqueued_count += nb_enqueued;
+
+	return nb_enqueued;
+}
+
+/* Enqueue burst */
+static uint16_t
 enqueue_dec_ops(struct rte_bbdev_queue_data *q_data,
 		 struct rte_bbdev_dec_op **ops, uint16_t nb_ops)
 {
@@ -1161,6 +1800,24 @@ struct turbo_sw_queue {
 	return nb_enqueued;
 }
 
+/* Enqueue burst */
+static uint16_t
+enqueue_ldpc_dec_ops(struct rte_bbdev_queue_data *q_data,
+		 struct rte_bbdev_dec_op **ops, uint16_t nb_ops)
+{
+	void *queue = q_data->queue_private;
+	struct turbo_sw_queue *q = queue;
+	uint16_t nb_enqueued = 0;
+
+	nb_enqueued = enqueue_ldpc_dec_all_ops(q, ops, nb_ops,
+			&q_data->queue_stats);
+
+	q_data->queue_stats.enqueue_err_count += nb_ops - nb_enqueued;
+	q_data->queue_stats.enqueued_count += nb_enqueued;
+
+	return nb_enqueued;
+}
+
 /* Dequeue decode burst */
 static uint16_t
 dequeue_dec_ops(struct rte_bbdev_queue_data *q_data,
@@ -1273,6 +1930,10 @@ struct turbo_sw_queue {
 	bbdev->dequeue_dec_ops = dequeue_dec_ops;
 	bbdev->enqueue_enc_ops = enqueue_enc_ops;
 	bbdev->enqueue_dec_ops = enqueue_dec_ops;
+	bbdev->dequeue_ldpc_enc_ops = dequeue_enc_ops;
+	bbdev->dequeue_ldpc_dec_ops = dequeue_dec_ops;
+	bbdev->enqueue_ldpc_enc_ops = enqueue_ldpc_enc_ops;
+	bbdev->enqueue_ldpc_dec_ops = enqueue_ldpc_dec_ops;
 	((struct bbdev_private *) bbdev->data->dev_private)->max_nb_queues =
 			init_params->queues_num;
 
diff --git a/drivers/baseband/turbo_sw/meson.build b/drivers/baseband/turbo_sw/meson.build
index 438b5a7..33345aa 100644
--- a/drivers/baseband/turbo_sw/meson.build
+++ b/drivers/baseband/turbo_sw/meson.build
@@ -23,6 +23,16 @@ if dpdk_conf.has('RTE_BBDEV_SDK_AVX2')
 		includes += include_directories(path + '/lib_common')
 	endif
 endif
+if dpdk_conf.has('RTE_BBDEV_SDK_AVX512')
+	ext_deps += cc.find_library('libldpc_encoder_5gnr', dirs: [path + '/lib_ldpc_encoder_5gnr'], required: true)
+	ext_deps += cc.find_library('libldpc_decoder_5gnr', dirs: [path + '/lib_ldpc_decoder_5gnr'], required: true)
+	ext_deps += cc.find_library('libLDPC_ratematch_5gnr', dirs: [path + '/lib_LDPC_ratematch_5gnr'], required: true)
+	ext_deps += cc.find_library('librate_dematching_5gnr', dirs: [path + '/lib_rate_dematching_5gnr'], required: true)
+	includes += include_directories(path + '/lib_ldpc_encoder_5gnr')
+	includes += include_directories(path + '/lib_ldpc_decoder_5gnr')
+	includes += include_directories(path + '/lib_LDPC_ratematch_5gnr')
+	includes += include_directories(path + '/lib_rate_dematching_5gnr')
+endif
 
 deps += ['bbdev', 'bus_vdev', 'ring']
 name = 'bbdev_turbo_sw'
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index c9fbdd6..1036df7 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -232,7 +232,13 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_crc -lcr
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_turbo -lturbo
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_rate_matching -lrate_matching
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_common -lcommon
-_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -lirc -limf -lstdc++ -lipps
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -lirc -limf -lstdc++ -lipps -lsvml
+ifeq ($(CONFIG_RTE_BBDEV_SDK_AVX512),y)
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_LDPC_ratematch_5gnr -lLDPC_ratematch_5gnr
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_ldpc_encoder_5gnr -lldpc_encoder_5gnr
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_ldpc_decoder_5gnr -lldpc_decoder_5gnr
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BBDEV_TURBO_SW) += -L$(FLEXRAN_SDK)/lib_rate_dematching_5gnr -lrate_dematching_5gnr
+endif # CONFIG_RTE_BBDEV_SDK_AVX512
 endif # CONFIG_RTE_BBDEV_SDK_AVX2
 endif # CONFIG_RTE_LIBRTE_BBDEV
 
-- 
1.8.3.1


^ permalink raw reply	[relevance 2%]

* [dpdk-dev] [PATCH v5 2/7] bbdev: extension of BBDEV API for 5G FEC
  @ 2019-07-01 18:06  3%   ` Nicolas Chautru
  2019-07-01 18:06  2%   ` [dpdk-dev] [PATCH v5 4/7] baseband/turbo_sw: extension of turbosw PMD for 5G Nicolas Chautru
  1 sibling, 0 replies; 200+ results
From: Nicolas Chautru @ 2019-07-01 18:06 UTC (permalink / raw)
  To: akhil.goyal, dev
  Cc: ferruh.yigit, thomas, amr.mokhtar, kamilx.chalupnik, Nicolas Chautru

Extension to BBDEV operations to support 5G
on top of existing 4G operations.

Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
Acked-by: Amr Mokhtar <amr.mokhtar@intel.com>
---
 doc/guides/rel_notes/release_19_08.rst |   4 +-
 lib/librte_bbdev/rte_bbdev.c           |  22 +-
 lib/librte_bbdev/rte_bbdev.h           | 138 +++++++-
 lib/librte_bbdev/rte_bbdev_op.h        | 567 ++++++++++++++++++++++++++-------
 4 files changed, 608 insertions(+), 123 deletions(-)

diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 335d24a..55ae8ee 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -126,7 +126,6 @@ New Features
   Added telemetry mode to l3fwd-power application to report
   application level busyness, empty and full polls of rte_eth_rx_burst().
 
-
 Removed Items
 -------------
 
@@ -192,6 +191,9 @@ ABI Changes
 
   Disabling unused features would facilitate efficient usage of HW/SW offload.
 
+* bbdev: New operations and parameters added to support new 5GNR operations.
+  The bbdev ABI is still kept experimental.
+
 Shared Library Versions
 -----------------------
 
diff --git a/lib/librte_bbdev/rte_bbdev.c b/lib/librte_bbdev/rte_bbdev.c
index 0c35480..f6fe05a 100644
--- a/lib/librte_bbdev/rte_bbdev.c
+++ b/lib/librte_bbdev/rte_bbdev.c
@@ -6,7 +6,6 @@
 #include <string.h>
 #include <stdbool.h>
 
-#include <rte_string_fns.h>
 #include <rte_compat.h>
 #include <rte_common.h>
 #include <rte_errno.h>
@@ -215,7 +214,7 @@ struct rte_bbdev *
 	bbdev->data->dev_id = dev_id;
 	bbdev->state = RTE_BBDEV_INITIALIZED;
 
-	ret = strlcpy(bbdev->data->name, name, RTE_BBDEV_NAME_MAX_LEN);
+	ret = snprintf(bbdev->data->name, RTE_BBDEV_NAME_MAX_LEN, "%s", name);
 	if ((ret < 0) || (ret >= RTE_BBDEV_NAME_MAX_LEN)) {
 		rte_bbdev_log(ERR, "Copying device name \"%s\" failed", name);
 		return NULL;
@@ -499,7 +498,7 @@ struct rte_bbdev *
 		if (conf->op_type == RTE_BBDEV_OP_TURBO_DEC &&
 			conf->priority > dev_info.max_ul_queue_priority) {
 			rte_bbdev_log(ERR,
-					"Priority (%u) of queue %u of bdev %u must be <= %u",
+					"Priority (%u) of queue %u of bbdev %u must be <= %u",
 					conf->priority, queue_id, dev_id,
 					dev_info.max_ul_queue_priority);
 			return -EINVAL;
@@ -507,7 +506,7 @@ struct rte_bbdev *
 		if (conf->op_type == RTE_BBDEV_OP_TURBO_ENC &&
 			conf->priority > dev_info.max_dl_queue_priority) {
 			rte_bbdev_log(ERR,
-					"Priority (%u) of queue %u of bdev %u must be <= %u",
+					"Priority (%u) of queue %u of bbdev %u must be <= %u",
 					conf->priority, queue_id, dev_id,
 					dev_info.max_dl_queue_priority);
 			return -EINVAL;
@@ -796,7 +795,7 @@ struct rte_bbdev *
 	memset(dev_info, 0, sizeof(*dev_info));
 	dev_info->dev_name = dev->data->name;
 	dev_info->num_queues = dev->data->num_queues;
-	dev_info->bus = rte_bus_find_by_device(dev->device);
+	dev_info->device = dev->device;
 	dev_info->socket_id = dev->data->socket_id;
 	dev_info->started = dev->data->started;
 
@@ -847,6 +846,12 @@ struct rte_bbdev *
 	case RTE_BBDEV_OP_TURBO_ENC:
 		result = sizeof(struct rte_bbdev_enc_op);
 		break;
+	case RTE_BBDEV_OP_LDPC_DEC:
+		result = sizeof(struct rte_bbdev_dec_op);
+		break;
+	case RTE_BBDEV_OP_LDPC_ENC:
+		result = sizeof(struct rte_bbdev_enc_op);
+		break;
 	default:
 		break;
 	}
@@ -861,11 +866,12 @@ struct rte_bbdev *
 {
 	enum rte_bbdev_op_type type = *(enum rte_bbdev_op_type *)arg;
 
-	if (type == RTE_BBDEV_OP_TURBO_DEC) {
+	if (type == RTE_BBDEV_OP_TURBO_DEC || type == RTE_BBDEV_OP_LDPC_DEC) {
 		struct rte_bbdev_dec_op *op = element;
 		memset(op, 0, mempool->elt_size);
 		op->mempool = mempool;
-	} else if (type == RTE_BBDEV_OP_TURBO_ENC) {
+	} else if (type == RTE_BBDEV_OP_TURBO_ENC ||
+			type == RTE_BBDEV_OP_LDPC_ENC) {
 		struct rte_bbdev_enc_op *op = element;
 		memset(op, 0, mempool->elt_size);
 		op->mempool = mempool;
@@ -1117,6 +1123,8 @@ struct rte_mempool *
 		"RTE_BBDEV_OP_NONE",
 		"RTE_BBDEV_OP_TURBO_DEC",
 		"RTE_BBDEV_OP_TURBO_ENC",
+		"RTE_BBDEV_OP_LDPC_DEC",
+		"RTE_BBDEV_OP_LDPC_ENC",
 	};
 
 	if (op_type < RTE_BBDEV_OP_TYPE_COUNT)
diff --git a/lib/librte_bbdev/rte_bbdev.h b/lib/librte_bbdev/rte_bbdev.h
index c5175cc..591fb79 100644
--- a/lib/librte_bbdev/rte_bbdev.h
+++ b/lib/librte_bbdev/rte_bbdev.h
@@ -167,7 +167,7 @@ struct rte_bbdev_queue_conf {
 
 /**
  * Start a device.
- * This is the last step needed before enqueuing operations is possible.
+ * This is the last step needed before enqueueing operations is possible.
  *
  * @param dev_id
  *   The identifier of the device.
@@ -326,7 +326,7 @@ struct rte_bbdev_driver_info {
 struct rte_bbdev_info {
 	int socket_id;  /**< NUMA socket that device is on */
 	const char *dev_name;  /**< Unique device name */
-	const struct rte_bus *bus;  /**< Bus information */
+	const struct rte_device *device; /**< Device Information */
 	uint16_t num_queues;  /**< Number of queues currently configured */
 	bool started;  /**< Set if device is currently started */
 	struct rte_bbdev_driver_info drv;  /**< Info from device driver */
@@ -448,6 +448,14 @@ struct __rte_cache_aligned rte_bbdev {
 	rte_bbdev_dequeue_enc_ops_t dequeue_enc_ops;
 	/**< Dequeue decode function */
 	rte_bbdev_dequeue_dec_ops_t dequeue_dec_ops;
+	/**< Enqueue encode function */
+	rte_bbdev_enqueue_enc_ops_t enqueue_ldpc_enc_ops;
+	/**< Enqueue decode function */
+	rte_bbdev_enqueue_dec_ops_t enqueue_ldpc_dec_ops;
+	/**< Dequeue encode function */
+	rte_bbdev_dequeue_enc_ops_t dequeue_ldpc_enc_ops;
+	/**< Dequeue decode function */
+	rte_bbdev_dequeue_dec_ops_t dequeue_ldpc_dec_ops;
 	const struct rte_bbdev_ops *dev_ops;  /**< Functions exported by PMD */
 	struct rte_bbdev_data *data;  /**< Pointer to device data */
 	enum rte_bbdev_state state;  /**< If device is currently used or not */
@@ -523,6 +531,69 @@ struct __rte_cache_aligned rte_bbdev {
 }
 
 /**
+ * Enqueue a burst of processed encode operations to a queue of the device.
+ * This functions only enqueues as many operations as currently possible and
+ * does not block until @p num_ops entries in the queue are available.
+ * This function does not provide any error notification to avoid the
+ * corresponding overhead.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param queue_id
+ *   The index of the queue.
+ * @param ops
+ *   Pointer array containing operations to be enqueued Must have at least
+ *   @p num_ops entries
+ * @param num_ops
+ *   The maximum number of operations to enqueue.
+ *
+ * @return
+ *   The number of operations actually enqueued (this is the number of processed
+ *   entries in the @p ops array).
+ */
+__rte_experimental
+static inline uint16_t
+rte_bbdev_enqueue_ldpc_enc_ops(uint16_t dev_id, uint16_t queue_id,
+		struct rte_bbdev_enc_op **ops, uint16_t num_ops)
+{
+	struct rte_bbdev *dev = &rte_bbdev_devices[dev_id];
+	struct rte_bbdev_queue_data *q_data = &dev->data->queues[queue_id];
+	return dev->enqueue_ldpc_enc_ops(q_data, ops, num_ops);
+}
+
+/**
+ * Enqueue a burst of processed decode operations to a queue of the device.
+ * This functions only enqueues as many operations as currently possible and
+ * does not block until @p num_ops entries in the queue are available.
+ * This function does not provide any error notification to avoid the
+ * corresponding overhead.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param queue_id
+ *   The index of the queue.
+ * @param ops
+ *   Pointer array containing operations to be enqueued Must have at least
+ *   @p num_ops entries
+ * @param num_ops
+ *   The maximum number of operations to enqueue.
+ *
+ * @return
+ *   The number of operations actually enqueued (this is the number of processed
+ *   entries in the @p ops array).
+ */
+__rte_experimental
+static inline uint16_t
+rte_bbdev_enqueue_ldpc_dec_ops(uint16_t dev_id, uint16_t queue_id,
+		struct rte_bbdev_dec_op **ops, uint16_t num_ops)
+{
+	struct rte_bbdev *dev = &rte_bbdev_devices[dev_id];
+	struct rte_bbdev_queue_data *q_data = &dev->data->queues[queue_id];
+	return dev->enqueue_ldpc_dec_ops(q_data, ops, num_ops);
+}
+
+
+/**
  * Dequeue a burst of processed encode operations from a queue of the device.
  * This functions returns only the current contents of the queue, and does not
  * block until @ num_ops is available.
@@ -585,6 +656,69 @@ struct __rte_cache_aligned rte_bbdev {
 	return dev->dequeue_dec_ops(q_data, ops, num_ops);
 }
 
+
+/**
+ * Dequeue a burst of processed encode operations from a queue of the device.
+ * This functions returns only the current contents of the queue, and does not
+ * block until @ num_ops is available.
+ * This function does not provide any error notification to avoid the
+ * corresponding overhead.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param queue_id
+ *   The index of the queue.
+ * @param ops
+ *   Pointer array where operations will be dequeued to. Must have at least
+ *   @p num_ops entries
+ * @param num_ops
+ *   The maximum number of operations to dequeue.
+ *
+ * @return
+ *   The number of operations actually dequeued (this is the number of entries
+ *   copied into the @p ops array).
+ */
+__rte_experimental
+static inline uint16_t
+rte_bbdev_dequeue_ldpc_enc_ops(uint16_t dev_id, uint16_t queue_id,
+		struct rte_bbdev_enc_op **ops, uint16_t num_ops)
+{
+	struct rte_bbdev *dev = &rte_bbdev_devices[dev_id];
+	struct rte_bbdev_queue_data *q_data = &dev->data->queues[queue_id];
+	return dev->dequeue_ldpc_enc_ops(q_data, ops, num_ops);
+}
+
+/**
+ * Dequeue a burst of processed decode operations from a queue of the device.
+ * This functions returns only the current contents of the queue, and does not
+ * block until @ num_ops is available.
+ * This function does not provide any error notification to avoid the
+ * corresponding overhead.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param queue_id
+ *   The index of the queue.
+ * @param ops
+ *   Pointer array where operations will be dequeued to. Must have at least
+ *   @p num_ops entries
+ * @param num_ops
+ *   The maximum number of operations to dequeue.
+ *
+ * @return
+ *   The number of operations actually dequeued (this is the number of entries
+ *   copied into the @p ops array).
+ */
+__rte_experimental
+static inline uint16_t
+rte_bbdev_dequeue_ldpc_dec_ops(uint16_t dev_id, uint16_t queue_id,
+		struct rte_bbdev_dec_op **ops, uint16_t num_ops)
+{
+	struct rte_bbdev *dev = &rte_bbdev_devices[dev_id];
+	struct rte_bbdev_queue_data *q_data = &dev->data->queues[queue_id];
+	return dev->dequeue_ldpc_dec_ops(q_data, ops, num_ops);
+}
+
 /** Definitions of device event types */
 enum rte_bbdev_event_type {
 	RTE_BBDEV_EVENT_UNKNOWN,  /**< unknown event type */
diff --git a/lib/librte_bbdev/rte_bbdev_op.h b/lib/librte_bbdev/rte_bbdev_op.h
index d860989..1e119a7 100644
--- a/lib/librte_bbdev/rte_bbdev_op.h
+++ b/lib/librte_bbdev/rte_bbdev_op.h
@@ -31,57 +31,61 @@
 #define RTE_BBDEV_TURBO_MAX_TB_SIZE (391656)
 /* Maximum size of Code Block (36.212, Table 5.1.3-3) */
 #define RTE_BBDEV_TURBO_MAX_CB_SIZE (6144)
+/* Maximum size of Code Block  */
+#define RTE_BBDEV_LDPC_MAX_CB_SIZE (8448)
 /* Minimum size of Code Block (36.212, Table 5.1.3-3) */
 #define RTE_BBDEV_TURBO_MIN_CB_SIZE (40)
 /* Maximum size of circular buffer */
 #define RTE_BBDEV_TURBO_MAX_KW (18528)
 /*
- * Maximum number of Code Blocks in Transport Block. It is calculated based on
- * maximum size of one Code Block and one Transport Block (considering CRC24A
- * and CRC24B):
+ * Turbo: Maximum number of Code Blocks in Transport Block. It is calculated
+ * based on maximum size of one Code Block and one Transport Block
+ * (considering CRC24A and CRC24B):
  * (391656 + 24) / (6144 - 24) = 64
  */
 #define RTE_BBDEV_TURBO_MAX_CODE_BLOCKS (64)
+/* LDPC:  Maximum number of Code Blocks in Transport Block.*/
+#define RTE_BBDEV_LDPC_MAX_CODE_BLOCKS (256)
 
 /** Flags for turbo decoder operation and capability structure */
 enum rte_bbdev_op_td_flag_bitmasks {
-	/**< If sub block de-interleaving is to be performed. */
+	/** If sub block de-interleaving is to be performed. */
 	RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE = (1ULL << 0),
-	/**< To use CRC Type 24B (otherwise use CRC Type 24A). */
+	/** To use CRC Type 24B (otherwise use CRC Type 24A). */
 	RTE_BBDEV_TURBO_CRC_TYPE_24B = (1ULL << 1),
-	/**< If turbo equalization is to be performed. */
+	/** If turbo equalization is to be performed. */
 	RTE_BBDEV_TURBO_EQUALIZER = (1ULL << 2),
-	/**< If set, saturate soft output to +/-127 */
+	/** If set, saturate soft output to +/-127 */
 	RTE_BBDEV_TURBO_SOFT_OUT_SATURATE = (1ULL << 3),
-	/**< Set to 1 to start iteration from even, else odd; one iteration =
+	/** Set to 1 to start iteration from even, else odd; one iteration =
 	 * max_iteration + 0.5
 	 */
 	RTE_BBDEV_TURBO_HALF_ITERATION_EVEN = (1ULL << 4),
-	/**< If 0, TD stops after CRC matches; else if 1, runs to end of next
+	/** If 0, TD stops after CRC matches; else if 1, runs to end of next
 	 * odd iteration after CRC matches
 	 */
 	RTE_BBDEV_TURBO_CONTINUE_CRC_MATCH = (1ULL << 5),
-	/**< Set if soft output is required to be output  */
+	/** Set if soft output is required to be output  */
 	RTE_BBDEV_TURBO_SOFT_OUTPUT = (1ULL << 6),
-	/**< Set to enable early termination mode */
+	/** Set to enable early termination mode */
 	RTE_BBDEV_TURBO_EARLY_TERMINATION = (1ULL << 7),
-	/**< Set if a device supports decoder dequeue interrupts */
+	/** Set if a device supports decoder dequeue interrupts */
 	RTE_BBDEV_TURBO_DEC_INTERRUPTS = (1ULL << 9),
-	/**< Set if positive LLR encoded input is supported. Positive LLR value
+	/** Set if positive LLR encoded input is supported. Positive LLR value
 	 * represents the level of confidence for bit '1', and vice versa for
 	 * bit '0'.
 	 * This is mutually exclusive with RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN
 	 * when used to formalize the input data format.
 	 */
 	RTE_BBDEV_TURBO_POS_LLR_1_BIT_IN = (1ULL << 10),
-	/**< Set if negative LLR encoded input is supported. Negative LLR value
+	/** Set if negative LLR encoded input is supported. Negative LLR value
 	 * represents the level of confidence for bit '1', and vice versa for
 	 * bit '0'.
 	 * This is mutually exclusive with RTE_BBDEV_TURBO_POS_LLR_1_BIT_IN
 	 * when used to formalize the input data format.
 	 */
 	RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN = (1ULL << 11),
-	/**< Set if positive LLR soft output is supported. Positive LLR value
+	/** Set if positive LLR soft output is supported. Positive LLR value
 	 * represents the level of confidence for bit '1', and vice versa for
 	 * bit '0'.
 	 * This is mutually exclusive with
@@ -89,7 +93,7 @@ enum rte_bbdev_op_td_flag_bitmasks {
 	 * the input data format.
 	 */
 	RTE_BBDEV_TURBO_POS_LLR_1_BIT_SOFT_OUT = (1ULL << 12),
-	/**< Set if negative LLR soft output is supported. Negative LLR value
+	/** Set if negative LLR soft output is supported. Negative LLR value
 	 * represents the level of confidence for bit '1', and vice versa for
 	 * bit '0'.
 	 * This is mutually exclusive with
@@ -97,43 +101,114 @@ enum rte_bbdev_op_td_flag_bitmasks {
 	 * input data format.
 	 */
 	RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT = (1ULL << 13),
-	/**< Set if driver supports flexible parallel MAP engine decoding. If
+	/** Set if driver supports flexible parallel MAP engine decoding. If
 	 * not supported, num_maps (number of MAP engines) argument is unusable.
 	 */
 	RTE_BBDEV_TURBO_MAP_DEC = (1ULL << 14),
-	/**< Set if a device supports scatter-gather functionality */
+	/** Set if a device supports scatter-gather functionality */
 	RTE_BBDEV_TURBO_DEC_SCATTER_GATHER = (1ULL << 15),
-	/**< Set to keep CRC24B bits appended while decoding. Only usable when
+	/** Set to keep CRC24B bits appended while decoding. Only usable when
 	 * decoding Transport Blocks (code_block_mode = 0).
 	 */
 	RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP = (1ULL << 16)
 };
 
+
 /** Flags for turbo encoder operation and capability structure */
 enum rte_bbdev_op_te_flag_bitmasks {
-	/**< Ignore rv_index and set K0 = 0 */
+	/** Ignore rv_index and set K0 = 0 */
 	RTE_BBDEV_TURBO_RV_INDEX_BYPASS = (1ULL << 0),
-	/**< If rate matching is to be performed */
+	/** If rate matching is to be performed */
 	RTE_BBDEV_TURBO_RATE_MATCH = (1ULL << 1),
-	/**< This bit must be set to enable CRC-24B generation */
+	/** This bit must be set to enable CRC-24B generation */
 	RTE_BBDEV_TURBO_CRC_24B_ATTACH = (1ULL << 2),
-	/**< This bit must be set to enable CRC-24A generation */
+	/** This bit must be set to enable CRC-24A generation */
 	RTE_BBDEV_TURBO_CRC_24A_ATTACH = (1ULL << 3),
-	/**< Set if a device supports encoder dequeue interrupts */
+	/** Set if a device supports encoder dequeue interrupts */
 	RTE_BBDEV_TURBO_ENC_INTERRUPTS = (1ULL << 4),
-	/**< Set if a device supports scatter-gather functionality */
+	/** Set if a device supports scatter-gather functionality */
 	RTE_BBDEV_TURBO_ENC_SCATTER_GATHER = (1ULL << 5)
 };
 
-/**< Data input and output buffer for BBDEV operations */
+/** Flags for LDPC decoder operation and capability structure */
+enum rte_bbdev_op_ldpcdec_flag_bitmasks {
+	/** Set for transport block CRC-24A checking */
+	RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK = (1ULL << 0),
+	/** Set for code block CRC-24B checking */
+	RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK = (1ULL << 1),
+	/** Set to drop the last CRC bits decoding output */
+	RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP = (1ULL << 2),
+	/** Set for bit-level de-interleaver bypass on Rx stream. */
+	RTE_BBDEV_LDPC_DEINTERLEAVER_BYPASS = (1ULL << 3),
+	/** Set for HARQ combined input stream enable. */
+	RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE = (1ULL << 4),
+	/** Set for HARQ combined output stream enable. */
+	RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE = (1ULL << 5),
+	/** Set for LDPC decoder bypass.
+	 *  RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE must be set.
+	 */
+	RTE_BBDEV_LDPC_DECODE_BYPASS = (1ULL << 6),
+	/** Set for soft-output stream enable */
+	RTE_BBDEV_LDPC_SOFT_OUT_ENABLE = (1ULL << 7),
+	/** Set for Rate-Matching bypass on soft-out stream. */
+	RTE_BBDEV_LDPC_SOFT_OUT_RM_BYPASS = (1ULL << 8),
+	/** Set for bit-level de-interleaver bypass on soft-output stream. */
+	RTE_BBDEV_LDPC_SOFT_OUT_DEINTERLEAVER_BYPASS = (1ULL << 9),
+	/** Set for iteration stopping on successful decode condition
+	 *  i.e. a successful syndrome check.
+	 */
+	RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE = (1ULL << 10),
+	/** Set if a device supports decoder dequeue interrupts. */
+	RTE_BBDEV_LDPC_DEC_INTERRUPTS = (1ULL << 11),
+	/** Set if a device supports scatter-gather functionality. */
+	RTE_BBDEV_LDPC_DEC_SCATTER_GATHER = (1ULL << 12),
+	/** Set if a device supports input/output HARQ compression. */
+	RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION = (1ULL << 13),
+	/** Set if a device supports input LLR compression. */
+	RTE_BBDEV_LDPC_LLR_COMPRESSION = (1ULL << 14),
+	/** Set if a device supports HARQ input from
+	 *  device's internal memory.
+	 */
+	RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE = (1ULL << 15),
+	/** Set if a device supports HARQ output to
+	 *  device's internal memory.
+	 */
+	RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE = (1ULL << 16),
+	/** Set if a device supports loop-back access to
+	 *  HARQ internal memory. Intended for troubleshooting.
+	 */
+	RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK = (1ULL << 17)
+};
+
+/** Flags for LDPC encoder operation and capability structure */
+enum rte_bbdev_op_ldpcenc_flag_bitmasks {
+	/** Set for bit-level interleaver bypass on output stream. */
+	RTE_BBDEV_LDPC_INTERLEAVER_BYPASS = (1ULL << 0),
+	/** If rate matching is to be performed */
+	RTE_BBDEV_LDPC_RATE_MATCH = (1ULL << 1),
+	/** Set for transport block CRC-24A attach */
+	RTE_BBDEV_LDPC_CRC_24A_ATTACH = (1ULL << 2),
+	/** Set for code block CRC-24B attach */
+	RTE_BBDEV_LDPC_CRC_24B_ATTACH = (1ULL << 3),
+	/** Set for code block CRC-16 attach */
+	RTE_BBDEV_LDPC_CRC_16_ATTACH = (1ULL << 4),
+	/** Set if a device supports encoder dequeue interrupts. */
+	RTE_BBDEV_LDPC_ENC_INTERRUPTS = (1ULL << 5),
+	/** Set if a device supports scatter-gather functionality. */
+	RTE_BBDEV_LDPC_ENC_SCATTER_GATHER = (1ULL << 6),
+	/** Set if a device supports concatenation of non byte aligned output */
+	RTE_BBDEV_LDPC_ENC_CONCATENATION = (1ULL << 7)
+};
+
+/** Data input and output buffer for BBDEV operations */
 struct rte_bbdev_op_data {
-	/**< The mbuf data structure representing the data for BBDEV operation.
+	/** The mbuf data structure representing the data for BBDEV operation.
 	 *
 	 * This mbuf pointer can point to one Code Block (CB) data buffer or
 	 * multiple CBs contiguously located next to each other.
 	 * A Transport Block (TB) represents a whole piece of data that is
 	 * divided into one or more CBs. Maximum number of CBs can be contained
-	 * in one TB is defined by RTE_BBDEV_TURBO_MAX_CODE_BLOCKS.
+	 * in one TB is defined by RTE_BBDEV_(TURBO/LDPC)_MAX_CODE_BLOCKS.
 	 *
 	 * An mbuf data structure cannot represent more than one TB. The
 	 * smallest piece of data that can be contained in one mbuf is one CB.
@@ -145,8 +220,8 @@ struct rte_bbdev_op_data {
 	 * then it is capable of collecting (gathering) non-contiguous
 	 * (scattered) data from multiple locations in the memory.
 	 * This capability is reported by the capability flags:
-	 * - RTE_BBDEV_TURBO_ENC_SCATTER_GATHER and
-	 * - RTE_BBDEV_TURBO_DEC_SCATTER_GATHER.
+	 * - RTE_BBDEV_(TURBO/LDPC)_ENC_SCATTER_GATHER and
+	 * - RTE_BBDEV_(TURBO/LDPC)_DEC_SCATTER_GATHER.
 	 * Only if a BBDEV PMD supports this feature, chained mbuf data
 	 * structures are accepted. A chained mbuf can represent one
 	 * non-contiguous CB or multiple non-contiguous CBs.
@@ -157,7 +232,7 @@ struct rte_bbdev_op_data {
 	 * was a chained mbuf.
 	 */
 	struct rte_mbuf *data;
-	/**< The starting point of the BBDEV (encode/decode) operation,
+	/** The starting point of the BBDEV (encode/decode) operation,
 	 * in bytes.
 	 *
 	 * BBDEV starts to read data past this offset.
@@ -165,13 +240,13 @@ struct rte_bbdev_op_data {
 	 * segment.
 	 */
 	uint32_t offset;
-	/**< The total data length to be processed in one operation, in bytes.
+	/** The total data length to be processed in one operation, in bytes.
 	 *
 	 * In case the mbuf data is representing one CB, this is the length of
 	 * the CB undergoing the operation.
 	 * If it's for multiple CBs, this is the total length of those CBs
 	 * undergoing the operation.
-	 * If it's for one TB, this is the total length of the TB under
+	 * If it is for one TB, this is the total length of the TB under
 	 * operation.
 	 *
 	 * In case of chained mbuf, this data length includes the lengths of the
@@ -180,51 +255,83 @@ struct rte_bbdev_op_data {
 	uint32_t length;
 };
 
-struct rte_bbdev_op_dec_cb_params {
-	/**< The K size of the input CB, in bits [40:6144], as specified in
+/** Turbo decode code block parameters */
+struct rte_bbdev_op_dec_turbo_cb_params {
+	/** The K size of the input CB, in bits [40:6144], as specified in
 	 * 3GPP TS 36.212.
 	 * This size is inclusive of CRC bits, regardless whether it was
 	 * pre-calculated by the application or not.
 	 */
 	uint16_t k;
-	/**< The E length of the CB rate matched LLR output, in bytes, as in
+	/** The E length of the CB rate matched LLR output, in bytes, as in
 	 * 3GPP TS 36.212.
 	 */
 	uint32_t e;
 };
 
-struct rte_bbdev_op_dec_tb_params {
-	/**< The K- size of the input CB, in bits [40:6144], that is in the
+/** LDPC decode code block parameters */
+struct rte_bbdev_op_dec_ldpc_cb_params {
+	/** Rate matching output sequence length in bits or LLRs.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint32_t e;
+};
+
+/** Turbo decode transport block parameters */
+struct rte_bbdev_op_dec_turbo_tb_params {
+	/** The K- size of the input CB, in bits [40:6144], that is in the
 	 * Turbo operation when r < C-, as in 3GPP TS 36.212.
 	 */
 	uint16_t k_neg;
-	/**< The K+ size of the input CB, in bits [40:6144], that is in the
+	/** The K+ size of the input CB, in bits [40:6144], that is in the
 	 * Turbo operation when r >= C-, as in 3GPP TS 36.212.
 	 */
 	uint16_t k_pos;
-	/**< The number of CBs that have K- size, [0:63] */
+	/** The number of CBs that have K- size, [0:63] */
 	uint8_t c_neg;
-	/**< The total number of CBs in the TB, [1:RTE_BBDEV_TURBO_MAX_CODE_BLOCKS] */
+	/** The total number of CBs in the TB,
+	 * [1:RTE_BBDEV_TURBO_MAX_CODE_BLOCKS]
+	 */
 	uint8_t c;
-	/**< The number of CBs that uses Ea before switching to Eb, [0:63] */
+	/** The number of CBs that uses Ea before switching to Eb, [0:63] */
 	uint8_t cab;
-	/**< The E size of the CB rate matched output to use in the Turbo
+	/** The E size of the CB rate matched output to use in the Turbo
 	 * operation when r < cab
 	 */
 	uint32_t ea;
-	/**< The E size of the CB rate matched output to use in the Turbo
+	/** The E size of the CB rate matched output to use in the Turbo
 	 * operation when r >= cab
 	 */
 	uint32_t eb;
-	/**< The index of the first CB in the inbound mbuf data, default is 0 */
+	/** The index of the first CB in the inbound mbuf data, default is 0 */
 	uint8_t r;
 };
 
-/**< Operation structure for Turbo decode.
- * An operation can perform on one CB at a time "CB-mode".
- * An operation can perform on one or multiple CBs that are logically belonging
- * to one TB "TB-mode".
- * The provided K size parameter of the CB is its size out coming from the
+/** LDPC decode transport block parameters */
+struct rte_bbdev_op_dec_ldpc_tb_params {
+	/** Ea, length after rate matching in bits, r < cab.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint32_t ea;
+	/** Eb, length after rate matching in bits, r >= cab.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint32_t eb;
+	/** The total number of CBs in the TB or partial TB
+	 * [1:RTE_BBDEV_LDPC_MAX_CODE_BLOCKS]
+	 */
+	uint8_t c;
+	/** The index of the first CB in the inbound mbuf data, default is 0 */
+	uint8_t r;
+	/** The number of CBs that use Ea before switching to Eb, [0:63] */
+	uint8_t cab;
+};
+
+/** Operation structure for Turbo decode.
+ * An operation can be performed on one CB at a time "CB-mode".
+ * An operation can be performed on one or multiple CBs that logically
+ * belong to one TB "TB-mode".
+ * The provided K size parameter of the CB is its size coming from the
  * decode operation.
  * CRC24A/B check is requested by the application by setting the flag
  * RTE_BBDEV_TURBO_CRC_TYPE_24B for CRC24B check or CRC24A otherwise.
@@ -249,94 +356,192 @@ struct rte_bbdev_op_dec_tb_params {
  * application with enough room for the output data.
  */
 struct rte_bbdev_op_turbo_dec {
-	/**< The Virtual Circular Buffer, wk, size 3*Kpi for each CB */
+	/** The Virtual Circular Buffer, wk, size 3*Kpi for each CB */
 	struct rte_bbdev_op_data input;
-	/**< The hard decisions buffer for the decoded output,
+	/** The hard decisions buffer for the decoded output,
 	 * size K for each CB
 	 */
 	struct rte_bbdev_op_data hard_output;
-	/**< The soft LLR output buffer - optional */
+	/** The soft LLR output buffer - optional */
 	struct rte_bbdev_op_data soft_output;
 
-	uint32_t op_flags;  /**< Flags from rte_bbdev_op_td_flag_bitmasks */
-	uint8_t rv_index;  /**< Rv index for rate matching [0:3] */
-	/**< The minimum number of iterations to perform in decoding all CBs in
+	/** Flags from rte_bbdev_op_td_flag_bitmasks */
+	uint32_t op_flags;
+
+	/** Rv index for rate matching [0:3] */
+	uint8_t rv_index;
+	/** The minimum number of iterations to perform in decoding all CBs in
 	 * this operation - input
 	 */
 	uint8_t iter_min:4;
-	/**< The maximum number of iterations to perform in decoding all CBs in
+	/** The maximum number of iterations to perform in decoding all CBs in
 	 * this operation - input
 	 */
 	uint8_t iter_max:4;
-	/**< The maximum number of iterations that were perform in decoding all
-	 * CBs in this decode operation - output
+	/** The maximum number of iterations that were performed in decoding
+	 * all CBs in this decode operation - output
 	 */
 	uint8_t iter_count;
-	/**< 5 bit extrinsic scale (scale factor on extrinsic info) */
+	/** 5 bit extrinsic scale (scale factor on extrinsic info) */
 	uint8_t ext_scale;
-	/**< Number of MAP engines to use in decode,
-	 * must be power of 2 (or 0 to auto-select)
+	/** Number of MAP engines to use in decode,
+	 *  must be power of 2 (or 0 to auto-select)
 	 */
 	uint8_t num_maps;
 
-	uint8_t code_block_mode; /**< [0 - TB : 1 - CB] */
+	/**< [0 - TB : 1 - CB] */
+	uint8_t code_block_mode;
 	union {
 		/**< Struct which stores Code Block specific parameters */
-		struct rte_bbdev_op_dec_cb_params cb_params;
+		struct rte_bbdev_op_dec_turbo_cb_params cb_params;
 		/**< Struct which stores Transport Block specific parameters */
-		struct rte_bbdev_op_dec_tb_params tb_params;
+		struct rte_bbdev_op_dec_turbo_tb_params tb_params;
 	};
 };
 
+/** Operation structure for LDPC decode.
+ *
+ * An operation can be performed on one CB at a time "CB-mode".
+ * An operation can also be performed on one or multiple CBs that logically
+ * belong to a TB "TB-mode" (Currently not supported).
+ *
+ * The input encoded CB data is the Virtual Circular Buffer data stream.
+ *
+ * Each byte in the input circular buffer is the LLR value of each bit of the
+ * original CB.
+ *
+ * Hard output is a mandatory capability that all BBDEV PMDs support. This is
+ * the decoded CBs (CRC24A/B is the last 24-bit in each decoded CB).
+ *
+ * Soft output is an optional capability for BBDEV PMDs. If supported, an LLR
+ * rate matched output is computed in the soft_output buffer structure.
+ * These are A Posteriori Probabilities (APP) LLR samples for coded bits.
+ *
+ * HARQ combined output is an optional capability for BBDEV PMDs.
+ * If supported, a LLR output is streamed to the harq_combined_output
+ * buffer.
+ *
+ * HARQ combined input is an optional capability for BBDEV PMDs.
+ * If supported, a LLR input is streamed from the harq_combined_input
+ * buffer.
+ *
+ * The output mbuf data structure is expected to be allocated by the
+ * application with enough room for the output data.
+ */
+struct rte_bbdev_op_ldpc_dec {
+	/** The Virtual Circular Buffer for this code block, one LLR
+	 * per bit of the original CB.
+	 */
+	struct rte_bbdev_op_data input;
+	/** The hard decisions buffer for the decoded output,
+	 * size K for each CB
+	 */
+	struct rte_bbdev_op_data hard_output;
+	/** The soft LLR output LLR stream buffer - optional */
+	struct rte_bbdev_op_data soft_output;
+	/** The HARQ combined LLR stream input buffer - optional */
+	struct rte_bbdev_op_data harq_combined_input;
+	/** The HARQ combined LLR stream output buffer - optional */
+	struct rte_bbdev_op_data harq_combined_output;
+
+	/** Flags from rte_bbdev_op_ldpcdec_flag_bitmasks */
+	uint32_t op_flags;
+
+	/** Rate matching redundancy version
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint8_t rv_index;
+	/** The maximum number of iterations to perform in decoding CB in
+	 *  this operation - input
+	 */
+	uint8_t iter_max;
+	/** The number of iterations that were performed in decoding
+	 * CB in this decode operation - output
+	 */
+	uint8_t iter_count;
+	/** 1: LDPC Base graph 1, 2: LDPC Base graph 2.
+	 * [3GPP TS38.212, section 5.2.2]
+	 */
+	uint8_t basegraph;
+	/** Zc, LDPC lifting size.
+	 *  [3GPP TS38.212, section 5.2.2]
+	 */
+	uint16_t z_c;
+	/** Ncb, length of the circular buffer in bits.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint16_t n_cb;
+	/** Qm, modulation order {1,2,4,6,8}.
+	 *  [3GPP TS38.212, section 5.4.2.2]
+	 */
+	uint8_t q_m;
+	/** Number of Filler bits, n_filler = K – K’
+	 *  [3GPP TS38.212 section 5.2.2]
+	 */
+	uint16_t n_filler;
+	/** [0 - TB : 1 - CB] */
+	uint8_t code_block_mode;
+	union {
+		/** Struct which stores Code Block specific parameters */
+		struct rte_bbdev_op_dec_ldpc_cb_params cb_params;
+		/** Struct which stores Transport Block specific parameters */
+		struct rte_bbdev_op_dec_ldpc_tb_params tb_params;
+	};
+};
+
+/** Turbo encode code block parameters */
 struct rte_bbdev_op_enc_turbo_cb_params {
-	/**< The K size of the input CB, in bits [40:6144], as specified in
+	/** The K size of the input CB, in bits [40:6144], as specified in
 	 * 3GPP TS 36.212.
 	 * This size is inclusive of CRC24A, regardless whether it was
 	 * pre-calculated by the application or not.
 	 */
 	uint16_t k;
-	/**< The E length of the CB rate matched output, in bits, as in
+	/** The E length of the CB rate matched output, in bits, as in
 	 * 3GPP TS 36.212.
 	 */
 	uint32_t e;
-	/**< The Ncb soft buffer size of the CB rate matched output [K:3*Kpi],
+	/** The Ncb soft buffer size of the CB rate matched output [K:3*Kpi],
 	 * in bits, as specified in 3GPP TS 36.212.
 	 */
 	uint16_t ncb;
 };
 
+/** Turbo encode transport block parameters */
 struct rte_bbdev_op_enc_turbo_tb_params {
-	/**< The K- size of the input CB, in bits [40:6144], that is in the
+	/** The K- size of the input CB, in bits [40:6144], that is in the
 	 * Turbo operation when r < C-, as in 3GPP TS 36.212.
 	 * This size is inclusive of CRC24B, regardless whether it was
 	 * pre-calculated and appended by the application or not.
 	 */
 	uint16_t k_neg;
-	/**< The K+ size of the input CB, in bits [40:6144], that is in the
+	/** The K+ size of the input CB, in bits [40:6144], that is in the
 	 * Turbo operation when r >= C-, as in 3GPP TS 36.212.
 	 * This size is inclusive of CRC24B, regardless whether it was
 	 * pre-calculated and appended by the application or not.
 	 */
 	uint16_t k_pos;
-	/**< The number of CBs that have K- size, [0:63] */
+	/** The number of CBs that have K- size, [0:63] */
 	uint8_t c_neg;
-	/**< The total number of CBs in the TB, [1:RTE_BBDEV_TURBO_MAX_CODE_BLOCKS] */
+	/** The total number of CBs in the TB,
+	 * [1:RTE_BBDEV_TURBO_MAX_CODE_BLOCKS]
+	 */
 	uint8_t c;
-	/**< The number of CBs that uses Ea before switching to Eb, [0:63] */
+	/** The number of CBs that uses Ea before switching to Eb, [0:63] */
 	uint8_t cab;
-	/**< The E size of the CB rate matched output to use in the Turbo
+	/** The E size of the CB rate matched output to use in the Turbo
 	 * operation when r < cab
 	 */
 	uint32_t ea;
-	/**< The E size of the CB rate matched output to use in the Turbo
+	/** The E size of the CB rate matched output to use in the Turbo
 	 * operation when r >= cab
 	 */
 	uint32_t eb;
-	/**< The Ncb soft buffer size for the rate matched CB that is used in
+	/** The Ncb soft buffer size for the rate matched CB that is used in
 	 * the Turbo operation when r < C-, [K:3*Kpi]
 	 */
 	uint16_t ncb_neg;
-	/**< The Ncb soft buffer size for the rate matched CB that is used in
+	/** The Ncb soft buffer size for the rate matched CB that is used in
 	 * the Turbo operation when r >= C-, [K:3*Kpi]
 	 */
 	uint16_t ncb_pos;
@@ -344,10 +549,38 @@ struct rte_bbdev_op_enc_turbo_tb_params {
 	uint8_t r;
 };
 
-/**< Operation structure for Turbo encode.
- * An operation can perform on one CB at a time "CB-mode".
- * An operation can perform on one or multiple CBs that are logically
- * belonging to one TB "TB-mode".
+/** LDPC encode code block parameters */
+struct rte_bbdev_op_enc_ldpc_cb_params {
+	/** E, length after rate matching in bits.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint32_t e;
+};
+
+/** LDPC encode transport block parameters */
+struct rte_bbdev_op_enc_ldpc_tb_params {
+	/** Ea, length after rate matching in bits, r < cab.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint32_t ea;
+	/** Eb, length after rate matching in bits, r >= cab.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint32_t eb;
+	/** The total number of CBs in the TB or partial TB
+	 * [1:RTE_BBDEV_LDPC_MAX_CODE_BLOCKS]
+	 */
+	uint8_t c;
+	/** The index of the first CB in the inbound mbuf data, default is 0 */
+	uint8_t r;
+	/** The number of CBs that use Ea before switching to Eb, [0:63] */
+	uint8_t cab;
+};
+
+/** Operation structure for Turbo encode.
+ * An operation can be performed on one CB at a time "CB-mode".
+ * An operation can pbe erformd on one or multiple CBs that logically
+ * belong to one TB "TB-mode".
  *
  * In CB-mode, CRC24A/B is an optional operation. K size parameter is not
  * affected by CRC24A/B inclusion, this only affects the inbound mbuf data
@@ -364,44 +597,131 @@ struct rte_bbdev_op_enc_turbo_tb_params {
  * application with enough room for the output data.
  */
 struct rte_bbdev_op_turbo_enc {
-	/**< The input CB or TB data */
+	/** The input CB or TB data */
 	struct rte_bbdev_op_data input;
-	/**< The rate matched CB or TB output buffer */
+	/** The rate matched CB or TB output buffer */
 	struct rte_bbdev_op_data output;
+	/** Flags from rte_bbdev_op_te_flag_bitmasks */
+	uint32_t op_flags;
 
-	uint32_t op_flags;  /**< Flags from rte_bbdev_op_te_flag_bitmasks */
-	uint8_t rv_index;  /**< Rv index for rate matching [0:3] */
-
-	uint8_t code_block_mode; /**< [0 - TB : 1 - CB] */
+	/** Rv index for rate matching [0:3] */
+	uint8_t rv_index;
+	/** [0 - TB : 1 - CB] */
+	uint8_t code_block_mode;
 	union {
-		/**< Struct which stores Code Block specific parameters */
+		/** Struct which stores Code Block specific parameters */
 		struct rte_bbdev_op_enc_turbo_cb_params cb_params;
-		/**< Struct which stores Transport Block specific parameters */
+		/** Struct which stores Transport Block specific parameters */
 		struct rte_bbdev_op_enc_turbo_tb_params tb_params;
 	};
 };
 
-/**< List of the capabilities for the Turbo Decoder */
+/** Operation structure for LDPC encode.
+ * An operation can be performed on one CB at a time "CB-mode".
+ * An operation can be performed on one or multiple CBs that logically
+ * belong to a TB "TB-mode".
+ *
+ * The input data is the CB or TB input to the decoder.
+ *
+ * The output data is the ratematched CB or TB data, or the output after
+ * bit-selection if RTE_BBDEV_LDPC_INTERLEAVER_BYPASS is set.
+ *
+ * The output mbuf data structure is expected to be allocated by the
+ * application with enough room for the output data.
+ */
+struct rte_bbdev_op_ldpc_enc {
+	/** The input TB or CB data */
+	struct rte_bbdev_op_data input;
+	/** The rate matched TB or CB output buffer */
+	struct rte_bbdev_op_data output;
+
+	/** Flags from rte_bbdev_op_ldpcenc_flag_bitmasks */
+	uint32_t op_flags;
+
+	/** Rate matching redundancy version */
+	uint8_t rv_index;
+	/** 1: LDPC Base graph 1, 2: LDPC Base graph 2.
+	 *  [3GPP TS38.212, section 5.2.2]
+	 */
+	uint8_t basegraph;
+	/** Zc, LDPC lifting size.
+	 *  [3GPP TS38.212, section 5.2.2]
+	 */
+	uint16_t z_c;
+	/** Ncb, length of the circular buffer in bits.
+	 *  [3GPP TS38.212, section 5.4.2.1]
+	 */
+	uint16_t n_cb;
+	/** Qm, modulation order {2,4,6,8,10}.
+	 *  [3GPP TS38.212, section 5.4.2.2]
+	 */
+	uint8_t q_m;
+	/** Number of Filler bits, n_filler = K – K’
+	 *  [3GPP TS38.212 section 5.2.2]
+	 */
+	uint16_t n_filler;
+	/** [0 - TB : 1 - CB] */
+	uint8_t code_block_mode;
+	union {
+		/** Struct which stores Code Block specific parameters */
+		struct rte_bbdev_op_enc_ldpc_cb_params cb_params;
+		/** Struct which stores Transport Block specific parameters */
+		struct rte_bbdev_op_enc_ldpc_tb_params tb_params;
+	};
+};
+
+/** List of the capabilities for the Turbo Decoder */
 struct rte_bbdev_op_cap_turbo_dec {
-	/**< Flags from rte_bbdev_op_td_flag_bitmasks */
+	/** Flags from rte_bbdev_op_td_flag_bitmasks */
 	uint32_t capability_flags;
 	/** Maximal LLR absolute value. Acceptable LLR values lie in range
 	 * [-max_llr_modulus, max_llr_modulus].
 	 */
 	int8_t max_llr_modulus;
+	/** Num input code block buffers */
 	uint8_t num_buffers_src;  /**< Num input code block buffers */
-	/**< Num hard output code block buffers */
+	/** Num hard output code block buffers */
 	uint8_t num_buffers_hard_out;
-	/**< Num soft output code block buffers if supported by the driver */
+	/** Num soft output code block buffers if supported by the driver */
 	uint8_t num_buffers_soft_out;
 };
 
-/**< List of the capabilities for the Turbo Encoder */
+/** List of the capabilities for the Turbo Encoder */
 struct rte_bbdev_op_cap_turbo_enc {
-	/**< Flags from rte_bbdev_op_te_flag_bitmasks */
+	/** Flags from rte_bbdev_op_te_flag_bitmasks */
 	uint32_t capability_flags;
-	uint8_t num_buffers_src;  /**< Num input code block buffers */
-	uint8_t num_buffers_dst;  /**< Num output code block buffers */
+	/** Num input code block buffers */
+	uint8_t num_buffers_src;
+	/** Num output code block buffers */
+	uint8_t num_buffers_dst;
+};
+
+/** List of the capabilities for the LDPC Decoder */
+struct rte_bbdev_op_cap_ldpc_dec {
+	/** Flags from rte_bbdev_op_ldpcdec_flag_bitmasks */
+	uint32_t capability_flags;
+	/** LLR size in bits. LLR is a two’s complement number. */
+	int8_t llr_size;
+	/** LLR numbers of decimals bit for arithmetic representation */
+	int8_t llr_decimals;
+	/** Amount of memory for HARQ in external DDR in MB */
+	uint16_t harq_memory_size;
+	/** Num input code block buffers */
+	uint16_t num_buffers_src;
+	/** Num hard output code block buffers */
+	uint16_t num_buffers_hard_out;
+	/** Num soft output code block buffers if supported by the driver */
+	uint16_t num_buffers_soft_out;
+};
+
+/** List of the capabilities for the LDPC Encoder */
+struct rte_bbdev_op_cap_ldpc_enc {
+	/** Flags from rte_bbdev_op_ldpcenc_flag_bitmasks */
+	uint32_t capability_flags;
+	/** Num input code block buffers */
+	uint16_t num_buffers_src;
+	/** Num output code block buffers */
+	uint16_t num_buffers_dst;
 };
 
 /** Different operation types supported by the device */
@@ -409,40 +729,59 @@ enum rte_bbdev_op_type {
 	RTE_BBDEV_OP_NONE,  /**< Dummy operation that does nothing */
 	RTE_BBDEV_OP_TURBO_DEC,  /**< Turbo decode */
 	RTE_BBDEV_OP_TURBO_ENC,  /**< Turbo encode */
+	RTE_BBDEV_OP_LDPC_DEC,  /**< LDPC decode */
+	RTE_BBDEV_OP_LDPC_ENC,  /**< LDPC encode */
 	RTE_BBDEV_OP_TYPE_COUNT,  /**< Count of different op types */
 };
 
-/**< Bit indexes of possible errors reported through status field */
+/** Bit indexes of possible errors reported through status field */
 enum {
 	RTE_BBDEV_DRV_ERROR,
 	RTE_BBDEV_DATA_ERROR,
 	RTE_BBDEV_CRC_ERROR,
+	RTE_BBDEV_SYNDROME_ERROR
 };
 
-/**< Structure specifying a single encode operation */
+/** Structure specifying a single encode operation */
 struct rte_bbdev_enc_op {
-	int status;  /**< Status of operation that was performed */
-	struct rte_mempool *mempool;  /**< Mempool which op instance is in */
-	void *opaque_data;  /**< Opaque pointer for user data */
-	/**< Contains encoder specific parameters */
-	struct rte_bbdev_op_turbo_enc turbo_enc;
+	/**< Status of operation that was performed */
+	int status;
+	/**< Mempool which op instance is in */
+	struct rte_mempool *mempool;
+	/**< Opaque pointer for user data */
+	void *opaque_data;
+	union {
+		/** Contains turbo decoder specific parameters */
+		struct rte_bbdev_op_turbo_enc turbo_enc;
+		/** Contains LDPC decoder specific parameters */
+		struct rte_bbdev_op_ldpc_enc ldpc_enc;
+	};
 };
 
-/**< Structure specifying a single decode operation */
+/** Structure specifying a single decode operation */
 struct rte_bbdev_dec_op {
-	int status;  /**< Status of operation that was performed */
-	struct rte_mempool *mempool;  /**< Mempool which op instance is in */
-	void *opaque_data;  /**< Opaque pointer for user data */
-	/**< Contains decoder specific parameters */
-	struct rte_bbdev_op_turbo_dec turbo_dec;
+	/** Status of operation that was performed */
+	int status;
+	/** Mempool which op instance is in */
+	struct rte_mempool *mempool;
+	/** Opaque pointer for user data */
+	void *opaque_data;
+	union {
+		/** Contains turbo decoder specific parameters */
+		struct rte_bbdev_op_turbo_dec turbo_dec;
+		/** Contains LDPC decoder specific parameters */
+		struct rte_bbdev_op_ldpc_dec ldpc_dec;
+	};
 };
 
-/**< Operation capabilities supported by a device */
+/** Operation capabilities supported by a device */
 struct rte_bbdev_op_cap {
 	enum rte_bbdev_op_type type;  /**< Type of operation */
 	union {
 		struct rte_bbdev_op_cap_turbo_dec turbo_dec;
 		struct rte_bbdev_op_cap_turbo_enc turbo_enc;
+		struct rte_bbdev_op_cap_ldpc_dec ldpc_dec;
+		struct rte_bbdev_op_cap_ldpc_enc ldpc_enc;
 	} cap;  /**< Operation-type specific capabilities */
 };
 
@@ -516,7 +855,8 @@ struct rte_mempool *
 	/* Check type */
 	priv = (struct rte_bbdev_op_pool_private *)
 			rte_mempool_get_priv(mempool);
-	if (unlikely(priv->type != RTE_BBDEV_OP_TURBO_ENC))
+	if (unlikely((priv->type != RTE_BBDEV_OP_TURBO_ENC) &&
+					(priv->type != RTE_BBDEV_OP_LDPC_ENC)))
 		return -EINVAL;
 
 	/* Get elements */
@@ -552,7 +892,8 @@ struct rte_mempool *
 	/* Check type */
 	priv = (struct rte_bbdev_op_pool_private *)
 			rte_mempool_get_priv(mempool);
-	if (unlikely(priv->type != RTE_BBDEV_OP_TURBO_DEC))
+	if (unlikely((priv->type != RTE_BBDEV_OP_TURBO_DEC) &&
+					(priv->type != RTE_BBDEV_OP_LDPC_DEC)))
 		return -EINVAL;
 
 	/* Get elements */
-- 
1.8.3.1


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH] ether: mark ethernet addresses as being 2-byte aligned
  2019-07-01 14:14  5%     ` Olivier Matz
@ 2019-07-01 14:28  0%       ` Bruce Richardson
  0 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2019-07-01 14:28 UTC (permalink / raw)
  To: Olivier Matz; +Cc: Stephen Hemminger, DPDK Dev List

On Mon, Jul 01, 2019 at 04:14:30PM +0200, Olivier Matz wrote:
> Hi Bruce,
> 
> On Mon, Jul 01, 2019 at 02:38:43PM +0100, Bruce Richardson wrote:
> > On Mon, Jul 01, 2019 at 03:11:12PM +0200, Olivier Matz wrote:
> > > Hi Bruce,
> > > 
> > > On Thu, May 16, 2019 at 04:54:57PM +0100, Bruce Richardson wrote:
> > > > When including the rte_ether.h header in applications with warnings
> > > > enabled, a warning was given because of the assumption of 2-byte
> > > > alignment of ethernet addresses when processing them.
> > > > 
> > > > .../include/rte_ether.h:149:2: warning: converting a packed ‘const
> > > > struct ether_addr’ pointer (alignment 1) to a ‘unaligned_uint16_t’
> > > > {aka ‘const short unsigned int’} pointer (alignment 2) may result
> > > > in an unaligned pointer value [-Waddress-of-packed-member] 149 |
> > > > const unaligned_uint16_t *ea_words = (const unaligned_uint16_t
> > > > *)ea; |  ^~~~~
> > > > 
> > > > Since ethernet addresses should always be aligned on a two-byte
> > > > boundary,
> > > 
> > > I'm a bit reserved about this last assumption. The ethernet address
> > > structure may be used in a private structure, whose alignment is 1.
> > > Are we sure that there is no (funny) protocol that carries unaligned
> > > ethernet addresses?
> > > 
> > > Shouldn't we change the definition of unaligned_uint16_t instead?  Or
> > > change the rte_is_broadcast_ether_addr() function?
> > > 
> > 
> > We could, but I believe the correct behaviour is to make the addresses
> > always 2-byte aligned, unless someone actually has a real-world case
> > where there is a protocol that doesn't have the data 2-byte aligned.
> 
> Maybe you missed that part of my previous answer, I'm copy it again here:
> 
>   > Although this is an ABI break, the network structures are all being
>   > renamed in this release, and a deprecation notice was previously
>   > posted for it.
> 
>   Yes, but the network renaming is identified in the release note as an
>   API break, not an ABI break.
> 
> I thought we agreed to limit ABI breakages to cases where there is no
> other solution. Here, this is surely a "small" ABI breakage, but I
> suppose there is a way to do differently.
> 
> If we really want to do that way, it's better to announce it as an ABI
> break.
>
At this stage, I'm ok with pushing this to 19.11 to follow the official
deprecation process. 

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] ether: mark ethernet addresses as being 2-byte aligned
  @ 2019-07-01 14:14  5%     ` Olivier Matz
  2019-07-01 14:28  0%       ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Olivier Matz @ 2019-07-01 14:14 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: Stephen Hemminger, DPDK Dev List

Hi Bruce,

On Mon, Jul 01, 2019 at 02:38:43PM +0100, Bruce Richardson wrote:
> On Mon, Jul 01, 2019 at 03:11:12PM +0200, Olivier Matz wrote:
> > Hi Bruce,
> > 
> > On Thu, May 16, 2019 at 04:54:57PM +0100, Bruce Richardson wrote:
> > > When including the rte_ether.h header in applications with warnings
> > > enabled, a warning was given because of the assumption of 2-byte alignment
> > > of ethernet addresses when processing them.
> > > 
> > > .../include/rte_ether.h:149:2: warning: converting a packed ‘const
> > >   struct ether_addr’ pointer (alignment 1) to a ‘unaligned_uint16_t’
> > >   {aka ‘const short unsigned int’} pointer (alignment 2) may result in
> > >   an unaligned pointer value [-Waddress-of-packed-member]
> > > 149 |  const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea;
> > >     |  ^~~~~
> > > 
> > > Since ethernet addresses should always be aligned on a two-byte boundary,
> > 
> > I'm a bit reserved about this last assumption. The ethernet address
> > structure may be used in a private structure, whose alignment is 1. Are
> > we sure that there is no (funny) protocol that carries unaligned
> > ethernet addresses?
> > 
> > Shouldn't we change the definition of unaligned_uint16_t instead?
> > Or change the rte_is_broadcast_ether_addr() function?
> > 
> 
> We could, but I believe the correct behaviour is to make the addresses
> always 2-byte aligned, unless someone actually has a real-world case where
> there is a protocol that doesn't have the data 2-byte aligned.

Maybe you missed that part of my previous answer, I'm copy it again here:

  > Although this is an ABI break, the network structures are all being renamed
  > in this release, and a deprecation notice was previously posted for it.

  Yes, but the network renaming is identified in the release note as an
  API break, not an ABI break.

I thought we agreed to limit ABI breakages to cases where there is no
other solution. Here, this is surely a "small" ABI breakage, but I
suppose there is a way to do differently.

If we really want to do that way, it's better to announce it as an ABI
break.

Olivier

^ permalink raw reply	[relevance 5%]

* Re: [dpdk-dev] [PATCH] ether: mark ethernet addresses as being 2-byte aligned
  @ 2019-07-01 13:11  3% ` Olivier Matz
    0 siblings, 1 reply; 200+ results
From: Olivier Matz @ 2019-07-01 13:11 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: Stephen Hemminger, DPDK Dev List

Hi Bruce,

On Thu, May 16, 2019 at 04:54:57PM +0100, Bruce Richardson wrote:
> When including the rte_ether.h header in applications with warnings
> enabled, a warning was given because of the assumption of 2-byte alignment
> of ethernet addresses when processing them.
> 
> .../include/rte_ether.h:149:2: warning: converting a packed ‘const
>   struct ether_addr’ pointer (alignment 1) to a ‘unaligned_uint16_t’
>   {aka ‘const short unsigned int’} pointer (alignment 2) may result in
>   an unaligned pointer value [-Waddress-of-packed-member]
> 149 |  const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea;
>     |  ^~~~~
> 
> Since ethernet addresses should always be aligned on a two-byte boundary,

I'm a bit reserved about this last assumption. The ethernet address
structure may be used in a private structure, whose alignment is 1. Are
we sure that there is no (funny) protocol that carries unaligned
ethernet addresses?

Shouldn't we change the definition of unaligned_uint16_t instead?
Or change the rte_is_broadcast_ether_addr() function?


> we can just inform the compiler of this assumption to remove the warnings
> and allow us to always access the addresses using 16-bit operations.
> 
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> 
> ---
> 
> Although this is an ABI break, the network structures are all being renamed
> in this release, and a deprecation notice was previously posted for it.

Yes, but the network renaming is identified in the release note as an
API break, not an ABI break.


> ---
>  lib/librte_net/rte_ether.h | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
> index 3a87ff184..8090b7c01 100644
> --- a/lib/librte_net/rte_ether.h
> +++ b/lib/librte_net/rte_ether.h
> @@ -55,7 +55,8 @@ extern "C" {
>   * See http://standards.ieee.org/regauth/groupmac/tutorial.html
>   */
>  struct ether_addr {
> -	uint8_t addr_bytes[ETHER_ADDR_LEN]; /**< Addr bytes in tx order */
> +	/** Addr bytes in tx order */
> +	uint8_t addr_bytes[ETHER_ADDR_LEN] __rte_aligned(2);
>  } __attribute__((__packed__));
>  
>  #define ETHER_LOCAL_ADMIN_ADDR 0x02 /**< Locally assigned Eth. address. */
> -- 
> 2.21.0
> 

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v3] ethdev: support QinQ strip dynamic configuration
  2019-07-01 10:07  0%     ` Andrew Rybchenko
@ 2019-07-01 13:05  0%       ` Ferruh Yigit
  0 siblings, 0 replies; 200+ results
From: Ferruh Yigit @ 2019-07-01 13:05 UTC (permalink / raw)
  To: Andrew Rybchenko, viveksharma, thomas
  Cc: dev, intoviveksharma, stephen, ramirose, Jerin Jacob Kollanukkaran

On 7/1/2019 11:07 AM, Andrew Rybchenko wrote:
> On 27.06.2019 14:08, Ferruh Yigit wrote:
>> On 4/19/2019 6:59 AM, viveksharma@marvell.com wrote:
>>> From: Vivek Sharma <viveksharma@marvell.com>
>>>
>>> Enable missing support for runtime configuration (setting/getting)
>>> of QinQ strip rx offload for a given ethdev.
>>>
>>> Signed-off-by: Vivek Sharma <viveksharma@marvell.com>
>> <...>
>>
>>> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
>>> index 40a068f..c1792f4 100644
>>> --- a/lib/librte_ethdev/rte_ethdev.h
>>> +++ b/lib/librte_ethdev/rte_ethdev.h
>>> @@ -550,11 +550,13 @@ struct rte_eth_rss_conf {
>>>   #define ETH_VLAN_STRIP_OFFLOAD   0x0001 /**< VLAN Strip  On/Off */
>>>   #define ETH_VLAN_FILTER_OFFLOAD  0x0002 /**< VLAN Filter On/Off */
>>>   #define ETH_VLAN_EXTEND_OFFLOAD  0x0004 /**< VLAN Extend On/Off */
>>> +#define ETH_QINQ_STRIP_OFFLOAD   0x0008 /**< QINQ Strip On/Off */
>>>   
>>>   /* Definitions used for mask VLAN setting */
>>>   #define ETH_VLAN_STRIP_MASK   0x0001 /**< VLAN Strip  setting mask */
>>>   #define ETH_VLAN_FILTER_MASK  0x0002 /**< VLAN Filter  setting mask*/
>>>   #define ETH_VLAN_EXTEND_MASK  0x0004 /**< VLAN Extend  setting mask*/
>>> +#define ETH_QINQ_STRIP_MASK   0x0008 /**< QINQ Strip  setting mask */
>>>   #define ETH_VLAN_ID_MAX       0x0FFF /**< VLAN ID is in lower 12 bits*/
>> On its own patch looks ok but a few high level questions:
>>
>> 1- Why we need this interim defines, instead of using actual offload values?
>> Although changing this will be API/ABI breakage.
>>
>> 2- Why we have specific function to set vlan offloads, for other offloads the
>> way is stop device and reconfigure it with new offload flags.
>>
>> 3- If devices can change offload configuration dynamically, do we need a generic
>> API to alter the offload configs? (similar to these vlan APIs but more generic)?
> 
> If dynamic switching of offloads is really required, I think it would be
> good if it is unified. If so, we can deprecate
> rte_eth_dev_{s,g}et_vlan_offload() and implement it using the new one
> to remove the old one from driver interface at least.
> It requires reporting of dynamically switchable offloads on device and
> queue level. Or just dynamically switchable offloads in assumption that
> if the offload is supported on queue level and dynamically switchable,
> it is dynamically switchable on queue level.

Not sure if "dynamic switching of offloads" required, but I agree we may need to
add "dynamically switchable offload" reporting for that.

> 
>> Related to the patch, what do you think about following options:
>> a)
>> - Get this patch
>> - Send a deprecation notice for 1) in this release
>> - Next release remove these flags, which will be practically reverse this patch
>> and more
>>
>> b)
>> - Send a deprecation notice for 1) in this release
>> - Next release update the APIs and a smaller/different version of this patch
>> will be required.
> 
> I'm OK with both options, but I think it would be fair to go (a) to avoid
> postponing of the feature too long.

OK

> 
> The patch itself should update rte_eth_dev_{s,g}et_vlan_offload()
> descriptions which enumerate switchable offloads.

+1

@Vivek, can you please send a new version with this update?



^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 10/10] doc: announce bbdev changes
  2019-06-24  2:52  8%   ` [dpdk-dev] [PATCH v4 10/10] doc: announce bbdev changes Nicolas Chautru
  2019-06-30 23:04  0%     ` Mokhtar, Amr
@ 2019-07-01 11:14  4%     ` Akhil Goyal
  2019-07-01 18:14  3%       ` Chautru, Nicolas
  1 sibling, 1 reply; 200+ results
From: Akhil Goyal @ 2019-07-01 11:14 UTC (permalink / raw)
  To: Nicolas Chautru, dev; +Cc: thomas, ferruh.yigit, amr.mokhtar

Hi Nicolas,

> 
> Update of the release notes for BBDEV features add
> and extension of ABI in previous commit.
> 
> Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
> ---
>  doc/guides/rel_notes/release_19_08.rst | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/doc/guides/rel_notes/release_19_08.rst
> b/doc/guides/rel_notes/release_19_08.rst
> index 8c3932d..35d3a09 100644
> --- a/doc/guides/rel_notes/release_19_08.rst
> +++ b/doc/guides/rel_notes/release_19_08.rst
> @@ -88,6 +88,19 @@ New Features
>    * Added multi-queue support to allow one af_xdp vdev with multiple netdev
>      queues
> 
> +* **Added a FPGA_LTE_FEC bbdev PMD.**
> +
> +  Added the new ``fpga_lte_fec`` bbdev driver for the Intel® FPGA PAC
> +  (Programmable  Acceleration Card) N3000.  See the
> +  :doc:`../bbdevs/fpga_lte_fec` BBDEV guide for more details on this new driver.
> +
> +* **Updated TURBO_SW bbdev PMD.**
> +
> +  Updated the ``turbo_sw`` bbdev driver with changes including:
> +
> +  * Added option to build the driver with or without dependency of external
> +    SDK libraries.
> +  * Added support for 5GNR encode/decode operations.
> 
>  Removed Items
>  -------------
> @@ -140,6 +153,8 @@ ABI Changes
>     Also, make sure to start the actual text at the margin.
>     =========================================================
> 
> +* bbdev: New parameters added to support 5GNR operations.
> +
> 
>  Shared Library Versions
>  -----------------------
> --
> 1.8.3.1

Release note changes should be part of the same patch which is adding that change.

One more thing, if there is a change in ABI, should you also increment the bbdev ABI version?

Please also send a rebased version of your patchset, so that builds can be verified by CI. The dependent patches are applied on the sub-tree.

-Akhil


^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v3] ethdev: support QinQ strip dynamic configuration
  2019-06-27 11:08  3%   ` Ferruh Yigit
@ 2019-07-01 10:07  0%     ` Andrew Rybchenko
  2019-07-01 13:05  0%       ` Ferruh Yigit
  0 siblings, 1 reply; 200+ results
From: Andrew Rybchenko @ 2019-07-01 10:07 UTC (permalink / raw)
  To: Ferruh Yigit, viveksharma, thomas
  Cc: dev, intoviveksharma, stephen, ramirose, Jerin Jacob Kollanukkaran

On 27.06.2019 14:08, Ferruh Yigit wrote:
> On 4/19/2019 6:59 AM, viveksharma@marvell.com wrote:
>> From: Vivek Sharma <viveksharma@marvell.com>
>>
>> Enable missing support for runtime configuration (setting/getting)
>> of QinQ strip rx offload for a given ethdev.
>>
>> Signed-off-by: Vivek Sharma <viveksharma@marvell.com>
> <...>
>
>> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
>> index 40a068f..c1792f4 100644
>> --- a/lib/librte_ethdev/rte_ethdev.h
>> +++ b/lib/librte_ethdev/rte_ethdev.h
>> @@ -550,11 +550,13 @@ struct rte_eth_rss_conf {
>>   #define ETH_VLAN_STRIP_OFFLOAD   0x0001 /**< VLAN Strip  On/Off */
>>   #define ETH_VLAN_FILTER_OFFLOAD  0x0002 /**< VLAN Filter On/Off */
>>   #define ETH_VLAN_EXTEND_OFFLOAD  0x0004 /**< VLAN Extend On/Off */
>> +#define ETH_QINQ_STRIP_OFFLOAD   0x0008 /**< QINQ Strip On/Off */
>>   
>>   /* Definitions used for mask VLAN setting */
>>   #define ETH_VLAN_STRIP_MASK   0x0001 /**< VLAN Strip  setting mask */
>>   #define ETH_VLAN_FILTER_MASK  0x0002 /**< VLAN Filter  setting mask*/
>>   #define ETH_VLAN_EXTEND_MASK  0x0004 /**< VLAN Extend  setting mask*/
>> +#define ETH_QINQ_STRIP_MASK   0x0008 /**< QINQ Strip  setting mask */
>>   #define ETH_VLAN_ID_MAX       0x0FFF /**< VLAN ID is in lower 12 bits*/
> On its own patch looks ok but a few high level questions:
>
> 1- Why we need this interim defines, instead of using actual offload values?
> Although changing this will be API/ABI breakage.
>
> 2- Why we have specific function to set vlan offloads, for other offloads the
> way is stop device and reconfigure it with new offload flags.
>
> 3- If devices can change offload configuration dynamically, do we need a generic
> API to alter the offload configs? (similar to these vlan APIs but more generic)?

If dynamic switching of offloads is really required, I think it would be
good if it is unified. If so, we can deprecate
rte_eth_dev_{s,g}et_vlan_offload() and implement it using the new one
to remove the old one from driver interface at least.
It requires reporting of dynamically switchable offloads on device and
queue level. Or just dynamically switchable offloads in assumption that
if the offload is supported on queue level and dynamically switchable,
it is dynamically switchable on queue level.

> Related to the patch, what do you think about following options:
> a)
> - Get this patch
> - Send a deprecation notice for 1) in this release
> - Next release remove these flags, which will be practically reverse this patch
> and more
>
> b)
> - Send a deprecation notice for 1) in this release
> - Next release update the APIs and a smaller/different version of this patch
> will be required.

I'm OK with both options, but I think it would be fair to go (a) to avoid
postponing of the feature too long.

The patch itself should update rte_eth_dev_{s,g}et_vlan_offload()
descriptions which enumerate switchable offloads.

Andrew.

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 10/10] doc: announce bbdev changes
  2019-06-24  2:52  8%   ` [dpdk-dev] [PATCH v4 10/10] doc: announce bbdev changes Nicolas Chautru
@ 2019-06-30 23:04  0%     ` Mokhtar, Amr
  2019-07-01 11:14  4%     ` Akhil Goyal
  1 sibling, 0 replies; 200+ results
From: Mokhtar, Amr @ 2019-06-30 23:04 UTC (permalink / raw)
  To: Chautru, Nicolas, akhil.goyal, dev; +Cc: thomas, Yigit, Ferruh


> -----Original Message-----
> From: Chautru, Nicolas
> Sent: Monday 24 June 2019 03:53
> To: akhil.goyal@nxp.com; dev@dpdk.org
> Cc: thomas@monjalon.net; Yigit, Ferruh <ferruh.yigit@intel.com>;
> Mokhtar, Amr <amr.mokhtar@intel.com>; Chautru, Nicolas
> <nicolas.chautru@intel.com>
> Subject: [PATCH v4 10/10] doc: announce bbdev changes
> 
> Update of the release notes for BBDEV features add
> and extension of ABI in previous commit.
> 
> Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
> ---

Acked-by: Amr Mokhtar <amr.mokhtar@intel.com>

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 3/4] eal: allow checking CPU flags by name
  @ 2019-06-28 13:34  3%       ` David Marchand
  0 siblings, 0 replies; 200+ results
From: David Marchand @ 2019-06-28 13:34 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev

On Fri, Jun 28, 2019 at 2:40 PM Bruce Richardson <bruce.richardson@intel.com>
wrote:

> On Thu, Jun 27, 2019 at 03:22:14PM +0200, David Marchand wrote:
> >    On Wed, May 29, 2019 at 5:42 PM Bruce Richardson
> >    <[1]bruce.richardson@intel.com> wrote:
> >
> >      Rather than using enum values for CPU flags, which means the symbols
> >      don't
> >      exist on other architectures, provide a flag lookup by name,
> >      allowing us to
> >      unconditionally check for a CPU flag.
> >
> >    Did you consider passing a string for the CPU architecture rather than
> >    an enum?
> >    It would have to be compared to RTE_ARCH in
> >    rte_cpu_get_flagname_enabled.
> >    Or to accomodate with x86_64/i686, this could be a cpu arch family.
> >    This avoids adding a new C type that seems quite limited wrt its uses.
> >    --
> >    David Marchand
> >
>
> I'm not sure I really see the value in having string names for the
> architecture values, I think it would be a lot more clunky to manage rather
> than having an enum value. The key difference vs the flags is that the
> flags are only valid per-architecture while the architecture defines can be
> globally valid, and secondly there is a finite, and small, number of
> architectures compared to the number of flags supported.
>
> If you feel strongly about it I can investigate it, but I'm not sure I see
> the value in doing so right now if the only benefit is avoiding the enum.
>

I suppose we won't have too much trouble handling ABI breakage (thinking
about when we will remove x86 support).
Ok, let's go with this.


-- 
David Marchand

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [EXT] Re: [PATCH 00/39] adding eventmode helper library
  2019-06-28  8:40  0%     ` Thomas Monjalon
  2019-06-28  9:07  0%       ` Mattias Rönnblom
@ 2019-06-28 11:34  0%       ` Anoob Joseph
  2019-07-02 14:17  0%         ` Anoob Joseph
  1 sibling, 1 reply; 200+ results
From: Anoob Joseph @ 2019-06-28 11:34 UTC (permalink / raw)
  To: Thomas Monjalon, Jerin Jacob Kollanukkaran
  Cc: dev, Mattias Rönnblom, Nikhil Rao, Erik Gabriel Carrillo,
	Abhinandan Gujjar, Bruce Richardson, Pablo de Lara,
	Narayana Prasad Raju Athreya, Lukas Bartosik,
	Pavan Nikhilesh Bhagavatula, Hemant Agrawal, Nipun Gupta,
	Harry van Haaren, Liang Ma, techboard

Hi Thomas, Jerin,

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Thomas Monjalon
> Sent: Friday, June 28, 2019 2:10 PM
> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Anoob Joseph
> <anoobj@marvell.com>
> Cc: dev@dpdk.org; Mattias Rönnblom <mattias.ronnblom@ericsson.com>;
> Nikhil Rao <nikhil.rao@intel.com>; Erik Gabriel Carrillo
> <erik.g.carrillo@intel.com>; Abhinandan Gujjar
> <abhinandan.gujjar@intel.com>; Bruce Richardson
> <bruce.richardson@intel.com>; Pablo de Lara
> <pablo.de.lara.guarch@intel.com>; Narayana Prasad Raju Athreya
> <pathreya@marvell.com>; Lukas Bartosik <lbartosik@marvell.com>; Pavan
> Nikhilesh Bhagavatula <pbhagavatula@marvell.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>; Nipun Gupta <nipun.gupta@nxp.com>; Harry
> van Haaren <harry.van.haaren@intel.com>; Liang Ma
> <liang.j.ma@intel.com>; techboard@dpdk.org
> Subject: [EXT] Re: [dpdk-dev] [PATCH 00/39] adding eventmode helper
> library
> 
> External Email
> 
> ----------------------------------------------------------------------
> 28/06/2019 05:37, Jerin Jacob Kollanukkaran:
> > From: Anoob Joseph
> > > From: Jerin Jacob Kollanukkaran
> > > > From: Anoob Joseph
> > > > > The helper library will be experimental while we add event-mode
> > > > > support for other applications like l3fwd & ipsec-secgw. I
> > > > > expect the helper library to be complete over the course of
> > > > > those applications also using the helper library.
> 
> You are doing a copy of l2fwd example to add event mode.
> It was the decision from the techboard to not complicate the original l2fwd.
> But it makes me nervous to see some code duplicated, especially if you plan
> to do the same for l3fwd and ipsec-secgw.
> We are not going to duplicate every examples. We should re-consider.
> 

[Anoob] For l3fwd & ipsec-secgw, the plan is to add eventmode in the original application itself. If you have concerns about code duplication in l2fwd-event, the changes can be added to l2fwd itself. Please advise on how to proceed.
 
> > > > I have only concern about moving this as library inside eventdev
> > > > that till we have mature version of helper library the eventdev
> > > > library ABI will not stable(i.e .so file version needs to be
> > > > incremented as when a change needed). Which align with Mattias
> > > > thoughts for some other reason:. How about moving this code to
> > > > 1) example/common or
> > > > 2) to specific application itself, once at least two applications
> > > > starts using it then move to Eventdev library.
> > > >
> > > > Thoughts?
> > >
> > > [Anoob] Either location is not a problem if there is a consensus.
> > > Earlier the suggestion was to move it to library (when the patch was
> > > submitted with changes added in app).
> 
> If there is only one user, making it grow in the application looks to be the
> best thing to do.
> Should we use it in more applications before it is more mature?
> If not, we could move the code in eventdev library when we will use it in
> more examples.
> 

[Anoob] The proposal with l2fwd-event was to present an easy enough example so that the APIs can be decided before moving onto complex examples. Additions to l3fwd & ipsec-secgw is in the pipeline.

> > If there NO objections then lets move to example/common.
> 
> If we really want to have this library standalone in examples, I suggest to give
> it a name and not use a "common" directory.
> 

[Anoob] I would suggest to add the eventmode code in 'examples/utils'.

What is being added here can be treated as a utility library. Almost all examples have duplicated code for the entire conf parsing, ethdev init etc. Anyone who would attempt a new application will have to duplicate lot of code. So a similar exercise with regular poll mode is also possible. 

As for build, we will have the following options,

1. From the examples/<example>/Makefile, build *helper*.o files ( '../utils/eventmode_helper.o') and prepare the binary. So each application will build its own version of *helper*.c
    +SRCS-y += ../utils/eventmode_helper.c

2. Make 'examples/utils' a separate library. This way, all applications can directly link without having to build separately.

Please do suggest on which would be a good way to execute.

Thanks,
Anoob

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 00/39] adding eventmode helper library
  2019-06-28  8:40  0%     ` Thomas Monjalon
@ 2019-06-28  9:07  0%       ` Mattias Rönnblom
  2019-06-28 11:34  0%       ` [dpdk-dev] [EXT] " Anoob Joseph
  1 sibling, 0 replies; 200+ results
From: Mattias Rönnblom @ 2019-06-28  9:07 UTC (permalink / raw)
  To: Thomas Monjalon, Jerin Jacob Kollanukkaran, Anoob Joseph
  Cc: dev, Nikhil Rao, Erik Gabriel Carrillo, Abhinandan Gujjar,
	Bruce Richardson, Pablo de Lara, Narayana Prasad Raju Athreya,
	Lukas Bartosik, Pavan Nikhilesh Bhagavatula, Hemant Agrawal,
	Nipun Gupta, Harry van Haaren, Liang Ma, techboard

On 2019-06-28 10:40, Thomas Monjalon wrote:
> 28/06/2019 05:37, Jerin Jacob Kollanukkaran:
>> From: Anoob Joseph
>>> From: Jerin Jacob Kollanukkaran
>>>> From: Anoob Joseph
>>>>> The helper library will be experimental while we add event-mode
>>>>> support for other applications like l3fwd & ipsec-secgw. I expect
>>>>> the helper library to be complete over the course of those
>>>>> applications also using the helper library.
> 
> You are doing a copy of l2fwd example to add event mode.
> It was the decision from the techboard to not complicate the original
> l2fwd. But it makes me nervous to see some code duplicated,
> especially if you plan to do the same for l3fwd and ipsec-secgw.
> We are not going to duplicate every examples. We should re-consider.
> 
>>>> I have only concern about moving this as library inside eventdev that
>>>> till we have mature version of helper library the eventdev library ABI
>>>> will not stable(i.e .so file version needs to be incremented as when a
>>>> change needed). Which align with Mattias thoughts for some other
>>>> reason:. How about moving this code to
>>>> 1) example/common or
>>>> 2) to specific application itself, once at least two applications
>>>> starts using it then move to Eventdev library.
>>>>
>>>> Thoughts?
>>>
>>> [Anoob] Either location is not a problem if there is a consensus. Earlier the
>>> suggestion was to move it to library (when the patch was submitted with
>>> changes added in app).
> 
> If there is only one user, making it grow in the application looks to be
> the best thing to do.
> Should we use it in more applications before it is more mature?
> If not, we could move the code in eventdev library when we will
> use it in more examples.
> 
>> If there NO objections then lets move to example/common.
> 
> If we really want to have this library standalone in examples,
> I suggest to give it a name and not use a "common" directory.
> 
> 

Another solution would be to keep it in a separate git repo, potentially 
together with a few forked DPDK example applications and new 
purpose-built example applications, until it's mature enough.

It's a bolt-on, not an integral part of eventdev or any other 
lower-layer infrastructure, so you don't need the whole DPDK tree.

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 00/39] adding eventmode helper library
  2019-06-28  3:37  0%   ` Jerin Jacob Kollanukkaran
  2019-06-28  8:02  0%     ` Mattias Rönnblom
@ 2019-06-28  8:40  0%     ` Thomas Monjalon
  2019-06-28  9:07  0%       ` Mattias Rönnblom
  2019-06-28 11:34  0%       ` [dpdk-dev] [EXT] " Anoob Joseph
  1 sibling, 2 replies; 200+ results
From: Thomas Monjalon @ 2019-06-28  8:40 UTC (permalink / raw)
  To: Jerin Jacob Kollanukkaran, Anoob Joseph
  Cc: dev, Mattias Rönnblom, Nikhil Rao, Erik Gabriel Carrillo,
	Abhinandan Gujjar, Bruce Richardson, Pablo de Lara,
	Narayana Prasad Raju Athreya, Lukas Bartosik,
	Pavan Nikhilesh Bhagavatula, Hemant Agrawal, Nipun Gupta,
	Harry van Haaren, Liang Ma, techboard

28/06/2019 05:37, Jerin Jacob Kollanukkaran:
> From: Anoob Joseph
> > From: Jerin Jacob Kollanukkaran
> > > From: Anoob Joseph
> > > > The helper library will be experimental while we add event-mode
> > > > support for other applications like l3fwd & ipsec-secgw. I expect
> > > > the helper library to be complete over the course of those
> > > > applications also using the helper library.

You are doing a copy of l2fwd example to add event mode.
It was the decision from the techboard to not complicate the original
l2fwd. But it makes me nervous to see some code duplicated,
especially if you plan to do the same for l3fwd and ipsec-secgw.
We are not going to duplicate every examples. We should re-consider.

> > > I have only concern about moving this as library inside eventdev that
> > > till we have mature version of helper library the eventdev library ABI
> > > will not stable(i.e .so file version needs to be incremented as when a
> > > change needed). Which align with Mattias thoughts for some other
> > > reason:. How about moving this code to
> > > 1) example/common or
> > > 2) to specific application itself, once at least two applications
> > > starts using it then move to Eventdev library.
> > >
> > > Thoughts?
> > 
> > [Anoob] Either location is not a problem if there is a consensus. Earlier the
> > suggestion was to move it to library (when the patch was submitted with
> > changes added in app).

If there is only one user, making it grow in the application looks to be
the best thing to do.
Should we use it in more applications before it is more mature?
If not, we could move the code in eventdev library when we will
use it in more examples.

> If there NO objections then lets move to example/common.

If we really want to have this library standalone in examples,
I suggest to give it a name and not use a "common" directory.



^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 00/39] adding eventmode helper library
  2019-06-28  3:37  0%   ` Jerin Jacob Kollanukkaran
@ 2019-06-28  8:02  0%     ` Mattias Rönnblom
  2019-06-28  8:40  0%     ` Thomas Monjalon
  1 sibling, 0 replies; 200+ results
From: Mattias Rönnblom @ 2019-06-28  8:02 UTC (permalink / raw)
  To: Jerin Jacob Kollanukkaran, Anoob Joseph, Nikhil Rao,
	Erik Gabriel Carrillo, Abhinandan Gujjar, Bruce Richardson,
	Pablo de Lara
  Cc: Narayana Prasad Raju Athreya, dev, Lukas Bartosik,
	Pavan Nikhilesh Bhagavatula, Hemant Agrawal, Nipun Gupta,
	Harry van Haaren, Liang Ma, techboard

On 2019-06-28 05:37, Jerin Jacob Kollanukkaran wrote:

>>>
>>> I have only concern about moving this as library inside eventdev that
>>> till we have mature version of helper library the eventdev library ABI
>>> will not stable(i.e .so file version needs to be incremented as when a
>>> change needed). Which align with Mattias thoughts for some other
>>> reason:. How about moving this code to
>>> 1) example/common or
>>> 2) to specific application itself, once at least two applications
>>> starts using it then move to Eventdev library.
>>>
>>> Thoughts?
>>
>> [Anoob] Either location is not a problem if there is a consensus. Earlier the
>> suggestion was to move it to library (when the patch was submitted with
>> changes added in app).
> 
> 
> If there NO objections then lets move to example/common.
> 

That sounds like a good idea to me.

I wish I had more time to devote to eventmode, so I could be more 
constructive than basically just saying "it's a hard problem" and "the 
proposed solution seems not generic-enough by far" - but I don't at the 
moment.

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 00/39] adding eventmode helper library
  2019-06-27  5:28  0% ` Anoob Joseph
@ 2019-06-28  3:37  0%   ` Jerin Jacob Kollanukkaran
  2019-06-28  8:02  0%     ` Mattias Rönnblom
  2019-06-28  8:40  0%     ` Thomas Monjalon
  0 siblings, 2 replies; 200+ results
From: Jerin Jacob Kollanukkaran @ 2019-06-28  3:37 UTC (permalink / raw)
  To: Anoob Joseph, Mattias Rönnblom, Nikhil Rao,
	Erik Gabriel Carrillo, Abhinandan Gujjar, Bruce Richardson,
	Pablo de Lara
  Cc: Narayana Prasad Raju Athreya, dev, Lukas Bartosik,
	Pavan Nikhilesh Bhagavatula, Hemant Agrawal, Nipun Gupta,
	Harry van Haaren, Liang Ma, techboard

> -----Original Message-----
> From: Anoob Joseph
> Sent: Thursday, June 27, 2019 10:58 AM
> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Mattias Rönnblom
> <mattias.ronnblom@ericsson.com>; Nikhil Rao <nikhil.rao@intel.com>; Erik
> Gabriel Carrillo <erik.g.carrillo@intel.com>; Abhinandan Gujjar
> <abhinandan.gujjar@intel.com>; Bruce Richardson
> <bruce.richardson@intel.com>; Pablo de Lara
> <pablo.de.lara.guarch@intel.com>
> Cc: Narayana Prasad Raju Athreya <pathreya@marvell.com>; dev@dpdk.org;
> Lukas Bartosik <lbartosik@marvell.com>; Pavan Nikhilesh Bhagavatula
> <pbhagavatula@marvell.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>; Nipun Gupta <nipun.gupta@nxp.com>; Harry
> van Haaren <harry.van.haaren@intel.com>; Liang Ma
> <liang.j.ma@intel.com>
> Subject: RE: [dpdk-dev] Re: [PATCH 00/39] adding eventmode helper library
> 
> Hi Jerin, Mattias,
> 
> Please see inline.
> 
> Thanks,
> Anoob
> 
> > -----Original Message-----
> > From: Jerin Jacob Kollanukkaran
> > Sent: Tuesday, June 25, 2019 4:03 PM
> > To: Anoob Joseph <anoobj@marvell.com>; Mattias Rönnblom
> > <mattias.ronnblom@ericsson.com>; Nikhil Rao <nikhil.rao@intel.com>;
> > Erik Gabriel Carrillo <erik.g.carrillo@intel.com>; Abhinandan Gujjar
> > <abhinandan.gujjar@intel.com>; Bruce Richardson
> > <bruce.richardson@intel.com>; Pablo de Lara
> > <pablo.de.lara.guarch@intel.com>
> > Cc: Narayana Prasad Raju Athreya <pathreya@marvell.com>;
> dev@dpdk.org;
> > Lukas Bartosik <lbartosik@marvell.com>; Pavan Nikhilesh Bhagavatula
> > <pbhagavatula@marvell.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>;
> > Nipun Gupta <nipun.gupta@nxp.com>; Harry van Haaren
> > <harry.van.haaren@intel.com>; Liang Ma <liang.j.ma@intel.com>
> > Subject: RE: [dpdk-dev] Re: [PATCH 00/39] adding eventmode helper
> > library
> >
> > > -----Original Message-----
> > > From: Anoob Joseph
> > > Sent: Thursday, June 20, 2019 9:15 AM
> > > To: Mattias Rönnblom <mattias.ronnblom@ericsson.com>; Jerin Jacob
> > > Kollanukkaran <jerinj@marvell.com>; Nikhil Rao
> > > <nikhil.rao@intel.com>; Erik Gabriel Carrillo
> > > <erik.g.carrillo@intel.com>; Abhinandan Gujjar
> > > <abhinandan.gujjar@intel.com>; Bruce Richardson
> > > <bruce.richardson@intel.com>; Pablo de Lara
> > > <pablo.de.lara.guarch@intel.com>
> > > Cc: Narayana Prasad Raju Athreya <pathreya@marvell.com>;
> > dev@dpdk.org;
> > > Lukas Bartosik <lbartosik@marvell.com>; Pavan Nikhilesh Bhagavatula
> > > <pbhagavatula@marvell.com>; Hemant Agrawal
> > <hemant.agrawal@nxp.com>;
> > > Nipun Gupta <nipun.gupta@nxp.com>; Harry van Haaren
> > > <harry.van.haaren@intel.com>; Liang Ma <liang.j.ma@intel.com>
> > > Subject: RE: [dpdk-dev] [EXT] Re: [PATCH 00/39] adding eventmode
> > > helper library
> > > > However, the flexibility and many of the parameters are there for
> > > > a reason (those there aren't should be deprecated). I would expect
> > > > a real-world application to tweak quite a few of them. I know our
> > > > applications
> > > do.
> > > >
> > > > I worry I have is that if you put eventmode (in its current form)
> > > > forward as a generic framework, applications might start using it,
> > > > only to realize it's not flexible enough, and then eventmode is
> > > > just an extra layer, increasing rather than reducing complexity.
> > > > Or even worse, the application's developers are forced to do a
> > > > big-bang switch over to using the event and ethernet device APIs
> > > > directly, in case they can't patch DPDK to work around the
> > > > eventmode-
> > > > assumption-that-
> > > didn't-hold-for-them.
> > > >
> > > > You could always add flexibility to the framework (as you
> > > > encounter a need for it), but then it will grow in complexity as well.
> > > >
> > > > A less ambitious approach would be to instead do a properly
> > > > modularized, non-trivial eventdev example application, for the
> > > > applications to start off from, instead of a generic library.
> > > >
> > > > I would expect it to be very difficult to design a truly generic
> > > > application framework for eventdev-based applications. Such a
> > > > framework would tie everything that's needed in a non-trivial
> > > > application together. If successful, it would be a huge step
> > > > toward making DPDK an operating system for packet processing
> applications.
> > >
> > > [Anoob] The idea here is not to deprecate any event dev APIs. I do
> > > agree that all the configuration exposed by eventdev & adapters are
> > > required for various requirements in the real world applications.
> > > But the requirement to understand & use all this configuration is
> > > making the applications complicated and causes significant effort
> > > from anyone who
> > would want to get started with event mode.
> > > The idea of helper is to allow an easy framework for applications to
> > > get started with eventmode, and then use various options from C/L or
> > > config file (both
> > > planned) to override the configuration as required. DPDK has
> > > components like crypto-scheduler which abstracts lot of
> > > configuration and simplify usage from application's perspective.
> > > This effort is on similar
> > lines.
> > >
> > > My patchset is a followup to http://patches.dpdk.org/patch/37955 ,
> > > wherein the approach of introducing a helper library for event mode
> > > was mooted. The initial patch proposed additions in one application,
> > > and that involved huge code additions just for doing the configuration.
> > >
> > > The helper library will be experimental while we add event-mode
> > > support for other applications like l3fwd & ipsec-secgw. I expect
> > > the helper library to be complete over the course of those
> > > applications also
> > using the helper library.
> >
> >
> > I have only concern about moving this as library inside eventdev that
> > till we have mature version of helper library the eventdev library ABI
> > will not stable(i.e .so file version needs to be incremented as when a
> > change needed). Which align with Mattias thoughts for some other
> > reason:. How about moving this code to
> > 1) example/common or
> > 2) to specific application itself, once at least two applications
> > starts using it then move to Eventdev library.
> >
> > Thoughts?
> 
> [Anoob] Either location is not a problem if there is a consensus. Earlier the
> suggestion was to move it to library (when the patch was submitted with
> changes added in app).


If there NO objections then lets move to example/common.

Cc: techboard@dpdk.org for final decision on the location.





> 
> Since there are other comments, which are being addressed, I would like to
> send the next series with the current layout itself. And when we have an
> agreement on the location to be used, I'll make the changes. Is that fine?
> 
> >
> >
> >
> >
> > >
> > > >
> > > > What event devices have you tested with?
> > >
> > > [Anoob] Eventmode helper is tested with the following combinations,
> > >     1. event-octeontx event PMD & nicvf eth PMD
> > >     2. event-octeontx event PMD & eth-octeontx eth PMD

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v3 14/14] eal: prevent different primary/secondary process versions
      2019-06-27 11:39  8%       ` [dpdk-dev] [PATCH v3 09/14] eal: hide shared memory config Anatoly Burakov
@ 2019-06-27 11:39  3%       ` Anatoly Burakov
  2 siblings, 0 replies; 200+ results
From: Anatoly Burakov @ 2019-06-27 11:39 UTC (permalink / raw)
  To: dev; +Cc: Bruce Richardson, david.marchand, thomas, stephen

Currently, nothing stops DPDK to attempt to run primary and
secondary processes while having different versions. This
can lead to all sorts of weird behavior and makes it harder
to maintain compatibility without breaking ABI every once
in a while.

Fix it by explicitly disallowing running different DPDK
versions as primary and secondary processes.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_eal/common/eal_common_mcfg.c | 15 +++++++++++++++
 lib/librte_eal/common/eal_memcfg.h      |  6 ++++++
 lib/librte_eal/freebsd/eal/eal.c        |  5 ++++-
 lib/librte_eal/linux/eal/eal.c          |  5 ++++-
 4 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_mcfg.c b/lib/librte_eal/common/eal_common_mcfg.c
index fe8d2b726..1825d9083 100644
--- a/lib/librte_eal/common/eal_common_mcfg.c
+++ b/lib/librte_eal/common/eal_common_mcfg.c
@@ -4,6 +4,7 @@
 
 #include <rte_config.h>
 #include <rte_eal_memconfig.h>
+#include <rte_version.h>
 
 #include "eal_internal_cfg.h"
 #include "eal_memcfg.h"
@@ -31,6 +32,18 @@ eal_mcfg_wait_complete(void)
 		rte_pause();
 }
 
+int
+eal_mcfg_check_version(void)
+{
+	struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+
+	/* check if version from memconfig matches compiled in macro */
+	if (mcfg->version != RTE_VERSION)
+		return -1;
+
+	return 0;
+}
+
 void
 eal_mcfg_update_internal(void)
 {
@@ -47,6 +60,8 @@ eal_mcfg_update_from_internal(void)
 
 	mcfg->legacy_mem = internal_config.legacy_mem;
 	mcfg->single_file_segments = internal_config.single_file_segments;
+	/* record current DPDK version */
+	mcfg->version = RTE_VERSION;
 }
 
 void
diff --git a/lib/librte_eal/common/eal_memcfg.h b/lib/librte_eal/common/eal_memcfg.h
index d02ac1621..a3d4b7fd1 100644
--- a/lib/librte_eal/common/eal_memcfg.h
+++ b/lib/librte_eal/common/eal_memcfg.h
@@ -21,6 +21,8 @@
  */
 struct rte_mem_config {
 	volatile uint32_t magic;   /**< Magic number - Sanity check. */
+	uint32_t version;
+	/**< Prevent secondary processes using different DPDK versions. */
 
 	/* memory topology */
 	uint32_t nchannel;    /**< Number of channels (0 if unknown). */
@@ -80,6 +82,10 @@ eal_mcfg_update_from_internal(void);
 void
 eal_mcfg_wait_complete(void);
 
+/* check if DPDK version of current process matches one stored in the config */
+int
+eal_mcfg_check_version(void);
+
 /* set mem config as complete */
 void
 eal_mcfg_complete(void);
diff --git a/lib/librte_eal/freebsd/eal/eal.c b/lib/librte_eal/freebsd/eal/eal.c
index 6bfe203fd..e2039927c 100644
--- a/lib/librte_eal/freebsd/eal/eal.c
+++ b/lib/librte_eal/freebsd/eal/eal.c
@@ -385,6 +385,10 @@ rte_config_init(void)
 		if (rte_eal_config_attach() < 0)
 			return -1;
 		eal_mcfg_wait_complete();
+		if (eal_mcfg_check_version() < 0) {
+			RTE_LOG(ERR, EAL, "Primary and secondary process DPDK version mismatch\n");
+			return -1;
+		}
 		if (rte_eal_config_reattach() < 0)
 			return -1;
 		eal_mcfg_update_from_internal();
@@ -395,7 +399,6 @@ rte_config_init(void)
 			rte_config.process_type);
 		return -1;
 	}
-
 	return 0;
 }
 
diff --git a/lib/librte_eal/linux/eal/eal.c b/lib/librte_eal/linux/eal/eal.c
index fa205fd29..5421e934e 100644
--- a/lib/librte_eal/linux/eal/eal.c
+++ b/lib/librte_eal/linux/eal/eal.c
@@ -488,6 +488,10 @@ rte_config_init(void)
 		if (rte_eal_config_attach() < 0)
 			return -1;
 		eal_mcfg_wait_complete();
+		if (eal_mcfg_check_version() < 0) {
+			RTE_LOG(ERR, EAL, "Primary and secondary process DPDK version mismatch\n");
+			return -1;
+		}
 		if (rte_eal_config_reattach() < 0)
 			return -1;
 		eal_mcfg_update_internal();
@@ -498,7 +502,6 @@ rte_config_init(void)
 			rte_config.process_type);
 		return -1;
 	}
-
 	return 0;
 }
 
-- 
2.17.1

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v3 09/14] eal: hide shared memory config
    @ 2019-06-27 11:39  8%       ` Anatoly Burakov
  2019-06-27 11:39  3%       ` [dpdk-dev] [PATCH v3 14/14] eal: prevent different primary/secondary process versions Anatoly Burakov
  2 siblings, 0 replies; 200+ results
From: Anatoly Burakov @ 2019-06-27 11:39 UTC (permalink / raw)
  To: dev
  Cc: Neil Horman, John McNamara, Marko Kovacevic, Konstantin Ananyev,
	David Hunt, Bruce Richardson, Byron Marohn, Pablo de Lara Guarch,
	Yipeng Wang, Sameh Gobriel, Vladimir Medvedkin, Olivier Matz,
	Andrew Rybchenko, Reshma Pattan, david.marchand, thomas, stephen

Now that everything that has ever accessed the shared memory
config is doing so through the public API's, we can make it
internal. Since we're removing quite a few headers from
rte_eal_memconfig.h, we need to add them back in places
where this header is used.

This bumps the ABI, so also change all build files and make
update documentation.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 app/test/test_memzone.c                       |  1 +
 app/test/test_tailq.c                         |  1 +
 doc/guides/rel_notes/deprecation.rst          |  3 -
 doc/guides/rel_notes/release_19_08.rst        |  8 +-
 drivers/bus/pci/linux/pci_vfio.c              |  1 +
 lib/librte_acl/rte_acl.c                      |  2 +
 lib/librte_distributor/rte_distributor.c      |  1 +
 lib/librte_distributor/rte_distributor_v20.c  |  1 +
 lib/librte_eal/common/eal_common_mcfg.c       |  2 +
 lib/librte_eal/common/eal_common_memory.c     |  1 +
 lib/librte_eal/common/eal_common_memzone.c    |  1 +
 lib/librte_eal/common/eal_common_tailqs.c     |  1 +
 lib/librte_eal/common/eal_memcfg.h            | 79 +++++++++++++++++++
 .../common/include/rte_eal_memconfig.h        | 75 ++----------------
 lib/librte_eal/common/malloc_heap.c           |  2 +
 lib/librte_eal/common/malloc_mp.c             |  1 +
 lib/librte_eal/common/rte_malloc.c            |  1 +
 lib/librte_eal/freebsd/eal/Makefile           |  2 +-
 lib/librte_eal/freebsd/eal/eal_memory.c       |  1 +
 lib/librte_eal/linux/eal/Makefile             |  2 +-
 lib/librte_eal/linux/eal/eal.c                |  1 +
 lib/librte_eal/linux/eal/eal_memalloc.c       |  1 +
 lib/librte_eal/linux/eal/eal_memory.c         |  1 +
 lib/librte_eal/linux/eal/eal_vfio.c           |  1 +
 lib/librte_eal/meson.build                    |  2 +-
 lib/librte_efd/rte_efd.c                      |  1 +
 lib/librte_hash/rte_cuckoo_hash.c             |  1 +
 lib/librte_hash/rte_fbk_hash.c                |  1 +
 lib/librte_lpm/rte_lpm.c                      |  1 +
 lib/librte_lpm/rte_lpm6.c                     |  1 +
 lib/librte_member/rte_member.c                |  1 +
 lib/librte_mempool/rte_mempool.c              |  1 +
 lib/librte_reorder/rte_reorder.c              |  1 +
 lib/librte_ring/rte_ring.c                    |  1 +
 34 files changed, 125 insertions(+), 76 deletions(-)
 create mode 100644 lib/librte_eal/common/eal_memcfg.h

diff --git a/app/test/test_memzone.c b/app/test/test_memzone.c
index 9fe465e62..7501b63c5 100644
--- a/app/test/test_memzone.c
+++ b/app/test/test_memzone.c
@@ -19,6 +19,7 @@
 #include <rte_errno.h>
 #include <rte_malloc.h>
 #include "../../lib/librte_eal/common/malloc_elem.h"
+#include "../../lib/librte_eal/common/eal_memcfg.h"
 
 #include "test.h"
 
diff --git a/app/test/test_tailq.c b/app/test/test_tailq.c
index a4ecea2d8..7c9b69fdb 100644
--- a/app/test/test_tailq.c
+++ b/app/test/test_tailq.c
@@ -12,6 +12,7 @@
 #include <rte_eal.h>
 #include <rte_eal_memconfig.h>
 #include <rte_string_fns.h>
+#include <rte_tailq.h>
 
 #include "test.h"
 
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index e2721fad6..583217da8 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -23,9 +23,6 @@ Deprecation Notices
 * eal: The function ``rte_eal_remote_launch`` will return new error codes
   after read or write error on the pipe, instead of calling ``rte_panic``.
 
-* eal: the ``rte_mem_config`` struct will be made private to remove it from the
-  externally visible ABI and allow it to be updated in the future.
-
 * eal: both declaring and identifying devices will be streamlined in v18.11.
   New functions will appear to query a specific port from buses, classes of
   device and device drivers. Device declaration will be made coherent with the
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 3da266705..b6314431a 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -132,6 +132,10 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* The ``rte_mem_config`` structure has been made private. The new accessor
+  ``rte_mcfg_*`` functions were introduced to provide replacement for direct
+  access to the shared mem config.
+
 * The network structures, definitions and functions have
   been prefixed by ``rte_`` to resolve conflicts with libc headers.
 
@@ -151,6 +155,8 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* The ``rte_mem_config`` structure has been made private.
+
 
 Shared Library Versions
 -----------------------
@@ -184,7 +190,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_compressdev.so.1
      librte_cryptodev.so.7
      librte_distributor.so.1
-     librte_eal.so.10
+   + librte_eal.so.11
      librte_efd.so.1
      librte_ethdev.so.12
      librte_eventdev.so.6
diff --git a/drivers/bus/pci/linux/pci_vfio.c b/drivers/bus/pci/linux/pci_vfio.c
index ebf6ccd3c..1ceb1c07b 100644
--- a/drivers/bus/pci/linux/pci_vfio.c
+++ b/drivers/bus/pci/linux/pci_vfio.c
@@ -20,6 +20,7 @@
 #include <rte_eal.h>
 #include <rte_bus.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "eal_filesystem.h"
 
diff --git a/lib/librte_acl/rte_acl.c b/lib/librte_acl/rte_acl.c
index 7ff11d25f..bd7247cc3 100644
--- a/lib/librte_acl/rte_acl.c
+++ b/lib/librte_acl/rte_acl.c
@@ -4,6 +4,8 @@
 
 #include <rte_string_fns.h>
 #include <rte_acl.h>
+#include <rte_tailq.h>
+
 #include "acl.h"
 
 TAILQ_HEAD(rte_acl_list, rte_tailq_entry);
diff --git a/lib/librte_distributor/rte_distributor.c b/lib/librte_distributor/rte_distributor.c
index 9eb78b330..0a3213bbf 100644
--- a/lib/librte_distributor/rte_distributor.c
+++ b/lib/librte_distributor/rte_distributor.c
@@ -14,6 +14,7 @@
 #include <rte_string_fns.h>
 #include <rte_eal_memconfig.h>
 #include <rte_pause.h>
+#include <rte_tailq.h>
 
 #include "rte_distributor_private.h"
 #include "rte_distributor.h"
diff --git a/lib/librte_distributor/rte_distributor_v20.c b/lib/librte_distributor/rte_distributor_v20.c
index 1fc03b971..cdc0969a8 100644
--- a/lib/librte_distributor/rte_distributor_v20.c
+++ b/lib/librte_distributor/rte_distributor_v20.c
@@ -13,6 +13,7 @@
 #include <rte_string_fns.h>
 #include <rte_eal_memconfig.h>
 #include <rte_pause.h>
+#include <rte_tailq.h>
 
 #include "rte_distributor_v20.h"
 #include "rte_distributor_private.h"
diff --git a/lib/librte_eal/common/eal_common_mcfg.c b/lib/librte_eal/common/eal_common_mcfg.c
index ba2bc37b7..337890a61 100644
--- a/lib/librte_eal/common/eal_common_mcfg.c
+++ b/lib/librte_eal/common/eal_common_mcfg.c
@@ -5,6 +5,8 @@
 #include <rte_config.h>
 #include <rte_eal_memconfig.h>
 
+#include "eal_memcfg.h"
+
 void
 rte_mcfg_mem_read_lock(void)
 {
diff --git a/lib/librte_eal/common/eal_common_memory.c b/lib/librte_eal/common/eal_common_memory.c
index e73a413cc..b33bc4b29 100644
--- a/lib/librte_eal/common/eal_common_memory.c
+++ b/lib/librte_eal/common/eal_common_memory.c
@@ -24,6 +24,7 @@
 #include "eal_memalloc.h"
 #include "eal_private.h"
 #include "eal_internal_cfg.h"
+#include "eal_memcfg.h"
 #include "malloc_heap.h"
 
 /*
diff --git a/lib/librte_eal/common/eal_common_memzone.c b/lib/librte_eal/common/eal_common_memzone.c
index 521ad7ca1..ef6c909cb 100644
--- a/lib/librte_eal/common/eal_common_memzone.c
+++ b/lib/librte_eal/common/eal_common_memzone.c
@@ -24,6 +24,7 @@
 #include "malloc_heap.h"
 #include "malloc_elem.h"
 #include "eal_private.h"
+#include "eal_memcfg.h"
 
 static inline const struct rte_memzone *
 memzone_lookup_thread_unsafe(const char *name)
diff --git a/lib/librte_eal/common/eal_common_tailqs.c b/lib/librte_eal/common/eal_common_tailqs.c
index dc2c13caa..ead06897b 100644
--- a/lib/librte_eal/common/eal_common_tailqs.c
+++ b/lib/librte_eal/common/eal_common_tailqs.c
@@ -23,6 +23,7 @@
 #include <rte_debug.h>
 
 #include "eal_private.h"
+#include "eal_memcfg.h"
 
 TAILQ_HEAD(rte_tailq_elem_head, rte_tailq_elem);
 /* local tailq list */
diff --git a/lib/librte_eal/common/eal_memcfg.h b/lib/librte_eal/common/eal_memcfg.h
new file mode 100644
index 000000000..466958352
--- /dev/null
+++ b/lib/librte_eal/common/eal_memcfg.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef EAL_MEMCFG_H
+#define EAL_MEMCFG_H
+
+#include <rte_config.h>
+#include <rte_eal_memconfig.h>
+#include <rte_malloc_heap.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_pause.h>
+#include <rte_rwlock.h>
+#include <rte_tailq.h>
+
+/**
+ * the structure for the memory configuration for the RTE.
+ * Used by the rte_config structure. It is separated out, as for multi-process
+ * support, the memory details should be shared across instances
+ */
+struct rte_mem_config {
+	volatile uint32_t magic;   /**< Magic number - Sanity check. */
+
+	/* memory topology */
+	uint32_t nchannel;    /**< Number of channels (0 if unknown). */
+	uint32_t nrank;       /**< Number of ranks (0 if unknown). */
+
+	/**
+	 * current lock nest order
+	 *  - qlock->mlock (ring/hash/lpm)
+	 *  - mplock->qlock->mlock (mempool)
+	 * Notice:
+	 *  *ALWAYS* obtain qlock first if having to obtain both qlock and mlock
+	 */
+	rte_rwlock_t mlock;   /**< only used by memzone LIB for thread-safe. */
+	rte_rwlock_t qlock;   /**< used for tailq operation for thread safe. */
+	rte_rwlock_t mplock;  /**< only used by mempool LIB for thread-safe. */
+
+	rte_rwlock_t memory_hotplug_lock;
+	/**< indicates whether memory hotplug request is in progress. */
+
+	/* memory segments and zones */
+	struct rte_fbarray memzones; /**< Memzone descriptors. */
+
+	struct rte_memseg_list memsegs[RTE_MAX_MEMSEG_LISTS];
+	/**< list of dynamic arrays holding memsegs */
+
+	struct rte_tailq_head tailq_head[RTE_MAX_TAILQ];
+	/**< Tailqs for objects */
+
+	/* Heaps of Malloc */
+	struct malloc_heap malloc_heaps[RTE_MAX_HEAPS];
+
+	/* next socket ID for external malloc heap */
+	int next_socket_id;
+
+	/* address of mem_config in primary process. used to map shared config
+	 * into exact same address the primary process maps it.
+	 */
+	uint64_t mem_cfg_addr;
+
+	/* legacy mem and single file segments options are shared */
+	uint32_t legacy_mem;
+	uint32_t single_file_segments;
+
+	/* keeps the more restricted dma mask */
+	uint8_t dma_maskbits;
+} __attribute__((packed));
+
+static inline void
+rte_eal_mcfg_wait_complete(struct rte_mem_config *mcfg)
+{
+	/* wait until shared mem_config finish initialising */
+	while (mcfg->magic != RTE_MAGIC)
+		rte_pause();
+}
+
+#endif /* EAL_MEMCFG_H */
diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
index 58dcbb96d..1b615c892 100644
--- a/lib/librte_eal/common/include/rte_eal_memconfig.h
+++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
@@ -5,13 +5,12 @@
 #ifndef _RTE_EAL_MEMCONFIG_H_
 #define _RTE_EAL_MEMCONFIG_H_
 
-#include <rte_config.h>
-#include <rte_tailq.h>
-#include <rte_memory.h>
-#include <rte_memzone.h>
-#include <rte_malloc_heap.h>
-#include <rte_rwlock.h>
-#include <rte_pause.h>
+/**
+ * @file
+ *
+ * This API allows access to EAL shared memory configuration through an API.
+ */
+
 #include <rte_fbarray.h>
 
 #ifdef __cplusplus
@@ -38,68 +37,6 @@ struct rte_memseg_list {
 	struct rte_fbarray memseg_arr;
 };
 
-/**
- * the structure for the memory configuration for the RTE.
- * Used by the rte_config structure. It is separated out, as for multi-process
- * support, the memory details should be shared across instances
- */
-struct rte_mem_config {
-	volatile uint32_t magic;   /**< Magic number - Sanity check. */
-
-	/* memory topology */
-	uint32_t nchannel;    /**< Number of channels (0 if unknown). */
-	uint32_t nrank;       /**< Number of ranks (0 if unknown). */
-
-	/**
-	 * current lock nest order
-	 *  - qlock->mlock (ring/hash/lpm)
-	 *  - mplock->qlock->mlock (mempool)
-	 * Notice:
-	 *  *ALWAYS* obtain qlock first if having to obtain both qlock and mlock
-	 */
-	rte_rwlock_t mlock;   /**< only used by memzone LIB for thread-safe. */
-	rte_rwlock_t qlock;   /**< used for tailq operation for thread safe. */
-	rte_rwlock_t mplock;  /**< only used by mempool LIB for thread-safe. */
-
-	rte_rwlock_t memory_hotplug_lock;
-	/**< indicates whether memory hotplug request is in progress. */
-
-	/* memory segments and zones */
-	struct rte_fbarray memzones; /**< Memzone descriptors. */
-
-	struct rte_memseg_list memsegs[RTE_MAX_MEMSEG_LISTS];
-	/**< list of dynamic arrays holding memsegs */
-
-	struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**< Tailqs for objects */
-
-	/* Heaps of Malloc */
-	struct malloc_heap malloc_heaps[RTE_MAX_HEAPS];
-
-	/* next socket ID for external malloc heap */
-	int next_socket_id;
-
-	/* address of mem_config in primary process. used to map shared config into
-	 * exact same address the primary process maps it.
-	 */
-	uint64_t mem_cfg_addr;
-
-	/* legacy mem and single file segments options are shared */
-	uint32_t legacy_mem;
-	uint32_t single_file_segments;
-
-	/* keeps the more restricted dma mask */
-	uint8_t dma_maskbits;
-} __attribute__((__packed__));
-
-
-inline static void
-rte_eal_mcfg_wait_complete(struct rte_mem_config* mcfg)
-{
-	/* wait until shared mem_config finish initialising */
-	while(mcfg->magic != RTE_MAGIC)
-		rte_pause();
-}
-
 /**
  * Lock the internal EAL shared memory configuration for shared access.
  */
diff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c
index f1d31de0d..634ca212f 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -20,11 +20,13 @@
 #include <rte_string_fns.h>
 #include <rte_spinlock.h>
 #include <rte_memcpy.h>
+#include <rte_memzone.h>
 #include <rte_atomic.h>
 #include <rte_fbarray.h>
 
 #include "eal_internal_cfg.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 #include "malloc_elem.h"
 #include "malloc_heap.h"
 #include "malloc_mp.h"
diff --git a/lib/librte_eal/common/malloc_mp.c b/lib/librte_eal/common/malloc_mp.c
index 7c6112c4e..1f212f834 100644
--- a/lib/librte_eal/common/malloc_mp.c
+++ b/lib/librte_eal/common/malloc_mp.c
@@ -10,6 +10,7 @@
 #include <rte_string_fns.h>
 
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 
 #include "malloc_elem.h"
 #include "malloc_mp.h"
diff --git a/lib/librte_eal/common/rte_malloc.c b/lib/librte_eal/common/rte_malloc.c
index 98e1bdd07..8d2ef8aeb 100644
--- a/lib/librte_eal/common/rte_malloc.c
+++ b/lib/librte_eal/common/rte_malloc.c
@@ -25,6 +25,7 @@
 #include "malloc_elem.h"
 #include "malloc_heap.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 
 
 /* Free the memory space back to heap */
diff --git a/lib/librte_eal/freebsd/eal/Makefile b/lib/librte_eal/freebsd/eal/Makefile
index dc56af582..0974518ab 100644
--- a/lib/librte_eal/freebsd/eal/Makefile
+++ b/lib/librte_eal/freebsd/eal/Makefile
@@ -22,7 +22,7 @@ LDLIBS += -lrte_kvargs
 
 EXPORT_MAP := ../../rte_eal_version.map
 
-LIBABIVER := 10
+LIBABIVER := 11
 
 # specific to freebsd exec-env
 SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) := eal.c
diff --git a/lib/librte_eal/freebsd/eal/eal_memory.c b/lib/librte_eal/freebsd/eal/eal_memory.c
index 4b092e1f2..9b9a0577a 100644
--- a/lib/librte_eal/freebsd/eal/eal_memory.c
+++ b/lib/librte_eal/freebsd/eal/eal_memory.c
@@ -18,6 +18,7 @@
 #include "eal_private.h"
 #include "eal_internal_cfg.h"
 #include "eal_filesystem.h"
+#include "eal_memcfg.h"
 
 #define EAL_PAGE_SIZE (sysconf(_SC_PAGESIZE))
 
diff --git a/lib/librte_eal/linux/eal/Makefile b/lib/librte_eal/linux/eal/Makefile
index 3b2642eb8..9c885a9c9 100644
--- a/lib/librte_eal/linux/eal/Makefile
+++ b/lib/librte_eal/linux/eal/Makefile
@@ -10,7 +10,7 @@ ARCH_DIR ?= $(RTE_ARCH)
 EXPORT_MAP := ../../rte_eal_version.map
 VPATH += $(RTE_SDK)/lib/librte_eal/common/arch/$(ARCH_DIR)
 
-LIBABIVER := 10
+LIBABIVER := 11
 
 VPATH += $(RTE_SDK)/lib/librte_eal/common
 
diff --git a/lib/librte_eal/linux/eal/eal.c b/lib/librte_eal/linux/eal/eal.c
index d96ed3a7c..1ab4cc769 100644
--- a/lib/librte_eal/linux/eal/eal.c
+++ b/lib/librte_eal/linux/eal/eal.c
@@ -57,6 +57,7 @@
 #include "eal_internal_cfg.h"
 #include "eal_filesystem.h"
 #include "eal_hugepages.h"
+#include "eal_memcfg.h"
 #include "eal_options.h"
 #include "eal_vfio.h"
 
diff --git a/lib/librte_eal/linux/eal/eal_memalloc.c b/lib/librte_eal/linux/eal/eal_memalloc.c
index 2019636fb..1f6a7c18f 100644
--- a/lib/librte_eal/linux/eal/eal_memalloc.c
+++ b/lib/librte_eal/linux/eal/eal_memalloc.c
@@ -44,6 +44,7 @@
 #include "eal_filesystem.h"
 #include "eal_internal_cfg.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 #include "eal_private.h"
 
 const int anonymous_hugepages_supported =
diff --git a/lib/librte_eal/linux/eal/eal_memory.c b/lib/librte_eal/linux/eal/eal_memory.c
index 1853acea5..9c948a374 100644
--- a/lib/librte_eal/linux/eal/eal_memory.c
+++ b/lib/librte_eal/linux/eal/eal_memory.c
@@ -46,6 +46,7 @@
 
 #include "eal_private.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 #include "eal_internal_cfg.h"
 #include "eal_filesystem.h"
 #include "eal_hugepages.h"
diff --git a/lib/librte_eal/linux/eal/eal_vfio.c b/lib/librte_eal/linux/eal/eal_vfio.c
index 924cba526..5d679ca68 100644
--- a/lib/librte_eal/linux/eal/eal_vfio.c
+++ b/lib/librte_eal/linux/eal/eal_vfio.c
@@ -15,6 +15,7 @@
 #include <rte_vfio.h>
 
 #include "eal_filesystem.h"
+#include "eal_memcfg.h"
 #include "eal_vfio.h"
 #include "eal_private.h"
 
diff --git a/lib/librte_eal/meson.build b/lib/librte_eal/meson.build
index fa36b20e0..5c5023dd4 100644
--- a/lib/librte_eal/meson.build
+++ b/lib/librte_eal/meson.build
@@ -12,7 +12,7 @@ subdir('common') # defines common_sources, common_objs, etc.
 dpdk_conf.set('RTE_EXEC_ENV_' + exec_env.to_upper(), 1)
 subdir(exec_env + '/eal')
 
-version = 10  # the version of the EAL API
+version = 11  # the version of the EAL API
 allow_experimental_apis = true
 deps += 'kvargs'
 if dpdk_conf.has('RTE_USE_LIBBSD')
diff --git a/lib/librte_efd/rte_efd.c b/lib/librte_efd/rte_efd.c
index b808ce99f..d3d019578 100644
--- a/lib/librte_efd/rte_efd.c
+++ b/lib/librte_efd/rte_efd.c
@@ -20,6 +20,7 @@
 #include <rte_ring.h>
 #include <rte_jhash.h>
 #include <rte_hash_crc.h>
+#include <rte_tailq.h>
 
 #include "rte_efd.h"
 #if defined(RTE_ARCH_X86)
diff --git a/lib/librte_hash/rte_cuckoo_hash.c b/lib/librte_hash/rte_cuckoo_hash.c
index 865c744d9..b76518b4c 100644
--- a/lib/librte_hash/rte_cuckoo_hash.c
+++ b/lib/librte_hash/rte_cuckoo_hash.c
@@ -27,6 +27,7 @@
 #include <rte_ring.h>
 #include <rte_compat.h>
 #include <rte_vect.h>
+#include <rte_tailq.h>
 
 #include "rte_hash.h"
 #include "rte_cuckoo_hash.h"
diff --git a/lib/librte_hash/rte_fbk_hash.c b/lib/librte_hash/rte_fbk_hash.c
index db118c930..576e8e666 100644
--- a/lib/librte_hash/rte_fbk_hash.c
+++ b/lib/librte_hash/rte_fbk_hash.c
@@ -20,6 +20,7 @@
 #include <rte_cpuflags.h>
 #include <rte_log.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_fbk_hash.h"
 
diff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c
index b91f74216..70c24ac1f 100644
--- a/lib/librte_lpm/rte_lpm.c
+++ b/lib/librte_lpm/rte_lpm.c
@@ -21,6 +21,7 @@
 #include <rte_errno.h>
 #include <rte_rwlock.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_lpm.h"
 
diff --git a/lib/librte_lpm/rte_lpm6.c b/lib/librte_lpm/rte_lpm6.c
index 5af74a539..9b8aeb972 100644
--- a/lib/librte_lpm/rte_lpm6.c
+++ b/lib/librte_lpm/rte_lpm6.c
@@ -24,6 +24,7 @@
 #include <rte_hash.h>
 #include <assert.h>
 #include <rte_jhash.h>
+#include <rte_tailq.h>
 
 #include "rte_lpm6.h"
 
diff --git a/lib/librte_member/rte_member.c b/lib/librte_member/rte_member.c
index efed28dd9..e0e7f127e 100644
--- a/lib/librte_member/rte_member.c
+++ b/lib/librte_member/rte_member.c
@@ -10,6 +10,7 @@
 #include <rte_memory.h>
 #include <rte_malloc.h>
 #include <rte_errno.h>
+#include <rte_tailq.h>
 
 #include "rte_member.h"
 #include "rte_member_ht.h"
diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c
index 5c688d456..7260ce0be 100644
--- a/lib/librte_mempool/rte_mempool.c
+++ b/lib/librte_mempool/rte_mempool.c
@@ -30,6 +30,7 @@
 #include <rte_errno.h>
 #include <rte_string_fns.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_mempool.h"
 
diff --git a/lib/librte_reorder/rte_reorder.c b/lib/librte_reorder/rte_reorder.c
index ae6e3f578..3c9f0e2d0 100644
--- a/lib/librte_reorder/rte_reorder.c
+++ b/lib/librte_reorder/rte_reorder.c
@@ -11,6 +11,7 @@
 #include <rte_eal_memconfig.h>
 #include <rte_errno.h>
 #include <rte_malloc.h>
+#include <rte_tailq.h>
 
 #include "rte_reorder.h"
 
diff --git a/lib/librte_ring/rte_ring.c b/lib/librte_ring/rte_ring.c
index 9ea26a631..b30b2aa7b 100644
--- a/lib/librte_ring/rte_ring.c
+++ b/lib/librte_ring/rte_ring.c
@@ -30,6 +30,7 @@
 #include <rte_errno.h>
 #include <rte_string_fns.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_ring.h"
 
-- 
2.17.1

^ permalink raw reply	[relevance 8%]

* Re: [dpdk-dev] [PATCH v3] ethdev: support QinQ strip dynamic configuration
  @ 2019-06-27 11:08  3%   ` Ferruh Yigit
  2019-07-01 10:07  0%     ` Andrew Rybchenko
  0 siblings, 1 reply; 200+ results
From: Ferruh Yigit @ 2019-06-27 11:08 UTC (permalink / raw)
  To: viveksharma, thomas, arybchenko
  Cc: dev, intoviveksharma, stephen, ramirose, Jerin Jacob Kollanukkaran

On 4/19/2019 6:59 AM, viveksharma@marvell.com wrote:
> From: Vivek Sharma <viveksharma@marvell.com>
> 
> Enable missing support for runtime configuration (setting/getting)
> of QinQ strip rx offload for a given ethdev.
> 
> Signed-off-by: Vivek Sharma <viveksharma@marvell.com>

<...>

> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
> index 40a068f..c1792f4 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -550,11 +550,13 @@ struct rte_eth_rss_conf {
>  #define ETH_VLAN_STRIP_OFFLOAD   0x0001 /**< VLAN Strip  On/Off */
>  #define ETH_VLAN_FILTER_OFFLOAD  0x0002 /**< VLAN Filter On/Off */
>  #define ETH_VLAN_EXTEND_OFFLOAD  0x0004 /**< VLAN Extend On/Off */
> +#define ETH_QINQ_STRIP_OFFLOAD   0x0008 /**< QINQ Strip On/Off */
>  
>  /* Definitions used for mask VLAN setting */
>  #define ETH_VLAN_STRIP_MASK   0x0001 /**< VLAN Strip  setting mask */
>  #define ETH_VLAN_FILTER_MASK  0x0002 /**< VLAN Filter  setting mask*/
>  #define ETH_VLAN_EXTEND_MASK  0x0004 /**< VLAN Extend  setting mask*/
> +#define ETH_QINQ_STRIP_MASK   0x0008 /**< QINQ Strip  setting mask */
>  #define ETH_VLAN_ID_MAX       0x0FFF /**< VLAN ID is in lower 12 bits*/

On its own patch looks ok but a few high level questions:

1- Why we need this interim defines, instead of using actual offload values?
Although changing this will be API/ABI breakage.

2- Why we have specific function to set vlan offloads, for other offloads the
way is stop device and reconfigure it with new offload flags.

3- If devices can change offload configuration dynamically, do we need a generic
API to alter the offload configs? (similar to these vlan APIs but more generic)?



Related to the patch, what do you think about following options:
a)
- Get this patch
- Send a deprecation notice for 1) in this release
- Next release remove these flags, which will be practically reverse this patch
and more

b)
- Send a deprecation notice for 1) in this release
- Next release update the APIs and a smaller/different version of this patch
will be required.

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v2 28/28] sched: add release note
  2019-06-26 21:31  3%     ` Thomas Monjalon
@ 2019-06-27 10:50  0%       ` Singh, Jasvinder
  0 siblings, 0 replies; 200+ results
From: Singh, Jasvinder @ 2019-06-27 10:50 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, Dumitrescu, Cristian, Krakowiak, LukaszX, Tovar, AbrahamX



> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Wednesday, June 26, 2019 10:31 PM
> To: Singh, Jasvinder <jasvinder.singh@intel.com>
> Cc: dev@dpdk.org; Dumitrescu, Cristian <cristian.dumitrescu@intel.com>;
> Krakowiak, LukaszX <lukaszx.krakowiak@intel.com>; Tovar, AbrahamX
> <abrahamx.tovar@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v2 28/28] sched: add release note
> 
> 25/06/2019 17:32, Jasvinder Singh:
> > --- a/doc/guides/rel_notes/release_19_08.rst
> > +++ b/doc/guides/rel_notes/release_19_08.rst
> > @@ -135,6 +135,11 @@ API Changes
> > +* sched: To allow more traffic classes, flexible mapping of pipe queues to
> > +  traffic classes, and subport level configuration of pipes and queues
> > +  changes are made to public macros, data structures and API functions
> defined
> > +  in "rte_sched.h".
> 
> Does it make sense to merge this text in a code patch?

Will merge this code patch. 

> > --- a/lib/librte_sched/Makefile
> > +++ b/lib/librte_sched/Makefile
> > -LIBABIVER := 2
> > +LIBABIVER := 3
> 
> Please merge this change in the first patch breaking the ABI.
> 
Will do that.

Thanks,
Jasvinder


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 00/39] adding eventmode helper library
  2019-06-25 10:33  3% [dpdk-dev] [PATCH 00/39] adding eventmode helper library Jerin Jacob Kollanukkaran
@ 2019-06-27  5:28  0% ` Anoob Joseph
  2019-06-28  3:37  0%   ` Jerin Jacob Kollanukkaran
  0 siblings, 1 reply; 200+ results
From: Anoob Joseph @ 2019-06-27  5:28 UTC (permalink / raw)
  To: Jerin Jacob Kollanukkaran, Mattias Rönnblom, Nikhil Rao,
	Erik Gabriel Carrillo, Abhinandan Gujjar, Bruce Richardson,
	Pablo de Lara
  Cc: Narayana Prasad Raju Athreya, dev, Lukas Bartosik,
	Pavan Nikhilesh Bhagavatula, Hemant Agrawal, Nipun Gupta,
	Harry van Haaren, Liang Ma

Hi Jerin, Mattias,

Please see inline.

Thanks,
Anoob

> -----Original Message-----
> From: Jerin Jacob Kollanukkaran
> Sent: Tuesday, June 25, 2019 4:03 PM
> To: Anoob Joseph <anoobj@marvell.com>; Mattias Rönnblom
> <mattias.ronnblom@ericsson.com>; Nikhil Rao <nikhil.rao@intel.com>; Erik
> Gabriel Carrillo <erik.g.carrillo@intel.com>; Abhinandan Gujjar
> <abhinandan.gujjar@intel.com>; Bruce Richardson
> <bruce.richardson@intel.com>; Pablo de Lara
> <pablo.de.lara.guarch@intel.com>
> Cc: Narayana Prasad Raju Athreya <pathreya@marvell.com>; dev@dpdk.org;
> Lukas Bartosik <lbartosik@marvell.com>; Pavan Nikhilesh Bhagavatula
> <pbhagavatula@marvell.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>; Nipun Gupta <nipun.gupta@nxp.com>; Harry
> van Haaren <harry.van.haaren@intel.com>; Liang Ma
> <liang.j.ma@intel.com>
> Subject: RE: [dpdk-dev] Re: [PATCH 00/39] adding eventmode helper library
> 
> > -----Original Message-----
> > From: Anoob Joseph
> > Sent: Thursday, June 20, 2019 9:15 AM
> > To: Mattias Rönnblom <mattias.ronnblom@ericsson.com>; Jerin Jacob
> > Kollanukkaran <jerinj@marvell.com>; Nikhil Rao <nikhil.rao@intel.com>;
> > Erik Gabriel Carrillo <erik.g.carrillo@intel.com>; Abhinandan Gujjar
> > <abhinandan.gujjar@intel.com>; Bruce Richardson
> > <bruce.richardson@intel.com>; Pablo de Lara
> > <pablo.de.lara.guarch@intel.com>
> > Cc: Narayana Prasad Raju Athreya <pathreya@marvell.com>;
> dev@dpdk.org;
> > Lukas Bartosik <lbartosik@marvell.com>; Pavan Nikhilesh Bhagavatula
> > <pbhagavatula@marvell.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>;
> > Nipun Gupta <nipun.gupta@nxp.com>; Harry van Haaren
> > <harry.van.haaren@intel.com>; Liang Ma <liang.j.ma@intel.com>
> > Subject: RE: [dpdk-dev] [EXT] Re: [PATCH 00/39] adding eventmode
> > helper library
> > > However, the flexibility and many of the parameters are there for a
> > > reason (those there aren't should be deprecated). I would expect a
> > > real-world application to tweak quite a few of them. I know our
> > > applications
> > do.
> > >
> > > I worry I have is that if you put eventmode (in its current form)
> > > forward as a generic framework, applications might start using it,
> > > only to realize it's not flexible enough, and then eventmode is just
> > > an extra layer, increasing rather than reducing complexity. Or even
> > > worse, the application's developers are forced to do a big-bang
> > > switch over to using the event and ethernet device APIs directly, in
> > > case they can't patch DPDK to work around the eventmode-
> > > assumption-that-
> > didn't-hold-for-them.
> > >
> > > You could always add flexibility to the framework (as you encounter
> > > a need for it), but then it will grow in complexity as well.
> > >
> > > A less ambitious approach would be to instead do a properly
> > > modularized, non-trivial eventdev example application, for the
> > > applications to start off from, instead of a generic library.
> > >
> > > I would expect it to be very difficult to design a truly generic
> > > application framework for eventdev-based applications. Such a
> > > framework would tie everything that's needed in a non-trivial
> > > application together. If successful, it would be a huge step toward
> > > making DPDK an operating system for packet processing applications.
> >
> > [Anoob] The idea here is not to deprecate any event dev APIs. I do
> > agree that all the configuration exposed by eventdev & adapters are
> > required for various requirements in the real world applications. But
> > the requirement to understand & use all this configuration is making
> > the applications complicated and causes significant effort from anyone who
> would want to get started with event mode.
> > The idea of helper is to allow an easy framework for applications to
> > get started with eventmode, and then use various options from C/L or
> > config file (both
> > planned) to override the configuration as required. DPDK has
> > components like crypto-scheduler which abstracts lot of configuration
> > and simplify usage from application's perspective. This effort is on similar
> lines.
> >
> > My patchset is a followup to http://patches.dpdk.org/patch/37955 ,
> > wherein the approach of introducing a helper library for event mode
> > was mooted. The initial patch proposed additions in one application,
> > and that involved huge code additions just for doing the configuration.
> >
> > The helper library will be experimental while we add event-mode
> > support for other applications like l3fwd & ipsec-secgw. I expect the
> > helper library to be complete over the course of those applications also
> using the helper library.
> 
> 
> I have only concern about moving this as library inside eventdev that till we
> have mature version of helper library the eventdev library ABI will not
> stable(i.e .so file version needs to be incremented as when a change
> needed). Which align with Mattias thoughts for some other reason:. How
> about moving this code to
> 1) example/common or
> 2) to specific application itself, once at least two applications starts using it
> then move to Eventdev library.
> 
> Thoughts?

[Anoob] Either location is not a problem if there is a consensus. Earlier the suggestion was to move it to library (when the patch was submitted with changes added in app).

Since there are other comments, which are being addressed, I would like to send the next series with the current layout itself. And when we have an agreement on the location to be used, I'll make the changes. Is that fine?

> 
> 
> 
> 
> >
> > >
> > > What event devices have you tested with?
> >
> > [Anoob] Eventmode helper is tested with the following combinations,
> >     1. event-octeontx event PMD & nicvf eth PMD
> >     2. event-octeontx event PMD & eth-octeontx eth PMD

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH] malloc: deprecate unused set limit
@ 2019-06-26 22:32  4% Stephen Hemminger
  0 siblings, 0 replies; 200+ results
From: Stephen Hemminger @ 2019-06-26 22:32 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

The function rte_malloc_set_limit was defined but never implemented.
Mark it as deprecated for now, and remove in next release.

There is no point in keeping dead code.
"You Aren't Going to Need It"

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test/test_malloc.c                     | 21 ---------------------
 doc/guides/rel_notes/release_19_08.rst     |  3 +++
 lib/librte_eal/common/include/rte_malloc.h |  2 +-
 3 files changed, 4 insertions(+), 22 deletions(-)

diff --git a/app/test/test_malloc.c b/app/test/test_malloc.c
index f0e608cdaf22..7243e8389472 100644
--- a/app/test/test_malloc.c
+++ b/app/test/test_malloc.c
@@ -372,18 +372,6 @@ test_multi_alloc_statistics(void)
 	return 0;
 }
 
-static int
-test_rte_malloc_type_limits(void)
-{
-	/* The type-limits functionality is not yet implemented,
-	 * so always return 0 no matter what the retval.
-	 */
-	const char *typename = "limit_test";
-	rte_malloc_set_limit(typename, 64 * 1024);
-	rte_malloc_dump_stats(stdout, typename);
-	return 0;
-}
-
 static int
 test_realloc(void)
 {
@@ -952,15 +940,6 @@ test_malloc(void)
 	}
 	else printf("test_random_alloc_free() passed\n");
 
-	/*----------------------------*/
-	ret = test_rte_malloc_type_limits();
-	if (ret < 0){
-		printf("test_rte_malloc_type_limits() failed\n");
-		return ret;
-	}
-	/* TODO: uncomment following line once type limits are valid */
-	/*else printf("test_rte_malloc_type_limits() passed\n");*/
-
 	/*----------------------------*/
 	ret = test_rte_malloc_validate();
 	if (ret < 0){
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 3da26670550d..0e79390e16a1 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -135,6 +135,9 @@ API Changes
 * The network structures, definitions and functions have
   been prefixed by ``rte_`` to resolve conflicts with libc headers.
 
+* malloc: The function ``rte_malloc_set_limit`` was never implemented
+  is deprecated and will be removed in a future release.
+
 
 ABI Changes
 -----------
diff --git a/lib/librte_eal/common/include/rte_malloc.h b/lib/librte_eal/common/include/rte_malloc.h
index 5ff1a39a2e78..924a08605998 100644
--- a/lib/librte_eal/common/include/rte_malloc.h
+++ b/lib/librte_eal/common/include/rte_malloc.h
@@ -526,7 +526,7 @@ rte_malloc_dump_heaps(FILE *f);
  *   - 0: Success.
  *   - (-1): Error.
  */
-int
+int __rte_deprecated
 rte_malloc_set_limit(const char *type, size_t max);
 
 /**
-- 
2.20.1


^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v2 28/28] sched: add release note
  2019-06-25 15:32  4%   ` [dpdk-dev] [PATCH v2 28/28] sched: add release note Jasvinder Singh
@ 2019-06-26 21:31  3%     ` Thomas Monjalon
  2019-06-27 10:50  0%       ` Singh, Jasvinder
  0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2019-06-26 21:31 UTC (permalink / raw)
  To: Jasvinder Singh; +Cc: dev, cristian.dumitrescu, Lukasz Krakowiak, Abraham Tovar

25/06/2019 17:32, Jasvinder Singh:
> --- a/doc/guides/rel_notes/release_19_08.rst
> +++ b/doc/guides/rel_notes/release_19_08.rst
> @@ -135,6 +135,11 @@ API Changes
> +* sched: To allow more traffic classes, flexible mapping of pipe queues to
> +  traffic classes, and subport level configuration of pipes and queues
> +  changes are made to public macros, data structures and API functions defined
> +  in "rte_sched.h".

Does it make sense to merge this text in a code patch?

> --- a/lib/librte_sched/Makefile
> +++ b/lib/librte_sched/Makefile
> -LIBABIVER := 2
> +LIBABIVER := 3

Please merge this change in the first patch breaking the ABI.




^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v2] eal: fix positive error codes from probe/remove
  2019-06-07  8:32  3%     ` David Marchand
@ 2019-06-26 21:03  0%       ` Thomas Monjalon
  0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2019-06-26 21:03 UTC (permalink / raw)
  To: David Marchand
  Cc: dev, Ilya Maximets, Anatoly Burakov, Jan Blunck, Qi Zhang,
	Kevin Traynor, dpdk stable, Gaetan Rivet

07/06/2019 10:32, David Marchand:
> Thomas,
> 
> - Calling unplug on a device that is not attached is a bit weird to me, all
> the more so that we have rte_dev_probed().
> But there might be users calling directly the bus unplug api and not the
> official api...
> Does this enter the ABI stability perimeter?
> If not, I would be for changing unplug api so that we only deal with 0 or <
> 0 on remove path.

Where the positive value is documented?
If it's only a non-documented usage, I tend to think it can be changed.

> On the plug side, is there a reason why we do not check for
> rte_dev_probed() and let the bus replies that the device is already probed?

A device can be re-probed to allow discovering new ports.

> Does it have something to do with representors ?
> Only guessing.

Yes representors are a case of ports which can appear on a new probe.

> - On the plug side again, can't we have an indication from the buses that
> they have a driver that can handle the device rather than this odd (and
> historical) > 0 return code?
> This should not change the current behavior, just make the code a bit
> easier to understand.

The positive code is also used for white/blacklist.
And I think we may need to try probing in order to give a final answer,
in general case.




^ permalink raw reply	[relevance 0%]

* [dpdk-dev] minutes of techboard meeting 2019-05-15
@ 2019-06-26 10:18  3% Bruce Richardson
  0 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2019-06-26 10:18 UTC (permalink / raw)
  To: dev; +Cc: techboard

Attendees:
- Bruce Richardson
- Ferruh Yigit
- Jerin Jacob
- Konstantin Ananyev
- Maxime Conquelin
- Olivier Matz
- Stephen Hemminger
- Thomas Monjalon

Meeting Minutes 2019-05-15
---------------------------

Item #1: DPDK Developer Survey 
      - Discussion deferred till next meeting

Item #2: SW bbdev Driver in DPDK
      - Brief problem description:
            - turbo_sw PMD has a dependency on FlexRAN SW libraries, which
              cannot be downloaded without an SLA
            - FlexRAN libraries also have a dependency on ICC, while
              similarly cannot be downloaded and installed without an SLA
            - Thomas has been asking for a solution since End 2018, with
              little progress, so issue being brought to technical board

      - Agreement that the issue here is with the turbo_sw PMD specifically
        rather than bbdev framework

      - Discussion followed on what is acceptable or not for drivers in
        DPDK and their dependencies. Some points of consensus, some open
        issues.

            - Agreement that all DPDK PMDs themselves must be possible to
              compile with a DPDK supported compiler - GCC and/or clang
            - All PMDs must be possible for maintainers to compile, in order
              to maintain those PMDs
                  - this implies that all dependencies of the PMDs are easily
                    available for maintainers to download.
            - General consensus seems to be that so long as a dependency is
              freely available, binary rather than source is ok
                  - there is already a precedent for this with existing PMDs

      - Consensus that the issue with turbo_sw PMD needs to be resolved in
        this release, proposed target is rc1

      - Idea of having a staging area for drivers was proposed, idea was
        not generally liked.

      - Issue will be worked by tech board along with PMD maintainers to see
        what resolution can be reached quickly.

Item #3: ABI Policy
      - Issue deferred due to lack of time
      - Issue to be Item #1 on next week's agenda


Item #4: Security Policy
      - The mailing list "security-prerelease@dpdk.org" has been created
      - Member companies must apply to join this list to be informed in
        advance of security issues
            - requests to join are to be sent to techboard@dpdk.org
            - the technical board must then approve those requests
            - companies can have more than one address registered, but
              should keep number very small

Item #5: Removal of examples
      - Follow on from last week - to be discussed publically on mailing
        list rather than just in technical board


Next Meeting: 22nd May 2019. To be chaired by Ferruh Yigit.




^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH 0/2] Fix timer resource leak
    @ 2019-06-25 16:11  4%   ` Anatoly Burakov
  2019-07-05 13:20  4%     ` [dpdk-dev] [PATCH v2 0/1] " Anatoly Burakov
  1 sibling, 1 reply; 200+ results
From: Anatoly Burakov @ 2019-06-25 16:11 UTC (permalink / raw)
  To: dev; +Cc: erik.g.carrillo

Previous attempts [1] at fixing the resource leak have been
deemed unsuccessful because of limitations around what
can be done without breaking the ABI. Now that we've
broken the EAL ABI, we can fix this issue properly.

This patchset is adding a new lock API, as well as fixes the
actual issue.

The patchset dependson the FreeBSD fixes [2], as well as the
mem config patchset [3].

[1] http://patches.dpdk.org/patch/53334/
[2] http://patches.dpdk.org/project/dpdk/list/?series=5161
[3] http://patches.dpdk.org/project/dpdk/list/?series=5162

Anatoly Burakov (2):
  eal: add internal locks for timer lib into EAL
  timer: fix resource leak in finalize

 lib/librte_eal/common/eal_common_mcfg.c       | 14 +++++++
 lib/librte_eal/common/eal_memcfg.h            |  2 +
 .../common/include/rte_eal_memconfig.h        | 18 ++++++++
 lib/librte_eal/rte_eal_version.map            |  2 +
 lib/librte_timer/rte_timer.c                  | 41 +++++++++++++------
 lib/librte_timer/rte_timer.h                  |  5 ++-
 6 files changed, 67 insertions(+), 15 deletions(-)

-- 
2.17.1

^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v2 14/14] eal: prevent different primary/secondary process versions
    2019-06-25 16:05  6%         ` [dpdk-dev] [PATCH v2 09/14] eal: hide shared memory config Anatoly Burakov
@ 2019-06-25 16:05  3%         ` Anatoly Burakov
  1 sibling, 0 replies; 200+ results
From: Anatoly Burakov @ 2019-06-25 16:05 UTC (permalink / raw)
  To: dev; +Cc: Bruce Richardson, david.marchand, thomas, stephen

Currently, nothing stops DPDK to attempt to run primary and
secondary processes while having different versions. This
can lead to all sorts of weird behavior and makes it harder
to maintain compatibility without breaking ABI every once
in a while.

Fix it by explicitly disallowing running different DPDK
versions as primary and secondary processes.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_eal/common/eal_common_mcfg.c | 15 +++++++++++++++
 lib/librte_eal/common/eal_memcfg.h      |  6 ++++++
 lib/librte_eal/freebsd/eal/eal.c        | 14 ++++++++++++--
 lib/librte_eal/linux/eal/eal.c          | 14 ++++++++++++--
 4 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_mcfg.c b/lib/librte_eal/common/eal_common_mcfg.c
index fe8d2b726..1825d9083 100644
--- a/lib/librte_eal/common/eal_common_mcfg.c
+++ b/lib/librte_eal/common/eal_common_mcfg.c
@@ -4,6 +4,7 @@
 
 #include <rte_config.h>
 #include <rte_eal_memconfig.h>
+#include <rte_version.h>
 
 #include "eal_internal_cfg.h"
 #include "eal_memcfg.h"
@@ -31,6 +32,18 @@ eal_mcfg_wait_complete(void)
 		rte_pause();
 }
 
+int
+eal_mcfg_check_version(void)
+{
+	struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+
+	/* check if version from memconfig matches compiled in macro */
+	if (mcfg->version != RTE_VERSION)
+		return -1;
+
+	return 0;
+}
+
 void
 eal_mcfg_update_internal(void)
 {
@@ -47,6 +60,8 @@ eal_mcfg_update_from_internal(void)
 
 	mcfg->legacy_mem = internal_config.legacy_mem;
 	mcfg->single_file_segments = internal_config.single_file_segments;
+	/* record current DPDK version */
+	mcfg->version = RTE_VERSION;
 }
 
 void
diff --git a/lib/librte_eal/common/eal_memcfg.h b/lib/librte_eal/common/eal_memcfg.h
index 908542e18..e1aae32df 100644
--- a/lib/librte_eal/common/eal_memcfg.h
+++ b/lib/librte_eal/common/eal_memcfg.h
@@ -21,6 +21,8 @@
  */
 struct rte_mem_config {
 	volatile uint32_t magic;   /**< Magic number - Sanity check. */
+	uint32_t version;
+	/**< Prevent secondary processes using different DPDK versions. */
 
 	/* memory topology */
 	uint32_t nchannel;    /**< Number of channels (0 if unknown). */
@@ -80,6 +82,10 @@ eal_mcfg_update_from_internal(void);
 void
 eal_mcfg_wait_complete(void);
 
+/* check if DPDK version of current process matches one stored in the config */
+int
+eal_mcfg_check_version(void);
+
 /* set mem config as complete */
 void
 eal_mcfg_complete(void);
diff --git a/lib/librte_eal/freebsd/eal/eal.c b/lib/librte_eal/freebsd/eal/eal.c
index 81eb44670..ab06d9c6f 100644
--- a/lib/librte_eal/freebsd/eal/eal.c
+++ b/lib/librte_eal/freebsd/eal/eal.c
@@ -342,7 +342,7 @@ eal_proc_type_detect(void)
 }
 
 /* Sets up rte_config structure with the pointer to shared memory config.*/
-static void
+static int
 rte_config_init(void)
 {
 	rte_config.process_type = internal_config.process_type;
@@ -355,6 +355,10 @@ rte_config_init(void)
 	case RTE_PROC_SECONDARY:
 		rte_eal_config_attach();
 		eal_mcfg_wait_complete();
+		if (eal_mcfg_check_version() < 0) {
+			RTE_LOG(ERR, EAL, "Primary and secondary process DPDK version mismatch\n");
+			return -1;
+		}
 		rte_eal_config_reattach();
 		eal_mcfg_update_from_internal();
 		break;
@@ -362,6 +366,7 @@ rte_config_init(void)
 	case RTE_PROC_INVALID:
 		rte_panic("Invalid process type\n");
 	}
+	return 0;
 }
 
 /* display usage */
@@ -686,7 +691,12 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	rte_config_init();
+	if (rte_config_init() < 0) {
+		rte_eal_init_alert("Cannot init config");
+		rte_errno = EINVAL;
+		rte_atomic32_clear(&run_once);
+		return -1;
+	}
 
 	if (rte_eal_intr_init() < 0) {
 		rte_eal_init_alert("Cannot init interrupt-handling thread");
diff --git a/lib/librte_eal/linux/eal/eal.c b/lib/librte_eal/linux/eal/eal.c
index e2be87e23..4a38718aa 100644
--- a/lib/librte_eal/linux/eal/eal.c
+++ b/lib/librte_eal/linux/eal/eal.c
@@ -444,7 +444,7 @@ eal_proc_type_detect(void)
 }
 
 /* Sets up rte_config structure with the pointer to shared memory config.*/
-static void
+static int
 rte_config_init(void)
 {
 	rte_config.process_type = internal_config.process_type;
@@ -457,6 +457,10 @@ rte_config_init(void)
 	case RTE_PROC_SECONDARY:
 		rte_eal_config_attach();
 		eal_mcfg_wait_complete();
+		if (eal_mcfg_check_version() < 0) {
+			RTE_LOG(ERR, EAL, "Primary and secondary process DPDK version mismatch\n");
+			return -1;
+		}
 		rte_eal_config_reattach();
 		eal_mcfg_update_internal();
 		break;
@@ -464,6 +468,7 @@ rte_config_init(void)
 	case RTE_PROC_INVALID:
 		rte_panic("Invalid process type\n");
 	}
+	return 0;
 }
 
 /* Unlocks hugepage directories that were locked by eal_hugepage_info_init */
@@ -971,7 +976,12 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	rte_config_init();
+	if (rte_config_init() < 0) {
+		rte_eal_init_alert("Cannot init config");
+		rte_errno = EINVAL;
+		rte_atomic32_clear(&run_once);
+		return -1;
+	}
 
 	if (rte_eal_intr_init() < 0) {
 		rte_eal_init_alert("Cannot init interrupt-handling thread");
-- 
2.17.1

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v2 09/14] eal: hide shared memory config
  @ 2019-06-25 16:05  6%         ` Anatoly Burakov
  2019-06-25 16:05  3%         ` [dpdk-dev] [PATCH v2 14/14] eal: prevent different primary/secondary process versions Anatoly Burakov
  1 sibling, 0 replies; 200+ results
From: Anatoly Burakov @ 2019-06-25 16:05 UTC (permalink / raw)
  To: dev
  Cc: Neil Horman, John McNamara, Marko Kovacevic, Konstantin Ananyev,
	David Hunt, Bruce Richardson, Byron Marohn, Pablo de Lara Guarch,
	Yipeng Wang, Sameh Gobriel, Vladimir Medvedkin, Olivier Matz,
	Andrew Rybchenko, Reshma Pattan, david.marchand, thomas, stephen

Now that everything that has ever accessed the shared memory
config is doing so through the public API's, we can make it
internal. Since we're removing quite a few headers from
rte_eal_memconfig.h, we need to add them back in places
where this header is used.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 app/test/test_memzone.c                       |  1 +
 app/test/test_tailq.c                         |  1 +
 doc/guides/rel_notes/deprecation.rst          |  3 -
 doc/guides/rel_notes/release_19_08.rst        |  8 +-
 drivers/bus/pci/linux/pci_vfio.c              |  1 +
 lib/librte_acl/rte_acl.c                      |  2 +
 lib/librte_distributor/rte_distributor.c      |  1 +
 lib/librte_distributor/rte_distributor_v20.c  |  1 +
 lib/librte_eal/common/eal_common_mcfg.c       |  2 +
 lib/librte_eal/common/eal_common_memory.c     |  1 +
 lib/librte_eal/common/eal_common_memzone.c    |  1 +
 lib/librte_eal/common/eal_common_tailqs.c     |  1 +
 lib/librte_eal/common/eal_memcfg.h            | 79 +++++++++++++++++++
 .../common/include/rte_eal_memconfig.h        | 75 ++----------------
 lib/librte_eal/common/malloc_heap.c           |  2 +
 lib/librte_eal/common/malloc_mp.c             |  1 +
 lib/librte_eal/common/rte_malloc.c            |  1 +
 lib/librte_eal/freebsd/eal/Makefile           |  2 +-
 lib/librte_eal/freebsd/eal/eal_memory.c       |  1 +
 lib/librte_eal/linux/eal/Makefile             |  2 +-
 lib/librte_eal/linux/eal/eal.c                |  1 +
 lib/librte_eal/linux/eal/eal_memalloc.c       |  1 +
 lib/librte_eal/linux/eal/eal_memory.c         |  1 +
 lib/librte_eal/linux/eal/eal_vfio.c           |  1 +
 lib/librte_eal/meson.build                    |  2 +-
 lib/librte_efd/rte_efd.c                      |  1 +
 lib/librte_hash/rte_cuckoo_hash.c             |  1 +
 lib/librte_hash/rte_fbk_hash.c                |  1 +
 lib/librte_lpm/rte_lpm.c                      |  1 +
 lib/librte_lpm/rte_lpm6.c                     |  1 +
 lib/librte_member/rte_member.c                |  1 +
 lib/librte_mempool/rte_mempool.c              |  1 +
 lib/librte_reorder/rte_reorder.c              |  1 +
 lib/librte_ring/rte_ring.c                    |  1 +
 34 files changed, 125 insertions(+), 76 deletions(-)
 create mode 100644 lib/librte_eal/common/eal_memcfg.h

diff --git a/app/test/test_memzone.c b/app/test/test_memzone.c
index 9fe465e62..7501b63c5 100644
--- a/app/test/test_memzone.c
+++ b/app/test/test_memzone.c
@@ -19,6 +19,7 @@
 #include <rte_errno.h>
 #include <rte_malloc.h>
 #include "../../lib/librte_eal/common/malloc_elem.h"
+#include "../../lib/librte_eal/common/eal_memcfg.h"
 
 #include "test.h"
 
diff --git a/app/test/test_tailq.c b/app/test/test_tailq.c
index a4ecea2d8..7c9b69fdb 100644
--- a/app/test/test_tailq.c
+++ b/app/test/test_tailq.c
@@ -12,6 +12,7 @@
 #include <rte_eal.h>
 #include <rte_eal_memconfig.h>
 #include <rte_string_fns.h>
+#include <rte_tailq.h>
 
 #include "test.h"
 
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index e2721fad6..583217da8 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -23,9 +23,6 @@ Deprecation Notices
 * eal: The function ``rte_eal_remote_launch`` will return new error codes
   after read or write error on the pipe, instead of calling ``rte_panic``.
 
-* eal: the ``rte_mem_config`` struct will be made private to remove it from the
-  externally visible ABI and allow it to be updated in the future.
-
 * eal: both declaring and identifying devices will be streamlined in v18.11.
   New functions will appear to query a specific port from buses, classes of
   device and device drivers. Device declaration will be made coherent with the
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 3da266705..b6314431a 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -132,6 +132,10 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* The ``rte_mem_config`` structure has been made private. The new accessor
+  ``rte_mcfg_*`` functions were introduced to provide replacement for direct
+  access to the shared mem config.
+
 * The network structures, definitions and functions have
   been prefixed by ``rte_`` to resolve conflicts with libc headers.
 
@@ -151,6 +155,8 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* The ``rte_mem_config`` structure has been made private.
+
 
 Shared Library Versions
 -----------------------
@@ -184,7 +190,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_compressdev.so.1
      librte_cryptodev.so.7
      librte_distributor.so.1
-     librte_eal.so.10
+   + librte_eal.so.11
      librte_efd.so.1
      librte_ethdev.so.12
      librte_eventdev.so.6
diff --git a/drivers/bus/pci/linux/pci_vfio.c b/drivers/bus/pci/linux/pci_vfio.c
index ebf6ccd3c..1ceb1c07b 100644
--- a/drivers/bus/pci/linux/pci_vfio.c
+++ b/drivers/bus/pci/linux/pci_vfio.c
@@ -20,6 +20,7 @@
 #include <rte_eal.h>
 #include <rte_bus.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "eal_filesystem.h"
 
diff --git a/lib/librte_acl/rte_acl.c b/lib/librte_acl/rte_acl.c
index 7ff11d25f..bd7247cc3 100644
--- a/lib/librte_acl/rte_acl.c
+++ b/lib/librte_acl/rte_acl.c
@@ -4,6 +4,8 @@
 
 #include <rte_string_fns.h>
 #include <rte_acl.h>
+#include <rte_tailq.h>
+
 #include "acl.h"
 
 TAILQ_HEAD(rte_acl_list, rte_tailq_entry);
diff --git a/lib/librte_distributor/rte_distributor.c b/lib/librte_distributor/rte_distributor.c
index 9eb78b330..0a3213bbf 100644
--- a/lib/librte_distributor/rte_distributor.c
+++ b/lib/librte_distributor/rte_distributor.c
@@ -14,6 +14,7 @@
 #include <rte_string_fns.h>
 #include <rte_eal_memconfig.h>
 #include <rte_pause.h>
+#include <rte_tailq.h>
 
 #include "rte_distributor_private.h"
 #include "rte_distributor.h"
diff --git a/lib/librte_distributor/rte_distributor_v20.c b/lib/librte_distributor/rte_distributor_v20.c
index 1fc03b971..cdc0969a8 100644
--- a/lib/librte_distributor/rte_distributor_v20.c
+++ b/lib/librte_distributor/rte_distributor_v20.c
@@ -13,6 +13,7 @@
 #include <rte_string_fns.h>
 #include <rte_eal_memconfig.h>
 #include <rte_pause.h>
+#include <rte_tailq.h>
 
 #include "rte_distributor_v20.h"
 #include "rte_distributor_private.h"
diff --git a/lib/librte_eal/common/eal_common_mcfg.c b/lib/librte_eal/common/eal_common_mcfg.c
index ba2bc37b7..337890a61 100644
--- a/lib/librte_eal/common/eal_common_mcfg.c
+++ b/lib/librte_eal/common/eal_common_mcfg.c
@@ -5,6 +5,8 @@
 #include <rte_config.h>
 #include <rte_eal_memconfig.h>
 
+#include "eal_memcfg.h"
+
 void
 rte_mcfg_mem_read_lock(void)
 {
diff --git a/lib/librte_eal/common/eal_common_memory.c b/lib/librte_eal/common/eal_common_memory.c
index e73a413cc..b33bc4b29 100644
--- a/lib/librte_eal/common/eal_common_memory.c
+++ b/lib/librte_eal/common/eal_common_memory.c
@@ -24,6 +24,7 @@
 #include "eal_memalloc.h"
 #include "eal_private.h"
 #include "eal_internal_cfg.h"
+#include "eal_memcfg.h"
 #include "malloc_heap.h"
 
 /*
diff --git a/lib/librte_eal/common/eal_common_memzone.c b/lib/librte_eal/common/eal_common_memzone.c
index 521ad7ca1..ef6c909cb 100644
--- a/lib/librte_eal/common/eal_common_memzone.c
+++ b/lib/librte_eal/common/eal_common_memzone.c
@@ -24,6 +24,7 @@
 #include "malloc_heap.h"
 #include "malloc_elem.h"
 #include "eal_private.h"
+#include "eal_memcfg.h"
 
 static inline const struct rte_memzone *
 memzone_lookup_thread_unsafe(const char *name)
diff --git a/lib/librte_eal/common/eal_common_tailqs.c b/lib/librte_eal/common/eal_common_tailqs.c
index dc2c13caa..ead06897b 100644
--- a/lib/librte_eal/common/eal_common_tailqs.c
+++ b/lib/librte_eal/common/eal_common_tailqs.c
@@ -23,6 +23,7 @@
 #include <rte_debug.h>
 
 #include "eal_private.h"
+#include "eal_memcfg.h"
 
 TAILQ_HEAD(rte_tailq_elem_head, rte_tailq_elem);
 /* local tailq list */
diff --git a/lib/librte_eal/common/eal_memcfg.h b/lib/librte_eal/common/eal_memcfg.h
new file mode 100644
index 000000000..466958352
--- /dev/null
+++ b/lib/librte_eal/common/eal_memcfg.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef EAL_MEMCFG_H
+#define EAL_MEMCFG_H
+
+#include <rte_config.h>
+#include <rte_eal_memconfig.h>
+#include <rte_malloc_heap.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_pause.h>
+#include <rte_rwlock.h>
+#include <rte_tailq.h>
+
+/**
+ * the structure for the memory configuration for the RTE.
+ * Used by the rte_config structure. It is separated out, as for multi-process
+ * support, the memory details should be shared across instances
+ */
+struct rte_mem_config {
+	volatile uint32_t magic;   /**< Magic number - Sanity check. */
+
+	/* memory topology */
+	uint32_t nchannel;    /**< Number of channels (0 if unknown). */
+	uint32_t nrank;       /**< Number of ranks (0 if unknown). */
+
+	/**
+	 * current lock nest order
+	 *  - qlock->mlock (ring/hash/lpm)
+	 *  - mplock->qlock->mlock (mempool)
+	 * Notice:
+	 *  *ALWAYS* obtain qlock first if having to obtain both qlock and mlock
+	 */
+	rte_rwlock_t mlock;   /**< only used by memzone LIB for thread-safe. */
+	rte_rwlock_t qlock;   /**< used for tailq operation for thread safe. */
+	rte_rwlock_t mplock;  /**< only used by mempool LIB for thread-safe. */
+
+	rte_rwlock_t memory_hotplug_lock;
+	/**< indicates whether memory hotplug request is in progress. */
+
+	/* memory segments and zones */
+	struct rte_fbarray memzones; /**< Memzone descriptors. */
+
+	struct rte_memseg_list memsegs[RTE_MAX_MEMSEG_LISTS];
+	/**< list of dynamic arrays holding memsegs */
+
+	struct rte_tailq_head tailq_head[RTE_MAX_TAILQ];
+	/**< Tailqs for objects */
+
+	/* Heaps of Malloc */
+	struct malloc_heap malloc_heaps[RTE_MAX_HEAPS];
+
+	/* next socket ID for external malloc heap */
+	int next_socket_id;
+
+	/* address of mem_config in primary process. used to map shared config
+	 * into exact same address the primary process maps it.
+	 */
+	uint64_t mem_cfg_addr;
+
+	/* legacy mem and single file segments options are shared */
+	uint32_t legacy_mem;
+	uint32_t single_file_segments;
+
+	/* keeps the more restricted dma mask */
+	uint8_t dma_maskbits;
+} __attribute__((packed));
+
+static inline void
+rte_eal_mcfg_wait_complete(struct rte_mem_config *mcfg)
+{
+	/* wait until shared mem_config finish initialising */
+	while (mcfg->magic != RTE_MAGIC)
+		rte_pause();
+}
+
+#endif /* EAL_MEMCFG_H */
diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
index 58dcbb96d..1b615c892 100644
--- a/lib/librte_eal/common/include/rte_eal_memconfig.h
+++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
@@ -5,13 +5,12 @@
 #ifndef _RTE_EAL_MEMCONFIG_H_
 #define _RTE_EAL_MEMCONFIG_H_
 
-#include <rte_config.h>
-#include <rte_tailq.h>
-#include <rte_memory.h>
-#include <rte_memzone.h>
-#include <rte_malloc_heap.h>
-#include <rte_rwlock.h>
-#include <rte_pause.h>
+/**
+ * @file
+ *
+ * This API allows access to EAL shared memory configuration through an API.
+ */
+
 #include <rte_fbarray.h>
 
 #ifdef __cplusplus
@@ -38,68 +37,6 @@ struct rte_memseg_list {
 	struct rte_fbarray memseg_arr;
 };
 
-/**
- * the structure for the memory configuration for the RTE.
- * Used by the rte_config structure. It is separated out, as for multi-process
- * support, the memory details should be shared across instances
- */
-struct rte_mem_config {
-	volatile uint32_t magic;   /**< Magic number - Sanity check. */
-
-	/* memory topology */
-	uint32_t nchannel;    /**< Number of channels (0 if unknown). */
-	uint32_t nrank;       /**< Number of ranks (0 if unknown). */
-
-	/**
-	 * current lock nest order
-	 *  - qlock->mlock (ring/hash/lpm)
-	 *  - mplock->qlock->mlock (mempool)
-	 * Notice:
-	 *  *ALWAYS* obtain qlock first if having to obtain both qlock and mlock
-	 */
-	rte_rwlock_t mlock;   /**< only used by memzone LIB for thread-safe. */
-	rte_rwlock_t qlock;   /**< used for tailq operation for thread safe. */
-	rte_rwlock_t mplock;  /**< only used by mempool LIB for thread-safe. */
-
-	rte_rwlock_t memory_hotplug_lock;
-	/**< indicates whether memory hotplug request is in progress. */
-
-	/* memory segments and zones */
-	struct rte_fbarray memzones; /**< Memzone descriptors. */
-
-	struct rte_memseg_list memsegs[RTE_MAX_MEMSEG_LISTS];
-	/**< list of dynamic arrays holding memsegs */
-
-	struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**< Tailqs for objects */
-
-	/* Heaps of Malloc */
-	struct malloc_heap malloc_heaps[RTE_MAX_HEAPS];
-
-	/* next socket ID for external malloc heap */
-	int next_socket_id;
-
-	/* address of mem_config in primary process. used to map shared config into
-	 * exact same address the primary process maps it.
-	 */
-	uint64_t mem_cfg_addr;
-
-	/* legacy mem and single file segments options are shared */
-	uint32_t legacy_mem;
-	uint32_t single_file_segments;
-
-	/* keeps the more restricted dma mask */
-	uint8_t dma_maskbits;
-} __attribute__((__packed__));
-
-
-inline static void
-rte_eal_mcfg_wait_complete(struct rte_mem_config* mcfg)
-{
-	/* wait until shared mem_config finish initialising */
-	while(mcfg->magic != RTE_MAGIC)
-		rte_pause();
-}
-
 /**
  * Lock the internal EAL shared memory configuration for shared access.
  */
diff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c
index f1d31de0d..634ca212f 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -20,11 +20,13 @@
 #include <rte_string_fns.h>
 #include <rte_spinlock.h>
 #include <rte_memcpy.h>
+#include <rte_memzone.h>
 #include <rte_atomic.h>
 #include <rte_fbarray.h>
 
 #include "eal_internal_cfg.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 #include "malloc_elem.h"
 #include "malloc_heap.h"
 #include "malloc_mp.h"
diff --git a/lib/librte_eal/common/malloc_mp.c b/lib/librte_eal/common/malloc_mp.c
index 7c6112c4e..1f212f834 100644
--- a/lib/librte_eal/common/malloc_mp.c
+++ b/lib/librte_eal/common/malloc_mp.c
@@ -10,6 +10,7 @@
 #include <rte_string_fns.h>
 
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 
 #include "malloc_elem.h"
 #include "malloc_mp.h"
diff --git a/lib/librte_eal/common/rte_malloc.c b/lib/librte_eal/common/rte_malloc.c
index 98e1bdd07..8d2ef8aeb 100644
--- a/lib/librte_eal/common/rte_malloc.c
+++ b/lib/librte_eal/common/rte_malloc.c
@@ -25,6 +25,7 @@
 #include "malloc_elem.h"
 #include "malloc_heap.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 
 
 /* Free the memory space back to heap */
diff --git a/lib/librte_eal/freebsd/eal/Makefile b/lib/librte_eal/freebsd/eal/Makefile
index dc56af582..0974518ab 100644
--- a/lib/librte_eal/freebsd/eal/Makefile
+++ b/lib/librte_eal/freebsd/eal/Makefile
@@ -22,7 +22,7 @@ LDLIBS += -lrte_kvargs
 
 EXPORT_MAP := ../../rte_eal_version.map
 
-LIBABIVER := 10
+LIBABIVER := 11
 
 # specific to freebsd exec-env
 SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) := eal.c
diff --git a/lib/librte_eal/freebsd/eal/eal_memory.c b/lib/librte_eal/freebsd/eal/eal_memory.c
index 4b092e1f2..9b9a0577a 100644
--- a/lib/librte_eal/freebsd/eal/eal_memory.c
+++ b/lib/librte_eal/freebsd/eal/eal_memory.c
@@ -18,6 +18,7 @@
 #include "eal_private.h"
 #include "eal_internal_cfg.h"
 #include "eal_filesystem.h"
+#include "eal_memcfg.h"
 
 #define EAL_PAGE_SIZE (sysconf(_SC_PAGESIZE))
 
diff --git a/lib/librte_eal/linux/eal/Makefile b/lib/librte_eal/linux/eal/Makefile
index 3b2642eb8..9c885a9c9 100644
--- a/lib/librte_eal/linux/eal/Makefile
+++ b/lib/librte_eal/linux/eal/Makefile
@@ -10,7 +10,7 @@ ARCH_DIR ?= $(RTE_ARCH)
 EXPORT_MAP := ../../rte_eal_version.map
 VPATH += $(RTE_SDK)/lib/librte_eal/common/arch/$(ARCH_DIR)
 
-LIBABIVER := 10
+LIBABIVER := 11
 
 VPATH += $(RTE_SDK)/lib/librte_eal/common
 
diff --git a/lib/librte_eal/linux/eal/eal.c b/lib/librte_eal/linux/eal/eal.c
index 3e1d6eb6a..0fc99de5b 100644
--- a/lib/librte_eal/linux/eal/eal.c
+++ b/lib/librte_eal/linux/eal/eal.c
@@ -57,6 +57,7 @@
 #include "eal_internal_cfg.h"
 #include "eal_filesystem.h"
 #include "eal_hugepages.h"
+#include "eal_memcfg.h"
 #include "eal_options.h"
 #include "eal_vfio.h"
 
diff --git a/lib/librte_eal/linux/eal/eal_memalloc.c b/lib/librte_eal/linux/eal/eal_memalloc.c
index 2019636fb..1f6a7c18f 100644
--- a/lib/librte_eal/linux/eal/eal_memalloc.c
+++ b/lib/librte_eal/linux/eal/eal_memalloc.c
@@ -44,6 +44,7 @@
 #include "eal_filesystem.h"
 #include "eal_internal_cfg.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 #include "eal_private.h"
 
 const int anonymous_hugepages_supported =
diff --git a/lib/librte_eal/linux/eal/eal_memory.c b/lib/librte_eal/linux/eal/eal_memory.c
index 1853acea5..9c948a374 100644
--- a/lib/librte_eal/linux/eal/eal_memory.c
+++ b/lib/librte_eal/linux/eal/eal_memory.c
@@ -46,6 +46,7 @@
 
 #include "eal_private.h"
 #include "eal_memalloc.h"
+#include "eal_memcfg.h"
 #include "eal_internal_cfg.h"
 #include "eal_filesystem.h"
 #include "eal_hugepages.h"
diff --git a/lib/librte_eal/linux/eal/eal_vfio.c b/lib/librte_eal/linux/eal/eal_vfio.c
index 924cba526..5d679ca68 100644
--- a/lib/librte_eal/linux/eal/eal_vfio.c
+++ b/lib/librte_eal/linux/eal/eal_vfio.c
@@ -15,6 +15,7 @@
 #include <rte_vfio.h>
 
 #include "eal_filesystem.h"
+#include "eal_memcfg.h"
 #include "eal_vfio.h"
 #include "eal_private.h"
 
diff --git a/lib/librte_eal/meson.build b/lib/librte_eal/meson.build
index fa36b20e0..5c5023dd4 100644
--- a/lib/librte_eal/meson.build
+++ b/lib/librte_eal/meson.build
@@ -12,7 +12,7 @@ subdir('common') # defines common_sources, common_objs, etc.
 dpdk_conf.set('RTE_EXEC_ENV_' + exec_env.to_upper(), 1)
 subdir(exec_env + '/eal')
 
-version = 10  # the version of the EAL API
+version = 11  # the version of the EAL API
 allow_experimental_apis = true
 deps += 'kvargs'
 if dpdk_conf.has('RTE_USE_LIBBSD')
diff --git a/lib/librte_efd/rte_efd.c b/lib/librte_efd/rte_efd.c
index b808ce99f..d3d019578 100644
--- a/lib/librte_efd/rte_efd.c
+++ b/lib/librte_efd/rte_efd.c
@@ -20,6 +20,7 @@
 #include <rte_ring.h>
 #include <rte_jhash.h>
 #include <rte_hash_crc.h>
+#include <rte_tailq.h>
 
 #include "rte_efd.h"
 #if defined(RTE_ARCH_X86)
diff --git a/lib/librte_hash/rte_cuckoo_hash.c b/lib/librte_hash/rte_cuckoo_hash.c
index 865c744d9..b76518b4c 100644
--- a/lib/librte_hash/rte_cuckoo_hash.c
+++ b/lib/librte_hash/rte_cuckoo_hash.c
@@ -27,6 +27,7 @@
 #include <rte_ring.h>
 #include <rte_compat.h>
 #include <rte_vect.h>
+#include <rte_tailq.h>
 
 #include "rte_hash.h"
 #include "rte_cuckoo_hash.h"
diff --git a/lib/librte_hash/rte_fbk_hash.c b/lib/librte_hash/rte_fbk_hash.c
index db118c930..576e8e666 100644
--- a/lib/librte_hash/rte_fbk_hash.c
+++ b/lib/librte_hash/rte_fbk_hash.c
@@ -20,6 +20,7 @@
 #include <rte_cpuflags.h>
 #include <rte_log.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_fbk_hash.h"
 
diff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c
index b91f74216..70c24ac1f 100644
--- a/lib/librte_lpm/rte_lpm.c
+++ b/lib/librte_lpm/rte_lpm.c
@@ -21,6 +21,7 @@
 #include <rte_errno.h>
 #include <rte_rwlock.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_lpm.h"
 
diff --git a/lib/librte_lpm/rte_lpm6.c b/lib/librte_lpm/rte_lpm6.c
index 5af74a539..9b8aeb972 100644
--- a/lib/librte_lpm/rte_lpm6.c
+++ b/lib/librte_lpm/rte_lpm6.c
@@ -24,6 +24,7 @@
 #include <rte_hash.h>
 #include <assert.h>
 #include <rte_jhash.h>
+#include <rte_tailq.h>
 
 #include "rte_lpm6.h"
 
diff --git a/lib/librte_member/rte_member.c b/lib/librte_member/rte_member.c
index efed28dd9..e0e7f127e 100644
--- a/lib/librte_member/rte_member.c
+++ b/lib/librte_member/rte_member.c
@@ -10,6 +10,7 @@
 #include <rte_memory.h>
 #include <rte_malloc.h>
 #include <rte_errno.h>
+#include <rte_tailq.h>
 
 #include "rte_member.h"
 #include "rte_member_ht.h"
diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c
index 5c688d456..7260ce0be 100644
--- a/lib/librte_mempool/rte_mempool.c
+++ b/lib/librte_mempool/rte_mempool.c
@@ -30,6 +30,7 @@
 #include <rte_errno.h>
 #include <rte_string_fns.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_mempool.h"
 
diff --git a/lib/librte_reorder/rte_reorder.c b/lib/librte_reorder/rte_reorder.c
index ae6e3f578..3c9f0e2d0 100644
--- a/lib/librte_reorder/rte_reorder.c
+++ b/lib/librte_reorder/rte_reorder.c
@@ -11,6 +11,7 @@
 #include <rte_eal_memconfig.h>
 #include <rte_errno.h>
 #include <rte_malloc.h>
+#include <rte_tailq.h>
 
 #include "rte_reorder.h"
 
diff --git a/lib/librte_ring/rte_ring.c b/lib/librte_ring/rte_ring.c
index 9ea26a631..b30b2aa7b 100644
--- a/lib/librte_ring/rte_ring.c
+++ b/lib/librte_ring/rte_ring.c
@@ -30,6 +30,7 @@
 #include <rte_errno.h>
 #include <rte_string_fns.h>
 #include <rte_spinlock.h>
+#include <rte_tailq.h>
 
 #include "rte_ring.h"
 
-- 
2.17.1

^ permalink raw reply	[relevance 6%]

* [dpdk-dev] [PATCH v2 28/28] sched: add release note
  @ 2019-06-25 15:32  4%   ` Jasvinder Singh
  2019-06-26 21:31  3%     ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Jasvinder Singh @ 2019-06-25 15:32 UTC (permalink / raw)
  To: dev; +Cc: cristian.dumitrescu, Lukasz Krakowiak, Abraham Tovar

From: Lukasz Krakowiak <lukaszx.krakowiak@intel.com>

Add release notes and remove deprecation note.

Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
Signed-off-by: Abraham Tovar <abrahamx.tovar@intel.com>
Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com>
---
 doc/guides/rel_notes/deprecation.rst   | 6 ------
 doc/guides/rel_notes/release_19_08.rst | 7 ++++++-
 lib/librte_sched/Makefile              | 2 +-
 lib/librte_sched/meson.build           | 2 +-
 4 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index e2721fad6..4810989da 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -86,12 +86,6 @@ Deprecation Notices
   to one it means it represents IV, when is set to zero it means J0 is used
   directly, in this case 16 bytes of J0 need to be passed.
 
-* sched: To allow more traffic classes, flexible mapping of pipe queues to
-  traffic classes, and subport level configuration of pipes and queues
-  changes will be made to macros, data structures and API functions defined
-  in "rte_sched.h". These changes are aligned to improvements suggested in the
-  RFC https://mails.dpdk.org/archives/dev/2018-November/120035.html.
-
 * metrics: The function ``rte_metrics_init`` will have a non-void return
   in order to notify errors instead of calling ``rte_exit``.
 
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 3da266705..8fe08424a 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -135,6 +135,11 @@ API Changes
 * The network structures, definitions and functions have
   been prefixed by ``rte_`` to resolve conflicts with libc headers.
 
+* sched: To allow more traffic classes, flexible mapping of pipe queues to
+  traffic classes, and subport level configuration of pipes and queues
+  changes are made to public macros, data structures and API functions defined
+  in "rte_sched.h".
+
 
 ABI Changes
 -----------
@@ -222,7 +227,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_rcu.so.1
      librte_reorder.so.1
      librte_ring.so.2
-     librte_sched.so.2
+   + librte_sched.so.3
      librte_security.so.2
      librte_stack.so.1
      librte_table.so.3
diff --git a/lib/librte_sched/Makefile b/lib/librte_sched/Makefile
index 644fd9d15..3d7f410e1 100644
--- a/lib/librte_sched/Makefile
+++ b/lib/librte_sched/Makefile
@@ -18,7 +18,7 @@ LDLIBS += -lrte_timer
 
 EXPORT_MAP := rte_sched_version.map
 
-LIBABIVER := 2
+LIBABIVER := 3
 
 #
 # all source are stored in SRCS-y
diff --git a/lib/librte_sched/meson.build b/lib/librte_sched/meson.build
index 8e989e5f6..59d43c6d8 100644
--- a/lib/librte_sched/meson.build
+++ b/lib/librte_sched/meson.build
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017 Intel Corporation
 
-version = 2
+version = 3
 sources = files('rte_sched.c', 'rte_red.c', 'rte_approx.c')
 headers = files('rte_sched.h', 'rte_sched_common.h',
 		'rte_red.h', 'rte_approx.h')
-- 
2.21.0


^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v4] cryptodev: make xform key pointer constant
  2019-06-24 13:35  3% ` [dpdk-dev] [PATCH v4] " Fan Zhang
@ 2019-06-25 12:46  4%   ` Akhil Goyal
  2019-07-05 12:30  0%     ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Akhil Goyal @ 2019-06-25 12:46 UTC (permalink / raw)
  To: Fan Zhang, dev; +Cc: pablo.de.lara.guarch



> 
> This patch changes the key pointer data types in cipher, auth,
> and aead xforms from "uint8_t *" to "const uint8_t *" for a
> more intuitive and safe sessionn creation.
> 
> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
> Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
> Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
> ---
> v4:
> - Removed deprecation notice and updated release note.
> - Updated ABI version.
> 
> v3:
> - rebased on top of latest dpdk-next-crypto
> 
> v2:
> - fixed a missed memory free for ixgbe ipsec

Applied to dpdk-next-crypto
The changes related to update for ABI version were incomplete in this patch, so they were dropped. Another patch from Anoob was also updating the ABI version, so not required in this patch.

Thanks.


^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v3] eventdev: change Rx adapter callback and stats structure
    2019-06-13 23:28  3% ` [dpdk-dev] [PATCH v2] eventdev: change Rx adapter callback and stats structure Nikhil Rao
@ 2019-06-24 23:16 15% ` Nikhil Rao
  1 sibling, 0 replies; 200+ results
From: Nikhil Rao @ 2019-06-24 23:16 UTC (permalink / raw)
  To: jerinj; +Cc: nikhil.rao, dev

Replace the mbuf pointer array in the event eth Rx adapter
callback with an event array. Using an event array allows
the application to change attributes of the events enqueued
by the SW adapter.

The callback can drop packets and populate a callback
argument with the number of dropped packets. Add a Rx adapter
stats field to keep track of the total number of dropped packets.

This commit removes the experimental tags from
the callback and stats APIs, the experimental tag from eventdev
is also removed and eventdev functions become part of the
main DPDK API/ABI.

Signed-off-by: Nikhil Rao <nikhil.rao@intel.com>
---
 lib/librte_eventdev/rte_event_eth_rx_adapter.h | 82 +++++++++++++-------------
 lib/librte_eventdev/rte_event_eth_rx_adapter.c | 34 ++++++-----
 MAINTAINERS                                    |  2 +-
 doc/guides/rel_notes/release_19_08.rst         | 20 ++++++-
 lib/librte_eventdev/Makefile                   |  2 +-
 lib/librte_eventdev/meson.build                |  2 +-
 lib/librte_eventdev/rte_eventdev_version.map   |  4 +-
 7 files changed, 83 insertions(+), 63 deletions(-)

v1:
* add implementation to RFC

v2:
* Bump library version
* Combine patch 1 & 2 into a single patch (single library version bump)
* Mention API change in release notes
* Remove __rte_experimental tag
* Remove EXPERIMENTAL status for eventdev

v3:
* Update version = 7 in lib/librte_eventdev/meson.build
* Update the "git comment and release notes" to mention the removal of
  experimental status
* Reduce rte_event_eth_rx_adapter.c line count

diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.h b/lib/librte_eventdev/rte_event_eth_rx_adapter.h
index beab870..99b55a8 100644
--- a/lib/librte_eventdev/rte_event_eth_rx_adapter.h
+++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.h
@@ -66,16 +66,17 @@
  * For SW based packet transfers, i.e., when the
  * RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT is not set in the adapter's
  * capabilities flags for a particular ethernet device, the service function
- * temporarily enqueues mbufs to an event buffer before batch enqueuing these
+ * temporarily enqueues events to an event buffer before batch enqueuing these
  * to the event device. If the buffer fills up, the service function stops
  * dequeuing packets from the ethernet device. The application may want to
  * monitor the buffer fill level and instruct the service function to
- * selectively buffer packets. The application may also use some other
+ * selectively buffer events. The application may also use some other
  * criteria to decide which packets should enter the event device even when
- * the event buffer fill level is low. The
- * rte_event_eth_rx_adapter_cb_register() function allows the
- * application to register a callback that selects which packets to enqueue
- * to the event device.
+ * the event buffer fill level is low or may want to enqueue packets to an
+ * internal event port. The rte_event_eth_rx_adapter_cb_register() function
+ * allows the application to register a callback that selects which packets are
+ * enqueued to the event device by the SW adapter. The callback interface is
+ * event based so the callback can also modify the event data if it needs to.
  */
 
 #ifdef __cplusplus
@@ -173,9 +174,6 @@ struct rte_event_eth_rx_adapter_queue_conf {
 };
 
 /**
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
- *
  * A structure used to retrieve statistics for an eth rx adapter instance.
  */
 struct rte_event_eth_rx_adapter_stats {
@@ -187,6 +185,8 @@ struct rte_event_eth_rx_adapter_stats {
 	/**< Eventdev enqueue count */
 	uint64_t rx_enq_retry;
 	/**< Eventdev enqueue retry count */
+	uint64_t rx_dropped;
+	/**< Received packet dropped count */
 	uint64_t rx_enq_start_ts;
 	/**< Rx enqueue start timestamp */
 	uint64_t rx_enq_block_cycles;
@@ -204,16 +204,25 @@ struct rte_event_eth_rx_adapter_stats {
 };
 
 /**
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
  *
  * Callback function invoked by the SW adapter before it continues
- * to process packets. The callback is passed the size of the enqueue
+ * to process events. The callback is passed the size of the enqueue
  * buffer in the SW adapter and the occupancy of the buffer. The
- * callback can use these values to decide which mbufs should be
- * enqueued to the event device. If the return value of the callback
- * is less than nb_mbuf then the SW adapter uses the return value to
- * enqueue enq_mbuf[] to the event device.
+ * callback can use these values to decide which events are
+ * enqueued to the event device by the SW adapter. The callback may
+ * also enqueue events internally using its own event port. The SW
+ * adapter populates the event information based on the Rx queue
+ * configuration in the adapter. The callback can modify the this event
+ * information for the events to be enqueued by the SW adapter.
+ *
+ * The callback return value is the number of events from the
+ * beginning of the event array that are to be enqueued by
+ * the SW adapter. It is the callback's responsibility to arrange
+ * these events at the beginning of the array, if these events are
+ * not contiguous in the original array. The *nb_dropped* parameter is
+ * a pointer to the number of events dropped by the callback, this
+ * number is used by the adapter to indicate the number of dropped packets
+ * as part of its statistics.
  *
  * @param eth_dev_id
  *  Port identifier of the Ethernet device.
@@ -222,27 +231,26 @@ struct rte_event_eth_rx_adapter_stats {
  * @param enqueue_buf_size
  *  Total enqueue buffer size.
  * @param enqueue_buf_count
- *  mbuf count in enqueue buffer.
- * @param mbuf
- *  mbuf array.
- * @param nb_mbuf
- *  mbuf count.
+ *  Event count in enqueue buffer.
+ * @param[in, out] ev
+ *  Event array.
+ * @param nb_event
+ *  Event array length.
  * @param cb_arg
  *  Callback argument.
- * @param[out] enq_mbuf
- *  The adapter enqueues enq_mbuf[] if the return value of the
- *  callback is less than nb_mbuf
+ * @param[out] nb_dropped
+ *  Packets dropped by callback.
  * @return
- *  Returns the number of mbufs should be enqueued to eventdev
+ *  - The number of events to be enqueued by the SW adapter.
  */
 typedef uint16_t (*rte_event_eth_rx_adapter_cb_fn)(uint16_t eth_dev_id,
 						uint16_t queue_id,
 						uint32_t enqueue_buf_size,
 						uint32_t enqueue_buf_count,
-						struct rte_mbuf **mbuf,
-						uint16_t nb_mbuf,
+						struct rte_event *ev,
+						uint16_t nb_event,
 						void *cb_arg,
-						struct rte_mbuf **enq_buf);
+						uint16_t *nb_dropped);
 
 /**
  * Create a new ethernet Rx event adapter with the specified identifier.
@@ -398,9 +406,6 @@ int rte_event_eth_rx_adapter_queue_del(uint8_t id, uint16_t eth_dev_id,
 int rte_event_eth_rx_adapter_stop(uint8_t id);
 
 /**
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
- *
  * Retrieve statistics for an adapter
  *
  * @param id
@@ -413,8 +418,7 @@ int rte_event_eth_rx_adapter_queue_del(uint8_t id, uint16_t eth_dev_id,
  *  - 0: Success, retrieved successfully.
  *  - <0: Error code on failure.
  */
-int __rte_experimental
-rte_event_eth_rx_adapter_stats_get(uint8_t id,
+int rte_event_eth_rx_adapter_stats_get(uint8_t id,
 				struct rte_event_eth_rx_adapter_stats *stats);
 
 /**
@@ -447,9 +451,6 @@ int rte_event_eth_rx_adapter_queue_del(uint8_t id, uint16_t eth_dev_id,
 int rte_event_eth_rx_adapter_service_id_get(uint8_t id, uint32_t *service_id);
 
 /**
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
- *
  * Register callback to process Rx packets, this is supported for
  * SW based packet transfers.
  * @see rte_event_eth_rx_cb_fn
@@ -466,11 +467,10 @@ int rte_event_eth_rx_adapter_queue_del(uint8_t id, uint16_t eth_dev_id,
  *  - 0: Success
  *  - <0: Error code on failure.
  */
-int __rte_experimental
-rte_event_eth_rx_adapter_cb_register(uint8_t id,
-				uint16_t eth_dev_id,
-				rte_event_eth_rx_adapter_cb_fn cb_fn,
-				void *cb_arg);
+int rte_event_eth_rx_adapter_cb_register(uint8_t id,
+					uint16_t eth_dev_id,
+					rte_event_eth_rx_adapter_cb_fn cb_fn,
+					void *cb_arg);
 
 #ifdef __cplusplus
 }
diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.c b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
index 161799e..95dd478 100644
--- a/lib/librte_eventdev/rte_event_eth_rx_adapter.c
+++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
@@ -763,8 +763,8 @@ static uint16_t rxa_gcd_u16(uint16_t a, uint16_t b)
 	uint32_t rss;
 	int do_rss;
 	uint64_t ts;
-	struct rte_mbuf *cb_mbufs[BATCH_SIZE];
 	uint16_t nb_cb;
+	uint16_t dropped;
 
 	/* 0xffff ffff if PKT_RX_RSS_HASH is set, otherwise 0 */
 	rss_mask = ~(((m->ol_flags & PKT_RX_RSS_HASH) != 0) - 1);
@@ -780,19 +780,6 @@ static uint16_t rxa_gcd_u16(uint16_t a, uint16_t b)
 		}
 	}
 
-
-	nb_cb = dev_info->cb_fn ? dev_info->cb_fn(eth_dev_id, rx_queue_id,
-						ETH_EVENT_BUFFER_SIZE,
-						buf->count, mbufs,
-						num,
-						dev_info->cb_arg,
-						cb_mbufs) :
-						num;
-	if (nb_cb < num) {
-		mbufs = cb_mbufs;
-		num = nb_cb;
-	}
-
 	for (i = 0; i < num; i++) {
 		m = mbufs[i];
 
@@ -806,6 +793,21 @@ static uint16_t rxa_gcd_u16(uint16_t a, uint16_t b)
 		ev++;
 	}
 
+	if (dev_info->cb_fn) {
+
+		dropped = 0;
+		nb_cb = dev_info->cb_fn(eth_dev_id, rx_queue_id,
+					ETH_EVENT_BUFFER_SIZE, buf->count, ev,
+					num, dev_info->cb_arg, &dropped);
+		if (unlikely(nb_cb > num))
+			RTE_EDEV_LOG_ERR("Rx CB returned %d (> %d) events",
+				nb_cb, num);
+		else
+			num = nb_cb;
+		if (dropped)
+			rx_adapter->stats.rx_dropped += dropped;
+	}
+
 	buf->count += num;
 }
 
@@ -2276,7 +2278,7 @@ static int rxa_sw_add(struct rte_event_eth_rx_adapter *rx_adapter,
 	return rxa_ctrl(id, 0);
 }
 
-int __rte_experimental
+int
 rte_event_eth_rx_adapter_stats_get(uint8_t id,
 			       struct rte_event_eth_rx_adapter_stats *stats)
 {
@@ -2363,7 +2365,7 @@ static int rxa_sw_add(struct rte_event_eth_rx_adapter *rx_adapter,
 	return rx_adapter->service_inited ? 0 : -ESRCH;
 }
 
-int __rte_experimental
+int
 rte_event_eth_rx_adapter_cb_register(uint8_t id,
 					uint16_t eth_dev_id,
 					rte_event_eth_rx_adapter_cb_fn cb_fn,
diff --git a/MAINTAINERS b/MAINTAINERS
index 0212fe6..09f0a98 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -399,7 +399,7 @@ F: lib/librte_eventdev/
 F: drivers/event/skeleton/
 F: app/test/test_eventdev.c
 
-Eventdev Ethdev Rx Adapter API - EXPERIMENTAL
+Eventdev Ethdev Rx Adapter API
 M: Nikhil Rao <nikhil.rao@intel.com>
 T: git://dpdk.org/next/dpdk-next-eventdev
 F: lib/librte_eventdev/*eth_rx_adapter*
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 8c3932d..0689ac1 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -124,6 +124,13 @@ API Changes
 * The network structures, definitions and functions have
   been prefixed by ``rte_`` to resolve conflicts with libc headers.
 
+* eventdev: No longer marked as experimental.
+
+  The eventdev functions are no longer marked as experimental, and have
+  become part of the normal DPDK API and ABI. Any future ABI changes will be
+  announced at least one release before the ABI change is made. There are no
+  ABI breaking changes planned.
+
 
 ABI Changes
 -----------
@@ -140,6 +147,17 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* eventdev: Event based Rx adapter callback
+
+  The mbuf pointer array in the event eth Rx adapter callback
+  has been replaced with an event array. Using
+  an event array allows the application to change attributes
+  of the events enqueued by the SW adapter.
+
+  The callback can drop packets and populate
+  a callback argument with the number of dropped packets.
+  Add a Rx adapter stats field to keep track of the total
+  number of dropped packets.
 
 Shared Library Versions
 -----------------------
@@ -176,7 +194,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_eal.so.10
      librte_efd.so.1
      librte_ethdev.so.12
-     librte_eventdev.so.6
+   + librte_eventdev.so.7
      librte_flow_classify.so.1
      librte_gro.so.1
      librte_gso.so.1
diff --git a/lib/librte_eventdev/Makefile b/lib/librte_eventdev/Makefile
index 53079f4..cd3ff80 100644
--- a/lib/librte_eventdev/Makefile
+++ b/lib/librte_eventdev/Makefile
@@ -8,7 +8,7 @@ include $(RTE_SDK)/mk/rte.vars.mk
 LIB = librte_eventdev.a
 
 # library version
-LIBABIVER := 6
+LIBABIVER := 7
 
 # build flags
 CFLAGS += -DALLOW_EXPERIMENTAL_API
diff --git a/lib/librte_eventdev/meson.build b/lib/librte_eventdev/meson.build
index 6cfe60e..19541f2 100644
--- a/lib/librte_eventdev/meson.build
+++ b/lib/librte_eventdev/meson.build
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017 Intel Corporation
 
-version = 6
+version = 7
 allow_experimental_apis = true
 
 if is_linux
diff --git a/lib/librte_eventdev/rte_eventdev_version.map b/lib/librte_eventdev/rte_eventdev_version.map
index 95fd089..76b3021 100644
--- a/lib/librte_eventdev/rte_eventdev_version.map
+++ b/lib/librte_eventdev/rte_eventdev_version.map
@@ -123,9 +123,9 @@ DPDK_19.05 {
 	rte_event_timer_cancel_burst;
 } DPDK_18.05;
 
-EXPERIMENTAL {
+DPDK_19.08 {
 	global:
 
 	rte_event_eth_rx_adapter_cb_register;
 	rte_event_eth_rx_adapter_stats_get;
-};
+} DPDK_19.05;
-- 
1.8.3.1


^ permalink raw reply	[relevance 15%]

* Re: [dpdk-dev] [PATCH 00/39] adding eventmode helper library
@ 2019-06-25 10:33  3% Jerin Jacob Kollanukkaran
  2019-06-27  5:28  0% ` Anoob Joseph
  0 siblings, 1 reply; 200+ results
From: Jerin Jacob Kollanukkaran @ 2019-06-25 10:33 UTC (permalink / raw)
  To: Anoob Joseph, Mattias Rönnblom, Nikhil Rao,
	Erik Gabriel Carrillo, Abhinandan Gujjar, Bruce Richardson,
	Pablo de Lara
  Cc: Narayana Prasad Raju Athreya, dev, Lukas Bartosik,
	Pavan Nikhilesh Bhagavatula, Hemant Agrawal, Nipun Gupta,
	Harry van Haaren, Liang Ma

> -----Original Message-----
> From: Anoob Joseph
> Sent: Thursday, June 20, 2019 9:15 AM
> To: Mattias Rönnblom <mattias.ronnblom@ericsson.com>; Jerin Jacob
> Kollanukkaran <jerinj@marvell.com>; Nikhil Rao <nikhil.rao@intel.com>; Erik
> Gabriel Carrillo <erik.g.carrillo@intel.com>; Abhinandan Gujjar
> <abhinandan.gujjar@intel.com>; Bruce Richardson
> <bruce.richardson@intel.com>; Pablo de Lara
> <pablo.de.lara.guarch@intel.com>
> Cc: Narayana Prasad Raju Athreya <pathreya@marvell.com>; dev@dpdk.org;
> Lukas Bartosik <lbartosik@marvell.com>; Pavan Nikhilesh Bhagavatula
> <pbhagavatula@marvell.com>; Hemant Agrawal <hemant.agrawal@nxp.com>;
> Nipun Gupta <nipun.gupta@nxp.com>; Harry van Haaren
> <harry.van.haaren@intel.com>; Liang Ma <liang.j.ma@intel.com>
> Subject: RE: [dpdk-dev] [EXT] Re: [PATCH 00/39] adding eventmode helper
> library
> > However, the flexibility and many of the parameters are there for a
> > reason (those there aren't should be deprecated). I would expect a
> > real-world application to tweak quite a few of them. I know our applications
> do.
> >
> > I worry I have is that if you put eventmode (in its current form)
> > forward as a generic framework, applications might start using it,
> > only to realize it's not flexible enough, and then eventmode is just
> > an extra layer, increasing rather than reducing complexity. Or even
> > worse, the application's developers are forced to do a big-bang switch
> > over to using the event and ethernet device APIs directly, in case
> > they can't patch DPDK to work around the eventmode- assumption-that-
> didn't-hold-for-them.
> >
> > You could always add flexibility to the framework (as you encounter a
> > need for it), but then it will grow in complexity as well.
> >
> > A less ambitious approach would be to instead do a properly
> > modularized, non-trivial eventdev example application, for the
> > applications to start off from, instead of a generic library.
> >
> > I would expect it to be very difficult to design a truly generic
> > application framework for eventdev-based applications. Such a
> > framework would tie everything that's needed in a non-trivial
> > application together. If successful, it would be a huge step toward
> > making DPDK an operating system for packet processing applications.
> 
> [Anoob] The idea here is not to deprecate any event dev APIs. I do agree that all
> the configuration exposed by eventdev & adapters are required for various
> requirements in the real world applications. But the requirement to understand
> & use all this configuration is making the applications complicated and causes
> significant effort from anyone who would want to get started with event mode.
> The idea of helper is to allow an easy framework for applications to get started
> with eventmode, and then use various options from C/L or config file (both
> planned) to override the configuration as required. DPDK has components like
> crypto-scheduler which abstracts lot of configuration and simplify usage from
> application's perspective. This effort is on similar lines.
> 
> My patchset is a followup to http://patches.dpdk.org/patch/37955 , wherein the
> approach of introducing a helper library for event mode was mooted. The initial
> patch proposed additions in one application, and that involved huge code
> additions just for doing the configuration.
> 
> The helper library will be experimental while we add event-mode support for
> other applications like l3fwd & ipsec-secgw. I expect the helper library to be
> complete over the course of those applications also using the helper library.


I have only concern about moving this as library inside eventdev that till we have mature
version of helper library the eventdev library ABI will not stable(i.e .so file version needs
to be incremented as when a change needed). Which align with Mattias thoughts for
some other reason:. How about moving this code to
1) example/common or
2) to specific application itself, once at least two applications starts using it then move
to Eventdev library.

Thoughts?




> 
> >
> > What event devices have you tested with?
> 
> [Anoob] Eventmode helper is tested with the following combinations,
>     1. event-octeontx event PMD & nicvf eth PMD
>     2. event-octeontx event PMD & eth-octeontx eth PMD

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v2] cryptodev: add ff_disable field in cryptodev config
  2019-06-03 15:25  5% [dpdk-dev] [PATCH] cryptodev: add ff_disable field in cryptodev config Anoob Joseph
@ 2019-06-25  5:39  4% ` Anoob Joseph
  0 siblings, 0 replies; 200+ results
From: Anoob Joseph @ 2019-06-25  5:39 UTC (permalink / raw)
  To: Akhil Goyal, Declan Doherty, Pablo de Lara
  Cc: Anoob Joseph, Abhinandan Gujjar, Maxime Coquelin, Tiwei Bie,
	Zhihong Wang, Konstantin Ananyev, Marko Kovacevic,
	Cristian Dumitrescu, Radu Nicolau, Fiona Trahe, Jerin Jacob,
	Narayana Prasad, dev

Adding a new field, ff_disable, to allow applications to control the
features enabled on the crypto device. This would allow for efficient
usage of HW/SW offloads.

Signed-off-by: Anoob Joseph <anoobj@marvell.com>
---
v2:
* Updated test & example applications to incorporate the default setting
  for ff_disable field. Disabling SECURITY offload for cases where only
  crypto is applicable & asymmetric crypto in case of ipsec etc.

 app/test-crypto-perf/main.c                   |  3 ++-
 app/test/test_cryptodev.c                     |  2 ++
 app/test/test_event_crypto_adapter.c          |  1 +
 app/test/test_ipsec.c                         |  1 +
 doc/guides/rel_notes/deprecation.rst          | 14 --------------
 doc/guides/rel_notes/release_19_08.rst        | 11 ++++++++++-
 examples/fips_validation/fips_dev_self_test.c |  6 +++++-
 examples/fips_validation/main.c               |  2 +-
 examples/ip_pipeline/cryptodev.c              |  1 +
 examples/ipsec-secgw/ipsec-secgw.c            |  1 +
 examples/l2fwd-crypto/main.c                  |  1 +
 examples/vhost_crypto/main.c                  |  1 +
 lib/librte_cryptodev/Makefile                 |  2 +-
 lib/librte_cryptodev/meson.build              |  2 +-
 lib/librte_cryptodev/rte_cryptodev.h          |  7 +++++++
 15 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/app/test-crypto-perf/main.c b/app/test-crypto-perf/main.c
index 4247f6a..db02907 100644
--- a/app/test-crypto-perf/main.c
+++ b/app/test-crypto-perf/main.c
@@ -200,7 +200,8 @@ cperf_initialize_cryptodev(struct cperf_options *opts, uint8_t *enabled_cdevs)
 		}
 		struct rte_cryptodev_config conf = {
 			.nb_queue_pairs = opts->nb_qps,
-			.socket_id = socket_id
+			.socket_id = socket_id,
+			.ff_disable = RTE_CRYPTODEV_FF_SECURITY,
 		};
 
 		struct rte_cryptodev_qp_conf qp_conf = {
diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index eca6d3d..bcba5a5 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -430,6 +430,7 @@ testsuite_setup(void)
 
 	ts_params->conf.nb_queue_pairs = info.max_nb_queue_pairs;
 	ts_params->conf.socket_id = SOCKET_ID_ANY;
+	ts_params->conf.ff_disable = RTE_CRYPTODEV_FF_SECURITY;
 
 	unsigned int session_size =
 		rte_cryptodev_sym_get_private_session_size(dev_id);
@@ -524,6 +525,7 @@ ut_setup(void)
 
 	/* Reconfigure device to default parameters */
 	ts_params->conf.socket_id = SOCKET_ID_ANY;
+	ts_params->conf.ff_disable = RTE_CRYPTODEV_FF_SECURITY;
 	ts_params->qp_conf.nb_descriptors = MAX_NUM_OPS_INFLIGHT;
 	ts_params->qp_conf.mp_session = ts_params->session_mpool;
 	ts_params->qp_conf.mp_session_private = ts_params->session_priv_mpool;
diff --git a/app/test/test_event_crypto_adapter.c b/app/test/test_event_crypto_adapter.c
index f750ce3..7365502 100644
--- a/app/test/test_event_crypto_adapter.c
+++ b/app/test/test_event_crypto_adapter.c
@@ -548,6 +548,7 @@ configure_cryptodev(void)
 	rte_cryptodev_info_get(TEST_CDEV_ID, &info);
 	conf.nb_queue_pairs = info.max_nb_queue_pairs;
 	conf.socket_id = SOCKET_ID_ANY;
+	conf.ff_disable = RTE_CRYPTODEV_FF_SECURITY;
 
 	TEST_ASSERT_SUCCESS(rte_cryptodev_configure(TEST_CDEV_ID, &conf),
 			"Failed to configure cryptodev %u with %u qps\n",
diff --git a/app/test/test_ipsec.c b/app/test/test_ipsec.c
index 3993ff4..e880700 100644
--- a/app/test/test_ipsec.c
+++ b/app/test/test_ipsec.c
@@ -342,6 +342,7 @@ testsuite_setup(void)
 
 	ts_params->conf.nb_queue_pairs = info.max_nb_queue_pairs;
 	ts_params->conf.socket_id = SOCKET_ID_ANY;
+	ts_params->conf.ff_disable = RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO;
 
 	sess_sz = rte_cryptodev_sym_get_private_session_size(dev_id);
 	sess_sz = RTE_MAX(sess_sz, sizeof(struct rte_security_session));
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index e2721fa..2cc63d8 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -62,20 +62,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* cryptodev: New member in ``rte_cryptodev_config`` to allow applications to
-  disable features supported by the crypto device. Only the following features
-  would be allowed to be disabled this way,
-
-  - ``RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO``
-  - ``RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO``
-  - ``RTE_CRYPTODEV_FF_SECURITY``
-
-  Disabling unused features would facilitate efficient usage of HW/SW offload.
-
-  - Member ``uint64_t ff_disable`` in ``rte_cryptodev_config``
-
-  The field would be added in v19.08.
-
 * cryptodev: the ``uint8_t *data`` member of ``key`` structure in the xforms
   structure (``rte_crypto_cipher_xform``, ``rte_crypto_auth_xform``, and
   ``rte_crypto_aead_xform``) will be changed to ``const uint8_t *data``.
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 8c3932d..c586e55 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -140,6 +140,15 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* cryptodev: New member in ``rte_cryptodev_config`` to allow applications to
+  disable features supported by the crypto device. Only the following features
+  would be allowed to be disabled this way,
+
+  - ``RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO``
+  - ``RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO``
+  - ``RTE_CRYPTODEV_FF_SECURITY``
+
+  Disabling unused features would facilitate efficient usage of HW/SW offload.
 
 Shared Library Versions
 -----------------------
@@ -171,7 +180,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_cfgfile.so.2
      librte_cmdline.so.2
      librte_compressdev.so.1
-     librte_cryptodev.so.7
+   + librte_cryptodev.so.8
      librte_distributor.so.1
      librte_eal.so.10
      librte_efd.so.1
diff --git a/examples/fips_validation/fips_dev_self_test.c b/examples/fips_validation/fips_dev_self_test.c
index 444bbaa..17e8597 100644
--- a/examples/fips_validation/fips_dev_self_test.c
+++ b/examples/fips_validation/fips_dev_self_test.c
@@ -1557,12 +1557,16 @@ fips_dev_auto_test_uninit(uint8_t dev_id,
 static int
 fips_dev_auto_test_init(uint8_t dev_id, struct fips_dev_auto_test_env *env)
 {
-	struct rte_cryptodev_config conf = {rte_cryptodev_socket_id(dev_id), 1};
 	struct rte_cryptodev_qp_conf qp_conf = {128, NULL, NULL};
 	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(dev_id);
+	struct rte_cryptodev_config conf;
 	char name[128];
 	int ret;
 
+	conf.socket_id = rte_cryptodev_socket_id(dev_id);
+	conf.nb_queue_pairs = 1;
+	conf.ff_disable = 0;
+
 	ret = rte_cryptodev_configure(dev_id, &conf);
 	if (ret < 0)
 		return ret;
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index aef4505..8135340 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -48,7 +48,7 @@ struct cryptodev_fips_validate_env {
 static int
 cryptodev_fips_validate_app_int(void)
 {
-	struct rte_cryptodev_config conf = {rte_socket_id(), 1};
+	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
 	struct rte_cryptodev_qp_conf qp_conf = {128, NULL, NULL};
 	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
 			env.dev_id);
diff --git a/examples/ip_pipeline/cryptodev.c b/examples/ip_pipeline/cryptodev.c
index 94a0462..b0d9f3d 100644
--- a/examples/ip_pipeline/cryptodev.c
+++ b/examples/ip_pipeline/cryptodev.c
@@ -93,6 +93,7 @@ cryptodev_create(const char *name, struct cryptodev_params *params)
 
 	dev_conf.socket_id = socket_id;
 	dev_conf.nb_queue_pairs = params->n_queues;
+	dev_conf.ff_disable = 0;
 
 	status = rte_cryptodev_configure(dev_id, &dev_conf);
 	if (status < 0)
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 6c626fa..931e5ea 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -1720,6 +1720,7 @@ cryptodevs_init(void)
 
 		dev_conf.socket_id = rte_cryptodev_socket_id(cdev_id);
 		dev_conf.nb_queue_pairs = qp;
+		dev_conf.ff_disable = RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO;
 
 		uint32_t dev_max_sess = cdev_info.sym.max_nb_sessions;
 		if (dev_max_sess != 0 && dev_max_sess < CDEV_MP_NB_OBJS)
diff --git a/examples/l2fwd-crypto/main.c b/examples/l2fwd-crypto/main.c
index 09cd4c9..3fe2ba7 100644
--- a/examples/l2fwd-crypto/main.c
+++ b/examples/l2fwd-crypto/main.c
@@ -2256,6 +2256,7 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports,
 		struct rte_cryptodev_config conf = {
 			.nb_queue_pairs = 1,
 			.socket_id = socket_id,
+			.ff_disable = RTE_CRYPTODEV_FF_SECURITY,
 		};
 
 		rte_cryptodev_info_get(cdev_id, &dev_info);
diff --git a/examples/vhost_crypto/main.c b/examples/vhost_crypto/main.c
index ac7118e..c7b747b 100644
--- a/examples/vhost_crypto/main.c
+++ b/examples/vhost_crypto/main.c
@@ -522,6 +522,7 @@ main(int argc, char *argv[])
 
 		config.nb_queue_pairs = dev_info.max_nb_queue_pairs;
 		config.socket_id = rte_lcore_to_socket_id(lo->lcore_id);
+		config.ff_disable = RTE_CRYPTODEV_FF_SECURITY;
 
 		ret = rte_cryptodev_configure(info->cid, &config);
 		if (ret < 0) {
diff --git a/lib/librte_cryptodev/Makefile b/lib/librte_cryptodev/Makefile
index c20e090..55d352a 100644
--- a/lib/librte_cryptodev/Makefile
+++ b/lib/librte_cryptodev/Makefile
@@ -7,7 +7,7 @@ include $(RTE_SDK)/mk/rte.vars.mk
 LIB = librte_cryptodev.a
 
 # library version
-LIBABIVER := 7
+LIBABIVER := 8
 
 # build flags
 CFLAGS += -O3
diff --git a/lib/librte_cryptodev/meson.build b/lib/librte_cryptodev/meson.build
index 9e009d4..0a2275d 100644
--- a/lib/librte_cryptodev/meson.build
+++ b/lib/librte_cryptodev/meson.build
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017-2019 Intel Corporation
 
-version = 7
+version = 8
 allow_experimental_apis = true
 sources = files('rte_cryptodev.c', 'rte_cryptodev_pmd.c')
 headers = files('rte_cryptodev.h',
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index 2d4f6d7..58bfab5 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -612,6 +612,13 @@ struct rte_cryptodev_config {
 	int socket_id;			/**< Socket to allocate resources on */
 	uint16_t nb_queue_pairs;
 	/**< Number of queue pairs to configure on device */
+	uint64_t ff_disable;
+	/**< Feature flags to be disabled. Only the following features are
+	 * allowed to be disabled,
+	 *  - RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO
+	 *  - RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO
+	 *  - RTE_CRYTPODEV_FF_SECURITY
+	 */
 };
 
 /**
-- 
2.7.4


^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v4] cryptodev: make xform key pointer constant
  @ 2019-06-24 13:35  3% ` Fan Zhang
  2019-06-25 12:46  4%   ` Akhil Goyal
  0 siblings, 1 reply; 200+ results
From: Fan Zhang @ 2019-06-24 13:35 UTC (permalink / raw)
  To: dev; +Cc: akhil.goyal, pablo.de.lara.guarch, Fan Zhang

This patch changes the key pointer data types in cipher, auth,
and aead xforms from "uint8_t *" to "const uint8_t *" for a
more intuitive and safe sessionn creation.

Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
---
v4:
- Removed deprecation notice and updated release note.
- Updated ABI version.

v3:
- rebased on top of latest dpdk-next-crypto

v2:
- fixed a missed memory free for ixgbe ipsec
 doc/guides/rel_notes/deprecation.rst            |  4 --
 doc/guides/rel_notes/release_19_08.rst          |  4 ++
 drivers/common/cpt/cpt_ucode.h                  | 14 ++---
 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c        |  2 +-
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c      |  2 +-
 drivers/crypto/openssl/rte_openssl_pmd.c        |  8 +--
 drivers/crypto/qat/qat_sym_session.c            |  8 +--
 drivers/crypto/qat/qat_sym_session.h            |  4 +-
 drivers/crypto/snow3g/rte_snow3g_pmd.c          | 23 ++++++--
 drivers/crypto/snow3g/rte_snow3g_pmd_private.h  |  1 +
 drivers/crypto/virtio/virtio_cryptodev.c        | 30 +++++++---
 drivers/crypto/virtio/virtio_cryptodev.h        |  2 +
 drivers/net/ixgbe/ixgbe_ipsec.c                 | 35 +++++++++---
 drivers/net/ixgbe/ixgbe_ipsec.h                 |  3 +-
 drivers/net/softnic/rte_eth_softnic_cli.c       | 74 ++++++++++++-------------
 drivers/net/softnic/rte_eth_softnic_internals.h |  4 ++
 examples/ip_pipeline/cli.c                      | 74 ++++++++++++-------------
 examples/ip_pipeline/cryptodev.c                |  2 -
 examples/ip_pipeline/pipeline.h                 |  6 ++
 examples/l2fwd-crypto/main.c                    | 40 +++++--------
 lib/librte_cryptodev/Makefile                   |  2 +-
 lib/librte_cryptodev/meson.build                |  2 +-
 lib/librte_cryptodev/rte_crypto_sym.h           | 12 ++--
 23 files changed, 196 insertions(+), 160 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index e2721fad6..90b29ab1a 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -76,10 +76,6 @@ Deprecation Notices
 
   The field would be added in v19.08.
 
-* cryptodev: the ``uint8_t *data`` member of ``key`` structure in the xforms
-  structure (``rte_crypto_cipher_xform``, ``rte_crypto_auth_xform``, and
-  ``rte_crypto_aead_xform``) will be changed to ``const uint8_t *data``.
-
 * cryptodev: support for using IV with all sizes is added, J0 still can
   be used but only when IV length in following structs ``rte_crypto_auth_xform``,
   ``rte_crypto_aead_xform`` is set to zero. When IV length is greater or equal
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 8c3932d06..a22e93863 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -124,6 +124,10 @@ API Changes
 * The network structures, definitions and functions have
   been prefixed by ``rte_`` to resolve conflicts with libc headers.
 
+* cryptodev: the ``uint8_t *data`` member of ``key`` structure in the xforms
+  structure (``rte_crypto_cipher_xform``, ``rte_crypto_auth_xform``, and
+  ``rte_crypto_aead_xform``) have been changed to ``const uint8_t *data``.
+
 
 ABI Changes
 -----------
diff --git a/drivers/common/cpt/cpt_ucode.h b/drivers/common/cpt/cpt_ucode.h
index f21352e6c..4f5e5dc88 100644
--- a/drivers/common/cpt/cpt_ucode.h
+++ b/drivers/common/cpt/cpt_ucode.h
@@ -55,7 +55,7 @@ cpt_is_algo_supported(struct rte_crypto_sym_xform *xform)
 }
 
 static __rte_always_inline void
-gen_key_snow3g(uint8_t *ck, uint32_t *keyx)
+gen_key_snow3g(const uint8_t *ck, uint32_t *keyx)
 {
 	int i, base;
 
@@ -174,7 +174,7 @@ cpt_fc_ciph_set_key_set_aes_key_type(mc_fc_context_t *fctx, uint16_t key_len)
 }
 
 static __rte_always_inline void
-cpt_fc_ciph_set_key_snow3g_uea2(struct cpt_ctx *cpt_ctx, uint8_t *key,
+cpt_fc_ciph_set_key_snow3g_uea2(struct cpt_ctx *cpt_ctx, const uint8_t *key,
 		uint16_t key_len)
 {
 	uint32_t keyx[4];
@@ -186,7 +186,7 @@ cpt_fc_ciph_set_key_snow3g_uea2(struct cpt_ctx *cpt_ctx, uint8_t *key,
 }
 
 static __rte_always_inline void
-cpt_fc_ciph_set_key_zuc_eea3(struct cpt_ctx *cpt_ctx, uint8_t *key,
+cpt_fc_ciph_set_key_zuc_eea3(struct cpt_ctx *cpt_ctx, const uint8_t *key,
 		uint16_t key_len)
 {
 	cpt_ctx->snow3g = 0;
@@ -197,7 +197,7 @@ cpt_fc_ciph_set_key_zuc_eea3(struct cpt_ctx *cpt_ctx, uint8_t *key,
 }
 
 static __rte_always_inline void
-cpt_fc_ciph_set_key_kasumi_f8_ecb(struct cpt_ctx *cpt_ctx, uint8_t *key,
+cpt_fc_ciph_set_key_kasumi_f8_ecb(struct cpt_ctx *cpt_ctx, const uint8_t *key,
 		uint16_t key_len)
 {
 	cpt_ctx->k_ecb = 1;
@@ -207,7 +207,7 @@ cpt_fc_ciph_set_key_kasumi_f8_ecb(struct cpt_ctx *cpt_ctx, uint8_t *key,
 }
 
 static __rte_always_inline void
-cpt_fc_ciph_set_key_kasumi_f8_cbc(struct cpt_ctx *cpt_ctx, uint8_t *key,
+cpt_fc_ciph_set_key_kasumi_f8_cbc(struct cpt_ctx *cpt_ctx, const uint8_t *key,
 		uint16_t key_len)
 {
 	memcpy(cpt_ctx->k_ctx.ci_key, key, key_len);
@@ -216,7 +216,7 @@ cpt_fc_ciph_set_key_kasumi_f8_cbc(struct cpt_ctx *cpt_ctx, uint8_t *key,
 }
 
 static __rte_always_inline int
-cpt_fc_ciph_set_key(void *ctx, cipher_type_t type, uint8_t *key,
+cpt_fc_ciph_set_key(void *ctx, cipher_type_t type, const uint8_t *key,
 		    uint16_t key_len, uint8_t *salt)
 {
 	struct cpt_ctx *cpt_ctx = ctx;
@@ -2569,7 +2569,7 @@ cpt_fc_enc_hmac_prep(uint32_t flags, uint64_t d_offs, uint64_t d_lens,
 }
 
 static __rte_always_inline int
-cpt_fc_auth_set_key(void *ctx, auth_type_t type, uint8_t *key,
+cpt_fc_auth_set_key(void *ctx, auth_type_t type, const uint8_t *key,
 		    uint16_t key_len, uint16_t mac_len)
 {
 	struct cpt_ctx *cpt_ctx = ctx;
diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index 49ee31708..1006a5c4d 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -24,7 +24,7 @@ aesni_gcm_set_session_parameters(const struct aesni_gcm_ops *gcm_ops,
 	const struct rte_crypto_sym_xform *auth_xform;
 	const struct rte_crypto_sym_xform *aead_xform;
 	uint8_t key_length;
-	uint8_t *key;
+	const uint8_t *key;
 
 	/* AES-GMAC */
 	if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index edb6608e2..b495a9679 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -35,7 +35,7 @@ typedef void (*aes_keyexp_t)(const void *key, void *enc_exp_keys, void *dec_exp_
 static void
 calculate_auth_precomputes(hash_one_block_t one_block_hash,
 		uint8_t *ipad, uint8_t *opad,
-		uint8_t *hkey, uint16_t hkey_len,
+		const uint8_t *hkey, uint16_t hkey_len,
 		uint16_t blocksize)
 {
 	unsigned i, length;
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index 73ce3833c..7c8bf0d9f 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -92,14 +92,14 @@ openssl_get_chain_order(const struct rte_crypto_sym_xform *xform)
 
 /** Get session cipher key from input cipher key */
 static void
-get_cipher_key(uint8_t *input_key, int keylen, uint8_t *session_key)
+get_cipher_key(const uint8_t *input_key, int keylen, uint8_t *session_key)
 {
 	memcpy(session_key, input_key, keylen);
 }
 
 /** Get key ede 24 bytes standard from input key */
 static int
-get_cipher_key_ede(uint8_t *key, int keylen, uint8_t *key_ede)
+get_cipher_key_ede(const uint8_t *key, int keylen, uint8_t *key_ede)
 {
 	int res = 0;
 
@@ -292,7 +292,7 @@ get_aead_algo(enum rte_crypto_aead_algorithm sess_algo, size_t keylen,
 static int
 openssl_set_sess_aead_enc_param(struct openssl_session *sess,
 		enum rte_crypto_aead_algorithm algo,
-		uint8_t tag_len, uint8_t *key)
+		uint8_t tag_len, const uint8_t *key)
 {
 	int iv_type = 0;
 	unsigned int do_ccm;
@@ -352,7 +352,7 @@ openssl_set_sess_aead_enc_param(struct openssl_session *sess,
 static int
 openssl_set_sess_aead_dec_param(struct openssl_session *sess,
 		enum rte_crypto_aead_algorithm algo,
-		uint8_t tag_len, uint8_t *key)
+		uint8_t tag_len, const uint8_t *key)
 {
 	int iv_type = 0;
 	unsigned int do_ccm = 0;
diff --git a/drivers/crypto/qat/qat_sym_session.c b/drivers/crypto/qat/qat_sym_session.c
index f66175d03..e5167b3fa 100644
--- a/drivers/crypto/qat/qat_sym_session.c
+++ b/drivers/crypto/qat/qat_sym_session.c
@@ -35,7 +35,7 @@ bpi_cipher_ctx_free(void *bpi_ctx)
 static int
 bpi_cipher_ctx_init(enum rte_crypto_cipher_algorithm cryptodev_algo,
 		enum rte_crypto_cipher_operation direction __rte_unused,
-		uint8_t *key, void **ctx)
+		const uint8_t *key, void **ctx)
 {
 	const EVP_CIPHER *algo = NULL;
 	int ret;
@@ -510,7 +510,7 @@ qat_sym_session_configure_auth(struct rte_cryptodev *dev,
 {
 	struct rte_crypto_auth_xform *auth_xform = qat_get_auth_xform(xform);
 	struct qat_sym_dev_private *internals = dev->data->dev_private;
-	uint8_t *key_data = auth_xform->key.data;
+	const uint8_t *key_data = auth_xform->key.data;
 	uint8_t key_length = auth_xform->key.length;
 	session->aes_cmac = 0;
 
@@ -1272,7 +1272,7 @@ qat_get_crypto_proto_flag(uint16_t flags)
 }
 
 int qat_sym_session_aead_create_cd_cipher(struct qat_sym_session *cdesc,
-						uint8_t *cipherkey,
+						const uint8_t *cipherkey,
 						uint32_t cipherkeylen)
 {
 	struct icp_qat_hw_cipher_algo_blk *cipher;
@@ -1427,7 +1427,7 @@ int qat_sym_session_aead_create_cd_cipher(struct qat_sym_session *cdesc,
 }
 
 int qat_sym_session_aead_create_cd_auth(struct qat_sym_session *cdesc,
-						uint8_t *authkey,
+						const uint8_t *authkey,
 						uint32_t authkeylen,
 						uint32_t aad_length,
 						uint32_t digestsize,
diff --git a/drivers/crypto/qat/qat_sym_session.h b/drivers/crypto/qat/qat_sym_session.h
index 43e25ceb7..ce1ca5af8 100644
--- a/drivers/crypto/qat/qat_sym_session.h
+++ b/drivers/crypto/qat/qat_sym_session.h
@@ -106,12 +106,12 @@ qat_sym_session_configure_auth(struct rte_cryptodev *dev,
 
 int
 qat_sym_session_aead_create_cd_cipher(struct qat_sym_session *cd,
-						uint8_t *enckey,
+						const uint8_t *enckey,
 						uint32_t enckeylen);
 
 int
 qat_sym_session_aead_create_cd_auth(struct qat_sym_session *cdesc,
-						uint8_t *authkey,
+						const uint8_t *authkey,
 						uint32_t authkeylen,
 						uint32_t aad_length,
 						uint32_t digestsize,
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 5fd94b686..68d7176f4 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -84,6 +84,8 @@ snow3g_set_session_parameters(struct snow3g_session *sess,
 	}
 
 	if (cipher_xform) {
+		uint8_t cipher_key[SNOW3G_MAX_KEY_SIZE];
+
 		/* Only SNOW 3G UEA2 supported */
 		if (cipher_xform->cipher.algo != RTE_CRYPTO_CIPHER_SNOW3G_UEA2)
 			return -ENOTSUP;
@@ -92,14 +94,22 @@ snow3g_set_session_parameters(struct snow3g_session *sess,
 			SNOW3G_LOG(ERR, "Wrong IV length");
 			return -EINVAL;
 		}
+		if (cipher_xform->cipher.key.length > SNOW3G_MAX_KEY_SIZE) {
+			SNOW3G_LOG(ERR, "Not enough memory to store the key");
+			return -ENOMEM;
+		}
+
 		sess->cipher_iv_offset = cipher_xform->cipher.iv.offset;
 
 		/* Initialize key */
-		sso_snow3g_init_key_sched(cipher_xform->cipher.key.data,
-				&sess->pKeySched_cipher);
+		memcpy(cipher_key, cipher_xform->cipher.key.data,
+				cipher_xform->cipher.key.length);
+		sso_snow3g_init_key_sched(cipher_key, &sess->pKeySched_cipher);
 	}
 
 	if (auth_xform) {
+		uint8_t auth_key[SNOW3G_MAX_KEY_SIZE];
+
 		/* Only SNOW 3G UIA2 supported */
 		if (auth_xform->auth.algo != RTE_CRYPTO_AUTH_SNOW3G_UIA2)
 			return -ENOTSUP;
@@ -108,6 +118,10 @@ snow3g_set_session_parameters(struct snow3g_session *sess,
 			SNOW3G_LOG(ERR, "Wrong digest length");
 			return -EINVAL;
 		}
+		if (auth_xform->auth.key.length > SNOW3G_MAX_KEY_SIZE) {
+			SNOW3G_LOG(ERR, "Not enough memory to store the key");
+			return -ENOMEM;
+		}
 
 		sess->auth_op = auth_xform->auth.op;
 
@@ -118,8 +132,9 @@ snow3g_set_session_parameters(struct snow3g_session *sess,
 		sess->auth_iv_offset = auth_xform->auth.iv.offset;
 
 		/* Initialize key */
-		sso_snow3g_init_key_sched(auth_xform->auth.key.data,
-				&sess->pKeySched_hash);
+		memcpy(auth_key, auth_xform->auth.key.data,
+				auth_xform->auth.key.length);
+		sso_snow3g_init_key_sched(auth_key, &sess->pKeySched_hash);
 	}
 
 
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd_private.h b/drivers/crypto/snow3g/rte_snow3g_pmd_private.h
index df5c6092b..95a3eba22 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd_private.h
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd_private.h
@@ -19,6 +19,7 @@ int snow3g_logtype_driver;
 					## __VA_ARGS__)
 
 #define SNOW3G_DIGEST_LENGTH 4
+#define SNOW3G_MAX_KEY_SIZE  128
 
 /** private data structure for each virtual SNOW 3G device */
 struct snow3g_private {
diff --git a/drivers/crypto/virtio/virtio_cryptodev.c b/drivers/crypto/virtio/virtio_cryptodev.c
index 4bae3b865..f16bdfe57 100644
--- a/drivers/crypto/virtio/virtio_cryptodev.c
+++ b/drivers/crypto/virtio/virtio_cryptodev.c
@@ -1210,7 +1210,7 @@ static int
 virtio_crypto_sym_pad_op_ctrl_req(
 		struct virtio_crypto_op_ctrl_req *ctrl,
 		struct rte_crypto_sym_xform *xform, bool is_chainned,
-		uint8_t **cipher_key_data, uint8_t **auth_key_data,
+		uint8_t *cipher_key_data, uint8_t *auth_key_data,
 		struct virtio_crypto_session *session)
 {
 	int ret;
@@ -1220,6 +1220,12 @@ virtio_crypto_sym_pad_op_ctrl_req(
 	/* Get cipher xform from crypto xform chain */
 	cipher_xform = virtio_crypto_get_cipher_xform(xform);
 	if (cipher_xform) {
+		if (cipher_xform->key.length > VIRTIO_CRYPTO_MAX_KEY_SIZE) {
+			VIRTIO_CRYPTO_SESSION_LOG_ERR(
+				"cipher key size cannot be longer than %u",
+				VIRTIO_CRYPTO_MAX_KEY_SIZE);
+			return -1;
+		}
 		if (cipher_xform->iv.length > VIRTIO_CRYPTO_MAX_IV_SIZE) {
 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
 				"cipher IV size cannot be longer than %u",
@@ -1241,7 +1247,8 @@ virtio_crypto_sym_pad_op_ctrl_req(
 			return -1;
 		}
 
-		*cipher_key_data = cipher_xform->key.data;
+		memcpy(cipher_key_data, cipher_xform->key.data,
+				cipher_xform->key.length);
 
 		session->iv.offset = cipher_xform->iv.offset;
 		session->iv.length = cipher_xform->iv.length;
@@ -1254,13 +1261,20 @@ virtio_crypto_sym_pad_op_ctrl_req(
 		struct virtio_crypto_alg_chain_session_para *para =
 			&(ctrl->u.sym_create_session.u.chain.para);
 		if (auth_xform->key.length) {
+			if (auth_xform->key.length >
+					VIRTIO_CRYPTO_MAX_KEY_SIZE) {
+				VIRTIO_CRYPTO_SESSION_LOG_ERR(
+				"auth key size cannot be longer than %u",
+					VIRTIO_CRYPTO_MAX_KEY_SIZE);
+				return -1;
+			}
 			para->hash_mode = VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH;
 			para->u.mac_param.auth_key_len =
 				(uint32_t)auth_xform->key.length;
 			para->u.mac_param.hash_result_len =
 				auth_xform->digest_length;
-
-			*auth_key_data = auth_xform->key.data;
+			memcpy(auth_key_data, auth_xform->key.data,
+					auth_xform->key.length);
 		} else {
 			para->hash_mode	= VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN;
 			para->u.hash_param.hash_result_len =
@@ -1310,8 +1324,8 @@ virtio_crypto_sym_configure_session(
 	struct virtio_crypto_session *session;
 	struct virtio_crypto_op_ctrl_req *ctrl_req;
 	enum virtio_crypto_cmd_id cmd_id;
-	uint8_t *cipher_key_data = NULL;
-	uint8_t *auth_key_data = NULL;
+	uint8_t cipher_key_data[VIRTIO_CRYPTO_MAX_KEY_SIZE] = {0};
+	uint8_t auth_key_data[VIRTIO_CRYPTO_MAX_KEY_SIZE] = {0};
 	struct virtio_crypto_hw *hw;
 	struct virtqueue *control_vq;
 
@@ -1355,7 +1369,7 @@ virtio_crypto_sym_configure_session(
 			= VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING;
 
 		ret = virtio_crypto_sym_pad_op_ctrl_req(ctrl_req,
-			xform, true, &cipher_key_data, &auth_key_data, session);
+			xform, true, cipher_key_data, auth_key_data, session);
 		if (ret < 0) {
 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
 				"padding sym op ctrl req failed");
@@ -1373,7 +1387,7 @@ virtio_crypto_sym_configure_session(
 		ctrl_req->u.sym_create_session.op_type
 			= VIRTIO_CRYPTO_SYM_OP_CIPHER;
 		ret = virtio_crypto_sym_pad_op_ctrl_req(ctrl_req, xform,
-			false, &cipher_key_data, &auth_key_data, session);
+			false, cipher_key_data, auth_key_data, session);
 		if (ret < 0) {
 			VIRTIO_CRYPTO_SESSION_LOG_ERR(
 				"padding sym op ctrl req failed");
diff --git a/drivers/crypto/virtio/virtio_cryptodev.h b/drivers/crypto/virtio/virtio_cryptodev.h
index 0fd7b722e..215bce786 100644
--- a/drivers/crypto/virtio/virtio_cryptodev.h
+++ b/drivers/crypto/virtio/virtio_cryptodev.h
@@ -18,6 +18,8 @@
 
 #define VIRTIO_CRYPTO_MAX_IV_SIZE 16
 
+#define VIRTIO_CRYPTO_MAX_KEY_SIZE 256
+
 extern uint8_t cryptodev_virtio_driver_id;
 
 enum virtio_crypto_cmd_id {
diff --git a/drivers/net/ixgbe/ixgbe_ipsec.c b/drivers/net/ixgbe/ixgbe_ipsec.c
index 5a416885f..57f2388e2 100644
--- a/drivers/net/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ixgbe/ixgbe_ipsec.c
@@ -97,6 +97,7 @@ ixgbe_crypto_add_sa(struct ixgbe_crypto_session *ic_session)
 
 	if (ic_session->op == IXGBE_OP_AUTHENTICATED_DECRYPTION) {
 		int i, ip_index = -1;
+		uint8_t *key;
 
 		/* Find a match in the IP table*/
 		for (i = 0; i < IPSEC_MAX_RX_IP_COUNT; i++) {
@@ -189,23 +190,32 @@ ixgbe_crypto_add_sa(struct ixgbe_crypto_session *ic_session)
 		IXGBE_WAIT_RWRITE;
 
 		/* write Key table entry*/
+		key = malloc(ic_session->key_len);
+		if (!key)
+			return -ENOMEM;
+
+		memcpy(key, ic_session->key, ic_session->key_len);
+
 		reg_val = IPSRXIDX_RX_EN | IPSRXIDX_WRITE |
 				IPSRXIDX_TABLE_KEY | (sa_index << 3);
 		IXGBE_WRITE_REG(hw, IXGBE_IPSRXKEY(0),
-			rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[12]));
+			rte_cpu_to_be_32(*(uint32_t *)&key[12]));
 		IXGBE_WRITE_REG(hw, IXGBE_IPSRXKEY(1),
-			rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[8]));
+			rte_cpu_to_be_32(*(uint32_t *)&key[8]));
 		IXGBE_WRITE_REG(hw, IXGBE_IPSRXKEY(2),
-			rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[4]));
+			rte_cpu_to_be_32(*(uint32_t *)&key[4]));
 		IXGBE_WRITE_REG(hw, IXGBE_IPSRXKEY(3),
-			rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[0]));
+			rte_cpu_to_be_32(*(uint32_t *)&key[0]));
 		IXGBE_WRITE_REG(hw, IXGBE_IPSRXSALT,
 				rte_cpu_to_be_32(ic_session->salt));
 		IXGBE_WRITE_REG(hw, IXGBE_IPSRXMOD,
 				priv->rx_sa_tbl[sa_index].mode);
 		IXGBE_WAIT_RWRITE;
 
+		free(key);
+
 	} else { /* sess->dir == RTE_CRYPTO_OUTBOUND */
+		uint8_t *key;
 		int i;
 
 		/* Find a free entry in the SA table*/
@@ -227,19 +237,27 @@ ixgbe_crypto_add_sa(struct ixgbe_crypto_session *ic_session)
 		priv->tx_sa_tbl[i].used = 1;
 		ic_session->sa_index = sa_index;
 
+		key = malloc(ic_session->key_len);
+		if (!key)
+			return -ENOMEM;
+
+		memcpy(key, ic_session->key, ic_session->key_len);
+
 		/* write Key table entry*/
 		reg_val = IPSRXIDX_RX_EN | IPSRXIDX_WRITE | (sa_index << 3);
 		IXGBE_WRITE_REG(hw, IXGBE_IPSTXKEY(0),
-			rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[12]));
+			rte_cpu_to_be_32(*(uint32_t *)&key[12]));
 		IXGBE_WRITE_REG(hw, IXGBE_IPSTXKEY(1),
-			rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[8]));
+			rte_cpu_to_be_32(*(uint32_t *)&key[8]));
 		IXGBE_WRITE_REG(hw, IXGBE_IPSTXKEY(2),
-			rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[4]));
+			rte_cpu_to_be_32(*(uint32_t *)&key[4]));
 		IXGBE_WRITE_REG(hw, IXGBE_IPSTXKEY(3),
-			rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[0]));
+			rte_cpu_to_be_32(*(uint32_t *)&key[0]));
 		IXGBE_WRITE_REG(hw, IXGBE_IPSTXSALT,
 				rte_cpu_to_be_32(ic_session->salt));
 		IXGBE_WAIT_TWRITE;
+
+		free(key);
 	}
 
 	return 0;
@@ -388,6 +406,7 @@ ixgbe_crypto_create_session(void *device,
 	}
 
 	ic_session->key = aead_xform->key.data;
+	ic_session->key_len = aead_xform->key.length;
 	memcpy(&ic_session->salt,
 	       &aead_xform->key.data[aead_xform->key.length], 4);
 	ic_session->spi = conf->ipsec.spi;
diff --git a/drivers/net/ixgbe/ixgbe_ipsec.h b/drivers/net/ixgbe/ixgbe_ipsec.h
index c73e18069..e218c0a4a 100644
--- a/drivers/net/ixgbe/ixgbe_ipsec.h
+++ b/drivers/net/ixgbe/ixgbe_ipsec.h
@@ -62,7 +62,8 @@ struct ipaddr {
 /** inline crypto crypto private session structure */
 struct ixgbe_crypto_session {
 	enum ixgbe_operation op;
-	uint8_t *key;
+	const uint8_t *key;
+	uint32_t key_len;
 	uint32_t salt;
 	uint32_t sa_index;
 	uint32_t spi;
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 56fc92ba2..88e0a848e 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -4095,24 +4095,18 @@ parse_free_sym_crypto_param_data(struct rte_table_action_sym_crypto_params *p)
 
 		switch (xform[i]->type) {
 		case RTE_CRYPTO_SYM_XFORM_CIPHER:
-			if (xform[i]->cipher.key.data)
-				free(xform[i]->cipher.key.data);
 			if (p->cipher_auth.cipher_iv.val)
 				free(p->cipher_auth.cipher_iv.val);
 			if (p->cipher_auth.cipher_iv_update.val)
 				free(p->cipher_auth.cipher_iv_update.val);
 			break;
 		case RTE_CRYPTO_SYM_XFORM_AUTH:
-			if (xform[i]->auth.key.data)
-				free(xform[i]->cipher.key.data);
 			if (p->cipher_auth.auth_iv.val)
 				free(p->cipher_auth.cipher_iv.val);
 			if (p->cipher_auth.auth_iv_update.val)
 				free(p->cipher_auth.cipher_iv_update.val);
 			break;
 		case RTE_CRYPTO_SYM_XFORM_AEAD:
-			if (xform[i]->aead.key.data)
-				free(xform[i]->cipher.key.data);
 			if (p->aead.iv.val)
 				free(p->aead.iv.val);
 			if (p->aead.aad.val)
@@ -4127,8 +4121,8 @@ parse_free_sym_crypto_param_data(struct rte_table_action_sym_crypto_params *p)
 
 static struct rte_crypto_sym_xform *
 parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p,
-		char **tokens, uint32_t n_tokens, uint32_t encrypt,
-		uint32_t *used_n_tokens)
+		uint8_t *key, uint32_t max_key_len, char **tokens,
+		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
 {
 	struct rte_crypto_sym_xform *xform_cipher;
 	int status;
@@ -4155,16 +4149,16 @@ parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p,
 
 	/* cipher_key */
 	len = strlen(tokens[4]);
-	xform_cipher->cipher.key.data = calloc(1, len / 2 + 1);
-	if (xform_cipher->cipher.key.data == NULL)
+	if (len / 2 > max_key_len) {
+		status = -ENOMEM;
 		goto error_exit;
+	}
 
-	status = softnic_parse_hex_string(tokens[4],
-			xform_cipher->cipher.key.data,
-			(uint32_t *)&len);
+	status = softnic_parse_hex_string(tokens[4], key, (uint32_t *)&len);
 	if (status < 0)
 		goto error_exit;
 
+	xform_cipher->cipher.key.data = key;
 	xform_cipher->cipher.key.length = (uint16_t)len;
 
 	/* cipher_iv */
@@ -4188,9 +4182,6 @@ parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p,
 	return xform_cipher;
 
 error_exit:
-	if (xform_cipher->cipher.key.data)
-		free(xform_cipher->cipher.key.data);
-
 	if (p->cipher_auth.cipher_iv.val) {
 		free(p->cipher_auth.cipher_iv.val);
 		p->cipher_auth.cipher_iv.val = NULL;
@@ -4203,8 +4194,8 @@ parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p,
 
 static struct rte_crypto_sym_xform *
 parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
-		char **tokens, uint32_t n_tokens, uint32_t encrypt,
-		uint32_t *used_n_tokens)
+		uint8_t *key, uint32_t max_key_len, char **tokens,
+		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
 {
 	struct rte_crypto_sym_xform *xform_cipher;
 	struct rte_crypto_sym_xform *xform_auth;
@@ -4233,17 +4224,21 @@ parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
 
 	/* auth_key */
 	len = strlen(tokens[10]);
-	xform_auth->auth.key.data = calloc(1, len / 2 + 1);
-	if (xform_auth->auth.key.data == NULL)
+	if (len / 2 > max_key_len) {
+		status = -ENOMEM;
 		goto error_exit;
+	}
 
-	status = softnic_parse_hex_string(tokens[10],
-			xform_auth->auth.key.data, (uint32_t *)&len);
+	status = softnic_parse_hex_string(tokens[10], key, (uint32_t *)&len);
 	if (status < 0)
 		goto error_exit;
 
+	xform_auth->auth.key.data = key;
 	xform_auth->auth.key.length = (uint16_t)len;
 
+	key += xform_auth->auth.key.length;
+	max_key_len -= xform_auth->auth.key.length;
+
 	if (strcmp(tokens[11], "digest_size"))
 		goto error_exit;
 
@@ -4252,8 +4247,8 @@ parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
 	if (status < 0)
 		goto error_exit;
 
-	xform_cipher = parse_table_action_cipher(p, tokens, 7, encrypt,
-			used_n_tokens);
+	xform_cipher = parse_table_action_cipher(p, key, max_key_len, tokens, 7,
+			encrypt, used_n_tokens);
 	if (xform_cipher == NULL)
 		goto error_exit;
 
@@ -4268,8 +4263,6 @@ parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
 	}
 
 error_exit:
-	if (xform_auth->auth.key.data)
-		free(xform_auth->auth.key.data);
 	if (p->cipher_auth.auth_iv.val) {
 		free(p->cipher_auth.auth_iv.val);
 		p->cipher_auth.auth_iv.val = 0;
@@ -4282,8 +4275,8 @@ parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
 
 static struct rte_crypto_sym_xform *
 parse_table_action_aead(struct rte_table_action_sym_crypto_params *p,
-		char **tokens, uint32_t n_tokens, uint32_t encrypt,
-		uint32_t *used_n_tokens)
+		uint8_t *key, uint32_t max_key_len, char **tokens,
+		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
 {
 	struct rte_crypto_sym_xform *xform_aead;
 	int status;
@@ -4312,15 +4305,16 @@ parse_table_action_aead(struct rte_table_action_sym_crypto_params *p,
 
 	/* aead_key */
 	len = strlen(tokens[4]);
-	xform_aead->aead.key.data = calloc(1, len / 2 + 1);
-	if (xform_aead->aead.key.data == NULL)
+	if (len / 2 > max_key_len) {
+		status = -ENOMEM;
 		goto error_exit;
+	}
 
-	status = softnic_parse_hex_string(tokens[4], xform_aead->aead.key.data,
-			(uint32_t *)&len);
+	status = softnic_parse_hex_string(tokens[4], key, (uint32_t *)&len);
 	if (status < 0)
 		goto error_exit;
 
+	xform_aead->aead.key.data = key;
 	xform_aead->aead.key.length = (uint16_t)len;
 
 	/* aead_iv */
@@ -4362,8 +4356,6 @@ parse_table_action_aead(struct rte_table_action_sym_crypto_params *p,
 	return xform_aead;
 
 error_exit:
-	if (xform_aead->aead.key.data)
-		free(xform_aead->aead.key.data);
 	if (p->aead.iv.val) {
 		free(p->aead.iv.val);
 		p->aead.iv.val = NULL;
@@ -4386,6 +4378,8 @@ parse_table_action_sym_crypto(char **tokens,
 {
 	struct rte_table_action_sym_crypto_params *p = &a->sym_crypto;
 	struct rte_crypto_sym_xform *xform = NULL;
+	uint8_t *key = a->sym_crypto_key;
+	uint32_t max_key_len = SYM_CRYPTO_MAX_KEY_SIZE;
 	uint32_t used_n_tokens;
 	uint32_t encrypt;
 	int status;
@@ -4410,20 +4404,20 @@ parse_table_action_sym_crypto(char **tokens,
 		tokens += 3;
 		n_tokens -= 3;
 
-		xform = parse_table_action_cipher(p, tokens, n_tokens, encrypt,
-				&used_n_tokens);
+		xform = parse_table_action_cipher(p, key, max_key_len, tokens,
+				n_tokens, encrypt, &used_n_tokens);
 	} else if (strcmp(tokens[3], "cipher_auth") == 0) {
 		tokens += 3;
 		n_tokens -= 3;
 
-		xform = parse_table_action_cipher_auth(p, tokens, n_tokens,
-				encrypt, &used_n_tokens);
+		xform = parse_table_action_cipher_auth(p, key, max_key_len,
+				tokens, n_tokens, encrypt, &used_n_tokens);
 	} else if (strcmp(tokens[3], "aead") == 0) {
 		tokens += 3;
 		n_tokens -= 3;
 
-		xform = parse_table_action_aead(p, tokens, n_tokens, encrypt,
-				&used_n_tokens);
+		xform = parse_table_action_aead(p, key, max_key_len, tokens,
+				n_tokens, encrypt, &used_n_tokens);
 	}
 
 	if (xform == NULL)
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index 415434d0d..08bc66051 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -948,6 +948,9 @@ struct softnic_table_rule_match {
 	} match;
 };
 
+#ifndef SYM_CRYPTO_MAX_KEY_SIZE
+#define SYM_CRYPTO_MAX_KEY_SIZE		(256)
+#endif
 struct softnic_table_rule_action {
 	uint64_t action_mask;
 	struct rte_table_action_fwd_params fwd;
@@ -962,6 +965,7 @@ struct softnic_table_rule_action {
 	struct rte_table_action_tag_params tag;
 	struct rte_table_action_decap_params decap;
 	struct rte_table_action_sym_crypto_params sym_crypto;
+	uint8_t sym_crypto_key[SYM_CRYPTO_MAX_KEY_SIZE];
 };
 
 struct rte_flow {
diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c
index 309b2936e..770b3bcd4 100644
--- a/examples/ip_pipeline/cli.c
+++ b/examples/ip_pipeline/cli.c
@@ -3772,24 +3772,18 @@ parse_free_sym_crypto_param_data(struct rte_table_action_sym_crypto_params *p)
 
 		switch (xform[i]->type) {
 		case RTE_CRYPTO_SYM_XFORM_CIPHER:
-			if (xform[i]->cipher.key.data)
-				free(xform[i]->cipher.key.data);
 			if (p->cipher_auth.cipher_iv.val)
 				free(p->cipher_auth.cipher_iv.val);
 			if (p->cipher_auth.cipher_iv_update.val)
 				free(p->cipher_auth.cipher_iv_update.val);
 			break;
 		case RTE_CRYPTO_SYM_XFORM_AUTH:
-			if (xform[i]->auth.key.data)
-				free(xform[i]->cipher.key.data);
 			if (p->cipher_auth.auth_iv.val)
 				free(p->cipher_auth.cipher_iv.val);
 			if (p->cipher_auth.auth_iv_update.val)
 				free(p->cipher_auth.cipher_iv_update.val);
 			break;
 		case RTE_CRYPTO_SYM_XFORM_AEAD:
-			if (xform[i]->aead.key.data)
-				free(xform[i]->cipher.key.data);
 			if (p->aead.iv.val)
 				free(p->aead.iv.val);
 			if (p->aead.aad.val)
@@ -3804,8 +3798,8 @@ parse_free_sym_crypto_param_data(struct rte_table_action_sym_crypto_params *p)
 
 static struct rte_crypto_sym_xform *
 parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p,
-		char **tokens, uint32_t n_tokens, uint32_t encrypt,
-		uint32_t *used_n_tokens)
+		uint8_t *key, uint32_t max_key_len, char **tokens,
+		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
 {
 	struct rte_crypto_sym_xform *xform_cipher;
 	int status;
@@ -3832,16 +3826,16 @@ parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p,
 
 	/* cipher_key */
 	len = strlen(tokens[4]);
-	xform_cipher->cipher.key.data = calloc(1, len / 2 + 1);
-	if (xform_cipher->cipher.key.data == NULL)
+	if (len / 2 > max_key_len) {
+		status = -ENOMEM;
 		goto error_exit;
+	}
 
-	status = parse_hex_string(tokens[4],
-			xform_cipher->cipher.key.data,
-			(uint32_t *)&len);
+	status = parse_hex_string(tokens[4], key, (uint32_t *)&len);
 	if (status < 0)
 		goto error_exit;
 
+	xform_cipher->cipher.key.data = key;
 	xform_cipher->cipher.key.length = (uint16_t)len;
 
 	/* cipher_iv */
@@ -3865,9 +3859,6 @@ parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p,
 	return xform_cipher;
 
 error_exit:
-	if (xform_cipher->cipher.key.data)
-		free(xform_cipher->cipher.key.data);
-
 	if (p->cipher_auth.cipher_iv.val) {
 		free(p->cipher_auth.cipher_iv.val);
 		p->cipher_auth.cipher_iv.val = NULL;
@@ -3880,8 +3871,8 @@ parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p,
 
 static struct rte_crypto_sym_xform *
 parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
-		char **tokens, uint32_t n_tokens, uint32_t encrypt,
-		uint32_t *used_n_tokens)
+		uint8_t *key, uint32_t max_key_len, char **tokens,
+		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
 {
 	struct rte_crypto_sym_xform *xform_cipher;
 	struct rte_crypto_sym_xform *xform_auth;
@@ -3910,17 +3901,21 @@ parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
 
 	/* auth_key */
 	len = strlen(tokens[10]);
-	xform_auth->auth.key.data = calloc(1, len / 2 + 1);
-	if (xform_auth->auth.key.data == NULL)
+	if (len / 2 > max_key_len) {
+		status = -ENOMEM;
 		goto error_exit;
+	}
 
-	status = parse_hex_string(tokens[10],
-			xform_auth->auth.key.data, (uint32_t *)&len);
+	status = parse_hex_string(tokens[10], key, (uint32_t *)&len);
 	if (status < 0)
 		goto error_exit;
 
+	xform_auth->auth.key.data = key;
 	xform_auth->auth.key.length = (uint16_t)len;
 
+	key += xform_auth->auth.key.length;
+	max_key_len -= xform_auth->auth.key.length;
+
 	if (strcmp(tokens[11], "digest_size"))
 		goto error_exit;
 
@@ -3929,8 +3924,8 @@ parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
 	if (status < 0)
 		goto error_exit;
 
-	xform_cipher = parse_table_action_cipher(p, tokens, 7, encrypt,
-			used_n_tokens);
+	xform_cipher = parse_table_action_cipher(p, key, max_key_len, tokens,
+			7, encrypt, used_n_tokens);
 	if (xform_cipher == NULL)
 		goto error_exit;
 
@@ -3945,8 +3940,6 @@ parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
 	}
 
 error_exit:
-	if (xform_auth->auth.key.data)
-		free(xform_auth->auth.key.data);
 	if (p->cipher_auth.auth_iv.val) {
 		free(p->cipher_auth.auth_iv.val);
 		p->cipher_auth.auth_iv.val = 0;
@@ -3959,8 +3952,8 @@ parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
 
 static struct rte_crypto_sym_xform *
 parse_table_action_aead(struct rte_table_action_sym_crypto_params *p,
-		char **tokens, uint32_t n_tokens, uint32_t encrypt,
-		uint32_t *used_n_tokens)
+		uint8_t *key, uint32_t max_key_len, char **tokens,
+		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
 {
 	struct rte_crypto_sym_xform *xform_aead;
 	int status;
@@ -3989,15 +3982,16 @@ parse_table_action_aead(struct rte_table_action_sym_crypto_params *p,
 
 	/* aead_key */
 	len = strlen(tokens[4]);
-	xform_aead->aead.key.data = calloc(1, len / 2 + 1);
-	if (xform_aead->aead.key.data == NULL)
+	if (len / 2 > max_key_len) {
+		status = -ENOMEM;
 		goto error_exit;
+	}
 
-	status = parse_hex_string(tokens[4], xform_aead->aead.key.data,
-			(uint32_t *)&len);
+	status = parse_hex_string(tokens[4], key, (uint32_t *)&len);
 	if (status < 0)
 		goto error_exit;
 
+	xform_aead->aead.key.data = key;
 	xform_aead->aead.key.length = (uint16_t)len;
 
 	/* aead_iv */
@@ -4039,8 +4033,6 @@ parse_table_action_aead(struct rte_table_action_sym_crypto_params *p,
 	return xform_aead;
 
 error_exit:
-	if (xform_aead->aead.key.data)
-		free(xform_aead->aead.key.data);
 	if (p->aead.iv.val) {
 		free(p->aead.iv.val);
 		p->aead.iv.val = NULL;
@@ -4063,6 +4055,8 @@ parse_table_action_sym_crypto(char **tokens,
 {
 	struct rte_table_action_sym_crypto_params *p = &a->sym_crypto;
 	struct rte_crypto_sym_xform *xform = NULL;
+	uint8_t *key = a->sym_crypto_key;
+	uint32_t max_key_len = SYM_CRYPTO_MAX_KEY_SIZE;
 	uint32_t used_n_tokens;
 	uint32_t encrypt;
 	int status;
@@ -4087,20 +4081,20 @@ parse_table_action_sym_crypto(char **tokens,
 		tokens += 3;
 		n_tokens -= 3;
 
-		xform = parse_table_action_cipher(p, tokens, n_tokens, encrypt,
-				&used_n_tokens);
+		xform = parse_table_action_cipher(p, key, max_key_len, tokens,
+				n_tokens, encrypt, &used_n_tokens);
 	} else if (strcmp(tokens[3], "cipher_auth") == 0) {
 		tokens += 3;
 		n_tokens -= 3;
 
-		xform = parse_table_action_cipher_auth(p, tokens, n_tokens,
-				encrypt, &used_n_tokens);
+		xform = parse_table_action_cipher_auth(p, key, max_key_len,
+				tokens, n_tokens, encrypt, &used_n_tokens);
 	} else if (strcmp(tokens[3], "aead") == 0) {
 		tokens += 3;
 		n_tokens -= 3;
 
-		xform = parse_table_action_aead(p, tokens, n_tokens, encrypt,
-				&used_n_tokens);
+		xform = parse_table_action_aead(p, key, max_key_len, tokens,
+				n_tokens, encrypt, &used_n_tokens);
 	}
 
 	if (xform == NULL)
diff --git a/examples/ip_pipeline/cryptodev.c b/examples/ip_pipeline/cryptodev.c
index ac1e38d6a..94a0462d0 100644
--- a/examples/ip_pipeline/cryptodev.c
+++ b/examples/ip_pipeline/cryptodev.c
@@ -90,8 +90,6 @@ cryptodev_create(const char *name, struct cryptodev_params *params)
 
 	if (dev_info.max_nb_queue_pairs < params->n_queues)
 		return NULL;
-	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_HW_ACCELERATED)
-		return NULL;
 
 	dev_conf.socket_id = socket_id;
 	dev_conf.nb_queue_pairs = params->n_queues;
diff --git a/examples/ip_pipeline/pipeline.h b/examples/ip_pipeline/pipeline.h
index 278775c2d..4d2ee29a5 100644
--- a/examples/ip_pipeline/pipeline.h
+++ b/examples/ip_pipeline/pipeline.h
@@ -276,6 +276,10 @@ struct table_rule_match {
 	} match;
 };
 
+#ifndef SYM_CRYPTO_MAX_KEY_SIZE
+#define SYM_CRYPTO_MAX_KEY_SIZE                (256)
+#endif
+
 struct table_rule_action {
 	uint64_t action_mask;
 	struct rte_table_action_fwd_params fwd;
@@ -288,8 +292,10 @@ struct table_rule_action {
 	struct rte_table_action_stats_params stats;
 	struct rte_table_action_time_params time;
 	struct rte_table_action_sym_crypto_params sym_crypto;
+	uint8_t sym_crypto_key[SYM_CRYPTO_MAX_KEY_SIZE];
 	struct rte_table_action_tag_params tag;
 	struct rte_table_action_decap_params decap;
+
 };
 
 struct table_rule {
diff --git a/examples/l2fwd-crypto/main.c b/examples/l2fwd-crypto/main.c
index e282cb7bf..09cd4c9a2 100644
--- a/examples/l2fwd-crypto/main.c
+++ b/examples/l2fwd-crypto/main.c
@@ -136,6 +136,7 @@ struct l2fwd_crypto_options {
 	struct rte_crypto_sym_xform cipher_xform;
 	unsigned ckey_param;
 	int ckey_random_size;
+	uint8_t cipher_key[MAX_KEY_SIZE];
 
 	struct l2fwd_iv cipher_iv;
 	unsigned int cipher_iv_param;
@@ -144,6 +145,7 @@ struct l2fwd_crypto_options {
 	struct rte_crypto_sym_xform auth_xform;
 	uint8_t akey_param;
 	int akey_random_size;
+	uint8_t auth_key[MAX_KEY_SIZE];
 
 	struct l2fwd_iv auth_iv;
 	unsigned int auth_iv_param;
@@ -152,6 +154,7 @@ struct l2fwd_crypto_options {
 	struct rte_crypto_sym_xform aead_xform;
 	unsigned int aead_key_param;
 	int aead_key_random_size;
+	uint8_t aead_key[MAX_KEY_SIZE];
 
 	struct l2fwd_iv aead_iv;
 	unsigned int aead_iv_param;
@@ -1219,8 +1222,7 @@ l2fwd_crypto_parse_args_long_options(struct l2fwd_crypto_options *options,
 	else if (strcmp(lgopts[option_index].name, "cipher_key") == 0) {
 		options->ckey_param = 1;
 		options->cipher_xform.cipher.key.length =
-			parse_bytes(options->cipher_xform.cipher.key.data, optarg,
-					MAX_KEY_SIZE);
+			parse_bytes(options->cipher_key, optarg, MAX_KEY_SIZE);
 		if (options->cipher_xform.cipher.key.length > 0)
 			return 0;
 		else
@@ -1256,8 +1258,7 @@ l2fwd_crypto_parse_args_long_options(struct l2fwd_crypto_options *options,
 	else if (strcmp(lgopts[option_index].name, "auth_key") == 0) {
 		options->akey_param = 1;
 		options->auth_xform.auth.key.length =
-			parse_bytes(options->auth_xform.auth.key.data, optarg,
-					MAX_KEY_SIZE);
+			parse_bytes(options->auth_key, optarg, MAX_KEY_SIZE);
 		if (options->auth_xform.auth.key.length > 0)
 			return 0;
 		else
@@ -1294,8 +1295,7 @@ l2fwd_crypto_parse_args_long_options(struct l2fwd_crypto_options *options,
 	else if (strcmp(lgopts[option_index].name, "aead_key") == 0) {
 		options->aead_key_param = 1;
 		options->aead_xform.aead.key.length =
-			parse_bytes(options->aead_xform.aead.key.data, optarg,
-					MAX_KEY_SIZE);
+			parse_bytes(options->aead_key, optarg, MAX_KEY_SIZE);
 		if (options->aead_xform.aead.key.length > 0)
 			return 0;
 		else
@@ -2348,8 +2348,7 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports,
 					options->aead_xform.aead.key.length =
 						cap->sym.aead.key_size.min;
 
-				generate_random_key(
-					options->aead_xform.aead.key.data,
+				generate_random_key(options->aead_key,
 					options->aead_xform.aead.key.length);
 			}
 
@@ -2406,8 +2405,7 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports,
 					options->cipher_xform.cipher.key.length =
 						cap->sym.cipher.key_size.min;
 
-				generate_random_key(
-					options->cipher_xform.cipher.key.data,
+				generate_random_key(options->cipher_key,
 					options->cipher_xform.cipher.key.length);
 			}
 		}
@@ -2440,8 +2438,7 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports,
 					options->auth_xform.auth.key.length =
 						cap->sym.auth.key_size.min;
 
-				generate_random_key(
-					options->auth_xform.auth.key.data,
+				generate_random_key(options->auth_key,
 					options->auth_xform.auth.key.length);
 			}
 
@@ -2612,20 +2609,11 @@ initialize_ports(struct l2fwd_crypto_options *options)
 static void
 reserve_key_memory(struct l2fwd_crypto_options *options)
 {
-	options->cipher_xform.cipher.key.data = rte_malloc("crypto key",
-						MAX_KEY_SIZE, 0);
-	if (options->cipher_xform.cipher.key.data == NULL)
-		rte_exit(EXIT_FAILURE, "Failed to allocate memory for cipher key");
-
-	options->auth_xform.auth.key.data = rte_malloc("auth key",
-						MAX_KEY_SIZE, 0);
-	if (options->auth_xform.auth.key.data == NULL)
-		rte_exit(EXIT_FAILURE, "Failed to allocate memory for auth key");
-
-	options->aead_xform.aead.key.data = rte_malloc("aead key",
-						MAX_KEY_SIZE, 0);
-	if (options->aead_xform.aead.key.data == NULL)
-		rte_exit(EXIT_FAILURE, "Failed to allocate memory for AEAD key");
+	options->cipher_xform.cipher.key.data = options->cipher_key;
+
+	options->auth_xform.auth.key.data = options->auth_key;
+
+	options->aead_xform.aead.key.data = options->aead_key;
 
 	options->cipher_iv.data = rte_malloc("cipher iv", MAX_KEY_SIZE, 0);
 	if (options->cipher_iv.data == NULL)
diff --git a/lib/librte_cryptodev/Makefile b/lib/librte_cryptodev/Makefile
index c20e090a8..55d352a23 100644
--- a/lib/librte_cryptodev/Makefile
+++ b/lib/librte_cryptodev/Makefile
@@ -7,7 +7,7 @@ include $(RTE_SDK)/mk/rte.vars.mk
 LIB = librte_cryptodev.a
 
 # library version
-LIBABIVER := 7
+LIBABIVER := 8
 
 # build flags
 CFLAGS += -O3
diff --git a/lib/librte_cryptodev/meson.build b/lib/librte_cryptodev/meson.build
index 9e009d466..0a2275d75 100644
--- a/lib/librte_cryptodev/meson.build
+++ b/lib/librte_cryptodev/meson.build
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017-2019 Intel Corporation
 
-version = 7
+version = 8
 allow_experimental_apis = true
 sources = files('rte_cryptodev.c', 'rte_cryptodev_pmd.c')
 headers = files('rte_cryptodev.h',
diff --git a/lib/librte_cryptodev/rte_crypto_sym.h b/lib/librte_cryptodev/rte_crypto_sym.h
index bfce84a35..4a6adbeef 100644
--- a/lib/librte_cryptodev/rte_crypto_sym.h
+++ b/lib/librte_cryptodev/rte_crypto_sym.h
@@ -114,8 +114,8 @@ struct rte_crypto_cipher_xform {
 	/**< Cipher algorithm */
 
 	struct {
-		uint8_t *data;	/**< pointer to key data */
-		uint16_t length;/**< key length in bytes */
+		const uint8_t *data;	/**< pointer to key data */
+		uint16_t length;	/**< key length in bytes */
 	} key;
 	/**< Cipher key
 	 *
@@ -282,8 +282,8 @@ struct rte_crypto_auth_xform {
 	/**< Authentication algorithm selection */
 
 	struct {
-		uint8_t *data;	/**< pointer to key data */
-		uint16_t length;/**< key length in bytes */
+		const uint8_t *data;	/**< pointer to key data */
+		uint16_t length;	/**< key length in bytes */
 	} key;
 	/**< Authentication key data.
 	 * The authentication key length MUST be less than or equal to the
@@ -374,8 +374,8 @@ struct rte_crypto_aead_xform {
 	/**< AEAD algorithm selection */
 
 	struct {
-		uint8_t *data;  /**< pointer to key data */
-		uint16_t length;/**< key length in bytes */
+		const uint8_t *data;	/**< pointer to key data */
+		uint16_t length;	/**< key length in bytes */
 	} key;
 
 	struct {
-- 
2.14.5


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC] ethdev: add min/max MTU to device info
  @ 2019-06-24 13:18  3%               ` Nithin Kumar Dabilpuram
  0 siblings, 0 replies; 200+ results
From: Nithin Kumar Dabilpuram @ 2019-06-24 13:18 UTC (permalink / raw)
  To: Ian Stokes, Ananyev, Konstantin, Morten Brørup,
	Stephen Hemminger, Yigit, Ferruh
  Cc: dev, Mcnamara, John, Kovacevic, Marko, Thomas Monjalon, Andrew Rybchenko

Hi All,

Since Ian's change didn't include MTU interpretation issue, we want to see if we can send out a patch for this discussion to conclude as we have a similar problem.

Currently two ways are as below.
#1 Konstantin's solution of adding new api rte_ethdev_mtu_to_frame_size(devid, mtu), that would dynamically provide the new max mtu.
#2 Can we have the value of max_mtu field in rte_eth_dev_info  be dynamic i.e based on device configure to indicate that new Tx offloads would need more space for L2.
       For this we can update max_mtu field documentation without abi change.

I also see a problem with above two solutions that is not present with Linux like approach. It is that currently MTU configuration both effects Rx frame size and Tx frame size.
If we change the MTU interpretation based on Tx offloads, then for Rx, there is a confusion of what will be its max frame size accepted.

Thanks
Nithin

 -----Original Message-----
From: dev <dev-bounces@dpdk.org> On Behalf Of Ian Stokes
Sent: Wednesday, February 20, 2019 9:32 PM
To: Ananyev, Konstantin <konstantin.ananyev@intel.com>; Morten Brørup <mb@smartsharesystems.com>; Stephen Hemminger <stephen@networkplumber.org>
Cc: dev@dpdk.org; Mcnamara, John <john.mcnamara@intel.com>; Kovacevic, Marko <marko.kovacevic@intel.com>; Thomas Monjalon <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew Rybchenko <arybchenko@solarflare.com>
Subject: Re: [dpdk-dev] [RFC] ethdev: add min/max MTU to device info

On 2/7/2019 12:00 PM, Ananyev, Konstantin wrote:
> 
>>> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Ananyev,
>>> Konstantin
>>>>
>>>>> From: dev on behalf of Stephen Hemminger
>>>>> On Wed, 6 Feb 2019 14:05:34 +0100
>>>>> Morten Brørup <mb@smartsharesystems.com> wrote:
>>>>>
>>>>>> Good work, Stephen.
>>>>>>
>>>>>> It should also be documented how PMDs should interpret this MTU.
>>>>>>
>>>>>> Obviously, a VLAN tagged Ethernet frame grows from 1518 to 1522
>>> bytes incl. header and CRC, and should be allowed with an Ethernet
>>>> MTU of 1500 bytes. There's even a #define ETHER_MAX_VLAN_FRAME_LEN
>>> for this, but that's as far as it goes...
>>>>>>
>>>>>> But how about frames with even larger headers, e.g. 4 MPLS labels
>>> makes a frame 16 bytes longer, i.e. it grows from 1518 to 1534
>>>> bytes... is such a frame acceptable with an MTU of 1500 bytes?
>>>>>
>>>>> No. According to standard practice in Linux and FreeBSD, only the
>>> first VLAN tag is free.
>>>>> After that any other headers count against MTU.
>>>>
>>>> Thank you for the insights. Just to clarify:
>>>> 1 VLAN tag is allowed for free.
>>>> But on order to support two VLAN tags, the MTU must be increased by
>>> the size of one VLAN tag, because the first VLAN tag is free?
>>>> Or must the MTU be increased by the size of two VLAN tags, because
>>> only the special case of exactly one VLAN tag is free?
>>>
>>> Can we introduce new function at ehtdev API to query PMD frame size
>>> based on MTU?
>>> Something like: rte_ethdev_mtu_to_frame_size(uint32_t mtu);
>>> Provide default behavior and allow PMD to overwrite it?
>>> Konstantin
>>
>> This assumes that the Layer 2 headers are fixed size. If you add e.g. an MPLS stack to the packet, the number of MPLS labels can vary, and
>> thus the size of the Layer 2 headers varies with each packet.
> 
> If all this extra stuff (MPLS labels, etc.) is added by SW - then yes, it will be SW (upper layer) to take account about such overhead
> and it would be accounted by PMD frame-size caluclation.
> If these fields would be added by HW/PMD - then it would be PMD responsibility to take these extras into account when calculating
> frame size.
> 
>>
>> It is a problem if Layer 3/4 offload features make assumptions about the Layer 3/4 MTUs based on the Layer 2 MTU without considering the
>> size of the actual Ethernet headers of each packet, but simply assume that the Ethernet header size is fixed.
>>
>> It might currently be calculated correctly for untagged or single VLAN tagged packets (assuming the VLAN tag is not already part of the
>> packet data, but is set in the mbuf for the NIC to add).
> 
> That could be a default behavior for that function.
> Konstantin
> 

Hi All,

with a view to help progress this I've posted an RFC series based on 
Stephens work and some of the PMD drivers

http://mails.dpdk.org/archives/dev/2019-February/124938.html

Any feedback welcome

Thanks
Ian

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v4 10/10] doc: announce bbdev changes
  @ 2019-06-24  2:52  8%   ` Nicolas Chautru
  2019-06-30 23:04  0%     ` Mokhtar, Amr
  2019-07-01 11:14  4%     ` Akhil Goyal
  0 siblings, 2 replies; 200+ results
From: Nicolas Chautru @ 2019-06-24  2:52 UTC (permalink / raw)
  To: akhil.goyal, dev; +Cc: thomas, ferruh.yigit, amr.mokhtar, Nicolas Chautru

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=a, Size: 1409 bytes --]

Update of the release notes for BBDEV features add
and extension of ABI in previous commit.

Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
---
 doc/guides/rel_notes/release_19_08.rst | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 8c3932d..35d3a09 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -88,6 +88,19 @@ New Features
   * Added multi-queue support to allow one af_xdp vdev with multiple netdev
     queues
 
+* **Added a FPGA_LTE_FEC bbdev PMD.**
+
+  Added the new ``fpga_lte_fec`` bbdev driver for the Intel® FPGA PAC
+  (Programmable  Acceleration Card) N3000.  See the
+  :doc:`../bbdevs/fpga_lte_fec` BBDEV guide for more details on this new driver.
+  
+* **Updated TURBO_SW bbdev PMD.**
+
+  Updated the ``turbo_sw`` bbdev driver with changes including:
+
+  * Added option to build the driver with or without dependency of external
+    SDK libraries.
+  * Added support for 5GNR encode/decode operations.
 
 Removed Items
 -------------
@@ -140,6 +153,8 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* bbdev: New parameters added to support 5GNR operations.
+
 
 Shared Library Versions
 -----------------------
-- 
1.8.3.1


^ permalink raw reply	[relevance 8%]

* [dpdk-dev] [PATCH v3 10/10] doc: announce bbdev changes
  @ 2019-06-21 16:59  5%   ` Nicolas Chautru
  0 siblings, 0 replies; 200+ results
From: Nicolas Chautru @ 2019-06-21 16:59 UTC (permalink / raw)
  To: akhil.goyal, dev; +Cc: thomas, ferruh.yigit, amr.mokhtar, Nicolas Chautru

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=:\b, Size: 1316 bytes --]

Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
---
 doc/guides/rel_notes/release_19_08.rst | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 8c3932d..35d3a09 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -88,6 +88,19 @@ New Features
   * Added multi-queue support to allow one af_xdp vdev with multiple netdev
     queues
 
+* **Added a FPGA_LTE_FEC bbdev PMD.**
+
+  Added the new ``fpga_lte_fec`` bbdev driver for the Intel® FPGA PAC
+  (Programmable  Acceleration Card) N3000.  See the
+  :doc:`../bbdevs/fpga_lte_fec` BBDEV guide for more details on this new driver.
+  
+* **Updated TURBO_SW bbdev PMD.**
+
+  Updated the ``turbo_sw`` bbdev driver with changes including:
+
+  * Added option to build the driver with or without dependency of external
+    SDK libraries.
+  * Added support for 5GNR encode/decode operations.
 
 Removed Items
 -------------
@@ -140,6 +153,8 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* bbdev: New parameters added to support 5GNR operations.
+
 
 Shared Library Versions
 -----------------------
-- 
1.8.3.1


^ permalink raw reply	[relevance 5%]

* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
  2019-06-21 16:45  3%                 ` David Marchand
@ 2019-06-21 16:57  3%                   ` Wang, Haiyue
  0 siblings, 0 replies; 200+ results
From: Wang, Haiyue @ 2019-06-21 16:57 UTC (permalink / raw)
  To: David Marchand
  Cc: Stephen Hemminger, Andrew Rybchenko, dev, Yigit, Ferruh, Thomas Monjalon

NAK is expected. ☺ Just like the __rte_experimental API may be remove one day,
the application will fight for compiling, or just keep their own DPDK version.

Well, private handling is not a good thing, but HW is different, reserving some bits may
also be another API style. In real world, many workarounds exist, then a good solution
comes.

BR,
Haiyue

From: David Marchand [mailto:david.marchand@redhat.com]
Sent: Saturday, June 22, 2019 00:46
To: Wang, Haiyue <haiyue.wang@intel.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>; Andrew Rybchenko <arybchenko@solarflare.com>; dev@dpdk.org; Yigit, Ferruh <ferruh.yigit@intel.com>; Thomas Monjalon <thomas@monjalon.net>
Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch



On Fri, Jun 21, 2019 at 6:37 PM Wang, Haiyue <haiyue.wang@intel.com<mailto:haiyue.wang@intel.com>> wrote:
> -----Original Message-----
> From: Stephen Hemminger [mailto:stephen@networkplumber.org<mailto:stephen@networkplumber.org>]
> Sent: Friday, June 21, 2019 23:14
> To: Wang, Haiyue <haiyue.wang@intel.com<mailto:haiyue.wang@intel.com>>
> Cc: Andrew Rybchenko <arybchenko@solarflare.com<mailto:arybchenko@solarflare.com>>; dev@dpdk.org<mailto:dev@dpdk.org>; Yigit, Ferruh <ferruh.yigit@intel.com<mailto:ferruh.yigit@intel.com>>;
> Thomas Monjalon <thomas@monjalon.net<mailto:thomas@monjalon.net>>
> Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
>
> On Fri, 21 Jun 2019 07:43:13 +0000
> "Wang, Haiyue" <haiyue.wang@intel.com<mailto:haiyue.wang@intel.com>> wrote:
>
> > The experimental reserved bits number is 6 currently. Tt can be one-bit
> >
> > for each features up to the the maximum number 6. It can also be some
> >
> > bits encoding: e.g, 6 bits can stand for 63 maximum number of features.
> >
> >
> >
> > We call these reserved bits as DEV_RX_OFFLOAD_PMD_SCRATCH. And the left
> >
> > unused bits number is : 64 - 19 (currently defined) - 6 (PMD scartch) =
> >
> > 39.
> >
> >
> >
> > This is not so nice for applications, they need to check PMD's driver
> >
> > name for lookuping their DEV_RX_OFFLOAD_PMD_SCRATCH definitions. But it
> >
> > is good for the applications to make use of the hardware compatibility.
> >
> >
> >
> > Signed-off-by: Haiyue Wang <haiyue.wang@intel.com<mailto:haiyue.wang@intel.com>><mailto:haiyue.wang@intel.com<mailto:haiyue.wang@intel.com>>
> >
> > I would say that it very bad for applications. It sounds like reserved bits
> > in registers which have meaning in fact and sometimes different meaning.
> > Of course, it is not that bad when rules are defined, but such kind of
> > features tend to spread and clutter up interfaces. IMHO, the feature is
> > really frightening.
>
> There are two issues. First, having more OFFLOAD capability feature bits
> is good. As long as these feature bits are well defined. If only one vendor
> implements that feature that is fine. Another vendor can implement the
> same thing, and application can know what it is asking for.
>
> The other issue is the limited number of feature bits. I expect that some
> time soon the bits will have to grow into an array and cause API/ABI
> break. That can be fixed when the last bit is exhausted.
>
>

If one bit for one feature, then it will be exhausted soon. That's why I said
using DEV_RX_OFFLOAD_PMD_SCRATCH bits to *encode* the PMD's offload if it is no
so common now, such as 6 bits will give the vendor 63 different types to select
their own features. And have 39 for common features defined in the future.

Frankly speaking, if we open some bits for PMD using, like the __rte_experimental
API style, then PMD will have more rich feature for open, customer can use the
experimental features, and these experimental features may be common in some day.

Just try to imagine what it would mean for the dataplane handling a packet:

if (is_port_vendor_X(portid)) {
  handle_exotic_vendor_X();
} else if (is_port_vendor_Y(portid)) {
  handle_exotic_vendor_Y();
} else {
  generic_handle();
}

Add to this changes with versions of dpdk since this would be out of the ABI/API stability and this is a huge mess.
This is a NAK for me.


--
David Marchand

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
  2019-06-21 16:37  0%               ` Wang, Haiyue
@ 2019-06-21 16:45  3%                 ` David Marchand
  2019-06-21 16:57  3%                   ` Wang, Haiyue
  0 siblings, 1 reply; 200+ results
From: David Marchand @ 2019-06-21 16:45 UTC (permalink / raw)
  To: Wang, Haiyue
  Cc: Stephen Hemminger, Andrew Rybchenko, dev, Yigit, Ferruh, Thomas Monjalon

On Fri, Jun 21, 2019 at 6:37 PM Wang, Haiyue <haiyue.wang@intel.com> wrote:

> > -----Original Message-----
> > From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> > Sent: Friday, June 21, 2019 23:14
> > To: Wang, Haiyue <haiyue.wang@intel.com>
> > Cc: Andrew Rybchenko <arybchenko@solarflare.com>; dev@dpdk.org; Yigit,
> Ferruh <ferruh.yigit@intel.com>;
> > Thomas Monjalon <thomas@monjalon.net>
> > Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload
> most-significant bits for PMD scartch
> >
> > On Fri, 21 Jun 2019 07:43:13 +0000
> > "Wang, Haiyue" <haiyue.wang@intel.com> wrote:
> >
> > > The experimental reserved bits number is 6 currently. Tt can be one-bit
> > >
> > > for each features up to the the maximum number 6. It can also be some
> > >
> > > bits encoding: e.g, 6 bits can stand for 63 maximum number of features.
> > >
> > >
> > >
> > > We call these reserved bits as DEV_RX_OFFLOAD_PMD_SCRATCH. And the left
> > >
> > > unused bits number is : 64 - 19 (currently defined) - 6 (PMD scartch) =
> > >
> > > 39.
> > >
> > >
> > >
> > > This is not so nice for applications, they need to check PMD's driver
> > >
> > > name for lookuping their DEV_RX_OFFLOAD_PMD_SCRATCH definitions. But it
> > >
> > > is good for the applications to make use of the hardware compatibility.
> > >
> > >
> > >
> > > Signed-off-by: Haiyue Wang <haiyue.wang@intel.com><mailto:
> haiyue.wang@intel.com>
> > >
> > > I would say that it very bad for applications. It sounds like reserved
> bits
> > > in registers which have meaning in fact and sometimes different
> meaning.
> > > Of course, it is not that bad when rules are defined, but such kind of
> > > features tend to spread and clutter up interfaces. IMHO, the feature is
> > > really frightening.
> >
> > There are two issues. First, having more OFFLOAD capability feature bits
> > is good. As long as these feature bits are well defined. If only one
> vendor
> > implements that feature that is fine. Another vendor can implement the
> > same thing, and application can know what it is asking for.
> >
> > The other issue is the limited number of feature bits. I expect that some
> > time soon the bits will have to grow into an array and cause API/ABI
> > break. That can be fixed when the last bit is exhausted.
> >
> >
>
> If one bit for one feature, then it will be exhausted soon. That's why I
> said
> using DEV_RX_OFFLOAD_PMD_SCRATCH bits to *encode* the PMD's offload if it
> is no
> so common now, such as 6 bits will give the vendor 63 different types to
> select
> their own features. And have 39 for common features defined in the future.
>
> Frankly speaking, if we open some bits for PMD using, like the
> __rte_experimental
> API style, then PMD will have more rich feature for open, customer can use
> the
> experimental features, and these experimental features may be common in
> some day.
>

Just try to imagine what it would mean for the dataplane handling a packet:

if (is_port_vendor_X(portid)) {
  handle_exotic_vendor_X();
} else if (is_port_vendor_Y(portid)) {
  handle_exotic_vendor_Y();
} else {
  generic_handle();
}

Add to this changes with versions of dpdk since this would be out of the
ABI/API stability and this is a huge mess.
This is a NAK for me.


-- 
David Marchand

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
  2019-06-21 15:14  3%             ` Stephen Hemminger
@ 2019-06-21 16:37  0%               ` Wang, Haiyue
  2019-06-21 16:45  3%                 ` David Marchand
  0 siblings, 1 reply; 200+ results
From: Wang, Haiyue @ 2019-06-21 16:37 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Andrew Rybchenko, dev, Yigit, Ferruh, Thomas Monjalon

> -----Original Message-----
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Friday, June 21, 2019 23:14
> To: Wang, Haiyue <haiyue.wang@intel.com>
> Cc: Andrew Rybchenko <arybchenko@solarflare.com>; dev@dpdk.org; Yigit, Ferruh <ferruh.yigit@intel.com>;
> Thomas Monjalon <thomas@monjalon.net>
> Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
> 
> On Fri, 21 Jun 2019 07:43:13 +0000
> "Wang, Haiyue" <haiyue.wang@intel.com> wrote:
> 
> > The experimental reserved bits number is 6 currently. Tt can be one-bit
> >
> > for each features up to the the maximum number 6. It can also be some
> >
> > bits encoding: e.g, 6 bits can stand for 63 maximum number of features.
> >
> >
> >
> > We call these reserved bits as DEV_RX_OFFLOAD_PMD_SCRATCH. And the left
> >
> > unused bits number is : 64 - 19 (currently defined) - 6 (PMD scartch) =
> >
> > 39.
> >
> >
> >
> > This is not so nice for applications, they need to check PMD's driver
> >
> > name for lookuping their DEV_RX_OFFLOAD_PMD_SCRATCH definitions. But it
> >
> > is good for the applications to make use of the hardware compatibility.
> >
> >
> >
> > Signed-off-by: Haiyue Wang <haiyue.wang@intel.com><mailto:haiyue.wang@intel.com>
> >
> > I would say that it very bad for applications. It sounds like reserved bits
> > in registers which have meaning in fact and sometimes different meaning.
> > Of course, it is not that bad when rules are defined, but such kind of
> > features tend to spread and clutter up interfaces. IMHO, the feature is
> > really frightening.
> 
> There are two issues. First, having more OFFLOAD capability feature bits
> is good. As long as these feature bits are well defined. If only one vendor
> implements that feature that is fine. Another vendor can implement the
> same thing, and application can know what it is asking for.
> 
> The other issue is the limited number of feature bits. I expect that some
> time soon the bits will have to grow into an array and cause API/ABI
> break. That can be fixed when the last bit is exhausted.
> 
> 

If one bit for one feature, then it will be exhausted soon. That's why I said
using DEV_RX_OFFLOAD_PMD_SCRATCH bits to *encode* the PMD's offload if it is no
so common now, such as 6 bits will give the vendor 63 different types to select
their own features. And have 39 for common features defined in the future.

Frankly speaking, if we open some bits for PMD using, like the __rte_experimental
API style, then PMD will have more rich feature for open, customer can use the
experimental features, and these experimental features may be common in some day.

Well, just my two cents. I've also provided the testpmd cmdline to help more
vendors can test their SCRATCH RX OFFLOADS if they have.

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v2 4/4] rawdev: pass device id as parameter to selftest
  @ 2019-06-21 15:56  3%   ` Bruce Richardson
  2019-07-04  9:33  0%     ` Shreyansh Jain
  0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2019-06-21 15:56 UTC (permalink / raw)
  To: dev; +Cc: Bruce Richardson, shreyansh.jain

When running self-tests, the driver needs to know the device on which to
run the tests, so we need to take the device ID as parameter. Only the
skeleton driver is providing this selftest capability right now, so we can
easily update it for this change.

Cc: shreyansh.jain@nxp.com
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---

Since this change only affects the internals of the drivers, it's not an
ABI or API change

---

 drivers/raw/skeleton_rawdev/skeleton_rawdev.c      | 8 +++++---
 drivers/raw/skeleton_rawdev/skeleton_rawdev.h      | 2 +-
 drivers/raw/skeleton_rawdev/skeleton_rawdev_test.c | 3 ++-
 lib/librte_rawdev/rte_rawdev.c                     | 2 +-
 lib/librte_rawdev/rte_rawdev_pmd.h                 | 2 +-
 5 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/raw/skeleton_rawdev/skeleton_rawdev.c b/drivers/raw/skeleton_rawdev/skeleton_rawdev.c
index 709be7691..42471fbd1 100644
--- a/drivers/raw/skeleton_rawdev/skeleton_rawdev.c
+++ b/drivers/raw/skeleton_rawdev/skeleton_rawdev.c
@@ -583,6 +583,8 @@ skeleton_rawdev_create(const char *name,
 		goto cleanup;
 	}
 
+	ret = rawdev->dev_id; /* return the rawdev id of new device */
+
 	rawdev->dev_ops = &skeleton_rawdev_ops;
 	rawdev->device = &vdev->device;
 
@@ -720,19 +722,19 @@ skeleton_rawdev_probe(struct rte_vdev_device *vdev)
 	/* In case of invalid argument, selftest != 1; ignore other values */
 
 	ret = skeleton_rawdev_create(name, vdev, rte_socket_id());
-	if (!ret) {
+	if (ret >= 0) {
 		/* In case command line argument for 'selftest' was passed;
 		 * if invalid arguments were passed, execution continues but
 		 * without selftest.
 		 */
 		if (selftest == 1)
-			test_rawdev_skeldev();
+			test_rawdev_skeldev(ret);
 	}
 
 	/* Device instance created; Second instance not possible */
 	skeldev_init_once = 1;
 
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 static int
diff --git a/drivers/raw/skeleton_rawdev/skeleton_rawdev.h b/drivers/raw/skeleton_rawdev/skeleton_rawdev.h
index 5045b5922..c3f92e72a 100644
--- a/drivers/raw/skeleton_rawdev/skeleton_rawdev.h
+++ b/drivers/raw/skeleton_rawdev/skeleton_rawdev.h
@@ -131,6 +131,6 @@ skeleton_rawdev_get_priv(const struct rte_rawdev *rawdev)
 	return rawdev->dev_private;
 }
 
-int test_rawdev_skeldev(void);
+int test_rawdev_skeldev(uint16_t dev_id);
 
 #endif /* __SKELETON_RAWDEV_H__ */
diff --git a/drivers/raw/skeleton_rawdev/skeleton_rawdev_test.c b/drivers/raw/skeleton_rawdev/skeleton_rawdev_test.c
index d7177ea75..ad700e21c 100644
--- a/drivers/raw/skeleton_rawdev/skeleton_rawdev_test.c
+++ b/drivers/raw/skeleton_rawdev/skeleton_rawdev_test.c
@@ -427,8 +427,9 @@ static void skeldev_test_run(int (*setup)(void),
 }
 
 int
-test_rawdev_skeldev(void)
+test_rawdev_skeldev(uint16_t dev_id)
 {
+	test_dev_id = dev_id;
 	testsuite_setup();
 
 	SKELDEV_TEST_RUN(NULL, NULL, test_rawdev_count);
diff --git a/lib/librte_rawdev/rte_rawdev.c b/lib/librte_rawdev/rte_rawdev.c
index 2b2f45d7c..15de2d413 100644
--- a/lib/librte_rawdev/rte_rawdev.c
+++ b/lib/librte_rawdev/rte_rawdev.c
@@ -378,7 +378,7 @@ rte_rawdev_selftest(uint16_t dev_id)
 	struct rte_rawdev *dev = &rte_rawdevs[dev_id];
 
 	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_selftest, -ENOTSUP);
-	return (*dev->dev_ops->dev_selftest)();
+	return (*dev->dev_ops->dev_selftest)(dev_id);
 }
 
 int
diff --git a/lib/librte_rawdev/rte_rawdev_pmd.h b/lib/librte_rawdev/rte_rawdev_pmd.h
index 5e6cf1d16..aa6af4a37 100644
--- a/lib/librte_rawdev/rte_rawdev_pmd.h
+++ b/lib/librte_rawdev/rte_rawdev_pmd.h
@@ -499,7 +499,7 @@ typedef int (*rawdev_firmware_unload_t)(struct rte_rawdev *dev);
  * @return
  *   Return 0 on success
  */
-typedef int (*rawdev_selftest_t)(void);
+typedef int (*rawdev_selftest_t)(uint16_t dev_id);
 
 /** Rawdevice operations function pointer table */
 struct rte_rawdev_ops {
-- 
2.21.0


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
  2019-06-21  7:43  2%           ` Wang, Haiyue
@ 2019-06-21 15:14  3%             ` Stephen Hemminger
  2019-06-21 16:37  0%               ` Wang, Haiyue
  0 siblings, 1 reply; 200+ results
From: Stephen Hemminger @ 2019-06-21 15:14 UTC (permalink / raw)
  To: Wang, Haiyue; +Cc: Andrew Rybchenko, dev, Yigit, Ferruh, Thomas Monjalon

On Fri, 21 Jun 2019 07:43:13 +0000
"Wang, Haiyue" <haiyue.wang@intel.com> wrote:

> I know my patch is ugly for making customers happy, I will try to find other method not to
> break the beautiful rte_ethdev desgin.
> 
> Really thanks for your reply. This helps me understand the PMD design practice more.
> 
> BR,
> Haiyue
> 
> From: Andrew Rybchenko [mailto:arybchenko@solarflare.com]
> Sent: Friday, June 21, 2019 15:40
> To: Wang, Haiyue <haiyue.wang@intel.com>; dev@dpdk.org
> Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; Thomas Monjalon <thomas@monjalon.net>
> Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
> 
> On 6/21/19 10:37 AM, Wang, Haiyue wrote:
> Then this is not so generic if a workaround is needed. In other words, no one is so perfect. ☺
> 
> Yes, it is a bug. No one is perfect.
> 
> 
> 
> BR,
> Haiyue
> 
> From: Andrew Rybchenko [mailto:arybchenko@solarflare.com]
> Sent: Friday, June 21, 2019 15:34
> To: Wang, Haiyue <haiyue.wang@intel.com><mailto:haiyue.wang@intel.com>; dev@dpdk.org<mailto:dev@dpdk.org>
> Cc: Yigit, Ferruh <ferruh.yigit@intel.com><mailto:ferruh.yigit@intel.com>; Thomas Monjalon <thomas@monjalon.net><mailto:thomas@monjalon.net>
> Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
> 
> On 6/21/19 4:12 AM, Wang, Haiyue wrote:
> Not so frightening in real world for an application to be aware of its NICs:
> https://github.com/Juniper/contrail-vrouter/blob/master/dpdk/vr_dpdk_ethdev.c#L387<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_Juniper_contrail-2Dvrouter_blob_master_dpdk_vr-5Fdpdk-5Fethdev.c-23L387&d=DwMGaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=flTOx6Av679My7o_iScb5sOlLD68bpUyE2RUtfW3SWQ&m=XSIm84nALkE7O1aeqpJkVJJWzepVsGEJsTeiDCxoLK4&s=L1vEJ5GeVHbammKc0iJn0YdoeKf0GqeeNJy-q5xCi6E&e=>
> 
> 
> 
> 
> In this particular case it is just a workaround for bonding and bnxt.
> Driver name is provided and sufficient to make it possible when
> absolutely required.
> 
> 
> 
> 
> 
> Yes, we need to avoid this kind of design.
> 
> BR,
> Haiyue
> 
> From: Andrew Rybchenko [mailto:arybchenko@solarflare.com]
> Sent: Friday, June 21, 2019 02:30
> To: Wang, Haiyue <haiyue.wang@intel.com><mailto:haiyue.wang@intel.com>; dev@dpdk.org<mailto:dev@dpdk.org>
> Cc: Yigit, Ferruh <ferruh.yigit@intel.com><mailto:ferruh.yigit@intel.com>; Thomas Monjalon <thomas@monjalon.net><mailto:thomas@monjalon.net>
> Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
> 
> CC ethdev maintainers
> 
> On 6/20/19 10:25 AM, Haiyue Wang wrote:
> 
> Generally speaking, the DEV_RX_OFFLOAD_xxx for RX offload capabilities
> 
> of a device is one-bit field definition, it has 64 different values at
> 
> most.
> 
> 
> 
> Nowdays the receiving queue of NIC has rich features not just checksum
> 
> offload, like it can extract the network protocol header fields to its
> 
> RX descriptors for quickly handling. But this kind of feature is not so
> 
> common, and it is hardware related. Normally, this can be done through
> 
> rte_devargs driver parameters, but the scope is per device. This is not
> 
> so nice for per queue design.
> 
> 
> 
> The per queue API 'rte_eth_rx_queue_setup' and data structure 'struct
> 
> rte_eth_rxconf' are stable now, and be common for all PMDs. For keeping
> 
> the ethdev API & ABI compatibility, and the application can make good
> 
> use of the NIC's specific features, reserving the most-significant bits
> 
> of RX offload seems an compromise method.
> 
> 
> 
> Then the PMDs redefine these bits as they want, all PMDs share the same
> 
> bit positions and expose their new definitions with the header file.
> 
> 
> 
> The experimental reserved bits number is 6 currently. Tt can be one-bit
> 
> for each features up to the the maximum number 6. It can also be some
> 
> bits encoding: e.g, 6 bits can stand for 63 maximum number of features.
> 
> 
> 
> We call these reserved bits as DEV_RX_OFFLOAD_PMD_SCRATCH. And the left
> 
> unused bits number is : 64 - 19 (currently defined) - 6 (PMD scartch) =
> 
> 39.
> 
> 
> 
> This is not so nice for applications, they need to check PMD's driver
> 
> name for lookuping their DEV_RX_OFFLOAD_PMD_SCRATCH definitions. But it
> 
> is good for the applications to make use of the hardware compatibility.
> 
> 
> 
> Signed-off-by: Haiyue Wang <haiyue.wang@intel.com><mailto:haiyue.wang@intel.com>
> 
> I would say that it very bad for applications. It sounds like reserved bits
> in registers which have meaning in fact and sometimes different meaning.
> Of course, it is not that bad when rules are defined, but such kind of
> features tend to spread and clutter up interfaces. IMHO, the feature is
> really frightening.

There are two issues. First, having more OFFLOAD capability feature bits
is good. As long as these feature bits are well defined. If only one vendor
implements that feature that is fine. Another vendor can implement the
same thing, and application can know what it is asking for.

The other issue is the limited number of feature bits. I expect that some
time soon the bits will have to grow into an array and cause API/ABI
break. That can be fixed when the last bit is exhausted.




^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
  2019-06-21  7:39  0%         ` Andrew Rybchenko
@ 2019-06-21  7:43  2%           ` Wang, Haiyue
  2019-06-21 15:14  3%             ` Stephen Hemminger
  0 siblings, 1 reply; 200+ results
From: Wang, Haiyue @ 2019-06-21  7:43 UTC (permalink / raw)
  To: Andrew Rybchenko, dev; +Cc: Yigit, Ferruh, Thomas Monjalon

I know my patch is ugly for making customers happy, I will try to find other method not to
break the beautiful rte_ethdev desgin.

Really thanks for your reply. This helps me understand the PMD design practice more.

BR,
Haiyue

From: Andrew Rybchenko [mailto:arybchenko@solarflare.com]
Sent: Friday, June 21, 2019 15:40
To: Wang, Haiyue <haiyue.wang@intel.com>; dev@dpdk.org
Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; Thomas Monjalon <thomas@monjalon.net>
Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch

On 6/21/19 10:37 AM, Wang, Haiyue wrote:
Then this is not so generic if a workaround is needed. In other words, no one is so perfect. ☺

Yes, it is a bug. No one is perfect.



BR,
Haiyue

From: Andrew Rybchenko [mailto:arybchenko@solarflare.com]
Sent: Friday, June 21, 2019 15:34
To: Wang, Haiyue <haiyue.wang@intel.com><mailto:haiyue.wang@intel.com>; dev@dpdk.org<mailto:dev@dpdk.org>
Cc: Yigit, Ferruh <ferruh.yigit@intel.com><mailto:ferruh.yigit@intel.com>; Thomas Monjalon <thomas@monjalon.net><mailto:thomas@monjalon.net>
Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch

On 6/21/19 4:12 AM, Wang, Haiyue wrote:
Not so frightening in real world for an application to be aware of its NICs:
https://github.com/Juniper/contrail-vrouter/blob/master/dpdk/vr_dpdk_ethdev.c#L387<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_Juniper_contrail-2Dvrouter_blob_master_dpdk_vr-5Fdpdk-5Fethdev.c-23L387&d=DwMGaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=flTOx6Av679My7o_iScb5sOlLD68bpUyE2RUtfW3SWQ&m=XSIm84nALkE7O1aeqpJkVJJWzepVsGEJsTeiDCxoLK4&s=L1vEJ5GeVHbammKc0iJn0YdoeKf0GqeeNJy-q5xCi6E&e=>




In this particular case it is just a workaround for bonding and bnxt.
Driver name is provided and sufficient to make it possible when
absolutely required.





Yes, we need to avoid this kind of design.

BR,
Haiyue

From: Andrew Rybchenko [mailto:arybchenko@solarflare.com]
Sent: Friday, June 21, 2019 02:30
To: Wang, Haiyue <haiyue.wang@intel.com><mailto:haiyue.wang@intel.com>; dev@dpdk.org<mailto:dev@dpdk.org>
Cc: Yigit, Ferruh <ferruh.yigit@intel.com><mailto:ferruh.yigit@intel.com>; Thomas Monjalon <thomas@monjalon.net><mailto:thomas@monjalon.net>
Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch

CC ethdev maintainers

On 6/20/19 10:25 AM, Haiyue Wang wrote:

Generally speaking, the DEV_RX_OFFLOAD_xxx for RX offload capabilities

of a device is one-bit field definition, it has 64 different values at

most.



Nowdays the receiving queue of NIC has rich features not just checksum

offload, like it can extract the network protocol header fields to its

RX descriptors for quickly handling. But this kind of feature is not so

common, and it is hardware related. Normally, this can be done through

rte_devargs driver parameters, but the scope is per device. This is not

so nice for per queue design.



The per queue API 'rte_eth_rx_queue_setup' and data structure 'struct

rte_eth_rxconf' are stable now, and be common for all PMDs. For keeping

the ethdev API & ABI compatibility, and the application can make good

use of the NIC's specific features, reserving the most-significant bits

of RX offload seems an compromise method.



Then the PMDs redefine these bits as they want, all PMDs share the same

bit positions and expose their new definitions with the header file.



The experimental reserved bits number is 6 currently. Tt can be one-bit

for each features up to the the maximum number 6. It can also be some

bits encoding: e.g, 6 bits can stand for 63 maximum number of features.



We call these reserved bits as DEV_RX_OFFLOAD_PMD_SCRATCH. And the left

unused bits number is : 64 - 19 (currently defined) - 6 (PMD scartch) =

39.



This is not so nice for applications, they need to check PMD's driver

name for lookuping their DEV_RX_OFFLOAD_PMD_SCRATCH definitions. But it

is good for the applications to make use of the hardware compatibility.



Signed-off-by: Haiyue Wang <haiyue.wang@intel.com><mailto:haiyue.wang@intel.com>

I would say that it very bad for applications. It sounds like reserved bits
in registers which have meaning in fact and sometimes different meaning.
Of course, it is not that bad when rules are defined, but such kind of
features tend to spread and clutter up interfaces. IMHO, the feature is
really frightening.



^ permalink raw reply	[relevance 2%]

* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
  2019-06-21  7:37  3%       ` Wang, Haiyue
@ 2019-06-21  7:39  0%         ` Andrew Rybchenko
  2019-06-21  7:43  2%           ` Wang, Haiyue
  0 siblings, 1 reply; 200+ results
From: Andrew Rybchenko @ 2019-06-21  7:39 UTC (permalink / raw)
  To: Wang, Haiyue, dev; +Cc: Yigit, Ferruh, Thomas Monjalon

On 6/21/19 10:37 AM, Wang, Haiyue wrote:
>
> Then this is not so generic if a workaround is needed. In other words, 
> no one is so perfect. J
>

Yes, it is a bug. No one is perfect.

> BR,
>
> Haiyue
>
> *From:*Andrew Rybchenko [mailto:arybchenko@solarflare.com]
> *Sent:* Friday, June 21, 2019 15:34
> *To:* Wang, Haiyue <haiyue.wang@intel.com>; dev@dpdk.org
> *Cc:* Yigit, Ferruh <ferruh.yigit@intel.com>; Thomas Monjalon 
> <thomas@monjalon.net>
> *Subject:* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload 
> most-significant bits for PMD scartch
>
> On 6/21/19 4:12 AM, Wang, Haiyue wrote:
>
>     Not so frightening in real world for an application to be aware of
>     its NICs:
>
>     https://github.com/Juniper/contrail-vrouter/blob/master/dpdk/vr_dpdk_ethdev.c#L387
>     <https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_Juniper_contrail-2Dvrouter_blob_master_dpdk_vr-5Fdpdk-5Fethdev.c-23L387&d=DwMGaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=flTOx6Av679My7o_iScb5sOlLD68bpUyE2RUtfW3SWQ&m=XSIm84nALkE7O1aeqpJkVJJWzepVsGEJsTeiDCxoLK4&s=L1vEJ5GeVHbammKc0iJn0YdoeKf0GqeeNJy-q5xCi6E&e=>
>
>
>
>
> In this particular case it is just a workaround for bonding and bnxt.
> Driver name is provided and sufficient to make it possible when
> absolutely required.
>
>
>
>     Yes, we need to avoid this kind of design.
>
>     BR,
>
>     Haiyue
>
>     *From:*Andrew Rybchenko [mailto:arybchenko@solarflare.com]
>     *Sent:* Friday, June 21, 2019 02:30
>     *To:* Wang, Haiyue <haiyue.wang@intel.com>
>     <mailto:haiyue.wang@intel.com>; dev@dpdk.org <mailto:dev@dpdk.org>
>     *Cc:* Yigit, Ferruh <ferruh.yigit@intel.com>
>     <mailto:ferruh.yigit@intel.com>; Thomas Monjalon
>     <thomas@monjalon.net> <mailto:thomas@monjalon.net>
>     *Subject:* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload
>     most-significant bits for PMD scartch
>
>     CC ethdev maintainers
>
>     On 6/20/19 10:25 AM, Haiyue Wang wrote:
>
>         Generally speaking, the DEV_RX_OFFLOAD_xxx for RX offload capabilities
>
>         of a device is one-bit field definition, it has 64 different values at
>
>         most.
>
>           
>
>         Nowdays the receiving queue of NIC has rich features not just checksum
>
>         offload, like it can extract the network protocol header fields to its
>
>         RX descriptors for quickly handling. But this kind of feature is not so
>
>         common, and it is hardware related. Normally, this can be done through
>
>         rte_devargs driver parameters, but the scope is per device. This is not
>
>         so nice for per queue design.
>
>           
>
>         The per queue API 'rte_eth_rx_queue_setup' and data structure 'struct
>
>         rte_eth_rxconf' are stable now, and be common for all PMDs. For keeping
>
>         the ethdev API & ABI compatibility, and the application can make good
>
>         use of the NIC's specific features, reserving the most-significant bits
>
>         of RX offload seems an compromise method.
>
>           
>
>         Then the PMDs redefine these bits as they want, all PMDs share the same
>
>         bit positions and expose their new definitions with the header file.
>
>           
>
>         The experimental reserved bits number is 6 currently. Tt can be one-bit
>
>         for each features up to the the maximum number 6. It can also be some
>
>         bits encoding: e.g, 6 bits can stand for 63 maximum number of features.
>
>           
>
>         We call these reserved bits as DEV_RX_OFFLOAD_PMD_SCRATCH. And the left
>
>         unused bits number is : 64 - 19 (currently defined) - 6 (PMD scartch) =
>
>         39.
>
>           
>
>         This is not so nice for applications, they need to check PMD's driver
>
>         name for lookuping their DEV_RX_OFFLOAD_PMD_SCRATCH definitions. But it
>
>         is good for the applications to make use of the hardware compatibility.
>
>           
>
>         Signed-off-by: Haiyue Wang<haiyue.wang@intel.com>  <mailto:haiyue.wang@intel.com>
>
>
>     I would say that it very bad for applications. It sounds like
>     reserved bits
>     in registers which have meaning in fact and sometimes different
>     meaning.
>     Of course, it is not that bad when rules are defined, but such kind of
>     features tend to spread and clutter up interfaces. IMHO, the
>     feature is
>     really frightening.
>


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
  2019-06-21  7:33  0%     ` Andrew Rybchenko
@ 2019-06-21  7:37  3%       ` Wang, Haiyue
  2019-06-21  7:39  0%         ` Andrew Rybchenko
  0 siblings, 1 reply; 200+ results
From: Wang, Haiyue @ 2019-06-21  7:37 UTC (permalink / raw)
  To: Andrew Rybchenko, dev; +Cc: Yigit, Ferruh, Thomas Monjalon

Then this is not so generic if a workaround is needed. In other words, no one is so perfect. ☺

BR,
Haiyue

From: Andrew Rybchenko [mailto:arybchenko@solarflare.com]
Sent: Friday, June 21, 2019 15:34
To: Wang, Haiyue <haiyue.wang@intel.com>; dev@dpdk.org
Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; Thomas Monjalon <thomas@monjalon.net>
Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch

On 6/21/19 4:12 AM, Wang, Haiyue wrote:
Not so frightening in real world for an application to be aware of its NICs:
https://github.com/Juniper/contrail-vrouter/blob/master/dpdk/vr_dpdk_ethdev.c#L387<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_Juniper_contrail-2Dvrouter_blob_master_dpdk_vr-5Fdpdk-5Fethdev.c-23L387&d=DwMGaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=flTOx6Av679My7o_iScb5sOlLD68bpUyE2RUtfW3SWQ&m=XSIm84nALkE7O1aeqpJkVJJWzepVsGEJsTeiDCxoLK4&s=L1vEJ5GeVHbammKc0iJn0YdoeKf0GqeeNJy-q5xCi6E&e=>



In this particular case it is just a workaround for bonding and bnxt.
Driver name is provided and sufficient to make it possible when
absolutely required.



Yes, we need to avoid this kind of design.

BR,
Haiyue

From: Andrew Rybchenko [mailto:arybchenko@solarflare.com]
Sent: Friday, June 21, 2019 02:30
To: Wang, Haiyue <haiyue.wang@intel.com><mailto:haiyue.wang@intel.com>; dev@dpdk.org<mailto:dev@dpdk.org>
Cc: Yigit, Ferruh <ferruh.yigit@intel.com><mailto:ferruh.yigit@intel.com>; Thomas Monjalon <thomas@monjalon.net><mailto:thomas@monjalon.net>
Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch

CC ethdev maintainers

On 6/20/19 10:25 AM, Haiyue Wang wrote:

Generally speaking, the DEV_RX_OFFLOAD_xxx for RX offload capabilities

of a device is one-bit field definition, it has 64 different values at

most.



Nowdays the receiving queue of NIC has rich features not just checksum

offload, like it can extract the network protocol header fields to its

RX descriptors for quickly handling. But this kind of feature is not so

common, and it is hardware related. Normally, this can be done through

rte_devargs driver parameters, but the scope is per device. This is not

so nice for per queue design.



The per queue API 'rte_eth_rx_queue_setup' and data structure 'struct

rte_eth_rxconf' are stable now, and be common for all PMDs. For keeping

the ethdev API & ABI compatibility, and the application can make good

use of the NIC's specific features, reserving the most-significant bits

of RX offload seems an compromise method.



Then the PMDs redefine these bits as they want, all PMDs share the same

bit positions and expose their new definitions with the header file.



The experimental reserved bits number is 6 currently. Tt can be one-bit

for each features up to the the maximum number 6. It can also be some

bits encoding: e.g, 6 bits can stand for 63 maximum number of features.



We call these reserved bits as DEV_RX_OFFLOAD_PMD_SCRATCH. And the left

unused bits number is : 64 - 19 (currently defined) - 6 (PMD scartch) =

39.



This is not so nice for applications, they need to check PMD's driver

name for lookuping their DEV_RX_OFFLOAD_PMD_SCRATCH definitions. But it

is good for the applications to make use of the hardware compatibility.



Signed-off-by: Haiyue Wang <haiyue.wang@intel.com><mailto:haiyue.wang@intel.com>

I would say that it very bad for applications. It sounds like reserved bits
in registers which have meaning in fact and sometimes different meaning.
Of course, it is not that bad when rules are defined, but such kind of
features tend to spread and clutter up interfaces. IMHO, the feature is
really frightening.


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
  2019-06-21  1:12  3%   ` Wang, Haiyue
@ 2019-06-21  7:33  0%     ` Andrew Rybchenko
  2019-06-21  7:37  3%       ` Wang, Haiyue
  0 siblings, 1 reply; 200+ results
From: Andrew Rybchenko @ 2019-06-21  7:33 UTC (permalink / raw)
  To: Wang, Haiyue, dev; +Cc: Yigit, Ferruh, Thomas Monjalon

On 6/21/19 4:12 AM, Wang, Haiyue wrote:
>
> Not so frightening in real world for an application to be aware of its 
> NICs:
>
> https://github.com/Juniper/contrail-vrouter/blob/master/dpdk/vr_dpdk_ethdev.c#L387 
> <https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_Juniper_contrail-2Dvrouter_blob_master_dpdk_vr-5Fdpdk-5Fethdev.c-23L387&d=DwMGaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=flTOx6Av679My7o_iScb5sOlLD68bpUyE2RUtfW3SWQ&m=XSIm84nALkE7O1aeqpJkVJJWzepVsGEJsTeiDCxoLK4&s=L1vEJ5GeVHbammKc0iJn0YdoeKf0GqeeNJy-q5xCi6E&e=>
>
>

In this particular case it is just a workaround for bonding and bnxt.
Driver name is provided and sufficient to make it possible when
absolutely required.

> Yes, we need to avoid this kind of design.
>
> BR,
>
> Haiyue
>
> *From:*Andrew Rybchenko [mailto:arybchenko@solarflare.com]
> *Sent:* Friday, June 21, 2019 02:30
> *To:* Wang, Haiyue <haiyue.wang@intel.com>; dev@dpdk.org
> *Cc:* Yigit, Ferruh <ferruh.yigit@intel.com>; Thomas Monjalon 
> <thomas@monjalon.net>
> *Subject:* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload 
> most-significant bits for PMD scartch
>
> CC ethdev maintainers
>
> On 6/20/19 10:25 AM, Haiyue Wang wrote:
>
>     Generally speaking, the DEV_RX_OFFLOAD_xxx for RX offload capabilities
>
>     of a device is one-bit field definition, it has 64 different values at
>
>     most.
>
>     Nowdays the receiving queue of NIC has rich features not just checksum
>
>     offload, like it can extract the network protocol header fields to its
>
>     RX descriptors for quickly handling. But this kind of feature is not so
>
>     common, and it is hardware related. Normally, this can be done through
>
>     rte_devargs driver parameters, but the scope is per device. This is not
>
>     so nice for per queue design.
>
>     The per queue API 'rte_eth_rx_queue_setup' and data structure 'struct
>
>     rte_eth_rxconf' are stable now, and be common for all PMDs. For keeping
>
>     the ethdev API & ABI compatibility, and the application can make good
>
>     use of the NIC's specific features, reserving the most-significant bits
>
>     of RX offload seems an compromise method.
>
>     Then the PMDs redefine these bits as they want, all PMDs share the same
>
>     bit positions and expose their new definitions with the header file.
>
>     The experimental reserved bits number is 6 currently. Tt can be one-bit
>
>     for each features up to the the maximum number 6. It can also be some
>
>     bits encoding: e.g, 6 bits can stand for 63 maximum number of features.
>
>     We call these reserved bits as DEV_RX_OFFLOAD_PMD_SCRATCH. And the left
>
>     unused bits number is : 64 - 19 (currently defined) - 6 (PMD scartch) =
>
>     39.
>
>     This is not so nice for applications, they need to check PMD's driver
>
>     name for lookuping their DEV_RX_OFFLOAD_PMD_SCRATCH definitions. But it
>
>     is good for the applications to make use of the hardware compatibility.
>
>     Signed-off-by: Haiyue Wang<haiyue.wang@intel.com>  <mailto:haiyue.wang@intel.com>
>
>
> I would say that it very bad for applications. It sounds like reserved 
> bits
> in registers which have meaning in fact and sometimes different meaning.
> Of course, it is not that bad when rules are defined, but such kind of
> features tend to spread and clutter up interfaces. IMHO, the feature is
> really frightening.
>


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
  2019-06-20 18:30  0% ` Andrew Rybchenko
@ 2019-06-21  1:12  3%   ` Wang, Haiyue
  2019-06-21  7:33  0%     ` Andrew Rybchenko
  0 siblings, 1 reply; 200+ results
From: Wang, Haiyue @ 2019-06-21  1:12 UTC (permalink / raw)
  To: Andrew Rybchenko, dev; +Cc: Yigit, Ferruh, Thomas Monjalon

Not so frightening in real world for an application to be aware of its NICs:
https://github.com/Juniper/contrail-vrouter/blob/master/dpdk/vr_dpdk_ethdev.c#L387

Yes, we need to avoid this kind of design.

BR,
Haiyue

From: Andrew Rybchenko [mailto:arybchenko@solarflare.com]
Sent: Friday, June 21, 2019 02:30
To: Wang, Haiyue <haiyue.wang@intel.com>; dev@dpdk.org
Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; Thomas Monjalon <thomas@monjalon.net>
Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch

CC ethdev maintainers

On 6/20/19 10:25 AM, Haiyue Wang wrote:

Generally speaking, the DEV_RX_OFFLOAD_xxx for RX offload capabilities

of a device is one-bit field definition, it has 64 different values at

most.



Nowdays the receiving queue of NIC has rich features not just checksum

offload, like it can extract the network protocol header fields to its

RX descriptors for quickly handling. But this kind of feature is not so

common, and it is hardware related. Normally, this can be done through

rte_devargs driver parameters, but the scope is per device. This is not

so nice for per queue design.



The per queue API 'rte_eth_rx_queue_setup' and data structure 'struct

rte_eth_rxconf' are stable now, and be common for all PMDs. For keeping

the ethdev API & ABI compatibility, and the application can make good

use of the NIC's specific features, reserving the most-significant bits

of RX offload seems an compromise method.



Then the PMDs redefine these bits as they want, all PMDs share the same

bit positions and expose their new definitions with the header file.



The experimental reserved bits number is 6 currently. Tt can be one-bit

for each features up to the the maximum number 6. It can also be some

bits encoding: e.g, 6 bits can stand for 63 maximum number of features.



We call these reserved bits as DEV_RX_OFFLOAD_PMD_SCRATCH. And the left

unused bits number is : 64 - 19 (currently defined) - 6 (PMD scartch) =

39.



This is not so nice for applications, they need to check PMD's driver

name for lookuping their DEV_RX_OFFLOAD_PMD_SCRATCH definitions. But it

is good for the applications to make use of the hardware compatibility.



Signed-off-by: Haiyue Wang <haiyue.wang@intel.com><mailto:haiyue.wang@intel.com>

I would say that it very bad for applications. It sounds like reserved bits
in registers which have meaning in fact and sometimes different meaning.
Of course, it is not that bad when rules are defined, but such kind of
features tend to spread and clutter up interfaces. IMHO, the feature is
really frightening.

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
  2019-06-20 18:35  0% ` Stephen Hemminger
@ 2019-06-21  0:55  0%   ` Wang, Haiyue
  0 siblings, 0 replies; 200+ results
From: Wang, Haiyue @ 2019-06-21  0:55 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

Hi

> -----Original Message-----
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Friday, June 21, 2019 02:36
> To: Wang, Haiyue <haiyue.wang@intel.com>
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
> 
> On Thu, 20 Jun 2019 15:25:52 +0800
> Haiyue Wang <haiyue.wang@intel.com> wrote:
> 
> > Generally speaking, the DEV_RX_OFFLOAD_xxx for RX offload capabilities
> > of a device is one-bit field definition, it has 64 different values at
> > most.
> >
> > Nowdays the receiving queue of NIC has rich features not just checksum
> > offload, like it can extract the network protocol header fields to its
> > RX descriptors for quickly handling. But this kind of feature is not so
> > common, and it is hardware related. Normally, this can be done through
> > rte_devargs driver parameters, but the scope is per device. This is not
> > so nice for per queue design.
> >
> > The per queue API 'rte_eth_rx_queue_setup' and data structure 'struct
> > rte_eth_rxconf' are stable now, and be common for all PMDs. For keeping
> > the ethdev API & ABI compatibility, and the application can make good
> > use of the NIC's specific features, reserving the most-significant bits
> > of RX offload seems an compromise method.
> >
> > Then the PMDs redefine these bits as they want, all PMDs share the same
> > bit positions and expose their new definitions with the header file.
> >
> > The experimental reserved bits number is 6 currently. Tt can be one-bit
> > for each features up to the the maximum number 6. It can also be some
> > bits encoding: e.g, 6 bits can stand for 63 maximum number of features.
> >
> > We call these reserved bits as DEV_RX_OFFLOAD_PMD_SCRATCH. And the left
> > unused bits number is : 64 - 19 (currently defined) - 6 (PMD scartch) =
> > 39.
> >
> > This is not so nice for applications, they need to check PMD's driver
> > name for lookuping their DEV_RX_OFFLOAD_PMD_SCRATCH definitions. But it
> > is good for the applications to make use of the hardware compatibility.
> >
> > Signed-off-by: Haiyue Wang <haiyue.wang@intel.com>
> > ---
> 
> Anything that is per device type is useless for a generic application.
> The goal of the DPDK should be to provide a high performance platform
> that works for many device types. Too often, I see patches from hardware
> vendors that are just "we can enable are cool proprietary hardware
> feature in DPDK". This would just encourage that bad practice.

Understand the DPDK's dream. :) This patch wants to make the bad application
and bad vender to use the DPDK's generic high performance platform features,
plus some bad practice like doing special hardware optimization.

Very appreciate your feedback. The PMDs should limit their desires. ;-)



^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 00/28] vhost: add virtio-vhost-user transport
  2019-06-20 11:32  3%   ` [dpdk-dev] [PATCH 00/28] vhost: add virtio-vhost-user transport Ilya Maximets
@ 2019-06-20 23:44  0%     ` Nikos Dragazis
  0 siblings, 0 replies; 200+ results
From: Nikos Dragazis @ 2019-06-20 23:44 UTC (permalink / raw)
  To: Ilya Maximets
  Cc: dev, Maxime Coquelin, Tiwei Bie, Zhihong Wang, Stefan Hajnoczi,
	Wei Wang, Stojaczyk Dariusz, Vangelis Koukis

On 20/6/19 2:32 μ.μ., Ilya Maximets wrote:
> On 19.06.2019 18:14, Nikos Dragazis wrote:
>> Hi everyone,
> Hi. I didn't look at the code, just a few comments inline.
>
>> this patch series introduces the concept of the virtio-vhost-user
>> transport. This is actually a revised version of an earlier RFC
>> implementation that has been proposed by Stefan Hajnoczi [1]. Though
>> this is a great feature, it seems to have been stalled, so I’d like to
>> restart the conversation on this and hopefully get it merged with your
>> help. Let me give you an overview.
>>
>> The virtio-vhost-user transport is a vhost-user transport implementation
>> that is based on the virtio-vhost-user device. Its key difference with
>> the existing transport is that it allows deploying vhost-user targets
>> inside dedicated Storage Appliance VMs instead of host user space. In
>> other words, it allows having guests that act as vhost-user backends for
>> other guests.
>>
>> The virtio-vhost-user device implements the vhost-user control plane
>> (master-slave communication) as follows:
>>
>> 1. it parses the vhost-user messages from the vhost-user unix domain
>>    socket and forwards them to the slave guest through virtqueues
>>
>> 2. it maps the vhost memory regions in QEMU’s process address space and
>>    exposes them to the slave guest as a RAM-backed PCI MMIO region
>>
>> 3. it hooks up doorbells to the callfds. The slave guest can use these
>>    doorbells to interrupt the master guest driver
>>
>> The device code has not yet been merged into upstream QEMU, but this is
>> definitely the end goal. The current state is that we are awaiting for
>> the approval of the virtio spec.
>>
>> I have Cced Darek from the SPDK community who has helped me a lot by
>> reviewing this series. Note that any device type could be implemented
>> over this new transport. So, adding the virtio-vhost-user transport in
>> DPDK would allow using it from SPDK as well.
>>
>> Getting into the code internals, this patch series makes the following
>> changes:
>>
>> 1. introduce a generic interface for the transport-specific operations.
>>    Each of the two available transports, the pre-existing AF_UNIX
>>    transport and the virtio-vhost-user transport, is going to implement
>>    this interface. The AF_UNIX-specific code has been extracted from the
>>    core vhost-user code and is now part of the AF_UNIX transport
>>    implementation in trans_af_unix.c.
>>
>> 2. introduce the virtio-vhost-user transport. The virtio-vhost-user
>>    transport requires a driver for the virtio-vhost-user devices. The
>>    driver along with the transport implementation have been packed into
>>    a separate library in `drivers/virtio_vhost_user/`. The necessary
>>    virtio-pci code has been copied from `drivers/net/virtio/`. Some
>>    additional changes have been made so that the driver can utilize the
>>    additional resources of the virtio-vhost-user device.
>>
>> 3. update librte_vhost public API to enable choosing transport for each
>>    new vhost device. Extend the vhost net driver and vhost-scsi example
>>    application to export this new API to the end user.
>>
>> The primary changes I did to Stefan’s RFC implementation are the
>> following:
>>
>> 1. moved postcopy live migration code into trans_af_unix.c. Postcopy
>>    live migration relies on the userfault fd mechanism, which cannot be
>>    supported by virtio-vhost-user.
>>
>> 2. moved setup of the log memory region into trans_af_unix.c. Setting up
>>    the log memory region involves mapping/unmapping guest memory. This
>>    is an AF_UNIX transport-specific operation.
> Logging dirty pages is the main concept of live migration support. Does it
> mean that the live migration is not supported for virtio-vhost-user at all?

No, it is supported. To be more precise, it can be supported, it is part
of the on-going virtio device specification:

https://lists.oasis-open.org/archives/virtio-dev/201905/msg00022.html

and it is in my TODO list for the device code. Here is how it works:

the log memory region, just like the other vhost memory regions, is a
portion of the master guest memory. In case of the AF_UNIX transport,
the master sends a VHOST_USER_SET_LOG_BASE message and the vhost target
mmaps the log memory region into the process' virtual address space. In
case of the virtio-vhost-user transport, the virtio-vhost-user device
parses the VHOST_USER_SET_LOG_BASE message and maps the log memory
region into QEMU's process address space. It then exposes the log memory
region to the slave guest as a RAM-backed PCI MMIO region.

So, from the vhost target's viewpoint, the only difference is the means
of accessing the log memory region. In case of the AF_UNIX transport,
the vhost target receives a file descriptor and mmaps this file. In case
of the virtio-vhost-user transport, the device exports the log memory
region to the vhost target (running in slave guest user space) via an
MMIO BAR.

To recap, just to make sure it is clear, the virtio-vhost-user transport
does support precopy live migration, but it doesn't support postcopy
live migration.

>
>> 3. introduced a vhost transport operation for
>>    process_slave_message_reply()
>>
>> 4. moved the virtio-vhost-user transport/driver into a separate library
>>    in `drivers/virtio_vhost_user/`. This required making vhost.h and
>>    vhost_user.h part of librte_vhost public API and exporting some
>>    private symbols via the version script. This looks better to me that
>>    just moving the entire librte_vhost into `drivers/`. I am not sure if
>>    this is the most appropriate solution. I am looking forward to your
>>    suggestions on this.
> Moving the virtio-vhost-user code to a separate driver looks strange for me.
> What is the purpose?

The virtio-vhost-user transport is based on the virtio-vhost-user
device. This means that we need a user space driver for this device
type.  Currently, the driver and the transport implementation are packed
together into `trans_virtio_vhost_user.c`. There are 2 reasons why I
moved all the virtio-vhost-user code (driver + transport implementation)
into `drivers/`:

1. my understanding is that all drivers should be located in `drivers/`.

2. |the driver depends on `rte_bus_pci.h` which gets exported when
   `drivers/` is built whereas librte_vhost is built before `drivers/`.
   However, I think this could be overcomed by just adding this line:

   CFLAGS += -I$(RTE_SDK)/drivers/bus/pci

   in librte_vhost Makefile.||


|
>
> Exporting a lot of vhost internal structures will lead to a frequent API/ABI
> breakages and will slow down accepting changes to releases in general.

I understand that there are many parameters that we have to consider. My
implementation is just a proposal.  I am looking forward to hearing from
you and the community any other suggestions on this.

>
> It looks inconsistent to have 'trans_af_unix.c' in 'lib/librte_vhost/' and
> 'trans_virtio_vhost_user.c' in 'drivers/virtio_vhost_user/' because these
> files should be similar in provided functionality, hence, should be located
> in similar places.

I agree. Actually, I was thinking about separating the driver from the
transport implementation and moving just the driver into `drivers/`. But
this would require exporting some low-level virtio PCI functions. And
this didn't look appropriate to me.

>
>> 5. made use of the virtio PCI capabilities for the additional device
>>    resources (doorbells, shared memory). This required changes in
>>    virtio_pci.c and trans_virtio_vhost_user.c.
>>
>> 6. [minor] changed some commit headlines to comply with
>>    check-git-log.sh.
>>
>> Please, have a look and let me know about your thoughts. Any
>> reviews/pointers/suggestions are welcome.
>>
>> Best regards,
>> Nikos
>>
>> [1] http://mails.dpdk.org/archives/dev/2018-January/088155.html
>>
>>
>> Nikos Dragazis (23):
>>   vhost: introduce vhost transport operations structure
>>   vhost: move socket management code
>>   vhost: move socket fd and un sockaddr
>>   vhost: move vhost-user connection
>>   vhost: move vhost-user reconnection
>>   vhost: move vhost-user fdset
>>   vhost: propagate vhost transport operations
>>   vhost: use a single structure for the device state
>>   vhost: extract socket I/O into transport
>>   vhost: move slave request fd and lock
>>   vhost: move mmap/munmap
>>   vhost: move setup of the log memory region
>>   vhost: remove main fd parameter from msg handlers
>>   vhost: move postcopy live migration code
>>   vhost: support registering additional vhost-user transports
>>   drivers/virtio_vhost_user: add virtio PCI framework
>>   drivers: add virtio-vhost-user transport
>>   drivers/virtio_vhost_user: use additional device resources
>>   vhost: add flag for choosing vhost-user transport
>>   net/vhost: add virtio-vhost-user support
>>   mk: link apps with virtio-vhost-user driver
>>   config: add option for the virtio-vhost-user transport
>>   usertools: add virtio-vhost-user devices to dpdk-devbind.py
>>
>> Stefan Hajnoczi (5):
>>   vhost: allocate per-socket transport state
>>   vhost: move start server/client calls
>>   vhost: add index field in vhost virtqueues
>>   examples/vhost_scsi: add --socket-file argument
>>   examples/vhost_scsi: add virtio-vhost-user support
>>
>>  config/common_base                                 |    6 +
>>  config/common_linux                                |    1 +
>>  drivers/Makefile                                   |    5 +
>>  drivers/net/vhost/rte_eth_vhost.c                  |   13 +
>>  drivers/virtio_vhost_user/Makefile                 |   27 +
>>  .../rte_virtio_vhost_user_version.map              |    4 +
>>  .../virtio_vhost_user/trans_virtio_vhost_user.c    | 1077 +++++++++++++++++++
>>  drivers/virtio_vhost_user/virtio_pci.c             |  520 ++++++++++
>>  drivers/virtio_vhost_user/virtio_pci.h             |  289 ++++++
>>  drivers/virtio_vhost_user/virtio_vhost_user.h      |   18 +
>>  drivers/virtio_vhost_user/virtqueue.h              |  181 ++++
>>  examples/vhost_scsi/vhost_scsi.c                   |  103 +-
>>  lib/librte_vhost/Makefile                          |    4 +-
>>  lib/librte_vhost/rte_vhost.h                       |    1 +
>>  lib/librte_vhost/rte_vhost_version.map             |   11 +
>>  lib/librte_vhost/socket.c                          |  685 +-----------
>>  lib/librte_vhost/trans_af_unix.c                   | 1094 ++++++++++++++++++++
>>  lib/librte_vhost/vhost.c                           |   22 +-
>>  lib/librte_vhost/vhost.h                           |  298 +++++-
>>  lib/librte_vhost/vhost_user.c                      |  474 ++-------
>>  lib/librte_vhost/vhost_user.h                      |   10 +-
>>  mk/rte.app.mk                                      |    6 +
>>  usertools/dpdk-devbind.py                          |    7 +
>>  23 files changed, 3764 insertions(+), 1092 deletions(-)
>>  create mode 100644 drivers/virtio_vhost_user/Makefile
>>  create mode 100644 drivers/virtio_vhost_user/rte_virtio_vhost_user_version.map
>>  create mode 100644 drivers/virtio_vhost_user/trans_virtio_vhost_user.c
>>  create mode 100644 drivers/virtio_vhost_user/virtio_pci.c
>>  create mode 100644 drivers/virtio_vhost_user/virtio_pci.h
>>  create mode 100644 drivers/virtio_vhost_user/virtio_vhost_user.h
>>  create mode 100644 drivers/virtio_vhost_user/virtqueue.h
>>  create mode 100644 lib/librte_vhost/trans_af_unix.c
>>


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
  2019-06-20  7:25  2% [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch Haiyue Wang
  2019-06-20 18:30  0% ` Andrew Rybchenko
@ 2019-06-20 18:35  0% ` Stephen Hemminger
  2019-06-21  0:55  0%   ` Wang, Haiyue
  1 sibling, 1 reply; 200+ results
From: Stephen Hemminger @ 2019-06-20 18:35 UTC (permalink / raw)
  To: Haiyue Wang; +Cc: dev

On Thu, 20 Jun 2019 15:25:52 +0800
Haiyue Wang <haiyue.wang@intel.com> wrote:

> Generally speaking, the DEV_RX_OFFLOAD_xxx for RX offload capabilities
> of a device is one-bit field definition, it has 64 different values at
> most.
> 
> Nowdays the receiving queue of NIC has rich features not just checksum
> offload, like it can extract the network protocol header fields to its
> RX descriptors for quickly handling. But this kind of feature is not so
> common, and it is hardware related. Normally, this can be done through
> rte_devargs driver parameters, but the scope is per device. This is not
> so nice for per queue design.
> 
> The per queue API 'rte_eth_rx_queue_setup' and data structure 'struct
> rte_eth_rxconf' are stable now, and be common for all PMDs. For keeping
> the ethdev API & ABI compatibility, and the application can make good
> use of the NIC's specific features, reserving the most-significant bits
> of RX offload seems an compromise method.
> 
> Then the PMDs redefine these bits as they want, all PMDs share the same
> bit positions and expose their new definitions with the header file.
> 
> The experimental reserved bits number is 6 currently. Tt can be one-bit
> for each features up to the the maximum number 6. It can also be some
> bits encoding: e.g, 6 bits can stand for 63 maximum number of features.
> 
> We call these reserved bits as DEV_RX_OFFLOAD_PMD_SCRATCH. And the left
> unused bits number is : 64 - 19 (currently defined) - 6 (PMD scartch) =
> 39.
> 
> This is not so nice for applications, they need to check PMD's driver
> name for lookuping their DEV_RX_OFFLOAD_PMD_SCRATCH definitions. But it
> is good for the applications to make use of the hardware compatibility.
> 
> Signed-off-by: Haiyue Wang <haiyue.wang@intel.com>
> ---

Anything that is per device type is useless for a generic application.
The goal of the DPDK should be to provide a high performance platform
that works for many device types. Too often, I see patches from hardware
vendors that are just "we can enable are cool proprietary hardware
feature in DPDK". This would just encourage that bad practice.

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
  2019-06-20  7:25  2% [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch Haiyue Wang
@ 2019-06-20 18:30  0% ` Andrew Rybchenko
  2019-06-21  1:12  3%   ` Wang, Haiyue
  2019-06-20 18:35  0% ` Stephen Hemminger
  1 sibling, 1 reply; 200+ results
From: Andrew Rybchenko @ 2019-06-20 18:30 UTC (permalink / raw)
  To: Haiyue Wang, dev; +Cc: Ferruh Yigit, Thomas Monjalon

CC ethdev maintainers

On 6/20/19 10:25 AM, Haiyue Wang wrote:
> Generally speaking, the DEV_RX_OFFLOAD_xxx for RX offload capabilities
> of a device is one-bit field definition, it has 64 different values at
> most.
>
> Nowdays the receiving queue of NIC has rich features not just checksum
> offload, like it can extract the network protocol header fields to its
> RX descriptors for quickly handling. But this kind of feature is not so
> common, and it is hardware related. Normally, this can be done through
> rte_devargs driver parameters, but the scope is per device. This is not
> so nice for per queue design.
>
> The per queue API 'rte_eth_rx_queue_setup' and data structure 'struct
> rte_eth_rxconf' are stable now, and be common for all PMDs. For keeping
> the ethdev API & ABI compatibility, and the application can make good
> use of the NIC's specific features, reserving the most-significant bits
> of RX offload seems an compromise method.
>
> Then the PMDs redefine these bits as they want, all PMDs share the same
> bit positions and expose their new definitions with the header file.
>
> The experimental reserved bits number is 6 currently. Tt can be one-bit
> for each features up to the the maximum number 6. It can also be some
> bits encoding: e.g, 6 bits can stand for 63 maximum number of features.
>
> We call these reserved bits as DEV_RX_OFFLOAD_PMD_SCRATCH. And the left
> unused bits number is : 64 - 19 (currently defined) - 6 (PMD scartch) =
> 39.
>
> This is not so nice for applications, they need to check PMD's driver
> name for lookuping their DEV_RX_OFFLOAD_PMD_SCRATCH definitions. But it
> is good for the applications to make use of the hardware compatibility.
>
> Signed-off-by: Haiyue Wang <haiyue.wang@intel.com>

I would say that it very bad for applications. It sounds like reserved bits
in registers which have meaning in fact and sometimes different meaning.
Of course, it is not that bad when rules are defined, but such kind of
features tend to spread and clutter up interfaces. IMHO, the feature is
really frightening.


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] eal: resort symbols in EXPERIMENTAL section
  2019-06-14 15:32  0%     ` Ferruh Yigit
@ 2019-06-20 17:23  0%       ` David Marchand
  0 siblings, 0 replies; 200+ results
From: David Marchand @ 2019-06-20 17:23 UTC (permalink / raw)
  To: Ferruh Yigit, Thomas Monjalon; +Cc: Stephen Hemminger, dev

On Fri, Jun 14, 2019 at 5:32 PM Ferruh Yigit <ferruh.yigit@intel.com> wrote:

> On 6/14/2019 8:44 AM, David Marchand wrote:
> > On Fri, Jun 14, 2019 at 9:39 AM Thomas Monjalon <thomas@monjalon.net>
> wrote:
> >
> >> 06/04/2019 05:30, Stephen Hemminger:
> >>> The symbols in the EXPERIMENTAL were close to alphabetic
> >>> order but running sort showed several mistakes.
> >>>
> >>> This has no impact on code, API, ABI or otherwise.
> >>> Purely for humans.
> >>>
> >>> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> >>
> >> I don't think it's worth adding a layer of git history for this sort.
> >> I would prefer to leave it as is.
> >>
> >>
> > If this is about preferrence, I would prefer we have those symbols sorted
> > per versions that introduced them ;-).
> > Much easier to check and see if they are candidates for entering stable
> ABI.
> >
>
> Not bad idea, +1 from my side J
>

Here is what it looks like:
https://github.com/david-marchand/dpdk/commit/cab0d75ea6bdc7782566d7aad6718b9f5fa784f7

Comments?


-- 
David Marchand

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [dpdk-announce] DPDK 18.11.2 (LTS) released
  2019-06-11 18:42  1% [dpdk-dev] [dpdk-announce] DPDK 18.11.2 (LTS) released Kevin Traynor
@ 2019-06-20 17:07  1% ` Ju-Hyoung Lee
  0 siblings, 0 replies; 200+ results
From: Ju-Hyoung Lee @ 2019-06-20 17:07 UTC (permalink / raw)
  To: Kevin Traynor, dev
  Cc: Stephen Hemminger, Luca Boccassi, Josh Poulson,
	Adrian Vladu (Cloudbase Solutions SRL),
	Ju-Hyoung Lee

Hello,

DPDK https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.dpdk.org%2Fdpdk-stable%2Fsnapshot%2Fdpdk-stable-v18.11.2.tar.gz&amp;data=02%7C01%7Cv-advlad%40microsoft.com%7Cf25bf3676935492f47a908d6f586fbdf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636966357449547606&amp;sdata=3Vkt83IWYWEP18ocYyroCPYxNsxLJI18SPZPNLNHjYI%3D&amp;reserved=0,  was validated on Azure for Canonical UbuntuServer 16.04-LTS latest, Canonical UbuntuServer 18.04-DAILY-LTS latest, RedHat RHEL 7-RAW latest, RedHat RHEL 7.5 latest, Openlogic CentOS 7.5 latest, SUSE SLES 15 latest.
Tested with Mellanox and netvsc poll-mode drivers.
The tests were executed using LISAv2 framework (https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FLIS%2FLISAv2&amp;data=02%7C01%7Cv-advlad%40microsoft.com%7Cf25bf3676935492f47a908d6f586fbdf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636966357449557602&amp;sdata=Ape9pbmocU5cMltRKDmJZCZJXIQOwvoo1HCMY8bVb0M%3D&amp;reserved=0).

NOTE: some tests below 'Failed' are not related to DPDK issue, but host did not bring up VF interface.

Test case description:

* VERIFY-DPDK-COMPLIANCE - verifies kernel is supported and that the build is successful
* VERIFY-DPDK-BUILD-AND-TESTPMD-TEST - verifies using testpmd that packets can be sent from a VM to another VM
* VERIFY-DPDK-OVS - builds OVS with DPDK support and tests if the OVS DPDK ports can be created (only on Ubuntu)
* VERIFY-SRIOV-FAILSAFE-FOR-DPDK - disables/enables Accelerated Networking for the NICs under test and makes sure DPDK works in both scenarios
* VERIFY-DPDK-FAILSAFE-DURING-TRAFFIC - disables/enables Accelerated Networking for the NICs while generating traffic using testpmd
* PERF-DPDK-FWD-PPS-DS15 - verifies DPDK forwarding performance using testpmd on 2, 4, 8 cores, rx and io mode on size Standard_DS15_v2
* PERF-DPDK-SINGLE-CORE-PPS-DS4 - verifies DPDK performance using testpmd on 1 core, rx and io mode on size Standard_DS4_v2
* PERF-DPDK-SINGLE-CORE-PPS-DS15 - verifies DPDK performance using testpmd on 1 core, rx and io mode on size Standard_DS15_v2
* PERF-DPDK-MULTICORE-PPS-DS15 - verifies DPDK performance using testpmd on 2, 4, 8 cores, rx and io mode on size Standard_DS15_v2
* PERF-DPDK-MULTICORE-PPS-F32 - verifies DPDK performance using testpmd on 2, 4, 8, 16 cores, rx and io mode on size Standard_F32s_v2
* DPDK-RING-LATENCY - verifies DPDK CPU latency using https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fshemminger%2Fdpdk-ring-ping.git&amp;data=02%7C01%7Cv-advlad%40microsoft.com%7Cf25bf3676935492f47a908d6f586fbdf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636966357449557602&amp;sdata=Q4nRfM8tGtlnppQuuNSFFKOTFr72%2BvnWuxy%2FRN9vFsM%3D&amp;reserved=0

 DPDK job exited with status: UNSTABLE - https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Flinuxpipeline.westus2.cloudapp.azure.com%2Fjob%2FDPDK%2Fjob%2Fpipeline-dpdk-validation%2Fjob%2Fmaster%2F113%2F&amp;data=02%7C01%7Cv-advlad%40microsoft.com%7Cf25bf3676935492f47a908d6f586fbdf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636966357449557602&amp;sdata=Hu9KjbtDnBpUZWK1o3IjWvpTGTB43FkeexhpxUZjH9g%3D&amp;reserved=0. 

Test results for DPDK 'https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.dpdk.org%2Fdpdk-stable%2Fsnapshot%2Fdpdk-stable-v18.11.2.tar.gz&amp;data=02%7C01%7Cv-advlad%40microsoft.com%7Cf25bf3676935492f47a908d6f586fbdf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636966357449557602&amp;sdata=yfpj4rFvFP2sDD3I42U%2B09wzNQS6Fb26p63BpB5Z%2BlQ%3D&amp;reserved=0' and Azure image: 'Canonical UbuntuServer 16.04-LTS latest': 
 
* PERF-DPDK-SINGLE-CORE-PPS-DS4: PASSED 
* VERIFY-DPDK-BUILD-AND-TESTPMD-TEST: PASSED 
* VERIFY-SRIOV-FAILSAFE-FOR-DPDK: PASSED 
* PERF-DPDK-MULTICORE-PPS-F32: PASSED 
* VERIFY-DPDK-FAILSAFE-DURING-TRAFFIC: PASSED 
* PERF-DPDK-FWD-PPS-DS15: ABORTED 
* PERF-DPDK-SINGLE-CORE-PPS-DS15: PASSED 
* PERF-DPDK-MULTICORE-PPS-DS15: PASSED 
* VERIFY-DPDK-COMPLIANCE: PASSED 
* VERIFY-DPDK-RING-LATENCY: PASSED 

Test results for DPDK 'https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.dpdk.org%2Fdpdk-stable%2Fsnapshot%2Fdpdk-stable-v18.11.2.tar.gz&amp;data=02%7C01%7Cv-advlad%40microsoft.com%7Cf25bf3676935492f47a908d6f586fbdf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636966357449557602&amp;sdata=yfpj4rFvFP2sDD3I42U%2B09wzNQS6Fb26p63BpB5Z%2BlQ%3D&amp;reserved=0' and Azure image: 'Canonical UbuntuServer 18.04-DAILY-LTS latest': 
 
* PERF-DPDK-SINGLE-CORE-PPS-DS4: PASSED 
* VERIFY-DPDK-BUILD-AND-TESTPMD-TEST: PASSED 
* VERIFY-SRIOV-FAILSAFE-FOR-DPDK: PASSED 
* PERF-DPDK-MULTICORE-PPS-F32: PASSED 
* VERIFY-DPDK-FAILSAFE-DURING-TRAFFIC: PASSED 
* PERF-DPDK-FWD-PPS-DS15: PASSED 
* PERF-DPDK-SINGLE-CORE-PPS-DS15: PASSED 
* PERF-DPDK-MULTICORE-PPS-DS15: PASSED 
* VERIFY-DPDK-COMPLIANCE: PASSED 
* VERIFY-DPDK-RING-LATENCY: PASSED 

Test results for DPDK 'https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.dpdk.org%2Fdpdk-stable%2Fsnapshot%2Fdpdk-stable-v18.11.2.tar.gz&amp;data=02%7C01%7Cv-advlad%40microsoft.com%7Cf25bf3676935492f47a908d6f586fbdf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636966357449557602&amp;sdata=yfpj4rFvFP2sDD3I42U%2B09wzNQS6Fb26p63BpB5Z%2BlQ%3D&amp;reserved=0' and Azure image: 'RedHat RHEL 7-RAW latest': 
 
* PERF-DPDK-SINGLE-CORE-PPS-DS4: PASSED 
* VERIFY-DPDK-BUILD-AND-TESTPMD-TEST: PASSED 
* VERIFY-SRIOV-FAILSAFE-FOR-DPDK: PASSED 
* PERF-DPDK-MULTICORE-PPS-F32: FAILED 
* VERIFY-DPDK-FAILSAFE-DURING-TRAFFIC: PASSED 
* PERF-DPDK-FWD-PPS-DS15: PASSED 
* PERF-DPDK-SINGLE-CORE-PPS-DS15: PASSED 
* PERF-DPDK-MULTICORE-PPS-DS15: PASSED 
* VERIFY-DPDK-COMPLIANCE: PASSED 
* VERIFY-DPDK-RING-LATENCY: PASSED 

Test results for DPDK 'https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.dpdk.org%2Fdpdk-stable%2Fsnapshot%2Fdpdk-stable-v18.11.2.tar.gz&amp;data=02%7C01%7Cv-advlad%40microsoft.com%7Cf25bf3676935492f47a908d6f586fbdf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636966357449557602&amp;sdata=yfpj4rFvFP2sDD3I42U%2B09wzNQS6Fb26p63BpB5Z%2BlQ%3D&amp;reserved=0' and Azure image: 'RedHat RHEL 7.5 latest': 
 
* PERF-DPDK-SINGLE-CORE-PPS-DS4: PASSED 
* VERIFY-DPDK-BUILD-AND-TESTPMD-TEST: PASSED 
* VERIFY-SRIOV-FAILSAFE-FOR-DPDK: PASSED 
* PERF-DPDK-MULTICORE-PPS-F32: PASSED 
* VERIFY-DPDK-FAILSAFE-DURING-TRAFFIC: PASSED 
* PERF-DPDK-FWD-PPS-DS15: PASSED 
* PERF-DPDK-SINGLE-CORE-PPS-DS15: PASSED 
* PERF-DPDK-MULTICORE-PPS-DS15: PASSED 
* VERIFY-DPDK-COMPLIANCE: PASSED 
* VERIFY-DPDK-RING-LATENCY: PASSED 

Test results for DPDK 'https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.dpdk.org%2Fdpdk-stable%2Fsnapshot%2Fdpdk-stable-v18.11.2.tar.gz&amp;data=02%7C01%7Cv-advlad%40microsoft.com%7Cf25bf3676935492f47a908d6f586fbdf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636966357449557602&amp;sdata=yfpj4rFvFP2sDD3I42U%2B09wzNQS6Fb26p63BpB5Z%2BlQ%3D&amp;reserved=0' and Azure image: 'Openlogic CentOS 7.5 latest': 
 
* PERF-DPDK-SINGLE-CORE-PPS-DS4: PASSED 
* VERIFY-DPDK-BUILD-AND-TESTPMD-TEST: FAILED 
* VERIFY-SRIOV-FAILSAFE-FOR-DPDK: FAILED 
* PERF-DPDK-MULTICORE-PPS-F32: FAILED 
* VERIFY-DPDK-FAILSAFE-DURING-TRAFFIC: PASSED 
* PERF-DPDK-FWD-PPS-DS15: PASSED 
* PERF-DPDK-SINGLE-CORE-PPS-DS15: PASSED 
* PERF-DPDK-MULTICORE-PPS-DS15: PASSED 
* VERIFY-DPDK-COMPLIANCE: ABORTED 
* VERIFY-DPDK-RING-LATENCY: ABORTED 

Test results for DPDK 'https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.dpdk.org%2Fdpdk-stable%2Fsnapshot%2Fdpdk-stable-v18.11.2.tar.gz&amp;data=02%7C01%7Cv-advlad%40microsoft.com%7Cf25bf3676935492f47a908d6f586fbdf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636966357449557602&amp;sdata=yfpj4rFvFP2sDD3I42U%2B09wzNQS6Fb26p63BpB5Z%2BlQ%3D&amp;reserved=0' and Azure image: 'SUSE SLES 15 latest': 
 
* PERF-DPDK-SINGLE-CORE-PPS-DS4: PASSED 
* VERIFY-DPDK-BUILD-AND-TESTPMD-TEST: PASSED 
* VERIFY-SRIOV-FAILSAFE-FOR-DPDK: PASSED 
* PERF-DPDK-MULTICORE-PPS-F32: FAILED 
* VERIFY-DPDK-FAILSAFE-DURING-TRAFFIC: PASSED 
* PERF-DPDK-FWD-PPS-DS15: PASSED 
* PERF-DPDK-SINGLE-CORE-PPS-DS15: PASSED 
* PERF-DPDK-MULTICORE-PPS-DS15: PASSED 
* VERIFY-DPDK-COMPLIANCE: PASSED 
* VERIFY-DPDK-RING-LATENCY: PASSED 


Thank you,
Jenkins DPDK

-----Original Message-----
From: announce <announce-bounces@dpdk.org> On Behalf Of Kevin Traynor
Sent: Tuesday, June 11, 2019 11:42 AM
To: announce@dpdk.org
Subject: [dpdk-announce] DPDK 18.11.2 (LTS) released

Hi all,

Here is a new LTS release:
	https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Ffast.dpdk.org%2Frel%2Fdpdk-18.11.2.tar.xz&amp;data=02%7C01%7CJuhlee%40microsoft.com%7C9ed7868402da4995f00008d6ef50b6c2%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636959527291601695&amp;sdata=5rwuID7BGc2rZ35Yx3fvaf1%2BKjgjkY6MYGkAfC4t9lg%3D&amp;reserved=0

The git tree is at:
	https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdpdk.org%2Fbrowse%2Fdpdk-stable%2F%3Fh%3D18.11&amp;data=02%7C01%7CJuhlee%40microsoft.com%7C9ed7868402da4995f00008d6ef50b6c2%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636959527291601695&amp;sdata=ndPDT68bsRRVTP9NHcRKPyXugJJTRggvS%2F%2BbiVrSzes%3D&amp;reserved=0

Information about this release and validation can be found at:
	https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdoc.dpdk.org%2Fguides-18.11%2Frel_notes%2Frelease_18_11.html%23id1&amp;data=02%7C01%7CJuhlee%40microsoft.com%7C9ed7868402da4995f00008d6ef50b6c2%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636959527291601695&amp;sdata=LstHdmkUbE75Ka2D1Eg%2FsqkFvhrq2F9ArFuSDfiqJSk%3D&amp;reserved=0

This is a big release with ~350 fixes backported.

Thanks to the companies who provided validation and those who helped with backports.

Kevin Traynor

---
 .ci/linux-build.sh                                 |  24 +
 .ci/linux-setup.sh                                 |   3 +
 .gitignore                                         |   1 +
 .travis.yml                                        |  98 +++
 MAINTAINERS                                        |   8 +-
 app/pdump/main.c                                   |  17 +-
 app/test-bbdev/test_bbdev.c                        |  10 +-
 app/test-crypto-perf/main.c                        |   5 +
 app/test-pmd/cmdline.c                             | 269 ++++++---
 app/test-pmd/cmdline_flow.c                        | 128 +++-
 app/test-pmd/config.c                              |  14 +-
 app/test-pmd/csumonly.c                            |   2 +-
 app/test-pmd/testpmd.c                             |  90 +--
 app/test-pmd/testpmd.h                             |  13 +-
 buildtools/symlink-drivers-solibs.sh               |   7 +-
 config/arm/meson.build                             |  10 +-
 config/meson.build                                 |   7 +
 config/x86/meson.build                             |  21 +-
 devtools/check-symbol-change.sh                    |  44 +-
 devtools/checkpatches.sh                           |   2 +-
 devtools/test-build.sh                             |  12 +-
 devtools/test-meson-builds.sh                      |  10 +-
 doc/guides/compressdevs/overview.rst               |   2 +-
 doc/guides/conf.py                                 |   5 +
 doc/guides/contributing/coding_style.rst           |   4 +-
 doc/guides/contributing/documentation.rst          |   9 +-
 doc/guides/contributing/patches.rst                |   6 +-
 doc/guides/contributing/versioning.rst             |  19 +-
 doc/guides/cryptodevs/aesni_mb.rst                 |   2 +-
 doc/guides/cryptodevs/features/aesni_gcm.ini       |   5 +
 doc/guides/cryptodevs/features/aesni_mb.ini        |  14 +
 doc/guides/cryptodevs/features/armv8.ini           |   5 +
 doc/guides/cryptodevs/features/caam_jr.ini         |   5 +
 doc/guides/cryptodevs/features/ccp.ini             |   5 +
 doc/guides/cryptodevs/features/default.ini         |   9 +
 doc/guides/cryptodevs/features/dpaa2_sec.ini       |   5 +
 doc/guides/cryptodevs/features/dpaa_sec.ini        |   5 +
 doc/guides/cryptodevs/features/kasumi.ini          |   5 +
 doc/guides/cryptodevs/features/mvsam.ini           |   5 +
 doc/guides/cryptodevs/features/null.ini            |   5 +
 doc/guides/cryptodevs/features/octeontx.ini        |   5 +
 doc/guides/cryptodevs/features/qat.ini             |   5 +
 doc/guides/cryptodevs/features/snow3g.ini          |   5 +
 doc/guides/cryptodevs/features/virtio.ini          |   5 +
 doc/guides/cryptodevs/features/zuc.ini             |   5 +
 doc/guides/cryptodevs/openssl.rst                  |   8 +
 doc/guides/cryptodevs/overview.rst                 |   9 +-
 doc/guides/cryptodevs/scheduler.rst                |   2 +-
 doc/guides/eventdevs/opdl.rst                      |   2 +-
 doc/guides/eventdevs/sw.rst                        |   4 +-
 doc/guides/howto/lm_bond_virtio_sriov.rst          |   2 +-
 doc/guides/howto/lm_virtio_vhost_user.rst          |   4 +-
 doc/guides/howto/rte_flow.rst                      |   6 +-
 .../howto/virtio_user_as_exceptional_path.rst      |   8 +-
 .../linux_gsg/cross_build_dpdk_for_arm64.rst       |  16 +-
 doc/guides/linux_gsg/sys_reqs.rst                  |   2 +-
 doc/guides/nics/atlantic.rst                       |   2 +-
 doc/guides/nics/cxgbe.rst                          |   4 +-
 doc/guides/nics/dpaa.rst                           |   2 +-
 doc/guides/nics/dpaa2.rst                          |   2 +-
 doc/guides/nics/enetc.rst                          |   2 +-
 doc/guides/nics/enic.rst                           |  13 +-
 doc/guides/nics/features.rst                       |   4 +-
 doc/guides/nics/features/qede.ini                  |   1 +
 doc/guides/nics/i40e.rst                           |   2 +-
 doc/guides/nics/ixgbe.rst                          |   4 +-
 doc/guides/nics/kni.rst                            |   2 +-
 doc/guides/nics/mlx5.rst                           |  15 +-
 doc/guides/nics/mvpp2.rst                          |   2 +-
 doc/guides/nics/netvsc.rst                         |   2 +-
 doc/guides/nics/sfc_efx.rst                        |  14 +-
 doc/guides/nics/szedata2.rst                       |   2 +-
 doc/guides/nics/tap.rst                            |   2 +-
 doc/guides/platform/dpaa.rst                       |   4 +-
 doc/guides/platform/dpaa2.rst                      |   4 +-
 doc/guides/prog_guide/bbdev.rst                    |   4 +-
 doc/guides/prog_guide/compressdev.rst              |   6 +-
 doc/guides/prog_guide/cryptodev_lib.rst            |  12 +-
 doc/guides/prog_guide/dev_kit_build_system.rst     |   4 +-
 doc/guides/prog_guide/efd_lib.rst                  |   2 +-
 doc/guides/prog_guide/env_abstraction_layer.rst    |  32 +-
 .../prog_guide/event_ethernet_rx_adapter.rst       |   6 +-
 doc/guides/prog_guide/eventdev.rst                 |   6 +-
 doc/guides/prog_guide/kernel_nic_interface.rst     |   2 +-
 .../prog_guide/link_bonding_poll_mode_drv_lib.rst  |   8 +-
 doc/guides/prog_guide/lpm_lib.rst                  |   2 +-
 doc/guides/prog_guide/metrics_lib.rst              |   2 +-
 doc/guides/prog_guide/multi_proc_support.rst       |  22 +-
 doc/guides/prog_guide/poll_mode_drv.rst            |   6 +-
 doc/guides/prog_guide/profile_app.rst              |   4 +-
 doc/guides/prog_guide/rte_flow.rst                 |   8 +-
 doc/guides/prog_guide/rte_security.rst             |  20 +-
 doc/guides/prog_guide/traffic_management.rst       |   2 +-
 doc/guides/prog_guide/vhost_lib.rst                |   2 +-
 doc/guides/rawdevs/ifpga_rawdev.rst                |   2 +-
 doc/guides/rel_notes/known_issues.rst              |   8 +-
 doc/guides/rel_notes/release_17_11.rst             |  10 +-
 doc/guides/rel_notes/release_18_11.rst             | 515 +++++++++++++++-
 doc/guides/sample_app_ug/bbdev_app.rst             |   4 +-
 doc/guides/sample_app_ug/eventdev_pipeline.rst     |   2 +-
 doc/guides/sample_app_ug/intro.rst                 |   2 +-
 doc/guides/sample_app_ug/ip_pipeline.rst           |   4 +-
 doc/guides/sample_app_ug/ipsec_secgw.rst           |   4 +-
 doc/guides/sample_app_ug/performance_thread.rst    |   4 +-
 doc/guides/sample_app_ug/qos_metering.rst          |   2 +-
 doc/guides/sample_app_ug/test_pipeline.rst         |   2 +-
 doc/guides/sample_app_ug/vhost.rst                 |   4 +-
 doc/guides/sample_app_ug/vhost_scsi.rst            |   2 +-
 doc/guides/sample_app_ug/vm_power_management.rst   |  15 +-
 doc/guides/testpmd_app_ug/run_app.rst              |  12 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst        | 158 ++++-
 doc/guides/tools/cryptoperf.rst                    |  22 +-
 doc/guides/tools/proc_info.rst                     |   2 +-
 doc/guides/tools/testbbdev.rst                     |  10 +-
 drivers/bus/dpaa/base/fman/fman_hw.c               |   4 +-
 drivers/bus/fslmc/fslmc_bus.c                      |   6 +-
 drivers/bus/fslmc/qbman/include/compat.h           |   2 +-
 drivers/bus/fslmc/qbman/include/fsl_qbman_debug.h  |   6 +-
 drivers/bus/fslmc/qbman/qbman_debug.c              |   5 +-
 drivers/bus/vdev/vdev.c                            |  17 +-
 drivers/bus/vmbus/linux/vmbus_uio.c                |  56 +-
 drivers/bus/vmbus/private.h                        |   3 +
 drivers/bus/vmbus/vmbus_channel.c                  |  20 +-
 drivers/bus/vmbus/vmbus_common_uio.c               |  22 +-
 drivers/common/cpt/cpt_ucode.h                     |   2 +-
 drivers/common/qat/qat_qp.c                        |  14 +-
 drivers/compress/isal/isal_compress_pmd.c          |   5 +-
 drivers/compress/isal/isal_compress_pmd_ops.c      |  16 +-
 drivers/compress/qat/qat_comp_pmd.c                |   9 +-
 drivers/crypto/caam_jr/caam_jr.c                   |   4 +-
 drivers/crypto/caam_jr/caam_jr_uio.c               |  10 +-
 drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c        |  12 +-
 drivers/crypto/dpaa2_sec/hw/desc/pdcp.h            |   4 +-
 drivers/crypto/dpaa_sec/dpaa_sec.c                 |   2 +-
 drivers/crypto/kasumi/meson.build                  |   8 +-
 drivers/crypto/meson.build                         |   2 +-
 drivers/crypto/openssl/rte_openssl_pmd.c           |  12 +-
 drivers/crypto/qat/qat_sym_session.c               |   3 +-
 drivers/crypto/snow3g/meson.build                  |  13 +
 drivers/crypto/virtio/virtio_logs.h                |   4 +-
 drivers/crypto/virtio/virtio_rxtx.c                |   4 +-
 drivers/crypto/zuc/meson.build                     |   8 +-
 drivers/event/dpaa2/dpaa2_eventdev.h               |   7 +-
 drivers/event/dpaa2/dpaa2_eventdev_logs.h          |   3 +-
 drivers/event/dsw/dsw_evdev.c                      |  13 +-
 drivers/event/meson.build                          |   6 +-
 drivers/event/opdl/opdl_evdev.c                    |   7 +-
 drivers/event/opdl/opdl_evdev_xstats.c             |   7 +-
 drivers/event/opdl/opdl_ring.h                     |   8 +-
 drivers/event/sw/sw_evdev_selftest.c               |  22 +-
 drivers/mempool/dpaa2/dpaa2_hw_mempool.c           |   4 +-
 drivers/mempool/dpaa2/dpaa2_hw_mempool_logs.h      |   3 +-
 drivers/net/atlantic/atl_ethdev.c                  | 106 ++--
 drivers/net/atlantic/atl_rxtx.c                    |  21 +-
 drivers/net/atlantic/atl_types.h                   |   9 +-
 drivers/net/atlantic/hw_atl/hw_atl_b0.c            |  14 +-
 drivers/net/atlantic/hw_atl/hw_atl_b0.h            |   2 +
 drivers/net/atlantic/hw_atl/hw_atl_utils.c         |  19 +-
 drivers/net/atlantic/hw_atl/hw_atl_utils.h         |  16 +-
 drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c    | 130 ++--
 drivers/net/avf/avf_ethdev.c                       |   3 +-
 drivers/net/axgbe/axgbe_common.h                   |   4 +-
 drivers/net/bnx2x/bnx2x.c                          |  59 +-
 drivers/net/bnx2x/bnx2x.h                          |   9 +-
 drivers/net/bnx2x/bnx2x_ethdev.c                   |  32 +-
 drivers/net/bnx2x/bnx2x_rxtx.c                     |  21 +-
 drivers/net/bnx2x/bnx2x_rxtx.h                     |   3 +-
 drivers/net/bnx2x/ecore_hsi.h                      |   2 +-
 drivers/net/bnx2x/ecore_reg.h                      |   2 +-
 drivers/net/bnx2x/ecore_sp.c                       |  12 +-
 drivers/net/bnx2x/ecore_sp.h                       |  17 +-
 drivers/net/bnx2x/elink.h                          |   2 +-
 drivers/net/bnxt/bnxt.h                            |   2 +-
 drivers/net/bnxt/bnxt_ethdev.c                     |  22 +-
 drivers/net/bnxt/bnxt_rxq.c                        |   3 +-
 drivers/net/bnxt/bnxt_rxr.c                        |   4 +-
 drivers/net/bonding/rte_eth_bond_8023ad.c          |  22 +-
 drivers/net/bonding/rte_eth_bond_8023ad_private.h  |   1 +
 drivers/net/bonding/rte_eth_bond_alb.c             |   4 +-
 drivers/net/bonding/rte_eth_bond_api.c             |   8 +-
 drivers/net/bonding/rte_eth_bond_pmd.c             | 167 +++---
 drivers/net/bonding/rte_eth_bond_private.h         |  15 +-
 drivers/net/cxgbe/base/t4_hw.c                     |   2 +-
 drivers/net/cxgbe/base/t4_pci_id_tbl.h             |  52 +-
 drivers/net/cxgbe/cxgbe.h                          |  24 +-
 drivers/net/cxgbe/cxgbe_ethdev.c                   |  15 +-
 drivers/net/cxgbe/cxgbe_main.c                     |  36 +-
 drivers/net/cxgbe/cxgbevf_main.c                   |  10 +-
 drivers/net/cxgbe/sge.c                            |  78 ++-
 drivers/net/dpaa2/dpaa2_pmd_logs.h                 |   3 +-
 drivers/net/e1000/base/e1000_82575.h               |   4 +-
 drivers/net/e1000/base/e1000_ich8lan.c             |   2 +-
 drivers/net/enetc/enetc_ethdev.c                   |   6 +-
 drivers/net/enetc/enetc_rxtx.c                     |  12 +-
 drivers/net/enic/enic.h                            |  12 +-
 drivers/net/enic/enic_clsf.c                       |  38 +-
 drivers/net/enic/enic_flow.c                       | 659 ++++++++++++---------
 drivers/net/enic/enic_main.c                       |   9 +-
 drivers/net/enic/enic_res.c                        |   5 +-
 drivers/net/enic/enic_rxtx_common.h                |   3 +-
 drivers/net/fm10k/fm10k_rxtx.c                     |   4 +-
 drivers/net/fm10k/fm10k_rxtx_vec.c                 |   6 +-
 drivers/net/i40e/i40e_ethdev.c                     |  60 +-
 drivers/net/i40e/i40e_ethdev_vf.c                  |   5 +-
 drivers/net/i40e/i40e_flow.c                       |   8 +
 drivers/net/i40e/i40e_rxtx.c                       |  11 +-
 drivers/net/i40e/rte_pmd_i40e.h                    |   4 +-
 drivers/net/ixgbe/ixgbe_rxtx.c                     |   6 +-
 drivers/net/kni/rte_eth_kni.c                      |   5 +-
 drivers/net/mlx4/mlx4.c                            |  14 +-
 drivers/net/mlx4/mlx4.h                            |  26 +-
 drivers/net/mlx4/mlx4_ethdev.c                     |  38 +-
 drivers/net/mlx4/mlx4_flow.c                       |  67 ++-
 drivers/net/mlx4/mlx4_flow.h                       |   6 +-
 drivers/net/mlx4/mlx4_intr.c                       |  40 +-
 drivers/net/mlx4/mlx4_mr.c                         |  51 +-
 drivers/net/mlx4/mlx4_rxq.c                        |  56 +-
 drivers/net/mlx4/mlx4_rxtx.h                       |  18 +-
 drivers/net/mlx4/mlx4_txq.c                        |  14 +-
 drivers/net/mlx5/mlx5.c                            |  23 +-
 drivers/net/mlx5/mlx5.h                            |   7 +-
 drivers/net/mlx5/mlx5_defs.h                       |   3 +-
 drivers/net/mlx5/mlx5_ethdev.c                     |  28 +-
 drivers/net/mlx5/mlx5_flow.c                       |  72 ++-
 drivers/net/mlx5/mlx5_flow.h                       |   1 +
 drivers/net/mlx5/mlx5_flow_dv.c                    |  20 +-
 drivers/net/mlx5/mlx5_flow_tcf.c                   |   8 +-
 drivers/net/mlx5/mlx5_flow_verbs.c                 |  12 +-
 drivers/net/mlx5/mlx5_mac.c                        |   4 +-
 drivers/net/mlx5/mlx5_mr.c                         |  57 +-
 drivers/net/mlx5/mlx5_nl.c                         |  12 +-
 drivers/net/mlx5/mlx5_rss.c                        |  10 +-
 drivers/net/mlx5/mlx5_rxmode.c                     |   8 +-
 drivers/net/mlx5/mlx5_rxq.c                        |  71 +--
 drivers/net/mlx5/mlx5_rxtx.c                       |   5 +-
 drivers/net/mlx5/mlx5_rxtx.h                       |   9 +-
 drivers/net/mlx5/mlx5_rxtx_vec.c                   |   4 +-
 drivers/net/mlx5/mlx5_rxtx_vec.h                   |  17 +-
 drivers/net/mlx5/mlx5_rxtx_vec_neon.h              |  12 +-
 drivers/net/mlx5/mlx5_rxtx_vec_sse.h               |  11 +-
 drivers/net/mlx5/mlx5_socket.c                     |   8 +-
 drivers/net/mlx5/mlx5_stats.c                      |  14 +-
 drivers/net/mlx5/mlx5_trigger.c                    |  16 +-
 drivers/net/mlx5/mlx5_txq.c                        |  65 +-
 drivers/net/mlx5/mlx5_vlan.c                       |   6 +-
 drivers/net/mvpp2/mrvl_mtr.c                       |   3 +-
 drivers/net/netvsc/hn_ethdev.c                     |   3 +-
 drivers/net/netvsc/hn_rxtx.c                       |  55 +-
 drivers/net/netvsc/hn_var.h                        |  32 +-
 drivers/net/netvsc/hn_vf.c                         |  86 +--
 drivers/net/nfp/nfp_net.c                          |  53 +-
 drivers/net/nfp/nfp_net_ctrl.h                     |   4 +-
 drivers/net/nfp/nfp_net_pmd.h                      |   4 +-
 drivers/net/nfp/nfpcore/nfp-common/nfp_cppat.h     |   3 +
 drivers/net/nfp/nfpcore/nfp_cpp_pcie_ops.c         |  18 +-
 drivers/net/nfp/nfpcore/nfp_cppcore.c              |   9 +-
 drivers/net/octeontx/octeontx_ethdev.h             |   1 +
 drivers/net/pcap/rte_eth_pcap.c                    |   5 +-
 drivers/net/qede/base/common_hsi.h                 |   4 +-
 drivers/net/qede/base/ecore_hsi_common.h           |   2 +-
 drivers/net/qede/base/ecore_hsi_eth.h              |   2 +-
 drivers/net/qede/base/ecore_hw_defs.h              |   2 +-
 drivers/net/qede/qede_ethdev.c                     |   6 +-
 drivers/net/qede/qede_rxtx.c                       |  17 +-
 drivers/net/ring/rte_eth_ring.c                    |  96 +--
 drivers/net/sfc/sfc.c                              |   6 +-
 drivers/net/sfc/sfc.h                              |   2 +-
 drivers/net/sfc/sfc_debug.h                        |   3 +-
 drivers/net/sfc/sfc_ef10_tx.c                      |  11 +-
 drivers/net/sfc/sfc_ethdev.c                       |  72 ++-
 drivers/net/sfc/sfc_mcdi.c                         |   3 +-
 drivers/net/sfc/sfc_rx.c                           |  22 +-
 drivers/net/sfc/sfc_rx.h                           |   4 +
 drivers/net/sfc/sfc_tso.c                          |  11 +-
 drivers/net/sfc/sfc_tx.c                           |   3 +-
 drivers/net/softnic/rte_eth_softnic_flow.c         |   5 +-
 drivers/net/tap/rte_eth_tap.c                      |  28 +-
 drivers/net/tap/tap_bpf_program.c                  |   2 +-
 drivers/net/vdev_netvsc/vdev_netvsc.c              |   7 +-
 drivers/net/virtio/virtio_ethdev.c                 |  24 +-
 drivers/net/virtio/virtio_ethdev.h                 |   2 +
 drivers/net/virtio/virtio_rxtx.c                   |  36 +-
 drivers/net/virtio/virtio_user/vhost.h             |   4 +-
 drivers/net/virtio/virtio_user/vhost_kernel_tap.c  |  12 +-
 drivers/net/virtio/virtio_user/vhost_user.c        |   5 +-
 drivers/net/virtio/virtio_user/virtio_user_dev.c   |   3 +-
 drivers/net/virtio/virtio_user/virtio_user_dev.h   |   2 +-
 drivers/net/virtio/virtio_user_ethdev.c            |  61 +-
 drivers/net/vmxnet3/vmxnet3_ethdev.c               |   1 +
 drivers/raw/dpaa2_cmdif/dpaa2_cmdif.c              |   2 +
 drivers/raw/dpaa2_qdma/dpaa2_qdma.c                |  21 +-
 drivers/raw/dpaa2_qdma/rte_pmd_dpaa2_qdma.h        |   4 +-
 drivers/raw/ifpga_rawdev/ifpga_rawdev.c            |   3 +-
 drivers/raw/ifpga_rawdev/ifpga_rawdev.h            |   4 +-
 drivers/raw/skeleton_rawdev/skeleton_rawdev.c      |   5 +
 examples/ethtool/lib/rte_ethtool.h                 |   4 +-
 examples/fips_validation/main.c                    |   8 +-
 examples/ip_pipeline/meson.build                   |   1 +
 examples/ipsec-secgw/Makefile                      |   2 +-
 examples/ipsec-secgw/esp.c                         |   5 +-
 examples/ipsec-secgw/ipsec-secgw.c                 |  26 +-
 examples/ipsec-secgw/ipsec.h                       |  14 +-
 examples/ipsec-secgw/sa.c                          |  58 +-
 examples/ipsec-secgw/sp4.c                         |  47 +-
 examples/ipsec-secgw/sp6.c                         |  47 +-
 examples/l2fwd-cat/cat.c                           |   2 +-
 .../client_server_mp/mp_server/init.c              |  13 +-
 examples/performance-thread/common/lthread_api.h   |  10 +-
 examples/vhost_crypto/meson.build                  |   1 +
 examples/vhost_scsi/vhost_scsi.c                   |   6 +
 examples/vm_power_manager/channel_monitor.c        |  12 +-
 examples/vm_power_manager/main.c                   |  15 +-
 examples/vm_power_manager/oob_monitor_x86.c        |  23 +-
 examples/vm_power_manager/power_manager.c          |   2 +-
 kernel/linux/kni/ethtool/igb/igb_main.c            |   6 +
 kernel/linux/kni/ethtool/igb/kcompat.h             |   4 +
 kernel/linux/kni/kni_misc.c                        |   2 +-
 lib/librte_acl/acl_vect.h                          |   4 +-
 lib/librte_acl/meson.build                         |   2 +-
 lib/librte_bbdev/rte_bbdev.h                       |   4 +-
 lib/librte_bitratestats/rte_bitrate.c              |   6 +-
 lib/librte_bpf/rte_bpf.h                           |   6 +-
 lib/librte_bpf/rte_bpf_ethdev.h                    |   4 +-
 lib/librte_cfgfile/rte_cfgfile.c                   |   4 +-
 lib/librte_cryptodev/rte_crypto_asym.h             |  10 +-
 lib/librte_cryptodev/rte_cryptodev.c               |   4 +-
 lib/librte_cryptodev/rte_cryptodev.h               |   2 +-
 lib/librte_distributor/rte_distributor_private.h   |   2 +-
 lib/librte_eal/bsdapp/eal/eal.c                    |  14 +-
 lib/librte_eal/bsdapp/eal/eal_hugepage_info.c      |   2 +-
 lib/librte_eal/common/eal_common_memory.c          |  13 +-
 lib/librte_eal/common/eal_common_options.c         | 243 +++++---
 lib/librte_eal/common/eal_common_proc.c            |  57 +-
 lib/librte_eal/common/eal_common_thread.c          |  23 +-
 lib/librte_eal/common/eal_internal_cfg.h           |   3 +
 lib/librte_eal/common/eal_options.h                |   2 +
 lib/librte_eal/common/hotplug_mp.c                 |   2 +-
 .../common/include/arch/ppc_64/rte_atomic.h        |   8 -
 lib/librte_eal/common/include/generic/rte_cycles.h |   2 +-
 lib/librte_eal/common/include/generic/rte_rwlock.h |  16 +-
 .../common/include/generic/rte_spinlock.h          |  18 +-
 lib/librte_eal/common/include/generic/rte_vect.h   |   2 +-
 lib/librte_eal/common/include/rte_class.h          |   2 +-
 lib/librte_eal/common/include/rte_common.h         |   4 +-
 lib/librte_eal/common/include/rte_eal.h            |  26 +-
 lib/librte_eal/common/include/rte_lcore.h          |  17 +-
 lib/librte_eal/common/include/rte_log.h            |   2 +-
 lib/librte_eal/common/include/rte_malloc.h         |   2 +-
 lib/librte_eal/common/include/rte_service.h        |   2 +-
 lib/librte_eal/common/include/rte_string_fns.h     |  16 +
 lib/librte_eal/common/include/rte_tailq.h          |   2 +-
 lib/librte_eal/common/include/rte_uuid.h           |   4 +-
 lib/librte_eal/common/include/rte_version.h        |   2 +-
 lib/librte_eal/common/include/rte_vfio.h           |   6 +-
 lib/librte_eal/common/malloc_mp.c                  |   2 +-
 lib/librte_eal/linuxapp/eal/eal.c                  |  19 +-
 lib/librte_eal/linuxapp/eal/eal_dev.c              |   4 +-
 lib/librte_eal/linuxapp/eal/eal_hugepage_info.c    |   2 +-
 lib/librte_eal/linuxapp/eal/eal_memalloc.c         |   4 +
 lib/librte_eal/linuxapp/eal/eal_memory.c           |  26 +-
 .../linuxapp/eal/include/exec-env/rte_kni_common.h |   2 +-
 lib/librte_efd/rte_efd.h                           |   2 +-
 lib/librte_ethdev/rte_eth_ctrl.h                   |   2 +-
 lib/librte_ethdev/rte_ethdev.c                     |   7 +-
 lib/librte_ethdev/rte_ethdev.h                     |  10 +-
 lib/librte_ethdev/rte_ethdev_core.h                |   4 +-
 lib/librte_ethdev/rte_ethdev_driver.h              |   2 +-
 lib/librte_ethdev/rte_tm.h                         |   8 +-
 lib/librte_eventdev/rte_event_crypto_adapter.c     |  16 +-
 lib/librte_eventdev/rte_event_crypto_adapter.h     |   2 +-
 lib/librte_eventdev/rte_event_eth_rx_adapter.c     |   2 +-
 lib/librte_eventdev/rte_event_eth_rx_adapter.h     |   4 +-
 lib/librte_eventdev/rte_event_eth_tx_adapter.h     |   3 +-
 lib/librte_eventdev/rte_eventdev.h                 |  21 +-
 lib/librte_eventdev/rte_eventdev_pmd.h             |   2 +-
 lib/librte_flow_classify/rte_flow_classify.h       |   4 +-
 lib/librte_hash/rte_cuckoo_hash.c                  |  15 +-
 lib/librte_hash/rte_hash.h                         |   4 +-
 lib/librte_ip_frag/rte_ip_frag.h                   |   2 +-
 lib/librte_kni/rte_kni.h                           |   2 +-
 lib/librte_latencystats/rte_latencystats.h         |   2 +-
 lib/librte_lpm/rte_lpm.h                           |   2 +-
 lib/librte_mbuf/rte_mbuf.h                         |  18 +-
 lib/librte_mbuf/rte_mbuf_ptype.h                   |   2 +-
 lib/librte_mempool/rte_mempool.h                   |   4 +-
 lib/librte_net/rte_ether.h                         |   2 +-
 lib/librte_power/power_acpi_cpufreq.c              |   5 +-
 lib/librte_power/rte_power.c                       |  30 +-
 lib/librte_power/rte_power.h                       |   2 +-
 lib/librte_power/rte_power_empty_poll.c            |   3 -
 lib/librte_power/rte_power_empty_poll.h            |   2 +-
 lib/librte_rawdev/rte_rawdev.h                     |   6 +-
 lib/librte_rawdev/rte_rawdev_pmd.h                 |   8 +-
 lib/librte_reorder/rte_reorder.h                   |   2 +-
 lib/librte_ring/rte_ring.c                         |   3 +-
 lib/librte_ring/rte_ring.h                         |   4 +-
 lib/librte_ring/rte_ring_generic.h                 |   9 +-
 lib/librte_sched/rte_sched.h                       |   2 +-
 lib/librte_security/rte_security.h                 |   4 +-
 lib/librte_table/rte_table_hash.h                  |   6 +-
 lib/librte_table/rte_table_hash_func.h             |   2 +-
 lib/librte_telemetry/Makefile                      |   5 +
 lib/librte_telemetry/rte_telemetry_parser.c        |  26 +-
 lib/librte_vhost/rte_vhost.h                       |   4 +-
 lib/librte_vhost/socket.c                          |  26 +-
 lib/librte_vhost/vdpa.c                            |   7 +-
 lib/librte_vhost/vhost.c                           |  16 +-
 lib/librte_vhost/vhost.h                           |  46 +-
 lib/librte_vhost/vhost_crypto.c                    |   4 +-
 lib/librte_vhost/vhost_user.c                      |  54 +-
 lib/librte_vhost/virtio_net.c                      |  34 --
 meson.build                                        |   9 +-
 mk/exec-env/linuxapp/rte.vars.mk                   |   6 +
 mk/rte.app.mk                                      |   3 -
 mk/rte.lib.mk                                      |   2 +
 mk/toolchain/gcc/rte.toolchain-compat.mk           |  11 +-
 mk/toolchain/gcc/rte.vars.mk                       |   3 +
 pkg/dpdk.spec                                      |   2 +-
 test/test/autotest_data.py                         |   6 -
 test/test/commands.c                               |  12 +-
 test/test/meson.build                              |   3 +-
 test/test/test_barrier.c                           |   6 +-
 test/test/test_compressdev.c                       |   1 +
 test/test/test_cryptodev.c                         |   3 +-
 test/test/test_cryptodev_blockcipher.h             |   4 +-
 test/test/test_distributor.c                       |   7 +-
 test/test/test_eal_flags.c                         |   1 +
 test/test/test_event_eth_rx_adapter.c              |   3 +-
 test/test/test_hash_perf.c                         |   6 +-
 test/test/test_link_bonding.c                      |  45 +-
 test/test/test_pmd_perf.c                          |  13 +-
 test/test/test_spinlock.c                          |  31 +-
 test/test/test_string_fns.c                        |  45 ++
 433 files changed, 4965 insertions(+), 2398 deletions(-) Aaron Conole (4):
      net/virtio: fix dangling pointer on failure
      ci: enable ccache in Travis
      ci: add a distinguisher to the extra Travis builds
      ipc: unlock on failure

Abhinandan Gujjar (1):
      eventdev: fix crypto adapter

Agalya Babu RadhaKrishnan (2):
      doc: fix interactive commands in testpmd guide
      app/testpmd: fix help info for interactive commands

Akhil Goyal (3):
      crypto/dpaa2_sec: fix session clearing
      crypto/dpaa2_sec: fix offset calculation for GCM
      crypto/dpaa: fix session destroy

Alejandro Lucero (5):
      net/nfp: fix RSS query
      net/nfp: fix file descriptor check
      net/nfp: fix potential integer overflow
      net/nfp: check return value
      net/nfp: fix memory leak

Anatoly Burakov (11):
      malloc: fix documentation of realloc function
      vfio: document multiprocess limitation for container API
      malloc: fix IPC message initialization
      mem: warn user when running without NUMA support
      eal: fix cleanup in no-shconf mode
      ipc: fix send error handling
      ipc: harden message receive
      ipc: handle more invalid parameter cases
      doc: fix typo in IPC guide
      ipc: add warnings about not using IPC with memory API
      ipc: add warnings about correct API usage

Andrew Rybchenko (3):
      net/sfc: remove control path logging from Rx queue count
      net/sfc: fix logging from secondary process
      net/sfc: fix speed capabilities reported in device info

Andrius Sirvys (4):
      drivers/net: fix shifting 32-bit signed variable 31 times
      acl: fix compiler flags with meson and AVX2 runtime
      net/virtio: fix duplicate naming of include guard
      bitrate: fix unchecked return value

Andy Pei (1):
      raw/ifpga: modify log output

Anoob Joseph (2):
      common/cpt: fix null auth only
      cryptodev: fix driver name comparison

Arek Kusztal (2):
      crypto/openssl: fix big numbers after computations
      crypto/openssl: fix modexp

Beilei Xing (2):
      net/i40e: fix logging on VF close
      net/i40e: fix link speed for X722

Bernard Iremonger (1):
      examples/ipsec-secgw: fix debug logs

Bill Hong (1):
      net: fix Tx VLAN flag for offload emulation

Bruce Richardson (24):
      test/compress: fix missing header include
      examples/ip_pipeline: disable build when no epoll
      examples/vhost_crypto: fix dependency on vhost library
      devtools: fix build test on FreeBSD
      eal: support strlcat function
      telemetry: fix mapping of statistics
      eal: tighten permissions on shared memory files
      net/bonding: fix buffer length when printing strings
      devtools: skip meson build for missing compilers
      devtools: support older compilers with meson test
      examples/l2fwd-cat: fix build on FreeBSD
      app/crypto-perf: check range of socket id
      examples/vhost_scsi: fix null-check for parameter
      net/i40e: fix dereference before null check in mbuf release
      net/i40e: fix dereference before check when getting EEPROM
      app/testpmd: fix variable use before null check
      crypto/snow3g: add to meson build
      crypto/kasumi: fix dependency check
      crypto/zuc: fix dependency check
      net/ixgbe: fix warning with GCC 9
      bus/fslmc: fix warning with GCC 9
      raw/skeleton: fix warnings with GCC 9
      raw/dpaa2_cmdif: fix warnings with GCC 9
      build: fix ninja install on FreeBSD

Chaitanya Babu Talluri (3):
      drivers/net: fix possible overflow using strlcat
      test/crypto: fix possible overflow using strlcat
      cfgfile: replace strcat with strlcat

Chas Williams (3):
      net/bonding: fix Tx in 802.3ad mode
      net/bonding: fix slave Tx burst for mode 4
      net/bonding: fix link status

Chenbo Xia (2):
      app/testpmd: fix return value check
      net/virtio-user: fix return value check

Darek Stojaczyk (1):
      eal: initialize alarms early

David Christensen (5):
      maintainers: update for IBM POWER
      examples/power: fix build with some disabled PMDs
      test/barrier: fix typo in log
      test/barrier: fix allocation check
      test/barrier: fix for Power CPUs

David Harton (1):
      net/ixgbe: restore VLAN filter for VF

David Hunt (5):
      power: fix governor storage to trim newlines
      examples/power: fix resource leak
      examples/power: fix unreachable VF MAC init
      examples/power: fix buffer overrun
      examples/power: fix json null termination

David Marchand (19):
      eal: fix check when retrieving current CPU affinity
      eal: fix control threads pinnning
      eal: restrict control threads to startup CPU affinity
      eal: remove dead code in core list parsing
      eal: fix core list validation with disabled cores
      app/testpmd: remove unused field from port struct
      doc: fix examples in bonding guide
      net/bonding: fix port id types
      net/bonding: fix slave id types
      net/bonding: fix packet count type for LACP
      net/bonding: fix queue index types
      app/testpmd: add missing newline when showing statistics
      app/testpmd: extend forwarding statistics to 64 bits
      app/testpmd: remove useless casts on statistics
      doc: fix ABI check script examples
      test: clean remaining trace of devargs autotest
      devtools: fix symbol name in check log
      devtools: accept experimental symbol promotion
      devtools: fix check of symbol added as stable API

Davide Caratti (1):
      net/bnxt: support IOVA VA mode

Dekel Peled (13):
      net/mlx5: fix Tx metadata for multi-segment packet
      net/mlx5: fix hex dump of error completion
      net/mlx5: fix sync when handling Tx completions
      eal/ppc: fix global memory barrier
      eal: fix typo in comment of vector function
      doc: fix links to doxygen and sphinx sites
      net/mlx5: fix errno typos in comments
      doc: fix typos in mlx5 guide
      doc: fix typos in testpmd user guide
      app/testpmd: fix typo in comment
      ethdev: fix typo in error messages
      net/mlx5: fix comments mixing Rx and Tx
      net/mlx5: fix release of Rx queue object

Dharmik Thakkar (2):
      hash: fix position returned in free slots
      hash: fix total entries count

Erik Gabriel Carrillo (1):
      eventdev: update references to removed function

Fan Zhang (3):
      examples/ipsec-secgw: fix AES-CTR block size
      vhost/crypto: fix parens
      crypto/virtio: fix IV offset

Ferruh Yigit (6):
      kni: fix build with Linux 5.1
      mbuf: update Tx VLAN and QinQ flags documentation
      build: fix meson binutils workaround
      build: fix crash by disabling AVX512 with binutils 2.31
      net/ring: fix return value check
      net/kni: fix return value check

Fiona Trahe (2):
      doc: fix missing asymmetric crypto table
      crypto/qat: fix null cipher algo for non 8-byte multiple

Gagandeep Singh (6):
      crypto/caam_jr: fix shared descriptor endianness
      crypto/caam_jr: fix total length in auth only s/g
      crypto/caam_jr: fix memory leak and illegal access
      net/enetc: fix SMMU unhandled context fault
      net/enetc: fix big endian build and buffer allocation
      net/enetc: fix crash at high speed traffic

Gage Eads (2):
      app/pdump: remove only created vdevs
      ring: fix namesize macro documentation block

Gavin Hu (4):
      ring: enforce reading tail before slots
      test/spinlock: remove delay for correct benchmarking
      test/spinlock: amortize the cost of getting time
      spinlock: reimplement with atomic one-way barrier

Hari Kumar Vemula (1):
      net/bonding: fix values of descriptor limits

Harry van Haaren (1):
      event/sw: fix enqueue checks in self-test

Hemant Agrawal (3):
      mempool/dpaa2: fix continuous print on empty pool
      test/crypto: fix duplicate id used by CCP device
      raw/dpaa2_qdma: fix spin lock release

Herakliusz Lipiec (5):
      net/tap: fix multi process reply buffer
      ipc: fix memory leak on request failure
      net/tap: fix memory leak on IPC request
      net/tap: fix potential IPC buffer overrun
      doc: fix broken link in LPM guide

Hyong Youb Kim (12):
      net/bonding: avoid warning for invalid port
      net/enic: fix flow director SCTP matching
      net/enic: fix SCTP match for flow API
      net/enic: allow flow mark ID 0
      net/enic: check for unsupported flow item types
      net/enic: reset VXLAN port regardless of overlay offload
      net/enic: fix VXLAN match
      net/enic: fix endianness in VLAN match
      net/enic: fix max MTU calculation
      net/enic: move arguments into struct
      net/enic: fix inner packet matching
      net/enic: fix VLAN inner type matching for old hardware

Igor Romanov (4):
      app/testpmd: fix stdout flush after printing stats
      net/sfc: improve TSO header length check in EFX datapath
      net/sfc: improve TSO header length check in EF10 datapath
      net/sfc: fix MTU change to check Rx scatter consistency

Igor Russkikh (11):
      net/atlantic: fix negative error codes
      net/atlantic: remove unused variable
      net/atlantic: remove extra checks for error codes
      net/atlantic: fix link configuration
      net/atlantic: fix missing VLAN filter offload
      net/atlantic: fix xstats return
      net/atlantic: enable broadcast traffic
      net/atlantic: extra line at eof
      net/atlantic: fix max eeprom size
      net/atlantic: validity check for eeprom dev address
      net/atlantic: eliminate excessive log levels on Rx/Tx

Ilya Maximets (4):
      net/virtio: add barriers for extra descriptors on Rx split
      vhost: fix device leak on connection add failure
      vhost: fix passing destroyed device to destroy callback
      vhost: fix silent queue enabling with legacy guests

Ivan Malov (1):
      net/sfc: log port ID as 16-bit unsigned integer on panic

Jens Freimann (1):
      net/virtio: set offload flag for jumbo frames

Jerin Jacob (3):
      mk: fix AVX512 disabled warning on non x86
      build: remove meson warning for Arm
      table: fix arm64 hash function selection

Jiayu Hu (1):
      vhost: fix interrupt suppression for the split ring

Jie Pan (1):
      kni: fix type for MAC address

John McNamara (2):
      doc: fix spelling reported by aspell in guides
      doc: fix spelling reported by aspell in comments

Joyce Kong (2):
      doc: update cross Arm toolchain in Linux guide
      rwlock: reimplement with atomic builtins

Julien Meunier (1):
      test/pmd_perf: fix the way to drain the port

Kevin Traynor (8):
      net/qede: support IOVA VA mode
      eal/linux: fix log levels for pagemap reading failure
      doc: fix formatting in testpmd guide
      bus/fslmc: fix warning with GCC 9
      mk: disable packed member pointer warning for telemetry
      version: 18.11.2-rc1
      Revert "app/testpmd: fix offload flags after port config"
      version: 18.11.2

Konstantin Ananyev (1):
      examples/ipsec-secgw: fix SPD no-match case

Krzysztof Kanas (1):
      test/bonding: fix MAC assignment for re-run

Li Qiang (1):
      raw/ifpga: fix file descriptor leak in error path

Liang Zhang (1):
      net/bonding: fix LACP negotiation

Luca Boccassi (1):
      build: use default flags for default Arm machine

Lukasz Krakowiak (1):
      doc: fix JSON interface for power sample

Marcin Hajkowski (1):
      power: fix thread-safety environment modification

Marcin Smoczynski (1):
      examples/ipsec-secgw: fix build error log

Mark Gillott (1):
      net/vmxnet3: add VLAN filter capability

Marko Kovacevic (2):
      compress/qat: fix setup inter buffers
      examples/fips_validation: fix CMAC test

Mattias Rönnblom (3):
      event/dsw: fix capability flags
      power: fix cache line alignment
      event/dsw: ignore scheduling type for single-link queues

Maxime Coquelin (1):
      vhost: prevent disabled rings to be processed with zero-copy

Michael Santana (2):
      devtools: fix result of svg include check
      ci: introduce Travis builds for GitHub repositories

Mohammad Abdul Awal (1):
      vhost: fix null pointer checking

Natanael Copa (7):
      eal/linux: remove thread ID from debug message
      bus/fslmc: remove unused include of error.h
      bus/fslmc: fix build with musl libc
      net/nfp: fix build with musl libc
      net/netvsc: fix include of fcntl.h
      app/test: fix flags with meson
      app/test: fix build with musl libc

Nikhil Rao (1):
      eventdev: fix Rx adapter event flush

Nithin Dabilpuram (2):
      app/testpmd: fix Tx VLAN and QinQ dependency
      app/testpmd: fix Tx QinQ set

Oleg Polyakov (1):
      net/tap: fix getting max iovec

Ori Kam (1):
      net/mlx5: fix RSS validation function

Pablo Cascón (1):
      net/nfp: fix setting MAC address

Pablo de Lara (1):
      doc: add missing algorithms for AESNI-MB PMD

Pallantla Poornima (10):
      vhost: fix sprintf with snprintf
      net/softnic: fix possible buffer overflow
      event/opdl: replace sprintf with snprintf
      net/nfp: fix possible buffer overflow
      app/test: fix sprintf with strlcat
      test/event: replace sprintf with snprintf
      power: remove unused variable
      test/distributor: replace sprintf with strlcpy
      test/hash: replace sprintf with snprintf
      app/bbdev: replace sprintf with snprintf or strlcpy

Pavel Belous (7):
      net/atlantic: fix buffer overflow
      net/atlantic: fix EEPROM get for small and uneven lengths
      net/atlantic: error handling for mailbox access
      net/atlantic: eeprom get/set should consider offset
      net/atlantic: bad logic with offsets talking with firmware
      net/atlantic: flow control settings synchronization on rx
      net/atlantic: use capability bits to detect eeprom access

Qi Zhang (3):
      net/pcap: fix memory leak
      net/i40e: fix time sync for 25G
      net/i40e: fix scattered Rx enabling

Qiming Yang (1):
      net/iavf: fix info get

Rahul Lakkireddy (1):
      net/cxgbe: update Chelsio T5/T6 NIC device ids

Rami Rosen (11):
      net/virtio: remove forward declaration
      mbuf: fix a typo
      doc: fix a minor typo in testpmd guide
      doc: remove reference to rte.doc.mk in programmers guide
      examples/ethtool: fix two typos
      doc: fix link in Linux getting started guide
      doc: fix tag for inner RSS feature
      app/testpmd: fix a typo in log message
      ethdev: fix method name in doxygen comment
      ethdev: fix a typo
      doc: fix two typos in contributing guide

Rasesh Mody (3):
      net/bnx2x: fix MTU for jumbo frame
      net/bnx2x: fix race for periodic flags
      net/bnx2x: fix optic module verification

Raslan Darawsheh (2):
      net/tap: fix multi-process request
      bus/vdev: fix hotplug twice

Reshma Pattan (4):
      examples/power: fix string null termination
      examples/power: fix string overflow
      examples/power: fix overflowed value
      mk: disable warning for packed member pointer

Shahaf Shuler (3):
      net/mlx5: fix packet inline on Tx queue wraparound
      mem: limit use of address hint
      app/testpmd: fix mempool free on exit

Shahed Shaikh (6):
      net/qede: fix Tx packet prepare for tunnel packets
      net/qede: fix Rx packet drop
      doc: add flow API to qede NIC features
      net/bnx2x: fix memory leak
      net/bnx2x: fix ramrod timeout
      net/bnx2x: fix DMAE timeout

Shreyansh Jain (2):
      bus/dpaa: fix Rx discard register mask
      raw/dpaa2_qdma: fix to support multiprocess execution

Somnath Kotur (1):
      net/bnxt: fix big endian build

Stephen Hemminger (26):
      crypto/virtio: use local log type
      net/bnxt: silence IOVA warnings
      net/bnxt: suppress spurious error log
      net/octeontx: fix vdev name
      drivers: fix SPDX license id consistency
      bus/vmbus: fix secondary process setup
      net/netvsc: fix VF support with secondary process
      bus/vmbus: fix check for mmap failure
      bus/vmbus: stop mapping if empty resource found
      bus/vmbus: map ring in secondary process
      bus/fslmc: decrease log level for unsupported devices
      net/vdev_netvsc: fix device cast
      net/bnxt: fix Rx VLAN offload flags
      net/netvsc: remove useless condition
      net/virtio: remove useless condition
      ring: fix an error message
      doc: fix spelling in testpmd guide
      net/virtio: fix buffer leak on VLAN insert
      net/cxgbe: fix colliding function names
      bus/vmbus: fix resource leak on error
      eal: fix formatting of hotplug error message
      net/ring: fix coding style
      net/ring: avoid hard-coded length
      net/ring: use calloc style where appropriate
      net/ring: check length of ring name
      net/netvsc: reset mbuf port on VF Rx

Thomas Monjalon (9):
      ethdev: remove unused variable
      mk: fix build of shared library with libbsd
      devtools: add libelf dependency to build test
      devtools: test build of zlib PMD
      devtools: fix test of some build options
      net/mlx: prefix private structure
      doc: fix PCI whitelist typo in prog guide
      bus/vdev: fix debug message on probing
      doc: fix heading levels in bbdev test guide

Tiwei Bie (8):
      net/virtio: fix in-order Tx path for split ring
      vhost: restore mbuf first when freeing zmbuf
      vhost: fix potential use-after-free for zero copy mbuf
      vhost: fix potential use-after-free for memory region
      net/virtio-user: fix multiqueue with vhost kernel
      net/virtio: add barrier in interrupt enable
      net/virtio-user: fix multi-process support
      app/testpmd: fix unintentional integer overflow

Tomasz Cel (2):
      compress/isal: fix compression stream initialization
      compress/isal: fix getting information about CPU

Tomasz Jozwiak (1):
      drivers/qat: fix queue pair NUMA node

Viacheslav Ovsiienko (3):
      net/mlx5: fix flow priorities probing error path
      net/mlx5: fix memory region cleanup
      net/mlx4: fix memory region cleanup

Vishal Kulkarni (1):
      net/cxgbe: fix missing checksum flags and packet type

Wei Zhao (6):
      net/avf: fix admin queue interrupt for ICE
      net/i40e: log when provided RSS key is not valid
      app/testpmd: fix hex string parser support for flow API
      net/i40e: fix queue number check
      app/testpmd: fix offload flags after port config
      net/i40e: forbid two RSS flow rules

Xiao Wang (1):
      net/fm10k: fix VLAN strip offload flag

Yipeng Wang (1):
      hash: fix doc about thread/process safety

Yongseok Koh (11):
      net/mlx5: fix memory event on secondary process
      net/mlx4: change device reference for secondary process
      net/mlx: remove debug messages on datapath
      net/mlx5: fix external memory registration
      drivers/event: disable OcteonTx for buggy Arm compilers
      net/mlx5: fix instruction hotspot on replenishing Rx buffer
      examples/multi_process: fix buffer underrun
      net/mlx5: check Tx queue size overflow
      net/mlx5: fix max number of queues for NEON Tx
      net/mlx5: fix Multi-Packet RQ mempool name
      doc: fix typo in mlx5 guide

^ permalink raw reply	[relevance 1%]

* Re: [dpdk-dev] [PATCH 00/28] vhost: add virtio-vhost-user transport
       [not found]     ` <CGME20190620113240eucas1p22ca4faa64a36bbb7aec38a81298ade56@eucas1p2.samsung.com>
@ 2019-06-20 11:32  3%   ` Ilya Maximets
  2019-06-20 23:44  0%     ` Nikos Dragazis
  0 siblings, 1 reply; 200+ results
From: Ilya Maximets @ 2019-06-20 11:32 UTC (permalink / raw)
  To: Nikos Dragazis, dev
  Cc: Maxime Coquelin, Tiwei Bie, Zhihong Wang, Stefan Hajnoczi,
	Wei Wang, Stojaczyk Dariusz, Vangelis Koukis

On 19.06.2019 18:14, Nikos Dragazis wrote:
> Hi everyone,

Hi. I didn't look at the code, just a few comments inline.

> 
> this patch series introduces the concept of the virtio-vhost-user
> transport. This is actually a revised version of an earlier RFC
> implementation that has been proposed by Stefan Hajnoczi [1]. Though
> this is a great feature, it seems to have been stalled, so I’d like to
> restart the conversation on this and hopefully get it merged with your
> help. Let me give you an overview.
> 
> The virtio-vhost-user transport is a vhost-user transport implementation
> that is based on the virtio-vhost-user device. Its key difference with
> the existing transport is that it allows deploying vhost-user targets
> inside dedicated Storage Appliance VMs instead of host user space. In
> other words, it allows having guests that act as vhost-user backends for
> other guests.
> 
> The virtio-vhost-user device implements the vhost-user control plane
> (master-slave communication) as follows:
> 
> 1. it parses the vhost-user messages from the vhost-user unix domain
>    socket and forwards them to the slave guest through virtqueues
> 
> 2. it maps the vhost memory regions in QEMU’s process address space and
>    exposes them to the slave guest as a RAM-backed PCI MMIO region
> 
> 3. it hooks up doorbells to the callfds. The slave guest can use these
>    doorbells to interrupt the master guest driver
> 
> The device code has not yet been merged into upstream QEMU, but this is
> definitely the end goal. The current state is that we are awaiting for
> the approval of the virtio spec.
> 
> I have Cced Darek from the SPDK community who has helped me a lot by
> reviewing this series. Note that any device type could be implemented
> over this new transport. So, adding the virtio-vhost-user transport in
> DPDK would allow using it from SPDK as well.
> 
> Getting into the code internals, this patch series makes the following
> changes:
> 
> 1. introduce a generic interface for the transport-specific operations.
>    Each of the two available transports, the pre-existing AF_UNIX
>    transport and the virtio-vhost-user transport, is going to implement
>    this interface. The AF_UNIX-specific code has been extracted from the
>    core vhost-user code and is now part of the AF_UNIX transport
>    implementation in trans_af_unix.c.
> 
> 2. introduce the virtio-vhost-user transport. The virtio-vhost-user
>    transport requires a driver for the virtio-vhost-user devices. The
>    driver along with the transport implementation have been packed into
>    a separate library in `drivers/virtio_vhost_user/`. The necessary
>    virtio-pci code has been copied from `drivers/net/virtio/`. Some
>    additional changes have been made so that the driver can utilize the
>    additional resources of the virtio-vhost-user device.
> 
> 3. update librte_vhost public API to enable choosing transport for each
>    new vhost device. Extend the vhost net driver and vhost-scsi example
>    application to export this new API to the end user.
> 
> The primary changes I did to Stefan’s RFC implementation are the
> following:
> 
> 1. moved postcopy live migration code into trans_af_unix.c. Postcopy
>    live migration relies on the userfault fd mechanism, which cannot be
>    supported by virtio-vhost-user.
> 
> 2. moved setup of the log memory region into trans_af_unix.c. Setting up
>    the log memory region involves mapping/unmapping guest memory. This
>    is an AF_UNIX transport-specific operation.

Logging dirty pages is the main concept of live migration support. Does it
mean that the live migration is not supported for virtio-vhost-user at all?

> 
> 3. introduced a vhost transport operation for
>    process_slave_message_reply()
> 
> 4. moved the virtio-vhost-user transport/driver into a separate library
>    in `drivers/virtio_vhost_user/`. This required making vhost.h and
>    vhost_user.h part of librte_vhost public API and exporting some
>    private symbols via the version script. This looks better to me that
>    just moving the entire librte_vhost into `drivers/`. I am not sure if
>    this is the most appropriate solution. I am looking forward to your
>    suggestions on this.

Moving the virtio-vhost-user code to a separate driver looks strange for me.
What is the purpose?

Exporting a lot of vhost internal structures will lead to a frequent API/ABI
breakages and will slow down accepting changes to releases in general.

It looks inconsistent to have 'trans_af_unix.c' in 'lib/librte_vhost/' and
'trans_virtio_vhost_user.c' in 'drivers/virtio_vhost_user/' because these
files should be similar in provided functionality, hence, should be located
in similar places.

> 
> 5. made use of the virtio PCI capabilities for the additional device
>    resources (doorbells, shared memory). This required changes in
>    virtio_pci.c and trans_virtio_vhost_user.c.
> 
> 6. [minor] changed some commit headlines to comply with
>    check-git-log.sh.
> 
> Please, have a look and let me know about your thoughts. Any
> reviews/pointers/suggestions are welcome.
> 
> Best regards,
> Nikos
> 
> [1] http://mails.dpdk.org/archives/dev/2018-January/088155.html
> 
> 
> Nikos Dragazis (23):
>   vhost: introduce vhost transport operations structure
>   vhost: move socket management code
>   vhost: move socket fd and un sockaddr
>   vhost: move vhost-user connection
>   vhost: move vhost-user reconnection
>   vhost: move vhost-user fdset
>   vhost: propagate vhost transport operations
>   vhost: use a single structure for the device state
>   vhost: extract socket I/O into transport
>   vhost: move slave request fd and lock
>   vhost: move mmap/munmap
>   vhost: move setup of the log memory region
>   vhost: remove main fd parameter from msg handlers
>   vhost: move postcopy live migration code
>   vhost: support registering additional vhost-user transports
>   drivers/virtio_vhost_user: add virtio PCI framework
>   drivers: add virtio-vhost-user transport
>   drivers/virtio_vhost_user: use additional device resources
>   vhost: add flag for choosing vhost-user transport
>   net/vhost: add virtio-vhost-user support
>   mk: link apps with virtio-vhost-user driver
>   config: add option for the virtio-vhost-user transport
>   usertools: add virtio-vhost-user devices to dpdk-devbind.py
> 
> Stefan Hajnoczi (5):
>   vhost: allocate per-socket transport state
>   vhost: move start server/client calls
>   vhost: add index field in vhost virtqueues
>   examples/vhost_scsi: add --socket-file argument
>   examples/vhost_scsi: add virtio-vhost-user support
> 
>  config/common_base                                 |    6 +
>  config/common_linux                                |    1 +
>  drivers/Makefile                                   |    5 +
>  drivers/net/vhost/rte_eth_vhost.c                  |   13 +
>  drivers/virtio_vhost_user/Makefile                 |   27 +
>  .../rte_virtio_vhost_user_version.map              |    4 +
>  .../virtio_vhost_user/trans_virtio_vhost_user.c    | 1077 +++++++++++++++++++
>  drivers/virtio_vhost_user/virtio_pci.c             |  520 ++++++++++
>  drivers/virtio_vhost_user/virtio_pci.h             |  289 ++++++
>  drivers/virtio_vhost_user/virtio_vhost_user.h      |   18 +
>  drivers/virtio_vhost_user/virtqueue.h              |  181 ++++
>  examples/vhost_scsi/vhost_scsi.c                   |  103 +-
>  lib/librte_vhost/Makefile                          |    4 +-
>  lib/librte_vhost/rte_vhost.h                       |    1 +
>  lib/librte_vhost/rte_vhost_version.map             |   11 +
>  lib/librte_vhost/socket.c                          |  685 +-----------
>  lib/librte_vhost/trans_af_unix.c                   | 1094 ++++++++++++++++++++
>  lib/librte_vhost/vhost.c                           |   22 +-
>  lib/librte_vhost/vhost.h                           |  298 +++++-
>  lib/librte_vhost/vhost_user.c                      |  474 ++-------
>  lib/librte_vhost/vhost_user.h                      |   10 +-
>  mk/rte.app.mk                                      |    6 +
>  usertools/dpdk-devbind.py                          |    7 +
>  23 files changed, 3764 insertions(+), 1092 deletions(-)
>  create mode 100644 drivers/virtio_vhost_user/Makefile
>  create mode 100644 drivers/virtio_vhost_user/rte_virtio_vhost_user_version.map
>  create mode 100644 drivers/virtio_vhost_user/trans_virtio_vhost_user.c
>  create mode 100644 drivers/virtio_vhost_user/virtio_pci.c
>  create mode 100644 drivers/virtio_vhost_user/virtio_pci.h
>  create mode 100644 drivers/virtio_vhost_user/virtio_vhost_user.h
>  create mode 100644 drivers/virtio_vhost_user/virtqueue.h
>  create mode 100644 lib/librte_vhost/trans_af_unix.c
> 

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] DPDK Techboard minutes of June 6
       [not found]     <VI1PR0401MB2541F07E6E640ED569918E6089E40@VI1PR0401MB2541.eurprd04.prod.outlook.com>
@ 2019-06-20  8:33  4% ` Hemant Agrawal
  0 siblings, 0 replies; 200+ results
From: Hemant Agrawal @ 2019-06-20  8:33 UTC (permalink / raw)
  To: dev; +Cc: dpdk-techboard

Meeting notes for the DPDK technical board meeting held on 2018-06-06

Attendees:
	- Bruce Richardson
	- Ferruh Yigit
	- Hemant Agrawal
	- Jerin Jacob
	- Maxime Coquelin
	- Olivier Matz
	- Stephen Hemminger
	- Thomas Monjalon

1) Techboard rep in DPDK Gov Board

- Stephen will be new tech board rep succeeding Maxime. Olivier gave it a pass. 

2) DPDK API Stability discussion

- A sub-group is working on how to improve ABI/API stability and will come with a proposal as update to versioning.html and stable.html. Sub-group consist of Ray, Bruce, Stephen and Kevin.
- Ray sent a proposal within sub-group for review. 
- There will be a status update in next TB meeting (June 19).
- Jerin suggested that API stability should not come at the cost of performance regression. 
- Ray is proposing a panel discussion on ABI Compatibility for DPDK Userspace. He will choose the panelists. 

3) discussion to extend Techboard membership
 -  proposed to discuss Techboard membership in 1 month time. 

4) Userspace summit CFP deadline over.
- Proposals are under review.

5) Next meeting will be on June 19 and Jerin will chair it

Thanks,
Hemant


^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch
@ 2019-06-20  7:25  2% Haiyue Wang
  2019-06-20 18:30  0% ` Andrew Rybchenko
  2019-06-20 18:35  0% ` Stephen Hemminger
  0 siblings, 2 replies; 200+ results
From: Haiyue Wang @ 2019-06-20  7:25 UTC (permalink / raw)
  To: dev; +Cc: Haiyue Wang

Generally speaking, the DEV_RX_OFFLOAD_xxx for RX offload capabilities
of a device is one-bit field definition, it has 64 different values at
most.

Nowdays the receiving queue of NIC has rich features not just checksum
offload, like it can extract the network protocol header fields to its
RX descriptors for quickly handling. But this kind of feature is not so
common, and it is hardware related. Normally, this can be done through
rte_devargs driver parameters, but the scope is per device. This is not
so nice for per queue design.

The per queue API 'rte_eth_rx_queue_setup' and data structure 'struct
rte_eth_rxconf' are stable now, and be common for all PMDs. For keeping
the ethdev API & ABI compatibility, and the application can make good
use of the NIC's specific features, reserving the most-significant bits
of RX offload seems an compromise method.

Then the PMDs redefine these bits as they want, all PMDs share the same
bit positions and expose their new definitions with the header file.

The experimental reserved bits number is 6 currently. Tt can be one-bit
for each features up to the the maximum number 6. It can also be some
bits encoding: e.g, 6 bits can stand for 63 maximum number of features.

We call these reserved bits as DEV_RX_OFFLOAD_PMD_SCRATCH. And the left
unused bits number is : 64 - 19 (currently defined) - 6 (PMD scartch) =
39.

This is not so nice for applications, they need to check PMD's driver
name for lookuping their DEV_RX_OFFLOAD_PMD_SCRATCH definitions. But it
is good for the applications to make use of the hardware compatibility.

Signed-off-by: Haiyue Wang <haiyue.wang@intel.com>
---
 app/test-pmd/cmdline.c         | 18 ++++++++++++------
 lib/librte_ethdev/rte_ethdev.c |  6 ++++++
 lib/librte_ethdev/rte_ethdev.h | 12 ++++++++++++
 3 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index d1e0d44..ffcc835 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -879,7 +879,8 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"ipv4_cksum|udp_cksum|tcp_cksum|tcp_lro|qinq_strip|"
 			"outer_ipv4_cksum|macsec_strip|header_split|"
 			"vlan_filter|vlan_extend|jumbo_frame|crc_strip|"
-			"scatter|timestamp|security|keep_crc on|off\n"
+			"scatter|timestamp|security|keep_crc|"
+			"pmd_scratch0|pmd_scratch1|pmd_scratch2|pmd_scratch3|pmd_scratch4|pmd_scratch5 on|off\n"
 			"     Enable or disable a per port Rx offloading"
 			" on all Rx queues of a port\n\n"
 
@@ -887,7 +888,8 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"ipv4_cksum|udp_cksum|tcp_cksum|tcp_lro|qinq_strip|"
 			"outer_ipv4_cksum|macsec_strip|header_split|"
 			"vlan_filter|vlan_extend|jumbo_frame|crc_strip|"
-			"scatter|timestamp|security|keep_crc on|off\n"
+			"scatter|timestamp|security|keep_crc|"
+			"pmd_scratch0|pmd_scratch1|pmd_scratch2|pmd_scratch3|pmd_scratch4|pmd_scratch5 on|off\n"
 			"    Enable or disable a per queue Rx offloading"
 			" only on a specific Rx queue\n\n"
 
@@ -17991,7 +17993,8 @@ cmdline_parse_token_string_t cmd_config_per_port_rx_offload_result_offload =
 		 offload, "vlan_strip#ipv4_cksum#udp_cksum#tcp_cksum#tcp_lro#"
 			   "qinq_strip#outer_ipv4_cksum#macsec_strip#"
 			   "header_split#vlan_filter#vlan_extend#jumbo_frame#"
-			   "crc_strip#scatter#timestamp#security#keep_crc");
+			   "crc_strip#scatter#timestamp#security#keep_crc#"
+			   "pmd_scratch0#pmd_scratch1#pmd_scratch2#pmd_scratch3#pmd_scratch4#pmd_scratch5");
 cmdline_parse_token_string_t cmd_config_per_port_rx_offload_result_on_off =
 	TOKEN_STRING_INITIALIZER
 		(struct cmd_config_per_port_rx_offload_result,
@@ -18067,7 +18070,8 @@ cmdline_parse_inst_t cmd_config_per_port_rx_offload = {
 	.help_str = "port config <port_id> rx_offload vlan_strip|ipv4_cksum|"
 		    "udp_cksum|tcp_cksum|tcp_lro|qinq_strip|outer_ipv4_cksum|"
 		    "macsec_strip|header_split|vlan_filter|vlan_extend|"
-		    "jumbo_frame|crc_strip|scatter|timestamp|security|keep_crc "
+		    "jumbo_frame|crc_strip|scatter|timestamp|security|keep_crc|"
+		    "pmd_scratch0|pmd_scratch1|pmd_scratch2|pmd_scratch3|pmd_scratch4|pmd_scratch5 "
 		    "on|off",
 	.tokens = {
 		(void *)&cmd_config_per_port_rx_offload_result_port,
@@ -18117,7 +18121,8 @@ cmdline_parse_token_string_t cmd_config_per_queue_rx_offload_result_offload =
 		 offload, "vlan_strip#ipv4_cksum#udp_cksum#tcp_cksum#tcp_lro#"
 			   "qinq_strip#outer_ipv4_cksum#macsec_strip#"
 			   "header_split#vlan_filter#vlan_extend#jumbo_frame#"
-			   "crc_strip#scatter#timestamp#security#keep_crc");
+			   "crc_strip#scatter#timestamp#security#keep_crc#"
+			   "pmd_scratch0#pmd_scratch1#pmd_scratch2#pmd_scratch3#pmd_scratch4#pmd_scratch5");
 cmdline_parse_token_string_t cmd_config_per_queue_rx_offload_result_on_off =
 	TOKEN_STRING_INITIALIZER
 		(struct cmd_config_per_queue_rx_offload_result,
@@ -18169,7 +18174,8 @@ cmdline_parse_inst_t cmd_config_per_queue_rx_offload = {
 		    "vlan_strip|ipv4_cksum|"
 		    "udp_cksum|tcp_cksum|tcp_lro|qinq_strip|outer_ipv4_cksum|"
 		    "macsec_strip|header_split|vlan_filter|vlan_extend|"
-		    "jumbo_frame|crc_strip|scatter|timestamp|security|keep_crc "
+		    "jumbo_frame|crc_strip|scatter|timestamp|security|keep_crc|"
+		    "pmd_scratch0|pmd_scratch1|pmd_scratch2|pmd_scratch3|pmd_scratch4|pmd_scratch5 "
 		    "on|off",
 	.tokens = {
 		(void *)&cmd_config_per_queue_rx_offload_result_port,
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 8ac3016..bc6a676 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -129,6 +129,12 @@ static const struct {
 	RTE_RX_OFFLOAD_BIT2STR(KEEP_CRC),
 	RTE_RX_OFFLOAD_BIT2STR(SCTP_CKSUM),
 	RTE_RX_OFFLOAD_BIT2STR(OUTER_UDP_CKSUM),
+	RTE_RX_OFFLOAD_BIT2STR(PMD_SCRATCH0),
+	RTE_RX_OFFLOAD_BIT2STR(PMD_SCRATCH1),
+	RTE_RX_OFFLOAD_BIT2STR(PMD_SCRATCH2),
+	RTE_RX_OFFLOAD_BIT2STR(PMD_SCRATCH3),
+	RTE_RX_OFFLOAD_BIT2STR(PMD_SCRATCH4),
+	RTE_RX_OFFLOAD_BIT2STR(PMD_SCRATCH5),
 };
 
 #undef RTE_RX_OFFLOAD_BIT2STR
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index 50c6936..45bac1c 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1011,6 +1011,12 @@ struct rte_eth_conf {
 #define DEV_RX_OFFLOAD_KEEP_CRC		0x00010000
 #define DEV_RX_OFFLOAD_SCTP_CKSUM	0x00020000
 #define DEV_RX_OFFLOAD_OUTER_UDP_CKSUM  0x00040000
+#define DEV_RX_OFFLOAD_PMD_SCRATCH0	(1ULL << 58) /* Defined by PMD */
+#define DEV_RX_OFFLOAD_PMD_SCRATCH1	(1ULL << 59) /* Defined by PMD */
+#define DEV_RX_OFFLOAD_PMD_SCRATCH2	(1ULL << 60) /* Defined by PMD */
+#define DEV_RX_OFFLOAD_PMD_SCRATCH3	(1ULL << 61) /* Defined by PMD */
+#define DEV_RX_OFFLOAD_PMD_SCRATCH4	(1ULL << 62) /* Defined by PMD */
+#define DEV_RX_OFFLOAD_PMD_SCRATCH5	(1ULL << 63) /* Defined by PMD */
 
 #define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \
 				 DEV_RX_OFFLOAD_UDP_CKSUM | \
@@ -1018,6 +1024,12 @@ struct rte_eth_conf {
 #define DEV_RX_OFFLOAD_VLAN (DEV_RX_OFFLOAD_VLAN_STRIP | \
 			     DEV_RX_OFFLOAD_VLAN_FILTER | \
 			     DEV_RX_OFFLOAD_VLAN_EXTEND)
+#define DEV_RX_OFFLOAD_PMD_SCRATCH (DEV_RX_OFFLOAD_PMD_SCRATCH0 | \
+				    DEV_RX_OFFLOAD_PMD_SCRATCH1 | \
+				    DEV_RX_OFFLOAD_PMD_SCRATCH2 | \
+				    DEV_RX_OFFLOAD_PMD_SCRATCH3 | \
+				    DEV_RX_OFFLOAD_PMD_SCRATCH4 | \
+				    DEV_RX_OFFLOAD_PMD_SCRATCH5)
 
 /*
  * If new Rx offload capabilities are defined, they also must be
-- 
2.7.4


^ permalink raw reply	[relevance 2%]

* [dpdk-dev] [PATCH v4 4/8] kni: drop unused fields
  @ 2019-06-19 18:59  4%   ` Stephen Hemminger
  0 siblings, 0 replies; 200+ results
From: Stephen Hemminger @ 2019-06-19 18:59 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

The kni net structure only exists in driver no API/ABI.
Several fields were either totally unused or set and never used.

The fields in dev_info do need to stay in the ABI but
kernel can ignore them.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>

kni: drop unused status element

Yet another ethtool leftover.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 kernel/linux/kni/kni_dev.h  | 5 -----
 kernel/linux/kni/kni_misc.c | 1 -
 2 files changed, 6 deletions(-)

diff --git a/kernel/linux/kni/kni_dev.h b/kernel/linux/kni/kni_dev.h
index 21e4b0d92368..f3e6c3ca4efa 100644
--- a/kernel/linux/kni/kni_dev.h
+++ b/kernel/linux/kni/kni_dev.h
@@ -39,8 +39,6 @@ struct kni_dev {
 	/* kni list */
 	struct list_head list;
 
-	int status;
-	uint16_t group_id;           /* Group ID of a group of KNI devices */
 	uint32_t core_id;            /* Core ID to bind */
 	char name[RTE_KNI_NAMESIZE]; /* Network device name */
 	struct task_struct *pthread;
@@ -79,9 +77,6 @@ struct kni_dev {
 	/* mbuf size */
 	uint32_t mbuf_size;
 
-	/* synchro for request processing */
-	unsigned long synchro;
-
 	/* buffers */
 	void *pa[MBUF_BURST_SZ];
 	void *va[MBUF_BURST_SZ];
diff --git a/kernel/linux/kni/kni_misc.c b/kernel/linux/kni/kni_misc.c
index 1fc5eeb9c8ca..b59cf24c2184 100644
--- a/kernel/linux/kni/kni_misc.c
+++ b/kernel/linux/kni/kni_misc.c
@@ -346,7 +346,6 @@ kni_ioctl_create(struct net *net, uint32_t ioctl_num,
 	kni = netdev_priv(net_dev);
 
 	kni->net_dev = net_dev;
-	kni->group_id = dev_info.group_id;
 	kni->core_id = dev_info.core_id;
 	strncpy(kni->name, dev_info.name, RTE_KNI_NAMESIZE);
 
-- 
2.20.1


^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH v3 4/8] kni: drop unused fields
  @ 2019-06-19 18:57  4%   ` Stephen Hemminger
  0 siblings, 0 replies; 200+ results
From: Stephen Hemminger @ 2019-06-19 18:57 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

The kni net structure only exists in driver no API/ABI.
Several fields were either totally unused or set and never used.

The fields in dev_info do need to stay in the ABI but
kernel can ignore them.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>

kni: drop unused status element

Yet another ethtool leftover.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 kernel/linux/kni/kni_dev.h  | 5 -----
 kernel/linux/kni/kni_misc.c | 1 -
 2 files changed, 6 deletions(-)

diff --git a/kernel/linux/kni/kni_dev.h b/kernel/linux/kni/kni_dev.h
index 21e4b0d92368..f3e6c3ca4efa 100644
--- a/kernel/linux/kni/kni_dev.h
+++ b/kernel/linux/kni/kni_dev.h
@@ -39,8 +39,6 @@ struct kni_dev {
 	/* kni list */
 	struct list_head list;
 
-	int status;
-	uint16_t group_id;           /* Group ID of a group of KNI devices */
 	uint32_t core_id;            /* Core ID to bind */
 	char name[RTE_KNI_NAMESIZE]; /* Network device name */
 	struct task_struct *pthread;
@@ -79,9 +77,6 @@ struct kni_dev {
 	/* mbuf size */
 	uint32_t mbuf_size;
 
-	/* synchro for request processing */
-	unsigned long synchro;
-
 	/* buffers */
 	void *pa[MBUF_BURST_SZ];
 	void *va[MBUF_BURST_SZ];
diff --git a/kernel/linux/kni/kni_misc.c b/kernel/linux/kni/kni_misc.c
index 1fc5eeb9c8ca..b59cf24c2184 100644
--- a/kernel/linux/kni/kni_misc.c
+++ b/kernel/linux/kni/kni_misc.c
@@ -346,7 +346,6 @@ kni_ioctl_create(struct net *net, uint32_t ioctl_num,
 	kni = netdev_priv(net_dev);
 
 	kni->net_dev = net_dev;
-	kni->group_id = dev_info.group_id;
 	kni->core_id = dev_info.core_id;
 	strncpy(kni->name, dev_info.name, RTE_KNI_NAMESIZE);
 
-- 
2.20.1


^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH 18/28] drivers/virtio_vhost_user: add virtio PCI framework
  @ 2019-06-19 15:14  2% ` Nikos Dragazis
       [not found]     ` <CGME20190620113240eucas1p22ca4faa64a36bbb7aec38a81298ade56@eucas1p2.samsung.com>
  1 sibling, 0 replies; 200+ results
From: Nikos Dragazis @ 2019-06-19 15:14 UTC (permalink / raw)
  To: dev
  Cc: Maxime Coquelin, Tiwei Bie, Zhihong Wang, Stefan Hajnoczi,
	Wei Wang, Stojaczyk Dariusz, Vangelis Koukis

The virtio-vhost-user transport requires a driver for the
virtio-vhost-user PCI device, hence it needs a virtio-pci driver.  There
is currently no librte_virtio API that we can use.

This commit is a hack that duplicates the virtio pci code from
drivers/net/ into drivers/virtio_vhost_user/.  A better solution would
be to extract the code cleanly from drivers/net/ and share it.  Or
perhaps we could backport SPDK's lib/virtio/.

drivers/virtio_vhost_user/ will host the virtio-vhost-user transport
implementation in the upcoming patches.

Signed-off-by: Nikos Dragazis <ndragazis@arrikto.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 drivers/virtio_vhost_user/virtio_pci.c | 504 +++++++++++++++++++++++++++++++++
 drivers/virtio_vhost_user/virtio_pci.h | 270 ++++++++++++++++++
 drivers/virtio_vhost_user/virtqueue.h  | 181 ++++++++++++
 3 files changed, 955 insertions(+)
 create mode 100644 drivers/virtio_vhost_user/virtio_pci.c
 create mode 100644 drivers/virtio_vhost_user/virtio_pci.h
 create mode 100644 drivers/virtio_vhost_user/virtqueue.h

diff --git a/drivers/virtio_vhost_user/virtio_pci.c b/drivers/virtio_vhost_user/virtio_pci.c
new file mode 100644
index 0000000..9c2c981
--- /dev/null
+++ b/drivers/virtio_vhost_user/virtio_pci.c
@@ -0,0 +1,504 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+#include <stdint.h>
+
+/* XXX This file is based on drivers/net/virtio/virtio_pci.c.  It would be
+ * better to create a shared rte_virtio library instead of duplicating this
+ * code.
+ */
+
+#ifdef RTE_EXEC_ENV_LINUX
+ #include <dirent.h>
+ #include <fcntl.h>
+#endif
+
+#include <rte_io.h>
+#include <rte_bus.h>
+
+#include "virtio_pci.h"
+#include "virtqueue.h"
+
+/*
+ * Following macros are derived from linux/pci_regs.h, however,
+ * we can't simply include that header here, as there is no such
+ * file for non-Linux platform.
+ */
+#define PCI_CAPABILITY_LIST	0x34
+#define PCI_CAP_ID_VNDR		0x09
+#define PCI_CAP_ID_MSIX		0x11
+
+/*
+ * The remaining space is defined by each driver as the per-driver
+ * configuration space.
+ */
+#define VIRTIO_PCI_CONFIG(hw) \
+		(((hw)->use_msix == VIRTIO_MSIX_ENABLED) ? 24 : 20)
+
+static inline int
+check_vq_phys_addr_ok(struct virtqueue *vq)
+{
+	/* Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit,
+	 * and only accepts 32 bit page frame number.
+	 * Check if the allocated physical memory exceeds 16TB.
+	 */
+	if ((vq->vq_ring_mem + vq->vq_ring_size - 1) >>
+			(VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) {
+		RTE_LOG(ERR, VIRTIO_PCI_CONFIG, "vring address shouldn't be above 16TB!\n");
+		return 0;
+	}
+
+	return 1;
+}
+
+static inline void
+io_write64_twopart(uint64_t val, uint32_t *lo, uint32_t *hi)
+{
+	rte_write32(val & ((1ULL << 32) - 1), lo);
+	rte_write32(val >> 32,		     hi);
+}
+
+static void
+modern_read_dev_config(struct virtio_hw *hw, size_t offset,
+		       void *dst, int length)
+{
+	int i;
+	uint8_t *p;
+	uint8_t old_gen, new_gen;
+
+	do {
+		old_gen = rte_read8(&hw->common_cfg->config_generation);
+
+		p = dst;
+		for (i = 0;  i < length; i++)
+			*p++ = rte_read8((uint8_t *)hw->dev_cfg + offset + i);
+
+		new_gen = rte_read8(&hw->common_cfg->config_generation);
+	} while (old_gen != new_gen);
+}
+
+static void
+modern_write_dev_config(struct virtio_hw *hw, size_t offset,
+			const void *src, int length)
+{
+	int i;
+	const uint8_t *p = src;
+
+	for (i = 0;  i < length; i++)
+		rte_write8((*p++), (((uint8_t *)hw->dev_cfg) + offset + i));
+}
+
+static uint64_t
+modern_get_features(struct virtio_hw *hw)
+{
+	uint32_t features_lo, features_hi;
+
+	rte_write32(0, &hw->common_cfg->device_feature_select);
+	features_lo = rte_read32(&hw->common_cfg->device_feature);
+
+	rte_write32(1, &hw->common_cfg->device_feature_select);
+	features_hi = rte_read32(&hw->common_cfg->device_feature);
+
+	return ((uint64_t)features_hi << 32) | features_lo;
+}
+
+static void
+modern_set_features(struct virtio_hw *hw, uint64_t features)
+{
+	rte_write32(0, &hw->common_cfg->guest_feature_select);
+	rte_write32(features & ((1ULL << 32) - 1),
+		    &hw->common_cfg->guest_feature);
+
+	rte_write32(1, &hw->common_cfg->guest_feature_select);
+	rte_write32(features >> 32,
+		    &hw->common_cfg->guest_feature);
+}
+
+static uint8_t
+modern_get_status(struct virtio_hw *hw)
+{
+	return rte_read8(&hw->common_cfg->device_status);
+}
+
+static void
+modern_set_status(struct virtio_hw *hw, uint8_t status)
+{
+	rte_write8(status, &hw->common_cfg->device_status);
+}
+
+static void
+modern_reset(struct virtio_hw *hw)
+{
+	modern_set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
+	modern_get_status(hw);
+}
+
+static uint8_t
+modern_get_isr(struct virtio_hw *hw)
+{
+	return rte_read8(hw->isr);
+}
+
+static uint16_t
+modern_set_config_irq(struct virtio_hw *hw, uint16_t vec)
+{
+	rte_write16(vec, &hw->common_cfg->msix_config);
+	return rte_read16(&hw->common_cfg->msix_config);
+}
+
+static uint16_t
+modern_set_queue_irq(struct virtio_hw *hw, struct virtqueue *vq, uint16_t vec)
+{
+	rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select);
+	rte_write16(vec, &hw->common_cfg->queue_msix_vector);
+	return rte_read16(&hw->common_cfg->queue_msix_vector);
+}
+
+static uint16_t
+modern_get_queue_num(struct virtio_hw *hw, uint16_t queue_id)
+{
+	rte_write16(queue_id, &hw->common_cfg->queue_select);
+	return rte_read16(&hw->common_cfg->queue_size);
+}
+
+static int
+modern_setup_queue(struct virtio_hw *hw, struct virtqueue *vq)
+{
+	uint64_t desc_addr, avail_addr, used_addr;
+	uint16_t notify_off;
+
+	if (!check_vq_phys_addr_ok(vq))
+		return -1;
+
+	desc_addr = vq->vq_ring_mem;
+	avail_addr = desc_addr + vq->vq_nentries * sizeof(struct vring_desc);
+	used_addr = RTE_ALIGN_CEIL(avail_addr + offsetof(struct vring_avail,
+							 ring[vq->vq_nentries]),
+				   VIRTIO_PCI_VRING_ALIGN);
+
+	rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select);
+
+	io_write64_twopart(desc_addr, &hw->common_cfg->queue_desc_lo,
+				      &hw->common_cfg->queue_desc_hi);
+	io_write64_twopart(avail_addr, &hw->common_cfg->queue_avail_lo,
+				       &hw->common_cfg->queue_avail_hi);
+	io_write64_twopart(used_addr, &hw->common_cfg->queue_used_lo,
+				      &hw->common_cfg->queue_used_hi);
+
+	notify_off = rte_read16(&hw->common_cfg->queue_notify_off);
+	vq->notify_addr = (void *)((uint8_t *)hw->notify_base +
+				notify_off * hw->notify_off_multiplier);
+
+	rte_write16(1, &hw->common_cfg->queue_enable);
+
+	RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG, "queue %u addresses:\n", vq->vq_queue_index);
+	RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG, "\t desc_addr: %" PRIx64 "\n", desc_addr);
+	RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG, "\t aval_addr: %" PRIx64 "\n", avail_addr);
+	RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG, "\t used_addr: %" PRIx64 "\n", used_addr);
+	RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG, "\t notify addr: %p (notify offset: %u)\n",
+		vq->notify_addr, notify_off);
+
+	return 0;
+}
+
+static void
+modern_del_queue(struct virtio_hw *hw, struct virtqueue *vq)
+{
+	rte_write16(vq->vq_queue_index, &hw->common_cfg->queue_select);
+
+	io_write64_twopart(0, &hw->common_cfg->queue_desc_lo,
+				  &hw->common_cfg->queue_desc_hi);
+	io_write64_twopart(0, &hw->common_cfg->queue_avail_lo,
+				  &hw->common_cfg->queue_avail_hi);
+	io_write64_twopart(0, &hw->common_cfg->queue_used_lo,
+				  &hw->common_cfg->queue_used_hi);
+
+	rte_write16(0, &hw->common_cfg->queue_enable);
+}
+
+static void
+modern_notify_queue(struct virtio_hw *hw __rte_unused, struct virtqueue *vq)
+{
+	rte_write16(vq->vq_queue_index, vq->notify_addr);
+}
+
+const struct virtio_pci_ops virtio_pci_modern_ops = {
+	.read_dev_cfg	= modern_read_dev_config,
+	.write_dev_cfg	= modern_write_dev_config,
+	.reset		= modern_reset,
+	.get_status	= modern_get_status,
+	.set_status	= modern_set_status,
+	.get_features	= modern_get_features,
+	.set_features	= modern_set_features,
+	.get_isr	= modern_get_isr,
+	.set_config_irq	= modern_set_config_irq,
+	.set_queue_irq  = modern_set_queue_irq,
+	.get_queue_num	= modern_get_queue_num,
+	.setup_queue	= modern_setup_queue,
+	.del_queue	= modern_del_queue,
+	.notify_queue	= modern_notify_queue,
+};
+
+
+void
+virtio_pci_read_dev_config(struct virtio_hw *hw, size_t offset,
+		      void *dst, int length)
+{
+	VTPCI_OPS(hw)->read_dev_cfg(hw, offset, dst, length);
+}
+
+void
+virtio_pci_write_dev_config(struct virtio_hw *hw, size_t offset,
+		       const void *src, int length)
+{
+	VTPCI_OPS(hw)->write_dev_cfg(hw, offset, src, length);
+}
+
+uint64_t
+virtio_pci_negotiate_features(struct virtio_hw *hw, uint64_t host_features)
+{
+	uint64_t features;
+
+	/*
+	 * Limit negotiated features to what the driver, virtqueue, and
+	 * host all support.
+	 */
+	features = host_features & hw->guest_features;
+	VTPCI_OPS(hw)->set_features(hw, features);
+
+	return features;
+}
+
+void
+virtio_pci_reset(struct virtio_hw *hw)
+{
+	VTPCI_OPS(hw)->set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
+	/* flush status write */
+	VTPCI_OPS(hw)->get_status(hw);
+}
+
+void
+virtio_pci_reinit_complete(struct virtio_hw *hw)
+{
+	virtio_pci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK);
+}
+
+void
+virtio_pci_set_status(struct virtio_hw *hw, uint8_t status)
+{
+	if (status != VIRTIO_CONFIG_STATUS_RESET)
+		status |= VTPCI_OPS(hw)->get_status(hw);
+
+	VTPCI_OPS(hw)->set_status(hw, status);
+}
+
+uint8_t
+virtio_pci_get_status(struct virtio_hw *hw)
+{
+	return VTPCI_OPS(hw)->get_status(hw);
+}
+
+uint8_t
+virtio_pci_isr(struct virtio_hw *hw)
+{
+	return VTPCI_OPS(hw)->get_isr(hw);
+}
+
+static void *
+get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap)
+{
+	uint8_t  bar    = cap->bar;
+	uint32_t length = cap->length;
+	uint32_t offset = cap->offset;
+	uint8_t *base;
+
+	if (bar >= PCI_MAX_RESOURCE) {
+		RTE_LOG(ERR, VIRTIO_PCI_CONFIG, "invalid bar: %u\n", bar);
+		return NULL;
+	}
+
+	if (offset + length < offset) {
+		RTE_LOG(ERR, VIRTIO_PCI_CONFIG, "offset(%u) + length(%u) overflows\n",
+			offset, length);
+		return NULL;
+	}
+
+	if (offset + length > dev->mem_resource[bar].len) {
+		RTE_LOG(ERR, VIRTIO_PCI_CONFIG,
+			"invalid cap: overflows bar space: %u > %" PRIu64 "\n",
+			offset + length, dev->mem_resource[bar].len);
+		return NULL;
+	}
+
+	base = dev->mem_resource[bar].addr;
+	if (base == NULL) {
+		RTE_LOG(ERR, VIRTIO_PCI_CONFIG, "bar %u base addr is NULL\n", bar);
+		return NULL;
+	}
+
+	return base + offset;
+}
+
+#define PCI_MSIX_ENABLE 0x8000
+
+static int
+virtio_read_caps(struct rte_pci_device *dev, struct virtio_hw *hw)
+{
+	uint8_t pos;
+	struct virtio_pci_cap cap;
+	int ret;
+
+	if (rte_pci_map_device(dev)) {
+		RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG, "failed to map pci device!\n");
+		return -1;
+	}
+
+	ret = rte_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST);
+	if (ret < 0) {
+		RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG, "failed to read pci capability list\n");
+		return -1;
+	}
+
+	while (pos) {
+		ret = rte_pci_read_config(dev, &cap, sizeof(cap), pos);
+		if (ret < 0) {
+			RTE_LOG(ERR, VIRTIO_PCI_CONFIG,
+				"failed to read pci cap at pos: %x\n", pos);
+			break;
+		}
+
+		if (cap.cap_vndr == PCI_CAP_ID_MSIX) {
+			/* Transitional devices would also have this capability,
+			 * that's why we also check if msix is enabled.
+			 * 1st byte is cap ID; 2nd byte is the position of next
+			 * cap; next two bytes are the flags.
+			 */
+			uint16_t flags = ((uint16_t *)&cap)[1];
+
+			if (flags & PCI_MSIX_ENABLE)
+				hw->use_msix = VIRTIO_MSIX_ENABLED;
+			else
+				hw->use_msix = VIRTIO_MSIX_DISABLED;
+		}
+
+		if (cap.cap_vndr != PCI_CAP_ID_VNDR) {
+			RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG,
+				"[%2x] skipping non VNDR cap id: %02x\n",
+				pos, cap.cap_vndr);
+			goto next;
+		}
+
+		RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG,
+			"[%2x] cfg type: %u, bar: %u, offset: %04x, len: %u\n",
+			pos, cap.cfg_type, cap.bar, cap.offset, cap.length);
+
+		switch (cap.cfg_type) {
+		case VIRTIO_PCI_CAP_COMMON_CFG:
+			hw->common_cfg = get_cfg_addr(dev, &cap);
+			break;
+		case VIRTIO_PCI_CAP_NOTIFY_CFG:
+			rte_pci_read_config(dev, &hw->notify_off_multiplier,
+					4, pos + sizeof(cap));
+			hw->notify_base = get_cfg_addr(dev, &cap);
+			break;
+		case VIRTIO_PCI_CAP_DEVICE_CFG:
+			hw->dev_cfg = get_cfg_addr(dev, &cap);
+			break;
+		case VIRTIO_PCI_CAP_ISR_CFG:
+			hw->isr = get_cfg_addr(dev, &cap);
+			break;
+		}
+
+next:
+		pos = cap.cap_next;
+	}
+
+	if (hw->common_cfg == NULL || hw->notify_base == NULL ||
+	    hw->dev_cfg == NULL    || hw->isr == NULL) {
+		RTE_LOG(INFO, VIRTIO_PCI_CONFIG, "no modern virtio pci device found.\n");
+		return -1;
+	}
+
+	RTE_LOG(INFO, VIRTIO_PCI_CONFIG, "found modern virtio pci device.\n");
+
+	RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG, "common cfg mapped at: %p\n", hw->common_cfg);
+	RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG, "device cfg mapped at: %p\n", hw->dev_cfg);
+	RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG, "isr cfg mapped at: %p\n", hw->isr);
+	RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG, "notify base: %p, notify off multiplier: %u\n",
+		hw->notify_base, hw->notify_off_multiplier);
+
+	return 0;
+}
+
+struct virtio_hw_internal virtio_pci_hw_internal[8];
+
+/*
+ * Return -1:
+ *   if there is error mapping with VFIO/UIO.
+ *   if port map error when driver type is KDRV_NONE.
+ *   if whitelisted but driver type is KDRV_UNKNOWN.
+ * Return 1 if kernel driver is managing the device.
+ * Return 0 on success.
+ */
+int
+virtio_pci_init(struct rte_pci_device *dev, struct virtio_hw *hw)
+{
+	static size_t internal_id;
+
+	if (internal_id >=
+	    sizeof(virtio_pci_hw_internal) / sizeof(*virtio_pci_hw_internal)) {
+		RTE_LOG(INFO, VIRTIO_PCI_CONFIG, "too many virtio pci devices.\n");
+		return -1;
+	}
+
+	/*
+	 * Try if we can succeed reading virtio pci caps, which exists
+	 * only on modern pci device.
+	 */
+	if (virtio_read_caps(dev, hw) != 0) {
+		RTE_LOG(INFO, VIRTIO_PCI_CONFIG, "legacy virtio pci is not supported.\n");
+		return -1;
+	}
+
+	RTE_LOG(INFO, VIRTIO_PCI_CONFIG, "modern virtio pci detected.\n");
+	hw->internal_id = internal_id++;
+	virtio_pci_hw_internal[hw->internal_id].vtpci_ops =
+		&virtio_pci_modern_ops;
+	return 0;
+}
+
+enum virtio_msix_status
+virtio_pci_msix_detect(struct rte_pci_device *dev)
+{
+	uint8_t pos;
+	struct virtio_pci_cap cap;
+	int ret;
+
+	ret = rte_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST);
+	if (ret < 0) {
+		RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG, "failed to read pci capability list\n");
+		return VIRTIO_MSIX_NONE;
+	}
+
+	while (pos) {
+		ret = rte_pci_read_config(dev, &cap, sizeof(cap), pos);
+		if (ret < 0) {
+			RTE_LOG(ERR, VIRTIO_PCI_CONFIG,
+				"failed to read pci cap at pos: %x\n", pos);
+			break;
+		}
+
+		if (cap.cap_vndr == PCI_CAP_ID_MSIX) {
+			uint16_t flags = ((uint16_t *)&cap)[1];
+
+			if (flags & PCI_MSIX_ENABLE)
+				return VIRTIO_MSIX_ENABLED;
+			else
+				return VIRTIO_MSIX_DISABLED;
+		}
+
+		pos = cap.cap_next;
+	}
+
+	return VIRTIO_MSIX_NONE;
+}
diff --git a/drivers/virtio_vhost_user/virtio_pci.h b/drivers/virtio_vhost_user/virtio_pci.h
new file mode 100644
index 0000000..018e0b7
--- /dev/null
+++ b/drivers/virtio_vhost_user/virtio_pci.h
@@ -0,0 +1,270 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+/* XXX This file is based on drivers/net/virtio/virtio_pci.h.  It would be
+ * better to create a shared rte_virtio library instead of duplicating this
+ * code.
+ */
+
+#ifndef _VIRTIO_PCI_H_
+#define _VIRTIO_PCI_H_
+
+#include <stdint.h>
+
+#include <rte_log.h>
+#include <rte_pci.h>
+#include <rte_bus_pci.h>
+#include <rte_spinlock.h>
+
+/* Macros for printing using RTE_LOG */
+#define RTE_LOGTYPE_VIRTIO_PCI_CONFIG RTE_LOGTYPE_USER2
+
+struct virtqueue;
+
+/* VirtIO PCI vendor/device ID. */
+#define VIRTIO_PCI_VENDORID     0x1AF4
+#define VIRTIO_PCI_LEGACY_DEVICEID_VHOST_USER 0x1017
+#define VIRTIO_PCI_MODERN_DEVICEID_VHOST_USER 0x1058
+
+/* VirtIO ABI version, this must match exactly. */
+#define VIRTIO_PCI_ABI_VERSION 0
+
+/*
+ * VirtIO Header, located in BAR 0.
+ */
+#define VIRTIO_PCI_HOST_FEATURES  0  /* host's supported features (32bit, RO)*/
+#define VIRTIO_PCI_GUEST_FEATURES 4  /* guest's supported features (32, RW) */
+#define VIRTIO_PCI_QUEUE_PFN      8  /* physical address of VQ (32, RW) */
+#define VIRTIO_PCI_QUEUE_NUM      12 /* number of ring entries (16, RO) */
+#define VIRTIO_PCI_QUEUE_SEL      14 /* current VQ selection (16, RW) */
+#define VIRTIO_PCI_QUEUE_NOTIFY   16 /* notify host regarding VQ (16, RW) */
+#define VIRTIO_PCI_STATUS         18 /* device status register (8, RW) */
+#define VIRTIO_PCI_ISR		  19 /* interrupt status register, reading
+				      * also clears the register (8, RO) */
+/* Only if MSIX is enabled: */
+#define VIRTIO_MSI_CONFIG_VECTOR  20 /* configuration change vector (16, RW) */
+#define VIRTIO_MSI_QUEUE_VECTOR	  22 /* vector for selected VQ notifications
+				      (16, RW) */
+
+/* The bit of the ISR which indicates a device has an interrupt. */
+#define VIRTIO_PCI_ISR_INTR   0x1
+/* The bit of the ISR which indicates a device configuration change. */
+#define VIRTIO_PCI_ISR_CONFIG 0x2
+/* Vector value used to disable MSI for queue. */
+#define VIRTIO_MSI_NO_VECTOR 0xFFFF
+
+/* VirtIO device IDs. */
+#define VIRTIO_ID_VHOST_USER  0x18
+
+/* Status byte for guest to report progress. */
+#define VIRTIO_CONFIG_STATUS_RESET     0x00
+#define VIRTIO_CONFIG_STATUS_ACK       0x01
+#define VIRTIO_CONFIG_STATUS_DRIVER    0x02
+#define VIRTIO_CONFIG_STATUS_DRIVER_OK 0x04
+#define VIRTIO_CONFIG_STATUS_FEATURES_OK 0x08
+#define VIRTIO_CONFIG_STATUS_FAILED    0x80
+
+/*
+ * Each virtqueue indirect descriptor list must be physically contiguous.
+ * To allow us to malloc(9) each list individually, limit the number
+ * supported to what will fit in one page. With 4KB pages, this is a limit
+ * of 256 descriptors. If there is ever a need for more, we can switch to
+ * contigmalloc(9) for the larger allocations, similar to what
+ * bus_dmamem_alloc(9) does.
+ *
+ * Note the sizeof(struct vring_desc) is 16 bytes.
+ */
+#define VIRTIO_MAX_INDIRECT ((int) (PAGE_SIZE / 16))
+
+/* Do we get callbacks when the ring is completely used, even if we've
+ * suppressed them? */
+#define VIRTIO_F_NOTIFY_ON_EMPTY	24
+
+/* Can the device handle any descriptor layout? */
+#define VIRTIO_F_ANY_LAYOUT		27
+
+/* We support indirect buffer descriptors */
+#define VIRTIO_RING_F_INDIRECT_DESC	28
+
+#define VIRTIO_F_VERSION_1		32
+#define VIRTIO_F_IOMMU_PLATFORM	33
+
+/*
+ * Some VirtIO feature bits (currently bits 28 through 31) are
+ * reserved for the transport being used (eg. virtio_ring), the
+ * rest are per-device feature bits.
+ */
+#define VIRTIO_TRANSPORT_F_START 28
+
+#ifndef VIRTIO_TRANSPORT_F_END
+#define VIRTIO_TRANSPORT_F_END   34
+#endif
+
+/* The Guest publishes the used index for which it expects an interrupt
+ * at the end of the avail ring. Host should ignore the avail->flags field. */
+/* The Host publishes the avail index for which it expects a kick
+ * at the end of the used ring. Guest should ignore the used->flags field. */
+#define VIRTIO_RING_F_EVENT_IDX		29
+
+/* Common configuration */
+#define VIRTIO_PCI_CAP_COMMON_CFG	1
+/* Notifications */
+#define VIRTIO_PCI_CAP_NOTIFY_CFG	2
+/* ISR Status */
+#define VIRTIO_PCI_CAP_ISR_CFG		3
+/* Device specific configuration */
+#define VIRTIO_PCI_CAP_DEVICE_CFG	4
+/* PCI configuration access */
+#define VIRTIO_PCI_CAP_PCI_CFG		5
+
+/* This is the PCI capability header: */
+struct virtio_pci_cap {
+	uint8_t cap_vndr;		/* Generic PCI field: PCI_CAP_ID_VNDR */
+	uint8_t cap_next;		/* Generic PCI field: next ptr. */
+	uint8_t cap_len;		/* Generic PCI field: capability length */
+	uint8_t cfg_type;		/* Identifies the structure. */
+	uint8_t bar;			/* Where to find it. */
+	uint8_t padding[3];		/* Pad to full dword. */
+	uint32_t offset;		/* Offset within bar. */
+	uint32_t length;		/* Length of the structure, in bytes. */
+};
+
+struct virtio_pci_notify_cap {
+	struct virtio_pci_cap cap;
+	uint32_t notify_off_multiplier;	/* Multiplier for queue_notify_off. */
+};
+
+/* Fields in VIRTIO_PCI_CAP_COMMON_CFG: */
+struct virtio_pci_common_cfg {
+	/* About the whole device. */
+	uint32_t device_feature_select;	/* read-write */
+	uint32_t device_feature;	/* read-only */
+	uint32_t guest_feature_select;	/* read-write */
+	uint32_t guest_feature;		/* read-write */
+	uint16_t msix_config;		/* read-write */
+	uint16_t num_queues;		/* read-only */
+	uint8_t device_status;		/* read-write */
+	uint8_t config_generation;	/* read-only */
+
+	/* About a specific virtqueue. */
+	uint16_t queue_select;		/* read-write */
+	uint16_t queue_size;		/* read-write, power of 2. */
+	uint16_t queue_msix_vector;	/* read-write */
+	uint16_t queue_enable;		/* read-write */
+	uint16_t queue_notify_off;	/* read-only */
+	uint32_t queue_desc_lo;		/* read-write */
+	uint32_t queue_desc_hi;		/* read-write */
+	uint32_t queue_avail_lo;	/* read-write */
+	uint32_t queue_avail_hi;	/* read-write */
+	uint32_t queue_used_lo;		/* read-write */
+	uint32_t queue_used_hi;		/* read-write */
+};
+
+struct virtio_hw;
+
+struct virtio_pci_ops {
+	void (*read_dev_cfg)(struct virtio_hw *hw, size_t offset,
+			     void *dst, int len);
+	void (*write_dev_cfg)(struct virtio_hw *hw, size_t offset,
+			      const void *src, int len);
+	void (*reset)(struct virtio_hw *hw);
+
+	uint8_t (*get_status)(struct virtio_hw *hw);
+	void    (*set_status)(struct virtio_hw *hw, uint8_t status);
+
+	uint64_t (*get_features)(struct virtio_hw *hw);
+	void     (*set_features)(struct virtio_hw *hw, uint64_t features);
+
+	uint8_t (*get_isr)(struct virtio_hw *hw);
+
+	uint16_t (*set_config_irq)(struct virtio_hw *hw, uint16_t vec);
+
+	uint16_t (*set_queue_irq)(struct virtio_hw *hw, struct virtqueue *vq,
+			uint16_t vec);
+
+	uint16_t (*get_queue_num)(struct virtio_hw *hw, uint16_t queue_id);
+	int (*setup_queue)(struct virtio_hw *hw, struct virtqueue *vq);
+	void (*del_queue)(struct virtio_hw *hw, struct virtqueue *vq);
+	void (*notify_queue)(struct virtio_hw *hw, struct virtqueue *vq);
+};
+
+struct virtio_hw {
+	uint64_t    guest_features;
+	uint32_t    max_queue_pairs;
+	uint16_t    started;
+	uint8_t	    use_msix;
+	uint16_t    internal_id;
+	uint32_t    notify_off_multiplier;
+	uint8_t     *isr;
+	uint16_t    *notify_base;
+	struct virtio_pci_common_cfg *common_cfg;
+	void	    *dev_cfg;
+	/*
+	 * App management thread and virtio interrupt handler thread
+	 * both can change device state, this lock is meant to avoid
+	 * such a contention.
+	 */
+	rte_spinlock_t state_lock;
+
+	struct virtqueue **vqs;
+};
+
+/*
+ * While virtio_hw is stored in shared memory, this structure stores
+ * some infos that may vary in the multiple process model locally.
+ * For example, the vtpci_ops pointer.
+ */
+struct virtio_hw_internal {
+	const struct virtio_pci_ops *vtpci_ops;
+};
+
+#define VTPCI_OPS(hw)	(virtio_pci_hw_internal[(hw)->internal_id].vtpci_ops)
+
+extern struct virtio_hw_internal virtio_pci_hw_internal[8];
+
+/*
+ * How many bits to shift physical queue address written to QUEUE_PFN.
+ * 12 is historical, and due to x86 page size.
+ */
+#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12
+
+/* The alignment to use between consumer and producer parts of vring. */
+#define VIRTIO_PCI_VRING_ALIGN 4096
+
+enum virtio_msix_status {
+	VIRTIO_MSIX_NONE = 0,
+	VIRTIO_MSIX_DISABLED = 1,
+	VIRTIO_MSIX_ENABLED = 2
+};
+
+static inline int
+virtio_pci_with_feature(struct virtio_hw *hw, uint64_t bit)
+{
+	return (hw->guest_features & (1ULL << bit)) != 0;
+}
+
+/*
+ * Function declaration from virtio_pci.c
+ */
+int virtio_pci_init(struct rte_pci_device *dev, struct virtio_hw *hw);
+void virtio_pci_reset(struct virtio_hw *);
+
+void virtio_pci_reinit_complete(struct virtio_hw *);
+
+uint8_t virtio_pci_get_status(struct virtio_hw *);
+void virtio_pci_set_status(struct virtio_hw *, uint8_t);
+
+uint64_t virtio_pci_negotiate_features(struct virtio_hw *, uint64_t);
+
+void virtio_pci_write_dev_config(struct virtio_hw *, size_t, const void *, int);
+
+void virtio_pci_read_dev_config(struct virtio_hw *, size_t, void *, int);
+
+uint8_t virtio_pci_isr(struct virtio_hw *);
+
+enum virtio_msix_status virtio_pci_msix_detect(struct rte_pci_device *dev);
+
+extern const struct virtio_pci_ops virtio_pci_modern_ops;
+
+#endif /* _VIRTIO_PCI_H_ */
diff --git a/drivers/virtio_vhost_user/virtqueue.h b/drivers/virtio_vhost_user/virtqueue.h
new file mode 100644
index 0000000..e2ac78e
--- /dev/null
+++ b/drivers/virtio_vhost_user/virtqueue.h
@@ -0,0 +1,181 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+/* XXX This file is based on drivers/net/virtio/virtqueue.h.  It would be
+ * better to create a shared rte_virtio library instead of duplicating this
+ * code.
+ */
+
+#ifndef _VIRTQUEUE_H_
+#define _VIRTQUEUE_H_
+
+#include <stdint.h>
+#include <linux/virtio_ring.h>
+
+#include <rte_atomic.h>
+#include <rte_memory.h>
+#include <rte_mempool.h>
+
+#include "virtio_pci.h"
+
+/*
+ * Per virtio_config.h in Linux.
+ *     For virtio_pci on SMP, we don't need to order with respect to MMIO
+ *     accesses through relaxed memory I/O windows, so smp_mb() et al are
+ *     sufficient.
+ *
+ */
+#define virtio_mb()	rte_smp_mb()
+#define virtio_rmb()	rte_smp_rmb()
+#define virtio_wmb()	rte_smp_wmb()
+
+#define VIRTQUEUE_MAX_NAME_SZ 32
+
+/**
+ * The maximum virtqueue size is 2^15. Use that value as the end of
+ * descriptor chain terminator since it will never be a valid index
+ * in the descriptor table. This is used to verify we are correctly
+ * handling vq_free_cnt.
+ */
+#define VQ_RING_DESC_CHAIN_END 32768
+
+struct vq_desc_extra {
+	void *cookie;
+	uint16_t ndescs;
+};
+
+struct virtqueue {
+	struct virtio_hw  *hw; /**< virtio_hw structure pointer. */
+	struct vring vq_ring;  /**< vring keeping desc, used and avail */
+	/**
+	 * Last consumed descriptor in the used table,
+	 * trails vq_ring.used->idx.
+	 */
+	uint16_t vq_used_cons_idx;
+	uint16_t vq_nentries;  /**< vring desc numbers */
+	uint16_t vq_free_cnt;  /**< num of desc available */
+	uint16_t vq_avail_idx; /**< sync until needed */
+	uint16_t vq_free_thresh; /**< free threshold */
+
+	void *vq_ring_virt_mem;  /**< linear address of vring*/
+	unsigned int vq_ring_size;
+
+	rte_iova_t vq_ring_mem; /**< physical address of vring */
+
+	const struct rte_memzone *mz; /**< memzone backing vring */
+
+	/**
+	 * Head of the free chain in the descriptor table. If
+	 * there are no free descriptors, this will be set to
+	 * VQ_RING_DESC_CHAIN_END.
+	 */
+	uint16_t  vq_desc_head_idx;
+	uint16_t  vq_desc_tail_idx;
+	uint16_t  vq_queue_index;   /**< PCI queue index */
+	uint16_t  *notify_addr;
+	struct vq_desc_extra vq_descx[0];
+};
+
+/* Chain all the descriptors in the ring with an END */
+static inline void
+vring_desc_init(struct vring_desc *dp, uint16_t n)
+{
+	uint16_t i;
+
+	for (i = 0; i < n - 1; i++)
+		dp[i].next = (uint16_t)(i + 1);
+	dp[i].next = VQ_RING_DESC_CHAIN_END;
+}
+
+/**
+ * Tell the backend not to interrupt us.
+ */
+static inline void
+virtqueue_disable_intr(struct virtqueue *vq)
+{
+	vq->vq_ring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
+}
+
+/**
+ * Tell the backend to interrupt us.
+ */
+static inline void
+virtqueue_enable_intr(struct virtqueue *vq)
+{
+	vq->vq_ring.avail->flags &= (~VRING_AVAIL_F_NO_INTERRUPT);
+}
+
+/**
+ *  Dump virtqueue internal structures, for debug purpose only.
+ */
+void virtqueue_dump(struct virtqueue *vq);
+
+static inline int
+virtqueue_full(const struct virtqueue *vq)
+{
+	return vq->vq_free_cnt == 0;
+}
+
+#define VIRTQUEUE_NUSED(vq) ((uint16_t)((vq)->vq_ring.used->idx - (vq)->vq_used_cons_idx))
+
+static inline void
+vq_update_avail_idx(struct virtqueue *vq)
+{
+	virtio_wmb();
+	vq->vq_ring.avail->idx = vq->vq_avail_idx;
+}
+
+static inline void
+vq_update_avail_ring(struct virtqueue *vq, uint16_t desc_idx)
+{
+	uint16_t avail_idx;
+	/*
+	 * Place the head of the descriptor chain into the next slot and make
+	 * it usable to the host. The chain is made available now rather than
+	 * deferring to virtqueue_notify() in the hopes that if the host is
+	 * currently running on another CPU, we can keep it processing the new
+	 * descriptor.
+	 */
+	avail_idx = (uint16_t)(vq->vq_avail_idx & (vq->vq_nentries - 1));
+	if (unlikely(vq->vq_ring.avail->ring[avail_idx] != desc_idx))
+		vq->vq_ring.avail->ring[avail_idx] = desc_idx;
+	vq->vq_avail_idx++;
+}
+
+static inline int
+virtqueue_kick_prepare(struct virtqueue *vq)
+{
+	return !(vq->vq_ring.used->flags & VRING_USED_F_NO_NOTIFY);
+}
+
+static inline void
+virtqueue_notify(struct virtqueue *vq)
+{
+	/*
+	 * Ensure updated avail->idx is visible to host.
+	 * For virtio on IA, the notificaiton is through io port operation
+	 * which is a serialization instruction itself.
+	 */
+	VTPCI_OPS(vq->hw)->notify_queue(vq->hw, vq);
+}
+
+#ifdef RTE_LIBRTE_VIRTIO_DEBUG_DUMP
+#define VIRTQUEUE_DUMP(vq) do { \
+	uint16_t used_idx, nused; \
+	used_idx = (vq)->vq_ring.used->idx; \
+	nused = (uint16_t)(used_idx - (vq)->vq_used_cons_idx); \
+	RTE_LOG(DEBUG, VIRTIO_PCI_CONFIG, \
+	  "VQ: - size=%d; free=%d; used=%d; desc_head_idx=%d;" \
+	  " avail.idx=%d; used_cons_idx=%d; used.idx=%d;" \
+	  " avail.flags=0x%x; used.flags=0x%x\n", \
+	  (vq)->vq_nentries, (vq)->vq_free_cnt, nused, \
+	  (vq)->vq_desc_head_idx, (vq)->vq_ring.avail->idx, \
+	  (vq)->vq_used_cons_idx, (vq)->vq_ring.used->idx, \
+	  (vq)->vq_ring.avail->flags, (vq)->vq_ring.used->flags); \
+} while (0)
+#else
+#define VIRTQUEUE_DUMP(vq) do { } while (0)
+#endif
+
+#endif /* _VIRTQUEUE_H_ */
-- 
2.7.4


^ permalink raw reply	[relevance 2%]

* Re: [dpdk-dev] [RFC 1/3] ethdev: extend flow metadata
  2019-06-11  0:06  0%       ` Yongseok Koh
@ 2019-06-19  9:05  0%         ` Andrew Rybchenko
  0 siblings, 0 replies; 200+ results
From: Andrew Rybchenko @ 2019-06-19  9:05 UTC (permalink / raw)
  To: Yongseok Koh
  Cc: Wang, Haiyue, Shahaf Shuler, Thomas Monjalon, Yigit, Ferruh,
	Adrien Mazarguil, olivier.matz, dev, Ananyev, Konstantin

On 11.06.2019 3:06, Yongseok Koh wrote:
> On Mon, Jun 10, 2019 at 10:20:28AM +0300, Andrew Rybchenko wrote:
>> On 6/10/19 6:19 AM, Wang, Haiyue wrote:
>>>> -----Original Message-----
>>>> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Andrew Rybchenko
>>>> Sent: Sunday, June 9, 2019 22:24
>>>> To: Yongseok Koh <yskoh@mellanox.com>; shahafs@mellanox.com; thomas@monjalon.net; Yigit, Ferruh
>>>> <ferruh.yigit@intel.com>; adrien.mazarguil@6wind.com; olivier.matz@6wind.com
>>>> Cc: dev@dpdk.org
>>>> Subject: Re: [dpdk-dev] [RFC 1/3] ethdev: extend flow metadata
>>>>
>>>> On 6/4/19 12:32 AM, Yongseok Koh wrote:
>>>>> Currently, metadata can be set on egress path via mbuf tx_meatadata field
>>>>> with PKT_TX_METADATA flag and RTE_FLOW_ITEM_TYPE_RX_META matches metadata.
>>>>>
>>>>> This patch extends the usability.
>>>>>
>>>>> 1) RTE_FLOW_ACTION_TYPE_SET_META
>>>>>
>>>>> When supporting multiple tables, Tx metadata can also be set by a rule and
>>>>> matched by another rule. This new action allows metadata to be set as a
>>>>> result of flow match.
>>>>>
>>>>> 2) Metadata on ingress
>>>>>
>>>>> There's also need to support metadata on packet Rx. Metadata can be set by
>>>>> SET_META action and matched by META item like Tx. The final value set by
>>>>> the action will be delivered to application via mbuf metadata field with
>>>>> PKT_RX_METADATA ol_flag.
>>>>>
>>>>> For this purpose, mbuf->tx_metadata is moved as a separate new field and
>>>>> renamed to 'metadata' to support both Rx and Tx metadata.
>>>>>
>>>>> For loopback/hairpin packet, metadata set on Rx/Tx may or may not be
>>>>> propagated to the other path depending on HW capability.
>>>>>
>>>>> Signed-off-by: Yongseok Koh <yskoh@mellanox.com>
>>>> There is a mark on Rx which is delivered to application in hash.fdir.hi.
>>>> Why do we need one more 32-bit value set by NIC and delivered to
>>>> application?
>>>> What is the difference between MARK and META on Rx?
>>>> When application should use MARK and when META?
>>>> Is there cases when both could be necessary?
>>>>
>>> In my understanding, MARK is FDIR related thing, META seems to be NIC
>>> specific. And we also need this kind of specific data field to export
>>> NIC's data to application.
>> I think it is better to avoid NIC vendor-specifics in motivation. I
>> understand
>> that it exists for you, but I think it is better to look at it from RTE flow
>> API
>> definition point of view: both are 32-bit (except endianess and I'm not sure
>> that I understand why meta is defined as big-endian since it is not a value
>> coming from or going to network in a packet, I'm sorry that I've missed it
>> on review that time), both may be set using action on Rx, both may be
>> matched using pattern item.
> Yes, MARK and META has the same characteristic on Rx path. Let me clarify why I
> picked this way.
>
> What if device has more bits to deliver to host? Currently, only 32-bit data can
> be delivered to user via MARK ID. Now we have more requests from users (OVS
> connection tracking) that want to see more information generated during flow
> match from the device. Let's say it is 64 bits and it may contain intermediate
> match results to keep track of multi-table match, to keep address of callback
> function to call, or so. I thought about extending the current MARK to 64-bit
> but I knew that we couldn't make more room in the first cacheline of mbuf where
> every vendor has their critical interest. And the FDIR has been there for a long
> time and has lots of use-cases in DPDK (not easy to break). This is why I'm
> suggesting to obtain another 32 bits in the second cacheline of the structure.
>
> Also, I thought about other scenario as well. Even though we have MARK item
> introduced lately, it isn't used by any PMD at all for now, meaning it might not
> be match-able on a certain device. What if there are two types registers on Rx
> and one is match-able and the other isn't? PMD can use META for match-able
> register while MARK is used for non-match-able register without supporting
> item match. If MARK simply becomes 64-bit just because it has the same
> characteristic in terms of rte_flow, only one of such registers can be used as
> we can't say only part of bits are match-able on the item. Instead of extending
> the MARK to 64 bits, I thought it would be better to give more flexibility by
> bundling it with Tx metadata, which can set by mbuf.

Thanks a lot for explanations. If the way is finally approved, priority
among META and MARK should be defined. I.e. if only one is supported
or only one may be match, it must be MARK. Otherwise, it will be too
complicated for applications to find out which one to use.
Is there any limitations on usage of MARK or META in transfer rules?
There is a lot of work on documentation in this area to make it usable.


> The actual issue we have may be how we can make it scalable? What if there's
> more need to carry more data from device? Well, IIRC, Olivier once suggested to
> put a pointer (like mbuf->userdata) to extend mbuf struct beyond two cachelines.
> But we still have some space left at the end.
>
>>>> Moreover, the third patch adds 32-bit tags which are not delivered to
>>>> application. May be META/MARK should be simply a kind of TAG (e.g. with
>>>> index 0 or marked using additional attribute) which is delivered to
>>>> application?
> Yes, TAG is a kind of transient device-internal data which isn't delivered to
> host. It would be a design choice. I could define all these kinds as an array of
> MARK IDs having different attributes - some are exportable/match-able and others
> are not, which sounds quite complex. As rte_flow doesn't have a direct way to
> check device capability (user has to call a series of validate functions
> instead), I thought defining TAG would be better.
>
>>>> (It is either API breakage (if tx_metadata is removed) or ABI breakage
>>>> if metadata and tx_metadata will share new location after shinfo).
> Fortunately, mlx5 is the only entity which uses tx_metadata so far.

As I understand it is still breakage.

>>> Make use of udata64 to export NIC metadata to application ?
>>> 	RTE_STD_C11
>>> 	union {
>>> 		void *userdata;   /**< Can be used for external metadata */
>>> 		uint64_t udata64; /**< Allow 8-byte userdata on 32-bit */
>>> 		uint64_t rx_metadata;
>>> 	};
>> As I understand it does not work for Tx and I'm not sure that it is
>> a good idea to have different locations for Tx and Rx.
>>
>> RFC adds it at the end of mbuf, but it was rejected before since
>> it eats space in mbuf structure (CC Konstantin).
> Yep, I was in the discussion. IIRC, the reason wasn't because it ate space but
> because it could recycle unused space on Tx path. We still have 16B after shinfo
> and I'm not sure how many bytes we should reserve. I think reserving space for
> one pointer would be fine.

I have no strong opinion.

Thanks,
Andrew.

> Thanks,
> Yongseok
>
>> There is a long discussion on the topic before [1], [2], [3] and [4].
>>
>> Andrew.
>>
>> [1] https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmails.dpdk.org%2Farchives%2Fdev%2F2018-August%2F109660.html&amp;data=02%7C01%7Cyskoh%40mellanox.com%7C6c81080cb68340d2128c08d6ed742746%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636957480475389496&amp;sdata=EFHyECwg0NBRvyrouZqWD6x0WD4xAsqsfYQGrEvS%2BEg%3D&amp;reserved=0
>> [2] https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmails.dpdk.org%2Farchives%2Fdev%2F2018-September%2F111771.html&amp;data=02%7C01%7Cyskoh%40mellanox.com%7C6c81080cb68340d2128c08d6ed742746%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636957480475389496&amp;sdata=M8cQSmQhWKlUVKvFgux0T0TWAnJhPxdO4Dn3fkReTyg%3D&amp;reserved=0
>> [3] https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmails.dpdk.org%2Farchives%2Fdev%2F2018-October%2F114559.html&amp;data=02%7C01%7Cyskoh%40mellanox.com%7C6c81080cb68340d2128c08d6ed742746%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636957480475394493&amp;sdata=ZVm5god7n1i07OCc5Z7B%2BBUpnjXCraJXU0FeF5KkCRc%3D&amp;reserved=0
>> [4] https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmails.dpdk.org%2Farchives%2Fdev%2F2018-October%2F115469.html&amp;data=02%7C01%7Cyskoh%40mellanox.com%7C6c81080cb68340d2128c08d6ed742746%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636957480475394493&amp;sdata=XgKV%2B331Vqsq9Ns40giI1nAwscVxBxqb78vB1BY8z%2Bc%3D&amp;reserved=0

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v3 4/8] kni: drop unused fields
  @ 2019-06-18 16:16  4%   ` Stephen Hemminger
  0 siblings, 0 replies; 200+ results
From: Stephen Hemminger @ 2019-06-18 16:16 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

The kni net structure only exists in driver no API/ABI.
Several fields were either totally unused or set and never used.

The fields in dev_info do need to stay in the ABI but
kernel can ignore them.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>

kni: drop unused status element

Yet another ethtool leftover.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 kernel/linux/kni/kni_dev.h  | 5 -----
 kernel/linux/kni/kni_misc.c | 1 -
 2 files changed, 6 deletions(-)

diff --git a/kernel/linux/kni/kni_dev.h b/kernel/linux/kni/kni_dev.h
index 21e4b0d92368..f3e6c3ca4efa 100644
--- a/kernel/linux/kni/kni_dev.h
+++ b/kernel/linux/kni/kni_dev.h
@@ -39,8 +39,6 @@ struct kni_dev {
 	/* kni list */
 	struct list_head list;
 
-	int status;
-	uint16_t group_id;           /* Group ID of a group of KNI devices */
 	uint32_t core_id;            /* Core ID to bind */
 	char name[RTE_KNI_NAMESIZE]; /* Network device name */
 	struct task_struct *pthread;
@@ -79,9 +77,6 @@ struct kni_dev {
 	/* mbuf size */
 	uint32_t mbuf_size;
 
-	/* synchro for request processing */
-	unsigned long synchro;
-
 	/* buffers */
 	void *pa[MBUF_BURST_SZ];
 	void *va[MBUF_BURST_SZ];
diff --git a/kernel/linux/kni/kni_misc.c b/kernel/linux/kni/kni_misc.c
index 1fc5eeb9c8ca..b59cf24c2184 100644
--- a/kernel/linux/kni/kni_misc.c
+++ b/kernel/linux/kni/kni_misc.c
@@ -346,7 +346,6 @@ kni_ioctl_create(struct net *net, uint32_t ioctl_num,
 	kni = netdev_priv(net_dev);
 
 	kni->net_dev = net_dev;
-	kni->group_id = dev_info.group_id;
 	kni->core_id = dev_info.core_id;
 	strncpy(kni->name, dev_info.name, RTE_KNI_NAMESIZE);
 
-- 
2.20.1


^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH 16/39] eventdev: add eventmode CL options framework
  2019-06-10 10:19  3%   ` Jerin Jacob Kollanukkaran
@ 2019-06-17 10:14  0%     ` Anoob Joseph
  0 siblings, 0 replies; 200+ results
From: Anoob Joseph @ 2019-06-17 10:14 UTC (permalink / raw)
  To: Jerin Jacob Kollanukkaran, Nikhil Rao, Erik Gabriel Carrillo,
	Abhinandan Gujjar, Bruce Richardson, Pablo de Lara
  Cc: Narayana Prasad Raju Athreya, dev, Lukas Bartosik,
	Pavan Nikhilesh Bhagavatula, Hemant Agrawal, Nipun Gupta,
	Harry van Haaren, Mattias Rönnblom, Liang Ma

Hi Jerin,

Please see inline.

Thanks,
Anoob

> -----Original Message-----
> From: Jerin Jacob Kollanukkaran
> Sent: Monday, June 10, 2019 3:49 PM
> To: Anoob Joseph <anoobj@marvell.com>; Nikhil Rao
> <nikhil.rao@intel.com>; Erik Gabriel Carrillo <erik.g.carrillo@intel.com>;
> Abhinandan Gujjar <abhinandan.gujjar@intel.com>; Bruce Richardson
> <bruce.richardson@intel.com>; Pablo de Lara
> <pablo.de.lara.guarch@intel.com>
> Cc: Anoob Joseph <anoobj@marvell.com>; Narayana Prasad Raju Athreya
> <pathreya@marvell.com>; dev@dpdk.org; Lukas Bartosik
> <lbartosik@marvell.com>; Pavan Nikhilesh Bhagavatula
> <pbhagavatula@marvell.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>; Nipun Gupta <nipun.gupta@nxp.com>; Harry
> van Haaren <harry.van.haaren@intel.com>; Mattias Rönnblom
> <mattias.ronnblom@ericsson.com>; Liang Ma <liang.j.ma@intel.com>
> Subject: RE: [PATCH 16/39] eventdev: add eventmode CL options framework
> 
> > -----Original Message-----
> > From: Anoob Joseph <anoobj@marvell.com>
> > Sent: Monday, June 3, 2019 11:02 PM
> > To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Nikhil Rao
> > <nikhil.rao@intel.com>; Erik Gabriel Carrillo
> > <erik.g.carrillo@intel.com>; Abhinandan Gujjar
> > <abhinandan.gujjar@intel.com>; Bruce Richardson
> > <bruce.richardson@intel.com>; Pablo de Lara
> > <pablo.de.lara.guarch@intel.com>
> > Cc: Anoob Joseph <anoobj@marvell.com>; Narayana Prasad Raju Athreya
> > <pathreya@marvell.com>; dev@dpdk.org; Lukas Bartosik
> > <lbartosik@marvell.com>; Pavan Nikhilesh Bhagavatula
> > <pbhagavatula@marvell.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>;
> > Nipun Gupta <nipun.gupta@nxp.com>; Harry van Haaren
> > <harry.van.haaren@intel.com>; Mattias Rönnblom
> > <mattias.ronnblom@ericsson.com>; Liang Ma <liang.j.ma@intel.com>
> > Subject: [PATCH 16/39] eventdev: add eventmode CL options framework
> >
> > Adding usage prints and CL parsing routines for eventmode. Option to
> > select packet transfer mode is also added.
> >
> > Signed-off-by: Anoob Joseph <anoobj@marvell.com>
> > Signed-off-by: Lukasz Bartosik <lbartosik@marvell.com>
> > ---
> > +#include <rte_compat.h>
> > +
> > +/* Packet transfer mode of the application */ enum
> > +rte_eventmode_helper_pkt_transfer_mode {
> > +	RTE_EVENTMODE_HELPER_PKT_TRANSFER_MODE_POLL = 0,
> > +	RTE_EVENTMODE_HELPER_PKT_TRANSFER_MODE_EVENT,
> > +};
> 
> Need to mark all public structues as EXPERIMENTAL.
> Please grep for EXPERIMENTAL in libeventdev or any other library

[Anoob] Will fix in v2.

> 
> > +struct rte_eventmode_helper_conf {
> > +	enum rte_eventmode_helper_pkt_transfer_mode mode;
> > +		/**< Packet transfer mode of the application */
> > +	void *mode_params;
> > +		/**< Mode specific parameters */
> > +};
> 
> Please make this event_helper object as 'opaque'  and move to internal so
> that it does have ABI policies and future new features can be added.
> 

[Anoob] The member, "mode_params" is the opaque pointer which is used internally. There are two fields which need to be communicated between application and helper library.

1. mode: whether the application is running in event-mode or poll-mode. Both application and helper library would need this. This field is set by the helper while parsing the eventmode args.
2. eth_portmask: helper library needs this info from application to know which all ethernet ports it can use. This is determined by the application and has to be communicated to the helper library. This can be made as params passed to the application, but eth_portmask will be the only member in it, as of now.

With the above use case, do you recommend any different structure layout?


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH] eal: resort symbols in EXPERIMENTAL section
  2019-06-14  7:44  3%   ` David Marchand
@ 2019-06-14 15:32  0%     ` Ferruh Yigit
  2019-06-20 17:23  0%       ` David Marchand
  0 siblings, 1 reply; 200+ results
From: Ferruh Yigit @ 2019-06-14 15:32 UTC (permalink / raw)
  To: David Marchand, Thomas Monjalon; +Cc: Stephen Hemminger, dev

On 6/14/2019 8:44 AM, David Marchand wrote:
> On Fri, Jun 14, 2019 at 9:39 AM Thomas Monjalon <thomas@monjalon.net> wrote:
> 
>> 06/04/2019 05:30, Stephen Hemminger:
>>> The symbols in the EXPERIMENTAL were close to alphabetic
>>> order but running sort showed several mistakes.
>>>
>>> This has no impact on code, API, ABI or otherwise.
>>> Purely for humans.
>>>
>>> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
>>
>> I don't think it's worth adding a layer of git history for this sort.
>> I would prefer to leave it as is.
>>
>>
> If this is about preferrence, I would prefer we have those symbols sorted
> per versions that introduced them ;-).
> Much easier to check and see if they are candidates for entering stable ABI.
> 

Not bad idea, +1 from my side J


^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v2] eventdev: change Rx adapter callback and stats structure
  @ 2019-06-13 23:28  3% ` Nikhil Rao
  2019-06-24 23:16 15% ` [dpdk-dev] [PATCH v3] " Nikhil Rao
  1 sibling, 0 replies; 200+ results
From: Nikhil Rao @ 2019-06-13 23:28 UTC (permalink / raw)
  To: jerinj; +Cc: nikhil.rao, dev

Replace the mbuf pointer array in the event eth Rx adapter
callback with an event array. Using an event array allows
the application to change attributes of the events enqueued
by the SW adapter.

The callback can drop packets and populate a callback
argument with the number of dropped packets. Add a Rx adapter
stats field to keep track of the total number of dropped packets.

Signed-off-by: Nikhil Rao <nikhil.rao@intel.com>
---
 lib/librte_eventdev/rte_event_eth_rx_adapter.h | 82 +++++++++++++-------------
 lib/librte_eventdev/rte_event_eth_rx_adapter.c | 39 +++++++-----
 MAINTAINERS                                    |  2 +-
 doc/guides/rel_notes/release_19_08.rst         | 13 +++-
 lib/librte_eventdev/Makefile                   |  2 +-
 lib/librte_eventdev/rte_eventdev_version.map   |  4 +-
 6 files changed, 80 insertions(+), 62 deletions(-)

v1:
* add implementation to RFC

v2:
* Bump library version
* Combine patch 1 & 2 into a single patch (single library version bump)
* Mention API change in release notes
* Remove __rte_experimental tag
* Remove EXPERIMENTAL status for eventdev

diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.h b/lib/librte_eventdev/rte_event_eth_rx_adapter.h
index beab870..99b55a8 100644
--- a/lib/librte_eventdev/rte_event_eth_rx_adapter.h
+++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.h
@@ -66,16 +66,17 @@
  * For SW based packet transfers, i.e., when the
  * RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT is not set in the adapter's
  * capabilities flags for a particular ethernet device, the service function
- * temporarily enqueues mbufs to an event buffer before batch enqueuing these
+ * temporarily enqueues events to an event buffer before batch enqueuing these
  * to the event device. If the buffer fills up, the service function stops
  * dequeuing packets from the ethernet device. The application may want to
  * monitor the buffer fill level and instruct the service function to
- * selectively buffer packets. The application may also use some other
+ * selectively buffer events. The application may also use some other
  * criteria to decide which packets should enter the event device even when
- * the event buffer fill level is low. The
- * rte_event_eth_rx_adapter_cb_register() function allows the
- * application to register a callback that selects which packets to enqueue
- * to the event device.
+ * the event buffer fill level is low or may want to enqueue packets to an
+ * internal event port. The rte_event_eth_rx_adapter_cb_register() function
+ * allows the application to register a callback that selects which packets are
+ * enqueued to the event device by the SW adapter. The callback interface is
+ * event based so the callback can also modify the event data if it needs to.
  */
 
 #ifdef __cplusplus
@@ -173,9 +174,6 @@ struct rte_event_eth_rx_adapter_queue_conf {
 };
 
 /**
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
- *
  * A structure used to retrieve statistics for an eth rx adapter instance.
  */
 struct rte_event_eth_rx_adapter_stats {
@@ -187,6 +185,8 @@ struct rte_event_eth_rx_adapter_stats {
 	/**< Eventdev enqueue count */
 	uint64_t rx_enq_retry;
 	/**< Eventdev enqueue retry count */
+	uint64_t rx_dropped;
+	/**< Received packet dropped count */
 	uint64_t rx_enq_start_ts;
 	/**< Rx enqueue start timestamp */
 	uint64_t rx_enq_block_cycles;
@@ -204,16 +204,25 @@ struct rte_event_eth_rx_adapter_stats {
 };
 
 /**
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
  *
  * Callback function invoked by the SW adapter before it continues
- * to process packets. The callback is passed the size of the enqueue
+ * to process events. The callback is passed the size of the enqueue
  * buffer in the SW adapter and the occupancy of the buffer. The
- * callback can use these values to decide which mbufs should be
- * enqueued to the event device. If the return value of the callback
- * is less than nb_mbuf then the SW adapter uses the return value to
- * enqueue enq_mbuf[] to the event device.
+ * callback can use these values to decide which events are
+ * enqueued to the event device by the SW adapter. The callback may
+ * also enqueue events internally using its own event port. The SW
+ * adapter populates the event information based on the Rx queue
+ * configuration in the adapter. The callback can modify the this event
+ * information for the events to be enqueued by the SW adapter.
+ *
+ * The callback return value is the number of events from the
+ * beginning of the event array that are to be enqueued by
+ * the SW adapter. It is the callback's responsibility to arrange
+ * these events at the beginning of the array, if these events are
+ * not contiguous in the original array. The *nb_dropped* parameter is
+ * a pointer to the number of events dropped by the callback, this
+ * number is used by the adapter to indicate the number of dropped packets
+ * as part of its statistics.
  *
  * @param eth_dev_id
  *  Port identifier of the Ethernet device.
@@ -222,27 +231,26 @@ struct rte_event_eth_rx_adapter_stats {
  * @param enqueue_buf_size
  *  Total enqueue buffer size.
  * @param enqueue_buf_count
- *  mbuf count in enqueue buffer.
- * @param mbuf
- *  mbuf array.
- * @param nb_mbuf
- *  mbuf count.
+ *  Event count in enqueue buffer.
+ * @param[in, out] ev
+ *  Event array.
+ * @param nb_event
+ *  Event array length.
  * @param cb_arg
  *  Callback argument.
- * @param[out] enq_mbuf
- *  The adapter enqueues enq_mbuf[] if the return value of the
- *  callback is less than nb_mbuf
+ * @param[out] nb_dropped
+ *  Packets dropped by callback.
  * @return
- *  Returns the number of mbufs should be enqueued to eventdev
+ *  - The number of events to be enqueued by the SW adapter.
  */
 typedef uint16_t (*rte_event_eth_rx_adapter_cb_fn)(uint16_t eth_dev_id,
 						uint16_t queue_id,
 						uint32_t enqueue_buf_size,
 						uint32_t enqueue_buf_count,
-						struct rte_mbuf **mbuf,
-						uint16_t nb_mbuf,
+						struct rte_event *ev,
+						uint16_t nb_event,
 						void *cb_arg,
-						struct rte_mbuf **enq_buf);
+						uint16_t *nb_dropped);
 
 /**
  * Create a new ethernet Rx event adapter with the specified identifier.
@@ -398,9 +406,6 @@ int rte_event_eth_rx_adapter_queue_del(uint8_t id, uint16_t eth_dev_id,
 int rte_event_eth_rx_adapter_stop(uint8_t id);
 
 /**
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
- *
  * Retrieve statistics for an adapter
  *
  * @param id
@@ -413,8 +418,7 @@ int rte_event_eth_rx_adapter_queue_del(uint8_t id, uint16_t eth_dev_id,
  *  - 0: Success, retrieved successfully.
  *  - <0: Error code on failure.
  */
-int __rte_experimental
-rte_event_eth_rx_adapter_stats_get(uint8_t id,
+int rte_event_eth_rx_adapter_stats_get(uint8_t id,
 				struct rte_event_eth_rx_adapter_stats *stats);
 
 /**
@@ -447,9 +451,6 @@ int rte_event_eth_rx_adapter_queue_del(uint8_t id, uint16_t eth_dev_id,
 int rte_event_eth_rx_adapter_service_id_get(uint8_t id, uint32_t *service_id);
 
 /**
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
- *
  * Register callback to process Rx packets, this is supported for
  * SW based packet transfers.
  * @see rte_event_eth_rx_cb_fn
@@ -466,11 +467,10 @@ int rte_event_eth_rx_adapter_queue_del(uint8_t id, uint16_t eth_dev_id,
  *  - 0: Success
  *  - <0: Error code on failure.
  */
-int __rte_experimental
-rte_event_eth_rx_adapter_cb_register(uint8_t id,
-				uint16_t eth_dev_id,
-				rte_event_eth_rx_adapter_cb_fn cb_fn,
-				void *cb_arg);
+int rte_event_eth_rx_adapter_cb_register(uint8_t id,
+					uint16_t eth_dev_id,
+					rte_event_eth_rx_adapter_cb_fn cb_fn,
+					void *cb_arg);
 
 #ifdef __cplusplus
 }
diff --git a/lib/librte_eventdev/rte_event_eth_rx_adapter.c b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
index eaf341c..718fbbf 100644
--- a/lib/librte_eventdev/rte_event_eth_rx_adapter.c
+++ b/lib/librte_eventdev/rte_event_eth_rx_adapter.c
@@ -768,8 +768,8 @@ static uint16_t rxa_gcd_u16(uint16_t a, uint16_t b)
 	uint32_t rss;
 	int do_rss;
 	uint64_t ts;
-	struct rte_mbuf *cb_mbufs[BATCH_SIZE];
 	uint16_t nb_cb;
+	uint16_t dropped;
 
 	/* 0xffff ffff if PKT_RX_RSS_HASH is set, otherwise 0 */
 	rss_mask = ~(((m->ol_flags & PKT_RX_RSS_HASH) != 0) - 1);
@@ -785,19 +785,6 @@ static uint16_t rxa_gcd_u16(uint16_t a, uint16_t b)
 		}
 	}
 
-
-	nb_cb = dev_info->cb_fn ? dev_info->cb_fn(eth_dev_id, rx_queue_id,
-						ETH_EVENT_BUFFER_SIZE,
-						buf->count, mbufs,
-						num,
-						dev_info->cb_arg,
-						cb_mbufs) :
-						num;
-	if (nb_cb < num) {
-		mbufs = cb_mbufs;
-		num = nb_cb;
-	}
-
 	for (i = 0; i < num; i++) {
 		m = mbufs[i];
 
@@ -819,6 +806,26 @@ static uint16_t rxa_gcd_u16(uint16_t a, uint16_t b)
 		ev++;
 	}
 
+	if (dev_info->cb_fn) {
+
+		dropped = 0;
+		nb_cb = dev_info->cb_fn(eth_dev_id,
+					rx_queue_id,
+					ETH_EVENT_BUFFER_SIZE,
+					buf->count,
+					ev,
+					num,
+					dev_info->cb_arg,
+					&dropped);
+		if (unlikely(nb_cb > num))
+			RTE_EDEV_LOG_ERR("Rx CB returned %d (> %d) events",
+				nb_cb, num);
+		else
+			num = nb_cb;
+		if (dropped)
+			rx_adapter->stats.rx_dropped += dropped;
+	}
+
 	buf->count += num;
 }
 
@@ -2285,7 +2292,7 @@ static int rxa_sw_add(struct rte_event_eth_rx_adapter *rx_adapter,
 	return rxa_ctrl(id, 0);
 }
 
-int __rte_experimental
+int
 rte_event_eth_rx_adapter_stats_get(uint8_t id,
 			       struct rte_event_eth_rx_adapter_stats *stats)
 {
@@ -2372,7 +2379,7 @@ static int rxa_sw_add(struct rte_event_eth_rx_adapter *rx_adapter,
 	return rx_adapter->service_inited ? 0 : -ESRCH;
 }
 
-int __rte_experimental
+int
 rte_event_eth_rx_adapter_cb_register(uint8_t id,
 					uint16_t eth_dev_id,
 					rte_event_eth_rx_adapter_cb_fn cb_fn,
diff --git a/MAINTAINERS b/MAINTAINERS
index d0bf259..d899d28 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -399,7 +399,7 @@ F: lib/librte_eventdev/
 F: drivers/event/skeleton/
 F: app/test/test_eventdev.c
 
-Eventdev Ethdev Rx Adapter API - EXPERIMENTAL
+Eventdev Ethdev Rx Adapter API
 M: Nikhil Rao <nikhil.rao@intel.com>
 T: git://dpdk.org/next/dpdk-next-eventdev
 F: lib/librte_eventdev/*eth_rx_adapter*
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index c199270..bb773cd 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -106,6 +106,17 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* eventdev: Event based Rx adapter callback
+
+  The mbuf pointer array in the event eth Rx adapter callbacl
+  has been replaced with an event array. Using
+  an event array allows the application to change attributes
+  of the events enqueued by the SW adapter.
+
+  The callback can drop packets and populate
+  a callback argument with the number of dropped packets.
+  Add a Rx adapter stats field to keep track of the total
+  number of dropped packets.
 
 Shared Library Versions
 -----------------------
@@ -142,7 +153,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_eal.so.10
      librte_efd.so.1
      librte_ethdev.so.12
-     librte_eventdev.so.6
+   + librte_eventdev.so.7
      librte_flow_classify.so.1
      librte_gro.so.1
      librte_gso.so.1
diff --git a/lib/librte_eventdev/Makefile b/lib/librte_eventdev/Makefile
index 53079f4..cd3ff80 100644
--- a/lib/librte_eventdev/Makefile
+++ b/lib/librte_eventdev/Makefile
@@ -8,7 +8,7 @@ include $(RTE_SDK)/mk/rte.vars.mk
 LIB = librte_eventdev.a
 
 # library version
-LIBABIVER := 6
+LIBABIVER := 7
 
 # build flags
 CFLAGS += -DALLOW_EXPERIMENTAL_API
diff --git a/lib/librte_eventdev/rte_eventdev_version.map b/lib/librte_eventdev/rte_eventdev_version.map
index 95fd089..76b3021 100644
--- a/lib/librte_eventdev/rte_eventdev_version.map
+++ b/lib/librte_eventdev/rte_eventdev_version.map
@@ -123,9 +123,9 @@ DPDK_19.05 {
 	rte_event_timer_cancel_burst;
 } DPDK_18.05;
 
-EXPERIMENTAL {
+DPDK_19.08 {
 	global:
 
 	rte_event_eth_rx_adapter_cb_register;
 	rte_event_eth_rx_adapter_stats_get;
-};
+} DPDK_19.05;
-- 
1.8.3.1


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH] eal: resort symbols in EXPERIMENTAL section
  2019-06-14  7:39  0% ` Thomas Monjalon
@ 2019-06-14  7:44  3%   ` David Marchand
  2019-06-14 15:32  0%     ` Ferruh Yigit
  0 siblings, 1 reply; 200+ results
From: David Marchand @ 2019-06-14  7:44 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: Stephen Hemminger, dev

On Fri, Jun 14, 2019 at 9:39 AM Thomas Monjalon <thomas@monjalon.net> wrote:

> 06/04/2019 05:30, Stephen Hemminger:
> > The symbols in the EXPERIMENTAL were close to alphabetic
> > order but running sort showed several mistakes.
> >
> > This has no impact on code, API, ABI or otherwise.
> > Purely for humans.
> >
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
>
> I don't think it's worth adding a layer of git history for this sort.
> I would prefer to leave it as is.
>
>
If this is about preferrence, I would prefer we have those symbols sorted
per versions that introduced them ;-).
Much easier to check and see if they are candidates for entering stable ABI.


-- 
David Marchand

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH] eal: resort symbols in EXPERIMENTAL section
  @ 2019-06-14  7:39  0% ` Thomas Monjalon
  2019-06-14  7:44  3%   ` David Marchand
  0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2019-06-14  7:39 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

06/04/2019 05:30, Stephen Hemminger:
> The symbols in the EXPERIMENTAL were close to alphabetic
> order but running sort showed several mistakes.
> 
> This has no impact on code, API, ABI or otherwise.
> Purely for humans.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>

I don't think it's worth adding a layer of git history for this sort.
I would prefer to leave it as is.




^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v2 01/10] Add __rte_internal tag for functions and version target
  2019-06-13 14:23  4% ` [dpdk-dev] [PATCH v2 0/10] " Neil Horman
@ 2019-06-13 14:23  3%   ` Neil Horman
  2019-06-13 14:23  3%   ` [dpdk-dev] [PATCH v2 03/10] Exempt INTERNAL symbols from checking Neil Horman
  1 sibling, 0 replies; 200+ results
From: Neil Horman @ 2019-06-13 14:23 UTC (permalink / raw)
  To: dev
  Cc: Neil Horman, Jerin Jacob Kollanukkaran, Bruce Richardson,
	Thomas Monjalon

This tag is meant to be used on function prototypes to identify
functions that are only meant to be used by internal DPDK libraries
(i.e. libraries that are built while building the SDK itself, as
identified by the defining of the BUILDING_RTE_SDK macro).  When that
flag is not set, it will resolve to an error function attribute, causing
build breakage for any compilation unit attempting to build it

Validate the use of this tag in much the same way we validate
__rte_experimental.  By adding an INTERNAL version to library map files,
we can exempt internal-only functions from ABI checking, and handle them
to ensure that symbols we wish to only be for internal use between dpdk
libraries are properly tagged with __rte_experimental

Note this patch updates the check-experimental-syms.sh script, which
normally only check the EXPERIMENTAL section to also check the INTERNAL
section now.  As such its been renamed to the now more appropriate
check-special-syms.sh

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
CC: Bruce Richardson <bruce.richardson@intel.com>
CC: Thomas Monjalon <thomas@monjalon.net>
---
 ...rimental-syms.sh => check-special-syms.sh} | 24 ++++++++++++++++++-
 lib/librte_eal/common/include/rte_compat.h    | 12 ++++++++++
 mk/internal/rte.compile-pre.mk                |  6 ++---
 mk/target/generic/rte.vars.mk                 |  2 +-
 4 files changed, 39 insertions(+), 5 deletions(-)
 rename buildtools/{check-experimental-syms.sh => check-special-syms.sh} (53%)

diff --git a/buildtools/check-experimental-syms.sh b/buildtools/check-special-syms.sh
similarity index 53%
rename from buildtools/check-experimental-syms.sh
rename to buildtools/check-special-syms.sh
index 7d1f3a568..63682c677 100755
--- a/buildtools/check-experimental-syms.sh
+++ b/buildtools/check-special-syms.sh
@@ -31,10 +31,32 @@ do
 		cat >&2 <<- END_OF_MESSAGE
 		$SYM is not flagged as experimental
 		but is listed in version map
-		Please add __rte_experimental to the definition of $SYM
+		Please add __rte_experimental to the definition/prototype of $SYM
 		END_OF_MESSAGE
 		exit 1
 	fi
 done
+
+for i in `awk 'BEGIN {found=0}
+		/.*INTERNAL.*/ {found=1}
+		/.*}.*;/ {found=0}
+		/.*;/ {if (found == 1) print $1}' $MAPFILE`
+do
+	SYM=`echo $i | sed -e"s/;//"`
+	objdump -t $OBJFILE | grep -q "\.text.*$SYM$"
+	IN_TEXT=$?
+	objdump -t $OBJFILE | grep -q "\.text\.internal.*$SYM$"
+	IN_EXP=$?
+	if [ $IN_TEXT -eq 0 -a $IN_EXP -ne 0 ]
+	then
+		cat >&2 <<- END_OF_MESSAGE
+		$SYM is not flagged as internal 
+		but is listed in version map
+		Please add __rte_internal to the definition/prototype of $SYM
+		END_OF_MESSAGE
+		exit 1
+	fi
+done
+
 exit 0
 
diff --git a/lib/librte_eal/common/include/rte_compat.h b/lib/librte_eal/common/include/rte_compat.h
index 92ff28faf..739e8485c 100644
--- a/lib/librte_eal/common/include/rte_compat.h
+++ b/lib/librte_eal/common/include/rte_compat.h
@@ -89,4 +89,16 @@ __attribute__((section(".text.experimental")))
 
 #endif
 
+/*
+ * __rte_internal tags mark functions as internal only, If specified in public
+ * header files, this tag will resolve to an error directive, preventing
+ * external applications from attempting to make calls to functions not meant
+ * for consumption outside the dpdk library
+ */
+#ifdef BUILDING_RTE_SDK
+#define __rte_internal __attribute__((section(".text.internal")))
+#else
+#define __rte_internal __attribute__((error("This function cannot be used outside of the core DPDK library"), \
+	section(".text.internal")))
+#endif
 #endif /* _RTE_COMPAT_H_ */
diff --git a/mk/internal/rte.compile-pre.mk b/mk/internal/rte.compile-pre.mk
index 0cf3791b4..f1d97ef76 100644
--- a/mk/internal/rte.compile-pre.mk
+++ b/mk/internal/rte.compile-pre.mk
@@ -56,8 +56,8 @@ C_TO_O = $(CC) -Wp,-MD,$(call obj2dep,$(@)).tmp $(CPPFLAGS) $(CFLAGS) \
 C_TO_O_STR = $(subst ','\'',$(C_TO_O)) #'# fix syntax highlight
 C_TO_O_DISP = $(if $(V),"$(C_TO_O_STR)","  CC $(@)")
 endif
-EXPERIMENTAL_CHECK = $(RTE_SDK)/buildtools/check-experimental-syms.sh
-CHECK_EXPERIMENTAL = $(EXPERIMENTAL_CHECK) $(SRCDIR)/$(EXPORT_MAP) $@
+SPECIAL_SYM_CHECK = $(RTE_SDK)/buildtools/check-special-syms.sh
+CHECK_SPECIAL_SYMS = $(SPECIAL_SYM_CHECK) $(SRCDIR)/$(EXPORT_MAP) $@
 
 PMDINFO_GEN = $(RTE_SDK_BIN)/app/dpdk-pmdinfogen $@ $@.pmd.c
 PMDINFO_CC = $(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@.pmd.o $@.pmd.c
@@ -75,7 +75,7 @@ C_TO_O_DO = @set -e; \
 	echo $(C_TO_O_DISP); \
 	$(C_TO_O) && \
 	$(PMDINFO_TO_O) && \
-	$(CHECK_EXPERIMENTAL) && \
+	$(CHECK_SPECIAL_SYMS) && \
 	echo $(C_TO_O_CMD) > $(call obj2cmd,$(@)) && \
 	sed 's,'$@':,dep_'$@' =,' $(call obj2dep,$(@)).tmp > $(call obj2dep,$(@)) && \
 	rm -f $(call obj2dep,$(@)).tmp
diff --git a/mk/target/generic/rte.vars.mk b/mk/target/generic/rte.vars.mk
index 25a578ad7..ed6a0c87b 100644
--- a/mk/target/generic/rte.vars.mk
+++ b/mk/target/generic/rte.vars.mk
@@ -96,7 +96,7 @@ LDFLAGS += -L$(RTE_OUTPUT)/lib
 # defined.
 ifeq ($(BUILDING_RTE_SDK),1)
 # building sdk
-CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h
+CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h -DBUILDING_RTE_SDK
 else
 # if we are building an external application, include SDK's lib and
 # includes too
-- 
2.20.1


^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v2 03/10] Exempt INTERNAL symbols from checking
  2019-06-13 14:23  4% ` [dpdk-dev] [PATCH v2 0/10] " Neil Horman
  2019-06-13 14:23  3%   ` [dpdk-dev] [PATCH v2 01/10] Add __rte_internal tag for functions and version target Neil Horman
@ 2019-06-13 14:23  3%   ` Neil Horman
  1 sibling, 0 replies; 200+ results
From: Neil Horman @ 2019-06-13 14:23 UTC (permalink / raw)
  To: dev
  Cc: Neil Horman, Jerin Jacob Kollanukkaran, Bruce Richardson,
	Thomas Monjalon

No need to restrict the ABI on symbols that are only used by core
libraries

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
CC: Bruce Richardson <bruce.richardson@intel.com>
CC: Thomas Monjalon <thomas@monjalon.net>
---
 devtools/check-symbol-change.sh | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/devtools/check-symbol-change.sh b/devtools/check-symbol-change.sh
index c5434f3bb..83e8b43ae 100755
--- a/devtools/check-symbol-change.sh
+++ b/devtools/check-symbol-change.sh
@@ -93,6 +93,13 @@ check_for_rule_violations()
 		if [ "$ar" = "add" ]
 		then
 
+			if [ "$secname" = "INTERNAL" ]
+			then
+				# these are absolved from any further checking
+				echo "Skipping symbol $symname in INTERNAL"
+				continue
+			fi
+
 			if [ "$secname" = "unknown" ]
 			then
 				# Just inform the user of this occurrence, but
-- 
2.20.1


^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v2 0/10] dpdk: introduce __rte_internal tag
                     ` (2 preceding siblings ...)
  2019-06-12 20:38  4% ` [dpdk-dev] [PATCH v1 0/9] dpdk: " Neil Horman
@ 2019-06-13 14:23  4% ` Neil Horman
  2019-06-13 14:23  3%   ` [dpdk-dev] [PATCH v2 01/10] Add __rte_internal tag for functions and version target Neil Horman
  2019-06-13 14:23  3%   ` [dpdk-dev] [PATCH v2 03/10] Exempt INTERNAL symbols from checking Neil Horman
  3 siblings, 2 replies; 200+ results
From: Neil Horman @ 2019-06-13 14:23 UTC (permalink / raw)
  To: dev
  Cc: Neil Horman, Jerin Jacob Kollanukkaran, Bruce Richardson,
	Thomas Monjalon

Hey-
        Based on our recent conversations regarding the use of symbols only
meant for internal dpdk consumption (between dpdk libraries), this is an idea
that I've come up with that I'd like to get some feedback on

Summary:
1) We have symbols in the DPDK that are meant to be used between DPDK libraries,
but not by applications linking to them
2) We would like to document those symbols in the code, so as to note them
clearly as for being meant for internal use only
3) Linker symbol visibility is a very coarse grained tool, and so there is no
good way in a single library to mark items as being meant for use only by other
DPDK libraries, at least not without some extensive runtime checking


Proposal:
I'm proposing that we introduce the __rte_internal tag.  From a coding
standpoint it works a great deal like the __rte_experimental tag in that it
expempts the tagged symbol from ABI constraints (as the only users should be
represented in the DPDK build environment).  Additionally, the __rte_internal
macro resolves differently based on the definition of the BUILDING_RTE_SDK flag
(working under the assumption that said flag should only ever be set if we are
actually building DPDK libraries which will make use of internal calls).  If the
BUILDING_RTE_SDK flag is set __rte_internal resolves to __attribute__((section
"text.internal)), placing it in a special text section which is then used to
validate that the the symbol appears in the INTERNAL section of the
corresponding library version map).  If BUILDING_RTE_SDK is not set, then
__rte_internal resolves to __attribute__((error("..."))), which causes any
caller of the tagged function to throw an error at compile time, indicating that
the symbol is not available for external use.

This isn't a perfect solution, as applications can still hack around it of
course, but I think it hits some of the high points, restricting symbol access
for any library that prototypes its public and private symbols in the same
header file, excluding the internal symbols from ABI constraints, and clearly
documenting those symbols which we wish to limit to internal usage.

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
CC: Bruce Richardson <bruce.richardson@intel.com>
CC: Thomas Monjalon <thomas@monjalon.net>

---
Change notes

v1->v2
Moved check-experimental-syms.sh rename to earlier in the series
Updated meson build environment to support BUILDING_RTE_SDK



^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v1 0/9] dpdk: introduce __rte_internal tag
  2019-06-13  7:53  3%   ` [dpdk-dev] [PATCH v1 0/9] dpdk: introduce __rte_internal tag David Marchand
@ 2019-06-13 10:30  0%     ` Neil Horman
  0 siblings, 0 replies; 200+ results
From: Neil Horman @ 2019-06-13 10:30 UTC (permalink / raw)
  To: David Marchand
  Cc: dev, Jerin Jacob Kollanukkaran, Bruce Richardson, Thomas Monjalon

On Thu, Jun 13, 2019 at 09:53:46AM +0200, David Marchand wrote:
> On Wed, Jun 12, 2019 at 10:40 PM Neil Horman <nhorman@tuxdriver.com> wrote:
> 
> > Hey-
> >         Based on our recent conversations regarding the use of symbols only
> > meant for internal dpdk consumption (between dpdk libraries), this is an
> > idea
> > that I've come up with that I'd like to get some feedback on
> >
> > Summary:
> > 1) We have symbols in the DPDK that are meant to be used between DPDK
> > libraries,
> > but not by applications linking to them
> > 2) We would like to document those symbols in the code, so as to note them
> > clearly as for being meant for internal use only
> > 3) Linker symbol visibility is a very coarse grained tool, and so there is
> > no
> > good way in a single library to mark items as being meant for use only by
> > other
> > DPDK libraries, at least not without some extensive runtime checking
> >
> >
> > Proposal:
> > I'm proposing that we introduce the __rte_internal tag.  From a coding
> > standpoint it works a great deal like the __rte_experimental tag in that it
> > expempts the tagged symbol from ABI constraints (as the only users should
> > be
> > represented in the DPDK build environment).  Additionally, the
> > __rte_internal
> > macro resolves differently based on the definition of the BUILDING_RTE_SDK
> > flag
> > (working under the assumption that said flag should only ever be set if we
> > are
> > actually building DPDK libraries which will make use of internal calls).
> > If the
> > BUILDING_RTE_SDK flag is set __rte_internal resolves to
> > __attribute__((section
> > "text.internal)), placing it in a special text section which is then used
> > to
> > validate that the the symbol appears in the INTERNAL section of the
> > corresponding library version map).  If BUILDING_RTE_SDK is not set, then
> > __rte_internal resolves to __attribute__((error("..."))), which causes any
> > caller of the tagged function to throw an error at compile time,
> > indicating that
> > the symbol is not available for external use.
> >
> > This isn't a perfect solution, as applications can still hack around it of
> > course, but I think it hits some of the high points, restricting symbol
> > access
> > for any library that prototypes its public and private symbols in the same
> > header file, excluding the internal symbols from ABI constraints, and
> > clearly
> > documenting those symbols which we wish to limit to internal usage.
> >
> > Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> > CC: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> > CC: Bruce Richardson <bruce.richardson@intel.com>
> > CC: Thomas Monjalon <thomas@monjalon.net>
> >
> >
> >
> On the principle, are we not breaking the ABI for the libraries that we
> touch with this?
> 
Yes, strictly speaking on principle, we are, because we are removing symbols
from the exported symbol list, but the purpose of this patch set was to identify
those symbols which, by (convention/documentation/etc), we had intended to
mandate should never be used by applications outside of the DPDK.  Since this
patch is meant to identify those symbols, and somewhat more formally isolate and
prevent users from accessing them, I was making the argument that it was ok to
do so.  If you like we can go through the process of deprecating them, prior to
moving them to an internal space, but given that I was under the impression
anyone reporting a bug about the symbol disappearing would be responded to with
a note indicating that they never should have been accessed to begin with, I had
assumed the movement would be ok.

> Compilation is broken in patch 1 and 2 because the script rename is part of
> patch 3.
> 
Good point, I'll reshuffle those to be more correct.
Neil

> 
> -- 
> David Marchand

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v2 10/10] doc: update release notes for 19.08
  2019-06-07 10:06  4%   ` [dpdk-dev] [PATCH v2 10/10] doc: update release notes for 19.08 Damian Nowak
@ 2019-06-13  8:14  0%     ` Akhil Goyal
  0 siblings, 0 replies; 200+ results
From: Akhil Goyal @ 2019-06-13  8:14 UTC (permalink / raw)
  To: Damian Nowak, dev; +Cc: fiona.trahe, arkadiuszx.kusztal

Hi Damian,

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Damian Nowak
> Sent: Friday, June 7, 2019 3:36 PM
> To: dev@dpdk.org
> Cc: fiona.trahe@intel.com; arkadiuszx.kusztal@intel.com; Damian Nowak
> <damianx.nowak@intel.com>
> Subject: [dpdk-dev] [PATCH v2 10/10] doc: update release notes for 19.08
> 
> This patch adds release note entries for
> hash-cipher digest-encrypted operations
> and new digest_encrypted feature flag.
> 
> Signed-off-by: Damian Nowak <damianx.nowak@intel.com>
> ---
>  doc/guides/rel_notes/release_19_08.rst | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/doc/guides/rel_notes/release_19_08.rst
> b/doc/guides/rel_notes/release_19_08.rst
> index b9510f9..1c85a2e 100644
> --- a/doc/guides/rel_notes/release_19_08.rst
> +++ b/doc/guides/rel_notes/release_19_08.rst
> @@ -54,6 +54,11 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =========================================================
> 
> +* **Updated the QuickAssist Technology (QAT) symmetric crypto PMD.**
> +
> +  Added support for hash-cipher with digest encrypted, when using
> +  out-of-place operations.
> +
> 
>  Removed Items
>  -------------
> @@ -83,6 +88,9 @@ API Changes
>     Also, make sure to start the actual text at the margin.
>     =========================================================
> 
> +* cryptodev: ``RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED`` feature flag
> +  has been introduced.
> +
> 
>  ABI Changes
>  -----------
> --
> 2.7.4
Split this patch in two and squash both of them in the patches which enables these features.

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v1 0/9] dpdk: introduce __rte_internal tag
  2019-06-12 20:38  4% ` [dpdk-dev] [PATCH v1 0/9] dpdk: " Neil Horman
  2019-06-12 20:38  3%   ` [dpdk-dev] [PATCH v1 1/9] Add __rte_internal tag for functions and version target Neil Horman
  2019-06-12 20:38  3%   ` [dpdk-dev] [PATCH v1 2/9] Exempt INTERNAL symbols from checking Neil Horman
@ 2019-06-13  7:53  3%   ` David Marchand
  2019-06-13 10:30  0%     ` Neil Horman
  2 siblings, 1 reply; 200+ results
From: David Marchand @ 2019-06-13  7:53 UTC (permalink / raw)
  To: Neil Horman
  Cc: dev, Jerin Jacob Kollanukkaran, Bruce Richardson, Thomas Monjalon

On Wed, Jun 12, 2019 at 10:40 PM Neil Horman <nhorman@tuxdriver.com> wrote:

> Hey-
>         Based on our recent conversations regarding the use of symbols only
> meant for internal dpdk consumption (between dpdk libraries), this is an
> idea
> that I've come up with that I'd like to get some feedback on
>
> Summary:
> 1) We have symbols in the DPDK that are meant to be used between DPDK
> libraries,
> but not by applications linking to them
> 2) We would like to document those symbols in the code, so as to note them
> clearly as for being meant for internal use only
> 3) Linker symbol visibility is a very coarse grained tool, and so there is
> no
> good way in a single library to mark items as being meant for use only by
> other
> DPDK libraries, at least not without some extensive runtime checking
>
>
> Proposal:
> I'm proposing that we introduce the __rte_internal tag.  From a coding
> standpoint it works a great deal like the __rte_experimental tag in that it
> expempts the tagged symbol from ABI constraints (as the only users should
> be
> represented in the DPDK build environment).  Additionally, the
> __rte_internal
> macro resolves differently based on the definition of the BUILDING_RTE_SDK
> flag
> (working under the assumption that said flag should only ever be set if we
> are
> actually building DPDK libraries which will make use of internal calls).
> If the
> BUILDING_RTE_SDK flag is set __rte_internal resolves to
> __attribute__((section
> "text.internal)), placing it in a special text section which is then used
> to
> validate that the the symbol appears in the INTERNAL section of the
> corresponding library version map).  If BUILDING_RTE_SDK is not set, then
> __rte_internal resolves to __attribute__((error("..."))), which causes any
> caller of the tagged function to throw an error at compile time,
> indicating that
> the symbol is not available for external use.
>
> This isn't a perfect solution, as applications can still hack around it of
> course, but I think it hits some of the high points, restricting symbol
> access
> for any library that prototypes its public and private symbols in the same
> header file, excluding the internal symbols from ABI constraints, and
> clearly
> documenting those symbols which we wish to limit to internal usage.
>
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> CC: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> CC: Bruce Richardson <bruce.richardson@intel.com>
> CC: Thomas Monjalon <thomas@monjalon.net>
>
>
>
On the principle, are we not breaking the ABI for the libraries that we
touch with this?

Compilation is broken in patch 1 and 2 because the script rename is part of
patch 3.


-- 
David Marchand

^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v1 2/9] Exempt INTERNAL symbols from checking
  2019-06-12 20:38  4% ` [dpdk-dev] [PATCH v1 0/9] dpdk: " Neil Horman
  2019-06-12 20:38  3%   ` [dpdk-dev] [PATCH v1 1/9] Add __rte_internal tag for functions and version target Neil Horman
@ 2019-06-12 20:38  3%   ` Neil Horman
  2019-06-13  7:53  3%   ` [dpdk-dev] [PATCH v1 0/9] dpdk: introduce __rte_internal tag David Marchand
  2 siblings, 0 replies; 200+ results
From: Neil Horman @ 2019-06-12 20:38 UTC (permalink / raw)
  To: dev
  Cc: Neil Horman, Jerin Jacob Kollanukkaran, Bruce Richardson,
	Thomas Monjalon

No need to restrict the ABI on symbols that are only used by core
libraries

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
CC: Bruce Richardson <bruce.richardson@intel.com>
CC: Thomas Monjalon <thomas@monjalon.net>
---
 devtools/check-symbol-change.sh | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/devtools/check-symbol-change.sh b/devtools/check-symbol-change.sh
index c5434f3bb..83e8b43ae 100755
--- a/devtools/check-symbol-change.sh
+++ b/devtools/check-symbol-change.sh
@@ -93,6 +93,13 @@ check_for_rule_violations()
 		if [ "$ar" = "add" ]
 		then
 
+			if [ "$secname" = "INTERNAL" ]
+			then
+				# these are absolved from any further checking
+				echo "Skipping symbol $symname in INTERNAL"
+				continue
+			fi
+
 			if [ "$secname" = "unknown" ]
 			then
 				# Just inform the user of this occurrence, but
-- 
2.20.1


^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v1 1/9] Add __rte_internal tag for functions and version target
  2019-06-12 20:38  4% ` [dpdk-dev] [PATCH v1 0/9] dpdk: " Neil Horman
@ 2019-06-12 20:38  3%   ` Neil Horman
  2019-06-12 20:38  3%   ` [dpdk-dev] [PATCH v1 2/9] Exempt INTERNAL symbols from checking Neil Horman
  2019-06-13  7:53  3%   ` [dpdk-dev] [PATCH v1 0/9] dpdk: introduce __rte_internal tag David Marchand
  2 siblings, 0 replies; 200+ results
From: Neil Horman @ 2019-06-12 20:38 UTC (permalink / raw)
  To: dev
  Cc: Neil Horman, Jerin Jacob Kollanukkaran, Bruce Richardson,
	Thomas Monjalon

This tag is meant to be used on function prototypes to identify
functions that are only meant to be used by internal DPDK libraries
(i.e. libraries that are built while building the SDK itself, as
identified by the defining of the BUILDING_RTE_SDK macro).  When that
flag is not set, it will resolve to an error function attribute, causing
build breakage for any compilation unit attempting to build it

Validate the use of this tag in much the same way we validate
__rte_experimental.  By adding an INTERNAL version to library map files,
we can exempt internal-only functions from ABI checking, and handle them
to ensure that symbols we wish to only be for internal use between dpdk
libraries are properly tagged with __rte_experimental

Note this patch updates the check-experimental-syms.sh script, which
normally only check the EXPERIMENTAL section to also check the INTERNAL
section now.  As such its been renamed to the now more appropriate
check-special-syms.sh

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
CC: Bruce Richardson <bruce.richardson@intel.com>
CC: Thomas Monjalon <thomas@monjalon.net>
---
 buildtools/check-experimental-syms.sh      | 24 +++++++++++++++++++++-
 lib/librte_eal/common/include/rte_compat.h | 12 +++++++++++
 mk/internal/rte.compile-pre.mk             |  6 +++---
 mk/target/generic/rte.vars.mk              |  2 +-
 4 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/buildtools/check-experimental-syms.sh b/buildtools/check-experimental-syms.sh
index 7d1f3a568..63682c677 100755
--- a/buildtools/check-experimental-syms.sh
+++ b/buildtools/check-experimental-syms.sh
@@ -31,10 +31,32 @@ do
 		cat >&2 <<- END_OF_MESSAGE
 		$SYM is not flagged as experimental
 		but is listed in version map
-		Please add __rte_experimental to the definition of $SYM
+		Please add __rte_experimental to the definition/prototype of $SYM
 		END_OF_MESSAGE
 		exit 1
 	fi
 done
+
+for i in `awk 'BEGIN {found=0}
+		/.*INTERNAL.*/ {found=1}
+		/.*}.*;/ {found=0}
+		/.*;/ {if (found == 1) print $1}' $MAPFILE`
+do
+	SYM=`echo $i | sed -e"s/;//"`
+	objdump -t $OBJFILE | grep -q "\.text.*$SYM$"
+	IN_TEXT=$?
+	objdump -t $OBJFILE | grep -q "\.text\.internal.*$SYM$"
+	IN_EXP=$?
+	if [ $IN_TEXT -eq 0 -a $IN_EXP -ne 0 ]
+	then
+		cat >&2 <<- END_OF_MESSAGE
+		$SYM is not flagged as internal 
+		but is listed in version map
+		Please add __rte_internal to the definition/prototype of $SYM
+		END_OF_MESSAGE
+		exit 1
+	fi
+done
+
 exit 0
 
diff --git a/lib/librte_eal/common/include/rte_compat.h b/lib/librte_eal/common/include/rte_compat.h
index 92ff28faf..739e8485c 100644
--- a/lib/librte_eal/common/include/rte_compat.h
+++ b/lib/librte_eal/common/include/rte_compat.h
@@ -89,4 +89,16 @@ __attribute__((section(".text.experimental")))
 
 #endif
 
+/*
+ * __rte_internal tags mark functions as internal only, If specified in public
+ * header files, this tag will resolve to an error directive, preventing
+ * external applications from attempting to make calls to functions not meant
+ * for consumption outside the dpdk library
+ */
+#ifdef BUILDING_RTE_SDK
+#define __rte_internal __attribute__((section(".text.internal")))
+#else
+#define __rte_internal __attribute__((error("This function cannot be used outside of the core DPDK library"), \
+	section(".text.internal")))
+#endif
 #endif /* _RTE_COMPAT_H_ */
diff --git a/mk/internal/rte.compile-pre.mk b/mk/internal/rte.compile-pre.mk
index 0cf3791b4..f1d97ef76 100644
--- a/mk/internal/rte.compile-pre.mk
+++ b/mk/internal/rte.compile-pre.mk
@@ -56,8 +56,8 @@ C_TO_O = $(CC) -Wp,-MD,$(call obj2dep,$(@)).tmp $(CPPFLAGS) $(CFLAGS) \
 C_TO_O_STR = $(subst ','\'',$(C_TO_O)) #'# fix syntax highlight
 C_TO_O_DISP = $(if $(V),"$(C_TO_O_STR)","  CC $(@)")
 endif
-EXPERIMENTAL_CHECK = $(RTE_SDK)/buildtools/check-experimental-syms.sh
-CHECK_EXPERIMENTAL = $(EXPERIMENTAL_CHECK) $(SRCDIR)/$(EXPORT_MAP) $@
+SPECIAL_SYM_CHECK = $(RTE_SDK)/buildtools/check-special-syms.sh
+CHECK_SPECIAL_SYMS = $(SPECIAL_SYM_CHECK) $(SRCDIR)/$(EXPORT_MAP) $@
 
 PMDINFO_GEN = $(RTE_SDK_BIN)/app/dpdk-pmdinfogen $@ $@.pmd.c
 PMDINFO_CC = $(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@.pmd.o $@.pmd.c
@@ -75,7 +75,7 @@ C_TO_O_DO = @set -e; \
 	echo $(C_TO_O_DISP); \
 	$(C_TO_O) && \
 	$(PMDINFO_TO_O) && \
-	$(CHECK_EXPERIMENTAL) && \
+	$(CHECK_SPECIAL_SYMS) && \
 	echo $(C_TO_O_CMD) > $(call obj2cmd,$(@)) && \
 	sed 's,'$@':,dep_'$@' =,' $(call obj2dep,$(@)).tmp > $(call obj2dep,$(@)) && \
 	rm -f $(call obj2dep,$(@)).tmp
diff --git a/mk/target/generic/rte.vars.mk b/mk/target/generic/rte.vars.mk
index 25a578ad7..ed6a0c87b 100644
--- a/mk/target/generic/rte.vars.mk
+++ b/mk/target/generic/rte.vars.mk
@@ -96,7 +96,7 @@ LDFLAGS += -L$(RTE_OUTPUT)/lib
 # defined.
 ifeq ($(BUILDING_RTE_SDK),1)
 # building sdk
-CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h
+CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h -DBUILDING_RTE_SDK
 else
 # if we are building an external application, include SDK's lib and
 # includes too
-- 
2.20.1


^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v1 0/9] dpdk: introduce __rte_internal tag
      2019-06-05 16:24  0% ` [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag Jerin Jacob Kollanukkaran
@ 2019-06-12 20:38  4% ` Neil Horman
  2019-06-12 20:38  3%   ` [dpdk-dev] [PATCH v1 1/9] Add __rte_internal tag for functions and version target Neil Horman
                     ` (2 more replies)
  2019-06-13 14:23  4% ` [dpdk-dev] [PATCH v2 0/10] " Neil Horman
  3 siblings, 3 replies; 200+ results
From: Neil Horman @ 2019-06-12 20:38 UTC (permalink / raw)
  To: dev
  Cc: Neil Horman, Jerin Jacob Kollanukkaran, Bruce Richardson,
	Thomas Monjalon

Hey-
        Based on our recent conversations regarding the use of symbols only
meant for internal dpdk consumption (between dpdk libraries), this is an idea
that I've come up with that I'd like to get some feedback on

Summary:
1) We have symbols in the DPDK that are meant to be used between DPDK libraries,
but not by applications linking to them
2) We would like to document those symbols in the code, so as to note them
clearly as for being meant for internal use only
3) Linker symbol visibility is a very coarse grained tool, and so there is no
good way in a single library to mark items as being meant for use only by other
DPDK libraries, at least not without some extensive runtime checking


Proposal:
I'm proposing that we introduce the __rte_internal tag.  From a coding
standpoint it works a great deal like the __rte_experimental tag in that it
expempts the tagged symbol from ABI constraints (as the only users should be
represented in the DPDK build environment).  Additionally, the __rte_internal
macro resolves differently based on the definition of the BUILDING_RTE_SDK flag
(working under the assumption that said flag should only ever be set if we are
actually building DPDK libraries which will make use of internal calls).  If the
BUILDING_RTE_SDK flag is set __rte_internal resolves to __attribute__((section
"text.internal)), placing it in a special text section which is then used to
validate that the the symbol appears in the INTERNAL section of the
corresponding library version map).  If BUILDING_RTE_SDK is not set, then
__rte_internal resolves to __attribute__((error("..."))), which causes any
caller of the tagged function to throw an error at compile time, indicating that
the symbol is not available for external use.

This isn't a perfect solution, as applications can still hack around it of
course, but I think it hits some of the high points, restricting symbol access
for any library that prototypes its public and private symbols in the same
header file, excluding the internal symbols from ABI constraints, and clearly
documenting those symbols which we wish to limit to internal usage.

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
CC: Bruce Richardson <bruce.richardson@intel.com>
CC: Thomas Monjalon <thomas@monjalon.net>



^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [dpdk-announce] DPDK 18.11.2 (LTS) released
@ 2019-06-11 18:42  1% Kevin Traynor
  2019-06-20 17:07  1% ` Ju-Hyoung Lee
  0 siblings, 1 reply; 200+ results
From: Kevin Traynor @ 2019-06-11 18:42 UTC (permalink / raw)
  To: announce

Hi all,

Here is a new LTS release:
	https://fast.dpdk.org/rel/dpdk-18.11.2.tar.xz

The git tree is at:
	https://dpdk.org/browse/dpdk-stable/?h=18.11

Information about this release and validation can be found at:
	http://doc.dpdk.org/guides-18.11/rel_notes/release_18_11.html#id1

This is a big release with ~350 fixes backported.

Thanks to the companies who provided validation
and those who helped with backports.

Kevin Traynor

---
 .ci/linux-build.sh                                 |  24 +
 .ci/linux-setup.sh                                 |   3 +
 .gitignore                                         |   1 +
 .travis.yml                                        |  98 +++
 MAINTAINERS                                        |   8 +-
 app/pdump/main.c                                   |  17 +-
 app/test-bbdev/test_bbdev.c                        |  10 +-
 app/test-crypto-perf/main.c                        |   5 +
 app/test-pmd/cmdline.c                             | 269 ++++++---
 app/test-pmd/cmdline_flow.c                        | 128 +++-
 app/test-pmd/config.c                              |  14 +-
 app/test-pmd/csumonly.c                            |   2 +-
 app/test-pmd/testpmd.c                             |  90 +--
 app/test-pmd/testpmd.h                             |  13 +-
 buildtools/symlink-drivers-solibs.sh               |   7 +-
 config/arm/meson.build                             |  10 +-
 config/meson.build                                 |   7 +
 config/x86/meson.build                             |  21 +-
 devtools/check-symbol-change.sh                    |  44 +-
 devtools/checkpatches.sh                           |   2 +-
 devtools/test-build.sh                             |  12 +-
 devtools/test-meson-builds.sh                      |  10 +-
 doc/guides/compressdevs/overview.rst               |   2 +-
 doc/guides/conf.py                                 |   5 +
 doc/guides/contributing/coding_style.rst           |   4 +-
 doc/guides/contributing/documentation.rst          |   9 +-
 doc/guides/contributing/patches.rst                |   6 +-
 doc/guides/contributing/versioning.rst             |  19 +-
 doc/guides/cryptodevs/aesni_mb.rst                 |   2 +-
 doc/guides/cryptodevs/features/aesni_gcm.ini       |   5 +
 doc/guides/cryptodevs/features/aesni_mb.ini        |  14 +
 doc/guides/cryptodevs/features/armv8.ini           |   5 +
 doc/guides/cryptodevs/features/caam_jr.ini         |   5 +
 doc/guides/cryptodevs/features/ccp.ini             |   5 +
 doc/guides/cryptodevs/features/default.ini         |   9 +
 doc/guides/cryptodevs/features/dpaa2_sec.ini       |   5 +
 doc/guides/cryptodevs/features/dpaa_sec.ini        |   5 +
 doc/guides/cryptodevs/features/kasumi.ini          |   5 +
 doc/guides/cryptodevs/features/mvsam.ini           |   5 +
 doc/guides/cryptodevs/features/null.ini            |   5 +
 doc/guides/cryptodevs/features/octeontx.ini        |   5 +
 doc/guides/cryptodevs/features/qat.ini             |   5 +
 doc/guides/cryptodevs/features/snow3g.ini          |   5 +
 doc/guides/cryptodevs/features/virtio.ini          |   5 +
 doc/guides/cryptodevs/features/zuc.ini             |   5 +
 doc/guides/cryptodevs/openssl.rst                  |   8 +
 doc/guides/cryptodevs/overview.rst                 |   9 +-
 doc/guides/cryptodevs/scheduler.rst                |   2 +-
 doc/guides/eventdevs/opdl.rst                      |   2 +-
 doc/guides/eventdevs/sw.rst                        |   4 +-
 doc/guides/howto/lm_bond_virtio_sriov.rst          |   2 +-
 doc/guides/howto/lm_virtio_vhost_user.rst          |   4 +-
 doc/guides/howto/rte_flow.rst                      |   6 +-
 .../howto/virtio_user_as_exceptional_path.rst      |   8 +-
 .../linux_gsg/cross_build_dpdk_for_arm64.rst       |  16 +-
 doc/guides/linux_gsg/sys_reqs.rst                  |   2 +-
 doc/guides/nics/atlantic.rst                       |   2 +-
 doc/guides/nics/cxgbe.rst                          |   4 +-
 doc/guides/nics/dpaa.rst                           |   2 +-
 doc/guides/nics/dpaa2.rst                          |   2 +-
 doc/guides/nics/enetc.rst                          |   2 +-
 doc/guides/nics/enic.rst                           |  13 +-
 doc/guides/nics/features.rst                       |   4 +-
 doc/guides/nics/features/qede.ini                  |   1 +
 doc/guides/nics/i40e.rst                           |   2 +-
 doc/guides/nics/ixgbe.rst                          |   4 +-
 doc/guides/nics/kni.rst                            |   2 +-
 doc/guides/nics/mlx5.rst                           |  15 +-
 doc/guides/nics/mvpp2.rst                          |   2 +-
 doc/guides/nics/netvsc.rst                         |   2 +-
 doc/guides/nics/sfc_efx.rst                        |  14 +-
 doc/guides/nics/szedata2.rst                       |   2 +-
 doc/guides/nics/tap.rst                            |   2 +-
 doc/guides/platform/dpaa.rst                       |   4 +-
 doc/guides/platform/dpaa2.rst                      |   4 +-
 doc/guides/prog_guide/bbdev.rst                    |   4 +-
 doc/guides/prog_guide/compressdev.rst              |   6 +-
 doc/guides/prog_guide/cryptodev_lib.rst            |  12 +-
 doc/guides/prog_guide/dev_kit_build_system.rst     |   4 +-
 doc/guides/prog_guide/efd_lib.rst                  |   2 +-
 doc/guides/prog_guide/env_abstraction_layer.rst    |  32 +-
 .../prog_guide/event_ethernet_rx_adapter.rst       |   6 +-
 doc/guides/prog_guide/eventdev.rst                 |   6 +-
 doc/guides/prog_guide/kernel_nic_interface.rst     |   2 +-
 .../prog_guide/link_bonding_poll_mode_drv_lib.rst  |   8 +-
 doc/guides/prog_guide/lpm_lib.rst                  |   2 +-
 doc/guides/prog_guide/metrics_lib.rst              |   2 +-
 doc/guides/prog_guide/multi_proc_support.rst       |  22 +-
 doc/guides/prog_guide/poll_mode_drv.rst            |   6 +-
 doc/guides/prog_guide/profile_app.rst              |   4 +-
 doc/guides/prog_guide/rte_flow.rst                 |   8 +-
 doc/guides/prog_guide/rte_security.rst             |  20 +-
 doc/guides/prog_guide/traffic_management.rst       |   2 +-
 doc/guides/prog_guide/vhost_lib.rst                |   2 +-
 doc/guides/rawdevs/ifpga_rawdev.rst                |   2 +-
 doc/guides/rel_notes/known_issues.rst              |   8 +-
 doc/guides/rel_notes/release_17_11.rst             |  10 +-
 doc/guides/rel_notes/release_18_11.rst             | 515 +++++++++++++++-
 doc/guides/sample_app_ug/bbdev_app.rst             |   4 +-
 doc/guides/sample_app_ug/eventdev_pipeline.rst     |   2 +-
 doc/guides/sample_app_ug/intro.rst                 |   2 +-
 doc/guides/sample_app_ug/ip_pipeline.rst           |   4 +-
 doc/guides/sample_app_ug/ipsec_secgw.rst           |   4 +-
 doc/guides/sample_app_ug/performance_thread.rst    |   4 +-
 doc/guides/sample_app_ug/qos_metering.rst          |   2 +-
 doc/guides/sample_app_ug/test_pipeline.rst         |   2 +-
 doc/guides/sample_app_ug/vhost.rst                 |   4 +-
 doc/guides/sample_app_ug/vhost_scsi.rst            |   2 +-
 doc/guides/sample_app_ug/vm_power_management.rst   |  15 +-
 doc/guides/testpmd_app_ug/run_app.rst              |  12 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst        | 158 ++++-
 doc/guides/tools/cryptoperf.rst                    |  22 +-
 doc/guides/tools/proc_info.rst                     |   2 +-
 doc/guides/tools/testbbdev.rst                     |  10 +-
 drivers/bus/dpaa/base/fman/fman_hw.c               |   4 +-
 drivers/bus/fslmc/fslmc_bus.c                      |   6 +-
 drivers/bus/fslmc/qbman/include/compat.h           |   2 +-
 drivers/bus/fslmc/qbman/include/fsl_qbman_debug.h  |   6 +-
 drivers/bus/fslmc/qbman/qbman_debug.c              |   5 +-
 drivers/bus/vdev/vdev.c                            |  17 +-
 drivers/bus/vmbus/linux/vmbus_uio.c                |  56 +-
 drivers/bus/vmbus/private.h                        |   3 +
 drivers/bus/vmbus/vmbus_channel.c                  |  20 +-
 drivers/bus/vmbus/vmbus_common_uio.c               |  22 +-
 drivers/common/cpt/cpt_ucode.h                     |   2 +-
 drivers/common/qat/qat_qp.c                        |  14 +-
 drivers/compress/isal/isal_compress_pmd.c          |   5 +-
 drivers/compress/isal/isal_compress_pmd_ops.c      |  16 +-
 drivers/compress/qat/qat_comp_pmd.c                |   9 +-
 drivers/crypto/caam_jr/caam_jr.c                   |   4 +-
 drivers/crypto/caam_jr/caam_jr_uio.c               |  10 +-
 drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c        |  12 +-
 drivers/crypto/dpaa2_sec/hw/desc/pdcp.h            |   4 +-
 drivers/crypto/dpaa_sec/dpaa_sec.c                 |   2 +-
 drivers/crypto/kasumi/meson.build                  |   8 +-
 drivers/crypto/meson.build                         |   2 +-
 drivers/crypto/openssl/rte_openssl_pmd.c           |  12 +-
 drivers/crypto/qat/qat_sym_session.c               |   3 +-
 drivers/crypto/snow3g/meson.build                  |  13 +
 drivers/crypto/virtio/virtio_logs.h                |   4 +-
 drivers/crypto/virtio/virtio_rxtx.c                |   4 +-
 drivers/crypto/zuc/meson.build                     |   8 +-
 drivers/event/dpaa2/dpaa2_eventdev.h               |   7 +-
 drivers/event/dpaa2/dpaa2_eventdev_logs.h          |   3 +-
 drivers/event/dsw/dsw_evdev.c                      |  13 +-
 drivers/event/meson.build                          |   6 +-
 drivers/event/opdl/opdl_evdev.c                    |   7 +-
 drivers/event/opdl/opdl_evdev_xstats.c             |   7 +-
 drivers/event/opdl/opdl_ring.h                     |   8 +-
 drivers/event/sw/sw_evdev_selftest.c               |  22 +-
 drivers/mempool/dpaa2/dpaa2_hw_mempool.c           |   4 +-
 drivers/mempool/dpaa2/dpaa2_hw_mempool_logs.h      |   3 +-
 drivers/net/atlantic/atl_ethdev.c                  | 106 ++--
 drivers/net/atlantic/atl_rxtx.c                    |  21 +-
 drivers/net/atlantic/atl_types.h                   |   9 +-
 drivers/net/atlantic/hw_atl/hw_atl_b0.c            |  14 +-
 drivers/net/atlantic/hw_atl/hw_atl_b0.h            |   2 +
 drivers/net/atlantic/hw_atl/hw_atl_utils.c         |  19 +-
 drivers/net/atlantic/hw_atl/hw_atl_utils.h         |  16 +-
 drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c    | 130 ++--
 drivers/net/avf/avf_ethdev.c                       |   3 +-
 drivers/net/axgbe/axgbe_common.h                   |   4 +-
 drivers/net/bnx2x/bnx2x.c                          |  59 +-
 drivers/net/bnx2x/bnx2x.h                          |   9 +-
 drivers/net/bnx2x/bnx2x_ethdev.c                   |  32 +-
 drivers/net/bnx2x/bnx2x_rxtx.c                     |  21 +-
 drivers/net/bnx2x/bnx2x_rxtx.h                     |   3 +-
 drivers/net/bnx2x/ecore_hsi.h                      |   2 +-
 drivers/net/bnx2x/ecore_reg.h                      |   2 +-
 drivers/net/bnx2x/ecore_sp.c                       |  12 +-
 drivers/net/bnx2x/ecore_sp.h                       |  17 +-
 drivers/net/bnx2x/elink.h                          |   2 +-
 drivers/net/bnxt/bnxt.h                            |   2 +-
 drivers/net/bnxt/bnxt_ethdev.c                     |  22 +-
 drivers/net/bnxt/bnxt_rxq.c                        |   3 +-
 drivers/net/bnxt/bnxt_rxr.c                        |   4 +-
 drivers/net/bonding/rte_eth_bond_8023ad.c          |  22 +-
 drivers/net/bonding/rte_eth_bond_8023ad_private.h  |   1 +
 drivers/net/bonding/rte_eth_bond_alb.c             |   4 +-
 drivers/net/bonding/rte_eth_bond_api.c             |   8 +-
 drivers/net/bonding/rte_eth_bond_pmd.c             | 167 +++---
 drivers/net/bonding/rte_eth_bond_private.h         |  15 +-
 drivers/net/cxgbe/base/t4_hw.c                     |   2 +-
 drivers/net/cxgbe/base/t4_pci_id_tbl.h             |  52 +-
 drivers/net/cxgbe/cxgbe.h                          |  24 +-
 drivers/net/cxgbe/cxgbe_ethdev.c                   |  15 +-
 drivers/net/cxgbe/cxgbe_main.c                     |  36 +-
 drivers/net/cxgbe/cxgbevf_main.c                   |  10 +-
 drivers/net/cxgbe/sge.c                            |  78 ++-
 drivers/net/dpaa2/dpaa2_pmd_logs.h                 |   3 +-
 drivers/net/e1000/base/e1000_82575.h               |   4 +-
 drivers/net/e1000/base/e1000_ich8lan.c             |   2 +-
 drivers/net/enetc/enetc_ethdev.c                   |   6 +-
 drivers/net/enetc/enetc_rxtx.c                     |  12 +-
 drivers/net/enic/enic.h                            |  12 +-
 drivers/net/enic/enic_clsf.c                       |  38 +-
 drivers/net/enic/enic_flow.c                       | 659 ++++++++++++---------
 drivers/net/enic/enic_main.c                       |   9 +-
 drivers/net/enic/enic_res.c                        |   5 +-
 drivers/net/enic/enic_rxtx_common.h                |   3 +-
 drivers/net/fm10k/fm10k_rxtx.c                     |   4 +-
 drivers/net/fm10k/fm10k_rxtx_vec.c                 |   6 +-
 drivers/net/i40e/i40e_ethdev.c                     |  60 +-
 drivers/net/i40e/i40e_ethdev_vf.c                  |   5 +-
 drivers/net/i40e/i40e_flow.c                       |   8 +
 drivers/net/i40e/i40e_rxtx.c                       |  11 +-
 drivers/net/i40e/rte_pmd_i40e.h                    |   4 +-
 drivers/net/ixgbe/ixgbe_rxtx.c                     |   6 +-
 drivers/net/kni/rte_eth_kni.c                      |   5 +-
 drivers/net/mlx4/mlx4.c                            |  14 +-
 drivers/net/mlx4/mlx4.h                            |  26 +-
 drivers/net/mlx4/mlx4_ethdev.c                     |  38 +-
 drivers/net/mlx4/mlx4_flow.c                       |  67 ++-
 drivers/net/mlx4/mlx4_flow.h                       |   6 +-
 drivers/net/mlx4/mlx4_intr.c                       |  40 +-
 drivers/net/mlx4/mlx4_mr.c                         |  51 +-
 drivers/net/mlx4/mlx4_rxq.c                        |  56 +-
 drivers/net/mlx4/mlx4_rxtx.h                       |  18 +-
 drivers/net/mlx4/mlx4_txq.c                        |  14 +-
 drivers/net/mlx5/mlx5.c                            |  23 +-
 drivers/net/mlx5/mlx5.h                            |   7 +-
 drivers/net/mlx5/mlx5_defs.h                       |   3 +-
 drivers/net/mlx5/mlx5_ethdev.c                     |  28 +-
 drivers/net/mlx5/mlx5_flow.c                       |  72 ++-
 drivers/net/mlx5/mlx5_flow.h                       |   1 +
 drivers/net/mlx5/mlx5_flow_dv.c                    |  20 +-
 drivers/net/mlx5/mlx5_flow_tcf.c                   |   8 +-
 drivers/net/mlx5/mlx5_flow_verbs.c                 |  12 +-
 drivers/net/mlx5/mlx5_mac.c                        |   4 +-
 drivers/net/mlx5/mlx5_mr.c                         |  57 +-
 drivers/net/mlx5/mlx5_nl.c                         |  12 +-
 drivers/net/mlx5/mlx5_rss.c                        |  10 +-
 drivers/net/mlx5/mlx5_rxmode.c                     |   8 +-
 drivers/net/mlx5/mlx5_rxq.c                        |  71 +--
 drivers/net/mlx5/mlx5_rxtx.c                       |   5 +-
 drivers/net/mlx5/mlx5_rxtx.h                       |   9 +-
 drivers/net/mlx5/mlx5_rxtx_vec.c                   |   4 +-
 drivers/net/mlx5/mlx5_rxtx_vec.h                   |  17 +-
 drivers/net/mlx5/mlx5_rxtx_vec_neon.h              |  12 +-
 drivers/net/mlx5/mlx5_rxtx_vec_sse.h               |  11 +-
 drivers/net/mlx5/mlx5_socket.c                     |   8 +-
 drivers/net/mlx5/mlx5_stats.c                      |  14 +-
 drivers/net/mlx5/mlx5_trigger.c                    |  16 +-
 drivers/net/mlx5/mlx5_txq.c                        |  65 +-
 drivers/net/mlx5/mlx5_vlan.c                       |   6 +-
 drivers/net/mvpp2/mrvl_mtr.c                       |   3 +-
 drivers/net/netvsc/hn_ethdev.c                     |   3 +-
 drivers/net/netvsc/hn_rxtx.c                       |  55 +-
 drivers/net/netvsc/hn_var.h                        |  32 +-
 drivers/net/netvsc/hn_vf.c                         |  86 +--
 drivers/net/nfp/nfp_net.c                          |  53 +-
 drivers/net/nfp/nfp_net_ctrl.h                     |   4 +-
 drivers/net/nfp/nfp_net_pmd.h                      |   4 +-
 drivers/net/nfp/nfpcore/nfp-common/nfp_cppat.h     |   3 +
 drivers/net/nfp/nfpcore/nfp_cpp_pcie_ops.c         |  18 +-
 drivers/net/nfp/nfpcore/nfp_cppcore.c              |   9 +-
 drivers/net/octeontx/octeontx_ethdev.h             |   1 +
 drivers/net/pcap/rte_eth_pcap.c                    |   5 +-
 drivers/net/qede/base/common_hsi.h                 |   4 +-
 drivers/net/qede/base/ecore_hsi_common.h           |   2 +-
 drivers/net/qede/base/ecore_hsi_eth.h              |   2 +-
 drivers/net/qede/base/ecore_hw_defs.h              |   2 +-
 drivers/net/qede/qede_ethdev.c                     |   6 +-
 drivers/net/qede/qede_rxtx.c                       |  17 +-
 drivers/net/ring/rte_eth_ring.c                    |  96 +--
 drivers/net/sfc/sfc.c                              |   6 +-
 drivers/net/sfc/sfc.h                              |   2 +-
 drivers/net/sfc/sfc_debug.h                        |   3 +-
 drivers/net/sfc/sfc_ef10_tx.c                      |  11 +-
 drivers/net/sfc/sfc_ethdev.c                       |  72 ++-
 drivers/net/sfc/sfc_mcdi.c                         |   3 +-
 drivers/net/sfc/sfc_rx.c                           |  22 +-
 drivers/net/sfc/sfc_rx.h                           |   4 +
 drivers/net/sfc/sfc_tso.c                          |  11 +-
 drivers/net/sfc/sfc_tx.c                           |   3 +-
 drivers/net/softnic/rte_eth_softnic_flow.c         |   5 +-
 drivers/net/tap/rte_eth_tap.c                      |  28 +-
 drivers/net/tap/tap_bpf_program.c                  |   2 +-
 drivers/net/vdev_netvsc/vdev_netvsc.c              |   7 +-
 drivers/net/virtio/virtio_ethdev.c                 |  24 +-
 drivers/net/virtio/virtio_ethdev.h                 |   2 +
 drivers/net/virtio/virtio_rxtx.c                   |  36 +-
 drivers/net/virtio/virtio_user/vhost.h             |   4 +-
 drivers/net/virtio/virtio_user/vhost_kernel_tap.c  |  12 +-
 drivers/net/virtio/virtio_user/vhost_user.c        |   5 +-
 drivers/net/virtio/virtio_user/virtio_user_dev.c   |   3 +-
 drivers/net/virtio/virtio_user/virtio_user_dev.h   |   2 +-
 drivers/net/virtio/virtio_user_ethdev.c            |  61 +-
 drivers/net/vmxnet3/vmxnet3_ethdev.c               |   1 +
 drivers/raw/dpaa2_cmdif/dpaa2_cmdif.c              |   2 +
 drivers/raw/dpaa2_qdma/dpaa2_qdma.c                |  21 +-
 drivers/raw/dpaa2_qdma/rte_pmd_dpaa2_qdma.h        |   4 +-
 drivers/raw/ifpga_rawdev/ifpga_rawdev.c            |   3 +-
 drivers/raw/ifpga_rawdev/ifpga_rawdev.h            |   4 +-
 drivers/raw/skeleton_rawdev/skeleton_rawdev.c      |   5 +
 examples/ethtool/lib/rte_ethtool.h                 |   4 +-
 examples/fips_validation/main.c                    |   8 +-
 examples/ip_pipeline/meson.build                   |   1 +
 examples/ipsec-secgw/Makefile                      |   2 +-
 examples/ipsec-secgw/esp.c                         |   5 +-
 examples/ipsec-secgw/ipsec-secgw.c                 |  26 +-
 examples/ipsec-secgw/ipsec.h                       |  14 +-
 examples/ipsec-secgw/sa.c                          |  58 +-
 examples/ipsec-secgw/sp4.c                         |  47 +-
 examples/ipsec-secgw/sp6.c                         |  47 +-
 examples/l2fwd-cat/cat.c                           |   2 +-
 .../client_server_mp/mp_server/init.c              |  13 +-
 examples/performance-thread/common/lthread_api.h   |  10 +-
 examples/vhost_crypto/meson.build                  |   1 +
 examples/vhost_scsi/vhost_scsi.c                   |   6 +
 examples/vm_power_manager/channel_monitor.c        |  12 +-
 examples/vm_power_manager/main.c                   |  15 +-
 examples/vm_power_manager/oob_monitor_x86.c        |  23 +-
 examples/vm_power_manager/power_manager.c          |   2 +-
 kernel/linux/kni/ethtool/igb/igb_main.c            |   6 +
 kernel/linux/kni/ethtool/igb/kcompat.h             |   4 +
 kernel/linux/kni/kni_misc.c                        |   2 +-
 lib/librte_acl/acl_vect.h                          |   4 +-
 lib/librte_acl/meson.build                         |   2 +-
 lib/librte_bbdev/rte_bbdev.h                       |   4 +-
 lib/librte_bitratestats/rte_bitrate.c              |   6 +-
 lib/librte_bpf/rte_bpf.h                           |   6 +-
 lib/librte_bpf/rte_bpf_ethdev.h                    |   4 +-
 lib/librte_cfgfile/rte_cfgfile.c                   |   4 +-
 lib/librte_cryptodev/rte_crypto_asym.h             |  10 +-
 lib/librte_cryptodev/rte_cryptodev.c               |   4 +-
 lib/librte_cryptodev/rte_cryptodev.h               |   2 +-
 lib/librte_distributor/rte_distributor_private.h   |   2 +-
 lib/librte_eal/bsdapp/eal/eal.c                    |  14 +-
 lib/librte_eal/bsdapp/eal/eal_hugepage_info.c      |   2 +-
 lib/librte_eal/common/eal_common_memory.c          |  13 +-
 lib/librte_eal/common/eal_common_options.c         | 243 +++++---
 lib/librte_eal/common/eal_common_proc.c            |  57 +-
 lib/librte_eal/common/eal_common_thread.c          |  23 +-
 lib/librte_eal/common/eal_internal_cfg.h           |   3 +
 lib/librte_eal/common/eal_options.h                |   2 +
 lib/librte_eal/common/hotplug_mp.c                 |   2 +-
 .../common/include/arch/ppc_64/rte_atomic.h        |   8 -
 lib/librte_eal/common/include/generic/rte_cycles.h |   2 +-
 lib/librte_eal/common/include/generic/rte_rwlock.h |  16 +-
 .../common/include/generic/rte_spinlock.h          |  18 +-
 lib/librte_eal/common/include/generic/rte_vect.h   |   2 +-
 lib/librte_eal/common/include/rte_class.h          |   2 +-
 lib/librte_eal/common/include/rte_common.h         |   4 +-
 lib/librte_eal/common/include/rte_eal.h            |  26 +-
 lib/librte_eal/common/include/rte_lcore.h          |  17 +-
 lib/librte_eal/common/include/rte_log.h            |   2 +-
 lib/librte_eal/common/include/rte_malloc.h         |   2 +-
 lib/librte_eal/common/include/rte_service.h        |   2 +-
 lib/librte_eal/common/include/rte_string_fns.h     |  16 +
 lib/librte_eal/common/include/rte_tailq.h          |   2 +-
 lib/librte_eal/common/include/rte_uuid.h           |   4 +-
 lib/librte_eal/common/include/rte_version.h        |   2 +-
 lib/librte_eal/common/include/rte_vfio.h           |   6 +-
 lib/librte_eal/common/malloc_mp.c                  |   2 +-
 lib/librte_eal/linuxapp/eal/eal.c                  |  19 +-
 lib/librte_eal/linuxapp/eal/eal_dev.c              |   4 +-
 lib/librte_eal/linuxapp/eal/eal_hugepage_info.c    |   2 +-
 lib/librte_eal/linuxapp/eal/eal_memalloc.c         |   4 +
 lib/librte_eal/linuxapp/eal/eal_memory.c           |  26 +-
 .../linuxapp/eal/include/exec-env/rte_kni_common.h |   2 +-
 lib/librte_efd/rte_efd.h                           |   2 +-
 lib/librte_ethdev/rte_eth_ctrl.h                   |   2 +-
 lib/librte_ethdev/rte_ethdev.c                     |   7 +-
 lib/librte_ethdev/rte_ethdev.h                     |  10 +-
 lib/librte_ethdev/rte_ethdev_core.h                |   4 +-
 lib/librte_ethdev/rte_ethdev_driver.h              |   2 +-
 lib/librte_ethdev/rte_tm.h                         |   8 +-
 lib/librte_eventdev/rte_event_crypto_adapter.c     |  16 +-
 lib/librte_eventdev/rte_event_crypto_adapter.h     |   2 +-
 lib/librte_eventdev/rte_event_eth_rx_adapter.c     |   2 +-
 lib/librte_eventdev/rte_event_eth_rx_adapter.h     |   4 +-
 lib/librte_eventdev/rte_event_eth_tx_adapter.h     |   3 +-
 lib/librte_eventdev/rte_eventdev.h                 |  21 +-
 lib/librte_eventdev/rte_eventdev_pmd.h             |   2 +-
 lib/librte_flow_classify/rte_flow_classify.h       |   4 +-
 lib/librte_hash/rte_cuckoo_hash.c                  |  15 +-
 lib/librte_hash/rte_hash.h                         |   4 +-
 lib/librte_ip_frag/rte_ip_frag.h                   |   2 +-
 lib/librte_kni/rte_kni.h                           |   2 +-
 lib/librte_latencystats/rte_latencystats.h         |   2 +-
 lib/librte_lpm/rte_lpm.h                           |   2 +-
 lib/librte_mbuf/rte_mbuf.h                         |  18 +-
 lib/librte_mbuf/rte_mbuf_ptype.h                   |   2 +-
 lib/librte_mempool/rte_mempool.h                   |   4 +-
 lib/librte_net/rte_ether.h                         |   2 +-
 lib/librte_power/power_acpi_cpufreq.c              |   5 +-
 lib/librte_power/rte_power.c                       |  30 +-
 lib/librte_power/rte_power.h                       |   2 +-
 lib/librte_power/rte_power_empty_poll.c            |   3 -
 lib/librte_power/rte_power_empty_poll.h            |   2 +-
 lib/librte_rawdev/rte_rawdev.h                     |   6 +-
 lib/librte_rawdev/rte_rawdev_pmd.h                 |   8 +-
 lib/librte_reorder/rte_reorder.h                   |   2 +-
 lib/librte_ring/rte_ring.c                         |   3 +-
 lib/librte_ring/rte_ring.h                         |   4 +-
 lib/librte_ring/rte_ring_generic.h                 |   9 +-
 lib/librte_sched/rte_sched.h                       |   2 +-
 lib/librte_security/rte_security.h                 |   4 +-
 lib/librte_table/rte_table_hash.h                  |   6 +-
 lib/librte_table/rte_table_hash_func.h             |   2 +-
 lib/librte_telemetry/Makefile                      |   5 +
 lib/librte_telemetry/rte_telemetry_parser.c        |  26 +-
 lib/librte_vhost/rte_vhost.h                       |   4 +-
 lib/librte_vhost/socket.c                          |  26 +-
 lib/librte_vhost/vdpa.c                            |   7 +-
 lib/librte_vhost/vhost.c                           |  16 +-
 lib/librte_vhost/vhost.h                           |  46 +-
 lib/librte_vhost/vhost_crypto.c                    |   4 +-
 lib/librte_vhost/vhost_user.c                      |  54 +-
 lib/librte_vhost/virtio_net.c                      |  34 --
 meson.build                                        |   9 +-
 mk/exec-env/linuxapp/rte.vars.mk                   |   6 +
 mk/rte.app.mk                                      |   3 -
 mk/rte.lib.mk                                      |   2 +
 mk/toolchain/gcc/rte.toolchain-compat.mk           |  11 +-
 mk/toolchain/gcc/rte.vars.mk                       |   3 +
 pkg/dpdk.spec                                      |   2 +-
 test/test/autotest_data.py                         |   6 -
 test/test/commands.c                               |  12 +-
 test/test/meson.build                              |   3 +-
 test/test/test_barrier.c                           |   6 +-
 test/test/test_compressdev.c                       |   1 +
 test/test/test_cryptodev.c                         |   3 +-
 test/test/test_cryptodev_blockcipher.h             |   4 +-
 test/test/test_distributor.c                       |   7 +-
 test/test/test_eal_flags.c                         |   1 +
 test/test/test_event_eth_rx_adapter.c              |   3 +-
 test/test/test_hash_perf.c                         |   6 +-
 test/test/test_link_bonding.c                      |  45 +-
 test/test/test_pmd_perf.c                          |  13 +-
 test/test/test_spinlock.c                          |  31 +-
 test/test/test_string_fns.c                        |  45 ++
 433 files changed, 4965 insertions(+), 2398 deletions(-)
Aaron Conole (4):
      net/virtio: fix dangling pointer on failure
      ci: enable ccache in Travis
      ci: add a distinguisher to the extra Travis builds
      ipc: unlock on failure

Abhinandan Gujjar (1):
      eventdev: fix crypto adapter

Agalya Babu RadhaKrishnan (2):
      doc: fix interactive commands in testpmd guide
      app/testpmd: fix help info for interactive commands

Akhil Goyal (3):
      crypto/dpaa2_sec: fix session clearing
      crypto/dpaa2_sec: fix offset calculation for GCM
      crypto/dpaa: fix session destroy

Alejandro Lucero (5):
      net/nfp: fix RSS query
      net/nfp: fix file descriptor check
      net/nfp: fix potential integer overflow
      net/nfp: check return value
      net/nfp: fix memory leak

Anatoly Burakov (11):
      malloc: fix documentation of realloc function
      vfio: document multiprocess limitation for container API
      malloc: fix IPC message initialization
      mem: warn user when running without NUMA support
      eal: fix cleanup in no-shconf mode
      ipc: fix send error handling
      ipc: harden message receive
      ipc: handle more invalid parameter cases
      doc: fix typo in IPC guide
      ipc: add warnings about not using IPC with memory API
      ipc: add warnings about correct API usage

Andrew Rybchenko (3):
      net/sfc: remove control path logging from Rx queue count
      net/sfc: fix logging from secondary process
      net/sfc: fix speed capabilities reported in device info

Andrius Sirvys (4):
      drivers/net: fix shifting 32-bit signed variable 31 times
      acl: fix compiler flags with meson and AVX2 runtime
      net/virtio: fix duplicate naming of include guard
      bitrate: fix unchecked return value

Andy Pei (1):
      raw/ifpga: modify log output

Anoob Joseph (2):
      common/cpt: fix null auth only
      cryptodev: fix driver name comparison

Arek Kusztal (2):
      crypto/openssl: fix big numbers after computations
      crypto/openssl: fix modexp

Beilei Xing (2):
      net/i40e: fix logging on VF close
      net/i40e: fix link speed for X722

Bernard Iremonger (1):
      examples/ipsec-secgw: fix debug logs

Bill Hong (1):
      net: fix Tx VLAN flag for offload emulation

Bruce Richardson (24):
      test/compress: fix missing header include
      examples/ip_pipeline: disable build when no epoll
      examples/vhost_crypto: fix dependency on vhost library
      devtools: fix build test on FreeBSD
      eal: support strlcat function
      telemetry: fix mapping of statistics
      eal: tighten permissions on shared memory files
      net/bonding: fix buffer length when printing strings
      devtools: skip meson build for missing compilers
      devtools: support older compilers with meson test
      examples/l2fwd-cat: fix build on FreeBSD
      app/crypto-perf: check range of socket id
      examples/vhost_scsi: fix null-check for parameter
      net/i40e: fix dereference before null check in mbuf release
      net/i40e: fix dereference before check when getting EEPROM
      app/testpmd: fix variable use before null check
      crypto/snow3g: add to meson build
      crypto/kasumi: fix dependency check
      crypto/zuc: fix dependency check
      net/ixgbe: fix warning with GCC 9
      bus/fslmc: fix warning with GCC 9
      raw/skeleton: fix warnings with GCC 9
      raw/dpaa2_cmdif: fix warnings with GCC 9
      build: fix ninja install on FreeBSD

Chaitanya Babu Talluri (3):
      drivers/net: fix possible overflow using strlcat
      test/crypto: fix possible overflow using strlcat
      cfgfile: replace strcat with strlcat

Chas Williams (3):
      net/bonding: fix Tx in 802.3ad mode
      net/bonding: fix slave Tx burst for mode 4
      net/bonding: fix link status

Chenbo Xia (2):
      app/testpmd: fix return value check
      net/virtio-user: fix return value check

Darek Stojaczyk (1):
      eal: initialize alarms early

David Christensen (5):
      maintainers: update for IBM POWER
      examples/power: fix build with some disabled PMDs
      test/barrier: fix typo in log
      test/barrier: fix allocation check
      test/barrier: fix for Power CPUs

David Harton (1):
      net/ixgbe: restore VLAN filter for VF

David Hunt (5):
      power: fix governor storage to trim newlines
      examples/power: fix resource leak
      examples/power: fix unreachable VF MAC init
      examples/power: fix buffer overrun
      examples/power: fix json null termination

David Marchand (19):
      eal: fix check when retrieving current CPU affinity
      eal: fix control threads pinnning
      eal: restrict control threads to startup CPU affinity
      eal: remove dead code in core list parsing
      eal: fix core list validation with disabled cores
      app/testpmd: remove unused field from port struct
      doc: fix examples in bonding guide
      net/bonding: fix port id types
      net/bonding: fix slave id types
      net/bonding: fix packet count type for LACP
      net/bonding: fix queue index types
      app/testpmd: add missing newline when showing statistics
      app/testpmd: extend forwarding statistics to 64 bits
      app/testpmd: remove useless casts on statistics
      doc: fix ABI check script examples
      test: clean remaining trace of devargs autotest
      devtools: fix symbol name in check log
      devtools: accept experimental symbol promotion
      devtools: fix check of symbol added as stable API

Davide Caratti (1):
      net/bnxt: support IOVA VA mode

Dekel Peled (13):
      net/mlx5: fix Tx metadata for multi-segment packet
      net/mlx5: fix hex dump of error completion
      net/mlx5: fix sync when handling Tx completions
      eal/ppc: fix global memory barrier
      eal: fix typo in comment of vector function
      doc: fix links to doxygen and sphinx sites
      net/mlx5: fix errno typos in comments
      doc: fix typos in mlx5 guide
      doc: fix typos in testpmd user guide
      app/testpmd: fix typo in comment
      ethdev: fix typo in error messages
      net/mlx5: fix comments mixing Rx and Tx
      net/mlx5: fix release of Rx queue object

Dharmik Thakkar (2):
      hash: fix position returned in free slots
      hash: fix total entries count

Erik Gabriel Carrillo (1):
      eventdev: update references to removed function

Fan Zhang (3):
      examples/ipsec-secgw: fix AES-CTR block size
      vhost/crypto: fix parens
      crypto/virtio: fix IV offset

Ferruh Yigit (6):
      kni: fix build with Linux 5.1
      mbuf: update Tx VLAN and QinQ flags documentation
      build: fix meson binutils workaround
      build: fix crash by disabling AVX512 with binutils 2.31
      net/ring: fix return value check
      net/kni: fix return value check

Fiona Trahe (2):
      doc: fix missing asymmetric crypto table
      crypto/qat: fix null cipher algo for non 8-byte multiple

Gagandeep Singh (6):
      crypto/caam_jr: fix shared descriptor endianness
      crypto/caam_jr: fix total length in auth only s/g
      crypto/caam_jr: fix memory leak and illegal access
      net/enetc: fix SMMU unhandled context fault
      net/enetc: fix big endian build and buffer allocation
      net/enetc: fix crash at high speed traffic

Gage Eads (2):
      app/pdump: remove only created vdevs
      ring: fix namesize macro documentation block

Gavin Hu (4):
      ring: enforce reading tail before slots
      test/spinlock: remove delay for correct benchmarking
      test/spinlock: amortize the cost of getting time
      spinlock: reimplement with atomic one-way barrier

Hari Kumar Vemula (1):
      net/bonding: fix values of descriptor limits

Harry van Haaren (1):
      event/sw: fix enqueue checks in self-test

Hemant Agrawal (3):
      mempool/dpaa2: fix continuous print on empty pool
      test/crypto: fix duplicate id used by CCP device
      raw/dpaa2_qdma: fix spin lock release

Herakliusz Lipiec (5):
      net/tap: fix multi process reply buffer
      ipc: fix memory leak on request failure
      net/tap: fix memory leak on IPC request
      net/tap: fix potential IPC buffer overrun
      doc: fix broken link in LPM guide

Hyong Youb Kim (12):
      net/bonding: avoid warning for invalid port
      net/enic: fix flow director SCTP matching
      net/enic: fix SCTP match for flow API
      net/enic: allow flow mark ID 0
      net/enic: check for unsupported flow item types
      net/enic: reset VXLAN port regardless of overlay offload
      net/enic: fix VXLAN match
      net/enic: fix endianness in VLAN match
      net/enic: fix max MTU calculation
      net/enic: move arguments into struct
      net/enic: fix inner packet matching
      net/enic: fix VLAN inner type matching for old hardware

Igor Romanov (4):
      app/testpmd: fix stdout flush after printing stats
      net/sfc: improve TSO header length check in EFX datapath
      net/sfc: improve TSO header length check in EF10 datapath
      net/sfc: fix MTU change to check Rx scatter consistency

Igor Russkikh (11):
      net/atlantic: fix negative error codes
      net/atlantic: remove unused variable
      net/atlantic: remove extra checks for error codes
      net/atlantic: fix link configuration
      net/atlantic: fix missing VLAN filter offload
      net/atlantic: fix xstats return
      net/atlantic: enable broadcast traffic
      net/atlantic: extra line at eof
      net/atlantic: fix max eeprom size
      net/atlantic: validity check for eeprom dev address
      net/atlantic: eliminate excessive log levels on Rx/Tx

Ilya Maximets (4):
      net/virtio: add barriers for extra descriptors on Rx split
      vhost: fix device leak on connection add failure
      vhost: fix passing destroyed device to destroy callback
      vhost: fix silent queue enabling with legacy guests

Ivan Malov (1):
      net/sfc: log port ID as 16-bit unsigned integer on panic

Jens Freimann (1):
      net/virtio: set offload flag for jumbo frames

Jerin Jacob (3):
      mk: fix AVX512 disabled warning on non x86
      build: remove meson warning for Arm
      table: fix arm64 hash function selection

Jiayu Hu (1):
      vhost: fix interrupt suppression for the split ring

Jie Pan (1):
      kni: fix type for MAC address

John McNamara (2):
      doc: fix spelling reported by aspell in guides
      doc: fix spelling reported by aspell in comments

Joyce Kong (2):
      doc: update cross Arm toolchain in Linux guide
      rwlock: reimplement with atomic builtins

Julien Meunier (1):
      test/pmd_perf: fix the way to drain the port

Kevin Traynor (8):
      net/qede: support IOVA VA mode
      eal/linux: fix log levels for pagemap reading failure
      doc: fix formatting in testpmd guide
      bus/fslmc: fix warning with GCC 9
      mk: disable packed member pointer warning for telemetry
      version: 18.11.2-rc1
      Revert "app/testpmd: fix offload flags after port config"
      version: 18.11.2

Konstantin Ananyev (1):
      examples/ipsec-secgw: fix SPD no-match case

Krzysztof Kanas (1):
      test/bonding: fix MAC assignment for re-run

Li Qiang (1):
      raw/ifpga: fix file descriptor leak in error path

Liang Zhang (1):
      net/bonding: fix LACP negotiation

Luca Boccassi (1):
      build: use default flags for default Arm machine

Lukasz Krakowiak (1):
      doc: fix JSON interface for power sample

Marcin Hajkowski (1):
      power: fix thread-safety environment modification

Marcin Smoczynski (1):
      examples/ipsec-secgw: fix build error log

Mark Gillott (1):
      net/vmxnet3: add VLAN filter capability

Marko Kovacevic (2):
      compress/qat: fix setup inter buffers
      examples/fips_validation: fix CMAC test

Mattias Rönnblom (3):
      event/dsw: fix capability flags
      power: fix cache line alignment
      event/dsw: ignore scheduling type for single-link queues

Maxime Coquelin (1):
      vhost: prevent disabled rings to be processed with zero-copy

Michael Santana (2):
      devtools: fix result of svg include check
      ci: introduce Travis builds for GitHub repositories

Mohammad Abdul Awal (1):
      vhost: fix null pointer checking

Natanael Copa (7):
      eal/linux: remove thread ID from debug message
      bus/fslmc: remove unused include of error.h
      bus/fslmc: fix build with musl libc
      net/nfp: fix build with musl libc
      net/netvsc: fix include of fcntl.h
      app/test: fix flags with meson
      app/test: fix build with musl libc

Nikhil Rao (1):
      eventdev: fix Rx adapter event flush

Nithin Dabilpuram (2):
      app/testpmd: fix Tx VLAN and QinQ dependency
      app/testpmd: fix Tx QinQ set

Oleg Polyakov (1):
      net/tap: fix getting max iovec

Ori Kam (1):
      net/mlx5: fix RSS validation function

Pablo Cascón (1):
      net/nfp: fix setting MAC address

Pablo de Lara (1):
      doc: add missing algorithms for AESNI-MB PMD

Pallantla Poornima (10):
      vhost: fix sprintf with snprintf
      net/softnic: fix possible buffer overflow
      event/opdl: replace sprintf with snprintf
      net/nfp: fix possible buffer overflow
      app/test: fix sprintf with strlcat
      test/event: replace sprintf with snprintf
      power: remove unused variable
      test/distributor: replace sprintf with strlcpy
      test/hash: replace sprintf with snprintf
      app/bbdev: replace sprintf with snprintf or strlcpy

Pavel Belous (7):
      net/atlantic: fix buffer overflow
      net/atlantic: fix EEPROM get for small and uneven lengths
      net/atlantic: error handling for mailbox access
      net/atlantic: eeprom get/set should consider offset
      net/atlantic: bad logic with offsets talking with firmware
      net/atlantic: flow control settings synchronization on rx
      net/atlantic: use capability bits to detect eeprom access

Qi Zhang (3):
      net/pcap: fix memory leak
      net/i40e: fix time sync for 25G
      net/i40e: fix scattered Rx enabling

Qiming Yang (1):
      net/iavf: fix info get

Rahul Lakkireddy (1):
      net/cxgbe: update Chelsio T5/T6 NIC device ids

Rami Rosen (11):
      net/virtio: remove forward declaration
      mbuf: fix a typo
      doc: fix a minor typo in testpmd guide
      doc: remove reference to rte.doc.mk in programmers guide
      examples/ethtool: fix two typos
      doc: fix link in Linux getting started guide
      doc: fix tag for inner RSS feature
      app/testpmd: fix a typo in log message
      ethdev: fix method name in doxygen comment
      ethdev: fix a typo
      doc: fix two typos in contributing guide

Rasesh Mody (3):
      net/bnx2x: fix MTU for jumbo frame
      net/bnx2x: fix race for periodic flags
      net/bnx2x: fix optic module verification

Raslan Darawsheh (2):
      net/tap: fix multi-process request
      bus/vdev: fix hotplug twice

Reshma Pattan (4):
      examples/power: fix string null termination
      examples/power: fix string overflow
      examples/power: fix overflowed value
      mk: disable warning for packed member pointer

Shahaf Shuler (3):
      net/mlx5: fix packet inline on Tx queue wraparound
      mem: limit use of address hint
      app/testpmd: fix mempool free on exit

Shahed Shaikh (6):
      net/qede: fix Tx packet prepare for tunnel packets
      net/qede: fix Rx packet drop
      doc: add flow API to qede NIC features
      net/bnx2x: fix memory leak
      net/bnx2x: fix ramrod timeout
      net/bnx2x: fix DMAE timeout

Shreyansh Jain (2):
      bus/dpaa: fix Rx discard register mask
      raw/dpaa2_qdma: fix to support multiprocess execution

Somnath Kotur (1):
      net/bnxt: fix big endian build

Stephen Hemminger (26):
      crypto/virtio: use local log type
      net/bnxt: silence IOVA warnings
      net/bnxt: suppress spurious error log
      net/octeontx: fix vdev name
      drivers: fix SPDX license id consistency
      bus/vmbus: fix secondary process setup
      net/netvsc: fix VF support with secondary process
      bus/vmbus: fix check for mmap failure
      bus/vmbus: stop mapping if empty resource found
      bus/vmbus: map ring in secondary process
      bus/fslmc: decrease log level for unsupported devices
      net/vdev_netvsc: fix device cast
      net/bnxt: fix Rx VLAN offload flags
      net/netvsc: remove useless condition
      net/virtio: remove useless condition
      ring: fix an error message
      doc: fix spelling in testpmd guide
      net/virtio: fix buffer leak on VLAN insert
      net/cxgbe: fix colliding function names
      bus/vmbus: fix resource leak on error
      eal: fix formatting of hotplug error message
      net/ring: fix coding style
      net/ring: avoid hard-coded length
      net/ring: use calloc style where appropriate
      net/ring: check length of ring name
      net/netvsc: reset mbuf port on VF Rx

Thomas Monjalon (9):
      ethdev: remove unused variable
      mk: fix build of shared library with libbsd
      devtools: add libelf dependency to build test
      devtools: test build of zlib PMD
      devtools: fix test of some build options
      net/mlx: prefix private structure
      doc: fix PCI whitelist typo in prog guide
      bus/vdev: fix debug message on probing
      doc: fix heading levels in bbdev test guide

Tiwei Bie (8):
      net/virtio: fix in-order Tx path for split ring
      vhost: restore mbuf first when freeing zmbuf
      vhost: fix potential use-after-free for zero copy mbuf
      vhost: fix potential use-after-free for memory region
      net/virtio-user: fix multiqueue with vhost kernel
      net/virtio: add barrier in interrupt enable
      net/virtio-user: fix multi-process support
      app/testpmd: fix unintentional integer overflow

Tomasz Cel (2):
      compress/isal: fix compression stream initialization
      compress/isal: fix getting information about CPU

Tomasz Jozwiak (1):
      drivers/qat: fix queue pair NUMA node

Viacheslav Ovsiienko (3):
      net/mlx5: fix flow priorities probing error path
      net/mlx5: fix memory region cleanup
      net/mlx4: fix memory region cleanup

Vishal Kulkarni (1):
      net/cxgbe: fix missing checksum flags and packet type

Wei Zhao (6):
      net/avf: fix admin queue interrupt for ICE
      net/i40e: log when provided RSS key is not valid
      app/testpmd: fix hex string parser support for flow API
      net/i40e: fix queue number check
      app/testpmd: fix offload flags after port config
      net/i40e: forbid two RSS flow rules

Xiao Wang (1):
      net/fm10k: fix VLAN strip offload flag

Yipeng Wang (1):
      hash: fix doc about thread/process safety

Yongseok Koh (11):
      net/mlx5: fix memory event on secondary process
      net/mlx4: change device reference for secondary process
      net/mlx: remove debug messages on datapath
      net/mlx5: fix external memory registration
      drivers/event: disable OcteonTx for buggy Arm compilers
      net/mlx5: fix instruction hotspot on replenishing Rx buffer
      examples/multi_process: fix buffer underrun
      net/mlx5: check Tx queue size overflow
      net/mlx5: fix max number of queues for NEON Tx
      net/mlx5: fix Multi-Packet RQ mempool name
      doc: fix typo in mlx5 guide

^ permalink raw reply	[relevance 1%]

* Re: [dpdk-dev] [PATCH v1 1/2] lib/ring: add enqueue-dequeue callabck
  2019-06-10  5:12  0%   ` Varghese, Vipin
@ 2019-06-11  4:17  0%     ` Honnappa Nagarahalli
  2019-07-04  5:04  0%       ` Varghese, Vipin
  0 siblings, 1 reply; 200+ results
From: Honnappa Nagarahalli @ 2019-06-11  4:17 UTC (permalink / raw)
  To: Varghese, Vipin, olivier.matz, Pattan, Reshma, Wiles,  Keith, dev
  Cc: Padubidri, Sanjay A, Honnappa Nagarahalli, nd, nd

> 
> Hi Honnappa,
> 
> snipped
> > >
> > > Add callback event handler for enqueue dequeue operation on ring.
> > > The pre-enqueue and post-dequeue operation on ring is selected to
> > > invoke user callback handler.
> > Can you provide a use case for this to better understand the need?
> Use cases:
>  - allow user to investigate the contents pre-enqueue.
>  - allow user to investigate the contents post-dequeue.
>  - modify pre-enqueue and post-dequeue stage content.
>  - investigate PMD meta data for debug in field nodes.
> 
> snipped
> > > +	struct rte_ring_enq_cb_list enq_cbs;
> > > +	struct rte_ring_deq_cb_list deq_cbs; };
> > This breaks ABI compatibility
> Can you help me understand this more clearly?
'struct rte_ring' is exposed to the application. It is possible that the application has declared a variable of type 'struct rte_ring'. Any addition to this structure will increase the size of 'struct rte_ring'. Hence, it won't be compatible.

> 
> snipped
> > > -rte_ring_enqueue_burst(struct rte_ring *r, void * const *obj_table,
> > > +rte_ring_enqueue_burst(struct rte_ring *r, void **obj_table,
> > >  		      unsigned int n, unsigned int *free_space)  {
> > > +#ifdef RTE_RING_ENQDEQ_CALLBACKS
> > > +	struct rte_ring_callback *cb = NULL;
> > > +
> > > +	TAILQ_FOREACH(cb, &(r->enq_cbs), next) {
> > Need to take the TAILQ lock before this. For ex: what happens if a
> > un-register is called concurrently?
> Let me check this, using rx|tx callback as reference.
> 
> > Also, traversing a linked list for every enqueue call would be too
> > costly. May be, understanding the use case will help.
> Internal testing with SP-SC is 0.1% (with extra cost of user function). But I will
> try to explore other alternatives too.
> 
> Snipped

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC 1/3] ethdev: extend flow metadata
  2019-06-10  7:20  0%     ` Andrew Rybchenko
@ 2019-06-11  0:06  0%       ` Yongseok Koh
  2019-06-19  9:05  0%         ` Andrew Rybchenko
  0 siblings, 1 reply; 200+ results
From: Yongseok Koh @ 2019-06-11  0:06 UTC (permalink / raw)
  To: Andrew Rybchenko
  Cc: Wang, Haiyue, Shahaf Shuler, Thomas Monjalon, Yigit, Ferruh,
	Adrien Mazarguil, olivier.matz, dev, Ananyev, Konstantin

On Mon, Jun 10, 2019 at 10:20:28AM +0300, Andrew Rybchenko wrote:
> On 6/10/19 6:19 AM, Wang, Haiyue wrote:
> > > -----Original Message-----
> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Andrew Rybchenko
> > > Sent: Sunday, June 9, 2019 22:24
> > > To: Yongseok Koh <yskoh@mellanox.com>; shahafs@mellanox.com; thomas@monjalon.net; Yigit, Ferruh
> > > <ferruh.yigit@intel.com>; adrien.mazarguil@6wind.com; olivier.matz@6wind.com
> > > Cc: dev@dpdk.org
> > > Subject: Re: [dpdk-dev] [RFC 1/3] ethdev: extend flow metadata
> > > 
> > > On 6/4/19 12:32 AM, Yongseok Koh wrote:
> > > > Currently, metadata can be set on egress path via mbuf tx_meatadata field
> > > > with PKT_TX_METADATA flag and RTE_FLOW_ITEM_TYPE_RX_META matches metadata.
> > > > 
> > > > This patch extends the usability.
> > > > 
> > > > 1) RTE_FLOW_ACTION_TYPE_SET_META
> > > > 
> > > > When supporting multiple tables, Tx metadata can also be set by a rule and
> > > > matched by another rule. This new action allows metadata to be set as a
> > > > result of flow match.
> > > > 
> > > > 2) Metadata on ingress
> > > > 
> > > > There's also need to support metadata on packet Rx. Metadata can be set by
> > > > SET_META action and matched by META item like Tx. The final value set by
> > > > the action will be delivered to application via mbuf metadata field with
> > > > PKT_RX_METADATA ol_flag.
> > > > 
> > > > For this purpose, mbuf->tx_metadata is moved as a separate new field and
> > > > renamed to 'metadata' to support both Rx and Tx metadata.
> > > > 
> > > > For loopback/hairpin packet, metadata set on Rx/Tx may or may not be
> > > > propagated to the other path depending on HW capability.
> > > > 
> > > > Signed-off-by: Yongseok Koh <yskoh@mellanox.com>
> > > There is a mark on Rx which is delivered to application in hash.fdir.hi.
> > > Why do we need one more 32-bit value set by NIC and delivered to
> > > application?
> > > What is the difference between MARK and META on Rx?
> > > When application should use MARK and when META?
> > > Is there cases when both could be necessary?
> > > 
> > In my understanding, MARK is FDIR related thing, META seems to be NIC
> > specific. And we also need this kind of specific data field to export
> > NIC's data to application.
> 
> I think it is better to avoid NIC vendor-specifics in motivation. I
> understand
> that it exists for you, but I think it is better to look at it from RTE flow
> API
> definition point of view: both are 32-bit (except endianess and I'm not sure
> that I understand why meta is defined as big-endian since it is not a value
> coming from or going to network in a packet, I'm sorry that I've missed it
> on review that time), both may be set using action on Rx, both may be
> matched using pattern item.

Yes, MARK and META has the same characteristic on Rx path. Let me clarify why I
picked this way.

What if device has more bits to deliver to host? Currently, only 32-bit data can
be delivered to user via MARK ID. Now we have more requests from users (OVS
connection tracking) that want to see more information generated during flow
match from the device. Let's say it is 64 bits and it may contain intermediate
match results to keep track of multi-table match, to keep address of callback
function to call, or so. I thought about extending the current MARK to 64-bit
but I knew that we couldn't make more room in the first cacheline of mbuf where
every vendor has their critical interest. And the FDIR has been there for a long
time and has lots of use-cases in DPDK (not easy to break). This is why I'm
suggesting to obtain another 32 bits in the second cacheline of the structure.

Also, I thought about other scenario as well. Even though we have MARK item
introduced lately, it isn't used by any PMD at all for now, meaning it might not
be match-able on a certain device. What if there are two types registers on Rx
and one is match-able and the other isn't? PMD can use META for match-able
register while MARK is used for non-match-able register without supporting
item match. If MARK simply becomes 64-bit just because it has the same
characteristic in terms of rte_flow, only one of such registers can be used as
we can't say only part of bits are match-able on the item. Instead of extending
the MARK to 64 bits, I thought it would be better to give more flexibility by
bundling it with Tx metadata, which can set by mbuf.

The actual issue we have may be how we can make it scalable? What if there's
more need to carry more data from device? Well, IIRC, Olivier once suggested to
put a pointer (like mbuf->userdata) to extend mbuf struct beyond two cachelines.
But we still have some space left at the end.

> > > Moreover, the third patch adds 32-bit tags which are not delivered to
> > > application. May be META/MARK should be simply a kind of TAG (e.g. with
> > > index 0 or marked using additional attribute) which is delivered to
> > > application?

Yes, TAG is a kind of transient device-internal data which isn't delivered to
host. It would be a design choice. I could define all these kinds as an array of
MARK IDs having different attributes - some are exportable/match-able and others
are not, which sounds quite complex. As rte_flow doesn't have a direct way to
check device capability (user has to call a series of validate functions
instead), I thought defining TAG would be better.

> > > (It is either API breakage (if tx_metadata is removed) or ABI breakage
> > > if metadata and tx_metadata will share new location after shinfo).

Fortunately, mlx5 is the only entity which uses tx_metadata so far.

> > Make use of udata64 to export NIC metadata to application ?
> > 	RTE_STD_C11
> > 	union {
> > 		void *userdata;   /**< Can be used for external metadata */
> > 		uint64_t udata64; /**< Allow 8-byte userdata on 32-bit */
> > 		uint64_t rx_metadata;
> > 	};
> 
> As I understand it does not work for Tx and I'm not sure that it is
> a good idea to have different locations for Tx and Rx.
> 
> RFC adds it at the end of mbuf, but it was rejected before since
> it eats space in mbuf structure (CC Konstantin).

Yep, I was in the discussion. IIRC, the reason wasn't because it ate space but
because it could recycle unused space on Tx path. We still have 16B after shinfo
and I'm not sure how many bytes we should reserve. I think reserving space for
one pointer would be fine.

Thanks,
Yongseok

> There is a long discussion on the topic before [1], [2], [3] and [4].
> 
> Andrew.
> 
> [1] https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmails.dpdk.org%2Farchives%2Fdev%2F2018-August%2F109660.html&amp;data=02%7C01%7Cyskoh%40mellanox.com%7C6c81080cb68340d2128c08d6ed742746%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636957480475389496&amp;sdata=EFHyECwg0NBRvyrouZqWD6x0WD4xAsqsfYQGrEvS%2BEg%3D&amp;reserved=0
> [2] https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmails.dpdk.org%2Farchives%2Fdev%2F2018-September%2F111771.html&amp;data=02%7C01%7Cyskoh%40mellanox.com%7C6c81080cb68340d2128c08d6ed742746%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636957480475389496&amp;sdata=M8cQSmQhWKlUVKvFgux0T0TWAnJhPxdO4Dn3fkReTyg%3D&amp;reserved=0
> [3] https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmails.dpdk.org%2Farchives%2Fdev%2F2018-October%2F114559.html&amp;data=02%7C01%7Cyskoh%40mellanox.com%7C6c81080cb68340d2128c08d6ed742746%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636957480475394493&amp;sdata=ZVm5god7n1i07OCc5Z7B%2BBUpnjXCraJXU0FeF5KkCRc%3D&amp;reserved=0
> [4] https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmails.dpdk.org%2Farchives%2Fdev%2F2018-October%2F115469.html&amp;data=02%7C01%7Cyskoh%40mellanox.com%7C6c81080cb68340d2128c08d6ed742746%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636957480475394493&amp;sdata=XgKV%2B331Vqsq9Ns40giI1nAwscVxBxqb78vB1BY8z%2Bc%3D&amp;reserved=0

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH v2 4/7] kni: drop unused fields
  @ 2019-06-10 17:51  3% ` Stephen Hemminger
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 200+ results
From: Stephen Hemminger @ 2019-06-10 17:51 UTC (permalink / raw)
  To: ferruh.yigit; +Cc: dev, Stephen Hemminger

The kni net structure only exists in driver no API/ABI.
Several fields were either totally unused or set and never used.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 kernel/linux/kni/kni_dev.h  | 8 --------
 kernel/linux/kni/kni_misc.c | 1 -
 2 files changed, 9 deletions(-)

diff --git a/kernel/linux/kni/kni_dev.h b/kernel/linux/kni/kni_dev.h
index f3a1f60d4bdc..f3e6c3ca4efa 100644
--- a/kernel/linux/kni/kni_dev.h
+++ b/kernel/linux/kni/kni_dev.h
@@ -39,8 +39,6 @@ struct kni_dev {
 	/* kni list */
 	struct list_head list;
 
-	int status;
-	uint16_t group_id;           /* Group ID of a group of KNI devices */
 	uint32_t core_id;            /* Core ID to bind */
 	char name[RTE_KNI_NAMESIZE]; /* Network device name */
 	struct task_struct *pthread;
@@ -49,9 +47,6 @@ struct kni_dev {
 	wait_queue_head_t wq;
 	struct mutex sync_lock;
 
-	/* PCI device id */
-	uint16_t device_id;
-
 	/* kni device */
 	struct net_device *net_dev;
 
@@ -82,9 +77,6 @@ struct kni_dev {
 	/* mbuf size */
 	uint32_t mbuf_size;
 
-	/* synchro for request processing */
-	unsigned long synchro;
-
 	/* buffers */
 	void *pa[MBUF_BURST_SZ];
 	void *va[MBUF_BURST_SZ];
diff --git a/kernel/linux/kni/kni_misc.c b/kernel/linux/kni/kni_misc.c
index af18c67c422f..6a206d883c0d 100644
--- a/kernel/linux/kni/kni_misc.c
+++ b/kernel/linux/kni/kni_misc.c
@@ -346,7 +346,6 @@ kni_ioctl_create(struct net *net, uint32_t ioctl_num,
 	kni = netdev_priv(net_dev);
 
 	kni->net_dev = net_dev;
-	kni->group_id = dev_info.group_id;
 	kni->core_id = dev_info.core_id;
 	strncpy(kni->name, dev_info.name, RTE_KNI_NAMESIZE);
 
-- 
2.20.1


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH 16/39] eventdev: add eventmode CL options framework
  @ 2019-06-10 10:19  3%   ` Jerin Jacob Kollanukkaran
  2019-06-17 10:14  0%     ` Anoob Joseph
  0 siblings, 1 reply; 200+ results
From: Jerin Jacob Kollanukkaran @ 2019-06-10 10:19 UTC (permalink / raw)
  To: Anoob Joseph, Nikhil Rao, Erik Gabriel Carrillo,
	Abhinandan Gujjar, Bruce Richardson, Pablo de Lara
  Cc: Anoob Joseph, Narayana Prasad Raju Athreya, dev, Lukas Bartosik,
	Pavan Nikhilesh Bhagavatula, Hemant Agrawal, Nipun Gupta,
	Harry van Haaren, Mattias Rönnblom, Liang Ma

> -----Original Message-----
> From: Anoob Joseph <anoobj@marvell.com>
> Sent: Monday, June 3, 2019 11:02 PM
> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Nikhil Rao
> <nikhil.rao@intel.com>; Erik Gabriel Carrillo <erik.g.carrillo@intel.com>;
> Abhinandan Gujjar <abhinandan.gujjar@intel.com>; Bruce Richardson
> <bruce.richardson@intel.com>; Pablo de Lara
> <pablo.de.lara.guarch@intel.com>
> Cc: Anoob Joseph <anoobj@marvell.com>; Narayana Prasad Raju Athreya
> <pathreya@marvell.com>; dev@dpdk.org; Lukas Bartosik
> <lbartosik@marvell.com>; Pavan Nikhilesh Bhagavatula
> <pbhagavatula@marvell.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>; Nipun Gupta <nipun.gupta@nxp.com>; Harry
> van Haaren <harry.van.haaren@intel.com>; Mattias Rönnblom
> <mattias.ronnblom@ericsson.com>; Liang Ma <liang.j.ma@intel.com>
> Subject: [PATCH 16/39] eventdev: add eventmode CL options framework
> 
> Adding usage prints and CL parsing routines for eventmode. Option to select
> packet transfer mode is also added.
> 
> Signed-off-by: Anoob Joseph <anoobj@marvell.com>
> Signed-off-by: Lukasz Bartosik <lbartosik@marvell.com>
> ---
> +#include <rte_compat.h>
> +
> +/* Packet transfer mode of the application */ enum
> +rte_eventmode_helper_pkt_transfer_mode {
> +	RTE_EVENTMODE_HELPER_PKT_TRANSFER_MODE_POLL = 0,
> +	RTE_EVENTMODE_HELPER_PKT_TRANSFER_MODE_EVENT,
> +};

Need to mark all public structues as EXPERIMENTAL.
Please grep for EXPERIMENTAL in libeventdev or any other library

> +struct rte_eventmode_helper_conf {
> +	enum rte_eventmode_helper_pkt_transfer_mode mode;
> +		/**< Packet transfer mode of the application */
> +	void *mode_params;
> +		/**< Mode specific parameters */
> +};

Please make this event_helper object as 'opaque'  and move to internal so that it does have
ABI policies and future new features can be added.



^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC 1/3] ethdev: extend flow metadata
  2019-06-10  3:19  0%   ` Wang, Haiyue
@ 2019-06-10  7:20  0%     ` Andrew Rybchenko
  2019-06-11  0:06  0%       ` Yongseok Koh
  0 siblings, 1 reply; 200+ results
From: Andrew Rybchenko @ 2019-06-10  7:20 UTC (permalink / raw)
  To: Wang, Haiyue, Yongseok Koh, shahafs, thomas, Yigit, Ferruh,
	adrien.mazarguil, olivier.matz
  Cc: dev, Ananyev, Konstantin

On 6/10/19 6:19 AM, Wang, Haiyue wrote:
>> -----Original Message-----
>> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Andrew Rybchenko
>> Sent: Sunday, June 9, 2019 22:24
>> To: Yongseok Koh <yskoh@mellanox.com>; shahafs@mellanox.com; thomas@monjalon.net; Yigit, Ferruh
>> <ferruh.yigit@intel.com>; adrien.mazarguil@6wind.com; olivier.matz@6wind.com
>> Cc: dev@dpdk.org
>> Subject: Re: [dpdk-dev] [RFC 1/3] ethdev: extend flow metadata
>>
>> On 6/4/19 12:32 AM, Yongseok Koh wrote:
>>> Currently, metadata can be set on egress path via mbuf tx_meatadata field
>>> with PKT_TX_METADATA flag and RTE_FLOW_ITEM_TYPE_RX_META matches metadata.
>>>
>>> This patch extends the usability.
>>>
>>> 1) RTE_FLOW_ACTION_TYPE_SET_META
>>>
>>> When supporting multiple tables, Tx metadata can also be set by a rule and
>>> matched by another rule. This new action allows metadata to be set as a
>>> result of flow match.
>>>
>>> 2) Metadata on ingress
>>>
>>> There's also need to support metadata on packet Rx. Metadata can be set by
>>> SET_META action and matched by META item like Tx. The final value set by
>>> the action will be delivered to application via mbuf metadata field with
>>> PKT_RX_METADATA ol_flag.
>>>
>>> For this purpose, mbuf->tx_metadata is moved as a separate new field and
>>> renamed to 'metadata' to support both Rx and Tx metadata.
>>>
>>> For loopback/hairpin packet, metadata set on Rx/Tx may or may not be
>>> propagated to the other path depending on HW capability.
>>>
>>> Signed-off-by: Yongseok Koh <yskoh@mellanox.com>
>> There is a mark on Rx which is delivered to application in hash.fdir.hi.
>> Why do we need one more 32-bit value set by NIC and delivered to
>> application?
>> What is the difference between MARK and META on Rx?
>> When application should use MARK and when META?
>> Is there cases when both could be necessary?
>>
> In my understanding, MARK is FDIR related thing, META seems to be NIC
> specific. And we also need this kind of specific data field to export
> NIC's data to application.

I think it is better to avoid NIC vendor-specifics in motivation. I 
understand
that it exists for you, but I think it is better to look at it from RTE 
flow API
definition point of view: both are 32-bit (except endianess and I'm not sure
that I understand why meta is defined as big-endian since it is not a value
coming from or going to network in a packet, I'm sorry that I've missed it
on review that time), both may be set using action on Rx, both may be
matched using pattern item.

>> Moreover, the third patch adds 32-bit tags which are not delivered to
>> application. May be META/MARK should be simply a kind of TAG (e.g. with
>> index 0 or marked using additional attribute) which is delivered to
>> application?
>>
>> (It is either API breakage (if tx_metadata is removed) or ABI breakage
>> if metadata and tx_metadata will share new location after shinfo).
>>
> Make use of udata64 to export NIC metadata to application ?
> 	RTE_STD_C11
> 	union {
> 		void *userdata;   /**< Can be used for external metadata */
> 		uint64_t udata64; /**< Allow 8-byte userdata on 32-bit */
> 		uint64_t rx_metadata;
> 	};

As I understand it does not work for Tx and I'm not sure that it is
a good idea to have different locations for Tx and Rx.

RFC adds it at the end of mbuf, but it was rejected before since
it eats space in mbuf structure (CC Konstantin).

There is a long discussion on the topic before [1], [2], [3] and [4].

Andrew.

[1] http://mails.dpdk.org/archives/dev/2018-August/109660.html
[2] http://mails.dpdk.org/archives/dev/2018-September/111771.html
[3] http://mails.dpdk.org/archives/dev/2018-October/114559.html
[4] http://mails.dpdk.org/archives/dev/2018-October/115469.html

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v1 1/2] lib/ring: add enqueue-dequeue callabck
  2019-06-07  6:03  3% ` Honnappa Nagarahalli
@ 2019-06-10  5:12  0%   ` Varghese, Vipin
  2019-06-11  4:17  0%     ` Honnappa Nagarahalli
  0 siblings, 1 reply; 200+ results
From: Varghese, Vipin @ 2019-06-10  5:12 UTC (permalink / raw)
  To: Honnappa Nagarahalli, olivier.matz, Pattan, Reshma, Wiles, Keith, dev
  Cc: Padubidri, Sanjay A, nd, nd

Hi Honnappa,

snipped
> >
> > Add callback event handler for enqueue dequeue operation on ring.
> > The pre-enqueue and post-dequeue operation on ring is selected to
> > invoke user callback handler.
> Can you provide a use case for this to better understand the need?
Use cases:
 - allow user to investigate the contents pre-enqueue.
 - allow user to investigate the contents post-dequeue.
 - modify pre-enqueue and post-dequeue stage content.
 - investigate PMD meta data for debug in field nodes.

snipped
> > +	struct rte_ring_enq_cb_list enq_cbs;
> > +	struct rte_ring_deq_cb_list deq_cbs; };
> This breaks ABI compatibility
Can you help me understand this more clearly?

snipped
> > -rte_ring_enqueue_burst(struct rte_ring *r, void * const *obj_table,
> > +rte_ring_enqueue_burst(struct rte_ring *r, void **obj_table,
> >  		      unsigned int n, unsigned int *free_space)  {
> > +#ifdef RTE_RING_ENQDEQ_CALLBACKS
> > +	struct rte_ring_callback *cb = NULL;
> > +
> > +	TAILQ_FOREACH(cb, &(r->enq_cbs), next) {
> Need to take the TAILQ lock before this. For ex: what happens if a un-register is
> called concurrently?
Let me check this, using rx|tx callback as reference.

> Also, traversing a linked list for every enqueue call would be too costly. May be,
> understanding the use case will help.
Internal testing with SP-SC is 0.1% (with extra cost of user function). But I will try to explore other alternatives too.

Snipped

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 1/2] eventdev: replace mbufs with events in Rx callback
@ 2019-06-10  4:33  3% Jerin Jacob Kollanukkaran
  0 siblings, 0 replies; 200+ results
From: Jerin Jacob Kollanukkaran @ 2019-06-10  4:33 UTC (permalink / raw)
  To: Nikhil Rao; +Cc: dev



> -----Original Message-----
> From: Nikhil Rao <nikhil.rao@intel.com>
> Sent: Thursday, May 30, 2019 6:50 AM
> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> Cc: dev@dpdk.org; Nikhil Rao <nikhil.rao@intel.com>
> Subject: [EXT] [PATCH 1/2] eventdev: replace mbufs with events in Rx
> callback
> 
> Replace the mbuf pointer array in the event eth Rx adapter callback with an
> event array instead of an mbuf array. Using an event array allows the
> application to change attributes of the events enqueued by the SW adapter.
> 
> Signed-off-by: Nikhil Rao <nikhil.rao@intel.com>
> ---
>  lib/librte_eventdev/rte_event_eth_rx_adapter.h | 57 +++++++++++++++--


# Please bump the library version as it an ABI change 
# Update API change In release notes. 
# remove __rte_experimental around this API
# We kept eventdev EXPERIMENTAL status to accommodate
this change. Please remove the EXPERMENTAL status

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [RFC 1/3] ethdev: extend flow metadata
  2019-06-09 14:23  3% ` Andrew Rybchenko
@ 2019-06-10  3:19  0%   ` Wang, Haiyue
  2019-06-10  7:20  0%     ` Andrew Rybchenko
  0 siblings, 1 reply; 200+ results
From: Wang, Haiyue @ 2019-06-10  3:19 UTC (permalink / raw)
  To: Andrew Rybchenko, Yongseok Koh, shahafs, thomas, Yigit, Ferruh,
	adrien.mazarguil, olivier.matz
  Cc: dev

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Andrew Rybchenko
> Sent: Sunday, June 9, 2019 22:24
> To: Yongseok Koh <yskoh@mellanox.com>; shahafs@mellanox.com; thomas@monjalon.net; Yigit, Ferruh
> <ferruh.yigit@intel.com>; adrien.mazarguil@6wind.com; olivier.matz@6wind.com
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [RFC 1/3] ethdev: extend flow metadata
> 
> On 6/4/19 12:32 AM, Yongseok Koh wrote:
> > Currently, metadata can be set on egress path via mbuf tx_meatadata field
> > with PKT_TX_METADATA flag and RTE_FLOW_ITEM_TYPE_RX_META matches metadata.
> >
> > This patch extends the usability.
> >
> > 1) RTE_FLOW_ACTION_TYPE_SET_META
> >
> > When supporting multiple tables, Tx metadata can also be set by a rule and
> > matched by another rule. This new action allows metadata to be set as a
> > result of flow match.
> >
> > 2) Metadata on ingress
> >
> > There's also need to support metadata on packet Rx. Metadata can be set by
> > SET_META action and matched by META item like Tx. The final value set by
> > the action will be delivered to application via mbuf metadata field with
> > PKT_RX_METADATA ol_flag.
> >
> > For this purpose, mbuf->tx_metadata is moved as a separate new field and
> > renamed to 'metadata' to support both Rx and Tx metadata.
> >
> > For loopback/hairpin packet, metadata set on Rx/Tx may or may not be
> > propagated to the other path depending on HW capability.
> >
> > Signed-off-by: Yongseok Koh <yskoh@mellanox.com>
> 
> There is a mark on Rx which is delivered to application in hash.fdir.hi.
> Why do we need one more 32-bit value set by NIC and delivered to
> application?
> What is the difference between MARK and META on Rx?
> When application should use MARK and when META?
> Is there cases when both could be necessary?
> 
In my understanding, MARK is FDIR related thing, META seems to be NIC
specific. And we also need this kind of specific data field to export
NIC's data to application.

> Moreover, the third patch adds 32-bit tags which are not delivered to
> application. May be META/MARK should be simply a kind of TAG (e.g. with
> index 0 or marked using additional attribute) which is delivered to
> application?
> 
> (It is either API breakage (if tx_metadata is removed) or ABI breakage
> if metadata and tx_metadata will share new location after shinfo).
> 
Make use of udata64 to export NIC metadata to application ?
	RTE_STD_C11
	union {
		void *userdata;   /**< Can be used for external metadata */
		uint64_t udata64; /**< Allow 8-byte userdata on 32-bit */
		uint64_t rx_metadata;
	};
> Andrew.


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [RFC 1/3] ethdev: extend flow metadata
  @ 2019-06-09 14:23  3% ` Andrew Rybchenko
  2019-06-10  3:19  0%   ` Wang, Haiyue
    1 sibling, 1 reply; 200+ results
From: Andrew Rybchenko @ 2019-06-09 14:23 UTC (permalink / raw)
  To: Yongseok Koh, shahafs, thomas, ferruh.yigit, adrien.mazarguil,
	olivier.matz
  Cc: dev

On 6/4/19 12:32 AM, Yongseok Koh wrote:
> Currently, metadata can be set on egress path via mbuf tx_meatadata field
> with PKT_TX_METADATA flag and RTE_FLOW_ITEM_TYPE_RX_META matches metadata.
>
> This patch extends the usability.
>
> 1) RTE_FLOW_ACTION_TYPE_SET_META
>
> When supporting multiple tables, Tx metadata can also be set by a rule and
> matched by another rule. This new action allows metadata to be set as a
> result of flow match.
>
> 2) Metadata on ingress
>
> There's also need to support metadata on packet Rx. Metadata can be set by
> SET_META action and matched by META item like Tx. The final value set by
> the action will be delivered to application via mbuf metadata field with
> PKT_RX_METADATA ol_flag.
>
> For this purpose, mbuf->tx_metadata is moved as a separate new field and
> renamed to 'metadata' to support both Rx and Tx metadata.
>
> For loopback/hairpin packet, metadata set on Rx/Tx may or may not be
> propagated to the other path depending on HW capability.
>
> Signed-off-by: Yongseok Koh <yskoh@mellanox.com>

There is a mark on Rx which is delivered to application in hash.fdir.hi.
Why do we need one more 32-bit value set by NIC and delivered to 
application?
What is the difference between MARK and META on Rx?
When application should use MARK and when META?
Is there cases when both could be necessary?

Moreover, the third patch adds 32-bit tags which are not delivered to
application. May be META/MARK should be simply a kind of TAG (e.g. with
index 0 or marked using additional attribute) which is delivered to 
application?

(It is either API breakage (if tx_metadata is removed) or ABI breakage
if metadata and tx_metadata will share new location after shinfo).

Andrew.


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet addresses as being 2-byte aligned
  2019-06-07 20:39  0%       ` Richardson, Bruce
@ 2019-06-08 12:15  4%         ` Ananyev, Konstantin
  0 siblings, 0 replies; 200+ results
From: Ananyev, Konstantin @ 2019-06-08 12:15 UTC (permalink / raw)
  To: Richardson, Bruce, Stephen Hemminger, dev; +Cc: Andrew Rybchenko


> > > -----Original Message-----
> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Stephen Hemminger
> > > Sent: Wednesday, June 5, 2019 7:10 PM
> > > To: dev@dpdk.org
> > > Cc: Richardson, Bruce <bruce.richardson@intel.com>; Stephen Hemminger
> > > <stephen@networkplumber.org>; Andrew Rybchenko
> > > <arybchenko@solarflare.com>
> > > Subject: [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet addresses
> > > as being 2-byte aligned
> > >
> > > From: Bruce Richardson <bruce.richardson@intel.com>
> > >
> > > When including the rte_ether.h header in applications with warnings
> > > enabled, a warning was given because of the assumption of 2-byte
> > > alignment of ethernet addresses when processing them.
> > >
> > > .../include/rte_ether.h:149:2: warning: converting a packed ‘const
> > >   struct ether_addr’ pointer (alignment 1) to a ‘unaligned_uint16_t’
> > >   {aka ‘const short unsigned int’} pointer (alignment 2) may result in
> > >   an unaligned pointer value [-Waddress-of-packed-member]
> > > 149 |  const unaligned_uint16_t *ea_words = (const unaligned_uint16_t
> > *)ea;
> > >     |  ^~~~~
> > >
> > > Since ethernet addresses should always be aligned on a two-byte
> > > boundary, we can just inform the compiler of this assumption to remove
> > > the warnings and allow us to always access the addresses using 16-bit
> > operations.
> > >
> > > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> > > Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
> > > ---
> > >  lib/librte_net/rte_ether.h | 11 ++++++-----
> > >  1 file changed, 6 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
> > > index feb35a33c94b..d7b76ddf63eb 100644
> > > --- a/lib/librte_net/rte_ether.h
> > > +++ b/lib/librte_net/rte_ether.h
> > > @@ -58,7 +58,8 @@ extern "C" {
> > >   * See http://standards.ieee.org/regauth/groupmac/tutorial.html
> > >   */
> > >  struct rte_ether_addr {
> > > -	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN]; /**< Addr bytes in tx order
> > */
> > > +	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN] __rte_aligned(2);
> > > +	/**< Addr bytes in tx order */
> > >  } __attribute__((__packed__));
> >
> > Hmm, that would change layout of any struct/union that has struct
> > rte_ether_addr inside.
> > So seems like implicit ABI breakage to me.
> > Konstantin
> >
> 
> I suppose it could, though only if you had the structure starting at an odd byte
> inside the larger structure.

Yes.

>  Personally, I'd think it should be ok in just about
> all cases, as I'd find it hard to imagine when you wouldn't have this, but
> technically I suppose it's a break.

I also don't expect it to be a common case, but it is not totally impossible.
So I still think it qualifies as ABI change and we need to follow our own ABI
breakage policy here. 

> For real packet heads the fields will always be
> two-byte aligned so there is no issue.
> 


^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet addresses as being 2-byte aligned
  2019-06-07 18:35  0%       ` Stephen Hemminger
  2019-06-07 20:40  0%         ` Richardson, Bruce
@ 2019-06-08 11:51  4%         ` Ananyev, Konstantin
  1 sibling, 0 replies; 200+ results
From: Ananyev, Konstantin @ 2019-06-08 11:51 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: dev, Richardson, Bruce, Andrew Rybchenko,
	Olivier Matz (olivier.matz@6wind.com)


> > >
> > > When including the rte_ether.h header in applications with warnings
> > > enabled, a warning was given because of the assumption of 2-byte alignment
> > > of ethernet addresses when processing them.
> > >
> > > .../include/rte_ether.h:149:2: warning: converting a packed ‘const
> > >   struct ether_addr’ pointer (alignment 1) to a ‘unaligned_uint16_t’
> > >   {aka ‘const short unsigned int’} pointer (alignment 2) may result in
> > >   an unaligned pointer value [-Waddress-of-packed-member]
> > > 149 |  const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea;
> > >     |  ^~~~~
> > >
> > > Since ethernet addresses should always be aligned on a two-byte boundary,
> > > we can just inform the compiler of this assumption to remove the warnings
> > > and allow us to always access the addresses using 16-bit operations.
> > >
> > > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> > > Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
> > > ---
> > >  lib/librte_net/rte_ether.h | 11 ++++++-----
> > >  1 file changed, 6 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
> > > index feb35a33c94b..d7b76ddf63eb 100644
> > > --- a/lib/librte_net/rte_ether.h
> > > +++ b/lib/librte_net/rte_ether.h
> > > @@ -58,7 +58,8 @@ extern "C" {
> > >   * See http://standards.ieee.org/regauth/groupmac/tutorial.html
> > >   */
> > >  struct rte_ether_addr {
> > > -	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN]; /**< Addr bytes in tx order */
> > > +	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN] __rte_aligned(2);
> > > +	/**< Addr bytes in tx order */
> > >  } __attribute__((__packed__));
> >
> > Hmm, that would change layout of any struct/union that has struct rte_ether_addr inside.
> > So seems like implicit ABI breakage to me.
> > Konstantin
> 
> There was no rte_ether_addr in previous releases.

I suppose you refer to the fact that struct ether_addr was renamed to rte_ether_addr by:
https://git.dpdk.org/dpdk/commit/?id=6d13ea8e8e49ab957deae2bba5ecf4a4bfe747d1 
As I understand, Olivier patches in that rework introduce API change only,  keeping ABI unchanged.
While your patch makes ABI breakage possible.
Konstantin 



^ permalink raw reply	[relevance 4%]

* [dpdk-dev] [PATCH 5/9] kni: drop unused group_id and device_id
    2019-06-08  0:19  3% ` [dpdk-dev] [PATCH 3/9] kni: drop unused field Stephen Hemminger
@ 2019-06-08  0:19  3% ` Stephen Hemminger
  1 sibling, 0 replies; 200+ results
From: Stephen Hemminger @ 2019-06-08  0:19 UTC (permalink / raw)
  To: ferruh.yigit; +Cc: dev, Stephen Hemminger

Kni devices no longer are restricted to PCI and device_id
in kni_dev is no longer used.

The group_id is set but never used.

The fields do need to stay in the ABI (dev_info) but
kernel can ignore them.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 kernel/linux/kni/kni_dev.h  | 4 ----
 kernel/linux/kni/kni_misc.c | 1 -
 2 files changed, 5 deletions(-)

diff --git a/kernel/linux/kni/kni_dev.h b/kernel/linux/kni/kni_dev.h
index ca3b07678b96..e39af97feaa7 100644
--- a/kernel/linux/kni/kni_dev.h
+++ b/kernel/linux/kni/kni_dev.h
@@ -40,7 +40,6 @@ struct kni_dev {
 	struct list_head list;
 
 	int status;
-	uint16_t group_id;           /* Group ID of a group of KNI devices */
 	uint32_t core_id;            /* Core ID to bind */
 	char name[RTE_KNI_NAMESIZE]; /* Network device name */
 	struct task_struct *pthread;
@@ -49,9 +48,6 @@ struct kni_dev {
 	wait_queue_head_t wq;
 	struct mutex sync_lock;
 
-	/* PCI device id */
-	uint16_t device_id;
-
 	/* kni device */
 	struct net_device *net_dev;
 
diff --git a/kernel/linux/kni/kni_misc.c b/kernel/linux/kni/kni_misc.c
index af18c67c422f..6a206d883c0d 100644
--- a/kernel/linux/kni/kni_misc.c
+++ b/kernel/linux/kni/kni_misc.c
@@ -346,7 +346,6 @@ kni_ioctl_create(struct net *net, uint32_t ioctl_num,
 	kni = netdev_priv(net_dev);
 
 	kni->net_dev = net_dev;
-	kni->group_id = dev_info.group_id;
 	kni->core_id = dev_info.core_id;
 	strncpy(kni->name, dev_info.name, RTE_KNI_NAMESIZE);
 
-- 
2.20.1


^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH 3/9] kni: drop unused field
  @ 2019-06-08  0:19  3% ` Stephen Hemminger
  2019-06-08  0:19  3% ` [dpdk-dev] [PATCH 5/9] kni: drop unused group_id and device_id Stephen Hemminger
  1 sibling, 0 replies; 200+ results
From: Stephen Hemminger @ 2019-06-08  0:19 UTC (permalink / raw)
  To: ferruh.yigit; +Cc: dev, Stephen Hemminger

The kni net structure only exists in driver no API/ABI.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 kernel/linux/kni/kni_dev.h | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/kernel/linux/kni/kni_dev.h b/kernel/linux/kni/kni_dev.h
index 44a5a61f7279..0117941e5a6c 100644
--- a/kernel/linux/kni/kni_dev.h
+++ b/kernel/linux/kni/kni_dev.h
@@ -83,9 +83,6 @@ struct kni_dev {
 	/* mbuf size */
 	uint32_t mbuf_size;
 
-	/* synchro for request processing */
-	unsigned long synchro;
-
 	/* buffers */
 	void *pa[MBUF_BURST_SZ];
 	void *va[MBUF_BURST_SZ];
-- 
2.20.1


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet addresses as being 2-byte aligned
  2019-06-07 18:35  0%       ` Stephen Hemminger
@ 2019-06-07 20:40  0%         ` Richardson, Bruce
  2019-06-08 11:51  4%         ` Ananyev, Konstantin
  1 sibling, 0 replies; 200+ results
From: Richardson, Bruce @ 2019-06-07 20:40 UTC (permalink / raw)
  To: Stephen Hemminger, Ananyev, Konstantin; +Cc: dev, Andrew Rybchenko



> -----Original Message-----
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Friday, June 7, 2019 7:35 PM
> To: Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Cc: dev@dpdk.org; Richardson, Bruce <bruce.richardson@intel.com>; Andrew
> Rybchenko <arybchenko@solarflare.com>
> Subject: Re: [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet addresses
> as being 2-byte aligned
> 
> On Fri, 7 Jun 2019 16:59:32 +0000
> "Ananyev, Konstantin" <konstantin.ananyev@intel.com> wrote:
> 
> > > -----Original Message-----
> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Stephen
> > > Hemminger
> > > Sent: Wednesday, June 5, 2019 7:10 PM
> > > To: dev@dpdk.org
> > > Cc: Richardson, Bruce <bruce.richardson@intel.com>; Stephen
> > > Hemminger <stephen@networkplumber.org>; Andrew Rybchenko
> > > <arybchenko@solarflare.com>
> > > Subject: [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet
> > > addresses as being 2-byte aligned
> > >
> > > From: Bruce Richardson <bruce.richardson@intel.com>
> > >
> > > When including the rte_ether.h header in applications with warnings
> > > enabled, a warning was given because of the assumption of 2-byte
> > > alignment of ethernet addresses when processing them.
> > >
> > > .../include/rte_ether.h:149:2: warning: converting a packed ‘const
> > >   struct ether_addr’ pointer (alignment 1) to a ‘unaligned_uint16_t’
> > >   {aka ‘const short unsigned int’} pointer (alignment 2) may result in
> > >   an unaligned pointer value [-Waddress-of-packed-member]
> > > 149 |  const unaligned_uint16_t *ea_words = (const unaligned_uint16_t
> *)ea;
> > >     |  ^~~~~
> > >
> > > Since ethernet addresses should always be aligned on a two-byte
> > > boundary, we can just inform the compiler of this assumption to
> > > remove the warnings and allow us to always access the addresses using
> 16-bit operations.
> > >
> > > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> > > Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
> > > ---
> > >  lib/librte_net/rte_ether.h | 11 ++++++-----
> > >  1 file changed, 6 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
> > > index feb35a33c94b..d7b76ddf63eb 100644
> > > --- a/lib/librte_net/rte_ether.h
> > > +++ b/lib/librte_net/rte_ether.h
> > > @@ -58,7 +58,8 @@ extern "C" {
> > >   * See http://standards.ieee.org/regauth/groupmac/tutorial.html
> > >   */
> > >  struct rte_ether_addr {
> > > -	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN]; /**< Addr bytes in tx order
> */
> > > +	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN] __rte_aligned(2);
> > > +	/**< Addr bytes in tx order */
> > >  } __attribute__((__packed__));
> >
> > Hmm, that would change layout of any struct/union that has struct
> rte_ether_addr inside.
> > So seems like implicit ABI breakage to me.
> > Konstantin
> 
> There was no rte_ether_addr in previous releases.

Good point. Thanks for remembering...

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet addresses as being 2-byte aligned
  2019-06-07 16:59  3%     ` Ananyev, Konstantin
  2019-06-07 18:35  0%       ` Stephen Hemminger
@ 2019-06-07 20:39  0%       ` Richardson, Bruce
  2019-06-08 12:15  4%         ` Ananyev, Konstantin
  1 sibling, 1 reply; 200+ results
From: Richardson, Bruce @ 2019-06-07 20:39 UTC (permalink / raw)
  To: Ananyev, Konstantin, Stephen Hemminger, dev; +Cc: Andrew Rybchenko



> -----Original Message-----
> From: Ananyev, Konstantin
> Sent: Friday, June 7, 2019 6:00 PM
> To: Stephen Hemminger <stephen@networkplumber.org>; dev@dpdk.org
> Cc: Richardson, Bruce <bruce.richardson@intel.com>; Andrew Rybchenko
> <arybchenko@solarflare.com>
> Subject: RE: [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet addresses
> as being 2-byte aligned
> 
> 
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Stephen Hemminger
> > Sent: Wednesday, June 5, 2019 7:10 PM
> > To: dev@dpdk.org
> > Cc: Richardson, Bruce <bruce.richardson@intel.com>; Stephen Hemminger
> > <stephen@networkplumber.org>; Andrew Rybchenko
> > <arybchenko@solarflare.com>
> > Subject: [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet addresses
> > as being 2-byte aligned
> >
> > From: Bruce Richardson <bruce.richardson@intel.com>
> >
> > When including the rte_ether.h header in applications with warnings
> > enabled, a warning was given because of the assumption of 2-byte
> > alignment of ethernet addresses when processing them.
> >
> > .../include/rte_ether.h:149:2: warning: converting a packed ‘const
> >   struct ether_addr’ pointer (alignment 1) to a ‘unaligned_uint16_t’
> >   {aka ‘const short unsigned int’} pointer (alignment 2) may result in
> >   an unaligned pointer value [-Waddress-of-packed-member]
> > 149 |  const unaligned_uint16_t *ea_words = (const unaligned_uint16_t
> *)ea;
> >     |  ^~~~~
> >
> > Since ethernet addresses should always be aligned on a two-byte
> > boundary, we can just inform the compiler of this assumption to remove
> > the warnings and allow us to always access the addresses using 16-bit
> operations.
> >
> > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> > Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
> > ---
> >  lib/librte_net/rte_ether.h | 11 ++++++-----
> >  1 file changed, 6 insertions(+), 5 deletions(-)
> >
> > diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
> > index feb35a33c94b..d7b76ddf63eb 100644
> > --- a/lib/librte_net/rte_ether.h
> > +++ b/lib/librte_net/rte_ether.h
> > @@ -58,7 +58,8 @@ extern "C" {
> >   * See http://standards.ieee.org/regauth/groupmac/tutorial.html
> >   */
> >  struct rte_ether_addr {
> > -	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN]; /**< Addr bytes in tx order
> */
> > +	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN] __rte_aligned(2);
> > +	/**< Addr bytes in tx order */
> >  } __attribute__((__packed__));
> 
> Hmm, that would change layout of any struct/union that has struct
> rte_ether_addr inside.
> So seems like implicit ABI breakage to me.
> Konstantin
> 

I suppose it could, though only if you had the structure starting at an odd byte
inside the larger structure. Personally, I'd think it should be ok in just about
all cases, as I'd find it hard to imagine when you wouldn't have this, but 
technically I suppose it's a break. For real packet heads the fields will always be
two-byte aligned so there is no issue.

/Bruce

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet addresses as being 2-byte aligned
  2019-06-07 16:59  3%     ` Ananyev, Konstantin
@ 2019-06-07 18:35  0%       ` Stephen Hemminger
  2019-06-07 20:40  0%         ` Richardson, Bruce
  2019-06-08 11:51  4%         ` Ananyev, Konstantin
  2019-06-07 20:39  0%       ` Richardson, Bruce
  1 sibling, 2 replies; 200+ results
From: Stephen Hemminger @ 2019-06-07 18:35 UTC (permalink / raw)
  To: Ananyev, Konstantin; +Cc: dev, Richardson, Bruce, Andrew Rybchenko

On Fri, 7 Jun 2019 16:59:32 +0000
"Ananyev, Konstantin" <konstantin.ananyev@intel.com> wrote:

> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Stephen Hemminger
> > Sent: Wednesday, June 5, 2019 7:10 PM
> > To: dev@dpdk.org
> > Cc: Richardson, Bruce <bruce.richardson@intel.com>; Stephen Hemminger <stephen@networkplumber.org>; Andrew Rybchenko
> > <arybchenko@solarflare.com>
> > Subject: [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet addresses as being 2-byte aligned
> > 
> > From: Bruce Richardson <bruce.richardson@intel.com>
> > 
> > When including the rte_ether.h header in applications with warnings
> > enabled, a warning was given because of the assumption of 2-byte alignment
> > of ethernet addresses when processing them.
> > 
> > .../include/rte_ether.h:149:2: warning: converting a packed ‘const
> >   struct ether_addr’ pointer (alignment 1) to a ‘unaligned_uint16_t’
> >   {aka ‘const short unsigned int’} pointer (alignment 2) may result in
> >   an unaligned pointer value [-Waddress-of-packed-member]
> > 149 |  const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea;
> >     |  ^~~~~
> > 
> > Since ethernet addresses should always be aligned on a two-byte boundary,
> > we can just inform the compiler of this assumption to remove the warnings
> > and allow us to always access the addresses using 16-bit operations.
> > 
> > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> > Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
> > ---
> >  lib/librte_net/rte_ether.h | 11 ++++++-----
> >  1 file changed, 6 insertions(+), 5 deletions(-)
> > 
> > diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
> > index feb35a33c94b..d7b76ddf63eb 100644
> > --- a/lib/librte_net/rte_ether.h
> > +++ b/lib/librte_net/rte_ether.h
> > @@ -58,7 +58,8 @@ extern "C" {
> >   * See http://standards.ieee.org/regauth/groupmac/tutorial.html
> >   */
> >  struct rte_ether_addr {
> > -	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN]; /**< Addr bytes in tx order */
> > +	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN] __rte_aligned(2);
> > +	/**< Addr bytes in tx order */
> >  } __attribute__((__packed__));  
> 
> Hmm, that would change layout of any struct/union that has struct rte_ether_addr inside.
> So seems like implicit ABI breakage to me.
> Konstantin

There was no rte_ether_addr in previous releases.


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-07 15:42  3%                   ` Ray Kinsella
@ 2019-06-07 18:21  0%                     ` Wiles, Keith
  0 siblings, 0 replies; 200+ results
From: Wiles, Keith @ 2019-06-07 18:21 UTC (permalink / raw)
  To: Ray Kinsella
  Cc: dpdk-dev, Neil Horman, Jerin Jacob Kollanukkaran, Richardson,
	Bruce, Thomas Monjalon



> On Jun 7, 2019, at 10:42 AM, Ray Kinsella <mdr@ashroe.eu> wrote:
> 
> 
> 
> On 06/06/2019 16:03, Neil Horman wrote:
>> On Thu, Jun 06, 2019 at 02:02:03PM +0000, Jerin Jacob Kollanukkaran wrote:
>>>> -----Original Message-----
>>>> From: Neil Horman <nhorman@tuxdriver.com>
>>>> Sent: Thursday, June 6, 2019 7:05 PM
>>>> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
>>>> Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
>>>> Thomas Monjalon <thomas@monjalon.net>
>>>> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
>>>> 
>>>> On Thu, Jun 06, 2019 at 12:04:57PM +0000, Jerin Jacob Kollanukkaran wrote:
>>>>>> -----Original Message-----
>>>>>> From: Neil Horman <nhorman@tuxdriver.com>
>>>>>> Sent: Thursday, June 6, 2019 5:04 PM
>>>>>> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
>>>>>> Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
>>>>>> Thomas Monjalon <thomas@monjalon.net>
>>>>>> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
>>>>>> 
>>>>>> On Thu, Jun 06, 2019 at 09:44:52AM +0000, Jerin Jacob Kollanukkaran
>>>> wrote:
>>>>>>>> -----Original Message-----
>>>>>>>> From: Neil Horman <nhorman@tuxdriver.com>
>>>>>>>> Sent: Wednesday, June 5, 2019 11:41 PM
>>>>>>>> To: Bruce Richardson <bruce.richardson@intel.com>
>>>>>>>> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
>>>>>>>> dev@dpdk.org; Thomas Monjalon <thomas@monjalon.net>
>>>>>>>> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
>>>>>>>> 
>>>>>>>> On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson wrote:
>>>>>>>>> On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob
>>>>>>>>> Kollanukkaran
>>>>>>>> wrote:
>>>>>>>>>>> -----Original Message-----
>>>>>>>>>>> From: Neil Horman <nhorman@tuxdriver.com>
>>>>>>>>>>> Sent: Sunday, May 26, 2019 12:14 AM
>>>>>>>>>>> To: dev@dpdk.org
>>>>>>>>>>> Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob
>>>>>>>>>>> Kollanukkaran <jerinj@marvell.com>; Bruce Richardson
>>>>>>>>>>> <bruce.richardson@intel.com>; Thomas Monjalon
>>>>>>>>>>> <thomas@monjalon.net>
>>>>>>>>>>> Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal
>>>>>>>>>>> tag
>>>>>>>>>>> 
>>>>>>>>>>> Hey-
>>>>>>>>>>> 	Based on our recent conversations regarding the use of
>>>>>>>>>>> symbols only meant for internal dpdk consumption (between
>>>>>>>>>>> dpdk libraries), this is an idea that I've come up with
>>>>>>>>>>> that I'd like to get some feedback on
>>>>>>>>>>> 
>>>>>>>>>>> Summary:
>>>>>>>>>>> 1) We have symbols in the DPDK that are meant to be used
>>>>>>>>>>> between DPDK libraries, but not by applications linking to
>>>>>>>>>>> them
>>>>>>>>>>> 2) We would like to document those symbols in the code, so
>>>>>>>>>>> as to note them clearly as for being meant for internal
>>>>>>>>>>> use only
>>>>>>>>>>> 3) Linker symbol visibility is a very coarse grained tool,
>>>>>>>>>>> and so there is no good way in a single library to mark
>>>>>>>>>>> items as being meant for use only by other DPDK libraries,
>>>>>>>>>>> at least not without some extensive runtime checking
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> Proposal:
>>>>>>>>>>> I'm proposing that we introduce the __rte_internal tag.
>>>>>>>>>>> From a coding standpoint it works a great deal like the
>>>>>>>>>>> __rte_experimental tag in that it expempts the tagged
>>>>>>>>>>> symbol from ABI constraints (as the only users should be
>>>>>>>>>>> represented in the DPDK build environment).  Additionally,
>>>>>>>>>>> the __rte_internal macro resolves differently based on the
>>>>>>>>>>> definition of the BUILDING_RTE_SDK flag (working under the
>>>>>>>>>>> assumption that said flag should only ever be set if we
>>>>>>>>>>> are actually building DPDK libraries which will make use
>>>>>>>>>>> of internal calls).  If the BUILDING_RTE_SDK flag is set
>>>>>>>>>>> __rte_internal resolves to __attribute__((section
>>>>>>>>>>> "text.internal)), placing it in a special text section
>>>>>>>>>>> which is then used to validate that the the symbol appears
>>>>>>>>>>> in the INTERNAL section of the corresponding library version
>>>> map).
>>>>>>>>>>> If BUILDING_RTE_SDK is not set, then __rte_internal
>>>>>>>>>>> resolves to
>>>>>>>> __attribute__((error("..."))), which causes any caller of the
>>>>>>>> tagged function to throw an error at compile time, indicating
>>>>>>>> that the symbol is not available for external use.
>>>>>>>>>>> 
>>>>>>>>>>> This isn't a perfect solution, as applications can still
>>>>>>>>>>> hack around it of course,
>>>>>>>>>> 
>>>>>>>>>> I think, one way to, avoid, hack around could be to,
>>>>>>>>>> 
>>>>>>>>>> 1) at config stage, create  a random number for the build
>>>>>>>>>> 2) introduce RTE_CALL_INTERNAL macro for calling internal
>>>>>>>>>> function, compare the generated random number for allowing
>>>>>>>>>> the calls to make within the library. i.e leverage the fact
>>>>>>>>>> that external library would never know the random number
>>>>>>>>>> generated for the DPDK build
>>>>>>>> and internal driver code does.
>>>>>>>>>> 
>>>>>>>>> Do we really need to care about this. If have some determined
>>>>>>>>> enough to hack around our limitations, then they surely know
>>>>>>>>> that they have an unsupported configuration. We just need to
>>>>>>>>> protect against inadvertent use of internals, IMHO.
>>>>>>>>> 
>>>>>>>> I agree, I too had thought about doing some sort of internal
>>>>>>>> runtime checking to match internal only symbols, such that they
>>>>>>>> were only accessable by internally approved users, but it
>>>>>>>> started to feel like a great
>>>>>> deal of overhead.
>>>>>>>> Its a good idea for a general mechanism I think, but I believe
>>>>>>>> the value here is more to internally document which apis we want
>>>>>>>> to mark as being for internal use only, and create a lightweight
>>>>>>>> roadblock at build time to catch users inadvertently using them.
>>>>>>>> Determined users will get around anything, and theres not much
>>>>>>>> we can do to stop
>>>>>> them.
>>>>>>> 
>>>>>>> I agree too. IMHO, Simply having following items would be enough
>>>>>>> 
>>>>>>> 1) Avoid exposing the internal function prototype through public
>>>>>>> header files
>>>>>>> 2) Add @internal to API documentation
>>>>>>> 3) Just decide the name space for internal API for tooling(i.e not
>>>>>>> start with rte_ or so) Using objdump scheme to detect internal
>>>>>>> functions
>>>>>> requires the the library to build prior to run the checkpatch.
>>>>>>> 
>>>>>> 
>>>>>> No, I'm not comfortable with that approach, and I've stated why:
>>>>>> 1) Not exposing the functions via header files is a fine start
>>>>>> 
>>>>>> 2) Adding internal documentation is also fine, but does nothing to
>>>>>> correlate the code implementing those functions to the
>>>>>> documentation.  Its valuable to have a tag on a function identifying it as
>>>> internal only.
>>>>>> 
>>>>>> 3) Using naming conventions to separate internal only from
>>>>>> non-internal functions is a vague approach, requiring future
>>>>>> developers to be cogniscent of the convention and make the
>>>>>> appropriate naming choices.  It also implicitly restricts the
>>>>>> abliity for future developers to make naming changes in conflict
>>>>>> with that convention
>>>>> 
>>>>> Enforcing the naming convention can be achieved through tooling as well.
>>>>> 
>>>> Sure, but why enforce any function naming at all, when you don't have to.
>>> 
>>> May I ask,  why to  enforce __rte_internal, when you don't have to
>>> 
>> 
>> Because its more clear.  Implicitly deciding that any function not prefixed with
>> rte_ is internal only does nothing to prevent a developer from accidentally
>> naming a function incorrectly, exporting it, and allowing a user to call it. We
>> can move headers all you want, but we provide an ABI guarantee to end users, and
>> developers should have a way to clearly record that without having to check the
>> documentation for each function that an application developer wants to use.
>> 
>> The long and the short of it for me is that I want a way for developers to opt
>> their code into an internal only condition, not to just document it as such
>> and hope its up to date.  If they tag a function as __rte_internal then its
>> clearly marked as internal only, they have checks to ensure that its in the
>> INTERNAL section of the version map, and should that header somehow get
>> externally exported (see rte_mempool_check_cookies for an example of how thats
>> happened), users are prevented from using them at build time, rather than having
>> to ask questions on the list, or read documentation after an error to find out
>> "oops, shouldn't have done that".
>> 
>> I think you'll find that going through all the header files, and bifurcating
>> them to public and private headers is a much larger undertaking than just
>> tagging those functions accordingly.  a quick scan of all our header file for
>> the @internal tag shows about 260 instances of such functions, almost all of
>> which are published to applications.  All of those functions would have to be
>> moved to private headers, and their requisite C files would need to be updated
>> to include the new header.  with the use of __rte_internal, we just have tag the
>> functions as such, which can be handled with a cocinelle or awk script.
>> 
>> Neil
> 
> This is good, I like alot about this, especially the build system
> complaining loudly when the developer does something they shouldn't - I
> think anything that we can add that promotes good behaviors is to be
> 100% welcomed.
> 
> I also agree with the points made elsewhere that this is essentially
> trying to solve a header problem, the mixing of public and private
> symbols in what are public headers, with __rte_internal. Adding
> __rte_internal would essentially ratify that behavior, whereas I would
> argue that something inherently private, should never see the light of
> day in a public header.
> 
> I completely get that it may be more work, however for me it is better
> way to fix this problem. It would also add completely clarity, all the
> extra hassle around does it have the rte_ prefix goes away - if it is in
> a "public header" it is part of the ABI/API, end of discussion.
> 
> Finally, not opposed to also asking folks putting symbols in the private
> header to mark those symbols with __rte_internal.

+1 I think we need to do both split headers and __rte_internal for extra measure. I am still concerned we are adding more work for the developer, if not then at least we split the headers.
> 
>> 
>> 
>>>> 
>>>>>> 
>>>>>> 4) Adding a tag like __rte_internal creates an interlock whereby,
>>>>>> not only are internal functions excused from ABI constraints, but
>>>>>> forces developers to intentionally mark their internal functions as
>>>>>> being internal in the code, which is beneficial to clarlity of understanding
>>>> during the development process.
>>>>> 
>>>>> No issues in adding __rte_internal. But, I am against current
>>>>> implementaion, Ie. adding objdump dependency
>>>> That dependency already exists for the __rte_external flag
>>> 
>>> Sorry, I could not see the dependency.
>>> 
>>> [master][dpdk.org] $ grep -ri "objdump" devtools/
>>> [master][dpdk.org] $ grep -ri "objdump" usertools/
>>> [master][dpdk.org] $ grep -ri "__rte_external" *
>>> 
>>>> 
>>>>> to checkpatch i.e developer has to build the library first so  that
>>>>> checkpatch can can know, Is it belongs to internal section or not?
>>>>> 
>>>> What developer is running checkpatch/posting patches without first building
>>>> their changes?
>>> 
>>> # it is not developer, The CI/CD tools can quicky check the sanity of patches
>>> before the build itself. Why to add unnecessary dependency?
>>> # If some PMD is not building if the requirements are not meet(say AES NI PMD for crypto)
>>> then how do take care of the dependency.
>>> 
>>> 
>>>> 
>>>> 
>>>>>> 
>>>>>> 5) Adding a tag like __rte_internal is explicit, and allows
>>>>>> developers to use a single header file instead of multiple header
>>>>>> files if they so choose
>>>>>> 
>>>>>> We went through this with experimental symbols as well[1], and it
>>>>>> just makes more sense to me to clearly document in the code what
>>>>>> constitutes an internal symbol rather than relying on naming
>>>>>> conventions and hoping that developers read the documentation before
>>>>>> exporting a symbol publically.
>>>>>> 
>>>>>> 
>>>>>> [1] https://mails.dpdk.org/archives/dev/2017-December/083828.html
>>>>>>>> 
>>>>>>>> If we really wanted to go down that road, we could use a
>>>>>>>> mechainsm simmilar to the EXPORT_SYMBOL / EXPORT_SYMBOL_GPL
>>>>>>>> infrastructure that the kernel uses, but that would required
>>>>>>>> building our own custom linker script, which seems like overkill here.
>>>>>>>> 
>>>>>>>> Best
>>>>>>>> Neil
>>>>>>>> 
>>>>>>>>> /Bruce

Regards,
Keith


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet addresses as being 2-byte aligned
  @ 2019-06-07 16:59  3%     ` Ananyev, Konstantin
  2019-06-07 18:35  0%       ` Stephen Hemminger
  2019-06-07 20:39  0%       ` Richardson, Bruce
  0 siblings, 2 replies; 200+ results
From: Ananyev, Konstantin @ 2019-06-07 16:59 UTC (permalink / raw)
  To: Stephen Hemminger, dev; +Cc: Richardson, Bruce, Andrew Rybchenko



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Stephen Hemminger
> Sent: Wednesday, June 5, 2019 7:10 PM
> To: dev@dpdk.org
> Cc: Richardson, Bruce <bruce.richardson@intel.com>; Stephen Hemminger <stephen@networkplumber.org>; Andrew Rybchenko
> <arybchenko@solarflare.com>
> Subject: [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet addresses as being 2-byte aligned
> 
> From: Bruce Richardson <bruce.richardson@intel.com>
> 
> When including the rte_ether.h header in applications with warnings
> enabled, a warning was given because of the assumption of 2-byte alignment
> of ethernet addresses when processing them.
> 
> .../include/rte_ether.h:149:2: warning: converting a packed ‘const
>   struct ether_addr’ pointer (alignment 1) to a ‘unaligned_uint16_t’
>   {aka ‘const short unsigned int’} pointer (alignment 2) may result in
>   an unaligned pointer value [-Waddress-of-packed-member]
> 149 |  const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea;
>     |  ^~~~~
> 
> Since ethernet addresses should always be aligned on a two-byte boundary,
> we can just inform the compiler of this assumption to remove the warnings
> and allow us to always access the addresses using 16-bit operations.
> 
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
> ---
>  lib/librte_net/rte_ether.h | 11 ++++++-----
>  1 file changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
> index feb35a33c94b..d7b76ddf63eb 100644
> --- a/lib/librte_net/rte_ether.h
> +++ b/lib/librte_net/rte_ether.h
> @@ -58,7 +58,8 @@ extern "C" {
>   * See http://standards.ieee.org/regauth/groupmac/tutorial.html
>   */
>  struct rte_ether_addr {
> -	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN]; /**< Addr bytes in tx order */
> +	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN] __rte_aligned(2);
> +	/**< Addr bytes in tx order */
>  } __attribute__((__packed__));

Hmm, that would change layout of any struct/union that has struct rte_ether_addr inside.
So seems like implicit ABI breakage to me.
Konstantin


> 
>  #define RTE_ETHER_LOCAL_ADMIN_ADDR 0x02 /**< Locally assigned Eth. address. */
> @@ -81,8 +82,8 @@ struct rte_ether_addr {
>  static inline int rte_is_same_ether_addr(const struct rte_ether_addr *ea1,
>  				     const struct rte_ether_addr *ea2)
>  {
> -	const unaligned_uint16_t *w1 = (const uint16_t *)ea1;
> -	const unaligned_uint16_t *w2 = (const uint16_t *)ea2;
> +	const uint16_t *w1 = (const uint16_t *)ea1;
> +	const uint16_t *w2 = (const uint16_t *)ea2;
> 
>  	return ((w1[0] ^ w2[0]) | (w1[1] ^ w2[1]) | (w1[2] ^ w2[2])) == 0;
>  }
> @@ -99,7 +100,7 @@ static inline int rte_is_same_ether_addr(const struct rte_ether_addr *ea1,
>   */
>  static inline int rte_is_zero_ether_addr(const struct rte_ether_addr *ea)
>  {
> -	const unaligned_uint16_t *w = (const uint16_t *)ea;
> +	const uint16_t *w = (const uint16_t *)ea;
> 
>  	return (w[0] | w[1] | w[2]) == 0;
>  }
> @@ -146,7 +147,7 @@ static inline int rte_is_multicast_ether_addr(const struct rte_ether_addr *ea)
>   */
>  static inline int rte_is_broadcast_ether_addr(const struct rte_ether_addr *ea)
>  {
> -	const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea;
> +	const uint16_t *ea_words = (const uint16_t *)ea;
> 
>  	return (ea_words[0] == 0xFFFF && ea_words[1] == 0xFFFF &&
>  		ea_words[2] == 0xFFFF);
> --
> 2.20.1


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-06 15:03  3%                 ` Neil Horman
  2019-06-06 15:14  0%                   ` Jerin Jacob Kollanukkaran
@ 2019-06-07 15:42  3%                   ` Ray Kinsella
  2019-06-07 18:21  0%                     ` Wiles, Keith
  1 sibling, 1 reply; 200+ results
From: Ray Kinsella @ 2019-06-07 15:42 UTC (permalink / raw)
  To: dev, Neil Horman, Jerin Jacob Kollanukkaran, bruce.richardson,
	Thomas Monjalon, Keith



On 06/06/2019 16:03, Neil Horman wrote:
> On Thu, Jun 06, 2019 at 02:02:03PM +0000, Jerin Jacob Kollanukkaran wrote:
>>> -----Original Message-----
>>> From: Neil Horman <nhorman@tuxdriver.com>
>>> Sent: Thursday, June 6, 2019 7:05 PM
>>> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
>>> Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
>>> Thomas Monjalon <thomas@monjalon.net>
>>> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
>>>
>>> On Thu, Jun 06, 2019 at 12:04:57PM +0000, Jerin Jacob Kollanukkaran wrote:
>>>>> -----Original Message-----
>>>>> From: Neil Horman <nhorman@tuxdriver.com>
>>>>> Sent: Thursday, June 6, 2019 5:04 PM
>>>>> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
>>>>> Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
>>>>> Thomas Monjalon <thomas@monjalon.net>
>>>>> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
>>>>>
>>>>> On Thu, Jun 06, 2019 at 09:44:52AM +0000, Jerin Jacob Kollanukkaran
>>> wrote:
>>>>>>> -----Original Message-----
>>>>>>> From: Neil Horman <nhorman@tuxdriver.com>
>>>>>>> Sent: Wednesday, June 5, 2019 11:41 PM
>>>>>>> To: Bruce Richardson <bruce.richardson@intel.com>
>>>>>>> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
>>>>>>> dev@dpdk.org; Thomas Monjalon <thomas@monjalon.net>
>>>>>>> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
>>>>>>>
>>>>>>> On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson wrote:
>>>>>>>> On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob
>>>>>>>> Kollanukkaran
>>>>>>> wrote:
>>>>>>>>>> -----Original Message-----
>>>>>>>>>> From: Neil Horman <nhorman@tuxdriver.com>
>>>>>>>>>> Sent: Sunday, May 26, 2019 12:14 AM
>>>>>>>>>> To: dev@dpdk.org
>>>>>>>>>> Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob
>>>>>>>>>> Kollanukkaran <jerinj@marvell.com>; Bruce Richardson
>>>>>>>>>> <bruce.richardson@intel.com>; Thomas Monjalon
>>>>>>>>>> <thomas@monjalon.net>
>>>>>>>>>> Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal
>>>>>>>>>> tag
>>>>>>>>>>
>>>>>>>>>> Hey-
>>>>>>>>>> 	Based on our recent conversations regarding the use of
>>>>>>>>>> symbols only meant for internal dpdk consumption (between
>>>>>>>>>> dpdk libraries), this is an idea that I've come up with
>>>>>>>>>> that I'd like to get some feedback on
>>>>>>>>>>
>>>>>>>>>> Summary:
>>>>>>>>>> 1) We have symbols in the DPDK that are meant to be used
>>>>>>>>>> between DPDK libraries, but not by applications linking to
>>>>>>>>>> them
>>>>>>>>>> 2) We would like to document those symbols in the code, so
>>>>>>>>>> as to note them clearly as for being meant for internal
>>>>>>>>>> use only
>>>>>>>>>> 3) Linker symbol visibility is a very coarse grained tool,
>>>>>>>>>> and so there is no good way in a single library to mark
>>>>>>>>>> items as being meant for use only by other DPDK libraries,
>>>>>>>>>> at least not without some extensive runtime checking
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Proposal:
>>>>>>>>>> I'm proposing that we introduce the __rte_internal tag.
>>>>>>>>>> From a coding standpoint it works a great deal like the
>>>>>>>>>> __rte_experimental tag in that it expempts the tagged
>>>>>>>>>> symbol from ABI constraints (as the only users should be
>>>>>>>>>> represented in the DPDK build environment).  Additionally,
>>>>>>>>>> the __rte_internal macro resolves differently based on the
>>>>>>>>>> definition of the BUILDING_RTE_SDK flag (working under the
>>>>>>>>>> assumption that said flag should only ever be set if we
>>>>>>>>>> are actually building DPDK libraries which will make use
>>>>>>>>>> of internal calls).  If the BUILDING_RTE_SDK flag is set
>>>>>>>>>> __rte_internal resolves to __attribute__((section
>>>>>>>>>> "text.internal)), placing it in a special text section
>>>>>>>>>> which is then used to validate that the the symbol appears
>>>>>>>>>> in the INTERNAL section of the corresponding library version
>>> map).
>>>>>>>>>> If BUILDING_RTE_SDK is not set, then __rte_internal
>>>>>>>>>> resolves to
>>>>>>> __attribute__((error("..."))), which causes any caller of the
>>>>>>> tagged function to throw an error at compile time, indicating
>>>>>>> that the symbol is not available for external use.
>>>>>>>>>>
>>>>>>>>>> This isn't a perfect solution, as applications can still
>>>>>>>>>> hack around it of course,
>>>>>>>>>
>>>>>>>>> I think, one way to, avoid, hack around could be to,
>>>>>>>>>
>>>>>>>>> 1) at config stage, create  a random number for the build
>>>>>>>>> 2) introduce RTE_CALL_INTERNAL macro for calling internal
>>>>>>>>> function, compare the generated random number for allowing
>>>>>>>>> the calls to make within the library. i.e leverage the fact
>>>>>>>>> that external library would never know the random number
>>>>>>>>> generated for the DPDK build
>>>>>>> and internal driver code does.
>>>>>>>>>
>>>>>>>> Do we really need to care about this. If have some determined
>>>>>>>> enough to hack around our limitations, then they surely know
>>>>>>>> that they have an unsupported configuration. We just need to
>>>>>>>> protect against inadvertent use of internals, IMHO.
>>>>>>>>
>>>>>>> I agree, I too had thought about doing some sort of internal
>>>>>>> runtime checking to match internal only symbols, such that they
>>>>>>> were only accessable by internally approved users, but it
>>>>>>> started to feel like a great
>>>>> deal of overhead.
>>>>>>> Its a good idea for a general mechanism I think, but I believe
>>>>>>> the value here is more to internally document which apis we want
>>>>>>> to mark as being for internal use only, and create a lightweight
>>>>>>> roadblock at build time to catch users inadvertently using them.
>>>>>>> Determined users will get around anything, and theres not much
>>>>>>> we can do to stop
>>>>> them.
>>>>>>
>>>>>> I agree too. IMHO, Simply having following items would be enough
>>>>>>
>>>>>> 1) Avoid exposing the internal function prototype through public
>>>>>> header files
>>>>>> 2) Add @internal to API documentation
>>>>>> 3) Just decide the name space for internal API for tooling(i.e not
>>>>>> start with rte_ or so) Using objdump scheme to detect internal
>>>>>> functions
>>>>> requires the the library to build prior to run the checkpatch.
>>>>>>
>>>>>
>>>>> No, I'm not comfortable with that approach, and I've stated why:
>>>>> 1) Not exposing the functions via header files is a fine start
>>>>>
>>>>> 2) Adding internal documentation is also fine, but does nothing to
>>>>> correlate the code implementing those functions to the
>>>>> documentation.  Its valuable to have a tag on a function identifying it as
>>> internal only.
>>>>>
>>>>> 3) Using naming conventions to separate internal only from
>>>>> non-internal functions is a vague approach, requiring future
>>>>> developers to be cogniscent of the convention and make the
>>>>> appropriate naming choices.  It also implicitly restricts the
>>>>> abliity for future developers to make naming changes in conflict
>>>>> with that convention
>>>>
>>>> Enforcing the naming convention can be achieved through tooling as well.
>>>>
>>> Sure, but why enforce any function naming at all, when you don't have to.
>>
>> May I ask,  why to  enforce __rte_internal, when you don't have to
>>
> 
> Because its more clear.  Implicitly deciding that any function not prefixed with
> rte_ is internal only does nothing to prevent a developer from accidentally
> naming a function incorrectly, exporting it, and allowing a user to call it. We
> can move headers all you want, but we provide an ABI guarantee to end users, and
> developers should have a way to clearly record that without having to check the
> documentation for each function that an application developer wants to use.
> 
> The long and the short of it for me is that I want a way for developers to opt
> their code into an internal only condition, not to just document it as such
> and hope its up to date.  If they tag a function as __rte_internal then its
> clearly marked as internal only, they have checks to ensure that its in the
> INTERNAL section of the version map, and should that header somehow get
> externally exported (see rte_mempool_check_cookies for an example of how thats
> happened), users are prevented from using them at build time, rather than having
> to ask questions on the list, or read documentation after an error to find out
> "oops, shouldn't have done that".
> 
> I think you'll find that going through all the header files, and bifurcating
> them to public and private headers is a much larger undertaking than just
> tagging those functions accordingly.  a quick scan of all our header file for
> the @internal tag shows about 260 instances of such functions, almost all of
> which are published to applications.  All of those functions would have to be
> moved to private headers, and their requisite C files would need to be updated
> to include the new header.  with the use of __rte_internal, we just have tag the
> functions as such, which can be handled with a cocinelle or awk script.
> 
> Neil

This is good, I like alot about this, especially the build system
complaining loudly when the developer does something they shouldn't - I
think anything that we can add that promotes good behaviors is to be
100% welcomed.

I also agree with the points made elsewhere that this is essentially
trying to solve a header problem, the mixing of public and private
symbols in what are public headers, with __rte_internal. Adding
__rte_internal would essentially ratify that behavior, whereas I would
argue that something inherently private, should never see the light of
day in a public header.

I completely get that it may be more work, however for me it is better
way to fix this problem. It would also add completely clarity, all the
extra hassle around does it have the rte_ prefix goes away - if it is in
a "public header" it is part of the ABI/API, end of discussion.

Finally, not opposed to also asking folks putting symbols in the private
header to mark those symbols with __rte_internal.

>  
> 
>>>
>>>>>
>>>>> 4) Adding a tag like __rte_internal creates an interlock whereby,
>>>>> not only are internal functions excused from ABI constraints, but
>>>>> forces developers to intentionally mark their internal functions as
>>>>> being internal in the code, which is beneficial to clarlity of understanding
>>> during the development process.
>>>>
>>>> No issues in adding __rte_internal. But, I am against current
>>>> implementaion, Ie. adding objdump dependency
>>> That dependency already exists for the __rte_external flag
>>
>> Sorry, I could not see the dependency.
>>
>> [master][dpdk.org] $ grep -ri "objdump" devtools/
>> [master][dpdk.org] $ grep -ri "objdump" usertools/
>> [master][dpdk.org] $ grep -ri "__rte_external" *
>>
>>>
>>>> to checkpatch i.e developer has to build the library first so  that
>>>> checkpatch can can know, Is it belongs to internal section or not?
>>>>
>>> What developer is running checkpatch/posting patches without first building
>>> their changes?
>>
>> # it is not developer, The CI/CD tools can quicky check the sanity of patches
>> before the build itself. Why to add unnecessary dependency?
>> # If some PMD is not building if the requirements are not meet(say AES NI PMD for crypto)
>> then how do take care of the dependency.
>>
>>
>>>
>>>
>>>>>
>>>>> 5) Adding a tag like __rte_internal is explicit, and allows
>>>>> developers to use a single header file instead of multiple header
>>>>> files if they so choose
>>>>>
>>>>> We went through this with experimental symbols as well[1], and it
>>>>> just makes more sense to me to clearly document in the code what
>>>>> constitutes an internal symbol rather than relying on naming
>>>>> conventions and hoping that developers read the documentation before
>>>>> exporting a symbol publically.
>>>>>
>>>>>
>>>>> [1] https://mails.dpdk.org/archives/dev/2017-December/083828.html
>>>>>>>
>>>>>>> If we really wanted to go down that road, we could use a
>>>>>>> mechainsm simmilar to the EXPORT_SYMBOL / EXPORT_SYMBOL_GPL
>>>>>>> infrastructure that the kernel uses, but that would required
>>>>>>> building our own custom linker script, which seems like overkill here.
>>>>>>>
>>>>>>> Best
>>>>>>> Neil
>>>>>>>
>>>>>>>> /Bruce
>>>>>>>>
>>>>>>
>>>>
>>
> 





^ permalink raw reply	[relevance 3%]

* [dpdk-dev] [PATCH v2 10/10] doc: update release notes for 19.08
  @ 2019-06-07 10:06  4%   ` Damian Nowak
  2019-06-13  8:14  0%     ` Akhil Goyal
    1 sibling, 1 reply; 200+ results
From: Damian Nowak @ 2019-06-07 10:06 UTC (permalink / raw)
  To: dev; +Cc: fiona.trahe, arkadiuszx.kusztal, Damian Nowak

This patch adds release note entries for
hash-cipher digest-encrypted operations
and new digest_encrypted feature flag.

Signed-off-by: Damian Nowak <damianx.nowak@intel.com>
---
 doc/guides/rel_notes/release_19_08.rst | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index b9510f9..1c85a2e 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -54,6 +54,11 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **Updated the QuickAssist Technology (QAT) symmetric crypto PMD.**
+
+  Added support for hash-cipher with digest encrypted, when using
+  out-of-place operations.
+
 
 Removed Items
 -------------
@@ -83,6 +88,9 @@ API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* cryptodev: ``RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED`` feature flag
+  has been introduced.
+
 
 ABI Changes
 -----------
-- 
2.7.4


^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v2] eal: fix positive error codes from probe/remove
  @ 2019-06-07  8:32  3%     ` David Marchand
  2019-06-26 21:03  0%       ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: David Marchand @ 2019-06-07  8:32 UTC (permalink / raw)
  To: Ilya Maximets, Thomas Monjalon, Anatoly Burakov
  Cc: dev, Jan Blunck, Qi Zhang, Kevin Traynor, dpdk stable, Gaetan Rivet

On Thu, Jun 6, 2019 at 12:03 PM Ilya Maximets <i.maximets@samsung.com>
wrote:

> According to API, 'rte_dev_probe()' and 'rte_dev_remove()' must
> return 0 or negative error code. Bus code returns positive values
> if device wasn't recognized by any driver, so the result of
> 'bus->plug/unplug()' must be converted. 'local_dev_probe()' and
> 'local_dev_remove()' also has their internal API, so the conversion
> should be done there.
>
> Positive on remove means that device not found by driver.
>

For backports, it is safer to add the check on > 0.
The patch looks good to me.

Reviewed-by: David Marchand <david.marchand@redhat.com>


But I have some comments on the current state of the code.
After inspecting the eal and buses, this problem is not supposed to happen
on the rte_dev_remove path.
rte_dev_remove() ensures that it calls local_dev_remove() after checking
that the device is attached to a driver (see the check on
!rte_dev_probed()).


Anatoly,

- When handling a detach operation in the primary process
https://git.dpdk.org/dpdk/tree/lib/librte_eal/common/hotplug_mp.c#n124, we
signal all other secondary processes to detach right away.
Then we do a bus/device lookup.
Then we call the bus unplug.

Would not it be better to check the device exists _and_ check if the device
is attached to a driver in the primary process before calling other
secondary processes?


Thomas,

- Calling unplug on a device that is not attached is a bit weird to me, all
the more so that we have rte_dev_probed().
But there might be users calling directly the bus unplug api and not the
official api...
Does this enter the ABI stability perimeter?
If not, I would be for changing unplug api so that we only deal with 0 or <
0 on remove path.

On the plug side, is there a reason why we do not check for
rte_dev_probed() and let the bus replies that the device is already probed?
Does it have something to do with representors ?
Only guessing.

- On the plug side again, can't we have an indication from the buses that
they have a driver that can handle the device rather than this odd (and
historical) > 0 return code?
This should not change the current behavior, just make the code a bit
easier to understand.

I know you are travelling, so this can wait anyway.



-- 
David Marchand

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v1 1/2] lib/ring: add enqueue-dequeue callabck
  @ 2019-06-07  6:03  3% ` Honnappa Nagarahalli
  2019-06-10  5:12  0%   ` Varghese, Vipin
  0 siblings, 1 reply; 200+ results
From: Honnappa Nagarahalli @ 2019-06-07  6:03 UTC (permalink / raw)
  To: Vipin Varghese, olivier.matz, reshma.pattan, keith.wiles, dev
  Cc: sanjay.padubidri, Honnappa Nagarahalli, nd, nd

> 
> Add callback event handler for enqueue dequeue operation on ring.
> The pre-enqueue and post-dequeue operation on ring is selected to invoke
> user callback handler.
Can you provide a use case for this to better understand the need?

> 
> Signed-off-by: Vipin Varghese <vipin.varghese@intel.com>
> ---
>  config/common_base                   |   1 +
>  lib/librte_ring/Makefile             |   1 +
>  lib/librte_ring/meson.build          |   2 +
>  lib/librte_ring/rte_ring.c           | 187 +++++++++++++++++++++++++++
>  lib/librte_ring/rte_ring.h           | 117 ++++++++++++++++-
>  lib/librte_ring/rte_ring_version.map |   9 ++
>  6 files changed, 316 insertions(+), 1 deletion(-)
> 
> diff --git a/config/common_base b/config/common_base index
> ec29455d2..022734f19 100644
> --- a/config/common_base
> +++ b/config/common_base
> @@ -500,6 +500,7 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=n
> CONFIG_RTE_LIBRTE_PMD_RING=y
>  CONFIG_RTE_PMD_RING_MAX_RX_RINGS=16
>  CONFIG_RTE_PMD_RING_MAX_TX_RINGS=16
> +CONFIG_RTE_RING_ENQDEQ_CALLBACKS=n
> 
>  #
>  # Compile SOFTNIC PMD
> diff --git a/lib/librte_ring/Makefile b/lib/librte_ring/Makefile index
> 21a36770d..4f086e687 100644
> --- a/lib/librte_ring/Makefile
> +++ b/lib/librte_ring/Makefile
> @@ -6,6 +6,7 @@ include $(RTE_SDK)/mk/rte.vars.mk  # library name  LIB =
> librte_ring.a
> 
> +CFLAGS += -DALLOW_EXPERIMENTAL_API
>  CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3  LDLIBS += -lrte_eal
> 
> diff --git a/lib/librte_ring/meson.build b/lib/librte_ring/meson.build index
> ab8b0b469..b92dcf027 100644
> --- a/lib/librte_ring/meson.build
> +++ b/lib/librte_ring/meson.build
> @@ -2,6 +2,8 @@
>  # Copyright(c) 2017 Intel Corporation
> 
>  version = 2
> +allow_experimental_apis = true
> +
>  sources = files('rte_ring.c')
>  headers = files('rte_ring.h',
>  		'rte_ring_c11_mem.h',
> diff --git a/lib/librte_ring/rte_ring.c b/lib/librte_ring/rte_ring.c index
> b89ecf999..ee740c401 100644
> --- a/lib/librte_ring/rte_ring.c
> +++ b/lib/librte_ring/rte_ring.c
> @@ -43,6 +43,11 @@ EAL_REGISTER_TAILQ(rte_ring_tailq)
>  /* true if x is a power of 2 */
>  #define POWEROF2(x) ((((x)-1) & (x)) == 0)
> 
> +/* spinlock for pre-enqueue callback */ rte_spinlock_t
> +rte_ring_preenq_cb_lock = RTE_SPINLOCK_INITIALIZER;
> +/* spinlock for post-dequeue callback */ rte_spinlock_t
> +rte_ring_pstdeq_cb_lock = RTE_SPINLOCK_INITIALIZER;
> +
>  /* return the size of memory occupied by a ring */  ssize_t
> rte_ring_get_memsize(unsigned count) @@ -103,6 +108,9 @@
> rte_ring_init(struct rte_ring *r, const char *name, unsigned count,
>  	r->prod.head = r->cons.head = 0;
>  	r->prod.tail = r->cons.tail = 0;
> 
> +	TAILQ_INIT(&(r->enq_cbs));
> +	TAILQ_INIT(&(r->deq_cbs));
> +
>  	return 0;
>  }
> 
> @@ -220,6 +228,185 @@ rte_ring_free(struct rte_ring *r)
>  	rte_free(te);
>  }
> 
> +int __rte_experimental
> +rte_ring_preenq_callback_register(struct rte_ring *r,
> +		rte_ring_cb_fn cb_fn, void *cb_arg)
> +{
> +#ifndef RTE_RING_ENQDEQ_CALLBACKS
> +	rte_errno = ENOTSUP;
> +	return -ENOTSUP;
> +#endif
> +
> +	struct rte_ring_callback *user_cb;
> +	rte_spinlock_t *lock = &rte_ring_preenq_cb_lock;
> +
> +	if (!cb_fn)
> +		return -EINVAL;
> +
> +	if (!rte_ring_get_capacity(r)) {
> +		RTE_LOG(ERR, RING, "Invalid ring=%p", r);
> +		return -EINVAL;
> +	}
> +
> +	rte_spinlock_lock(lock);
> +
> +	TAILQ_FOREACH(user_cb, &(r->enq_cbs), next) {
> +		if ((void *) user_cb->cb_fn == (void *) cb_fn &&
> +				user_cb->cb_arg == cb_arg)
> +			break;
> +	}
> +
> +	/* create a new callback. */
> +	if (user_cb == NULL) {
> +		user_cb = rte_zmalloc("RING_USER_CALLBACK",
> +				sizeof(struct rte_ring_callback), 0);
> +		if (user_cb != NULL) {
> +			user_cb->cb_fn = cb_fn;
> +			user_cb->cb_arg = cb_arg;
> +			TAILQ_INSERT_TAIL(&(r->enq_cbs), user_cb, next);
> +		}
> +	}
> +
> +	rte_spinlock_unlock(lock);
> +
> +	return (user_cb == NULL) ? -ENOMEM : 0; }
> +
> +int __rte_experimental
> +rte_ring_pstdeq_callback_register(struct rte_ring *r,
> +		rte_ring_cb_fn cb_fn, void *cb_arg)
> +{
> +#ifndef RTE_RING_ENQDEQ_CALLBACKS
> +	rte_errno = ENOTSUP;
> +	return -ENOTSUP;
> +#endif
> +
> +	struct rte_ring_callback *user_cb;
> +	rte_spinlock_t *lock = &rte_ring_pstdeq_cb_lock;
> +
> +	if (!cb_fn)
> +		return -EINVAL;
> +
> +	if (!rte_ring_get_capacity(r)) {
> +		RTE_LOG(ERR, RING, "Invalid ring=%p", r);
> +		return -EINVAL;
> +	}
> +
> +	rte_spinlock_lock(lock);
> +
> +	TAILQ_FOREACH(user_cb, &(r->deq_cbs), next) {
> +		if ((void *) user_cb->cb_fn == (void *) cb_fn &&
> +				user_cb->cb_arg == cb_arg)
> +			break;
> +	}
> +
> +	/* create a new callback. */
> +	if (user_cb == NULL) {
> +		user_cb = rte_zmalloc("RING_USER_CALLBACK",
> +				sizeof(struct rte_ring_callback), 0);
> +		if (user_cb != NULL) {
> +			user_cb->cb_fn = cb_fn;
> +			user_cb->cb_arg = cb_arg;
> +			TAILQ_INSERT_TAIL(&(r->deq_cbs), user_cb, next);
> +		}
> +	}
> +
> +	rte_spinlock_unlock(lock);
> +
> +	return (user_cb == NULL) ? -ENOMEM : 0; }
> +
> +int __rte_experimental
> +rte_ring_preenq_callback_unregister(struct rte_ring *r,
> +		rte_ring_cb_fn cb_fn, void *cb_arg)
> +{
> +#ifndef RTE_RING_ENQDEQ_CALLBACKS
> +	rte_errno = ENOTSUP;
> +	return -ENOTSUP;
> +#endif
> +
> +	int ret = 0;
> +	struct rte_ring_callback *cb, *next;
> +	rte_spinlock_t *lock = &rte_ring_preenq_cb_lock;
> +
> +	if (!cb_fn)
> +		return -EINVAL;
> +
> +	if (!rte_ring_get_capacity(r)) {
> +		RTE_LOG(ERR, RING, "Invalid ring=%p", r);
> +		return -EINVAL;
> +	}
> +
> +	rte_spinlock_lock(lock);
> +
> +	ret = -EINVAL;
> +	for (cb = TAILQ_FIRST(&r->enq_cbs); cb != NULL; cb = next) {
> +		next = TAILQ_NEXT(cb, next);
> +
> +		if (cb->cb_fn != cb_fn || cb->cb_arg != cb_arg)
> +			continue;
> +
> +		if (cb->active == 0) {
> +			TAILQ_REMOVE(&(r->enq_cbs), cb, next);
> +			rte_free(cb);
> +			ret = 0;
> +		} else {
> +			ret = -EAGAIN;
> +		}
> +	}
> +
> +	rte_spinlock_unlock(lock);
> +
> +	return ret;
> +}
> +
> +int __rte_experimental
> +rte_ring_pstdeq_callback_unregister(struct rte_ring *r,
> +		rte_ring_cb_fn cb_fn, void *cb_arg)
> +{
> +#ifndef RTE_RING_ENQDEQ_CALLBACKS
> +	rte_errno = ENOTSUP;
> +	return -ENOTSUP;
> +#endif
> +
> +	int ret = 0;
> +	struct rte_ring_callback *cb, *next;
> +	rte_spinlock_t *lock = &rte_ring_pstdeq_cb_lock;
> +
> +	if (!cb_fn)
> +		return -EINVAL;
> +
> +	if (!rte_ring_get_capacity(r)) {
> +		RTE_LOG(ERR, RING, "Invalid ring=%p", r);
> +		return -EINVAL;
> +	}
> +
> +	rte_spinlock_lock(lock);
> +
> +	ret = -EINVAL;
> +	for (cb = TAILQ_FIRST(&r->deq_cbs); cb != NULL; cb = next) {
> +		next = TAILQ_NEXT(cb, next);
> +
> +		if (cb->cb_fn != cb_fn || cb->cb_arg != cb_arg)
> +			continue;
> +
> +		if (cb->active == 0) {
> +			TAILQ_REMOVE(&(r->deq_cbs), cb, next);
> +			rte_free(cb);
> +			ret = 0;
> +		} else {
> +			ret = -EAGAIN;
> +		}
> +	}
> +
> +	rte_spinlock_unlock(lock);
> +
> +	return ret;
> +
> +	return 0;
> +}
> +
> +
>  /* dump the status of the ring on the console */  void  rte_ring_dump(FILE *f,
> const struct rte_ring *r) diff --git a/lib/librte_ring/rte_ring.h
> b/lib/librte_ring/rte_ring.h index e265e9479..fb0f3efb5 100644
> --- a/lib/librte_ring/rte_ring.h
> +++ b/lib/librte_ring/rte_ring.h
> @@ -63,6 +63,11 @@ enum rte_ring_queue_behavior {
> 
>  struct rte_memzone; /* forward declaration, so as not to require memzone.h
> */
> 
> +struct rte_ring_callback;
> +
> +TAILQ_HEAD(rte_ring_enq_cb_list, rte_ring_callback);
> +TAILQ_HEAD(rte_ring_deq_cb_list, rte_ring_callback);
> +
>  /* structure to hold a pair of head/tail values and other metadata */  struct
> rte_ring_headtail {
>  	volatile uint32_t head;  /**< Prod/consumer head. */ @@ -103,6
> +108,20 @@ struct rte_ring {
>  	/** Ring consumer status. */
>  	struct rte_ring_headtail cons __rte_cache_aligned;
>  	char pad2 __rte_cache_aligned; /**< empty cache line */
> +
> +	struct rte_ring_enq_cb_list enq_cbs;
> +	struct rte_ring_deq_cb_list deq_cbs;
> +};
This breaks ABI compatibility

> +
> +typedef unsigned int (*rte_ring_cb_fn)(struct rte_ring *r,
> +			void *obj_table, unsigned int n,
> +			void *cb_arg);
> +
> +struct rte_ring_callback {
> +	TAILQ_ENTRY(rte_ring_callback) next; /* Callbacks list */
> +	rte_ring_cb_fn cb_fn; /* Callback address */
> +	void *cb_arg; /* Parameter for callback */
> +	uint32_t active; /* Callback is executing */
>  };
> 
>  #define RING_F_SP_ENQ 0x0001 /**< The default enqueue is "single-
> producer". */ @@ -850,9 +869,23 @@ rte_ring_sp_enqueue_burst(struct
> rte_ring *r, void * const *obj_table,
>   *   - n: Actual number of objects enqueued.
>   */
>  static __rte_always_inline unsigned
> -rte_ring_enqueue_burst(struct rte_ring *r, void * const *obj_table,
> +rte_ring_enqueue_burst(struct rte_ring *r, void **obj_table,
>  		      unsigned int n, unsigned int *free_space)  {
> +#ifdef RTE_RING_ENQDEQ_CALLBACKS
> +	struct rte_ring_callback *cb = NULL;
> +
> +	TAILQ_FOREACH(cb, &(r->enq_cbs), next) {
Need to take the TAILQ lock before this. For ex: what happens if a un-register is called concurrently?
Also, traversing a linked list for every enqueue call would be too costly. May be, understanding the use case will help.

> +		if (cb->cb_fn == NULL)
> +			continue;
> +
> +		cb->active = 1;
> +		n = cb->cb_fn(r, obj_table, n, cb->cb_arg);
> +		cb->active = 0;
> +	}
> +
> +#endif
> +
>  	return __rte_ring_do_enqueue(r, obj_table, n,
> RTE_RING_QUEUE_VARIABLE,
>  			r->prod.single, free_space);
>  }

<snip>

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-06 15:03  3%                 ` Neil Horman
@ 2019-06-06 15:14  0%                   ` Jerin Jacob Kollanukkaran
  2019-06-07 15:42  3%                   ` Ray Kinsella
  1 sibling, 0 replies; 200+ results
From: Jerin Jacob Kollanukkaran @ 2019-06-06 15:14 UTC (permalink / raw)
  To: Neil Horman; +Cc: Bruce Richardson, dev, Thomas Monjalon

> -----Original Message-----
> From: Neil Horman <nhorman@tuxdriver.com>
> Sent: Thursday, June 6, 2019 8:34 PM
> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
> Thomas Monjalon <thomas@monjalon.net>
> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> 
> On Thu, Jun 06, 2019 at 02:02:03PM +0000, Jerin Jacob Kollanukkaran wrote:
> > > -----Original Message-----
> > > From: Neil Horman <nhorman@tuxdriver.com>
> > > Sent: Thursday, June 6, 2019 7:05 PM
> > > To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> > > Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
> > > Thomas Monjalon <thomas@monjalon.net>
> > > Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > >
> > > On Thu, Jun 06, 2019 at 12:04:57PM +0000, Jerin Jacob Kollanukkaran
> wrote:
> > > > > -----Original Message-----
> > > > > From: Neil Horman <nhorman@tuxdriver.com>
> > > > > Sent: Thursday, June 6, 2019 5:04 PM
> > > > > To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> > > > > Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
> > > > > Thomas Monjalon <thomas@monjalon.net>
> > > > > Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > > > >
> > > > > On Thu, Jun 06, 2019 at 09:44:52AM +0000, Jerin Jacob
> > > > > Kollanukkaran
> > > wrote:
> > > > > > > -----Original Message-----
> > > > > > > From: Neil Horman <nhorman@tuxdriver.com>
> > > > > > > Sent: Wednesday, June 5, 2019 11:41 PM
> > > > > > > To: Bruce Richardson <bruce.richardson@intel.com>
> > > > > > > Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
> > > > > > > dev@dpdk.org; Thomas Monjalon <thomas@monjalon.net>
> > > > > > > Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal
> > > > > > > tag
> > > > > > >
> > > > > > > On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson
> wrote:
> > > > > > > > On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob
> > > > > > > > Kollanukkaran
> > > > > > > wrote:
> > > > > > > > > > -----Original Message-----
> > > > > > > > > > From: Neil Horman <nhorman@tuxdriver.com>
> > > > > > > > > > Sent: Sunday, May 26, 2019 12:14 AM
> > > > > > > > > > To: dev@dpdk.org
> > > > > > > > > > Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob
> > > > > > > > > > Kollanukkaran <jerinj@marvell.com>; Bruce Richardson
> > > > > > > > > > <bruce.richardson@intel.com>; Thomas Monjalon
> > > > > > > > > > <thomas@monjalon.net>
> > > > > > > > > > Subject: [EXT] [RFC PATCH 0/2] introduce
> > > > > > > > > > __rte_internal tag
> > > > > > > > > >
> > > > > > > > > > Hey-
> > > > > > > > > > 	Based on our recent conversations regarding the use
> > > > > > > > > > of symbols only meant for internal dpdk consumption
> > > > > > > > > > (between dpdk libraries), this is an idea that I've
> > > > > > > > > > come up with that I'd like to get some feedback on
> > > > > > > > > >
> > > > > > > > > > Summary:
> > > > > > > > > > 1) We have symbols in the DPDK that are meant to be
> > > > > > > > > > used between DPDK libraries, but not by applications
> > > > > > > > > > linking to them
> > > > > > > > > > 2) We would like to document those symbols in the
> > > > > > > > > > code, so as to note them clearly as for being meant
> > > > > > > > > > for internal use only
> > > > > > > > > > 3) Linker symbol visibility is a very coarse grained
> > > > > > > > > > tool, and so there is no good way in a single library
> > > > > > > > > > to mark items as being meant for use only by other
> > > > > > > > > > DPDK libraries, at least not without some extensive
> > > > > > > > > > runtime checking
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > Proposal:
> > > > > > > > > > I'm proposing that we introduce the __rte_internal tag.
> > > > > > > > > > From a coding standpoint it works a great deal like
> > > > > > > > > > the __rte_experimental tag in that it expempts the
> > > > > > > > > > tagged symbol from ABI constraints (as the only users
> > > > > > > > > > should be represented in the DPDK build environment).
> > > > > > > > > > Additionally, the __rte_internal macro resolves
> > > > > > > > > > differently based on the definition of the
> > > > > > > > > > BUILDING_RTE_SDK flag (working under the assumption
> > > > > > > > > > that said flag should only ever be set if we are
> > > > > > > > > > actually building DPDK libraries which will make use
> > > > > > > > > > of internal calls).  If the BUILDING_RTE_SDK flag is
> > > > > > > > > > set __rte_internal resolves to __attribute__((section
> > > > > > > > > > "text.internal)), placing it in a special text section
> > > > > > > > > > which is then used to validate that the the symbol
> > > > > > > > > > appears in the INTERNAL section of the corresponding
> > > > > > > > > > library version
> > > map).
> > > > > > > > > > If BUILDING_RTE_SDK is not set, then __rte_internal
> > > > > > > > > > resolves to
> > > > > > > __attribute__((error("..."))), which causes any caller of
> > > > > > > the tagged function to throw an error at compile time,
> > > > > > > indicating that the symbol is not available for external use.
> > > > > > > > > >
> > > > > > > > > > This isn't a perfect solution, as applications can
> > > > > > > > > > still hack around it of course,
> > > > > > > > >
> > > > > > > > > I think, one way to, avoid, hack around could be to,
> > > > > > > > >
> > > > > > > > > 1) at config stage, create  a random number for the
> > > > > > > > > build
> > > > > > > > > 2) introduce RTE_CALL_INTERNAL macro for calling
> > > > > > > > > internal function, compare the generated random number
> > > > > > > > > for allowing the calls to make within the library. i.e
> > > > > > > > > leverage the fact that external library would never know
> > > > > > > > > the random number generated for the DPDK build
> > > > > > > and internal driver code does.
> > > > > > > > >
> > > > > > > > Do we really need to care about this. If have some
> > > > > > > > determined enough to hack around our limitations, then
> > > > > > > > they surely know that they have an unsupported
> > > > > > > > configuration. We just need to protect against inadvertent use
> of internals, IMHO.
> > > > > > > >
> > > > > > > I agree, I too had thought about doing some sort of internal
> > > > > > > runtime checking to match internal only symbols, such that
> > > > > > > they were only accessable by internally approved users, but
> > > > > > > it started to feel like a great
> > > > > deal of overhead.
> > > > > > > Its a good idea for a general mechanism I think, but I
> > > > > > > believe the value here is more to internally document which
> > > > > > > apis we want to mark as being for internal use only, and
> > > > > > > create a lightweight roadblock at build time to catch users
> inadvertently using them.
> > > > > > > Determined users will get around anything, and theres not
> > > > > > > much we can do to stop
> > > > > them.
> > > > > >
> > > > > > I agree too. IMHO, Simply having following items would be
> > > > > > enough
> > > > > >
> > > > > > 1) Avoid exposing the internal function prototype through
> > > > > > public header files
> > > > > > 2) Add @internal to API documentation
> > > > > > 3) Just decide the name space for internal API for tooling(i.e
> > > > > > not start with rte_ or so) Using objdump scheme to detect
> > > > > > internal functions
> > > > > requires the the library to build prior to run the checkpatch.
> > > > > >
> > > > >
> > > > > No, I'm not comfortable with that approach, and I've stated why:
> > > > > 1) Not exposing the functions via header files is a fine start
> > > > >
> > > > > 2) Adding internal documentation is also fine, but does nothing
> > > > > to correlate the code implementing those functions to the
> > > > > documentation.  Its valuable to have a tag on a function
> > > > > identifying it as
> > > internal only.
> > > > >
> > > > > 3) Using naming conventions to separate internal only from
> > > > > non-internal functions is a vague approach, requiring future
> > > > > developers to be cogniscent of the convention and make the
> > > > > appropriate naming choices.  It also implicitly restricts the
> > > > > abliity for future developers to make naming changes in conflict
> > > > > with that convention
> > > >
> > > > Enforcing the naming convention can be achieved through tooling as
> well.
> > > >
> > > Sure, but why enforce any function naming at all, when you don't have
> to.
> >
> > May I ask,  why to  enforce __rte_internal, when you don't have to
> >
> 
> Because its more clear.  Implicitly deciding that any function not prefixed with
> rte_ is internal only does nothing to prevent a developer from accidentally
> naming a function incorrectly, exporting it, and allowing a user to call it. We
> can move headers all you want, but we provide an ABI guarantee to end
> users, and developers should have a way to clearly record that without
> having to check the documentation for each function that an application
> developer wants to use.
> 
> The long and the short of it for me is that I want a way for developers to opt
> their code into an internal only condition, not to just document it as such and
> hope its up to date.  If they tag a function as __rte_internal then its clearly
> marked as internal only, they have checks to ensure that its in the INTERNAL
> section of the version map, and should that header somehow get externally
> exported (see rte_mempool_check_cookies for an example of how thats
> happened), users are prevented from using them at build time, rather than
> having to ask questions on the list, or read documentation after an error to
> find out "oops, shouldn't have done that".
> 
> I think you'll find that going through all the header files, and bifurcating them
> to public and private headers is a much larger undertaking than just tagging
> those functions accordingly.  a quick scan of all our header file for the
> @internal tag shows about 260 instances of such functions, almost all of
> which are published to applications.  All of those functions would have to be
> moved to private headers, and their requisite C files would need to be
> updated to include the new header.  with the use of __rte_internal, we just
> have tag the functions as such, which can be handled with a cocinelle or awk
> script.

I don't have any strong opinion on name prefix vs marking as __rte_internal.
Or combination of both. I am fine any approach.

I have only strong option on not to  induce objdump dependency for checkpatch. 
For the reason mentioned in http://mails.dpdk.org/archives/dev/2019-June/134160.html.


> 
> Neil
> 
> 
> > >
> > > > >
> > > > > 4) Adding a tag like __rte_internal creates an interlock
> > > > > whereby, not only are internal functions excused from ABI
> > > > > constraints, but forces developers to intentionally mark their
> > > > > internal functions as being internal in the code, which is
> > > > > beneficial to clarlity of understanding
> > > during the development process.
> > > >
> > > > No issues in adding __rte_internal. But, I am against current
> > > > implementaion, Ie. adding objdump dependency
> > > That dependency already exists for the __rte_external flag
> >
> > Sorry, I could not see the dependency.
> >
> > [master][dpdk.org] $ grep -ri "objdump" devtools/ [master][dpdk.org] $
> > grep -ri "objdump" usertools/ [master][dpdk.org] $ grep -ri
> > "__rte_external" *
> >
> > >
> > > > to checkpatch i.e developer has to build the library first so
> > > > that checkpatch can can know, Is it belongs to internal section or not?
> > > >
> > > What developer is running checkpatch/posting patches without first
> > > building their changes?
> >
> > # it is not developer, The CI/CD tools can quicky check the sanity of
> > patches before the build itself. Why to add unnecessary dependency?
> > # If some PMD is not building if the requirements are not meet(say AES
> > NI PMD for crypto) then how do take care of the dependency.
> >
> >
> > >
> > >
> > > > >
> > > > > 5) Adding a tag like __rte_internal is explicit, and allows
> > > > > developers to use a single header file instead of multiple
> > > > > header files if they so choose
> > > > >
> > > > > We went through this with experimental symbols as well[1], and
> > > > > it just makes more sense to me to clearly document in the code
> > > > > what constitutes an internal symbol rather than relying on
> > > > > naming conventions and hoping that developers read the
> > > > > documentation before exporting a symbol publically.
> > > > >
> > > > >
> > > > > [1]
> > > > > https://mails.dpdk.org/archives/dev/2017-December/083828.html
> > > > > > >
> > > > > > > If we really wanted to go down that road, we could use a
> > > > > > > mechainsm simmilar to the EXPORT_SYMBOL /
> EXPORT_SYMBOL_GPL
> > > > > > > infrastructure that the kernel uses, but that would required
> > > > > > > building our own custom linker script, which seems like overkill
> here.
> > > > > > >
> > > > > > > Best
> > > > > > > Neil
> > > > > > >
> > > > > > > > /Bruce
> > > > > > > >
> > > > > >
> > > >
> >

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-06 14:02  0%               ` Jerin Jacob Kollanukkaran
@ 2019-06-06 15:03  3%                 ` Neil Horman
  2019-06-06 15:14  0%                   ` Jerin Jacob Kollanukkaran
  2019-06-07 15:42  3%                   ` Ray Kinsella
  0 siblings, 2 replies; 200+ results
From: Neil Horman @ 2019-06-06 15:03 UTC (permalink / raw)
  To: Jerin Jacob Kollanukkaran; +Cc: Bruce Richardson, dev, Thomas Monjalon

On Thu, Jun 06, 2019 at 02:02:03PM +0000, Jerin Jacob Kollanukkaran wrote:
> > -----Original Message-----
> > From: Neil Horman <nhorman@tuxdriver.com>
> > Sent: Thursday, June 6, 2019 7:05 PM
> > To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> > Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
> > Thomas Monjalon <thomas@monjalon.net>
> > Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > 
> > On Thu, Jun 06, 2019 at 12:04:57PM +0000, Jerin Jacob Kollanukkaran wrote:
> > > > -----Original Message-----
> > > > From: Neil Horman <nhorman@tuxdriver.com>
> > > > Sent: Thursday, June 6, 2019 5:04 PM
> > > > To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> > > > Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
> > > > Thomas Monjalon <thomas@monjalon.net>
> > > > Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > > >
> > > > On Thu, Jun 06, 2019 at 09:44:52AM +0000, Jerin Jacob Kollanukkaran
> > wrote:
> > > > > > -----Original Message-----
> > > > > > From: Neil Horman <nhorman@tuxdriver.com>
> > > > > > Sent: Wednesday, June 5, 2019 11:41 PM
> > > > > > To: Bruce Richardson <bruce.richardson@intel.com>
> > > > > > Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
> > > > > > dev@dpdk.org; Thomas Monjalon <thomas@monjalon.net>
> > > > > > Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > > > > >
> > > > > > On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson wrote:
> > > > > > > On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob
> > > > > > > Kollanukkaran
> > > > > > wrote:
> > > > > > > > > -----Original Message-----
> > > > > > > > > From: Neil Horman <nhorman@tuxdriver.com>
> > > > > > > > > Sent: Sunday, May 26, 2019 12:14 AM
> > > > > > > > > To: dev@dpdk.org
> > > > > > > > > Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob
> > > > > > > > > Kollanukkaran <jerinj@marvell.com>; Bruce Richardson
> > > > > > > > > <bruce.richardson@intel.com>; Thomas Monjalon
> > > > > > > > > <thomas@monjalon.net>
> > > > > > > > > Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal
> > > > > > > > > tag
> > > > > > > > >
> > > > > > > > > Hey-
> > > > > > > > > 	Based on our recent conversations regarding the use of
> > > > > > > > > symbols only meant for internal dpdk consumption (between
> > > > > > > > > dpdk libraries), this is an idea that I've come up with
> > > > > > > > > that I'd like to get some feedback on
> > > > > > > > >
> > > > > > > > > Summary:
> > > > > > > > > 1) We have symbols in the DPDK that are meant to be used
> > > > > > > > > between DPDK libraries, but not by applications linking to
> > > > > > > > > them
> > > > > > > > > 2) We would like to document those symbols in the code, so
> > > > > > > > > as to note them clearly as for being meant for internal
> > > > > > > > > use only
> > > > > > > > > 3) Linker symbol visibility is a very coarse grained tool,
> > > > > > > > > and so there is no good way in a single library to mark
> > > > > > > > > items as being meant for use only by other DPDK libraries,
> > > > > > > > > at least not without some extensive runtime checking
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > Proposal:
> > > > > > > > > I'm proposing that we introduce the __rte_internal tag.
> > > > > > > > > From a coding standpoint it works a great deal like the
> > > > > > > > > __rte_experimental tag in that it expempts the tagged
> > > > > > > > > symbol from ABI constraints (as the only users should be
> > > > > > > > > represented in the DPDK build environment).  Additionally,
> > > > > > > > > the __rte_internal macro resolves differently based on the
> > > > > > > > > definition of the BUILDING_RTE_SDK flag (working under the
> > > > > > > > > assumption that said flag should only ever be set if we
> > > > > > > > > are actually building DPDK libraries which will make use
> > > > > > > > > of internal calls).  If the BUILDING_RTE_SDK flag is set
> > > > > > > > > __rte_internal resolves to __attribute__((section
> > > > > > > > > "text.internal)), placing it in a special text section
> > > > > > > > > which is then used to validate that the the symbol appears
> > > > > > > > > in the INTERNAL section of the corresponding library version
> > map).
> > > > > > > > > If BUILDING_RTE_SDK is not set, then __rte_internal
> > > > > > > > > resolves to
> > > > > > __attribute__((error("..."))), which causes any caller of the
> > > > > > tagged function to throw an error at compile time, indicating
> > > > > > that the symbol is not available for external use.
> > > > > > > > >
> > > > > > > > > This isn't a perfect solution, as applications can still
> > > > > > > > > hack around it of course,
> > > > > > > >
> > > > > > > > I think, one way to, avoid, hack around could be to,
> > > > > > > >
> > > > > > > > 1) at config stage, create  a random number for the build
> > > > > > > > 2) introduce RTE_CALL_INTERNAL macro for calling internal
> > > > > > > > function, compare the generated random number for allowing
> > > > > > > > the calls to make within the library. i.e leverage the fact
> > > > > > > > that external library would never know the random number
> > > > > > > > generated for the DPDK build
> > > > > > and internal driver code does.
> > > > > > > >
> > > > > > > Do we really need to care about this. If have some determined
> > > > > > > enough to hack around our limitations, then they surely know
> > > > > > > that they have an unsupported configuration. We just need to
> > > > > > > protect against inadvertent use of internals, IMHO.
> > > > > > >
> > > > > > I agree, I too had thought about doing some sort of internal
> > > > > > runtime checking to match internal only symbols, such that they
> > > > > > were only accessable by internally approved users, but it
> > > > > > started to feel like a great
> > > > deal of overhead.
> > > > > > Its a good idea for a general mechanism I think, but I believe
> > > > > > the value here is more to internally document which apis we want
> > > > > > to mark as being for internal use only, and create a lightweight
> > > > > > roadblock at build time to catch users inadvertently using them.
> > > > > > Determined users will get around anything, and theres not much
> > > > > > we can do to stop
> > > > them.
> > > > >
> > > > > I agree too. IMHO, Simply having following items would be enough
> > > > >
> > > > > 1) Avoid exposing the internal function prototype through public
> > > > > header files
> > > > > 2) Add @internal to API documentation
> > > > > 3) Just decide the name space for internal API for tooling(i.e not
> > > > > start with rte_ or so) Using objdump scheme to detect internal
> > > > > functions
> > > > requires the the library to build prior to run the checkpatch.
> > > > >
> > > >
> > > > No, I'm not comfortable with that approach, and I've stated why:
> > > > 1) Not exposing the functions via header files is a fine start
> > > >
> > > > 2) Adding internal documentation is also fine, but does nothing to
> > > > correlate the code implementing those functions to the
> > > > documentation.  Its valuable to have a tag on a function identifying it as
> > internal only.
> > > >
> > > > 3) Using naming conventions to separate internal only from
> > > > non-internal functions is a vague approach, requiring future
> > > > developers to be cogniscent of the convention and make the
> > > > appropriate naming choices.  It also implicitly restricts the
> > > > abliity for future developers to make naming changes in conflict
> > > > with that convention
> > >
> > > Enforcing the naming convention can be achieved through tooling as well.
> > >
> > Sure, but why enforce any function naming at all, when you don't have to.
> 
> May I ask,  why to  enforce __rte_internal, when you don't have to
> 

Because its more clear.  Implicitly deciding that any function not prefixed with
rte_ is internal only does nothing to prevent a developer from accidentally
naming a function incorrectly, exporting it, and allowing a user to call it. We
can move headers all you want, but we provide an ABI guarantee to end users, and
developers should have a way to clearly record that without having to check the
documentation for each function that an application developer wants to use.

The long and the short of it for me is that I want a way for developers to opt
their code into an internal only condition, not to just document it as such
and hope its up to date.  If they tag a function as __rte_internal then its
clearly marked as internal only, they have checks to ensure that its in the
INTERNAL section of the version map, and should that header somehow get
externally exported (see rte_mempool_check_cookies for an example of how thats
happened), users are prevented from using them at build time, rather than having
to ask questions on the list, or read documentation after an error to find out
"oops, shouldn't have done that".

I think you'll find that going through all the header files, and bifurcating
them to public and private headers is a much larger undertaking than just
tagging those functions accordingly.  a quick scan of all our header file for
the @internal tag shows about 260 instances of such functions, almost all of
which are published to applications.  All of those functions would have to be
moved to private headers, and their requisite C files would need to be updated
to include the new header.  with the use of __rte_internal, we just have tag the
functions as such, which can be handled with a cocinelle or awk script.

Neil
 

> > 
> > > >
> > > > 4) Adding a tag like __rte_internal creates an interlock whereby,
> > > > not only are internal functions excused from ABI constraints, but
> > > > forces developers to intentionally mark their internal functions as
> > > > being internal in the code, which is beneficial to clarlity of understanding
> > during the development process.
> > >
> > > No issues in adding __rte_internal. But, I am against current
> > > implementaion, Ie. adding objdump dependency
> > That dependency already exists for the __rte_external flag
> 
> Sorry, I could not see the dependency.
> 
> [master][dpdk.org] $ grep -ri "objdump" devtools/
> [master][dpdk.org] $ grep -ri "objdump" usertools/
> [master][dpdk.org] $ grep -ri "__rte_external" *
> 
> > 
> > > to checkpatch i.e developer has to build the library first so  that
> > > checkpatch can can know, Is it belongs to internal section or not?
> > >
> > What developer is running checkpatch/posting patches without first building
> > their changes?
> 
> # it is not developer, The CI/CD tools can quicky check the sanity of patches
> before the build itself. Why to add unnecessary dependency?
> # If some PMD is not building if the requirements are not meet(say AES NI PMD for crypto)
> then how do take care of the dependency.
> 
> 
> > 
> > 
> > > >
> > > > 5) Adding a tag like __rte_internal is explicit, and allows
> > > > developers to use a single header file instead of multiple header
> > > > files if they so choose
> > > >
> > > > We went through this with experimental symbols as well[1], and it
> > > > just makes more sense to me to clearly document in the code what
> > > > constitutes an internal symbol rather than relying on naming
> > > > conventions and hoping that developers read the documentation before
> > > > exporting a symbol publically.
> > > >
> > > >
> > > > [1] https://mails.dpdk.org/archives/dev/2017-December/083828.html
> > > > > >
> > > > > > If we really wanted to go down that road, we could use a
> > > > > > mechainsm simmilar to the EXPORT_SYMBOL / EXPORT_SYMBOL_GPL
> > > > > > infrastructure that the kernel uses, but that would required
> > > > > > building our own custom linker script, which seems like overkill here.
> > > > > >
> > > > > > Best
> > > > > > Neil
> > > > > >
> > > > > > > /Bruce
> > > > > > >
> > > > >
> > >
> 

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-06 13:53  0%                 ` Wiles, Keith
@ 2019-06-06 14:46  0%                   ` Neil Horman
  0 siblings, 0 replies; 200+ results
From: Neil Horman @ 2019-06-06 14:46 UTC (permalink / raw)
  To: Wiles, Keith
  Cc: Jerin Jacob Kollanukkaran, Richardson, Bruce, dev, Thomas Monjalon

On Thu, Jun 06, 2019 at 01:53:47PM +0000, Wiles, Keith wrote:
> 
> 
> > On Jun 6, 2019, at 8:43 AM, Neil Horman <nhorman@tuxdriver.com> wrote:
> > 
> > On Thu, Jun 06, 2019 at 01:18:29PM +0000, Wiles, Keith wrote:
> >> 
> >> 
> >>> On Jun 6, 2019, at 7:04 AM, Jerin Jacob Kollanukkaran <jerinj@marvell.com> wrote:
> >>> 
> >>>> -----Original Message-----
> >>>> From: Neil Horman <nhorman@tuxdriver.com>
> >>>> Sent: Thursday, June 6, 2019 5:04 PM
> >>>> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> >>>> Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
> >>>> Thomas Monjalon <thomas@monjalon.net>
> >>>> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> >>>> 
> >>>> On Thu, Jun 06, 2019 at 09:44:52AM +0000, Jerin Jacob Kollanukkaran wrote:
> >>>>>> -----Original Message-----
> >>>>>> From: Neil Horman <nhorman@tuxdriver.com>
> >>>>>> Sent: Wednesday, June 5, 2019 11:41 PM
> >>>>>> To: Bruce Richardson <bruce.richardson@intel.com>
> >>>>>> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; dev@dpdk.org;
> >>>>>> Thomas Monjalon <thomas@monjalon.net>
> >>>>>> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> >>>>>> 
> >>>>>> On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson wrote:
> >>>>>>> On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob
> >>>>>>> Kollanukkaran
> >>>>>> wrote:
> >>>>>>>>> -----Original Message-----
> >>>>>>>>> From: Neil Horman <nhorman@tuxdriver.com>
> >>>>>>>>> Sent: Sunday, May 26, 2019 12:14 AM
> >>>>>>>>> To: dev@dpdk.org
> >>>>>>>>> Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob
> >>>>>>>>> Kollanukkaran <jerinj@marvell.com>; Bruce Richardson
> >>>>>>>>> <bruce.richardson@intel.com>; Thomas Monjalon
> >>>>>>>>> <thomas@monjalon.net>
> >>>>>>>>> Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> >>>>>>>>> 
> >>>>>>>>> Hey-
> >>>>>>>>> 	Based on our recent conversations regarding the use of
> >>>>>>>>> symbols only meant for internal dpdk consumption (between dpdk
> >>>>>>>>> libraries), this is an idea that I've come up with that I'd
> >>>>>>>>> like to get some feedback on
> >>>>>>>>> 
> >>>>>>>>> Summary:
> >>>>>>>>> 1) We have symbols in the DPDK that are meant to be used
> >>>>>>>>> between DPDK libraries, but not by applications linking to
> >>>>>>>>> them
> >>>>>>>>> 2) We would like to document those symbols in the code, so as
> >>>>>>>>> to note them clearly as for being meant for internal use only
> >>>>>>>>> 3) Linker symbol visibility is a very coarse grained tool, and
> >>>>>>>>> so there is no good way in a single library to mark items as
> >>>>>>>>> being meant for use only by other DPDK libraries, at least not
> >>>>>>>>> without some extensive runtime checking
> >>>>>>>>> 
> >>>>>>>>> 
> >>>>>>>>> Proposal:
> >>>>>>>>> I'm proposing that we introduce the __rte_internal tag.  From
> >>>>>>>>> a coding standpoint it works a great deal like the
> >>>>>>>>> __rte_experimental tag in that it expempts the tagged symbol
> >>>>>>>>> from ABI constraints (as the only users should be represented
> >>>>>>>>> in the DPDK build environment).  Additionally, the
> >>>>>>>>> __rte_internal macro resolves differently based on the
> >>>>>>>>> definition of the BUILDING_RTE_SDK flag (working under the
> >>>>>>>>> assumption that said flag should only ever be set if we are
> >>>>>>>>> actually building DPDK libraries which will make use of
> >>>>>>>>> internal calls).  If the BUILDING_RTE_SDK flag is set
> >>>>>>>>> __rte_internal resolves to __attribute__((section
> >>>>>>>>> "text.internal)), placing it in a special text section which
> >>>>>>>>> is then used to validate that the the symbol appears in the
> >>>>>>>>> INTERNAL section of the corresponding library version map).
> >>>>>>>>> If BUILDING_RTE_SDK is not set, then __rte_internal resolves
> >>>>>>>>> to
> >>>>>> __attribute__((error("..."))), which causes any caller of the tagged
> >>>>>> function to throw an error at compile time, indicating that the
> >>>>>> symbol is not available for external use.
> >>>>>>>>> 
> >>>>>>>>> This isn't a perfect solution, as applications can still hack
> >>>>>>>>> around it of course,
> >>>>>>>> 
> >>>>>>>> I think, one way to, avoid, hack around could be to,
> >>>>>>>> 
> >>>>>>>> 1) at config stage, create  a random number for the build
> >>>>>>>> 2) introduce RTE_CALL_INTERNAL macro for calling internal
> >>>>>>>> function, compare the generated random number for allowing the
> >>>>>>>> calls to make within the library. i.e leverage the fact that
> >>>>>>>> external library would never know the random number generated
> >>>>>>>> for the DPDK build
> >>>>>> and internal driver code does.
> >>>>>>>> 
> >>>>>>> Do we really need to care about this. If have some determined
> >>>>>>> enough to hack around our limitations, then they surely know that
> >>>>>>> they have an unsupported configuration. We just need to protect
> >>>>>>> against inadvertent use of internals, IMHO.
> >>>>>>> 
> >>>>>> I agree, I too had thought about doing some sort of internal runtime
> >>>>>> checking to match internal only symbols, such that they were only
> >>>>>> accessable by internally approved users, but it started to feel like a great
> >>>> deal of overhead.
> >>>>>> Its a good idea for a general mechanism I think, but I believe the
> >>>>>> value here is more to internally document which apis we want to mark
> >>>>>> as being for internal use only, and create a lightweight roadblock
> >>>>>> at build time to catch users inadvertently using them.  Determined
> >>>>>> users will get around anything, and theres not much we can do to stop
> >>>> them.
> >>>>> 
> >>>>> I agree too. IMHO, Simply having following items would be enough
> >>>>> 
> >>>>> 1) Avoid exposing the internal function prototype through public
> >>>>> header files
> >>>>> 2) Add @internal to API documentation
> >>>>> 3) Just decide the name space for internal API for tooling(i.e not
> >>>>> start with rte_ or so) Using objdump scheme to detect internal functions
> >>>> requires the the library to build prior to run the checkpatch.
> >>>>> 
> >>>> 
> >>>> No, I'm not comfortable with that approach, and I've stated why:
> >>>> 1) Not exposing the functions via header files is a fine start
> >>>> 
> >>>> 2) Adding internal documentation is also fine, but does nothing to correlate
> >>>> the code implementing those functions to the documentation.  Its valuable
> >>>> to have a tag on a function identifying it as internal only.
> >>>> 
> >>>> 3) Using naming conventions to separate internal only from non-internal
> >>>> functions is a vague approach, requiring future developers to be cogniscent
> >>>> of the convention and make the appropriate naming choices.  It also implicitly
> >>>> restricts the abliity for future developers to make naming changes in conflict
> >>>> with that convention
> >>> 
> >>> Enforcing the naming convention can be achieved through tooling as well.
> >>> 
> >>>> 
> >>>> 4) Adding a tag like __rte_internal creates an interlock whereby, not only are
> >>>> internal functions excused from ABI constraints, but forces developers to
> >>>> intentionally mark their internal functions as being internal in the code, which
> >>>> is beneficial to clarlity of understanding during the development process.
> >>> 
> >>> No issues in adding __rte_internal. But, I am against current implementaion, 
> >>> Ie. adding objdump dependency
> >>> to checkpatch i.e developer has to build the library first so  that checkpatch can
> >>> can know, Is it belongs to internal section or not?
> >>> 
> >>>> 
> >>>> 5) Adding a tag like __rte_internal is explicit, and allows developers to use a
> >>>> single header file instead of multiple header files if they so choose
> >>>> 
> >>>> We went through this with experimental symbols as well[1], and it just
> >>>> makes more sense to me to clearly document in the code what constitutes
> >>>> an internal symbol rather than relying on naming conventions and hoping
> >>>> that developers read the documentation before exporting a symbol
> >>>> publically.
> >> 
> >> I feel like we are creating a lot of extra work for the developer and adding a number of constraints to getting code patches submitted as the tools all have to be working together. The versioning file and __rte_experimental stuff today has always being handle wrong or not done by the developer. Altering the tools to detect these changes works and it seemed to take a while to iron out. To me we should be doing the minimum steps to reasonably isolate internal API and data from the user. If someone wants to access the those APIs that is their choice and enforcing with new macros and tools is over kill IMHO.
> >> 
> >> 1) Adding @internal to documentation is a great start along with more docs to explain what internal functions/data should be handled.
> > I've got no issue with this
> >> 2) Hiding/moving internal function prototypes in private headers.
> > Nor this, though if you want to do it, ensuring that every library has a private
> > header that doesn't get exported has to be part of the review process, and I'm
> > not confident that that will be a focus of anyones review
> > 
> >> 3) Adding setters/getters for internal data.
> > Sure, no issue here
> >> 4) Make sure we review and reject direct use of internal functions and data.
> > How exactly do you intend to enforce this?  By definition, the use of internal
> > functions is restricted only to dpdk core libraries, and those are the only
> > patches we ever see on the list.  This change is meant to enforce usage
> > prevention for users writing applications whos patches will never be seen for
> > review (save for our example programs)
> > 
> > We already have this mechanism available for experimental abi, and from my
> > perspective it works quite well, and is fairly well understood.  I don't see
> > whats wrong with expanding that mechanism to internal functions.
> 
> On this case I was talking more about accessing internal data directly instead of using getters/setters.
> 
Sure, we want to prevent that, but the linker version map should prevent it by
not exporting those globals already, meaning we're required to implement getters
and setters.  You can get around that of course by adding a global variable to
the linker map file, but thats strongly discouraged.

> I understand your other points, but if we use the items above it should solve most of the issues. Adding another tag and then adding tools to make it work is just going a bit too far. The reason that experimental works is normally the developer only has a few APIs to mark and it works along with versioning you added. The versioning and experimental parts are kind of a requirement with shared libs and identifying experimental APIs. In the case of marking all of the APIs as internal could be a huge list for all of the libs, we should move them to private headers instead.
We're not adding tools, we're modifying existing tools to make this work.  

If you're concerned about the added onus of tagging internal only functions, I
wouldn't be opposed to adding tooling to automatically document functions marked
with __rte_internal with @internal in the documentation tree, so that the
overhead is no larger than what we expect now (documenting @internal in the docs
directly)

As for the effort to tag functions as internal only, I think we might disagree
on what the size of the internal-only api is.  If we start with Jerins
assumption that all internal functions do not start with rte_, then a quick scan
of the version maps in the dpdk suggests there are currently 266 functions that
we would consider to be internal only.  Of those 266 a little less than half are
already addressed by the RFC patch I sent.  Getting the rest under tagged as
__rte_internal is about a days worth of work.  From there its just standard
maintenence.

Neil

> > 
> > Neil
> > 
> >> 
> >> The goal here is to handle the 80% rule and make it very obvious to the developer these are internal functions and data. Using these or similar minimum steps should be reasonable IMHO.
> >>>> 
> >>>> 
> >>>> [1] https://mails.dpdk.org/archives/dev/2017-December/083828.html
> >>>>>> 
> >>>>>> If we really wanted to go down that road, we could use a mechainsm
> >>>>>> simmilar to the EXPORT_SYMBOL / EXPORT_SYMBOL_GPL infrastructure
> >>>>>> that the kernel uses, but that would required building our own
> >>>>>> custom linker script, which seems like overkill here.
> >>>>>> 
> >>>>>> Best
> >>>>>> Neil
> >>>>>> 
> >>>>>>> /Bruce
> >> 
> >> Regards,
> >> Keith
> 
> Regards,
> Keith
> 
> 

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-06 13:35  0%             ` Neil Horman
@ 2019-06-06 14:02  0%               ` Jerin Jacob Kollanukkaran
  2019-06-06 15:03  3%                 ` Neil Horman
  0 siblings, 1 reply; 200+ results
From: Jerin Jacob Kollanukkaran @ 2019-06-06 14:02 UTC (permalink / raw)
  To: Neil Horman; +Cc: Bruce Richardson, dev, Thomas Monjalon

> -----Original Message-----
> From: Neil Horman <nhorman@tuxdriver.com>
> Sent: Thursday, June 6, 2019 7:05 PM
> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
> Thomas Monjalon <thomas@monjalon.net>
> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> 
> On Thu, Jun 06, 2019 at 12:04:57PM +0000, Jerin Jacob Kollanukkaran wrote:
> > > -----Original Message-----
> > > From: Neil Horman <nhorman@tuxdriver.com>
> > > Sent: Thursday, June 6, 2019 5:04 PM
> > > To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> > > Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
> > > Thomas Monjalon <thomas@monjalon.net>
> > > Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > >
> > > On Thu, Jun 06, 2019 at 09:44:52AM +0000, Jerin Jacob Kollanukkaran
> wrote:
> > > > > -----Original Message-----
> > > > > From: Neil Horman <nhorman@tuxdriver.com>
> > > > > Sent: Wednesday, June 5, 2019 11:41 PM
> > > > > To: Bruce Richardson <bruce.richardson@intel.com>
> > > > > Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
> > > > > dev@dpdk.org; Thomas Monjalon <thomas@monjalon.net>
> > > > > Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > > > >
> > > > > On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson wrote:
> > > > > > On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob
> > > > > > Kollanukkaran
> > > > > wrote:
> > > > > > > > -----Original Message-----
> > > > > > > > From: Neil Horman <nhorman@tuxdriver.com>
> > > > > > > > Sent: Sunday, May 26, 2019 12:14 AM
> > > > > > > > To: dev@dpdk.org
> > > > > > > > Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob
> > > > > > > > Kollanukkaran <jerinj@marvell.com>; Bruce Richardson
> > > > > > > > <bruce.richardson@intel.com>; Thomas Monjalon
> > > > > > > > <thomas@monjalon.net>
> > > > > > > > Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal
> > > > > > > > tag
> > > > > > > >
> > > > > > > > Hey-
> > > > > > > > 	Based on our recent conversations regarding the use of
> > > > > > > > symbols only meant for internal dpdk consumption (between
> > > > > > > > dpdk libraries), this is an idea that I've come up with
> > > > > > > > that I'd like to get some feedback on
> > > > > > > >
> > > > > > > > Summary:
> > > > > > > > 1) We have symbols in the DPDK that are meant to be used
> > > > > > > > between DPDK libraries, but not by applications linking to
> > > > > > > > them
> > > > > > > > 2) We would like to document those symbols in the code, so
> > > > > > > > as to note them clearly as for being meant for internal
> > > > > > > > use only
> > > > > > > > 3) Linker symbol visibility is a very coarse grained tool,
> > > > > > > > and so there is no good way in a single library to mark
> > > > > > > > items as being meant for use only by other DPDK libraries,
> > > > > > > > at least not without some extensive runtime checking
> > > > > > > >
> > > > > > > >
> > > > > > > > Proposal:
> > > > > > > > I'm proposing that we introduce the __rte_internal tag.
> > > > > > > > From a coding standpoint it works a great deal like the
> > > > > > > > __rte_experimental tag in that it expempts the tagged
> > > > > > > > symbol from ABI constraints (as the only users should be
> > > > > > > > represented in the DPDK build environment).  Additionally,
> > > > > > > > the __rte_internal macro resolves differently based on the
> > > > > > > > definition of the BUILDING_RTE_SDK flag (working under the
> > > > > > > > assumption that said flag should only ever be set if we
> > > > > > > > are actually building DPDK libraries which will make use
> > > > > > > > of internal calls).  If the BUILDING_RTE_SDK flag is set
> > > > > > > > __rte_internal resolves to __attribute__((section
> > > > > > > > "text.internal)), placing it in a special text section
> > > > > > > > which is then used to validate that the the symbol appears
> > > > > > > > in the INTERNAL section of the corresponding library version
> map).
> > > > > > > > If BUILDING_RTE_SDK is not set, then __rte_internal
> > > > > > > > resolves to
> > > > > __attribute__((error("..."))), which causes any caller of the
> > > > > tagged function to throw an error at compile time, indicating
> > > > > that the symbol is not available for external use.
> > > > > > > >
> > > > > > > > This isn't a perfect solution, as applications can still
> > > > > > > > hack around it of course,
> > > > > > >
> > > > > > > I think, one way to, avoid, hack around could be to,
> > > > > > >
> > > > > > > 1) at config stage, create  a random number for the build
> > > > > > > 2) introduce RTE_CALL_INTERNAL macro for calling internal
> > > > > > > function, compare the generated random number for allowing
> > > > > > > the calls to make within the library. i.e leverage the fact
> > > > > > > that external library would never know the random number
> > > > > > > generated for the DPDK build
> > > > > and internal driver code does.
> > > > > > >
> > > > > > Do we really need to care about this. If have some determined
> > > > > > enough to hack around our limitations, then they surely know
> > > > > > that they have an unsupported configuration. We just need to
> > > > > > protect against inadvertent use of internals, IMHO.
> > > > > >
> > > > > I agree, I too had thought about doing some sort of internal
> > > > > runtime checking to match internal only symbols, such that they
> > > > > were only accessable by internally approved users, but it
> > > > > started to feel like a great
> > > deal of overhead.
> > > > > Its a good idea for a general mechanism I think, but I believe
> > > > > the value here is more to internally document which apis we want
> > > > > to mark as being for internal use only, and create a lightweight
> > > > > roadblock at build time to catch users inadvertently using them.
> > > > > Determined users will get around anything, and theres not much
> > > > > we can do to stop
> > > them.
> > > >
> > > > I agree too. IMHO, Simply having following items would be enough
> > > >
> > > > 1) Avoid exposing the internal function prototype through public
> > > > header files
> > > > 2) Add @internal to API documentation
> > > > 3) Just decide the name space for internal API for tooling(i.e not
> > > > start with rte_ or so) Using objdump scheme to detect internal
> > > > functions
> > > requires the the library to build prior to run the checkpatch.
> > > >
> > >
> > > No, I'm not comfortable with that approach, and I've stated why:
> > > 1) Not exposing the functions via header files is a fine start
> > >
> > > 2) Adding internal documentation is also fine, but does nothing to
> > > correlate the code implementing those functions to the
> > > documentation.  Its valuable to have a tag on a function identifying it as
> internal only.
> > >
> > > 3) Using naming conventions to separate internal only from
> > > non-internal functions is a vague approach, requiring future
> > > developers to be cogniscent of the convention and make the
> > > appropriate naming choices.  It also implicitly restricts the
> > > abliity for future developers to make naming changes in conflict
> > > with that convention
> >
> > Enforcing the naming convention can be achieved through tooling as well.
> >
> Sure, but why enforce any function naming at all, when you don't have to.

May I ask,  why to  enforce __rte_internal, when you don't have to

> 
> > >
> > > 4) Adding a tag like __rte_internal creates an interlock whereby,
> > > not only are internal functions excused from ABI constraints, but
> > > forces developers to intentionally mark their internal functions as
> > > being internal in the code, which is beneficial to clarlity of understanding
> during the development process.
> >
> > No issues in adding __rte_internal. But, I am against current
> > implementaion, Ie. adding objdump dependency
> That dependency already exists for the __rte_external flag

Sorry, I could not see the dependency.

[master][dpdk.org] $ grep -ri "objdump" devtools/
[master][dpdk.org] $ grep -ri "objdump" usertools/
[master][dpdk.org] $ grep -ri "__rte_external" *

> 
> > to checkpatch i.e developer has to build the library first so  that
> > checkpatch can can know, Is it belongs to internal section or not?
> >
> What developer is running checkpatch/posting patches without first building
> their changes?

# it is not developer, The CI/CD tools can quicky check the sanity of patches
before the build itself. Why to add unnecessary dependency?
# If some PMD is not building if the requirements are not meet(say AES NI PMD for crypto)
then how do take care of the dependency.


> 
> 
> > >
> > > 5) Adding a tag like __rte_internal is explicit, and allows
> > > developers to use a single header file instead of multiple header
> > > files if they so choose
> > >
> > > We went through this with experimental symbols as well[1], and it
> > > just makes more sense to me to clearly document in the code what
> > > constitutes an internal symbol rather than relying on naming
> > > conventions and hoping that developers read the documentation before
> > > exporting a symbol publically.
> > >
> > >
> > > [1] https://mails.dpdk.org/archives/dev/2017-December/083828.html
> > > > >
> > > > > If we really wanted to go down that road, we could use a
> > > > > mechainsm simmilar to the EXPORT_SYMBOL / EXPORT_SYMBOL_GPL
> > > > > infrastructure that the kernel uses, but that would required
> > > > > building our own custom linker script, which seems like overkill here.
> > > > >
> > > > > Best
> > > > > Neil
> > > > >
> > > > > > /Bruce
> > > > > >
> > > >
> >

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-06 13:43  3%               ` Neil Horman
@ 2019-06-06 13:53  0%                 ` Wiles, Keith
  2019-06-06 14:46  0%                   ` Neil Horman
  0 siblings, 1 reply; 200+ results
From: Wiles, Keith @ 2019-06-06 13:53 UTC (permalink / raw)
  To: Neil Horman
  Cc: Jerin Jacob Kollanukkaran, Richardson, Bruce, dev, Thomas Monjalon



> On Jun 6, 2019, at 8:43 AM, Neil Horman <nhorman@tuxdriver.com> wrote:
> 
> On Thu, Jun 06, 2019 at 01:18:29PM +0000, Wiles, Keith wrote:
>> 
>> 
>>> On Jun 6, 2019, at 7:04 AM, Jerin Jacob Kollanukkaran <jerinj@marvell.com> wrote:
>>> 
>>>> -----Original Message-----
>>>> From: Neil Horman <nhorman@tuxdriver.com>
>>>> Sent: Thursday, June 6, 2019 5:04 PM
>>>> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
>>>> Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
>>>> Thomas Monjalon <thomas@monjalon.net>
>>>> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
>>>> 
>>>> On Thu, Jun 06, 2019 at 09:44:52AM +0000, Jerin Jacob Kollanukkaran wrote:
>>>>>> -----Original Message-----
>>>>>> From: Neil Horman <nhorman@tuxdriver.com>
>>>>>> Sent: Wednesday, June 5, 2019 11:41 PM
>>>>>> To: Bruce Richardson <bruce.richardson@intel.com>
>>>>>> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; dev@dpdk.org;
>>>>>> Thomas Monjalon <thomas@monjalon.net>
>>>>>> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
>>>>>> 
>>>>>> On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson wrote:
>>>>>>> On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob
>>>>>>> Kollanukkaran
>>>>>> wrote:
>>>>>>>>> -----Original Message-----
>>>>>>>>> From: Neil Horman <nhorman@tuxdriver.com>
>>>>>>>>> Sent: Sunday, May 26, 2019 12:14 AM
>>>>>>>>> To: dev@dpdk.org
>>>>>>>>> Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob
>>>>>>>>> Kollanukkaran <jerinj@marvell.com>; Bruce Richardson
>>>>>>>>> <bruce.richardson@intel.com>; Thomas Monjalon
>>>>>>>>> <thomas@monjalon.net>
>>>>>>>>> Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
>>>>>>>>> 
>>>>>>>>> Hey-
>>>>>>>>> 	Based on our recent conversations regarding the use of
>>>>>>>>> symbols only meant for internal dpdk consumption (between dpdk
>>>>>>>>> libraries), this is an idea that I've come up with that I'd
>>>>>>>>> like to get some feedback on
>>>>>>>>> 
>>>>>>>>> Summary:
>>>>>>>>> 1) We have symbols in the DPDK that are meant to be used
>>>>>>>>> between DPDK libraries, but not by applications linking to
>>>>>>>>> them
>>>>>>>>> 2) We would like to document those symbols in the code, so as
>>>>>>>>> to note them clearly as for being meant for internal use only
>>>>>>>>> 3) Linker symbol visibility is a very coarse grained tool, and
>>>>>>>>> so there is no good way in a single library to mark items as
>>>>>>>>> being meant for use only by other DPDK libraries, at least not
>>>>>>>>> without some extensive runtime checking
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> Proposal:
>>>>>>>>> I'm proposing that we introduce the __rte_internal tag.  From
>>>>>>>>> a coding standpoint it works a great deal like the
>>>>>>>>> __rte_experimental tag in that it expempts the tagged symbol
>>>>>>>>> from ABI constraints (as the only users should be represented
>>>>>>>>> in the DPDK build environment).  Additionally, the
>>>>>>>>> __rte_internal macro resolves differently based on the
>>>>>>>>> definition of the BUILDING_RTE_SDK flag (working under the
>>>>>>>>> assumption that said flag should only ever be set if we are
>>>>>>>>> actually building DPDK libraries which will make use of
>>>>>>>>> internal calls).  If the BUILDING_RTE_SDK flag is set
>>>>>>>>> __rte_internal resolves to __attribute__((section
>>>>>>>>> "text.internal)), placing it in a special text section which
>>>>>>>>> is then used to validate that the the symbol appears in the
>>>>>>>>> INTERNAL section of the corresponding library version map).
>>>>>>>>> If BUILDING_RTE_SDK is not set, then __rte_internal resolves
>>>>>>>>> to
>>>>>> __attribute__((error("..."))), which causes any caller of the tagged
>>>>>> function to throw an error at compile time, indicating that the
>>>>>> symbol is not available for external use.
>>>>>>>>> 
>>>>>>>>> This isn't a perfect solution, as applications can still hack
>>>>>>>>> around it of course,
>>>>>>>> 
>>>>>>>> I think, one way to, avoid, hack around could be to,
>>>>>>>> 
>>>>>>>> 1) at config stage, create  a random number for the build
>>>>>>>> 2) introduce RTE_CALL_INTERNAL macro for calling internal
>>>>>>>> function, compare the generated random number for allowing the
>>>>>>>> calls to make within the library. i.e leverage the fact that
>>>>>>>> external library would never know the random number generated
>>>>>>>> for the DPDK build
>>>>>> and internal driver code does.
>>>>>>>> 
>>>>>>> Do we really need to care about this. If have some determined
>>>>>>> enough to hack around our limitations, then they surely know that
>>>>>>> they have an unsupported configuration. We just need to protect
>>>>>>> against inadvertent use of internals, IMHO.
>>>>>>> 
>>>>>> I agree, I too had thought about doing some sort of internal runtime
>>>>>> checking to match internal only symbols, such that they were only
>>>>>> accessable by internally approved users, but it started to feel like a great
>>>> deal of overhead.
>>>>>> Its a good idea for a general mechanism I think, but I believe the
>>>>>> value here is more to internally document which apis we want to mark
>>>>>> as being for internal use only, and create a lightweight roadblock
>>>>>> at build time to catch users inadvertently using them.  Determined
>>>>>> users will get around anything, and theres not much we can do to stop
>>>> them.
>>>>> 
>>>>> I agree too. IMHO, Simply having following items would be enough
>>>>> 
>>>>> 1) Avoid exposing the internal function prototype through public
>>>>> header files
>>>>> 2) Add @internal to API documentation
>>>>> 3) Just decide the name space for internal API for tooling(i.e not
>>>>> start with rte_ or so) Using objdump scheme to detect internal functions
>>>> requires the the library to build prior to run the checkpatch.
>>>>> 
>>>> 
>>>> No, I'm not comfortable with that approach, and I've stated why:
>>>> 1) Not exposing the functions via header files is a fine start
>>>> 
>>>> 2) Adding internal documentation is also fine, but does nothing to correlate
>>>> the code implementing those functions to the documentation.  Its valuable
>>>> to have a tag on a function identifying it as internal only.
>>>> 
>>>> 3) Using naming conventions to separate internal only from non-internal
>>>> functions is a vague approach, requiring future developers to be cogniscent
>>>> of the convention and make the appropriate naming choices.  It also implicitly
>>>> restricts the abliity for future developers to make naming changes in conflict
>>>> with that convention
>>> 
>>> Enforcing the naming convention can be achieved through tooling as well.
>>> 
>>>> 
>>>> 4) Adding a tag like __rte_internal creates an interlock whereby, not only are
>>>> internal functions excused from ABI constraints, but forces developers to
>>>> intentionally mark their internal functions as being internal in the code, which
>>>> is beneficial to clarlity of understanding during the development process.
>>> 
>>> No issues in adding __rte_internal. But, I am against current implementaion, 
>>> Ie. adding objdump dependency
>>> to checkpatch i.e developer has to build the library first so  that checkpatch can
>>> can know, Is it belongs to internal section or not?
>>> 
>>>> 
>>>> 5) Adding a tag like __rte_internal is explicit, and allows developers to use a
>>>> single header file instead of multiple header files if they so choose
>>>> 
>>>> We went through this with experimental symbols as well[1], and it just
>>>> makes more sense to me to clearly document in the code what constitutes
>>>> an internal symbol rather than relying on naming conventions and hoping
>>>> that developers read the documentation before exporting a symbol
>>>> publically.
>> 
>> I feel like we are creating a lot of extra work for the developer and adding a number of constraints to getting code patches submitted as the tools all have to be working together. The versioning file and __rte_experimental stuff today has always being handle wrong or not done by the developer. Altering the tools to detect these changes works and it seemed to take a while to iron out. To me we should be doing the minimum steps to reasonably isolate internal API and data from the user. If someone wants to access the those APIs that is their choice and enforcing with new macros and tools is over kill IMHO.
>> 
>> 1) Adding @internal to documentation is a great start along with more docs to explain what internal functions/data should be handled.
> I've got no issue with this
>> 2) Hiding/moving internal function prototypes in private headers.
> Nor this, though if you want to do it, ensuring that every library has a private
> header that doesn't get exported has to be part of the review process, and I'm
> not confident that that will be a focus of anyones review
> 
>> 3) Adding setters/getters for internal data.
> Sure, no issue here
>> 4) Make sure we review and reject direct use of internal functions and data.
> How exactly do you intend to enforce this?  By definition, the use of internal
> functions is restricted only to dpdk core libraries, and those are the only
> patches we ever see on the list.  This change is meant to enforce usage
> prevention for users writing applications whos patches will never be seen for
> review (save for our example programs)
> 
> We already have this mechanism available for experimental abi, and from my
> perspective it works quite well, and is fairly well understood.  I don't see
> whats wrong with expanding that mechanism to internal functions.

On this case I was talking more about accessing internal data directly instead of using getters/setters.

I understand your other points, but if we use the items above it should solve most of the issues. Adding another tag and then adding tools to make it work is just going a bit too far. The reason that experimental works is normally the developer only has a few APIs to mark and it works along with versioning you added. The versioning and experimental parts are kind of a requirement with shared libs and identifying experimental APIs. In the case of marking all of the APIs as internal could be a huge list for all of the libs, we should move them to private headers instead.
> 
> Neil
> 
>> 
>> The goal here is to handle the 80% rule and make it very obvious to the developer these are internal functions and data. Using these or similar minimum steps should be reasonable IMHO.
>>>> 
>>>> 
>>>> [1] https://mails.dpdk.org/archives/dev/2017-December/083828.html
>>>>>> 
>>>>>> If we really wanted to go down that road, we could use a mechainsm
>>>>>> simmilar to the EXPORT_SYMBOL / EXPORT_SYMBOL_GPL infrastructure
>>>>>> that the kernel uses, but that would required building our own
>>>>>> custom linker script, which seems like overkill here.
>>>>>> 
>>>>>> Best
>>>>>> Neil
>>>>>> 
>>>>>>> /Bruce
>> 
>> Regards,
>> Keith

Regards,
Keith


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-06 13:18  0%             ` Wiles, Keith
@ 2019-06-06 13:43  3%               ` Neil Horman
  2019-06-06 13:53  0%                 ` Wiles, Keith
  0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2019-06-06 13:43 UTC (permalink / raw)
  To: Wiles, Keith
  Cc: Jerin Jacob Kollanukkaran, Richardson, Bruce, dev, Thomas Monjalon

On Thu, Jun 06, 2019 at 01:18:29PM +0000, Wiles, Keith wrote:
> 
> 
> > On Jun 6, 2019, at 7:04 AM, Jerin Jacob Kollanukkaran <jerinj@marvell.com> wrote:
> > 
> >> -----Original Message-----
> >> From: Neil Horman <nhorman@tuxdriver.com>
> >> Sent: Thursday, June 6, 2019 5:04 PM
> >> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> >> Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
> >> Thomas Monjalon <thomas@monjalon.net>
> >> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> >> 
> >> On Thu, Jun 06, 2019 at 09:44:52AM +0000, Jerin Jacob Kollanukkaran wrote:
> >>>> -----Original Message-----
> >>>> From: Neil Horman <nhorman@tuxdriver.com>
> >>>> Sent: Wednesday, June 5, 2019 11:41 PM
> >>>> To: Bruce Richardson <bruce.richardson@intel.com>
> >>>> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; dev@dpdk.org;
> >>>> Thomas Monjalon <thomas@monjalon.net>
> >>>> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> >>>> 
> >>>> On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson wrote:
> >>>>> On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob
> >>>>> Kollanukkaran
> >>>> wrote:
> >>>>>>> -----Original Message-----
> >>>>>>> From: Neil Horman <nhorman@tuxdriver.com>
> >>>>>>> Sent: Sunday, May 26, 2019 12:14 AM
> >>>>>>> To: dev@dpdk.org
> >>>>>>> Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob
> >>>>>>> Kollanukkaran <jerinj@marvell.com>; Bruce Richardson
> >>>>>>> <bruce.richardson@intel.com>; Thomas Monjalon
> >>>>>>> <thomas@monjalon.net>
> >>>>>>> Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> >>>>>>> 
> >>>>>>> Hey-
> >>>>>>> 	Based on our recent conversations regarding the use of
> >>>>>>> symbols only meant for internal dpdk consumption (between dpdk
> >>>>>>> libraries), this is an idea that I've come up with that I'd
> >>>>>>> like to get some feedback on
> >>>>>>> 
> >>>>>>> Summary:
> >>>>>>> 1) We have symbols in the DPDK that are meant to be used
> >>>>>>> between DPDK libraries, but not by applications linking to
> >>>>>>> them
> >>>>>>> 2) We would like to document those symbols in the code, so as
> >>>>>>> to note them clearly as for being meant for internal use only
> >>>>>>> 3) Linker symbol visibility is a very coarse grained tool, and
> >>>>>>> so there is no good way in a single library to mark items as
> >>>>>>> being meant for use only by other DPDK libraries, at least not
> >>>>>>> without some extensive runtime checking
> >>>>>>> 
> >>>>>>> 
> >>>>>>> Proposal:
> >>>>>>> I'm proposing that we introduce the __rte_internal tag.  From
> >>>>>>> a coding standpoint it works a great deal like the
> >>>>>>> __rte_experimental tag in that it expempts the tagged symbol
> >>>>>>> from ABI constraints (as the only users should be represented
> >>>>>>> in the DPDK build environment).  Additionally, the
> >>>>>>> __rte_internal macro resolves differently based on the
> >>>>>>> definition of the BUILDING_RTE_SDK flag (working under the
> >>>>>>> assumption that said flag should only ever be set if we are
> >>>>>>> actually building DPDK libraries which will make use of
> >>>>>>> internal calls).  If the BUILDING_RTE_SDK flag is set
> >>>>>>> __rte_internal resolves to __attribute__((section
> >>>>>>> "text.internal)), placing it in a special text section which
> >>>>>>> is then used to validate that the the symbol appears in the
> >>>>>>> INTERNAL section of the corresponding library version map).
> >>>>>>> If BUILDING_RTE_SDK is not set, then __rte_internal resolves
> >>>>>>> to
> >>>> __attribute__((error("..."))), which causes any caller of the tagged
> >>>> function to throw an error at compile time, indicating that the
> >>>> symbol is not available for external use.
> >>>>>>> 
> >>>>>>> This isn't a perfect solution, as applications can still hack
> >>>>>>> around it of course,
> >>>>>> 
> >>>>>> I think, one way to, avoid, hack around could be to,
> >>>>>> 
> >>>>>> 1) at config stage, create  a random number for the build
> >>>>>> 2) introduce RTE_CALL_INTERNAL macro for calling internal
> >>>>>> function, compare the generated random number for allowing the
> >>>>>> calls to make within the library. i.e leverage the fact that
> >>>>>> external library would never know the random number generated
> >>>>>> for the DPDK build
> >>>> and internal driver code does.
> >>>>>> 
> >>>>> Do we really need to care about this. If have some determined
> >>>>> enough to hack around our limitations, then they surely know that
> >>>>> they have an unsupported configuration. We just need to protect
> >>>>> against inadvertent use of internals, IMHO.
> >>>>> 
> >>>> I agree, I too had thought about doing some sort of internal runtime
> >>>> checking to match internal only symbols, such that they were only
> >>>> accessable by internally approved users, but it started to feel like a great
> >> deal of overhead.
> >>>> Its a good idea for a general mechanism I think, but I believe the
> >>>> value here is more to internally document which apis we want to mark
> >>>> as being for internal use only, and create a lightweight roadblock
> >>>> at build time to catch users inadvertently using them.  Determined
> >>>> users will get around anything, and theres not much we can do to stop
> >> them.
> >>> 
> >>> I agree too. IMHO, Simply having following items would be enough
> >>> 
> >>> 1) Avoid exposing the internal function prototype through public
> >>> header files
> >>> 2) Add @internal to API documentation
> >>> 3) Just decide the name space for internal API for tooling(i.e not
> >>> start with rte_ or so) Using objdump scheme to detect internal functions
> >> requires the the library to build prior to run the checkpatch.
> >>> 
> >> 
> >> No, I'm not comfortable with that approach, and I've stated why:
> >> 1) Not exposing the functions via header files is a fine start
> >> 
> >> 2) Adding internal documentation is also fine, but does nothing to correlate
> >> the code implementing those functions to the documentation.  Its valuable
> >> to have a tag on a function identifying it as internal only.
> >> 
> >> 3) Using naming conventions to separate internal only from non-internal
> >> functions is a vague approach, requiring future developers to be cogniscent
> >> of the convention and make the appropriate naming choices.  It also implicitly
> >> restricts the abliity for future developers to make naming changes in conflict
> >> with that convention
> > 
> > Enforcing the naming convention can be achieved through tooling as well.
> > 
> >> 
> >> 4) Adding a tag like __rte_internal creates an interlock whereby, not only are
> >> internal functions excused from ABI constraints, but forces developers to
> >> intentionally mark their internal functions as being internal in the code, which
> >> is beneficial to clarlity of understanding during the development process.
> > 
> > No issues in adding __rte_internal. But, I am against current implementaion, 
> > Ie. adding objdump dependency
> > to checkpatch i.e developer has to build the library first so  that checkpatch can
> > can know, Is it belongs to internal section or not?
> > 
> >> 
> >> 5) Adding a tag like __rte_internal is explicit, and allows developers to use a
> >> single header file instead of multiple header files if they so choose
> >> 
> >> We went through this with experimental symbols as well[1], and it just
> >> makes more sense to me to clearly document in the code what constitutes
> >> an internal symbol rather than relying on naming conventions and hoping
> >> that developers read the documentation before exporting a symbol
> >> publically.
> 
> I feel like we are creating a lot of extra work for the developer and adding a number of constraints to getting code patches submitted as the tools all have to be working together. The versioning file and __rte_experimental stuff today has always being handle wrong or not done by the developer. Altering the tools to detect these changes works and it seemed to take a while to iron out. To me we should be doing the minimum steps to reasonably isolate internal API and data from the user. If someone wants to access the those APIs that is their choice and enforcing with new macros and tools is over kill IMHO.
> 
> 1) Adding @internal to documentation is a great start along with more docs to explain what internal functions/data should be handled.
I've got no issue with this
> 2) Hiding/moving internal function prototypes in private headers.
Nor this, though if you want to do it, ensuring that every library has a private
header that doesn't get exported has to be part of the review process, and I'm
not confident that that will be a focus of anyones review

> 3) Adding setters/getters for internal data.
Sure, no issue here
> 4) Make sure we review and reject direct use of internal functions and data.
How exactly do you intend to enforce this?  By definition, the use of internal
functions is restricted only to dpdk core libraries, and those are the only
patches we ever see on the list.  This change is meant to enforce usage
prevention for users writing applications whos patches will never be seen for
review (save for our example programs)

We already have this mechanism available for experimental abi, and from my
perspective it works quite well, and is fairly well understood.  I don't see
whats wrong with expanding that mechanism to internal functions.

Neil

> 
> The goal here is to handle the 80% rule and make it very obvious to the developer these are internal functions and data. Using these or similar minimum steps should be reasonable IMHO.
> >> 
> >> 
> >> [1] https://mails.dpdk.org/archives/dev/2017-December/083828.html
> >>>> 
> >>>> If we really wanted to go down that road, we could use a mechainsm
> >>>> simmilar to the EXPORT_SYMBOL / EXPORT_SYMBOL_GPL infrastructure
> >>>> that the kernel uses, but that would required building our own
> >>>> custom linker script, which seems like overkill here.
> >>>> 
> >>>> Best
> >>>> Neil
> >>>> 
> >>>>> /Bruce
> 
> Regards,
> Keith
> 
> 

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-06 12:04  0%           ` Jerin Jacob Kollanukkaran
  2019-06-06 13:18  0%             ` Wiles, Keith
@ 2019-06-06 13:35  0%             ` Neil Horman
  2019-06-06 14:02  0%               ` Jerin Jacob Kollanukkaran
  1 sibling, 1 reply; 200+ results
From: Neil Horman @ 2019-06-06 13:35 UTC (permalink / raw)
  To: Jerin Jacob Kollanukkaran; +Cc: Bruce Richardson, dev, Thomas Monjalon

On Thu, Jun 06, 2019 at 12:04:57PM +0000, Jerin Jacob Kollanukkaran wrote:
> > -----Original Message-----
> > From: Neil Horman <nhorman@tuxdriver.com>
> > Sent: Thursday, June 6, 2019 5:04 PM
> > To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> > Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
> > Thomas Monjalon <thomas@monjalon.net>
> > Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > 
> > On Thu, Jun 06, 2019 at 09:44:52AM +0000, Jerin Jacob Kollanukkaran wrote:
> > > > -----Original Message-----
> > > > From: Neil Horman <nhorman@tuxdriver.com>
> > > > Sent: Wednesday, June 5, 2019 11:41 PM
> > > > To: Bruce Richardson <bruce.richardson@intel.com>
> > > > Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; dev@dpdk.org;
> > > > Thomas Monjalon <thomas@monjalon.net>
> > > > Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > > >
> > > > On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson wrote:
> > > > > On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob
> > > > > Kollanukkaran
> > > > wrote:
> > > > > > > -----Original Message-----
> > > > > > > From: Neil Horman <nhorman@tuxdriver.com>
> > > > > > > Sent: Sunday, May 26, 2019 12:14 AM
> > > > > > > To: dev@dpdk.org
> > > > > > > Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob
> > > > > > > Kollanukkaran <jerinj@marvell.com>; Bruce Richardson
> > > > > > > <bruce.richardson@intel.com>; Thomas Monjalon
> > > > > > > <thomas@monjalon.net>
> > > > > > > Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > > > > > >
> > > > > > > Hey-
> > > > > > > 	Based on our recent conversations regarding the use of
> > > > > > > symbols only meant for internal dpdk consumption (between dpdk
> > > > > > > libraries), this is an idea that I've come up with that I'd
> > > > > > > like to get some feedback on
> > > > > > >
> > > > > > > Summary:
> > > > > > > 1) We have symbols in the DPDK that are meant to be used
> > > > > > > between DPDK libraries, but not by applications linking to
> > > > > > > them
> > > > > > > 2) We would like to document those symbols in the code, so as
> > > > > > > to note them clearly as for being meant for internal use only
> > > > > > > 3) Linker symbol visibility is a very coarse grained tool, and
> > > > > > > so there is no good way in a single library to mark items as
> > > > > > > being meant for use only by other DPDK libraries, at least not
> > > > > > > without some extensive runtime checking
> > > > > > >
> > > > > > >
> > > > > > > Proposal:
> > > > > > > I'm proposing that we introduce the __rte_internal tag.  From
> > > > > > > a coding standpoint it works a great deal like the
> > > > > > > __rte_experimental tag in that it expempts the tagged symbol
> > > > > > > from ABI constraints (as the only users should be represented
> > > > > > > in the DPDK build environment).  Additionally, the
> > > > > > > __rte_internal macro resolves differently based on the
> > > > > > > definition of the BUILDING_RTE_SDK flag (working under the
> > > > > > > assumption that said flag should only ever be set if we are
> > > > > > > actually building DPDK libraries which will make use of
> > > > > > > internal calls).  If the BUILDING_RTE_SDK flag is set
> > > > > > > __rte_internal resolves to __attribute__((section
> > > > > > > "text.internal)), placing it in a special text section which
> > > > > > > is then used to validate that the the symbol appears in the
> > > > > > > INTERNAL section of the corresponding library version map).
> > > > > > > If BUILDING_RTE_SDK is not set, then __rte_internal resolves
> > > > > > > to
> > > > __attribute__((error("..."))), which causes any caller of the tagged
> > > > function to throw an error at compile time, indicating that the
> > > > symbol is not available for external use.
> > > > > > >
> > > > > > > This isn't a perfect solution, as applications can still hack
> > > > > > > around it of course,
> > > > > >
> > > > > > I think, one way to, avoid, hack around could be to,
> > > > > >
> > > > > > 1) at config stage, create  a random number for the build
> > > > > > 2) introduce RTE_CALL_INTERNAL macro for calling internal
> > > > > > function, compare the generated random number for allowing the
> > > > > > calls to make within the library. i.e leverage the fact that
> > > > > > external library would never know the random number generated
> > > > > > for the DPDK build
> > > > and internal driver code does.
> > > > > >
> > > > > Do we really need to care about this. If have some determined
> > > > > enough to hack around our limitations, then they surely know that
> > > > > they have an unsupported configuration. We just need to protect
> > > > > against inadvertent use of internals, IMHO.
> > > > >
> > > > I agree, I too had thought about doing some sort of internal runtime
> > > > checking to match internal only symbols, such that they were only
> > > > accessable by internally approved users, but it started to feel like a great
> > deal of overhead.
> > > > Its a good idea for a general mechanism I think, but I believe the
> > > > value here is more to internally document which apis we want to mark
> > > > as being for internal use only, and create a lightweight roadblock
> > > > at build time to catch users inadvertently using them.  Determined
> > > > users will get around anything, and theres not much we can do to stop
> > them.
> > >
> > > I agree too. IMHO, Simply having following items would be enough
> > >
> > > 1) Avoid exposing the internal function prototype through public
> > > header files
> > > 2) Add @internal to API documentation
> > > 3) Just decide the name space for internal API for tooling(i.e not
> > > start with rte_ or so) Using objdump scheme to detect internal functions
> > requires the the library to build prior to run the checkpatch.
> > >
> > 
> > No, I'm not comfortable with that approach, and I've stated why:
> > 1) Not exposing the functions via header files is a fine start
> > 
> > 2) Adding internal documentation is also fine, but does nothing to correlate
> > the code implementing those functions to the documentation.  Its valuable
> > to have a tag on a function identifying it as internal only.
> > 
> > 3) Using naming conventions to separate internal only from non-internal
> > functions is a vague approach, requiring future developers to be cogniscent
> > of the convention and make the appropriate naming choices.  It also implicitly
> > restricts the abliity for future developers to make naming changes in conflict
> > with that convention
> 
> Enforcing the naming convention can be achieved through tooling as well.
> 
Sure, but why enforce any function naming at all, when you don't have to.

> > 
> > 4) Adding a tag like __rte_internal creates an interlock whereby, not only are
> > internal functions excused from ABI constraints, but forces developers to
> > intentionally mark their internal functions as being internal in the code, which
> > is beneficial to clarlity of understanding during the development process.
> 
> No issues in adding __rte_internal. But, I am against current implementaion, 
> Ie. adding objdump dependency
That dependency already exists for the __rte_external flag

> to checkpatch i.e developer has to build the library first so  that checkpatch can
> can know, Is it belongs to internal section or not?
> 
What developer is running checkpatch/posting patches without first building
their changes?


> > 
> > 5) Adding a tag like __rte_internal is explicit, and allows developers to use a
> > single header file instead of multiple header files if they so choose
> > 
> > We went through this with experimental symbols as well[1], and it just
> > makes more sense to me to clearly document in the code what constitutes
> > an internal symbol rather than relying on naming conventions and hoping
> > that developers read the documentation before exporting a symbol
> > publically.
> > 
> > 
> > [1] https://mails.dpdk.org/archives/dev/2017-December/083828.html
> > > >
> > > > If we really wanted to go down that road, we could use a mechainsm
> > > > simmilar to the EXPORT_SYMBOL / EXPORT_SYMBOL_GPL infrastructure
> > > > that the kernel uses, but that would required building our own
> > > > custom linker script, which seems like overkill here.
> > > >
> > > > Best
> > > > Neil
> > > >
> > > > > /Bruce
> > > > >
> > >
> 

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-06 12:04  0%           ` Jerin Jacob Kollanukkaran
@ 2019-06-06 13:18  0%             ` Wiles, Keith
  2019-06-06 13:43  3%               ` Neil Horman
  2019-06-06 13:35  0%             ` Neil Horman
  1 sibling, 1 reply; 200+ results
From: Wiles, Keith @ 2019-06-06 13:18 UTC (permalink / raw)
  To: Jerin Jacob Kollanukkaran
  Cc: Neil Horman, Richardson, Bruce, dev, Thomas Monjalon



> On Jun 6, 2019, at 7:04 AM, Jerin Jacob Kollanukkaran <jerinj@marvell.com> wrote:
> 
>> -----Original Message-----
>> From: Neil Horman <nhorman@tuxdriver.com>
>> Sent: Thursday, June 6, 2019 5:04 PM
>> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
>> Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
>> Thomas Monjalon <thomas@monjalon.net>
>> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
>> 
>> On Thu, Jun 06, 2019 at 09:44:52AM +0000, Jerin Jacob Kollanukkaran wrote:
>>>> -----Original Message-----
>>>> From: Neil Horman <nhorman@tuxdriver.com>
>>>> Sent: Wednesday, June 5, 2019 11:41 PM
>>>> To: Bruce Richardson <bruce.richardson@intel.com>
>>>> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; dev@dpdk.org;
>>>> Thomas Monjalon <thomas@monjalon.net>
>>>> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
>>>> 
>>>> On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson wrote:
>>>>> On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob
>>>>> Kollanukkaran
>>>> wrote:
>>>>>>> -----Original Message-----
>>>>>>> From: Neil Horman <nhorman@tuxdriver.com>
>>>>>>> Sent: Sunday, May 26, 2019 12:14 AM
>>>>>>> To: dev@dpdk.org
>>>>>>> Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob
>>>>>>> Kollanukkaran <jerinj@marvell.com>; Bruce Richardson
>>>>>>> <bruce.richardson@intel.com>; Thomas Monjalon
>>>>>>> <thomas@monjalon.net>
>>>>>>> Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
>>>>>>> 
>>>>>>> Hey-
>>>>>>> 	Based on our recent conversations regarding the use of
>>>>>>> symbols only meant for internal dpdk consumption (between dpdk
>>>>>>> libraries), this is an idea that I've come up with that I'd
>>>>>>> like to get some feedback on
>>>>>>> 
>>>>>>> Summary:
>>>>>>> 1) We have symbols in the DPDK that are meant to be used
>>>>>>> between DPDK libraries, but not by applications linking to
>>>>>>> them
>>>>>>> 2) We would like to document those symbols in the code, so as
>>>>>>> to note them clearly as for being meant for internal use only
>>>>>>> 3) Linker symbol visibility is a very coarse grained tool, and
>>>>>>> so there is no good way in a single library to mark items as
>>>>>>> being meant for use only by other DPDK libraries, at least not
>>>>>>> without some extensive runtime checking
>>>>>>> 
>>>>>>> 
>>>>>>> Proposal:
>>>>>>> I'm proposing that we introduce the __rte_internal tag.  From
>>>>>>> a coding standpoint it works a great deal like the
>>>>>>> __rte_experimental tag in that it expempts the tagged symbol
>>>>>>> from ABI constraints (as the only users should be represented
>>>>>>> in the DPDK build environment).  Additionally, the
>>>>>>> __rte_internal macro resolves differently based on the
>>>>>>> definition of the BUILDING_RTE_SDK flag (working under the
>>>>>>> assumption that said flag should only ever be set if we are
>>>>>>> actually building DPDK libraries which will make use of
>>>>>>> internal calls).  If the BUILDING_RTE_SDK flag is set
>>>>>>> __rte_internal resolves to __attribute__((section
>>>>>>> "text.internal)), placing it in a special text section which
>>>>>>> is then used to validate that the the symbol appears in the
>>>>>>> INTERNAL section of the corresponding library version map).
>>>>>>> If BUILDING_RTE_SDK is not set, then __rte_internal resolves
>>>>>>> to
>>>> __attribute__((error("..."))), which causes any caller of the tagged
>>>> function to throw an error at compile time, indicating that the
>>>> symbol is not available for external use.
>>>>>>> 
>>>>>>> This isn't a perfect solution, as applications can still hack
>>>>>>> around it of course,
>>>>>> 
>>>>>> I think, one way to, avoid, hack around could be to,
>>>>>> 
>>>>>> 1) at config stage, create  a random number for the build
>>>>>> 2) introduce RTE_CALL_INTERNAL macro for calling internal
>>>>>> function, compare the generated random number for allowing the
>>>>>> calls to make within the library. i.e leverage the fact that
>>>>>> external library would never know the random number generated
>>>>>> for the DPDK build
>>>> and internal driver code does.
>>>>>> 
>>>>> Do we really need to care about this. If have some determined
>>>>> enough to hack around our limitations, then they surely know that
>>>>> they have an unsupported configuration. We just need to protect
>>>>> against inadvertent use of internals, IMHO.
>>>>> 
>>>> I agree, I too had thought about doing some sort of internal runtime
>>>> checking to match internal only symbols, such that they were only
>>>> accessable by internally approved users, but it started to feel like a great
>> deal of overhead.
>>>> Its a good idea for a general mechanism I think, but I believe the
>>>> value here is more to internally document which apis we want to mark
>>>> as being for internal use only, and create a lightweight roadblock
>>>> at build time to catch users inadvertently using them.  Determined
>>>> users will get around anything, and theres not much we can do to stop
>> them.
>>> 
>>> I agree too. IMHO, Simply having following items would be enough
>>> 
>>> 1) Avoid exposing the internal function prototype through public
>>> header files
>>> 2) Add @internal to API documentation
>>> 3) Just decide the name space for internal API for tooling(i.e not
>>> start with rte_ or so) Using objdump scheme to detect internal functions
>> requires the the library to build prior to run the checkpatch.
>>> 
>> 
>> No, I'm not comfortable with that approach, and I've stated why:
>> 1) Not exposing the functions via header files is a fine start
>> 
>> 2) Adding internal documentation is also fine, but does nothing to correlate
>> the code implementing those functions to the documentation.  Its valuable
>> to have a tag on a function identifying it as internal only.
>> 
>> 3) Using naming conventions to separate internal only from non-internal
>> functions is a vague approach, requiring future developers to be cogniscent
>> of the convention and make the appropriate naming choices.  It also implicitly
>> restricts the abliity for future developers to make naming changes in conflict
>> with that convention
> 
> Enforcing the naming convention can be achieved through tooling as well.
> 
>> 
>> 4) Adding a tag like __rte_internal creates an interlock whereby, not only are
>> internal functions excused from ABI constraints, but forces developers to
>> intentionally mark their internal functions as being internal in the code, which
>> is beneficial to clarlity of understanding during the development process.
> 
> No issues in adding __rte_internal. But, I am against current implementaion, 
> Ie. adding objdump dependency
> to checkpatch i.e developer has to build the library first so  that checkpatch can
> can know, Is it belongs to internal section or not?
> 
>> 
>> 5) Adding a tag like __rte_internal is explicit, and allows developers to use a
>> single header file instead of multiple header files if they so choose
>> 
>> We went through this with experimental symbols as well[1], and it just
>> makes more sense to me to clearly document in the code what constitutes
>> an internal symbol rather than relying on naming conventions and hoping
>> that developers read the documentation before exporting a symbol
>> publically.

I feel like we are creating a lot of extra work for the developer and adding a number of constraints to getting code patches submitted as the tools all have to be working together. The versioning file and __rte_experimental stuff today has always being handle wrong or not done by the developer. Altering the tools to detect these changes works and it seemed to take a while to iron out. To me we should be doing the minimum steps to reasonably isolate internal API and data from the user. If someone wants to access the those APIs that is their choice and enforcing with new macros and tools is over kill IMHO.

1) Adding @internal to documentation is a great start along with more docs to explain what internal functions/data should be handled.
2) Hiding/moving internal function prototypes in private headers.
3) Adding setters/getters for internal data.
4) Make sure we review and reject direct use of internal functions and data.

The goal here is to handle the 80% rule and make it very obvious to the developer these are internal functions and data. Using these or similar minimum steps should be reasonable IMHO.
>> 
>> 
>> [1] https://mails.dpdk.org/archives/dev/2017-December/083828.html
>>>> 
>>>> If we really wanted to go down that road, we could use a mechainsm
>>>> simmilar to the EXPORT_SYMBOL / EXPORT_SYMBOL_GPL infrastructure
>>>> that the kernel uses, but that would required building our own
>>>> custom linker script, which seems like overkill here.
>>>> 
>>>> Best
>>>> Neil
>>>> 
>>>>> /Bruce

Regards,
Keith


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-06 11:34  3%         ` Neil Horman
@ 2019-06-06 12:04  0%           ` Jerin Jacob Kollanukkaran
  2019-06-06 13:18  0%             ` Wiles, Keith
  2019-06-06 13:35  0%             ` Neil Horman
  0 siblings, 2 replies; 200+ results
From: Jerin Jacob Kollanukkaran @ 2019-06-06 12:04 UTC (permalink / raw)
  To: Neil Horman; +Cc: Bruce Richardson, dev, Thomas Monjalon

> -----Original Message-----
> From: Neil Horman <nhorman@tuxdriver.com>
> Sent: Thursday, June 6, 2019 5:04 PM
> To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> Cc: Bruce Richardson <bruce.richardson@intel.com>; dev@dpdk.org;
> Thomas Monjalon <thomas@monjalon.net>
> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> 
> On Thu, Jun 06, 2019 at 09:44:52AM +0000, Jerin Jacob Kollanukkaran wrote:
> > > -----Original Message-----
> > > From: Neil Horman <nhorman@tuxdriver.com>
> > > Sent: Wednesday, June 5, 2019 11:41 PM
> > > To: Bruce Richardson <bruce.richardson@intel.com>
> > > Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; dev@dpdk.org;
> > > Thomas Monjalon <thomas@monjalon.net>
> > > Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > >
> > > On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson wrote:
> > > > On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob
> > > > Kollanukkaran
> > > wrote:
> > > > > > -----Original Message-----
> > > > > > From: Neil Horman <nhorman@tuxdriver.com>
> > > > > > Sent: Sunday, May 26, 2019 12:14 AM
> > > > > > To: dev@dpdk.org
> > > > > > Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob
> > > > > > Kollanukkaran <jerinj@marvell.com>; Bruce Richardson
> > > > > > <bruce.richardson@intel.com>; Thomas Monjalon
> > > > > > <thomas@monjalon.net>
> > > > > > Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > > > > >
> > > > > > Hey-
> > > > > > 	Based on our recent conversations regarding the use of
> > > > > > symbols only meant for internal dpdk consumption (between dpdk
> > > > > > libraries), this is an idea that I've come up with that I'd
> > > > > > like to get some feedback on
> > > > > >
> > > > > > Summary:
> > > > > > 1) We have symbols in the DPDK that are meant to be used
> > > > > > between DPDK libraries, but not by applications linking to
> > > > > > them
> > > > > > 2) We would like to document those symbols in the code, so as
> > > > > > to note them clearly as for being meant for internal use only
> > > > > > 3) Linker symbol visibility is a very coarse grained tool, and
> > > > > > so there is no good way in a single library to mark items as
> > > > > > being meant for use only by other DPDK libraries, at least not
> > > > > > without some extensive runtime checking
> > > > > >
> > > > > >
> > > > > > Proposal:
> > > > > > I'm proposing that we introduce the __rte_internal tag.  From
> > > > > > a coding standpoint it works a great deal like the
> > > > > > __rte_experimental tag in that it expempts the tagged symbol
> > > > > > from ABI constraints (as the only users should be represented
> > > > > > in the DPDK build environment).  Additionally, the
> > > > > > __rte_internal macro resolves differently based on the
> > > > > > definition of the BUILDING_RTE_SDK flag (working under the
> > > > > > assumption that said flag should only ever be set if we are
> > > > > > actually building DPDK libraries which will make use of
> > > > > > internal calls).  If the BUILDING_RTE_SDK flag is set
> > > > > > __rte_internal resolves to __attribute__((section
> > > > > > "text.internal)), placing it in a special text section which
> > > > > > is then used to validate that the the symbol appears in the
> > > > > > INTERNAL section of the corresponding library version map).
> > > > > > If BUILDING_RTE_SDK is not set, then __rte_internal resolves
> > > > > > to
> > > __attribute__((error("..."))), which causes any caller of the tagged
> > > function to throw an error at compile time, indicating that the
> > > symbol is not available for external use.
> > > > > >
> > > > > > This isn't a perfect solution, as applications can still hack
> > > > > > around it of course,
> > > > >
> > > > > I think, one way to, avoid, hack around could be to,
> > > > >
> > > > > 1) at config stage, create  a random number for the build
> > > > > 2) introduce RTE_CALL_INTERNAL macro for calling internal
> > > > > function, compare the generated random number for allowing the
> > > > > calls to make within the library. i.e leverage the fact that
> > > > > external library would never know the random number generated
> > > > > for the DPDK build
> > > and internal driver code does.
> > > > >
> > > > Do we really need to care about this. If have some determined
> > > > enough to hack around our limitations, then they surely know that
> > > > they have an unsupported configuration. We just need to protect
> > > > against inadvertent use of internals, IMHO.
> > > >
> > > I agree, I too had thought about doing some sort of internal runtime
> > > checking to match internal only symbols, such that they were only
> > > accessable by internally approved users, but it started to feel like a great
> deal of overhead.
> > > Its a good idea for a general mechanism I think, but I believe the
> > > value here is more to internally document which apis we want to mark
> > > as being for internal use only, and create a lightweight roadblock
> > > at build time to catch users inadvertently using them.  Determined
> > > users will get around anything, and theres not much we can do to stop
> them.
> >
> > I agree too. IMHO, Simply having following items would be enough
> >
> > 1) Avoid exposing the internal function prototype through public
> > header files
> > 2) Add @internal to API documentation
> > 3) Just decide the name space for internal API for tooling(i.e not
> > start with rte_ or so) Using objdump scheme to detect internal functions
> requires the the library to build prior to run the checkpatch.
> >
> 
> No, I'm not comfortable with that approach, and I've stated why:
> 1) Not exposing the functions via header files is a fine start
> 
> 2) Adding internal documentation is also fine, but does nothing to correlate
> the code implementing those functions to the documentation.  Its valuable
> to have a tag on a function identifying it as internal only.
> 
> 3) Using naming conventions to separate internal only from non-internal
> functions is a vague approach, requiring future developers to be cogniscent
> of the convention and make the appropriate naming choices.  It also implicitly
> restricts the abliity for future developers to make naming changes in conflict
> with that convention

Enforcing the naming convention can be achieved through tooling as well.

> 
> 4) Adding a tag like __rte_internal creates an interlock whereby, not only are
> internal functions excused from ABI constraints, but forces developers to
> intentionally mark their internal functions as being internal in the code, which
> is beneficial to clarlity of understanding during the development process.

No issues in adding __rte_internal. But, I am against current implementaion, 
Ie. adding objdump dependency
to checkpatch i.e developer has to build the library first so  that checkpatch can
can know, Is it belongs to internal section or not?

> 
> 5) Adding a tag like __rte_internal is explicit, and allows developers to use a
> single header file instead of multiple header files if they so choose
> 
> We went through this with experimental symbols as well[1], and it just
> makes more sense to me to clearly document in the code what constitutes
> an internal symbol rather than relying on naming conventions and hoping
> that developers read the documentation before exporting a symbol
> publically.
> 
> 
> [1] https://mails.dpdk.org/archives/dev/2017-December/083828.html
> > >
> > > If we really wanted to go down that road, we could use a mechainsm
> > > simmilar to the EXPORT_SYMBOL / EXPORT_SYMBOL_GPL infrastructure
> > > that the kernel uses, but that would required building our own
> > > custom linker script, which seems like overkill here.
> > >
> > > Best
> > > Neil
> > >
> > > > /Bruce
> > > >
> >

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-06  9:44  0%       ` Jerin Jacob Kollanukkaran
@ 2019-06-06 11:34  3%         ` Neil Horman
  2019-06-06 12:04  0%           ` Jerin Jacob Kollanukkaran
  0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2019-06-06 11:34 UTC (permalink / raw)
  To: Jerin Jacob Kollanukkaran; +Cc: Bruce Richardson, dev, Thomas Monjalon

On Thu, Jun 06, 2019 at 09:44:52AM +0000, Jerin Jacob Kollanukkaran wrote:
> > -----Original Message-----
> > From: Neil Horman <nhorman@tuxdriver.com>
> > Sent: Wednesday, June 5, 2019 11:41 PM
> > To: Bruce Richardson <bruce.richardson@intel.com>
> > Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; dev@dpdk.org; Thomas
> > Monjalon <thomas@monjalon.net>
> > Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > 
> > On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson wrote:
> > > On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob Kollanukkaran
> > wrote:
> > > > > -----Original Message-----
> > > > > From: Neil Horman <nhorman@tuxdriver.com>
> > > > > Sent: Sunday, May 26, 2019 12:14 AM
> > > > > To: dev@dpdk.org
> > > > > Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob Kollanukkaran
> > > > > <jerinj@marvell.com>; Bruce Richardson
> > > > > <bruce.richardson@intel.com>; Thomas Monjalon
> > > > > <thomas@monjalon.net>
> > > > > Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > > > >
> > > > > Hey-
> > > > > 	Based on our recent conversations regarding the use of symbols
> > > > > only meant for internal dpdk consumption (between dpdk libraries),
> > > > > this is an idea that I've come up with that I'd like to get some
> > > > > feedback on
> > > > >
> > > > > Summary:
> > > > > 1) We have symbols in the DPDK that are meant to be used between
> > > > > DPDK libraries, but not by applications linking to them
> > > > > 2) We would like to document those symbols in the code, so as to
> > > > > note them clearly as for being meant for internal use only
> > > > > 3) Linker symbol visibility is a very coarse grained tool, and so
> > > > > there is no good way in a single library to mark items as being
> > > > > meant for use only by other DPDK libraries, at least not without
> > > > > some extensive runtime checking
> > > > >
> > > > >
> > > > > Proposal:
> > > > > I'm proposing that we introduce the __rte_internal tag.  From a
> > > > > coding standpoint it works a great deal like the
> > > > > __rte_experimental tag in that it expempts the tagged symbol from
> > > > > ABI constraints (as the only users should be represented in the
> > > > > DPDK build environment).  Additionally, the __rte_internal macro
> > > > > resolves differently based on the definition of the
> > > > > BUILDING_RTE_SDK flag (working under the assumption that said flag
> > > > > should only ever be set if we are actually building DPDK libraries
> > > > > which will make use of internal calls).  If the BUILDING_RTE_SDK
> > > > > flag is set __rte_internal resolves to __attribute__((section
> > > > > "text.internal)), placing it in a special text section which is
> > > > > then used to validate that the the symbol appears in the INTERNAL
> > > > > section of the corresponding library version map).  If
> > > > > BUILDING_RTE_SDK is not set, then __rte_internal resolves to
> > __attribute__((error("..."))), which causes any caller of the tagged function
> > to throw an error at compile time, indicating that the symbol is not available
> > for external use.
> > > > >
> > > > > This isn't a perfect solution, as applications can still hack
> > > > > around it of course,
> > > >
> > > > I think, one way to, avoid, hack around could be to,
> > > >
> > > > 1) at config stage, create  a random number for the build
> > > > 2) introduce RTE_CALL_INTERNAL macro for calling internal function,
> > > > compare the generated random number for allowing the calls to make
> > > > within the library. i.e leverage the fact that external library
> > > > would never know the random number generated for the DPDK build
> > and internal driver code does.
> > > >
> > > Do we really need to care about this. If have some determined enough
> > > to hack around our limitations, then they surely know that they have
> > > an unsupported configuration. We just need to protect against
> > > inadvertent use of internals, IMHO.
> > >
> > I agree, I too had thought about doing some sort of internal runtime checking
> > to match internal only symbols, such that they were only accessable by
> > internally approved users, but it started to feel like a great deal of overhead.
> > Its a good idea for a general mechanism I think, but I believe the value here is
> > more to internally document which apis we want to mark as being for
> > internal use only, and create a lightweight roadblock at build time to catch
> > users inadvertently using them.  Determined users will get around anything,
> > and theres not much we can do to stop them.
> 
> I agree too. IMHO, Simply having following items would be enough
> 
> 1) Avoid exposing the internal function prototype through public header files
> 2) Add @internal to API documentation
> 3) Just decide the name space for internal API for tooling(i.e not start with rte_ or so)
> Using objdump scheme to detect internal functions requires the the library to build prior to run the checkpatch.
> 

No, I'm not comfortable with that approach, and I've stated why:
1) Not exposing the functions via header files is a fine start

2) Adding internal documentation is also fine, but does nothing to correlate the
code implementing those functions to the documentation.  Its valuable to have a
tag on a function identifying it as internal only.

3) Using naming conventions to separate internal only from non-internal
functions is a vague approach, requiring future developers to be cogniscent of
the convention and make the appropriate naming choices.  It also implicitly
restricts the abliity for future developers to make naming changes in conflict
with that convention

4) Adding a tag like __rte_internal creates an interlock whereby, not only are
internal functions excused from ABI constraints, but forces developers to
intentionally mark their internal functions as being internal in the code, which
is beneficial to clarlity of understanding during the development process.

5) Adding a tag like __rte_internal is explicit, and allows developers to use a
single header file instead of multiple header files if they so choose

We went through this with experimental symbols as well[1], and it just makes
more sense to me to clearly document in the code what constitutes an internal
symbol rather than relying on naming conventions and hoping that developers read
the documentation before exporting a symbol publically.


[1] https://mails.dpdk.org/archives/dev/2017-December/083828.html
> > 
> > If we really wanted to go down that road, we could use a mechainsm
> > simmilar to the EXPORT_SYMBOL / EXPORT_SYMBOL_GPL infrastructure that
> > the kernel uses, but that would required building our own custom linker
> > script, which seems like overkill here.
> > 
> > Best
> > Neil
> > 
> > > /Bruce
> > >
> 

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-05 18:11  0%     ` Neil Horman
@ 2019-06-06  9:44  0%       ` Jerin Jacob Kollanukkaran
  2019-06-06 11:34  3%         ` Neil Horman
  0 siblings, 1 reply; 200+ results
From: Jerin Jacob Kollanukkaran @ 2019-06-06  9:44 UTC (permalink / raw)
  To: Neil Horman, Bruce Richardson; +Cc: dev, Thomas Monjalon

> -----Original Message-----
> From: Neil Horman <nhorman@tuxdriver.com>
> Sent: Wednesday, June 5, 2019 11:41 PM
> To: Bruce Richardson <bruce.richardson@intel.com>
> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; dev@dpdk.org; Thomas
> Monjalon <thomas@monjalon.net>
> Subject: Re: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> 
> On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson wrote:
> > On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob Kollanukkaran
> wrote:
> > > > -----Original Message-----
> > > > From: Neil Horman <nhorman@tuxdriver.com>
> > > > Sent: Sunday, May 26, 2019 12:14 AM
> > > > To: dev@dpdk.org
> > > > Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob Kollanukkaran
> > > > <jerinj@marvell.com>; Bruce Richardson
> > > > <bruce.richardson@intel.com>; Thomas Monjalon
> > > > <thomas@monjalon.net>
> > > > Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > > >
> > > > Hey-
> > > > 	Based on our recent conversations regarding the use of symbols
> > > > only meant for internal dpdk consumption (between dpdk libraries),
> > > > this is an idea that I've come up with that I'd like to get some
> > > > feedback on
> > > >
> > > > Summary:
> > > > 1) We have symbols in the DPDK that are meant to be used between
> > > > DPDK libraries, but not by applications linking to them
> > > > 2) We would like to document those symbols in the code, so as to
> > > > note them clearly as for being meant for internal use only
> > > > 3) Linker symbol visibility is a very coarse grained tool, and so
> > > > there is no good way in a single library to mark items as being
> > > > meant for use only by other DPDK libraries, at least not without
> > > > some extensive runtime checking
> > > >
> > > >
> > > > Proposal:
> > > > I'm proposing that we introduce the __rte_internal tag.  From a
> > > > coding standpoint it works a great deal like the
> > > > __rte_experimental tag in that it expempts the tagged symbol from
> > > > ABI constraints (as the only users should be represented in the
> > > > DPDK build environment).  Additionally, the __rte_internal macro
> > > > resolves differently based on the definition of the
> > > > BUILDING_RTE_SDK flag (working under the assumption that said flag
> > > > should only ever be set if we are actually building DPDK libraries
> > > > which will make use of internal calls).  If the BUILDING_RTE_SDK
> > > > flag is set __rte_internal resolves to __attribute__((section
> > > > "text.internal)), placing it in a special text section which is
> > > > then used to validate that the the symbol appears in the INTERNAL
> > > > section of the corresponding library version map).  If
> > > > BUILDING_RTE_SDK is not set, then __rte_internal resolves to
> __attribute__((error("..."))), which causes any caller of the tagged function
> to throw an error at compile time, indicating that the symbol is not available
> for external use.
> > > >
> > > > This isn't a perfect solution, as applications can still hack
> > > > around it of course,
> > >
> > > I think, one way to, avoid, hack around could be to,
> > >
> > > 1) at config stage, create  a random number for the build
> > > 2) introduce RTE_CALL_INTERNAL macro for calling internal function,
> > > compare the generated random number for allowing the calls to make
> > > within the library. i.e leverage the fact that external library
> > > would never know the random number generated for the DPDK build
> and internal driver code does.
> > >
> > Do we really need to care about this. If have some determined enough
> > to hack around our limitations, then they surely know that they have
> > an unsupported configuration. We just need to protect against
> > inadvertent use of internals, IMHO.
> >
> I agree, I too had thought about doing some sort of internal runtime checking
> to match internal only symbols, such that they were only accessable by
> internally approved users, but it started to feel like a great deal of overhead.
> Its a good idea for a general mechanism I think, but I believe the value here is
> more to internally document which apis we want to mark as being for
> internal use only, and create a lightweight roadblock at build time to catch
> users inadvertently using them.  Determined users will get around anything,
> and theres not much we can do to stop them.

I agree too. IMHO, Simply having following items would be enough

1) Avoid exposing the internal function prototype through public header files
2) Add @internal to API documentation
3) Just decide the name space for internal API for tooling(i.e not start with rte_ or so)
Using objdump scheme to detect internal functions requires the the library to build prior to run the checkpatch.

> 
> If we really wanted to go down that road, we could use a mechainsm
> simmilar to the EXPORT_SYMBOL / EXPORT_SYMBOL_GPL infrastructure that
> the kernel uses, but that would required building our own custom linker
> script, which seems like overkill here.
> 
> Best
> Neil
> 
> > /Bruce
> >

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH 01/10] build: print list of disabled components for meson build
  @ 2019-06-05 20:22  4% ` Bruce Richardson
  0 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2019-06-05 20:22 UTC (permalink / raw)
  To: bluca, thomas; +Cc: dev, john.mcnamara, Bruce Richardson

When configuring with meson we print out a list of enabled components, but
it is also useful to list out the disabled components and the reasons why.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 doc/guides/contributing/coding_style.rst | 15 ++++++++++++++-
 drivers/meson.build                      | 12 +++++++++++-
 lib/meson.build                          |  6 +++++-
 meson.build                              | 15 +++++++++++++++
 4 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/doc/guides/contributing/coding_style.rst b/doc/guides/contributing/coding_style.rst
index a5d5897f3..449b33494 100644
--- a/doc/guides/contributing/coding_style.rst
+++ b/doc/guides/contributing/coding_style.rst
@@ -852,12 +852,15 @@ allow_experimental_apis
 build
 	**Default Value = true**
 	Used to optionally compile a library, based on its dependencies or
-	environment. A simple example of use would be:
+	environment. When set to "false" the ``reason`` value, explained below, should
+	also be set to explain to the user why the component is not being built.
+	A simple example of use would be:
 
 .. code-block:: python
 
 	if not is_linux
 	        build = false
+	        reason = 'only supported on Linux'
 	endif
 
 
@@ -938,6 +941,13 @@ objs
 	objects that were compiled up as part of another target given in the
 	included library ``meson.build`` file.
 
+reason
+	**Default Value = '<unknown reason>'**.
+	This variable should be used when a library is not to be built i.e. when
+	``build`` is set to "false", to specify the reason why a library will not be
+	built. For missing dependencies this should be of the form
+	``'missing dependency, "libname"'``.
+
 version
 	**Default Value = 1**.
 	Specifies the ABI version of the library, and is used as the major
@@ -991,6 +1001,9 @@ pkgconfig_extra_libs
 	using static libraries. Anything added here will be appended to the end
 	of the ``pkgconfig --libs`` output.
 
+reason
+	As above.
+
 sources [mandatory]
 	As above
 
diff --git a/drivers/meson.build b/drivers/meson.build
index 4c444f495..94e6c829e 100644
--- a/drivers/meson.build
+++ b/drivers/meson.build
@@ -40,6 +40,7 @@ foreach class:dpdk_driver_classes
 
 		# set up empty variables used for build
 		build = true # set to false to disable, e.g. missing deps
+		reason = '<unknown reason>' # set if build == false to explain
 		name = drv
 		version = 1
 		allow_experimental_apis = false
@@ -61,7 +62,16 @@ foreach class:dpdk_driver_classes
 		# pull in driver directory which should assign to each of the above
 		subdir(drv_path)
 
-		if build
+		if not build
+			# some driver directories are placeholders which
+			# are never built, so we allow suppression of the
+			# component disable printout in those cases
+			if reason != ''
+				dpdk_drvs_disabled += drv_path
+				set_variable(drv_path.underscorify() +
+						'_disable_reason', reason)
+			endif
+		else
 			class_drivers += name
 
 			dpdk_conf.set(config_flag_fmt.format(name.to_upper()),1)
diff --git a/lib/meson.build b/lib/meson.build
index e067ce5ea..76c13b7da 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -46,6 +46,7 @@ default_cflags += '-D_GNU_SOURCE'
 
 foreach l:libraries
 	build = true
+	reason = '<unknown reason>' # set if build == false to explain why
 	name = l
 	version = 1
 	allow_experimental_apis = false
@@ -68,7 +69,10 @@ foreach l:libraries
 	dir_name = 'librte_' + l
 	subdir(dir_name)
 
-	if build
+	if not build
+		dpdk_libs_disabled += name
+		set_variable(name.underscorify() + '_disable_reason', reason)
+	else
 		enabled_libs += name
 		dpdk_conf.set('RTE_LIBRTE_' + name.to_upper(), 1)
 		install_headers(headers)
diff --git a/meson.build b/meson.build
index 9cad43481..63a1ce25b 100644
--- a/meson.build
+++ b/meson.build
@@ -20,6 +20,8 @@ dpdk_driver_classes = []
 dpdk_drivers = []
 dpdk_extra_ldflags = []
 dpdk_app_link_libraries = []
+dpdk_libs_disabled = []
+dpdk_drvs_disabled = []
 
 # configure the build, and make sure configs here and in config folder are
 # able to be included in any file. We also store a global array of include dirs
@@ -108,3 +110,16 @@ foreach class:dpdk_driver_classes
 	endforeach
 endforeach
 message(output_message + '\n')
+
+output_message = '\n=================\nContent Skipped\n=================\n'
+output_message += '\nlibs:\n\t'
+foreach lib:dpdk_libs_disabled
+	reason = get_variable(lib.underscorify() + '_disable_reason')
+	output_message += lib + ':\t' + reason + '\n\t'
+endforeach
+output_message += '\ndrivers:\n\t'
+foreach drv:dpdk_drvs_disabled
+	reason = get_variable(drv.underscorify() + '_disable_reason')
+	output_message += drv + ':\t' + reason + '\n\t'
+endforeach
+message(output_message + '\n')
-- 
2.21.0


^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-05 16:45  0%   ` Bruce Richardson
@ 2019-06-05 18:11  0%     ` Neil Horman
  2019-06-06  9:44  0%       ` Jerin Jacob Kollanukkaran
  0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2019-06-05 18:11 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: Jerin Jacob Kollanukkaran, dev, Thomas Monjalon

On Wed, Jun 05, 2019 at 05:45:41PM +0100, Bruce Richardson wrote:
> On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob Kollanukkaran wrote:
> > > -----Original Message-----
> > > From: Neil Horman <nhorman@tuxdriver.com>
> > > Sent: Sunday, May 26, 2019 12:14 AM
> > > To: dev@dpdk.org
> > > Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob Kollanukkaran
> > > <jerinj@marvell.com>; Bruce Richardson <bruce.richardson@intel.com>;
> > > Thomas Monjalon <thomas@monjalon.net>
> > > Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > > 
> > > Hey-
> > > 	Based on our recent conversations regarding the use of symbols only
> > > meant for internal dpdk consumption (between dpdk libraries), this is an idea
> > > that I've come up with that I'd like to get some feedback on
> > > 
> > > Summary:
> > > 1) We have symbols in the DPDK that are meant to be used between DPDK
> > > libraries, but not by applications linking to them
> > > 2) We would like to document those symbols in the code, so as to note them
> > > clearly as for being meant for internal use only
> > > 3) Linker symbol visibility is a very coarse grained tool, and so there is no good
> > > way in a single library to mark items as being meant for use only by other
> > > DPDK libraries, at least not without some extensive runtime checking
> > > 
> > > 
> > > Proposal:
> > > I'm proposing that we introduce the __rte_internal tag.  From a coding
> > > standpoint it works a great deal like the __rte_experimental tag in that it
> > > expempts the tagged symbol from ABI constraints (as the only users should
> > > be represented in the DPDK build environment).  Additionally, the
> > > __rte_internal macro resolves differently based on the definition of the
> > > BUILDING_RTE_SDK flag (working under the assumption that said flag should
> > > only ever be set if we are actually building DPDK libraries which will make use
> > > of internal calls).  If the BUILDING_RTE_SDK flag is set __rte_internal resolves
> > > to __attribute__((section "text.internal)), placing it in a special text section
> > > which is then used to validate that the the symbol appears in the INTERNAL
> > > section of the corresponding library version map).  If BUILDING_RTE_SDK is
> > > not set, then __rte_internal resolves to __attribute__((error("..."))), which
> > > causes any caller of the tagged function to throw an error at compile time,
> > > indicating that the symbol is not available for external use.
> > > 
> > > This isn't a perfect solution, as applications can still hack around it of course,
> > 
> > I think, one way to, avoid, hack around could be to,
> > 
> > 1) at config stage, create  a random number for the build
> > 2) introduce RTE_CALL_INTERNAL macro for calling internal function, compare 
> > the generated random number for allowing the calls to make within the library. i.e leverage the
> > fact that external library would never know the random number generated 
> > for the DPDK build and internal driver code does.
> > 
> Do we really need to care about this. If have some determined enough to
> hack around our limitations, then they surely know that they have an
> unsupported configuration. We just need to protect against inadvertent use
> of internals, IMHO.
> 
I agree, I too had thought about doing some sort of internal runtime checking to
match internal only symbols, such that they were only accessable by internally
approved users, but it started to feel like a great deal of overhead.  Its a
good idea for a general mechanism I think, but I believe the value here is more
to internally document which apis we want to mark as being for internal use
only, and create a lightweight roadblock at build time to catch users
inadvertently using them.  Determined users will get around anything, and theres
not much we can do to stop them.

If we really wanted to go down that road, we could use a mechainsm simmilar to
the EXPORT_SYMBOL / EXPORT_SYMBOL_GPL infrastructure that the kernel uses, but
that would required building our own custom linker script, which seems like
overkill here.

Best
Neil

> /Bruce
> 

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
  2019-06-05 16:24  0% ` [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag Jerin Jacob Kollanukkaran
@ 2019-06-05 16:45  0%   ` Bruce Richardson
  2019-06-05 18:11  0%     ` Neil Horman
  0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2019-06-05 16:45 UTC (permalink / raw)
  To: Jerin Jacob Kollanukkaran; +Cc: Neil Horman, dev, Thomas Monjalon

On Wed, Jun 05, 2019 at 04:24:09PM +0000, Jerin Jacob Kollanukkaran wrote:
> > -----Original Message-----
> > From: Neil Horman <nhorman@tuxdriver.com>
> > Sent: Sunday, May 26, 2019 12:14 AM
> > To: dev@dpdk.org
> > Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob Kollanukkaran
> > <jerinj@marvell.com>; Bruce Richardson <bruce.richardson@intel.com>;
> > Thomas Monjalon <thomas@monjalon.net>
> > Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> > 
> > Hey-
> > 	Based on our recent conversations regarding the use of symbols only
> > meant for internal dpdk consumption (between dpdk libraries), this is an idea
> > that I've come up with that I'd like to get some feedback on
> > 
> > Summary:
> > 1) We have symbols in the DPDK that are meant to be used between DPDK
> > libraries, but not by applications linking to them
> > 2) We would like to document those symbols in the code, so as to note them
> > clearly as for being meant for internal use only
> > 3) Linker symbol visibility is a very coarse grained tool, and so there is no good
> > way in a single library to mark items as being meant for use only by other
> > DPDK libraries, at least not without some extensive runtime checking
> > 
> > 
> > Proposal:
> > I'm proposing that we introduce the __rte_internal tag.  From a coding
> > standpoint it works a great deal like the __rte_experimental tag in that it
> > expempts the tagged symbol from ABI constraints (as the only users should
> > be represented in the DPDK build environment).  Additionally, the
> > __rte_internal macro resolves differently based on the definition of the
> > BUILDING_RTE_SDK flag (working under the assumption that said flag should
> > only ever be set if we are actually building DPDK libraries which will make use
> > of internal calls).  If the BUILDING_RTE_SDK flag is set __rte_internal resolves
> > to __attribute__((section "text.internal)), placing it in a special text section
> > which is then used to validate that the the symbol appears in the INTERNAL
> > section of the corresponding library version map).  If BUILDING_RTE_SDK is
> > not set, then __rte_internal resolves to __attribute__((error("..."))), which
> > causes any caller of the tagged function to throw an error at compile time,
> > indicating that the symbol is not available for external use.
> > 
> > This isn't a perfect solution, as applications can still hack around it of course,
> 
> I think, one way to, avoid, hack around could be to,
> 
> 1) at config stage, create  a random number for the build
> 2) introduce RTE_CALL_INTERNAL macro for calling internal function, compare 
> the generated random number for allowing the calls to make within the library. i.e leverage the
> fact that external library would never know the random number generated 
> for the DPDK build and internal driver code does.
> 
Do we really need to care about this. If have some determined enough to
hack around our limitations, then they surely know that they have an
unsupported configuration. We just need to protect against inadvertent use
of internals, IMHO.

/Bruce

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
    @ 2019-06-05 16:24  0% ` Jerin Jacob Kollanukkaran
  2019-06-05 16:45  0%   ` Bruce Richardson
  2019-06-12 20:38  4% ` [dpdk-dev] [PATCH v1 0/9] dpdk: " Neil Horman
  2019-06-13 14:23  4% ` [dpdk-dev] [PATCH v2 0/10] " Neil Horman
  3 siblings, 1 reply; 200+ results
From: Jerin Jacob Kollanukkaran @ 2019-06-05 16:24 UTC (permalink / raw)
  To: Neil Horman, dev; +Cc: Bruce Richardson, Thomas Monjalon

> -----Original Message-----
> From: Neil Horman <nhorman@tuxdriver.com>
> Sent: Sunday, May 26, 2019 12:14 AM
> To: dev@dpdk.org
> Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob Kollanukkaran
> <jerinj@marvell.com>; Bruce Richardson <bruce.richardson@intel.com>;
> Thomas Monjalon <thomas@monjalon.net>
> Subject: [EXT] [RFC PATCH 0/2] introduce __rte_internal tag
> 
> Hey-
> 	Based on our recent conversations regarding the use of symbols only
> meant for internal dpdk consumption (between dpdk libraries), this is an idea
> that I've come up with that I'd like to get some feedback on
> 
> Summary:
> 1) We have symbols in the DPDK that are meant to be used between DPDK
> libraries, but not by applications linking to them
> 2) We would like to document those symbols in the code, so as to note them
> clearly as for being meant for internal use only
> 3) Linker symbol visibility is a very coarse grained tool, and so there is no good
> way in a single library to mark items as being meant for use only by other
> DPDK libraries, at least not without some extensive runtime checking
> 
> 
> Proposal:
> I'm proposing that we introduce the __rte_internal tag.  From a coding
> standpoint it works a great deal like the __rte_experimental tag in that it
> expempts the tagged symbol from ABI constraints (as the only users should
> be represented in the DPDK build environment).  Additionally, the
> __rte_internal macro resolves differently based on the definition of the
> BUILDING_RTE_SDK flag (working under the assumption that said flag should
> only ever be set if we are actually building DPDK libraries which will make use
> of internal calls).  If the BUILDING_RTE_SDK flag is set __rte_internal resolves
> to __attribute__((section "text.internal)), placing it in a special text section
> which is then used to validate that the the symbol appears in the INTERNAL
> section of the corresponding library version map).  If BUILDING_RTE_SDK is
> not set, then __rte_internal resolves to __attribute__((error("..."))), which
> causes any caller of the tagged function to throw an error at compile time,
> indicating that the symbol is not available for external use.
> 
> This isn't a perfect solution, as applications can still hack around it of course,

I think, one way to, avoid, hack around could be to,

1) at config stage, create  a random number for the build
2) introduce RTE_CALL_INTERNAL macro for calling internal function, compare 
the generated random number for allowing the calls to make within the library. i.e leverage the
fact that external library would never know the random number generated 
for the DPDK build and internal driver code does.


> but I think it hits some of the high points, restricting symbol access for any
> library that prototypes its public and private symbols in the same header file,
> excluding the internal symbols from ABI constraints, and clearly documenting
> those symbols which we wish to limit to internal usage.
> 
> I've included a patch to the dpaa library to demonstrate its usage.  If there is
> consensus on this approach, I'll expand and repost the patch, pulling in the
> other libraries which have internal-only symbol usage.
> 
> Regards
> Neil
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> CC: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> CC: Bruce Richardson <bruce.richardson@intel.com>
> CC: Thomas Monjalon <thomas@monjalon.net>
> 


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [EXT] [RFC PATCH 1/2] Add __rte_internal tag for functions and version target
  @ 2019-06-05 16:14  0%   ` Jerin Jacob Kollanukkaran
  0 siblings, 0 replies; 200+ results
From: Jerin Jacob Kollanukkaran @ 2019-06-05 16:14 UTC (permalink / raw)
  To: Neil Horman, dev; +Cc: Bruce Richardson, Thomas Monjalon

> -----Original Message-----
> From: Neil Horman <nhorman@tuxdriver.com>
> Sent: Sunday, May 26, 2019 12:14 AM
> To: dev@dpdk.org
> Cc: Neil Horman <nhorman@tuxdriver.com>; Jerin Jacob Kollanukkaran
> <jerinj@marvell.com>; Bruce Richardson <bruce.richardson@intel.com>;
> Thomas Monjalon <thomas@monjalon.net>
> Subject: [EXT] [RFC PATCH 1/2] Add __rte_internal tag for functions and
> version target
> This tag is meant to be used on function prototypes to identify functions that
> are only meant to be used by internal DPDK libraries (i.e. libraries that are
> built while building the SDK itself, as identified by the defining of the
> BUILDING_RTE_SDK macro).  When that flag is not set, it will resolve to an
> error function attribute, causing build breakage for any compilation unit
> attempting to build it
> 
> Validate the use of this tag in much the same way we validate
> __rte_experimental.  By adding an INTERNAL version to library map files, we
> can exempt internal-only functions from ABI checking, and handle them to
> ensure that symbols we wish to only be for internal use between dpdk
> libraries are properly tagged with __rte_experimental
> 
> Note this patch updates the check-experimental-syms.sh script, which
> normally only check the EXPERIMENTAL section to also check the INTERNAL
> section now.  As such its been renamed to the now more appropriate check-
> special-syms.sh
> 
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> CC: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> CC: Bruce Richardson <bruce.richardson@intel.com>
> CC: Thomas Monjalon <thomas@monjalon.net>
> ---
>  buildtools/check-experimental-syms.sh      | 24 +++++++++++++++++++++-
>  lib/librte_eal/common/include/rte_compat.h | 12 +++++++++++
>  mk/internal/rte.compile-pre.mk             |  6 +++---
>  mk/target/generic/rte.vars.mk              |  2 +-
>  4 files changed, 39 insertions(+), 5 deletions(-)
> 
> diff --git a/buildtools/check-experimental-syms.sh b/buildtools/check-
> experimental-syms.sh
> index 7d1f3a568..63682c677 100755
> --- a/buildtools/check-experimental-syms.sh
> +++ b/buildtools/check-experimental-syms.sh
> @@ -31,10 +31,32 @@ do
>  		cat >&2 <<- END_OF_MESSAGE
>  		$SYM is not flagged as experimental
>  		but is listed in version map
> -		Please add __rte_experimental to the definition of $SYM
> +		Please add __rte_experimental to the definition/prototype
> of $SYM
>  		END_OF_MESSAGE
>  		exit 1
>  	fi
>  done
> +
> +for i in `awk 'BEGIN {found=0}
> +		/.*INTERNAL.*/ {found=1}
> +		/.*}.*;/ {found=0}
> +		/.*;/ {if (found == 1) print $1}' $MAPFILE` do
> +	SYM=`echo $i | sed -e"s/;//"`
> +	objdump -t $OBJFILE | grep -q "\.text.*$SYM$"
> +	IN_TEXT=$?
> +	objdump -t $OBJFILE | grep -q "\.text\.internal.*$SYM$"

I think, it should be OK for cross compilation case. But please cross check.

> +	IN_EXP=$?
> +	if [ $IN_TEXT -eq 0 -a $IN_EXP -ne 0 ]
> +	then
> +		cat >&2 <<- END_OF_MESSAGE
> +		$SYM is not flagged as internal
> +		but is listed in version map
> +		Please add __rte_internal to the definition/prototype of
> $SYM
> +		END_OF_MESSAGE
> +		exit 1
> +	fi
> +done
> +
>  exit 0
> 
> diff --git a/lib/librte_eal/common/include/rte_compat.h
> b/lib/librte_eal/common/include/rte_compat.h
> index 92ff28faf..739e8485c 100644
> --- a/lib/librte_eal/common/include/rte_compat.h
> +++ b/lib/librte_eal/common/include/rte_compat.h


It is a public header file, How about, having __rte_internal
In internal header file so that only SDK components can use it.

> @@ -89,4 +89,16 @@ __attribute__((section(".text.experimental")))
> 
>  #endif
> 
> +/*
> + * __rte_internal tags mark functions as internal only, If specified in
> +public
> + * header files, this tag will resolve to an error directive,
> +preventing
> + * external applications from attempting to make calls to functions not
> +meant
> + * for consumption outside the dpdk library  */ #ifdef BUILDING_RTE_SDK
> +#define __rte_internal __attribute__((section(".text.internal")))


Sometimes, we may have global variables like variable for dynamic logging etc.
If so, I think, it is better to change something not starting with .text


> +#else
> +#define __rte_internal __attribute__((error("This function cannot be used
> outside of the core DPDK library"), \
> +	section(".text.internal")))

Since the above statement is an error, Do we need section attribute here?



^ permalink raw reply	[relevance 0%]

* [dpdk-dev] DPDK techboard minutes of May 22
@ 2019-06-05 15:03  3% Ferruh Yigit
  0 siblings, 0 replies; 200+ results
From: Ferruh Yigit @ 2019-06-05 15:03 UTC (permalink / raw)
  To: dpdk-dev; +Cc: dpdk-techboard

Meeting notes for the DPDK technical board meeting held on 2018-05-22

Attendees:
	- Bruce Richardson
	- Ferruh Yigit
	- Hemant Agrawal
	- Konstantin Ananyev
	- Maxime Coquelin
	- Olivier Matz
	- Stephen Hemminger
	- Thomas Monjalon


1) DPDK API Stability discussion

- A sub-group will work on how to improve ABI/API stability and will come with a
proposal as update to versioning.html and stable.html.
- Sub-group consist of Ray, Bruce, Stephen and Kevin. Ray will drive the effort.
- There will be a status update in next meeting (June 5) and target date is June 19.


2) Userspace summit CFP deadline

- Techboard need to synchronize on major topics to cover in the summit.
- If you think a topic must be covered in the userspace summit, but you don't
want to submit it yourself, please ask to techboard@dpdk.org.


3)  DPDK development process and tools survey

- Honnappa put out the report
- Thomas and Maxime will review the report
- After review techboard approval will be get via email
- When approved, outcome will be shared in the mail list by Honnappa
- Outcome will be presented in the userspace summit by Honnappa
- Maxime and Honnapa will propose list of actions/improvements based on survey
to the techboard on June 19 techboard meeting.

4) Next meeting will be on June 5 and Hemant will chair it

Thanks,
ferruh


^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v3] timer: fix resource leak in finalize
  2019-06-05  9:33  0%     ` Thomas Monjalon
@ 2019-06-05  9:47  3%       ` Burakov, Anatoly
  0 siblings, 0 replies; 200+ results
From: Burakov, Anatoly @ 2019-06-05  9:47 UTC (permalink / raw)
  To: Thomas Monjalon, Erik Gabriel Carrillo; +Cc: dev, rsanford, david.marchand

On 05-Jun-19 10:33 AM, Thomas Monjalon wrote:
> 09/05/2019 10:29, Burakov, Anatoly:
>> On 08-May-19 11:35 PM, Erik Gabriel Carrillo wrote:
>>> By using a lock added to the rte_mem_config (which lives in shared
>>> memory), we can synchronize multiple processes in init/finalize and
>>> safely free allocations made during init.
>>>
>>> Signed-off-by: Erik Gabriel Carrillo <erik.g.carrillo@intel.com>
>>> ---
>>> changes in v3:
>>>    - The previous version had race condition.  This version fixes the race
>>>      by adding a lock in shared memory outside of the DPDK heap area
>>>      that can be used to safely free the memzone reserved in the subsystem
>>>      init call. (Anatoly)
>>>
>>>      This patch depends on http://patches.dpdk.org/patch/53333/.
>>>    
>>> changes in v2:
>>>    - Handle scenario where primary process exits before secondaries such
>>>      that memzone is not freed early (Anatoly)
>>>
>>>    lib/librte_eal/common/include/rte_eal_memconfig.h |  3 +++
>>>    lib/librte_timer/rte_timer.c                      | 23 ++++++++++++++++++++++-
>>>    2 files changed, 25 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
>>> index 84aabe3..8cbc09c 100644
>>> --- a/lib/librte_eal/common/include/rte_eal_memconfig.h
>>> +++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
>>> @@ -64,6 +64,9 @@ struct rte_mem_config {
>>>    	rte_rwlock_t memory_hotplug_lock;
>>>    	/**< indicates whether memory hotplug request is in progress. */
>>>    
>>> +	rte_spinlock_t timer_subsystem_lock;
>>> +	/**< indicates whether timer subsystem init/finalize is in progress. */
>>> +
>>
>> I believe there's an initialize function somewhere which will initialize
>> all of these locks. This lock should be in there as well.
>>
>> Other than that, i'm OK with this change, however i feel like /just/
>> adding this would be a missed opportunity, because next time we want to
>> add something here it will be an ABI break again.
>>
>> We could perhaps use this opportunity to leave some padding for future
>> data. I'm not sure how would that look like, just an idea floating in my
>> head :)
> 
> Any update or other opinion?
> 

I have a patchset that hides mem config - if we are to add a lock, it 
would be after adding that patch, as a bugfix (since by then it would n 
longer be an ABI breakage or an API change).

-- 
Thanks,
Anatoly

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v3] timer: fix resource leak in finalize
  @ 2019-06-05  9:33  0%     ` Thomas Monjalon
  2019-06-05  9:47  3%       ` Burakov, Anatoly
  0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2019-06-05  9:33 UTC (permalink / raw)
  To: Erik Gabriel Carrillo; +Cc: dev, Burakov, Anatoly, rsanford, david.marchand

09/05/2019 10:29, Burakov, Anatoly:
> On 08-May-19 11:35 PM, Erik Gabriel Carrillo wrote:
> > By using a lock added to the rte_mem_config (which lives in shared
> > memory), we can synchronize multiple processes in init/finalize and
> > safely free allocations made during init.
> > 
> > Signed-off-by: Erik Gabriel Carrillo <erik.g.carrillo@intel.com>
> > ---
> > changes in v3:
> >   - The previous version had race condition.  This version fixes the race
> >     by adding a lock in shared memory outside of the DPDK heap area
> >     that can be used to safely free the memzone reserved in the subsystem
> >     init call. (Anatoly)
> > 
> >     This patch depends on http://patches.dpdk.org/patch/53333/.
> >   
> > changes in v2:
> >   - Handle scenario where primary process exits before secondaries such
> >     that memzone is not freed early (Anatoly)
> > 
> >   lib/librte_eal/common/include/rte_eal_memconfig.h |  3 +++
> >   lib/librte_timer/rte_timer.c                      | 23 ++++++++++++++++++++++-
> >   2 files changed, 25 insertions(+), 1 deletion(-)
> > 
> > diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
> > index 84aabe3..8cbc09c 100644
> > --- a/lib/librte_eal/common/include/rte_eal_memconfig.h
> > +++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
> > @@ -64,6 +64,9 @@ struct rte_mem_config {
> >   	rte_rwlock_t memory_hotplug_lock;
> >   	/**< indicates whether memory hotplug request is in progress. */
> >   
> > +	rte_spinlock_t timer_subsystem_lock;
> > +	/**< indicates whether timer subsystem init/finalize is in progress. */
> > +
> 
> I believe there's an initialize function somewhere which will initialize 
> all of these locks. This lock should be in there as well.
> 
> Other than that, i'm OK with this change, however i feel like /just/ 
> adding this would be a missed opportunity, because next time we want to 
> add something here it will be an ABI break again.
> 
> We could perhaps use this opportunity to leave some padding for future 
> data. I'm not sure how would that look like, just an idea floating in my 
> head :)

Any update or other opinion?



^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] 18.11.2 (LTS) patches review and test
  @ 2019-06-04  8:11  1% ` Pei Zhang
  0 siblings, 0 replies; 200+ results
From: Pei Zhang @ 2019-06-04  8:11 UTC (permalink / raw)
  To: Kevin Traynor
  Cc: dpdk stable, dev, Sitong Liu, Raslan Darawsheh, qian q xu,
	Ju-Hyoung Lee, Ian Stokes, Ali Alnubani, David Christensen,
	benjamin walker, Thomas Monjalon, John McNamara, Luca Boccassi,
	Jerin Jacob Kollanukkaran, Hemant Agrawal, Akhil Goyal,
	Chao Yang

Hi Kevin,

Sorry for late response. We have finished the 18.11.2-rc1 testing and got PASS results. 

Testing scenarios:

(1)Guest with device assignment(PF) throughput testing(1G hugepage size)  PASS
(2)Guest with device assignment(PF) throughput testing(2M hugepage size)  PASS
(3)Guest with device assignment(VF) throughput testing: PASS
(4)PVP (host dpdk testpmd as vswitch) 1 queue: throughput testing: PASS
(5)vhost-user reconnect with dpdk-client, qemu-server: ovs reconnect: PASS
(6)PVP vhost-user 2 queues throughput testing: PASS
(7)PVP vhost-user 2 queues - cross numa node  throughput testing: PASS
(8)Guest with vhost-user 2 queues throughput testing: PASS


Best regards,
Pei

----- Original Message -----
From: "Kevin Traynor" <ktraynor@redhat.com>
To: "dpdk stable" <stable@dpdk.org>
Cc: dev@dpdk.org, "Sitong Liu" <siliu@redhat.com>, "Pei Zhang" <pezhang@redhat.com>, "Raslan Darawsheh" <rasland@mellanox.com>, "qian q xu" <qian.q.xu@intel.com>, "Ju-Hyoung Lee" <juhlee@microsoft.com>, "Ian Stokes" <ian.stokes@intel.com>, "Ali Alnubani" <alialnu@mellanox.com>, "David Christensen" <drc@linux.vnet.ibm.com>, "benjamin walker" <benjamin.walker@intel.com>, "Thomas Monjalon" <thomas@monjalon.net>, "John McNamara" <john.mcnamara@intel.com>, "Luca Boccassi" <bluca@debian.org>, "Jerin Jacob Kollanukkaran" <jerinj@marvell.com>, "Hemant Agrawal" <hemant.agrawal@nxp.com>, "Akhil Goyal" <akhil.goyal@nxp.com>
Sent: Tuesday, May 21, 2019 10:01:02 PM
Subject: 18.11.2 (LTS) patches review and test

Hi all,

Here is a list of patches targeted for LTS release 18.11.2.

The planned date for the final release is 11th June.

Please help with testing and validation of your use cases and report
any issues/results. For the final release I will update the release
notes with fixes and reported validations.

A release candidate tarball can be found at:

    https://dpdk.org/browse/dpdk-stable/tag/?id=v18.11.2-rc1

These patches are located at branch 18.11 of dpdk-stable repo:
    https://dpdk.org/browse/dpdk-stable/

Thanks.

Kevin Traynor

---
Aaron Conole (4):
      net/virtio: fix dangling pointer on failure
      ci: enable ccache in Travis
      ci: add a distinguisher to the extra Travis builds
      ipc: unlock on failure

Abhinandan Gujjar (1):
      eventdev: fix crypto adapter

Agalya Babu RadhaKrishnan (2):
      doc: fix interactive commands in testpmd guide
      app/testpmd: fix help info for interactive commands

Akhil Goyal (3):
      crypto/dpaa2_sec: fix session clearing
      crypto/dpaa2_sec: fix offset calculation for GCM
      crypto/dpaa: fix session destroy

Alejandro Lucero (5):
      net/nfp: fix RSS query
      net/nfp: fix file descriptor check
      net/nfp: fix potential integer overflow
      net/nfp: check return value
      net/nfp: fix memory leak

Anatoly Burakov (11):
      malloc: fix documentation of realloc function
      vfio: document multiprocess limitation for container API
      malloc: fix IPC message initialization
      mem: warn user when running without NUMA support
      eal: fix cleanup in no-shconf mode
      ipc: fix send error handling
      ipc: harden message receive
      ipc: handle more invalid parameter cases
      doc: fix typo in IPC guide
      ipc: add warnings about not using IPC with memory API
      ipc: add warnings about correct API usage

Andrew Rybchenko (3):
      net/sfc: remove control path logging from Rx queue count
      net/sfc: fix logging from secondary process
      net/sfc: fix speed capabilities reported in device info

Andrius Sirvys (4):
      drivers/net: fix shifting 32-bit signed variable 31 times
      acl: fix compiler flags with meson and AVX2 runtime
      net/virtio: fix duplicate naming of include guard
      bitrate: fix unchecked return value

Andy Pei (1):
      raw/ifpga: modify log output

Anoob Joseph (2):
      common/cpt: fix null auth only
      cryptodev: fix driver name comparison

Arek Kusztal (2):
      crypto/openssl: fix big numbers after computations
      crypto/openssl: fix modexp

Beilei Xing (2):
      net/i40e: fix logging on VF close
      net/i40e: fix link speed for X722

Bernard Iremonger (1):
      examples/ipsec-secgw: fix debug logs

Bill Hong (1):
      net: fix Tx VLAN flag for offload emulation

Bruce Richardson (24):
      test/compress: fix missing header include
      examples/ip_pipeline: disable build when no epoll
      examples/vhost_crypto: fix dependency on vhost library
      devtools: fix build test on FreeBSD
      eal: support strlcat function
      telemetry: fix mapping of statistics
      eal: tighten permissions on shared memory files
      net/bonding: fix buffer length when printing strings
      devtools: skip meson build for missing compilers
      devtools: support older compilers with meson test
      examples/l2fwd-cat: fix build on FreeBSD
      app/crypto-perf: check range of socket id
      examples/vhost_scsi: fix null-check for parameter
      net/i40e: fix dereference before null check in mbuf release
      net/i40e: fix dereference before check when getting EEPROM
      app/testpmd: fix variable use before null check
      crypto/snow3g: add to meson build
      crypto/kasumi: fix dependency check
      crypto/zuc: fix dependency check
      net/ixgbe: fix warning with GCC 9
      bus/fslmc: fix warning with GCC 9
      raw/skeleton: fix warnings with GCC 9
      raw/dpaa2_cmdif: fix warnings with GCC 9
      build: fix ninja install on FreeBSD

Chaitanya Babu Talluri (3):
      drivers/net: fix possible overflow using strlcat
      test/crypto: fix possible overflow using strlcat
      cfgfile: replace strcat with strlcat

Chas Williams (3):
      net/bonding: fix Tx in 802.3ad mode
      net/bonding: fix slave Tx burst for mode 4
      net/bonding: fix link status

Chenbo Xia (2):
      app/testpmd: fix return value check
      net/virtio-user: fix return value check

Darek Stojaczyk (1):
      eal: initialize alarms early

David Christensen (5):
      maintainers: update for IBM POWER
      examples/power: fix build with some disabled PMDs
      test/barrier: fix typo in log
      test/barrier: fix allocation check
      test/barrier: fix for Power CPUs

David Harton (1):
      net/ixgbe: restore VLAN filter for VF

David Hunt (5):
      power: fix governor storage to trim newlines
      examples/power: fix resource leak
      examples/power: fix unreachable VF MAC init
      examples/power: fix buffer overrun
      examples/power: fix json null termination

David Marchand (19):
      eal: fix check when retrieving current CPU affinity
      eal: fix control threads pinnning
      eal: restrict control threads to startup CPU affinity
      eal: remove dead code in core list parsing
      eal: fix core list validation with disabled cores
      app/testpmd: remove unused field from port struct
      doc: fix examples in bonding guide
      net/bonding: fix port id types
      net/bonding: fix slave id types
      net/bonding: fix packet count type for LACP
      net/bonding: fix queue index types
      app/testpmd: add missing newline when showing statistics
      app/testpmd: extend forwarding statistics to 64 bits
      app/testpmd: remove useless casts on statistics
      doc: fix ABI check script examples
      test: clean remaining trace of devargs autotest
      devtools: fix symbol name in check log
      devtools: accept experimental symbol promotion
      devtools: fix check of symbol added as stable API

Davide Caratti (1):
      net/bnxt: support IOVA VA mode

Dekel Peled (13):
      net/mlx5: fix Tx metadata for multi-segment packet
      net/mlx5: fix hex dump of error completion
      net/mlx5: fix sync when handling Tx completions
      eal/ppc: fix global memory barrier
      eal: fix typo in comment of vector function
      doc: fix links to doxygen and sphinx sites
      net/mlx5: fix errno typos in comments
      doc: fix typos in mlx5 guide
      doc: fix typos in testpmd user guide
      app/testpmd: fix typo in comment
      ethdev: fix typo in error messages
      net/mlx5: fix comments mixing Rx and Tx
      net/mlx5: fix release of Rx queue object

Dharmik Thakkar (2):
      hash: fix position returned in free slots
      hash: fix total entries count

Erik Gabriel Carrillo (1):
      eventdev: update references to removed function

Fan Zhang (3):
      examples/ipsec-secgw: fix AES-CTR block size
      vhost/crypto: fix parens
      crypto/virtio: fix IV offset

Ferruh Yigit (6):
      kni: fix build with Linux 5.1
      mbuf: update Tx VLAN and QinQ flags documentation
      build: fix meson binutils workaround
      build: fix crash by disabling AVX512 with binutils 2.31
      net/ring: fix return value check
      net/kni: fix return value check

Fiona Trahe (2):
      doc: fix missing asymmetric crypto table
      crypto/qat: fix null cipher algo for non 8-byte multiple

Gagandeep Singh (6):
      crypto/caam_jr: fix shared descriptor endianness
      crypto/caam_jr: fix total length in auth only s/g
      crypto/caam_jr: fix memory leak and illegal access
      net/enetc: fix SMMU unhandled context fault
      net/enetc: fix big endian build and buffer allocation
      net/enetc: fix crash at high speed traffic

Gage Eads (2):
      app/pdump: remove only created vdevs
      ring: fix namesize macro documentation block

Gavin Hu (4):
      ring: enforce reading tail before slots
      test/spinlock: remove delay for correct benchmarking
      test/spinlock: amortize the cost of getting time
      spinlock: reimplement with atomic one-way barrier

Hari Kumar Vemula (1):
      net/bonding: fix values of descriptor limits

Harry van Haaren (1):
      event/sw: fix enqueue checks in self-test

Hemant Agrawal (3):
      mempool/dpaa2: fix continuous print on empty pool
      test/crypto: fix duplicate id used by CCP device
      raw/dpaa2_qdma: fix spin lock release

Herakliusz Lipiec (5):
      net/tap: fix multi process reply buffer
      ipc: fix memory leak on request failure
      net/tap: fix memory leak on IPC request
      net/tap: fix potential IPC buffer overrun
      doc: fix broken link in LPM guide

Hyong Youb Kim (12):
      net/bonding: avoid warning for invalid port
      net/enic: fix flow director SCTP matching
      net/enic: fix SCTP match for flow API
      net/enic: allow flow mark ID 0
      net/enic: check for unsupported flow item types
      net/enic: reset VXLAN port regardless of overlay offload
      net/enic: fix VXLAN match
      net/enic: fix endianness in VLAN match
      net/enic: fix max MTU calculation
      net/enic: move arguments into struct
      net/enic: fix inner packet matching
      net/enic: fix VLAN inner type matching for old hardware

Igor Romanov (4):
      app/testpmd: fix stdout flush after printing stats
      net/sfc: improve TSO header length check in EFX datapath
      net/sfc: improve TSO header length check in EF10 datapath
      net/sfc: fix MTU change to check Rx scatter consistency

Igor Russkikh (11):
      net/atlantic: fix negative error codes
      net/atlantic: remove unused variable
      net/atlantic: remove extra checks for error codes
      net/atlantic: fix link configuration
      net/atlantic: fix missing VLAN filter offload
      net/atlantic: fix xstats return
      net/atlantic: enable broadcast traffic
      net/atlantic: extra line at eof
      net/atlantic: fix max eeprom size
      net/atlantic: validity check for eeprom dev address
      net/atlantic: eliminate excessive log levels on Rx/Tx

Ilya Maximets (4):
      net/virtio: add barriers for extra descriptors on Rx split
      vhost: fix device leak on connection add failure
      vhost: fix passing destroyed device to destroy callback
      vhost: fix silent queue enabling with legacy guests

Ivan Malov (1):
      net/sfc: log port ID as 16-bit unsigned integer on panic

Jens Freimann (1):
      net/virtio: set offload flag for jumbo frames

Jerin Jacob (3):
      mk: fix AVX512 disabled warning on non x86
      build: remove meson warning for Arm
      table: fix arm64 hash function selection

Jiayu Hu (1):
      vhost: fix interrupt suppression for the split ring

Jie Pan (1):
      kni: fix type for MAC address

John McNamara (2):
      doc: fix spelling reported by aspell in guides
      doc: fix spelling reported by aspell in comments

Joyce Kong (2):
      doc: update cross Arm toolchain in Linux guide
      rwlock: reimplement with atomic builtins

Julien Meunier (1):
      test/pmd_perf: fix the way to drain the port

Kevin Traynor (5):
      net/qede: support IOVA VA mode
      eal/linux: fix log levels for pagemap reading failure
      doc: fix formatting in testpmd guide
      bus/fslmc: fix warning with GCC 9
      mk: disable packed member pointer warning for telemetry

Konstantin Ananyev (1):
      examples/ipsec-secgw: fix SPD no-match case

Krzysztof Kanas (1):
      test/bonding: fix MAC assignment for re-run

Li Qiang (1):
      raw/ifpga: fix file descriptor leak in error path

Liang Zhang (1):
      net/bonding: fix LACP negotiation

Luca Boccassi (1):
      build: use default flags for default Arm machine

Lukasz Krakowiak (1):
      doc: fix JSON interface for power sample

Marcin Hajkowski (1):
      power: fix thread-safety environment modification

Marcin Smoczynski (1):
      examples/ipsec-secgw: fix build error log

Mark Gillott (1):
      net/vmxnet3: add VLAN filter capability

Marko Kovacevic (2):
      compress/qat: fix setup inter buffers
      examples/fips_validation: fix CMAC test

Mattias Rönnblom (3):
      event/dsw: fix capability flags
      power: fix cache line alignment
      event/dsw: ignore scheduling type for single-link queues

Maxime Coquelin (1):
      vhost: prevent disabled rings to be processed with zero-copy

Michael Santana (2):
      devtools: fix result of svg include check
      ci: introduce Travis builds for GitHub repositories

Mohammad Abdul Awal (1):
      vhost: fix null pointer checking

Natanael Copa (7):
      eal/linux: remove thread ID from debug message
      bus/fslmc: remove unused include of error.h
      bus/fslmc: fix build with musl libc
      net/nfp: fix build with musl libc
      net/netvsc: fix include of fcntl.h
      app/test: fix flags with meson
      app/test: fix build with musl libc

Nikhil Rao (1):
      eventdev: fix Rx adapter event flush

Nithin Dabilpuram (2):
      app/testpmd: fix Tx VLAN and QinQ dependency
      app/testpmd: fix Tx QinQ set

Oleg Polyakov (1):
      net/tap: fix getting max iovec

Ori Kam (1):
      net/mlx5: fix RSS validation function

Pablo Cascón (1):
      net/nfp: fix setting MAC address

Pablo de Lara (1):
      doc: add missing algorithms for AESNI-MB PMD

Pallantla Poornima (10):
      vhost: fix sprintf with snprintf
      net/softnic: fix possible buffer overflow
      event/opdl: replace sprintf with snprintf
      net/nfp: fix possible buffer overflow
      app/test: fix sprintf with strlcat
      test/event: replace sprintf with snprintf
      power: remove unused variable
      test/distributor: replace sprintf with strlcpy
      test/hash: replace sprintf with snprintf
      app/bbdev: replace sprintf with snprintf or strlcpy

Pavel Belous (7):
      net/atlantic: fix buffer overflow
      net/atlantic: fix EEPROM get for small and uneven lengths
      net/atlantic: error handling for mailbox access
      net/atlantic: eeprom get/set should consider offset
      net/atlantic: bad logic with offsets talking with firmware
      net/atlantic: flow control settings synchronization on rx
      net/atlantic: use capability bits to detect eeprom access

Qi Zhang (3):
      net/pcap: fix memory leak
      net/i40e: fix time sync for 25G
      net/i40e: fix scattered Rx enabling

Qiming Yang (1):
      net/iavf: fix info get

Rahul Lakkireddy (1):
      net/cxgbe: update Chelsio T5/T6 NIC device ids

Rami Rosen (11):
      net/virtio: remove forward declaration
      mbuf: fix a typo
      doc: fix a minor typo in testpmd guide
      doc: remove reference to rte.doc.mk in programmers guide
      examples/ethtool: fix two typos
      doc: fix link in Linux getting started guide
      doc: fix tag for inner RSS feature
      app/testpmd: fix a typo in log message
      ethdev: fix method name in doxygen comment
      ethdev: fix a typo
      doc: fix two typos in contributing guide

Rasesh Mody (3):
      net/bnx2x: fix MTU for jumbo frame
      net/bnx2x: fix race for periodic flags
      net/bnx2x: fix optic module verification

Raslan Darawsheh (2):
      net/tap: fix multi-process request
      bus/vdev: fix hotplug twice

Reshma Pattan (4):
      examples/power: fix string null termination
      examples/power: fix string overflow
      examples/power: fix overflowed value
      mk: disable warning for packed member pointer

Shahaf Shuler (3):
      net/mlx5: fix packet inline on Tx queue wraparound
      mem: limit use of address hint
      app/testpmd: fix mempool free on exit

Shahed Shaikh (6):
      net/qede: fix Tx packet prepare for tunnel packets
      net/qede: fix Rx packet drop
      doc: add flow API to qede NIC features
      net/bnx2x: fix memory leak
      net/bnx2x: fix ramrod timeout
      net/bnx2x: fix DMAE timeout

Shreyansh Jain (2):
      bus/dpaa: fix Rx discard register mask
      raw/dpaa2_qdma: fix to support multiprocess execution

Somnath Kotur (1):
      net/bnxt: fix big endian build

Stephen Hemminger (26):
      crypto/virtio: use local log type
      net/bnxt: silence IOVA warnings
      net/bnxt: suppress spurious error log
      net/octeontx: fix vdev name
      drivers: fix SPDX license id consistency
      bus/vmbus: fix secondary process setup
      net/netvsc: fix VF support with secondary process
      bus/vmbus: fix check for mmap failure
      bus/vmbus: stop mapping if empty resource found
      bus/vmbus: map ring in secondary process
      bus/fslmc: decrease log level for unsupported devices
      net/vdev_netvsc: fix device cast
      net/bnxt: fix Rx VLAN offload flags
      net/netvsc: remove useless condition
      net/virtio: remove useless condition
      ring: fix an error message
      doc: fix spelling in testpmd guide
      net/virtio: fix buffer leak on VLAN insert
      net/cxgbe: fix colliding function names
      bus/vmbus: fix resource leak on error
      eal: fix formatting of hotplug error message
      net/ring: fix coding style
      net/ring: avoid hard-coded length
      net/ring: use calloc style where appropriate
      net/ring: check length of ring name
      net/netvsc: reset mbuf port on VF Rx

Thomas Monjalon (9):
      ethdev: remove unused variable
      mk: fix build of shared library with libbsd
      devtools: add libelf dependency to build test
      devtools: test build of zlib PMD
      devtools: fix test of some build options
      net/mlx: prefix private structure
      doc: fix PCI whitelist typo in prog guide
      bus/vdev: fix debug message on probing
      doc: fix heading levels in bbdev test guide

Tiwei Bie (8):
      net/virtio: fix in-order Tx path for split ring
      vhost: restore mbuf first when freeing zmbuf
      vhost: fix potential use-after-free for zero copy mbuf
      vhost: fix potential use-after-free for memory region
      net/virtio-user: fix multiqueue with vhost kernel
      net/virtio: add barrier in interrupt enable
      net/virtio-user: fix multi-process support
      app/testpmd: fix unintentional integer overflow

Tomasz Cel (2):
      compress/isal: fix compression stream initialization
      compress/isal: fix getting information about CPU

Tomasz Jozwiak (1):
      drivers/qat: fix queue pair NUMA node

Viacheslav Ovsiienko (3):
      net/mlx5: fix flow priorities probing error path
      net/mlx5: fix memory region cleanup
      net/mlx4: fix memory region cleanup

Vishal Kulkarni (1):
      net/cxgbe: fix missing checksum flags and packet type

Wei Zhao (5):
      net/avf: fix admin queue interrupt for ICE
      net/i40e: log when provided RSS key is not valid
      app/testpmd: fix hex string parser support for flow API
      net/i40e: fix queue number check
      app/testpmd: fix offload flags after port config

Xiao Wang (1):
      net/fm10k: fix VLAN strip offload flag

Yipeng Wang (1):
      hash: fix doc about thread/process safety

Yongseok Koh (11):
      net/mlx5: fix memory event on secondary process
      net/mlx4: change device reference for secondary process
      net/mlx: remove debug messages on datapath
      net/mlx5: fix external memory registration
      drivers/event: disable OcteonTx for buggy Arm compilers
      net/mlx5: fix instruction hotspot on replenishing Rx buffer
      examples/multi_process: fix buffer underrun
      net/mlx5: check Tx queue size overflow
      net/mlx5: fix max number of queues for NEON Tx
      net/mlx5: fix Multi-Packet RQ mempool name
      doc: fix typo in mlx5 guide

^ permalink raw reply	[relevance 1%]

* Re: [dpdk-dev] [RFC] ethdev: enhance metadata as flow rule criteria
  @ 2019-06-03 21:44  0% ` Yongseok Koh
  0 siblings, 0 replies; 200+ results
From: Yongseok Koh @ 2019-06-03 21:44 UTC (permalink / raw)
  To: Adrien Mazarguil; +Cc: dev, Moti Haimovsky

This has been overridden by another RFC.
http://patches.dpdk.org/project/dpdk/list/?series=4875


Thanks,
Yongseok

> On May 16, 2019, at 8:31 AM, Moti Haimovsky <motih@mellanox.com> wrote:
> 
> Current implementation of rte_flow metadata match sets metadata only
> for egress traffic leaving the need for such feature in ingress
> flows unsatisfied and the lack of metadata index or ID limits it to
> a single metadata action and match per flow which is a drawback in
> several scenarios we would like to address.
> 
> This RFC proposes an enhancement of the existing implementation of
> "[RFC,v2] ethdev: support metadata as flow rule criteria" without
> breaking the API or ABI of the existing implementation.
> We will do so by introducing new metadata item 'RTE_FLOW_ITEM_METADATA'
> with a corresponding 'rte_flow_item_metadata' data structure,
> and a new metadata action 'RTE_FLOW_ACTION_TYPE_SET_METADATA' with
> a corresponding 'rte_flow_action_set_metadata' data structure.
> 
> These new action and item will be super-set of the existing
> implementation allowing us to deprecate it later on.
> 
> Application will set and match on the new metadata action and item
> respectively via the standard rte_flow rules, letting the PMD to worry
> about the implementation details.
> 
> For example suppose an ingress flow packet has to traverse several
> flow-groups before reaching its destination (fate), during this
> traversal the packet may be changed several times by the flow rules,
> like encap or decap headers, mac address modification, etc. making
> the primary match on the packet header useless. How will we track the
> flow making sure that the correct rules are applied to it ?
> We can do so by setting a unique flow ID to each flow, setting the
> metadata of each packet in that flow to that value, and now the rest
> of the flow table will match on this unique value.
> testpmd commands for such flow could look like:
> 
> testpmd> flow create 0 ingress pattern eth ... / end actions
>         set_meta_data id 1 data 5 / vxlan_decap / jump group 1 / end
> 
> testpmd> flow create 0 ingress group 1 pattern metadata id is 1 data
>         is 5 / end actions .... / end
> 
> Comments are welcome.
> 
> Signed-off-by: Moti Haimovsky <motih@mellanox.com>
> ---
> app/test-pmd/cmdline_flow.c        | 68 ++++++++++++++++++++++++++++++++++++++
> doc/guides/prog_guide/rte_flow.rst | 50 ++++++++++++++++++++++++++++
> lib/librte_ethdev/rte_flow.c       |  3 ++
> lib/librte_ethdev/rte_flow.h       | 61 ++++++++++++++++++++++++++++++++++
> 4 files changed, 182 insertions(+)
> 
> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> index 3070e0e..d10f511 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -181,6 +181,9 @@ enum index {
> 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
> 	ITEM_META,
> 	ITEM_META_DATA,
> +	ITEM_METADATA,
> +	ITEM_METADATA_ID,
> +	ITEM_METADATA_DATA,
> 
> 	/* Validate/create actions. */
> 	ACTIONS,
> @@ -272,6 +275,9 @@ enum index {
> 	ACTION_SET_MAC_SRC_MAC_SRC,
> 	ACTION_SET_MAC_DST,
> 	ACTION_SET_MAC_DST_MAC_DST,
> +	ACTION_SET_METADATA,
> +	ACTION_SET_METADATA_ID,
> +	ACTION_SET_METADATA_DATA,
> };
> 
> /** Maximum size for pattern in struct rte_flow_item_raw. */
> @@ -610,6 +616,7 @@ struct parse_action_priv {
> 	ITEM_ICMP6_ND_OPT_SLA_ETH,
> 	ITEM_ICMP6_ND_OPT_TLA_ETH,
> 	ITEM_META,
> +	ITEM_METADATA,
> 	ZERO,
> };
> 
> @@ -836,6 +843,13 @@ struct parse_action_priv {
> 	ZERO,
> };
> 
> +static const enum index item_metadata[] = {
> +	ITEM_METADATA_ID,
> +	ITEM_METADATA_DATA,
> +	ITEM_NEXT,
> +	ZERO,
> +};
> +
> static const enum index next_action[] = {
> 	ACTION_END,
> 	ACTION_VOID,
> @@ -885,6 +899,7 @@ struct parse_action_priv {
> 	ACTION_SET_TTL,
> 	ACTION_SET_MAC_SRC,
> 	ACTION_SET_MAC_DST,
> +	ACTION_SET_METADATA,
> 	ZERO,
> };
> 
> @@ -1047,6 +1062,14 @@ struct parse_action_priv {
> 	ZERO,
> };
> 
> +static const enum index action_set_metadata[] = {
> +	ACTION_SET_METADATA,
> +	ACTION_SET_METADATA_ID,
> +	ACTION_SET_METADATA_DATA,
> +	ACTION_NEXT,
> +	ZERO,
> +};
> +
> static int parse_init(struct context *, const struct token *,
> 		      const char *, unsigned int,
> 		      void *, unsigned int);
> @@ -2147,6 +2170,27 @@ static int comp_vc_action_rss_queue(struct context *, const struct token *,
> 		.name = "data",
> 		.help = "metadata value",
> 		.next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
> +					     data, "\xff\xff\xff\xff")),
> +	},
> +	[ITEM_METADATA] = {
> +		.name = "metadata",
> +		.help = "match on metadata info",
> +		.priv = PRIV_ITEM(METADATA,
> +				  sizeof(struct rte_flow_item_metadata)),
> +		.next = NEXT(item_metadata),
> +		.call = parse_vc,
> +	},
> +	[ITEM_METADATA_ID] = {
> +		.name = "id",
> +		.help = " device-specific location of metadata",
> +		.next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_metadata, id)),
> +	},
> +	[ITEM_METADATA_DATA] = {
> +		.name = "data",
> +		.help = "metadata data value",
> +		.next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param),
> 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_meta,
> 						  data, "\xff\xff\xff\xff")),
> 	},
> @@ -2854,6 +2898,30 @@ static int comp_vc_action_rss_queue(struct context *, const struct token *,
> 			     (struct rte_flow_action_set_mac, mac_addr)),
> 		.call = parse_vc_conf,
> 	},
> +	[ACTION_SET_METADATA] = {
> +		.name = "set_meta_data",
> +		.help = "attach metadata info to flow packets",
> +		.priv = PRIV_ACTION(SET_METADATA,
> +			sizeof(struct rte_flow_action_set_metadata)),
> +		.next = NEXT(action_set_metadata),
> +		.call = parse_vc,
> +	},
> +	[ACTION_SET_METADATA_ID] = {
> +		.name = "id",
> +		.help = "device-specific metadata id to use",
> +		.next = NEXT(action_set_metadata, NEXT_ENTRY(UNSIGNED)),
> +		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_metadata,
> +					id)),
> +		.call = parse_vc_conf,
> +	},
> +	[ACTION_SET_METADATA_DATA] = {
> +		.name = "data",
> +		.help = "data to use",
> +		.next = NEXT(action_set_metadata, NEXT_ENTRY(UNSIGNED)),
> +		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_metadata,
> +					data)),
> +		.call = parse_vc_conf,
> +	},
> };
> 
> /** Remove and return last entry from argument stack. */
> diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
> index 937f52b..743c357 100644
> --- a/doc/guides/prog_guide/rte_flow.rst
> +++ b/doc/guides/prog_guide/rte_flow.rst
> @@ -1210,6 +1210,30 @@ Matches an application specific 32 bit metadata item.
>    | ``mask`` | ``data`` | bit-mask applies to "spec" and "last" |
>    +----------+----------+---------------------------------------+
> 
> +Item: ``METADATA``
> +^^^^^^^^^^^^^^^^^^
> +
> +Matches an application specific 32 bit metadata item present in the specified
> +location of a device-specific, per-packet metadata information.
> +This information is set either by a ``METADATA`` action in a previously matched
> +rule or by the device hardware itself.
> +
> +This item may be specified several times as a match criteria on several metadata
> +fields.
> +
> +Note the value of the data field is arbitrary and is PMD or application defined.
> +The value of the id field is device-dependent.
> +
> +Depending on the underlying implementation the METADATA item may be supported
> +as a set of registers or a memory region on the physical device,
> +with virtual groups in the PMD or not supported at all.
> +
> +- ``id``: The metadata field id to match.
> +- ``data``: The data to match against.
> +
> +- Default ``mask`` matches the specified integer value in the specified
> +  metadata location.
> +
> Actions
> ~~~~~~~
> 
> @@ -1476,6 +1500,32 @@ sets the ``PKT_RX_FDIR`` mbuf flag.
>    | no properties |
>    +---------------+
> 
> +Action: ``METADATA``
> +^^^^^^^^^^^^^^^^^^^^
> +
> +Insetrs a 32 bit integer value in the specified location of a device-specific
> +metadata information attached to each packet of a flow.
> +
> +This value is arbitrary and is application or PMD defined.
> +Maximum allowed value depends on the underlying implementation.
> +
> +Depending on the underlying implementation the METADATA action may be supported
> +as a set of registers or a memory region on the physical device, with virtual
> +groups in the PMD or not supported at all.
> +
> +.. _table_rte_flow_action_metadata:
> +
> +.. table:: METADATA
> +
> +   +----------+-----------------------------------------------------------+
> +   | Field    | Value                                                     |
> +   +==========+===========================================================+
> +   | ``id``   | unsigned integer value indicating where to write the data |
> +   |          | in the metadata info.                                     |
> +   +----------+-----------------------------------------------------------+
> +   | ``data`` | unsigned integer value of data to write                   |
> +   +----------+-----------------------------------------------------------+
> +
> Action: ``QUEUE``
> ^^^^^^^^^^^^^^^^^
> 
> diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c
> index 3277be1..ea2b9a0 100644
> --- a/lib/librte_ethdev/rte_flow.c
> +++ b/lib/librte_ethdev/rte_flow.c
> @@ -74,6 +74,7 @@ struct rte_flow_desc_data {
> 		     sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
> 	MK_FLOW_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
> 	MK_FLOW_ITEM(META, sizeof(struct rte_flow_item_meta)),
> +	MK_FLOW_ITEM(METADATA, sizeof(struct rte_flow_item_metadata)),
> };
> 
> /** Generate flow_action[] entry. */
> @@ -143,6 +144,8 @@ struct rte_flow_desc_data {
> 	MK_FLOW_ACTION(SET_TTL, sizeof(struct rte_flow_action_set_ttl)),
> 	MK_FLOW_ACTION(SET_MAC_SRC, sizeof(struct rte_flow_action_set_mac)),
> 	MK_FLOW_ACTION(SET_MAC_DST, sizeof(struct rte_flow_action_set_mac)),
> +	MK_FLOW_ACTION(SET_METADATA,
> +		       sizeof(struct rte_flow_action_set_metadata)),
> };
> 
> static int
> diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
> index 63f84fc..801831f 100644
> --- a/lib/librte_ethdev/rte_flow.h
> +++ b/lib/librte_ethdev/rte_flow.h
> @@ -421,6 +421,15 @@ enum rte_flow_item_type {
> 	 * See struct rte_flow_item_meta.
> 	 */
> 	RTE_FLOW_ITEM_TYPE_META,
> +
> +	/**
> +	 * [METADATA]
> +	 *
> +	 * Matches a metadata value specified in device-specific metadata field
> +	 * attached to each flow.
> +	 * See struct rte_flow_item_metadata.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_METADATA,
> };
> 
> /**
> @@ -1183,6 +1192,33 @@ struct rte_flow_item_meta {
>  * @warning
>  * @b EXPERIMENTAL: this structure may change without prior notice
>  *
> + * RTE_FLOW_ITEM_TYPE_METADATA.
> + *
> + * Matches an arbitrary integer value in the device-specific per-flow metadata
> + * location identified by the given id.
> + * This data value may have been set using the `METADATA` action in a previously
> + * matched rule or by the underlying hardware itself.
> + *
> + * The offset field is device-specific and its interpretation may change
> + * according to the device in use and its current configuration.
> + */
> +struct rte_flow_item_metadata {
> +	uint32_t id;
> +	rte_be32_t data;
> +};
> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_METADATA. */
> +#ifndef __cplusplus
> +static const struct rte_flow_item_metadata rte_flow_item_metadata_mask = {
> +	.id = UINT32_MAX,
> +	.data = RTE_BE32(UINT32_MAX),
> +};
> +#endif
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this structure may change without prior notice
> + *
>  * RTE_FLOW_ITEM_TYPE_MARK
>  *
>  * Matches an arbitrary integer value which was set using the ``MARK`` action
> @@ -1650,6 +1686,14 @@ enum rte_flow_action_type {
> 	 * See struct rte_flow_action_set_mac.
> 	 */
> 	RTE_FLOW_ACTION_TYPE_SET_MAC_DST,
> +
> +	/**
> +	 * Attaches an integer value to device-specific metadata info attached
> +	 * to each packet in a flow.
> +	 *
> +	 * See struct rte_flow_action_set_metadata.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_SET_METADATA,
> };
> 
> /**
> @@ -2131,6 +2175,23 @@ struct rte_flow_action_set_mac {
> 	uint8_t mac_addr[ETHER_ADDR_LEN];
> };
> 
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this structure may change without prior notice
> + *
> + * RTE_FLOW_ACTION_TYPE_SET_METADATA.
> + *
> + * Attaches an integer value to device-specific metadata info attached
> + * to each packet in a flow.
> + *
> + * The offset field is device-specific and its interpretation may change
> + * according to the device in use and its current configuration.
> + */
> +struct rte_flow_action_set_metadata {
> +	uint32_t id;
> +	rte_be32_t data;
> +};
> +
> /*
>  * Definition of a single action.
>  *
> -- 
> 1.8.3.1
> 


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v5 0/5] make lcore_config internal
  2019-06-03 10:32  0%   ` Thomas Monjalon
@ 2019-06-03 20:15  0%     ` Stephen Hemminger
  0 siblings, 0 replies; 200+ results
From: Stephen Hemminger @ 2019-06-03 20:15 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: David Marchand, dev, bruce.richardson

On Mon, 03 Jun 2019 12:32:02 +0200
Thomas Monjalon <thomas@monjalon.net> wrote:

> 31/05/2019 17:36, David Marchand:
> > This set of patches makes the lcore_config structure less visible
> > as part of the ABI.  This version does not break the ABI (yet)
> > follow on patch moves lcore_config into eal_private.h
> > 
> > Changelog since v4:
> > The only change is in patch 2: marked new apis as experimental.
> > 
> > Changelog since v3:
> > I took the liberty of taking over Stephen series.
> > I rebased and did some adjustments following [1] cleanups.
> > As stated before, we will still need a deprecation notice when hiding
> > lcore_config but this series does not break API nor ABI.
> > 
> > Changelog since v2:
> >  - new patch to use unsigned int in lcore.h first
> >  - incorporate feedback from David
> >  - don't include last patch to make it private
> >         (to avoid accidental early merge)  
> 
> Applied, thanks
> 
> 

Thanks. Now to get to eal_config

^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [PATCH] cryptodev: add ff_disable field in cryptodev config
@ 2019-06-03 15:25  5% Anoob Joseph
  2019-06-25  5:39  4% ` [dpdk-dev] [PATCH v2] " Anoob Joseph
  0 siblings, 1 reply; 200+ results
From: Anoob Joseph @ 2019-06-03 15:25 UTC (permalink / raw)
  To: Akhil Goyal, Declan Doherty, Fiona Trahe, Pablo de Lara, dev
  Cc: Anoob Joseph, Jerin Jacob, Narayana Prasad

Adding a new field, ff_disable, to allow applications to control the
features enabled on the crypto device. This would allow for efficient
usage of HW/SW offloads by disabling the features not required by the
application.

Signed-off-by: Anoob Joseph <anoobj@marvell.com>
---
 doc/guides/rel_notes/deprecation.rst   | 14 --------------
 doc/guides/rel_notes/release_19_08.rst | 11 ++++++++++-
 lib/librte_cryptodev/Makefile          |  2 +-
 lib/librte_cryptodev/meson.build       |  2 +-
 lib/librte_cryptodev/rte_cryptodev.h   |  7 +++++++
 5 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 098d243..ea1d7b7 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -75,20 +75,6 @@ Deprecation Notices
   kernel modules in DPDK. As a result users won't be able to use ``ethtool``
   via ``igb`` & ``ixgbe`` anymore.
 
-* cryptodev: New member in ``rte_cryptodev_config`` to allow applications to
-  disable features supported by the crypto device. Only the following features
-  would be allowed to be disabled this way,
-
-  - ``RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO``
-  - ``RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO``
-  - ``RTE_CRYPTODEV_FF_SECURITY``
-
-  Disabling unused features would facilitate efficient usage of HW/SW offload.
-
-  - Member ``uint64_t ff_disable`` in ``rte_cryptodev_config``
-
-  The field would be added in v19.08.
-
 * cryptodev: the ``uint8_t *data`` member of ``key`` structure in the xforms
   structure (``rte_crypto_cipher_xform``, ``rte_crypto_auth_xform``, and
   ``rte_crypto_aead_xform``) will be changed to ``const uint8_t *data``.
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index b9510f9..205733d 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -99,6 +99,15 @@ ABI Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* cryptodev: New member in ``rte_cryptodev_config`` to allow applications to
+  disable features supported by the crypto device. Only the following features
+  would be allowed to be disabled this way,
+
+  - ``RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO``
+  - ``RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO``
+  - ``RTE_CRYPTODEV_FF_SECURITY``
+
+  Disabling unused features would facilitate efficient usage of HW/SW offload.
 
 Shared Library Versions
 -----------------------
@@ -130,7 +139,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_cfgfile.so.2
      librte_cmdline.so.2
      librte_compressdev.so.1
-     librte_cryptodev.so.7
+   + librte_cryptodev.so.8
      librte_distributor.so.1
      librte_eal.so.10
      librte_efd.so.1
diff --git a/lib/librte_cryptodev/Makefile b/lib/librte_cryptodev/Makefile
index c20e090..55d352a 100644
--- a/lib/librte_cryptodev/Makefile
+++ b/lib/librte_cryptodev/Makefile
@@ -7,7 +7,7 @@ include $(RTE_SDK)/mk/rte.vars.mk
 LIB = librte_cryptodev.a
 
 # library version
-LIBABIVER := 7
+LIBABIVER := 8
 
 # build flags
 CFLAGS += -O3
diff --git a/lib/librte_cryptodev/meson.build b/lib/librte_cryptodev/meson.build
index 9e009d4..0a2275d 100644
--- a/lib/librte_cryptodev/meson.build
+++ b/lib/librte_cryptodev/meson.build
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017-2019 Intel Corporation
 
-version = 7
+version = 8
 allow_experimental_apis = true
 sources = files('rte_cryptodev.c', 'rte_cryptodev_pmd.c')
 headers = files('rte_cryptodev.h',
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index 2d4f6d7..58bfab5 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -612,6 +612,13 @@ struct rte_cryptodev_config {
 	int socket_id;			/**< Socket to allocate resources on */
 	uint16_t nb_queue_pairs;
 	/**< Number of queue pairs to configure on device */
+	uint64_t ff_disable;
+	/**< Feature flags to be disabled. Only the following features are
+	 * allowed to be disabled,
+	 *  - RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO
+	 *  - RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO
+	 *  - RTE_CRYTPODEV_FF_SECURITY
+	 */
 };
 
 /**
-- 
2.7.4


^ permalink raw reply	[relevance 5%]

* Re: [dpdk-dev] [PATCH v5 0/5] make lcore_config internal
  2019-05-31 15:36  4% ` [dpdk-dev] [PATCH v5 0/5] make lcore_config internal David Marchand
@ 2019-06-03 10:32  0%   ` Thomas Monjalon
  2019-06-03 20:15  0%     ` Stephen Hemminger
  0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2019-06-03 10:32 UTC (permalink / raw)
  To: David Marchand, stephen; +Cc: dev, bruce.richardson

31/05/2019 17:36, David Marchand:
> This set of patches makes the lcore_config structure less visible
> as part of the ABI.  This version does not break the ABI (yet)
> follow on patch moves lcore_config into eal_private.h
> 
> Changelog since v4:
> The only change is in patch 2: marked new apis as experimental.
> 
> Changelog since v3:
> I took the liberty of taking over Stephen series.
> I rebased and did some adjustments following [1] cleanups.
> As stated before, we will still need a deprecation notice when hiding
> lcore_config but this series does not break API nor ABI.
> 
> Changelog since v2:
>  - new patch to use unsigned int in lcore.h first
>  - incorporate feedback from David
>  - don't include last patch to make it private
>         (to avoid accidental early merge)

Applied, thanks



^ permalink raw reply	[relevance 0%]

* [dpdk-dev] [RFC 1/5] security: MACSEC infrastructure data declarations
@ 2019-05-31 16:14  2% Igor Russkikh
  0 siblings, 0 replies; 200+ results
From: Igor Russkikh @ 2019-05-31 16:14 UTC (permalink / raw)
  To: dev
  Cc: ferruh.yigit, Pavel Belous, John McNamara, Konstantin Ananyev,
	Thomas Monjalon, Akhil Goyal, Declan Doherty, Igor Russkikh

This RFC suggest possible API to implement generic MACSEC HW
offload in DPDK infrastructure.

Right now two PMDs implementing MACSEC hw offload via private
API: ixgbe (Intel) and atlantic (Aquantia).

During that private API discussion it was decided to go further
with well defined public API, based most probably on rte_security
infrastructure.

Here is that previous discussion:

http://inbox.dpdk.org/dev/20190416101145.nVecHKp3w14Ptd_hne-DqHhKyzbre88PwNI-OAowXJM@z/

Declaring macsec API via rte_security gives a good data-centric view on parameters
and operations macsec supports. Old, pure functional API (basically ixbe only API)
presented function calls with big argument lists which is hard to extend and analyse.

However, I'd like to note rte_security has to be used via explicitly created
mempools - this hardens abit the usage.
It also may be hard to extend the structures in the ABI compatible way.

One of the problems with MACSEC is that internally implementation and hardware
support could be either very simple, doing only endpoint encryption with a single
TX SC (Secure Connection), or quite complex, capable to do flexible filtering
and SC matching based on mac, vlan, ethertype and other.

Different macsec hardware supports some custom features and from our experience
users would like to configure these as well. Therefore there will probably be
needed a number of PMD specific macsec operators support.

Examples include: custom in-the-clear tag (matched by vlan id or mask),
configurable internal logic to allow both secure and unsecure traffic,
bypass filters on specific ethertypes.
To support such extensions, suggest use rte_security_macsec_op enum with
vendor specific operation codes.

In context of rte_security, MACSEC operations should normally be based on
security session create and update calls.

Session create is used to setup overall session. Thats equivalent of old
`macsec enable` operation.

Session update is used to update security connections and associations.
Here xform->op contains the required operation: rx/tx session/association
add/update/removal.

This RFC contains:
- patch 1 is rte_security data structures declaration
- patches 2-4 is a draft on how testpmd based invocations of rte_security
  API will look like
- patch 5 is a draft on how PMD driver will implement security infrastructure

To be done/decide:
- testpmd macsec command layout changes: encryption and repl protection
  are properties of SC, not the overall connection.
- add missing documentation and comments to all the structures
- full testpmd macsec API adoption
- ixgbe api adoptation
- atlantic api adiptation
- decide on how to declare SA (Security Associations) auto rollover and
  some other important features.
- interrupt event callback detalization of possible macsec events.
  Notice that it is not a part of rte_security, but a part of rte_ethdev.
- macsec statistics is now part of xstats list. Alternatively it could be
  moved to rte_security statistics. The hard thing is that stats are
  often available per SC/SA, a special API is required to fetch that.

Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
 lib/librte_security/meson.build    |   2 +-
 lib/librte_security/rte_security.h | 115 ++++++++++++++++++++++++++++-
 2 files changed, 113 insertions(+), 4 deletions(-)

diff --git a/lib/librte_security/meson.build b/lib/librte_security/meson.build
index a5130d2f6d1e..10877d3ae544 100644
--- a/lib/librte_security/meson.build
+++ b/lib/librte_security/meson.build
@@ -4,4 +4,4 @@
 version = 2
 sources = files('rte_security.c')
 headers = files('rte_security.h', 'rte_security_driver.h')
-deps += ['mempool', 'cryptodev']
+deps += ['mempool', 'cryptodev', 'net']
diff --git a/lib/librte_security/rte_security.h b/lib/librte_security/rte_security.h
index 76f54e0e05bb..a3a9204fb62d 100644
--- a/lib/librte_security/rte_security.h
+++ b/lib/librte_security/rte_security.h
@@ -29,6 +29,7 @@ extern "C" {
 #include <rte_mbuf.h>
 #include <rte_memory.h>
 #include <rte_mempool.h>
+#include <rte_ether.h>
 
 /** IPSec protocol mode */
 enum rte_security_ipsec_sa_mode {
@@ -197,12 +198,87 @@ struct rte_security_ipsec_xform {
 	/**< ESN for which the overflow event need to be raised */
 };
 
+/**
+ * MACSEC global configuration parameters
+ *
+ */
+struct rte_security_macsec_param {
+	uint8_t enabled;
+};
+
+/**
+ * MACSEC SC (Secure Connection) parameters
+ *
+ */
+struct rte_security_macsec_txsc_param {
+	struct ether_addr s_mac;
+	/**< local side mac address */
+	struct ether_addr d_mac;
+	/**< remote side mac address */
+	uint32_t sci;
+	uint32_t tci;
+	uint8_t encrypt;
+	uint8_t protect;
+};
+
+struct rte_security_macsec_rxsc_param {
+	struct ether_addr s_mac, d_mac;
+	/**< remote side mac address */
+	uint8_t replay_protection;
+	/**< replay protection */
+	uint32_t anti_replay_window;
+	/**< anti replay window */
+	uint16_t port_ident;
+	/**< remote side port identifier */
+	uint8_t auto_rollover_enabled;
+};
+
+struct rte_security_macsec_sa_param {
+	uint8_t sa_idx;
+	uint8_t an;
+	uint32_t packet_number;
+	uint8_t key_len;
+	uint8_t key[32];
+};
+
+/**
+ * Available operations over MACSEC instance
+ */
+enum rte_security_macsec_op {
+	RTE_SECURITY_MACSEC_OP_CONFIG,
+
+	RTE_SECURITY_MACSEC_OP_ADD_TXSC,
+	RTE_SECURITY_MACSEC_OP_DEL_TXSC,
+	RTE_SECURITY_MACSEC_OP_UPD_TXSC,
+
+	RTE_SECURITY_MACSEC_OP_ADD_RXSC,
+	RTE_SECURITY_MACSEC_OP_DEL_RXSC,
+	RTE_SECURITY_MACSEC_OP_UPD_RXSC,
+
+	RTE_SECURITY_MACSEC_OP_ADD_TXSA,
+	RTE_SECURITY_MACSEC_OP_DEL_TXSA,
+	RTE_SECURITY_MACSEC_OP_UPD_TXSA,
+
+	RTE_SECURITY_MACSEC_OP_ADD_RXSA,
+	RTE_SECURITY_MACSEC_OP_DEL_RXSA,
+	RTE_SECURITY_MACSEC_OP_UPD_RXSA,
+
+	RTE_SECURITY_MACSEC_OP_STATS,
+
+	RTE_SECURITY_MACSEC_OP_VENDOR = 0x100,
+};
+
 /**
  * MACsec security session configuration
  */
 struct rte_security_macsec_xform {
-	/** To be Filled */
-	int dummy;
+	enum rte_security_macsec_op op;
+	union {
+		struct rte_security_macsec_param config_options;
+		struct rte_security_macsec_txsc_param txsc_options;
+		struct rte_security_macsec_rxsc_param rxsc_options;
+		struct rte_security_macsec_sa_param sa_options;
+	};
 };
 
 /**
@@ -467,7 +543,40 @@ rte_security_attach_session(struct rte_crypto_op *op,
 }
 
 struct rte_security_macsec_stats {
-	uint64_t reserved;
+	/* Ingress Common Counters */
+	uint64_t in_ctl_pkts;
+	uint64_t in_tagged_miss_pkts;
+	uint64_t in_untagged_miss_pkts;
+	uint64_t in_notag_pkts;
+	uint64_t in_untagged_pkts;
+	uint64_t in_bad_tag_pkts;
+	uint64_t in_no_sci_pkts;
+	uint64_t in_unknown_sci_pkts;
+	/* Ingress SA Counters */
+	uint64_t in_untagged_hit_pkts;
+	uint64_t in_not_using_sa;
+	uint64_t in_unused_sa;
+	uint64_t in_not_valid_pkts;
+	uint64_t in_invalid_pkts;
+	uint64_t in_ok_pkts;
+	uint64_t in_unchecked_pkts;
+	uint64_t in_validated_octets;
+	uint64_t in_decrypted_octets;
+	/* Egress Common Counters */
+	uint64_t out_ctl_pkts;
+	uint64_t out_unknown_sa_pkts;
+	uint64_t out_untagged_pkts;
+	uint64_t out_too_long;
+	/* Egress SC Counters */
+	uint64_t out_sc_protected_pkts;
+	uint64_t out_sc_encrypted_pkts;
+	uint64_t out_sc_protected_octets;
+	uint64_t out_sc_encrypted_octets;
+	/* Egress SA Counters */
+	uint64_t out_sa_hit_drop_redirect;
+	uint64_t out_sa_protected2_pkts;
+	uint64_t out_sa_protected_pkts;
+	uint64_t out_sa_encrypted_pkts;
 };
 
 struct rte_security_ipsec_stats {
-- 
2.17.1


^ permalink raw reply	[relevance 2%]

* [dpdk-dev] [PATCH v5 0/5] make lcore_config internal
    @ 2019-05-31 15:36  4% ` David Marchand
  2019-06-03 10:32  0%   ` Thomas Monjalon
  1 sibling, 1 reply; 200+ results
From: David Marchand @ 2019-05-31 15:36 UTC (permalink / raw)
  To: dev; +Cc: thomas, stephen, bruce.richardson

This set of patches makes the lcore_config structure less visible
as part of the ABI.  This version does not break the ABI (yet)
follow on patch moves lcore_config into eal_private.h

Changelog since v4:
The only change is in patch 2: marked new apis as experimental.

Changelog since v3:
I took the liberty of taking over Stephen series.
I rebased and did some adjustments following [1] cleanups.
As stated before, we will still need a deprecation notice when hiding
lcore_config but this series does not break API nor ABI.

Changelog since v2:
 - new patch to use unsigned int in lcore.h first
 - incorporate feedback from David
 - don't include last patch to make it private
        (to avoid accidental early merge)

1: http://patchwork.dpdk.org/patch/53621/

-- 
David Marchand

Stephen Hemminger (5):
  eal: use unsigned int in lcore API prototypes
  eal: add lcore accessors
  drivers/bus: use lcore accessors
  examples/bond: use lcore accessors
  test: use lcore accessors

 app/test/test_cryptodev.c                 |  2 +-
 app/test/test_ring_perf.c                 | 22 +++++++------
 app/test/test_stack_perf.c                | 20 ++++++------
 drivers/bus/dpaa/dpaa_bus.c               |  6 ++--
 drivers/bus/fslmc/portal/dpaa2_hw_dpio.c  |  4 ++-
 examples/bond/main.c                      | 13 ++++----
 lib/librte_eal/common/eal_common_lcore.c  | 33 ++++++++++++++++++++
 lib/librte_eal/common/include/rte_lcore.h | 52 ++++++++++++++++++++-----------
 lib/librte_eal/rte_eal_version.map        | 12 +++++++
 9 files changed, 116 insertions(+), 48 deletions(-)

-- 
1.8.3.1


^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH v4 2/5] eal: add lcore accessors
  2019-05-30 17:00  0%                 ` David Marchand
@ 2019-05-30 20:08  0%                   ` Bruce Richardson
  0 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2019-05-30 20:08 UTC (permalink / raw)
  To: David Marchand
  Cc: Thomas Monjalon, Stephen Hemminger, dev, Kevin Traynor,
	Neil Horman, Luca Boccassi

On Thu, May 30, 2019 at 07:00:36PM +0200, David Marchand wrote:
>    On Thu, May 30, 2019 at 3:39 PM Thomas Monjalon
>    <[1]thomas@monjalon.net> wrote:
> 
>      30/05/2019 12:11, Bruce Richardson:
>      > On Thu, May 30, 2019 at 09:40:08AM +0200, Thomas Monjalon wrote:
>      > > 30/05/2019 09:31, David Marchand:
>      > > > On Thu, May 30, 2019 at 12:51 AM Stephen Hemminger <
>      > > > [2]stephen@networkplumber.org> wrote:
>      > > >
>      > > > > On Thu, 30 May 2019 00:46:30 +0200
>      > > > > Thomas Monjalon <[3]thomas@monjalon.net> wrote:
>      > > > >
>      > > > > > 23/05/2019 15:58, David Marchand:
>      > > > > > > From: Stephen Hemminger <[4]stephen@networkplumber.org>
>      > > > > > >
>      > > > > > > The fields of the internal EAL core configuration are
>      currently
>      > > > > > > laid bare as part of the API. This is not good practice
>      and limits
>      > > > > > > fixing issues with layout and sizes.
>      > > > > > >
>      > > > > > > Make new accessor functions for the fields used by
>      current drivers
>      > > > > > > and examples.
>      > > > > > [...]
>      > > > > > > +DPDK_19.08 {
>      > > > > > > +   global:
>      > > > > > > +
>      > > > > > > +   rte_lcore_cpuset;
>      > > > > > > +   rte_lcore_index;
>      > > > > > > +   rte_lcore_to_cpu_id;
>      > > > > > > +   rte_lcore_to_socket_id;
>      > > > > > > +
>      > > > > > > +} DPDK_19.05;
>      > > > > > > +
>      > > > > > >  EXPERIMENTAL {
>      > > > > > >     global:
>      > > > > >
>      > > > > > Just to make sure, are we OK to introduce these functions
>      > > > > > as non-experimental?
>      > > > >
>      > > > > They were in previous releases as inlines this patch
>      converts them
>      > > > > to real functions.
>      > > > >
>      > > > >
>      > > > Well, yes and no.
>      > > >
>      > > > rte_lcore_index and rte_lcore_to_socket_id already existed, so
>      making them
>      > > > part of the ABI is fine for me.
>      > > >
>      > > > rte_lcore_to_cpu_id is new but seems quite safe in how it can
>      be used,
>      > > > adding it to the ABI is ok for me.
>      > >
>      > > It is used by DPAA and some test.
>      > > I guess adding as experimental is fine too?
>      > > I'm fine with both options, I'm just trying to apply the policy
>      > > we agreed on. Does this case deserve an exception?
>      > >
>      >
>      > While it may be a good candidate, I'm not sure how much making an
>      exception
>      > for it really matters. I'd be tempted to just mark it experimental
>      and then
>      > have it stable for the 19.11 release. What do we really lose by
>      waiting a
>      > release to stabilize it?
>      I would agree Bruce.
>      If no more comment, I will wait for a v5 of this series.
> 
>    I agree that there is no reason we make an exception for those 2 new
>    ones.
>    But to me the existing rte_lcore_index and rte_lcore_to_socket_id must
>    be marked as stable.
>    This is to avoid breaking existing users that did not set
>    ALLOW_EXPERIMENTAL_API.
>    I will prepare a v5 later.
>    --
Yes, agreed. Any existing APIs that were already present as static inlines
can go straight to stable when added to the .map file.

/Bruce

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 2/5] eal: add lcore accessors
  2019-05-30 13:39  0%               ` Thomas Monjalon
@ 2019-05-30 17:00  0%                 ` David Marchand
  2019-05-30 20:08  0%                   ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: David Marchand @ 2019-05-30 17:00 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: Bruce Richardson, Stephen Hemminger, dev, Kevin Traynor,
	Neil Horman, Luca Boccassi

On Thu, May 30, 2019 at 3:39 PM Thomas Monjalon <thomas@monjalon.net> wrote:

> 30/05/2019 12:11, Bruce Richardson:
> > On Thu, May 30, 2019 at 09:40:08AM +0200, Thomas Monjalon wrote:
> > > 30/05/2019 09:31, David Marchand:
> > > > On Thu, May 30, 2019 at 12:51 AM Stephen Hemminger <
> > > > stephen@networkplumber.org> wrote:
> > > >
> > > > > On Thu, 30 May 2019 00:46:30 +0200
> > > > > Thomas Monjalon <thomas@monjalon.net> wrote:
> > > > >
> > > > > > 23/05/2019 15:58, David Marchand:
> > > > > > > From: Stephen Hemminger <stephen@networkplumber.org>
> > > > > > >
> > > > > > > The fields of the internal EAL core configuration are currently
> > > > > > > laid bare as part of the API. This is not good practice and
> limits
> > > > > > > fixing issues with layout and sizes.
> > > > > > >
> > > > > > > Make new accessor functions for the fields used by current
> drivers
> > > > > > > and examples.
> > > > > > [...]
> > > > > > > +DPDK_19.08 {
> > > > > > > +   global:
> > > > > > > +
> > > > > > > +   rte_lcore_cpuset;
> > > > > > > +   rte_lcore_index;
> > > > > > > +   rte_lcore_to_cpu_id;
> > > > > > > +   rte_lcore_to_socket_id;
> > > > > > > +
> > > > > > > +} DPDK_19.05;
> > > > > > > +
> > > > > > >  EXPERIMENTAL {
> > > > > > >     global:
> > > > > >
> > > > > > Just to make sure, are we OK to introduce these functions
> > > > > > as non-experimental?
> > > > >
> > > > > They were in previous releases as inlines this patch converts them
> > > > > to real functions.
> > > > >
> > > > >
> > > > Well, yes and no.
> > > >
> > > > rte_lcore_index and rte_lcore_to_socket_id already existed, so
> making them
> > > > part of the ABI is fine for me.
> > > >
> > > > rte_lcore_to_cpu_id is new but seems quite safe in how it can be
> used,
> > > > adding it to the ABI is ok for me.
> > >
> > > It is used by DPAA and some test.
> > > I guess adding as experimental is fine too?
> > > I'm fine with both options, I'm just trying to apply the policy
> > > we agreed on. Does this case deserve an exception?
> > >
> >
> > While it may be a good candidate, I'm not sure how much making an
> exception
> > for it really matters. I'd be tempted to just mark it experimental and
> then
> > have it stable for the 19.11 release. What do we really lose by waiting a
> > release to stabilize it?
>
> I would agree Bruce.
> If no more comment, I will wait for a v5 of this series.
>

I agree that there is no reason we make an exception for those 2 new ones.

But to me the existing rte_lcore_index and rte_lcore_to_socket_id must be
marked as stable.
This is to avoid breaking existing users that did not set
ALLOW_EXPERIMENTAL_API.

I will prepare a v5 later.


-- 
David Marchand

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 2/5] eal: add lcore accessors
  2019-05-30 10:11  0%             ` Bruce Richardson
@ 2019-05-30 13:39  0%               ` Thomas Monjalon
  2019-05-30 17:00  0%                 ` David Marchand
  0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2019-05-30 13:39 UTC (permalink / raw)
  To: Bruce Richardson
  Cc: David Marchand, Stephen Hemminger, dev, Kevin Traynor,
	Neil Horman, Luca Boccassi

30/05/2019 12:11, Bruce Richardson:
> On Thu, May 30, 2019 at 09:40:08AM +0200, Thomas Monjalon wrote:
> > 30/05/2019 09:31, David Marchand:
> > > On Thu, May 30, 2019 at 12:51 AM Stephen Hemminger <
> > > stephen@networkplumber.org> wrote:
> > > 
> > > > On Thu, 30 May 2019 00:46:30 +0200
> > > > Thomas Monjalon <thomas@monjalon.net> wrote:
> > > >
> > > > > 23/05/2019 15:58, David Marchand:
> > > > > > From: Stephen Hemminger <stephen@networkplumber.org>
> > > > > >
> > > > > > The fields of the internal EAL core configuration are currently
> > > > > > laid bare as part of the API. This is not good practice and limits
> > > > > > fixing issues with layout and sizes.
> > > > > >
> > > > > > Make new accessor functions for the fields used by current drivers
> > > > > > and examples.
> > > > > [...]
> > > > > > +DPDK_19.08 {
> > > > > > +   global:
> > > > > > +
> > > > > > +   rte_lcore_cpuset;
> > > > > > +   rte_lcore_index;
> > > > > > +   rte_lcore_to_cpu_id;
> > > > > > +   rte_lcore_to_socket_id;
> > > > > > +
> > > > > > +} DPDK_19.05;
> > > > > > +
> > > > > >  EXPERIMENTAL {
> > > > > >     global:
> > > > >
> > > > > Just to make sure, are we OK to introduce these functions
> > > > > as non-experimental?
> > > >
> > > > They were in previous releases as inlines this patch converts them
> > > > to real functions.
> > > >
> > > >
> > > Well, yes and no.
> > > 
> > > rte_lcore_index and rte_lcore_to_socket_id already existed, so making them
> > > part of the ABI is fine for me.
> > > 
> > > rte_lcore_to_cpu_id is new but seems quite safe in how it can be used,
> > > adding it to the ABI is ok for me.
> > 
> > It is used by DPAA and some test.
> > I guess adding as experimental is fine too?
> > I'm fine with both options, I'm just trying to apply the policy
> > we agreed on. Does this case deserve an exception?
> > 
> 
> While it may be a good candidate, I'm not sure how much making an exception
> for it really matters. I'd be tempted to just mark it experimental and then
> have it stable for the 19.11 release. What do we really lose by waiting a
> release to stabilize it?

I would agree Bruce.
If no more comment, I will wait for a v5 of this series.




^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 2/2] meson: make build configurable
  2019-05-30 11:59  0%           ` Ilya Maximets
@ 2019-05-30 13:30  0%             ` Luca Boccassi
  0 siblings, 0 replies; 200+ results
From: Luca Boccassi @ 2019-05-30 13:30 UTC (permalink / raw)
  To: Ilya Maximets, dev, Thomas Monjalon
  Cc: Bruce Richardson, Aaron Conole, Kevin Traynor

On Thu, 2019-05-30 at 14:59 +0300, Ilya Maximets wrote:
> On 30.05.2019 14:06, Luca Boccassi wrote:
> > On Thu, 2019-05-30 at 13:03 +0300, Ilya Maximets wrote:
> > > On 29.05.2019 23:37, Luca Boccassi wrote:
> > > > On Wed, 2019-05-29 at 19:39 +0300, Ilya Maximets wrote:
> > > > > The first thing many developers do before start building DPDK
> > > > > is
> > > > > disabling all the not needed divers and libraries. This
> > > > > happens
> > > > > just because more than a half of DPDK dirvers and libraries
> > > > > are
> > > > > not
> > > > > needed for the particular reason. For example, you don't need
> > > > > dpaa*, octeon*, various croypto devices, eventdev, etc. if
> > > > > you're
> > > > > only want to build OVS for x86_64 with static linking.
> > > > > 
> > > > > By disabling everything you don't need, build speeds up
> > > > > literally
> > > > > 10x
> > > > > times. This is important for CI systems. For example,
> > > > > TravisCI
> > > > > wastes
> > > > > 10 minutes for the default DPDK build just to check linking
> > > > > with
> > > > > OVS.
> > > > > 
> > > > > Another thing is the binary size. Number of DPDK libraries
> > > > > and,
> > > > > as a result, size of resulted statically linked application
> > > > > decreases
> > > > > significantly.
> > > > > 
> > > > > Important thing also that you're able to not install some
> > > > > dependencies
> > > > > if you don't have them on a target platform. Just disable
> > > > > libs/drivers
> > > > > that depends on it. Similar thing for the glibc version
> > > > > mismatch
> > > > > between build and target platforms.
> > > > > 
> > > > > Also, I have to note that less code means less probability of
> > > > > failures and less number of attack vectors.
> > > > > 
> > > > > This patch gives 'meson' the power of configurability that we
> > > > > have with 'make'. Using new options it's possible to enable
> > > > > just
> > > > > what you need and nothing more.
> > > > > 
> > > > > For example, following cmdline could be used to build almost
> > > > > minimal
> > > > > set of DPDK libs and drivers to check OVS build:
> > > > > 
> > > > >   $ meson build -Dexamples='' -Dtests=false
> > > > > -Denable_kmods=false
> > > > > \
> > > > >                 -Ddrivers_bus=pci,vdev          \
> > > > >                 -Ddrivers_mempool=ring          \
> > > > >                 -Ddrivers_net=null,virtio,ring  \
> > > > >                 -Ddrivers_crypto=virtio         \
> > > > >                 -Ddrivers_compress=none         \
> > > > >                 -Ddrivers_event=none            \
> > > > >                 -Ddrivers_baseband=none         \
> > > > >                 -Ddrivers_raw=none              \
> > > > >                 -Ddrivers_common=none           \
> > > > >                
> > > > > -Dlibs=kvargs,eal,cmdline,ring,mempool,mbuf,net,meter,\
> > > > >                        ethdev,pci,hash,cryptodev,pdump,vhost
> > > > > \
> > > > >                 -Dapps=none
> > > > > 
> > > > > Adding a few real net drivers will give configuration that
> > > > > can be
> > > > > used
> > > > > in production environment.
> > > > > 
> > > > > Looks not very pretty, but this could be moved to a script.
> > > > > 
> > > > > Build details:
> > > > > 
> > > > >   Build targets in project: 57
> > > > > 
> > > > >   $ time ninja
> > > > >   real    0m11,528s
> > > > >   user    1m4,137s
> > > > >   sys     0m4,935s
> > > > > 
> > > > >   $ du -sh ../dpdk_meson_install/
> > > > >   3,5M    ../dpdk_meson_install/
> > > > > 
> > > > > To compare with what we have without these options:
> > > > > 
> > > > >   $ meson build -Dexamples='' -Dtests=false
> > > > > -Denable_kmods=false
> > > > >   Build targets in project: 434
> > > > > 
> > > > >   $ time ninja
> > > > >   real    1m38,963s
> > > > >   user    10m18,624s
> > > > >   sys     0m45,478s
> > > > > 
> > > > >   $ du -sh ../dpdk_meson_install/
> > > > >   27M     ../dpdk_meson_install/
> > > > > 
> > > > > 10x speed up for the user time.
> > > > > 7.7 times size decrease.
> > > > > 
> > > > > This is probably not much user-friendly because it's not a
> > > > > Kconfig
> > > > > and dependency tracking in meson is really poor, so it
> > > > > requires
> > > > > usually few iterations to pick correct set of libraries to
> > > > > satisfy
> > > > > all dependencies. However, it's not a big deal. Options
> > > > > intended
> > > > > for a proficient users who knows what they need.
> > > > 
> > > > Hi,
> > > > 
> > > > We talked about this a few times in the past, and it was
> > > > actually
> > > > one
> > > > of the design goals to _avoid_ replicating the octopus-like
> > > > config
> > > > system of the makefiles. That's because it makes the test
> > > > matrix
> > > > insanely complicated, not to mention the harm to user
> > > > friendliness,
> > > > among other things.
> > > > 
> > > > If someone doesn't want to use a PMD, they can just avoid
> > > > installing it
> > > > - it's simple enough.
> > > 
> > > So how can I do this? I don't think 'ninja install' has such
> > > option.
> > > Also, if you think that it is safe to skip some libs/drivers in
> > > installation
> > > process, it must be safe to not build them at all. It's just a
> > > waste
> > > of
> > > time and computational resources to build something known to be
> > > not
> > > used.
> > > And if you're going to ship DPDK libraries separately in distros,
> > > you'll
> > > have to test their different combinations anyway. If they're so
> > > independent
> > > that you don't need to test them in various combinations, than
> > > your
> > > point
> > > about test matrix is not valid.
> > 
> > It can be done in the packaging step, or post-install if there's no
> > packaging. An operating system vendor is free to do its own test
> > and
> > support plan, and decide to leave out some PMDs from it.
> 
> This technically means doing this manually/write custom scripts.

It's a standard part of packaging software, both in RPM and DEB - not
too familiar with AUR, but I suspect it's not too different in that
regard.

> > Canonical does
> > something similar: in Debian/Ubuntu and derivatives we package PMDs
> > individually, and then Canonical groups them in 2 sets - a subset
> > they
> > guarantee to support from their own resources, and the full set as
> > delivered by the community. But the point is that it's a step that
> > they
> > decide to take, and pay the price for it in terms of time
> > investment in
> > validating that particular combination, rather than the onus being
> > on
> > our very limited and already stretched resources to validate all
> > combinations.
> > 
> > We can focus our resources into making sure the few combinations
> > that
> > _must_ be supported, for example due to external dependencies, work
> > fine.
> > 
> > > > Sorry, but from me it's a very strong NACK.
> > > 
> > > Sorry, but let me disagree with you. For me, meson
> > > configurability is
> > > the
> > > essential thing to have in terms of deprecating the 'make' build
> > > system.
> > > DPDK was and keeps being (in most cases) the library that users
> > > statically
> > > linking to a single application built for particular platform and
> > > not
> > > using
> > > for anything else. This means that user in most cases knows which
> > > parts
> > > needed and which parts will never be used. Current meson build
> > > system
> > > doesn't allow to disable anything forcing users to link with the
> > > whole bunch
> > > of unused code.
> > > 
> > > One major case is that you have to have build environment equal
> > > to
> > > your
> > > target platform in terms of availability of external libraries.
> > > So,
> > > if I
> > > have some external library on build system, meson will build all
> > > the
> > > modules
> > > it depends from and will link them to my application. As a result
> > > I'll not
> > > be able to run my application on a target platform without
> > > installing
> > > additional dependencies which is not acceptable. This patch will
> > > allow to
> > > specifically disable all the libs that has unsatisfiable
> > > dependencies
> > > on
> > > target. Without the patch it's required to manually remove
> > > resulted
> > > libs and
> > > fix pkg-config and stuff before building apps. This is far less
> > > user-
> > > friendly
> > > than options I proposed. And yes, I still have to waste time for
> > > building
> > > libraries I'll remove right after.
> > > 
> > > While testing OVS on TravisCI, DPDK was built far more than 30K
> > > times
> > > which is more than half of a year of a wasted computational
> > > resources
> > > (if we'll count 10 minutes per build).
> > > I think this time could be used more wisely.
> > > 
> > > Best regards, Ilya Maximets.
> > 
> > But that's the thing: as it was discussed recently, we need to move
> > away from DPDK being by default a "special sauce" toolkit with
> > millions
> > of customizations that is custom built and statically linked, like
> > busybox, and to a situation where it's just another set of system
> > libraries like any other, shipped by the operating system, like
> > glibc -
> > see the threads about stable API/ABI and OS-driven delivery by Ray.
> > The status quo of an insanely granular build configuration that
> > means
> > everyone is using something different from each other is a bug -
> > not a
> > feature. Excessive _build time_ configuration exacerbates and
> > encourages this bug.
> > 
> > Sure, an initial build from scratch will take a couple of minutes
> > more
> > - mildly annoying, but worth the price. Caching takes care of that
> > problem already pretty well. Also standardizing on radically fewer
> > build configurations means you _don't_ have to rebuild DPDK for
> > third
> > party testing - you just consume the pre-built binaries from the OS
> > of
> > choice, or the PPA or similar for backports and HEAD builds. That
> > will
> > save even more time and resources in third-party build systems.
> > 
> 
> CI systems usually build everything from scratch. So caching doesn't
> help.
> And I don't think that distros will have any pre-built binaries for
> the
> old systems used in public CI systems. For example, TravisCI has
> 'Trusty'
> as a default environment. At most you may use 'Xenial'. But I don't
> think
> that DPDK 18.11 will ever be packaged for them. Also, distros mostly
> has
> dynamic libraries in their packages not providing static ones. It
> might
> be changed in the future, but still we'll not have them for 'xenial'.
> 
> So, OVS will stuck with slow building DPDK each time from scratch on
> Travis.
> And developers will maintain local patches for meson for stripping
> extra
> libraries or local build scripts that will package only what they
> need.
> 
> Best regards, Ilya Maximets.

Well, I'm not sure most CI systems build everything from scratch, and
even if they do, ccache is supported natively on Travis and others - we
use it for DPDK's Travis config, for example. I've yet to see a Travis
configuration that rebuilds the kernel, glibc, compiler and every
single other dependency of a project from scratch every time, though :-
)
In fact, Travis has native support for APT repositories and even PPAs
to do the opposite, and it's quite popular as far as I know.

Making a PPA or a project on OBS available with repositories for older
LTS releases is not only possible, but we already do it today - it's
based mostly on request, so for example even though Xenial shipped with
DPDk 2.2, a 17.11 PPA is available and maintained already, and I'm sure
if we ask very nicely 18.11 can be made available too :-)

I'm not sure about the RPM world, but in Debian, Ubuntu and derivatives
we ship both static and dynamic libraries by default, and that includes
DPDK from day 1.

So I can assure you I simpathize with the idea of making CIs faster,
and there are many ways to achieve that, that don't require manually
hacking the dependencies. For example, I've set up the ZeroMQ CI so
that all dependencies from the project and backports for Xenial are
built on OBS just as they would be built by the distro, with no
compromises or local just-in-time "hacks" to speed up individual
builds, so that binary packages are available and installed by Travis
via APT on each build. That takes less than 30s regardless of the
number of packages (within reason), so whatever we add as a dependency
it's still the same.

I had done that even for Trusty and Pristine at the time:

https://build.opensuse.org/project/monitor/network:messaging:zeromq:git-stable?arch_x86_64=1&defaults=0&repo_xUbuntu_14_04=1&succeeded=1
https://build.opensuse.org/project/monitor/network:messaging:zeromq:git-stable?arch_x86_64=1&defaults=0&repo_xUbuntu_12_04=1&succeeded=1

Here's a CI job that uses the Trusty repository:

https://travis-ci.org/zeromq/czmq/jobs/538626364

-- 
Kind regards,
Luca Boccassi

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 2/2] meson: make build configurable
  2019-05-30 11:06  3%         ` Luca Boccassi
@ 2019-05-30 11:59  0%           ` Ilya Maximets
  2019-05-30 13:30  0%             ` Luca Boccassi
  0 siblings, 1 reply; 200+ results
From: Ilya Maximets @ 2019-05-30 11:59 UTC (permalink / raw)
  To: Luca Boccassi, dev, Thomas Monjalon
  Cc: Bruce Richardson, Aaron Conole, Kevin Traynor

On 30.05.2019 14:06, Luca Boccassi wrote:
> On Thu, 2019-05-30 at 13:03 +0300, Ilya Maximets wrote:
>> On 29.05.2019 23:37, Luca Boccassi wrote:
>>> On Wed, 2019-05-29 at 19:39 +0300, Ilya Maximets wrote:
>>>> The first thing many developers do before start building DPDK is
>>>> disabling all the not needed divers and libraries. This happens
>>>> just because more than a half of DPDK dirvers and libraries are
>>>> not
>>>> needed for the particular reason. For example, you don't need
>>>> dpaa*, octeon*, various croypto devices, eventdev, etc. if you're
>>>> only want to build OVS for x86_64 with static linking.
>>>>
>>>> By disabling everything you don't need, build speeds up literally
>>>> 10x
>>>> times. This is important for CI systems. For example, TravisCI
>>>> wastes
>>>> 10 minutes for the default DPDK build just to check linking with
>>>> OVS.
>>>>
>>>> Another thing is the binary size. Number of DPDK libraries and,
>>>> as a result, size of resulted statically linked application
>>>> decreases
>>>> significantly.
>>>>
>>>> Important thing also that you're able to not install some
>>>> dependencies
>>>> if you don't have them on a target platform. Just disable
>>>> libs/drivers
>>>> that depends on it. Similar thing for the glibc version mismatch
>>>> between build and target platforms.
>>>>
>>>> Also, I have to note that less code means less probability of
>>>> failures and less number of attack vectors.
>>>>
>>>> This patch gives 'meson' the power of configurability that we
>>>> have with 'make'. Using new options it's possible to enable just
>>>> what you need and nothing more.
>>>>
>>>> For example, following cmdline could be used to build almost
>>>> minimal
>>>> set of DPDK libs and drivers to check OVS build:
>>>>
>>>>   $ meson build -Dexamples='' -Dtests=false -Denable_kmods=false
>>>> \
>>>>                 -Ddrivers_bus=pci,vdev          \
>>>>                 -Ddrivers_mempool=ring          \
>>>>                 -Ddrivers_net=null,virtio,ring  \
>>>>                 -Ddrivers_crypto=virtio         \
>>>>                 -Ddrivers_compress=none         \
>>>>                 -Ddrivers_event=none            \
>>>>                 -Ddrivers_baseband=none         \
>>>>                 -Ddrivers_raw=none              \
>>>>                 -Ddrivers_common=none           \
>>>>                
>>>> -Dlibs=kvargs,eal,cmdline,ring,mempool,mbuf,net,meter,\
>>>>                        ethdev,pci,hash,cryptodev,pdump,vhost \
>>>>                 -Dapps=none
>>>>
>>>> Adding a few real net drivers will give configuration that can be
>>>> used
>>>> in production environment.
>>>>
>>>> Looks not very pretty, but this could be moved to a script.
>>>>
>>>> Build details:
>>>>
>>>>   Build targets in project: 57
>>>>
>>>>   $ time ninja
>>>>   real    0m11,528s
>>>>   user    1m4,137s
>>>>   sys     0m4,935s
>>>>
>>>>   $ du -sh ../dpdk_meson_install/
>>>>   3,5M    ../dpdk_meson_install/
>>>>
>>>> To compare with what we have without these options:
>>>>
>>>>   $ meson build -Dexamples='' -Dtests=false -Denable_kmods=false
>>>>   Build targets in project: 434
>>>>
>>>>   $ time ninja
>>>>   real    1m38,963s
>>>>   user    10m18,624s
>>>>   sys     0m45,478s
>>>>
>>>>   $ du -sh ../dpdk_meson_install/
>>>>   27M     ../dpdk_meson_install/
>>>>
>>>> 10x speed up for the user time.
>>>> 7.7 times size decrease.
>>>>
>>>> This is probably not much user-friendly because it's not a
>>>> Kconfig
>>>> and dependency tracking in meson is really poor, so it requires
>>>> usually few iterations to pick correct set of libraries to
>>>> satisfy
>>>> all dependencies. However, it's not a big deal. Options intended
>>>> for a proficient users who knows what they need.
>>>
>>> Hi,
>>>
>>> We talked about this a few times in the past, and it was actually
>>> one
>>> of the design goals to _avoid_ replicating the octopus-like config
>>> system of the makefiles. That's because it makes the test matrix
>>> insanely complicated, not to mention the harm to user friendliness,
>>> among other things.
>>>
>>> If someone doesn't want to use a PMD, they can just avoid
>>> installing it
>>> - it's simple enough.
>>
>> So how can I do this? I don't think 'ninja install' has such option.
>> Also, if you think that it is safe to skip some libs/drivers in
>> installation
>> process, it must be safe to not build them at all. It's just a waste
>> of
>> time and computational resources to build something known to be not
>> used.
>> And if you're going to ship DPDK libraries separately in distros,
>> you'll
>> have to test their different combinations anyway. If they're so
>> independent
>> that you don't need to test them in various combinations, than your
>> point
>> about test matrix is not valid.
> 
> It can be done in the packaging step, or post-install if there's no
> packaging. An operating system vendor is free to do its own test and
> support plan, and decide to leave out some PMDs from it.

This technically means doing this manually/write custom scripts.

> Canonical does
> something similar: in Debian/Ubuntu and derivatives we package PMDs
> individually, and then Canonical groups them in 2 sets - a subset they
> guarantee to support from their own resources, and the full set as
> delivered by the community. But the point is that it's a step that they
> decide to take, and pay the price for it in terms of time investment in
> validating that particular combination, rather than the onus being on
> our very limited and already stretched resources to validate all
> combinations.
> 
> We can focus our resources into making sure the few combinations that
> _must_ be supported, for example due to external dependencies, work
> fine.
> 
>>> Sorry, but from me it's a very strong NACK.
>>
>> Sorry, but let me disagree with you. For me, meson configurability is
>> the
>> essential thing to have in terms of deprecating the 'make' build
>> system.
>> DPDK was and keeps being (in most cases) the library that users
>> statically
>> linking to a single application built for particular platform and not
>> using
>> for anything else. This means that user in most cases knows which
>> parts
>> needed and which parts will never be used. Current meson build system
>> doesn't allow to disable anything forcing users to link with the
>> whole bunch
>> of unused code.
>>
>> One major case is that you have to have build environment equal to
>> your
>> target platform in terms of availability of external libraries. So,
>> if I
>> have some external library on build system, meson will build all the
>> modules
>> it depends from and will link them to my application. As a result
>> I'll not
>> be able to run my application on a target platform without installing
>> additional dependencies which is not acceptable. This patch will
>> allow to
>> specifically disable all the libs that has unsatisfiable dependencies
>> on
>> target. Without the patch it's required to manually remove resulted
>> libs and
>> fix pkg-config and stuff before building apps. This is far less user-
>> friendly
>> than options I proposed. And yes, I still have to waste time for
>> building
>> libraries I'll remove right after.
>>
>> While testing OVS on TravisCI, DPDK was built far more than 30K times
>> which is more than half of a year of a wasted computational resources
>> (if we'll count 10 minutes per build).
>> I think this time could be used more wisely.
>>
>> Best regards, Ilya Maximets.
> 
> But that's the thing: as it was discussed recently, we need to move
> away from DPDK being by default a "special sauce" toolkit with millions
> of customizations that is custom built and statically linked, like
> busybox, and to a situation where it's just another set of system
> libraries like any other, shipped by the operating system, like glibc -
> see the threads about stable API/ABI and OS-driven delivery by Ray.
> The status quo of an insanely granular build configuration that means
> everyone is using something different from each other is a bug - not a
> feature. Excessive _build time_ configuration exacerbates and
> encourages this bug.
> 
> Sure, an initial build from scratch will take a couple of minutes more
> - mildly annoying, but worth the price. Caching takes care of that
> problem already pretty well. Also standardizing on radically fewer
> build configurations means you _don't_ have to rebuild DPDK for third
> party testing - you just consume the pre-built binaries from the OS of
> choice, or the PPA or similar for backports and HEAD builds. That will
> save even more time and resources in third-party build systems.
> 

CI systems usually build everything from scratch. So caching doesn't help.
And I don't think that distros will have any pre-built binaries for the
old systems used in public CI systems. For example, TravisCI has 'Trusty'
as a default environment. At most you may use 'Xenial'. But I don't think
that DPDK 18.11 will ever be packaged for them. Also, distros mostly has
dynamic libraries in their packages not providing static ones. It might
be changed in the future, but still we'll not have them for 'xenial'.

So, OVS will stuck with slow building DPDK each time from scratch on Travis.
And developers will maintain local patches for meson for stripping extra
libraries or local build scripts that will package only what they need.

Best regards, Ilya Maximets.

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 2/2] meson: make build configurable
  @ 2019-05-30 11:06  3%         ` Luca Boccassi
  2019-05-30 11:59  0%           ` Ilya Maximets
  0 siblings, 1 reply; 200+ results
From: Luca Boccassi @ 2019-05-30 11:06 UTC (permalink / raw)
  To: Ilya Maximets, dev, Thomas Monjalon
  Cc: Bruce Richardson, Aaron Conole, Kevin Traynor

On Thu, 2019-05-30 at 13:03 +0300, Ilya Maximets wrote:
> On 29.05.2019 23:37, Luca Boccassi wrote:
> > On Wed, 2019-05-29 at 19:39 +0300, Ilya Maximets wrote:
> > > The first thing many developers do before start building DPDK is
> > > disabling all the not needed divers and libraries. This happens
> > > just because more than a half of DPDK dirvers and libraries are
> > > not
> > > needed for the particular reason. For example, you don't need
> > > dpaa*, octeon*, various croypto devices, eventdev, etc. if you're
> > > only want to build OVS for x86_64 with static linking.
> > > 
> > > By disabling everything you don't need, build speeds up literally
> > > 10x
> > > times. This is important for CI systems. For example, TravisCI
> > > wastes
> > > 10 minutes for the default DPDK build just to check linking with
> > > OVS.
> > > 
> > > Another thing is the binary size. Number of DPDK libraries and,
> > > as a result, size of resulted statically linked application
> > > decreases
> > > significantly.
> > > 
> > > Important thing also that you're able to not install some
> > > dependencies
> > > if you don't have them on a target platform. Just disable
> > > libs/drivers
> > > that depends on it. Similar thing for the glibc version mismatch
> > > between build and target platforms.
> > > 
> > > Also, I have to note that less code means less probability of
> > > failures and less number of attack vectors.
> > > 
> > > This patch gives 'meson' the power of configurability that we
> > > have with 'make'. Using new options it's possible to enable just
> > > what you need and nothing more.
> > > 
> > > For example, following cmdline could be used to build almost
> > > minimal
> > > set of DPDK libs and drivers to check OVS build:
> > > 
> > >   $ meson build -Dexamples='' -Dtests=false -Denable_kmods=false
> > > \
> > >                 -Ddrivers_bus=pci,vdev          \
> > >                 -Ddrivers_mempool=ring          \
> > >                 -Ddrivers_net=null,virtio,ring  \
> > >                 -Ddrivers_crypto=virtio         \
> > >                 -Ddrivers_compress=none         \
> > >                 -Ddrivers_event=none            \
> > >                 -Ddrivers_baseband=none         \
> > >                 -Ddrivers_raw=none              \
> > >                 -Ddrivers_common=none           \
> > >                
> > > -Dlibs=kvargs,eal,cmdline,ring,mempool,mbuf,net,meter,\
> > >                        ethdev,pci,hash,cryptodev,pdump,vhost \
> > >                 -Dapps=none
> > > 
> > > Adding a few real net drivers will give configuration that can be
> > > used
> > > in production environment.
> > > 
> > > Looks not very pretty, but this could be moved to a script.
> > > 
> > > Build details:
> > > 
> > >   Build targets in project: 57
> > > 
> > >   $ time ninja
> > >   real    0m11,528s
> > >   user    1m4,137s
> > >   sys     0m4,935s
> > > 
> > >   $ du -sh ../dpdk_meson_install/
> > >   3,5M    ../dpdk_meson_install/
> > > 
> > > To compare with what we have without these options:
> > > 
> > >   $ meson build -Dexamples='' -Dtests=false -Denable_kmods=false
> > >   Build targets in project: 434
> > > 
> > >   $ time ninja
> > >   real    1m38,963s
> > >   user    10m18,624s
> > >   sys     0m45,478s
> > > 
> > >   $ du -sh ../dpdk_meson_install/
> > >   27M     ../dpdk_meson_install/
> > > 
> > > 10x speed up for the user time.
> > > 7.7 times size decrease.
> > > 
> > > This is probably not much user-friendly because it's not a
> > > Kconfig
> > > and dependency tracking in meson is really poor, so it requires
> > > usually few iterations to pick correct set of libraries to
> > > satisfy
> > > all dependencies. However, it's not a big deal. Options intended
> > > for a proficient users who knows what they need.
> > 
> > Hi,
> > 
> > We talked about this a few times in the past, and it was actually
> > one
> > of the design goals to _avoid_ replicating the octopus-like config
> > system of the makefiles. That's because it makes the test matrix
> > insanely complicated, not to mention the harm to user friendliness,
> > among other things.
> > 
> > If someone doesn't want to use a PMD, they can just avoid
> > installing it
> > - it's simple enough.
> 
> So how can I do this? I don't think 'ninja install' has such option.
> Also, if you think that it is safe to skip some libs/drivers in
> installation
> process, it must be safe to not build them at all. It's just a waste
> of
> time and computational resources to build something known to be not
> used.
> And if you're going to ship DPDK libraries separately in distros,
> you'll
> have to test their different combinations anyway. If they're so
> independent
> that you don't need to test them in various combinations, than your
> point
> about test matrix is not valid.

It can be done in the packaging step, or post-install if there's no
packaging. An operating system vendor is free to do its own test and
support plan, and decide to leave out some PMDs from it. Canonical does
something similar: in Debian/Ubuntu and derivatives we package PMDs
individually, and then Canonical groups them in 2 sets - a subset they
guarantee to support from their own resources, and the full set as
delivered by the community. But the point is that it's a step that they
decide to take, and pay the price for it in terms of time investment in
validating that particular combination, rather than the onus being on
our very limited and already stretched resources to validate all
combinations.

We can focus our resources into making sure the few combinations that
_must_ be supported, for example due to external dependencies, work
fine.

> > Sorry, but from me it's a very strong NACK.
> 
> Sorry, but let me disagree with you. For me, meson configurability is
> the
> essential thing to have in terms of deprecating the 'make' build
> system.
> DPDK was and keeps being (in most cases) the library that users
> statically
> linking to a single application built for particular platform and not
> using
> for anything else. This means that user in most cases knows which
> parts
> needed and which parts will never be used. Current meson build system
> doesn't allow to disable anything forcing users to link with the
> whole bunch
> of unused code.
> 
> One major case is that you have to have build environment equal to
> your
> target platform in terms of availability of external libraries. So,
> if I
> have some external library on build system, meson will build all the
> modules
> it depends from and will link them to my application. As a result
> I'll not
> be able to run my application on a target platform without installing
> additional dependencies which is not acceptable. This patch will
> allow to
> specifically disable all the libs that has unsatisfiable dependencies
> on
> target. Without the patch it's required to manually remove resulted
> libs and
> fix pkg-config and stuff before building apps. This is far less user-
> friendly
> than options I proposed. And yes, I still have to waste time for
> building
> libraries I'll remove right after.
> 
> While testing OVS on TravisCI, DPDK was built far more than 30K times
> which is more than half of a year of a wasted computational resources
> (if we'll count 10 minutes per build).
> I think this time could be used more wisely.
> 
> Best regards, Ilya Maximets.

But that's the thing: as it was discussed recently, we need to move
away from DPDK being by default a "special sauce" toolkit with millions
of customizations that is custom built and statically linked, like
busybox, and to a situation where it's just another set of system
libraries like any other, shipped by the operating system, like glibc -
see the threads about stable API/ABI and OS-driven delivery by Ray.
The status quo of an insanely granular build configuration that means
everyone is using something different from each other is a bug - not a
feature. Excessive _build time_ configuration exacerbates and
encourages this bug.

Sure, an initial build from scratch will take a couple of minutes more
- mildly annoying, but worth the price. Caching takes care of that
problem already pretty well. Also standardizing on radically fewer
build configurations means you _don't_ have to rebuild DPDK for third
party testing - you just consume the pre-built binaries from the OS of
choice, or the PPA or similar for backports and HEAD builds. That will
save even more time and resources in third-party build systems.

-- 
Kind regards,
Luca Boccassi

^ permalink raw reply	[relevance 3%]

* Re: [dpdk-dev] [PATCH v4 2/5] eal: add lcore accessors
  2019-05-30  7:40  0%           ` Thomas Monjalon
@ 2019-05-30 10:11  0%             ` Bruce Richardson
  2019-05-30 13:39  0%               ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2019-05-30 10:11 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: David Marchand, Stephen Hemminger, dev, Kevin Traynor,
	Neil Horman, Luca Boccassi

On Thu, May 30, 2019 at 09:40:08AM +0200, Thomas Monjalon wrote:
> 30/05/2019 09:31, David Marchand:
> > On Thu, May 30, 2019 at 12:51 AM Stephen Hemminger <
> > stephen@networkplumber.org> wrote:
> > 
> > > On Thu, 30 May 2019 00:46:30 +0200
> > > Thomas Monjalon <thomas@monjalon.net> wrote:
> > >
> > > > 23/05/2019 15:58, David Marchand:
> > > > > From: Stephen Hemminger <stephen@networkplumber.org>
> > > > >
> > > > > The fields of the internal EAL core configuration are currently
> > > > > laid bare as part of the API. This is not good practice and limits
> > > > > fixing issues with layout and sizes.
> > > > >
> > > > > Make new accessor functions for the fields used by current drivers
> > > > > and examples.
> > > > [...]
> > > > > +DPDK_19.08 {
> > > > > +   global:
> > > > > +
> > > > > +   rte_lcore_cpuset;
> > > > > +   rte_lcore_index;
> > > > > +   rte_lcore_to_cpu_id;
> > > > > +   rte_lcore_to_socket_id;
> > > > > +
> > > > > +} DPDK_19.05;
> > > > > +
> > > > >  EXPERIMENTAL {
> > > > >     global:
> > > >
> > > > Just to make sure, are we OK to introduce these functions
> > > > as non-experimental?
> > >
> > > They were in previous releases as inlines this patch converts them
> > > to real functions.
> > >
> > >
> > Well, yes and no.
> > 
> > rte_lcore_index and rte_lcore_to_socket_id already existed, so making them
> > part of the ABI is fine for me.
> > 
> > rte_lcore_to_cpu_id is new but seems quite safe in how it can be used,
> > adding it to the ABI is ok for me.
> 
> It is used by DPAA and some test.
> I guess adding as experimental is fine too?
> I'm fine with both options, I'm just trying to apply the policy
> we agreed on. Does this case deserve an exception?
> 

While it may be a good candidate, I'm not sure how much making an exception
for it really matters. I'd be tempted to just mark it experimental and then
have it stable for the 19.11 release. What do we really lose by waiting a
release to stabilize it?


^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 2/5] eal: add lcore accessors
  2019-05-30  7:31  4%         ` David Marchand
@ 2019-05-30  7:40  0%           ` Thomas Monjalon
  2019-05-30 10:11  0%             ` Bruce Richardson
  0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2019-05-30  7:40 UTC (permalink / raw)
  To: David Marchand, Stephen Hemminger
  Cc: dev, Kevin Traynor, Neil Horman, Luca Boccassi, Bruce Richardson

30/05/2019 09:31, David Marchand:
> On Thu, May 30, 2019 at 12:51 AM Stephen Hemminger <
> stephen@networkplumber.org> wrote:
> 
> > On Thu, 30 May 2019 00:46:30 +0200
> > Thomas Monjalon <thomas@monjalon.net> wrote:
> >
> > > 23/05/2019 15:58, David Marchand:
> > > > From: Stephen Hemminger <stephen@networkplumber.org>
> > > >
> > > > The fields of the internal EAL core configuration are currently
> > > > laid bare as part of the API. This is not good practice and limits
> > > > fixing issues with layout and sizes.
> > > >
> > > > Make new accessor functions for the fields used by current drivers
> > > > and examples.
> > > [...]
> > > > +DPDK_19.08 {
> > > > +   global:
> > > > +
> > > > +   rte_lcore_cpuset;
> > > > +   rte_lcore_index;
> > > > +   rte_lcore_to_cpu_id;
> > > > +   rte_lcore_to_socket_id;
> > > > +
> > > > +} DPDK_19.05;
> > > > +
> > > >  EXPERIMENTAL {
> > > >     global:
> > >
> > > Just to make sure, are we OK to introduce these functions
> > > as non-experimental?
> >
> > They were in previous releases as inlines this patch converts them
> > to real functions.
> >
> >
> Well, yes and no.
> 
> rte_lcore_index and rte_lcore_to_socket_id already existed, so making them
> part of the ABI is fine for me.
> 
> rte_lcore_to_cpu_id is new but seems quite safe in how it can be used,
> adding it to the ABI is ok for me.

It is used by DPAA and some test.
I guess adding as experimental is fine too?
I'm fine with both options, I'm just trying to apply the policy
we agreed on. Does this case deserve an exception?

> rte_lcore_cpuset is new too, and still a bit obscure to me. I am not really
> convinced we need it until I understand why dpaa2 and fslmc bus need to
> know about this.
> I might need more time to look at it, so flag this as experimental sounds
> fair to me.




^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH v4 2/5] eal: add lcore accessors
  @ 2019-05-30  7:31  4%         ` David Marchand
  2019-05-30  7:40  0%           ` Thomas Monjalon
  0 siblings, 1 reply; 200+ results
From: David Marchand @ 2019-05-30  7:31 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Thomas Monjalon, dev, Kevin Traynor, Neil Horman, Luca Boccassi,
	Bruce Richardson

On Thu, May 30, 2019 at 12:51 AM Stephen Hemminger <
stephen@networkplumber.org> wrote:

> On Thu, 30 May 2019 00:46:30 +0200
> Thomas Monjalon <thomas@monjalon.net> wrote:
>
> > 23/05/2019 15:58, David Marchand:
> > > From: Stephen Hemminger <stephen@networkplumber.org>
> > >
> > > The fields of the internal EAL core configuration are currently
> > > laid bare as part of the API. This is not good practice and limits
> > > fixing issues with layout and sizes.
> > >
> > > Make new accessor functions for the fields used by current drivers
> > > and examples.
> > [...]
> > > +DPDK_19.08 {
> > > +   global:
> > > +
> > > +   rte_lcore_cpuset;
> > > +   rte_lcore_index;
> > > +   rte_lcore_to_cpu_id;
> > > +   rte_lcore_to_socket_id;
> > > +
> > > +} DPDK_19.05;
> > > +
> > >  EXPERIMENTAL {
> > >     global:
> >
> > Just to make sure, are we OK to introduce these functions
> > as non-experimental?
>
> They were in previous releases as inlines this patch converts them
> to real functions.
>
>
Well, yes and no.

rte_lcore_index and rte_lcore_to_socket_id already existed, so making them
part of the ABI is fine for me.

rte_lcore_to_cpu_id is new but seems quite safe in how it can be used,
adding it to the ABI is ok for me.

rte_lcore_cpuset is new too, and still a bit obscure to me. I am not really
convinced we need it until I understand why dpaa2 and fslmc bus need to
know about this.
I might need more time to look at it, so flag this as experimental sounds
fair to me.


-- 
David Marchand

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH 00/15] prefix network structures
  2019-05-29 14:46  0%       ` Olivier Matz
@ 2019-05-29 17:29  0%         ` David Marchand
  0 siblings, 0 replies; 200+ results
From: David Marchand @ 2019-05-29 17:29 UTC (permalink / raw)
  To: Olivier Matz
  Cc: Ferruh Yigit, dev, Stephen Hemminger, Maxime Coquelin,
	Thomas Monjalon, Ian Stokes, Ilya Maximets

On Wed, May 29, 2019 at 6:50 PM Olivier Matz <olivier.matz@6wind.com> wrote:

> On Wed, May 29, 2019 at 09:59:11AM +0200, David Marchand wrote:
> > On Fri, May 24, 2019 at 1:38 PM Ferruh Yigit <ferruh.yigit@intel.com>
> wrote:
> >
> > > On 5/21/2019 5:13 PM, Olivier Matz wrote:
> > > > The rte_net headers conflict with the libc headers, because
> > > > some definitions are duplicated, sometimes with few differences.
> > > >
> > > > This patchset adds the rte_ (or RTE_) prefix to all structures,
> functions
> > > > and defines in rte_net library. This is a big changeset, that will
> > > > break the API of many functions, but not the ABI.
> > > >
> > > > This was discussed in [1], and requested by the techboard [2].
> > > >
> > > > patch-v1:
> > > > * rease on top of v19.05
> > > > * remove uneeded renames in drivers/net/bonding/rte_eth_bond_pmd.c
> > > >   and app/test-pmd/icmpecho.c (arp-related variables)
> > > > * do not modify base drivers, except cxgbe, thunderx, enetc, qede:
> > > >   only files that already contain dpdk definitions are modified.
> > > > * fix checkpatch issues when it does not impact the code style too
> > > >   much. Big warnings remain about the RTE_IPv4() macros because
> > > >   arguments are separated by ',' instead of ', '.
> > > > * add a release note patch
> > > > * tested compilation on x86_64-linux and x86_64-freebsd.
> > > >
> > > > rfc-v2:
> > > > * rebase on top of v19.05-rc1
> > > >
> > > >
> > > > [1] http://mails.dpdk.org/archives/dev/2018-January/087384.html
> > > > [2] http://mails.dpdk.org/archives/dev/2019-February/125033.html
> > > >
> > > >
> > > > Olivier Matz (15):
> > > >   net: add rte prefix to arp structures
> > > >   net: add rte prefix to arp defines
> > > >   net: add rte prefix to ether structures
> > > >   net: add rte prefix to ether functions
> > > >   net: add rte prefix to ether defines
> > > >   net: add rte prefix to esp structure
> > > >   net: add rte prefix to gre structure
> > > >   net: add rte prefix to icmp structure
> > > >   net: add rte prefix to icmp defines
> > > >   net: add rte prefix to ip structure
> > > >   net: add rte prefix to ip defines
> > > >   net: add rte prefix to sctp structure
> > > >   net: add rte prefix to tcp structure
> > > >   net: add rte prefix to udp structure
> > > >   doc: announce network api change
> > >
> > > Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
> > > Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
> > >
> > > For series,
> > > Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
> > >
> > > Series applied to dpdk-next-net/master, thanks.
> > >
> >
> > Sorry, late to the party...
> >
> > Since we change those defines, we might as well avoid these warnings:
> > CHECK:CAMELCASE: Avoid CamelCase: <RTE_ETHER_TYPE_IPv4>
> > CHECK:CAMELCASE: Avoid CamelCase: <RTE_ETHER_TYPE_IPv6>
> >
> > I can send a patch.
>
> Thanks.
>
> By the way, here is below a script that can be used to ease the
> porting of an application. It includes modifications proposed by
> David [1].
>
> It is probably not 100% reliable, but it will do most of the job.
>
>
> Olivier
>
> [1] https://mails.dpdk.org/archives/dev/2019-May/133060.html
>
> -----------------------
> #!/bin/bash
>
> # Prefix network structure/defines/functions with "rte_".
>
> set -e
>
> if [ $# = 0 ]; then
>         echo 'usage: $0 <files>'
>         exit 1
> fi
>
> files="$@"
>
> # $1: pattern
> # $2: replacement
> replace()
> {
>         local pattern="$1"
>         local replace="$2"
>
>         sed -i -e "s,${pattern},${replace},g" ${files}
> }
>
> # $*: function names
> replace_function()
> {
>         for i in $*; do
>                 replace "\<$i\>(" "rte_$i("
>         done
> }
>
> # $*: define names
> replace_define()
> {
>         for i in $*; do
>                 local pattern
>                 case "$i" in
>                         *'(')
>                                 pattern="\<${i%(}\>("
>                                 ;;
>                         *)
>                                 pattern="\<${i}\>"
>                                 ;;
>                 esac
>                 replace "$pattern" "RTE_${i^^}"
>         done
> }
>
> # $*: struct names
> replace_struct()
> {
>         for i in $*; do
>                 replace "struct\([      ][      ]*\)\<$i\>"
> "struct\1rte_$i"
>         done
> }
>
> replace arp_hrd arp_hardware
> replace arp_pro arp_protocol
> replace arp_hln arp_hlen
> replace arp_pln arp_plen
> replace arp_op arp_opcode
> replace_struct arp_hdr arp_ipv4
> replace_define ARP_HRD_ETHER ARP_OP_REQUEST ARP_OP_REPLY ARP_OP_REVREQUEST
> \
>                ARP_OP_REVREPLY ARP_OP_INVREQUEST ARP_OP_INVREPLY
> replace_struct ether_addr ether_hdr vlan_hdr vxlan_hdr vxlan_gpe_hdr
> replace_function is_same_ether_addr is_zero_ether_addr
> is_unicast_ether_addr \
>                  is_multicast_ether_addr is_broadcast_ether_addr \
>                  is_universal_ether_addr is_local_admin_ether_addr \
>                  is_valid_assigned_ether_addr eth_random_addr
> ether_addr_copy \
>                  ether_format_addr
> replace_define ETHER_ADDR_LEN ETHER_TYPE_LEN ETHER_CRC_LEN ETHER_HDR_LEN \
>                ETHER_MIN_LEN ETHER_MAX_LEN ETHER_MTU
> ETHER_MAX_VLAN_FRAME_LEN \
>                ETHER_MAX_VLAN_ID ETHER_MAX_JUMBO_FRAME_LEN ETHER_MIN_MTU \
>                ETHER_LOCAL_ADMIN_ADDR ETHER_GROUP_ADDR ETHER_TYPE_IPv4 \
>                ETHER_TYPE_IPv6 ETHER_TYPE_ARP ETHER_TYPE_VLAN
> ETHER_TYPE_RARP \
>                ETHER_TYPE_QINQ ETHER_TYPE_ETAG ETHER_TYPE_1588
> ETHER_TYPE_SLOW \
>                ETHER_TYPE_TEB ETHER_TYPE_LLDP ETHER_TYPE_MPLS
> ETHER_TYPE_MPLSM \
>                ETHER_VXLAN_HLEN ETHER_ADDR_FMT_SIZE VXLAN_GPE_TYPE_IPV4 \
>                VXLAN_GPE_TYPE_IPV6 VXLAN_GPE_TYPE_ETH VXLAN_GPE_TYPE_NSH \
>                VXLAN_GPE_TYPE_MPLS VXLAN_GPE_TYPE_GBP VXLAN_GPE_TYPE_VBNG \
>                ETHER_VXLAN_GPE_HLEN
> replace_struct esp_hdr
> replace_struct gre_hdr
> replace_struct icmp_hdr
> replace_define IP_ICMP_ECHO_REPLY IP_ICMP_ECHO_REQUEST
> replace_struct ipv4_hdr ipv6_hdr
> replace_define "IPv4(" IPV4_MAX_PKT_LEN IPV4_HDR_IHL_MASK
> IPV4_IHL_MULTIPLIER \
>                IPV4_HDR_DF_SHIFT IPV4_HDR_MF_SHIFT IPV4_HDR_FO_SHIFT \
>                IPV4_HDR_DF_FLAG IPV4_HDR_MF_FLAG IPV4_HDR_OFFSET_MASK \
>                IPV4_HDR_OFFSET_UNITS IPV4_ANY IPV4_LOOPBACK IPV4_BROADCAST
> \
>                IPV4_ALLHOSTS_GROUP IPV4_ALLRTRS_GROUP IPV4_MAX_LOCAL_GROUP
> \
>                IPV4_MIN_MCAST IPV4_MAX_MCAST IS_IPV4_MCAST
> IPV6_HDR_FL_SHIFT \
>                IPV6_HDR_TC_SHIFT IPV6_HDR_FL_MASK IPV6_HDR_TC_MASK
> replace_struct sctp_hdr
> replace_struct tcp_hdr
> replace_struct udp_hdr
>

Thanks Olivier.

I tested this script against OVS dpdk-latest branch and did not catch any
false positive, so I will submit the changes to OVS ml once my latest
changes are in.


-- 
David Marchand

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 00/15] prefix network structures
  2019-05-29  7:59  0%     ` David Marchand
@ 2019-05-29 14:46  0%       ` Olivier Matz
  2019-05-29 17:29  0%         ` David Marchand
  0 siblings, 1 reply; 200+ results
From: Olivier Matz @ 2019-05-29 14:46 UTC (permalink / raw)
  To: David Marchand
  Cc: Ferruh Yigit, dev, Stephen Hemminger, Maxime Coquelin, Thomas Monjalon

On Wed, May 29, 2019 at 09:59:11AM +0200, David Marchand wrote:
> On Fri, May 24, 2019 at 1:38 PM Ferruh Yigit <ferruh.yigit@intel.com> wrote:
> 
> > On 5/21/2019 5:13 PM, Olivier Matz wrote:
> > > The rte_net headers conflict with the libc headers, because
> > > some definitions are duplicated, sometimes with few differences.
> > >
> > > This patchset adds the rte_ (or RTE_) prefix to all structures, functions
> > > and defines in rte_net library. This is a big changeset, that will
> > > break the API of many functions, but not the ABI.
> > >
> > > This was discussed in [1], and requested by the techboard [2].
> > >
> > > patch-v1:
> > > * rease on top of v19.05
> > > * remove uneeded renames in drivers/net/bonding/rte_eth_bond_pmd.c
> > >   and app/test-pmd/icmpecho.c (arp-related variables)
> > > * do not modify base drivers, except cxgbe, thunderx, enetc, qede:
> > >   only files that already contain dpdk definitions are modified.
> > > * fix checkpatch issues when it does not impact the code style too
> > >   much. Big warnings remain about the RTE_IPv4() macros because
> > >   arguments are separated by ',' instead of ', '.
> > > * add a release note patch
> > > * tested compilation on x86_64-linux and x86_64-freebsd.
> > >
> > > rfc-v2:
> > > * rebase on top of v19.05-rc1
> > >
> > >
> > > [1] http://mails.dpdk.org/archives/dev/2018-January/087384.html
> > > [2] http://mails.dpdk.org/archives/dev/2019-February/125033.html
> > >
> > >
> > > Olivier Matz (15):
> > >   net: add rte prefix to arp structures
> > >   net: add rte prefix to arp defines
> > >   net: add rte prefix to ether structures
> > >   net: add rte prefix to ether functions
> > >   net: add rte prefix to ether defines
> > >   net: add rte prefix to esp structure
> > >   net: add rte prefix to gre structure
> > >   net: add rte prefix to icmp structure
> > >   net: add rte prefix to icmp defines
> > >   net: add rte prefix to ip structure
> > >   net: add rte prefix to ip defines
> > >   net: add rte prefix to sctp structure
> > >   net: add rte prefix to tcp structure
> > >   net: add rte prefix to udp structure
> > >   doc: announce network api change
> >
> > Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
> > Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
> >
> > For series,
> > Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
> >
> > Series applied to dpdk-next-net/master, thanks.
> >
> 
> Sorry, late to the party...
> 
> Since we change those defines, we might as well avoid these warnings:
> CHECK:CAMELCASE: Avoid CamelCase: <RTE_ETHER_TYPE_IPv4>
> CHECK:CAMELCASE: Avoid CamelCase: <RTE_ETHER_TYPE_IPv6>
> 
> I can send a patch.

Thanks.

By the way, here is below a script that can be used to ease the
porting of an application. It includes modifications proposed by
David [1].

It is probably not 100% reliable, but it will do most of the job.


Olivier

[1] https://mails.dpdk.org/archives/dev/2019-May/133060.html

-----------------------
#!/bin/bash

# Prefix network structure/defines/functions with "rte_".

set -e

if [ $# = 0 ]; then
	echo 'usage: $0 <files>'
	exit 1
fi

files="$@"

# $1: pattern
# $2: replacement
replace()
{
	local pattern="$1"
	local replace="$2"

	sed -i -e "s,${pattern},${replace},g" ${files}
}

# $*: function names
replace_function()
{
	for i in $*; do
		replace "\<$i\>(" "rte_$i("
	done
}

# $*: define names
replace_define()
{
	for i in $*; do
		local pattern
		case "$i" in
			*'(')
				pattern="\<${i%(}\>("
				;;
			*)
				pattern="\<${i}\>"
				;;
		esac
		replace "$pattern" "RTE_${i^^}"
	done
}

# $*: struct names
replace_struct()
{
	for i in $*; do
		replace "struct\([ 	][ 	]*\)\<$i\>" "struct\1rte_$i"
	done
}

replace arp_hrd arp_hardware
replace arp_pro arp_protocol
replace arp_hln arp_hlen
replace arp_pln arp_plen
replace arp_op arp_opcode
replace_struct arp_hdr arp_ipv4
replace_define ARP_HRD_ETHER ARP_OP_REQUEST ARP_OP_REPLY ARP_OP_REVREQUEST \
	       ARP_OP_REVREPLY ARP_OP_INVREQUEST ARP_OP_INVREPLY
replace_struct ether_addr ether_hdr vlan_hdr vxlan_hdr vxlan_gpe_hdr
replace_function is_same_ether_addr is_zero_ether_addr is_unicast_ether_addr \
		 is_multicast_ether_addr is_broadcast_ether_addr \
		 is_universal_ether_addr is_local_admin_ether_addr \
		 is_valid_assigned_ether_addr eth_random_addr ether_addr_copy \
		 ether_format_addr
replace_define ETHER_ADDR_LEN ETHER_TYPE_LEN ETHER_CRC_LEN ETHER_HDR_LEN \
	       ETHER_MIN_LEN ETHER_MAX_LEN ETHER_MTU ETHER_MAX_VLAN_FRAME_LEN \
	       ETHER_MAX_VLAN_ID ETHER_MAX_JUMBO_FRAME_LEN ETHER_MIN_MTU \
	       ETHER_LOCAL_ADMIN_ADDR ETHER_GROUP_ADDR ETHER_TYPE_IPv4 \
	       ETHER_TYPE_IPv6 ETHER_TYPE_ARP ETHER_TYPE_VLAN ETHER_TYPE_RARP \
	       ETHER_TYPE_QINQ ETHER_TYPE_ETAG ETHER_TYPE_1588 ETHER_TYPE_SLOW \
	       ETHER_TYPE_TEB ETHER_TYPE_LLDP ETHER_TYPE_MPLS ETHER_TYPE_MPLSM \
	       ETHER_VXLAN_HLEN ETHER_ADDR_FMT_SIZE VXLAN_GPE_TYPE_IPV4 \
	       VXLAN_GPE_TYPE_IPV6 VXLAN_GPE_TYPE_ETH VXLAN_GPE_TYPE_NSH \
	       VXLAN_GPE_TYPE_MPLS VXLAN_GPE_TYPE_GBP VXLAN_GPE_TYPE_VBNG \
	       ETHER_VXLAN_GPE_HLEN
replace_struct esp_hdr
replace_struct gre_hdr
replace_struct icmp_hdr
replace_define IP_ICMP_ECHO_REPLY IP_ICMP_ECHO_REQUEST
replace_struct ipv4_hdr ipv6_hdr
replace_define "IPv4(" IPV4_MAX_PKT_LEN IPV4_HDR_IHL_MASK IPV4_IHL_MULTIPLIER \
	       IPV4_HDR_DF_SHIFT IPV4_HDR_MF_SHIFT IPV4_HDR_FO_SHIFT \
	       IPV4_HDR_DF_FLAG IPV4_HDR_MF_FLAG IPV4_HDR_OFFSET_MASK \
	       IPV4_HDR_OFFSET_UNITS IPV4_ANY IPV4_LOOPBACK IPV4_BROADCAST \
	       IPV4_ALLHOSTS_GROUP IPV4_ALLRTRS_GROUP IPV4_MAX_LOCAL_GROUP \
	       IPV4_MIN_MCAST IPV4_MAX_MCAST IS_IPV4_MCAST IPV6_HDR_FL_SHIFT \
	       IPV6_HDR_TC_SHIFT IPV6_HDR_FL_MASK IPV6_HDR_TC_MASK
replace_struct sctp_hdr
replace_struct tcp_hdr
replace_struct udp_hdr

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 2/2] app/test: LPMv4 ABI Version Testing
  2019-05-28 11:51  3% ` [dpdk-dev] [PATCH 2/2] app/test: LPMv4 ABI Version Testing Ray Kinsella
@ 2019-05-29 13:50  4%   ` Aaron Conole
  0 siblings, 0 replies; 200+ results
From: Aaron Conole @ 2019-05-29 13:50 UTC (permalink / raw)
  To: Ray Kinsella; +Cc: bruce.richardson, vladimir.medvedkin, dev

Ray Kinsella <ray.kinsella@intel.com> writes:

> This second patch adds the LPM ABI Version Unit Tests, comprised of
>
> 1. Registering DPDK v2.0 and DPDK v16.04 ABI Versions with the
>    infrastructure.
> 2. Forward Porting the DPDK v2.0 and DPDK v16.04 LPM Unit Test
>    cases, remapping the LPM Library symbols to the appropriate versions.
> 3. Refactoring the lpm perf routes table to make this
>    functionality available to the v2.0 and v16.04 unit tests, forwarding
>    porting this code also from v2.0 etc would have increased the DPDK
>    codebase several MLoC.q
>
> Signed-off-by: Ray Kinsella <ray.kinsella@intel.com>
> ---

Hi Ray,

This patch causes build failures when building for AARCH64 platforms.

See:

https://travis-ci.com/ovsrobot/dpdk/jobs/203566521

>  app/test/Makefile              |   12 +-
>  app/test/meson.build           |    5 +
>  app/test/test_lpm.c            |    1 +
>  app/test/test_lpm_perf.c       |  293 +------
>  app/test/test_lpm_routes.c     |  287 +++++++
>  app/test/test_lpm_routes.h     |   25 +
>  app/test/v16.04/dcompat.h      |   23 +
>  app/test/v16.04/rte_lpm.h      |  463 +++++++++++
>  app/test/v16.04/rte_lpm_neon.h |  119 +++
>  app/test/v16.04/rte_lpm_sse.h  |  120 +++
>  app/test/v16.04/test_lpm.c     | 1405 ++++++++++++++++++++++++++++++++
>  app/test/v16.04/test_v1604.c   |   14 +
>  app/test/v2.0/dcompat.h        |   23 +
>  app/test/v2.0/rte_lpm.h        |  443 ++++++++++
>  app/test/v2.0/test_lpm.c       | 1306 +++++++++++++++++++++++++++++
>  app/test/v2.0/test_v20.c       |   14 +
>  16 files changed, 4261 insertions(+), 292 deletions(-)
>  create mode 100644 app/test/test_lpm_routes.c
>  create mode 100644 app/test/test_lpm_routes.h
>  create mode 100644 app/test/v16.04/dcompat.h
>  create mode 100644 app/test/v16.04/rte_lpm.h
>  create mode 100644 app/test/v16.04/rte_lpm_neon.h
>  create mode 100644 app/test/v16.04/rte_lpm_sse.h
>  create mode 100644 app/test/v16.04/test_lpm.c
>  create mode 100644 app/test/v16.04/test_v1604.c
>  create mode 100644 app/test/v2.0/dcompat.h
>  create mode 100644 app/test/v2.0/rte_lpm.h
>  create mode 100644 app/test/v2.0/test_lpm.c
>  create mode 100644 app/test/v2.0/test_v20.c
>
> diff --git a/app/test/Makefile b/app/test/Makefile
> index 68d6b4fbc..5899eb8b9 100644
> --- a/app/test/Makefile
> +++ b/app/test/Makefile
> @@ -78,6 +78,10 @@ SRCS-y += test_ring.c
>  SRCS-y += test_ring_perf.c
>  SRCS-y += test_pmd_perf.c
>  
> +#ABI Version Testing
> +SRCS-$(CONFIG_RTE_BUILD_SHARED_LIB) += v2.0/test_v20.c
> +SRCS-$(CONFIG_RTE_BUILD_SHARED_LIB) += v16.04/test_v1604.c
> +
>  ifeq ($(CONFIG_RTE_LIBRTE_TABLE),y)
>  SRCS-y += test_table.c
>  SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += test_table_pipeline.c
> @@ -107,7 +111,6 @@ SRCS-y += test_logs.c
>  SRCS-y += test_memcpy.c
>  SRCS-y += test_memcpy_perf.c
>  
> -
>  SRCS-$(CONFIG_RTE_LIBRTE_MEMBER) += test_member.c
>  SRCS-$(CONFIG_RTE_LIBRTE_MEMBER) += test_member_perf.c
>  
> @@ -122,11 +125,18 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_multiwriter.c
>  SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_readwrite.c
>  SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_readwrite_lf.c
>  
> +SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm_routes.c
>  SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm.c
>  SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm_perf.c
>  SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6.c
>  SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6_perf.c
>  
> +#LPM ABI Testing
> +ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
> +SRCS-$(CONFIG_RTE_LIBRTE_LPM) += v2.0/test_lpm.c
> +SRCS-$(CONFIG_RTE_LIBRTE_LPM) += v16.04/test_lpm.c
> +endif
> +
>  SRCS-y += test_debug.c
>  SRCS-y += test_errno.c
>  SRCS-y += test_tailq.c
> diff --git a/app/test/meson.build b/app/test/meson.build
> index 83391cef0..628f4e1ff 100644
> --- a/app/test/meson.build
> +++ b/app/test/meson.build
> @@ -4,6 +4,8 @@
>  test_sources = files('commands.c',
>  	'packet_burst_generator.c',
>  	'sample_packet_forward.c',
> +	'v2.0/test_v20.c',
> +	'v16.04/test_v1604.c',
>  	'test.c',
>  	'test_acl.c',
>  	'test_alarm.c',
> @@ -63,6 +65,9 @@ test_sources = files('commands.c',
>  	'test_lpm6.c',
>  	'test_lpm6_perf.c',
>  	'test_lpm_perf.c',
> +	'test_lpm_routes.c',
> +	'v2.0/test_lpm.c',
> +	'v16.04/test_lpm.c',
>  	'test_malloc.c',
>  	'test_mbuf.c',
>  	'test_member.c',
> diff --git a/app/test/test_lpm.c b/app/test/test_lpm.c
> index 5d697dd0f..bfa702677 100644
> --- a/app/test/test_lpm.c
> +++ b/app/test/test_lpm.c
> @@ -1277,6 +1277,7 @@ test_lpm(void)
>  	int status, global_status = 0;
>  
>  	for (i = 0; i < NUM_LPM_TESTS; i++) {
> +		printf("# test %02d\n", i);
>  		status = tests[i]();
>  		if (status < 0) {
>  			printf("ERROR: LPM Test %u: FAIL\n", i);
> diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
> index 3b98ce0c8..a6b8b35c2 100644
> --- a/app/test/test_lpm_perf.c
> +++ b/app/test/test_lpm_perf.c
> @@ -5,7 +5,6 @@
>  #include <stdio.h>
>  #include <stdint.h>
>  #include <stdlib.h>
> -#include <math.h>
>  
>  #include <rte_cycles.h>
>  #include <rte_random.h>
> @@ -13,6 +12,7 @@
>  #include <rte_ip.h>
>  #include <rte_lpm.h>
>  
> +#include "test_lpm_routes.h"
>  #include "test.h"
>  #include "test_xmmt_ops.h"
>  
> @@ -27,295 +27,6 @@
>  #define BATCH_SIZE (1 << 12)
>  #define BULK_SIZE 32
>  
> -#define MAX_RULE_NUM (1200000)
> -
> -struct route_rule {
> -	uint32_t ip;
> -	uint8_t depth;
> -};
> -
> -struct route_rule large_route_table[MAX_RULE_NUM];
> -
> -static uint32_t num_route_entries;
> -#define NUM_ROUTE_ENTRIES num_route_entries
> -
> -enum {
> -	IP_CLASS_A,
> -	IP_CLASS_B,
> -	IP_CLASS_C
> -};
> -
> -/* struct route_rule_count defines the total number of rules in following a/b/c
> - * each item in a[]/b[]/c[] is the number of common IP address class A/B/C, not
> - * including the ones for private local network.
> - */
> -struct route_rule_count {
> -	uint32_t a[RTE_LPM_MAX_DEPTH];
> -	uint32_t b[RTE_LPM_MAX_DEPTH];
> -	uint32_t c[RTE_LPM_MAX_DEPTH];
> -};
> -
> -/* All following numbers of each depth of each common IP class are just
> - * got from previous large constant table in app/test/test_lpm_routes.h .
> - * In order to match similar performance, they keep same depth and IP
> - * address coverage as previous constant table. These numbers don't
> - * include any private local IP address. As previous large const rule
> - * table was just dumped from a real router, there are no any IP address
> - * in class C or D.
> - */
> -static struct route_rule_count rule_count = {
> -	.a = { /* IP class A in which the most significant bit is 0 */
> -		    0, /* depth =  1 */
> -		    0, /* depth =  2 */
> -		    1, /* depth =  3 */
> -		    0, /* depth =  4 */
> -		    2, /* depth =  5 */
> -		    1, /* depth =  6 */
> -		    3, /* depth =  7 */
> -		  185, /* depth =  8 */
> -		   26, /* depth =  9 */
> -		   16, /* depth = 10 */
> -		   39, /* depth = 11 */
> -		  144, /* depth = 12 */
> -		  233, /* depth = 13 */
> -		  528, /* depth = 14 */
> -		  866, /* depth = 15 */
> -		 3856, /* depth = 16 */
> -		 3268, /* depth = 17 */
> -		 5662, /* depth = 18 */
> -		17301, /* depth = 19 */
> -		22226, /* depth = 20 */
> -		11147, /* depth = 21 */
> -		16746, /* depth = 22 */
> -		17120, /* depth = 23 */
> -		77578, /* depth = 24 */
> -		  401, /* depth = 25 */
> -		  656, /* depth = 26 */
> -		 1107, /* depth = 27 */
> -		 1121, /* depth = 28 */
> -		 2316, /* depth = 29 */
> -		  717, /* depth = 30 */
> -		   10, /* depth = 31 */
> -		   66  /* depth = 32 */
> -	},
> -	.b = { /* IP class A in which the most 2 significant bits are 10 */
> -		    0, /* depth =  1 */
> -		    0, /* depth =  2 */
> -		    0, /* depth =  3 */
> -		    0, /* depth =  4 */
> -		    1, /* depth =  5 */
> -		    1, /* depth =  6 */
> -		    1, /* depth =  7 */
> -		    3, /* depth =  8 */
> -		    3, /* depth =  9 */
> -		   30, /* depth = 10 */
> -		   25, /* depth = 11 */
> -		  168, /* depth = 12 */
> -		  305, /* depth = 13 */
> -		  569, /* depth = 14 */
> -		 1129, /* depth = 15 */
> -		50800, /* depth = 16 */
> -		 1645, /* depth = 17 */
> -		 1820, /* depth = 18 */
> -		 3506, /* depth = 19 */
> -		 3258, /* depth = 20 */
> -		 3424, /* depth = 21 */
> -		 4971, /* depth = 22 */
> -		 6885, /* depth = 23 */
> -		39771, /* depth = 24 */
> -		  424, /* depth = 25 */
> -		  170, /* depth = 26 */
> -		  433, /* depth = 27 */
> -		   92, /* depth = 28 */
> -		  366, /* depth = 29 */
> -		  377, /* depth = 30 */
> -		    2, /* depth = 31 */
> -		  200  /* depth = 32 */
> -	},
> -	.c = { /* IP class A in which the most 3 significant bits are 110 */
> -		     0, /* depth =  1 */
> -		     0, /* depth =  2 */
> -		     0, /* depth =  3 */
> -		     0, /* depth =  4 */
> -		     0, /* depth =  5 */
> -		     0, /* depth =  6 */
> -		     0, /* depth =  7 */
> -		    12, /* depth =  8 */
> -		     8, /* depth =  9 */
> -		     9, /* depth = 10 */
> -		    33, /* depth = 11 */
> -		    69, /* depth = 12 */
> -		   237, /* depth = 13 */
> -		  1007, /* depth = 14 */
> -		  1717, /* depth = 15 */
> -		 14663, /* depth = 16 */
> -		  8070, /* depth = 17 */
> -		 16185, /* depth = 18 */
> -		 48261, /* depth = 19 */
> -		 36870, /* depth = 20 */
> -		 33960, /* depth = 21 */
> -		 50638, /* depth = 22 */
> -		 61422, /* depth = 23 */
> -		466549, /* depth = 24 */
> -		  1829, /* depth = 25 */
> -		  4824, /* depth = 26 */
> -		  4927, /* depth = 27 */
> -		  5914, /* depth = 28 */
> -		 10254, /* depth = 29 */
> -		  4905, /* depth = 30 */
> -		     1, /* depth = 31 */
> -		   716  /* depth = 32 */
> -	}
> -};
> -
> -static void generate_random_rule_prefix(uint32_t ip_class, uint8_t depth)
> -{
> -/* IP address class A, the most significant bit is 0 */
> -#define IP_HEAD_MASK_A			0x00000000
> -#define IP_HEAD_BIT_NUM_A		1
> -
> -/* IP address class B, the most significant 2 bits are 10 */
> -#define IP_HEAD_MASK_B			0x80000000
> -#define IP_HEAD_BIT_NUM_B		2
> -
> -/* IP address class C, the most significant 3 bits are 110 */
> -#define IP_HEAD_MASK_C			0xC0000000
> -#define IP_HEAD_BIT_NUM_C		3
> -
> -	uint32_t class_depth;
> -	uint32_t range;
> -	uint32_t mask;
> -	uint32_t step;
> -	uint32_t start;
> -	uint32_t fixed_bit_num;
> -	uint32_t ip_head_mask;
> -	uint32_t rule_num;
> -	uint32_t k;
> -	struct route_rule *ptr_rule;
> -
> -	if (ip_class == IP_CLASS_A) {        /* IP Address class A */
> -		fixed_bit_num = IP_HEAD_BIT_NUM_A;
> -		ip_head_mask = IP_HEAD_MASK_A;
> -		rule_num = rule_count.a[depth - 1];
> -	} else if (ip_class == IP_CLASS_B) { /* IP Address class B */
> -		fixed_bit_num = IP_HEAD_BIT_NUM_B;
> -		ip_head_mask = IP_HEAD_MASK_B;
> -		rule_num = rule_count.b[depth - 1];
> -	} else {                             /* IP Address class C */
> -		fixed_bit_num = IP_HEAD_BIT_NUM_C;
> -		ip_head_mask = IP_HEAD_MASK_C;
> -		rule_num = rule_count.c[depth - 1];
> -	}
> -
> -	if (rule_num == 0)
> -		return;
> -
> -	/* the number of rest bits which don't include the most significant
> -	 * fixed bits for this IP address class
> -	 */
> -	class_depth = depth - fixed_bit_num;
> -
> -	/* range is the maximum number of rules for this depth and
> -	 * this IP address class
> -	 */
> -	range = 1 << class_depth;
> -
> -	/* only mask the most depth significant generated bits
> -	 * except fixed bits for IP address class
> -	 */
> -	mask = range - 1;
> -
> -	/* Widen coverage of IP address in generated rules */
> -	if (range <= rule_num)
> -		step = 1;
> -	else
> -		step = round((double)range / rule_num);
> -
> -	/* Only generate rest bits except the most significant
> -	 * fixed bits for IP address class
> -	 */
> -	start = lrand48() & mask;
> -	ptr_rule = &large_route_table[num_route_entries];
> -	for (k = 0; k < rule_num; k++) {
> -		ptr_rule->ip = (start << (RTE_LPM_MAX_DEPTH - depth))
> -			| ip_head_mask;
> -		ptr_rule->depth = depth;
> -		ptr_rule++;
> -		start = (start + step) & mask;
> -	}
> -	num_route_entries += rule_num;
> -}
> -
> -static void insert_rule_in_random_pos(uint32_t ip, uint8_t depth)
> -{
> -	uint32_t pos;
> -	int try_count = 0;
> -	struct route_rule tmp;
> -
> -	do {
> -		pos = lrand48();
> -		try_count++;
> -	} while ((try_count < 10) && (pos > num_route_entries));
> -
> -	if ((pos > num_route_entries) || (pos >= MAX_RULE_NUM))
> -		pos = num_route_entries >> 1;
> -
> -	tmp = large_route_table[pos];
> -	large_route_table[pos].ip = ip;
> -	large_route_table[pos].depth = depth;
> -	if (num_route_entries < MAX_RULE_NUM)
> -		large_route_table[num_route_entries++] = tmp;
> -}
> -
> -static void generate_large_route_rule_table(void)
> -{
> -	uint32_t ip_class;
> -	uint8_t  depth;
> -
> -	num_route_entries = 0;
> -	memset(large_route_table, 0, sizeof(large_route_table));
> -
> -	for (ip_class = IP_CLASS_A; ip_class <= IP_CLASS_C; ip_class++) {
> -		for (depth = 1; depth <= RTE_LPM_MAX_DEPTH; depth++) {
> -			generate_random_rule_prefix(ip_class, depth);
> -		}
> -	}
> -
> -	/* Add following rules to keep same as previous large constant table,
> -	 * they are 4 rules with private local IP address and 1 all-zeros prefix
> -	 * with depth = 8.
> -	 */
> -	insert_rule_in_random_pos(IPv4(0, 0, 0, 0), 8);
> -	insert_rule_in_random_pos(IPv4(10, 2, 23, 147), 32);
> -	insert_rule_in_random_pos(IPv4(192, 168, 100, 10), 24);
> -	insert_rule_in_random_pos(IPv4(192, 168, 25, 100), 24);
> -	insert_rule_in_random_pos(IPv4(192, 168, 129, 124), 32);
> -}
> -
> -static void
> -print_route_distribution(const struct route_rule *table, uint32_t n)
> -{
> -	unsigned i, j;
> -
> -	printf("Route distribution per prefix width: \n");
> -	printf("DEPTH    QUANTITY (PERCENT)\n");
> -	printf("--------------------------- \n");
> -
> -	/* Count depths. */
> -	for (i = 1; i <= 32; i++) {
> -		unsigned depth_counter = 0;
> -		double percent_hits;
> -
> -		for (j = 0; j < n; j++)
> -			if (table[j].depth == (uint8_t) i)
> -				depth_counter++;
> -
> -		percent_hits = ((double)depth_counter)/((double)n) * 100;
> -		printf("%.2u%15u (%.2f)\n", i, depth_counter, percent_hits);
> -	}
> -	printf("\n");
> -}
> -
>  static int
>  test_lpm_perf(void)
>  {
> @@ -375,7 +86,7 @@ test_lpm_perf(void)
>  			(unsigned) cache_line_counter, (unsigned) cache_line_counter * 64);
>  
>  	printf("Average LPM Add: %g cycles\n",
> -			(double)total_time / NUM_ROUTE_ENTRIES);
> +	       (double)total_time / NUM_ROUTE_ENTRIES);
>  
>  	/* Measure single Lookup */
>  	total_time = 0;
> diff --git a/app/test/test_lpm_routes.c b/app/test/test_lpm_routes.c
> new file mode 100644
> index 000000000..08128542a
> --- /dev/null
> +++ b/app/test/test_lpm_routes.c
> @@ -0,0 +1,287 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2010-2019 Intel Corporation
> + */
> +
> +#include <math.h>
> +
> +#include "rte_lpm.h"
> +#include "test_lpm_routes.h"
> +
> +uint32_t num_route_entries;
> +struct route_rule large_route_table[MAX_RULE_NUM];
> +
> +enum {
> +	IP_CLASS_A,
> +	IP_CLASS_B,
> +	IP_CLASS_C
> +};
> +
> +/* struct route_rule_count defines the total number of rules in following a/b/c
> + * each item in a[]/b[]/c[] is the number of common IP address class A/B/C, not
> + * including the ones for private local network.
> + */
> +struct route_rule_count {
> +	uint32_t a[RTE_LPM_MAX_DEPTH];
> +	uint32_t b[RTE_LPM_MAX_DEPTH];
> +	uint32_t c[RTE_LPM_MAX_DEPTH];
> +};
> +
> +/* All following numbers of each depth of each common IP class are just
> + * got from previous large constant table in app/test/test_lpm_routes.h .
> + * In order to match similar performance, they keep same depth and IP
> + * address coverage as previous constant table. These numbers don't
> + * include any private local IP address. As previous large const rule
> + * table was just dumped from a real router, there are no any IP address
> + * in class C or D.
> + */
> +static struct route_rule_count rule_count = {
> +	.a = { /* IP class A in which the most significant bit is 0 */
> +		    0, /* depth =  1 */
> +		    0, /* depth =  2 */
> +		    1, /* depth =  3 */
> +		    0, /* depth =  4 */
> +		    2, /* depth =  5 */
> +		    1, /* depth =  6 */
> +		    3, /* depth =  7 */
> +		  185, /* depth =  8 */
> +		   26, /* depth =  9 */
> +		   16, /* depth = 10 */
> +		   39, /* depth = 11 */
> +		  144, /* depth = 12 */
> +		  233, /* depth = 13 */
> +		  528, /* depth = 14 */
> +		  866, /* depth = 15 */
> +		 3856, /* depth = 16 */
> +		 3268, /* depth = 17 */
> +		 5662, /* depth = 18 */
> +		17301, /* depth = 19 */
> +		22226, /* depth = 20 */
> +		11147, /* depth = 21 */
> +		16746, /* depth = 22 */
> +		17120, /* depth = 23 */
> +		77578, /* depth = 24 */
> +		  401, /* depth = 25 */
> +		  656, /* depth = 26 */
> +		 1107, /* depth = 27 */
> +		 1121, /* depth = 28 */
> +		 2316, /* depth = 29 */
> +		  717, /* depth = 30 */
> +		   10, /* depth = 31 */
> +		   66  /* depth = 32 */
> +	},
> +	.b = { /* IP class A in which the most 2 significant bits are 10 */
> +		    0, /* depth =  1 */
> +		    0, /* depth =  2 */
> +		    0, /* depth =  3 */
> +		    0, /* depth =  4 */
> +		    1, /* depth =  5 */
> +		    1, /* depth =  6 */
> +		    1, /* depth =  7 */
> +		    3, /* depth =  8 */
> +		    3, /* depth =  9 */
> +		   30, /* depth = 10 */
> +		   25, /* depth = 11 */
> +		  168, /* depth = 12 */
> +		  305, /* depth = 13 */
> +		  569, /* depth = 14 */
> +		 1129, /* depth = 15 */
> +		50800, /* depth = 16 */
> +		 1645, /* depth = 17 */
> +		 1820, /* depth = 18 */
> +		 3506, /* depth = 19 */
> +		 3258, /* depth = 20 */
> +		 3424, /* depth = 21 */
> +		 4971, /* depth = 22 */
> +		 6885, /* depth = 23 */
> +		39771, /* depth = 24 */
> +		  424, /* depth = 25 */
> +		  170, /* depth = 26 */
> +		  433, /* depth = 27 */
> +		   92, /* depth = 28 */
> +		  366, /* depth = 29 */
> +		  377, /* depth = 30 */
> +		    2, /* depth = 31 */
> +		  200  /* depth = 32 */
> +	},
> +	.c = { /* IP class A in which the most 3 significant bits are 110 */
> +		     0, /* depth =  1 */
> +		     0, /* depth =  2 */
> +		     0, /* depth =  3 */
> +		     0, /* depth =  4 */
> +		     0, /* depth =  5 */
> +		     0, /* depth =  6 */
> +		     0, /* depth =  7 */
> +		    12, /* depth =  8 */
> +		     8, /* depth =  9 */
> +		     9, /* depth = 10 */
> +		    33, /* depth = 11 */
> +		    69, /* depth = 12 */
> +		   237, /* depth = 13 */
> +		  1007, /* depth = 14 */
> +		  1717, /* depth = 15 */
> +		 14663, /* depth = 16 */
> +		  8070, /* depth = 17 */
> +		 16185, /* depth = 18 */
> +		 48261, /* depth = 19 */
> +		 36870, /* depth = 20 */
> +		 33960, /* depth = 21 */
> +		 50638, /* depth = 22 */
> +		 61422, /* depth = 23 */
> +		466549, /* depth = 24 */
> +		  1829, /* depth = 25 */
> +		  4824, /* depth = 26 */
> +		  4927, /* depth = 27 */
> +		  5914, /* depth = 28 */
> +		 10254, /* depth = 29 */
> +		  4905, /* depth = 30 */
> +		     1, /* depth = 31 */
> +		   716  /* depth = 32 */
> +	}
> +};
> +
> +static void generate_random_rule_prefix(uint32_t ip_class, uint8_t depth)
> +{
> +/* IP address class A, the most significant bit is 0 */
> +#define IP_HEAD_MASK_A			0x00000000
> +#define IP_HEAD_BIT_NUM_A		1
> +
> +/* IP address class B, the most significant 2 bits are 10 */
> +#define IP_HEAD_MASK_B			0x80000000
> +#define IP_HEAD_BIT_NUM_B		2
> +
> +/* IP address class C, the most significant 3 bits are 110 */
> +#define IP_HEAD_MASK_C			0xC0000000
> +#define IP_HEAD_BIT_NUM_C		3
> +
> +	uint32_t class_depth;
> +	uint32_t range;
> +	uint32_t mask;
> +	uint32_t step;
> +	uint32_t start;
> +	uint32_t fixed_bit_num;
> +	uint32_t ip_head_mask;
> +	uint32_t rule_num;
> +	uint32_t k;
> +	struct route_rule *ptr_rule;
> +
> +	if (ip_class == IP_CLASS_A) {        /* IP Address class A */
> +		fixed_bit_num = IP_HEAD_BIT_NUM_A;
> +		ip_head_mask = IP_HEAD_MASK_A;
> +		rule_num = rule_count.a[depth - 1];
> +	} else if (ip_class == IP_CLASS_B) { /* IP Address class B */
> +		fixed_bit_num = IP_HEAD_BIT_NUM_B;
> +		ip_head_mask = IP_HEAD_MASK_B;
> +		rule_num = rule_count.b[depth - 1];
> +	} else {                             /* IP Address class C */
> +		fixed_bit_num = IP_HEAD_BIT_NUM_C;
> +		ip_head_mask = IP_HEAD_MASK_C;
> +		rule_num = rule_count.c[depth - 1];
> +	}
> +
> +	if (rule_num == 0)
> +		return;
> +
> +	/* the number of rest bits which don't include the most significant
> +	 * fixed bits for this IP address class
> +	 */
> +	class_depth = depth - fixed_bit_num;
> +
> +	/* range is the maximum number of rules for this depth and
> +	 * this IP address class
> +	 */
> +	range = 1 << class_depth;
> +
> +	/* only mask the most depth significant generated bits
> +	 * except fixed bits for IP address class
> +	 */
> +	mask = range - 1;
> +
> +	/* Widen coverage of IP address in generated rules */
> +	if (range <= rule_num)
> +		step = 1;
> +	else
> +		step = round((double)range / rule_num);
> +
> +	/* Only generate rest bits except the most significant
> +	 * fixed bits for IP address class
> +	 */
> +	start = lrand48() & mask;
> +	ptr_rule = &large_route_table[num_route_entries];
> +	for (k = 0; k < rule_num; k++) {
> +		ptr_rule->ip = (start << (RTE_LPM_MAX_DEPTH - depth))
> +			| ip_head_mask;
> +		ptr_rule->depth = depth;
> +		ptr_rule++;
> +		start = (start + step) & mask;
> +	}
> +	num_route_entries += rule_num;
> +}
> +
> +static void insert_rule_in_random_pos(uint32_t ip, uint8_t depth)
> +{
> +	uint32_t pos;
> +	int try_count = 0;
> +	struct route_rule tmp;
> +
> +	do {
> +		pos = lrand48();
> +		try_count++;
> +	} while ((try_count < 10) && (pos > num_route_entries));
> +
> +	if ((pos > num_route_entries) || (pos >= MAX_RULE_NUM))
> +		pos = num_route_entries >> 1;
> +
> +	tmp = large_route_table[pos];
> +	large_route_table[pos].ip = ip;
> +	large_route_table[pos].depth = depth;
> +	if (num_route_entries < MAX_RULE_NUM)
> +		large_route_table[num_route_entries++] = tmp;
> +}
> +
> +void generate_large_route_rule_table(void)
> +{
> +	uint32_t ip_class;
> +	uint8_t  depth;
> +
> +	num_route_entries = 0;
> +	memset(large_route_table, 0, sizeof(large_route_table));
> +
> +	for (ip_class = IP_CLASS_A; ip_class <= IP_CLASS_C; ip_class++) {
> +		for (depth = 1; depth <= RTE_LPM_MAX_DEPTH; depth++)
> +			generate_random_rule_prefix(ip_class, depth);
> +	}
> +
> +	/* Add following rules to keep same as previous large constant table,
> +	 * they are 4 rules with private local IP address and 1 all-zeros prefix
> +	 * with depth = 8.
> +	 */
> +	insert_rule_in_random_pos(IPv4(0, 0, 0, 0), 8);
> +	insert_rule_in_random_pos(IPv4(10, 2, 23, 147), 32);
> +	insert_rule_in_random_pos(IPv4(192, 168, 100, 10), 24);
> +	insert_rule_in_random_pos(IPv4(192, 168, 25, 100), 24);
> +	insert_rule_in_random_pos(IPv4(192, 168, 129, 124), 32);
> +}
> +
> +void
> +print_route_distribution(const struct route_rule *table, uint32_t n)
> +{
> +	unsigned int i, j;
> +
> +	printf("Route distribution per prefix width: \n");
> +	printf("DEPTH    QUANTITY (PERCENT)\n");
> +	printf("---------------------------\n");
> +
> +	/* Count depths. */
> +	for (i = 1; i <= 32; i++) {
> +		unsigned int depth_counter = 0;
> +		double percent_hits;
> +
> +		for (j = 0; j < n; j++)
> +			if (table[j].depth == (uint8_t) i)
> +				depth_counter++;
> +
> +		percent_hits = ((double)depth_counter)/((double)n) * 100;
> +		printf("%.2u%15u (%.2f)\n", i, depth_counter, percent_hits);
> +	}
> +	printf("\n");
> +}
> diff --git a/app/test/test_lpm_routes.h b/app/test/test_lpm_routes.h
> new file mode 100644
> index 000000000..c7874ea8f
> --- /dev/null
> +++ b/app/test/test_lpm_routes.h
> @@ -0,0 +1,25 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2010-2019 Intel Corporation
> + */
> +
> +#ifndef _TEST_LPM_ROUTES_H_
> +#define _TEST_LPM_ROUTES_H_
> +
> +#include <rte_ip.h>
> +
> +#define MAX_RULE_NUM (1200000)
> +
> +struct route_rule {
> +	uint32_t ip;
> +	uint8_t depth;
> +};
> +
> +extern struct route_rule large_route_table[MAX_RULE_NUM];
> +
> +extern uint32_t num_route_entries;
> +#define NUM_ROUTE_ENTRIES num_route_entries
> +
> +void generate_large_route_rule_table(void);
> +void print_route_distribution(const struct route_rule *table, uint32_t n);
> +
> +#endif
> diff --git a/app/test/v16.04/dcompat.h b/app/test/v16.04/dcompat.h
> new file mode 100644
> index 000000000..889c3b503
> --- /dev/null
> +++ b/app/test/v16.04/dcompat.h
> @@ -0,0 +1,23 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2010-2019 Intel Corporation
> + */
> +
> +#ifndef _DCOMPAT_H_
> +#define _DCOMPAT_H_
> +
> +#define ABI_VERSION DPDK_16.04
> +
> +#define MAP_ABI_SYMBOL(name) \
> +	MAP_ABI_SYMBOL_VERSION(name, ABI_VERSION)
> +
> +MAP_ABI_SYMBOL(rte_lpm_add);
> +MAP_ABI_SYMBOL(rte_lpm_create);
> +MAP_ABI_SYMBOL(rte_lpm_delete);
> +MAP_ABI_SYMBOL(rte_lpm_delete_all);
> +MAP_ABI_SYMBOL(rte_lpm_find_existing);
> +MAP_ABI_SYMBOL(rte_lpm_free);
> +MAP_ABI_SYMBOL(rte_lpm_is_rule_present);
> +
> +#undef MAP_ABI_SYMBOL
> +
> +#endif
> diff --git a/app/test/v16.04/rte_lpm.h b/app/test/v16.04/rte_lpm.h
> new file mode 100644
> index 000000000..c3348fbc1
> --- /dev/null
> +++ b/app/test/v16.04/rte_lpm.h
> @@ -0,0 +1,463 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2010-2014 Intel Corporation
> + */
> +
> +#ifndef _RTE_LPM_H_
> +#define _RTE_LPM_H_
> +
> +/**
> + * @file
> + * RTE Longest Prefix Match (LPM)
> + */
> +
> +#include <errno.h>
> +#include <sys/queue.h>
> +#include <stdint.h>
> +#include <stdlib.h>
> +#include <rte_branch_prediction.h>
> +#include <rte_byteorder.h>
> +#include <rte_memory.h>
> +#include <rte_common.h>
> +#include <rte_vect.h>
> +#include <rte_compat.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/** Max number of characters in LPM name. */
> +#define RTE_LPM_NAMESIZE                32
> +
> +/** Maximum depth value possible for IPv4 LPM. */
> +#define RTE_LPM_MAX_DEPTH               32
> +
> +/** @internal Total number of tbl24 entries. */
> +#define RTE_LPM_TBL24_NUM_ENTRIES       (1 << 24)
> +
> +/** @internal Number of entries in a tbl8 group. */
> +#define RTE_LPM_TBL8_GROUP_NUM_ENTRIES  256
> +
> +/** @internal Max number of tbl8 groups in the tbl8. */
> +#define RTE_LPM_MAX_TBL8_NUM_GROUPS         (1 << 24)
> +
> +/** @internal Total number of tbl8 groups in the tbl8. */
> +#define RTE_LPM_TBL8_NUM_GROUPS         256
> +
> +/** @internal Total number of tbl8 entries. */
> +#define RTE_LPM_TBL8_NUM_ENTRIES        (RTE_LPM_TBL8_NUM_GROUPS * \
> +					RTE_LPM_TBL8_GROUP_NUM_ENTRIES)
> +
> +/** @internal Macro to enable/disable run-time checks. */
> +#if defined(RTE_LIBRTE_LPM_DEBUG)
> +#define RTE_LPM_RETURN_IF_TRUE(cond, retval) do { \
> +	if (cond) \
> +		return (retval); \
> +} while (0)
> +#else
> +#define RTE_LPM_RETURN_IF_TRUE(cond, retval)
> +#endif
> +
> +/** @internal bitmask with valid and valid_group fields set */
> +#define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x03000000
> +
> +/** Bitmask used to indicate successful lookup */
> +#define RTE_LPM_LOOKUP_SUCCESS          0x01000000
> +
> +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
> +/** @internal Tbl24 entry structure. */
> +struct rte_lpm_tbl_entry_v20 {
> +	/**
> +	 * Stores Next hop (tbl8 or tbl24 when valid_group is not set) or
> +	 * a group index pointing to a tbl8 structure (tbl24 only, when
> +	 * valid_group is set)
> +	 */
> +	union {
> +		uint8_t next_hop;
> +		uint8_t group_idx;
> +	};
> +	/* Using single uint8_t to store 3 values. */
> +	uint8_t valid     :1;   /**< Validation flag. */
> +	/**
> +	 * For tbl24:
> +	 *  - valid_group == 0: entry stores a next hop
> +	 *  - valid_group == 1: entry stores a group_index pointing to a tbl8
> +	 * For tbl8:
> +	 *  - valid_group indicates whether the current tbl8 is in use or not
> +	 */
> +	uint8_t valid_group :1;
> +	uint8_t depth       :6; /**< Rule depth. */
> +};
> +
> +struct rte_lpm_tbl_entry {
> +	/**
> +	 * Stores Next hop (tbl8 or tbl24 when valid_group is not set) or
> +	 * a group index pointing to a tbl8 structure (tbl24 only, when
> +	 * valid_group is set)
> +	 */
> +	uint32_t next_hop    :24;
> +	/* Using single uint8_t to store 3 values. */
> +	uint32_t valid       :1;   /**< Validation flag. */
> +	/**
> +	 * For tbl24:
> +	 *  - valid_group == 0: entry stores a next hop
> +	 *  - valid_group == 1: entry stores a group_index pointing to a tbl8
> +	 * For tbl8:
> +	 *  - valid_group indicates whether the current tbl8 is in use or not
> +	 */
> +	uint32_t valid_group :1;
> +	uint32_t depth       :6; /**< Rule depth. */
> +};
> +
> +#else
> +struct rte_lpm_tbl_entry_v20 {
> +	uint8_t depth       :6;
> +	uint8_t valid_group :1;
> +	uint8_t valid       :1;
> +	union {
> +		uint8_t group_idx;
> +		uint8_t next_hop;
> +	};
> +};
> +
> +struct rte_lpm_tbl_entry {
> +	uint32_t depth       :6;
> +	uint32_t valid_group :1;
> +	uint32_t valid       :1;
> +	uint32_t next_hop    :24;
> +
> +};
> +
> +#endif
> +
> +/** LPM configuration structure. */
> +struct rte_lpm_config {
> +	uint32_t max_rules;      /**< Max number of rules. */
> +	uint32_t number_tbl8s;   /**< Number of tbl8s to allocate. */
> +	int flags;               /**< This field is currently unused. */
> +};
> +
> +/** @internal Rule structure. */
> +struct rte_lpm_rule_v20 {
> +	uint32_t ip; /**< Rule IP address. */
> +	uint8_t  next_hop; /**< Rule next hop. */
> +};
> +
> +struct rte_lpm_rule {
> +	uint32_t ip; /**< Rule IP address. */
> +	uint32_t next_hop; /**< Rule next hop. */
> +};
> +
> +/** @internal Contains metadata about the rules table. */
> +struct rte_lpm_rule_info {
> +	uint32_t used_rules; /**< Used rules so far. */
> +	uint32_t first_rule; /**< Indexes the first rule of a given depth. */
> +};
> +
> +/** @internal LPM structure. */
> +struct rte_lpm_v20 {
> +	/* LPM metadata. */
> +	char name[RTE_LPM_NAMESIZE];        /**< Name of the lpm. */
> +	uint32_t max_rules; /**< Max. balanced rules per lpm. */
> +	struct rte_lpm_rule_info rule_info[RTE_LPM_MAX_DEPTH]; /**< Rule info table. */
> +
> +	/* LPM Tables. */
> +	struct rte_lpm_tbl_entry_v20 tbl24[RTE_LPM_TBL24_NUM_ENTRIES]
> +			__rte_cache_aligned; /**< LPM tbl24 table. */
> +	struct rte_lpm_tbl_entry_v20 tbl8[RTE_LPM_TBL8_NUM_ENTRIES]
> +			__rte_cache_aligned; /**< LPM tbl8 table. */
> +	struct rte_lpm_rule_v20 rules_tbl[0] \
> +			__rte_cache_aligned; /**< LPM rules. */
> +};
> +
> +struct rte_lpm {
> +	/* LPM metadata. */
> +	char name[RTE_LPM_NAMESIZE];        /**< Name of the lpm. */
> +	uint32_t max_rules; /**< Max. balanced rules per lpm. */
> +	uint32_t number_tbl8s; /**< Number of tbl8s. */
> +	struct rte_lpm_rule_info rule_info[RTE_LPM_MAX_DEPTH]; /**< Rule info table. */
> +
> +	/* LPM Tables. */
> +	struct rte_lpm_tbl_entry tbl24[RTE_LPM_TBL24_NUM_ENTRIES]
> +			__rte_cache_aligned; /**< LPM tbl24 table. */
> +	struct rte_lpm_tbl_entry *tbl8; /**< LPM tbl8 table. */
> +	struct rte_lpm_rule *rules_tbl; /**< LPM rules. */
> +};
> +
> +/**
> + * Create an LPM object.
> + *
> + * @param name
> + *   LPM object name
> + * @param socket_id
> + *   NUMA socket ID for LPM table memory allocation
> + * @param config
> + *   Structure containing the configuration
> + * @return
> + *   Handle to LPM object on success, NULL otherwise with rte_errno set
> + *   to an appropriate values. Possible rte_errno values include:
> + *    - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
> + *    - E_RTE_SECONDARY - function was called from a secondary process instance
> + *    - EINVAL - invalid parameter passed to function
> + *    - ENOSPC - the maximum number of memzones has already been allocated
> + *    - EEXIST - a memzone with the same name already exists
> + *    - ENOMEM - no appropriate memory area found in which to create memzone
> + */
> +struct rte_lpm *
> +rte_lpm_create(const char *name, int socket_id,
> +		const struct rte_lpm_config *config);
> +struct rte_lpm_v20 *
> +rte_lpm_create_v20(const char *name, int socket_id, int max_rules, int flags);
> +struct rte_lpm *
> +rte_lpm_create_v1604(const char *name, int socket_id,
> +		const struct rte_lpm_config *config);
> +
> +/**
> + * Find an existing LPM object and return a pointer to it.
> + *
> + * @param name
> + *   Name of the lpm object as passed to rte_lpm_create()
> + * @return
> + *   Pointer to lpm object or NULL if object not found with rte_errno
> + *   set appropriately. Possible rte_errno values include:
> + *    - ENOENT - required entry not available to return.
> + */
> +struct rte_lpm *
> +rte_lpm_find_existing(const char *name);
> +struct rte_lpm_v20 *
> +rte_lpm_find_existing_v20(const char *name);
> +struct rte_lpm *
> +rte_lpm_find_existing_v1604(const char *name);
> +
> +/**
> + * Free an LPM object.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @return
> + *   None
> + */
> +void
> +rte_lpm_free(struct rte_lpm *lpm);
> +void
> +rte_lpm_free_v20(struct rte_lpm_v20 *lpm);
> +void
> +rte_lpm_free_v1604(struct rte_lpm *lpm);
> +
> +/**
> + * Add a rule to the LPM table.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @param ip
> + *   IP of the rule to be added to the LPM table
> + * @param depth
> + *   Depth of the rule to be added to the LPM table
> + * @param next_hop
> + *   Next hop of the rule to be added to the LPM table
> + * @return
> + *   0 on success, negative value otherwise
> + */
> +int
> +rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint32_t next_hop);
> +int
> +rte_lpm_add_v20(struct rte_lpm_v20 *lpm, uint32_t ip, uint8_t depth,
> +		uint8_t next_hop);
> +int
> +rte_lpm_add_v1604(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,
> +		uint32_t next_hop);
> +
> +/**
> + * Check if a rule is present in the LPM table,
> + * and provide its next hop if it is.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @param ip
> + *   IP of the rule to be searched
> + * @param depth
> + *   Depth of the rule to searched
> + * @param next_hop
> + *   Next hop of the rule (valid only if it is found)
> + * @return
> + *   1 if the rule exists, 0 if it does not, a negative value on failure
> + */
> +int
> +rte_lpm_is_rule_present(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,
> +uint32_t *next_hop);
> +int
> +rte_lpm_is_rule_present_v20(struct rte_lpm_v20 *lpm, uint32_t ip, uint8_t depth,
> +uint8_t *next_hop);
> +int
> +rte_lpm_is_rule_present_v1604(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,
> +uint32_t *next_hop);
> +
> +/**
> + * Delete a rule from the LPM table.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @param ip
> + *   IP of the rule to be deleted from the LPM table
> + * @param depth
> + *   Depth of the rule to be deleted from the LPM table
> + * @return
> + *   0 on success, negative value otherwise
> + */
> +int
> +rte_lpm_delete(struct rte_lpm *lpm, uint32_t ip, uint8_t depth);
> +int
> +rte_lpm_delete_v20(struct rte_lpm_v20 *lpm, uint32_t ip, uint8_t depth);
> +int
> +rte_lpm_delete_v1604(struct rte_lpm *lpm, uint32_t ip, uint8_t depth);
> +
> +/**
> + * Delete all rules from the LPM table.
> + *
> + * @param lpm
> + *   LPM object handle
> + */
> +void
> +rte_lpm_delete_all(struct rte_lpm *lpm);
> +void
> +rte_lpm_delete_all_v20(struct rte_lpm_v20 *lpm);
> +void
> +rte_lpm_delete_all_v1604(struct rte_lpm *lpm);
> +
> +/**
> + * Lookup an IP into the LPM table.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @param ip
> + *   IP to be looked up in the LPM table
> + * @param next_hop
> + *   Next hop of the most specific rule found for IP (valid on lookup hit only)
> + * @return
> + *   -EINVAL for incorrect arguments, -ENOENT on lookup miss, 0 on lookup hit
> + */
> +static inline int
> +rte_lpm_lookup(struct rte_lpm *lpm, uint32_t ip, uint32_t *next_hop)
> +{
> +	unsigned tbl24_index = (ip >> 8);
> +	uint32_t tbl_entry;
> +	const uint32_t *ptbl;
> +
> +	/* DEBUG: Check user input arguments. */
> +	RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (next_hop == NULL)), -EINVAL);
> +
> +	/* Copy tbl24 entry */
> +	ptbl = (const uint32_t *)(&lpm->tbl24[tbl24_index]);
> +	tbl_entry = *ptbl;
> +
> +	/* Copy tbl8 entry (only if needed) */
> +	if (unlikely((tbl_entry & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +
> +		unsigned tbl8_index = (uint8_t)ip +
> +				(((uint32_t)tbl_entry & 0x00FFFFFF) *
> +						RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
> +
> +		ptbl = (const uint32_t *)&lpm->tbl8[tbl8_index];
> +		tbl_entry = *ptbl;
> +	}
> +
> +	*next_hop = ((uint32_t)tbl_entry & 0x00FFFFFF);
> +	return (tbl_entry & RTE_LPM_LOOKUP_SUCCESS) ? 0 : -ENOENT;
> +}
> +
> +/**
> + * Lookup multiple IP addresses in an LPM table. This may be implemented as a
> + * macro, so the address of the function should not be used.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @param ips
> + *   Array of IPs to be looked up in the LPM table
> + * @param next_hops
> + *   Next hop of the most specific rule found for IP (valid on lookup hit only).
> + *   This is an array of two byte values. The most significant byte in each
> + *   value says whether the lookup was successful (bitmask
> + *   RTE_LPM_LOOKUP_SUCCESS is set). The least significant byte is the
> + *   actual next hop.
> + * @param n
> + *   Number of elements in ips (and next_hops) array to lookup. This should be a
> + *   compile time constant, and divisible by 8 for best performance.
> + *  @return
> + *   -EINVAL for incorrect arguments, otherwise 0
> + */
> +#define rte_lpm_lookup_bulk(lpm, ips, next_hops, n) \
> +		rte_lpm_lookup_bulk_func(lpm, ips, next_hops, n)
> +
> +static inline int
> +rte_lpm_lookup_bulk_func(const struct rte_lpm *lpm, const uint32_t *ips,
> +		uint32_t *next_hops, const unsigned n)
> +{
> +	unsigned i;
> +	unsigned tbl24_indexes[n];
> +	const uint32_t *ptbl;
> +
> +	/* DEBUG: Check user input arguments. */
> +	RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (ips == NULL) ||
> +			(next_hops == NULL)), -EINVAL);
> +
> +	for (i = 0; i < n; i++) {
> +		tbl24_indexes[i] = ips[i] >> 8;
> +	}
> +
> +	for (i = 0; i < n; i++) {
> +		/* Simply copy tbl24 entry to output */
> +		ptbl = (const uint32_t *)&lpm->tbl24[tbl24_indexes[i]];
> +		next_hops[i] = *ptbl;
> +
> +		/* Overwrite output with tbl8 entry if needed */
> +		if (unlikely((next_hops[i] & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +				RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +
> +			unsigned tbl8_index = (uint8_t)ips[i] +
> +					(((uint32_t)next_hops[i] & 0x00FFFFFF) *
> +					 RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
> +
> +			ptbl = (const uint32_t *)&lpm->tbl8[tbl8_index];
> +			next_hops[i] = *ptbl;
> +		}
> +	}
> +	return 0;
> +}
> +
> +/* Mask four results. */
> +#define	 RTE_LPM_MASKX4_RES	UINT64_C(0x00ffffff00ffffff)
> +
> +/**
> + * Lookup four IP addresses in an LPM table.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @param ip
> + *   Four IPs to be looked up in the LPM table
> + * @param hop
> + *   Next hop of the most specific rule found for IP (valid on lookup hit only).
> + *   This is an 4 elements array of two byte values.
> + *   If the lookup was succesfull for the given IP, then least significant byte
> + *   of the corresponding element is the  actual next hop and the most
> + *   significant byte is zero.
> + *   If the lookup for the given IP failed, then corresponding element would
> + *   contain default value, see description of then next parameter.
> + * @param defv
> + *   Default value to populate into corresponding element of hop[] array,
> + *   if lookup would fail.
> + */
> +static inline void
> +rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4],
> +	uint32_t defv);
> +
> +#if defined(RTE_ARCH_ARM) || defined(RTE_ARCH_ARM64)
> +#include "rte_lpm_neon.h"
> +#else
> +#include "rte_lpm_sse.h"
> +#endif
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_LPM_H_ */
> diff --git a/app/test/v16.04/rte_lpm_neon.h b/app/test/v16.04/rte_lpm_neon.h
> new file mode 100644
> index 000000000..936ec7af3
> --- /dev/null
> +++ b/app/test/v16.04/rte_lpm_neon.h
> @@ -0,0 +1,119 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2010-2014 Intel Corporation
> + */
> +
> +#ifndef _RTE_LPM_NEON_H_
> +#define _RTE_LPM_NEON_H_
> +
> +#include <rte_branch_prediction.h>
> +#include <rte_byteorder.h>
> +#include <rte_common.h>
> +#include <rte_vect.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +static inline void
> +rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4],
> +	uint32_t defv)
> +{
> +	uint32x4_t i24;
> +	rte_xmm_t i8;
> +	uint32_t tbl[4];
> +	uint64_t idx, pt, pt2;
> +	const uint32_t *ptbl;
> +
> +	const uint32_t mask = UINT8_MAX;
> +	const int32x4_t mask8 = vdupq_n_s32(mask);
> +
> +	/*
> +	 * RTE_LPM_VALID_EXT_ENTRY_BITMASK for 2 LPM entries
> +	 * as one 64-bit value (0x0300000003000000).
> +	 */
> +	const uint64_t mask_xv =
> +		((uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK |
> +		(uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 32);
> +
> +	/*
> +	 * RTE_LPM_LOOKUP_SUCCESS for 2 LPM entries
> +	 * as one 64-bit value (0x0100000001000000).
> +	 */
> +	const uint64_t mask_v =
> +		((uint64_t)RTE_LPM_LOOKUP_SUCCESS |
> +		(uint64_t)RTE_LPM_LOOKUP_SUCCESS << 32);
> +
> +	/* get 4 indexes for tbl24[]. */
> +	i24 = vshrq_n_u32((uint32x4_t)ip, CHAR_BIT);
> +
> +	/* extract values from tbl24[] */
> +	idx = vgetq_lane_u64((uint64x2_t)i24, 0);
> +
> +	ptbl = (const uint32_t *)&lpm->tbl24[(uint32_t)idx];
> +	tbl[0] = *ptbl;
> +	ptbl = (const uint32_t *)&lpm->tbl24[idx >> 32];
> +	tbl[1] = *ptbl;
> +
> +	idx = vgetq_lane_u64((uint64x2_t)i24, 1);
> +
> +	ptbl = (const uint32_t *)&lpm->tbl24[(uint32_t)idx];
> +	tbl[2] = *ptbl;
> +	ptbl = (const uint32_t *)&lpm->tbl24[idx >> 32];
> +	tbl[3] = *ptbl;
> +
> +	/* get 4 indexes for tbl8[]. */
> +	i8.x = vandq_s32(ip, mask8);
> +
> +	pt = (uint64_t)tbl[0] |
> +		(uint64_t)tbl[1] << 32;
> +	pt2 = (uint64_t)tbl[2] |
> +		(uint64_t)tbl[3] << 32;
> +
> +	/* search successfully finished for all 4 IP addresses. */
> +	if (likely((pt & mask_xv) == mask_v) &&
> +			likely((pt2 & mask_xv) == mask_v)) {
> +		*(uint64_t *)hop = pt & RTE_LPM_MASKX4_RES;
> +		*(uint64_t *)(hop + 2) = pt2 & RTE_LPM_MASKX4_RES;
> +		return;
> +	}
> +
> +	if (unlikely((pt & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +		i8.u32[0] = i8.u32[0] +
> +			(uint8_t)tbl[0] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
> +		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[0]];
> +		tbl[0] = *ptbl;
> +	}
> +	if (unlikely((pt >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +		i8.u32[1] = i8.u32[1] +
> +			(uint8_t)tbl[1] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
> +		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[1]];
> +		tbl[1] = *ptbl;
> +	}
> +	if (unlikely((pt2 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +		i8.u32[2] = i8.u32[2] +
> +			(uint8_t)tbl[2] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
> +		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[2]];
> +		tbl[2] = *ptbl;
> +	}
> +	if (unlikely((pt2 >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +		i8.u32[3] = i8.u32[3] +
> +			(uint8_t)tbl[3] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
> +		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[3]];
> +		tbl[3] = *ptbl;
> +	}
> +
> +	hop[0] = (tbl[0] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[0] & 0x00FFFFFF : defv;
> +	hop[1] = (tbl[1] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[1] & 0x00FFFFFF : defv;
> +	hop[2] = (tbl[2] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[2] & 0x00FFFFFF : defv;
> +	hop[3] = (tbl[3] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[3] & 0x00FFFFFF : defv;
> +}
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_LPM_NEON_H_ */
> diff --git a/app/test/v16.04/rte_lpm_sse.h b/app/test/v16.04/rte_lpm_sse.h
> new file mode 100644
> index 000000000..edfa36be1
> --- /dev/null
> +++ b/app/test/v16.04/rte_lpm_sse.h
> @@ -0,0 +1,120 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2010-2014 Intel Corporation
> + */
> +
> +#ifndef _RTE_LPM_SSE_H_
> +#define _RTE_LPM_SSE_H_
> +
> +#include <rte_branch_prediction.h>
> +#include <rte_byteorder.h>
> +#include <rte_common.h>
> +#include <rte_vect.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +static inline void
> +rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4],
> +	uint32_t defv)
> +{
> +	__m128i i24;
> +	rte_xmm_t i8;
> +	uint32_t tbl[4];
> +	uint64_t idx, pt, pt2;
> +	const uint32_t *ptbl;
> +
> +	const __m128i mask8 =
> +		_mm_set_epi32(UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX);
> +
> +	/*
> +	 * RTE_LPM_VALID_EXT_ENTRY_BITMASK for 2 LPM entries
> +	 * as one 64-bit value (0x0300000003000000).
> +	 */
> +	const uint64_t mask_xv =
> +		((uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK |
> +		(uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 32);
> +
> +	/*
> +	 * RTE_LPM_LOOKUP_SUCCESS for 2 LPM entries
> +	 * as one 64-bit value (0x0100000001000000).
> +	 */
> +	const uint64_t mask_v =
> +		((uint64_t)RTE_LPM_LOOKUP_SUCCESS |
> +		(uint64_t)RTE_LPM_LOOKUP_SUCCESS << 32);
> +
> +	/* get 4 indexes for tbl24[]. */
> +	i24 = _mm_srli_epi32(ip, CHAR_BIT);
> +
> +	/* extract values from tbl24[] */
> +	idx = _mm_cvtsi128_si64(i24);
> +	i24 = _mm_srli_si128(i24, sizeof(uint64_t));
> +
> +	ptbl = (const uint32_t *)&lpm->tbl24[(uint32_t)idx];
> +	tbl[0] = *ptbl;
> +	ptbl = (const uint32_t *)&lpm->tbl24[idx >> 32];
> +	tbl[1] = *ptbl;
> +
> +	idx = _mm_cvtsi128_si64(i24);
> +
> +	ptbl = (const uint32_t *)&lpm->tbl24[(uint32_t)idx];
> +	tbl[2] = *ptbl;
> +	ptbl = (const uint32_t *)&lpm->tbl24[idx >> 32];
> +	tbl[3] = *ptbl;
> +
> +	/* get 4 indexes for tbl8[]. */
> +	i8.x = _mm_and_si128(ip, mask8);
> +
> +	pt = (uint64_t)tbl[0] |
> +		(uint64_t)tbl[1] << 32;
> +	pt2 = (uint64_t)tbl[2] |
> +		(uint64_t)tbl[3] << 32;
> +
> +	/* search successfully finished for all 4 IP addresses. */
> +	if (likely((pt & mask_xv) == mask_v) &&
> +			likely((pt2 & mask_xv) == mask_v)) {
> +		*(uint64_t *)hop = pt & RTE_LPM_MASKX4_RES;
> +		*(uint64_t *)(hop + 2) = pt2 & RTE_LPM_MASKX4_RES;
> +		return;
> +	}
> +
> +	if (unlikely((pt & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +		i8.u32[0] = i8.u32[0] +
> +			(uint8_t)tbl[0] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
> +		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[0]];
> +		tbl[0] = *ptbl;
> +	}
> +	if (unlikely((pt >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +		i8.u32[1] = i8.u32[1] +
> +			(uint8_t)tbl[1] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
> +		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[1]];
> +		tbl[1] = *ptbl;
> +	}
> +	if (unlikely((pt2 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +		i8.u32[2] = i8.u32[2] +
> +			(uint8_t)tbl[2] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
> +		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[2]];
> +		tbl[2] = *ptbl;
> +	}
> +	if (unlikely((pt2 >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +		i8.u32[3] = i8.u32[3] +
> +			(uint8_t)tbl[3] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
> +		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[3]];
> +		tbl[3] = *ptbl;
> +	}
> +
> +	hop[0] = (tbl[0] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[0] & 0x00FFFFFF : defv;
> +	hop[1] = (tbl[1] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[1] & 0x00FFFFFF : defv;
> +	hop[2] = (tbl[2] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[2] & 0x00FFFFFF : defv;
> +	hop[3] = (tbl[3] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[3] & 0x00FFFFFF : defv;
> +}
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_LPM_SSE_H_ */
> diff --git a/app/test/v16.04/test_lpm.c b/app/test/v16.04/test_lpm.c
> new file mode 100644
> index 000000000..2aab8d0cc
> --- /dev/null
> +++ b/app/test/v16.04/test_lpm.c
> @@ -0,0 +1,1405 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2010-2019 Intel Corporation
> + *
> + * LPM Autotests from DPDK v16.04 for abi compability testing.
> + *
> + */
> +
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <stdlib.h>
> +#include <errno.h>
> +#include <sys/queue.h>
> +
> +#include <rte_common.h>
> +#include <rte_cycles.h>
> +#include <rte_memory.h>
> +#include <rte_random.h>
> +#include <rte_branch_prediction.h>
> +#include <rte_ip.h>
> +#include <time.h>
> +
> +#include "../test_lpm_routes.h"
> +#include "../test.h"
> +#include "../test_xmmt_ops.h"
> +
> +/* backported header from DPDK v16.04 */
> +#include "rte_lpm.h"
> +/* remapping of DPDK v16.04 symbols */
> +#include "dcompat.h"
> +
> +#define TEST_LPM_ASSERT(cond) do {                                            \
> +	if (!(cond)) {                                                        \
> +		printf("Error at line %d: \n", __LINE__);                     \
> +		return -1;                                                    \
> +	}                                                                     \
> +} while (0)
> +
> +typedef int32_t (*rte_lpm_test)(void);
> +
> +static int32_t test0(void);
> +static int32_t test1(void);
> +static int32_t test2(void);
> +static int32_t test3(void);
> +static int32_t test4(void);
> +static int32_t test5(void);
> +static int32_t test6(void);
> +static int32_t test7(void);
> +static int32_t test8(void);
> +static int32_t test9(void);
> +static int32_t test10(void);
> +static int32_t test11(void);
> +static int32_t test12(void);
> +static int32_t test13(void);
> +static int32_t test14(void);
> +static int32_t test15(void);
> +static int32_t test16(void);
> +static int32_t test17(void);
> +static int32_t perf_test(void);
> +
> +static rte_lpm_test tests[] = {
> +/* Test Cases */
> +	test0,
> +	test1,
> +	test2,
> +	test3,
> +	test4,
> +	test5,
> +	test6,
> +	test7,
> +	test8,
> +	test9,
> +	test10,
> +	test11,
> +	test12,
> +	test13,
> +	test14,
> +	test15,
> +	test16,
> +	test17,
> +	perf_test,
> +};
> +
> +#define NUM_LPM_TESTS (sizeof(tests)/sizeof(tests[0]))
> +#define MAX_DEPTH 32
> +#define MAX_RULES 256
> +#define NUMBER_TBL8S 256
> +#define PASS 0
> +
> +/*
> + * Check that rte_lpm_create fails gracefully for incorrect user input
> + * arguments
> + */
> +int32_t
> +test0(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +
> +	/* rte_lpm_create: lpm name == NULL */
> +	lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm == NULL);
> +
> +	/* rte_lpm_create: max_rules = 0 */
> +	/* Note: __func__ inserts the function name, in this case "test0". */
> +	config.max_rules = 0;
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm == NULL);
> +
> +	/* socket_id < -1 is invalid */
> +	config.max_rules = MAX_RULES;
> +	lpm = rte_lpm_create(__func__, -2, &config);
> +	TEST_LPM_ASSERT(lpm == NULL);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Create lpm table then delete lpm table 100 times
> + * Use a slightly different rules size each time
> + * */
> +int32_t
> +test1(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	int32_t i;
> +
> +	/* rte_lpm_free: Free NULL */
> +	for (i = 0; i < 100; i++) {
> +		config.max_rules = MAX_RULES - i;
> +		lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +		TEST_LPM_ASSERT(lpm != NULL);
> +
> +		rte_lpm_free(lpm);
> +	}
> +
> +	/* Can not test free so return success */
> +	return PASS;
> +}
> +
> +/*
> + * Call rte_lpm_free for NULL pointer user input. Note: free has no return and
> + * therefore it is impossible to check for failure but this test is added to
> + * increase function coverage metrics and to validate that freeing null does
> + * not crash.
> + */
> +int32_t
> +test2(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	rte_lpm_free(lpm);
> +	rte_lpm_free(NULL);
> +	return PASS;
> +}
> +
> +/*
> + * Check that rte_lpm_add fails gracefully for incorrect user input arguments
> + */
> +int32_t
> +test3(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	uint32_t ip = IPv4(0, 0, 0, 0), next_hop = 100;
> +	uint8_t depth = 24;
> +	int32_t status = 0;
> +
> +	/* rte_lpm_add: lpm == NULL */
> +	status = rte_lpm_add(NULL, ip, depth, next_hop);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	/*Create vaild lpm to use in rest of test. */
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	/* rte_lpm_add: depth < 1 */
> +	status = rte_lpm_add(lpm, ip, 0, next_hop);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	/* rte_lpm_add: depth > MAX_DEPTH */
> +	status = rte_lpm_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Check that rte_lpm_delete fails gracefully for incorrect user input
> + * arguments
> + */
> +int32_t
> +test4(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	uint32_t ip = IPv4(0, 0, 0, 0);
> +	uint8_t depth = 24;
> +	int32_t status = 0;
> +
> +	/* rte_lpm_delete: lpm == NULL */
> +	status = rte_lpm_delete(NULL, ip, depth);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	/*Create vaild lpm to use in rest of test. */
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	/* rte_lpm_delete: depth < 1 */
> +	status = rte_lpm_delete(lpm, ip, 0);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	/* rte_lpm_delete: depth > MAX_DEPTH */
> +	status = rte_lpm_delete(lpm, ip, (MAX_DEPTH + 1));
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Check that rte_lpm_lookup fails gracefully for incorrect user input
> + * arguments
> + */
> +int32_t
> +test5(void)
> +{
> +#if defined(RTE_LIBRTE_LPM_DEBUG)
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	uint32_t ip = IPv4(0, 0, 0, 0), next_hop_return = 0;
> +	int32_t status = 0;
> +
> +	/* rte_lpm_lookup: lpm == NULL */
> +	status = rte_lpm_lookup(NULL, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	/*Create vaild lpm to use in rest of test. */
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	/* rte_lpm_lookup: depth < 1 */
> +	status = rte_lpm_lookup(lpm, ip, NULL);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	rte_lpm_free(lpm);
> +#endif
> +	return PASS;
> +}
> +
> +
> +
> +/*
> + * Call add, lookup and delete for a single rule with depth <= 24
> + */
> +int32_t
> +test6(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	uint32_t ip = IPv4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
> +	uint8_t depth = 24;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Call add, lookup and delete for a single rule with depth > 24
> + */
> +
> +int32_t
> +test7(void)
> +{
> +	xmm_t ipx4;
> +	uint32_t hop[4];
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	uint32_t ip = IPv4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
> +	uint8_t depth = 32;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	ipx4 = vect_set_epi32(ip, ip + 0x100, ip - 0x100, ip);
> +	rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
> +	TEST_LPM_ASSERT(hop[0] == next_hop_add);
> +	TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
> +	TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
> +	TEST_LPM_ASSERT(hop[3] == next_hop_add);
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Use rte_lpm_add to add rules which effect only the second half of the lpm
> + * table. Use all possible depths ranging from 1..32. Set the next hop = to the
> + * depth. Check lookup hit for on every add and check for lookup miss on the
> + * first half of the lpm table after each add. Finally delete all rules going
> + * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
> + * delete. The lookup should return the next_hop_add value related to the
> + * previous depth value (i.e. depth -1).
> + */
> +int32_t
> +test8(void)
> +{
> +	xmm_t ipx4;
> +	uint32_t hop[4];
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	uint32_t ip1 = IPv4(127, 255, 255, 255), ip2 = IPv4(128, 0, 0, 0);
> +	uint32_t next_hop_add, next_hop_return;
> +	uint8_t depth;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	/* Loop with rte_lpm_add. */
> +	for (depth = 1; depth <= 32; depth++) {
> +		/* Let the next_hop_add value = depth. Just for change. */
> +		next_hop_add = depth;
> +
> +		status = rte_lpm_add(lpm, ip2, depth, next_hop_add);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		/* Check IP in first half of tbl24 which should be empty. */
> +		status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
> +		TEST_LPM_ASSERT(status == -ENOENT);
> +
> +		status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
> +		TEST_LPM_ASSERT((status == 0) &&
> +			(next_hop_return == next_hop_add));
> +
> +		ipx4 = vect_set_epi32(ip2, ip1, ip2, ip1);
> +		rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
> +		TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
> +		TEST_LPM_ASSERT(hop[1] == next_hop_add);
> +		TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
> +		TEST_LPM_ASSERT(hop[3] == next_hop_add);
> +	}
> +
> +	/* Loop with rte_lpm_delete. */
> +	for (depth = 32; depth >= 1; depth--) {
> +		next_hop_add = (uint8_t) (depth - 1);
> +
> +		status = rte_lpm_delete(lpm, ip2, depth);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
> +
> +		if (depth != 1) {
> +			TEST_LPM_ASSERT((status == 0) &&
> +				(next_hop_return == next_hop_add));
> +		} else {
> +			TEST_LPM_ASSERT(status == -ENOENT);
> +		}
> +
> +		status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
> +		TEST_LPM_ASSERT(status == -ENOENT);
> +
> +		ipx4 = vect_set_epi32(ip1, ip1, ip2, ip2);
> +		rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
> +		if (depth != 1) {
> +			TEST_LPM_ASSERT(hop[0] == next_hop_add);
> +			TEST_LPM_ASSERT(hop[1] == next_hop_add);
> +		} else {
> +			TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
> +			TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
> +		}
> +		TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
> +		TEST_LPM_ASSERT(hop[3] == UINT32_MAX);
> +	}
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * - Add & lookup to hit invalid TBL24 entry
> + * - Add & lookup to hit valid TBL24 entry not extended
> + * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
> + * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
> + *
> + */
> +int32_t
> +test9(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	uint32_t ip, ip_1, ip_2;
> +	uint8_t depth, depth_1, depth_2;
> +	uint32_t next_hop_add, next_hop_add_1, next_hop_add_2, next_hop_return;
> +	int32_t status = 0;
> +
> +	/* Add & lookup to hit invalid TBL24 entry */
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +	next_hop_add = 100;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Add & lookup to hit valid TBL24 entry not extended */
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 23;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	depth = 24;
> +	next_hop_add = 101;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	depth = 24;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	depth = 23;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
> +	 * entry */
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 32;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	ip = IPv4(128, 0, 0, 5);
> +	depth = 32;
> +	next_hop_add = 101;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 32;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Add & lookup to hit valid extended TBL24 entry with valid TBL8
> +	 * entry */
> +	ip_1 = IPv4(128, 0, 0, 0);
> +	depth_1 = 25;
> +	next_hop_add_1 = 101;
> +
> +	ip_2 = IPv4(128, 0, 0, 5);
> +	depth_2 = 32;
> +	next_hop_add_2 = 102;
> +
> +	next_hop_return = 0;
> +
> +	status = rte_lpm_add(lpm, ip_1, depth_1, next_hop_add_1);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
> +
> +	status = rte_lpm_add(lpm, ip_2, depth_2, next_hop_add_2);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
> +
> +	status = rte_lpm_delete(lpm, ip_2, depth_2);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
> +
> +	status = rte_lpm_delete(lpm, ip_1, depth_1);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +
> +/*
> + * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
> + *   lookup)
> + * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
> + * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
> + *   delete & lookup)
> + * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
> + * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
> + * - Delete a rule that is not present in the TBL24 & lookup
> + * - Delete a rule that is not present in the TBL8 & lookup
> + *
> + */
> +int32_t
> +test10(void)
> +{
> +
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	uint32_t ip, next_hop_add, next_hop_return;
> +	uint8_t depth;
> +	int32_t status = 0;
> +
> +	/* Add rule that covers a TBL24 range previously invalid & lookup
> +	 * (& delete & lookup) */
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 16;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 25;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Add rule that extends a TBL24 valid entry & lookup for both rules
> +	 * (& delete & lookup) */
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	ip = IPv4(128, 0, 0, 10);
> +	depth = 32;
> +	next_hop_add = 101;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	ip = IPv4(128, 0, 0, 10);
> +	depth = 32;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Add rule that updates the next hop in TBL24 & lookup
> +	 * (& delete & lookup) */
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	next_hop_add = 101;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Add rule that updates the next hop in TBL8 & lookup
> +	 * (& delete & lookup) */
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 32;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	next_hop_add = 101;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Delete a rule that is not present in the TBL24 & lookup */
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Delete a rule that is not present in the TBL8 & lookup */
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 32;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Add two rules, lookup to hit the more specific one, lookup to hit the less
> + * specific one delete the less specific rule and lookup previous values again;
> + * add a more specific rule than the existing rule, lookup again
> + *
> + * */
> +int32_t
> +test11(void)
> +{
> +
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	uint32_t ip, next_hop_add, next_hop_return;
> +	uint8_t depth;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	ip = IPv4(128, 0, 0, 10);
> +	depth = 32;
> +	next_hop_add = 101;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	ip = IPv4(128, 0, 0, 10);
> +	depth = 32;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
> + * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension
> + * and contraction.
> + *
> + * */
> +
> +int32_t
> +test12(void)
> +{
> +	xmm_t ipx4;
> +	uint32_t hop[4];
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	uint32_t ip, i, next_hop_add, next_hop_return;
> +	uint8_t depth;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 32;
> +	next_hop_add = 100;
> +
> +	for (i = 0; i < 1000; i++) {
> +		status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +		TEST_LPM_ASSERT((status == 0) &&
> +				(next_hop_return == next_hop_add));
> +
> +		ipx4 = vect_set_epi32(ip, ip + 1, ip, ip - 1);
> +		rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
> +		TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
> +		TEST_LPM_ASSERT(hop[1] == next_hop_add);
> +		TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
> +		TEST_LPM_ASSERT(hop[3] == next_hop_add);
> +
> +		status = rte_lpm_delete(lpm, ip, depth);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +		TEST_LPM_ASSERT(status == -ENOENT);
> +	}
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Add a rule to tbl24, lookup (hit), then add a rule that will extend this
> + * tbl24 entry, lookup (hit). delete the rule that caused the tbl24 extension,
> + * lookup (miss) and repeat for loop of 1000 times. This will check tbl8
> + * extension and contraction.
> + *
> + * */
> +
> +int32_t
> +test13(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	uint32_t ip, i, next_hop_add_1, next_hop_add_2, next_hop_return;
> +	uint8_t depth;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +	next_hop_add_1 = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add_1);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
> +
> +	depth = 32;
> +	next_hop_add_2 = 101;
> +
> +	for (i = 0; i < 1000; i++) {
> +		status = rte_lpm_add(lpm, ip, depth, next_hop_add_2);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +		TEST_LPM_ASSERT((status == 0) &&
> +				(next_hop_return == next_hop_add_2));
> +
> +		status = rte_lpm_delete(lpm, ip, depth);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +		TEST_LPM_ASSERT((status == 0) &&
> +				(next_hop_return == next_hop_add_1));
> +	}
> +
> +	depth = 24;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Fore TBL8 extension exhaustion. Add 256 rules that require a tbl8 extension.
> + * No more tbl8 extensions will be allowed. Now add one more rule that required
> + * a tbl8 extension and get fail.
> + * */
> +int32_t
> +test14(void)
> +{
> +
> +	/* We only use depth = 32 in the loop below so we must make sure
> +	 * that we have enough storage for all rules at that depth*/
> +
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = 256 * 32;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	uint32_t ip, next_hop_add, next_hop_return;
> +	uint8_t depth;
> +	int32_t status = 0;
> +
> +	/* Add enough space for 256 rules for every depth */
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	depth = 32;
> +	next_hop_add = 100;
> +	ip = IPv4(0, 0, 0, 0);
> +
> +	/* Add 256 rules that require a tbl8 extension */
> +	for (; ip <= IPv4(0, 0, 255, 0); ip += 256) {
> +		status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +		TEST_LPM_ASSERT((status == 0) &&
> +				(next_hop_return == next_hop_add));
> +	}
> +
> +	/* All tbl8 extensions have been used above. Try to add one more and
> +	 * we get a fail */
> +	ip = IPv4(1, 0, 0, 0);
> +	depth = 32;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Sequence of operations for find existing lpm table
> + *
> + *  - create table
> + *  - find existing table: hit
> + *  - find non-existing table: miss
> + *
> + */
> +int32_t
> +test15(void)
> +{
> +	struct rte_lpm *lpm = NULL, *result = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = 256 * 32;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +
> +	/* Create lpm  */
> +	lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	/* Try to find existing lpm */
> +	result = rte_lpm_find_existing("lpm_find_existing");
> +	TEST_LPM_ASSERT(result == lpm);
> +
> +	/* Try to find non-existing lpm */
> +	result = rte_lpm_find_existing("lpm_find_non_existing");
> +	TEST_LPM_ASSERT(result == NULL);
> +
> +	/* Cleanup. */
> +	rte_lpm_delete_all(lpm);
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * test failure condition of overloading the tbl8 so no more will fit
> + * Check we get an error return value in that case
> + */
> +int32_t
> +test16(void)
> +{
> +	uint32_t ip;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = 256 * 32;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +
> +	/* ip loops through all possibilities for top 24 bits of address */
> +	for (ip = 0; ip < 0xFFFFFF; ip++) {
> +		/* add an entry within a different tbl8 each time, since
> +		 * depth >24 and the top 24 bits are different */
> +		if (rte_lpm_add(lpm, (ip << 8) + 0xF0, 30, 0) < 0)
> +			break;
> +	}
> +
> +	if (ip != NUMBER_TBL8S) {
> +		printf("Error, unexpected failure with filling tbl8 groups\n");
> +		printf("Failed after %u additions, expected after %u\n",
> +				(unsigned)ip, (unsigned)NUMBER_TBL8S);
> +	}
> +
> +	rte_lpm_free(lpm);
> +	return 0;
> +}
> +
> +/*
> + * Test for overwriting of tbl8:
> + *  - add rule /32 and lookup
> + *  - add new rule /24 and lookup
> + *	- add third rule /25 and lookup
> + *	- lookup /32 and /24 rule to ensure the table has not been overwritten.
> + */
> +int32_t
> +test17(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = MAX_RULES;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	const uint32_t ip_10_32 = IPv4(10, 10, 10, 2);
> +	const uint32_t ip_10_24 = IPv4(10, 10, 10, 0);
> +	const uint32_t ip_20_25 = IPv4(10, 10, 20, 2);
> +	const uint8_t d_ip_10_32 = 32,
> +			d_ip_10_24 = 24,
> +			d_ip_20_25 = 25;
> +	const uint32_t next_hop_ip_10_32 = 100,
> +			next_hop_ip_10_24 = 105,
> +			next_hop_ip_20_25 = 111;
> +	uint32_t next_hop_return = 0;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	status = rte_lpm_add(lpm, ip_10_32, d_ip_10_32, next_hop_ip_10_32);
> +	if (status < 0)
> +		return -1;
> +
> +	status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
> +	uint32_t test_hop_10_32 = next_hop_return;
> +	TEST_LPM_ASSERT(status == 0);
> +	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
> +
> +	status = rte_lpm_add(lpm, ip_10_24, d_ip_10_24, next_hop_ip_10_24);
> +	if (status < 0)
> +		return -1;
> +
> +	status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
> +	uint32_t test_hop_10_24 = next_hop_return;
> +	TEST_LPM_ASSERT(status == 0);
> +	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
> +
> +	status = rte_lpm_add(lpm, ip_20_25, d_ip_20_25, next_hop_ip_20_25);
> +	if (status < 0)
> +		return -1;
> +
> +	status = rte_lpm_lookup(lpm, ip_20_25, &next_hop_return);
> +	uint32_t test_hop_20_25 = next_hop_return;
> +	TEST_LPM_ASSERT(status == 0);
> +	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
> +
> +	if (test_hop_10_32 == test_hop_10_24) {
> +		printf("Next hop return equal\n");
> +		return -1;
> +	}
> +
> +	if (test_hop_10_24 == test_hop_20_25) {
> +		printf("Next hop return equal\n");
> +		return -1;
> +	}
> +
> +	status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
> +	TEST_LPM_ASSERT(status == 0);
> +	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
> +
> +	status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
> +	TEST_LPM_ASSERT(status == 0);
> +	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Lookup performance test
> + */
> +
> +#define ITERATIONS (1 << 10)
> +#define BATCH_SIZE (1 << 12)
> +#define BULK_SIZE 32
> +
> +int32_t
> +perf_test(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	struct rte_lpm_config config;
> +
> +	config.max_rules = 1000000;
> +	config.number_tbl8s = NUMBER_TBL8S;
> +	config.flags = 0;
> +	uint64_t begin, total_time, lpm_used_entries = 0;
> +	unsigned i, j;
> +	uint32_t next_hop_add = 0xAA, next_hop_return = 0;
> +	int status = 0;
> +	uint64_t cache_line_counter = 0;
> +	int64_t count = 0;
> +
> +	rte_srand(rte_rdtsc());
> +
> +	/* (re) generate the routing table */
> +	generate_large_route_rule_table();
> +
> +	printf("No. routes = %u\n", (unsigned) NUM_ROUTE_ENTRIES);
> +
> +	print_route_distribution(large_route_table,
> +				(uint32_t) NUM_ROUTE_ENTRIES);
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	/* Measue add. */
> +	begin = rte_rdtsc();
> +
> +	for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
> +		if (rte_lpm_add(lpm, large_route_table[i].ip,
> +				large_route_table[i].depth, next_hop_add) == 0)
> +			status++;
> +	}
> +	/* End Timer. */
> +	total_time = rte_rdtsc() - begin;
> +
> +	printf("Unique added entries = %d\n", status);
> +	/* Obtain add statistics. */
> +	for (i = 0; i < RTE_LPM_TBL24_NUM_ENTRIES; i++) {
> +		if (lpm->tbl24[i].valid)
> +			lpm_used_entries++;
> +
> +		if (i % 32 == 0) {
> +			if ((uint64_t)count < lpm_used_entries) {
> +				cache_line_counter++;
> +				count = lpm_used_entries;
> +			}
> +		}
> +	}
> +
> +	printf("Used table 24 entries = %u (%g%%)\n",
> +			(unsigned) lpm_used_entries,
> +			(lpm_used_entries * 100.0) / RTE_LPM_TBL24_NUM_ENTRIES);
> +	printf("64 byte Cache entries used = %u (%u bytes)\n",
> +			(unsigned) cache_line_counter, (unsigned) cache_line_counter * 64);
> +
> +	printf("Average LPM Add: %g cycles\n",
> +			(double)total_time / NUM_ROUTE_ENTRIES);
> +
> +	/* Measure single Lookup */
> +	total_time = 0;
> +	count = 0;
> +
> +	for (i = 0; i < ITERATIONS; i++) {
> +		static uint32_t ip_batch[BATCH_SIZE];
> +
> +		for (j = 0; j < BATCH_SIZE; j++)
> +			ip_batch[j] = rte_rand();
> +
> +		/* Lookup per batch */
> +		begin = rte_rdtsc();
> +
> +		for (j = 0; j < BATCH_SIZE; j++) {
> +			if (rte_lpm_lookup(lpm, ip_batch[j], &next_hop_return) != 0)
> +				count++;
> +		}
> +
> +		total_time += rte_rdtsc() - begin;
> +
> +	}
> +	printf("Average LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
> +			(double)total_time / ((double)ITERATIONS * BATCH_SIZE),
> +			(count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
> +
> +	/* Measure bulk Lookup */
> +	total_time = 0;
> +	count = 0;
> +	for (i = 0; i < ITERATIONS; i++) {
> +		static uint32_t ip_batch[BATCH_SIZE];
> +		uint32_t next_hops[BULK_SIZE];
> +
> +		/* Create array of random IP addresses */
> +		for (j = 0; j < BATCH_SIZE; j++)
> +			ip_batch[j] = rte_rand();
> +
> +		/* Lookup per batch */
> +		begin = rte_rdtsc();
> +		for (j = 0; j < BATCH_SIZE; j += BULK_SIZE) {
> +			unsigned k;
> +			rte_lpm_lookup_bulk(lpm, &ip_batch[j], next_hops, BULK_SIZE);
> +			for (k = 0; k < BULK_SIZE; k++)
> +				if (unlikely(!(next_hops[k] & RTE_LPM_LOOKUP_SUCCESS)))
> +					count++;
> +		}
> +
> +		total_time += rte_rdtsc() - begin;
> +	}
> +	printf("BULK LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
> +			(double)total_time / ((double)ITERATIONS * BATCH_SIZE),
> +			(count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
> +
> +	/* Measure LookupX4 */
> +	total_time = 0;
> +	count = 0;
> +	for (i = 0; i < ITERATIONS; i++) {
> +		static uint32_t ip_batch[BATCH_SIZE];
> +		uint32_t next_hops[4];
> +
> +		/* Create array of random IP addresses */
> +		for (j = 0; j < BATCH_SIZE; j++)
> +			ip_batch[j] = rte_rand();
> +
> +		/* Lookup per batch */
> +		begin = rte_rdtsc();
> +		for (j = 0; j < BATCH_SIZE; j += RTE_DIM(next_hops)) {
> +			unsigned k;
> +			xmm_t ipx4;
> +
> +			ipx4 = vect_loadu_sil128((xmm_t *)(ip_batch + j));
> +			ipx4 = *(xmm_t *)(ip_batch + j);
> +			rte_lpm_lookupx4(lpm, ipx4, next_hops, UINT32_MAX);
> +			for (k = 0; k < RTE_DIM(next_hops); k++)
> +				if (unlikely(next_hops[k] == UINT32_MAX))
> +					count++;
> +		}
> +
> +		total_time += rte_rdtsc() - begin;
> +	}
> +	printf("LPM LookupX4: %.1f cycles (fails = %.1f%%)\n",
> +			(double)total_time / ((double)ITERATIONS * BATCH_SIZE),
> +			(count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
> +
> +	/* Delete */
> +	status = 0;
> +	begin = rte_rdtsc();
> +
> +	for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
> +		/* rte_lpm_delete(lpm, ip, depth) */
> +		status += rte_lpm_delete(lpm, large_route_table[i].ip,
> +				large_route_table[i].depth);
> +	}
> +
> +	total_time += rte_rdtsc() - begin;
> +
> +	printf("Average LPM Delete: %g cycles\n",
> +			(double)total_time / NUM_ROUTE_ENTRIES);
> +
> +	rte_lpm_delete_all(lpm);
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Do all unit and performance tests.
> + */
> +
> +static int
> +test_lpm(void)
> +{
> +	unsigned i;
> +	int status, global_status = 0;
> +
> +	for (i = 0; i < NUM_LPM_TESTS; i++) {
> +		status = tests[i]();
> +		if (status < 0) {
> +			printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests[i]));
> +			global_status = status;
> +		}
> +	}
> +
> +	return global_status;
> +}
> +
> +REGISTER_TEST_COMMAND_VERSION(lpm_autotest, test_lpm, TEST_DPDK_ABI_VERSION_V1604);
> diff --git a/app/test/v16.04/test_v1604.c b/app/test/v16.04/test_v1604.c
> new file mode 100644
> index 000000000..a5399bbfe
> --- /dev/null
> +++ b/app/test/v16.04/test_v1604.c
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2010-2014 Intel Corporation
> + */
> +
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <stdlib.h>
> +
> +#include <rte_ip.h>
> +#include <rte_lpm.h>
> +
> +#include "../test.h"
> +
> +REGISTER_TEST_ABI_VERSION(v1604, TEST_DPDK_ABI_VERSION_V1604);
> diff --git a/app/test/v2.0/dcompat.h b/app/test/v2.0/dcompat.h
> new file mode 100644
> index 000000000..108fcf8f6
> --- /dev/null
> +++ b/app/test/v2.0/dcompat.h
> @@ -0,0 +1,23 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2010-2019 Intel Corporation
> + */
> +
> +#ifndef _DCOMPAT_H_
> +#define _DCOMPAT_H_
> +
> +#define ABI_VERSION DPDK_2.0
> +
> +#define MAP_ABI_SYMBOL(name) \
> +	MAP_ABI_SYMBOL_VERSION(name, ABI_VERSION)
> +
> +MAP_ABI_SYMBOL(rte_lpm_add);
> +MAP_ABI_SYMBOL(rte_lpm_create);
> +MAP_ABI_SYMBOL(rte_lpm_delete);
> +MAP_ABI_SYMBOL(rte_lpm_delete_all);
> +MAP_ABI_SYMBOL(rte_lpm_find_existing);
> +MAP_ABI_SYMBOL(rte_lpm_free);
> +MAP_ABI_SYMBOL(rte_lpm_is_rule_present);
> +
> +#undef MAP_ABI_SYMBOL
> +
> +#endif
> diff --git a/app/test/v2.0/rte_lpm.h b/app/test/v2.0/rte_lpm.h
> new file mode 100644
> index 000000000..b1efd1c2d
> --- /dev/null
> +++ b/app/test/v2.0/rte_lpm.h
> @@ -0,0 +1,443 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2010-2014 Intel Corporation
> + */
> +
> +#ifndef _RTE_LPM_H_
> +#define _RTE_LPM_H_
> +
> +/**
> + * @file
> + * RTE Longest Prefix Match (LPM)
> + */
> +
> +#include <errno.h>
> +#include <sys/queue.h>
> +#include <stdint.h>
> +#include <stdlib.h>
> +#include <rte_branch_prediction.h>
> +#include <rte_memory.h>
> +#include <rte_common.h>
> +#include <rte_vect.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/** Max number of characters in LPM name. */
> +#define RTE_LPM_NAMESIZE                32
> +
> +/** @deprecated Possible location to allocate memory. This was for last
> + * parameter of rte_lpm_create(), but is now redundant. The LPM table is always
> + * allocated in memory using librte_malloc which uses a memzone. */
> +#define RTE_LPM_HEAP                    0
> +
> +/** @deprecated Possible location to allocate memory. This was for last
> + * parameter of rte_lpm_create(), but is now redundant. The LPM table is always
> + * allocated in memory using librte_malloc which uses a memzone. */
> +#define RTE_LPM_MEMZONE                 1
> +
> +/** Maximum depth value possible for IPv4 LPM. */
> +#define RTE_LPM_MAX_DEPTH               32
> +
> +/** @internal Total number of tbl24 entries. */
> +#define RTE_LPM_TBL24_NUM_ENTRIES       (1 << 24)
> +
> +/** @internal Number of entries in a tbl8 group. */
> +#define RTE_LPM_TBL8_GROUP_NUM_ENTRIES  256
> +
> +/** @internal Total number of tbl8 groups in the tbl8. */
> +#define RTE_LPM_TBL8_NUM_GROUPS         256
> +
> +/** @internal Total number of tbl8 entries. */
> +#define RTE_LPM_TBL8_NUM_ENTRIES        (RTE_LPM_TBL8_NUM_GROUPS * \
> +					RTE_LPM_TBL8_GROUP_NUM_ENTRIES)
> +
> +/** @internal Macro to enable/disable run-time checks. */
> +#if defined(RTE_LIBRTE_LPM_DEBUG)
> +#define RTE_LPM_RETURN_IF_TRUE(cond, retval) do { \
> +	if (cond) \
> +		return (retval); \
> +} while (0)
> +#else
> +#define RTE_LPM_RETURN_IF_TRUE(cond, retval)
> +#endif
> +
> +/** @internal bitmask with valid and ext_entry/valid_group fields set */
> +#define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x0300
> +
> +/** Bitmask used to indicate successful lookup */
> +#define RTE_LPM_LOOKUP_SUCCESS          0x0100
> +
> +/** @internal Tbl24 entry structure. */
> +struct rte_lpm_tbl24_entry {
> +	/* Stores Next hop or group index (i.e. gindex)into tbl8. */
> +	union {
> +		uint8_t next_hop;
> +		uint8_t tbl8_gindex;
> +	};
> +	/* Using single uint8_t to store 3 values. */
> +	uint8_t valid     :1; /**< Validation flag. */
> +	uint8_t ext_entry :1; /**< External entry. */
> +	uint8_t depth     :6; /**< Rule depth. */
> +};
> +
> +/** @internal Tbl8 entry structure. */
> +struct rte_lpm_tbl8_entry {
> +	uint8_t next_hop; /**< next hop. */
> +	/* Using single uint8_t to store 3 values. */
> +	uint8_t valid       :1; /**< Validation flag. */
> +	uint8_t valid_group :1; /**< Group validation flag. */
> +	uint8_t depth       :6; /**< Rule depth. */
> +};
> +
> +/** @internal Rule structure. */
> +struct rte_lpm_rule {
> +	uint32_t ip; /**< Rule IP address. */
> +	uint8_t  next_hop; /**< Rule next hop. */
> +};
> +
> +/** @internal Contains metadata about the rules table. */
> +struct rte_lpm_rule_info {
> +	uint32_t used_rules; /**< Used rules so far. */
> +	uint32_t first_rule; /**< Indexes the first rule of a given depth. */
> +};
> +
> +/** @internal LPM structure. */
> +struct rte_lpm {
> +	/* LPM metadata. */
> +	char name[RTE_LPM_NAMESIZE];        /**< Name of the lpm. */
> +	int mem_location; /**< @deprecated @see RTE_LPM_HEAP and RTE_LPM_MEMZONE. */
> +	uint32_t max_rules; /**< Max. balanced rules per lpm. */
> +	struct rte_lpm_rule_info rule_info[RTE_LPM_MAX_DEPTH]; /**< Rule info table. */
> +
> +	/* LPM Tables. */
> +	struct rte_lpm_tbl24_entry tbl24[RTE_LPM_TBL24_NUM_ENTRIES] \
> +			__rte_cache_aligned; /**< LPM tbl24 table. */
> +	struct rte_lpm_tbl8_entry tbl8[RTE_LPM_TBL8_NUM_ENTRIES] \
> +			__rte_cache_aligned; /**< LPM tbl8 table. */
> +	struct rte_lpm_rule rules_tbl[0] \
> +			__rte_cache_aligned; /**< LPM rules. */
> +};
> +
> +/**
> + * Create an LPM object.
> + *
> + * @param name
> + *   LPM object name
> + * @param socket_id
> + *   NUMA socket ID for LPM table memory allocation
> + * @param max_rules
> + *   Maximum number of LPM rules that can be added
> + * @param flags
> + *   This parameter is currently unused
> + * @return
> + *   Handle to LPM object on success, NULL otherwise with rte_errno set
> + *   to an appropriate values. Possible rte_errno values include:
> + *    - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
> + *    - E_RTE_SECONDARY - function was called from a secondary process instance
> + *    - EINVAL - invalid parameter passed to function
> + *    - ENOSPC - the maximum number of memzones has already been allocated
> + *    - EEXIST - a memzone with the same name already exists
> + *    - ENOMEM - no appropriate memory area found in which to create memzone
> + */
> +struct rte_lpm *
> +rte_lpm_create(const char *name, int socket_id, int max_rules, int flags);
> +
> +/**
> + * Find an existing LPM object and return a pointer to it.
> + *
> + * @param name
> + *   Name of the lpm object as passed to rte_lpm_create()
> + * @return
> + *   Pointer to lpm object or NULL if object not found with rte_errno
> + *   set appropriately. Possible rte_errno values include:
> + *    - ENOENT - required entry not available to return.
> + */
> +struct rte_lpm *
> +rte_lpm_find_existing(const char *name);
> +
> +/**
> + * Free an LPM object.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @return
> + *   None
> + */
> +void
> +rte_lpm_free(struct rte_lpm *lpm);
> +
> +/**
> + * Add a rule to the LPM table.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @param ip
> + *   IP of the rule to be added to the LPM table
> + * @param depth
> + *   Depth of the rule to be added to the LPM table
> + * @param next_hop
> + *   Next hop of the rule to be added to the LPM table
> + * @return
> + *   0 on success, negative value otherwise
> + */
> +int
> +rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint8_t next_hop);
> +
> +/**
> + * Check if a rule is present in the LPM table,
> + * and provide its next hop if it is.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @param ip
> + *   IP of the rule to be searched
> + * @param depth
> + *   Depth of the rule to searched
> + * @param next_hop
> + *   Next hop of the rule (valid only if it is found)
> + * @return
> + *   1 if the rule exists, 0 if it does not, a negative value on failure
> + */
> +int
> +rte_lpm_is_rule_present(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,
> +uint8_t *next_hop);
> +
> +/**
> + * Delete a rule from the LPM table.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @param ip
> + *   IP of the rule to be deleted from the LPM table
> + * @param depth
> + *   Depth of the rule to be deleted from the LPM table
> + * @return
> + *   0 on success, negative value otherwise
> + */
> +int
> +rte_lpm_delete(struct rte_lpm *lpm, uint32_t ip, uint8_t depth);
> +
> +/**
> + * Delete all rules from the LPM table.
> + *
> + * @param lpm
> + *   LPM object handle
> + */
> +void
> +rte_lpm_delete_all(struct rte_lpm *lpm);
> +
> +/**
> + * Lookup an IP into the LPM table.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @param ip
> + *   IP to be looked up in the LPM table
> + * @param next_hop
> + *   Next hop of the most specific rule found for IP (valid on lookup hit only)
> + * @return
> + *   -EINVAL for incorrect arguments, -ENOENT on lookup miss, 0 on lookup hit
> + */
> +static inline int
> +rte_lpm_lookup(struct rte_lpm *lpm, uint32_t ip, uint8_t *next_hop)
> +{
> +	unsigned tbl24_index = (ip >> 8);
> +	uint16_t tbl_entry;
> +
> +	/* DEBUG: Check user input arguments. */
> +	RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (next_hop == NULL)), -EINVAL);
> +
> +	/* Copy tbl24 entry */
> +	tbl_entry = *(const uint16_t *)&lpm->tbl24[tbl24_index];
> +
> +	/* Copy tbl8 entry (only if needed) */
> +	if (unlikely((tbl_entry & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +
> +		unsigned tbl8_index = (uint8_t)ip +
> +				((uint8_t)tbl_entry * RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
> +
> +		tbl_entry = *(const uint16_t *)&lpm->tbl8[tbl8_index];
> +	}
> +
> +	*next_hop = (uint8_t)tbl_entry;
> +	return (tbl_entry & RTE_LPM_LOOKUP_SUCCESS) ? 0 : -ENOENT;
> +}
> +
> +/**
> + * Lookup multiple IP addresses in an LPM table. This may be implemented as a
> + * macro, so the address of the function should not be used.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @param ips
> + *   Array of IPs to be looked up in the LPM table
> + * @param next_hops
> + *   Next hop of the most specific rule found for IP (valid on lookup hit only).
> + *   This is an array of two byte values. The most significant byte in each
> + *   value says whether the lookup was successful (bitmask
> + *   RTE_LPM_LOOKUP_SUCCESS is set). The least significant byte is the
> + *   actual next hop.
> + * @param n
> + *   Number of elements in ips (and next_hops) array to lookup. This should be a
> + *   compile time constant, and divisible by 8 for best performance.
> + *  @return
> + *   -EINVAL for incorrect arguments, otherwise 0
> + */
> +#define rte_lpm_lookup_bulk(lpm, ips, next_hops, n) \
> +		rte_lpm_lookup_bulk_func(lpm, ips, next_hops, n)
> +
> +static inline int
> +rte_lpm_lookup_bulk_func(const struct rte_lpm *lpm, const uint32_t *ips,
> +		uint16_t *next_hops, const unsigned n)
> +{
> +	unsigned i;
> +	unsigned tbl24_indexes[n];
> +
> +	/* DEBUG: Check user input arguments. */
> +	RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (ips == NULL) ||
> +			(next_hops == NULL)), -EINVAL);
> +
> +	for (i = 0; i < n; i++) {
> +		tbl24_indexes[i] = ips[i] >> 8;
> +	}
> +
> +	for (i = 0; i < n; i++) {
> +		/* Simply copy tbl24 entry to output */
> +		next_hops[i] = *(const uint16_t *)&lpm->tbl24[tbl24_indexes[i]];
> +
> +		/* Overwrite output with tbl8 entry if needed */
> +		if (unlikely((next_hops[i] & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +				RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +
> +			unsigned tbl8_index = (uint8_t)ips[i] +
> +					((uint8_t)next_hops[i] *
> +					 RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
> +
> +			next_hops[i] = *(const uint16_t *)&lpm->tbl8[tbl8_index];
> +		}
> +	}
> +	return 0;
> +}
> +
> +/* Mask four results. */
> +#define	 RTE_LPM_MASKX4_RES	UINT64_C(0x00ff00ff00ff00ff)
> +
> +/**
> + * Lookup four IP addresses in an LPM table.
> + *
> + * @param lpm
> + *   LPM object handle
> + * @param ip
> + *   Four IPs to be looked up in the LPM table
> + * @param hop
> + *   Next hop of the most specific rule found for IP (valid on lookup hit only).
> + *   This is an 4 elements array of two byte values.
> + *   If the lookup was succesfull for the given IP, then least significant byte
> + *   of the corresponding element is the  actual next hop and the most
> + *   significant byte is zero.
> + *   If the lookup for the given IP failed, then corresponding element would
> + *   contain default value, see description of then next parameter.
> + * @param defv
> + *   Default value to populate into corresponding element of hop[] array,
> + *   if lookup would fail.
> + */
> +static inline void
> +rte_lpm_lookupx4(const struct rte_lpm *lpm, __m128i ip, uint16_t hop[4],
> +	uint16_t defv)
> +{
> +	__m128i i24;
> +	rte_xmm_t i8;
> +	uint16_t tbl[4];
> +	uint64_t idx, pt;
> +
> +	const __m128i mask8 =
> +		_mm_set_epi32(UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX);
> +
> +	/*
> +	 * RTE_LPM_VALID_EXT_ENTRY_BITMASK for 4 LPM entries
> +	 * as one 64-bit value (0x0300030003000300).
> +	 */
> +	const uint64_t mask_xv =
> +		((uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK |
> +		(uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 16 |
> +		(uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 32 |
> +		(uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 48);
> +
> +	/*
> +	 * RTE_LPM_LOOKUP_SUCCESS for 4 LPM entries
> +	 * as one 64-bit value (0x0100010001000100).
> +	 */
> +	const uint64_t mask_v =
> +		((uint64_t)RTE_LPM_LOOKUP_SUCCESS |
> +		(uint64_t)RTE_LPM_LOOKUP_SUCCESS << 16 |
> +		(uint64_t)RTE_LPM_LOOKUP_SUCCESS << 32 |
> +		(uint64_t)RTE_LPM_LOOKUP_SUCCESS << 48);
> +
> +	/* get 4 indexes for tbl24[]. */
> +	i24 = _mm_srli_epi32(ip, CHAR_BIT);
> +
> +	/* extract values from tbl24[] */
> +	idx = _mm_cvtsi128_si64(i24);
> +	i24 = _mm_srli_si128(i24, sizeof(uint64_t));
> +
> +	tbl[0] = *(const uint16_t *)&lpm->tbl24[(uint32_t)idx];
> +	tbl[1] = *(const uint16_t *)&lpm->tbl24[idx >> 32];
> +
> +	idx = _mm_cvtsi128_si64(i24);
> +
> +	tbl[2] = *(const uint16_t *)&lpm->tbl24[(uint32_t)idx];
> +	tbl[3] = *(const uint16_t *)&lpm->tbl24[idx >> 32];
> +
> +	/* get 4 indexes for tbl8[]. */
> +	i8.x = _mm_and_si128(ip, mask8);
> +
> +	pt = (uint64_t)tbl[0] |
> +		(uint64_t)tbl[1] << 16 |
> +		(uint64_t)tbl[2] << 32 |
> +		(uint64_t)tbl[3] << 48;
> +
> +	/* search successfully finished for all 4 IP addresses. */
> +	if (likely((pt & mask_xv) == mask_v)) {
> +		uintptr_t ph = (uintptr_t)hop;
> +		*(uint64_t *)ph = pt & RTE_LPM_MASKX4_RES;
> +		return;
> +	}
> +
> +	if (unlikely((pt & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +		i8.u32[0] = i8.u32[0] +
> +			(uint8_t)tbl[0] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
> +		tbl[0] = *(const uint16_t *)&lpm->tbl8[i8.u32[0]];
> +	}
> +	if (unlikely((pt >> 16 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +		i8.u32[1] = i8.u32[1] +
> +			(uint8_t)tbl[1] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
> +		tbl[1] = *(const uint16_t *)&lpm->tbl8[i8.u32[1]];
> +	}
> +	if (unlikely((pt >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +		i8.u32[2] = i8.u32[2] +
> +			(uint8_t)tbl[2] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
> +		tbl[2] = *(const uint16_t *)&lpm->tbl8[i8.u32[2]];
> +	}
> +	if (unlikely((pt >> 48 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
> +			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
> +		i8.u32[3] = i8.u32[3] +
> +			(uint8_t)tbl[3] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
> +		tbl[3] = *(const uint16_t *)&lpm->tbl8[i8.u32[3]];
> +	}
> +
> +	hop[0] = (tbl[0] & RTE_LPM_LOOKUP_SUCCESS) ? (uint8_t)tbl[0] : defv;
> +	hop[1] = (tbl[1] & RTE_LPM_LOOKUP_SUCCESS) ? (uint8_t)tbl[1] : defv;
> +	hop[2] = (tbl[2] & RTE_LPM_LOOKUP_SUCCESS) ? (uint8_t)tbl[2] : defv;
> +	hop[3] = (tbl[3] & RTE_LPM_LOOKUP_SUCCESS) ? (uint8_t)tbl[3] : defv;
> +}
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_LPM_H_ */
> diff --git a/app/test/v2.0/test_lpm.c b/app/test/v2.0/test_lpm.c
> new file mode 100644
> index 000000000..e71d213ba
> --- /dev/null
> +++ b/app/test/v2.0/test_lpm.c
> @@ -0,0 +1,1306 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2010-2019 Intel Corporation
> + *
> + * LPM Autotests from DPDK v2.0 for abi compability testing.
> + *
> + */
> +
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <stdlib.h>
> +#include <errno.h>
> +#include <sys/queue.h>
> +
> +#include <rte_common.h>
> +#include <rte_cycles.h>
> +#include <rte_memory.h>
> +#include <rte_random.h>
> +#include <rte_branch_prediction.h>
> +#include <rte_ip.h>
> +#include <time.h>
> +
> +#include "../test_lpm_routes.h"
> +#include "../test.h"
> +
> +/* remapping of DPDK v2.0 symbols */
> +#include "dcompat.h"
> +/* backported header from DPDK v2.0 */
> +#include "rte_lpm.h"
> +
> +#define TEST_LPM_ASSERT(cond) do {                                            \
> +	if (!(cond)) {                                                        \
> +		printf("Error at line %d:\n", __LINE__);                      \
> +		return -1;                                                    \
> +	}                                                                     \
> +} while (0)
> +
> +typedef int32_t (*rte_lpm_test)(void);
> +
> +static int32_t test0(void);
> +static int32_t test1(void);
> +static int32_t test2(void);
> +static int32_t test3(void);
> +static int32_t test4(void);
> +static int32_t test5(void);
> +static int32_t test6(void);
> +static int32_t test7(void);
> +static int32_t test8(void);
> +static int32_t test9(void);
> +static int32_t test10(void);
> +static int32_t test11(void);
> +static int32_t test12(void);
> +static int32_t test13(void);
> +static int32_t test14(void);
> +static int32_t test15(void);
> +static int32_t test16(void);
> +static int32_t test17(void);
> +static int32_t perf_test(void);
> +
> +static rte_lpm_test tests[] = {
> +/* Test Cases */
> +	test0,
> +	test1,
> +	test2,
> +	test3,
> +	test4,
> +	test5,
> +	test6,
> +	test7,
> +	test8,
> +	test9,
> +	test10,
> +	test11,
> +	test12,
> +	test13,
> +	test14,
> +	test15,
> +	test16,
> +	test17,
> +	perf_test,
> +};
> +
> +#define NUM_LPM_TESTS (sizeof(tests)/sizeof(tests[0]))
> +#define MAX_DEPTH 32
> +#define MAX_RULES 256
> +#define PASS 0
> +
> +/*
> + * Check that rte_lpm_create fails gracefully for incorrect user input
> + * arguments
> + */
> +int32_t
> +test0(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +
> +	/* rte_lpm_create: lpm name == NULL */
> +	lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, MAX_RULES, 0);
> +	TEST_LPM_ASSERT(lpm == NULL);
> +
> +	/* rte_lpm_create: max_rules = 0 */
> +	/* Note: __func__ inserts the function name, in this case "test0". */
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, 0, 0);
> +	TEST_LPM_ASSERT(lpm == NULL);
> +
> +	/* socket_id < -1 is invalid */
> +	lpm = rte_lpm_create(__func__, -2, MAX_RULES, 0);
> +	TEST_LPM_ASSERT(lpm == NULL);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Create lpm table then delete lpm table 100 times
> + * Use a slightly different rules size each time
> + * */
> +int32_t
> +test1(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	int32_t i;
> +
> +	/* rte_lpm_free: Free NULL */
> +	for (i = 0; i < 100; i++) {
> +		lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES - i, 0);
> +		TEST_LPM_ASSERT(lpm != NULL);
> +
> +		rte_lpm_free(lpm);
> +	}
> +
> +	/* Can not test free so return success */
> +	return PASS;
> +}
> +
> +/*
> + * Call rte_lpm_free for NULL pointer user input. Note: free has no return and
> + * therefore it is impossible to check for failure but this test is added to
> + * increase function coverage metrics and to validate that freeing null does
> + * not crash.
> + */
> +int32_t
> +test2(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, RTE_LPM_HEAP);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	rte_lpm_free(lpm);
> +	rte_lpm_free(NULL);
> +	return PASS;
> +}
> +
> +/*
> + * Check that rte_lpm_add fails gracefully for incorrect user input arguments
> + */
> +int32_t
> +test3(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	uint32_t ip = IPv4(0, 0, 0, 0);
> +	uint8_t depth = 24, next_hop = 100;
> +	int32_t status = 0;
> +
> +	/* rte_lpm_add: lpm == NULL */
> +	status = rte_lpm_add(NULL, ip, depth, next_hop);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	/*Create vaild lpm to use in rest of test. */
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	/* rte_lpm_add: depth < 1 */
> +	status = rte_lpm_add(lpm, ip, 0, next_hop);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	/* rte_lpm_add: depth > MAX_DEPTH */
> +	status = rte_lpm_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Check that rte_lpm_delete fails gracefully for incorrect user input
> + * arguments
> + */
> +int32_t
> +test4(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	uint32_t ip = IPv4(0, 0, 0, 0);
> +	uint8_t depth = 24;
> +	int32_t status = 0;
> +
> +	/* rte_lpm_delete: lpm == NULL */
> +	status = rte_lpm_delete(NULL, ip, depth);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	/*Create vaild lpm to use in rest of test. */
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	/* rte_lpm_delete: depth < 1 */
> +	status = rte_lpm_delete(lpm, ip, 0);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	/* rte_lpm_delete: depth > MAX_DEPTH */
> +	status = rte_lpm_delete(lpm, ip, (MAX_DEPTH + 1));
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Check that rte_lpm_lookup fails gracefully for incorrect user input
> + * arguments
> + */
> +int32_t
> +test5(void)
> +{
> +#if defined(RTE_LIBRTE_LPM_DEBUG)
> +	struct rte_lpm *lpm = NULL;
> +	uint32_t ip = IPv4(0, 0, 0, 0);
> +	uint8_t next_hop_return = 0;
> +	int32_t status = 0;
> +
> +	/* rte_lpm_lookup: lpm == NULL */
> +	status = rte_lpm_lookup(NULL, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	/*Create vaild lpm to use in rest of test. */
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	/* rte_lpm_lookup: depth < 1 */
> +	status = rte_lpm_lookup(lpm, ip, NULL);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	rte_lpm_free(lpm);
> +#endif
> +	return PASS;
> +}
> +
> +
> +
> +/*
> + * Call add, lookup and delete for a single rule with depth <= 24
> + */
> +int32_t
> +test6(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	uint32_t ip = IPv4(0, 0, 0, 0);
> +	uint8_t depth = 24, next_hop_add = 100, next_hop_return = 0;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Call add, lookup and delete for a single rule with depth > 24
> + */
> +
> +int32_t
> +test7(void)
> +{
> +	__m128i ipx4;
> +	uint16_t hop[4];
> +	struct rte_lpm *lpm = NULL;
> +	uint32_t ip = IPv4(0, 0, 0, 0);
> +	uint8_t depth = 32, next_hop_add = 100, next_hop_return = 0;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	ipx4 = _mm_set_epi32(ip, ip + 0x100, ip - 0x100, ip);
> +	rte_lpm_lookupx4(lpm, ipx4, hop, UINT16_MAX);
> +	TEST_LPM_ASSERT(hop[0] == next_hop_add);
> +	TEST_LPM_ASSERT(hop[1] == UINT16_MAX);
> +	TEST_LPM_ASSERT(hop[2] == UINT16_MAX);
> +	TEST_LPM_ASSERT(hop[3] == next_hop_add);
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Use rte_lpm_add to add rules which effect only the second half of the lpm
> + * table. Use all possible depths ranging from 1..32. Set the next hop = to the
> + * depth. Check lookup hit for on every add and check for lookup miss on the
> + * first half of the lpm table after each add. Finally delete all rules going
> + * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
> + * delete. The lookup should return the next_hop_add value related to the
> + * previous depth value (i.e. depth -1).
> + */
> +int32_t
> +test8(void)
> +{
> +	__m128i ipx4;
> +	uint16_t hop[4];
> +	struct rte_lpm *lpm = NULL;
> +	uint32_t ip1 = IPv4(127, 255, 255, 255), ip2 = IPv4(128, 0, 0, 0);
> +	uint8_t depth, next_hop_add, next_hop_return;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	/* Loop with rte_lpm_add. */
> +	for (depth = 1; depth <= 32; depth++) {
> +		/* Let the next_hop_add value = depth. Just for change. */
> +		next_hop_add = depth;
> +
> +		status = rte_lpm_add(lpm, ip2, depth, next_hop_add);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		/* Check IP in first half of tbl24 which should be empty. */
> +		status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
> +		TEST_LPM_ASSERT(status == -ENOENT);
> +
> +		status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
> +		TEST_LPM_ASSERT((status == 0) &&
> +			(next_hop_return == next_hop_add));
> +
> +		ipx4 = _mm_set_epi32(ip2, ip1, ip2, ip1);
> +		rte_lpm_lookupx4(lpm, ipx4, hop, UINT16_MAX);
> +		TEST_LPM_ASSERT(hop[0] == UINT16_MAX);
> +		TEST_LPM_ASSERT(hop[1] == next_hop_add);
> +		TEST_LPM_ASSERT(hop[2] == UINT16_MAX);
> +		TEST_LPM_ASSERT(hop[3] == next_hop_add);
> +	}
> +
> +	/* Loop with rte_lpm_delete. */
> +	for (depth = 32; depth >= 1; depth--) {
> +		next_hop_add = (uint8_t) (depth - 1);
> +
> +		status = rte_lpm_delete(lpm, ip2, depth);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
> +
> +		if (depth != 1) {
> +			TEST_LPM_ASSERT((status == 0) &&
> +				(next_hop_return == next_hop_add));
> +		} else {
> +			TEST_LPM_ASSERT(status == -ENOENT);
> +		}
> +
> +		status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
> +		TEST_LPM_ASSERT(status == -ENOENT);
> +
> +		ipx4 = _mm_set_epi32(ip1, ip1, ip2, ip2);
> +		rte_lpm_lookupx4(lpm, ipx4, hop, UINT16_MAX);
> +		if (depth != 1) {
> +			TEST_LPM_ASSERT(hop[0] == next_hop_add);
> +			TEST_LPM_ASSERT(hop[1] == next_hop_add);
> +		} else {
> +			TEST_LPM_ASSERT(hop[0] == UINT16_MAX);
> +			TEST_LPM_ASSERT(hop[1] == UINT16_MAX);
> +		}
> +		TEST_LPM_ASSERT(hop[2] == UINT16_MAX);
> +		TEST_LPM_ASSERT(hop[3] == UINT16_MAX);
> +	}
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * - Add & lookup to hit invalid TBL24 entry
> + * - Add & lookup to hit valid TBL24 entry not extended
> + * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
> + * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
> + *
> + */
> +int32_t
> +test9(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	uint32_t ip, ip_1, ip_2;
> +	uint8_t depth, depth_1, depth_2, next_hop_add, next_hop_add_1,
> +		next_hop_add_2, next_hop_return;
> +	int32_t status = 0;
> +
> +	/* Add & lookup to hit invalid TBL24 entry */
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +	next_hop_add = 100;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Add & lookup to hit valid TBL24 entry not extended */
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 23;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	depth = 24;
> +	next_hop_add = 101;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	depth = 24;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	depth = 23;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
> +	 * entry */
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 32;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	ip = IPv4(128, 0, 0, 5);
> +	depth = 32;
> +	next_hop_add = 101;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 32;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Add & lookup to hit valid extended TBL24 entry with valid TBL8
> +	 * entry */
> +	ip_1 = IPv4(128, 0, 0, 0);
> +	depth_1 = 25;
> +	next_hop_add_1 = 101;
> +
> +	ip_2 = IPv4(128, 0, 0, 5);
> +	depth_2 = 32;
> +	next_hop_add_2 = 102;
> +
> +	next_hop_return = 0;
> +
> +	status = rte_lpm_add(lpm, ip_1, depth_1, next_hop_add_1);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
> +
> +	status = rte_lpm_add(lpm, ip_2, depth_2, next_hop_add_2);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
> +
> +	status = rte_lpm_delete(lpm, ip_2, depth_2);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
> +
> +	status = rte_lpm_delete(lpm, ip_1, depth_1);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +
> +/*
> + * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
> + *   lookup)
> + * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
> + * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
> + *   delete & lookup)
> + * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
> + * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
> + * - Delete a rule that is not present in the TBL24 & lookup
> + * - Delete a rule that is not present in the TBL8 & lookup
> + *
> + */
> +int32_t
> +test10(void)
> +{
> +
> +	struct rte_lpm *lpm = NULL;
> +	uint32_t ip;
> +	uint8_t depth, next_hop_add, next_hop_return;
> +	int32_t status = 0;
> +
> +	/* Add rule that covers a TBL24 range previously invalid & lookup
> +	 * (& delete & lookup) */
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, RTE_LPM_HEAP);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 16;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 25;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Add rule that extends a TBL24 valid entry & lookup for both rules
> +	 * (& delete & lookup) */
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	ip = IPv4(128, 0, 0, 10);
> +	depth = 32;
> +	next_hop_add = 101;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	ip = IPv4(128, 0, 0, 10);
> +	depth = 32;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Add rule that updates the next hop in TBL24 & lookup
> +	 * (& delete & lookup) */
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	next_hop_add = 101;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Add rule that updates the next hop in TBL8 & lookup
> +	 * (& delete & lookup) */
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 32;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	next_hop_add = 101;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Delete a rule that is not present in the TBL24 & lookup */
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_delete_all(lpm);
> +
> +	/* Delete a rule that is not present in the TBL8 & lookup */
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 32;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Add two rules, lookup to hit the more specific one, lookup to hit the less
> + * specific one delete the less specific rule and lookup previous values again;
> + * add a more specific rule than the existing rule, lookup again
> + *
> + * */
> +int32_t
> +test11(void)
> +{
> +
> +	struct rte_lpm *lpm = NULL;
> +	uint32_t ip;
> +	uint8_t depth, next_hop_add, next_hop_return;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	ip = IPv4(128, 0, 0, 10);
> +	depth = 32;
> +	next_hop_add = 101;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	next_hop_add = 100;
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	ip = IPv4(128, 0, 0, 10);
> +	depth = 32;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
> + * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension
> + * and contraction.
> + *
> + * */
> +
> +int32_t
> +test12(void)
> +{
> +	__m128i ipx4;
> +	uint16_t hop[4];
> +	struct rte_lpm *lpm = NULL;
> +	uint32_t ip, i;
> +	uint8_t depth, next_hop_add, next_hop_return;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 32;
> +	next_hop_add = 100;
> +
> +	for (i = 0; i < 1000; i++) {
> +		status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +		TEST_LPM_ASSERT((status == 0) &&
> +				(next_hop_return == next_hop_add));
> +
> +		ipx4 = _mm_set_epi32(ip, ip + 1, ip, ip - 1);
> +		rte_lpm_lookupx4(lpm, ipx4, hop, UINT16_MAX);
> +		TEST_LPM_ASSERT(hop[0] == UINT16_MAX);
> +		TEST_LPM_ASSERT(hop[1] == next_hop_add);
> +		TEST_LPM_ASSERT(hop[2] == UINT16_MAX);
> +		TEST_LPM_ASSERT(hop[3] == next_hop_add);
> +
> +		status = rte_lpm_delete(lpm, ip, depth);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +		TEST_LPM_ASSERT(status == -ENOENT);
> +	}
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Add a rule to tbl24, lookup (hit), then add a rule that will extend this
> + * tbl24 entry, lookup (hit). delete the rule that caused the tbl24 extension,
> + * lookup (miss) and repeat for loop of 1000 times. This will check tbl8
> + * extension and contraction.
> + *
> + * */
> +
> +int32_t
> +test13(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	uint32_t ip, i;
> +	uint8_t depth, next_hop_add_1, next_hop_add_2, next_hop_return;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	ip = IPv4(128, 0, 0, 0);
> +	depth = 24;
> +	next_hop_add_1 = 100;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add_1);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
> +
> +	depth = 32;
> +	next_hop_add_2 = 101;
> +
> +	for (i = 0; i < 1000; i++) {
> +		status = rte_lpm_add(lpm, ip, depth, next_hop_add_2);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +		TEST_LPM_ASSERT((status == 0) &&
> +				(next_hop_return == next_hop_add_2));
> +
> +		status = rte_lpm_delete(lpm, ip, depth);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +		TEST_LPM_ASSERT((status == 0) &&
> +				(next_hop_return == next_hop_add_1));
> +	}
> +
> +	depth = 24;
> +
> +	status = rte_lpm_delete(lpm, ip, depth);
> +	TEST_LPM_ASSERT(status == 0);
> +
> +	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +	TEST_LPM_ASSERT(status == -ENOENT);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Fore TBL8 extension exhaustion. Add 256 rules that require a tbl8 extension.
> + * No more tbl8 extensions will be allowed. Now add one more rule that required
> + * a tbl8 extension and get fail.
> + * */
> +int32_t
> +test14(void)
> +{
> +
> +	/* We only use depth = 32 in the loop below so we must make sure
> +	 * that we have enough storage for all rules at that depth*/
> +
> +	struct rte_lpm *lpm = NULL;
> +	uint32_t ip;
> +	uint8_t depth, next_hop_add, next_hop_return;
> +	int32_t status = 0;
> +
> +	/* Add enough space for 256 rules for every depth */
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, 256 * 32, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	depth = 32;
> +	next_hop_add = 100;
> +	ip = IPv4(0, 0, 0, 0);
> +
> +	/* Add 256 rules that require a tbl8 extension */
> +	for (; ip <= IPv4(0, 0, 255, 0); ip += 256) {
> +		status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +		TEST_LPM_ASSERT(status == 0);
> +
> +		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
> +		TEST_LPM_ASSERT((status == 0) &&
> +				(next_hop_return == next_hop_add));
> +	}
> +
> +	/* All tbl8 extensions have been used above. Try to add one more and
> +	 * we get a fail */
> +	ip = IPv4(1, 0, 0, 0);
> +	depth = 32;
> +
> +	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
> +	TEST_LPM_ASSERT(status < 0);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Sequence of operations for find existing lpm table
> + *
> + *  - create table
> + *  - find existing table: hit
> + *  - find non-existing table: miss
> + *
> + */
> +int32_t
> +test15(void)
> +{
> +	struct rte_lpm *lpm = NULL, *result = NULL;
> +
> +	/* Create lpm  */
> +	lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, 256 * 32, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	/* Try to find existing lpm */
> +	result = rte_lpm_find_existing("lpm_find_existing");
> +	TEST_LPM_ASSERT(result == lpm);
> +
> +	/* Try to find non-existing lpm */
> +	result = rte_lpm_find_existing("lpm_find_non_existing");
> +	TEST_LPM_ASSERT(result == NULL);
> +
> +	/* Cleanup. */
> +	rte_lpm_delete_all(lpm);
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * test failure condition of overloading the tbl8 so no more will fit
> + * Check we get an error return value in that case
> + */
> +int32_t
> +test16(void)
> +{
> +	uint32_t ip;
> +	struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY,
> +			256 * 32, 0);
> +
> +	/* ip loops through all possibilities for top 24 bits of address */
> +	for (ip = 0; ip < 0xFFFFFF; ip++) {
> +		/* add an entry within a different tbl8 each time, since
> +		 * depth >24 and the top 24 bits are different */
> +		if (rte_lpm_add(lpm, (ip << 8) + 0xF0, 30, 0) < 0)
> +			break;
> +	}
> +
> +	if (ip != RTE_LPM_TBL8_NUM_GROUPS) {
> +		printf("Error, unexpected failure with filling tbl8 groups\n");
> +		printf("Failed after %u additions, expected after %u\n",
> +				(unsigned)ip, (unsigned)RTE_LPM_TBL8_NUM_GROUPS);
> +	}
> +
> +	rte_lpm_free(lpm);
> +	return 0;
> +}
> +
> +/*
> + * Test for overwriting of tbl8:
> + *  - add rule /32 and lookup
> + *  - add new rule /24 and lookup
> + *	- add third rule /25 and lookup
> + *	- lookup /32 and /24 rule to ensure the table has not been overwritten.
> + */
> +int32_t
> +test17(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	const uint32_t ip_10_32 = IPv4(10, 10, 10, 2);
> +	const uint32_t ip_10_24 = IPv4(10, 10, 10, 0);
> +	const uint32_t ip_20_25 = IPv4(10, 10, 20, 2);
> +	const uint8_t d_ip_10_32 = 32,
> +			d_ip_10_24 = 24,
> +			d_ip_20_25 = 25;
> +	const uint8_t next_hop_ip_10_32 = 100,
> +			next_hop_ip_10_24 = 105,
> +			next_hop_ip_20_25 = 111;
> +	uint8_t next_hop_return = 0;
> +	int32_t status = 0;
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	status = rte_lpm_add(lpm, ip_10_32, d_ip_10_32, next_hop_ip_10_32);
> +	if (status < 0)
> +		return -1;
> +
> +	status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
> +	uint8_t test_hop_10_32 = next_hop_return;
> +	TEST_LPM_ASSERT(status == 0);
> +	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
> +
> +	status = rte_lpm_add(lpm, ip_10_24, d_ip_10_24, next_hop_ip_10_24);
> +	if (status < 0)
> +		return -1;
> +
> +	status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
> +	uint8_t test_hop_10_24 = next_hop_return;
> +	TEST_LPM_ASSERT(status == 0);
> +	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
> +
> +	status = rte_lpm_add(lpm, ip_20_25, d_ip_20_25, next_hop_ip_20_25);
> +	if (status < 0)
> +		return -1;
> +
> +	status = rte_lpm_lookup(lpm, ip_20_25, &next_hop_return);
> +	uint8_t test_hop_20_25 = next_hop_return;
> +	TEST_LPM_ASSERT(status == 0);
> +	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
> +
> +	if (test_hop_10_32 == test_hop_10_24) {
> +		printf("Next hop return equal\n");
> +		return -1;
> +	}
> +
> +	if (test_hop_10_24 == test_hop_20_25) {
> +		printf("Next hop return equal\n");
> +		return -1;
> +	}
> +
> +	status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
> +	TEST_LPM_ASSERT(status == 0);
> +	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
> +
> +	status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
> +	TEST_LPM_ASSERT(status == 0);
> +	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
> +
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Lookup performance test
> + */
> +
> +#define ITERATIONS (1 << 10)
> +#define BATCH_SIZE (1 << 12)
> +#define BULK_SIZE 32
> +
> +int32_t
> +perf_test(void)
> +{
> +	struct rte_lpm *lpm = NULL;
> +	uint64_t begin, total_time, lpm_used_entries = 0;
> +	unsigned i, j;
> +	uint8_t next_hop_add = 0xAA, next_hop_return = 0;
> +	int status = 0;
> +	uint64_t cache_line_counter = 0;
> +	int64_t count = 0;
> +
> +	rte_srand(rte_rdtsc());
> +
> +	/* (re) generate the routing table */
> +	generate_large_route_rule_table();
> +
> +	printf("No. routes = %u\n", (unsigned) NUM_ROUTE_ENTRIES);
> +
> +	print_route_distribution(large_route_table,
> +				 (uint32_t) NUM_ROUTE_ENTRIES);
> +
> +	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, 1000000, 0);
> +	TEST_LPM_ASSERT(lpm != NULL);
> +
> +	/* Measue add. */
> +	begin = rte_rdtsc();
> +
> +	for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
> +		if (rte_lpm_add(lpm, large_route_table[i].ip,
> +				large_route_table[i].depth, next_hop_add) == 0)
> +			status++;
> +	}
> +	/* End Timer. */
> +	total_time = rte_rdtsc() - begin;
> +
> +	printf("Unique added entries = %d\n", status);
> +	/* Obtain add statistics. */
> +	for (i = 0; i < RTE_LPM_TBL24_NUM_ENTRIES; i++) {
> +		if (lpm->tbl24[i].valid)
> +			lpm_used_entries++;
> +
> +		if (i % 32 == 0) {
> +			if ((uint64_t)count < lpm_used_entries) {
> +				cache_line_counter++;
> +				count = lpm_used_entries;
> +			}
> +		}
> +	}
> +
> +	printf("Used table 24 entries = %u (%g%%)\n",
> +			(unsigned) lpm_used_entries,
> +			(lpm_used_entries * 100.0) / RTE_LPM_TBL24_NUM_ENTRIES);
> +	printf("64 byte Cache entries used = %u (%u bytes)\n",
> +			(unsigned) cache_line_counter, (unsigned) cache_line_counter * 64);
> +
> +	printf("Average LPM Add: %g cycles\n", (double)total_time / NUM_ROUTE_ENTRIES);
> +
> +	/* Measure single Lookup */
> +	total_time = 0;
> +	count = 0;
> +
> +	for (i = 0; i < ITERATIONS; i++) {
> +		static uint32_t ip_batch[BATCH_SIZE];
> +
> +		for (j = 0; j < BATCH_SIZE; j++)
> +			ip_batch[j] = rte_rand();
> +
> +		/* Lookup per batch */
> +		begin = rte_rdtsc();
> +
> +		for (j = 0; j < BATCH_SIZE; j++) {
> +			if (rte_lpm_lookup(lpm, ip_batch[j], &next_hop_return) != 0)
> +				count++;
> +		}
> +
> +		total_time += rte_rdtsc() - begin;
> +
> +	}
> +	printf("Average LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
> +			(double)total_time / ((double)ITERATIONS * BATCH_SIZE),
> +			(count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
> +
> +	/* Measure bulk Lookup */
> +	total_time = 0;
> +	count = 0;
> +	for (i = 0; i < ITERATIONS; i++) {
> +		static uint32_t ip_batch[BATCH_SIZE];
> +		uint16_t next_hops[BULK_SIZE];
> +
> +		/* Create array of random IP addresses */
> +		for (j = 0; j < BATCH_SIZE; j++)
> +			ip_batch[j] = rte_rand();
> +
> +		/* Lookup per batch */
> +		begin = rte_rdtsc();
> +		for (j = 0; j < BATCH_SIZE; j += BULK_SIZE) {
> +			unsigned k;
> +			rte_lpm_lookup_bulk(lpm, &ip_batch[j], next_hops, BULK_SIZE);
> +			for (k = 0; k < BULK_SIZE; k++)
> +				if (unlikely(!(next_hops[k] & RTE_LPM_LOOKUP_SUCCESS)))
> +					count++;
> +		}
> +
> +		total_time += rte_rdtsc() - begin;
> +	}
> +	printf("BULK LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
> +			(double)total_time / ((double)ITERATIONS * BATCH_SIZE),
> +			(count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
> +
> +	/* Measure LookupX4 */
> +	total_time = 0;
> +	count = 0;
> +	for (i = 0; i < ITERATIONS; i++) {
> +		static uint32_t ip_batch[BATCH_SIZE];
> +		uint16_t next_hops[4];
> +
> +		/* Create array of random IP addresses */
> +		for (j = 0; j < BATCH_SIZE; j++)
> +			ip_batch[j] = rte_rand();
> +
> +		/* Lookup per batch */
> +		begin = rte_rdtsc();
> +		for (j = 0; j < BATCH_SIZE; j += RTE_DIM(next_hops)) {
> +			unsigned k;
> +			__m128i ipx4;
> +
> +			ipx4 = _mm_loadu_si128((__m128i *)(ip_batch + j));
> +			ipx4 = *(__m128i *)(ip_batch + j);
> +			rte_lpm_lookupx4(lpm, ipx4, next_hops, UINT16_MAX);
> +			for (k = 0; k < RTE_DIM(next_hops); k++)
> +				if (unlikely(next_hops[k] == UINT16_MAX))
> +					count++;
> +		}
> +
> +		total_time += rte_rdtsc() - begin;
> +	}
> +	printf("LPM LookupX4: %.1f cycles (fails = %.1f%%)\n",
> +			(double)total_time / ((double)ITERATIONS * BATCH_SIZE),
> +			(count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
> +
> +	/* Delete */
> +	status = 0;
> +	begin = rte_rdtsc();
> +
> +	for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
> +		/* rte_lpm_delete(lpm, ip, depth) */
> +		status += rte_lpm_delete(lpm, large_route_table[i].ip,
> +				large_route_table[i].depth);
> +	}
> +
> +	total_time += rte_rdtsc() - begin;
> +
> +	printf("Average LPM Delete: %g cycles\n",
> +			(double)total_time / NUM_ROUTE_ENTRIES);
> +
> +	rte_lpm_delete_all(lpm);
> +	rte_lpm_free(lpm);
> +
> +	return PASS;
> +}
> +
> +/*
> + * Do all unit and performance tests.
> + */
> +
> +static int
> +test_lpm(void)
> +{
> +	unsigned i;
> +	int status, global_status = 0;
> +
> +	for (i = 0; i < NUM_LPM_TESTS; i++) {
> +		status = tests[i]();
> +		if (status < 0) {
> +			printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests[i]));
> +			global_status = status;
> +		}
> +	}
> +
> +	return global_status;
> +}
> +
> +REGISTER_TEST_COMMAND_VERSION(lpm_autotest, test_lpm, TEST_DPDK_ABI_VERSION_V20);
> diff --git a/app/test/v2.0/test_v20.c b/app/test/v2.0/test_v20.c
> new file mode 100644
> index 000000000..6285e2882
> --- /dev/null
> +++ b/app/test/v2.0/test_v20.c
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2010-2014 Intel Corporation
> + */
> +
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <stdlib.h>
> +
> +#include <rte_ip.h>
> +#include <rte_lpm.h>
> +
> +#include "../test.h"
> +
> +REGISTER_TEST_ABI_VERSION(v20, TEST_DPDK_ABI_VERSION_V20);

^ permalink raw reply	[relevance 4%]

* Re: [dpdk-dev] [PATCH 00/15] prefix network structures
  @ 2019-05-29  7:59  0%     ` David Marchand
  2019-05-29 14:46  0%       ` Olivier Matz
  0 siblings, 1 reply; 200+ results
From: David Marchand @ 2019-05-29  7:59 UTC (permalink / raw)
  To: Ferruh Yigit
  Cc: Olivier Matz, dev, Stephen Hemminger, Maxime Coquelin, Thomas Monjalon

On Fri, May 24, 2019 at 1:38 PM Ferruh Yigit <ferruh.yigit@intel.com> wrote:

> On 5/21/2019 5:13 PM, Olivier Matz wrote:
> > The rte_net headers conflict with the libc headers, because
> > some definitions are duplicated, sometimes with few differences.
> >
> > This patchset adds the rte_ (or RTE_) prefix to all structures, functions
> > and defines in rte_net library. This is a big changeset, that will
> > break the API of many functions, but not the ABI.
> >
> > This was discussed in [1], and requested by the techboard [2].
> >
> > patch-v1:
> > * rease on top of v19.05
> > * remove uneeded renames in drivers/net/bonding/rte_eth_bond_pmd.c
> >   and app/test-pmd/icmpecho.c (arp-related variables)
> > * do not modify base drivers, except cxgbe, thunderx, enetc, qede:
> >   only files that already contain dpdk definitions are modified.
> > * fix checkpatch issues when it does not impact the code style too
> >   much. Big warnings remain about the RTE_IPv4() macros because
> >   arguments are separated by ',' instead of ', '.
> > * add a release note patch
> > * tested compilation on x86_64-linux and x86_64-freebsd.
> >
> > rfc-v2:
> > * rebase on top of v19.05-rc1
> >
> >
> > [1] http://mails.dpdk.org/archives/dev/2018-January/087384.html
> > [2] http://mails.dpdk.org/archives/dev/2019-February/125033.html
> >
> >
> > Olivier Matz (15):
> >   net: add rte prefix to arp structures
> >   net: add rte prefix to arp defines
> >   net: add rte prefix to ether structures
> >   net: add rte prefix to ether functions
> >   net: add rte prefix to ether defines
> >   net: add rte prefix to esp structure
> >   net: add rte prefix to gre structure
> >   net: add rte prefix to icmp structure
> >   net: add rte prefix to icmp defines
> >   net: add rte prefix to ip structure
> >   net: add rte prefix to ip defines
> >   net: add rte prefix to sctp structure
> >   net: add rte prefix to tcp structure
> >   net: add rte prefix to udp structure
> >   doc: announce network api change
>
> Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
> Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
>
> For series,
> Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
>
> Series applied to dpdk-next-net/master, thanks.
>

Sorry, late to the party...

Since we change those defines, we might as well avoid these warnings:
CHECK:CAMELCASE: Avoid CamelCase: <RTE_ETHER_TYPE_IPv4>
CHECK:CAMELCASE: Avoid CamelCase: <RTE_ETHER_TYPE_IPv6>

I can send a patch.


-- 
David Marchand

^ permalink raw reply	[relevance 0%]

* Re: [dpdk-dev] [PATCH 0/2] Add ABI Version Testing to app/test
  @ 2019-05-28 14:01  9%   ` Ray Kinsella
  0 siblings, 0 replies; 200+ results
From: Ray Kinsella @ 2019-05-28 14:01 UTC (permalink / raw)
  To: Bruce Richardson, Ray Kinsella; +Cc: vladimir.medvedkin, dev

Someone kindly approved it, and saved me sending it again from the right
email a/c, thank you.

On 28/05/2019 13:08, Bruce Richardson wrote:
> On Tue, May 28, 2019 at 12:51:56PM +0100, Ray Kinsella wrote:
>> This patchset adds ABI Version Testing functionality to the app/test unit
>> test framework.
>>
>> The patchset is intended to address two issues previously raised during ML
>> conversations on ABI Stability;
>> 1. How do we unit test still supported previous ABI Versions.
>> 2. How to we unit test inline functions from still supported previous ABI
>> Versions.
>>
>> The more obvious way to achieve both of the above is to simply archive
>> pre-built binaries compiled against previous versions of DPDK for use unit
>> testing previous ABI Versions, and while this should still be done as an
>> additional check, this approach does not scale well, must every DPDK
>> developer have a local copy of these binaries to test with, before
>> upstreaming changes?
>>
>> Instead starting with rte_lpm, I did the following:-
>>
>> * I reproduced mostly unmodified unit tests from previous ABI Versions,
>>   in this case v2.0 and v16.04
>> * I reproduced the rte_lpm interface header from these previous ABI
>>   Versions,including the inline functions and remapping symbols to
>>   appropriate versions.
>> * I added support for multiple abi versions to the app/test unit test
>>   framework to allow users to switch between abi versions (set_abi_version),
>>   without further polluting the already long list of unit tests available in
>>   app/test.
>>
>> The intention here is that, in future as developers need to depreciate
>> APIs, their associated unit tests may move into the ABI Version testing
>> mechanism of the app/test instead of being replaced by the latest set of
>> unit tests as would be the case today.
>>
>> ToDo:
>> * Refactor the v2.0 and v16.04 unit tests to separate functional and
>>   performance test cases.
>> * Add support for trigger ABI Version unit tests from the app/test command
>>   line.
>>
> While I admire the goal, given the amount of code that seems to be involved
> here, I'm not sure if the "test" binary is the place to put this. I think
> it might be better as a separate ABI compatiblity test app.

I did think about that also - the test binary, similar to testpmd is
very busy. I sought to mitigate that with set_abi_version command,
mitigating unit test name collisions etc.

I would have a huge concern about putting it into a separate binary, as
these tcs would quickly become forgotten about.

> 
> A separate question is whether this is really necessary to ensure ABI
> compatibility? 

I would argue that we currently have no idea if ABI versioned functions
actually work? Why offer backward compatibility, if we don't test it?

> Do other projects do this? 

The C++ stdlib is many ways similar to DPDK, ABI compatibility is a well
understood problem over there. See the following presentation Slide 20.

https://accu.org/content/conf2015/JonathanWakely-What%20Is%20An%20ABI%20And%20Why%20Is%20It%20So%20Complicated.pdf

They have a small corpus of TC's for this

https://github.com/gcc-mirror/gcc/tree/master/libstdc%2B%2B-v3/testsuite/[backward,abi]

> Is the info from the abi
> compatiblity checker script already in DPDK, or from other
> already-available tools not sufficient?

Well this just tells you that you ABI has changed. We don't have
anything at the moment that tells us that the ABI compatible functions
actually work ... ?

> 
> /Bruce
> 

^ permalink raw reply	[relevance 9%]

* [dpdk-dev] [PATCH 2/2] app/test: LPMv4 ABI Version Testing
  @ 2019-05-28 11:51  3% ` Ray Kinsella
  2019-05-29 13:50  4%   ` Aaron Conole
    1 sibling, 1 reply; 200+ results
From: Ray Kinsella @ 2019-05-28 11:51 UTC (permalink / raw)
  To: bruce.richardson, vladimir.medvedkin; +Cc: dev, Ray Kinsella

This second patch adds the LPM ABI Version Unit Tests, comprised of

1. Registering DPDK v2.0 and DPDK v16.04 ABI Versions with the
   infrastructure.
2. Forward Porting the DPDK v2.0 and DPDK v16.04 LPM Unit Test
   cases, remapping the LPM Library symbols to the appropriate versions.
3. Refactoring the lpm perf routes table to make this
   functionality available to the v2.0 and v16.04 unit tests, forwarding
   porting this code also from v2.0 etc would have increased the DPDK
   codebase several MLoC.q

Signed-off-by: Ray Kinsella <ray.kinsella@intel.com>
---
 app/test/Makefile              |   12 +-
 app/test/meson.build           |    5 +
 app/test/test_lpm.c            |    1 +
 app/test/test_lpm_perf.c       |  293 +------
 app/test/test_lpm_routes.c     |  287 +++++++
 app/test/test_lpm_routes.h     |   25 +
 app/test/v16.04/dcompat.h      |   23 +
 app/test/v16.04/rte_lpm.h      |  463 +++++++++++
 app/test/v16.04/rte_lpm_neon.h |  119 +++
 app/test/v16.04/rte_lpm_sse.h  |  120 +++
 app/test/v16.04/test_lpm.c     | 1405 ++++++++++++++++++++++++++++++++
 app/test/v16.04/test_v1604.c   |   14 +
 app/test/v2.0/dcompat.h        |   23 +
 app/test/v2.0/rte_lpm.h        |  443 ++++++++++
 app/test/v2.0/test_lpm.c       | 1306 +++++++++++++++++++++++++++++
 app/test/v2.0/test_v20.c       |   14 +
 16 files changed, 4261 insertions(+), 292 deletions(-)
 create mode 100644 app/test/test_lpm_routes.c
 create mode 100644 app/test/test_lpm_routes.h
 create mode 100644 app/test/v16.04/dcompat.h
 create mode 100644 app/test/v16.04/rte_lpm.h
 create mode 100644 app/test/v16.04/rte_lpm_neon.h
 create mode 100644 app/test/v16.04/rte_lpm_sse.h
 create mode 100644 app/test/v16.04/test_lpm.c
 create mode 100644 app/test/v16.04/test_v1604.c
 create mode 100644 app/test/v2.0/dcompat.h
 create mode 100644 app/test/v2.0/rte_lpm.h
 create mode 100644 app/test/v2.0/test_lpm.c
 create mode 100644 app/test/v2.0/test_v20.c

diff --git a/app/test/Makefile b/app/test/Makefile
index 68d6b4fbc..5899eb8b9 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -78,6 +78,10 @@ SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
 
+#ABI Version Testing
+SRCS-$(CONFIG_RTE_BUILD_SHARED_LIB) += v2.0/test_v20.c
+SRCS-$(CONFIG_RTE_BUILD_SHARED_LIB) += v16.04/test_v1604.c
+
 ifeq ($(CONFIG_RTE_LIBRTE_TABLE),y)
 SRCS-y += test_table.c
 SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += test_table_pipeline.c
@@ -107,7 +111,6 @@ SRCS-y += test_logs.c
 SRCS-y += test_memcpy.c
 SRCS-y += test_memcpy_perf.c
 
-
 SRCS-$(CONFIG_RTE_LIBRTE_MEMBER) += test_member.c
 SRCS-$(CONFIG_RTE_LIBRTE_MEMBER) += test_member_perf.c
 
@@ -122,11 +125,18 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_multiwriter.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_readwrite.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_readwrite_lf.c
 
+SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm_routes.c
 SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm.c
 SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm_perf.c
 SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6.c
 SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6_perf.c
 
+#LPM ABI Testing
+ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
+SRCS-$(CONFIG_RTE_LIBRTE_LPM) += v2.0/test_lpm.c
+SRCS-$(CONFIG_RTE_LIBRTE_LPM) += v16.04/test_lpm.c
+endif
+
 SRCS-y += test_debug.c
 SRCS-y += test_errno.c
 SRCS-y += test_tailq.c
diff --git a/app/test/meson.build b/app/test/meson.build
index 83391cef0..628f4e1ff 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -4,6 +4,8 @@
 test_sources = files('commands.c',
 	'packet_burst_generator.c',
 	'sample_packet_forward.c',
+	'v2.0/test_v20.c',
+	'v16.04/test_v1604.c',
 	'test.c',
 	'test_acl.c',
 	'test_alarm.c',
@@ -63,6 +65,9 @@ test_sources = files('commands.c',
 	'test_lpm6.c',
 	'test_lpm6_perf.c',
 	'test_lpm_perf.c',
+	'test_lpm_routes.c',
+	'v2.0/test_lpm.c',
+	'v16.04/test_lpm.c',
 	'test_malloc.c',
 	'test_mbuf.c',
 	'test_member.c',
diff --git a/app/test/test_lpm.c b/app/test/test_lpm.c
index 5d697dd0f..bfa702677 100644
--- a/app/test/test_lpm.c
+++ b/app/test/test_lpm.c
@@ -1277,6 +1277,7 @@ test_lpm(void)
 	int status, global_status = 0;
 
 	for (i = 0; i < NUM_LPM_TESTS; i++) {
+		printf("# test %02d\n", i);
 		status = tests[i]();
 		if (status < 0) {
 			printf("ERROR: LPM Test %u: FAIL\n", i);
diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 3b98ce0c8..a6b8b35c2 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -5,7 +5,6 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
-#include <math.h>
 
 #include <rte_cycles.h>
 #include <rte_random.h>
@@ -13,6 +12,7 @@
 #include <rte_ip.h>
 #include <rte_lpm.h>
 
+#include "test_lpm_routes.h"
 #include "test.h"
 #include "test_xmmt_ops.h"
 
@@ -27,295 +27,6 @@
 #define BATCH_SIZE (1 << 12)
 #define BULK_SIZE 32
 
-#define MAX_RULE_NUM (1200000)
-
-struct route_rule {
-	uint32_t ip;
-	uint8_t depth;
-};
-
-struct route_rule large_route_table[MAX_RULE_NUM];
-
-static uint32_t num_route_entries;
-#define NUM_ROUTE_ENTRIES num_route_entries
-
-enum {
-	IP_CLASS_A,
-	IP_CLASS_B,
-	IP_CLASS_C
-};
-
-/* struct route_rule_count defines the total number of rules in following a/b/c
- * each item in a[]/b[]/c[] is the number of common IP address class A/B/C, not
- * including the ones for private local network.
- */
-struct route_rule_count {
-	uint32_t a[RTE_LPM_MAX_DEPTH];
-	uint32_t b[RTE_LPM_MAX_DEPTH];
-	uint32_t c[RTE_LPM_MAX_DEPTH];
-};
-
-/* All following numbers of each depth of each common IP class are just
- * got from previous large constant table in app/test/test_lpm_routes.h .
- * In order to match similar performance, they keep same depth and IP
- * address coverage as previous constant table. These numbers don't
- * include any private local IP address. As previous large const rule
- * table was just dumped from a real router, there are no any IP address
- * in class C or D.
- */
-static struct route_rule_count rule_count = {
-	.a = { /* IP class A in which the most significant bit is 0 */
-		    0, /* depth =  1 */
-		    0, /* depth =  2 */
-		    1, /* depth =  3 */
-		    0, /* depth =  4 */
-		    2, /* depth =  5 */
-		    1, /* depth =  6 */
-		    3, /* depth =  7 */
-		  185, /* depth =  8 */
-		   26, /* depth =  9 */
-		   16, /* depth = 10 */
-		   39, /* depth = 11 */
-		  144, /* depth = 12 */
-		  233, /* depth = 13 */
-		  528, /* depth = 14 */
-		  866, /* depth = 15 */
-		 3856, /* depth = 16 */
-		 3268, /* depth = 17 */
-		 5662, /* depth = 18 */
-		17301, /* depth = 19 */
-		22226, /* depth = 20 */
-		11147, /* depth = 21 */
-		16746, /* depth = 22 */
-		17120, /* depth = 23 */
-		77578, /* depth = 24 */
-		  401, /* depth = 25 */
-		  656, /* depth = 26 */
-		 1107, /* depth = 27 */
-		 1121, /* depth = 28 */
-		 2316, /* depth = 29 */
-		  717, /* depth = 30 */
-		   10, /* depth = 31 */
-		   66  /* depth = 32 */
-	},
-	.b = { /* IP class A in which the most 2 significant bits are 10 */
-		    0, /* depth =  1 */
-		    0, /* depth =  2 */
-		    0, /* depth =  3 */
-		    0, /* depth =  4 */
-		    1, /* depth =  5 */
-		    1, /* depth =  6 */
-		    1, /* depth =  7 */
-		    3, /* depth =  8 */
-		    3, /* depth =  9 */
-		   30, /* depth = 10 */
-		   25, /* depth = 11 */
-		  168, /* depth = 12 */
-		  305, /* depth = 13 */
-		  569, /* depth = 14 */
-		 1129, /* depth = 15 */
-		50800, /* depth = 16 */
-		 1645, /* depth = 17 */
-		 1820, /* depth = 18 */
-		 3506, /* depth = 19 */
-		 3258, /* depth = 20 */
-		 3424, /* depth = 21 */
-		 4971, /* depth = 22 */
-		 6885, /* depth = 23 */
-		39771, /* depth = 24 */
-		  424, /* depth = 25 */
-		  170, /* depth = 26 */
-		  433, /* depth = 27 */
-		   92, /* depth = 28 */
-		  366, /* depth = 29 */
-		  377, /* depth = 30 */
-		    2, /* depth = 31 */
-		  200  /* depth = 32 */
-	},
-	.c = { /* IP class A in which the most 3 significant bits are 110 */
-		     0, /* depth =  1 */
-		     0, /* depth =  2 */
-		     0, /* depth =  3 */
-		     0, /* depth =  4 */
-		     0, /* depth =  5 */
-		     0, /* depth =  6 */
-		     0, /* depth =  7 */
-		    12, /* depth =  8 */
-		     8, /* depth =  9 */
-		     9, /* depth = 10 */
-		    33, /* depth = 11 */
-		    69, /* depth = 12 */
-		   237, /* depth = 13 */
-		  1007, /* depth = 14 */
-		  1717, /* depth = 15 */
-		 14663, /* depth = 16 */
-		  8070, /* depth = 17 */
-		 16185, /* depth = 18 */
-		 48261, /* depth = 19 */
-		 36870, /* depth = 20 */
-		 33960, /* depth = 21 */
-		 50638, /* depth = 22 */
-		 61422, /* depth = 23 */
-		466549, /* depth = 24 */
-		  1829, /* depth = 25 */
-		  4824, /* depth = 26 */
-		  4927, /* depth = 27 */
-		  5914, /* depth = 28 */
-		 10254, /* depth = 29 */
-		  4905, /* depth = 30 */
-		     1, /* depth = 31 */
-		   716  /* depth = 32 */
-	}
-};
-
-static void generate_random_rule_prefix(uint32_t ip_class, uint8_t depth)
-{
-/* IP address class A, the most significant bit is 0 */
-#define IP_HEAD_MASK_A			0x00000000
-#define IP_HEAD_BIT_NUM_A		1
-
-/* IP address class B, the most significant 2 bits are 10 */
-#define IP_HEAD_MASK_B			0x80000000
-#define IP_HEAD_BIT_NUM_B		2
-
-/* IP address class C, the most significant 3 bits are 110 */
-#define IP_HEAD_MASK_C			0xC0000000
-#define IP_HEAD_BIT_NUM_C		3
-
-	uint32_t class_depth;
-	uint32_t range;
-	uint32_t mask;
-	uint32_t step;
-	uint32_t start;
-	uint32_t fixed_bit_num;
-	uint32_t ip_head_mask;
-	uint32_t rule_num;
-	uint32_t k;
-	struct route_rule *ptr_rule;
-
-	if (ip_class == IP_CLASS_A) {        /* IP Address class A */
-		fixed_bit_num = IP_HEAD_BIT_NUM_A;
-		ip_head_mask = IP_HEAD_MASK_A;
-		rule_num = rule_count.a[depth - 1];
-	} else if (ip_class == IP_CLASS_B) { /* IP Address class B */
-		fixed_bit_num = IP_HEAD_BIT_NUM_B;
-		ip_head_mask = IP_HEAD_MASK_B;
-		rule_num = rule_count.b[depth - 1];
-	} else {                             /* IP Address class C */
-		fixed_bit_num = IP_HEAD_BIT_NUM_C;
-		ip_head_mask = IP_HEAD_MASK_C;
-		rule_num = rule_count.c[depth - 1];
-	}
-
-	if (rule_num == 0)
-		return;
-
-	/* the number of rest bits which don't include the most significant
-	 * fixed bits for this IP address class
-	 */
-	class_depth = depth - fixed_bit_num;
-
-	/* range is the maximum number of rules for this depth and
-	 * this IP address class
-	 */
-	range = 1 << class_depth;
-
-	/* only mask the most depth significant generated bits
-	 * except fixed bits for IP address class
-	 */
-	mask = range - 1;
-
-	/* Widen coverage of IP address in generated rules */
-	if (range <= rule_num)
-		step = 1;
-	else
-		step = round((double)range / rule_num);
-
-	/* Only generate rest bits except the most significant
-	 * fixed bits for IP address class
-	 */
-	start = lrand48() & mask;
-	ptr_rule = &large_route_table[num_route_entries];
-	for (k = 0; k < rule_num; k++) {
-		ptr_rule->ip = (start << (RTE_LPM_MAX_DEPTH - depth))
-			| ip_head_mask;
-		ptr_rule->depth = depth;
-		ptr_rule++;
-		start = (start + step) & mask;
-	}
-	num_route_entries += rule_num;
-}
-
-static void insert_rule_in_random_pos(uint32_t ip, uint8_t depth)
-{
-	uint32_t pos;
-	int try_count = 0;
-	struct route_rule tmp;
-
-	do {
-		pos = lrand48();
-		try_count++;
-	} while ((try_count < 10) && (pos > num_route_entries));
-
-	if ((pos > num_route_entries) || (pos >= MAX_RULE_NUM))
-		pos = num_route_entries >> 1;
-
-	tmp = large_route_table[pos];
-	large_route_table[pos].ip = ip;
-	large_route_table[pos].depth = depth;
-	if (num_route_entries < MAX_RULE_NUM)
-		large_route_table[num_route_entries++] = tmp;
-}
-
-static void generate_large_route_rule_table(void)
-{
-	uint32_t ip_class;
-	uint8_t  depth;
-
-	num_route_entries = 0;
-	memset(large_route_table, 0, sizeof(large_route_table));
-
-	for (ip_class = IP_CLASS_A; ip_class <= IP_CLASS_C; ip_class++) {
-		for (depth = 1; depth <= RTE_LPM_MAX_DEPTH; depth++) {
-			generate_random_rule_prefix(ip_class, depth);
-		}
-	}
-
-	/* Add following rules to keep same as previous large constant table,
-	 * they are 4 rules with private local IP address and 1 all-zeros prefix
-	 * with depth = 8.
-	 */
-	insert_rule_in_random_pos(IPv4(0, 0, 0, 0), 8);
-	insert_rule_in_random_pos(IPv4(10, 2, 23, 147), 32);
-	insert_rule_in_random_pos(IPv4(192, 168, 100, 10), 24);
-	insert_rule_in_random_pos(IPv4(192, 168, 25, 100), 24);
-	insert_rule_in_random_pos(IPv4(192, 168, 129, 124), 32);
-}
-
-static void
-print_route_distribution(const struct route_rule *table, uint32_t n)
-{
-	unsigned i, j;
-
-	printf("Route distribution per prefix width: \n");
-	printf("DEPTH    QUANTITY (PERCENT)\n");
-	printf("--------------------------- \n");
-
-	/* Count depths. */
-	for (i = 1; i <= 32; i++) {
-		unsigned depth_counter = 0;
-		double percent_hits;
-
-		for (j = 0; j < n; j++)
-			if (table[j].depth == (uint8_t) i)
-				depth_counter++;
-
-		percent_hits = ((double)depth_counter)/((double)n) * 100;
-		printf("%.2u%15u (%.2f)\n", i, depth_counter, percent_hits);
-	}
-	printf("\n");
-}
-
 static int
 test_lpm_perf(void)
 {
@@ -375,7 +86,7 @@ test_lpm_perf(void)
 			(unsigned) cache_line_counter, (unsigned) cache_line_counter * 64);
 
 	printf("Average LPM Add: %g cycles\n",
-			(double)total_time / NUM_ROUTE_ENTRIES);
+	       (double)total_time / NUM_ROUTE_ENTRIES);
 
 	/* Measure single Lookup */
 	total_time = 0;
diff --git a/app/test/test_lpm_routes.c b/app/test/test_lpm_routes.c
new file mode 100644
index 000000000..08128542a
--- /dev/null
+++ b/app/test/test_lpm_routes.c
@@ -0,0 +1,287 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2019 Intel Corporation
+ */
+
+#include <math.h>
+
+#include "rte_lpm.h"
+#include "test_lpm_routes.h"
+
+uint32_t num_route_entries;
+struct route_rule large_route_table[MAX_RULE_NUM];
+
+enum {
+	IP_CLASS_A,
+	IP_CLASS_B,
+	IP_CLASS_C
+};
+
+/* struct route_rule_count defines the total number of rules in following a/b/c
+ * each item in a[]/b[]/c[] is the number of common IP address class A/B/C, not
+ * including the ones for private local network.
+ */
+struct route_rule_count {
+	uint32_t a[RTE_LPM_MAX_DEPTH];
+	uint32_t b[RTE_LPM_MAX_DEPTH];
+	uint32_t c[RTE_LPM_MAX_DEPTH];
+};
+
+/* All following numbers of each depth of each common IP class are just
+ * got from previous large constant table in app/test/test_lpm_routes.h .
+ * In order to match similar performance, they keep same depth and IP
+ * address coverage as previous constant table. These numbers don't
+ * include any private local IP address. As previous large const rule
+ * table was just dumped from a real router, there are no any IP address
+ * in class C or D.
+ */
+static struct route_rule_count rule_count = {
+	.a = { /* IP class A in which the most significant bit is 0 */
+		    0, /* depth =  1 */
+		    0, /* depth =  2 */
+		    1, /* depth =  3 */
+		    0, /* depth =  4 */
+		    2, /* depth =  5 */
+		    1, /* depth =  6 */
+		    3, /* depth =  7 */
+		  185, /* depth =  8 */
+		   26, /* depth =  9 */
+		   16, /* depth = 10 */
+		   39, /* depth = 11 */
+		  144, /* depth = 12 */
+		  233, /* depth = 13 */
+		  528, /* depth = 14 */
+		  866, /* depth = 15 */
+		 3856, /* depth = 16 */
+		 3268, /* depth = 17 */
+		 5662, /* depth = 18 */
+		17301, /* depth = 19 */
+		22226, /* depth = 20 */
+		11147, /* depth = 21 */
+		16746, /* depth = 22 */
+		17120, /* depth = 23 */
+		77578, /* depth = 24 */
+		  401, /* depth = 25 */
+		  656, /* depth = 26 */
+		 1107, /* depth = 27 */
+		 1121, /* depth = 28 */
+		 2316, /* depth = 29 */
+		  717, /* depth = 30 */
+		   10, /* depth = 31 */
+		   66  /* depth = 32 */
+	},
+	.b = { /* IP class A in which the most 2 significant bits are 10 */
+		    0, /* depth =  1 */
+		    0, /* depth =  2 */
+		    0, /* depth =  3 */
+		    0, /* depth =  4 */
+		    1, /* depth =  5 */
+		    1, /* depth =  6 */
+		    1, /* depth =  7 */
+		    3, /* depth =  8 */
+		    3, /* depth =  9 */
+		   30, /* depth = 10 */
+		   25, /* depth = 11 */
+		  168, /* depth = 12 */
+		  305, /* depth = 13 */
+		  569, /* depth = 14 */
+		 1129, /* depth = 15 */
+		50800, /* depth = 16 */
+		 1645, /* depth = 17 */
+		 1820, /* depth = 18 */
+		 3506, /* depth = 19 */
+		 3258, /* depth = 20 */
+		 3424, /* depth = 21 */
+		 4971, /* depth = 22 */
+		 6885, /* depth = 23 */
+		39771, /* depth = 24 */
+		  424, /* depth = 25 */
+		  170, /* depth = 26 */
+		  433, /* depth = 27 */
+		   92, /* depth = 28 */
+		  366, /* depth = 29 */
+		  377, /* depth = 30 */
+		    2, /* depth = 31 */
+		  200  /* depth = 32 */
+	},
+	.c = { /* IP class A in which the most 3 significant bits are 110 */
+		     0, /* depth =  1 */
+		     0, /* depth =  2 */
+		     0, /* depth =  3 */
+		     0, /* depth =  4 */
+		     0, /* depth =  5 */
+		     0, /* depth =  6 */
+		     0, /* depth =  7 */
+		    12, /* depth =  8 */
+		     8, /* depth =  9 */
+		     9, /* depth = 10 */
+		    33, /* depth = 11 */
+		    69, /* depth = 12 */
+		   237, /* depth = 13 */
+		  1007, /* depth = 14 */
+		  1717, /* depth = 15 */
+		 14663, /* depth = 16 */
+		  8070, /* depth = 17 */
+		 16185, /* depth = 18 */
+		 48261, /* depth = 19 */
+		 36870, /* depth = 20 */
+		 33960, /* depth = 21 */
+		 50638, /* depth = 22 */
+		 61422, /* depth = 23 */
+		466549, /* depth = 24 */
+		  1829, /* depth = 25 */
+		  4824, /* depth = 26 */
+		  4927, /* depth = 27 */
+		  5914, /* depth = 28 */
+		 10254, /* depth = 29 */
+		  4905, /* depth = 30 */
+		     1, /* depth = 31 */
+		   716  /* depth = 32 */
+	}
+};
+
+static void generate_random_rule_prefix(uint32_t ip_class, uint8_t depth)
+{
+/* IP address class A, the most significant bit is 0 */
+#define IP_HEAD_MASK_A			0x00000000
+#define IP_HEAD_BIT_NUM_A		1
+
+/* IP address class B, the most significant 2 bits are 10 */
+#define IP_HEAD_MASK_B			0x80000000
+#define IP_HEAD_BIT_NUM_B		2
+
+/* IP address class C, the most significant 3 bits are 110 */
+#define IP_HEAD_MASK_C			0xC0000000
+#define IP_HEAD_BIT_NUM_C		3
+
+	uint32_t class_depth;
+	uint32_t range;
+	uint32_t mask;
+	uint32_t step;
+	uint32_t start;
+	uint32_t fixed_bit_num;
+	uint32_t ip_head_mask;
+	uint32_t rule_num;
+	uint32_t k;
+	struct route_rule *ptr_rule;
+
+	if (ip_class == IP_CLASS_A) {        /* IP Address class A */
+		fixed_bit_num = IP_HEAD_BIT_NUM_A;
+		ip_head_mask = IP_HEAD_MASK_A;
+		rule_num = rule_count.a[depth - 1];
+	} else if (ip_class == IP_CLASS_B) { /* IP Address class B */
+		fixed_bit_num = IP_HEAD_BIT_NUM_B;
+		ip_head_mask = IP_HEAD_MASK_B;
+		rule_num = rule_count.b[depth - 1];
+	} else {                             /* IP Address class C */
+		fixed_bit_num = IP_HEAD_BIT_NUM_C;
+		ip_head_mask = IP_HEAD_MASK_C;
+		rule_num = rule_count.c[depth - 1];
+	}
+
+	if (rule_num == 0)
+		return;
+
+	/* the number of rest bits which don't include the most significant
+	 * fixed bits for this IP address class
+	 */
+	class_depth = depth - fixed_bit_num;
+
+	/* range is the maximum number of rules for this depth and
+	 * this IP address class
+	 */
+	range = 1 << class_depth;
+
+	/* only mask the most depth significant generated bits
+	 * except fixed bits for IP address class
+	 */
+	mask = range - 1;
+
+	/* Widen coverage of IP address in generated rules */
+	if (range <= rule_num)
+		step = 1;
+	else
+		step = round((double)range / rule_num);
+
+	/* Only generate rest bits except the most significant
+	 * fixed bits for IP address class
+	 */
+	start = lrand48() & mask;
+	ptr_rule = &large_route_table[num_route_entries];
+	for (k = 0; k < rule_num; k++) {
+		ptr_rule->ip = (start << (RTE_LPM_MAX_DEPTH - depth))
+			| ip_head_mask;
+		ptr_rule->depth = depth;
+		ptr_rule++;
+		start = (start + step) & mask;
+	}
+	num_route_entries += rule_num;
+}
+
+static void insert_rule_in_random_pos(uint32_t ip, uint8_t depth)
+{
+	uint32_t pos;
+	int try_count = 0;
+	struct route_rule tmp;
+
+	do {
+		pos = lrand48();
+		try_count++;
+	} while ((try_count < 10) && (pos > num_route_entries));
+
+	if ((pos > num_route_entries) || (pos >= MAX_RULE_NUM))
+		pos = num_route_entries >> 1;
+
+	tmp = large_route_table[pos];
+	large_route_table[pos].ip = ip;
+	large_route_table[pos].depth = depth;
+	if (num_route_entries < MAX_RULE_NUM)
+		large_route_table[num_route_entries++] = tmp;
+}
+
+void generate_large_route_rule_table(void)
+{
+	uint32_t ip_class;
+	uint8_t  depth;
+
+	num_route_entries = 0;
+	memset(large_route_table, 0, sizeof(large_route_table));
+
+	for (ip_class = IP_CLASS_A; ip_class <= IP_CLASS_C; ip_class++) {
+		for (depth = 1; depth <= RTE_LPM_MAX_DEPTH; depth++)
+			generate_random_rule_prefix(ip_class, depth);
+	}
+
+	/* Add following rules to keep same as previous large constant table,
+	 * they are 4 rules with private local IP address and 1 all-zeros prefix
+	 * with depth = 8.
+	 */
+	insert_rule_in_random_pos(IPv4(0, 0, 0, 0), 8);
+	insert_rule_in_random_pos(IPv4(10, 2, 23, 147), 32);
+	insert_rule_in_random_pos(IPv4(192, 168, 100, 10), 24);
+	insert_rule_in_random_pos(IPv4(192, 168, 25, 100), 24);
+	insert_rule_in_random_pos(IPv4(192, 168, 129, 124), 32);
+}
+
+void
+print_route_distribution(const struct route_rule *table, uint32_t n)
+{
+	unsigned int i, j;
+
+	printf("Route distribution per prefix width: \n");
+	printf("DEPTH    QUANTITY (PERCENT)\n");
+	printf("---------------------------\n");
+
+	/* Count depths. */
+	for (i = 1; i <= 32; i++) {
+		unsigned int depth_counter = 0;
+		double percent_hits;
+
+		for (j = 0; j < n; j++)
+			if (table[j].depth == (uint8_t) i)
+				depth_counter++;
+
+		percent_hits = ((double)depth_counter)/((double)n) * 100;
+		printf("%.2u%15u (%.2f)\n", i, depth_counter, percent_hits);
+	}
+	printf("\n");
+}
diff --git a/app/test/test_lpm_routes.h b/app/test/test_lpm_routes.h
new file mode 100644
index 000000000..c7874ea8f
--- /dev/null
+++ b/app/test/test_lpm_routes.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2019 Intel Corporation
+ */
+
+#ifndef _TEST_LPM_ROUTES_H_
+#define _TEST_LPM_ROUTES_H_
+
+#include <rte_ip.h>
+
+#define MAX_RULE_NUM (1200000)
+
+struct route_rule {
+	uint32_t ip;
+	uint8_t depth;
+};
+
+extern struct route_rule large_route_table[MAX_RULE_NUM];
+
+extern uint32_t num_route_entries;
+#define NUM_ROUTE_ENTRIES num_route_entries
+
+void generate_large_route_rule_table(void);
+void print_route_distribution(const struct route_rule *table, uint32_t n);
+
+#endif
diff --git a/app/test/v16.04/dcompat.h b/app/test/v16.04/dcompat.h
new file mode 100644
index 000000000..889c3b503
--- /dev/null
+++ b/app/test/v16.04/dcompat.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2019 Intel Corporation
+ */
+
+#ifndef _DCOMPAT_H_
+#define _DCOMPAT_H_
+
+#define ABI_VERSION DPDK_16.04
+
+#define MAP_ABI_SYMBOL(name) \
+	MAP_ABI_SYMBOL_VERSION(name, ABI_VERSION)
+
+MAP_ABI_SYMBOL(rte_lpm_add);
+MAP_ABI_SYMBOL(rte_lpm_create);
+MAP_ABI_SYMBOL(rte_lpm_delete);
+MAP_ABI_SYMBOL(rte_lpm_delete_all);
+MAP_ABI_SYMBOL(rte_lpm_find_existing);
+MAP_ABI_SYMBOL(rte_lpm_free);
+MAP_ABI_SYMBOL(rte_lpm_is_rule_present);
+
+#undef MAP_ABI_SYMBOL
+
+#endif
diff --git a/app/test/v16.04/rte_lpm.h b/app/test/v16.04/rte_lpm.h
new file mode 100644
index 000000000..c3348fbc1
--- /dev/null
+++ b/app/test/v16.04/rte_lpm.h
@@ -0,0 +1,463 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef _RTE_LPM_H_
+#define _RTE_LPM_H_
+
+/**
+ * @file
+ * RTE Longest Prefix Match (LPM)
+ */
+
+#include <errno.h>
+#include <sys/queue.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <rte_branch_prediction.h>
+#include <rte_byteorder.h>
+#include <rte_memory.h>
+#include <rte_common.h>
+#include <rte_vect.h>
+#include <rte_compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Max number of characters in LPM name. */
+#define RTE_LPM_NAMESIZE                32
+
+/** Maximum depth value possible for IPv4 LPM. */
+#define RTE_LPM_MAX_DEPTH               32
+
+/** @internal Total number of tbl24 entries. */
+#define RTE_LPM_TBL24_NUM_ENTRIES       (1 << 24)
+
+/** @internal Number of entries in a tbl8 group. */
+#define RTE_LPM_TBL8_GROUP_NUM_ENTRIES  256
+
+/** @internal Max number of tbl8 groups in the tbl8. */
+#define RTE_LPM_MAX_TBL8_NUM_GROUPS         (1 << 24)
+
+/** @internal Total number of tbl8 groups in the tbl8. */
+#define RTE_LPM_TBL8_NUM_GROUPS         256
+
+/** @internal Total number of tbl8 entries. */
+#define RTE_LPM_TBL8_NUM_ENTRIES        (RTE_LPM_TBL8_NUM_GROUPS * \
+					RTE_LPM_TBL8_GROUP_NUM_ENTRIES)
+
+/** @internal Macro to enable/disable run-time checks. */
+#if defined(RTE_LIBRTE_LPM_DEBUG)
+#define RTE_LPM_RETURN_IF_TRUE(cond, retval) do { \
+	if (cond) \
+		return (retval); \
+} while (0)
+#else
+#define RTE_LPM_RETURN_IF_TRUE(cond, retval)
+#endif
+
+/** @internal bitmask with valid and valid_group fields set */
+#define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x03000000
+
+/** Bitmask used to indicate successful lookup */
+#define RTE_LPM_LOOKUP_SUCCESS          0x01000000
+
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+/** @internal Tbl24 entry structure. */
+struct rte_lpm_tbl_entry_v20 {
+	/**
+	 * Stores Next hop (tbl8 or tbl24 when valid_group is not set) or
+	 * a group index pointing to a tbl8 structure (tbl24 only, when
+	 * valid_group is set)
+	 */
+	union {
+		uint8_t next_hop;
+		uint8_t group_idx;
+	};
+	/* Using single uint8_t to store 3 values. */
+	uint8_t valid     :1;   /**< Validation flag. */
+	/**
+	 * For tbl24:
+	 *  - valid_group == 0: entry stores a next hop
+	 *  - valid_group == 1: entry stores a group_index pointing to a tbl8
+	 * For tbl8:
+	 *  - valid_group indicates whether the current tbl8 is in use or not
+	 */
+	uint8_t valid_group :1;
+	uint8_t depth       :6; /**< Rule depth. */
+};
+
+struct rte_lpm_tbl_entry {
+	/**
+	 * Stores Next hop (tbl8 or tbl24 when valid_group is not set) or
+	 * a group index pointing to a tbl8 structure (tbl24 only, when
+	 * valid_group is set)
+	 */
+	uint32_t next_hop    :24;
+	/* Using single uint8_t to store 3 values. */
+	uint32_t valid       :1;   /**< Validation flag. */
+	/**
+	 * For tbl24:
+	 *  - valid_group == 0: entry stores a next hop
+	 *  - valid_group == 1: entry stores a group_index pointing to a tbl8
+	 * For tbl8:
+	 *  - valid_group indicates whether the current tbl8 is in use or not
+	 */
+	uint32_t valid_group :1;
+	uint32_t depth       :6; /**< Rule depth. */
+};
+
+#else
+struct rte_lpm_tbl_entry_v20 {
+	uint8_t depth       :6;
+	uint8_t valid_group :1;
+	uint8_t valid       :1;
+	union {
+		uint8_t group_idx;
+		uint8_t next_hop;
+	};
+};
+
+struct rte_lpm_tbl_entry {
+	uint32_t depth       :6;
+	uint32_t valid_group :1;
+	uint32_t valid       :1;
+	uint32_t next_hop    :24;
+
+};
+
+#endif
+
+/** LPM configuration structure. */
+struct rte_lpm_config {
+	uint32_t max_rules;      /**< Max number of rules. */
+	uint32_t number_tbl8s;   /**< Number of tbl8s to allocate. */
+	int flags;               /**< This field is currently unused. */
+};
+
+/** @internal Rule structure. */
+struct rte_lpm_rule_v20 {
+	uint32_t ip; /**< Rule IP address. */
+	uint8_t  next_hop; /**< Rule next hop. */
+};
+
+struct rte_lpm_rule {
+	uint32_t ip; /**< Rule IP address. */
+	uint32_t next_hop; /**< Rule next hop. */
+};
+
+/** @internal Contains metadata about the rules table. */
+struct rte_lpm_rule_info {
+	uint32_t used_rules; /**< Used rules so far. */
+	uint32_t first_rule; /**< Indexes the first rule of a given depth. */
+};
+
+/** @internal LPM structure. */
+struct rte_lpm_v20 {
+	/* LPM metadata. */
+	char name[RTE_LPM_NAMESIZE];        /**< Name of the lpm. */
+	uint32_t max_rules; /**< Max. balanced rules per lpm. */
+	struct rte_lpm_rule_info rule_info[RTE_LPM_MAX_DEPTH]; /**< Rule info table. */
+
+	/* LPM Tables. */
+	struct rte_lpm_tbl_entry_v20 tbl24[RTE_LPM_TBL24_NUM_ENTRIES]
+			__rte_cache_aligned; /**< LPM tbl24 table. */
+	struct rte_lpm_tbl_entry_v20 tbl8[RTE_LPM_TBL8_NUM_ENTRIES]
+			__rte_cache_aligned; /**< LPM tbl8 table. */
+	struct rte_lpm_rule_v20 rules_tbl[0] \
+			__rte_cache_aligned; /**< LPM rules. */
+};
+
+struct rte_lpm {
+	/* LPM metadata. */
+	char name[RTE_LPM_NAMESIZE];        /**< Name of the lpm. */
+	uint32_t max_rules; /**< Max. balanced rules per lpm. */
+	uint32_t number_tbl8s; /**< Number of tbl8s. */
+	struct rte_lpm_rule_info rule_info[RTE_LPM_MAX_DEPTH]; /**< Rule info table. */
+
+	/* LPM Tables. */
+	struct rte_lpm_tbl_entry tbl24[RTE_LPM_TBL24_NUM_ENTRIES]
+			__rte_cache_aligned; /**< LPM tbl24 table. */
+	struct rte_lpm_tbl_entry *tbl8; /**< LPM tbl8 table. */
+	struct rte_lpm_rule *rules_tbl; /**< LPM rules. */
+};
+
+/**
+ * Create an LPM object.
+ *
+ * @param name
+ *   LPM object name
+ * @param socket_id
+ *   NUMA socket ID for LPM table memory allocation
+ * @param config
+ *   Structure containing the configuration
+ * @return
+ *   Handle to LPM object on success, NULL otherwise with rte_errno set
+ *   to an appropriate values. Possible rte_errno values include:
+ *    - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
+ *    - E_RTE_SECONDARY - function was called from a secondary process instance
+ *    - EINVAL - invalid parameter passed to function
+ *    - ENOSPC - the maximum number of memzones has already been allocated
+ *    - EEXIST - a memzone with the same name already exists
+ *    - ENOMEM - no appropriate memory area found in which to create memzone
+ */
+struct rte_lpm *
+rte_lpm_create(const char *name, int socket_id,
+		const struct rte_lpm_config *config);
+struct rte_lpm_v20 *
+rte_lpm_create_v20(const char *name, int socket_id, int max_rules, int flags);
+struct rte_lpm *
+rte_lpm_create_v1604(const char *name, int socket_id,
+		const struct rte_lpm_config *config);
+
+/**
+ * Find an existing LPM object and return a pointer to it.
+ *
+ * @param name
+ *   Name of the lpm object as passed to rte_lpm_create()
+ * @return
+ *   Pointer to lpm object or NULL if object not found with rte_errno
+ *   set appropriately. Possible rte_errno values include:
+ *    - ENOENT - required entry not available to return.
+ */
+struct rte_lpm *
+rte_lpm_find_existing(const char *name);
+struct rte_lpm_v20 *
+rte_lpm_find_existing_v20(const char *name);
+struct rte_lpm *
+rte_lpm_find_existing_v1604(const char *name);
+
+/**
+ * Free an LPM object.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @return
+ *   None
+ */
+void
+rte_lpm_free(struct rte_lpm *lpm);
+void
+rte_lpm_free_v20(struct rte_lpm_v20 *lpm);
+void
+rte_lpm_free_v1604(struct rte_lpm *lpm);
+
+/**
+ * Add a rule to the LPM table.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @param ip
+ *   IP of the rule to be added to the LPM table
+ * @param depth
+ *   Depth of the rule to be added to the LPM table
+ * @param next_hop
+ *   Next hop of the rule to be added to the LPM table
+ * @return
+ *   0 on success, negative value otherwise
+ */
+int
+rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint32_t next_hop);
+int
+rte_lpm_add_v20(struct rte_lpm_v20 *lpm, uint32_t ip, uint8_t depth,
+		uint8_t next_hop);
+int
+rte_lpm_add_v1604(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,
+		uint32_t next_hop);
+
+/**
+ * Check if a rule is present in the LPM table,
+ * and provide its next hop if it is.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @param ip
+ *   IP of the rule to be searched
+ * @param depth
+ *   Depth of the rule to searched
+ * @param next_hop
+ *   Next hop of the rule (valid only if it is found)
+ * @return
+ *   1 if the rule exists, 0 if it does not, a negative value on failure
+ */
+int
+rte_lpm_is_rule_present(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,
+uint32_t *next_hop);
+int
+rte_lpm_is_rule_present_v20(struct rte_lpm_v20 *lpm, uint32_t ip, uint8_t depth,
+uint8_t *next_hop);
+int
+rte_lpm_is_rule_present_v1604(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,
+uint32_t *next_hop);
+
+/**
+ * Delete a rule from the LPM table.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @param ip
+ *   IP of the rule to be deleted from the LPM table
+ * @param depth
+ *   Depth of the rule to be deleted from the LPM table
+ * @return
+ *   0 on success, negative value otherwise
+ */
+int
+rte_lpm_delete(struct rte_lpm *lpm, uint32_t ip, uint8_t depth);
+int
+rte_lpm_delete_v20(struct rte_lpm_v20 *lpm, uint32_t ip, uint8_t depth);
+int
+rte_lpm_delete_v1604(struct rte_lpm *lpm, uint32_t ip, uint8_t depth);
+
+/**
+ * Delete all rules from the LPM table.
+ *
+ * @param lpm
+ *   LPM object handle
+ */
+void
+rte_lpm_delete_all(struct rte_lpm *lpm);
+void
+rte_lpm_delete_all_v20(struct rte_lpm_v20 *lpm);
+void
+rte_lpm_delete_all_v1604(struct rte_lpm *lpm);
+
+/**
+ * Lookup an IP into the LPM table.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @param ip
+ *   IP to be looked up in the LPM table
+ * @param next_hop
+ *   Next hop of the most specific rule found for IP (valid on lookup hit only)
+ * @return
+ *   -EINVAL for incorrect arguments, -ENOENT on lookup miss, 0 on lookup hit
+ */
+static inline int
+rte_lpm_lookup(struct rte_lpm *lpm, uint32_t ip, uint32_t *next_hop)
+{
+	unsigned tbl24_index = (ip >> 8);
+	uint32_t tbl_entry;
+	const uint32_t *ptbl;
+
+	/* DEBUG: Check user input arguments. */
+	RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (next_hop == NULL)), -EINVAL);
+
+	/* Copy tbl24 entry */
+	ptbl = (const uint32_t *)(&lpm->tbl24[tbl24_index]);
+	tbl_entry = *ptbl;
+
+	/* Copy tbl8 entry (only if needed) */
+	if (unlikely((tbl_entry & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+
+		unsigned tbl8_index = (uint8_t)ip +
+				(((uint32_t)tbl_entry & 0x00FFFFFF) *
+						RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
+
+		ptbl = (const uint32_t *)&lpm->tbl8[tbl8_index];
+		tbl_entry = *ptbl;
+	}
+
+	*next_hop = ((uint32_t)tbl_entry & 0x00FFFFFF);
+	return (tbl_entry & RTE_LPM_LOOKUP_SUCCESS) ? 0 : -ENOENT;
+}
+
+/**
+ * Lookup multiple IP addresses in an LPM table. This may be implemented as a
+ * macro, so the address of the function should not be used.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @param ips
+ *   Array of IPs to be looked up in the LPM table
+ * @param next_hops
+ *   Next hop of the most specific rule found for IP (valid on lookup hit only).
+ *   This is an array of two byte values. The most significant byte in each
+ *   value says whether the lookup was successful (bitmask
+ *   RTE_LPM_LOOKUP_SUCCESS is set). The least significant byte is the
+ *   actual next hop.
+ * @param n
+ *   Number of elements in ips (and next_hops) array to lookup. This should be a
+ *   compile time constant, and divisible by 8 for best performance.
+ *  @return
+ *   -EINVAL for incorrect arguments, otherwise 0
+ */
+#define rte_lpm_lookup_bulk(lpm, ips, next_hops, n) \
+		rte_lpm_lookup_bulk_func(lpm, ips, next_hops, n)
+
+static inline int
+rte_lpm_lookup_bulk_func(const struct rte_lpm *lpm, const uint32_t *ips,
+		uint32_t *next_hops, const unsigned n)
+{
+	unsigned i;
+	unsigned tbl24_indexes[n];
+	const uint32_t *ptbl;
+
+	/* DEBUG: Check user input arguments. */
+	RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (ips == NULL) ||
+			(next_hops == NULL)), -EINVAL);
+
+	for (i = 0; i < n; i++) {
+		tbl24_indexes[i] = ips[i] >> 8;
+	}
+
+	for (i = 0; i < n; i++) {
+		/* Simply copy tbl24 entry to output */
+		ptbl = (const uint32_t *)&lpm->tbl24[tbl24_indexes[i]];
+		next_hops[i] = *ptbl;
+
+		/* Overwrite output with tbl8 entry if needed */
+		if (unlikely((next_hops[i] & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+				RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+
+			unsigned tbl8_index = (uint8_t)ips[i] +
+					(((uint32_t)next_hops[i] & 0x00FFFFFF) *
+					 RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
+
+			ptbl = (const uint32_t *)&lpm->tbl8[tbl8_index];
+			next_hops[i] = *ptbl;
+		}
+	}
+	return 0;
+}
+
+/* Mask four results. */
+#define	 RTE_LPM_MASKX4_RES	UINT64_C(0x00ffffff00ffffff)
+
+/**
+ * Lookup four IP addresses in an LPM table.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @param ip
+ *   Four IPs to be looked up in the LPM table
+ * @param hop
+ *   Next hop of the most specific rule found for IP (valid on lookup hit only).
+ *   This is an 4 elements array of two byte values.
+ *   If the lookup was succesfull for the given IP, then least significant byte
+ *   of the corresponding element is the  actual next hop and the most
+ *   significant byte is zero.
+ *   If the lookup for the given IP failed, then corresponding element would
+ *   contain default value, see description of then next parameter.
+ * @param defv
+ *   Default value to populate into corresponding element of hop[] array,
+ *   if lookup would fail.
+ */
+static inline void
+rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4],
+	uint32_t defv);
+
+#if defined(RTE_ARCH_ARM) || defined(RTE_ARCH_ARM64)
+#include "rte_lpm_neon.h"
+#else
+#include "rte_lpm_sse.h"
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_LPM_H_ */
diff --git a/app/test/v16.04/rte_lpm_neon.h b/app/test/v16.04/rte_lpm_neon.h
new file mode 100644
index 000000000..936ec7af3
--- /dev/null
+++ b/app/test/v16.04/rte_lpm_neon.h
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef _RTE_LPM_NEON_H_
+#define _RTE_LPM_NEON_H_
+
+#include <rte_branch_prediction.h>
+#include <rte_byteorder.h>
+#include <rte_common.h>
+#include <rte_vect.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline void
+rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4],
+	uint32_t defv)
+{
+	uint32x4_t i24;
+	rte_xmm_t i8;
+	uint32_t tbl[4];
+	uint64_t idx, pt, pt2;
+	const uint32_t *ptbl;
+
+	const uint32_t mask = UINT8_MAX;
+	const int32x4_t mask8 = vdupq_n_s32(mask);
+
+	/*
+	 * RTE_LPM_VALID_EXT_ENTRY_BITMASK for 2 LPM entries
+	 * as one 64-bit value (0x0300000003000000).
+	 */
+	const uint64_t mask_xv =
+		((uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK |
+		(uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 32);
+
+	/*
+	 * RTE_LPM_LOOKUP_SUCCESS for 2 LPM entries
+	 * as one 64-bit value (0x0100000001000000).
+	 */
+	const uint64_t mask_v =
+		((uint64_t)RTE_LPM_LOOKUP_SUCCESS |
+		(uint64_t)RTE_LPM_LOOKUP_SUCCESS << 32);
+
+	/* get 4 indexes for tbl24[]. */
+	i24 = vshrq_n_u32((uint32x4_t)ip, CHAR_BIT);
+
+	/* extract values from tbl24[] */
+	idx = vgetq_lane_u64((uint64x2_t)i24, 0);
+
+	ptbl = (const uint32_t *)&lpm->tbl24[(uint32_t)idx];
+	tbl[0] = *ptbl;
+	ptbl = (const uint32_t *)&lpm->tbl24[idx >> 32];
+	tbl[1] = *ptbl;
+
+	idx = vgetq_lane_u64((uint64x2_t)i24, 1);
+
+	ptbl = (const uint32_t *)&lpm->tbl24[(uint32_t)idx];
+	tbl[2] = *ptbl;
+	ptbl = (const uint32_t *)&lpm->tbl24[idx >> 32];
+	tbl[3] = *ptbl;
+
+	/* get 4 indexes for tbl8[]. */
+	i8.x = vandq_s32(ip, mask8);
+
+	pt = (uint64_t)tbl[0] |
+		(uint64_t)tbl[1] << 32;
+	pt2 = (uint64_t)tbl[2] |
+		(uint64_t)tbl[3] << 32;
+
+	/* search successfully finished for all 4 IP addresses. */
+	if (likely((pt & mask_xv) == mask_v) &&
+			likely((pt2 & mask_xv) == mask_v)) {
+		*(uint64_t *)hop = pt & RTE_LPM_MASKX4_RES;
+		*(uint64_t *)(hop + 2) = pt2 & RTE_LPM_MASKX4_RES;
+		return;
+	}
+
+	if (unlikely((pt & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+		i8.u32[0] = i8.u32[0] +
+			(uint8_t)tbl[0] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[0]];
+		tbl[0] = *ptbl;
+	}
+	if (unlikely((pt >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+		i8.u32[1] = i8.u32[1] +
+			(uint8_t)tbl[1] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[1]];
+		tbl[1] = *ptbl;
+	}
+	if (unlikely((pt2 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+		i8.u32[2] = i8.u32[2] +
+			(uint8_t)tbl[2] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[2]];
+		tbl[2] = *ptbl;
+	}
+	if (unlikely((pt2 >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+		i8.u32[3] = i8.u32[3] +
+			(uint8_t)tbl[3] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[3]];
+		tbl[3] = *ptbl;
+	}
+
+	hop[0] = (tbl[0] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[0] & 0x00FFFFFF : defv;
+	hop[1] = (tbl[1] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[1] & 0x00FFFFFF : defv;
+	hop[2] = (tbl[2] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[2] & 0x00FFFFFF : defv;
+	hop[3] = (tbl[3] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[3] & 0x00FFFFFF : defv;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_LPM_NEON_H_ */
diff --git a/app/test/v16.04/rte_lpm_sse.h b/app/test/v16.04/rte_lpm_sse.h
new file mode 100644
index 000000000..edfa36be1
--- /dev/null
+++ b/app/test/v16.04/rte_lpm_sse.h
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef _RTE_LPM_SSE_H_
+#define _RTE_LPM_SSE_H_
+
+#include <rte_branch_prediction.h>
+#include <rte_byteorder.h>
+#include <rte_common.h>
+#include <rte_vect.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline void
+rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4],
+	uint32_t defv)
+{
+	__m128i i24;
+	rte_xmm_t i8;
+	uint32_t tbl[4];
+	uint64_t idx, pt, pt2;
+	const uint32_t *ptbl;
+
+	const __m128i mask8 =
+		_mm_set_epi32(UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX);
+
+	/*
+	 * RTE_LPM_VALID_EXT_ENTRY_BITMASK for 2 LPM entries
+	 * as one 64-bit value (0x0300000003000000).
+	 */
+	const uint64_t mask_xv =
+		((uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK |
+		(uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 32);
+
+	/*
+	 * RTE_LPM_LOOKUP_SUCCESS for 2 LPM entries
+	 * as one 64-bit value (0x0100000001000000).
+	 */
+	const uint64_t mask_v =
+		((uint64_t)RTE_LPM_LOOKUP_SUCCESS |
+		(uint64_t)RTE_LPM_LOOKUP_SUCCESS << 32);
+
+	/* get 4 indexes for tbl24[]. */
+	i24 = _mm_srli_epi32(ip, CHAR_BIT);
+
+	/* extract values from tbl24[] */
+	idx = _mm_cvtsi128_si64(i24);
+	i24 = _mm_srli_si128(i24, sizeof(uint64_t));
+
+	ptbl = (const uint32_t *)&lpm->tbl24[(uint32_t)idx];
+	tbl[0] = *ptbl;
+	ptbl = (const uint32_t *)&lpm->tbl24[idx >> 32];
+	tbl[1] = *ptbl;
+
+	idx = _mm_cvtsi128_si64(i24);
+
+	ptbl = (const uint32_t *)&lpm->tbl24[(uint32_t)idx];
+	tbl[2] = *ptbl;
+	ptbl = (const uint32_t *)&lpm->tbl24[idx >> 32];
+	tbl[3] = *ptbl;
+
+	/* get 4 indexes for tbl8[]. */
+	i8.x = _mm_and_si128(ip, mask8);
+
+	pt = (uint64_t)tbl[0] |
+		(uint64_t)tbl[1] << 32;
+	pt2 = (uint64_t)tbl[2] |
+		(uint64_t)tbl[3] << 32;
+
+	/* search successfully finished for all 4 IP addresses. */
+	if (likely((pt & mask_xv) == mask_v) &&
+			likely((pt2 & mask_xv) == mask_v)) {
+		*(uint64_t *)hop = pt & RTE_LPM_MASKX4_RES;
+		*(uint64_t *)(hop + 2) = pt2 & RTE_LPM_MASKX4_RES;
+		return;
+	}
+
+	if (unlikely((pt & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+		i8.u32[0] = i8.u32[0] +
+			(uint8_t)tbl[0] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[0]];
+		tbl[0] = *ptbl;
+	}
+	if (unlikely((pt >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+		i8.u32[1] = i8.u32[1] +
+			(uint8_t)tbl[1] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[1]];
+		tbl[1] = *ptbl;
+	}
+	if (unlikely((pt2 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+		i8.u32[2] = i8.u32[2] +
+			(uint8_t)tbl[2] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[2]];
+		tbl[2] = *ptbl;
+	}
+	if (unlikely((pt2 >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+		i8.u32[3] = i8.u32[3] +
+			(uint8_t)tbl[3] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[3]];
+		tbl[3] = *ptbl;
+	}
+
+	hop[0] = (tbl[0] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[0] & 0x00FFFFFF : defv;
+	hop[1] = (tbl[1] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[1] & 0x00FFFFFF : defv;
+	hop[2] = (tbl[2] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[2] & 0x00FFFFFF : defv;
+	hop[3] = (tbl[3] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[3] & 0x00FFFFFF : defv;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_LPM_SSE_H_ */
diff --git a/app/test/v16.04/test_lpm.c b/app/test/v16.04/test_lpm.c
new file mode 100644
index 000000000..2aab8d0cc
--- /dev/null
+++ b/app/test/v16.04/test_lpm.c
@@ -0,0 +1,1405 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2019 Intel Corporation
+ *
+ * LPM Autotests from DPDK v16.04 for abi compability testing.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_random.h>
+#include <rte_branch_prediction.h>
+#include <rte_ip.h>
+#include <time.h>
+
+#include "../test_lpm_routes.h"
+#include "../test.h"
+#include "../test_xmmt_ops.h"
+
+/* backported header from DPDK v16.04 */
+#include "rte_lpm.h"
+/* remapping of DPDK v16.04 symbols */
+#include "dcompat.h"
+
+#define TEST_LPM_ASSERT(cond) do {                                            \
+	if (!(cond)) {                                                        \
+		printf("Error at line %d: \n", __LINE__);                     \
+		return -1;                                                    \
+	}                                                                     \
+} while (0)
+
+typedef int32_t (*rte_lpm_test)(void);
+
+static int32_t test0(void);
+static int32_t test1(void);
+static int32_t test2(void);
+static int32_t test3(void);
+static int32_t test4(void);
+static int32_t test5(void);
+static int32_t test6(void);
+static int32_t test7(void);
+static int32_t test8(void);
+static int32_t test9(void);
+static int32_t test10(void);
+static int32_t test11(void);
+static int32_t test12(void);
+static int32_t test13(void);
+static int32_t test14(void);
+static int32_t test15(void);
+static int32_t test16(void);
+static int32_t test17(void);
+static int32_t perf_test(void);
+
+static rte_lpm_test tests[] = {
+/* Test Cases */
+	test0,
+	test1,
+	test2,
+	test3,
+	test4,
+	test5,
+	test6,
+	test7,
+	test8,
+	test9,
+	test10,
+	test11,
+	test12,
+	test13,
+	test14,
+	test15,
+	test16,
+	test17,
+	perf_test,
+};
+
+#define NUM_LPM_TESTS (sizeof(tests)/sizeof(tests[0]))
+#define MAX_DEPTH 32
+#define MAX_RULES 256
+#define NUMBER_TBL8S 256
+#define PASS 0
+
+/*
+ * Check that rte_lpm_create fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test0(void)
+{
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+
+	/* rte_lpm_create: lpm name == NULL */
+	lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm == NULL);
+
+	/* rte_lpm_create: max_rules = 0 */
+	/* Note: __func__ inserts the function name, in this case "test0". */
+	config.max_rules = 0;
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm == NULL);
+
+	/* socket_id < -1 is invalid */
+	config.max_rules = MAX_RULES;
+	lpm = rte_lpm_create(__func__, -2, &config);
+	TEST_LPM_ASSERT(lpm == NULL);
+
+	return PASS;
+}
+
+/*
+ * Create lpm table then delete lpm table 100 times
+ * Use a slightly different rules size each time
+ * */
+int32_t
+test1(void)
+{
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	int32_t i;
+
+	/* rte_lpm_free: Free NULL */
+	for (i = 0; i < 100; i++) {
+		config.max_rules = MAX_RULES - i;
+		lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+		TEST_LPM_ASSERT(lpm != NULL);
+
+		rte_lpm_free(lpm);
+	}
+
+	/* Can not test free so return success */
+	return PASS;
+}
+
+/*
+ * Call rte_lpm_free for NULL pointer user input. Note: free has no return and
+ * therefore it is impossible to check for failure but this test is added to
+ * increase function coverage metrics and to validate that freeing null does
+ * not crash.
+ */
+int32_t
+test2(void)
+{
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	rte_lpm_free(lpm);
+	rte_lpm_free(NULL);
+	return PASS;
+}
+
+/*
+ * Check that rte_lpm_add fails gracefully for incorrect user input arguments
+ */
+int32_t
+test3(void)
+{
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	uint32_t ip = IPv4(0, 0, 0, 0), next_hop = 100;
+	uint8_t depth = 24;
+	int32_t status = 0;
+
+	/* rte_lpm_add: lpm == NULL */
+	status = rte_lpm_add(NULL, ip, depth, next_hop);
+	TEST_LPM_ASSERT(status < 0);
+
+	/*Create vaild lpm to use in rest of test. */
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	/* rte_lpm_add: depth < 1 */
+	status = rte_lpm_add(lpm, ip, 0, next_hop);
+	TEST_LPM_ASSERT(status < 0);
+
+	/* rte_lpm_add: depth > MAX_DEPTH */
+	status = rte_lpm_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
+	TEST_LPM_ASSERT(status < 0);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Check that rte_lpm_delete fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test4(void)
+{
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	uint32_t ip = IPv4(0, 0, 0, 0);
+	uint8_t depth = 24;
+	int32_t status = 0;
+
+	/* rte_lpm_delete: lpm == NULL */
+	status = rte_lpm_delete(NULL, ip, depth);
+	TEST_LPM_ASSERT(status < 0);
+
+	/*Create vaild lpm to use in rest of test. */
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	/* rte_lpm_delete: depth < 1 */
+	status = rte_lpm_delete(lpm, ip, 0);
+	TEST_LPM_ASSERT(status < 0);
+
+	/* rte_lpm_delete: depth > MAX_DEPTH */
+	status = rte_lpm_delete(lpm, ip, (MAX_DEPTH + 1));
+	TEST_LPM_ASSERT(status < 0);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Check that rte_lpm_lookup fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test5(void)
+{
+#if defined(RTE_LIBRTE_LPM_DEBUG)
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	uint32_t ip = IPv4(0, 0, 0, 0), next_hop_return = 0;
+	int32_t status = 0;
+
+	/* rte_lpm_lookup: lpm == NULL */
+	status = rte_lpm_lookup(NULL, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status < 0);
+
+	/*Create vaild lpm to use in rest of test. */
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	/* rte_lpm_lookup: depth < 1 */
+	status = rte_lpm_lookup(lpm, ip, NULL);
+	TEST_LPM_ASSERT(status < 0);
+
+	rte_lpm_free(lpm);
+#endif
+	return PASS;
+}
+
+
+
+/*
+ * Call add, lookup and delete for a single rule with depth <= 24
+ */
+int32_t
+test6(void)
+{
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	uint32_t ip = IPv4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
+	uint8_t depth = 24;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Call add, lookup and delete for a single rule with depth > 24
+ */
+
+int32_t
+test7(void)
+{
+	xmm_t ipx4;
+	uint32_t hop[4];
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	uint32_t ip = IPv4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
+	uint8_t depth = 32;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	ipx4 = vect_set_epi32(ip, ip + 0x100, ip - 0x100, ip);
+	rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
+	TEST_LPM_ASSERT(hop[0] == next_hop_add);
+	TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
+	TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
+	TEST_LPM_ASSERT(hop[3] == next_hop_add);
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Use rte_lpm_add to add rules which effect only the second half of the lpm
+ * table. Use all possible depths ranging from 1..32. Set the next hop = to the
+ * depth. Check lookup hit for on every add and check for lookup miss on the
+ * first half of the lpm table after each add. Finally delete all rules going
+ * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
+ * delete. The lookup should return the next_hop_add value related to the
+ * previous depth value (i.e. depth -1).
+ */
+int32_t
+test8(void)
+{
+	xmm_t ipx4;
+	uint32_t hop[4];
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	uint32_t ip1 = IPv4(127, 255, 255, 255), ip2 = IPv4(128, 0, 0, 0);
+	uint32_t next_hop_add, next_hop_return;
+	uint8_t depth;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	/* Loop with rte_lpm_add. */
+	for (depth = 1; depth <= 32; depth++) {
+		/* Let the next_hop_add value = depth. Just for change. */
+		next_hop_add = depth;
+
+		status = rte_lpm_add(lpm, ip2, depth, next_hop_add);
+		TEST_LPM_ASSERT(status == 0);
+
+		/* Check IP in first half of tbl24 which should be empty. */
+		status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
+		TEST_LPM_ASSERT(status == -ENOENT);
+
+		status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
+		TEST_LPM_ASSERT((status == 0) &&
+			(next_hop_return == next_hop_add));
+
+		ipx4 = vect_set_epi32(ip2, ip1, ip2, ip1);
+		rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
+		TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
+		TEST_LPM_ASSERT(hop[1] == next_hop_add);
+		TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
+		TEST_LPM_ASSERT(hop[3] == next_hop_add);
+	}
+
+	/* Loop with rte_lpm_delete. */
+	for (depth = 32; depth >= 1; depth--) {
+		next_hop_add = (uint8_t) (depth - 1);
+
+		status = rte_lpm_delete(lpm, ip2, depth);
+		TEST_LPM_ASSERT(status == 0);
+
+		status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
+
+		if (depth != 1) {
+			TEST_LPM_ASSERT((status == 0) &&
+				(next_hop_return == next_hop_add));
+		} else {
+			TEST_LPM_ASSERT(status == -ENOENT);
+		}
+
+		status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
+		TEST_LPM_ASSERT(status == -ENOENT);
+
+		ipx4 = vect_set_epi32(ip1, ip1, ip2, ip2);
+		rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
+		if (depth != 1) {
+			TEST_LPM_ASSERT(hop[0] == next_hop_add);
+			TEST_LPM_ASSERT(hop[1] == next_hop_add);
+		} else {
+			TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
+			TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
+		}
+		TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
+		TEST_LPM_ASSERT(hop[3] == UINT32_MAX);
+	}
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * - Add & lookup to hit invalid TBL24 entry
+ * - Add & lookup to hit valid TBL24 entry not extended
+ * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
+ * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
+ *
+ */
+int32_t
+test9(void)
+{
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	uint32_t ip, ip_1, ip_2;
+	uint8_t depth, depth_1, depth_2;
+	uint32_t next_hop_add, next_hop_add_1, next_hop_add_2, next_hop_return;
+	int32_t status = 0;
+
+	/* Add & lookup to hit invalid TBL24 entry */
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+	next_hop_add = 100;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Add & lookup to hit valid TBL24 entry not extended */
+	ip = IPv4(128, 0, 0, 0);
+	depth = 23;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	depth = 24;
+	next_hop_add = 101;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	depth = 24;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	depth = 23;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
+	 * entry */
+	ip = IPv4(128, 0, 0, 0);
+	depth = 32;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	ip = IPv4(128, 0, 0, 5);
+	depth = 32;
+	next_hop_add = 101;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 32;
+	next_hop_add = 100;
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Add & lookup to hit valid extended TBL24 entry with valid TBL8
+	 * entry */
+	ip_1 = IPv4(128, 0, 0, 0);
+	depth_1 = 25;
+	next_hop_add_1 = 101;
+
+	ip_2 = IPv4(128, 0, 0, 5);
+	depth_2 = 32;
+	next_hop_add_2 = 102;
+
+	next_hop_return = 0;
+
+	status = rte_lpm_add(lpm, ip_1, depth_1, next_hop_add_1);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
+
+	status = rte_lpm_add(lpm, ip_2, depth_2, next_hop_add_2);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
+
+	status = rte_lpm_delete(lpm, ip_2, depth_2);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
+
+	status = rte_lpm_delete(lpm, ip_1, depth_1);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+
+/*
+ * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
+ *   lookup)
+ * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
+ * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
+ *   delete & lookup)
+ * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
+ * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
+ * - Delete a rule that is not present in the TBL24 & lookup
+ * - Delete a rule that is not present in the TBL8 & lookup
+ *
+ */
+int32_t
+test10(void)
+{
+
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	uint32_t ip, next_hop_add, next_hop_return;
+	uint8_t depth;
+	int32_t status = 0;
+
+	/* Add rule that covers a TBL24 range previously invalid & lookup
+	 * (& delete & lookup) */
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 16;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 25;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Add rule that extends a TBL24 valid entry & lookup for both rules
+	 * (& delete & lookup) */
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	ip = IPv4(128, 0, 0, 10);
+	depth = 32;
+	next_hop_add = 101;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	ip = IPv4(128, 0, 0, 0);
+	next_hop_add = 100;
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	ip = IPv4(128, 0, 0, 10);
+	depth = 32;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Add rule that updates the next hop in TBL24 & lookup
+	 * (& delete & lookup) */
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	next_hop_add = 101;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Add rule that updates the next hop in TBL8 & lookup
+	 * (& delete & lookup) */
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 32;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	next_hop_add = 101;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Delete a rule that is not present in the TBL24 & lookup */
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status < 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Delete a rule that is not present in the TBL8 & lookup */
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 32;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status < 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Add two rules, lookup to hit the more specific one, lookup to hit the less
+ * specific one delete the less specific rule and lookup previous values again;
+ * add a more specific rule than the existing rule, lookup again
+ *
+ * */
+int32_t
+test11(void)
+{
+
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	uint32_t ip, next_hop_add, next_hop_return;
+	uint8_t depth;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	ip = IPv4(128, 0, 0, 10);
+	depth = 32;
+	next_hop_add = 101;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	ip = IPv4(128, 0, 0, 0);
+	next_hop_add = 100;
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	ip = IPv4(128, 0, 0, 10);
+	depth = 32;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
+ * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension
+ * and contraction.
+ *
+ * */
+
+int32_t
+test12(void)
+{
+	xmm_t ipx4;
+	uint32_t hop[4];
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	uint32_t ip, i, next_hop_add, next_hop_return;
+	uint8_t depth;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 32;
+	next_hop_add = 100;
+
+	for (i = 0; i < 1000; i++) {
+		status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+		TEST_LPM_ASSERT(status == 0);
+
+		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+		TEST_LPM_ASSERT((status == 0) &&
+				(next_hop_return == next_hop_add));
+
+		ipx4 = vect_set_epi32(ip, ip + 1, ip, ip - 1);
+		rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
+		TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
+		TEST_LPM_ASSERT(hop[1] == next_hop_add);
+		TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
+		TEST_LPM_ASSERT(hop[3] == next_hop_add);
+
+		status = rte_lpm_delete(lpm, ip, depth);
+		TEST_LPM_ASSERT(status == 0);
+
+		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+		TEST_LPM_ASSERT(status == -ENOENT);
+	}
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Add a rule to tbl24, lookup (hit), then add a rule that will extend this
+ * tbl24 entry, lookup (hit). delete the rule that caused the tbl24 extension,
+ * lookup (miss) and repeat for loop of 1000 times. This will check tbl8
+ * extension and contraction.
+ *
+ * */
+
+int32_t
+test13(void)
+{
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	uint32_t ip, i, next_hop_add_1, next_hop_add_2, next_hop_return;
+	uint8_t depth;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+	next_hop_add_1 = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add_1);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
+
+	depth = 32;
+	next_hop_add_2 = 101;
+
+	for (i = 0; i < 1000; i++) {
+		status = rte_lpm_add(lpm, ip, depth, next_hop_add_2);
+		TEST_LPM_ASSERT(status == 0);
+
+		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+		TEST_LPM_ASSERT((status == 0) &&
+				(next_hop_return == next_hop_add_2));
+
+		status = rte_lpm_delete(lpm, ip, depth);
+		TEST_LPM_ASSERT(status == 0);
+
+		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+		TEST_LPM_ASSERT((status == 0) &&
+				(next_hop_return == next_hop_add_1));
+	}
+
+	depth = 24;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Fore TBL8 extension exhaustion. Add 256 rules that require a tbl8 extension.
+ * No more tbl8 extensions will be allowed. Now add one more rule that required
+ * a tbl8 extension and get fail.
+ * */
+int32_t
+test14(void)
+{
+
+	/* We only use depth = 32 in the loop below so we must make sure
+	 * that we have enough storage for all rules at that depth*/
+
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = 256 * 32;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	uint32_t ip, next_hop_add, next_hop_return;
+	uint8_t depth;
+	int32_t status = 0;
+
+	/* Add enough space for 256 rules for every depth */
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	depth = 32;
+	next_hop_add = 100;
+	ip = IPv4(0, 0, 0, 0);
+
+	/* Add 256 rules that require a tbl8 extension */
+	for (; ip <= IPv4(0, 0, 255, 0); ip += 256) {
+		status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+		TEST_LPM_ASSERT(status == 0);
+
+		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+		TEST_LPM_ASSERT((status == 0) &&
+				(next_hop_return == next_hop_add));
+	}
+
+	/* All tbl8 extensions have been used above. Try to add one more and
+	 * we get a fail */
+	ip = IPv4(1, 0, 0, 0);
+	depth = 32;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status < 0);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Sequence of operations for find existing lpm table
+ *
+ *  - create table
+ *  - find existing table: hit
+ *  - find non-existing table: miss
+ *
+ */
+int32_t
+test15(void)
+{
+	struct rte_lpm *lpm = NULL, *result = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = 256 * 32;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+
+	/* Create lpm  */
+	lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	/* Try to find existing lpm */
+	result = rte_lpm_find_existing("lpm_find_existing");
+	TEST_LPM_ASSERT(result == lpm);
+
+	/* Try to find non-existing lpm */
+	result = rte_lpm_find_existing("lpm_find_non_existing");
+	TEST_LPM_ASSERT(result == NULL);
+
+	/* Cleanup. */
+	rte_lpm_delete_all(lpm);
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * test failure condition of overloading the tbl8 so no more will fit
+ * Check we get an error return value in that case
+ */
+int32_t
+test16(void)
+{
+	uint32_t ip;
+	struct rte_lpm_config config;
+
+	config.max_rules = 256 * 32;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+
+	/* ip loops through all possibilities for top 24 bits of address */
+	for (ip = 0; ip < 0xFFFFFF; ip++) {
+		/* add an entry within a different tbl8 each time, since
+		 * depth >24 and the top 24 bits are different */
+		if (rte_lpm_add(lpm, (ip << 8) + 0xF0, 30, 0) < 0)
+			break;
+	}
+
+	if (ip != NUMBER_TBL8S) {
+		printf("Error, unexpected failure with filling tbl8 groups\n");
+		printf("Failed after %u additions, expected after %u\n",
+				(unsigned)ip, (unsigned)NUMBER_TBL8S);
+	}
+
+	rte_lpm_free(lpm);
+	return 0;
+}
+
+/*
+ * Test for overwriting of tbl8:
+ *  - add rule /32 and lookup
+ *  - add new rule /24 and lookup
+ *	- add third rule /25 and lookup
+ *	- lookup /32 and /24 rule to ensure the table has not been overwritten.
+ */
+int32_t
+test17(void)
+{
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = MAX_RULES;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	const uint32_t ip_10_32 = IPv4(10, 10, 10, 2);
+	const uint32_t ip_10_24 = IPv4(10, 10, 10, 0);
+	const uint32_t ip_20_25 = IPv4(10, 10, 20, 2);
+	const uint8_t d_ip_10_32 = 32,
+			d_ip_10_24 = 24,
+			d_ip_20_25 = 25;
+	const uint32_t next_hop_ip_10_32 = 100,
+			next_hop_ip_10_24 = 105,
+			next_hop_ip_20_25 = 111;
+	uint32_t next_hop_return = 0;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	status = rte_lpm_add(lpm, ip_10_32, d_ip_10_32, next_hop_ip_10_32);
+	if (status < 0)
+		return -1;
+
+	status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
+	uint32_t test_hop_10_32 = next_hop_return;
+	TEST_LPM_ASSERT(status == 0);
+	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
+
+	status = rte_lpm_add(lpm, ip_10_24, d_ip_10_24, next_hop_ip_10_24);
+	if (status < 0)
+		return -1;
+
+	status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
+	uint32_t test_hop_10_24 = next_hop_return;
+	TEST_LPM_ASSERT(status == 0);
+	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
+
+	status = rte_lpm_add(lpm, ip_20_25, d_ip_20_25, next_hop_ip_20_25);
+	if (status < 0)
+		return -1;
+
+	status = rte_lpm_lookup(lpm, ip_20_25, &next_hop_return);
+	uint32_t test_hop_20_25 = next_hop_return;
+	TEST_LPM_ASSERT(status == 0);
+	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
+
+	if (test_hop_10_32 == test_hop_10_24) {
+		printf("Next hop return equal\n");
+		return -1;
+	}
+
+	if (test_hop_10_24 == test_hop_20_25) {
+		printf("Next hop return equal\n");
+		return -1;
+	}
+
+	status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
+	TEST_LPM_ASSERT(status == 0);
+	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
+
+	status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
+	TEST_LPM_ASSERT(status == 0);
+	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Lookup performance test
+ */
+
+#define ITERATIONS (1 << 10)
+#define BATCH_SIZE (1 << 12)
+#define BULK_SIZE 32
+
+int32_t
+perf_test(void)
+{
+	struct rte_lpm *lpm = NULL;
+	struct rte_lpm_config config;
+
+	config.max_rules = 1000000;
+	config.number_tbl8s = NUMBER_TBL8S;
+	config.flags = 0;
+	uint64_t begin, total_time, lpm_used_entries = 0;
+	unsigned i, j;
+	uint32_t next_hop_add = 0xAA, next_hop_return = 0;
+	int status = 0;
+	uint64_t cache_line_counter = 0;
+	int64_t count = 0;
+
+	rte_srand(rte_rdtsc());
+
+	/* (re) generate the routing table */
+	generate_large_route_rule_table();
+
+	printf("No. routes = %u\n", (unsigned) NUM_ROUTE_ENTRIES);
+
+	print_route_distribution(large_route_table,
+				(uint32_t) NUM_ROUTE_ENTRIES);
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	/* Measue add. */
+	begin = rte_rdtsc();
+
+	for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
+		if (rte_lpm_add(lpm, large_route_table[i].ip,
+				large_route_table[i].depth, next_hop_add) == 0)
+			status++;
+	}
+	/* End Timer. */
+	total_time = rte_rdtsc() - begin;
+
+	printf("Unique added entries = %d\n", status);
+	/* Obtain add statistics. */
+	for (i = 0; i < RTE_LPM_TBL24_NUM_ENTRIES; i++) {
+		if (lpm->tbl24[i].valid)
+			lpm_used_entries++;
+
+		if (i % 32 == 0) {
+			if ((uint64_t)count < lpm_used_entries) {
+				cache_line_counter++;
+				count = lpm_used_entries;
+			}
+		}
+	}
+
+	printf("Used table 24 entries = %u (%g%%)\n",
+			(unsigned) lpm_used_entries,
+			(lpm_used_entries * 100.0) / RTE_LPM_TBL24_NUM_ENTRIES);
+	printf("64 byte Cache entries used = %u (%u bytes)\n",
+			(unsigned) cache_line_counter, (unsigned) cache_line_counter * 64);
+
+	printf("Average LPM Add: %g cycles\n",
+			(double)total_time / NUM_ROUTE_ENTRIES);
+
+	/* Measure single Lookup */
+	total_time = 0;
+	count = 0;
+
+	for (i = 0; i < ITERATIONS; i++) {
+		static uint32_t ip_batch[BATCH_SIZE];
+
+		for (j = 0; j < BATCH_SIZE; j++)
+			ip_batch[j] = rte_rand();
+
+		/* Lookup per batch */
+		begin = rte_rdtsc();
+
+		for (j = 0; j < BATCH_SIZE; j++) {
+			if (rte_lpm_lookup(lpm, ip_batch[j], &next_hop_return) != 0)
+				count++;
+		}
+
+		total_time += rte_rdtsc() - begin;
+
+	}
+	printf("Average LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
+			(double)total_time / ((double)ITERATIONS * BATCH_SIZE),
+			(count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
+
+	/* Measure bulk Lookup */
+	total_time = 0;
+	count = 0;
+	for (i = 0; i < ITERATIONS; i++) {
+		static uint32_t ip_batch[BATCH_SIZE];
+		uint32_t next_hops[BULK_SIZE];
+
+		/* Create array of random IP addresses */
+		for (j = 0; j < BATCH_SIZE; j++)
+			ip_batch[j] = rte_rand();
+
+		/* Lookup per batch */
+		begin = rte_rdtsc();
+		for (j = 0; j < BATCH_SIZE; j += BULK_SIZE) {
+			unsigned k;
+			rte_lpm_lookup_bulk(lpm, &ip_batch[j], next_hops, BULK_SIZE);
+			for (k = 0; k < BULK_SIZE; k++)
+				if (unlikely(!(next_hops[k] & RTE_LPM_LOOKUP_SUCCESS)))
+					count++;
+		}
+
+		total_time += rte_rdtsc() - begin;
+	}
+	printf("BULK LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
+			(double)total_time / ((double)ITERATIONS * BATCH_SIZE),
+			(count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
+
+	/* Measure LookupX4 */
+	total_time = 0;
+	count = 0;
+	for (i = 0; i < ITERATIONS; i++) {
+		static uint32_t ip_batch[BATCH_SIZE];
+		uint32_t next_hops[4];
+
+		/* Create array of random IP addresses */
+		for (j = 0; j < BATCH_SIZE; j++)
+			ip_batch[j] = rte_rand();
+
+		/* Lookup per batch */
+		begin = rte_rdtsc();
+		for (j = 0; j < BATCH_SIZE; j += RTE_DIM(next_hops)) {
+			unsigned k;
+			xmm_t ipx4;
+
+			ipx4 = vect_loadu_sil128((xmm_t *)(ip_batch + j));
+			ipx4 = *(xmm_t *)(ip_batch + j);
+			rte_lpm_lookupx4(lpm, ipx4, next_hops, UINT32_MAX);
+			for (k = 0; k < RTE_DIM(next_hops); k++)
+				if (unlikely(next_hops[k] == UINT32_MAX))
+					count++;
+		}
+
+		total_time += rte_rdtsc() - begin;
+	}
+	printf("LPM LookupX4: %.1f cycles (fails = %.1f%%)\n",
+			(double)total_time / ((double)ITERATIONS * BATCH_SIZE),
+			(count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
+
+	/* Delete */
+	status = 0;
+	begin = rte_rdtsc();
+
+	for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
+		/* rte_lpm_delete(lpm, ip, depth) */
+		status += rte_lpm_delete(lpm, large_route_table[i].ip,
+				large_route_table[i].depth);
+	}
+
+	total_time += rte_rdtsc() - begin;
+
+	printf("Average LPM Delete: %g cycles\n",
+			(double)total_time / NUM_ROUTE_ENTRIES);
+
+	rte_lpm_delete_all(lpm);
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Do all unit and performance tests.
+ */
+
+static int
+test_lpm(void)
+{
+	unsigned i;
+	int status, global_status = 0;
+
+	for (i = 0; i < NUM_LPM_TESTS; i++) {
+		status = tests[i]();
+		if (status < 0) {
+			printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests[i]));
+			global_status = status;
+		}
+	}
+
+	return global_status;
+}
+
+REGISTER_TEST_COMMAND_VERSION(lpm_autotest, test_lpm, TEST_DPDK_ABI_VERSION_V1604);
diff --git a/app/test/v16.04/test_v1604.c b/app/test/v16.04/test_v1604.c
new file mode 100644
index 000000000..a5399bbfe
--- /dev/null
+++ b/app/test/v16.04/test_v1604.c
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <rte_ip.h>
+#include <rte_lpm.h>
+
+#include "../test.h"
+
+REGISTER_TEST_ABI_VERSION(v1604, TEST_DPDK_ABI_VERSION_V1604);
diff --git a/app/test/v2.0/dcompat.h b/app/test/v2.0/dcompat.h
new file mode 100644
index 000000000..108fcf8f6
--- /dev/null
+++ b/app/test/v2.0/dcompat.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2019 Intel Corporation
+ */
+
+#ifndef _DCOMPAT_H_
+#define _DCOMPAT_H_
+
+#define ABI_VERSION DPDK_2.0
+
+#define MAP_ABI_SYMBOL(name) \
+	MAP_ABI_SYMBOL_VERSION(name, ABI_VERSION)
+
+MAP_ABI_SYMBOL(rte_lpm_add);
+MAP_ABI_SYMBOL(rte_lpm_create);
+MAP_ABI_SYMBOL(rte_lpm_delete);
+MAP_ABI_SYMBOL(rte_lpm_delete_all);
+MAP_ABI_SYMBOL(rte_lpm_find_existing);
+MAP_ABI_SYMBOL(rte_lpm_free);
+MAP_ABI_SYMBOL(rte_lpm_is_rule_present);
+
+#undef MAP_ABI_SYMBOL
+
+#endif
diff --git a/app/test/v2.0/rte_lpm.h b/app/test/v2.0/rte_lpm.h
new file mode 100644
index 000000000..b1efd1c2d
--- /dev/null
+++ b/app/test/v2.0/rte_lpm.h
@@ -0,0 +1,443 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef _RTE_LPM_H_
+#define _RTE_LPM_H_
+
+/**
+ * @file
+ * RTE Longest Prefix Match (LPM)
+ */
+
+#include <errno.h>
+#include <sys/queue.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <rte_branch_prediction.h>
+#include <rte_memory.h>
+#include <rte_common.h>
+#include <rte_vect.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Max number of characters in LPM name. */
+#define RTE_LPM_NAMESIZE                32
+
+/** @deprecated Possible location to allocate memory. This was for last
+ * parameter of rte_lpm_create(), but is now redundant. The LPM table is always
+ * allocated in memory using librte_malloc which uses a memzone. */
+#define RTE_LPM_HEAP                    0
+
+/** @deprecated Possible location to allocate memory. This was for last
+ * parameter of rte_lpm_create(), but is now redundant. The LPM table is always
+ * allocated in memory using librte_malloc which uses a memzone. */
+#define RTE_LPM_MEMZONE                 1
+
+/** Maximum depth value possible for IPv4 LPM. */
+#define RTE_LPM_MAX_DEPTH               32
+
+/** @internal Total number of tbl24 entries. */
+#define RTE_LPM_TBL24_NUM_ENTRIES       (1 << 24)
+
+/** @internal Number of entries in a tbl8 group. */
+#define RTE_LPM_TBL8_GROUP_NUM_ENTRIES  256
+
+/** @internal Total number of tbl8 groups in the tbl8. */
+#define RTE_LPM_TBL8_NUM_GROUPS         256
+
+/** @internal Total number of tbl8 entries. */
+#define RTE_LPM_TBL8_NUM_ENTRIES        (RTE_LPM_TBL8_NUM_GROUPS * \
+					RTE_LPM_TBL8_GROUP_NUM_ENTRIES)
+
+/** @internal Macro to enable/disable run-time checks. */
+#if defined(RTE_LIBRTE_LPM_DEBUG)
+#define RTE_LPM_RETURN_IF_TRUE(cond, retval) do { \
+	if (cond) \
+		return (retval); \
+} while (0)
+#else
+#define RTE_LPM_RETURN_IF_TRUE(cond, retval)
+#endif
+
+/** @internal bitmask with valid and ext_entry/valid_group fields set */
+#define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x0300
+
+/** Bitmask used to indicate successful lookup */
+#define RTE_LPM_LOOKUP_SUCCESS          0x0100
+
+/** @internal Tbl24 entry structure. */
+struct rte_lpm_tbl24_entry {
+	/* Stores Next hop or group index (i.e. gindex)into tbl8. */
+	union {
+		uint8_t next_hop;
+		uint8_t tbl8_gindex;
+	};
+	/* Using single uint8_t to store 3 values. */
+	uint8_t valid     :1; /**< Validation flag. */
+	uint8_t ext_entry :1; /**< External entry. */
+	uint8_t depth     :6; /**< Rule depth. */
+};
+
+/** @internal Tbl8 entry structure. */
+struct rte_lpm_tbl8_entry {
+	uint8_t next_hop; /**< next hop. */
+	/* Using single uint8_t to store 3 values. */
+	uint8_t valid       :1; /**< Validation flag. */
+	uint8_t valid_group :1; /**< Group validation flag. */
+	uint8_t depth       :6; /**< Rule depth. */
+};
+
+/** @internal Rule structure. */
+struct rte_lpm_rule {
+	uint32_t ip; /**< Rule IP address. */
+	uint8_t  next_hop; /**< Rule next hop. */
+};
+
+/** @internal Contains metadata about the rules table. */
+struct rte_lpm_rule_info {
+	uint32_t used_rules; /**< Used rules so far. */
+	uint32_t first_rule; /**< Indexes the first rule of a given depth. */
+};
+
+/** @internal LPM structure. */
+struct rte_lpm {
+	/* LPM metadata. */
+	char name[RTE_LPM_NAMESIZE];        /**< Name of the lpm. */
+	int mem_location; /**< @deprecated @see RTE_LPM_HEAP and RTE_LPM_MEMZONE. */
+	uint32_t max_rules; /**< Max. balanced rules per lpm. */
+	struct rte_lpm_rule_info rule_info[RTE_LPM_MAX_DEPTH]; /**< Rule info table. */
+
+	/* LPM Tables. */
+	struct rte_lpm_tbl24_entry tbl24[RTE_LPM_TBL24_NUM_ENTRIES] \
+			__rte_cache_aligned; /**< LPM tbl24 table. */
+	struct rte_lpm_tbl8_entry tbl8[RTE_LPM_TBL8_NUM_ENTRIES] \
+			__rte_cache_aligned; /**< LPM tbl8 table. */
+	struct rte_lpm_rule rules_tbl[0] \
+			__rte_cache_aligned; /**< LPM rules. */
+};
+
+/**
+ * Create an LPM object.
+ *
+ * @param name
+ *   LPM object name
+ * @param socket_id
+ *   NUMA socket ID for LPM table memory allocation
+ * @param max_rules
+ *   Maximum number of LPM rules that can be added
+ * @param flags
+ *   This parameter is currently unused
+ * @return
+ *   Handle to LPM object on success, NULL otherwise with rte_errno set
+ *   to an appropriate values. Possible rte_errno values include:
+ *    - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
+ *    - E_RTE_SECONDARY - function was called from a secondary process instance
+ *    - EINVAL - invalid parameter passed to function
+ *    - ENOSPC - the maximum number of memzones has already been allocated
+ *    - EEXIST - a memzone with the same name already exists
+ *    - ENOMEM - no appropriate memory area found in which to create memzone
+ */
+struct rte_lpm *
+rte_lpm_create(const char *name, int socket_id, int max_rules, int flags);
+
+/**
+ * Find an existing LPM object and return a pointer to it.
+ *
+ * @param name
+ *   Name of the lpm object as passed to rte_lpm_create()
+ * @return
+ *   Pointer to lpm object or NULL if object not found with rte_errno
+ *   set appropriately. Possible rte_errno values include:
+ *    - ENOENT - required entry not available to return.
+ */
+struct rte_lpm *
+rte_lpm_find_existing(const char *name);
+
+/**
+ * Free an LPM object.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @return
+ *   None
+ */
+void
+rte_lpm_free(struct rte_lpm *lpm);
+
+/**
+ * Add a rule to the LPM table.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @param ip
+ *   IP of the rule to be added to the LPM table
+ * @param depth
+ *   Depth of the rule to be added to the LPM table
+ * @param next_hop
+ *   Next hop of the rule to be added to the LPM table
+ * @return
+ *   0 on success, negative value otherwise
+ */
+int
+rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint8_t next_hop);
+
+/**
+ * Check if a rule is present in the LPM table,
+ * and provide its next hop if it is.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @param ip
+ *   IP of the rule to be searched
+ * @param depth
+ *   Depth of the rule to searched
+ * @param next_hop
+ *   Next hop of the rule (valid only if it is found)
+ * @return
+ *   1 if the rule exists, 0 if it does not, a negative value on failure
+ */
+int
+rte_lpm_is_rule_present(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,
+uint8_t *next_hop);
+
+/**
+ * Delete a rule from the LPM table.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @param ip
+ *   IP of the rule to be deleted from the LPM table
+ * @param depth
+ *   Depth of the rule to be deleted from the LPM table
+ * @return
+ *   0 on success, negative value otherwise
+ */
+int
+rte_lpm_delete(struct rte_lpm *lpm, uint32_t ip, uint8_t depth);
+
+/**
+ * Delete all rules from the LPM table.
+ *
+ * @param lpm
+ *   LPM object handle
+ */
+void
+rte_lpm_delete_all(struct rte_lpm *lpm);
+
+/**
+ * Lookup an IP into the LPM table.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @param ip
+ *   IP to be looked up in the LPM table
+ * @param next_hop
+ *   Next hop of the most specific rule found for IP (valid on lookup hit only)
+ * @return
+ *   -EINVAL for incorrect arguments, -ENOENT on lookup miss, 0 on lookup hit
+ */
+static inline int
+rte_lpm_lookup(struct rte_lpm *lpm, uint32_t ip, uint8_t *next_hop)
+{
+	unsigned tbl24_index = (ip >> 8);
+	uint16_t tbl_entry;
+
+	/* DEBUG: Check user input arguments. */
+	RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (next_hop == NULL)), -EINVAL);
+
+	/* Copy tbl24 entry */
+	tbl_entry = *(const uint16_t *)&lpm->tbl24[tbl24_index];
+
+	/* Copy tbl8 entry (only if needed) */
+	if (unlikely((tbl_entry & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+
+		unsigned tbl8_index = (uint8_t)ip +
+				((uint8_t)tbl_entry * RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
+
+		tbl_entry = *(const uint16_t *)&lpm->tbl8[tbl8_index];
+	}
+
+	*next_hop = (uint8_t)tbl_entry;
+	return (tbl_entry & RTE_LPM_LOOKUP_SUCCESS) ? 0 : -ENOENT;
+}
+
+/**
+ * Lookup multiple IP addresses in an LPM table. This may be implemented as a
+ * macro, so the address of the function should not be used.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @param ips
+ *   Array of IPs to be looked up in the LPM table
+ * @param next_hops
+ *   Next hop of the most specific rule found for IP (valid on lookup hit only).
+ *   This is an array of two byte values. The most significant byte in each
+ *   value says whether the lookup was successful (bitmask
+ *   RTE_LPM_LOOKUP_SUCCESS is set). The least significant byte is the
+ *   actual next hop.
+ * @param n
+ *   Number of elements in ips (and next_hops) array to lookup. This should be a
+ *   compile time constant, and divisible by 8 for best performance.
+ *  @return
+ *   -EINVAL for incorrect arguments, otherwise 0
+ */
+#define rte_lpm_lookup_bulk(lpm, ips, next_hops, n) \
+		rte_lpm_lookup_bulk_func(lpm, ips, next_hops, n)
+
+static inline int
+rte_lpm_lookup_bulk_func(const struct rte_lpm *lpm, const uint32_t *ips,
+		uint16_t *next_hops, const unsigned n)
+{
+	unsigned i;
+	unsigned tbl24_indexes[n];
+
+	/* DEBUG: Check user input arguments. */
+	RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (ips == NULL) ||
+			(next_hops == NULL)), -EINVAL);
+
+	for (i = 0; i < n; i++) {
+		tbl24_indexes[i] = ips[i] >> 8;
+	}
+
+	for (i = 0; i < n; i++) {
+		/* Simply copy tbl24 entry to output */
+		next_hops[i] = *(const uint16_t *)&lpm->tbl24[tbl24_indexes[i]];
+
+		/* Overwrite output with tbl8 entry if needed */
+		if (unlikely((next_hops[i] & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+				RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+
+			unsigned tbl8_index = (uint8_t)ips[i] +
+					((uint8_t)next_hops[i] *
+					 RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
+
+			next_hops[i] = *(const uint16_t *)&lpm->tbl8[tbl8_index];
+		}
+	}
+	return 0;
+}
+
+/* Mask four results. */
+#define	 RTE_LPM_MASKX4_RES	UINT64_C(0x00ff00ff00ff00ff)
+
+/**
+ * Lookup four IP addresses in an LPM table.
+ *
+ * @param lpm
+ *   LPM object handle
+ * @param ip
+ *   Four IPs to be looked up in the LPM table
+ * @param hop
+ *   Next hop of the most specific rule found for IP (valid on lookup hit only).
+ *   This is an 4 elements array of two byte values.
+ *   If the lookup was succesfull for the given IP, then least significant byte
+ *   of the corresponding element is the  actual next hop and the most
+ *   significant byte is zero.
+ *   If the lookup for the given IP failed, then corresponding element would
+ *   contain default value, see description of then next parameter.
+ * @param defv
+ *   Default value to populate into corresponding element of hop[] array,
+ *   if lookup would fail.
+ */
+static inline void
+rte_lpm_lookupx4(const struct rte_lpm *lpm, __m128i ip, uint16_t hop[4],
+	uint16_t defv)
+{
+	__m128i i24;
+	rte_xmm_t i8;
+	uint16_t tbl[4];
+	uint64_t idx, pt;
+
+	const __m128i mask8 =
+		_mm_set_epi32(UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX);
+
+	/*
+	 * RTE_LPM_VALID_EXT_ENTRY_BITMASK for 4 LPM entries
+	 * as one 64-bit value (0x0300030003000300).
+	 */
+	const uint64_t mask_xv =
+		((uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK |
+		(uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 16 |
+		(uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 32 |
+		(uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 48);
+
+	/*
+	 * RTE_LPM_LOOKUP_SUCCESS for 4 LPM entries
+	 * as one 64-bit value (0x0100010001000100).
+	 */
+	const uint64_t mask_v =
+		((uint64_t)RTE_LPM_LOOKUP_SUCCESS |
+		(uint64_t)RTE_LPM_LOOKUP_SUCCESS << 16 |
+		(uint64_t)RTE_LPM_LOOKUP_SUCCESS << 32 |
+		(uint64_t)RTE_LPM_LOOKUP_SUCCESS << 48);
+
+	/* get 4 indexes for tbl24[]. */
+	i24 = _mm_srli_epi32(ip, CHAR_BIT);
+
+	/* extract values from tbl24[] */
+	idx = _mm_cvtsi128_si64(i24);
+	i24 = _mm_srli_si128(i24, sizeof(uint64_t));
+
+	tbl[0] = *(const uint16_t *)&lpm->tbl24[(uint32_t)idx];
+	tbl[1] = *(const uint16_t *)&lpm->tbl24[idx >> 32];
+
+	idx = _mm_cvtsi128_si64(i24);
+
+	tbl[2] = *(const uint16_t *)&lpm->tbl24[(uint32_t)idx];
+	tbl[3] = *(const uint16_t *)&lpm->tbl24[idx >> 32];
+
+	/* get 4 indexes for tbl8[]. */
+	i8.x = _mm_and_si128(ip, mask8);
+
+	pt = (uint64_t)tbl[0] |
+		(uint64_t)tbl[1] << 16 |
+		(uint64_t)tbl[2] << 32 |
+		(uint64_t)tbl[3] << 48;
+
+	/* search successfully finished for all 4 IP addresses. */
+	if (likely((pt & mask_xv) == mask_v)) {
+		uintptr_t ph = (uintptr_t)hop;
+		*(uint64_t *)ph = pt & RTE_LPM_MASKX4_RES;
+		return;
+	}
+
+	if (unlikely((pt & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+		i8.u32[0] = i8.u32[0] +
+			(uint8_t)tbl[0] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+		tbl[0] = *(const uint16_t *)&lpm->tbl8[i8.u32[0]];
+	}
+	if (unlikely((pt >> 16 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+		i8.u32[1] = i8.u32[1] +
+			(uint8_t)tbl[1] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+		tbl[1] = *(const uint16_t *)&lpm->tbl8[i8.u32[1]];
+	}
+	if (unlikely((pt >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+		i8.u32[2] = i8.u32[2] +
+			(uint8_t)tbl[2] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+		tbl[2] = *(const uint16_t *)&lpm->tbl8[i8.u32[2]];
+	}
+	if (unlikely((pt >> 48 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
+			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
+		i8.u32[3] = i8.u32[3] +
+			(uint8_t)tbl[3] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+		tbl[3] = *(const uint16_t *)&lpm->tbl8[i8.u32[3]];
+	}
+
+	hop[0] = (tbl[0] & RTE_LPM_LOOKUP_SUCCESS) ? (uint8_t)tbl[0] : defv;
+	hop[1] = (tbl[1] & RTE_LPM_LOOKUP_SUCCESS) ? (uint8_t)tbl[1] : defv;
+	hop[2] = (tbl[2] & RTE_LPM_LOOKUP_SUCCESS) ? (uint8_t)tbl[2] : defv;
+	hop[3] = (tbl[3] & RTE_LPM_LOOKUP_SUCCESS) ? (uint8_t)tbl[3] : defv;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_LPM_H_ */
diff --git a/app/test/v2.0/test_lpm.c b/app/test/v2.0/test_lpm.c
new file mode 100644
index 000000000..e71d213ba
--- /dev/null
+++ b/app/test/v2.0/test_lpm.c
@@ -0,0 +1,1306 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2019 Intel Corporation
+ *
+ * LPM Autotests from DPDK v2.0 for abi compability testing.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_random.h>
+#include <rte_branch_prediction.h>
+#include <rte_ip.h>
+#include <time.h>
+
+#include "../test_lpm_routes.h"
+#include "../test.h"
+
+/* remapping of DPDK v2.0 symbols */
+#include "dcompat.h"
+/* backported header from DPDK v2.0 */
+#include "rte_lpm.h"
+
+#define TEST_LPM_ASSERT(cond) do {                                            \
+	if (!(cond)) {                                                        \
+		printf("Error at line %d:\n", __LINE__);                      \
+		return -1;                                                    \
+	}                                                                     \
+} while (0)
+
+typedef int32_t (*rte_lpm_test)(void);
+
+static int32_t test0(void);
+static int32_t test1(void);
+static int32_t test2(void);
+static int32_t test3(void);
+static int32_t test4(void);
+static int32_t test5(void);
+static int32_t test6(void);
+static int32_t test7(void);
+static int32_t test8(void);
+static int32_t test9(void);
+static int32_t test10(void);
+static int32_t test11(void);
+static int32_t test12(void);
+static int32_t test13(void);
+static int32_t test14(void);
+static int32_t test15(void);
+static int32_t test16(void);
+static int32_t test17(void);
+static int32_t perf_test(void);
+
+static rte_lpm_test tests[] = {
+/* Test Cases */
+	test0,
+	test1,
+	test2,
+	test3,
+	test4,
+	test5,
+	test6,
+	test7,
+	test8,
+	test9,
+	test10,
+	test11,
+	test12,
+	test13,
+	test14,
+	test15,
+	test16,
+	test17,
+	perf_test,
+};
+
+#define NUM_LPM_TESTS (sizeof(tests)/sizeof(tests[0]))
+#define MAX_DEPTH 32
+#define MAX_RULES 256
+#define PASS 0
+
+/*
+ * Check that rte_lpm_create fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test0(void)
+{
+	struct rte_lpm *lpm = NULL;
+
+	/* rte_lpm_create: lpm name == NULL */
+	lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, MAX_RULES, 0);
+	TEST_LPM_ASSERT(lpm == NULL);
+
+	/* rte_lpm_create: max_rules = 0 */
+	/* Note: __func__ inserts the function name, in this case "test0". */
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, 0, 0);
+	TEST_LPM_ASSERT(lpm == NULL);
+
+	/* socket_id < -1 is invalid */
+	lpm = rte_lpm_create(__func__, -2, MAX_RULES, 0);
+	TEST_LPM_ASSERT(lpm == NULL);
+
+	return PASS;
+}
+
+/*
+ * Create lpm table then delete lpm table 100 times
+ * Use a slightly different rules size each time
+ * */
+int32_t
+test1(void)
+{
+	struct rte_lpm *lpm = NULL;
+	int32_t i;
+
+	/* rte_lpm_free: Free NULL */
+	for (i = 0; i < 100; i++) {
+		lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES - i, 0);
+		TEST_LPM_ASSERT(lpm != NULL);
+
+		rte_lpm_free(lpm);
+	}
+
+	/* Can not test free so return success */
+	return PASS;
+}
+
+/*
+ * Call rte_lpm_free for NULL pointer user input. Note: free has no return and
+ * therefore it is impossible to check for failure but this test is added to
+ * increase function coverage metrics and to validate that freeing null does
+ * not crash.
+ */
+int32_t
+test2(void)
+{
+	struct rte_lpm *lpm = NULL;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, RTE_LPM_HEAP);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	rte_lpm_free(lpm);
+	rte_lpm_free(NULL);
+	return PASS;
+}
+
+/*
+ * Check that rte_lpm_add fails gracefully for incorrect user input arguments
+ */
+int32_t
+test3(void)
+{
+	struct rte_lpm *lpm = NULL;
+	uint32_t ip = IPv4(0, 0, 0, 0);
+	uint8_t depth = 24, next_hop = 100;
+	int32_t status = 0;
+
+	/* rte_lpm_add: lpm == NULL */
+	status = rte_lpm_add(NULL, ip, depth, next_hop);
+	TEST_LPM_ASSERT(status < 0);
+
+	/*Create vaild lpm to use in rest of test. */
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	/* rte_lpm_add: depth < 1 */
+	status = rte_lpm_add(lpm, ip, 0, next_hop);
+	TEST_LPM_ASSERT(status < 0);
+
+	/* rte_lpm_add: depth > MAX_DEPTH */
+	status = rte_lpm_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
+	TEST_LPM_ASSERT(status < 0);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Check that rte_lpm_delete fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test4(void)
+{
+	struct rte_lpm *lpm = NULL;
+	uint32_t ip = IPv4(0, 0, 0, 0);
+	uint8_t depth = 24;
+	int32_t status = 0;
+
+	/* rte_lpm_delete: lpm == NULL */
+	status = rte_lpm_delete(NULL, ip, depth);
+	TEST_LPM_ASSERT(status < 0);
+
+	/*Create vaild lpm to use in rest of test. */
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	/* rte_lpm_delete: depth < 1 */
+	status = rte_lpm_delete(lpm, ip, 0);
+	TEST_LPM_ASSERT(status < 0);
+
+	/* rte_lpm_delete: depth > MAX_DEPTH */
+	status = rte_lpm_delete(lpm, ip, (MAX_DEPTH + 1));
+	TEST_LPM_ASSERT(status < 0);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Check that rte_lpm_lookup fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test5(void)
+{
+#if defined(RTE_LIBRTE_LPM_DEBUG)
+	struct rte_lpm *lpm = NULL;
+	uint32_t ip = IPv4(0, 0, 0, 0);
+	uint8_t next_hop_return = 0;
+	int32_t status = 0;
+
+	/* rte_lpm_lookup: lpm == NULL */
+	status = rte_lpm_lookup(NULL, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status < 0);
+
+	/*Create vaild lpm to use in rest of test. */
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	/* rte_lpm_lookup: depth < 1 */
+	status = rte_lpm_lookup(lpm, ip, NULL);
+	TEST_LPM_ASSERT(status < 0);
+
+	rte_lpm_free(lpm);
+#endif
+	return PASS;
+}
+
+
+
+/*
+ * Call add, lookup and delete for a single rule with depth <= 24
+ */
+int32_t
+test6(void)
+{
+	struct rte_lpm *lpm = NULL;
+	uint32_t ip = IPv4(0, 0, 0, 0);
+	uint8_t depth = 24, next_hop_add = 100, next_hop_return = 0;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Call add, lookup and delete for a single rule with depth > 24
+ */
+
+int32_t
+test7(void)
+{
+	__m128i ipx4;
+	uint16_t hop[4];
+	struct rte_lpm *lpm = NULL;
+	uint32_t ip = IPv4(0, 0, 0, 0);
+	uint8_t depth = 32, next_hop_add = 100, next_hop_return = 0;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	ipx4 = _mm_set_epi32(ip, ip + 0x100, ip - 0x100, ip);
+	rte_lpm_lookupx4(lpm, ipx4, hop, UINT16_MAX);
+	TEST_LPM_ASSERT(hop[0] == next_hop_add);
+	TEST_LPM_ASSERT(hop[1] == UINT16_MAX);
+	TEST_LPM_ASSERT(hop[2] == UINT16_MAX);
+	TEST_LPM_ASSERT(hop[3] == next_hop_add);
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Use rte_lpm_add to add rules which effect only the second half of the lpm
+ * table. Use all possible depths ranging from 1..32. Set the next hop = to the
+ * depth. Check lookup hit for on every add and check for lookup miss on the
+ * first half of the lpm table after each add. Finally delete all rules going
+ * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
+ * delete. The lookup should return the next_hop_add value related to the
+ * previous depth value (i.e. depth -1).
+ */
+int32_t
+test8(void)
+{
+	__m128i ipx4;
+	uint16_t hop[4];
+	struct rte_lpm *lpm = NULL;
+	uint32_t ip1 = IPv4(127, 255, 255, 255), ip2 = IPv4(128, 0, 0, 0);
+	uint8_t depth, next_hop_add, next_hop_return;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	/* Loop with rte_lpm_add. */
+	for (depth = 1; depth <= 32; depth++) {
+		/* Let the next_hop_add value = depth. Just for change. */
+		next_hop_add = depth;
+
+		status = rte_lpm_add(lpm, ip2, depth, next_hop_add);
+		TEST_LPM_ASSERT(status == 0);
+
+		/* Check IP in first half of tbl24 which should be empty. */
+		status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
+		TEST_LPM_ASSERT(status == -ENOENT);
+
+		status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
+		TEST_LPM_ASSERT((status == 0) &&
+			(next_hop_return == next_hop_add));
+
+		ipx4 = _mm_set_epi32(ip2, ip1, ip2, ip1);
+		rte_lpm_lookupx4(lpm, ipx4, hop, UINT16_MAX);
+		TEST_LPM_ASSERT(hop[0] == UINT16_MAX);
+		TEST_LPM_ASSERT(hop[1] == next_hop_add);
+		TEST_LPM_ASSERT(hop[2] == UINT16_MAX);
+		TEST_LPM_ASSERT(hop[3] == next_hop_add);
+	}
+
+	/* Loop with rte_lpm_delete. */
+	for (depth = 32; depth >= 1; depth--) {
+		next_hop_add = (uint8_t) (depth - 1);
+
+		status = rte_lpm_delete(lpm, ip2, depth);
+		TEST_LPM_ASSERT(status == 0);
+
+		status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
+
+		if (depth != 1) {
+			TEST_LPM_ASSERT((status == 0) &&
+				(next_hop_return == next_hop_add));
+		} else {
+			TEST_LPM_ASSERT(status == -ENOENT);
+		}
+
+		status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
+		TEST_LPM_ASSERT(status == -ENOENT);
+
+		ipx4 = _mm_set_epi32(ip1, ip1, ip2, ip2);
+		rte_lpm_lookupx4(lpm, ipx4, hop, UINT16_MAX);
+		if (depth != 1) {
+			TEST_LPM_ASSERT(hop[0] == next_hop_add);
+			TEST_LPM_ASSERT(hop[1] == next_hop_add);
+		} else {
+			TEST_LPM_ASSERT(hop[0] == UINT16_MAX);
+			TEST_LPM_ASSERT(hop[1] == UINT16_MAX);
+		}
+		TEST_LPM_ASSERT(hop[2] == UINT16_MAX);
+		TEST_LPM_ASSERT(hop[3] == UINT16_MAX);
+	}
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * - Add & lookup to hit invalid TBL24 entry
+ * - Add & lookup to hit valid TBL24 entry not extended
+ * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
+ * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
+ *
+ */
+int32_t
+test9(void)
+{
+	struct rte_lpm *lpm = NULL;
+	uint32_t ip, ip_1, ip_2;
+	uint8_t depth, depth_1, depth_2, next_hop_add, next_hop_add_1,
+		next_hop_add_2, next_hop_return;
+	int32_t status = 0;
+
+	/* Add & lookup to hit invalid TBL24 entry */
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+	next_hop_add = 100;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Add & lookup to hit valid TBL24 entry not extended */
+	ip = IPv4(128, 0, 0, 0);
+	depth = 23;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	depth = 24;
+	next_hop_add = 101;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	depth = 24;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	depth = 23;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
+	 * entry */
+	ip = IPv4(128, 0, 0, 0);
+	depth = 32;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	ip = IPv4(128, 0, 0, 5);
+	depth = 32;
+	next_hop_add = 101;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 32;
+	next_hop_add = 100;
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Add & lookup to hit valid extended TBL24 entry with valid TBL8
+	 * entry */
+	ip_1 = IPv4(128, 0, 0, 0);
+	depth_1 = 25;
+	next_hop_add_1 = 101;
+
+	ip_2 = IPv4(128, 0, 0, 5);
+	depth_2 = 32;
+	next_hop_add_2 = 102;
+
+	next_hop_return = 0;
+
+	status = rte_lpm_add(lpm, ip_1, depth_1, next_hop_add_1);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
+
+	status = rte_lpm_add(lpm, ip_2, depth_2, next_hop_add_2);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
+
+	status = rte_lpm_delete(lpm, ip_2, depth_2);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
+
+	status = rte_lpm_delete(lpm, ip_1, depth_1);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+
+/*
+ * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
+ *   lookup)
+ * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
+ * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
+ *   delete & lookup)
+ * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
+ * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
+ * - Delete a rule that is not present in the TBL24 & lookup
+ * - Delete a rule that is not present in the TBL8 & lookup
+ *
+ */
+int32_t
+test10(void)
+{
+
+	struct rte_lpm *lpm = NULL;
+	uint32_t ip;
+	uint8_t depth, next_hop_add, next_hop_return;
+	int32_t status = 0;
+
+	/* Add rule that covers a TBL24 range previously invalid & lookup
+	 * (& delete & lookup) */
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, RTE_LPM_HEAP);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 16;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 25;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Add rule that extends a TBL24 valid entry & lookup for both rules
+	 * (& delete & lookup) */
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	ip = IPv4(128, 0, 0, 10);
+	depth = 32;
+	next_hop_add = 101;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	ip = IPv4(128, 0, 0, 0);
+	next_hop_add = 100;
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	ip = IPv4(128, 0, 0, 10);
+	depth = 32;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Add rule that updates the next hop in TBL24 & lookup
+	 * (& delete & lookup) */
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	next_hop_add = 101;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Add rule that updates the next hop in TBL8 & lookup
+	 * (& delete & lookup) */
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 32;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	next_hop_add = 101;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Delete a rule that is not present in the TBL24 & lookup */
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status < 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_delete_all(lpm);
+
+	/* Delete a rule that is not present in the TBL8 & lookup */
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 32;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status < 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Add two rules, lookup to hit the more specific one, lookup to hit the less
+ * specific one delete the less specific rule and lookup previous values again;
+ * add a more specific rule than the existing rule, lookup again
+ *
+ * */
+int32_t
+test11(void)
+{
+
+	struct rte_lpm *lpm = NULL;
+	uint32_t ip;
+	uint8_t depth, next_hop_add, next_hop_return;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+	next_hop_add = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	ip = IPv4(128, 0, 0, 10);
+	depth = 32;
+	next_hop_add = 101;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	ip = IPv4(128, 0, 0, 0);
+	next_hop_add = 100;
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	ip = IPv4(128, 0, 0, 10);
+	depth = 32;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
+ * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension
+ * and contraction.
+ *
+ * */
+
+int32_t
+test12(void)
+{
+	__m128i ipx4;
+	uint16_t hop[4];
+	struct rte_lpm *lpm = NULL;
+	uint32_t ip, i;
+	uint8_t depth, next_hop_add, next_hop_return;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 32;
+	next_hop_add = 100;
+
+	for (i = 0; i < 1000; i++) {
+		status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+		TEST_LPM_ASSERT(status == 0);
+
+		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+		TEST_LPM_ASSERT((status == 0) &&
+				(next_hop_return == next_hop_add));
+
+		ipx4 = _mm_set_epi32(ip, ip + 1, ip, ip - 1);
+		rte_lpm_lookupx4(lpm, ipx4, hop, UINT16_MAX);
+		TEST_LPM_ASSERT(hop[0] == UINT16_MAX);
+		TEST_LPM_ASSERT(hop[1] == next_hop_add);
+		TEST_LPM_ASSERT(hop[2] == UINT16_MAX);
+		TEST_LPM_ASSERT(hop[3] == next_hop_add);
+
+		status = rte_lpm_delete(lpm, ip, depth);
+		TEST_LPM_ASSERT(status == 0);
+
+		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+		TEST_LPM_ASSERT(status == -ENOENT);
+	}
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Add a rule to tbl24, lookup (hit), then add a rule that will extend this
+ * tbl24 entry, lookup (hit). delete the rule that caused the tbl24 extension,
+ * lookup (miss) and repeat for loop of 1000 times. This will check tbl8
+ * extension and contraction.
+ *
+ * */
+
+int32_t
+test13(void)
+{
+	struct rte_lpm *lpm = NULL;
+	uint32_t ip, i;
+	uint8_t depth, next_hop_add_1, next_hop_add_2, next_hop_return;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	ip = IPv4(128, 0, 0, 0);
+	depth = 24;
+	next_hop_add_1 = 100;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add_1);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
+
+	depth = 32;
+	next_hop_add_2 = 101;
+
+	for (i = 0; i < 1000; i++) {
+		status = rte_lpm_add(lpm, ip, depth, next_hop_add_2);
+		TEST_LPM_ASSERT(status == 0);
+
+		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+		TEST_LPM_ASSERT((status == 0) &&
+				(next_hop_return == next_hop_add_2));
+
+		status = rte_lpm_delete(lpm, ip, depth);
+		TEST_LPM_ASSERT(status == 0);
+
+		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+		TEST_LPM_ASSERT((status == 0) &&
+				(next_hop_return == next_hop_add_1));
+	}
+
+	depth = 24;
+
+	status = rte_lpm_delete(lpm, ip, depth);
+	TEST_LPM_ASSERT(status == 0);
+
+	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+	TEST_LPM_ASSERT(status == -ENOENT);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Fore TBL8 extension exhaustion. Add 256 rules that require a tbl8 extension.
+ * No more tbl8 extensions will be allowed. Now add one more rule that required
+ * a tbl8 extension and get fail.
+ * */
+int32_t
+test14(void)
+{
+
+	/* We only use depth = 32 in the loop below so we must make sure
+	 * that we have enough storage for all rules at that depth*/
+
+	struct rte_lpm *lpm = NULL;
+	uint32_t ip;
+	uint8_t depth, next_hop_add, next_hop_return;
+	int32_t status = 0;
+
+	/* Add enough space for 256 rules for every depth */
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, 256 * 32, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	depth = 32;
+	next_hop_add = 100;
+	ip = IPv4(0, 0, 0, 0);
+
+	/* Add 256 rules that require a tbl8 extension */
+	for (; ip <= IPv4(0, 0, 255, 0); ip += 256) {
+		status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+		TEST_LPM_ASSERT(status == 0);
+
+		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+		TEST_LPM_ASSERT((status == 0) &&
+				(next_hop_return == next_hop_add));
+	}
+
+	/* All tbl8 extensions have been used above. Try to add one more and
+	 * we get a fail */
+	ip = IPv4(1, 0, 0, 0);
+	depth = 32;
+
+	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+	TEST_LPM_ASSERT(status < 0);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Sequence of operations for find existing lpm table
+ *
+ *  - create table
+ *  - find existing table: hit
+ *  - find non-existing table: miss
+ *
+ */
+int32_t
+test15(void)
+{
+	struct rte_lpm *lpm = NULL, *result = NULL;
+
+	/* Create lpm  */
+	lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, 256 * 32, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	/* Try to find existing lpm */
+	result = rte_lpm_find_existing("lpm_find_existing");
+	TEST_LPM_ASSERT(result == lpm);
+
+	/* Try to find non-existing lpm */
+	result = rte_lpm_find_existing("lpm_find_non_existing");
+	TEST_LPM_ASSERT(result == NULL);
+
+	/* Cleanup. */
+	rte_lpm_delete_all(lpm);
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * test failure condition of overloading the tbl8 so no more will fit
+ * Check we get an error return value in that case
+ */
+int32_t
+test16(void)
+{
+	uint32_t ip;
+	struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY,
+			256 * 32, 0);
+
+	/* ip loops through all possibilities for top 24 bits of address */
+	for (ip = 0; ip < 0xFFFFFF; ip++) {
+		/* add an entry within a different tbl8 each time, since
+		 * depth >24 and the top 24 bits are different */
+		if (rte_lpm_add(lpm, (ip << 8) + 0xF0, 30, 0) < 0)
+			break;
+	}
+
+	if (ip != RTE_LPM_TBL8_NUM_GROUPS) {
+		printf("Error, unexpected failure with filling tbl8 groups\n");
+		printf("Failed after %u additions, expected after %u\n",
+				(unsigned)ip, (unsigned)RTE_LPM_TBL8_NUM_GROUPS);
+	}
+
+	rte_lpm_free(lpm);
+	return 0;
+}
+
+/*
+ * Test for overwriting of tbl8:
+ *  - add rule /32 and lookup
+ *  - add new rule /24 and lookup
+ *	- add third rule /25 and lookup
+ *	- lookup /32 and /24 rule to ensure the table has not been overwritten.
+ */
+int32_t
+test17(void)
+{
+	struct rte_lpm *lpm = NULL;
+	const uint32_t ip_10_32 = IPv4(10, 10, 10, 2);
+	const uint32_t ip_10_24 = IPv4(10, 10, 10, 0);
+	const uint32_t ip_20_25 = IPv4(10, 10, 20, 2);
+	const uint8_t d_ip_10_32 = 32,
+			d_ip_10_24 = 24,
+			d_ip_20_25 = 25;
+	const uint8_t next_hop_ip_10_32 = 100,
+			next_hop_ip_10_24 = 105,
+			next_hop_ip_20_25 = 111;
+	uint8_t next_hop_return = 0;
+	int32_t status = 0;
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	status = rte_lpm_add(lpm, ip_10_32, d_ip_10_32, next_hop_ip_10_32);
+	if (status < 0)
+		return -1;
+
+	status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
+	uint8_t test_hop_10_32 = next_hop_return;
+	TEST_LPM_ASSERT(status == 0);
+	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
+
+	status = rte_lpm_add(lpm, ip_10_24, d_ip_10_24, next_hop_ip_10_24);
+	if (status < 0)
+		return -1;
+
+	status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
+	uint8_t test_hop_10_24 = next_hop_return;
+	TEST_LPM_ASSERT(status == 0);
+	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
+
+	status = rte_lpm_add(lpm, ip_20_25, d_ip_20_25, next_hop_ip_20_25);
+	if (status < 0)
+		return -1;
+
+	status = rte_lpm_lookup(lpm, ip_20_25, &next_hop_return);
+	uint8_t test_hop_20_25 = next_hop_return;
+	TEST_LPM_ASSERT(status == 0);
+	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
+
+	if (test_hop_10_32 == test_hop_10_24) {
+		printf("Next hop return equal\n");
+		return -1;
+	}
+
+	if (test_hop_10_24 == test_hop_20_25) {
+		printf("Next hop return equal\n");
+		return -1;
+	}
+
+	status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
+	TEST_LPM_ASSERT(status == 0);
+	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
+
+	status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
+	TEST_LPM_ASSERT(status == 0);
+	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
+
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Lookup performance test
+ */
+
+#define ITERATIONS (1 << 10)
+#define BATCH_SIZE (1 << 12)
+#define BULK_SIZE 32
+
+int32_t
+perf_test(void)
+{
+	struct rte_lpm *lpm = NULL;
+	uint64_t begin, total_time, lpm_used_entries = 0;
+	unsigned i, j;
+	uint8_t next_hop_add = 0xAA, next_hop_return = 0;
+	int status = 0;
+	uint64_t cache_line_counter = 0;
+	int64_t count = 0;
+
+	rte_srand(rte_rdtsc());
+
+	/* (re) generate the routing table */
+	generate_large_route_rule_table();
+
+	printf("No. routes = %u\n", (unsigned) NUM_ROUTE_ENTRIES);
+
+	print_route_distribution(large_route_table,
+				 (uint32_t) NUM_ROUTE_ENTRIES);
+
+	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, 1000000, 0);
+	TEST_LPM_ASSERT(lpm != NULL);
+
+	/* Measue add. */
+	begin = rte_rdtsc();
+
+	for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
+		if (rte_lpm_add(lpm, large_route_table[i].ip,
+				large_route_table[i].depth, next_hop_add) == 0)
+			status++;
+	}
+	/* End Timer. */
+	total_time = rte_rdtsc() - begin;
+
+	printf("Unique added entries = %d\n", status);
+	/* Obtain add statistics. */
+	for (i = 0; i < RTE_LPM_TBL24_NUM_ENTRIES; i++) {
+		if (lpm->tbl24[i].valid)
+			lpm_used_entries++;
+
+		if (i % 32 == 0) {
+			if ((uint64_t)count < lpm_used_entries) {
+				cache_line_counter++;
+				count = lpm_used_entries;
+			}
+		}
+	}
+
+	printf("Used table 24 entries = %u (%g%%)\n",
+			(unsigned) lpm_used_entries,
+			(lpm_used_entries * 100.0) / RTE_LPM_TBL24_NUM_ENTRIES);
+	printf("64 byte Cache entries used = %u (%u bytes)\n",
+			(unsigned) cache_line_counter, (unsigned) cache_line_counter * 64);
+
+	printf("Average LPM Add: %g cycles\n", (double)total_time / NUM_ROUTE_ENTRIES);
+
+	/* Measure single Lookup */
+	total_time = 0;
+	count = 0;
+
+	for (i = 0; i < ITERATIONS; i++) {
+		static uint32_t ip_batch[BATCH_SIZE];
+
+		for (j = 0; j < BATCH_SIZE; j++)
+			ip_batch[j] = rte_rand();
+
+		/* Lookup per batch */
+		begin = rte_rdtsc();
+
+		for (j = 0; j < BATCH_SIZE; j++) {
+			if (rte_lpm_lookup(lpm, ip_batch[j], &next_hop_return) != 0)
+				count++;
+		}
+
+		total_time += rte_rdtsc() - begin;
+
+	}
+	printf("Average LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
+			(double)total_time / ((double)ITERATIONS * BATCH_SIZE),
+			(count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
+
+	/* Measure bulk Lookup */
+	total_time = 0;
+	count = 0;
+	for (i = 0; i < ITERATIONS; i++) {
+		static uint32_t ip_batch[BATCH_SIZE];
+		uint16_t next_hops[BULK_SIZE];
+
+		/* Create array of random IP addresses */
+		for (j = 0; j < BATCH_SIZE; j++)
+			ip_batch[j] = rte_rand();
+
+		/* Lookup per batch */
+		begin = rte_rdtsc();
+		for (j = 0; j < BATCH_SIZE; j += BULK_SIZE) {
+			unsigned k;
+			rte_lpm_lookup_bulk(lpm, &ip_batch[j], next_hops, BULK_SIZE);
+			for (k = 0; k < BULK_SIZE; k++)
+				if (unlikely(!(next_hops[k] & RTE_LPM_LOOKUP_SUCCESS)))
+					count++;
+		}
+
+		total_time += rte_rdtsc() - begin;
+	}
+	printf("BULK LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
+			(double)total_time / ((double)ITERATIONS * BATCH_SIZE),
+			(count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
+
+	/* Measure LookupX4 */
+	total_time = 0;
+	count = 0;
+	for (i = 0; i < ITERATIONS; i++) {
+		static uint32_t ip_batch[BATCH_SIZE];
+		uint16_t next_hops[4];
+
+		/* Create array of random IP addresses */
+		for (j = 0; j < BATCH_SIZE; j++)
+			ip_batch[j] = rte_rand();
+
+		/* Lookup per batch */
+		begin = rte_rdtsc();
+		for (j = 0; j < BATCH_SIZE; j += RTE_DIM(next_hops)) {
+			unsigned k;
+			__m128i ipx4;
+
+			ipx4 = _mm_loadu_si128((__m128i *)(ip_batch + j));
+			ipx4 = *(__m128i *)(ip_batch + j);
+			rte_lpm_lookupx4(lpm, ipx4, next_hops, UINT16_MAX);
+			for (k = 0; k < RTE_DIM(next_hops); k++)
+				if (unlikely(next_hops[k] == UINT16_MAX))
+					count++;
+		}
+
+		total_time += rte_rdtsc() - begin;
+	}
+	printf("LPM LookupX4: %.1f cycles (fails = %.1f%%)\n",
+			(double)total_time / ((double)ITERATIONS * BATCH_SIZE),
+			(count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
+
+	/* Delete */
+	status = 0;
+	begin = rte_rdtsc();
+
+	for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
+		/* rte_lpm_delete(lpm, ip, depth) */
+		status += rte_lpm_delete(lpm, large_route_table[i].ip,
+				large_route_table[i].depth);
+	}
+
+	total_time += rte_rdtsc() - begin;
+
+	printf("Average LPM Delete: %g cycles\n",
+			(double)total_time / NUM_ROUTE_ENTRIES);
+
+	rte_lpm_delete_all(lpm);
+	rte_lpm_free(lpm);
+
+	return PASS;
+}
+
+/*
+ * Do all unit and performance tests.
+ */
+
+static int
+test_lpm(void)
+{
+	unsigned i;
+	int status, global_status = 0;
+
+	for (i = 0; i < NUM_LPM_TESTS; i++) {
+		status = tests[i]();
+		if (status < 0) {
+			printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests[i]));
+			global_status = status;
+		}
+	}
+
+	return global_status;
+}
+
+REGISTER_TEST_COMMAND_VERSION(lpm_autotest, test_lpm, TEST_DPDK_ABI_VERSION_V20);
diff --git a/app/test/v2.0/test_v20.c b/app/test/v2.0/test_v20.c
new file mode 100644
index 000000000..6285e2882
--- /dev/null
+++ b/app/test/v2.0/test_v20.c
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <rte_ip.h>
+#include <rte_lpm.h>
+
+#include "../test.h"
+
+REGISTER_TEST_ABI_VERSION(v20, TEST_DPDK_ABI_VERSION_V20);
-- 
2.17.1


^ permalink raw reply	[relevance 3%]

Results 8001-8200 of ~18000   |  | reverse | sort options + mbox downloads above
-- links below jump to the message on this page --
2018-09-05 16:41     [dpdk-dev] [RFC] ethdev: add min/max MTU to device info Stephen Hemminger
2019-02-06 13:05     ` Morten Brørup
2019-02-06 16:11       ` Stephen Hemminger
2019-02-06 21:58         ` Morten Brørup
2019-02-07 10:25           ` Ananyev, Konstantin
2019-02-07 11:10             ` Morten Brørup
2019-02-07 12:00               ` Ananyev, Konstantin
2019-02-20 16:02                 ` Ian Stokes
2019-06-24 13:18  3%               ` Nithin Kumar Dabilpuram
2018-12-12  6:24     [dpdk-dev] [PATCH v1 0/2] add rte_ring_reset and use it to flush a ring Gavin Hu
2019-03-15  3:31     ` [dpdk-dev] [PATCH v7 1/2] ring: add reset API to flush the ring when not in use Gavin Hu
2019-03-29 14:17       ` Olivier Matz
2019-07-04 14:42  0%     ` Thomas Monjalon
2019-03-20 13:32     [dpdk-dev] [PATCH v3] cryptodev: make xform key pointer constant Fan Zhang
2019-06-24 13:35  3% ` [dpdk-dev] [PATCH v4] " Fan Zhang
2019-06-25 12:46  4%   ` Akhil Goyal
2019-07-05 12:30  0%     ` Thomas Monjalon
2019-04-05 20:30     [dpdk-dev] [PATCH] eal: resort symbols in EXPERIMENTAL section Stephen Hemminger
2019-06-14  7:39  0% ` Thomas Monjalon
2019-06-14  7:44  3%   ` David Marchand
2019-06-14 15:32  0%     ` Ferruh Yigit
2019-06-20 17:23  0%       ` David Marchand
2019-04-08 18:25     [dpdk-dev] [PATCH v1 0/5] make lcore_config internal Stephen Hemminger
2019-05-23 13:58     ` [dpdk-dev] [PATCH v4 " David Marchand
2019-05-23 13:58       ` [dpdk-dev] [PATCH v4 2/5] eal: add lcore accessors David Marchand
2019-05-29 22:46         ` Thomas Monjalon
2019-05-29 22:51           ` Stephen Hemminger
2019-05-30  7:31  4%         ` David Marchand
2019-05-30  7:40  0%           ` Thomas Monjalon
2019-05-30 10:11  0%             ` Bruce Richardson
2019-05-30 13:39  0%               ` Thomas Monjalon
2019-05-30 17:00  0%                 ` David Marchand
2019-05-30 20:08  0%                   ` Bruce Richardson
2019-05-31 15:36  4% ` [dpdk-dev] [PATCH v5 0/5] make lcore_config internal David Marchand
2019-06-03 10:32  0%   ` Thomas Monjalon
2019-06-03 20:15  0%     ` Stephen Hemminger
2019-04-10  8:32     [dpdk-dev] [RFC v2 00/14] prefix network structures Olivier Matz
2019-05-21 16:13     ` [dpdk-dev] [PATCH 00/15] " Olivier Matz
2019-05-24 11:38       ` Ferruh Yigit
2019-05-29  7:59  0%     ` David Marchand
2019-05-29 14:46  0%       ` Olivier Matz
2019-05-29 17:29  0%         ` David Marchand
2019-04-16  1:59     [dpdk-dev] [PATCH] fbarray: get fbarrays from containerized secondary ogawa.yasufumi
2019-04-16  3:43     ` [dpdk-dev] [PATCH v2 0/1] Get " ogawa.yasufumi
2019-04-16  3:43       ` [dpdk-dev] [PATCH v2 1/1] fbarray: get " ogawa.yasufumi
2019-07-05  8:53         ` Burakov, Anatoly
2019-07-09 10:22           ` Yasufumi Ogawa
2019-07-09 10:24             ` Burakov, Anatoly
2019-07-09 10:26  4%           ` Burakov, Anatoly
2019-04-17  7:40     [dpdk-dev] [PATCH v2] ethdev: fix QinQ strip offload support viveksharma
2019-04-19  5:59     ` [dpdk-dev] [PATCH v3] ethdev: support QinQ strip dynamic configuration viveksharma
2019-06-27 11:08  3%   ` Ferruh Yigit
2019-07-01 10:07  0%     ` Andrew Rybchenko
2019-07-01 13:05  0%       ` Ferruh Yigit
2019-05-03 13:35     [dpdk-dev] [PATCH 19.08 0/6] improve building examples Bruce Richardson
2019-05-17 11:47     ` [dpdk-dev] [PATCH v2 0/5] " Bruce Richardson
2019-05-17 11:47       ` [dpdk-dev] [PATCH v2 4/5] examples/vdpa: support building from pkg-config info Bruce Richardson
2019-07-02  7:57  3%     ` Thomas Monjalon
2019-07-02 14:35  0%       ` Bruce Richardson
2019-05-03 22:54     [dpdk-dev] [PATCH v2] timer: fix resource leak in finalize Erik Gabriel Carrillo
2019-05-08 22:35     ` [dpdk-dev] [PATCH v3] " Erik Gabriel Carrillo
2019-05-09  8:29       ` Burakov, Anatoly
2019-06-05  9:33  0%     ` Thomas Monjalon
2019-06-05  9:47  3%       ` Burakov, Anatoly
2019-06-25 16:11  4%   ` [dpdk-dev] [PATCH 0/2] Fix timer resource leak Anatoly Burakov
2019-07-05 13:20  4%     ` [dpdk-dev] [PATCH v2 0/1] " Anatoly Burakov
2019-07-05 17:22  4%       ` [dpdk-dev] [PATCH v3 " Anatoly Burakov
2019-05-14 19:45     [dpdk-dev] [PATCH v2 1/5] baseband/fpga_lte_fec: adding driver for FEC on FPGA Nicolas Chautru
2019-06-21 16:59     ` [dpdk-dev] [PATCH v3 00/10] bbdev: adding support in BBDEV for 5GNR FEC Nicolas Chautru
2019-06-21 16:59  5%   ` [dpdk-dev] [PATCH v3 10/10] doc: announce bbdev changes Nicolas Chautru
2019-05-16 15:31     [dpdk-dev] [RFC] ethdev: enhance metadata as flow rule criteria Moti Haimovsky
2019-06-03 21:44  0% ` Yongseok Koh
2019-05-16 15:54     [dpdk-dev] [PATCH] ether: mark ethernet addresses as being 2-byte aligned Bruce Richardson
2019-07-01 13:11  3% ` Olivier Matz
2019-07-01 13:38       ` Bruce Richardson
2019-07-01 14:14  5%     ` Olivier Matz
2019-07-01 14:28  0%       ` Bruce Richardson
2019-05-16 18:04     [dpdk-dev] [PATCH v2 0/7] ether: improvements and optimizations Stephen Hemminger
2019-06-05 18:09     ` [dpdk-dev] [PATCH v4 0/8] net/ether: enhancements " Stephen Hemminger
2019-06-05 18:09       ` [dpdk-dev] [PATCH v4 5/8] net/ether: mark ethernet addresses as being 2-byte aligned Stephen Hemminger
2019-06-07 16:59  3%     ` Ananyev, Konstantin
2019-06-07 18:35  0%       ` Stephen Hemminger
2019-06-07 20:40  0%         ` Richardson, Bruce
2019-06-08 11:51  4%         ` Ananyev, Konstantin
2019-06-07 20:39  0%       ` Richardson, Bruce
2019-06-08 12:15  4%         ` Ananyev, Konstantin
2019-07-02 22:12     ` [dpdk-dev] [PATCH v7 00/12] ether: improvements and optimizations Stephen Hemminger
2019-07-02 22:12       ` [dpdk-dev] [PATCH v7 05/12] net/ether: mark ethernet addresses as being 2-byte aligned Stephen Hemminger
2019-07-05 14:34  3%     ` Olivier Matz
2019-07-05 15:45  0%       ` Richardson, Bruce
2019-05-20 10:59     [dpdk-dev] [PATCH v3 1/2] examples/ip_fragmentation: Enabling IP checksum offload in mbuf Sunil Kumar Kori
2019-07-08  4:32  9% ` [dpdk-dev] [PATCH v4 1/3] lib/librte_ip_frag: remove IP checkum offload flag jerinj
2019-07-08  9:07  3%   ` Thomas Monjalon
2019-05-21 14:01     [dpdk-dev] 18.11.2 (LTS) patches review and test Kevin Traynor
2019-06-04  8:11  1% ` Pei Zhang
2019-05-23  7:43     [dpdk-dev] [PATCH] devtools: better freebsd support Olivier Matz
2019-07-05 13:58  6% ` [dpdk-dev] [PATCH v2] " Olivier Matz
2019-07-09 11:05  0%   ` Musatescu, Flavia
2019-05-25 18:43     [dpdk-dev] [RFC PATCH 0/2] introduce __rte_internal tag Neil Horman
2019-05-25 18:43     ` [dpdk-dev] [RFC PATCH 1/2] Add __rte_internal tag for functions and version target Neil Horman
2019-06-05 16:14  0%   ` [dpdk-dev] [EXT] " Jerin Jacob Kollanukkaran
2019-06-05 16:24  0% ` [dpdk-dev] [EXT] [RFC PATCH 0/2] introduce __rte_internal tag Jerin Jacob Kollanukkaran
2019-06-05 16:45  0%   ` Bruce Richardson
2019-06-05 18:11  0%     ` Neil Horman
2019-06-06  9:44  0%       ` Jerin Jacob Kollanukkaran
2019-06-06 11:34  3%         ` Neil Horman
2019-06-06 12:04  0%           ` Jerin Jacob Kollanukkaran
2019-06-06 13:18  0%             ` Wiles, Keith
2019-06-06 13:43  3%               ` Neil Horman
2019-06-06 13:53  0%                 ` Wiles, Keith
2019-06-06 14:46  0%                   ` Neil Horman
2019-06-06 13:35  0%             ` Neil Horman
2019-06-06 14:02  0%               ` Jerin Jacob Kollanukkaran
2019-06-06 15:03  3%                 ` Neil Horman
2019-06-06 15:14  0%                   ` Jerin Jacob Kollanukkaran
2019-06-07 15:42  3%                   ` Ray Kinsella
2019-06-07 18:21  0%                     ` Wiles, Keith
2019-06-12 20:38  4% ` [dpdk-dev] [PATCH v1 0/9] dpdk: " Neil Horman
2019-06-12 20:38  3%   ` [dpdk-dev] [PATCH v1 1/9] Add __rte_internal tag for functions and version target Neil Horman
2019-06-12 20:38  3%   ` [dpdk-dev] [PATCH v1 2/9] Exempt INTERNAL symbols from checking Neil Horman
2019-06-13  7:53  3%   ` [dpdk-dev] [PATCH v1 0/9] dpdk: introduce __rte_internal tag David Marchand
2019-06-13 10:30  0%     ` Neil Horman
2019-06-13 14:23  4% ` [dpdk-dev] [PATCH v2 0/10] " Neil Horman
2019-06-13 14:23  3%   ` [dpdk-dev] [PATCH v2 01/10] Add __rte_internal tag for functions and version target Neil Horman
2019-06-13 14:23  3%   ` [dpdk-dev] [PATCH v2 03/10] Exempt INTERNAL symbols from checking Neil Horman
2019-05-28 11:51     [dpdk-dev] [PATCH 0/2] Add ABI Version Testing to app/test Ray Kinsella
2019-05-28 11:51  3% ` [dpdk-dev] [PATCH 2/2] app/test: LPMv4 ABI Version Testing Ray Kinsella
2019-05-29 13:50  4%   ` Aaron Conole
2019-05-28 12:08     ` [dpdk-dev] [PATCH 0/2] Add ABI Version Testing to app/test Bruce Richardson
2019-05-28 14:01  9%   ` Ray Kinsella
2019-05-28 12:05     [dpdk-dev] [PATCH 01/27] sched: update macros for flexible config Lukasz Krakowiak
2019-06-25 15:31     ` [dpdk-dev] [PATCH v2 00/28] sched: feature enhancements Jasvinder Singh
2019-06-25 15:32  4%   ` [dpdk-dev] [PATCH v2 28/28] sched: add release note Jasvinder Singh
2019-06-26 21:31  3%     ` Thomas Monjalon
2019-06-27 10:50  0%       ` Singh, Jasvinder
2019-05-29 15:41     [dpdk-dev] [PATCH 0/4] Enhance CPU flag support Bruce Richardson
2019-05-29 15:41     ` [dpdk-dev] [PATCH 3/4] eal: allow checking CPU flags by name Bruce Richardson
2019-06-27 13:22       ` David Marchand
2019-06-28 12:40         ` Bruce Richardson
2019-06-28 13:34  3%       ` David Marchand
2019-05-29 16:39     [dpdk-dev] [PATCH 0/2] Make meson configurable Ilya Maximets
     [not found]     ` <CGME20190529164009eucas1p289f1dcf87012ecf049efc8eee2c2ea9d@eucas1p2.samsung.com>
2019-05-29 16:39       ` [dpdk-dev] [PATCH 2/2] meson: make build configurable Ilya Maximets
2019-05-29 20:37         ` Luca Boccassi
2019-05-30 10:03           ` Ilya Maximets
2019-05-30 11:06  3%         ` Luca Boccassi
2019-05-30 11:59  0%           ` Ilya Maximets
2019-05-30 13:30  0%             ` Luca Boccassi
2019-05-30  1:19     [dpdk-dev] [PATCH 1/2] eventdev: replace mbufs with events in Rx callback Nikhil Rao
2019-06-13 23:28  3% ` [dpdk-dev] [PATCH v2] eventdev: change Rx adapter callback and stats structure Nikhil Rao
2019-06-24 23:16 15% ` [dpdk-dev] [PATCH v3] " Nikhil Rao
2019-05-31 16:14  2% [dpdk-dev] [RFC 1/5] security: MACSEC infrastructure data declarations Igor Russkikh
2019-06-03 14:50     [dpdk-dev] [PATCH 0/9] add QAT support for digest encrypted Nowak
2019-06-07 10:05     ` [dpdk-dev] [PATCH v2 00/10] cryptodev: support encrypted-digest use-cases Damian Nowak
2019-06-07 10:06  4%   ` [dpdk-dev] [PATCH v2 10/10] doc: update release notes for 19.08 Damian Nowak
2019-06-13  8:14  0%     ` Akhil Goyal
2019-07-03 11:15       ` [dpdk-dev] [PATCH v3 0/8] cryptodev: support encrypted-digest use-cases Damian Nowak
2019-07-03 11:15  4%     ` [dpdk-dev] [PATCH v3 2/8] cryptodev: add digest encrypted feature flag Damian Nowak
2019-06-03 15:25  5% [dpdk-dev] [PATCH] cryptodev: add ff_disable field in cryptodev config Anoob Joseph
2019-06-25  5:39  4% ` [dpdk-dev] [PATCH v2] " Anoob Joseph
2019-06-03 17:32     [dpdk-dev] [PATCH 00/39] adding eventmode helper library Anoob Joseph
2019-06-03 17:32     ` [dpdk-dev] [PATCH 16/39] eventdev: add eventmode CL options framework Anoob Joseph
2019-06-10 10:19  3%   ` Jerin Jacob Kollanukkaran
2019-06-17 10:14  0%     ` Anoob Joseph
2019-06-03 21:32     [dpdk-dev] [RFC 1/3] ethdev: extend flow metadata Yongseok Koh
2019-06-09 14:23  3% ` Andrew Rybchenko
2019-06-10  3:19  0%   ` Wang, Haiyue
2019-06-10  7:20  0%     ` Andrew Rybchenko
2019-06-11  0:06  0%       ` Yongseok Koh
2019-06-19  9:05  0%         ` Andrew Rybchenko
2019-07-04 23:21     ` [dpdk-dev] [PATCH] " Yongseok Koh
2019-07-10  9:31  3%   ` Olivier Matz
2019-07-10  9:55  4%     ` Bruce Richardson
2019-07-10 10:07  3%       ` Olivier Matz
2019-07-10 12:01  4%         ` Bruce Richardson
2019-07-10 12:26  3%           ` Thomas Monjalon
2019-06-05 15:03  3% [dpdk-dev] DPDK techboard minutes of May 22 Ferruh Yigit
2019-06-05 20:22     [dpdk-dev] [PATCH 00/10] enhance meson summary - list disabled components Bruce Richardson
2019-06-05 20:22  4% ` [dpdk-dev] [PATCH 01/10] build: print list of disabled components for meson build Bruce Richardson
2019-06-06 18:33     [dpdk-dev] [PATCH v1 1/2] lib/ring: add enqueue-dequeue callabck Vipin Varghese
2019-06-07  6:03  3% ` Honnappa Nagarahalli
2019-06-10  5:12  0%   ` Varghese, Vipin
2019-06-11  4:17  0%     ` Honnappa Nagarahalli
2019-07-04  5:04  0%       ` Varghese, Vipin
     [not found]     <CGME20190606100234eucas1p2a73029a37495cde21bce3b9a3b023ac4@eucas1p2.samsung.com>
2019-05-30 13:25     ` [dpdk-dev] [PATCH] eal: fix positive error codes from probe/remove Ilya Maximets
2019-06-06 10:02       ` [dpdk-dev] [PATCH v2] " Ilya Maximets
2019-06-07  8:32  3%     ` David Marchand
2019-06-26 21:03  0%       ` Thomas Monjalon
2019-06-08  0:19     [dpdk-dev] [PATCH 0/9] kni: cleanups and improvements Stephen Hemminger
2019-06-08  0:19  3% ` [dpdk-dev] [PATCH 3/9] kni: drop unused field Stephen Hemminger
2019-06-08  0:19  3% ` [dpdk-dev] [PATCH 5/9] kni: drop unused group_id and device_id Stephen Hemminger
2019-06-10  4:33  3% [dpdk-dev] [PATCH 1/2] eventdev: replace mbufs with events in Rx callback Jerin Jacob Kollanukkaran
2019-06-10 17:51     [dpdk-dev] [PATCH v2 0/7] kni: cleanups and improvements Stephen Hemminger
2019-06-10 17:51  3% ` [dpdk-dev] [PATCH v2 4/7] kni: drop unused fields Stephen Hemminger
2019-06-18 16:16     ` [dpdk-dev] [PATCH v3 0/8] kni: fixes and cleanups Stephen Hemminger
2019-06-18 16:16  4%   ` [dpdk-dev] [PATCH v3 4/8] kni: drop unused fields Stephen Hemminger
2019-06-19 18:57     ` [dpdk-dev] [PATCH v3 0/8] kni: cleanups and fixes Stephen Hemminger
2019-06-19 18:57  4%   ` [dpdk-dev] [PATCH v3 4/8] kni: drop unused fields Stephen Hemminger
2019-06-19 18:59     ` [dpdk-dev] [PATCH v4 0/8] kni: fixes and cleanups Stephen Hemminger
2019-06-19 18:59  4%   ` [dpdk-dev] [PATCH v4 4/8] kni: drop unused fields Stephen Hemminger
2019-06-11 18:42  1% [dpdk-dev] [dpdk-announce] DPDK 18.11.2 (LTS) released Kevin Traynor
2019-06-20 17:07  1% ` Ju-Hyoung Lee
2019-06-19 15:14     [dpdk-dev] [PATCH 00/28] vhost: add virtio-vhost-user transport Nikos Dragazis
2019-06-19 15:14  2% ` [dpdk-dev] [PATCH 18/28] drivers/virtio_vhost_user: add virtio PCI framework Nikos Dragazis
     [not found]     ` <CGME20190620113240eucas1p22ca4faa64a36bbb7aec38a81298ade56@eucas1p2.samsung.com>
2019-06-20 11:32  3%   ` [dpdk-dev] [PATCH 00/28] vhost: add virtio-vhost-user transport Ilya Maximets
2019-06-20 23:44  0%     ` Nikos Dragazis
2019-06-19 17:08     [dpdk-dev] [PATCH 0/2] rawdev autotest fixes Bruce Richardson
2019-06-21 15:56     ` [dpdk-dev] [PATCH v2 0/4] fixes and improvements for rawdev Bruce Richardson
2019-06-21 15:56  3%   ` [dpdk-dev] [PATCH v2 4/4] rawdev: pass device id as parameter to selftest Bruce Richardson
2019-07-04  9:33  0%     ` Shreyansh Jain
2019-06-20  7:25  2% [dpdk-dev] [RFC] ethdev: reserve the RX offload most-significant bits for PMD scartch Haiyue Wang
2019-06-20 18:30  0% ` Andrew Rybchenko
2019-06-21  1:12  3%   ` Wang, Haiyue
2019-06-21  7:33  0%     ` Andrew Rybchenko
2019-06-21  7:37  3%       ` Wang, Haiyue
2019-06-21  7:39  0%         ` Andrew Rybchenko
2019-06-21  7:43  2%           ` Wang, Haiyue
2019-06-21 15:14  3%             ` Stephen Hemminger
2019-06-21 16:37  0%               ` Wang, Haiyue
2019-06-21 16:45  3%                 ` David Marchand
2019-06-21 16:57  3%                   ` Wang, Haiyue
2019-06-20 18:35  0% ` Stephen Hemminger
2019-06-21  0:55  0%   ` Wang, Haiyue
     [not found]     <VI1PR0401MB2541F07E6E640ED569918E6089E40@VI1PR0401MB2541.eurprd04.prod.outlook.com>
2019-06-20  8:33  4% ` [dpdk-dev] DPDK Techboard minutes of June 6 Hemant Agrawal
2019-06-21 16:59     [dpdk-dev] [PATCH v3 01/10] baseband/turbo_sw: baseband/turbo_sw: dependency patch Nicolas Chautru
2019-06-24  2:52     ` [dpdk-dev] [PATCH v4 00/10] bbdev: adding support in BBDEV for 5GNR FEC Nicolas Chautru
2019-06-24  2:52  8%   ` [dpdk-dev] [PATCH v4 10/10] doc: announce bbdev changes Nicolas Chautru
2019-06-30 23:04  0%     ` Mokhtar, Amr
2019-07-01 11:14  4%     ` Akhil Goyal
2019-07-01 18:14  3%       ` Chautru, Nicolas
2019-07-01 19:17  3%         ` Thomas Monjalon
2019-07-01 20:27  4%           ` Chautru, Nicolas
2019-07-01 20:38  3%             ` Bruce Richardson
2019-06-24  2:52     [dpdk-dev] [PATCH v4 01/10] baseband/turbo_sw: baseband/turbo_sw: dependency patch Nicolas Chautru
2019-07-01 18:06     ` [dpdk-dev] [PATCH v5 0/7] bbdev: adding support in BBDEV for 5GNR FEC Nicolas Chautru
2019-07-01 18:06  3%   ` [dpdk-dev] [PATCH v5 2/7] bbdev: extension of BBDEV API for 5G FEC Nicolas Chautru
2019-07-01 18:06  2%   ` [dpdk-dev] [PATCH v5 4/7] baseband/turbo_sw: extension of turbosw PMD for 5G Nicolas Chautru
2019-07-03 15:24     ` [dpdk-dev] [PATCH v6 0/7] bbdev: adding support in BBDEV for 5GNR FEC Nicolas Chautru
2019-07-03 15:24  3%   ` [dpdk-dev] [PATCH v6 2/7] bbdev: extension of BBDEV API for 5G FEC Nicolas Chautru
2019-07-03 15:24  2%   ` [dpdk-dev] [PATCH v6 4/7] baseband/turbo_sw: extension of turbosw PMD for 5G Nicolas Chautru
2019-06-24 15:40     [dpdk-dev] [PATCH 0/4] ethdev: add GRE key field to flow API Xiaoyu Min
2019-07-02  9:45     ` [dpdk-dev] [PATCH v4 0/4] match on GRE's key Xiaoyu Min
2019-07-02  9:45       ` [dpdk-dev] [PATCH v4 1/4] ethdev: add GRE key field to flow API Xiaoyu Min
2019-07-03 15:25  4%     ` Adrien Mazarguil
2019-07-04  2:43  0%       ` Jack Min
2019-06-25 10:33  3% [dpdk-dev] [PATCH 00/39] adding eventmode helper library Jerin Jacob Kollanukkaran
2019-06-27  5:28  0% ` Anoob Joseph
2019-06-28  3:37  0%   ` Jerin Jacob Kollanukkaran
2019-06-28  8:02  0%     ` Mattias Rönnblom
2019-06-28  8:40  0%     ` Thomas Monjalon
2019-06-28  9:07  0%       ` Mattias Rönnblom
2019-06-28 11:34  0%       ` [dpdk-dev] [EXT] " Anoob Joseph
2019-07-02 14:17  0%         ` Anoob Joseph
2019-07-02 14:26  0%           ` Jerin Jacob Kollanukkaran
2019-06-26 10:18  3% [dpdk-dev] minutes of techboard meeting 2019-05-15 Bruce Richardson
2019-06-26 16:38     [dpdk-dev] [PATCH] [v1]vhost: support inflight share memory protocol feature JinYu
2019-07-05  8:47  3% ` Maxime Coquelin
2019-07-08  7:23  0%   ` Yu, Jin
2019-06-26 22:32  4% [dpdk-dev] [PATCH] malloc: deprecate unused set limit Stephen Hemminger
2019-07-02  4:52  0% [dpdk-dev] [PATCH v3] eventdev: change Rx adapter callback and stats structure Jerin Jacob Kollanukkaran
2019-07-03  5:45     [dpdk-dev] [RFC PATCH] bus/pci: avoid depending on private value in kernel source Tiwei Bie
2019-07-03  7:02     ` David Marchand
2019-07-03  7:33       ` Tiwei Bie
2019-07-03  7:36         ` David Marchand
2019-07-03  7:56           ` Tiwei Bie
2019-07-03  8:01             ` David Marchand
2019-07-03  8:15               ` Tiwei Bie
2019-07-03  8:26  3%             ` David Marchand
2019-07-03  8:59  0%               ` Tiwei Bie
2019-07-03  9:10  0%                 ` David Marchand
2019-07-03  9:25  0%                   ` Tiwei Bie
2019-07-04  4:43  4% [dpdk-dev] [PATCH] doc: announce ABI change for RSS hash funtion simei
2019-07-04  4:46     [dpdk-dev] [RFC] ethdev: support symmetric hash function simei
2019-07-04  9:06  3% ` Adrien Mazarguil
2019-07-04 12:48  3%   ` Zhang, Qi Z
2019-07-04 13:19  3%     ` Adrien Mazarguil
2019-07-04  4:46  4% [dpdk-dev] [PATCH] doc: announce ABI change for rte flow RSS action simei
2019-07-04  4:47     [dpdk-dev] [RFC] ethdev: support input set change by " simei
2019-07-04  9:07  3% ` Adrien Mazarguil
2019-07-04 13:55  0%   ` Zhang, Qi Z
2019-07-04 14:08  3%     ` Adrien Mazarguil
2019-07-09  5:41  3%       ` Zhang, Qi Z
2019-07-09  8:19  0%         ` Jerin Jacob Kollanukkaran
2019-07-04  6:56     [dpdk-dev] [PATCH v3] net/i40e: i40e get link status update from ipn3ke Andy Pei
2019-07-08  3:03     ` [dpdk-dev] [PATCH v4] " Andy Pei
2019-07-08  7:27  3%   ` Zhang, Qi Z
2019-07-04 12:26 11% [dpdk-dev] [PATCH] Changes to ABI Policy introducing major ABI versions Ray Kinsella
2019-07-04 12:26 31% ` [dpdk-dev] [PATCH] doc: " Ray Kinsella
2019-07-05 11:15     [dpdk-dev] [PATCH v7 1/6] app/test-compress-perf: add weak functions for multi-cores test Fiona Trahe
2019-07-08 18:16     ` [dpdk-dev] [PATCH v8 0/7] add multiple cores feature to test-compress-perf Artur Trybula
2019-07-08 18:16  3%   ` [dpdk-dev] [PATCH v8 4/7] app/test-compress-perf: add benchmark test case Artur Trybula
2019-07-05 17:26     [dpdk-dev] [PATCH v5 0/9] Make shared memory config non-public Anatoly Burakov
2019-07-05 13:10     ` [dpdk-dev] [PATCH v4 0/8] " Anatoly Burakov
2019-06-27 11:38       ` [dpdk-dev] [PATCH v3 00/14] " Anatoly Burakov
2019-06-25 16:05         ` [dpdk-dev] [PATCH v2 " Anatoly Burakov
2019-05-29 16:30           ` [dpdk-dev] [PATCH 00/25] " Anatoly Burakov
2019-06-25 16:05  6%         ` [dpdk-dev] [PATCH v2 09/14] eal: hide shared memory config Anatoly Burakov
2019-06-25 16:05  3%         ` [dpdk-dev] [PATCH v2 14/14] eal: prevent different primary/secondary process versions Anatoly Burakov
2019-06-27 11:39  8%       ` [dpdk-dev] [PATCH v3 09/14] eal: hide shared memory config Anatoly Burakov
2019-06-27 11:39  3%       ` [dpdk-dev] [PATCH v3 14/14] eal: prevent different primary/secondary process versions Anatoly Burakov
2019-07-03  9:38         ` [dpdk-dev] [PATCH v3 00/14] Make shared memory config non-public David Marchand
2019-07-04  8:09  3%       ` David Marchand
2019-07-04 19:52  0%         ` Thomas Monjalon
2019-07-05 13:10  7%     ` [dpdk-dev] [PATCH v4 4/8] eal: hide shared memory config Anatoly Burakov
2019-07-05 17:26  7%   ` [dpdk-dev] [PATCH v5 4/9] " Anatoly Burakov
2019-07-05 17:26  3%   ` [dpdk-dev] [PATCH v5 9/9] eal: prevent different primary/secondary process versions Anatoly Burakov
2019-07-09 14:58  5% [dpdk-dev] [PATCH] doc: deprecation notice for change of ether struct alignment Bruce Richardson
2019-07-09 14:59  0% ` Stephen Hemminger
2019-07-09 15:02  0%   ` Bruce Richardson
2019-07-10  9:29  4% [dpdk-dev] [RFC] mbuf: support dynamic fields and flags Olivier Matz
2019-07-10  9:57     [dpdk-dev] devtools: fix symbol change file matching Bing Zhao
2019-07-10 11:10  0% ` Neil Horman

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).