Home DPDK 사용기(1)
Post
Cancel

DPDK 사용기(1)

1. 배경

Developing High-Frequency Systems을 우연히 읽다가, HFT 시스템에서 지연을 최소화하기 위해, Kernel bypass와 zero-copy를 사용해야 한다는 것을 알게 되었다. (참고로 저 책은 별로 추천안함)

Kernel bypass란 말 그대로 커널을 우회하여 사용자 공간에서 직접 하드웨어에 접근하는 기술이다. 네트워크를 최적화할 때 가장 많이 사용되는 기술인데, 기존에는 NIC는 packet을 수신하면 interrupt를 발생시켜 커널에 알리고, 커널은 이를 처리하여 사용자 공간으로 전달하는 방식이었다. 이 과정에서 많은 오버헤드가 발생하게 된다. Kernel bypass는 이러한 과정을 우회하여 NIC와 사용자 공간 간의 직접적인 데이터 전송을 가능하게 한다.

Zero-copy는 데이터 복사를 최소화하여 성능을 향상시키는 기술이다. 일반적으로 네트워크 패킷을 수신하면, NIC에서 커널로 복사되고, 다시 사용자 공간으로 복사되는 과정이 필요하다. 이 과정에서 많은 CPU 사이클과 메모리 대역폭이 소모된다. Zero-copy는 이러한 복사를 최소화하여 성능을 향상시킨다.

2. DPDK

2-1. DPDK란?

DPDK

DPDK는 Data Plane Development Kit의 약자로, Intel에서 개발한 오픈소스 라이브러리이다. DPDK는 고성능 패킷 처리 애플리케이션을 개발하기 위한 프레임워크로, 주로 네트워크 장비 및 서버에서 사용된다. DPDK는 CPU와 NIC(네트워크 인터페이스 카드) 간의 데이터 전송을 최적화하여 높은 성능을 제공한다.

가장 대표적인 기능은, 위의 사진 처럼 Kernel을 거치지 않고 user가 직접 NIC에 접근할 수 있도록 해주는 것이다. 이를 PMD(Polled Mode Driver)라고 한다. 구체적으로는 user가 NIC에 새로운 패킷이 올 때까지 polling을 하여 패킷을 즉각적으로 처리할 수 있도록 해준다. 이로 인해, interrupt를 발생시키는 오버헤드를 줄일 수 있다.

또한, DPDK는 메모리 관리, 멀티스레딩, CPU 코어 관리 등 다양한 기능을 제공하여 고성능 패킷 처리 애플리케이션을 개발하는 데 필요한 모든 기능을 지원한다. DPDK는 Intel CPU에서 최적화되어 있지만, ARM 및 PowerPC 아키텍처에서도 사용할 수 있다.

DPDK는 다양한 NIC 드라이버를 지원하며, Intel, Mellanox, Broadcom 등 다양한 제조업체의 NIC을 지원한다. DPDK는 또한 다양한 프로토콜 스택을 지원하여, TCP/IP, UDP/IP, MPLS 등 다양한 프로토콜을 처리할 수 있다. DPDK는 고성능 패킷 처리 애플리케이션을 개발하는 데 필요한 모든 기능을 제공하며, 대규모 데이터 센터 및 클라우드 환경에서 널리 사용되고 있다.

2-2. 구성요소

DPDK Docs를 참고하여 아주 최소한으로 DPDK의 주요 구성요소를 정리해보았다.

EAL

  1. EAL(Execution Abstraction Layer): DPDK의 핵심 구성 요소로, DPDK 애플리케이션이 하드웨어 리소스에 접근할 수 있도록 해준다. EAL은 CPU, 메모리, NIC 등 하드웨어 리소스를 관리하고, DPDK 애플리케이션이 하드웨어 리소스에 접근할 수 있도록 해준다. EAL은 DPDK 애플리케이션이 하드웨어 리소스를 효율적으로 사용할 수 있도록 최적화되어 있다.
  2. PMD(Polled Mode Driver): DPDK의 NIC 드라이버로, NIC와 DPDK 애플리케이션 간의 데이터 전송을 최적화한다. PMD는 NIC에서 수신한 패킷을 DPDK 애플리케이션으로 전달하고, DPDK 애플리케이션에서 전송한 패킷을 NIC로 전달한다. PMD는 polling 방식으로 동작하여, interrupt를 발생시키지 않고 패킷을 처리할 수 있다.
  3. mbuf: DPDK의 메모리 버퍼로, DPDK 애플리케이션이 패킷을 처리하는 데 사용되는 메모리 블록이다. mbuf는 패킷의 헤더와 페이로드를 저장하는 데 사용되며, DPDK 애플리케이션이 패킷을 처리하는 데 필요한 모든 정보를 저장한다. mbuf는 DPDK 애플리케이션이 패킷을 처리하는 데 필요한 모든 정보를 저장하며, DPDK 애플리케이션이 패킷을 처리하는 데 필요한 모든 기능을 제공한다.

그래서 위의 사진처럼, EAL을 통해 DPDK 애플리케이션의 시작, 종료, 메모리 관리, NIC 연결 등을 수행하고, PMD를 통해 NIC와 DPDK 애플리케이션 간의 데이터 전송을 최적화한다. 그리고 애플리케이션과 NIC는 mbuf를 통해 데이터를 주고받는다.

2-3. 사용 예시

DPDK Ecosystem에서 DPDK를 사용하는 다양한 프로젝트를 확인할 수 있다.

3. DPDK 사용기

3-1. 설치

우선 DPDK를 쓰는 이유가 Kernel bypass와 zero-copy를 사용하기 위함이므로, DPDK를 설치하기 전에 NIC가 DPDK(특히 PMD)를 지원하는지 확인해야 한다. DPDK는 Intel, Mellanox, Broadcom 등 다양한 제조업체의 NIC을 지원한다. DPDK를 지원하는 NIC은 DPDK Supported NICs에서 확인할 수 있다.

근데 내 컴퓨터의 NIC는 PMD를 지원안해서, NIC를 새로 사야하나 고민하다가, aws의 EC2의 NIC가 PMD를 지원한다고 하여 aws EC2를 사용하기로 했다.
하드웨어는 t3 medium을 사용하고, OS는 ubuntu 22.04를 사용했다.

1
2
3
4
5
# DPDK 설치
sudo apt-get update
sudo apt install -y build-essential meson ninja-build \
    python3-pyelftools libnuma-dev libpcap-dev
git clone git@github.com:DPDK/dpdk.git
1
2
3
4
5
# DPDK 빌드
cd dpdk
meson setup build
cd build
ninja

이렇게 하면 build는 끝난다.
그리고 이제 주 목표인 PMD를 설정해주어야 하는데, PMD는 Kernel에서 NIC를 user로 뺏어오는 것이기에, ssh로 접속한 상태에서 PMD를 설정하면 그냥 ssh가 끊긴다(해보진 않았는데 아마 그럴듯). 그래서 PMD용 NIC를 위해 ec2에 별도의 NIC를 추가해주었다.

그래서 처음에는,

1
2
3
4
5
ubuntu@ip-172-31-13-20:~/dpdk-stable-24.11.2/usertools$ sudo ./dpdk-devbind.py --status

Network devices using kernel driver
===================================
0000:00:05.0 'Elastic Network Adapter (ENA) ec20' if=ens5 drv=ena unused= *Active*

이런식으로 하나만 나왔는데,

1
2
3
4
Network devices using kernel driver
===================================
0000:00:05.0 'Elastic Network Adapter (ENA) ec20' if=ens5 drv=ena unused= *Active*
0000:00:06.0 'Elastic Network Adapter (ENA) ec20' if=ens6 drv=ena unused= *Active*

하나를 더 추가해주었다.
그리고 PMD를 사용하는 방식이 크게 두 가지가 있는데,

  1. UIO
  2. VFIO

UIO는 사용자 공간에서 NIC를 제어할 수 있도록 해주는 드라이버로, DPDK에서 가장 많이 사용되는 드라이버이다. UIO는 커널 모드와 사용자 모드 간의 전환이 필요하므로, 성능이 떨어질 수 있다.
VFIO는 커널 모드와 사용자 모드 간의 전환이 필요하지 않으므로, 성능이 더 좋다. 하지만 VFIO는 UIO보다 설정이 복잡하고, ec2 t3 medium에서는 지원하지 않는다. 그래서 UIO를 사용하기로 했다.

1
2
3
4
5
6
#uio 설치
git clone https://dpdk.org/git/dpdk-kmods
pushd dpdk-kmods/linux/igb_uio
sudo make
sudo depmod && sudo insmod igb_uio.ko
popd
1
2
# PMD 설정
sudo ./dpdk-devbind.py --bind=igb_uio 0000:00:06.0

여기까지 하면,

1
2
3
4
5
6
7
8
9
ubuntu@ip-172-31-13-20:~/dpdk-stable-24.11.2/usertools$ sudo ./dpdk-devbind.py --status

Network devices using DPDK-compatible driver
============================================
0000:00:06.0 'Elastic Network Adapter (ENA) ec20' drv=igb_uio unused=ena

Network devices using kernel driver
===================================
0000:00:05.0 'Elastic Network Adapter (ENA) ec20' if=ens5 drv=ena unused=igb_uio *Active*

이런식으로 PMD가 설정된 것을 확인할 수 있다.

그리고 DPDK를 사용하기 위해서는 hugepage를 설정해주어야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# hugepage 설정
sudo mkdir -p /mnt/hugepg
sudo mount -t hugetlbfs -o pagesize=1G none /mnt/hugepg

echo 512 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

ubuntu@ip-172-31-13-20:~/dpdk-stable-24.11.2/build$ cat /proc/meminfo | grep HugePages
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
FileHugePages:         0 kB
HugePages_Total:     512
HugePages_Free:      512
HugePages_Rsvd:        0
HugePages_Surp:        0

원래는 1Gb짜리 hugepage를 만들려고 했는데, t3 medium의 메모리가 4Gb라서 512 x 2Mb짜리 hugepage를 만들었다.

여기까지 하면 DPDK를 사용할 준비가 끝났다!!

3-2. Hello World

1
2
# Hello World
sudo ./dpdk-helloworld -c 0x3 --socket-mem 1024 --huge-dir=/dev/hugepages --allow 0000:00:06.0

옵션의 의미는 다음과 같다.

  • -c: CPU 코어 마스크를 설정한다. 0x3은 2개의 코어를 사용하겠다는 의미이다.
  • –socket-mem: 소켓 메모리를 설정한다. 1024는 1Gb의 메모리를 사용하겠다는 의미이다.
  • –huge-dir: hugepage가 마운트된 디렉토리를 설정한다. /dev/hugepages는 hugepage가 마운트된 디렉토리이다.
  • –allow: PMD를 설정한 NIC의 PCI 주소를 설정한다. 0000:00:06.0은 PMD를 설정한 NIC의 PCI 주소이다.

3-3. further study

DPDK를 사용해서 web socket client를 만들어보려고 한다.그리고 web socket client를 만들어서 최종적으로는 HFT용 Local Order Book을 만들어보려고 한다.
일단 문제는, DPDK는 Layer 2에서 동작하기 때문에, Layer 3인 TCP/IP를 사용하기 위해서는 DPDK위에서 TCP/IP 스택을 구현해야 한다.
DPDK는 TCP/IP 스택을 구현하기 위한 라이브러리를 제공하지 않기 때문에, 직접 구현해야 한다. 근데 그건 미친짓이고, 어떻게 잘 포팅한다고 해도 성능이 안나올 수 있기에, 다른 라이브러리들을 찾아봤다.
찾아본 라이브러리는 다음과 같다.

다음 글에서는 DPDK를 사용해서 web socket client를 만드는 과정을 정리해보려고 한다.

This post is licensed under CC BY 4.0 by the author.

라즈베리 파이로 Syncthing 서버 만들기

Photomap 개발 기록