From: root Date: Mon, 19 Nov 2018 12:35:32 +0000 (-0800) Subject: bgpd: Creating Loopback Interface Flaps BGPd (#2865) X-Git-Tag: frr-7.0.1~184^2 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=36dc75886db92145540585ab203c0c9d339a9dae;p=mirror_frr.git bgpd: Creating Loopback Interface Flaps BGPd (#2865) * The function bgp_router_id_zebra_bump() will check for active bgp peers before chenging the router ID. If there are established peers, router ID is not modified which prevents the flapping of established peer connection * Added field in bgp structure to store the count of established peers Signed-off-by: kssoman --- diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 1f0cfd6e2..b70c8bbd6 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -935,9 +935,29 @@ static void bgp_update_delay_process_status_change(struct peer *peer) read/write and timer thread. */ void bgp_fsm_change_status(struct peer *peer, int status) { + struct bgp *bgp; + uint32_t peer_count; bgp_dump_state(peer, peer->status, status); + bgp = peer->bgp; + peer_count = bgp->established_peers; + + if (status == Established) + bgp->established_peers++; + else if ((peer->status == Established) && (status != Established)) + bgp->established_peers--; + + if (BGP_DEBUG(neighbor_events, NEIGHBOR_EVENTS)) + zlog_debug("%s : vrf %u, established_peers %u", __func__, + bgp->vrf_id, bgp->established_peers); + /* Set to router ID to the value provided by RIB if there are no peers + * in the established state and peer count did not change + */ + if ((peer_count != bgp->established_peers) && + (bgp->established_peers == 0)) + bgp_router_id_zebra_bump(bgp->vrf_id, NULL); + /* Transition into Clearing or Deleted must /always/ clear all routes.. * (and must do so before actually changing into Deleted.. */ diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index a078c4f58..48a3b1bb0 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -274,6 +274,10 @@ void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id) { struct listnode *node, *nnode; struct bgp *bgp; + struct in_addr *addr = NULL; + + if (router_id != NULL) + addr = (struct in_addr *)&(router_id->u.prefix4); if (vrf_id == VRF_DEFAULT) { /* Router-id change for default VRF has to also update all @@ -282,17 +286,43 @@ void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id) if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) continue; - bgp->router_id_zebra = router_id->u.prefix4; - if (!bgp->router_id_static.s_addr) - bgp_router_id_set(bgp, &router_id->u.prefix4); + if (addr) + bgp->router_id_zebra = *addr; + else + addr = &bgp->router_id_zebra; + + if (!bgp->router_id_static.s_addr) { + /* Router ID is updated if there are no active + * peer sessions + */ + if (bgp->established_peers == 0) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("RID change : vrf %u, RTR ID %s", + bgp->vrf_id, inet_ntoa(*addr)); + bgp_router_id_set(bgp, addr); + } + } } } else { bgp = bgp_lookup_by_vrf_id(vrf_id); if (bgp) { - bgp->router_id_zebra = router_id->u.prefix4; + if (addr) + bgp->router_id_zebra = *addr; + else + addr = &bgp->router_id_zebra; + + if (!bgp->router_id_static.s_addr) { + /* Router ID is updated if there are no active + * peer sessions + */ + if (bgp->established_peers == 0) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("RID change : vrf %u, RTR ID %s", + bgp->vrf_id, inet_ntoa(*addr)); + bgp_router_id_set(bgp, addr); + } + } - if (!bgp->router_id_static.s_addr) - bgp_router_id_set(bgp, &router_id->u.prefix4); } } } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 70193104b..383fbc1c9 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -542,6 +542,9 @@ struct bgp { /* local esi hash table */ struct hash *esihash; + /* Count of peers in established state */ + uint32_t established_peers; + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(bgp) @@ -1886,5 +1889,4 @@ extern void bgp_update_redist_vrf_bitmaps(struct bgp *, vrf_id_t); /* For benefit of rfapi */ extern struct peer *peer_new(struct bgp *bgp); - #endif /* _QUAGGA_BGPD_H */