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

This commit is contained in:
Adam Ierymenko 2016-09-03 15:39:05 -07:00
parent 01aa469591
commit eebcf08084
8 changed files with 50 additions and 50 deletions

View File

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

View File

@ -264,7 +264,7 @@
/** /**
* Peers forget paths that have not spoken in this long * 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) * Timeout for overall peer activity (measured from last receive)

View File

@ -36,7 +36,7 @@
#include "Peer.hpp" #include "Peer.hpp"
// Uncomment to make the rules engine dump trace info to stdout // 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 { namespace ZeroTier {

View File

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

View File

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

View File

@ -121,7 +121,9 @@ public:
bool hasActivePathTo(uint64_t now,const InetAddress &addr) const; 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 * @param addr Address to make exclusive
*/ */
@ -161,7 +163,7 @@ public:
* Send pings or keepalives depending on configured timeouts * Send pings or keepalives depending on configured timeouts
* *
* @param now Current time * @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 * @return True if we have at least one direct path
*/ */
bool doPingAndKeepalive(uint64_t now,int inetAddressFamily); bool doPingAndKeepalive(uint64_t now,int inetAddressFamily);
@ -285,7 +287,7 @@ public:
inline bool hasClusterOptimalPath(uint64_t now) const inline bool hasClusterOptimalPath(uint64_t now) const
{ {
for(unsigned int p=0,np=_numPaths;p<np;++p) { 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 true;
} }
return false; return false;
@ -365,7 +367,9 @@ private:
inline uint64_t _pathScore(const unsigned int p) const 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]; unsigned char _key[ZT_PEER_SECRET_KEY_LENGTH];
@ -384,9 +388,9 @@ private:
uint16_t _vRevision; uint16_t _vRevision;
Identity _id; Identity _id;
struct { struct {
SharedPtr<Path> path;
uint64_t lastReceive; uint64_t lastReceive;
bool clusterSuboptimal; SharedPtr<Path> path;
unsigned int clusterWeights;
} _paths[ZT_MAX_PEER_NETWORK_PATHS]; } _paths[ZT_MAX_PEER_NETWORK_PATHS];
Mutex _paths_m; Mutex _paths_m;
unsigned int _numPaths; unsigned int _numPaths;

10
one.cpp
View File

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

View File

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