From: Remy Horton Date: Wed, 15 Jun 2016 15:25:33 +0000 (+0100) Subject: ethdev: remove name from extended statistic fetch X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=e2aae1c1ced9;p=dpdk.git ethdev: remove name from extended statistic fetch The current extended ethernet statistics fetching involve doing several string operations, which causes performance issues if there are lots of statistics and/or network interfaces. This patch changes the test-pmd and proc_info applications to use the new xstats API, and removes deprecated code associated with the old API. Signed-off-by: Remy Horton --- diff --git a/app/proc_info/main.c b/app/proc_info/main.c index 5f8309244b..f2063fa3c9 100644 --- a/app/proc_info/main.c +++ b/app/proc_info/main.c @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -243,11 +243,13 @@ nic_stats_clear(uint8_t port_id) static void nic_xstats_display(uint8_t port_id) { - struct rte_eth_xstats *xstats; + struct rte_eth_xstat_name *xstats_names; + struct rte_eth_xstat *xstats; int len, ret, i; + int idx_name; static const char *nic_stats_border = "########################"; - len = rte_eth_xstats_get(port_id, NULL, 0); + len = rte_eth_xstats_get_names(port_id, NULL, 0); if (len < 0) { printf("Cannot get xstats count\n"); return; @@ -258,6 +260,18 @@ nic_xstats_display(uint8_t port_id) return; } + xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * len); + if (xstats_names == NULL) { + printf("Cannot allocate memory for xstat names\n"); + free(xstats); + return; + } + if (len != rte_eth_xstats_get_names( + port_id, xstats_names, len)) { + printf("Cannot get xstat names\n"); + return; + } + printf("###### NIC extended statistics for port %-2d #########\n", port_id); printf("%s############################\n", @@ -270,11 +284,18 @@ nic_xstats_display(uint8_t port_id) } for (i = 0; i < len; i++) - printf("%s: %"PRIu64"\n", xstats[i].name, xstats[i].value); + for (idx_name = 0; idx_name < len; idx_name++) + if (xstats_names[idx_name].id == xstats[i].id) { + printf("%s: %"PRIu64"\n", + xstats_names[idx_name].name, + xstats[i].value); + break; + } printf("%s############################\n", nic_stats_border); free(xstats); + free(xstats_names); } static void diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index 406158bd48..10f0a36604 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -255,29 +255,57 @@ nic_stats_clear(portid_t port_id) void nic_xstats_display(portid_t port_id) { - struct rte_eth_xstats *xstats; - int len, ret, i; + struct rte_eth_xstat *xstats; + int cnt_xstats, idx_xstat, idx_name; + struct rte_eth_xstat_name *xstats_names; printf("###### NIC extended statistics for port %-2d\n", port_id); + if (!rte_eth_dev_is_valid_port(port_id)) { + printf("Error: Invalid port number %i\n", port_id); + return; + } + + /* Get count */ + cnt_xstats = rte_eth_xstats_get_names(port_id, NULL, 0); + if (cnt_xstats < 0) { + printf("Error: Cannot get count of xstats\n"); + return; + } - len = rte_eth_xstats_get(port_id, NULL, 0); - if (len < 0) { - printf("Cannot get xstats count\n"); + /* Get id-name lookup table */ + xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * cnt_xstats); + if (xstats_names == NULL) { + printf("Cannot allocate memory for xstats lookup\n"); return; } - xstats = malloc(sizeof(xstats[0]) * len); + if (cnt_xstats != rte_eth_xstats_get_names( + port_id, xstats_names, cnt_xstats)) { + printf("Error: Cannot get xstats lookup\n"); + return; + } + + /* Get stats themselves */ + xstats = malloc(sizeof(struct rte_eth_xstat) * cnt_xstats); if (xstats == NULL) { printf("Cannot allocate memory for xstats\n"); + free(xstats_names); return; } - ret = rte_eth_xstats_get(port_id, xstats, len); - if (ret < 0 || ret > len) { - printf("Cannot get xstats\n"); - free(xstats); + if (cnt_xstats != rte_eth_xstats_get(port_id, xstats, cnt_xstats)) { + printf("Error: Unable to get xstats\n"); return; } - for (i = 0; i < len; i++) - printf("%s: %"PRIu64"\n", xstats[i].name, xstats[i].value); + + /* Display xstats */ + for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++) + for (idx_name = 0; idx_name < cnt_xstats; idx_name++) + if (xstats_names[idx_name].id == xstats[idx_xstat].id) { + printf("%s: %"PRIu64"\n", + xstats_names[idx_name].name, + xstats[idx_xstat].value); + break; + } + free(xstats_names); free(xstats); } diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst index 702dfce6aa..f75183f2a2 100644 --- a/doc/guides/rel_notes/deprecation.rst +++ b/doc/guides/rel_notes/deprecation.rst @@ -23,11 +23,6 @@ Deprecation Notices do not need to care about the kind of devices that are being used, making it easier to add new buses later. -* The xstats API and rte_eth_xstats struct will be changed to allow retrieval - of values without any string copies or parsing. - No backwards compatibility is planned, as it would require code duplication - in every PMD that supports xstats. - * ABI changes are planned for adding four new flow types. This impacts RTE_ETH_FLOW_MAX. The release 2.2 does not contain these ABI changes, but release 2.3 will. [postponed] diff --git a/doc/guides/rel_notes/release_16_07.rst b/doc/guides/rel_notes/release_16_07.rst index 131723ca6a..0075e04354 100644 --- a/doc/guides/rel_notes/release_16_07.rst +++ b/doc/guides/rel_notes/release_16_07.rst @@ -139,6 +139,9 @@ API Changes ibadcrc, ibadlen, imcasts, fdirmatch, fdirmiss, tx_pause_xon, rx_pause_xon, tx_pause_xoff, rx_pause_xoff. +* The extended statistics are fetched by ids with ``rte_eth_xstats_get`` + after a lookup by name ``rte_eth_xstats_get_names``. + ABI Changes ----------- diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c index dffa04f8d3..b822992409 100644 --- a/drivers/net/e1000/igb_ethdev.c +++ b/drivers/net/e1000/igb_ethdev.c @@ -99,7 +99,7 @@ static int eth_igb_link_update(struct rte_eth_dev *dev, static void eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats); static int eth_igb_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstats *xstats, unsigned n); + struct rte_eth_xstat *xstats, unsigned n); static int eth_igb_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, unsigned limit); @@ -167,7 +167,7 @@ static int eth_igbvf_link_update(struct e1000_hw *hw); static void eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats); static int eth_igbvf_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstats *xstats, unsigned n); + struct rte_eth_xstat *xstats, unsigned n); static int eth_igbvf_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, unsigned limit); @@ -1720,7 +1720,7 @@ static int eth_igb_xstats_get_names(__rte_unused struct rte_eth_dev *dev, } static int -eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, +eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); @@ -1741,7 +1741,6 @@ eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, /* Extended stats */ for (i = 0; i < IGB_NB_XSTATS; i++) { - xstats[i].name[0] = '\0'; xstats[i].id = i; xstats[i].value = *(uint64_t *)(((char *)hw_stats) + rte_igb_stats_strings[i].offset); @@ -1807,7 +1806,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev, } static int -eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, +eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); @@ -1824,7 +1823,6 @@ eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, return 0; for (i = 0; i < IGBVF_NB_XSTATS; i++) { - xstats[i].name[0] = '\0'; xstats[i].id = i; xstats[i].value = *(uint64_t *)(((char *)hw_stats) + rte_igbvf_stats_strings[i].offset); diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c index e07c1ec902..ce053b03f3 100644 --- a/drivers/net/fm10k/fm10k_ethdev.c +++ b/drivers/net/fm10k/fm10k_ethdev.c @@ -1298,7 +1298,7 @@ static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev, } static int -fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, +fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n) { struct fm10k_hw_stats *hw_stats = @@ -1310,7 +1310,6 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, /* Global stats */ for (i = 0; i < FM10K_NB_HW_XSTATS; i++) { - xstats[count].name[0] = '\0'; xstats[count].value = *(uint64_t *)(((char *)hw_stats) + fm10k_hw_stats_strings[count].offset); count++; @@ -1319,14 +1318,12 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, /* PF queue stats */ for (q = 0; q < FM10K_MAX_QUEUES_PF; q++) { for (i = 0; i < FM10K_NB_RX_Q_XSTATS; i++) { - xstats[count].name[0] = '\0'; xstats[count].value = *(uint64_t *)(((char *)&hw_stats->q[q]) + fm10k_hw_stats_rx_q_strings[i].offset); count++; } for (i = 0; i < FM10K_NB_TX_Q_XSTATS; i++) { - xstats[count].name[0] = '\0'; xstats[count].value = *(uint64_t *)(((char *)&hw_stats->q[q]) + fm10k_hw_stats_tx_q_strings[i].offset); diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index d712bbe965..f94ad87f37 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -305,7 +305,7 @@ static int i40e_dev_set_link_down(struct rte_eth_dev *dev); static void i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static int i40e_dev_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstats *xstats, unsigned n); + struct rte_eth_xstat *xstats, unsigned n); static int i40e_dev_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, unsigned limit); @@ -2264,7 +2264,7 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev, } static int -i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, +i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); @@ -2285,7 +2285,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, /* Get stats from i40e_eth_stats struct */ for (i = 0; i < I40E_NB_ETH_XSTATS; i++) { - xstats[count].name[0] = '\0'; xstats[count].id = count; xstats[count].value = *(uint64_t *)(((char *)&hw_stats->eth) + rte_i40e_stats_strings[i].offset); @@ -2294,7 +2293,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, /* Get individiual stats from i40e_hw_port struct */ for (i = 0; i < I40E_NB_HW_PORT_XSTATS; i++) { - xstats[count].name[0] = '\0'; xstats[count].id = count; xstats[count].value = *(uint64_t *)(((char *)hw_stats) + rte_i40e_hw_port_strings[i].offset); @@ -2303,7 +2301,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, for (i = 0; i < I40E_NB_RXQ_PRIO_XSTATS; i++) { for (prio = 0; prio < 8; prio++) { - xstats[count].name[0] = '\0'; xstats[count].id = count; xstats[count].value = *(uint64_t *)(((char *)hw_stats) + @@ -2315,7 +2312,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, for (i = 0; i < I40E_NB_TXQ_PRIO_XSTATS; i++) { for (prio = 0; prio < 8; prio++) { - xstats[count].name[0] = '\0'; xstats[count].id = count; xstats[count].value = *(uint64_t *)(((char *)hw_stats) + diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c index 4c5e45e65c..37af399ed0 100644 --- a/drivers/net/i40e/i40e_ethdev_vf.c +++ b/drivers/net/i40e/i40e_ethdev_vf.c @@ -111,7 +111,7 @@ static int i40evf_dev_link_update(struct rte_eth_dev *dev, static void i40evf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static int i40evf_dev_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstats *xstats, unsigned n); + struct rte_eth_xstat *xstats, unsigned n); static int i40evf_dev_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, unsigned limit); @@ -1005,7 +1005,7 @@ static int i40evf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev, } static int i40evf_dev_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstats *xstats, unsigned n) + struct rte_eth_xstat *xstats, unsigned n) { int ret; unsigned i; @@ -1023,7 +1023,6 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev, /* loop over xstats array and values from pstats */ for (i = 0; i < I40EVF_NB_XSTATS; i++) { - xstats[i].name[0] = '\0'; xstats[i].id = i; xstats[i].value = *(uint64_t *)(((char *)pstats) + rte_i40evf_stats_strings[i].offset); diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c index 5d557a2ddc..e11a43157b 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -174,9 +174,9 @@ static int ixgbe_dev_link_update(struct rte_eth_dev *dev, static void ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static int ixgbe_dev_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstats *xstats, unsigned n); + struct rte_eth_xstat *xstats, unsigned n); static int ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstats *xstats, unsigned n); + struct rte_eth_xstat *xstats, unsigned n); static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev); static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev); static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev, @@ -2786,7 +2786,7 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev, } static int -ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, +ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n) { struct ixgbe_hw *hw = @@ -2819,7 +2819,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, count = 0; for (i = 0; i < IXGBE_NB_HW_STATS; i++) { xstats[count].id = count; - xstats[count].name[0] = '\0'; xstats[count].value = *(uint64_t *)(((char *)hw_stats) + rte_ixgbe_stats_strings[i].offset); count++; @@ -2829,7 +2828,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) { for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) { xstats[count].id = count; - xstats[count].name[0] = '\0'; xstats[count].value = *(uint64_t *)(((char *)hw_stats) + rte_ixgbe_rxq_strings[stat].offset + (sizeof(uint64_t) * i)); @@ -2841,7 +2839,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) { for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) { xstats[count].id = count; - xstats[count].name[0] = '\0'; xstats[count].value = *(uint64_t *)(((char *)hw_stats) + rte_ixgbe_txq_strings[stat].offset + (sizeof(uint64_t) * i)); @@ -2895,7 +2892,7 @@ ixgbevf_update_stats(struct rte_eth_dev *dev) } static int -ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, +ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n) { struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *) diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 83df0258ea..a833740f11 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -79,7 +79,7 @@ static void virtio_get_hwaddr(struct virtio_hw *hw); static void virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static int virtio_dev_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstats *xstats, unsigned n); + struct rte_eth_xstat *xstats, unsigned n); static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, unsigned limit); @@ -759,7 +759,7 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev, } static int -virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, +virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n) { unsigned i; @@ -780,7 +780,6 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, unsigned t; for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) { - xstats[count].name[0] = '\0'; xstats[count].id = count; xstats[count].value = *(uint64_t *)(((char *)rxvq) + rte_virtio_q_stat_strings[t].offset); @@ -797,7 +796,6 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, unsigned t; for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) { - xstats[count].name[0] = '\0'; xstats[count].id = count; xstats[count].value = *(uint64_t *)(((char *)txvq) + rte_virtio_q_stat_strings[t].offset); diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 98e5efb893..63320cc35b 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -1583,7 +1583,7 @@ rte_eth_xstats_get_names(uint8_t port_id, /* retrieve ethdev extended statistics */ int -rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, +rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats, unsigned n) { struct rte_eth_stats eth_stats; @@ -1625,7 +1625,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, stats_ptr = RTE_PTR_ADD(ð_stats, rte_stats_strings[i].offset); val = *stats_ptr; - xstats[count].name[0] = '\0'; xstats[count].id = count + xcount; xstats[count++].value = val; } @@ -1637,7 +1636,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, rte_rxq_stats_strings[i].offset + q * sizeof(uint64_t)); val = *stats_ptr; - xstats[count].name[0] = '\0'; xstats[count].id = count + xcount; xstats[count++].value = val; } @@ -1650,7 +1648,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, rte_txq_stats_strings[i].offset + q * sizeof(uint64_t)); val = *stats_ptr; - xstats[count].name[0] = '\0'; xstats[count].id = count + xcount; xstats[count++].value = val; } diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index c344c2cda9..9748ec032d 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -914,8 +914,7 @@ struct rte_eth_txq_info { * statistics that are not provided in the generic rte_eth_stats * structure. */ -struct rte_eth_xstats { - char name[RTE_ETH_XSTATS_NAME_SIZE]; +struct rte_eth_xstat { uint64_t id; uint64_t value; }; @@ -1060,7 +1059,7 @@ typedef void (*eth_stats_reset_t)(struct rte_eth_dev *dev); /**< @internal Reset global I/O statistics of an Ethernet device to 0. */ typedef int (*eth_xstats_get_t)(struct rte_eth_dev *dev, - struct rte_eth_xstats *stats, unsigned n); + struct rte_eth_xstat *stats, unsigned n); /**< @internal Get extended stats of an Ethernet device. */ typedef void (*eth_xstats_reset_t)(struct rte_eth_dev *dev); @@ -2314,7 +2313,7 @@ int rte_eth_xstats_get_names(uint8_t port_id, * shall not be used by the caller. * - negative value on error (invalid port id) */ -int rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, +int rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats, unsigned n); /**