Implements 'allow local as' option.

Similar to allowas-in option on other routers.
This commit is contained in:
Ondrej Zajicek 2013-10-21 14:58:32 +02:00
parent f8cc7396cf
commit a15dab76f9
7 changed files with 22 additions and 6 deletions

View file

@ -1486,6 +1486,16 @@ for each neighbor using the following configuration parameters:
This option requires that the connected routing table is This option requires that the connected routing table is
<ref id="dsc-sorted" name="sorted">. Default: off. <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 <tag>enable route refresh <m/switch/</tag> When BGP speaker
changes its import filter, it has to re-examine all routes changes its import filter, it has to re-examine all routes
received from its neighbor against the new filter. As these received from its neighbor against the new filter. As these

View 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); return as_path_match(v1.val.ad, v2.val.path_mask);
if ((v1.type == T_INT) && (v2.type == T_PATH)) 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)) if (((v1.type == T_PAIR) || (v1.type == T_QUAD)) && (v2.type == T_CLIST))
return int_set_contains(v2.val.ad, v1.val.i); return int_set_contains(v2.val.ad, v1.val.i);

View file

@ -244,10 +244,11 @@ as_path_get_first(struct adata *path, u32 *last_as)
} }
int 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 *p = path->data;
u8 *q = p+path->length; u8 *q = p+path->length;
int num = 0;
int i, n; int i, n;
while (p<q) while (p<q)
@ -257,6 +258,7 @@ as_path_is_member(struct adata *path, u32 as)
for(i=0; i<n; i++) for(i=0; i<n; i++)
{ {
if (get_as(p) == as) if (get_as(p) == as)
if (++num == min)
return 1; return 1;
p += BS; p += BS;
} }

View 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_getlen_int(struct adata *path, int bs);
int as_path_get_first(struct adata *path, u32 *orig_as); 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_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); 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); struct adata *as_path_filter(struct linpool *pool, struct adata *path, struct f_tree *set, u32 key, int pos);

View file

@ -950,8 +950,9 @@ bgp_create_attrs(struct bgp_proto *p, rte *e, ea_list **attrs, struct linpool *p
static inline int static inline int
bgp_as_path_loopy(struct bgp_proto *p, rta *a) 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)); 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 static inline int

View file

@ -44,6 +44,7 @@ struct bgp_config {
int passive; /* Do not initiate outgoing connection */ int passive; /* Do not initiate outgoing connection */
int interpret_communities; /* Hardwired handling of well-known communities */ int interpret_communities; /* Hardwired handling of well-known communities */
int secondary; /* Accept also non-best routes (i.e. RA_ACCEPTED) */ 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 connect_retry_time;
unsigned hold_time, initial_hold_time; unsigned hold_time, initial_hold_time;
unsigned keepalive_time; unsigned keepalive_time;

View file

@ -26,7 +26,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH, PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH,
INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP, INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC, TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
SECONDARY) SECONDARY, ALLOW)
CF_GRAMMAR CF_GRAMMAR
@ -108,6 +108,8 @@ bgp_proto:
| bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; } | bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; }
| bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; } | bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; }
| bgp_proto SECONDARY bool ';' { BGP_CFG->secondary = $3; } | 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 IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; }
| bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; } | bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; }
; ;