From 625ddf41a75e73e3613453e1166de19a756d7e7f Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 4 May 2015 17:41:48 -0700 Subject: [PATCH 1/6] docs --- include/ZeroTierOne.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index fd1cf81b9..ecc2edef2 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -416,7 +416,7 @@ typedef struct uint64_t nwid; /** - * Ethernet MAC (40 bits) that should be assigned to port + * Ethernet MAC (48 bits) that should be assigned to port */ uint64_t mac; From b4b067bf12489a0b3e701515959f81ca96a29240 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 4 May 2015 18:34:30 -0700 Subject: [PATCH 2/6] So we need to keep track of external surface per reporter, since some NATs assign different external IPs for each external destination. Keeping just one known surface could create a race condition. --- node/IncomingPacket.cpp | 4 +- node/InetAddress.hpp | 3 -- node/Node.cpp | 1 + node/SelfAwareness.cpp | 93 +++++++++++++++++++++++++---------------- node/SelfAwareness.hpp | 36 ++++++++++++++-- 5 files changed, 92 insertions(+), 45 deletions(-) diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 453e3945d..7833382a0 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -273,7 +273,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) trusted = true; } if (destAddr) - RR->sa->iam(id.address(),_remoteAddress,destAddr,trusted); + RR->sa->iam(id.address(),_remoteAddress,destAddr,trusted,RR->node->now()); Packet outp(id.address(),RR->identity.address(),Packet::VERB_OK); @@ -358,7 +358,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p trusted = true; } if (destAddr) - RR->sa->iam(peer->address(),_remoteAddress,destAddr,trusted); + RR->sa->iam(peer->address(),_remoteAddress,destAddr,trusted,RR->node->now()); } break; case Packet::VERB_WHOIS: { diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index 0cc4542ba..5b7251745 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -63,9 +63,6 @@ struct InetAddress : public sockaddr_storage /** * IP address scope - * - * Do not change these numeric index values without taking a look - * at SelfAwareness. Values 1-5 are mapped onto an array index. */ enum IpScope { diff --git a/node/Node.cpp b/node/Node.cpp index 7d5bbe8b4..654465e8d 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -264,6 +264,7 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next try { RR->topology->clean(now); + RR->sa->clean(now); } catch ( ... ) { return ZT1_RESULT_FATAL_ERROR_INTERNAL; } diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index b1830ef03..1e1f09f76 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -37,6 +37,9 @@ #include "Packet.hpp" #include "Peer.hpp" +// Entry timeout -- make it fairly long since this is just to prevent stale buildup +#define ZT_SELFAWARENESS_ENTRY_TIMEOUT 3600000 + namespace ZeroTier { class _ResetWithinScope @@ -64,53 +67,59 @@ private: SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) : RR(renv) { - memset(_lastPhysicalAddress,0,sizeof(_lastPhysicalAddress)); } SelfAwareness::~SelfAwareness() { } -void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted) +void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now) { - // This code depends on the numeric values assigned to scopes in InetAddress.hpp - const unsigned int scope = (unsigned int)myPhysicalAddress.ipScope(); - if ((scope > 0)&&(scope < (unsigned int)InetAddress::IP_SCOPE_LOOPBACK)) { - if ( (!trusted) && ((scope == (unsigned int)InetAddress::IP_SCOPE_GLOBAL)||(scope != (unsigned int)reporterPhysicalAddress.ipScope())) ) { - /* For now only trusted peers are permitted to inform us of changes to - * our global Internet IP or to changes of NATed IPs. We'll let peers on - * private, shared, or link-local networks inform us of changes as long - * as they too are at the same scope. This discrimination avoids a DoS - * attack in which an attacker could force us to reset our connections. */ + const InetAddress::IpScope scope = myPhysicalAddress.ipScope(); + + switch(scope) { + case InetAddress::IP_SCOPE_NONE: + case InetAddress::IP_SCOPE_LOOPBACK: + case InetAddress::IP_SCOPE_MULTICAST: return; - } else { - Mutex::Lock _l(_lock); - InetAddress &lastPhy = _lastPhysicalAddress[scope - 1]; - if (!lastPhy) { - TRACE("learned physical address %s for scope %u from reporter %s(%s) (replaced )",myPhysicalAddress.toString().c_str(),scope,reporter.toString().c_str(),reporterPhysicalAddress.toString().c_str()); - lastPhy = myPhysicalAddress; - } else if (lastPhy != myPhysicalAddress) { - TRACE("learned physical address %s for scope %u from reporter %s(%s) (replaced %s, resetting within scope)",myPhysicalAddress.toString().c_str(),scope,reporter.toString().c_str(),reporterPhysicalAddress.toString().c_str(),lastPhy.toString().c_str()); - lastPhy = myPhysicalAddress; - uint64_t now = RR->node->now(); + case InetAddress::IP_SCOPE_GLOBAL: + if ((!trusted)||(scope != reporterPhysicalAddress.ipScope())) + return; + break; + default: + if (scope != reporterPhysicalAddress.ipScope()) + return; + break; + } - _ResetWithinScope rset(RR,now,(InetAddress::IpScope)scope); - RR->topology->eachPeer<_ResetWithinScope &>(rset); + Mutex::Lock _l(_phy_m); - // For all peers for whom we forgot an address, send a packet indirectly if - // they are still considered alive so that we will re-establish direct links. - SharedPtr sn(RR->topology->getBestSupernode()); - if (sn) { - Path *snp = sn->getBestPath(now); - if (snp) { - for(std::vector< SharedPtr >::const_iterator p(rset.peersReset.begin());p!=rset.peersReset.end();++p) { - if ((*p)->alive(now)) { - TRACE("sending indirect NOP to %s via %s(%s) to re-establish link",(*p)->address().toString().c_str(),sn->address().toString().c_str(),snp->address().toString().c_str()); - Packet outp((*p)->address(),RR->identity.address(),Packet::VERB_NOP); - outp.armor((*p)->key(),true); - snp->send(RR,outp.data(),outp.size(),now); - } - } + PhySurfaceEntry &entry = _phy[PhySurfaceKey(reporter,scope)]; + + if (!entry.ts) { + entry.mySurface = myPhysicalAddress; + entry.ts = now; + TRACE("learned physical address %s for scope %u as seen from %s(%s) (replaced )",myPhysicalAddress.toString().c_str(),(unsigned int)scope,reporter.toString().c_str(),reporterPhysicalAddress.toString().c_str()); + } else if (entry.mySurface != myPhysicalAddress) { + entry.mySurface = myPhysicalAddress; + entry.ts = now; + TRACE("learned physical address %s for scope %u as seen from %s(%s) (replaced %s, resetting all in scope)",myPhysicalAddress.toString().c_str(),(unsigned int)scope,reporter.toString().c_str(),reporterPhysicalAddress.toString().c_str(),entry.mySurface.toString().c_str()); + + _ResetWithinScope rset(RR,now,(InetAddress::IpScope)scope); + RR->topology->eachPeer<_ResetWithinScope &>(rset); + + // For all peers for whom we forgot an address, send a packet indirectly if + // they are still considered alive so that we will re-establish direct links. + SharedPtr sn(RR->topology->getBestSupernode()); + if (sn) { + Path *snp = sn->getBestPath(now); + if (snp) { + for(std::vector< SharedPtr >::const_iterator p(rset.peersReset.begin());p!=rset.peersReset.end();++p) { + if ((*p)->alive(now)) { + TRACE("sending indirect NOP to %s via %s(%s) to re-establish link",(*p)->address().toString().c_str(),sn->address().toString().c_str(),snp->address().toString().c_str()); + Packet outp((*p)->address(),RR->identity.address(),Packet::VERB_NOP); + outp.armor((*p)->key(),true); + snp->send(RR,outp.data(),outp.size(),now); } } } @@ -118,4 +127,14 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysi } } +void SelfAwareness::clean(uint64_t now) +{ + Mutex::Lock _l(_phy_m); + for(std::map< PhySurfaceKey,PhySurfaceEntry >::iterator p(_phy.begin());p!=_phy.end();) { + if ((now - p->second.ts) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT) + _phy.erase(p++); + else ++p; + } +} + } // namespace ZeroTier diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index 2eb9b59f1..4780fa5b5 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -28,6 +28,8 @@ #ifndef ZT_SELFAWARENESS_HPP #define ZT_SELFAWARENESS_HPP +#include + #include "InetAddress.hpp" #include "Address.hpp" #include "Mutex.hpp" @@ -52,13 +54,41 @@ public: * @param reporterPhysicalAddress Physical address that reporting peer seems to have * @param myPhysicalAddress Physical address that peer says we have * @param trusted True if this peer is trusted as an authority to inform us of external address changes + * @param now Current time */ - void iam(const Address &reporter,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted); + void iam(const Address &reporter,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now); + + /** + * Clean up database periodically + * + * @param now Current time + */ + void clean(uint64_t now); private: + struct PhySurfaceKey + { + Address reporter; + InetAddress::IpScope scope; + + PhySurfaceKey() : reporter(),scope(InetAddress::IP_SCOPE_NONE) {} + PhySurfaceKey(const Address &r,InetAddress::IpScope s) : reporter(r),scope(s) {} + inline bool operator<(const PhySurfaceKey &k) const throw() { return ((reporter < k.reporter) ? true : ((reporter == k.reporter) ? ((int)scope < (int)k.scope) : false)); } + inline bool operator==(const PhySurfaceKey &k) const throw() { return ((reporter == k.reporter)&&(scope == k.scope)); } + }; + struct PhySurfaceEntry + { + InetAddress mySurface; + uint64_t ts; + + PhySurfaceEntry() : mySurface(),ts(0) {} + PhySurfaceEntry(const InetAddress &a,const uint64_t t) : mySurface(a),ts(t) {} + }; + const RuntimeEnvironment *RR; - Mutex _lock; - InetAddress _lastPhysicalAddress[5]; // 5 == the number of address classes we care about, see InetAddress.hpp and SelfAwareness.cpp + + std::map< PhySurfaceKey,PhySurfaceEntry > _phy; + Mutex _phy_m; }; } // namespace ZeroTier From e922324bc61f3d4fd96c66f628d3b84d50551cec Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 4 May 2015 18:39:53 -0700 Subject: [PATCH 3/6] Stop inlining all the Packet armor/dearmor stuff to reduce binary bloat. This stuff is called all over the place. --- node/Packet.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++++++ node/Packet.hpp | 91 +++---------------------------------------------- 2 files changed, 91 insertions(+), 86 deletions(-) diff --git a/node/Packet.cpp b/node/Packet.cpp index 8a2d7c5d0..176dea09e 100644 --- a/node/Packet.cpp +++ b/node/Packet.cpp @@ -71,4 +71,90 @@ const char *Packet::errorString(ErrorCode e) return "(unknown)"; } +void Packet::armor(const void *key,bool encryptPayload) +{ + unsigned char mangledKey[32]; + unsigned char macKey[32]; + unsigned char mac[16]; + const unsigned int payloadLen = size() - ZT_PACKET_IDX_VERB; + unsigned char *const payload = field(ZT_PACKET_IDX_VERB,payloadLen); + + // Set flag now, since it affects key mangle function + setCipher(encryptPayload ? ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012 : ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE); + + _salsa20MangleKey((const unsigned char *)key,mangledKey); + Salsa20 s20(mangledKey,256,field(ZT_PACKET_IDX_IV,8),ZT_PROTO_SALSA20_ROUNDS); + + // MAC key is always the first 32 bytes of the Salsa20 key stream + // This is the same construction DJB's NaCl library uses + s20.encrypt(ZERO_KEY,macKey,sizeof(macKey)); + + if (encryptPayload) + s20.encrypt(payload,payload,payloadLen); + + Poly1305::compute(mac,payload,payloadLen,macKey); + memcpy(field(ZT_PACKET_IDX_MAC,8),mac,8); +} + +bool Packet::dearmor(const void *key) +{ + unsigned char mangledKey[32]; + unsigned char macKey[32]; + unsigned char mac[16]; + const unsigned int payloadLen = size() - ZT_PACKET_IDX_VERB; + unsigned char *const payload = field(ZT_PACKET_IDX_VERB,payloadLen); + unsigned int cs = cipher(); + + if ((cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)||(cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012)) { + _salsa20MangleKey((const unsigned char *)key,mangledKey); + Salsa20 s20(mangledKey,256,field(ZT_PACKET_IDX_IV,8),ZT_PROTO_SALSA20_ROUNDS); + + s20.encrypt(ZERO_KEY,macKey,sizeof(macKey)); + Poly1305::compute(mac,payload,payloadLen,macKey); + if (!Utils::secureEq(mac,field(ZT_PACKET_IDX_MAC,8),8)) + return false; + + if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) + s20.decrypt(payload,payload,payloadLen); + + return true; + } else if (cs == ZT_PROTO_CIPHER_SUITE__C25519_AES256_GCM) { + return false; // not implemented yet + } else return false; // unrecognized cipher suite +} + +bool Packet::compress() +{ + unsigned char buf[ZT_PROTO_MAX_PACKET_LENGTH * 2]; + if ((!compressed())&&(size() > (ZT_PACKET_IDX_PAYLOAD + 32))) { + int pl = (int)(size() - ZT_PACKET_IDX_PAYLOAD); + int cl = LZ4_compress((const char *)field(ZT_PACKET_IDX_PAYLOAD,(unsigned int)pl),(char *)buf,pl); + if ((cl > 0)&&(cl < pl)) { + (*this)[ZT_PACKET_IDX_VERB] |= (char)ZT_PROTO_VERB_FLAG_COMPRESSED; + setSize((unsigned int)cl + ZT_PACKET_IDX_PAYLOAD); + memcpy(field(ZT_PACKET_IDX_PAYLOAD,(unsigned int)cl),buf,cl); + return true; + } + } + (*this)[ZT_PACKET_IDX_VERB] &= (char)(~ZT_PROTO_VERB_FLAG_COMPRESSED); + return false; +} + +bool Packet::uncompress() +{ + unsigned char buf[ZT_PROTO_MAX_PACKET_LENGTH]; + if ((compressed())&&(size() >= ZT_PROTO_MIN_PACKET_LENGTH)) { + if (size() > ZT_PACKET_IDX_PAYLOAD) { + unsigned int compLen = size() - ZT_PACKET_IDX_PAYLOAD; + int ucl = LZ4_decompress_safe((const char *)field(ZT_PACKET_IDX_PAYLOAD,compLen),(char *)buf,compLen,sizeof(buf)); + if ((ucl > 0)&&(ucl <= (int)(capacity() - ZT_PACKET_IDX_PAYLOAD))) { + setSize((unsigned int)ucl + ZT_PACKET_IDX_PAYLOAD); + memcpy(field(ZT_PACKET_IDX_PAYLOAD,(unsigned int)ucl),buf,ucl); + } else return false; + } + (*this)[ZT_PACKET_IDX_VERB] &= (char)(~ZT_PROTO_VERB_FLAG_COMPRESSED); + } + return true; +} + } // namespace ZeroTier diff --git a/node/Packet.hpp b/node/Packet.hpp index d79ba2bd2..d365e8455 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -1019,10 +1019,7 @@ public: /** * @return Raw packet payload */ - inline const unsigned char *payload() const - { - return field(ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD); - } + inline const unsigned char *payload() const { return field(ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD); } /** * Armor packet for transport @@ -1030,30 +1027,7 @@ public: * @param key 32-byte key * @param encryptPayload If true, encrypt packet payload, else just MAC */ - inline void armor(const void *key,bool encryptPayload) - { - unsigned char mangledKey[32]; - unsigned char macKey[32]; - unsigned char mac[16]; - const unsigned int payloadLen = size() - ZT_PACKET_IDX_VERB; - unsigned char *const payload = field(ZT_PACKET_IDX_VERB,payloadLen); - - // Set flag now, since it affects key mangle function - setCipher(encryptPayload ? ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012 : ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE); - - _salsa20MangleKey((const unsigned char *)key,mangledKey); - Salsa20 s20(mangledKey,256,field(ZT_PACKET_IDX_IV,8),ZT_PROTO_SALSA20_ROUNDS); - - // MAC key is always the first 32 bytes of the Salsa20 key stream - // This is the same construction DJB's NaCl library uses - s20.encrypt(ZERO_KEY,macKey,sizeof(macKey)); - - if (encryptPayload) - s20.encrypt(payload,payload,payloadLen); - - Poly1305::compute(mac,payload,payloadLen,macKey); - memcpy(field(ZT_PACKET_IDX_MAC,8),mac,8); - } + void armor(const void *key,bool encryptPayload); /** * Verify and (if encrypted) decrypt packet @@ -1061,32 +1035,7 @@ public: * @param key 32-byte key * @return False if packet is invalid or failed MAC authenticity check */ - inline bool dearmor(const void *key) - { - unsigned char mangledKey[32]; - unsigned char macKey[32]; - unsigned char mac[16]; - const unsigned int payloadLen = size() - ZT_PACKET_IDX_VERB; - unsigned char *const payload = field(ZT_PACKET_IDX_VERB,payloadLen); - unsigned int cs = cipher(); - - if ((cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)||(cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012)) { - _salsa20MangleKey((const unsigned char *)key,mangledKey); - Salsa20 s20(mangledKey,256,field(ZT_PACKET_IDX_IV,8),ZT_PROTO_SALSA20_ROUNDS); - - s20.encrypt(ZERO_KEY,macKey,sizeof(macKey)); - Poly1305::compute(mac,payload,payloadLen,macKey); - if (!Utils::secureEq(mac,field(ZT_PACKET_IDX_MAC,8),8)) - return false; - - if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) - s20.decrypt(payload,payload,payloadLen); - - return true; - } else if (cs == ZT_PROTO_CIPHER_SUITE__C25519_AES256_GCM) { - return false; // not implemented yet - } else return false; // unrecognized cipher suite - } + bool dearmor(const void *key); /** * Attempt to compress payload if not already (must be unencrypted) @@ -1098,22 +1047,7 @@ public: * * @return True if compression occurred */ - inline bool compress() - { - unsigned char buf[ZT_PROTO_MAX_PACKET_LENGTH * 2]; - if ((!compressed())&&(size() > (ZT_PACKET_IDX_PAYLOAD + 32))) { - int pl = (int)(size() - ZT_PACKET_IDX_PAYLOAD); - int cl = LZ4_compress((const char *)field(ZT_PACKET_IDX_PAYLOAD,(unsigned int)pl),(char *)buf,pl); - if ((cl > 0)&&(cl < pl)) { - (*this)[ZT_PACKET_IDX_VERB] |= (char)ZT_PROTO_VERB_FLAG_COMPRESSED; - setSize((unsigned int)cl + ZT_PACKET_IDX_PAYLOAD); - memcpy(field(ZT_PACKET_IDX_PAYLOAD,(unsigned int)cl),buf,cl); - return true; - } - } - (*this)[ZT_PACKET_IDX_VERB] &= (char)(~ZT_PROTO_VERB_FLAG_COMPRESSED); - return false; - } + bool compress(); /** * Attempt to decompress payload if it is compressed (must be unencrypted) @@ -1123,22 +1057,7 @@ public: * * @return True if data is now decompressed and valid, false on error */ - inline bool uncompress() - { - unsigned char buf[ZT_PROTO_MAX_PACKET_LENGTH]; - if ((compressed())&&(size() >= ZT_PROTO_MIN_PACKET_LENGTH)) { - if (size() > ZT_PACKET_IDX_PAYLOAD) { - unsigned int compLen = size() - ZT_PACKET_IDX_PAYLOAD; - int ucl = LZ4_decompress_safe((const char *)field(ZT_PACKET_IDX_PAYLOAD,compLen),(char *)buf,compLen,sizeof(buf)); - if ((ucl > 0)&&(ucl <= (int)(capacity() - ZT_PACKET_IDX_PAYLOAD))) { - setSize((unsigned int)ucl + ZT_PACKET_IDX_PAYLOAD); - memcpy(field(ZT_PACKET_IDX_PAYLOAD,(unsigned int)ucl),buf,ucl); - } else return false; - } - (*this)[ZT_PACKET_IDX_VERB] &= (char)(~ZT_PROTO_VERB_FLAG_COMPRESSED); - } - return true; - } + bool uncompress(); private: static const unsigned char ZERO_KEY[32]; From 59fa68783054ace53aec4fc942a31c332e97a761 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 4 May 2015 18:43:24 -0700 Subject: [PATCH 4/6] Make timeout also apply to null check in iam() --- node/SelfAwareness.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 1e1f09f76..9f57cc691 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -96,7 +96,7 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysi PhySurfaceEntry &entry = _phy[PhySurfaceKey(reporter,scope)]; - if (!entry.ts) { + if ((now - entry.ts) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT) { entry.mySurface = myPhysicalAddress; entry.ts = now; TRACE("learned physical address %s for scope %u as seen from %s(%s) (replaced )",myPhysicalAddress.toString().c_str(),(unsigned int)scope,reporter.toString().c_str(),reporterPhysicalAddress.toString().c_str()); From 18ca6f34ff91a79fd67050459ec68c65ab3ff851 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 4 May 2015 18:45:39 -0700 Subject: [PATCH 5/6] Always update timestamp. --- node/SelfAwareness.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 9f57cc691..425fbb0bc 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -124,7 +124,7 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysi } } } - } + } else entry.ts = now; } void SelfAwareness::clean(uint64_t now) From 40f312a827ffecf7d5a233ee5d13b0a3bc88e8a6 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 4 May 2015 19:02:36 -0700 Subject: [PATCH 6/6] When we reset within scope, erase the other entries for that scope so we won't keep resetting the same scope repeatedly. --- node/SelfAwareness.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 425fbb0bc..d7c0e5cc4 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -105,6 +105,14 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysi entry.ts = now; TRACE("learned physical address %s for scope %u as seen from %s(%s) (replaced %s, resetting all in scope)",myPhysicalAddress.toString().c_str(),(unsigned int)scope,reporter.toString().c_str(),reporterPhysicalAddress.toString().c_str(),entry.mySurface.toString().c_str()); + // Erase all entries (other than this one) for this scope to prevent thrashing + // Note: we should probably not use 'entry' after this + for(std::map< PhySurfaceKey,PhySurfaceEntry >::iterator p(_phy.begin());p!=_phy.end();) { + if ((p->first.reporter != reporter)&&(p->first.scope == scope)) + _phy.erase(p++); + else ++p; + } + _ResetWithinScope rset(RR,now,(InetAddress::IpScope)scope); RR->topology->eachPeer<_ResetWithinScope &>(rset); @@ -124,7 +132,9 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysi } } } - } else entry.ts = now; + } else { + entry.ts = now; + } } void SelfAwareness::clean(uint64_t now)