[bgpd] Add support for AS_PATHLIMIT / draft-ietf-idr-as-pathlimit

2007-07-31 Paul Jakma <paul.jakma@sun.com>

	* (general) Support for draft-ietf-idr-as-pathlimit-03.
	* bgp_attr.h: (struct attr) Add pathlimit struct
          bgp_attr.c: (attr_str) Add BGP_ATTR_AS_PATHLIMIT string.
          (attrhash_key_make) tally pathlimit too
          (attrhash_cmp) cmp pathlimit attr
          (bgp_attr_aspathlimit) New, parse AS_PATHLIMIT attr.
          (bgp_attr_parse) ditto
          (bgp_packet_attribute) Write out AS_PATHLIMIT when set
          (bgp_dump_routes_attr) ditto
         * bgp_route.h: (struct bgp_static) Add TTL field
         * bgp_route.c: (bgp_announce_check) Drop paths that are over
           their hop-count TTL before sending via EBGP.
           Mangle ASN in pathlimit for confeds/private as best we can.
           (bgp_static_update_{rsclient,main}) Add any configure pathlimit
           information.
           (bgp_pathlimit_update_parents) New, update atomic-aggr setting for
           parents of an aspathlimit'ed static.
           (bgp_static_set) Add TTL argument, for all the 'bgp network'
           commands.
           Call previous for TTL changed statics.
           (bgp_static_unset) Call pathlimit_update_parents.
           (various bgp network commands) Add 'pathlimit <0-255>' qualifier
           to all the various forms, bar route-map - which can set ttl
           itself.
         * bgp_routemap.c: (general) Add support for 'set pathlimit ttl' and
           'match pathlimit as'.
         * doc/bgpd.texi: Document 'network ... pathlimit <ttl>'
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 1c0e6f1..0f4da98 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -883,7 +883,20 @@
 	    return 0;
 	}
     }
-
+  
+  /* AS-Pathlimit check */
+  if (ri->attr->pathlimit.ttl && peer_sort (peer) == BGP_PEER_EBGP)
+    /* Our ASN has not yet been pre-pended, that's done in packet_attribute
+     * on output. Hence the test here is for >=.
+     */
+    if (aspath_count_hops (ri->attr->aspath) >= ri->attr->pathlimit.ttl)
+      {
+        if (BGP_DEBUG (filter, FILTER))
+          zlog_info ("%s [Update:SEND] suppressed, AS-Pathlimit TTL %u exceeded",
+                     peer->host, ri->attr->pathlimit.ttl);
+        return 0;
+      }
+  
   /* For modify attribute, copy it to temporary structure. */
   bgp_attr_dup (attr, ri->attr);
   
@@ -988,6 +1001,39 @@
     }
 #endif /* HAVE_IPV6 */
 
+  /* AS-Pathlimit: Check ASN for private/confed */
+  if (attr->pathlimit.ttl)
+    {
+      /* locally originated update */
+      if (!attr->pathlimit.as)
+        attr->pathlimit.as = peer->local_as;
+      
+      /* if the AS_PATHLIMIT attribute is attached to a prefix by a
+         member of a confederation, then when the prefix is advertised outside
+         of the confederation boundary, then the AS number of the
+         confederation member inside of the AS_PATHLIMIT attribute should be
+         replaced by the confederation's AS number. */
+      if (peer_sort (from) == BGP_PEER_CONFED 
+          && peer_sort (peer) != BGP_PEER_CONFED)
+        attr->pathlimit.as = peer->local_as;
+
+      /* Private ASN should be updated whenever announcement leaves
+       * private space. This is deliberately done after simple confed
+       * based update..
+       */
+      if (attr->pathlimit.as >= BGP_PRIVATE_AS_MIN
+          && attr->pathlimit.as <= BGP_PRIVATE_AS_MAX)
+        {
+          if (peer->local_as < BGP_PRIVATE_AS_MIN 
+              || peer->local_as > BGP_PRIVATE_AS_MAX)
+            attr->pathlimit.as = peer->local_as;
+          /* Ours is private, try using theirs.. */
+          else if (peer->as < BGP_PRIVATE_AS_MIN
+                   || peer->local_as > BGP_PRIVATE_AS_MAX)
+            attr->pathlimit.as = peer->as;
+        }
+    }
+  
   /* If this is EBGP peer and remove-private-AS is set.  */
   if (peer_sort (peer) == BGP_PEER_EBGP
       && peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
@@ -3151,7 +3197,18 @@
   attr.nexthop = bgp_static->igpnexthop;
   attr.med = bgp_static->igpmetric;
   attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
-
+  
+  if (bgp_static->ttl)
+    {
+      attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATHLIMIT);
+      attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
+      attr.pathlimit.as = 0;
+      attr.pathlimit.ttl = bgp_static->ttl;
+    }
+  
+  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)
     {
@@ -3297,6 +3354,17 @@
   attr.med = bgp_static->igpmetric;
   attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
 
+  if (bgp_static->ttl)
+    {
+      attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATHLIMIT);
+      attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
+      attr.pathlimit.as = 0;
+      attr.pathlimit.ttl = bgp_static->ttl;
+    }
+
+  if (bgp_static->atomic)
+    attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
+
   /* Apply route-map. */
   if (bgp_static->rmap.name)
     {
@@ -3517,17 +3585,44 @@
   bgp_unlock_node (rn);
 }
 
+static void
+bgp_pathlimit_update_parents (struct bgp *bgp, struct bgp_node *rn,
+                              int ttl_edge)
+{
+  struct bgp_node *parent = rn;
+  struct bgp_static *sp;
+  
+  /* Existing static changed TTL, search parents and adjust their atomic */
+  while ((parent = parent->parent))
+    if ((sp = parent->info))
+      {
+        int sp_level = (sp->atomic ? 1 : 0);
+        ttl_edge ? sp->atomic++ : sp->atomic--;
+        
+        /* did we change state of parent whether atomic is set or not? */
+        if (sp_level != (sp->atomic ? 1 : 0))
+          {
+            bgp_static_update (bgp, &parent->p, sp,
+                               rn->table->afi, rn->table->safi);
+          }
+      }
+}
+
 /* Configure static BGP network.  When user don't run zebra, static
    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)
+                u_int16_t afi, u_char safi, const char *rmap, int backdoor,
+                u_char ttl)
 {
   int ret;
   struct prefix p;
   struct bgp_static *bgp_static;
   struct bgp_node *rn;
-  int need_update = 0;
+  u_char need_update = 0;
+  u_char ttl_change = 0;
+  u_char ttl_edge = (ttl ? 1 : 0);
+  u_char new = 0;
 
   /* Convert IP prefix string to struct prefix. */
   ret = str2prefix (ip_str, &p);
@@ -3556,10 +3651,22 @@
       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)
+        {
+          if (bgp_static->backdoor != backdoor
+              || bgp_static->ttl != ttl)
+            need_update = 1;
+        }
+      
+      /* need to catch TTL set/unset transitions for handling of
+       * ATOMIC_AGGREGATE 
+       */ 
+      if ((bgp_static->ttl ? 1 : 0) != ttl_edge)
+        ttl_change = 1;
+          
       bgp_static->backdoor = backdoor;
+      bgp_static->ttl = ttl;
+      
       if (rmap)
 	{
 	  if (bgp_static->rmap.name)
@@ -3585,6 +3692,10 @@
       bgp_static->valid = 0;
       bgp_static->igpmetric = 0;
       bgp_static->igpnexthop.s_addr = 0;
+      bgp_static->ttl = ttl;
+      ttl_change = ttl_edge;
+      new = 1;
+      
       if (rmap)
 	{
 	  if (bgp_static->rmap.name)
@@ -3595,6 +3706,39 @@
       rn->info = bgp_static;
     }
 
+  /* ".. sites that choose to advertise the
+   *  AS_PATHLIMIT path attribute SHOULD advertise the ATOMIC_AGGREGATE on
+   *  all less specific covering prefixes as well as the more specific
+   *  prefixes."
+   *
+   * So:
+   * Prefix that has just had pathlimit set/unset:
+   * - Must bump ATOMIC refcount on all parents.
+   *
+   * To catch less specific prefixes:
+   * - Must search children for ones with TTL, bump atomic refcount
+   *   (we dont care if we're deleting a less specific prefix..)
+   */
+  if (ttl_change)
+    {
+      /* Existing static changed TTL, search parents and adjust their atomic */
+      bgp_pathlimit_update_parents (bgp, rn, ttl_edge);
+    }
+  
+  if (new)
+    {
+      struct bgp_node *child;
+      struct bgp_static *sc;
+      
+      /* New static, search children and bump this statics atomic.. */
+      child = bgp_lock_node (rn); /* route_next_until unlocks it.. */
+      while ((child = bgp_route_next_until (child, rn)))
+        {
+          if ((sc = child->info) && sc->ttl)
+            bgp_static->atomic++;
+        }
+    }
+  
   /* If BGP scan is not enabled, we should install this route here.  */
   if (! bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
     {
@@ -3647,7 +3791,10 @@
     }
 
   bgp_static = rn->info;
-
+  
+  /* decrement atomic in parents, see bgp_static_set */
+  bgp_pathlimit_update_parents (bgp, rn, 0);
+  
   /* Update BGP RIB. */
   if (! bgp_static->backdoor)
     bgp_static_withdraw (bgp, &p, afi, safi);
@@ -3844,10 +3991,23 @@
        "Specify a network to announce via BGP\n"
        "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
 {
+  u_char ttl = 0;
+  
+  if (argc == 2)
+    VTY_GET_INTEGER_RANGE ("Pathlimit TTL", ttl, argv[1], 1, 255);
+  
   return bgp_static_set (vty, vty->index, argv[0],
-			 AFI_IP, bgp_node_safi (vty), NULL, 0);
+			 AFI_IP, bgp_node_safi (vty), NULL, 0, ttl);
 }
 
+ALIAS (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")
+
 DEFUN (bgp_network_route_map,
        bgp_network_route_map_cmd,
        "network A.B.C.D/M route-map WORD",
@@ -3857,7 +4017,7 @@
        "Name of the route map\n")
 {
   return bgp_static_set (vty, vty->index, argv[0],
-			 AFI_IP, bgp_node_safi (vty), argv[1], 0);
+			 AFI_IP, bgp_node_safi (vty), argv[1], 0, 0);
 }
 
 DEFUN (bgp_network_backdoor,
@@ -3867,9 +4027,24 @@
        "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);
+  u_char ttl = 0;
+  
+  if (argc == 2)
+    VTY_GET_INTEGER_RANGE ("Pathlimit TTL", ttl, argv[1], 1, 255);
+  
+  return bgp_static_set (vty, vty->index, argv[0], AFI_IP, SAFI_UNICAST,
+                         NULL, 1, ttl);
 }
 
+ALIAS (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")
+
 DEFUN (bgp_network_mask,
        bgp_network_mask_cmd,
        "network A.B.C.D mask A.B.C.D",
@@ -3880,7 +4055,11 @@
 {
   int ret;
   char prefix_str[BUFSIZ];
-
+  u_char ttl = 0;
+  
+  if (argc == 3)
+    VTY_GET_INTEGER_RANGE ("Pathlimit TTL", ttl, argv[2], 1, 255);
+  
   ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
   if (! ret)
     {
@@ -3889,9 +4068,19 @@
     }
 
   return bgp_static_set (vty, vty->index, prefix_str,
-			 AFI_IP, bgp_node_safi (vty), NULL, 0);
+			 AFI_IP, bgp_node_safi (vty), NULL, 0, ttl);
 }
 
+ALIAS (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")
+
 DEFUN (bgp_network_mask_route_map,
        bgp_network_mask_route_map_cmd,
        "network A.B.C.D mask A.B.C.D route-map WORD",
@@ -3904,7 +4093,7 @@
 {
   int ret;
   char prefix_str[BUFSIZ];
-
+  
   ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
   if (! ret)
     {
@@ -3913,7 +4102,7 @@
     }
 
   return bgp_static_set (vty, vty->index, prefix_str,
-			 AFI_IP, bgp_node_safi (vty), argv[2], 0);
+			 AFI_IP, bgp_node_safi (vty), argv[2], 0, 0);
 }
 
 DEFUN (bgp_network_mask_backdoor,
@@ -3927,6 +4116,10 @@
 {
   int ret;
   char prefix_str[BUFSIZ];
+  u_char ttl = 0;
+  
+  if (argc == 3)
+    VTY_GET_INTEGER_RANGE ("Pathlimit TTL", ttl, argv[2], 1, 255);
 
   ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
   if (! ret)
@@ -3935,9 +4128,21 @@
       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, ttl);
 }
 
+ALIAS (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")
+
 DEFUN (bgp_network_mask_natural,
        bgp_network_mask_natural_cmd,
        "network A.B.C.D",
@@ -3946,6 +4151,10 @@
 {
   int ret;
   char prefix_str[BUFSIZ];
+  u_char ttl = 0;
+  
+  if (argc == 2)
+    VTY_GET_INTEGER_RANGE ("Pathlimit TTL", ttl, argv[1], 1, 255);
 
   ret = netmask_str2prefix_str (argv[0], NULL, prefix_str);
   if (! ret)
@@ -3955,9 +4164,17 @@
     }
 
   return bgp_static_set (vty, vty->index, prefix_str,
-			 AFI_IP, bgp_node_safi (vty), NULL, 0);
+			 AFI_IP, bgp_node_safi (vty), NULL, 0, ttl);
 }
 
+ALIAS (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")
+
 DEFUN (bgp_network_mask_natural_route_map,
        bgp_network_mask_natural_route_map_cmd,
        "network A.B.C.D route-map WORD",
@@ -3977,7 +4194,7 @@
     }
 
   return bgp_static_set (vty, vty->index, prefix_str,
-			 AFI_IP, bgp_node_safi (vty), argv[1], 0);
+			 AFI_IP, bgp_node_safi (vty), argv[1], 0, 0);
 }
 
 DEFUN (bgp_network_mask_natural_backdoor,
@@ -3989,6 +4206,10 @@
 {
   int ret;
   char prefix_str[BUFSIZ];
+  u_char ttl = 0;
+  
+  if (argc == 2)
+    VTY_GET_INTEGER_RANGE ("Pathlimit TTL", ttl, argv[1], 1, 255);
 
   ret = netmask_str2prefix_str (argv[0], NULL, prefix_str);
   if (! ret)
@@ -3997,9 +4218,19 @@
       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, ttl);
 }
 
+ALIAS (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")
+
 DEFUN (no_bgp_network,
        no_bgp_network_cmd,
        "no network A.B.C.D/M",
@@ -4012,6 +4243,15 @@
 }
 
 ALIAS (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 (no_bgp_network,
        no_bgp_network_route_map_cmd,
        "no network A.B.C.D/M route-map WORD",
        NO_STR
@@ -4028,6 +4268,16 @@
        "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
        "Specify a BGP backdoor route\n")
 
+ALIAS (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")
+
 DEFUN (no_bgp_network_mask,
        no_bgp_network_mask_cmd,
        "no network A.B.C.D mask A.B.C.D",
@@ -4051,6 +4301,17 @@
 			   bgp_node_safi (vty));
 }
 
+ALIAS (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 (no_bgp_network_mask,
        no_bgp_network_mask_route_map_cmd,
        "no network A.B.C.D mask A.B.C.D route-map WORD",
@@ -4072,6 +4333,18 @@
        "Network mask\n"
        "Specify a BGP backdoor route\n")
 
+ALIAS (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")
+
 DEFUN (no_bgp_network_mask_natural,
        no_bgp_network_mask_natural_cmd,
        "no network A.B.C.D",
@@ -4110,6 +4383,25 @@
        "Network number\n"
        "Specify a BGP backdoor route\n")
 
+ALIAS (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 (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
 DEFUN (ipv6_bgp_network,
        ipv6_bgp_network_cmd,
@@ -4117,9 +4409,23 @@
        "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);
+  u_char ttl = 0;
+  
+  if (argc == 2)
+    VTY_GET_INTEGER_RANGE ("Pathlimit TTL", ttl, argv[1], 1, 255);
+
+  return bgp_static_set (vty, vty->index, argv[0], AFI_IP6, SAFI_UNICAST,
+                         NULL, 0, ttl);
 }
 
+ALIAS (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")
+
 DEFUN (ipv6_bgp_network_route_map,
        ipv6_bgp_network_route_map_cmd,
        "network X:X::X:X/M route-map WORD",
@@ -4129,7 +4435,7 @@
        "Name of the route map\n")
 {
   return bgp_static_set (vty, vty->index, argv[0], AFI_IP6,
-			 bgp_node_safi (vty), argv[1], 0);
+			 bgp_node_safi (vty), argv[1], 0, 0);
 }
 
 DEFUN (no_ipv6_bgp_network,
@@ -4151,6 +4457,15 @@
        "Route-map to modify the attributes\n"
        "Name of the route map\n")
 
+ALIAS (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")
+
 ALIAS (ipv6_bgp_network,
        old_ipv6_bgp_network_cmd,
        "ipv6 bgp network X:X::X:X/M",
@@ -5777,7 +6092,18 @@
 	    }
 	  vty_out (vty, "%s", VTY_NEWLINE);
 	}
-
+      
+      /* 7: AS Pathlimit */
+      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AS_PATHLIMIT))
+        {
+          
+          vty_out (vty, "      AS-Pathlimit: %u",
+                   attr->pathlimit.ttl);
+          if (attr->pathlimit.as)
+            vty_out (vty, " (%u)", attr->pathlimit.as);
+          vty_out (vty, "%s", VTY_NEWLINE);
+        }
+      
       if (binfo->extra && binfo->extra->damp_info)
 	bgp_damp_info_vty (vty, binfo);
 
@@ -11166,8 +11492,13 @@
 
 	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");
+            if (bgp_static->ttl)
+              vty_out (vty, " pathlimit %u", bgp_static->ttl);
+          }
 
 	vty_out (vty, "%s", VTY_NEWLINE);
       }
@@ -11255,6 +11586,12 @@
   install_element (BGP_NODE, &bgp_network_backdoor_cmd);
   install_element (BGP_NODE, &bgp_network_mask_backdoor_cmd);
   install_element (BGP_NODE, &bgp_network_mask_natural_backdoor_cmd);
+  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_cmd);
   install_element (BGP_NODE, &no_bgp_network_mask_cmd);
   install_element (BGP_NODE, &no_bgp_network_mask_natural_cmd);
@@ -11264,6 +11601,12 @@
   install_element (BGP_NODE, &no_bgp_network_backdoor_cmd);
   install_element (BGP_NODE, &no_bgp_network_mask_backdoor_cmd);
   install_element (BGP_NODE, &no_bgp_network_mask_natural_backdoor_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_NODE, &aggregate_address_cmd);
   install_element (BGP_NODE, &aggregate_address_mask_cmd);
@@ -11293,12 +11636,23 @@
   install_element (BGP_IPV4_NODE, &bgp_network_route_map_cmd);
   install_element (BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd);
   install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd);
-  install_element (BGP_IPV4_NODE, &no_bgp_network_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_cmd);
   install_element (BGP_IPV4_NODE, &no_bgp_network_mask_cmd);
   install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_cmd);
   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, &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_IPV4_NODE, &no_bgp_network_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);
@@ -11327,12 +11681,24 @@
   install_element (BGP_IPV4M_NODE, &bgp_network_route_map_cmd);
   install_element (BGP_IPV4M_NODE, &bgp_network_mask_route_map_cmd);
   install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_route_map_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_IPV4_NODE, &no_bgp_network_cmd);
   install_element (BGP_IPV4M_NODE, &no_bgp_network_cmd);
   install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_cmd);
   install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_cmd);
   install_element (BGP_IPV4M_NODE, &no_bgp_network_route_map_cmd);
   install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_route_map_cmd);
   install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_route_map_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);  install_element (BGP_IPV4_NODE, &no_bgp_network_cmd);
   install_element (BGP_IPV4M_NODE, &aggregate_address_cmd);
   install_element (BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
   install_element (BGP_IPV4M_NODE, &aggregate_address_summary_only_cmd);
@@ -11518,8 +11884,10 @@
   /* 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);
+  install_element (BGP_IPV6_NODE, &ipv6_bgp_network_ttl_cmd);
   install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd);
   install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_route_map_cmd);
+  install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_ttl_cmd);
 
   install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
   install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_summary_only_cmd);