]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_route.c
Merge branch 'quagga' into google-bgp-multipath
[mirror_frr.git] / bgpd / bgp_route.c
index 862fd4333e60e7270680fe9d5e68eedab1ba21a2..087f83961446e6c5f3d23608e55a2d0bce1faf33 100644 (file)
@@ -54,10 +54,11 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "bgpd/bgp_advertise.h"
 #include "bgpd/bgp_zebra.h"
 #include "bgpd/bgp_vty.h"
+#include "bgpd/bgp_mpath.h"
 
 /* Extern from bgp_dump.c */
-extern char *bgp_origin_str[];
-extern char *bgp_origin_long_str[];
+extern const char *bgp_origin_str[];
+extern const char *bgp_origin_long_str[];
 \f
 static struct bgp_node *
 bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix *p,
@@ -65,13 +66,17 @@ bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix
 {
   struct bgp_node *rn;
   struct bgp_node *prn = NULL;
-
+  
+  assert (table);
+  if (!table)
+    return NULL;
+  
   if (safi == SAFI_MPLS_VPN)
     {
       prn = bgp_node_get (table, (struct prefix *) prd);
 
       if (prn->info == NULL)
-       prn->info = bgp_table_init ();
+       prn->info = bgp_table_init (afi, safi);
       else
        bgp_unlock_node (prn);
       table = prn->info;
@@ -85,16 +90,47 @@ bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix
   return rn;
 }
 \f
-/* Allocate new bgp info structure. */
-static struct bgp_info *
-bgp_info_new ()
+/* Allocate bgp_info_extra */
+static struct bgp_info_extra *
+bgp_info_extra_new (void)
 {
-  struct bgp_info *new;
+  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;
+    }
+}
 
-  new = XMALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info));
-  memset (new, 0, sizeof (struct bgp_info));
+/* 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;
+}
 
-  return new;
+/* Allocate new bgp info structure. */
+static struct bgp_info *
+bgp_info_new (void)
+{
+  return XCALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info));
 }
 
 /* Free bgp route information. */
@@ -102,10 +138,10 @@ static void
 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_attr_unintern (&binfo->attr);
+  
+  bgp_info_extra_free (&binfo->extra);
+  bgp_info_mpath_free (&binfo->mpath);
 
   peer_unlock (binfo->peer); /* bgp_info peer reference */
 
@@ -176,6 +212,7 @@ bgp_info_reap (struct bgp_node *rn, struct bgp_info *ri)
   else
     rn->info = ri->next;
   
+  bgp_info_mpath_dequeue (ri);
   bgp_info_unlock (ri);
   bgp_unlock_node (rn);
 }
@@ -183,12 +220,87 @@ bgp_info_reap (struct bgp_node *rn, struct bgp_info *ri)
 void
 bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri)
 {
-  /* leave info in place for now in place for now, 
-   * bgp_process will reap it later. */
-  SET_FLAG (ri->flags, BGP_INFO_REMOVED);
+  bgp_info_set_flag (rn, ri, BGP_INFO_REMOVED);
+  /* set of previous already took care of pcount */
   UNSET_FLAG (ri->flags, BGP_INFO_VALID);
 }
 
+/* undo the effects of a previous call to bgp_info_delete; typically
+   called when a route is deleted and then quickly re-added before the
+   deletion has been processed */
+static void
+bgp_info_restore (struct bgp_node *rn, struct bgp_info *ri)
+{
+  bgp_info_unset_flag (rn, ri, BGP_INFO_REMOVED);
+  /* unset of previous already took care of pcount */
+  SET_FLAG (ri->flags, BGP_INFO_VALID);
+}
+
+/* Adjust pcount as required */   
+static void
+bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri)
+{
+  assert (rn && rn->table);
+  assert (ri && ri->peer && ri->peer->bgp);
+
+  /* Ignore 'pcount' for RS-client tables */
+  if (rn->table->type != BGP_TABLE_MAIN
+      || ri->peer == ri->peer->bgp->peer_self)
+    return;
+    
+  if (BGP_INFO_HOLDDOWN (ri)
+      && CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
+    {
+          
+      UNSET_FLAG (ri->flags, BGP_INFO_COUNTED);
+      
+      /* slight hack, but more robust against errors. */
+      if (ri->peer->pcount[rn->table->afi][rn->table->safi])
+        ri->peer->pcount[rn->table->afi][rn->table->safi]--;
+      else
+        {
+          zlog_warn ("%s: Asked to decrement 0 prefix count for peer %s",
+                     __func__, ri->peer->host);
+          zlog_backtrace (LOG_WARNING);
+          zlog_warn ("%s: Please report to Quagga bugzilla", __func__);
+        }      
+    }
+  else if (!BGP_INFO_HOLDDOWN (ri) 
+           && !CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
+    {
+      SET_FLAG (ri->flags, BGP_INFO_COUNTED);
+      ri->peer->pcount[rn->table->afi][rn->table->safi]++;
+    }
+}
+
+
+/* Set/unset bgp_info flags, adjusting any other state as needed.
+ * This is here primarily to keep prefix-count in check.
+ */
+void
+bgp_info_set_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag)
+{
+  SET_FLAG (ri->flags, flag);
+  
+  /* early bath if we know it's not a flag that changes useability state */
+  if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_UNUSEABLE))
+    return;
+  
+  bgp_pcount_adjust (rn, ri);
+}
+
+void
+bgp_info_unset_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag)
+{
+  UNSET_FLAG (ri->flags, flag);
+  
+  /* early bath if we know it's not a flag that changes useability state */
+  if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_UNUSEABLE))
+    return;
+  
+  bgp_pcount_adjust (rn, ri);
+}
+
 /* Get MED value.  If MED value is missing and "bgp bestpath
    missing-as-worst" is specified, treat it as the worst value. */
 static u_int32_t
@@ -207,12 +319,15 @@ bgp_med_value (struct attr *attr, struct bgp *bgp)
 
 /* Compare two bgp route entity.  br is preferable then return 1. */
 static int
-bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist)
+bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
+             int *paths_eq)
 {
   u_int32_t new_pref;
   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;
@@ -220,6 +335,9 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist)
   int internal_as_route = 0;
   int confed_as_route = 0;
   int ret;
+  uint32_t newm, existm;
+
+  *paths_eq = 0;
 
   /* 0. Null check. */
   if (new == NULL)
@@ -228,9 +346,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. */
@@ -268,24 +390,28 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist)
   /* 4. AS path length check. */
   if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
     {
+      int exist_hops = aspath_count_hops (exist->attr->aspath);
+      int exist_confeds = aspath_count_confeds (exist->attr->aspath);
+      
       if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
        {
-         if ((new->attr->aspath->count +
-              new->attr->aspath->confed_count)
-             < (exist->attr->aspath->count +
-                exist->attr->aspath->confed_count))
+         int aspath_hops;
+         
+         aspath_hops = aspath_count_hops (new->attr->aspath);
+          aspath_hops += aspath_count_confeds (new->attr->aspath);
+          
+         if ( aspath_hops < (exist_hops + exist_confeds))
            return 1;
-         if ((new->attr->aspath->count +
-              new->attr->aspath->confed_count)
-             > (exist->attr->aspath->count +
-                exist->attr->aspath->confed_count))
+         if ( aspath_hops > (exist_hops + exist_confeds))
            return 0;
        }
       else
        {
-         if (new->attr->aspath->count < exist->attr->aspath->count)
+         int newhops = aspath_count_hops (new->attr->aspath);
+         
+         if (newhops < exist_hops)
            return 1;
-          if (new->attr->aspath->count > exist->attr->aspath->count)
+          if (newhops > exist_hops)
            return 0;
        }
     }
@@ -297,12 +423,12 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist)
     return 0;
 
   /* 6. MED check. */
-  internal_as_route = (new->attr->aspath->length == 0
-                     && exist->attr->aspath->length == 0);
-  confed_as_route = (new->attr->aspath->length > 0
-                   && exist->attr->aspath->length > 0
-                   && new->attr->aspath->count == 0
-                   && exist->attr->aspath->count == 0);
+  internal_as_route = (aspath_count_hops (new->attr->aspath) == 0
+                     && aspath_count_hops (exist->attr->aspath) == 0);
+  confed_as_route = (aspath_count_confeds (new->attr->aspath) > 0
+                   && aspath_count_confeds (exist->attr->aspath) > 0
+                   && aspath_count_hops (new->attr->aspath) == 0
+                   && aspath_count_hops (exist->attr->aspath) == 0);
   
   if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
       || (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
@@ -335,12 +461,32 @@ 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;
+  newm = (new->extra ? new->extra->igpmetric : 0);
+  existm = (exist->extra ? exist->extra->igpmetric : 0);
+  if (newm < existm)
+    ret = 1;
+  if (newm > existm)
+    ret = 0;
 
   /* 9. Maximum path check. */
+  if (newm == existm)
+    {
+      if ((peer_sort (new->peer) == BGP_PEER_IBGP))
+       {
+         if (aspath_cmp (new->attr->aspath, exist->attr->aspath))
+           *paths_eq = 1;
+       }
+      else if (new->peer->as == exist->peer->as)
+       *paths_eq = 1;
+    }
+  else
+    {
+      /*
+       * TODO: If unequal cost ibgp multipath is enabled we can
+       * mark the paths as equal here instead of returning
+       */
+      return ret;
+    }
 
   /* 10. If both paths are external, prefer the path that was received
      first (the oldest one).  This step minimizes route-flap, since a
@@ -358,11 +504,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;
 
@@ -373,11 +519,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;
 
@@ -405,19 +551,35 @@ bgp_input_filter (struct peer *peer, struct prefix *p, struct attr *attr,
 
   filter = &peer->filter[afi][safi];
 
-  if (DISTRIBUTE_IN_NAME (filter))
+#define FILTER_EXIST_WARN(F,f,filter) \
+  if (BGP_DEBUG (update, UPDATE_IN) \
+      && !(F ## _IN (filter))) \
+    plog_warn (peer->log, "%s: Could not find configured input %s-list %s!", \
+               peer->host, #f, F ## _IN_NAME(filter));
+  
+  if (DISTRIBUTE_IN_NAME (filter)) {
+    FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
+      
     if (access_list_apply (DISTRIBUTE_IN (filter), p) == FILTER_DENY)
       return FILTER_DENY;
+  }
 
-  if (PREFIX_LIST_IN_NAME (filter))
+  if (PREFIX_LIST_IN_NAME (filter)) {
+    FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
+    
     if (prefix_list_apply (PREFIX_LIST_IN (filter), p) == PREFIX_DENY)
       return FILTER_DENY;
+  }
   
-  if (FILTER_LIST_IN_NAME (filter))
+  if (FILTER_LIST_IN_NAME (filter)) {
+    FILTER_EXIST_WARN(FILTER_LIST, as, filter);
+    
     if (as_list_apply (FILTER_LIST_IN (filter), attr->aspath)== AS_FILTER_DENY)
       return FILTER_DENY;
-
+  }
+  
   return FILTER_PERMIT;
+#undef FILTER_EXIST_WARN
 }
 
 static enum filter_type
@@ -428,19 +590,35 @@ bgp_output_filter (struct peer *peer, struct prefix *p, struct attr *attr,
 
   filter = &peer->filter[afi][safi];
 
-  if (DISTRIBUTE_OUT_NAME (filter))
+#define FILTER_EXIST_WARN(F,f,filter) \
+  if (BGP_DEBUG (update, UPDATE_OUT) \
+      && !(F ## _OUT (filter))) \
+    plog_warn (peer->log, "%s: Could not find configured output %s-list %s!", \
+               peer->host, #f, F ## _OUT_NAME(filter));
+
+  if (DISTRIBUTE_OUT_NAME (filter)) {
+    FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
+    
     if (access_list_apply (DISTRIBUTE_OUT (filter), p) == FILTER_DENY)
       return FILTER_DENY;
+  }
 
-  if (PREFIX_LIST_OUT_NAME (filter))
+  if (PREFIX_LIST_OUT_NAME (filter)) {
+    FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
+    
     if (prefix_list_apply (PREFIX_LIST_OUT (filter), p) == PREFIX_DENY)
       return FILTER_DENY;
+  }
 
-  if (FILTER_LIST_OUT_NAME (filter))
+  if (FILTER_LIST_OUT_NAME (filter)) {
+    FILTER_EXIST_WARN(FILTER_LIST, as, filter);
+    
     if (as_list_apply (FILTER_LIST_OUT (filter), attr->aspath) == AS_FILTER_DENY)
       return FILTER_DENY;
+  }
 
   return FILTER_PERMIT;
+#undef FILTER_EXIST_WARN
 }
 
 /* If community attribute includes no_export then return 1. */
@@ -473,14 +651,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;
@@ -497,7 +675,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))
@@ -568,7 +747,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))
@@ -601,20 +781,19 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
   int ret;
   char buf[SU_ADDRSTRLEN];
   struct bgp_filter *filter;
-  struct bgp_info info;
   struct peer *from;
   struct bgp *bgp;
-  struct attr dummy_attr;
   int transparent;
   int reflect;
+  struct attr *riattr;
 
   from = ri->peer;
   filter = &peer->filter[afi][safi];
   bgp = peer->bgp;
+  riattr = bgp_info_mpath_count (ri) ? bgp_info_mpath_attr (ri) : ri->attr;
   
-#ifdef DISABLE_BGP_ANNOUNCE
-  return 0;
-#endif
+  if (DISABLE_BGP_ANNOUNCE)
+    return 0;
 
   /* Do not send announces to RS-clients from the 'normal' bgp_table. */
   if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
@@ -626,16 +805,16 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
 
   /* If peer's id and route's nexthop are same. draft-ietf-idr-bgp4-23 5.1.3 */
   if (p->family == AF_INET
-      && IPV4_ADDR_SAME(&peer->remote_id, &ri->attr->nexthop))
+      && IPV4_ADDR_SAME(&peer->remote_id, &riattr->nexthop))
     return 0;
 #ifdef HAVE_IPV6
   if (p->family == AF_INET6
-     && IPV6_ADDR_SAME(&peer->remote_id, &ri->attr->nexthop))
+     && IPV6_ADDR_SAME(&peer->remote_id, &riattr->nexthop))
     return 0;
 #endif
 
   /* Aggregate-address suppress check. */
-  if (ri->suppress)
+  if (ri->extra && ri->extra->suppress)
     if (! UNSUPPRESS_MAP_NAME (filter))
       return 0;
 
@@ -658,14 +837,14 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
     transparent = 0;
 
   /* If community is not disabled check the no-export and local. */
-  if (! transparent && bgp_community_filter (peer, ri->attr)) 
+  if (! transparent && bgp_community_filter (peer, riattr))
     return 0;
 
   /* If the attribute has originator-id and it is same as remote
      peer's id. */
-  if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))
+  if (riattr->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, &riattr->extra->originator_id))
        {
          if (BGP_DEBUG (filter, FILTER))  
            zlog (peer->log, LOG_DEBUG,
@@ -688,7 +867,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
       }
 
   /* Output filter check. */
-  if (bgp_output_filter (peer, p, ri->attr, afi, safi) == FILTER_DENY)
+  if (bgp_output_filter (peer, p, riattr, afi, safi) == FILTER_DENY)
     {
       if (BGP_DEBUG (filter, FILTER))
        zlog (peer->log, LOG_DEBUG,
@@ -701,11 +880,11 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
 
 #ifdef BGP_SEND_ASPATH_CHECK
   /* AS path loop check. */
-  if (aspath_loop_check (ri->attr->aspath, peer->as))
+  if (aspath_loop_check (riattr->aspath, peer->as))
     {
       if (BGP_DEBUG (filter, FILTER))  
         zlog (peer->log, LOG_DEBUG, 
-             "%s [Update:SEND] suppress announcement to peer AS %d is AS path.",
+             "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
              peer->host, peer->as);
       return 0;
     }
@@ -714,11 +893,11 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
   /* If we're a CONFED we need to loop check the CONFED ID too */
   if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
     {
-      if (aspath_loop_check(ri->attr->aspath, bgp->confed_id))
+      if (aspath_loop_check(riattr->aspath, bgp->confed_id))
        {
          if (BGP_DEBUG (filter, FILTER))  
            zlog (peer->log, LOG_DEBUG, 
-                 "%s [Update:SEND] suppress announcement to peer AS %d is AS path.",
+                 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
                  peer->host,
                  bgp->confed_id);
          return 0;
@@ -753,10 +932,10 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
            return 0;
        }
     }
-
+  
   /* For modify attribute, copy it to temporary structure. */
-  *attr = *ri->attr;
-
+  bgp_attr_dup (attr, riattr);
+  
   /* If local-preference is not set. */
   if ((peer_sort (peer) == BGP_PEER_IBGP 
        || peer_sort (peer) == BGP_PEER_CONFED) 
@@ -781,7 +960,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 */
              )))
     {
@@ -791,7 +970,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))
@@ -800,7 +979,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);
        }
@@ -809,9 +989,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 */
     }
@@ -823,35 +1003,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;
     }
 
     }
@@ -865,8 +1045,11 @@ 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 = { 0 };
+      
       info.peer = peer;
       info.attr = attr;
 
@@ -875,19 +1058,22 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
       if (peer_sort (from) == BGP_PEER_IBGP 
          && peer_sort (peer) == BGP_PEER_IBGP)
        {
-         dummy_attr = *attr;
+         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;
-
+      
+      if (dummy_attr.extra)
+        bgp_attr_extra_free (&dummy_attr);
+      
       if (ret == RMAP_DENYMATCH)
        {
          bgp_attr_flush (attr);
@@ -906,22 +1092,21 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
   struct bgp_filter *filter;
   struct bgp_info info;
   struct peer *from;
-  struct bgp *bgp;
+  struct attr *riattr;
 
   from = ri->peer;
   filter = &rsclient->filter[afi][safi];
-  bgp = rsclient->bgp;
+  riattr = bgp_info_mpath_count (ri) ? bgp_info_mpath_attr (ri) : ri->attr;
 
-#ifdef DISABLE_BGP_ANNOUNCE
-  return 0;
-#endif
+  if (DISABLE_BGP_ANNOUNCE)
+    return 0;
 
   /* Do not send back route to sender. */
   if (from == rsclient)
     return 0;
 
   /* Aggregate-address suppress check. */
-  if (ri->suppress)
+  if (ri->extra && ri->extra->suppress)
     if (! UNSUPPRESS_MAP_NAME (filter))
       return 0;
 
@@ -939,9 +1124,10 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
 
   /* If the attribute has originator-id and it is same as remote
      peer's id. */
-  if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))
+  if (riattr->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, 
+                          &riattr->extra->originator_id))
         {
          if (BGP_DEBUG (filter, FILTER))
            zlog (rsclient->log, LOG_DEBUG,
@@ -964,7 +1150,7 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
       }
 
   /* Output filter check. */
-  if (bgp_output_filter (rsclient, p, ri->attr, afi, safi) == FILTER_DENY)
+  if (bgp_output_filter (rsclient, p, riattr, afi, safi) == FILTER_DENY)
     {
       if (BGP_DEBUG (filter, FILTER))
        zlog (rsclient->log, LOG_DEBUG,
@@ -977,24 +1163,24 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
 
 #ifdef BGP_SEND_ASPATH_CHECK
   /* AS path loop check. */
-  if (aspath_loop_check (ri->attr->aspath, rsclient->as))
+  if (aspath_loop_check (riattr->aspath, rsclient->as))
     {
       if (BGP_DEBUG (filter, FILTER))
         zlog (rsclient->log, LOG_DEBUG,
-             "%s [Update:SEND] suppress announcement to peer AS %d is AS path.",
+             "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
              rsclient->host, rsclient->as);
       return 0;
     }
 #endif /* BGP_SEND_ASPATH_CHECK */
 
   /* For modify attribute, copy it to temporary structure. */
-  *attr = *ri->attr;
+  bgp_attr_dup (attr, riattr);
 
   /* next-hop-set */
   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 */
      )
   {
@@ -1002,7 +1188,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);
@@ -1012,10 +1198,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 */
   }
@@ -1023,14 +1208,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 */
@@ -1040,23 +1229,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;
         }
 
     }
@@ -1070,14 +1259,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);
@@ -1101,7 +1290,9 @@ struct bgp_info_pair
 };
 
 static void
-bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair *result)
+bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
+                   struct bgp_maxpaths_cfg *mpath_cfg,
+                   struct bgp_info_pair *result)
 {
   struct bgp_info *new_select;
   struct bgp_info *old_select;
@@ -1109,7 +1300,13 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair *
   struct bgp_info *ri1;
   struct bgp_info *ri2;
   struct bgp_info *nextri = NULL;
-  
+  int paths_eq, do_mpath;
+  struct list mp_list;
+
+  bgp_mp_list_init (&mp_list);
+  do_mpath = (mpath_cfg->maxpaths_ebgp != BGP_DEFAULT_MAXPATHS ||
+             mpath_cfg->maxpaths_ibgp != BGP_DEFAULT_MAXPATHS);
+
   /* bgp deterministic-med */
   new_select = NULL;
   if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
@@ -1121,6 +1318,9 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair *
          continue;
 
        new_select = ri1;
+       if (do_mpath)
+         bgp_mp_list_add (&mp_list, ri1);
+       old_select = CHECK_FLAG (ri1->flags, BGP_INFO_SELECTED) ? ri1 : NULL;
        if (ri1->next)
          for (ri2 = ri1->next; ri2; ri2 = ri2->next)
            {
@@ -1133,17 +1333,30 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair *
                  || aspath_cmp_left_confed (ri1->attr->aspath,
                                             ri2->attr->aspath))
                {
-                 if (bgp_info_cmp (bgp, ri2, new_select))
+                 if (CHECK_FLAG (ri2->flags, BGP_INFO_SELECTED))
+                   old_select = ri2;
+                 if (bgp_info_cmp (bgp, ri2, new_select, &paths_eq))
                    {
-                     UNSET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED);
+                     bgp_info_unset_flag (rn, new_select, BGP_INFO_DMED_SELECTED);
                      new_select = ri2;
+                     if (do_mpath && !paths_eq)
+                       {
+                         bgp_mp_list_clear (&mp_list);
+                         bgp_mp_list_add (&mp_list, ri2);
+                       }
                    }
 
-                 SET_FLAG (ri2->flags, BGP_INFO_DMED_CHECK);
+                 if (do_mpath && paths_eq)
+                   bgp_mp_list_add (&mp_list, ri2);
+
+                 bgp_info_set_flag (rn, ri2, BGP_INFO_DMED_CHECK);
                }
            }
-       SET_FLAG (new_select->flags, BGP_INFO_DMED_CHECK);
-       SET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED);
+       bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_CHECK);
+       bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_SELECTED);
+
+       bgp_info_mpath_update (rn, new_select, old_select, &mp_list, mpath_cfg);
+       bgp_mp_list_clear (&mp_list);
       }
 
   /* Check old selected route and new selected route. */
@@ -1169,39 +1382,63 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair *
       if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)
           && (! CHECK_FLAG (ri->flags, BGP_INFO_DMED_SELECTED)))
        {
-         UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK);
+         bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK);
          continue;
         }
-      UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK);
-      UNSET_FLAG (ri->flags, BGP_INFO_DMED_SELECTED);
+      bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK);
+      bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_SELECTED);
+
+      if (bgp_info_cmp (bgp, ri, new_select, &paths_eq))
+       {
+         if (do_mpath && bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
+           bgp_mp_dmed_deselect (new_select);
+
+         new_select = ri;
+
+         if (do_mpath && !paths_eq)
+           {
+             bgp_mp_list_clear (&mp_list);
+             bgp_mp_list_add (&mp_list, ri);
+           }
+       }
+      else if (do_mpath && bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
+       bgp_mp_dmed_deselect (ri);
 
-      if (bgp_info_cmp (bgp, ri, new_select))
-       new_select = ri;
+      if (do_mpath && paths_eq)
+       bgp_mp_list_add (&mp_list, ri);
     }
     
-    result->old = old_select;
-    result->new = new_select;
 
-    return;
+  if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
+    bgp_info_mpath_update (rn, new_select, old_select, &mp_list, mpath_cfg);
+
+  bgp_info_mpath_aggregate_update (new_select, old_select);
+  bgp_mp_list_clear (&mp_list);
+
+  result->old = old_select;
+  result->new = new_select;
+
+  return;
 }
 
 static int
 bgp_process_announce_selected (struct peer *peer, struct bgp_info *selected,
-        struct bgp_node *rn, struct attr *attr, afi_t afi, safi_t safi)
-    {
+                               struct bgp_node *rn, afi_t afi, safi_t safi)
+{
   struct prefix *p;
+  struct attr attr = { 0 };
 
   p = &rn->p;
 
-      /* Announce route to Established peer. */
-      if (peer->status != Established)
+  /* Announce route to Established peer. */
+  if (peer->status != Established)
     return 0;
 
-      /* Address family configuration check. */
-      if (! peer->afc_nego[afi][safi])
+  /* Address family configuration check. */
+  if (! peer->afc_nego[afi][safi])
     return 0;
 
-      /* First update is deferred until ORF or ROUTE-REFRESH is received */
+  /* First update is deferred until ORF or ROUTE-REFRESH is received */
   if (CHECK_FLAG (peer->af_sflags[afi][safi],
       PEER_STATUS_ORF_WAIT_REFRESH))
     return 0;
@@ -1211,21 +1448,24 @@ bgp_process_announce_selected (struct peer *peer, struct bgp_info *selected,
       case BGP_TABLE_MAIN:
       /* Announcement to peer->conf.  If the route is filtered,
          withdraw it. */
-        if (selected && bgp_announce_check (selected, peer, p, attr, afi, safi))
-          bgp_adj_out_set (rn, peer, p, attr, afi, safi, selected);
+        if (selected && bgp_announce_check (selected, peer, p, &attr, afi, safi))
+          bgp_adj_out_set (rn, peer, p, &attr, afi, safi, selected);
         else
           bgp_adj_out_unset (rn, peer, p, afi, safi);
         break;
       case BGP_TABLE_RSCLIENT:
         /* Announcement to peer->conf.  If the route is filtered, 
            withdraw it. */
-        if (selected && bgp_announce_check_rsclient
-              (selected, peer, p, attr, afi, safi))
-          bgp_adj_out_set (rn, peer, p, attr, afi, safi, selected);
-      else
-       bgp_adj_out_unset (rn, peer, p, afi, safi);
+        if (selected && 
+            bgp_announce_check_rsclient (selected, peer, p, &attr, afi, safi))
+          bgp_adj_out_set (rn, peer, p, &attr, afi, safi, selected);
+        else
+         bgp_adj_out_unset (rn, peer, p, afi, safi);
         break;
     }
+  
+  bgp_attr_extra_free (&attr);
+  
   return 0;
 }
 
@@ -1238,8 +1478,9 @@ struct bgp_process_queue
 };
 
 static wq_item_status
-bgp_process_rsclient (struct bgp_process_queue *pq)
+bgp_process_rsclient (struct work_queue *wq, void *data)
 {
+  struct bgp_process_queue *pq = data;
   struct bgp *bgp = pq->bgp;
   struct bgp_node *rn = pq->rn;
   afi_t afi = pq->afi;
@@ -1247,47 +1488,48 @@ bgp_process_rsclient (struct bgp_process_queue *pq)
   struct bgp_info *new_select;
   struct bgp_info *old_select;
   struct bgp_info_pair old_and_new;
-  struct attr attr;
   struct listnode *node, *nnode;
   struct peer *rsclient = rn->table->owner;
   
-  /* we shouldn't run if the clear_route_node queue is still running
-   * or scheduled to run, or we can race with session coming up
-   * and adding routes back before we've cleared them
-   */
-  if (bm->clear_node_queue && bm->clear_node_queue->thread)
-    return WQ_QUEUE_BLOCKED;
-  
   /* Best path selection. */
-  bgp_best_selection (bgp, rn, &old_and_new);
+  bgp_best_selection (bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new);
   new_select = old_and_new.new;
   old_select = old_and_new.old;
 
   if (CHECK_FLAG (rsclient->sflags, PEER_STATUS_GROUP))
     {
-      for (ALL_LIST_ELEMENTS (rsclient->group->peer, node, nnode, rsclient))
-       {
-         /* Nothing to do. */
-         if (old_select && old_select == new_select)
-           if (!CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
-             continue;
-
-         if (old_select)
-           UNSET_FLAG (old_select->flags, BGP_INFO_SELECTED);
-         if (new_select)
-           {
-             SET_FLAG (new_select->flags, BGP_INFO_SELECTED);
-             UNSET_FLAG (new_select->flags, BGP_INFO_ATTR_CHANGED);
-           }
-
-         bgp_process_announce_selected (rsclient, new_select, rn, &attr,
-                                        afi, safi);
-       }
+      if (rsclient->group)
+        for (ALL_LIST_ELEMENTS (rsclient->group->peer, node, nnode, rsclient))
+          {
+            /* Nothing to do. */
+            if (old_select && old_select == new_select)
+              if (!CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
+                continue;
+
+            if (old_select)
+              bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
+            if (new_select)
+              {
+                bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
+                bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
+               UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
+             }
+
+            bgp_process_announce_selected (rsclient, new_select, rn,
+                                           afi, safi);
+          }
     }
   else
     {
-      bgp_process_announce_selected (rsclient, new_select, rn,
-                                    &attr, afi, safi);
+      if (old_select)
+       bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
+      if (new_select)
+       {
+         bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
+         bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
+         UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
+       }
+      bgp_process_announce_selected (rsclient, new_select, rn, afi, safi);
     }
 
   if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED))
@@ -1298,8 +1540,9 @@ bgp_process_rsclient (struct bgp_process_queue *pq)
 }
 
 static wq_item_status
-bgp_process_main (struct bgp_process_queue *pq)
+bgp_process_main (struct work_queue *wq, void *data)
 {
+  struct bgp_process_queue *pq = data;
   struct bgp *bgp = pq->bgp;
   struct bgp_node *rn = pq->rn;
   afi_t afi = pq->afi;
@@ -1310,17 +1553,9 @@ bgp_process_main (struct bgp_process_queue *pq)
   struct bgp_info_pair old_and_new;
   struct listnode *node, *nnode;
   struct peer *peer;
-  struct attr attr;
   
-  /* we shouldn't run if the clear_route_node queue is still running
-   * or scheduled to run, or we can race with session coming up
-   * and adding routes back before we've cleared them
-   */
-  if (bm->clear_node_queue && bm->clear_node_queue->thread)
-    return WQ_QUEUE_BLOCKED;
-
   /* Best path selection. */
-  bgp_best_selection (bgp, rn, &old_and_new);
+  bgp_best_selection (bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new);
   old_select = old_and_new.old;
   new_select = old_and_new.new;
 
@@ -1329,44 +1564,47 @@ bgp_process_main (struct bgp_process_queue *pq)
     {
       if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
         {
-          if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED))
-            bgp_zebra_announce (p, old_select, bgp);
+          if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED) ||
+             CHECK_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG))
+            bgp_zebra_announce (p, old_select, bgp, safi);
           
+         UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG);
           UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
           return WQ_SUCCESS;
         }
     }
 
   if (old_select)
-    UNSET_FLAG (old_select->flags, BGP_INFO_SELECTED);
+    bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
   if (new_select)
     {
-      SET_FLAG (new_select->flags, BGP_INFO_SELECTED);
-      UNSET_FLAG (new_select->flags, BGP_INFO_ATTR_CHANGED);
+      bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
+      bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
+      UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
     }
 
 
   /* Check each BGP peer. */
   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
     {
-      bgp_process_announce_selected (peer, new_select, rn, &attr, afi, safi);
+      bgp_process_announce_selected (peer, new_select, rn, afi, safi);
     }
 
   /* FIB update. */
-  if (safi == SAFI_UNICAST && ! bgp->name &&
-      ! bgp_option_check (BGP_OPT_NO_FIB))
+  if ((safi == SAFI_UNICAST || safi == SAFI_MULTICAST) && (! bgp->name &&
+      ! bgp_option_check (BGP_OPT_NO_FIB)))
     {
       if (new_select 
          && new_select->type == ZEBRA_ROUTE_BGP 
          && new_select->sub_type == BGP_ROUTE_NORMAL)
-       bgp_zebra_announce (p, new_select, bgp);
+       bgp_zebra_announce (p, new_select, bgp, safi);
       else
        {
          /* Withdraw the route from the kernel. */
          if (old_select 
              && old_select->type == ZEBRA_ROUTE_BGP
              && old_select->sub_type == BGP_ROUTE_NORMAL)
-           bgp_zebra_withdraw (p, old_select);
+           bgp_zebra_withdraw (p, old_select, safi);
        }
     }
     
@@ -1379,9 +1617,14 @@ bgp_process_main (struct bgp_process_queue *pq)
 }
 
 static void
-bgp_processq_del (struct bgp_process_queue *pq)
+bgp_processq_del (struct work_queue *wq, void *data)
 {
+  struct bgp_process_queue *pq = data;
+  struct bgp_table *table = pq->rn->table;
+  
+  bgp_unlock (pq->bgp);
   bgp_unlock_node (pq->rn);
+  bgp_table_unlock (table);
   XFREE (MTYPE_BGP_PROCESS_QUEUE, pq);
 }
 
@@ -1400,16 +1643,13 @@ bgp_process_queue_init (void)
     }
   
   bm->process_main_queue->spec.workfunc = &bgp_process_main;
-  bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient;
   bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
-  bm->process_rsclient_queue->spec.del_item_data
-    =  bm->process_main_queue->spec.del_item_data;
-  bm->process_main_queue->spec.max_retries
-    = bm->process_main_queue->spec.max_retries = 0;
-  bm->process_rsclient_queue->spec.hold
-    = bm->process_main_queue->spec.hold = 500;
-  bm->process_rsclient_queue->spec.delay
-    = bm->process_main_queue->spec.delay = 10;
+  bm->process_main_queue->spec.max_retries = 0;
+  bm->process_main_queue->spec.hold = 50;
+  
+  memcpy (bm->process_rsclient_queue, bm->process_main_queue,
+          sizeof (struct work_queue *));
+  bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient;
 }
 
 void
@@ -1429,9 +1669,12 @@ bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
                     sizeof (struct bgp_process_queue));
   if (!pqnode)
     return;
-  
-  pqnode->rn = bgp_lock_node (rn); /* unlocked by bgp_processq_del */
+
+  /* all unlocked in bgp_processq_del */
+  bgp_table_lock (rn->table);
+  pqnode->rn = bgp_lock_node (rn);
   pqnode->bgp = bgp;
+  bgp_lock (bgp);
   pqnode->afi = afi;
   pqnode->safi = safi;
   
@@ -1491,7 +1734,7 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi,
        u_int8_t ndata[7];
 
        if (safi == SAFI_MPLS_VPN)
-         safi = BGP_SAFI_VPNV4;
+         safi = SAFI_MPLS_LABELED_VPN;
          
        ndata[0] = (afi >>  8);
        ndata[1] = afi;
@@ -1548,38 +1791,20 @@ static void
 bgp_rib_remove (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
                afi_t afi, safi_t safi)
 {
-  if (!CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)
-      && rn->table->type == BGP_TABLE_MAIN)
-    {
-      /* Ignore 'pcount' for RS-client tables */
-      if ( rn->table->type == BGP_TABLE_MAIN)
-        {
-          peer->pcount[afi][safi]--;
-          bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
-        }
-    }
+  bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
+  
+  if (!CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
+    bgp_info_delete (rn, ri); /* keep historical info */
+    
   bgp_process (peer->bgp, rn, afi, safi);
-  bgp_info_delete (rn, ri);
 }
 
 static void
 bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
                  afi_t afi, safi_t safi)
 {
-  int valid;
   int status = BGP_DAMP_NONE;
 
-  if (!CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)
-      && rn->table->type == BGP_TABLE_MAIN)
-    {
-      /* Ignore 'pcount' for RS-client tables */
-      if ( rn->table->type == BGP_TABLE_MAIN)
-        {
-          peer->pcount[afi][safi]--;
-          bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
-        }
-    }
-  
   /* apply dampening, if result is suppressed, we'll be retaining 
    * the bgp_info in the RIB for historical reference.
    */
@@ -1587,12 +1812,12 @@ bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
       && peer_sort (peer) == BGP_PEER_EBGP)
     if ( (status = bgp_damp_withdraw (ri, rn, afi, safi, 0)) 
          == BGP_DAMP_SUPPRESSED)
-      return;
-
-  bgp_process (peer->bgp, rn, afi, safi);
-
-  if (status != BGP_DAMP_USED)
-    bgp_info_delete (rn, ri);
+      {
+        bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
+        return;
+      }
+    
+  bgp_rib_remove (rn, ri, peer, afi, safi);
 }
 
 static void
@@ -1602,7 +1827,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;
@@ -1631,13 +1856,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) &&
@@ -1648,43 +1873,47 @@ 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)
     {
-      bgp_attr_unintern (attr_new2);
+      bgp_attr_unintern (&attr_new2);
 
       reason = "import-policy;";
       goto filtered;
     }
 
   attr_new = bgp_attr_intern (&new_attr);
-  bgp_attr_unintern (attr_new2);
+  bgp_attr_unintern (&attr_new2);
 
   /* IPv4 unicast next hop check.  */
-  if (afi == AFI_IP && safi == SAFI_UNICAST)
+  if ((afi == AFI_IP) && ((safi == SAFI_UNICAST) || safi == SAFI_MULTICAST))
     {
-     /* Next hop must not be 0.0.0.0 nor Class E address. */
+     /* Next hop must not be 0.0.0.0 nor Class D/E address. */
       if (new_attr.nexthop.s_addr == 0
-         || ntohl (new_attr.nexthop.s_addr) >= 0xe0000000)
+         || IPV4_CLASS_DE (ntohl (new_attr.nexthop.s_addr)))
        {
-         bgp_attr_unintern (attr_new);
+         bgp_attr_unintern (&attr_new);
 
          reason = "martian next-hop;";
          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)
     {
-      ri->uptime = time (NULL);
+      ri->uptime = bgp_clock ();
 
       /* Same attribute comes in. */
-      if (attrhash_cmp (ri->attr, attr_new))
+      if (!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
+          && attrhash_cmp (ri->attr, attr_new))
         {
 
-          UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+          bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
 
           if (BGP_DEBUG (update, UPDATE_IN))
             zlog (peer->log, LOG_DEBUG,
@@ -1693,12 +1922,16 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
                     inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
                     p->prefixlen, rsclient->host);
 
-                    bgp_unlock_node (rn);
-                    bgp_attr_unintern (attr_new);
+          bgp_unlock_node (rn);
+          bgp_attr_unintern (&attr_new);
 
-                    return;
+          return;
         }
 
+      /* Withdraw/Announce before we fully processed the withdraw */
+      if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
+        bgp_info_restore (rn, ri);
+      
       /* Received Logging. */
       if (BGP_DEBUG (update, UPDATE_IN))
         zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d for RS-client %s",
@@ -1707,17 +1940,17 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
                 p->prefixlen, rsclient->host);
 
       /* The attribute is changed. */
-      SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+      bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
 
       /* Update to new attribute.  */
-      bgp_attr_unintern (ri->attr);
+      bgp_attr_unintern (&ri->attr);
       ri->attr = attr_new;
 
       /* Update MPLS tag.  */
       if (safi == SAFI_MPLS_VPN)
-        memcpy (ri->tag, tag, 3);
+        memcpy ((bgp_info_extra_get (ri))->tag, tag, 3);
 
-      SET_FLAG (ri->flags, BGP_INFO_VALID);
+      bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
 
       /* Process change. */
       bgp_process (bgp, rn, afi, safi);
@@ -1741,13 +1974,13 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
   new->sub_type = sub_type;
   new->peer = peer;
   new->attr = attr_new;
-  new->uptime = time (NULL);
+  new->uptime = bgp_clock ();
 
   /* Update MPLS tag. */
   if (safi == SAFI_MPLS_VPN)
-    memcpy (new->tag, tag, 3);
+    memcpy ((bgp_info_extra_get (new))->tag, tag, 3);
 
-  SET_FLAG (new->flags, BGP_INFO_VALID);
+  bgp_info_set_flag (rn, new, BGP_INFO_VALID);
 
   /* Register new BGP information. */
   bgp_info_add (rn, new);
@@ -1757,7 +1990,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: 
@@ -1774,7 +2009,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;
 }
 
@@ -1782,13 +2020,13 @@ static void
 bgp_withdraw_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
       struct peer *peer, struct prefix *p, int type, int sub_type,
       struct prefix_rd *prd, u_char *tag)
-    {
+{
   struct bgp_node *rn;
   struct bgp_info *ri;
   char buf[SU_ADDRSTRLEN];
 
   if (rsclient == peer)
-       return;
+    return;
 
   rn = bgp_afi_node_get (rsclient->rib[afi][safi], afi, safi, p, prd);
 
@@ -1807,8 +2045,8 @@ bgp_withdraw_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
           p->prefixlen);
 
   /* Unlock bgp_node_get() lock. */
-      bgp_unlock_node (rn);
-    }
+  bgp_unlock_node (rn);
+}
 
 static int
 bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
@@ -1819,7 +2057,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;
@@ -1828,7 +2066,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)
@@ -1865,7 +2103,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;
@@ -1886,7 +2124,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)
     {
@@ -1900,18 +2138,18 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
       /* If the peer is EBGP and nexthop is not on connected route,
         discard it.  */
       if (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl == 1
-         && ! bgp_nexthop_check_ebgp (afi, &new_attr)
+         && ! bgp_nexthop_onlink (afi, &new_attr)
          && ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
        {
          reason = "non-connected next-hop;";
          goto filtered;
        }
 
-      /* Next hop must not be 0.0.0.0 nor Class E address.  Next hop
+      /* Next hop must not be 0.0.0.0 nor Class D/E address. Next hop
         must not be my own address.  */
       if (bgp_nexthop_self (afi, &new_attr)
          || new_attr.nexthop.s_addr == 0
-         || ntohl (new_attr.nexthop.s_addr) >= 0xe0000000)
+         || IPV4_CLASS_DE (ntohl (new_attr.nexthop.s_addr)))
        {
          reason = "martian next-hop;";
          goto filtered;
@@ -1923,12 +2161,13 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
   /* If the update is implicit withdraw. */
   if (ri)
     {
-      ri->uptime = time (NULL);
+      ri->uptime = bgp_clock ();
 
       /* Same attribute comes in. */
-      if (attrhash_cmp (ri->attr, attr_new))
+      if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED) 
+          && attrhash_cmp (ri->attr, attr_new))
        {
-         UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+         bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
 
          if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
              && peer_sort (peer) == BGP_PEER_EBGP
@@ -1940,15 +2179,13 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
                  inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
                  p->prefixlen);
 
-             peer->pcount[afi][safi]++;
-             ret = bgp_damp_update (ri, rn, afi, safi);
-             if (ret != BGP_DAMP_SUPPRESSED)
-               {
-                 bgp_aggregate_increment (bgp, p, ri, afi, safi);
-                 bgp_process (bgp, rn, afi, safi);
-               }
+             if (bgp_damp_update (ri, rn, afi, safi) != BGP_DAMP_SUPPRESSED)
+               {
+                  bgp_aggregate_increment (bgp, p, ri, afi, safi);
+                  bgp_process (bgp, rn, afi, safi);
+                }
            }
-         else
+          else /* Duplicate - odd */
            {
              if (BGP_DEBUG (update, UPDATE_IN))  
                zlog (peer->log, LOG_DEBUG,
@@ -1960,16 +2197,29 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
              /* graceful restart STALE flag unset. */
              if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
                {
-                 UNSET_FLAG (ri->flags, BGP_INFO_STALE);
-                 peer->pcount[afi][safi]++;
+                 bgp_info_unset_flag (rn, ri, BGP_INFO_STALE);
+                 bgp_process (bgp, rn, afi, safi);
                }
            }
 
          bgp_unlock_node (rn);
-         bgp_attr_unintern (attr_new);
+         bgp_attr_unintern (&attr_new);
+         bgp_attr_extra_free (&new_attr);
+         
          return 0;
        }
 
+      /* Withdraw/Announce before we fully processed the withdraw */
+      if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
+        {
+          if (BGP_DEBUG (update, UPDATE_IN))
+            zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d, flapped quicker than processing",
+            peer->host,
+            inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+            p->prefixlen);
+          bgp_info_restore (rn, ri);
+        }
+
       /* Received Logging. */
       if (BGP_DEBUG (update, UPDATE_IN))  
        zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d",
@@ -1979,14 +2229,16 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
 
       /* graceful restart STALE flag unset. */
       if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
-       {
-         UNSET_FLAG (ri->flags, BGP_INFO_STALE);
-         peer->pcount[afi][safi]++;
-       }
+       bgp_info_unset_flag (rn, ri, BGP_INFO_STALE);
 
       /* The attribute is changed. */
-      SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
-
+      bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
+      
+      /* implicit withdraw, decrement aggregate and pcount here.
+       * only if update is accepted, they'll increment below.
+       */
+      bgp_aggregate_decrement (bgp, p, ri, afi, safi);
+      
       /* Update bgp route dampening information.  */
       if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
          && peer_sort (peer) == BGP_PEER_EBGP)
@@ -1995,19 +2247,15 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
             information.  */
          if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
            bgp_damp_withdraw (ri, rn, afi, safi, 1);  
-         else
-           peer->pcount[afi][safi]++;
        }
        
-      bgp_aggregate_decrement (bgp, p, ri, afi, safi);
-
       /* Update to new attribute.  */
-      bgp_attr_unintern (ri->attr);
+      bgp_attr_unintern (&ri->attr);
       ri->attr = attr_new;
 
       /* 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)
@@ -2018,6 +2266,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;
            }
        }
@@ -2026,22 +2275,25 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
       if ((afi == AFI_IP || afi == AFI_IP6)
          && safi == SAFI_UNICAST 
          && (peer_sort (peer) == BGP_PEER_IBGP
+              || peer_sort (peer) == BGP_PEER_CONFED
              || (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1)
              || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)))
        {
          if (bgp_nexthop_lookup (afi, peer, ri, NULL, NULL))
-           SET_FLAG (ri->flags, BGP_INFO_VALID);
+           bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
          else
-           UNSET_FLAG (ri->flags, BGP_INFO_VALID);
+           bgp_info_unset_flag (rn, ri, BGP_INFO_VALID);
        }
       else
-       SET_FLAG (ri->flags, BGP_INFO_VALID);
+        bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
 
       /* Process change. */
       bgp_aggregate_increment (bgp, p, ri, afi, safi);
 
       bgp_process (bgp, rn, afi, safi);
       bgp_unlock_node (rn);
+      bgp_attr_extra_free (&new_attr);
+      
       return 0;
     }
 
@@ -2054,37 +2306,35 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
            p->prefixlen);
     }
 
-  /* Increment prefix counter */
-  peer->pcount[afi][safi]++;
-
   /* Make new BGP info. */
   new = bgp_info_new ();
   new->type = type;
   new->sub_type = sub_type;
   new->peer = peer;
   new->attr = attr_new;
-  new->uptime = time (NULL);
+  new->uptime = bgp_clock ();
 
   /* 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)
       && safi == SAFI_UNICAST
       && (peer_sort (peer) == BGP_PEER_IBGP
+          || peer_sort (peer) == BGP_PEER_CONFED
          || (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1)
          || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)))
     {
       if (bgp_nexthop_lookup (afi, peer, new, NULL, NULL))
-       SET_FLAG (new->flags, BGP_INFO_VALID);
+       bgp_info_set_flag (rn, new, BGP_INFO_VALID);
       else
-       UNSET_FLAG (new->flags, BGP_INFO_VALID);
+        bgp_info_unset_flag (rn, new, BGP_INFO_VALID);
     }
   else
-    SET_FLAG (new->flags, BGP_INFO_VALID);
+    bgp_info_set_flag (rn, new, BGP_INFO_VALID);
 
-  /* Aggregate address increment. */
+  /* Increment prefix */
   bgp_aggregate_increment (bgp, p, new, afi, safi);
   
   /* Register new BGP information. */
@@ -2093,6 +2343,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))
@@ -2117,7 +2369,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;
 }
 
@@ -2208,16 +2462,19 @@ void
 bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw)
 {
   struct bgp *bgp;
-  struct attr attr;
-  struct aspath *aspath;
+  struct attr attr = { 0 };
+  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;
@@ -2228,26 +2485,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)
     {
@@ -2279,8 +2540,9 @@ 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);
     }
-
-  aspath_unintern (aspath);
+  
+  bgp_attr_extra_free (&attr);
+  aspath_unintern (&aspath);
 }
 \f
 static void
@@ -2289,8 +2551,8 @@ bgp_announce_table (struct peer *peer, afi_t afi, safi_t safi,
 {
   struct bgp_node *rn;
   struct bgp_info *ri;
-  struct attr attr;
-
+  struct attr attr = { 0 };
+  
   if (! table)
     table = (rsclient) ? peer->rib[afi][safi] : peer->bgp->rib[afi][safi];
 
@@ -2308,6 +2570,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);
        }
 }
 
@@ -2431,157 +2695,250 @@ bgp_soft_reconfig_in (struct peer *peer, afi_t afi, safi_t safi)
        bgp_soft_reconfig_table (peer, afi, safi, table);
 }
 \f
+
 struct bgp_clear_node_queue
 {
   struct bgp_node *rn;
-  struct peer *peer;
-  afi_t afi;
-  safi_t safi;
+  enum bgp_clear_route_type purpose;
 };
 
 static wq_item_status
-bgp_clear_route_node (struct bgp_clear_node_queue *cq)
+bgp_clear_route_node (struct work_queue *wq, void *data)
 {
-  struct bgp_adj_in *ain;
-  struct bgp_adj_out *aout;
+  struct bgp_clear_node_queue *cnq = data;
+  struct bgp_node *rn = cnq->rn;
+  struct peer *peer = wq->spec.data;
   struct bgp_info *ri;
+  afi_t afi = rn->table->afi;
+  safi_t safi = rn->table->safi;
   
-  assert (cq->rn && cq->peer);
+  assert (rn && peer);
   
-  for (ri = cq->rn->info; ri; ri = ri->next)
-    if (ri->peer == cq->peer)
+  for (ri = rn->info; ri; ri = ri->next)
+    if (ri->peer == peer || cnq->purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
       {
         /* graceful restart STALE flag set. */
-        if (CHECK_FLAG (cq->peer->sflags, PEER_STATUS_NSF_WAIT)
-            && cq->peer->nsf[cq->afi][cq->safi]
+        if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)
+            && peer->nsf[afi][safi]
             && ! CHECK_FLAG (ri->flags, BGP_INFO_STALE)
-            && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)
-            && ! CHECK_FLAG (ri->flags, BGP_INFO_DAMPED))
-          {
-            SET_FLAG (ri->flags, BGP_INFO_STALE);
-            cq->peer->pcount[cq->afi][cq->safi]--;
-          }
+            && ! CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
+          bgp_info_set_flag (rn, ri, BGP_INFO_STALE);
         else
-          bgp_rib_remove (cq->rn, ri, cq->peer, cq->afi, cq->safi);
-        break;
-      }
-  for (ain = cq->rn->adj_in; ain; ain = ain->next)
-    if (ain->peer == cq->peer)
-      {
-        bgp_adj_in_remove (cq->rn, ain);
-        bgp_unlock_node (cq->rn);
-        break;
-      }
-  for (aout = cq->rn->adj_out; aout; aout = aout->next)
-    if (aout->peer == cq->peer)
-      {
-        bgp_adj_out_remove (cq->rn, aout, cq->peer, cq->afi, cq->safi);
-        bgp_unlock_node (cq->rn);
+          bgp_rib_remove (rn, ri, peer, afi, safi);
         break;
       }
   return WQ_SUCCESS;
 }
 
 static void
-bgp_clear_node_queue_del (struct bgp_clear_node_queue *cq)
+bgp_clear_node_queue_del (struct work_queue *wq, void *data)
 {
-  bgp_unlock_node (cq->rn); 
-  peer_unlock (cq->peer); /* bgp_clear_node_queue_del */
-  XFREE (MTYPE_BGP_CLEAR_NODE_QUEUE, cq);
+  struct bgp_clear_node_queue *cnq = data;
+  struct bgp_node *rn = cnq->rn;
+  struct bgp_table *table = rn->table;
+  
+  bgp_unlock_node (rn); 
+  bgp_table_unlock (table);
+  XFREE (MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
 }
 
 static void
 bgp_clear_node_complete (struct work_queue *wq)
 {
-  /* unplug the 2 processing queues */
-  if (bm->process_main_queue)
-    work_queue_unplug (bm->process_main_queue);
-  if (bm->process_rsclient_queue)
-    work_queue_unplug (bm->process_rsclient_queue);
+  struct peer *peer = wq->spec.data;
+  
+  /* Tickle FSM to start moving again */
+  BGP_EVENT_ADD (peer, Clearing_Completed);
+
+  peer_unlock (peer); /* bgp_clear_route */
 }
 
 static void
-bgp_clear_node_queue_init (void)
+bgp_clear_node_queue_init (struct peer *peer)
 {
-  if ( (bm->clear_node_queue
-          = work_queue_new (bm->master, "clear_route_node")) == NULL)
+  char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
+  
+  snprintf (wname, sizeof(wname), "clear %s", peer->host);
+#undef CLEAR_QUEUE_NAME_LEN
+
+  if ( (peer->clear_node_queue = work_queue_new (bm->master, wname)) == NULL)
     {
       zlog_err ("%s: Failed to allocate work queue", __func__);
       exit (1);
     }
-  bm->clear_node_queue->spec.hold = 10;
-  bm->clear_node_queue->spec.delay = 0; /* no gathering to be gained */
-  bm->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
-  bm->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
-  bm->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
-  bm->clear_node_queue->spec.max_retries = 0;
+  peer->clear_node_queue->spec.hold = 10;
+  peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
+  peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
+  peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
+  peer->clear_node_queue->spec.max_retries = 0;
+  
+  /* we only 'lock' this peer reference when the queue is actually active */
+  peer->clear_node_queue->spec.data = peer;
 }
 
 static void
 bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi,
-                      struct bgp_table *table, struct peer *rsclient)
+                       struct bgp_table *table, struct peer *rsclient,
+                       enum bgp_clear_route_type purpose)
 {
-  struct bgp_clear_node_queue *cqnode;
   struct bgp_node *rn;
   
+  
   if (! table)
     table = (rsclient) ? rsclient->rib[afi][safi] : peer->bgp->rib[afi][safi];
-
+  
   /* If still no table => afi/safi isn't configured at all or smth. */
   if (! table)
     return;
-
-  if (bm->clear_node_queue == NULL)
-    bgp_clear_node_queue_init ();
-  
-  /* plug the two bgp_process queues to avoid any chance of racing
-   * with a session coming back up and adding routes before we've
-   * cleared them all. We'll unplug them with completion callback.
-   */
-  if (bm->process_main_queue)
-    work_queue_plug (bm->process_main_queue);
-  if (bm->process_rsclient_queue)
-    work_queue_plug (bm->process_rsclient_queue);
   
   for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
     {
-      if (rn->info == NULL)
-        continue;
+      struct bgp_info *ri;
+      struct bgp_adj_in *ain;
+      struct bgp_adj_out *aout;
       
-      if ( (cqnode = XCALLOC (MTYPE_BGP_CLEAR_NODE_QUEUE, 
-                              sizeof (struct bgp_clear_node_queue))) == NULL)
+      if (rn->info == NULL)
         continue;
-      
-      cqnode->rn = bgp_lock_node (rn); /* unlocked: bgp_clear_node_queue_del */
-      cqnode->afi = afi;
-      cqnode->safi = safi;
-      cqnode->peer = peer_lock (peer); /* bgp_clear_node_queue_del */
-      work_queue_add (bm->clear_node_queue, cqnode);
+
+      /* XXX:TODO: This is suboptimal, every non-empty route_node is
+       * queued for every clearing peer, regardless of whether it is
+       * relevant to the peer at hand.
+       *
+       * Overview: There are 3 different indices which need to be
+       * scrubbed, potentially, when a peer is removed:
+       *
+       * 1 peer's routes visible via the RIB (ie accepted routes)
+       * 2 peer's routes visible by the (optional) peer's adj-in index
+       * 3 other routes visible by the peer's adj-out index
+       *
+       * 3 there is no hurry in scrubbing, once the struct peer is
+       * removed from bgp->peer, we could just GC such deleted peer's
+       * adj-outs at our leisure.
+       *
+       * 1 and 2 must be 'scrubbed' in some way, at least made
+       * invisible via RIB index before peer session is allowed to be
+       * brought back up. So one needs to know when such a 'search' is
+       * complete.
+       *
+       * Ideally:
+       *
+       * - there'd be a single global queue or a single RIB walker
+       * - rather than tracking which route_nodes still need to be
+       *   examined on a peer basis, we'd track which peers still
+       *   aren't cleared
+       *
+       * Given that our per-peer prefix-counts now should be reliable,
+       * this may actually be achievable. It doesn't seem to be a huge
+       * problem at this time,
+       */
+      for (ri = rn->info; ri; ri = ri->next)
+        if (ri->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
+          {
+            struct bgp_clear_node_queue *cnq;
+
+            /* both unlocked in bgp_clear_node_queue_del */
+            bgp_table_lock (rn->table);
+            bgp_lock_node (rn);
+            cnq = XCALLOC (MTYPE_BGP_CLEAR_NODE_QUEUE,
+                           sizeof (struct bgp_clear_node_queue));
+            cnq->rn = rn;
+            cnq->purpose = purpose;
+            work_queue_add (peer->clear_node_queue, cnq);
+            break;
+          }
+
+      for (ain = rn->adj_in; ain; ain = ain->next)
+        if (ain->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
+          {
+            bgp_adj_in_remove (rn, ain);
+            bgp_unlock_node (rn);
+            break;
+          }
+      for (aout = rn->adj_out; aout; aout = aout->next)
+        if (aout->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
+          {
+            bgp_adj_out_remove (rn, aout, peer, afi, safi);
+            bgp_unlock_node (rn);
+            break;
+          }
     }
   return;
 }
 
 void
-bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi)
+bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi,
+                 enum bgp_clear_route_type purpose)
 {
   struct bgp_node *rn;
   struct bgp_table *table;
   struct peer *rsclient;
   struct listnode *node, *nnode;
 
-  if (safi != SAFI_MPLS_VPN)
-    bgp_clear_route_table (peer, afi, safi, NULL, NULL);
-  else
-    for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
-        rn = bgp_route_next (rn))
-      if ((table = rn->info) != NULL)
-       bgp_clear_route_table (peer, afi, safi, table, NULL);
+  if (peer->clear_node_queue == NULL)
+    bgp_clear_node_queue_init (peer);
+  
+  /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
+   * Idle until it receives a Clearing_Completed event. This protects
+   * against peers which flap faster than we can we clear, which could
+   * lead to:
+   *
+   * a) race with routes from the new session being installed before
+   *    clear_route_node visits the node (to delete the route of that
+   *    peer)
+   * b) resource exhaustion, clear_route_node likely leads to an entry
+   *    on the process_main queue. Fast-flapping could cause that queue
+   *    to grow and grow.
+   */
+  if (!peer->clear_node_queue->thread)
+    peer_lock (peer); /* bgp_clear_node_complete */
 
-  for (ALL_LIST_ELEMENTS (peer->bgp->rsclient, node, nnode, rsclient))
+  switch (purpose)
     {
-      if (CHECK_FLAG(rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
-        bgp_clear_route_table (peer, afi, safi, NULL, rsclient);
+    case BGP_CLEAR_ROUTE_NORMAL:
+      if (safi != SAFI_MPLS_VPN)
+        bgp_clear_route_table (peer, afi, safi, NULL, NULL, purpose);
+      else
+        for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
+             rn = bgp_route_next (rn))
+          if ((table = rn->info) != NULL)
+            bgp_clear_route_table (peer, afi, safi, table, NULL, purpose);
+
+      for (ALL_LIST_ELEMENTS (peer->bgp->rsclient, node, nnode, rsclient))
+        if (CHECK_FLAG(rsclient->af_flags[afi][safi],
+                       PEER_FLAG_RSERVER_CLIENT))
+          bgp_clear_route_table (peer, afi, safi, NULL, rsclient, purpose);
+      break;
+
+    case BGP_CLEAR_ROUTE_MY_RSCLIENT:
+      bgp_clear_route_table (peer, afi, safi, NULL, peer, purpose);
+      break;
+
+    default:
+      assert (0);
+      break;
     }
+  
+  /* If no routes were cleared, nothing was added to workqueue, the
+   * completion function won't be run by workqueue code - call it here. 
+   * XXX: Actually, this assumption doesn't hold, see
+   * bgp_clear_route_table(), we queue all non-empty nodes.
+   *
+   * Additionally, there is a presumption in FSM that clearing is only
+   * really needed if peer state is Established - peers in
+   * pre-Established states shouldn't have any route-update state
+   * associated with them (in or out).
+   *
+   * We still can get here in pre-Established though, through
+   * peer_delete -> bgp_fsm_change_status, so this is a useful sanity
+   * check to ensure the assumption above holds.
+   *
+   * At some future point, this check could be move to the top of the
+   * function, and do a quick early-return when state is
+   * pre-Established, avoiding above list and table scans. Once we're
+   * sure it is safe..
+   */
+  if (!peer->clear_node_queue->thread)
+    bgp_clear_node_complete (peer->clear_node_queue);
 }
   
 void
@@ -2592,7 +2949,7 @@ bgp_clear_route_all (struct peer *peer)
 
   for (afi = AFI_IP; afi < AFI_MAX; afi++)
     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
-      bgp_clear_route (peer, afi, safi);
+      bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
 }
 
 void
@@ -2637,7 +2994,7 @@ bgp_clear_stale_route (struct peer *peer, afi_t afi, safi_t safi)
 \f
 /* Delete all kernel routes. */
 void
-bgp_cleanup_routes ()
+bgp_cleanup_routes (void)
 {
   struct bgp *bgp;
   struct listnode *node, *nnode;
@@ -2654,7 +3011,7 @@ bgp_cleanup_routes ()
          if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
              && ri->type == ZEBRA_ROUTE_BGP 
              && ri->sub_type == BGP_ROUTE_NORMAL)
-           bgp_zebra_withdraw (&rn->p, ri);
+           bgp_zebra_withdraw (&rn->p, ri,SAFI_UNICAST);
 
       table = bgp->rib[AFI_IP6][SAFI_UNICAST];
 
@@ -2663,12 +3020,12 @@ bgp_cleanup_routes ()
          if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
              && ri->type == ZEBRA_ROUTE_BGP 
              && ri->sub_type == BGP_ROUTE_NORMAL)
-           bgp_zebra_withdraw (&rn->p, ri);
+           bgp_zebra_withdraw (&rn->p, ri,SAFI_UNICAST);
     }
 }
 
 void
-bgp_reset ()
+bgp_reset (void)
 {
   vty_reset ();
   bgp_zclient_reset ();
@@ -2840,12 +3197,9 @@ bgp_nlri_sanity_check (struct peer *peer, int afi, u_char *pnt,
 }
 \f
 static struct bgp_static *
-bgp_static_new ()
+bgp_static_new (void)
 {
-  struct bgp_static *new;
-  new = XMALLOC (MTYPE_BGP_STATIC, sizeof (struct bgp_static));
-  memset (new, 0, sizeof (struct bgp_static));
-  return new;
+  return XCALLOC (MTYPE_BGP_STATIC, sizeof (struct bgp_static));
 }
 
 static void
@@ -2875,9 +3229,8 @@ bgp_static_withdraw_rsclient (struct bgp *bgp, struct peer *rsclient,
   /* Withdraw static BGP route from routing table. */
   if (ri)
     {
-      UNSET_FLAG (ri->flags, BGP_INFO_VALID);
-      bgp_process (bgp, rn, afi, safi);
       bgp_info_delete (rn, ri);
+      bgp_process (bgp, rn, afi, safi);
     }
 
   /* Unlock bgp_node_lookup. */
@@ -2886,39 +3239,44 @@ 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];
 
   bgp = rsclient->bgp;
 
+  assert (bgp_static);
+  if (!bgp_static)
+    return;
+
   rn = bgp_afi_node_get (rsclient->rib[afi][safi], afi, safi, p, NULL);
 
   bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
-  if (bgp_static)
-    {
-      attr.nexthop = bgp_static->igpnexthop;
-      attr.med = bgp_static->igpmetric;
-      attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
-    }
-
-  new_attr = attr;
 
+  attr.nexthop = bgp_static->igpnexthop;
+  attr.med = bgp_static->igpmetric;
+  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
+  
+  if (bgp_static->atomic)
+    attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
+  
   /* 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);
 
@@ -2929,25 +3287,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);
+          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;
-
+  
+  bgp_attr_dup(&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,
@@ -2957,18 +3317,20 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
 
       bgp->peer_self->rmap_type = 0;
 
-      bgp_attr_unintern (attr_new);
-      aspath_unintern (attr.aspath);
+      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;
 
-  bgp_attr_unintern (attr_new);
+  bgp_attr_unintern (&attr_new);
   attr_new = bgp_attr_intern (&new_attr);
+  bgp_attr_extra_free (&new_attr);
 
   for (ri = rn->info; ri; ri = ri->next)
     if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
@@ -2977,31 +3339,36 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
 
   if (ri)
        {
-      if (attrhash_cmp (ri->attr, attr_new))
+      if (attrhash_cmp (ri->attr, attr_new) &&
+         !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
         {
           bgp_unlock_node (rn);
-          bgp_attr_unintern (attr_new);
-          aspath_unintern (attr.aspath);
+          bgp_attr_unintern (&attr_new);
+          aspath_unintern (&attr.aspath);
+          bgp_attr_extra_free (&attr);
           return;
        }
       else
         {
           /* The attribute is changed. */
-          SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+          bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
 
           /* Rewrite BGP route information. */
-          bgp_attr_unintern (ri->attr);
+         if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
+           bgp_info_restore(rn, ri);
+          bgp_attr_unintern (&ri->attr);
           ri->attr = attr_new;
-          ri->uptime = time (NULL);
+          ri->uptime = bgp_clock ();
 
           /* Process change. */
           bgp_process (bgp, rn, afi, safi);
           bgp_unlock_node (rn);
-          aspath_unintern (attr.aspath);
+          aspath_unintern (&attr.aspath);
+          bgp_attr_extra_free (&attr);
           return;
+        }
     }
-}
-\f
+  
   /* Make new BGP info. */
   new = bgp_info_new ();
   new->type = ZEBRA_ROUTE_BGP;
@@ -3009,7 +3376,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
   new->peer = bgp->peer_self;
   SET_FLAG (new->flags, BGP_INFO_VALID);
   new->attr = attr_new;
-  new->uptime = time (NULL);
+  new->uptime = bgp_clock ();
 
   /* Register new BGP information. */
   bgp_info_add (rn, new);
@@ -3021,7 +3388,8 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
   bgp_process (bgp, rn, afi, safi);
 
   /* Unintern original. */
-  aspath_unintern (attr.aspath);
+  aspath_unintern (&attr.aspath);
+  bgp_attr_extra_free (&attr);
 }
 
 static void
@@ -3032,25 +3400,29 @@ 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;
 
+  assert (bgp_static);
+  if (!bgp_static)
+    return;
+
   rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, NULL);
 
   bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
-  if (bgp_static)
-    {
-      attr.nexthop = bgp_static->igpnexthop;
-      attr.med = bgp_static->igpmetric;
-      attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
-    }
+  
+  attr.nexthop = bgp_static->igpnexthop;
+  attr.med = bgp_static->igpmetric;
+  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
+
+  if (bgp_static->atomic)
+    attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
 
   /* 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;
 
@@ -3066,7 +3438,8 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
          bgp_attr_flush (&attr_tmp);
 
          /* Unintern original. */
-         aspath_unintern (attr.aspath);
+         aspath_unintern (&attr.aspath);
+         bgp_attr_extra_free (&attr);
          bgp_static_withdraw (bgp, p, afi, safi);
          return;
        }
@@ -3082,29 +3455,35 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
 
   if (ri)
     {
-      if (attrhash_cmp (ri->attr, attr_new))
+      if (attrhash_cmp (ri->attr, attr_new) &&
+         !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
        {
          bgp_unlock_node (rn);
-         bgp_attr_unintern (attr_new);
-         aspath_unintern (attr.aspath);
+         bgp_attr_unintern (&attr_new);
+         aspath_unintern (&attr.aspath);
+         bgp_attr_extra_free (&attr);
          return;
        }
       else
        {
          /* The attribute is changed. */
-         SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+         bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
 
          /* Rewrite BGP route information. */
-         bgp_aggregate_decrement (bgp, p, ri, afi, safi);
-         bgp_attr_unintern (ri->attr);
+         if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
+           bgp_info_restore(rn, ri);
+         else
+           bgp_aggregate_decrement (bgp, p, ri, afi, safi);
+         bgp_attr_unintern (&ri->attr);
          ri->attr = attr_new;
-         ri->uptime = time (NULL);
+         ri->uptime = bgp_clock ();
 
          /* Process change. */
          bgp_aggregate_increment (bgp, p, ri, afi, safi);
          bgp_process (bgp, rn, afi, safi);
          bgp_unlock_node (rn);
-         aspath_unintern (attr.aspath);
+         aspath_unintern (&attr.aspath);
+         bgp_attr_extra_free (&attr);
          return;
        }
     }
@@ -3116,7 +3495,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
   new->peer = bgp->peer_self;
   SET_FLAG (new->flags, BGP_INFO_VALID);
   new->attr = attr_new;
-  new->uptime = time (NULL);
+  new->uptime = bgp_clock ();
 
   /* Aggregate address increment. */
   bgp_aggregate_increment (bgp, p, new, afi, safi);
@@ -3131,7 +3510,8 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
   bgp_process (bgp, rn, afi, safi);
 
   /* Unintern original. */
-  aspath_unintern (attr.aspath);
+  aspath_unintern (&attr.aspath);
+  bgp_attr_extra_free (&attr);
 }
 
 void
@@ -3145,17 +3525,18 @@ bgp_static_update (struct bgp *bgp, struct prefix *p,
 
   for (ALL_LIST_ELEMENTS (bgp->rsclient, node, nnode, rsclient))
     {
-      bgp_static_update_rsclient (rsclient, p, bgp_static, afi, safi);
+      if (CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
+        bgp_static_update_rsclient (rsclient, p, bgp_static, afi, safi);
     }
 }
 
 static void
-bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi,
-                        u_char safi, struct prefix_rd *prd, u_char *tag)
+bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi,
+                        safi_t safi, struct prefix_rd *prd, u_char *tag)
 {
   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. */
@@ -3165,8 +3546,9 @@ bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi,
   new->peer = bgp->peer_self;
   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->uptime = bgp_clock ();
+  new->extra = bgp_info_extra_new();
+  memcpy (new->extra->tag, tag, 3);
 
   /* Aggregate address increment. */
   bgp_aggregate_increment (bgp, p, new, afi, safi);
@@ -3201,9 +3583,8 @@ bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi,
   if (ri)
     {
       bgp_aggregate_decrement (bgp, p, ri, afi, safi);
-      UNSET_FLAG (ri->flags, BGP_INFO_VALID);
-      bgp_process (bgp, rn, afi, safi);
       bgp_info_delete (rn, ri);
+      bgp_process (bgp, rn, afi, safi);
     }
 
   /* Unlock bgp_node_lookup. */
@@ -3231,8 +3612,8 @@ bgp_check_local_routes_rsclient (struct peer *rsclient, afi_t afi, safi_t safi)
 }
 
 static void
-bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi,
-                          u_char safi, struct prefix_rd *prd, u_char *tag)
+bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi,
+                          safi_t safi, struct prefix_rd *prd, u_char *tag)
 {
   struct bgp_node *rn;
   struct bgp_info *ri;
@@ -3250,9 +3631,8 @@ bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi,
   if (ri)
     {
       bgp_aggregate_decrement (bgp, p, ri, afi, safi);
-      UNSET_FLAG (ri->flags, BGP_INFO_VALID);
-      bgp_process (bgp, rn, afi, safi);
       bgp_info_delete (rn, ri);
+      bgp_process (bgp, rn, afi, safi);
     }
 
   /* Unlock bgp_node_lookup. */
@@ -3263,13 +3643,13 @@ bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi,
    route should be installed as valid.  */
 static int
 bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str, 
-                u_int16_t afi, u_char safi, const char *rmap, int backdoor)
+                afi_t afi, safi_t safi, const char *rmap, int backdoor)
 {
   int ret;
   struct prefix p;
   struct bgp_static *bgp_static;
   struct bgp_node *rn;
-  int need_update = 0;
+  u_char need_update = 0;
 
   /* Convert IP prefix string to struct prefix. */
   ret = str2prefix (ip_str, &p);
@@ -3298,10 +3678,11 @@ bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str,
       bgp_static = rn->info;
 
       /* Check previous routes are installed into BGP.  */
-      if (! bgp_static->backdoor && bgp_static->valid)
-       need_update = 1;
-
+      if (bgp_static->valid && bgp_static->backdoor != backdoor)
+        need_update = 1;
+      
       bgp_static->backdoor = backdoor;
+      
       if (rmap)
        {
          if (bgp_static->rmap.name)
@@ -3327,6 +3708,7 @@ bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str,
       bgp_static->valid = 0;
       bgp_static->igpmetric = 0;
       bgp_static->igpnexthop.s_addr = 0;
+      
       if (rmap)
        {
          if (bgp_static->rmap.name)
@@ -3355,7 +3737,7 @@ bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str,
 /* Configure static BGP network. */
 static int
 bgp_static_unset (struct vty *vty, struct bgp *bgp, const char *ip_str,
-                 u_int16_t afi, u_char safi)
+                 afi_t afi, safi_t safi)
 {
   int ret;
   struct prefix p;
@@ -3389,7 +3771,7 @@ bgp_static_unset (struct vty *vty, struct bgp *bgp, const char *ip_str,
     }
 
   bgp_static = rn->info;
-
+  
   /* Update BGP RIB. */
   if (! bgp_static->backdoor)
     bgp_static_withdraw (bgp, &p, afi, safi);
@@ -3488,7 +3870,7 @@ bgp_static_set_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str,
   prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN],
                        (struct prefix *)&prd);
   if (prn->info == NULL)
-    prn->info = bgp_table_init ();
+    prn->info = bgp_table_init (AFI_IP, SAFI_MPLS_VPN);
   else
     bgp_unlock_node (prn);
   table = prn->info;
@@ -3557,7 +3939,7 @@ bgp_static_unset_vpnv4 (struct vty *vty, const char *ip_str,
   prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN],
                        (struct prefix *)&prd);
   if (prn->info == NULL)
-    prn->info = bgp_table_init ();
+    prn->info = bgp_table_init (AFI_IP, SAFI_MPLS_VPN);
   else
     bgp_unlock_node (prn);
   table = prn->info;
@@ -3609,7 +3991,8 @@ DEFUN (bgp_network_backdoor,
        "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
        "Specify a BGP backdoor route\n")
 {
-  return bgp_static_set (vty, vty->index, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1);
+  return bgp_static_set (vty, vty->index, argv[0], AFI_IP, SAFI_UNICAST,
+                         NULL, 1);
 }
 
 DEFUN (bgp_network_mask,
@@ -3622,7 +4005,7 @@ DEFUN (bgp_network_mask,
 {
   int ret;
   char prefix_str[BUFSIZ];
-
+  
   ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
   if (! ret)
     {
@@ -3646,7 +4029,7 @@ DEFUN (bgp_network_mask_route_map,
 {
   int ret;
   char prefix_str[BUFSIZ];
-
+  
   ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
   if (! ret)
     {
@@ -3669,7 +4052,7 @@ DEFUN (bgp_network_mask_backdoor,
 {
   int ret;
   char prefix_str[BUFSIZ];
-
+  
   ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
   if (! ret)
     {
@@ -3677,7 +4060,8 @@ DEFUN (bgp_network_mask_backdoor,
       return CMD_WARNING;
     }
 
-  return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1);
+  return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST,
+                         NULL, 1);
 }
 
 DEFUN (bgp_network_mask_natural,
@@ -3739,7 +4123,8 @@ DEFUN (bgp_network_mask_natural_backdoor,
       return CMD_WARNING;
     }
 
-  return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1);
+  return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST,
+                         NULL, 1);
 }
 
 DEFUN (no_bgp_network,
@@ -3859,7 +4244,8 @@ DEFUN (ipv6_bgp_network,
        "Specify a network to announce via BGP\n"
        "IPv6 prefix <network>/<length>\n")
 {
-  return bgp_static_set (vty, vty->index, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0);
+  return bgp_static_set (vty, vty->index, argv[0], AFI_IP6, bgp_node_safi(vty),
+                         NULL, 0);
 }
 
 DEFUN (ipv6_bgp_network_route_map,
@@ -3881,7 +4267,7 @@ DEFUN (no_ipv6_bgp_network,
        "Specify a network to announce via BGP\n"
        "IPv6 prefix <network>/<length>\n")
 {
-  return bgp_static_unset (vty, vty->index, argv[0], AFI_IP6, SAFI_UNICAST);
+  return bgp_static_unset (vty, vty->index, argv[0], AFI_IP6, bgp_node_safi(vty));
 }
 
 ALIAS (no_ipv6_bgp_network,
@@ -3910,6 +4296,129 @@ ALIAS (no_ipv6_bgp_network,
        "Specify a network to announce via BGP\n"
        "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
 #endif /* HAVE_IPV6 */
+
+/* stubs for removed AS-Pathlimit commands, kept for config compatibility */
+ALIAS_DEPRECATED (bgp_network,
+       bgp_network_ttl_cmd,
+       "network A.B.C.D/M pathlimit <0-255>",
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (bgp_network_backdoor,
+       bgp_network_backdoor_ttl_cmd,
+       "network A.B.C.D/M backdoor pathlimit <0-255>",
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Specify a BGP backdoor route\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (bgp_network_mask,
+       bgp_network_mask_ttl_cmd,
+       "network A.B.C.D mask A.B.C.D pathlimit <0-255>",
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Network mask\n"
+       "Network mask\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (bgp_network_mask_backdoor,
+       bgp_network_mask_backdoor_ttl_cmd,
+       "network A.B.C.D mask A.B.C.D backdoor pathlimit <0-255>",
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Network mask\n"
+       "Network mask\n"
+       "Specify a BGP backdoor route\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (bgp_network_mask_natural,
+       bgp_network_mask_natural_ttl_cmd,
+       "network A.B.C.D pathlimit <0-255>",
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (bgp_network_mask_natural_backdoor,
+       bgp_network_mask_natural_backdoor_ttl_cmd,
+       "network A.B.C.D backdoor pathlimit (1-255>",
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Specify a BGP backdoor route\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_bgp_network,
+       no_bgp_network_ttl_cmd,
+       "no network A.B.C.D/M pathlimit <0-255>",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_bgp_network,
+       no_bgp_network_backdoor_ttl_cmd,
+       "no network A.B.C.D/M backdoor pathlimit <0-255>",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Specify a BGP backdoor route\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_bgp_network,
+       no_bgp_network_mask_ttl_cmd,
+       "no network A.B.C.D mask A.B.C.D pathlimit <0-255>",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Network mask\n"
+       "Network mask\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_bgp_network_mask,
+       no_bgp_network_mask_backdoor_ttl_cmd,
+       "no network A.B.C.D mask A.B.C.D  backdoor pathlimit <0-255>",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Network mask\n"
+       "Network mask\n"
+       "Specify a BGP backdoor route\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_bgp_network_mask_natural,
+       no_bgp_network_mask_natural_ttl_cmd,
+       "no network A.B.C.D pathlimit <0-255>",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_bgp_network_mask_natural,
+       no_bgp_network_mask_natural_backdoor_ttl_cmd,
+       "no network A.B.C.D backdoor pathlimit <0-255>",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Specify a BGP backdoor route\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+#ifdef HAVE_IPV6
+ALIAS_DEPRECATED (ipv6_bgp_network,
+       ipv6_bgp_network_ttl_cmd,
+       "network X:X::X:X/M pathlimit <0-255>",
+       "Specify a network to announce via BGP\n"
+       "IPv6 prefix <network>/<length>\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_ipv6_bgp_network,
+       no_ipv6_bgp_network_ttl_cmd,
+       "no network X:X::X:X/M pathlimit <0-255>",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IPv6 prefix <network>/<length>\n"
+       "AS-Path hopcount limit attribute\n"
+       "AS-Pathlimit TTL, in number of AS-Path hops\n")
+#endif /* HAVE_IPV6 */
 \f
 /* Aggreagete address:
 
@@ -3940,12 +4449,9 @@ struct bgp_aggregate
 };
 
 static struct bgp_aggregate *
-bgp_aggregate_new ()
+bgp_aggregate_new (void)
 {
-  struct bgp_aggregate *new;
-  new = XMALLOC (MTYPE_BGP_AGGREGATE, sizeof (struct bgp_aggregate));
-  memset (new, 0, sizeof (struct bgp_aggregate));
-  return new;
+  return XCALLOC (MTYPE_BGP_AGGREGATE, sizeof (struct bgp_aggregate));
 }
 
 static void
@@ -4032,8 +4538,8 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew,
              {
                if (aggregate->summary_only)
                  {
-                   ri->suppress++;
-                   SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+                   (bgp_info_extra_get (ri))->suppress++;
+                   bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
                    match++;
                  }
 
@@ -4078,7 +4584,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)
        {
@@ -4118,7 +4624,7 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew,
       new->peer = bgp->peer_self;
       SET_FLAG (new->flags, BGP_INFO_VALID);
       new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set);
-      new->uptime = time (NULL);
+      new->uptime = bgp_clock ();
 
       bgp_info_add (rn, new);
       bgp_unlock_node (rn);
@@ -4235,8 +4741,8 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi,
                   route announcement.  */
                if (aggregate->summary_only)
                  {
-                   ri->suppress++;
-                   SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+                   (bgp_info_extra_get (ri))->suppress++;
+                   bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
                    match++;
                  }
                /* as-set aggregate route generate origin, as path,
@@ -4289,7 +4795,7 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi,
       new->peer = bgp->peer_self;
       SET_FLAG (new->flags, BGP_INFO_VALID);
       new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set);
-      new->uptime = time (NULL);
+      new->uptime = bgp_clock ();
 
       bgp_info_add (rn, new);
       bgp_unlock_node (rn);
@@ -4330,13 +4836,13 @@ 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)
                      {
-                       SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+                       bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
                        match++;
                      }
                  }
@@ -4344,7 +4850,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);
       }
@@ -4362,9 +4868,8 @@ bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi,
   /* Withdraw static BGP route from routing table. */
   if (ri)
     {
-      UNSET_FLAG (ri->flags, BGP_INFO_VALID);
-      bgp_process (bgp, rn, afi, safi);
       bgp_info_delete (rn, ri);
+      bgp_process (bgp, rn, afi, safi);
     }
 
   /* Unlock bgp_node_lookup. */
@@ -4376,9 +4881,8 @@ bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi,
 #define AGGREGATE_AS_SET       1
 
 static int
-bgp_aggregate_set (struct vty *vty, const char *prefix_str, 
-                   afi_t afi, safi_t safi,
-                  u_char summary_only, u_char as_set)
+bgp_aggregate_unset (struct vty *vty, const char *prefix_str,
+                     afi_t afi, safi_t safi)
 {
   int ret;
   struct prefix p;
@@ -4399,34 +4903,33 @@ bgp_aggregate_set (struct vty *vty, const char *prefix_str,
   bgp = vty->index;
 
   /* Old configuration check. */
-  rn = bgp_node_get (bgp->aggregate[afi][safi], &p);
-
-  if (rn->info)
+  rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p);
+  if (! rn)
     {
-      vty_out (vty, "There is already same aggregate network.%s", VTY_NEWLINE);
-      bgp_unlock_node (rn);
+      vty_out (vty, "%% There is no aggregate-address configuration.%s",
+               VTY_NEWLINE);
       return CMD_WARNING;
     }
 
-  /* Make aggregate address structure. */
-  aggregate = bgp_aggregate_new ();
-  aggregate->summary_only = summary_only;
-  aggregate->as_set = as_set;
-  aggregate->safi = safi;
-  rn->info = aggregate;
+  aggregate = rn->info;
+  if (aggregate->safi & SAFI_UNICAST)
+    bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate);
+  if (aggregate->safi & SAFI_MULTICAST)
+    bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate);
 
-  /* Aggregate address insert into BGP routing table. */
-  if (safi & SAFI_UNICAST)
-    bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate);
-  if (safi & SAFI_MULTICAST)
-    bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate);
+  /* Unlock aggregate address configuration. */
+  rn->info = NULL;
+  bgp_aggregate_free (aggregate);
+  bgp_unlock_node (rn);
+  bgp_unlock_node (rn);
 
   return CMD_SUCCESS;
 }
 
 static int
-bgp_aggregate_unset (struct vty *vty, const char *prefix_str, 
-                     afi_t afi, safi_t safi)
+bgp_aggregate_set (struct vty *vty, const char *prefix_str,
+                   afi_t afi, safi_t safi,
+                  u_char summary_only, u_char as_set)
 {
   int ret;
   struct prefix p;
@@ -4447,25 +4950,33 @@ bgp_aggregate_unset (struct vty *vty, const char *prefix_str,
   bgp = vty->index;
 
   /* Old configuration check. */
-  rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p);
-  if (! rn)
+  rn = bgp_node_get (bgp->aggregate[afi][safi], &p);
+
+  if (rn->info)
     {
-      vty_out (vty, "%% There is no aggregate-address configuration.%s",
-              VTY_NEWLINE);
-      return CMD_WARNING;
+      vty_out (vty, "There is already same aggregate network.%s", VTY_NEWLINE);
+      /* try to remove the old entry */
+      ret = bgp_aggregate_unset (vty, prefix_str, afi, safi);
+      if (ret)
+        {
+          vty_out (vty, "Error deleting aggregate.%s", VTY_NEWLINE);
+         bgp_unlock_node (rn);
+         return CMD_WARNING;
+        }
     }
 
-  aggregate = rn->info;
-  if (aggregate->safi & SAFI_UNICAST)
-    bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate);
-  if (aggregate->safi & SAFI_MULTICAST)
-    bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate);
+  /* Make aggregate address structure. */
+  aggregate = bgp_aggregate_new ();
+  aggregate->summary_only = summary_only;
+  aggregate->as_set = as_set;
+  aggregate->safi = safi;
+  rn->info = aggregate;
 
-  /* Unlock aggregate address configuration. */
-  rn->info = NULL;
-  bgp_aggregate_free (aggregate);
-  bgp_unlock_node (rn);
-  bgp_unlock_node (rn);
+  /* Aggregate address insert into BGP routing table. */
+  if (safi & SAFI_UNICAST)
+    bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate);
+  if (safi & SAFI_MULTICAST)
+    bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate);
 
   return CMD_SUCCESS;
 }
@@ -4808,7 +5319,8 @@ ALIAS (no_ipv6_aggregate_address_summary_only,
 \f
 /* Redistribute route treatment. */
 void
-bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
+bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
+                     const struct in6_addr *nexthop6,
                      u_int32_t metric, u_char type)
 {
   struct bgp *bgp;
@@ -4817,8 +5329,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;
@@ -4828,6 +5340,15 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
   if (nexthop)
     attr.nexthop = *nexthop;
 
+#ifdef HAVE_IPV6
+  if (nexthop6)
+    {
+      struct attr_extra *extra = bgp_attr_extra_get(&attr);
+      extra->mp_nexthop_global = *nexthop6;
+      extra->mp_nexthop_len = 16;
+    }
+#endif
+
   attr.med = metric;
   attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
 
@@ -4838,7 +5359,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];
@@ -4860,17 +5381,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);
+                 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)
@@ -4878,29 +5404,35 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
  
          if (bi)
            {
-             if (attrhash_cmp (bi->attr, new_attr))
+             if (attrhash_cmp (bi->attr, new_attr) &&
+                 !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
                {
-                 bgp_attr_unintern (new_attr);
-                 aspath_unintern (attr.aspath);
+                 bgp_attr_unintern (&new_attr);
+                 aspath_unintern (&attr.aspath);
+                 bgp_attr_extra_free (&attr);
                  bgp_unlock_node (bn);
                  return;
                }
              else
                {
                  /* The attribute is changed. */
-                 SET_FLAG (bi->flags, BGP_INFO_ATTR_CHANGED);
+                 bgp_info_set_flag (bn, bi, BGP_INFO_ATTR_CHANGED);
  
                  /* Rewrite BGP route information. */
-                 bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
-                 bgp_attr_unintern (bi->attr);
+                 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
+                   bgp_info_restore(bn, bi);
+                 else
+                   bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
+                 bgp_attr_unintern (&bi->attr);
                  bi->attr = new_attr;
-                 bi->uptime = time (NULL);
+                 bi->uptime = bgp_clock ();
  
                  /* Process change. */
                  bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST);
                  bgp_process (bgp, bn, afi, SAFI_UNICAST);
                  bgp_unlock_node (bn);
-                 aspath_unintern (attr.aspath);
+                 aspath_unintern (&attr.aspath);
+                 bgp_attr_extra_free (&attr);
                  return;
                } 
            }
@@ -4911,7 +5443,7 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
          new->peer = bgp->peer_self;
          SET_FLAG (new->flags, BGP_INFO_VALID);
          new->attr = new_attr;
-         new->uptime = time (NULL);
+         new->uptime = bgp_clock ();
 
          bgp_aggregate_increment (bgp, p, new, afi, SAFI_UNICAST);
          bgp_info_add (bn, new);
@@ -4921,7 +5453,8 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
     }
 
   /* Unintern original. */
-  aspath_unintern (attr.aspath);
+  aspath_unintern (&attr.aspath);
+  bgp_attr_extra_free (&attr);
 }
 
 void
@@ -4949,9 +5482,8 @@ bgp_redistribute_delete (struct prefix *p, u_char type)
          if (ri)
            {
              bgp_aggregate_decrement (bgp, p, ri, afi, SAFI_UNICAST);
-             UNSET_FLAG (ri->flags, BGP_INFO_VALID);
-             bgp_process (bgp, rn, afi, SAFI_UNICAST);
              bgp_info_delete (rn, ri);
+             bgp_process (bgp, rn, afi, SAFI_UNICAST);
            }
          bgp_unlock_node (rn);
        }
@@ -4978,9 +5510,8 @@ bgp_redistribute_withdraw (struct bgp *bgp, afi_t afi, int type)
       if (ri)
        {
          bgp_aggregate_decrement (bgp, &rn->p, ri, afi, SAFI_UNICAST);
-         UNSET_FLAG (ri->flags, BGP_INFO_VALID);
-         bgp_process (bgp, rn, afi, SAFI_UNICAST);
          bgp_info_delete (rn, ri);
+         bgp_process (bgp, rn, afi, SAFI_UNICAST);
        }
     }
 }
@@ -5033,7 +5564,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, "*");
@@ -5080,7 +5611,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));
        }
@@ -5091,7 +5623,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, " ");
@@ -5101,27 +5634,24 @@ route_vty_out (struct vty *vty, struct prefix *p,
 #endif /* HAVE_IPV6 */
 
       if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
-       vty_out (vty, "%10d", attr->med);
+       vty_out (vty, "%10u", attr->med);
       else
        vty_out (vty, "          ");
 
       if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
-       vty_out (vty, "%7d", attr->local_pref);
+       vty_out (vty, "%7u", attr->local_pref);
       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)
-      aspath_print_vty (vty, attr->aspath);
+      /* Print aspath */
+      if (attr->aspath)
+        aspath_print_vty (vty, "%s", attr->aspath, " ");
 
-    /* Print origin */
-    if (strlen (attr->aspath->str) == 0)
+      /* Print origin */
       vty_out (vty, "%s", bgp_origin_str[attr->origin]);
-    else
-      vty_out (vty, " %s", bgp_origin_str[attr->origin]);
-  }
+    }
   vty_out (vty, "%s", VTY_NEWLINE);
 }  
 
@@ -5144,7 +5674,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));
        }
@@ -5153,9 +5684,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, " ");
@@ -5165,27 +5699,24 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p,
 #endif /* HAVE_IPV6 */
 
       if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
-       vty_out (vty, "%10d", attr->med);
+       vty_out (vty, "%10u", attr->med);
       else
        vty_out (vty, "          ");
 
       if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
-       vty_out (vty, "%7d", attr->local_pref);
+       vty_out (vty, "%7u", attr->local_pref);
       else
        vty_out (vty, "       ");
+      
+      vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0));
+      
+      /* Print aspath */
+      if (attr->aspath)
+        aspath_print_vty (vty, "%s", attr->aspath, " ");
 
-      vty_out (vty, "%7d ",attr->weight);
-    
-    /* Print aspath */
-    if (attr->aspath)
-      aspath_print_vty (vty, attr->aspath);
-
-    /* Print origin */
-    if (strlen (attr->aspath->str) == 0)
+      /* Print origin */
       vty_out (vty, "%s", bgp_origin_str[attr->origin]);
-    else
-      vty_out (vty, " %s", bgp_origin_str[attr->origin]);
-  }
+    }
 
   vty_out (vty, "%s", VTY_NEWLINE);
 }  
@@ -5196,7 +5727,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);
     
@@ -5213,28 +5747,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);
 
@@ -5248,6 +5787,7 @@ damp_route_vty_out (struct vty *vty, struct prefix *p,
 {
   struct attr *attr;
   int len;
+  char timebuf[BGP_UPTIME_LEN];
 
   /* short status lead text */ 
   route_vty_short_status_out (vty, binfo);
@@ -5265,7 +5805,7 @@ damp_route_vty_out (struct vty *vty, struct prefix *p,
   else
     vty_out (vty, "%*s", len, " ");
 
-  vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo));
+  vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN));
 
   /* Print attribute */
   attr = binfo->attr;
@@ -5273,19 +5813,14 @@ damp_route_vty_out (struct vty *vty, struct prefix *p,
     {
       /* Print aspath */
       if (attr->aspath)
-       aspath_print_vty (vty, attr->aspath);
+       aspath_print_vty (vty, "%s", attr->aspath, " ");
 
       /* Print origin */
-      if (strlen (attr->aspath->str) == 0)
-       vty_out (vty, "%s", bgp_origin_str[attr->origin]);
-      else
-       vty_out (vty, " %s", bgp_origin_str[attr->origin]);
+      vty_out (vty, "%s", bgp_origin_str[attr->origin]);
     }
   vty_out (vty, "%s", VTY_NEWLINE);
 }
 
-#define BGP_UPTIME_LEN 25
-
 /* flap route */
 static void
 flap_route_vty_out (struct vty *vty, struct prefix *p,
@@ -5295,8 +5830,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);
@@ -5326,7 +5864,7 @@ flap_route_vty_out (struct vty *vty, struct prefix *p,
 
   if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
       && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
-    vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo));
+    vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN));
   else
     vty_out (vty, "%*s ", 8, " ");
 
@@ -5336,13 +5874,10 @@ flap_route_vty_out (struct vty *vty, struct prefix *p,
     {
       /* Print aspath */
       if (attr->aspath)
-       aspath_print_vty (vty, attr->aspath);
+       aspath_print_vty (vty, "%s", attr->aspath, " ");
 
       /* Print origin */
-      if (strlen (attr->aspath->str) == 0)
-       vty_out (vty, "%s", bgp_origin_str[attr->origin]);
-      else
-       vty_out (vty, " %s", bgp_origin_str[attr->origin]);
+      vty_out (vty, "%s", bgp_origin_str[attr->origin]);
     }
   vty_out (vty, "%s", VTY_NEWLINE);
 }
@@ -5355,6 +5890,9 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
   char buf1[BUFSIZ];
   struct attr *attr;
   int sockunion_vty_out (struct vty *, union sockunion *);
+#ifdef HAVE_CLOCK_MONOTONIC
+  time_t tbuf;
+#endif
        
   attr = binfo->attr;
 
@@ -5364,10 +5902,10 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
       if (attr->aspath)
        {
          vty_out (vty, "  ");
-         if (attr->aspath->length == 0)
+         if (aspath_count_hops (attr->aspath) == 0)
            vty_out (vty, "Local");
          else
-           aspath_print_vty (vty, attr->aspath);
+           aspath_print_vty (vty, "%s", attr->aspath, "");
        }
 
       if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))
@@ -5375,8 +5913,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 %u %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))
@@ -5391,14 +5930,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 */
@@ -5413,11 +5953,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));
        }
@@ -5425,10 +5965,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);
        }
@@ -5438,15 +5978,15 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
       vty_out (vty, "      Origin %s", bgp_origin_long_str[attr->origin]);
          
       if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
-       vty_out (vty, ", metric %d", attr->med);
+       vty_out (vty, ", metric %u", attr->med);
          
       if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
-       vty_out (vty, ", localpref %d", attr->local_pref);
+       vty_out (vty, ", localpref %u", attr->local_pref);
       else
-       vty_out (vty, ", localpref %d", bgp->default_local_pref);
+       vty_out (vty, ", localpref %u", 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 %u", attr->extra->weight);
        
       if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
        vty_out (vty, ", valid");
@@ -5469,6 +6009,11 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
       if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
        vty_out (vty, ", atomic-aggregate");
          
+      if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH) ||
+         (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED) &&
+          bgp_info_mpath_count (binfo)))
+       vty_out (vty, ", multipath");
+
       if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
        vty_out (vty, ", best");
 
@@ -5481,31 +6026,39 @@ 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 */
-      vty_out (vty, "      Last update: %s", ctime (&binfo->uptime));
+#ifdef HAVE_CLOCK_MONOTONIC
+      tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
+      vty_out (vty, "      Last update: %s", ctime(&tbuf));
+#else
+      vty_out (vty, "      Last update: %s", ctime(&binfo->uptime));
+#endif /* HAVE_CLOCK_MONOTONIC */
     }
   vty_out (vty, "%s", VTY_NEWLINE);
 }  
@@ -5579,7 +6132,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
@@ -5611,15 +6164,17 @@ bgp_show_table (struct vty *vty, struct bgp_table *table, struct in_addr *router
              {
                struct route_map *rmap = output_arg;
                struct bgp_info binfo;
-               struct attr dummy_attr; 
+               struct attr dummy_attr = { 0 }
                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;
              }
@@ -5823,7 +6378,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)
            {
@@ -5912,7 +6467,10 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
               if ((rm = bgp_node_match (table, &match)) != NULL)
                 {
                   if (prefix_check && rm->p.prefixlen != match.prefixlen)
-                    continue;
+                    {
+                      bgp_unlock_node (rm);
+                      continue;
+                    }
 
                   for (ri = rm->info; ri; ri = ri->next)
                     {
@@ -5926,6 +6484,8 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
                       display++;
                       route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, SAFI_MPLS_VPN);
                     }
+
+                  bgp_unlock_node (rm);
                 }
             }
         }
@@ -5949,6 +6509,8 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
                   route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi);
                 }
             }
+
+          bgp_unlock_node (rn);
         }
     }
 
@@ -6021,6 +6583,15 @@ DEFUN (show_ip_bgp_ipv4,
   return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_normal, NULL);
 }
 
+ALIAS (show_ip_bgp_ipv4,
+       show_bgp_ipv4_safi_cmd,
+       "show bgp ipv4 (unicast|multicast)",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n")
+
 DEFUN (show_ip_bgp_route,
        show_ip_bgp_route_cmd,
        "show ip bgp A.B.C.D",
@@ -6049,6 +6620,16 @@ DEFUN (show_ip_bgp_ipv4_route,
   return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0);
 }
 
+ALIAS (show_ip_bgp_ipv4_route,
+       show_bgp_ipv4_safi_route_cmd,
+       "show bgp ipv4 (unicast|multicast) A.B.C.D",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Network in the BGP routing table to display\n")
+
 DEFUN (show_ip_bgp_vpnv4_all_route,
        show_ip_bgp_vpnv4_all_route_cmd,
        "show ip bgp vpnv4 all A.B.C.D",
@@ -6113,6 +6694,16 @@ DEFUN (show_ip_bgp_ipv4_prefix,
   return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1);
 }
 
+ALIAS (show_ip_bgp_ipv4_prefix,
+       show_bgp_ipv4_safi_prefix_cmd,
+       "show bgp ipv4 (unicast|multicast) A.B.C.D/M",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+
 DEFUN (show_ip_bgp_vpnv4_all_prefix,
        show_ip_bgp_vpnv4_all_prefix_cmd,
        "show ip bgp vpnv4 all A.B.C.D/M",
@@ -6215,6 +6806,22 @@ ALIAS (show_bgp,
        BGP_STR
        "Address family\n")
 
+DEFUN (show_bgp_ipv6_safi,
+       show_bgp_ipv6_safi_cmd,
+       "show bgp ipv6 (unicast|multicast)",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show (vty, NULL, AFI_IP6, SAFI_MULTICAST, bgp_show_type_normal,
+                     NULL);
+
+  return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal, NULL);
+}
+
 /* old command */
 DEFUN (show_ipv6_bgp,
        show_ipv6_bgp_cmd,
@@ -6245,6 +6852,22 @@ ALIAS (show_bgp_route,
        "Address family\n"
        "Network in the BGP routing table to display\n")
 
+DEFUN (show_bgp_ipv6_safi_route,
+       show_bgp_ipv6_safi_route_cmd,
+       "show bgp ipv6 (unicast|multicast) X:X::X:X",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Network in the BGP routing table to display\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 0);
+
+  return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0);
+}
+
 /* old command */
 DEFUN (show_ipv6_bgp_route,
        show_ipv6_bgp_route_cmd,
@@ -6275,6 +6898,22 @@ ALIAS (show_bgp_prefix,
        "Address family\n"
        "IPv6 prefix <network>/<length>\n")
 
+DEFUN (show_bgp_ipv6_safi_prefix,
+       show_bgp_ipv6_safi_prefix_cmd,
+       "show bgp ipv6 (unicast|multicast) X:X::X:X/M",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 1);
+
+  return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1);
+}
+
 /* old command */
 DEFUN (show_ipv6_bgp_prefix,
        show_ipv6_bgp_prefix_cmd,
@@ -6979,15 +7618,36 @@ DEFUN (show_ipv6_mbgp_community_all,
 #endif /* HAVE_IPV6 */
 \f
 static int
-bgp_show_community (struct vty *vty, int argc, const char **argv, int exact,
-                    u_int16_t afi, u_char safi)
+bgp_show_community (struct vty *vty, const char *view_name, int argc,
+                   const char **argv, int exact, afi_t afi, safi_t safi)
 {
   struct community *com;
   struct buffer *b;
+  struct bgp *bgp;
   int i;
   char *str;
   int first = 0;
 
+  /* BGP structure lookup */
+  if (view_name)
+    {
+      bgp = bgp_lookup_by_name (view_name);
+      if (bgp == NULL)
+       {
+         vty_out (vty, "Can't find BGP view %s%s", view_name, VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+       {
+         vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+
   b = buffer_new (1024);
   for (i = 0; i < argc; i++)
     {
@@ -7015,7 +7675,7 @@ bgp_show_community (struct vty *vty, int argc, const char **argv, int exact,
       return CMD_WARNING;
     }
 
-  return bgp_show (vty, NULL, afi, safi,
+  return bgp_show (vty, bgp, afi, safi,
                    (exact ? bgp_show_type_community_exact :
                            bgp_show_type_community), com);
 }
@@ -7032,7 +7692,7 @@ DEFUN (show_ip_bgp_community,
        "Do not advertise to any peer (well-known community)\n"
        "Do not export to next AS (well-known community)\n")
 {
-  return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_UNICAST);
 }
 
 ALIAS (show_ip_bgp_community,
@@ -7111,9 +7771,9 @@ DEFUN (show_ip_bgp_ipv4_community,
        "Do not export to next AS (well-known community)\n")
 {
   if (strncmp (argv[0], "m", 1) == 0)
-    return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_MULTICAST);
+    return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_MULTICAST);
  
-  return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_UNICAST);
 }
 
 ALIAS (show_ip_bgp_ipv4_community,
@@ -7185,6 +7845,177 @@ ALIAS (show_ip_bgp_ipv4_community,
        "Do not advertise to any peer (well-known community)\n"
        "Do not export to next AS (well-known community)\n")
 
+DEFUN (show_bgp_view_afi_safi_community_all,
+       show_bgp_view_afi_safi_community_all_cmd,
+#ifdef HAVE_IPV6
+       "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community",
+#else
+       "show bgp view WORD ipv4 (unicast|multicast) community",
+#endif
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+#ifdef HAVE_IPV6
+       "Address family\n"
+#endif
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes containing communities\n")
+{
+  int afi;
+  int safi;
+  struct bgp *bgp;
+
+  /* BGP structure lookup. */
+  bgp = bgp_lookup_by_name (argv[0]);
+  if (bgp == NULL)
+    {
+      vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+#ifdef HAVE_IPV6
+  afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
+  safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+#else
+  afi = AFI_IP;
+  safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+#endif
+  return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL);
+}
+
+DEFUN (show_bgp_view_afi_safi_community,
+       show_bgp_view_afi_safi_community_cmd,
+#ifdef HAVE_IPV6
+       "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)",
+#else
+       "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)",
+#endif
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+#ifdef HAVE_IPV6
+       "Address family\n"
+#endif
+       "Address family modifier\n"
+       "Address family modifier\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+{
+  int afi;
+  int safi;
+
+#ifdef HAVE_IPV6
+  afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
+  safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  return bgp_show_community (vty, argv[0], argc-3, &argv[3], 0, afi, safi);
+#else
+  afi = AFI_IP;
+  safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  return bgp_show_community (vty, argv[0], argc-2, &argv[2], 0, afi, safi);
+#endif
+}
+
+ALIAS (show_bgp_view_afi_safi_community,
+       show_bgp_view_afi_safi_community2_cmd,
+#ifdef HAVE_IPV6
+       "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#else
+       "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#endif
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+#ifdef HAVE_IPV6
+       "Address family\n"
+#endif
+       "Address family modifier\n"
+       "Address family modifier\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+ALIAS (show_bgp_view_afi_safi_community,
+       show_bgp_view_afi_safi_community3_cmd,
+#ifdef HAVE_IPV6
+       "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#else
+       "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#endif
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+#ifdef HAVE_IPV6
+       "Address family\n"
+#endif
+       "Address family modifier\n"
+       "Address family modifier\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+ALIAS (show_bgp_view_afi_safi_community,
+       show_bgp_view_afi_safi_community4_cmd,
+#ifdef HAVE_IPV6
+       "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#else
+       "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#endif
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+#ifdef HAVE_IPV6
+       "Address family\n"
+#endif
+       "Address family modifier\n"
+       "Address family modifier\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
 DEFUN (show_ip_bgp_community_exact,
        show_ip_bgp_community_exact_cmd,
        "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match",
@@ -7198,7 +8029,7 @@ DEFUN (show_ip_bgp_community_exact,
        "Do not export to next AS (well-known community)\n"
        "Exact match of the communities")
 {
-  return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST);
 }
 
 ALIAS (show_ip_bgp_community_exact,
@@ -7281,9 +8112,9 @@ DEFUN (show_ip_bgp_ipv4_community_exact,
        "Exact match of the communities")
 {
   if (strncmp (argv[0], "m", 1) == 0)
-    return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_MULTICAST);
+    return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_MULTICAST);
  
-  return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST);
 }
 
 ALIAS (show_ip_bgp_ipv4_community_exact,
@@ -7370,7 +8201,7 @@ DEFUN (show_bgp_community,
        "Do not advertise to any peer (well-known community)\n"
        "Do not export to next AS (well-known community)\n")
 {
-  return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
 }
 
 ALIAS (show_bgp_community,
@@ -7515,7 +8346,7 @@ DEFUN (show_ipv6_bgp_community,
        "Do not advertise to any peer (well-known community)\n"
        "Do not export to next AS (well-known community)\n")
 {
-  return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
 }
 
 /* old command */
@@ -7593,7 +8424,7 @@ DEFUN (show_bgp_community_exact,
        "Do not export to next AS (well-known community)\n"
        "Exact match of the communities")
 {
-  return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
 }
 
 ALIAS (show_bgp_community_exact,
@@ -7746,7 +8577,7 @@ DEFUN (show_ipv6_bgp_community_exact,
        "Do not export to next AS (well-known community)\n"
        "Exact match of the communities")
 {
-  return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
 }
 
 /* old command */
@@ -7828,7 +8659,7 @@ DEFUN (show_ipv6_mbgp_community,
        "Do not advertise to any peer (well-known community)\n"
        "Do not export to next AS (well-known community)\n")
 {
-  return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_MULTICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_MULTICAST);
 }
 
 /* old command */
@@ -7908,7 +8739,7 @@ DEFUN (show_ipv6_mbgp_community_exact,
        "Do not export to next AS (well-known community)\n"
        "Exact match of the communities")
 {
-  return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_MULTICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_MULTICAST);
 }
 
 /* old command */
@@ -7980,7 +8811,7 @@ ALIAS (show_ipv6_mbgp_community_exact,
 \f
 static int
 bgp_show_community_list (struct vty *vty, const char *com, int exact,
-                        u_int16_t afi, u_char safi)
+                        afi_t afi, safi_t safi)
 {
   struct community_list *list;
 
@@ -8084,7 +8915,7 @@ ALIAS (show_bgp_community_list,
        "Address family\n"
        "Display routes matching the community-list\n"
        "community-list number\n"
-       "community-list name\n");
+       "community-list name\n")
 
 /* old command */
 DEFUN (show_ipv6_bgp_community_list,
@@ -8356,34 +9187,617 @@ peer_lookup_in_view (struct vty *vty, const char *view_name,
   
   return peer;
 }
+\f
+enum bgp_stats
+{
+  BGP_STATS_MAXBITLEN = 0,
+  BGP_STATS_RIB,
+  BGP_STATS_PREFIXES,
+  BGP_STATS_TOTPLEN,
+  BGP_STATS_UNAGGREGATEABLE,
+  BGP_STATS_MAX_AGGREGATEABLE,
+  BGP_STATS_AGGREGATES,
+  BGP_STATS_SPACE,
+  BGP_STATS_ASPATH_COUNT,
+  BGP_STATS_ASPATH_MAXHOPS,
+  BGP_STATS_ASPATH_TOTHOPS,
+  BGP_STATS_ASPATH_MAXSIZE,
+  BGP_STATS_ASPATH_TOTSIZE,
+  BGP_STATS_ASN_HIGHEST,
+  BGP_STATS_MAX,
+};
 
-static void
-show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
-               int in)
+static const char *table_stats_strs[] =
+{
+  [BGP_STATS_PREFIXES]            = "Total Prefixes",
+  [BGP_STATS_TOTPLEN]             = "Average prefix length",
+  [BGP_STATS_RIB]                 = "Total Advertisements",
+  [BGP_STATS_UNAGGREGATEABLE]     = "Unaggregateable prefixes",
+  [BGP_STATS_MAX_AGGREGATEABLE]   = "Maximum aggregateable prefixes",
+  [BGP_STATS_AGGREGATES]          = "BGP Aggregate advertisements",
+  [BGP_STATS_SPACE]               = "Address space advertised",
+  [BGP_STATS_ASPATH_COUNT]        = "Advertisements with paths",
+  [BGP_STATS_ASPATH_MAXHOPS]      = "Longest AS-Path (hops)",
+  [BGP_STATS_ASPATH_MAXSIZE]      = "Largest AS-Path (bytes)",
+  [BGP_STATS_ASPATH_TOTHOPS]      = "Average AS-Path length (hops)",
+  [BGP_STATS_ASPATH_TOTSIZE]      = "Average AS-Path size (bytes)",
+  [BGP_STATS_ASN_HIGHEST]         = "Highest public ASN",
+  [BGP_STATS_MAX] = NULL,
+};
+
+struct bgp_table_stats
 {
   struct bgp_table *table;
-  struct bgp_adj_in *ain;
-  struct bgp_adj_out *adj;
-  unsigned long output_count;
-  struct bgp_node *rn;
-  int header1 = 1;
-  struct bgp *bgp;
-  int header2 = 1;
-
-  bgp = peer->bgp;
+  unsigned long long counts[BGP_STATS_MAX];
+};
 
-  if (! bgp)
-    return;
+#if 0
+#define TALLY_SIGFIG 100000
+static unsigned long
+ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
+{
+  unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
+  unsigned long res = (newtot * TALLY_SIGFIG) / count;
+  unsigned long ret = newtot / count;
+  
+  if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
+    return ret + 1;
+  else
+    return ret;
+}
+#endif
 
-  table = bgp->rib[afi][safi];
+static int
+bgp_table_stats_walker (struct thread *t)
+{
+  struct bgp_node *rn;
+  struct bgp_node *top;
+  struct bgp_table_stats *ts = THREAD_ARG (t);
+  unsigned int space = 0;
+  
+  if (!(top = bgp_table_top (ts->table)))
+    return 0;
 
-  output_count = 0;
-       
-  if (! in && CHECK_FLAG (peer->af_sflags[afi][safi],
-                         PEER_STATUS_DEFAULT_ORIGINATE))
+  switch (top->p.family)
     {
-      vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
-      vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
+      case AF_INET:
+        space = IPV4_MAX_BITLEN;
+        break;
+      case AF_INET6:
+        space = IPV6_MAX_BITLEN;
+        break;
+    }
+    
+  ts->counts[BGP_STATS_MAXBITLEN] = space;
+
+  for (rn = top; rn; rn = bgp_route_next (rn))
+    {
+      struct bgp_info *ri;
+      struct bgp_node *prn = rn->parent;
+      unsigned int rinum = 0;
+      
+      if (rn == top)
+        continue;
+      
+      if (!rn->info)
+        continue;
+      
+      ts->counts[BGP_STATS_PREFIXES]++;
+      ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
+
+#if 0
+      ts->counts[BGP_STATS_AVGPLEN]
+        = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
+                      ts->counts[BGP_STATS_AVGPLEN],
+                      rn->p.prefixlen);
+#endif
+      
+      /* check if the prefix is included by any other announcements */
+      while (prn && !prn->info)
+        prn = prn->parent;
+      
+      if (prn == NULL || prn == top)
+        {
+          ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
+          /* announced address space */
+          if (space)
+            ts->counts[BGP_STATS_SPACE] += 1 << (space - rn->p.prefixlen);
+        }
+      else if (prn->info)
+        ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
+      
+      for (ri = rn->info; ri; ri = ri->next)
+        {
+          rinum++;
+          ts->counts[BGP_STATS_RIB]++;
+          
+          if (ri->attr &&
+              (CHECK_FLAG (ri->attr->flag,
+                           ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))))
+            ts->counts[BGP_STATS_AGGREGATES]++;
+          
+          /* as-path stats */
+          if (ri->attr && ri->attr->aspath)
+            {
+              unsigned int hops = aspath_count_hops (ri->attr->aspath);
+              unsigned int size = aspath_size (ri->attr->aspath);
+              as_t highest = aspath_highest (ri->attr->aspath);
+              
+              ts->counts[BGP_STATS_ASPATH_COUNT]++;
+              
+              if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
+                ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
+              
+              if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
+                ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
+              
+              ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
+              ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
+#if 0
+              ts->counts[BGP_STATS_ASPATH_AVGHOPS] 
+                = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
+                              ts->counts[BGP_STATS_ASPATH_AVGHOPS],
+                              hops);
+              ts->counts[BGP_STATS_ASPATH_AVGSIZE]
+                = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
+                              ts->counts[BGP_STATS_ASPATH_AVGSIZE],
+                              size);
+#endif
+              if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
+                ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
+            }
+        }
+    }
+  return 0;
+}
+
+static int
+bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi)
+{
+  struct bgp_table_stats ts;
+  unsigned int i;
+  
+  if (!bgp->rib[afi][safi])
+    {
+      vty_out (vty, "%% No RIB exist for the AFI/SAFI%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  
+  memset (&ts, 0, sizeof (ts));
+  ts.table = bgp->rib[afi][safi];
+  thread_execute (bm->master, bgp_table_stats_walker, &ts, 0);
+
+  vty_out (vty, "BGP %s RIB statistics%s%s",
+           afi_safi_print (afi, safi), VTY_NEWLINE, VTY_NEWLINE);
+  
+  for (i = 0; i < BGP_STATS_MAX; i++)
+    {
+      if (!table_stats_strs[i])
+        continue;
+      
+      switch (i)
+        {
+#if 0
+          case BGP_STATS_ASPATH_AVGHOPS:
+          case BGP_STATS_ASPATH_AVGSIZE:
+          case BGP_STATS_AVGPLEN:
+            vty_out (vty, "%-30s: ", table_stats_strs[i]);
+            vty_out (vty, "%12.2f",
+                     (float)ts.counts[i] / (float)TALLY_SIGFIG);
+            break;
+#endif
+          case BGP_STATS_ASPATH_TOTHOPS:
+          case BGP_STATS_ASPATH_TOTSIZE:
+            vty_out (vty, "%-30s: ", table_stats_strs[i]);
+            vty_out (vty, "%12.2f",
+                     ts.counts[i] ?
+                     (float)ts.counts[i] / 
+                      (float)ts.counts[BGP_STATS_ASPATH_COUNT]
+                     : 0);
+            break;
+          case BGP_STATS_TOTPLEN:
+            vty_out (vty, "%-30s: ", table_stats_strs[i]);
+            vty_out (vty, "%12.2f",
+                     ts.counts[i] ?
+                     (float)ts.counts[i] / 
+                      (float)ts.counts[BGP_STATS_PREFIXES]
+                     : 0);
+            break;
+          case BGP_STATS_SPACE:
+            vty_out (vty, "%-30s: ", table_stats_strs[i]);
+            vty_out (vty, "%12llu%s", ts.counts[i], VTY_NEWLINE);
+            if (ts.counts[BGP_STATS_MAXBITLEN] < 9)
+              break;
+            vty_out (vty, "%30s: ", "%% announced ");
+            vty_out (vty, "%12.2f%s", 
+                     100 * (float)ts.counts[BGP_STATS_SPACE] / 
+                       (float)((uint64_t)1UL << ts.counts[BGP_STATS_MAXBITLEN]),
+                       VTY_NEWLINE);
+            vty_out (vty, "%30s: ", "/8 equivalent ");
+            vty_out (vty, "%12.2f%s", 
+                     (float)ts.counts[BGP_STATS_SPACE] / 
+                       (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 8)),
+                     VTY_NEWLINE);
+            if (ts.counts[BGP_STATS_MAXBITLEN] < 25)
+              break;
+            vty_out (vty, "%30s: ", "/24 equivalent ");
+            vty_out (vty, "%12.2f", 
+                     (float)ts.counts[BGP_STATS_SPACE] / 
+                       (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 24)));
+            break;
+          default:
+            vty_out (vty, "%-30s: ", table_stats_strs[i]);
+            vty_out (vty, "%12llu", ts.counts[i]);
+        }
+        
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+static int
+bgp_table_stats_vty (struct vty *vty, const char *name,
+                     const char *afi_str, const char *safi_str)
+{
+  struct bgp *bgp;
+  afi_t afi;
+  safi_t safi;
+  
+ if (name)
+    bgp = bgp_lookup_by_name (name);
+  else
+    bgp = bgp_get_default ();
+
+  if (!bgp)
+    {
+      vty_out (vty, "%% No such BGP instance exist%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  if (strncmp (afi_str, "ipv", 3) == 0)
+    {
+      if (strncmp (afi_str, "ipv4", 4) == 0)
+        afi = AFI_IP;
+      else if (strncmp (afi_str, "ipv6", 4) == 0)
+        afi = AFI_IP6;
+      else
+        {
+          vty_out (vty, "%% Invalid address family %s%s",
+                   afi_str, VTY_NEWLINE);
+          return CMD_WARNING;
+        }
+      if (strncmp (safi_str, "m", 1) == 0)
+        safi = SAFI_MULTICAST;
+      else if (strncmp (safi_str, "u", 1) == 0)
+        safi = SAFI_UNICAST;
+      else if (strncmp (safi_str, "vpnv4", 5) == 0 || strncmp (safi_str, "vpnv6", 5) == 0)
+        safi = SAFI_MPLS_LABELED_VPN;
+      else
+        {
+          vty_out (vty, "%% Invalid subsequent address family %s%s",
+                   safi_str, VTY_NEWLINE);
+          return CMD_WARNING;
+        }
+    }
+  else
+    {
+      vty_out (vty, "%% Invalid address family %s%s",
+               afi_str, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_table_stats (vty, bgp, afi, safi);
+}
+
+DEFUN (show_bgp_statistics,
+       show_bgp_statistics_cmd,
+       "show bgp (ipv4|ipv6) (unicast|multicast) statistics",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "BGP RIB advertisement statistics\n")
+{
+  return bgp_table_stats_vty (vty, NULL, argv[0], argv[1]);
+}
+
+ALIAS (show_bgp_statistics,
+       show_bgp_statistics_vpnv4_cmd,
+       "show bgp (ipv4) (vpnv4) statistics",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "BGP RIB advertisement statistics\n")
+
+DEFUN (show_bgp_statistics_view,
+       show_bgp_statistics_view_cmd,
+       "show bgp view WORD (ipv4|ipv6) (unicast|multicast) statistics",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "Address family\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "BGP RIB advertisement statistics\n")
+{
+  return bgp_table_stats_vty (vty, NULL, argv[0], argv[1]);
+}
+
+ALIAS (show_bgp_statistics_view,
+       show_bgp_statistics_view_vpnv4_cmd,
+       "show bgp view WORD (ipv4) (vpnv4) statistics",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "BGP RIB advertisement statistics\n")
+\f
+enum bgp_pcounts
+{
+  PCOUNT_ADJ_IN = 0,
+  PCOUNT_DAMPED,
+  PCOUNT_REMOVED,
+  PCOUNT_HISTORY,
+  PCOUNT_STALE,
+  PCOUNT_VALID,
+  PCOUNT_ALL,
+  PCOUNT_COUNTED,
+  PCOUNT_PFCNT, /* the figure we display to users */
+  PCOUNT_MAX,
+};
+
+static const char *pcount_strs[] =
+{
+  [PCOUNT_ADJ_IN]  = "Adj-in",
+  [PCOUNT_DAMPED]  = "Damped",
+  [PCOUNT_REMOVED] = "Removed",
+  [PCOUNT_HISTORY] = "History",
+  [PCOUNT_STALE]   = "Stale",
+  [PCOUNT_VALID]   = "Valid",
+  [PCOUNT_ALL]     = "All RIB",
+  [PCOUNT_COUNTED] = "PfxCt counted",
+  [PCOUNT_PFCNT]   = "Useable",
+  [PCOUNT_MAX]     = NULL,
+};
+
+struct peer_pcounts
+{
+  unsigned int count[PCOUNT_MAX];
+  const struct peer *peer;
+  const struct bgp_table *table;
+};
+
+static int
+bgp_peer_count_walker (struct thread *t)
+{
+  struct bgp_node *rn;
+  struct peer_pcounts *pc = THREAD_ARG (t);
+  const struct peer *peer = pc->peer;
+  
+  for (rn = bgp_table_top (pc->table); rn; rn = bgp_route_next (rn))
+    {
+      struct bgp_adj_in *ain;
+      struct bgp_info *ri;
+      
+      for (ain = rn->adj_in; ain; ain = ain->next)
+        if (ain->peer == peer)
+          pc->count[PCOUNT_ADJ_IN]++;
+
+      for (ri = rn->info; ri; ri = ri->next)
+        {
+          char buf[SU_ADDRSTRLEN];
+          
+          if (ri->peer != peer)
+            continue;
+          
+          pc->count[PCOUNT_ALL]++;
+          
+          if (CHECK_FLAG (ri->flags, BGP_INFO_DAMPED))
+            pc->count[PCOUNT_DAMPED]++;
+          if (CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
+            pc->count[PCOUNT_HISTORY]++;
+          if (CHECK_FLAG (ri->flags, BGP_INFO_REMOVED))
+            pc->count[PCOUNT_REMOVED]++;
+          if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
+            pc->count[PCOUNT_STALE]++;
+          if (CHECK_FLAG (ri->flags, BGP_INFO_VALID))
+            pc->count[PCOUNT_VALID]++;
+          if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
+            pc->count[PCOUNT_PFCNT]++;
+          
+          if (CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
+            {
+              pc->count[PCOUNT_COUNTED]++;
+              if (CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
+                plog_warn (peer->log,
+                           "%s [pcount] %s/%d is counted but flags 0x%x",
+                           peer->host,
+                           inet_ntop(rn->p.family, &rn->p.u.prefix,
+                                     buf, SU_ADDRSTRLEN),
+                           rn->p.prefixlen,
+                           ri->flags);
+            }
+          else
+            {
+              if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
+                plog_warn (peer->log,
+                           "%s [pcount] %s/%d not counted but flags 0x%x",
+                           peer->host,
+                           inet_ntop(rn->p.family, &rn->p.u.prefix,
+                                     buf, SU_ADDRSTRLEN),
+                           rn->p.prefixlen,
+                           ri->flags);
+            }
+        }
+    }
+  return 0;
+}
+
+static int
+bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct peer_pcounts pcounts = { .peer = peer };
+  unsigned int i;
+  
+  if (!peer || !peer->bgp || !peer->afc[afi][safi]
+      || !peer->bgp->rib[afi][safi])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  
+  memset (&pcounts, 0, sizeof(pcounts));
+  pcounts.peer = peer;
+  pcounts.table = peer->bgp->rib[afi][safi];
+  
+  /* in-place call via thread subsystem so as to record execution time
+   * stats for the thread-walk (i.e. ensure this can't be blamed on
+   * on just vty_read()).
+   */
+  thread_execute (bm->master, bgp_peer_count_walker, &pcounts, 0);
+  
+  vty_out (vty, "Prefix counts for %s, %s%s", 
+           peer->host, afi_safi_print (afi, safi), VTY_NEWLINE);
+  vty_out (vty, "PfxCt: %ld%s", peer->pcount[afi][safi], VTY_NEWLINE);
+  vty_out (vty, "%sCounts from RIB table walk:%s%s", 
+           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+
+  for (i = 0; i < PCOUNT_MAX; i++)
+      vty_out (vty, "%20s: %-10d%s",
+               pcount_strs[i], pcounts.count[i], VTY_NEWLINE);
+
+  if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi])
+    {
+      vty_out (vty, "%s [pcount] PfxCt drift!%s",
+               peer->host, VTY_NEWLINE);
+      vty_out (vty, "Please report this bug, with the above command output%s",
+              VTY_NEWLINE);
+    }
+               
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_bgp_neighbor_prefix_counts,
+       show_ip_bgp_neighbor_prefix_counts_cmd,
+       "show ip bgp neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display detailed prefix count information\n")
+{
+  struct peer *peer;
+
+  peer = peer_lookup_in_view (vty, NULL, argv[0]);  
+  if (! peer) 
+    return CMD_WARNING;
+  return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST);
+}
+
+DEFUN (show_bgp_ipv6_neighbor_prefix_counts,
+       show_bgp_ipv6_neighbor_prefix_counts_cmd,
+       "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display detailed prefix count information\n")
+{
+  struct peer *peer;
+
+  peer = peer_lookup_in_view (vty, NULL, argv[0]);  
+  if (! peer) 
+    return CMD_WARNING;
+  return bgp_peer_counts (vty, peer, AFI_IP6, SAFI_UNICAST);
+}
+
+DEFUN (show_ip_bgp_ipv4_neighbor_prefix_counts,
+       show_ip_bgp_ipv4_neighbor_prefix_counts_cmd,
+       "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display detailed prefix count information\n")
+{
+  struct peer *peer;
+
+  peer = peer_lookup_in_view (vty, NULL, argv[1]);
+  if (! peer)
+    return CMD_WARNING;
+
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_peer_counts (vty, peer, AFI_IP, SAFI_MULTICAST);
+
+  return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST);
+}
+
+DEFUN (show_ip_bgp_vpnv4_neighbor_prefix_counts,
+       show_ip_bgp_vpnv4_neighbor_prefix_counts_cmd,
+       "show ip bgp vpnv4 all neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display detailed prefix count information\n")
+{
+  struct peer *peer;
+
+  peer = peer_lookup_in_view (vty, NULL, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+  
+  return bgp_peer_counts (vty, peer, AFI_IP, SAFI_MPLS_VPN);
+}
+
+
+static void
+show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
+               int in)
+{
+  struct bgp_table *table;
+  struct bgp_adj_in *ain;
+  struct bgp_adj_out *adj;
+  unsigned long output_count;
+  struct bgp_node *rn;
+  int header1 = 1;
+  struct bgp *bgp;
+  int header2 = 1;
+
+  bgp = peer->bgp;
+
+  if (! bgp)
+    return;
+
+  table = bgp->rib[afi][safi];
+
+  output_count = 0;
+       
+  if (! in && CHECK_FLAG (peer->af_sflags[afi][safi],
+                         PEER_STATUS_DEFAULT_ORIGINATE))
+    {
+      vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
+      vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
       vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
 
       vty_out (vty, "Originating default network 0.0.0.0%s%s",
@@ -8467,12 +9881,14 @@ peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, int
   return CMD_SUCCESS;
 }
 
-DEFUN (show_ip_bgp_neighbor_advertised_route,
-       show_ip_bgp_neighbor_advertised_route_cmd,
-       "show ip bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+DEFUN (show_ip_bgp_view_neighbor_advertised_route,
+       show_ip_bgp_view_neighbor_advertised_route_cmd,
+       "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X) advertised-routes",
        SHOW_STR
        IP_STR
        BGP_STR
+       "BGP view\n"
+       "View name\n"
        "Detailed information on TCP and BGP neighbor connections\n"
        "Neighbor to display information about\n"
        "Neighbor to display information about\n"
@@ -8480,13 +9896,28 @@ DEFUN (show_ip_bgp_neighbor_advertised_route,
 {
   struct peer *peer;
 
-  peer = peer_lookup_in_view (vty, NULL, argv[0]);  
+  if (argc == 2)
+    peer = peer_lookup_in_view (vty, argv[0], argv[1]);
+  else
+    peer = peer_lookup_in_view (vty, NULL, argv[0]);
+
   if (! peer) 
     return CMD_WARNING;
  
   return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 0);
 }
 
+ALIAS (show_ip_bgp_view_neighbor_advertised_route,
+       show_ip_bgp_neighbor_advertised_route_cmd,
+       "show ip bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the routes advertised to a BGP neighbor\n")
+
 DEFUN (show_ip_bgp_ipv4_neighbor_advertised_route,
        show_ip_bgp_ipv4_neighbor_advertised_route_cmd,
        "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) advertised-routes",
@@ -8645,12 +10076,14 @@ DEFUN (ipv6_mbgp_neighbor_advertised_route,
 }
 #endif /* HAVE_IPV6 */
 \f
-DEFUN (show_ip_bgp_neighbor_received_routes,
-       show_ip_bgp_neighbor_received_routes_cmd,
-       "show ip bgp neighbors (A.B.C.D|X:X::X:X) received-routes",
+DEFUN (show_ip_bgp_view_neighbor_received_routes,
+       show_ip_bgp_view_neighbor_received_routes_cmd,
+       "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X) received-routes",
        SHOW_STR
        IP_STR
        BGP_STR
+       "BGP view\n"
+       "View name\n"
        "Detailed information on TCP and BGP neighbor connections\n"
        "Neighbor to display information about\n"
        "Neighbor to display information about\n"
@@ -8658,13 +10091,28 @@ DEFUN (show_ip_bgp_neighbor_received_routes,
 {
   struct peer *peer;
 
-  peer = peer_lookup_in_view (vty, NULL, argv[0]);
+  if (argc == 2)
+    peer = peer_lookup_in_view (vty, argv[0], argv[1]);
+  else
+    peer = peer_lookup_in_view (vty, NULL, argv[0]);
+
   if (! peer)
     return CMD_WARNING;
 
   return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 1);
 }
 
+ALIAS (show_ip_bgp_view_neighbor_received_routes,
+       show_ip_bgp_neighbor_received_routes_cmd,
+       "show ip bgp neighbors (A.B.C.D|X:X::X:X) received-routes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the received routes from neighbor\n")
+
 DEFUN (show_ip_bgp_ipv4_neighbor_received_routes,
        show_ip_bgp_ipv4_neighbor_received_routes_cmd,
        "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) received-routes",
@@ -8691,6 +10139,56 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_routes,
   return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 1);
 }
 
+DEFUN (show_bgp_view_afi_safi_neighbor_adv_recd_routes,
+       show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd,
+#ifdef HAVE_IPV6
+       "show bgp view WORD (ipv4|ipv6) (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) (advertised-routes|received-routes)",
+#else
+       "show bgp view WORD ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) (advertised-routes|received-routes)",
+#endif
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+#ifdef HAVE_IPV6
+       "Address family\n"
+#endif
+       "Address family modifier\n"
+       "Address family modifier\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the advertised routes to neighbor\n"
+       "Display the received routes from neighbor\n")
+{
+  int afi;
+  int safi;
+  int in;
+  struct peer *peer;
+
+#ifdef HAVE_IPV6
+    peer = peer_lookup_in_view (vty, argv[0], argv[3]);
+#else
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+#endif
+
+  if (! peer)
+    return CMD_WARNING;
+
+#ifdef HAVE_IPV6
+  afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
+  safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  in = (strncmp (argv[4], "r", 1) == 0) ? 1 : 0;
+#else
+  afi = AFI_IP;
+  safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  in = (strncmp (argv[3], "r", 1) == 0) ? 1 : 0;
+#endif
+
+  return peer_adj_routes (vty, peer, afi, safi, in);
+}
+
 DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
        show_ip_bgp_neighbor_received_prefix_filter_cmd,
        "show ip bgp neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
@@ -9098,9 +10596,68 @@ ALIAS (show_ip_bgp_view_rsclient,
        "Information about Route Server Client\n"
        NEIGHBOR_ADDR_STR)
 
+DEFUN (show_bgp_view_ipv4_safi_rsclient,
+       show_bgp_view_ipv4_safi_rsclient_cmd,
+       "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR)
+{
+  struct bgp_table *table;
+  struct peer *peer;
+  safi_t safi;
+
+  if (argc == 3) {
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  } else {
+    peer = peer_lookup_in_view (vty, NULL, argv[1]);
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  }
+
+  if (! peer)
+    return CMD_WARNING;
+
+  if (! peer->afc[AFI_IP][safi])
+    {
+      vty_out (vty, "%% Activate the neighbor for the address family first%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi],
+              PEER_FLAG_RSERVER_CLIENT))
+    {
+      vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  table = peer->rib[AFI_IP][safi];
+
+  return bgp_show_table (vty, table, &peer->remote_id, bgp_show_type_normal, NULL);
+}
+
+ALIAS (show_bgp_view_ipv4_safi_rsclient,
+       show_bgp_ipv4_safi_rsclient_cmd,
+       "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR)
+
 DEFUN (show_ip_bgp_view_rsclient_route,
        show_ip_bgp_view_rsclient_route_cmd,
-       "show bgp view WORD rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
+       "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
        SHOW_STR
        IP_STR
        BGP_STR
@@ -9171,6 +10728,87 @@ ALIAS (show_ip_bgp_view_rsclient_route,
        NEIGHBOR_ADDR_STR
        "Network in the BGP routing table to display\n")
 
+DEFUN (show_bgp_view_ipv4_safi_rsclient_route,
+       show_bgp_view_ipv4_safi_rsclient_route_cmd,
+       "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "Network in the BGP routing table to display\n")
+{
+  struct bgp *bgp;
+  struct peer *peer;
+  safi_t safi;
+
+  /* BGP structure lookup. */
+  if (argc == 4)
+    {
+      bgp = bgp_lookup_by_name (argv[0]);
+      if (bgp == NULL)
+       {
+         vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+       {
+         vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+
+  if (argc == 4) {
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  } else {
+    peer = peer_lookup_in_view (vty, NULL, argv[1]);
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  }
+
+  if (! peer)
+    return CMD_WARNING;
+
+  if (! peer->afc[AFI_IP][safi])
+    {
+      vty_out (vty, "%% Activate the neighbor for the address family first%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+}
+
+  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi],
+              PEER_FLAG_RSERVER_CLIENT))
+    {
+      vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi],
+                                  (argc == 4) ? argv[3] : argv[2],
+                                  AFI_IP, safi, NULL, 0);
+}
+
+ALIAS (show_bgp_view_ipv4_safi_rsclient_route,
+       show_bgp_ipv4_safi_rsclient_route_cmd,
+       "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "Network in the BGP routing table to display\n")
+
 DEFUN (show_ip_bgp_view_rsclient_prefix,
        show_ip_bgp_view_rsclient_prefix_cmd,
        "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
@@ -9187,7 +10825,83 @@ DEFUN (show_ip_bgp_view_rsclient_prefix,
   struct peer *peer;
 
   /* BGP structure lookup. */
-  if (argc == 3)
+  if (argc == 3)
+    {
+      bgp = bgp_lookup_by_name (argv[0]);
+      if (bgp == NULL)
+       {
+         vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+       {
+         vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+
+  if (argc == 3)
+    peer = peer_lookup_in_view (vty, argv[0], argv[1]);
+  else
+  peer = peer_lookup_in_view (vty, NULL, argv[0]);
+
+  if (! peer)
+    return CMD_WARNING;
+    
+  if (! peer->afc[AFI_IP][SAFI_UNICAST])
+    {
+      vty_out (vty, "%% Activate the neighbor for the address family first%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+}
+
+  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
+              PEER_FLAG_RSERVER_CLIENT))
+{
+      vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+            VTY_NEWLINE);
+    return CMD_WARNING;
+    }
+    
+  return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][SAFI_UNICAST], 
+                                  (argc == 3) ? argv[2] : argv[1],
+                                  AFI_IP, SAFI_UNICAST, NULL, 1);
+}
+
+ALIAS (show_ip_bgp_view_rsclient_prefix,
+       show_ip_bgp_rsclient_prefix_cmd,
+       "show ip bgp rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+
+DEFUN (show_bgp_view_ipv4_safi_rsclient_prefix,
+       show_bgp_view_ipv4_safi_rsclient_prefix_cmd,
+       "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+  struct bgp *bgp;
+  struct peer *peer;
+  safi_t safi;
+
+  /* BGP structure lookup. */
+  if (argc == 4)
     {
       bgp = bgp_lookup_by_name (argv[0]);
       if (bgp == NULL)
@@ -9206,45 +10920,49 @@ DEFUN (show_ip_bgp_view_rsclient_prefix,
        }
     }
 
-  if (argc == 3)
-    peer = peer_lookup_in_view (vty, argv[0], argv[1]);
-  else
-  peer = peer_lookup_in_view (vty, NULL, argv[0]);
+  if (argc == 4) {
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  } else {
+    peer = peer_lookup_in_view (vty, NULL, argv[1]);
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  }
 
   if (! peer)
     return CMD_WARNING;
-    
-  if (! peer->afc[AFI_IP][SAFI_UNICAST])
+
+  if (! peer->afc[AFI_IP][safi])
     {
       vty_out (vty, "%% Activate the neighbor for the address family first%s",
             VTY_NEWLINE);
       return CMD_WARNING;
 }
 
-  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
+  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi],
               PEER_FLAG_RSERVER_CLIENT))
 {
       vty_out (vty, "%% Neighbor is not a Route-Server client%s",
             VTY_NEWLINE);
     return CMD_WARNING;
     }
-    
-  return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][SAFI_UNICAST], 
-                                  (argc == 3) ? argv[2] : argv[1],
-                                  AFI_IP, SAFI_UNICAST, NULL, 1);
+
+  return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi],
+                                  (argc == 4) ? argv[3] : argv[2],
+                                  AFI_IP, safi, NULL, 1);
 }
 
-ALIAS (show_ip_bgp_view_rsclient_prefix,
-       show_ip_bgp_rsclient_prefix_cmd,
-       "show ip bgp rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
+ALIAS (show_bgp_view_ipv4_safi_rsclient_prefix,
+       show_bgp_ipv4_safi_rsclient_prefix_cmd,
+       "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
        SHOW_STR
-       IP_STR
        BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
        "Information about Route Server Client\n"
        NEIGHBOR_ADDR_STR
        "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
 
-
 #ifdef HAVE_IPV6
 DEFUN (show_bgp_view_neighbor_routes,
        show_bgp_view_neighbor_routes_cmd,
@@ -9510,6 +11228,65 @@ ALIAS (show_bgp_view_rsclient,
        "Information about Route Server Client\n"
        NEIGHBOR_ADDR_STR)
 
+DEFUN (show_bgp_view_ipv6_safi_rsclient,
+       show_bgp_view_ipv6_safi_rsclient_cmd,
+       "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR)
+{
+  struct bgp_table *table;
+  struct peer *peer;
+  safi_t safi;
+
+  if (argc == 3) {
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  } else {
+    peer = peer_lookup_in_view (vty, NULL, argv[1]);
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  }
+
+  if (! peer)
+    return CMD_WARNING;
+
+  if (! peer->afc[AFI_IP6][safi])
+    {
+      vty_out (vty, "%% Activate the neighbor for the address family first%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi],
+              PEER_FLAG_RSERVER_CLIENT))
+    {
+      vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  table = peer->rib[AFI_IP6][safi];
+
+  return bgp_show_table (vty, table, &peer->remote_id, bgp_show_type_normal, NULL);
+}
+
+ALIAS (show_bgp_view_ipv6_safi_rsclient,
+       show_bgp_ipv6_safi_rsclient_cmd,
+       "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR)
+
 DEFUN (show_bgp_view_rsclient_route,
        show_bgp_view_rsclient_route_cmd,
        "show bgp view WORD rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
@@ -9581,6 +11358,87 @@ ALIAS (show_bgp_view_rsclient_route,
        NEIGHBOR_ADDR_STR
        "Network in the BGP routing table to display\n")
 
+DEFUN (show_bgp_view_ipv6_safi_rsclient_route,
+       show_bgp_view_ipv6_safi_rsclient_route_cmd,
+       "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "Network in the BGP routing table to display\n")
+{
+  struct bgp *bgp;
+  struct peer *peer;
+  safi_t safi;
+
+  /* BGP structure lookup. */
+  if (argc == 4)
+    {
+      bgp = bgp_lookup_by_name (argv[0]);
+      if (bgp == NULL)
+       {
+         vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+       {
+         vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+
+  if (argc == 4) {
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  } else {
+    peer = peer_lookup_in_view (vty, NULL, argv[1]);
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  }
+
+  if (! peer)
+    return CMD_WARNING;
+
+  if (! peer->afc[AFI_IP6][safi])
+    {
+      vty_out (vty, "%% Activate the neighbor for the address family first%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+}
+
+  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi],
+              PEER_FLAG_RSERVER_CLIENT))
+    {
+      vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi],
+                                  (argc == 4) ? argv[3] : argv[2],
+                                  AFI_IP6, safi, NULL, 0);
+}
+
+ALIAS (show_bgp_view_ipv6_safi_rsclient_route,
+       show_bgp_ipv6_safi_rsclient_route_cmd,
+       "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "Network in the BGP routing table to display\n")
+
 DEFUN (show_bgp_view_rsclient_prefix,
        show_bgp_view_rsclient_prefix_cmd,
        "show bgp view WORD rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
@@ -9652,6 +11510,87 @@ ALIAS (show_bgp_view_rsclient_prefix,
        NEIGHBOR_ADDR_STR
        "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
 
+DEFUN (show_bgp_view_ipv6_safi_rsclient_prefix,
+       show_bgp_view_ipv6_safi_rsclient_prefix_cmd,
+       "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "IP prefix <network>/<length>, e.g., 3ffe::/16\n")
+{
+  struct bgp *bgp;
+  struct peer *peer;
+  safi_t safi;
+
+  /* BGP structure lookup. */
+  if (argc == 4)
+    {
+      bgp = bgp_lookup_by_name (argv[0]);
+      if (bgp == NULL)
+       {
+         vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+       {
+         vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+
+  if (argc == 4) {
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  } else {
+    peer = peer_lookup_in_view (vty, NULL, argv[1]);
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  }
+
+  if (! peer)
+    return CMD_WARNING;
+
+  if (! peer->afc[AFI_IP6][safi])
+    {
+      vty_out (vty, "%% Activate the neighbor for the address family first%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+}
+
+  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi],
+              PEER_FLAG_RSERVER_CLIENT))
+{
+      vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+            VTY_NEWLINE);
+    return CMD_WARNING;
+    }
+
+  return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi],
+                                  (argc == 4) ? argv[3] : argv[2],
+                                  AFI_IP6, safi, NULL, 1);
+}
+
+ALIAS (show_bgp_view_ipv6_safi_rsclient_prefix,
+       show_bgp_ipv6_safi_rsclient_prefix_cmd,
+       "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "IP prefix <network>/<length>, e.g., 3ffe::/16\n")
+
 #endif /* HAVE_IPV6 */
 \f
 struct bgp_table *bgp_distance_table;
@@ -9666,12 +11605,9 @@ struct bgp_distance
 };
 
 static struct bgp_distance *
-bgp_distance_new ()
+bgp_distance_new (void)
 {
-  struct bgp_distance *new;
-  new = XMALLOC (MTYPE_BGP_DISTANCE, sizeof (struct bgp_distance));
-  memset (new, 0, sizeof (struct bgp_distance));
-  return new;
+  return XCALLOC (MTYPE_BGP_DISTANCE, sizeof (struct bgp_distance));
 }
 
 static void
@@ -9766,23 +11702,6 @@ bgp_distance_unset (struct vty *vty, const char *distance_str,
   return CMD_SUCCESS;
 }
 
-static void
-bgp_distance_reset ()
-{
-  struct bgp_node *rn;
-  struct bgp_distance *bdistance;
-
-  for (rn = bgp_table_top (bgp_distance_table); rn; rn = bgp_route_next (rn))
-    if ((bdistance = rn->info) != NULL)
-      {
-       if (bdistance->access_list)
-         free (bdistance->access_list);
-       bgp_distance_free (bdistance);
-       rn->info = NULL;
-       bgp_unlock_node (rn);
-      }
-}
-
 /* Apply BGP information to distance method. */
 u_char
 bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp)
@@ -10100,41 +12019,49 @@ bgp_clear_damp_route (struct vty *vty, const char *view_name,
 
          if ((table = rn->info) != NULL)
            if ((rm = bgp_node_match (table, &match)) != NULL)
-             if (! prefix_check || rm->p.prefixlen == match.prefixlen)
-               {
-                 ri = rm->info;
-                 while (ri)
-                   {
-                     if (ri->damp_info)
-                       {
-                         ri_temp = ri->next;
-                         bgp_damp_info_free (ri->damp_info, 1);
-                         ri = ri_temp;
-                       }
-                     else
-                       ri = ri->next;
-                   }
-               }
+              {
+                if (! prefix_check || rm->p.prefixlen == match.prefixlen)
+                  {
+                    ri = rm->info;
+                    while (ri)
+                      {
+                        if (ri->extra && ri->extra->damp_info)
+                          {
+                            ri_temp = ri->next;
+                            bgp_damp_info_free (ri->extra->damp_info, 1);
+                            ri = ri_temp;
+                          }
+                        else
+                          ri = ri->next;
+                      }
+                  }
+
+                bgp_unlock_node (rm);
+              }
         }
     }
   else
     {
       if ((rn = bgp_node_match (bgp->rib[afi][safi], &match)) != NULL)
-       if (! prefix_check || rn->p.prefixlen == match.prefixlen)
-         {
-           ri = rn->info;
-           while (ri)
-             {
-               if (ri->damp_info)
-                 {
-                   ri_temp = ri->next;
-                   bgp_damp_info_free (ri->damp_info, 1);
-                   ri = ri_temp;
-                 }
-               else
-                 ri = ri->next;
-             }
-         }
+        {
+          if (! prefix_check || rn->p.prefixlen == match.prefixlen)
+            {
+              ri = rn->info;
+              while (ri)
+                {
+                  if (ri->extra && ri->extra->damp_info)
+                    {
+                      ri_temp = ri->next;
+                      bgp_damp_info_free (ri->extra->damp_info, 1);
+                      ri = ri_temp;
+                    }
+                  else
+                    ri = ri->next;
+                }
+            }
+
+          bgp_unlock_node (rn);
+        }
     }
 
   return CMD_SUCCESS;
@@ -10295,8 +12222,11 @@ bgp_config_write_network (struct vty *vty, struct bgp *bgp,
 
        if (bgp_static->rmap.name)
          vty_out (vty, " route-map %s", bgp_static->rmap.name);
-       else if (bgp_static->backdoor)
-         vty_out (vty, " backdoor");
+       else 
+         {
+           if (bgp_static->backdoor)
+             vty_out (vty, " backdoor");
+          }
 
        vty_out (vty, "%s", VTY_NEWLINE);
       }
@@ -10369,10 +12299,10 @@ bgp_config_write_distance (struct vty *vty, struct bgp *bgp)
 
 /* Allocate routing table structure and install commands. */
 void
-bgp_route_init ()
+bgp_route_init (void)
 {
   /* Init BGP distance table. */
-  bgp_distance_table = bgp_table_init ();
+  bgp_distance_table = bgp_table_init (AFI_IP, SAFI_UNICAST);
 
   /* IPv4 BGP commands. */
   install_element (BGP_NODE, &bgp_network_cmd);
@@ -10428,6 +12358,7 @@ bgp_route_init ()
   install_element (BGP_IPV4_NODE, &no_bgp_network_route_map_cmd);
   install_element (BGP_IPV4_NODE, &no_bgp_network_mask_route_map_cmd);
   install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_route_map_cmd);
+  
   install_element (BGP_IPV4_NODE, &aggregate_address_cmd);
   install_element (BGP_IPV4_NODE, &aggregate_address_mask_cmd);
   install_element (BGP_IPV4_NODE, &aggregate_address_summary_only_cmd);
@@ -10485,12 +12416,15 @@ bgp_route_init ()
 
   install_element (VIEW_NODE, &show_ip_bgp_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_prefix_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_prefix_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_view_cmd);
@@ -10516,6 +12450,11 @@ bgp_route_init ()
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_community2_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_community3_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_community4_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_afi_safi_community_all_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_afi_safi_community_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_afi_safi_community2_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_afi_safi_community3_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_afi_safi_community4_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_community_exact_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_community2_exact_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_community3_exact_cmd);
@@ -10534,6 +12473,7 @@ bgp_route_init ()
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_routes_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
@@ -10551,20 +12491,73 @@ bgp_route_init ()
   install_element (VIEW_NODE, &show_ip_bgp_neighbor_flap_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_neighbor_damp_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_rsclient_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_rsclient_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_rsclient_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd);
+  
+  /* Restricted node: VIEW_NODE - (set of dangerous commands) */
+  install_element (RESTRICTED_NODE, &show_ip_bgp_route_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_route_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_route_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_view_route_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_view_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_community_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_community2_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_community3_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_community4_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community2_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community3_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community4_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community_all_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community2_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community3_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community4_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_community_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_community2_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_community3_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_community4_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community2_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community3_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community4_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_rsclient_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_rsclient_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_view_rsclient_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd);
+  install_element (RESTRICTED_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd);
 
   install_element (ENABLE_NODE, &show_ip_bgp_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_prefix_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_prefix_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_view_cmd);
@@ -10590,6 +12583,11 @@ bgp_route_init ()
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community2_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community3_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community4_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community_all_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community2_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community3_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community4_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_community_exact_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_community2_exact_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_community3_exact_cmd);
@@ -10608,6 +12606,7 @@ bgp_route_init ()
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_routes_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_routes_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
@@ -10625,11 +12624,19 @@ bgp_route_init ()
   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_flap_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_damp_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_rsclient_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_rsclient_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_rsclient_prefix_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd);
 
  /* BGP dampening clear commands */
   install_element (ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
@@ -10637,7 +12644,13 @@ bgp_route_init ()
   install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
   install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
 
+  /* prefix count */
+  install_element (ENABLE_NODE, &show_ip_bgp_neighbor_prefix_counts_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_prefix_counts_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_neighbor_prefix_counts_cmd);
 #ifdef HAVE_IPV6
+  install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_prefix_counts_cmd);
+
   /* New config IPv6 BGP commands.  */
   install_element (BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
   install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd);
@@ -10649,6 +12662,9 @@ bgp_route_init ()
   install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
   install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_summary_only_cmd);
 
+  install_element (BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
+  install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd);
+
   /* Old config IPv6 BGP commands.  */
   install_element (BGP_NODE, &old_ipv6_bgp_network_cmd);
   install_element (BGP_NODE, &old_no_ipv6_bgp_network_cmd);
@@ -10660,10 +12676,13 @@ bgp_route_init ()
 
   install_element (VIEW_NODE, &show_bgp_cmd);
   install_element (VIEW_NODE, &show_bgp_ipv6_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_cmd);
   install_element (VIEW_NODE, &show_bgp_route_cmd);
   install_element (VIEW_NODE, &show_bgp_ipv6_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_route_cmd);
   install_element (VIEW_NODE, &show_bgp_prefix_cmd);
   install_element (VIEW_NODE, &show_bgp_ipv6_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_prefix_cmd);
   install_element (VIEW_NODE, &show_bgp_regexp_cmd);
   install_element (VIEW_NODE, &show_bgp_ipv6_regexp_cmd);
   install_element (VIEW_NODE, &show_bgp_prefix_list_cmd);
@@ -10709,8 +12728,11 @@ bgp_route_init ()
   install_element (VIEW_NODE, &show_bgp_neighbor_damp_cmd);
   install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_damp_cmd);
   install_element (VIEW_NODE, &show_bgp_rsclient_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_cmd);
   install_element (VIEW_NODE, &show_bgp_rsclient_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd);
   install_element (VIEW_NODE, &show_bgp_rsclient_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd);
   install_element (VIEW_NODE, &show_bgp_view_cmd);
   install_element (VIEW_NODE, &show_bgp_view_ipv6_cmd);
   install_element (VIEW_NODE, &show_bgp_view_route_cmd);
@@ -10730,15 +12752,61 @@ bgp_route_init ()
   install_element (VIEW_NODE, &show_bgp_view_neighbor_damp_cmd);
   install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_damp_cmd); 
   install_element (VIEW_NODE, &show_bgp_view_rsclient_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_cmd);
   install_element (VIEW_NODE, &show_bgp_view_rsclient_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd);
   install_element (VIEW_NODE, &show_bgp_view_rsclient_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd);
+  
+  /* Restricted:
+   * VIEW_NODE - (set of dangerous commands) - (commands dependent on prev) 
+   */
+  install_element (RESTRICTED_NODE, &show_bgp_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_community_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_community_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_community2_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_community2_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_community3_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_community3_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_community4_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_community4_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_community_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_community_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_community2_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_community2_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_community3_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_community3_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_community4_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_community4_exact_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_rsclient_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_rsclient_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_neighbor_received_prefix_filter_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_neighbor_received_prefix_filter_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_rsclient_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_rsclient_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd);
 
   install_element (ENABLE_NODE, &show_bgp_cmd);
   install_element (ENABLE_NODE, &show_bgp_ipv6_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_cmd);
   install_element (ENABLE_NODE, &show_bgp_route_cmd);
   install_element (ENABLE_NODE, &show_bgp_ipv6_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_route_cmd);
   install_element (ENABLE_NODE, &show_bgp_prefix_cmd);
   install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_prefix_cmd);
   install_element (ENABLE_NODE, &show_bgp_regexp_cmd);
   install_element (ENABLE_NODE, &show_bgp_ipv6_regexp_cmd);
   install_element (ENABLE_NODE, &show_bgp_prefix_list_cmd);
@@ -10784,8 +12852,11 @@ bgp_route_init ()
   install_element (ENABLE_NODE, &show_bgp_neighbor_damp_cmd);
   install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_damp_cmd);
   install_element (ENABLE_NODE, &show_bgp_rsclient_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_cmd);
   install_element (ENABLE_NODE, &show_bgp_rsclient_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd);
   install_element (ENABLE_NODE, &show_bgp_rsclient_prefix_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_ipv6_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_route_cmd);
@@ -10805,9 +12876,18 @@ bgp_route_init ()
   install_element (ENABLE_NODE, &show_bgp_view_neighbor_damp_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_damp_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_rsclient_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_rsclient_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_rsclient_prefix_cmd);
-
+  install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd);
+  
+  /* Statistics */
+  install_element (ENABLE_NODE, &show_bgp_statistics_cmd);
+  install_element (ENABLE_NODE, &show_bgp_statistics_vpnv4_cmd);
+  install_element (ENABLE_NODE, &show_bgp_statistics_view_cmd);
+  install_element (ENABLE_NODE, &show_bgp_statistics_view_vpnv4_cmd);
+  
   /* old command */
   install_element (VIEW_NODE, &show_ipv6_bgp_cmd);
   install_element (VIEW_NODE, &show_ipv6_bgp_route_cmd);
@@ -10921,4 +13001,59 @@ bgp_route_init ()
   install_element (BGP_IPV4_NODE, &bgp_damp_set3_cmd);
   install_element (BGP_IPV4_NODE, &bgp_damp_unset_cmd);
   install_element (BGP_IPV4_NODE, &bgp_damp_unset2_cmd);
+  
+  /* Deprecated AS-Pathlimit commands */
+  install_element (BGP_NODE, &bgp_network_ttl_cmd);
+  install_element (BGP_NODE, &bgp_network_mask_ttl_cmd);
+  install_element (BGP_NODE, &bgp_network_mask_natural_ttl_cmd);
+  install_element (BGP_NODE, &bgp_network_backdoor_ttl_cmd);
+  install_element (BGP_NODE, &bgp_network_mask_backdoor_ttl_cmd);
+  install_element (BGP_NODE, &bgp_network_mask_natural_backdoor_ttl_cmd);
+  
+  install_element (BGP_NODE, &no_bgp_network_ttl_cmd);
+  install_element (BGP_NODE, &no_bgp_network_mask_ttl_cmd);
+  install_element (BGP_NODE, &no_bgp_network_mask_natural_ttl_cmd);
+  install_element (BGP_NODE, &no_bgp_network_backdoor_ttl_cmd);
+  install_element (BGP_NODE, &no_bgp_network_mask_backdoor_ttl_cmd);
+  install_element (BGP_NODE, &no_bgp_network_mask_natural_backdoor_ttl_cmd);
+  
+  install_element (BGP_IPV4_NODE, &bgp_network_ttl_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_network_mask_ttl_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_ttl_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_network_backdoor_ttl_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_network_mask_backdoor_ttl_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_backdoor_ttl_cmd);
+  
+  install_element (BGP_IPV4_NODE, &no_bgp_network_ttl_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_mask_ttl_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_ttl_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_backdoor_ttl_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_mask_backdoor_ttl_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_backdoor_ttl_cmd);
+  
+  install_element (BGP_IPV4M_NODE, &bgp_network_ttl_cmd);
+  install_element (BGP_IPV4M_NODE, &bgp_network_mask_ttl_cmd);
+  install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_ttl_cmd);
+  install_element (BGP_IPV4M_NODE, &bgp_network_backdoor_ttl_cmd);
+  install_element (BGP_IPV4M_NODE, &bgp_network_mask_backdoor_ttl_cmd);
+  install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_backdoor_ttl_cmd);
+  
+  install_element (BGP_IPV4M_NODE, &no_bgp_network_ttl_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_ttl_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_ttl_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_network_backdoor_ttl_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_backdoor_ttl_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_backdoor_ttl_cmd);
+
+#ifdef HAVE_IPV6
+  install_element (BGP_IPV6_NODE, &ipv6_bgp_network_ttl_cmd);
+  install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_ttl_cmd);
+#endif
+}
+
+void
+bgp_route_finish (void)
+{
+  bgp_table_unlock (bgp_distance_table);
+  bgp_distance_table = NULL;
 }