diff options
| author | Donatas Abraitis <donatas@opensourcerouting.org> | 2022-05-11 19:42:53 +0300 | 
|---|---|---|
| committer | Donatas Abraitis <donatas@opensourcerouting.org> | 2022-05-14 21:43:55 +0300 | 
| commit | 20170775da3a3c5d41aba714d0c1d5a29b0da61c (patch) | |
| tree | ee5d8b05d49086c148a0d45c534a1c02a606f531 /bgpd | |
| parent | daa97042a2720ed46a1c1817d58cd7a9d08b333e (diff) | |
bgpd: Activate Graceful-Restart when receiving CEASE/HOLDTIME notifications
If we receive CEASE Notification or HOLDTIME notification, retain STALE
routes if it's not a CEASE/Hard Reset.
When doing `clear ip bgp PEER`, we can control if this would be CEASE/Hard Reset
or not by using `bgp hard-administrative-reset` knob.
When `bgp graceful-restart notification` is disabled, STALE routes won't be
retained when receiving Notification message.
Co-authored-by: Biswajit Sadhu <biswajit.sadhu@gmail.com>
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
Diffstat (limited to 'bgpd')
| -rw-r--r-- | bgpd/bgp_fsm.c | 9 | ||||
| -rw-r--r-- | bgpd/bgp_packet.c | 20 | ||||
| -rw-r--r-- | bgpd/bgp_packet.h | 1 | 
3 files changed, 26 insertions, 4 deletions
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index cc3505333b..ba018d3f56 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1961,6 +1961,15 @@ static int bgp_fsm_holdtime_expire(struct peer *peer)  	if (bgp_debug_neighbor_events(peer))  		zlog_debug("%s [FSM] Hold timer expire", peer->host); +	/* RFC8538 updates RFC 4724 by defining an extension that permits +	 * the Graceful Restart procedures to be performed when the BGP +	 * speaker receives a BGP NOTIFICATION message or the Hold Time expires. +	 */ +	if (peer_established(peer) && +	    bgp_has_graceful_restart_notification(peer)) +		if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)) +			SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT); +  	return bgp_stop_with_notify(peer, BGP_NOTIFY_HOLD_ERR, 0);  } diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 9a1216a031..29db23fbbd 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -748,6 +748,13 @@ struct bgp_notify bgp_notify_decapsulate_hard_reset(struct bgp_notify *notify)  	return bn;  } +/* Check if Graceful-Restart N-bit is exchanged */ +bool bgp_has_graceful_restart_notification(struct peer *peer) +{ +	return CHECK_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV) && +	       CHECK_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV); +} +  /*   * Check if to send BGP CEASE Notification/Hard Reset?   */ @@ -757,8 +764,7 @@ bool bgp_notify_send_hard_reset(struct peer *peer, uint8_t code,  	/* When the "N" bit has been exchanged, a Hard Reset message is used to  	 * indicate to the peer that the session is to be fully terminated.  	 */ -	if (!CHECK_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV) || -	    !CHECK_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV)) +	if (!bgp_has_graceful_restart_notification(peer))  		return false;  	/* @@ -797,8 +803,7 @@ bool bgp_notify_received_hard_reset(struct peer *peer, uint8_t code,  	/* When the "N" bit has been exchanged, a Hard Reset message is used to  	 * indicate to the peer that the session is to be fully terminated.  	 */ -	if (!CHECK_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV) || -	    !CHECK_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV)) +	if (!bgp_has_graceful_restart_notification(peer))  		return false;  	if (code == BGP_NOTIFY_CEASE && subcode == BGP_NOTIFY_CEASE_HARD_RESET) @@ -2094,6 +2099,13 @@ static int bgp_notify_receive(struct peer *peer, bgp_size_t size)  	    inner.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM)  		UNSET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN); +	/* If Graceful-Restart N-bit (Notification) is exchanged, +	 * and it's not a Hard Reset, let's retain the routes. +	 */ +	if (bgp_has_graceful_restart_notification(peer) && !hard_reset && +	    CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)) +		SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT); +  	bgp_peer_gr_flags_update(peer);  	BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(peer->bgp,  							  peer->bgp->peer); diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h index 92c7f60ac7..a0eb579db7 100644 --- a/bgpd/bgp_packet.h +++ b/bgpd/bgp_packet.h @@ -88,6 +88,7 @@ extern void bgp_send_delayed_eor(struct bgp *bgp);  void bgp_packet_process_error(struct thread *thread);  extern struct bgp_notify  bgp_notify_decapsulate_hard_reset(struct bgp_notify *notify); +extern bool bgp_has_graceful_restart_notification(struct peer *peer);  extern bool bgp_notify_send_hard_reset(struct peer *peer, uint8_t code,  				       uint8_t subcode);  extern bool bgp_notify_received_hard_reset(struct peer *peer, uint8_t code,  | 
