Перейти к содержанию

DPDK

Коротко

Data Plane Development Kit - набор библиотек для высокопроизводительной обработки пакетов в userspace. Разработан Intel, сейчас под Linux Foundation.

Главная идея: kernel bypass. Пакеты идут напрямую из NIC в приложение, минуя ядро Linux.

Проблема

Классический путь пакета: NIC -> драйвер ядра -> сетевой стек ядра -> socket API -> приложение.

Проблемы этого пути: - Прерывание на каждый пакет (или группу) - Context switch между kernel space и user space - Копирование данных между буферами - Выделение/освобождение sk_buff на каждый пакет - Обработка netfilter/iptables

При 10 Gbit/s и пакетах 64 байта: ~14.88 миллионов пакетов в секунду. Ядро не справляется.

Решение DPDK

Перенос fast path в userspace: - Драйвер NIC работает в userspace (PMD) - Polling вместо прерываний - Hugepages для памяти (меньше TLB misses) - Lockless структуры данных - Batch обработка пакетов - CPU pinning (lcore привязан к ядру)

Результат: миллионы pps на обычном CPU.

Архитектура

EAL (Environment Abstraction Layer)

Инициализация DPDK: - Выделение hugepages - Маппинг устройств в userspace - Привязка потоков к ядрам CPU - NUMA awareness - Логирование, таймеры

Скрывает специфику ОС от приложения.

PMD (Poll Mode Driver)

Userspace драйвер для NIC. Работает без прерываний - постоянно опрашивает (poll) RX/TX дескрипторы.

Один lcore (logical core) крутится в busy loop:

Text Only
while (true) {
    nb_rx = rte_eth_rx_burst(port, queue, pkts, BURST_SIZE);
    process(pkts, nb_rx);
    rte_eth_tx_burst(port, queue, pkts, nb_tx);
}

CPU занят на 100%, но латентность минимальна.

Mempool

Пул заранее выделенных буферов. Буферы создаются при старте, не выделяются динамически.

Использует hugepages (2MB или 1GB страницы). Меньше записей в TLB, меньше cache misses.

mbuf

Структура для хранения пакета. Аналог sk_buff в ядре, но проще и быстрее. Выделяется из mempool.

Ring

Lockless FIFO очередь. Multi-producer/multi-consumer. Используется для передачи пакетов между ядрами в pipeline модели.

Модели обработки

Run-to-completion

Один lcore делает все: RX -> обработка -> TX. Пакет не покидает ядро.

Text Only
lcore 1: NIC RX -> parse -> forward -> NIC TX
lcore 2: NIC RX -> parse -> forward -> NIC TX

Простая модель, хорошая локальность кэша.

Pipeline

Пакет проходит через несколько ядер. Между ядрами - ring очереди.

Text Only
lcore 1: NIC RX -> ring
lcore 2: ring -> parse -> ring
lcore 3: ring -> forward -> NIC TX

Сложнее, но позволяет разделить тяжелую обработку.

Binding устройств

NIC надо отвязать от kernel драйвера и привязать к DPDK.

Userspace драйверы для доступа к PCI: - vfio-pci - современный, безопасный (IOMMU) - uio_pci_generic - старый, требует root - igb_uio - DPDK-специфичный (deprecated)

После binding: NIC не виден в ip link, только через DPDK API.

Hugepages

DPDK требует hugepages для mempool. Стандартные 4KB страницы создают overhead на TLB.

Типичные размеры: - 2MB hugepages (по умолчанию на x86) - 1GB hugepages (для больших mempool)

Память выделяется при старте, не динамически.

NUMA

DPDK учитывает NUMA топологию: - Mempool выделяется на нужной NUMA node - lcore запускается на ядре той же NUMA node что и NIC - Минимизация cross-NUMA доступов

Use cases

Сетевые функции (NFV): - vSwitch (OVS-DPDK) - vRouter (VPP/FD.io) - Firewall, NAT, Load Balancer

Телеком: - 5G UPF (User Plane Function) - EPC (Evolved Packet Core) - BNG (Broadband Network Gateway)

Безопасность: - DDoS mitigation - IDS/IPS (Suricata с DPDK) - Deep Packet Inspection

Инфраструктура: - Traffic generator (TRex) - Packet capture - Network monitoring

Ограничения

  • NIC не виден в Linux (нет ip link, tcpdump)
  • Требует выделенных CPU ядер (100% load)
  • Сложнее отладка
  • Не все NIC поддерживаются
  • Требует hugepages, иногда IOMMU

Альтернативы

XDP/eBPF - обработка в ядре, но очень рано (до сетевого стека). Проще интеграция с Linux.

AF_XDP - сокеты с zero-copy из XDP в userspace. Компромисс между DPDK и ядром.

Netmap - похожий на DPDK подход, но менее распространен.