Merge branch 'net-core-unify-dstats-with-tstats-and-lstats-implement-generic-dstats-collection'
Jeremy Kerr says: ==================== net: core: Unify dstats with tstats and lstats, implement generic dstats collection The struct pcpu_dstats ("dstats") has a few variations from the other two stats types (struct pcpu_sw_netstats and struct pcpu_lstats), and doesn't have generic helpers for collecting the per-cpu stats into a struct rtnl_link_stats64. This change unifies dstats with the other types, adds a collection implementation to the core, and updates the single driver (vrf) to use this generic implementation. Of course, questions/comments/etc are most welcome! v3: https://lore.kernel.org/r/20240605-dstats-v2-0-7fae03f813f3@codeconstruct.com.au v2: v1: https://lore.kernel.org/r/20240605-dstats-v1-0-1024396e1670@codeconstruct.com.au ==================== Link: https://lore.kernel.org/r/20240607-dstats-v3-0-cc781fe116f7@codeconstruct.com.au Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
bfc65070a3
@ -126,8 +126,8 @@ static void vrf_rx_stats(struct net_device *dev, int len)
|
||||
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
|
||||
|
||||
u64_stats_update_begin(&dstats->syncp);
|
||||
dstats->rx_packets++;
|
||||
dstats->rx_bytes += len;
|
||||
u64_stats_inc(&dstats->rx_packets);
|
||||
u64_stats_add(&dstats->rx_bytes, len);
|
||||
u64_stats_update_end(&dstats->syncp);
|
||||
}
|
||||
|
||||
@ -137,33 +137,6 @@ static void vrf_tx_error(struct net_device *vrf_dev, struct sk_buff *skb)
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
static void vrf_get_stats64(struct net_device *dev,
|
||||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
int i;
|
||||
|
||||
for_each_possible_cpu(i) {
|
||||
const struct pcpu_dstats *dstats;
|
||||
u64 tbytes, tpkts, tdrops, rbytes, rpkts;
|
||||
unsigned int start;
|
||||
|
||||
dstats = per_cpu_ptr(dev->dstats, i);
|
||||
do {
|
||||
start = u64_stats_fetch_begin(&dstats->syncp);
|
||||
tbytes = dstats->tx_bytes;
|
||||
tpkts = dstats->tx_packets;
|
||||
tdrops = dstats->tx_drops;
|
||||
rbytes = dstats->rx_bytes;
|
||||
rpkts = dstats->rx_packets;
|
||||
} while (u64_stats_fetch_retry(&dstats->syncp, start));
|
||||
stats->tx_bytes += tbytes;
|
||||
stats->tx_packets += tpkts;
|
||||
stats->tx_dropped += tdrops;
|
||||
stats->rx_bytes += rbytes;
|
||||
stats->rx_packets += rpkts;
|
||||
}
|
||||
}
|
||||
|
||||
static struct vrf_map *netns_vrf_map(struct net *net)
|
||||
{
|
||||
struct netns_vrf *nn_vrf = net_generic(net, vrf_net_id);
|
||||
@ -408,10 +381,15 @@ static int vrf_local_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
|
||||
if (likely(__netif_rx(skb) == NET_RX_SUCCESS))
|
||||
if (likely(__netif_rx(skb) == NET_RX_SUCCESS)) {
|
||||
vrf_rx_stats(dev, len);
|
||||
else
|
||||
this_cpu_inc(dev->dstats->rx_drops);
|
||||
} else {
|
||||
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
|
||||
|
||||
u64_stats_update_begin(&dstats->syncp);
|
||||
u64_stats_inc(&dstats->rx_drops);
|
||||
u64_stats_update_end(&dstats->syncp);
|
||||
}
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
@ -599,19 +577,20 @@ static netdev_tx_t is_ip_tx_frame(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
|
||||
|
||||
int len = skb->len;
|
||||
netdev_tx_t ret = is_ip_tx_frame(skb, dev);
|
||||
|
||||
u64_stats_update_begin(&dstats->syncp);
|
||||
if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
|
||||
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
|
||||
|
||||
u64_stats_update_begin(&dstats->syncp);
|
||||
dstats->tx_packets++;
|
||||
dstats->tx_bytes += len;
|
||||
u64_stats_update_end(&dstats->syncp);
|
||||
u64_stats_inc(&dstats->tx_packets);
|
||||
u64_stats_add(&dstats->tx_bytes, len);
|
||||
} else {
|
||||
this_cpu_inc(dev->dstats->tx_drops);
|
||||
u64_stats_inc(&dstats->tx_drops);
|
||||
}
|
||||
u64_stats_update_end(&dstats->syncp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1195,7 +1174,6 @@ static const struct net_device_ops vrf_netdev_ops = {
|
||||
.ndo_uninit = vrf_dev_uninit,
|
||||
.ndo_start_xmit = vrf_xmit,
|
||||
.ndo_set_mac_address = eth_mac_addr,
|
||||
.ndo_get_stats64 = vrf_get_stats64,
|
||||
.ndo_add_slave = vrf_add_slave,
|
||||
.ndo_del_slave = vrf_del_slave,
|
||||
};
|
||||
|
@ -2731,12 +2731,12 @@ struct pcpu_sw_netstats {
|
||||
} __aligned(4 * sizeof(u64));
|
||||
|
||||
struct pcpu_dstats {
|
||||
u64 rx_packets;
|
||||
u64 rx_bytes;
|
||||
u64 rx_drops;
|
||||
u64 tx_packets;
|
||||
u64 tx_bytes;
|
||||
u64 tx_drops;
|
||||
u64_stats_t rx_packets;
|
||||
u64_stats_t rx_bytes;
|
||||
u64_stats_t rx_drops;
|
||||
u64_stats_t tx_packets;
|
||||
u64_stats_t tx_bytes;
|
||||
u64_stats_t tx_drops;
|
||||
struct u64_stats_sync syncp;
|
||||
} __aligned(8 * sizeof(u64));
|
||||
|
||||
|
@ -10703,6 +10703,54 @@ void netdev_run_todo(void)
|
||||
wake_up(&netdev_unregistering_wq);
|
||||
}
|
||||
|
||||
/* Collate per-cpu network dstats statistics
|
||||
*
|
||||
* Read per-cpu network statistics from dev->dstats and populate the related
|
||||
* fields in @s.
|
||||
*/
|
||||
static void dev_fetch_dstats(struct rtnl_link_stats64 *s,
|
||||
const struct pcpu_dstats __percpu *dstats)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
u64 rx_packets, rx_bytes, rx_drops;
|
||||
u64 tx_packets, tx_bytes, tx_drops;
|
||||
const struct pcpu_dstats *stats;
|
||||
unsigned int start;
|
||||
|
||||
stats = per_cpu_ptr(dstats, cpu);
|
||||
do {
|
||||
start = u64_stats_fetch_begin(&stats->syncp);
|
||||
rx_packets = u64_stats_read(&stats->rx_packets);
|
||||
rx_bytes = u64_stats_read(&stats->rx_bytes);
|
||||
rx_drops = u64_stats_read(&stats->rx_drops);
|
||||
tx_packets = u64_stats_read(&stats->tx_packets);
|
||||
tx_bytes = u64_stats_read(&stats->tx_bytes);
|
||||
tx_drops = u64_stats_read(&stats->tx_drops);
|
||||
} while (u64_stats_fetch_retry(&stats->syncp, start));
|
||||
|
||||
s->rx_packets += rx_packets;
|
||||
s->rx_bytes += rx_bytes;
|
||||
s->rx_dropped += rx_drops;
|
||||
s->tx_packets += tx_packets;
|
||||
s->tx_bytes += tx_bytes;
|
||||
s->tx_dropped += tx_drops;
|
||||
}
|
||||
}
|
||||
|
||||
/* ndo_get_stats64 implementation for dtstats-based accounting.
|
||||
*
|
||||
* Populate @s from dev->stats and dev->dstats. This is used internally by the
|
||||
* core for NETDEV_PCPU_STAT_DSTAT-type stats collection.
|
||||
*/
|
||||
static void dev_get_dstats64(const struct net_device *dev,
|
||||
struct rtnl_link_stats64 *s)
|
||||
{
|
||||
netdev_stats_to_stats64(s, &dev->stats);
|
||||
dev_fetch_dstats(s, dev->dstats);
|
||||
}
|
||||
|
||||
/* Convert net_device_stats to rtnl_link_stats64. rtnl_link_stats64 has
|
||||
* all the same fields in the same order as net_device_stats, with only
|
||||
* the type differing, but rtnl_link_stats64 may have additional fields
|
||||
@ -10779,6 +10827,8 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
|
||||
netdev_stats_to_stats64(storage, ops->ndo_get_stats(dev));
|
||||
} else if (dev->pcpu_stat_type == NETDEV_PCPU_STAT_TSTATS) {
|
||||
dev_get_tstats64(dev, storage);
|
||||
} else if (dev->pcpu_stat_type == NETDEV_PCPU_STAT_DSTATS) {
|
||||
dev_get_dstats64(dev, storage);
|
||||
} else {
|
||||
netdev_stats_to_stats64(storage, &dev->stats);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user