datapath: Always use generic stats for devices (vports)
authorPravin Shelar <pshelar@nicira.com>
Fri, 16 Sep 2011 02:36:17 +0000 (19:36 -0700)
committerPravin Shelar <pshelar@nicira.com>
Fri, 16 Sep 2011 02:36:17 +0000 (19:36 -0700)
    Currently ovs is using device stats for Linux devices and count them
itself in other situations. This leads to overlap with hardware stats,
inconsistencies, etc. It's much better to just always count the packets
flowing through the switch and let userspace do any merging that it wants.

Following patch removes vport->get_stats() interface. vport-stat is changed
to use new `struct ovs_vport_stat` rather than rtnl_link_stats64.
Definitions of rtnl_link_stats64 is removed from OVS.  dipf_port->stat is also
removed as aggregate stats are only available at netdev layer.

Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
26 files changed:
acinclude.m4
configure.ac
datapath/datapath.c
datapath/linux/compat/include/linux/netdevice.h
datapath/linux/compat/netdevice.c
datapath/vport-capwap.c
datapath/vport-gre.c
datapath/vport-internal_dev.c
datapath/vport-netdev.c
datapath/vport-netdev.h
datapath/vport-patch.c
datapath/vport.c
datapath/vport.h
include/automake.mk
include/linux/automake.mk [deleted file]
include/linux/if_link.h [deleted file]
include/openvswitch/datapath-protocol.h
lib/dpif-linux.c
lib/dpif-linux.h
lib/dpif.c
lib/dpif.h
lib/netdev-linux.c
lib/netdev-linux.h
lib/netdev-vport.c
m4/openvswitch.m4
utilities/ovs-dpctl.c

index b3794893a36d39c9b50aed97ecd7a60751d55f9a..648132a2a5b4bce308ad7a59a47d00d5acaf1fb3 100644 (file)
@@ -254,8 +254,6 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
   OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_get_be16])
   OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_find_nested])
 
-  OVS_GREP_IFELSE([$KSRC/include/linux/if_link.h], [rtnl_link_stats64])
-
   OVS_GREP_IFELSE([$KSRC/include/linux/if_vlan.h], [ADD_ALL_VLANS_CMD],
                   [OVS_DEFINE([HAVE_VLAN_BUG_WORKAROUND])])
 
index e03946aa378a5424f53dacaf3c7881d5ba5d874d..7387d8264b87dd55f6cf39c0edd533664aa28961 100644 (file)
@@ -47,7 +47,6 @@ OVS_CHECK_NDEBUG
 OVS_CHECK_NETLINK
 OVS_CHECK_OPENSSL
 OVS_CHECK_LOGDIR
-OVS_CHECK_RTNL_LINK_STATS64
 OVS_CHECK_PYTHON
 OVS_CHECK_PYUIC4
 OVS_CHECK_OVSDBMONITOR
index 0238c5f3b32c5167e8b347ef46b976a168782d5d..98c2bafd306634e6eb2d7e34163f2afb0d31f5fa 100644 (file)
@@ -1504,10 +1504,10 @@ static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
        [OVS_VPORT_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
        [OVS_VPORT_ATTR_PORT_NO] = { .type = NLA_U32 },
        [OVS_VPORT_ATTR_TYPE] = { .type = NLA_U32 },
-       [OVS_VPORT_ATTR_STATS] = { .len = sizeof(struct rtnl_link_stats64) },
+       [OVS_VPORT_ATTR_STATS] = { .len = sizeof(struct ovs_vport_stats) },
        [OVS_VPORT_ATTR_ADDRESS] = { .len = ETH_ALEN },
 #else
-       [OVS_VPORT_ATTR_STATS] = { .minlen = sizeof(struct rtnl_link_stats64) },
+       [OVS_VPORT_ATTR_STATS] = { .minlen = sizeof(struct ovs_vport_stats) },
        [OVS_VPORT_ATTR_ADDRESS] = { .minlen = ETH_ALEN },
 #endif
        [OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
@@ -1545,11 +1545,11 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
        NLA_PUT_U32(skb, OVS_VPORT_ATTR_TYPE, vport_get_type(vport));
        NLA_PUT_STRING(skb, OVS_VPORT_ATTR_NAME, vport_get_name(vport));
 
-       nla = nla_reserve(skb, OVS_VPORT_ATTR_STATS, sizeof(struct rtnl_link_stats64));
+       nla = nla_reserve(skb, OVS_VPORT_ATTR_STATS, sizeof(struct ovs_vport_stats));
        if (!nla)
                goto nla_put_failure;
-       if (vport_get_stats(vport, nla_data(nla)))
-               __skb_trim(skb, skb->len - nla->nla_len);
+
+       vport_get_stats(vport, nla_data(nla));
 
        NLA_PUT(skb, OVS_VPORT_ATTR_ADDRESS, ETH_ALEN, vport_get_addr(vport));
 
@@ -1628,10 +1628,13 @@ static struct vport *lookup_vport(struct ovs_header *ovs_header,
 static int change_vport(struct vport *vport, struct nlattr *a[OVS_VPORT_ATTR_MAX + 1])
 {
        int err = 0;
+
        if (a[OVS_VPORT_ATTR_STATS])
-               err = vport_set_stats(vport, nla_data(a[OVS_VPORT_ATTR_STATS]));
-       if (!err && a[OVS_VPORT_ATTR_ADDRESS])
+               vport_set_stats(vport, nla_data(a[OVS_VPORT_ATTR_STATS]));
+
+       if (a[OVS_VPORT_ATTR_ADDRESS])
                err = vport_set_addr(vport, nla_data(a[OVS_VPORT_ATTR_ADDRESS]));
+
        return err;
 }
 
index 1ac3831287a55c21d4f0ba6d412d75b837dead38..8d24cd969c809b2df69c1eb1dd70efb93f9f65ea 100644 (file)
@@ -77,19 +77,6 @@ extern void unregister_netdevice_many(struct list_head *head);
 extern void dev_disable_lro(struct net_device *dev);
 #endif
 
-/* Linux 2.6.28 introduced dev_get_stats():
- * const struct net_device_stats *dev_get_stats(struct net_device *dev);
- *
- * Linux 2.6.36 changed dev_get_stats() to:
- * struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
- *                                         struct rtnl_link_stats64 *storage);
- */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
-#define dev_get_stats(dev, storage) rpl_dev_get_stats(dev, storage)
-struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
-                                       struct rtnl_link_stats64 *storage);
-#endif
-
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
 #define skb_checksum_help(skb) skb_checksum_help((skb), 0)
 #endif
index 91855c47a665fd659bd562e00ce9125470a67469..9e92eeb8d9191537d77d66c7c1d7b8fda872c512 100644 (file)
@@ -1,54 +1,6 @@
-#include <linux/if_link.h>
 #include <linux/netdevice.h>
 #include <linux/if_vlan.h>
 
-/* Linux 2.6.28 introduced dev_get_stats():
- * const struct net_device_stats *dev_get_stats(struct net_device *dev);
- *
- * Linux 2.6.36 changed dev_get_stats() to:
- * struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
- *                                         struct rtnl_link_stats64 *storage);
- */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
-struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
-                                       struct rtnl_link_stats64 *storage)
-{
-       const struct net_device_stats *stats;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
-       stats = dev->get_stats(dev);
-#else  /* 2.6.28 < kernel version < 2.6.36 */
-       stats = (dev_get_stats)(dev);
-#endif /* 2.6.28 < kernel version < 2.6.36 */
-
-       storage->rx_packets = stats->rx_packets;
-       storage->tx_packets = stats->tx_packets;
-       storage->rx_bytes = stats->rx_bytes;
-       storage->tx_bytes = stats->tx_bytes;
-       storage->rx_errors = stats->rx_errors;
-       storage->tx_errors = stats->tx_errors;
-       storage->rx_dropped = stats->rx_dropped;
-       storage->tx_dropped = stats->tx_dropped;
-       storage->multicast = stats->multicast;
-       storage->collisions = stats->collisions;
-       storage->rx_length_errors = stats->rx_length_errors;
-       storage->rx_over_errors = stats->rx_over_errors;
-       storage->rx_crc_errors = stats->rx_crc_errors;
-       storage->rx_frame_errors = stats->rx_frame_errors;
-       storage->rx_fifo_errors = stats->rx_fifo_errors;
-       storage->rx_missed_errors = stats->rx_missed_errors;
-       storage->tx_aborted_errors = stats->tx_aborted_errors;
-       storage->tx_carrier_errors = stats->tx_carrier_errors;
-       storage->tx_fifo_errors = stats->tx_fifo_errors;
-       storage->tx_heartbeat_errors = stats->tx_heartbeat_errors;
-       storage->tx_window_errors = stats->tx_window_errors;
-       storage->rx_compressed = stats->rx_compressed;
-       storage->tx_compressed = stats->tx_compressed;
-
-       return storage;
-}
-#endif /* kernel version < 2.6.36 */
-
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
 static bool can_checksum_protocol(unsigned long features, __be16 protocol)
 {
index 68a168b6e7cc83f9f9430346234715c9289a8f24..76db8a737e219188bcb5e23a6db15a83598a29c6 100644 (file)
@@ -788,7 +788,7 @@ static void capwap_frag_expire(unsigned long ifq)
 
 const struct vport_ops capwap_vport_ops = {
        .type           = OVS_VPORT_TYPE_CAPWAP,
-       .flags          = VPORT_F_GEN_STATS | VPORT_F_TUN_ID,
+       .flags          = VPORT_F_TUN_ID,
        .init           = capwap_init,
        .exit           = capwap_exit,
        .create         = capwap_create,
index 24c53f89680d4b46ee85f180fe8d197e692b3c88..5beae42eded3ed680c4c740fe6f9bd31ed479965 100644 (file)
@@ -389,7 +389,7 @@ static void gre_exit(void)
 
 const struct vport_ops gre_vport_ops = {
        .type           = OVS_VPORT_TYPE_GRE,
-       .flags          = VPORT_F_GEN_STATS | VPORT_F_TUN_ID,
+       .flags          = VPORT_F_TUN_ID,
        .init           = gre_init,
        .exit           = gre_exit,
        .create         = gre_create,
index 04f51eb330186ba8c90b5e41be2e1248d7a3a558..ecfb37933cf4a8a3c86d468c0304cf509ec865d7 100644 (file)
@@ -32,16 +32,14 @@ static inline struct internal_dev *internal_dev_priv(struct net_device *netdev)
        return netdev_priv(netdev);
 }
 
-/* This function is only called by the kernel network layer.  It is not a vport
- * get_stats() function.  If a vport get_stats() function is defined that
- * results in this being called it will cause infinite recursion. */
+/* This function is only called by the kernel network layer.*/
 static struct net_device_stats *internal_dev_sys_stats(struct net_device *netdev)
 {
        struct vport *vport = internal_dev_get_vport(netdev);
        struct net_device_stats *stats = &internal_dev_priv(netdev)->stats;
 
        if (vport) {
-               struct rtnl_link_stats64 vport_stats;
+               struct ovs_vport_stats vport_stats;
 
                vport_get_stats(vport, &vport_stats);
 
@@ -55,7 +53,6 @@ static struct net_device_stats *internal_dev_sys_stats(struct net_device *netdev
                stats->tx_errors        = vport_stats.rx_errors;
                stats->rx_dropped       = vport_stats.tx_dropped;
                stats->tx_dropped       = vport_stats.rx_dropped;
-               stats->collisions       = vport_stats.collisions;
        }
 
        return stats;
@@ -266,7 +263,7 @@ static int internal_dev_recv(struct vport *vport, struct sk_buff *skb)
 
 const struct vport_ops internal_vport_ops = {
        .type           = OVS_VPORT_TYPE_INTERNAL,
-       .flags          = VPORT_F_REQUIRED | VPORT_F_GEN_STATS | VPORT_F_FLOW,
+       .flags          = VPORT_F_REQUIRED | VPORT_F_FLOW,
        .create         = internal_dev_create,
        .destroy        = internal_dev_destroy,
        .set_addr       = netdev_set_addr,
index 7cd6c6b3b79ceb103c188ba951b9a79378776f8b..4c7f1cb43692354d66cc863f1491026b2d9fa167 100644 (file)
@@ -35,9 +35,6 @@ MODULE_PARM_DESC(vlan_tso, "Enable TSO for VLAN packets");
 #define vlan_tso true
 #endif
 
-/* 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 vport *vport, struct sk_buff *skb);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
@@ -144,16 +141,6 @@ static struct vport *netdev_create(const struct vport_parms *parms)
                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 rtnl_link_stats64 stats;
-
-               err = netdev_get_stats(vport, &stats);
-               if (!err)
-                       vport_set_stats(vport, &stats);
-       }
-
        err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook,
                                         vport);
        if (err)
@@ -218,13 +205,6 @@ struct kobject *netdev_get_kobj(const struct vport *vport)
        return &netdev_vport->dev->NETDEV_DEV_MEMBER.kobj;
 }
 
-int netdev_get_stats(const struct vport *vport, struct rtnl_link_stats64 *stats)
-{
-       const struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
-       dev_get_stats(netdev_vport->dev, stats);
-       return 0;
-}
-
 unsigned netdev_get_dev_flags(const struct vport *vport)
 {
        const struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
@@ -410,8 +390,7 @@ struct vport *netdev_get_vport(struct net_device *dev)
 
 const struct vport_ops netdev_vport_ops = {
        .type           = OVS_VPORT_TYPE_NETDEV,
-       .flags          = (VPORT_F_REQUIRED |
-                         (USE_VPORT_STATS ? VPORT_F_GEN_STATS : 0)),
+       .flags          = VPORT_F_REQUIRED,
        .init           = netdev_init,
        .exit           = netdev_exit,
        .create         = netdev_create,
@@ -420,7 +399,6 @@ const struct vport_ops netdev_vport_ops = {
        .get_name       = netdev_get_name,
        .get_addr       = netdev_get_addr,
        .get_kobj       = netdev_get_kobj,
-       .get_stats      = netdev_get_stats,
        .get_dev_flags  = netdev_get_dev_flags,
        .is_running     = netdev_is_running,
        .get_operstate  = netdev_get_operstate,
index 7a743d24b30189588f6c95ef84cac2ee2417c742..9b138be35e34b36763659934937f22851379c2fc 100644 (file)
@@ -30,7 +30,6 @@ const char *netdev_get_name(const struct vport *);
 const unsigned char *netdev_get_addr(const struct vport *);
 const char *netdev_get_config(const struct vport *);
 struct kobject *netdev_get_kobj(const struct vport *);
-int netdev_get_stats(const struct vport *, struct rtnl_link_stats64 *);
 unsigned netdev_get_dev_flags(const struct vport *);
 int netdev_is_running(const struct vport *);
 unsigned char netdev_get_operstate(const struct vport *);
index 1ec3a4c96b98c59657483e64bb76d90bad121318..9554f1214e914089ae659abf56cdad97bc0254d2 100644 (file)
@@ -287,7 +287,6 @@ static int patch_send(struct vport *vport, struct sk_buff *skb)
 
 const struct vport_ops patch_vport_ops = {
        .type           = OVS_VPORT_TYPE_PATCH,
-       .flags          = VPORT_F_GEN_STATS,
        .init           = patch_init,
        .exit           = patch_exit,
        .create         = patch_create,
index ca802b4b28e02fa372e7c706caf0614a9b8ca98e..71fdd841159584137799b9b574c7cc2127b069f9 100644 (file)
@@ -184,13 +184,11 @@ struct vport *vport_alloc(int priv_size, const struct vport_ops *ops, const stru
        vport->kobj.kset = NULL;
        kobject_init(&vport->kobj, &brport_ktype);
 
-       if (vport->ops->flags & VPORT_F_GEN_STATS) {
-               vport->percpu_stats = alloc_percpu(struct vport_percpu_stats);
-               if (!vport->percpu_stats)
-                       return ERR_PTR(-ENOMEM);
+       vport->percpu_stats = alloc_percpu(struct vport_percpu_stats);
+       if (!vport->percpu_stats)
+               return ERR_PTR(-ENOMEM);
 
-               spin_lock_init(&vport->stats_lock);
-       }
+       spin_lock_init(&vport->stats_lock);
 
        return vport;
 }
@@ -207,8 +205,7 @@ struct vport *vport_alloc(int priv_size, const struct vport_ops *ops, const stru
  */
 void vport_free(struct vport *vport)
 {
-       if (vport->ops->flags & VPORT_F_GEN_STATS)
-               free_percpu(vport->percpu_stats);
+       free_percpu(vport->percpu_stats);
 
        kobject_put(&vport->kobj);
 }
@@ -320,18 +317,13 @@ int vport_set_addr(struct vport *vport, const unsigned char *addr)
  *
  * Must be called with RTNL lock.
  */
-int vport_set_stats(struct vport *vport, struct rtnl_link_stats64 *stats)
+void vport_set_stats(struct vport *vport, struct ovs_vport_stats *stats)
 {
        ASSERT_RTNL();
 
-       if (vport->ops->flags & VPORT_F_GEN_STATS) {
-               spin_lock_bh(&vport->stats_lock);
-               vport->offset_stats = *stats;
-               spin_unlock_bh(&vport->stats_lock);
-
-               return 0;
-       } else
-               return -EOPNOTSUPP;
+       spin_lock_bh(&vport->stats_lock);
+       vport->offset_stats = *stats;
+       spin_unlock_bh(&vport->stats_lock);
 }
 
 /**
@@ -389,17 +381,6 @@ struct kobject *vport_get_kobj(const struct vport *vport)
                return NULL;
 }
 
-static int vport_call_get_stats(struct vport *vport, struct rtnl_link_stats64 *stats)
-{
-       int err;
-
-       rcu_read_lock();
-       err = vport->ops->get_stats(vport, stats);
-       rcu_read_unlock();
-
-       return err;
-}
-
 /**
  *     vport_get_stats - retrieve device stats
  *
@@ -410,19 +391,20 @@ static int vport_call_get_stats(struct vport *vport, struct rtnl_link_stats64 *s
  *
  * Must be called with RTNL lock or rcu_read_lock.
  */
-int vport_get_stats(struct vport *vport, struct rtnl_link_stats64 *stats)
+void vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
 {
        int i;
 
-       if (!(vport->ops->flags & VPORT_F_GEN_STATS))
-               return vport_call_get_stats(vport, stats);
-
        /* We potentially have 3 sources of stats that need to be
         * combined: those we have collected (split into err_stats and
         * percpu_stats), offset_stats from set_stats(), and device
-        * error stats from get_stats() (for errors that happen
+        * error stats from netdev->get_stats() (for errors that happen
         * downstream and therefore aren't reported through our
-        * vport_record_error() function). */
+        * vport_record_error() function).
+        * Stats from first two sources are merged and reported by ovs over
+        * OVS_VPORT_ATTR_STATS.
+        * netdev-stats can be directly read over netlink-ioctl.
+        */
 
        spin_lock_bh(&vport->stats_lock);
 
@@ -435,35 +417,6 @@ int vport_get_stats(struct vport *vport, struct rtnl_link_stats64 *stats)
 
        spin_unlock_bh(&vport->stats_lock);
 
-       if (vport->ops->get_stats) {
-               struct rtnl_link_stats64 dev_stats;
-               int err;
-
-               err = vport_call_get_stats(vport, &dev_stats);
-               if (err)
-                       return err;
-
-               stats->rx_errors           += dev_stats.rx_errors;
-               stats->tx_errors           += dev_stats.tx_errors;
-               stats->rx_dropped          += dev_stats.rx_dropped;
-               stats->tx_dropped          += dev_stats.tx_dropped;
-               stats->multicast           += dev_stats.multicast;
-               stats->collisions          += dev_stats.collisions;
-               stats->rx_length_errors    += dev_stats.rx_length_errors;
-               stats->rx_over_errors      += dev_stats.rx_over_errors;
-               stats->rx_crc_errors       += dev_stats.rx_crc_errors;
-               stats->rx_frame_errors     += dev_stats.rx_frame_errors;
-               stats->rx_fifo_errors      += dev_stats.rx_fifo_errors;
-               stats->rx_missed_errors    += dev_stats.rx_missed_errors;
-               stats->tx_aborted_errors   += dev_stats.tx_aborted_errors;
-               stats->tx_carrier_errors   += dev_stats.tx_carrier_errors;
-               stats->tx_fifo_errors      += dev_stats.tx_fifo_errors;
-               stats->tx_heartbeat_errors += dev_stats.tx_heartbeat_errors;
-               stats->tx_window_errors    += dev_stats.tx_window_errors;
-               stats->rx_compressed       += dev_stats.rx_compressed;
-               stats->tx_compressed       += dev_stats.tx_compressed;
-       }
-
        for_each_possible_cpu(i) {
                const struct vport_percpu_stats *percpu_stats;
                struct vport_percpu_stats local_stats;
@@ -481,8 +434,6 @@ int vport_get_stats(struct vport *vport, struct rtnl_link_stats64 *stats)
                stats->tx_bytes         += local_stats.tx_bytes;
                stats->tx_packets       += local_stats.tx_packets;
        }
-
-       return 0;
 }
 
 /**
@@ -610,19 +561,17 @@ int vport_get_options(const struct vport *vport, struct sk_buff *skb)
  */
 void vport_receive(struct vport *vport, struct sk_buff *skb)
 {
-       if (vport->ops->flags & VPORT_F_GEN_STATS) {
-               struct vport_percpu_stats *stats;
+       struct vport_percpu_stats *stats;
 
-               local_bh_disable();
-               stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
+       local_bh_disable();
+       stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
 
-               write_seqcount_begin(&stats->seqlock);
-               stats->rx_packets++;
-               stats->rx_bytes += skb->len;
-               write_seqcount_end(&stats->seqlock);
+       write_seqcount_begin(&stats->seqlock);
+       stats->rx_packets++;
+       stats->rx_bytes += skb->len;
+       write_seqcount_end(&stats->seqlock);
 
-               local_bh_enable();
-       }
+       local_bh_enable();
 
        if (!(vport->ops->flags & VPORT_F_FLOW))
                OVS_CB(skb)->flow = NULL;
@@ -644,21 +593,18 @@ void vport_receive(struct vport *vport, struct sk_buff *skb)
  */
 int vport_send(struct vport *vport, struct sk_buff *skb)
 {
+       struct vport_percpu_stats *stats;
        int sent = vport->ops->send(vport, skb);
 
-       if (vport->ops->flags & VPORT_F_GEN_STATS && sent > 0) {
-               struct vport_percpu_stats *stats;
-
-               local_bh_disable();
-               stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
+       local_bh_disable();
+       stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
 
-               write_seqcount_begin(&stats->seqlock);
-               stats->tx_packets++;
-               stats->tx_bytes += sent;
-               write_seqcount_end(&stats->seqlock);
+       write_seqcount_begin(&stats->seqlock);
+       stats->tx_packets++;
+       stats->tx_bytes += sent;
+       write_seqcount_end(&stats->seqlock);
 
-               local_bh_enable();
-       }
+       local_bh_enable();
 
        return sent;
 }
@@ -674,28 +620,25 @@ int vport_send(struct vport *vport, struct sk_buff *skb)
  */
 void vport_record_error(struct vport *vport, enum vport_err_type err_type)
 {
-       if (vport->ops->flags & VPORT_F_GEN_STATS) {
-
-               spin_lock_bh(&vport->stats_lock);
+       spin_lock_bh(&vport->stats_lock);
 
-               switch (err_type) {
-               case VPORT_E_RX_DROPPED:
-                       vport->err_stats.rx_dropped++;
-                       break;
+       switch (err_type) {
+       case VPORT_E_RX_DROPPED:
+               vport->err_stats.rx_dropped++;
+               break;
 
-               case VPORT_E_RX_ERROR:
-                       vport->err_stats.rx_errors++;
-                       break;
+       case VPORT_E_RX_ERROR:
+               vport->err_stats.rx_errors++;
+               break;
 
-               case VPORT_E_TX_DROPPED:
-                       vport->err_stats.tx_dropped++;
-                       break;
+       case VPORT_E_TX_DROPPED:
+               vport->err_stats.tx_dropped++;
+               break;
 
-               case VPORT_E_TX_ERROR:
-                       vport->err_stats.tx_errors++;
-                       break;
-               };
+       case VPORT_E_TX_ERROR:
+               vport->err_stats.tx_errors++;
+               break;
+       };
 
-               spin_unlock_bh(&vport->stats_lock);
-       }
+       spin_unlock_bh(&vport->stats_lock);
 }
index 6c4da24fb19133ebfc1975d7bdadb963ae7f4cae..e7d2eb5cb46847f7b3ad340e9d66ee9251ca893f 100644 (file)
@@ -31,14 +31,14 @@ void vport_del(struct vport *);
 struct vport *vport_locate(const char *name);
 
 int vport_set_addr(struct vport *, const unsigned char *);
-int vport_set_stats(struct vport *, struct rtnl_link_stats64 *);
+void vport_set_stats(struct vport *, struct ovs_vport_stats *);
 
 const char *vport_get_name(const struct vport *);
 enum ovs_vport_type vport_get_type(const struct vport *);
 const unsigned char *vport_get_addr(const struct vport *);
 
 struct kobject *vport_get_kobj(const struct vport *);
-int vport_get_stats(struct vport *, struct rtnl_link_stats64 *);
+void vport_get_stats(struct vport *, struct ovs_vport_stats *);
 
 unsigned vport_get_flags(const struct vport *);
 int vport_is_running(const struct vport *);
@@ -84,11 +84,9 @@ struct vport_err_stats {
  * regardless of whether they were actually chosen and sent down to userspace.
  * @hash_node: Element in @dev_table hash table in vport.c.
  * @ops: Class structure.
- * @percpu_stats: Points to per-CPU statistics used and maintained by the vport
- * code if %VPORT_F_GEN_STATS is set to 1 in @ops flags, otherwise unused.
+ * @percpu_stats: Points to per-CPU statistics used and maintained by vport
  * @stats_lock: Protects @err_stats and @offset_stats.
- * @err_stats: Points to error statistics used and maintained by the vport code
- * if %VPORT_F_GEN_STATS is set to 1 in @ops flags, otherwise unused.
+ * @err_stats: Points to error statistics used and maintained by vport
  * @offset_stats: Added to actual statistics as a sop to compatibility with
  * XAPI for Citrix XenServer.  Deprecated.
  */
@@ -108,13 +106,12 @@ struct vport {
 
        spinlock_t stats_lock;
        struct vport_err_stats err_stats;
-       struct rtnl_link_stats64 offset_stats;
+       struct ovs_vport_stats offset_stats;
 };
 
 #define VPORT_F_REQUIRED       (1 << 0) /* If init fails, module loading fails. */
-#define VPORT_F_GEN_STATS      (1 << 1) /* Track stats at the generic layer. */
-#define VPORT_F_FLOW           (1 << 2) /* Sets OVS_CB(skb)->flow. */
-#define VPORT_F_TUN_ID         (1 << 3) /* Sets OVS_CB(skb)->tun_id. */
+#define VPORT_F_FLOW           (1 << 1) /* Sets OVS_CB(skb)->flow. */
+#define VPORT_F_TUN_ID         (1 << 2) /* Sets OVS_CB(skb)->tun_id. */
 
 /**
  * struct vport_parms - parameters for creating a new vport
@@ -160,10 +157,6 @@ struct vport_parms {
  * @get_addr: Get the device's MAC address.
  * @get_config: Get the device's configuration.
  * @get_kobj: Get the kobj associated with the device (may return null).
- * @get_stats: Fill in the transmit/receive stats.  May be null if stats are
- * not supported or if generic stats are in use.  If defined and
- * VPORT_F_GEN_STATS is also set, the error stats are added to those already
- * collected.
  * @get_dev_flags: Get the device's flags.
  * @is_running: Checks whether the device is running.
  * @get_operstate: Get the device's operating state.
@@ -195,7 +188,6 @@ struct vport_ops {
        const unsigned char *(*get_addr)(const struct vport *);
        void (*get_config)(const struct vport *, void *);
        struct kobject *(*get_kobj)(const struct vport *);
-       int (*get_stats)(const struct vport *, struct rtnl_link_stats64 *);
 
        unsigned (*get_dev_flags)(const struct vport *);
        int (*is_running)(const struct vport *);
index f34e5c9bf8d4db21f2df9173b9a8743f20a2c313..9ec5b72ed4c415f002781bfd575f7a78dddf836c 100644 (file)
@@ -1,4 +1,3 @@
-include include/linux/automake.mk
 include include/openflow/automake.mk
 include include/openvswitch/automake.mk
 include include/sparse/automake.mk
diff --git a/include/linux/automake.mk b/include/linux/automake.mk
deleted file mode 100644 (file)
index a0a963d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-noinst_HEADERS += \
-       include/linux/if_link.h
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
deleted file mode 100644 (file)
index 55d99e4..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef __LINUX_IF_LINK_WRAPPER_H
-#define __LINUX_IF_LINK_WRAPPER_H 1
-
-#include <linux/version.h>
-
-#ifdef HAVE_RTNL_LINK_STATS64
-#include_next <linux/if_link.h>
-#else  /* !HAVE_RTNL_LINK_STATS64 */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
-#include_next <linux/if_link.h>
-#else
-/* Before 2.6.19 there was no <linux/if_link.h>.  Instead all of the types now
- * declared there were in <linux/if.h>.  Unfortunately <linux/if.h> from 2.6.18
- * conflicts badly enough with <net/if.h> to break the userspace build.  All
- * we really need from <linux/if_link.h> is struct rtnl_link_stats64, which in
- * turn only really needs __u64.  */
-#include <linux/types.h>
-#include <linux/netlink.h>
-#endif /* kernel < 2.6.19 */
-
-/* The main device statistics structure */
-struct rtnl_link_stats64 {
-       __u64   rx_packets;             /* total packets received       */
-       __u64   tx_packets;             /* total packets transmitted    */
-       __u64   rx_bytes;               /* total bytes received         */
-       __u64   tx_bytes;               /* total bytes transmitted      */
-       __u64   rx_errors;              /* bad packets received         */
-       __u64   tx_errors;              /* packet transmit problems     */
-       __u64   rx_dropped;             /* no space in linux buffers    */
-       __u64   tx_dropped;             /* no space available in linux  */
-       __u64   multicast;              /* multicast packets received   */
-       __u64   collisions;
-
-       /* detailed rx_errors: */
-       __u64   rx_length_errors;
-       __u64   rx_over_errors;         /* receiver ring buff overflow  */
-       __u64   rx_crc_errors;          /* recved pkt with crc error    */
-       __u64   rx_frame_errors;        /* recv'd frame alignment error */
-       __u64   rx_fifo_errors;         /* recv'r fifo overrun          */
-       __u64   rx_missed_errors;       /* receiver missed packet       */
-
-       /* detailed tx_errors */
-       __u64   tx_aborted_errors;
-       __u64   tx_carrier_errors;
-       __u64   tx_fifo_errors;
-       __u64   tx_heartbeat_errors;
-       __u64   tx_window_errors;
-
-       /* for cslip etc */
-       __u64   rx_compressed;
-       __u64   tx_compressed;
-};
-#endif /* !HAVE_RTNL_LINK_STATS64 */
-
-#endif
index 5687792dff708408048e2afcc70c38d04ddaff7f..8ed1c7f413a554b5d42a912669bb571eef52ab81 100644 (file)
@@ -51,7 +51,6 @@
 #include <sys/socket.h>
 #endif
 
-#include <linux/if_link.h>
 #include <linux/netlink.h>
 \f
 /* datapaths. */
@@ -136,6 +135,17 @@ struct ovs_dp_stats {
     uint64_t n_flows;           /* Number of flows present */
 };
 
+struct ovs_vport_stats {
+       uint64_t   rx_packets;          /* total packets received       */
+       uint64_t   tx_packets;          /* total packets transmitted    */
+       uint64_t   rx_bytes;            /* total bytes received         */
+       uint64_t   tx_bytes;            /* total bytes transmitted      */
+       uint64_t   rx_errors;           /* bad packets received         */
+       uint64_t   tx_errors;           /* packet transmit problems     */
+       uint64_t   rx_dropped;          /* no space in linux buffers    */
+       int64_t   tx_dropped;           /* no space available in linux  */
+};
+
 /* Logical ports. */
 #define OVSP_LOCAL      ((uint16_t)0)
 \f
@@ -219,7 +229,7 @@ enum ovs_vport_cmd {
  * @OVS_VPORT_ATTR_NAME: Name of vport.  For a vport based on a network device
  * this is the name of the network device.  Maximum length %IFNAMSIZ-1 bytes
  * plus a null terminator.
- * @OVS_VPORT_ATTR_STATS: A &struct rtnl_link_stats64 giving statistics for
+ * @OVS_VPORT_ATTR_STATS: A &struct ovs_vport_stats giving statistics for
  * packets sent or received through the vport.
  * @OVS_VPORT_ATTR_ADDRESS: A 6-byte Ethernet address for the vport.
  * @OVS_VPORT_ATTR_IFINDEX: ifindex of the underlying network device, if any.
@@ -247,7 +257,7 @@ enum ovs_vport_attr {
        OVS_VPORT_ATTR_PORT_NO, /* port number within datapath */
        OVS_VPORT_ATTR_TYPE,    /* 32-bit OVS_VPORT_TYPE_* constant. */
        OVS_VPORT_ATTR_NAME,    /* string name, up to IFNAMSIZ bytes long */
-       OVS_VPORT_ATTR_STATS,   /* struct rtnl_link_stats64 */
+       OVS_VPORT_ATTR_STATS,   /* struct ovs_vport_stats */
        OVS_VPORT_ATTR_ADDRESS, /* hardware address */
        OVS_VPORT_ATTR_OPTIONS, /* nested attributes, varies by vport type */
        OVS_VPORT_ATTR_IFINDEX, /* 32-bit ifindex of backing netdev */
index 9533e1489a83aadd84f36eb77e6c3811ec9ab340..3d081aab50a67aee5ef1899dd98bdbf3d7a955d1 100644 (file)
@@ -463,12 +463,6 @@ dpif_linux_port_query__(const struct dpif *dpif, uint32_t port_no,
         dpif_port->name = xstrdup(reply.name);
         dpif_port->type = xstrdup(netdev_vport_get_netdev_type(&reply));
         dpif_port->port_no = reply.port_no;
-        if (reply.stats) {
-            netdev_stats_from_rtnl_link_stats64(&dpif_port->stats,
-                                                reply.stats);
-        } else {
-            memset(&dpif_port->stats, 0xff, sizeof dpif_port->stats);
-        }
         ofpbuf_delete(buf);
     }
     return error;
@@ -564,11 +558,6 @@ dpif_linux_port_dump_next(const struct dpif *dpif OVS_UNUSED, void *state_,
     dpif_port->name = (char *) vport.name;
     dpif_port->type = (char *) netdev_vport_get_netdev_type(&vport);
     dpif_port->port_no = vport.port_no;
-    if (vport.stats) {
-        netdev_stats_from_rtnl_link_stats64(&dpif_port->stats, vport.stats);
-    } else {
-        memset(&dpif_port->stats, 0xff, sizeof dpif_port->stats);
-    }
     return 0;
 }
 
@@ -1231,8 +1220,8 @@ dpif_linux_vport_from_ofpbuf(struct dpif_linux_vport *vport,
         [OVS_VPORT_ATTR_TYPE] = { .type = NL_A_U32 },
         [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .max_len = IFNAMSIZ },
         [OVS_VPORT_ATTR_STATS] = { .type = NL_A_UNSPEC,
-                                   .min_len = sizeof(struct rtnl_link_stats64),
-                                   .max_len = sizeof(struct rtnl_link_stats64),
+                                   .min_len = sizeof(struct ovs_vport_stats),
+                                   .max_len = sizeof(struct ovs_vport_stats),
                                    .optional = true },
         [OVS_VPORT_ATTR_ADDRESS] = { .type = NL_A_UNSPEC,
                                      .min_len = ETH_ADDR_LEN,
index c673beeb3c1c42c3d8fdaab3c7ded514d05ab16b..727a9e52d20ee2f0fb4727188f55289386e5b679 100644 (file)
@@ -34,7 +34,7 @@ struct dpif_linux_vport {
 
     /* Attributes. */
     const char *name;                      /* OVS_VPORT_ATTR_NAME. */
-    const struct rtnl_link_stats64 *stats; /* OVS_VPORT_ATTR_STATS. */
+    const struct ovs_vport_stats *stats;   /* OVS_VPORT_ATTR_STATS. */
     const uint8_t *address;                /* OVS_VPORT_ATTR_ADDRESS. */
     const struct nlattr *options;          /* OVS_VPORT_ATTR_OPTIONS. */
     size_t options_len;
index 8cf7cfe44114d34accb708e1df33f2ddaa423a5e..ad143c8ed21c7ad612d334531921c4909670391c 100644 (file)
@@ -469,7 +469,6 @@ dpif_port_clone(struct dpif_port *dst, const struct dpif_port *src)
     dst->name = xstrdup(src->name);
     dst->type = xstrdup(src->type);
     dst->port_no = src->port_no;
-    dst->stats = src->stats;
 }
 
 /* Frees memory allocated to members of 'dpif_port'.
index 1f352065055c273c8f854d04ddf9fb8b5082ae14..c01010db93c020b00760858d63b5560260fdf17b 100644 (file)
@@ -72,7 +72,6 @@ struct dpif_port {
     char *name;                 /* Network device name, e.g. "eth0". */
     char *type;                 /* Network device type, e.g. "system". */
     uint32_t port_no;           /* Port number within datapath. */
-    struct netdev_stats stats;  /* Port statistics. */
 };
 void dpif_port_clone(struct dpif_port *, const struct dpif_port *);
 void dpif_port_destroy(struct dpif_port *);
index fc61d452d266915304988ce1ca0510cb3fa5f06c..ee3c5f52a5cc931e59caf8444586728768606b4c 100644 (file)
@@ -115,9 +115,8 @@ enum {
     VALID_IN6               = 1 << 3,
     VALID_MTU               = 1 << 4,
     VALID_CARRIER           = 1 << 5,
-    VALID_IS_PSEUDO         = 1 << 6, /* Represents is_internal and is_tap. */
-    VALID_POLICING          = 1 << 7,
-    VALID_HAVE_VPORT_STATS  = 1 << 8
+    VALID_POLICING          = 1 << 6,
+    VALID_HAVE_VPORT_STATS  = 1 << 7
 };
 
 struct tap_state {
@@ -369,8 +368,6 @@ struct netdev_dev_linux {
     struct in6_addr in6;
     int mtu;
     int carrier;
-    bool is_internal;           /* Is this an openvswitch internal device? */
-    bool is_tap;                /* Is this a tuntap device? */
     uint32_t kbits_rate;        /* Policing data. */
     uint32_t kbits_burst;
     bool have_vport_stats;
@@ -1246,21 +1243,6 @@ check_for_working_netlink_stats(void)
     }
 }
 
-/* Brings the 'is_internal' and 'is_tap' members of 'netdev_dev' up-to-date. */
-static void
-netdev_linux_update_is_pseudo(struct netdev_dev_linux *netdev_dev)
-{
-    if (!(netdev_dev->cache_valid & VALID_IS_PSEUDO)) {
-        const char *name = netdev_dev_get_name(&netdev_dev->netdev_dev);
-        const char *type = netdev_dev_get_type(&netdev_dev->netdev_dev);
-
-        netdev_dev->is_tap = !strcmp(type, "tap");
-        netdev_dev->is_internal = (!netdev_dev->is_tap
-                                   && dpif_linux_is_internal_device(name));
-        netdev_dev->cache_valid |= VALID_IS_PSEUDO;
-    }
-}
-
 static void
 swap_uint64(uint64_t *a, uint64_t *b)
 {
@@ -1269,37 +1251,123 @@ swap_uint64(uint64_t *a, uint64_t *b)
     *b = tmp;
 }
 
-/* Retrieves current device stats for 'netdev'. */
-static int
-netdev_linux_get_stats(const struct netdev *netdev_,
-                       struct netdev_stats *stats)
+static void
+get_stats_via_vport(const struct netdev *netdev_,
+                    struct netdev_stats *stats)
 {
     struct netdev_dev_linux *netdev_dev =
                                 netdev_dev_linux_cast(netdev_get_dev(netdev_));
-    static int use_netlink_stats = -1;
-    int error;
 
     if (netdev_dev->have_vport_stats ||
         !(netdev_dev->cache_valid & VALID_HAVE_VPORT_STATS)) {
+        int error;
 
         error = netdev_vport_get_stats(netdev_, stats);
+        if (error) {
+            VLOG_WARN_RL(&rl, "%s: obtaining netdev stats via vport failed %d",
+                         netdev_get_name(netdev_), error);
+        }
         netdev_dev->have_vport_stats = !error;
         netdev_dev->cache_valid |= VALID_HAVE_VPORT_STATS;
     }
+}
 
-    if (!netdev_dev->have_vport_stats) {
-        if (use_netlink_stats < 0) {
-            use_netlink_stats = check_for_working_netlink_stats();
+static int
+netdev_linux_sys_get_stats(const struct netdev *netdev_,
+                         struct netdev_stats *stats)
+{
+    static int use_netlink_stats = -1;
+    int error;
+
+    if (use_netlink_stats < 0) {
+        use_netlink_stats = check_for_working_netlink_stats();
+    }
+
+    if (use_netlink_stats) {
+        int ifindex;
+
+        error = get_ifindex(netdev_, &ifindex);
+        if (!error) {
+            error = get_stats_via_netlink(ifindex, stats);
         }
-        if (use_netlink_stats) {
-            int ifindex;
+    } else {
+        error = get_stats_via_proc(netdev_get_name(netdev_), stats);
+    }
 
-            error = get_ifindex(netdev_, &ifindex);
-            if (!error) {
-                error = get_stats_via_netlink(ifindex, stats);
-            }
+    if (error) {
+        VLOG_WARN_RL(&rl, "%s: linux-sys get stats failed %d",
+                      netdev_get_name(netdev_), error);
+    }
+    return error;
+
+}
+
+/* Retrieves current device stats for 'netdev-linux'. */
+static int
+netdev_linux_get_stats(const struct netdev *netdev_,
+                       struct netdev_stats *stats)
+{
+    struct netdev_dev_linux *netdev_dev =
+                                netdev_dev_linux_cast(netdev_get_dev(netdev_));
+    struct netdev_stats dev_stats;
+    int error;
+
+    get_stats_via_vport(netdev_, stats);
+
+    error = netdev_linux_sys_get_stats(netdev_, &dev_stats);
+
+    if (error) {
+        if (!netdev_dev->have_vport_stats) {
+            return error;
         } else {
-            error = get_stats_via_proc(netdev_get_name(netdev_), stats);
+            return 0;
+        }
+    }
+
+    if (!netdev_dev->have_vport_stats) {
+        /* stats not available from OVS then use ioctl stats. */
+        *stats = dev_stats;
+    } else {
+        stats->rx_errors           += dev_stats.rx_errors;
+        stats->tx_errors           += dev_stats.tx_errors;
+        stats->rx_dropped          += dev_stats.rx_dropped;
+        stats->tx_dropped          += dev_stats.tx_dropped;
+        stats->multicast           += dev_stats.multicast;
+        stats->collisions          += dev_stats.collisions;
+        stats->rx_length_errors    += dev_stats.rx_length_errors;
+        stats->rx_over_errors      += dev_stats.rx_over_errors;
+        stats->rx_crc_errors       += dev_stats.rx_crc_errors;
+        stats->rx_frame_errors     += dev_stats.rx_frame_errors;
+        stats->rx_fifo_errors      += dev_stats.rx_fifo_errors;
+        stats->rx_missed_errors    += dev_stats.rx_missed_errors;
+        stats->tx_aborted_errors   += dev_stats.tx_aborted_errors;
+        stats->tx_carrier_errors   += dev_stats.tx_carrier_errors;
+        stats->tx_fifo_errors      += dev_stats.tx_fifo_errors;
+        stats->tx_heartbeat_errors += dev_stats.tx_heartbeat_errors;
+        stats->tx_window_errors    += dev_stats.tx_window_errors;
+    }
+    return 0;
+}
+
+/* Retrieves current device stats for 'netdev-tap' netdev or
+ * netdev-internal. */
+static int
+netdev_pseudo_get_stats(const struct netdev *netdev_,
+                        struct netdev_stats *stats)
+{
+    struct netdev_dev_linux *netdev_dev =
+                                netdev_dev_linux_cast(netdev_get_dev(netdev_));
+    struct netdev_stats dev_stats;
+    int error;
+
+    get_stats_via_vport(netdev_, stats);
+
+    error = netdev_linux_sys_get_stats(netdev_, &dev_stats);
+    if (error) {
+        if (!netdev_dev->have_vport_stats) {
+            return error;
+        } else {
+            return 0;
         }
     }
 
@@ -1309,9 +1377,8 @@ netdev_linux_get_stats(const struct netdev *netdev_,
      * them back here. This does not apply if we are getting stats from the
      * vport layer because it always tracks stats from the perspective of the
      * switch. */
-    netdev_linux_update_is_pseudo(netdev_dev);
-    if (!error && !netdev_dev->have_vport_stats &&
-        (netdev_dev->is_internal || netdev_dev->is_tap)) {
+    if (!netdev_dev->have_vport_stats) {
+        *stats = dev_stats;
         swap_uint64(&stats->rx_packets, &stats->tx_packets);
         swap_uint64(&stats->rx_bytes, &stats->tx_bytes);
         swap_uint64(&stats->rx_errors, &stats->tx_errors);
@@ -1327,9 +1394,17 @@ netdev_linux_get_stats(const struct netdev *netdev_,
         stats->tx_fifo_errors = 0;
         stats->tx_heartbeat_errors = 0;
         stats->tx_window_errors = 0;
-    }
+    } else {
+        stats->rx_dropped          += dev_stats.tx_dropped;
+        stats->tx_dropped          += dev_stats.rx_dropped;
 
-    return error;
+        stats->rx_errors           += dev_stats.tx_errors;
+        stats->tx_errors           += dev_stats.rx_errors;
+
+        stats->multicast           += dev_stats.multicast;
+        stats->collisions          += dev_stats.collisions;
+    }
+    return 0;
 }
 
 /* Stores the features supported by 'netdev' into each of '*current',
@@ -2263,7 +2338,7 @@ netdev_linux_change_seq(const struct netdev *netdev)
     return netdev_dev_linux_cast(netdev_get_dev(netdev))->change_seq;
 }
 
-#define NETDEV_LINUX_CLASS(NAME, CREATE, ENUMERATE, SET_STATS)  \
+#define NETDEV_LINUX_CLASS(NAME, CREATE, ENUMERATE, GET_STATS, SET_STATS)  \
 {                                                               \
     NAME,                                                       \
                                                                 \
@@ -2296,7 +2371,7 @@ netdev_linux_change_seq(const struct netdev *netdev)
     netdev_linux_get_ifindex,                                   \
     netdev_linux_get_carrier,                                   \
     netdev_linux_set_miimon_interval,                           \
-    netdev_linux_get_stats,                                     \
+    GET_STATS,                                                  \
     SET_STATS,                                                  \
                                                                 \
     netdev_linux_get_features,                                  \
@@ -2333,6 +2408,7 @@ const struct netdev_class netdev_linux_class =
         "system",
         netdev_linux_create,
         netdev_linux_enumerate,
+        netdev_linux_get_stats,
         NULL);                  /* set_stats */
 
 const struct netdev_class netdev_tap_class =
@@ -2340,6 +2416,7 @@ const struct netdev_class netdev_tap_class =
         "tap",
         netdev_linux_create_tap,
         NULL,                   /* enumerate */
+        netdev_pseudo_get_stats,
         NULL);                  /* set_stats */
 
 const struct netdev_class netdev_internal_class =
@@ -2347,6 +2424,7 @@ const struct netdev_class netdev_internal_class =
         "internal",
         netdev_linux_create,
         NULL,                    /* enumerate */
+        netdev_pseudo_get_stats,
         netdev_vport_set_stats);
 \f
 /* HTB traffic control class. */
@@ -3956,56 +4034,34 @@ tc_calc_buffer(unsigned int Bps, int mtu, uint64_t burst_bytes)
     return tc_bytes_to_ticks(Bps, MAX(burst_bytes, min_burst));
 }
 \f
-/* Public utility functions. */
-
-#define COPY_NETDEV_STATS                                   \
-    dst->rx_packets = src->rx_packets;                      \
-    dst->tx_packets = src->tx_packets;                      \
-    dst->rx_bytes = src->rx_bytes;                          \
-    dst->tx_bytes = src->tx_bytes;                          \
-    dst->rx_errors = src->rx_errors;                        \
-    dst->tx_errors = src->tx_errors;                        \
-    dst->rx_dropped = src->rx_dropped;                      \
-    dst->tx_dropped = src->tx_dropped;                      \
-    dst->multicast = src->multicast;                        \
-    dst->collisions = src->collisions;                      \
-    dst->rx_length_errors = src->rx_length_errors;          \
-    dst->rx_over_errors = src->rx_over_errors;              \
-    dst->rx_crc_errors = src->rx_crc_errors;                \
-    dst->rx_frame_errors = src->rx_frame_errors;            \
-    dst->rx_fifo_errors = src->rx_fifo_errors;              \
-    dst->rx_missed_errors = src->rx_missed_errors;          \
-    dst->tx_aborted_errors = src->tx_aborted_errors;        \
-    dst->tx_carrier_errors = src->tx_carrier_errors;        \
-    dst->tx_fifo_errors = src->tx_fifo_errors;              \
-    dst->tx_heartbeat_errors = src->tx_heartbeat_errors;    \
-    dst->tx_window_errors = src->tx_window_errors
-
 /* Copies 'src' into 'dst', performing format conversion in the process. */
-void
+static void
 netdev_stats_from_rtnl_link_stats(struct netdev_stats *dst,
                                   const struct rtnl_link_stats *src)
 {
-    COPY_NETDEV_STATS;
-}
-
-/* Copies 'src' into 'dst', performing format conversion in the process. */
-void
-netdev_stats_from_rtnl_link_stats64(struct netdev_stats *dst,
-                                    const struct rtnl_link_stats64 *src)
-{
-    COPY_NETDEV_STATS;
+    dst->rx_packets = src->rx_packets;
+    dst->tx_packets = src->tx_packets;
+    dst->rx_bytes = src->rx_bytes;
+    dst->tx_bytes = src->tx_bytes;
+    dst->rx_errors = src->rx_errors;
+    dst->tx_errors = src->tx_errors;
+    dst->rx_dropped = src->rx_dropped;
+    dst->tx_dropped = src->tx_dropped;
+    dst->multicast = src->multicast;
+    dst->collisions = src->collisions;
+    dst->rx_length_errors = src->rx_length_errors;
+    dst->rx_over_errors = src->rx_over_errors;
+    dst->rx_crc_errors = src->rx_crc_errors;
+    dst->rx_frame_errors = src->rx_frame_errors;
+    dst->rx_fifo_errors = src->rx_fifo_errors;
+    dst->rx_missed_errors = src->rx_missed_errors;
+    dst->tx_aborted_errors = src->tx_aborted_errors;
+    dst->tx_carrier_errors = src->tx_carrier_errors;
+    dst->tx_fifo_errors = src->tx_fifo_errors;
+    dst->tx_heartbeat_errors = src->tx_heartbeat_errors;
+    dst->tx_window_errors = src->tx_window_errors;
 }
 
-/* Copies 'src' into 'dst', performing format conversion in the process. */
-void
-netdev_stats_to_rtnl_link_stats64(struct rtnl_link_stats64 *dst,
-                                  const struct netdev_stats *src)
-{
-    COPY_NETDEV_STATS;
-    dst->rx_compressed = 0;
-    dst->tx_compressed = 0;
-}
 \f
 /* Utility functions. */
 
index d34a4401894863fa3b9cc74b805898a67d462662..c00a846b41335c0c30413a875336ce9d78d3c2b1 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include "openvswitch/datapath-protocol.h"
 
 /* These functions are Linux specific, so they should be used directly only by
  * Linux-specific code. */
 struct netdev;
 struct netdev_stats;
 struct rtnl_link_stats;
-struct rtnl_link_stats64;
-
-void netdev_stats_from_rtnl_link_stats(struct netdev_stats *dst,
-                                       const struct rtnl_link_stats *src);
-void netdev_stats_from_rtnl_link_stats64(struct netdev_stats *dst,
-                                         const struct rtnl_link_stats64 *src);
-void netdev_stats_to_rtnl_link_stats64(struct rtnl_link_stats64 *dst,
-                                       const struct netdev_stats *src);
 
 int netdev_linux_ethtool_set_flag(struct netdev *netdev, uint32_t flag,
                                   const char *flag_name, bool enable);
index cf475b2427f83b8bcf34e46b473dcb83b7175460..d85d528454b46201675ff252ab022482bd914217 100644 (file)
@@ -361,6 +361,45 @@ netdev_vport_get_etheraddr(const struct netdev *netdev,
     return error;
 }
 
+#define COPY_OVS_STATS                                      \
+    dst->rx_packets = src->rx_packets;                      \
+    dst->tx_packets = src->tx_packets;                      \
+    dst->rx_bytes = src->rx_bytes;                          \
+    dst->tx_bytes = src->tx_bytes;                          \
+    dst->rx_errors = src->rx_errors;                        \
+    dst->tx_errors = src->tx_errors;                        \
+    dst->rx_dropped = src->rx_dropped;                      \
+    dst->tx_dropped = src->tx_dropped;
+
+/* Copies 'src' into 'dst', performing format conversion in the process. */
+static void
+netdev_stats_from_ovs_vport_stats(struct netdev_stats *dst,
+                                  const struct ovs_vport_stats *src)
+{
+    COPY_OVS_STATS
+    dst->multicast = 0;
+    dst->collisions = 0;
+    dst->rx_length_errors = 0;
+    dst->rx_over_errors = 0;
+    dst->rx_crc_errors = 0;
+    dst->rx_frame_errors = 0;
+    dst->rx_fifo_errors = 0;
+    dst->rx_missed_errors = 0;
+    dst->tx_aborted_errors = 0;
+    dst->tx_carrier_errors = 0;
+    dst->tx_fifo_errors = 0;
+    dst->tx_heartbeat_errors = 0;
+    dst->tx_window_errors = 0;
+}
+
+/* Copies 'src' into 'dst', performing format conversion in the process. */
+static void
+netdev_stats_to_ovs_vport_stats(struct ovs_vport_stats *dst,
+                                const struct netdev_stats *src)
+{
+    COPY_OVS_STATS
+}
+
 int
 netdev_vport_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
 {
@@ -376,7 +415,7 @@ netdev_vport_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
         return EOPNOTSUPP;
     }
 
-    netdev_stats_from_rtnl_link_stats64(stats, reply.stats);
+    netdev_stats_from_ovs_vport_stats(stats, reply.stats);
 
     ofpbuf_delete(buf);
 
@@ -386,11 +425,11 @@ netdev_vport_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
 int
 netdev_vport_set_stats(struct netdev *netdev, const struct netdev_stats *stats)
 {
-    struct rtnl_link_stats64 rtnl_stats;
+    struct ovs_vport_stats rtnl_stats;
     struct dpif_linux_vport vport;
     int err;
 
-    netdev_stats_to_rtnl_link_stats64(&rtnl_stats, stats);
+    netdev_stats_to_ovs_vport_stats(&rtnl_stats, stats);
 
     dpif_linux_vport_init(&vport);
     vport.cmd = OVS_VPORT_CMD_SET;
index 7aaf67a209402b38aecc65c90a747dbd433399a0..c59d5d4c1d7447f13b298f2889a837d87a54c4c3 100644 (file)
@@ -46,25 +46,6 @@ AC_DEFUN([OVS_CHECK_NDEBUG],
      [ndebug=false])
    AM_CONDITIONAL([NDEBUG], [test x$ndebug = xtrue])])
 
-dnl Checks for struct rtnl_link_stats64.
-dnl
-dnl (OVS checks for this structure in both kernel and userspace headers.  This
-dnl is not redundant, because the kernel and userspace builds have completely
-dnl different include paths.  It is possible for the kernel to have this
-dnl structure but not userspace, and vice versa.)
-AC_DEFUN([OVS_CHECK_RTNL_LINK_STATS64],
-  [AC_REQUIRE([OVS_CHECK_NETLINK])
-   if test $HAVE_NETLINK = yes; then
-     AC_CHECK_MEMBER(
-       [struct rtnl_link_stats64.tx_packets],
-       [AC_DEFINE([HAVE_RTNL_LINK_STATS64], [1],
-                  [Define to 1 if <linux/if_link.h> defines
-                   struct rtnl_link_stats64.])],
-       [], [#include <sys/socket.h>     /* Provides sa_family_t. */
-#include <linux/if_link.h>
-])
-   fi])
-
 dnl Checks for Netlink support.
 AC_DEFUN([OVS_CHECK_NETLINK],
   [AC_CHECK_HEADER([linux/netlink.h],
index 0e6c16fa44e1052ac62ca1a2ecf8d6153d53143a..e724e745b2316787c5c396cb2cf20733e94f0138 100644 (file)
@@ -367,6 +367,7 @@ show_dpif(struct dpif *dpif)
     struct dpif_port_dump dump;
     struct dpif_port dpif_port;
     struct ovs_dp_stats stats;
+    struct netdev *netdev;
 
     printf("%s:\n", dpif_name(dpif));
     if (!dpif_get_dp_stats(dpif, &stats)) {
@@ -381,7 +382,6 @@ show_dpif(struct dpif *dpif)
         printf("\tport %u: %s", dpif_port.port_no, dpif_port.name);
 
         if (strcmp(dpif_port.type, "system")) {
-            struct netdev *netdev;
             int error;
 
             printf (" (%s", dpif_port.type);
@@ -418,29 +418,42 @@ show_dpif(struct dpif *dpif)
         putchar('\n');
 
         if (print_statistics) {
-            const struct netdev_stats *s = &dpif_port.stats;
+            struct netdev_stats s;
+            int error;
+
+            error = netdev_open(dpif_port.name, dpif_port.type, &netdev);
+            if (error) {
+                printf(", open failed (%s)", strerror(error));
+                continue;
+            }
+            error = netdev_get_stats(netdev, &s);
+            if (error) {
+                printf(", could not retrieve stats (%s)", strerror(error));
+                continue;
+            }
 
-            print_stat("\t\tRX packets:", s->rx_packets);
-            print_stat(" errors:", s->rx_errors);
-            print_stat(" dropped:", s->rx_dropped);
-            print_stat(" overruns:", s->rx_over_errors);
-            print_stat(" frame:", s->rx_frame_errors);
+            netdev_close(netdev);
+            print_stat("\t\tRX packets:", s.rx_packets);
+            print_stat(" errors:", s.rx_errors);
+            print_stat(" dropped:", s.rx_dropped);
+            print_stat(" overruns:", s.rx_over_errors);
+            print_stat(" frame:", s.rx_frame_errors);
             printf("\n");
 
-            print_stat("\t\tTX packets:", s->tx_packets);
-            print_stat(" errors:", s->tx_errors);
-            print_stat(" dropped:", s->tx_dropped);
-            print_stat(" aborted:", s->tx_aborted_errors);
-            print_stat(" carrier:", s->tx_carrier_errors);
+            print_stat("\t\tTX packets:", s.tx_packets);
+            print_stat(" errors:", s.tx_errors);
+            print_stat(" dropped:", s.tx_dropped);
+            print_stat(" aborted:", s.tx_aborted_errors);
+            print_stat(" carrier:", s.tx_carrier_errors);
             printf("\n");
 
-            print_stat("\t\tcollisions:", s->collisions);
+            print_stat("\t\tcollisions:", s.collisions);
             printf("\n");
 
-            print_stat("\t\tRX bytes:", s->rx_bytes);
-            print_human_size(s->rx_bytes);
-            print_stat("  TX bytes:", s->tx_bytes);
-            print_human_size(s->tx_bytes);
+            print_stat("\t\tRX bytes:", s.rx_bytes);
+            print_human_size(s.rx_bytes);
+            print_stat("  TX bytes:", s.tx_bytes);
+            print_human_size(s.tx_bytes);
             printf("\n");
         }
     }