netdev: do not allow devices to be opened with conflicting types netdev
authorThadeu Lima de Souza Cascardo <cascardo@redhat.com>
Tue, 5 Jul 2016 14:41:24 +0000 (11:41 -0300)
committerThadeu Lima de Souza Cascardo <cascardo@redhat.com>
Wed, 27 Jul 2016 14:59:01 +0000 (11:59 -0300)
When a device is already opened, netdev_open should verify that the types match,
or else return an error.

Otherwise, users might expect to open a device with a certain type and get a
handle belonging to a different type.

This also prevents certain conflicting configurations that would have a port of
a certain type in the database and one of a different type on the system.

For example, when adding an interface with a type other than system, and there
is already a system interface with the same name, as the routing table will hold
a reference to that system interface, some conflicts will arise. The netdev will
be opened with the incorrect type and that will make vswitchd remove it, but
adding it again will fail as it already exists. Failing earlier prevents some
vswitchd loops in reconfiguring the interface.

Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@redhat.com>
lib/netdev.c

index 31a6a46..f0dcfc8 100644 (file)
@@ -339,7 +339,8 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp)
     if (!netdev) {
         struct netdev_registered_class *rc;
 
-        rc = netdev_lookup_class(type && type[0] ? type : "system");
+        type = type && type[0] ? type : "system";
+        rc = netdev_lookup_class(type);
         if (rc && ovs_refcount_try_ref_rcu(&rc->refcnt)) {
             netdev = rc->class->alloc();
             if (netdev) {
@@ -376,6 +377,11 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp)
                       name, type);
             error = EAFNOSUPPORT;
         }
+    } else if (type && strcmp(type, netdev_get_type(netdev))) {
+        VLOG_WARN("trying to create netdev %s of different type %s,"
+                  " already is %s\n",
+                  name, type, netdev_get_type(netdev));
+        error = EEXIST;
     } else {
         error = 0;
     }