From 0073d0f694f925d925db96d25e2a504abda99722 Mon Sep 17 00:00:00 2001 From: Moritz Warning Date: Fri, 19 Jun 2015 00:24:17 +0200 Subject: replace txQueue list by vector for faster memory access and less allocations --- node/Multicaster.cpp | 20 ++++++++++++-------- node/Multicaster.hpp | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'node') diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 7da2b14c..40be2441 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -320,10 +320,12 @@ void Multicaster::clean(uint64_t now) { Mutex::Lock _l(_groups_m); for(std::map< std::pair,MulticastGroupStatus >::iterator mm(_groups.begin());mm!=_groups.end();) { - for(std::list::iterator tx(mm->second.txQueue.begin());tx!=mm->second.txQueue.end();) { - if ((tx->expired(now))||(tx->atLimit())) - mm->second.txQueue.erase(tx++); - else ++tx; + for(std::vector::iterator tx(mm->second.txQueue.begin());tx!=mm->second.txQueue.end();) { + if ((tx->expired(now))||(tx->atLimit())) { + // erase element (replace by last) + *tx = mm->second.txQueue.back(); + mm->second.txQueue.pop_back(); + } else ++tx; } unsigned long count = 0; @@ -371,14 +373,16 @@ void Multicaster::_add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,Multi //TRACE("..MC %s joined multicast group %.16llx/%s via %s",member.toString().c_str(),nwid,mg.toString().c_str(),((learnedFrom) ? learnedFrom.toString().c_str() : "(direct)")); - for(std::list::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) { + for(std::vector::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) { if (tx->atLimit()) { gs.txQueue.erase(tx++); } else { tx->sendIfNew(RR,member); - if (tx->atLimit()) - gs.txQueue.erase(tx++); - else ++tx; + if (tx->atLimit()) { + // erase element (replace by last) + *tx = gs.txQueue.back(); + gs.txQueue.pop_back(); + } else ++tx; } } } diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index c6c93b1f..281222b8 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -70,7 +70,7 @@ private: MulticastGroupStatus() : lastExplicitGather(0) {} uint64_t lastExplicitGather; - std::list txQueue; // pending outbound multicasts + std::vector txQueue; // pending outbound multicasts std::vector members; // members of this group }; -- cgit v1.2.3 From 7bae95836c8824a76e0299df776a708eb3e58576 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 19 Jun 2015 10:23:25 -0700 Subject: Root server terminology cleanup, and tighten up a security check by checking full identity of peers instead of just address. --- include/ZeroTierOne.h | 4 +- node/Constants.hpp | 6 +-- node/IncomingPacket.cpp | 16 +++---- node/Multicaster.cpp | 47 +------------------- node/Network.cpp | 6 +-- node/Node.cpp | 14 +++--- node/Packet.hpp | 2 +- node/Peer.cpp | 6 +-- node/SelfAwareness.cpp | 2 +- node/Switch.cpp | 26 +++++------ node/Topology.cpp | 109 +++++++++++++++++++++++++---------------------- node/Topology.hpp | 73 +++++++++++++------------------ service/ControlPlane.cpp | 6 +-- 13 files changed, 131 insertions(+), 186 deletions(-) (limited to 'node') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index b67d97ed..b6ff69ab 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -559,8 +559,8 @@ typedef struct */ enum ZT1_PeerRole { ZT1_PEER_ROLE_LEAF = 0, // ordinary node - ZT1_PEER_ROLE_HUB = 1, // locally federated hub - ZT1_PEER_ROLE_ROOTSERVER = 2 // planetary rootserver + ZT1_PEER_ROLE_RELAY = 1, // relay node + ZT1_PEER_ROLE_ROOT = 2 // root server }; /** diff --git a/node/Constants.hpp b/node/Constants.hpp index aced6fe7..ac9dbc99 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -254,7 +254,7 @@ /** * Delay between scans of the topology active peer DB for peers that need ping * - * This is also how often pings will be retried to upstream peers (rootservers) + * This is also how often pings will be retried to upstream peers (relays, roots) * constantly until something is heard. */ #define ZT_PING_CHECK_INVERVAL 6250 @@ -279,9 +279,9 @@ * * When we send something (including frames), we generally expect a response. * Switching relays if no response in a short period of time causes more - * rapid failover if a rootserver goes down or becomes unreachable. In the + * rapid failover if a root server goes down or becomes unreachable. In the * mistaken case, little harm is done as it'll pick the next-fastest - * rootserver and will switch back eventually. + * root server and will switch back eventually. */ #define ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD 10000 diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 8f95b9ba..7e2bcdaa 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -110,7 +110,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr case Packet::ERROR_OBJ_NOT_FOUND: if (inReVerb == Packet::VERB_WHOIS) { - if (RR->topology->isRootserver(peer->address())) + if (RR->topology->isRoot(peer->identity())) RR->sw->cancelWhoisRequest(Address(field(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH)); } else if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) { SharedPtr network(RR->node->network(at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); @@ -128,7 +128,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr break; case Packet::ERROR_IDENTITY_COLLISION: - if (RR->topology->isRootserver(peer->address())) + if (RR->topology->isRoot(peer->identity())) RR->node->postEvent(ZT1_EVENT_FATAL_ERROR_IDENTITY_COLLISION); break; @@ -268,7 +268,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision); bool trusted = false; - if (RR->topology->isRootserver(id.address())) { + if (RR->topology->isRoot(id)) { RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision); trusted = true; } @@ -353,7 +353,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision); bool trusted = false; - if (RR->topology->isRootserver(peer->address())) { + if (RR->topology->isRoot(peer->identity())) { RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision); trusted = true; } @@ -362,10 +362,10 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p } break; case Packet::VERB_WHOIS: { - // Right now only rootservers are allowed to send OK(WHOIS) to prevent - // poisoning attacks. Further decentralization will require some other - // kind of trust mechanism. - if (RR->topology->isRootserver(peer->address())) { + /* Right now only root servers are allowed to send OK(WHOIS) to prevent + * poisoning attacks. Further decentralization will require some other + * kind of trust mechanism. */ + if (RR->topology->isRoot(peer->identity())) { const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY); if (id.locallyValidate()) RR->sw->doAnythingWaitingForPeer(RR->topology->addPeer(SharedPtr(new Peer(RR->identity,id)))); diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 360233fe..29e89189 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -216,7 +216,7 @@ void Multicaster::send( if ((now - gs.lastExplicitGather) >= ZT_MULTICAST_EXPLICIT_GATHER_DELAY) { gs.lastExplicitGather = now; - SharedPtr sn(RR->topology->getBestRootserver()); + SharedPtr sn(RR->topology->getBestRoot()); if (sn) { TRACE(">>MC upstream GATHER up to %u for group %.16llx/%s",gatherLimit,nwid,mg.toString().c_str()); @@ -269,51 +269,6 @@ void Multicaster::send( // Free allocated memory buffer if any if (indexes != idxbuf) delete [] indexes; - -#ifdef ZT_SUPPORT_LEGACY_MULTICAST - // This sends a P5 multicast up to our rootserver, who then - // redistributes it manually down to all <1.0.0 peers for - // legacy support. These peers don't support the new multicast - // frame type, so even if they receive it they will ignore it. - { - SharedPtr sn(RR->topology->getBestRootserver()); - if (sn) { - uint32_t rn = RR->prng->next32(); - Packet outp(sn->address(),RR->identity.address(),Packet::VERB_P5_MULTICAST_FRAME); - - outp.append((uint16_t)0xffff); // do not forward - outp.append((unsigned char)0,320 + 1024); // empty queue and bloom filter - - outp.append((unsigned char)((com) ? ZT_PROTO_VERB_P5_MULTICAST_FRAME_FLAGS_HAS_MEMBERSHIP_CERTIFICATE : 0)); - outp.append((uint64_t)nwid); - outp.append((uint16_t)0); - outp.append((unsigned char)0); - outp.append((unsigned char)0); - RR->identity.address().appendTo(outp); - outp.append((const void *)&rn,3); // random multicast ID - if (src) - src.appendTo(outp); - else MAC(RR->identity.address(),nwid).appendTo(outp); - mg.mac().appendTo(outp); - outp.append((uint32_t)mg.adi()); - outp.append((uint16_t)etherType); - outp.append((uint16_t)len); - outp.append(data,len); - unsigned int signedPortionLen = outp.size() - ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION; - - C25519::Signature sig(RR->identity.sign(outp.field(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION,signedPortionLen),signedPortionLen)); - - outp.append((uint16_t)sig.size()); - outp.append(sig.data,(unsigned int)sig.size()); - - if (com) com->serialize(outp); - - outp.compress(); - outp.armor(sn->key(),true); - sn->send(RR,outp.data(),outp.size(),now); - } - } -#endif // ZT_SUPPORT_LEGACY_MULTICAST } void Multicaster::clean(uint64_t now) diff --git a/node/Network.cpp b/node/Network.cpp index 60262cd5..a217595a 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -518,13 +518,13 @@ public: RR(renv), _now(renv->node->now()), _network(nw), - _rootserverAddresses(renv->topology->rootserverAddresses()), + _rootAddresses(renv->topology->rootAddresses()), _allMulticastGroups(nw->_allMulticastGroups()) {} inline void operator()(Topology &t,const SharedPtr &p) { - if ( ( (p->hasActiveDirectPath(_now)) && (_network->_isAllowed(p->address())) ) || (std::find(_rootserverAddresses.begin(),_rootserverAddresses.end(),p->address()) != _rootserverAddresses.end()) ) { + if ( ( (p->hasActiveDirectPath(_now)) && (_network->_isAllowed(p->address())) ) || (std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end()) ) { Packet outp(p->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); for(std::vector::iterator mg(_allMulticastGroups.begin());mg!=_allMulticastGroups.end();++mg) { @@ -551,7 +551,7 @@ private: const RuntimeEnvironment *RR; uint64_t _now; Network *_network; - std::vector
_rootserverAddresses; + std::vector
_rootAddresses; std::vector _allMulticastGroups; }; diff --git a/node/Node.cpp b/node/Node.cpp index 1f6d474c..45e2463c 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -133,9 +133,7 @@ Node::Node( if (!rt.size()) rt.fromString(ZT_DEFAULTS.defaultRootTopology); } - Dictionary rootservers(rt.get("rootservers","")); - rootservers.update(rt.get("supernodes","")); - RR->topology->setRootservers(rootservers); + RR->topology->setRootServers(Dictionary(rt.get("rootservers",""))); postEvent(ZT1_EVENT_UP); } @@ -191,7 +189,7 @@ public: RR(renv), _now(now), _relays(relays), - _rootservers(RR->topology->rootserverAddresses()) + _rootAddresses(RR->topology->rootAddresses()) { } @@ -207,7 +205,7 @@ public: } } - if ((isRelay)||(std::find(_rootservers.begin(),_rootservers.end(),p->address()) != _rootservers.end())) { + if ((isRelay)||(std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end())) { p->doPingAndKeepalive(RR,_now); if (p->lastReceive() > lastReceiveFromUpstream) lastReceiveFromUpstream = p->lastReceive(); @@ -221,7 +219,7 @@ private: const RuntimeEnvironment *RR; uint64_t _now; const std::vector< std::pair > &_relays; - std::vector
_rootservers; + std::vector
_rootAddresses; }; ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) @@ -262,7 +260,7 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next } } - // Ping living or rootserver/relay peers + // Ping living or root server/relay peers _PingPeersThatNeedPing pfunc(RR,now,networkRelays); RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc); @@ -386,7 +384,7 @@ ZT1_PeerList *Node::peers() const p->versionRev = -1; } p->latency = pi->second->latency(); - p->role = RR->topology->isRootserver(pi->second->address()) ? ZT1_PEER_ROLE_ROOTSERVER : ZT1_PEER_ROLE_LEAF; + p->role = RR->topology->isRoot(pi->second->identity()) ? ZT1_PEER_ROLE_ROOT : ZT1_PEER_ROLE_LEAF; std::vector paths(pi->second->paths()); Path *bestPath = pi->second->getBestPath(_now); diff --git a/node/Packet.hpp b/node/Packet.hpp index 21f8ca57..49201b71 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -626,7 +626,7 @@ public: * [... additional tuples of network/address/adi ...] * * LIKEs are sent to peers with whom you have a direct peer to peer - * connection, and always including rootservers. + * connection, and always including root servers. * * OK/ERROR are not generated. */ diff --git a/node/Peer.cpp b/node/Peer.cpp index 3093ef41..96caa72c 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -122,16 +122,16 @@ void Peer::received( /* Announce multicast groups of interest to direct peers if they are * considered authorized members of a given network. Also announce to - * rootservers and network controllers. */ + * root servers and network controllers. */ if ((pathIsConfirmed)&&((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000))) { _lastAnnouncedTo = now; - const bool isRootserver = RR->topology->isRootserver(_id.address()); + const bool isRoot = RR->topology->isRoot(_id); Packet outp(_id.address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); const std::vector< SharedPtr > networks(RR->node->allNetworks()); for(std::vector< SharedPtr >::const_iterator n(networks.begin());n!=networks.end();++n) { - if ( (isRootserver) || ((*n)->isAllowed(_id.address())) ) { + if ( (isRoot) || ((*n)->isAllowed(_id.address())) ) { const std::vector mgs((*n)->allMulticastGroups()); for(std::vector::const_iterator mg(mgs.begin());mg!=mgs.end();++mg) { if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) { diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 5fc8be2a..9f7c41d7 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -118,7 +118,7 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysi // 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->getBestRootserver()); + SharedPtr sn(RR->topology->getBestRoot()); if (sn) { Path *snp = sn->getBestPath(now); if (snp) { diff --git a/node/Switch.cpp b/node/Switch.cpp index 3ac0b920..af80f5e8 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -320,8 +320,8 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force) * P2 in randomized order in terms of which gets sent first. This is done * since in a few cases NAT-t can be sensitive to slight timing differences * in terms of when the two peers initiate. Normally this is accounted for - * by the nearly-simultaneous RENDEZVOUS kickoff from the rootserver, but - * given that rootservers are hosted on cloud providers this can in some + * by the nearly-simultaneous RENDEZVOUS kickoff from the relay, but + * given that relay are hosted on cloud providers this can in some * cases have a few ms of latency between packet departures. By randomizing * the order we make each attempted NAT-t favor one or the other going * first, meaning if it doesn't succeed the first time it might the second @@ -565,8 +565,8 @@ void Switch::_handleRemotePacketFragment(const InetAddress &fromAddr,const void // It wouldn't hurt anything, just redundant and unnecessary. SharedPtr relayTo = RR->topology->getPeer(destination); if ((!relayTo)||(!relayTo->send(RR,fragment.data(),fragment.size(),RR->node->now()))) { - // Don't know peer or no direct path -- so relay via rootserver - relayTo = RR->topology->getBestRootserver(); + // Don't know peer or no direct path -- so relay via root server + relayTo = RR->topology->getBestRoot(); if (relayTo) relayTo->send(RR,fragment.data(),fragment.size(),RR->node->now()); } @@ -641,8 +641,8 @@ void Switch::_handleRemotePacketHead(const InetAddress &fromAddr,const void *dat if ((relayTo)&&((relayTo->send(RR,packet->data(),packet->size(),RR->node->now())))) { unite(source,destination,false); } else { - // Don't know peer or no direct path -- so relay via rootserver - relayTo = RR->topology->getBestRootserver(&source,1,true); + // Don't know peer or no direct path -- so relay via root server + relayTo = RR->topology->getBestRoot(&source,1,true); if (relayTo) relayTo->send(RR,packet->data(),packet->size(),RR->node->now()); } @@ -712,13 +712,13 @@ void Switch::_handleBeacon(const InetAddress &fromAddr,const Buffer rootserver(RR->topology->getBestRootserver(peersAlreadyConsulted,numPeersAlreadyConsulted,false)); - if (rootserver) { - Packet outp(rootserver->address(),RR->identity.address(),Packet::VERB_WHOIS); + SharedPtr root(RR->topology->getBestRoot(peersAlreadyConsulted,numPeersAlreadyConsulted,false)); + if (root) { + Packet outp(root->address(),RR->identity.address(),Packet::VERB_WHOIS); addr.appendTo(outp); - outp.armor(rootserver->key(),true); - if (rootserver->send(RR,outp.data(),outp.size(),RR->node->now())) - return rootserver->address(); + outp.armor(root->key(),true); + if (root->send(RR,outp.data(),outp.size(),RR->node->now())) + return root->address(); } return Address(); } @@ -752,7 +752,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid) } if (!relay) - relay = RR->topology->getBestRootserver(); + relay = RR->topology->getBestRoot(); if (!(relay)||(!(viaPath = relay->getBestPath(now)))) return false; diff --git a/node/Topology.cpp b/node/Topology.cpp index cfa6749c..2b1cc31f 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -36,7 +36,7 @@ namespace ZeroTier { Topology::Topology(const RuntimeEnvironment *renv) : RR(renv), - _amRootserver(false) + _amRoot(false) { } @@ -44,16 +44,16 @@ Topology::~Topology() { } -void Topology::setRootservers(const std::map< Identity,std::vector > &sn) +void Topology::setRootServers(const std::map< Identity,std::vector > &sn) { Mutex::Lock _l(_lock); - if (_rootservers == sn) + if (_roots == sn) return; // no change - _rootservers = sn; - _rootserverAddresses.clear(); - _rootserverPeers.clear(); + _roots = sn; + _rootAddresses.clear(); + _rootPeers.clear(); const uint64_t now = RR->node->now(); for(std::map< Identity,std::vector >::const_iterator i(sn.begin());i!=sn.end();++i) { @@ -64,17 +64,17 @@ void Topology::setRootservers(const std::map< Identity,std::vector for(std::vector::const_iterator j(i->second.begin());j!=i->second.end();++j) p->addPath(Path(*j,true)); p->use(now); - _rootserverPeers.push_back(p); + _rootPeers.push_back(p); } - _rootserverAddresses.push_back(i->first.address()); + _rootAddresses.push_back(i->first.address()); } - std::sort(_rootserverAddresses.begin(),_rootserverAddresses.end()); + std::sort(_rootAddresses.begin(),_rootAddresses.end()); - _amRootserver = (_rootservers.find(RR->identity) != _rootservers.end()); + _amRoot = (_roots.find(RR->identity) != _roots.end()); } -void Topology::setRootservers(const Dictionary &sn) +void Topology::setRootServers(const Dictionary &sn) { std::map< Identity,std::vector > m; for(Dictionary::const_iterator d(sn.begin());d!=sn.end();++d) { @@ -86,11 +86,11 @@ void Topology::setRootservers(const Dictionary &sn) if (udp.length() > 0) a.push_back(InetAddress(udp)); } catch ( ... ) { - TRACE("rootserver list contained invalid entry for: %s",d->first.c_str()); + TRACE("root server list contained invalid entry for: %s",d->first.c_str()); } } } - this->setRootservers(m); + this->setRootServers(m); } SharedPtr Topology::addPeer(const SharedPtr &peer) @@ -141,28 +141,28 @@ SharedPtr Topology::getPeer(const Address &zta) return SharedPtr(); } -SharedPtr Topology::getBestRootserver(const Address *avoid,unsigned int avoidCount,bool strictAvoid) +SharedPtr Topology::getBestRoot(const Address *avoid,unsigned int avoidCount,bool strictAvoid) { - SharedPtr bestRootserver; + SharedPtr bestRoot; const uint64_t now = RR->node->now(); Mutex::Lock _l(_lock); - if (_amRootserver) { - /* If I am a rootserver, the "best" rootserver is the one whose address + if (_amRoot) { + /* If I am a root server, the "best" root server is the one whose address * is numerically greater than mine (with wrap at top of list). This * causes packets searching for a route to pretty much literally * circumnavigate the globe rather than bouncing between just two. */ - if (_rootserverAddresses.size() > 1) { // gotta be one other than me for this to work - std::vector
::const_iterator sna(std::find(_rootserverAddresses.begin(),_rootserverAddresses.end(),RR->identity.address())); - if (sna != _rootserverAddresses.end()) { // sanity check -- _amRootserver should've been false in this case + if (_rootAddresses.size() > 1) { // gotta be one other than me for this to work + std::vector
::const_iterator sna(std::find(_rootAddresses.begin(),_rootAddresses.end(),RR->identity.address())); + if (sna != _rootAddresses.end()) { // sanity check -- _amRoot should've been false in this case for(;;) { - if (++sna == _rootserverAddresses.end()) - sna = _rootserverAddresses.begin(); // wrap around at end + if (++sna == _rootAddresses.end()) + sna = _rootAddresses.begin(); // wrap around at end if (*sna != RR->identity.address()) { // pick one other than us -- starting from me+1 in sorted set order std::map< Address,SharedPtr >::const_iterator p(_activePeers.find(*sna)); if ((p != _activePeers.end())&&(p->second->hasActiveDirectPath(now))) { - bestRootserver = p->second; + bestRoot = p->second; break; } } @@ -170,80 +170,87 @@ SharedPtr Topology::getBestRootserver(const Address *avoid,unsigned int av } } } else { - /* If I am not a rootserver, the best rootserver is the active one with + /* If I am not a root server, the best root server is the active one with * the lowest latency. */ - unsigned int l,bestRootserverLatency = 65536; + unsigned int l,bestLatency = 65536; uint64_t lds,ldr; - // First look for a best rootserver by comparing latencies, but exclude - // rootservers that have not responded to direct messages in order to + // First look for a best root by comparing latencies, but exclude + // root servers that have not responded to direct messages in order to // try to exclude any that are dead or unreachable. - for(std::vector< SharedPtr >::const_iterator sn(_rootserverPeers.begin());sn!=_rootserverPeers.end();) { + for(std::vector< SharedPtr >::const_iterator sn(_rootPeers.begin());sn!=_rootPeers.end();) { // Skip explicitly avoided relays for(unsigned int i=0;iaddress()) - goto keep_searching_for_rootservers; + goto keep_searching_for_roots; } // Skip possibly comatose or unreachable relays lds = (*sn)->lastDirectSend(); ldr = (*sn)->lastDirectReceive(); if ((lds)&&(lds > ldr)&&((lds - ldr) > ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD)) - goto keep_searching_for_rootservers; + goto keep_searching_for_roots; if ((*sn)->hasActiveDirectPath(now)) { l = (*sn)->latency(); - if (bestRootserver) { - if ((l)&&(l < bestRootserverLatency)) { - bestRootserverLatency = l; - bestRootserver = *sn; + if (bestRoot) { + if ((l)&&(l < bestLatency)) { + bestLatency = l; + bestRoot = *sn; } } else { if (l) - bestRootserverLatency = l; - bestRootserver = *sn; + bestLatency = l; + bestRoot = *sn; } } -keep_searching_for_rootservers: +keep_searching_for_roots: ++sn; } - if (bestRootserver) { - bestRootserver->use(now); - return bestRootserver; + if (bestRoot) { + bestRoot->use(now); + return bestRoot; } else if (strictAvoid) return SharedPtr(); // If we have nothing from above, just pick one without avoidance criteria. - for(std::vector< SharedPtr >::const_iterator sn=_rootserverPeers.begin();sn!=_rootserverPeers.end();++sn) { + for(std::vector< SharedPtr >::const_iterator sn=_rootPeers.begin();sn!=_rootPeers.end();++sn) { if ((*sn)->hasActiveDirectPath(now)) { unsigned int l = (*sn)->latency(); - if (bestRootserver) { - if ((l)&&(l < bestRootserverLatency)) { - bestRootserverLatency = l; - bestRootserver = *sn; + if (bestRoot) { + if ((l)&&(l < bestLatency)) { + bestLatency = l; + bestRoot = *sn; } } else { if (l) - bestRootserverLatency = l; - bestRootserver = *sn; + bestLatency = l; + bestRoot = *sn; } } } } - if (bestRootserver) - bestRootserver->use(now); - return bestRootserver; + if (bestRoot) + bestRoot->use(now); + return bestRoot; +} + +bool Topology::isRoot(const Identity &id) const + throw() +{ + Mutex::Lock _l(_lock); + return (_roots.count(id) != 0); } void Topology::clean(uint64_t now) { Mutex::Lock _l(_lock); for(std::map< Address,SharedPtr >::iterator p(_activePeers.begin());p!=_activePeers.end();) { - if (((now - p->second->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(std::find(_rootserverAddresses.begin(),_rootserverAddresses.end(),p->first) == _rootserverAddresses.end())) { + if (((now - p->second->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(std::find(_rootAddresses.begin(),_rootAddresses.end(),p->first) == _rootAddresses.end())) { _activePeers.erase(p++); } else ++p; } diff --git a/node/Topology.hpp b/node/Topology.hpp index 8aeae784..c878bcc6 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -59,21 +59,19 @@ public: ~Topology(); /** - * Set up rootservers for this network - * - * @param sn Rootservers for this network + * @param sn Root server identities and addresses */ - void setRootservers(const std::map< Identity,std::vector > &sn); + void setRootServers(const std::map< Identity,std::vector > &sn); /** - * Set up rootservers for this network + * Set up root servers for this network * * This performs no signature verification of any kind. The caller must * check the signature of the root topology dictionary first. * - * @param sn Rootservers dictionary from root-topology + * @param sn 'rootservers' key from root-topology Dictionary (deserialized as Dictionary) */ - void setRootservers(const Dictionary &sn); + void setRootServers(const Dictionary &sn); /** * Add a peer to database @@ -95,65 +93,52 @@ public: SharedPtr getPeer(const Address &zta); /** - * @return Vector of peers that are rootservers - */ - inline std::vector< SharedPtr > rootserverPeers() const - { - Mutex::Lock _l(_lock); - return _rootserverPeers; - } - - /** - * @return Number of rootservers + * @return Vector of peers that are root servers */ - inline unsigned int numRootservers() const + inline std::vector< SharedPtr > rootPeers() const { Mutex::Lock _l(_lock); - return (unsigned int)_rootserverPeers.size(); + return _rootPeers; } /** - * Get the current favorite rootserver + * Get the current favorite root server * - * @return Rootserver with lowest latency or NULL if none + * @return Root server with lowest latency or NULL if none */ - inline SharedPtr getBestRootserver() + inline SharedPtr getBestRoot() { - return getBestRootserver((const Address *)0,0,false); + return getBestRoot((const Address *)0,0,false); } /** - * Get the best rootserver, avoiding rootservers listed in an array + * Get the best root server, avoiding root servers listed in an array * - * This will get the best rootserver (lowest latency, etc.) but will - * try to avoid the listed rootservers, only using them if no others + * This will get the best root server (lowest latency, etc.) but will + * try to avoid the listed root servers, only using them if no others * are available. * * @param avoid Nodes to avoid * @param avoidCount Number of nodes to avoid - * @param strictAvoid If false, consider avoided rootservers anyway if no non-avoid rootservers are available - * @return Rootserver or NULL if none + * @param strictAvoid If false, consider avoided root servers anyway if no non-avoid root servers are available + * @return Root server or NULL if none available */ - SharedPtr getBestRootserver(const Address *avoid,unsigned int avoidCount,bool strictAvoid); + SharedPtr getBestRoot(const Address *avoid,unsigned int avoidCount,bool strictAvoid); /** - * @param zta ZeroTier address - * @return True if this is a designated rootserver + * @param id Identity to check + * @return True if this is a designated root server */ - inline bool isRootserver(const Address &zta) const - throw() - { - Mutex::Lock _l(_lock); - return (std::find(_rootserverAddresses.begin(),_rootserverAddresses.end(),zta) != _rootserverAddresses.end()); - } + bool isRoot(const Identity &id) const + throw(); /** - * @return Vector of rootserver addresses + * @return Vector of root server addresses */ - inline std::vector
rootserverAddresses() const + inline std::vector
rootAddresses() const { Mutex::Lock _l(_lock); - return _rootserverAddresses; + return _rootAddresses; } /** @@ -206,13 +191,13 @@ private: const RuntimeEnvironment *RR; std::map< Address,SharedPtr > _activePeers; - std::map< Identity,std::vector > _rootservers; - std::vector< Address > _rootserverAddresses; - std::vector< SharedPtr > _rootserverPeers; + std::map< Identity,std::vector > _roots; + std::vector< Address > _rootAddresses; + std::vector< SharedPtr > _rootPeers; Mutex _lock; - bool _amRootserver; + bool _amRoot; }; } // namespace ZeroTier diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index e42c9ef8..01582586 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -211,9 +211,9 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT1_Peer *peer const char *prole = ""; switch(peer->role) { - case ZT1_PEER_ROLE_LEAF: prole = "LEAF"; break; - case ZT1_PEER_ROLE_HUB: prole = "HUB"; break; - case ZT1_PEER_ROLE_ROOTSERVER: prole = "ROOT"; break; + case ZT1_PEER_ROLE_LEAF: prole = "LEAF"; break; + case ZT1_PEER_ROLE_RELAY: prole = "RELAY"; break; + case ZT1_PEER_ROLE_ROOT: prole = "ROOT"; break; } Utils::snprintf(json,sizeof(json), -- cgit v1.2.3 From 2b04ac5e9b8be8bd1cc1263755a55a579f28009e Mon Sep 17 00:00:00 2001 From: Moritz Warning Date: Sat, 20 Jun 2015 09:36:51 +0200 Subject: replace _networks map by vector _networks is usually quite small, using binary search on a vector might be faster comapred to std::map. This is especially true when using uClibc++, which uses a list. --- node/Node.cpp | 38 ++++++++++++++++++++++---------------- node/Node.hpp | 23 ++++++++++++++++------- 2 files changed, 38 insertions(+), 23 deletions(-) (limited to 'node') diff --git a/node/Node.cpp b/node/Node.cpp index 9f195a10..8e00071f 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -236,13 +236,14 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next std::vector< SharedPtr > needConfig; { Mutex::Lock _l(_networks_m); - for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) { - SharedPtr nc(n->second->config2()); - if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!nc)) - needConfig.push_back(n->second); + for(std::vector< SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) { + SharedPtr nc((*n)->config2()); + if (((now - (*n)->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!nc)) + needConfig.push_back(*n); if (nc) networkRelays.insert(networkRelays.end(),nc->relays().begin(),nc->relays().end()); } + std::sort(_networks.begin(),_networks.end()); } // Request updated configuration for networks that need it @@ -310,19 +311,24 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next ZT1_ResultCode Node::join(uint64_t nwid) { Mutex::Lock _l(_networks_m); - SharedPtr &nwe = _networks[nwid]; - if (!nwe) - nwe = SharedPtr(new Network(RR,nwid)); + std::vector< SharedPtr >::const_iterator nwi = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); + if(nwi == _networks.end() || (*nwi)->id() != nwid) { + _networks.push_back(SharedPtr(new Network(RR,nwid))); + std::sort(_networks.begin(),_networks.end()); + } return ZT1_RESULT_OK; } ZT1_ResultCode Node::leave(uint64_t nwid) { Mutex::Lock _l(_networks_m); - std::map< uint64_t,SharedPtr >::iterator nw(_networks.find(nwid)); - if (nw != _networks.end()) { - nw->second->destroy(); - _networks.erase(nw); + std::vector< SharedPtr >::iterator nwi = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); + if(nwi != _networks.end() && (*nwi)->id() == nwid) { + (*nwi)->destroy(); + // erase element (replace by last) + *nwi = _networks.back(); + _networks.pop_back(); + std::sort(_networks.begin(),_networks.end()); } return ZT1_RESULT_OK; } @@ -406,10 +412,10 @@ ZT1_PeerList *Node::peers() const ZT1_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const { Mutex::Lock _l(_networks_m); - std::map< uint64_t,SharedPtr >::const_iterator nw(_networks.find(nwid)); - if (nw != _networks.end()) { + std::vector< SharedPtr >::const_iterator nwi = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); + if(nwi != _networks.end() && (*nwi)->id() == nwid) { ZT1_VirtualNetworkConfig *nc = (ZT1_VirtualNetworkConfig *)::malloc(sizeof(ZT1_VirtualNetworkConfig)); - nw->second->externalConfig(nc); + (*nwi)->externalConfig(nc); return nc; } return (ZT1_VirtualNetworkConfig *)0; @@ -426,8 +432,8 @@ ZT1_VirtualNetworkList *Node::networks() const nl->networks = (ZT1_VirtualNetworkConfig *)(buf + sizeof(ZT1_VirtualNetworkList)); nl->networkCount = 0; - for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) - n->second->externalConfig(&(nl->networks[nl->networkCount++])); + for(std::vector< SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) + (*n)->externalConfig(&(nl->networks[nl->networkCount++])); return nl; } diff --git a/node/Node.hpp b/node/Node.hpp index 1d9372e4..6ef306eb 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -155,19 +155,21 @@ public: len); } - inline SharedPtr network(uint64_t nwid) + inline SharedPtr network(uint64_t nwid) const { Mutex::Lock _l(_networks_m); - std::map< uint64_t,SharedPtr >::iterator nw(_networks.find(nwid)); - return ((nw == _networks.end()) ? SharedPtr() : nw->second); + std::vector< SharedPtr >::const_iterator iter = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); + if(iter != _networks.end() && (*iter)->id() == nwid) { + return *iter; + } else { + return SharedPtr(); + } } inline std::vector< SharedPtr > allNetworks() const { Mutex::Lock _l(_networks_m); - std::vector< SharedPtr > nw; - for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) - nw.push_back(n->second); + std::vector< SharedPtr > nw(_networks); return nw; } @@ -208,6 +210,13 @@ public: #endif private: + // for binary search on _networks + struct NetworkComparator { + bool operator()(const SharedPtr &n,uint64_t nwid) const { + return n->id() < nwid; + } + }; + RuntimeEnvironment _RR; RuntimeEnvironment *RR; @@ -223,7 +232,7 @@ private: //Dictionary _localConfig; // persisted as local.conf //Mutex _localConfig_m; - std::map< uint64_t,SharedPtr > _networks; + std::vector< SharedPtr > _networks; Mutex _networks_m; Mutex _backgroundTasksLock; -- cgit v1.2.3 From 787608b5683eb5df2a8ca0d365438234b5497c60 Mon Sep 17 00:00:00 2001 From: Moritz Warning Date: Sat, 20 Jun 2015 16:32:48 +0200 Subject: use _network function to reduce source code complexity --- node/Node.cpp | 10 +++++----- node/Node.hpp | 17 +++++++++++------ 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'node') diff --git a/node/Node.cpp b/node/Node.cpp index 8e00071f..1dbb6d19 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -311,8 +311,8 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next ZT1_ResultCode Node::join(uint64_t nwid) { Mutex::Lock _l(_networks_m); - std::vector< SharedPtr >::const_iterator nwi = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); - if(nwi == _networks.end() || (*nwi)->id() != nwid) { + SharedPtr nw = _network(nwid); + if(!nw) { _networks.push_back(SharedPtr(new Network(RR,nwid))); std::sort(_networks.begin(),_networks.end()); } @@ -412,10 +412,10 @@ ZT1_PeerList *Node::peers() const ZT1_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const { Mutex::Lock _l(_networks_m); - std::vector< SharedPtr >::const_iterator nwi = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); - if(nwi != _networks.end() && (*nwi)->id() == nwid) { + SharedPtr nw = _network(nwid); + if(nw) { ZT1_VirtualNetworkConfig *nc = (ZT1_VirtualNetworkConfig *)::malloc(sizeof(ZT1_VirtualNetworkConfig)); - (*nwi)->externalConfig(nc); + nw->externalConfig(nc); return nc; } return (ZT1_VirtualNetworkConfig *)0; diff --git a/node/Node.hpp b/node/Node.hpp index 6ef306eb..b0f4ab22 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -158,12 +158,7 @@ public: inline SharedPtr network(uint64_t nwid) const { Mutex::Lock _l(_networks_m); - std::vector< SharedPtr >::const_iterator iter = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); - if(iter != _networks.end() && (*iter)->id() == nwid) { - return *iter; - } else { - return SharedPtr(); - } + return _network(nwid); } inline std::vector< SharedPtr > allNetworks() const @@ -217,6 +212,16 @@ private: } }; + inline SharedPtr _network(uint64_t nwid) const + { + std::vector< SharedPtr >::const_iterator iter = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); + if(iter != _networks.end() && (*iter)->id() == nwid) { + return *iter; + } else { + return SharedPtr(); + } + } + RuntimeEnvironment _RR; RuntimeEnvironment *RR; -- cgit v1.2.3 From def9cf2a6a6991bf19ceb74877152cdc6c149db7 Mon Sep 17 00:00:00 2001 From: Moritz Warning Date: Tue, 23 Jun 2015 00:08:59 +0200 Subject: replace vector::erase, was missed in a previous commit (ref #186) --- node/Multicaster.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'node') diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 29e89189..8a15bac1 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -330,7 +330,9 @@ void Multicaster::_add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,Multi for(std::vector::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) { if (tx->atLimit()) { - gs.txQueue.erase(tx++); + // erase element (replace by last) + *tx = gs.txQueue.back(); + gs.txQueue.pop_back(); } else { tx->sendIfNew(RR,member); if (tx->atLimit()) { -- cgit v1.2.3 From c287ae4d1d0cb6448e556dda2c5c98eee4898cfe Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 26 Jun 2015 11:38:31 -0700 Subject: Redo conversion of _networks to a vector. Just use a simple linear search and put the nwid in a pair with the pointer so linear search can be done without pointer chasing. This should be the fastest option for anything less than dozens of networks, and should save memory over the old map. --- node/Node.cpp | 34 +++++++++++++++------------------- node/Node.hpp | 24 ++++++++++-------------- 2 files changed, 25 insertions(+), 33 deletions(-) (limited to 'node') diff --git a/node/Node.cpp b/node/Node.cpp index 60aeff1f..85011434 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -141,7 +141,7 @@ Node::Node( Node::~Node() { Mutex::Lock _l(_networks_m); - _networks.clear(); + _networks.clear(); // ensure that networks are destroyed before shutdown delete RR->sa; delete RR->topology; delete RR->antiRec; @@ -236,14 +236,13 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next std::vector< SharedPtr > needConfig; { Mutex::Lock _l(_networks_m); - for(std::vector< SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) { - SharedPtr nc((*n)->config2()); - if (((now - (*n)->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!nc)) - needConfig.push_back(*n); + for(std::vector< std::pair< uint64_t,SharedPtr > >::const_iterator n(_networks.begin());n!=_networks.end();++n) { + SharedPtr nc(n->second->config2()); + if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!nc)) + needConfig.push_back(n->second); if (nc) networkRelays.insert(networkRelays.end(),nc->relays().begin(),nc->relays().end()); } - std::sort(_networks.begin(),_networks.end()); } // Request updated configuration for networks that need it @@ -312,24 +311,21 @@ ZT1_ResultCode Node::join(uint64_t nwid) { Mutex::Lock _l(_networks_m); SharedPtr nw = _network(nwid); - if(!nw) { - _networks.push_back(SharedPtr(new Network(RR,nwid))); - std::sort(_networks.begin(),_networks.end()); - } + if(!nw) + _networks.push_back(std::pair< uint64_t,SharedPtr >(nwid,SharedPtr(new Network(RR,nwid)))); + std::sort(_networks.begin(),_networks.end()); // will sort by nwid since it's the first in a pair<> return ZT1_RESULT_OK; } ZT1_ResultCode Node::leave(uint64_t nwid) { + std::vector< std::pair< uint64_t,SharedPtr > > newn; Mutex::Lock _l(_networks_m); - std::vector< SharedPtr >::iterator nwi = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); - if(nwi != _networks.end() && (*nwi)->id() == nwid) { - (*nwi)->destroy(); - // erase element (replace by last) - *nwi = _networks.back(); - _networks.pop_back(); - std::sort(_networks.begin(),_networks.end()); + for(std::vector< std::pair< uint64_t,SharedPtr > >::const_iterator n(_networks.begin());n!=_networks.end();++n) { + if (n->first != nwid) + newn.push_back(*n); } + _networks.swap(newn); return ZT1_RESULT_OK; } @@ -432,8 +428,8 @@ ZT1_VirtualNetworkList *Node::networks() const nl->networks = (ZT1_VirtualNetworkConfig *)(buf + sizeof(ZT1_VirtualNetworkList)); nl->networkCount = 0; - for(std::vector< SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) - (*n)->externalConfig(&(nl->networks[nl->networkCount++])); + for(std::vector< std::pair< uint64_t,SharedPtr > >::const_iterator n(_networks.begin());n!=_networks.end();++n) + n->second->externalConfig(&(nl->networks[nl->networkCount++])); return nl; } diff --git a/node/Node.hpp b/node/Node.hpp index b0f4ab22..2d2898b5 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -163,8 +163,11 @@ public: inline std::vector< SharedPtr > allNetworks() const { + std::vector< SharedPtr > nw; Mutex::Lock _l(_networks_m); - std::vector< SharedPtr > nw(_networks); + nw.reserve(_networks.size()); + for(std::vector< std::pair< uint64_t, SharedPtr > >::const_iterator i=_networks.begin();i!=_networks.end();++i) + nw.push_back(i->second); return nw; } @@ -205,21 +208,14 @@ public: #endif private: - // for binary search on _networks - struct NetworkComparator { - bool operator()(const SharedPtr &n,uint64_t nwid) const { - return n->id() < nwid; - } - }; - inline SharedPtr _network(uint64_t nwid) const { - std::vector< SharedPtr >::const_iterator iter = std::lower_bound(_networks.begin(), _networks.end(), nwid, NetworkComparator()); - if(iter != _networks.end() && (*iter)->id() == nwid) { - return *iter; - } else { - return SharedPtr(); + // assumes _networks_m is locked + for(std::vector< std::pair< uint64_t, SharedPtr > >::const_iterator i=_networks.begin();i!=_networks.end();++i) { + if (i->first == nwid) + return i->second; } + return SharedPtr(); } RuntimeEnvironment _RR; @@ -237,7 +233,7 @@ private: //Dictionary _localConfig; // persisted as local.conf //Mutex _localConfig_m; - std::vector< SharedPtr > _networks; + std::vector< std::pair< uint64_t, SharedPtr > > _networks; Mutex _networks_m; Mutex _backgroundTasksLock; -- cgit v1.2.3 From 57c7992c785ab2f69fb2ddffd6f48bfebd96cab8 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 26 Jun 2015 12:36:45 -0700 Subject: GitHub issue #191 - kill intra-network multicast rate limits (which were not well supported or easily configurable anyway) -- this is really left over from the old collaborative multicast propagation algorithm. New algorithm (in for a while) has been sender-side replication in which sender "pays" all bandwidth, which intrinsically limits multicast. --- attic/BandwidthAccount.hpp | 153 +++++++++++++++++++++++++++++++++ controller/SqliteNetworkController.cpp | 26 +----- controller/SqliteNetworkController.hpp | 1 - controller/schema.sql | 11 --- controller/schema.sql.c | 11 --- node/BandwidthAccount.hpp | 153 --------------------------------- node/Network.cpp | 14 --- node/Network.hpp | 11 --- node/NetworkConfig.cpp | 31 ------- node/NetworkConfig.hpp | 33 ------- node/Switch.cpp | 6 -- 11 files changed, 157 insertions(+), 293 deletions(-) create mode 100644 attic/BandwidthAccount.hpp delete mode 100644 node/BandwidthAccount.hpp (limited to 'node') diff --git a/attic/BandwidthAccount.hpp b/attic/BandwidthAccount.hpp new file mode 100644 index 00000000..3a6432c4 --- /dev/null +++ b/attic/BandwidthAccount.hpp @@ -0,0 +1,153 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#ifndef ZT_BWACCOUNT_HPP +#define ZT_BWACCOUNT_HPP + +#include "Constants.hpp" + +#include + +#include +#include + +#include "Utils.hpp" + +#ifdef __WINDOWS__ +#define round(x) ((x-floor(x))>0.5 ? ceil(x) : floor(x)) +#endif + +namespace ZeroTier { + +/** + * Bandwidth account used for rate limiting multicast groups + * + * This is used to apply a bank account model to multicast groups. Each + * multicast packet counts against a balance, which accrues at a given + * rate in bytes per second. Debt is possible. These parameters are + * configurable. + * + * A bank account model permits bursting behavior, which correctly models + * how OSes and apps typically use multicast. It's common for things to + * spew lots of multicast messages at once, wait a while, then do it + * again. A consistent bandwidth limit model doesn't fit. + */ +class BandwidthAccount +{ +public: + /** + * Create an uninitialized account + * + * init() must be called before this is used. + */ + BandwidthAccount() throw() {} + + /** + * Create and initialize + * + * @param preload Initial balance to place in account + * @param maxb Maximum allowed balance (> 0) + * @param acc Rate of accrual in bytes per second + * @param now Current time + */ + BandwidthAccount(uint32_t preload,uint32_t maxb,uint32_t acc,uint64_t now) + throw() + { + init(preload,maxb,acc,now); + } + + /** + * Initialize or re-initialize account + * + * @param preload Initial balance to place in account + * @param maxb Maximum allowed balance (> 0) + * @param acc Rate of accrual in bytes per second + * @param now Current time + */ + inline void init(uint32_t preload,uint32_t maxb,uint32_t acc,uint64_t now) + throw() + { + _lastTime = ((double)now / 1000.0); + _balance = preload; + _maxBalance = maxb; + _accrual = acc; + } + + /** + * Update and retrieve balance of this account + * + * @param now Current time + * @return New balance updated from current clock + */ + inline uint32_t update(uint64_t now) + throw() + { + double lt = _lastTime; + double nowf = ((double)now / 1000.0); + _lastTime = nowf; + return (_balance = std::min(_maxBalance,(uint32_t)round((double)_balance + ((double)_accrual * (nowf - lt))))); + } + + /** + * Update balance and conditionally deduct + * + * If the deduction amount fits, it is deducted after update. Otherwise + * balance is updated and false is returned. + * + * @param amt Amount to deduct + * @param now Current time + * @return True if amount fit within balance and was deducted + */ + inline bool deduct(uint32_t amt,uint64_t now) + throw() + { + if (update(now) >= amt) { + _balance -= amt; + return true; + } + return false; + } + + /** + * @return Most recent balance without update + */ + inline uint32_t balance() const + throw() + { + return _balance; + } + +private: + double _lastTime; + uint32_t _balance; + uint32_t _maxBalance; + uint32_t _accrual; +}; + +} // namespace ZeroTier + +#endif diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index a1827a72..d77e06d8 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -155,7 +155,6 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) : ||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastAt = ?,lastSeen = ? WHERE id = ?",-1,&_sUpdateNode,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"UPDATE Node SET lastSeen = ? WHERE id = ?",-1,&_sUpdateNode2,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT etherType FROM Rule WHERE networkId = ? AND \"action\" = 'accept'",-1,&_sGetEtherTypesFromRuleTable,(const char **)0) != SQLITE_OK) - ||(sqlite3_prepare_v2(_db,"SELECT mgMac,mgAdi,preload,maxBalance,accrual FROM MulticastRate WHERE networkId = ?",-1,&_sGetMulticastRates,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT nodeId FROM Member WHERE networkId = ? AND activeBridge > 0 AND authorized > 0",-1,&_sGetActiveBridges,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT ip,ipNetmaskBits FROM IpAssignment WHERE networkId = ? AND nodeId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentsForNode,(const char **)0) != SQLITE_OK) ||(sqlite3_prepare_v2(_db,"SELECT ipNetwork,ipNetmaskBits FROM IpAssignmentPool WHERE networkId = ? AND ipVersion = ?",-1,&_sGetIpAssignmentPools,(const char **)0) != SQLITE_OK) @@ -204,7 +203,6 @@ SqliteNetworkController::~SqliteNetworkController() sqlite3_finalize(_sUpdateNode); sqlite3_finalize(_sUpdateNode2); sqlite3_finalize(_sGetEtherTypesFromRuleTable); - sqlite3_finalize(_sGetMulticastRates); sqlite3_finalize(_sGetActiveBridges); sqlite3_finalize(_sGetIpAssignmentsForNode); sqlite3_finalize(_sGetIpAssignmentPools); @@ -403,26 +401,10 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co netconf[ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES] = allowedEtherTypesCsv; } - { - std::string multicastRates; - sqlite3_reset(_sGetMulticastRates); - sqlite3_bind_text(_sGetMulticastRates,1,network.id,16,SQLITE_STATIC); - while (sqlite3_step(_sGetMulticastRates) == SQLITE_ROW) { - const char *mac = (const char *)sqlite3_column_text(_sGetMulticastRates,0); - if ((mac)&&(strlen(mac) == 12)) { - unsigned long adi = ((unsigned long)sqlite3_column_int64(_sGetMulticastRates,1)) & 0xffffffff; - char tmp[256]; - Utils::snprintf(tmp,sizeof(tmp),"%s/%.4lx=%x,%x,%x\n",mac,adi,sqlite3_column_int(_sGetMulticastRates,2),sqlite3_column_int(_sGetMulticastRates,3),sqlite3_column_int(_sGetMulticastRates,4)); - multicastRates.append(tmp); - } - } - if (multicastRates.length() > 0) - netconf[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES] = multicastRates; - if (network.multicastLimit > 0) { - char ml[16]; - Utils::snprintf(ml,sizeof(ml),"%lx",(unsigned long)network.multicastLimit); - netconf[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT] = ml; - } + if (network.multicastLimit > 0) { + char ml[16]; + Utils::snprintf(ml,sizeof(ml),"%lx",(unsigned long)network.multicastLimit); + netconf[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT] = ml; } { diff --git a/controller/SqliteNetworkController.hpp b/controller/SqliteNetworkController.hpp index be2ca694..9cdbc404 100644 --- a/controller/SqliteNetworkController.hpp +++ b/controller/SqliteNetworkController.hpp @@ -99,7 +99,6 @@ private: sqlite3_stmt *_sUpdateNode; sqlite3_stmt *_sUpdateNode2; sqlite3_stmt *_sGetEtherTypesFromRuleTable; - sqlite3_stmt *_sGetMulticastRates; sqlite3_stmt *_sGetActiveBridges; sqlite3_stmt *_sGetIpAssignmentsForNode; sqlite3_stmt *_sGetIpAssignmentPools; diff --git a/controller/schema.sql b/controller/schema.sql index 809c7161..d2261b2a 100644 --- a/controller/schema.sql +++ b/controller/schema.sql @@ -64,17 +64,6 @@ CREATE TABLE Member ( CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge); -CREATE TABLE MulticastRate ( - networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, - mgMac char(12) NOT NULL, - mgAdi integer NOT NULL DEFAULT(0), - preload integer NOT NULL, - maxBalance integer NOT NULL, - accrual integer NOT NULL -); - -CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId); - CREATE TABLE Relay ( networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE, nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE, diff --git a/controller/schema.sql.c b/controller/schema.sql.c index f1c66358..1157facc 100644 --- a/controller/schema.sql.c +++ b/controller/schema.sql.c @@ -65,17 +65,6 @@ "\n"\ "CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\ "\n"\ -"CREATE TABLE MulticastRate (\n"\ -" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ -" mgMac char(12) NOT NULL,\n"\ -" mgAdi integer NOT NULL DEFAULT(0),\n"\ -" preload integer NOT NULL,\n"\ -" maxBalance integer NOT NULL,\n"\ -" accrual integer NOT NULL\n"\ -");\n"\ -"\n"\ -"CREATE INDEX MulticastRate_networkId ON MulticastRate (networkId);\n"\ -"\n"\ "CREATE TABLE Relay (\n"\ " networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\ " nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\ diff --git a/node/BandwidthAccount.hpp b/node/BandwidthAccount.hpp deleted file mode 100644 index 3a6432c4..00000000 --- a/node/BandwidthAccount.hpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2015 ZeroTier, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * ZeroTier may be used and distributed under the terms of the GPLv3, which - * are available at: http://www.gnu.org/licenses/gpl-3.0.html - * - * If you would like to embed ZeroTier into a commercial application or - * redistribute it in a modified binary form, please contact ZeroTier Networks - * LLC. Start here: http://www.zerotier.com/ - */ - -#ifndef ZT_BWACCOUNT_HPP -#define ZT_BWACCOUNT_HPP - -#include "Constants.hpp" - -#include - -#include -#include - -#include "Utils.hpp" - -#ifdef __WINDOWS__ -#define round(x) ((x-floor(x))>0.5 ? ceil(x) : floor(x)) -#endif - -namespace ZeroTier { - -/** - * Bandwidth account used for rate limiting multicast groups - * - * This is used to apply a bank account model to multicast groups. Each - * multicast packet counts against a balance, which accrues at a given - * rate in bytes per second. Debt is possible. These parameters are - * configurable. - * - * A bank account model permits bursting behavior, which correctly models - * how OSes and apps typically use multicast. It's common for things to - * spew lots of multicast messages at once, wait a while, then do it - * again. A consistent bandwidth limit model doesn't fit. - */ -class BandwidthAccount -{ -public: - /** - * Create an uninitialized account - * - * init() must be called before this is used. - */ - BandwidthAccount() throw() {} - - /** - * Create and initialize - * - * @param preload Initial balance to place in account - * @param maxb Maximum allowed balance (> 0) - * @param acc Rate of accrual in bytes per second - * @param now Current time - */ - BandwidthAccount(uint32_t preload,uint32_t maxb,uint32_t acc,uint64_t now) - throw() - { - init(preload,maxb,acc,now); - } - - /** - * Initialize or re-initialize account - * - * @param preload Initial balance to place in account - * @param maxb Maximum allowed balance (> 0) - * @param acc Rate of accrual in bytes per second - * @param now Current time - */ - inline void init(uint32_t preload,uint32_t maxb,uint32_t acc,uint64_t now) - throw() - { - _lastTime = ((double)now / 1000.0); - _balance = preload; - _maxBalance = maxb; - _accrual = acc; - } - - /** - * Update and retrieve balance of this account - * - * @param now Current time - * @return New balance updated from current clock - */ - inline uint32_t update(uint64_t now) - throw() - { - double lt = _lastTime; - double nowf = ((double)now / 1000.0); - _lastTime = nowf; - return (_balance = std::min(_maxBalance,(uint32_t)round((double)_balance + ((double)_accrual * (nowf - lt))))); - } - - /** - * Update balance and conditionally deduct - * - * If the deduction amount fits, it is deducted after update. Otherwise - * balance is updated and false is returned. - * - * @param amt Amount to deduct - * @param now Current time - * @return True if amount fit within balance and was deducted - */ - inline bool deduct(uint32_t amt,uint64_t now) - throw() - { - if (update(now) >= amt) { - _balance -= amt; - return true; - } - return false; - } - - /** - * @return Most recent balance without update - */ - inline uint32_t balance() const - throw() - { - return _balance; - } - -private: - double _lastTime; - uint32_t _balance; - uint32_t _maxBalance; - uint32_t _accrual; -}; - -} // namespace ZeroTier - -#endif diff --git a/node/Network.cpp b/node/Network.cpp index a217595a..d5dc7d58 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -357,20 +357,6 @@ void Network::clean() } } -bool Network::updateAndCheckMulticastBalance(const MulticastGroup &mg,unsigned int bytes) -{ - const uint64_t now = RR->node->now(); - Mutex::Lock _l(_lock); - if (!_config) - return false; - std::map< MulticastGroup,BandwidthAccount >::iterator bal(_multicastRateAccounts.find(mg)); - if (bal == _multicastRateAccounts.end()) { - NetworkConfig::MulticastRate r(_config->multicastRate(mg)); - bal = _multicastRateAccounts.insert(std::pair< MulticastGroup,BandwidthAccount >(mg,BandwidthAccount(r.preload,r.maxBalance,r.accrual,now))).first; - } - return bal->second.deduct(bytes,now); -} - void Network::learnBridgeRoute(const MAC &mac,const Address &addr) { Mutex::Lock _l(_lock); diff --git a/node/Network.hpp b/node/Network.hpp index 7976d901..daa4554e 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -47,7 +47,6 @@ #include "MulticastGroup.hpp" #include "MAC.hpp" #include "Dictionary.hpp" -#include "BandwidthAccount.hpp" #include "Multicaster.hpp" #include "NetworkConfig.hpp" #include "CertificateOfMembership.hpp" @@ -237,15 +236,6 @@ public: _externalConfig(ec); } - /** - * Update and check multicast rate balance for a multicast group - * - * @param mg Multicast group - * @param bytes Size of packet - * @return True if packet is within budget - */ - bool updateAndCheckMulticastBalance(const MulticastGroup &mg,unsigned int bytes); - /** * Get current network config or throw exception * @@ -370,7 +360,6 @@ private: std::vector< MulticastGroup > _myMulticastGroups; // multicast groups that we belong to including those behind us (updated periodically) std::map< MulticastGroup,uint64_t > _multicastGroupsBehindMe; // multicast groups bridged to us and when we last saw activity on each - std::map< MulticastGroup,BandwidthAccount > _multicastRateAccounts; std::map _remoteBridgeRoutes; // remote addresses where given MACs are reachable diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 5ed1dd3f..8d682947 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -32,10 +32,6 @@ namespace ZeroTier { -// This is fast enough for things like Apple's mDNS spam, so it should serve -// as a good default for your average network. -const NetworkConfig::MulticastRate NetworkConfig::DEFAULT_MULTICAST_RATE(40000,60000,80); - SharedPtr NetworkConfig::createTestNetworkConfig(const Address &self) { SharedPtr nc(new NetworkConfig()); @@ -85,18 +81,6 @@ std::vector NetworkConfig::allowedEtherTypes() const return ets; } -const NetworkConfig::MulticastRate &NetworkConfig::multicastRate(const MulticastGroup &mg) const - throw() -{ - std::map::const_iterator r(_multicastRates.find(mg)); - if (r == _multicastRates.end()) { - r = _multicastRates.find(MulticastGroup()); // zero MG signifies network's default rate - if (r == _multicastRates.end()) - return DEFAULT_MULTICAST_RATE; // neither specific nor default found in network config - } - return r->second; -} - void NetworkConfig::_fromDictionary(const Dictionary &d) { static const std::string zero("0"); @@ -181,13 +165,6 @@ void NetworkConfig::_fromDictionary(const Dictionary &d) std::sort(_activeBridges.begin(),_activeBridges.end()); std::unique(_activeBridges.begin(),_activeBridges.end()); - Dictionary multicastRateEntries(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES,std::string())); - for(Dictionary::const_iterator i(multicastRateEntries.begin());i!=multicastRateEntries.end();++i) { - std::vector params(Utils::split(i->second.c_str(),",","","")); - if (params.size() >= 3) - _multicastRates[MulticastGroup(i->first)] = MulticastRate(Utils::hexStrToUInt(params[0].c_str()),Utils::hexStrToUInt(params[1].c_str()),Utils::hexStrToUInt(params[2].c_str())); - } - std::vector relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","","")); for(std::vector::const_iterator r(relaysSplit.begin());r!=relaysSplit.end();++r) { std::size_t semi(r->find(';')); // address;ip/port,... @@ -221,14 +198,6 @@ bool NetworkConfig::operator==(const NetworkConfig &nc) const if (_gateways != nc._gateways) return false; if (_activeBridges != nc._activeBridges) return false; if (_relays != nc._relays) return false; - if (_multicastRates.size() == nc._multicastRates.size()) { - // uclibc++ doesn't seem to implement map<> != map<> correctly, so do - // it ourselves. Note that this depends on the maps being sorted. - for(std::map::const_iterator a(_multicastRates.begin()),b(nc._multicastRates.begin());a!=_multicastRates.end();++a,++b) { - if ((a->first != b->first)||(a->second != b->second)) - return false; - } - } else return false; if (_com != nc._com) return false; return true; } diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 2fb56d6a..75395fd5 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -68,9 +68,6 @@ namespace ZeroTier { // integer(hex) #define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml" -// dictionary of one or more of: MAC/ADI=preload,maxbalance,accrual -#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES "mr" - // 0/1 #define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p" @@ -114,27 +111,6 @@ class NetworkConfig friend class SharedPtr; public: - /** - * Tuple of multicast rate parameters - */ - struct MulticastRate - { - MulticastRate() throw() {} - MulticastRate(uint32_t pl,uint32_t maxb,uint32_t acc) throw() : preload(pl),maxBalance(maxb),accrual(acc) {} - - uint32_t preload; - uint32_t maxBalance; - uint32_t accrual; - - inline bool operator==(const MulticastRate &mr) const { return ((preload == mr.preload)&&(maxBalance == mr.maxBalance)&&(accrual == mr.accrual)); } - inline bool operator!=(const MulticastRate &mr) const { return (!(*this == mr)); } - }; - - /** - * A hard-coded default multicast rate for networks that don't specify - */ - static const MulticastRate DEFAULT_MULTICAST_RATE; - /** * Create an instance of a NetworkConfig for the test network ID * @@ -176,7 +152,6 @@ public: inline uint64_t revision() const throw() { return _revision; } inline const Address &issuedTo() const throw() { return _issuedTo; } inline unsigned int multicastLimit() const throw() { return _multicastLimit; } - inline const std::map &multicastRates() const throw() { return _multicastRates; } inline bool allowPassiveBridging() const throw() { return _allowPassiveBridging; } inline bool isPublic() const throw() { return (!_private); } inline bool isPrivate() const throw() { return _private; } @@ -198,13 +173,6 @@ public: return ( (_allowPassiveBridging) || (std::find(_activeBridges.begin(),_activeBridges.end(),fromPeer) != _activeBridges.end()) ); } - /** - * @param mg Multicast group - * @return Multicast rate or DEFAULT_MULTICAST_RATE if not set - */ - const MulticastRate &multicastRate(const MulticastGroup &mg) const - throw(); - bool operator==(const NetworkConfig &nc) const; inline bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); } @@ -229,7 +197,6 @@ private: std::vector _gateways; std::vector
_activeBridges; std::vector< std::pair > _relays; - std::map _multicastRates; CertificateOfMembership _com; AtomicCounter __refCount; diff --git a/node/Switch.cpp b/node/Switch.cpp index af80f5e8..236c1e66 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -145,12 +145,6 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c if (fromBridged) network->learnBridgedMulticastGroup(mg,RR->node->now()); - // Check multicast/broadcast bandwidth quotas and reject if quota exceeded - if (!network->updateAndCheckMulticastBalance(mg,len)) { - TRACE("%.16llx: didn't multicast %u bytes, quota exceeded for multicast group %s",network->id(),len,mg.toString().c_str()); - return; - } - //TRACE("%.16llx: MULTICAST %s -> %s %s %u",network->id(),from.toString().c_str(),mg.toString().c_str(),etherTypeName(etherType),len); RR->mc->send( -- cgit v1.2.3 From 8a68624dae9e2bdb073e89f8e02e4bce85bfc7a8 Mon Sep 17 00:00:00 2001 From: Kees Bos Date: Fri, 26 Jun 2015 07:22:13 +0200 Subject: Fix cert verification check for self signed signatures --- node/Network.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'node') diff --git a/node/Network.cpp b/node/Network.cpp index d5dc7d58..c072e978 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -286,18 +286,28 @@ void Network::addMembershipCertificate(const CertificateOfMembership &cert,bool return; } - SharedPtr signer(RR->topology->getPeer(cert.signedBy())); + if (cert.signedBy() == RR->identity.address()) { + // We are the controller: RR->identity.address() == controller() == cert.signedBy() + // So, verify that we signed th cert ourself + if (!cert.verify(RR->identity)) { + TRACE("rejected network membership certificate for %.16llx self signed by %s: signature check failed",(unsigned long long)_id,cert.signedBy().toString().c_str()); + return; + } + } else { - if (!signer) { - // This would be rather odd, since this is our controller... could happen - // if we get packets before we've gotten config. - RR->sw->requestWhois(cert.signedBy()); - return; - } + SharedPtr signer(RR->topology->getPeer(cert.signedBy())); - if (!cert.verify(signer->identity())) { - TRACE("rejected network membership certificate for %.16llx signed by %s: signature check failed",(unsigned long long)_id,cert.signedBy().toString().c_str()); - return; + if (!signer) { + // This would be rather odd, since this is our controller... could happen + // if we get packets before we've gotten config. + RR->sw->requestWhois(cert.signedBy()); + return; + } + + if (!cert.verify(signer->identity())) { + TRACE("rejected network membership certificate for %.16llx signed by %s: signature check failed",(unsigned long long)_id,cert.signedBy().toString().c_str()); + return; + } } } -- cgit v1.2.3 From 3f71afd0fbb2d87a2c9288166299600da51470dc Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 26 Jun 2015 14:26:35 -0700 Subject: Put multicast txQueue back to list. --- node/Multicaster.cpp | 28 +++++++++++----------------- node/Multicaster.hpp | 2 +- 2 files changed, 12 insertions(+), 18 deletions(-) (limited to 'node') diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 8a15bac1..77ea2e66 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -275,12 +275,10 @@ void Multicaster::clean(uint64_t now) { Mutex::Lock _l(_groups_m); for(std::map< std::pair,MulticastGroupStatus >::iterator mm(_groups.begin());mm!=_groups.end();) { - for(std::vector::iterator tx(mm->second.txQueue.begin());tx!=mm->second.txQueue.end();) { - if ((tx->expired(now))||(tx->atLimit())) { - // erase element (replace by last) - *tx = mm->second.txQueue.back(); - mm->second.txQueue.pop_back(); - } else ++tx; + for(std::list::iterator tx(mm->second.txQueue.begin());tx!=mm->second.txQueue.end();) { + if ((tx->expired(now))||(tx->atLimit())) + mm->second.txQueue.erase(tx++); + else ++tx; } unsigned long count = 0; @@ -328,18 +326,14 @@ void Multicaster::_add(uint64_t now,uint64_t nwid,const MulticastGroup &mg,Multi //TRACE("..MC %s joined multicast group %.16llx/%s via %s",member.toString().c_str(),nwid,mg.toString().c_str(),((learnedFrom) ? learnedFrom.toString().c_str() : "(direct)")); - for(std::vector::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) { - if (tx->atLimit()) { - // erase element (replace by last) - *tx = gs.txQueue.back(); - gs.txQueue.pop_back(); - } else { + for(std::list::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) { + if (tx->atLimit()) + gs.txQueue.erase(tx++); + else { tx->sendIfNew(RR,member); - if (tx->atLimit()) { - // erase element (replace by last) - *tx = gs.txQueue.back(); - gs.txQueue.pop_back(); - } else ++tx; + if (tx->atLimit()) + gs.txQueue.erase(tx++); + else ++tx; } } } diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index 281222b8..c6c93b1f 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -70,7 +70,7 @@ private: MulticastGroupStatus() : lastExplicitGather(0) {} uint64_t lastExplicitGather; - std::vector txQueue; // pending outbound multicasts + std::list txQueue; // pending outbound multicasts std::vector members; // members of this group }; -- cgit v1.2.3