summaryrefslogtreecommitdiff
path: root/proto/bgp
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2011-04-22 16:13:27 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2011-04-22 16:13:27 +0200
commit73272f04af40484b72451f541a986da996b0da58 (patch)
treedf2b6b6ee2696f034dcdb5404cde442730d60cc1 /proto/bgp
parent71ca77169d5d3e67459e46841b8bdb95accd8c2a (diff)
Adds BGP option related to MED handling.
Adds option 'med metric' allows to compare MEDs between routes received from different neighbors.
Diffstat (limited to 'proto/bgp')
-rw-r--r--proto/bgp/attrs.c12
-rw-r--r--proto/bgp/bgp.h1
-rw-r--r--proto/bgp/config.Y3
3 files changed, 14 insertions, 2 deletions
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index e1a3671a..95eee9aa 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -1118,7 +1118,17 @@ bgp_rte_better(rte *new, rte *old)
return 0;
/* RFC 4271 9.1.2.2. c) Compare MED's */
- if (bgp_get_neighbor(new) == bgp_get_neighbor(old))
+ /* This is noncompliant. Proper RFC 4271 path selection cannot be
+ * interpreted as finding the best path in some ordering.
+ * Therefore, it cannot be implemented in BIRD without some ugly
+ * hacks. This is just an approximation, which in specific
+ * situations may lead to persistent routing loops, because it is
+ * nondeterministic - it depends on the order in which routes
+ * appeared. But it is also the same behavior as used by default in
+ * Cisco routers, so it is probably not a big issue.
+ */
+ if (new_bgp->cf->med_metric || old_bgp->cf->med_metric ||
+ (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));
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index b06f20a0..097faa6a 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -25,6 +25,7 @@ struct bgp_config {
int missing_lladdr; /* What we will do when we don' know link-local addr, see MLL_* */
int gw_mode; /* How we compute route gateway from next_hop attr, see GW_* */
int compare_path_lengths; /* Use path lengths when selecting best route */
+ int med_metric; /* Compare MULTI_EXIT_DISC even between routes from differen ASes */
int igp_metric; /* Use IGP metrics when selecting best route */
int prefer_older; /* Prefer older routes according to RFC 5004 */
u32 default_local_pref; /* Default value for LOCAL_PREF attribute */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index e932a7f6..93f832aa 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -25,7 +25,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
ADVERTISE, IPV4, CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER,
MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH, INTERPRET,
COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP, TABLE,
- GATEWAY, DIRECT, RECURSIVE)
+ GATEWAY, DIRECT, RECURSIVE, MED)
CF_GRAMMAR
@@ -79,6 +79,7 @@ bgp_proto:
| bgp_proto GATEWAY DIRECT ';' { BGP_CFG->gw_mode = GW_DIRECT; }
| bgp_proto GATEWAY RECURSIVE ';' { BGP_CFG->gw_mode = GW_RECURSIVE; }
| bgp_proto PATH METRIC bool ';' { BGP_CFG->compare_path_lengths = $4; }
+ | bgp_proto MED METRIC bool ';' { BGP_CFG->med_metric = $4; }
| bgp_proto IGP METRIC bool ';' { BGP_CFG->igp_metric = $4; }
| bgp_proto PREFER OLDER bool ';' { BGP_CFG->prefer_older = $4; }
| bgp_proto DEFAULT BGP_MED expr ';' { BGP_CFG->default_med = $4; }