Bugfixes in MULIT_EXIT_DISC attribute handling.
- Old MED handling was completely different from behavior specified in RFCs - for example they havn't been propagated to neighboring areas. - Update tie-breaking according to RFC 4271. - Change default value for 'default bgp_med' configuration option according to RFC 4271.
This commit is contained in:
parent
4819c3e17a
commit
b6bf284a90
5 changed files with 63 additions and 16 deletions
|
@ -784,7 +784,7 @@ for each neighbor using the following configuration parameters:
|
||||||
|
|
||||||
<tag>default bgp_med <m/number/</tag> Value of the Multiple Exit
|
<tag>default bgp_med <m/number/</tag> Value of the Multiple Exit
|
||||||
Discriminator to be used during route selection when the MED attribute
|
Discriminator to be used during route selection when the MED attribute
|
||||||
is missing. Default: infinite.
|
is missing. Default: 0.
|
||||||
|
|
||||||
<tag>default bgp_local_pref <m/number/</tag> Value of the Local Preference
|
<tag>default bgp_local_pref <m/number/</tag> Value of the Local Preference
|
||||||
to be used during route selection when the Local Preference attribute
|
to be used during route selection when the Local Preference attribute
|
||||||
|
@ -806,10 +806,16 @@ with `<tt/O/') are optional.
|
||||||
selection among multiple BGP routes (see the selection rules above). It's
|
selection among multiple BGP routes (see the selection rules above). It's
|
||||||
used as an additional metric which is propagated through the whole local AS.
|
used as an additional metric which is propagated through the whole local AS.
|
||||||
|
|
||||||
<tag>int <cf/bgp_med/ [IO]</tag> The Multiple Exit Discriminator of the route
|
<tag>int <cf/bgp_med/ [O]</tag> The Multiple Exit Discriminator of the route
|
||||||
is an optional attribute which is often used within the local AS to
|
is an optional attribute which is used on on external (inter-AS) links to
|
||||||
reflect interior distances to various boundary routers. See the route selection
|
convey to an adjacent AS the optimal entry point into the local AS.
|
||||||
rules above for exact semantics.
|
The received attribute may be also propagated over internal BGP links
|
||||||
|
(and this is default behavior). The attribute value is zeroed when a route
|
||||||
|
is exported from a routing table to a BGP instance to ensure that the attribute
|
||||||
|
received from a neighboring AS is not propagated to other neighboring ASes.
|
||||||
|
A new value might be set in the export filter of a BGP instance.
|
||||||
|
See RFC 4451<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4451.txt">
|
||||||
|
for further discussion of BGP MED attribute.
|
||||||
|
|
||||||
<tag>enum <cf/bgp_origin/</tag> Origin of the route: either <cf/ORIGIN_IGP/
|
<tag>enum <cf/bgp_origin/</tag> Origin of the route: either <cf/ORIGIN_IGP/
|
||||||
if the route has originated in an interior routing protocol or
|
if the route has originated in an interior routing protocol or
|
||||||
|
|
|
@ -243,6 +243,20 @@ as_path_get_first(struct adata *path, u32 *orig_as)
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
as_path_get_last(struct adata *path, u32 *last_as)
|
||||||
|
{
|
||||||
|
u8 *p = path->data;
|
||||||
|
|
||||||
|
if ((path->length == 0) || (p[0] != AS_PATH_SEQUENCE) || (p[1] == 0))
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*last_as = get_as(p+2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
as_path_is_member(struct adata *path, u32 as)
|
as_path_is_member(struct adata *path, u32 as)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,6 +27,7 @@ int as_path_convert_to_new(struct adata *path, byte *dst, int req_as);
|
||||||
void as_path_format(struct adata *path, byte *buf, unsigned int size);
|
void as_path_format(struct adata *path, byte *buf, unsigned int size);
|
||||||
int as_path_getlen(struct adata *path);
|
int as_path_getlen(struct adata *path);
|
||||||
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_is_member(struct adata *path, u32 as);
|
int as_path_is_member(struct adata *path, u32 as);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -146,7 +146,7 @@ static struct attr_desc bgp_attr_table[] = {
|
||||||
bgp_check_as_path, NULL },
|
bgp_check_as_path, NULL },
|
||||||
{ "next_hop", 4, BAF_TRANSITIVE, EAF_TYPE_IP_ADDRESS, 1, /* BA_NEXT_HOP */
|
{ "next_hop", 4, BAF_TRANSITIVE, EAF_TYPE_IP_ADDRESS, 1, /* BA_NEXT_HOP */
|
||||||
bgp_check_next_hop, NULL },
|
bgp_check_next_hop, NULL },
|
||||||
{ "med", 4, BAF_OPTIONAL, EAF_TYPE_INT, 0, /* BA_MULTI_EXIT_DISC */
|
{ "med", 4, BAF_OPTIONAL, EAF_TYPE_INT, 1, /* BA_MULTI_EXIT_DISC */
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
{ "local_pref", 4, BAF_TRANSITIVE, EAF_TYPE_INT, 0, /* BA_LOCAL_PREF */
|
{ "local_pref", 4, BAF_TRANSITIVE, EAF_TYPE_INT, 0, /* BA_LOCAL_PREF */
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
|
@ -829,7 +829,17 @@ bgp_update_attrs(struct bgp_proto *p, rte *e, ea_list **attrs, struct linpool *p
|
||||||
eattr *a;
|
eattr *a;
|
||||||
|
|
||||||
if (!p->is_internal)
|
if (!p->is_internal)
|
||||||
bgp_path_prepend(e, attrs, pool, p->local_as);
|
{
|
||||||
|
bgp_path_prepend(e, attrs, pool, p->local_as);
|
||||||
|
|
||||||
|
/* The MULTI_EXIT_DISC attribute received from a neighboring AS MUST NOT be
|
||||||
|
* propagated to other neighboring ASes.
|
||||||
|
* Perhaps it would be better to undefine it.
|
||||||
|
*/
|
||||||
|
a = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
|
||||||
|
if (a)
|
||||||
|
bgp_attach_attr(attrs, pool, BA_MULTI_EXIT_DISC, 0);
|
||||||
|
}
|
||||||
|
|
||||||
a = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
|
a = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
|
||||||
if (a && (p->is_internal || (!p->is_internal && e->attrs->iface == p->neigh->iface)))
|
if (a && (p->is_internal || (!p->is_internal && e->attrs->iface == p->neigh->iface)))
|
||||||
|
@ -894,6 +904,18 @@ bgp_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *
|
||||||
return bgp_create_attrs(p, e, attrs, pool);
|
return bgp_create_attrs(p, e, attrs, pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline u32
|
||||||
|
bgp_get_neighbor(rte *r)
|
||||||
|
{
|
||||||
|
eattr *e = ea_find(r->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
|
||||||
|
u32 as;
|
||||||
|
|
||||||
|
if (e && as_path_get_last(e->u.ptr, &as))
|
||||||
|
return as;
|
||||||
|
else
|
||||||
|
return ((struct bgp_proto *) r->attrs->proto)->remote_as;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bgp_rte_better(rte *new, rte *old)
|
bgp_rte_better(rte *new, rte *old)
|
||||||
{
|
{
|
||||||
|
@ -936,14 +958,18 @@ bgp_rte_better(rte *new, rte *old)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* RFC 4271 9.1.2.2. c) Compare MED's */
|
/* RFC 4271 9.1.2.2. c) Compare MED's */
|
||||||
x = ea_find(new->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
|
|
||||||
y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
|
if (bgp_get_neighbor(new) == bgp_get_neighbor(old))
|
||||||
n = x ? x->u.data : new_bgp->cf->default_med;
|
{
|
||||||
o = y ? y->u.data : old_bgp->cf->default_med;
|
x = ea_find(new->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
|
||||||
if (n < o)
|
y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
|
||||||
return 1;
|
n = x ? x->u.data : new_bgp->cf->default_med;
|
||||||
if (n > o)
|
o = y ? y->u.data : old_bgp->cf->default_med;
|
||||||
return 0;
|
if (n < o)
|
||||||
|
return 1;
|
||||||
|
if (n > o)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* RFC 4271 9.1.2.2. d) Prefer external peers */
|
/* RFC 4271 9.1.2.2. d) Prefer external peers */
|
||||||
if (new_bgp->is_internal > old_bgp->is_internal)
|
if (new_bgp->is_internal > old_bgp->is_internal)
|
||||||
|
|
|
@ -33,7 +33,7 @@ bgp_proto_start: proto_start BGP {
|
||||||
BGP_CFG->hold_time = 240;
|
BGP_CFG->hold_time = 240;
|
||||||
BGP_CFG->connect_retry_time = 120;
|
BGP_CFG->connect_retry_time = 120;
|
||||||
BGP_CFG->initial_hold_time = 240;
|
BGP_CFG->initial_hold_time = 240;
|
||||||
BGP_CFG->default_med = ~0; /* RFC 1771 doesn't specify this, draft-09 says ~0 */
|
BGP_CFG->default_med = 0;
|
||||||
BGP_CFG->compare_path_lengths = 1;
|
BGP_CFG->compare_path_lengths = 1;
|
||||||
BGP_CFG->start_delay_time = 5;
|
BGP_CFG->start_delay_time = 5;
|
||||||
BGP_CFG->error_amnesia_time = 300;
|
BGP_CFG->error_amnesia_time = 300;
|
||||||
|
|
Loading…
Reference in a new issue