From af8496af080d4655fdb80542af0bcf0a65bb74cc Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Sat, 15 Jan 2022 23:16:15 +0200 Subject: [PATCH] bgpd: Do not delete BGP dynamic peers if graceful restart kicks in ``` ~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17 *donatas-pc(192.168.10.17) 4 65002 8 12 0 0 0 00:01:35 2 14 N/A ``` Before shutting down 192.168.10.17: ``` ~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32' BGP routing table entry for 100.100.100.100/32, version 7 Paths: (2 available, best #2, table default) Advertised to non peer-group peers: home-spine1.donatas.net(192.168.0.2) 65002, (stale) 192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0) Origin incomplete, valid, external Last update: Sat Jan 15 21:45:47 2022 65001 192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2) Origin incomplete, metric 0, valid, external, best (Older Path) Last update: Sat Jan 15 21:25:19 2022 ``` After 192.168.10.17 is down: ``` ~# vtysh -c 'show bgp ipv4 unicast summary' | grep 192.168.10.17 donatas-pc(192.168.10.17) 4 65002 5 9 0 0 0 00:00:12 Active 0 N/A ~# vtysh -c 'show bgp ipv4 unicast 100.100.100.100/32' BGP routing table entry for 100.100.100.100/32, version 7 Paths: (2 available, best #2, table default) Advertised to non peer-group peers: home-spine1.donatas.net(192.168.0.2) 65002, (stale) 192.168.10.17 from donatas-pc(192.168.10.17) (0.0.0.0) Origin incomplete, valid, external Community: llgr-stale Last update: Sat Jan 15 21:49:01 2022 Time until Long-lived stale route deleted: 16 65001 192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (2.2.2.2) Origin incomplete, metric 0, valid, external, best (First path received) Last update: Sat Jan 15 21:25:19 2022 ``` Signed-off-by: Donatas Abraitis --- bgpd/bgp_fsm.c | 18 +++++++++++++----- bgpd/bgpd.h | 10 ++++++++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 45e9aad1ba..c2e3d02230 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -662,6 +662,14 @@ static void bgp_graceful_restart_timer_off(struct peer *peer) UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT); BGP_TIMER_OFF(peer->t_gr_stale); + + if (peer_dynamic_neighbor(peer) && + !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s (dynamic neighbor) deleted", peer->host); + peer_delete(peer); + } + bgp_timer_set(peer); } @@ -1380,8 +1388,8 @@ int bgp_stop(struct peer *peer) && peer->last_reset == PEER_DOWN_UPDATE_SOURCE_CHANGE) bfd_sess_uninstall(peer->bfd_config->session); - if (peer_dynamic_neighbor(peer) - && !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) { + if (peer_dynamic_neighbor_no_nsf(peer) && + !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) { if (bgp_debug_neighbor_events(peer)) zlog_debug("%s (dynamic neighbor) deleted", peer->host); peer_delete(peer); @@ -1602,7 +1610,7 @@ static int bgp_stop_with_error(struct peer *peer) if (peer->v_start >= (60 * 2)) peer->v_start = (60 * 2); - if (peer_dynamic_neighbor(peer)) { + if (peer_dynamic_neighbor_no_nsf(peer)) { if (bgp_debug_neighbor_events(peer)) zlog_debug("%s (dynamic neighbor) deleted", peer->host); peer_delete(peer); @@ -1620,7 +1628,7 @@ static int bgp_stop_with_notify(struct peer *peer, uint8_t code, /* Send notify to remote peer */ bgp_notify_send(peer, code, sub_code); - if (peer_dynamic_neighbor(peer)) { + if (peer_dynamic_neighbor_no_nsf(peer)) { if (bgp_debug_neighbor_events(peer)) zlog_debug("%s (dynamic neighbor) deleted", peer->host); peer_delete(peer); @@ -1781,7 +1789,7 @@ static int bgp_connect_success_w_delayopen(struct peer *peer) /* TCP connect fail */ static int bgp_connect_fail(struct peer *peer) { - if (peer_dynamic_neighbor(peer)) { + if (peer_dynamic_neighbor_no_nsf(peer)) { if (bgp_debug_neighbor_events(peer)) zlog_debug("%s (dynamic neighbor) deleted", peer->host); peer_delete(peer); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 747c185e39..57d135e781 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -2380,9 +2380,15 @@ static inline bool peer_established(struct peer *peer) return peer->status == Established; } -static inline int peer_dynamic_neighbor(struct peer *peer) +static inline bool peer_dynamic_neighbor(struct peer *peer) { - return (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR)) ? 1 : 0; + return CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR); +} + +static inline bool peer_dynamic_neighbor_no_nsf(struct peer *peer) +{ + return (peer_dynamic_neighbor(peer) && + !CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)); } static inline int peer_cap_enhe(struct peer *peer, afi_t afi, safi_t safi)