mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-01 23:10:52 +00:00
Some cleanup, Multicaster now sends multicasts as it gets additional members.
This commit is contained in:
parent
ae082c3cb8
commit
e1882b614b
@ -40,7 +40,8 @@
|
|||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
Multicaster::Multicaster()
|
Multicaster::Multicaster(const RuntimeEnvironment *renv) :
|
||||||
|
RR(renv)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,9 +105,9 @@ restart_member_scan:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Multicaster::send(
|
void Multicaster::send(
|
||||||
const RuntimeEnvironment *RR,
|
|
||||||
const CertificateOfMembership *com,
|
const CertificateOfMembership *com,
|
||||||
unsigned int limit,
|
unsigned int limit,
|
||||||
|
unsigned int gatherLimit,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const MulticastGroup &mg,
|
const MulticastGroup &mg,
|
||||||
@ -122,7 +123,19 @@ void Multicaster::send(
|
|||||||
// If we already have enough members, just send and we're done -- no need for TX queue
|
// If we already have enough members, just send and we're done -- no need for TX queue
|
||||||
OutboundMulticast out;
|
OutboundMulticast out;
|
||||||
|
|
||||||
out.init(now,RR->identity.address(),nwid,com,ZT_MULTICAST_DEFAULT_IMPLICIT_GATHER,src,mg,etherType,data,len);
|
out.init(
|
||||||
|
now,
|
||||||
|
RR->identity.address(),
|
||||||
|
nwid,
|
||||||
|
com,
|
||||||
|
limit,
|
||||||
|
gatherLimit,
|
||||||
|
src,
|
||||||
|
mg,
|
||||||
|
etherType,
|
||||||
|
data,
|
||||||
|
len);
|
||||||
|
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
for(std::vector<MulticastGroupMember>::const_reverse_iterator m(gs.members.rbegin());m!=gs.members.rend();++m) {
|
for(std::vector<MulticastGroupMember>::const_reverse_iterator m(gs.members.rbegin());m!=gs.members.rend();++m) {
|
||||||
out.sendOnly(*(RR->sw),m->address); // sendOnly() avoids overhead of creating sent log since we're going to discard this immediately
|
out.sendOnly(*(RR->sw),m->address); // sendOnly() avoids overhead of creating sent log since we're going to discard this immediately
|
||||||
@ -134,7 +147,19 @@ void Multicaster::send(
|
|||||||
gs.txQueue.push_back(OutboundMulticast());
|
gs.txQueue.push_back(OutboundMulticast());
|
||||||
OutboundMulticast &out = gs.txQueue.back();
|
OutboundMulticast &out = gs.txQueue.back();
|
||||||
|
|
||||||
out.init(now,RR->identity.address(),nwid,com,ZT_MULTICAST_DEFAULT_IMPLICIT_GATHER,src,mg,etherType,data,len);
|
out.init(
|
||||||
|
now,
|
||||||
|
RR->identity.address(),
|
||||||
|
nwid,
|
||||||
|
com,
|
||||||
|
limit,
|
||||||
|
gatherLimit,
|
||||||
|
src,
|
||||||
|
mg,
|
||||||
|
etherType,
|
||||||
|
data,
|
||||||
|
len);
|
||||||
|
|
||||||
for(std::vector<MulticastGroupMember>::const_reverse_iterator m(gs.members.rbegin());m!=gs.members.rend();++m)
|
for(std::vector<MulticastGroupMember>::const_reverse_iterator m(gs.members.rbegin());m!=gs.members.rend();++m)
|
||||||
out.sendAndLog(*(RR->sw),m->address);
|
out.sendAndLog(*(RR->sw),m->address);
|
||||||
|
|
||||||
@ -161,13 +186,13 @@ void Multicaster::send(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Multicaster::clean(const RuntimeEnvironment *RR,uint64_t now)
|
void Multicaster::clean(uint64_t now)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_groups_m);
|
Mutex::Lock _l(_groups_m);
|
||||||
for(std::map< std::pair<uint64_t,MulticastGroup>,MulticastGroupStatus >::iterator mm(_groups.begin());mm!=_groups.end();) {
|
for(std::map< std::pair<uint64_t,MulticastGroup>,MulticastGroupStatus >::iterator mm(_groups.begin());mm!=_groups.end();) {
|
||||||
// Remove expired outgoing multicasts from multicast TX queue
|
// Remove expired outgoing multicasts from multicast TX queue
|
||||||
for(std::list<OutboundMulticast>::iterator tx(mm->second.txQueue.begin());tx!=mm->second.txQueue.end();) {
|
for(std::list<OutboundMulticast>::iterator tx(mm->second.txQueue.begin());tx!=mm->second.txQueue.end();) {
|
||||||
if (tx->expired(now))
|
if ((tx->expired(now))||(tx->atLimit()))
|
||||||
mm->second.txQueue.erase(tx++);
|
mm->second.txQueue.erase(tx++);
|
||||||
else ++tx;
|
else ++tx;
|
||||||
}
|
}
|
||||||
@ -218,7 +243,7 @@ void Multicaster::clean(const RuntimeEnvironment *RR,uint64_t now)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Multicaster::_add(uint64_t now,MulticastGroupStatus &gs,const Address &learnedFrom,const Address &member)
|
void Multicaster::_add(uint64_t now,uint64_t nwid,MulticastGroupStatus &gs,const Address &learnedFrom,const Address &member)
|
||||||
{
|
{
|
||||||
// assumes _groups_m is locked
|
// assumes _groups_m is locked
|
||||||
|
|
||||||
@ -236,6 +261,14 @@ void Multicaster::_add(uint64_t now,MulticastGroupStatus &gs,const Address &lear
|
|||||||
// be resorted on next clean(). In the future we might want to insert
|
// be resorted on next clean(). In the future we might want to insert
|
||||||
// this somewhere else but we'll try this for now.
|
// this somewhere else but we'll try this for now.
|
||||||
gs.members.push_back(MulticastGroupMember(member,learnedFrom,now));
|
gs.members.push_back(MulticastGroupMember(member,learnedFrom,now));
|
||||||
|
|
||||||
|
// Try to send to any outgoing multicasts that are waiting for more recipients
|
||||||
|
for(std::list<OutboundMulticast>::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) {
|
||||||
|
tx->sendIfNew(*(RR->sw),member);
|
||||||
|
if (tx->atLimit())
|
||||||
|
gs.txQueue.erase(tx++);
|
||||||
|
else ++tx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "OutboundMulticast.hpp"
|
#include "OutboundMulticast.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
#include "Mutex.hpp"
|
#include "Mutex.hpp"
|
||||||
|
#include "NonCopyable.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ class Packet;
|
|||||||
/**
|
/**
|
||||||
* Database of known multicast peers within a network
|
* Database of known multicast peers within a network
|
||||||
*/
|
*/
|
||||||
class Multicaster
|
class Multicaster : NonCopyable
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
struct MulticastGroupMember
|
struct MulticastGroupMember
|
||||||
@ -79,7 +80,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Multicaster();
|
Multicaster(const RuntimeEnvironment *renv);
|
||||||
~Multicaster();
|
~Multicaster();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,7 +95,7 @@ public:
|
|||||||
inline void subscribe(uint64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &learnedFrom,const Address &member)
|
inline void subscribe(uint64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &learnedFrom,const Address &member)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_groups_m);
|
Mutex::Lock _l(_groups_m);
|
||||||
_add(now,_groups[std::pair<uint64_t,MulticastGroup>(nwid,mg)],learnedFrom,member);
|
_add(now,nwid,_groups[std::pair<uint64_t,MulticastGroup>(nwid,mg)],learnedFrom,member);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,10 +121,10 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Send a multicast
|
* Send a multicast
|
||||||
*
|
*
|
||||||
* @param RR Runtime environment
|
|
||||||
* @param nwid Network ID
|
* @param nwid Network ID
|
||||||
* @param com Certificate of membership to include or NULL for none
|
* @param com Certificate of membership to include or NULL for none
|
||||||
* @param limit Multicast limit
|
* @param limit Multicast limit
|
||||||
|
* @param gatherLimit Limit to pass for implicit gather with MULTICAST_FRAME
|
||||||
* @param now Current time
|
* @param now Current time
|
||||||
* @param mg Multicast group
|
* @param mg Multicast group
|
||||||
* @param from Source Ethernet MAC address
|
* @param from Source Ethernet MAC address
|
||||||
@ -132,9 +133,9 @@ public:
|
|||||||
* @param len Length of packet data
|
* @param len Length of packet data
|
||||||
*/
|
*/
|
||||||
void send(
|
void send(
|
||||||
const RuntimeEnvironment *RR,
|
|
||||||
const CertificateOfMembership *com,
|
const CertificateOfMembership *com,
|
||||||
unsigned int limit,
|
unsigned int limit,
|
||||||
|
unsigned int gatherLimit,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const MulticastGroup &mg,
|
const MulticastGroup &mg,
|
||||||
@ -149,11 +150,12 @@ public:
|
|||||||
* @param RR Runtime environment
|
* @param RR Runtime environment
|
||||||
* @param now Current time
|
* @param now Current time
|
||||||
*/
|
*/
|
||||||
void clean(const RuntimeEnvironment *RR,uint64_t now);
|
void clean(uint64_t now);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _add(uint64_t now,MulticastGroupStatus &gs,const Address &learnedFrom,const Address &member);
|
void _add(uint64_t now,uint64_t nwid,MulticastGroupStatus &gs,const Address &learnedFrom,const Address &member);
|
||||||
|
|
||||||
|
const RuntimeEnvironment *RR;
|
||||||
std::map< std::pair<uint64_t,MulticastGroup>,MulticastGroupStatus > _groups;
|
std::map< std::pair<uint64_t,MulticastGroup>,MulticastGroupStatus > _groups;
|
||||||
Mutex _groups_m;
|
Mutex _groups_m;
|
||||||
};
|
};
|
||||||
|
@ -382,7 +382,7 @@ Node::ReasonForTermination Node::run()
|
|||||||
|
|
||||||
RR->http = new HttpClient();
|
RR->http = new HttpClient();
|
||||||
RR->antiRec = new AntiRecursion();
|
RR->antiRec = new AntiRecursion();
|
||||||
RR->mc = new Multicaster();
|
RR->mc = new Multicaster(RR);
|
||||||
RR->sw = new Switch(RR);
|
RR->sw = new Switch(RR);
|
||||||
RR->sm = new SocketManager(impl->udpPort,impl->tcpPort,&_CBztTraffic,RR);
|
RR->sm = new SocketManager(impl->udpPort,impl->tcpPort,&_CBztTraffic,RR);
|
||||||
RR->topology = new Topology(RR,Utils::fileExists((RR->homePath + ZT_PATH_SEPARATOR_S + "iddb.d").c_str()));
|
RR->topology = new Topology(RR,Utils::fileExists((RR->homePath + ZT_PATH_SEPARATOR_S + "iddb.d").c_str()));
|
||||||
@ -605,8 +605,8 @@ Node::ReasonForTermination Node::run()
|
|||||||
// Do periodic tasks in submodules.
|
// Do periodic tasks in submodules.
|
||||||
if ((now - lastClean) >= ZT_DB_CLEAN_PERIOD) {
|
if ((now - lastClean) >= ZT_DB_CLEAN_PERIOD) {
|
||||||
lastClean = now;
|
lastClean = now;
|
||||||
RR->topology->clean();
|
RR->topology->clean(now);
|
||||||
RR->mc->clean(RR,now);
|
RR->mc->clean(now);
|
||||||
RR->nc->clean();
|
RR->nc->clean();
|
||||||
if (RR->updater)
|
if (RR->updater)
|
||||||
RR->updater->checkIfMaxIntervalExceeded(now);
|
RR->updater->checkIfMaxIntervalExceeded(now);
|
||||||
|
@ -32,12 +32,24 @@
|
|||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
void OutboundMulticast::init(uint64_t timestamp,const Address &self,uint64_t nwid,const CertificateOfMembership *com,unsigned int gatherLimit,const MAC &src,const MulticastGroup &dest,unsigned int etherType,const void *payload,unsigned int len)
|
void OutboundMulticast::init(
|
||||||
|
uint64_t timestamp,
|
||||||
|
const Address &self,
|
||||||
|
uint64_t nwid,
|
||||||
|
const CertificateOfMembership *com,
|
||||||
|
unsigned int limit,
|
||||||
|
unsigned int gatherLimit,
|
||||||
|
const MAC &src,
|
||||||
|
const MulticastGroup &dest,
|
||||||
|
unsigned int etherType,
|
||||||
|
const void *payload,
|
||||||
|
unsigned int len)
|
||||||
{
|
{
|
||||||
_timestamp = timestamp;
|
_timestamp = timestamp;
|
||||||
_nwid = nwid;
|
_nwid = nwid;
|
||||||
_source = src;
|
_source = src;
|
||||||
_destination = dest;
|
_destination = dest;
|
||||||
|
_limit = limit;
|
||||||
_etherType = etherType;
|
_etherType = etherType;
|
||||||
|
|
||||||
_packet.setSource(self);
|
_packet.setSource(self);
|
||||||
@ -46,7 +58,7 @@ void OutboundMulticast::init(uint64_t timestamp,const Address &self,uint64_t nwi
|
|||||||
self.appendTo(_packet);
|
self.appendTo(_packet);
|
||||||
_packet.append((uint64_t)nwid);
|
_packet.append((uint64_t)nwid);
|
||||||
_packet.append((uint8_t)((com) ? 0x01 : 0x00));
|
_packet.append((uint8_t)((com) ? 0x01 : 0x00));
|
||||||
_packet.append((uint32_t)gatherLimit); // gather limit -- set before send, start with 0
|
_packet.append((uint32_t)gatherLimit);
|
||||||
if (com) com->serialize(_packet);
|
if (com) com->serialize(_packet);
|
||||||
_packet.append((uint32_t)dest.adi());
|
_packet.append((uint32_t)dest.adi());
|
||||||
dest.mac().appendTo(_packet);
|
dest.mac().appendTo(_packet);
|
||||||
|
@ -66,6 +66,7 @@ public:
|
|||||||
* @param self My ZeroTier address
|
* @param self My ZeroTier address
|
||||||
* @param nwid Network ID
|
* @param nwid Network ID
|
||||||
* @param com Certificate of membership to attach or NULL to omit
|
* @param com Certificate of membership to attach or NULL to omit
|
||||||
|
* @param limit Multicast limit for desired number of packets to send
|
||||||
* @param gatherLimit Number to lazily/implicitly gather with this frame or 0 for none
|
* @param gatherLimit Number to lazily/implicitly gather with this frame or 0 for none
|
||||||
* @param src Source MAC address of frame
|
* @param src Source MAC address of frame
|
||||||
* @param dest Destination multicast group (MAC + ADI)
|
* @param dest Destination multicast group (MAC + ADI)
|
||||||
@ -79,6 +80,7 @@ public:
|
|||||||
const Address &self,
|
const Address &self,
|
||||||
uint64_t nwid,
|
uint64_t nwid,
|
||||||
const CertificateOfMembership *com,
|
const CertificateOfMembership *com,
|
||||||
|
unsigned int limit,
|
||||||
unsigned int gatherLimit,
|
unsigned int gatherLimit,
|
||||||
const MAC &src,
|
const MAC &src,
|
||||||
const MulticastGroup &dest,
|
const MulticastGroup &dest,
|
||||||
@ -98,9 +100,9 @@ public:
|
|||||||
inline bool expired(uint64_t now) const throw() { return ((now - _timestamp) >= ZT_MULTICAST_TRANSMIT_TIMEOUT); }
|
inline bool expired(uint64_t now) const throw() { return ((now - _timestamp) >= ZT_MULTICAST_TRANSMIT_TIMEOUT); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Number of unique recipients to which this packet has already been sent
|
* @return True if this outbound multicast has been sent to enough peers
|
||||||
*/
|
*/
|
||||||
inline unsigned int sentToCount() const throw() { return (unsigned int)_alreadySentTo.size(); }
|
inline bool atLimit() const throw() { return (_alreadySentTo.size() > _limit); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Just send without checking log
|
* Just send without checking log
|
||||||
@ -144,6 +146,7 @@ private:
|
|||||||
uint64_t _nwid;
|
uint64_t _nwid;
|
||||||
MAC _source;
|
MAC _source;
|
||||||
MulticastGroup _destination;
|
MulticastGroup _destination;
|
||||||
|
unsigned int _limit;
|
||||||
unsigned int _etherType;
|
unsigned int _etherType;
|
||||||
Packet _packet; // packet contains basic structure of MULTICAST_FRAME and payload, is re-used with new IV and addressing each time
|
Packet _packet; // packet contains basic structure of MULTICAST_FRAME and payload, is re-used with new IV and addressing each time
|
||||||
std::vector<Address> _alreadySentTo;
|
std::vector<Address> _alreadySentTo;
|
||||||
|
@ -151,9 +151,9 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
|||||||
TRACE("%s: MULTICAST %s -> %s %s %d",network->tapDeviceName().c_str(),from.toString().c_str(),mg.toString().c_str(),etherTypeName(etherType),(int)data.size());
|
TRACE("%s: MULTICAST %s -> %s %s %d",network->tapDeviceName().c_str(),from.toString().c_str(),mg.toString().c_str(),etherTypeName(etherType),(int)data.size());
|
||||||
|
|
||||||
RR->mc->send(
|
RR->mc->send(
|
||||||
RR,
|
|
||||||
((!nconf->isPublic())&&(nconf->com())) ? &(nconf->com()) : (const CertificateOfMembership *)0,
|
((!nconf->isPublic())&&(nconf->com())) ? &(nconf->com()) : (const CertificateOfMembership *)0,
|
||||||
network->wantMulticastGroup(mg) ? nconf->multicastLimit() : 0,
|
nconf->multicastLimit(),
|
||||||
|
network->wantMulticastGroup(mg) ? ZT_MULTICAST_DEFAULT_IMPLICIT_GATHER : 0,
|
||||||
now,
|
now,
|
||||||
network->id(),
|
network->id(),
|
||||||
mg,
|
mg,
|
||||||
|
@ -49,7 +49,7 @@ Topology::Topology(const RuntimeEnvironment *renv,bool enablePermanentIdCaching)
|
|||||||
|
|
||||||
Topology::~Topology()
|
Topology::~Topology()
|
||||||
{
|
{
|
||||||
clean();
|
clean(Utils::now());
|
||||||
_dumpPeers();
|
_dumpPeers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,9 +256,8 @@ keep_searching_for_supernodes:
|
|||||||
return bestSupernode;
|
return bestSupernode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Topology::clean()
|
void Topology::clean(uint64_t now)
|
||||||
{
|
{
|
||||||
uint64_t now = Utils::now();
|
|
||||||
Mutex::Lock _l(_activePeers_m);
|
Mutex::Lock _l(_activePeers_m);
|
||||||
Mutex::Lock _l2(_supernodes_m);
|
Mutex::Lock _l2(_supernodes_m);
|
||||||
for(std::map< Address,SharedPtr<Peer> >::iterator p(_activePeers.begin());p!=_activePeers.end();) {
|
for(std::map< Address,SharedPtr<Peer> >::iterator p(_activePeers.begin());p!=_activePeers.end();) {
|
||||||
|
@ -186,7 +186,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Clean and flush database
|
* Clean and flush database
|
||||||
*/
|
*/
|
||||||
void clean();
|
void clean(uint64_t now);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply a function or function object to all peers
|
* Apply a function or function object to all peers
|
||||||
|
Loading…
x
Reference in New Issue
Block a user