Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ed343e6
rtnetlink: introduce generic XDP statistics
alobakin Oct 7, 2021
e6c1aff
xdp: provide common driver helpers for implementing XDP stats
alobakin Oct 22, 2021
4aa773c
ena: implement generic XDP statistics callbacks
alobakin Oct 7, 2021
e959ec1
dpaa2: implement generic XDP stats callbacks
alobakin Oct 7, 2021
fae6144
enetc: implement generic XDP stats callbacks
alobakin Oct 7, 2021
6eba333
mvneta: reformat mvneta_netdev_ops
alobakin Oct 7, 2021
95b1b5e
mvneta: add .ndo_get_xdp_stats() callback
alobakin Oct 7, 2021
adfbabc
mvpp2: provide .ndo_get_xdp_stats() callback
alobakin Oct 7, 2021
81cfee4
mlx5: don't mix XDP_DROP and Rx XDP error cases
alobakin Oct 7, 2021
48c2c04
mlx5: provide generic XDP stats callbacks
alobakin Oct 7, 2021
59a71d6
sf100, sfx: implement generic XDP stats callbacks
alobakin Oct 7, 2021
793c67a
veth: don't mix XDP_DROP counter with Rx XDP errors
alobakin Oct 7, 2021
971ee4a
veth: drop 'xdp_' suffix from packets and bytes stats
alobakin Oct 7, 2021
079e144
veth: reformat veth_netdev_ops
alobakin Oct 18, 2021
90e192e
veth: add generic XDP stats callbacks
alobakin Oct 7, 2021
7e3a91d
virtio_net: don't mix XDP_DROP counter with Rx XDP errors
alobakin Oct 7, 2021
5134c90
virtio_net: rename xdp_tx{,_drops} SQ stats to xdp_xmit{,_errors}
alobakin Oct 7, 2021
3a8b631
virtio_net: reformat virtnet_netdev
alobakin Oct 18, 2021
21b530d
virtio_net: add callbacks for generic XDP stats
alobakin Oct 7, 2021
5f047e9
i40e: add XDP and XSK generic per-channel statistics
alobakin Oct 22, 2021
6f9206e
ice: add XDP and XSK generic per-channel statistics
alobakin Oct 22, 2021
6437362
igb: add XDP generic per-channel statistics
alobakin Oct 22, 2021
b87200b
igc: bail out early on XSK xmit if no descs are available
alobakin Oct 22, 2021
15b1089
igc: add XDP and XSK generic per-channel statistics
alobakin Oct 22, 2021
6fb6697
ixgbe: add XDP and XSK generic per-channel statistics
alobakin Oct 22, 2021
eee07b2
Documentation: reflect generic XDP statistics
alobakin Oct 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions Documentation/networking/statistics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,29 @@ If `-s` is specified once the detailed errors won't be shown.

`ip` supports JSON formatting via the `-j` option.

For some interfaces, standard XDP statistics are available.
It can be accessed the same ways, e.g. `ip`::

$ ip link xdpstats dev enp178s0
16: enp178s0:
xdp-channel0-rx_xdp_packets: 0
xdp-channel0-rx_xdp_bytes: 1
xdp-channel0-rx_xdp_errors: 2
xdp-channel0-rx_xdp_aborted: 3
xdp-channel0-rx_xdp_drop: 4
xdp-channel0-rx_xdp_invalid: 5
xdp-channel0-rx_xdp_pass: 6
xdp-channel0-rx_xdp_redirect: 7
xdp-channel0-rx_xdp_redirect_errors: 8
xdp-channel0-rx_xdp_tx: 9
xdp-channel0-rx_xdp_tx_errors: 10
xdp-channel0-tx_xdp_xmit_packets: 11
xdp-channel0-tx_xdp_xmit_bytes: 12
xdp-channel0-tx_xdp_xmit_errors: 13
xdp-channel0-tx_xdp_xmit_full: 14

Those are usually per-channel. JSON is also supported via the `-j` opt.

Protocol-specific statistics
----------------------------

Expand Down Expand Up @@ -147,6 +170,8 @@ Statistics are reported both in the responses to link information
requests (`RTM_GETLINK`) and statistic requests (`RTM_GETSTATS`,
when `IFLA_STATS_LINK_64` bit is set in the `.filter_mask` of the request).

`IFLA_STATS_LINK_XDP_XSTATS` bit is used to retrieve standard XDP statstics.

ethtool
-------

Expand Down Expand Up @@ -206,6 +231,14 @@ Retrieving ethtool statistics is a multi-syscall process, drivers are advised
to keep the number of statistics constant to avoid race conditions with
user space trying to read them.

It is up to the developers whether to implement XDP statistics or not due to
possible performance hits. If so, it is encouraged to export it using generic
XDP statistics infrastructure, not driver-defined Ethtool stats.
It can be achieve by implementing `.ndo_get_xdp_stats` and, optionally but
preferred, `.ndo_get_xdp_stats_nch`. There are several common helper structures
and functions in `include/net/xdp.h` to make this simpler and keep the code
compact.

Statistics must persist across routine operations like bringing the interface
down and up.

Expand Down
53 changes: 53 additions & 0 deletions drivers/net/ethernet/amazon/ena/ena_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -3313,12 +3313,65 @@ static void ena_get_stats64(struct net_device *netdev,
stats->tx_errors = 0;
}

static int ena_get_xdp_stats_nch(const struct net_device *netdev, u32 attr_id)
{
const struct ena_adapter *adapter = netdev_priv(netdev);

switch (attr_id) {
case IFLA_XDP_XSTATS_TYPE_XDP:
return adapter->num_io_queues;
default:
return -EOPNOTSUPP;
}
}

static int ena_get_xdp_stats(const struct net_device *netdev, u32 attr_id,
void *attr_data)
{
const struct ena_adapter *adapter = netdev_priv(netdev);
struct ifla_xdp_stats *xdp_stats = attr_data;
u32 i;

switch (attr_id) {
case IFLA_XDP_XSTATS_TYPE_XDP:
break;
default:
return -EOPNOTSUPP;
}

for (i = 0; i < adapter->num_io_queues; i++) {
const struct u64_stats_sync *syncp;
const struct ena_stats_rx *stats;
u32 start;

stats = &adapter->rx_ring[i].rx_stats;
syncp = &adapter->rx_ring[i].syncp;

do {
start = u64_stats_fetch_begin_irq(syncp);

xdp_stats->drop = stats->xdp_drop;
xdp_stats->pass = stats->xdp_pass;
xdp_stats->tx = stats->xdp_tx;
xdp_stats->redirect = stats->xdp_redirect;
xdp_stats->aborted = stats->xdp_aborted;
xdp_stats->invalid = stats->xdp_invalid;
} while (u64_stats_fetch_retry_irq(syncp, start));

xdp_stats++;
}

return 0;
}

static const struct net_device_ops ena_netdev_ops = {
.ndo_open = ena_open,
.ndo_stop = ena_close,
.ndo_start_xmit = ena_start_xmit,
.ndo_select_queue = ena_select_queue,
.ndo_get_stats64 = ena_get_stats64,
.ndo_get_xdp_stats_nch = ena_get_xdp_stats_nch,
.ndo_get_xdp_stats = ena_get_xdp_stats,
.ndo_tx_timeout = ena_tx_timeout,
.ndo_change_mtu = ena_change_mtu,
.ndo_set_mac_address = NULL,
Expand Down
45 changes: 45 additions & 0 deletions drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -1973,6 +1973,49 @@ static void dpaa2_eth_get_stats(struct net_device *net_dev,
}
}

static int dpaa2_eth_get_xdp_stats_nch(const struct net_device *net_dev,
u32 attr_id)
{
const struct dpaa2_eth_priv *priv = netdev_priv(net_dev);

switch (attr_id) {
case IFLA_XDP_XSTATS_TYPE_XDP:
return priv->num_channels;
default:
return -EOPNOTSUPP;
}
}

static int dpaa2_eth_get_xdp_stats(const struct net_device *net_dev,
u32 attr_id, void *attr_data)
{
const struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
struct ifla_xdp_stats *xdp_stats = attr_data;
u32 i;

switch (attr_id) {
case IFLA_XDP_XSTATS_TYPE_XDP:
break;
default:
return -EOPNOTSUPP;
}

for (i = 0; i < priv->num_channels; i++) {
const struct dpaa2_eth_ch_stats *ch_stats;

ch_stats = &priv->channel[i]->stats;

xdp_stats->drop = ch_stats->xdp_drop;
xdp_stats->redirect = ch_stats->xdp_redirect;
xdp_stats->tx = ch_stats->xdp_tx;
xdp_stats->tx_errors = ch_stats->xdp_tx_err;

xdp_stats++;
}

return 0;
}

/* Copy mac unicast addresses from @net_dev to @priv.
* Its sole purpose is to make dpaa2_eth_set_rx_mode() more readable.
*/
Expand Down Expand Up @@ -2601,6 +2644,8 @@ static const struct net_device_ops dpaa2_eth_ops = {
.ndo_stop = dpaa2_eth_stop,
.ndo_set_mac_address = dpaa2_eth_set_addr,
.ndo_get_stats64 = dpaa2_eth_get_stats,
.ndo_get_xdp_stats_nch = dpaa2_eth_get_xdp_stats_nch,
.ndo_get_xdp_stats = dpaa2_eth_get_xdp_stats,
.ndo_set_rx_mode = dpaa2_eth_set_rx_mode,
.ndo_set_features = dpaa2_eth_set_features,
.ndo_eth_ioctl = dpaa2_eth_ioctl,
Expand Down
48 changes: 48 additions & 0 deletions drivers/net/ethernet/freescale/enetc/enetc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2575,6 +2575,54 @@ struct net_device_stats *enetc_get_stats(struct net_device *ndev)
return stats;
}

int enetc_get_xdp_stats_nch(const struct net_device *ndev, u32 attr_id)
{
const struct enetc_ndev_priv *priv = netdev_priv(ndev);

switch (attr_id) {
case IFLA_XDP_XSTATS_TYPE_XDP:
return max(priv->num_rx_rings, priv->num_tx_rings);
default:
return -EOPNOTSUPP;
}
}

int enetc_get_xdp_stats(const struct net_device *ndev, u32 attr_id,
void *attr_data)
{
struct ifla_xdp_stats *xdp_iter, *xdp_stats = attr_data;
const struct enetc_ndev_priv *priv = netdev_priv(ndev);
const struct enetc_ring_stats *stats;
u32 i;

switch (attr_id) {
case IFLA_XDP_XSTATS_TYPE_XDP:
break;
default:
return -EOPNOTSUPP;
}

for (i = 0; i < priv->num_tx_rings; i++) {
stats = &priv->tx_ring[i]->stats;
xdp_iter = xdp_stats + i;

xdp_iter->tx = stats->xdp_tx;
xdp_iter->tx_errors = stats->xdp_tx_drops;
}

for (i = 0; i < priv->num_rx_rings; i++) {
stats = &priv->rx_ring[i]->stats;
xdp_iter = xdp_stats + i;

xdp_iter->drop = stats->xdp_drops;
xdp_iter->redirect = stats->xdp_redirect;
xdp_iter->redirect_errors = stats->xdp_redirect_failures;
xdp_iter->redirect_errors += stats->xdp_redirect_sg;
}

return 0;
}

static int enetc_set_rss(struct net_device *ndev, int en)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/freescale/enetc/enetc.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,9 @@ void enetc_start(struct net_device *ndev);
void enetc_stop(struct net_device *ndev);
netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev);
struct net_device_stats *enetc_get_stats(struct net_device *ndev);
int enetc_get_xdp_stats_nch(const struct net_device *ndev, u32 attr_id);
int enetc_get_xdp_stats(const struct net_device *ndev, u32 attr_id,
void *attr_data);
int enetc_set_features(struct net_device *ndev,
netdev_features_t features);
int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/freescale/enetc/enetc_pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,8 @@ static const struct net_device_ops enetc_ndev_ops = {
.ndo_stop = enetc_close,
.ndo_start_xmit = enetc_xmit,
.ndo_get_stats = enetc_get_stats,
.ndo_get_xdp_stats_nch = enetc_get_xdp_stats_nch,
.ndo_get_xdp_stats = enetc_get_xdp_stats,
.ndo_set_mac_address = enetc_pf_set_mac_addr,
.ndo_set_rx_mode = enetc_pf_set_rx_mode,
.ndo_vlan_rx_add_vid = enetc_vlan_rx_add_vid,
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/i40e/i40e.h
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,7 @@ struct i40e_vsi {
irqreturn_t (*irq_handler)(int irq, void *data);

unsigned long *af_xdp_zc_qps; /* tracks AF_XDP ZC enabled qps */
struct xdp_drv_stats *xdp_stats; /* XDP/XSK stats array */
} ____cacheline_internodealigned_in_smp;

struct i40e_netdev_priv {
Expand Down
38 changes: 37 additions & 1 deletion drivers/net/ethernet/intel/i40e/i40e_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -11087,7 +11087,7 @@ static int i40e_set_num_rings_in_vsi(struct i40e_vsi *vsi)
static int i40e_vsi_alloc_arrays(struct i40e_vsi *vsi, bool alloc_qvectors)
{
struct i40e_ring **next_rings;
int size;
int size, i;
int ret = 0;

/* allocate memory for both Tx, XDP Tx and Rx ring pointers */
Expand All @@ -11103,6 +11103,15 @@ static int i40e_vsi_alloc_arrays(struct i40e_vsi *vsi, bool alloc_qvectors)
}
vsi->rx_rings = next_rings;

vsi->xdp_stats = kcalloc(vsi->alloc_queue_pairs,
sizeof(*vsi->xdp_stats),
GFP_KERNEL);
if (!vsi->xdp_stats)
goto err_xdp_stats;

for (i = 0; i < vsi->alloc_queue_pairs; i++)
xdp_init_drv_stats(vsi->xdp_stats + i);

if (alloc_qvectors) {
/* allocate memory for q_vector pointers */
size = sizeof(struct i40e_q_vector *) * vsi->num_q_vectors;
Expand All @@ -11115,6 +11124,10 @@ static int i40e_vsi_alloc_arrays(struct i40e_vsi *vsi, bool alloc_qvectors)
return ret;

err_vectors:
kfree(vsi->xdp_stats);
vsi->xdp_stats = NULL;

err_xdp_stats:
kfree(vsi->tx_rings);
return ret;
}
Expand Down Expand Up @@ -11225,6 +11238,10 @@ static void i40e_vsi_free_arrays(struct i40e_vsi *vsi, bool free_qvectors)
kfree(vsi->q_vectors);
vsi->q_vectors = NULL;
}

kfree(vsi->xdp_stats);
vsi->xdp_stats = NULL;

kfree(vsi->tx_rings);
vsi->tx_rings = NULL;
vsi->rx_rings = NULL;
Expand Down Expand Up @@ -11347,6 +11364,7 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
if (vsi->back->hw_features & I40E_HW_WB_ON_ITR_CAPABLE)
ring->flags = I40E_TXR_FLAGS_WB_ON_ITR;
ring->itr_setting = pf->tx_itr_default;
ring->xdp_stats = vsi->xdp_stats + i;
WRITE_ONCE(vsi->tx_rings[i], ring++);

if (!i40e_enabled_xdp_vsi(vsi))
Expand All @@ -11365,6 +11383,7 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
ring->flags = I40E_TXR_FLAGS_WB_ON_ITR;
set_ring_xdp(ring);
ring->itr_setting = pf->tx_itr_default;
ring->xdp_stats = vsi->xdp_stats + i;
WRITE_ONCE(vsi->xdp_rings[i], ring++);

setup_rx:
Expand All @@ -11378,6 +11397,7 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
ring->size = 0;
ring->dcb_tc = 0;
ring->itr_setting = pf->rx_itr_default;
ring->xdp_stats = vsi->xdp_stats + i;
WRITE_ONCE(vsi->rx_rings[i], ring);
}

Expand Down Expand Up @@ -13308,6 +13328,19 @@ static int i40e_xdp(struct net_device *dev,
}
}

static int i40e_get_xdp_stats_nch(const struct net_device *dev, u32 attr_id)
{
const struct i40e_netdev_priv *np = netdev_priv(dev);

switch (attr_id) {
case IFLA_XDP_XSTATS_TYPE_XDP:
case IFLA_XDP_XSTATS_TYPE_XSK:
return np->vsi->alloc_queue_pairs;
default:
return -EOPNOTSUPP;
}
}

static const struct net_device_ops i40e_netdev_ops = {
.ndo_open = i40e_open,
.ndo_stop = i40e_close,
Expand Down Expand Up @@ -13343,6 +13376,8 @@ static const struct net_device_ops i40e_netdev_ops = {
.ndo_bpf = i40e_xdp,
.ndo_xdp_xmit = i40e_xdp_xmit,
.ndo_xsk_wakeup = i40e_xsk_wakeup,
.ndo_get_xdp_stats_nch = i40e_get_xdp_stats_nch,
.ndo_get_xdp_stats = xdp_get_drv_stats_generic,
.ndo_dfwd_add_station = i40e_fwd_add,
.ndo_dfwd_del_station = i40e_fwd_del,
};
Expand Down Expand Up @@ -13487,6 +13522,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
netdev->netdev_ops = &i40e_netdev_ops;
netdev->watchdog_timeo = 5 * HZ;
i40e_set_ethtool_ops(netdev);
netdev->xstats = vsi->xdp_stats;

/* MTU range: 68 - 9706 */
netdev->min_mtu = ETH_MIN_MTU;
Expand Down
Loading