engineering/Network Eng.2006. 8. 10. 13:53

지난 4번의 강좌를 통해 QoS의 전체적인 그림을 그려봤다. 이제부터는 세부적인 튜닝으로 들어가 QoS 혼잡예방을 위한 다양한 메커니즘에 대해 알아보자. 이번 호에는 TCP 프로토콜의 혼잡제어 메커니즘의 작동 방법과 테일 드롭시 어떤 문제점이 있는지, QoS에서는 어떻게 적용하는지 살펴볼 것이다. 특히 이론적으로 중요한 TCP 혼잡제어 메커니즘, 글로벌 싱크로나이제이션, RED, WRED 등에 대해 중점적으로 설명한다.

김화식 | 온세통신 시설운영팀 CCIE

QoS의 혼잡 회피(congestion avoidance) 메커니즘은 TCP 프로토콜이 네트워크 상에서 패킷손실 후 전송속도를 줄이는 TCP 혼잡제어 메커니즘을 기반으로 한다. 이는 큐에 혼잡이 발생하기 전에 미리 일부의 TCP 패킷을 드롭시킴으로 자연스럽게 큐에 들어오는 TCP 트래픽의 양을 줄어들게 만든다. 따라서 큐의 혼잡을 예방해 네트워크의 성능을 저하시키는 테일 드롭(tail drop)과 글로벌 싱크로나이제이션(global synchronization)이 발생하는 것을 미연에 방지한다. 결과적으로는 지연(delay)과 지터(Jitter)를 줄이는 역할을 수행하는 것이다.


TCP 프로토콜과 혼잡 제어
혼잡은 적정 수준 이상으로 큐에 패킷이 쌓여 있는 상태를 말하는데, 이는 주로 많은 양의 패킷이 들어오거나 과도한 쉐이핑 정책으로 인해 큐에 트래픽이 적체돼 있는 상태에서 발생한다(혼잡에 대한 자세한 내용은 QoS 강좌 1회를 참고하면 된다).
이렇게 혼잡이 발생한 상황에서 패킷이 더 들어오면 큐의 용량이 초과된다. 이때 큐의 용량을 초과해 버려지는 현상을 테일 드롭이라고 한다. 테일 드롭이 발생하면 해당 네트워크 상에 있는 대부분의 시스템 성능이 떨어지는데, 이를 두고 글로벌 싱크로나이제이션 현상이라고 한다. 그러면 테일 드롭은 왜 발생하고, 시스템 성능은 왜 저하되는 것일까. 그 이유는 TCP 혼잡제어 메커니즘을 자세히 살펴보면 알 수 있다.
초기에 TCP가 구현될 당시에는 패킷이 손실되거나 다른 이유로 인해 승인 패킷이 수신되지 않는 경우 RTO(Retransmission TimeOut) 만큼 기다렸다가 다시 전송을 시작하는 것이 거의 전부라고 할만큼 혼잡 제어의 개념은 거의 포함돼 있지 않았다.
물론, 당시의 네트워크 전송 속도나 전송되는 정보의 양은 지금과는 비교할 수 없을 정도로 적었기 때문에 그다지 필요성이 부각되지 않았다고 생각할 수 있다. 그러나, 인터넷의 사용이 증가하면서 인터넷 상의 라우터들을 연결하는 링크의 속도 차이로 인해 라우터 버퍼의 오버플로우(overflow)가 발생하고, 이로 인한 패킷 손실이 급격하게 증가하게 됐다. 만일 엔드 투 엔드로 연결이 돼 있을 때 수신측에서 허용 용량만 송신쪽에서 전송을 한다면 혼잡현상이 발생하지 않을 것이다.


TCP 슬로우 스타트와 TCP 혼잡 회피
어떤 TCP 연결이 초기 설정됐을 때 현재의 연결로는 어느 정도의 전송 속도를 수용할 수 있을지 전혀 알 수가 없다. 그렇다고 한꺼번에 많은 패킷들을 전송했다가 혼잡이 발생하면, 이는 더 큰 성능 저하의 요인이 된다. 따라서 현재 연결이 어느 정도의 전송 속도를 수용할 수 있는지를 파악하는 것(흔히 영문으로는 probe라는 용어를 사용한다)은 대단히 중요한 일이다. 이는 TCP 슬로우 스타트(slow start) 알고리즘을 이용하면 가능하다.



(그림 1)을 보면 연결이 설정된 후, 송신원은 초기 cwnd(congestion window: 혼잡 윈도우)를 1로 설정해 패킷 1을 전송한다(실제 TCP는 바이트 단위로 동작한다. 그러나, 설명을 쉽게 하기 위해 여기서는 패킷의 크기가 모두 동일하고, 바이트 대신 일련의 번호로 구분되는 것으로 설정했다).
패킷 1을 수신했다는 하나의 승인패킷(ACK)을 수신하면, 송신원은 cwnd를 1 증가시키므로 두 개의 패킷 2~3이 전송된다. 이 후 2개의 승인패킷(ACK)을 수신하면 다시 cwnd를 2 증가시키므로 네 개의 패킷이 전송될 수 있고, 이와 같은 방식으로 승인패킷(ACK)이 하나 수신될 때마다 계속 윈도우의 크기를 1만큼 증가시키게 된다.
즉, 슬로우 스타트 동안 송신원은 하나의 승인패킷(ACK)을 수신할 때마다 윈도우를 1 증가시키기 때문에 결과적으로는 하나의 승인 패킷을 수신할 때마다 두 개의 추가적인 패킷을 전송할 수 있게 된다. 슬로우라는 말과는 달리 실제로 윈도우는 지수적으로(exponentially) 빠르게 증가하는 것이다.
슬로우 스타트 상태에서의 윈도우는 지수적으로 계속 증가하는데, 윈도우의 크기가 임계 값(ssthresh: slow-start-threshold)과 같아지면 TCP 혼잡 회피가 시작된다(초기 ssthresh 값은 64K로 설정된다). 슬로우 스타트와는 달리 TCP 혼잡 회피 상태에서는 하나의 승인패킷(ACK)은 혼잡 윈도우의 크기를 1씩 증가시킨다. 예를 들어 cwnd의 값이 10인 상태에서 10개의 패킷이 안전하게 전송됐다는 승인 패킷을 수신하면, cwnd의 값을 11로 증가시킨다. 중요한 점은 혼잡 회피에서의 cwnd의 값은 슬로우 스타트에 비해 훨씬 느린 속도로 증가한다는 것이다.





(그림 2)는 TCP 슬로우 스타트와 TCP 혼잡 회피 상황에서 윈도우의 크기 변화를 표현한 것이다. (그림 2)를 보면 TCP 슬로우 스타트 상황일 때에 비해 윈도우의 크기가 완만하게 증가되는 것을 볼 수 있다.


TCP 혼잡 제어 메커니즘
송신원의 상태가 TCP 슬로우 스타트 상태에 있건, 아니면 TCP 혼잡 회피 상태에 있건 현재 연결이 유지되고 이를 통해 패킷들이 전송되는 한, 윈도우는 지속적으로 증가하고 언젠가는 혼잡으로 인한 패킷 손실이 발생하게 된다. 따라서 이를 복구하기 위한 기능이 TCP 혼잡 제어 메커니즘이다.
TCP 프로토콜에서 패킷이 전달되는 과정을 쉽게 설명하면 처음 TCP 세션이 연결된 후 전송을 시작할 때, 처음 윈도우 크기를 1로 설정해 전송을 시작하며, 타임아웃(retransmission timeout: RTO)이 발생하기 전에 승인 패킷(ACK)을 수신할 경우에는 윈도우의 크기를 2배로 증가시킨 후 전송한다.
만일 타임아웃이 발생할 때까지 승인 패킷(ACK)을 수신하지 못하면, 임계값(ssthresh)을 윈도우 크기의 반으로 설정을 하고, 윈도우 크기를 1로 재전송을 시작한다. 이후 윈도우 크기를 2배씩 증가시키다가 윈도우 크기가 임계값보다 커지면 윈도우 크기를 1씩 증가시킨다.

(그림 3)은 TCP의 동작을 보여주고 있다. 1로 표시된 구간은 TCP 슬로우 스타트에 해당되며, 2로 표시된 구간은 TCP 혼잡 회피에 해당된다.





·TCP 송신원이 타임아웃 이전에 ACK 수신할 때
  if CWND ( Threshold --> CWND = 2 * CWND
  if CWND > Threshold --> CWND = CWND + 1


· TCP 송신원이 타임아웃 이전에 ACK 수신하지 못할 때   
  Threshold = CWND / 2
  CWND = 1



네트워크의 불안요소 '글로벌 싱크로나이제이션'
TCP가 동작하는 모습을 살펴보면 네트워크의 전송상태가 좋을 경우에는 트래픽을 많이 전송하고, 패킷 손실이 발생하면 전송하는 트래픽의 양을 줄이는 것을 알 수 있다. 이 사실만으로 본다면 TCP는 상당히 똑똑한 프로토콜이라고 할 수도 있다. 하지만 바로 이런 TCP의 혼잡제어 메커니즘 때문에 사실은 또 다른 문제가 발생할 수 있다.
예를 들어, 일반적인 소규모의 네트워크 구성을 생각해보자. 라우터에 외부 네트워크가 연결돼 있고 내부에는 스위치 아래에 호스트 PC들이 연결돼 있다. 모든 호스트 PC들은 라우터를 통해서 외부 네트워크와 연결돼 있다. 동시에 여러 PC들이 인터넷을 접속하게 되면 TCP의 동작 상황에 따라 라우터의 출력 인터페이스 버퍼(buffer)에는 여러 개의 TCP 플로우가 존재하게 된다. 이럴 경우 큐 사이즈는 빠른 속도로 증가하게 되며, 이내 버퍼 풀(buffer full)이 발생하고, 오버플로우가 발생하게 된다.
그러면, 모든 TCP 플로우들은 버퍼 풀 이후에 도착한 모든 패킷들을 잃게 되며(테일 드롭 발생), 모든 호스트 PC들은 타임아웃이 발생할 때까지 잃어버린 패킷들에 대한 ACK를 받지 못하게 된다.
결국, 모든 호스트 PC들은 자신의 전송 속도를 줄이게 되며(윈도우의 크기를 1로 줄인다) 빠른 속도로 큐 사이즈는 줄어들게 된다. 그러나, 다시 슬로우 스타트 과정으로 인해 큐 사이즈는 증가하게 되고, 오버플로우가 발생하며, 모든 TCP 플로우에 대해 동일한 과정이 반복되게 된다. 이런 현상을 글로벌 싱크로나이제이션(Global Synchronization)이라 하는데, 트래픽 양의 급격한 출렁거림으로 인해 성능은 물론 네트워크 장비가 불안정해지는 원인이 된다.


글로벌 싱크로나이제이션 해결 방법 1 : RED
실제로 글로벌 싱크로나이제이션은 네트워크에 심각한 문제를 유발시킨다. 물론 QoS 측면에서는 더더욱 안 좋은 현상이기도 하다. 가장 큰 문제는 지연과 지터가 커진다는 것이다. QoS에서는 글로벌 싱크로나이제이션 현상을 해결하기 위해 RED(Random Early Detection), WRED(Weighted Random Early Detection) 등을 사용한다.

(그림 4)는 RED를 적용하기 전과 적용한 후의 TCP 트래픽 흐름이 어떻게 차이가 나는지 보여주는 그림이다. RED는 TCP 동작 특성을 이용한 대표적인 혼잡 제어 기법으로, 이름이 암시하는 것처럼, 혼잡이 발생하기 이전에 미리 랜덤한 방식으로 패킷을 버림으로써 특정한 TCP 플로우로 하여금 전송 속도를 줄이게 하는 방법이다. 기본적인 동작은 큐에 두 개의 쓰레시홀드 TH_min과 TH_max를 두고 세 구간에 서로 다른 드롭 확률을 적용하는 것이다.



RED의 동작 과정은 다음과 같다(그림 5).




① 평균 큐 사이즈(AQS: Average Queue Size)가 TH_min보다 작은 경우에는 어떤 패킷도 버리지 않고 모두 받아 들인다.

② 큐 사이즈가 TH_min보다는 크지만 TH_max보다는 작은 경우 큐 사이즈에 따라 특정한 확률값을 갖고 패킷을 버린다.

③ 큐 사이즈가 TH_max보다 큰 경우는 입력되는 모든 패킷을 버린다. 즉, 혼잡의 정도가 심해질수록 많은 패킷을 버림으로써 입력되는 트래픽의 양을 줄이려는 방법이다.


일반적으로, TH_max 값이 너무 작으면 패킷 드롭이 빈번히 발생해서 전체 성능에 심각한 영향을 줄 수도 있으며, TH_max 이상에서 모든 입력되는 패킷을 버리는 동작이 버퍼 오버플로우에 의한 결과와 동일하기 때문에 TH_max를 큐의 최대 크기와 같거나 가까운 값으로 설정을 하게 된다. 또한, p(드롭 가능성)의 값이 너무 작으면 패킷이 드롭되는 빈도가 낮아져 혼잡 제어 효과가 제대로 나타나지 않을 수도 있다. 따라서, RED를 사용할 때는 TH_min, TH_max, 그리고 p 값을 적절하게 설정해 주는 것이 중요하다.


RED를 진일보시킨 'WRED'
RED를 적용함으로써 글로벌 싱크로나이제이션 현상은 예방할 수 있다. 하지만 랜덤하게 패킷을 버리기 때문에 중요한 패킷이 버려질 수 있는 단점이 있다. 이런 문제점을 해결하기 위해 버려질 수 있는 확률에 대한 가중치를 부여했다. 즉, WRED는 하나 혹은 여러 개의 서로 다른 클래스 트래픽에 서로 다른 특성을 갖는 RED를 적용함으로써 혼잡 제어를 하는 것을 말한다. 서로 다른 특성을 갖는 RED라는 것은 TH_min, TH_max, 그리고 max p 값이 서로 다른 RED 패킷 드롭 확률을 말한다.
동일한 클래스 트래픽에 WRED를 적용하는 경우는, 같은 클래스에 속한 서로 다른 우선순위의 패킷들에 서로 다른 RED를 적용하게 된다. 예를 들면, DiffServ의 AFx 클래스의 경우, 동일한 클래스에 3개의 서로 다른 드롭 우선권(drop precedence)이 존재하는데, 각각의 드롭 우선권에 대해 서로 다른 RED를 적용할 수 있다.

(그림 6)은 WRED 패킷 드롭 확률의 일례를 보여주고 있다. 이 그림은 DiffServ의 어떤 클래스 트래픽에서 파랑색과 빨간색으로 마크된 패킷들에 대해 서로 다른 RED를 적용할 수 있음을 보여주고 있다.





(그림 6)에서 볼 수 있듯이 낮은 우선순위의 패킷 혹은 클래스에 대해서는 더욱 공격적인 패킷 드롭이 발생하며, 우선순위가 높은 패킷 혹은 클래스에 대해서는 보수적인 패킷 드롭이 발생된다. 그림에서는 우선순위가 낮은 A에 대한 TH_max가 Z에 대한 TH_min보다 크게 설정된 경우를 보여주고 있으나, A에 대한 TH_max가 Z에 대한 TH_min보다 반드시 작거나 같아야 하는 조건을 줄 수도 있다.
비록 같은 클래스에 속한 패킷들이지만, 드롭 우선순위가 다르며, 서로 다른 RED가 적용된다. (그림 6)에서 큐에 10개의 패킷이 들어있는 상태에서 새로운 패킷이 들어왔을 경우 새로 들어온 패킷이 빨간색이라면 렌덤하게 드롭이 되겠지만, 파란색 패킷이 들어오면 정상적으로 서비스를 하게 된다.
또, 큐에 패킷이 30 이상 들어있는 상태에서는 빨간색 패킷은 100% 드롭되며, 나머지의 여유공간은 파란색 패킷이 서비스되는 것이다. 즉, 중요한 트래픽을 파란색으로 규정하고, 중요하지 않은 트래픽을 빨간색으로 규정해 서로 다른 우선순위를 부여함으로써 차별화 된 서비스를 제공할 수 있게 되는 것이다.
IP 우선권을 기준으로 WRED를 구성할 때는 8개의 WRED 설정이 가능하며, DSCP를 기준으로 WRED를 구성할 때는 64개까지의 WRED 설정이 가능하다.

실전! 연습문제


그럼 이제부터 연습문제를 풀어보면서 WRED 설정에 대해 알아보자.

<연습 문제>

(그림 7)에서 R3는 프레임 릴레이 128Kbps로 연결돼 있다. 다음의 조건을 만족하도록 R3에 설정하라.




① E0/0에서 들어오는 VoIP 패킷은 DSCP EF 코드를 사용해 CB 마킹하고, 전용큐를 사용해 58Kbps의 대역폭을 할당하며, WRED는 적용하지 말아라.


② E0/0에서 들어오는 HTTP 트래픽 중 URL에 "important"가 들어가는 패킷은 DSCP AF21 코드를 사용해 CB 마킹하고, 전용큐를 사용해 20Kbps의 대역폭을 할당하며, WRED를 적용하라.


③ E0/0에서 들어오는 HTTP 트래픽 중 URL에 "not-so"가 들어가는 패킷은 DSCP AF23 코드를 사용해 CB 마킹하고, 전용큐를 사용해 8Kbps의 대역폭을 할당하며, WRED를 적용하라.


④ E0/0에서 들어오는 나머지 패킷은 DSCP BE 코드를 사용해 CB 마킹하고, 전용큐를 사용해 20Kbps의 대역폭을 할당하며, WRED를 적용하라.


<연습 문제에 대한 설명>


CB 마킹(Class-Based Marking) 설정 순서는 다음과 같다.


① Class-map match-all/any 명령어를 이용해 클래스를 설정한다.

② policy-map 명령어를 이용해 적용할 정책을 설정한다.

③ 2번에서 만든 policy-map 이름을 적용하고자 하는 인터페이스에서 service-policy 명령어를 이용해 적용한다.

<연습문제 해결 : WRED 설정>

ip cef  
!                                                              → S0/0에 LLQ를 생성하는 과정
Class-map match-all dscp-ef                → dscp-ef 라는 Class-map 생성
  match ip dscp ef  
Class-map match-all dscp-af21             → dscp-af21 라는 Class-map 생성
  match ip dscp af21  
Class-map match-all dscp-af23             → dscp-af23 라는 Class-map 생성
  match ip dscp af23  
  !                                                           → E0/0에서 들어오는 트래픽에 대한 BC마킹 과정
Class-map match-all http-impo              → http-impo라는 Class-map 생성
  match protocol http url "*important*"  
Class-map match-all http-not                 → http-not라는 Class-map 생성
  match protocol http url "*not-so*"  
Class-map match-all class-default         → class-default라는 Class-map 생성
  match any                                             → 나머지 모든 트래픽들은 class-default에 적용
Class-map match-all voip-rtp                  → voip-rtp 라는 Class-map 생성
  match ip rtp 16384 16383                       → VoIP 트래픽을 구분
!                                                               → E0/0에 들어오는 부분에 적용할 정책 생성하는 과정
Policy-map laundry-list                           → laundry-list 라는 Policy-map 생성
  class voip-rtp                                       → 기 작성한 'voip-rtp' 라는 class-map을 소환
    set ip dscp ef                                      → voip 패킷에 대하여 DSCP 값을 EF로 설정
  class http-impo  
    set ip dscp af21  
  class http-not  
    set ip dscp af23  
  class class-default  
    set ip dscp default  
!                                                              → S0/0에 나가는 부분에 적용할 WRED 정책 생성하는 과정
Policy-map queue-on-dscp                   → queue-on-dscp라는 Policy-map 생성
  class dscp-ef                                      → 기 작성한 'dscp-ef' 라는 class-map을 소환
    priority 58                                           → LLQ 설정 부분(최우선순위 설정)
  class dscp-af21                                  → 기 작성한 'dscp-af21'라는 class-map을 소환
    bandwidth 20                                      → 대역폭을 20Kbps로 설정
    random-detect dscp-based              → dscp-base WRED 적용부분
  class dscp-af23  
    bandwidth 8  
    random-detect dscp-based  
  class class-default  
    fair-queue  
    random-detect dscp-based  
!  
interface Ethernet0/0  
  ip address 192.168.3.253 255.255.255.0  
  ip nbar protocol-descovery                  → nbar를 적용함
  service-policy input laundry-list           → 기 작성한 'laundry-list' 정책을 적용함
!  
interface Serial0/0  
  no ip address  
  bandwidth 128  
  encapsulation frame-relay  
  load-interval 30  
  max-reserved-bandwidth 85  
  service-policy output queue-on-dscp  → 기 작성한 'queue-to-point' 정책을 적용함
  clockrate 128000  
!  
interface Serial0/0.1 point-to-point  
  ip address 192.168.2.253 255.255.0  
  frame-relay interface-dlci 101  


<WRED 설정 확인>


R3# show policy-map int s0/0      
     
Serial0/0      

service-policy output: queue-on-dscp      
     
  Class-map:  dscp-ef  (match-all)      
  46437 packets, 2971968 bytes      
  30 second offered rate 0 bps, drop rate 0 bps      
  Match: ip dscp ef      
  Weighted Fair Queueing      
     Strict Priority      
     Qutput queue: Conversation 264      
     Bandwidth 58 (kbps) Burst 1450 (Bytes)      
     (pkts matched/bytes matched) 42805/2739520    
     (total drops/no-buffer drops) 0/0      
     
  Class-map:  dscp-af21  (match-all)      
  2878 packets, 3478830 byte      
  30 second offered rate 76000 bps, drop rate 0 bps    
  Match: ip dscp af21      
  Weighted Fair Queueing      
     Qutput queue: Conversation 266      
     Bandwidth 20 (kbps)      
     (pkts matched/bytes matched) 2889/3494718    
     (depth/total drops/no-buffer drops) 11/26/0    
      exponential weight: 9      
      mean queue depth: 5      
     
dscp Transmitted Random drop Tail drop Minimum Maximum Mark
pkts/bytes pkts/bytes pkts/bytes thresh thersh prob
af21 2889/3494718 8/9904 18/21288 32 40 1/10
     
  Class-map:  dscp-af23  (match-all)      
  1034 packets, 1250984 byte      
  30 second offered rate 32000 bps, drop rate 0 bps    
  Match: ip dscp af23      
  Weighted Fair Queueing      
     Qutput queue: Conversation 267      
     Bandwidth 8 (kbps)      
     (pkts matched/bytes matched) 1047/1266140    
     (depth/total drops/no-buffer drops) 11/46/0    
     exponential weight: 9      
     mean queue depth: 5      
     
dscp Transmitted Random drop Tail drop Minimum Maximum Mark
pkts/bytes pkts/bytes pkts/bytes thresh thersh prob
af23 1047/1266140 13/18252 33/34083 24 40 1/10
     
  Class-map:  dscp-default  (match-any)      
  847 packets, 348716 byte      
  30 second offered rate 2000 bps, drop rate 0 bps    
  Match: any      
  Weighted Fair Queueing      
     Flow Based Fair Queueing      
     Maximum Number of Hashed queues 256      
     (total queued/total drops/no-buffer drops) 0/0/0    
      exponential weight: 9      
     
dscp Transmitted Random drop Tail drop Minimum Maximum Mark
pkts/bytes pkts/bytes pkts/bytes thresh thersh prob
default 59/767 0/0 0/0 20 40 1/10



이번에 풀어본 연습문제는 상당히 복잡하므로, 지금까지 배워왔던 내용들을 잘 숙지하고 있어야 성공적으로 해결할 수 있을 것이다. CB 마킹을 이용한 이유는 명령어를 적용하는 형식에 익숙해지도록 유도하기 위해서였다. 이 CB 구조는 실무에서 요구되는 거의 모든 조건에 적용할 수 있기 때문에, 이 문장의 구조에 익숙해지면 상당한 실력을 요구하는 문제라도 쉽게 풀어낼 수 있을 것이다. 다음호에는 QoS에서 사용되는 또 다른 튜닝기법인 LE(Link Efficiency) 매커니즘에 대해 알아볼 것이다.

출처 - http://www.ionthenet.co.kr

Posted by theYoungman