vswitchd: Move fail-mode config to Bridge table
authorJustin Pettit <jpettit@nicira.com>
Fri, 16 Jul 2010 03:56:43 +0000 (20:56 -0700)
committerJustin Pettit <jpettit@nicira.com>
Sat, 31 Jul 2010 04:26:54 +0000 (21:26 -0700)
Configuration of the fail-mode was an attribute of the Controller table.
However, it makes more sense as an attribute of the Bridge table, since
the behavior defines what a bridge should do if it can't connect to
*any* controller.  This commit makes the move.

ofproto/ofproto.c
ofproto/ofproto.h
tests/ovs-vsctl.at
utilities/ovs-openflowd.c
utilities/ovs-vsctl.c
vswitchd/bridge.c
vswitchd/vswitch.ovsschema
vswitchd/vswitch.xml

index 66b957e..69004bc 100644 (file)
@@ -274,6 +274,7 @@ struct ofproto {
     /* OpenFlow connections. */
     struct hmap controllers;   /* Controller "struct ofconn"s. */
     struct list all_conns;     /* Contains "struct ofconn"s. */
+    enum ofproto_fail_mode fail_mode;
     struct pvconn **listeners;
     size_t n_listeners;
     struct pvconn **snoops;
@@ -586,13 +587,40 @@ update_in_band_remotes(struct ofproto *ofproto)
     free(addrs);
 }
 
+static void
+update_fail_open(struct ofproto *p)
+{
+    struct ofconn *ofconn;
+
+    if (!hmap_is_empty(&p->controllers)
+            && p->fail_mode == OFPROTO_FAIL_STANDALONE) {
+        struct rconn **rconns;
+        size_t n;
+
+        if (!p->fail_open) {
+            p->fail_open = fail_open_create(p, p->switch_status);
+        }
+
+        n = 0;
+        rconns = xmalloc(hmap_count(&p->controllers) * sizeof *rconns);
+        HMAP_FOR_EACH (ofconn, struct ofconn, hmap_node, &p->controllers) {
+            rconns[n++] = ofconn->rconn;
+        }
+
+        fail_open_set_controllers(p->fail_open, rconns, n);
+        /* p->fail_open takes ownership of 'rconns'. */
+    } else {
+        fail_open_destroy(p->fail_open);
+        p->fail_open = NULL;
+    }
+}
+
 void
 ofproto_set_controllers(struct ofproto *p,
                         const struct ofproto_controller *controllers,
                         size_t n_controllers)
 {
     struct shash new_controllers;
-    enum ofproto_fail_mode fail_mode;
     struct ofconn *ofconn, *next;
     bool ss_exists;
     size_t i;
@@ -607,7 +635,6 @@ ofproto_set_controllers(struct ofproto *p,
         }
     }
 
-    fail_mode = OFPROTO_FAIL_STANDALONE;
     ss_exists = false;
     HMAP_FOR_EACH_SAFE (ofconn, next, struct ofconn, hmap_node,
                         &p->controllers) {
@@ -621,36 +648,13 @@ ofproto_set_controllers(struct ofproto *p,
             if (ofconn->ss) {
                 ss_exists = true;
             }
-            if (c->fail == OFPROTO_FAIL_SECURE) {
-                fail_mode = OFPROTO_FAIL_SECURE;
-            }
         }
     }
     shash_destroy(&new_controllers);
 
     update_in_band_remotes(p);
 
-    if (!hmap_is_empty(&p->controllers)
-        && fail_mode == OFPROTO_FAIL_STANDALONE) {
-        struct rconn **rconns;
-        size_t n;
-
-        if (!p->fail_open) {
-            p->fail_open = fail_open_create(p, p->switch_status);
-        }
-
-        n = 0;
-        rconns = xmalloc(hmap_count(&p->controllers) * sizeof *rconns);
-        HMAP_FOR_EACH (ofconn, struct ofconn, hmap_node, &p->controllers) {
-            rconns[n++] = ofconn->rconn;
-        }
-
-        fail_open_set_controllers(p->fail_open, rconns, n);
-        /* p->fail_open takes ownership of 'rconns'. */
-    } else {
-        fail_open_destroy(p->fail_open);
-        p->fail_open = NULL;
-    }
+    update_fail_open(p);
 
     if (!hmap_is_empty(&p->controllers) && !ss_exists) {
         ofconn = CONTAINER_OF(hmap_first(&p->controllers),
@@ -660,6 +664,13 @@ ofproto_set_controllers(struct ofproto *p,
     }
 }
 
+void
+ofproto_set_fail_mode(struct ofproto *p, enum ofproto_fail_mode fail_mode)
+{
+    p->fail_mode = fail_mode;
+    update_fail_open(p);
+}
+
 /* Drops the connections between 'ofproto' and all of its controllers, forcing
  * them to reconnect. */
 void
index 9880e82..56c54f5 100644 (file)
@@ -72,7 +72,6 @@ struct ofproto_controller {
     char *target;               /* e.g. "tcp:127.0.0.1" */
     int max_backoff;            /* Maximum reconnection backoff, in seconds. */
     int probe_interval;         /* Max idle time before probing, in seconds. */
-    enum ofproto_fail_mode fail; /* Controller failure handling mode. */
     enum ofproto_band band;      /* In-band or out-of-band? */
 
     /* Discovery options. */
@@ -104,6 +103,7 @@ bool ofproto_is_alive(const struct ofproto *);
 void ofproto_set_datapath_id(struct ofproto *, uint64_t datapath_id);
 void ofproto_set_controllers(struct ofproto *,
                              const struct ofproto_controller *, size_t n);
+void ofproto_set_fail_mode(struct ofproto *, enum ofproto_fail_mode fail_mode);
 void ofproto_reconnect_controllers(struct ofproto *);
 void ofproto_set_extra_in_band_remotes(struct ofproto *,
                                        const struct sockaddr_in *, size_t n);
index a8dc854..72090d0 100644 (file)
@@ -522,6 +522,7 @@ controller          : []
 datapath_id         : []
 datapath_type       : ""
 external_ids        : {}
+fail_mode           : []
 flood_vlans         : []
 mirrors             : []
 name                : "br0"
@@ -718,6 +719,7 @@ controller          : []
 datapath_id         : []
 datapath_type       : ""
 external_ids        : {}
+fail_mode           : []
 flood_vlans         : []
 mirrors             : []
 name                : "br0"
index bb77d58..6dda8fb 100644 (file)
@@ -53,6 +53,7 @@ struct ofsettings {
     /* Controller configuration. */
     struct ofproto_controller *controllers;
     size_t n_controllers;
+    enum ofproto_fail_mode fail_mode;
 
     /* Datapath. */
     uint64_t datapath_id;       /* Datapath ID. */
@@ -165,6 +166,7 @@ main(int argc, char *argv[])
         ovs_fatal(error, "failed to configure STP");
     }
     ofproto_set_controllers(ofproto, s.controllers, s.n_controllers);
+    ofproto_set_fail_mode(ofproto, s.fail_mode);
 
     daemonize_complete();
 
@@ -265,12 +267,12 @@ parse_options(int argc, char *argv[], struct ofsettings *s)
     controller_opts.target = NULL;
     controller_opts.max_backoff = 8;
     controller_opts.probe_interval = 5;
-    controller_opts.fail = OFPROTO_FAIL_STANDALONE;
     controller_opts.band = OFPROTO_IN_BAND;
     controller_opts.accept_re = NULL;
     controller_opts.update_resolv_conf = true;
     controller_opts.rate_limit = 0;
     controller_opts.burst_limit = 0;
+    s->fail_mode = OFPROTO_FAIL_STANDALONE;
     s->datapath_id = 0;
     s->mfr_desc = NULL;
     s->hw_desc = NULL;
@@ -329,10 +331,10 @@ parse_options(int argc, char *argv[], struct ofsettings *s)
 
         case OPT_FAIL_MODE:
             if (!strcmp(optarg, "open") || !strcmp(optarg, "standalone")) {
-                controller_opts.fail = OFPROTO_FAIL_STANDALONE;
+                s->fail_mode = OFPROTO_FAIL_STANDALONE;
             } else if (!strcmp(optarg, "closed")
                        || !strcmp(optarg, "secure")) {
-                controller_opts.fail = OFPROTO_FAIL_SECURE;
+                s->fail_mode = OFPROTO_FAIL_SECURE;
             } else {
                 ovs_fatal(0, "--fail argument must be \"standalone\" "
                           "or \"secure\"");
index 88ddd99..d68e474 100644 (file)
@@ -512,6 +512,7 @@ struct vsctl_bridge {
     struct ovsrec_bridge *br_cfg;
     char *name;
     struct ovsrec_controller **ctrl;
+    char *fail_mode;
     size_t n_ctrl;
     struct vsctl_bridge *parent;
     int vlan;
@@ -570,9 +571,11 @@ add_bridge(struct vsctl_info *b,
     if (parent) {
         br->ctrl = parent->br_cfg->controller;
         br->n_ctrl = parent->br_cfg->n_controller;
+        br->fail_mode = parent->br_cfg->fail_mode;
     } else {
         br->ctrl = br_cfg->controller;
         br->n_ctrl = br_cfg->n_controller;
+        br->fail_mode = br_cfg->fail_mode;
     }
     shash_add(&b->bridges, br->name, br);
     return br;
@@ -1625,57 +1628,22 @@ cmd_set_controller(struct vsctl_context *ctx)
     free_info(&info);
 }
 
-static const char *
-get_fail_mode(struct ovsrec_controller **controllers, size_t n_controllers)
-{
-    const char *fail_mode;
-    size_t i;
-
-    fail_mode = NULL;
-    for (i = 0; i < n_controllers; i++) {
-        const char *s = controllers[i]->fail_mode;
-        if (s) {
-            if (!strcmp(s, "secure")) {
-                return s;
-            } else {
-                fail_mode = s;
-            }
-        }
-    }
-
-    return fail_mode;
-}
-
 static void
 cmd_get_fail_mode(struct vsctl_context *ctx)
 {
     struct vsctl_info info;
     struct vsctl_bridge *br;
-    const char *fail_mode = NULL;
 
     get_info(ctx->ovs, &info);
     br = find_bridge(&info, ctx->argv[1], true);
 
-    fail_mode = get_fail_mode(br->ctrl, br->n_ctrl);
-
-    if (fail_mode && strlen(fail_mode)) {
-        ds_put_format(&ctx->output, "%s\n", fail_mode);
+    if (br->fail_mode && strlen(br->fail_mode)) {
+        ds_put_format(&ctx->output, "%s\n", br->fail_mode);
     }
 
     free_info(&info);
 }
 
-static void
-set_fail_mode(struct ovsrec_controller **controllers, size_t n_controllers,
-              const char *fail_mode)
-{
-    size_t i;
-
-    for (i = 0; i < n_controllers; i++) {
-        ovsrec_controller_set_fail_mode(controllers[i], fail_mode);
-    }
-}
-
 static void
 cmd_del_fail_mode(struct vsctl_context *ctx)
 {
@@ -1685,7 +1653,7 @@ cmd_del_fail_mode(struct vsctl_context *ctx)
     get_info(ctx->ovs, &info);
     br = find_real_bridge(&info, ctx->argv[1], true);
 
-    set_fail_mode(br->ctrl, br->n_ctrl, NULL);
+    ovsrec_bridge_set_fail_mode(br->br_cfg, NULL);
 
     free_info(&info);
 }
@@ -1704,10 +1672,7 @@ cmd_set_fail_mode(struct vsctl_context *ctx)
         vsctl_fatal("fail-mode must be \"standalone\" or \"secure\"");
     }
 
-    if (!br->ctrl) {
-        vsctl_fatal("no controller declared for %s", br->name);
-    }
-    set_fail_mode(br->ctrl, br->n_ctrl, fail_mode);
+    ovsrec_bridge_set_fail_mode(br->br_cfg, fail_mode);
 
     free_info(&info);
 }
index fc03a12..507c70c 100644 (file)
@@ -1423,6 +1423,7 @@ bridge_reconfigure_one(struct bridge *br)
     struct svec listeners, old_listeners;
     struct svec snoops, old_snoops;
     struct shash_node *node;
+    enum ofproto_fail_mode fail_mode;
     size_t i;
 
     /* Collect old ports. */
@@ -1491,6 +1492,13 @@ bridge_reconfigure_one(struct bridge *br)
     shash_destroy(&old_ports);
     shash_destroy(&new_ports);
 
+    /* Set the fail-mode */
+    fail_mode = !br->cfg->fail_mode
+                || !strcmp(br->cfg->fail_mode, "standalone")
+                    ? OFPROTO_FAIL_STANDALONE
+                    : OFPROTO_FAIL_SECURE;
+    ofproto_set_fail_mode(br->ofproto, fail_mode);
+
     /* Delete all flows if we're switching from connected to standalone or vice
      * versa.  (XXX Should we delete all flows if we are switching from one
      * controller to another?) */
@@ -1604,11 +1612,6 @@ bridge_reconfigure_remotes(struct bridge *br,
             oc->max_backoff = c->max_backoff ? *c->max_backoff / 1000 : 8;
             oc->probe_interval = (c->inactivity_probe
                                  ? *c->inactivity_probe / 1000 : 5);
-            oc->fail = (!c->fail_mode
-                       || !strcmp(c->fail_mode, "standalone")
-                       || !strcmp(c->fail_mode, "open")
-                       ? OFPROTO_FAIL_STANDALONE
-                       : OFPROTO_FAIL_SECURE);
             oc->band = (!c->connection_mode
                        || !strcmp(c->connection_mode, "in-band")
                        ? OFPROTO_IN_BAND
index 417ce96..5df97b9 100644 (file)
          "type": {"key": {"type": "uuid",
                           "refTable": "Controller"},
                   "min": 0, "max": "unlimited"}},
+       "fail_mode": {
+         "type": {"key": {"type": "string",
+                          "enum": ["set", ["standalone", "secure"]]},
+                  "min": 0, "max": 1}},
        "other_config": {
          "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}},
        "external_ids": {
                   "min": 0, "max": 1}},
        "inactivity_probe": {
          "type": {"key": "integer", "min": 0, "max": 1}},
-       "fail_mode": {
-         "type": {"key": {"type": "string",
-                          "enum": ["set", ["standalone", "secure"]]},
-                  "min": 0, "max": 1}},
        "discover_accept_regex": {
          "type": {"key": "string", "min": 0, "max": 1}},
        "discover_update_resolv_conf": {
index da3652b..f5e010b 100644 (file)
         will be used.
       </column>
 
+      <column name="fail_mode">
+        <p>When a controller is configured, it is, ordinarily, responsible
+          for setting up all flows on the switch.  Thus, if the connection to
+          the controller fails, no new network connections can be set up.
+          If the connection to the controller stays down long enough,
+          no packets can pass through the switch at all.  This setting
+          determines the switch's response to such a situation.  It may be set
+          to one of the following:
+          <dl>
+            <dt><code>standalone</code></dt>
+            <dd>If no message is received from the controller for three
+              times the inactivity probe interval
+              (see <ref column="inactivity_probe"/>), then Open vSwitch
+              will take over responsibility for setting up flows.  In
+              this mode, Open vSwitch causes the bridge to act like an
+              ordinary MAC-learning switch.  Open vSwitch will continue
+              to retry connecting to the controller in the background
+              and, when the connection succeeds, it will discontinue its
+              standalone behavior.</dd>
+            <dt><code>secure</code></dt>
+            <dd>Open vSwitch will not set up flows on its own when the
+              controller connection fails.  It will continue retry
+              connecting to the controller forever.</dd>
+          </dl>
+        </p>
+        <p>If this value is unset, the default is implementation-specific.</p>
+        <p>When more than one controller is configured, 
+          <ref column="fail_mode"/> is considered only when none of the
+          configured controllers can be contacted.</p>
+      </column>
+
       <column name="datapath_id">
         Reports the OpenFlow datapath ID in use.  Exactly 16 hex
         digits.  (Setting this column will have no useful effect.  Set
         assumes the connection has been broken and attempts to reconnect.
         Default is implementation-specific.
       </column>
-
-      <column name="fail_mode">
-        <p>When a controller is configured, it is, ordinarily, responsible
-          for setting up all flows on the switch.  Thus, if the connection to
-          the controller fails, no new network connections can be set up.
-          If the connection to the controller stays down long enough,
-          no packets can pass through the switch at all.  This setting
-          determines the switch's response to such a situation.  It may be set
-          to one of the following:
-          <dl>
-            <dt><code>standalone</code></dt>
-            <dd>If no message is received from the controller for three
-              times the inactivity probe interval
-              (see <ref column="inactivity_probe"/>), then Open vSwitch
-              will take over responsibility for setting up flows.  In
-              this mode, Open vSwitch causes the bridge to act like an
-              ordinary MAC-learning switch.  Open vSwitch will continue
-              to retry connecting to the controller in the background
-              and, when the connection succeeds, it will discontinue its
-              standalone behavior.</dd>
-            <dt><code>secure</code></dt>
-            <dd>Open vSwitch will not set up flows on its own when the
-              controller connection fails.  It will continue retry
-              connecting to the controller forever.</dd>
-          </dl>
-        </p>
-        <p>If this value is unset, the default is implementation-specific.</p>
-       <p>When more than one controller is configured,
-         <ref column="fail_mode"/> is considered only when none of the
-         configured controllers can be contacted.  At that point, the bridge
-         enters secure mode if any of the controllers'
-         <ref column="fail_mode"/> is set to <code>secure</code>.  Otherwise,
-         it enters standalone mode if at least one <ref column="fail_mode"/>
-         is set to <code>standalone</code>.  If none of the
-         <ref column="fail_mode"/> values are set, the default is
-         implementation-defined.</p>
-      </column>
     </group>
 
     <group title="OpenFlow Rate Limiting">