mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 11:01:48 +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;
|
||||
uint16_t len;
|
||||
uint32_t gr_restart_time;
|
||||
const char *capability = lookup_msg(capcode_str, capability_code,
|
||||
"Unknown");
|
||||
|
||||
if (!peer_established(peer->connection))
|
||||
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);
|
||||
|
||||
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,
|
||||
action == CAPABILITY_ACTION_SET
|
||||
? "Advertising"
|
||||
: "Removing",
|
||||
iana_afi2str(pkt_afi),
|
||||
capability, iana_afi2str(pkt_afi),
|
||||
iana_safi2str(pkt_safi));
|
||||
break;
|
||||
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);
|
||||
|
||||
if (bgp_debug_neighbor_events(peer))
|
||||
zlog_debug(
|
||||
"%pBP sending CAPABILITY has %s MP_EXT CAP for afi/safi: %s/%s",
|
||||
peer,
|
||||
action == CAPABILITY_ACTION_SET ? "Advertising"
|
||||
: "Removing",
|
||||
iana_afi2str(pkt_afi), iana_safi2str(pkt_safi));
|
||||
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_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;
|
||||
stream_putc_at(s, cap_len, len);
|
||||
|
||||
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,
|
||||
action == CAPABILITY_ACTION_SET
|
||||
? "Advertising"
|
||||
: "Removing",
|
||||
iana_afi2str(pkt_afi),
|
||||
capability, iana_afi2str(pkt_afi),
|
||||
iana_safi2str(pkt_safi));
|
||||
|
||||
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_ORF:
|
||||
case CAPABILITY_CODE_AS4:
|
||||
case CAPABILITY_CODE_DYNAMIC:
|
||||
case CAPABILITY_CODE_ADDPATH:
|
||||
case CAPABILITY_CODE_ENHANCED_RR:
|
||||
case CAPABILITY_CODE_LLGR:
|
||||
case CAPABILITY_CODE_FQDN:
|
||||
case CAPABILITY_CODE_ENHE:
|
||||
case CAPABILITY_CODE_EXT_MESSAGE:
|
||||
@ -2832,6 +2871,83 @@ static int bgp_route_refresh_receive(struct peer_connection *connection,
|
||||
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,
|
||||
struct capability_header *hdr,
|
||||
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,
|
||||
hdr, peer);
|
||||
break;
|
||||
case CAPABILITY_CODE_LLGR:
|
||||
bgp_dynamic_capability_llgr(pnt, action, hdr, peer);
|
||||
break;
|
||||
case CAPABILITY_CODE_REFRESH:
|
||||
case CAPABILITY_CODE_ORF:
|
||||
case CAPABILITY_CODE_AS4:
|
||||
case CAPABILITY_CODE_DYNAMIC:
|
||||
case CAPABILITY_CODE_ADDPATH:
|
||||
case CAPABILITY_CODE_ENHANCED_RR:
|
||||
case CAPABILITY_CODE_LLGR:
|
||||
case CAPABILITY_CODE_FQDN:
|
||||
case CAPABILITY_CODE_ENHE:
|
||||
case CAPABILITY_CODE_EXT_MESSAGE:
|
||||
|
@ -3619,10 +3619,16 @@ DEFUN(bgp_llgr_stalepath_time, bgp_llgr_stalepath_time_cmd,
|
||||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||
|
||||
uint32_t llgr_stale_time;
|
||||
struct listnode *node, *nnode;
|
||||
struct peer *peer;
|
||||
|
||||
llgr_stale_time = strtoul(argv[3]->arg, NULL, 10);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -3634,9 +3640,16 @@ DEFUN(no_bgp_llgr_stalepath_time, no_bgp_llgr_stalepath_time_cmd,
|
||||
"Stale time value (seconds)\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||
struct listnode *node, *nnode;
|
||||
struct peer *peer;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user