More tweaks to path behavior.

This commit is contained in:
Adam Ierymenko 2016-09-05 15:47:22 -07:00
parent eebcf08084
commit d7f2287ce9
5 changed files with 34 additions and 24 deletions

View file

@ -152,16 +152,10 @@ public:
inline InetAddress::IpScope ipScope() const { return _ipScope; } inline InetAddress::IpScope ipScope() const { return _ipScope; }
/** /**
* @return Preference rank, higher == better (will be less than 255) * @return Preference rank, higher == better
*/ */
inline unsigned int preferenceRank() const inline unsigned int preferenceRank() const
{ {
/* First, since the scope enum values in InetAddress.hpp are in order of
* use preference rank, we take that. Then we multiple by two, yielding
* a sequence like 0, 2, 4, 6, etc. Then if it's IPv6 we add one. This
* makes IPv6 addresses of a given scope outrank IPv4 addresses of the
* same scope -- e.g. 1 outranks 0. This makes us prefer IPv6, but not
* if the address scope/class is of a fundamentally lower rank. */
return ( ((unsigned int)_ipScope << 1) | (unsigned int)(_addr.ss_family == AF_INET6) ); return ( ((unsigned int)_ipScope << 1) | (unsigned int)(_addr.ss_family == AF_INET6) );
} }
@ -213,7 +207,7 @@ public:
/** /**
* @return True if this path needs a heartbeat * @return True if this path needs a heartbeat
*/ */
inline bool needsHeartbeat(const uint64_t now) const { return ((now - _lastOut) > ZT_PATH_HEARTBEAT_PERIOD); } inline bool needsHeartbeat(const uint64_t now) const { return ((now - _lastOut) >= ZT_PATH_HEARTBEAT_PERIOD); }
/** /**
* @return Last time we sent something * @return Last time we sent something

View file

@ -134,24 +134,38 @@ void Peer::received(
} }
} }
if ((!pathIsConfirmed)&&(RR->node->shouldUsePathForZeroTierTraffic(path->localAddress(),path->address()))) { if ( (!pathIsConfirmed) && (RR->node->shouldUsePathForZeroTierTraffic(path->localAddress(),path->address())) ) {
if (verb == Packet::VERB_OK) { if (verb == Packet::VERB_OK) {
Mutex::Lock _l(_paths_m); Mutex::Lock _l(_paths_m);
unsigned int slot = 0; unsigned int slot;
if (_numPaths < ZT_MAX_PEER_NETWORK_PATHS) { if (_numPaths < ZT_MAX_PEER_NETWORK_PATHS) {
slot = _numPaths++; slot = _numPaths++;
} else { } else {
// First try to replace the worst within the same address family, if possible
int worstSlot = -1;
uint64_t worstScore = 0xffffffffffffffffULL; uint64_t worstScore = 0xffffffffffffffffULL;
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) {
const uint64_t s = _pathScore(p); if (_paths[p].path->address().ss_family == path->address().ss_family) {
if (s < worstScore) { const uint64_t s = _pathScore(p);
worstScore = s; if (s < worstScore) {
worstPath = p; worstScore = s;
worstSlot = (int)p;
}
}
}
if (worstSlot >= 0) {
slot = (unsigned int)worstSlot;
} else {
slot = ZT_MAX_PEER_NETWORK_PATHS - 1;
for(unsigned int p=0;p<_numPaths;++p) {
const uint64_t s = _pathScore(p);
if (s < worstScore) {
worstScore = s;
slot = p;
}
} }
} }
slot = worstPath;
} }
_paths[slot].lastReceive = now; _paths[slot].lastReceive = now;
@ -164,20 +178,21 @@ void Peer::received(
_paths[slot].clusterWeights = 1; _paths[slot].clusterWeights = 1;
#endif #endif
} else { } else {
TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),path->address().toString().c_str());
TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),remoteAddr.toString().c_str());
if ( (_vProto >= 5) && ( !((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0)) ) ) { if ( (_vProto >= 5) && ( !((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0)) ) ) {
// Newer than 1.1.0 can use ECHO, which is smaller
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO); Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO);
outp.armor(_key,true); outp.armor(_key,true);
path->send(RR,outp.data(),outp.size(),now); path->send(RR,outp.data(),outp.size(),now);
} else { } else {
// For backward compatibility we send HELLO to ancient nodes
sendHELLO(path->localAddress(),path->address(),now); sendHELLO(path->localAddress(),path->address(),now);
} }
} }
} }
} else if (trustEstablished) { } else if (trustEstablished) {
// Send PUSH_DIRECT_PATHS if hops>0 (relayed) and we have a trust relationship (common network membership)
_pushDirectPaths(path,now); _pushDirectPaths(path,now);
} }
@ -286,7 +301,7 @@ 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)) { if ((inetAddressFamily < 0)||((int)_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;

View file

@ -164,7 +164,7 @@ public:
* *
* @param now Current time * @param now Current time
* @param inetAddressFamily Keep this address family alive, or -1 for any * @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 of the given family (or any if family is -1)
*/ */
bool doPingAndKeepalive(uint64_t now,int inetAddressFamily); bool doPingAndKeepalive(uint64_t now,int inetAddressFamily);
@ -367,7 +367,7 @@ private:
inline uint64_t _pathScore(const unsigned int p) const inline uint64_t _pathScore(const unsigned int p) const
{ {
return ( _paths[p].path->lastIn() + return ( _paths[p].lastReceive +
(uint64_t)(_paths[p].path->preferenceRank() * (ZT_PEER_PING_PERIOD / ZT_PATH_MAX_PREFERENCE_RANK)) + (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)(_paths[p].clusterWeights * ZT_PEER_PING_PERIOD) );
} }

View file

@ -292,6 +292,7 @@ unsigned int Utils::snprintf(char *buf,unsigned int len,const char *fmt,...)
if ((n >= (int)len)||(n < 0)) { if ((n >= (int)len)||(n < 0)) {
if (len) if (len)
buf[len - 1] = (char)0; buf[len - 1] = (char)0;
abort();
throw std::length_error("buf[] overflow in Utils::snprintf"); throw std::length_error("buf[] overflow in Utils::snprintf");
} }

View file

@ -165,7 +165,7 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_VirtualNetw
static std::string _jsonEnumerate(unsigned int depth,const ZT_PeerPhysicalPath *pp,unsigned int count) static std::string _jsonEnumerate(unsigned int depth,const ZT_PeerPhysicalPath *pp,unsigned int count)
{ {
char json[1024]; char json[2048];
char prefix[32]; char prefix[32];
if (depth >= sizeof(prefix)) // sanity check -- shouldn't be possible if (depth >= sizeof(prefix)) // sanity check -- shouldn't be possible
@ -201,7 +201,7 @@ static std::string _jsonEnumerate(unsigned int depth,const ZT_PeerPhysicalPath *
static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_Peer *peer) static void _jsonAppend(unsigned int depth,std::string &buf,const ZT_Peer *peer)
{ {
char json[1024]; char json[2048];
char prefix[32]; char prefix[32];
if (depth >= sizeof(prefix)) // sanity check -- shouldn't be possible if (depth >= sizeof(prefix)) // sanity check -- shouldn't be possible