]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: BGP tcp session failed to apply GR configuration on the transferred
authorbisdhdh <biswajit.sadhu@gmail.com>
Thu, 24 Oct 2019 04:40:53 +0000 (10:10 +0530)
committerbisdhdh <biswajit.sadhu@gmail.com>
Thu, 23 Jan 2020 04:04:25 +0000 (09:34 +0530)
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>
bgpd/bgp_fsm.c
bgpd/bgp_io.c
bgpd/bgp_network.c
bgpd/bgp_open.c
bgpd/bgpd.c
bgpd/bgpd.h

index 5e5ac636ed4473b5b36b8220247bcc82cdc36e7a..a86c457b6255b683769723155b5e762cb57472c1 100644 (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);
+               }
+       }
 }
index fed34e5b65ca375904c19da9068027a75c1552c5..626c36ff052e85c7efbf4f22fc5b15eff486c456 100644 (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
index 4031d2dfde40301a67315ce252f310b7f7d63a08..4487684de59bedda80b211b7626250b8a0c8d224 100644 (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);
        }
 
index eb6dc1a753087d405427f1c5b8bb245c0930affd..89437a5149969bc5ab0fbc239cd750317fad5178 100644 (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;
index fae91655aba743d04e2de4948cd46168923d2ca8..2c60b818efde7775054cae4272e124c059f75967 100644 (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;
index 390dc8a7ffef7c0472c4378cf9b58cb12a9492f2..a8ba6ad2581953c99f98add9bb68f5ea40854d8a 100644 (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 */