]> git.puffer.fish Git - mirror/frr.git/commitdiff
[bgpd] Trim memory usage of BGP routes
authorPaul Jakma <paul.jakma@sun.com>
Fri, 4 May 2007 20:15:47 +0000 (20:15 +0000)
committerPaul Jakma <paul.jakma@sun.com>
Fri, 4 May 2007 20:15:47 +0000 (20:15 +0000)
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

15 files changed:
bgpd/ChangeLog
bgpd/bgp_attr.c
bgpd/bgp_attr.h
bgpd/bgp_damp.c
bgpd/bgp_debug.c
bgpd/bgp_nexthop.c
bgpd/bgp_packet.c
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_routemap.c
bgpd/bgp_snmp.c
bgpd/bgp_vty.c
bgpd/bgp_zebra.c
lib/ChangeLog
lib/memtypes.c

index d5822facf528e043f22f1b48a8866dbb5e1cd470..ed6064945de1eb2eeffd22ce77a2ff4e64e5f795 100644 (file)
@@ -1,5 +1,30 @@
-2007-04-22 Sebastien Tandel <sebastien@tandel.be>
+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
 
+2007-04-22 Sebastien Tandel <sebastien@tandel.be>
        * bgp_advertise.c : (baa_hash_alloc, baa_hash_key, baa_hash_cmp)
          conforms to quagga hash API. Defines _hash_[alloc|key|cmp] with
          void * arguments as defined by the API.
index 28f01609cb1c8f7c8a4403382f98911fb5ae3534..07c941300fc5edf26ec71fd972f1762ef163c641 100644 (file)
@@ -282,9 +282,47 @@ transit_init ()
 }
 \f
 /* 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);
index 0734bc270314d6999f9ed9ad803748b8d1ad944f..ac14947f12dae51fc9c96715cd45b1716cc060e5 100644 (file)
@@ -45,24 +45,20 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
 /* BGP attribute header must bigger than 2. */
 #define BGP_ATTR_MIN_LEN        2       /* Attribute flag and type. */
-
 #define BGP_ATTR_DEFAULT_WEIGHT 32768
 
-/* BGP attribute structure. */
-struct attr
+/* Additional/uncommon BGP attributes.
+ * lazily allocated as and when a struct attr
+ * requires it.
+ */
+struct attr_extra
 {
-  /* Attributes. */
+  /* Multi-Protocol Nexthop, AFI IPv6 */
 #ifdef HAVE_IPV6
   struct in6_addr mp_nexthop_global;
   struct in6_addr mp_nexthop_local;
 #endif /* HAVE_IPV6 */
 
-  /* AS Path structure */
-  struct aspath *aspath;
-
-  /* Community structure */
-  struct community *community; 
-
   /* Extended Communities attribute. */
   struct ecommunity *ecommunity;
   
@@ -72,6 +68,37 @@ struct attr
   /* Unknown transitive attribute. */
   struct transit *transit;
 
+  struct in_addr mp_nexthop_global_in;
+  struct in_addr mp_nexthop_local_in;
+  
+  /* Aggregator Router ID attribute */
+  struct in_addr aggregator_addr;
+  
+  /* Route Reflector Originator attribute */
+  struct in_addr originator_id;
+  
+  /* Local weight, not actually an attribute */
+  u_int32_t weight;
+  
+  /* Aggregator ASN */
+  as_t aggregator_as;
+  
+  /* MP Nexthop length */
+  u_char mp_nexthop_len;
+};
+
+/* BGP core attribute structure. */
+struct attr
+{
+  /* AS Path structure */
+  struct aspath *aspath;
+
+  /* Community structure */
+  struct community *community; 
+  
+  /* Lazily allocated pointer to extra attributes */
+  struct attr_extra *extra;
+  
   /* Reference count of this attribute. */
   unsigned long refcnt;
 
@@ -82,14 +109,9 @@ struct attr
   struct in_addr nexthop;
   u_int32_t med;
   u_int32_t local_pref;
-  struct in_addr aggregator_addr;
-  struct in_addr originator_id;
-  struct in_addr mp_nexthop_global_in;
-  struct in_addr mp_nexthop_local_in;
-  u_int32_t weight;
-  as_t aggregator_as;
+
+  /* Path origin attribute */
   u_char origin;
-  u_char mp_nexthop_len;
 };
 
 /* Router Reflector related structure. */
@@ -115,6 +137,9 @@ extern void bgp_attr_init (void);
 extern int bgp_attr_parse (struct peer *, struct attr *, bgp_size_t,
                    struct bgp_nlri *, struct bgp_nlri *);
 extern int bgp_attr_check (struct peer *, struct attr *);
+extern struct attr_extra *bgp_attr_extra_get (struct attr *);
+extern void bgp_attr_extra_free (struct attr *);
+extern void bgp_attr_dup (struct attr *, struct attr *);
 extern struct attr *bgp_attr_intern (struct attr *attr);
 extern void bgp_attr_unintern (struct attr *);
 extern void bgp_attr_flush (struct attr *);
index 8ba39b651c4487812be19c7377e42b2992592241..5a7c9aaaac9fa052f0c939a6cab2ea7c76d75f8d 100644 (file)
@@ -178,14 +178,15 @@ bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
                   afi_t afi, safi_t safi, int attr_change)
 {
   time_t t_now;
-  struct bgp_damp_info *bdi;
+  struct bgp_damp_info *bdi = NULL;
   double last_penalty = 0;
   
   t_now = time (NULL);
 
   /* Processing Unreachable Messages.  */
-  bdi = binfo->damp_info;
-
+  if (binfo->extra)
+    bdi = binfo->extra->damp_info;
+  
   if (bdi == NULL)
     {
       /* If there is no previous stability history. */
@@ -205,7 +206,7 @@ bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
       bdi->index = -1;
       bdi->afi = afi;
       bdi->safi = safi;
-      binfo->damp_info = bdi;
+      (bgp_info_extra_get (binfo))->damp_info = bdi;
       BGP_DAMP_LIST_ADD (damp, bdi);
     }
   else
@@ -264,8 +265,7 @@ bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn,
   struct bgp_damp_info *bdi;
   int status;
 
-  bdi = binfo->damp_info;
-  if (! bdi)
+  if (!binfo->extra || !((bdi = binfo->extra->damp_info)))
     return BGP_DAMP_USED;
 
   t_now = time (NULL);
@@ -303,9 +303,11 @@ bgp_damp_scan (struct bgp_info *binfo, afi_t afi, safi_t safi)
 {
   time_t t_now, t_diff;
   struct bgp_damp_info *bdi;
-
+  
+  assert (binfo->extra && binfo->extra->damp_info);
+  
   t_now = time (NULL);
-  bdi = binfo->damp_info;
+  bdi = binfo->extra->damp_info;
  
   if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
     {
@@ -353,7 +355,7 @@ bgp_damp_info_free (struct bgp_damp_info *bdi, int withdraw)
     return;
 
   binfo = bdi->binfo;
-  binfo->damp_info = NULL;
+  binfo->extra->damp_info = NULL;
 
   if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
     bgp_reuse_list_delete (bdi);
@@ -590,8 +592,11 @@ bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo)
   char timebuf[BGP_UPTIME_LEN];
   int penalty;
 
+  if (!binfo->extra)
+    return;
+  
   /* BGP dampening information.  */
-  bdi = binfo->damp_info;
+  bdi = binfo->extra->damp_info;
 
   /* If dampening is not enabled or there is no dampening information,
      return immediately.  */
@@ -622,9 +627,12 @@ bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo)
   time_t t_now, t_diff;
   char timebuf[BGP_UPTIME_LEN];
   int penalty;
-
+  
+  if (!binfo->extra)
+    return NULL;
+  
   /* BGP dampening information.  */
-  bdi = binfo->damp_info;
+  bdi = binfo->extra->damp_info;
 
   /* If dampening is not enabled or there is no dampening information,
      return immediately.  */
index 1986b35b3c3dd5f2e60cb898631526e218a9f66b..60284a2d8c4cd6dd382c670dc96d2b439fdd5703 100644 (file)
@@ -176,20 +176,22 @@ bgp_dump_attr (struct peer *peer, struct attr *attr, char *buf, size_t size)
              bgp_origin_str[attr->origin]);
 
 #ifdef HAVE_IPV6
-  {
-    char addrbuf[BUFSIZ];
-
-    /* Add MP case. */
-    if (attr->mp_nexthop_len == 16 || attr->mp_nexthop_len == 32)
-      snprintf (buf + strlen (buf), size - strlen (buf), ", mp_nexthop %s",
-               inet_ntop (AF_INET6, &attr->mp_nexthop_global, 
-                          addrbuf, BUFSIZ));
-
-    if (attr->mp_nexthop_len == 32)
-      snprintf (buf + strlen (buf), size - strlen (buf), "(%s)",
-               inet_ntop (AF_INET6, &attr->mp_nexthop_local, 
-                          addrbuf, BUFSIZ));
-  }
+  if (attr->extra)
+    {
+      char addrbuf[BUFSIZ];
+
+      /* Add MP case. */
+      if (attr->extra->mp_nexthop_len == 16 
+          || attr->extra->mp_nexthop_len == 32)
+        snprintf (buf + strlen (buf), size - strlen (buf), ", mp_nexthop %s",
+                  inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, 
+                             addrbuf, BUFSIZ));
+
+      if (attr->extra->mp_nexthop_len == 32)
+        snprintf (buf + strlen (buf), size - strlen (buf), "(%s)",
+                  inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, 
+                             addrbuf, BUFSIZ));
+    }
 #endif /* HAVE_IPV6 */
 
   if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
@@ -209,20 +211,21 @@ bgp_dump_attr (struct peer *peer, struct attr *attr, char *buf, size_t size)
 
   if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)))
     snprintf (buf + strlen (buf), size - strlen (buf), ", aggregated by %d %s",
-             attr->aggregator_as, inet_ntoa (attr->aggregator_addr));
+             attr->extra->aggregator_as,
+             inet_ntoa (attr->extra->aggregator_addr));
 
   if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)))
     snprintf (buf + strlen (buf), size - strlen (buf), ", originator %s",
-             inet_ntoa (attr->originator_id));
+             inet_ntoa (attr->extra->originator_id));
 
   if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST)))
     {
       int i;
 
       snprintf (buf + strlen (buf), size - strlen (buf), ", clusterlist");
-      for (i = 0; i < attr->cluster->length / 4; i++)
+      for (i = 0; i < attr->extra->cluster->length / 4; i++)
        snprintf (buf + strlen (buf), size - strlen (buf), " %s",
-                 inet_ntoa (attr->cluster->list[i]));
+                 inet_ntoa (attr->extra->cluster->list[i]));
     }
 
   if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))) 
index 50ae74e45582d263efda1e441eeff6ee9e3f46cc..4dd5d946340e6cff3c64325b3cf2ab04943d2677 100644 (file)
@@ -196,15 +196,15 @@ bgp_nexthop_check_ebgp (afi_t afi, struct attr *attr)
 #ifdef HAVE_IPV6
   else if (afi == AFI_IP6)
     {
-      if (attr->mp_nexthop_len == 32)
+      if (attr->extra->mp_nexthop_len == 32)
        return 1;
-      else if (attr->mp_nexthop_len == 16)
+      else if (attr->extra->mp_nexthop_len == 16)
        {
-         if (IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_global))
+         if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
            return 1;
 
          rn = bgp_node_match_ipv6 (bgp_connected_table[AFI_IP6],
-                                     &attr->mp_nexthop_global);
+                                     &attr->extra->mp_nexthop_global);
          if (rn)
            {
              bgp_unlock_node (rn);
@@ -230,21 +230,22 @@ bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
   /* If lookup is not enabled, return valid. */
   if (zlookup->sock < 0)
     {
-      ri->igpmetric = 0;
+      if (ri->extra)
+        ri->extra->igpmetric = 0;
       return 1;
     }
 
   /* Only check IPv6 global address only nexthop. */
   attr = ri->attr;
 
-  if (attr->mp_nexthop_len != 16 
-      || IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_global))
+  if (attr->extra->mp_nexthop_len != 16 
+      || IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
     return 1;
 
   memset (&p, 0, sizeof (struct prefix));
   p.family = AF_INET6;
   p.prefixlen = IPV6_MAX_BITLEN;
-  p.u.prefix6 = attr->mp_nexthop_global;
+  p.u.prefix6 = attr->extra->mp_nexthop_global;
 
   /* IBGP or ebgp-multihop */
   rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP6], &p);
@@ -256,7 +257,7 @@ bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
     }
   else
     {
-      bnc = zlookup_query_ipv6 (&attr->mp_nexthop_global);
+      bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global);
       if (bnc)
        {
          struct bgp_table *old;
@@ -296,10 +297,10 @@ bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
   if (metricchanged)
     *metricchanged = bnc->metricchanged;
 
-  if (bnc->valid)
-    ri->igpmetric = bnc->metric;
-  else
-    ri->igpmetric = 0;
+  if (bnc->valid && bnc->metric)
+    (bgp_info_extra_get (ri))->igpmetric = bnc->metric;
+  else if (ri->extra)
+    ri->extra->igpmetric = 0;
 
   return bnc->valid;
 }
@@ -318,7 +319,8 @@ bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
   /* If lookup is not enabled, return valid. */
   if (zlookup->sock < 0)
     {
-      ri->igpmetric = 0;
+      if (ri->extra)
+        ri->extra->igpmetric = 0;
       return 1;
     }
 
@@ -384,10 +386,10 @@ bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
   if (metricchanged)
     *metricchanged = bnc->metricchanged;
 
-  if (bnc->valid)
-    ri->igpmetric = bnc->metric;
-  else
-    ri->igpmetric = 0;
+  if (bnc->valid && bnc->metric)
+    (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
+  else if (ri->extra)
+    ri->extra->igpmetric = 0;
 
   return bnc->valid;
 }
@@ -490,7 +492,7 @@ bgp_scan (afi_t afi, safi_t safi)
 
               if (CHECK_FLAG (bgp->af_flags[afi][SAFI_UNICAST],
                  BGP_CONFIG_DAMPENING)
-                  &&  bi->damp_info )
+                  &&  bi->extra && bi->extra->damp_info )
                 if (bgp_damp_scan (bi, afi, SAFI_UNICAST))
                  bgp_aggregate_increment (bgp, &rn->p, bi,
                                           afi, SAFI_UNICAST);
index 9859e50babf0e772335d10d00b2914ec6aa0a9bf..2653201172a594d1d063ac5e59419de6c9b34214 100644 (file)
@@ -177,9 +177,9 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
          
          if (rn->prn)
            prd = (struct prefix_rd *) &rn->prn->p;
-          if (binfo)
+          if (binfo && binfo->extra)
             {
-              tag = binfo->tag;
+              tag = binfo->extra->tag;
               from = binfo->peer;
             }
           
@@ -1706,12 +1706,16 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
     aspath_unintern (attr.aspath);
   if (attr.community)
     community_unintern (attr.community);
-  if (attr.ecommunity)
-    ecommunity_unintern (attr.ecommunity);
-  if (attr.cluster)
-    cluster_unintern (attr.cluster);
-  if (attr.transit)
-    transit_unintern (attr.transit);
+  if (attr.extra)
+    {
+      if (attr.extra->ecommunity)
+        ecommunity_unintern (attr.extra->ecommunity);
+      if (attr.extra->cluster)
+        cluster_unintern (attr.extra->cluster);
+      if (attr.extra->transit)
+        transit_unintern (attr.extra->transit);
+      bgp_attr_extra_free (&attr);
+    }
 
   /* If peering is stopped due to some reason, do not generate BGP
      event.  */
index c33c596eec80937ef11cd762813b9173e5e62ab5..db0f3a74090319ac9b2e1418c245b90b4d4ae4bb 100644 (file)
@@ -89,6 +89,42 @@ bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix
   return rn;
 }
 \f
+/* 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);
 }
 \f
@@ -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;
+        }
     }
-}
-\f
+  
   /* 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
index b0c2fccf74652ee4e6cd3761bc7aaefebb9dffdd..c7eb8c6c640e64485d02781ea39d89387211c9d0 100644 (file)
@@ -23,6 +23,25 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
 #include "bgp_table.h"
 
+/* Ancillary information to struct bgp_info, 
+ * used for uncommonly used data (aggregation, MPLS, etc.)
+ * and lazily allocated to save memory.
+ */
+struct bgp_info_extra
+{
+  /* Pointer to dampening structure.  */
+  struct bgp_damp_info *damp_info;
+
+  /* This route is suppressed with aggregation.  */
+  int suppress;
+
+  /* Nexthop reachability check.  */
+  u_int32_t igpmetric;
+
+  /* MPLS label.  */
+  u_char tag[3];  
+};
+
 struct bgp_info
 {
   /* For linked list. */
@@ -34,19 +53,13 @@ struct bgp_info
 
   /* Attribute structure.  */
   struct attr *attr;
-
-  /* Pointer to dampening structure.  */
-  struct bgp_damp_info *damp_info;
-
+  
+  /* Extra information */
+  struct bgp_info_extra *extra;
+  
   /* Uptime.  */
   time_t uptime;
 
-  /* This route is suppressed with aggregation.  */
-  int suppress;
-  
-  /* Nexthop reachability check.  */
-  u_int32_t igpmetric;
-
   /* reference count */
   unsigned int lock;
   
@@ -64,9 +77,6 @@ struct bgp_info
 #define BGP_INFO_REMOVED        (1 << 9)
 #define BGP_INFO_COUNTED       (1 << 10)
 
-  /* MPLS label.  */
-  u_char tag[3];
-
   /* BGP route type.  This can be static, RIP, OSPF, BGP etc.  */
   u_char type;
 
@@ -162,6 +172,7 @@ extern struct bgp_info *bgp_info_lock (struct bgp_info *);
 extern struct bgp_info *bgp_info_unlock (struct bgp_info *);
 extern void bgp_info_add (struct bgp_node *rn, struct bgp_info *ri);
 extern void bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri);
+extern struct bgp_info_extra *bgp_info_extra_get (struct bgp_info *);
 extern void bgp_info_set_flag (struct bgp_node *, struct bgp_info *, u_int32_t);
 extern void bgp_info_unset_flag (struct bgp_node *, struct bgp_info *, u_int32_t);
 
index 806a50727ebd0a8643f2a76fc9191df5f4764a49..6a44c479615859ac93f0f07583a074f675566dec 100644 (file)
@@ -692,13 +692,16 @@ route_match_ecommunity (void *rule, struct prefix *prefix,
   if (type == RMAP_BGP) 
     {
       bgp_info = object;
-
+      
+      if (!bgp_info->attr->extra)
+        return RMAP_NOMATCH;
+      
       list = community_list_lookup (bgp_clist, (char *) rule,
                                    EXTCOMMUNITY_LIST_MASTER);
       if (! list)
        return RMAP_NOMATCH;
 
-      if (ecommunity_list_match (bgp_info->attr->ecommunity, list))
+      if (ecommunity_list_match (bgp_info->attr->extra->ecommunity, list))
        return RMAP_MATCH;
     }
   return RMAP_NOMATCH;
@@ -973,7 +976,10 @@ route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
       bgp_info = object;
     
       /* Set weight value. */ 
-      bgp_info->attr->weight = *weight;
+      if (*weight)
+        (bgp_attr_extra_get (bgp_info->attr))->weight = *weight;
+      else if (bgp_info->attr->extra)
+        bgp_info->attr->extra->weight = 0;
     }
 
   return RMAP_OKAY;
@@ -1402,14 +1408,14 @@ route_set_ecommunity_rt (void *rule, struct prefix *prefix,
        return RMAP_OKAY;
     
       /* We assume additive for Extended Community. */
-      old_ecom = bgp_info->attr->ecommunity;
+      old_ecom = (bgp_attr_extra_get (bgp_info->attr))->ecommunity;
 
       if (old_ecom)
        new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);
       else
        new_ecom = ecommunity_dup (ecom);
 
-      bgp_info->attr->ecommunity = new_ecom;
+      bgp_info->attr->extra->ecommunity = new_ecom;
 
       if (old_ecom)
        ecommunity_free (old_ecom);
@@ -1467,7 +1473,7 @@ route_set_ecommunity_soo (void *rule, struct prefix *prefix,
        return RMAP_OKAY;
     
       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
-      bgp_info->attr->ecommunity = ecommunity_dup (ecom);
+      (bgp_attr_extra_get (bgp_info->attr))->ecommunity = ecommunity_dup (ecom);
     }
   return RMAP_OKAY;
 }
@@ -1610,14 +1616,16 @@ route_set_aggregator_as (void *rule, struct prefix *prefix,
 {
   struct bgp_info *bgp_info;
   struct aggregator *aggregator;
+  struct attr_extra *ae;
 
   if (type == RMAP_BGP)
     {
       bgp_info = object;
       aggregator = rule;
-    
-      bgp_info->attr->aggregator_as = aggregator->as;
-      bgp_info->attr->aggregator_addr = aggregator->address;
+      ae = bgp_attr_extra_get (bgp_info->attr);
+      
+      ae->aggregator_as = aggregator->as;
+      ae->aggregator_addr = aggregator->address;
       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
     }
 
@@ -1711,12 +1719,15 @@ route_match_ipv6_next_hop (void *rule, struct prefix *prefix,
     {
       addr = rule;
       bgp_info = object;
-    
-      if (IPV6_ADDR_SAME (&bgp_info->attr->mp_nexthop_global, rule))
+      
+      if (!bgp_info->attr->extra)
+        return RMAP_NOMATCH;
+      
+      if (IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_global, rule))
        return RMAP_MATCH;
 
-      if (bgp_info->attr->mp_nexthop_len == 32 &&
-         IPV6_ADDR_SAME (&bgp_info->attr->mp_nexthop_local, rule))
+      if (bgp_info->attr->extra->mp_nexthop_len == 32 &&
+         IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_local, rule))
        return RMAP_MATCH;
 
       return RMAP_NOMATCH;
@@ -1814,11 +1825,11 @@ route_set_ipv6_nexthop_global (void *rule, struct prefix *prefix,
       bgp_info = object;
     
       /* Set next hop value. */ 
-      bgp_info->attr->mp_nexthop_global = *address;
+      (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global = *address;
     
       /* Set nexthop length. */
-      if (bgp_info->attr->mp_nexthop_len == 0)
-       bgp_info->attr->mp_nexthop_len = 16;
+      if (bgp_info->attr->extra->mp_nexthop_len == 0)
+       bgp_info->attr->extra->mp_nexthop_len = 16;
     }
 
   return RMAP_OKAY;
@@ -1878,11 +1889,11 @@ route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix,
       bgp_info = object;
     
       /* Set next hop value. */ 
-      bgp_info->attr->mp_nexthop_local = *address;
+      (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local = *address;
     
       /* Set nexthop length. */
-      if (bgp_info->attr->mp_nexthop_len != 32)
-       bgp_info->attr->mp_nexthop_len = 32;
+      if (bgp_info->attr->extra->mp_nexthop_len != 32)
+       bgp_info->attr->extra->mp_nexthop_len = 32;
     }
 
   return RMAP_OKAY;
@@ -1942,7 +1953,7 @@ route_set_vpnv4_nexthop (void *rule, struct prefix *prefix,
       bgp_info = object;
     
       /* Set next hop value. */ 
-      bgp_info->attr->mp_nexthop_global_in = *address;
+      (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global_in = *address;
     }
 
   return RMAP_OKAY;
@@ -1997,7 +2008,7 @@ route_set_originator_id (void *rule, struct prefix *prefix, route_map_object_t t
       bgp_info = object;
     
       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
-      bgp_info->attr->originator_id = *address;
+      (bgp_attr_extra_get (bgp_info->attr))->originator_id = *address;
     }
 
   return RMAP_OKAY;
index 430521f1df340a7c0f087bb0b7b1530474dc637a..3d26890ebb3762dcd5936aeefee3e0026158187d 100644 (file)
@@ -797,10 +797,16 @@ bgp4PathAttrTable (struct variable *v, oid name[], size_t *length,
       return SNMP_INTEGER (1);
       break;
     case BGP4PATHATTRAGGREGATORAS: /* 10 */
-      return SNMP_INTEGER (binfo->attr->aggregator_as);
+      if (binfo->attr->extra)
+        return SNMP_INTEGER (binfo->attr->extra->aggregator_as);
+      else
+        return SNMP_INTEGER (0);
       break;
     case BGP4PATHATTRAGGREGATORADDR: /* 11 */
-      return SNMP_IPADDRESS (binfo->attr->aggregator_addr);
+      if (binfo->attr->extra)
+        return SNMP_IPADDRESS (binfo->attr->extra->aggregator_addr);
+      else
+        return SNMP_INTEGER (0);
       break;
     case BGP4PATHATTRCALCLOCALPREF: /* 12 */
       return SNMP_INTEGER (-1);
index b108164f3659850695fa73efd1ae419dc60ef7dd..1e21c74f43d79242f938a100786b5b9f70194c4b 100644 (file)
@@ -6496,6 +6496,11 @@ DEFUN (show_bgp_memory,
            mtype_memstr (memstrbuf, sizeof (memstrbuf),
                          count * sizeof (struct bgp_info)),
            VTY_NEWLINE);
+  if ((count = mtype_stats_alloc (MTYPE_BGP_ROUTE_EXTRA)))
+    vty_out (vty, "%ld BGP route ancillaries, using %s of memory%s", count,
+             mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                           count * sizeof (struct bgp_info_extra)),
+             VTY_NEWLINE);
   
   if ((count = mtype_stats_alloc (MTYPE_BGP_STATIC)))
     vty_out (vty, "%ld Static routes, using %s of memory%s", count,
@@ -6533,6 +6538,11 @@ DEFUN (show_bgp_memory,
            mtype_memstr (memstrbuf, sizeof (memstrbuf), 
                          count * sizeof(struct attr)), 
            VTY_NEWLINE);
+  if ((count = mtype_stats_alloc (MTYPE_ATTR_EXTRA)))
+    vty_out (vty, "%ld BGP extra attributes, using %s of memory%s", count, 
+             mtype_memstr (memstrbuf, sizeof (memstrbuf), 
+                           count * sizeof(struct attr_extra)), 
+             VTY_NEWLINE);
   
   if ((count = attr_unknown_count()))
     vty_out (vty, "%ld unknown attributes%s", count, VTY_NEWLINE);
index 301c15b052fca98f14266725eb628e95b4838c52..0b6ab45a715e192b9cf45e7740be34634ccb81dd 100644 (file)
@@ -746,20 +746,22 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
 
       ifindex = 0;
       nexthop = NULL;
-
+      
+      assert (info->attr->extra);
+      
       /* Only global address nexthop exists. */
-      if (info->attr->mp_nexthop_len == 16)
-       nexthop = &info->attr->mp_nexthop_global;
+      if (info->attr->extra->mp_nexthop_len == 16)
+       nexthop = &info->attr->extra->mp_nexthop_global;
       
       /* If both global and link-local address present. */
-      if (info->attr->mp_nexthop_len == 32)
+      if (info->attr->extra->mp_nexthop_len == 32)
        {
          /* Workaround for Cisco's nexthop bug.  */
-         if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->mp_nexthop_global)
+         if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
              && peer->su_remote->sa.sa_family == AF_INET6)
            nexthop = &peer->su_remote->sin6.sin6_addr;
          else
-           nexthop = &info->attr->mp_nexthop_local;
+           nexthop = &info->attr->extra->mp_nexthop_local;
 
          if (info->peer->nexthop.ifp)
            ifindex = info->peer->nexthop.ifp->ifindex;
@@ -867,18 +869,20 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info)
       struct zapi_ipv6 api;
       unsigned int ifindex;
       struct in6_addr *nexthop;
-
+      
+      assert (info->attr->extra);
+      
       ifindex = 0;
       nexthop = NULL;
 
       /* Only global address nexthop exists. */
-      if (info->attr->mp_nexthop_len == 16)
-       nexthop = &info->attr->mp_nexthop_global;
+      if (info->attr->extra->mp_nexthop_len == 16)
+       nexthop = &info->attr->extra->mp_nexthop_global;
 
       /* If both global and link-local address present. */
-      if (info->attr->mp_nexthop_len == 32)
+      if (info->attr->extra->mp_nexthop_len == 32)
        {
-         nexthop = &info->attr->mp_nexthop_local;
+         nexthop = &info->attr->extra->mp_nexthop_local;
          if (info->peer->nexthop.ifp)
            ifindex = info->peer->nexthop.ifp->ifindex;
        }
index 3787b68cbf048758aa590654e659e44e3b4eeab4..5666cbad7e4481891143b45436200d9ef40434cd 100644 (file)
@@ -1,3 +1,7 @@
+2007-05-03 Paul Jakma <paul.jakma@sun.com>
+
+       * memtypes.c: Add MTYPE_ATTR_EXTRA and MTYPE_BGP_ROUTE_EXTRA
+
 2007-05-01 David L Stevens <dlstevens@us.ibm.com>
 
        * (general) These changes collectively add route-map and
index 5a685e0ee300064a77c3105a72f00ea4c9ec53aa..f1b10e71f60f1568f490491a9a8b92dabe3e505d 100644 (file)
@@ -6,7 +6,7 @@
  * The script is sensitive to the format (though not whitespace), see
  * the top of memtypes.awk for more details.
  *
- * $Id: memtypes.c,v 1.11 2006/03/30 14:09:38 paul Exp $
+ * $Id$
  */
 
 #include "zebra.h"
@@ -96,6 +96,7 @@ struct memory_list memory_list_bgp[] =
   { MTYPE_PEER_GROUP,          "Peer group"                    },
   { MTYPE_PEER_DESC,           "Peer description"              },
   { MTYPE_ATTR,                        "BGP attribute"                 },
+  { MTYPE_ATTR_EXTRA,          "BGP extra attributes"          },
   { MTYPE_AS_PATH,             "BGP aspath"                    },
   { MTYPE_AS_SEG,              "BGP aspath seg"                },
   { MTYPE_AS_SEG_DATA,         "BGP aspath segment data"       },
@@ -104,6 +105,7 @@ struct memory_list memory_list_bgp[] =
   { MTYPE_BGP_TABLE,           "BGP table"                     },
   { MTYPE_BGP_NODE,            "BGP node"                      },
   { MTYPE_BGP_ROUTE,           "BGP route"                     },
+  { MTYPE_BGP_ROUTE_EXTRA,     "BGP ancillary route info"      },
   { MTYPE_BGP_STATIC,          "BGP static"                    },
   { MTYPE_BGP_ADVERTISE_ATTR,  "BGP adv attr"                  },
   { MTYPE_BGP_ADVERTISE,       "BGP adv"                       },