- Transport-layer services
- Multiplexing & demultiplexing
- Connectionless transport: UDP
- Principles of reliable data transfer
- Connection-oriented transport: TCP
- Principles of congestion control
- TCP congestion control
- Evolution of transport layer funcitonality
Sender는 sending rate를 packet loss(congestion)이 발생할 때까지 증가시킬 수 있고, loss event가 발생할 경우 줄이게 된다.
그래서 시간에 따라 TCP의 sender rate를 표기하면 톱날 모양의 그래프를 얻게 된다.
이런 방식을 채택한 이유는 congestion threshold가 어느 지점인지 알 수 없고, 따라서 congestion window 크기가 매번 바뀌니 loss가 발생하는 지점이 달라 AIMD(Additive Increase Multiplicative Decrease) 행동을 하게 되는 것이다. 따라서, congestion window의 크기가 클수록 해당 범위 내에서 대역폭을 잘 활용할 수 있게 된다.
Q. 왜 AIMD를 사용하는가?
A. AIMD는 distributed, asynchronous algorithm으로 혼잡된 flow rate를 전체 네트워크에서 최적화시킬 수 있으며, 안정적인 특성을 가지고 있기 때문이다.
TCP sending behavior는 cwnd bytes만큼 보내고, ACK을 위해 RTT만큼 기다리고, 남은 byte를 보내는 방식으로 진행된다.
즉, TCP rate는 cwnd/RTT (bytes/sec)로 근사해서 표현할 수 있다.
TCP sender는 transmission을 제한하기 위해 LastByteSent - LastByteAcked <= cwnd 라는 조건식을 사용한다. cwnd는 관찰된 네트워크의 혼잡 상황에 따라 동적으로 정해지는 값이다.
Connection이 시작되면, sending rate를 첫 번째 loss event가 발생하기 전까지 지수적으로 증가시킨다.
따라서, initial rate는 느린데, 지수적으로 증가시키는 방식이다.
Q. 그렇다면 이 지수적 증가는 어느 시점에서 선형적인 증가로 대체되는가?
A. cwnd가 timeout이 발생하기도 전에 절반으로 감소하는 시점부터
이를 구현하기 위해, ssthresh라는 variable을 이용한다. Loss event가 발생하면, ssthresh가 lost event가 발생하기 직전의 cwnd의 1/2 값으로 설정된다. Congestion control 알고리즘이 혼잡 상황을 감지하면 ssthresh 값을 설정하고, 이후에 cwnd 값이 ssthresh보다 작은 상태를 유지하도록 Congestion Avoidance 과정을 거치게 된다.
Q. 그렇다면 cwnd를 2배씩 증가시키는 건 어떻게 구현하는가?
A. 각 packet의 ack을 받을 때마다 cwnd를 1씩 증가시킨다.
우선, cwnd는 1MSS로 초기화, ssthresh는 64KB, dupACKcount는 0으로 초기화된 상태이다.
+) 각 state의 의미
Slow start state : Slow Start 상태는 TCP 연결이 처음 설정될 때와, 패킷 유실이 발생했을 때 사용. cwnd의 지수적 증가.
Congestion Avoidance state : Congestion Avoidance 상태는 Slow Start 상태에서 cwnd 값이 ssthresh(threshold) 값보다 커지는 경우에 전환. cwnd의 선형적 증가.
Fast Recovery state : Fast Recovery 상태는 Dup ACK 패킷이 수신될 때마다 혼잡 상황을 회피하기 위해 사용. 이 state로 들어오면서 ssthresh가 cwnd/2로 설정되고, 해당 state에 머무르며 현재 cwnd 값이 ssthresh 값보다 작아지게 만든다.
AIMD의 경우, 반복적으로 sending rate를 증가시키고 감소시키는 과정을 통해 bandwith를 추측해 대응하였다. 이보다 더 좋은 방법으로 대응할 수 없을까?
TCP Tahoe (86) vs TCP Reno (90) vs TCP CUBIC (06)
비교분석그래프를 보면, TCP Tahoe와 TCP Reno가 유사한 혼잡 제어 알고리즘을 사용한다는 것을 알 수 있습니다. 혼잡이 발생하면, 이들은 송신률을 반으로 줄이는 것처럼 혼잡 윈도우 크기를 급격히 줄입니다. 타임아웃 기간 후, 다시 다음 혼잡 이벤트가 발생할 때까지 혼잡 윈도우 크기를 선형적으로 증가시킵니다.
반면, TCP CUBIC은 다른 혼잡 제어 알고리즘을 사용합니다. 혼잡이 감지될 때까지 혼잡 윈도우 크기를 지수적으로 증가시키며, 그 이후에는 혼잡 윈도우 크기를 감소시킨 다음, 점진적으로 다시 증가시킵니다.
TCP Tahoe는 Congestion Avoidance 단계에서 패킷 손실이 발생하면 혼잡 윈도우 크기를 작게 조정합니다. 패킷 손실을 감지하면 Slow Start 단계로 돌아가서 혼잡 윈도우 크기를 작게 설정하고 다시 시작합니다. 이로 인해 TCP Tahoe는 패킷 손실을 지속적으로 경험하게 됩니다.
반면에 TCP Reno는 Congestion Avoidance 단계에서 패킷 손실을 감지하면, 혼잡 윈도우 크기를 반으로 줄이고 Fast Recovery 모드로 전환합니다. Fast Recovery 모드에서는 패킷 손실을 감지하지 않고도 혼잡 윈도우 크기를 증가시키면서 전송을 계속합니다. 이러한 방식으로 TCP Reno는 패킷 손실을 더 능동적으로 처리하며, 혼잡 윈도우 크기를 조절하는 데 더 정교한 방법을 사용합니다.
따라서, TCP Tahoe와 TCP Reno의 차이점은 Congestion Avoidance 단계에서 발생하며, TCP Reno가 더욱 효율적으로 혼잡 제어를 수행할 수 있도록 개선된 알고리즘을 사용한다는 것이 가장 큰 차이점입니다.
TCP (classic, CUBIC)은 어떤 임의의 router에서 packet loss가 발생할때까지 TCP의 sending rate를 증가시킨다. 즉, 특정 bottleneck link가 congestion의 원인인 것인데, 이곳에 TCP sending rate를 증가시키는 것은 RTT가 길어지는 것으로 이어지게 된다.
우린 end-end pipe를 최대한 이용하는 것이지, 더 넘치게 이용하고 싶은 것이 아니다. 즉, bootleneck link를 바쁘게 이용하되, 높은 delay/buffering을 피하고 싶은 것이다.
우리가 지금까지 배웠던 AIMD나 CUBIC congestion control 알고리즘은 packet loss가 발생하였을 때만 cwnd 크기를 조절하기 때문에, packet loss를 경험하지 않으면 congestion control에 대해 반응이 느리고 전송률이 불안정해질 수 있다.
Delay-based congestion control의 경우 RTT의 길이를 기반으로 cwnd의 크기를 동적으로 조절함으로써 packet loss를 경험하지 않더라도 congestion control이 가능하다. Uncongested path에 대해서 RTTmin을 관측하고, 현재 throughput이 uncongested throughput에 가까우면 cwnd를 선형적으로 증가시키고, 멀어지면 cwnd를 선형적으로 줄인다. 이 방식을 통해 delay를 낮으면서도 throughput을 최대화할 수 있다.
다수의 TCP는 이 delay-based 방식을 사용하며, 구글의 네트워크도 대표적인 delay-based 알고리즘인 BBR(Bottleneck Bandwidth and RTT) 알고리즘을 사용한다.
이전에 소개되었던 end-to-end congestion control 방식과 달리, network-assisted congestion control은 네트워크 요소들이 congestion을 감지하고 이를 제어하는 데 직접적으로 개입한다. 위 그림에서도 볼 수 있듯이, TCP header 내부에 있는 CWR, ECE라는 두 flag를 이용해 congestion control을 수행한다.
Explicit congestion notification은 network router에서 congestion이 발생하였음을 감지하면 IP header (ToS field)에 있는 두 개의 bit를 이용해 congestion이 일어났음을 명시한다. (네트워크 운영자가 선택한 표시를 결정하는 정책)
이렇게 congestion이 표시된 header는 destionation까지 전달되어, destination에서 ACK segment에 ENE bit로 설정되어 congestion의 sender에게 congestion이 발생하였음을 알리게 된다.
IP(IP header ECN bit marking)과 TCP (TCP header CWR, ECE bit marking)이 포함된다.
TCP는 bandwith를 사용할 때 경쟁적인 방식으로 동작하나, 각각의 TCP connection이 bandwith를 공정하게 나누어 사용할 수 있도록 하는 것을 목표로 한다. 즉, K개의 TCP session이 있고 bandwith가 R이면 각 session이 R/K만큼씩 사용할 수 있게 하고자 한다.
그래서 두 개의 TCP session이 경쟁하고 있는 상황을 보자. 첫 지점을 보면 connection 1과 2의 throughput이 결정되어 있는데 1이 2에 비해 적은 bandwith를 사용하고 있다. 따라서, connection 1이 additive increase를 사용해 equal bandwith share의 기울기를 따라 bandwith를 증가시킨다. (congestion avoidance state) 이때 두 connection의 합이 bandwith R을 넘어서면, multiplicative decrease를 이용해 throughput을 줄인다. 이 과정을 반복하여 bandwith를 공정하게 나누는 지점에 가까워지게 된다.
따라서 TCP는 각 connection이 같은 RTT를 가지고, 특정한 시점에서 전송중인 TCP session의 수가 고정되어있으며 해당 세션들이 congestion avoidance 상태라는 조건이 충족되면 fair하다고 말할 수 있다.
Fairness and UDP
Fairness, parallel TCP connections
Fairness, parallel TCP connections