mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-16 08:32:45 +00:00
bgpd: Implement Paths-Limit capability
https://datatracker.ietf.org/doc/html/draft-abraitis-idr-addpath-paths-limit Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
This commit is contained in:
parent
cd7851d99e
commit
72f0e06824
@ -21,6 +21,12 @@ struct bgp_addpath_capability {
|
|||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bgp_paths_limit_capability {
|
||||||
|
uint16_t afi;
|
||||||
|
uint8_t safi;
|
||||||
|
uint16_t paths_limit;
|
||||||
|
};
|
||||||
|
|
||||||
#define BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE 1
|
#define BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE 1
|
||||||
|
|
||||||
void bgp_addpath_init_bgp_data(struct bgp_addpath_bgp_data *d);
|
void bgp_addpath_init_bgp_data(struct bgp_addpath_bgp_data *d);
|
||||||
|
@ -260,6 +260,8 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
|
|||||||
peer->afc_recv[afi][safi] = from_peer->afc_recv[afi][safi];
|
peer->afc_recv[afi][safi] = from_peer->afc_recv[afi][safi];
|
||||||
peer->orf_plist[afi][safi] = from_peer->orf_plist[afi][safi];
|
peer->orf_plist[afi][safi] = from_peer->orf_plist[afi][safi];
|
||||||
peer->llgr[afi][safi] = from_peer->llgr[afi][safi];
|
peer->llgr[afi][safi] = from_peer->llgr[afi][safi];
|
||||||
|
peer->addpath_paths_limit[afi][safi] =
|
||||||
|
from_peer->addpath_paths_limit[afi][safi];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bgp_getsockname(peer) < 0) {
|
if (bgp_getsockname(peer) < 0) {
|
||||||
|
@ -42,6 +42,7 @@ const struct message capcode_str[] = {
|
|||||||
{ CAPABILITY_CODE_LLGR, "Long-lived BGP Graceful Restart" },
|
{ CAPABILITY_CODE_LLGR, "Long-lived BGP Graceful Restart" },
|
||||||
{ CAPABILITY_CODE_ROLE, "Role" },
|
{ CAPABILITY_CODE_ROLE, "Role" },
|
||||||
{ CAPABILITY_CODE_SOFT_VERSION, "Software Version" },
|
{ CAPABILITY_CODE_SOFT_VERSION, "Software Version" },
|
||||||
|
{ CAPABILITY_CODE_PATHS_LIMIT, "Paths-Limit" },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -61,6 +62,7 @@ static const size_t cap_minsizes[] = {
|
|||||||
[CAPABILITY_CODE_LLGR] = CAPABILITY_CODE_LLGR_LEN,
|
[CAPABILITY_CODE_LLGR] = CAPABILITY_CODE_LLGR_LEN,
|
||||||
[CAPABILITY_CODE_ROLE] = CAPABILITY_CODE_ROLE_LEN,
|
[CAPABILITY_CODE_ROLE] = CAPABILITY_CODE_ROLE_LEN,
|
||||||
[CAPABILITY_CODE_SOFT_VERSION] = CAPABILITY_CODE_SOFT_VERSION_LEN,
|
[CAPABILITY_CODE_SOFT_VERSION] = CAPABILITY_CODE_SOFT_VERSION_LEN,
|
||||||
|
[CAPABILITY_CODE_PATHS_LIMIT] = CAPABILITY_CODE_PATHS_LIMIT_LEN,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* value the capability must be a multiple of.
|
/* value the capability must be a multiple of.
|
||||||
@ -83,6 +85,7 @@ static const size_t cap_modsizes[] = {
|
|||||||
[CAPABILITY_CODE_LLGR] = 1,
|
[CAPABILITY_CODE_LLGR] = 1,
|
||||||
[CAPABILITY_CODE_ROLE] = 1,
|
[CAPABILITY_CODE_ROLE] = 1,
|
||||||
[CAPABILITY_CODE_SOFT_VERSION] = 1,
|
[CAPABILITY_CODE_SOFT_VERSION] = 1,
|
||||||
|
[CAPABILITY_CODE_PATHS_LIMIT] = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
|
/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
|
||||||
@ -739,6 +742,62 @@ static int bgp_capability_addpath(struct peer *peer,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bgp_capability_paths_limit(struct peer *peer,
|
||||||
|
struct capability_header *hdr)
|
||||||
|
{
|
||||||
|
struct stream *s = BGP_INPUT(peer);
|
||||||
|
size_t end = stream_get_getp(s) + hdr->length;
|
||||||
|
|
||||||
|
if (hdr->length % CAPABILITY_CODE_PATHS_LIMIT_LEN) {
|
||||||
|
flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
|
||||||
|
"Paths-Limit: Received invalid length %d, non-multiple of %d",
|
||||||
|
hdr->length, CAPABILITY_CODE_PATHS_LIMIT_LEN);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV)) {
|
||||||
|
flog_warn(EC_BGP_CAPABILITY_INVALID_DATA,
|
||||||
|
"Paths-Limit: Received Paths-Limit capability without Add-Path capability");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SET_FLAG(peer->cap, PEER_CAP_PATHS_LIMIT_RCV);
|
||||||
|
|
||||||
|
while (stream_get_getp(s) + CAPABILITY_CODE_PATHS_LIMIT_LEN <= end) {
|
||||||
|
afi_t afi;
|
||||||
|
safi_t safi;
|
||||||
|
iana_afi_t pkt_afi = stream_getw(s);
|
||||||
|
iana_safi_t pkt_safi = stream_getc(s);
|
||||||
|
uint16_t paths_limit = stream_getw(s);
|
||||||
|
|
||||||
|
if (bgp_debug_neighbor_events(peer))
|
||||||
|
zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s limit: %u",
|
||||||
|
peer->host,
|
||||||
|
lookup_msg(capcode_str, hdr->code, NULL),
|
||||||
|
iana_afi2str(pkt_afi),
|
||||||
|
iana_safi2str(pkt_safi), paths_limit);
|
||||||
|
|
||||||
|
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 Paths-Limit capability for this AFI/SAFI",
|
||||||
|
peer->host, iana_afi2str(pkt_afi),
|
||||||
|
iana_safi2str(pkt_safi));
|
||||||
|
continue;
|
||||||
|
} else if (!peer->afc[afi][safi]) {
|
||||||
|
if (bgp_debug_neighbor_events(peer))
|
||||||
|
zlog_debug("%s Addr-family %s/%s(afi/safi) not enabled. Ignore the Paths-Limit capability for this AFI/SAFI",
|
||||||
|
peer->host, iana_afi2str(pkt_afi),
|
||||||
|
iana_safi2str(pkt_safi));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_PATHS_LIMIT_AF_RCV);
|
||||||
|
peer->addpath_paths_limit[afi][safi].receive = paths_limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int bgp_capability_enhe(struct peer *peer, struct capability_header *hdr)
|
static int bgp_capability_enhe(struct peer *peer, struct capability_header *hdr)
|
||||||
{
|
{
|
||||||
struct stream *s = BGP_INPUT(peer);
|
struct stream *s = BGP_INPUT(peer);
|
||||||
@ -1012,6 +1071,7 @@ static int bgp_capability_parse(struct peer *peer, size_t length,
|
|||||||
case CAPABILITY_CODE_EXT_MESSAGE:
|
case CAPABILITY_CODE_EXT_MESSAGE:
|
||||||
case CAPABILITY_CODE_ROLE:
|
case CAPABILITY_CODE_ROLE:
|
||||||
case CAPABILITY_CODE_SOFT_VERSION:
|
case CAPABILITY_CODE_SOFT_VERSION:
|
||||||
|
case CAPABILITY_CODE_PATHS_LIMIT:
|
||||||
/* Check length. */
|
/* Check length. */
|
||||||
if (caphdr.length < cap_minsizes[caphdr.code]) {
|
if (caphdr.length < cap_minsizes[caphdr.code]) {
|
||||||
zlog_info(
|
zlog_info(
|
||||||
@ -1113,6 +1173,9 @@ static int bgp_capability_parse(struct peer *peer, size_t length,
|
|||||||
case CAPABILITY_CODE_SOFT_VERSION:
|
case CAPABILITY_CODE_SOFT_VERSION:
|
||||||
ret = bgp_capability_software_version(peer, &caphdr);
|
ret = bgp_capability_software_version(peer, &caphdr);
|
||||||
break;
|
break;
|
||||||
|
case CAPABILITY_CODE_PATHS_LIMIT:
|
||||||
|
ret = bgp_capability_paths_limit(peer, &caphdr);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (caphdr.code > 128) {
|
if (caphdr.code > 128) {
|
||||||
/* We don't send Notification for unknown vendor
|
/* We don't send Notification for unknown vendor
|
||||||
@ -1874,6 +1937,31 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Paths-Limit capability */
|
||||||
|
SET_FLAG(peer->cap, PEER_CAP_PATHS_LIMIT_ADV);
|
||||||
|
stream_putc(s, BGP_OPEN_OPT_CAP);
|
||||||
|
ext_opt_params ? stream_putw(s, (CAPABILITY_CODE_PATHS_LIMIT_LEN *
|
||||||
|
afi_safi_count) +
|
||||||
|
2)
|
||||||
|
: stream_putc(s, (CAPABILITY_CODE_PATHS_LIMIT_LEN *
|
||||||
|
afi_safi_count) +
|
||||||
|
2);
|
||||||
|
stream_putc(s, CAPABILITY_CODE_PATHS_LIMIT);
|
||||||
|
stream_putc(s, CAPABILITY_CODE_PATHS_LIMIT_LEN * afi_safi_count);
|
||||||
|
|
||||||
|
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_putw(s, peer->addpath_paths_limit[afi][safi].send);
|
||||||
|
|
||||||
|
SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_PATHS_LIMIT_AF_ADV);
|
||||||
|
}
|
||||||
|
|
||||||
/* ORF capability. */
|
/* ORF capability. */
|
||||||
FOREACH_AFI_SAFI (afi, safi) {
|
FOREACH_AFI_SAFI (afi, safi) {
|
||||||
if (CHECK_FLAG(peer->af_flags[afi][safi],
|
if (CHECK_FLAG(peer->af_flags[afi][safi],
|
||||||
|
@ -53,6 +53,7 @@ struct graceful_restart_af {
|
|||||||
#define CAPABILITY_CODE_ENHE 5 /* Extended Next Hop Encoding */
|
#define CAPABILITY_CODE_ENHE 5 /* Extended Next Hop Encoding */
|
||||||
#define CAPABILITY_CODE_EXT_MESSAGE 6 /* Extended Message Support */
|
#define CAPABILITY_CODE_EXT_MESSAGE 6 /* Extended Message Support */
|
||||||
#define CAPABILITY_CODE_ROLE 9 /* Role Capability */
|
#define CAPABILITY_CODE_ROLE 9 /* Role Capability */
|
||||||
|
#define CAPABILITY_CODE_PATHS_LIMIT 76 /* Paths Limit Capability */
|
||||||
|
|
||||||
/* Capability Length */
|
/* Capability Length */
|
||||||
#define CAPABILITY_CODE_MP_LEN 4
|
#define CAPABILITY_CODE_MP_LEN 4
|
||||||
@ -61,6 +62,7 @@ struct graceful_restart_af {
|
|||||||
#define CAPABILITY_CODE_RESTART_LEN 2 /* Receiving only case */
|
#define CAPABILITY_CODE_RESTART_LEN 2 /* Receiving only case */
|
||||||
#define CAPABILITY_CODE_AS4_LEN 4
|
#define CAPABILITY_CODE_AS4_LEN 4
|
||||||
#define CAPABILITY_CODE_ADDPATH_LEN 4
|
#define CAPABILITY_CODE_ADDPATH_LEN 4
|
||||||
|
#define CAPABILITY_CODE_PATHS_LIMIT_LEN 5
|
||||||
#define CAPABILITY_CODE_ENHE_LEN 6 /* NRLI AFI = 2, SAFI = 2, Nexthop AFI = 2 */
|
#define CAPABILITY_CODE_ENHE_LEN 6 /* NRLI AFI = 2, SAFI = 2, Nexthop AFI = 2 */
|
||||||
#define CAPABILITY_CODE_MIN_FQDN_LEN 2
|
#define CAPABILITY_CODE_MIN_FQDN_LEN 2
|
||||||
#define CAPABILITY_CODE_ENHANCED_LEN 0
|
#define CAPABILITY_CODE_ENHANCED_LEN 0
|
||||||
|
@ -1461,6 +1461,49 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
|
|||||||
capability, iana_afi2str(pkt_afi),
|
capability, iana_afi2str(pkt_afi),
|
||||||
iana_safi2str(pkt_safi));
|
iana_safi2str(pkt_safi));
|
||||||
|
|
||||||
|
break;
|
||||||
|
case CAPABILITY_CODE_PATHS_LIMIT:
|
||||||
|
SET_FLAG(peer->cap, PEER_CAP_PATHS_LIMIT_ADV);
|
||||||
|
|
||||||
|
FOREACH_AFI_SAFI (afi, safi) {
|
||||||
|
if (!peer->afc[afi][safi])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
addpath_afi_safi_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_putc(s, action);
|
||||||
|
stream_putc(s, CAPABILITY_CODE_PATHS_LIMIT);
|
||||||
|
stream_putc(s, CAPABILITY_CODE_PATHS_LIMIT_LEN *
|
||||||
|
addpath_afi_safi_count);
|
||||||
|
|
||||||
|
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_putw(s,
|
||||||
|
peer->addpath_paths_limit[afi][safi].send);
|
||||||
|
|
||||||
|
SET_FLAG(peer->af_cap[afi][safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_ADV);
|
||||||
|
|
||||||
|
if (bgp_debug_neighbor_events(peer))
|
||||||
|
zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s, limit: %u",
|
||||||
|
peer,
|
||||||
|
action == CAPABILITY_ACTION_SET
|
||||||
|
? "Advertising"
|
||||||
|
: "Removing",
|
||||||
|
capability, iana_afi2str(pkt_afi),
|
||||||
|
iana_safi2str(pkt_safi),
|
||||||
|
peer->addpath_paths_limit[afi][safi]
|
||||||
|
.send);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CAPABILITY_CODE_ORF:
|
case CAPABILITY_CODE_ORF:
|
||||||
/* Convert AFI, SAFI to values for packet. */
|
/* Convert AFI, SAFI to values for packet. */
|
||||||
@ -3170,6 +3213,85 @@ ignore:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bgp_dynamic_capability_paths_limit(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;
|
||||||
|
afi_t afi;
|
||||||
|
safi_t safi;
|
||||||
|
|
||||||
|
if (action == CAPABILITY_ACTION_SET) {
|
||||||
|
if (len % CAPABILITY_CODE_PATHS_LIMIT_LEN) {
|
||||||
|
flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
|
||||||
|
"Paths-Limit: Received invalid length %zu, non-multiple of %d",
|
||||||
|
len, CAPABILITY_CODE_PATHS_LIMIT_LEN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV)) {
|
||||||
|
flog_warn(EC_BGP_CAPABILITY_INVALID_DATA,
|
||||||
|
"Paths-Limit: Received Paths-Limit capability without Add-Path capability");
|
||||||
|
goto ignore;
|
||||||
|
}
|
||||||
|
|
||||||
|
SET_FLAG(peer->cap, PEER_CAP_PATHS_LIMIT_RCV);
|
||||||
|
|
||||||
|
while (data + CAPABILITY_CODE_PATHS_LIMIT_LEN <= end) {
|
||||||
|
afi_t afi;
|
||||||
|
safi_t safi;
|
||||||
|
iana_afi_t pkt_afi;
|
||||||
|
iana_safi_t pkt_safi;
|
||||||
|
struct bgp_paths_limit_capability bpl = {};
|
||||||
|
|
||||||
|
memcpy(&bpl, data, sizeof(bpl));
|
||||||
|
pkt_afi = ntohs(bpl.afi);
|
||||||
|
pkt_safi = safi_int2iana(bpl.safi);
|
||||||
|
|
||||||
|
if (bgp_debug_neighbor_events(peer))
|
||||||
|
zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s limit: %u",
|
||||||
|
peer->host,
|
||||||
|
lookup_msg(capcode_str, hdr->code,
|
||||||
|
NULL),
|
||||||
|
iana_afi2str(pkt_afi),
|
||||||
|
iana_safi2str(pkt_safi),
|
||||||
|
bpl.paths_limit);
|
||||||
|
|
||||||
|
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 Paths-Limit capability for this AFI/SAFI",
|
||||||
|
peer->host,
|
||||||
|
iana_afi2str(pkt_afi),
|
||||||
|
iana_safi2str(pkt_safi));
|
||||||
|
goto ignore;
|
||||||
|
} else if (!peer->afc[afi][safi]) {
|
||||||
|
if (bgp_debug_neighbor_events(peer))
|
||||||
|
zlog_debug("%s Addr-family %s/%s(afi/safi) not enabled. Ignore the Paths-Limit capability for this AFI/SAFI",
|
||||||
|
peer->host,
|
||||||
|
iana_afi2str(pkt_afi),
|
||||||
|
iana_safi2str(pkt_safi));
|
||||||
|
goto ignore;
|
||||||
|
}
|
||||||
|
|
||||||
|
SET_FLAG(peer->af_cap[afi][safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_RCV);
|
||||||
|
peer->addpath_paths_limit[afi][safi].receive =
|
||||||
|
bpl.paths_limit;
|
||||||
|
ignore:
|
||||||
|
data += CAPABILITY_CODE_PATHS_LIMIT_LEN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FOREACH_AFI_SAFI (afi, safi)
|
||||||
|
UNSET_FLAG(peer->af_cap[afi][safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_RCV);
|
||||||
|
|
||||||
|
UNSET_FLAG(peer->cap, PEER_CAP_PATHS_LIMIT_RCV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void bgp_dynamic_capability_orf(uint8_t *pnt, int action,
|
static void bgp_dynamic_capability_orf(uint8_t *pnt, int action,
|
||||||
struct capability_header *hdr,
|
struct capability_header *hdr,
|
||||||
struct peer *peer)
|
struct peer *peer)
|
||||||
@ -3723,6 +3845,10 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
|
|||||||
case CAPABILITY_CODE_ADDPATH:
|
case CAPABILITY_CODE_ADDPATH:
|
||||||
bgp_dynamic_capability_addpath(pnt, action, hdr, peer);
|
bgp_dynamic_capability_addpath(pnt, action, hdr, peer);
|
||||||
break;
|
break;
|
||||||
|
case CAPABILITY_CODE_PATHS_LIMIT:
|
||||||
|
bgp_dynamic_capability_paths_limit(pnt, action, hdr,
|
||||||
|
peer);
|
||||||
|
break;
|
||||||
case CAPABILITY_CODE_ORF:
|
case CAPABILITY_CODE_ORF:
|
||||||
bgp_dynamic_capability_orf(pnt, action, hdr, peer);
|
bgp_dynamic_capability_orf(pnt, action, hdr, peer);
|
||||||
break;
|
break;
|
||||||
|
@ -145,6 +145,8 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
|
|||||||
dst->addpath_type[afi][safi] = src->addpath_type[afi][safi];
|
dst->addpath_type[afi][safi] = src->addpath_type[afi][safi];
|
||||||
dst->addpath_best_selected[afi][safi] =
|
dst->addpath_best_selected[afi][safi] =
|
||||||
src->addpath_best_selected[afi][safi];
|
src->addpath_best_selected[afi][safi];
|
||||||
|
dst->addpath_paths_limit[afi][safi] =
|
||||||
|
src->addpath_paths_limit[afi][safi];
|
||||||
dst->local_as = src->local_as;
|
dst->local_as = src->local_as;
|
||||||
dst->change_local_as = src->change_local_as;
|
dst->change_local_as = src->change_local_as;
|
||||||
dst->shared_network = src->shared_network;
|
dst->shared_network = src->shared_network;
|
||||||
@ -348,6 +350,8 @@ static unsigned int updgrp_hash_key_make(const void *p)
|
|||||||
key = jhash_1word((flags & PEER_UPDGRP_AF_FLAGS), key);
|
key = jhash_1word((flags & PEER_UPDGRP_AF_FLAGS), key);
|
||||||
key = jhash_1word((uint32_t)peer->addpath_type[afi][safi], key);
|
key = jhash_1word((uint32_t)peer->addpath_type[afi][safi], key);
|
||||||
key = jhash_1word(peer->addpath_best_selected[afi][safi], key);
|
key = jhash_1word(peer->addpath_best_selected[afi][safi], key);
|
||||||
|
key = jhash_1word(peer->addpath_paths_limit[afi][safi].receive, key);
|
||||||
|
key = jhash_1word(peer->addpath_paths_limit[afi][safi].send, key);
|
||||||
key = jhash_1word((peer->cap & PEER_UPDGRP_CAP_FLAGS), key);
|
key = jhash_1word((peer->cap & PEER_UPDGRP_CAP_FLAGS), key);
|
||||||
key = jhash_1word((peer->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS),
|
key = jhash_1word((peer->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS),
|
||||||
key);
|
key);
|
||||||
@ -461,6 +465,9 @@ static unsigned int updgrp_hash_key_make(const void *p)
|
|||||||
PEER_UPDGRP_AF_CAP_FLAGS),
|
PEER_UPDGRP_AF_CAP_FLAGS),
|
||||||
peer->v_routeadv, peer->change_local_as,
|
peer->v_routeadv, peer->change_local_as,
|
||||||
peer->as_path_loop_detection);
|
peer->as_path_loop_detection);
|
||||||
|
zlog_debug("%pBP Update Group Hash: addpath paths-limit: (send %u, receive %u)",
|
||||||
|
peer, peer->addpath_paths_limit[afi][safi].send,
|
||||||
|
peer->addpath_paths_limit[afi][safi].receive);
|
||||||
zlog_debug(
|
zlog_debug(
|
||||||
"%pBP Update Group Hash: max packet size: %u pmax_out: %u Peer Group: %s rmap out: %s",
|
"%pBP Update Group Hash: max packet size: %u pmax_out: %u Peer Group: %s rmap out: %s",
|
||||||
peer, peer->max_packet_size, peer->pmax_out[afi][safi],
|
peer, peer->max_packet_size, peer->pmax_out[afi][safi],
|
||||||
|
@ -97,13 +97,19 @@ subgrp_announce_addpath_best_selected(struct bgp_dest *dest,
|
|||||||
enum bgp_path_selection_reason reason;
|
enum bgp_path_selection_reason reason;
|
||||||
char pfx_buf[PREFIX2STR_BUFFER] = {};
|
char pfx_buf[PREFIX2STR_BUFFER] = {};
|
||||||
int paths_eq = 0;
|
int paths_eq = 0;
|
||||||
int best_path_count = 0;
|
|
||||||
struct list *list = list_new();
|
struct list *list = list_new();
|
||||||
struct bgp_path_info *pi = NULL;
|
struct bgp_path_info *pi = NULL;
|
||||||
|
uint16_t paths_count = 0;
|
||||||
|
uint16_t paths_limit = peer->addpath_paths_limit[afi][safi].receive;
|
||||||
|
|
||||||
if (peer->addpath_type[afi][safi] == BGP_ADDPATH_BEST_SELECTED) {
|
if (peer->addpath_type[afi][safi] == BGP_ADDPATH_BEST_SELECTED) {
|
||||||
while (best_path_count++ <
|
paths_limit =
|
||||||
peer->addpath_best_selected[afi][safi]) {
|
paths_limit
|
||||||
|
? MIN(paths_limit,
|
||||||
|
peer->addpath_best_selected[afi][safi])
|
||||||
|
: peer->addpath_best_selected[afi][safi];
|
||||||
|
|
||||||
|
while (paths_count++ < paths_limit) {
|
||||||
struct bgp_path_info *exist = NULL;
|
struct bgp_path_info *exist = NULL;
|
||||||
|
|
||||||
for (pi = bgp_dest_get_bgp_path_info(dest); pi;
|
for (pi = bgp_dest_get_bgp_path_info(dest); pi;
|
||||||
@ -139,8 +145,26 @@ subgrp_announce_addpath_best_selected(struct bgp_dest *dest,
|
|||||||
subgroup_process_announce_selected(
|
subgroup_process_announce_selected(
|
||||||
subgrp, NULL, dest, afi, safi, id);
|
subgrp, NULL, dest, afi, safi, id);
|
||||||
} else {
|
} else {
|
||||||
subgroup_process_announce_selected(subgrp, pi, dest,
|
/* No Paths-Limit involved */
|
||||||
afi, safi, id);
|
if (!paths_limit) {
|
||||||
|
subgroup_process_announce_selected(subgrp, pi,
|
||||||
|
dest, afi,
|
||||||
|
safi, id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have Paths-Limit capability, we MUST
|
||||||
|
* not send more than the number of paths expected
|
||||||
|
* by the peer.
|
||||||
|
*/
|
||||||
|
if (paths_count++ < paths_limit)
|
||||||
|
subgroup_process_announce_selected(subgrp, pi,
|
||||||
|
dest, afi,
|
||||||
|
safi, id);
|
||||||
|
else
|
||||||
|
subgroup_process_announce_selected(subgrp, NULL,
|
||||||
|
dest, afi,
|
||||||
|
safi, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
203
bgpd/bgp_vty.c
203
bgpd/bgp_vty.c
@ -9198,6 +9198,63 @@ DEFPY(
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFPY (neighbor_addpath_paths_limit,
|
||||||
|
neighbor_addpath_paths_limit_cmd,
|
||||||
|
"neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor addpath-rx-paths-limit (1-65535)$paths_limit",
|
||||||
|
NEIGHBOR_STR
|
||||||
|
NEIGHBOR_ADDR_STR2
|
||||||
|
"Paths Limit for Addpath to receive from the peer\n"
|
||||||
|
"Maximum number of paths\n")
|
||||||
|
{
|
||||||
|
struct peer *peer;
|
||||||
|
afi_t afi = bgp_node_afi(vty);
|
||||||
|
safi_t safi = bgp_node_safi(vty);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
peer = peer_and_group_lookup_vty(vty, neighbor);
|
||||||
|
if (!peer)
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
|
||||||
|
ret = peer_af_flag_set_vty(vty, neighbor, afi, safi,
|
||||||
|
PEER_FLAG_ADDPATH_RX_PATHS_LIMIT);
|
||||||
|
|
||||||
|
peer->addpath_paths_limit[afi][safi].send = paths_limit;
|
||||||
|
|
||||||
|
bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_PATHS_LIMIT,
|
||||||
|
CAPABILITY_ACTION_SET);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFPY (no_neighbor_addpath_paths_limit,
|
||||||
|
no_neighbor_addpath_paths_limit_cmd,
|
||||||
|
"no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor addpath-rx-paths-limit [(1-65535)]",
|
||||||
|
NO_STR
|
||||||
|
NEIGHBOR_STR
|
||||||
|
NEIGHBOR_ADDR_STR2
|
||||||
|
"Paths Limit for Addpath to receive from the peer\n"
|
||||||
|
"Maximum number of paths\n")
|
||||||
|
{
|
||||||
|
struct peer *peer;
|
||||||
|
afi_t afi = bgp_node_afi(vty);
|
||||||
|
safi_t safi = bgp_node_safi(vty);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
peer = peer_and_group_lookup_vty(vty, neighbor);
|
||||||
|
if (!peer)
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
|
||||||
|
ret = peer_af_flag_unset_vty(vty, neighbor, afi, safi,
|
||||||
|
PEER_FLAG_ADDPATH_RX_PATHS_LIMIT);
|
||||||
|
|
||||||
|
peer->addpath_paths_limit[afi][safi].send = 0;
|
||||||
|
|
||||||
|
bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_PATHS_LIMIT,
|
||||||
|
CAPABILITY_ACTION_UNSET);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
DEFPY(
|
DEFPY(
|
||||||
no_neighbor_aspath_loop_detection,
|
no_neighbor_aspath_loop_detection,
|
||||||
no_neighbor_aspath_loop_detection_cmd,
|
no_neighbor_aspath_loop_detection_cmd,
|
||||||
@ -14146,6 +14203,86 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
|
|||||||
json_add);
|
json_add);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Paths-Limit */
|
||||||
|
if (CHECK_FLAG(p->cap, PEER_CAP_PATHS_LIMIT_RCV) ||
|
||||||
|
CHECK_FLAG(p->cap, PEER_CAP_PATHS_LIMIT_ADV)) {
|
||||||
|
json_object *json_add = NULL;
|
||||||
|
const char *print_store;
|
||||||
|
|
||||||
|
json_add = json_object_new_object();
|
||||||
|
|
||||||
|
FOREACH_AFI_SAFI (afi, safi) {
|
||||||
|
json_object *json_sub = NULL;
|
||||||
|
|
||||||
|
json_sub = json_object_new_object();
|
||||||
|
print_store = get_afi_safi_str(afi, safi,
|
||||||
|
true);
|
||||||
|
|
||||||
|
if (CHECK_FLAG(p->af_cap[afi][safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_ADV) ||
|
||||||
|
CHECK_FLAG(p->af_cap[afi][safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_RCV)) {
|
||||||
|
if (CHECK_FLAG(p->af_cap[afi][safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_ADV) &&
|
||||||
|
CHECK_FLAG(p->af_cap[afi][safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_RCV)) {
|
||||||
|
json_object_boolean_true_add(
|
||||||
|
json_sub,
|
||||||
|
"advertisedAndReceived");
|
||||||
|
json_object_int_add(
|
||||||
|
json_sub,
|
||||||
|
"advertisedPathsLimit",
|
||||||
|
p->addpath_paths_limit
|
||||||
|
[afi][safi]
|
||||||
|
.send);
|
||||||
|
json_object_int_add(
|
||||||
|
json_sub,
|
||||||
|
"receivedPathsLimit",
|
||||||
|
p->addpath_paths_limit
|
||||||
|
[afi][safi]
|
||||||
|
.receive);
|
||||||
|
} else if (CHECK_FLAG(p->af_cap[afi]
|
||||||
|
[safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_ADV)) {
|
||||||
|
json_object_boolean_true_add(
|
||||||
|
json_sub,
|
||||||
|
"advertised");
|
||||||
|
json_object_int_add(
|
||||||
|
json_sub,
|
||||||
|
"advertisedPathsLimit",
|
||||||
|
p->addpath_paths_limit
|
||||||
|
[afi][safi]
|
||||||
|
.send);
|
||||||
|
} else if (CHECK_FLAG(p->af_cap[afi]
|
||||||
|
[safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_RCV)) {
|
||||||
|
json_object_boolean_true_add(
|
||||||
|
json_sub,
|
||||||
|
"received");
|
||||||
|
json_object_int_add(
|
||||||
|
json_sub,
|
||||||
|
"receivedPathsLimit",
|
||||||
|
p->addpath_paths_limit
|
||||||
|
[afi][safi]
|
||||||
|
.receive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CHECK_FLAG(p->af_cap[afi][safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_ADV) ||
|
||||||
|
CHECK_FLAG(p->af_cap[afi][safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_RCV))
|
||||||
|
json_object_object_add(json_add,
|
||||||
|
print_store,
|
||||||
|
json_sub);
|
||||||
|
else
|
||||||
|
json_object_free(json_sub);
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object_object_add(json_cap, "pathsLimit",
|
||||||
|
json_add);
|
||||||
|
}
|
||||||
|
|
||||||
/* Dynamic */
|
/* Dynamic */
|
||||||
if (CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_RCV) ||
|
if (CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_RCV) ||
|
||||||
CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_ADV)) {
|
CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_ADV)) {
|
||||||
@ -14599,6 +14736,47 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Paths-Limit */
|
||||||
|
if (CHECK_FLAG(p->cap, PEER_CAP_PATHS_LIMIT_RCV) ||
|
||||||
|
CHECK_FLAG(p->cap, PEER_CAP_PATHS_LIMIT_ADV)) {
|
||||||
|
vty_out(vty, " Paths-Limit:\n");
|
||||||
|
|
||||||
|
FOREACH_AFI_SAFI (afi, safi) {
|
||||||
|
if (CHECK_FLAG(p->af_cap[afi][safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_ADV) ||
|
||||||
|
CHECK_FLAG(p->af_cap[afi][safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_RCV)) {
|
||||||
|
vty_out(vty, " %s: ",
|
||||||
|
get_afi_safi_str(afi,
|
||||||
|
safi,
|
||||||
|
false));
|
||||||
|
|
||||||
|
if (CHECK_FLAG(p->af_cap[afi][safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_ADV))
|
||||||
|
vty_out(vty,
|
||||||
|
"advertised (%u)",
|
||||||
|
p->addpath_paths_limit
|
||||||
|
[afi][safi]
|
||||||
|
.send);
|
||||||
|
|
||||||
|
if (CHECK_FLAG(p->af_cap[afi][safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_RCV))
|
||||||
|
vty_out(vty,
|
||||||
|
"%sreceived (%u)",
|
||||||
|
CHECK_FLAG(p->af_cap[afi]
|
||||||
|
[safi],
|
||||||
|
PEER_CAP_PATHS_LIMIT_AF_ADV)
|
||||||
|
? " and "
|
||||||
|
: "",
|
||||||
|
p->addpath_paths_limit
|
||||||
|
[afi][safi]
|
||||||
|
.receive);
|
||||||
|
|
||||||
|
vty_out(vty, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Dynamic */
|
/* Dynamic */
|
||||||
if (CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_RCV) ||
|
if (CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_RCV) ||
|
||||||
CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_ADV)) {
|
CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_ADV)) {
|
||||||
@ -18383,6 +18561,11 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
|||||||
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DISABLE_ADDPATH_RX))
|
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DISABLE_ADDPATH_RX))
|
||||||
vty_out(vty, " neighbor %s disable-addpath-rx\n", addr);
|
vty_out(vty, " neighbor %s disable-addpath-rx\n", addr);
|
||||||
|
|
||||||
|
if (CHECK_FLAG(peer->af_flags[afi][safi],
|
||||||
|
PEER_FLAG_ADDPATH_RX_PATHS_LIMIT))
|
||||||
|
vty_out(vty, " neighbor %s addpath-rx-paths-limit %u\n", addr,
|
||||||
|
peer->addpath_paths_limit[afi][safi].send);
|
||||||
|
|
||||||
/* ORF capability. */
|
/* ORF capability. */
|
||||||
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
|
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
|
||||||
|| peergroup_af_flag_check(peer, afi, safi,
|
|| peergroup_af_flag_check(peer, afi, safi,
|
||||||
@ -20544,6 +20727,26 @@ void bgp_vty_init(void)
|
|||||||
install_element(BGP_VPNV6_NODE,
|
install_element(BGP_VPNV6_NODE,
|
||||||
&no_neighbor_addpath_tx_bestpath_per_as_cmd);
|
&no_neighbor_addpath_tx_bestpath_per_as_cmd);
|
||||||
|
|
||||||
|
/* "neighbor addpath-rx-paths-limit" commands.*/
|
||||||
|
install_element(BGP_NODE, &neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_NODE, &no_neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_IPV4_NODE, &neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_IPV4_NODE, &no_neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_IPV4M_NODE, &neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_IPV4M_NODE, &no_neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_IPV4L_NODE, &neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_IPV4L_NODE, &no_neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_IPV6_NODE, &neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_IPV6_NODE, &no_neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_IPV6M_NODE, &neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_IPV6M_NODE, &no_neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_IPV6L_NODE, &neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_IPV6L_NODE, &no_neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_VPNV4_NODE, &neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_VPNV4_NODE, &no_neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_VPNV6_NODE, &neighbor_addpath_paths_limit_cmd);
|
||||||
|
install_element(BGP_VPNV6_NODE, &no_neighbor_addpath_paths_limit_cmd);
|
||||||
|
|
||||||
/* "neighbor sender-as-path-loop-detection" commands. */
|
/* "neighbor sender-as-path-loop-detection" commands. */
|
||||||
install_element(BGP_NODE, &neighbor_aspath_loop_detection_cmd);
|
install_element(BGP_NODE, &neighbor_aspath_loop_detection_cmd);
|
||||||
install_element(BGP_NODE, &no_neighbor_aspath_loop_detection_cmd);
|
install_element(BGP_NODE, &no_neighbor_aspath_loop_detection_cmd);
|
||||||
|
@ -1527,6 +1527,8 @@ struct peer *peer_new(struct bgp *bgp)
|
|||||||
PEER_FLAG_SEND_LARGE_COMMUNITY);
|
PEER_FLAG_SEND_LARGE_COMMUNITY);
|
||||||
peer->addpath_type[afi][safi] = BGP_ADDPATH_NONE;
|
peer->addpath_type[afi][safi] = BGP_ADDPATH_NONE;
|
||||||
peer->addpath_best_selected[afi][safi] = 0;
|
peer->addpath_best_selected[afi][safi] = 0;
|
||||||
|
peer->addpath_paths_limit[afi][safi].receive = 0;
|
||||||
|
peer->addpath_paths_limit[afi][safi].send = 0;
|
||||||
peer->soo[afi][safi] = NULL;
|
peer->soo[afi][safi] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1620,6 +1622,8 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
|
|||||||
peer_dst->weight[afi][safi] = peer_src->weight[afi][safi];
|
peer_dst->weight[afi][safi] = peer_src->weight[afi][safi];
|
||||||
peer_dst->addpath_type[afi][safi] =
|
peer_dst->addpath_type[afi][safi] =
|
||||||
peer_src->addpath_type[afi][safi];
|
peer_src->addpath_type[afi][safi];
|
||||||
|
peer_dst->addpath_paths_limit[afi][safi] =
|
||||||
|
peer_src->addpath_paths_limit[afi][safi];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
|
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
|
||||||
@ -4614,6 +4618,7 @@ static const struct peer_flag_action peer_af_flag_action_list[] = {
|
|||||||
{PEER_FLAG_SOO, 0, peer_change_reset},
|
{PEER_FLAG_SOO, 0, peer_change_reset},
|
||||||
{PEER_FLAG_ACCEPT_OWN, 0, peer_change_reset},
|
{PEER_FLAG_ACCEPT_OWN, 0, peer_change_reset},
|
||||||
{PEER_FLAG_SEND_EXT_COMMUNITY_RPKI, 1, peer_change_reset_out},
|
{PEER_FLAG_SEND_EXT_COMMUNITY_RPKI, 1, peer_change_reset_out},
|
||||||
|
{PEER_FLAG_ADDPATH_RX_PATHS_LIMIT, 0, peer_change_none},
|
||||||
{0, 0, 0}};
|
{0, 0, 0}};
|
||||||
|
|
||||||
/* Proper action set. */
|
/* Proper action set. */
|
||||||
|
13
bgpd/bgpd.h
13
bgpd/bgpd.h
@ -1140,6 +1140,11 @@ struct llgr_info {
|
|||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct addpath_paths_limit {
|
||||||
|
uint16_t send;
|
||||||
|
uint16_t receive;
|
||||||
|
};
|
||||||
|
|
||||||
struct peer_connection {
|
struct peer_connection {
|
||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
|
|
||||||
@ -1333,6 +1338,8 @@ struct peer {
|
|||||||
#define PEER_CAP_ROLE_RCV (1ULL << 26) /* role received */
|
#define PEER_CAP_ROLE_RCV (1ULL << 26) /* role received */
|
||||||
#define PEER_CAP_SOFT_VERSION_ADV (1ULL << 27)
|
#define PEER_CAP_SOFT_VERSION_ADV (1ULL << 27)
|
||||||
#define PEER_CAP_SOFT_VERSION_RCV (1ULL << 28)
|
#define PEER_CAP_SOFT_VERSION_RCV (1ULL << 28)
|
||||||
|
#define PEER_CAP_PATHS_LIMIT_ADV (1U << 29)
|
||||||
|
#define PEER_CAP_PATHS_LIMIT_RCV (1U << 30)
|
||||||
|
|
||||||
/* Capability flags (reset in bgp_stop) */
|
/* Capability flags (reset in bgp_stop) */
|
||||||
uint32_t af_cap[AFI_MAX][SAFI_MAX];
|
uint32_t af_cap[AFI_MAX][SAFI_MAX];
|
||||||
@ -1351,6 +1358,8 @@ struct peer {
|
|||||||
#define PEER_CAP_ENHE_AF_NEGO (1U << 14) /* Extended nexthop afi/safi negotiated */
|
#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_ADV (1U << 15)
|
||||||
#define PEER_CAP_LLGR_AF_RCV (1U << 16)
|
#define PEER_CAP_LLGR_AF_RCV (1U << 16)
|
||||||
|
#define PEER_CAP_PATHS_LIMIT_AF_ADV (1U << 17)
|
||||||
|
#define PEER_CAP_PATHS_LIMIT_AF_RCV (1U << 18)
|
||||||
|
|
||||||
/* Global configuration flags. */
|
/* Global configuration flags. */
|
||||||
/*
|
/*
|
||||||
@ -1528,6 +1537,7 @@ struct peer {
|
|||||||
#define PEER_FLAG_DISABLE_ADDPATH_RX (1ULL << 27)
|
#define PEER_FLAG_DISABLE_ADDPATH_RX (1ULL << 27)
|
||||||
#define PEER_FLAG_SOO (1ULL << 28)
|
#define PEER_FLAG_SOO (1ULL << 28)
|
||||||
#define PEER_FLAG_SEND_EXT_COMMUNITY_RPKI (1ULL << 29)
|
#define PEER_FLAG_SEND_EXT_COMMUNITY_RPKI (1ULL << 29)
|
||||||
|
#define PEER_FLAG_ADDPATH_RX_PATHS_LIMIT (1ULL << 30)
|
||||||
#define PEER_FLAG_ACCEPT_OWN (1ULL << 63)
|
#define PEER_FLAG_ACCEPT_OWN (1ULL << 63)
|
||||||
|
|
||||||
enum bgp_addpath_strat addpath_type[AFI_MAX][SAFI_MAX];
|
enum bgp_addpath_strat addpath_type[AFI_MAX][SAFI_MAX];
|
||||||
@ -1845,6 +1855,9 @@ struct peer {
|
|||||||
/* Add-Path Best selected paths number to advertise */
|
/* Add-Path Best selected paths number to advertise */
|
||||||
uint8_t addpath_best_selected[AFI_MAX][SAFI_MAX];
|
uint8_t addpath_best_selected[AFI_MAX][SAFI_MAX];
|
||||||
|
|
||||||
|
/* Add-Path Paths-Limit */
|
||||||
|
struct addpath_paths_limit addpath_paths_limit[AFI_MAX][SAFI_MAX];
|
||||||
|
|
||||||
QOBJ_FIELDS;
|
QOBJ_FIELDS;
|
||||||
};
|
};
|
||||||
DECLARE_QOBJ_TYPE(peer);
|
DECLARE_QOBJ_TYPE(peer);
|
||||||
|
Loading…
Reference in New Issue
Block a user