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