summaryrefslogtreecommitdiff
path: root/utilities/ovs-vsctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'utilities/ovs-vsctl.c')
-rw-r--r--utilities/ovs-vsctl.c217
1 files changed, 154 insertions, 63 deletions
diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
index fe7838767..091e6bc7b 100644
--- a/utilities/ovs-vsctl.c
+++ b/utilities/ovs-vsctl.c
@@ -489,7 +489,8 @@ struct vsctl_context {
struct vsctl_bridge {
struct ovsrec_bridge *br_cfg;
char *name;
- struct ovsrec_controller *ctrl;
+ struct ovsrec_controller **ctrl;
+ size_t n_ctrl;
struct vsctl_bridge *parent;
int vlan;
};
@@ -508,7 +509,8 @@ struct vsctl_info {
struct shash bridges;
struct shash ports;
struct shash ifaces;
- struct ovsrec_controller *ctrl;
+ struct ovsrec_controller **ctrl;
+ size_t n_ctrl;
};
static char *
@@ -545,7 +547,13 @@ add_bridge(struct vsctl_info *b,
br->name = xstrdup(name);
br->parent = parent;
br->vlan = vlan;
- br->ctrl = parent ? parent->br_cfg->controller : br_cfg->controller;
+ if (parent) {
+ br->ctrl = parent->br_cfg->controller;
+ br->n_ctrl = parent->br_cfg->n_controller;
+ } else {
+ br->ctrl = br_cfg->controller;
+ br->n_ctrl = br_cfg->n_controller;
+ }
shash_add(&b->bridges, br->name, br);
return br;
}
@@ -610,6 +618,7 @@ get_info(const struct ovsrec_open_vswitch *ovs, struct vsctl_info *info)
shash_init(&info->ifaces);
info->ctrl = ovs->controller;
+ info->n_ctrl = ovs->n_controller;
shash_init(&bridges);
shash_init(&ports);
@@ -1440,6 +1449,29 @@ cmd_iface_to_br(struct vsctl_context *ctx)
free_info(&info);
}
+/* Print targets of the 'n_controllers' in 'controllers' on the output for
+ * 'ctx'. */
+static void
+print_controllers(struct vsctl_context *ctx,
+ struct ovsrec_controller **controllers,
+ size_t n_controllers)
+{
+ /* Print the targets in sorted order for reproducibility. */
+ struct svec targets;
+ size_t i;
+
+ svec_init(&targets);
+ for (i = 0; i < n_controllers; i++) {
+ svec_add(&targets, controllers[i]->target);
+ }
+
+ svec_sort(&targets);
+ for (i = 0; i < targets.n; i++) {
+ ds_put_format(&ctx->output, "%s\n", targets.names[i]);
+ }
+ svec_destroy(&targets);
+}
+
static void
cmd_get_controller(struct vsctl_context *ctx)
{
@@ -1447,21 +1479,14 @@ cmd_get_controller(struct vsctl_context *ctx)
get_info(ctx->ovs, &info);
- if (ctx->argc == 1) {
- /* Return the controller from the "Open_vSwitch" table */
- if (info.ctrl) {
- ds_put_format(&ctx->output, "%s\n", info.ctrl->target);
- }
+ if (ctx->argc == 1 || !strcmp(ctx->argv[1], "default")) {
+ print_controllers(ctx, info.ctrl, info.n_ctrl);
} else {
- /* Return the controller for a particular bridge. */
struct vsctl_bridge *br = find_bridge(&info, ctx->argv[1], true);
-
- /* If no controller is explicitly defined for the requested
- * bridge, fallback to the "Open_vSwitch" table's controller. */
- if (br->ctrl) {
- ds_put_format(&ctx->output, "%s\n", br->ctrl->target);
- } else if (info.ctrl) {
- ds_put_format(&ctx->output, "%s\n", info.ctrl->target);
+ if (br->n_ctrl) {
+ print_controllers(ctx, br->ctrl, br->n_ctrl);
+ } else {
+ print_controllers(ctx, info.ctrl, info.n_ctrl);
}
}
@@ -1469,60 +1494,117 @@ cmd_get_controller(struct vsctl_context *ctx)
}
static void
+delete_controllers(struct ovsrec_controller **controllers,
+ size_t n_controllers)
+{
+ size_t i;
+
+ for (i = 0; i < n_controllers; i++) {
+ ovsrec_controller_delete(controllers[i]);
+ }
+}
+
+static void
cmd_del_controller(struct vsctl_context *ctx)
{
struct vsctl_info info;
get_info(ctx->ovs, &info);
- if (ctx->argc == 1) {
- if (info.ctrl) {
- ovsrec_controller_delete(info.ctrl);
- ovsrec_open_vswitch_set_controller(ctx->ovs, NULL);
+ if (ctx->argc == 1 || !strcmp(ctx->argv[1], "default")) {
+ if (info.n_ctrl) {
+ delete_controllers(info.ctrl, info.n_ctrl);
+ ovsrec_open_vswitch_set_controller(ctx->ovs, NULL, 0);
}
} else {
struct vsctl_bridge *br = find_real_bridge(&info, ctx->argv[1], true);
-
if (br->ctrl) {
- ovsrec_controller_delete(br->ctrl);
- ovsrec_bridge_set_controller(br->br_cfg, NULL);
+ delete_controllers(br->ctrl, br->n_ctrl);
+ ovsrec_bridge_set_controller(br->br_cfg, NULL, 0);
}
}
free_info(&info);
}
+static struct ovsrec_controller **
+insert_controllers(struct ovsdb_idl_txn *txn, char *targets[], size_t n)
+{
+ struct ovsrec_controller **controllers;
+ size_t i;
+
+ controllers = xmalloc(n * sizeof *controllers);
+ for (i = 0; i < n; i++) {
+ controllers[i] = ovsrec_controller_insert(txn);
+ ovsrec_controller_set_target(controllers[i], targets[i]);
+ }
+
+ return controllers;
+}
+
+static void
+set_default_controllers(struct vsctl_context *ctx, char *targets[], size_t n)
+{
+ struct ovsrec_controller **controllers;
+
+ delete_controllers(ctx->ovs->controller, ctx->ovs->n_controller);
+
+ controllers = insert_controllers(ctx->txn, targets, n);
+ ovsrec_open_vswitch_set_controller(ctx->ovs, controllers, n);
+ free(controllers);
+}
+
static void
cmd_set_controller(struct vsctl_context *ctx)
{
struct vsctl_info info;
- struct ovsrec_controller *ctrl;
get_info(ctx->ovs, &info);
if (ctx->argc == 2) {
- /* Set the controller in the "Open_vSwitch" table. */
- if (info.ctrl) {
- ovsrec_controller_delete(info.ctrl);
- }
- ctrl = ovsrec_controller_insert(ctx->txn);
- ovsrec_controller_set_target(ctrl, ctx->argv[1]);
- ovsrec_open_vswitch_set_controller(ctx->ovs, ctrl);
+ /* Set one controller in the "Open_vSwitch" table. */
+ set_default_controllers(ctx, &ctx->argv[1], 1);
+ } else if (!strcmp(ctx->argv[1], "default")) {
+ /* Set one or more controllers in the "Open_vSwitch" table. */
+ set_default_controllers(ctx, &ctx->argv[2], ctx->argc - 2);
} else {
- /* Set the controller for a particular bridge. */
+ /* Set one or more controllers for a particular bridge. */
struct vsctl_bridge *br = find_real_bridge(&info, ctx->argv[1], true);
+ struct ovsrec_controller **controllers;
+ size_t n;
- if (br->ctrl) {
- ovsrec_controller_delete(br->ctrl);
- }
- ctrl = ovsrec_controller_insert(ctx->txn);
- ovsrec_controller_set_target(ctrl, ctx->argv[2]);
- ovsrec_bridge_set_controller(br->br_cfg, ctrl);
+ delete_controllers(br->ctrl, br->n_ctrl);
+
+ n = ctx->argc - 2;
+ controllers = insert_controllers(ctx->txn, &ctx->argv[2], n);
+ ovsrec_bridge_set_controller(br->br_cfg, controllers, n);
+ free(controllers);
}
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)
{
@@ -1531,23 +1613,18 @@ cmd_get_fail_mode(struct vsctl_context *ctx)
get_info(ctx->ovs, &info);
- if (ctx->argc == 1) {
+ if (ctx->argc == 1 || !strcmp(ctx->argv[1], "default")) {
/* Return the fail-mode from the "Open_vSwitch" table */
- if (info.ctrl && info.ctrl->fail_mode) {
- fail_mode = info.ctrl->fail_mode;
- }
+ fail_mode = get_fail_mode(info.ctrl, info.n_ctrl);
} else {
/* Return the fail-mode for a particular bridge. */
struct vsctl_bridge *br = find_bridge(&info, ctx->argv[1], true);
- /* If no controller or fail-mode is explicitly defined for the
- * requested bridge, fallback to the "Open_vSwitch" table's
- * setting. */
- if (br->ctrl && br->ctrl->fail_mode) {
- fail_mode = br->ctrl->fail_mode;
- } else if (info.ctrl && info.ctrl->fail_mode) {
- fail_mode = info.ctrl->fail_mode;
- }
+ /* If no controller is defined for the requested bridge, fallback to
+ * the "Open_vSwitch" table's controller. */
+ fail_mode = (br->n_ctrl
+ ? get_fail_mode(br->ctrl, br->n_ctrl)
+ : get_fail_mode(info.ctrl, info.n_ctrl));
}
if (fail_mode && strlen(fail_mode)) {
@@ -1558,22 +1635,29 @@ cmd_get_fail_mode(struct vsctl_context *ctx)
}
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)
{
struct vsctl_info info;
get_info(ctx->ovs, &info);
- if (ctx->argc == 1) {
- if (info.ctrl && info.ctrl->fail_mode) {
- ovsrec_controller_set_fail_mode(info.ctrl, NULL);
- }
+ if (ctx->argc == 1 || !strcmp(ctx->argv[1], "default")) {
+ set_fail_mode(info.ctrl, info.n_ctrl, NULL);
} else {
struct vsctl_bridge *br = find_real_bridge(&info, ctx->argv[1], true);
- if (br->ctrl && br->ctrl->fail_mode) {
- ovsrec_controller_set_fail_mode(br->ctrl, NULL);
- }
+ set_fail_mode(br->ctrl, br->n_ctrl, NULL);
}
free_info(&info);
@@ -1583,29 +1667,36 @@ static void
cmd_set_fail_mode(struct vsctl_context *ctx)
{
struct vsctl_info info;
+ const char *bridge;
const char *fail_mode;
get_info(ctx->ovs, &info);
- fail_mode = (ctx->argc == 2) ? ctx->argv[1] : ctx->argv[2];
+ if (ctx->argc == 2) {
+ bridge = "default";
+ fail_mode = ctx->argv[1];
+ } else {
+ bridge = ctx->argv[1];
+ fail_mode = ctx->argv[2];
+ }
if (strcmp(fail_mode, "standalone") && strcmp(fail_mode, "secure")) {
vsctl_fatal("fail-mode must be \"standalone\" or \"secure\"");
}
- if (ctx->argc == 2) {
+ if (!strcmp(bridge, "default")) {
/* Set the fail-mode in the "Open_vSwitch" table. */
if (!info.ctrl) {
vsctl_fatal("no controller declared");
}
- ovsrec_controller_set_fail_mode(info.ctrl, fail_mode);
+ set_fail_mode(info.ctrl, info.n_ctrl, fail_mode);
} else {
- struct vsctl_bridge *br = find_real_bridge(&info, ctx->argv[1], true);
+ struct vsctl_bridge *br = find_real_bridge(&info, bridge, true);
if (!br->ctrl) {
vsctl_fatal("no controller declared for %s", br->name);
}
- ovsrec_controller_set_fail_mode(br->ctrl, fail_mode);
+ set_fail_mode(br->ctrl, br->n_ctrl, fail_mode);
}
free_info(&info);
@@ -2544,7 +2635,7 @@ static const struct vsctl_command_syntax all_commands[] = {
/* Controller commands. */
{"get-controller", 0, 1, cmd_get_controller, NULL, ""},
{"del-controller", 0, 1, cmd_del_controller, NULL, ""},
- {"set-controller", 1, 2, cmd_set_controller, NULL, ""},
+ {"set-controller", 1, INT_MAX, cmd_set_controller, NULL, ""},
{"get-fail-mode", 0, 1, cmd_get_fail_mode, NULL, ""},
{"del-fail-mode", 0, 1, cmd_del_fail_mode, NULL, ""},
{"set-fail-mode", 1, 2, cmd_set_fail_mode, NULL, ""},