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
| Parameter | Description |
|---|---|
-l 0-3 | CPU cores to use |
--lcores '(0-1)@0,(2-3)@1' | Map lcores to physical cores |
-n 4 | Number of memory channels |
--socket-mem 1024,1024 | Memory per NUMA socket (MB) |
-a 0000:03:00.0 | Allow (whitelist) PCI device |
-b 0000:03:00.1 | Block (blacklist) PCI device |
--file-prefix dpdk1 | Shared memory file prefix |
--proc-type primary | Process type (primary/secondary/auto) |
--huge-dir /dev/hugepages | Hugepage mount point |
--log-level 8 | Log level (1=emergency to 8=debug) |
--no-pci | Disable 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
| Issue | Solution |
|---|---|
| EAL init fails: no hugepages | Allocate hugepages and mount hugetlbfs |
| NIC not found by DPDK | Bind NIC to vfio-pci or igb_uio driver |
| VFIO: permission denied | Enable IOMMU in BIOS, add kernel parameters |
| Low packet throughput | Check CPU isolation, verify NUMA awareness |
| mbuf allocation failure | Increase NUM_MBUFS or hugepage allocation |
| Secondary process can’t attach | Match —file-prefix and —proc-type |
| Compilation errors | Verify pkg-config --libs libdpdk works |
| Port link down | Check 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