mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 19:10:35 +00:00
Merge pull request #15723 from opensourcerouting/feature/extended_link_bw_refactored_v1
bgpd: Implement extended link-bandwidth
This commit is contained in:
commit
f19817f71d
158
bgpd/bgp_attr.c
158
bgpd/bgp_attr.c
@ -915,12 +915,13 @@ static void attr_show_all_iterator(struct hash_bucket *bucket, struct vty *vty)
|
|||||||
"\n",
|
"\n",
|
||||||
attr->flag, attr->distance, attr->med, attr->local_pref,
|
attr->flag, attr->distance, attr->med, attr->local_pref,
|
||||||
attr->origin, attr->weight, attr->label, sid, attr->aigp_metric);
|
attr->origin, attr->weight, attr->label, sid, attr->aigp_metric);
|
||||||
vty_out(vty,
|
vty_out(vty, "\taspath: %s Community: %s Large Community: %s\n",
|
||||||
"\taspath: %s Community: %s Extended Community: %s Large Community: %s\n",
|
|
||||||
aspath_print(attr->aspath),
|
aspath_print(attr->aspath),
|
||||||
community_str(attr->community, false, false),
|
community_str(attr->community, false, false),
|
||||||
ecommunity_str(attr->ecommunity),
|
|
||||||
lcommunity_str(attr->lcommunity, false, false));
|
lcommunity_str(attr->lcommunity, false, false));
|
||||||
|
vty_out(vty, "\tExtended Community: %s Extended IPv6 Community: %s\n",
|
||||||
|
ecommunity_str(attr->ecommunity),
|
||||||
|
ecommunity_str(attr->ipv6_ecommunity));
|
||||||
}
|
}
|
||||||
|
|
||||||
void attr_show_all(struct vty *vty)
|
void attr_show_all(struct vty *vty)
|
||||||
@ -2650,10 +2651,7 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
|
|||||||
if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
|
if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
|
||||||
goto ipv6_ext_community_ignore;
|
goto ipv6_ext_community_ignore;
|
||||||
|
|
||||||
ipv6_ecomm = ecommunity_parse_ipv6(
|
ipv6_ecomm = ecommunity_parse_ipv6(stream_pnt(peer->curr), length);
|
||||||
stream_pnt(peer->curr), length,
|
|
||||||
CHECK_FLAG(peer->flags,
|
|
||||||
PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
|
|
||||||
bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
|
bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
|
||||||
|
|
||||||
/* XXX: fix ecommunity_parse to use stream API */
|
/* XXX: fix ecommunity_parse to use stream API */
|
||||||
@ -2663,6 +2661,10 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
|
|||||||
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
|
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
|
||||||
args->total);
|
args->total);
|
||||||
|
|
||||||
|
/* Extract link bandwidth, if any. */
|
||||||
|
(void)ecommunity_linkbw_present(bgp_attr_get_ipv6_ecommunity(attr),
|
||||||
|
&attr->link_bw);
|
||||||
|
|
||||||
return BGP_ATTR_PARSE_PROCEED;
|
return BGP_ATTR_PARSE_PROCEED;
|
||||||
|
|
||||||
ipv6_ext_community_ignore:
|
ipv6_ext_community_ignore:
|
||||||
@ -4354,6 +4356,69 @@ static bool bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bgp_packet_ecommunity_attribute(struct stream *s, struct peer *peer,
|
||||||
|
struct ecommunity *ecomm,
|
||||||
|
bool transparent, int attribute)
|
||||||
|
{
|
||||||
|
if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED ||
|
||||||
|
peer->sub_sort == BGP_PEER_EBGP_OAD || transparent) {
|
||||||
|
if (ecomm->size * ecomm->unit_size > 255) {
|
||||||
|
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
|
||||||
|
BGP_ATTR_FLAG_TRANS |
|
||||||
|
BGP_ATTR_FLAG_EXTLEN);
|
||||||
|
stream_putc(s, attribute);
|
||||||
|
stream_putw(s, ecomm->size * ecomm->unit_size);
|
||||||
|
} else {
|
||||||
|
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
|
||||||
|
BGP_ATTR_FLAG_TRANS);
|
||||||
|
stream_putc(s, attribute);
|
||||||
|
stream_putc(s, ecomm->size * ecomm->unit_size);
|
||||||
|
}
|
||||||
|
stream_put(s, ecomm->val, ecomm->size * ecomm->unit_size);
|
||||||
|
} else {
|
||||||
|
uint8_t *pnt;
|
||||||
|
int tbit;
|
||||||
|
int ecom_tr_size = 0;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < ecomm->size; i++) {
|
||||||
|
pnt = ecomm->val + (i * ecomm->unit_size);
|
||||||
|
tbit = *pnt;
|
||||||
|
|
||||||
|
if (CHECK_FLAG(tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ecom_tr_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ecom_tr_size) {
|
||||||
|
if (ecom_tr_size * ecomm->unit_size > 255) {
|
||||||
|
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
|
||||||
|
BGP_ATTR_FLAG_TRANS |
|
||||||
|
BGP_ATTR_FLAG_EXTLEN);
|
||||||
|
stream_putc(s, attribute);
|
||||||
|
stream_putw(s, ecom_tr_size * ecomm->unit_size);
|
||||||
|
} else {
|
||||||
|
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
|
||||||
|
BGP_ATTR_FLAG_TRANS);
|
||||||
|
stream_putc(s, attribute);
|
||||||
|
stream_putc(s, ecom_tr_size * ecomm->unit_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ecomm->size; i++) {
|
||||||
|
pnt = ecomm->val + (i * ecomm->unit_size);
|
||||||
|
tbit = *pnt;
|
||||||
|
|
||||||
|
if (CHECK_FLAG(tbit,
|
||||||
|
ECOMMUNITY_FLAG_NON_TRANSITIVE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
stream_put(s, pnt, ecomm->unit_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Make attribute packet. */
|
/* Make attribute packet. */
|
||||||
bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
|
bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
|
||||||
struct stream *s, struct attr *attr,
|
struct stream *s, struct attr *attr,
|
||||||
@ -4656,82 +4721,31 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extended Communities attribute. */
|
/* Extended IPv6/Communities attributes. */
|
||||||
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
|
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) {
|
||||||
&& (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
|
|
||||||
struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
|
|
||||||
bool transparent = CHECK_FLAG(peer->af_flags[afi][safi],
|
bool transparent = CHECK_FLAG(peer->af_flags[afi][safi],
|
||||||
PEER_FLAG_RSERVER_CLIENT) &&
|
PEER_FLAG_RSERVER_CLIENT) &&
|
||||||
from &&
|
from &&
|
||||||
CHECK_FLAG(from->af_flags[afi][safi],
|
CHECK_FLAG(from->af_flags[afi][safi],
|
||||||
PEER_FLAG_RSERVER_CLIENT);
|
PEER_FLAG_RSERVER_CLIENT);
|
||||||
|
|
||||||
if (peer->sort == BGP_PEER_IBGP ||
|
if (CHECK_FLAG(attr->flag,
|
||||||
peer->sort == BGP_PEER_CONFED || transparent) {
|
ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
|
||||||
if (ecomm->size * 8 > 255) {
|
struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
|
||||||
stream_putc(s,
|
|
||||||
BGP_ATTR_FLAG_OPTIONAL
|
|
||||||
| BGP_ATTR_FLAG_TRANS
|
|
||||||
| BGP_ATTR_FLAG_EXTLEN);
|
|
||||||
stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
|
|
||||||
stream_putw(s, ecomm->size * 8);
|
|
||||||
} else {
|
|
||||||
stream_putc(s,
|
|
||||||
BGP_ATTR_FLAG_OPTIONAL
|
|
||||||
| BGP_ATTR_FLAG_TRANS);
|
|
||||||
stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
|
|
||||||
stream_putc(s, ecomm->size * 8);
|
|
||||||
}
|
|
||||||
stream_put(s, ecomm->val, ecomm->size * 8);
|
|
||||||
} else {
|
|
||||||
uint8_t *pnt;
|
|
||||||
int tbit;
|
|
||||||
int ecom_tr_size = 0;
|
|
||||||
uint32_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < ecomm->size; i++) {
|
bgp_packet_ecommunity_attribute(s, peer, ecomm,
|
||||||
pnt = ecomm->val + (i * 8);
|
transparent,
|
||||||
tbit = *pnt;
|
|
||||||
|
|
||||||
if (CHECK_FLAG(tbit,
|
|
||||||
ECOMMUNITY_FLAG_NON_TRANSITIVE))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ecom_tr_size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ecom_tr_size) {
|
|
||||||
if (ecom_tr_size * 8 > 255) {
|
|
||||||
stream_putc(
|
|
||||||
s,
|
|
||||||
BGP_ATTR_FLAG_OPTIONAL
|
|
||||||
| BGP_ATTR_FLAG_TRANS
|
|
||||||
| BGP_ATTR_FLAG_EXTLEN);
|
|
||||||
stream_putc(s,
|
|
||||||
BGP_ATTR_EXT_COMMUNITIES);
|
BGP_ATTR_EXT_COMMUNITIES);
|
||||||
stream_putw(s, ecom_tr_size * 8);
|
|
||||||
} else {
|
|
||||||
stream_putc(
|
|
||||||
s,
|
|
||||||
BGP_ATTR_FLAG_OPTIONAL
|
|
||||||
| BGP_ATTR_FLAG_TRANS);
|
|
||||||
stream_putc(s,
|
|
||||||
BGP_ATTR_EXT_COMMUNITIES);
|
|
||||||
stream_putc(s, ecom_tr_size * 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ecomm->size; i++) {
|
if (CHECK_FLAG(attr->flag,
|
||||||
pnt = ecomm->val + (i * 8);
|
ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES))) {
|
||||||
tbit = *pnt;
|
struct ecommunity *ecomm =
|
||||||
|
bgp_attr_get_ipv6_ecommunity(attr);
|
||||||
|
|
||||||
if (CHECK_FLAG(
|
bgp_packet_ecommunity_attribute(s, peer, ecomm,
|
||||||
tbit,
|
transparent,
|
||||||
ECOMMUNITY_FLAG_NON_TRANSITIVE))
|
BGP_ATTR_IPV6_EXT_COMMUNITIES);
|
||||||
continue;
|
|
||||||
|
|
||||||
stream_put(s, pnt, 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +301,7 @@ struct attr {
|
|||||||
uint32_t rmap_table_id;
|
uint32_t rmap_table_id;
|
||||||
|
|
||||||
/* Link bandwidth value, if any. */
|
/* Link bandwidth value, if any. */
|
||||||
uint32_t link_bw;
|
uint64_t link_bw;
|
||||||
|
|
||||||
/* EVPN ES */
|
/* EVPN ES */
|
||||||
esi_t esi;
|
esi_t esi;
|
||||||
|
@ -237,11 +237,10 @@ struct ecommunity *ecommunity_parse(uint8_t *pnt, unsigned short length,
|
|||||||
disable_ieee_floating);
|
disable_ieee_floating);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, unsigned short length,
|
struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, unsigned short length)
|
||||||
bool disable_ieee_floating)
|
|
||||||
{
|
{
|
||||||
return ecommunity_parse_internal(pnt, length, IPV6_ECOMMUNITY_SIZE,
|
return ecommunity_parse_internal(pnt, length, IPV6_ECOMMUNITY_SIZE,
|
||||||
disable_ieee_floating);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Duplicate the Extended Communities Attribute structure. */
|
/* Duplicate the Extended Communities Attribute structure. */
|
||||||
@ -1026,10 +1025,6 @@ static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt,
|
|||||||
uint32_t bw_tmp, bw;
|
uint32_t bw_tmp, bw;
|
||||||
char bps_buf[20] = {0};
|
char bps_buf[20] = {0};
|
||||||
|
|
||||||
#define ONE_GBPS_BYTES (1000 * 1000 * 1000 / 8)
|
|
||||||
#define ONE_MBPS_BYTES (1000 * 1000 / 8)
|
|
||||||
#define ONE_KBPS_BYTES (1000 / 8)
|
|
||||||
|
|
||||||
as = (*pnt++ << 8);
|
as = (*pnt++ << 8);
|
||||||
as |= (*pnt++);
|
as |= (*pnt++);
|
||||||
(void)ptr_get_be32(pnt, &bw_tmp);
|
(void)ptr_get_be32(pnt, &bw_tmp);
|
||||||
@ -1053,6 +1048,33 @@ static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ipv6_ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
as_t as;
|
||||||
|
uint64_t bw;
|
||||||
|
char bps_buf[20] = { 0 };
|
||||||
|
|
||||||
|
pnt += 2; /* Reserved */
|
||||||
|
pnt = ptr_get_be64(pnt, &bw);
|
||||||
|
(void)ptr_get_be32(pnt, &as);
|
||||||
|
|
||||||
|
if (bw >= ONE_GBPS_BYTES)
|
||||||
|
snprintf(bps_buf, sizeof(bps_buf), "%.3f Gbps",
|
||||||
|
(float)(bw / ONE_GBPS_BYTES));
|
||||||
|
else if (bw >= ONE_MBPS_BYTES)
|
||||||
|
snprintf(bps_buf, sizeof(bps_buf), "%.3f Mbps",
|
||||||
|
(float)(bw / ONE_MBPS_BYTES));
|
||||||
|
else if (bw >= ONE_KBPS_BYTES)
|
||||||
|
snprintf(bps_buf, sizeof(bps_buf), "%.3f Kbps",
|
||||||
|
(float)(bw / ONE_KBPS_BYTES));
|
||||||
|
else
|
||||||
|
snprintfrr(bps_buf, sizeof(bps_buf), "%" PRIu64 " bps", bw * 8);
|
||||||
|
|
||||||
|
len = snprintfrr(buf, bufsz, "LB:%u:%" PRIu64 " (%s)", as, bw, bps_buf);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
bool ecommunity_has_route_target(struct ecommunity *ecom)
|
bool ecommunity_has_route_target(struct ecommunity *ecom)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
@ -1153,6 +1175,12 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
|
|||||||
ecommunity_lb_str(
|
ecommunity_lb_str(
|
||||||
encbuf, sizeof(encbuf), pnt,
|
encbuf, sizeof(encbuf), pnt,
|
||||||
ecom->disable_ieee_floating);
|
ecom->disable_ieee_floating);
|
||||||
|
} else if (sub_type ==
|
||||||
|
ECOMMUNITY_EXTENDED_LINK_BANDWIDTH &&
|
||||||
|
type == ECOMMUNITY_ENCODE_AS4) {
|
||||||
|
ipv6_ecommunity_lb_str(encbuf,
|
||||||
|
sizeof(encbuf),
|
||||||
|
pnt);
|
||||||
} else if (sub_type == ECOMMUNITY_NODE_TARGET &&
|
} else if (sub_type == ECOMMUNITY_NODE_TARGET &&
|
||||||
type == ECOMMUNITY_ENCODE_IP) {
|
type == ECOMMUNITY_ENCODE_IP) {
|
||||||
ecommunity_node_target_str(
|
ecommunity_node_target_str(
|
||||||
@ -1370,6 +1398,13 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
|
|||||||
ecom->disable_ieee_floating);
|
ecom->disable_ieee_floating);
|
||||||
else
|
else
|
||||||
unk_ecom = 1;
|
unk_ecom = 1;
|
||||||
|
} else if (type == ECOMMUNITY_ENCODE_AS_NON_TRANS) {
|
||||||
|
sub_type = *pnt++;
|
||||||
|
if (sub_type == ECOMMUNITY_EXTENDED_LINK_BANDWIDTH)
|
||||||
|
ipv6_ecommunity_lb_str(encbuf, sizeof(encbuf),
|
||||||
|
pnt);
|
||||||
|
else
|
||||||
|
unk_ecom = 1;
|
||||||
} else if (type == ECOMMUNITY_ENCODE_IP_NON_TRANS) {
|
} else if (type == ECOMMUNITY_ENCODE_IP_NON_TRANS) {
|
||||||
sub_type = *pnt++;
|
sub_type = *pnt++;
|
||||||
if (sub_type == ECOMMUNITY_NODE_TARGET)
|
if (sub_type == ECOMMUNITY_NODE_TARGET)
|
||||||
@ -1805,7 +1840,7 @@ ecommunity_add_origin_validation_state(enum rpki_states rpki_state,
|
|||||||
* return the BGP link bandwidth extended community, if present;
|
* return the BGP link bandwidth extended community, if present;
|
||||||
* the actual bandwidth is returned via param
|
* the actual bandwidth is returned via param
|
||||||
*/
|
*/
|
||||||
const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw)
|
const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint64_t *bw)
|
||||||
{
|
{
|
||||||
const uint8_t *eval;
|
const uint8_t *eval;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
@ -1819,23 +1854,36 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw)
|
|||||||
for (i = 0; i < ecom->size; i++) {
|
for (i = 0; i < ecom->size; i++) {
|
||||||
const uint8_t *pnt;
|
const uint8_t *pnt;
|
||||||
uint8_t type, sub_type;
|
uint8_t type, sub_type;
|
||||||
uint32_t bwval;
|
|
||||||
|
|
||||||
eval = pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
|
eval = pnt = (ecom->val + (i * ecom->unit_size));
|
||||||
type = *pnt++;
|
type = *pnt++;
|
||||||
sub_type = *pnt++;
|
sub_type = *pnt++;
|
||||||
|
|
||||||
if ((type == ECOMMUNITY_ENCODE_AS ||
|
if ((type == ECOMMUNITY_ENCODE_AS ||
|
||||||
type == ECOMMUNITY_ENCODE_AS_NON_TRANS) &&
|
type == ECOMMUNITY_ENCODE_AS_NON_TRANS) &&
|
||||||
sub_type == ECOMMUNITY_LINK_BANDWIDTH) {
|
sub_type == ECOMMUNITY_LINK_BANDWIDTH) {
|
||||||
|
uint32_t bwval;
|
||||||
|
|
||||||
pnt += 2; /* bandwidth is encoded as AS:val */
|
pnt += 2; /* bandwidth is encoded as AS:val */
|
||||||
pnt = ptr_get_be32(pnt, &bwval);
|
pnt = ptr_get_be32(pnt, &bwval);
|
||||||
(void)pnt; /* consume value */
|
(void)pnt; /* consume value */
|
||||||
if (bw)
|
if (bw)
|
||||||
*bw = ecom->disable_ieee_floating
|
*bw = (uint64_t)(ecom->disable_ieee_floating
|
||||||
? bwval
|
? bwval
|
||||||
: ieee_float_uint32_to_uint32(
|
: ieee_float_uint32_to_uint32(
|
||||||
bwval);
|
bwval));
|
||||||
|
return eval;
|
||||||
|
} else if (type == ECOMMUNITY_ENCODE_AS4 &&
|
||||||
|
sub_type == ECOMMUNITY_EXTENDED_LINK_BANDWIDTH) {
|
||||||
|
uint64_t bwval;
|
||||||
|
|
||||||
|
pnt += 2; /* Reserved */
|
||||||
|
pnt = ptr_get_be64(pnt, &bwval);
|
||||||
|
(void)pnt;
|
||||||
|
|
||||||
|
if (bw)
|
||||||
|
*bw = bwval;
|
||||||
|
|
||||||
return eval;
|
return eval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1846,13 +1894,13 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw)
|
|||||||
|
|
||||||
struct ecommunity *ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom,
|
struct ecommunity *ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom,
|
||||||
uint64_t cum_bw,
|
uint64_t cum_bw,
|
||||||
bool disable_ieee_floating)
|
bool disable_ieee_floating,
|
||||||
|
bool extended)
|
||||||
{
|
{
|
||||||
struct ecommunity *new;
|
struct ecommunity *new;
|
||||||
struct ecommunity_val lb_eval;
|
|
||||||
const uint8_t *eval;
|
const uint8_t *eval;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint32_t cur_bw;
|
uint64_t cur_bw;
|
||||||
|
|
||||||
/* Nothing to replace if link-bandwidth doesn't exist or
|
/* Nothing to replace if link-bandwidth doesn't exist or
|
||||||
* is non-transitive - just return existing extcommunity.
|
* is non-transitive - just return existing extcommunity.
|
||||||
@ -1876,10 +1924,21 @@ struct ecommunity *ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom,
|
|||||||
*/
|
*/
|
||||||
if (cum_bw > 0xFFFFFFFF)
|
if (cum_bw > 0xFFFFFFFF)
|
||||||
cum_bw = 0xFFFFFFFF;
|
cum_bw = 0xFFFFFFFF;
|
||||||
encode_lb_extcomm(as > BGP_AS_MAX ? BGP_AS_TRANS : as, cum_bw, false,
|
|
||||||
&lb_eval, disable_ieee_floating);
|
if (extended) {
|
||||||
|
struct ecommunity_val_ipv6 lb_eval;
|
||||||
|
|
||||||
|
encode_lb_extended_extcomm(as, cum_bw, false, &lb_eval);
|
||||||
|
new = ecommunity_dup(ecom);
|
||||||
|
ecommunity_add_val_ipv6(new, &lb_eval, true, true);
|
||||||
|
} else {
|
||||||
|
struct ecommunity_val lb_eval;
|
||||||
|
|
||||||
|
encode_lb_extcomm(as > BGP_AS_MAX ? BGP_AS_TRANS : as, cum_bw,
|
||||||
|
false, &lb_eval, disable_ieee_floating);
|
||||||
new = ecommunity_dup(ecom);
|
new = ecommunity_dup(ecom);
|
||||||
ecommunity_add_val(new, &lb_eval, true, true);
|
ecommunity_add_val(new, &lb_eval, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,10 @@
|
|||||||
#include "bgpd/bgp_rpki.h"
|
#include "bgpd/bgp_rpki.h"
|
||||||
#include "bgpd/bgpd.h"
|
#include "bgpd/bgpd.h"
|
||||||
|
|
||||||
|
#define ONE_GBPS_BYTES (1000 * 1000 * 1000 / 8)
|
||||||
|
#define ONE_MBPS_BYTES (1000 * 1000 / 8)
|
||||||
|
#define ONE_KBPS_BYTES (1000 / 8)
|
||||||
|
|
||||||
/* Refer to rfc7153 for the IANA registry definitions. These are
|
/* Refer to rfc7153 for the IANA registry definitions. These are
|
||||||
* updated by other standards like rfc7674.
|
* updated by other standards like rfc7674.
|
||||||
*/
|
*/
|
||||||
@ -55,6 +59,12 @@
|
|||||||
/* RFC 8956 */
|
/* RFC 8956 */
|
||||||
#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0d
|
#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0d
|
||||||
|
|
||||||
|
/* https://datatracker.ietf.org/doc/html/draft-li-idr-link-bandwidth-ext-01
|
||||||
|
* Sub-type is allocated by IANA, just the draft is not yet updated with the
|
||||||
|
* new value.
|
||||||
|
*/
|
||||||
|
#define ECOMMUNITY_EXTENDED_LINK_BANDWIDTH 0x0006
|
||||||
|
|
||||||
/* Low-order octet of the Extended Communities type field for EVPN types */
|
/* Low-order octet of the Extended Communities type field for EVPN types */
|
||||||
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00
|
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00
|
||||||
#define ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL 0x01
|
#define ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL 0x01
|
||||||
@ -224,12 +234,13 @@ static uint32_t uint32_to_ieee_float_uint32(uint32_t u)
|
|||||||
* Encode BGP Link Bandwidth extended community
|
* Encode BGP Link Bandwidth extended community
|
||||||
* bandwidth (bw) is in bytes-per-sec
|
* bandwidth (bw) is in bytes-per-sec
|
||||||
*/
|
*/
|
||||||
static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
|
static inline void encode_lb_extcomm(as_t as, uint64_t bw, bool non_trans,
|
||||||
struct ecommunity_val *eval,
|
struct ecommunity_val *eval,
|
||||||
bool disable_ieee_floating)
|
bool disable_ieee_floating)
|
||||||
{
|
{
|
||||||
uint32_t bandwidth =
|
uint64_t bandwidth = disable_ieee_floating
|
||||||
disable_ieee_floating ? bw : uint32_to_ieee_float_uint32(bw);
|
? bw
|
||||||
|
: uint32_to_ieee_float_uint32(bw);
|
||||||
|
|
||||||
memset(eval, 0, sizeof(*eval));
|
memset(eval, 0, sizeof(*eval));
|
||||||
eval->val[0] = ECOMMUNITY_ENCODE_AS;
|
eval->val[0] = ECOMMUNITY_ENCODE_AS;
|
||||||
@ -244,6 +255,33 @@ static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
|
|||||||
eval->val[7] = bandwidth & 0xff;
|
eval->val[7] = bandwidth & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encode BGP Link Bandwidth inside IPv6 Extended Community,
|
||||||
|
* bandwidth is in bytes per second.
|
||||||
|
*/
|
||||||
|
static inline void encode_lb_extended_extcomm(as_t as, uint64_t bandwidth,
|
||||||
|
bool non_trans,
|
||||||
|
struct ecommunity_val_ipv6 *eval)
|
||||||
|
{
|
||||||
|
memset(eval, 0, sizeof(*eval));
|
||||||
|
eval->val[0] = ECOMMUNITY_ENCODE_AS4;
|
||||||
|
if (non_trans)
|
||||||
|
eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE;
|
||||||
|
eval->val[1] = ECOMMUNITY_EXTENDED_LINK_BANDWIDTH;
|
||||||
|
eval->val[4] = (bandwidth >> 56) & 0xff;
|
||||||
|
eval->val[5] = (bandwidth >> 48) & 0xff;
|
||||||
|
eval->val[6] = (bandwidth >> 40) & 0xff;
|
||||||
|
eval->val[7] = (bandwidth >> 32) & 0xff;
|
||||||
|
eval->val[8] = (bandwidth >> 24) & 0xff;
|
||||||
|
eval->val[9] = (bandwidth >> 16) & 0xff;
|
||||||
|
eval->val[10] = (bandwidth >> 8) & 0xff;
|
||||||
|
eval->val[11] = bandwidth & 0xff;
|
||||||
|
eval->val[12] = (as >> 24) & 0xff;
|
||||||
|
eval->val[13] = (as >> 16) & 0xff;
|
||||||
|
eval->val[14] = (as >> 8) & 0xff;
|
||||||
|
eval->val[15] = as & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void encode_origin_validation_state(enum rpki_states state,
|
static inline void encode_origin_validation_state(enum rpki_states state,
|
||||||
struct ecommunity_val *eval)
|
struct ecommunity_val *eval)
|
||||||
{
|
{
|
||||||
@ -325,8 +363,7 @@ extern void ecommunity_free(struct ecommunity **);
|
|||||||
extern struct ecommunity *ecommunity_parse(uint8_t *, unsigned short,
|
extern struct ecommunity *ecommunity_parse(uint8_t *, unsigned short,
|
||||||
bool disable_ieee_floating);
|
bool disable_ieee_floating);
|
||||||
extern struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt,
|
extern struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt,
|
||||||
unsigned short length,
|
unsigned short length);
|
||||||
bool disable_ieee_floating);
|
|
||||||
extern struct ecommunity *ecommunity_dup(struct ecommunity *);
|
extern struct ecommunity *ecommunity_dup(struct ecommunity *);
|
||||||
extern struct ecommunity *ecommunity_merge(struct ecommunity *,
|
extern struct ecommunity *ecommunity_merge(struct ecommunity *,
|
||||||
struct ecommunity *);
|
struct ecommunity *);
|
||||||
@ -385,11 +422,10 @@ extern void bgp_remove_ecomm_from_aggregate_hash(
|
|||||||
struct ecommunity *ecommunity);
|
struct ecommunity *ecommunity);
|
||||||
extern void bgp_aggr_ecommunity_remove(void *arg);
|
extern void bgp_aggr_ecommunity_remove(void *arg);
|
||||||
extern const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom,
|
extern const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom,
|
||||||
uint32_t *bw);
|
uint64_t *bw);
|
||||||
extern struct ecommunity *ecommunity_replace_linkbw(as_t as,
|
extern struct ecommunity *
|
||||||
struct ecommunity *ecom,
|
ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom, uint64_t cum_bw,
|
||||||
uint64_t cum_bw,
|
bool disable_ieee_floating, bool extended);
|
||||||
bool disable_ieee_floating);
|
|
||||||
|
|
||||||
extern bool soo_in_ecom(struct ecommunity *ecom, struct ecommunity *soo);
|
extern bool soo_in_ecom(struct ecommunity *ecom, struct ecommunity *soo);
|
||||||
|
|
||||||
|
@ -521,7 +521,7 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
|
|||||||
struct bgp_maxpaths_cfg *mpath_cfg)
|
struct bgp_maxpaths_cfg *mpath_cfg)
|
||||||
{
|
{
|
||||||
uint16_t maxpaths, mpath_count, old_mpath_count;
|
uint16_t maxpaths, mpath_count, old_mpath_count;
|
||||||
uint32_t bwval;
|
uint64_t bwval;
|
||||||
uint64_t cum_bw, old_cum_bw;
|
uint64_t cum_bw, old_cum_bw;
|
||||||
struct listnode *mp_node, *mp_next_node;
|
struct listnode *mp_node, *mp_next_node;
|
||||||
struct bgp_path_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath;
|
struct bgp_path_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath;
|
||||||
@ -613,8 +613,11 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
|
|||||||
cur_mpath);
|
cur_mpath);
|
||||||
prev_mpath = cur_mpath;
|
prev_mpath = cur_mpath;
|
||||||
mpath_count++;
|
mpath_count++;
|
||||||
if (ecommunity_linkbw_present(
|
if (ecommunity_linkbw_present(bgp_attr_get_ecommunity(
|
||||||
bgp_attr_get_ecommunity(
|
cur_mpath->attr),
|
||||||
|
&bwval) ||
|
||||||
|
ecommunity_linkbw_present(
|
||||||
|
bgp_attr_get_ipv6_ecommunity(
|
||||||
cur_mpath->attr),
|
cur_mpath->attr),
|
||||||
&bwval))
|
&bwval))
|
||||||
cum_bw += bwval;
|
cum_bw += bwval;
|
||||||
@ -700,8 +703,11 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
|
|||||||
prev_mpath = new_mpath;
|
prev_mpath = new_mpath;
|
||||||
mpath_changed = 1;
|
mpath_changed = 1;
|
||||||
mpath_count++;
|
mpath_count++;
|
||||||
if (ecommunity_linkbw_present(
|
if (ecommunity_linkbw_present(bgp_attr_get_ecommunity(
|
||||||
bgp_attr_get_ecommunity(
|
new_mpath->attr),
|
||||||
|
&bwval) ||
|
||||||
|
ecommunity_linkbw_present(
|
||||||
|
bgp_attr_get_ipv6_ecommunity(
|
||||||
new_mpath->attr),
|
new_mpath->attr),
|
||||||
&bwval))
|
&bwval))
|
||||||
cum_bw += bwval;
|
cum_bw += bwval;
|
||||||
@ -724,8 +730,12 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
|
|||||||
if (new_best) {
|
if (new_best) {
|
||||||
bgp_path_info_mpath_count_set(new_best, mpath_count - 1);
|
bgp_path_info_mpath_count_set(new_best, mpath_count - 1);
|
||||||
if (mpath_count <= 1 ||
|
if (mpath_count <= 1 ||
|
||||||
!ecommunity_linkbw_present(
|
(!ecommunity_linkbw_present(bgp_attr_get_ecommunity(
|
||||||
bgp_attr_get_ecommunity(new_best->attr), &bwval))
|
new_best->attr),
|
||||||
|
&bwval) &&
|
||||||
|
!ecommunity_linkbw_present(bgp_attr_get_ipv6_ecommunity(
|
||||||
|
new_best->attr),
|
||||||
|
&bwval)))
|
||||||
all_paths_lb = false;
|
all_paths_lb = false;
|
||||||
else
|
else
|
||||||
cum_bw += bwval;
|
cum_bw += bwval;
|
||||||
|
@ -2771,17 +2771,26 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
|
|||||||
* the most sense. However, don't modify if the link-bandwidth has
|
* the most sense. However, don't modify if the link-bandwidth has
|
||||||
* been explicitly set by user policy.
|
* been explicitly set by user policy.
|
||||||
*/
|
*/
|
||||||
if (nh_reset &&
|
if (nh_reset && bgp_path_info_mpath_chkwtd(bgp, pi) &&
|
||||||
bgp_path_info_mpath_chkwtd(bgp, pi) &&
|
|
||||||
(cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
|
(cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
|
||||||
!CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
|
!CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET)) {
|
||||||
|
if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_LINK_BANDWIDTH))
|
||||||
|
bgp_attr_set_ipv6_ecommunity(
|
||||||
|
attr,
|
||||||
|
ecommunity_replace_linkbw(bgp->as,
|
||||||
|
bgp_attr_get_ipv6_ecommunity(
|
||||||
|
attr),
|
||||||
|
cum_bw, false, true));
|
||||||
|
else
|
||||||
bgp_attr_set_ecommunity(
|
bgp_attr_set_ecommunity(
|
||||||
attr,
|
attr,
|
||||||
ecommunity_replace_linkbw(
|
ecommunity_replace_linkbw(
|
||||||
bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
|
bgp->as, bgp_attr_get_ecommunity(attr),
|
||||||
CHECK_FLAG(
|
cum_bw,
|
||||||
peer->flags,
|
CHECK_FLAG(peer->flags,
|
||||||
PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
|
PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE),
|
||||||
|
false));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -10457,6 +10466,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
|
|||||||
json_object *json_cluster_list = NULL;
|
json_object *json_cluster_list = NULL;
|
||||||
json_object *json_cluster_list_list = NULL;
|
json_object *json_cluster_list_list = NULL;
|
||||||
json_object *json_ext_community = NULL;
|
json_object *json_ext_community = NULL;
|
||||||
|
json_object *json_ext_ipv6_community = NULL;
|
||||||
json_object *json_last_update = NULL;
|
json_object *json_last_update = NULL;
|
||||||
json_object *json_pmsi = NULL;
|
json_object *json_pmsi = NULL;
|
||||||
json_object *json_nexthop_global = NULL;
|
json_object *json_nexthop_global = NULL;
|
||||||
@ -11165,6 +11175,21 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES)) {
|
||||||
|
if (json_paths) {
|
||||||
|
json_ext_ipv6_community = json_object_new_object();
|
||||||
|
json_object_string_add(json_ext_ipv6_community, "string",
|
||||||
|
bgp_attr_get_ipv6_ecommunity(attr)
|
||||||
|
->str);
|
||||||
|
json_object_object_add(json_path,
|
||||||
|
"extendedIpv6Community",
|
||||||
|
json_ext_ipv6_community);
|
||||||
|
} else {
|
||||||
|
vty_out(vty, " Extended IPv6 Community: %s\n",
|
||||||
|
bgp_attr_get_ipv6_ecommunity(attr)->str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Line 6 display Large community */
|
/* Line 6 display Large community */
|
||||||
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
|
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
|
||||||
if (json_paths) {
|
if (json_paths) {
|
||||||
|
@ -3196,7 +3196,7 @@ struct rmap_ecomm_lb_set {
|
|||||||
#define RMAP_ECOMM_LB_SET_CUMUL 2
|
#define RMAP_ECOMM_LB_SET_CUMUL 2
|
||||||
#define RMAP_ECOMM_LB_SET_NUM_MPATH 3
|
#define RMAP_ECOMM_LB_SET_NUM_MPATH 3
|
||||||
bool non_trans;
|
bool non_trans;
|
||||||
uint32_t bw;
|
uint64_t bw;
|
||||||
};
|
};
|
||||||
|
|
||||||
static enum route_map_cmd_result_t
|
static enum route_map_cmd_result_t
|
||||||
@ -3206,8 +3206,7 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
|
|||||||
struct bgp_path_info *path;
|
struct bgp_path_info *path;
|
||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
struct ecommunity ecom_lb = {0};
|
struct ecommunity ecom_lb = {0};
|
||||||
struct ecommunity_val lb_eval;
|
uint64_t bw_bytes = 0;
|
||||||
uint32_t bw_bytes = 0;
|
|
||||||
uint16_t mpath_count = 0;
|
uint16_t mpath_count = 0;
|
||||||
struct ecommunity *new_ecom;
|
struct ecommunity *new_ecom;
|
||||||
struct ecommunity *old_ecom;
|
struct ecommunity *old_ecom;
|
||||||
@ -3221,13 +3220,13 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
|
|||||||
/* Build link bandwidth extended community */
|
/* Build link bandwidth extended community */
|
||||||
as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as;
|
as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as;
|
||||||
if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) {
|
if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) {
|
||||||
bw_bytes = ((uint64_t)rels->bw * 1000 * 1000) / 8;
|
bw_bytes = (rels->bw * 1000 * 1000) / 8;
|
||||||
} else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) {
|
} else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) {
|
||||||
/* process this only for the best path. */
|
/* process this only for the best path. */
|
||||||
if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
|
if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
|
||||||
return RMAP_OKAY;
|
return RMAP_OKAY;
|
||||||
|
|
||||||
bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path);
|
bw_bytes = bgp_path_info_mpath_cumbw(path);
|
||||||
if (!bw_bytes)
|
if (!bw_bytes)
|
||||||
return RMAP_OKAY;
|
return RMAP_OKAY;
|
||||||
|
|
||||||
@ -3237,16 +3236,38 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
|
|||||||
if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
|
if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
|
||||||
return RMAP_OKAY;
|
return RMAP_OKAY;
|
||||||
|
|
||||||
bw_bytes = ((uint64_t)peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
|
bw_bytes = (peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
|
||||||
mpath_count = bgp_path_info_mpath_count(path) + 1;
|
mpath_count = bgp_path_info_mpath_count(path) + 1;
|
||||||
bw_bytes *= mpath_count;
|
bw_bytes *= mpath_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_LINK_BANDWIDTH)) {
|
||||||
|
struct ecommunity_val_ipv6 lb_eval;
|
||||||
|
|
||||||
|
encode_lb_extended_extcomm(as, bw_bytes, rels->non_trans,
|
||||||
|
&lb_eval);
|
||||||
|
|
||||||
|
old_ecom = bgp_attr_get_ipv6_ecommunity(path->attr);
|
||||||
|
if (old_ecom) {
|
||||||
|
new_ecom = ecommunity_dup(old_ecom);
|
||||||
|
ecommunity_add_val_ipv6(new_ecom, &lb_eval, true, true);
|
||||||
|
if (!old_ecom->refcnt)
|
||||||
|
ecommunity_free(&old_ecom);
|
||||||
|
} else {
|
||||||
|
ecom_lb.size = 1;
|
||||||
|
ecom_lb.unit_size = IPV6_ECOMMUNITY_SIZE;
|
||||||
|
ecom_lb.val = (uint8_t *)lb_eval.val;
|
||||||
|
new_ecom = ecommunity_dup(&ecom_lb);
|
||||||
|
}
|
||||||
|
|
||||||
|
bgp_attr_set_ipv6_ecommunity(path->attr, new_ecom);
|
||||||
|
} else {
|
||||||
|
struct ecommunity_val lb_eval;
|
||||||
|
|
||||||
encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval,
|
encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval,
|
||||||
CHECK_FLAG(peer->flags,
|
CHECK_FLAG(peer->flags,
|
||||||
PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
|
PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
|
||||||
|
|
||||||
/* add to route or merge with existing */
|
|
||||||
old_ecom = bgp_attr_get_ecommunity(path->attr);
|
old_ecom = bgp_attr_get_ecommunity(path->attr);
|
||||||
if (old_ecom) {
|
if (old_ecom) {
|
||||||
new_ecom = ecommunity_dup(old_ecom);
|
new_ecom = ecommunity_dup(old_ecom);
|
||||||
@ -3260,8 +3281,8 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
|
|||||||
new_ecom = ecommunity_dup(&ecom_lb);
|
new_ecom = ecommunity_dup(&ecom_lb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* new_ecom will be intern()'d or attr_flush()'d in call stack */
|
|
||||||
bgp_attr_set_ecommunity(path->attr, new_ecom);
|
bgp_attr_set_ecommunity(path->attr, new_ecom);
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark that route-map has set link bandwidth; used in attribute
|
/* Mark that route-map has set link bandwidth; used in attribute
|
||||||
* setting decisions.
|
* setting decisions.
|
||||||
@ -3275,7 +3296,7 @@ static void *route_set_ecommunity_lb_compile(const char *arg)
|
|||||||
{
|
{
|
||||||
struct rmap_ecomm_lb_set *rels;
|
struct rmap_ecomm_lb_set *rels;
|
||||||
uint8_t lb_type;
|
uint8_t lb_type;
|
||||||
uint32_t bw = 0;
|
uint64_t bw = 0;
|
||||||
char bw_str[40] = {0};
|
char bw_str[40] = {0};
|
||||||
char *p, *str;
|
char *p, *str;
|
||||||
bool non_trans = false;
|
bool non_trans = false;
|
||||||
@ -6875,7 +6896,7 @@ DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd,
|
|||||||
|
|
||||||
DEFUN_YANG (set_ecommunity_lb,
|
DEFUN_YANG (set_ecommunity_lb,
|
||||||
set_ecommunity_lb_cmd,
|
set_ecommunity_lb_cmd,
|
||||||
"set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
|
"set extcommunity bandwidth <(1-4294967295)|cumulative|num-multipaths> [non-transitive]",
|
||||||
SET_STR
|
SET_STR
|
||||||
"BGP extended community attribute\n"
|
"BGP extended community attribute\n"
|
||||||
"Link bandwidth extended community\n"
|
"Link bandwidth extended community\n"
|
||||||
@ -6929,7 +6950,7 @@ DEFUN_YANG (set_ecommunity_lb,
|
|||||||
|
|
||||||
DEFUN_YANG (no_set_ecommunity_lb,
|
DEFUN_YANG (no_set_ecommunity_lb,
|
||||||
no_set_ecommunity_lb_cmd,
|
no_set_ecommunity_lb_cmd,
|
||||||
"no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
|
"no set extcommunity bandwidth <(1-4294967295)|cumulative|num-multipaths> [non-transitive]",
|
||||||
NO_STR
|
NO_STR
|
||||||
SET_STR
|
SET_STR
|
||||||
"BGP extended community attribute\n"
|
"BGP extended community attribute\n"
|
||||||
|
@ -2937,7 +2937,7 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish(
|
|||||||
struct routemap_hook_context *rhc;
|
struct routemap_hook_context *rhc;
|
||||||
enum ecommunity_lb_type lb_type;
|
enum ecommunity_lb_type lb_type;
|
||||||
char str[VTY_BUFSIZ];
|
char str[VTY_BUFSIZ];
|
||||||
uint16_t bandwidth;
|
uint32_t bandwidth;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Add configuration. */
|
/* Add configuration. */
|
||||||
@ -2951,8 +2951,8 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish(
|
|||||||
|
|
||||||
switch (lb_type) {
|
switch (lb_type) {
|
||||||
case EXPLICIT_BANDWIDTH:
|
case EXPLICIT_BANDWIDTH:
|
||||||
bandwidth = yang_dnode_get_uint16(args->dnode, "bandwidth");
|
bandwidth = yang_dnode_get_uint32(args->dnode, "bandwidth");
|
||||||
snprintf(str, sizeof(str), "%d", bandwidth);
|
snprintf(str, sizeof(str), "%u", bandwidth);
|
||||||
break;
|
break;
|
||||||
case CUMULATIVE_BANDWIDTH:
|
case CUMULATIVE_BANDWIDTH:
|
||||||
snprintf(str, sizeof(str), "%s", "cumulative");
|
snprintf(str, sizeof(str), "%s", "cumulative");
|
||||||
|
@ -7115,6 +7115,26 @@ DEFUN (no_neighbor_disable_connected_check,
|
|||||||
PEER_FLAG_DISABLE_CONNECTED_CHECK);
|
PEER_FLAG_DISABLE_CONNECTED_CHECK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFPY(neighbor_extended_link_bw,
|
||||||
|
neighbor_extended_link_bw_cmd,
|
||||||
|
"[no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor extended-link-bandwidth",
|
||||||
|
NO_STR
|
||||||
|
NEIGHBOR_STR
|
||||||
|
NEIGHBOR_ADDR_STR2
|
||||||
|
"Send Extended (64-bit) version of encoding for Link-Bandwidth\n")
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (no)
|
||||||
|
ret = peer_flag_unset_vty(vty, neighbor,
|
||||||
|
PEER_FLAG_EXTENDED_LINK_BANDWIDTH);
|
||||||
|
else
|
||||||
|
ret = peer_flag_set_vty(vty, neighbor,
|
||||||
|
PEER_FLAG_EXTENDED_LINK_BANDWIDTH);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* disable-link-bw-encoding-ieee */
|
/* disable-link-bw-encoding-ieee */
|
||||||
DEFUN(neighbor_disable_link_bw_encoding_ieee,
|
DEFUN(neighbor_disable_link_bw_encoding_ieee,
|
||||||
neighbor_disable_link_bw_encoding_ieee_cmd,
|
neighbor_disable_link_bw_encoding_ieee_cmd,
|
||||||
@ -18439,6 +18459,9 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
|
|||||||
vty_out(vty, " neighbor %s disable-link-bw-encoding-ieee\n",
|
vty_out(vty, " neighbor %s disable-link-bw-encoding-ieee\n",
|
||||||
addr);
|
addr);
|
||||||
|
|
||||||
|
if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_LINK_BANDWIDTH))
|
||||||
|
vty_out(vty, " neighbor %s extended-link-bandwidth\n", addr);
|
||||||
|
|
||||||
/* extended-optional-parameters */
|
/* extended-optional-parameters */
|
||||||
if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_OPT_PARAMS))
|
if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_OPT_PARAMS))
|
||||||
vty_out(vty, " neighbor %s extended-optional-parameters\n",
|
vty_out(vty, " neighbor %s extended-optional-parameters\n",
|
||||||
@ -20951,6 +20974,9 @@ void bgp_vty_init(void)
|
|||||||
install_element(BGP_NODE,
|
install_element(BGP_NODE,
|
||||||
&no_neighbor_disable_link_bw_encoding_ieee_cmd);
|
&no_neighbor_disable_link_bw_encoding_ieee_cmd);
|
||||||
|
|
||||||
|
|
||||||
|
install_element(BGP_NODE, &neighbor_extended_link_bw_cmd);
|
||||||
|
|
||||||
/* "neighbor extended-optional-parameters" commands. */
|
/* "neighbor extended-optional-parameters" commands. */
|
||||||
install_element(BGP_NODE, &neighbor_extended_optional_parameters_cmd);
|
install_element(BGP_NODE, &neighbor_extended_optional_parameters_cmd);
|
||||||
install_element(BGP_NODE,
|
install_element(BGP_NODE,
|
||||||
|
@ -1211,7 +1211,7 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool bgp_zebra_use_nhop_weighted(struct bgp *bgp, struct attr *attr,
|
static bool bgp_zebra_use_nhop_weighted(struct bgp *bgp, struct attr *attr,
|
||||||
uint32_t *nh_weight)
|
uint64_t *nh_weight)
|
||||||
{
|
{
|
||||||
/* zero link-bandwidth and link-bandwidth not present are treated
|
/* zero link-bandwidth and link-bandwidth not present are treated
|
||||||
* as the same situation.
|
* as the same situation.
|
||||||
@ -1273,7 +1273,7 @@ static void bgp_zebra_announce_parse_nexthop(
|
|||||||
for (; mpinfo; mpinfo = bgp_path_info_mpath_next(mpinfo)) {
|
for (; mpinfo; mpinfo = bgp_path_info_mpath_next(mpinfo)) {
|
||||||
labels = NULL;
|
labels = NULL;
|
||||||
num_labels = 0;
|
num_labels = 0;
|
||||||
uint32_t nh_weight;
|
uint64_t nh_weight;
|
||||||
bool is_evpn;
|
bool is_evpn;
|
||||||
bool is_parent_evpn;
|
bool is_parent_evpn;
|
||||||
|
|
||||||
@ -1518,8 +1518,9 @@ static void bgp_debug_zebra_nh(struct zapi_route *api)
|
|||||||
snprintf(eth_buf, sizeof(eth_buf), " RMAC %s",
|
snprintf(eth_buf, sizeof(eth_buf), " RMAC %s",
|
||||||
prefix_mac2str(&api_nh->rmac, buf1,
|
prefix_mac2str(&api_nh->rmac, buf1,
|
||||||
sizeof(buf1)));
|
sizeof(buf1)));
|
||||||
zlog_debug(" nhop [%d]: %s if %u VRF %u wt %u %s %s %s", i + 1,
|
zlog_debug(" nhop [%d]: %s if %u VRF %u wt %" PRIu64
|
||||||
nh_buf, api_nh->ifindex, api_nh->vrf_id,
|
" %s %s %s",
|
||||||
|
i + 1, nh_buf, api_nh->ifindex, api_nh->vrf_id,
|
||||||
api_nh->weight, label_buf, segs_buf, eth_buf);
|
api_nh->weight, label_buf, segs_buf, eth_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4623,6 +4623,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
|
|||||||
{PEER_FLAG_CAPABILITY_SOFT_VERSION, 0, peer_change_none},
|
{PEER_FLAG_CAPABILITY_SOFT_VERSION, 0, peer_change_none},
|
||||||
{PEER_FLAG_CAPABILITY_FQDN, 0, peer_change_none},
|
{PEER_FLAG_CAPABILITY_FQDN, 0, peer_change_none},
|
||||||
{PEER_FLAG_AS_LOOP_DETECTION, 0, peer_change_none},
|
{PEER_FLAG_AS_LOOP_DETECTION, 0, peer_change_none},
|
||||||
|
{PEER_FLAG_EXTENDED_LINK_BANDWIDTH, 0, peer_change_none},
|
||||||
{0, 0, 0}};
|
{0, 0, 0}};
|
||||||
|
|
||||||
static const struct peer_flag_action peer_af_flag_action_list[] = {
|
static const struct peer_flag_action peer_af_flag_action_list[] = {
|
||||||
|
@ -478,7 +478,7 @@ struct bgp {
|
|||||||
* factor (e.g., number of multipaths for the prefix)
|
* factor (e.g., number of multipaths for the prefix)
|
||||||
* Value is in Mbps
|
* Value is in Mbps
|
||||||
*/
|
*/
|
||||||
uint32_t lb_ref_bw;
|
uint64_t lb_ref_bw;
|
||||||
#define BGP_LINK_BW_REF_BW 1
|
#define BGP_LINK_BW_REF_BW 1
|
||||||
|
|
||||||
/* BGP flags. */
|
/* BGP flags. */
|
||||||
@ -1480,6 +1480,7 @@ struct peer {
|
|||||||
#define PEER_FLAG_CAPABILITY_SOFT_VERSION (1ULL << 36)
|
#define PEER_FLAG_CAPABILITY_SOFT_VERSION (1ULL << 36)
|
||||||
#define PEER_FLAG_CAPABILITY_FQDN (1ULL << 37) /* fqdn capability */
|
#define PEER_FLAG_CAPABILITY_FQDN (1ULL << 37) /* fqdn capability */
|
||||||
#define PEER_FLAG_AS_LOOP_DETECTION (1ULL << 38) /* as path loop detection */
|
#define PEER_FLAG_AS_LOOP_DETECTION (1ULL << 38) /* as path loop detection */
|
||||||
|
#define PEER_FLAG_EXTENDED_LINK_BANDWIDTH (1ULL << 39)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART
|
*GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART
|
||||||
|
@ -1572,6 +1572,15 @@ Configuring Peers
|
|||||||
value is carried encoded as uint32. To enable backward compatibility we
|
value is carried encoded as uint32. To enable backward compatibility we
|
||||||
need to disable IEEE floating-point encoding option per-peer.
|
need to disable IEEE floating-point encoding option per-peer.
|
||||||
|
|
||||||
|
.. clicmd:: neighbor PEER extended-link-bandwidth
|
||||||
|
|
||||||
|
By default bandwidth in extended communities is carried encoded as IEEE
|
||||||
|
floating-point format, and is limited to maximum of 25 Gbps.
|
||||||
|
|
||||||
|
Enabling this parameter, you can use the bandwidth of to 4294967295 Mbps.
|
||||||
|
|
||||||
|
This is disabled by default.
|
||||||
|
|
||||||
.. clicmd:: neighbor PEER enforce-first-as
|
.. clicmd:: neighbor PEER enforce-first-as
|
||||||
|
|
||||||
Discard updates received from the specified (eBGP) peer if the AS_PATH
|
Discard updates received from the specified (eBGP) peer if the AS_PATH
|
||||||
|
@ -1252,14 +1252,14 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
|
|||||||
} else if (IS_SET_EXTCOMMUNITY_LB(action)) {
|
} else if (IS_SET_EXTCOMMUNITY_LB(action)) {
|
||||||
enum ecommunity_lb_type lb_type;
|
enum ecommunity_lb_type lb_type;
|
||||||
char str[VTY_BUFSIZ];
|
char str[VTY_BUFSIZ];
|
||||||
uint16_t bandwidth;
|
uint32_t bandwidth;
|
||||||
|
|
||||||
lb_type = yang_dnode_get_enum(
|
lb_type = yang_dnode_get_enum(
|
||||||
dnode,
|
dnode,
|
||||||
"./rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type");
|
"./rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type");
|
||||||
switch (lb_type) {
|
switch (lb_type) {
|
||||||
case EXPLICIT_BANDWIDTH:
|
case EXPLICIT_BANDWIDTH:
|
||||||
bandwidth = yang_dnode_get_uint16(
|
bandwidth = yang_dnode_get_uint32(
|
||||||
dnode,
|
dnode,
|
||||||
"./rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth");
|
"./rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth");
|
||||||
snprintf(str, sizeof(str), "%d", bandwidth);
|
snprintf(str, sizeof(str), "%d", bandwidth);
|
||||||
|
@ -1040,7 +1040,7 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (api_nh->weight)
|
if (api_nh->weight)
|
||||||
stream_putl(s, api_nh->weight);
|
stream_putq(s, api_nh->weight);
|
||||||
|
|
||||||
/* Router MAC for EVPN routes. */
|
/* Router MAC for EVPN routes. */
|
||||||
if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_EVPN))
|
if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_EVPN))
|
||||||
@ -1412,7 +1412,7 @@ int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_WEIGHT))
|
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_WEIGHT))
|
||||||
STREAM_GETL(s, api_nh->weight);
|
STREAM_GETQ(s, api_nh->weight);
|
||||||
|
|
||||||
/* Router MAC for EVPN routes. */
|
/* Router MAC for EVPN routes. */
|
||||||
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN))
|
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN))
|
||||||
|
@ -441,7 +441,7 @@ struct zapi_nexthop {
|
|||||||
|
|
||||||
struct ethaddr rmac;
|
struct ethaddr rmac;
|
||||||
|
|
||||||
uint32_t weight;
|
uint64_t weight;
|
||||||
|
|
||||||
/* Backup nexthops, for IP-FRR, TI-LFA, etc */
|
/* Backup nexthops, for IP-FRR, TI-LFA, etc */
|
||||||
uint8_t backup_num;
|
uint8_t backup_num;
|
||||||
|
32
tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf
Normal file
32
tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
!
|
||||||
|
int r1-eth0
|
||||||
|
ip address 192.168.1.1/24
|
||||||
|
!
|
||||||
|
router bgp 65000
|
||||||
|
no bgp ebgp-requires-policy
|
||||||
|
no bgp network import-check
|
||||||
|
neighbor 192.168.1.2 remote-as internal
|
||||||
|
neighbor 192.168.1.2 timers 1 3
|
||||||
|
neighbor 192.168.1.2 timers connect 1
|
||||||
|
neighbor 192.168.1.2 extended-link-bandwidth
|
||||||
|
address-family ipv4 unicast
|
||||||
|
network 10.10.10.40/32
|
||||||
|
network 10.10.10.100/32
|
||||||
|
network 10.10.10.200/32
|
||||||
|
neighbor 192.168.1.2 route-map r2 out
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
ip prefix-list p40 seq 5 permit 10.10.10.40/32
|
||||||
|
ip prefix-list p100 seq 5 permit 10.10.10.100/32
|
||||||
|
ip prefix-list p200 seq 5 permit 10.10.10.200/32
|
||||||
|
!
|
||||||
|
route-map r2 permit 10
|
||||||
|
match ip address prefix-list p40
|
||||||
|
set extcommunity bandwidth 40000
|
||||||
|
route-map r2 permit 20
|
||||||
|
match ip address prefix-list p100
|
||||||
|
set extcommunity bandwidth 100000
|
||||||
|
route-map r2 permit 30
|
||||||
|
match ip address prefix-list p200
|
||||||
|
set extcommunity bandwidth 200000
|
||||||
|
exit
|
10
tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf
Normal file
10
tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
!
|
||||||
|
int r2-eth0
|
||||||
|
ip address 192.168.1.2/24
|
||||||
|
!
|
||||||
|
router bgp 65000
|
||||||
|
no bgp ebgp-requires-policy
|
||||||
|
neighbor 192.168.1.1 remote-as internal
|
||||||
|
neighbor 192.168.1.1 timers 1 3
|
||||||
|
neighbor 192.168.1.1 timers connect 1
|
||||||
|
!
|
@ -0,0 +1,95 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# SPDX-License-Identifier: ISC
|
||||||
|
|
||||||
|
# Copyright (c) 2024 by
|
||||||
|
# Donatas Abraitis <donatas@opensourcerouting.org>
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import pytest
|
||||||
|
import functools
|
||||||
|
|
||||||
|
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
sys.path.append(os.path.join(CWD, "../"))
|
||||||
|
|
||||||
|
# pylint: disable=C0413
|
||||||
|
from lib import topotest
|
||||||
|
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||||
|
|
||||||
|
pytestmark = [pytest.mark.bgpd]
|
||||||
|
|
||||||
|
|
||||||
|
def setup_module(mod):
|
||||||
|
topodef = {"s1": ("r1", "r2")}
|
||||||
|
tgen = Topogen(topodef, mod.__name__)
|
||||||
|
tgen.start_topology()
|
||||||
|
|
||||||
|
router_list = tgen.routers()
|
||||||
|
|
||||||
|
for _, (rname, router) in enumerate(router_list.items(), 1):
|
||||||
|
router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
|
||||||
|
|
||||||
|
tgen.start_router()
|
||||||
|
|
||||||
|
|
||||||
|
def teardown_module(mod):
|
||||||
|
tgen = get_topogen()
|
||||||
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
|
||||||
|
def test_bgp_dynamic_capability_role():
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
r2 = tgen.gears["r2"]
|
||||||
|
|
||||||
|
def _bgp_converge():
|
||||||
|
output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast json detail"))
|
||||||
|
expected = {
|
||||||
|
"routes": {
|
||||||
|
"10.10.10.40/32": {
|
||||||
|
"paths": [
|
||||||
|
{
|
||||||
|
"extendedIpv6Community": {
|
||||||
|
"string": "LB:65000:5000000000 (40.000 Gbps)",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"10.10.10.100/32": {
|
||||||
|
"paths": [
|
||||||
|
{
|
||||||
|
"extendedIpv6Community": {
|
||||||
|
"string": "LB:65000:12500000000 (100.000 Gbps)",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"10.10.10.200/32": {
|
||||||
|
"paths": [
|
||||||
|
{
|
||||||
|
"extendedIpv6Community": {
|
||||||
|
"string": "LB:65000:25000000000 (200.000 Gbps)",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return topotest.json_cmp(output, expected)
|
||||||
|
|
||||||
|
test_func = functools.partial(
|
||||||
|
_bgp_converge,
|
||||||
|
)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
|
||||||
|
assert result is None, "Can't see link bandwidths as expected"
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = ["-s"] + sys.argv[1:]
|
||||||
|
sys.exit(pytest.main(args))
|
@ -4,7 +4,7 @@
|
|||||||
{
|
{
|
||||||
"valid":true,
|
"valid":true,
|
||||||
"multipath":true,
|
"multipath":true,
|
||||||
"extendedCommunity":{
|
"extendedIpv6Community":{
|
||||||
"string":"LB:65302:125000 (1.000 Mbps)"
|
"string":"LB:65302:125000 (1.000 Mbps)"
|
||||||
},
|
},
|
||||||
"nexthops":[
|
"nexthops":[
|
||||||
|
@ -13,6 +13,7 @@ router bgp 65302
|
|||||||
bgp bestpath as-path multipath-relax
|
bgp bestpath as-path multipath-relax
|
||||||
no bgp ebgp-requires-policy
|
no bgp ebgp-requires-policy
|
||||||
neighbor 11.1.2.5 remote-as external
|
neighbor 11.1.2.5 remote-as external
|
||||||
|
neighbor 11.1.2.5 extended-link-bandwidth
|
||||||
neighbor 11.1.2.5 timers 3 10
|
neighbor 11.1.2.5 timers 3 10
|
||||||
neighbor 11.1.5.2 remote-as external
|
neighbor 11.1.5.2 remote-as external
|
||||||
neighbor 11.1.5.2 timers 3 10
|
neighbor 11.1.5.2 timers 3 10
|
||||||
|
@ -881,9 +881,7 @@ identity set-extcommunity-color {
|
|||||||
leaf bandwidth {
|
leaf bandwidth {
|
||||||
when "../lb-type = 'explicit-bandwidth'";
|
when "../lb-type = 'explicit-bandwidth'";
|
||||||
mandatory true;
|
mandatory true;
|
||||||
type uint16 {
|
type uint32;
|
||||||
range "1..25600";
|
|
||||||
}
|
|
||||||
description
|
description
|
||||||
"Bandwidth value in Mbps";
|
"Bandwidth value in Mbps";
|
||||||
}
|
}
|
||||||
|
@ -1738,9 +1738,8 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
|
|||||||
for (i = 0; i < nexthop_num; i++) {
|
for (i = 0; i < nexthop_num; i++) {
|
||||||
znh = &nhops[i];
|
znh = &nhops[i];
|
||||||
|
|
||||||
tmp = (uint64_t)znh->weight *
|
tmp = znh->weight * zrouter.nexthop_weight_scale_value;
|
||||||
zrouter.nexthop_weight_scale_value;
|
znh->weight = MAX(1, (tmp / max_weight));
|
||||||
znh->weight = MAX(1, ((uint32_t)(tmp / max_weight)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user