From 89130bf0996d592e6facd50bef1c7101e659d0ff Mon Sep 17 00:00:00 2001 From: John Sharratt Date: Sun, 2 Jul 2017 22:38:23 +0200 Subject: [PATCH] Now creating session on receiving NDP adverts even if no one has specifically asked for one yet thus ensuring the routes are created and that the latecy on proxy solicitation is kept much lower --- src/iface.cc | 20 ++++++++++++ src/iface.h | 8 ++++- src/ndppd.cc | 1 + src/proxy.cc | 86 +++++++++++++++++++++++++++++++------------------- src/proxy.h | 7 ++-- src/session.cc | 17 +++++++--- src/session.h | 4 +-- 7 files changed, 101 insertions(+), 42 deletions(-) diff --git a/src/iface.cc b/src/iface.cc index 99617be..6c09f60 100644 --- a/src/iface.cc +++ b/src/iface.cc @@ -599,6 +599,7 @@ int iface::poll_all() continue; } + bool found = false; for (std::list >::iterator s_it = ifa->_sessions.begin(); s_it != ifa->_sessions.end(); s_it++) { assert(!s_it->is_null()); @@ -607,9 +608,18 @@ int iface::poll_all() if ((sess->taddr() == taddr) && (sess->status() == session::WAITING || sess->status() == session::RENEWING)) { sess->handle_advert(ifa); + found = true; break; } } + + if (found == false) { + if (ifa->owner()) { + ifa->owner()->handle_advert(saddr, taddr, ifa); + } else { + logger::debug() << "iface::poll_all - ignoring advert on proxy iface=" << ifa->name(); + } + } } } @@ -709,4 +719,14 @@ const ptr& iface::pr() const return _pr; } +void iface::owner(const ptr& pr) +{ + _owner = pr; +} + +const ptr& iface::owner() const +{ + return _owner; +} + NDPPD_NS_END diff --git a/src/iface.h b/src/iface.h index 48d49e2..573b613 100644 --- a/src/iface.h +++ b/src/iface.h @@ -67,8 +67,12 @@ public: void remove_session(const ptr& se); void pr(const ptr& pr); - + const ptr& pr() const; + + void owner(const ptr& pr); + + const ptr& owner() const; private: static std::map > _map; @@ -108,6 +112,8 @@ private: std::list > _sessions; weak_ptr _pr; + + weak_ptr _owner; // The link-layer address of this interface. struct ether_addr hwaddr; diff --git a/src/ndppd.cc b/src/ndppd.cc index 813b931..51cb852 100644 --- a/src/ndppd.cc +++ b/src/ndppd.cc @@ -204,6 +204,7 @@ static bool configure(ptr& cf) if (!ifa || ifa.is_null() == true) { return false; } + ifa->owner(pr); pr->add_rule(addr, ifa); } else if (ru_cf->find("auto")) { diff --git a/src/proxy.cc b/src/proxy.cc index c878ac6..5e32b2f 100644 --- a/src/proxy.cc +++ b/src/proxy.cc @@ -26,7 +26,9 @@ #include "session.h" NDPPD_NS_BEGIN - + +static address all_nodes = address("ff02::1"); + std::list > proxy::_list; proxy::proxy() : @@ -61,14 +63,8 @@ ptr proxy::open(const std::string& ifname, bool promiscuous) return create(ifa, promiscuous); } -void proxy::handle_solicit(const address& saddr, const address& daddr, - const address& taddr) +ptr proxy::find_or_create_session(const address& saddr, const address& daddr, const address& taddr, const ptr& receiver) { - logger::debug() - << "proxy::handle_solicit() ifa=" << ((_ifa) ? _ifa->name() : "null") - << ", saddr=" << saddr.to_string() - << ", taddr=" << taddr.to_string(); - // Let's check this proxy's list of sessions to see if we can // find one with the same target address. @@ -76,43 +72,32 @@ void proxy::handle_solicit(const address& saddr, const address& daddr, sit != _sessions.end(); sit++) { if ((*sit)->taddr() == taddr) - { - (*sit)->touch(); - - switch ((*sit)->status()) { - case session::WAITING: - case session::INVALID: - break; - - case session::VALID: - case session::RENEWING: - (*sit)->send_advert(); - } - - return; - } + return (*sit); } - + // Since we couldn't find a session that matched, we'll try to find // a matching rule instead, and then set up a new session. - + ptr se; - + for (std::list >::iterator it = _rules.begin(); it != _rules.end(); it++) { ptr ru = *it; logger::debug() << "checking " << ru->addr() << " against " << taddr; - if (!daddr.is_multicast() && ru->addr() != daddr) { + if (!daddr.is_multicast() && ru->addr() != daddr && daddr != taddr) { continue; } + + if (receiver && ru->ifa() && receiver->name() != ru->ifa()->name()) + continue; if (ru->addr() == taddr) { if (!se) { se = session::create(_ptr, saddr, daddr, taddr, _autowire); } - + if (ru->is_auto()) { ptr rt = route::find(taddr); @@ -129,23 +114,60 @@ void proxy::handle_solicit(const address& saddr, const address& daddr, // This rule doesn't have an interface, and thus we'll consider // it "static" and immediately send the response. se->handle_advert(); - return; + return se; } else { se->add_iface((*it)->ifa()); #ifdef WITH_ND_NETLINK if (if_addr_find((*it)->ifa()->name(), &taddr.const_addr())) { logger::debug() << "Sending NA out " << (*it)->ifa()->name(); se->add_iface(_ifa); - se->handle_advert(_ifa); + se->handle_advert(); } #endif } } } - + if (se) { _sessions.push_back(se); - se->send_solicit(); + } + + return se; +} + +void proxy::handle_advert(const address& saddr, const address& taddr, const ptr& receiver) +{ + logger::debug() + << "proxy::handle_advert() proxy=" << (ifa() ? ifa()->name() : "null") << ", receiver=" << (receiver ? receiver->name() : "null") + << ", saddr=" << saddr.to_string() + << ", taddr=" << taddr.to_string(); + + ptr se = find_or_create_session(saddr, all_nodes, taddr, receiver); + if (!se) return; + + se->handle_advert(receiver); +} + +void proxy::handle_solicit(const address& saddr, const address& daddr, const address& taddr) +{ + logger::debug() + << "proxy::handle_solicit() ifa=" << ((_ifa) ? _ifa->name() : "null") + << ", saddr=" << saddr.to_string() + << ", taddr=" << taddr.to_string(); + + ptr se = find_or_create_session(saddr, daddr, taddr, ptr()); + if (!se) return; + + se->touch(); + + switch (se->status()) { + case session::WAITING: + case session::INVALID: + return; + + case session::VALID: + case session::RENEWING: + se->send_advert(); } } diff --git a/src/proxy.h b/src/proxy.h index c19ea60..c09212d 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -33,9 +33,12 @@ public: static ptr create(const ptr& ifa, bool promiscuous); static ptr open(const std::string& ifn, bool promiscuous); + + ptr find_or_create_session(const address& saddr, const address& daddr, const address& taddr, const ptr& receiver); + + void handle_advert(const address& saddr, const address& taddr, const ptr& receiver); - void handle_solicit(const address& saddr, const address& daddr, - const address& taddr); + void handle_solicit(const address& saddr, const address& daddr, const address& taddr); void remove_session(const ptr& se); diff --git a/src/session.cc b/src/session.cc index ba000d0..10e7130 100644 --- a/src/session.cc +++ b/src/session.cc @@ -104,14 +104,14 @@ ptr session::create(const ptr& pr, const address& saddr, se->_taddr = taddr; se->_daddr = daddr; se->_autowire = auto_wire; - se->_wired = false; + se->_wired = false; se->_ttl = pr->timeout(); - se->_touched = true; + se->_touched = false; _sessions.push_back(se); logger::debug() - << "session::create() pr=" << logger::format("%x", (proxy* )pr) << ", slave=" << ((pr->ifa()) ? pr->ifa()->name() : "null") << ", saddr=" << saddr + << "session::create() pr=" << logger::format("%x", (proxy* )pr) << ", proxy=" << ((pr->ifa()) ? pr->ifa()->name() : "null") << ", saddr=" << saddr << ", daddr=" << daddr << ", taddr=" << taddr << ", autowire=" << (auto_wire == true ? "yes" : "no") << " =" << logger::format("%x", (session* )se); return se; @@ -139,7 +139,13 @@ void session::send_solicit() void session::touch() { - _touched = true; + if (_touched == false) + { + _touched = true; + + if (status() == session::WAITING || status() == session::INVALID) + send_solicit(); + } } void session::send_advert() @@ -193,13 +199,14 @@ void session::handle_auto_unwire(const ptr& ifa) void session::handle_advert(const ptr& ifa) { - if (_autowire == true) { + if (_autowire == true && _status == WAITING) { handle_auto_wire(ifa); } handle_advert(); } + void session::handle_advert() { logger::debug() diff --git a/src/session.h b/src/session.h index eacead3..6b6a6cc 100644 --- a/src/session.h +++ b/src/session.h @@ -84,9 +84,9 @@ public: int status() const; void status(int val); - - void handle_advert(); + void handle_advert(); + void handle_advert(const ptr& ifa); void handle_auto_wire(const ptr& ifa);