diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index e2321ad296..913634bf59 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -915,12 +915,13 @@ static void attr_show_all_iterator(struct hash_bucket *bucket, struct vty *vty) "\n", attr->flag, attr->distance, attr->med, attr->local_pref, attr->origin, attr->weight, attr->label, sid, attr->aigp_metric); - vty_out(vty, - "\taspath: %s Community: %s Extended Community: %s Large Community: %s\n", + vty_out(vty, "\taspath: %s Community: %s Large Community: %s\n", aspath_print(attr->aspath), community_str(attr->community, false, false), - ecommunity_str(attr->ecommunity), 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) @@ -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]) goto ipv6_ext_community_ignore; - ipv6_ecomm = ecommunity_parse_ipv6( - stream_pnt(peer->curr), length, - CHECK_FLAG(peer->flags, - PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)); + ipv6_ecomm = ecommunity_parse_ipv6(stream_pnt(peer->curr), length); bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm); /* 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, 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; 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; } +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. */ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, 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. */ - 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); + /* Extended IPv6/Communities attributes. */ + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) { bool transparent = CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) && from && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT); - if (peer->sort == BGP_PEER_IBGP || - peer->sort == BGP_PEER_CONFED || transparent) { - if (ecomm->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); - 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; + if (CHECK_FLAG(attr->flag, + ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) { + struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr); - for (i = 0; i < ecomm->size; i++) { - pnt = ecomm->val + (i * 8); - tbit = *pnt; + bgp_packet_ecommunity_attribute(s, peer, ecomm, + transparent, + BGP_ATTR_EXT_COMMUNITIES); + } - if (CHECK_FLAG(tbit, - ECOMMUNITY_FLAG_NON_TRANSITIVE)) - continue; + if (CHECK_FLAG(attr->flag, + ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES))) { + struct ecommunity *ecomm = + bgp_attr_get_ipv6_ecommunity(attr); - 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); - 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++) { - pnt = ecomm->val + (i * 8); - tbit = *pnt; - - if (CHECK_FLAG( - tbit, - ECOMMUNITY_FLAG_NON_TRANSITIVE)) - continue; - - stream_put(s, pnt, 8); - } - } + bgp_packet_ecommunity_attribute(s, peer, ecomm, + transparent, + BGP_ATTR_IPV6_EXT_COMMUNITIES); } } diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 164aa5ae79..3f8e2784f1 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -301,7 +301,7 @@ struct attr { uint32_t rmap_table_id; /* Link bandwidth value, if any. */ - uint32_t link_bw; + uint64_t link_bw; /* EVPN ES */ esi_t esi; diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index e1b462ae56..be8f56637e 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -237,11 +237,10 @@ struct ecommunity *ecommunity_parse(uint8_t *pnt, unsigned short length, disable_ieee_floating); } -struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, unsigned short length, - bool disable_ieee_floating) +struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, unsigned short length) { return ecommunity_parse_internal(pnt, length, IPV6_ECOMMUNITY_SIZE, - disable_ieee_floating); + false); } /* 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; 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++); (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; } +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) { uint32_t i; @@ -1153,6 +1175,12 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) ecommunity_lb_str( encbuf, sizeof(encbuf), pnt, 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 && type == ECOMMUNITY_ENCODE_IP) { ecommunity_node_target_str( @@ -1370,6 +1398,13 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) ecom->disable_ieee_floating); else 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) { sub_type = *pnt++; 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; * 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; 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++) { const uint8_t *pnt; 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++; sub_type = *pnt++; if ((type == ECOMMUNITY_ENCODE_AS || type == ECOMMUNITY_ENCODE_AS_NON_TRANS) && sub_type == ECOMMUNITY_LINK_BANDWIDTH) { + uint32_t bwval; + pnt += 2; /* bandwidth is encoded as AS:val */ pnt = ptr_get_be32(pnt, &bwval); (void)pnt; /* consume value */ if (bw) - *bw = ecom->disable_ieee_floating - ? bwval - : ieee_float_uint32_to_uint32( - bwval); + *bw = (uint64_t)(ecom->disable_ieee_floating + ? bwval + : ieee_float_uint32_to_uint32( + 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; } } @@ -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, uint64_t cum_bw, - bool disable_ieee_floating) + bool disable_ieee_floating, + bool extended) { struct ecommunity *new; - struct ecommunity_val lb_eval; const uint8_t *eval; uint8_t type; - uint32_t cur_bw; + uint64_t cur_bw; /* Nothing to replace if link-bandwidth doesn't exist or * 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) cum_bw = 0xFFFFFFFF; - encode_lb_extcomm(as > BGP_AS_MAX ? BGP_AS_TRANS : as, cum_bw, false, - &lb_eval, disable_ieee_floating); - new = ecommunity_dup(ecom); - ecommunity_add_val(new, &lb_eval, true, true); + + 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); + ecommunity_add_val(new, &lb_eval, true, true); + } return new; } diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index 794c5a3975..929e4e60be 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -10,6 +10,10 @@ #include "bgpd/bgp_rpki.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 * updated by other standards like rfc7674. */ @@ -55,6 +59,12 @@ /* RFC 8956 */ #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 */ #define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00 #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 * 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, bool disable_ieee_floating) { - uint32_t bandwidth = - disable_ieee_floating ? bw : uint32_to_ieee_float_uint32(bw); + uint64_t bandwidth = disable_ieee_floating + ? bw + : uint32_to_ieee_float_uint32(bw); memset(eval, 0, sizeof(*eval)); 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; } +/* + * 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, struct ecommunity_val *eval) { @@ -325,8 +363,7 @@ extern void ecommunity_free(struct ecommunity **); extern struct ecommunity *ecommunity_parse(uint8_t *, unsigned short, bool disable_ieee_floating); extern struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, - unsigned short length, - bool disable_ieee_floating); + unsigned short length); extern struct ecommunity *ecommunity_dup(struct ecommunity *); extern struct ecommunity *ecommunity_merge(struct ecommunity *, struct ecommunity *); @@ -385,11 +422,10 @@ extern void bgp_remove_ecomm_from_aggregate_hash( struct ecommunity *ecommunity); extern void bgp_aggr_ecommunity_remove(void *arg); extern const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, - uint32_t *bw); -extern struct ecommunity *ecommunity_replace_linkbw(as_t as, - struct ecommunity *ecom, - uint64_t cum_bw, - bool disable_ieee_floating); + uint64_t *bw); +extern struct ecommunity * +ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom, uint64_t cum_bw, + bool disable_ieee_floating, bool extended); extern bool soo_in_ecom(struct ecommunity *ecom, struct ecommunity *soo); diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 296e64003d..e12d84b84c 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -521,7 +521,7 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, struct bgp_maxpaths_cfg *mpath_cfg) { uint16_t maxpaths, mpath_count, old_mpath_count; - uint32_t bwval; + uint64_t bwval; uint64_t cum_bw, old_cum_bw; struct listnode *mp_node, *mp_next_node; 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); prev_mpath = cur_mpath; mpath_count++; - if (ecommunity_linkbw_present( - bgp_attr_get_ecommunity( + if (ecommunity_linkbw_present(bgp_attr_get_ecommunity( + cur_mpath->attr), + &bwval) || + ecommunity_linkbw_present( + bgp_attr_get_ipv6_ecommunity( cur_mpath->attr), &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; mpath_changed = 1; mpath_count++; - if (ecommunity_linkbw_present( - bgp_attr_get_ecommunity( + if (ecommunity_linkbw_present(bgp_attr_get_ecommunity( + new_mpath->attr), + &bwval) || + ecommunity_linkbw_present( + bgp_attr_get_ipv6_ecommunity( new_mpath->attr), &bwval)) cum_bw += bwval; @@ -724,8 +730,12 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, if (new_best) { bgp_path_info_mpath_count_set(new_best, mpath_count - 1); if (mpath_count <= 1 || - !ecommunity_linkbw_present( - bgp_attr_get_ecommunity(new_best->attr), &bwval)) + (!ecommunity_linkbw_present(bgp_attr_get_ecommunity( + new_best->attr), + &bwval) && + !ecommunity_linkbw_present(bgp_attr_get_ipv6_ecommunity( + new_best->attr), + &bwval))) all_paths_lb = false; else cum_bw += bwval; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 3feb2717d1..6bf56a5285 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -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 * been explicitly set by user policy. */ - if (nh_reset && - bgp_path_info_mpath_chkwtd(bgp, pi) && + if (nh_reset && bgp_path_info_mpath_chkwtd(bgp, pi) && (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 && - !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET)) - bgp_attr_set_ecommunity( - attr, - ecommunity_replace_linkbw( - bgp->as, bgp_attr_get_ecommunity(attr), cum_bw, - CHECK_FLAG( - peer->flags, - PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE))); + !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( + attr, + ecommunity_replace_linkbw( + bgp->as, bgp_attr_get_ecommunity(attr), + cum_bw, + CHECK_FLAG(peer->flags, + PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE), + false)); + } 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_list = NULL; json_object *json_ext_community = NULL; + json_object *json_ext_ipv6_community = NULL; json_object *json_last_update = NULL; json_object *json_pmsi = 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 */ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) { if (json_paths) { diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 15828b6594..1515b64b77 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -3196,7 +3196,7 @@ struct rmap_ecomm_lb_set { #define RMAP_ECOMM_LB_SET_CUMUL 2 #define RMAP_ECOMM_LB_SET_NUM_MPATH 3 bool non_trans; - uint32_t bw; + uint64_t bw; }; 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 peer *peer; struct ecommunity ecom_lb = {0}; - struct ecommunity_val lb_eval; - uint32_t bw_bytes = 0; + uint64_t bw_bytes = 0; uint16_t mpath_count = 0; struct ecommunity *new_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 */ as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as; 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) { /* process this only for the best path. */ if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) return RMAP_OKAY; - bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path); + bw_bytes = bgp_path_info_mpath_cumbw(path); if (!bw_bytes) return RMAP_OKAY; @@ -3237,31 +3236,53 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object) if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) 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; bw_bytes *= mpath_count; } - encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval, - CHECK_FLAG(peer->flags, - PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)); + if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_LINK_BANDWIDTH)) { + struct ecommunity_val_ipv6 lb_eval; - /* add to route or merge with existing */ - old_ecom = bgp_attr_get_ecommunity(path->attr); - if (old_ecom) { - new_ecom = ecommunity_dup(old_ecom); - ecommunity_add_val(new_ecom, &lb_eval, true, true); - if (!old_ecom->refcnt) - ecommunity_free(&old_ecom); + 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 { - ecom_lb.size = 1; - ecom_lb.unit_size = ECOMMUNITY_SIZE; - ecom_lb.val = (uint8_t *)lb_eval.val; - new_ecom = ecommunity_dup(&ecom_lb); - } + struct ecommunity_val lb_eval; - /* new_ecom will be intern()'d or attr_flush()'d in call stack */ - bgp_attr_set_ecommunity(path->attr, new_ecom); + encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval, + CHECK_FLAG(peer->flags, + PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)); + + old_ecom = bgp_attr_get_ecommunity(path->attr); + if (old_ecom) { + new_ecom = ecommunity_dup(old_ecom); + ecommunity_add_val(new_ecom, &lb_eval, true, true); + if (!old_ecom->refcnt) + ecommunity_free(&old_ecom); + } else { + ecom_lb.size = 1; + ecom_lb.unit_size = ECOMMUNITY_SIZE; + ecom_lb.val = (uint8_t *)lb_eval.val; + new_ecom = ecommunity_dup(&ecom_lb); + } + + bgp_attr_set_ecommunity(path->attr, new_ecom); + } /* Mark that route-map has set link bandwidth; used in attribute * setting decisions. @@ -3275,7 +3296,7 @@ static void *route_set_ecommunity_lb_compile(const char *arg) { struct rmap_ecomm_lb_set *rels; uint8_t lb_type; - uint32_t bw = 0; + uint64_t bw = 0; char bw_str[40] = {0}; char *p, *str; bool non_trans = false; @@ -6875,7 +6896,7 @@ DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd, DEFUN_YANG (set_ecommunity_lb, 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 "BGP extended community attribute\n" "Link bandwidth extended community\n" @@ -6929,7 +6950,7 @@ DEFUN_YANG (set_ecommunity_lb, DEFUN_YANG (no_set_ecommunity_lb, 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 SET_STR "BGP extended community attribute\n" diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c index c1d6ee12e1..15c32eaa28 100644 --- a/bgpd/bgp_routemap_nb_config.c +++ b/bgpd/bgp_routemap_nb_config.c @@ -2937,7 +2937,7 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish( struct routemap_hook_context *rhc; enum ecommunity_lb_type lb_type; char str[VTY_BUFSIZ]; - uint16_t bandwidth; + uint32_t bandwidth; int ret; /* Add configuration. */ @@ -2951,8 +2951,8 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish( switch (lb_type) { case EXPLICIT_BANDWIDTH: - bandwidth = yang_dnode_get_uint16(args->dnode, "bandwidth"); - snprintf(str, sizeof(str), "%d", bandwidth); + bandwidth = yang_dnode_get_uint32(args->dnode, "bandwidth"); + snprintf(str, sizeof(str), "%u", bandwidth); break; case CUMULATIVE_BANDWIDTH: snprintf(str, sizeof(str), "%s", "cumulative"); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index f8d8e8ad3a..b4e938b822 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -7115,6 +7115,26 @@ DEFUN (no_neighbor_disable_connected_check, PEER_FLAG_DISABLE_CONNECTED_CHECK); } +DEFPY(neighbor_extended_link_bw, + neighbor_extended_link_bw_cmd, + "[no] neighbor $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 */ DEFUN(neighbor_disable_link_bw_encoding_ieee, 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", addr); + if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_LINK_BANDWIDTH)) + vty_out(vty, " neighbor %s extended-link-bandwidth\n", addr); + /* extended-optional-parameters */ if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_OPT_PARAMS)) vty_out(vty, " neighbor %s extended-optional-parameters\n", @@ -20951,6 +20974,9 @@ void bgp_vty_init(void) install_element(BGP_NODE, &no_neighbor_disable_link_bw_encoding_ieee_cmd); + + install_element(BGP_NODE, &neighbor_extended_link_bw_cmd); + /* "neighbor extended-optional-parameters" commands. */ install_element(BGP_NODE, &neighbor_extended_optional_parameters_cmd); install_element(BGP_NODE, diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 9a81965773..ec79f944eb 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -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, - uint32_t *nh_weight) + uint64_t *nh_weight) { /* zero link-bandwidth and link-bandwidth not present are treated * as the same situation. @@ -1273,7 +1273,7 @@ static void bgp_zebra_announce_parse_nexthop( for (; mpinfo; mpinfo = bgp_path_info_mpath_next(mpinfo)) { labels = NULL; num_labels = 0; - uint32_t nh_weight; + uint64_t nh_weight; bool is_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", prefix_mac2str(&api_nh->rmac, buf1, sizeof(buf1))); - zlog_debug(" nhop [%d]: %s if %u VRF %u wt %u %s %s %s", i + 1, - nh_buf, api_nh->ifindex, api_nh->vrf_id, + zlog_debug(" nhop [%d]: %s if %u VRF %u wt %" PRIu64 + " %s %s %s", + i + 1, nh_buf, api_nh->ifindex, api_nh->vrf_id, api_nh->weight, label_buf, segs_buf, eth_buf); } } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 95d949343c..a7564da8b3 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -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_FQDN, 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}}; static const struct peer_flag_action peer_af_flag_action_list[] = { diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index e882a181b5..06ef1d3537 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -478,7 +478,7 @@ struct bgp { * factor (e.g., number of multipaths for the prefix) * Value is in Mbps */ - uint32_t lb_ref_bw; + uint64_t lb_ref_bw; #define BGP_LINK_BW_REF_BW 1 /* BGP flags. */ @@ -1480,6 +1480,7 @@ struct peer { #define PEER_FLAG_CAPABILITY_SOFT_VERSION (1ULL << 36) #define PEER_FLAG_CAPABILITY_FQDN (1ULL << 37) /* fqdn capability */ #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 diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 878473cd77..1de6773922 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -1572,6 +1572,15 @@ Configuring Peers value is carried encoded as uint32. To enable backward compatibility we 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 Discard updates received from the specified (eBGP) peer if the AS_PATH diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c index 88b341cac0..a12a07c14f 100644 --- a/lib/routemap_cli.c +++ b/lib/routemap_cli.c @@ -1252,14 +1252,14 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode, } else if (IS_SET_EXTCOMMUNITY_LB(action)) { enum ecommunity_lb_type lb_type; char str[VTY_BUFSIZ]; - uint16_t bandwidth; + uint32_t bandwidth; lb_type = yang_dnode_get_enum( dnode, "./rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type"); switch (lb_type) { case EXPLICIT_BANDWIDTH: - bandwidth = yang_dnode_get_uint16( + bandwidth = yang_dnode_get_uint32( dnode, "./rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth"); snprintf(str, sizeof(str), "%d", bandwidth); diff --git a/lib/zclient.c b/lib/zclient.c index 4cbd04c116..8a6eb95134 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1040,7 +1040,7 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, } if (api_nh->weight) - stream_putl(s, api_nh->weight); + stream_putq(s, api_nh->weight); /* Router MAC for EVPN routes. */ 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)) - STREAM_GETL(s, api_nh->weight); + STREAM_GETQ(s, api_nh->weight); /* Router MAC for EVPN routes. */ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) diff --git a/lib/zclient.h b/lib/zclient.h index 1bf91064e2..3759f94542 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -441,7 +441,7 @@ struct zapi_nexthop { struct ethaddr rmac; - uint32_t weight; + uint64_t weight; /* Backup nexthops, for IP-FRR, TI-LFA, etc */ uint8_t backup_num; diff --git a/tests/topotests/bgp_extended_link_bandwidth/__init__.py b/tests/topotests/bgp_extended_link_bandwidth/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf b/tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf new file mode 100644 index 0000000000..d0c0813e84 --- /dev/null +++ b/tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf @@ -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 diff --git a/tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf b/tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf new file mode 100644 index 0000000000..5cad150aef --- /dev/null +++ b/tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf @@ -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 +! diff --git a/tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py b/tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py new file mode 100644 index 0000000000..e7058f5392 --- /dev/null +++ b/tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# Copyright (c) 2024 by +# Donatas Abraitis +# + +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)) diff --git a/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json index dfc4171bad..6289a2eea3 100644 --- a/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json +++ b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json @@ -4,7 +4,7 @@ { "valid":true, "multipath":true, - "extendedCommunity":{ + "extendedIpv6Community":{ "string":"LB:65302:125000 (1.000 Mbps)" }, "nexthops":[ diff --git a/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf index 4014bfbc8b..e4ed92db1d 100644 --- a/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf +++ b/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf @@ -13,6 +13,7 @@ router bgp 65302 bgp bestpath as-path multipath-relax no bgp ebgp-requires-policy 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.5.2 remote-as external neighbor 11.1.5.2 timers 3 10 diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang index c679f3b911..b0858e153c 100644 --- a/yang/frr-bgp-route-map.yang +++ b/yang/frr-bgp-route-map.yang @@ -881,9 +881,7 @@ identity set-extcommunity-color { leaf bandwidth { when "../lb-type = 'explicit-bandwidth'"; mandatory true; - type uint16 { - range "1..25600"; - } + type uint32; description "Bandwidth value in Mbps"; } diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 76cabd1bf0..d585ef996b 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1724,7 +1724,7 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p, * Let's convert the weights to a scaled value * between 1 and zrouter.nexthop_weight_scale_value * This is a simple application of a ratio: - * scaled_weight/zrouter.nexthop_weight_scale_value = + * scaled_weight/zrouter.nexthop_weight_scale_value = * weight/max_weight * This translates to: * scaled_weight = weight * zrouter.nexthop_weight_scale_value @@ -1738,9 +1738,8 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p, for (i = 0; i < nexthop_num; i++) { znh = &nhops[i]; - tmp = (uint64_t)znh->weight * - zrouter.nexthop_weight_scale_value; - znh->weight = MAX(1, ((uint32_t)(tmp / max_weight))); + tmp = znh->weight * zrouter.nexthop_weight_scale_value; + znh->weight = MAX(1, (tmp / max_weight)); } }