mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-19 11:16:32 +00:00
Make root and relay selection somewhat more robust.
This commit is contained in:
parent
00dcb0f22c
commit
4e9d430476
@ -236,15 +236,33 @@ public:
|
||||
inline uint64_t activelyTransferringFrames(uint64_t now) const throw() { return ((now - lastFrame()) < ZT_PEER_ACTIVITY_TIMEOUT); }
|
||||
|
||||
/**
|
||||
* @return Current latency or 0 if unknown (max: 65535)
|
||||
* @return Latency in milliseconds or 0 if unknown
|
||||
*/
|
||||
inline unsigned int latency() const
|
||||
throw()
|
||||
inline unsigned int latency() const { return _latency; }
|
||||
|
||||
/**
|
||||
* This computes a quality score for relays and root servers
|
||||
*
|
||||
* If we haven't heard anything from these in ZT_PEER_ACTIVITY_TIMEOUT, they
|
||||
* receive the worst possible quality (max unsigned int). Otherwise the
|
||||
* quality is a product of latency and the number of potential missed
|
||||
* pings. This causes roots and relays to switch over a bit faster if they
|
||||
* fail.
|
||||
*
|
||||
* @return Relay quality score computed from latency and other factors, lower is better
|
||||
*/
|
||||
inline unsigned int relayQuality(const uint64_t now) const
|
||||
{
|
||||
const uint64_t tsr = now - _lastReceive;
|
||||
if (tsr >= ZT_PEER_ACTIVITY_TIMEOUT)
|
||||
return (~(unsigned int)0);
|
||||
unsigned int l = _latency;
|
||||
return std::min(l,(unsigned int)65535);
|
||||
if (!l)
|
||||
l = 0xffff;
|
||||
return (l * (((unsigned int)tsr / (ZT_PEER_DIRECT_PING_DELAY + 1000)) + 1));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update latency with a new direct measurment
|
||||
*
|
||||
|
@ -741,12 +741,15 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid)
|
||||
if (!viaPath) {
|
||||
// See if this network has a preferred relay (if packet has an associated network)
|
||||
if (nconf) {
|
||||
unsigned int latency = ~((unsigned int)0);
|
||||
unsigned int bestq = ~((unsigned int)0);
|
||||
for(std::vector< std::pair<Address,InetAddress> >::const_iterator r(nconf->relays().begin());r!=nconf->relays().end();++r) {
|
||||
if (r->first != peer->address()) {
|
||||
SharedPtr<Peer> rp(RR->topology->getPeer(r->first));
|
||||
if ((rp)&&(rp->hasActiveDirectPath(now))&&(rp->latency() <= latency))
|
||||
const unsigned int q = rp->relayQuality(now);
|
||||
if ((rp)&&(q < bestq)) { // SUBTILE: < == don't use these if they are nil quality (unsigned int max), instead use a root
|
||||
bestq = q;
|
||||
rp.swap(relay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -227,33 +227,30 @@ SharedPtr<Peer> Topology::getBestRoot(const Address *avoid,unsigned int avoidCou
|
||||
|
||||
} else {
|
||||
/* If I am not a root server, the best root server is the active one with
|
||||
* the lowest latency. */
|
||||
* the lowest quality score. (lower == better) */
|
||||
|
||||
unsigned int bestLatencyOverall = ~((unsigned int)0);
|
||||
unsigned int bestLatencyNotAvoid = ~((unsigned int)0);
|
||||
unsigned int bestQualityOverall = ~((unsigned int)0);
|
||||
unsigned int bestQualityNotAvoid = ~((unsigned int)0);
|
||||
const SharedPtr<Peer> *bestOverall = (const SharedPtr<Peer> *)0;
|
||||
const SharedPtr<Peer> *bestNotAvoid = (const SharedPtr<Peer> *)0;
|
||||
|
||||
for(std::vector< SharedPtr<Peer> >::const_iterator r(_rootPeers.begin());r!=_rootPeers.end();++r) {
|
||||
if ((*r)->hasActiveDirectPath(now)) {
|
||||
bool avoiding = false;
|
||||
for(unsigned int i=0;i<avoidCount;++i) {
|
||||
if (avoid[i] == (*r)->address()) {
|
||||
avoiding = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
unsigned int l = (*r)->latency();
|
||||
if (!l) l = ~l; // zero latency indicates no measurment, so make this 'max'
|
||||
if (l <= bestLatencyOverall) {
|
||||
bestLatencyOverall = l;
|
||||
bestOverall = &(*r);
|
||||
}
|
||||
if ((!avoiding)&&(l <= bestLatencyNotAvoid)) {
|
||||
bestLatencyNotAvoid = l;
|
||||
bestNotAvoid = &(*r);
|
||||
bool avoiding = false;
|
||||
for(unsigned int i=0;i<avoidCount;++i) {
|
||||
if (avoid[i] == (*r)->address()) {
|
||||
avoiding = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const unsigned int q = (*r)->relayQuality(now);
|
||||
if (q <= bestQualityOverall) {
|
||||
bestQualityOverall = q;
|
||||
bestOverall = &(*r);
|
||||
}
|
||||
if ((!avoiding)&&(q <= bestQualityNotAvoid)) {
|
||||
bestQualityNotAvoid = q;
|
||||
bestNotAvoid = &(*r);
|
||||
}
|
||||
}
|
||||
|
||||
if (bestNotAvoid) {
|
||||
|
Loading…
Reference in New Issue
Block a user