net: veth: add page_pool stats

Introduce page_pool stats support to report info about local page_pool
through ethtool

Tested-by: Maryam Tahhan <mtahhan@redhat.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Lorenzo Bianconi 2023-04-22 20:54:33 +02:00 committed by Jakub Kicinski
parent 0ebab78cbc
commit 4fc418053e
2 changed files with 18 additions and 3 deletions

View File

@ -403,6 +403,7 @@ config TUN_VNET_CROSS_LE
config VETH config VETH
tristate "Virtual ethernet pair device" tristate "Virtual ethernet pair device"
select PAGE_POOL select PAGE_POOL
select PAGE_POOL_STATS
help help
This device is a local ethernet tunnel. Devices are created in pairs. This device is a local ethernet tunnel. Devices are created in pairs.
When one end receives the packet it appears on its pair and vice When one end receives the packet it appears on its pair and vice

View File

@ -157,6 +157,8 @@ static void veth_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
for (j = 0; j < VETH_TQ_STATS_LEN; j++) for (j = 0; j < VETH_TQ_STATS_LEN; j++)
ethtool_sprintf(&p, "tx_queue_%u_%.18s", ethtool_sprintf(&p, "tx_queue_%u_%.18s",
i, veth_tq_stats_desc[j].desc); i, veth_tq_stats_desc[j].desc);
page_pool_ethtool_stats_get_strings(p);
break; break;
} }
} }
@ -167,7 +169,8 @@ static int veth_get_sset_count(struct net_device *dev, int sset)
case ETH_SS_STATS: case ETH_SS_STATS:
return ARRAY_SIZE(ethtool_stats_keys) + return ARRAY_SIZE(ethtool_stats_keys) +
VETH_RQ_STATS_LEN * dev->real_num_rx_queues + VETH_RQ_STATS_LEN * dev->real_num_rx_queues +
VETH_TQ_STATS_LEN * dev->real_num_tx_queues; VETH_TQ_STATS_LEN * dev->real_num_tx_queues +
page_pool_ethtool_stats_get_count();
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
@ -178,7 +181,8 @@ static void veth_get_ethtool_stats(struct net_device *dev,
{ {
struct veth_priv *rcv_priv, *priv = netdev_priv(dev); struct veth_priv *rcv_priv, *priv = netdev_priv(dev);
struct net_device *peer = rtnl_dereference(priv->peer); struct net_device *peer = rtnl_dereference(priv->peer);
int i, j, idx; struct page_pool_stats pp_stats = {};
int i, j, idx, pp_idx;
data[0] = peer ? peer->ifindex : 0; data[0] = peer ? peer->ifindex : 0;
idx = 1; idx = 1;
@ -197,9 +201,10 @@ static void veth_get_ethtool_stats(struct net_device *dev,
} while (u64_stats_fetch_retry(&rq_stats->syncp, start)); } while (u64_stats_fetch_retry(&rq_stats->syncp, start));
idx += VETH_RQ_STATS_LEN; idx += VETH_RQ_STATS_LEN;
} }
pp_idx = idx;
if (!peer) if (!peer)
return; goto page_pool_stats;
rcv_priv = netdev_priv(peer); rcv_priv = netdev_priv(peer);
for (i = 0; i < peer->real_num_rx_queues; i++) { for (i = 0; i < peer->real_num_rx_queues; i++) {
@ -216,7 +221,16 @@ static void veth_get_ethtool_stats(struct net_device *dev,
data[tx_idx + j] += *(u64 *)(base + offset); data[tx_idx + j] += *(u64 *)(base + offset);
} }
} while (u64_stats_fetch_retry(&rq_stats->syncp, start)); } while (u64_stats_fetch_retry(&rq_stats->syncp, start));
pp_idx = tx_idx + VETH_TQ_STATS_LEN;
} }
page_pool_stats:
for (i = 0; i < dev->real_num_rx_queues; i++) {
if (!priv->rq[i].page_pool)
continue;
page_pool_get_stats(priv->rq[i].page_pool, &pp_stats);
}
page_pool_ethtool_stats_get(&data[pp_idx], &pp_stats);
} }
static void veth_get_channels(struct net_device *dev, static void veth_get_channels(struct net_device *dev,