This patch is based on the monitor-cond V4 patch series:
http://openvswitch.org/pipermail/dev/2016-February/066331.html
and is a draft implementation of OVN making usage of this new feature.
The patch turns monitoring of Port_Binding and Logical_Flow tables to 
conditional
and only relevant rows are being monitored. 
The logic is simple: each iface-id of each local port is being added to 
condition
and then each new logical datapath is added also to the condition. (Each table 
has its
own condition).

It was good if we were able to know which logical datapath an ovn-controller 
serves
dirtectly from the local port record (like we know iface-id).

We expect to see performance improvment in the ovn-controller side and under 
common VM
scheduling policy we expect to see server improvment as well.

Signed-off-by: Liran Schour <[email protected]>
---
 ovn/controller/binding.c        | 93 +++++++++++++++++++++++++++++++++++++++++
 ovn/controller/lflow.c          | 34 +++++++++++++--
 ovn/controller/ovn-controller.c | 19 +++++++++
 ovn/controller/ovn-controller.h |  4 ++
 4 files changed, 146 insertions(+), 4 deletions(-)

diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c
index cb12cea..ad4d581 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 %s", 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 %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 %s", 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 %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 d53213c..dd8e419 100644
--- a/ovn/controller/lflow.c
+++ b/ovn/controller/lflow.c
@@ -210,10 +210,22 @@ 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);
+        ctx->binding_cond_updated = true;
+        ctx->lflow_cond_updated = true;
+     }
+    return ldp;
 }
 
 static void
@@ -237,20 +249,34 @@ 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("add remove 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);
+                ctx->binding_cond_updated = true;
+                ctx->lflow_cond_updated = true;
+            }
             ldp_free(ldp);
         }
     }
diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
index 3638342..7bd0fe9 100644
--- a/ovn/controller/ovn-controller.c
+++ b/ovn/controller/ovn-controller.c
@@ -259,6 +259,15 @@ 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);
     ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl);
 
     /* Initialize connection tracking zones. */
@@ -276,6 +285,10 @@ 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,
         };
 
         /* Contains bare "struct hmap_node"s whose hash values are the 
tunnel_key
@@ -339,6 +352,12 @@ 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);
+        }
     }
 
     /* It's time to exit.  Clean up the databases. */
diff --git a/ovn/controller/ovn-controller.h b/ovn/controller/ovn-controller.h
index 8c437a7..abcc317 100644
--- a/ovn/controller/ovn-controller.h
+++ b/ovn/controller/ovn-controller.h
@@ -29,6 +29,10 @@ 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;
 };
 
 const struct ovsrec_bridge *get_bridge(struct ovsdb_idl *,
-- 
2.1.4


_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to