summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--node/Node.cpp8
-rw-r--r--node/PacketDecoder.cpp17
-rw-r--r--node/Topology.cpp7
-rw-r--r--node/Topology.hpp8
4 files changed, 30 insertions, 10 deletions
diff --git a/node/Node.cpp b/node/Node.cpp
index f8de7908..08b08fc1 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -415,11 +415,9 @@ Node::ReasonForTermination Node::run()
if ((now - lastPingCheck) >= ZT_PING_CHECK_DELAY) {
lastPingCheck = now;
try {
- if (_r->topology->isSupernode(_r->identity.address())) {
- // The only difference in how supernodes behave is here: they only
- // actively ping each other and only passively listen for pings
- // from anyone else. They also don't send firewall openers, since
- // they're never firewalled.
+ if (_r->topology->amSupernode()) {
+ // Supernodes do not ping anyone but each other. They also don't
+ // send firewall openers, since they aren't ever firewalled.
std::vector< SharedPtr<Peer> > sns(_r->topology->supernodePeers());
for(std::vector< SharedPtr<Peer> >::const_iterator p(sns.begin());p!=sns.end();++p) {
if ((now - (*p)->lastDirectSend()) > ZT_PEER_DIRECT_PING_DELAY)
diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp
index ba1a9001..810e30a7 100644
--- a/node/PacketDecoder.cpp
+++ b/node/PacketDecoder.cpp
@@ -450,19 +450,28 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
// Technically should not happen, since the original submitter is
// excluded from consideration as a propagation recipient.
TRACE("dropped boomerang MULTICAST_FRAME received from %s(%s)",source().toString().c_str(),_remoteAddress.toString().c_str());
- } else if ((!isDuplicate)||(_r->topology->isSupernode(_r->identity.address()))) {
+ } else if ((!isDuplicate)||(_r->topology->amSupernode())) {
+ //
// If I am a supernode, I will repeatedly propagate duplicates. That's
// because supernodes are used to bridge sparse multicast groups. Non-
// supernodes will ignore duplicates completely.
+ //
+ // TODO: supernodes should keep a local bloom filter too and OR it with
+ // the bloom from the packet in order to pick different recipients each
+ // time a multicast returns to them for repropagation.
+ //
+
SharedPtr<Peer> originalSubmitter(_r->topology->getPeer(originalSubmitterAddress));
if (!originalSubmitter) {
TRACE("requesting WHOIS on original multicast frame submitter %s",originalSubmitterAddress.toString().c_str());
_r->sw->requestWhois(originalSubmitterAddress);
_step = DECODE_STEP_WAITING_FOR_ORIGINAL_SUBMITTER_LOOKUP;
- return false;
+ return false; // try again if/when we get OK(WHOIS)
} else if (Multicaster::verifyMulticastPacket(originalSubmitter->identity(),network->id(),fromMac,mg,etherType,dataAndSignature,datalen,dataAndSignature + datalen,signaturelen)) {
_r->multicaster->addToDedupHistory(mccrc,now);
+ // Even if we are a supernode, we still don't repeatedly inject
+ // duplicates into our own tap.
if (!isDuplicate)
network->tap().put(fromMac,mg.mac(),etherType,dataAndSignature,datalen);
@@ -494,7 +503,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
compress();
for(unsigned int i=0;i<np;++i) {
- TRACE("propagating multicast from original node %s: %s -> %s",originalSubmitterAddress.toString().c_str(),upstream.toString().c_str(),propPeers[i]->address().toString().c_str());
+ //TRACE("propagating multicast from original node %s: %s -> %s",originalSubmitterAddress.toString().c_str(),upstream.toString().c_str(),propPeers[i]->address().toString().c_str());
// Re-use this packet to re-send multicast frame to everyone
// downstream from us.
newInitializationVector();
@@ -504,7 +513,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
return true;
} else {
- TRACE("terminating MULTICAST_FRAME propagation from %s(%s): max depth reached",source().toString().c_str(),_remoteAddress.toString().c_str());
+ //TRACE("terminating MULTICAST_FRAME propagation from %s(%s): max depth reached",source().toString().c_str(),_remoteAddress.toString().c_str());
}
} else {
LOG("rejected MULTICAST_FRAME from %s(%s) due to failed signature check (claims original sender %s)",source().toString().c_str(),_remoteAddress.toString().c_str(),originalSubmitterAddress.toString().c_str());
diff --git a/node/Topology.cpp b/node/Topology.cpp
index e627e767..43c5303e 100644
--- a/node/Topology.cpp
+++ b/node/Topology.cpp
@@ -39,7 +39,8 @@ namespace ZeroTier {
Topology::Topology(const RuntimeEnvironment *renv,const char *dbpath)
throw(std::runtime_error) :
Thread(),
- _r(renv)
+ _r(renv),
+ _amSupernode(false)
{
if (KISSDB_open(&_dbm,dbpath,KISSDB_OPEN_MODE_RWCREAT,ZT_KISSDB_HASH_TABLE_SIZE,ZT_KISSDB_KEY_SIZE,ZT_KISSDB_VALUE_SIZE)) {
if (KISSDB_open(&_dbm,dbpath,KISSDB_OPEN_MODE_RWREPLACE,ZT_KISSDB_HASH_TABLE_SIZE,ZT_KISSDB_KEY_SIZE,ZT_KISSDB_VALUE_SIZE))
@@ -77,9 +78,11 @@ Topology::~Topology()
void Topology::setSupernodes(const std::map< Identity,std::vector<InetAddress> > &sn)
{
Mutex::Lock _l(_supernodes_m);
+
_supernodes = sn;
_supernodeAddresses.clear();
_supernodePeers.clear();
+
for(std::map< Identity,std::vector<InetAddress> >::const_iterator i(sn.begin());i!=sn.end();++i) {
if (i->first != _r->identity) {
SharedPtr<Peer> p(getPeer(i->first.address()));
@@ -93,6 +96,8 @@ void Topology::setSupernodes(const std::map< Identity,std::vector<InetAddress> >
}
_supernodeAddresses.insert(i->first.address());
}
+
+ _amSupernode = (_supernodes.find(_r->identity) != _supernodes.end());
}
void Topology::addPeer(const SharedPtr<Peer> &candidate,void (*callback)(void *,const SharedPtr<Peer> &,Topology::PeerVerifyResult),void *arg)
diff --git a/node/Topology.hpp b/node/Topology.hpp
index 2a977aa8..104ad344 100644
--- a/node/Topology.hpp
+++ b/node/Topology.hpp
@@ -163,6 +163,11 @@ public:
}
/**
+ * @return True if this node's identity is in the supernode set
+ */
+ inline bool amSupernode() const { return _amSupernode; }
+
+ /**
* Clean and flush database now (runs in the background)
*/
void clean();
@@ -305,6 +310,9 @@ private:
std::vector< SharedPtr<Peer> > _supernodePeers;
Mutex _supernodes_m;
+ // Set to true if my identity is in _supernodes
+ volatile bool _amSupernode;
+
KISSDB _dbm;
Mutex _dbm_m;
};