]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Send Hard Reset Notification for BGP_NOTIFY_CEASE_ADMIN_RESET
authorDonatas Abraitis <donatas@opensourcerouting.org>
Fri, 6 May 2022 07:21:15 +0000 (10:21 +0300)
committerDonatas Abraitis <donatas@opensourcerouting.org>
Tue, 10 May 2022 06:04:25 +0000 (09:04 +0300)
`clear bgp neighbor` should send Hard Reset and graceful restart should be
activated. Let's make this adjustable.

https://datatracker.ietf.org/doc/html/rfc8538#section-5.1

   +-------+------------------------------------+----------------------+
   | Value |                Name                |  Suggested Behavior  |
   +-------+------------------------------------+----------------------+
   |   1   | Maximum Number of Prefixes Reached |      Hard Reset      |
   |   2   |      Administrative Shutdown       |      Hard Reset      |
   |   3   |         Peer De-configured         |      Hard Reset      |
   |   4   |        Administrative Reset        | Provide user control |
   |   5   |        Connection Rejected         |    Graceful Cease    |
   |   6   |     Other Configuration Change     |    Graceful Cease    |
   |   7   |  Connection Collision Resolution   |    Graceful Cease    |
   |   8   |          Out of Resources          |    Graceful Cease    |
   |   9   |             Hard Reset             |      Hard Reset      |
   +-------+------------------------------------+----------------------+

Enabled by default.

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

index 88eeab6ed1642aa846d4167a3f69de5a0b503c43..0d5e9eb6f2c2bd6d30236b9d15b506f32d4d4648 100644 (file)
@@ -751,7 +751,8 @@ struct bgp_notify bgp_notify_decapsulate_hard_reset(struct bgp_notify *notify)
 /*
  * Check if to send BGP CEASE Notification/Hard Reset?
  */
-bool bgp_notify_is_hard_reset(struct peer *peer, uint8_t code, uint8_t subcode)
+bool bgp_notify_send_hard_reset(struct peer *peer, uint8_t code,
+                               uint8_t subcode)
 {
        /* 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.
@@ -763,13 +764,22 @@ bool bgp_notify_is_hard_reset(struct peer *peer, uint8_t code, uint8_t subcode)
        /*
         * https://datatracker.ietf.org/doc/html/rfc8538#section-5.1
         */
-       if (code == BGP_NOTIFY_CEASE || code == BGP_NOTIFY_HOLD_ERR) {
+       if (code == BGP_NOTIFY_CEASE) {
                switch (subcode) {
                case BGP_NOTIFY_CEASE_MAX_PREFIX:
                case BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN:
                case BGP_NOTIFY_CEASE_PEER_UNCONFIG:
                case BGP_NOTIFY_CEASE_HARD_RESET:
                        return true;
+               case BGP_NOTIFY_CEASE_ADMIN_RESET:
+                       /* Provide user control:
+                        * `bgp hard-adminstrative-reset`
+                        */
+                       if (CHECK_FLAG(peer->bgp->flags,
+                                      BGP_FLAG_HARD_ADMIN_RESET))
+                               return true;
+                       else
+                               return false;
                default:
                        break;
                }
@@ -778,6 +788,25 @@ bool bgp_notify_is_hard_reset(struct peer *peer, uint8_t code, uint8_t subcode)
        return false;
 }
 
+/*
+ * Check if received BGP CEASE Notification/Hard Reset?
+ */
+bool bgp_notify_received_hard_reset(struct peer *peer, uint8_t code,
+                                   uint8_t subcode)
+{
+       /* 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))
+               return false;
+
+       if (code == BGP_NOTIFY_CEASE && subcode == BGP_NOTIFY_CEASE_HARD_RESET)
+               return true;
+
+       return false;
+}
+
 /*
  * Creates a BGP Notify and appends it to the peer's output queue.
  *
@@ -802,7 +831,7 @@ void bgp_notify_send_with_data(struct peer *peer, uint8_t code,
                               uint8_t sub_code, uint8_t *data, size_t datalen)
 {
        struct stream *s;
-       bool hard_reset = bgp_notify_is_hard_reset(peer, code, sub_code);
+       bool hard_reset = bgp_notify_send_hard_reset(peer, code, sub_code);
 
        /* Lock I/O mutex to prevent other threads from pushing packets */
        frr_mutex_lock_autounlock(&peer->io_mtx);
@@ -1992,7 +2021,8 @@ static int bgp_notify_receive(struct peer *peer, bgp_size_t size)
                memcpy(outer.raw_data, stream_pnt(peer->curr), outer.length);
        }
 
-       hard_reset = bgp_notify_is_hard_reset(peer, outer.code, outer.subcode);
+       hard_reset =
+               bgp_notify_received_hard_reset(peer, outer.code, outer.subcode);
        if (hard_reset && outer.length) {
                inner = bgp_notify_decapsulate_hard_reset(&outer);
                peer->notify.hard_reset = true;
index 2fd7ff64d4ad47b396e9a9d3a66c290782835f20..92c7f60ac7714dc8fadc32186e78a57856fe1499 100644 (file)
@@ -88,7 +88,9 @@ 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_notify_is_hard_reset(struct peer *peer, uint8_t code,
-                                    uint8_t subcode);
+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,
+                                          uint8_t subcode);
 
 #endif /* _QUAGGA_BGP_PACKET_H */
index 192af2216aaa9ad3532e5d61c9f6ca96d7bdf380..747445d31e79e5b37792f6520633ad6609d7e447 100644 (file)
@@ -127,6 +127,10 @@ FRR_CFG_DEFAULT_BOOL(BGP_GRACEFUL_NOTIFICATION,
        { .val_bool = false, .match_version = "< 8.3", },
        { .val_bool = true },
 );
+FRR_CFG_DEFAULT_BOOL(BGP_HARD_ADMIN_RESET,
+       { .val_bool = false, .match_version = "< 8.3", },
+       { .val_bool = true },
+);
 
 DEFINE_HOOK(bgp_inst_config_write,
                (struct bgp *bgp, struct vty *vty),
@@ -575,6 +579,8 @@ int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name,
                        SET_FLAG((*bgp)->flags, BGP_FLAG_SUPPRESS_DUPLICATES);
                if (DFLT_BGP_GRACEFUL_NOTIFICATION)
                        SET_FLAG((*bgp)->flags, BGP_FLAG_GRACEFUL_NOTIFICATION);
+               if (DFLT_BGP_HARD_ADMIN_RESET)
+                       SET_FLAG((*bgp)->flags, BGP_FLAG_HARD_ADMIN_RESET);
 
                ret = BGP_SUCCESS;
        }
@@ -2892,6 +2898,23 @@ DEFPY (bgp_graceful_restart_notification,
        return CMD_SUCCESS;
 }
 
+DEFPY (bgp_administrative_reset,
+       bgp_administrative_reset_cmd,
+       "[no$no] bgp hard-administrative-reset",
+       NO_STR
+       BGP_STR
+       "Send Hard Reset CEASE Notification for 'Administrative Reset'\n")
+{
+       VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+       if (no)
+               UNSET_FLAG(bgp->flags, BGP_FLAG_HARD_ADMIN_RESET);
+       else
+               SET_FLAG(bgp->flags, BGP_FLAG_HARD_ADMIN_RESET);
+
+       return CMD_SUCCESS;
+}
+
 DEFUN (bgp_graceful_restart_disable,
        bgp_graceful_restart_disable_cmd,
        "bgp graceful-restart-disable",
@@ -17167,6 +17190,16 @@ int bgp_config_write(struct vty *vty)
                                        ? ""
                                        : "no ");
 
+               /* Send Hard Reset CEASE Notification for 'Administrative Reset'
+                */
+               if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_HARD_ADMIN_RESET) !=
+                   SAVE_BGP_HARD_ADMIN_RESET)
+                       vty_out(vty, " %sbgp hard-administrative-reset\n",
+                               CHECK_FLAG(bgp->flags,
+                                          BGP_FLAG_HARD_ADMIN_RESET)
+                                       ? ""
+                                       : "no ");
+
                /* BGP default <afi>-<safi> */
                FOREACH_AFI_SAFI (afi, safi) {
                        if (afi == AFI_IP && safi == SAFI_UNICAST) {
@@ -17950,6 +17983,9 @@ void bgp_vty_init(void)
        install_element(BGP_NODE, &bgp_graceful_shutdown_cmd);
        install_element(BGP_NODE, &no_bgp_graceful_shutdown_cmd);
 
+       /* "bgp hard-administrative-reset" commands */
+       install_element(BGP_NODE, &bgp_administrative_reset_cmd);
+
        /* "bgp long-lived-graceful-restart" commands */
        install_element(BGP_NODE, &bgp_llgr_stalepath_time_cmd);
        install_element(BGP_NODE, &no_bgp_llgr_stalepath_time_cmd);
index a0de2dab69df0e40a58650974ce54d7750727eac..6ad4c581c35ec7a099803a5a991cb71bfa702967 100644 (file)
@@ -490,6 +490,8 @@ struct bgp {
 #define BGP_FLAG_PEERTYPE_MULTIPATH_RELAX (1 << 29)
 /* Indicate Graceful Restart support for BGP NOTIFICATION messages */
 #define BGP_FLAG_GRACEFUL_NOTIFICATION (1 << 30)
+/* Send Hard Reset CEASE Notification for 'Administrative Reset' */
+#define BGP_FLAG_HARD_ADMIN_RESET (1 << 31)
 
        /* BGP default address-families.
         * New peers inherit enabled afi/safis from bgp instance.
index 68d6d8714b44d25ceb1ffa9e3a0082865afe700f..163a12c4d57363ed3a91f566dc9da69a1e74f80e 100644 (file)
@@ -501,6 +501,19 @@ Suppress duplicate updates
    Suppress duplicate updates if the route actually not changed.
    Default: enabled.
 
+Send Hard Reset CEASE Notification for Administrative Reset
+-----------------------------------------------------------
+
+.. clicmd:: bgp hard-administrative-reset
+
+   Send Hard Reset CEASE Notification for 'Administrative Reset' events.
+
+   When disabled, and Graceful Restart Notification capability is exchanged
+   between the peers, Graceful Restart procedures apply, and routes will be
+   retained.
+
+   Enabled by default.
+
 Disable checking if nexthop is connected on EBGP sessions
 ---------------------------------------------------------