From fb982c25aa771b7c7425a3c3cce0a2cda0a715de Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Fri, 4 May 2007 20:15:47 +0000 Subject: [bgpd] Trim memory usage of BGP routes 2007-05-03 Paul Jakma * 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 --- bgpd/bgp_route.c | 466 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 302 insertions(+), 164 deletions(-) (limited to 'bgpd/bgp_route.c') diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index c33c596e..db0f3a74 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -89,6 +89,42 @@ bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix return rn; } +/* Allocate bgp_info_extra */ +static struct bgp_info_extra * +bgp_info_extra_new (void) +{ + struct bgp_info_extra *new; + new = XCALLOC (MTYPE_BGP_ROUTE_EXTRA, sizeof (struct bgp_info_extra)); + return new; +} + +static void +bgp_info_extra_free (struct bgp_info_extra **extra) +{ + if (extra && *extra) + { + if ((*extra)->damp_info) + bgp_damp_info_free ((*extra)->damp_info, 0); + + (*extra)->damp_info = NULL; + + XFREE (MTYPE_BGP_ROUTE_EXTRA, *extra); + + *extra = NULL; + } +} + +/* Get bgp_info extra information for the given bgp_info, lazy allocated + * if required. + */ +struct bgp_info_extra * +bgp_info_extra_get (struct bgp_info *ri) +{ + if (!ri->extra) + ri->extra = bgp_info_extra_new(); + return ri->extra; +} + /* Allocate new bgp info structure. */ static struct bgp_info * bgp_info_new () @@ -107,9 +143,8 @@ bgp_info_free (struct bgp_info *binfo) { if (binfo->attr) bgp_attr_unintern (binfo->attr); - - if (binfo->damp_info) - bgp_damp_info_free (binfo->damp_info, 0); + + bgp_info_extra_free (&binfo->extra); peer_unlock (binfo->peer); /* bgp_info peer reference */ @@ -292,6 +327,8 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) u_int32_t exist_pref; u_int32_t new_med; u_int32_t exist_med; + u_int32_t new_weight = 0; + u_int32_t exist_weight = 0; struct in_addr new_id; struct in_addr exist_id; int new_cluster; @@ -307,9 +344,13 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) return 1; /* 1. Weight check. */ - if (new->attr->weight > exist->attr->weight) + if (new->attr->extra) + new_weight = new->attr->extra->weight; + if (exist->attr->extra) + exist_weight = exist->attr->extra->weight; + if (new_weight > exist_weight) return 1; - if (new->attr->weight < exist->attr->weight) + if (new_weight < exist_weight) return 0; /* 2. Local preference check. */ @@ -418,10 +459,16 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) return 0; /* 8. IGP metric check. */ - if (new->igpmetric < exist->igpmetric) - return 1; - if (new->igpmetric > exist->igpmetric) - return 0; + if (new->extra || exist->extra) + { + uint32_t newm = (new->extra ? new->extra->igpmetric : 0); + uint32_t existm = (exist->extra ? exist->extra->igpmetric : 0); + + if (newm < existm) + return 1; + if (newm > existm) + return 0; + } /* 9. Maximum path check. */ @@ -441,11 +488,11 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) /* 11. Rourter-ID comparision. */ if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) - new_id.s_addr = new->attr->originator_id.s_addr; + new_id.s_addr = new->attr->extra->originator_id.s_addr; else new_id.s_addr = new->peer->remote_id.s_addr; if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) - exist_id.s_addr = exist->attr->originator_id.s_addr; + exist_id.s_addr = exist->attr->extra->originator_id.s_addr; else exist_id.s_addr = exist->peer->remote_id.s_addr; @@ -456,11 +503,11 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist) /* 12. Cluster length comparision. */ if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) - new_cluster = new->attr->cluster->length; + new_cluster = new->attr->extra->cluster->length; else new_cluster = 0; if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) - exist_cluster = exist->attr->cluster->length; + exist_cluster = exist->attr->extra->cluster->length; else exist_cluster = 0; @@ -556,14 +603,14 @@ bgp_cluster_filter (struct peer *peer, struct attr *attr) { struct in_addr cluster_id; - if (attr->cluster) + if (attr->extra && attr->extra->cluster) { if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID) cluster_id = peer->bgp->cluster_id; else cluster_id = peer->bgp->router_id; - if (cluster_loop_check (attr->cluster, cluster_id)) + if (cluster_loop_check (attr->extra->cluster, cluster_id)) return 1; } return 0; @@ -580,7 +627,8 @@ bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr, filter = &peer->filter[afi][safi]; /* Apply default weight value. */ - attr->weight = peer->weight; + if (peer->weight) + (bgp_attr_extra_get (attr))->weight = peer->weight; /* Route map apply. */ if (ROUTE_MAP_IN_NAME (filter)) @@ -651,7 +699,8 @@ bgp_import_modifier (struct peer *rsclient, struct peer *peer, filter = &rsclient->filter[afi][safi]; /* Apply default weight value. */ - attr->weight = peer->weight; + if (peer->weight) + (bgp_attr_extra_get (attr))->weight = peer->weight; /* Route map apply. */ if (ROUTE_MAP_IMPORT_NAME (filter)) @@ -716,7 +765,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, #endif /* Aggregate-address suppress check. */ - if (ri->suppress) + if (ri->extra && ri->extra->suppress) if (! UNSUPPRESS_MAP_NAME (filter)) return 0; @@ -746,7 +795,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, peer's id. */ if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)) { - if (IPV4_ADDR_SAME (&peer->remote_id, &ri->attr->originator_id)) + if (IPV4_ADDR_SAME (&peer->remote_id, &ri->attr->extra->originator_id)) { if (BGP_DEBUG (filter, FILTER)) zlog (peer->log, LOG_DEBUG, @@ -836,8 +885,8 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, } /* For modify attribute, copy it to temporary structure. */ - *attr = *ri->attr; - + bgp_attr_dup (attr, ri->attr); + /* If local-preference is not set. */ if ((peer_sort (peer) == BGP_PEER_IBGP || peer_sort (peer) == BGP_PEER_CONFED) @@ -862,7 +911,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, && ((p->family == AF_INET && attr->nexthop.s_addr) #ifdef HAVE_IPV6 || (p->family == AF_INET6 && - ! IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)) + ! IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global)) #endif /* HAVE_IPV6 */ ))) { @@ -872,7 +921,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, || (p->family == AF_INET && attr->nexthop.s_addr == 0) #ifdef HAVE_IPV6 || (p->family == AF_INET6 && - IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)) + IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global)) #endif /* HAVE_IPV6 */ || (peer_sort (peer) == BGP_PEER_EBGP && bgp_multiaccess_check_v4 (attr->nexthop, peer->host) == 0)) @@ -881,7 +930,8 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, if (p->family == AF_INET) { if (safi == SAFI_MPLS_VPN) - memcpy (&attr->mp_nexthop_global_in, &peer->nexthop.v4, IPV4_MAX_BYTELEN); + memcpy (&attr->extra->mp_nexthop_global_in, &peer->nexthop.v4, + IPV4_MAX_BYTELEN); else memcpy (&attr->nexthop, &peer->nexthop.v4, IPV4_MAX_BYTELEN); } @@ -890,9 +940,9 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, if (p->family == AF_INET6) { /* IPv6 global nexthop must be included. */ - memcpy (&attr->mp_nexthop_global, &peer->nexthop.v6_global, + memcpy (&attr->extra->mp_nexthop_global, &peer->nexthop.v6_global, IPV6_MAX_BYTELEN); - attr->mp_nexthop_len = 16; + attr->extra->mp_nexthop_len = 16; } #endif /* HAVE_IPV6 */ } @@ -904,35 +954,35 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, if ( CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) ) { - if ( IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_local) ) - attr->mp_nexthop_len=32; + if ( IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_local) ) + attr->extra->mp_nexthop_len=32; else - attr->mp_nexthop_len=16; + attr->extra->mp_nexthop_len=16; } /* Default nexthop_local treatment for non-RS-Clients */ else { /* Link-local address should not be transit to different peer. */ - attr->mp_nexthop_len = 16; + attr->extra->mp_nexthop_len = 16; /* Set link-local address for shared network peer. */ if (peer->shared_network && ! IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local)) { - memcpy (&attr->mp_nexthop_local, &peer->nexthop.v6_local, + memcpy (&attr->extra->mp_nexthop_local, &peer->nexthop.v6_local, IPV6_MAX_BYTELEN); - attr->mp_nexthop_len = 32; + attr->extra->mp_nexthop_len = 32; } /* If bgpd act as BGP-4+ route-reflector, do not send link-local address.*/ if (reflect) - attr->mp_nexthop_len = 16; + attr->extra->mp_nexthop_len = 16; /* If BGP-4+ link-local nexthop is not link-local nexthop. */ if (! IN6_IS_ADDR_LINKLOCAL (&peer->nexthop.v6_local)) - attr->mp_nexthop_len = 16; + attr->extra->mp_nexthop_len = 16; } } @@ -946,32 +996,36 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, /* Route map & unsuppress-map apply. */ if (ROUTE_MAP_OUT_NAME (filter) - || ri->suppress) + || (ri->extra && ri->extra->suppress) ) { struct bgp_info info; struct attr dummy_attr; info.peer = peer; info.attr = attr; + /* The route reflector is not allowed to modify the attributes of the reflected IBGP routes. */ if (peer_sort (from) == BGP_PEER_IBGP && peer_sort (peer) == BGP_PEER_IBGP) { - dummy_attr = *attr; - info.attr = &dummy_attr; + dummy_attr.extra = NULL; + bgp_attr_dup (&dummy_attr, attr); + info.attr = &dummy_attr; } SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT); - if (ri->suppress) + if (ri->extra && ri->extra->suppress) ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info); else ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info); peer->rmap_type = 0; - + + bgp_attr_extra_free (&dummy_attr); + if (ret == RMAP_DENYMATCH) { bgp_attr_flush (attr); @@ -1005,7 +1059,7 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, return 0; /* Aggregate-address suppress check. */ - if (ri->suppress) + if (ri->extra && ri->extra->suppress) if (! UNSUPPRESS_MAP_NAME (filter)) return 0; @@ -1025,7 +1079,8 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, peer's id. */ if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)) { - if (IPV4_ADDR_SAME (&rsclient->remote_id, &ri->attr->originator_id)) + if (IPV4_ADDR_SAME (&rsclient->remote_id, + &ri->attr->extra->originator_id)) { if (BGP_DEBUG (filter, FILTER)) zlog (rsclient->log, LOG_DEBUG, @@ -1078,7 +1133,7 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, if ((p->family == AF_INET && attr->nexthop.s_addr == 0) #ifdef HAVE_IPV6 || (p->family == AF_INET6 && - IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)) + IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global)) #endif /* HAVE_IPV6 */ ) { @@ -1086,7 +1141,7 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, if (p->family == AF_INET) { if (safi == SAFI_MPLS_VPN) - memcpy (&attr->mp_nexthop_global_in, &rsclient->nexthop.v4, + memcpy (&attr->extra->mp_nexthop_global_in, &rsclient->nexthop.v4, IPV4_MAX_BYTELEN); else memcpy (&attr->nexthop, &rsclient->nexthop.v4, IPV4_MAX_BYTELEN); @@ -1096,10 +1151,9 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, if (p->family == AF_INET6) { /* IPv6 global nexthop must be included. */ - memcpy (&attr->mp_nexthop_global, &rsclient->nexthop.v6_global, - + memcpy (&attr->extra->mp_nexthop_global, &rsclient->nexthop.v6_global, IPV6_MAX_BYTELEN); - attr->mp_nexthop_len = 16; + attr->extra->mp_nexthop_len = 16; } #endif /* HAVE_IPV6 */ } @@ -1107,14 +1161,18 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, #ifdef HAVE_IPV6 if (p->family == AF_INET6) { + struct attr_extra *attre = attr->extra; + + assert (attr->extra); + /* Left nexthop_local unchanged if so configured. */ if ( CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) ) { - if ( IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_local) ) - attr->mp_nexthop_len=32; + if ( IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local) ) + attre->mp_nexthop_len=32; else - attr->mp_nexthop_len=16; + attre->mp_nexthop_len=16; } /* Default nexthop_local treatment for RS-Clients */ @@ -1124,23 +1182,23 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, if (rsclient->shared_network && from->shared_network && (rsclient->ifindex == from->ifindex)) { - if ( IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_local) ) - attr->mp_nexthop_len=32; + if ( IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local) ) + attre->mp_nexthop_len=32; else - attr->mp_nexthop_len=16; + attre->mp_nexthop_len=16; } /* Set link-local address for shared network peer. */ else if (rsclient->shared_network && IN6_IS_ADDR_LINKLOCAL (&rsclient->nexthop.v6_local)) { - memcpy (&attr->mp_nexthop_local, &rsclient->nexthop.v6_local, + memcpy (&attre->mp_nexthop_local, &rsclient->nexthop.v6_local, IPV6_MAX_BYTELEN); - attr->mp_nexthop_len = 32; + attre->mp_nexthop_len = 32; } else - attr->mp_nexthop_len = 16; + attre->mp_nexthop_len = 16; } } @@ -1154,14 +1212,14 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, attr->aspath = aspath_empty_get (); /* Route map & unsuppress-map apply. */ - if (ROUTE_MAP_OUT_NAME (filter) || ri->suppress) + if (ROUTE_MAP_OUT_NAME (filter) || (ri->extra && ri->extra->suppress) ) { info.peer = rsclient; info.attr = attr; SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_OUT); - if (ri->suppress) + if (ri->extra && ri->extra->suppress) ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info); else ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info); @@ -1336,6 +1394,7 @@ bgp_process_rsclient (struct work_queue *wq, void *data) struct listnode *node, *nnode; struct peer *rsclient = rn->table->owner; + memset (&attr, 0, sizeof (struct attr)); /* Best path selection. */ bgp_best_selection (bgp, rn, &old_and_new); new_select = old_and_new.new; @@ -1378,6 +1437,8 @@ bgp_process_rsclient (struct work_queue *wq, void *data) if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED)) bgp_info_reap (rn, old_select); + bgp_attr_extra_free (&attr); + UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); return WQ_SUCCESS; } @@ -1398,6 +1459,8 @@ bgp_process_main (struct work_queue *wq, void *data) struct peer *peer; struct attr attr; + memset (&attr, 0, sizeof (struct attr)); + /* Best path selection. */ bgp_best_selection (bgp, rn, &old_and_new); old_select = old_and_new.old; @@ -1453,6 +1516,8 @@ bgp_process_main (struct work_queue *wq, void *data) if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED)) bgp_info_reap (rn, old_select); + bgp_attr_extra_free (&attr); + UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); return WQ_SUCCESS; } @@ -1663,7 +1728,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, { struct bgp_node *rn; struct bgp *bgp; - struct attr new_attr; + struct attr new_attr = { 0 }; struct attr *attr_new; struct attr *attr_new2; struct bgp_info *ri; @@ -1671,6 +1736,8 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, const char *reason; char buf[SU_ADDRSTRLEN]; + //memset (new_attr, 0, sizeof (struct attr)); + /* Do not insert announces from a rsclient into its own 'bgp_table'. */ if (peer == rsclient) return; @@ -1692,13 +1759,13 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, /* Route reflector originator ID check. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID) - && IPV4_ADDR_SAME (&rsclient->remote_id, &attr->originator_id)) + && IPV4_ADDR_SAME (&rsclient->remote_id, &attr->extra->originator_id)) { reason = "originator is us;"; goto filtered; } - - new_attr = *attr; + + bgp_attr_dup (&new_attr, attr); /* Apply export policy. */ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) && @@ -1709,7 +1776,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, } attr_new2 = bgp_attr_intern (&new_attr); - + /* Apply import policy. */ if (bgp_import_modifier (rsclient, peer, p, &new_attr, afi, safi) == RMAP_DENY) { @@ -1735,7 +1802,10 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, goto filtered; } } - + + /* new_attr isn't passed to any functions after here */ + bgp_attr_extra_free (&new_attr); + /* If the update is implicit withdraw. */ if (ri) { @@ -1781,7 +1851,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, /* Update MPLS tag. */ if (safi == SAFI_MPLS_VPN) - memcpy (ri->tag, tag, 3); + memcpy ((bgp_info_extra_get (ri))->tag, tag, 3); bgp_info_set_flag (rn, ri, BGP_INFO_VALID); @@ -1811,7 +1881,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, /* Update MPLS tag. */ if (safi == SAFI_MPLS_VPN) - memcpy (new->tag, tag, 3); + memcpy ((bgp_info_extra_get (new))->tag, tag, 3); bgp_info_set_flag (rn, new, BGP_INFO_VALID); @@ -1823,7 +1893,9 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, /* Process change. */ bgp_process (bgp, rn, afi, safi); - + + bgp_attr_extra_free (&new_attr); + return; filtered: @@ -1840,7 +1912,10 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, bgp_rib_remove (rn, ri, peer, afi, safi); bgp_unlock_node (rn); - + + if (new_attr.extra) + bgp_attr_extra_free (&new_attr); + return; } @@ -1885,7 +1960,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, int aspath_loop_count = 0; struct bgp_node *rn; struct bgp *bgp; - struct attr new_attr; + struct attr new_attr = { 0 }; struct attr *attr_new; struct bgp_info *ri; struct bgp_info *new; @@ -1894,7 +1969,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, bgp = peer->bgp; rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); - + /* When peer's soft reconfiguration enabled. Record input packet in Adj-RIBs-In. */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) @@ -1931,7 +2006,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* Route reflector originator ID check. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID) - && IPV4_ADDR_SAME (&bgp->router_id, &attr->originator_id)) + && IPV4_ADDR_SAME (&bgp->router_id, &attr->extra->originator_id)) { reason = "originator is us;"; goto filtered; @@ -1952,7 +2027,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, } /* Apply incoming route-map. */ - new_attr = *attr; + bgp_attr_dup (&new_attr, attr); if (bgp_input_modifier (peer, p, &new_attr, afi, safi) == RMAP_DENY) { @@ -2032,6 +2107,8 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, bgp_unlock_node (rn); bgp_attr_unintern (attr_new); + bgp_attr_extra_free (&new_attr); + return 0; } @@ -2081,7 +2158,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* Update MPLS tag. */ if (safi == SAFI_MPLS_VPN) - memcpy (ri->tag, tag, 3); + memcpy ((bgp_info_extra_get (ri))->tag, tag, 3); /* Update bgp route dampening information. */ if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) @@ -2092,6 +2169,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, if (ret == BGP_DAMP_SUPPRESSED) { bgp_unlock_node (rn); + bgp_attr_extra_free (&new_attr); return 0; } } @@ -2116,6 +2194,8 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, bgp_process (bgp, rn, afi, safi); bgp_unlock_node (rn); + bgp_attr_extra_free (&new_attr); + return 0; } @@ -2138,7 +2218,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* Update MPLS tag. */ if (safi == SAFI_MPLS_VPN) - memcpy (new->tag, tag, 3); + memcpy ((bgp_info_extra_get (new))->tag, tag, 3); /* Nexthop reachability check. */ if ((afi == AFI_IP || afi == AFI_IP6) @@ -2164,6 +2244,8 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* route_node_get lock */ bgp_unlock_node (rn); + bgp_attr_extra_free (&new_attr); + /* If maximum prefix count is configured and current prefix count exeed it. */ if (bgp_maximum_prefix_overflow (peer, afi, safi, 0)) @@ -2188,7 +2270,9 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, bgp_rib_remove (rn, ri, peer, afi, safi); bgp_unlock_node (rn); - + + bgp_attr_extra_free (&new_attr); + return 0; } @@ -2280,15 +2364,18 @@ bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw) { struct bgp *bgp; struct attr attr; - struct aspath *aspath; + struct aspath *aspath = { 0 }; struct prefix p; struct bgp_info binfo; struct peer *from; int ret = RMAP_DENYMATCH; - + + if (afi != AFI_IP || afi != AFI_IP6) + return; + bgp = peer->bgp; from = bgp->peer_self; - + bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); aspath = attr.aspath; attr.local_pref = bgp->default_local_pref; @@ -2299,26 +2386,30 @@ bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw) #ifdef HAVE_IPV6 else if (afi == AFI_IP6) { + struct attr_extra *ae; + attr.extra = NULL; + + ae = bgp_attr_extra_get (&attr); + attr.extra = ae; + str2prefix ("::/0", &p); /* IPv6 global nexthop must be included. */ - memcpy (&attr.mp_nexthop_global, &peer->nexthop.v6_global, + memcpy (&ae->mp_nexthop_global, &peer->nexthop.v6_global, IPV6_MAX_BYTELEN); - attr.mp_nexthop_len = 16; + ae->mp_nexthop_len = 16; /* If the peer is on shared nextwork and we have link-local nexthop set it. */ if (peer->shared_network && !IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local)) { - memcpy (&attr.mp_nexthop_local, &peer->nexthop.v6_local, + memcpy (&ae->mp_nexthop_local, &peer->nexthop.v6_local, IPV6_MAX_BYTELEN); - attr.mp_nexthop_len = 32; + ae->mp_nexthop_len = 32; } } #endif /* HAVE_IPV6 */ - else - return; if (peer->default_rmap[afi][safi].name) { @@ -2350,7 +2441,8 @@ bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw) SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE); bgp_default_update_send (peer, &attr, afi, safi, from); } - + + bgp_attr_extra_free (&attr); aspath_unintern (aspath); } @@ -2361,7 +2453,9 @@ bgp_announce_table (struct peer *peer, afi_t afi, safi_t safi, struct bgp_node *rn; struct bgp_info *ri; struct attr attr; - + + memset (&attr, 0, sizeof (struct attr)); + if (! table) table = (rsclient) ? peer->rib[afi][safi] : peer->bgp->rib[afi][safi]; @@ -2379,6 +2473,8 @@ bgp_announce_table (struct peer *peer, afi_t afi, safi_t safi, bgp_adj_out_set (rn, peer, &rn->p, &attr, afi, safi, ri); else bgp_adj_out_unset (rn, peer, &rn->p, afi, safi); + + bgp_attr_extra_free (&attr); } } @@ -3028,15 +3124,16 @@ bgp_static_withdraw_rsclient (struct bgp *bgp, struct peer *rsclient, static void bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, - struct bgp_static *bgp_static, afi_t afi, safi_t safi) + struct bgp_static *bgp_static, + afi_t afi, safi_t safi) { struct bgp_node *rn; struct bgp_info *ri; struct bgp_info *new; struct bgp_info info; - struct attr new_attr; struct attr *attr_new; - struct attr attr; + struct attr attr = {0 }; + struct attr new_attr = { .extra = 0 }; struct bgp *bgp; int ret; char buf[SU_ADDRSTRLEN]; @@ -3055,14 +3152,13 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, attr.med = bgp_static->igpmetric; attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); - new_attr = attr; - /* Apply network route-map for export to this rsclient. */ if (bgp_static->rmap.name) { + struct attr attr_tmp = attr; info.peer = rsclient; - info.attr = &new_attr; - + info.attr = &attr_tmp; + SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_EXPORT); SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_NETWORK); @@ -3073,25 +3169,27 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, if (ret == RMAP_DENYMATCH) { /* Free uninterned attribute. */ - bgp_attr_flush (&new_attr); + bgp_attr_flush (&attr_tmp); /* Unintern original. */ aspath_unintern (attr.aspath); bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi); - + bgp_attr_extra_free (&attr); + return; } - attr_new = bgp_attr_intern (&new_attr); + attr_new = bgp_attr_intern (&attr_tmp); } else attr_new = bgp_attr_intern (&attr); - + new_attr = *attr_new; - + SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); - if (bgp_import_modifier (rsclient, bgp->peer_self, p, &new_attr, afi, safi) == RMAP_DENY) -{ + if (bgp_import_modifier (rsclient, bgp->peer_self, p, &new_attr, afi, safi) + == RMAP_DENY) + { /* This BGP update is filtered. Log the reason then update BGP entry. */ if (BGP_DEBUG (update, UPDATE_IN)) zlog (rsclient->log, LOG_DEBUG, @@ -3103,11 +3201,12 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, bgp_attr_unintern (attr_new); aspath_unintern (attr.aspath); + bgp_attr_extra_free (&attr); bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi); return; - } + } bgp->peer_self->rmap_type = 0; @@ -3127,6 +3226,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, bgp_unlock_node (rn); bgp_attr_unintern (attr_new); aspath_unintern (attr.aspath); + bgp_attr_extra_free (&attr); return; } else @@ -3145,10 +3245,11 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, bgp_process (bgp, rn, afi, safi); bgp_unlock_node (rn); aspath_unintern (attr.aspath); + bgp_attr_extra_free (&attr); return; + } } -} - + /* Make new BGP info. */ new = bgp_info_new (); new->type = ZEBRA_ROUTE_BGP; @@ -3169,6 +3270,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p, /* Unintern original. */ aspath_unintern (attr.aspath); + bgp_attr_extra_free (&attr); } static void @@ -3179,8 +3281,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, struct bgp_info *ri; struct bgp_info *new; struct bgp_info info; - struct attr attr; - struct attr attr_tmp; + struct attr attr = { 0 }; struct attr *attr_new; int ret; @@ -3199,7 +3300,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, /* Apply route-map. */ if (bgp_static->rmap.name) { - attr_tmp = attr; + struct attr attr_tmp = attr; info.peer = bgp->peer_self; info.attr = &attr_tmp; @@ -3216,6 +3317,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, /* Unintern original. */ aspath_unintern (attr.aspath); + bgp_attr_extra_free (&attr); bgp_static_withdraw (bgp, p, afi, safi); return; } @@ -3237,6 +3339,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, bgp_unlock_node (rn); bgp_attr_unintern (attr_new); aspath_unintern (attr.aspath); + bgp_attr_extra_free (&attr); return; } else @@ -3258,6 +3361,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, bgp_process (bgp, rn, afi, safi); bgp_unlock_node (rn); aspath_unintern (attr.aspath); + bgp_attr_extra_free (&attr); return; } } @@ -3285,6 +3389,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p, /* Unintern original. */ aspath_unintern (attr.aspath); + bgp_attr_extra_free (&attr); } void @@ -3309,7 +3414,7 @@ bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi, { struct bgp_node *rn; struct bgp_info *new; - + rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); /* Make new BGP info. */ @@ -3320,7 +3425,8 @@ bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi, new->attr = bgp_attr_default_intern (BGP_ORIGIN_IGP); SET_FLAG (new->flags, BGP_INFO_VALID); new->uptime = time (NULL); - memcpy (new->tag, tag, 3); + new->extra = bgp_info_extra_new(); + memcpy (new->extra->tag, tag, 3); /* Aggregate address increment. */ bgp_aggregate_increment (bgp, p, new, afi, safi); @@ -4184,7 +4290,7 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, { if (aggregate->summary_only) { - ri->suppress++; + (bgp_info_extra_get (ri))->suppress++; bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); match++; } @@ -4230,7 +4336,7 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, aggregate->count++; if (aggregate->summary_only) - rinew->suppress++; + (bgp_info_extra_get (rinew))->suppress++; if (aggregate->as_set) { @@ -4387,7 +4493,7 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, route announcement. */ if (aggregate->summary_only) { - ri->suppress++; + (bgp_info_extra_get (ri))->suppress++; bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); match++; } @@ -4482,11 +4588,11 @@ bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi, if (ri->sub_type != BGP_ROUTE_AGGREGATE) { - if (aggregate->summary_only) + if (aggregate->summary_only && ri->extra) { - ri->suppress--; + ri->extra->suppress--; - if (ri->suppress == 0) + if (ri->extra->suppress == 0) { bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); match++; @@ -4496,7 +4602,7 @@ bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi, } } - /* If this node is suppressed, process the change. */ + /* If this node was suppressed, process the change. */ if (match) bgp_process (bgp, rn, afi, safi); } @@ -4968,8 +5074,8 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, struct bgp_info *bi; struct bgp_info info; struct bgp_node *bn; - struct attr attr; - struct attr attr_new; + struct attr attr = { 0 }; + struct attr attr_new = { 0 }; struct attr *new_attr; afi_t afi; int ret; @@ -4989,7 +5095,7 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, if (bgp->redist[afi][type]) { /* Copy attribute for modification. */ - attr_new = attr; + bgp_attr_dup (&attr_new, &attr); if (bgp->redist_metric_flag[afi][type]) attr_new.med = bgp->redist_metric[afi][type]; @@ -5011,17 +5117,22 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, { /* Free uninterned attribute. */ bgp_attr_flush (&attr_new); - + bgp_attr_extra_free (&attr_new); + /* Unintern original. */ aspath_unintern (attr.aspath); + bgp_attr_extra_free (&attr); bgp_redistribute_delete (p, type); return; } } - bn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, p, NULL); + bn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], + afi, SAFI_UNICAST, p, NULL); + new_attr = bgp_attr_intern (&attr_new); - + bgp_attr_extra_free (&attr_new); + for (bi = bn->info; bi; bi = bi->next) if (bi->peer == bgp->peer_self && bi->sub_type == BGP_ROUTE_REDISTRIBUTE) @@ -5034,6 +5145,7 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, { bgp_attr_unintern (new_attr); aspath_unintern (attr.aspath); + bgp_attr_extra_free (&attr); bgp_unlock_node (bn); return; } @@ -5056,6 +5168,7 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, bgp_process (bgp, bn, afi, SAFI_UNICAST); bgp_unlock_node (bn); aspath_unintern (attr.aspath); + bgp_attr_extra_free (&attr); return; } } @@ -5077,6 +5190,7 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop, /* Unintern original. */ aspath_unintern (attr.aspath); + bgp_attr_extra_free (&attr); } void @@ -5186,7 +5300,7 @@ route_vty_short_status_out (struct vty *vty, struct bgp_info *binfo) vty_out (vty, "R"); else if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE)) vty_out (vty, "S"); - else if (binfo->suppress) + else if (binfo->extra && binfo->extra->suppress) vty_out (vty, "s"); else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) vty_out (vty, "*"); @@ -5233,7 +5347,8 @@ route_vty_out (struct vty *vty, struct prefix *p, if (p->family == AF_INET) { if (safi == SAFI_MPLS_VPN) - vty_out (vty, "%-16s", inet_ntoa (attr->mp_nexthop_global_in)); + vty_out (vty, "%-16s", + inet_ntoa (attr->extra->mp_nexthop_global_in)); else vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); } @@ -5244,7 +5359,8 @@ route_vty_out (struct vty *vty, struct prefix *p, char buf[BUFSIZ]; len = vty_out (vty, "%s", - inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ)); + inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, + buf, BUFSIZ)); len = 16 - len; if (len < 1) vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " "); @@ -5263,7 +5379,7 @@ route_vty_out (struct vty *vty, struct prefix *p, else vty_out (vty, " "); - vty_out (vty, "%7u ",attr->weight); + vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0)); /* Print aspath */ if (attr->aspath) @@ -5294,7 +5410,8 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, if (p->family == AF_INET) { if (safi == SAFI_MPLS_VPN) - vty_out (vty, "%-16s", inet_ntoa (attr->mp_nexthop_global_in)); + vty_out (vty, "%-16s", + inet_ntoa (attr->extra->mp_nexthop_global_in)); else vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); } @@ -5303,9 +5420,12 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, { int len; char buf[BUFSIZ]; + + assert (attr->extra); len = vty_out (vty, "%s", - inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ)); + inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, + buf, BUFSIZ)); len = 16 - len; if (len < 1) vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " "); @@ -5323,9 +5443,9 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, vty_out (vty, "%7d", attr->local_pref); else vty_out (vty, " "); - - vty_out (vty, "%7d ",attr->weight); - + + vty_out (vty, "%7d ", (attr->extra ? attr->extra->weight : 0)); + /* Print aspath */ if (attr->aspath) aspath_print_vty (vty, "%s ", attr->aspath); @@ -5343,7 +5463,10 @@ route_vty_out_tag (struct vty *vty, struct prefix *p, { struct attr *attr; u_int32_t label = 0; - + + if (!binfo->extra) + return; + /* short status lead text */ route_vty_short_status_out (vty, binfo); @@ -5360,28 +5483,33 @@ route_vty_out_tag (struct vty *vty, struct prefix *p, if (p->family == AF_INET) { if (safi == SAFI_MPLS_VPN) - vty_out (vty, "%-16s", inet_ntoa (attr->mp_nexthop_global_in)); + vty_out (vty, "%-16s", + inet_ntoa (attr->extra->mp_nexthop_global_in)); else vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); } #ifdef HAVE_IPV6 else if (p->family == AF_INET6) { + assert (attr->extra); char buf[BUFSIZ]; char buf1[BUFSIZ]; - if (attr->mp_nexthop_len == 16) + if (attr->extra->mp_nexthop_len == 16) vty_out (vty, "%s", - inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ)); - else if (attr->mp_nexthop_len == 32) + inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, + buf, BUFSIZ)); + else if (attr->extra->mp_nexthop_len == 32) vty_out (vty, "%s(%s)", - inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ), - inet_ntop (AF_INET6, &attr->mp_nexthop_local, buf1, BUFSIZ)); + inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, + buf, BUFSIZ), + inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, + buf1, BUFSIZ)); } #endif /* HAVE_IPV6 */ } - label = decode_label (binfo->tag); + label = decode_label (binfo->extra->tag); vty_out (vty, "notag/%d", label); @@ -5439,8 +5567,11 @@ flap_route_vty_out (struct vty *vty, struct prefix *p, struct bgp_damp_info *bdi; char timebuf[BGP_UPTIME_LEN]; int len; - - bdi = binfo->damp_info; + + if (!binfo->extra) + return; + + bdi = binfo->extra->damp_info; /* short status lead text */ route_vty_short_status_out (vty, binfo); @@ -5516,8 +5647,9 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE)) vty_out (vty, ", (stale)"); if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))) - vty_out (vty, ", (aggregated by %d %s)", attr->aggregator_as, - inet_ntoa (attr->aggregator_addr)); + vty_out (vty, ", (aggregated by %d %s)", + attr->extra->aggregator_as, + inet_ntoa (attr->extra->aggregator_addr)); if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) vty_out (vty, ", (Received from a RR-client)"); if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) @@ -5532,14 +5664,15 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, if (p->family == AF_INET) { vty_out (vty, " %s", safi == SAFI_MPLS_VPN ? - inet_ntoa (attr->mp_nexthop_global_in) : + inet_ntoa (attr->extra->mp_nexthop_global_in) : inet_ntoa (attr->nexthop)); } #ifdef HAVE_IPV6 else { + assert (attr->extra); vty_out (vty, " %s", - inet_ntop (AF_INET6, &attr->mp_nexthop_global, + inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, buf, INET6_ADDRSTRLEN)); } #endif /* HAVE_IPV6 */ @@ -5554,11 +5687,11 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, { if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID)) vty_out (vty, " (inaccessible)"); - else if (binfo->igpmetric) - vty_out (vty, " (metric %d)", binfo->igpmetric); + else if (binfo->extra && binfo->extra->igpmetric) + vty_out (vty, " (metric %d)", binfo->extra->igpmetric); vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN)); if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) - vty_out (vty, " (%s)", inet_ntoa (attr->originator_id)); + vty_out (vty, " (%s)", inet_ntoa (attr->extra->originator_id)); else vty_out (vty, " (%s)", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ)); } @@ -5566,10 +5699,10 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, #ifdef HAVE_IPV6 /* display nexthop local */ - if (attr->mp_nexthop_len == 32) + if (attr->extra && attr->extra->mp_nexthop_len == 32) { vty_out (vty, " (%s)%s", - inet_ntop (AF_INET6, &attr->mp_nexthop_local, + inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, buf, INET6_ADDRSTRLEN), VTY_NEWLINE); } @@ -5586,8 +5719,8 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, else vty_out (vty, ", localpref %d", bgp->default_local_pref); - if (attr->weight != 0) - vty_out (vty, ", weight %d", attr->weight); + if (attr->extra && attr->extra->weight != 0) + vty_out (vty, ", weight %d", attr->extra->weight); if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) vty_out (vty, ", valid"); @@ -5622,27 +5755,30 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, /* Line 5 display Extended-community */ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) - vty_out (vty, " Extended Community: %s%s", attr->ecommunity->str, - VTY_NEWLINE); + vty_out (vty, " Extended Community: %s%s", + attr->extra->ecommunity->str, VTY_NEWLINE); /* Line 6 display Originator, Cluster-id */ if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) { + assert (attr->extra); if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) - vty_out (vty, " Originator: %s", inet_ntoa (attr->originator_id)); + vty_out (vty, " Originator: %s", + inet_ntoa (attr->extra->originator_id)); if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) { int i; vty_out (vty, ", Cluster list: "); - for (i = 0; i < attr->cluster->length / 4; i++) - vty_out (vty, "%s ", inet_ntoa (attr->cluster->list[i])); + for (i = 0; i < attr->extra->cluster->length / 4; i++) + vty_out (vty, "%s ", + inet_ntoa (attr->extra->cluster->list[i])); } vty_out (vty, "%s", VTY_NEWLINE); } - if (binfo->damp_info) + if (binfo->extra && binfo->extra->damp_info) bgp_damp_info_vty (vty, binfo); /* Line 7 display Uptime */ @@ -5720,7 +5856,7 @@ bgp_show_table (struct vty *vty, struct bgp_table *table, struct in_addr *router || type == bgp_show_type_dampend_paths || type == bgp_show_type_damp_neighbor) { - if (! ri->damp_info) + if (!(ri->extra && ri->extra->damp_info)) continue; } if (type == bgp_show_type_regexp @@ -5755,12 +5891,14 @@ bgp_show_table (struct vty *vty, struct bgp_table *table, struct in_addr *router struct attr dummy_attr; int ret; - dummy_attr = *ri->attr; + bgp_attr_dup (&dummy_attr, ri->attr); binfo.peer = ri->peer; binfo.attr = &dummy_attr; ret = route_map_apply (rmap, &rn->p, RMAP_BGP, &binfo); - + + bgp_attr_extra_free (&dummy_attr); + if (ret == RMAP_DENYMATCH) continue; } @@ -5964,7 +6102,7 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp, if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) { best = count; - if (ri->suppress) + if (ri->extra && ri->extra->suppress) suppress = 1; if (ri->attr->community != NULL) { @@ -10838,10 +10976,10 @@ bgp_clear_damp_route (struct vty *vty, const char *view_name, ri = rm->info; while (ri) { - if (ri->damp_info) + if (ri->extra && ri->extra->damp_info) { ri_temp = ri->next; - bgp_damp_info_free (ri->damp_info, 1); + bgp_damp_info_free (ri->extra->damp_info, 1); ri = ri_temp; } else @@ -10858,10 +10996,10 @@ bgp_clear_damp_route (struct vty *vty, const char *view_name, ri = rn->info; while (ri) { - if (ri->damp_info) + if (ri->extra && ri->extra->damp_info) { ri_temp = ri->next; - bgp_damp_info_free (ri->damp_info, 1); + bgp_damp_info_free (ri->extra->damp_info, 1); ri = ri_temp; } else -- cgit v1.2.1