diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 5e5ac636ed..a86c457b62 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -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); + } + } } diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c index fed34e5b65..626c36ff05 100644 --- a/bgpd/bgp_io.c +++ b/bgpd/bgp_io.c @@ -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 diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 4031d2dfde..4487684de5 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -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); } diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index eb6dc1a753..89437a5149 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -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; diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index fae91655ab..2c60b818ef 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -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; diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 390dc8a7ff..a8ba6ad258 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -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 */