From 9b8c257e6c1f3659e5d7da5954511e76e0c09ab9 Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Wed, 22 Jan 2025 13:30:55 +0100 Subject: bgpd: fix bfd with update-source in peer-group Fix BFD session not created when the peer is in update-group with the update-source option. Signed-off-by: Louis Scalbert --- bgpd/bgp_bfd.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'bgpd') diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 14ff5f2e11..240b310696 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -104,6 +104,10 @@ void bgp_peer_config_apply(struct peer *p, struct peer_group *pg) */ gconfig = pg->conf; + if (CHECK_FLAG(gconfig->flags, PEER_FLAG_UPDATE_SOURCE) || + CHECK_FLAG(p->flags_override, PEER_FLAG_UPDATE_SOURCE)) + bgp_peer_bfd_update_source(p); + /* * If using default control plane independent configuration, * then prefer group's (e.g. it means it wasn't manually configured). -- cgit v1.2.3 From 8c3b2ed3bf95e0be58eb479be1a59bf090bb15ff Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 5 Dec 2024 10:16:03 -0500 Subject: bgpd: When bgp notices a change to shared_network inform bfd of it When bgp is started up and reads the config in *before* it has received interface addresses from zebra, shared_network can be set to false in this case. Later on once bgp attempts to reconnect it will refigure out the shared_network again( because it has received the data from zebra now ). In this case tell bfd about it. Signed-off-by: Donald Sharp --- bgpd/bgp_zebra.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'bgpd') diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 07ab822b03..9fa04e5420 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -744,6 +744,7 @@ bool bgp_zebra_nexthop_set(union sockunion *local, union sockunion *remote, int ret = 0; struct interface *ifp = NULL; bool v6_ll_avail = true; + bool shared_network_original = peer->shared_network; memset(nexthop, 0, sizeof(struct bgp_nexthop)); @@ -908,6 +909,9 @@ bool bgp_zebra_nexthop_set(union sockunion *local, union sockunion *remote, peer->shared_network = 0; } + if (shared_network_original != peer->shared_network) + bgp_peer_bfd_update_source(peer); + /* KAME stack specific treatment. */ #ifdef KAME if (IN6_IS_ADDR_LINKLOCAL(&nexthop->v6_global) -- cgit v1.2.3 From 9679470d719377059aa49345d3957fba4f3d1381 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 20 Nov 2024 16:07:34 -0500 Subject: bgpd: Allow bfd to work if peer known but interface address not yet If bgp is coming up and bgp has not received the interface address yet but bgp has knowledge about a bfd peering, allow it to set the peering data appropriately. Signed-off-by: Donald Sharp --- bgpd/bgp_bfd.c | 8 ++++++-- bgpd/bgp_nexthop.c | 28 +++++++++++++++++----------- 2 files changed, 23 insertions(+), 13 deletions(-) (limited to 'bgpd') diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 240b310696..82dd0b593e 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -145,8 +145,8 @@ void bgp_peer_config_apply(struct peer *p, struct peer_group *pg) void bgp_peer_bfd_update_source(struct peer *p) { - struct bfd_session_params *session = p->bfd_config->session; - const union sockunion *source; + struct bfd_session_params *session; + const union sockunion *source = NULL; bool changed = false; int family; union { @@ -154,6 +154,10 @@ void bgp_peer_bfd_update_source(struct peer *p) struct in6_addr v6; } src, dst; + if (!p->bfd_config) + return; + + session = p->bfd_config->session; /* Nothing to do for groups. */ if (CHECK_FLAG(p->sflags, PEER_STATUS_GROUP)) return; diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index ba6d707109..68a1b85806 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -32,6 +32,7 @@ #include "bgpd/bgp_vty.h" #include "bgpd/bgp_rd.h" #include "bgpd/bgp_mplsvpn.h" +#include "bgpd/bgp_bfd.h" DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Addr Intf String"); @@ -409,17 +410,6 @@ void bgp_connected_add(struct bgp *bgp, struct connected *ifc) bgp_dest_set_bgp_connected_ref_info(dest, bc); } - for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { - if (peer->conf_if && - (strcmp(peer->conf_if, ifc->ifp->name) == 0) && - !peer_established(peer->connection) && - !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) { - connection = peer->connection; - if (peer_active(peer)) - BGP_EVENT_ADD(connection, BGP_Stop); - BGP_EVENT_ADD(connection, BGP_Start); - } - } } else if (addr->family == AF_INET6) { apply_mask_ipv6((struct prefix_ipv6 *)&p); @@ -443,6 +433,22 @@ void bgp_connected_add(struct bgp *bgp, struct connected *ifc) bgp_dest_set_bgp_connected_ref_info(dest, bc); } } + + /* + * Iterate over all the peers and attempt to set the bfd session + * data and if it's a bgp unnumbered get her flowing if necessary + */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + bgp_peer_bfd_update_source(peer); + if (peer->conf_if && (strcmp(peer->conf_if, ifc->ifp->name) == 0) && + !peer_established(peer->connection) && + !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) { + connection = peer->connection; + if (peer_active(peer)) + BGP_EVENT_ADD(connection, BGP_Stop); + BGP_EVENT_ADD(connection, BGP_Start); + } + } } void bgp_connected_delete(struct bgp *bgp, struct connected *ifc) -- cgit v1.2.3 From 643f063d66e787728e63a607d4963941afbdf88d Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Tue, 12 Nov 2024 13:09:09 +0200 Subject: bgpd: Update source address for BFD session If BFD is down, we should try to detect the source automatically from the given interface. Signed-off-by: Donatas Abraitis --- bgpd/bgp_bfd.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'bgpd') diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 82dd0b593e..3f4ef7d5b2 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -26,6 +26,7 @@ #include "bgpd/bgp_debug.h" #include "bgpd/bgp_vty.h" #include "bgpd/bgp_packet.h" +#include "bgpd/bgp_network.h" DEFINE_MTYPE_STATIC(BGPD, BFD_CONFIG, "BFD configuration data"); @@ -153,6 +154,8 @@ void bgp_peer_bfd_update_source(struct peer *p) struct in_addr v4; struct in6_addr v6; } src, dst; + struct interface *ifp; + union sockunion addr; if (!p->bfd_config) return; @@ -163,10 +166,25 @@ void bgp_peer_bfd_update_source(struct peer *p) return; /* Figure out the correct source to use. */ - if (CHECK_FLAG(p->flags, PEER_FLAG_UPDATE_SOURCE) && p->update_source) - source = p->update_source; - else + if (CHECK_FLAG(p->flags, PEER_FLAG_UPDATE_SOURCE)) { + if (p->update_source) { + source = p->update_source; + } else if (p->update_if) { + ifp = if_lookup_by_name(p->update_if, p->bgp->vrf_id); + if (ifp) { + sockunion_init(&addr); + if (bgp_update_address(ifp, &p->connection->su, &addr)) { + if (BGP_DEBUG(bfd, BFD_LIB)) + zlog_debug("%s: can't find the source address for interface %s", + __func__, p->update_if); + } + + source = &addr; + } + } + } else { source = p->su_local; + } /* Update peer's source/destination addresses. */ bfd_sess_addresses(session, &family, &src.v6, &dst.v6); -- cgit v1.2.3 From c295738afcde4a4de597bfddd33ac59ebbe957bc Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Tue, 5 Nov 2024 15:51:58 +0200 Subject: bgpd: Reset BGP session only if it was a real BFD DOWN event Without this patch we always see a double-reset, e.g.: ``` 2024/11/04 12:42:43.010 BGP: [VQY9X-CQZKG] bgp_peer_bfd_update_source: address [0.0.0.0->172.18.0.3] to [172.18.0.2->172.18.0.3] 2024/11/04 12:42:43.010 BGP: [X8BD9-8RKN4] bgp_peer_bfd_update_source: interface none to eth0 2024/11/04 12:42:43.010 BFD: [MSVDW-Y8Z5Q] ptm-del-dest: deregister peer [mhop:no peer:172.18.0.3 local:0.0.0.0 vrf:default cbit:0x00 minimum-ttl:255] 2024/11/04 12:42:43.010 BFD: [NYF5K-SE3NS] ptm-del-session: [mhop:no peer:172.18.0.3 local:0.0.0.0 vrf:default] refcount=0 2024/11/04 12:42:43.010 BFD: [NW21R-MRYNT] session-delete: mhop:no peer:172.18.0.3 local:0.0.0.0 vrf:default 2024/11/04 12:42:43.010 BGP: [P3D3N-3277A] 172.18.0.3 [FSM] Timer (routeadv timer expire) 2024/11/04 12:42:43.010 BFD: [YA0Q5-C0BPV] control-packet: no session found [mhop:no peer:172.18.0.3 local:172.18.0.2 port:11] 2024/11/04 12:42:43.010 BFD: [MSVDW-Y8Z5Q] ptm-add-dest: register peer [mhop:no peer:172.18.0.3 local:172.18.0.2 vrf:default cbit:0x00 minimum-ttl:255] 2024/11/04 12:42:43.011 BFD: [PSB4R-8T1TJ] session-new: mhop:no peer:172.18.0.3 local:172.18.0.2 vrf:default ifname:eth0 2024/11/04 12:42:43.011 BGP: [Q4BCV-6FHZ5] zclient_bfd_session_update: 172.18.0.2/32 -> 172.18.0.3/32 (interface eth0) VRF default(0) (CPI bit no): Down 2024/11/04 12:42:43.011 BGP: [MKVHZ-7MS3V] bfd_session_status_update: neighbor 172.18.0.3 vrf default(0) bfd state Up -> Down 2024/11/04 12:42:43.011 BGP: [HZN6M-XRM1G] %NOTIFICATION: sent to neighbor 172.18.0.3 6/10 (Cease/BFD Down) 0 bytes 2024/11/04 12:42:43.011 BGP: [QFMSE-NPSNN] zclient_bfd_session_update: sessions updated: 1 2024/11/04 12:42:43.011 BGP: [ZWCSR-M7FG9] 172.18.0.3 [FSM] BGP_Stop (Established->Clearing), fd 22 ``` Reset is due to the source address change. With this patch, we reset the session only if it's a _REAL_ BFD down event, which means we trigger session reset if BFD session is established earlier than BGP. Signed-off-by: Donatas Abraitis --- bgpd/bgp_bfd.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'bgpd') diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 3f4ef7d5b2..add93d3a5f 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -54,14 +54,23 @@ static void bfd_session_status_update(struct bfd_session_params *bsp, peer->host); return; } - peer->last_reset = PEER_DOWN_BFD_DOWN; - /* rfc9384 */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_BFD_DOWN); - - BGP_EVENT_ADD(peer->connection, BGP_Stop); + /* Once the BFD session is UP, and later BGP session is UP, + * BFD notices that peer->su_local changed, and BFD session goes down. + * We should trigger BGP session reset if BFD session is UP + * only when BGP session is UP already. + * Otherwise, we end up resetting BGP session when BFD session is UP, + * when the source address is changed, e.g. 0.0.0.0 -> 10.0.0.1. + */ + if (bss->last_event > peer->uptime) { + peer->last_reset = PEER_DOWN_BFD_DOWN; + /* rfc9384 */ + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) + bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_BFD_DOWN); + + BGP_EVENT_ADD(peer->connection, BGP_Stop); + } } if (bss->state == BSS_UP && bss->previous_state != BSS_UP && -- cgit v1.2.3