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);
}
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?
*/
/* 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;
/*
/* 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)
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);
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,