vport-netdev: Use vport stats layer on 32-bit machines.
authorJesse Gross <jesse@nicira.com>
Wed, 19 May 2010 22:22:28 +0000 (15:22 -0700)
committerJesse Gross <jesse@nicira.com>
Thu, 10 Jun 2010 21:30:30 +0000 (14:30 -0700)
Linux devices store stats in counters the size of a machine word,
which are rapidly overflowed on a 32-bit machine.  In this
situation we now use the vport stats layer, which always uses 64-
bit stats.  On 64-bit machines we continue to use the normal
Linux stats to avoid the extra overhead of counting twice.

datapath/vport-netdev.c

index 8e7847efda923f26959238d9d44db20f9e72e67d..72d2928d5f2e95156931e22e6e092bd9fba229dc 100644 (file)
@@ -22,6 +22,9 @@
 
 #include "compat.h"
 
+/* If the native device stats aren't 64 bit use the vport stats tracking instead. */
+#define USE_VPORT_STATS (sizeof(((struct net_device_stats *)0)->rx_bytes) < sizeof(u64))
+
 static void netdev_port_receive(struct net_bridge_port *, struct sk_buff *);
 
 /*
@@ -97,6 +100,16 @@ netdev_create(const char *name, const void __user *config)
                goto error_put;
        }
 
+       /* If we are using the vport stats layer initialize it to the current
+        * values so we are roughly consistent with the device stats. */
+       if (USE_VPORT_STATS) {
+               struct odp_vport_stats stats;
+
+               err = netdev_get_stats(vport, &stats);
+               if (!err)
+                       vport_set_stats(vport, &stats);
+       }
+
        return vport;
 
 error_put:
@@ -291,7 +304,8 @@ netdev_get_vport(struct net_device *dev)
 
 struct vport_ops netdev_vport_ops = {
        .type           = "netdev",
-       .flags          = VPORT_F_REQUIRED,
+       .flags          = (VPORT_F_REQUIRED |
+                         (USE_VPORT_STATS ? VPORT_F_GEN_STATS : 0)),
        .init           = netdev_init,
        .exit           = netdev_exit,
        .create         = netdev_create,