This commit adds function in lib/netdev.c to check that the interface name
is not the same as any of the registered vport providers' dpif_port name
(e.g. gre_system) or the datapath's internal port name (e.g. ovs-system).

This function is called in iface_do_create() function in vswitchd/bridge.c.
If there is a name conflict, no interface and of_port will be created. And
the warning will be given in the ovs-vswitchd.log

Signed-off-by: Alex Wang <al...@nicira.com>
---
 lib/netdev-vport.c |   15 ++++++++++---
 lib/netdev-vport.h |    3 ++-
 lib/netdev.c       |   41 ++++++++++++++++++++++++++++++++++
 lib/netdev.h       |    1 +
 tests/ovs-vsctl.at |   62 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 vswitchd/bridge.c  |    5 +++++
 6 files changed, 123 insertions(+), 4 deletions(-)

diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 699ed71..d63c6c7 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -115,6 +115,17 @@ netdev_vport_needs_dst_port(const struct netdev *dev)
 }
 
 const char *
+netdev_class_get_dpif_port(const struct netdev_class *class)
+{
+    const char *dpif_port;
+
+    dpif_port = (is_vport_class(class)
+                 ? vport_class_cast(class)->dpif_port
+                 : NULL);
+    return dpif_port;
+}
+
+const char *
 netdev_vport_get_dpif_port(const struct netdev *netdev)
 {
     const char *dpif_port;
@@ -136,9 +147,7 @@ netdev_vport_get_dpif_port(const struct netdev *netdev)
         return dpif_port_combined;
     } else {
         const struct netdev_class *class = netdev_get_class(netdev);
-        dpif_port = (is_vport_class(class)
-                     ? vport_class_cast(class)->dpif_port
-                     : NULL);
+        dpif_port = netdev_class_get_dpif_port(class);
     }
 
     return dpif_port ? dpif_port : netdev_get_name(netdev);
diff --git a/lib/netdev-vport.h b/lib/netdev-vport.h
index c907b0c..7eaf9b2 100644
--- a/lib/netdev-vport.h
+++ b/lib/netdev-vport.h
@@ -22,6 +22,7 @@
 struct dpif_linux_vport;
 struct dpif_flow_stats;
 struct netdev;
+struct netdev_class;
 struct netdev_stats;
 
 void netdev_vport_tunnel_register(void);
@@ -37,5 +38,5 @@ void netdev_vport_inc_tx(const struct netdev *,
                          const struct dpif_flow_stats *);
 
 const char *netdev_vport_get_dpif_port(const struct netdev *);
-
+const char *netdev_class_get_dpif_port(const struct netdev_class *);
 #endif /* netdev-vport.h */
diff --git a/lib/netdev.c b/lib/netdev.c
index d93526a..5b1d208 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -25,6 +25,7 @@
 #include <unistd.h>
 
 #include "coverage.h"
+#include "dpif.h"
 #include "dynamic-string.h"
 #include "fatal-signal.h"
 #include "hash.h"
@@ -200,6 +201,46 @@ netdev_enumerate_types(struct sset *types)
     }
 }
 
+/* Check that the network device name is not the same as any of the registered
+ * vport providers' dpif_port name (dpif_port is NULL if the vport provider
+ * does not define it) or the datapath internal port name (e.g. ovs-system).
+ *
+ * 0 is returned if there is no naming conflict. Otherwise, EINVAL is returned.
+ */
+int
+netdev_check_reserved_word(const char *name)
+{
+    struct shash_node *node;
+    struct sset types;
+    const char *dpif_port;
+    const char *type;
+
+    dpif_port = NULL;
+    netdev_initialize();
+    SHASH_FOR_EACH(node, &netdev_classes) {
+        dpif_port = netdev_class_get_dpif_port(node->data);
+        if (dpif_port && !strcmp(dpif_port, name)) {
+            VLOG_WARN("name \"%s\" is a reserved name (%s)",
+                      name, strerror(EINVAL));
+            return EINVAL;
+        }
+    }
+
+    sset_init(&types);
+    dp_enumerate_types(&types);
+    SSET_FOR_EACH (type, &types) {
+        if ((strstr(name, "ovs-") == name)
+            && (strstr(name, type) == (name + 4))) {
+            VLOG_WARN("name \"%s\" is a reserved name (%s)",
+                      name, strerror(EINVAL));
+            sset_destroy(&types);
+            return EINVAL;
+        }
+    }
+    sset_destroy(&types);
+    return 0;
+}
+
 /* Opens the network device named 'name' (e.g. "eth0") of the specified 'type'
  * (e.g. "system") and returns zero if successful, otherwise a positive errno
  * value.  On success, sets '*netdevp' to the new network device, otherwise to
diff --git a/lib/netdev.h b/lib/netdev.h
index 852b75d..08a6e26 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -106,6 +106,7 @@ void netdev_run(void);
 void netdev_wait(void);
 
 void netdev_enumerate_types(struct sset *types);
+int netdev_check_reserved_word(const char *name);
 
 /* Open and close. */
 int netdev_open(const char *name, const char *type, struct netdev **);
diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at
index 439bd2d..2da05b5 100644
--- a/tests/ovs-vsctl.at
+++ b/tests/ovs-vsctl.at
@@ -1185,3 +1185,65 @@ AT_CHECK([RUN_OVS_VSCTL(
    [-- list Queue])], [0], [], [], [OVS_VSCTL_CLEANUP])
 OVS_VSCTL_CLEANUP
 AT_CLEANUP
+
+dnl ----------------------------------------------------------------------
+AT_BANNER([ovs-vsctl add-port -- reserved port names])
+
+AT_SETUP([add-port -- reserved names 1])
+OVS_VSWITCHD_START
+
+# Test creating all reserved port names
+m4_foreach(
+[reserved_name],
+[[ovs-netdev],
+[ovs-dummy],
+[gre_system],
+[gre64_system],
+[lisp_system],
+[vxlan_system]],
+[
+# Try creating the port
+AT_CHECK([ovs-vsctl add-port br0 reserved_name], [0], [], [])
+# Detect the warning log message
+AT_CHECK([sed -n "s/^.*\(|netdev|WARN|.*\)$/\1/p" ovs-vswitchd.log], [0], [dnl
+|netdev|WARN|name "reserved_name" is a reserved name (Invalid argument)
+])
+# Delete the warning log message
+AT_CHECK([sed "/|netdev|WARN|/d" ovs-vswitchd.log > ovs-vswitchd.log], [0], 
[], [])
+# Delete the port
+AT_CHECK([ovs-vsctl del-port br0 reserved_name], [0], [], [])])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([add-port -- reserved names 2])
+# Creates all type of tunnel ports
+OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=gre \
+                    options:remote_ip=1.1.1.1 ofport_request=1\
+                    -- add-port br0 p2 -- set Interface p2 type=gre64 \
+                    options:local_ip=2.2.2.2 options:remote_ip=1.1.1.1 \
+                    ofport_request=2 \
+                    -- add-port br0 p3 -- set Interface p3 type=lisp \
+                    options:remote_ip=2.2.2.2 ofport_request=3 \
+                    -- add-port br0 p4 -- set Interface p4 type=vxlan \
+                    options:remote_ip=2.2.2.2 ofport_request=4])
+
+# Test creating all reserved tunnel port names
+m4_foreach(
+[reserved_name],
+[[gre_system],
+[gre64_system],
+[lisp_system],
+[vxlan_system]],
+[
+# Try creating the port
+AT_CHECK([ovs-vsctl add-port br0 reserved_name], [0], [], [])
+# Detect the warning log message
+AT_CHECK([sed -n "s/^.*\(|netdev|WARN|.*\)$/\1/p" ovs-vswitchd.log], [0], [dnl
+|netdev|WARN|name "reserved_name" is a reserved name (Invalid argument)
+])
+# Delete the warning log message
+AT_CHECK([sed "/|netdev|WARN|/d" ovs-vswitchd.log > ovs-vswitchd.log], [0], 
[], [])
+# Delete the port
+AT_CHECK([ovs-vsctl del-port br0 reserved_name], [0], [], [])])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index cf26e87..beb1462 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -1418,6 +1418,11 @@ iface_do_create(const struct bridge *br,
     struct netdev *netdev;
     int error;
 
+    error = netdev_check_reserved_word(iface_cfg->name);
+    if (error) {
+        goto error;
+    }
+
     error = netdev_open(iface_cfg->name,
                         iface_get_type(iface_cfg, br->cfg), &netdev);
     if (error) {
-- 
1.7.9.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to