关于 dpdk
面向使用 DPDK 进行用户态数据包处理的 Agent 技能,涵盖环境配置、收发包、队列管理、验证和虚拟机测试。
主要功能
- 01大页与 EAL 配置
- 02PMD 和网卡配置
- 03RX/TX 突发处理
- 04RSS 与核间队列
- 05testpmd 和 QEMU 测试
适用场景
- 01构建用户态数据包转发器
- 02原型开发 NFV 或 vSwitch 数据平面
- 03使用 testpmd 验证网卡配置
- 04在虚拟机中开发 DPDK 应用
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill dpdk安装后在 Claude Code 中输入/dpdk确认已加载。
详细介绍
DPDK
用途
指导 Agent 使用 DPDK(Data Plane Development Kit):EAL 初始化、轮询模式驱动(PMD)概念、rte_eth_rx_burst/tx_burst、mbuf 内存池、rte_ring 队列、大页设置、RSS 配置、testpmd 验证、QEMU virtio 测试,以及流水线与运行至完成模型。
适用场景
- 构建绕过内核网络栈的用户态数据包转发器
- 在 10/25/100 GbE 网卡上实现线速
- 为 NFV/vSwitch 数据平面组件制作原型
- 在编写自定义代码前,使用 testpmd 测试网卡配置
- 对比 DPDK 与内核网络或 AF_XDP 的吞吐量
- 在 VM 中使用 virtio 运行 DPDK 进行开发
工作流
1. 设置大页
# 2MB hugepages (common)
echo 1024 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# 1GB hugepages (better TLB perf on large memory)
echo 4 | sudo tee /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages
# Mount hugetlbfs
sudo mkdir -p /mnt/huge
sudo mount -t hugetlbfs nodev /mnt/huge
# Verify
grep Huge /proc/meminfo
DPDK EAL 会在启动时映射大页——大页数量不足会导致初始化失败。
2. EAL 初始化
#include <rte_eal.h>
#include <rte_ethdev.h>
int main(int argc, char **argv) {
int ret = rte_eal_init(argc, argv);
if (ret < 0)
rte_exit(EXIT_FAILURE, "EAL init failed\n");
// argc/argv adjusted — remaining args for app
return run_dataplane(argc - ret, argv + ret);
}
# Typical EAL args
./dpdk_app -l 0-3 -n 4 --huge-dir=/mnt/huge -- -p 0x3
# Flags:
# -l 0-3 — cores for DPDK (lcore mask)
# -n 4 — memory channels
# --proc-type=primary
# --file-prefix=myapp — multi-instance
3. 端口配置和 PMD
#include <rte_ethdev.h>
#define RX_RING_SIZE 1024
#define TX_RING_SIZE 1024
#define NUM_MBUFS 8191
#define MBUF_CACHE 250
#define BURST_SIZE 32
static const struct rte_eth_conf port_conf = {
.rxmode = { .max_lro_pkt_size = RTE_ETHER_MAX_LEN },
};
struct rte_mempool *mbuf_pool;
int port_init(uint16_t port) {
mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS,
MBUF_CACHE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
struct rte_eth_rxconf rxq_conf = dev_info.default_rxconf;
ret = rte_eth_rx_queue_setup(port, 0, RX_RING_SIZE,
rte_eth_dev_socket_id(port), &rxq_conf, mbuf_pool);
// ... tx queue setup ...
ret = rte_eth_dev_start(port);
rte_eth_promiscuous_enable(port);
return 0;
}
# List available PMDs
dpdk-devbind.py --status
# Bind NIC to vfio-pci (required for physical NICs)
sudo modprobe vfio-pci
sudo dpdk-devbind.py --bind=vfio-pci 0000:03:00.0
4. RX/TX 突发处理循环
static inline void lcore_main(void) {
const uint16_t port = 0;
struct rte_mbuf *bufs[BURST_SIZE];
while (1) {
uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE);
if (nb_rx == 0)
continue;
uint16_t nb_tx = rte_eth_tx_burst(port, 0, bufs, nb_rx);
// Free unsent mbufs
if (nb_tx < nb_rx) {
for (uint16_t i = nb_tx; i < nb_rx; i++)
rte_pktmbuf_free(bufs[i]);
}
}
}
轮询模式:不使用中断——核心会持续轮询数据包。每个队列分配一个核心,以实现扩展。
5. 使用 rte_ring 实现核间队列
#include <rte_ring.h>
struct rte_ring *ring = rte_ring_create("RX_RING", 1024,
rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ);
// Producer (RX core)
rte_ring_enqueue_bulk(ring, (void **)bufs, nb_rx, NULL);
// Consumer (worker core)
uint16_t nb_deq = rte_ring_dequeue_bulk(ring, (void **)bufs, BURST_SIZE, NULL);
6. RSS 配置
static const struct rte_eth_rss_conf rss_conf = {
.rss_key = NULL,
.rss_hf = RTE_ETH_RSS_IP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP,
};
struct rte_eth_conf port_conf = {
.rxmode = { .mq_mode = RTE_ETH_MQ_RX_RSS },
.rx_adv_conf = { .rss_conf = rss_conf },
};
将流量分发到各个 RX 队列——将队列映射到核心,实现并行处理。
7. testpmd 验证
# Build testpmd
cd dpdk/build
ninja -C build dpdk-testpmd
# Forward mode test
sudo ./build/app/dpdk-testpmd -l 0-3 -n 4 -- -i --forward-mode=io
testpmd> show port stats all
testpmd> start tx_first
testpmd> show port stats all
转发模式:io、mac、macswap、flowgen,用于吞吐量测试。
8. QEMU virtio 测试
qemu-system-x86_64 \
-cpu host -m 4096 -smp 4 \
-netdev user,id=net0 \
-device virtio-net-pci,netdev=net0,mq=on,vectors=10 \
-object memory-backend-file,id=mem,size=2G,mem-path=/dev/hugepages,share=on \
-numa node,memdev=mem \
...
在 VM 内:将 virtio PCI 绑定到 vfio-pci,或使用 vhost-user 以获得更高性能。
9. 流水线与运行至完成
Run-to-completion (simple)
├── One core: RX → process → TX
└── Good for low latency, simple logic
Pipeline (scaled)
├── Core 0: RX → ring
├── Core 1-N: process from ring → ring
└── Core N+1: TX
└── Better for complex per-packet processing
常见问题
| 现象 | 原因 | 修复方法 |
|---|---|---|
| EAL: 无法初始化大页 | 大页数量不足 | 增加 nr_hugepages;挂载 hugetlbfs |
No probed ethernet devices | 网卡未绑定到 DPDK 驱动 | dpdk-devbind.py --bind=vfio-pci |
| RX 丢包持续增加 | Mbuf 池耗尽 | 增加 NUM_MBUFS;检查是否存在泄漏(释放 mbuf) |
| testpmd 中为 0 Mbps | 端口未启动 | 在 testpmd 中执行 start;检查链路状态 |
| VFIO 权限错误 | 无权访问 IOMMU 组 | 对 vfio 组执行 chmod/chown;启用 IOMMU |
| 多核扩展效果不佳 | RSS 未进行分发 | 启用 RSS;配置多个 RX 队列 |
相关技能
skills/async-io/af-xdp— 更轻量的 XDP 替代方案skills/async-io/io-uring— 内核异步 I/O 对比skills/observability/ebpf— 将 XDP 程序重定向到 AF_XDPskills/virtualization/qemu-kvm— 用于 virtio 测试的 QEMU 设置skills/allocators/numa-programming— NUMA 感知的 DPDK 内存skills/profilers/linux-perf— 分析 DPDK lcore 热路径
评论
支持 Markdown