Skip to content

Commit 6f2684b

Browse files
peilin-yeMartin KaFai Lau
authored andcommitted
veth: Use tstats per-CPU traffic counters
Currently veth devices use the lstats per-CPU traffic counters, which only cover TX traffic. veth_get_stats64() actually populates RX stats of a veth device from its peer's TX counters, based on the assumption that a veth device can _only_ receive packets from its peer, which is no longer true: For example, recent CNIs (like Cilium) can use the bpf_redirect_peer() BPF helper to redirect traffic from NIC's tc ingress to veth's tc ingress (in a different netns), skipping veth's peer device. Unfortunately, this kind of traffic isn't currently accounted for in veth's RX stats. In preparation for the fix, use tstats (instead of lstats) to maintain both RX and TX counters for each veth device. We'll use RX counters for bpf_redirect_peer() traffic, and keep using TX counters for the usual "peer-to-peer" traffic. In veth_get_stats64(), calculate RX stats by _adding_ RX count to peer's TX count, in order to cover both kinds of traffic. veth_stats_rx() might need a name change (perhaps to "veth_stats_xdp()") for less confusion, but let's leave it to another patch to keep the fix minimal. Signed-off-by: Peilin Ye <peilin.ye@bytedance.com> Co-developed-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org> Link: https://lore.kernel.org/r/20231114004220.6495-5-daniel@iogearbox.net Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
1 parent ae16582 commit 6f2684b

File tree

1 file changed

+11
-19
lines changed

1 file changed

+11
-19
lines changed

drivers/net/veth.c

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
373373
skb_tx_timestamp(skb);
374374
if (likely(veth_forward_skb(rcv, skb, rq, use_napi) == NET_RX_SUCCESS)) {
375375
if (!use_napi)
376-
dev_lstats_add(dev, length);
376+
dev_sw_netstats_tx_add(dev, 1, length);
377377
else
378378
__veth_xdp_flush(rq);
379379
} else {
@@ -387,14 +387,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
387387
return ret;
388388
}
389389

390-
static u64 veth_stats_tx(struct net_device *dev, u64 *packets, u64 *bytes)
391-
{
392-
struct veth_priv *priv = netdev_priv(dev);
393-
394-
dev_lstats_read(dev, packets, bytes);
395-
return atomic64_read(&priv->dropped);
396-
}
397-
398390
static void veth_stats_rx(struct veth_stats *result, struct net_device *dev)
399391
{
400392
struct veth_priv *priv = netdev_priv(dev);
@@ -432,24 +424,24 @@ static void veth_get_stats64(struct net_device *dev,
432424
struct veth_priv *priv = netdev_priv(dev);
433425
struct net_device *peer;
434426
struct veth_stats rx;
435-
u64 packets, bytes;
436427

437-
tot->tx_dropped = veth_stats_tx(dev, &packets, &bytes);
438-
tot->tx_bytes = bytes;
439-
tot->tx_packets = packets;
428+
tot->tx_dropped = atomic64_read(&priv->dropped);
429+
dev_fetch_sw_netstats(tot, dev->tstats);
440430

441431
veth_stats_rx(&rx, dev);
442432
tot->tx_dropped += rx.xdp_tx_err;
443433
tot->rx_dropped = rx.rx_drops + rx.peer_tq_xdp_xmit_err;
444-
tot->rx_bytes = rx.xdp_bytes;
445-
tot->rx_packets = rx.xdp_packets;
434+
tot->rx_bytes += rx.xdp_bytes;
435+
tot->rx_packets += rx.xdp_packets;
446436

447437
rcu_read_lock();
448438
peer = rcu_dereference(priv->peer);
449439
if (peer) {
450-
veth_stats_tx(peer, &packets, &bytes);
451-
tot->rx_bytes += bytes;
452-
tot->rx_packets += packets;
440+
struct rtnl_link_stats64 tot_peer = {};
441+
442+
dev_fetch_sw_netstats(&tot_peer, peer->tstats);
443+
tot->rx_bytes += tot_peer.tx_bytes;
444+
tot->rx_packets += tot_peer.tx_packets;
453445

454446
veth_stats_rx(&rx, peer);
455447
tot->tx_dropped += rx.peer_tq_xdp_xmit_err;
@@ -1783,7 +1775,7 @@ static void veth_setup(struct net_device *dev)
17831775
NETIF_F_HW_VLAN_STAG_RX);
17841776
dev->needs_free_netdev = true;
17851777
dev->priv_destructor = veth_dev_free;
1786-
dev->pcpu_stat_type = NETDEV_PCPU_STAT_LSTATS;
1778+
dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
17871779
dev->max_mtu = ETH_MAX_MTU;
17881780

17891781
dev->hw_features = VETH_FEATURES;

0 commit comments

Comments
 (0)