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

Reply via email to