Fix some deadlock issues, move awareness of broadcast subscription into core, other bug fixes.

This commit is contained in:
Adam Ierymenko 2015-04-15 13:09:20 -07:00
parent 508519b62a
commit 1c9ca73065
7 changed files with 105 additions and 108 deletions

View file

@ -47,6 +47,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid) :
_id(nwid),
_mac(renv->identity.address(),nwid),
_enabled(true),
_portInitialized(false),
_lastConfigUpdate(0),
_destroyed(false),
_netconfFailure(NETCONF_FAILURE_NONE),
@ -84,7 +85,6 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid) :
const char *e = p + mcdb.length();
if (!memcmp("ZTMCD0",p,6)) {
p += 6;
Mutex::Lock _l(_lock);
while (p != e) {
CertificateOfMembership com;
com.deserialize2(p,e);
@ -97,9 +97,12 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid) :
} catch ( ... ) {} // ignore invalid MCDB, we'll re-learn from peers
}
ZT1_VirtualNetworkConfig ctmp;
_externalConfig(&ctmp);
_portError = RR->node->configureVirtualNetworkPort(_id,ZT1_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
if (!_portInitialized) {
ZT1_VirtualNetworkConfig ctmp;
_externalConfig(&ctmp);
_portError = RR->node->configureVirtualNetworkPort(_id,ZT1_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
_portInitialized = true;
}
}
Network::~Network()
@ -145,6 +148,8 @@ std::vector<MulticastGroup> Network::allMulticastGroups() const
if (!std::binary_search(mgs.begin(),oldend,i->first))
mgs.push_back(i->first);
}
if ((_config)&&(_config->enableBroadcast()))
mgs.push_back(Network::BROADCAST);
std::sort(mgs.begin(),mgs.end());
return mgs;
}
@ -161,11 +166,13 @@ bool Network::subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBr
void Network::multicastSubscribe(const MulticastGroup &mg)
{
Mutex::Lock _l(_lock);
if (std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg))
return;
_myMulticastGroups.push_back(mg);
std::sort(_myMulticastGroups.begin(),_myMulticastGroups.end());
{
Mutex::Lock _l(_lock);
if (std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg))
return;
_myMulticastGroups.push_back(mg);
std::sort(_myMulticastGroups.begin(),_myMulticastGroups.end());
}
_announceMulticastGroups();
}
@ -183,19 +190,22 @@ void Network::multicastUnsubscribe(const MulticastGroup &mg)
bool Network::applyConfiguration(const SharedPtr<NetworkConfig> &conf)
{
Mutex::Lock _l(_lock);
if (_destroyed)
if (_destroyed) // sanity check
return false;
try {
if ((conf->networkId() == _id)&&(conf->issuedTo() == RR->identity.address())) {
_config = conf;
_lastConfigUpdate = RR->node->now();
_netconfFailure = NETCONF_FAILURE_NONE;
ZT1_VirtualNetworkConfig ctmp;
_externalConfig(&ctmp);
_portError = RR->node->configureVirtualNetworkPort(_id,ZT1_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE,&ctmp);
bool portInitialized;
{
Mutex::Lock _l(_lock);
_config = conf;
_lastConfigUpdate = RR->node->now();
_netconfFailure = NETCONF_FAILURE_NONE;
_externalConfig(&ctmp);
portInitialized = _portInitialized;
_portInitialized = true;
}
_portError = RR->node->configureVirtualNetworkPort(_id,(portInitialized) ? ZT1_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT1_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
return true;
} else {
TRACE("ignored invalid configuration for network %.16llx (configuration contains mismatched network ID or issued-to address)",(unsigned long long)_id);
@ -462,7 +472,7 @@ ZT1_VirtualNetworkStatus Network::_status() const
case NETCONF_FAILURE_NOT_FOUND:
return ZT1_NETWORK_STATUS_NOT_FOUND;
case NETCONF_FAILURE_NONE:
return ((_lastConfigUpdate > 0) ? ZT1_NETWORK_STATUS_OK : ZT1_NETWORK_STATUS_REQUESTING_CONFIGURATION);
return ((_config) ? ZT1_NETWORK_STATUS_OK : ZT1_NETWORK_STATUS_REQUESTING_CONFIGURATION);
default:
return ZT1_NETWORK_STATUS_PORT_ERROR;
}

View file

@ -65,6 +65,16 @@ class Network : NonCopyable
public:
/**
* Broadcast multicast group: ff:ff:ff:ff:ff:ff / 0
*/
static const MulticastGroup BROADCAST;
/**
* Construct a new network
*
* Note that init() should be called immediately after the network is
* constructed to actually configure the port.
*
* @param renv Runtime environment
* @param nwid Network ID
*/
@ -72,11 +82,6 @@ public:
~Network();
/**
* Broadcast multicast group: ff:ff:ff:ff:ff:ff / 0
*/
static const MulticastGroup BROADCAST;
/**
* @return Network ID
*/
@ -348,7 +353,8 @@ private:
const RuntimeEnvironment *RR;
uint64_t _id;
MAC _mac; // local MAC address
bool _enabled;
volatile bool _enabled;
volatile bool _portInitialized;
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
@ -370,7 +376,7 @@ private:
NETCONF_FAILURE_NOT_FOUND,
NETCONF_FAILURE_INIT_FAILED
} _netconfFailure;
int _portError; // return value from port config callback
volatile int _portError; // return value from port config callback
Mutex _lock;

View file

@ -152,16 +152,10 @@ ZT1_ResultCode Node::processWirePacket(
unsigned int linkDesperation,
const void *packetData,
unsigned int packetLength,
uint64_t *nextBackgroundTaskDeadline)
volatile uint64_t *nextBackgroundTaskDeadline)
{
if (now >= *nextBackgroundTaskDeadline) {
ZT1_ResultCode rc = processBackgroundTasks(now,nextBackgroundTaskDeadline);
if (rc != ZT1_RESULT_OK)
return rc;
} else _now = now;
_now = now;
RR->sw->onRemotePacket(*(reinterpret_cast<const InetAddress *>(remoteAddress)),linkDesperation,packetData,packetLength);
return ZT1_RESULT_OK;
}
@ -174,20 +168,14 @@ ZT1_ResultCode Node::processVirtualNetworkFrame(
unsigned int vlanId,
const void *frameData,
unsigned int frameLength,
uint64_t *nextBackgroundTaskDeadline)
volatile uint64_t *nextBackgroundTaskDeadline)
{
if (now >= *nextBackgroundTaskDeadline) {
ZT1_ResultCode rc = processBackgroundTasks(now,nextBackgroundTaskDeadline);
if (rc != ZT1_RESULT_OK)
return rc;
} else _now = now;
SharedPtr<Network> nw(network(nwid));
if (nw)
_now = now;
SharedPtr<Network> nw(this->network(nwid));
if (nw) {
RR->sw->onLocalEthernet(nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength);
else return ZT1_RESULT_ERROR_NETWORK_NOT_FOUND;
return ZT1_RESULT_OK;
return ZT1_RESULT_OK;
} else return ZT1_RESULT_ERROR_NETWORK_NOT_FOUND;
}
class _PingPeersThatNeedPing
@ -217,7 +205,7 @@ private:
std::vector<Address> _supernodes;
};
ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,uint64_t *nextBackgroundTaskDeadline)
ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
{
_now = now;
Mutex::Lock bl(_backgroundTasksLock);
@ -260,6 +248,7 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,uint64_t *nextBackgroun
*(reinterpret_cast<uint32_t *>(beacon)) = RR->prng->next32();
*(reinterpret_cast<uint32_t *>(beacon + 4)) = RR->prng->next32();
RR->identity.address().copyTo(beacon + 8,5);
RR->antiRec->logOutgoingZT(beacon,13);
putPacket(ZT_DEFAULTS.v4Broadcast,beacon,13,0);
}
}
@ -292,9 +281,9 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,uint64_t *nextBackgroun
ZT1_ResultCode Node::join(uint64_t nwid)
{
Mutex::Lock _l(_networks_m);
SharedPtr<Network> &nw = _networks[nwid];
if (!nw)
nw = SharedPtr<Network>(new Network(RR,nwid));
SharedPtr<Network> &nwe = _networks[nwid];
if (!nwe)
nwe = SharedPtr<Network>(new Network(RR,nwid));
return ZT1_RESULT_OK;
}
@ -311,20 +300,20 @@ ZT1_ResultCode Node::leave(uint64_t nwid)
ZT1_ResultCode Node::multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi)
{
Mutex::Lock _l(_networks_m);
std::map< uint64_t,SharedPtr<Network> >::iterator nw(_networks.find(nwid));
if (nw != _networks.end())
nw->second->multicastSubscribe(MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
return ZT1_RESULT_OK;
SharedPtr<Network> nw(this->network(nwid));
if (nw) {
nw->multicastSubscribe(MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
return ZT1_RESULT_OK;
} else return ZT1_RESULT_ERROR_NETWORK_NOT_FOUND;
}
ZT1_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi)
{
Mutex::Lock _l(_networks_m);
std::map< uint64_t,SharedPtr<Network> >::iterator nw(_networks.find(nwid));
if (nw != _networks.end())
nw->second->multicastUnsubscribe(MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
return ZT1_RESULT_OK;
SharedPtr<Network> nw(this->network(nwid));
if (nw) {
nw->multicastUnsubscribe(MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
return ZT1_RESULT_OK;
} else return ZT1_RESULT_ERROR_NETWORK_NOT_FOUND;
}
uint64_t Node::address() const
@ -531,7 +520,7 @@ enum ZT1_ResultCode ZT1_Node_processWirePacket(
unsigned int linkDesperation,
const void *packetData,
unsigned int packetLength,
uint64_t *nextBackgroundTaskDeadline)
volatile uint64_t *nextBackgroundTaskDeadline)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(now,remoteAddress,linkDesperation,packetData,packetLength,nextBackgroundTaskDeadline);
@ -553,7 +542,7 @@ enum ZT1_ResultCode ZT1_Node_processVirtualNetworkFrame(
unsigned int vlanId,
const void *frameData,
unsigned int frameLength,
uint64_t *nextBackgroundTaskDeadline)
volatile uint64_t *nextBackgroundTaskDeadline)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->processVirtualNetworkFrame(now,nwid,sourceMac,destMac,etherType,vlanId,frameData,frameLength,nextBackgroundTaskDeadline);
@ -564,7 +553,7 @@ enum ZT1_ResultCode ZT1_Node_processVirtualNetworkFrame(
}
}
enum ZT1_ResultCode ZT1_Node_processBackgroundTasks(ZT1_Node *node,uint64_t now,uint64_t *nextBackgroundTaskDeadline)
enum ZT1_ResultCode ZT1_Node_processBackgroundTasks(ZT1_Node *node,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->processBackgroundTasks(now,nextBackgroundTaskDeadline);

View file

@ -83,7 +83,7 @@ public:
unsigned int linkDesperation,
const void *packetData,
unsigned int packetLength,
uint64_t *nextBackgroundTaskDeadline);
volatile uint64_t *nextBackgroundTaskDeadline);
ZT1_ResultCode processVirtualNetworkFrame(
uint64_t now,
uint64_t nwid,
@ -93,8 +93,8 @@ public:
unsigned int vlanId,
const void *frameData,
unsigned int frameLength,
uint64_t *nextBackgroundTaskDeadline);
ZT1_ResultCode processBackgroundTasks(uint64_t now,uint64_t *nextBackgroundTaskDeadline);
volatile uint64_t *nextBackgroundTaskDeadline);
ZT1_ResultCode processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline);
ZT1_ResultCode join(uint64_t nwid);
ZT1_ResultCode leave(uint64_t nwid);
ZT1_ResultCode multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);

View file

@ -153,7 +153,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
return;
}
//TRACE("%.16llx: MULTICAST %s -> %s %s %u",network->id(),from.toString().c_str(),mg.toString().c_str(),etherTypeName(etherType),len);
TRACE("%.16llx: MULTICAST %s -> %s %s %u",network->id(),from.toString().c_str(),mg.toString().c_str(),etherTypeName(etherType),len);
RR->mc->send(
((!nconf->isPublic())&&(nconf->com())) ? &(nconf->com()) : (const CertificateOfMembership *)0,
@ -171,7 +171,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
}
if (to[0] == MAC::firstOctetForNetwork(network->id())) {
// Destination is another ZeroTier peer
// Destination is another ZeroTier peer on the same network
Address toZT(to.toAddress(network->id()));
if (network->isAllowed(toZT)) {
@ -203,8 +203,10 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
outp.compress();
send(outp,true);
}
TRACE("%.16llx: UNICAST: %s -> %s etherType==%s(%.4x) vlanId==%u len==%u fromBridged==%d",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType),etherType,vlanId,len,(int)fromBridged);
} else {
TRACE("%.16llx: UNICAST: %s -> %s %s dropped, destination not a member of private network",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
TRACE("%.16llx: UNICAST: %s -> %s etherType==%s dropped, destination not a member of private network",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
}
return;