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 66b957e1091a4a001031a6443f970f300e04ca38..69004bc43692bf013769163919d772fee227aae0 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 9880e8250b5de82ecb81112c3117fa398fa81122..56c54f5f09c06d303e3fe7736674b6c13a0c762d 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 a8dc8546643494215bf179bd57fd73b0b48fb371..72090d0207d7292b953170a6f3016ec72fd80ebb 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 bb77d589658de070a0bf25b6be1e0a02e2ce75e5..6dda8fb95521d746d1e9af7ae4c4e5ed40f371be 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 88ddd9968602cd711543c4a8ecfb9e5da9ec0049..d68e4740a65ce434b75811a61afcc8cdb696eeb3 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 fc03a1226565c836b10eb8c12200d1e504b741dd..507c70ce19f28a01d00b97db2dfe2ae200799325 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 417ce96a9ad8ef02fef5cb4ace5619af970744af..5df97b9137b2eec379d6932aa0e813182b9d0025 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 da3652b95a06a329681b0aaadba648f96b315dfa..f5e010ba6ea559cc954e07ccfa1029acb97e598d 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">