netdev-linux: Check notifications are for netdev-linux device.
authorJesse Gross <jesse@nicira.com>
Tue, 30 Mar 2010 22:39:20 +0000 (18:39 -0400)
committerJesse Gross <jesse@nicira.com>
Mon, 19 Apr 2010 13:11:57 +0000 (09:11 -0400)
When receiving a change notification from rtnetlink we checked whether
a netdev of that name existed and if so tried to handle it.  This also
checks that the type of the device is one handled by netdev-linux.

lib/netdev-linux.c
lib/netdev-provider.h
lib/netdev.c

index 2941bf98e32ad1d228f71e6f0675d1c4b52c9a55..1b69a20d610e236978eb3266f7d9ad8ea56b6c2e 100644 (file)
@@ -157,6 +157,7 @@ static struct rtnetlink_notifier netdev_linux_poll_notifier;
  * additional log messages. */
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
 
+static int netdev_linux_init(void);
 static int if_up(const char *name);
 static int destroy_gre(const char *name);
 static int netdev_linux_do_ethtool(const char *name, struct ethtool_cmd *,
@@ -178,21 +179,28 @@ static int set_etheraddr(const char *netdev_name, int hwaddr_family,
 static int get_stats_via_netlink(int ifindex, struct netdev_stats *stats);
 static int get_stats_via_proc(const char *netdev_name, struct netdev_stats *stats);
 
+static bool
+is_netdev_linux_class(const struct netdev_class *netdev_class)
+{
+    return netdev_class->init == netdev_linux_init;
+}
+
 static struct netdev_dev_linux *
 netdev_dev_linux_cast(const struct netdev_dev *netdev_dev)
 {
-    const char *type = netdev_dev_get_type(netdev_dev);
-    assert(!strcmp(type, "system") || !strcmp(type, "tap")
-            || !strcmp(type, "gre") || !strcmp(type, "patch"));
+    const struct netdev_class *netdev_class = netdev_dev_get_class(netdev_dev);
+    assert(is_netdev_linux_class(netdev_class));
+
     return CONTAINER_OF(netdev_dev, struct netdev_dev_linux, netdev_dev);
 }
 
 static struct netdev_linux *
 netdev_linux_cast(const struct netdev *netdev)
 {
-    const char *type = netdev_get_type(netdev);
-    assert(!strcmp(type, "system") || !strcmp(type, "tap")
-            || !strcmp(type, "gre") || !strcmp(type, "patch"));
+    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));
+
     return CONTAINER_OF(netdev, struct netdev_linux, netdev);
 }
 
@@ -230,8 +238,13 @@ netdev_linux_cache_cb(const struct rtnetlink_change *change,
     if (change) {
         struct netdev_dev *base_dev = netdev_dev_from_name(change->ifname);
         if (base_dev) {
-            dev = netdev_dev_linux_cast(base_dev);
-            dev->cache_valid = 0;
+            const struct netdev_class *netdev_class =
+                                                netdev_dev_get_class(base_dev);
+
+            if (is_netdev_linux_class(netdev_class)) {
+                dev = netdev_dev_linux_cast(base_dev);
+                dev->cache_valid = 0;
+            }
         }
     } else {
         struct shash device_shash;
index aac482b02626a1adf6676dcd42a2e85f78841fc9..18ec1ab6e380c5a7e0c30d75ccaadbba9781edaf 100644 (file)
@@ -52,6 +52,7 @@ void netdev_dev_init(struct netdev_dev *, const char *name,
                      const struct netdev_class *);
 void netdev_dev_uninit(struct netdev_dev *, bool destroy);
 const char *netdev_dev_get_type(const struct netdev_dev *);
+const struct netdev_class *netdev_dev_get_class(const struct netdev_dev *);
 const char *netdev_dev_get_name(const struct netdev_dev *);
 struct netdev_dev *netdev_dev_from_name(const char *name);
 void netdev_dev_get_devices(const struct netdev_class *,
index d8fd7e44b54520fbcfd6e550d83c5372511cde60..3102e6e3d8c48ca7ba931ad8085322c314242f16 100644 (file)
@@ -1051,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. */