net/igc: enable statistics

Enable base statistics, extend statistics and per-queue statistics.

Below ops are added:
stats_get
xstats_get
xstats_get_by_id
xstats_get_names_by_id
xstats_get_names
stats_reset
xstats_reset
queue_stats_mapping_set

Signed-off-by: Alvin Zhang <alvinx.zhang@intel.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
This commit is contained in:
Alvin Zhang 2020-04-15 16:48:04 +08:00 committed by Ferruh Yigit
parent a5aeb2b9e2
commit e6defdfddc
3 changed files with 613 additions and 1 deletions

View File

@ -23,6 +23,9 @@ RSS hash = Y
CRC offload = Y
L3 checksum offload = Y
L4 checksum offload = Y
Basic stats = Y
Extended stats = Y
Stats per queue = Y
Linux UIO = Y
Linux VFIO = Y
x86-64 = Y

View File

@ -5,11 +5,13 @@
#include <stdint.h>
#include <string.h>
#include <rte_string_fns.h>
#include <rte_pci.h>
#include <rte_bus_pci.h>
#include <rte_ethdev_driver.h>
#include <rte_ethdev_pci.h>
#include <rte_malloc.h>
#include <rte_alarm.h>
#include "igc_logs.h"
#include "igc_txrx.h"
@ -48,6 +50,28 @@
/* External VLAN Enable bit mask */
#define IGC_CTRL_EXT_EXT_VLAN (1u << 26)
/* Per Queue Good Packets Received Count */
#define IGC_PQGPRC(idx) (0x10010 + 0x100 * (idx))
/* Per Queue Good Octets Received Count */
#define IGC_PQGORC(idx) (0x10018 + 0x100 * (idx))
/* Per Queue Good Octets Transmitted Count */
#define IGC_PQGOTC(idx) (0x10034 + 0x100 * (idx))
/* Per Queue Multicast Packets Received Count */
#define IGC_PQMPRC(idx) (0x10038 + 0x100 * (idx))
/* Transmit Queue Drop Packet Count */
#define IGC_TQDPC(idx) (0xe030 + 0x40 * (idx))
#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
#define U32_0_IN_U64 0 /* lower bytes of u64 */
#define U32_1_IN_U64 1 /* higher bytes of u64 */
#else
#define U32_0_IN_U64 1
#define U32_1_IN_U64 0
#endif
#define IGC_ALARM_INTERVAL 8000000u
/* us, about 13.6s some per-queue registers will wrap around back to 0. */
static const struct rte_eth_desc_lim rx_desc_lim = {
.nb_max = IGC_MAX_RXD,
.nb_min = IGC_MIN_RXD,
@ -70,6 +94,76 @@ static const struct rte_pci_id pci_id_igc_map[] = {
{ .vendor_id = 0, /* sentinel */ },
};
/* store statistics names and its offset in stats structure */
struct rte_igc_xstats_name_off {
char name[RTE_ETH_XSTATS_NAME_SIZE];
unsigned int offset;
};
static const struct rte_igc_xstats_name_off rte_igc_stats_strings[] = {
{"rx_crc_errors", offsetof(struct igc_hw_stats, crcerrs)},
{"rx_align_errors", offsetof(struct igc_hw_stats, algnerrc)},
{"rx_errors", offsetof(struct igc_hw_stats, rxerrc)},
{"rx_missed_packets", offsetof(struct igc_hw_stats, mpc)},
{"tx_single_collision_packets", offsetof(struct igc_hw_stats, scc)},
{"tx_multiple_collision_packets", offsetof(struct igc_hw_stats, mcc)},
{"tx_excessive_collision_packets", offsetof(struct igc_hw_stats,
ecol)},
{"tx_late_collisions", offsetof(struct igc_hw_stats, latecol)},
{"tx_total_collisions", offsetof(struct igc_hw_stats, colc)},
{"tx_deferred_packets", offsetof(struct igc_hw_stats, dc)},
{"tx_no_carrier_sense_packets", offsetof(struct igc_hw_stats, tncrs)},
{"tx_discarded_packets", offsetof(struct igc_hw_stats, htdpmc)},
{"rx_length_errors", offsetof(struct igc_hw_stats, rlec)},
{"rx_xon_packets", offsetof(struct igc_hw_stats, xonrxc)},
{"tx_xon_packets", offsetof(struct igc_hw_stats, xontxc)},
{"rx_xoff_packets", offsetof(struct igc_hw_stats, xoffrxc)},
{"tx_xoff_packets", offsetof(struct igc_hw_stats, xofftxc)},
{"rx_flow_control_unsupported_packets", offsetof(struct igc_hw_stats,
fcruc)},
{"rx_size_64_packets", offsetof(struct igc_hw_stats, prc64)},
{"rx_size_65_to_127_packets", offsetof(struct igc_hw_stats, prc127)},
{"rx_size_128_to_255_packets", offsetof(struct igc_hw_stats, prc255)},
{"rx_size_256_to_511_packets", offsetof(struct igc_hw_stats, prc511)},
{"rx_size_512_to_1023_packets", offsetof(struct igc_hw_stats,
prc1023)},
{"rx_size_1024_to_max_packets", offsetof(struct igc_hw_stats,
prc1522)},
{"rx_broadcast_packets", offsetof(struct igc_hw_stats, bprc)},
{"rx_multicast_packets", offsetof(struct igc_hw_stats, mprc)},
{"rx_undersize_errors", offsetof(struct igc_hw_stats, ruc)},
{"rx_fragment_errors", offsetof(struct igc_hw_stats, rfc)},
{"rx_oversize_errors", offsetof(struct igc_hw_stats, roc)},
{"rx_jabber_errors", offsetof(struct igc_hw_stats, rjc)},
{"rx_no_buffers", offsetof(struct igc_hw_stats, rnbc)},
{"rx_management_packets", offsetof(struct igc_hw_stats, mgprc)},
{"rx_management_dropped", offsetof(struct igc_hw_stats, mgpdc)},
{"tx_management_packets", offsetof(struct igc_hw_stats, mgptc)},
{"rx_total_packets", offsetof(struct igc_hw_stats, tpr)},
{"tx_total_packets", offsetof(struct igc_hw_stats, tpt)},
{"rx_total_bytes", offsetof(struct igc_hw_stats, tor)},
{"tx_total_bytes", offsetof(struct igc_hw_stats, tot)},
{"tx_size_64_packets", offsetof(struct igc_hw_stats, ptc64)},
{"tx_size_65_to_127_packets", offsetof(struct igc_hw_stats, ptc127)},
{"tx_size_128_to_255_packets", offsetof(struct igc_hw_stats, ptc255)},
{"tx_size_256_to_511_packets", offsetof(struct igc_hw_stats, ptc511)},
{"tx_size_512_to_1023_packets", offsetof(struct igc_hw_stats,
ptc1023)},
{"tx_size_1023_to_max_packets", offsetof(struct igc_hw_stats,
ptc1522)},
{"tx_multicast_packets", offsetof(struct igc_hw_stats, mptc)},
{"tx_broadcast_packets", offsetof(struct igc_hw_stats, bptc)},
{"tx_tso_packets", offsetof(struct igc_hw_stats, tsctc)},
{"rx_sent_to_host_packets", offsetof(struct igc_hw_stats, rpthc)},
{"tx_sent_by_host_packets", offsetof(struct igc_hw_stats, hgptc)},
{"interrupt_assert_count", offsetof(struct igc_hw_stats, iac)},
{"rx_descriptor_lower_threshold",
offsetof(struct igc_hw_stats, icrxdmtc)},
};
#define IGC_NB_XSTATS (sizeof(rte_igc_stats_strings) / \
sizeof(rte_igc_stats_strings[0]))
static int eth_igc_configure(struct rte_eth_dev *dev);
static int eth_igc_link_update(struct rte_eth_dev *dev, int wait_to_complete);
static void eth_igc_stop(struct rte_eth_dev *dev);
@ -98,6 +192,23 @@ static int eth_igc_set_mc_addr_list(struct rte_eth_dev *dev,
static int eth_igc_allmulticast_enable(struct rte_eth_dev *dev);
static int eth_igc_allmulticast_disable(struct rte_eth_dev *dev);
static int eth_igc_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
static int eth_igc_stats_get(struct rte_eth_dev *dev,
struct rte_eth_stats *rte_stats);
static int eth_igc_xstats_get(struct rte_eth_dev *dev,
struct rte_eth_xstat *xstats, unsigned int n);
static int eth_igc_xstats_get_by_id(struct rte_eth_dev *dev,
const uint64_t *ids,
uint64_t *values, unsigned int n);
static int eth_igc_xstats_get_names(struct rte_eth_dev *dev,
struct rte_eth_xstat_name *xstats_names,
unsigned int size);
static int eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev,
struct rte_eth_xstat_name *xstats_names, const uint64_t *ids,
unsigned int limit);
static int eth_igc_xstats_reset(struct rte_eth_dev *dev);
static int
eth_igc_queue_stats_mapping_set(struct rte_eth_dev *dev,
uint16_t queue_id, uint8_t stat_idx, uint8_t is_rx);
static const struct eth_dev_ops eth_igc_ops = {
.dev_configure = eth_igc_configure,
@ -134,6 +245,14 @@ static const struct eth_dev_ops eth_igc_ops = {
.tx_done_cleanup = eth_igc_tx_done_cleanup,
.rxq_info_get = eth_igc_rxq_info_get,
.txq_info_get = eth_igc_txq_info_get,
.stats_get = eth_igc_stats_get,
.xstats_get = eth_igc_xstats_get,
.xstats_get_by_id = eth_igc_xstats_get_by_id,
.xstats_get_names_by_id = eth_igc_xstats_get_names_by_id,
.xstats_get_names = eth_igc_xstats_get_names,
.stats_reset = eth_igc_xstats_reset,
.xstats_reset = eth_igc_xstats_reset,
.queue_stats_mapping_set = eth_igc_queue_stats_mapping_set,
};
/*
@ -398,6 +517,22 @@ eth_igc_interrupt_handler(void *param)
eth_igc_interrupt_action(dev);
}
static void igc_read_queue_stats_register(struct rte_eth_dev *dev);
/*
* Update the queue status every IGC_ALARM_INTERVAL time.
* @param
* The address of parameter (struct rte_eth_dev *) registered before.
*/
static void
igc_update_queue_stats_handler(void *param)
{
struct rte_eth_dev *dev = param;
igc_read_queue_stats_register(dev);
rte_eal_alarm_set(IGC_ALARM_INTERVAL,
igc_update_queue_stats_handler, dev);
}
/*
* rx,tx enable/disable
*/
@ -451,6 +586,8 @@ eth_igc_stop(struct rte_eth_dev *dev)
igc_intr_other_disable(dev);
rte_eal_alarm_cancel(igc_update_queue_stats_handler, dev);
/* disable intr eventfd mapping */
rte_intr_disable(intr_handle);
@ -754,6 +891,9 @@ eth_igc_start(struct rte_eth_dev *dev)
/* enable uio/vfio intr/eventfd mapping */
rte_intr_enable(intr_handle);
rte_eal_alarm_set(IGC_ALARM_INTERVAL,
igc_update_queue_stats_handler, dev);
/* resume enabled intr since hw reset */
igc_intr_other_enable(dev);
@ -894,7 +1034,7 @@ eth_igc_dev_init(struct rte_eth_dev *dev)
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
int error = 0;
int i, error = 0;
PMD_INIT_FUNC_TRACE();
dev->dev_ops = &eth_igc_ops;
@ -1019,6 +1159,11 @@ eth_igc_dev_init(struct rte_eth_dev *dev)
/* enable support intr */
igc_intr_other_enable(dev);
/* initiate queue status */
for (i = 0; i < IGC_QUEUE_PAIRS_NUM; i++) {
igc->txq_stats_map[i] = -1;
igc->rxq_stats_map[i] = -1;
}
return 0;
err_late:
@ -1323,6 +1468,441 @@ eth_igc_set_mc_addr_list(struct rte_eth_dev *dev,
return 0;
}
/*
* Read hardware registers
*/
static void
igc_read_stats_registers(struct igc_hw *hw, struct igc_hw_stats *stats)
{
int pause_frames;
uint64_t old_gprc = stats->gprc;
uint64_t old_gptc = stats->gptc;
uint64_t old_tpr = stats->tpr;
uint64_t old_tpt = stats->tpt;
uint64_t old_rpthc = stats->rpthc;
uint64_t old_hgptc = stats->hgptc;
stats->crcerrs += IGC_READ_REG(hw, IGC_CRCERRS);
stats->algnerrc += IGC_READ_REG(hw, IGC_ALGNERRC);
stats->rxerrc += IGC_READ_REG(hw, IGC_RXERRC);
stats->mpc += IGC_READ_REG(hw, IGC_MPC);
stats->scc += IGC_READ_REG(hw, IGC_SCC);
stats->ecol += IGC_READ_REG(hw, IGC_ECOL);
stats->mcc += IGC_READ_REG(hw, IGC_MCC);
stats->latecol += IGC_READ_REG(hw, IGC_LATECOL);
stats->colc += IGC_READ_REG(hw, IGC_COLC);
stats->dc += IGC_READ_REG(hw, IGC_DC);
stats->tncrs += IGC_READ_REG(hw, IGC_TNCRS);
stats->htdpmc += IGC_READ_REG(hw, IGC_HTDPMC);
stats->rlec += IGC_READ_REG(hw, IGC_RLEC);
stats->xonrxc += IGC_READ_REG(hw, IGC_XONRXC);
stats->xontxc += IGC_READ_REG(hw, IGC_XONTXC);
/*
* For watchdog management we need to know if we have been
* paused during the last interval, so capture that here.
*/
pause_frames = IGC_READ_REG(hw, IGC_XOFFRXC);
stats->xoffrxc += pause_frames;
stats->xofftxc += IGC_READ_REG(hw, IGC_XOFFTXC);
stats->fcruc += IGC_READ_REG(hw, IGC_FCRUC);
stats->prc64 += IGC_READ_REG(hw, IGC_PRC64);
stats->prc127 += IGC_READ_REG(hw, IGC_PRC127);
stats->prc255 += IGC_READ_REG(hw, IGC_PRC255);
stats->prc511 += IGC_READ_REG(hw, IGC_PRC511);
stats->prc1023 += IGC_READ_REG(hw, IGC_PRC1023);
stats->prc1522 += IGC_READ_REG(hw, IGC_PRC1522);
stats->gprc += IGC_READ_REG(hw, IGC_GPRC);
stats->bprc += IGC_READ_REG(hw, IGC_BPRC);
stats->mprc += IGC_READ_REG(hw, IGC_MPRC);
stats->gptc += IGC_READ_REG(hw, IGC_GPTC);
/* For the 64-bit byte counters the low dword must be read first. */
/* Both registers clear on the read of the high dword */
/* Workaround CRC bytes included in size, take away 4 bytes/packet */
stats->gorc += IGC_READ_REG(hw, IGC_GORCL);
stats->gorc += ((uint64_t)IGC_READ_REG(hw, IGC_GORCH) << 32);
stats->gorc -= (stats->gprc - old_gprc) * RTE_ETHER_CRC_LEN;
stats->gotc += IGC_READ_REG(hw, IGC_GOTCL);
stats->gotc += ((uint64_t)IGC_READ_REG(hw, IGC_GOTCH) << 32);
stats->gotc -= (stats->gptc - old_gptc) * RTE_ETHER_CRC_LEN;
stats->rnbc += IGC_READ_REG(hw, IGC_RNBC);
stats->ruc += IGC_READ_REG(hw, IGC_RUC);
stats->rfc += IGC_READ_REG(hw, IGC_RFC);
stats->roc += IGC_READ_REG(hw, IGC_ROC);
stats->rjc += IGC_READ_REG(hw, IGC_RJC);
stats->mgprc += IGC_READ_REG(hw, IGC_MGTPRC);
stats->mgpdc += IGC_READ_REG(hw, IGC_MGTPDC);
stats->mgptc += IGC_READ_REG(hw, IGC_MGTPTC);
stats->b2ospc += IGC_READ_REG(hw, IGC_B2OSPC);
stats->b2ogprc += IGC_READ_REG(hw, IGC_B2OGPRC);
stats->o2bgptc += IGC_READ_REG(hw, IGC_O2BGPTC);
stats->o2bspc += IGC_READ_REG(hw, IGC_O2BSPC);
stats->tpr += IGC_READ_REG(hw, IGC_TPR);
stats->tpt += IGC_READ_REG(hw, IGC_TPT);
stats->tor += IGC_READ_REG(hw, IGC_TORL);
stats->tor += ((uint64_t)IGC_READ_REG(hw, IGC_TORH) << 32);
stats->tor -= (stats->tpr - old_tpr) * RTE_ETHER_CRC_LEN;
stats->tot += IGC_READ_REG(hw, IGC_TOTL);
stats->tot += ((uint64_t)IGC_READ_REG(hw, IGC_TOTH) << 32);
stats->tot -= (stats->tpt - old_tpt) * RTE_ETHER_CRC_LEN;
stats->ptc64 += IGC_READ_REG(hw, IGC_PTC64);
stats->ptc127 += IGC_READ_REG(hw, IGC_PTC127);
stats->ptc255 += IGC_READ_REG(hw, IGC_PTC255);
stats->ptc511 += IGC_READ_REG(hw, IGC_PTC511);
stats->ptc1023 += IGC_READ_REG(hw, IGC_PTC1023);
stats->ptc1522 += IGC_READ_REG(hw, IGC_PTC1522);
stats->mptc += IGC_READ_REG(hw, IGC_MPTC);
stats->bptc += IGC_READ_REG(hw, IGC_BPTC);
stats->tsctc += IGC_READ_REG(hw, IGC_TSCTC);
stats->iac += IGC_READ_REG(hw, IGC_IAC);
stats->rpthc += IGC_READ_REG(hw, IGC_RPTHC);
stats->hgptc += IGC_READ_REG(hw, IGC_HGPTC);
stats->icrxdmtc += IGC_READ_REG(hw, IGC_ICRXDMTC);
/* Host to Card Statistics */
stats->hgorc += IGC_READ_REG(hw, IGC_HGORCL);
stats->hgorc += ((uint64_t)IGC_READ_REG(hw, IGC_HGORCH) << 32);
stats->hgorc -= (stats->rpthc - old_rpthc) * RTE_ETHER_CRC_LEN;
stats->hgotc += IGC_READ_REG(hw, IGC_HGOTCL);
stats->hgotc += ((uint64_t)IGC_READ_REG(hw, IGC_HGOTCH) << 32);
stats->hgotc -= (stats->hgptc - old_hgptc) * RTE_ETHER_CRC_LEN;
stats->lenerrs += IGC_READ_REG(hw, IGC_LENERRS);
}
/*
* Write 0 to all queue status registers
*/
static void
igc_reset_queue_stats_register(struct igc_hw *hw)
{
int i;
for (i = 0; i < IGC_QUEUE_PAIRS_NUM; i++) {
IGC_WRITE_REG(hw, IGC_PQGPRC(i), 0);
IGC_WRITE_REG(hw, IGC_PQGPTC(i), 0);
IGC_WRITE_REG(hw, IGC_PQGORC(i), 0);
IGC_WRITE_REG(hw, IGC_PQGOTC(i), 0);
IGC_WRITE_REG(hw, IGC_PQMPRC(i), 0);
IGC_WRITE_REG(hw, IGC_RQDPC(i), 0);
IGC_WRITE_REG(hw, IGC_TQDPC(i), 0);
}
}
/*
* Read all hardware queue status registers
*/
static void
igc_read_queue_stats_register(struct rte_eth_dev *dev)
{
struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
struct igc_hw_queue_stats *queue_stats =
IGC_DEV_PRIVATE_QUEUE_STATS(dev);
int i;
/*
* This register is not cleared on read. Furthermore, the register wraps
* around back to 0x00000000 on the next increment when reaching a value
* of 0xFFFFFFFF and then continues normal count operation.
*/
for (i = 0; i < IGC_QUEUE_PAIRS_NUM; i++) {
union {
u64 ddword;
u32 dword[2];
} value;
u32 tmp;
/*
* Read the register first, if the value is smaller than that
* previous read, that mean the register has been overflowed,
* then we add the high 4 bytes by 1 and replace the low 4
* bytes by the new value.
*/
tmp = IGC_READ_REG(hw, IGC_PQGPRC(i));
value.ddword = queue_stats->pqgprc[i];
if (value.dword[U32_0_IN_U64] > tmp)
value.dword[U32_1_IN_U64]++;
value.dword[U32_0_IN_U64] = tmp;
queue_stats->pqgprc[i] = value.ddword;
tmp = IGC_READ_REG(hw, IGC_PQGPTC(i));
value.ddword = queue_stats->pqgptc[i];
if (value.dword[U32_0_IN_U64] > tmp)
value.dword[U32_1_IN_U64]++;
value.dword[U32_0_IN_U64] = tmp;
queue_stats->pqgptc[i] = value.ddword;
tmp = IGC_READ_REG(hw, IGC_PQGORC(i));
value.ddword = queue_stats->pqgorc[i];
if (value.dword[U32_0_IN_U64] > tmp)
value.dword[U32_1_IN_U64]++;
value.dword[U32_0_IN_U64] = tmp;
queue_stats->pqgorc[i] = value.ddword;
tmp = IGC_READ_REG(hw, IGC_PQGOTC(i));
value.ddword = queue_stats->pqgotc[i];
if (value.dword[U32_0_IN_U64] > tmp)
value.dword[U32_1_IN_U64]++;
value.dword[U32_0_IN_U64] = tmp;
queue_stats->pqgotc[i] = value.ddword;
tmp = IGC_READ_REG(hw, IGC_PQMPRC(i));
value.ddword = queue_stats->pqmprc[i];
if (value.dword[U32_0_IN_U64] > tmp)
value.dword[U32_1_IN_U64]++;
value.dword[U32_0_IN_U64] = tmp;
queue_stats->pqmprc[i] = value.ddword;
tmp = IGC_READ_REG(hw, IGC_RQDPC(i));
value.ddword = queue_stats->rqdpc[i];
if (value.dword[U32_0_IN_U64] > tmp)
value.dword[U32_1_IN_U64]++;
value.dword[U32_0_IN_U64] = tmp;
queue_stats->rqdpc[i] = value.ddword;
tmp = IGC_READ_REG(hw, IGC_TQDPC(i));
value.ddword = queue_stats->tqdpc[i];
if (value.dword[U32_0_IN_U64] > tmp)
value.dword[U32_1_IN_U64]++;
value.dword[U32_0_IN_U64] = tmp;
queue_stats->tqdpc[i] = value.ddword;
}
}
static int
eth_igc_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
{
struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
struct igc_hw_stats *stats = IGC_DEV_PRIVATE_STATS(dev);
struct igc_hw_queue_stats *queue_stats =
IGC_DEV_PRIVATE_QUEUE_STATS(dev);
int i;
/*
* Cancel status handler since it will read the queue status registers
*/
rte_eal_alarm_cancel(igc_update_queue_stats_handler, dev);
/* Read status register */
igc_read_queue_stats_register(dev);
igc_read_stats_registers(hw, stats);
if (rte_stats == NULL) {
/* Restart queue status handler */
rte_eal_alarm_set(IGC_ALARM_INTERVAL,
igc_update_queue_stats_handler, dev);
return -EINVAL;
}
/* Rx Errors */
rte_stats->imissed = stats->mpc;
rte_stats->ierrors = stats->crcerrs +
stats->rlec + stats->ruc + stats->roc +
stats->rxerrc + stats->algnerrc;
/* Tx Errors */
rte_stats->oerrors = stats->ecol + stats->latecol;
rte_stats->ipackets = stats->gprc;
rte_stats->opackets = stats->gptc;
rte_stats->ibytes = stats->gorc;
rte_stats->obytes = stats->gotc;
/* Get per-queue statuses */
for (i = 0; i < IGC_QUEUE_PAIRS_NUM; i++) {
/* GET TX queue statuses */
int map_id = igc->txq_stats_map[i];
if (map_id >= 0) {
rte_stats->q_opackets[map_id] += queue_stats->pqgptc[i];
rte_stats->q_obytes[map_id] += queue_stats->pqgotc[i];
}
/* Get RX queue statuses */
map_id = igc->rxq_stats_map[i];
if (map_id >= 0) {
rte_stats->q_ipackets[map_id] += queue_stats->pqgprc[i];
rte_stats->q_ibytes[map_id] += queue_stats->pqgorc[i];
rte_stats->q_errors[map_id] += queue_stats->rqdpc[i];
}
}
/* Restart queue status handler */
rte_eal_alarm_set(IGC_ALARM_INTERVAL,
igc_update_queue_stats_handler, dev);
return 0;
}
static int
eth_igc_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
unsigned int n)
{
struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
struct igc_hw_stats *hw_stats =
IGC_DEV_PRIVATE_STATS(dev);
unsigned int i;
igc_read_stats_registers(hw, hw_stats);
if (n < IGC_NB_XSTATS)
return IGC_NB_XSTATS;
/* If this is a reset xstats is NULL, and we have cleared the
* registers by reading them.
*/
if (!xstats)
return 0;
/* Extended stats */
for (i = 0; i < IGC_NB_XSTATS; i++) {
xstats[i].id = i;
xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
rte_igc_stats_strings[i].offset);
}
return IGC_NB_XSTATS;
}
static int
eth_igc_xstats_reset(struct rte_eth_dev *dev)
{
struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
struct igc_hw_stats *hw_stats = IGC_DEV_PRIVATE_STATS(dev);
struct igc_hw_queue_stats *queue_stats =
IGC_DEV_PRIVATE_QUEUE_STATS(dev);
/* Cancel queue status handler for avoid conflict */
rte_eal_alarm_cancel(igc_update_queue_stats_handler, dev);
/* HW registers are cleared on read */
igc_reset_queue_stats_register(hw);
igc_read_stats_registers(hw, hw_stats);
/* Reset software totals */
memset(hw_stats, 0, sizeof(*hw_stats));
memset(queue_stats, 0, sizeof(*queue_stats));
/* Restart the queue status handler */
rte_eal_alarm_set(IGC_ALARM_INTERVAL, igc_update_queue_stats_handler,
dev);
return 0;
}
static int
eth_igc_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
struct rte_eth_xstat_name *xstats_names, unsigned int size)
{
unsigned int i;
if (xstats_names == NULL)
return IGC_NB_XSTATS;
if (size < IGC_NB_XSTATS) {
PMD_DRV_LOG(ERR, "not enough buffers!");
return IGC_NB_XSTATS;
}
for (i = 0; i < IGC_NB_XSTATS; i++)
strlcpy(xstats_names[i].name, rte_igc_stats_strings[i].name,
sizeof(xstats_names[i].name));
return IGC_NB_XSTATS;
}
static int
eth_igc_xstats_get_names_by_id(struct rte_eth_dev *dev,
struct rte_eth_xstat_name *xstats_names, const uint64_t *ids,
unsigned int limit)
{
unsigned int i;
if (!ids)
return eth_igc_xstats_get_names(dev, xstats_names, limit);
for (i = 0; i < limit; i++) {
if (ids[i] >= IGC_NB_XSTATS) {
PMD_DRV_LOG(ERR, "id value isn't valid");
return -EINVAL;
}
strlcpy(xstats_names[i].name,
rte_igc_stats_strings[ids[i]].name,
sizeof(xstats_names[i].name));
}
return limit;
}
static int
eth_igc_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids,
uint64_t *values, unsigned int n)
{
struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
struct igc_hw_stats *hw_stats = IGC_DEV_PRIVATE_STATS(dev);
unsigned int i;
igc_read_stats_registers(hw, hw_stats);
if (!ids) {
if (n < IGC_NB_XSTATS)
return IGC_NB_XSTATS;
/* If this is a reset xstats is NULL, and we have cleared the
* registers by reading them.
*/
if (!values)
return 0;
/* Extended stats */
for (i = 0; i < IGC_NB_XSTATS; i++)
values[i] = *(uint64_t *)(((char *)hw_stats) +
rte_igc_stats_strings[i].offset);
return IGC_NB_XSTATS;
} else {
for (i = 0; i < n; i++) {
if (ids[i] >= IGC_NB_XSTATS) {
PMD_DRV_LOG(ERR, "id value isn't valid");
return -EINVAL;
}
values[i] = *(uint64_t *)(((char *)hw_stats) +
rte_igc_stats_strings[ids[i]].offset);
}
return n;
}
}
static int
eth_igc_queue_stats_mapping_set(struct rte_eth_dev *dev,
uint16_t queue_id, uint8_t stat_idx, uint8_t is_rx)
{
struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
/* check queue id is valid */
if (queue_id >= IGC_QUEUE_PAIRS_NUM) {
PMD_DRV_LOG(ERR, "queue id(%u) error, max is %u",
queue_id, IGC_QUEUE_PAIRS_NUM - 1);
return -EINVAL;
}
/* store the mapping status id */
if (is_rx)
igc->rxq_stats_map[queue_id] = stat_idx;
else
igc->txq_stats_map[queue_id] = stat_idx;
return 0;
}
static int
eth_igc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
struct rte_pci_device *pci_dev)

View File

@ -86,11 +86,34 @@ union igc_rss_reta_reg {
uint8_t bytes[4];
};
/* Structure to per-queue statics */
struct igc_hw_queue_stats {
u64 pqgprc[IGC_QUEUE_PAIRS_NUM];
/* per queue good packets received count */
u64 pqgptc[IGC_QUEUE_PAIRS_NUM];
/* per queue good packets transmitted count */
u64 pqgorc[IGC_QUEUE_PAIRS_NUM];
/* per queue good octets received count */
u64 pqgotc[IGC_QUEUE_PAIRS_NUM];
/* per queue good octets transmitted count */
u64 pqmprc[IGC_QUEUE_PAIRS_NUM];
/* per queue multicast packets received count */
u64 rqdpc[IGC_QUEUE_PAIRS_NUM];
/* per receive queue drop packet count */
u64 tqdpc[IGC_QUEUE_PAIRS_NUM];
/* per transmit queue drop packet count */
};
/*
* Structure to store private data for each driver instance (for each port).
*/
struct igc_adapter {
struct igc_hw hw;
struct igc_hw_stats stats;
struct igc_hw_queue_stats queue_stats;
int16_t txq_stats_map[IGC_QUEUE_PAIRS_NUM];
int16_t rxq_stats_map[IGC_QUEUE_PAIRS_NUM];
struct igc_interrupt intr;
bool stopped;
};
@ -100,6 +123,12 @@ struct igc_adapter {
#define IGC_DEV_PRIVATE_HW(_dev) \
(&((struct igc_adapter *)(_dev)->data->dev_private)->hw)
#define IGC_DEV_PRIVATE_STATS(_dev) \
(&((struct igc_adapter *)(_dev)->data->dev_private)->stats)
#define IGC_DEV_PRIVATE_QUEUE_STATS(_dev) \
(&((struct igc_adapter *)(_dev)->data->dev_private)->queue_stats)
#define IGC_DEV_PRIVATE_INTR(_dev) \
(&((struct igc_adapter *)(_dev)->data->dev_private)->intr)