summaryrefslogtreecommitdiffstats
path: root/nhrpd/nhrp_cache.c
diff options
context:
space:
mode:
authorGhasem Naddaf <ghasem.naddaf@gmail.com>2020-02-27 20:37:37 +0100
committerGhasem Naddaf <ghasem.naddaf@gmail.com>2020-02-27 20:37:37 +0100
commit912c556b3a0354f37328f52108777e434307e339 (patch)
tree8f57741c6804ff7b98d2433c3fa43496ec729e84 /nhrpd/nhrp_cache.c
parentnhrpd: add holdtime and MTU to CIE (diff)
downloadfrr-912c556b3a0354f37328f52108777e434307e339.tar.xz
frr-912c556b3a0354f37328f52108777e434307e339.zip
nhrpd: route update support for natoa nbma
nhrp_cache_update_route, nhrp_cache_authorize_binding: Fix route update for NAT scenario. When remote_nbma_natoa is already set in the cache entry, binding should be updated to this value and not vc remote nbma, which would be different from the NATted address. nhrp_shortcut_recv_resolution_rep: Simplify the logic for finding the natoa nbma. Also, install shortcut entries as DYNAMIC type, as suggested in Section 6.2.2 of RFC2332. nhrp_shortcut_cache_notify: announce the installed route with the correct interface from cache. Signed-off-by: Ghasem Naddaf <gshirazi@infoblox.com>
Diffstat (limited to 'nhrpd/nhrp_cache.c')
-rw-r--r--nhrpd/nhrp_cache.c90
1 files changed, 86 insertions, 4 deletions
diff --git a/nhrpd/nhrp_cache.c b/nhrpd/nhrp_cache.c
index cc18b36f6..ad478bab9 100644
--- a/nhrpd/nhrp_cache.c
+++ b/nhrpd/nhrp_cache.c
@@ -119,12 +119,47 @@ static void nhrp_cache_update_route(struct nhrp_cache *c)
{
struct prefix pfx;
struct nhrp_peer *p = c->cur.peer;
+ char buf[3][SU_ADDRSTRLEN];
+ struct nhrp_interface *nifp;
sockunion2hostprefix(&c->remote_addr, &pfx);
if (p && nhrp_peer_check(p, 1)) {
- netlink_update_binding(p->ifp, &c->remote_addr,
- &p->vc->remote.nbma);
+ if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) {
+ /* remote_nbma_natoa is already set. Therefore, binding
+ * should be updated to this value and not vc's remote
+ * nbma.
+ */
+ debugf(NHRP_DEBUG_COMMON,
+ "cache (peer check ok, remote_nbma_natoa is set): "
+ "Update binding for %s dev %s from (deleted) "
+ "peer.vc.nbma %s to %s",
+ sockunion2str(&c->remote_addr, buf[0],
+ sizeof(buf[0])),
+ p->ifp->name,
+ sockunion2str(&p->vc->remote.nbma, buf[1],
+ sizeof(buf[1])),
+ sockunion2str(&c->cur.remote_nbma_natoa, buf[2],
+ sizeof(buf[2])));
+
+ netlink_update_binding(p->ifp, &c->remote_addr,
+ &c->cur.remote_nbma_natoa);
+ } else {
+ // update binding to peer->vc->remote->nbma
+ debugf(NHRP_DEBUG_COMMON,
+ "cache (peer check ok, remote_nbma_natoa unspec): "
+ "Update binding for %s dev %s from (deleted) "
+ "to peer.vc.nbma %s",
+ sockunion2str(&c->remote_addr, buf[0],
+ sizeof(buf[0])),
+ p->ifp->name,
+ sockunion2str(&p->vc->remote.nbma, buf[1],
+ sizeof(buf[1])));
+
+ netlink_update_binding(p->ifp, &c->remote_addr,
+ &p->vc->remote.nbma);
+ }
+
nhrp_route_announce(1, c->cur.type, &pfx, c->ifp, NULL,
c->cur.mtu);
if (c->cur.type >= NHRP_CACHE_DYNAMIC) {
@@ -139,6 +174,18 @@ static void nhrp_cache_update_route(struct nhrp_cache *c)
c->route_installed = 1;
}
} else {
+ // debug the reason for peer check fail
+ if (p) {
+ nifp = p->ifp->info;
+ debugf(NHRP_DEBUG_COMMON,
+ "cache (peer check failed: "
+ "online?%d requested?%d ipsec?%d)",
+ p->online, p->requested,
+ nifp->ipsec_profile ? 1 : 0);
+ } else
+ debugf(NHRP_DEBUG_COMMON,
+ "cache (peer check failed: no p)");
+
if (c->nhrp_route_installed) {
nhrp_route_update_nhrp(&pfx, NULL);
c->nhrp_route_installed = 0;
@@ -207,10 +254,10 @@ static void nhrp_cache_update_timers(struct nhrp_cache *c)
static void nhrp_cache_authorize_binding(struct nhrp_reqid *r, void *arg)
{
struct nhrp_cache *c = container_of(r, struct nhrp_cache, eventid);
- char buf[SU_ADDRSTRLEN];
+ char buf[3][SU_ADDRSTRLEN];
debugf(NHRP_DEBUG_COMMON, "cache: %s %s: %s", c->ifp->name,
- sockunion2str(&c->remote_addr, buf, sizeof buf),
+ sockunion2str(&c->remote_addr, buf[0], sizeof buf[0]),
(const char *)arg);
nhrp_reqid_free(&nhrp_event_reqid, r);
@@ -230,6 +277,26 @@ static void nhrp_cache_authorize_binding(struct nhrp_reqid *r, void *arg)
if (c->cur.peer)
nhrp_peer_notify_add(c->cur.peer, &c->peer_notifier,
nhrp_cache_peer_notifier);
+
+ if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) {
+ debugf(NHRP_DEBUG_COMMON,
+ "cache: update binding for %s dev %s from "
+ "(deleted) peer.vc.nbma %s to %s",
+ sockunion2str(&c->remote_addr, buf[0],
+ sizeof buf[0]),
+ c->ifp->name,
+ (c->cur.peer ? sockunion2str(
+ &c->cur.peer->vc->remote.nbma, buf[1],
+ sizeof buf[1])
+ : "(no peer)"),
+ sockunion2str(&c->cur.remote_nbma_natoa, buf[2],
+ sizeof buf[2]));
+
+ netlink_update_binding(c->cur.peer->ifp,
+ &c->remote_addr,
+ &c->cur.remote_nbma_natoa);
+ }
+
nhrp_cache_update_route(c);
notifier_call(&c->notifier_list, NOTIFY_CACHE_BINDING_CHANGE);
} else {
@@ -273,6 +340,7 @@ int nhrp_cache_update_binding(struct nhrp_cache *c, enum nhrp_cache_type type,
int holding_time, struct nhrp_peer *p,
uint32_t mtu, union sockunion *nbma_oa)
{
+ char buf[2][SU_ADDRSTRLEN];
if (c->cur.type > type || c->new.type > type) {
nhrp_peer_unref(p);
return 0;
@@ -293,8 +361,16 @@ int nhrp_cache_update_binding(struct nhrp_cache *c, enum nhrp_cache_type type,
break;
}
+ sockunion2str(&c->cur.remote_nbma_natoa, buf[0], sizeof(buf[0]));
+ if (nbma_oa)
+ sockunion2str(nbma_oa, buf[1], sizeof(buf[1]));
+
nhrp_cache_reset_new(c);
if (c->cur.type == type && c->cur.peer == p && c->cur.mtu == mtu) {
+ debugf(NHRP_DEBUG_COMMON,
+ "cache: same type %u, updating "
+ "expiry and changing nbma addr from %s to %s",
+ type, buf[0], nbma_oa ? buf[1] : "(NULL)");
if (holding_time > 0)
c->cur.expires = monotime(NULL) + holding_time;
if (nbma_oa)
@@ -304,6 +380,12 @@ int nhrp_cache_update_binding(struct nhrp_cache *c, enum nhrp_cache_type type,
sizeof c->cur.remote_nbma_natoa);
nhrp_peer_unref(p);
} else {
+ debugf(NHRP_DEBUG_COMMON,
+ "cache: new type %u/%u, or peer %s, "
+ "or mtu %u/%u, nbma %s --> %s (map %d)",
+ c->cur.type, type, (c->cur.peer == p) ? "same" : "diff",
+ c->cur.mtu, mtu, buf[0], nbma_oa ? buf[1] : "(NULL)",
+ c->map);
c->new.type = type;
c->new.peer = p;
c->new.mtu = mtu;