Implements 'allow local as' option.
Similar to allowas-in option on other routers.
This commit is contained in:
parent
f8cc7396cf
commit
a15dab76f9
7 changed files with 22 additions and 6 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,7 +258,8 @@ 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)
|
||||||
return 1;
|
if (++num == min)
|
||||||
|
return 1;
|
||||||
p += BS;
|
p += BS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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; }
|
||||||
;
|
;
|
||||||
|
|
Loading…
Reference in a new issue