diff options
Diffstat (limited to 'node')
-rw-r--r-- | node/Hashtable.hpp | 2 | ||||
-rw-r--r-- | node/Path.hpp | 2 | ||||
-rw-r--r-- | node/Peer.cpp | 40 | ||||
-rw-r--r-- | node/Peer.hpp | 43 |
4 files changed, 50 insertions, 37 deletions
diff --git a/node/Hashtable.hpp b/node/Hashtable.hpp index c550191e..66f2990a 100644 --- a/node/Hashtable.hpp +++ b/node/Hashtable.hpp @@ -362,7 +362,7 @@ private: template<typename O> static inline unsigned long _hc(const O &obj) { - return obj.hashCode(); + return (unsigned long)obj.hashCode(); } static inline unsigned long _hc(const uint64_t i) { diff --git a/node/Path.hpp b/node/Path.hpp index 718e1cdd..8151ed27 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -156,6 +156,8 @@ public: */ inline unsigned int preferenceRank() const { + // This causes us to rank paths in order of IP scope rank (see InetAdddress.hpp) but + // within each IP scope class to prefer IPv6 over IPv4. return ( ((unsigned int)_ipScope << 1) | (unsigned int)(_addr.ss_family == AF_INET6) ); } diff --git a/node/Peer.cpp b/node/Peer.cpp index 3701d9a1..ab287d05 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -33,7 +33,6 @@ namespace ZeroTier { static uint32_t _natKeepaliveBuf = 0; Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) : - RR(renv), _lastUsed(0), _lastReceive(0), _lastUnicastFrame(0), @@ -41,6 +40,8 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident _lastAnnouncedTo(0), _lastDirectPathPushSent(0), _lastDirectPathPushReceive(0), + RR(renv), + _remoteClusterOptimal4(0), _vProto(0), _vMajor(0), _vMinor(0), @@ -50,6 +51,7 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident _latency(0), _directPathPushCutoffCount(0) { + memset(_remoteClusterOptimal6,0,sizeof(_remoteClusterOptimal6)); if (!myIdentity.agree(peerIdentity,_key,ZT_PEER_SECRET_KEY_LENGTH)) throw std::runtime_error("new peer identity key agreement failed"); } @@ -126,7 +128,7 @@ void Peer::received( _paths[p].lastReceive = now; _paths[p].path = path; // local address may have changed! #ifdef ZT_ENABLE_CLUSTER - _paths[p].clusterWeights = (unsigned int)(!suboptimalPath); + _paths[p].localClusterSuboptimal = suboptimalPath; #endif pathIsConfirmed = true; break; @@ -138,6 +140,7 @@ void Peer::received( if (verb == Packet::VERB_OK) { Mutex::Lock _l(_paths_m); + // Since this is a new path, figure out where to put it (possibly replacing an old/dead one) unsigned int slot; if (_numPaths < ZT_MAX_PEER_NETWORK_PATHS) { slot = _numPaths++; @@ -157,6 +160,7 @@ void Peer::received( if (worstSlot >= 0) { slot = (unsigned int)worstSlot; } else { + // If we can't find one with the same family, replace the worst of any family slot = ZT_MAX_PEER_NETWORK_PATHS - 1; for(unsigned int p=0;p<_numPaths;++p) { const uint64_t s = _pathScore(p); @@ -171,11 +175,9 @@ void Peer::received( _paths[slot].lastReceive = now; _paths[slot].path = path; #ifdef ZT_ENABLE_CLUSTER - _paths[slot].clusterWeights = (unsigned int)(!suboptimalPath); + _paths[p].localClusterSuboptimal = suboptimalPath; if (RR->cluster) RR->cluster->broadcastHavePeer(_id); -#else - _paths[slot].clusterWeights = 1; #endif } else { TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),path->address().toString().c_str()); @@ -214,26 +216,6 @@ bool Peer::hasActivePathTo(uint64_t now,const InetAddress &addr) const return false; } -void Peer::setClusterOptimal(const InetAddress &addr) -{ - Mutex::Lock _l(_paths_m); - - int opt = -1; - for(unsigned int p=0;p<_numPaths;++p) { - if (_paths[p].path->address() == addr) { - opt = (int)p; - break; - } - } - - if (opt >= 0) { // only change anything if we have the optimal path - for(unsigned int p=0;p<_numPaths;++p) { - if (_paths[p].path->address().ss_family == addr.ss_family) - _paths[p].clusterWeights = ((int)p == opt) ? 2 : 0; - } - } -} - bool Peer::sendDirect(const void *data,unsigned int len,uint64_t now,bool forceEvenIfDead) { Mutex::Lock _l(_paths_m); @@ -348,7 +330,9 @@ bool Peer::resetWithinScope(InetAddress::IpScope scope,uint64_t now) if (x != y) { _paths[y].lastReceive = _paths[x].lastReceive; _paths[y].path = _paths[x].path; - _paths[y].clusterWeights = _paths[x].clusterWeights; +#ifdef ZT_ENABLE_CLUSTER + _paths[y].localClusterSuboptimal = _paths[x].localClusterSuboptimal; +#endif } ++y; } @@ -397,7 +381,9 @@ void Peer::clean(uint64_t now) if (y != x) { _paths[y].lastReceive = _paths[x].lastReceive; _paths[y].path = _paths[x].path; - _paths[y].clusterWeights = _paths[x].clusterWeights; +#ifdef ZT_ENABLE_CLUSTER + _paths[y].localClusterSuboptimal = _paths[x].localClusterSuboptimal; +#endif } ++y; } diff --git a/node/Peer.hpp b/node/Peer.hpp index 25ef72b7..cd08e2d7 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -123,11 +123,16 @@ public: /** * Set which known path for an address family is optimal * - * This only modifies paths within the same address family - * * @param addr Address to make exclusive */ - void setClusterOptimal(const InetAddress &addr); + inline void setClusterOptimal(const InetAddress &addr) + { + if (addr.ss_family == AF_INET) { + _remoteClusterOptimal4 = (uint32_t)reinterpret_cast<const struct sockaddr_in *>(&addr)->sin_addr.s_addr; + } else if (addr.ss_family == AF_INET6) { + memcpy(_remoteClusterOptimal6,reinterpret_cast<const struct sockaddr_in6 *>(&addr)->sin6_addr.s6_addr,16); + } + } /** * Send via best direct path @@ -367,14 +372,30 @@ private: inline uint64_t _pathScore(const unsigned int p) const { - return ( _paths[p].lastReceive + - (uint64_t)(_paths[p].path->preferenceRank() * (ZT_PEER_PING_PERIOD / ZT_PATH_MAX_PREFERENCE_RANK)) + - (uint64_t)(_paths[p].clusterWeights * ZT_PEER_PING_PERIOD) ); + uint64_t s = ZT_PEER_PING_PERIOD; + if (_paths[p].path->address().ss_family == AF_INET) { + s += _paths[p].lastReceive + (uint64_t)(_paths[p].path->preferenceRank() * (ZT_PEER_PING_PERIOD / ZT_PATH_MAX_PREFERENCE_RANK)) + (uint64_t)(ZT_PEER_PING_PERIOD * (unsigned long)(reinterpret_cast<const struct sockaddr_in *>(&(_paths[p].path->address()))->sin_addr.s_addr == _remoteClusterOptimal4)); + } else if (_paths[p].path->address().ss_family == AF_INET6) { + uint64_t clusterWeight = ZT_PEER_PING_PERIOD; + const uint8_t *a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&(_paths[p].path->address()))->sin6_addr.s6_addr); + for(long i=0;i<16;++i) { + if (a[i] != _remoteClusterOptimal6[i]) { + clusterWeight = 0; + break; + } + } + s += _paths[p].lastReceive + (uint64_t)(_paths[p].path->preferenceRank() * (ZT_PEER_PING_PERIOD / ZT_PATH_MAX_PREFERENCE_RANK)) + clusterWeight; + } else { + s += _paths[p].lastReceive + (uint64_t)(_paths[p].path->preferenceRank() * (ZT_PEER_PING_PERIOD / ZT_PATH_MAX_PREFERENCE_RANK)); + } +#ifdef ZT_ENABLE_CLUSTER + s -= ZT_PEER_PING_PERIOD * (uint64_t)_paths[p].localClusterSuboptimal; +#endif + return s; } unsigned char _key[ZT_PEER_SECRET_KEY_LENGTH]; - - const RuntimeEnvironment *RR; + uint8_t _remoteClusterOptimal6[16]; uint64_t _lastUsed; uint64_t _lastReceive; // direct or indirect uint64_t _lastUnicastFrame; @@ -382,6 +403,8 @@ private: uint64_t _lastAnnouncedTo; uint64_t _lastDirectPathPushSent; uint64_t _lastDirectPathPushReceive; + const RuntimeEnvironment *RR; + uint32_t _remoteClusterOptimal4; uint16_t _vProto; uint16_t _vMajor; uint16_t _vMinor; @@ -390,7 +413,9 @@ private: struct { uint64_t lastReceive; SharedPtr<Path> path; - unsigned int clusterWeights; +#ifdef ZT_ENABLE_CLUSTER + bool localClusterSuboptimal; +#endif } _paths[ZT_MAX_PEER_NETWORK_PATHS]; Mutex _paths_m; unsigned int _numPaths; |