mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-29 02:37:00 +00:00
bgpd: Implement CEASE/Hard Reset notification
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>
This commit is contained in:
parent
54394daa2d
commit
eea685b6d3
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
|
@ -144,4 +144,6 @@ DECLARE_MTYPE(BGP_SRV6_FUNCTION);
|
||||
|
||||
DECLARE_MTYPE(EVPN_REMOTE_IP);
|
||||
|
||||
DECLARE_MTYPE(BGP_NOTIFICATION);
|
||||
|
||||
#endif /* _QUAGGA_BGP_MEMORY_H */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user