[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
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index c33c596..db0f3a7 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -89,6 +89,42 @@
   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 @@
 {
   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 @@
   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 @@
     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 @@
     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 @@
 
   /* 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 @@
 
   /* 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 @@
 {
   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 @@
   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 @@
   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 @@
 #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 @@
      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 @@
     }
 
   /* 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 @@
 	  && ((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 @@
 	   || (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 @@
       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 @@
       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 @@
       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 @@
 
   /* 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 @@
     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 @@
      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 @@
   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 @@
     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 @@
     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 @@
 #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 @@
           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 @@
     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 @@
   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 @@
   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 @@
   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 @@
   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 @@
 {
   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 @@
   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 @@
 
   /* 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 @@
     }
 
   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 @@
          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 @@
 
       /* 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 @@
 
   /* 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 @@
   
   /* Process change. */
   bgp_process (bgp, rn, afi, safi);
-
+  
+  bgp_attr_extra_free (&new_attr);
+  
   return;
 
  filtered: 
@@ -1840,7 +1912,10 @@
     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 @@
   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 = 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 @@
 
   /* 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 @@
     }
 
   /* 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_unlock_node (rn);
 	  bgp_attr_unintern (attr_new);
+	  bgp_attr_extra_free (&new_attr);
+	  
 	  return 0;
 	}
 
@@ -2081,7 +2158,7 @@
 
       /* 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 @@
 	  if (ret == BGP_DAMP_SUPPRESSED)
 	    {
 	      bgp_unlock_node (rn);
+	      bgp_attr_extra_free (&new_attr);
 	      return 0;
 	    }
 	}
@@ -2116,6 +2194,8 @@
 
       bgp_process (bgp, rn, afi, safi);
       bgp_unlock_node (rn);
+      bgp_attr_extra_free (&new_attr);
+      
       return 0;
     }
 
@@ -2138,7 +2218,7 @@
 
   /* 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 @@
   /* 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_rib_remove (rn, ri, peer, afi, safi);
 
   bgp_unlock_node (rn);
-
+  
+  bgp_attr_extra_free (&new_attr);
+  
   return 0;
 }
 
@@ -2280,15 +2364,18 @@
 {
   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 @@
 #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 @@
       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 @@
   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_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 @@
 
 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 @@
   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 @@
       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_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_unlock_node (rn);
           bgp_attr_unintern (attr_new);
           aspath_unintern (attr.aspath);
+          bgp_attr_extra_free (&attr);
           return;
        }
       else
@@ -3145,10 +3245,11 @@
           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 @@
 
   /* Unintern original. */
   aspath_unintern (attr.aspath);
+  bgp_attr_extra_free (&attr);
 }
 
 static void
@@ -3179,8 +3281,7 @@
   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 @@
   /* 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 @@
 
 	  /* Unintern original. */
 	  aspath_unintern (attr.aspath);
+	  bgp_attr_extra_free (&attr);
 	  bgp_static_withdraw (bgp, p, afi, safi);
 	  return;
 	}
@@ -3237,6 +3339,7 @@
 	  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_process (bgp, rn, afi, safi);
 	  bgp_unlock_node (rn);
 	  aspath_unintern (attr.aspath);
+	  bgp_attr_extra_free (&attr);
 	  return;
 	}
     }
@@ -3285,6 +3389,7 @@
 
   /* Unintern original. */
   aspath_unintern (attr.aspath);
+  bgp_attr_extra_free (&attr);
 }
 
 void
@@ -3309,7 +3414,7 @@
 {
   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 @@
   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 @@
 	      {
 		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 @@
       aggregate->count++;
       
       if (aggregate->summary_only)
-	rinew->suppress++;
+        (bgp_info_extra_get (rinew))->suppress++;
 
       if (aggregate->as_set)
 	{
@@ -4387,7 +4493,7 @@
 		   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 @@
 
 	    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 @@
 	      }
 	  }
 
-	/* 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 @@
   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 @@
       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 @@
 		{
 		  /* 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_attr_unintern (new_attr);
  		  aspath_unintern (attr.aspath);
+ 		  bgp_attr_extra_free (&attr);
  		  bgp_unlock_node (bn);
  		  return;
  		}
@@ -5056,6 +5168,7 @@
  		  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 @@
 
   /* Unintern original. */
   aspath_unintern (attr.aspath);
+  bgp_attr_extra_free (&attr);
 }
 
 void
@@ -5186,7 +5300,7 @@
     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 @@
       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 @@
 	  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 @@
       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 @@
       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 @@
         {
           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 @@
 	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 @@
 {
   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 @@
       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 @@
   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 @@
       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 @@
       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 @@
 	{
 	  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 @@
 
 #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 @@
       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 @@
 	  
       /* 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 @@
 		|| 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 @@
 		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 @@
       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 @@
 		  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 @@
 	    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