Signed-off-by: Darrell Ball <db...@vmware.com> --- 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 dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev