From fe0c4ed7ba11ad8654ab868c4bbf9744f8df4db6 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 12 Mar 2020 14:04:30 +0100 Subject: [PATCH] bgpd: reset bfd session when bgp comes up This scenario has been seen against microtik virtual machine with bfd enabled. When remote microtik bgp reestablishes the bgp session after a bgp reset, the bgp establishment comes first, then bfd is initialising. The second point is true for microtik, but not for frrouting, as the frrouting, when receiving bfd down messages, is not at init state. Actually, bfd state is up, and sees the first bfd down packet from bfd as an issue. Consequently, the BGP session is cleared. The fix consists in resetting the BFD session, only if bfd status is considered as up, once BGP comes up. That permits to align state machines of both local and remote bfd. Signed-off-by: Philippe Guibert --- bgpd/bgp_bfd.c | 19 +++++++++++++++++++ bgpd/bgp_bfd.h | 2 ++ bgpd/bgp_fsm.c | 3 +-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 1f650aaeb7..5f4db3dfa8 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -200,6 +200,25 @@ static void bgp_bfd_update_peer(struct peer *peer) bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE); } +/** + * bgp_bfd_reset_peer - reinitialise bfd + * ensures that bfd state machine is restarted + * to be synced with remote bfd + */ +void bgp_bfd_reset_peer(struct peer *peer) +{ + struct bfd_info *bfd_info; + + if (!peer->bfd_info) + return; + bfd_info = (struct bfd_info *)peer->bfd_info; + + /* if status is not down, reset bfd */ + if (bfd_info->status != BFD_STATUS_DOWN) + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); +} + /* * bgp_bfd_update_type - update session type with BFD through zebra. */ diff --git a/bgpd/bgp_bfd.h b/bgpd/bgp_bfd.h index caa5651e3a..b96ebb6c96 100644 --- a/bgpd/bgp_bfd.h +++ b/bgpd/bgp_bfd.h @@ -31,6 +31,8 @@ extern void bgp_bfd_register_peer(struct peer *peer); extern void bgp_bfd_deregister_peer(struct peer *peer); +extern void bgp_bfd_reset_peer(struct peer *peer); + extern void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr); diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 71e2b02602..d2f6477c6a 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1935,8 +1935,7 @@ static int bgp_establish(struct peer *peer) hash_release(peer->bgp->peerhash, peer); hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); - bgp_bfd_deregister_peer(peer); - bgp_bfd_register_peer(peer); + bgp_bfd_reset_peer(peer); return ret; } -- 2.39.5