recognize external links passed via command line
[sliver-openvswitch.git] / lib / netdev-linux.c
index e1936fa..c0e0c40 100644 (file)
@@ -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);
 }
@@ -583,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);
@@ -600,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;
     }
@@ -916,7 +916,7 @@ netdev_linux_send(struct netdev *netdev_, const void *data, size_t size)
 
             sock = af_packet_sock();
             if (sock < 0) {
-                return sock;
+                return -sock;
             }
 
             error = get_ifindex(netdev_, &ifindex);
@@ -1310,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)
@@ -1321,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));
@@ -1919,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;
     }
@@ -3731,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);
 
@@ -4145,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;
@@ -4587,7 +4639,11 @@ af_packet_sock(void)
     if (sock == INT_MIN) {
         sock = socket(AF_PACKET, SOCK_RAW, 0);
         if (sock >= 0) {
-            set_nonblocking(sock);
+            int error = set_nonblocking(sock);
+            if (error) {
+                close(sock);
+                sock = -error;
+            }
         } else {
             sock = -errno;
             VLOG_ERR("failed to create packet socket: %s", strerror(errno));