vswitch: Keep existing datapaths when starting up.
authorBen Pfaff <blp@nicira.com>
Fri, 6 Mar 2009 22:12:36 +0000 (14:12 -0800)
committerBen Pfaff <blp@nicira.com>
Fri, 6 Mar 2009 22:12:36 +0000 (14:12 -0800)
Until now, vswitchd has deleted all existing datapaths when it started up,
and then re-created the ones that are actually configured.  This is a very
"clean", conservative design, but it has undesirable effects in practice.
In particular, if any datapath has a local port with an IP address
configured on it, then deleting the datapath and recreating it will drop
that IP address, which can mean that your machine just lost connectivity
to the outside world.

So, with this commit, now vswitchd only deletes datapaths at startup that
don't have configured bridges, preserving local port IP addresses.

vswitchd/bridge.c
vswitchd/vswitchd.c

index 60ba99114d439a23ef88de10189c1e767e6abbad..0d1aedba8926c58c5f3d3917c120645d628536b8 100644 (file)
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <arpa/inet.h>
 #include <inttypes.h>
+#include <net/if.h>
 #include <openflow/openflow.h>
 #include <openflow/openflow-netlink.h>
 #include <signal.h>
@@ -246,6 +247,7 @@ static struct iface *iface_from_dp_ifidx(const struct bridge *,
 \f
 /* Public functions. */
 
+/* The caller must already have called cfg_read(). */
 void
 bridge_init(void)
 {
@@ -259,13 +261,19 @@ bridge_init(void)
         sprintf(devname, "dp%d", i);
         retval = dpif_open(devname, &dpif);
         if (!retval) {
-            dpif_delete(&dpif);
+            char dpif_name[IF_NAMESIZE];
+            if (dpif_get_name(&dpif, dpif_name, sizeof dpif_name)
+                || !cfg_has("bridge.%s.port", dpif_name)) {
+                dpif_delete(&dpif);
+            }
             dpif_close(&dpif);
         } else if (retval != ENODEV) {
             VLOG_ERR("failed to delete datapath nl:%d: %s",
                      i, strerror(retval));
         }
     }
+
+    bridge_reconfigure();
 }
 
 static bool
@@ -585,7 +593,16 @@ bridge_create(const char *name)
     br = xcalloc(1, sizeof *br);
 
     error = dpif_create(name, &br->dpif);
-    if (error) {
+    if (error == EEXIST) {
+        error = dpif_open(name, &br->dpif);
+        if (error) {
+            VLOG_ERR("datapath %s already exists but cannot be opened: %s",
+                     name, strerror(error));
+            free(br);
+            return NULL;
+        }
+        dpif_flow_flush(&br->dpif);
+    } else if (error) {
         VLOG_ERR("failed to create datapath %s: %s", name, strerror(error));
         free(br);
         return NULL;
index c83a22bf3ccee599e998fd0b9ec97348a3f6ec99..1890b091111a2183ac80124f1113536848072ad7 100644 (file)
@@ -87,8 +87,8 @@ main(int argc, char *argv[])
         ofp_fatal(retval, "could not listen for vlog connections");
     }
 
+    cfg_read();
     bridge_init();
-    reconfigure();
 
     for (;;) {
         if (signal_poll(sighup)) {