While parsing the OVN bridge mapping configuration, ensure that patch ports exist between the OVN integration bridge and the physical network bridge. If they do not exist, create them automatically.
Signed-off-by: Russell Bryant <rbry...@redhat.com> --- ovn/controller/ovn-controller.c | 114 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 16b6a8c..64d46da 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -87,6 +87,113 @@ get_bridge(struct controller_ctx *ctx, const char *name) return NULL; } +/* + * Return true if the port is a patch port to a given bridge + */ +static bool +match_patch_port(const struct ovsrec_port *port, const struct ovsrec_bridge *to_br) +{ + struct ovsrec_interface *iface; + size_t i; + + for (i = 0; i < port->n_interfaces; i++) { + const char *peer; + iface = port->interfaces[i]; + if (strcmp(iface->type, "patch")) { + continue; + } + peer = smap_get(&iface->options, "peer"); + if (peer && !strcmp(peer, to_br->name)) { + return true; + } + } + + return false; +} + +static int +create_patch_port(struct controller_ctx *ctx, const struct ovsrec_bridge *b1, + const struct ovsrec_bridge *b2) +{ + struct ovsdb_idl_txn *ovs_txn; + struct ovsrec_interface *iface; + struct ovsrec_port *port, **ports; + struct smap options = SMAP_INITIALIZER(&options); + size_t i; + int retval, res = 0; + char *port_name; + + port_name = xasprintf("patch-%s-to-%s", b1->name, b2->name); + + ovs_txn = ovsdb_idl_txn_create(ctx->ovs_idl); + ovsdb_idl_txn_add_comment(ovs_txn, + "ovn-controller: creating patch port '%s' from '%s' to '%s'", + port_name, b1->name, b2->name); + + iface = ovsrec_interface_insert(ovs_txn); + ovsrec_interface_set_name(iface, port_name); + ovsrec_interface_set_type(iface, "patch"); + smap_add(&options, "peer", b2->name); + ovsrec_interface_set_options(iface, &options); + smap_destroy(&options); + + port = ovsrec_port_insert(ovs_txn); + ovsrec_port_set_name(port, port_name); + ovsrec_port_set_interfaces(port, &iface, 1); + + ports = xmalloc(sizeof *port * (b1->n_ports + 1)); + for (i = 0; i < b1->n_ports; i++) { + ports[i] = b1->ports[i]; + } + ports[i] = port; + ovsrec_bridge_verify_ports(b1); + ovsrec_bridge_set_ports(b1, ports, b1->n_ports + 1); + + retval = ovsdb_idl_txn_commit_block(ovs_txn); + if (retval != TXN_SUCCESS && retval != TXN_UNCHANGED) { + VLOG_INFO("Problem adding patch port: %s", + ovsdb_idl_txn_status_to_string(retval)); + poll_immediate_wake(); + res = -1; + } + + ovsdb_idl_txn_destroy(ovs_txn); + free(ports); + free(port_name); + + return res; +} + +static int +create_patch_ports(struct controller_ctx *ctx, const struct ovsrec_bridge *bridge) +{ + size_t i; + + for (i = 0; i < ctx->br_int->n_ports; i++) { + if (match_patch_port(ctx->br_int->ports[i], bridge)) { + /* Patch port already exists on br_int */ + break; + } + } + if (i == ctx->br_int->n_ports && + create_patch_port(ctx, ctx->br_int, bridge)) { + return -1; + } + + for (i = 0; i < bridge->n_ports; i++) { + if (match_patch_port(bridge->ports[i], ctx->br_int)) { + /* Patch port already exists on bridge */ + break; + } + } + if (i == bridge->n_ports && + create_patch_port(ctx, bridge, ctx->br_int)) { + return -1; + } + + return 0; +} + static int parse_bridge_mappings(struct controller_ctx *ctx, const char *bridge_mappings_) { @@ -115,6 +222,13 @@ parse_bridge_mappings(struct controller_ctx *ctx, const char *bridge_mappings_) break; } + if (create_patch_ports(ctx, ovs_bridge)) { + VLOG_WARN("Failed to create patch ports between '%s' and '%s'", + ctx->br_int_name, bridge); + res = -1; + break; + } + smap_add(&ctx->localnet_mappings, network, bridge); smap_add(&ctx->bridge_mappings, bridge, network); } -- 2.4.3 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev