summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2013-04-16 17:27:34 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2013-04-16 17:27:34 +0200
commit48bc232f08141d26691237c3d79db587ce16932b (patch)
treea1b58dced547671340b294f47cbe1ee6f385ca0a
parent9ff5257357d9975654279db17bbc8525583ba1cc (diff)
Implements 'next hop keep' option for BGP.
This option allows to keep the received next hop even in cases when the route is sent to an interface with a different subnet.
-rw-r--r--doc/bird.sgml5
-rw-r--r--proto/bgp/attrs.c8
-rw-r--r--proto/bgp/bgp.h1
-rw-r--r--proto/bgp/config.Y3
4 files changed, 14 insertions, 3 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml
index 8e5641e0..300a71f3 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -1329,6 +1329,11 @@ for each neighbor using the following configuration parameters:
circumvent misconfigurations of other routers. Default:
disabled.
+ <tag>next hop keep</tag> Forward the received Next Hop
+ attribute even in situations where the local address should be
+ used instead, like when the route is sent to an interface with
+ a different subnet. Default: disabled.
+
<tag>missing lladdr self|drop|ignore</tag>Next Hop attribute
in BGP-IPv6 sometimes contains just the global IPv6 address,
but sometimes it has to contain both global and link-local
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index 98b2f2c2..c27a4988 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -935,7 +935,8 @@ bgp_create_attrs(struct bgp_proto *p, rte *e, ea_list **attrs, struct linpool *p
rta->dest != RTD_ROUTER ||
ipa_equal(rta->gw, IPA_NONE) ||
ipa_has_link_scope(rta->gw) ||
- (!p->is_internal && (!p->neigh || (rta->iface != p->neigh->iface))))
+ (!p->is_internal && !p->cf->next_hop_keep &&
+ (!p->neigh || (rta->iface != p->neigh->iface))))
set_next_hop(z, p->source_addr);
else
set_next_hop(z, rta->gw);
@@ -1003,10 +1004,13 @@ bgp_update_attrs(struct bgp_proto *p, rte *e, ea_list **attrs, struct linpool *p
/* iBGP -> keep next_hop, eBGP multi-hop -> use source_addr,
* eBGP single-hop -> keep next_hop if on the same iface.
* If the next_hop is zero (i.e. link-local), keep only if on the same iface.
+ *
+ * Note that same-iface-check uses iface from route, which is based on gw.
*/
a = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
if (a && !p->cf->next_hop_self &&
- ((p->is_internal && ipa_nonzero(*((ip_addr *) a->u.ptr->data))) ||
+ (p->cf->next_hop_keep ||
+ (p->is_internal && ipa_nonzero(*((ip_addr *) a->u.ptr->data))) ||
(p->neigh && (e->attrs->iface == p->neigh->iface))))
{
/* Leave the original next hop attribute, will check later where does it point */
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index c3adf254..13c7fd80 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -24,6 +24,7 @@ struct bgp_config {
int multihop; /* Number of hops if multihop */
int ttl_security; /* Enable TTL security [RFC5082] */
int next_hop_self; /* Always set next hop to local IP address */
+ int next_hop_keep; /* Do not touch next hop attribute */
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 */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 8b80d7fd..d5e5aaca 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -76,7 +76,8 @@ bgp_proto:
| bgp_proto KEEPALIVE TIME expr ';' { BGP_CFG->keepalive_time = $4; }
| bgp_proto MULTIHOP ';' { BGP_CFG->multihop = 64; }
| bgp_proto MULTIHOP expr ';' { BGP_CFG->multihop = $3; if (($3<1) || ($3>255)) cf_error("Multihop must be in range 1-255"); }
- | bgp_proto NEXT HOP SELF ';' { BGP_CFG->next_hop_self = 1; }
+ | bgp_proto NEXT HOP SELF ';' { BGP_CFG->next_hop_self = 1; BGP_CFG->next_hop_keep = 0; }
+ | bgp_proto NEXT HOP KEEP ';' { BGP_CFG->next_hop_keep = 1; BGP_CFG->next_hop_self = 0; }
| bgp_proto MISSING LLADDR SELF ';' { BGP_CFG->missing_lladdr = MLL_SELF; }
| bgp_proto MISSING LLADDR DROP ';' { BGP_CFG->missing_lladdr = MLL_DROP; }
| bgp_proto MISSING LLADDR IGNORE ';' { BGP_CFG->missing_lladdr = MLL_IGNORE; }