summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/Constants.hpp5
-rw-r--r--node/Node.cpp2
-rw-r--r--node/Node.hpp7
-rw-r--r--node/Peer.cpp11
-rw-r--r--node/Peer.hpp8
-rw-r--r--node/Switch.cpp15
6 files changed, 38 insertions, 10 deletions
diff --git a/node/Constants.hpp b/node/Constants.hpp
index 8803ecee..ac1919b3 100644
--- a/node/Constants.hpp
+++ b/node/Constants.hpp
@@ -321,6 +321,11 @@
#define ZT_MIN_UNITE_INTERVAL 30000
/**
+ * How often should peers try memorized or statically defined paths?
+ */
+#define ZT_TRY_MEMORIZED_PATH_INTERVAL 30000
+
+/**
* Sanity limit on maximum bridge routes
*
* If the number of bridge routes exceeds this, we cull routes from the
diff --git a/node/Node.cpp b/node/Node.cpp
index a180766b..11f76365 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -683,7 +683,7 @@ void Node::postTrace(const char *module,unsigned int line,const char *fmt,...)
uint64_t Node::prng()
{
- unsigned int p = (++_prngStreamPtr % (sizeof(_prngStream) / sizeof(uint64_t)));
+ unsigned int p = (++_prngStreamPtr % ZT_NODE_PRNG_BUF_SIZE);
if (!p)
_prng.encrypt12(_prngStream,_prngStream,sizeof(_prngStream));
return _prngStream[p];
diff --git a/node/Node.hpp b/node/Node.hpp
index 7d99ff09..eb46527d 100644
--- a/node/Node.hpp
+++ b/node/Node.hpp
@@ -49,6 +49,9 @@
#define ZT_EXPECTING_REPLIES_BUCKET_MASK1 255
#define ZT_EXPECTING_REPLIES_BUCKET_MASK2 31
+// Size of PRNG stream buffer
+#define ZT_NODE_PRNG_BUF_SIZE 64
+
namespace ZeroTier {
/**
@@ -195,7 +198,7 @@ public:
#endif
bool shouldUsePathForZeroTierTraffic(const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress);
- inline bool getPathHint(const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,ztaddr.toInt(),family,reinterpret_cast<struct sockaddr_storage *>(&addr)) != 0) : false ); }
+ inline bool externalPathLookup(const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,ztaddr.toInt(),family,reinterpret_cast<struct sockaddr_storage *>(&addr)) != 0) : false ); }
uint64_t prng();
void postCircuitTestReport(const ZT_CircuitTestReport *report);
@@ -284,7 +287,7 @@ private:
unsigned int _prngStreamPtr;
Salsa20 _prng;
- uint64_t _prngStream[16]; // repeatedly encrypted with _prng to yield a high-quality non-crypto PRNG stream
+ uint64_t _prngStream[ZT_NODE_PRNG_BUF_SIZE]; // repeatedly encrypted with _prng to yield a high-quality non-crypto PRNG stream
uint64_t _now;
uint64_t _lastPingCheck;
diff --git a/node/Peer.cpp b/node/Peer.cpp
index e0bd0eac..2ef139e1 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -43,6 +43,7 @@ static uint32_t _natKeepaliveBuf = 0;
Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) :
_lastReceive(0),
_lastNontrivialReceive(0),
+ _lastTriedMemorizedPath(0),
_lastDirectPathPushSent(0),
_lastDirectPathPushReceive(0),
_lastCredentialRequestSent(0),
@@ -373,6 +374,16 @@ void Peer::attemptToContactAt(const InetAddress &localAddr,const InetAddress &at
}
}
+void Peer::tryMemorizedPath(uint64_t now)
+{
+ if ((now - _lastTriedMemorizedPath) >= ZT_TRY_MEMORIZED_PATH_INTERVAL) {
+ _lastTriedMemorizedPath = now;
+ InetAddress mp;
+ if (RR->node->externalPathLookup(_id.address(),-1,mp))
+ attemptToContactAt(InetAddress(),mp,now);
+ }
+}
+
bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily)
{
Mutex::Lock _l(_paths_m);
diff --git a/node/Peer.hpp b/node/Peer.hpp
index a7240cb4..78b345b9 100644
--- a/node/Peer.hpp
+++ b/node/Peer.hpp
@@ -165,6 +165,13 @@ public:
void attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now);
/**
+ * Try a memorized or statically defined path if any are known
+ *
+ * Under the hood this is done periodically based on ZT_TRY_MEMORIZED_PATH_INTERVAL.
+ */
+ void tryMemorizedPath(uint64_t now);
+
+ /**
* Send pings or keepalives depending on configured timeouts
*
* @param now Current time
@@ -435,6 +442,7 @@ private:
uint8_t _remoteClusterOptimal6[16];
uint64_t _lastReceive; // direct or indirect
uint64_t _lastNontrivialReceive; // frames, things like netconf, etc.
+ uint64_t _lastTriedMemorizedPath;
uint64_t _lastDirectPathPushSent;
uint64_t _lastDirectPathPushReceive;
uint64_t _lastCredentialRequestSent;
diff --git a/node/Switch.cpp b/node/Switch.cpp
index 881d7b92..7c94d438 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -710,12 +710,12 @@ bool Switch::_trySend(const Packet &packet,bool encrypt)
if (peer) {
const uint64_t now = RR->node->now();
- // First get the best path, and if it's dead (and this is not a root)
- // we attempt to re-activate that path but this packet will flow
- // upstream. If the path comes back alive, it will be used in the future.
- // For roots we don't do the alive check since roots are not required
- // to send heartbeats "down" and because we have to at least try to
- // go somewhere.
+ /* First get the best path, and if it's dead (and this is not a root)
+ * we attempt to re-activate that path but this packet will flow
+ * upstream. If the path comes back alive, it will be used in the future.
+ * For roots we don't do the alive check since roots are not required
+ * to send heartbeats "down" and because we have to at least try to
+ * go somewhere. */
SharedPtr<Path> viaPath(peer->getBestPath(now,false));
if ( (viaPath) && (!viaPath->alive(now)) && (!RR->topology->isRoot(peer->identity())) ) {
@@ -724,7 +724,8 @@ bool Switch::_trySend(const Packet &packet,bool encrypt)
viaPath.zero();
}
if (!viaPath) {
- SharedPtr<Peer> relay(RR->topology->getUpstreamPeer());
+ peer->tryMemorizedPath(now); // periodically attempt memorized or statically defined paths, if any are known
+ const SharedPtr<Peer> relay(RR->topology->getUpstreamPeer());
if ( (!relay) || (!(viaPath = relay->getBestPath(now,false))) ) {
if (!(viaPath = peer->getBestPath(now,true)))
return false;