mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 04:36:45 +00:00
bgpd: Handle LLGR capability using dynamic capabilities
LLGR stale time is exchanged using OPEN messages. In order to reduce stal time before doing an actual graceful restart + LLGR, it might be useful to increase the time, but this is not possible without resetting the session. With this change, it's possible to send dynamic capability with a new value, and GR will respect a new reset time value when LLGR kicks in. Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
This commit is contained in:
parent
b1b3fc5fe0
commit
7e6ca0742c
@ -1211,6 +1211,8 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
|
|||||||
unsigned long cap_len;
|
unsigned long cap_len;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint32_t gr_restart_time;
|
uint32_t gr_restart_time;
|
||||||
|
const char *capability = lookup_msg(capcode_str, capability_code,
|
||||||
|
"Unknown");
|
||||||
|
|
||||||
if (!peer_established(peer->connection))
|
if (!peer_established(peer->connection))
|
||||||
return;
|
return;
|
||||||
@ -1254,12 +1256,12 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
|
|||||||
stream_putc_at(s, cap_len, len);
|
stream_putc_at(s, cap_len, len);
|
||||||
|
|
||||||
if (bgp_debug_neighbor_events(peer))
|
if (bgp_debug_neighbor_events(peer))
|
||||||
zlog_debug("%pBP sending CAPABILITY has %s Software Version for afi/safi: %s/%s",
|
zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s",
|
||||||
peer,
|
peer,
|
||||||
action == CAPABILITY_ACTION_SET
|
action == CAPABILITY_ACTION_SET
|
||||||
? "Advertising"
|
? "Advertising"
|
||||||
: "Removing",
|
: "Removing",
|
||||||
iana_afi2str(pkt_afi),
|
capability, iana_afi2str(pkt_afi),
|
||||||
iana_safi2str(pkt_safi));
|
iana_safi2str(pkt_safi));
|
||||||
break;
|
break;
|
||||||
case CAPABILITY_CODE_MP:
|
case CAPABILITY_CODE_MP:
|
||||||
@ -1271,12 +1273,13 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
|
|||||||
stream_putc(s, pkt_safi);
|
stream_putc(s, pkt_safi);
|
||||||
|
|
||||||
if (bgp_debug_neighbor_events(peer))
|
if (bgp_debug_neighbor_events(peer))
|
||||||
zlog_debug(
|
zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s",
|
||||||
"%pBP sending CAPABILITY has %s MP_EXT CAP for afi/safi: %s/%s",
|
|
||||||
peer,
|
peer,
|
||||||
action == CAPABILITY_ACTION_SET ? "Advertising"
|
action == CAPABILITY_ACTION_SET
|
||||||
|
? "Advertising"
|
||||||
: "Removing",
|
: "Removing",
|
||||||
iana_afi2str(pkt_afi), iana_safi2str(pkt_safi));
|
capability, iana_afi2str(pkt_afi),
|
||||||
|
iana_safi2str(pkt_safi));
|
||||||
break;
|
break;
|
||||||
case CAPABILITY_CODE_RESTART:
|
case CAPABILITY_CODE_RESTART:
|
||||||
if (!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART) &&
|
if (!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART) &&
|
||||||
@ -1320,27 +1323,63 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Software Version capability Len. */
|
|
||||||
len = stream_get_endp(s) - cap_len - 1;
|
len = stream_get_endp(s) - cap_len - 1;
|
||||||
stream_putc_at(s, cap_len, len);
|
stream_putc_at(s, cap_len, len);
|
||||||
|
|
||||||
if (bgp_debug_neighbor_events(peer))
|
if (bgp_debug_neighbor_events(peer))
|
||||||
zlog_debug("%pBP sending CAPABILITY has %s Graceful-Restart CAP for afi/safi: %s/%s",
|
zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s",
|
||||||
peer,
|
peer,
|
||||||
action == CAPABILITY_ACTION_SET
|
action == CAPABILITY_ACTION_SET
|
||||||
? "Advertising"
|
? "Advertising"
|
||||||
: "Removing",
|
: "Removing",
|
||||||
iana_afi2str(pkt_afi),
|
capability, iana_afi2str(pkt_afi),
|
||||||
iana_safi2str(pkt_safi));
|
iana_safi2str(pkt_safi));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
case CAPABILITY_CODE_LLGR:
|
||||||
|
if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SET_FLAG(peer->cap, PEER_CAP_LLGR_ADV);
|
||||||
|
|
||||||
|
stream_putc(s, action);
|
||||||
|
stream_putc(s, CAPABILITY_CODE_LLGR);
|
||||||
|
cap_len = 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
len = stream_get_endp(s) - cap_len - 1;
|
||||||
|
stream_putc_at(s, cap_len, len);
|
||||||
|
|
||||||
|
if (bgp_debug_neighbor_events(peer))
|
||||||
|
zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s",
|
||||||
|
peer,
|
||||||
|
action == CAPABILITY_ACTION_SET
|
||||||
|
? "Advertising"
|
||||||
|
: "Removing",
|
||||||
|
capability, iana_afi2str(pkt_afi),
|
||||||
|
iana_safi2str(pkt_safi));
|
||||||
|
break;
|
||||||
case CAPABILITY_CODE_REFRESH:
|
case CAPABILITY_CODE_REFRESH:
|
||||||
case CAPABILITY_CODE_ORF:
|
case CAPABILITY_CODE_ORF:
|
||||||
case CAPABILITY_CODE_AS4:
|
case CAPABILITY_CODE_AS4:
|
||||||
case CAPABILITY_CODE_DYNAMIC:
|
case CAPABILITY_CODE_DYNAMIC:
|
||||||
case CAPABILITY_CODE_ADDPATH:
|
case CAPABILITY_CODE_ADDPATH:
|
||||||
case CAPABILITY_CODE_ENHANCED_RR:
|
case CAPABILITY_CODE_ENHANCED_RR:
|
||||||
case CAPABILITY_CODE_LLGR:
|
|
||||||
case CAPABILITY_CODE_FQDN:
|
case CAPABILITY_CODE_FQDN:
|
||||||
case CAPABILITY_CODE_ENHE:
|
case CAPABILITY_CODE_ENHE:
|
||||||
case CAPABILITY_CODE_EXT_MESSAGE:
|
case CAPABILITY_CODE_EXT_MESSAGE:
|
||||||
@ -2832,6 +2871,83 @@ static int bgp_route_refresh_receive(struct peer_connection *connection,
|
|||||||
return BGP_PACKET_NOOP;
|
return BGP_PACKET_NOOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bgp_dynamic_capability_llgr(uint8_t *pnt, int action,
|
||||||
|
struct capability_header *hdr,
|
||||||
|
struct peer *peer)
|
||||||
|
{
|
||||||
|
uint8_t *data = pnt + 3;
|
||||||
|
uint8_t *end = data + hdr->length;
|
||||||
|
size_t len = end - data;
|
||||||
|
|
||||||
|
if (action == CAPABILITY_ACTION_SET) {
|
||||||
|
if (len < BGP_CAP_LLGR_MIN_PACKET_LEN) {
|
||||||
|
zlog_err("%pBP: Received invalid Long-Lived Graceful-Restart capability length %zu",
|
||||||
|
peer, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SET_FLAG(peer->cap, PEER_CAP_LLGR_RCV);
|
||||||
|
|
||||||
|
while (data + BGP_CAP_LLGR_MIN_PACKET_LEN <= end) {
|
||||||
|
afi_t afi;
|
||||||
|
safi_t safi;
|
||||||
|
iana_afi_t pkt_afi;
|
||||||
|
iana_safi_t pkt_safi;
|
||||||
|
struct graceful_restart_af graf;
|
||||||
|
|
||||||
|
memcpy(&graf, data, sizeof(graf));
|
||||||
|
pkt_afi = ntohs(graf.afi);
|
||||||
|
pkt_safi = safi_int2iana(graf.safi);
|
||||||
|
|
||||||
|
/* Stale time is after AFI/SAFI/flags.
|
||||||
|
* It's encoded as 24 bits (= 3 bytes), so we need to
|
||||||
|
* put it into 32 bits.
|
||||||
|
*/
|
||||||
|
uint32_t stale_time;
|
||||||
|
uint8_t *stale_time_ptr = data + 4;
|
||||||
|
|
||||||
|
stale_time = stale_time_ptr[0] << 16;
|
||||||
|
stale_time |= stale_time_ptr[1] << 8;
|
||||||
|
stale_time |= stale_time_ptr[2];
|
||||||
|
|
||||||
|
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 {
|
||||||
|
if (bgp_debug_neighbor_events(peer))
|
||||||
|
zlog_debug("%s Addr-family %s/%s(afi/safi) Long-lived Graceful Restart capability stale time %u sec",
|
||||||
|
peer->host,
|
||||||
|
iana_afi2str(pkt_afi),
|
||||||
|
iana_safi2str(pkt_safi),
|
||||||
|
stale_time);
|
||||||
|
|
||||||
|
peer->llgr[afi][safi].flags = graf.flag;
|
||||||
|
peer->llgr[afi][safi].stale_time =
|
||||||
|
MIN(stale_time,
|
||||||
|
peer->bgp->llgr_stale_time);
|
||||||
|
SET_FLAG(peer->af_cap[afi][safi],
|
||||||
|
PEER_CAP_LLGR_AF_RCV);
|
||||||
|
}
|
||||||
|
|
||||||
|
data += BGP_CAP_LLGR_MIN_PACKET_LEN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
UNSET_FLAG(peer->cap, PEER_CAP_LLGR_RCV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void bgp_dynamic_capability_graceful_restart(uint8_t *pnt, int action,
|
static void bgp_dynamic_capability_graceful_restart(uint8_t *pnt, int action,
|
||||||
struct capability_header *hdr,
|
struct capability_header *hdr,
|
||||||
struct peer *peer)
|
struct peer *peer)
|
||||||
@ -3065,13 +3181,15 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
|
|||||||
bgp_dynamic_capability_graceful_restart(pnt, action,
|
bgp_dynamic_capability_graceful_restart(pnt, action,
|
||||||
hdr, peer);
|
hdr, peer);
|
||||||
break;
|
break;
|
||||||
|
case CAPABILITY_CODE_LLGR:
|
||||||
|
bgp_dynamic_capability_llgr(pnt, action, hdr, peer);
|
||||||
|
break;
|
||||||
case CAPABILITY_CODE_REFRESH:
|
case CAPABILITY_CODE_REFRESH:
|
||||||
case CAPABILITY_CODE_ORF:
|
case CAPABILITY_CODE_ORF:
|
||||||
case CAPABILITY_CODE_AS4:
|
case CAPABILITY_CODE_AS4:
|
||||||
case CAPABILITY_CODE_DYNAMIC:
|
case CAPABILITY_CODE_DYNAMIC:
|
||||||
case CAPABILITY_CODE_ADDPATH:
|
case CAPABILITY_CODE_ADDPATH:
|
||||||
case CAPABILITY_CODE_ENHANCED_RR:
|
case CAPABILITY_CODE_ENHANCED_RR:
|
||||||
case CAPABILITY_CODE_LLGR:
|
|
||||||
case CAPABILITY_CODE_FQDN:
|
case CAPABILITY_CODE_FQDN:
|
||||||
case CAPABILITY_CODE_ENHE:
|
case CAPABILITY_CODE_ENHE:
|
||||||
case CAPABILITY_CODE_EXT_MESSAGE:
|
case CAPABILITY_CODE_EXT_MESSAGE:
|
||||||
|
@ -3619,10 +3619,16 @@ DEFUN(bgp_llgr_stalepath_time, bgp_llgr_stalepath_time_cmd,
|
|||||||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
|
||||||
uint32_t llgr_stale_time;
|
uint32_t llgr_stale_time;
|
||||||
|
struct listnode *node, *nnode;
|
||||||
|
struct peer *peer;
|
||||||
|
|
||||||
llgr_stale_time = strtoul(argv[3]->arg, NULL, 10);
|
llgr_stale_time = strtoul(argv[3]->arg, NULL, 10);
|
||||||
bgp->llgr_stale_time = llgr_stale_time;
|
bgp->llgr_stale_time = llgr_stale_time;
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
|
||||||
|
bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
|
||||||
|
CAPABILITY_CODE_LLGR, CAPABILITY_ACTION_SET);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3634,9 +3640,16 @@ DEFUN(no_bgp_llgr_stalepath_time, no_bgp_llgr_stalepath_time_cmd,
|
|||||||
"Stale time value (seconds)\n")
|
"Stale time value (seconds)\n")
|
||||||
{
|
{
|
||||||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
struct listnode *node, *nnode;
|
||||||
|
struct peer *peer;
|
||||||
|
|
||||||
bgp->llgr_stale_time = BGP_DEFAULT_LLGR_STALE_TIME;
|
bgp->llgr_stale_time = BGP_DEFAULT_LLGR_STALE_TIME;
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
|
||||||
|
bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
|
||||||
|
CAPABILITY_CODE_LLGR,
|
||||||
|
CAPABILITY_ACTION_UNSET);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user