bgp tcp connection.
When the BGP peer is configured between two bgp routes both routers would create
peer structure , when they receive each other’s open message. In this event both
speakers, open duplicate TCP sessions and send OPEN messages on each socket
simultaneously, the BGP Identifier is used to resolve which socket should be closed.
If BGP GR is enabled the old tcp session is dumped and the new session is retained.
So while this transfer of connection is happening, if all the bgp gr config
is not migrated to the new connection, the new bgp gr mode will never get applied.
Fix Summary:
1. Replicate GR configuration from the old session to the new session in bgp_accept().
2. Replicate GR configuration from stub to full-fledged peer in bgp_establish().
3. Disable all NSF flags, clear stale routes (if present), stop restart & stale timers
(if they are running) when the bgp GR mode is changed to “Disabled”.
4. Disable R-bit in cap, if it is not set the received open message.
Signed-off-by: Biswajit Sadhu <sadhub@vmware.com>
peer->remote_id = from_peer->remote_id;
peer->last_reset = from_peer->last_reset;
+ peer->peer_gr_present_state = from_peer->peer_gr_present_state;
+ peer->peer_gr_new_status_flag = from_peer->peer_gr_new_status_flag;
+ bgp_peer_gr_flags_update(peer);
+
+ if (bgp_peer_gr_mode_get(peer) == PEER_DISABLE) {
+
+ UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
+
+ if (CHECK_FLAG(peer->sflags,
+ PEER_STATUS_NSF_WAIT)) {
+ peer_nsf_stop(peer);
+ }
+ }
+
if (from_peer->hostname != NULL) {
if (peer->hostname) {
XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
peer->host,
(CHECK_FLAG(peer->flags,
PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT) ?
- "Set" : "UnSet"));
+ "Set" : "UnSet"));
+
+ if (!CHECK_FLAG(peer->flags,
+ PEER_FLAG_GRACEFUL_RESTART) &&
+ !CHECK_FLAG(peer->flags,
+ PEER_FLAG_GRACEFUL_RESTART_HELPER)){
+ zlog_debug(
+ "BGP_GR:: Peer %s UNSET PEER_STATUS_NSF_MODE!",
+ peer->host);
+
+ UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
+
+ if (CHECK_FLAG(peer->sflags,
+ PEER_STATUS_NSF_WAIT)) {
+
+ peer_nsf_stop(peer);
+ zlog_debug(
+ "BGP_GR:: Peer %s UNSET PEER_STATUS_NSF_WAIT!",
+ peer->host);
+ }
+ }
}
safe_strerror(errno));
if (peer->status == Established) {
- if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)) {
+ if ((CHECK_FLAG(peer->flags,
+ PEER_FLAG_GRACEFUL_RESTART) ||
+ CHECK_FLAG(peer->flags,
+ PEER_FLAG_GRACEFUL_RESTART_HELPER)) &&
+ CHECK_FLAG(peer->sflags,
+ PEER_STATUS_NSF_MODE)) {
peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
} else
} else if (nbytes == 0) {
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s [Event] BGP connection closed fd %d",
- peer->host, peer->fd);
+ peer->host, peer->fd);
if (peer->status == Established) {
- if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)) {
+ if ((CHECK_FLAG(peer->flags,
+ PEER_FLAG_GRACEFUL_RESTART) ||
+ CHECK_FLAG(peer->flags,
+ PEER_FLAG_GRACEFUL_RESTART_HELPER)) &&
+ CHECK_FLAG(peer->sflags,
+ PEER_STATUS_NSF_MODE)) {
peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
} else
hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
peer_xfer_config(peer, peer1);
+ bgp_peer_gr_flags_update(peer);
+
+ if (bgp_peer_gr_mode_get(peer) == PEER_DISABLE) {
+
+ UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
+
+ if (CHECK_FLAG(peer->sflags,
+ PEER_STATUS_NSF_WAIT)) {
+ peer_nsf_stop(peer);
+ }
+ }
+
UNSET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
peer->doppelganger = peer1;
BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */
SET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
-
/* Make dummy peer until read Open packet. */
if (peer1->status == Established
- && CHECK_FLAG(peer1->sflags, PEER_STATUS_NSF_MODE)) {
+ && CHECK_FLAG(peer1->sflags, PEER_STATUS_NSF_MODE)) {
/* If we have an existing established connection with graceful
* restart
* capability announced with one or more address families, then
* existing established connection and move state to connect.
*/
peer1->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
- SET_FLAG(peer1->sflags, PEER_STATUS_NSF_WAIT);
+
+ if (CHECK_FLAG(peer1->flags,
+ PEER_FLAG_GRACEFUL_RESTART) ||
+ CHECK_FLAG(peer1->flags,
+ PEER_FLAG_GRACEFUL_RESTART_HELPER))
+ SET_FLAG(peer1->sflags,
+ PEER_STATUS_NSF_WAIT);
+
bgp_event_update(peer1, TCP_connection_closed);
}
restart_flag_time = stream_getw(s);
if (CHECK_FLAG(restart_flag_time, RESTART_R_BIT))
SET_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV);
+ else
+ UNSET_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV);
UNSET_FLAG(restart_flag_time, 0xF000);
peer->v_gr_restart = restart_flag_time;
peer_dst->flags = peer_src->flags;
peer_dst->cap = peer_src->cap;
+ peer_dst->peer_gr_present_state = peer_src->peer_gr_present_state;
+ peer_dst->peer_gr_new_status_flag = peer_src->peer_gr_new_status_flag;
+
peer_dst->local_as = peer_src->local_as;
peer_dst->port = peer_src->port;
(void)peer_sort(peer_dst);
return peer_deactivate(peer, afi, safi);
}
-static void peer_nsf_stop(struct peer *peer)
+void peer_nsf_stop(struct peer *peer)
{
afi_t afi;
safi_t safi;
/* Hooks */
DECLARE_HOOK(peer_status_changed, (struct peer * peer), (peer))
+void peer_nsf_stop(struct peer *peer);
#endif /* _QUAGGA_BGPD_H */