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
