On Wed, Jun 18, 2025 at 7:33 AM Ales Musil <amu...@redhat.com> wrote:
> The function behavior would be unexpected in cases when there is > BFD flap between two gateway chassis. This would result in two > chassis claiming that the port binding should be claimed by them. > This leads to multiple problems like unsent gARPs. The gARP problem > on its own was solved [0], but unfortunately reintroduced [1] in > slightly different form. > > The conclusion from the investigation is that the function in > the current form is easy to misuse. To prevent that use > only SB state to determine which chassis has actually claimed > the port binding. This is the desired behavior in cases where > this function was used previously. > > The code that determines which chassis should claim port binding > based on BFD status remains unchanged, thus the behavior during > failover should be the same with minimizing the impact for BFD > flapping cases. > > [0] 289ec19b01ad ("pinctrl: Fix missing garp.") > [1] 05527bd6ccdb ("controller: Extract garp_rarp to engine node."). > > Signed-off-by: Ales Musil <amu...@redhat.com> > --- > controller/garp_rarp.c | 8 +++----- > controller/lport.c | 19 +++++++------------ > controller/lport.h | 3 --- > controller/ovn-controller.c | 11 ++--------- > controller/physical.c | 3 +-- > controller/pinctrl.c | 22 ++++++++-------------- > controller/pinctrl.h | 1 - > controller/route.c | 5 +---- > controller/route.h | 2 -- > 9 files changed, 22 insertions(+), 52 deletions(-) > > diff --git a/controller/garp_rarp.c b/controller/garp_rarp.c > index ef377e26b..551d8303f 100644 > --- a/controller/garp_rarp.c > +++ b/controller/garp_rarp.c > @@ -17,6 +17,7 @@ > #include <config.h> > > #include "controller/local_data.h" > +#include "lport.h" > #include "mac-binding-index.h" > #include "openvswitch/hmap.h" > #include "openvswitch/vlog.h" > @@ -147,11 +148,7 @@ consider_nat_address(struct ovsdb_idl_index > *sbrec_port_binding_by_name, > { > struct lport_addresses *laddrs = xmalloc(sizeof *laddrs); > char *lport = NULL; > - const struct sbrec_port_binding *cr_pb = NULL; > bool rc = extract_addresses_with_port(nat_address, laddrs, &lport); > - if (lport) { > - cr_pb = lport_lookup_by_name(sbrec_port_binding_by_name, lport); > - } > if (!rc > || (!lport && !strcmp(pb->type, "patch"))) { > destroy_lport_addresses(laddrs); > @@ -160,7 +157,8 @@ consider_nat_address(struct ovsdb_idl_index > *sbrec_port_binding_by_name, > return; > } > if (lport) { > - if (!cr_pb || (cr_pb->chassis != chassis)) { > + if (!lport_is_chassis_resident(sbrec_port_binding_by_name, > + chassis, lport)) { > sset_add(non_local_lports, lport); > destroy_lport_addresses(laddrs); > free(laddrs); > diff --git a/controller/lport.c b/controller/lport.c > index 92de375b5..1ea57a5ca 100644 > --- a/controller/lport.c > +++ b/controller/lport.c > @@ -65,35 +65,30 @@ lport_lookup_by_key(struct ovsdb_idl_index > *sbrec_datapath_binding_by_key, > > bool > lport_pb_is_chassis_resident(const struct sbrec_chassis *chassis, > - const struct sset *active_tunnels, > const struct sbrec_port_binding *pb) > { > if (!pb || !pb->chassis) { > return false; > } > - if (strcmp(pb->type, "chassisredirect")) { > - return pb->chassis == chassis; > - } else { > - return ha_chassis_group_is_active(pb->ha_chassis_group, > - active_tunnels, chassis); > - } > + > + /* Note we relay on SB to provide the information, this is needed in > case > + * of flapping BFD when it's not detected by one side. */ > + return pb->chassis == chassis; > } > > bool > lport_is_chassis_resident(struct ovsdb_idl_index > *sbrec_port_binding_by_name, > const struct sbrec_chassis *chassis, > - const struct sset *active_tunnels, > const char *port_name) > { > const struct sbrec_port_binding *pb > = lport_lookup_by_name(sbrec_port_binding_by_name, port_name); > - return lport_pb_is_chassis_resident(chassis, active_tunnels, pb); > + return lport_pb_is_chassis_resident(chassis, pb); > } > > bool > lport_is_local(struct ovsdb_idl_index *sbrec_port_binding_by_name, > const struct sbrec_chassis *chassis, > - const struct sset *active_tunnels, > const char *port_name) > { > const struct sbrec_port_binding *pb = lport_lookup_by_name( > @@ -103,14 +98,14 @@ lport_is_local(struct ovsdb_idl_index > *sbrec_port_binding_by_name, > return false; > } > > - if (lport_pb_is_chassis_resident(chassis, active_tunnels, pb)) { > + if (lport_pb_is_chassis_resident(chassis, pb)) { > return true; > } > > const struct sbrec_port_binding *cr_pb = > lport_get_cr_port(sbrec_port_binding_by_name, pb, NULL); > > - return lport_pb_is_chassis_resident(chassis, active_tunnels, cr_pb); > + return lport_pb_is_chassis_resident(chassis, cr_pb); > } > > const struct sbrec_port_binding * > diff --git a/controller/lport.h b/controller/lport.h > index 8b1809a27..6d48301d2 100644 > --- a/controller/lport.h > +++ b/controller/lport.h > @@ -62,15 +62,12 @@ const struct sbrec_multicast_group > *mcgroup_lookup_by_dp_name( > bool > lport_is_chassis_resident(struct ovsdb_idl_index > *sbrec_port_binding_by_name, > const struct sbrec_chassis *chassis, > - const struct sset *active_tunnels, > const char *port_name); > bool lport_pb_is_chassis_resident(const struct sbrec_chassis *chassis, > - const struct sset *active_tunnels, > const struct sbrec_port_binding *pb); > > bool lport_is_local(struct ovsdb_idl_index *sbrec_port_binding_by_name, > const struct sbrec_chassis *chassis, > - const struct sset *active_tunnels, > const char *port_name); > const struct sbrec_port_binding *lport_get_peer( > const struct sbrec_port_binding *, > diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c > index 7940091da..e0dc754a7 100644 > --- a/controller/ovn-controller.c > +++ b/controller/ovn-controller.c > @@ -5062,7 +5062,6 @@ en_route_run(struct engine_node *node, void *data) > .sbrec_port_binding_by_name = sbrec_port_binding_by_name, > .chassis = chassis, > .dynamic_routing_port_mapping = dynamic_routing_port_mapping, > - .active_tunnels = &rt_data->active_tunnels, > .local_datapaths = &rt_data->local_datapaths, > .local_bindings = &rt_data->lbinding_data.bindings, > }; > @@ -5164,7 +5163,6 @@ route_runtime_data_handler(struct engine_node *node, > void *data) > struct tracked_lport *lport = shash_node->data; > > if (route_exchange_find_port(sbrec_port_binding_by_name, > chassis, > - &rt_data->active_tunnels, > lport->pb)) { > /* XXX: Until we get I-P support for route exchange we > need to > * request recompute. */ > @@ -5222,8 +5220,6 @@ route_sb_port_binding_data_handler(struct > engine_node *node, void *data) > engine_ovsdb_node_get_index( > engine_get_input("SB_port_binding", node), > "name"); > - struct ed_type_runtime_data *rt_data = > - engine_get_input_data("runtime_data", node); > > > /* There are the following cases where we need to handle updates to > the > @@ -5246,8 +5242,8 @@ route_sb_port_binding_data_handler(struct > engine_node *node, void *data) > return EN_UNHANDLED; > } > > - if (route_exchange_find_port(sbrec_port_binding_by_name, chassis, > - &rt_data->active_tunnels, sbrec_pb)) > { > + if (route_exchange_find_port(sbrec_port_binding_by_name, > + chassis, sbrec_pb)) { > /* XXX: Until we get I-P support for route exchange we need to > * request recompute. */ > return EN_UNHANDLED; > @@ -5556,7 +5552,6 @@ garp_rarp_sb_port_binding_handler(struct engine_node > *node, > > if (sset_contains(&data->non_local_lports, pb->logical_port) && > lport_is_chassis_resident(sbrec_port_binding_by_name, chassis, > - &rt_data->active_tunnels, > pb->logical_port)) { > /* XXX: actually handle this incrementally. */ > return EN_UNHANDLED; > @@ -5564,7 +5559,6 @@ garp_rarp_sb_port_binding_handler(struct engine_node > *node, > > if (sset_contains(&data->local_lports, pb->logical_port) && > !lport_is_chassis_resident(sbrec_port_binding_by_name, > chassis, > - &rt_data->active_tunnels, > pb->logical_port)) { > /* XXX: actually handle this incrementally. */ > return EN_UNHANDLED; > @@ -6650,7 +6644,6 @@ main(int argc, char *argv[]) > ovnsb_idl_loop.idl), > chassis, > &runtime_data->local_datapaths, > - &runtime_data->active_tunnels, > > &runtime_data->local_active_ports_ipv6_pd, > &runtime_data->local_active_ports_ras, > ovsrec_open_vswitch_table_get( > diff --git a/controller/physical.c b/controller/physical.c > index 65b4c7335..1cc4173b2 100644 > --- a/controller/physical.c > +++ b/controller/physical.c > @@ -872,8 +872,7 @@ put_replace_router_port_mac_flows(const struct > physical_ctx *ctx, > struct ofpact_mac *replace_mac; > char *cr_peer_name = xasprintf("cr-%s", > rport_binding->logical_port); > if (lport_is_chassis_resident(ctx->sbrec_port_binding_by_name, > - ctx->chassis, ctx->active_tunnels, > - cr_peer_name)) { > + ctx->chassis, cr_peer_name)) { > /* If a router port's chassisredirect port is > * resident on this chassis, then we need not do mac replace. > */ > free(cr_peer_name); > diff --git a/controller/pinctrl.c b/controller/pinctrl.c > index 545f1b174..d4f4da731 100644 > --- a/controller/pinctrl.c > +++ b/controller/pinctrl.c > @@ -366,8 +366,7 @@ pinctrl_handle_bfd_msg(struct rconn *swconn, const > struct flow *ip_flow, > static void bfd_monitor_run(struct ovsdb_idl_txn *ovnsb_idl_txn, > const struct sbrec_bfd_table *bfd_table, > struct ovsdb_idl_index > *sbrec_port_binding_by_name, > - const struct sbrec_chassis *chassis, > - const struct sset *active_tunnels) > + const struct sbrec_chassis *chassis) > OVS_REQUIRES(pinctrl_mutex); > static void init_fdb_entries(void); > static void destroy_fdb_entries(void); > @@ -1434,7 +1433,6 @@ prepare_ipv6_prefixd(struct ovsdb_idl_txn > *ovnsb_idl_txn, > struct ovsdb_idl_index *sbrec_port_binding_by_name, > const struct shash *local_active_ports_ipv6_pd, > const struct sbrec_chassis *chassis, > - const struct sset *active_tunnels, > const struct hmap *local_datapaths) > OVS_REQUIRES(pinctrl_mutex) > { > @@ -1463,9 +1461,8 @@ prepare_ipv6_prefixd(struct ovsdb_idl_txn > *ovnsb_idl_txn, > } > > char *redirect_name = xasprintf("cr-%s", pb->logical_port); > - bool resident = lport_is_chassis_resident( > - sbrec_port_binding_by_name, chassis, active_tunnels, > - redirect_name); > + bool resident = > lport_is_chassis_resident(sbrec_port_binding_by_name, > + chassis, redirect_name); > free(redirect_name); > if ((strcmp(pb->type, "l3gateway") || pb->chassis != chassis) && > !resident) { > @@ -4070,7 +4067,6 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, > const struct sbrec_ecmp_nexthop_table *ecmp_nh_table, > const struct sbrec_chassis *chassis, > const struct hmap *local_datapaths, > - const struct sset *active_tunnels, > const struct shash *local_active_ports_ipv6_pd, > const struct shash *local_active_ports_ras, > const struct ovsrec_open_vswitch_table *ovs_table, > @@ -4086,7 +4082,7 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, > prepare_ipv6_ras(local_active_ports_ras, sbrec_port_binding_by_name); > prepare_ipv6_prefixd(ovnsb_idl_txn, sbrec_port_binding_by_name, > local_active_ports_ipv6_pd, chassis, > - active_tunnels, local_datapaths); > + local_datapaths); > controller_event_run(ovnsb_idl_txn, ce_table, chassis); > ip_mcast_sync(ovnsb_idl_txn, chassis, local_datapaths, > sbrec_datapath_binding_by_key, > @@ -4101,7 +4097,7 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, > sync_svc_monitors(ovnsb_idl_txn, svc_mon_table, > sbrec_port_binding_by_name, > chassis); > bfd_monitor_run(ovnsb_idl_txn, bfd_table, sbrec_port_binding_by_name, > - chassis, active_tunnels); > + chassis); > run_put_fdbs(ovnsb_idl_txn, sbrec_port_binding_by_key, > sbrec_datapath_binding_by_key, sbrec_fdb_by_dp_key_mac); > run_activated_ports(ovnsb_idl_txn, sbrec_datapath_binding_by_key, > @@ -7749,8 +7745,7 @@ static void > bfd_monitor_run(struct ovsdb_idl_txn *ovnsb_idl_txn, > const struct sbrec_bfd_table *bfd_table, > struct ovsdb_idl_index *sbrec_port_binding_by_name, > - const struct sbrec_chassis *chassis, > - const struct sset *active_tunnels) > + const struct sbrec_chassis *chassis) > OVS_REQUIRES(pinctrl_mutex) > { > struct bfd_entry *entry; > @@ -7782,9 +7777,8 @@ bfd_monitor_run(struct ovsdb_idl_txn *ovnsb_idl_txn, > } > > char *redirect_name = xasprintf("cr-%s", pb->logical_port); > - bool resident = lport_is_chassis_resident( > - sbrec_port_binding_by_name, chassis, active_tunnels, > - redirect_name); > + bool resident = > lport_is_chassis_resident(sbrec_port_binding_by_name, > + chassis, redirect_name); > free(redirect_name); > if ((strcmp(pb->type, "l3gateway") || pb->chassis != chassis) && > !resident) { > diff --git a/controller/pinctrl.h b/controller/pinctrl.h > index f977d1168..80384ac9b 100644 > --- a/controller/pinctrl.h > +++ b/controller/pinctrl.h > @@ -57,7 +57,6 @@ void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, > const struct sbrec_ecmp_nexthop_table *, > const struct sbrec_chassis *chassis, > const struct hmap *local_datapaths, > - const struct sset *active_tunnels, > const struct shash *local_active_ports_ipv6_pd, > const struct shash *local_active_ports_ras, > const struct ovsrec_open_vswitch_table *ovs_table, > diff --git a/controller/route.c b/controller/route.c > index 2ea53a287..7615f3f59 100644 > --- a/controller/route.c > +++ b/controller/route.c > @@ -52,7 +52,6 @@ advertise_route_hash(const struct in6_addr *dst, > unsigned int plen) > const struct sbrec_port_binding* > route_exchange_find_port(struct ovsdb_idl_index > *sbrec_port_binding_by_name, > const struct sbrec_chassis *chassis, > - const struct sset *active_tunnels, > const struct sbrec_port_binding *pb) > { > if (!pb) { > @@ -69,7 +68,7 @@ route_exchange_find_port(struct ovsdb_idl_index > *sbrec_port_binding_by_name, > return NULL; > } > > - if (!lport_pb_is_chassis_resident(chassis, active_tunnels, cr_pb)) { > + if (!lport_pb_is_chassis_resident(chassis, cr_pb)) { > return NULL; > } > > @@ -171,7 +170,6 @@ route_run(struct route_ctx_in *r_ctx_in, > const struct sbrec_port_binding *repb = > > route_exchange_find_port(r_ctx_in->sbrec_port_binding_by_name, > r_ctx_in->chassis, > - r_ctx_in->active_tunnels, > local_peer); > if (!repb) { > continue; > @@ -257,7 +255,6 @@ route_run(struct route_ctx_in *r_ctx_in, > if (route->tracked_port) { > if (lport_is_local(r_ctx_in->sbrec_port_binding_by_name, > r_ctx_in->chassis, > - r_ctx_in->active_tunnels, > route->tracked_port->logical_port)) { > priority = PRIORITY_LOCAL_BOUND; > sset_add(r_ctx_out->tracked_ports_local, > diff --git a/controller/route.h b/controller/route.h > index 11016d818..09aff89ff 100644 > --- a/controller/route.h > +++ b/controller/route.h > @@ -35,7 +35,6 @@ struct route_ctx_in { > struct ovsdb_idl_index *sbrec_port_binding_by_name; > const struct sbrec_chassis *chassis; > const char *dynamic_routing_port_mapping; > - const struct sset *active_tunnels; > const struct hmap *local_datapaths; > struct shash *local_bindings; > }; > @@ -81,7 +80,6 @@ struct advertise_route_entry { > const struct sbrec_port_binding *route_exchange_find_port( > struct ovsdb_idl_index *sbrec_port_binding_by_name, > const struct sbrec_chassis *chassis, > - const struct sset *active_tunnels, > const struct sbrec_port_binding *pb); > uint32_t advertise_route_hash(const struct in6_addr *dst, unsigned int > plen); > void route_run(struct route_ctx_in *, struct route_ctx_out *); > -- > 2.49.0 > > Load image error, let's try again. Recheck-request: github-robot-_Build_and_Test _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev