Implement NBL device xstats and stats functions Signed-off-by: Kyo Liu <kyo....@nebula-matrix.com> --- drivers/net/nbl/nbl_dev/nbl_dev.c | 148 +++++++++++++++++- drivers/net/nbl/nbl_dev/nbl_dev.h | 2 + drivers/net/nbl/nbl_dispatch.c | 111 +++++++++++++ .../nbl/nbl_hw/nbl_hw_leonis/nbl_res_leonis.c | 113 +++++++++++++ drivers/net/nbl/nbl_hw/nbl_txrx.c | 112 ++++++++++++- 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 + 9 files changed, 510 insertions(+), 6 deletions(-)
diff --git a/drivers/net/nbl/nbl_dev/nbl_dev.c b/drivers/net/nbl/nbl_dev/nbl_dev.c index 949d42506d..4fa132ae1c 100644 --- a/drivers/net/nbl/nbl_dev/nbl_dev.c +++ b/drivers/net/nbl/nbl_dev/nbl_dev.c @@ -384,6 +384,129 @@ static int nbl_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *rte_ return disp_ops->get_stats(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt), rte_stats); } +static 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); + 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; +} + +static 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; +} + +static 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); + 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; +} + + + +static 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 = { .dev_configure = nbl_dev_configure, .dev_start = nbl_dev_port_start, @@ -396,6 +519,10 @@ struct nbl_dev_ops 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_dev_setup_chan_queue(struct nbl_adapter *adapter) @@ -438,6 +565,7 @@ static int nbl_dev_common_start(struct nbl_dev_mgt *dev_mgt) struct nbl_board_port_info *board_info; 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); @@ -456,8 +584,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); @@ -719,6 +864,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 f58699a51e..1541aebba5 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; diff --git a/drivers/net/nbl/nbl_dispatch.c b/drivers/net/nbl/nbl_dispatch.c index 33964641c4..e18b543ad6 100644 --- a/drivers/net/nbl/nbl_dispatch.c +++ b/drivers/net/nbl/nbl_dispatch.c @@ -724,9 +724,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, ¶m, + 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(alloc_txrx_queues, nbl_disp_alloc_txrx_queues, \ @@ -859,6 +944,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_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 361415cd21..0436f0df88 100644 --- a/drivers/net/nbl/nbl_hw/nbl_txrx.c +++ b/drivers/net/nbl/nbl_hw/nbl_txrx.c @@ -538,6 +538,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; @@ -617,6 +618,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; @@ -644,15 +647,19 @@ 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 dumplicate 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; @@ -722,6 +729,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)); + } + + 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. @@ -740,6 +846,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 ba960ebdbf..30cb14b746 100644 --- a/drivers/net/nbl/nbl_include/nbl_def_channel.h +++ b/drivers/net/nbl/nbl_include/nbl_def_channel.h @@ -399,6 +399,11 @@ enum nbl_chan_state { NBL_CHAN_STATE_MAX }; +struct nbl_chan_param_get_private_stat_data { + u32 eth_id; + u32 data_len; +}; + struct nbl_channel_ops { int (*send_msg)(void *priv, struct nbl_chan_send_info *chan_send); int (*send_ack)(void *priv, struct nbl_chan_ack_info *chan_ack); diff --git a/drivers/net/nbl/nbl_include/nbl_def_dispatch.h b/drivers/net/nbl/nbl_include/nbl_def_dispatch.h index 20510f7fa2..92dbc428ef 100644 --- a/drivers/net/nbl/nbl_include/nbl_def_dispatch.h +++ b/drivers/net/nbl/nbl_include/nbl_def_dispatch.h @@ -70,6 +70,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 da683cd957..f9864e261b 100644 --- a/drivers/net/nbl/nbl_include/nbl_def_resource.h +++ b/drivers/net/nbl/nbl_include/nbl_def_resource.h @@ -42,6 +42,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); @@ -54,10 +62,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 06aaad09d8..3faf4b969f 100644 --- a/drivers/net/nbl/nbl_include/nbl_include.h +++ b/drivers/net/nbl/nbl_include/nbl_include.h @@ -58,6 +58,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.43.0