mcpField
D
dpdk

dpdk

github.com/mohitmishra786開発269300 回インストール18 週間前に更新
リポジトリ

dpdk について

DPDK によるユーザー空間のパケット処理を支援するエージェント向けスキルです。環境設定、送受信、キュー管理、検証、VM テストを扱います。

主な機能

  1. 01Huge page と EAL の設定
  2. 02PMD と NIC の設定
  3. 03RX/TX バースト処理
  4. 04RSS とコア間キュー
  5. 05testpmd と QEMU によるテスト

活用シーン

  1. 01ユーザー空間パケットフォワーダーの構築
  2. 02NFV や vSwitch データプレーンの試作
  3. 03testpmd による NIC 設定の検証
  4. 04VM 内での DPDK アプリ開発

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mohitmishra786/low-level-dev-skills --skill dpdk

インストール後、Claude Code で/dpdkを入力して読み込まれたか確認します。

詳細

DPDK

目的

DPDK(Data Plane Development Kit)を使うエージェントをガイドします。対象には、EAL の初期化、ポーリングモードドライバー(PMD)の概念、rte_eth_rx_burst/tx_burst、mbuf メモリプール、rte_ring キュー、Huge Page の設定、RSS の構成、testpmd による検証、QEMU virtio のテスト、パイプラインモデルと run-to-completion モデルの比較が含まれます。

使用する場面

  • カーネルのネットワークスタックを迂回するユーザー空間パケットフォワーダーを構築する場合
  • 10/25/100 GbE NIC で回線速度を達成する場合
  • NFV/vSwitch のデータプレーンコンポーネントを試作する場合
  • 独自コードを書く前に testpmd で NIC の設定をテストする場合
  • DPDK のスループットをカーネルネットワーキングや AF_XDP と比較する場合
  • 開発用に virtio を使って VM 内で DPDK を実行する場合

ワークフロー

1. Huge Page の設定
# 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 は起動時に Huge Page をマッピングするため、ページ数が不足すると初期化に失敗します。

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]);
        }
    }
}

ポーリングモードでは割り込みを使わず、コアがパケットを求めてスピンします。スケーリングのため、キューごとにコアを 1 つ割り当てます。

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 の比較
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: Cannot init hugepagesHuge Page の不足nr_hugepages を増やし、hugetlbfs をマウントします
No probed ethernet devicesNIC が 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 — AF_XDP にリダイレクトする XDP プログラム
  • skills/virtualization/qemu-kvm — virtio テスト用の QEMU 設定
  • skills/allocators/numa-programming — NUMA を考慮した DPDK メモリ
  • skills/profilers/linux-perf — DPDK の lcore ホットパスをプロファイリングする

コメント