diff options
author | Paul Jakma <paul.jakma@sun.com> | 2007-05-04 20:15:47 +0000 |
---|---|---|
committer | Paul Jakma <paul.jakma@sun.com> | 2007-05-04 20:15:47 +0000 |
commit | fb982c25aa771b7c7425a3c3cce0a2cda0a715de (patch) | |
tree | 74aa4dc86b04365d90a1030682796421b0eff011 /bgpd/bgp_attr.c | |
parent | 5921ef9aae3b5d6ff8663298f649fb9d76594acd (diff) |
[bgpd] Trim memory usage of BGP routes
2007-05-03 Paul Jakma <paul.jakma@sun.com>
* bgp_route.h: (struct info) Move less frequently used
fields to a lazily allocated struct info_extra.
Export bgp_info_extra_get
* bgp_route.c: (bgp_info_extra_new) allocate extra
(bgp_info_extra_free) Free damp info and the info_extra.
(bgp_info_extra_get) Retrieve the info_extra of a struct
info, allocating as required.
(generally) adjust to use info->extra
* bgp_damp.c: (generally) use bgp_info_extra_get to access
dampinfo
* bgp_attr.h: Move rarely allocated attributes from struct attr
to a struct attr_extra, for a substantial saving in size of
struct attr.
* bgp_attr.c: (bgp_attr_extra_{new,free}), new, self-explanatory.
(bgp_attr_extra_get) Get the attr_extra for a given struct
attr, allocating it if needs be.
(bgp_attr_dup) Shallow copy the struct attr and its attr_extra.
(generally) adjust to know about attr->extra.
* bgp_debug.c: (bgp_dump_attr) ditto
* bgp_vty.c: (show_bgp_memory) print attr and info extra sizes.
* bgp_nexthop.c: (generally) adjust to know about attr->extra
and info->extra.
* bgp_{packet,routemap,snmp,zebra}.c: ditto
* lib/memtypes.c: Add MTYPE_ATTR_EXTRA and MTYPE_BGP_ROUTE_EXTRA
Diffstat (limited to 'bgpd/bgp_attr.c')
-rw-r--r-- | bgpd/bgp_attr.c | 385 |
1 files changed, 246 insertions, 139 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 28f01609..07c94130 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -282,9 +282,47 @@ transit_init () } /* Attribute hash routines. */ - struct hash *attrhash; +static struct attr_extra * +bgp_attr_extra_new (void) +{ + return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra)); +} + +void +bgp_attr_extra_free (struct attr *attr) +{ + if (attr->extra) + { + XFREE (MTYPE_ATTR_EXTRA, attr->extra); + attr->extra = NULL; + } +} + +struct attr_extra * +bgp_attr_extra_get (struct attr *attr) +{ + if (!attr->extra) + attr->extra = bgp_attr_extra_new(); + return attr->extra; +} + +/* Shallow copy of an attribute + * Though, not so shallow that it doesn't copy the contents + * of the attr_extra pointed to by 'extra' + */ +void +bgp_attr_dup (struct attr *new, struct attr *orig) +{ + *new = *orig; + if (orig->extra) + { + new->extra = bgp_attr_extra_new(); + *new->extra = *orig->extra; + } +} + unsigned long int attr_count (void) { @@ -307,33 +345,41 @@ attrhash_key_make (void *p) key += attr->nexthop.s_addr; key += attr->med; key += attr->local_pref; - key += attr->aggregator_as; - key += attr->aggregator_addr.s_addr; - key += attr->weight; - - key += attr->mp_nexthop_global_in.s_addr; + + if (attr->extra) + { + key += attr->extra->aggregator_as; + key += attr->extra->aggregator_addr.s_addr; + key += attr->extra->weight; + key += attr->extra->mp_nexthop_global_in.s_addr; + } + if (attr->aspath) key += aspath_key_make (attr->aspath); if (attr->community) key += community_hash_make (attr->community); - if (attr->ecommunity) - key += ecommunity_hash_make (attr->ecommunity); - if (attr->cluster) - key += cluster_hash_key_make (attr->cluster); - if (attr->transit) - key += transit_hash_key_make (attr->transit); + + if (attr->extra) + { + if (attr->extra->ecommunity) + key += ecommunity_hash_make (attr->extra->ecommunity); + if (attr->extra->cluster) + key += cluster_hash_key_make (attr->extra->cluster); + if (attr->extra->transit) + key += transit_hash_key_make (attr->extra->transit); #ifdef HAVE_IPV6 - { - int i; - - key += attr->mp_nexthop_len; - for (i = 0; i < 16; i++) - key += attr->mp_nexthop_global.s6_addr[i]; - for (i = 0; i < 16; i++) - key += attr->mp_nexthop_local.s6_addr[i]; - } + { + int i; + + key += attr->extra->mp_nexthop_len; + for (i = 0; i < 16; i++) + key += attr->extra->mp_nexthop_global.s6_addr[i]; + for (i = 0; i < 16; i++) + key += attr->extra->mp_nexthop_local.s6_addr[i]; + } #endif /* HAVE_IPV6 */ + } return key; } @@ -347,23 +393,33 @@ attrhash_cmp (void *p1, void *p2) if (attr1->flag == attr2->flag && attr1->origin == attr2->origin && attr1->nexthop.s_addr == attr2->nexthop.s_addr + && attr1->aspath == attr2->aspath + && attr1->community == attr2->community && attr1->med == attr2->med - && attr1->local_pref == attr2->local_pref - && attr1->aggregator_as == attr2->aggregator_as - && attr1->aggregator_addr.s_addr == attr2->aggregator_addr.s_addr - && attr1->weight == attr2->weight + && attr1->local_pref == attr2->local_pref) + { + struct attr_extra *ae1 = attr1->extra; + struct attr_extra *ae2 = attr2->extra; + + if (ae1 && ae2 + && ae1->aggregator_as == ae2->aggregator_as + && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr + && ae1->weight == ae2->weight #ifdef HAVE_IPV6 - && attr1->mp_nexthop_len == attr2->mp_nexthop_len - && IPV6_ADDR_SAME (&attr1->mp_nexthop_global, &attr2->mp_nexthop_global) - && IPV6_ADDR_SAME (&attr1->mp_nexthop_local, &attr2->mp_nexthop_local) + && ae1->mp_nexthop_len == ae2->mp_nexthop_len + && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global) + && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local) #endif /* HAVE_IPV6 */ - && IPV4_ADDR_SAME (&attr1->mp_nexthop_global_in, &attr2->mp_nexthop_global_in) - && attr1->aspath == attr2->aspath - && attr1->community == attr2->community - && attr1->ecommunity == attr2->ecommunity - && attr1->cluster == attr2->cluster - && attr1->transit == attr2->transit) - return 1; + && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in) + && ae1->ecommunity == ae2->ecommunity + && ae1->cluster == ae2->cluster + && ae1->transit == ae2->transit) + return 1; + else if (ae1 || ae2) + return 0; + /* neither attribute has extra attributes, so they're same */ + return 1; + } else return 0; } @@ -400,6 +456,11 @@ bgp_attr_hash_alloc (void *p) attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr)); *attr = *val; + if (val->extra) + { + attr->extra = bgp_attr_extra_new (); + *attr->extra = *val->extra; + } attr->refcnt = 0; return attr; } @@ -425,26 +486,31 @@ bgp_attr_intern (struct attr *attr) else attr->community->refcnt++; } - if (attr->ecommunity) + if (attr->extra) { - if (! attr->ecommunity->refcnt) - attr->ecommunity = ecommunity_intern (attr->ecommunity); - else - attr->ecommunity->refcnt++; - } - if (attr->cluster) - { - if (! attr->cluster->refcnt) - attr->cluster = cluster_intern (attr->cluster); - else - attr->cluster->refcnt++; - } - if (attr->transit) - { - if (! attr->transit->refcnt) - attr->transit = transit_intern (attr->transit); - else - attr->transit->refcnt++; + struct attr_extra *attre = attr->extra; + + if (attre->ecommunity) + { + if (! attre->ecommunity->refcnt) + attre->ecommunity = ecommunity_intern (attre->ecommunity); + else + attre->ecommunity->refcnt++; + } + if (attre->cluster) + { + if (! attre->cluster->refcnt) + attre->cluster = cluster_intern (attre->cluster); + else + attre->cluster->refcnt++; + } + if (attre->transit) + { + if (! attre->transit->refcnt) + attre->transit = transit_intern (attre->transit); + else + attre->transit->refcnt++; + } } find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc); @@ -459,15 +525,16 @@ struct attr * bgp_attr_default_set (struct attr *attr, u_char origin) { memset (attr, 0, sizeof (struct attr)); - + bgp_attr_extra_get (attr); + attr->origin = origin; attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN); attr->aspath = aspath_empty (); attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH); - attr->weight = BGP_ATTR_DEFAULT_WEIGHT; + attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT; attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); #ifdef HAVE_IPV6 - attr->mp_nexthop_len = IPV6_MAX_BYTELEN; + attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN; #endif return attr; @@ -480,10 +547,16 @@ bgp_attr_default_intern (u_char origin) { struct attr attr; struct attr *new; - + struct attr_extra *attre; + + memset (&attr, 0, sizeof (struct attr)); + attre = bgp_attr_extra_get (&attr); + bgp_attr_default_set(&attr, origin); new = bgp_attr_intern (&attr); + bgp_attr_extra_free (&attr); + aspath_unintern (new->aspath); return new; } @@ -495,9 +568,11 @@ bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin, { struct attr attr; struct attr *new; + struct attr_extra *attre; memset (&attr, 0, sizeof (struct attr)); - + attre = bgp_attr_extra_get (&attr); + /* Origin attribute. */ attr.origin = origin; attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN); @@ -518,20 +593,22 @@ bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin, attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES); } - attr.weight = BGP_ATTR_DEFAULT_WEIGHT; + attre->weight = BGP_ATTR_DEFAULT_WEIGHT; #ifdef HAVE_IPV6 - attr.mp_nexthop_len = IPV6_MAX_BYTELEN; + attre->mp_nexthop_len = IPV6_MAX_BYTELEN; #endif if (! as_set) attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE); attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR); if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION)) - attr.aggregator_as = bgp->confed_id; + attre->aggregator_as = bgp->confed_id; else - attr.aggregator_as = bgp->as; - attr.aggregator_addr = bgp->router_id; + attre->aggregator_as = bgp->as; + attre->aggregator_addr = bgp->router_id; new = bgp_attr_intern (&attr); + bgp_attr_extra_free (&attr); + aspath_unintern (new->aspath); return new; } @@ -543,23 +620,27 @@ bgp_attr_unintern (struct attr *attr) struct attr *ret; struct aspath *aspath; struct community *community; - struct ecommunity *ecommunity; - struct cluster_list *cluster; - struct transit *transit; + struct ecommunity *ecommunity = NULL; + struct cluster_list *cluster = NULL; + struct transit *transit = NULL; /* Decrement attribute reference. */ attr->refcnt--; aspath = attr->aspath; community = attr->community; - ecommunity = attr->ecommunity; - cluster = attr->cluster; - transit = attr->transit; + if (attr->extra) + { + ecommunity = attr->extra->ecommunity; + cluster = attr->extra->cluster; + transit = attr->extra->transit; + } /* If reference becomes zero then free attribute object. */ if (attr->refcnt == 0) { ret = hash_release (attrhash, attr); assert (ret != NULL); + bgp_attr_extra_free (attr); XFREE (MTYPE_ATTR, attr); } @@ -583,12 +664,16 @@ bgp_attr_flush (struct attr *attr) aspath_free (attr->aspath); if (attr->community && ! attr->community->refcnt) community_free (attr->community); - if (attr->ecommunity && ! attr->ecommunity->refcnt) - ecommunity_free (attr->ecommunity); - if (attr->cluster && ! attr->cluster->refcnt) - cluster_free (attr->cluster); - if (attr->transit && ! attr->transit->refcnt) - transit_free (attr->transit); + if (attr->extra) + { + struct attr_extra *attre = attr->extra; + if (attre->ecommunity && ! attre->ecommunity->refcnt) + ecommunity_free (attre->ecommunity); + if (attre->cluster && ! attre->cluster->refcnt) + cluster_free (attre->cluster); + if (attre->transit && ! attre->transit->refcnt) + transit_free (attre->transit); + } } /* Get origin attribute of the update message. */ @@ -851,6 +936,8 @@ static int bgp_attr_aggregator (struct peer *peer, bgp_size_t length, struct attr *attr, u_char flag) { + struct attr_extra *attre = bgp_attr_extra_get (attr); + if (length != 6) { zlog (peer->log, LOG_ERR, "Aggregator length is not 6 [%d]", length); @@ -860,8 +947,8 @@ bgp_attr_aggregator (struct peer *peer, bgp_size_t length, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); return -1; } - attr->aggregator_as = stream_getw (peer->ibuf); - attr->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf); + attre->aggregator_as = stream_getw (peer->ibuf); + attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf); /* Set atomic aggregate flag. */ attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR); @@ -903,7 +990,8 @@ bgp_attr_originator_id (struct peer *peer, bgp_size_t length, return -1; } - attr->originator_id.s_addr = stream_get_ipv4 (peer->ibuf); + (bgp_attr_extra_get (attr))->originator_id.s_addr + = stream_get_ipv4 (peer->ibuf); attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID); @@ -926,8 +1014,8 @@ bgp_attr_cluster_list (struct peer *peer, bgp_size_t length, return -1; } - attr->cluster = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), - length); + (bgp_attr_extra_get (attr))->cluster + = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length); stream_forward_getp (peer->ibuf, length);; @@ -947,6 +1035,7 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr, size_t start; int ret; struct stream *s; + struct attr_extra *attre = bgp_attr_extra_get(attr); /* Set end of packet. */ s = BGP_INPUT(peer); @@ -962,16 +1051,16 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr, safi = stream_getc (s); /* Get nexthop length. */ - attr->mp_nexthop_len = stream_getc (s); + attre->mp_nexthop_len = stream_getc (s); - if (STREAM_READABLE(s) < attr->mp_nexthop_len) + if (STREAM_READABLE(s) < attre->mp_nexthop_len) return -1; /* Nexthop length check. */ - switch (attr->mp_nexthop_len) + switch (attre->mp_nexthop_len) { case 4: - stream_get (&attr->mp_nexthop_global_in, s, 4); + stream_get (&attre->mp_nexthop_global_in, s, 4); break; case 12: { @@ -980,35 +1069,35 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr, rd_high = stream_getl (s); rd_low = stream_getl (s); - stream_get (&attr->mp_nexthop_global_in, s, 4); + stream_get (&attre->mp_nexthop_global_in, s, 4); } break; #ifdef HAVE_IPV6 case 16: - stream_get (&attr->mp_nexthop_global, s, 16); + stream_get (&attre->mp_nexthop_global, s, 16); break; case 32: - stream_get (&attr->mp_nexthop_global, s, 16); - stream_get (&attr->mp_nexthop_local, s, 16); - if (! IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_local)) + stream_get (&attre->mp_nexthop_global, s, 16); + stream_get (&attre->mp_nexthop_local, s, 16); + if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local)) { char buf1[INET6_ADDRSTRLEN]; char buf2[INET6_ADDRSTRLEN]; if (BGP_DEBUG (update, UPDATE_IN)) zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host, - inet_ntop (AF_INET6, &attr->mp_nexthop_global, + inet_ntop (AF_INET6, &attre->mp_nexthop_global, buf1, INET6_ADDRSTRLEN), - inet_ntop (AF_INET6, &attr->mp_nexthop_local, + inet_ntop (AF_INET6, &attre->mp_nexthop_local, buf2, INET6_ADDRSTRLEN)); - attr->mp_nexthop_len = 16; + attre->mp_nexthop_len = 16; } break; #endif /* HAVE_IPV6 */ default: zlog_info ("Wrong multiprotocol next hop length: %d", - attr->mp_nexthop_len); + attre->mp_nexthop_len); return -1; } @@ -1089,10 +1178,13 @@ bgp_attr_ext_communities (struct peer *peer, bgp_size_t length, struct attr *attr, u_char flag) { if (length == 0) - attr->ecommunity = NULL; + { + if (attr->extra) + attr->extra->ecommunity = NULL; + } else { - attr->ecommunity = + (bgp_attr_extra_get (attr))->ecommunity = ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length); stream_forward_getp (peer->ibuf, length); } @@ -1108,6 +1200,7 @@ bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag, { bgp_size_t total; struct transit *transit; + struct attr_extra *attre; if (BGP_DEBUG (normal, NORMAL)) zlog_debug ("%s Unknown attribute is received (type %d, length %d)", @@ -1149,13 +1242,13 @@ bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag, SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL); /* Store transitive attribute to the end of attr->transit. */ - if (! attr->transit) + if (! ((attre = bgp_attr_extra_get(attr))->transit) ) { - attr->transit = XMALLOC (MTYPE_TRANSIT, sizeof (struct transit)); - memset (attr->transit, 0, sizeof (struct transit)); + attre->transit = XMALLOC (MTYPE_TRANSIT, sizeof (struct transit)); + memset (attre->transit, 0, sizeof (struct transit)); } - transit = attr->transit; + transit = attre->transit; if (transit->val) transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val, @@ -1337,8 +1430,8 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, } /* Finally intern unknown attribute. */ - if (attr->transit) - attr->transit = transit_intern (attr->transit); + if (attr->extra && attr->extra->transit) + attr->extra->transit = transit_intern (attr->extra->transit); return 0; } @@ -1500,11 +1593,12 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, /* Aggregator. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)) { + assert (attr->extra); stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_AGGREGATOR); stream_putc (s, 6); - stream_putw (s, attr->aggregator_as); - stream_put_ipv4 (s, attr->aggregator_addr.s_addr); + stream_putw (s, attr->extra->aggregator_as); + stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr); } /* Community attribute. */ @@ -1531,13 +1625,15 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, && from && peer_sort (from) == BGP_PEER_IBGP) { + assert (attr->extra); + /* Originator ID. */ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_ORIGINATOR_ID); stream_putc (s, 4); if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) - stream_put_in_addr (s, &attr->originator_id); + stream_put_in_addr (s, &attr->extra->originator_id); else stream_put_in_addr (s, &from->remote_id); @@ -1545,15 +1641,16 @@ 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) + if (attr->extra->cluster) { - stream_putc (s, attr->cluster->length + 4); + stream_putc (s, attr->extra->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, attr->extra->cluster->list, + attr->extra->cluster->length); } else { @@ -1571,22 +1668,25 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, if (p->family == AF_INET6) { unsigned long sizep; - + struct attr_extra *attre = attr->extra; + + assert (attr->extra); + stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_MP_REACH_NLRI); sizep = stream_get_endp (s); - stream_putc (s, 0); /* Length of this attribute. */ + stream_putc (s, 0); /* Marker: Attribute length. */ stream_putw (s, AFI_IP6); /* AFI */ stream_putc (s, safi); /* SAFI */ - stream_putc (s, attr->mp_nexthop_len); + stream_putc (s, attre->mp_nexthop_len); - if (attr->mp_nexthop_len == 16) - stream_put (s, &attr->mp_nexthop_global, 16); - else if (attr->mp_nexthop_len == 32) + if (attre->mp_nexthop_len == 16) + stream_put (s, &attre->mp_nexthop_global, 16); + else if (attre->mp_nexthop_len == 32) { - stream_put (s, &attr->mp_nexthop_global, 16); - stream_put (s, &attr->mp_nexthop_local, 16); + stream_put (s, &attre->mp_nexthop_global, 16); + stream_put (s, &attre->mp_nexthop_local, 16); } /* SNPA */ @@ -1607,7 +1707,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_MP_REACH_NLRI); sizep = stream_get_endp (s); - stream_putc (s, 0); /* Length of this attribute. */ + stream_putc (s, 0); /* Marker: Attribute Length. */ stream_putw (s, AFI_IP); /* AFI */ stream_putc (s, SAFI_MULTICAST); /* SAFI */ @@ -1638,7 +1738,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, stream_putc (s, 12); stream_putl (s, 0); stream_putl (s, 0); - stream_put (s, &attr->mp_nexthop_global_in, 4); + stream_put (s, &attr->extra->mp_nexthop_global_in, 4); /* SNPA */ stream_putc (s, 0); @@ -1657,21 +1757,26 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES))) { - if (peer_sort (peer) == BGP_PEER_IBGP || peer_sort (peer) == BGP_PEER_CONFED) + struct attr_extra *attre = attr->extra; + + assert (attre); + + if (peer_sort (peer) == BGP_PEER_IBGP + || peer_sort (peer) == BGP_PEER_CONFED) { - if (attr->ecommunity->size * 8 > 255) + if (attre->ecommunity->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, attr->ecommunity->size * 8); + stream_putw (s, attre->ecommunity->size * 8); } else { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_EXT_COMMUNITIES); - stream_putc (s, attr->ecommunity->size * 8); + stream_putc (s, attre->ecommunity->size * 8); } - stream_put (s, attr->ecommunity->val, attr->ecommunity->size * 8); + stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8); } else { @@ -1680,9 +1785,9 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, int ecom_tr_size = 0; int i; - for (i = 0; i < attr->ecommunity->size; i++) + for (i = 0; i < attre->ecommunity->size; i++) { - pnt = attr->ecommunity->val + (i * 8); + pnt = attre->ecommunity->val + (i * 8); tbit = *pnt; if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE)) @@ -1706,9 +1811,9 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, stream_putc (s, ecom_tr_size * 8); } - for (i = 0; i < attr->ecommunity->size; i++) + for (i = 0; i < attre->ecommunity->size; i++) { - pnt = attr->ecommunity->val + (i * 8); + pnt = attre->ecommunity->val + (i * 8); tbit = *pnt; if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE)) @@ -1721,8 +1826,8 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, } /* Unknown transit attribute. */ - if (attr->transit) - stream_put (s, attr->transit->val, attr->transit->length); + if (attr->extra && attr->extra->transit) + stream_put (s, attr->extra->transit->val, attr->extra->transit->length); /* Return total size of attribute. */ return stream_get_endp (s) - cp; @@ -1869,11 +1974,12 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr, /* Aggregator. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)) { + assert (attr->extra); stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_AGGREGATOR); stream_putc (s, 6); - stream_putw (s, attr->aggregator_as); - stream_put_ipv4 (s, attr->aggregator_addr.s_addr); + stream_putw (s, attr->extra->aggregator_as); + stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr); } /* Community attribute. */ @@ -1896,25 +2002,26 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr, #ifdef HAVE_IPV6 /* Add a MP_NLRI attribute to dump the IPv6 next hop */ - if(prefix != NULL && prefix->family == AF_INET6 && - (attr->mp_nexthop_len == 16 || attr->mp_nexthop_len == 32) ) + if (prefix != NULL && prefix->family == AF_INET6 && attr->extra && + (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) ) { int sizep; - + struct attr_extra *attre = attr->extra; + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); stream_putc(s, BGP_ATTR_MP_REACH_NLRI); sizep = stream_get_endp (s); /* MP header */ - stream_putc (s, 0); /* Length of this attribute. */ + stream_putc (s, 0); /* Marker: Attribute length. */ stream_putw(s, AFI_IP6); /* AFI */ stream_putc(s, SAFI_UNICAST); /* SAFI */ /* Next hop */ - stream_putc(s, attr->mp_nexthop_len); - stream_put(s, &attr->mp_nexthop_global, 16); - if(attr->mp_nexthop_len == 32) - stream_put(s, &attr->mp_nexthop_local, 16); + stream_putc(s, attre->mp_nexthop_len); + stream_put(s, &attre->mp_nexthop_global, 16); + if (attre->mp_nexthop_len == 32) + stream_put(s, &attre->mp_nexthop_local, 16); /* SNPA */ stream_putc(s, 0); |