summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_open.c91
-rw-r--r--bgpd/bgp_open.h5
-rw-r--r--bgpd/bgp_vty.c132
-rw-r--r--bgpd/bgpd.c1
-rw-r--r--bgpd/bgpd.h18
-rw-r--r--doc/user/bgp.rst12
6 files changed, 259 insertions, 0 deletions
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index ca8b1e398..e15690835 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -572,6 +572,46 @@ static int bgp_capability_restart(struct peer *peer,
return 0;
}
+static int bgp_capability_llgr(struct peer *peer,
+ struct capability_header *caphdr)
+{
+ struct stream *s = BGP_INPUT(peer);
+ size_t end = stream_get_getp(s) + caphdr->length;
+
+ SET_FLAG(peer->cap, PEER_CAP_LLGR_RCV);
+
+ while (stream_get_getp(s) + 4 <= end) {
+ afi_t afi;
+ safi_t safi;
+ iana_afi_t pkt_afi = stream_getw(s);
+ iana_safi_t pkt_safi = stream_getc(s);
+ uint8_t flags = stream_getc(s);
+ uint32_t stale_time = stream_get3(s);
+
+ if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%s Addr-family %s/%s(afi/safi) not supported. Ignore the Long-lived Graceful Restart capability for this AFI/SAFI",
+ peer->host, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ } else if (!peer->afc[afi][safi]
+ || !CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_RESTART_AF_RCV)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%s Addr-family %s/%s(afi/safi) not enabled. Ignore the Long-lived Graceful Restart capability",
+ peer->host, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ } else {
+ peer->llgr[afi][safi].flags = flags;
+ peer->llgr[afi][safi].stale_time = stale_time;
+ SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_LLGR_AF_RCV);
+ }
+ }
+
+ return 0;
+}
+
/* Unlike other capability parsing routines, this one returns 0 on error */
static as_t bgp_capability_as4(struct peer *peer, struct capability_header *hdr)
{
@@ -954,6 +994,9 @@ static int bgp_capability_parse(struct peer *peer, size_t length,
case CAPABILITY_CODE_RESTART:
ret = bgp_capability_restart(peer, &caphdr);
break;
+ case CAPABILITY_CODE_LLGR:
+ ret = bgp_capability_llgr(peer, &caphdr);
+ break;
case CAPABILITY_CODE_DYNAMIC:
case CAPABILITY_CODE_DYNAMIC_OLD:
SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV);
@@ -1404,6 +1447,53 @@ static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
stream_putc_at(s, capp, len);
}
+static void bgp_peer_send_llgr_capability(struct stream *s, struct peer *peer,
+ unsigned long cp)
+{
+ int len;
+ iana_afi_t pkt_afi;
+ afi_t afi;
+ safi_t safi;
+ iana_safi_t pkt_safi;
+ unsigned long capp = 0;
+ unsigned long rcapp = 0;
+
+ if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV))
+ return;
+
+ SET_FLAG(peer->cap, PEER_CAP_LLGR_ADV);
+
+ stream_putc(s, BGP_OPEN_OPT_CAP);
+ capp = stream_get_endp(s); /* Set Capability Len Pointer */
+ stream_putc(s, 0); /* Capability Length */
+ stream_putc(s, CAPABILITY_CODE_LLGR);
+
+ rcapp = stream_get_endp(s);
+ stream_putc(s, 0);
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (!peer->afc[afi][safi])
+ continue;
+
+ bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
+
+ stream_putw(s, pkt_afi);
+ stream_putc(s, pkt_safi);
+ stream_putc(s, LLGR_F_BIT);
+ stream_put3(s, peer->bgp->llgr_stale_time);
+
+ SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_LLGR_AF_ADV);
+ }
+
+ /* Total Long-lived Graceful Restart capability Len. */
+ len = stream_get_endp(s) - rcapp - 1;
+ stream_putc_at(s, rcapp, len);
+
+ /* Total Capability Len. */
+ len = stream_get_endp(s) - capp - 1;
+ stream_putc_at(s, capp, len);
+}
+
/* Fill in capability open option to the packet. */
void bgp_open_capability(struct stream *s, struct peer *peer)
{
@@ -1632,6 +1722,7 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
}
bgp_peer_send_gr_capability(s, peer, cp);
+ bgp_peer_send_llgr_capability(s, peer, cp);
/* Total Opt Parm Len. */
len = stream_get_endp(s) - cp - 1;
diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h
index bc6eedac8..0d616926a 100644
--- a/bgpd/bgp_open.h
+++ b/bgpd/bgp_open.h
@@ -50,6 +50,7 @@ struct graceful_restart_af {
#define CAPABILITY_CODE_DYNAMIC 67 /* Dynamic Capability */
#define CAPABILITY_CODE_ADDPATH 69 /* Addpath Capability */
#define CAPABILITY_CODE_ENHANCED_RR 70 /* Enhanced Route Refresh capability */
+#define CAPABILITY_CODE_LLGR 71 /* Long-lived Graceful Restart */
#define CAPABILITY_CODE_FQDN 73 /* Advertise hostname capability */
#define CAPABILITY_CODE_ENHE 5 /* Extended Next Hop Encoding */
#define CAPABILITY_CODE_REFRESH_OLD 128 /* Route Refresh Capability(cisco) */
@@ -66,6 +67,7 @@ struct graceful_restart_af {
#define CAPABILITY_CODE_ENHE_LEN 6 /* NRLI AFI = 2, SAFI = 2, Nexthop AFI = 2 */
#define CAPABILITY_CODE_MIN_FQDN_LEN 2
#define CAPABILITY_CODE_ENHANCED_LEN 0
+#define CAPABILITY_CODE_LLGR_LEN 0
#define CAPABILITY_CODE_ORF_LEN 5
#define CAPABILITY_CODE_EXT_MESSAGE_LEN 0 /* Extended Message Support */
@@ -88,6 +90,9 @@ struct graceful_restart_af {
#define RESTART_R_BIT 0x8000
#define RESTART_F_BIT 0x80
+/* Long-lived Graceful Restart */
+#define LLGR_F_BIT 0x80
+
extern int bgp_open_option_parse(struct peer *, uint8_t, int *);
extern void bgp_open_capability(struct stream *, struct peer *);
extern void bgp_capability_vty_out(struct vty *vty, struct peer *peer,
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 772e20dc8..65806bb5f 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -3168,6 +3168,36 @@ DEFUN (no_bgp_graceful_restart_rib_stale_time,
return CMD_SUCCESS;
}
+DEFUN(bgp_llgr_stalepath_time, bgp_llgr_stalepath_time_cmd,
+ "bgp long-lived-graceful-restart stale-time (0-4294967295)", BGP_STR
+ "Enable Long-lived Graceful Restart\n"
+ "Specifies maximum time to wait before purging long-lived stale routes\n"
+ "Stale time value (seconds)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ uint32_t llgr_stale_time;
+
+ llgr_stale_time = strtoul(argv[3]->arg, NULL, 10);
+ bgp->llgr_stale_time = llgr_stale_time;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_bgp_llgr_stalepath_time, no_bgp_llgr_stalepath_time_cmd,
+ "no bgp long-lived-graceful-restart stale-time [(0-4294967295)]",
+ NO_STR BGP_STR
+ "Enable Long-lived Graceful Restart\n"
+ "Specifies maximum time to wait before purging long-lived stale routes\n"
+ "Stale time value (seconds)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp->llgr_stale_time = BGP_DEFAULT_LLGR_STALE_TIME;
+
+ return CMD_SUCCESS;
+}
+
static inline void bgp_initiate_graceful_shut_unshut(struct vty *vty,
struct bgp *bgp)
{
@@ -12838,6 +12868,61 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
}
}
+ /* Long-lived Graceful Restart */
+ if (CHECK_FLAG(p->cap, PEER_CAP_LLGR_RCV)
+ || CHECK_FLAG(p->cap, PEER_CAP_LLGR_ADV)) {
+ json_object *json_llgr = NULL;
+ const char *afi_safi_str;
+
+ if (CHECK_FLAG(p->cap,
+ PEER_CAP_LLGR_ADV)
+ && CHECK_FLAG(p->cap,
+ PEER_CAP_LLGR_RCV))
+ json_object_string_add(
+ json_cap,
+ "longLivedGracefulRestart",
+ "advertisedAndReceived");
+ else if (CHECK_FLAG(p->cap,
+ PEER_CAP_LLGR_ADV))
+ json_object_string_add(
+ json_cap,
+ "longLivedGracefulRestart",
+ "advertised");
+ else if (CHECK_FLAG(p->cap,
+ PEER_CAP_LLGR_RCV))
+ json_object_string_add(
+ json_cap,
+ "longLivedGracefulRestart",
+ "received");
+
+ if (CHECK_FLAG(p->cap,
+ PEER_CAP_LLGR_RCV)) {
+ json_llgr =
+ json_object_new_object();
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (CHECK_FLAG(
+ p->af_cap
+ [afi]
+ [safi],
+ PEER_CAP_ENHE_AF_RCV)) {
+ afi_safi_str = get_afi_safi_str(
+ afi,
+ safi,
+ true);
+ json_object_string_add(
+ json_llgr,
+ afi_safi_str,
+ "received");
+ }
+ }
+ json_object_object_add(
+ json_cap,
+ "longLivedGracefulRestartByPeer",
+ json_llgr);
+ }
+ }
+
/* Route Refresh */
if (CHECK_FLAG(p->cap, PEER_CAP_REFRESH_ADV)
|| CHECK_FLAG(p->cap,
@@ -13278,6 +13363,43 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
}
}
+ /* Long-lived Graceful Restart */
+ if (CHECK_FLAG(p->cap, PEER_CAP_LLGR_RCV)
+ || CHECK_FLAG(p->cap, PEER_CAP_LLGR_ADV)) {
+ vty_out(vty,
+ " Long-lived Graceful Restart:");
+ if (CHECK_FLAG(p->cap,
+ PEER_CAP_LLGR_ADV))
+ vty_out(vty, " advertised");
+ if (CHECK_FLAG(p->cap,
+ PEER_CAP_LLGR_RCV))
+ vty_out(vty, " %sreceived",
+ CHECK_FLAG(
+ p->cap,
+ PEER_CAP_LLGR_ADV)
+ ? "and "
+ : "");
+ vty_out(vty, "\n");
+
+ if (CHECK_FLAG(p->cap,
+ PEER_CAP_LLGR_RCV)) {
+ vty_out(vty,
+ " Address families by peer:\n");
+ FOREACH_AFI_SAFI (afi, safi)
+ if (CHECK_FLAG(
+ p->af_cap
+ [afi]
+ [safi],
+ PEER_CAP_LLGR_AF_RCV))
+ vty_out(vty,
+ " %s\n",
+ get_afi_safi_str(
+ afi,
+ safi,
+ false));
+ }
+ }
+
/* Route Refresh */
if (CHECK_FLAG(p->cap, PEER_CAP_REFRESH_ADV)
|| CHECK_FLAG(p->cap,
@@ -17253,6 +17375,12 @@ int bgp_config_write(struct vty *vty)
if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
vty_out(vty, " bgp graceful-shutdown\n");
+ /* Long-lived Graceful Restart */
+ if (bgp->llgr_stale_time != BGP_DEFAULT_LLGR_STALE_TIME)
+ vty_out(vty,
+ " bgp long-lived-graceful-restart stale-time %u\n",
+ bgp->llgr_stale_time);
+
/* BGP graceful-restart. */
if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
vty_out(vty,
@@ -17830,6 +17958,10 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &bgp_graceful_shutdown_cmd);
install_element(BGP_NODE, &no_bgp_graceful_shutdown_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);
+
/* "bgp fast-external-failover" commands */
install_element(BGP_NODE, &bgp_fast_external_failover_cmd);
install_element(BGP_NODE, &no_bgp_fast_external_failover_cmd);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index c5a5e49a4..ff2c0c8bd 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -3169,6 +3169,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp_addpath_init_bgp_data(&bgp->tx_addpath);
bgp->fast_convergence = false;
bgp->as = *as;
+ bgp->llgr_stale_time = BGP_DEFAULT_LLGR_STALE_TIME;
#ifdef ENABLE_BGP_VNC
if (inst_type != BGP_INSTANCE_TYPE_VRF) {
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 5e1eacbb9..e60acecfa 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -613,6 +613,9 @@ struct bgp {
struct graceful_restart_info gr_info[AFI_MAX][SAFI_MAX];
uint32_t rib_stale_time;
+ /* BGP Long-lived Graceful Restart */
+ uint32_t llgr_stale_time;
+
#define BGP_ROUTE_SELECT_DELAY 1
#define BGP_MAX_BEST_ROUTE_SELECT 10000
/* Maximum-paths configuration */
@@ -1052,6 +1055,11 @@ enum bgp_fsm_status {
#define PEER_HOSTNAME(peer) ((peer)->host ? (peer)->host : "(unknown peer)")
+struct llgr_info {
+ uint32_t stale_time;
+ uint8_t flags;
+};
+
/* BGP neighbor structure. */
struct peer {
/* BGP structure. */
@@ -1182,6 +1190,8 @@ struct peer {
#define PEER_CAP_ENHANCED_RR_RCV (1U << 18) /* enhanced rr received */
#define PEER_CAP_EXTENDED_MESSAGE_ADV (1U << 19)
#define PEER_CAP_EXTENDED_MESSAGE_RCV (1U << 20)
+#define PEER_CAP_LLGR_ADV (1U << 21)
+#define PEER_CAP_LLGR_RCV (1U << 22)
/* Capability flags (reset in bgp_stop) */
uint32_t af_cap[AFI_MAX][SAFI_MAX];
@@ -1200,6 +1210,8 @@ struct peer {
#define PEER_CAP_ENHE_AF_ADV (1U << 12) /* Extended nexthopi afi/safi advertised */
#define PEER_CAP_ENHE_AF_RCV (1U << 13) /* Extended nexthop afi/safi received */
#define PEER_CAP_ENHE_AF_NEGO (1U << 14) /* Extended nexthop afi/safi negotiated */
+#define PEER_CAP_LLGR_AF_ADV (1U << 15)
+#define PEER_CAP_LLGR_AF_RCV (1U << 16)
/* Global configuration flags. */
/*
@@ -1657,6 +1669,9 @@ struct peer {
/* set TCP max segment size */
uint32_t tcp_mss;
+ /* Long-lived Graceful Restart */
+ struct llgr_info llgr[AFI_MAX][SAFI_MAX];
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(peer);
@@ -1869,6 +1884,9 @@ struct bgp_nlri {
#define BGP_DEFAULT_RIB_STALE_TIME 500
#define BGP_DEFAULT_UPDATE_ADVERTISEMENT_TIME 1
+/* BGP Long-lived Graceful Restart */
+#define BGP_DEFAULT_LLGR_STALE_TIME 360
+
/* BGP uptime string length. */
#define BGP_UPTIME_LEN 25
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 1793ae3d2..38d215e76 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -989,6 +989,18 @@ BGP GR Peer Mode Commands
at the peer level.
+Long-lived Graceful Restart
+---------------------------
+
+Currently, only restarter mode is supported. This capability is advertised only
+if graceful restart capability is negotiated.
+
+.. clicmd:: bgp long-lived-graceful-restart stale-time (0-4294967295)
+
+ Specifies the maximum time to wait before purging long-lived stale routes for
+ helper routers.
+
+
.. _bgp-shutdown:
Administrative Shutdown