mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-20 11:38:48 +00:00
Multicast propagation is now working from non-supernodes, and working quite well. Time for some more simulation before 0.5.0!
This commit is contained in:
parent
929ed5d8b8
commit
2cfa76fa8b
@ -25,6 +25,8 @@
|
|||||||
* LLC. Start here: http://www.zerotier.com/
|
* LLC. Start here: http://www.zerotier.com/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "Multicaster.hpp"
|
#include "Multicaster.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
|
@ -177,7 +177,7 @@ public:
|
|||||||
uint64_t aint = a.toInt() + _bloomNonce;
|
uint64_t aint = a.toInt() + _bloomNonce;
|
||||||
const unsigned int bit = (unsigned int)(aint ^ (aint >> 13) ^ (aint >> 26) ^ (aint >> 39)) & 0x1fff;
|
const unsigned int bit = (unsigned int)(aint ^ (aint >> 13) ^ (aint >> 26) ^ (aint >> 39)) & 0x1fff;
|
||||||
unsigned char *const bbyte = _bloom + (bit >> 3); // note: bloom filter size == 1024 is hard-coded here
|
unsigned char *const bbyte = _bloom + (bit >> 3); // note: bloom filter size == 1024 is hard-coded here
|
||||||
const unsigned char bmask = 0x80 >> (bit & 7);
|
const unsigned char bmask = 1 << (bit & 7);
|
||||||
if ((*bbyte & bmask))
|
if ((*bbyte & bmask))
|
||||||
return true;
|
return true;
|
||||||
else *bbyte |= bmask;
|
else *bbyte |= bmask;
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
* LLC. Start here: http://www.zerotier.com/
|
* LLC. Start here: http://www.zerotier.com/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
|
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
@ -463,23 +467,27 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These fields change
|
||||||
unsigned int depth = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH);
|
unsigned int depth = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH);
|
||||||
unsigned char *fifo = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_FIFO,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO);
|
unsigned char *const fifo = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_FIFO,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO);
|
||||||
unsigned char *bloom = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM);
|
unsigned char *const bloom = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM);
|
||||||
uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID);
|
|
||||||
uint16_t bloomNonce = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE);
|
|
||||||
unsigned int prefixBits = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS];
|
|
||||||
unsigned int prefix = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX];
|
|
||||||
uint64_t guid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GUID);
|
|
||||||
MAC sourceMac(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_SOURCE_MAC));
|
|
||||||
MulticastGroup dest(MAC(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_MAC)),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI));
|
|
||||||
unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE);
|
|
||||||
unsigned int frameLen = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME_LEN);
|
|
||||||
unsigned char *frame = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,frameLen);
|
|
||||||
unsigned int signatureLen = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen);
|
|
||||||
unsigned char *signature = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen + 2,signatureLen);
|
|
||||||
|
|
||||||
unsigned int signedPartLen = (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME - ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION) + frameLen;
|
// These fields don't -- they're signed by the original sender
|
||||||
|
// const unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS];
|
||||||
|
const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID);
|
||||||
|
const uint16_t bloomNonce = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE);
|
||||||
|
const unsigned int prefixBits = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS];
|
||||||
|
const unsigned int prefix = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX];
|
||||||
|
const uint64_t guid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GUID);
|
||||||
|
const MAC sourceMac(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_SOURCE_MAC));
|
||||||
|
const MulticastGroup dest(MAC(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_MAC)),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI));
|
||||||
|
const unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE);
|
||||||
|
const unsigned int frameLen = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME_LEN);
|
||||||
|
const unsigned char *const frame = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,frameLen);
|
||||||
|
const unsigned int signatureLen = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen);
|
||||||
|
const unsigned char *const signature = field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen + 2,signatureLen);
|
||||||
|
|
||||||
|
const unsigned int signedPartLen = (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME - ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION) + frameLen;
|
||||||
if (!originPeer->identity().verify(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION,signedPartLen),signedPartLen,signature,signatureLen)) {
|
if (!originPeer->identity().verify(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION,signedPartLen),signedPartLen,signature,signatureLen)) {
|
||||||
TRACE("dropped MULTICAST_FRAME from %s(%s): failed signature verification, claims to be from %s",source().toString().c_str(),_remoteAddress.toString().c_str(),origin.toString().c_str());
|
TRACE("dropped MULTICAST_FRAME from %s(%s): failed signature verification, claims to be from %s",source().toString().c_str(),_remoteAddress.toString().c_str(),origin.toString().c_str());
|
||||||
return true;
|
return true;
|
||||||
@ -491,6 +499,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
|
|||||||
_r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1);
|
_r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Security check to prohibit multicasts that are really Ethernet unicasts
|
||||||
if (!dest.mac().isMulticast()) {
|
if (!dest.mac().isMulticast()) {
|
||||||
TRACE("dropped MULTICAST_FRAME from %s(%s): %s is not a multicast/broadcast address",source().toString().c_str(),_remoteAddress.toString().c_str(),dest.mac().toString().c_str());
|
TRACE("dropped MULTICAST_FRAME from %s(%s): %s is not a multicast/broadcast address",source().toString().c_str(),_remoteAddress.toString().c_str(),dest.mac().toString().c_str());
|
||||||
return true;
|
return true;
|
||||||
@ -564,15 +573,20 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
|
|||||||
// New FIFO with room for one extra, since head will be next hop
|
// New FIFO with room for one extra, since head will be next hop
|
||||||
unsigned char newFifo[ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO + ZT_ADDRESS_LENGTH];
|
unsigned char newFifo[ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO + ZT_ADDRESS_LENGTH];
|
||||||
unsigned char *newFifoPtr = newFifo;
|
unsigned char *newFifoPtr = newFifo;
|
||||||
unsigned char *const newFifoEnd = newFifoPtr + sizeof(newFifo);
|
unsigned char *const newFifoEnd = newFifo + sizeof(newFifo);
|
||||||
for(unsigned int i=0;i<ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO;) {
|
|
||||||
unsigned int j = i;
|
// Copy old FIFO into new buffer, terminating at first NULL address
|
||||||
i += ZT_ADDRESS_LENGTH;
|
for(unsigned char *f=fifo,*const fifoEnd=(fifo + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO);f!=fifoEnd;) {
|
||||||
unsigned char zm = 0;
|
unsigned char *nf = newFifoPtr;
|
||||||
while (j != i)
|
unsigned char *e = nf + ZT_ADDRESS_LENGTH;
|
||||||
zm |= (*(newFifoPtr++) = fifo[j++]);
|
unsigned char *ftmp = f;
|
||||||
if (!zm) // stop at zero address
|
unsigned char zeroCheckMask = 0;
|
||||||
break;
|
while (nf != e)
|
||||||
|
zeroCheckMask |= (*(nf++) = *(ftmp++));
|
||||||
|
if (zeroCheckMask) {
|
||||||
|
f = ftmp;
|
||||||
|
newFifoPtr = nf;
|
||||||
|
} else break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add any next hops we know about to FIFO
|
// Add any next hops we know about to FIFO
|
||||||
|
@ -162,7 +162,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @return Last successfully sent firewall opener
|
* @return Last successfully sent firewall opener
|
||||||
*/
|
*/
|
||||||
uint64_t lastFirewallOpener() const
|
inline uint64_t lastFirewallOpener() const
|
||||||
throw()
|
throw()
|
||||||
{
|
{
|
||||||
return std::max(_ipv4p.lastFirewallOpener,_ipv6p.lastFirewallOpener);
|
return std::max(_ipv4p.lastFirewallOpener,_ipv6p.lastFirewallOpener);
|
||||||
@ -171,7 +171,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @return Time of last direct packet receive
|
* @return Time of last direct packet receive
|
||||||
*/
|
*/
|
||||||
uint64_t lastDirectReceive() const
|
inline uint64_t lastDirectReceive() const
|
||||||
throw()
|
throw()
|
||||||
{
|
{
|
||||||
return std::max(_ipv4p.lastReceive,_ipv6p.lastReceive);
|
return std::max(_ipv4p.lastReceive,_ipv6p.lastReceive);
|
||||||
@ -180,7 +180,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @return Time of last direct packet send
|
* @return Time of last direct packet send
|
||||||
*/
|
*/
|
||||||
uint64_t lastDirectSend() const
|
inline uint64_t lastDirectSend() const
|
||||||
throw()
|
throw()
|
||||||
{
|
{
|
||||||
return std::max(_ipv4p.lastSend,_ipv6p.lastSend);
|
return std::max(_ipv4p.lastSend,_ipv6p.lastSend);
|
||||||
@ -189,7 +189,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @return Time of most recent unicast frame received
|
* @return Time of most recent unicast frame received
|
||||||
*/
|
*/
|
||||||
uint64_t lastUnicastFrame() const
|
inline uint64_t lastUnicastFrame() const
|
||||||
throw()
|
throw()
|
||||||
{
|
{
|
||||||
return _lastUnicastFrame;
|
return _lastUnicastFrame;
|
||||||
@ -198,7 +198,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @return Time of most recent multicast frame received
|
* @return Time of most recent multicast frame received
|
||||||
*/
|
*/
|
||||||
uint64_t lastMulticastFrame() const
|
inline uint64_t lastMulticastFrame() const
|
||||||
throw()
|
throw()
|
||||||
{
|
{
|
||||||
return _lastMulticastFrame;
|
return _lastMulticastFrame;
|
||||||
@ -207,7 +207,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @return Time of most recent frame of any kind (unicast or multicast)
|
* @return Time of most recent frame of any kind (unicast or multicast)
|
||||||
*/
|
*/
|
||||||
uint64_t lastFrame() const
|
inline uint64_t lastFrame() const
|
||||||
throw()
|
throw()
|
||||||
{
|
{
|
||||||
return std::max(_lastUnicastFrame,_lastMulticastFrame);
|
return std::max(_lastUnicastFrame,_lastMulticastFrame);
|
||||||
@ -216,16 +216,28 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @return Time we last announced state TO this peer, such as multicast LIKEs
|
* @return Time we last announced state TO this peer, such as multicast LIKEs
|
||||||
*/
|
*/
|
||||||
uint64_t lastAnnouncedTo() const
|
inline uint64_t lastAnnouncedTo() const
|
||||||
throw()
|
throw()
|
||||||
{
|
{
|
||||||
return _lastAnnouncedTo;
|
return _lastAnnouncedTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the time of last announcement
|
||||||
|
*
|
||||||
|
* @param t Time, typically current
|
||||||
|
*/
|
||||||
|
inline void setLastAnnouncedTo(const uint64_t t)
|
||||||
|
throw()
|
||||||
|
{
|
||||||
|
_lastAnnouncedTo = t;
|
||||||
|
_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Lowest of measured latencies of all paths or 0 if unknown
|
* @return Lowest of measured latencies of all paths or 0 if unknown
|
||||||
*/
|
*/
|
||||||
unsigned int latency() const
|
inline unsigned int latency() const
|
||||||
throw()
|
throw()
|
||||||
{
|
{
|
||||||
if (_ipv4p.latency) {
|
if (_ipv4p.latency) {
|
||||||
@ -241,7 +253,7 @@ public:
|
|||||||
* @param addr Remote address
|
* @param addr Remote address
|
||||||
* @param latency Latency measurment
|
* @param latency Latency measurment
|
||||||
*/
|
*/
|
||||||
void setLatency(const InetAddress &addr,unsigned int latency)
|
inline void setLatency(const InetAddress &addr,unsigned int latency)
|
||||||
{
|
{
|
||||||
if (addr == _ipv4p.addr) {
|
if (addr == _ipv4p.addr) {
|
||||||
_ipv4p.latency = latency;
|
_ipv4p.latency = latency;
|
||||||
|
@ -107,27 +107,27 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
|||||||
mg = MulticastGroup::deriveMulticastGroupForAddressResolution(InetAddress(data.field(24,4),4,0));
|
mg = MulticastGroup::deriveMulticastGroupForAddressResolution(InetAddress(data.field(24,4),4,0));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int mcid = ++_multicastIdCounter & 0xffffff;
|
const unsigned int mcid = ++_multicastIdCounter & 0xffffff;
|
||||||
uint16_t bloomNonce = (uint16_t)_r->prng->next32(); // doesn't need to be cryptographically strong
|
const uint16_t bloomNonce = (uint16_t)(_r->prng->next32() & 0xffff); // doesn't need to be cryptographically strong
|
||||||
unsigned char bloom[ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM];
|
unsigned char bloom[ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM];
|
||||||
unsigned char fifo[ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO + ZT_ADDRESS_LENGTH];
|
unsigned char fifo[ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO + ZT_ADDRESS_LENGTH];
|
||||||
|
unsigned char *const fifoEnd = fifo + sizeof(fifo);
|
||||||
|
const unsigned int signedPartLen = (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME - ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION) + data.size();
|
||||||
|
const SharedPtr<Peer> supernode(_r->topology->getBestSupernode());
|
||||||
|
|
||||||
for(unsigned int prefix=0,np=((unsigned int)2 << (network->multicastPrefixBits() - 1));prefix<np;++prefix) {
|
for(unsigned int prefix=0,np=((unsigned int)2 << (network->multicastPrefixBits() - 1));prefix<np;++prefix) {
|
||||||
memset(bloom,0,sizeof(bloom));
|
memset(bloom,0,sizeof(bloom));
|
||||||
|
|
||||||
unsigned char *fifoPtr = fifo;
|
unsigned char *fifoPtr = fifo;
|
||||||
unsigned char *fifoEnd = fifo + sizeof(fifo);
|
|
||||||
|
|
||||||
_r->mc->getNextHops(network->id(),mg,Multicaster::AddToPropagationQueue(&fifoPtr,fifoEnd,bloom,bloomNonce,_r->identity.address(),network->multicastPrefixBits(),prefix));
|
_r->mc->getNextHops(network->id(),mg,Multicaster::AddToPropagationQueue(&fifoPtr,fifoEnd,bloom,bloomNonce,_r->identity.address(),network->multicastPrefixBits(),prefix));
|
||||||
while (fifoPtr != fifoEnd)
|
while (fifoPtr != fifoEnd)
|
||||||
*(fifoPtr++) = (unsigned char)0;
|
*(fifoPtr++) = (unsigned char)0;
|
||||||
|
|
||||||
Address firstHop(fifo,ZT_ADDRESS_LENGTH); // fifo is +1 in size, with first element being used here
|
Address firstHop(fifo,ZT_ADDRESS_LENGTH); // fifo is +1 in size, with first element being used here
|
||||||
if (!firstHop) {
|
if (!firstHop) {
|
||||||
SharedPtr<Peer> sn(_r->topology->getBestSupernode());
|
if (supernode)
|
||||||
if (sn)
|
firstHop = supernode->address();
|
||||||
firstHop = sn->address();
|
else continue;
|
||||||
else break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet outp(firstHop,_r->identity.address(),Packet::VERB_MULTICAST_FRAME);
|
Packet outp(firstHop,_r->identity.address(),Packet::VERB_MULTICAST_FRAME);
|
||||||
@ -150,7 +150,6 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
|||||||
outp.append((uint16_t)data.size());
|
outp.append((uint16_t)data.size());
|
||||||
outp.append(data);
|
outp.append(data);
|
||||||
|
|
||||||
unsigned int signedPartLen = (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME - ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION) + data.size();
|
|
||||||
C25519::Signature sig(_r->identity.sign(outp.field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION,signedPartLen),signedPartLen));
|
C25519::Signature sig(_r->identity.sign(outp.field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION,signedPartLen),signedPartLen));
|
||||||
outp.append((uint16_t)sig.size());
|
outp.append((uint16_t)sig.size());
|
||||||
outp.append(sig.data,sig.size());
|
outp.append(sig.data,sig.size());
|
||||||
|
Loading…
Reference in New Issue
Block a user