On Fri, Nov 20, 2020 at 5:44 AM Mark Michelson <[email protected]> wrote:
>
> In commit f9cab11d5fabe2ae321a3b4bad5972b61df958c0, a LOG_TO_PHY flow
> was changed so that it was no longer associated with a particular port
> binding. The logic there was that the particular flow contains data
> pertaining to the port binding's peer's datapath, so it didn't make
> sense to associate the flow with the port binding. This change was
> necessary in order for flows to be recalculated properly if the
> requested SNAT CT zone on a gateway router was changed. Since the
> datapath was changed but no port bindings were changed, that particular
> flow needed to be cleared so it could be recalculated with the new CT
> zones put in place.
>
> Unfortunately, that change broke some other behavior. Specifically, if a
> router was changed from a distributed router to a gateway router, then
> its port bindings and its port bindings' peers would be updated so that
> they were no longer type "patch" but instead type "l3gateway". They
> would attempt to remove all associated physical flows and then install
> the newly relevant ones. Since the LOG_TO_PHY flow was no longer
> associated with a port binding, that flow would remain. The result was
> that traffic could be sent to the gateway router on chassis where the
> gateway router was not pinned.
>
> This commit seeks to fix both behaviors. Now if CT zones are changed on
> a particular datapath, then all port bindings on that datapath, as well
> as all of those port bindings' peers will have their physical flows
> removed. When physical flows are recomputed, all of the appropriate
> flows will be added.
>
> Signed-off-by: Mark Michelson <[email protected]>
> ---
> controller/ovn-controller.c | 31 ++++++++++++++++++--
> controller/physical.c | 58 +++++++++++++++++++++++++++++--------
> controller/physical.h | 4 +++
> 3 files changed, 79 insertions(+), 14 deletions(-)
>
> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> index 25de0c72f..eceb804ac 100644
> --- a/controller/ovn-controller.c
> +++ b/controller/ovn-controller.c
> @@ -64,6 +64,7 @@
> #include "timer.h"
> #include "stopwatch.h"
> #include "lib/inc-proc-eng.h"
> +#include "hmapx.h"
>
> VLOG_DEFINE_THIS_MODULE(main);
>
> @@ -549,7 +550,7 @@ add_pending_ct_zone_entry(struct shash *pending_ct_zones,
> static void
> update_ct_zones(const struct sset *lports, const struct hmap
> *local_datapaths,
> struct simap *ct_zones, unsigned long *ct_zone_bitmap,
> - struct shash *pending_ct_zones)
> + struct shash *pending_ct_zones, struct hmapx *updated_dps)
> {
> struct simap_node *ct_zone, *ct_zone_next;
> int scan_start = 1;
> @@ -563,6 +564,7 @@ update_ct_zones(const struct sset *lports, const struct
> hmap *local_datapaths,
> }
>
> /* Local patched datapath (gateway routers) need zones assigned. */
> + struct shash all_lds = SHASH_INITIALIZER(&all_lds);
> const struct local_datapath *ld;
> HMAP_FOR_EACH (ld, hmap_node, local_datapaths) {
> /* XXX Add method to limit zone assignment to logical router
> @@ -571,6 +573,8 @@ update_ct_zones(const struct sset *lports, const struct
> hmap *local_datapaths,
> char *snat = alloc_nat_zone_key(&ld->datapath->header_.uuid, "snat");
> sset_add(&all_users, dnat);
> sset_add(&all_users, snat);
> + shash_add(&all_lds, dnat, ld);
> + shash_add(&all_lds, snat, ld);
>
> int req_snat_zone = datapath_snat_ct_zone(ld->datapath);
> if (req_snat_zone >= 0) {
> @@ -636,6 +640,11 @@ update_ct_zones(const struct sset *lports, const struct
> hmap *local_datapaths,
>
> bitmap_set1(ct_zone_bitmap, snat_req_node->data);
> simap_put(ct_zones, snat_req_node->name, snat_req_node->data);
> + struct shash_node *ld_node = shash_find(&all_lds,
> snat_req_node->name);
> + if (ld_node) {
> + struct local_datapath *dp = ld_node->data;
> + hmapx_add(updated_dps, (void *) dp->datapath);
> + }
> }
>
> /* xxx This is wasteful to assign a zone to each port--even if no
> @@ -664,10 +673,17 @@ update_ct_zones(const struct sset *lports, const struct
> hmap *local_datapaths,
>
> bitmap_set1(ct_zone_bitmap, zone);
> simap_put(ct_zones, user, zone);
> +
> + struct shash_node *ld_node = shash_find(&all_lds, user);
> + if (ld_node) {
> + struct local_datapath *dp = ld_node->data;
> + hmapx_add(updated_dps, (void *) dp->datapath);
> + }
> }
>
> simap_destroy(&req_snat_zones);
> sset_destroy(&all_users);
> + shash_destroy(&all_lds);
> }
>
> static void
> @@ -1098,6 +1114,9 @@ struct ed_type_runtime_data {
> bool tracked;
> bool local_lports_changed;
> struct hmap tracked_dp_bindings;
> +
> + /* CT zone data. Contains datapaths that had updated CT zones */
> + struct hmapx ct_updated_datapaths;
Thanks for the fix.
The patch overall looks fine to me, except the above hmax -
ct_updated_datapaths. Since this hmapx is modified by
en_ct_zone_run(), it should be part of ct_zone engine data. Since
flow_output engine node also has ct_zone as input,
It can access the hmapx directly.
I went ahead and applied this patch to fix the 159 test case failure
with the below changes. I also added Fixes tag in
the commit message.
****
diff --git a/controller/physical.h b/controller/physical.h
index 0a4c3bab80..0bf13f2683 100644
--- a/controller/physical.h
+++ b/controller/physical.h
@@ -64,8 +64,8 @@ void physical_run(struct physical_ctx *,
struct ovn_desired_flow_table *);
void physical_clear_unassoc_flows_with_db(struct ovn_desired_flow_table *);
void physical_clear_dp_flows(struct physical_ctx *p_ctx,
- struct hmapx *ct_updated_datapaths,
- struct ovn_desired_flow_table *flow_table);
+ struct hmapx *ct_updated_datapaths,
+ struct ovn_desired_flow_table *flow_table);
void physical_handle_port_binding_changes(struct physical_ctx *,
struct ovn_desired_flow_table *);
void physical_handle_mc_group_changes(struct physical_ctx *,
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 53cd1be869..b0f197550c 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -1269,6 +1269,7 @@ en_runtime_data_cleanup(void *data)
}
hmap_destroy(&rt_data->local_datapaths);
local_bindings_destroy(&rt_data->local_bindings);
+ hmapx_destroy(&rt_data->ct_updated_datapaths);
}
*****
Valgrind reported a memory leak. So I added hmapx_destroy during cleanup.
I will submit a follow up patch to move the hmapx to ct_zone engine.
Thanks
Numan
> };
>
> /* struct ed_type_runtime_data has the below members for tracking the
> @@ -1189,6 +1208,8 @@ en_runtime_data_init(struct engine_node *node
> OVS_UNUSED,
> /* Init the tracked data. */
> hmap_init(&data->tracked_dp_bindings);
>
> + hmapx_init(&data->ct_updated_datapaths);
> +
> return data;
> }
>
> @@ -1348,6 +1369,7 @@ en_runtime_data_run(struct engine_node *node, void
> *data)
> sset_init(&rt_data->egress_ifaces);
> smap_init(&rt_data->local_iface_ids);
> local_bindings_init(&rt_data->local_bindings);
> + hmapx_clear(&rt_data->ct_updated_datapaths);
> }
>
> struct binding_ctx_in b_ctx_in;
> @@ -1486,9 +1508,11 @@ en_ct_zones_run(struct engine_node *node, void *data)
> struct ed_type_runtime_data *rt_data =
> engine_get_input_data("runtime_data", node);
>
> + hmapx_clear(&rt_data->ct_updated_datapaths);
> update_ct_zones(&rt_data->local_lports, &rt_data->local_datapaths,
> &ct_zones_data->current, ct_zones_data->bitmap,
> - &ct_zones_data->pending);
> + &ct_zones_data->pending, &rt_data->ct_updated_datapaths);
> +
>
> engine_set_node_state(node, EN_UPDATED);
> }
> @@ -1698,6 +1722,7 @@ static void init_physical_ctx(struct engine_node *node,
> p_ctx->ct_zones = ct_zones;
> p_ctx->mff_ovn_geneve = ed_mff_ovn_geneve->mff_ovn_geneve;
> p_ctx->local_bindings = &rt_data->local_bindings;
> + p_ctx->ct_updated_datapaths = &rt_data->ct_updated_datapaths;
> }
>
> static void init_lflow_ctx(struct engine_node *node,
> @@ -2125,6 +2150,8 @@ flow_output_physical_flow_changes_handler(struct
> engine_node *node, void *data)
> if (pfc_data->recompute_physical_flows) {
> /* This indicates that we need to recompute the physical flows. */
> physical_clear_unassoc_flows_with_db(&fo->flow_table);
> + physical_clear_dp_flows(&p_ctx, &rt_data->ct_updated_datapaths,
> + &fo->flow_table);
> physical_run(&p_ctx, &fo->flow_table);
> return true;
> }
> diff --git a/controller/physical.c b/controller/physical.c
> index 00c4ca4fd..fa5d0d692 100644
> --- a/controller/physical.c
> +++ b/controller/physical.c
> @@ -44,6 +44,7 @@
> #include "sset.h"
> #include "util.h"
> #include "vswitch-idl.h"
> +#include "hmapx.h"
>
> VLOG_DEFINE_THIS_MODULE(physical);
>
> @@ -860,6 +861,28 @@ load_logical_ingress_metadata(const struct
> sbrec_port_binding *binding,
> put_load(port_key, MFF_LOG_INPORT, 0, 32, ofpacts_p);
> }
>
> +static const struct sbrec_port_binding *
> +get_binding_peer(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> + const struct sbrec_port_binding *binding)
> +{
> + const char *peer_name = smap_get(&binding->options, "peer");
> + if (!peer_name) {
> + return NULL;
> + }
> +
> + const struct sbrec_port_binding *peer = lport_lookup_by_name(
> + sbrec_port_binding_by_name, peer_name);
> + if (!peer || strcmp(peer->type, binding->type)) {
> + return NULL;
> + }
> + const char *peer_peer_name = smap_get(&peer->options, "peer");
> + if (!peer_peer_name || strcmp(peer_peer_name, binding->logical_port)) {
> + return NULL;
> + }
> +
> + return peer;
> +}
> +
> static void
> consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> enum mf_field_id mff_ovn_geneve,
> @@ -882,18 +905,10 @@ consider_port_binding(struct ovsdb_idl_index
> *sbrec_port_binding_by_name,
> if (!strcmp(binding->type, "patch")
> || (!strcmp(binding->type, "l3gateway")
> && binding->chassis == chassis)) {
> - const char *peer_name = smap_get(&binding->options, "peer");
> - if (!peer_name) {
> - return;
> - }
>
> - const struct sbrec_port_binding *peer = lport_lookup_by_name(
> - sbrec_port_binding_by_name, peer_name);
> - if (!peer || strcmp(peer->type, binding->type)) {
> - return;
> - }
> - const char *peer_peer_name = smap_get(&peer->options, "peer");
> - if (!peer_peer_name || strcmp(peer_peer_name,
> binding->logical_port)) {
> + const struct sbrec_port_binding *peer = get_binding_peer(
> + sbrec_port_binding_by_name, binding);
> + if (!peer) {
> return;
> }
>
> @@ -926,7 +941,7 @@ consider_port_binding(struct ovsdb_idl_index
> *sbrec_port_binding_by_name,
>
> ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100,
> binding->header_.uuid.parts[0],
> - &match, ofpacts_p, hc_uuid);
> + &match, ofpacts_p, &binding->header_.uuid);
> return;
> }
>
> @@ -1874,3 +1889,22 @@ physical_clear_unassoc_flows_with_db(struct
> ovn_desired_flow_table *flow_table)
> ofctrl_remove_flows(flow_table, hc_uuid);
> }
> }
> +
> +void
> +physical_clear_dp_flows(struct physical_ctx *p_ctx,
> + struct hmapx *ct_updated_datapaths,
> + struct ovn_desired_flow_table *flow_table)
> +{
> + const struct sbrec_port_binding *binding;
> + SBREC_PORT_BINDING_TABLE_FOR_EACH (binding, p_ctx->port_binding_table) {
> + if (!hmapx_find(ct_updated_datapaths, binding->datapath)) {
> + continue;
> + }
> + const struct sbrec_port_binding *peer =
> + get_binding_peer(p_ctx->sbrec_port_binding_by_name, binding);
> + ofctrl_remove_flows(flow_table, &binding->header_.uuid);
> + if (peer) {
> + ofctrl_remove_flows(flow_table, &peer->header_.uuid);
> + }
> + }
> +}
> diff --git a/controller/physical.h b/controller/physical.h
> index feab41df4..0a4c3bab8 100644
> --- a/controller/physical.h
> +++ b/controller/physical.h
> @@ -56,12 +56,16 @@ struct physical_ctx {
> const struct simap *ct_zones;
> enum mf_field_id mff_ovn_geneve;
> struct shash *local_bindings;
> + struct hmapx *ct_updated_datapaths;
> };
>
> void physical_register_ovs_idl(struct ovsdb_idl *);
> void physical_run(struct physical_ctx *,
> struct ovn_desired_flow_table *);
> void physical_clear_unassoc_flows_with_db(struct ovn_desired_flow_table *);
> +void physical_clear_dp_flows(struct physical_ctx *p_ctx,
> + struct hmapx *ct_updated_datapaths,
> + struct ovn_desired_flow_table *flow_table);
> void physical_handle_port_binding_changes(struct physical_ctx *,
> struct ovn_desired_flow_table *);
> void physical_handle_mc_group_changes(struct physical_ctx *,
> --
> 2.25.4
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev