[v3] ethdev: fix getting supported ptypes list

Message ID 20231221184001.928922-1-venkatx.sivaramakrishnan@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series [v3] ethdev: fix getting supported ptypes list |

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/github-robot: build success github build: passed
ci/Intel-compilation fail Compilation issues
ci/intel-Testing success Testing PASS
ci/intel-Functional success Functional PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-abi-testing warning Testing issues
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-compile-amd64-testing fail Testing issues
ci/iol-unit-amd64-testing fail Testing issues
ci/iol-sample-apps-testing success Testing PASS
ci/iol-unit-arm64-testing success Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-compile-arm64-testing success Testing PASS

Commit Message

Sivaramakrishnan Venkat Dec. 21, 2023, 6:40 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: 4790935 ("ethdev: make device operations struct private")
Cc: ferruh.yigit@intel.com
CC: stable@dpdk.org

--
V3: Rework function pointer to return number of elements and remove
    the need for RTE_PTYPE_UNKNOWN in list

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         |  7 +++++--
 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/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/netvsc/hn_var.h            |  3 ++-
 drivers/net/netvsc/hn_vf.c             |  5 +++--
 drivers/net/nfp/nfp_net_common.c       | 12 +++++++++---
 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           |  8 ++++++--
 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          |  4 +++-
 drivers/net/thunderx/nicvf_ethdev.c    |  4 +++-
 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 ++++++----
 58 files changed, 280 insertions(+), 172 deletions(-)
  

Comments

Tyler Retzlaff Dec. 21, 2023, 9:03 p.m. UTC | #1
On Thu, Dec 21, 2023 at 06:40:01PM +0000, 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: 4790935 ("ethdev: make device operations struct private")
> Cc: ferruh.yigit@intel.com
> CC: stable@dpdk.org
> 
> --
> V3: Rework function pointer to return number of elements and remove
>     the need for RTE_PTYPE_UNKNOWN in list
> 
> 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         |  7 +++++--
>  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/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/netvsc/hn_var.h            |  3 ++-
>  drivers/net/netvsc/hn_vf.c             |  5 +++--
>  drivers/net/nfp/nfp_net_common.c       | 12 +++++++++---
>  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           |  8 ++++++--
>  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          |  4 +++-
>  drivers/net/thunderx/nicvf_ethdev.c    |  4 +++-
>  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 ++++++----
>  58 files changed, 280 insertions(+), 172 deletions(-)
> 
> diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
> index 3a028f4290..d0d9e121db 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,
> +	uint32_t *no_of_elements);

based on the code that follows no_of_elements should probably be type
size_t * because the resulting type of the expression using RTE_DIM.

clearly it will never overflow uint32_t i suppose you could explicitly
cast to make it clear the potential truncation is on purpose.

>  
>  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,
> +	uint32_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);
				  ^^^^^^^^^^^^^^^ <-- is T = size_t

>  		return ptypes;
> +	}
>  
>  	return NULL;
>  }
  
David Marchand Dec. 22, 2023, 8:21 a.m. UTC | #2
On Thu, Dec 21, 2023 at 7:40 PM Sivaramakrishnan Venkat
<venkatx.sivaramakrishnan@intel.com> wrote:
>
> Incorrect ptypes list causes buffer overflow for Address Sanitizer
> run.Previously, the last element in the ptypes lists to be

Which driver(s) is(are) affected?
We need separated fixes for backporting.


> "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: 4790935 ("ethdev: make device operations struct private")

I doubt it is a correct Fixes: tag.

> Cc: ferruh.yigit@intel.com
> CC: stable@dpdk.org

Once the fixes are separated, then the driver API update proposed in
this patch can be done in a second step (and it won't be backported).

The CI caught unconverted drivers, please fix.
  
Sivaramakrishnan Venkat Jan. 4, 2024, 5:51 p.m. UTC | #3
[PATCH 1] - net/tap: fix buffer overflow for ptypes list through
updation of last element. The first patch is for drivers for backporting

[PATCH 2] - net/tap: fix buffer overflow for ptypes list through
through driver API update. The second patch is for drivers API update


Sivaramakrishnan Venkat (2):
  net/tap: fix buffer overflow for ptypes list through updation of last
    element.
  net/tap: fix buffer overflow for ptypes list through driver API update

 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         |  8 ++++++--
 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     |  4 +++-
 drivers/net/mvpp2/mrvl_ethdev.c        |  4 +++-
 drivers/net/netvsc/hn_var.h            |  3 ++-
 drivers/net/netvsc/hn_vf.c             |  5 +++--
 drivers/net/nfp/nfp_net_common.c       | 14 ++++++++++----
 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           |  8 ++++++--
 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          |  6 ++++--
 drivers/net/thunderx/nicvf_ethdev.c    |  8 +++++---
 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, 295 insertions(+), 181 deletions(-)
  

Patch

diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
index 3a028f4290..d0d9e121db 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,
+	uint32_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,
+	uint32_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..437fd35fd2 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,
+	uint32_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,
+	uint32_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..2d4407dba3 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,
+			 uint32_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..6dc42d3f18 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,
+				 uint32_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..56253c6353 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,
+	uint32_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..680462d774 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,
+		     uint32_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..c56a867722 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,
+				     uint32_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..f85003e83a 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,
+			 uint32_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 ef4c06db6a..922975b0b6 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,
+				uint32_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER,
@@ -368,8 +369,10 @@  dpaa_supported_ptypes_get(struct rte_eth_dev *dev)
 
 	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;
+	}
 	return NULL;
 }
 
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 8e610b6bba..7f18bf2a34 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,
+			 uint32_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..585a056e1e 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,
+			      uint32_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,
+		       uint32_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..97e71ad842 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,
+		    uint32_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..14283d2b7a 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,
+	uint32_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..b254e74aaa 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,
+		  uint32_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..33f56a07b9 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,
+	uint32_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,
+	uint32_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..b9f801c842 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,
+		    uint32_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..b66f47be87 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,
+			   uint32_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..315925095d 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,
+				uint32_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..bf5db78c76 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,
+			    uint32_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..d5af4b7836 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,
+			     uint32_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,
+		    uint32_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..9f6e066189 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,
+				uint32_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..81ca84079c 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,
+			uint32_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..3a432b8b50 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,
+					  uint32_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..c1683cbf78 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,
+		     uint32_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..a487e64634 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,
+			uint32_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,
+		uint32_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..50fa10890d 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,
+	uint32_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..34c46e1bc0 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,
+	uint32_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..00d4deb2c9 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,
+				uint32_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,
+		     uint32_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/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index d90570add6..4eb7fe14b6 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,
+		       uint32_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..7a8ee99357 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,
+		      uint32_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..526b03cc9c 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,
+			 uint32_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..5dbc24cc21 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,
+			  uint32_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/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h
index e37946804d..f832635ca2 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,
+			       uint32_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..2df1da5ea1 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,
+			   uint32_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 e969b840d6..d565f3cd57 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,
+		uint32_t *no_of_elements)
 {
 	struct nfp_net_hw *net_hw;
 	static const uint32_t ptypes[] = {
@@ -1301,13 +1302,18 @@  nfp_net_supported_ptypes_get(struct rte_eth_dev *dev)
 		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..ef7f930fed 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,
+		uint32_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..3d7a818e91 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,
+		uint32_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..99cbfaad61 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,
+				      uint32_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..55d147736b 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(uint32_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..98ecd869bf 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(uint32_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..81bd3ff05e 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,
+				uint32_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 551f3cf193..9cd4552137 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,
+		   uint32_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		/*todo -= add more types */
@@ -524,8 +525,11 @@  pfe_supported_ptypes_get(struct rte_eth_dev *dev)
 	};
 
 	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..db195368d7 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,
+			      uint32_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..a26dc37054 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, uint32_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..4c350c064e 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,
+		  uint32_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..a84cdca3d3 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,
+				uint32_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..02d3925aae 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,
+			  uint32_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..0332537dce 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,
+		     uint32_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..f11be38bc3 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,
+			uint32_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 b41fa971cb..423542c40d 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,
+		  uint32_t *no_of_elements)
 {
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_INNER_L2_ETHER,
@@ -1805,6 +1806,7 @@  tap_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 		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 a504d41dfe..1dffedcf0c 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,
+			 uint32_t *no_of_elements)
 {
 	size_t copied;
 	static uint32_t ptypes[32];
@@ -412,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..31afffc046 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,
+			    uint32_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..0488626aac 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,
+				      uint32_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..b28249e6a2 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(uint32_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..36d63ebb0d 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(uint32_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..5560709014 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,
+				       uint32_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,
+		   uint32_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..7662406a42 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,
+				   uint32_t *no_of_elements);
 
 /**
  * @internal
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index 3858983fcc..e330e88b1d 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;
+	uint32_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;
+	uint32_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];