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; }
/**
* @return Preference rank, higher == better (will be less than 255)
* @return Preference rank, higher == better
*/
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) );
}
@ -213,7 +207,7 @@ public:
/**
* @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

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) {
Mutex::Lock _l(_paths_m);
unsigned int slot = 0;
unsigned int slot;
if (_numPaths < ZT_MAX_PEER_NETWORK_PATHS) {
slot = _numPaths++;
} else {
// First try to replace the worst within the same address family, if possible
int worstSlot = -1;
uint64_t worstScore = 0xffffffffffffffffULL;
unsigned int worstPath = 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;
worstPath = p;
if (_paths[p].path->address().ss_family == path->address().ss_family) {
const uint64_t s = _pathScore(p);
if (s < worstScore) {
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;
@ -164,20 +178,21 @@ void Peer::received(
_paths[slot].clusterWeights = 1;
#endif
} else {
TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),remoteAddr.toString().c_str());
TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),path->address().toString().c_str());
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);
outp.armor(_key,true);
path->send(RR,outp.data(),outp.size(),now);
} else {
// For backward compatibility we send HELLO to ancient nodes
sendHELLO(path->localAddress(),path->address(),now);
}
}
}
} else if (trustEstablished) {
// Send PUSH_DIRECT_PATHS if hops>0 (relayed) and we have a trust relationship (common network membership)
_pushDirectPaths(path,now);
}
@ -286,7 +301,7 @@ bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily)
int bestp = -1;
uint64_t best = 0ULL;
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);
if (s >= best) {
best = s;

View File

@ -164,7 +164,7 @@ public:
*
* @param now Current time
* @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);
@ -367,7 +367,7 @@ private:
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].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 (len)
buf[len - 1] = (char)0;
abort();
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)
{
char json[1024];
char json[2048];
char prefix[32];
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)
{
char json[1024];
char json[2048];
char prefix[32];
if (depth >= sizeof(prefix)) // sanity check -- shouldn't be possible