summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/Constants.hpp16
-rw-r--r--node/Network.cpp4
-rw-r--r--node/Network.hpp62
-rw-r--r--node/PacketDecoder.cpp4
-rw-r--r--node/Switch.cpp7
5 files changed, 77 insertions, 16 deletions
diff --git a/node/Constants.hpp b/node/Constants.hpp
index 91fd5abd..08ec2243 100644
--- a/node/Constants.hpp
+++ b/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
diff --git a/node/Network.cpp b/node/Network.cpp
index 65e61738..82fa6398 100644
--- a/node/Network.cpp
+++ b/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();
diff --git a/node/Network.hpp b/node/Network.hpp
index 2ed70504..cccae17e 100644
--- a/node/Network.hpp
+++ b/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
{
@@ -340,6 +348,34 @@ public:
}
/**
+ * @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
*/
inline bool isOpen() const
@@ -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];
diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp
index 1ec087c7..afc7e4fe 100644
--- a/node/PacketDecoder.cpp
+++ b/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;
}
diff --git a/node/Switch.cpp b/node/Switch.cpp
index 90f0b2e5..14b658a7 100644
--- a/node/Switch.cpp
+++ b/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));