본문 바로가기
컴퓨터공학/네트워크

TCP/IP Congestion Control

by 딩코딩코 2019. 11. 21.

1. Congestion이 발생하는 경우

 그림처럼 두 노드가 1GB 링크를 통해 데이터를 전송하는데, 두 노드가 링크의 용량을 최대한으로 활용해서 데이터를 전송할 경우 중간 지점에서 데이터의 손실이 발생하는 것이다. TCP의 경우 전송하는 노드가 데이터의 손실을 감지하면 해당 데이터를 재전송하기 때문에, 위와 같은 경우 두 노드는 영원히 데이터를 전송하는 지옥에 빠질 것이다.
 때문에 위와 같은 문제를 해결하기 위해서는 두 노드가 모두 데이터를 보내는 양을 조절해야하 하는데, 네트워크 상에서는 각 노드에게 얼마만큼의 데이터를 전송하라고 지시하는 중앙 노드가 없기에 이 문제를 해결하는게 쉽지는 않다. 한 가지 더 고려해야 할 점은, 노드가 자신이 사용하는 링크들의 용량을 알 수 없다는 것이다. 지금 내 노트북에서 어떤 서버로 접근한다면 링크 하나만을 통과하는 것이 아니라 수십 번 혹은 몇 백번까지 링크를 갈아탈 수도 있는 것이다. 때문에 내가 한 번에 보낼 수 있는 데이터의 양을 매번 체크하는 기능이 필요하다.

2. Congestion Window

 Congestion Window 혹은 flight size 라고 한다. Congestion Window란 ack을 확인하지 않고도 보낼 수 있는 데이터의 양을 말한다. 예를 들어, 전송자에게 Congestion Window가 2로 세팅된다면, 전송자는 2 segments를 보낸 후 수신자로부터 ack이 올 때까지 기다려야 하는 것이다.  
 당연히 Congestion Window의 크기가 크면 한 번에 보낼 수 있는 데이터의 양이 많으니 데이터를 완전하게 보내는 데에 걸리는 시간이 줄어들 것이다. 그러나, 그 크기를 키우는 것은 Congestion을 발생시킬 수 있으니, 이 적당한 사이즈를 찾는 알고리즘이 필요하다.

3. TCP Tahoe

 이 방법은 80년대에 만들어진 것으로, 2가지 단계를 통해 Congestion Window의 크기를 키운다.

 - 1 Slow start

 이 알고리즘은 Slow start 라는 상태에서 시작한다. 이 상태에서 Congestion Window는 ack을 받을 때마다 크기가 1씩 커진다. 예를 들어, Congestion Window가 4이고, 4의 데이터가 전송된 후, 수신자가 각 데이터에 대한 ack을 보내면 Congestion Window가 8이 되는 것이다. 이러한 과정은 Slow start threshold에 도달할 때까지 반복된다. (이 숫자는 따로 세팅할 수 있다.)

- 2 Congestion avoidance

 한 번 ssthresh에 도달하게 되면, Congestion Window의 성장 속도가 줄어든다. Congestion Window가 4이고, 4의 데이터가 전송된 후, 수신자가 각 데이터에 대한 ack을 보내면 Congestion Window는 8이 아닌 5가 되는 것이다.
 중요한 것은 패킷 손실을 감지했을 경우다. 패킷 손실을 확인하면, 전송자는 해당 패킷을 재전송하면서 ssthresh는 현재 Congestion Window의 반이 되고 Congestion Window는 1이 된다.

ssthresh = congestion_window*0.5
congestion_window = 1

- 3 결과 그래프

Slow start 때는 급격히 커지다가 Congestion avoidance 단계에 들어가며 크기가 1이 되었다가 서서히 커지는 모습을 확인할 수 있다.

4. CUBIC

 그런데 위 방법은 80년대에 개발된 방식으로 현 네트워크 상황에 그리 알맞지는 않다. 이유는 현재 네트워크의 bandwidth의 크기가 상당히 커졌다. 때문에 송신자는 80년대보다 훨씬 큰 Congestion Window의 크기를 파악해야한다. 즉, Tahoe를 통해 적당한 크기의 Congestion Window를 파악하는데까지 상당히 오랜 시간이 걸리게 된 것이다.

이렇게 커져버린 bandwidth에 맞춰진 것이 CUBIC이다. 다른 전송자의 bandwidth 크기를 줄이지 않으면서도 네트워크에 오버로드하지 않는 방법이다. CUBIC 은 y=x**3 함수에서 착안했다.

x의 값이 조금만 커져도 y의 값은 순식간에 커진다.

방법은 간단하다.

- 1 시작할 때는 빠르게 크기를 키운다.
- 2 데이터를 손실했었던 포인트를 만나면, congestion window의 성장 속도를 줄인다.
- 3 해당 포인트를 지나도 데이터 손실이 일어나지 않으면 다시 congestion window의 성장 속도를 키운다.

Cubic이 더 좋은 성능을 보이긴 하지만 그 차이가 크게 나타나지 않는다.

- 5 높은 BDP Network에서의 비교 그래프

이제 좀 큰 차이가 나타난다.

 

참고 : http://squidarth.com/rc/programming/networking/2018/08/01/congestion-cubic.html