From 84732fcb12d66708e7887fba51413cbe629d86d3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 22 Nov 2016 14:23:13 -0800 Subject: [PATCH] Wire through external path lookup. Static paths should now work. --- node/Constants.hpp | 5 +++++ node/Node.cpp | 2 +- node/Node.hpp | 7 +++++-- node/Peer.cpp | 11 +++++++++++ node/Peer.hpp | 8 ++++++++ node/Switch.cpp | 15 ++++++++------- service/OneService.cpp | 13 +++++++------ 7 files changed, 45 insertions(+), 16 deletions(-) diff --git a/node/Constants.hpp b/node/Constants.hpp index 8803eceeb..ac1919b34 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -320,6 +320,11 @@ */ #define ZT_MIN_UNITE_INTERVAL 30000 +/** + * How often should peers try memorized or statically defined paths? + */ +#define ZT_TRY_MEMORIZED_PATH_INTERVAL 30000 + /** * Sanity limit on maximum bridge routes * diff --git a/node/Node.cpp b/node/Node.cpp index a180766b9..11f763653 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -683,7 +683,7 @@ void Node::postTrace(const char *module,unsigned int line,const char *fmt,...) uint64_t Node::prng() { - unsigned int p = (++_prngStreamPtr % (sizeof(_prngStream) / sizeof(uint64_t))); + unsigned int p = (++_prngStreamPtr % ZT_NODE_PRNG_BUF_SIZE); if (!p) _prng.encrypt12(_prngStream,_prngStream,sizeof(_prngStream)); return _prngStream[p]; diff --git a/node/Node.hpp b/node/Node.hpp index 7d99ff093..eb46527da 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -49,6 +49,9 @@ #define ZT_EXPECTING_REPLIES_BUCKET_MASK1 255 #define ZT_EXPECTING_REPLIES_BUCKET_MASK2 31 +// Size of PRNG stream buffer +#define ZT_NODE_PRNG_BUF_SIZE 64 + namespace ZeroTier { /** @@ -195,7 +198,7 @@ public: #endif bool shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress); - inline bool getPathHint(const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast(this),_uPtr,ztaddr.toInt(),family,reinterpret_cast(&addr)) != 0) : false ); } + inline bool externalPathLookup(const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast(this),_uPtr,ztaddr.toInt(),family,reinterpret_cast(&addr)) != 0) : false ); } uint64_t prng(); void postCircuitTestReport(const ZT_CircuitTestReport *report); @@ -284,7 +287,7 @@ private: unsigned int _prngStreamPtr; Salsa20 _prng; - uint64_t _prngStream[16]; // repeatedly encrypted with _prng to yield a high-quality non-crypto PRNG stream + uint64_t _prngStream[ZT_NODE_PRNG_BUF_SIZE]; // repeatedly encrypted with _prng to yield a high-quality non-crypto PRNG stream uint64_t _now; uint64_t _lastPingCheck; diff --git a/node/Peer.cpp b/node/Peer.cpp index e0bd0eac4..2ef139e10 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -43,6 +43,7 @@ static uint32_t _natKeepaliveBuf = 0; Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) : _lastReceive(0), _lastNontrivialReceive(0), + _lastTriedMemorizedPath(0), _lastDirectPathPushSent(0), _lastDirectPathPushReceive(0), _lastCredentialRequestSent(0), @@ -373,6 +374,16 @@ void Peer::attemptToContactAt(const InetAddress &localAddr,const InetAddress &at } } +void Peer::tryMemorizedPath(uint64_t now) +{ + if ((now - _lastTriedMemorizedPath) >= ZT_TRY_MEMORIZED_PATH_INTERVAL) { + _lastTriedMemorizedPath = now; + InetAddress mp; + if (RR->node->externalPathLookup(_id.address(),-1,mp)) + attemptToContactAt(InetAddress(),mp,now); + } +} + bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily) { Mutex::Lock _l(_paths_m); diff --git a/node/Peer.hpp b/node/Peer.hpp index a7240cb42..78b345b9a 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -164,6 +164,13 @@ public: */ void attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now); + /** + * Try a memorized or statically defined path if any are known + * + * Under the hood this is done periodically based on ZT_TRY_MEMORIZED_PATH_INTERVAL. + */ + void tryMemorizedPath(uint64_t now); + /** * Send pings or keepalives depending on configured timeouts * @@ -435,6 +442,7 @@ private: uint8_t _remoteClusterOptimal6[16]; uint64_t _lastReceive; // direct or indirect uint64_t _lastNontrivialReceive; // frames, things like netconf, etc. + uint64_t _lastTriedMemorizedPath; uint64_t _lastDirectPathPushSent; uint64_t _lastDirectPathPushReceive; uint64_t _lastCredentialRequestSent; diff --git a/node/Switch.cpp b/node/Switch.cpp index 881d7b92f..7c94d4387 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -710,12 +710,12 @@ bool Switch::_trySend(const Packet &packet,bool encrypt) if (peer) { const uint64_t now = RR->node->now(); - // First get the best path, and if it's dead (and this is not a root) - // we attempt to re-activate that path but this packet will flow - // upstream. If the path comes back alive, it will be used in the future. - // For roots we don't do the alive check since roots are not required - // to send heartbeats "down" and because we have to at least try to - // go somewhere. + /* First get the best path, and if it's dead (and this is not a root) + * we attempt to re-activate that path but this packet will flow + * upstream. If the path comes back alive, it will be used in the future. + * For roots we don't do the alive check since roots are not required + * to send heartbeats "down" and because we have to at least try to + * go somewhere. */ SharedPtr viaPath(peer->getBestPath(now,false)); if ( (viaPath) && (!viaPath->alive(now)) && (!RR->topology->isRoot(peer->identity())) ) { @@ -724,7 +724,8 @@ bool Switch::_trySend(const Packet &packet,bool encrypt) viaPath.zero(); } if (!viaPath) { - SharedPtr relay(RR->topology->getUpstreamPeer()); + peer->tryMemorizedPath(now); // periodically attempt memorized or statically defined paths, if any are known + const SharedPtr relay(RR->topology->getUpstreamPeer()); if ( (!relay) || (!(viaPath = relay->getBestPath(now,false))) ) { if (!(viaPath = peer->getBestPath(now,true))) return false; diff --git a/service/OneService.cpp b/service/OneService.cpp index 7434ca672..a2024e520 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1163,6 +1163,7 @@ public: // Internal implementation methods ----------------------------------------- + // Must be called after _localConfig is read or modified void applyLocalConfig() { Mutex::Lock _l(_localConfig_m); @@ -1872,6 +1873,12 @@ public: } } + /* Note: I do not think we need to scan for overlap with managed routes + * because of the "route forking" and interface binding that we do. This + * ensures (we hope) that ZeroTier traffic will still take the physical + * path even if its managed routes override this for other traffic. Will + * revisit if we see recursion problems. */ + // Check blacklists const Hashtable< uint64_t,std::vector > *blh = (const Hashtable< uint64_t,std::vector > *)0; const std::vector *gbl = (const std::vector *)0; @@ -1897,12 +1904,6 @@ public: } } - /* Note: I do not think we need to scan for overlap with managed routes - * because of the "route forking" and interface binding that we do. This - * ensures (we hope) that ZeroTier traffic will still take the physical - * path even if its managed routes override this for other traffic. Will - * revisit if we see problems with this. */ - return 1; }