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 b379489..648132a 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 e03946a..7387d82 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 0238c5f..98c2baf 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 1ac3831..8d24cd9 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 91855c4..9e92eeb 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 68a168b..76db8a7 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 24c53f8..5beae42 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 04f51eb..ecfb379 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 7cd6c6b..4c7f1cb 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 7a743d2..9b138be 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 1ec3a4c..9554f12 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 ca802b4..71fdd84 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 6c4da24..e7d2eb5 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 f34e5c9..9ec5b72 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 5687792..8ed1c7f 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 9533e14..3d081aa 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 c673bee..727a9e5 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 8cf7cfe..ad143c8 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 1f35206..c01010d 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 fc61d45..ee3c5f5 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 d34a440..c00a846 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 cf475b2..d85d528 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 7aaf67a..c59d5d4 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 0e6c16f..e724e74 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");
         }
     }