Announce multicast group changes on network rescanMulticastGroups()

This commit is contained in:
Adam Ierymenko 2014-10-03 18:27:42 -07:00
parent aad344bb84
commit 496109fdcc
6 changed files with 86 additions and 39 deletions

1
.gitignore vendored
View File

@ -33,6 +33,7 @@
*.autosave
/ZeroTier One.dmg
/root-topology/*.secret
/testnet/local-testnet/n????
/testnet/local-testnet/*/peers.persist
/testnet/local-testnet/*/authtoken.secret
/testnet/local-testnet/*/*.log

View File

@ -111,33 +111,84 @@ SharedPtr<Network> Network::newInstance(const RuntimeEnvironment *renv,NodeConfi
return nw;
}
bool Network::updateMulticastGroups()
// Function object used by rescanMulticastGroups()
class AnnounceMulticastGroupsToPeersWithActiveDirectPaths
{
Mutex::Lock _l(_lock);
EthernetTap *t = _tap;
if (t) {
// Grab current groups from the local tap
bool updated = t->updateMulticastGroups(_myMulticastGroups);
public:
AnnounceMulticastGroupsToPeersWithActiveDirectPaths(const RuntimeEnvironment *renv,Network *nw) :
RR(renv),
_now(Utils::now()),
_network(nw)
{}
// Merge in learned groups from any hosts bridged in behind us
for(std::map<MulticastGroup,uint64_t>::const_iterator mg(_multicastGroupsBehindMe.begin());mg!=_multicastGroupsBehindMe.end();++mg)
_myMulticastGroups.insert(mg->first);
inline void operator()(Topology &t,const SharedPtr<Peer> &p)
{
if ( ( (p->hasActiveDirectPath(_now)) && (_network->isAllowed(p->address())) ) || (_network->controller() == p->address()) || (t.isSupernode(p->address())) ) {
Packet outp(p->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
// Add or remove BROADCAST group based on broadcast enabled netconf flag
if ((_config)&&(_config->enableBroadcast())) {
if (_myMulticastGroups.count(BROADCAST))
return updated;
else {
_myMulticastGroups.insert(BROADCAST);
return true;
std::set<MulticastGroup> mgs(_network->multicastGroups());
for(std::set<MulticastGroup>::iterator mg(mgs.begin());mg!=mgs.end();++mg) {
if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) {
outp.armor(p->key(),true);
p->send(RR,outp.data(),outp.size(),_now);
outp.reset(p->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
}
// network ID, MAC, ADI
outp.append((uint64_t)_network->id());
mg->mac().appendTo(outp);
outp.append((uint32_t)mg->adi());
}
if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) {
outp.armor(p->key(),true);
p->send(RR,outp.data(),outp.size(),_now);
}
} else {
if (_myMulticastGroups.count(BROADCAST)) {
_myMulticastGroups.erase(BROADCAST);
return true;
} else return updated;
}
} else return false;
}
private:
const RuntimeEnvironment *RR;
uint64_t _now;
Network *_network;
};
bool Network::rescanMulticastGroups()
{
bool updated = false;
{
Mutex::Lock _l(_lock);
EthernetTap *t = _tap;
if (t) {
// Grab current groups from the local tap
updated = t->updateMulticastGroups(_myMulticastGroups);
// Merge in learned groups from any hosts bridged in behind us
for(std::map<MulticastGroup,uint64_t>::const_iterator mg(_multicastGroupsBehindMe.begin());mg!=_multicastGroupsBehindMe.end();++mg)
_myMulticastGroups.insert(mg->first);
// Add or remove BROADCAST group based on broadcast enabled netconf flag
if ((_config)&&(_config->enableBroadcast())) {
if (!_myMulticastGroups.count(BROADCAST)) {
_myMulticastGroups.insert(BROADCAST);
updated = true;
}
} else {
if (_myMulticastGroups.count(BROADCAST)) {
_myMulticastGroups.erase(BROADCAST);
updated = true;
}
}
}
}
if (updated) {
AnnounceMulticastGroupsToPeersWithActiveDirectPaths afunc(RR,this);
RR->topology->eachPeer<AnnounceMulticastGroupsToPeersWithActiveDirectPaths &>(afunc);
}
return updated;
}
bool Network::applyConfiguration(const SharedPtr<NetworkConfig> &conf)
@ -449,6 +500,8 @@ void Network::threadMain()
t->setEnabled(_enabled);
}
}
rescanMulticastGroups();
}
void Network::_CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data)

View File

@ -148,11 +148,11 @@ public:
}
/**
* Update multicast groups for this network's tap and announce changes
* Rescan multicast groups for this network's tap and update peers on change
*
* @return True if internal multicast group set has changed since last update
*/
bool updateMulticastGroups();
bool rescanMulticastGroups();
/**
* @return Latest set of multicast groups for this network's tap
@ -163,16 +163,6 @@ public:
return _myMulticastGroups;
}
/**
* @param mg Multicast group
* @return True if this group is among those to which I am subscribed
*/
inline bool wantMulticastGroup(const MulticastGroup &mg) const
{
Mutex::Lock _l(_lock);
return (_myMulticastGroups.count(mg) > 0);
}
/**
* Apply a NetworkConfig to this network
*

View File

@ -585,7 +585,7 @@ Node::ReasonForTermination Node::run()
try {
std::vector< SharedPtr<Network> > networks(RR->nc->networks());
for(std::vector< SharedPtr<Network> >::const_iterator nw(networks.begin());nw!=networks.end();++nw)
(*nw)->updateMulticastGroups();
(*nw)->rescanMulticastGroups();
} catch (std::exception &exc) {
LOG("unexpected exception announcing multicast groups: %s",exc.what());
} catch ( ... ) {

View File

@ -113,10 +113,11 @@ void Peer::receive(
}
}
// Announce multicast groups of interest to direct peers if they are
// considered authorized members of a given network. Also announce to
// supernodes and network controllers. TODO: the former may go
// obsolete with time as network controllers take over this role.
/* Announce multicast groups of interest to direct peers if they are
* considered authorized members of a given network. Also announce to
* supernodes and network controllers. The other place this is done
* is in rescanMulticastGroups() in Network, but that only sends something
* if a network's multicast groups change. */
if ((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) {
_lastAnnouncedTo = now;

View File

@ -459,6 +459,8 @@ public:
}
private:
void _announceMulticastGroups(const RuntimeEnvironment *RR,uint64_t now);
unsigned char _key[ZT_PEER_SECRET_KEY_LENGTH];
Identity _id;