diff options
Diffstat (limited to 'bgpd/bgp_attr.c')
-rw-r--r-- | bgpd/bgp_attr.c | 376 |
1 files changed, 240 insertions, 136 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index e4ee589a..1a2fa831 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -198,6 +198,7 @@ static struct hash *vnc_hash = NULL; #endif static struct hash *srv6_l3vpn_hash; static struct hash *srv6_vpn_hash; +static struct hash *evpn_overlay_hash; struct bgp_attr_encap_subtlv *encap_tlv_dup(struct bgp_attr_encap_subtlv *orig) { @@ -479,22 +480,11 @@ static bool bgp_attr_aigp_get_tlv_metric(uint8_t *pnt, int length, return false; } -static uint64_t bgp_aigp_metric_total(struct bgp_path_info *bpi) -{ - uint64_t aigp = bgp_attr_get_aigp_metric(bpi->attr); - - if (bpi->nexthop) - return aigp + bpi->nexthop->metric; - else - return aigp; -} - -static void stream_put_bgp_aigp_tlv_metric(struct stream *s, - struct bgp_path_info *bpi) +static void stream_put_bgp_aigp_tlv_metric(struct stream *s, uint64_t aigp) { stream_putc(s, BGP_AIGP_TLV_METRIC); stream_putw(s, BGP_AIGP_TLV_METRIC_LEN); - stream_putq(s, bgp_aigp_metric_total(bpi)); + stream_putq(s, aigp); } static bool bgp_attr_aigp_valid(uint8_t *pnt, int length) @@ -549,6 +539,81 @@ static bool bgp_attr_aigp_valid(uint8_t *pnt, int length) return true; } +static void *evpn_overlay_hash_alloc(void *p) +{ + return p; +} + +void evpn_overlay_free(struct bgp_route_evpn *bre) +{ + XFREE(MTYPE_BGP_EVPN_OVERLAY, bre); +} + +static struct bgp_route_evpn *evpn_overlay_intern(struct bgp_route_evpn *bre) +{ + struct bgp_route_evpn *find; + + find = hash_get(evpn_overlay_hash, bre, evpn_overlay_hash_alloc); + if (find != bre) + evpn_overlay_free(bre); + find->refcnt++; + return find; +} + +static void evpn_overlay_unintern(struct bgp_route_evpn **brep) +{ + struct bgp_route_evpn *bre = *brep; + + if (!*brep) + return; + + if (bre->refcnt) + bre->refcnt--; + + if (bre->refcnt == 0) { + hash_release(evpn_overlay_hash, bre); + evpn_overlay_free(bre); + *brep = NULL; + } +} + +static uint32_t evpn_overlay_hash_key_make(const void *p) +{ + const struct bgp_route_evpn *bre = p; + uint32_t key = 0; + + if (IS_IPADDR_V4(&bre->gw_ip)) + key = jhash_1word(bre->gw_ip.ipaddr_v4.s_addr, 0); + else + key = jhash2(bre->gw_ip.ipaddr_v6.s6_addr32, + array_size(bre->gw_ip.ipaddr_v6.s6_addr32), 0); + + key = jhash_1word(bre->type, key); + key = jhash(bre->eth_s_id.val, sizeof(bre->eth_s_id.val), key); + return key; +} + +static bool evpn_overlay_hash_cmp(const void *p1, const void *p2) +{ + const struct bgp_route_evpn *bre1 = p1; + const struct bgp_route_evpn *bre2 = p2; + + return bgp_route_evpn_same(bre1, bre2); +} + +static void evpn_overlay_init(void) +{ + evpn_overlay_hash = hash_create(evpn_overlay_hash_key_make, + evpn_overlay_hash_cmp, + "BGP EVPN Overlay"); +} + +static void evpn_overlay_finish(void) +{ + hash_clean_and_free(&evpn_overlay_hash, + (void (*)(void *))evpn_overlay_free); +} + static void *srv6_l3vpn_hash_alloc(void *p) { return p; @@ -788,6 +853,8 @@ unsigned int attrhash_key_make(const void *p) MIX(encap_hash_key_make(attr->encap_subtlvs)); if (attr->srv6_l3vpn) MIX(srv6_l3vpn_hash_key_make(attr->srv6_l3vpn)); + if (bgp_attr_get_evpn_overlay(attr)) + MIX(evpn_overlay_hash_key_make(bgp_attr_get_evpn_overlay(attr))); if (attr->srv6_vpn) MIX(srv6_vpn_hash_key_make(attr->srv6_vpn)); #ifdef ENABLE_BGP_VNC @@ -814,19 +881,16 @@ bool attrhash_cmp(const void *p1, const void *p2) const struct attr *attr1 = p1; const struct attr *attr2 = p2; - if (attr1->flag == attr2->flag && attr1->origin == attr2->origin - && attr1->nexthop.s_addr == attr2->nexthop.s_addr - && attr1->aspath == attr2->aspath - && bgp_attr_get_community(attr1) - == bgp_attr_get_community(attr2) - && attr1->med == attr2->med - && attr1->local_pref == attr2->local_pref - && attr1->rmap_change_flags == attr2->rmap_change_flags) { + if (attr1->flag == attr2->flag && attr1->origin == attr2->origin && + attr1->nexthop.s_addr == attr2->nexthop.s_addr && + attr1->aspath == attr2->aspath && + bgp_attr_get_community(attr1) == bgp_attr_get_community(attr2) && + attr1->med == attr2->med && attr1->local_pref == attr2->local_pref && + attr1->rmap_change_flags == attr2->rmap_change_flags) { if (attr1->aggregator_as == attr2->aggregator_as && attr1->aggregator_addr.s_addr == attr2->aggregator_addr.s_addr && - attr1->weight == attr2->weight && - attr1->tag == attr2->tag && + attr1->weight == attr2->weight && attr1->tag == attr2->tag && attr1->label_index == attr2->label_index && attr1->mp_nexthop_len == attr2->mp_nexthop_len && bgp_attr_get_ecommunity(attr1) == @@ -835,10 +899,8 @@ bool attrhash_cmp(const void *p1, const void *p2) bgp_attr_get_ipv6_ecommunity(attr2) && bgp_attr_get_lcommunity(attr1) == bgp_attr_get_lcommunity(attr2) && - bgp_attr_get_cluster(attr1) == - bgp_attr_get_cluster(attr2) && - bgp_attr_get_transit(attr1) == - bgp_attr_get_transit(attr2) && + bgp_attr_get_cluster(attr1) == bgp_attr_get_cluster(attr2) && + bgp_attr_get_transit(attr1) == bgp_attr_get_transit(attr2) && bgp_attr_get_aigp_metric(attr1) == bgp_attr_get_aigp_metric(attr2) && attr1->rmap_table_id == attr2->rmap_table_id && @@ -870,8 +932,7 @@ bool attrhash_cmp(const void *p1, const void *p2) srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn) && attr1->srte_color == attr2->srte_color && attr1->nh_type == attr2->nh_type && - attr1->bh_type == attr2->bh_type && - attr1->otc == attr2->otc) + attr1->bh_type == attr2->bh_type && attr1->otc == attr2->otc) return true; } @@ -961,6 +1022,7 @@ struct attr *bgp_attr_intern(struct attr *attr) struct ecommunity *ipv6_ecomm = NULL; struct lcommunity *lcomm = NULL; struct community *comm = NULL; + struct bgp_route_evpn *bre = NULL; /* Intern referenced structure. */ if (attr->aspath) { @@ -1027,6 +1089,16 @@ struct attr *bgp_attr_intern(struct attr *attr) else attr->encap_subtlvs->refcnt++; } + + bre = bgp_attr_get_evpn_overlay(attr); + if (bre) { + if (!bre->refcnt) + bgp_attr_set_evpn_overlay(attr, + evpn_overlay_intern(bre)); + else + bre->refcnt++; + } + if (attr->srv6_l3vpn) { if (!attr->srv6_l3vpn->refcnt) attr->srv6_l3vpn = srv6_l3vpn_intern(attr->srv6_l3vpn); @@ -1072,14 +1144,14 @@ struct attr *bgp_attr_default_set(struct attr *attr, struct bgp *bgp, memset(attr, 0, sizeof(struct attr)); attr->origin = origin; - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)); attr->aspath = aspath_empty(bgp->asnotation); - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)); attr->weight = BGP_ATTR_DEFAULT_WEIGHT; attr->tag = 0; attr->label_index = BGP_INVALID_LABEL_INDEX; attr->label = MPLS_INVALID_LABEL; - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)); attr->mp_nexthop_len = IPV6_MAX_BYTELEN; attr->local_pref = bgp->default_local_pref; @@ -1101,18 +1173,18 @@ struct attr *bgp_attr_aggregate_intern( /* Origin attribute. */ attr.origin = origin; - attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN); + SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)); /* MED */ attr.med = 0; - attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); + SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)); /* AS path attribute. */ if (aspath) attr.aspath = aspath_intern(aspath); else attr.aspath = aspath_empty(bgp->asnotation); - attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH); + SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)); if (community) { uint32_t gshut = COMMUNITY_GSHUT; @@ -1142,8 +1214,8 @@ struct attr *bgp_attr_aggregate_intern( attr.weight = BGP_ATTR_DEFAULT_WEIGHT; attr.mp_nexthop_len = IPV6_MAX_BYTELEN; if (!aggregate->as_set || atomic_aggregate) - attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE); - attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR); + SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)); + SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)); if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) attr.aggregator_as = bgp->confed_id; else @@ -1161,7 +1233,7 @@ struct attr *bgp_attr_aggregate_intern( */ if (p->family == AF_INET) { /* Next hop attribute. */ - attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)); attr.mp_nexthop_len = IPV4_MAX_BYTELEN; } @@ -1216,6 +1288,7 @@ void bgp_attr_unintern_sub(struct attr *attr) struct lcommunity *lcomm = NULL; struct community *comm = NULL; struct transit *transit; + struct bgp_route_evpn *bre; /* aspath refcount shoud be decrement. */ aspath_unintern(&attr->aspath); @@ -1257,6 +1330,10 @@ void bgp_attr_unintern_sub(struct attr *attr) srv6_l3vpn_unintern(&attr->srv6_l3vpn); srv6_vpn_unintern(&attr->srv6_vpn); + + bre = bgp_attr_get_evpn_overlay(attr); + evpn_overlay_unintern(&bre); + bgp_attr_set_evpn_overlay(attr, NULL); } /* Free bgp attribute and aspath. */ @@ -1289,6 +1366,7 @@ void bgp_attr_flush(struct attr *attr) struct cluster_list *cluster; struct lcommunity *lcomm; struct community *comm; + struct bgp_route_evpn *bre; if (attr->aspath && !attr->aspath->refcnt) { aspath_free(attr->aspath); @@ -1347,6 +1425,11 @@ void bgp_attr_flush(struct attr *attr) bgp_attr_set_vnc_subtlvs(attr, NULL); } #endif + bre = bgp_attr_get_evpn_overlay(attr); + if (bre && !bre->refcnt) { + evpn_overlay_free(bre); + bgp_attr_set_evpn_overlay(attr, NULL); + } } /* Implement draft-scudder-idr-optional-transitive behaviour and @@ -1467,8 +1550,8 @@ bgp_attr_flags_diagnose(struct bgp_attr_parser_args *args, uint8_t real_flags = args->flags; const uint8_t attr_code = args->type; - desired_flags &= ~BGP_ATTR_FLAG_EXTLEN; - real_flags &= ~BGP_ATTR_FLAG_EXTLEN; + UNSET_FLAG(desired_flags, BGP_ATTR_FLAG_EXTLEN); + UNSET_FLAG(real_flags, BGP_ATTR_FLAG_EXTLEN); for (i = 0; i <= 2; i++) /* O,T,P, but not E */ if (CHECK_FLAG(desired_flags, attr_flag_str[i].key) != CHECK_FLAG(real_flags, attr_flag_str[i].key)) { @@ -1582,7 +1665,7 @@ static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) && CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)) SET_FLAG(mask, BGP_ATTR_FLAG_PARTIAL); - if ((flags & ~mask) == attr_flags_values[attr_code]) + if (CHECK_FLAG(flags, ~mask) == attr_flags_values[attr_code]) return false; bgp_attr_flags_diagnose(args, attr_flags_values[attr_code]); @@ -1624,7 +1707,7 @@ bgp_attr_origin(struct bgp_attr_parser_args *args) } /* Set oring attribute flag. */ - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)); return 0; } @@ -1674,7 +1757,7 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args) } /* Set aspath attribute flag. */ - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)); return BGP_ATTR_PARSE_PROCEED; } @@ -1778,7 +1861,7 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args, } /* Set aspath attribute flag. */ - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)); return BGP_ATTR_PARSE_PROCEED; } @@ -1828,7 +1911,7 @@ bgp_attr_nexthop(struct bgp_attr_parser_args *args) } attr->nexthop.s_addr = stream_get_ipv4(peer->curr); - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)); return BGP_ATTR_PARSE_PROCEED; } @@ -1851,7 +1934,7 @@ static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args) attr->med = stream_getl(peer->curr); - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)); return BGP_ATTR_PARSE_PROCEED; } @@ -1889,7 +1972,7 @@ bgp_attr_local_pref(struct bgp_attr_parser_args *args) STREAM_GETL(peer->curr, attr->local_pref); /* Set the local-pref flag. */ - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)); return BGP_ATTR_PARSE_PROCEED; @@ -1918,7 +2001,7 @@ static int bgp_attr_atomic(struct bgp_attr_parser_args *args) goto atomic_ignore; /* Set atomic aggregate flag. */ - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)); return BGP_ATTR_PARSE_PROCEED; @@ -1976,7 +2059,7 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args) zlog_debug("%s: attributes: %s", __func__, attr_str); } } else { - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)); } return BGP_ATTR_PARSE_PROCEED; @@ -2027,7 +2110,7 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args, zlog_debug("%s: attributes: %s", __func__, attr_str); } } else { - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)); } return BGP_ATTR_PARSE_PROCEED; @@ -2066,12 +2149,13 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr, * should not send them */ if (BGP_DEBUG(as4, AS4)) { - if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH))) + if (CHECK_FLAG(attr->flag, + (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))) zlog_debug("[AS4] %s %s AS4_PATH", peer->host, "AS4 capable peer, yet it sent"); - if (attr->flag - & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))) + if (CHECK_FLAG(attr->flag, + (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))) zlog_debug("[AS4] %s %s AS4_AGGREGATOR", peer->host, "AS4 capable peer, yet it sent"); @@ -2083,8 +2167,9 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr, /* We have a asn16 peer. First, look for AS4_AGGREGATOR * because that may override AS4_PATH */ - if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))) { - if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) { + if (CHECK_FLAG(attr->flag, (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))) { + if (CHECK_FLAG(attr->flag, + (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)))) { /* received both. * if the as_number in aggregator is not AS_TRANS, * then AS4_AGGREGATOR and AS4_PATH shall be ignored @@ -2124,13 +2209,14 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr, attr->aggregator_as = as4_aggregator; /* sweep it under the carpet and simulate a "good" * AGGREGATOR */ - attr->flag |= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)); + SET_FLAG(attr->flag, + (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))); } } /* need to reconcile NEW_AS_PATH and AS_PATH */ - if (!ignore_as4_path - && (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))) { + if (!ignore_as4_path && + (CHECK_FLAG(attr->flag, (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH))))) { newpath = aspath_reconcile_as4(attr->aspath, as4_path); if (!newpath) return BGP_ATTR_PARSE_ERROR; @@ -2215,7 +2301,7 @@ bgp_attr_originator_id(struct bgp_attr_parser_args *args) attr->originator_id.s_addr = stream_get_ipv4(peer->curr); - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)); return BGP_ATTR_PARSE_PROCEED; @@ -2473,7 +2559,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args, stream_forward_getp(s, nlri_len); - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)); return BGP_ATTR_PARSE_PROCEED; #undef LEN_LEFT @@ -2525,7 +2611,7 @@ int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args, stream_forward_getp(s, withdraw_len); - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI)); return BGP_ATTR_PARSE_PROCEED; } @@ -2575,7 +2661,6 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args) struct peer *const peer = args->peer; struct attr *const attr = args->attr; const bgp_size_t length = args->length; - uint8_t sticky = 0; bool proxy = false; struct ecommunity *ecomm; @@ -2586,10 +2671,9 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args) args->total); } - ecomm = ecommunity_parse( - stream_pnt(peer->curr), length, - CHECK_FLAG(peer->flags, - PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)); + ecomm = ecommunity_parse(stream_pnt(peer->curr), length, + CHECK_FLAG(peer->flags, + PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)); bgp_attr_set_ecommunity(attr, ecomm); /* XXX: fix ecommunity_parse to use stream API */ stream_forward_getp(peer->curr, length); @@ -2605,23 +2689,22 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args) attr->df_pref = bgp_attr_df_pref_from_ec(attr, &attr->df_alg); /* Extract MAC mobility sequence number, if any. */ - attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr, &sticky); - attr->sticky = sticky; + attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr); /* Check if this is a Gateway MAC-IP advertisement */ - attr->default_gw = bgp_attr_default_gw(attr); + bgp_attr_default_gw(attr); /* Handle scenario where router flag ecommunity is not * set but default gw ext community is present. * Use default gateway, set and propogate R-bit. */ - if (attr->default_gw) - attr->router_flag = 1; + if (CHECK_FLAG(attr->evpn_flags, ATTR_EVPN_FLAG_DEFAULT_GW)) + SET_FLAG(attr->evpn_flags, ATTR_EVPN_FLAG_ROUTER); /* Check EVPN Neighbor advertisement flags, R-bit */ - bgp_attr_evpn_na_flag(attr, &attr->router_flag, &proxy); + bgp_attr_evpn_na_flag(attr, &proxy); if (proxy) - attr->es_flags |= ATTR_ES_PROXY_ADVERT; + SET_FLAG(attr->es_flags, ATTR_ES_PROXY_ADVERT); /* Extract the Rmac, if any */ if (bgp_attr_rmac(attr, &attr->rmac)) { @@ -2692,6 +2775,9 @@ static int bgp_attr_encap(struct bgp_attr_parser_args *args) uint8_t type = args->type; uint8_t flag = args->flags; + if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type]) + goto encap_ignore; + if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS) || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) { zlog_err("Tunnel Encap attribute flag isn't optional and transitive %d", @@ -2810,7 +2896,14 @@ static int bgp_attr_encap(struct bgp_attr_parser_args *args) args->total); } - return 0; + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ENCAP)); + + return BGP_ATTR_PARSE_PROCEED; + +encap_ignore: + stream_forward_getp(peer->curr, length); + + return bgp_attr_ignore(peer, type); } @@ -3202,6 +3295,9 @@ enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args) size_t headersz = sizeof(type) + sizeof(length); size_t psid_parsed_length = 0; + if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type]) + goto prefix_sid_ignore; + while (STREAM_READABLE(peer->curr) > 0 && psid_parsed_length < args->length) { @@ -3249,6 +3345,11 @@ enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args) SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)); return BGP_ATTR_PARSE_PROCEED; + +prefix_sid_ignore: + stream_forward_getp(peer->curr, args->length); + + return bgp_attr_ignore(peer, args->type); } /* PMSI tunnel attribute (RFC 6514) @@ -3263,6 +3364,9 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args) uint8_t tnl_type; int attr_parse_len = 2 + BGP_LABEL_BYTES; + if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type]) + goto pmsi_tunnel_ignore; + /* Verify that the receiver is expecting "ingress replication" as we * can only support that. */ @@ -3291,7 +3395,7 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args) } } - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)); bgp_attr_set_pmsi_tnl_type(attr, tnl_type); stream_get(&attr->label, peer->curr, BGP_LABEL_BYTES); @@ -3299,6 +3403,11 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args) stream_forward_getp(peer->curr, length - attr_parse_len); return BGP_ATTR_PARSE_PROCEED; + +pmsi_tunnel_ignore: + stream_forward_getp(peer->curr, length); + + return bgp_attr_ignore(peer, args->type); } /* AIGP attribute (rfc7311) */ @@ -3369,7 +3478,7 @@ static enum bgp_attr_parse_ret bgp_attr_otc(struct bgp_attr_parser_args *args) args->total); } - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC); + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_OTC)); return BGP_ATTR_PARSE_PROCEED; @@ -3566,18 +3675,17 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr, * unused. They MUST be zero when sent and MUST be ignored when * received. */ - flag = 0xF0 & stream_getc(BGP_INPUT(peer)); + flag = CHECK_FLAG(0xF0, stream_getc(BGP_INPUT(peer))); type = stream_getc(BGP_INPUT(peer)); /* Check whether Extended-Length applies and is in bounds */ if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) { - flog_warn( - EC_BGP_EXT_ATTRIBUTE_TOO_SMALL, - "%s: Extended length set, but just %lu bytes of attr header", - peer->host, - (unsigned long)(endp - - stream_pnt(BGP_INPUT(peer)))); + flog_warn(EC_BGP_EXT_ATTRIBUTE_TOO_SMALL, + "%s: Extended length set, but just %lu bytes of attr header", + peer->host, + (unsigned long)(endp - + stream_pnt(BGP_INPUT(peer)))); if (peer->sort != BGP_PEER_EBGP) { bgp_notify_send(peer->connection, @@ -3924,7 +4032,7 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr, * Finally do the checks on the aspath we did not do yet * because we waited for a potentially synthesized aspath. */ - if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) { + if (CHECK_FLAG(attr->flag, (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))) { ret = bgp_attr_aspath_check(peer, attr); if (ret != BGP_ATTR_PARSE_PROCEED) goto done; @@ -4102,8 +4210,8 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi, case SAFI_MULTICAST: case SAFI_LABELED_UNICAST: case SAFI_EVPN: { - if (attr->mp_nexthop_len - == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { + if (attr->mp_nexthop_len == + BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { stream_putc(s, BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL); stream_put(s, &attr->mp_nexthop_global, @@ -4324,12 +4432,12 @@ static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN); stream_putc(s, attrtype); - stream_putw(s, attrlenfield & 0xffff); + stream_putw(s, CHECK_FLAG(attrlenfield, 0xffff)); } else { /* 1-octet length field */ stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL); stream_putc(s, attrtype); - stream_putc(s, attrlenfield & 0xff); + stream_putc(s, CHECK_FLAG(attrlenfield, 0xff)); } if (attrtype == BGP_ATTR_ENCAP) { @@ -4440,14 +4548,11 @@ static void bgp_packet_ecommunity_attribute(struct stream *s, struct peer *peer, } /* Make attribute packet. */ -bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, - struct stream *s, struct attr *attr, - struct bpacket_attr_vec_arr *vecarr, - struct prefix *p, afi_t afi, safi_t safi, - struct peer *from, struct prefix_rd *prd, - mpls_label_t *label, uint8_t num_labels, - bool addpath_capable, uint32_t addpath_tx_id, - struct bgp_path_info *bpi) +bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, struct stream *s, + struct attr *attr, struct bpacket_attr_vec_arr *vecarr, + struct prefix *p, afi_t afi, safi_t safi, struct peer *from, + struct prefix_rd *prd, mpls_label_t *label, uint8_t num_labels, + bool addpath_capable, uint32_t addpath_tx_id) { size_t cp; size_t aspath_sizep; @@ -4476,6 +4581,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, bgp_packet_mpattr_end(s, mpattrlen_pos); } + (void)peer_sort(peer); + /* Origin attribute. */ stream_putc(s, BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_ORIGIN); @@ -4569,15 +4676,15 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, && !peer_cap_enhe(peer, afi, safi)) { afi_t nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len); - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))) { stream_putc(s, BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_NEXT_HOP); bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s, attr); stream_putc(s, 4); stream_put_ipv4(s, attr->nexthop.s_addr); - } else if (peer_cap_enhe(from, afi, safi) - || (nh_afi == AFI_IP6)) { + } else if (peer_cap_enhe(from, afi, safi) || + (nh_afi == AFI_IP6)) { /* * Likely this is the case when an IPv4 prefix was * received with Extended Next-hop capability in this @@ -4599,8 +4706,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, } /* MED attribute. */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC) - || bgp->maxmed_active) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) || + bgp->maxmed_active) { stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC); stream_putc(s, 4); @@ -4618,14 +4725,14 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, } /* Atomic aggregate. */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))) { stream_putc(s, BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE); stream_putc(s, 0); } /* Aggregator. */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) { /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_AGGREGATOR); @@ -4656,8 +4763,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, } /* Community attribute. */ - if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) - && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) { + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) && + CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) { struct community *comm = NULL; comm = bgp_attr_get_community(attr); @@ -4681,8 +4788,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, * Large Community attribute. */ if (CHECK_FLAG(peer->af_flags[afi][safi], - PEER_FLAG_SEND_LARGE_COMMUNITY) - && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) { + PEER_FLAG_SEND_LARGE_COMMUNITY) && + CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) { if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) { stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS @@ -4712,7 +4819,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, stream_putc(s, BGP_ATTR_ORIGINATOR_ID); stream_putc(s, 4); - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) + if (CHECK_FLAG(attr->flag, + ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))) stream_put_in_addr(s, &attr->originator_id); else stream_put_in_addr(s, &from->remote_id); @@ -4725,7 +4833,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, stream_putc(s, cluster->length + 4); /* If this peer configuration's parent BGP has * cluster_id. */ - if (bgp->config & BGP_CONFIG_CLUSTER_ID) + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID)) stream_put_in_addr(s, &bgp->cluster_id); else stream_put_in_addr(s, &bgp->router_id); @@ -4734,7 +4842,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, stream_putc(s, 4); /* If this peer configuration's parent BGP has * cluster_id. */ - if (bgp->config & BGP_CONFIG_CLUSTER_ID) + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID)) stream_put_in_addr(s, &bgp->cluster_id); else stream_put_in_addr(s, &bgp->router_id); @@ -4902,7 +5010,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, } /* PMSI Tunnel */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL))) { stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_PMSI_TUNNEL); stream_putc(s, 9); // Length @@ -4915,7 +5023,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, } /* OTC */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_OTC))) { stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_OTC); stream_putc(s, 4); @@ -4923,10 +5031,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, } /* AIGP */ - if (bpi && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP) && - (CHECK_FLAG(peer->flags, PEER_FLAG_AIGP) || - peer->sub_sort == BGP_PEER_EBGP_OAD || - peer->sort != BGP_PEER_EBGP)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) && AIGP_TRANSMIT_ALLOWED(peer)) { /* At the moment only AIGP Metric TLV exists for AIGP * attribute. If more comes in, do not forget to update * attr_len variable to include new ones. @@ -4936,7 +5041,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); stream_putc(s, BGP_ATTR_AIGP); stream_putc(s, attr_len); - stream_put_bgp_aigp_tlv_metric(s, bpi); + stream_put_bgp_aigp_tlv_metric(s, attr->aigp_metric); } /* Unknown transit attribute. */ @@ -5006,6 +5111,7 @@ void bgp_attr_init(void) transit_init(); encap_init(); srv6_init(); + evpn_overlay_init(); } void bgp_attr_finish(void) @@ -5019,6 +5125,7 @@ void bgp_attr_finish(void) transit_finish(); encap_finish(); srv6_finish(); + evpn_overlay_finish(); } /* Make attribute packet. */ @@ -5064,7 +5171,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi, } /* MED attribute. */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))) { stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC); stream_putc(s, 4); @@ -5072,7 +5179,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi, } /* Local preference. */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) { stream_putc(s, BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_LOCAL_PREF); stream_putc(s, 4); @@ -5080,14 +5187,14 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi, } /* Atomic aggregate. */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))) { stream_putc(s, BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE); stream_putc(s, 0); } /* Aggregator. */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) { stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_AGGREGATOR); stream_putc(s, 8); @@ -5096,7 +5203,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi, } /* Community attribute. */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) { struct community *comm = NULL; comm = bgp_attr_get_community(attr); @@ -5107,9 +5214,8 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi, stream_putc(s, BGP_ATTR_COMMUNITIES); stream_putw(s, comm->size * 4); } else { - stream_putc(s, - BGP_ATTR_FLAG_OPTIONAL - | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | + BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_COMMUNITIES); stream_putc(s, comm->size * 4); } @@ -5117,7 +5223,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi, } /* Large Community attribute. */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) { if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) { stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS @@ -5126,9 +5232,8 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi, stream_putw(s, lcom_length(bgp_attr_get_lcommunity(attr))); } else { - stream_putc(s, - BGP_ATTR_FLAG_OPTIONAL - | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | + BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES); stream_putc(s, lcom_length(bgp_attr_get_lcommunity(attr))); @@ -5172,11 +5277,10 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi, } /* Prefix SID */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID))) { if (attr->label_index != BGP_INVALID_LABEL_INDEX) { - stream_putc(s, - BGP_ATTR_FLAG_OPTIONAL - | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | + BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_PREFIX_SID); stream_putc(s, 10); stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX); @@ -5188,7 +5292,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi, } /* OTC */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_OTC))) { stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_OTC); stream_putc(s, 4); @@ -5196,7 +5300,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi, } /* AIGP */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) { + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP))) { /* At the moment only AIGP Metric TLV exists for AIGP * attribute. If more comes in, do not forget to update * attr_len variable to include new ones. @@ -5206,7 +5310,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi, stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_AIGP); stream_putc(s, attr_len); - stream_put_bgp_aigp_tlv_metric(s, bpi); + stream_put_bgp_aigp_tlv_metric(s, attr->aigp_metric); } /* Return total size of attribute. */ |