netdev-vport: Build on all platforms.
[sliver-openvswitch.git] / lib / netdev-linux.c
index 60f985e..5de4fa2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@
 
 #include "netdev-linux.h"
 
-#include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <arpa/inet.h>
 #include "hmap.h"
 #include "netdev-provider.h"
 #include "netdev-vport.h"
-#include "netlink.h"
 #include "netlink-notifier.h"
 #include "netlink-socket.h"
+#include "netlink.h"
 #include "ofpbuf.h"
 #include "openflow/openflow.h"
 #include "packets.h"
 #include "poll-loop.h"
 #include "rtnetlink-link.h"
-#include "socket-util.h"
 #include "shash.h"
+#include "socket-util.h"
 #include "sset.h"
 #include "timer.h"
+#include "unaligned.h"
 #include "vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(netdev_linux);
@@ -444,7 +444,7 @@ static struct netdev_dev_linux *
 netdev_dev_linux_cast(const struct netdev_dev *netdev_dev)
 {
     const struct netdev_class *netdev_class = netdev_dev_get_class(netdev_dev);
-    assert(is_netdev_linux_class(netdev_class));
+    ovs_assert(is_netdev_linux_class(netdev_class));
 
     return CONTAINER_OF(netdev_dev, struct netdev_dev_linux, netdev_dev);
 }
@@ -454,7 +454,7 @@ netdev_linux_cast(const struct netdev *netdev)
 {
     struct netdev_dev *netdev_dev = netdev_get_dev(netdev);
     const struct netdev_class *netdev_class = netdev_dev_get_class(netdev_dev);
-    assert(is_netdev_linux_class(netdev_class));
+    ovs_assert(is_netdev_linux_class(netdev_class));
 
     return CONTAINER_OF(netdev, struct netdev_linux, netdev);
 }
@@ -497,28 +497,6 @@ netdev_linux_wait(void)
     netdev_linux_miimon_wait();
 }
 
-static int
-netdev_linux_get_drvinfo(struct netdev_dev_linux *netdev_dev)
-{
-
-    int error;
-
-    if (netdev_dev->cache_valid & VALID_DRVINFO) {
-        return 0;
-    }
-
-    COVERAGE_INC(netdev_get_ethtool);
-    memset(&netdev_dev->drvinfo, 0, sizeof netdev_dev->drvinfo);
-    error = netdev_linux_do_ethtool(netdev_dev->netdev_dev.name,
-                                    (struct ethtool_cmd *)&netdev_dev->drvinfo,
-                                    ETHTOOL_GDRVINFO,
-                                    "ETHTOOL_GDRVINFO");
-    if (!error) {
-        netdev_dev->cache_valid |= VALID_DRVINFO;
-    }
-    return error;
-}
-
 static void
 netdev_dev_linux_changed(struct netdev_dev_linux *dev,
                          unsigned int ifi_flags,
@@ -605,7 +583,7 @@ static int
 cache_notifier_ref(void)
 {
     if (!cache_notifier_refcount) {
-        assert(!netdev_linux_cache_notifier);
+        ovs_assert(!netdev_linux_cache_notifier);
 
         netdev_linux_cache_notifier =
             rtnetlink_link_notifier_create(netdev_linux_cache_cb, NULL);
@@ -622,9 +600,9 @@ cache_notifier_ref(void)
 static void
 cache_notifier_unref(void)
 {
-    assert(cache_notifier_refcount > 0);
+    ovs_assert(cache_notifier_refcount > 0);
     if (!--cache_notifier_refcount) {
-        assert(netdev_linux_cache_notifier);
+        ovs_assert(netdev_linux_cache_notifier);
         rtnetlink_link_notifier_destroy(netdev_linux_cache_notifier);
         netdev_linux_cache_notifier = NULL;
     }
@@ -1332,6 +1310,58 @@ swap_uint64(uint64_t *a, uint64_t *b)
     *b = tmp;
 }
 
+/* Copies 'src' into 'dst', performing format conversion in the process.
+ *
+ * 'src' is allowed to be misaligned. */
+static void
+netdev_stats_from_ovs_vport_stats(struct netdev_stats *dst,
+                                  const struct ovs_vport_stats *src)
+{
+    dst->rx_packets = get_unaligned_u64(&src->rx_packets);
+    dst->tx_packets = get_unaligned_u64(&src->tx_packets);
+    dst->rx_bytes = get_unaligned_u64(&src->rx_bytes);
+    dst->tx_bytes = get_unaligned_u64(&src->tx_bytes);
+    dst->rx_errors = get_unaligned_u64(&src->rx_errors);
+    dst->tx_errors = get_unaligned_u64(&src->tx_errors);
+    dst->rx_dropped = get_unaligned_u64(&src->rx_dropped);
+    dst->tx_dropped = get_unaligned_u64(&src->tx_dropped);
+    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;
+}
+
+static int
+get_stats_via_vport__(const struct netdev *netdev, struct netdev_stats *stats)
+{
+    struct dpif_linux_vport reply;
+    struct ofpbuf *buf;
+    int error;
+
+    error = dpif_linux_vport_get(netdev_get_name(netdev), &reply, &buf);
+    if (error) {
+        return error;
+    } else if (!reply.stats) {
+        ofpbuf_delete(buf);
+        return EOPNOTSUPP;
+    }
+
+    netdev_stats_from_ovs_vport_stats(stats, reply.stats);
+
+    ofpbuf_delete(buf);
+
+    return 0;
+}
+
 static void
 get_stats_via_vport(const struct netdev *netdev_,
                     struct netdev_stats *stats)
@@ -1343,7 +1373,7 @@ get_stats_via_vport(const struct netdev *netdev_,
         !(netdev_dev->cache_valid & VALID_VPORT_STAT_ERROR)) {
         int error;
 
-        error = netdev_vport_get_stats(netdev_, stats);
+        error = get_stats_via_vport__(netdev_, stats);
         if (error && error != ENOENT) {
             VLOG_WARN_RL(&rl, "%s: obtaining netdev stats via vport failed "
                          "(%s)", netdev_get_name(netdev_), strerror(error));
@@ -1941,11 +1971,11 @@ netdev_linux_set_qos(struct netdev *netdev,
         if (error) {
             return error;
         }
-        assert(netdev_dev->tc == NULL);
+        ovs_assert(netdev_dev->tc == NULL);
 
         /* Install new qdisc. */
         error = new_ops->tc_install(netdev, details);
-        assert((error == 0) == (netdev_dev->tc != NULL));
+        ovs_assert((error == 0) == (netdev_dev->tc != NULL));
 
         return error;
     }
@@ -2323,13 +2353,26 @@ netdev_linux_get_next_hop(const struct in_addr *host, struct in_addr *next_hop,
 }
 
 static int
-netdev_linux_get_drv_info(const struct netdev *netdev, struct smap *smap)
+netdev_linux_get_status(const struct netdev *netdev, struct smap *smap)
 {
-    int error;
-    struct netdev_dev_linux *netdev_dev =
-                                netdev_dev_linux_cast(netdev_get_dev(netdev));
+    struct netdev_dev_linux *netdev_dev;
+    int error = 0;
+
+    netdev_dev = netdev_dev_linux_cast(netdev_get_dev(netdev));
+    if (!(netdev_dev->cache_valid & VALID_DRVINFO)) {
+        struct ethtool_cmd *cmd = (struct ethtool_cmd *) &netdev_dev->drvinfo;
+
+        COVERAGE_INC(netdev_get_ethtool);
+        memset(&netdev_dev->drvinfo, 0, sizeof netdev_dev->drvinfo);
+        error = netdev_linux_do_ethtool(netdev_dev->netdev_dev.name,
+                                        cmd,
+                                        ETHTOOL_GDRVINFO,
+                                        "ETHTOOL_GDRVINFO");
+        if (!error) {
+            netdev_dev->cache_valid |= VALID_DRVINFO;
+        }
+    }
 
-    error = netdev_linux_get_drvinfo(netdev_dev);
     if (!error) {
         smap_add(smap, "driver_name", netdev_dev->drvinfo.driver);
         smap_add(smap, "driver_version", netdev_dev->drvinfo.version);
@@ -2339,8 +2382,8 @@ netdev_linux_get_drv_info(const struct netdev *netdev, struct smap *smap)
 }
 
 static int
-netdev_internal_get_drv_info(const struct netdev *netdev OVS_UNUSED,
-                             struct smap *smap)
+netdev_internal_get_status(const struct netdev *netdev OVS_UNUSED,
+                           struct smap *smap)
 {
     smap_add(smap, "driver_name", "openvswitch");
     return 0;
@@ -2442,6 +2485,7 @@ netdev_linux_change_seq(const struct netdev *netdev)
     netdev_linux_destroy,                                       \
     NULL,                       /* get_config */                \
     NULL,                       /* set_config */                \
+    NULL,                       /* get_tunnel_config */         \
                                                                 \
     netdev_linux_open,                                          \
     netdev_linux_close,                                         \
@@ -2500,7 +2544,7 @@ const struct netdev_class netdev_linux_class =
         netdev_linux_get_stats,
         NULL,                    /* set_stats */
         netdev_linux_get_features,
-        netdev_linux_get_drv_info);
+        netdev_linux_get_status);
 
 const struct netdev_class netdev_tap_class =
     NETDEV_LINUX_CLASS(
@@ -2509,7 +2553,7 @@ const struct netdev_class netdev_tap_class =
         netdev_tap_get_stats,
         NULL,                   /* set_stats */
         netdev_linux_get_features,
-        netdev_linux_get_drv_info);
+        netdev_linux_get_status);
 
 const struct netdev_class netdev_internal_class =
     NETDEV_LINUX_CLASS(
@@ -2518,7 +2562,7 @@ const struct netdev_class netdev_internal_class =
         netdev_internal_get_stats,
         netdev_internal_set_stats,
         NULL,                  /* get_features */
-        netdev_internal_get_drv_info);
+        netdev_internal_get_status);
 \f
 /* HTB traffic control class. */
 
@@ -3739,7 +3783,7 @@ tc_add_policer(struct netdev *netdev, int kbits_rate, int kbits_burst)
     memset(&tc_police, 0, sizeof tc_police);
     tc_police.action = TC_POLICE_SHOT;
     tc_police.mtu = mtu;
-    tc_fill_rate(&tc_police.rate, kbits_rate/8 * 1000, mtu);
+    tc_fill_rate(&tc_police.rate, (kbits_rate * 1000)/8, mtu);
     tc_police.burst = tc_bytes_to_ticks(tc_police.rate.rate,
                                         kbits_burst * 1024);
 
@@ -4153,7 +4197,7 @@ tc_query_qdisc(const struct netdev *netdev)
 
     /* Instantiate it. */
     load_error = ops->tc_load(CONST_CAST(struct netdev *, netdev), qdisc);
-    assert((load_error == 0) == (netdev_dev->tc != NULL));
+    ovs_assert((load_error == 0) == (netdev_dev->tc != NULL));
     ofpbuf_delete(qdisc);
 
     return error ? error : load_error;