netdev-linux: Check notifications are for netdev-linux device.
[sliver-openvswitch.git] / lib / netdev.c
index ddd6e92..3102e6e 100644 (file)
@@ -45,6 +45,7 @@ static const struct netdev_class *base_netdev_classes[] = {
     &netdev_linux_class,
     &netdev_tap_class,
     &netdev_gre_class,
+    &netdev_patch_class,
 };
 
 static struct shash netdev_classes = SHASH_INITIALIZER(&netdev_classes);
@@ -59,7 +60,7 @@ static struct list netdev_list = LIST_INITIALIZER(&netdev_list);
  * additional log messages. */
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
 
-static void close_all_netdevs(void *aux UNUSED);
+static void close_all_netdevs(void *aux OVS_UNUSED);
 static int restore_flags(struct netdev *netdev);
 void update_device_args(struct netdev_dev *, const struct shash *args);
 
@@ -89,9 +90,9 @@ netdev_run(void)
 {
     struct shash_node *node;
     SHASH_FOR_EACH(node, &netdev_classes) {
-        const struct netdev_class *class = node->data;
-        if (class->run) {
-            class->run();
+        const struct netdev_class *netdev_class = node->data;
+        if (netdev_class->run) {
+            netdev_class->run();
         }
     }
 }
@@ -105,9 +106,9 @@ netdev_wait(void)
 {
     struct shash_node *node;
     SHASH_FOR_EACH(node, &netdev_classes) {
-        const struct netdev_class *class = node->data;
-        if (class->wait) {
-            class->wait();
+        const struct netdev_class *netdev_class = node->data;
+        if (netdev_class->wait) {
+            netdev_class->wait();
         }
     }
 }
@@ -434,6 +435,14 @@ netdev_exists(const char *name)
     }
 }
 
+/* Returns true if a network device named 'name' is currently opened,
+ * otherwise false. */
+bool
+netdev_is_open(const char *name)
+{
+    return !!shash_find_data(&netdev_dev_shash, name);
+}
+
 /*  Clears 'svec' and enumerates the names of all known network devices. */
 int
 netdev_enumerate(struct svec *svec)
@@ -472,17 +481,23 @@ netdev_enumerate(struct svec *svec)
  * guaranteed to contain at least ETH_TOTAL_MIN bytes.  Otherwise, returns a
  * positive errno value.  Returns EAGAIN immediately if no packet is ready to
  * be returned.
+ *
+ * Some network devices may not implement support for this function.  In such
+ * cases this function will always return EOPNOTSUPP.
  */
 int
 netdev_recv(struct netdev *netdev, struct ofpbuf *buffer)
 {
+    int (*recv)(struct netdev *, void *, size_t);
     int retval;
 
     assert(buffer->size == 0);
     assert(ofpbuf_tailroom(buffer) >= ETH_TOTAL_MIN);
 
-    retval = netdev_get_dev(netdev)->netdev_class->recv(netdev, buffer->data,
-             ofpbuf_tailroom(buffer));
+    recv = netdev_get_dev(netdev)->netdev_class->recv;
+    retval = (recv
+              ? (recv)(netdev, buffer->data, ofpbuf_tailroom(buffer))
+              : -EOPNOTSUPP);
     if (retval >= 0) {
         COVERAGE_INC(netdev_received);
         buffer->size += retval;
@@ -500,14 +515,22 @@ netdev_recv(struct netdev *netdev, struct ofpbuf *buffer)
 void
 netdev_recv_wait(struct netdev *netdev)
 {
-    netdev_get_dev(netdev)->netdev_class->recv_wait(netdev);
+    void (*recv_wait)(struct netdev *);
+
+    recv_wait = netdev_get_dev(netdev)->netdev_class->recv_wait;
+    if (recv_wait) {
+        recv_wait(netdev);
+    }
 }
 
 /* Discards all packets waiting to be received from 'netdev'. */
 int
 netdev_drain(struct netdev *netdev)
 {
-    return netdev_get_dev(netdev)->netdev_class->drain(netdev);
+    int (*drain)(struct netdev *);
+
+    drain = netdev_get_dev(netdev)->netdev_class->drain;
+    return drain ? drain(netdev) : 0;
 }
 
 /* Sends 'buffer' on 'netdev'.  Returns 0 if successful, otherwise a positive
@@ -518,12 +541,18 @@ netdev_drain(struct netdev *netdev)
  * The caller retains ownership of 'buffer' in all cases.
  *
  * The kernel maintains a packet transmission queue, so the caller is not
- * expected to do additional queuing of packets. */
+ * expected to do additional queuing of packets.
+ *
+ * Some network devices may not implement support for this function.  In such
+ * cases this function will always return EOPNOTSUPP. */
 int
 netdev_send(struct netdev *netdev, const struct ofpbuf *buffer)
 {
-    int error = netdev_get_dev(netdev)->netdev_class->send(netdev, 
-            buffer->data, buffer->size);
+    int (*send)(struct netdev *, const void *, size_t);
+    int error;
+
+    send = netdev_get_dev(netdev)->netdev_class->send;
+    error = send ? (send)(netdev, buffer->data, buffer->size) : EOPNOTSUPP;
     if (!error) {
         COVERAGE_INC(netdev_sent);
     }
@@ -540,7 +569,12 @@ netdev_send(struct netdev *netdev, const struct ofpbuf *buffer)
 void
 netdev_send_wait(struct netdev *netdev)
 {
-    return netdev_get_dev(netdev)->netdev_class->send_wait(netdev);
+    void (*send_wait)(struct netdev *);
+
+    send_wait = netdev_get_dev(netdev)->netdev_class->send_wait;
+    if (send_wait) {
+        send_wait(netdev);
+    }
 }
 
 /* Attempts to set 'netdev''s MAC address to 'mac'.  Returns 0 if successful,
@@ -975,12 +1009,12 @@ exit:
  * the refcount drops to zero.  */
 void
 netdev_dev_init(struct netdev_dev *netdev_dev, const char *name,
-                const struct netdev_class *class_)
+                const struct netdev_class *netdev_class)
 {
     assert(!shash_find(&netdev_dev_shash, name));
 
     memset(netdev_dev, 0, sizeof *netdev_dev);
-    netdev_dev->netdev_class = class_;
+    netdev_dev->netdev_class = netdev_class;
     netdev_dev->name = xstrdup(name);
     netdev_dev->node = shash_add(&netdev_dev_shash, name, netdev_dev);
 }
@@ -1017,6 +1051,13 @@ netdev_dev_get_type(const struct netdev_dev *netdev_dev)
     return netdev_dev->netdev_class->type;
 }
 
+/* Returns the class associated with 'netdev_dev'. */
+const struct netdev_class *
+netdev_dev_get_class(const struct netdev_dev *netdev_dev)
+{
+    return netdev_dev->netdev_class;
+}
+
 /* Returns the name of 'netdev_dev'.
  *
  * The caller must not free the returned value. */
@@ -1035,19 +1076,19 @@ netdev_dev_from_name(const char *name)
     return shash_find_data(&netdev_dev_shash, name);
 }
 
-/* Fills 'device_list' with devices that match 'class'.
+/* Fills 'device_list' with devices that match 'netdev_class'.
  *
  * The caller is responsible for initializing and destroying 'device_list'
  * but the contained netdev_devs must not be freed. */
 void
-netdev_dev_get_devices(const struct netdev_class *class_,
+netdev_dev_get_devices(const struct netdev_class *netdev_class,
                        struct shash *device_list)
 {
     struct shash_node *node;
     SHASH_FOR_EACH (node, &netdev_dev_shash) {
         struct netdev_dev *dev = node->data;
 
-        if (dev->netdev_class == class_) {
+        if (dev->netdev_class == netdev_class) {
             shash_add(device_list, node->name, node->data);
         }
     }
@@ -1265,7 +1306,7 @@ restore_flags(struct netdev *netdev)
 /* Close all netdevs on shutdown so they can do any needed cleanup such as
  * destroying devices, restoring flags, etc. */
 static void
-close_all_netdevs(void *aux UNUSED)
+close_all_netdevs(void *aux OVS_UNUSED)
 {
     struct netdev *netdev, *next;
     LIST_FOR_EACH_SAFE(netdev, next, struct netdev, node, &netdev_list) {