Bläddra i källkod

Tweaks to new Path code for dual-stack operation, and other fixes.

Adam Ierymenko 9 år sedan
förälder
incheckning
eebcf08084
8 ändrade filer med 50 tillägg och 50 borttagningar
  1. 0 5
      include/ZeroTierOne.h
  2. 1 1
      node/Constants.hpp
  3. 1 1
      node/Network.cpp
  4. 1 2
      node/Node.cpp
  5. 30 28
      node/Peer.cpp
  6. 10 6
      node/Peer.hpp
  7. 5 5
      one.cpp
  8. 2 2
      service/ControlPlane.cpp

+ 0 - 5
include/ZeroTierOne.h

@@ -1053,11 +1053,6 @@ typedef struct
 	 */
 	uint64_t trustedPathId;
 
-	/**
-	 * Is path active?
-	 */
-	int active;
-
 	/**
 	 * Is path preferred?
 	 */

+ 1 - 1
node/Constants.hpp

@@ -264,7 +264,7 @@
 /**
  * Peers forget paths that have not spoken in this long
  */
-#define ZT_PEER_PATH_EXPIRATION ((ZT_PEER_PING_PERIOD * 3) + 3000)
+#define ZT_PEER_PATH_EXPIRATION ((ZT_PEER_PING_PERIOD * 4) + 3000)
 
 /**
  * Timeout for overall peer activity (measured from last receive)

+ 1 - 1
node/Network.cpp

@@ -36,7 +36,7 @@
 #include "Peer.hpp"
 
 // Uncomment to make the rules engine dump trace info to stdout
-#define ZT_RULES_ENGINE_DEBUGGING 1
+//#define ZT_RULES_ENGINE_DEBUGGING 1
 
 namespace ZeroTier {
 

+ 1 - 2
node/Node.cpp

@@ -243,7 +243,7 @@ public:
 			lastReceiveFromUpstream = std::max(p->lastReceive(),lastReceiveFromUpstream);
 		} else if (p->activelyTransferringFrames(_now)) {
 			// Normal nodes get their preferred link kept alive if the node has generated frame traffic recently
-			p->doPingAndKeepalive(_now,0);
+			p->doPingAndKeepalive(_now,-1);
 		}
 	}
 
@@ -422,7 +422,6 @@ ZT_PeerList *Node::peers() const
 			memcpy(&(p->paths[p->pathCount].address),&((*path)->address()),sizeof(struct sockaddr_storage));
 			p->paths[p->pathCount].lastSend = (*path)->lastOut();
 			p->paths[p->pathCount].lastReceive = (*path)->lastIn();
-			p->paths[p->pathCount].active = (*path)->alive(_now) ? 1 : 0;
 			p->paths[p->pathCount].preferred = (*path == bestp) ? 1 : 0;
 			p->paths[p->pathCount].trustedPathId = RR->topology->getOutboundPathTrust((*path)->address());
 			++p->pathCount;

+ 30 - 28
node/Peer.cpp

@@ -122,10 +122,11 @@ void Peer::received(
 		{
 			Mutex::Lock _l(_paths_m);
 			for(unsigned int p=0;p<_numPaths;++p) {
-				if (_paths[p].path == path) { // paths are canonicalized so pointer compare is good here
+				if (_paths[p].path->address() == path->address()) {
 					_paths[p].lastReceive = now;
+					_paths[p].path = path; // local address may have changed!
 #ifdef ZT_ENABLE_CLUSTER
-					_paths[p].clusterSuboptimal = suboptimalPath;
+					_paths[p].clusterWeights = (unsigned int)(!suboptimalPath);
 #endif
 					pathIsConfirmed = true;
 					break;
@@ -141,25 +142,26 @@ void Peer::received(
 				if (_numPaths < ZT_MAX_PEER_NETWORK_PATHS) {
 					slot = _numPaths++;
 				} else {
-					uint64_t oldest = 0ULL;
-					unsigned int oldestPath = 0;
+					uint64_t worstScore = 0xffffffffffffffffULL;
+					unsigned int worstPath = ZT_MAX_PEER_NETWORK_PATHS-1;
 					for(unsigned int p=0;p<_numPaths;++p) {
-						if (_paths[p].lastReceive < oldest) {
-							oldest = _paths[p].lastReceive;
-							oldestPath = p;
+						const uint64_t s = _pathScore(p);
+						if (s < worstScore) {
+							worstScore = s;
+							worstPath = p;
 						}
 					}
-					slot = oldestPath;
+					slot = worstPath;
 				}
 
-				_paths[slot].path = path;
 				_paths[slot].lastReceive = now;
+				_paths[slot].path = path;
 #ifdef ZT_ENABLE_CLUSTER
-				_paths[slot].clusterSuboptimal = suboptimalPath;
+				_paths[slot].clusterWeights = (unsigned int)(!suboptimalPath);
 				if (RR->cluster)
 					RR->cluster->broadcastHavePeer(_id);
 #else
-				_paths[slot].clusterSuboptimal = false;
+				_paths[slot].clusterWeights = 1;
 #endif
 			} else {
 
@@ -201,17 +203,19 @@ void Peer::setClusterOptimal(const InetAddress &addr)
 {
 	Mutex::Lock _l(_paths_m);
 
-	int have = -1;
+	int opt = -1;
 	for(unsigned int p=0;p<_numPaths;++p) {
 		if (_paths[p].path->address() == addr) {
-			have = (int)p;
+			opt = (int)p;
 			break;
 		}
 	}
 
-	if (have >= 0) {
-		for(unsigned int p=0;p<_numPaths;++p)
-			_paths[p].clusterSuboptimal = (p != have);
+	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;
+		}
 	}
 }
 
@@ -282,10 +286,12 @@ bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily)
 	int bestp = -1;
 	uint64_t best = 0ULL;
 	for(unsigned int p=0;p<_numPaths;++p) {
-		const uint64_t s = _pathScore(p);
-		if (s >= best) {
-			best = s;
-			bestp = (int)p;
+		if ((inetAddressFamily < 0)||(_paths[p].path->address().ss_family == inetAddressFamily)) {
+			const uint64_t s = _pathScore(p);
+			if (s >= best) {
+				best = s;
+				bestp = (int)p;
+			}
 		}
 	}
 
@@ -325,11 +331,9 @@ bool Peer::resetWithinScope(InetAddress::IpScope scope,uint64_t now)
 			sendHELLO(_paths[x].path->localAddress(),_paths[x].path->address(),now);
 		} else {
 			if (x != y) {
-				_paths[y].path = _paths[x].path;
 				_paths[y].lastReceive = _paths[x].lastReceive;
-#ifdef ZT_ENABLE_CLUSTER
-				_paths[y].clusterSuboptimal = _paths[x].clusterSuboptimal;
-#endif
+				_paths[y].path = _paths[x].path;
+				_paths[y].clusterWeights = _paths[x].clusterWeights;
 			}
 			++y;
 		}
@@ -376,11 +380,9 @@ void Peer::clean(uint64_t now)
 	while (x < np) {
 		if ((now - _paths[x].lastReceive) <= ZT_PEER_PATH_EXPIRATION) {
 			if (y != x) {
-				_paths[y].path = _paths[x].path;
 				_paths[y].lastReceive = _paths[x].lastReceive;
-#ifdef ZT_ENABLE_CLUSTER
-				_paths[y].clusterSuboptimal = _paths[x].clusterSuboptimal;
-#endif
+				_paths[y].path = _paths[x].path;
+				_paths[y].clusterWeights = _paths[x].clusterWeights;
 			}
 			++y;
 		}

+ 10 - 6
node/Peer.hpp

@@ -121,7 +121,9 @@ public:
 	bool hasActivePathTo(uint64_t now,const InetAddress &addr) const;
 
 	/**
-	 * If we have a confirmed path to this address, mark others as cluster suboptimal
+	 * 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
 	 */
@@ -161,7 +163,7 @@ public:
 	 * Send pings or keepalives depending on configured timeouts
 	 *
 	 * @param now Current time
-	 * @param inetAddressFamily Keep this address family alive, or 0 to simply pick current best ignoring family
+	 * @param inetAddressFamily Keep this address family alive, or -1 for any
 	 * @return True if we have at least one direct path
 	 */
 	bool doPingAndKeepalive(uint64_t now,int inetAddressFamily);
@@ -285,7 +287,7 @@ public:
 	inline bool hasClusterOptimalPath(uint64_t now) const
 	{
 		for(unsigned int p=0,np=_numPaths;p<np;++p) {
-			if ( (_paths[p].path->alive(now)) && (!_paths[p].clusterSuboptimal) )
+			if ( (_paths[p].path->alive(now)) && ((_paths[p].clusterWeights & 1) != 0) )
 				return true;
 		}
 		return false;
@@ -365,7 +367,9 @@ private:
 
 	inline uint64_t _pathScore(const unsigned int p) const
 	{
-		return ( (_paths[p].path->lastIn() + (_paths[p].path->preferenceRank() * (ZT_PEER_PING_PERIOD / ZT_PATH_MAX_PREFERENCE_RANK))) - ((ZT_PEER_PING_PERIOD * 10) * (uint64_t)_paths[p].clusterSuboptimal) );
+		return ( _paths[p].path->lastIn() +
+		         (uint64_t)(_paths[p].path->preferenceRank() * (ZT_PEER_PING_PERIOD / ZT_PATH_MAX_PREFERENCE_RANK)) +
+						 (uint64_t)(_paths[p].clusterWeights * ZT_PEER_PING_PERIOD) );
 	}
 
 	unsigned char _key[ZT_PEER_SECRET_KEY_LENGTH];
@@ -384,9 +388,9 @@ private:
 	uint16_t _vRevision;
 	Identity _id;
 	struct {
-		SharedPtr<Path> path;
 		uint64_t lastReceive;
-		bool clusterSuboptimal;
+		SharedPtr<Path> path;
+		unsigned int clusterWeights;
 	} _paths[ZT_MAX_PEER_NETWORK_PATHS];
 	Mutex _paths_m;
 	unsigned int _numPaths;

+ 5 - 5
one.cpp

@@ -330,12 +330,12 @@ static int cli(int argc,char **argv)
 				out << "200 listpeers <ztaddr> <path> <latency> <version> <role>" << ZT_EOL_S;
 				if (j.is_array()) {
 					for(unsigned long k=0;k<j.size();++k) {
-						auto p = j[k];
+						auto &p = j[k];
 						std::string bestPath;
 						auto paths = p["paths"];
 						if (paths.is_array()) {
 							for(unsigned long i=0;i<paths.size();++i) {
-								auto path = paths[i];
+								auto &path = paths[i];
 								if (path["preferred"]) {
 									char tmp[256];
 									std::string addr = path["address"];
@@ -389,13 +389,13 @@ static int cli(int argc,char **argv)
 				out << "200 listnetworks <nwid> <name> <mac> <status> <type> <dev> <ZT assigned ips>" << ZT_EOL_S;
 				if (j.is_array()) {
 					for(unsigned long i=0;i<j.size();++i) {
-						auto n = j[i];
+						auto &n = j[i];
 						if (n.is_object()) {
 							std::string aa;
-							auto assignedAddresses = n["assignedAddresses"];
+							auto &assignedAddresses = n["assignedAddresses"];
 							if (assignedAddresses.is_array()) {
 								for(unsigned long j=0;j<assignedAddresses.size();++j) {
-									auto addr = assignedAddresses[j];
+									auto &addr = assignedAddresses[j];
 									if (addr.is_string()) {
 										if (aa.length() > 0) aa.push_back(',');
 										aa.append(addr);

+ 2 - 2
service/ControlPlane.cpp

@@ -183,14 +183,14 @@ static std::string _jsonEnumerate(unsigned int depth,const ZT_PeerPhysicalPath *
 			"%s\t\"address\": \"%s\",\n"
 			"%s\t\"lastSend\": %llu,\n"
 			"%s\t\"lastReceive\": %llu,\n"
-			"%s\t\"active\": %s,\n"
+			"%s\t\"active\": true,\n"
 			"%s\t\"preferred\": %s,\n"
 			"%s\t\"trustedPathId\": %llu\n"
 			"%s}",
 			prefix,_jsonEscape(reinterpret_cast<const InetAddress *>(&(pp[i].address))->toString()).c_str(),
 			prefix,pp[i].lastSend,
 			prefix,pp[i].lastReceive,
-			prefix,(pp[i].active == 0) ? "false" : "true",
+			prefix,
 			prefix,(pp[i].preferred == 0) ? "false" : "true",
 			prefix,pp[i].trustedPathId,
 			prefix);