From 48bc232f08141d26691237c3d79db587ce16932b Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Tue, 16 Apr 2013 17:27:34 +0200 Subject: [PATCH] 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. --- doc/bird.sgml | 5 +++++ proto/bgp/attrs.c | 8 ++++++-- proto/bgp/bgp.h | 1 + proto/bgp/config.Y | 3 ++- 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. + next hop keep 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. + missing lladdr self|drop|ignoreNext 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; }