2013년 2월 26일 화요일

패킷사이즈가 MTU 1500 바이트를 넘는 경우는 ?

저번 포스팅에서 MTU 에 대해서 설명을 드렸습니다. 그런데 가끔 패킷 덤프를 하다보면 MTU 이상의 패킷 사이즈를 보는 경우가 있습니다. 이건 무엇이지 하고 의아해할 수 있는 것이죠. 이를 설명드리기 위해 패킷 전송과 관련한 이야기를 조금 더 해볼께요.

10G 네트워크 링크를 사용하는 경우 1500 바이트 MTU 로 계산하면 대략 초당 800,000 가까이 됩니다. 이것은 결국 패킷처리를 위해 CPU 오버헤드를 가져올 수 있게 됩니다. 이런 오버헤드를 줄이기 위해 MTU 를 늘리면 될것 같습니다. 자 점보프레임인 9000 바이트로 늘리면 한번에 더 큰 패킷을 처리할 수 있습니다. 그런데 문제는 인터넷에 연결되어 있는 모든 구간이 이 MTU 값을 사용하지 않는다는데 있습니다. 보통의 경우는 1500 바이트 이내일 것이죠. 내부 네트워크라면 모르지만 인터넷 구간에서는 현실적으로 사용이 힘들어집니다.

그래서 네트워크 어뎁터에서 채용하기 시작한 것이 TCP 세그먼테이션 오프로드 기능입니다. TSO 로도 불리기도 하죠. TSO 호환 가능 어뎁터는 커널상에서 아웃바운드 데이터에 대해 보다 큰 패킷데이터를 처리할 수 있습니다. 즉, 밖으로 패킷을 보낼때 데이터를 재-세그먼트 하여 작게 보내게 된다는 것이죠. 이것은 호스트 컴퓨터의 CPU 자원 사용면에서도 효율적이게 됩니다. TSO 외 GSO(Generic segmentation offload)도 있습니다. GSO 는 TCP 에만 한정을 두지 않는다는 장점이 있지만 데이터 전송에서만 동작하고 받는쪽에서는 동작하지 않습니다. 이 부분에 대한 솔루션 형태의 하나로 LRO(Large Receive Offload) 가 있습니다. 들어오는 패킷에 대해 한번에 Merge 를 하게 되는 것입니다. 리눅스 기반의 10G 드라이버들이 이 LRO 를 넓게 채용하고 있기도 합니다.

이전 포스팅에서도 이 오프로드에 대해서 언급한 적이 있는데 좀더 궁금하신 분들은 다음 글을 참고하시기 바랍니다.

TOE(TCP offload engine)란 무엇인가?



자, 오프로드를 언급했는데 바로 오늘 제가 여러분들에게 설명드릴 MTU 이상의 크기가 이것과 연관되어 있습니다. 다음과 같이 ethtool 을 통해 네트워크 인터페이스의 정보를 확인해 보겠습니다.


# ethtool -k eth0
Offload parameters for eth0:
rx-checksumming: on
tx-checksumming: off
scatter-gather: off
tcp-segmentation-offload: off
udp-fragmentation-offload: off
generic-segmentation-offload: off
generic-receive-offload: on
large-receive-offload: off
rx-vlan-offload: on
tx-vlan-offload: on
ntuple-filters: off
receive-hashing: off

generic-receive-offload 가 on 되어 있는 것이 보입니다. 오프로드 기능이 동작하여 패킷을 덤프할 시에 패킷의 사이즈가 다르게 보였던 것입니다. 아래 그림을 한번 보시죠.

GRO 기능이 On 되어 있는 경우는 그림과 같이 패킷 사이즈가 2762, 4017, 3538 과 같이 MTU 값 이상으로 크게 나타납니다.

[그림] GRO 기능 On

그러나 gro 기능을 off 하고 패킷 캡쳐를 다시 해보면 패킷 데이터 전송크기가  1414로 동일하게 나타납니다.


# ethtool -K eth0 gro off
# ethtool -k eth0
Offload parameters for eth0:
rx-checksumming: on
tx-checksumming: off
scatter-gather: off
tcp-segmentation-offload: off
udp-fragmentation-offload: off
generic-segmentation-offload: off
generic-receive-offload: off
large-receive-offload: off
rx-vlan-offload: on
tx-vlan-offload: on
ntuple-filters: off
receive-hashing: off


[그림] GRO 기능 off


네트워크 어뎁터에서 처리해 주었기 때문에, 패킷 캡쳐 프로그램에서는 크기가 큰 패킷 사이즈를 볼 수 있었던 것입니다.

MTU 보다 패킷 크기가 크게 나왔던 이유가 바로 오프로드 기능이 있었던 것이었죠.
좀더 많은 내용은 다음 '참고'를 확인해 보세요.

[참고]

1. 점보프레임(Jumbo Frame)으로 전송속도 높이기
http://www.packetinside.com/2012/03/jumbo-frame.html
2. Ethtool 을 통해 네트워크 카드(NIC) 정보 확인 또는 설정하기
http://www.packetinside.com/2012/04/ethtool-nic.html
3. 윈도우에서 네트워크 드라이버 설정 정보 보기 (TOE, 점보프레임등 확인)
http://www.packetinside.com/2012/05/toe.html
4. 패킷 전송 크기를 지정하는 MTU(Maximum Transmission Unit)를 알아봅시다!
http://www.packetinside.com/2013/02/mtumaximum-transmission-unit.html

2013년 2월 19일 화요일

패킷 전송 크기를 지정하는 MTU(Maximum Transmission Unit)를 알아봅시다!

최근 저에게 질문을 주신분인 계신데 그와 관련하여 몇 가지 글들을 써보고자 합니다. 저도 깊게는 생각해 보지 않다가 네트워크 전송 과정을 좀더 깊게 들여다 볼 수 있을거 같아 적어보고자 합니다. 오늘은 그 첫번째로 MTU 에 대해서 알아보도록 하겠습니다.

MTU 란 무엇인가?


MTU(Maximum Transmission Unit)는 네트워크 인터페이스에서 세그먼트 없이 보낼수 있는 최대 데이터그램 크기 값입니다. 만약 데이터가 MTU 값 이상이라면 여러개의 패킷으로 분할이 될 것입니다. 간단하게 보자면 MTU 는 패킷이 한번에 보낼 수 있는 최대 크기라고 볼 수 있습니다.

우리가 주로 사용하는 이더넷의 MTU 값은 일반적으로 1500 바이트이며 옛날에 모뎀을 통해 접속하던 PPPoE 연결은 1492 바이트를 가지고 있습니다. 블로그에서 다뤘던 점보프레임은 9000 바이트의 큰 크기를 가지고 있기도 합니다. MTU 는 각 패킷 프레임안에 최대 전송할 수 있는 값 MSS(Maximum segment size) 가 정의되어 있습니다. 그렇다면 MTU는 MSS + TCP/IP 헤더 크기가 될 것이고 반대로 MSS 는 MTU - 40  바이트가 됩니다. 40 바이트는 IP 와 TCP 헤더 20 바이트씩을 뜻합니다.

그러므로 일반적으로 우리가 사용하는 TCP 환경에서 애플리케이션이 사용할 수 있는 크기는 헤더를 제외한 1460 바이트 입니다. RFC1323 에서 정의한 타임스탬프 옵션이 확장되어 사용되면 12바이트가 늘어 1448 바이트가 됩니다. 자 그럼 MSS 를 조금더 들여다 보죠. TCP 프로토콜 연결시 SYN 패킷을 보내고 함께 MSS 를 포함하게 됩니다. SYN 패킷을 들여다 보면

0x0204 0x05B4


값을 볼 수가 있습니다. 02 는 MSS 옵션의 시작정의 부분을 뜻하고 04는 옵션의 크기(4바이트) 그리고 0x05B4 는 크기를 뜻합니다. 05B4 값이 1460 바이트 입니다. 이렇게 MSS 크기를 전송하면 받는 측에서도 어떤 크기로 전송해야 할지 알고 준비하게 됩니다.


MTU 와 속도상관관계를 한번 알아볼까요. 전용선 라인 T1 을 사용한다고 가정해 봅니다. T1 은 1.544Mbps (1,544,000 bits/sec) 가 됩니다. 여기서 MTU 가 1500 바이트라고 보면

(1460 + 40 ) * 8 / 1544000 = 7.772ms 가 됩니다. 여러분이 1Mbytes 의 파일을 전송한다고 봅니다. 1Mbyte 는 1024KB 이고 바이트로는 1,048,576 바이트입니다.

1Mbyte / MSS 로 나눠 봅니다 : 1048576bytes / 1460 = 718.2 가 나옵니다. 1M 를 T1 라인에서 전송한다고 보면 718.2 * 7.772 = 5581ms 가 나오네요. T1 라인에서는 1M 전송하는데 이 정도의 속도가 될 것이라고 생각해 볼 수 있는 것입니다. 물론 이것은 이론적인 것이므로 네트워크 환경에 따라 달라집니다.

윈도우 MTU 확인


윈도우에서는 netsh 명령어를 통해 인터페이스 정보를 확인할 수 있습니다.


C:\>netsh interface ip show interface

The Routing and Remote Access Service is not currently running on the local mach
ine.
Please use 'net start remoteaccess' on the machine to start the service.

그런데 서비스가 시작되어 있지 않다고 remoteaccess 서비스를 시작하라고 하네요.

C:\>net start remoteaccess
System error 1058 has occurred.

The service cannot be started, either because it is disabled or because it has n
o enabled devices associated with it.

위와 같이 나오는 경우는 해당 서비스가 disabled 되어 있는 경우입니다. 제어판->관리도구->서비스 에서 Routing and Remote Access 를 찾아보면 disabled 되어 있을 것이고, Startup Type 을 자동 또는 수동으로 변경후 시작해 주면 다음과 같이 인터페이스 결과를 얻을 수 있습니다. 윈도우 비스타 7의 경우라면 netsh interface ipv4 show subinterfaces 를 사용하면 됩니다.

C:\>netsh interface ip show interface

MIB-II Interface Information
------------------------------------------------------
Index:                              1
User-friendly Name:                 Loopback
GUID Name:                          Loopback
Type:                               Loopback
MTU:                                32768
Speed:                              10000000
Physical Address:
Admin Status:                       Up
Operational Status:                 Operational
Last Change:                        0
In Octets:                          0
In Unicast Packets:                 0
In Non-unicast Packets:             0
In Packets Discarded:               0
In Erroneous Packets:               0
In Unknown Protocol Packets:        0
Out Octets:                         0
Out Unicast Packets:                0
Out Non-unicast Packets:            0
Out Packets Discarded:              0
Out Erroneous Packets:              0
Output Queue Length:                0
Description:                        Internal loopback interface for 127.0.0 netw
ork

Index:                              2
User-friendly Name:                 Local Area Connection
GUID Name:                          {6D963098-CA8B-43EA-XXXXX}
Type:                               Ethernet
MTU:                                1500
Speed:                              1000000000
Physical Address:                   00-1F-D0-XX-XX-XX
Admin Status:                       Up
Operational Status:                 Operational
Last Change:                        3481341758
In Octets:                          164176737
In Unicast Packets:                 436671
In Non-unicast Packets:             31746
In Packets Discarded:               0
In Erroneous Packets:               0
In Unknown Protocol Packets:        516
Out Octets:                         1062079118
Out Unicast Packets:                952955
Out Non-unicast Packets:            349
Out Packets Discarded:              0
Out Erroneous Packets:              1
Output Queue Length:                0
Description:                        Realtek RTL8168/8111 PCI-E Gigabit Ethernet
NIC - Packet Scheduler Miniport

1500 트로 확인이 됩니다. 이외 간단히 ping 을 이용해 알아볼 수 도 있습니다. -l 로 데이터 크기를 지정할 수가 있는데, MTU 크기 값 이상이 되면 Fragment 메시지를 볼 수 있게 되어 이걸로 MTU 를 알아볼 수 있는 것이죠.

C:\>ping -f -l 1472 packetinside.com

Pinging packetinside.com [216.239.36.21] with 1472 bytes of data:

Reply from 216.239.36.21: bytes=64 (sent 1472) time=62ms TTL=43
Reply from 216.239.36.21: bytes=64 (sent 1472) time=62ms TTL=43
Reply from 216.239.36.21: bytes=64 (sent 1472) time=62ms TTL=43
Reply from 216.239.36.21: bytes=64 (sent 1472) time=62ms TTL=43

Ping statistics for 216.239.36.21:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 62ms, Maximum = 62ms, Average = 62ms

1473 크기를 지정하니 Fragment 되어야 한다고 나타납니다. 그런데 왜 1472 바이트 일까요 ? 위에서 본것과 같이 인터페이스에 설정된 값은 1500 바이트 입니다. IP 헤더가 20 바이트이고 ICMP 헤더가 8바이트( TYPE, CODE, CHECKSUM, DATA) 이죠.  즉 1500 - 28 = 1472 바이트가 되는 것입니다.

1472 바이트보다 크게 1 바이트를 늘려서 전송해 보았더니 fragment 가 필요하다고 나타납니다. 그러므로 한번에 전송할 수 있는 값이 1472 바이트 이구나 하고 생각할 수 있죠.

C:\>ping -f -l 1473 packetinside.com

Pinging packetinside.com [216.239.36.21] with 1473 bytes of data:

Packet needs to be fragmented but DF set.
Packet needs to be fragmented but DF set.
Packet needs to be fragmented but DF set.
Packet needs to be fragmented but DF set.

Ping statistics for 216.239.36.21:
    Packets: Sent = 4, Received = 0, Lost = 4 (100% loss),


추가로 윈도우 XP 의 경우는 다음의 도구를 이용해서 MTU 값을 조금 더 쉽게 바꿀수도 있으니 참고해 보세요.

1) DrTCP
http://www.dslreports.com/drtcp
2) How to change the PPPoE MTU size in Windows XP
http://support.microsoft.com/kb/283165

리눅스의 MTU 값 확인 


ifconfig 를 이용하면 쉽게 확인이 가능합니다.


$ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr bc:ae:c5:xx:xx:xx
          inet addr:192.168.xx.xx Bcast:192.168.xx.255  Mask:255.255.255.0
          inet6 addr: fe80::beae:xxxx:xxxx:b436/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:22530399 errors:0 dropped:0 overruns:0 frame:0
          TX packets:16150847 errors:0 dropped:1 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:10308945022 (10.3 GB)  TX bytes:3971757833 (3.9 GB)
          Interrupt:45 Base address:0x2000


mtu 값 변경도 아주 쉽게 ifconfig eth0 mtu 9000 과 같이 하면 됩니다.

이상으로 MTU 에 대해서 알아보았는데, 점보프레임과 같이 큰 MTU 값이 나오는 이유를 아시겠나요? 점보프레임 같은 경우는 로컬 네트워크 상에서는 사용하는데 큰 이슈가 없지만, 인터넷 구간으로 넘어가면 거치게 되는 디바이스들이 많아지다보니 9000 바이트와 같은 큰 값을 사용한다고 보장할수가 없습니다.

오늘은 여기에서 마무리 하고 다음번에 궁금해 할것 같은 다른 이야기를 다뤄볼께요?
MTU 에 의하면 패킷 데이터가 1500 바이트 이상으로 커질 수 없는데 패킷 덤프에서 보다보면 몇천바이트도 보이기 하는데 이건 무엇일까요? 다음 글에서 알아볼께요 :-)

2013년 2월 8일 금요일

GPU를 이용한 고성능 처리 PacketShader 와 Packet I/O

내일이면 2013년 구정의 시작이네요. 생각해 보면 시간은 참으로 빨리도 흘러갑니다. 오늘은 가볍게 GPU 기반의 소프트웨어 라우터 PacketShader 를 소개해 봅니다. PC 기반의 소프트웨어 플랫폼에서 GPU 를 이용해 코어 패킷 프로세싱을 구현하겠다는 것입니다. GPU 는 패킷인사이드에서도 몇번 언급했듯이 연산처리에 있어서 상당히 뛰어납니다. 그래서 암호해독 같은 것에 GPU 를 이용하면 속도가 크게 좋아지죠.

초기 프로젝트의 시작은 초당 10Gbps 를 목표로 했는데 40Gbps 에 도달했다고 합니다. (현재상황에서 구조적으로 40Gbps 이상의 성능을 만들어내는 것은 어렵다고 하네요) 프로토타입 시스템은 2개의 4 코어 Nehalem CPU (2.66GHz) 를 이용하고 4개의 듀얼포트 10Gbe 인텔 NIC 카드 그리고 2개의 NVIDIA GTX 480 카드를 이용했습니다.

몇가지 성능 측정 결과가 있는데, CPU 만을 이용한 것보다 연산처리가 보다 많이 들어가는 OpenFlow 스위치나 IPsec 터널링에서 상당히 좋은 성능 결과를 보여주고 있습니다.


Figure : IPv4 forwarding


Figure :  OpenFlow switch


Figure : IPsec tunneling (AES-CTR and SHA1)

유저레벨 단에서 고성능을 구현하기 위한 Packet I/O 엔진이라는 것을 공개하고 있습니다. Intel 82598/82599 기반의 네트워크 카드의 디바이스 드라이버입니다. 기존 인텔 IXGBE 드라이버를 많이 뜯어고친 것입니다. libpcap 를 이용하는 것보다 고 성능을 원한다면 해당 드라이버를 한번 이용해 보는 것도 좋을것 같습니다.

고성능에 관심있으신 분은 참고해 보세요.

그리고, KAIST 분들에게 응원을 보냅니다. 마지막으로 구정 연휴 잘 보내고 오세요 :-)

[참고]
1. Packet Shader
http://shader.kaist.edu/packetshader/
2. Packet I/O
http://shader.kaist.edu/packetshader/io_engine/index.html