1. 특징
•
TCP 3 way handshake는 왕복시간 한번만큼의 latency를 발생시킨다.
•
TCP Slow start는 connection이 새로 만들어질 때 항상 발생한다.
•
TCP Flow control과 Congestion control은 모든 Connection의 처리량을 조절한다.
•
TCP 처리량은 현재 cwnd(Congestion Window) size에 의해 결정된다.
rwnd 크기 통지
2. 흐름제어
흐름제어는 송신자가 수신자에게 처리하지 못할 만큼의 많은 데이터를 전송하는 것을 미리 방지하는 메커니즘이다. 수신자가 데이터를 받지 못하는 경우는 보통 수신자가 다른 데이터를 처리하고 있거나, 밀려있는 데이터가 많거나 버퍼공간을 충분히 지정해주지 않는 경우다. 이러한 문제를 해결하기 위해 양쪽의 TCP 커넥션이 각각 자신의 receive window(rwnd)를 통지하여 수신데이터를 저장할 버퍼 공간의 크기를 서로에게 알려준다. 이 버퍼 공간은 데이터 처리를 기다리는 응용 계층 프로토콜에 스택을 꽉 채울때까지 데이터가 임시적으로 저장되는 공간이다. 따라서 전송 호스트는 한 번에 window size 필드에 명시된 데이터 양 만큼만 보낼 수 있다.
window size를 조정하는 프로세스는 매우 명확하지만, 완벽한 것은 아니다. 데이터가 TCP 스택에 수신될 때마다 ACK가 생성되고 반복적으로 보내지지지만 수신자의 버퍼에 있는 데이터가 항상 즉시 처리되는 것은 아니기 때문이다. window size를 재조정하는 프로세스로 zero window 전송을 통한 데이트 흐름을 중지하는 방법과 TCP sliding window 등의 두가지 방법을 사용한다.
1) zero window 전송을 통한 데이터 흐름 중지
메모리 부족, 처리능력의 부족 또는 다른 문제로 인해 서버가 클라이언트로부터 보내온 데이터를 처리할 수 없는 경우 서버는 크기가 0인 window를 보낼 수 있다. 클라이언트가 이 패킷을 수신하면 데이터 전송은 중지되지만, keep-alive 패킷의 전송을 통해 서버와의 연결은 유지되며, 서버 측 receive window의 상태를 점검하기 위해 일정 간격으로 패킷을 보낸다.
2) TCP Sliding window
위의 캡쳐를 보면 window size가 8760 -> 5840 -> 2920 바이트로 감소되다 0이 된다. 이 후 Window Update 패킷이 수신되면 다시 데이터를 수신할 수 있게 된다.
3) Window Scaling
원래의 TCP spec에서는 rwnd를 지정할 때 16 비트를 할당한다. 이는 송신자와 수신자가 지정할 수 있는 receive window size의 최대치가 65,535 바이트로 정해져있음을 의미한다. RFC 1323에 기술된 TCP window scale option을 사용하면 rwnd를 1 기가바이트까지 늘릴 수 있게 해준다. 최근 대부분의 플랫폼에서는 기본적으로 활성화되어 있다.
3. 혼잡제어
혼잡붕괴(Congestion collapse)란, Speed mismatch(1G input port 1개에서 100Mbps output port 1개로 나갈 때)거나 여러 port에서 입력된 트래픽이 하나의 port로 집중(1G input port 2개에서 1개의 1G output port으로 나갈 때)되는 등의 상황에 발생한다. 전자의 경우 buffering은 output port의 buffer(output queue)에서 발생하며, 후자의 경우엔 input/output queue 모두 발생할 수 있다. 후자의 경우 port별 경쟁 상황이 발생하는데 queue의 크기가 작으면 buffer overflow에 의해 packet drop이 발생하여 TCP 송신자가 DUP_ACK를 연속 3회 수신하게 된다. 반면, queue의 크기가 크면 queue에서 대기하는 buffering delay가 증가하여 TCP retransmission timeout이 발생한다. 그리고 이 두 경우에 TCP congestion을 감지하고 혼잡 제어 동작을 수행한다.
TCP retransmission
TCP Congestion Control에는 대표적으로 slow start, congestion avoidance, fast retransmit, fast recovery 등 4가지 방법이 있다.
1) Slow Start
클라이언트와 서버간의 허용량을 가늠하는 유일한 방법은 실제로 데이터를 교환하면서 허용량을 측정하는 것 뿐이다. 이것이 Slow Start가 하는 일이다. 우선 서버가 각 TCP 커넥션마다 새 혼잡윈도(cwnd)를 만들고 그 값을 시스템에서 정해진 안전한 수치로 설정한다.
cwnd
receive window size나 send window size는 모두 byte 단위이나, cwnd (congestion window) size는 segment 수를 단위로 한다. 여기서 segment란 TCP header를 제외한 TCP payload 크기 즉, TCP MSS를 의미한다.
혼잡 윈도 크기를 증가시키는데 걸리는 시간을 단축시키기 위해서는 클라이언트와 서버간의 왕복시간을 줄이거나 초기 혼잡윈도크기 값(intial cwnd)을 늘릴 수도 있다. (최근의 리눅스커널은 initial cwnd size를 10 segment (lw 10)로 설정되어 있다. https://tools.ietf.org/html/rfc6928)
<그림 1> ssthresh default가 설정되지 않았을 경우
2) Congestion Avoidance
혼잡 회피에서 암묵적으로 판단하기에 패킷 손실이 일어났다는 것은 네트워크 혼잡이 일어났다는 신호다. 이동 경로의 어딘가에서 정체가 일어난 링크나 라우터가 패킷을 누락시켰을 것이다. 그래서 네트워크에 부담을 덜어주고 더 이상의 패킷 손실을 막기 위해 윈도 사이즈를 조정해야 하는 것이다.
Packet loss가 감지되면, 바로 이전 Congestion window size를 ssthresh 값으로 설정하고 이후에 congestion avoidance 단계에서 그 ssthresh 값으로부터 segment를 하나씩 증가시키면서 network congestion이 발생하는 지점을 찾는다. packet loss가 발생하면 다시 ssthresh 값을 직전 cwnd의 절반으로 줄이고 다시 slow start를 수행한다. (<그림1>을 참조하자)
그런데 packet loss가 발생했을 경우 이전까지 TCP 송신자는 매번 retransmission timeout(RTO)가 발생할 때까지 기다려서 packet loss를 감지하였다. 이에 대한 대안으로 Fast Retransmission과 Fast Recovery가 제시되었다.
3) Fast Retransmission & Fast Recovery
Network에서 packet loass가 발생한 사실을 RTO가 아닌 연속 3회 DUP_ACK로 인지하게 될 경우 (<그림1>의 4번, Fast Retransmission) 이전처럼 cwnd를 초기값부터 다시 slow start를 하지 않고 현재의 절반으로 줄인 후에 congestion avoidance를 수행해서 빠르게 packet loss가 발생했던 cwnd 직전까지 찾아간다(Fast recovery).
중복 ACK (DUP_ACK)
4. BBR
기존의 CUBIC 알고리즘의 경우, 사용자가 몰리는 등의 트래픽 증가로 패킷손실이 발생할 당시의 window size를 기준으로 cwnd(congestion window)를 계산하여 패킷 손실을 방지하였다.
이에 반해, Google의 BBR은 패킷 손실보다는 최근 network's delivery rate과 round-trip time을 활용하여 허용할 수 있는 데이터 양을 제어한다.