아래 코드는 tcp slow start와 congestion avoidance가 구현되어 있는 리눅스 코드 입니다. tcp_input.c에 정의 되어 있습니다.
1699 static __inline__ void tcp_cong_avoid(struct tcp_opt *tp)
1700 {
1701 if (tp->snd_cwnd <= tp->snd_ssthresh) {
1702 /* In "safe" area, increase. */
1703 if (tp->snd_cwnd < tp->snd_cwnd_clamp)
1704 tp->snd_cwnd++;
1705 } else {
1706 /* In dangerous area, increase slowly.
1707 * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd
1708 */
1709 if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
1710 if (tp->snd_cwnd < tp->snd_cwnd_clamp)
1711 tp->snd_cwnd++;
1712 tp->snd_cwnd_cnt=0;
1713 } else
1714 tp->snd_cwnd_cnt++;
1715 }
1716 tp->snd_cwnd_stamp = tcp_time_stamp;
1717 }
그런데...
cwnd가 threshhold 보다 작을때는 exponential 증가가 되어야 하는데 코드에 보면은(tp->snd_cwnd++) 리니어 하게 증가 시키고 있습니다. 어떻게 된거죠 ?
또한 ..
1707라인에 주석으로 처리되어 있는
1707 * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd [/code]
이 내용이 의미하는 바는 무엇인가요?
congestion avoidance phase에서 왜 cwnd 값을 하나씩 증가 시키지 않고 위와 같이 증가시키는 건가요 ?
제가 알고 있는대로 라면 위의 코드는 잡다한 거 다 빼고 아래와 같이 되어야 할것 같은데요
1699 static __inline__ void tcp_cong_avoid(struct tcp_opt *tp)
1700 {
1701 if (tp->snd_cwnd <= tp->snd_ssthresh) {
1702 /* slow start 상태 exponetial하게 증가 */
1703 if (tp->snd_cwnd < tp->snd_cwnd_clamp)
1704 tp->snd_cwnd=tp->snd_cwnd*2;
1705 }
else //congestion avoidance 상태 리니어 하게 증가
{
1706 tp->snd_cwnd++;
1712 }
1716 tp->snd_cwnd_stamp = tcp_time_stamp;
1717 }
이렇게 되어야 할것 같은데...
추가질문 하나 더 드리자면
리눅스 커널에서 사용하는 TCP가 어느 버전 인가요?
tahoe? RENO 인가요 ?
new reno 인가요 ?
vegas 인가요 ?
아니면 ...
답변 부탁드립니다.
기본적으로 우선 cwnd <= ssthresh 인 상황에서는 지수적(exponetial)으로 증가하고
cwnd>ssthresh 인 상황에서는 리니어 하게 증가하게 되는데.
코드의 1701부터 1704의 경우가 슬로우 스타트 부분으로 지수적 으로 증가하는 코드는 맞습니다.
분석해 보자면.. 한개의 ACK가 올때마다 tp->snd_cwnd++; 를 하게됩니다.
즉 이전cwnd값이 10 이라 할때 한개의 ACK가 올때마다 cwnd는 1씩 증가하게 되어 10번째의 ACK까지 모두 받았을때는 10 이 증가하게 되어 결국 cwnd는 20(10+10) 이 되는거죠~ 그러면 20개의 패킷을 보낼수 있는거고, 또 그 20개의 패킷에 대한 각각의 ACK를 받을때마다 cwnd가 하나씩 증가하게 되어 모든 결국 다시 cwnd는 40이 되는거죠.. 즉 10==>20==>40 이렇게 지수적으로 증가 하게 되죠...
그리고 1706부터 1714부터는 혼잡회피 부분으로 리니어하게 증가되는 부분인데..
리니어 하게 증가한다는 것. 즉 " tp->snd_cwnd += 1 / tp->snd_cwnd" 이 말하는것은
현재 cwnd값이 10일경우 10개의 ACK를 모두 받았을때 tp->snd_cwnd++;를 하게됩니다. 그러면 다음 cwnd값은 11이 되겠죠?(하나의 ACK를 받을때 마다 10+1/10 이 증가하므로 10개의 ACK를 모두 받으면 10+1 이 되어 11이 되겠죠) 그리고 나서 11개의 패킷을 보낼수 있고 이 11개의 패킷을 모두 받았을때 cwnd를 1증가 하여 12가 되는것이죠~~ 10==>11==>12이렇게 리니어 하게 증가합니다.
마지막으로
Vegas는 Reno와는 좀 다른 식으로 혼잡제어를 하죠.
미리 혼잡부분을 예상하고 적절히 cwnd를 조절하는 방법으로..
암턴 리눅스 2.4는 Reno까지 지원 하고 있고요(New Reno도 자원할듯),
2.6부터 vegas가 지원되고 있습니다.
2.6에서 vegas를 enable시키기 위해서는 /proc/sys/net/tcp_vegas 등의 값을 설정하시면 됩니다.
도움이 되셨으면 좋겠습니다. ^^