brcompat: Add support for bonded interfaces; avoid multiple cfg_read() call.s
authorBen Pfaff <blp@nicira.com>
Tue, 7 Apr 2009 18:10:56 +0000 (11:10 -0700)
committerBen Pfaff <blp@nicira.com>
Tue, 7 Apr 2009 18:16:30 +0000 (11:16 -0700)
Bonded interfaces have to be looked up under the bonding.* hierarchy, but
the code here didn't know about that.  Also, this was calling cfg_read()
and cfg_write() for every interface to be deleted, which means that our
set of bridges and interfaces could change while we were iterating.  In
theory, they shouldn't have, since the file was locked, but that
assumption still made me nervous so I eliminated it.

vswitchd/brcompatd.c

index 6e8b18c1b2c5b20ec97de036eb4cc6eb7c367bab..8050b0e429ebf2631dc02f022b78375f9075892e 100644 (file)
@@ -203,8 +203,7 @@ prune_ports(void)
 {
     int i, j;
     int error;
-    struct svec bridges;
-    bool pruned = false;
+    struct svec bridges, delete;
 
     if (cfg_lock(NULL, 0)) {
         /* Couldn't lock config file. */
@@ -212,37 +211,69 @@ prune_ports(void)
     }
 
     svec_init(&bridges);
+    svec_init(&delete);
     cfg_get_subsections(&bridges, "bridge");
-    
     for (i=0; i<bridges.n; i++) {
         const char *br_name = bridges.names[i];
-        struct svec ports;
+        struct svec ports, ifaces;
+
         svec_init(&ports);
 
+        /* Get all the interfaces for the given bridge, breaking bonded
+         * interfaces down into their constituent parts. */
+        svec_init(&ifaces);
         cfg_get_all_keys(&ports, "bridge.%s.port", br_name);
         for (j=0; j<ports.n; j++) {
             const char *port_name = ports.names[j];
+            if (cfg_has_section("bonding.%s", port_name)) {
+                struct svec slaves;
+                svec_init(&slaves);
+                cfg_get_all_keys(&slaves, "bonding.%s.slave", port_name);
+                svec_append(&ifaces, &slaves);
+                svec_destroy(&slaves);
+            } else {
+                svec_add(&ifaces, port_name);
+            }
+        }
+        svec_destroy(&ports);
+
+        /* Check that the interfaces exist. */
+        for (j = 0; j < ifaces.n; j++) {
+            const char *iface_name = ifaces.names[j];
             enum netdev_flags flags;
 
-            error = netdev_nodev_get_flags(port_name, &flags);
+            error = netdev_nodev_get_flags(iface_name, &flags);
             if (error == ENODEV) {
-                VLOG_DBG_RL(&rl, "removing dead port %s from %s", 
-                        port_name, br_name);
-                modify_config(br_name, port_name, BMC_DEL_PORT);
-                pruned = true;
+                VLOG_DBG_RL(&rl, "removing dead interface %s from %s", 
+                        iface_name, br_name);
+                svec_add(&delete, iface_name);
             } else if (error) {
-                VLOG_DBG_RL(&rl, "unknown error %d on port %s from %s", 
-                        error, port_name, br_name);
+                VLOG_DBG_RL(&rl, "unknown error %d on interface %s from %s", 
+                        error, iface_name, br_name);
             }
         }
+        svec_destroy(&ifaces);
     }
+    svec_destroy(&bridges);
 
-    cfg_unlock();
+    if (delete.n) {
+        size_t i;
+
+        for (i = 0; i < delete.n; i++) {
+            cfg_del_match("bridge.*.port=%s", delete.names[i]);
+            cfg_del_match("bonding.*.slave=%s", delete.names[i]);
+        }
+        cfg_write();
+        cfg_read();
+
+        cfg_unlock();
 
-    if (pruned) {
         /* Ask vswitchd to reconfigure itself. */
         force_reconfigure();
+    } else {
+        cfg_unlock();
     }
+    svec_destroy(&delete);
 }
 
 /* Modify the existing configuration according to 'act'.  The configuration