리눅스

리눅스/네트워크 대역폭 제한 - 트래픽 셰이핑(Traffic Shaping)

우진샘 2010. 4. 14. 14:55

출처 : http://bebop.emstone.com/projects/sentry24/artnlife/network_traffic_shaping/view?set_language=en

목적

(현재 기능에 한함)네트워크 트래픽 셰이핑의 사용 목적은 네트워크 환경이 좋지 않은 곳에서나 관리자의 정책에 따라 dvr의 네트워크 업로드 대역폭을 조절하므로 과도한 네트워크 점유를 피하도록 구현하는데 있다.

트래픽 셰이핑이란?

트래픽 셰이핑(Traffic Shaping)은 성능이나 빠른 응답시간 등을 보장하고 최적화하기 위해 네트워크 소통량(traffic)을 제어하는 것을 말한다. P2P 프로그램을 사용해본 사람은 경험해 보았듯이, 보통 download의 전송률은 제한을 두지 않고, upload의 전송률을 제한하고는 하는데, 쉽게 말하면 이런 것을 트래픽 셰이핑이라고 한다.

트래픽 셰이핑을 이용하면 단순히 대여폭을 제어하는 것 뿐 아니라, 전송률(rate)을 조절하여 패킷 끊김(jitter), 패킷 손실(loss), 반응시간(low latency) 등을 최적화할 수 있다. 예를 들어 트래픽 셰이핑을 하기 전과 후의 패킷 전송 동작을 초단위로 표현하면 다음과 같다.

트래픽 셰이핑 이전

  10  0 10  0 10  0 10  0 10  0

트래픽 셰이핑 이후

   5  5  5  5  5  5  5  5  5  5

네트워크 연결별로 우선 순위가 필요한 경우도 정책(policy)을 통해 조절할 수 있다. 예를 들어 FTP 데이터 전송과 SSH 접속을 동시에 진행할 경우 대량의 FTP 데이터 전송으로 SSH 터미널 연결이 지연되는 현상이 발생하는데, 이런 경우 셰이핑 기능을 이용하면 SSH 연결의 우선순위를 높여 소통을 원활하게 할 수 있다.

트래픽 셰이핑에 사용되는 개념 및 방법

Classification, Queueing, Scheduling

HTB (Hierarchical Token Bucket)
HTB는 대역폭을 각각의 queue에 나누어주는 시스템이다. 대역폭은 보장하지만 interactive는 보장하지 않는다. 왜냐하면 패킷 갯수를 세지않고, 바이트 수를 세기때문이다.

qdisc라는 것이 사용되는데 각 우선순위 마다 부여되는 queue를 말한다.
root qdisc는 하나의 클래스를 가질 수 있다. 물론 여러개의 클래스를 가질 수도 있다. 이 하나의 HTB 클래스는 rate와 ceil 두개의 인수로 설정이 된다. 이 값들은 최상위 크래스를 위한 것이라고 할 수 있으며 링크에 대한 최대 가능한 대역폭을 나타낸다.
HTB에서 rate는 클래스를 위한 대역폭을 보장하는 값이며 ceil은 ceiling의 줄임말로 클래스가 최대로 사용할 수 있는 대역폭을 의미한다. 따라서 최상위 레벨에서는 이 두가지는 같은 의미이다.
자식 클래스의 수는 이 클래스 밑으로 생성할 수 있는데, 이 클래스들은 부모 클래스로 부터 가능한 대역폭을 할당받는다. 자식 클래스에서 부터는 rate와 ceil은 더이상 같은 값은 아니며 특정한 대역폭을 예약하고 가능한 대역폭의 분배율을 계산해서 클래스들에 허용한다.
HTB(Hierarchical Token Bucket)는 사용자로 하여금 절대적인 대역폭을 조절하고 여분의 대역폭에 대해 정해진 비율로 계산하여 우선순위에 따라 각 클래스에 할당한다.

CBQ (Class based Queueing)

네트워크 트래픽을 서비스 타입(FTP, SMTP or HTTP)이나 목적지에 따라 클래스들로 나눈다. 각각의 클래스들은 FIFO 기반의 큐에 할당되며 각각의 큐들에게는 클래스에 정의된 특정한 대역폭이 할당된다. CBQ와 HTB의 가장 큰 차이는 ceiling 기능의 유무이다. CBQ는 대역폭이 여유가 생기더라도 해당 클래스에 정해놓은 대역폭 이상은 절대 사용할 수 없다.

SFQ (Stochastic Fairness Queueing)

지정한 큐로 들어오는 모든 트래픽에 대하여 큰 queue를 사용하여 공평하게 다룬다. 트래픽이 full일 경우에 적용된다.

네트워크 셰이핑 방법

셰이핑을 하기 위한 몇가지 방법을 소개하면 다음과 같다.

  • Port

P2P 프로그램이 사용하는 port의 우선순위를 낮출 수 있지만 사용자가 다시 P2P프로그램의 포트를 바꾸면 소용이 없다.

  • Packet size

패킷 크기를 이용하여 큰 패킷의 우선순위를 낮출 수 있다. 하지만 사용자가 MTU(전송될 수 있는 최대크기의 패킷)를 조정하면 작은 패킷을 내보낸다.

  • Traffic type

네트워크 트래픽 셰이핑의 예 

만약 두개의 인터페이스를 가진 리눅스 머신이 있다고 하자.
DSL-modem - ip: 192.168.2.1
Linux box ip - eth0: 192.168.1.1, eth1: 192.168.0.2.2 and gateway: 192.168.2.1
clients - ip: 192.168.1.16, 192.168.1.17, 192.168.1.18 and gateway: 192.168.1.1

1. 패킷이 클라이언트 192.168.1.16을 떠난다.
2. 패킷이 gateway eth0 (192.168.1.1)에 도착한다.
3. gateway는 output queue를 통해 패킷을 보낸다.
4. 패킷이 gateway eth1 (192.168.2.2)에서 떠난다.
5. 패킷이 DSL-modem (192.168.2.1)에 도착한다.
6. 패킷이 DSL-modem의 output queue에 들어간다.
7. 패킷이 DSL-modem을 떠난다.

DSL-modem의 경우 upload 속도는 128kbit이다. 이것은 리눅스 박스가 DSL-modem을 통해서는 데이타를 보낼 수 없다는 말이다. DSL-modem보다 빠른 것은 upload 할 수 있다. 그렇다고 DSL-modem의 동작을 직접 컨트롤 할 방법이 없기때문에, DSL-modem의 output queue를 리눅스 박스로 옮겨와야 한다. 이것이 트래픽 셰이핑을 적용하는 것이다. 이것은 DSL-modem으로 내보내는 eth1의 출력 속도를 DSL-modem의  upload 속도보다 낮춤으로 가능하다. 즉 queue가 옮겨지는 것이다.

구현

tc 라는 프로그램을 사용하여 간단하게 네트워크 트래픽 셰이핑을 시도한다.

  • 우선순위 등의 고려를 제외하고 전체 대역폭만 다루도록 한다. 클래스를 하나만 생성함.
  • eth0, eth1 등 네트워크 인터페이스 별로 최대 전송률을 설정할 수 있는 UI를 구현한다.
  • 추가될 커널 옵션은 무엇인가?
    • 다음과 같은 커널 옵션을 적용하여 테스트 중이다.
Networking --> Networking options
[*] Network packet filtering
QoS and/or fair queueing -->
<M> HTB packet scheduler
<M> SFQ queue
[*] Packet classifier API
<M> Firewall based classifier
<M> U32 Classifier
[*] Traffic policing



테스트 할 스크립트는 다음과 같다. wondershaper라는 스크립트를 응용하였다.

#!/bin/sh

if [ $# == 0 ]; then
  echo Please read the man page for the wondershaper and
  echo the file /usr/share/doc/wondershaper/README.Debian
  exit
fi

if [ $# == 1 ]; then
  tc -s qdisc ls dev $1
  tc -s class ls dev $1
  exit
fi

if [ "$2" == "del" ]; then
  tc qdisc del dev $1 root    2> /dev/null > /dev/null
  echo Wondershaper queues have been cleared.
  exit
fi

# please read the README before filling out these values
#
# Set the following values to somewhat less than your actual download
# and uplink speed. In kilobits. Also set the device that is to be shaped.
UPLINK=$2
DEV=$1

#########################################################

# clean existing down- and uplink qdiscs, hide errors
tc qdisc del dev $DEV root    2> /dev/null > /dev/null

###### uplink

# install root HTB

tc qdisc add dev $DEV root handle 1:0 htb default 15

# main class

tc class add dev $DEV parent 1:0 classid 1:1 htb rate ${UPLINK}kbit

# high prio class 1:5

tc class add dev $DEV parent 1:1 classid 1:5 htb rate $(($UPLINK/2))kbit \
    ceil ${UPLINK}kbit prio 2

# bulk and default class 1:10 - gets slightly less traffic,
#  and a lower priority:

tc class add dev $DEV parent 1:1 classid 1:10 htb rate $(($UPLINK/2))kbit \
    ceil ${UPLINK}kbit prio 6

# 'traffic we hate'

tc class add dev $DEV parent 1:1 classid 1:15 htb rate $(($UPLINK/2))kbit \
    ceil ${UPLINK}kbit prio 10

# all get Stochastic Fairness:
tc qdisc add dev $DEV parent 1:5 handle 5: sfq perturb 10
tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev $DEV parent 1:15 handle 15: sfq perturb 10


HTB를 사용할 것인지 CBQ를 사용할 것인지, fair정책을 사용할 것인가?
CBQ는 HTB보다 설정이 복잡하다. 굳이 CBQ를 사용할 이유는 없다. fair 정책은 클래스가 여러개일때 필요하다. 클래스를 한개만 사용할 것이므로 무의미할 것 으로 보인다.

테스트

최종적으로 사용한 명령어는 다음과 같다. 최상위 클래스 만 생성하여 대역폭을 제한해보았다. (DEV - eth0, eth1...)

tc qdisc add dev $DEV root handle 1:0 htb default 1
tc class add dev $DEV parent 1:0 classid 1:1 htb rate ${UPLINK}kbit

첫번째 명령어에서 1:0은 커널 레벨의 qdisc를 의미한다. 그 qdisc에 root 클래스를 하나 생성하여 UPLINK라는 인수를 받아 대역폭 제한 명령을 한다.

./test_script eth0 512

커널은 위에서 제시한 옵션을 적용하였으며 위 명령을 실행시 sch_htb 라는 모듈이 올라간다.

[root@sentry24 root]# lsmod | grep htb
sch_htb                15360  1

대역폭을 512kbps 이하로 적용한 결과이다.

[root@sentry24 root]# ./test_script eth0
qdisc htb 1: r2q 10 default 1 direct_packets_stat 0
 Sent 15319 bytes 123 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
class htb 1:1 root prio 0 rate 512000bit ceil 512000bit burst 2239b cburst 2239b
 Sent 15789 bytes 126 pkt (dropped 0, overlimits 0 requeues 0)
 rate 2880bit 3pps backlog 0b 0p requeues 0
 lended: 126 borrowed: 0 giants: 0
 tokens: 33794 ctokens: 33794

트래픽 셰이핑을 해제하려고 할 때는 다음과 같이 명령한다.

> tc qdisc del dev eth0 root

참고 : http://wiki.kldp.org/wiki.php/Adv-Routing-HOWTO

'리눅스' 카테고리의 다른 글

리눅스/대용량 파일 시스템 포멧(Format)  (0) 2010.11.04
리눅스/vi(vim)을 Source Insight 처럼 사용하기  (0) 2010.07.01
리눅스/NFS 설치하기  (0) 2010.01.07
리눅스/압축 tar  (0) 2010.01.06
리눅스/ssmtp  (0) 2009.12.29