diff options
-rw-r--r-- | doc/bird.sgml | 10 | ||||
-rw-r--r-- | filter/filter.c | 2 | ||||
-rw-r--r-- | nest/a-path.c | 6 | ||||
-rw-r--r-- | nest/attrs.h | 2 | ||||
-rw-r--r-- | proto/bgp/attrs.c | 3 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 1 | ||||
-rw-r--r-- | proto/bgp/config.Y | 4 |
7 files changed, 22 insertions, 6 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index 2b9ffa02..63890031 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -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 diff --git a/filter/filter.c b/filter/filter.c index b01933f7..a28de5df 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -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); diff --git a/nest/a-path.c b/nest/a-path.c index b1812981..dc36e653 100644 --- a/nest/a-path.c +++ b/nest/a-path.c @@ -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; } } diff --git a/nest/attrs.h b/nest/attrs.h index a0dae221..b6e067cb 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -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); diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index c27a4988..8e25c4d2 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -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 diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 77a36715..bcbdf2cc 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -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; diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index d5e5aaca..f4b2c5fe 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -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; } ; |