<tag>default bgp_med <m/number/</tag> Value of the Multiple Exit
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
to be used during route selection when the Local Preference attribute
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.
- <tag>int <cf/bgp_med/ [IO]</tag> The Multiple Exit Discriminator of the route
- is an optional attribute which is often used within the local AS to
- reflect interior distances to various boundary routers. See the route selection
- rules above for exact semantics.
+ <tag>int <cf/bgp_med/ [O]</tag> The Multiple Exit Discriminator of the route
+ is an optional attribute which is used on on external (inter-AS) links to
+ convey to an adjacent AS the optimal entry point into the local AS.
+ 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/
if the route has originated in an interior routing protocol or
bgp_check_as_path, NULL },
{ "next_hop", 4, BAF_TRANSITIVE, EAF_TYPE_IP_ADDRESS, 1, /* BA_NEXT_HOP */
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 },
{ "local_pref", 4, BAF_TRANSITIVE, EAF_TYPE_INT, 0, /* BA_LOCAL_PREF */
NULL, NULL },
eattr *a;
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));
if (a && (p->is_internal || (!p->is_internal && e->attrs->iface == p->neigh->iface)))
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
bgp_rte_better(rte *new, rte *old)
{
return 0;
/* 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));
- n = x ? x->u.data : new_bgp->cf->default_med;
- o = y ? y->u.data : old_bgp->cf->default_med;
- if (n < o)
- return 1;
- if (n > o)
- return 0;
+
+ if (bgp_get_neighbor(new) == bgp_get_neighbor(old))
+ {
+ 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));
+ n = x ? x->u.data : new_bgp->cf->default_med;
+ o = y ? y->u.data : old_bgp->cf->default_med;
+ if (n < o)
+ return 1;
+ if (n > o)
+ return 0;
+ }
/* RFC 4271 9.1.2.2. d) Prefer external peers */
if (new_bgp->is_internal > old_bgp->is_internal)