diff options
author | Ghasem Naddaf <ghasem.naddaf@gmail.com> | 2020-02-27 20:37:37 +0100 |
---|---|---|
committer | Ghasem Naddaf <ghasem.naddaf@gmail.com> | 2020-02-27 20:37:37 +0100 |
commit | 912c556b3a0354f37328f52108777e434307e339 (patch) | |
tree | 8f57741c6804ff7b98d2433c3fa43496ec729e84 /nhrpd/nhrp_cache.c | |
parent | nhrpd: add holdtime and MTU to CIE (diff) | |
download | frr-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.c | 90 |
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; |