summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_fsm.c20
-rw-r--r--bgpd/bgpd.c42
-rw-r--r--bgpd/bgpd.h4
3 files changed, 59 insertions, 7 deletions
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 1f0cfd6e25..b70c8bbd63 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 a078c4f587..48a3b1bb09 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 70193104b4..383fbc1c92 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 */