]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Implement CEASE/Hard Reset notification 11128/head
authorDonatas Abraitis <donatas@opensourcerouting.org>
Sat, 30 Apr 2022 20:04:58 +0000 (23:04 +0300)
committerDonatas Abraitis <donatas@opensourcerouting.org>
Mon, 2 May 2022 06:43:40 +0000 (09:43 +0300)
Also, add N-Bit (Notification) flag for Graceful Restart.

This is a preparation for RFC8538.

More information: https://datatracker.ietf.org/doc/html/rfc8538

Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
13 files changed:
bgpd/bgp_debug.c
bgpd/bgp_debug.h
bgpd/bgp_fsm.c
bgpd/bgp_memory.c
bgpd/bgp_memory.h
bgpd/bgp_open.c
bgpd/bgp_open.h
bgpd/bgp_packet.c
bgpd/bgp_packet.h
bgpd/bgp_vty.c
bgpd/bgp_vty.h
bgpd/bgpd.c
bgpd/bgpd.h

index 49003e94288af04424037126d4976017738b39c5..0993d6de576781e1025dd720fc80f9319587d556 100644 (file)
@@ -49,6 +49,7 @@
 #include "bgpd/bgp_evpn_vty.h"
 #include "bgpd/bgp_vty.h"
 #include "bgpd/bgp_flowspec.h"
+#include "bgpd/bgp_packet.h"
 
 unsigned long conf_bgp_debug_as4;
 unsigned long conf_bgp_debug_neighbor_events;
@@ -168,6 +169,7 @@ static const struct message bgp_notify_cease_msg[] = {
        {BGP_NOTIFY_CEASE_COLLISION_RESOLUTION,
         "/Connection Collision Resolution"},
        {BGP_NOTIFY_CEASE_OUT_OF_RESOURCE, "/Out of Resources"},
+       {BGP_NOTIFY_CEASE_HARD_RESET, "/Hard Reset"},
        {0}};
 
 static const struct message bgp_notify_route_refresh_msg[] = {
@@ -520,7 +522,7 @@ const char *bgp_notify_admin_message(char *buf, size_t bufsz, uint8_t *data,
 
 /* dump notify packet */
 void bgp_notify_print(struct peer *peer, struct bgp_notify *bgp_notify,
-                     const char *direct)
+                     const char *direct, bool hard_reset)
 {
        const char *subcode_str;
        const char *code_str;
@@ -544,7 +546,8 @@ void bgp_notify_print(struct peer *peer, struct bgp_notify *bgp_notify,
 
                if (msg_str) {
                        zlog_info(
-                               "%%NOTIFICATION: %s neighbor %s %d/%d (%s%s) \"%s\"",
+                               "%%NOTIFICATION%s: %s neighbor %s %d/%d (%s%s) \"%s\"",
+                               hard_reset ? "(Hard Reset)" : "",
                                strcmp(direct, "received") == 0
                                        ? "received from"
                                        : "sent to",
@@ -554,7 +557,8 @@ void bgp_notify_print(struct peer *peer, struct bgp_notify *bgp_notify,
                } else {
                        msg_str = bgp_notify->data ? bgp_notify->data : "";
                        zlog_info(
-                               "%%NOTIFICATION: %s neighbor %s %d/%d (%s%s) %d bytes %s",
+                               "%%NOTIFICATION%s: %s neighbor %s %d/%d (%s%s) %d bytes %s",
+                               hard_reset ? "(Hard Reset)" : "",
                                strcmp(direct, "received") == 0
                                        ? "received from"
                                        : "sent to",
index d847fb84e7a8257ac43061d4f4f9abff4a2082fc..cf6325ba3660a83b05cac9832f362ddbc9ff7426 100644 (file)
@@ -170,7 +170,8 @@ extern bool bgp_dump_attr(struct attr *, char *, size_t);
 extern bool bgp_debug_peer_updout_enabled(char *host);
 extern const char *bgp_notify_code_str(char);
 extern const char *bgp_notify_subcode_str(char, char);
-extern void bgp_notify_print(struct peer *, struct bgp_notify *, const char *);
+extern void bgp_notify_print(struct peer *peer, struct bgp_notify *bgp_notify,
+                            const char *direct, bool hard_reset);
 
 extern const struct message bgp_status_msg[];
 extern int bgp_debug_neighbor_events(struct peer *peer);
index e78eb7453ac655533f977d0580d47383bc17ac1f..fe5f04ba11a13eadbbec904324a78ca75bcf7ebc 100644 (file)
@@ -2160,7 +2160,8 @@ static int bgp_establish(struct peer *peer)
        } else {
                /* Peer sends R-bit. In this case, we need to send
                 * ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE to Zebra. */
-               if (CHECK_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV)) {
+               if (CHECK_FLAG(peer->cap,
+                              PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV)) {
                        FOREACH_AFI_SAFI (afi, safi)
                                /* Send route processing complete
                                   message to RIB */
index a994b536c4116c34f69fd487f779ff96ef004d5d..1dc992fb94556cd2c62e2ffdf05dcbb16399b2dc 100644 (file)
@@ -145,3 +145,5 @@ DEFINE_MTYPE(BGPD, BGP_SRV6_VPN, "BGP prefix-sid srv6 vpn service");
 DEFINE_MTYPE(BGPD, BGP_SRV6_SID, "BGP srv6 segment-id");
 DEFINE_MTYPE(BGPD, BGP_SRV6_FUNCTION, "BGP srv6 function");
 DEFINE_MTYPE(BGPD, EVPN_REMOTE_IP, "BGP EVPN Remote IP hash entry");
+
+DEFINE_MTYPE(BGPD, BGP_NOTIFICATION, "BGP Notification Message");
index 76b2f9f56a9ec7d17297619f8a0191d155dce554..d4d7b0cf88be5ca63eb1bc27c016caf7abe45fc0 100644 (file)
@@ -144,4 +144,6 @@ DECLARE_MTYPE(BGP_SRV6_FUNCTION);
 
 DECLARE_MTYPE(EVPN_REMOTE_IP);
 
+DECLARE_MTYPE(BGP_NOTIFICATION);
+
 #endif /* _QUAGGA_BGP_MEMORY_H */
index dc9f97f3696a12f17590387159d386b8ac36de57..324c966b356d2185af8ed3555cf2133edaeaccea 100644 (file)
@@ -517,22 +517,39 @@ static int bgp_capability_restart(struct peer *peer,
 
        SET_FLAG(peer->cap, PEER_CAP_RESTART_RCV);
        restart_flag_time = stream_getw(s);
+
+       /* The most significant bit is defined in [RFC4724] as
+        * the Restart State ("R") bit.
+        */
        if (CHECK_FLAG(restart_flag_time, GRACEFUL_RESTART_R_BIT))
                SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV);
        else
                UNSET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV);
 
+       /* The second most significant bit is defined in this
+        * document as the Graceful Notification ("N") bit.
+        */
+       if (CHECK_FLAG(restart_flag_time, GRACEFUL_RESTART_N_BIT))
+               SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV);
+       else
+               UNSET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV);
+
        UNSET_FLAG(restart_flag_time, 0xF000);
        peer->v_gr_restart = restart_flag_time;
 
        if (bgp_debug_neighbor_events(peer)) {
-               zlog_debug("%s Peer has%srestarted. Restart Time : %d",
-                          peer->host,
-                          CHECK_FLAG(peer->cap,
-                                     PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV)
-                                  ? " "
-                                  : " not ",
-                          peer->v_gr_restart);
+               zlog_debug(
+                       "%s Peer has%srestarted. Restart Time: %d, N-bit set: %s",
+                       peer->host,
+                       CHECK_FLAG(peer->cap,
+                                  PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV)
+                               ? " "
+                               : " not ",
+                       peer->v_gr_restart,
+                       CHECK_FLAG(peer->cap,
+                                  PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV)
+                               ? "yes"
+                               : "no");
        }
 
        while (stream_get_getp(s) + 4 <= end) {
@@ -1418,10 +1435,12 @@ static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
        restart_time = peer->bgp->restart_time;
        if (peer->bgp->t_startup) {
                SET_FLAG(restart_time, GRACEFUL_RESTART_R_BIT);
+               SET_FLAG(restart_time, GRACEFUL_RESTART_N_BIT);
                SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_ADV);
+               SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV);
 
                if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
-                       zlog_debug("[BGP_GR] Sending R-Bit for Peer :%s :",
+                       zlog_debug("[BGP_GR] Sending R-Bit/N-Bit for peer: %s",
                                   peer->host);
        }
 
index d359a872dc141b0896071e88eaefb916855613a9..1727b6604174bc3a2b21d9bfa3e16e22e868834b 100644 (file)
@@ -88,6 +88,7 @@ struct graceful_restart_af {
 
 /* Graceful Restart */
 #define GRACEFUL_RESTART_R_BIT 0x8000
+#define GRACEFUL_RESTART_N_BIT 0x4000
 #define GRACEFUL_RESTART_F_BIT 0x80
 
 /* Long-lived Graceful Restart */
index b0d852ee63a958a889624bfab78f16cfca6d423b..fc4c0b515463670c0f462e14b046754d5ef732bb 100644 (file)
@@ -712,6 +712,72 @@ static void bgp_write_notify(struct peer *peer)
        stream_free(s);
 }
 
+/*
+ * Encapsulate an original BGP CEASE Notification into Hard Reset
+ */
+static uint8_t *bgp_notify_encapsulate_hard_reset(uint8_t code, uint8_t subcode,
+                                                 uint8_t *data, size_t datalen)
+{
+       uint8_t *message = XCALLOC(MTYPE_BGP_NOTIFICATION, datalen + 2);
+
+       /* ErrCode */
+       message[0] = code;
+       /* Subcode */
+       message[1] = subcode;
+       /* Data */
+       if (datalen)
+               memcpy(message + 2, data, datalen);
+
+       return message;
+}
+
+/*
+ * Decapsulate an original BGP CEASE Notification from Hard Reset
+ */
+struct bgp_notify bgp_notify_decapsulate_hard_reset(struct bgp_notify *notify)
+{
+       struct bgp_notify bn = {};
+
+       bn.code = notify->raw_data[0];
+       bn.subcode = notify->raw_data[1];
+       bn.length = notify->length - 2;
+
+       bn.raw_data = XCALLOC(MTYPE_BGP_NOTIFICATION, bn.length);
+       memcpy(bn.raw_data, notify->raw_data + 2, bn.length);
+
+       return bn;
+}
+
+/*
+ * Check if to send BGP CEASE Notification/Hard Reset?
+ */
+bool bgp_notify_is_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;
+
+       /*
+        * https://datatracker.ietf.org/doc/html/rfc8538#section-5.1
+        */
+       if (code == BGP_NOTIFY_CEASE || code == BGP_NOTIFY_HOLD_ERR) {
+               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;
+               default:
+                       break;
+               }
+       }
+
+       return false;
+}
+
 /*
  * Creates a BGP Notify and appends it to the peer's output queue.
  *
@@ -736,6 +802,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);
 
        /* Lock I/O mutex to prevent other threads from pushing packets */
        frr_mutex_lock_autounlock(&peer->io_mtx);
@@ -747,13 +814,25 @@ void bgp_notify_send_with_data(struct peer *peer, uint8_t code,
        /* Make notify packet. */
        bgp_packet_set_marker(s, BGP_MSG_NOTIFY);
 
-       /* Set notify packet values. */
-       stream_putc(s, code);     /* BGP notify code */
-       stream_putc(s, sub_code); /* BGP notify sub_code */
+       /* Check if we should send Hard Reset Notification or not */
+       if (hard_reset) {
+               uint8_t *hard_reset_message = bgp_notify_encapsulate_hard_reset(
+                       code, sub_code, data, datalen);
 
-       /* If notify data is present. */
-       if (data)
-               stream_write(s, data, datalen);
+               /* Hard Reset encapsulates another NOTIFICATION message
+                * in its data portion.
+                */
+               stream_putc(s, BGP_NOTIFY_CEASE);
+               stream_putc(s, BGP_NOTIFY_CEASE_HARD_RESET);
+               stream_write(s, hard_reset_message, datalen + 2);
+
+               XFREE(MTYPE_BGP_NOTIFICATION, hard_reset_message);
+       } else {
+               stream_putc(s, code);
+               stream_putc(s, sub_code);
+               if (data)
+                       stream_write(s, data, datalen);
+       }
 
        /* Set BGP packet length. */
        bgp_packet_set_size(s);
@@ -808,7 +887,7 @@ void bgp_notify_send_with_data(struct peer *peer, uint8_t code,
                                                bgp_notify.length);
                                }
                }
-               bgp_notify_print(peer, &bgp_notify, "sending");
+               bgp_notify_print(peer, &bgp_notify, "sending", hard_reset);
 
                if (bgp_notify.data) {
                        XFREE(MTYPE_TMP, bgp_notify.data);
@@ -1894,27 +1973,42 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
  */
 static int bgp_notify_receive(struct peer *peer, bgp_size_t size)
 {
-       struct bgp_notify bgp_notify;
+       struct bgp_notify outer;
+       struct bgp_notify inner;
+       bool hard_reset = false;
 
        if (peer->notify.data) {
-               XFREE(MTYPE_TMP, peer->notify.data);
+               XFREE(MTYPE_BGP_NOTIFICATION, peer->notify.data);
                peer->notify.length = 0;
        }
 
-       bgp_notify.code = stream_getc(peer->curr);
-       bgp_notify.subcode = stream_getc(peer->curr);
-       bgp_notify.length = size - 2;
-       bgp_notify.data = NULL;
-       bgp_notify.raw_data = NULL;
+       outer.code = stream_getc(peer->curr);
+       outer.subcode = stream_getc(peer->curr);
+       outer.length = size - 2;
+       outer.data = NULL;
+       outer.raw_data = NULL;
+       if (outer.length) {
+               outer.raw_data = XMALLOC(MTYPE_BGP_NOTIFICATION, outer.length);
+               memcpy(outer.raw_data, stream_pnt(peer->curr), outer.length);
+       }
+
+       hard_reset = bgp_notify_is_hard_reset(peer, outer.code, outer.subcode);
+       if (hard_reset && outer.length) {
+               inner = bgp_notify_decapsulate_hard_reset(&outer);
+               peer->notify.hard_reset = true;
+       } else {
+               inner = outer;
+       }
 
        /* Preserv notify code and sub code. */
-       peer->notify.code = bgp_notify.code;
-       peer->notify.subcode = bgp_notify.subcode;
+       peer->notify.code = inner.code;
+       peer->notify.subcode = inner.subcode;
        /* For further diagnostic record returned Data. */
-       if (bgp_notify.length) {
-               peer->notify.length = size - 2;
-               peer->notify.data = XMALLOC(MTYPE_TMP, size - 2);
-               memcpy(peer->notify.data, stream_pnt(peer->curr), size - 2);
+       if (inner.length) {
+               peer->notify.length = inner.length;
+               peer->notify.data =
+                       XMALLOC(MTYPE_BGP_NOTIFICATION, inner.length);
+               memcpy(peer->notify.data, inner.raw_data, inner.length);
        }
 
        /* For debug */
@@ -1923,32 +2017,35 @@ static int bgp_notify_receive(struct peer *peer, bgp_size_t size)
                int first = 0;
                char c[4];
 
-               if (bgp_notify.length) {
-                       bgp_notify.data =
-                               XMALLOC(MTYPE_TMP, bgp_notify.length * 3);
-                       for (i = 0; i < bgp_notify.length; i++)
+               if (inner.length) {
+                       inner.data = XMALLOC(MTYPE_BGP_NOTIFICATION,
+                                            inner.length * 3);
+                       for (i = 0; i < inner.length; i++)
                                if (first) {
                                        snprintf(c, sizeof(c), " %02x",
                                                stream_getc(peer->curr));
 
-                                       strlcat(bgp_notify.data, c,
-                                               bgp_notify.length * 3);
+                                       strlcat(inner.data, c,
+                                               inner.length * 3);
 
                                } else {
                                        first = 1;
                                        snprintf(c, sizeof(c), "%02x",
                                                 stream_getc(peer->curr));
 
-                                       strlcpy(bgp_notify.data, c,
-                                               bgp_notify.length * 3);
+                                       strlcpy(inner.data, c,
+                                               inner.length * 3);
                                }
-                       bgp_notify.raw_data = (uint8_t *)peer->notify.data;
                }
 
-               bgp_notify_print(peer, &bgp_notify, "received");
-               if (bgp_notify.data) {
-                       XFREE(MTYPE_TMP, bgp_notify.data);
-                       bgp_notify.length = 0;
+               bgp_notify_print(peer, &inner, "received", hard_reset);
+               if (inner.data) {
+                       XFREE(MTYPE_BGP_NOTIFICATION, inner.data);
+                       inner.length = 0;
+               }
+               if (outer.length) {
+                       XFREE(MTYPE_BGP_NOTIFICATION, outer.data);
+                       outer.length = 0;
                }
        }
 
@@ -1961,8 +2058,8 @@ static int bgp_notify_receive(struct peer *peer, bgp_size_t size)
           in that case we fallback to open without the capability option.
           But this done in bgp_stop. We just mark it here to avoid changing
           the fsm tables.  */
-       if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR
-           && bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM)
+       if (inner.code == BGP_NOTIFY_OPEN_ERR &&
+           inner.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM)
                UNSET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
 
        bgp_peer_gr_flags_update(peer);
index 8c2de6d622257d4ff39111f7606574c6843f1840..2fd7ff64d4ad47b396e9a9d3a66c290782835f20 100644 (file)
@@ -86,5 +86,9 @@ extern void bgp_send_delayed_eor(struct bgp *bgp);
 
 /* Task callback to handle socket error encountered in the io pthread */
 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);
 
 #endif /* _QUAGGA_BGP_PACKET_H */
index bdd3164600522ec401f6156b40b341485ac13f34..0cbb341ff3910afe7e1ed7c1024ce9c3fdc0fde8 100644 (file)
@@ -10052,6 +10052,9 @@ static void bgp_show_peer_reset(struct vty * vty, struct peer *peer,
                        json_object_string_add(json_peer,
                                               "lastNotificationReason",
                                               errorcodesubcode_str);
+                       json_object_boolean_add(json_peer,
+                                               "lastNotificationHardReset",
+                                               peer->notify.hard_reset);
                        if (peer->last_reset == PEER_DOWN_NOTIFY_RECEIVED
                            && peer->notify.code == BGP_NOTIFY_CEASE
                            && (peer->notify.subcode
@@ -10085,11 +10088,16 @@ static void bgp_show_peer_reset(struct vty * vty, struct peer *peer,
                        subcode_str =
                                bgp_notify_subcode_str(peer->notify.code,
                                                       peer->notify.subcode);
-                       vty_out(vty, "  Notification %s (%s%s)\n",
+                       vty_out(vty, " Notification %s (%s%s%s)\n",
                                peer->last_reset == PEER_DOWN_NOTIFY_SEND
-                               ? "sent"
-                               : "received",
-                               code_str, subcode_str);
+                                       ? "sent"
+                                       : "received",
+                               code_str, subcode_str,
+                               peer->notify.hard_reset
+                                       ? bgp_notify_subcode_str(
+                                                 BGP_NOTIFY_CEASE,
+                                                 BGP_NOTIFY_CEASE_HARD_RESET)
+                                       : "");
                } else {
                        vty_out(vty, " %s\n",
                                peer_down_str[(int)peer->last_reset]);
@@ -11246,36 +11254,27 @@ static void bgp_show_peer_afi_orf_cap(struct vty *vty, struct peer *p,
        }
 }
 
-static void bgp_show_neighnor_graceful_restart_rbit(struct vty *vty,
-                                                   struct peer *p,
-                                                   bool use_json,
-                                                   json_object *json)
+static void bgp_show_neighnor_graceful_restart_flags(struct vty *vty,
+                                                    struct peer *p,
+                                                    bool use_json,
+                                                    json_object *json)
 {
-       bool rbit_status = false;
-
-       if (!use_json)
-               vty_out(vty, "\n    R bit: ");
+       bool rbit = false;
+       bool nbit = false;
 
        if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_ADV)
            && (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV))
            && (peer_established(p))) {
-
-               if (CHECK_FLAG(p->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV))
-                       rbit_status = true;
-               else
-                       rbit_status = false;
+               rbit = CHECK_FLAG(p->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV);
+               nbit = CHECK_FLAG(p->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV);
        }
 
-       if (rbit_status) {
-               if (use_json)
-                       json_object_boolean_true_add(json, "rBit");
-               else
-                       vty_out(vty, "True\n");
+       if (use_json) {
+               json_object_boolean_add(json, "rBit", rbit);
+               json_object_boolean_add(json, "nBit", nbit);
        } else {
-               if (use_json)
-                       json_object_boolean_false_add(json, "rBit");
-               else
-                       vty_out(vty, "False\n");
+               vty_out(vty, "\n    R bit: %s", rbit ? "True" : "False");
+               vty_out(vty, "\n    N bit: %s\n", nbit ? "True" : "False");
        }
 }
 
index 4b393275d6c8f17407bb0fada53d0d6949787d58..143d3c1ac5f02efc2bd602508afbe0b829d60e0c 100644 (file)
@@ -59,19 +59,18 @@ struct bgp;
        "V         AS    LocalAS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc\n"
 #define BGP_SHOW_SUMMARY_HEADER_FAILED "EstdCnt DropCnt ResetTime Reason\n"
 
-#define BGP_SHOW_PEER_GR_CAPABILITY( \
-                       vty, p, use_json, json) \
-       do {                    \
-               bgp_show_neighbor_graceful_restart_local_mode( \
-                               vty, p, use_json, json);                \
-               bgp_show_neighbor_graceful_restart_remote_mode( \
-                               vty, p, use_json, json); \
-               bgp_show_neighnor_graceful_restart_rbit( \
-                               vty, p, use_json, json);        \
-               bgp_show_neighbor_graceful_restart_time( \
-                               vty, p, use_json, json);        \
-               bgp_show_neighbor_graceful_restart_capability_per_afi_safi(\
-                                               vty, p, use_json, json); \
+#define BGP_SHOW_PEER_GR_CAPABILITY(vty, p, use_json, json)                    \
+       do {                                                                   \
+               bgp_show_neighbor_graceful_restart_local_mode(vty, p,          \
+                                                             use_json, json); \
+               bgp_show_neighbor_graceful_restart_remote_mode(                \
+                       vty, p, use_json, json);                               \
+               bgp_show_neighnor_graceful_restart_flags(vty, p, use_json,     \
+                                                        json);                \
+               bgp_show_neighbor_graceful_restart_time(vty, p, use_json,      \
+                                                       json);                 \
+               bgp_show_neighbor_graceful_restart_capability_per_afi_safi(    \
+                       vty, p, use_json, json);                               \
        } while (0)
 
 #define VTY_BGP_GR_DEFINE_LOOP_VARIABLE                                        \
index a2361758dc468a5d951f5602bd5714a2a61eb51a..38fc51f507ce931d033017e4f46622cbcd9d8576 100644 (file)
@@ -1153,7 +1153,7 @@ static void peer_free(struct peer *peer)
 
        XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
 
-       XFREE(MTYPE_TMP, peer->notify.data);
+       XFREE(MTYPE_BGP_NOTIFICATION, peer->notify.data);
        memset(&peer->notify, 0, sizeof(struct bgp_notify));
 
        if (peer->clear_node_queue)
index aee5ce35d778e8f4217352c55d8329d27ca7ab3d..e43c529f355eabf5562bb68eca1e6ea7fb5682f3 100644 (file)
@@ -819,6 +819,7 @@ struct bgp_notify {
        char *data;
        bgp_size_t length;
        uint8_t *raw_data;
+       bool hard_reset;
 };
 
 /* Next hop self address. */
@@ -1192,6 +1193,10 @@ struct peer {
 #define PEER_CAP_EXTENDED_MESSAGE_RCV (1U << 20)
 #define PEER_CAP_LLGR_ADV (1U << 21)
 #define PEER_CAP_LLGR_RCV (1U << 22)
+/* sent graceful-restart notification (N) bit */
+#define PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV (1U << 23)
+/* received graceful-restart notification (N) bit */
+#define PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV (1U << 24)
 
        /* Capability flags (reset in bgp_stop) */
        uint32_t af_cap[AFI_MAX][SAFI_MAX];
@@ -1852,6 +1857,7 @@ struct bgp_nlri {
 #define BGP_NOTIFY_CEASE_CONFIG_CHANGE           6
 #define BGP_NOTIFY_CEASE_COLLISION_RESOLUTION    7
 #define BGP_NOTIFY_CEASE_OUT_OF_RESOURCE         8
+#define BGP_NOTIFY_CEASE_HARD_RESET 9
 
 /* BGP_NOTIFY_ROUTE_REFRESH_ERR sub codes (RFC 7313). */
 #define BGP_NOTIFY_ROUTE_REFRESH_INVALID_MSG_LEN 1