Some work on congestion avoidance now uses a sliding congestion window instead of a static one

This commit is contained in:
KimLS 2017-06-29 14:13:55 -07:00
parent d6ac686a54
commit 5c6f684808
2 changed files with 68 additions and 21 deletions

View File

@ -283,6 +283,9 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
m_combined[0] = 0; m_combined[0] = 0;
m_combined[1] = OP_Combined; m_combined[1] = OP_Combined;
m_last_session_stats = Clock::now(); m_last_session_stats = Clock::now();
m_outstanding_bytes = 0;
m_cwnd = m_max_packet_size;
m_ssthresh = m_owner->m_options.max_outstanding_bytes;
} }
//new connection made as client //new connection made as client
@ -306,6 +309,9 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
m_combined[0] = 0; m_combined[0] = 0;
m_combined[1] = OP_Combined; m_combined[1] = OP_Combined;
m_last_session_stats = Clock::now(); m_last_session_stats = Clock::now();
m_outstanding_bytes = 0;
m_cwnd = m_max_packet_size;
m_ssthresh = m_owner->m_options.max_outstanding_bytes;
} }
EQ::Net::DaybreakConnection::~DaybreakConnection() EQ::Net::DaybreakConnection::~DaybreakConnection()
@ -463,20 +469,16 @@ void EQ::Net::DaybreakConnection::ProcessOutboundQueue()
{ {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
auto stream = &m_streams[i]; auto stream = &m_streams[i];
if (stream->outstanding_bytes == 0) {
continue;
}
while (!stream->buffered_packets.empty()) { while (!stream->buffered_packets.empty()) {
auto &buff = stream->buffered_packets.front(); auto &buff = stream->buffered_packets.front();
if (stream->outstanding_bytes + buff.sent.packet.Length() >= m_owner->m_options.max_outstanding_bytes || if (m_outstanding_bytes + buff.sent.packet.Length() >= m_cwnd) {
stream->outstanding_packets.size() + 1 >= m_owner->m_options.max_outstanding_packets) {
break; break;
} }
stream->outstanding_bytes += buff.sent.packet.Length(); LogF(Logs::Detail, Logs::Netcode, "Sending buffered packet {0} on stream {1}", buff.seq, i);
m_outstanding_bytes += buff.sent.packet.Length();
stream->outstanding_packets.insert(std::make_pair(buff.seq, buff.sent)); stream->outstanding_packets.insert(std::make_pair(buff.seq, buff.sent));
InternalSend(buff.sent.packet); InternalSend(buff.sent.packet);
stream->buffered_packets.pop_front(); stream->buffered_packets.pop_front();
@ -1051,7 +1053,10 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
InternalBufferedSend(entry.second.packet); InternalBufferedSend(entry.second.packet);
entry.second.last_sent = now; entry.second.last_sent = now;
entry.second.times_resent++; entry.second.times_resent++;
m_rolling_ping += 100;
LogF(Logs::Detail, Logs::Netcode, "Congestion detected, reducing window size");
m_ssthresh = m_cwnd / 2;
m_cwnd = m_cwnd / 2;
} }
} }
else { else {
@ -1065,7 +1070,10 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
InternalBufferedSend(entry.second.packet); InternalBufferedSend(entry.second.packet);
entry.second.last_sent = now; entry.second.last_sent = now;
entry.second.times_resent++; entry.second.times_resent++;
m_rolling_ping += 100;
LogF(Logs::Detail, Logs::Netcode, "Congestion detected, reducing window size");
m_ssthresh = m_cwnd / 2;
m_cwnd = m_cwnd / 2;
} }
} }
} }
@ -1086,10 +1094,29 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq)
m_stats.max_ping = std::max(m_stats.max_ping, round_time); m_stats.max_ping = std::max(m_stats.max_ping, round_time);
m_stats.min_ping = std::min(m_stats.min_ping, round_time); m_stats.min_ping = std::min(m_stats.min_ping, round_time);
m_stats.last_ping = round_time; m_stats.last_ping = round_time;
m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; m_rolling_ping = (m_rolling_ping * 4 + round_time) / 5;
s->outstanding_bytes -= iter->second.packet.Length(); m_outstanding_bytes -= iter->second.packet.Length();
iter = s->outstanding_packets.erase(iter); iter = s->outstanding_packets.erase(iter);
if (m_cwnd < m_ssthresh) {
//Still in slow start mode
m_cwnd *= 2;
if (m_cwnd > m_owner->m_options.max_outstanding_bytes) {
m_cwnd = m_owner->m_options.max_outstanding_bytes;
}
LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd);
}
else {
m_cwnd += m_max_packet_size;
if (m_cwnd > m_owner->m_options.max_outstanding_bytes) {
m_cwnd = m_owner->m_options.max_outstanding_bytes;
}
LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd);
}
ProcessOutboundQueue(); ProcessOutboundQueue();
} }
else { else {
@ -1111,8 +1138,28 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq)
m_stats.last_ping = round_time; m_stats.last_ping = round_time;
m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3;
s->outstanding_bytes -= iter->second.packet.Length(); m_outstanding_bytes -= iter->second.packet.Length();
s->outstanding_packets.erase(iter); s->outstanding_packets.erase(iter);
if (m_cwnd < m_ssthresh) {
//Still in slow start mode
m_cwnd *= 2;
if (m_cwnd > m_owner->m_options.max_outstanding_bytes) {
m_cwnd = m_owner->m_options.max_outstanding_bytes;
}
LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd);
}
else {
m_cwnd += m_max_packet_size;
if (m_cwnd > m_owner->m_options.max_outstanding_bytes) {
m_cwnd = m_owner->m_options.max_outstanding_bytes;
}
LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd);
}
ProcessOutboundQueue(); ProcessOutboundQueue();
} }
} }
@ -1122,16 +1169,17 @@ void EQ::Net::DaybreakConnection::BufferPacket(int stream, uint16_t seq, Daybrea
auto s = &m_streams[stream]; auto s = &m_streams[stream];
//If we can send the packet then send it //If we can send the packet then send it
//else buffer it to be sent when we can send it //else buffer it to be sent when we can send it
if (s->outstanding_bytes + sent.packet.Length() >= m_owner->m_options.max_outstanding_bytes || s->outstanding_packets.size() + 1 >= m_owner->m_options.max_outstanding_packets) { if (m_outstanding_bytes + sent.packet.Length() > m_cwnd) {
//Would go over one of the limits, buffer this packet. //Would go over one of the limits, buffer this packet.
DaybreakBufferedPacket bp; DaybreakBufferedPacket bp;
bp.sent = std::move(sent); bp.sent = std::move(sent);
bp.seq = seq; bp.seq = seq;
s->buffered_packets.push_back(bp); s->buffered_packets.push_back(bp);
LogF(Logs::Detail, Logs::Netcode, "Buffering packet {0} on stream {1}", seq, stream);
return; return;
} }
s->outstanding_bytes += sent.packet.Length(); m_outstanding_bytes += sent.packet.Length();
s->outstanding_packets.insert(std::make_pair(seq, sent)); s->outstanding_packets.insert(std::make_pair(seq, sent));
InternalSend(sent.packet); InternalSend(sent.packet);
} }
@ -1438,4 +1486,4 @@ EQ::Net::SequenceOrder EQ::Net::DaybreakConnection::CompareSequence(uint16_t exp
} }
return SequencePast; return SequencePast;
} }

View File

@ -136,7 +136,10 @@ namespace EQ
size_t m_resend_delay; size_t m_resend_delay;
size_t m_rolling_ping; size_t m_rolling_ping;
Timestamp m_close_time; Timestamp m_close_time;
size_t m_outstanding_bytes;
size_t m_cwnd;
size_t m_ssthresh;
struct DaybreakSentPacket struct DaybreakSentPacket
{ {
DynamicPacket packet; DynamicPacket packet;
@ -158,7 +161,6 @@ namespace EQ
sequence_out = 0; sequence_out = 0;
fragment_current_bytes = 0; fragment_current_bytes = 0;
fragment_total_bytes = 0; fragment_total_bytes = 0;
outstanding_bytes = 0;
} }
uint16_t sequence_in; uint16_t sequence_in;
@ -171,7 +173,6 @@ namespace EQ
uint32_t fragment_total_bytes; uint32_t fragment_total_bytes;
std::unordered_map<uint16_t, DaybreakSentPacket> outstanding_packets; std::unordered_map<uint16_t, DaybreakSentPacket> outstanding_packets;
size_t outstanding_bytes;
}; };
DaybreakStream m_streams[4]; DaybreakStream m_streams[4];
@ -236,8 +237,7 @@ namespace EQ
tic_rate_hertz = 60.0; tic_rate_hertz = 60.0;
resend_timeout = 90000; resend_timeout = 90000;
connection_close_time = 2000; connection_close_time = 2000;
max_outstanding_packets = 300; max_outstanding_bytes = 65535;
max_outstanding_bytes = 200 * 512;
} }
size_t max_packet_size; size_t max_packet_size;
@ -260,7 +260,6 @@ namespace EQ
size_t connection_close_time; size_t connection_close_time;
DaybreakEncodeType encode_passes[2]; DaybreakEncodeType encode_passes[2];
int port; int port;
size_t max_outstanding_packets;
size_t max_outstanding_bytes; size_t max_outstanding_bytes;
}; };