]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ppp: convert to percpu netstats
authorQingfang Deng <dqfext@gmail.com>
Tue, 10 Jun 2025 08:32:10 +0000 (16:32 +0800)
committerJakub Kicinski <kuba@kernel.org>
Wed, 11 Jun 2025 21:11:48 +0000 (14:11 -0700)
Convert to percpu netstats to avoid lock contention when reading them.

Signed-off-by: Qingfang Deng <dqfext@gmail.com>
Link: https://patch.msgid.link/20250610083211.909015-1-dqfext@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ppp/ppp_generic.c

index def84e87e05b2e9daa7a5717d20b58854d74dbf1..4cf9d1822a83f9ec253dc738463de4081b607a43 100644 (file)
@@ -107,18 +107,6 @@ struct ppp_file {
 #define PF_TO_PPP(pf)          PF_TO_X(pf, struct ppp)
 #define PF_TO_CHANNEL(pf)      PF_TO_X(pf, struct channel)
 
-/*
- * Data structure to hold primary network stats for which
- * we want to use 64 bit storage.  Other network stats
- * are stored in dev->stats of the ppp strucute.
- */
-struct ppp_link_stats {
-       u64 rx_packets;
-       u64 tx_packets;
-       u64 rx_bytes;
-       u64 tx_bytes;
-};
-
 /*
  * Data structure describing one ppp unit.
  * A ppp unit corresponds to a ppp network interface device
@@ -162,7 +150,6 @@ struct ppp {
        struct bpf_prog *active_filter; /* filter for pkts to reset idle */
 #endif /* CONFIG_PPP_FILTER */
        struct net      *ppp_net;       /* the net we belong to */
-       struct ppp_link_stats stats64;  /* 64 bit network stats */
 };
 
 /*
@@ -1539,23 +1526,12 @@ ppp_net_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
 static void
 ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64)
 {
-       struct ppp *ppp = netdev_priv(dev);
-
-       ppp_recv_lock(ppp);
-       stats64->rx_packets = ppp->stats64.rx_packets;
-       stats64->rx_bytes   = ppp->stats64.rx_bytes;
-       ppp_recv_unlock(ppp);
-
-       ppp_xmit_lock(ppp);
-       stats64->tx_packets = ppp->stats64.tx_packets;
-       stats64->tx_bytes   = ppp->stats64.tx_bytes;
-       ppp_xmit_unlock(ppp);
-
        stats64->rx_errors        = dev->stats.rx_errors;
        stats64->tx_errors        = dev->stats.tx_errors;
        stats64->rx_dropped       = dev->stats.rx_dropped;
        stats64->tx_dropped       = dev->stats.tx_dropped;
        stats64->rx_length_errors = dev->stats.rx_length_errors;
+       dev_fetch_sw_netstats(stats64, dev->tstats);
 }
 
 static int ppp_dev_init(struct net_device *dev)
@@ -1650,6 +1626,7 @@ static void ppp_setup(struct net_device *dev)
        dev->type = ARPHRD_PPP;
        dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
        dev->priv_destructor = ppp_dev_priv_destructor;
+       dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
        netif_keep_dst(dev);
 }
 
@@ -1796,8 +1773,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
 #endif /* CONFIG_PPP_FILTER */
        }
 
-       ++ppp->stats64.tx_packets;
-       ppp->stats64.tx_bytes += skb->len - PPP_PROTO_LEN;
+       dev_sw_netstats_tx_add(ppp->dev, 1, skb->len - PPP_PROTO_LEN);
 
        switch (proto) {
        case PPP_IP:
@@ -2474,8 +2450,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
                break;
        }
 
-       ++ppp->stats64.rx_packets;
-       ppp->stats64.rx_bytes += skb->len - 2;
+       dev_sw_netstats_rx_add(ppp->dev, skb->len - PPP_PROTO_LEN);
 
        npi = proto_to_npindex(proto);
        if (npi < 0) {
@@ -3303,14 +3278,25 @@ static void
 ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
 {
        struct slcompress *vj = ppp->vj;
+       int cpu;
 
        memset(st, 0, sizeof(*st));
-       st->p.ppp_ipackets = ppp->stats64.rx_packets;
+       for_each_possible_cpu(cpu) {
+               struct pcpu_sw_netstats *p = per_cpu_ptr(ppp->dev->tstats, cpu);
+               u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+
+               rx_packets = u64_stats_read(&p->rx_packets);
+               rx_bytes = u64_stats_read(&p->rx_bytes);
+               tx_packets = u64_stats_read(&p->tx_packets);
+               tx_bytes = u64_stats_read(&p->tx_bytes);
+
+               st->p.ppp_ipackets += rx_packets;
+               st->p.ppp_ibytes += rx_bytes;
+               st->p.ppp_opackets += tx_packets;
+               st->p.ppp_obytes += tx_bytes;
+       }
        st->p.ppp_ierrors = ppp->dev->stats.rx_errors;
-       st->p.ppp_ibytes = ppp->stats64.rx_bytes;
-       st->p.ppp_opackets = ppp->stats64.tx_packets;
        st->p.ppp_oerrors = ppp->dev->stats.tx_errors;
-       st->p.ppp_obytes = ppp->stats64.tx_bytes;
        if (!vj)
                return;
        st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;