]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Activate Graceful-Restart when receiving CEASE/HOLDTIME notifications
authorDonatas Abraitis <donatas@opensourcerouting.org>
Wed, 11 May 2022 16:42:53 +0000 (19:42 +0300)
committerDonatas Abraitis <donatas@opensourcerouting.org>
Sat, 14 May 2022 18:43:55 +0000 (21:43 +0300)
If we receive CEASE Notification or HOLDTIME notification, retain STALE
routes if it's not a CEASE/Hard Reset.

When doing `clear ip bgp PEER`, we can control if this would be CEASE/Hard Reset
or not by using `bgp hard-administrative-reset` knob.

When `bgp graceful-restart notification` is disabled, STALE routes won't be
retained when receiving Notification message.

Co-authored-by: Biswajit Sadhu <biswajit.sadhu@gmail.com>
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
bgpd/bgp_fsm.c
bgpd/bgp_packet.c
bgpd/bgp_packet.h

index cc3505333b4bc43c87850d5dfe6a6efcb19d7af1..ba018d3f5673faf2f18288c77688817b63e8f5ba 100644 (file)
@@ -1961,6 +1961,15 @@ static int bgp_fsm_holdtime_expire(struct peer *peer)
        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);
 }
 
index 9a1216a031dbd141629ed5537868882d3d848db1..29db23fbbd6a61ffa4d0448d6749a1442b627069 100644 (file)
@@ -748,6 +748,13 @@ struct bgp_notify bgp_notify_decapsulate_hard_reset(struct bgp_notify *notify)
        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?
  */
@@ -757,8 +764,7 @@ bool bgp_notify_send_hard_reset(struct peer *peer, uint8_t code,
        /* 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;
 
        /*
@@ -797,8 +803,7 @@ bool bgp_notify_received_hard_reset(struct peer *peer, uint8_t code,
        /* 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)
@@ -2094,6 +2099,13 @@ static int bgp_notify_receive(struct peer *peer, bgp_size_t size)
            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);
index 92c7f60ac7714dc8fadc32186e78a57856fe1499..a0eb579db7a80a0fb08f7b1f20fed0609815322a 100644 (file)
@@ -88,6 +88,7 @@ extern void bgp_send_delayed_eor(struct bgp *bgp);
 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,