summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/ChangeLog29
-rw-r--r--bgpd/bgp_attr.c82
-rw-r--r--bgpd/bgp_attr.h8
-rw-r--r--bgpd/bgp_route.c418
-rw-r--r--bgpd/bgp_route.h6
-rw-r--r--bgpd/bgp_routemap.c169
-rw-r--r--bgpd/bgpd.h1
-rw-r--r--doc/ChangeLog4
-rw-r--r--doc/bgpd.texi25
-rw-r--r--doc/routemap.texi14
10 files changed, 725 insertions, 31 deletions
diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog
index 7a93a90b..26614ced 100644
--- a/bgpd/ChangeLog
+++ b/bgpd/ChangeLog
@@ -1,3 +1,32 @@
+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'.
+
2007-07-26 Paul Jakma <paul.jakma@sun.com>
* (general) Clean up and compact capability parsing slightly.
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 07c94130..23d95865 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -56,6 +56,8 @@ static struct message attr_str [] =
{ BGP_ATTR_RCID_PATH, "RCID_PATH" },
{ BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
{ BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
+ { BGP_ATTR_EXT_COMMUNITIES, "BGP_ATTR_EXT_COMMUNITIES" },
+ { BGP_ATTR_AS_PATHLIMIT, "BGP_ATTR_AS_PATHLIMIT" },
{ 0, NULL }
};
int attr_str_max = sizeof(attr_str)/sizeof(attr_str[0]);
@@ -345,6 +347,11 @@ attrhash_key_make (void *p)
key += attr->nexthop.s_addr;
key += attr->med;
key += attr->local_pref;
+ if (attr->pathlimit.as)
+ {
+ key += attr->pathlimit.ttl;
+ key += attr->pathlimit.as;
+ }
if (attr->extra)
{
@@ -396,7 +403,9 @@ attrhash_cmp (void *p1, void *p2)
&& attr1->aspath == attr2->aspath
&& attr1->community == attr2->community
&& attr1->med == attr2->med
- && attr1->local_pref == attr2->local_pref)
+ && attr1->local_pref == attr2->local_pref
+ && attr1->pathlimit.ttl == attr2->pathlimit.ttl
+ && attr1->pathlimit.as == attr2->pathlimit.as)
{
struct attr_extra *ae1 = attr1->extra;
struct attr_extra *ae2 = attr2->extra;
@@ -676,6 +685,42 @@ bgp_attr_flush (struct attr *attr)
}
}
+/* Parse AS_PATHLIMIT attribute in an UPDATE */
+static int
+bgp_attr_aspathlimit (struct peer *peer, bgp_size_t length,
+ struct attr *attr, u_char flag, u_char *startp)
+{
+ bgp_size_t total;
+
+ total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+
+ if (flag != (BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL))
+ {
+ zlog (peer->log, LOG_ERR,
+ "AS-Pathlimit attribute flag isn't transitive %d", flag);
+ bgp_notify_send_with_data (peer,
+ BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
+ return -1;
+ }
+
+ if (length != 5)
+ {
+ zlog (peer->log, LOG_ERR,
+ "AS-Pathlimit length, %u, is not 5", length);
+ bgp_notify_send_with_data (peer,
+ BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+ startp, total);
+ return -1;
+ }
+
+ attr->pathlimit.ttl = stream_getc (BGP_INPUT(peer));
+ attr->pathlimit.as = stream_getl (BGP_INPUT(peer));
+ attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATHLIMIT);
+ return 0;
+}
/* Get origin attribute of the update message. */
static int
bgp_attr_origin (struct peer *peer, bgp_size_t length,
@@ -1290,7 +1335,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
{
/* XXX warning: long int format, int arg (arg 5) */
zlog (peer->log, LOG_WARNING,
- "%s error BGP attribute length %ld is smaller than min len",
+ "%s error BGP attribute length %lu is smaller than min len",
peer->host, endp - STREAM_PNT (BGP_INPUT (peer)));
bgp_notify_send (peer,
@@ -1386,6 +1431,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
case BGP_ATTR_EXT_COMMUNITIES:
ret = bgp_attr_ext_communities (peer, length, attr, flag);
break;
+ case BGP_ATTR_AS_PATHLIMIT:
+ ret = bgp_attr_aspathlimit (peer, length, attr, flag, startp);
+ break;
default:
ret = bgp_attr_unknown (peer, attr, flag, type, length, startp);
break;
@@ -1824,7 +1872,25 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
}
}
}
-
+
+ /* AS-Pathlimit */
+ if (attr->pathlimit.ttl)
+ {
+ u_int32_t as = attr->pathlimit.as;
+
+ /* should already have been done in announce_check(),
+ * but just in case..
+ */
+ if (!as)
+ as = peer->local_as;
+
+ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+ stream_putc (s, BGP_ATTR_AS_PATHLIMIT);
+ stream_putc (s, 5);
+ stream_putc (s, attr->pathlimit.ttl);
+ stream_putl (s, as);
+ }
+
/* Unknown transit attribute. */
if (attr->extra && attr->extra->transit)
stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
@@ -2034,6 +2100,16 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
}
#endif /* HAVE_IPV6 */
+ /* AS-Pathlimit */
+ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AS_PATHLIMIT))
+ {
+ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+ stream_putc (s, BGP_ATTR_AS_PATHLIMIT);
+ stream_putc (s, 5);
+ stream_putc (s, attr->pathlimit.ttl);
+ stream_putl (s, attr->pathlimit.as);
+ }
+
/* Return total size of attribute. */
len = stream_get_endp (s) - cp - 2;
stream_putw_at (s, cp, len);
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index ac14947f..1af9ce30 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -109,7 +109,13 @@ struct attr
struct in_addr nexthop;
u_int32_t med;
u_int32_t local_pref;
-
+
+ /* AS-Pathlimit */
+ struct {
+ u_int32_t as;
+ u_char ttl;
+ } pathlimit;
+
/* Path origin attribute */
u_char origin;
};
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 1c0e6f1a..0f4da980 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -883,7 +883,20 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
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 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
}
#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 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
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 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
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_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi,
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_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)
+ {
+ 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_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;
+ bgp_static->ttl = ttl;
+ ttl_change = ttl_edge;
+ new = 1;
+
if (rmap)
{
if (bgp_static->rmap.name)
@@ -3595,6 +3706,39 @@ bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str,
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_unset (struct vty *vty, struct bgp *bgp, const char *ip_str,
}
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 @@ DEFUN (bgp_network,
"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 @@ DEFUN (bgp_network_route_map,
"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 @@ 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);
+ 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 @@ DEFUN (bgp_network_mask,
{
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 @@ DEFUN (bgp_network_mask,
}
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 @@ DEFUN (bgp_network_mask_route_map,
{
int ret;
char prefix_str[BUFSIZ];
-
+
ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
if (! ret)
{
@@ -3913,7 +4102,7 @@ DEFUN (bgp_network_mask_route_map,
}
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 @@ DEFUN (bgp_network_mask_backdoor,
{
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 @@ 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, 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 @@ DEFUN (bgp_network_mask_natural,
{
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 @@ DEFUN (bgp_network_mask_natural,
}
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 @@ DEFUN (bgp_network_mask_natural_route_map,
}
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 @@ DEFUN (bgp_network_mask_natural_backdoor,
{
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 @@ 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, 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 @@ DEFUN (no_bgp_network,
}
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 @@ ALIAS (no_bgp_network,
"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 @@ DEFUN (no_bgp_network_mask,
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 @@ ALIAS (no_bgp_network_mask,
"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 @@ ALIAS (no_bgp_network_mask_natural,
"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 @@ 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);
+ 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 @@ DEFUN (ipv6_bgp_network_route_map,
"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 @@ ALIAS (no_ipv6_bgp_network,
"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 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
}
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 @@ 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");
+ if (bgp_static->ttl)
+ vty_out (vty, " pathlimit %u", bgp_static->ttl);
+ }
vty_out (vty, "%s", VTY_NEWLINE);
}
@@ -11255,6 +11586,12 @@ bgp_route_init ()
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 @@ bgp_route_init ()
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 @@ bgp_route_init ()
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 @@ bgp_route_init ()
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 @@ bgp_route_init ()
/* 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);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index c7eb8c6c..e5987972 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -104,6 +104,9 @@ struct bgp_static
/* IGP nexthop. */
struct in_addr igpnexthop;
+ /* Atomic set reference count (ie cause of pathlimit) */
+ u_int32_t atomic;
+
/* BGP redistribute route-map. */
struct
{
@@ -113,6 +116,9 @@ struct bgp_static
/* MPLS label. */
u_char tag[3];
+
+ /* AS-Pathlimit TTL */
+ u_char ttl;
};
/* Flags which indicate a route is unuseable in some form */
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 6a44c479..305d6796 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -87,14 +87,106 @@ o Cisco route-map
origin : Done
tag : (This will not be implemented by bgpd)
weight : Done
+ pathlimit : Done
o Local extention
set ipv6 next-hop global: Done
set ipv6 next-hop local : Done
+ set pathlimit ttl : Done
+ match pathlimit as : Done
*/
+/* Compiles either AS or TTL argument. It is amused the VTY code
+ * has already range-checked the values to be suitable as TTL or ASN
+ */
+static void *
+route_pathlimit_compile (const char *arg)
+{
+ unsigned long tmp;
+ u_int32_t *val;
+ char *endptr = NULL;
+
+ /* TTL or AS value shoud be integer. */
+ if (! all_digit (arg))
+ return NULL;
+
+ tmp = strtoul (arg, &endptr, 10);
+ if (*endptr != '\0' || tmp == ULONG_MAX || tmp > UINT32_MAX)
+ return NULL;
+
+ if (!(val = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t))))
+ return NULL;
+
+ *val = tmp;
+
+ return val;
+}
+
+static void
+route_pathlimit_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static route_map_result_t
+route_match_pathlimit_as (void *rule, struct prefix *prefix, route_map_object_t type,
+ void *object)
+{
+ struct bgp_info *info = object;
+ struct attr *attr = info->attr;
+ uint32_t as = *(uint32_t *)rule;
+
+ if (type != RMAP_BGP)
+ return RMAP_NOMATCH;
+
+ if (!attr->pathlimit.as)
+ return RMAP_NOMATCH;
+
+ if (as == attr->pathlimit.as)
+ return RMAP_MATCH;
+
+ return RMAP_NOMATCH;
+}
+
+/* 'match pathlimit as' */
+struct route_map_rule_cmd route_match_pathlimit_as_cmd =
+{
+ "pathlimit as",
+ route_match_pathlimit_as,
+ route_pathlimit_compile,
+ route_pathlimit_free
+};
+
+/* Set pathlimit TTL. */
+static route_map_result_t
+route_set_pathlimit_ttl (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct bgp_info *info = object;
+ struct attr *attr = info->attr;
+ u_char ttl = *(uint32_t *)rule;
+
+ if (type == RMAP_BGP)
+ {
+ attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATHLIMIT);
+ attr->pathlimit.ttl = ttl;
+ attr->pathlimit.as = 0;
+ }
+
+ return RMAP_OKAY;
+}
+
+/* Set local preference rule structure. */
+struct route_map_rule_cmd route_set_pathlimit_ttl_cmd =
+{
+ "pathlimit ttl",
+ route_set_pathlimit_ttl,
+ route_pathlimit_compile,
+ route_pathlimit_free,
+};
+
/* 'match peer (A.B.C.D|X:X::X:X)' */
/* Compares the peer specified in the 'match peer' clause with the peer
@@ -3538,6 +3630,70 @@ ALIAS (no_set_originator_id,
"BGP originator ID attribute\n"
"IP address of originator\n")
+DEFUN (set_pathlimit_ttl,
+ set_pathlimit_ttl_cmd,
+ "set pathlimit ttl <1-255>",
+ SET_STR
+ "BGP AS-Pathlimit attribute\n"
+ "Set AS-Path Hop-count TTL\n")
+{
+ return bgp_route_set_add (vty, vty->index, "pathlimit ttl", argv[0]);
+}
+
+DEFUN (no_set_pathlimit_ttl,
+ no_set_pathlimit_ttl_cmd,
+ "no set pathlimit ttl",
+ NO_STR
+ SET_STR
+ "BGP AS-Pathlimit attribute\n"
+ "Set AS-Path Hop-count TTL\n")
+{
+ if (argc == 0)
+ return bgp_route_set_delete (vty, vty->index, "pathlimit ttl", NULL);
+
+ return bgp_route_set_delete (vty, vty->index, "pathlimit ttl", argv[0]);
+}
+
+ALIAS (no_set_pathlimit_ttl,
+ no_set_pathlimit_ttl_val_cmd,
+ "no set pathlimit ttl <1-255>",
+ NO_STR
+ MATCH_STR
+ "BGP AS-Pathlimit attribute\n"
+ "Set AS-Path Hop-count TTL\n")
+
+DEFUN (match_pathlimit_as,
+ match_pathlimit_as_cmd,
+ "match pathlimit as <1-65535>",
+ MATCH_STR
+ "BGP AS-Pathlimit attribute\n"
+ "Match Pathlimit AS number\n")
+{
+ return bgp_route_match_add (vty, vty->index, "pathlimit as", argv[0]);
+}
+
+DEFUN (no_match_pathlimit_as,
+ no_match_pathlimit_as_cmd,
+ "no match pathlimit as",
+ NO_STR
+ MATCH_STR
+ "BGP AS-Pathlimit attribute\n"
+ "Match Pathlimit AS number\n")
+{
+ if (argc == 0)
+ return bgp_route_match_delete (vty, vty->index, "pathlimit as", NULL);
+
+ return bgp_route_match_delete (vty, vty->index, "pathlimit as", argv[0]);
+}
+
+ALIAS (no_match_pathlimit_as,
+ no_match_pathlimit_as_val_cmd,
+ "no match pathlimit as <1-65535>",
+ NO_STR
+ MATCH_STR
+ "BGP AS-Pathlimit attribute\n"
+ "Match Pathlimit ASN\n")
+
/* Initialization of route map. */
void
@@ -3671,7 +3827,7 @@ bgp_route_map_init (void)
route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);
route_map_install_set (&route_set_ipv6_nexthop_global_cmd);
route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
-
+
install_element (RMAP_NODE, &match_ipv6_address_cmd);
install_element (RMAP_NODE, &no_match_ipv6_address_cmd);
install_element (RMAP_NODE, &match_ipv6_next_hop_cmd);
@@ -3685,4 +3841,15 @@ bgp_route_map_init (void)
install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);
#endif /* HAVE_IPV6 */
+
+ /* AS-Pathlimit */
+ route_map_install_match (&route_match_pathlimit_as_cmd);
+ route_map_install_set (&route_set_pathlimit_ttl_cmd);
+
+ install_element (RMAP_NODE, &set_pathlimit_ttl_cmd);
+ install_element (RMAP_NODE, &no_set_pathlimit_ttl_cmd);
+ install_element (RMAP_NODE, &no_set_pathlimit_ttl_val_cmd);
+ install_element (RMAP_NODE, &match_pathlimit_as_cmd);
+ install_element (RMAP_NODE, &no_match_pathlimit_as_cmd);
+ install_element (RMAP_NODE, &no_match_pathlimit_as_val_cmd);
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 8b180a43..3fba6042 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -591,6 +591,7 @@ struct bgp_nlri
#define BGP_ATTR_MP_REACH_NLRI 14
#define BGP_ATTR_MP_UNREACH_NLRI 15
#define BGP_ATTR_EXT_COMMUNITIES 16
+#define BGP_ATTR_AS_PATHLIMIT 21
/* BGP update origin. */
#define BGP_ORIGIN_IGP 0
diff --git a/doc/ChangeLog b/doc/ChangeLog
index b8c81e74..5fcb195b 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2007-07-31 Paul Jakma <paul.jakma@sun.com>
+
+ * bgpd.texi: Document 'network ... pathlimit <ttl>'
+
2007-05-01 David L Stevens <dlstevens@us.ibm.com>
* main.texi: added route-map, prefix-list, ip protocol
diff --git a/doc/bgpd.texi b/doc/bgpd.texi
index d82f6c37..bdfd6e4c 100644
--- a/doc/bgpd.texi
+++ b/doc/bgpd.texi
@@ -145,10 +145,33 @@ router bgp 1
@end example
This configuration example says that network 10.0.0.0/8 will be
announced to all neighbors. Some vendors' routers don't advertise
-routes if they aren't present in their IGP routing tables; @code{bgp}
+routes if they aren't present in their IGP routing tables; @code{bgpd}
doesn't care about IGP routes when announcing its routes.
@end deffn
+@deffn {BGP} {network @var{A.B.C.D/M} pathlimit <0-255>} {}
+This command configures a route to be originated into BGP, just as with the
+previous command, but additionally sets an AS-Pathlimit TTL to be advertised
+on the route. See draft-ietf-idr-as-pathlimit.
+
+Specifying a TTL of 0 can be used to remove pathlimit from a previously
+configured network statement.
+
+Note that when advertising prefixes with AS-Pathlimit set, all less-specific
+prefixes advertised SHOULD also have the Atomic-Aggregate attribute set.
+Failure to do so increases the risks of accidental routing loops occuring.
+
+This implementation will try to automatically set Atomic-Aggregate as
+appropriate on any less-specific prefixes originated by the same speaker,
+however it will not (and often can not) do so where @b{other} speakers in
+the AS are originating more specifics.
+
+Hence the system administrator must take care to ensure that all
+less-specific prefixes originated carry atomic-aggregate as appropriate, by
+manually configuring speakers originating less-specifics to set
+Atomic-Aggregate on those advertisements!
+@end deffn
+
@deffn {BGP} {no network @var{A.B.C.D/M}} {}
@end deffn
diff --git a/doc/routemap.texi b/doc/routemap.texi
index db3e72d2..9ac001c4 100644
--- a/doc/routemap.texi
+++ b/doc/routemap.texi
@@ -155,6 +155,10 @@ Matches the specified @var{metric}.
Matches the specified @var{community_list}
@end deffn
+@deffn {Route-map Command} {match pathlimit as @var{ASN}} {}
+Matches the specified AS-Pathlimit @var{ASN}.
+@end deffn
+
@node Route Map Set Command
@section Route Map Set Command
@@ -190,6 +194,16 @@ Set the BGP-4+ global IPv6 nexthop address.
Set the BGP-4+ link local IPv6 nexthop address.
@end deffn
+@deffn {Route-map Command} {set pathlimit ttl @var{ttl}} {}
+Sets the specified AS-Pathlimit @var{ttl} on the route. This will also cause
+the AS to be set to the local AS.
+
+Note that the AS-Pathlimit RFC specifies that speakers advertising this
+attribute should set Atomic-aggregate on all less specific routes. Setting
+AS-Pathlimit by route-map does not do this, the user must do so themselves,
+as they wish.
+@end deffn
+
@node Route Map Call Command
@section Route Map Call Command