lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Sun, 22 Jul 2012 16:19:56 -0400 From: Kevin Groeneveld <kgroeneveld@...il.com> To: netdev@...r.kernel.org Cc: Kevin Groeneveld <kgroeneveld@...il.com> Subject: [PATCH] ppp: add 64 bit stats Add 64 bit stats to ppp driver. The 64 bit stats include tx_bytes, rx_bytes, tx_packets and rx_packets. Other stats are still 32 bit. The 64 bit stats can be retrieved via the ndo_get_stats operation. The SIOCGPPPSTATS ioctl is still 32 bit stats only. Signed-off-by: Kevin Groeneveld <kgroeneveld@...il.com> --- drivers/net/ppp/ppp_generic.c | 110 +++++++++++++++++++++++++++++++++++------ 1 file changed, 95 insertions(+), 15 deletions(-) diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 5c05572..210238c 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -94,6 +94,19 @@ struct ppp_file { #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 { + struct u64_stats_sync syncp; + u64 tx_bytes; + u64 tx_packets; + u64 rx_bytes; + u64 rx_packets; +}; + +/* * Data structure describing one ppp unit. * A ppp unit corresponds to a ppp network interface device * and represents a multilink bundle. @@ -136,6 +149,7 @@ struct ppp { unsigned pass_len, active_len; #endif /* CONFIG_PPP_FILTER */ struct net *ppp_net; /* the net we belong to */ + struct ppp_link_stats __percpu *stats; /* 64 bit network stats */ }; /* @@ -1021,9 +1035,45 @@ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return err; } +struct rtnl_link_stats64* +ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *tot) +{ + struct ppp *ppp = netdev_priv(dev); + int cpu; + + for_each_possible_cpu(cpu) { + struct ppp_link_stats *stats = per_cpu_ptr(ppp->stats, cpu); + unsigned int start; + u64 rx_packets, rx_bytes, tx_packets, tx_bytes; + + do { + start = u64_stats_fetch_begin_bh(&stats->syncp); + rx_packets = stats->rx_packets; + tx_packets = stats->tx_packets; + rx_bytes = stats->rx_bytes; + tx_bytes = stats->tx_bytes; + + } while (u64_stats_fetch_retry_bh(&stats->syncp, start)); + + tot->rx_packets += rx_packets; + tot->tx_packets += tx_packets; + tot->rx_bytes += rx_bytes; + tot->tx_bytes += tx_bytes; + } + + tot->rx_errors = dev->stats.rx_errors; + tot->tx_errors = dev->stats.tx_errors; + tot->rx_dropped = dev->stats.rx_dropped; + tot->tx_dropped = dev->stats.tx_dropped; + tot->rx_length_errors = dev->stats.rx_length_errors; + + return tot; +} + static const struct net_device_ops ppp_netdev_ops = { - .ndo_start_xmit = ppp_start_xmit, - .ndo_do_ioctl = ppp_net_ioctl, + .ndo_start_xmit = ppp_start_xmit, + .ndo_do_ioctl = ppp_net_ioctl, + .ndo_get_stats64 = ppp_get_stats64, }; static void ppp_setup(struct net_device *dev) @@ -1130,6 +1180,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) struct sk_buff *new_skb; int len; unsigned char *cp; + struct ppp_link_stats *stats = this_cpu_ptr(ppp->stats); if (proto < 0x8000) { #ifdef CONFIG_PPP_FILTER @@ -1157,8 +1208,10 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) #endif /* CONFIG_PPP_FILTER */ } - ++ppp->dev->stats.tx_packets; - ppp->dev->stats.tx_bytes += skb->len - 2; + u64_stats_update_begin(&stats->syncp); + ++stats->tx_packets; + stats->tx_bytes += skb->len - 2; + u64_stats_update_end(&stats->syncp); switch (proto) { case PPP_IP: @@ -1673,6 +1726,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) { struct sk_buff *ns; int proto, len, npi; + struct ppp_link_stats *stats = this_cpu_ptr(ppp->stats); /* * Decompress the frame, if compressed. @@ -1745,8 +1799,10 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) break; } - ++ppp->dev->stats.rx_packets; - ppp->dev->stats.rx_bytes += skb->len - 2; + u64_stats_update_begin(&stats->syncp); + ++stats->rx_packets; + stats->rx_bytes += skb->len - 2; + u64_stats_update_end(&stats->syncp); npi = proto_to_npindex(proto); if (npi < 0) { @@ -2568,14 +2624,32 @@ 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->dev->stats.rx_packets; + + for_each_possible_cpu(cpu) { + struct ppp_link_stats *stats = per_cpu_ptr(ppp->stats, cpu); + unsigned int start; + u64 rx_packets, rx_bytes, tx_packets, tx_bytes; + + do { + start = u64_stats_fetch_begin_bh(&stats->syncp); + rx_packets = stats->rx_packets; + tx_packets = stats->tx_packets; + rx_bytes = stats->rx_bytes; + tx_bytes = stats->tx_bytes; + + } while (u64_stats_fetch_retry_bh(&stats->syncp, start)); + + st->p.ppp_ipackets += rx_packets; + st->p.ppp_opackets += tx_packets; + st->p.ppp_ibytes += rx_bytes; + st->p.ppp_obytes += tx_bytes; + } + st->p.ppp_ierrors = ppp->dev->stats.rx_errors; - st->p.ppp_ibytes = ppp->dev->stats.rx_bytes; - st->p.ppp_opackets = ppp->dev->stats.tx_packets; st->p.ppp_oerrors = ppp->dev->stats.tx_errors; - st->p.ppp_obytes = ppp->dev->stats.tx_bytes; if (!vj) return; st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed; @@ -2627,6 +2701,9 @@ ppp_create_interface(struct net *net, int unit, int *retp) ppp->minseq = -1; skb_queue_head_init(&ppp->mrq); #endif /* CONFIG_PPP_MULTILINK */ + ppp->stats = alloc_percpu(struct ppp_link_stats); + if (ppp->stats == NULL) + goto out2; /* * drum roll: don't forget to set @@ -2640,12 +2717,12 @@ ppp_create_interface(struct net *net, int unit, int *retp) unit = unit_get(&pn->units_idr, ppp); if (unit < 0) { ret = unit; - goto out2; + goto out3; } } else { ret = -EEXIST; if (unit_find(&pn->units_idr, unit)) - goto out2; /* unit already exists */ + goto out3; /* unit already exists */ /* * if caller need a specified unit number * lets try to satisfy him, otherwise -- @@ -2657,7 +2734,7 @@ ppp_create_interface(struct net *net, int unit, int *retp) */ unit = unit_set(&pn->units_idr, ppp, unit); if (unit < 0) - goto out2; + goto out3; } /* Initialize the new ppp unit */ @@ -2669,7 +2746,7 @@ ppp_create_interface(struct net *net, int unit, int *retp) unit_put(&pn->units_idr, unit); netdev_err(ppp->dev, "PPP: couldn't register device %s (%d)\n", dev->name, ret); - goto out2; + goto out3; } ppp->ppp_net = net; @@ -2680,8 +2757,10 @@ ppp_create_interface(struct net *net, int unit, int *retp) *retp = 0; return ppp; -out2: +out3: mutex_unlock(&pn->all_ppp_mutex); + free_percpu(ppp->stats); +out2: free_netdev(dev); out1: *retp = ret; @@ -2765,6 +2844,7 @@ static void ppp_destroy_interface(struct ppp *ppp) kfree_skb(ppp->xmit_pending); + free_percpu(ppp->stats); free_netdev(ppp->dev); } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists