struct ovsrec_controller *ctrl;
};
+static char *
+vsctl_context_to_string(const struct vsctl_context *ctx)
+{
+ const struct shash_node *node;
+ struct svec words;
+ char *s;
+ int i;
+
+ svec_init(&words);
+ SHASH_FOR_EACH (node, &ctx->options) {
+ svec_add(&words, node->name);
+ }
+ for (i = 0; i < ctx->argc; i++) {
+ svec_add(&words, ctx->argv[i]);
+ }
+ svec_terminate(&words);
+
+ s = process_escape_args(words.names);
+
+ svec_destroy(&words);
+
+ return s;
+}
+
static struct vsctl_bridge *
add_bridge(struct vsctl_info *b,
struct ovsrec_bridge *br_cfg, const char *name,
}
static void
-cmd_init(struct vsctl_context *ctx UNUSED)
+cmd_init(struct vsctl_context *ctx OVS_UNUSED)
{
}
static void
cmd_add_br(struct vsctl_context *ctx)
{
- const char *br_name = ctx->argv[1];
+ bool may_exist = shash_find(&ctx->options, "--may-exist") != 0;
+ const char *br_name, *parent_name;
struct vsctl_info info;
+ int vlan;
+
+ br_name = ctx->argv[1];
+ if (ctx->argc == 2) {
+ parent_name = NULL;
+ vlan = 0;
+ } else if (ctx->argc == 4) {
+ parent_name = ctx->argv[2];
+ vlan = atoi(ctx->argv[3]);
+ if (vlan < 1 || vlan > 4095) {
+ vsctl_fatal("%s: vlan must be between 1 and 4095", ctx->argv[0]);
+ }
+ } else {
+ vsctl_fatal("'%s' command takes exactly 1 or 3 arguments",
+ ctx->argv[0]);
+ }
get_info(ctx->ovs, &info);
+ if (may_exist) {
+ struct vsctl_bridge *br;
+
+ br = find_bridge(&info, br_name, false);
+ if (br) {
+ if (!parent_name) {
+ if (br->parent) {
+ vsctl_fatal("\"--may-exist add-br %s\" but %s is "
+ "a VLAN bridge for VLAN %d",
+ br_name, br_name, br->vlan);
+ }
+ } else {
+ if (!br->parent) {
+ vsctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
+ "is not a VLAN bridge",
+ br_name, parent_name, vlan, br_name);
+ } else if (strcmp(br->parent->name, parent_name)) {
+ vsctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
+ "has the wrong parent %s",
+ br_name, parent_name, vlan,
+ br_name, br->parent->name);
+ } else if (br->vlan != vlan) {
+ vsctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
+ "is a VLAN bridge for the wrong VLAN %d",
+ br_name, parent_name, vlan, br_name, br->vlan);
+ }
+ }
+ return;
+ }
+ }
check_conflicts(&info, br_name,
xasprintf("cannot create a bridge named %s", br_name));
- if (ctx->argc == 2) {
- struct ovsrec_bridge *br;
+ if (!parent_name) {
struct ovsrec_port *port;
struct ovsrec_interface *iface;
+ struct ovsrec_bridge *br;
iface = ovsrec_interface_insert(ctx->txn);
ovsrec_interface_set_name(iface, br_name);
ovsrec_bridge_set_ports(br, &port, 1);
ovs_insert_bridge(ctx->ovs, br);
- } else if (ctx->argc == 3) {
- vsctl_fatal("'%s' command takes exactly 1 or 3 arguments",
- ctx->argv[0]);
- } else if (ctx->argc == 4) {
- const char *parent_name = ctx->argv[2];
- int vlan = atoi(ctx->argv[3]);
- struct ovsrec_bridge *br;
+ } else {
struct vsctl_bridge *parent;
struct ovsrec_port *port;
struct ovsrec_interface *iface;
+ struct ovsrec_bridge *br;
int64_t tag = vlan;
- if (vlan < 1 || vlan > 4095) {
- vsctl_fatal("%s: vlan must be between 1 and 4095", ctx->argv[0]);
- }
-
parent = find_bridge(&info, parent_name, false);
if (parent && parent->vlan) {
vsctl_fatal("cannot create bridge with fake bridge as parent");
ovsrec_port_set_tag(port, &tag, 1);
bridge_insert_port(br, port);
- } else {
- NOT_REACHED();
}
free_info(&info);
static void
add_port(struct vsctl_context *ctx,
- const char *br_name, const char *port_name, bool fake_iface,
+ const char *br_name, const char *port_name,
+ bool may_exist, bool fake_iface,
char *iface_names[], int n_ifaces)
{
struct vsctl_info info;
size_t i;
get_info(ctx->ovs, &info);
+ if (may_exist) {
+ struct vsctl_port *port;
+
+ port = find_port(&info, port_name, false);
+ if (port) {
+ struct svec want_names, have_names;
+ size_t i;
+
+ svec_init(&want_names);
+ for (i = 0; i < n_ifaces; i++) {
+ svec_add(&want_names, iface_names[i]);
+ }
+ svec_sort(&want_names);
+
+ svec_init(&have_names);
+ for (i = 0; i < port->port_cfg->n_interfaces; i++) {
+ svec_add(&have_names, port->port_cfg->interfaces[i]->name);
+ }
+ svec_sort(&have_names);
+
+ if (strcmp(port->bridge->name, br_name)) {
+ char *command = vsctl_context_to_string(ctx);
+ vsctl_fatal("\"%s\" but %s is actually attached to bridge %s",
+ command, port_name, port->bridge->name);
+ }
+
+ if (!svec_equal(&want_names, &have_names)) {
+ char *have_names_string = svec_join(&have_names, ", ", "");
+ char *command = vsctl_context_to_string(ctx);
+
+ vsctl_fatal("\"%s\" but %s actually has interface(s) %s",
+ command, port_name, have_names_string);
+ }
+
+ svec_destroy(&want_names);
+ svec_destroy(&have_names);
+
+ return;
+ }
+ }
check_conflicts(&info, port_name,
xasprintf("cannot create a port named %s", port_name));
- /* XXX need to check for conflicts on interfaces too */
+ for (i = 0; i < n_ifaces; i++) {
+ check_conflicts(&info, iface_names[i],
+ xasprintf("cannot create an interface named %s",
+ iface_names[i]));
+ }
bridge = find_bridge(&info, br_name, true);
ifaces = xmalloc(n_ifaces * sizeof *ifaces);
static void
cmd_add_port(struct vsctl_context *ctx)
{
- add_port(ctx, ctx->argv[1], ctx->argv[2], false, &ctx->argv[2], 1);
+ bool may_exist = shash_find(&ctx->options, "--may-exist") != 0;
+
+ add_port(ctx, ctx->argv[1], ctx->argv[2], may_exist, false,
+ &ctx->argv[2], 1);
}
static void
cmd_add_bond(struct vsctl_context *ctx)
{
+ bool may_exist = shash_find(&ctx->options, "--may-exist") != 0;
bool fake_iface = shash_find(&ctx->options, "--fake-iface");
- add_port(ctx, ctx->argv[1], ctx->argv[2], fake_iface,
+ add_port(ctx, ctx->argv[1], ctx->argv[2], may_exist, fake_iface,
&ctx->argv[3], ctx->argc - 3);
}
cmd_del_port(struct vsctl_context *ctx)
{
bool must_exist = !shash_find(&ctx->options, "--if-exists");
+ bool with_iface = shash_find(&ctx->options, "--with-iface") != NULL;
+ struct vsctl_port *port;
struct vsctl_info info;
get_info(ctx->ovs, &info);
- if (ctx->argc == 2) {
- struct vsctl_port *port = find_port(&info, ctx->argv[1], must_exist);
- if (port) {
- del_port(&info, port);
+ if (!with_iface) {
+ port = find_port(&info, ctx->argv[ctx->argc - 1], must_exist);
+ } else {
+ const char *target = ctx->argv[ctx->argc - 1];
+ struct vsctl_iface *iface;
+
+ port = find_port(&info, target, false);
+ if (!port) {
+ iface = find_iface(&info, target, false);
+ if (iface) {
+ port = iface->port;
+ }
+ }
+ if (must_exist && !port) {
+ vsctl_fatal("no port or interface named %s", target);
}
- } else if (ctx->argc == 3) {
- struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1], true);
- struct vsctl_port *port = find_port(&info, ctx->argv[2], must_exist);
+ }
- if (port) {
- if (port->bridge == bridge) {
- del_port(&info, port);
- } else if (port->bridge->parent == bridge) {
- vsctl_fatal("bridge %s does not have a port %s (although its "
- "parent bridge %s does)",
- ctx->argv[1], ctx->argv[2], bridge->parent->name);
- } else {
- vsctl_fatal("bridge %s does not have a port %s",
- ctx->argv[1], ctx->argv[2]);
+ if (port) {
+ if (ctx->argc == 3) {
+ struct vsctl_bridge *bridge;
+
+ bridge = find_bridge(&info, ctx->argv[1], true);
+ if (port->bridge != bridge) {
+ if (port->bridge->parent == bridge) {
+ vsctl_fatal("bridge %s does not have a port %s (although "
+ "its parent bridge %s does)",
+ ctx->argv[1], ctx->argv[2],
+ bridge->parent->name);
+ } else {
+ vsctl_fatal("bridge %s does not have a port %s",
+ ctx->argv[1], ctx->argv[2]);
+ }
}
}
+
+ del_port(&info, port);
}
+
free_info(&info);
}
vsctl_context_done(&ctx, c);
}
- while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
- ovsdb_idl_run(idl);
- ovsdb_idl_wait(idl);
- ovsdb_idl_txn_wait(txn);
- poll_block();
- }
+ status = ovsdb_idl_txn_commit_block(txn);
if (wait_for_reload && status == TXN_SUCCESS) {
next_cfg = ovsdb_idl_txn_get_increment_new_value(txn);
}
{"init", 0, 0, cmd_init, NULL, ""},
/* Bridge commands. */
- {"add-br", 1, 3, cmd_add_br, NULL, ""},
+ {"add-br", 1, 3, cmd_add_br, NULL, "--may-exist"},
{"del-br", 1, 1, cmd_del_br, NULL, "--if-exists"},
{"list-br", 0, 0, cmd_list_br, NULL, ""},
{"br-exists", 1, 1, cmd_br_exists, NULL, ""},
/* Port commands. */
{"list-ports", 1, 1, cmd_list_ports, NULL, ""},
- {"add-port", 2, 2, cmd_add_port, NULL, ""},
- {"add-bond", 4, INT_MAX, cmd_add_bond, NULL, "--fake-iface"},
- {"del-port", 1, 2, cmd_del_port, NULL, "--if-exists"},
+ {"add-port", 2, 2, cmd_add_port, NULL, "--may-exist"},
+ {"add-bond", 4, INT_MAX, cmd_add_bond, NULL, "--may-exist,--fake-iface"},
+ {"del-port", 1, 2, cmd_del_port, NULL, "--if-exists,--with-iface"},
{"port-to-br", 1, 1, cmd_port_to_br, NULL, ""},
/* Interface commands. */