[v4,2/2] net/tap: fix buffer overflow for ptypes list through driver API update

Message ID 20240104175111.2190075-3-venkatx.sivaramakrishnan@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series [v4,1/2] net/tap: fix buffer overflow for ptypes list through updation of last element. |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/Intel-compilation success Compilation OK
ci/github-robot: build success github build: passed
ci/intel-Testing success Testing PASS
ci/intel-Functional success Functional PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-abi-testing success Testing PASS
ci/iol-compile-amd64-testing success Testing PASS
ci/iol-unit-amd64-testing success Testing PASS
ci/iol-unit-arm64-testing success Testing PASS
ci/iol-sample-apps-testing success Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-compile-arm64-testing success Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-intel-Functional success Functional Testing PASS

Commit Message

Sivaramakrishnan Venkat Jan. 4, 2024, 5:51 p.m. UTC
  Incorrect ptypes list causes buffer overflow for Address Sanitizer
run. Previously, the last element in the ptypes lists to be
"RTE_PTYPE_UNKNOWN" for rte_eth_dev_get_supported_ptypes(), but this was
not clearly documented and many PMDs did not follow this implementation.
Instead, the dev_supported_ptypes_get() function pointer now returns the
number of elements to eliminate the need for "RTE_PTYPE_UNKNOWN"
as the last item.

Fixes: 47909357a069 ("ethdev: make device operations struct private")
Cc: ferruh.yigit@intel.com
Cc: stable@dpdk.org

Signed-off-by: Sivaramakrishnan Venkat <venkatx.sivaramakrishnan@intel.com>
---
 drivers/net/atlantic/atl_ethdev.c      | 13 ++++++++-----
 drivers/net/axgbe/axgbe_ethdev.c       | 13 ++++++++-----
 drivers/net/bnxt/bnxt_ethdev.c         |  7 ++++---
 drivers/net/cnxk/cnxk_ethdev.h         |  3 ++-
 drivers/net/cnxk/cnxk_lookup.c         |  7 ++++---
 drivers/net/cpfl/cpfl_ethdev.c         |  7 ++++---
 drivers/net/cxgbe/cxgbe_ethdev.c       | 10 ++++++----
 drivers/net/cxgbe/cxgbe_pfvf.h         |  3 ++-
 drivers/net/dpaa/dpaa_ethdev.c         | 11 +++++++----
 drivers/net/dpaa2/dpaa2_ethdev.c       | 10 ++++++----
 drivers/net/e1000/igb_ethdev.c         | 13 ++++++++-----
 drivers/net/enetc/enetc_ethdev.c       |  7 ++++---
 drivers/net/enic/enic_ethdev.c         | 17 ++++++++++-------
 drivers/net/failsafe/failsafe_ops.c    |  5 +++--
 drivers/net/fm10k/fm10k_ethdev.c       | 15 +++++++++------
 drivers/net/hns3/hns3_rxtx.c           | 16 +++++++++-------
 drivers/net/hns3/hns3_rxtx.h           |  3 ++-
 drivers/net/i40e/i40e_rxtx.c           | 11 +++++++----
 drivers/net/i40e/i40e_rxtx.h           |  3 ++-
 drivers/net/iavf/iavf_ethdev.c         | 10 ++++++----
 drivers/net/ice/ice_dcf_ethdev.c       |  7 ++++---
 drivers/net/ice/ice_rxtx.c             | 23 ++++++++++++++---------
 drivers/net/ice/ice_rxtx.h             |  3 ++-
 drivers/net/idpf/idpf_ethdev.c         |  7 ++++---
 drivers/net/igc/igc_ethdev.c           | 10 ++++++----
 drivers/net/ionic/ionic_rxtx.c         |  7 ++++---
 drivers/net/ionic/ionic_rxtx.h         |  3 ++-
 drivers/net/ixgbe/ixgbe_ethdev.c       | 18 ++++++++++++------
 drivers/net/mana/mana.c                |  7 ++++---
 drivers/net/mlx4/mlx4.h                |  3 ++-
 drivers/net/mlx4/mlx4_ethdev.c         | 17 ++++++++++-------
 drivers/net/mlx5/mlx5.h                |  3 ++-
 drivers/net/mlx5/mlx5_ethdev.c         | 11 +++++++----
 drivers/net/mvneta/mvneta_ethdev.c     |  7 ++++---
 drivers/net/mvpp2/mrvl_ethdev.c        |  7 ++++---
 drivers/net/netvsc/hn_var.h            |  3 ++-
 drivers/net/netvsc/hn_vf.c             |  5 +++--
 drivers/net/nfp/nfp_net_common.c       | 15 ++++++++++-----
 drivers/net/nfp/nfp_net_common.h       |  3 ++-
 drivers/net/ngbe/ngbe_ethdev.c         |  9 ++++++---
 drivers/net/ngbe/ngbe_ethdev.h         |  3 ++-
 drivers/net/ngbe/ngbe_ptypes.c         |  3 ++-
 drivers/net/ngbe/ngbe_ptypes.h         |  2 +-
 drivers/net/octeontx/octeontx_ethdev.c | 11 +++++++----
 drivers/net/pfe/pfe_ethdev.c           | 11 +++++++----
 drivers/net/qede/qede_ethdev.c         | 11 +++++++----
 drivers/net/sfc/sfc_dp_rx.h            |  2 +-
 drivers/net/sfc/sfc_ef10.h             |  3 ++-
 drivers/net/sfc/sfc_ef100_rx.c         |  7 ++++---
 drivers/net/sfc/sfc_ef10_rx.c          | 11 ++++++-----
 drivers/net/sfc/sfc_ethdev.c           |  5 +++--
 drivers/net/sfc/sfc_rx.c               |  7 ++++---
 drivers/net/tap/rte_eth_tap.c          |  7 ++++---
 drivers/net/thunderx/nicvf_ethdev.c    | 10 +++++-----
 drivers/net/txgbe/txgbe_ethdev.c       |  9 ++++++---
 drivers/net/txgbe/txgbe_ethdev.h       |  3 ++-
 drivers/net/txgbe/txgbe_ptypes.c       |  6 +++---
 drivers/net/txgbe/txgbe_ptypes.h       |  2 +-
 drivers/net/vmxnet3/vmxnet3_ethdev.c   | 14 +++++++++-----
 lib/ethdev/ethdev_driver.h             |  3 ++-
 lib/ethdev/rte_ethdev.c                | 10 ++++++----
 61 files changed, 299 insertions(+), 193 deletions(-)
  

Comments

Ferruh Yigit Jan. 11, 2024, 3:12 p.m. UTC | #1
On 1/4/2024 5:51 PM, Sivaramakrishnan Venkat wrote:
> Incorrect ptypes list causes buffer overflow for Address Sanitizer
> run. Previously, the last element in the ptypes lists to be
> "RTE_PTYPE_UNKNOWN" for rte_eth_dev_get_supported_ptypes(), but this was
> not clearly documented and many PMDs did not follow this implementation.
> Instead, the dev_supported_ptypes_get() function pointer now returns the
> number of elements to eliminate the need for "RTE_PTYPE_UNKNOWN"
> as the last item.
> 
> Fixes: 47909357a069 ("ethdev: make device operations struct private")
> Cc: ferruh.yigit@intel.com
> Cc: stable@dpdk.org
> 

I think this is not fix, your previous patch fixes mentioned issue, but
this patch improved code to make sure it will be correct in the future.

Can you please update the commit log accordingly, remove fixes and
stable tag and patch title can be something like:
"drivers/net: return number of types in get supported ptypes"


> Signed-off-by: Sivaramakrishnan Venkat <venkatx.sivaramakrishnan@intel.com>
> ---
>  

<...>

> 
> diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
> index 3a028f4290..bc087738e4 100644
> --- a/drivers/net/atlantic/atl_ethdev.c
> +++ b/drivers/net/atlantic/atl_ethdev.c
> @@ -43,7 +43,8 @@ static int atl_dev_stats_reset(struct rte_eth_dev *dev);
>  static int atl_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
>  			      size_t fw_size);
>  
> -static const uint32_t *atl_dev_supported_ptypes_get(struct rte_eth_dev *dev);
> +static const uint32_t *atl_dev_supported_ptypes_get(struct rte_eth_dev *dev,
> +	size_t *no_of_elements);
>  
>  static int atl_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
>  
> @@ -1132,7 +1133,8 @@ atl_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
>  }
>  
>  static const uint32_t *
> -atl_dev_supported_ptypes_get(struct rte_eth_dev *dev)
> +atl_dev_supported_ptypes_get(struct rte_eth_dev *dev,
> +	size_t *no_of_elements)
>

Can be single line, no need to break the line.
Same for some other drivers, can you please check all.

>  {
>  	static const uint32_t ptypes[] = {
>  		RTE_PTYPE_L2_ETHER,
> @@ -1143,12 +1145,13 @@ atl_dev_supported_ptypes_get(struct rte_eth_dev *dev)
>  		RTE_PTYPE_L4_TCP,
>  		RTE_PTYPE_L4_UDP,
>  		RTE_PTYPE_L4_SCTP,
> -		RTE_PTYPE_L4_ICMP,
> -		RTE_PTYPE_UNKNOWN
> +		RTE_PTYPE_L4_ICMP
>

Better to keep trailing ',' to reduce change when new ptypes appended in
the future, like:
"RTE_PTYPE_L4_ICMP,"

<...>

> @@ -348,7 +348,8 @@ dpaa_eth_dev_configure(struct rte_eth_dev *dev)
>  }
>  
>  static const uint32_t *
> -dpaa_supported_ptypes_get(struct rte_eth_dev *dev)
> +dpaa_supported_ptypes_get(struct rte_eth_dev *dev,
> +				size_t *no_of_elements)
>  {
>  	static const uint32_t ptypes[] = {
>  		RTE_PTYPE_L2_ETHER,
> @@ -363,14 +364,16 @@ dpaa_supported_ptypes_get(struct rte_eth_dev *dev)
>  		RTE_PTYPE_L4_TCP,
>  		RTE_PTYPE_L4_UDP,
>  		RTE_PTYPE_L4_SCTP,
> -		RTE_PTYPE_TUNNEL_ESP,
> -		RTE_PTYPE_UNKNOWN
> +		RTE_PTYPE_TUNNEL_ESP
>  	};
>  
>  	PMD_INIT_FUNC_TRACE();
>  
> -	if (dev->rx_pkt_burst == dpaa_eth_queue_rx)
> +	if (dev->rx_pkt_burst == dpaa_eth_queue_rx) {
> +		*no_of_elements = RTE_DIM(ptypes);
>  		return ptypes;
> +	}
> +	*no_of_elements = 0;


No need to set it to '0' when NULL returned, it is already 0 by default.
There are other drivers doing this, can you please check all?

<...>

> @@ -2261,19 +2261,22 @@ ice_dev_supported_ptypes_get(struct rte_eth_dev *dev)
>  		RTE_PTYPE_INNER_L4_UDP,
>  		RTE_PTYPE_TUNNEL_GTPC,
>  		RTE_PTYPE_TUNNEL_GTPU,
> -		RTE_PTYPE_L2_ETHER_PPPOE,
> -		RTE_PTYPE_UNKNOWN
> +		RTE_PTYPE_L2_ETHER_PPPOE
>  	};
>  
> -	if (ad->active_pkg_type == ICE_PKG_TYPE_COMMS)
> +	if (ad->active_pkg_type == ICE_PKG_TYPE_COMMS) {
> +		*no_of_elements = RTE_DIM(ptypes_comms);
>  		ptypes = ptypes_comms;
> -	else
> +	} else {
> +		*no_of_elements = RTE_DIM(ptypes_os);
>  		ptypes = ptypes_os;
> +	}
>  
>  	if (dev->rx_pkt_burst == ice_recv_pkts ||
>  	    dev->rx_pkt_burst == ice_recv_pkts_bulk_alloc ||
> -	    dev->rx_pkt_burst == ice_recv_scattered_pkts)
> +	    dev->rx_pkt_burst == ice_recv_scattered_pkts) {
>  		return ptypes;
> +	}
>

No need to add { }, same below.

<...>


> @@ -3978,7 +3979,8 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
>  }
>  
>  static const uint32_t *
> -ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev)
> +ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev,
> +		     size_t *no_of_elements)
>  {
>  	static const uint32_t ptypes[] = {
>  		/* For non-vec functions,
> @@ -3998,21 +4000,25 @@ ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev)
>  		RTE_PTYPE_INNER_L3_IPV6,
>  		RTE_PTYPE_INNER_L3_IPV6_EXT,
>  		RTE_PTYPE_INNER_L4_TCP,
> -		RTE_PTYPE_INNER_L4_UDP,
> -		RTE_PTYPE_UNKNOWN
> +		RTE_PTYPE_INNER_L4_UDP
>  	};
>  
>  	if (dev->rx_pkt_burst == ixgbe_recv_pkts ||
>  	    dev->rx_pkt_burst == ixgbe_recv_pkts_lro_single_alloc ||
>  	    dev->rx_pkt_burst == ixgbe_recv_pkts_lro_bulk_alloc ||
> -	    dev->rx_pkt_burst == ixgbe_recv_pkts_bulk_alloc)
> +	    dev->rx_pkt_burst == ixgbe_recv_pkts_bulk_alloc) {
> +		*no_of_elements = RTE_DIM(ptypes);
>  		return ptypes;
> +	}
>  
>  #if defined(RTE_ARCH_X86) || defined(__ARM_NEON)
>  	if (dev->rx_pkt_burst == ixgbe_recv_pkts_vec ||
> -	    dev->rx_pkt_burst == ixgbe_recv_scattered_pkts_vec)
> +	    dev->rx_pkt_burst == ixgbe_recv_scattered_pkts_vec) {
> +		*no_of_elements = (sizeof(ptypes) / sizeof(uint32_t));
>

Why not use 'RTE_DIM()' here?

<...>


> diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
> index b482cd12bb..9b03d27e62 100644
> --- a/lib/ethdev/ethdev_driver.h
> +++ b/lib/ethdev/ethdev_driver.h
> @@ -448,7 +448,8 @@ typedef int (*eth_dev_infos_get_t)(struct rte_eth_dev *dev,
>  				   struct rte_eth_dev_info *dev_info);
>  
>  /** @internal Get supported ptypes of an Ethernet device. */
> -typedef const uint32_t *(*eth_dev_supported_ptypes_get_t)(struct rte_eth_dev *dev);
> +typedef const uint32_t *(*eth_dev_supported_ptypes_get_t)(struct rte_eth_dev *dev,
> +				   size_t *no_of_elements);
>  

Can you please add doxygen comments, and document new paramter there.
There are samples in same file, like 'eth_promiscuous_enable_t' one.


Thanks,
Ferruh
  
Andrew Rybchenko Jan. 11, 2024, 4:29 p.m. UTC | #2
On 1/4/24 20:51, Sivaramakrishnan Venkat wrote:
> Incorrect ptypes list causes buffer overflow for Address Sanitizer
> run. Previously, the last element in the ptypes lists to be
> "RTE_PTYPE_UNKNOWN" for rte_eth_dev_get_supported_ptypes(), but this was
> not clearly documented and many PMDs did not follow this implementation.
> Instead, the dev_supported_ptypes_get() function pointer now returns the
> number of elements to eliminate the need for "RTE_PTYPE_UNKNOWN"
> as the last item.
> 
> Fixes: 47909357a069 ("ethdev: make device operations struct private")
> Cc: ferruh.yigit@intel.com
> Cc: stable@dpdk.org
> 
> Signed-off-by: Sivaramakrishnan Venkat <venkatx.sivaramakrishnan@intel.com>

[snip]

> @@ -3956,7 +3958,7 @@ rte_eth_dev_set_ptypes(uint16_t port_id, uint32_t ptype_mask,
>   	 * set_ptypes array is insufficient fill it partially.
>   	 */
>   	for (i = 0, j = 0; set_ptypes != NULL &&
> -				(all_ptypes[i] != RTE_PTYPE_UNKNOWN); ++i) {
> +				(all_ptypes[i] < no_of_elements); ++i) {

condition here looks wrong, it should be i < no_of_elements

>   		if (ptype_mask & all_ptypes[i]) {
>   			if (j < num - 1) {
>   				set_ptypes[j] = all_ptypes[i];
  

Patch

diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
index 3a028f4290..bc087738e4 100644
--- a/drivers/net/atlantic/atl_ethdev.c
+++ b/drivers/net/atlantic/atl_ethdev.c
@@ -43,7 +43,8 @@  static int atl_dev_stats_reset(struct rte_eth_dev *dev);
 static int atl_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
 			      size_t fw_size);
 
-static const uint32_t *atl_dev_supported_ptypes_get(struct rte_eth_dev *dev);
+static const uint32_t *atl_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+	size_t *no_of_elements);
 
 static int atl_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
 
@@ -1132,7 +1133,8 @@  atl_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 }
 
 static const uint32_t *
-atl_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+atl_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+	size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -1143,12 +1145,13 @@  atl_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_L4_TCP,
 		RTE_PTYPE_L4_UDP,
 		RTE_PTYPE_L4_SCTP,
-		RTE_PTYPE_L4_ICMP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_ICMP
 	};
 
-	if (dev->rx_pkt_burst == atl_recv_pkts)
+	if (dev->rx_pkt_burst == atl_recv_pkts) {
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
+	}
 
 	return NULL;
 }
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index f174d46143..958af22597 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -93,7 +93,8 @@  static void axgbe_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 	struct rte_eth_rxq_info *qinfo);
 static void axgbe_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 	struct rte_eth_txq_info *qinfo);
-const uint32_t *axgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev);
+const uint32_t *axgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+	size_t *no_of_elements);
 static int axgb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
 
 static int
@@ -1454,7 +1455,8 @@  axgbe_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 	qinfo->conf.tx_free_thresh = txq->free_thresh;
 }
 const uint32_t *
-axgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+axgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+	size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -1480,12 +1482,13 @@  axgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_INNER_L4_NONFRAG,
 		RTE_PTYPE_INNER_L4_SCTP,
 		RTE_PTYPE_INNER_L4_TCP,
-		RTE_PTYPE_INNER_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_UDP
 	};
 
-	if (dev->rx_pkt_burst == axgbe_recv_pkts)
+	if (dev->rx_pkt_burst == axgbe_recv_pkts) {
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
+	}
 	return NULL;
 }
 
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index acf7e6e46e..6189227a72 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -3435,7 +3435,8 @@  bnxt_flow_ops_get_op(struct rte_eth_dev *dev,
 }
 
 static const uint32_t *
-bnxt_dev_supported_ptypes_get_op(struct rte_eth_dev *dev)
+bnxt_dev_supported_ptypes_get_op(struct rte_eth_dev *dev,
+			 size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER_VLAN,
@@ -3448,13 +3449,13 @@  bnxt_dev_supported_ptypes_get_op(struct rte_eth_dev *dev)
 		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
 		RTE_PTYPE_INNER_L4_ICMP,
 		RTE_PTYPE_INNER_L4_TCP,
-		RTE_PTYPE_INNER_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_UDP
 	};
 
 	if (!dev->rx_pkt_burst)
 		return NULL;
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/cnxk/cnxk_ethdev.h b/drivers/net/cnxk/cnxk_ethdev.h
index 4d3ebf123b..390c01c212 100644
--- a/drivers/net/cnxk/cnxk_ethdev.h
+++ b/drivers/net/cnxk/cnxk_ethdev.h
@@ -613,7 +613,8 @@  int cnxk_nix_tx_descriptor_status(void *txq, uint16_t offset);
 uint32_t cnxk_nix_rx_queue_count(void *rxq);
 
 /* Lookup configuration */
-const uint32_t *cnxk_nix_supported_ptypes_get(struct rte_eth_dev *eth_dev);
+const uint32_t *cnxk_nix_supported_ptypes_get(struct rte_eth_dev *eth_dev,
+				 size_t *no_of_elements);
 void *cnxk_nix_fastpath_lookup_mem_get(void);
 
 /* Devargs */
diff --git a/drivers/net/cnxk/cnxk_lookup.c b/drivers/net/cnxk/cnxk_lookup.c
index c0a7129a9c..664d648c5e 100644
--- a/drivers/net/cnxk/cnxk_lookup.c
+++ b/drivers/net/cnxk/cnxk_lookup.c
@@ -9,7 +9,8 @@ 
 
 #define LOOKUP_ARRAY_SZ (PTYPE_ARRAY_SZ + ERR_ARRAY_SZ + SA_BASE_TBL_SZ + MEMPOOL_TBL_SZ)
 const uint32_t *
-cnxk_nix_supported_ptypes_get(struct rte_eth_dev *eth_dev)
+cnxk_nix_supported_ptypes_get(struct rte_eth_dev *eth_dev,
+	size_t *no_of_elements)
 {
 	RTE_SET_USED(eth_dev);
 
@@ -47,10 +48,10 @@  cnxk_nix_supported_ptypes_get(struct rte_eth_dev *eth_dev)
 		RTE_PTYPE_INNER_L4_TCP,	      /* LH */
 		RTE_PTYPE_INNER_L4_UDP,	      /* LH */
 		RTE_PTYPE_INNER_L4_SCTP,      /* LH */
-		RTE_PTYPE_INNER_L4_ICMP,      /* LH */
-		RTE_PTYPE_UNKNOWN,
+		RTE_PTYPE_INNER_L4_ICMP       /* LH */
 	};
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/cpfl/cpfl_ethdev.c b/drivers/net/cpfl/cpfl_ethdev.c
index 7697aea0ce..225d16dbf3 100644
--- a/drivers/net/cpfl/cpfl_ethdev.c
+++ b/drivers/net/cpfl/cpfl_ethdev.c
@@ -273,7 +273,8 @@  cpfl_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 }
 
 static const uint32_t *
-cpfl_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
+cpfl_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
+		     size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -283,10 +284,10 @@  cpfl_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 		RTE_PTYPE_L4_UDP,
 		RTE_PTYPE_L4_TCP,
 		RTE_PTYPE_L4_SCTP,
-		RTE_PTYPE_L4_ICMP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_ICMP
 	};
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index 8cc3d9f257..9b3106f899 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -1149,16 +1149,18 @@  static int cxgbe_flow_ctrl_set(struct rte_eth_dev *eth_dev,
 }
 
 const uint32_t *
-cxgbe_dev_supported_ptypes_get(struct rte_eth_dev *eth_dev)
+cxgbe_dev_supported_ptypes_get(struct rte_eth_dev *eth_dev,
+				     size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L3_IPV4,
-		RTE_PTYPE_L3_IPV6,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L3_IPV6
 	};
 
-	if (eth_dev->rx_pkt_burst == cxgbe_recv_pkts)
+	if (eth_dev->rx_pkt_burst == cxgbe_recv_pkts) {
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
+	}
 	return NULL;
 }
 
diff --git a/drivers/net/cxgbe/cxgbe_pfvf.h b/drivers/net/cxgbe/cxgbe_pfvf.h
index 21035dd319..e0958c4805 100644
--- a/drivers/net/cxgbe/cxgbe_pfvf.h
+++ b/drivers/net/cxgbe/cxgbe_pfvf.h
@@ -51,7 +51,8 @@  uint16_t cxgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 			 uint16_t nb_pkts);
 uint16_t cxgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 			 uint16_t nb_pkts);
-const uint32_t *cxgbe_dev_supported_ptypes_get(struct rte_eth_dev *eth_dev);
+const uint32_t *cxgbe_dev_supported_ptypes_get(struct rte_eth_dev *eth_dev,
+			 size_t *no_of_elements);
 int cxgbe_dev_xstats_get_by_id(struct rte_eth_dev *dev,
 			       const uint64_t *ids, uint64_t *values,
 			       unsigned int n);
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 779bdc5860..1e89c24979 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -348,7 +348,8 @@  dpaa_eth_dev_configure(struct rte_eth_dev *dev)
 }
 
 static const uint32_t *
-dpaa_supported_ptypes_get(struct rte_eth_dev *dev)
+dpaa_supported_ptypes_get(struct rte_eth_dev *dev,
+				size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -363,14 +364,16 @@  dpaa_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_L4_TCP,
 		RTE_PTYPE_L4_UDP,
 		RTE_PTYPE_L4_SCTP,
-		RTE_PTYPE_TUNNEL_ESP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_TUNNEL_ESP
 	};
 
 	PMD_INIT_FUNC_TRACE();
 
-	if (dev->rx_pkt_burst == dpaa_eth_queue_rx)
+	if (dev->rx_pkt_burst == dpaa_eth_queue_rx) {
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
+	}
+	*no_of_elements = 0;
 	return NULL;
 }
 
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 8e610b6bba..e8b3290fca 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -1081,7 +1081,8 @@  dpaa2_dev_rx_queue_count(void *rx_queue)
 }
 
 static const uint32_t *
-dpaa2_supported_ptypes_get(struct rte_eth_dev *dev)
+dpaa2_supported_ptypes_get(struct rte_eth_dev *dev,
+			 size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		/*todo -= add more types */
@@ -1093,14 +1094,15 @@  dpaa2_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_L4_TCP,
 		RTE_PTYPE_L4_UDP,
 		RTE_PTYPE_L4_SCTP,
-		RTE_PTYPE_L4_ICMP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_ICMP
 	};
 
 	if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx ||
 		dev->rx_pkt_burst == dpaa2_dev_rx ||
-		dev->rx_pkt_burst == dpaa2_dev_loopback_rx)
+		dev->rx_pkt_burst == dpaa2_dev_loopback_rx) {
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
+	}
 	return NULL;
 }
 
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 8858f975f8..7b38f439b8 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -104,7 +104,8 @@  static int eth_igb_fw_version_get(struct rte_eth_dev *dev,
 				   char *fw_version, size_t fw_size);
 static int eth_igb_infos_get(struct rte_eth_dev *dev,
 			      struct rte_eth_dev_info *dev_info);
-static const uint32_t *eth_igb_supported_ptypes_get(struct rte_eth_dev *dev);
+static const uint32_t *eth_igb_supported_ptypes_get(struct rte_eth_dev *dev,
+			      size_t *no_of_elements);
 static int eth_igbvf_infos_get(struct rte_eth_dev *dev,
 				struct rte_eth_dev_info *dev_info);
 static int  eth_igb_flow_ctrl_get(struct rte_eth_dev *dev,
@@ -2257,7 +2258,8 @@  eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 }
 
 static const uint32_t *
-eth_igb_supported_ptypes_get(struct rte_eth_dev *dev)
+eth_igb_supported_ptypes_get(struct rte_eth_dev *dev,
+		       size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		/* refers to igb_rxd_pkt_info_to_pkt_type() */
@@ -2273,13 +2275,14 @@  eth_igb_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_INNER_L3_IPV6,
 		RTE_PTYPE_INNER_L3_IPV6_EXT,
 		RTE_PTYPE_INNER_L4_TCP,
-		RTE_PTYPE_INNER_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_UDP
 	};
 
 	if (dev->rx_pkt_burst == eth_igb_recv_pkts ||
-	    dev->rx_pkt_burst == eth_igb_recv_scattered_pkts)
+	    dev->rx_pkt_burst == eth_igb_recv_scattered_pkts) {
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
+	}
 	return NULL;
 }
 
diff --git a/drivers/net/enetc/enetc_ethdev.c b/drivers/net/enetc/enetc_ethdev.c
index c9352f0746..30be0c1668 100644
--- a/drivers/net/enetc/enetc_ethdev.c
+++ b/drivers/net/enetc/enetc_ethdev.c
@@ -85,7 +85,8 @@  enetc_dev_stop(struct rte_eth_dev *dev)
 }
 
 static const uint32_t *
-enetc_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
+enetc_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
+		    size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -94,10 +95,10 @@  enetc_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 		RTE_PTYPE_L4_TCP,
 		RTE_PTYPE_L4_UDP,
 		RTE_PTYPE_L4_SCTP,
-		RTE_PTYPE_L4_ICMP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_ICMP
 	};
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
index b04b6c9aa1..6b036977db 100644
--- a/drivers/net/enic/enic_ethdev.c
+++ b/drivers/net/enic/enic_ethdev.c
@@ -511,7 +511,8 @@  static int enicpmd_dev_info_get(struct rte_eth_dev *eth_dev,
 	return 0;
 }
 
-static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+	size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -521,8 +522,7 @@  static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_L4_TCP,
 		RTE_PTYPE_L4_UDP,
 		RTE_PTYPE_L4_FRAG,
-		RTE_PTYPE_L4_NONFRAG,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_NONFRAG
 	};
 	static const uint32_t ptypes_overlay[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -540,18 +540,21 @@  static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_INNER_L4_TCP,
 		RTE_PTYPE_INNER_L4_UDP,
 		RTE_PTYPE_INNER_L4_FRAG,
-		RTE_PTYPE_INNER_L4_NONFRAG,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_NONFRAG
 	};
 
 	if (dev->rx_pkt_burst != rte_eth_pkt_burst_dummy &&
 	    dev->rx_pkt_burst != NULL) {
 		struct enic *enic = pmd_priv(dev);
-		if (enic->overlay_offload)
+		if (enic->overlay_offload) {
+			*no_of_elements = RTE_DIM(ptypes_overlay);
 			return ptypes_overlay;
-		else
+		} else {
+			*no_of_elements = RTE_DIM(ptypes);
 			return ptypes;
+		}
 	}
+	*no_of_elements = 0;
 	return NULL;
 }
 
diff --git a/drivers/net/failsafe/failsafe_ops.c b/drivers/net/failsafe/failsafe_ops.c
index 35649b6244..15d3344abd 100644
--- a/drivers/net/failsafe/failsafe_ops.c
+++ b/drivers/net/failsafe/failsafe_ops.c
@@ -1282,7 +1282,8 @@  fs_dev_infos_get(struct rte_eth_dev *dev,
 }
 
 static const uint32_t *
-fs_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+fs_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+		  size_t *no_of_elements)
 {
 	struct sub_device *sdev;
 	struct rte_eth_dev *edev;
@@ -1308,7 +1309,7 @@  fs_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 	 * We just return the ptypes of the device of highest
 	 * priority, usually the PREFERRED device.
 	 */
-	ret = SUBOPS(sdev, dev_supported_ptypes_get)(edev);
+	ret = SUBOPS(sdev, dev_supported_ptypes_get)(edev, no_of_elements);
 unlock:
 	fs_unlock(dev, 0);
 	return ret;
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 4d3c4c10cf..e03be9bac5 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1446,7 +1446,8 @@  fm10k_dev_infos_get(struct rte_eth_dev *dev,
 
 #ifdef RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE
 static const uint32_t *
-fm10k_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+fm10k_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+	size_t *no_of_elements)
 {
 	if (dev->rx_pkt_burst == fm10k_recv_pkts ||
 	    dev->rx_pkt_burst == fm10k_recv_scattered_pkts) {
@@ -1458,10 +1459,10 @@  fm10k_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 			RTE_PTYPE_L3_IPV6,
 			RTE_PTYPE_L3_IPV6_EXT,
 			RTE_PTYPE_L4_TCP,
-			RTE_PTYPE_L4_UDP,
-			RTE_PTYPE_UNKNOWN
+			RTE_PTYPE_L4_UDP
 		};
 
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
 	} else if (dev->rx_pkt_burst == fm10k_recv_pkts_vec ||
 		   dev->rx_pkt_burst == fm10k_recv_scattered_pkts_vec) {
@@ -1476,10 +1477,10 @@  fm10k_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 			RTE_PTYPE_TUNNEL_GENEVE,
 			RTE_PTYPE_TUNNEL_NVGRE,
 			RTE_PTYPE_TUNNEL_VXLAN,
-			RTE_PTYPE_TUNNEL_GRE,
-			RTE_PTYPE_UNKNOWN
+			RTE_PTYPE_TUNNEL_GRE
 		};
 
+		*no_of_elements = RTE_DIM(ptypes_vec);
 		return ptypes_vec;
 	}
 
@@ -1487,8 +1488,10 @@  fm10k_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 }
 #else
 static const uint32_t *
-fm10k_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
+fm10k_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
+	size_t *no_of_elements)
 {
+	*no_of_elements = 0;
 	return NULL;
 }
 #endif
diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index 09b7e90c70..7557690a8c 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -1971,7 +1971,8 @@  hns3_rx_scattered_calc(struct rte_eth_dev *dev)
 }
 
 const uint32_t *
-hns3_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+hns3_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+		    size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -1997,8 +1998,7 @@  hns3_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_INNER_L4_SCTP,
 		RTE_PTYPE_INNER_L4_ICMP,
 		RTE_PTYPE_TUNNEL_GRENAT,
-		RTE_PTYPE_TUNNEL_NVGRE,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_TUNNEL_NVGRE
 	};
 	static const uint32_t adv_layout_ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -2025,8 +2025,7 @@  hns3_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_INNER_L4_UDP,
 		RTE_PTYPE_INNER_L4_TCP,
 		RTE_PTYPE_INNER_L4_SCTP,
-		RTE_PTYPE_INNER_L4_ICMP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_ICMP
 	};
 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
@@ -2034,10 +2033,13 @@  hns3_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 	    dev->rx_pkt_burst == hns3_recv_scattered_pkts ||
 	    dev->rx_pkt_burst == hns3_recv_pkts_vec ||
 	    dev->rx_pkt_burst == hns3_recv_pkts_vec_sve) {
-		if (hns3_dev_get_support(hw, RXD_ADV_LAYOUT))
+		if (hns3_dev_get_support(hw, RXD_ADV_LAYOUT)) {
+			*no_of_elements = RTE_DIM(adv_layout_ptypes);
 			return adv_layout_ptypes;
-		else
+		} else {
+			*no_of_elements = RTE_DIM(ptypes);
 			return ptypes;
+		}
 	}
 
 	return NULL;
diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h
index b6a6513307..74c76b4714 100644
--- a/drivers/net/hns3/hns3_rxtx.h
+++ b/drivers/net/hns3/hns3_rxtx.h
@@ -776,7 +776,8 @@  uint16_t hns3_xmit_pkts_vec_sve(void *tx_queue, struct rte_mbuf **tx_pkts,
 int hns3_tx_burst_mode_get(struct rte_eth_dev *dev,
 			   __rte_unused uint16_t queue_id,
 			   struct rte_eth_burst_mode *mode);
-const uint32_t *hns3_dev_supported_ptypes_get(struct rte_eth_dev *dev);
+const uint32_t *hns3_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+			   size_t *no_of_elements);
 void hns3_init_rx_ptype_tble(struct rte_eth_dev *dev);
 void hns3_set_rxtx_function(struct rte_eth_dev *eth_dev);
 uint32_t hns3_get_tqp_intr_reg_offset(uint16_t tqp_intr_id);
diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c
index 9aa5facb53..d438bf06c8 100644
--- a/drivers/net/i40e/i40e_rxtx.c
+++ b/drivers/net/i40e/i40e_rxtx.c
@@ -1823,7 +1823,8 @@  i40e_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 }
 
 const uint32_t *
-i40e_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+i40e_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+				size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		/* refers to i40e_rxd_pkt_type_mapping() */
@@ -1850,8 +1851,7 @@  i40e_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_INNER_L4_NONFRAG,
 		RTE_PTYPE_INNER_L4_SCTP,
 		RTE_PTYPE_INNER_L4_TCP,
-		RTE_PTYPE_INNER_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_UDP
 	};
 
 	if (dev->rx_pkt_burst == i40e_recv_pkts ||
@@ -1866,8 +1866,11 @@  i40e_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 	    dev->rx_pkt_burst == i40e_recv_pkts_vec_avx512 ||
 #endif
 	    dev->rx_pkt_burst == i40e_recv_scattered_pkts_vec_avx2 ||
-	    dev->rx_pkt_burst == i40e_recv_pkts_vec_avx2)
+	    dev->rx_pkt_burst == i40e_recv_pkts_vec_avx2) {
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
+	}
+	*no_of_elements = 0;
 	return NULL;
 }
 
diff --git a/drivers/net/i40e/i40e_rxtx.h b/drivers/net/i40e/i40e_rxtx.h
index b191f23e1f..f1204140da 100644
--- a/drivers/net/i40e/i40e_rxtx.h
+++ b/drivers/net/i40e/i40e_rxtx.h
@@ -190,7 +190,8 @@  int i40e_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id);
 int i40e_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id);
 int i40e_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id);
 int i40e_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id);
-const uint32_t *i40e_dev_supported_ptypes_get(struct rte_eth_dev *dev);
+const uint32_t *i40e_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+			    size_t *no_of_elements);
 int i40e_dev_rx_queue_setup(struct rte_eth_dev *dev,
 			    uint16_t queue_idx,
 			    uint16_t nb_desc,
diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c
index d1edb0dd5c..0957f24a32 100644
--- a/drivers/net/iavf/iavf_ethdev.c
+++ b/drivers/net/iavf/iavf_ethdev.c
@@ -97,7 +97,8 @@  static int iavf_dev_close(struct rte_eth_dev *dev);
 static int iavf_dev_reset(struct rte_eth_dev *dev);
 static int iavf_dev_info_get(struct rte_eth_dev *dev,
 			     struct rte_eth_dev_info *dev_info);
-static const uint32_t *iavf_dev_supported_ptypes_get(struct rte_eth_dev *dev);
+static const uint32_t *iavf_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+			     size_t *no_of_elements);
 static int iavf_dev_stats_get(struct rte_eth_dev *dev,
 			     struct rte_eth_stats *stats);
 static int iavf_dev_stats_reset(struct rte_eth_dev *dev);
@@ -1217,7 +1218,8 @@  iavf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 }
 
 static const uint32_t *
-iavf_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
+iavf_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
+		    size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -1227,9 +1229,9 @@  iavf_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 		RTE_PTYPE_L4_NONFRAG,
 		RTE_PTYPE_L4_SCTP,
 		RTE_PTYPE_L4_TCP,
-		RTE_PTYPE_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_UDP
 	};
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/ice/ice_dcf_ethdev.c b/drivers/net/ice/ice_dcf_ethdev.c
index 5d845bba31..829198e688 100644
--- a/drivers/net/ice/ice_dcf_ethdev.c
+++ b/drivers/net/ice/ice_dcf_ethdev.c
@@ -1864,7 +1864,8 @@  ice_dcf_dev_reset(struct rte_eth_dev *dev)
 }
 
 static const uint32_t *
-ice_dcf_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
+ice_dcf_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
+				size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -1874,9 +1875,9 @@  ice_dcf_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 		RTE_PTYPE_L4_NONFRAG,
 		RTE_PTYPE_L4_SCTP,
 		RTE_PTYPE_L4_TCP,
-		RTE_PTYPE_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_UDP
 	};
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/ice/ice_rxtx.c b/drivers/net/ice/ice_rxtx.c
index 73e47ae92d..10c7658baf 100644
--- a/drivers/net/ice/ice_rxtx.c
+++ b/drivers/net/ice/ice_rxtx.c
@@ -2200,7 +2200,8 @@  ice_recv_scattered_pkts(void *rx_queue,
 }
 
 const uint32_t *
-ice_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+ice_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+			size_t *no_of_elements)
 {
 	struct ice_adapter *ad =
 		ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
@@ -2230,8 +2231,7 @@  ice_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_INNER_L4_NONFRAG,
 		RTE_PTYPE_INNER_L4_SCTP,
 		RTE_PTYPE_INNER_L4_TCP,
-		RTE_PTYPE_INNER_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_UDP
 	};
 
 	static const uint32_t ptypes_comms[] = {
@@ -2261,19 +2261,22 @@  ice_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_INNER_L4_UDP,
 		RTE_PTYPE_TUNNEL_GTPC,
 		RTE_PTYPE_TUNNEL_GTPU,
-		RTE_PTYPE_L2_ETHER_PPPOE,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L2_ETHER_PPPOE
 	};
 
-	if (ad->active_pkg_type == ICE_PKG_TYPE_COMMS)
+	if (ad->active_pkg_type == ICE_PKG_TYPE_COMMS) {
+		*no_of_elements = RTE_DIM(ptypes_comms);
 		ptypes = ptypes_comms;
-	else
+	} else {
+		*no_of_elements = RTE_DIM(ptypes_os);
 		ptypes = ptypes_os;
+	}
 
 	if (dev->rx_pkt_burst == ice_recv_pkts ||
 	    dev->rx_pkt_burst == ice_recv_pkts_bulk_alloc ||
-	    dev->rx_pkt_burst == ice_recv_scattered_pkts)
+	    dev->rx_pkt_burst == ice_recv_scattered_pkts) {
 		return ptypes;
+	}
 
 #ifdef RTE_ARCH_X86
 	if (dev->rx_pkt_burst == ice_recv_pkts_vec ||
@@ -2287,10 +2290,12 @@  ice_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 	    dev->rx_pkt_burst == ice_recv_pkts_vec_avx2 ||
 	    dev->rx_pkt_burst == ice_recv_pkts_vec_avx2_offload ||
 	    dev->rx_pkt_burst == ice_recv_scattered_pkts_vec_avx2 ||
-	    dev->rx_pkt_burst == ice_recv_scattered_pkts_vec_avx2_offload)
+	    dev->rx_pkt_burst == ice_recv_scattered_pkts_vec_avx2_offload) {
 		return ptypes;
+	}
 #endif
 
+	*no_of_elements = 0;
 	return NULL;
 }
 
diff --git a/drivers/net/ice/ice_rxtx.h b/drivers/net/ice/ice_rxtx.h
index bd2c4abec9..20e5628439 100644
--- a/drivers/net/ice/ice_rxtx.h
+++ b/drivers/net/ice/ice_rxtx.h
@@ -271,7 +271,8 @@  int ice_tx_burst_mode_get(struct rte_eth_dev *dev, uint16_t queue_id,
 int ice_rx_descriptor_status(void *rx_queue, uint16_t offset);
 int ice_tx_descriptor_status(void *tx_queue, uint16_t offset);
 void ice_set_default_ptype_table(struct rte_eth_dev *dev);
-const uint32_t *ice_dev_supported_ptypes_get(struct rte_eth_dev *dev);
+const uint32_t *ice_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+					  size_t *no_of_elements);
 void ice_select_rxd_to_pkt_fields_handler(struct ice_rx_queue *rxq,
 					  uint32_t rxdid);
 
diff --git a/drivers/net/idpf/idpf_ethdev.c b/drivers/net/idpf/idpf_ethdev.c
index 6ae2ac2681..75c741ecc4 100644
--- a/drivers/net/idpf/idpf_ethdev.c
+++ b/drivers/net/idpf/idpf_ethdev.c
@@ -232,7 +232,8 @@  idpf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 }
 
 static const uint32_t *
-idpf_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
+idpf_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
+		     size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -242,10 +243,10 @@  idpf_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 		RTE_PTYPE_L4_UDP,
 		RTE_PTYPE_L4_TCP,
 		RTE_PTYPE_L4_SCTP,
-		RTE_PTYPE_L4_ICMP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_ICMP
 	};
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/igc/igc_ethdev.c b/drivers/net/igc/igc_ethdev.c
index 58c4f80927..e1c638699f 100644
--- a/drivers/net/igc/igc_ethdev.c
+++ b/drivers/net/igc/igc_ethdev.c
@@ -207,7 +207,8 @@  static int eth_igc_infos_get(struct rte_eth_dev *dev,
 			struct rte_eth_dev_info *dev_info);
 static int eth_igc_led_on(struct rte_eth_dev *dev);
 static int eth_igc_led_off(struct rte_eth_dev *dev);
-static const uint32_t *eth_igc_supported_ptypes_get(struct rte_eth_dev *dev);
+static const uint32_t *eth_igc_supported_ptypes_get(struct rte_eth_dev *dev,
+			size_t *no_of_elements);
 static int eth_igc_rar_set(struct rte_eth_dev *dev,
 		struct rte_ether_addr *mac_addr, uint32_t index, uint32_t pool);
 static void eth_igc_rar_clear(struct rte_eth_dev *dev, uint32_t index);
@@ -1650,7 +1651,8 @@  eth_igc_led_off(struct rte_eth_dev *dev)
 }
 
 static const uint32_t *
-eth_igc_supported_ptypes_get(__rte_unused struct rte_eth_dev *dev)
+eth_igc_supported_ptypes_get(__rte_unused struct rte_eth_dev *dev,
+		size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		/* refers to rx_desc_pkt_info_to_pkt_type() */
@@ -1666,10 +1668,10 @@  eth_igc_supported_ptypes_get(__rte_unused struct rte_eth_dev *dev)
 		RTE_PTYPE_INNER_L3_IPV6,
 		RTE_PTYPE_INNER_L3_IPV6_EXT,
 		RTE_PTYPE_INNER_L4_TCP,
-		RTE_PTYPE_INNER_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_UDP
 	};
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/ionic/ionic_rxtx.c b/drivers/net/ionic/ionic_rxtx.c
index b9e73b4871..b760d9540e 100644
--- a/drivers/net/ionic/ionic_rxtx.c
+++ b/drivers/net/ionic/ionic_rxtx.c
@@ -619,7 +619,8 @@  const uint32_t ionic_ptype_table[IONIC_RXQ_COMP_PKT_TYPE_MASK]
 };
 
 const uint32_t *
-ionic_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
+ionic_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
+	size_t *no_of_elements)
 {
 	/* See ionic_ptype_table[] */
 	static const uint32_t ptypes[] = {
@@ -630,10 +631,10 @@  ionic_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 		RTE_PTYPE_L3_IPV4,
 		RTE_PTYPE_L3_IPV6,
 		RTE_PTYPE_L4_TCP,
-		RTE_PTYPE_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_UDP
 	};
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/ionic/ionic_rxtx.h b/drivers/net/ionic/ionic_rxtx.h
index 8537141597..6a63c8d54c 100644
--- a/drivers/net/ionic/ionic_rxtx.h
+++ b/drivers/net/ionic/ionic_rxtx.h
@@ -54,7 +54,8 @@  void ionic_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 int ionic_dev_rx_descriptor_status(void *rx_queue, uint16_t offset);
 int ionic_dev_tx_descriptor_status(void *tx_queue, uint16_t offset);
 
-const uint32_t *ionic_dev_supported_ptypes_get(struct rte_eth_dev *dev);
+const uint32_t *ionic_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+	size_t *no_of_elements);
 
 int ionic_tx_tso(struct ionic_tx_qcq *txq, struct rte_mbuf *txm);
 
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index d6cf00317e..000e132e2c 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -191,7 +191,8 @@  static int ixgbe_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
 				 size_t fw_size);
 static int ixgbe_dev_info_get(struct rte_eth_dev *dev,
 			      struct rte_eth_dev_info *dev_info);
-static const uint32_t *ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev);
+static const uint32_t *ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+				size_t *no_of_elements);
 static int ixgbevf_dev_info_get(struct rte_eth_dev *dev,
 				struct rte_eth_dev_info *dev_info);
 static int ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
@@ -3978,7 +3979,8 @@  ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 }
 
 static const uint32_t *
-ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+		     size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		/* For non-vec functions,
@@ -3998,21 +4000,25 @@  ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_INNER_L3_IPV6,
 		RTE_PTYPE_INNER_L3_IPV6_EXT,
 		RTE_PTYPE_INNER_L4_TCP,
-		RTE_PTYPE_INNER_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_UDP
 	};
 
 	if (dev->rx_pkt_burst == ixgbe_recv_pkts ||
 	    dev->rx_pkt_burst == ixgbe_recv_pkts_lro_single_alloc ||
 	    dev->rx_pkt_burst == ixgbe_recv_pkts_lro_bulk_alloc ||
-	    dev->rx_pkt_burst == ixgbe_recv_pkts_bulk_alloc)
+	    dev->rx_pkt_burst == ixgbe_recv_pkts_bulk_alloc) {
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
+	}
 
 #if defined(RTE_ARCH_X86) || defined(__ARM_NEON)
 	if (dev->rx_pkt_burst == ixgbe_recv_pkts_vec ||
-	    dev->rx_pkt_burst == ixgbe_recv_scattered_pkts_vec)
+	    dev->rx_pkt_burst == ixgbe_recv_scattered_pkts_vec) {
+		*no_of_elements = (sizeof(ptypes) / sizeof(uint32_t));
 		return ptypes;
+	}
 #endif
+	*no_of_elements = 0;
 	return NULL;
 }
 
diff --git a/drivers/net/mana/mana.c b/drivers/net/mana/mana.c
index 781ed76139..a50d21d6c2 100644
--- a/drivers/net/mana/mana.c
+++ b/drivers/net/mana/mana.c
@@ -387,7 +387,8 @@  mana_dev_rx_queue_info(struct rte_eth_dev *dev, uint16_t queue_id,
 }
 
 static const uint32_t *
-mana_supported_ptypes(struct rte_eth_dev *dev __rte_unused)
+mana_supported_ptypes(struct rte_eth_dev *dev __rte_unused,
+		       size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -395,10 +396,10 @@  mana_supported_ptypes(struct rte_eth_dev *dev __rte_unused)
 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
 		RTE_PTYPE_L4_FRAG,
 		RTE_PTYPE_L4_TCP,
-		RTE_PTYPE_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_UDP
 	};
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index d90570add6..8e0bca5765 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -229,7 +229,8 @@  int mlx4_flow_ctrl_get(struct rte_eth_dev *dev,
 		       struct rte_eth_fc_conf *fc_conf);
 int mlx4_flow_ctrl_set(struct rte_eth_dev *dev,
 		       struct rte_eth_fc_conf *fc_conf);
-const uint32_t *mlx4_dev_supported_ptypes_get(struct rte_eth_dev *dev);
+const uint32_t *mlx4_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+		       size_t *no_of_elements);
 int mlx4_is_removed(struct rte_eth_dev *dev);
 
 /* mlx4_intr.c */
diff --git a/drivers/net/mlx4/mlx4_ethdev.c b/drivers/net/mlx4/mlx4_ethdev.c
index bb1dd33e7c..e2ff894bd3 100644
--- a/drivers/net/mlx4/mlx4_ethdev.c
+++ b/drivers/net/mlx4/mlx4_ethdev.c
@@ -934,7 +934,8 @@  mlx4_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
  *   NULL otherwise.
  */
 const uint32_t *
-mlx4_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+mlx4_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+		      size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		/* refers to rxq_cq_to_pkt_type() */
@@ -943,8 +944,7 @@  mlx4_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
 		RTE_PTYPE_L4_FRAG,
 		RTE_PTYPE_L4_TCP,
-		RTE_PTYPE_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_UDP
 	};
 	static const uint32_t ptypes_l2tun[] = {
 		/* refers to rxq_cq_to_pkt_type() */
@@ -955,17 +955,20 @@  mlx4_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_L4_TCP,
 		RTE_PTYPE_L4_UDP,
 		RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
-		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN
 	};
 	struct mlx4_priv *priv = dev->data->dev_private;
 
 	if (dev->rx_pkt_burst == mlx4_rx_burst) {
-		if (priv->hw_csum_l2tun)
+		if (priv->hw_csum_l2tun) {
+			*no_of_elements = RTE_DIM(ptypes_l2tun);
 			return ptypes_l2tun;
-		else
+		} else {
+			*no_of_elements = RTE_DIM(ptypes);
 			return ptypes;
+		}
 	}
+	*no_of_elements = 0;
 	return NULL;
 }
 
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 263ebead7f..90afcc2bb5 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -2090,7 +2090,8 @@  uint16_t mlx5_representor_id_encode(const struct mlx5_switch_info *info,
 				    enum rte_eth_representor_type hpf_type);
 int mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info);
 int mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size);
-const uint32_t *mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev);
+const uint32_t *mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+			 size_t *no_of_elements);
 int mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu);
 int mlx5_hairpin_cap_get(struct rte_eth_dev *dev,
 			 struct rte_eth_hairpin_cap *cap);
diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c
index ab30e2c215..eea346d6d5 100644
--- a/drivers/net/mlx5/mlx5_ethdev.c
+++ b/drivers/net/mlx5/mlx5_ethdev.c
@@ -579,7 +579,8 @@  mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size)
  *   A pointer to the supported Packet types array.
  */
 const uint32_t *
-mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+			  size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		/* refers to rxq_cq_to_pkt_type() */
@@ -595,15 +596,17 @@  mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_INNER_L4_NONFRAG,
 		RTE_PTYPE_INNER_L4_FRAG,
 		RTE_PTYPE_INNER_L4_TCP,
-		RTE_PTYPE_INNER_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_UDP
 	};
 
 	if (dev->rx_pkt_burst == mlx5_rx_burst ||
 	    dev->rx_pkt_burst == mlx5_rx_burst_mprq ||
 	    dev->rx_pkt_burst == mlx5_rx_burst_vec ||
-	    dev->rx_pkt_burst == mlx5_rx_burst_mprq_vec)
+	    dev->rx_pkt_burst == mlx5_rx_burst_mprq_vec) {
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
+	}
+	*no_of_elements = 0;
 	return NULL;
 }
 
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 212c300c14..48db3fae57 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -190,7 +190,8 @@  mvneta_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
  *   Const pointer to the table with supported packet types.
  */
 static const uint32_t *
-mvneta_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
+mvneta_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
+		   size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -198,10 +199,10 @@  mvneta_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 		RTE_PTYPE_L3_IPV4,
 		RTE_PTYPE_L3_IPV6,
 		RTE_PTYPE_L4_TCP,
-		RTE_PTYPE_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_UDP
 	};
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/mvpp2/mrvl_ethdev.c b/drivers/net/mvpp2/mrvl_ethdev.c
index 4cc64c7cad..e7748c910e 100644
--- a/drivers/net/mvpp2/mrvl_ethdev.c
+++ b/drivers/net/mvpp2/mrvl_ethdev.c
@@ -1764,7 +1764,8 @@  mrvl_dev_infos_get(struct rte_eth_dev *dev,
  *   Const pointer to the table with supported packet types.
  */
 static const uint32_t *
-mrvl_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
+mrvl_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
+		   size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -1777,10 +1778,10 @@  mrvl_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 		RTE_PTYPE_L3_IPV6_EXT,
 		RTE_PTYPE_L2_ETHER_ARP,
 		RTE_PTYPE_L4_TCP,
-		RTE_PTYPE_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_UDP
 	};
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h
index e37946804d..c884369a07 100644
--- a/drivers/net/netvsc/hn_var.h
+++ b/drivers/net/netvsc/hn_var.h
@@ -246,7 +246,8 @@  int	hn_vf_info_get(struct hn_data *hv,
 int	hn_vf_add(struct rte_eth_dev *dev, struct hn_data *hv);
 int	hn_vf_configure_locked(struct rte_eth_dev *dev,
 			       const struct rte_eth_conf *dev_conf);
-const uint32_t *hn_vf_supported_ptypes(struct rte_eth_dev *dev);
+const uint32_t *hn_vf_supported_ptypes(struct rte_eth_dev *dev,
+			       size_t *no_of_elements);
 int	hn_vf_start(struct rte_eth_dev *dev);
 int	hn_vf_close(struct rte_eth_dev *dev);
 int	hn_vf_stop(struct rte_eth_dev *dev);
diff --git a/drivers/net/netvsc/hn_vf.c b/drivers/net/netvsc/hn_vf.c
index 90cb6f6923..3be1ca6c95 100644
--- a/drivers/net/netvsc/hn_vf.c
+++ b/drivers/net/netvsc/hn_vf.c
@@ -466,7 +466,8 @@  int hn_vf_configure_locked(struct rte_eth_dev *dev,
 	return ret;
 }
 
-const uint32_t *hn_vf_supported_ptypes(struct rte_eth_dev *dev)
+const uint32_t *hn_vf_supported_ptypes(struct rte_eth_dev *dev,
+			   size_t *no_of_elements)
 {
 	struct hn_data *hv = dev->data->dev_private;
 	struct rte_eth_dev *vf_dev;
@@ -475,7 +476,7 @@  const uint32_t *hn_vf_supported_ptypes(struct rte_eth_dev *dev)
 	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev && vf_dev->dev_ops->dev_supported_ptypes_get)
-		ptypes = (*vf_dev->dev_ops->dev_supported_ptypes_get)(vf_dev);
+		ptypes = (*vf_dev->dev_ops->dev_supported_ptypes_get)(vf_dev, no_of_elements);
 	rte_rwlock_read_unlock(&hv->vf_lock);
 
 	return ptypes;
diff --git a/drivers/net/nfp/nfp_net_common.c b/drivers/net/nfp/nfp_net_common.c
index 46d0e07850..dbebcb6443 100644
--- a/drivers/net/nfp/nfp_net_common.c
+++ b/drivers/net/nfp/nfp_net_common.c
@@ -1266,7 +1266,8 @@  nfp_net_common_init(struct rte_pci_device *pci_dev,
 }
 
 const uint32_t *
-nfp_net_supported_ptypes_get(struct rte_eth_dev *dev)
+nfp_net_supported_ptypes_get(struct rte_eth_dev *dev,
+		size_t *no_of_elements)
 {
 	struct nfp_net_hw *net_hw;
 	static const uint32_t ptypes[] = {
@@ -1298,17 +1299,21 @@  nfp_net_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_INNER_L4_FRAG,
 		RTE_PTYPE_INNER_L4_NONFRAG,
 		RTE_PTYPE_INNER_L4_ICMP,
-		RTE_PTYPE_INNER_L4_SCTP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_SCTP
 	};
 
-	if (dev->rx_pkt_burst != nfp_net_recv_pkts)
+	if (dev->rx_pkt_burst != nfp_net_recv_pkts) {
+		*no_of_elements = 0;
 		return NULL;
+	}
 
 	net_hw = dev->data->dev_private;
-	if ((net_hw->super.cap_ext & NFP_NET_CFG_CTRL_PKT_TYPE) == 0)
+	if ((net_hw->super.cap_ext & NFP_NET_CFG_CTRL_PKT_TYPE) == 0) {
+		*no_of_elements = 0;
 		return NULL;
+	}
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/nfp/nfp_net_common.h b/drivers/net/nfp/nfp_net_common.h
index 30fea7ae02..7be9fb6ad9 100644
--- a/drivers/net/nfp/nfp_net_common.h
+++ b/drivers/net/nfp/nfp_net_common.h
@@ -229,7 +229,8 @@  int nfp_net_xstats_get_by_id(struct rte_eth_dev *dev,
 int nfp_net_xstats_reset(struct rte_eth_dev *dev);
 int nfp_net_infos_get(struct rte_eth_dev *dev,
 		struct rte_eth_dev_info *dev_info);
-const uint32_t *nfp_net_supported_ptypes_get(struct rte_eth_dev *dev);
+const uint32_t *nfp_net_supported_ptypes_get(struct rte_eth_dev *dev,
+		size_t *no_of_elements);
 int nfp_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
 int nfp_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);
 void nfp_net_params_setup(struct nfp_net_hw *hw);
diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c
index 478da014b2..1da3629c50 100644
--- a/drivers/net/ngbe/ngbe_ethdev.c
+++ b/drivers/net/ngbe/ngbe_ethdev.c
@@ -1864,14 +1864,17 @@  ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 }
 
 const uint32_t *
-ngbe_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+ngbe_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+		size_t *no_of_elements)
 {
 	if (dev->rx_pkt_burst == ngbe_recv_pkts ||
 	    dev->rx_pkt_burst == ngbe_recv_pkts_sc_single_alloc ||
 	    dev->rx_pkt_burst == ngbe_recv_pkts_sc_bulk_alloc ||
-	    dev->rx_pkt_burst == ngbe_recv_pkts_bulk_alloc)
-		return ngbe_get_supported_ptypes();
+	    dev->rx_pkt_burst == ngbe_recv_pkts_bulk_alloc) {
+		return ngbe_get_supported_ptypes(no_of_elements);
+	}
 
+	*no_of_elements = 0;
 	return NULL;
 }
 
diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h
index 3cde7c8750..9de0cba408 100644
--- a/drivers/net/ngbe/ngbe_ethdev.h
+++ b/drivers/net/ngbe/ngbe_ethdev.h
@@ -328,7 +328,8 @@  struct rte_ngbe_xstats_name_off {
 	unsigned int offset;
 };
 
-const uint32_t *ngbe_dev_supported_ptypes_get(struct rte_eth_dev *dev);
+const uint32_t *ngbe_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+				      size_t *no_of_elements);
 int ngbe_dev_set_mc_addr_list(struct rte_eth_dev *dev,
 				      struct rte_ether_addr *mc_addr_set,
 				      uint32_t nb_mc_addr);
diff --git a/drivers/net/ngbe/ngbe_ptypes.c b/drivers/net/ngbe/ngbe_ptypes.c
index 33f20e9247..b590ca1a88 100644
--- a/drivers/net/ngbe/ngbe_ptypes.c
+++ b/drivers/net/ngbe/ngbe_ptypes.c
@@ -92,7 +92,7 @@  static u32 ngbe_ptype_lookup[NGBE_PTID_MAX] __rte_cache_aligned = {
 	TPTE(0xCD, ETHER, IPV6, NONE, IP, NONE, IPV6, SCTP),
 };
 
-u32 *ngbe_get_supported_ptypes(void)
+u32 *ngbe_get_supported_ptypes(size_t *no_of_elements)
 {
 	static u32 ptypes[] = {
 		/* For non-vec functions,
@@ -114,6 +114,7 @@  u32 *ngbe_get_supported_ptypes(void)
 		RTE_PTYPE_UNKNOWN
 	};
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/ngbe/ngbe_ptypes.h b/drivers/net/ngbe/ngbe_ptypes.h
index 16635e3390..e4238d50f8 100644
--- a/drivers/net/ngbe/ngbe_ptypes.h
+++ b/drivers/net/ngbe/ngbe_ptypes.h
@@ -110,7 +110,7 @@  struct rte_ngbe_ptype {
 #define RTE_PTYPE_L2_ETHER_EAPOL            RTE_PTYPE_L2_ETHER
 #define RTE_PTYPE_L2_ETHER_FILTER           RTE_PTYPE_L2_ETHER
 
-u32 *ngbe_get_supported_ptypes(void);
+u32 *ngbe_get_supported_ptypes(size_t *no_of_elements);
 u32 ngbe_decode_ptype(u8 ptid);
 u8 ngbe_encode_ptype(u32 ptype);
 
diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
index 2a8378a33e..a398ce3033 100644
--- a/drivers/net/octeontx/octeontx_ethdev.c
+++ b/drivers/net/octeontx/octeontx_ethdev.c
@@ -1467,7 +1467,8 @@  octeontx_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
 }
 
 static const uint32_t *
-octeontx_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+octeontx_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+				size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L3_IPV4,
@@ -1476,13 +1477,15 @@  octeontx_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_L3_IPV6_EXT,
 		RTE_PTYPE_L4_TCP,
 		RTE_PTYPE_L4_UDP,
-		RTE_PTYPE_L4_FRAG,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_FRAG
 	};
 
-	if (dev->rx_pkt_burst == octeontx_recv_pkts)
+	if (dev->rx_pkt_burst == octeontx_recv_pkts) {
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
+	}
 
+	*no_of_elements = 0;
 	return NULL;
 }
 
diff --git a/drivers/net/pfe/pfe_ethdev.c b/drivers/net/pfe/pfe_ethdev.c
index 0073dd7405..c2825813be 100644
--- a/drivers/net/pfe/pfe_ethdev.c
+++ b/drivers/net/pfe/pfe_ethdev.c
@@ -509,7 +509,8 @@  pfe_tx_queue_setup(struct rte_eth_dev *dev,
 }
 
 static const uint32_t *
-pfe_supported_ptypes_get(struct rte_eth_dev *dev)
+pfe_supported_ptypes_get(struct rte_eth_dev *dev,
+		   size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		/*todo -= add more types */
@@ -520,13 +521,15 @@  pfe_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_L3_IPV6_EXT,
 		RTE_PTYPE_L4_TCP,
 		RTE_PTYPE_L4_UDP,
-		RTE_PTYPE_L4_SCTP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_SCTP
 	};
 
 	if (dev->rx_pkt_burst == pfe_recv_pkts ||
-			dev->rx_pkt_burst == pfe_recv_pkts_on_intr)
+			dev->rx_pkt_burst == pfe_recv_pkts_on_intr) {
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
+	}
+	*no_of_elements = 0;
 	return NULL;
 }
 
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 22cd470646..bb51236d13 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -2054,7 +2054,8 @@  static int qede_flow_ctrl_get(struct rte_eth_dev *eth_dev,
 }
 
 static const uint32_t *
-qede_dev_supported_ptypes_get(struct rte_eth_dev *eth_dev)
+qede_dev_supported_ptypes_get(struct rte_eth_dev *eth_dev,
+			      size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -2074,15 +2075,17 @@  qede_dev_supported_ptypes_get(struct rte_eth_dev *eth_dev)
 		RTE_PTYPE_INNER_L3_IPV6,
 		RTE_PTYPE_INNER_L4_TCP,
 		RTE_PTYPE_INNER_L4_UDP,
-		RTE_PTYPE_INNER_L4_FRAG,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_FRAG
 	};
 
 	if (eth_dev->rx_pkt_burst == qede_recv_pkts ||
 	    eth_dev->rx_pkt_burst == qede_recv_pkts_regular ||
-	    eth_dev->rx_pkt_burst == qede_recv_pkts_cmt)
+	    eth_dev->rx_pkt_burst == qede_recv_pkts_cmt) {
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
+	}
 
+	*no_of_elements = 0;
 	return NULL;
 }
 
diff --git a/drivers/net/sfc/sfc_dp_rx.h b/drivers/net/sfc/sfc_dp_rx.h
index 9f9bf28988..852d567091 100644
--- a/drivers/net/sfc/sfc_dp_rx.h
+++ b/drivers/net/sfc/sfc_dp_rx.h
@@ -199,7 +199,7 @@  typedef void (sfc_dp_rx_qpurge_t)(struct sfc_dp_rxq *dp_rxq);
 
 /** Get packet types recognized/classified */
 typedef const uint32_t * (sfc_dp_rx_supported_ptypes_get_t)(
-				uint32_t tunnel_encaps);
+	uint32_t tunnel_encaps, size_t *no_of_elements);
 
 /** Get number of pending Rx descriptors */
 typedef unsigned int (sfc_dp_rx_qdesc_npending_t)(struct sfc_dp_rxq *dp_rxq);
diff --git a/drivers/net/sfc/sfc_ef10.h b/drivers/net/sfc/sfc_ef10.h
index e9bb72e28b..793d0070b3 100644
--- a/drivers/net/sfc/sfc_ef10.h
+++ b/drivers/net/sfc/sfc_ef10.h
@@ -134,7 +134,8 @@  sfc_ef10_ev_qprime(volatile void *qprime, unsigned int read_ptr,
 }
 
 
-const uint32_t * sfc_ef10_supported_ptypes_get(uint32_t tunnel_encaps);
+const uint32_t *sfc_ef10_supported_ptypes_get(uint32_t tunnel_encaps,
+		  size_t *no_of_elements);
 
 
 #ifdef __cplusplus
diff --git a/drivers/net/sfc/sfc_ef100_rx.c b/drivers/net/sfc/sfc_ef100_rx.c
index 2677003da3..c07930dd98 100644
--- a/drivers/net/sfc/sfc_ef100_rx.c
+++ b/drivers/net/sfc/sfc_ef100_rx.c
@@ -665,7 +665,8 @@  sfc_ef100_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 }
 
 static const uint32_t *
-sfc_ef100_supported_ptypes_get(__rte_unused uint32_t tunnel_encaps)
+sfc_ef100_supported_ptypes_get(__rte_unused uint32_t tunnel_encaps,
+				size_t *no_of_elements)
 {
 	static const uint32_t ef100_native_ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -683,10 +684,10 @@  sfc_ef100_supported_ptypes_get(__rte_unused uint32_t tunnel_encaps)
 		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
 		RTE_PTYPE_INNER_L4_TCP,
 		RTE_PTYPE_INNER_L4_UDP,
-		RTE_PTYPE_INNER_L4_FRAG,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_FRAG
 	};
 
+	*no_of_elements = RTE_DIM(ef100_native_ptypes);
 	return ef100_native_ptypes;
 }
 
diff --git a/drivers/net/sfc/sfc_ef10_rx.c b/drivers/net/sfc/sfc_ef10_rx.c
index 30a320d079..576268a1a7 100644
--- a/drivers/net/sfc/sfc_ef10_rx.c
+++ b/drivers/net/sfc/sfc_ef10_rx.c
@@ -471,7 +471,8 @@  sfc_ef10_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 }
 
 const uint32_t *
-sfc_ef10_supported_ptypes_get(uint32_t tunnel_encaps)
+sfc_ef10_supported_ptypes_get(uint32_t tunnel_encaps,
+			  size_t *no_of_elements)
 {
 	static const uint32_t ef10_native_ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -482,8 +483,7 @@  sfc_ef10_supported_ptypes_get(uint32_t tunnel_encaps)
 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
 		RTE_PTYPE_L4_FRAG,
 		RTE_PTYPE_L4_TCP,
-		RTE_PTYPE_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_UDP
 	};
 	static const uint32_t ef10_overlay_ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -504,8 +504,7 @@  sfc_ef10_supported_ptypes_get(uint32_t tunnel_encaps)
 		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
 		RTE_PTYPE_INNER_L4_FRAG,
 		RTE_PTYPE_INNER_L4_TCP,
-		RTE_PTYPE_INNER_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_UDP
 	};
 
 	/*
@@ -517,6 +516,7 @@  sfc_ef10_supported_ptypes_get(uint32_t tunnel_encaps)
 	case (1u << EFX_TUNNEL_PROTOCOL_VXLAN |
 	      1u << EFX_TUNNEL_PROTOCOL_GENEVE |
 	      1u << EFX_TUNNEL_PROTOCOL_NVGRE):
+		*no_of_elements = RTE_DIM(ef10_overlay_ptypes);
 		return ef10_overlay_ptypes;
 	default:
 		SFC_GENERIC_LOG(ERR,
@@ -524,6 +524,7 @@  sfc_ef10_supported_ptypes_get(uint32_t tunnel_encaps)
 			tunnel_encaps);
 		/* FALLTHROUGH */
 	case 0:
+		*no_of_elements = RTE_DIM(ef10_native_ptypes);
 		return ef10_native_ptypes;
 	}
 }
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index 6d57b2ba26..890ed04934 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -194,11 +194,12 @@  sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 }
 
 static const uint32_t *
-sfc_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+sfc_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+		     size_t *no_of_elements)
 {
 	const struct sfc_adapter_priv *sap = sfc_adapter_priv_by_eth_dev(dev);
 
-	return sap->dp_rx->supported_ptypes_get(sap->shared->tunnel_encaps);
+	return sap->dp_rx->supported_ptypes_get(sap->shared->tunnel_encaps, no_of_elements);
 }
 
 static int
diff --git a/drivers/net/sfc/sfc_rx.c b/drivers/net/sfc/sfc_rx.c
index 1dde2c1110..dfd4b2cbe9 100644
--- a/drivers/net/sfc/sfc_rx.c
+++ b/drivers/net/sfc/sfc_rx.c
@@ -194,17 +194,18 @@  sfc_efx_rx_desc_flags_to_packet_type(const unsigned int desc_flags)
 }
 
 static const uint32_t *
-sfc_efx_supported_ptypes_get(__rte_unused uint32_t tunnel_encaps)
+sfc_efx_supported_ptypes_get(__rte_unused uint32_t tunnel_encaps,
+			size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
 		RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
 		RTE_PTYPE_L4_TCP,
-		RTE_PTYPE_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_UDP
 	};
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index 3fa03cdbee..975fd293a3 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -1778,7 +1778,8 @@  tap_intr_handle_set(struct rte_eth_dev *dev, int set)
 }
 
 static const uint32_t*
-tap_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
+tap_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
+		     size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_INNER_L2_ETHER,
@@ -1802,10 +1803,10 @@  tap_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 		RTE_PTYPE_L4_FRAG,
 		RTE_PTYPE_L4_UDP,
 		RTE_PTYPE_L4_TCP,
-		RTE_PTYPE_L4_SCTP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_SCTP
 	};
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/thunderx/nicvf_ethdev.c b/drivers/net/thunderx/nicvf_ethdev.c
index 5a0c3dc4a6..75ff2e2542 100644
--- a/drivers/net/thunderx/nicvf_ethdev.c
+++ b/drivers/net/thunderx/nicvf_ethdev.c
@@ -379,7 +379,8 @@  nicvf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 }
 
 static const uint32_t *
-nicvf_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+nicvf_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+			 size_t *no_of_elements)
 {
 	size_t copied;
 	static uint32_t ptypes[32];
@@ -391,15 +392,13 @@  nicvf_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		RTE_PTYPE_L3_IPV6_EXT,
 		RTE_PTYPE_L4_TCP,
 		RTE_PTYPE_L4_UDP,
-		RTE_PTYPE_L4_FRAG,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L4_FRAG
 	};
 	static const uint32_t ptypes_tunnel[] = {
 		RTE_PTYPE_TUNNEL_GRE,
 		RTE_PTYPE_TUNNEL_GENEVE,
 		RTE_PTYPE_TUNNEL_VXLAN,
-		RTE_PTYPE_TUNNEL_NVGRE,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_TUNNEL_NVGRE
 	};
 	static const uint32_t ptypes_end = RTE_PTYPE_UNKNOWN;
 
@@ -414,6 +413,7 @@  nicvf_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 	memcpy((char *)ptypes + copied, &ptypes_end, sizeof(ptypes_end));
 
 	/* All Ptypes are supported in all Rx functions. */
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c
index 6bc231a130..f1c285fd92 100644
--- a/drivers/net/txgbe/txgbe_ethdev.c
+++ b/drivers/net/txgbe/txgbe_ethdev.c
@@ -2727,14 +2727,17 @@  txgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 }
 
 const uint32_t *
-txgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+txgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+			    size_t *no_of_elements)
 {
 	if (dev->rx_pkt_burst == txgbe_recv_pkts ||
 	    dev->rx_pkt_burst == txgbe_recv_pkts_lro_single_alloc ||
 	    dev->rx_pkt_burst == txgbe_recv_pkts_lro_bulk_alloc ||
-	    dev->rx_pkt_burst == txgbe_recv_pkts_bulk_alloc)
-		return txgbe_get_supported_ptypes();
+	    dev->rx_pkt_burst == txgbe_recv_pkts_bulk_alloc) {
+		return txgbe_get_supported_ptypes(no_of_elements);
+	}
 
+	*no_of_elements = 0;
 	return NULL;
 }
 
diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h
index 7feb45d0cf..830ce9d750 100644
--- a/drivers/net/txgbe/txgbe_ethdev.h
+++ b/drivers/net/txgbe/txgbe_ethdev.h
@@ -704,7 +704,8 @@  struct rte_txgbe_xstats_name_off {
 	unsigned int offset;
 };
 
-const uint32_t *txgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev);
+const uint32_t *txgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+				      size_t *no_of_elements);
 int txgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev,
 				      struct rte_ether_addr *mc_addr_set,
 				      uint32_t nb_mc_addr);
diff --git a/drivers/net/txgbe/txgbe_ptypes.c b/drivers/net/txgbe/txgbe_ptypes.c
index c444d5d3f1..1974d94c22 100644
--- a/drivers/net/txgbe/txgbe_ptypes.c
+++ b/drivers/net/txgbe/txgbe_ptypes.c
@@ -186,7 +186,7 @@  static u32 txgbe_ptype_lookup[TXGBE_PTID_MAX] __rte_cache_aligned = {
 	TPTE(0xFD, ETHER, IPV6, NONE, GRENAT, ETHER_VLAN, IPV6, SCTP),
 };
 
-u32 *txgbe_get_supported_ptypes(void)
+u32 *txgbe_get_supported_ptypes(size_t *no_of_elements)
 {
 	static u32 ptypes[] = {
 		/* For non-vec functions,
@@ -204,10 +204,10 @@  u32 *txgbe_get_supported_ptypes(void)
 		RTE_PTYPE_INNER_L3_IPV6,
 		RTE_PTYPE_INNER_L3_IPV6_EXT,
 		RTE_PTYPE_INNER_L4_TCP,
-		RTE_PTYPE_INNER_L4_UDP,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_INNER_L4_UDP
 	};
 
+	*no_of_elements = RTE_DIM(ptypes);
 	return ptypes;
 }
 
diff --git a/drivers/net/txgbe/txgbe_ptypes.h b/drivers/net/txgbe/txgbe_ptypes.h
index 6fa8147f05..eb81882d53 100644
--- a/drivers/net/txgbe/txgbe_ptypes.h
+++ b/drivers/net/txgbe/txgbe_ptypes.h
@@ -185,7 +185,7 @@  struct rte_txgbe_ptype {
 #define RTE_PTYPE_L2_ETHER_EAPOL            RTE_PTYPE_L2_ETHER
 #define RTE_PTYPE_L2_ETHER_FILTER           RTE_PTYPE_L2_ETHER
 
-u32 *txgbe_get_supported_ptypes(void);
+u32 *txgbe_get_supported_ptypes(size_t *no_of_elements);
 u32 txgbe_decode_ptype(u8 ptid);
 u8 txgbe_encode_ptype(u32 ptype);
 
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index e49191718a..34a6fd6abe 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -88,7 +88,8 @@  static int vmxnet3_dev_info_get(struct rte_eth_dev *dev,
 static int vmxnet3_hw_ver_get(struct rte_eth_dev *dev,
 			      char *fw_version, size_t fw_size);
 static const uint32_t *
-vmxnet3_dev_supported_ptypes_get(struct rte_eth_dev *dev);
+vmxnet3_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+				       size_t *no_of_elements);
 static int vmxnet3_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
 static int vmxnet3_dev_vlan_filter_set(struct rte_eth_dev *dev,
 				       uint16_t vid, int on);
@@ -1615,16 +1616,19 @@  vmxnet3_hw_ver_get(struct rte_eth_dev *dev,
 }
 
 static const uint32_t *
-vmxnet3_dev_supported_ptypes_get(struct rte_eth_dev *dev)
+vmxnet3_dev_supported_ptypes_get(struct rte_eth_dev *dev,
+		   size_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L3_IPV4_EXT,
-		RTE_PTYPE_L3_IPV4,
-		RTE_PTYPE_UNKNOWN
+		RTE_PTYPE_L3_IPV4
 	};
 
-	if (dev->rx_pkt_burst == vmxnet3_recv_pkts)
+	if (dev->rx_pkt_burst == vmxnet3_recv_pkts) {
+		*no_of_elements = RTE_DIM(ptypes);
 		return ptypes;
+	}
+	*no_of_elements = 0;
 	return NULL;
 }
 
diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
index b482cd12bb..9b03d27e62 100644
--- a/lib/ethdev/ethdev_driver.h
+++ b/lib/ethdev/ethdev_driver.h
@@ -448,7 +448,8 @@  typedef int (*eth_dev_infos_get_t)(struct rte_eth_dev *dev,
 				   struct rte_eth_dev_info *dev_info);
 
 /** @internal Get supported ptypes of an Ethernet device. */
-typedef const uint32_t *(*eth_dev_supported_ptypes_get_t)(struct rte_eth_dev *dev);
+typedef const uint32_t *(*eth_dev_supported_ptypes_get_t)(struct rte_eth_dev *dev,
+				   size_t *no_of_elements);
 
 /**
  * @internal
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index c5e75a91c8..3a7da813aa 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -3857,6 +3857,7 @@  rte_eth_dev_get_supported_ptypes(uint16_t port_id, uint32_t ptype_mask,
 	int i, j;
 	struct rte_eth_dev *dev;
 	const uint32_t *all_ptypes;
+	size_t no_of_elements = 0;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
 	dev = &rte_eth_devices[port_id];
@@ -3870,12 +3871,12 @@  rte_eth_dev_get_supported_ptypes(uint16_t port_id, uint32_t ptype_mask,
 
 	if (*dev->dev_ops->dev_supported_ptypes_get == NULL)
 		return 0;
-	all_ptypes = (*dev->dev_ops->dev_supported_ptypes_get)(dev);
+	all_ptypes = (*dev->dev_ops->dev_supported_ptypes_get)(dev, &no_of_elements);
 
 	if (!all_ptypes)
 		return 0;
 
-	for (i = 0, j = 0; all_ptypes[i] != RTE_PTYPE_UNKNOWN; ++i)
+	for (i = 0, j = 0; all_ptypes[i] < no_of_elements; ++i)
 		if (all_ptypes[i] & ptype_mask) {
 			if (j < num) {
 				ptypes[j] = all_ptypes[i];
@@ -3907,6 +3908,7 @@  rte_eth_dev_set_ptypes(uint16_t port_id, uint32_t ptype_mask,
 	uint32_t unused_mask;
 	unsigned int i, j;
 	int ret;
+	size_t no_of_elements = 0;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
 	dev = &rte_eth_devices[port_id];
@@ -3945,7 +3947,7 @@  rte_eth_dev_set_ptypes(uint16_t port_id, uint32_t ptype_mask,
 		goto ptype_unknown;
 	}
 
-	all_ptypes = (*dev->dev_ops->dev_supported_ptypes_get)(dev);
+	all_ptypes = (*dev->dev_ops->dev_supported_ptypes_get)(dev, &no_of_elements);
 	if (all_ptypes == NULL) {
 		ret = 0;
 		goto ptype_unknown;
@@ -3956,7 +3958,7 @@  rte_eth_dev_set_ptypes(uint16_t port_id, uint32_t ptype_mask,
 	 * set_ptypes array is insufficient fill it partially.
 	 */
 	for (i = 0, j = 0; set_ptypes != NULL &&
-				(all_ptypes[i] != RTE_PTYPE_UNKNOWN); ++i) {
+				(all_ptypes[i] < no_of_elements); ++i) {
 		if (ptype_mask & all_ptypes[i]) {
 			if (j < num - 1) {
 				set_ptypes[j] = all_ptypes[i];