Browse Source

Make new multicast depth and prefix bits parameters configurable.

Adam Ierymenko 12 years ago
parent
commit
9db7939d38
6 changed files with 90 additions and 17 deletions
  1. 13 1
      netconf-service/netconf.cpp
  2. 6 10
      node/Constants.hpp
  3. 4 0
      node/Network.cpp
  4. 60 2
      node/Network.hpp
  5. 3 1
      node/PacketDecoder.cpp
  6. 4 3
      node/Switch.cpp

+ 13 - 1
netconf-service/netconf.cpp

@@ -204,15 +204,19 @@ int main(int argc,char **argv)
 				}
 
 				bool isOpen = false;
+				unsigned int mpb = 0;
+				unsigned int md = 0;
 				std::string name,desc;
 				{
 					Query q = dbCon->query();
-					q << "SELECT name,`desc`,isOpen FROM Network WHERE id = " << nwid;
+					q << "SELECT name,`desc`,isOpen,multicastPrefixBits,multicastDepth FROM Network WHERE id = " << nwid;
 					StoreQueryResult rs = q.store();
 					if (rs.num_rows() > 0) {
 						name = rs[0]["name"].c_str();
 						desc = rs[0]["desc"].c_str();
 						isOpen = ((int)rs[0]["isOpen"] > 0);
+						mpb = (unsigned int)rs[0]["multicastPrefixBits"];
+						md = (unsigned int)rs[0]["multicastDepth"];
 					} else {
 						Dictionary response;
 						response["peer"] = peerIdentity.address().toString();
@@ -279,6 +283,14 @@ int main(int argc,char **argv)
 				sprintf(buf,"%llx",(unsigned long long)Utils::now());
 				netconf["ts"] = buf;
 				netconf["peer"] = peerIdentity.address().toString();
+				if (mpb) {
+					sprintf(buf,"%x",mpb);
+					netconf["mpb"] = buf;
+				}
+				if (md) {
+					sprintf(buf,"%x",md);
+					netconf["md"] = buf;
+				}
 
 				if (!isOpen) {
 					// TODO: handle closed networks, look up private membership,

+ 6 - 10
node/Constants.hpp

@@ -236,23 +236,19 @@ error_no_ZT_ARCH_defined;
 #define ZT_MULTICAST_DEDUP_HISTORY_LENGTH 1024
 
 /**
- * Maximum propagation depth for multicasts
- *
- * TODO: in the future make this configurable per-network.
+ * Default number of bits in multicast propagation prefix
  */
-#define ZT_MULTICAST_MAX_PROPAGATION_DEPTH 128
+#define ZT_DEFAULT_MULTICAST_PREFIX_BITS 2
 
 /**
- * Number of frames to send when originating a multicast
- *
- * This MUST be a power of two.
+ * Default max depth (TTL) for multicast propagation
  */
-#define ZT_MULTICAST_NUM_PROPAGATION_PREFIXES 4
+#define ZT_DEFAULT_MULTICAST_DEPTH 64
 
 /**
- * Power of two used for ZT_MULTICAST_NUM_PROPAGATION_PREFIXES
+ * Global maximum for multicast propagation depth
  */
-#define ZT_MULTICAST_NUM_PROPAGATION_PREFIX_BITS 2
+#define ZT_MULTICAST_GLOBAL_MAX_DEPTH 500
 
 /**
  * Period between announcements of all multicast 'likes' in ms

+ 4 - 0
node/Network.cpp

@@ -161,6 +161,8 @@ SharedPtr<Network> Network::newInstance(const RuntimeEnvironment *renv,uint64_t
 	nw->_r = renv;
 	nw->_tap = new EthernetTap(renv,tag,renv->identity.address().toMAC(),ZT_IF_MTU,&_CBhandleTapData,nw.ptr());
 	nw->_isOpen = false;
+	nw->_multicastPrefixBits = ZT_DEFAULT_MULTICAST_PREFIX_BITS;
+	nw->_multicastDepth = ZT_DEFAULT_MULTICAST_DEPTH;
 	memset(nw->_etWhitelist,0,sizeof(nw->_etWhitelist));
 	nw->_id = id;
 	nw->_lastConfigUpdate = 0;
@@ -185,6 +187,8 @@ void Network::setConfiguration(const Network::Config &conf)
 			_mcRates = conf.multicastRates();
 			_staticAddresses = conf.staticAddresses();
 			_isOpen = conf.isOpen();
+			_multicastPrefixBits = conf.multicastPrefixBits();
+			_multicastDepth = conf.multicastDepth();
 
 			_lastConfigUpdate = Utils::now();
 

+ 60 - 2
node/Network.hpp

@@ -266,12 +266,20 @@ public:
 	 * nwid=<hex network ID> (required)
 	 * name=short name
 	 * desc=long(er) description
-	 * com=Certificate (serialized dictionary)
+	 * com=Serialized certificate of membership
 	 * mr=MulticastRates (serialized dictionary)
+	 * md=multicast propagation depth
+	 * mpb=multicast propagation prefix bits (2^mpb packets are sent by origin)
 	 * o=open network? (1 or 0, default false if missing)
 	 * et=ethertype whitelist (comma-delimited list of ethertypes in decimal)
 	 * v4s=IPv4 static assignments / netmasks (comma-delimited)
 	 * v6s=IPv6 static assignments / netmasks (comma-delimited)
+	 *
+	 * Notes:
+	 *
+	 * If zero appears in the 'et' list, the sense is inverted. It becomes an
+	 * ethertype blacklist instead of a whitelist and anything not blacklisted
+	 * is permitted.
 	 */
 	class Config : private Dictionary
 	{
@@ -339,6 +347,34 @@ public:
 			else return MulticastRates(mr->second);
 		}
 
+		/**
+		 * @return Number of bits in propagation prefix for this network
+		 */
+		inline unsigned int multicastPrefixBits() const
+		{
+			const_iterator mpb(find("mpb"));
+			if (mpb == end())
+				return ZT_DEFAULT_MULTICAST_PREFIX_BITS;
+			unsigned int tmp = Utils::hexStrToUInt(mpb->second.c_str());
+			if (tmp)
+				return tmp;
+			else return ZT_DEFAULT_MULTICAST_PREFIX_BITS;
+		}
+
+		/**
+		 * @return Maximum multicast propagation depth for this network
+		 */
+		inline unsigned int multicastDepth() const
+		{
+			const_iterator md(find("md"));
+			if (md == end())
+				return ZT_DEFAULT_MULTICAST_DEPTH;
+			unsigned int tmp = Utils::hexStrToUInt(md->second.c_str());
+			if (tmp)
+				return tmp;
+			else return ZT_DEFAULT_MULTICAST_DEPTH;
+		}
+
 		/**
 		 * @return True if this is an open non-access-controlled network
 		 */
@@ -557,7 +593,9 @@ public:
 			return false;
 		else if (etherType > 65535)
 			return false;
-		else return ((_etWhitelist[etherType / 8] & (unsigned char)(1 << (etherType % 8))) != 0);
+		else if ((_etWhitelist[0] & 1)) // if type 0 is in the whitelist, sense is inverted from whitelist to blacklist
+			return ((_etWhitelist[etherType / 8] & (unsigned char)(1 << (etherType & 7))) == 0);
+		else return ((_etWhitelist[etherType / 8] & (unsigned char)(1 << (etherType & 7))) != 0);
 	}
 
 	/**
@@ -592,6 +630,24 @@ public:
 		return false; // TODO: bridging not implemented yet
 	}
 
+	/**
+	 * @return Bits in multicast restriciton prefix
+	 */
+	inline unsigned int multicastPrefixBits() const
+		throw()
+	{
+		return _multicastPrefixBits;
+	}
+
+	/**
+	 * @return Max depth (TTL) for a multicast frame
+	 */
+	inline unsigned int multicastDepth() const
+		throw()
+	{
+		return _multicastDepth;
+	}
+
 private:
 	static void _CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data);
 	void _restoreState();
@@ -614,6 +670,8 @@ private:
 	MulticastRates _mcRates; // memoized from _configuration
 	std::set<InetAddress> _staticAddresses; // memoized from _configuration
 	bool _isOpen; // memoized from _configuration
+	unsigned int _multicastPrefixBits; // memoized from _configuration
+	unsigned int _multicastDepth; // memoized from _configuration
 
 	// Ethertype whitelist bit field, set from config, for really fast lookup
 	unsigned char _etWhitelist[65536 / 8];

+ 3 - 1
node/PacketDecoder.cpp

@@ -485,6 +485,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
 		}
 
 		bool rateLimitsExceeded = false;
+		unsigned int maxDepth = ZT_MULTICAST_GLOBAL_MAX_DEPTH;
 
 		if ((origin == _r->identity.address())||(_r->mc->deduplicate(nwid,guid))) {
 			// Ordinary frames will drop duplicates. Supernodes keep propagating
@@ -502,6 +503,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
 			// for the same frame would not be fair.
 			SharedPtr<Network> network(_r->nc->network(nwid));
 			if (network) {
+				maxDepth = network->multicastDepth(); // pull from network config if available
 				if (!network->isAllowed(origin)) {
 					TRACE("didn't inject MULTICAST_FRAME from %s(%s) into %.16llx: sender %s not allowed or we don't have a certificate",source().toString().c_str(),nwid,_remoteAddress.toString().c_str(),origin.toString().c_str());
 
@@ -541,7 +543,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
 			TRACE("not forwarding MULTICAST_FRAME from %s(%s): depth == 0xffff (do not forward)",source().toString().c_str(),_remoteAddress.toString().c_str());
 			return true;
 		}
-		if (++depth > ZT_MULTICAST_MAX_PROPAGATION_DEPTH) {
+		if (++depth > maxDepth) {
 			TRACE("not forwarding MULTICAST_FRAME from %s(%s): max propagation depth reached",source().toString().c_str(),_remoteAddress.toString().c_str());
 			return true;
 		}

+ 4 - 3
node/Switch.cpp

@@ -111,13 +111,14 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 		uint16_t bloomNonce = (uint16_t)_r->prng->next32(); // doesn't need to be cryptographically strong
 		unsigned char bloom[ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM];
 		unsigned char fifo[ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO + ZT_ADDRESS_LENGTH];
-		for(unsigned int prefix=0;prefix<ZT_MULTICAST_NUM_PROPAGATION_PREFIXES;++prefix) {
+
+		for(unsigned int prefix=0,np=((unsigned int)2 << (network->multicastPrefixBits() - 1));prefix<np;++prefix) {
 			memset(bloom,0,sizeof(bloom));
 
 			unsigned char *fifoPtr = fifo;
 			unsigned char *fifoEnd = fifo + sizeof(fifo);
 
-			_r->mc->getNextHops(network->id(),mg,Multicaster::AddToPropagationQueue(&fifoPtr,fifoEnd,bloom,bloomNonce,_r->identity.address(),ZT_MULTICAST_NUM_PROPAGATION_PREFIX_BITS,prefix));
+			_r->mc->getNextHops(network->id(),mg,Multicaster::AddToPropagationQueue(&fifoPtr,fifoEnd,bloom,bloomNonce,_r->identity.address(),network->multicastPrefixBits(),prefix));
 			while (fifoPtr != fifoEnd)
 				*(fifoPtr++) = (unsigned char)0;
 
@@ -136,7 +137,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 			outp.append((unsigned char)0);
 			outp.append(network->id());
 			outp.append(bloomNonce);
-			outp.append((unsigned char)ZT_MULTICAST_NUM_PROPAGATION_PREFIX_BITS);
+			outp.append((unsigned char)network->multicastPrefixBits());
 			outp.append((unsigned char)prefix);
 			_r->identity.address().appendTo(outp);
 			outp.append((unsigned char)((mcid >> 16) & 0xff));