vlan: 64 bit rx counters
authorEric Dumazet <eric.dumazet@gmail.com>
Thu, 24 Jun 2010 00:55:06 +0000 (00:55 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 29 Jun 2010 06:24:31 +0000 (23:24 -0700)
Use u64_stats_sync infrastructure to implement 64bit rx stats.

(tx stats are addressed later)

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Acked-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/8021q/vlan.h
net/8021q/vlan_core.c
net/8021q/vlan_dev.c

index 6abdcac1b2e81f1e59e3029569b719ea86c2c4db..8d9503ad01daa65729212de33f579b32aeffc1dc 100644 (file)
@@ -2,6 +2,7 @@
 #define __BEN_VLAN_802_1Q_INC__
 
 #include <linux/if_vlan.h>
+#include <linux/u64_stats_sync.h>
 
 
 /**
@@ -21,14 +22,16 @@ struct vlan_priority_tci_mapping {
  *     struct vlan_rx_stats - VLAN percpu rx stats
  *     @rx_packets: number of received packets
  *     @rx_bytes: number of received bytes
- *     @multicast: number of received multicast packets
+ *     @rx_multicast: number of received multicast packets
+ *     @syncp: synchronization point for 64bit counters
  *     @rx_errors: number of errors
  */
 struct vlan_rx_stats {
-       unsigned long rx_packets;
-       unsigned long rx_bytes;
-       unsigned long multicast;
-       unsigned long rx_errors;
+       u64                     rx_packets;
+       u64                     rx_bytes;
+       u64                     rx_multicast;
+       struct u64_stats_sync   syncp;
+       unsigned long           rx_errors;
 };
 
 /**
index 50f58f5f1c3491f775a5ac6c97ea32c5c5b23674..1b9406a31f0c3dde95df11f889c0aa514e0b72ca 100644 (file)
@@ -41,9 +41,9 @@ int vlan_hwaccel_do_receive(struct sk_buff *skb)
        skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
        skb->vlan_tci = 0;
 
-       rx_stats = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats,
-                              smp_processor_id());
+       rx_stats = this_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats);
 
+       u64_stats_update_begin(&rx_stats->syncp);
        rx_stats->rx_packets++;
        rx_stats->rx_bytes += skb->len;
 
@@ -51,7 +51,7 @@ int vlan_hwaccel_do_receive(struct sk_buff *skb)
        case PACKET_BROADCAST:
                break;
        case PACKET_MULTICAST:
-               rx_stats->multicast++;
+               rx_stats->rx_multicast++;
                break;
        case PACKET_OTHERHOST:
                /* Our lower layer thinks this is not local, let's make sure.
@@ -62,6 +62,7 @@ int vlan_hwaccel_do_receive(struct sk_buff *skb)
                        skb->pkt_type = PACKET_HOST;
                break;
        }
+       u64_stats_update_end(&rx_stats->syncp);
        return 0;
 }
 
index 52984267781782cd78aa0bd7bc3d38280745c1b1..c6456cb842faded41a5f94016c441c5b6c748f5a 100644 (file)
@@ -166,6 +166,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
 
        rx_stats = per_cpu_ptr(vlan_dev_info(skb->dev)->vlan_rx_stats,
                               smp_processor_id());
+       u64_stats_update_begin(&rx_stats->syncp);
        rx_stats->rx_packets++;
        rx_stats->rx_bytes += skb->len;
 
@@ -182,7 +183,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
                break;
 
        case PACKET_MULTICAST:
-               rx_stats->multicast++;
+               rx_stats->rx_multicast++;
                break;
 
        case PACKET_OTHERHOST:
@@ -197,6 +198,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
        default:
                break;
        }
+       u64_stats_update_end(&rx_stats->syncp);
 
        vlan_set_encap_proto(skb, vhdr);
 
@@ -801,27 +803,37 @@ static u32 vlan_ethtool_get_flags(struct net_device *dev)
        return dev_ethtool_get_flags(vlan->real_dev);
 }
 
-static struct net_device_stats *vlan_dev_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev)
 {
-       struct net_device_stats *stats = &dev->stats;
+       struct rtnl_link_stats64 *stats = &dev->stats64;
 
-       dev_txq_stats_fold(dev, stats);
+       dev_txq_stats_fold(dev, &dev->stats);
 
        if (vlan_dev_info(dev)->vlan_rx_stats) {
-               struct vlan_rx_stats *p, rx = {0};
+               struct vlan_rx_stats *p, accum = {0};
                int i;
 
                for_each_possible_cpu(i) {
+                       u64 rxpackets, rxbytes, rxmulticast;
+                       unsigned int start;
+
                        p = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats, i);
-                       rx.rx_packets += p->rx_packets;
-                       rx.rx_bytes   += p->rx_bytes;
-                       rx.rx_errors  += p->rx_errors;
-                       rx.multicast  += p->multicast;
+                       do {
+                               start = u64_stats_fetch_begin_bh(&p->syncp);
+                               rxpackets       = p->rx_packets;
+                               rxbytes         = p->rx_bytes;
+                               rxmulticast     = p->rx_multicast;
+                       } while (u64_stats_fetch_retry_bh(&p->syncp, start));
+                       accum.rx_packets += rxpackets;
+                       accum.rx_bytes   += rxbytes;
+                       accum.rx_multicast += rxmulticast;
+                       /* rx_errors is an ulong, not protected by syncp */
+                       accum.rx_errors  += p->rx_errors;
                }
-               stats->rx_packets = rx.rx_packets;
-               stats->rx_bytes   = rx.rx_bytes;
-               stats->rx_errors  = rx.rx_errors;
-               stats->multicast  = rx.multicast;
+               stats->rx_packets = accum.rx_packets;
+               stats->rx_bytes   = accum.rx_bytes;
+               stats->rx_errors  = accum.rx_errors;
+               stats->multicast  = accum.rx_multicast;
        }
        return stats;
 }
@@ -848,7 +860,7 @@ static const struct net_device_ops vlan_netdev_ops = {
        .ndo_change_rx_flags    = vlan_dev_change_rx_flags,
        .ndo_do_ioctl           = vlan_dev_ioctl,
        .ndo_neigh_setup        = vlan_dev_neigh_setup,
-       .ndo_get_stats          = vlan_dev_get_stats,
+       .ndo_get_stats64        = vlan_dev_get_stats64,
 #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
        .ndo_fcoe_ddp_setup     = vlan_dev_fcoe_ddp_setup,
        .ndo_fcoe_ddp_done      = vlan_dev_fcoe_ddp_done,
@@ -872,7 +884,7 @@ static const struct net_device_ops vlan_netdev_accel_ops = {
        .ndo_change_rx_flags    = vlan_dev_change_rx_flags,
        .ndo_do_ioctl           = vlan_dev_ioctl,
        .ndo_neigh_setup        = vlan_dev_neigh_setup,
-       .ndo_get_stats          = vlan_dev_get_stats,
+       .ndo_get_stats64        = vlan_dev_get_stats64,
 #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
        .ndo_fcoe_ddp_setup     = vlan_dev_fcoe_ddp_setup,
        .ndo_fcoe_ddp_done      = vlan_dev_fcoe_ddp_done,
@@ -897,7 +909,7 @@ static const struct net_device_ops vlan_netdev_ops_sq = {
        .ndo_change_rx_flags    = vlan_dev_change_rx_flags,
        .ndo_do_ioctl           = vlan_dev_ioctl,
        .ndo_neigh_setup        = vlan_dev_neigh_setup,
-       .ndo_get_stats          = vlan_dev_get_stats,
+       .ndo_get_stats64        = vlan_dev_get_stats64,
 #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
        .ndo_fcoe_ddp_setup     = vlan_dev_fcoe_ddp_setup,
        .ndo_fcoe_ddp_done      = vlan_dev_fcoe_ddp_done,
@@ -922,7 +934,7 @@ static const struct net_device_ops vlan_netdev_accel_ops_sq = {
        .ndo_change_rx_flags    = vlan_dev_change_rx_flags,
        .ndo_do_ioctl           = vlan_dev_ioctl,
        .ndo_neigh_setup        = vlan_dev_neigh_setup,
-       .ndo_get_stats          = vlan_dev_get_stats,
+       .ndo_get_stats64        = vlan_dev_get_stats64,
 #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
        .ndo_fcoe_ddp_setup     = vlan_dev_fcoe_ddp_setup,
        .ndo_fcoe_ddp_done      = vlan_dev_fcoe_ddp_done,