diff options
Diffstat (limited to 'bgpd/bgp_attr.c')
| -rw-r--r-- | bgpd/bgp_attr.c | 162 |
1 files changed, 88 insertions, 74 deletions
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; - - for (i = 0; i < ecomm->size; i++) { - pnt = ecomm->val + (i * 8); - tbit = *pnt; + if (CHECK_FLAG(attr->flag, + ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) { + struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr); - if (CHECK_FLAG(tbit, - ECOMMUNITY_FLAG_NON_TRANSITIVE)) - continue; + bgp_packet_ecommunity_attribute(s, peer, ecomm, + transparent, + BGP_ATTR_EXT_COMMUNITIES); + } - ecom_tr_size++; - } + if (CHECK_FLAG(attr->flag, + ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES))) { + struct ecommunity *ecomm = + bgp_attr_get_ipv6_ecommunity(attr); - 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); } } |
