net/vmxnet3: retain counters on restart
Most NICs like virtio, igb/ixgbe etc. don't reset counters on dev_start and arguably this helps in monitoring the counters across a longer time span with multiple device start/stops. vmxnet3 behavior is opposite to that and counters are reset by the host side implementation each time the device is restarted. Change the driver to save the counters in its private context before it is reset by writing CMD_ACTIVATE to REG_CMD. Signed-off-by: Nachiketa Prachanda <nprachan@brocade.com> Acked-by: Shrikrishna Khare <skhare@vmware.com>
This commit is contained in:
parent
4810d3af83
commit
e4d56c333f
@ -85,6 +85,7 @@ static void vmxnet3_dev_allmulticast_enable(struct rte_eth_dev *dev);
|
||||
static void vmxnet3_dev_allmulticast_disable(struct rte_eth_dev *dev);
|
||||
static int vmxnet3_dev_link_update(struct rte_eth_dev *dev,
|
||||
int wait_to_complete);
|
||||
static void vmxnet3_hw_stats_save(struct vmxnet3_hw *hw);
|
||||
static void vmxnet3_dev_stats_get(struct rte_eth_dev *dev,
|
||||
struct rte_eth_stats *stats);
|
||||
static void vmxnet3_dev_info_get(struct rte_eth_dev *dev,
|
||||
@ -351,6 +352,10 @@ eth_vmxnet3_dev_init(struct rte_eth_dev *eth_dev)
|
||||
RTE_ASSERT((hw->rxdata_desc_size & ~VMXNET3_RXDATA_DESC_SIZE_MASK) ==
|
||||
hw->rxdata_desc_size);
|
||||
|
||||
/* clear shadow stats */
|
||||
memset(hw->saved_tx_stats, 0, sizeof(hw->saved_tx_stats));
|
||||
memset(hw->saved_rx_stats, 0, sizeof(hw->saved_rx_stats));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -707,6 +712,9 @@ vmxnet3_dev_start(struct rte_eth_dev *dev)
|
||||
|
||||
PMD_INIT_FUNC_TRACE();
|
||||
|
||||
/* Save stats before it is reset by CMD_ACTIVATE */
|
||||
vmxnet3_hw_stats_save(hw);
|
||||
|
||||
ret = vmxnet3_setup_driver_shared(dev);
|
||||
if (ret != VMXNET3_SUCCESS)
|
||||
return ret;
|
||||
@ -819,48 +827,106 @@ vmxnet3_dev_close(struct rte_eth_dev *dev)
|
||||
hw->adapter_stopped = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
vmxnet3_hw_tx_stats_get(struct vmxnet3_hw *hw, unsigned int q,
|
||||
struct UPT1_TxStats *res)
|
||||
{
|
||||
#define VMXNET3_UPDATE_TX_STAT(h, i, f, r) \
|
||||
((r)->f = (h)->tqd_start[(i)].stats.f + \
|
||||
(h)->saved_tx_stats[(i)].f)
|
||||
|
||||
VMXNET3_UPDATE_TX_STAT(hw, q, ucastPktsTxOK, res);
|
||||
VMXNET3_UPDATE_TX_STAT(hw, q, mcastPktsTxOK, res);
|
||||
VMXNET3_UPDATE_TX_STAT(hw, q, bcastPktsTxOK, res);
|
||||
VMXNET3_UPDATE_TX_STAT(hw, q, ucastBytesTxOK, res);
|
||||
VMXNET3_UPDATE_TX_STAT(hw, q, mcastBytesTxOK, res);
|
||||
VMXNET3_UPDATE_TX_STAT(hw, q, bcastBytesTxOK, res);
|
||||
VMXNET3_UPDATE_TX_STAT(hw, q, pktsTxError, res);
|
||||
VMXNET3_UPDATE_TX_STAT(hw, q, pktsTxDiscard, res);
|
||||
|
||||
#undef VMXNET3_UPDATE_TX_STAT
|
||||
}
|
||||
|
||||
static void
|
||||
vmxnet3_hw_rx_stats_get(struct vmxnet3_hw *hw, unsigned int q,
|
||||
struct UPT1_RxStats *res)
|
||||
{
|
||||
#define VMXNET3_UPDATE_RX_STAT(h, i, f, r) \
|
||||
((r)->f = (h)->rqd_start[(i)].stats.f + \
|
||||
(h)->saved_rx_stats[(i)].f)
|
||||
|
||||
VMXNET3_UPDATE_RX_STAT(hw, q, ucastPktsRxOK, res);
|
||||
VMXNET3_UPDATE_RX_STAT(hw, q, mcastPktsRxOK, res);
|
||||
VMXNET3_UPDATE_RX_STAT(hw, q, bcastPktsRxOK, res);
|
||||
VMXNET3_UPDATE_RX_STAT(hw, q, ucastBytesRxOK, res);
|
||||
VMXNET3_UPDATE_RX_STAT(hw, q, mcastBytesRxOK, res);
|
||||
VMXNET3_UPDATE_RX_STAT(hw, q, bcastBytesRxOK, res);
|
||||
VMXNET3_UPDATE_RX_STAT(hw, q, pktsRxError, res);
|
||||
VMXNET3_UPDATE_RX_STAT(hw, q, pktsRxOutOfBuf, res);
|
||||
|
||||
#undef VMXNET3_UPDATE_RX_STATS
|
||||
}
|
||||
|
||||
static void
|
||||
vmxnet3_hw_stats_save(struct vmxnet3_hw *hw)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
|
||||
|
||||
RTE_BUILD_BUG_ON(RTE_ETHDEV_QUEUE_STAT_CNTRS < VMXNET3_MAX_TX_QUEUES);
|
||||
|
||||
for (i = 0; i < hw->num_tx_queues; i++)
|
||||
vmxnet3_hw_tx_stats_get(hw, i, &hw->saved_tx_stats[i]);
|
||||
for (i = 0; i < hw->num_rx_queues; i++)
|
||||
vmxnet3_hw_rx_stats_get(hw, i, &hw->saved_rx_stats[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
vmxnet3_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
|
||||
{
|
||||
unsigned int i;
|
||||
struct vmxnet3_hw *hw = dev->data->dev_private;
|
||||
struct UPT1_TxStats txStats;
|
||||
struct UPT1_RxStats rxStats;
|
||||
|
||||
VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
|
||||
|
||||
RTE_BUILD_BUG_ON(RTE_ETHDEV_QUEUE_STAT_CNTRS < VMXNET3_MAX_TX_QUEUES);
|
||||
for (i = 0; i < hw->num_tx_queues; i++) {
|
||||
struct UPT1_TxStats *txStats = &hw->tqd_start[i].stats;
|
||||
vmxnet3_hw_tx_stats_get(hw, i, &txStats);
|
||||
|
||||
stats->q_opackets[i] = txStats->ucastPktsTxOK +
|
||||
txStats->mcastPktsTxOK +
|
||||
txStats->bcastPktsTxOK;
|
||||
stats->q_obytes[i] = txStats->ucastBytesTxOK +
|
||||
txStats->mcastBytesTxOK +
|
||||
txStats->bcastBytesTxOK;
|
||||
stats->q_opackets[i] = txStats.ucastPktsTxOK +
|
||||
txStats.mcastPktsTxOK +
|
||||
txStats.bcastPktsTxOK;
|
||||
|
||||
stats->q_obytes[i] = txStats.ucastBytesTxOK +
|
||||
txStats.mcastBytesTxOK +
|
||||
txStats.bcastBytesTxOK;
|
||||
|
||||
stats->opackets += stats->q_opackets[i];
|
||||
stats->obytes += stats->q_obytes[i];
|
||||
stats->oerrors += txStats->pktsTxError + txStats->pktsTxDiscard;
|
||||
stats->oerrors += txStats.pktsTxError + txStats.pktsTxDiscard;
|
||||
}
|
||||
|
||||
RTE_BUILD_BUG_ON(RTE_ETHDEV_QUEUE_STAT_CNTRS < VMXNET3_MAX_RX_QUEUES);
|
||||
for (i = 0; i < hw->num_rx_queues; i++) {
|
||||
struct UPT1_RxStats *rxStats = &hw->rqd_start[i].stats;
|
||||
vmxnet3_hw_rx_stats_get(hw, i, &rxStats);
|
||||
|
||||
stats->q_ipackets[i] = rxStats->ucastPktsRxOK +
|
||||
rxStats->mcastPktsRxOK +
|
||||
rxStats->bcastPktsRxOK;
|
||||
stats->q_ipackets[i] = rxStats.ucastPktsRxOK +
|
||||
rxStats.mcastPktsRxOK +
|
||||
rxStats.bcastPktsRxOK;
|
||||
|
||||
stats->q_ibytes[i] = rxStats->ucastBytesRxOK +
|
||||
rxStats->mcastBytesRxOK +
|
||||
rxStats->bcastBytesRxOK;
|
||||
stats->q_ibytes[i] = rxStats.ucastBytesRxOK +
|
||||
rxStats.mcastBytesRxOK +
|
||||
rxStats.bcastBytesRxOK;
|
||||
|
||||
stats->ipackets += stats->q_ipackets[i];
|
||||
stats->ibytes += stats->q_ibytes[i];
|
||||
|
||||
stats->q_errors[i] = rxStats->pktsRxError;
|
||||
stats->ierrors += rxStats->pktsRxError;
|
||||
stats->rx_nombuf += rxStats->pktsRxOutOfBuf;
|
||||
stats->q_errors[i] = rxStats.pktsRxError;
|
||||
stats->ierrors += rxStats.pktsRxError;
|
||||
stats->rx_nombuf += rxStats.pktsRxOutOfBuf;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,6 +122,8 @@ struct vmxnet3_hw {
|
||||
Vmxnet3_MemRegs *memRegs;
|
||||
uint64_t memRegsPA;
|
||||
#define VMXNET3_VFT_TABLE_SIZE (VMXNET3_VFT_SIZE * sizeof(uint32_t))
|
||||
UPT1_TxStats saved_tx_stats[VMXNET3_MAX_TX_QUEUES];
|
||||
UPT1_RxStats saved_rx_stats[VMXNET3_MAX_RX_QUEUES];
|
||||
};
|
||||
|
||||
#define VMXNET3_REV_3 2 /* Vmxnet3 Rev. 3 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user