OVS_VSCTL_SETUP
AT_CHECK([RUN_OVS_VSCTL([add-br a], [add-br b])], [0], [], [],
[OVS_VSCTL_CLEANUP])
+AT_CHECK([RUN_OVS_VSCTL([--may-exist add-br a b 9])], [1], [],
+ [ovs-vsctl: "--may-exist add-br a b 9" but a is not a VLAN bridge
+],
+ [OVS_VSCTL_CLEANUP])
CHECK_BRIDGES([a, a, 0], [b, b, 0])
CHECK_PORTS([a])
CHECK_IFACES([a])
[AT_CHECK(
[RUN_OVS_VSCTL(
[add-br xenbr0],
+ [--may-exist add-br xenbr0],
[add-port xenbr0 eth0],
[add-br xapi1 xenbr0 9],
+ [--may-exist add-br xapi1 xenbr0 9],
[add-port xapi1 eth0.9])],
[0], [], [], [OVS_VSCTL_CLEANUP])])
AT_KEYWORDS([ovs-vsctl fake-bridge])
OVS_VSCTL_SETUP
OVS_VSCTL_SETUP_SIMPLE_FAKE_CONF
+AT_CHECK([RUN_OVS_VSCTL([--may-exist add-br xapi1])], [1], [],
+ [ovs-vsctl: "--may-exist add-br xapi1" but xapi1 is a VLAN bridge for VLAN 9
+], [OVS_VSCTL_CLEANUP])
+AT_CHECK([RUN_OVS_VSCTL([--may-exist add-br xapi1 xxx 9])], [1], [],
+ [ovs-vsctl: "--may-exist add-br xapi1 xxx 9" but xapi1 has the wrong parent xenbr0
+], [OVS_VSCTL_CLEANUP])
+AT_CHECK([RUN_OVS_VSCTL([--may-exist add-br xapi1 xenbr0 10])], [1], [],
+ [ovs-vsctl: "--may-exist add-br xapi1 xenbr0 10" but xapi1 is a VLAN bridge for the wrong VLAN 9
+], [OVS_VSCTL_CLEANUP])
CHECK_BRIDGES([xapi1, xenbr0, 9], [xenbr0, xenbr0, 0])
CHECK_PORTS([xenbr0], [eth0])
CHECK_IFACES([xenbr0], [eth0])
.SS "Bridge Commands"
These commands examine and manipulate Open vSwitch bridges.
.
-.IP "\fBadd\-br \fIbridge\fR"
+.IP "[\fB\-\-may\-exist\fR] \fBadd\-br \fIbridge\fR"
Creates a new bridge named \fIbridge\fR. Initially the bridge will
have no ports (other than \fIbridge\fR itself).
+.IP
+Without \fB\-\-may\-exist\fR, attempting to create a bridge that
+exists is an error. With \fB\-\-may\-exist\fR, \fIbridge\fR may
+already exist (but it must be a real bridge, not a VLAN bridge).
.
-.IP "\fBadd\-br \fIbridge parent vlan\fR"
+.IP "[\fB\-\-may\-exist\fR] \fBadd\-br \fIbridge parent vlan\fR"
Creates a ``fake bridge'' named \fIbridge\fR within the existing Open
vSwitch bridge \fIparent\fR, which must already exist and must not
itself be a fake bridge. The new fake bridge will be on 802.1Q VLAN
\fIvlan\fR, which must be an integer between 1 and 4095. Initially
\fIbridge\fR will have no ports (other than \fIbridge\fR itself).
+.IP
+Without \fB\-\-may\-exist\fR, attempting to create a bridge that
+exists is an error. With \fB\-\-may\-exist\fR, \fIbridge\fR may
+already exist (but it must have the specified \fIvlan\fR and
+\fIparent\fR).
.
.IP "[\fB\-\-if\-exists\fR] \fBdel\-br \fIbridge\fR"
Deletes \fIbridge\fR and all of its ports. If \fIbridge\fR is a real
static void
cmd_add_br(struct vsctl_context *ctx)
{
+ bool may_exist = shash_find(&ctx->options, "--may-exist") != 0;
const char *br_name = ctx->argv[1];
+ const char *parent_name = ctx->argc > 2 ? ctx->argv[2] : NULL;
+ int vlan = ctx->argc > 3 ? atoi(ctx->argv[3]) : 0;
struct vsctl_info info;
+ 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);
{"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, ""},