diff options
Diffstat (limited to 'bgpd/bgp_attr.c')
| -rw-r--r-- | bgpd/bgp_attr.c | 262 |
1 files changed, 166 insertions, 96 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index b94e24e870..ce22e8404d 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -257,9 +257,12 @@ void bgp_attr_flush_encap(struct attr *attr) attr->encap_subtlvs = NULL; } #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs) { - encap_free(attr->vnc_subtlvs); - attr->vnc_subtlvs = NULL; + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + if (vnc_subtlvs) { + encap_free(vnc_subtlvs); + bgp_attr_set_vnc_subtlvs(attr, NULL); } #endif } @@ -403,7 +406,9 @@ static bool overlay_index_same(const struct attr *a1, const struct attr *a2) return false; if (!a1 && !a2) return true; - return !memcmp(&(a1->evpn_overlay), &(a2->evpn_overlay), + + return !memcmp(bgp_attr_get_evpn_overlay(a1), + bgp_attr_get_evpn_overlay(a2), sizeof(struct bgp_route_evpn)); } @@ -663,17 +668,19 @@ unsigned int attrhash_key_make(const void *p) MIX(lcommunity_hash_make(attr->lcommunity)); if (attr->ecommunity) MIX(ecommunity_hash_make(attr->ecommunity)); - if (attr->ipv6_ecommunity) - MIX(ecommunity_hash_make(attr->ipv6_ecommunity)); - if (attr->cluster) - MIX(cluster_hash_key_make(attr->cluster)); - if (attr->transit) - MIX(transit_hash_key_make(attr->transit)); + if (bgp_attr_get_ipv6_ecommunity(attr)) + MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr))); + if (bgp_attr_get_cluster(attr)) + MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr))); + if (bgp_attr_get_transit(attr)) + MIX(transit_hash_key_make(bgp_attr_get_transit(attr))); if (attr->encap_subtlvs) MIX(encap_hash_key_make(attr->encap_subtlvs)); #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - MIX(encap_hash_key_make(attr->vnc_subtlvs)); + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + if (vnc_subtlvs) + MIX(encap_hash_key_make(vnc_subtlvs)); #endif MIX(attr->mp_nexthop_len); key = jhash(attr->mp_nexthop_global.s6_addr, IPV6_MAX_BYTELEN, key); @@ -703,15 +710,19 @@ bool attrhash_cmp(const void *p1, const void *p2) && attr1->label_index == attr2->label_index && attr1->mp_nexthop_len == attr2->mp_nexthop_len && attr1->ecommunity == attr2->ecommunity - && attr1->ipv6_ecommunity == attr2->ipv6_ecommunity + && bgp_attr_get_ipv6_ecommunity(attr1) + == bgp_attr_get_ipv6_ecommunity(attr2) && attr1->lcommunity == attr2->lcommunity - && attr1->cluster == attr2->cluster - && attr1->transit == attr2->transit + && bgp_attr_get_cluster(attr1) + == bgp_attr_get_cluster(attr2) + && bgp_attr_get_transit(attr1) + == bgp_attr_get_transit(attr2) && attr1->rmap_table_id == attr2->rmap_table_id && (attr1->encap_tunneltype == attr2->encap_tunneltype) && encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs) #ifdef ENABLE_BGP_VNC - && encap_same(attr1->vnc_subtlvs, attr2->vnc_subtlvs) + && encap_same(bgp_attr_get_vnc_subtlvs(attr1), + bgp_attr_get_vnc_subtlvs(attr2)) #endif && IPV6_ADDR_SAME(&attr1->mp_nexthop_global, &attr2->mp_nexthop_global) @@ -797,9 +808,11 @@ static void *bgp_attr_hash_alloc(void *p) val->encap_subtlvs = NULL; } #ifdef ENABLE_BGP_VNC - if (val->vnc_subtlvs) { - val->vnc_subtlvs = NULL; - } + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(val); + + if (vnc_subtlvs) + bgp_attr_set_vnc_subtlvs(val, NULL); #endif if (val->srv6_l3vpn) val->srv6_l3vpn = NULL; @@ -814,6 +827,7 @@ static void *bgp_attr_hash_alloc(void *p) struct attr *bgp_attr_intern(struct attr *attr) { struct attr *find; + struct ecommunity *ecomm; /* Intern referenced strucutre. */ if (attr->aspath) { @@ -836,12 +850,13 @@ struct attr *bgp_attr_intern(struct attr *attr) attr->ecommunity->refcnt++; } - if (attr->ipv6_ecommunity) { - if (!attr->ipv6_ecommunity->refcnt) - attr->ipv6_ecommunity = - ecommunity_intern(attr->ipv6_ecommunity); + ecomm = bgp_attr_get_ipv6_ecommunity(attr); + if (ecomm) { + if (!ecomm->refcnt) + bgp_attr_set_ipv6_ecommunity(attr, + ecommunity_intern(ecomm)); else - attr->ipv6_ecommunity->refcnt++; + ecomm->refcnt++; } if (attr->lcommunity) { @@ -850,17 +865,23 @@ struct attr *bgp_attr_intern(struct attr *attr) else attr->lcommunity->refcnt++; } - if (attr->cluster) { - if (!attr->cluster->refcnt) - attr->cluster = cluster_intern(attr->cluster); + + struct cluster_list *cluster = bgp_attr_get_cluster(attr); + + if (cluster) { + if (!cluster->refcnt) + bgp_attr_set_cluster(attr, cluster_intern(cluster)); else - attr->cluster->refcnt++; + cluster->refcnt++; } - if (attr->transit) { - if (!attr->transit->refcnt) - attr->transit = transit_intern(attr->transit); + + struct transit *transit = bgp_attr_get_transit(attr); + + if (transit) { + if (!transit->refcnt) + bgp_attr_set_transit(attr, transit_intern(transit)); else - attr->transit->refcnt++; + transit->refcnt++; } if (attr->encap_subtlvs) { if (!attr->encap_subtlvs->refcnt) @@ -882,12 +903,16 @@ struct attr *bgp_attr_intern(struct attr *attr) attr->srv6_vpn->refcnt++; } #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs) { - if (!attr->vnc_subtlvs->refcnt) - attr->vnc_subtlvs = encap_intern(attr->vnc_subtlvs, - VNC_SUBTLV_TYPE); + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + if (vnc_subtlvs) { + if (!vnc_subtlvs->refcnt) + bgp_attr_set_vnc_subtlvs( + attr, + encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE)); else - attr->vnc_subtlvs->refcnt++; + vnc_subtlvs->refcnt++; } #endif @@ -1003,8 +1028,7 @@ struct attr *bgp_attr_aggregate_intern( SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE); - ret = route_map_apply(aggregate->rmap.map, p, RMAP_BGP, - &rmap_path); + ret = route_map_apply(aggregate->rmap.map, p, &rmap_path); bgp->peer_self->rmap_type = 0; @@ -1036,6 +1060,9 @@ struct attr *bgp_attr_aggregate_intern( /* Unintern just the sub-components of the attr, but not the attr */ void bgp_attr_unintern_sub(struct attr *attr) { + struct ecommunity *ecomm; + struct cluster_list *cluster; + /* aspath refcount shoud be decrement. */ if (attr->aspath) aspath_unintern(&attr->aspath); @@ -1045,31 +1072,43 @@ void bgp_attr_unintern_sub(struct attr *attr) community_unintern(&attr->community); UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)); - if (attr->ecommunity) - ecommunity_unintern(&attr->ecommunity); + ecommunity_unintern(&attr->ecommunity); UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)); - if (attr->ipv6_ecommunity) - ecommunity_unintern(&attr->ipv6_ecommunity); + ecomm = bgp_attr_get_ipv6_ecommunity(attr); + ecommunity_unintern(&ecomm); UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES)); + bgp_attr_set_ipv6_ecommunity(attr, NULL); if (attr->lcommunity) lcommunity_unintern(&attr->lcommunity); UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)); - if (attr->cluster) - cluster_unintern(&attr->cluster); + cluster = bgp_attr_get_cluster(attr); + if (cluster) { + cluster_unintern(&cluster); + bgp_attr_set_cluster(attr, cluster); + } UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)); - if (attr->transit) - transit_unintern(&attr->transit); + struct transit *transit = bgp_attr_get_transit(attr); + + if (transit) { + transit_unintern(&transit); + bgp_attr_set_transit(attr, transit); + } if (attr->encap_subtlvs) encap_unintern(&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE); #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - encap_unintern(&attr->vnc_subtlvs, VNC_SUBTLV_TYPE); + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + if (vnc_subtlvs) { + encap_unintern(&vnc_subtlvs, VNC_SUBTLV_TYPE); + bgp_attr_set_vnc_subtlvs(attr, vnc_subtlvs); + } #endif if (attr->srv6_l3vpn) @@ -1129,6 +1168,9 @@ void bgp_attr_unintern(struct attr **pattr) void bgp_attr_flush(struct attr *attr) { + struct ecommunity *ecomm; + struct cluster_list *cluster; + if (attr->aspath && !attr->aspath->refcnt) { aspath_free(attr->aspath); attr->aspath = NULL; @@ -1137,26 +1179,36 @@ void bgp_attr_flush(struct attr *attr) community_free(&attr->community); if (attr->ecommunity && !attr->ecommunity->refcnt) ecommunity_free(&attr->ecommunity); - if (attr->ipv6_ecommunity && !attr->ipv6_ecommunity->refcnt) - ecommunity_free(&attr->ipv6_ecommunity); + ecomm = bgp_attr_get_ipv6_ecommunity(attr); + if (ecomm && !ecomm->refcnt) + ecommunity_free(&ecomm); + bgp_attr_set_ipv6_ecommunity(attr, NULL); if (attr->lcommunity && !attr->lcommunity->refcnt) lcommunity_free(&attr->lcommunity); - if (attr->cluster && !attr->cluster->refcnt) { - cluster_free(attr->cluster); - attr->cluster = NULL; + + cluster = bgp_attr_get_cluster(attr); + if (cluster && !cluster->refcnt) { + cluster_free(cluster); + bgp_attr_set_cluster(attr, NULL); } - if (attr->transit && !attr->transit->refcnt) { - transit_free(attr->transit); - attr->transit = NULL; + + struct transit *transit = bgp_attr_get_transit(attr); + + if (transit && !transit->refcnt) { + transit_free(transit); + bgp_attr_set_transit(attr, NULL); } if (attr->encap_subtlvs && !attr->encap_subtlvs->refcnt) { encap_free(attr->encap_subtlvs); attr->encap_subtlvs = NULL; } #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs && !attr->vnc_subtlvs->refcnt) { - encap_free(attr->vnc_subtlvs); - attr->vnc_subtlvs = NULL; + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + if (vnc_subtlvs && !vnc_subtlvs->refcnt) { + encap_free(vnc_subtlvs); + bgp_attr_set_vnc_subtlvs(attr, NULL); } #endif } @@ -1929,8 +1981,9 @@ bgp_attr_cluster_list(struct bgp_attr_parser_args *args) args->total); } - attr->cluster = - cluster_parse((struct in_addr *)stream_pnt(peer->curr), length); + bgp_attr_set_cluster( + attr, cluster_parse((struct in_addr *)stream_pnt(peer->curr), + length)); /* XXX: Fix cluster_parse to use stream API and then remove this */ stream_forward_getp(peer->curr, length); @@ -2302,19 +2355,21 @@ bgp_attr_ipv6_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; + struct ecommunity *ipv6_ecomm = NULL; if (length == 0) { - attr->ipv6_ecommunity = NULL; + bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm); return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, args->total); } - attr->ipv6_ecommunity = - ecommunity_parse_ipv6(stream_pnt(peer->curr), length); + 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 */ stream_forward_getp(peer->curr, length); - if (!attr->ipv6_ecommunity) + if (!ipv6_ecomm) return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, args->total); @@ -2419,15 +2474,17 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */ #ifdef ENABLE_BGP_VNC } else { struct bgp_attr_encap_subtlv *stlv_last; - for (stlv_last = attr->vnc_subtlvs; + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + for (stlv_last = vnc_subtlvs; stlv_last && stlv_last->next; stlv_last = stlv_last->next) ; - if (stlv_last) { + if (stlv_last) stlv_last->next = tlv; - } else { - attr->vnc_subtlvs = tlv; - } + else + bgp_attr_set_vnc_subtlvs(attr, tlv); #endif } } @@ -2787,7 +2844,7 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args) } attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL); - attr->pmsi_tnl_type = tnl_type; + bgp_attr_set_pmsi_tnl_type(attr, tnl_type); stream_get(&attr->label, peer->curr, BGP_LABEL_BYTES); /* Forward read pointer of input stream. */ @@ -2837,10 +2894,9 @@ static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args) SET_FLAG(*startp, BGP_ATTR_FLAG_PARTIAL); /* Store transitive attribute to the end of attr->transit. */ - if (!attr->transit) - attr->transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit)); - - transit = attr->transit; + transit = bgp_attr_get_transit(attr); + if (!transit) + transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit)); if (transit->val) transit->val = XREALLOC(MTYPE_TRANSIT_VAL, transit->val, @@ -2850,6 +2906,7 @@ static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args) memcpy(transit->val + transit->length, startp, total); transit->length += total; + bgp_attr_set_transit(attr, transit); return BGP_ATTR_PARSE_PROCEED; } @@ -2922,6 +2979,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, struct aspath *as4_path = NULL; as_t as4_aggregator = 0; struct in_addr as4_aggregator_addr = {.s_addr = 0}; + struct transit *transit; /* Initialize bitmap. */ memset(seen, 0, BGP_ATTR_BITMAP_SIZE); @@ -3287,35 +3345,44 @@ done: aspath_unintern(&as4_path); } + transit = bgp_attr_get_transit(attr); if (ret != BGP_ATTR_PARSE_ERROR) { /* Finally intern unknown attribute. */ - if (attr->transit) - attr->transit = transit_intern(attr->transit); + if (transit) + bgp_attr_set_transit(attr, transit_intern(transit)); if (attr->encap_subtlvs) attr->encap_subtlvs = encap_intern(attr->encap_subtlvs, ENCAP_SUBTLV_TYPE); #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - attr->vnc_subtlvs = encap_intern(attr->vnc_subtlvs, - VNC_SUBTLV_TYPE); + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + if (vnc_subtlvs) + bgp_attr_set_vnc_subtlvs( + attr, + encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE)); #endif } else { - if (attr->transit) { - transit_free(attr->transit); - attr->transit = NULL; + if (transit) { + transit_free(transit); + bgp_attr_set_transit(attr, NULL); } bgp_attr_flush_encap(attr); }; /* Sanity checks */ - if (attr->transit) - assert(attr->transit->refcnt > 0); + transit = bgp_attr_get_transit(attr); + if (transit) + assert(transit->refcnt > 0); if (attr->encap_subtlvs) assert(attr->encap_subtlvs->refcnt > 0); #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - assert(attr->vnc_subtlvs->refcnt > 0); + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + if (vnc_subtlvs) + assert(vnc_subtlvs->refcnt > 0); #endif return ret; @@ -3567,7 +3634,7 @@ static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer, #ifdef ENABLE_BGP_VNC_ATTR case BGP_ATTR_VNC: attrname = "VNC"; - subtlvs = attr->vnc_subtlvs; + subtlvs = bgp_attr_get_vnc_subtlvs(attr); if (subtlvs == NULL) /* nothing to do */ return; attrlenfield = 0; /* no outer T + L */ @@ -3893,6 +3960,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, /* Route Reflector. */ if (peer->sort == BGP_PEER_IBGP && from && from->sort == BGP_PEER_IBGP) { + struct cluster_list *cluster = bgp_attr_get_cluster(attr); + /* Originator ID. */ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); stream_putc(s, BGP_ATTR_ORIGINATOR_ID); @@ -3907,16 +3976,15 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); stream_putc(s, BGP_ATTR_CLUSTER_LIST); - if (attr->cluster) { - stream_putc(s, attr->cluster->length + 4); + if (cluster) { + stream_putc(s, cluster->length + 4); /* If this peer configuration's parent BGP has * cluster_id. */ if (bgp->config & BGP_CONFIG_CLUSTER_ID) stream_put_in_addr(s, &bgp->cluster_id); else stream_put_in_addr(s, &bgp->router_id); - stream_put(s, attr->cluster->list, - attr->cluster->length); + stream_put(s, cluster->list, cluster->length); } else { stream_putc(s, 4); /* If this peer configuration's parent BGP has @@ -4112,7 +4180,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, stream_putc(s, BGP_ATTR_PMSI_TUNNEL); stream_putc(s, 9); // Length stream_putc(s, 0); // Flags - stream_putc(s, attr->pmsi_tnl_type); + stream_putc(s, bgp_attr_get_pmsi_tnl_type(attr)); stream_put(s, &(attr->label), BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI stream_put_ipv4(s, attr->nexthop.s_addr); @@ -4120,8 +4188,10 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, } /* Unknown transit attribute. */ - if (attr->transit) - stream_put(s, attr->transit->val, attr->transit->length); + struct transit *transit = bgp_attr_get_transit(attr); + + if (transit) + stream_put(s, transit->val, transit->length); /* Return total size of attribute. */ return stream_get_endp(s) - cp; |
