summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--node/Path.hpp10
-rw-r--r--node/Peer.cpp39
-rw-r--r--node/Peer.hpp4
-rw-r--r--node/Utils.cpp1
-rw-r--r--service/ControlPlane.cpp4
5 files changed, 34 insertions, 24 deletions
diff --git a/node/Path.hpp b/node/Path.hpp
index d0e1d737..718e1cdd 100644
--- a/node/Path.hpp
+++ b/node/Path.hpp
@@ -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
diff --git a/node/Peer.cpp b/node/Peer.cpp
index 0cb55fd8..3701d9a1 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -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;
diff --git a/node/Peer.hpp b/node/Peer.hpp
index 8286bfff..25ef72b7 100644
--- a/node/Peer.hpp
+++ b/node/Peer.hpp
@@ -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) );
}
diff --git a/node/Utils.cpp b/node/Utils.cpp
index 2d9515ee..9d67fc22 100644
--- a/node/Utils.cpp
+++ b/node/Utils.cpp
@@ -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");
}
diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp
index 03c5942d..a24e3eb4 100644
--- a/service/ControlPlane.cpp
+++ b/service/ControlPlane.cpp
@@ -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