coverage: Make the coverage counters catalog program-specific.
[sliver-openvswitch.git] / lib / netdev.c
index c1eb5d0..d108e9c 100644 (file)
@@ -31,6 +31,7 @@
 #include "hash.h"
 #include "list.h"
 #include "netdev-provider.h"
+#include "netdev-vport.h"
 #include "ofpbuf.h"
 #include "openflow/openflow.h"
 #include "packets.h"
 #include "svec.h"
 #include "vlog.h"
 
-VLOG_DEFINE_THIS_MODULE(netdev)
+VLOG_DEFINE_THIS_MODULE(netdev);
 
-static const struct netdev_class *base_netdev_classes[] = {
-#ifdef HAVE_NETLINK
-    &netdev_linux_class,
-    &netdev_tap_class,
-    &netdev_patch_class,
-    &netdev_gre_class,
-    &netdev_capwap_class,
-#endif
-};
+COVERAGE_DEFINE(netdev_received);
+COVERAGE_DEFINE(netdev_sent);
+COVERAGE_DEFINE(netdev_add_router);
+COVERAGE_DEFINE(netdev_get_stats);
 
 static struct shash netdev_classes = SHASH_INITIALIZER(&netdev_classes);
 
@@ -70,17 +66,18 @@ void update_device_args(struct netdev_dev *, const struct shash *args);
 static void
 netdev_initialize(void)
 {
-    static int status = -1;
+    static bool inited;
 
-    if (status < 0) {
-        int i;
+    if (!inited) {
+        inited = true;
 
         fatal_signal_add_hook(close_all_netdevs, NULL, NULL, true);
 
-        status = 0;
-        for (i = 0; i < ARRAY_SIZE(base_netdev_classes); i++) {
-            netdev_register_provider(base_netdev_classes[i]);
-        }
+#ifdef HAVE_NETLINK
+        netdev_register_provider(&netdev_linux_class);
+        netdev_register_provider(&netdev_tap_class);
+        netdev_vport_register();
+#endif
     }
 }
 
@@ -121,8 +118,6 @@ netdev_wait(void)
 int
 netdev_register_provider(const struct netdev_class *new_class)
 {
-    struct netdev_class *new_provider;
-
     if (shash_find(&netdev_classes, new_class->type)) {
         VLOG_WARN("attempted to register duplicate netdev provider: %s",
                    new_class->type);
@@ -138,10 +133,7 @@ netdev_register_provider(const struct netdev_class *new_class)
         }
     }
 
-    new_provider = xmalloc(sizeof *new_provider);
-    memcpy(new_provider, new_class, sizeof *new_provider);
-
-    shash_add(&netdev_classes, new_class->type, new_provider);
+    shash_add(&netdev_classes, new_class->type, new_class);
 
     return 0;
 }
@@ -171,7 +163,6 @@ netdev_unregister_provider(const char *type)
     }
 
     shash_delete(&netdev_classes, del_node);
-    free(del_node->data);
 
     return 0;
 }
@@ -265,6 +256,7 @@ static int
 create_device(struct netdev_options *options, struct netdev_dev **netdev_devp)
 {
     struct netdev_class *netdev_class;
+    int error;
 
     if (!options->type || strlen(options->type) == 0) {
         /* Default to system. */
@@ -276,8 +268,10 @@ create_device(struct netdev_options *options, struct netdev_dev **netdev_devp)
         return EAFNOSUPPORT;
     }
 
-    return netdev_class->create(options->name, options->type, options->args,
-                                netdev_devp);
+    error = netdev_class->create(netdev_class, options->name, options->args,
+                                 netdev_devp);
+    assert(error || (*netdev_devp)->netdev_class == netdev_class);
+    return error;
 }
 
 /* Opens the network device named 'name' (e.g. "eth0") and returns zero if
@@ -285,13 +279,12 @@ create_device(struct netdev_options *options, struct netdev_dev **netdev_devp)
  * to the new network device, otherwise to null.
  *
  * If this is the first time the device has been opened, then create is called
- * before opening.  The device is  created using the given type and arguments.
+ * before opening.  The device is created using the given type and arguments.
  *
  * 'ethertype' may be a 16-bit Ethernet protocol value in host byte order to
  * capture frames of that type received on the device.  It may also be one of
  * the 'enum netdev_pseudo_ethertype' values to receive frames in one of those
  * categories. */
-
 int
 netdev_open(struct netdev_options *options, struct netdev **netdevp)
 {
@@ -465,8 +458,7 @@ netdev_enumerate(struct svec *svec)
  * be returned.
  *
  * Some network devices may not implement support for this function.  In such
- * cases this function will always return EOPNOTSUPP.
- */
+ * cases this function will always return EOPNOTSUPP. */
 int
 netdev_recv(struct netdev *netdev, struct ofpbuf *buffer)
 {
@@ -632,8 +624,7 @@ netdev_get_ifindex(const struct netdev *netdev)
  * passed-in values are set to 0.
  *
  * Some network devices may not implement support for this function.  In such
- * cases this function will always return EOPNOTSUPP.
- */
+ * cases this function will always return EOPNOTSUPP. */
 int
 netdev_get_features(struct netdev *netdev,
                     uint32_t *current, uint32_t *advertised,
@@ -718,8 +709,8 @@ netdev_set_advertisements(struct netdev *netdev, uint32_t advertise)
  *
  *   - EOPNOTSUPP: No IPv4 network stack attached to 'netdev'.
  *
- * 'address' or 'netmask' or both may be null, in which case the address or netmask
- * is not reported. */
+ * 'address' or 'netmask' or both may be null, in which case the address or 
+ * netmask is not reported. */
 int
 netdev_get_in4(const struct netdev *netdev,
                struct in_addr *address_, struct in_addr *netmask_)
@@ -909,19 +900,32 @@ netdev_arp_lookup(const struct netdev *netdev,
     return error;
 }
 
-/* Sets 'carrier' to true if carrier is active (link light is on) on
- * 'netdev'. */
-int
-netdev_get_carrier(const struct netdev *netdev, bool *carrier)
+/* Returns true if carrier is active (link light is on) on 'netdev'. */
+bool
+netdev_get_carrier(const struct netdev *netdev)
 {
-    int error = (netdev_get_dev(netdev)->netdev_class->get_carrier
-                 ? netdev_get_dev(netdev)->netdev_class->get_carrier(netdev,
-                        carrier)
-                 : EOPNOTSUPP);
+    int error;
+    enum netdev_flags flags;
+    bool carrier;
+
+    netdev_get_flags(netdev, &flags);
+    if (!(flags & NETDEV_UP)) {
+        return false;
+    }
+
+    if (!netdev_get_dev(netdev)->netdev_class->get_carrier) {
+        return true;
+    }
+
+    error = netdev_get_dev(netdev)->netdev_class->get_carrier(netdev,
+                                                              &carrier);
     if (error) {
-        *carrier = false;
+        VLOG_DBG("%s: failed to get network device carrier status, assuming "
+                 "down: %s", netdev_get_name(netdev), strerror(error));
+        carrier = false;
     }
-    return error;
+
+    return carrier;
 }
 
 /* Retrieves current device stats for 'netdev'. */
@@ -1150,8 +1154,7 @@ netdev_get_queue(const struct netdev *netdev,
  * the current form of QoS (e.g. as returned by netdev_get_n_queues(netdev)).
  *
  * This function does not modify 'details', and the caller retains ownership of
- * it.
- */
+ * it. */
 int
 netdev_set_queue(struct netdev *netdev,
                  unsigned int queue_id, const struct shash *details)
@@ -1543,8 +1546,7 @@ netdev_monitor_remove(struct netdev_monitor *monitor, struct netdev *netdev)
  * sets '*devnamep' to the name of a device that has changed and returns 0.
  * The caller is responsible for freeing '*devnamep' (with free()).
  *
- * If no devices have changed, sets '*devnamep' to NULL and returns EAGAIN.
- */
+ * If no devices have changed, sets '*devnamep' to NULL and returns EAGAIN. */
 int
 netdev_monitor_poll(struct netdev_monitor *monitor, char **devnamep)
 {
@@ -1596,7 +1598,7 @@ static void
 close_all_netdevs(void *aux OVS_UNUSED)
 {
     struct netdev *netdev, *next;
-    LIST_FOR_EACH_SAFE(netdev, next, struct netdev, node, &netdev_list) {
+    LIST_FOR_EACH_SAFE(netdev, next, node, &netdev_list) {
         netdev_close(netdev);
     }
 }