]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Implements 'allow local as' option.
authorOndrej Zajicek <santiago@crfreenet.org>
Mon, 21 Oct 2013 12:58:32 +0000 (14:58 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Mon, 21 Oct 2013 12:59:35 +0000 (14:59 +0200)
Similar to allowas-in option on other routers.

doc/bird.sgml
filter/filter.c
nest/a-path.c
nest/attrs.h
proto/bgp/attrs.c
proto/bgp/bgp.h
proto/bgp/config.Y

index 2b9ffa027b4d3f5169e5b5558c9576d321be5c32..638900310574c79f0865a51746089fed9649423f 100644 (file)
@@ -1486,6 +1486,16 @@ for each neighbor using the following configuration parameters:
        This option requires that the connected routing table is
        <ref id="dsc-sorted" name="sorted">. Default: off.
 
+       <tag>allow local as [<m/number/]</tag> 
+       BGP prevents routing loops by rejecting received routes with
+       the local AS number in the AS path. This option allows to
+       loose or disable the check. Optional <cf/number/ argument can
+       be used to specify the maximum number of local ASNs in the AS
+       path that is allowed for received routes. When the option is
+       used without the argument, the check is completely disabled
+       and you should ensure loop-free behavior by some other means.
+       Default: 0 (no local AS number allowed).
+
        <tag>enable route refresh <m/switch/</tag> When BGP speaker
        changes its import filter, it has to re-examine all routes
        received from its neighbor against the new filter. As these
index b01933f73dd37c88d57f1e4310d2294c39920201..a28de5df590085b4342c57e210be311162939b94 100644 (file)
@@ -392,7 +392,7 @@ val_in_range(struct f_val v1, struct f_val v2)
     return as_path_match(v1.val.ad, v2.val.path_mask);
 
   if ((v1.type == T_INT) && (v2.type == T_PATH))
-    return as_path_is_member(v2.val.ad, v1.val.i);
+    return as_path_contains(v2.val.ad, v1.val.i, 1);
 
   if (((v1.type == T_PAIR) || (v1.type == T_QUAD)) && (v2.type == T_CLIST))
     return int_set_contains(v2.val.ad, v1.val.i);
index b181298178896c4bfb889ca676c5fe3bad7008a8..dc36e6538951f1c3ca3401290b40e6663c4449ea 100644 (file)
@@ -244,10 +244,11 @@ as_path_get_first(struct adata *path, u32 *last_as)
 }
 
 int
-as_path_is_member(struct adata *path, u32 as)
+as_path_contains(struct adata *path, u32 as, int min)
 {
   u8 *p = path->data;
   u8 *q = p+path->length;
+  int num = 0;
   int i, n;
 
   while (p<q)
@@ -257,7 +258,8 @@ as_path_is_member(struct adata *path, u32 as)
       for(i=0; i<n; i++)
        {
          if (get_as(p) == as)
-           return 1;
+           if (++num == min)
+             return 1;
          p += BS;
        }
     }
index a0dae221953d9d8cd8f8eba08d7d36485c30eb3e..b6e067cb8c6fc144d2b69d4f1a936d6d02626e4f 100644 (file)
@@ -35,7 +35,7 @@ int as_path_getlen(struct adata *path);
 int as_path_getlen_int(struct adata *path, int bs);
 int as_path_get_first(struct adata *path, u32 *orig_as);
 int as_path_get_last(struct adata *path, u32 *last_as);
-int as_path_is_member(struct adata *path, u32 as);
+int as_path_contains(struct adata *path, u32 as, int min);
 int as_path_match_set(struct adata *path, struct f_tree *set);
 struct adata *as_path_filter(struct linpool *pool, struct adata *path, struct f_tree *set, u32 key, int pos);
 
index c27a49880fe0840ca69267d8b8491da7893a4c1a..8e25c4d2413ee943d18250b4c1be391725f81ee0 100644 (file)
@@ -950,8 +950,9 @@ bgp_create_attrs(struct bgp_proto *p, rte *e, ea_list **attrs, struct linpool *p
 static inline int
 bgp_as_path_loopy(struct bgp_proto *p, rta *a)
 {
+  int num = p->cf->allow_local_as + 1;
   eattr *e = ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
-  return (e && as_path_is_member(e->u.ptr, p->local_as));
+  return (e && (num > 0) && as_path_contains(e->u.ptr, p->local_as, num));
 }
 
 static inline int
index 77a3671504acd502ec94b7b40ba1bfb9aec2506a..bcbdf2cca3f81f4b303656620e6dd6664560dfdf 100644 (file)
@@ -44,6 +44,7 @@ struct bgp_config {
   int passive;                         /* Do not initiate outgoing connection */
   int interpret_communities;           /* Hardwired handling of well-known communities */
   int secondary;                       /* Accept also non-best routes (i.e. RA_ACCEPTED) */
+  int allow_local_as;                  /* Allow that number of local ASNs in incoming AS_PATHs */
   unsigned connect_retry_time;
   unsigned hold_time, initial_hold_time;
   unsigned keepalive_time;
index d5e5aacadc38a94a265b95306ec35fd103b2051a..f4b2c5fe67fb61b5bee994ecd44534e7349aa308 100644 (file)
@@ -26,7 +26,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
        PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH,
        INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
        TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
-       SECONDARY)
+       SECONDARY, ALLOW)
 
 CF_GRAMMAR
 
@@ -108,6 +108,8 @@ bgp_proto:
  | bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; }
  | bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; }
  | bgp_proto SECONDARY bool ';' { BGP_CFG->secondary = $3; }
+ | bgp_proto ALLOW LOCAL AS ';' { BGP_CFG->allow_local_as = -1; }
+ | bgp_proto ALLOW LOCAL AS expr ';' { BGP_CFG->allow_local_as = $5; }
  | bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; }
  | bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; }
  ;