Bunch of fixes to startup, pinging, and choice of route. Also some TRACE updates.

This commit is contained in:
Adam Ierymenko 2014-01-30 14:23:52 -08:00
parent 6e076e77d8
commit 490e86dde3
6 changed files with 32 additions and 24 deletions

View File

@ -543,7 +543,7 @@ Node::ReasonForTermination Node::run()
Thread::sleep(ZT_SLEEP_WAKE_SETTLE_TIME); 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)) { if ((resynchronize)||((now - lastNetworkFingerprintCheck) >= ZT_NETWORK_FINGERPRINT_CHECK_DELAY)) {
lastNetworkFingerprintCheck = now; lastNetworkFingerprintCheck = now;
uint64_t fp = _r->sysEnv->getNetworkConfigurationFingerprint(_r->nc->networkTapDeviceNames()); 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)) { if ((resynchronize)||((now - lastSupernodePing) >= ZT_PEER_DIRECT_PING_DELAY)) {
lastSupernodePing = now; lastSupernodePing = now;
std::vector< SharedPtr<Peer> > sns(_r->topology->supernodePeers()); std::vector< SharedPtr<Peer> > sns(_r->topology->supernodePeers());
TRACE("pinging %d supernodes",(int)sns.size());
for(std::vector< SharedPtr<Peer> >::const_iterator p(sns.begin());p!=sns.end();++p) for(std::vector< SharedPtr<Peer> >::const_iterator p(sns.begin());p!=sns.end();++p)
_r->sw->sendHELLO((*p)->address()); (*p)->sendPing(_r,now);
} }
if (resynchronize) { if (resynchronize) {

View File

@ -51,7 +51,7 @@ bool PacketDecoder::tryDecode(const RuntimeEnvironment *_r)
// Unencrypted HELLOs are handled here since they are used to // Unencrypted HELLOs are handled here since they are used to
// populate our identity cache in the first place. _doHELLO() is special // populate our identity cache in the first place. _doHELLO() is special
// in that it contains its own authentication logic. // 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); return _doHELLO(_r);
} }
@ -78,9 +78,10 @@ bool PacketDecoder::tryDecode(const RuntimeEnvironment *_r)
return true; return true;
} }
TRACE("<< %s from %s(%s)",Packet::verbString(verb()),source().toString().c_str(),_remoteAddress.toString().c_str());
switch(verb()) { switch(verb()) {
case Packet::VERB_NOP: 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()); peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_NOP,0,Packet::VERB_NOP,Utils::now());
return true; return true;
case Packet::VERB_HELLO: case Packet::VERB_HELLO:
@ -107,11 +108,7 @@ bool PacketDecoder::tryDecode(const RuntimeEnvironment *_r)
return _doNETWORK_CONFIG_REQUEST(_r,peer); return _doNETWORK_CONFIG_REQUEST(_r,peer);
case Packet::VERB_NETWORK_CONFIG_REFRESH: case Packet::VERB_NETWORK_CONFIG_REFRESH:
return _doNETWORK_CONFIG_REFRESH(_r,peer); return _doNETWORK_CONFIG_REFRESH(_r,peer);
default: default: // ignore unknown verbs
// 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());
return true; return true;
} }
} else { } else {

View File

@ -77,12 +77,6 @@ void Peer::onReceive(
uint64_t now) uint64_t now)
{ {
if (!hops) { // direct packet 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<Peer>(this));
}
// Update last receive info for our direct path // Update last receive info for our direct path
WanPath *const wp = (remoteAddr.isV4() ? &_ipv4p : &_ipv6p); WanPath *const wp = (remoteAddr.isV4() ? &_ipv4p : &_ipv6p);
wp->lastReceive = now; 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<Peer>(this));
}
} }
if (verb == Packet::VERB_FRAME) { if (verb == Packet::VERB_FRAME) {
@ -150,12 +150,14 @@ bool Peer::sendPing(const RuntimeEnvironment *_r,uint64_t now)
{ {
bool sent = false; bool sent = false;
if (_ipv4p.addr) { if (_ipv4p.addr) {
TRACE("PING %s(%s)",_id.address().toString().c_str(),_ipv4p.addr.toString().c_str());
if (_r->sw->sendHELLO(SharedPtr<Peer>(this),_ipv4p.localPort,_ipv4p.addr)) { if (_r->sw->sendHELLO(SharedPtr<Peer>(this),_ipv4p.localPort,_ipv4p.addr)) {
_ipv4p.lastSend = now; _ipv4p.lastSend = now;
sent = true; sent = true;
} }
} }
if (_ipv6p.addr) { if (_ipv6p.addr) {
TRACE("PING %s(%s)",_id.address().toString().c_str(),_ipv6p.addr.toString().c_str());
if (_r->sw->sendHELLO(SharedPtr<Peer>(this),_ipv6p.localPort,_ipv6p.addr)) { if (_r->sw->sendHELLO(SharedPtr<Peer>(this),_ipv6p.localPort,_ipv6p.addr)) {
_ipv6p.lastSend = now; _ipv6p.lastSend = now;
sent = true; sent = true;

View File

@ -256,9 +256,8 @@ public:
inline bool hasDirectPath() const throw() { return ((_ipv4p.addr)||(_ipv6p.addr)); } 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 * @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))); } 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 inline bool isActive(const uint64_t now) const
throw() throw()
{ {
return ((addr)&&((now - lastReceive) < ZT_PEER_LINK_ACTIVITY_TIMEOUT)); return ((addr)&&((fixed)||((now - lastReceive) < ZT_PEER_LINK_ACTIVITY_TIMEOUT)));
} }
template<unsigned int C> template<unsigned int C>

View File

@ -700,7 +700,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt)
uint64_t now = Utils::now(); uint64_t now = Utils::now();
SharedPtr<Peer> via; SharedPtr<Peer> via;
if ((_r->topology->isSupernode(peer->address()))||(peer->hasActiveDirectPath(now))) { if (peer->hasActiveDirectPath(now)) {
via = peer; via = peer;
} else { } else {
via = _r->topology->getBestSupernode(); via = _r->topology->getBestSupernode();
@ -745,6 +745,14 @@ bool Switch::_trySend(const Packet &packet,bool encrypt)
break; 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 true;
} }
return false; return false;

View File

@ -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 class PingPeersThatNeedPing
{ {
public: public:
PingPeersThatNeedPing(const RuntimeEnvironment *renv,uint64_t now) throw() : PingPeersThatNeedPing(const RuntimeEnvironment *renv,uint64_t now) throw() :
_now(now), _now(now),
_supernodeAddresses(renv->topology->supernodeAddresses()),
_r(renv) {} _r(renv) {}
inline void operator()(Topology &t,const SharedPtr<Peer> &p) inline void operator()(Topology &t,const SharedPtr<Peer> &p)
@ -228,8 +229,8 @@ public:
( (
(p->hasDirectPath())&& (p->hasDirectPath())&&
((_now - p->lastFrame()) < ZT_PEER_LINK_ACTIVITY_TIMEOUT) ((_now - p->lastFrame()) < ZT_PEER_LINK_ACTIVITY_TIMEOUT)
) || ) &&
(t.isSupernode(p->address())) (!_supernodeAddresses.count(p->address()))
) )
) { ) {
p->sendPing(_r,_now); p->sendPing(_r,_now);
@ -238,6 +239,7 @@ public:
private: private:
uint64_t _now; uint64_t _now;
std::set<Address> _supernodeAddresses;
const RuntimeEnvironment *_r; const RuntimeEnvironment *_r;
}; };
@ -259,10 +261,9 @@ public:
{ {
if (_supernodeAddresses.count(p->address())) if (_supernodeAddresses.count(p->address()))
return; // skip supernodes return; // skip supernodes
TRACE(">> %s",p->address().toString().c_str());
p->forgetDirectPaths(false); // false means don't forget 'fixed' paths e.g. supernodes p->forgetDirectPaths(false); // false means don't forget 'fixed' paths e.g. supernodes
if (((_now - p->lastFrame()) < ZT_PEER_LINK_ACTIVITY_TIMEOUT)&&(_supernode)) { 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); Packet outp(p->address(),_r->identity.address(),Packet::VERB_NOP);
outp.armor(p->key(),false); // no need to encrypt a NOP outp.armor(p->key(),false); // no need to encrypt a NOP
_supernode->send(_r,outp.data(),outp.size(),_now); _supernode->send(_r,outp.data(),outp.size(),_now);