This commit is contained in:
Adam Ierymenko 2019-08-21 10:44:52 -07:00
parent 67a9898a99
commit 5280d28505
No known key found for this signature in database
GPG key ID: 1657198823E52A61
6 changed files with 89 additions and 82 deletions

View file

@ -311,6 +311,8 @@ public:
inline operator bool() const { return (_id); } inline operator bool() const { return (_id); }
inline bool addressesEqual(const Locator &l) const { return ((_physical == l._physical)&&(_virtual == l._virtual)); }
inline bool operator==(const Locator &l) const { return ((_ts == l._ts)&&(_id == l._id)&&(_signedBy == l._signedBy)&&(_physical == l._physical)&&(_virtual == l._virtual)&&(_signatureLength == l._signatureLength)&&(memcmp(_signature,l._signature,_signatureLength) == 0)); } inline bool operator==(const Locator &l) const { return ((_ts == l._ts)&&(_id == l._id)&&(_signedBy == l._signedBy)&&(_physical == l._physical)&&(_virtual == l._virtual)&&(_signatureLength == l._signatureLength)&&(memcmp(_signature,l._signature,_signatureLength) == 0)); }
inline bool operator!=(const Locator &l) const { return (!(*this == l)); } inline bool operator!=(const Locator &l) const { return (!(*this == l)); }
inline bool operator<(const Locator &l) const inline bool operator<(const Locator &l) const

View file

@ -78,12 +78,9 @@ public:
void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf); void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf);
/** /**
* @return True if we haven't pushed credentials in a long time (to cause proactive credential push) * @return Time we last pushed credentials to this member
*/ */
inline bool shouldPushCredentials(const int64_t now) const inline int64_t lastPushedCredentials() const { return _lastPushedCredentials; }
{
return ((now - _lastPushedCredentials) > ZT_PEER_ACTIVITY_TIMEOUT);
}
/** /**
* Check whether we should push MULTICAST_LIKEs to this peer, and update last sent time if true * Check whether we should push MULTICAST_LIKEs to this peer, and update last sent time if true

View file

@ -606,6 +606,11 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *u
Network::~Network() Network::~Network()
{ {
_memberships_l.lock();
_config_l.lock();
_config_l.unlock();
_memberships_l.unlock();
ZT_VirtualNetworkConfig ctmp; ZT_VirtualNetworkConfig ctmp;
_externalConfig(&ctmp); _externalConfig(&ctmp);
@ -638,7 +643,8 @@ bool Network::filterOutgoingPacket(
unsigned int ccLength = 0; unsigned int ccLength = 0;
bool ccWatch = false; bool ccWatch = false;
Mutex::Lock _l(_lock); Mutex::Lock l1(_memberships_l);
Mutex::Lock l2(_config_l);
Membership *const membership = (ztDest) ? _memberships.get(ztDest) : (Membership *)0; Membership *const membership = (ztDest) ? _memberships.get(ztDest) : (Membership *)0;
@ -755,7 +761,8 @@ int Network::filterIncomingPacket(
uint8_t qosBucket = 255; // For incoming packets this is a dummy value uint8_t qosBucket = 255; // For incoming packets this is a dummy value
Mutex::Lock _l(_lock); Mutex::Lock l1(_memberships_l);
Mutex::Lock l2(_config_l);
Membership &membership = _memberships[sourcePeer->address()]; Membership &membership = _memberships[sourcePeer->address()];
@ -861,7 +868,7 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
NetworkConfig *nc = (NetworkConfig *)0; NetworkConfig *nc = (NetworkConfig *)0;
uint64_t configUpdateId; uint64_t configUpdateId;
{ {
Mutex::Lock _l(_lock); Mutex::Lock l1(_config_l);
_IncomingConfigChunk *c = (_IncomingConfigChunk *)0; _IncomingConfigChunk *c = (_IncomingConfigChunk *)0;
uint64_t chunkId = 0; uint64_t chunkId = 0;
@ -907,6 +914,7 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
// New properly verified chunks can be flooded "virally" through the network // New properly verified chunks can be flooded "virally" through the network
if (fastPropagate) { if (fastPropagate) {
Mutex::Lock l2(_memberships_l);
Address *a = (Address *)0; Address *a = (Address *)0;
Membership *m = (Membership *)0; Membership *m = (Membership *)0;
Hashtable<Address,Membership>::Iterator i(_memberships); Hashtable<Address,Membership>::Iterator i(_memberships);
@ -993,7 +1001,7 @@ int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToD
ZT_VirtualNetworkConfig ctmp; ZT_VirtualNetworkConfig ctmp;
bool oldPortInitialized; bool oldPortInitialized;
{ // do things that require lock here, but unlock before calling callbacks { // do things that require lock here, but unlock before calling callbacks
Mutex::Lock _l(_lock); Mutex::Lock _l(_config_l);
_config = nconf; _config = nconf;
_lastConfigUpdate = RR->node->now(); _lastConfigUpdate = RR->node->now();
@ -1206,15 +1214,17 @@ void Network::requestConfiguration(void *tPtr)
bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer) bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer)
{ {
const int64_t now = RR->node->now(); const int64_t now = RR->node->now();
Mutex::Lock _l(_lock); Mutex::Lock l(_memberships_l);
try { try {
if (_config) { if (_config) {
Membership *m = _memberships.get(peer->address()); Membership *m = _memberships.get(peer->address());
if ( (_config.isPublic()) || ((m)&&(m->isAllowedOnNetwork(_config))) ) { if ( (_config.isPublic()) || ((m)&&(m->isAllowedOnNetwork(_config))) ) {
if (!m) if (!m)
m = &(_memberships[peer->address()]); m = &(_memberships[peer->address()]);
if (m->multicastLikeGate(now)) if (m->multicastLikeGate(now)) {
Mutex::Lock l2(_myMulticastGroups_l);
_announceMulticastGroupsTo(tPtr,peer->address(),_allMulticastGroups()); _announceMulticastGroupsTo(tPtr,peer->address(),_allMulticastGroups());
}
return true; return true;
} }
} }
@ -1224,7 +1234,7 @@ bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer)
bool Network::recentlyAssociatedWith(const Address &addr) bool Network::recentlyAssociatedWith(const Address &addr)
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_memberships_l);
const Membership *m = _memberships.get(addr); const Membership *m = _memberships.get(addr);
return ((m)&&(m->recentlyAssociated(RR->node->now()))); return ((m)&&(m->recentlyAssociated(RR->node->now())));
} }
@ -1232,7 +1242,7 @@ bool Network::recentlyAssociatedWith(const Address &addr)
void Network::clean() void Network::clean()
{ {
const int64_t now = RR->node->now(); const int64_t now = RR->node->now();
Mutex::Lock _l(_lock); Mutex::Lock _l(_memberships_l);
if (_destroyed) if (_destroyed)
return; return;
@ -1260,7 +1270,7 @@ Membership::AddCredentialResult Network::addCredential(void *tPtr,const Certific
{ {
if (com.networkId() != _id) if (com.networkId() != _id)
return Membership::ADD_REJECTED; return Membership::ADD_REJECTED;
Mutex::Lock _l(_lock); Mutex::Lock _l(_memberships_l);
return _memberships[com.issuedTo()].addCredential(RR,tPtr,_config,com); return _memberships[com.issuedTo()].addCredential(RR,tPtr,_config,com);
} }
@ -1269,7 +1279,7 @@ Membership::AddCredentialResult Network::addCredential(void *tPtr,const Address
if (rev.networkId() != _id) if (rev.networkId() != _id)
return Membership::ADD_REJECTED; return Membership::ADD_REJECTED;
Mutex::Lock _l(_lock); Mutex::Lock _l(_memberships_l);
Membership &m = _memberships[rev.target()]; Membership &m = _memberships[rev.target()];
const Membership::AddCredentialResult result = m.addCredential(RR,tPtr,_config,rev); const Membership::AddCredentialResult result = m.addCredential(RR,tPtr,_config,rev);
@ -1295,15 +1305,8 @@ Membership::AddCredentialResult Network::addCredential(void *tPtr,const Address
return result; return result;
} }
void Network::destroy()
{
Mutex::Lock _l(_lock);
_destroyed = true;
}
ZT_VirtualNetworkStatus Network::_status() const ZT_VirtualNetworkStatus Network::_status() const
{ {
// assumes _lock is locked
if (_portError) if (_portError)
return ZT_NETWORK_STATUS_PORT_ERROR; return ZT_NETWORK_STATUS_PORT_ERROR;
switch(_netconfFailure) { switch(_netconfFailure) {
@ -1320,7 +1323,7 @@ ZT_VirtualNetworkStatus Network::_status() const
void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
{ {
// assumes _lock is locked // assumes _config_l is locked
ec->nwid = _id; ec->nwid = _id;
ec->mac = _mac.toInt(); ec->mac = _mac.toInt();
if (_config) if (_config)
@ -1363,9 +1366,9 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
} }
} }
void Network::_sendUpdatesToMembers(void *tPtr) void Network::_announceMulticastGroups(void *tPtr)
{ {
// Assumes _lock is locked // Assumes _myMulticastGroups_l and _memberships_l are locked
const std::vector<MulticastGroup> groups(_allMulticastGroups()); const std::vector<MulticastGroup> groups(_allMulticastGroups());
_announceMulticastGroupsTo(tPtr,controller(),groups); _announceMulticastGroupsTo(tPtr,controller(),groups);
{ {
@ -1381,7 +1384,7 @@ void Network::_sendUpdatesToMembers(void *tPtr)
void Network::_announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups) void Network::_announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups)
{ {
// Assumes _lock is locked // Assumes _myMulticastGroups_l and _memberships_l are locked
Packet *const outp = new Packet(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE); Packet *const outp = new Packet(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) { for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) {

View file

@ -98,7 +98,7 @@ public:
inline bool multicastEnabled() const { return (_config.multicastLimit > 0); } inline bool multicastEnabled() const { return (_config.multicastLimit > 0); }
inline bool hasConfig() const { return (_config); } inline bool hasConfig() const { return (_config); }
inline uint64_t lastConfigUpdate() const { return _lastConfigUpdate; } inline uint64_t lastConfigUpdate() const { return _lastConfigUpdate; }
inline ZT_VirtualNetworkStatus status() const { Mutex::Lock _l(_lock); return _status(); } inline ZT_VirtualNetworkStatus status() const { return _status(); }
inline const NetworkConfig &config() const { return _config; } inline const NetworkConfig &config() const { return _config; }
inline const MAC &mac() const { return _mac; } inline const MAC &mac() const { return _mac; }
@ -174,7 +174,7 @@ public:
*/ */
inline bool subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBridgedGroups) const inline bool subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBridgedGroups) const
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_myMulticastGroups_l);
if (std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)) if (std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg))
return true; return true;
else if (includeBridgedGroups) else if (includeBridgedGroups)
@ -190,10 +190,11 @@ public:
*/ */
inline void multicastSubscribe(void *tPtr,const MulticastGroup &mg) inline void multicastSubscribe(void *tPtr,const MulticastGroup &mg)
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_myMulticastGroups_l);
if (!std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)) { if (!std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)) {
_myMulticastGroups.insert(std::upper_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg),mg); _myMulticastGroups.insert(std::upper_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg),mg);
_sendUpdatesToMembers(tPtr); Mutex::Lock l2(_memberships_l);
_announceMulticastGroups(tPtr);
} }
} }
@ -204,7 +205,7 @@ public:
*/ */
inline void multicastUnsubscribe(const MulticastGroup &mg) inline void multicastUnsubscribe(const MulticastGroup &mg)
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_myMulticastGroups_l);
std::vector<MulticastGroup>::iterator i(std::lower_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)); std::vector<MulticastGroup>::iterator i(std::lower_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg));
if ( (i != _myMulticastGroups.end()) && (*i == mg) ) if ( (i != _myMulticastGroups.end()) && (*i == mg) )
_myMulticastGroups.erase(i); _myMulticastGroups.erase(i);
@ -239,20 +240,12 @@ public:
/** /**
* Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this * Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this
*/ */
inline void setAccessDenied() inline void setAccessDenied() { _netconfFailure = NETCONF_FAILURE_ACCESS_DENIED; }
{
Mutex::Lock _l(_lock);
_netconfFailure = NETCONF_FAILURE_ACCESS_DENIED;
}
/** /**
* Set netconf failure to 'not found' -- called by IncomingPacket when controller reports this * Set netconf failure to 'not found' -- called by IncomingPacket when controller reports this
*/ */
inline void setNotFound() inline void setNotFound() { _netconfFailure = NETCONF_FAILURE_NOT_FOUND; }
{
Mutex::Lock _l(_lock);
_netconfFailure = NETCONF_FAILURE_NOT_FOUND;
}
/** /**
* Causes this network to request an updated configuration from its master node now * Causes this network to request an updated configuration from its master node now
@ -294,8 +287,9 @@ public:
*/ */
inline void sendUpdatesToMembers(void *tPtr) inline void sendUpdatesToMembers(void *tPtr)
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_myMulticastGroups_l);
_sendUpdatesToMembers(tPtr); Mutex::Lock _l2(_memberships_l);
_announceMulticastGroups(tPtr);
} }
/** /**
@ -306,7 +300,7 @@ public:
*/ */
inline Address findBridgeTo(const MAC &mac) const inline Address findBridgeTo(const MAC &mac) const
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_remoteBridgeRoutes_l);
const Address *const br = _remoteBridgeRoutes.get(mac); const Address *const br = _remoteBridgeRoutes.get(mac);
return ((br) ? *br : Address()); return ((br) ? *br : Address());
} }
@ -324,7 +318,7 @@ public:
*/ */
inline void learnBridgeRoute(const MAC &mac,const Address &addr) inline void learnBridgeRoute(const MAC &mac,const Address &addr)
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_remoteBridgeRoutes_l);
_remoteBridgeRoutes[mac] = addr; _remoteBridgeRoutes[mac] = addr;
// Anti-DOS circuit breaker to prevent nodes from spamming us with absurd numbers of bridge routes // Anti-DOS circuit breaker to prevent nodes from spamming us with absurd numbers of bridge routes
@ -368,7 +362,7 @@ public:
*/ */
inline void learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int64_t now) inline void learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int64_t now)
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_multicastGroupsBehindMe_l);
_multicastGroupsBehindMe.set(mg,now); _multicastGroupsBehindMe.set(mg,now);
} }
@ -384,7 +378,7 @@ public:
{ {
if (cap.networkId() != _id) if (cap.networkId() != _id)
return Membership::ADD_REJECTED; return Membership::ADD_REJECTED;
Mutex::Lock _l(_lock); Mutex::Lock _l(_memberships_l);
return _memberships[cap.issuedTo()].addCredential(RR,tPtr,_config,cap); return _memberships[cap.issuedTo()].addCredential(RR,tPtr,_config,cap);
} }
@ -395,7 +389,7 @@ public:
{ {
if (tag.networkId() != _id) if (tag.networkId() != _id)
return Membership::ADD_REJECTED; return Membership::ADD_REJECTED;
Mutex::Lock _l(_lock); Mutex::Lock _l(_memberships_l);
return _memberships[tag.issuedTo()].addCredential(RR,tPtr,_config,tag); return _memberships[tag.issuedTo()].addCredential(RR,tPtr,_config,tag);
} }
@ -411,7 +405,7 @@ public:
{ {
if (coo.networkId() != _id) if (coo.networkId() != _id)
return Membership::ADD_REJECTED; return Membership::ADD_REJECTED;
Mutex::Lock _l(_lock); Mutex::Lock _l(_memberships_l);
return _memberships[coo.issuedTo()].addCredential(RR,tPtr,_config,coo); return _memberships[coo.issuedTo()].addCredential(RR,tPtr,_config,coo);
} }
@ -424,7 +418,7 @@ public:
*/ */
inline void pushCredentialsNow(void *tPtr,const Address &to,const int64_t now) inline void pushCredentialsNow(void *tPtr,const Address &to,const int64_t now)
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_memberships_l);
_memberships[to].pushCredentials(RR,tPtr,now,to,_config); _memberships[to].pushCredentials(RR,tPtr,now,to,_config);
} }
@ -437,9 +431,10 @@ public:
*/ */
inline void pushCredentialsIfNeeded(void *tPtr,const Address &to,const int64_t now) inline void pushCredentialsIfNeeded(void *tPtr,const Address &to,const int64_t now)
{ {
Mutex::Lock _l(_lock); const int64_t tout = std::min(_config.credentialTimeMaxDelta,(int64_t)ZT_PEER_ACTIVITY_TIMEOUT);
Mutex::Lock _l(_memberships_l);
Membership &m = _memberships[to]; Membership &m = _memberships[to];
if (m.shouldPushCredentials(now)) if (((now - m.lastPushedCredentials()) + 5000) >= tout)
m.pushCredentials(RR,tPtr,now,to,_config); m.pushCredentials(RR,tPtr,now,to,_config);
} }
@ -449,7 +444,14 @@ public:
* This sets the network to completely remove itself on delete. This also prevents the * This sets the network to completely remove itself on delete. This also prevents the
* call of the normal port shutdown event on delete. * call of the normal port shutdown event on delete.
*/ */
void destroy(); inline void destroy()
{
_memberships_l.lock();
_config_l.lock();
_destroyed = true;
_config_l.unlock();
_memberships_l.unlock();
}
/** /**
* Get this network's config for export via the ZT core API * Get this network's config for export via the ZT core API
@ -458,7 +460,7 @@ public:
*/ */
inline void externalConfig(ZT_VirtualNetworkConfig *ec) const inline void externalConfig(ZT_VirtualNetworkConfig *ec) const
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_config_l);
_externalConfig(ec); _externalConfig(ec);
} }
@ -471,7 +473,7 @@ private:
ZT_VirtualNetworkStatus _status() const; ZT_VirtualNetworkStatus _status() const;
void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked
bool _gate(const SharedPtr<Peer> &peer); bool _gate(const SharedPtr<Peer> &peer);
void _sendUpdatesToMembers(void *tPtr); void _announceMulticastGroups(void *tPtr);
void _announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups); void _announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups);
std::vector<MulticastGroup> _allMulticastGroups() const; std::vector<MulticastGroup> _allMulticastGroups() const;
@ -501,9 +503,9 @@ private:
}; };
_IncomingConfigChunk _incomingConfigChunks[ZT_NETWORK_MAX_INCOMING_UPDATES]; _IncomingConfigChunk _incomingConfigChunks[ZT_NETWORK_MAX_INCOMING_UPDATES];
bool _destroyed; volatile bool _destroyed;
enum { volatile enum {
NETCONF_FAILURE_NONE, NETCONF_FAILURE_NONE,
NETCONF_FAILURE_ACCESS_DENIED, NETCONF_FAILURE_ACCESS_DENIED,
NETCONF_FAILURE_NOT_FOUND, NETCONF_FAILURE_NOT_FOUND,
@ -513,7 +515,11 @@ private:
Hashtable<Address,Membership> _memberships; Hashtable<Address,Membership> _memberships;
Mutex _lock; Mutex _myMulticastGroups_l;
Mutex _multicastGroupsBehindMe_l;
Mutex _remoteBridgeRoutes_l;
Mutex _config_l;
Mutex _memberships_l;
AtomicCounter __refCount; AtomicCounter __refCount;
}; };

View file

@ -914,9 +914,8 @@ public:
* <[2] 16-bit number of peers> * <[2] 16-bit number of peers>
* <[16] 128-bit hash of node public key> * <[16] 128-bit hash of node public key>
* <[2] 16-bit latency to node or 0 if unspecified> * <[2] 16-bit latency to node or 0 if unspecified>
* <[1] 8-bit number of network hops to node or 0 if unspecified>
* <[4] 32-bit max bandwidth in megabits or 0 if unspecified> * <[4] 32-bit max bandwidth in megabits or 0 if unspecified>
* [<[...] additional hash,latency,hops,bandwidth tuples>] * [<[...] additional hash,latency,bandwidth tuples>]
* *
* This messages can be pushed to indicate that this peer is willing * This messages can be pushed to indicate that this peer is willing
* to relay traffic to other peers. It contains a list of 128-bit * to relay traffic to other peers. It contains a list of 128-bit