> Previously local ports that had an external_id:iface-id set would get a > ct-zone assigned on recompute, independent if there is a matching > southbound port_binding for them or if this port_binding can actually > reside on the local chassis. > However during incremental processing this was not the case and only > bound local ports would have their ct zone added or removed (as only > they are included in tracked_dp_bindings). > > To fix this we add a status enum to local_lports that defines if there > is a matching port_binding or not. > The ct_zones engine node no only considers local_lports that are backed > by some port_binding entry. > > This means we can also get rid of workarounds in testcases that where > introduced in 9f052bdb because of this problem. > > Signed-off-by: Felix Huettner <felix.huettner@stackit.cloud>
Acked-by: Lorenzo Bianconi <lorenzo.bianc...@redhat.com> > --- > v6->v7: > * introduced > * addressed review comments > > controller/binding.c | 33 ++++++++++++++++++++++++--------- > controller/binding.h | 8 +++++++- > controller/ct-zone.c | 19 ++++++++++++++----- > controller/ct-zone.h | 2 +- > controller/ovn-controller.c | 21 ++++++++++++--------- > controller/physical.h | 2 +- > controller/route.h | 2 +- > tests/ovn.at | 21 --------------------- > 8 files changed, 60 insertions(+), 48 deletions(-) > > diff --git a/controller/binding.c b/controller/binding.c > index 470aa8c53..f0cc84a50 100644 > --- a/controller/binding.c > +++ b/controller/binding.c > @@ -654,11 +654,19 @@ update_ld_localnet_port(const struct sbrec_port_binding > *binding_rec, > * Also track if the set has changed. > */ > static void > -update_local_lports(const char *iface_id, struct binding_ctx_out *b_ctx) > +update_local_lports(const char *iface_id, struct binding_ctx_out *b_ctx, > + enum binding_local_lport_status status) > { > - if (sset_add(b_ctx->local_lports, iface_id) != NULL) { > - b_ctx->local_lports_changed = true; > + struct simap_node *node = simap_find(b_ctx->local_lports, iface_id); > + if (node && node->data == status) { > + return; > } > + if (node) { > + node->data = status; > + } else { > + simap_put(b_ctx->local_lports, iface_id, status); > + } > + b_ctx->local_lports_changed = true; > } > > /* Remove an interface ID from the set of local lports. Also track if the > @@ -667,7 +675,7 @@ update_local_lports(const char *iface_id, struct > binding_ctx_out *b_ctx) > static void > remove_local_lports(const char *iface_id, struct binding_ctx_out *b_ctx) > { > - if (sset_find_and_delete(b_ctx->local_lports, iface_id)) { > + if (simap_find_and_delete(b_ctx->local_lports, iface_id)) { > b_ctx->local_lports_changed = true; > } > } > @@ -1603,7 +1611,8 @@ consider_vif_lport_(const struct sbrec_port_binding *pb, > b_ctx_out->local_datapaths, > b_ctx_out->tracked_dp_bindings); > update_related_lport(pb, b_ctx_out); > - update_local_lports(pb->logical_port, b_ctx_out); > + update_local_lports(pb->logical_port, b_ctx_out, > + LPORT_STATUS_BOUND); > if (binding_lport_update_port_sec(b_lport, pb) && > b_ctx_out->tracked_dp_bindings) { > tracked_datapath_lport_add(pb, TRACKED_RESOURCE_UPDATED, > @@ -1893,6 +1902,10 @@ consider_localport(const struct sbrec_port_binding *pb, > remove_related_lport(pb, b_ctx_out); > } > > + /* Add all localnet ports to local_ifaces so that we allocate ct zones > + * for them. */ > + update_local_lports(pb->logical_port, b_ctx_out, LPORT_STATUS_BOUND); > + > update_related_lport(pb, b_ctx_out); > return true; > } > @@ -1911,7 +1924,7 @@ consider_nonvif_lport_(const struct sbrec_port_binding > *pb, > pb->datapath->tunnel_key); > > if (our_chassis) { > - update_local_lports(pb->logical_port, b_ctx_out); > + update_local_lports(pb->logical_port, b_ctx_out, LPORT_STATUS_BOUND); > if (!ld) { > add_local_datapath(b_ctx_in->sbrec_datapath_binding_by_key, > b_ctx_in->sbrec_port_binding_by_datapath, > @@ -2017,7 +2030,7 @@ consider_localnet_lport(const struct sbrec_port_binding > *pb, > > /* Add all localnet ports to local_ifaces so that we allocate ct zones > * for them. */ > - update_local_lports(pb->logical_port, b_ctx_out); > + update_local_lports(pb->logical_port, b_ctx_out, LPORT_STATUS_BOUND); > > add_or_del_qos_port(pb->logical_port, true); > update_related_lport(pb, b_ctx_out); > @@ -2118,7 +2131,8 @@ build_local_bindings(struct binding_ctx_in *b_ctx_in, > iface_rec->name); > } > > - update_local_lports(iface_id, b_ctx_out); > + update_local_lports(iface_id, b_ctx_out, > + LPORT_STATUS_NOT_BOUND); > smap_replace(b_ctx_out->local_iface_ids, iface_rec->name, > iface_id); > } else if (smap_get_bool(&iface_rec->external_ids, > @@ -2399,7 +2413,6 @@ consider_iface_claim(const struct ovsrec_interface > *iface_rec, > struct binding_ctx_in *b_ctx_in, > struct binding_ctx_out *b_ctx_out) > { > - update_local_lports(iface_id, b_ctx_out); > smap_replace(b_ctx_out->local_iface_ids, iface_rec->name, iface_id); > > struct shash *local_bindings = &b_ctx_out->lbinding_data->bindings; > @@ -2427,6 +2440,8 @@ consider_iface_claim(const struct ovsrec_interface > *iface_rec, > pb = b_lport->pb; > } > > + update_local_lports(iface_id, b_ctx_out, pb ? LPORT_STATUS_BOUND : > + LPORT_STATUS_NOT_BOUND); > if (!pb) { > /* There is no port_binding row for this local binding. */ > return true; > diff --git a/controller/binding.h b/controller/binding.h > index 00dd9dbf5..8a5c6996c 100644 > --- a/controller/binding.h > +++ b/controller/binding.h > @@ -71,6 +71,12 @@ struct related_lports { > */ > }; > > +enum binding_local_lport_status { > + LPORT_STATUS_NOT_BOUND, /* Set if just iface-id is set but the port is > + not in sb. */ > + LPORT_STATUS_BOUND, /* Set if the port is in sb and locally relevant. */ > +}; > + > void related_lports_init(struct related_lports *); > void related_lports_destroy(struct related_lports *); > > @@ -81,7 +87,7 @@ struct binding_ctx_out { > struct local_binding_data *lbinding_data; > > /* sset of (potential) local lports. */ > - struct sset *local_lports; > + struct simap *local_lports; > /* Track if local_lports have been updated. */ > bool local_lports_changed; > > diff --git a/controller/ct-zone.c b/controller/ct-zone.c > index 469a8fc54..cf8f92b41 100644 > --- a/controller/ct-zone.c > +++ b/controller/ct-zone.c > @@ -167,7 +167,7 @@ out: > } > > void > -ct_zones_update(const struct sset *local_lports, > +ct_zones_update(const struct simap *local_lports, > const struct ovsrec_open_vswitch_table *ovs_table, > const struct hmap *local_datapaths, struct ct_zone_ctx *ctx) > { > @@ -178,9 +178,11 @@ ct_zones_update(const struct sset *local_lports, > unsigned long *unreq_snat_zones_map = bitmap_allocate(MAX_CT_ZONES); > struct simap unreq_snat_zones = SIMAP_INITIALIZER(&unreq_snat_zones); > > - const char *local_lport; > - SSET_FOR_EACH (local_lport, local_lports) { > - sset_add(&all_users, local_lport); > + const struct simap_node *sinode; > + SIMAP_FOR_EACH (sinode, local_lports) { > + if (sinode->data == LPORT_STATUS_BOUND) { > + sset_add(&all_users, sinode->name); > + } > } > > /* Local patched datapath (gateway routers) need zones assigned. */ > @@ -217,7 +219,14 @@ ct_zones_update(const struct sset *local_lports, > SHASH_FOR_EACH_SAFE (node, &ctx->current) { > struct ct_zone *ct_zone = node->data; > if (!sset_contains(&all_users, node->name)) { > - ct_zone_remove(ctx, node->name); > + /* If we started recently and do not monitor all db entries then > we > + * might not have yet learned a port binding entry to the port. > + * In this case we skip removing the zone until we either know > the > + * port binding or we are sure the zone is no longer needed. */ > + if (!(daemon_started_recently() && > + simap_contains(local_lports, node->name))) { > + ct_zone_remove(ctx, node->name); > + } > } else if (!simap_find(&req_snat_zones, node->name)) { > if (ct_zone->zone < min_ct_zone || ct_zone->zone > max_ct_zone) { > ct_zone_remove(ctx, node->name); > diff --git a/controller/ct-zone.h b/controller/ct-zone.h > index 6df03975c..cc313d423 100644 > --- a/controller/ct-zone.h > +++ b/controller/ct-zone.h > @@ -70,7 +70,7 @@ void ct_zones_restore(struct ct_zone_ctx *ctx, > const struct ovsrec_open_vswitch_table *ovs_table, > const struct sbrec_datapath_binding_table *dp_table, > const struct ovsrec_bridge *br_int); > -void ct_zones_update(const struct sset *local_lports, > +void ct_zones_update(const struct simap *local_lports, > const struct ovsrec_open_vswitch_table *ovs_table, > const struct hmap *local_datapaths, > struct ct_zone_ctx *ctx); > diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c > index 4dfb426f9..4e1623163 100644 > --- a/controller/ovn-controller.c > +++ b/controller/ovn-controller.c > @@ -218,7 +218,7 @@ static char *get_file_system_id(void) > static unsigned int > update_sb_monitors(struct ovsdb_idl *ovnsb_idl, > const struct sbrec_chassis *chassis, > - const struct sset *local_ifaces, > + const struct simap *local_ifaces, > const struct shash *local_bindings, > struct hmap *local_datapaths, > bool monitor_all) > @@ -358,7 +358,9 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl, > const char *name; > > ovs_assert(local_bindings); > - SSET_FOR_EACH (name, local_ifaces) { > + const struct simap_node *n; > + SIMAP_FOR_EACH (n, local_ifaces) { > + name = n->name; > /* Skip the VIFs we bound already, we should have a local > datapath > * for those. */ > const struct sbrec_port_binding *local_pb > @@ -1291,8 +1293,9 @@ struct ed_type_runtime_data { > * hypervisor. These logical ports include the VIFs (and their child > * logical ports, if any) that belong to VMs running on the hypervisor, > * l2gateway ports for which options:l2gateway-chassis designates the > - * local hypervisor, and localnet ports. */ > - struct sset local_lports; > + * local hypervisor, and localnet ports. > + * The value is mapped to enum binding_local_lport_status. */ > + struct simap local_lports; > > /* Port bindings that are relevant to the local chassis (VIFs bound > * localy, patch ports). > @@ -1396,7 +1399,7 @@ en_runtime_data_init(struct engine_node *node > OVS_UNUSED, > struct ed_type_runtime_data *data = xzalloc(sizeof *data); > > hmap_init(&data->local_datapaths); > - sset_init(&data->local_lports); > + simap_init(&data->local_lports); > related_lports_init(&data->related_lports); > sset_init(&data->active_tunnels); > hmap_init(&data->qos_map); > @@ -1416,7 +1419,7 @@ en_runtime_data_cleanup(void *data) > { > struct ed_type_runtime_data *rt_data = data; > > - sset_destroy(&rt_data->local_lports); > + simap_destroy(&rt_data->local_lports); > related_lports_destroy(&rt_data->related_lports); > sset_destroy(&rt_data->active_tunnels); > destroy_qos_map(&rt_data->qos_map); > @@ -1530,7 +1533,7 @@ en_runtime_data_run(struct engine_node *node, void > *data) > struct hmap *local_datapaths = &rt_data->local_datapaths; > struct shash *local_active_ipv6_pd = > &rt_data->local_active_ports_ipv6_pd; > struct shash *local_active_ras = &rt_data->local_active_ports_ras; > - struct sset *local_lports = &rt_data->local_lports; > + struct simap *local_lports = &rt_data->local_lports; > struct sset *active_tunnels = &rt_data->active_tunnels; > > static bool first_run = true; > @@ -1542,13 +1545,13 @@ en_runtime_data_run(struct engine_node *node, void > *data) > shash_clear(local_active_ipv6_pd); > shash_clear(local_active_ras); > local_binding_data_destroy(&rt_data->lbinding_data); > - sset_destroy(local_lports); > + simap_destroy(local_lports); > related_lports_destroy(&rt_data->related_lports); > sset_destroy(active_tunnels); > destroy_qos_map(&rt_data->qos_map); > smap_destroy(&rt_data->local_iface_ids); > hmap_init(local_datapaths); > - sset_init(local_lports); > + simap_init(local_lports); > related_lports_init(&rt_data->related_lports); > sset_init(active_tunnels); > hmap_init(&rt_data->qos_map); > diff --git a/controller/physical.h b/controller/physical.h > index 1a126ce8d..77831e536 100644 > --- a/controller/physical.h > +++ b/controller/physical.h > @@ -60,7 +60,7 @@ struct physical_ctx { > const struct sset *active_tunnels; > const struct if_status_mgr *if_mgr; > struct hmap *local_datapaths; > - struct sset *local_lports; > + struct simap *local_lports; > const struct shash *ct_zones; > enum mf_field_id mff_ovn_geneve; > struct shash *local_bindings; > diff --git a/controller/route.h b/controller/route.h > index 5047ce202..15323d357 100644 > --- a/controller/route.h > +++ b/controller/route.h > @@ -37,7 +37,7 @@ struct route_ctx_in { > const char *dynamic_routing_port_mapping; > const struct sset *active_tunnels; > const struct hmap *local_datapaths; > - const struct sset *local_lports; > + const struct simap *local_lports; > struct shash *local_bindings; > }; > > diff --git a/tests/ovn.at b/tests/ovn.at > index cf8cdce3a..fb68abbd1 100644 > --- a/tests/ovn.at > +++ b/tests/ovn.at > @@ -15772,16 +15772,6 @@ echo $request >> hv3/third.expected > > check_packets > > -# ct_zone allocation differs between I+P and recompute: > -# - In I+P an ovs interface with external-ids:iface-id set (but no > -# logical_port in sb) results in no ct_zone allocated. > -# - In recompute, in the same case, a ct_zone is allocated - this is > -# necessary to avoid flushing ct_zone if/when controller is restarted. > -# As migrrator has iface-id set on hv1 but is bound to hv2, we would hit > -# some ct-zone related differences in flows before and after recompute. > -# Avoid/hide this by removing iface-id on hv1. > - > -as hv1 check ovs-vsctl remove Interface migrator external-ids iface-id > OVN_CLEANUP([hv1],[hv2],[hv3]) > > AT_CLEANUP > @@ -16172,11 +16162,6 @@ echo $request >> hv2/n1.expected > > check_packets > > -# ct_zone allocation differs between I+P and recompute. > -# As migrrator has iface-id set on hv1 but is bound to hv2, we would hit > -# some ct-zone related differences in flows before and after recompute. > -# Avoid/hide this by removing iface-id on hv1. > -as hv1 check ovs-vsctl remove Interface migrator external-ids iface-id > OVN_CLEANUP([hv1],[hv2],[hv3]) > > AT_CLEANUP > @@ -16733,12 +16718,6 @@ m4_define([ACTIVATION_STRATEGY_TEST], > check ovn-nbctl lsp-set-options migrator requested-chassis=hv2 > OVS_WAIT_UNTIL([test x = x$(ovn-sbctl get Port_Binding $pb_uuid > options:additional-chassis-activated)]) > > - # ct_zone allocation differs between I+P and recompute. > - # As migrrator has iface-id set on hv1 but is bound to hv2, we would hit > - # some ct-zone related differences in flows before and after recompute. > - # Avoid/hide this by removing iface-id on hv1. > - as hv1 check ovs-vsctl remove Interface migrator external-ids iface-id > - > OVN_CLEANUP([hv1],[hv2],[hv3]) > > AT_CLEANUP > -- > 2.43.0 > > > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev >
_______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev