vswitchd: Avoid mishandling duplicate object names.
authorBen Pfaff <blp@nicira.com>
Fri, 16 Jan 2009 00:33:51 +0000 (16:33 -0800)
committerBen Pfaff <blp@nicira.com>
Fri, 16 Jan 2009 00:40:31 +0000 (16:40 -0800)
If a port was named twice in bridge.BRNAME.port, we would add two different
ports with the same name to bridge BRNAME.  Fix the problem.

Also, be more vigilant about duplicate names for other kinds of objects,
even though it should be difficult or impossible to end up with them.

vswitchd/bridge.c

index 78c1f2db491ab38658a9b94f0825c5860a9fb4da..c0d0eabc6400e5adcd573115fa65724f17766b58 100644 (file)
@@ -292,6 +292,8 @@ bridge_reconfigure(void)
     /* Get rid of deleted bridges and add new bridges. */
     svec_sort(&old_br);
     svec_sort(&new_br);
+    assert(svec_is_unique(&old_br));
+    assert(svec_is_unique(&new_br));
     LIST_FOR_EACH_SAFE (br, next, struct bridge, node, &all_bridges) {
         if (!svec_contains(&new_br, br->name)) {
             bridge_destroy(br);
@@ -321,8 +323,6 @@ bridge_reconfigure(void)
 
         bridge_fetch_dp_ifaces(br, &cur_ifaces);
         bridge_get_all_ifaces(br, &want_ifaces);
-        svec_sort(&want_ifaces);
-        svec_sort(&cur_ifaces);
         svec_diff(&want_ifaces, &cur_ifaces, NULL, NULL, &del_ifaces);
         for (i = 0; i < del_ifaces.n; i++) {
             const char *if_name = del_ifaces.names[i];
@@ -345,8 +345,6 @@ bridge_reconfigure(void)
 
         bridge_fetch_dp_ifaces(br, &cur_ifaces);
         bridge_get_all_ifaces(br, &want_ifaces);
-        svec_sort(&want_ifaces);
-        svec_sort(&cur_ifaces);
         svec_diff(&want_ifaces, &cur_ifaces, &add_ifaces, NULL, NULL);
         for (i = 0; i < add_ifaces.n; i++) {
             const char *if_name = add_ifaces.names[i];
@@ -849,7 +847,13 @@ bridge_reconfigure_one(struct bridge *br)
 
     /* Get rid of deleted ports and add new ports. */
     svec_sort(&old_ports);
+    assert(svec_is_unique(&old_ports));
     svec_sort(&new_ports);
+    if (!svec_is_unique(&new_ports)) {
+        VLOG_WARN("bridge %s: %s specified twice as bridge port",
+                  br->name, svec_get_duplicate(&new_ports));
+        svec_unique(&new_ports);
+    }
     for (i = 0; i < br->n_ports; ) {
         struct port *port = br->ports[i];
         if (!svec_contains(&new_ports, port->name)) {
@@ -955,6 +959,8 @@ bridge_get_all_ifaces(const struct bridge *br, struct svec *ifaces)
             svec_add(ifaces, iface->name);
         }
     }
+    svec_sort(ifaces);
+    assert(svec_is_unique(ifaces));
 }
 
 static bool
@@ -1050,6 +1056,15 @@ bridge_fetch_dp_ifaces(struct bridge *br, struct svec *iface_names)
     }
     retval = 0;
 
+    if (iface_names) {
+        svec_sort(iface_names);
+        if (!svec_is_unique(iface_names)) {
+            VLOG_WARN("datapath nl:%d reported interface named %s twice",
+                      br->dp_idx, svec_get_duplicate(iface_names));
+            svec_unique(iface_names);
+        }
+    }
+
 done:
     vconn_close(vconn);
     ofpbuf_delete(reply);
@@ -2618,7 +2633,9 @@ mirror_reconfigure(struct bridge *br)
 
     /* Get rid of deleted mirrors and add new mirrors. */
     svec_sort(&old_mirrors);
+    assert(svec_is_unique(&old_mirrors));
     svec_sort(&new_mirrors);
+    assert(svec_is_unique(&new_mirrors));
     for (i = 0; i < MAX_MIRRORS; i++) {
         struct mirror *m = br->mirrors[i];
         if (m && !svec_contains(&new_mirrors, m->name)) {
@@ -2714,8 +2731,7 @@ prune_ports(struct mirror *m, struct svec *ports)
     struct svec tmp;
     size_t i;
 
-    svec_sort(ports);
-    svec_unique(ports);
+    svec_sort_unique(ports);
 
     svec_init(&tmp);
     for (i = 0; i < ports->n; i++) {
@@ -2739,8 +2755,7 @@ prune_vlans(struct mirror *m, struct svec *vlan_strings, int **vlans)
     /* This isn't perfect: it won't combine "0" and "00", and the textual sort
      * order won't give us numeric sort order.  But that's good enough for what
      * we need right now. */
-    svec_sort(vlan_strings);
-    svec_unique(vlan_strings);
+    svec_sort_unique(vlan_strings);
 
     *vlans = xmalloc(sizeof *vlans * vlan_strings->n);
     n_vlans = 0;