diff options
-rw-r--r-- | node/Constants.hpp | 11 | ||||
-rw-r--r-- | node/Defaults.cpp | 3 | ||||
-rw-r--r-- | node/Defaults.hpp | 8 | ||||
-rw-r--r-- | node/InetAddress.hpp | 6 | ||||
-rw-r--r-- | node/Node.cpp | 23 | ||||
-rw-r--r-- | node/PacketDecoder.cpp | 16 | ||||
-rw-r--r-- | node/Peer.cpp | 7 | ||||
-rw-r--r-- | node/Peer.hpp | 30 | ||||
-rw-r--r-- | node/Switch.cpp | 25 | ||||
-rw-r--r-- | node/Switch.hpp | 16 |
10 files changed, 105 insertions, 40 deletions
diff --git a/node/Constants.hpp b/node/Constants.hpp index 08ec2243..6b2f6d40 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -251,18 +251,9 @@ error_no_ZT_ARCH_defined; #define ZT_MULTICAST_GLOBAL_MAX_DEPTH 500 /** - * Period between announcements of all multicast 'likes' in ms - * - * Announcement occurs when a multicast group is locally joined, but all - * memberships are periodically re-broadcast. If they're not they will - * expire. - */ -#define ZT_MULTICAST_LIKE_ANNOUNCE_ALL_PERIOD 120000 - -/** * Expire time for multicast 'likes' in ms */ -#define ZT_MULTICAST_LIKE_EXPIRE ((ZT_MULTICAST_LIKE_ANNOUNCE_ALL_PERIOD * 2) + 1000) +#define ZT_MULTICAST_LIKE_EXPIRE 120000 /** * Time between polls of local taps for multicast membership changes diff --git a/node/Defaults.cpp b/node/Defaults.cpp index 733832f3..9ce72b30 100644 --- a/node/Defaults.cpp +++ b/node/Defaults.cpp @@ -101,6 +101,9 @@ static inline std::string _mkDefaultHomePath() Defaults::Defaults() throw(std::runtime_error) : +#ifdef ZT_TRACE_MULTICAST + multicastTraceWatcher(ZT_TRACE_MULTICAST), +#endif defaultHomePath(_mkDefaultHomePath()), supernodes(_mkSupernodeMap()) { diff --git a/node/Defaults.hpp b/node/Defaults.hpp index 787193dc..4937ec03 100644 --- a/node/Defaults.hpp +++ b/node/Defaults.hpp @@ -33,6 +33,7 @@ #include <vector> #include <map> +#include "Constants.hpp" #include "Identity.hpp" #include "InetAddress.hpp" @@ -52,6 +53,13 @@ public: throw(std::runtime_error); ~Defaults() {} +#ifdef ZT_TRACE_MULTICAST + /** + * Host to send UDP multicast trace messages to (human readable) + */ + const InetAddress multicastTraceWatcher; +#endif + /** * Default home path for this platform */ diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index 6f21cc7f..54fbc395 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -109,6 +109,12 @@ public: this->fromString(ipSlashPort); } + InetAddress(const char *ipSlashPort) + throw() + { + this->fromString(std::string(ipSlashPort)); + } + inline InetAddress &operator=(const InetAddress &a) throw() { diff --git a/node/Node.cpp b/node/Node.cpp index 954f4cba..ef0598de 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -425,7 +425,6 @@ Node::ReasonForTermination Node::run() uint64_t lastNetworkFingerprintCheck = 0; uint64_t networkConfigurationFingerprint = _r->sysEnv->getNetworkConfigurationFingerprint(); uint64_t lastMulticastCheck = 0; - uint64_t lastMulticastAnnounceAll = 0; long lastDelayDelta = 0; while (impl->reasonForTermination == NODE_RUNNING) { @@ -468,27 +467,15 @@ Node::ReasonForTermination Node::run() // those changes to peers. if ((resynchronize)||((now - lastMulticastCheck) >= ZT_MULTICAST_LOCAL_POLL_PERIOD)) { lastMulticastCheck = now; - bool announceAll = ((resynchronize)||((now - lastMulticastAnnounceAll) >= ZT_MULTICAST_LIKE_ANNOUNCE_ALL_PERIOD)); try { std::map< SharedPtr<Network>,std::set<MulticastGroup> > toAnnounce; - { - std::vector< SharedPtr<Network> > networks(_r->nc->networks()); - for(std::vector< SharedPtr<Network> >::const_iterator nw(networks.begin());nw!=networks.end();++nw) { - if (((*nw)->updateMulticastGroups())||(announceAll)) - toAnnounce.insert(std::pair< SharedPtr<Network>,std::set<MulticastGroup> >(*nw,(*nw)->multicastGroups())); - } + std::vector< SharedPtr<Network> > networks(_r->nc->networks()); + for(std::vector< SharedPtr<Network> >::const_iterator nw(networks.begin());nw!=networks.end();++nw) { + if ((*nw)->updateMulticastGroups()) + toAnnounce.insert(std::pair< SharedPtr<Network>,std::set<MulticastGroup> >(*nw,(*nw)->multicastGroups())); } - - if (toAnnounce.size()) { + if (toAnnounce.size()) _r->sw->announceMulticastGroups(toAnnounce); - - // Only update lastMulticastAnnounceAll if we've announced something. This keeps - // the announceAll condition true during startup when there are no multicast - // groups until there is at least one. Technically this shouldn't be required as - // updateMulticastGroups() should return true on any change, but why not? - if (announceAll) - lastMulticastAnnounceAll = now; - } } catch (std::exception &exc) { LOG("unexpected exception announcing multicast groups: %s",exc.what()); } catch ( ... ) { diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp index a2b827c0..3269504b 100644 --- a/node/PacketDecoder.cpp +++ b/node/PacketDecoder.cpp @@ -28,6 +28,7 @@ #include "../version.h" #include "Constants.hpp" +#include "Defaults.hpp" #include "RuntimeEnvironment.hpp" #include "Topology.hpp" #include "PacketDecoder.hpp" @@ -36,6 +37,7 @@ #include "NodeConfig.hpp" #include "Filter.hpp" #include "Service.hpp" +#include "Demarc.hpp" namespace ZeroTier { @@ -461,7 +463,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared return false; } - uint16_t depth = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH); + unsigned int depth = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH); unsigned char *fifo = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_FIFO,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO); unsigned char *bloom = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM); uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID); @@ -483,6 +485,12 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared return true; } +#ifdef ZT_TRACE_MULTICAST + char mct[256]; + Utils::snprintf(mct,sizeof(mct),"%s <- %.16llx %.16llx %s via %s depth:%u len:%u",_r->identity.address().toString().c_str(),nwid,guid,origin.toString().c_str(),source().toString().c_str(),depth,frameLen); + _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); +#endif + if (!dest.mac().isMulticast()) { TRACE("dropped MULTICAST_FRAME from %s(%s): %s is not a multicast/broadcast address",source().toString().c_str(),_remoteAddress.toString().c_str(),dest.mac().toString().c_str()); return true; @@ -589,7 +597,11 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared // The rest of newFifo[] goes back into the packet memcpy(fifo,newFifo + ZT_ADDRESS_LENGTH,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO); - //TRACE("forwarding MULTICAST_FRAME from %s(%s) to %s, original sender %s, current depth: %u",source().toString().c_str(),_remoteAddress.toString().c_str(),nextHop.toString().c_str(),origin.toString().c_str(),depth); +#ifdef ZT_TRACE_MULTICAST + char mct[256]; + Utils::snprintf(mct,sizeof(mct),"%s -> %.16llx %.16llx %s via %s",_r->identity.address().toString().c_str(),nwid,guid,origin.toString().c_str(),nextHop.toString().c_str()); + _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); +#endif // Send to next hop, reusing this packet as scratch space newInitializationVector(); diff --git a/node/Peer.cpp b/node/Peer.cpp index 1d22fd1f..1c7eec34 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -26,6 +26,7 @@ */ #include "Peer.hpp" +#include "Switch.hpp" namespace ZeroTier { @@ -66,6 +67,12 @@ void Peer::onReceive(const RuntimeEnvironment *_r,Demarc::Port localPort,const I wp->localPort = localPort; if (!wp->fixed) wp->addr = remoteAddr; + + if ((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) { + _lastAnnouncedTo = now; + _r->sw->announceMulticastGroups(SharedPtr<Peer>(this)); + } + _dirty = true; } diff --git a/node/Peer.hpp b/node/Peer.hpp index 38b93a32..e9b24bd8 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -62,8 +62,8 @@ 16 + \ 1 \ ) * 2) + \ - sizeof(uint64_t) + \ - sizeof(uint64_t) \ + (sizeof(uint64_t) * 3) + \ + (sizeof(uint16_t) * 3) \ ) namespace ZeroTier { @@ -214,6 +214,15 @@ public: } /** + * @return Time we last announced state TO this peer, such as multicast LIKEs + */ + uint64_t lastAnnouncedTo() const + throw() + { + return _lastAnnouncedTo; + } + + /** * @return Lowest of measured latencies of all paths or 0 if unknown */ unsigned int latency() const @@ -367,6 +376,10 @@ public: _ipv6p.serialize(b); b.append(_lastUnicastFrame); b.append(_lastMulticastFrame); + b.append(_lastAnnouncedTo); + b.append((uint16_t)_vMajor); + b.append((uint16_t)_vMinor); + b.append((uint16_t)_vRevision); } template<unsigned int C> @@ -384,10 +397,11 @@ public: p += _ipv6p.deserialize(b,p); _lastUnicastFrame = b.template at<uint64_t>(p); p += sizeof(uint64_t); _lastMulticastFrame = b.template at<uint64_t>(p); p += sizeof(uint64_t); + _lastAnnouncedTo = b.template at<uint64_t>(p); p += sizeof(uint64_t); + _vMajor = b.template at<uint16_t>(p); p += sizeof(uint16_t); + _vMinor = b.template at<uint16_t>(p); p += sizeof(uint16_t); + _vRevision = b.template at<uint16_t>(p); p += sizeof(uint16_t); - _vMajor = 0; - _vMinor = 0; - _vRevision = 0; _dirty = false; return (p - startAt); @@ -516,12 +530,12 @@ private: uint64_t _lastUnicastFrame; uint64_t _lastMulticastFrame; + uint64_t _lastAnnouncedTo; + unsigned int _vMajor,_vMinor,_vRevision; - // Fields below this line are not persisted with serialize() + // Fields below this line are not persisted with serialize() --------------- - unsigned int _vMajor,_vMinor,_vRevision; bool _dirty; - AtomicCounter __refCount; }; diff --git a/node/Switch.cpp b/node/Switch.cpp index 14b658a7..896c6435 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -400,6 +400,7 @@ void Switch::announceMulticastGroups(const std::map< SharedPtr<Network>,std::set outp.reset((*p)->address(),_r->identity.address(),Packet::VERB_MULTICAST_LIKE); } + // network ID, MAC, ADI outp.append((uint64_t)nwmgs->first->id()); outp.append(mg->mac().data,6); outp.append((uint32_t)mg->adi()); @@ -412,6 +413,30 @@ void Switch::announceMulticastGroups(const std::map< SharedPtr<Network>,std::set } } +void Switch::announceMulticastGroups(const SharedPtr<Peer> &peer) +{ + Packet outp(peer->address(),_r->identity.address(),Packet::VERB_MULTICAST_LIKE); + std::vector< SharedPtr<Network> > networks(_r->nc->networks()); + for(std::vector< SharedPtr<Network> >::iterator n(networks.begin());n!=networks.end();++n) { + if (((*n)->isAllowed(peer->address()))||(_r->topology->isSupernode(peer->address()))) { + std::set<MulticastGroup> mgs((*n)->multicastGroups()); + for(std::set<MulticastGroup>::iterator mg(mgs.begin());mg!=mgs.end();++mg) { + if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) { + send(outp,true); + outp.reset(peer->address(),_r->identity.address(),Packet::VERB_MULTICAST_LIKE); + } + + // network ID, MAC, ADI + outp.append((uint64_t)(*n)->id()); + outp.append(mg->mac().data,6); + outp.append((uint32_t)mg->adi()); + } + } + } + if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) + send(outp,true); +} + void Switch::requestWhois(const Address &addr) { TRACE("requesting WHOIS for %s",addr.toString().c_str()); diff --git a/node/Switch.hpp b/node/Switch.hpp index bac12a50..d9032a27 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -153,14 +153,26 @@ public: /** * Announce multicast group memberships * - * This efficiently announces memberships, sending single packets with - * many LIKEs. + * This announces all the groups for all the networks in the supplied map to + * all peers with whom we have an active direct link. Only isAllowed() peers + * and supernodes get announcements for each given network. * * @param allMemberships Memberships for a number of networks */ void announceMulticastGroups(const std::map< SharedPtr<Network>,std::set<MulticastGroup> > &allMemberships); /** + * Announce multicast group memberships + * + * This announces all current multicast memberships to a single peer. Only + * memberships for networks where the peer isAllowed() are included, unless + * the peer is a supernode. + * + * @param peer Peer to announce all memberships to + */ + void announceMulticastGroups(const SharedPtr<Peer> &peer); + + /** * Request WHOIS on a given address * * @param addr Address to look up |