From eebd271bb1e3ab0d25f48db07a1a3f1154215bc7 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 30 Jan 2017 15:40:22 -0800 Subject: Implement cross cluster sharing of network configs to make clusters able to actually join networks. --- node/Cluster.cpp | 19 +++++++++++++++++++ node/Cluster.hpp | 15 +++++++++++---- node/IncomingPacket.cpp | 9 ++++++++- 3 files changed, 38 insertions(+), 5 deletions(-) (limited to 'node') diff --git a/node/Cluster.cpp b/node/Cluster.cpp index 2a261e51..55503f63 100644 --- a/node/Cluster.cpp +++ b/node/Cluster.cpp @@ -44,6 +44,7 @@ #include "Packet.hpp" #include "Switch.hpp" #include "Node.hpp" +#include "Network.hpp" #include "Array.hpp" namespace ZeroTier { @@ -469,6 +470,15 @@ void Cluster::handleIncomingStateMessage(const void *msg,unsigned int len) RR->sw->send(outp,true); //TRACE("[%u] proxy send %s to %s length %u",(unsigned int)fromMemberId,Packet::verbString(verb),rcpt.toString().c_str(),len); } break; + + case CLUSTER_MESSAGE_NETWORK_CONFIG: { + const SharedPtr network(RR->node->network(dmsg.at(ptr))); + if (network) { + // Copy into a Packet just to conform to Network API. Eventually + // will want to refactor. + network->handleConfigChunk(Packet(dmsg),ptr); + } + } break; } } catch ( ... ) { TRACE("invalid message of size %u type %d (inner decode), discarding",mlen,mtype); @@ -494,6 +504,15 @@ void Cluster::broadcastHavePeer(const Identity &id) } } +void Cluster::broadcastNetworkConfigChunk(const void *chunk,unsigned int len) +{ + Mutex::Lock _l(_memberIds_m); + for(std::vector::const_iterator mid(_memberIds.begin());mid!=_memberIds.end();++mid) { + Mutex::Lock _l2(_members[*mid].lock); + _send(*mid,CLUSTER_MESSAGE_NETWORK_CONFIG,chunk,len); + } +} + void Cluster::sendViaCluster(const Address &fromPeerAddress,const Address &toPeerAddress,const void *data,unsigned int len,bool unite) { if (len > ZT_PROTO_MAX_PACKET_LENGTH) // sanity check diff --git a/node/Cluster.hpp b/node/Cluster.hpp index dafbf425..aba3b8a9 100644 --- a/node/Cluster.hpp +++ b/node/Cluster.hpp @@ -216,14 +216,13 @@ public: /** * Replicate a network config for a network we belong to: - * <[8] 64-bit network ID> - * <[2] 16-bit length of network config> - * <[...] serialized network config> + * <[...] network config chunk> * * This is used by clusters to avoid every member having to query * for the same netconf for networks all members belong to. * - * TODO: not implemented yet! + * The first field of a network config chunk is the network ID, + * so this can be checked to look up the network on receipt. */ CLUSTER_MESSAGE_NETWORK_CONFIG = 7 }; @@ -267,6 +266,14 @@ public: */ void broadcastHavePeer(const Identity &id); + /** + * Broadcast a network config chunk to other members of cluster + * + * @param chunk Chunk data + * @param len Length of chunk + */ + void broadcastNetworkConfigChunk(const void *chunk,unsigned int len); + /** * Send this packet via another node in this cluster if another node has this peer * diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index a3fbbefc..e703af59 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -461,8 +461,12 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p case Packet::VERB_NETWORK_CONFIG_REQUEST: { const SharedPtr network(RR->node->network(at(ZT_PROTO_VERB_OK_IDX_PAYLOAD))); - if (network) + if (network) { +#ifdef ZT_ENABLE_CLUSTER + RR->cluster->broadcastNetworkConfigChunk(field(ZT_PACKET_IDX_PAYLOAD,size() - ZT_PROTO_VERB_OK_IDX_PAYLOAD),size() - ZT_PROTO_VERB_OK_IDX_PAYLOAD); +#endif network->handleConfigChunk(*this,ZT_PROTO_VERB_OK_IDX_PAYLOAD); + } } break; case Packet::VERB_MULTICAST_GATHER: { @@ -922,6 +926,9 @@ bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,const Shared try { const SharedPtr network(RR->node->network(at(ZT_PACKET_IDX_PAYLOAD))); if (network) { +#ifdef ZT_ENABLE_CLUSTER + RR->cluster->broadcastNetworkConfigChunk(field(ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD),size() - ZT_PACKET_IDX_PAYLOAD); +#endif const uint64_t configUpdateId = network->handleConfigChunk(*this,ZT_PACKET_IDX_PAYLOAD); if (configUpdateId) { Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK); -- cgit v1.2.3