[bgpd] Trim memory usage of BGP routes

2007-05-03 Paul Jakma <paul.jakma@sun.com>

	* bgp_route.h: (struct info) Move less frequently used
	  fields to a lazily allocated struct info_extra.
	  Export bgp_info_extra_get
	* bgp_route.c: (bgp_info_extra_new) allocate extra
	  (bgp_info_extra_free) Free damp info and the info_extra.
	  (bgp_info_extra_get) Retrieve the info_extra of a struct
	  info, allocating as required.
	  (generally) adjust to use info->extra
	* bgp_damp.c: (generally) use bgp_info_extra_get to access
	  dampinfo
	* bgp_attr.h: Move rarely allocated attributes from struct attr
	  to a struct attr_extra, for a substantial saving in size of
	  struct attr.
	* bgp_attr.c: (bgp_attr_extra_{new,free}), new, self-explanatory.
	  (bgp_attr_extra_get) Get the attr_extra for a given struct
	  attr, allocating it if needs be.
	  (bgp_attr_dup) Shallow copy the struct attr and its attr_extra.
	  (generally) adjust to know about attr->extra.
	* bgp_debug.c: (bgp_dump_attr) ditto
	* bgp_vty.c: (show_bgp_memory) print attr and info extra sizes.
	* bgp_nexthop.c: (generally) adjust to know about attr->extra
	  and info->extra.
	* bgp_{packet,routemap,snmp,zebra}.c: ditto
	* lib/memtypes.c: Add MTYPE_ATTR_EXTRA and MTYPE_BGP_ROUTE_EXTRA
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 806a507..6a44c47 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -692,13 +692,16 @@
   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 @@
       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 @@
 	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 @@
 	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 @@
 {
   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 @@
     {
       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 @@
       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 @@
       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 @@
       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 @@
       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;