return NULL;
}
+
+
+struct ecommunity *ecommunity_replace_linkbw(as_t as,
+ struct ecommunity *ecom,
+ uint64_t cum_bw)
+{
+ struct ecommunity *new;
+ struct ecommunity_val lb_eval;
+ const uint8_t *eval;
+ uint8_t type;
+ uint32_t cur_bw;
+
+ /* Nothing to replace if link-bandwidth doesn't exist or
+ * is non-transitive - just return existing extcommunity.
+ */
+ new = ecom;
+ if (!ecom || !ecom->size)
+ return new;
+
+ eval = ecommunity_linkbw_present(ecom, &cur_bw);
+ if (!eval)
+ return new;
+
+ type = *eval;
+ if (type & ECOMMUNITY_FLAG_NON_TRANSITIVE)
+ return new;
+
+ /* Transitive link-bandwidth exists, replace with the passed
+ * (cumulative) bandwidth value. We need to create a new
+ * extcommunity for this - refer to AS-Path replace function
+ * for reference.
+ */
+ if (cum_bw > 0xFFFFFFFF)
+ cum_bw = 0xFFFFFFFF;
+ encode_lb_extcomm(as > BGP_AS_MAX ? BGP_AS_TRANS : as, cum_bw,
+ false, &lb_eval);
+ new = ecommunity_dup(ecom);
+ ecommunity_add_val(new, &lb_eval, true, true);
+
+ return new;
+}
afi_t afi;
safi_t safi;
int samepeer_safe = 0; /* for synthetic mplsvpns routes */
+ bool nh_reset = false;
+ uint64_t cum_bw;
if (DISABLE_BGP_ANNOUNCE)
return false;
PEER_FLAG_FORCE_NEXTHOP_SELF)) {
if (!reflect
|| CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_FORCE_NEXTHOP_SELF))
+ PEER_FLAG_FORCE_NEXTHOP_SELF)) {
subgroup_announce_reset_nhop(
(peer_cap_enhe(peer, afi, safi)
? AF_INET6
: p->family),
attr);
+ nh_reset = true;
+ }
} else if (peer->sort == BGP_PEER_EBGP) {
/* Can also reset the nexthop if announcing to EBGP, but
* only if
if ((p->family == AF_INET) &&
(!bgp_subgrp_multiaccess_check_v4(
piattr->nexthop,
- subgrp, from)))
+ subgrp, from))) {
subgroup_announce_reset_nhop(
(peer_cap_enhe(peer, afi, safi)
? AF_INET6
: p->family),
attr);
+ nh_reset = true;
+ }
if ((p->family == AF_INET6) &&
(!bgp_subgrp_multiaccess_check_v6(
piattr->mp_nexthop_global,
- subgrp, from)))
+ subgrp, from))) {
subgroup_announce_reset_nhop(
(peer_cap_enhe(peer, afi, safi)
? AF_INET6
: p->family),
attr);
+ nh_reset = true;
+ }
"%s: BGP_PATH_ANNC_NH_SELF, family=%s",
__func__, family2str(family));
subgroup_announce_reset_nhop(family, attr);
+ nh_reset = true;
}
}
* the same interface.
*/
if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
- if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
+ if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
subgroup_announce_reset_nhop(AF_INET6, attr);
+ nh_reset = true;
+ }
}
+ /*
+ * When the next hop is set to ourselves, if all multipaths have
+ * link-bandwidth announce the cumulative bandwidth as that makes
+ * 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(pi) &&
+ (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
+ !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
+ attr->ecommunity = ecommunity_replace_linkbw(
+ bgp->as, attr->ecommunity, cum_bw);
+
return true;
}