تخطَّ إلى المحتوى

DPDK Cheat Sheet

Overview

DPDK (Data Plane Development Kit) is an open-source set of libraries and NIC drivers that enable high-performance packet processing entirely in user space, bypassing the Linux kernel network stack. By using poll-mode drivers (PMDs), huge pages for memory, and CPU affinity to dedicate cores to packet processing, DPDK achieves near line-rate throughput with minimal latency. Originally developed by Intel, DPDK is now a Linux Foundation project supporting NICs from multiple vendors including Intel, Mellanox, Broadcom, and Marvell.

DPDK is the foundation for high-performance networking applications including virtual switches (Open vSwitch with DPDK), NFV (Network Function Virtualization) platforms, load balancers, firewalls, and telecom packet processing systems. It provides an Environment Abstraction Layer (EAL) for portability, ring buffers for lock-free inter-core communication, memory pools for efficient buffer management, and a comprehensive set of packet classification and manipulation libraries. DPDK is essential for any application requiring millions of packets per second throughput.

Installation

Prerequisites

# Check CPU supports required features
grep -E "sse4_2|avx|hugepage" /proc/cpuinfo

# Install build dependencies (Ubuntu/Debian)
sudo apt update
sudo apt install build-essential meson ninja-build python3-pyelftools \
    libnuma-dev libpcap-dev pkg-config

# Install build dependencies (CentOS/RHEL)
sudo yum install gcc gcc-c++ meson ninja-build python3-pyelftools \
    numactl-devel libpcap-devel

Build from Source

# Download DPDK
wget https://fast.dpdk.org/rel/dpdk-23.11.tar.xz
tar xf dpdk-23.11.tar.xz
cd dpdk-23.11

# Configure build
meson setup build
cd build
ninja

# Install
sudo ninja install
sudo ldconfig

# Verify
pkg-config --modversion libdpdk

Hugepage Setup

# Allocate 2MB hugepages (1024 pages = 2GB)
echo 1024 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

# Allocate 1GB hugepages (requires boot parameter)
# Add to kernel cmdline: hugepagesz=1G hugepages=4
echo 4 | sudo tee /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages

# Mount hugetlbfs
sudo mkdir -p /dev/hugepages
sudo mount -t hugetlbfs nodev /dev/hugepages

# Persistent hugepage config in /etc/fstab
# nodev /dev/hugepages hugetlbfs defaults 0 0

# Verify hugepages
cat /proc/meminfo | grep -i huge

NIC Binding

# List available NICs and their current drivers
dpdk-devbind.py --status

# Bind NIC to DPDK-compatible driver
sudo modprobe vfio-pci
sudo dpdk-devbind.py --bind=vfio-pci 0000:03:00.0

# Bind to igb_uio (legacy)
sudo modprobe uio
sudo insmod build/kernel/linux/igb_uio/igb_uio.ko
sudo dpdk-devbind.py --bind=igb_uio 0000:03:00.0

# Unbind and return to kernel driver
sudo dpdk-devbind.py --bind=ixgbe 0000:03:00.0

# Enable IOMMU for vfio-pci
# Add to kernel cmdline: intel_iommu=on iommu=pt

EAL Parameters

ParameterDescription
-l 0-3CPU cores to use
--lcores '(0-1)@0,(2-3)@1'Map lcores to physical cores
-n 4Number of memory channels
--socket-mem 1024,1024Memory per NUMA socket (MB)
-a 0000:03:00.0Allow (whitelist) PCI device
-b 0000:03:00.1Block (blacklist) PCI device
--file-prefix dpdk1Shared memory file prefix
--proc-type primaryProcess type (primary/secondary/auto)
--huge-dir /dev/hugepagesHugepage mount point
--log-level 8Log level (1=emergency to 8=debug)
--no-pciDisable PCI bus scanning
--vdev net_pcap0,...Virtual device

Example EAL Initialization

# Run DPDK application
sudo ./my_app -l 0-3 -n 4 -a 0000:03:00.0 -- --config="(0,0,1),(1,0,2)"

# Use pcap virtual device (no real NIC needed)
sudo ./my_app -l 0-1 --vdev 'net_pcap0,rx_pcap=input.pcap,tx_pcap=output.pcap'

Core Commands and Tools

dpdk-testpmd

# Start testpmd (built-in packet forwarding test)
sudo dpdk-testpmd -l 0-3 -n 4 -a 0000:03:00.0 -a 0000:03:00.1 -- \
    --portmask=0x3 --nb-cores=2 -i

# Testpmd interactive commands
testpmd> show port info all
testpmd> show port stats all
testpmd> set fwd io            # I/O forwarding
testpmd> set fwd mac           # MAC forwarding
testpmd> set fwd rxonly        # Receive only
testpmd> set fwd txonly        # Transmit only
testpmd> set burst 64          # Burst size
testpmd> start                 # Start forwarding
testpmd> stop                  # Stop forwarding
testpmd> clear port stats all  # Reset statistics
testpmd> quit

dpdk-proc-info

# Show running DPDK process info
sudo dpdk-proc-info -- --stats
sudo dpdk-proc-info -- --stats-reset
sudo dpdk-proc-info -- --xstats
sudo dpdk-proc-info -- --metrics

dpdk-pdump

# Capture packets from DPDK port
sudo dpdk-pdump -- --pdump 'port=0,queue=*,rx-dev=/tmp/rx.pcap'

# Capture TX packets
sudo dpdk-pdump -- --pdump 'port=0,queue=*,tx-dev=/tmp/tx.pcap'

Application Development

Minimal DPDK Application

#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>

#define RX_RING_SIZE 1024
#define TX_RING_SIZE 1024
#define NUM_MBUFS 8191
#define MBUF_CACHE_SIZE 250
#define BURST_SIZE 32

int main(int argc, char *argv[]) {
    struct rte_mempool *mbuf_pool;
    uint16_t port_id = 0;

    // Initialize EAL
    int ret = rte_eal_init(argc, argv);
    if (ret < 0) rte_exit(EXIT_FAILURE, "EAL init failed\n");

    // Create mbuf pool
    mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL",
        NUM_MBUFS, MBUF_CACHE_SIZE, 0,
        RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());

    // Configure port
    struct rte_eth_conf port_conf = {0};
    rte_eth_dev_configure(port_id, 1, 1, &port_conf);

    // Setup RX/TX queues
    rte_eth_rx_queue_setup(port_id, 0, RX_RING_SIZE,
        rte_eth_dev_socket_id(port_id), NULL, mbuf_pool);
    rte_eth_tx_queue_setup(port_id, 0, TX_RING_SIZE,
        rte_eth_dev_socket_id(port_id), NULL);

    // Start port
    rte_eth_dev_start(port_id);
    rte_eth_promiscuous_enable(port_id);

    // Main packet processing loop
    struct rte_mbuf *bufs[BURST_SIZE];
    for (;;) {
        uint16_t nb_rx = rte_eth_rx_burst(port_id, 0, bufs, BURST_SIZE);
        if (nb_rx > 0) {
            uint16_t nb_tx = rte_eth_tx_burst(port_id, 0, bufs, nb_rx);
            // Free unsent packets
            for (uint16_t i = nb_tx; i < nb_rx; i++)
                rte_pktmbuf_free(bufs[i]);
        }
    }

    rte_eal_cleanup();
    return 0;
}

Build with Meson

# meson.build for DPDK application
project('my_dpdk_app', 'c',
    default_options: ['buildtype=release'])

dpdk = dependency('libdpdk')
executable('my_app', 'main.c', dependencies: dpdk)
meson setup build
cd build && ninja

Configuration

DPDK Memory Configuration

# /etc/dpdk/dpdk.conf (distribution-managed)
NR_2M_PAGES=1024
NR_1G_PAGES=4

# NUMA-aware hugepage allocation
echo 512 | sudo tee /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
echo 512 | sudo tee /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages

CPU Isolation for DPDK Cores

# Kernel cmdline parameters
# isolcpus=2-7 nohz_full=2-7 rcu_nocbs=2-7

# Verify isolated CPUs
cat /sys/devices/system/cpu/isolated

# Set CPU governor to performance
for cpu in /sys/devices/system/cpu/cpu[2-7]/cpufreq/scaling_governor; do
    echo performance | sudo tee $cpu
done

Advanced Usage

Ring Buffers (Inter-Core Communication)

// Create ring
struct rte_ring *ring = rte_ring_create("my_ring", 1024,
    rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ);

// Enqueue
rte_ring_enqueue(ring, obj);

// Dequeue
void *obj;
rte_ring_dequeue(ring, &obj);

Flow Classification (rte_flow)

// Create flow rule to match TCP port 80
struct rte_flow_attr attr = { .ingress = 1 };
struct rte_flow_item pattern[] = {
    { .type = RTE_FLOW_ITEM_TYPE_ETH },
    { .type = RTE_FLOW_ITEM_TYPE_IPV4 },
    { .type = RTE_FLOW_ITEM_TYPE_TCP,
      .spec = &(struct rte_flow_item_tcp){ .hdr.dst_port = rte_cpu_to_be_16(80) },
      .mask = &(struct rte_flow_item_tcp){ .hdr.dst_port = 0xFFFF } },
    { .type = RTE_FLOW_ITEM_TYPE_END }
};
struct rte_flow_action actions[] = {
    { .type = RTE_FLOW_ACTION_TYPE_QUEUE,
      .conf = &(struct rte_flow_action_queue){ .index = 1 } },
    { .type = RTE_FLOW_ACTION_TYPE_END }
};
rte_flow_create(port_id, &attr, pattern, actions, &error);

Troubleshooting

IssueSolution
EAL init fails: no hugepagesAllocate hugepages and mount hugetlbfs
NIC not found by DPDKBind NIC to vfio-pci or igb_uio driver
VFIO: permission deniedEnable IOMMU in BIOS, add kernel parameters
Low packet throughputCheck CPU isolation, verify NUMA awareness
mbuf allocation failureIncrease NUM_MBUFS or hugepage allocation
Secondary process can’t attachMatch —file-prefix and —proc-type
Compilation errorsVerify pkg-config --libs libdpdk works
Port link downCheck cable, verify NIC firmware version

Performance Tuning Checklist

# 1. Isolate CPU cores
cat /proc/cmdline | grep isolcpus

# 2. Disable CPU frequency scaling
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

# 3. Verify hugepage allocation
cat /proc/meminfo | grep Huge

# 4. Check NUMA topology
numactl --hardware

# 5. Verify NIC driver binding
dpdk-devbind.py --status

# 6. Disable irqbalance
sudo systemctl stop irqbalance