ZeroTier now has link quality measurement. We are not using this yet but decided to put it in to prep for future QoS support and SD-WAN stuff.

This commit is contained in:
Adam Ierymenko 2017-03-01 14:36:52 -08:00
parent 2bf9145ae6
commit 1d39be61b2
9 changed files with 111 additions and 22 deletions

View file

@ -21,6 +21,7 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdexcept>
#include <algorithm>
@ -30,6 +31,7 @@
#include "SharedPtr.hpp"
#include "AtomicCounter.hpp"
#include "NonCopyable.hpp"
#include "Utils.hpp"
/**
* Maximum return value of preferenceRank()
@ -105,22 +107,34 @@ public:
_lastOut(0),
_lastIn(0),
_lastTrustEstablishedPacketReceived(0),
_incomingLinkQualityFastLog(0xffffffffffffffffULL),
_incomingLinkQualitySlowLogPtr(0),
_incomingLinkQualitySlowLogCounter(-64), // discard first fast log
_incomingLinkQualityPreviousPacketCounter(0),
_outgoingPacketCounter(0),
_addr(),
_localAddress(),
_ipScope(InetAddress::IP_SCOPE_NONE)
{
for(int i=0;i<(int)sizeof(_incomingLinkQualitySlowLog);++i)
_incomingLinkQualitySlowLog[i] = ZT_PATH_LINK_QUALITY_MAX;
}
Path(const InetAddress &localAddress,const InetAddress &addr) :
_lastOut(0),
_lastIn(0),
_lastTrustEstablishedPacketReceived(0),
_incomingLinkQualityFastLog(0xffffffffffffffffULL),
_incomingLinkQualitySlowLogPtr(0),
_incomingLinkQualitySlowLogCounter(-64), // discard first fast log
_incomingLinkQualityPreviousPacketCounter(0),
_outgoingPacketCounter(0),
_addr(addr),
_localAddress(localAddress),
_ipScope(addr.ipScope())
{
for(int i=0;i<(int)sizeof(_incomingLinkQualitySlowLog);++i)
_incomingLinkQualitySlowLog[i] = ZT_PATH_LINK_QUALITY_MAX;
}
/**
@ -130,6 +144,39 @@ public:
*/
inline void received(const uint64_t t) { _lastIn = t; }
/**
* Update link quality using a counter from an incoming packet (or packet head in fragmented case)
*
* @param counter Packet link quality counter (range 0 to 7, must not have other bits set)
*/
inline void updateLinkQuality(const unsigned int counter)
{
const unsigned int prev = _incomingLinkQualityPreviousPacketCounter;
_incomingLinkQualityPreviousPacketCounter = counter;
const uint64_t fl = (_incomingLinkQualityFastLog = ((_incomingLinkQualityFastLog << 1) | (uint64_t)(prev == ((counter - 1) & 0x7))));
if (++_incomingLinkQualitySlowLogCounter >= 64) {
_incomingLinkQualitySlowLogCounter = 0;
_incomingLinkQualitySlowLog[_incomingLinkQualitySlowLogPtr++ % sizeof(_incomingLinkQualitySlowLog)] = Utils::countBits(fl);
}
}
/**
* @return Link quality from 0 (min) to 255 (max)
*/
inline unsigned int linkQuality() const
{
unsigned long slsize = _incomingLinkQualitySlowLogPtr;
if (slsize > (unsigned long)sizeof(_incomingLinkQualitySlowLog))
slsize = (unsigned long)sizeof(_incomingLinkQualitySlowLog);
else if (!slsize)
return 255; // ZT_PATH_LINK_QUALITY_MAX
unsigned long lq = 0;
for(unsigned long i=0;i<slsize;++i)
lq += (unsigned long)_incomingLinkQualitySlowLog[i] * 4;
lq /= slsize;
return (unsigned int)((lq >= 255) ? 255 : lq);
}
/**
* Set time last trusted packet was received (done in Peer::received())
*/
@ -251,13 +298,18 @@ public:
inline unsigned int nextOutgoingCounter() { return _outgoingPacketCounter++; }
private:
uint64_t _lastOut;
uint64_t _lastIn;
uint64_t _lastTrustEstablishedPacketReceived;
unsigned int _outgoingPacketCounter;
volatile uint64_t _lastOut;
volatile uint64_t _lastIn;
volatile uint64_t _lastTrustEstablishedPacketReceived;
volatile uint64_t _incomingLinkQualityFastLog;
volatile unsigned long _incomingLinkQualitySlowLogPtr;
volatile signed int _incomingLinkQualitySlowLogCounter;
volatile unsigned int _incomingLinkQualityPreviousPacketCounter;
volatile unsigned int _outgoingPacketCounter;
InetAddress _addr;
InetAddress _localAddress;
InetAddress::IpScope _ipScope; // memoize this since it's a computed value checked often
volatile uint8_t _incomingLinkQualitySlowLog[32];
AtomicCounter __refCount;
};