Conditional monitor Port_Binding Logical_Flow and Multicast_Group
tables. As a result ovn-controller will write flows only to datapath
that has a port added on this hypervisor.

Signed-off-by: Liran Schour <lir...@il.ibm.com>
---
 ovn/controller/binding.c        | 93 +++++++++++++++++++++++++++++++++++++++++
 ovn/controller/lflow.c          | 41 +++++++++++++++---
 ovn/controller/ovn-controller.c | 28 +++++++++++++
 ovn/controller/ovn-controller.h |  6 +++
 4 files changed, 163 insertions(+), 5 deletions(-)

diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c
index 9087052..9440a33 100644
--- a/ovn/controller/binding.c
+++ b/ovn/controller/binding.c
@@ -27,6 +27,8 @@
 
 VLOG_DEFINE_THIS_MODULE(binding);
 
+struct sset g_lports = SSET_INITIALIZER(&g_lports);
+
 void
 binding_register_ovs_idl(struct ovsdb_idl *ovs_idl)
 {
@@ -146,6 +148,91 @@ update_qos(const struct ovsrec_interface *iface_rec,
     ovsrec_interface_set_ingress_policing_burst(iface_rec, MAX(0, burst));
 }
 
+static void
+update_lports(struct controller_ctx *ctx,
+              struct sset *tmp_lports)
+{
+    const char **lports_array, **tmp_lports_array;
+    int i, j;
+
+    lports_array = sset_sort(&g_lports);
+    tmp_lports_array = sset_sort(tmp_lports);
+    for (i = 0, j = 0; lports_array[i] && tmp_lports_array[j];) {
+        int cmp = strcmp(lports_array[i], tmp_lports_array[j]);
+        if (!cmp) {
+            i++;
+            j++;
+        } else if (cmp < 0) {
+            VLOG_INFO("Remove port %s from condition", lports_array[i]);
+            sbrec_port_binding_remove_clause_logical_port(ctx->binding_cond,
+                                                       OVSDB_IDL_F_EQ,
+                                                       lports_array[i]);
+            sbrec_port_binding_remove_clause_parent_port(ctx->binding_cond,
+                                                      OVSDB_IDL_F_EQ,
+                                                      lports_array[i]);
+            ctx->binding_cond_updated = true;
+            sset_find_and_delete_assert(&g_lports, lports_array[i]);
+            i++;
+        } else if (cmp > 0) {
+            VLOG_INFO("Add conditional port %s", tmp_lports_array[j]);
+            sbrec_port_binding_add_clause_logical_port(ctx->binding_cond,
+                                                       OVSDB_IDL_F_EQ,
+                                                       tmp_lports_array[j]);
+            sbrec_port_binding_add_clause_parent_port(ctx->binding_cond,
+                                                      OVSDB_IDL_F_EQ,
+                                                      tmp_lports_array[j]);
+            ctx->binding_cond_updated = true;
+            sset_add(&g_lports, tmp_lports_array[j]);
+            j++;
+        }
+    }
+    for (; lports_array[i]; i++) {
+        VLOG_INFO("Remove port %s from condition", lports_array[i]);
+        sbrec_port_binding_remove_clause_logical_port(ctx->binding_cond,
+                                                       OVSDB_IDL_F_EQ,
+                                                       lports_array[i]);
+        sbrec_port_binding_remove_clause_parent_port(ctx->binding_cond,
+                                                     OVSDB_IDL_F_EQ,
+                                                     lports_array[i]);
+        ctx->binding_cond_updated = true;
+        sset_find_and_delete_assert(&g_lports, lports_array[i]);
+    }
+    for (; tmp_lports_array[j]; j++) {
+        VLOG_INFO("Add conditional port %s", tmp_lports_array[j]);
+        sbrec_port_binding_add_clause_logical_port(ctx->binding_cond,
+                                                   OVSDB_IDL_F_EQ,
+                                                   tmp_lports_array[j]);
+        sbrec_port_binding_add_clause_parent_port(ctx->binding_cond,
+                                                  OVSDB_IDL_F_EQ,
+                                                  tmp_lports_array[j]);
+        ctx->binding_cond_updated = true;
+        sset_add(&g_lports, tmp_lports_array[j]);
+    }
+
+    free(lports_array);
+    free(tmp_lports_array);
+
+    return;
+}
+
+struct sset g_peer_lports = SSET_INITIALIZER(&g_peer_lports);
+
+static void
+add_peer_port(struct controller_ctx *ctx, const char *lport)
+{
+    if (!sset_contains(&g_peer_lports, lport)) {
+        sset_add(&g_peer_lports, lport);
+        VLOG_INFO("Add peer %s", lport);
+        sbrec_port_binding_add_clause_logical_port(ctx->binding_cond,
+                                                   OVSDB_IDL_F_EQ,
+                                                   lport);
+        sbrec_port_binding_add_clause_parent_port(ctx->binding_cond,
+                                                  OVSDB_IDL_F_EQ,
+                                                  lport);
+        ctx->binding_cond_updated = true;
+    }
+}
+
 void
 binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
             const char *chassis_id, struct simap *ct_zones,
@@ -177,6 +264,8 @@ binding_run(struct controller_ctx *ctx, const struct 
ovsrec_bridge *br_int,
         sset_add(&all_lports, node->name);
     }
 
+    update_lports(ctx, &all_lports);
+
     ovsdb_idl_txn_add_comment(
         ctx->ovnsb_idl_txn,"ovn-controller: updating port bindings for '%s'",
         chassis_id);
@@ -185,6 +274,10 @@ binding_run(struct controller_ctx *ctx, const struct 
ovsrec_bridge *br_int,
      * chassis and update the binding accordingly.  This includes both
      * directly connected logical ports and children of those ports. */
     SBREC_PORT_BINDING_FOR_EACH(binding_rec, ctx->ovnsb_idl) {
+        const char *peer = smap_get(&binding_rec->options, "peer");
+        if (peer) {
+            add_peer_port(ctx, peer);
+        }
         const struct ovsrec_interface *iface_rec
             = shash_find_and_delete(&lports, binding_rec->logical_port);
         if (iface_rec
diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
index 33dca9b..e783390 100644
--- a/ovn/controller/lflow.c
+++ b/ovn/controller/lflow.c
@@ -212,10 +212,25 @@ ldp_create(const struct sbrec_datapath_binding *binding)
 }
 
 static struct logical_datapath *
-ldp_lookup_or_create(const struct sbrec_datapath_binding *binding)
+ldp_lookup_or_create(struct controller_ctx *ctx,
+                     const struct sbrec_datapath_binding *binding)
 {
     struct logical_datapath *ldp = ldp_lookup(binding);
-    return ldp ? ldp : ldp_create(binding);
+
+     if (!ldp) {
+        ldp = ldp_create(binding);
+        VLOG_INFO("add logical datapath "UUID_FMT, UUID_ARGS(&ldp->uuid));
+        sbrec_port_binding_add_clause_datapath(ctx->binding_cond,
+                                               OVSDB_IDL_F_EQ, binding);
+        sbrec_logical_flow_add_clause_logical_datapath(ctx->lflow_cond,
+                                                       OVSDB_IDL_F_EQ, 
binding);
+        sbrec_multicast_group_add_clause_datapath(ctx->mgroup_cond,
+                                                  OVSDB_IDL_F_EQ, binding);
+        ctx->binding_cond_updated = true;
+        ctx->lflow_cond_updated = true;
+        ctx->mgroup_cond_updated = true;
+     }
+    return ldp;
 }
 
 static void
@@ -239,20 +254,36 @@ ldp_run(struct controller_ctx *ctx)
 
     const struct sbrec_port_binding *binding;
     SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
-        struct logical_datapath *ldp = ldp_lookup_or_create(binding->datapath);
-
+        struct logical_datapath *ldp = ldp_lookup_or_create(ctx, 
binding->datapath);
         simap_put(&ldp->ports, binding->logical_port, binding->tunnel_key);
     }
 
     const struct sbrec_multicast_group *mc;
     SBREC_MULTICAST_GROUP_FOR_EACH (mc, ctx->ovnsb_idl) {
-        struct logical_datapath *ldp = ldp_lookup_or_create(mc->datapath);
+        struct logical_datapath *ldp = ldp_lookup_or_create(ctx, mc->datapath);
         simap_put(&ldp->ports, mc->name, mc->tunnel_key);
     }
 
     struct logical_datapath *next_ldp;
     HMAP_FOR_EACH_SAFE (ldp, next_ldp, hmap_node, &logical_datapaths) {
         if (simap_is_empty(&ldp->ports)) {
+            const struct sbrec_datapath_binding *datapath =
+                sbrec_datapath_binding_get_for_uuid(ctx->ovnsb_idl, 
&ldp->uuid);
+            if (datapath) {
+                VLOG_INFO("Remove logical datapath "UUID_FMT, 
UUID_ARGS(&ldp->uuid));
+                sbrec_port_binding_remove_clause_datapath(ctx->binding_cond,
+                                                          OVSDB_IDL_F_EQ,
+                                                          datapath);
+                
sbrec_logical_flow_remove_clause_logical_datapath(ctx->lflow_cond,
+                                                                  
OVSDB_IDL_F_EQ,
+                                                                  datapath);
+                sbrec_multicast_group_remove_clause_datapath(ctx->mgroup_cond,
+                                                             OVSDB_IDL_F_EQ,
+                                                             datapath);
+                ctx->binding_cond_updated = true;
+                ctx->lflow_cond_updated = true;
+                ctx->mgroup_cond_updated = true;
+            }
             ldp_free(ldp);
         }
     }
diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
index f5769b5..8328419 100644
--- a/ovn/controller/ovn-controller.c
+++ b/ovn/controller/ovn-controller.c
@@ -259,6 +259,19 @@ main(int argc, char *argv[])
     char *ovnsb_remote = get_ovnsb_remote(ovs_idl_loop.idl);
     struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
         ovsdb_idl_create(ovnsb_remote, &sbrec_idl_class, true, true));
+
+    struct ovsdb_idl_condition binding_cond;
+    ovsdb_idl_condition_init(&binding_cond, &sbrec_table_port_binding);
+    sbrec_port_binding_add_clause_false(&binding_cond);
+    ovsdb_idl_cond_update(ovnsb_idl_loop.idl, &binding_cond);
+    struct ovsdb_idl_condition lflow_cond;
+    ovsdb_idl_condition_init(&lflow_cond, &sbrec_table_logical_flow);
+    sbrec_logical_flow_add_clause_false(&lflow_cond);
+    ovsdb_idl_cond_update(ovnsb_idl_loop.idl, &lflow_cond);
+    struct ovsdb_idl_condition mgroup_cond;
+    ovsdb_idl_condition_init(&mgroup_cond, &sbrec_table_multicast_group);
+    sbrec_multicast_group_add_clause_false(&mgroup_cond);
+    ovsdb_idl_cond_update(ovnsb_idl_loop.idl, &mgroup_cond);
     ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl);
 
     /* Initialize connection tracking zones. */
@@ -276,6 +289,12 @@ main(int argc, char *argv[])
             .ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop),
             .ovnsb_idl = ovnsb_idl_loop.idl,
             .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
+            .binding_cond = &binding_cond,
+            .binding_cond_updated = false,
+            .lflow_cond = &lflow_cond,
+            .lflow_cond_updated = false,
+            .mgroup_cond = &mgroup_cond,
+            .mgroup_cond_updated = false,
         };
 
         /* Contains "struct local_datpath" nodes whose hash values are the
@@ -335,6 +354,15 @@ main(int argc, char *argv[])
         if (should_service_stop()) {
             exiting = true;
         }
+        if (ctx.binding_cond_updated) {
+            ovsdb_idl_cond_update(ctx.ovnsb_idl, ctx.binding_cond);
+        }
+        if (ctx.lflow_cond_updated) {
+            ovsdb_idl_cond_update(ctx.ovnsb_idl, ctx.lflow_cond);
+        }
+        if (ctx.mgroup_cond_updated) {
+            ovsdb_idl_cond_update(ctx.ovnsb_idl, ctx.mgroup_cond);
+        }
     }
 
     /* It's time to exit.  Clean up the databases. */
diff --git a/ovn/controller/ovn-controller.h b/ovn/controller/ovn-controller.h
index a3465eb..0172cab 100644
--- a/ovn/controller/ovn-controller.h
+++ b/ovn/controller/ovn-controller.h
@@ -29,6 +29,12 @@ struct controller_ctx {
 
     struct ovsdb_idl *ovs_idl;
     struct ovsdb_idl_txn *ovs_idl_txn;
+    struct ovsdb_idl_condition *binding_cond;
+    bool binding_cond_updated;
+    struct ovsdb_idl_condition *lflow_cond;
+    bool lflow_cond_updated;
+    struct ovsdb_idl_condition *mgroup_cond;
+    bool mgroup_cond_updated;
 };
 
 /* Contains hmap_node whose hash values are the tunnel_key of datapaths
-- 
2.1.4


_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to