From eebcf08084097fc7cd8703a11686e66157fa8efa Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sat, 3 Sep 2016 15:39:05 -0700 Subject: [PATCH] Tweaks to new Path code for dual-stack operation, and other fixes. --- include/ZeroTierOne.h | 5 ---- node/Constants.hpp | 2 +- node/Network.cpp | 2 +- node/Node.cpp | 3 +-- node/Peer.cpp | 58 +++++++++++++++++++++------------------- node/Peer.hpp | 16 ++++++----- one.cpp | 10 +++---- service/ControlPlane.cpp | 4 +-- 8 files changed, 50 insertions(+), 50 deletions(-) diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index db0560a32..583abfe49 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -1053,11 +1053,6 @@ typedef struct */ uint64_t trustedPathId; - /** - * Is path active? - */ - int active; - /** * Is path preferred? */ diff --git a/node/Constants.hpp b/node/Constants.hpp index b783e2c2d..ea4c434d7 100644 --- a/node/Constants.hpp +++ b/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) diff --git a/node/Network.cpp b/node/Network.cpp index 4dc8aa303..b18a3b229 100644 --- a/node/Network.cpp +++ b/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 { diff --git a/node/Node.cpp b/node/Node.cpp index d2840bd0f..a7d4cfa9f 100644 --- a/node/Node.cpp +++ b/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; diff --git a/node/Peer.cpp b/node/Peer.cpp index ecf2a8706..0cb55fd83 100644 --- a/node/Peer.cpp +++ b/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; } diff --git a/node/Peer.hpp b/node/Peer.hpp index efe34825d..8286bfff0 100644 --- a/node/Peer.hpp +++ b/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;palive(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; uint64_t lastReceive; - bool clusterSuboptimal; + SharedPtr path; + unsigned int clusterWeights; } _paths[ZT_MAX_PEER_NETWORK_PATHS]; Mutex _paths_m; unsigned int _numPaths; diff --git a/one.cpp b/one.cpp index 7cddb3763..6ad5c8e6c 100644 --- a/one.cpp +++ b/one.cpp @@ -330,12 +330,12 @@ static int cli(int argc,char **argv) out << "200 listpeers " << ZT_EOL_S; if (j.is_array()) { for(unsigned long k=0;k " << ZT_EOL_S; if (j.is_array()) { for(unsigned long i=0;i 0) aa.push_back(','); aa.append(addr); diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index 5ed6b8b70..03c5942d4 100644 --- a/service/ControlPlane.cpp +++ b/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(&(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);