summaryrefslogtreecommitdiff
path: root/bgpd/bgp_attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_attr.c')
-rw-r--r--bgpd/bgp_attr.c162
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);
}
}