Fix for ab-mode link failure, QoS metrics (WIP)

This commit is contained in:
Joseph Henry 2022-06-08 10:01:54 -07:00
parent 75652ce667
commit 7ed5bde426
No known key found for this signature in database
GPG key ID: C45B33FF5EBC9344
5 changed files with 177 additions and 16 deletions

View file

@ -638,6 +638,15 @@ class Bond {
*/
void receivedQoS(const SharedPtr<Path>& path, int64_t now, int count, uint64_t* rx_id, uint16_t* rx_ts);
/**
* Process the contents of an inbound VERB_ACK to gather path quality observations.
*
* @param pathIdx Path over which packet was received
* @param now Current time
* @param ackedBytes Number of bytes ACKed by this VERB_ACK
*/
void receivedAck(int pathIdx, int64_t now, int32_t ackedBytes);
/**
* Generate the contents of a VERB_QOS_MEASUREMENT packet.
*
@ -879,6 +888,26 @@ class Bond {
*/
void processBackgroundBondTasks(void* tPtr, int64_t now);
/**
* Rate limit gate for VERB_ACK
*
* @param now Current time
* @return Whether the incoming packet should be rate-gated
*/
inline bool rateGateACK(const int64_t now)
{
_ackCutoffCount++;
int numToDrain = _lastAckRateCheck ? (now - _lastAckRateCheck) / ZT_ACK_DRAINAGE_DIVISOR : _ackCutoffCount;
_lastAckRateCheck = now;
if (_ackCutoffCount > numToDrain) {
_ackCutoffCount -= numToDrain;
}
else {
_ackCutoffCount = 0;
}
return (_ackCutoffCount < ZT_ACK_CUTOFF_LIMIT);
}
/**
* Rate limit gate for VERB_QOS_MEASUREMENT
*
@ -1204,7 +1233,11 @@ class Bond {
private:
struct NominatedPath {
NominatedPath()
: lastQoSMeasurement(0)
: lastAckSent(0)
, lastAckReceived(0)
, unackedBytes(0)
, packetsReceivedSinceLastAck(0)
, lastQoSMeasurement(0)
, lastThroughputEstimation(0)
, lastRefractoryUpdate(0)
, lastAliveToggle(0)
@ -1295,6 +1328,15 @@ class Bond {
return ((packetsReceivedSinceLastQoS >= ZT_QOS_TABLE_SIZE) || ((now - lastQoSMeasurement) > qosSendInterval)) && packetsReceivedSinceLastQoS;
}
/**
* @param now Current time
* @return Whether an ACK (VERB_ACK) packet needs to be emitted at this time
*/
inline bool needsToSendAck(int64_t now, int ackSendInterval)
{
return ((now - lastAckSent) >= ackSendInterval || (packetsReceivedSinceLastAck == ZT_QOS_TABLE_SIZE)) && packetsReceivedSinceLastAck;
}
/**
* Reset packet counters
*/
@ -1306,6 +1348,7 @@ class Bond {
std::map<uint64_t, uint64_t> qosStatsOut; // id:egress_time
std::map<uint64_t, uint64_t> qosStatsIn; // id:now
std::map<uint64_t, uint64_t> ackStatsIn; // id:now
RingBuffer<int, ZT_QOS_SHORTTERM_SAMPLE_WIN_SIZE> qosRecordSize;
RingBuffer<float, ZT_QOS_SHORTTERM_SAMPLE_WIN_SIZE> qosRecordLossSamples;
@ -1314,6 +1357,11 @@ class Bond {
RingBuffer<float, ZT_QOS_SHORTTERM_SAMPLE_WIN_SIZE> throughputVarianceSamples;
RingBuffer<uint16_t, ZT_QOS_SHORTTERM_SAMPLE_WIN_SIZE> latencySamples;
uint64_t lastAckSent;
uint64_t lastAckReceived;
uint64_t unackedBytes;
uint64_t packetsReceivedSinceLastAck;
uint64_t lastQoSMeasurement; // Last time that a VERB_QOS_MEASUREMENT was sent out on this path.
uint64_t lastThroughputEstimation; // Last time that the path's throughput was estimated.
uint64_t lastRefractoryUpdate; // The last time that the refractory period was updated.
@ -1513,7 +1561,9 @@ class Bond {
* Rate-limiting
*/
uint16_t _qosCutoffCount;
uint16_t _ackCutoffCount;
uint64_t _lastQoSRateCheck;
uint64_t _lastAckRateCheck;
uint16_t _pathNegotiationCutoffCount;
uint64_t _lastPathNegotiationReceived;