Jelajahi Sumber

Rework how paths are set as remote cluster preferred. The code is now clearer and cluster preference indications are now very sticky as they should be.

Adam Ierymenko 9 tahun lalu
induk
melakukan
8a2e8bd585
3 mengubah file dengan 46 tambahan dan 37 penghapusan
  1. 1 1
      node/Hashtable.hpp
  2. 11 27
      node/Peer.cpp
  3. 34 9
      node/Peer.hpp

+ 1 - 1
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)
 	{

+ 11 - 27
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;
@@ -173,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());
@@ -216,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);
@@ -350,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;
 		}
@@ -399,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;
 		}

+ 34 - 9
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;