Skip to content

Instantly share code, notes, and snippets.

@fuji246
Created November 11, 2020 00:06
Show Gist options
  • Save fuji246/8e0f414ca0ebc2c767e2ba6bb9332fa7 to your computer and use it in GitHub Desktop.
Save fuji246/8e0f414ca0ebc2c767e2ba6bb9332fa7 to your computer and use it in GitHub Desktop.
copa congestion control

Copa Memos

[toc]

  1. It is delay-based congestion control, no react to packet loss.
  2. It is window based, not rate based congestion control.
  3. It relies on ACK feedback.
  4. It has mode switch to compete with buffer-filling flows like TCP.
  5. It uses smallest RTT in recent srtt/2 duration to filter noise (ACK compression, WiFi aggregation)
  6. Compared with Copa, NADA can achieve low delay and maintain at steady state as well, and it also has mode switch to compete with TCP, and it's more easiler to try NADA with current framework/protocols. However NADA may be sensative to noise in delay/loss, which need more investigation.

Target state

on each ACK arrives

From paper:

# steady state sending rate (lambda) in pakets per second
# delta = 0.5 and averge_queuing_delay is in seconds
# delta determines the weight delay compared to throughput.

# 200 ms queuing delay gives 0.2 * 0.5 = 0.1 => lambda = 10 pkts/sec = 1200 Bytes * 10 = 96000 bits/s = 9.6 kbps?
# 2 ms queueing delay gives 9.600 mbps, and 1 ms queueing delay gives 19.2 mbps

target_rate = lambda = 1 / (delta * averge_queuing_delay)
current_rate = cwnd / rtt_standing

From code:

auto rttStandingMicroSec = standingRTTFilter_.GetBest().count();
delayInMicroSec = rttStandingMicroSec - rttMin.count();
auto targetRate = (1.0 * conn_.udpSendPacketLen * 1000000) /
        (deltaParam_ * delayInMicroSec);
auto currentRate = (1.0 * cwndBytes_ * 1000000) / rttStandingMicroSec;

Rate update

on each ACK arrives

From paper:

# change cwnd v/delta packets per RTT (cwnd acks)
# when delta = 0.5, v = 1, change 2 packets per RTT

# v is velocity parameter, default to 1 in steady state
# if it moves to one direction, cwnd keeps increasing or decreasing for 3 times, double v.
# if change direction, reset v to 1

if current_rate <= target_rate:
    cwnd += v/(delta * cwnd)
else:
    cwnd -= v/(delta * cwnd)

From code:

increaseCwnd = targetRate >= currentRate;
if (increaseCwnd) {
    // seems a little difference with paper, more acks, more change??
    uint64_t addition = (ack.ackedPackets.size() * conn_.udpSendPacketLen *
                           conn_.udpSendPacketLen * velocityState_.velocity) /
          (deltaParam_ * cwndBytes_);
    addAndCheckOverflow(cwndBytes_, addition);
} else {
    uint64_t reduction = (ack.ackedPackets.size() * conn_.udpSendPacketLen *
                          conn_.udpSendPacketLen * velocityState_.velocity) /
        (deltaParam_ * cwndBytes_);
    subtractAndCheckUnderflow(
        cwndBytes_,
        std::min<uint64_t>(
            reduction,
            cwndBytes_ -
                conn_.transportSettings.minCwndInMss * conn_.udpSendPacketLen));
}

Dynamics

  1. In steady state (in which v=1), on each RTT, there will queue 1/delta per RTT. So one RTT before reaching target rate when dropped below that.
  2. And will use smallest RTT in recent srtt/2 duration to filter noise (ACK compression, WiFi aggregation) in RTT as the standing RTT. So have srtt/2 watching window.
  3. Then need 1 RTT to get the feedback. So direction change per 2.5 RTT
  4. Now since target rate is smaller (queuing delay goes larger), reduce congestion window.
  5. And after one RTT, target rate is still smaller, still having packets queued, and having srtt/2 watching window.
  6. Then need 1 RTT to get the feedback, and find now the target rate goes larger than current rate, ramp up again and go to step 1.

Competing with buffer-filling schemas

  1. same queueing qdelay will cause global synchorization on Copa flows
  2. Copa flow is expected to empty the queue at least once 5 RTT.
  3. If queueing delay not "nearly empty" in 5 RTT, then switch mode and use delta <= 0.5, which makes Copa more aggressive.
  4. "nearly empty" is defined to be less than 10% of RTT_max - RTT_min.

Reference

http://people.csail.mit.edu/venkatar/copa.pdf

https://github.com/facebookincubator/mvfst/blob/master/quic/congestion_control/Copa.cpp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment