mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 20:13:44 +02:00
Clean up some multicast code.
This commit is contained in:
parent
e74cd4b4ef
commit
f03fd57997
5 changed files with 79 additions and 44 deletions
|
@ -28,7 +28,6 @@
|
||||||
|
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "RuntimeEnvironment.hpp"
|
#include "RuntimeEnvironment.hpp"
|
||||||
#include "SharedPtr.hpp"
|
|
||||||
#include "Multicaster.hpp"
|
#include "Multicaster.hpp"
|
||||||
#include "Topology.hpp"
|
#include "Topology.hpp"
|
||||||
#include "Switch.hpp"
|
#include "Switch.hpp"
|
||||||
|
@ -37,6 +36,7 @@
|
||||||
#include "C25519.hpp"
|
#include "C25519.hpp"
|
||||||
#include "CertificateOfMembership.hpp"
|
#include "CertificateOfMembership.hpp"
|
||||||
#include "Node.hpp"
|
#include "Node.hpp"
|
||||||
|
#include "Network.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
@ -159,11 +159,8 @@ std::vector<Address> Multicaster::getMembers(uint64_t nwid,const MulticastGroup
|
||||||
|
|
||||||
void Multicaster::send(
|
void Multicaster::send(
|
||||||
void *tPtr,
|
void *tPtr,
|
||||||
unsigned int limit,
|
|
||||||
int64_t now,
|
int64_t now,
|
||||||
uint64_t nwid,
|
const SharedPtr<Network> &network,
|
||||||
bool disableCompression,
|
|
||||||
const std::vector<Address> &alwaysSendTo,
|
|
||||||
const MulticastGroup &mg,
|
const MulticastGroup &mg,
|
||||||
const MAC &src,
|
const MAC &src,
|
||||||
unsigned int etherType,
|
unsigned int etherType,
|
||||||
|
@ -175,7 +172,7 @@ void Multicaster::send(
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Mutex::Lock _l(_groups_m);
|
Mutex::Lock _l(_groups_m);
|
||||||
MulticastGroupStatus &gs = _groups[Multicaster::Key(nwid,mg)];
|
MulticastGroupStatus &gs = _groups[Multicaster::Key(network->id(),mg)];
|
||||||
|
|
||||||
if (!gs.members.empty()) {
|
if (!gs.members.empty()) {
|
||||||
// Allocate a memory buffer if group is monstrous
|
// Allocate a memory buffer if group is monstrous
|
||||||
|
@ -193,6 +190,10 @@ void Multicaster::send(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Address activeBridges[ZT_MAX_NETWORK_SPECIALISTS];
|
||||||
|
const unsigned int activeBridgeCount = network->config().activeBridges(activeBridges);
|
||||||
|
const unsigned int limit = network->config().multicastLimit;
|
||||||
|
|
||||||
if (gs.members.size() >= limit) {
|
if (gs.members.size() >= limit) {
|
||||||
// Skip queue if we already have enough members to complete the send operation
|
// Skip queue if we already have enough members to complete the send operation
|
||||||
OutboundMulticast out;
|
OutboundMulticast out;
|
||||||
|
@ -200,8 +201,8 @@ void Multicaster::send(
|
||||||
out.init(
|
out.init(
|
||||||
RR,
|
RR,
|
||||||
now,
|
now,
|
||||||
nwid,
|
network->id(),
|
||||||
disableCompression,
|
network->config().disableCompression(),
|
||||||
limit,
|
limit,
|
||||||
1, // we'll still gather a little from peers to keep multicast list fresh
|
1, // we'll still gather a little from peers to keep multicast list fresh
|
||||||
src,
|
src,
|
||||||
|
@ -212,9 +213,9 @@ void Multicaster::send(
|
||||||
|
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
|
|
||||||
for(std::vector<Address>::const_iterator ast(alwaysSendTo.begin());ast!=alwaysSendTo.end();++ast) {
|
for(unsigned int i=0;i<activeBridgeCount;++i) {
|
||||||
if (*ast != RR->identity.address()) {
|
if (activeBridges[i] != RR->identity.address()) {
|
||||||
out.sendOnly(RR,tPtr,*ast); // optimization: don't use dedup log if it's a one-pass send
|
out.sendOnly(RR,tPtr,activeBridges[i]); // optimization: don't use dedup log if it's a one-pass send
|
||||||
if (++count >= limit)
|
if (++count >= limit)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -222,40 +223,59 @@ void Multicaster::send(
|
||||||
|
|
||||||
unsigned long idx = 0;
|
unsigned long idx = 0;
|
||||||
while ((count < limit)&&(idx < gs.members.size())) {
|
while ((count < limit)&&(idx < gs.members.size())) {
|
||||||
Address ma(gs.members[indexes[idx++]].address);
|
const Address ma(gs.members[indexes[idx++]].address);
|
||||||
if (std::find(alwaysSendTo.begin(),alwaysSendTo.end(),ma) == alwaysSendTo.end()) {
|
if (std::find(activeBridges,activeBridges + activeBridgeCount,ma) == (activeBridges + activeBridgeCount)) {
|
||||||
out.sendOnly(RR,tPtr,ma); // optimization: don't use dedup log if it's a one-pass send
|
out.sendOnly(RR,tPtr,ma); // optimization: don't use dedup log if it's a one-pass send
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unsigned int gatherLimit = (limit - (unsigned int)gs.members.size()) + 1;
|
const unsigned int gatherLimit = (limit - (unsigned int)gs.members.size()) + 1;
|
||||||
|
|
||||||
if ((gs.members.empty())||((now - gs.lastExplicitGather) >= ZT_MULTICAST_EXPLICIT_GATHER_DELAY)) {
|
if ((gs.members.empty())||((now - gs.lastExplicitGather) >= ZT_MULTICAST_EXPLICIT_GATHER_DELAY)) {
|
||||||
gs.lastExplicitGather = now;
|
gs.lastExplicitGather = now;
|
||||||
|
|
||||||
Address explicitGatherPeers[16];
|
Address explicitGatherPeers[16];
|
||||||
unsigned int numExplicitGatherPeers = 0;
|
unsigned int numExplicitGatherPeers = 0;
|
||||||
|
|
||||||
SharedPtr<Peer> bestRoot(RR->topology->getUpstreamPeer());
|
SharedPtr<Peer> bestRoot(RR->topology->getUpstreamPeer());
|
||||||
if (bestRoot)
|
if (bestRoot)
|
||||||
explicitGatherPeers[numExplicitGatherPeers++] = bestRoot->address();
|
explicitGatherPeers[numExplicitGatherPeers++] = bestRoot->address();
|
||||||
explicitGatherPeers[numExplicitGatherPeers++] = Network::controllerFor(nwid);
|
|
||||||
SharedPtr<Network> network(RR->node->network(nwid));
|
explicitGatherPeers[numExplicitGatherPeers++] = network->controller();
|
||||||
if (network) {
|
|
||||||
std::vector<Address> anchors(network->config().anchors());
|
Address ac[ZT_MAX_NETWORK_SPECIALISTS];
|
||||||
for(std::vector<Address>::const_iterator a(anchors.begin());a!=anchors.end();++a) {
|
const unsigned int accnt = network->config().alwaysContactAddresses(ac);
|
||||||
if (*a != RR->identity.address()) {
|
unsigned int shuffled[ZT_MAX_NETWORK_SPECIALISTS];
|
||||||
explicitGatherPeers[numExplicitGatherPeers++] = *a;
|
for(unsigned int i=0;i<accnt;++i)
|
||||||
if (numExplicitGatherPeers == 16)
|
shuffled[i] = i;
|
||||||
break;
|
for(unsigned int i=0,k=accnt>>1;i<k;++i) {
|
||||||
}
|
const uint64_t x = RR->node->prng();
|
||||||
|
const unsigned int x1 = shuffled[(unsigned int)x % accnt];
|
||||||
|
const unsigned int x2 = shuffled[(unsigned int)(x >> 32) % accnt];
|
||||||
|
const unsigned int tmp = shuffled[x1];
|
||||||
|
shuffled[x1] = shuffled[x2];
|
||||||
|
shuffled[x2] = tmp;
|
||||||
|
}
|
||||||
|
for(unsigned int i=0;i<accnt;++i) {
|
||||||
|
explicitGatherPeers[numExplicitGatherPeers++] = ac[shuffled[i]];
|
||||||
|
if (numExplicitGatherPeers == 16)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Address> anchors(network->config().anchors());
|
||||||
|
for(std::vector<Address>::const_iterator a(anchors.begin());a!=anchors.end();++a) {
|
||||||
|
if (*a != RR->identity.address()) {
|
||||||
|
explicitGatherPeers[numExplicitGatherPeers++] = *a;
|
||||||
|
if (numExplicitGatherPeers == 16)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int k=0;k<numExplicitGatherPeers;++k) {
|
for(unsigned int k=0;k<numExplicitGatherPeers;++k) {
|
||||||
const CertificateOfMembership *com = (network) ? ((network->config().com) ? &(network->config().com) : (const CertificateOfMembership *)0) : (const CertificateOfMembership *)0;
|
const CertificateOfMembership *com = (network) ? ((network->config().com) ? &(network->config().com) : (const CertificateOfMembership *)0) : (const CertificateOfMembership *)0;
|
||||||
Packet outp(explicitGatherPeers[k],RR->identity.address(),Packet::VERB_MULTICAST_GATHER);
|
Packet outp(explicitGatherPeers[k],RR->identity.address(),Packet::VERB_MULTICAST_GATHER);
|
||||||
outp.append(nwid);
|
outp.append(network->id());
|
||||||
outp.append((uint8_t)((com) ? 0x01 : 0x00));
|
outp.append((uint8_t)((com) ? 0x01 : 0x00));
|
||||||
mg.mac().appendTo(outp);
|
mg.mac().appendTo(outp);
|
||||||
outp.append((uint32_t)mg.adi());
|
outp.append((uint32_t)mg.adi());
|
||||||
|
@ -273,8 +293,8 @@ void Multicaster::send(
|
||||||
out.init(
|
out.init(
|
||||||
RR,
|
RR,
|
||||||
now,
|
now,
|
||||||
nwid,
|
network->id(),
|
||||||
disableCompression,
|
network->config().disableCompression(),
|
||||||
limit,
|
limit,
|
||||||
gatherLimit,
|
gatherLimit,
|
||||||
src,
|
src,
|
||||||
|
@ -285,9 +305,9 @@ void Multicaster::send(
|
||||||
|
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
|
|
||||||
for(std::vector<Address>::const_iterator ast(alwaysSendTo.begin());ast!=alwaysSendTo.end();++ast) {
|
for(unsigned int i=0;i<activeBridgeCount;++i) {
|
||||||
if (*ast != RR->identity.address()) {
|
if (activeBridges[i] != RR->identity.address()) {
|
||||||
out.sendAndLog(RR,tPtr,*ast);
|
out.sendAndLog(RR,tPtr,activeBridges[i]);
|
||||||
if (++count >= limit)
|
if (++count >= limit)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -296,7 +316,7 @@ void Multicaster::send(
|
||||||
unsigned long idx = 0;
|
unsigned long idx = 0;
|
||||||
while ((count < limit)&&(idx < gs.members.size())) {
|
while ((count < limit)&&(idx < gs.members.size())) {
|
||||||
Address ma(gs.members[indexes[idx++]].address);
|
Address ma(gs.members[indexes[idx++]].address);
|
||||||
if (std::find(alwaysSendTo.begin(),alwaysSendTo.end(),ma) == alwaysSendTo.end()) {
|
if (std::find(activeBridges,activeBridges + activeBridgeCount,ma) == (activeBridges + activeBridgeCount)) {
|
||||||
out.sendAndLog(RR,tPtr,ma);
|
out.sendAndLog(RR,tPtr,ma);
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,12 +42,14 @@
|
||||||
#include "OutboundMulticast.hpp"
|
#include "OutboundMulticast.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
#include "Mutex.hpp"
|
#include "Mutex.hpp"
|
||||||
|
#include "SharedPtr.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
class RuntimeEnvironment;
|
class RuntimeEnvironment;
|
||||||
class CertificateOfMembership;
|
class CertificateOfMembership;
|
||||||
class Packet;
|
class Packet;
|
||||||
|
class Network;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database of known multicast peers within a network
|
* Database of known multicast peers within a network
|
||||||
|
@ -128,11 +130,8 @@ public:
|
||||||
* Send a multicast
|
* Send a multicast
|
||||||
*
|
*
|
||||||
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
||||||
* @param limit Multicast limit
|
|
||||||
* @param now Current time
|
* @param now Current time
|
||||||
* @param nwid Network ID
|
* @param network Network
|
||||||
* @param disableCompression Disable packet payload compression?
|
|
||||||
* @param alwaysSendTo Send to these peers first and even if not included in subscriber list
|
|
||||||
* @param mg Multicast group
|
* @param mg Multicast group
|
||||||
* @param src Source Ethernet MAC address or NULL to skip in packet and compute from ZT address (non-bridged mode)
|
* @param src Source Ethernet MAC address or NULL to skip in packet and compute from ZT address (non-bridged mode)
|
||||||
* @param etherType Ethernet frame type
|
* @param etherType Ethernet frame type
|
||||||
|
@ -141,11 +140,8 @@ public:
|
||||||
*/
|
*/
|
||||||
void send(
|
void send(
|
||||||
void *tPtr,
|
void *tPtr,
|
||||||
unsigned int limit,
|
|
||||||
int64_t now,
|
int64_t now,
|
||||||
uint64_t nwid,
|
const SharedPtr<Network> &network,
|
||||||
bool disableCompression,
|
|
||||||
const std::vector<Address> &alwaysSendTo,
|
|
||||||
const MulticastGroup &mg,
|
const MulticastGroup &mg,
|
||||||
const MAC &src,
|
const MAC &src,
|
||||||
unsigned int etherType,
|
unsigned int etherType,
|
||||||
|
|
|
@ -1432,7 +1432,8 @@ void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMu
|
||||||
std::sort(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end());
|
std::sort(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end());
|
||||||
|
|
||||||
for(std::vector<Address>::const_iterator a(alwaysAnnounceTo.begin());a!=alwaysAnnounceTo.end();++a) {
|
for(std::vector<Address>::const_iterator a(alwaysAnnounceTo.begin());a!=alwaysAnnounceTo.end();++a) {
|
||||||
if ( (_config.com) && (!_memberships.contains(*a)) ) { // push COM to non-members so they can do multicast request auth
|
// push COM to non-members so they can do multicast request auth
|
||||||
|
if ( (_config.com) && (!_memberships.contains(*a)) && (*a != RR->identity.address()) ) {
|
||||||
Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
||||||
_config.com.serialize(outp);
|
_config.com.serialize(outp);
|
||||||
outp.append((uint8_t)0x00);
|
outp.append((uint8_t)0x00);
|
||||||
|
|
|
@ -292,6 +292,16 @@ public:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline unsigned int activeBridges(Address ab[ZT_MAX_NETWORK_SPECIALISTS]) const
|
||||||
|
{
|
||||||
|
unsigned int c = 0;
|
||||||
|
for(unsigned int i=0;i<specialistCount;++i) {
|
||||||
|
if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0)
|
||||||
|
ab[c++] = specialists[i];
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
inline std::vector<Address> anchors() const
|
inline std::vector<Address> anchors() const
|
||||||
{
|
{
|
||||||
std::vector<Address> r;
|
std::vector<Address> r;
|
||||||
|
@ -322,6 +332,16 @@ public:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline unsigned int alwaysContactAddresses(Address ac[ZT_MAX_NETWORK_SPECIALISTS]) const
|
||||||
|
{
|
||||||
|
unsigned int c = 0;
|
||||||
|
for(unsigned int i=0;i<specialistCount;++i) {
|
||||||
|
if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0)
|
||||||
|
ac[c++] = specialists[i];
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
inline void alwaysContactAddresses(Hashtable< Address,std::vector<InetAddress> > &a) const
|
inline void alwaysContactAddresses(Hashtable< Address,std::vector<InetAddress> > &a) const
|
||||||
{
|
{
|
||||||
for(unsigned int i=0;i<specialistCount;++i) {
|
for(unsigned int i=0;i<specialistCount;++i) {
|
||||||
|
|
|
@ -389,11 +389,9 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
|
||||||
|
|
||||||
RR->mc->send(
|
RR->mc->send(
|
||||||
tPtr,
|
tPtr,
|
||||||
network->config().multicastLimit,
|
|
||||||
RR->node->now(),
|
RR->node->now(),
|
||||||
network->id(),
|
network,
|
||||||
network->config().disableCompression(),
|
// network->config().activeBridges(),
|
||||||
network->config().activeBridges(),
|
|
||||||
multicastGroup,
|
multicastGroup,
|
||||||
(fromBridged) ? from : MAC(),
|
(fromBridged) ? from : MAC(),
|
||||||
etherType,
|
etherType,
|
||||||
|
|
Loading…
Add table
Reference in a new issue