On Wed, Jun 18, 2025 at 9:45 AM Ales Musil <amu...@redhat.com> wrote:

>
>
> 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
>

Recheck-request: github-robot-_Build_and_Test
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to