On Wed, Jun 18, 2025 at 7:33 AM Ales Musil <[email protected]> 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 <[email protected]>
> ---
> 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
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev