diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index ec9f12d61a..e1b056ff45 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -2206,6 +2206,16 @@ cluster_list_ignore: return bgp_attr_ignore(peer, args->type); } +/* get locally configure or received srte-color value*/ +uint32_t bgp_attr_get_color(struct attr *attr) +{ + if (attr->srte_color) + return attr->srte_color; + if (attr->ecommunity) + return ecommunity_select_color(attr->ecommunity); + return 0; +} + /* Multiprotocol reachability information parse. */ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args, struct bgp_nlri *mp_update) diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 1c7e88a4f9..cf3e8d7d7f 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -466,6 +466,8 @@ extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt); extern enum bgp_attr_parse_ret bgp_attr_nexthop_valid(struct peer *peer, struct attr *attr); +extern uint32_t bgp_attr_get_color(struct attr *attr); + static inline bool bgp_rmap_nhop_changed(uint32_t out_rmap_flags, uint32_t in_rmap_flags) { diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index ec860c5a1c..0fea9074c5 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -1420,6 +1420,29 @@ bool ecommunity_match(const struct ecommunity *ecom1, return false; } +/* return last occurence of color */ +/* it will be the greatest color value */ +extern uint32_t ecommunity_select_color(const struct ecommunity *ecom) +{ + + uint32_t aux_color = 0; + uint8_t *p; + uint32_t c = 0; + + /* If the value already exists in the structure return 0. */ + + for (p = ecom->val; c < ecom->size; p += ecom->unit_size, c++) { + if (p == NULL) + break; + + if (p[0] == ECOMMUNITY_ENCODE_OPAQUE && + p[1] == ECOMMUNITY_COLOR) + ptr_get_be32((const uint8_t *)&p[4], &aux_color); + } + return aux_color; +} + + /* return first occurence of type */ extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *ecom, uint8_t type, uint8_t subtype) diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index 5e67e5015e..31196e9ca9 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -349,6 +349,7 @@ extern char *ecommunity_str(struct ecommunity *ecom); extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *, uint8_t, uint8_t); +extern uint32_t ecommunity_select_color(const struct ecommunity *ecom); extern bool ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval, bool unique, bool overwrite); diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index d7b1429881..1d99e5e829 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -32,6 +32,7 @@ #include "bgpd/bgp_evpn.h" #include "bgpd/bgp_rd.h" #include "bgpd/bgp_mplsvpn.h" +#include "bgpd/bgp_ecommunity.h" extern struct zclient *zclient; @@ -321,7 +322,10 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, return 0; } - srte_color = pi->attr->srte_color; + if (CHECK_FLAG(pi->attr->flag, + ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR))) + srte_color = bgp_attr_get_color(pi->attr); + } else if (peer) { /* * Gather the ifindex for if up/down events to be @@ -1238,9 +1242,9 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc) else if (bpi_ultimate->extra) bpi_ultimate->extra->igpmetric = 0; - if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) - || CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED) - || path->attr->srte_color != 0) + if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) || + CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED) || + bgp_attr_get_color(path->attr)) SET_FLAG(path->flags, BGP_PATH_IGP_CHANGED); path_valid = CHECK_FLAG(path->flags, BGP_PATH_VALID); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 1965cd2704..7e773b6cd7 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1440,7 +1440,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, if (CHECK_FLAG(info->attr->flag, ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR))) - api_nh->srte_color = info->attr->srte_color; + api_nh->srte_color = bgp_attr_get_color(info->attr); if (bgp_debug_zebra(&api.prefix)) { if (mpinfo->extra) {