DPDK patches and discussions
 help / color / mirror / Atom feed
From: Ivan Malov <ivan.malov@arknetworks.am>
To: Dimon Zhao <dimon.zhao@nebula-matrix.com>
Cc: dev@dpdk.org, Kyo Liu <kyo.liu@nebula-matrix.com>,
	 Leon Yu <leon.yu@nebula-matrix.com>,
	Sam Chen <sam.chen@nebula-matrix.com>
Subject: Re: [PATCH v4 15/16] net/nbl: add nbl device xstats and stats
Date: Wed, 13 Aug 2025 15:48:29 +0400 (+04)	[thread overview]
Message-ID: <6a088ad9-2d80-88a0-81e8-d6fec073c0c8@arknetworks.am> (raw)
In-Reply-To: <20250813064410.3894506-16-dimon.zhao@nebula-matrix.com>

Hi Dimon,

(please see below)

On Tue, 12 Aug 2025, Dimon Zhao wrote:

> Implement NBL device xstats and stats functions
>
> Signed-off-by: Dimon Zhao <dimon.zhao@nebula-matrix.com>
> ---
> drivers/net/nbl/nbl_dev/nbl_dev.c             | 141 +++++++++++++++++-
> drivers/net/nbl/nbl_dev/nbl_dev.h             |   8 +
> drivers/net/nbl/nbl_dispatch.c                | 111 ++++++++++++++
> drivers/net/nbl/nbl_ethdev.c                  |   4 +
> .../nbl/nbl_hw/nbl_hw_leonis/nbl_res_leonis.c | 113 ++++++++++++++
> drivers/net/nbl/nbl_hw/nbl_txrx.c             | 113 +++++++++++++-
> drivers/net/nbl/nbl_include/nbl_def_channel.h |   5 +
> .../net/nbl/nbl_include/nbl_def_dispatch.h    |   9 ++
> .../net/nbl/nbl_include/nbl_def_resource.h    |  12 +-
> drivers/net/nbl/nbl_include/nbl_include.h     |   4 +
> 10 files changed, 514 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/nbl/nbl_dev/nbl_dev.c b/drivers/net/nbl/nbl_dev/nbl_dev.c
> index b32ab839d5..bab89c707f 100644
> --- a/drivers/net/nbl/nbl_dev/nbl_dev.c
> +++ b/drivers/net/nbl/nbl_dev/nbl_dev.c
> @@ -381,6 +381,126 @@ int nbl_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *rte_stats)
> 	return disp_ops->get_stats(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt), rte_stats);
> }
>
> +int nbl_stats_reset(struct rte_eth_dev *eth_dev)
> +{
> +	struct nbl_adapter *adapter = ETH_DEV_TO_NBL_DEV_PF_PRIV(eth_dev);
> +	struct nbl_dev_mgt *dev_mgt = NBL_ADAPTER_TO_DEV_MGT(adapter);
> +	struct nbl_dispatch_ops *disp_ops = NBL_DEV_MGT_TO_DISP_OPS(dev_mgt);
> +
> +	return disp_ops->reset_stats(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt));
> +}
> +
> +static int nbl_dev_update_hw_xstats(struct nbl_dev_mgt *dev_mgt, struct rte_eth_xstat *xstats,
> +				    u16 hw_xstats_cnt, u16 *xstats_cnt)
> +{
> +	struct nbl_common_info *common = NBL_DEV_MGT_TO_COMMON(dev_mgt);
> +	struct nbl_dispatch_ops *disp_ops = NBL_DEV_MGT_TO_DISP_OPS(dev_mgt);
> +	u64 *hw_stats;
> +	int i;
> +	u16 count = *xstats_cnt;
> +
> +	hw_stats = rte_zmalloc("nbl_xstats_cnt", hw_xstats_cnt * sizeof(u64), 0);

Do you believe it's the best course of action, to allocate and free a bounce
buffer on each invocation? This function is not strictly fast-path, but I'd say
semi-fast. Some applications may want to invoke it pretty often.

> +	if (!hw_stats)
> +		return -ENOMEM;
> +
> +	disp_ops->get_private_stat_data(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt),
> +					common->eth_id, hw_stats, hw_xstats_cnt * sizeof(u64));
> +	for (i = 0; i < hw_xstats_cnt; i++) {
> +		xstats[count].value = hw_stats[i] - dev_mgt->net_dev->hw_xstats_offset[i];
> +		xstats[count].id = count;
> +		count++;
> +	}
> +
> +	*xstats_cnt = count;
> +	rte_free(hw_stats);
> +	return 0;
> +}
> +
> +int nbl_xstats_get(struct rte_eth_dev *eth_dev, struct rte_eth_xstat *xstats, unsigned int n)
> +{
> +	struct nbl_adapter *adapter = ETH_DEV_TO_NBL_DEV_PF_PRIV(eth_dev);
> +	struct nbl_dev_mgt *dev_mgt = NBL_ADAPTER_TO_DEV_MGT(adapter);
> +	struct nbl_common_info *common = NBL_DEV_MGT_TO_COMMON(dev_mgt);
> +	struct nbl_dispatch_ops *disp_ops = NBL_DEV_MGT_TO_DISP_OPS(dev_mgt);
> +	int ret = 0;
> +	u16 txrx_xstats_cnt = 0, hw_xstats_cnt = 0, xstats_cnt = 0;
> +
> +	if (!xstats)
> +		return 0;
> +
> +	ret = disp_ops->get_txrx_xstats_cnt(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt), &txrx_xstats_cnt);
> +	if (!common->is_vf)
> +		ret |= disp_ops->get_hw_xstats_cnt(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt),
> +						   &hw_xstats_cnt);
> +	if (ret)
> +		return -EIO;
> +
> +	if (n < (txrx_xstats_cnt + hw_xstats_cnt))
> +		return txrx_xstats_cnt + hw_xstats_cnt;
> +
> +	if (txrx_xstats_cnt)
> +		ret = disp_ops->get_txrx_xstats(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt),
> +						xstats, &xstats_cnt);
> +	if (hw_xstats_cnt)
> +		ret |= nbl_dev_update_hw_xstats(dev_mgt, xstats, hw_xstats_cnt, &xstats_cnt);
> +
> +	if (ret)
> +		return -EIO;
> +
> +	return xstats_cnt;
> +}
> +
> +int nbl_xstats_get_names(struct rte_eth_dev *eth_dev,
> +			 struct rte_eth_xstat_name *xstats_names,
> +			 __rte_unused unsigned int limit)
> +{
> +	struct nbl_adapter *adapter = ETH_DEV_TO_NBL_DEV_PF_PRIV(eth_dev);
> +	struct nbl_dev_mgt *dev_mgt = NBL_ADAPTER_TO_DEV_MGT(adapter);
> +	struct nbl_common_info *common = NBL_DEV_MGT_TO_COMMON(dev_mgt);
> +	struct nbl_dispatch_ops *disp_ops = NBL_DEV_MGT_TO_DISP_OPS(dev_mgt);
> +	u16 txrx_xstats_cnt = 0, hw_xstats_cnt = 0, xstats_cnt = 0;
> +	int ret = 0;
> +
> +	ret = disp_ops->get_txrx_xstats_cnt(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt), &txrx_xstats_cnt);

Exceeds 80-column limit.

> +	if (!common->is_vf)
> +		ret |= disp_ops->get_hw_xstats_cnt(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt),
> +							&hw_xstats_cnt);
> +	if (ret)
> +		return -EIO;
> +
> +	if (!xstats_names)
> +		return txrx_xstats_cnt + hw_xstats_cnt;
> +
> +	if (txrx_xstats_cnt)
> +		ret = disp_ops->get_txrx_xstats_names(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt),
> +						      xstats_names, &xstats_cnt);
> +	if (hw_xstats_cnt)
> +		ret |= disp_ops->get_hw_xstats_names(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt),
> +						     xstats_names, &xstats_cnt);
> +	if (ret)
> +		return -EIO;
> +
> +	return xstats_cnt;
> +}
> +
> +int nbl_xstats_reset(struct rte_eth_dev *eth_dev)
> +{
> +	struct nbl_adapter *adapter = ETH_DEV_TO_NBL_DEV_PF_PRIV(eth_dev);
> +	struct nbl_dev_mgt *dev_mgt = NBL_ADAPTER_TO_DEV_MGT(adapter);
> +	struct nbl_common_info *common = NBL_DEV_MGT_TO_COMMON(dev_mgt);
> +	struct nbl_dispatch_ops *disp_ops = NBL_DEV_MGT_TO_DISP_OPS(dev_mgt);
> +	struct nbl_dev_net_mgt *net_dev = dev_mgt->net_dev;
> +
> +	if (!common->is_vf) {
> +		disp_ops->get_private_stat_data(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt),
> +						dev_mgt->common->eth_id,
> +						net_dev->hw_xstats_offset, net_dev->hw_xstats_size);
> +	}
> +
> +	nbl_stats_reset(eth_dev);
> +	return 0;
> +}
> +
> struct nbl_dev_ops dev_ops = {
> };
>
> @@ -435,6 +555,7 @@ static int nbl_dev_common_start(struct nbl_dev_mgt *dev_mgt)
> 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
> 	u8 *mac;
> 	int ret;
> +	u16 priv_cnt = 0;
>
> 	board_info = &common->board_info;
> 	disp_ops->get_board_info(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt), board_info);
> @@ -477,8 +598,25 @@ static int nbl_dev_common_start(struct nbl_dev_mgt *dev_mgt)
> 			goto add_multi_rule_failed;
> 	}
>
> -	return 0;
> +	net_dev->hw_xstats_offset = NULL;
> +	if (!dev_mgt->common->is_vf)
> +		disp_ops->get_hw_xstats_cnt(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt), &priv_cnt);
> +	if (priv_cnt) {
> +		net_dev->hw_xstats_offset = rte_zmalloc("nbl_xstats_cnt",
> +							priv_cnt * sizeof(u64), 0);
> +		net_dev->hw_xstats_size = priv_cnt * sizeof(u64);
> +		if (!net_dev->hw_xstats_offset) {
> +			ret = -ENOMEM;
> +			goto alloc_xstats_offset_failed;
> +		}
> +
> +		disp_ops->get_private_stat_data(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt),
> +						dev_mgt->common->eth_id,
> +						net_dev->hw_xstats_offset, net_dev->hw_xstats_size);
> +	}
>
> +	return 0;
> +alloc_xstats_offset_failed:
> add_multi_rule_failed:
> 	disp_ops->del_macvlan(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt), mac, 0, net_dev->vsi_id);
> add_macvlan_failed:
> @@ -757,6 +895,7 @@ int nbl_dev_init(void *p, struct rte_eth_dev *eth_dev)
> 			       eth_dev->data->mac_addrs[0].addr_bytes);
>
> 	adapter->state = NBL_ETHDEV_INITIALIZED;
> +	eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
> 	disp_ops->get_resource_pt_ops(NBL_DEV_MGT_TO_DISP_PRIV(*dev_mgt),
> 				      &(*dev_mgt)->pt_ops, 0);
>
> diff --git a/drivers/net/nbl/nbl_dev/nbl_dev.h b/drivers/net/nbl/nbl_dev/nbl_dev.h
> index 577a28b32d..1500a782a5 100644
> --- a/drivers/net/nbl/nbl_dev/nbl_dev.h
> +++ b/drivers/net/nbl/nbl_dev/nbl_dev.h
> @@ -41,6 +41,8 @@ struct nbl_dev_net_mgt {
> 	struct rte_eth_dev *eth_dev;
> 	struct nbl_dev_ring_mgt ring_mgt;
> 	struct nbl_eth_link_info eth_link_info;
> +	u64 *hw_xstats_offset;
> +	u32 hw_xstats_size;
> 	u16 vsi_id;
> 	u8 eth_mode;
> 	u8 eth_id;
> @@ -71,5 +73,11 @@ void nbl_rx_queues_release(struct rte_eth_dev *eth_dev, uint16_t queue_id);
> int nbl_dev_infos_get(struct rte_eth_dev *eth_dev __rte_unused, struct rte_eth_dev_info *dev_info);
> int nbl_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete __rte_unused);
> int nbl_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *rte_stats);
> +int nbl_stats_reset(struct rte_eth_dev *eth_dev);
> +int nbl_xstats_get(struct rte_eth_dev *eth_dev, struct rte_eth_xstat *xstats, unsigned int n);
> +int nbl_xstats_get_names(struct rte_eth_dev *eth_dev,
> +			 struct rte_eth_xstat_name *xstats_names,
> +			 __rte_unused unsigned int limit);
> +int nbl_xstats_reset(struct rte_eth_dev *eth_dev);
>
> #endif
> diff --git a/drivers/net/nbl/nbl_dispatch.c b/drivers/net/nbl/nbl_dispatch.c
> index 9382b76ce6..15ea61d8e4 100644
> --- a/drivers/net/nbl/nbl_dispatch.c
> +++ b/drivers/net/nbl/nbl_dispatch.c
> @@ -809,9 +809,94 @@ static int nbl_disp_get_stats(void *priv, struct rte_eth_stats *rte_stats)
> {
> 	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
> 	struct nbl_resource_ops *res_ops = NBL_DISP_MGT_TO_RES_OPS(disp_mgt);
> +
> 	return res_ops->get_stats(NBL_DISP_MGT_TO_RES_PRIV(disp_mgt), rte_stats);
> }
>
> +static int nbl_disp_reset_stats(void *priv)
> +{
> +	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
> +	struct nbl_resource_ops *res_ops = NBL_DISP_MGT_TO_RES_OPS(disp_mgt);
> +
> +	return res_ops->reset_stats(NBL_DISP_MGT_TO_RES_PRIV(disp_mgt));
> +}
> +
> +static int nbl_disp_get_txrx_xstats_cnt(void *priv, u16 *xstats_cnt)
> +{
> +	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
> +	struct nbl_resource_ops *res_ops;
> +
> +	res_ops = NBL_DISP_MGT_TO_RES_OPS(disp_mgt);
> +	return res_ops->get_txrx_xstats_cnt(NBL_DISP_MGT_TO_RES_PRIV(disp_mgt), xstats_cnt);
> +}
> +
> +static int nbl_disp_get_txrx_xstats(void *priv, struct rte_eth_xstat *xstats, u16 *xstats_cnt)
> +{
> +	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
> +	struct nbl_resource_ops *res_ops;
> +
> +	res_ops = NBL_DISP_MGT_TO_RES_OPS(disp_mgt);
> +	return res_ops->get_txrx_xstats(NBL_DISP_MGT_TO_RES_PRIV(disp_mgt), xstats, xstats_cnt);
> +}
> +
> +static int nbl_disp_get_txrx_xstats_names(void *priv, struct rte_eth_xstat_name *xstats_names,
> +					  u16 *xstats_cnt)
> +{
> +	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
> +	struct nbl_resource_ops *res_ops;
> +
> +	res_ops = NBL_DISP_MGT_TO_RES_OPS(disp_mgt);
> +	return res_ops->get_txrx_xstats_names(NBL_DISP_MGT_TO_RES_PRIV(disp_mgt),
> +					 xstats_names, xstats_cnt);
> +}
> +
> +static int nbl_disp_get_hw_xstats_cnt(void *priv, u16 *xstats_cnt)
> +{
> +	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
> +	struct nbl_resource_ops *res_ops;
> +
> +	res_ops = NBL_DISP_MGT_TO_RES_OPS(disp_mgt);
> +	return res_ops->get_hw_xstats_cnt(NBL_DISP_MGT_TO_RES_PRIV(disp_mgt), xstats_cnt);
> +}
> +
> +static int nbl_disp_get_hw_xstats_names(void *priv, struct rte_eth_xstat_name *xstats_names,
> +					u16 *xstats_cnt)
> +{
> +	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
> +	struct nbl_resource_ops *res_ops;
> +
> +	res_ops = NBL_DISP_MGT_TO_RES_OPS(disp_mgt);
> +	return res_ops->get_hw_xstats_names(NBL_DISP_MGT_TO_RES_PRIV(disp_mgt),
> +					    xstats_names, xstats_cnt);
> +}
> +
> +static void nbl_disp_get_private_stat_data(void *priv, u32 eth_id, u64 *data,
> +					   __rte_unused u32 data_len)
> +{
> +	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
> +	struct nbl_resource_ops *res_ops;
> +
> +	res_ops = NBL_DISP_MGT_TO_RES_OPS(disp_mgt);
> +	NBL_OPS_CALL(res_ops->get_private_stat_data,
> +		     (NBL_DISP_MGT_TO_RES_PRIV(disp_mgt), eth_id, data));
> +}
> +
> +static void nbl_disp_get_private_stat_data_req(void *priv, u32 eth_id, u64 *data, u32 data_len)
> +{
> +	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
> +	struct nbl_channel_ops *chan_ops;
> +	struct nbl_chan_send_info chan_send = {0};
> +	struct nbl_chan_param_get_private_stat_data param = {0};
> +
> +	chan_ops = NBL_DISP_MGT_TO_CHAN_OPS(disp_mgt);
> +
> +	param.eth_id = eth_id;
> +	param.data_len = data_len;
> +	NBL_CHAN_SEND(chan_send, 0, NBL_CHAN_MSG_GET_ETH_STATS, &param,
> +		      sizeof(param), data, data_len, 1);
> +	chan_ops->send_msg(NBL_DISP_MGT_TO_CHAN_PRIV(disp_mgt), &chan_send);
> +}
> +
> #define NBL_DISP_OPS_TBL						\
> do {									\
> 	NBL_DISP_SET_OPS(configure_msix_map, nbl_disp_configure_msix_map,			\
> @@ -956,6 +1041,32 @@ do {									\
> 	NBL_DISP_SET_OPS(get_stats, nbl_disp_get_stats,			\
> 			 NBL_DISP_CTRL_LVL_ALWAYS, -1,			\
> 			 NULL, NULL);					\
> +	NBL_DISP_SET_OPS(reset_stats, nbl_disp_reset_stats,		\
> +			 NBL_DISP_CTRL_LVL_ALWAYS, -1,			\
> +			 NULL, NULL);					\
> +	NBL_DISP_SET_OPS(get_txrx_xstats_cnt,				\
> +			 nbl_disp_get_txrx_xstats_cnt,			\
> +			 NBL_DISP_CTRL_LVL_ALWAYS, -1,			\
> +			 NULL, NULL);					\
> +	NBL_DISP_SET_OPS(get_txrx_xstats, nbl_disp_get_txrx_xstats,	\
> +			 NBL_DISP_CTRL_LVL_ALWAYS, -1,			\
> +			 NULL, NULL);					\
> +	NBL_DISP_SET_OPS(get_txrx_xstats_names,				\
> +			 nbl_disp_get_txrx_xstats_names,		\
> +			 NBL_DISP_CTRL_LVL_ALWAYS, -1,			\
> +			 NULL, NULL);					\
> +	NBL_DISP_SET_OPS(get_hw_xstats_cnt, nbl_disp_get_hw_xstats_cnt,	\
> +			 NBL_DISP_CTRL_LVL_ALWAYS, -1,			\
> +			 NULL, NULL);					\
> +	NBL_DISP_SET_OPS(get_hw_xstats_names,				\
> +			 nbl_disp_get_hw_xstats_names,			\
> +			 NBL_DISP_CTRL_LVL_ALWAYS, -1,			\
> +			 NULL, NULL);					\
> +	NBL_DISP_SET_OPS(get_private_stat_data,				\
> +			 nbl_disp_get_private_stat_data,		\
> +			 NBL_DISP_CTRL_LVL_MGT,				\
> +			 NBL_CHAN_MSG_GET_ETH_STATS,			\
> +			 nbl_disp_get_private_stat_data_req, NULL);	\
> } while (0)
>
> /* Structure starts here, adding an op should not modify anything below */
> diff --git a/drivers/net/nbl/nbl_ethdev.c b/drivers/net/nbl/nbl_ethdev.c
> index f30aca2b7f..81b8946acc 100644
> --- a/drivers/net/nbl/nbl_ethdev.c
> +++ b/drivers/net/nbl/nbl_ethdev.c
> @@ -41,6 +41,10 @@ const struct eth_dev_ops nbl_eth_dev_ops = {
> 	.dev_infos_get = nbl_dev_infos_get,
> 	.link_update = nbl_link_update,
> 	.stats_get = nbl_stats_get,
> +	.stats_reset = nbl_stats_reset,
> +	.xstats_get = nbl_xstats_get,
> +	.xstats_get_names = nbl_xstats_get_names,
> +	.xstats_reset = nbl_xstats_reset,
> };
>
> static int nbl_eth_dev_init(struct rte_eth_dev *eth_dev)
> diff --git a/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_res_leonis.c b/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_res_leonis.c
> index e7036373f1..41ae423ff0 100644
> --- a/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_res_leonis.c
> +++ b/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_res_leonis.c
> @@ -4,7 +4,120 @@
>
> #include "nbl_res_leonis.h"
>
> +/* store statistics names */
> +struct nbl_xstats_name {
> +	char name[RTE_ETH_XSTATS_NAME_SIZE];
> +};
> +
> +static const struct nbl_xstats_name nbl_stats_strings[] = {
> +	{"eth_frames_tx"},
> +	{"eth_frames_tx_ok"},
> +	{"eth_frames_tx_badfcs"},
> +	{"eth_unicast_frames_tx_ok"},
> +	{"eth_multicast_frames_tx_ok"},
> +	{"eth_broadcast_frames_tx_ok"},
> +	{"eth_macctrl_frames_tx_ok"},
> +	{"eth_fragment_frames_tx"},
> +	{"eth_fragment_frames_tx_ok"},
> +	{"eth_pause_frames_tx"},
> +	{"eth_pause_macctrl_frames_tx"},
> +	{"eth_pfc_frames_tx"},
> +	{"eth_pfc_frames_tx_prio0"},
> +	{"eth_pfc_frames_tx_prio1"},
> +	{"eth_pfc_frames_tx_prio2"},
> +	{"eth_pfc_frames_tx_prio3"},
> +	{"eth_pfc_frames_tx_prio4"},
> +	{"eth_pfc_frames_tx_prio5"},
> +	{"eth_pfc_frames_tx_prio6"},
> +	{"eth_pfc_frames_tx_prio7"},
> +	{"eth_verify_frames_tx"},
> +	{"eth_respond_frames_tx"},
> +	{"eth_frames_tx_64B"},
> +	{"eth_frames_tx_65_to_127B"},
> +	{"eth_frames_tx_128_to_255B"},
> +	{"eth_frames_tx_256_to_511B"},
> +	{"eth_frames_tx_512_to_1023B"},
> +	{"eth_frames_tx_1024_to_1535B"},
> +	{"eth_frames_tx_1536_to_2047B"},
> +	{"eth_frames_tx_2048_to_MAXB"},
> +	{"eth_undersize_frames_tx_goodfcs"},
> +	{"eth_oversize_frames_tx_goodfcs"},
> +	{"eth_undersize_frames_tx_badfcs"},
> +	{"eth_oversize_frames_tx_badfcs"},
> +	{"eth_octets_tx"},
> +	{"eth_octets_tx_ok"},
> +	{"eth_octets_tx_badfcs"},
> +	{"eth_frames_rx"},
> +	{"eth_frames_rx_ok"},
> +	{"eth_frames_rx_badfcs"},
> +	{"eth_undersize_frames_rx_goodfcs"},
> +	{"eth_undersize_frames_rx_badfcs"},
> +	{"eth_oversize_frames_rx_goodfcs"},
> +	{"eth_oversize_frames_rx_badfcs"},
> +	{"eth_frames_rx_misc_error"},
> +	{"eth_frames_rx_misc_dropped"},
> +	{"eth_unicast_frames_rx_ok"},
> +	{"eth_multicast_frames_rx_ok"},
> +	{"eth_broadcast_frames_rx_ok"},
> +	{"eth_pause_frames_rx"},
> +	{"eth_pfc_frames_rx"},
> +	{"eth_pfc_frames_rx_prio0"},
> +	{"eth_pfc_frames_rx_prio1"},
> +	{"eth_pfc_frames_rx_prio2"},
> +	{"eth_pfc_frames_rx_prio3"},
> +	{"eth_pfc_frames_rx_prio4"},
> +	{"eth_pfc_frames_rx_prio5"},
> +	{"eth_pfc_frames_rx_prio6"},
> +	{"eth_pfc_frames_rx_prio7"},
> +	{"eth_macctrl_frames_rx"},
> +	{"eth_verify_frames_rx_ok"},
> +	{"eth_respond_frames_rx_ok"},
> +	{"eth_fragment_frames_rx_ok"},
> +	{"eth_fragment_rx_smdc_nocontext"},
> +	{"eth_fragment_rx_smds_seq_error"},
> +	{"eth_fragment_rx_smdc_seq_error"},
> +	{"eth_fragment_rx_frag_cnt_error"},
> +	{"eth_frames_assembled_ok"},
> +	{"eth_frames_assembled_error"},
> +	{"eth_frames_rx_64B"},
> +	{"eth_frames_rx_65_to_127B"},
> +	{"eth_frames_rx_128_to_255B"},
> +	{"eth_frames_rx_256_to_511B"},
> +	{"eth_frames_rx_512_to_1023B"},
> +	{"eth_frames_rx_1024_to_1535B"},
> +	{"eth_frames_rx_1536_to_2047B"},
> +	{"eth_frames_rx_2048_to_MAXB"},
> +	{"eth_octets_rx"},
> +	{"eth_octets_rx_ok"},
> +	{"eth_octets_rx_badfcs"},
> +	{"eth_octets_rx_dropped"},
> +};
> +
> +static int nbl_get_xstats_cnt(__rte_unused void *priv, u16 *xstats_cnt)
> +{
> +	*xstats_cnt = ARRAY_SIZE(nbl_stats_strings);
> +	return 0;
> +}
> +
> +static int nbl_get_xstats_names(__rte_unused void *priv,
> +				struct rte_eth_xstat_name *xstats_names,
> +				u16 *xstats_cnt)
> +{
> +	u32 i = 0;
> +	u16 count = *xstats_cnt;
> +
> +	for (i = 0; i < ARRAY_SIZE(nbl_stats_strings); i++) {
> +		strlcpy(xstats_names[count].name, nbl_stats_strings[i].name,
> +			sizeof(nbl_stats_strings[count].name));
> +		count++;
> +	}
> +	*xstats_cnt = count;
> +	return 0;
> +}
> +
> static struct nbl_resource_ops res_ops = {
> +	.get_hw_xstats_cnt = nbl_get_xstats_cnt,
> +	.get_hw_xstats_names = nbl_get_xstats_names,
> };
>
> static bool is_ops_inited;
> diff --git a/drivers/net/nbl/nbl_hw/nbl_txrx.c b/drivers/net/nbl/nbl_hw/nbl_txrx.c
> index d0acbe867d..3de4eedbdb 100644
> --- a/drivers/net/nbl/nbl_hw/nbl_txrx.c
> +++ b/drivers/net/nbl/nbl_hw/nbl_txrx.c
> @@ -536,6 +536,7 @@ nbl_res_txrx_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, u16 nb_pkts, u
> 			txe->mbuf = tx_pkt;
>
> 			data_len = tx_pkt->data_len;
> +			txq->txq_stats.tx_bytes += tx_pkt->data_len;
> 			dma_addr = rte_mbuf_data_iova(tx_pkt);
> 			tx_desc->addr = NBL_DMA_ADDERSS_FULL_TRANSLATE(txq, dma_addr) + addr_offset;
> 			tx_desc->len = data_len - addr_offset;
> @@ -615,6 +616,8 @@ nbl_res_txrx_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, u16 nb_pkts)
> 			rx_ext_hdr = (union nbl_rx_extend_head *)((char *)rx_mbuf->buf_addr +
> 								  RTE_PKTMBUF_HEADROOM);
> 			num_sg = rx_ext_hdr->common.num_buffers;
> +			if (num_sg > 1)
> +				rxq->rxq_stats.rx_multi_descs++;
>
> 			rx_mbuf->nb_segs = num_sg;
> 			rx_mbuf->data_len = rx_desc->len - rxq->exthdr_len;
> @@ -642,15 +645,20 @@ nbl_res_txrx_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, u16 nb_pkts)
> 		if (--num_sg)
> 			continue;
> 		if (drop) {
> +			rxq->rxq_stats.rx_drop_proto++;
> 			rte_pktmbuf_free(rx_mbuf);
> 			continue;
> 		}
> 		rx_pkts[nb_recv_pkts++] = rx_mbuf;
> +		rxq->rxq_stats.rx_bytes += rx_mbuf->pkt_len;
> 	}
>
> 	/* BUG on duplicate pkt free */
> -	if (unlikely(num_sg))
> +	if (unlikely(num_sg)) {
> +		rxq->rxq_stats.rx_ierror++;
> 		rte_pktmbuf_free(rx_mbuf);
> +	}
> +
> 	/* clean memory */
> 	rxq->next_to_clean = desc_index;
> 	fill_num = rxq->vq_free_cnt;
> @@ -720,6 +728,105 @@ static int nbl_res_txrx_get_stats(void *priv, struct rte_eth_stats *rte_stats)
> 	return 0;
> }
>
> +static int
> +nbl_res_txrx_reset_stats(void *priv)
> +{
> +	struct nbl_resource_mgt *res_mgt = (struct nbl_resource_mgt *)priv;
> +	struct rte_eth_dev *eth_dev = res_mgt->eth_dev;
> +	struct nbl_res_rx_ring *rxq;
> +	struct nbl_rxq_stats *rxq_stats;
> +	struct nbl_res_tx_ring  *txq;
> +	struct nbl_txq_stats *txq_stats;
> +	uint32_t i;
> +
> +	/* Add software counters. */
> +	for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
> +		rxq = eth_dev->data->rx_queues[i];
> +		if (unlikely(rxq == NULL))
> +			continue;
> +
> +		rxq_stats = &rxq->rxq_stats;
> +		memset(rxq_stats, 0, sizeof(struct nbl_rxq_stats));

What if the application has dedicated lcores for datapath Rx/Tx burst calls and
uses another, admin core to query/reset statistics?

Thank you.

> +	}
> +
> +	for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
> +		txq = eth_dev->data->tx_queues[i];
> +		if (unlikely(txq == NULL))
> +			continue;
> +
> +		txq_stats = &txq->txq_stats;
> +		memset(txq_stats, 0, sizeof(struct nbl_txq_stats));
> +	}
> +
> +	return 0;
> +}
> +
> +/* store statistics names */
> +struct nbl_txrx_xstats_name {
> +	char name[RTE_ETH_XSTATS_NAME_SIZE];
> +};
> +
> +static const struct nbl_txrx_xstats_name nbl_stats_strings[] = {
> +	{"rx_multidescs_packets"},
> +	{"rx_drop_noport_packets"},
> +	{"rx_drop_proto_packets"},
> +};
> +
> +static int nbl_res_txrx_get_xstats_cnt(__rte_unused void *priv, u16 *xstats_cnt)
> +{
> +	*xstats_cnt = ARRAY_SIZE(nbl_stats_strings);
> +	return 0;
> +}
> +
> +static int nbl_res_txrx_get_xstats(void *priv, struct rte_eth_xstat *xstats, u16 *xstats_cnt)
> +{
> +	struct nbl_resource_mgt *res_mgt = (struct nbl_resource_mgt *)priv;
> +	struct nbl_txrx_mgt *txrx_mgt = NBL_RES_MGT_TO_TXRX_MGT(res_mgt);
> +	struct nbl_res_rx_ring *rxq;
> +	uint64_t rx_multi_descs = 0, rx_drop_noport = 0, rx_drop_proto = 0;
> +	unsigned int i = 0;
> +	u16 count = *xstats_cnt;
> +
> +	/* todo: get eth stats from emp */
> +	for (i = 0; i < txrx_mgt->rx_ring_num; i++) {
> +		rxq = NBL_RES_MGT_TO_RX_RING(res_mgt, i);
> +
> +		if (unlikely(rxq == NULL))
> +			return -EINVAL;
> +
> +		rx_multi_descs += rxq->rxq_stats.rx_multi_descs;
> +		rx_drop_noport += rxq->rxq_stats.rx_drop_noport;
> +		rx_drop_proto += rxq->rxq_stats.rx_drop_proto;
> +	}
> +
> +	xstats[count].value = rx_multi_descs;
> +	xstats[count].id = count;
> +	xstats[count + 1].value = rx_drop_noport;
> +	xstats[count + 1].id = count + 1;
> +	xstats[count + 2].value = rx_drop_proto;
> +	xstats[count + 2].id = count + 2;
> +
> +	*xstats_cnt = count + 3;
> +
> +	return 0;
> +}
> +
> +static int nbl_res_txrx_get_xstats_names(__rte_unused void *priv,
> +					 struct rte_eth_xstat_name *xstats_names,
> +					 u16 *xstats_cnt)
> +{
> +	unsigned int i = 0;
> +	u16 count = *xstats_cnt;
> +
> +	for (i = 0; i < ARRAY_SIZE(nbl_stats_strings); i++) {
> +		strlcpy(xstats_names[count].name, nbl_stats_strings[i].name,
> +			sizeof(nbl_stats_strings[count].name));
> +		count++;
> +	}
> +	*xstats_cnt = count;
> +	return 0;
> +}
> +
> /* NBL_TXRX_SET_OPS(ops_name, func)
>  *
>  * Use X Macros to reduce setup and remove codes.
> @@ -738,6 +845,10 @@ do {										\
> 	NBL_TXRX_SET_OPS(update_rx_ring, nbl_res_txrx_update_rx_ring);		\
> 	NBL_TXRX_SET_OPS(get_resource_pt_ops, nbl_res_get_pt_ops);		\
> 	NBL_TXRX_SET_OPS(get_stats, nbl_res_txrx_get_stats);			\
> +	NBL_TXRX_SET_OPS(reset_stats, nbl_res_txrx_reset_stats);		\
> +	NBL_TXRX_SET_OPS(get_txrx_xstats_cnt, nbl_res_txrx_get_xstats_cnt);	\
> +	NBL_TXRX_SET_OPS(get_txrx_xstats_names, nbl_res_txrx_get_xstats_names);	\
> +	NBL_TXRX_SET_OPS(get_txrx_xstats, nbl_res_txrx_get_xstats);		\
> } while (0)
>
> /* Structure starts here, adding an op should not modify anything below */
> diff --git a/drivers/net/nbl/nbl_include/nbl_def_channel.h b/drivers/net/nbl/nbl_include/nbl_def_channel.h
> index 481a725a3d..39050a3999 100644
> --- a/drivers/net/nbl/nbl_include/nbl_def_channel.h
> +++ b/drivers/net/nbl/nbl_include/nbl_def_channel.h
> @@ -385,6 +385,11 @@ struct nbl_chan_param_get_link_state {
> 	u8 eth_id;
> };
>
> +struct nbl_chan_param_get_private_stat_data {
> +	u32 eth_id;
> +	u32 data_len;
> +};
> +
> struct nbl_chan_send_info {
> 	uint16_t dstid;
> 	uint16_t msg_type;
> diff --git a/drivers/net/nbl/nbl_include/nbl_def_dispatch.h b/drivers/net/nbl/nbl_include/nbl_def_dispatch.h
> index 0139b37ad1..f38a10e5f4 100644
> --- a/drivers/net/nbl/nbl_include/nbl_def_dispatch.h
> +++ b/drivers/net/nbl/nbl_include/nbl_def_dispatch.h
> @@ -74,6 +74,15 @@ struct nbl_dispatch_ops {
> 	void (*get_board_info)(void *priv, struct nbl_board_port_info *board_info);
> 	void (*get_link_state)(void *priv, u8 eth_id, struct nbl_eth_link_info *eth_link_info);
> 	int (*get_stats)(void *priv, struct rte_eth_stats *rte_stats);
> +	int (*reset_stats)(void *priv);
> +	int (*get_txrx_xstats_cnt)(void *priv, u16 *xstats_cnt);
> +	int (*get_txrx_xstats)(void *priv, struct rte_eth_xstat *xstats, u16 *xstats_cnt);
> +	int (*get_txrx_xstats_names)(void *priv, struct rte_eth_xstat_name *xstats_names,
> +				     u16 *xstats_cnt);
> +	int (*get_hw_xstats_cnt)(void *priv, u16 *xstats_cnt);
> +	int (*get_hw_xstats_names)(void *priv, struct rte_eth_xstat_name *xstats_names,
> +				   u16 *xstats_cnt);
> +	void (*get_private_stat_data)(void *priv, u32 eth_id, u64 *data, u32 data_len);
>
> 	void (*dummy_func)(void *priv);
> };
> diff --git a/drivers/net/nbl/nbl_include/nbl_def_resource.h b/drivers/net/nbl/nbl_include/nbl_def_resource.h
> index c14fdc773e..5b32506be1 100644
> --- a/drivers/net/nbl/nbl_include/nbl_def_resource.h
> +++ b/drivers/net/nbl/nbl_include/nbl_def_resource.h
> @@ -46,6 +46,14 @@ struct nbl_resource_ops {
> 	void (*release_rx_ring)(void *priv, u16 queue_idx);
> 	int (*get_stats)(void *priv, struct rte_eth_stats *rte_stats);
> 	int (*reset_stats)(void *priv);
> +	int (*get_txrx_xstats_cnt)(void *priv, u16 *xstats_cnt);
> +	int (*get_txrx_xstats)(void *priv, struct rte_eth_xstat *xstats, u16 *xstats_cnt);
> +	int (*get_txrx_xstats_names)(void *priv, struct rte_eth_xstat_name *xstats_names,
> +				     u16 *xstats_cnt);
> +	int (*get_hw_xstats_cnt)(void *priv, u16 *xstats_cnt);
> +	int (*get_hw_xstats_names)(void *priv, struct rte_eth_xstat_name *xstats_names,
> +				   u16 *xstats_cnt);
> +	void (*get_private_stat_data)(void *priv, u32 eth_id, u64 *data);
> 	void (*update_rx_ring)(void *priv, u16 queue_idx);
> 	u16 (*get_tx_ehdr_len)(void *priv);
> 	int (*alloc_txrx_queues)(void *priv, u16 vsi_id, u16 queue_num);
> @@ -58,10 +66,6 @@ struct nbl_resource_ops {
> 	void (*cfg_txrx_vlan)(void *priv, u16 vlan_tci, u16 vlan_proto);
> 	int (*txrx_burst_mode_get)(void *priv, struct rte_eth_dev *dev,
> 				   struct rte_eth_burst_mode *mode, bool is_tx);
> -	int (*get_txrx_xstats_cnt)(void *priv, u16 *xstats_cnt);
> -	int (*get_txrx_xstats)(void *priv, struct rte_eth_xstat *xstats, u16 *xstats_cnt);
> -	int (*get_txrx_xstats_names)(void *priv, struct rte_eth_xstat_name *xstats_names,
> -				     u16 *xstats_cnt);
> 	int (*add_macvlan)(void *priv, u8 *mac, u16 vlan_id, u16 vsi_id);
> 	void (*del_macvlan)(void *priv, u8 *mac, u16 vlan_id, u16 vsi_id);
> 	int (*add_multi_rule)(void *priv, u16 vsi_id);
> diff --git a/drivers/net/nbl/nbl_include/nbl_include.h b/drivers/net/nbl/nbl_include/nbl_include.h
> index 14c41a0139..a0e18cec20 100644
> --- a/drivers/net/nbl/nbl_include/nbl_include.h
> +++ b/drivers/net/nbl/nbl_include/nbl_include.h
> @@ -50,6 +50,10 @@ typedef int32_t s32;
> typedef int16_t s16;
> typedef int8_t s8;
>
> +#ifndef ARRAY_SIZE
> +#define ARRAY_SIZE(arr) RTE_DIM(arr)
> +#endif
> +
> /* Used for macros to pass checkpatch */
> #define NBL_NAME(x)				x
> #define BIT(a)					(1UL << (a))
> -- 
> 2.34.1
>
>

  reply	other threads:[~2025-08-13 11:48 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-27  1:40 [PATCH v3 00/16] NBL PMD for Nebulamatrix NICs dimon.zhao
2025-06-27  1:40 ` [PATCH v3 01/16] net/nbl: add doc and minimum nbl build framework dimon.zhao
2025-06-27  1:40 ` [PATCH v3 02/16] net/nbl: add simple probe/remove and log module dimon.zhao
2025-06-27  1:40 ` [PATCH v3 03/16] net/nbl: add PHY layer definitions and implementation dimon.zhao
2025-06-27  1:40 ` [PATCH v3 04/16] net/nbl: add Channel " dimon.zhao
2025-06-27  1:40 ` [PATCH v3 05/16] net/nbl: add Resource " dimon.zhao
2025-06-27  1:40 ` [PATCH v3 06/16] net/nbl: add Dispatch " dimon.zhao
2025-06-27  1:40 ` [PATCH v3 07/16] net/nbl: add Dev " dimon.zhao
2025-06-27  1:40 ` [PATCH v3 08/16] net/nbl: add complete device init and uninit functionality dimon.zhao
2025-06-27  1:40 ` [PATCH v3 09/16] net/nbl: add UIO and VFIO mode for nbl dimon.zhao
2025-06-27  1:40 ` [PATCH v3 10/16] net/nbl: add nbl coexistence " dimon.zhao
2025-06-27  1:40 ` [PATCH v3 11/16] net/nbl: add nbl ethdev configuration dimon.zhao
2025-06-27  1:40 ` [PATCH v3 12/16] net/nbl: add nbl device rxtx queue setup and release ops dimon.zhao
2025-06-27  1:40 ` [PATCH v3 13/16] net/nbl: add nbl device start and stop ops dimon.zhao
2025-06-27  1:40 ` [PATCH v3 14/16] net/nbl: add nbl device Tx and Rx burst dimon.zhao
2025-06-27  1:40 ` [PATCH v3 15/16] net/nbl: add nbl device xstats and stats dimon.zhao
2025-06-27  1:40 ` [PATCH v3 16/16] net/nbl: nbl device support set MTU and promisc dimon.zhao
2025-06-27 21:07 ` [PATCH v3 00/16] NBL PMD for Nebulamatrix NICs Stephen Hemminger
2025-06-27 21:40   ` Thomas Monjalon
2025-08-13  6:43 ` [PATCH v4 " Dimon Zhao
2025-08-13  6:43   ` [PATCH v4 01/16] net/nbl: add doc and minimum nbl build framework Dimon Zhao
2025-08-13 14:43     ` Stephen Hemminger
2025-08-13  6:43   ` [PATCH v4 02/16] net/nbl: add simple probe/remove and log module Dimon Zhao
2025-08-13  6:43   ` [PATCH v4 03/16] net/nbl: add PHY layer definitions and implementation Dimon Zhao
2025-08-13  9:30     ` Ivan Malov
2025-08-13 14:19       ` Stephen Hemminger
2025-08-13  6:43   ` [PATCH v4 04/16] net/nbl: add Channel " Dimon Zhao
2025-08-13  9:54     ` Ivan Malov
2025-08-13 14:21     ` Stephen Hemminger
2025-08-13 14:22     ` Stephen Hemminger
2025-08-13 14:25     ` Stephen Hemminger
2025-08-13 14:28     ` Stephen Hemminger
2025-08-13  6:43   ` [PATCH v4 05/16] net/nbl: add Resource " Dimon Zhao
2025-08-13  6:44   ` [PATCH v4 06/16] net/nbl: add Dispatch " Dimon Zhao
2025-08-13  6:44   ` [PATCH v4 07/16] net/nbl: add Dev " Dimon Zhao
2025-08-13 10:12     ` Ivan Malov
2025-08-13  6:44   ` [PATCH v4 08/16] net/nbl: add complete device init and uninit functionality Dimon Zhao
2025-08-13  6:44   ` [PATCH v4 09/16] net/nbl: add UIO and VFIO mode for nbl Dimon Zhao
2025-08-13  6:44   ` [PATCH v4 10/16] net/nbl: add nbl coexistence " Dimon Zhao
2025-08-13 10:35     ` Ivan Malov
2025-08-13  6:44   ` [PATCH v4 11/16] net/nbl: add nbl ethdev configuration Dimon Zhao
2025-08-13 10:40     ` Ivan Malov
2025-08-13  6:44   ` [PATCH v4 12/16] net/nbl: add nbl device rxtx queue setup and release ops Dimon Zhao
2025-08-13 12:00     ` Ivan Malov
2025-08-13  6:44   ` [PATCH v4 13/16] net/nbl: add nbl device start and stop ops Dimon Zhao
2025-08-13  6:44   ` [PATCH v4 14/16] net/nbl: add nbl device Tx and Rx burst Dimon Zhao
2025-08-13 11:31     ` Ivan Malov
2025-08-13  6:44   ` [PATCH v4 15/16] net/nbl: add nbl device xstats and stats Dimon Zhao
2025-08-13 11:48     ` Ivan Malov [this message]
2025-08-13 14:27       ` Stephen Hemminger
2025-08-13  6:44   ` [PATCH v4 16/16] net/nbl: nbl device support set MTU and promisc Dimon Zhao
2025-08-13 12:06     ` Ivan Malov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6a088ad9-2d80-88a0-81e8-d6fec073c0c8@arknetworks.am \
    --to=ivan.malov@arknetworks.am \
    --cc=dev@dpdk.org \
    --cc=dimon.zhao@nebula-matrix.com \
    --cc=kyo.liu@nebula-matrix.com \
    --cc=leon.yu@nebula-matrix.com \
    --cc=sam.chen@nebula-matrix.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).