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

Reply via email to