diff options
-rw-r--r-- | node/Node.cpp | 8 | ||||
-rw-r--r-- | node/PacketDecoder.cpp | 17 | ||||
-rw-r--r-- | node/Topology.cpp | 7 | ||||
-rw-r--r-- | node/Topology.hpp | 8 |
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; }; |