From 490e86dde3532b36617548bdf9d952caa43dffa3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 30 Jan 2014 14:23:52 -0800 Subject: [PATCH] Bunch of fixes to startup, pinging, and choice of route. Also some TRACE updates. --- node/Node.cpp | 5 +++-- node/PacketDecoder.cpp | 11 ++++------- node/Peer.cpp | 14 ++++++++------ node/Peer.hpp | 5 ++--- node/Switch.cpp | 10 +++++++++- node/Topology.hpp | 11 ++++++----- 6 files changed, 32 insertions(+), 24 deletions(-) diff --git a/node/Node.cpp b/node/Node.cpp index 323e8b210..fe3407bed 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -543,7 +543,7 @@ Node::ReasonForTermination Node::run() Thread::sleep(ZT_SLEEP_WAKE_SETTLE_TIME); } - // If our network environment looks like it changed, also set resynchronize flag. + // If our network environment looks like it changed, resynchronize. if ((resynchronize)||((now - lastNetworkFingerprintCheck) >= ZT_NETWORK_FINGERPRINT_CHECK_DELAY)) { lastNetworkFingerprintCheck = now; uint64_t fp = _r->sysEnv->getNetworkConfigurationFingerprint(_r->nc->networkTapDeviceNames()); @@ -559,8 +559,9 @@ Node::ReasonForTermination Node::run() if ((resynchronize)||((now - lastSupernodePing) >= ZT_PEER_DIRECT_PING_DELAY)) { lastSupernodePing = now; std::vector< SharedPtr > sns(_r->topology->supernodePeers()); + TRACE("pinging %d supernodes",(int)sns.size()); for(std::vector< SharedPtr >::const_iterator p(sns.begin());p!=sns.end();++p) - _r->sw->sendHELLO((*p)->address()); + (*p)->sendPing(_r,now); } if (resynchronize) { diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp index 919b537e8..25ec85ce6 100644 --- a/node/PacketDecoder.cpp +++ b/node/PacketDecoder.cpp @@ -51,7 +51,7 @@ bool PacketDecoder::tryDecode(const RuntimeEnvironment *_r) // Unencrypted HELLOs are handled here since they are used to // populate our identity cache in the first place. _doHELLO() is special // in that it contains its own authentication logic. - TRACE("HELLO from %s(%s)",source().toString().c_str(),_remoteAddress.toString().c_str()); + TRACE("<< HELLO from %s(%s) (normal unencrypted HELLO)",source().toString().c_str(),_remoteAddress.toString().c_str()); return _doHELLO(_r); } @@ -78,9 +78,10 @@ bool PacketDecoder::tryDecode(const RuntimeEnvironment *_r) return true; } + TRACE("<< %s from %s(%s)",Packet::verbString(verb()),source().toString().c_str(),_remoteAddress.toString().c_str()); + switch(verb()) { case Packet::VERB_NOP: - TRACE("NOP from %s(%s)",source().toString().c_str(),_remoteAddress.toString().c_str()); peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_NOP,0,Packet::VERB_NOP,Utils::now()); return true; case Packet::VERB_HELLO: @@ -107,11 +108,7 @@ bool PacketDecoder::tryDecode(const RuntimeEnvironment *_r) return _doNETWORK_CONFIG_REQUEST(_r,peer); case Packet::VERB_NETWORK_CONFIG_REFRESH: return _doNETWORK_CONFIG_REFRESH(_r,peer); - default: - // This might be something from a new or old version of the protocol. - // Technically it passed MAC so the packet is still valid, but we - // ignore it. - TRACE("ignored unrecognized verb %.2x from %s(%s)",(unsigned int)verb(),source().toString().c_str(),_remoteAddress.toString().c_str()); + default: // ignore unknown verbs return true; } } else { diff --git a/node/Peer.cpp b/node/Peer.cpp index 5a59031d2..512918de6 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -77,12 +77,6 @@ void Peer::onReceive( uint64_t now) { if (!hops) { // direct packet - // Announce multicast LIKEs to peers to whom we have a direct link - if ((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) { - _lastAnnouncedTo = now; - _r->sw->announceMulticastGroups(SharedPtr(this)); - } - // Update last receive info for our direct path WanPath *const wp = (remoteAddr.isV4() ? &_ipv4p : &_ipv6p); wp->lastReceive = now; @@ -100,6 +94,12 @@ void Peer::onReceive( } } } + + // Announce multicast LIKEs to peers to whom we have a direct link + if ((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) { + _lastAnnouncedTo = now; + _r->sw->announceMulticastGroups(SharedPtr(this)); + } } if (verb == Packet::VERB_FRAME) { @@ -150,12 +150,14 @@ bool Peer::sendPing(const RuntimeEnvironment *_r,uint64_t now) { bool sent = false; if (_ipv4p.addr) { + TRACE("PING %s(%s)",_id.address().toString().c_str(),_ipv4p.addr.toString().c_str()); if (_r->sw->sendHELLO(SharedPtr(this),_ipv4p.localPort,_ipv4p.addr)) { _ipv4p.lastSend = now; sent = true; } } if (_ipv6p.addr) { + TRACE("PING %s(%s)",_id.address().toString().c_str(),_ipv6p.addr.toString().c_str()); if (_r->sw->sendHELLO(SharedPtr(this),_ipv6p.localPort,_ipv6p.addr)) { _ipv6p.lastSend = now; sent = true; diff --git a/node/Peer.hpp b/node/Peer.hpp index 64e9c39a6..ac9de661f 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -256,9 +256,8 @@ public: inline bool hasDirectPath() const throw() { return ((_ipv4p.addr)||(_ipv6p.addr)); } /** - * @return True if this peer has at least one direct IP address path that looks active - * * @param now Current time + * @return True if this peer has at least one active or fixed direct path */ inline bool hasActiveDirectPath(uint64_t now) const throw() { return ((_ipv4p.isActive(now))||(_ipv6p.isActive(now))); } @@ -446,7 +445,7 @@ private: inline bool isActive(const uint64_t now) const throw() { - return ((addr)&&((now - lastReceive) < ZT_PEER_LINK_ACTIVITY_TIMEOUT)); + return ((addr)&&((fixed)||((now - lastReceive) < ZT_PEER_LINK_ACTIVITY_TIMEOUT))); } template diff --git a/node/Switch.cpp b/node/Switch.cpp index 9ec15411e..6c7d0fc93 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -700,7 +700,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt) uint64_t now = Utils::now(); SharedPtr via; - if ((_r->topology->isSupernode(peer->address()))||(peer->hasActiveDirectPath(now))) { + if (peer->hasActiveDirectPath(now)) { via = peer; } else { via = _r->topology->getBestSupernode(); @@ -745,6 +745,14 @@ bool Switch::_trySend(const Packet &packet,bool encrypt) break; } +#ifdef ZT_TRACE + if (via != peer) { + TRACE(">> %s to %s via %s (%d)",Packet::verbString(packet.verb()),peer->address().toString().c_str(),via->address().toString().c_str(),(int)packet.size()); + } else { + TRACE(">> %s to %s (%d)",Packet::verbString(packet.verb()),peer->address().toString().c_str(),(int)packet.size()); + } +#endif + return true; } return false; diff --git a/node/Topology.hpp b/node/Topology.hpp index 505cf10e8..4a6d711fc 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -211,13 +211,14 @@ public: }; /** - * Function object to collect peers that need a ping sent + * Pings all peers that need a ping sent, excluding supernodes (which are pinged separately) */ class PingPeersThatNeedPing { public: PingPeersThatNeedPing(const RuntimeEnvironment *renv,uint64_t now) throw() : _now(now), + _supernodeAddresses(renv->topology->supernodeAddresses()), _r(renv) {} inline void operator()(Topology &t,const SharedPtr &p) @@ -228,8 +229,8 @@ public: ( (p->hasDirectPath())&& ((_now - p->lastFrame()) < ZT_PEER_LINK_ACTIVITY_TIMEOUT) - ) || - (t.isSupernode(p->address())) + ) && + (!_supernodeAddresses.count(p->address())) ) ) { p->sendPing(_r,_now); @@ -238,6 +239,7 @@ public: private: uint64_t _now; + std::set
_supernodeAddresses; const RuntimeEnvironment *_r; }; @@ -259,10 +261,9 @@ public: { if (_supernodeAddresses.count(p->address())) return; // skip supernodes - TRACE(">> %s",p->address().toString().c_str()); p->forgetDirectPaths(false); // false means don't forget 'fixed' paths e.g. supernodes if (((_now - p->lastFrame()) < ZT_PEER_LINK_ACTIVITY_TIMEOUT)&&(_supernode)) { - TRACE("sending NOP to %s",p->address().toString().c_str()); + TRACE("sending reset NOP to %s",p->address().toString().c_str()); Packet outp(p->address(),_r->identity.address(),Packet::VERB_NOP); outp.armor(p->key(),false); // no need to encrypt a NOP _supernode->send(_r,outp.data(),outp.size(),_now);