From 7bbc6864de7071873fc47680cb80a583280495b3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 22 Jul 2015 12:35:37 -0700 Subject: [PATCH] When IPv6 peer BFD down status is received by BGP, all the the peers for which the BFD is enabled are brought down. This happens due to reverse memcmp check of destination and source IPv6 addresses with the BFD enabled BGP peers. Fixed it by doing the memcmp correctly. Also, there is no reason stored in the last_reset field when BGP peer goes down due BFD. Incorrect/no peer down reason can get logged when BGP peer goes down due to BFD. Fixed it by adding new BFD peer down reason code and storing it in the peer last_reset field when peer is broght down due to BFD. --- bgpd/bgp_bfd.c | 44 ++++++++++++++++++++++++++++++-------------- bgpd/bgp_fsm.c | 3 ++- bgpd/bgpd.h | 1 + 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 3005373d25..02047f7f07 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -337,36 +337,52 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient, if (!CHECK_FLAG (peer->flags, PEER_FLAG_BFD)) continue; - if (dp.family == AF_INET) - if (dp.u.prefix4.s_addr != peer->su.sin.sin_addr.s_addr) - continue; + if ((dp.family == AF_INET) && (peer->su.sa.sa_family == AF_INET)) + { + if (dp.u.prefix4.s_addr != peer->su.sin.sin_addr.s_addr) + continue; + } #ifdef HAVE_IPV6 - else if (dp.family == AF_INET6) - if (!memcmp(&dp.u.prefix6, &peer->su.sin6.sin6_addr, - sizeof (struct in6_addr))) - continue; + else if ((dp.family == AF_INET6) && + (peer->su.sa.sa_family == AF_INET6)) + { + if (memcmp(&dp.u.prefix6, &peer->su.sin6.sin6_addr, + sizeof (struct in6_addr))) + continue; + } #endif else continue; if (ifp && (ifp == peer->nexthop.ifp)) + { + peer->last_reset = PEER_DOWN_BFD_DOWN; BGP_EVENT_ADD (peer, BGP_Stop); + } else { if (!peer->su_local) continue; - if (sp.family == AF_INET) - if (sp.u.prefix4.s_addr != peer->su_local->sin.sin_addr.s_addr) - continue; + if ((sp.family == AF_INET) && + (peer->su_local->sa.sa_family == AF_INET)) + { + if (sp.u.prefix4.s_addr != peer->su_local->sin.sin_addr.s_addr) + continue; + } #ifdef HAVE_IPV6 - else if (sp.family == AF_INET6) - if (!memcmp(&sp.u.prefix6, &peer->su_local->sin6.sin6_addr, - sizeof (struct in6_addr))) - continue; + else if ((sp.family == AF_INET6) && + (peer->su_local->sa.sa_family == AF_INET6)) + { + if (memcmp(&sp.u.prefix6, &peer->su_local->sin6.sin6_addr, + sizeof (struct in6_addr))) + continue; + } #endif else continue; + + peer->last_reset = PEER_DOWN_BFD_DOWN; BGP_EVENT_ADD (peer, BGP_Stop); } } diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 6948a6defb..ec9427bb49 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -475,7 +475,8 @@ const char *peer_down_str[] = "Passive config change", "Multihop config change", "NSF peer closed the session", - "Intf peering v6only config change" + "Intf peering v6only config change", + "BFD down received" }; static int diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 4bbfbf7192..1778aadbef 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -799,6 +799,7 @@ struct peer #define PEER_DOWN_MULTIHOP_CHANGE 21 /* neighbor multihop command */ #define PEER_DOWN_NSF_CLOSE_SESSION 22 /* NSF tcp session close */ #define PEER_DOWN_V6ONLY_CHANGE 23 /* if-based peering v6only toggled */ +#define PEER_DOWN_BFD_DOWN 24 /* BFD down */ unsigned long last_reset_cause_size; u_char last_reset_cause[BGP_MAX_PACKET_SIZE]; -- 2.39.5