mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 12:53:03 +02:00
update the flow window size for the send queue
This commit is contained in:
parent
55555cf13e
commit
4907418587
3 changed files with 63 additions and 44 deletions
|
@ -368,10 +368,15 @@ void Connection::processACK(std::unique_ptr<ControlPacket> controlPacket) {
|
||||||
_congestionControl->setBandwidth(_bandwidth);
|
_congestionControl->setBandwidth(_bandwidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fire the onACK callback for congestion control
|
// update the last sent sequence number in congestion control
|
||||||
_congestionControl->setSendCurrentSequenceNumber(_sendQueue->getCurrentSequenceNumber());
|
_congestionControl->setSendCurrentSequenceNumber(_sendQueue->getCurrentSequenceNumber());
|
||||||
|
|
||||||
|
// fire the onACK callback for congestion control
|
||||||
_congestionControl->onAck(ack);
|
_congestionControl->onAck(ack);
|
||||||
|
|
||||||
|
// now that we've updated the congestion control, update the packet send period and flow window size
|
||||||
_sendQueue->setPacketSendPeriod(_congestionControl->_packetSendPeriod);
|
_sendQueue->setPacketSendPeriod(_congestionControl->_packetSendPeriod);
|
||||||
|
_sendQueue->setFlowWindowSize(std::min(_flowWindowSize, (int) _congestionControl->_congestionWindowSize));
|
||||||
|
|
||||||
// update the total count of received ACKs
|
// update the total count of received ACKs
|
||||||
++_totalReceivedACKs;
|
++_totalReceivedACKs;
|
||||||
|
@ -437,10 +442,15 @@ void Connection::processNAK(std::unique_ptr<ControlPacket> controlPacket) {
|
||||||
// send that off to the send queue so it knows there was loss
|
// send that off to the send queue so it knows there was loss
|
||||||
_sendQueue->nak(start, end);
|
_sendQueue->nak(start, end);
|
||||||
|
|
||||||
// Tell the congestion control object that there was loss
|
// update the last sent sequence number in congestion control
|
||||||
_congestionControl->setSendCurrentSequenceNumber(_sendQueue->getCurrentSequenceNumber());
|
_congestionControl->setSendCurrentSequenceNumber(_sendQueue->getCurrentSequenceNumber());
|
||||||
|
|
||||||
|
// give the loss to the congestion control object
|
||||||
_congestionControl->onLoss(start, end);
|
_congestionControl->onLoss(start, end);
|
||||||
|
|
||||||
|
// now that we've updated the congestion control, update the packet send period and flow window size
|
||||||
_sendQueue->setPacketSendPeriod(_congestionControl->_packetSendPeriod);
|
_sendQueue->setPacketSendPeriod(_congestionControl->_packetSendPeriod);
|
||||||
|
_sendQueue->setFlowWindowSize(std::min(_flowWindowSize, (int) _congestionControl->_congestionWindowSize));
|
||||||
|
|
||||||
++_totalReceivedNAKs;
|
++_totalReceivedNAKs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,13 +80,13 @@ void SendQueue::sendPacket(const BasePacket& packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendQueue::ack(SequenceNumber ack) {
|
void SendQueue::ack(SequenceNumber ack) {
|
||||||
if (_lastAck == ack) {
|
if (_lastACKSequenceNumber == (uint32_t) ack) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // remove any ACKed packets from the map of sent packets
|
{ // remove any ACKed packets from the map of sent packets
|
||||||
QWriteLocker locker(&_sentLock);
|
QWriteLocker locker(&_sentLock);
|
||||||
for (auto seq = _lastAck; seq <= ack; ++seq) {
|
for (auto seq = SequenceNumber { (uint32_t) _lastACKSequenceNumber }; seq <= ack; ++seq) {
|
||||||
_sentPackets.erase(seq);
|
_sentPackets.erase(seq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ void SendQueue::ack(SequenceNumber ack) {
|
||||||
_naks.remove(_naks.getFirstSequenceNumber(), ack);
|
_naks.remove(_naks.getFirstSequenceNumber(), ack);
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastAck = ack;
|
_lastACKSequenceNumber = (uint32_t) ack;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendQueue::nak(SequenceNumber start, SequenceNumber end) {
|
void SendQueue::nak(SequenceNumber start, SequenceNumber end) {
|
||||||
|
@ -131,49 +131,53 @@ void SendQueue::loop() {
|
||||||
// Record timing
|
// Record timing
|
||||||
_lastSendTimestamp = high_resolution_clock::now();
|
_lastSendTimestamp = high_resolution_clock::now();
|
||||||
|
|
||||||
if (_nextPacket) {
|
// we're only allowed to send if the flow window size
|
||||||
|
// is greater than or equal to the gap between the last ACKed sent and the one we are about to send
|
||||||
|
if (seqlen(SequenceNumber { (uint32_t) _lastACKSequenceNumber }, _currentSequenceNumber + 1) <= _flowWindowSize) {
|
||||||
|
bool hasResend = false;
|
||||||
|
SequenceNumber seqNum;
|
||||||
|
{
|
||||||
|
// Check nak list for packet to resend
|
||||||
|
QWriteLocker locker(&_naksLock);
|
||||||
|
if (_naks.getLength() > 0) {
|
||||||
|
hasResend = true;
|
||||||
|
seqNum = _naks.popFirstSequenceNumber();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Packet> nextPacket;
|
||||||
|
|
||||||
|
// Find packet in sent list using SequenceNumber
|
||||||
|
if (hasResend) {
|
||||||
|
QWriteLocker locker(&_sentLock);
|
||||||
|
auto it = _sentPackets.find(seqNum);
|
||||||
|
Q_ASSERT_X(it != _sentPackets.end(),
|
||||||
|
"SendQueue::sendNextPacket()", "Couldn't find NAKed packet to resend");
|
||||||
|
|
||||||
|
if (it != _sentPackets.end()) {
|
||||||
|
it->second.swap(nextPacket);
|
||||||
|
_sentPackets.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no packet to resend, grab the next one in the list
|
||||||
|
if (!nextPacket) {
|
||||||
|
QWriteLocker locker(&_packetsLock);
|
||||||
|
nextPacket.swap(_packets.front());
|
||||||
|
_packets.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
// Write packet's sequence number and send it off
|
// Write packet's sequence number and send it off
|
||||||
_nextPacket->writeSequenceNumber(getNextSequenceNumber());
|
nextPacket->writeSequenceNumber(getNextSequenceNumber());
|
||||||
sendPacket(*_nextPacket);
|
sendPacket(*nextPacket);
|
||||||
|
|
||||||
// Insert the packet we have just sent in the sent list
|
// Insert the packet we have just sent in the sent list
|
||||||
QWriteLocker locker(&_sentLock);
|
QWriteLocker locker(&_sentLock);
|
||||||
_sentPackets[_nextPacket->getSequenceNumber()].swap(_nextPacket);
|
_sentPackets[nextPacket->getSequenceNumber()].swap(nextPacket);
|
||||||
Q_ASSERT_X(!_nextPacket,
|
Q_ASSERT_X(!nextPacket,
|
||||||
"SendQueue::sendNextPacket()", "Overriden packet in sent list");
|
"SendQueue::sendNextPacket()", "Overriden packet in sent list");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasResend = false;
|
|
||||||
SequenceNumber seqNum;
|
|
||||||
{
|
|
||||||
// Check nak list for packet to resend
|
|
||||||
QWriteLocker locker(&_naksLock);
|
|
||||||
if (_naks.getLength() > 0) {
|
|
||||||
hasResend = true;
|
|
||||||
seqNum = _naks.popFirstSequenceNumber();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find packet in sent list using SequenceNumber
|
|
||||||
if (hasResend) {
|
|
||||||
QWriteLocker locker(&_sentLock);
|
|
||||||
auto it = _sentPackets.find(seqNum);
|
|
||||||
Q_ASSERT_X(it != _sentPackets.end(),
|
|
||||||
"SendQueue::sendNextPacket()", "Couldn't find NAKed packet to resend");
|
|
||||||
|
|
||||||
if (it != _sentPackets.end()) {
|
|
||||||
it->second.swap(_nextPacket);
|
|
||||||
_sentPackets.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is no packet to resend, grab the next one in the list
|
|
||||||
if (!_nextPacket) {
|
|
||||||
QWriteLocker locker(&_packetsLock);
|
|
||||||
_nextPacket.swap(_packets.front());
|
|
||||||
_packets.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
// since we're a while loop, give the thread a chance to process events
|
// since we're a while loop, give the thread a chance to process events
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "../HifiSockAddr.h"
|
#include "../HifiSockAddr.h"
|
||||||
|
|
||||||
|
#include "Constants.h"
|
||||||
#include "SequenceNumber.h"
|
#include "SequenceNumber.h"
|
||||||
#include "LossList.h"
|
#include "LossList.h"
|
||||||
|
|
||||||
|
@ -45,6 +46,8 @@ public:
|
||||||
|
|
||||||
SequenceNumber getCurrentSequenceNumber() const { return SequenceNumber(_atomicCurrentSequenceNumber); }
|
SequenceNumber getCurrentSequenceNumber() const { return SequenceNumber(_atomicCurrentSequenceNumber); }
|
||||||
|
|
||||||
|
void setFlowWindowSize(int flowWindowSize) { _flowWindowSize = flowWindowSize; }
|
||||||
|
|
||||||
int getPacketSendPeriod() const { return _packetSendPeriod; }
|
int getPacketSendPeriod() const { return _packetSendPeriod; }
|
||||||
void setPacketSendPeriod(int newPeriod) { _packetSendPeriod = newPeriod; }
|
void setPacketSendPeriod(int newPeriod) { _packetSendPeriod = newPeriod; }
|
||||||
|
|
||||||
|
@ -74,11 +77,11 @@ private:
|
||||||
|
|
||||||
mutable QReadWriteLock _packetsLock; // Protects the packets to be sent list.
|
mutable QReadWriteLock _packetsLock; // Protects the packets to be sent list.
|
||||||
std::list<std::unique_ptr<Packet>> _packets; // List of packets to be sent
|
std::list<std::unique_ptr<Packet>> _packets; // List of packets to be sent
|
||||||
std::unique_ptr<Packet> _nextPacket; // Next packet to be sent
|
|
||||||
|
|
||||||
Socket* _socket { nullptr }; // Socket to send packet on
|
Socket* _socket { nullptr }; // Socket to send packet on
|
||||||
HifiSockAddr _destination; // Destination addr
|
HifiSockAddr _destination; // Destination addr
|
||||||
SequenceNumber _lastAck; // Last ACKed sequence number
|
|
||||||
|
std::atomic<uint32_t> _lastACKSequenceNumber; // Last ACKed sequence number
|
||||||
|
|
||||||
SequenceNumber _currentSequenceNumber; // Last sequence number sent out
|
SequenceNumber _currentSequenceNumber; // Last sequence number sent out
|
||||||
std::atomic<uint32_t> _atomicCurrentSequenceNumber; // Atomic for last sequence number sent out
|
std::atomic<uint32_t> _atomicCurrentSequenceNumber; // Atomic for last sequence number sent out
|
||||||
|
@ -87,6 +90,8 @@ private:
|
||||||
std::chrono::high_resolution_clock::time_point _lastSendTimestamp; // Record last time of packet departure
|
std::chrono::high_resolution_clock::time_point _lastSendTimestamp; // Record last time of packet departure
|
||||||
std::atomic<bool> _isRunning { false };
|
std::atomic<bool> _isRunning { false };
|
||||||
|
|
||||||
|
std::atomic<int> _flowWindowSize { udt::MAX_PACKETS_IN_FLIGHT }; // Flow control window size (number of packets that can be on wire)
|
||||||
|
|
||||||
mutable QReadWriteLock _naksLock; // Protects the naks list.
|
mutable QReadWriteLock _naksLock; // Protects the naks list.
|
||||||
LossList _naks; // Sequence numbers of packets to resend
|
LossList _naks; // Sequence numbers of packets to resend
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue