Browse Source

Tighten up credential push just a bit for faster up-time with older nodes, should not have significant impact on bandwidth. Also some cleanup and push direct path timing fixes.

Adam Ierymenko 6 years ago
parent
commit
a019c3dd5d
8 changed files with 52 additions and 20 deletions
  1. 7 2
      node/Constants.hpp
  2. 0 3
      node/InetAddress.cpp
  3. 3 0
      node/Membership.cpp
  4. 11 0
      node/Membership.hpp
  5. 15 0
      node/Network.hpp
  6. 3 4
      node/OutboundMulticast.cpp
  7. 11 10
      node/Peer.cpp
  8. 2 1
      node/Switch.cpp

+ 7 - 2
node/Constants.hpp

@@ -530,14 +530,19 @@
 #define ZT_MAX_BRIDGE_ROUTES 67108864
 
 /**
- * If there is no known route, spam to up to this many active bridges
+ * If there is no known L2 bridging route, spam to up to this many active bridges
  */
 #define ZT_MAX_BRIDGE_SPAM 32
 
 /**
  * Interval between direct path pushes in milliseconds
  */
-#define ZT_DIRECT_PATH_PUSH_INTERVAL 120000
+#define ZT_DIRECT_PATH_PUSH_INTERVAL 15000
+
+/**
+ * Interval between direct path pushes in milliseconds if we already have a path
+ */
+#define ZT_DIRECT_PATH_PUSH_INTERVAL_HAVEPATH 120000
 
 /**
  * Time horizon for push direct paths cutoff

+ 0 - 3
node/InetAddress.cpp

@@ -185,15 +185,12 @@ bool InetAddress::fromString(const char *ipSlashPort)
 		inet_pton(AF_INET6, buf, &in6->sin6_addr.s6_addr);
 		in6->sin6_family = AF_INET6;
 		in6->sin6_port = Utils::hton((uint16_t)port);
-
-
 		return true;
 	} else if (strchr(buf,'.')) {
 		struct sockaddr_in *const in = reinterpret_cast<struct sockaddr_in *>(this);
 		inet_pton(AF_INET, buf, &in->sin_addr.s_addr);
 		in->sin_family = AF_INET;
 		in->sin_port = Utils::hton((uint16_t)port);
-
 		return true;
 	} else {
 		return false;

+ 3 - 0
node/Membership.cpp

@@ -40,6 +40,7 @@ namespace ZeroTier {
 Membership::Membership() :
 	_lastUpdatedMulticast(0),
 	_comRevocationThreshold(0),
+	_lastPushedCredentials(0),
 	_revocations(4),
 	_remoteTags(4),
 	_remoteCaps(4),
@@ -103,6 +104,8 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i
 		outp.compress();
 		RR->sw->send(tPtr,outp,true);
 	}
+
+	_lastPushedCredentials = now;
 }
 
 Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfMembership &com)

+ 11 - 0
node/Membership.hpp

@@ -78,6 +78,14 @@ public:
 	 */
 	void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex);
 
+	/**
+	 * @return True if we haven't pushed credentials in a long time (to cause proactive credential push)
+	 */
+	inline bool shouldPushCredentials(const int64_t now) const
+	{
+		return ((now - _lastPushedCredentials) > ZT_PEER_ACTIVITY_TIMEOUT);
+	}
+
 	/**
 	 * Check whether we should push MULTICAST_LIKEs to this peer, and update last sent time if true
 	 *
@@ -213,6 +221,9 @@ private:
 	// Revocation threshold for COM or 0 if none
 	int64_t _comRevocationThreshold;
 
+	// Time we last pushed credentials
+	int64_t _lastPushedCredentials;
+
 	// Remote member's latest network COM
 	CertificateOfMembership _com;
 

+ 15 - 0
node/Network.hpp

@@ -368,6 +368,21 @@ public:
 		_membership(to).pushCredentials(RR,tPtr,now,to,_config,-1);
 	}
 
+	/**
+	 * Push credentials if we haven't done so in a very long time
+	 * 
+	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
+	 * @param to Destination peer address
+	 * @param now Current time
+	 */
+	inline void pushCredentialsIfNeeded(void *tPtr,const Address &to,const int64_t now)
+	{
+		Mutex::Lock _l(_lock);
+		Membership &m = _membership(to);
+		if (m.shouldPushCredentials(now))
+			m.pushCredentials(RR,tPtr,now,to,_config,-1);
+	}
+
 	/**
 	 * Destroy this network
 	 *

+ 3 - 4
node/OutboundMulticast.cpp

@@ -84,13 +84,12 @@ void OutboundMulticast::init(
 void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,void *tPtr,const Address &toAddr)
 {
 	const SharedPtr<Network> nw(RR->node->network(_nwid));
-	const Address toAddr2(toAddr);
 	uint8_t QoSBucket = 255; // Dummy value
-	if ((nw)&&(nw->filterOutgoingPacket(tPtr,true,RR->identity.address(),toAddr2,_macSrc,_macDest,_frameData,_frameLen,_etherType,0,QoSBucket))) {
+	if ((nw)&&(nw->filterOutgoingPacket(tPtr,true,RR->identity.address(),toAddr,_macSrc,_macDest,_frameData,_frameLen,_etherType,0,QoSBucket))) {
+		nw->pushCredentialsIfNeeded(tPtr,toAddr,RR->node->now());
 		_packet.newInitializationVector();
-		_packet.setDestination(toAddr2);
+		_packet.setDestination(toAddr);
 		RR->node->expectReplyTo(_packet.packetId());
-
 		_tmp = _packet;
 		RR->sw->send(tPtr,_tmp,true);
 	}

+ 11 - 10
node/Peer.cpp

@@ -39,6 +39,8 @@
 
 namespace ZeroTier {
 
+static unsigned char s_freeRandomByteCounter = 0;
+
 Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) :
 	RR(renv),
 	_lastReceive(0),
@@ -55,7 +57,7 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident
 	_lastACKWindowReset(0),
 	_lastQoSWindowReset(0),
 	_lastMultipathCompatibilityCheck(0),
-	_freeRandomByte(0),
+	_freeRandomByte((unsigned char)((uintptr_t)this >> 4) ^ ++s_freeRandomByteCounter),
 	_uniqueAlivePathCount(0),
 	_localMultipathSupported(false),
 	_remoteMultipathSupported(false),
@@ -73,7 +75,6 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident
 	_lastAggregateStatsReport(0),
 	_lastAggregateAllocation(0)
 {
-	Utils::getSecureRandom(&_freeRandomByte, 1);
 	if (!myIdentity.agree(peerIdentity,_key,ZT_PEER_SECRET_KEY_LENGTH))
 		throw ZT_EXCEPTION_INVALID_ARGUMENT;
 }
@@ -101,7 +102,8 @@ void Peer::received(
 		case Packet::VERB_MULTICAST_FRAME:
 			_lastNontrivialReceive = now;
 			break;
-		default: break;
+		default:
+			break;
 	}
 
 	if (trustEstablished) {
@@ -202,17 +204,17 @@ void Peer::received(
 	}
 
 	// If we have a trust relationship periodically push a message enumerating
-	// all known external addresses for ourselves. We now do this even if we
-	// have a current path since we'll want to use new ones too.
+	// all known external addresses for ourselves. If we already have a path this
+	// is done less frequently.
 	if (this->trustEstablished(now)) {
-		const uint64_t sinceLastPush = now - _lastDirectPathPushSent;
-		if (sinceLastPush >= ZT_DIRECT_PATH_PUSH_INTERVAL) {
+		const int64_t sinceLastPush = now - _lastDirectPathPushSent;
+		if (sinceLastPush >= ((hops == 0) ? ZT_DIRECT_PATH_PUSH_INTERVAL_HAVEPATH : ZT_DIRECT_PATH_PUSH_INTERVAL)) {
 			_lastDirectPathPushSent = now;
 			std::vector<InetAddress> pathsToPush(RR->node->directPaths());
 			if (pathsToPush.size() > 0) {
 				std::vector<InetAddress>::const_iterator p(pathsToPush.begin());
 				while (p != pathsToPush.end()) {
-					Packet *outp = new Packet(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS);
+					Packet *const outp = new Packet(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS);
 					outp->addSize(2); // leave room for count
 					unsigned int count = 0;
 					while ((p != pathsToPush.end())&&((outp->size() + 24) < 1200)) {
@@ -254,8 +256,7 @@ void Peer::received(
 void Peer::recordOutgoingPacket(const SharedPtr<Path> &path, const uint64_t packetId,
 	uint16_t payloadLength, const Packet::Verb verb, int64_t now)
 {
-	// Grab second byte from packetId to use as a source of entropy in the next path selection
-	_freeRandomByte = (packetId & 0xFF00) >> 8;
+	_freeRandomByte += (unsigned char)(packetId >> 8); // grab entropy to use in path selection logic for multipath
 	if (_canUseMultipath) {
 		path->recordOutgoingPacket(now, packetId, payloadLength, verb);
 	}

+ 2 - 1
node/Switch.cpp

@@ -417,6 +417,8 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
 			return;
 		}
 
+		network->pushCredentialsIfNeeded(tPtr,toZT,RR->node->now());
+
 		if (fromBridged) {
 			Packet outp(toZT,RR->identity.address(),Packet::VERB_EXT_FRAME);
 			outp.append(network->id());
@@ -437,7 +439,6 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
 				outp.compress();
 			aqm_enqueue(tPtr,network,outp,true,qosBucket);
 		}
-
 	} else {
 		// Destination is bridged behind a remote peer