Browse Source

Network memory for bridge-side multicast groups that we learn - GitHub issue #68

Adam Ierymenko 11 years ago
parent
commit
08b7bb3c7a
2 changed files with 75 additions and 45 deletions
  1. 60 1
      node/Network.cpp
  2. 15 44
      node/Network.hpp

+ 60 - 1
node/Network.cpp

@@ -119,6 +119,35 @@ SharedPtr<Network> Network::newInstance(const RuntimeEnvironment *renv,NodeConfi
 	return nw;
 }
 
+bool Network::updateMulticastGroups()
+{
+	Mutex::Lock _l(_lock);
+	EthernetTap *t = _tap;
+	if (t) {
+		// Grab current groups from the local tap
+		bool updated = _tap->updateMulticastGroups(_multicastGroups);
+
+		// Merge in learned groups from any hosts bridged in behind us
+		for(std::map<MulticastGroup,uint64_t>::const_iterator mg(_bridgedMulticastGroups.begin());mg!=_bridgedMulticastGroups.end();++mg)
+			_multicastGroups.insert(mg->first);
+
+		// Add or remove BROADCAST group based on broadcast enabled netconf flag
+		if ((_config)&&(_config->enableBroadcast())) {
+			if (_multicastGroups.count(BROADCAST))
+				return updated;
+			else {
+				_multicastGroups.insert(BROADCAST);
+				return true;
+			}
+		} else {
+			if (_multicastGroups.count(BROADCAST)) {
+				_multicastGroups.erase(BROADCAST);
+				return true;
+			} else return updated;
+		}
+	} else return false;
+}
+
 bool Network::setConfiguration(const Dictionary &conf,bool saveToDisk)
 {
 	Mutex::Lock _l(_lock);
@@ -224,6 +253,7 @@ bool Network::isAllowed(const Address &peer) const
 void Network::clean()
 {
 	Mutex::Lock _l(_lock);
+	uint64_t now = Utils::now();
 
 	if ((_config)&&(_config->isOpen())) {
 		// Open (public) networks do not track certs or cert pushes at all.
@@ -239,13 +269,42 @@ void Network::clean()
 
 		// Clean entries from the last pushed tracking map if they're so old as
 		// to be no longer relevant.
-		uint64_t forgetIfBefore = Utils::now() - (_config->com().timestampMaxDelta() * 3ULL);
+		uint64_t forgetIfBefore = now - (_config->com().timestampMaxDelta() * 3ULL);
 		for(std::map<Address,uint64_t>::iterator lp(_lastPushedMembershipCertificate.begin());lp!=_lastPushedMembershipCertificate.end();) {
 			if (lp->second < forgetIfBefore)
 				_lastPushedMembershipCertificate.erase(lp++);
 			else ++lp;
 		}
 	}
+
+	// Clean learned multicast groups if we haven't heard from them in a while
+	for(std::map<MulticastGroup,uint64_t>::iterator mg(_bridgedMulticastGroups.begin());mg!=_bridgedMulticastGroups.end();) {
+		if ((now - mg->second) > (ZT_MULTICAST_LIKE_EXPIRE * 2))
+			_bridgedMulticastGroups.erase(mg++);
+		else ++mg;
+	}
+}
+
+Network::Status Network::status() const
+{
+	Mutex::Lock _l(_lock);
+	if (_tap) {
+		switch(_netconfFailure) {
+			case NETCONF_FAILURE_ACCESS_DENIED:
+				return NETWORK_ACCESS_DENIED;
+			case NETCONF_FAILURE_NOT_FOUND:
+				return NETWORK_NOT_FOUND;
+			case NETCONF_FAILURE_NONE:
+				if (_lastConfigUpdate > 0)
+					return NETWORK_OK;
+				else return NETWORK_WAITING_FOR_FIRST_AUTOCONF;
+			case NETCONF_FAILURE_INIT_FAILED:
+			default:
+				return NETWORK_INITIALIZATION_FAILED;
+		}
+	} else if (_netconfFailure == NETCONF_FAILURE_INIT_FAILED) {
+		return NETWORK_INITIALIZATION_FAILED;
+	} else return NETWORK_INITIALIZING;
 }
 
 void Network::_CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data)

+ 15 - 44
node/Network.hpp

@@ -158,27 +158,7 @@ public:
 	 *
 	 * @return True if internal multicast group set has changed
 	 */
-	inline bool updateMulticastGroups()
-	{
-		Mutex::Lock _l(_lock);
-		EthernetTap *t = _tap;
-		if (t) {
-			bool updated = _tap->updateMulticastGroups(_multicastGroups);
-			if ((_config)&&(_config->enableBroadcast())) {
-				if (_multicastGroups.count(BROADCAST))
-					return updated;
-				else {
-					_multicastGroups.insert(BROADCAST);
-					return true;
-				}
-			} else {
-				if (_multicastGroups.count(BROADCAST)) {
-					_multicastGroups.erase(BROADCAST);
-					return true;
-				} else return updated;
-			}
-		} else return false;
-	}
+	bool updateMulticastGroups();
 
 	/**
 	 * @return Latest set of multicast groups for this network's tap
@@ -272,28 +252,7 @@ public:
 	/**
 	 * @return Status of this network
 	 */
-	inline Status status() const
-		throw()
-	{
-		Mutex::Lock _l(_lock);
-		if (_tap) {
-			switch(_netconfFailure) {
-				case NETCONF_FAILURE_ACCESS_DENIED:
-					return NETWORK_ACCESS_DENIED;
-				case NETCONF_FAILURE_NOT_FOUND:
-					return NETWORK_NOT_FOUND;
-				case NETCONF_FAILURE_NONE:
-					if (_lastConfigUpdate > 0)
-						return NETWORK_OK;
-					else return NETWORK_WAITING_FOR_FIRST_AUTOCONF;
-				case NETCONF_FAILURE_INIT_FAILED:
-				default:
-					return NETWORK_INITIALIZATION_FAILED;
-			}
-		} else if (_netconfFailure == NETCONF_FAILURE_INIT_FAILED) {
-			return NETWORK_INITIALIZATION_FAILED;
-		} else return NETWORK_INITIALIZING;
-	}
+	Status status() const;
 
 	/**
 	 * Update multicast balance for an address and multicast group, return whether packet is allowed
@@ -418,7 +377,7 @@ public:
 
 	/**
 	 * @param mac MAC address
-	 * @return ZeroTier address of bridge to this MAC or null address if not found
+	 * @return ZeroTier address of bridge to this MAC or null address if not found (also check result for self, since this can happen)
 	 */
 	inline Address findBridgeTo(const MAC &mac) const
 	{
@@ -437,6 +396,17 @@ public:
 	 */
 	void learnBridgeRoute(const MAC &mac,const Address &addr);
 
+	/**
+	 * Learn a multicast group that is bridged to our tap device
+	 *
+	 * @param mg Multicast group
+	 */
+	inline void learnBridgedMulticastGroup(const MulticastGroup &mg)
+	{
+		Mutex::Lock _l(_lock);
+		_bridgedMulticastGroups[mg] = Utils::now();
+	}
+
 private:
 	static void _CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data);
 
@@ -457,6 +427,7 @@ private:
 	std::map<Address,uint64_t> _lastPushedMembershipCertificate;
 
 	std::map<MAC,Address> _bridgeRoutes;
+	std::map<MulticastGroup,uint64_t> _bridgedMulticastGroups;
 
 	SharedPtr<NetworkConfig> _config;
 	volatile uint64_t _lastConfigUpdate;