Implement first pass on rapid dead path detection, and increment version to 1.1.3 (dev)

This commit is contained in:
Adam Ierymenko 2016-01-05 16:41:54 -08:00
parent cba739fd6b
commit d8143a5e18
11 changed files with 144 additions and 112 deletions

View file

@ -46,8 +46,8 @@ namespace ZeroTier {
// Used to send varying values for NAT keepalive
static uint32_t _natKeepaliveBuf = 0;
Peer::Peer(const Identity &myIdentity,const Identity &peerIdentity)
throw(std::runtime_error) :
Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) :
RR(renv),
_lastUsed(0),
_lastReceive(0),
_lastUnicastFrame(0),
@ -72,7 +72,6 @@ Peer::Peer(const Identity &myIdentity,const Identity &peerIdentity)
}
void Peer::received(
const RuntimeEnvironment *RR,
const InetAddress &localAddr,
const InetAddress &remoteAddr,
unsigned int hops,
@ -199,7 +198,7 @@ void Peer::received(
outp.armor(_key,true);
RR->node->putPacket(localAddr,remoteAddr,outp.data(),outp.size());
} else {
sendHELLO(RR,localAddr,remoteAddr,now);
sendHELLO(localAddr,remoteAddr,now);
}
}
@ -214,7 +213,7 @@ void Peer::received(
}
}
void Peer::sendHELLO(const RuntimeEnvironment *RR,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int ttl)
void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int ttl)
{
// _lock not required here since _id is immutable and nothing else is accessed
@ -234,7 +233,7 @@ void Peer::sendHELLO(const RuntimeEnvironment *RR,const InetAddress &localAddr,c
RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size(),ttl);
}
bool Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now,int inetAddressFamily)
bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily)
{
Path *p = (Path *)0;
@ -248,7 +247,7 @@ bool Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now,int inet
if (p) {
if ((now - p->lastReceived()) >= ZT_PEER_DIRECT_PING_DELAY) {
//TRACE("PING %s(%s) after %llums/%llums send/receive inactivity",_id.address().toString().c_str(),p->address().toString().c_str(),now - p->lastSend(),now - p->lastReceived());
sendHELLO(RR,p->localAddress(),p->address(),now);
sendHELLO(p->localAddress(),p->address(),now);
p->sent(now);
} else if (((now - p->lastSend()) >= ZT_NAT_KEEPALIVE_DELAY)&&(!p->reliable())) {
//TRACE("NAT keepalive %s(%s) after %llums/%llums send/receive inactivity",_id.address().toString().c_str(),p->address().toString().c_str(),now - p->lastSend(),now - p->lastReceived());
@ -264,7 +263,7 @@ bool Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now,int inet
return false;
}
void Peer::pushDirectPaths(const RuntimeEnvironment *RR,Path *path,uint64_t now,bool force)
void Peer::pushDirectPaths(Path *path,uint64_t now,bool force)
{
#ifdef ZT_ENABLE_CLUSTER
// Cluster mode disables normal PUSH_DIRECT_PATHS in favor of cluster-based peer redirection
@ -332,7 +331,7 @@ void Peer::pushDirectPaths(const RuntimeEnvironment *RR,Path *path,uint64_t now,
}
}
bool Peer::resetWithinScope(const RuntimeEnvironment *RR,InetAddress::IpScope scope,uint64_t now)
bool Peer::resetWithinScope(InetAddress::IpScope scope,uint64_t now)
{
Mutex::Lock _l(_lock);
unsigned int np = _numPaths;
@ -340,7 +339,7 @@ bool Peer::resetWithinScope(const RuntimeEnvironment *RR,InetAddress::IpScope sc
unsigned int y = 0;
while (x < np) {
if (_paths[x].address().ipScope() == scope) {
sendHELLO(RR,_paths[x].localAddress(),_paths[x].address(),now);
sendHELLO(_paths[x].localAddress(),_paths[x].address(),now);
} else {
_paths[y++] = _paths[x];
}
@ -383,7 +382,7 @@ bool Peer::networkMembershipCertificatesAgree(uint64_t nwid,const CertificateOfM
return false;
}
bool Peer::validateAndSetNetworkMembershipCertificate(const RuntimeEnvironment *RR,uint64_t nwid,const CertificateOfMembership &com)
bool Peer::validateAndSetNetworkMembershipCertificate(uint64_t nwid,const CertificateOfMembership &com)
{
// Sanity checks
if ((!com)||(com.issuedTo() != _id.address()))
@ -448,7 +447,7 @@ bool Peer::needsOurNetworkMembershipCertificate(uint64_t nwid,uint64_t now,bool
return ((now - tmp) >= (ZT_NETWORK_AUTOCONF_DELAY / 2));
}
void Peer::clean(const RuntimeEnvironment *RR,uint64_t now)
void Peer::clean(uint64_t now)
{
Mutex::Lock _l(_lock);
@ -485,6 +484,34 @@ void Peer::clean(const RuntimeEnvironment *RR,uint64_t now)
}
}
bool Peer::_checkPath(Path &p,const uint64_t now)
{
// assumes _lock is locked
if (!p.active(now))
return false;
if (p.lastSend() > p.lastReceived()) {
if ((p.lastSend() - p.lastReceived()) >= ZT_PEER_DEAD_PATH_DETECTION_NO_ANSWER_TIMEOUT) {
TRACE("%s(%s) has not answered, checking if dead (probation: %u)",_id.address().toString().c_str(),p.address().toString().c_str(),p.probation());
if ( (_vProto >= 5) && ( !((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0)) ) ) {
// 1.1.1 and newer nodes support ECHO, which is smaller -- but 1.1.0 has a bug so use HELLO there too
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO);
outp.armor(_key,true);
p.send(RR,outp.data(),outp.size(),now);
} else {
sendHELLO(p.localAddress(),p.address(),now);
p.sent(now);
}
p.increaseProbation();
}
}
return true;
}
Path *Peer::_getBestPath(const uint64_t now)
{
// assumes _lock is locked
@ -492,7 +519,7 @@ Path *Peer::_getBestPath(const uint64_t now)
uint64_t bestPathScore = 0;
for(unsigned int i=0;i<_numPaths;++i) {
const uint64_t score = _paths[i].score();
if ((score >= bestPathScore)&&(_paths[i].active(now))) {
if ((score >= bestPathScore)&&(_checkPath(_paths[i],now))) {
bestPathScore = score;
bestPath = &(_paths[i]);
}
@ -507,7 +534,7 @@ Path *Peer::_getBestPath(const uint64_t now,int inetAddressFamily)
uint64_t bestPathScore = 0;
for(unsigned int i=0;i<_numPaths;++i) {
const uint64_t score = _paths[i].score();
if (((int)_paths[i].address().ss_family == inetAddressFamily)&&(score >= bestPathScore)&&(_paths[i].active(now))) {
if (((int)_paths[i].address().ss_family == inetAddressFamily)&&(score >= bestPathScore)&&(_checkPath(_paths[i],now))) {
bestPathScore = score;
bestPath = &(_paths[i]);
}