mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 03:53:44 +02:00
Make root and relay selection somewhat more robust.
This commit is contained in:
parent
00dcb0f22c
commit
4e9d430476
3 changed files with 44 additions and 26 deletions
|
@ -236,15 +236,33 @@ public:
|
||||||
inline uint64_t activelyTransferringFrames(uint64_t now) const throw() { return ((now - lastFrame()) < ZT_PEER_ACTIVITY_TIMEOUT); }
|
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
|
inline unsigned int latency() const { return _latency; }
|
||||||
throw()
|
|
||||||
|
/**
|
||||||
|
* 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;
|
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
|
* Update latency with a new direct measurment
|
||||||
*
|
*
|
||||||
|
|
|
@ -741,12 +741,15 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid)
|
||||||
if (!viaPath) {
|
if (!viaPath) {
|
||||||
// See if this network has a preferred relay (if packet has an associated network)
|
// See if this network has a preferred relay (if packet has an associated network)
|
||||||
if (nconf) {
|
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) {
|
for(std::vector< std::pair<Address,InetAddress> >::const_iterator r(nconf->relays().begin());r!=nconf->relays().end();++r) {
|
||||||
if (r->first != peer->address()) {
|
if (r->first != peer->address()) {
|
||||||
SharedPtr<Peer> rp(RR->topology->getPeer(r->first));
|
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);
|
rp.swap(relay);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,33 +227,30 @@ SharedPtr<Peer> Topology::getBestRoot(const Address *avoid,unsigned int avoidCou
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* If I am not a root server, the best root server is the active one with
|
/* 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 bestQualityOverall = ~((unsigned int)0);
|
||||||
unsigned int bestLatencyNotAvoid = ~((unsigned int)0);
|
unsigned int bestQualityNotAvoid = ~((unsigned int)0);
|
||||||
const SharedPtr<Peer> *bestOverall = (const SharedPtr<Peer> *)0;
|
const SharedPtr<Peer> *bestOverall = (const SharedPtr<Peer> *)0;
|
||||||
const SharedPtr<Peer> *bestNotAvoid = (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) {
|
for(std::vector< SharedPtr<Peer> >::const_iterator r(_rootPeers.begin());r!=_rootPeers.end();++r) {
|
||||||
if ((*r)->hasActiveDirectPath(now)) {
|
bool avoiding = false;
|
||||||
bool avoiding = false;
|
for(unsigned int i=0;i<avoidCount;++i) {
|
||||||
for(unsigned int i=0;i<avoidCount;++i) {
|
if (avoid[i] == (*r)->address()) {
|
||||||
if (avoid[i] == (*r)->address()) {
|
avoiding = true;
|
||||||
avoiding = true;
|
break;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const unsigned int q = (*r)->relayQuality(now);
|
||||||
|
if (q <= bestQualityOverall) {
|
||||||
|
bestQualityOverall = q;
|
||||||
|
bestOverall = &(*r);
|
||||||
|
}
|
||||||
|
if ((!avoiding)&&(q <= bestQualityNotAvoid)) {
|
||||||
|
bestQualityNotAvoid = q;
|
||||||
|
bestNotAvoid = &(*r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bestNotAvoid) {
|
if (bestNotAvoid) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue