TCP: Overview
- connection-oriented: message 교환 전에 송신자/수신자 사이에 연결 필요
- point-to-point: 한 연결 당, 한 명의 송신자와 수신자
- full duplex data: 한 연결에 양방향 통신 가능
- flow controlled: 송신자는 수신자가 메시지를 받을 수 없는 상태면 메시지를 보내지 않음
- pipelined: congestion control / flow control은 window size를 dynamic하게 설정할 수 있음
- reliable, in-order byte stream
- reliable: 메시지 전송은 아예 성공하거나 아예 실패하거나 둘 중 하나
- in-order: 송신자가 보낸 순서대로 메시지를 받음
- byte stream
- 메시지(data stream)을 받은 후 segment를 만들어서 데이터를 전송함
- segment의 크기는 MSS로 제한됨
- MSS: Maximum Segment Size
Many flavors of TCP
- 여러 종류의 TCP가 있는데, 대부분 congestion control algorithm에서 차이가 존재함
- 이 수업에서는 TCP (new) Reno를 다룸
TCP segment structure
- TCP header
- src / dst port #
- seq num: segment의 첫 번째 바이트의 byte stream number
- ack num
- 상대방으로부터 다음에 받을 것이라고 예상되는 sequence number
- 누적 ACK 사용
- header length
- flag: U, A, P, R, S, F
- A: ack # valid
- RST, SYN, FIN: connection 생성에 사용됨
- receive window
- 수신자가 받을 수 있는 bytes 수
- checksum
- urg data pointer
- TCP Payload
- application data (variable length)
TCP sequence numbers, ACK numbers
- full-duplex: packet은 seq #, ack #를 동시에 가지기 때문에 양방향 통신에 이용할 수 있음
- seq #는 connection 설정 단계에서 랜덤으로 설정되고, 송신자/수신자가 서로 이 정보를 교환함
- 매 연결마다 같은 seq #를 사용해서 보내면 receiver가 혼동할 수 있음
- 송신자의 seq# space
- window size = N
- N = (전송 중이지만 ACK를 받지 않은 packet) + (전송 가능하지만 아직 보내지 않은 packet)
- SendBase: 아직 ACK를 받지 못한 첫번째 byte
- 수신자는 out-of-order segments를 어떻게 처리할까?
- TCP에선 결정된 것이 없음. 프로그래머가 결정
TCP round trip time, timeout
- timeout 까지 ACK가 오지 않으면 packet loss가 일어났다고 생각하고, packet을 재전송함
- TCP가 Timeout value를 설정하는 방법
- RTT보다 길어야 함. RTT는 queueing delay 때문에 고정된 값이 아님. timeout value를 너무 짧게 설정하면 재전송이 많이 일어나 네트워크를 혼잡하게 만들 수 있음. 그렇다고 또 너무 길면 packet loss에 느리게 대응하기 때문에 throughput이 저조해짐. 둘 다 안 좋음.
- RTT를 추정하는 방법
- SampleRTT
- segment가 전송되고 ACK를 받을 때까지 측정된 시간
- 재전송은 무시함, 하나의 패킷에 대한 RTT 당 하나의 SampleRTT 측정
- Sample RTT는 다양하기 때문에 일반화(smoother)한 버전이 필요함
- Exponential Weighted Moving Average (EWMA)
- EstimatedRTT = (1-alpha) * EstimatedRTT + alpha * SampleRTT
- 여기서 EsitmatedRTT는 과거에 측정한 값이고, SampleRTT가 가장 최근에 측정한 값임
- 위 식을 보면 과거 측정값의 영향이 exponentially하게 감소하는 것을 볼 수 있음
- 보통 alpha의 값으로 0.125를 사용한다고 함
- SampleRTT
- Timeout Interval
- EstimatedRTT + "safety margin"
- EstimatedRTT의 변동이 클수록 더 큰 safety margin이 필요함
- DevRTT
- EstimatedRTT로부터 SampleRTT의 편차를 추정
- DevRTT = (1-Beta) * DevRTT + Beta * |SampleRTT - EstimatedRTT|
- Beta는 보통 0.25를 사용
- Timeout Interval
- EstimatedRTT + 4 * DevRTT
TCP - reliable data transfer
- IP는 unreliable / best effort 서비스임. queue overflow, our-of-order 등 전송 중에 문제가 생길 수 있음.
- TCP는 IP 위의 계층으로, reliable data transfer를 지원함.
- Pipelined segments, 누적 ACK, 하나의 재전송 타이머를 사용
- timeout, 누적 ACK가 발생하면 재전송이 일어남
- 간단한 이해를 위해 누적 ACK와 flow/congestion control를 무시하고 한 송신자가 한 수신자에게 메시지를 전달한다고 가정해보자.
- 송신자는 상위 계층으로 부터 데이터를 받는다. 그리고 segment를 만들고 seq#를 설정한다. seq #는 segment의 첫 번째 data byte의 number이다. 그리고 timer가 돌아가고 있지 않으면 timer를 시작한다. 타이머는 전송은 했지만 ack를 받지 않은 가장 오래된 segment에 대한 타이머로 생각하면 된다. timeout value는 위에서 구한 TimeOutInterval로 설정한다.
- Timeout 발생: timeout이 발생된 segment를 재전송하고 timeout value를 두 배로 늘려서 timer를 다시 시작한다. packet loss는 보통 network가 혼잡할 때 일어난다. 이전과 같이 단순하게 재전송하면 또 timeout이 생길 것이고, 재전송으로 이어져 혼잡한 네트워크를 더 혼잡하게 만들게 된다.
- ACK received: ACK를 아직 받지 않은 segment에 대한 ACK인 경우에는, ACK를 받았다고 sequence window를 업데이트하고, 아직 ACK를 받지 않은 segment가 있다면 타이머를 시작한다. 만약 이미 받은 ACK를 또 받은 경우는 재전송을 해야하는 상황이다.
TCP ACK generation
Event at receiver | TCP receiver action |
예상했던 seq #의 segment를 올바른 순서로 받음. 예상했던 seq #까지의 모든 데이터들이 이미 ACK가 된 상태 | delayed ACK 너무 많은 ACK를 보내는 것도 자원 낭비라고 생각해서 다음 segment가 올 때까지 500ms를 기다림. 만약 다음 segment가 오지 않는다면 ACK 전송 |
예상했던 seq #의 segment를 받았지만, ACK를 받지 못한 segment가 하나 있는 상태 | 멀쩡하게 잘 받은 것까지 나타낼 수 있는 누적 ACK를 즉시 보냄 |
예상했던 seq #보다 큰 segment를 받아 gap이 생긴 상태 ex) 1 2 x x 5 |
즉시 누적 ACK를 보냄 ex) ACK3 전송 |
gap을 채우는 segment가 도착했다! | 즉시 누적 ACK를 보냄 |
TCP fast retransmit
- 문제: timeout이 종종 커서 재전송하기전에 오랜 시간을 기다리는 경우가 존재함
- 아이디어: duplicate ack를 통해 packet loss를 감지해보자
- segment가 중간에 loss되면, duplicate ACK가 생김
- 송신자가 같은 ACK를 3번 받으면, packet loss가 발생했다고 생각하고, ACK를 받지 않은 segment 중 가장 오래된 segment 재전송하자
TCP flow control
- 송신자가 메시지를 너무 빠르게 보내면 buffer overflow가 생겨 packet이 drop될 수 있음
- 수신자는 수신자의 버퍼가 넘치지 않게끔 송신자를 제어함
- 수신자는 송신자에게 보내는 세그먼트의 헤더에 'rwnd'를 포함시켜 'free buffer space'를 알림
- rwnd는 버퍼(RcvBuffer)에 얼마나 여유 공간이 남아있는지 알려줌
- 버퍼의 크기는 socket option을 통해 설정 가능함. 보통은 4096 bytes이고, OS가 버퍼 사이즈를 자동으로 증ㄱ마시킬 수 있음
- 송신자는 수신자의 rwnd 값으로 unacked data의 양을 제한함으로써 수신자 버퍼에 overflow가 생기는 것을 방지할 수 있음
TCP connection management
- 송신자와 수신자는 통신 전에 connection establishment 단계를 거침. 이 단계에서 첫 seq #를 주고 받음
- 2-way handshake: 송신자는 수신자가 보낸 메세지를 받았는지 확인할 수 없음
- 3-way handshake 사용
- open a connection
Client | Server |
초기 seq #인 x 를 결정하고, Server에 TCP SYN msg를 보냄 ex) SYNbit = 1, Seq#=x ------------------------------------------------> |
|
초기 seq #인 y를 결정하고, Client에 TCP SYNACK msg를 보냄. ex) <------------ SYNbit = 1, Seq# = y, ACKbit=1, ACKnum=x+1 |
|
SYNACK(x)를 받은 것은 Server가 실행 중이라는 것을 의미함. (establishment!) SYNACK에 대한 ACK를 보냄. 이 세그먼트는 clinet-to-server data를 포함할 수 있음 ex) ACKbit=1, ACKnum=y+1 ------------------------------------------> |
|
ACK(y)를 받고, client가 실행 중이라는 것을 확정지음 (establishment!) |
- close a connection
Client | Server |
clientSocket.close() 메세지를 이제 안보내지만, 받을 수는 있음 ex) FINbit=1, seq=x ----------------------------------------------------> |
|
메세지를 아직 보낼 수 있음 ex) <------- ACKbit=1, ACKnum=x+1 |
|
서버가 닫히는 것을 기다림 | |
... | |
서버가 이제 socket을 닫겠다고 client에게 알려줌 이제 서버는 데이터를 안보낼꺼다! ex) <-------- FINbit=1, seq=y |
|
FIN msg에 대한 ACK를 보냄 segment의 lifetime의 두 배 동안 기다리고 닫음. FIN msg에 대한 ACK 메세지가 제대로 갔는지 모르기 때문임 ex) ACKbit=1, ACKnum=y+1 ---------------------------------------> |
|
ACK msg가 도착하면 닫음 |
TCP congestion control
- Congestion: 너무 많은 소스가 네트워크가 다루기에 너무 빠르게 많은 데이터를 보내서 생김
- flow control과는 다름
- flow control은 송신자가 수신자가 감당할 수 없을 만큼 빠르게 데이터를 보내지 않도록 제어하는 것이고, congestion control은 송신자들이 네트워크가 감당할 수 없을만큼 많은 데이터를 빠르게 보내지 않도록 제어하는 것
- 증상으로는 buffer overflow로 인한 packet loss와, buffer에서의 queueing delay가 있음
- congestion의 원인과 cost
- Ideal case
- 가정1. sender가 router의 buffer에 free space가 얼마나 있는지 알고 있음
- 가정2. packet loss가 생긴 것을 sender가 안다. packet이 loss 되었을 때만 재전송을 함
- Realistic case (cause)
- 송신자는 packet loss를 감지하기 위해 timeout을 사용함. timeout이 일찍 일어나면, 수신자가 패킷을 잘 받았어도 다시 보내기 때문에 duplicate들이 발생하게 됨.
- cost: 불필요한 재전송. link가 같은 pkt을 여러번 옮기는 상황이 존재함
- 문제가 없던 상위 link의 bandwidth에 낭비가 발생
- ACK/timeout을 기다리는데 시간 낭비 발생
- Ideal case
- 그래서 congestion control 어케함?
- congestion이 있을 때는 전송 속도를 줄이고, congestion이 없으면 전송 속도를 올린다
- 1. 전송 속도를 어떻게 제어할까?
- 2. congestion control를 어떻게 감지할까?
- 3. 전송 속도를 언제, 얼마나 높이고, 낮추어야 하는가?
- In TCP Reno,
- Key states & mechanisms
- slow start
- congestion control - "AIMD: Additive Increase Multiplicative Decrease"
- fast recovery
- Key parameters
- congestion window: cwnd
- slow-start threshold: ssthresh
- MSS, RTT
- Key events
- ACK received: good
- timeout: very bad
- 3 duplicate ACK received: bad
- Key states & mechanisms
TCP Congestion Window
- (가장 최근에 보낸 byte - 가장 최근에 받은 byte) < cwnd
- cwnd는 dynamic함
- TCP 전송률 = cwnd/RTT bytes/sec
TCP Slow Start
- slowstart: 연결을 시작할 때, 첫번째 loss가 생길 때 까지 전송 속도를 exponential하게 증가시킴
- 초기 cwnd = 1 MSS
- 매 RTT 마다, 즉 ACK를 받을 때마다 2배씩 증가시킴
- timeout: slow start와 유사하게 돌아옴
- 네트워크가 ACK도 못보낼 최악의 상황이라는거임
- cwnd를 1로 설정함
- ssthresh에 도달 할 때까지 window를 exponential하게 늘림
- 3 dup ack: congestion avoidance 단계로 감
- 네트워크에 여유가 있는 상태임
- cwnd를 절반으로 줄이고, linear하게 증가시킴
TCP congestion avoidance: AIMD
- additive increase: loss가 발생할 때까지 매 RTT마다 cwnd를 1 MSS씩 증가시킴
- multiplicative decrease: loss 발생 후 cwnd를 절반으로 줄임 (ssthresh가 cwnd의 1/2로 설정됨)
TCP throughput
- TCP의 평균 throughput?
- slow start, +3 무시
- W: loss가 일어나는 곳의 window size
- 평균 window size는 3/4W
- 평균 throughput: 3/4 * W/RTT bytes/sec
TCP Fairness
- bandwidth가 R인 bottleneck를 공유하는 K개의 TCP sessions은 각각 평균 속도가 R/K이어야 함
- 왜?
'학교 > network' 카테고리의 다른 글
[ch4] 2. what's inside a router (0) | 2022.06.19 |
---|---|
[ch4] 1. overview of network-layer (0) | 2022.06.19 |
[ch3] 7. TCP congestion control (0) | 2022.05.16 |
[ch3] 6. Principles of Congestion Control (0) | 2022.05.16 |
[ch3] 5. connection-oriented transport: TCP (0) | 2022.05.16 |
댓글