Signed-off-by: Darrell Ball <[email protected]>
---
ovn/controller/patch.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 132 insertions(+), 2 deletions(-)
diff --git a/ovn/controller/patch.c b/ovn/controller/patch.c
index 753ce3e..168513d 100644
--- a/ovn/controller/patch.c
+++ b/ovn/controller/patch.c
@@ -276,9 +276,136 @@ add_logical_patch_ports(struct controller_ctx *ctx,
}
}
+static const struct ovsrec_bridge *
+create_br_physical_for_gateway(struct controller_ctx *ctx,
+ const struct ovsrec_open_vswitch *cfg,
+ const char *bridge_name)
+{
+ if (!ctx->ovs_idl_txn) {
+ return NULL;
+ }
+
+ ovsdb_idl_txn_add_comment(ctx->ovs_idl_txn,
+ "ovn-controller: creating gateway physical bridge '%s'",
+ bridge_name);
+
+ struct ovsrec_interface *iface;
+ iface = ovsrec_interface_insert(ctx->ovs_idl_txn);
+ ovsrec_interface_set_name(iface, bridge_name);
+ ovsrec_interface_set_type(iface, "internal");
+
+ struct ovsrec_port *port;
+ port = ovsrec_port_insert(ctx->ovs_idl_txn);
+ ovsrec_port_set_name(port, bridge_name);
+ ovsrec_port_set_interfaces(port, &iface, 1);
+
+ struct ovsrec_bridge *bridge;
+ bridge = ovsrec_bridge_insert(ctx->ovs_idl_txn);
+ ovsrec_bridge_set_name(bridge, bridge_name);
+ ovsrec_bridge_set_fail_mode(bridge, "standalone");
+ ovsrec_bridge_set_ports(bridge, &port, 1);
+
+ struct ovsrec_bridge **bridges;
+ size_t bytes = sizeof *bridges * cfg->n_bridges;
+ bridges = xmalloc(bytes + sizeof *bridges);
+ memcpy(bridges, cfg->bridges, bytes);
+ bridges[cfg->n_bridges] = bridge;
+ ovsrec_open_vswitch_verify_bridges(cfg);
+ ovsrec_open_vswitch_set_bridges(cfg, bridges, cfg->n_bridges + 1);
+
+ return bridge;
+}
+
+static const struct ovsrec_bridge *
+get_and_create_br_as_needed(struct controller_ctx *ctx, const char *br_name)
+{
+ const struct ovsrec_open_vswitch *cfg;
+
+ cfg = ovsrec_open_vswitch_first(ctx->ovs_idl);
+ if (!cfg) {
+ return NULL;
+ }
+
+ const struct ovsrec_bridge *br;
+ br = get_bridge(ctx->ovs_idl, br_name);
+ if (!br) {
+ return create_br_physical_for_gateway(ctx, cfg, br_name);
+ }
+
+ return br;
+}
+
+/* Note that create_patch_port checks/avoids redundant creates */
+static void
+add_gateway_ls_br_and_patch_ports(struct controller_ctx *ctx,
+ const struct ovsrec_bridge *br_int,
+ struct shash *existing_ports,
+ const char *chassis_id)
+{
+ const struct ovsrec_bridge *br_gateway_physical = NULL;
+
+ if (!br_int || !chassis_id) {
+ return;
+ }
+
+ const struct sbrec_port_binding *binding;
+ const struct sbrec_physical_endpoint * phys_endpt_rec;
+ const struct sbrec_chassis *chassis_rec;
+ SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
+
+ if (!binding || !binding->phys_endpts ||
+ strcmp(binding->type, "gw")) {
+ /* Not a binding for a gw port. */
+ continue;
+ }
+
+ if(!binding->phys_endpts[0]) {
+ VLOG_ERR("No physical endpt configured for gw port '%s' ",
+ binding->logical_port);
+ return;
+ }
+
+ phys_endpt_rec = binding->phys_endpts[0];
+ chassis_rec = phys_endpt_rec->chassis;
+
+ if(!chassis_rec || !chassis_rec->name) {
+ VLOG_ERR("No chassis configured "
+ "for gw port '%s' in phys endpt ",
+ binding->logical_port);
+ return;
+ }
+
+ /* The logical port is not on this chassis */
+ if(strcmp(chassis_rec->name, chassis_id)) {
+ continue;
+ }
+
+ /* Sync chassis from phys endpt table to port binding table */
+ if (ctx->ovnsb_idl_txn) {
+ sbrec_port_binding_set_chassis(binding, chassis_rec);
+ }
+
+ br_gateway_physical =
+ get_and_create_br_as_needed(ctx, chassis_rec->name);
+
+ char *name1 = patch_port_name(br_int->name, binding->logical_port);
+ char *name2 = patch_port_name(binding->logical_port, br_int->name);
+
+ create_patch_port(ctx, "ovn-gateway-patch-port", binding->logical_port,
+ br_int, name1, br_gateway_physical, name2,
existing_ports);
+ create_patch_port(ctx, "ovn-gateway-patch-port", binding->logical_port,
+ br_gateway_physical, name2, br_int, name1,
existing_ports);
+
+ free(name1);
+ free(name2);
+
+ }
+
+}
+
void
patch_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
- struct hmap *local_datapaths)
+ struct hmap *local_datapaths, const char *chassis_id)
{
if (!ctx->ovs_idl_txn) {
return;
@@ -289,7 +416,8 @@ patch_run(struct controller_ctx *ctx, const struct
ovsrec_bridge *br_int,
const struct ovsrec_port *port;
OVSREC_PORT_FOR_EACH (port, ctx->ovs_idl) {
if (smap_get(&port->external_ids, "ovn-localnet-port") ||
- smap_get(&port->external_ids, "ovn-logical-patch-port")) {
+ smap_get(&port->external_ids, "ovn-logical-patch-port") ||
+ smap_get(&port->external_ids, "ovn-gateway-patch-port")) {
shash_add(&existing_ports, port->name, port);
}
}
@@ -298,6 +426,8 @@ patch_run(struct controller_ctx *ctx, const struct
ovsrec_bridge *br_int,
* 'existing_ports' any patch ports that do exist in the database and
* should be there. */
add_bridge_mappings(ctx, br_int, &existing_ports, local_datapaths);
+ add_gateway_ls_br_and_patch_ports(ctx, br_int,
+ &existing_ports, chassis_id);
add_logical_patch_ports(ctx, br_int, &existing_ports);
/* Now 'existing_ports' only still contains patch ports that exist in the
--
1.9.1
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev