Better handling of well-known communities.
Process well-known communities before the export filter (old behavior is to process these attributes after, which does not allow to send route with such community) and just for routes received from other BGP protocols. Also fixes a bug in next_hop check.
This commit is contained in:
parent
a306208582
commit
6cb8f742f1
4 changed files with 55 additions and 42 deletions
|
@ -996,6 +996,17 @@ for each neighbor using the following configuration parameters:
|
||||||
capability and accepts such requests. Even when disabled, BIRD
|
capability and accepts such requests. Even when disabled, BIRD
|
||||||
can send route refresh requests. Default: on.
|
can send route refresh requests. Default: on.
|
||||||
|
|
||||||
|
<tag>ignore communities <m/switch/</tag> RFC 1997 demands that
|
||||||
|
BGP speaker should process well-known communities like
|
||||||
|
no-export (65535, 65281) or no-advertise (65535, 65282). For
|
||||||
|
example, received route carrying a no-adverise community
|
||||||
|
should not be advertised to any of its neighbors. BIRD has
|
||||||
|
such behavior hardwired (it is evaluated when a route is
|
||||||
|
exported to the protocol just before the export filter). This
|
||||||
|
option allows to disable such hardwired processing of
|
||||||
|
well-known communities (in that case, similar behavior can be
|
||||||
|
implemented in the export filter). Default: off.
|
||||||
|
|
||||||
<tag>enable as4 <m/switch/</tag> BGP protocol was designed to use 2B AS numbers
|
<tag>enable as4 <m/switch/</tag> BGP protocol was designed to use 2B AS numbers
|
||||||
and was extended later to allow 4B AS number. BIRD supports 4B AS extension,
|
and was extended later to allow 4B AS number. BIRD supports 4B AS extension,
|
||||||
but by disabling this option it can be persuaded not to advertise it and
|
but by disabling this option it can be persuaded not to advertise it and
|
||||||
|
|
|
@ -664,44 +664,8 @@ bgp_new_bucket(struct bgp_proto *p, ea_list *new, unsigned hash)
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
bgp_export_check(struct bgp_proto *p, ea_list *new)
|
|
||||||
{
|
|
||||||
eattr *a;
|
|
||||||
struct adata *d;
|
|
||||||
|
|
||||||
/* Check if next hop is valid */
|
|
||||||
a = ea_find(new, EA_CODE(EAP_BGP, BA_NEXT_HOP));
|
|
||||||
if (!a || ipa_equal(p->next_hop, *(ip_addr *)a->u.ptr))
|
|
||||||
{
|
|
||||||
DBG("\tInvalid NEXT_HOP\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we aren't forbidden to export the route by communities */
|
|
||||||
a = ea_find(new, EA_CODE(EAP_BGP, BA_COMMUNITY));
|
|
||||||
if (a)
|
|
||||||
{
|
|
||||||
d = a->u.ptr;
|
|
||||||
if (int_set_contains(d, BGP_COMM_NO_ADVERTISE))
|
|
||||||
{
|
|
||||||
DBG("\tNO_ADVERTISE\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!p->is_internal &&
|
|
||||||
(int_set_contains(d, BGP_COMM_NO_EXPORT) ||
|
|
||||||
int_set_contains(d, BGP_COMM_NO_EXPORT_SUBCONFED)))
|
|
||||||
{
|
|
||||||
DBG("\tNO_EXPORT\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct bgp_bucket *
|
static struct bgp_bucket *
|
||||||
bgp_get_bucket(struct bgp_proto *p, ea_list *attrs, int originate)
|
bgp_get_bucket(struct bgp_proto *p, net *n, ea_list *attrs, int originate)
|
||||||
{
|
{
|
||||||
ea_list *new;
|
ea_list *new;
|
||||||
unsigned i, cnt, hash, code;
|
unsigned i, cnt, hash, code;
|
||||||
|
@ -778,12 +742,17 @@ bgp_get_bucket(struct bgp_proto *p, ea_list *attrs, int originate)
|
||||||
for(i=0; i<ARRAY_SIZE(bgp_mandatory_attrs); i++)
|
for(i=0; i<ARRAY_SIZE(bgp_mandatory_attrs); i++)
|
||||||
if (!(seen & (1 << bgp_mandatory_attrs[i])))
|
if (!(seen & (1 << bgp_mandatory_attrs[i])))
|
||||||
{
|
{
|
||||||
log(L_ERR "%s: Mandatory attribute %s missing", p->p.name, bgp_attr_table[bgp_mandatory_attrs[i]].name);
|
log(L_ERR "%s: Mandatory attribute %s missing in route %I/%d", p->p.name, bgp_attr_table[bgp_mandatory_attrs[i]].name, n->n.prefix, n->n.pxlen);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bgp_export_check(p, new))
|
/* Check if next hop is valid */
|
||||||
|
a = ea_find(new, EA_CODE(EAP_BGP, BA_NEXT_HOP));
|
||||||
|
if (!a || ipa_equal(p->next_hop, *(ip_addr *)a->u.ptr->data))
|
||||||
|
{
|
||||||
|
log(L_ERR "%s: Invalid NEXT_HOP attribute in route %I/%d", p->p.name, n->n.prefix, n->n.pxlen);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create new bucket */
|
/* Create new bucket */
|
||||||
DBG("Creating bucket.\n");
|
DBG("Creating bucket.\n");
|
||||||
|
@ -813,7 +782,7 @@ bgp_rt_notify(struct proto *P, net *n, rte *new, rte *old UNUSED, ea_list *attrs
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
buck = bgp_get_bucket(p, attrs, new->attrs->source != RTS_BGP);
|
buck = bgp_get_bucket(p, n, attrs, new->attrs->source != RTS_BGP);
|
||||||
if (!buck) /* Inconsistent attribute list */
|
if (!buck) /* Inconsistent attribute list */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -963,6 +932,34 @@ bgp_update_attrs(struct bgp_proto *p, rte *e, ea_list **attrs, struct linpool *p
|
||||||
return 0; /* Leave decision to the filters */
|
return 0; /* Leave decision to the filters */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bgp_community_filter(struct bgp_proto *p, rte *e)
|
||||||
|
{
|
||||||
|
eattr *a;
|
||||||
|
struct adata *d;
|
||||||
|
|
||||||
|
/* Check if we aren't forbidden to export the route by communities */
|
||||||
|
a = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_COMMUNITY));
|
||||||
|
if (a)
|
||||||
|
{
|
||||||
|
d = a->u.ptr;
|
||||||
|
if (int_set_contains(d, BGP_COMM_NO_ADVERTISE))
|
||||||
|
{
|
||||||
|
DBG("\tNO_ADVERTISE\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!p->is_internal &&
|
||||||
|
(int_set_contains(d, BGP_COMM_NO_EXPORT) ||
|
||||||
|
int_set_contains(d, BGP_COMM_NO_EXPORT_SUBCONFED)))
|
||||||
|
{
|
||||||
|
DBG("\tNO_EXPORT\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bgp_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool)
|
bgp_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool)
|
||||||
{
|
{
|
||||||
|
@ -979,6 +976,9 @@ bgp_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *
|
||||||
if (bgp_cluster_list_loopy(p, e->attrs))
|
if (bgp_cluster_list_loopy(p, e->attrs))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (!p->cf->ignore_communities && bgp_community_filter(p, e))
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (p->local_as == new_bgp->local_as && p->is_internal && new_bgp->is_internal)
|
if (p->local_as == new_bgp->local_as && p->is_internal && new_bgp->is_internal)
|
||||||
{
|
{
|
||||||
/* Redistribution of internal routes with IBGP */
|
/* Redistribution of internal routes with IBGP */
|
||||||
|
|
|
@ -37,6 +37,7 @@ struct bgp_config {
|
||||||
int advertise_ipv4; /* Whether we should add IPv4 capability advertisement to OPEN message */
|
int advertise_ipv4; /* Whether we should add IPv4 capability advertisement to OPEN message */
|
||||||
u32 route_limit; /* Number of routes that may be imported, 0 means disable limit */
|
u32 route_limit; /* Number of routes that may be imported, 0 means disable limit */
|
||||||
int passive; /* Do not initiate outgoing connection */
|
int passive; /* Do not initiate outgoing connection */
|
||||||
|
int ignore_communities; /* Skip hardwired handling of well-known communities */
|
||||||
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;
|
||||||
|
|
|
@ -23,7 +23,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
|
||||||
BGP_ATOMIC_AGGR, BGP_AGGREGATOR, BGP_COMMUNITY, SOURCE, ADDRESS,
|
BGP_ATOMIC_AGGR, BGP_AGGREGATOR, BGP_COMMUNITY, SOURCE, ADDRESS,
|
||||||
PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4, ADVERTISE, IPV4,
|
PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4, ADVERTISE, IPV4,
|
||||||
CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER, MISSING, LLADDR,
|
CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER, MISSING, LLADDR,
|
||||||
DROP, IGNORE, ROUTE, REFRESH)
|
DROP, IGNORE, ROUTE, REFRESH, COMMUNITIES)
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ bgp_proto:
|
||||||
| bgp_proto PASSWORD TEXT ';' { BGP_CFG->password = $3; }
|
| bgp_proto PASSWORD TEXT ';' { BGP_CFG->password = $3; }
|
||||||
| bgp_proto ROUTE LIMIT expr ';' { BGP_CFG->route_limit = $4; }
|
| bgp_proto ROUTE LIMIT expr ';' { BGP_CFG->route_limit = $4; }
|
||||||
| bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; }
|
| bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; }
|
||||||
|
| bgp_proto IGNORE COMMUNITIES bool ';' { BGP_CFG->ignore_communities = $4; }
|
||||||
;
|
;
|
||||||
|
|
||||||
CF_ADDTO(dynamic_attr, BGP_PATH
|
CF_ADDTO(dynamic_attr, BGP_PATH
|
||||||
|
|
Loading…
Reference in a new issue