mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-21 05:53:09 +00:00
Cleanup in numerous places, reduce network chattiness around MULTICAST_LIKE, and fix a "how was that working" latent bug causing some control traffic to take the scenic route.
This commit is contained in:
parent
affbca74b4
commit
2f18a92e20
@ -710,7 +710,7 @@ bool Cluster::findBetterEndpoint(InetAddress &redirectTo,const Address &peerAddr
|
|||||||
// Pick based on location if it can be determined
|
// Pick based on location if it can be determined
|
||||||
int px = 0,py = 0,pz = 0;
|
int px = 0,py = 0,pz = 0;
|
||||||
if (_addressToLocationFunction(_addressToLocationFunctionArg,reinterpret_cast<const struct sockaddr_storage *>(&peerPhysicalAddress),&px,&py,&pz) == 0) {
|
if (_addressToLocationFunction(_addressToLocationFunctionArg,reinterpret_cast<const struct sockaddr_storage *>(&peerPhysicalAddress),&px,&py,&pz) == 0) {
|
||||||
TRACE("no geolocation data for %s (geo-lookup is lazy/async so it may work next time)",peerPhysicalAddress.toIpString().c_str());
|
TRACE("no geolocation data for %s",peerPhysicalAddress.toIpString().c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@
|
|||||||
/**
|
/**
|
||||||
* No answer timeout to trigger dead path detection
|
* No answer timeout to trigger dead path detection
|
||||||
*/
|
*/
|
||||||
#define ZT_PEER_DEAD_PATH_DETECTION_NO_ANSWER_TIMEOUT 2500
|
#define ZT_PEER_DEAD_PATH_DETECTION_NO_ANSWER_TIMEOUT 2000
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Probation threshold after which a path becomes dead
|
* Probation threshold after which a path becomes dead
|
||||||
|
@ -71,6 +71,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,bool deferred)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Packet::Verb v = verb();
|
const Packet::Verb v = verb();
|
||||||
|
//if (RR->topology->isRoot(peer->identity())) printf("<< %s from %s(%s)\n",Packet::verbString(v),sourceAddress.toString().c_str(),_remoteAddress.toString().c_str());
|
||||||
//TRACE("<< %s from %s(%s)",Packet::verbString(v),sourceAddress.toString().c_str(),_remoteAddress.toString().c_str());
|
//TRACE("<< %s from %s(%s)",Packet::verbString(v),sourceAddress.toString().c_str(),_remoteAddress.toString().c_str());
|
||||||
switch(v) {
|
switch(v) {
|
||||||
//case Packet::VERB_NOP:
|
//case Packet::VERB_NOP:
|
||||||
@ -349,6 +350,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
|
|||||||
const uint64_t inRePacketId = at<uint64_t>(ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID);
|
const uint64_t inRePacketId = at<uint64_t>(ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID);
|
||||||
|
|
||||||
//TRACE("%s(%s): OK(%s)",source().toString().c_str(),_remoteAddress.toString().c_str(),Packet::verbString(inReVerb));
|
//TRACE("%s(%s): OK(%s)",source().toString().c_str(),_remoteAddress.toString().c_str(),Packet::verbString(inReVerb));
|
||||||
|
//if (RR->topology->isRoot(peer->identity())) printf("%s(%s): OK(%s)\n",source().toString().c_str(),_remoteAddress.toString().c_str(),Packet::verbString(inReVerb));
|
||||||
|
|
||||||
switch(inReVerb) {
|
switch(inReVerb) {
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ bool Network::tryAnnounceMulticastGroupsTo(const SharedPtr<Peer> &peer)
|
|||||||
(peer->address() == this->controller()) ||
|
(peer->address() == this->controller()) ||
|
||||||
(RR->topology->isRoot(peer->identity()))
|
(RR->topology->isRoot(peer->identity()))
|
||||||
) {
|
) {
|
||||||
_announceMulticastGroupsTo(peer->address(),_allMulticastGroups());
|
_announceMulticastGroupsTo(peer,_allMulticastGroups());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -400,10 +400,10 @@ bool Network::_isAllowed(const SharedPtr<Peer> &peer) const
|
|||||||
return false; // default position on any failure
|
return false; // default position on any failure
|
||||||
}
|
}
|
||||||
|
|
||||||
class _GetPeersThatNeedMulticastAnnouncement
|
class _MulticastAnnounceAll
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
_GetPeersThatNeedMulticastAnnouncement(const RuntimeEnvironment *renv,Network *nw) :
|
_MulticastAnnounceAll(const RuntimeEnvironment *renv,Network *nw) :
|
||||||
_now(renv->node->now()),
|
_now(renv->node->now()),
|
||||||
_controller(nw->controller()),
|
_controller(nw->controller()),
|
||||||
_network(nw),
|
_network(nw),
|
||||||
@ -416,47 +416,45 @@ public:
|
|||||||
(p->address() == _controller) ||
|
(p->address() == _controller) ||
|
||||||
(std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end())
|
(std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end())
|
||||||
) {
|
) {
|
||||||
peers.push_back(p->address());
|
peers.push_back(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<Address> peers;
|
std::vector< SharedPtr<Peer> > peers;
|
||||||
private:
|
private:
|
||||||
uint64_t _now;
|
const uint64_t _now;
|
||||||
Address _controller;
|
const Address _controller;
|
||||||
Network *_network;
|
Network *const _network;
|
||||||
std::vector<Address> _rootAddresses;
|
const std::vector<Address> _rootAddresses;
|
||||||
};
|
};
|
||||||
void Network::_announceMulticastGroups()
|
void Network::_announceMulticastGroups()
|
||||||
{
|
{
|
||||||
// Assumes _lock is locked
|
// Assumes _lock is locked
|
||||||
|
_MulticastAnnounceAll gpfunc(RR,this);
|
||||||
_GetPeersThatNeedMulticastAnnouncement gpfunc(RR,this);
|
RR->topology->eachPeer<_MulticastAnnounceAll &>(gpfunc);
|
||||||
RR->topology->eachPeer<_GetPeersThatNeedMulticastAnnouncement &>(gpfunc);
|
|
||||||
|
|
||||||
std::vector<MulticastGroup> allMulticastGroups(_allMulticastGroups());
|
std::vector<MulticastGroup> allMulticastGroups(_allMulticastGroups());
|
||||||
for(std::vector<Address>::const_iterator pa(gpfunc.peers.begin());pa!=gpfunc.peers.end();++pa)
|
for(std::vector< SharedPtr<Peer> >::const_iterator i(gpfunc.peers.begin());i!=gpfunc.peers.end();++i)
|
||||||
_announceMulticastGroupsTo(*pa,allMulticastGroups);
|
_announceMulticastGroupsTo(*i,allMulticastGroups);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Network::_announceMulticastGroupsTo(const Address &peerAddress,const std::vector<MulticastGroup> &allMulticastGroups) const
|
void Network::_announceMulticastGroupsTo(const SharedPtr<Peer> &peer,const std::vector<MulticastGroup> &allMulticastGroups) const
|
||||||
{
|
{
|
||||||
// Assumes _lock is locked
|
// Assumes _lock is locked
|
||||||
|
|
||||||
// We push COMs ahead of MULTICAST_LIKE since they're used for access control -- a COM is a public
|
// We push COMs ahead of MULTICAST_LIKE since they're used for access control -- a COM is a public
|
||||||
// credential so "over-sharing" isn't really an issue (and we only do so with roots).
|
// credential so "over-sharing" isn't really an issue (and we only do so with roots).
|
||||||
if ((_config)&&(_config.com())&&(!_config.isPublic())) {
|
if ((_config)&&(_config.com())&&(!_config.isPublic())&&(peer->needsOurNetworkMembershipCertificate(_id,RR->node->now(),true))) {
|
||||||
Packet outp(peerAddress,RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE);
|
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE);
|
||||||
_config.com().serialize(outp);
|
_config.com().serialize(outp);
|
||||||
RR->sw->send(outp,true,0);
|
RR->sw->send(outp,true,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Packet outp(peerAddress,RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
|
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
|
||||||
|
|
||||||
for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) {
|
for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) {
|
||||||
if ((outp.size() + 18) >= ZT_UDP_DEFAULT_PAYLOAD_MTU) {
|
if ((outp.size() + 18) >= ZT_UDP_DEFAULT_PAYLOAD_MTU) {
|
||||||
RR->sw->send(outp,true,0);
|
RR->sw->send(outp,true,0);
|
||||||
outp.reset(peerAddress,RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
|
outp.reset(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// network ID, MAC, ADI
|
// network ID, MAC, ADI
|
||||||
|
@ -47,7 +47,7 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
class RuntimeEnvironment;
|
class RuntimeEnvironment;
|
||||||
class Peer;
|
class Peer;
|
||||||
class _GetPeersThatNeedMulticastAnnouncement;
|
class _MulticastAnnounceAll;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A virtual LAN
|
* A virtual LAN
|
||||||
@ -55,7 +55,7 @@ class _GetPeersThatNeedMulticastAnnouncement;
|
|||||||
class Network : NonCopyable
|
class Network : NonCopyable
|
||||||
{
|
{
|
||||||
friend class SharedPtr<Network>;
|
friend class SharedPtr<Network>;
|
||||||
friend class _GetPeersThatNeedMulticastAnnouncement; // internal function object
|
friend class _MulticastAnnounceAll; // internal function object
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -317,9 +317,8 @@ private:
|
|||||||
ZT_VirtualNetworkStatus _status() const;
|
ZT_VirtualNetworkStatus _status() const;
|
||||||
void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
|
void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
|
||||||
bool _isAllowed(const SharedPtr<Peer> &peer) const;
|
bool _isAllowed(const SharedPtr<Peer> &peer) const;
|
||||||
bool _tryAnnounceMulticastGroupsTo(const std::vector<Address> &rootAddresses,const std::vector<MulticastGroup> &allMulticastGroups,const SharedPtr<Peer> &peer,uint64_t now) const;
|
|
||||||
void _announceMulticastGroups();
|
void _announceMulticastGroups();
|
||||||
void _announceMulticastGroupsTo(const Address &peerAddress,const std::vector<MulticastGroup> &allMulticastGroups) const;
|
void _announceMulticastGroupsTo(const SharedPtr<Peer> &peer,const std::vector<MulticastGroup> &allMulticastGroups) const;
|
||||||
std::vector<MulticastGroup> _allMulticastGroups() const;
|
std::vector<MulticastGroup> _allMulticastGroups() const;
|
||||||
|
|
||||||
const RuntimeEnvironment *RR;
|
const RuntimeEnvironment *RR;
|
||||||
|
@ -191,7 +191,7 @@ public:
|
|||||||
|
|
||||||
// If this is a world root, pick (if possible) both an IPv4 and an IPv6 stable endpoint to use if link isn't currently alive.
|
// If this is a world root, pick (if possible) both an IPv4 and an IPv6 stable endpoint to use if link isn't currently alive.
|
||||||
for(std::vector<World::Root>::const_iterator r(_world.roots().begin());r!=_world.roots().end();++r) {
|
for(std::vector<World::Root>::const_iterator r(_world.roots().begin());r!=_world.roots().end();++r) {
|
||||||
if (r->identity.address() == p->address()) {
|
if (r->identity == p->identity()) {
|
||||||
upstream = true;
|
upstream = true;
|
||||||
for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)r->stableEndpoints.size();++k) {
|
for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)r->stableEndpoints.size();++k) {
|
||||||
const InetAddress &addr = r->stableEndpoints[ptr++ % r->stableEndpoints.size()];
|
const InetAddress &addr = r->stableEndpoints[ptr++ % r->stableEndpoints.size()];
|
||||||
|
@ -19,11 +19,25 @@
|
|||||||
#include "Path.hpp"
|
#include "Path.hpp"
|
||||||
#include "RuntimeEnvironment.hpp"
|
#include "RuntimeEnvironment.hpp"
|
||||||
#include "Node.hpp"
|
#include "Node.hpp"
|
||||||
|
//#include "Topology.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
bool Path::send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now)
|
bool Path::send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
if (len > 13) {
|
||||||
|
Address zta(reinterpret_cast<const uint8_t *>(data)+8,5);
|
||||||
|
if ((zta.toInt() == 0x9d219039f3ULL)||(zta.toInt() == 0x8841408a2eULL)) {
|
||||||
|
printf(">> %s@%s %u ",zta.toString().c_str(),address().toString().c_str(),len);
|
||||||
|
Packet pcopy(data,len);
|
||||||
|
SharedPtr<Peer> rp(RR->topology->getPeer(zta));
|
||||||
|
if (pcopy.dearmor(rp->key())) {
|
||||||
|
printf("%s\n",Packet::verbString(pcopy.verb()));
|
||||||
|
} else printf("!!!!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
if (RR->node->putPacket(_localAddress,address(),data,len)) {
|
if (RR->node->putPacket(_localAddress,address(),data,len)) {
|
||||||
sent(now);
|
sent(now);
|
||||||
return true;
|
return true;
|
||||||
|
@ -28,6 +28,9 @@
|
|||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "InetAddress.hpp"
|
#include "InetAddress.hpp"
|
||||||
|
|
||||||
|
// Note: if you change these flags check the logic below. Some of it depends
|
||||||
|
// on these bits being what they are.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag indicating that this path is suboptimal
|
* Flag indicating that this path is suboptimal
|
||||||
*
|
*
|
||||||
@ -133,9 +136,8 @@ public:
|
|||||||
* @return True if this path appears active
|
* @return True if this path appears active
|
||||||
*/
|
*/
|
||||||
inline bool active(uint64_t now) const
|
inline bool active(uint64_t now) const
|
||||||
throw()
|
|
||||||
{
|
{
|
||||||
return (((now - _lastReceived) < ZT_PATH_ACTIVITY_TIMEOUT)&&(_probation < ZT_PEER_DEAD_PATH_DETECTION_MAX_PROBATION));
|
return ( ((now - _lastReceived) < ZT_PATH_ACTIVITY_TIMEOUT) && (_probation < ZT_PEER_DEAD_PATH_DETECTION_MAX_PROBATION) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -221,20 +223,27 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return This path's overall score (higher == better)
|
* @return This path's overall quality score (higher is better)
|
||||||
*/
|
*/
|
||||||
inline uint64_t score() const throw()
|
inline uint64_t score() const throw()
|
||||||
{
|
{
|
||||||
/* We compute the score based on the "freshness" of the path (when we last
|
// This is a little bit convoluted because we try to be branch-free, using multiplication instead of branches for boolean flags
|
||||||
* received something) scaled/corrected by the preference rank within the
|
|
||||||
* ping keepalive window. That way higher ranking paths are preferred but
|
// Start with the last time this path was active, and add a fudge factor to prevent integer underflow if _lastReceived is 0
|
||||||
* not to the point of overriding timeouts and choosing potentially dead
|
uint64_t score = _lastReceived + (ZT_PEER_DIRECT_PING_DELAY * (ZT_PEER_DEAD_PATH_DETECTION_MAX_PROBATION + 1));
|
||||||
* paths. Finally we increase the score for known to be cluster optimal
|
|
||||||
* paths and decrease it for paths known to be suboptimal. */
|
// Increase score based on path preference rank, which is based on IP scope and address family
|
||||||
uint64_t score = _lastReceived + ZT_PEER_DIRECT_PING_DELAY; // make sure it's never less than ZT_PEER_DIRECT_PING_DELAY to prevent integer underflow
|
|
||||||
score += preferenceRank() * (ZT_PEER_DIRECT_PING_DELAY / ZT_PATH_MAX_PREFERENCE_RANK);
|
score += preferenceRank() * (ZT_PEER_DIRECT_PING_DELAY / ZT_PATH_MAX_PREFERENCE_RANK);
|
||||||
|
|
||||||
|
// Increase score if this is known to be an optimal path to a cluster
|
||||||
score += (uint64_t)(_flags & ZT_PATH_FLAG_CLUSTER_OPTIMAL) * (ZT_PEER_DIRECT_PING_DELAY / 2); // /2 because CLUSTER_OPTIMAL is flag 0x0002
|
score += (uint64_t)(_flags & ZT_PATH_FLAG_CLUSTER_OPTIMAL) * (ZT_PEER_DIRECT_PING_DELAY / 2); // /2 because CLUSTER_OPTIMAL is flag 0x0002
|
||||||
|
|
||||||
|
// Decrease score if this is known to be a sub-optimal path to a cluster
|
||||||
score -= (uint64_t)(_flags & ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL) * ZT_PEER_DIRECT_PING_DELAY;
|
score -= (uint64_t)(_flags & ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL) * ZT_PEER_DIRECT_PING_DELAY;
|
||||||
|
|
||||||
|
// Penalize for missed ECHO tests in dead path detection
|
||||||
|
score -= (uint64_t)((ZT_PEER_DIRECT_PING_DELAY / 2) * _probation);
|
||||||
|
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ void Peer::received(
|
|||||||
// Note: findBetterEndpoint() is first since we still want to check
|
// Note: findBetterEndpoint() is first since we still want to check
|
||||||
// for a better endpoint even if we don't actually send a redirect.
|
// for a better endpoint even if we don't actually send a redirect.
|
||||||
InetAddress redirectTo;
|
InetAddress redirectTo;
|
||||||
if ( (RR->cluster->findBetterEndpoint(redirectTo,_id.address(),remoteAddr,false)) && (verb != Packet::VERB_OK)&&(verb != Packet::VERB_ERROR)&&(verb != Packet::VERB_RENDEZVOUS)&&(verb != Packet::VERB_PUSH_DIRECT_PATHS) ) {
|
if ( (verb != Packet::VERB_OK) && (verb != Packet::VERB_ERROR) && (verb != Packet::VERB_RENDEZVOUS) && (verb != Packet::VERB_PUSH_DIRECT_PATHS) && (RR->cluster->findBetterEndpoint(redirectTo,_id.address(),remoteAddr,false)) ) {
|
||||||
if (_vProto >= 5) {
|
if (_vProto >= 5) {
|
||||||
// For newer peers we can send a more idiomatic verb: PUSH_DIRECT_PATHS.
|
// For newer peers we can send a more idiomatic verb: PUSH_DIRECT_PATHS.
|
||||||
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS);
|
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS);
|
||||||
@ -243,7 +243,7 @@ bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Peer::pushDirectPaths(const InetAddress &localAddr,const InetAddress &toAddress,uint64_t now,bool force)
|
bool Peer::pushDirectPaths(const InetAddress &localAddr,const InetAddress &toAddress,uint64_t now,bool force,bool includePrivatePaths)
|
||||||
{
|
{
|
||||||
#ifdef ZT_ENABLE_CLUSTER
|
#ifdef ZT_ENABLE_CLUSTER
|
||||||
// Cluster mode disables normal PUSH_DIRECT_PATHS in favor of cluster-based peer redirection
|
// Cluster mode disables normal PUSH_DIRECT_PATHS in favor of cluster-based peer redirection
|
||||||
@ -257,38 +257,45 @@ bool Peer::pushDirectPaths(const InetAddress &localAddr,const InetAddress &toAdd
|
|||||||
else _lastDirectPathPushSent = now;
|
else _lastDirectPathPushSent = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<InetAddress> pathsToPush;
|
||||||
|
|
||||||
std::vector<InetAddress> dps(RR->node->directPaths());
|
std::vector<InetAddress> dps(RR->node->directPaths());
|
||||||
|
for(std::vector<InetAddress>::const_iterator i(dps.begin());i!=dps.end();++i) {
|
||||||
|
if ((includePrivatePaths)||(i->ipScope() == InetAddress::IP_SCOPE_GLOBAL))
|
||||||
|
pathsToPush.push_back(*i);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<InetAddress> sym(RR->sa->getSymmetricNatPredictions());
|
std::vector<InetAddress> sym(RR->sa->getSymmetricNatPredictions());
|
||||||
for(unsigned long i=0,added=0;i<sym.size();++i) {
|
for(unsigned long i=0,added=0;i<sym.size();++i) {
|
||||||
InetAddress tmp(sym[(unsigned long)RR->node->prng() % sym.size()]);
|
InetAddress tmp(sym[(unsigned long)RR->node->prng() % sym.size()]);
|
||||||
if (std::find(dps.begin(),dps.end(),tmp) == dps.end()) {
|
if (std::find(pathsToPush.begin(),pathsToPush.end(),tmp) == pathsToPush.end()) {
|
||||||
dps.push_back(tmp);
|
pathsToPush.push_back(tmp);
|
||||||
if (++added >= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY)
|
if (++added >= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dps.empty())
|
if (pathsToPush.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
#ifdef ZT_TRACE
|
#ifdef ZT_TRACE
|
||||||
{
|
{
|
||||||
std::string ps;
|
std::string ps;
|
||||||
for(std::vector<InetAddress>::const_iterator p(dps.begin());p!=dps.end();++p) {
|
for(std::vector<InetAddress>::const_iterator p(pathsToPush.begin());p!=pathsToPush.end();++p) {
|
||||||
if (ps.length() > 0)
|
if (ps.length() > 0)
|
||||||
ps.push_back(',');
|
ps.push_back(',');
|
||||||
ps.append(p->toString());
|
ps.append(p->toString());
|
||||||
}
|
}
|
||||||
TRACE("pushing %u direct paths to %s: %s",(unsigned int)dps.size(),_id.address().toString().c_str(),ps.c_str());
|
TRACE("pushing %u direct paths to %s: %s",(unsigned int)pathsToPush.size(),_id.address().toString().c_str(),ps.c_str());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::vector<InetAddress>::const_iterator p(dps.begin());
|
std::vector<InetAddress>::const_iterator p(pathsToPush.begin());
|
||||||
while (p != dps.end()) {
|
while (p != pathsToPush.end()) {
|
||||||
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS);
|
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS);
|
||||||
outp.addSize(2); // leave room for count
|
outp.addSize(2); // leave room for count
|
||||||
|
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
while ((p != dps.end())&&((outp.size() + 24) < 1200)) {
|
while ((p != pathsToPush.end())&&((outp.size() + 24) < 1200)) {
|
||||||
uint8_t addressType = 4;
|
uint8_t addressType = 4;
|
||||||
switch(p->ss_family) {
|
switch(p->ss_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
@ -475,11 +482,8 @@ void Peer::clean(uint64_t now)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Peer::_checkPath(Path &p,const uint64_t now)
|
void Peer::_doDeadPathDetection(Path &p,const uint64_t now)
|
||||||
{
|
{
|
||||||
if (!p.active(now))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Dead path detection: if we have sent something to this peer and have not
|
/* Dead path detection: if we have sent something to this peer and have not
|
||||||
* yet received a reply, double check this path. The majority of outbound
|
* yet received a reply, double check this path. The majority of outbound
|
||||||
* packets including Ethernet frames do generate some kind of reply either
|
* packets including Ethernet frames do generate some kind of reply either
|
||||||
@ -499,6 +503,7 @@ bool Peer::_checkPath(Path &p,const uint64_t now)
|
|||||||
(p.lastSend() > p.lastReceived()) &&
|
(p.lastSend() > p.lastReceived()) &&
|
||||||
((p.lastSend() - p.lastReceived()) >= ZT_PEER_DEAD_PATH_DETECTION_NO_ANSWER_TIMEOUT) &&
|
((p.lastSend() - p.lastReceived()) >= ZT_PEER_DEAD_PATH_DETECTION_NO_ANSWER_TIMEOUT) &&
|
||||||
((now - p.lastPing()) >= ZT_PEER_DEAD_PATH_DETECTION_NO_ANSWER_TIMEOUT) &&
|
((now - p.lastPing()) >= ZT_PEER_DEAD_PATH_DETECTION_NO_ANSWER_TIMEOUT) &&
|
||||||
|
(!p.isClusterSuboptimal()) &&
|
||||||
(!RR->topology->amRoot())
|
(!RR->topology->amRoot())
|
||||||
) {
|
) {
|
||||||
TRACE("%s(%s) does not seem to be answering in a timely manner, checking if dead (probation == %u)",_id.address().toString().c_str(),p.address().toString().c_str(),p.probation());
|
TRACE("%s(%s) does not seem to be answering in a timely manner, checking if dead (probation == %u)",_id.address().toString().c_str(),p.address().toString().c_str(),p.probation());
|
||||||
@ -516,8 +521,6 @@ bool Peer::_checkPath(Path &p,const uint64_t now)
|
|||||||
|
|
||||||
p.increaseProbation();
|
p.increaseProbation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Path *Peer::_getBestPath(const uint64_t now)
|
Path *Peer::_getBestPath(const uint64_t now)
|
||||||
@ -526,11 +529,13 @@ Path *Peer::_getBestPath(const uint64_t now)
|
|||||||
uint64_t bestPathScore = 0;
|
uint64_t bestPathScore = 0;
|
||||||
for(unsigned int i=0;i<_numPaths;++i) {
|
for(unsigned int i=0;i<_numPaths;++i) {
|
||||||
const uint64_t score = _paths[i].score();
|
const uint64_t score = _paths[i].score();
|
||||||
if ((score >= bestPathScore)&&(_checkPath(_paths[i],now))) {
|
if ((score >= bestPathScore)&&(_paths[i].active(now))) {
|
||||||
bestPathScore = score;
|
bestPathScore = score;
|
||||||
bestPath = &(_paths[i]);
|
bestPath = &(_paths[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (bestPath)
|
||||||
|
_doDeadPathDetection(*bestPath,now);
|
||||||
return bestPath;
|
return bestPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,11 +545,13 @@ Path *Peer::_getBestPath(const uint64_t now,int inetAddressFamily)
|
|||||||
uint64_t bestPathScore = 0;
|
uint64_t bestPathScore = 0;
|
||||||
for(unsigned int i=0;i<_numPaths;++i) {
|
for(unsigned int i=0;i<_numPaths;++i) {
|
||||||
const uint64_t score = _paths[i].score();
|
const uint64_t score = _paths[i].score();
|
||||||
if (((int)_paths[i].address().ss_family == inetAddressFamily)&&(score >= bestPathScore)&&(_checkPath(_paths[i],now))) {
|
if (((int)_paths[i].address().ss_family == inetAddressFamily)&&(score >= bestPathScore)&&(_paths[i].active(now))) {
|
||||||
bestPathScore = score;
|
bestPathScore = score;
|
||||||
bestPath = &(_paths[i]);
|
bestPath = &(_paths[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (bestPath)
|
||||||
|
_doDeadPathDetection(*bestPath,now);
|
||||||
return bestPath;
|
return bestPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,9 +204,10 @@ public:
|
|||||||
* @param toAddress Remote address to send push to (usually from path)
|
* @param toAddress Remote address to send push to (usually from path)
|
||||||
* @param now Current time
|
* @param now Current time
|
||||||
* @param force If true, push regardless of rate limit
|
* @param force If true, push regardless of rate limit
|
||||||
|
* @param includePrivatePaths If true, include local interface address paths (should only be done to peers with a trust relationship)
|
||||||
* @return True if something was actually sent
|
* @return True if something was actually sent
|
||||||
*/
|
*/
|
||||||
bool pushDirectPaths(const InetAddress &localAddr,const InetAddress &toAddress,uint64_t now,bool force);
|
bool pushDirectPaths(const InetAddress &localAddr,const InetAddress &toAddress,uint64_t now,bool force,bool includePrivatePaths);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return All known direct paths to this peer (active or inactive)
|
* @return All known direct paths to this peer (active or inactive)
|
||||||
@ -560,7 +561,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _checkPath(Path &p,const uint64_t now);
|
void _doDeadPathDetection(Path &p,const uint64_t now);
|
||||||
Path *_getBestPath(const uint64_t now);
|
Path *_getBestPath(const uint64_t now);
|
||||||
Path *_getBestPath(const uint64_t now,int inetAddressFamily);
|
Path *_getBestPath(const uint64_t now,int inetAddressFamily);
|
||||||
|
|
||||||
|
@ -229,7 +229,6 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
relayTo = RR->topology->getBestRoot(&source,1,true);
|
relayTo = RR->topology->getBestRoot(&source,1,true);
|
||||||
if (relayTo)
|
if (relayTo)
|
||||||
relayTo->send(packet.data(),packet.size(),now);
|
relayTo->send(packet.data(),packet.size(),now);
|
||||||
@ -681,7 +680,7 @@ unsigned long Switch::doTimerTasks(uint64_t now)
|
|||||||
Mutex::Lock _l(_contactQueue_m);
|
Mutex::Lock _l(_contactQueue_m);
|
||||||
for(std::list<ContactQueueEntry>::iterator qi(_contactQueue.begin());qi!=_contactQueue.end();) {
|
for(std::list<ContactQueueEntry>::iterator qi(_contactQueue.begin());qi!=_contactQueue.end();) {
|
||||||
if (now >= qi->fireAtTime) {
|
if (now >= qi->fireAtTime) {
|
||||||
if (!qi->peer->pushDirectPaths(qi->localAddr,qi->inaddr,now,true))
|
if (!qi->peer->pushDirectPaths(qi->localAddr,qi->inaddr,now,true,false))
|
||||||
qi->peer->sendHELLO(qi->localAddr,qi->inaddr,now);
|
qi->peer->sendHELLO(qi->localAddr,qi->inaddr,now);
|
||||||
_contactQueue.erase(qi++);
|
_contactQueue.erase(qi++);
|
||||||
continue;
|
continue;
|
||||||
@ -790,38 +789,38 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid)
|
|||||||
return false; // we probably just left this network, let its packets die
|
return false; // we probably just left this network, let its packets die
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Path *viaPath = peer->getBestPath(now);
|
||||||
SharedPtr<Peer> relay;
|
SharedPtr<Peer> relay;
|
||||||
|
|
||||||
// Check for a network preferred relay
|
if (!viaPath) {
|
||||||
Path *viaPath = peer->getBestPath(now);
|
if (network) {
|
||||||
if ((!viaPath)&&(network)) {
|
unsigned int bestq = ~((unsigned int)0); // max unsigned int since quality is lower==better
|
||||||
unsigned int bestq = ~((unsigned int)0); // max unsigned int since quality is lower==better
|
for(unsigned int ri=0;ri<network->config().staticDeviceCount();++ri) {
|
||||||
for(unsigned int ri=0;ri<network->config().staticDeviceCount();++ri) {
|
const ZT_VirtualNetworkStaticDevice &r = network->config().staticDevice(ri);
|
||||||
const ZT_VirtualNetworkStaticDevice &r = network->config().staticDevice(ri);
|
if ((r.address != peer->address().toInt())&&((r.flags & ZT_NETWORK_STATIC_DEVICE_IS_RELAY) != 0)) {
|
||||||
if ((r.address != peer->address().toInt())&&((r.flags & ZT_NETWORK_STATIC_DEVICE_IS_RELAY) != 0)) {
|
SharedPtr<Peer> rp(RR->topology->getPeer(Address(r.address)));
|
||||||
SharedPtr<Peer> rp(RR->topology->getPeer(Address(r.address)));
|
if (rp) {
|
||||||
if (rp) {
|
const unsigned int q = rp->relayQuality(now);
|
||||||
const unsigned int q = rp->relayQuality(now);
|
if (q < bestq) {
|
||||||
if (q < bestq) {
|
bestq = q;
|
||||||
bestq = q;
|
rp.swap(relay);
|
||||||
rp.swap(relay);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!relay)
|
||||||
|
relay = RR->topology->getBestRoot();
|
||||||
|
|
||||||
|
if ( (!relay) || (!(viaPath = relay->getBestPath(now))) )
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
// viaPath will not be null if we make it here
|
||||||
|
|
||||||
// Otherwise relay off a root server
|
// Push possible direct paths to us if we are relaying
|
||||||
if (!relay)
|
if (relay) {
|
||||||
relay = RR->topology->getBestRoot();
|
peer->pushDirectPaths(viaPath->localAddress(),viaPath->address(),now,false,( (network)&&(network->isAllowed(peer)) ));
|
||||||
|
|
||||||
// No relay or relay has no active paths == :P~~~~
|
|
||||||
if ( (!(relay)) || (!(viaPath = relay->getBestPath(now))) )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ((network)&&(relay)&&(network->isAllowed(peer))) {
|
|
||||||
// Push hints for direct connectivity to this peer if we are relaying
|
|
||||||
peer->pushDirectPaths(viaPath->localAddress(),viaPath->address(),now,false);
|
|
||||||
viaPath->sent(now);
|
viaPath->sent(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,8 +48,6 @@ public:
|
|||||||
char name[256];
|
char name[256];
|
||||||
InetAddress clusterEndpoint;
|
InetAddress clusterEndpoint;
|
||||||
std::vector<InetAddress> zeroTierEndpoints;
|
std::vector<InetAddress> zeroTierEndpoints;
|
||||||
|
|
||||||
//inline operator<(const MemberDefinition &md) const { return (id < md.id); } // sort order
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user