bgpd: BGP tcp session failed to apply GR configuration on the transferred

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>
This commit is contained in:
bisdhdh 2019-10-24 10:10:53 +05:30
parent 2bb5d39b14
commit d7b3cda6f7
6 changed files with 76 additions and 8 deletions

View file

@ -251,6 +251,20 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
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);
@ -2604,5 +2618,25 @@ void bgp_peer_gr_flags_update(struct peer *peer)
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);
}
}
}

View file

@ -462,7 +462,12 @@ static uint16_t bgp_read(struct peer *peer)
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
@ -475,10 +480,15 @@ static uint16_t bgp_read(struct peer *peer)
} 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

View file

@ -487,6 +487,18 @@ static int bgp_accept(struct thread *thread)
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;
@ -497,10 +509,9 @@ static int bgp_accept(struct thread *thread)
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
@ -508,7 +519,14 @@ static int bgp_accept(struct thread *thread)
* 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);
}

View file

@ -462,6 +462,8 @@ static int bgp_capability_restart(struct peer *peer,
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;

View file

@ -1326,6 +1326,9 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
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);
@ -2213,7 +2216,7 @@ int peer_afc_set(struct peer *peer, afi_t afi, safi_t safi, int enable)
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;

View file

@ -2081,5 +2081,6 @@ extern struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
/* Hooks */
DECLARE_HOOK(peer_status_changed, (struct peer * peer), (peer))
void peer_nsf_stop(struct peer *peer);
#endif /* _QUAGGA_BGPD_H */