mcpField
A
af-xdp

af-xdp

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

af-xdp について

af-xdpは、AF_XDPによるパケットI/Oを扱うエージェント向けスキルです。ソケットやXDPの設定、リング管理、運用上の問題への対処を含み、ユーザー空間のパケット処理を実装する開発者向けです。

主な機能

  1. 01UMEMとXSKソケットの設定
  2. 02RX・TX・fill・completionリング
  3. 03XDPからユーザー空間へのリダイレクト
  4. 04コピーとゼロコピーの切り替え
  5. 05libbpfヘルパーと性能比較

活用シーン

  1. 01ユーザー空間パケット処理の実装
  2. 02独自ロードバランサーやIDSの構築
  3. 03NICのゼロコピー対応の確認
  4. 04パケット損失やキュー問題の調査

インストール

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

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

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

詳細

AF_XDP

目的

高性能なパケット I/O のために、AF_XDP ソケットの使い方をエージェントに案内します。ソケットの作成、UMEM のセットアップ、fill/completion/RX/TX リング、XSK への XDP_REDIRECT を使った XDP プログラム、コピーとゼロコピーの各モード、libbpf ヘルパー、DPDK との性能比較、実運用でのユースケースを扱います。

使用する場面

  • raw ソケットよりオーバーヘッドの少ないユーザー空間パケットプロセッサーを構築する場合
  • DPDK の複雑さを避けつつ、XDP でフィルタリングしたトラフィックをユーザー空間にリダイレクトする場合
  • カスタムロードバランサーや IDS データプレーンを実装する場合
  • NIC/ドライバーでゼロコピーとコピーの各モードを比較する場合
  • 既存の libbpf/XDP インフラストラクチャと統合する場合
  • カーネルの連携(ファイアウォールルール)とユーザー空間での処理の両方が必要な場合

ワークフロー

1. アーキテクチャの概要
NIC → XDP program (BPF) → XDP_REDIRECT → AF_XDP socket → userspace
                ↓
           XDP_DROP/PASS/TX

コンポーネント:

  • UMEM — フレーム用の共有メモリー領域
  • Fill ring — ユーザー空間からカーネルに空のフレームアドレスを提供します
  • Completion ring — カーネルから完了した TX フレームを返します
  • RX ring — カーネルから受信パケットを渡します
  • TX ring — ユーザー空間から送信するパケットを登録します
2. UMEM と XSK ソケットの作成
#include <bpf/xsk.h>
#include <bpf/libbpf.h>
#include <xdp/xsk.h>

#define NUM_FRAMES     4096
#define FRAME_SIZE     XSK_UMEM__DEFAULT_FRAME_SIZE
#define RX_BATCH_SIZE  64

struct xsk_umem_info {
    struct xsk_ring_prod fill;
    struct xsk_ring_cons comp;
    struct xsk_umem *umem;
    void *buffer;
};

struct xsk_socket_info {
    struct xsk_ring_cons rx;
    struct xsk_ring_prod tx;
    struct xsk_socket *xsk;
};

int xsk_setup(struct xsk_umem_info *umem_info,
              struct xsk_socket_info *xsk_info,
              int ifindex, int queue_id, int xsk_flags)
{
    umem_info->buffer = mmap(NULL, NUM_FRAMES * FRAME_SIZE,
        PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

    struct xsk_umem_config umem_cfg = {
        .fill_size = XSK_RING_PROD__DEFAULT_NUM_DESCS,
        .comp_size = XSK_RING_CONS__DEFAULT_NUM_DESCS,
        .frame_size = FRAME_SIZE,
        .frame_headroom = XSK_UMEM__DEFAULT_FRAME_HEADROOM,
        .flags = 0,
    };

    int ret = xsk_umem__create(&umem_info->umem, umem_info->buffer,
        NUM_FRAMES * FRAME_SIZE, &umem_info->fill, &umem_info->comp,
        &umem_cfg);
    if (ret)
        return ret;

    struct xsk_socket_config xsk_cfg = {
        .rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS,
        .tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS,
        .libbpf_flags = XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD,
        .xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST,
        .bind_flags = xsk_flags,  // XDP_ZEROCOPY or XDP_COPY
    };

    return xsk_socket__create(&xsk_info->xsk, "eth0", queue_id,
        umem_info->umem, &xsk_info->rx, &xsk_info->tx, &xsk_cfg);
}
3. Fill ring への登録
void populate_fill_ring(struct xsk_umem_info *umem) {
    uint32_t idx;
    uint32_t ret = xsk_ring_prod__reserve(&umem->fill, RX_BATCH_SIZE, &idx);
    for (uint32_t i = 0; i < ret; i++)
        *xsk_ring_prod__fill_addr(&umem->fill, idx + i) = i * FRAME_SIZE;
    xsk_ring_prod__submit(&umem->fill, ret);
}

Fill ring に常にバッファーを補充しておく必要があります。バッファーがないと、カーネルはパケットをドロップします。

4. XDP リダイレクトプログラム
// xdp_redirect.c
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>

struct {
    __uint(type, BPF_MAP_TYPE_XSKMAP);
    __uint(max_entries, 64);
    __type(key, int);
    __type(value, int);
} xsks_map SEC(".maps");

SEC("xdp")
int xdp_redirect_prog(struct xdp_md *ctx)
{
    int index = ctx->rx_queue_index;
    return bpf_redirect_map(&xsks_map, index, 0);
}
# Load and attach
bpftool prog load xdp_redirect.o /sys/fs/bpf/xdp_redirect
ip link set dev eth0 xdp obj xdp_redirect.o sec xdp

# Pin xsks_map and update with socket fd
5. RX 処理ループ
while (running) {
    uint32_t idx_rx = 0, rcvd;
    rcvd = xsk_ring_cons__peek(&xsk_info->rx, RX_BATCH_SIZE, &idx_rx);
    if (!rcvd)
        continue;

    for (uint32_t i = 0; i < rcvd; i++) {
        const struct xdp_desc *desc = xsk_ring_cons__rx_desc(&xsk_info->rx, idx_rx + i);
        uint64_t addr = desc->addr;
        uint32_t len = desc->len;
        uint8_t *pkt = (uint8_t *)xsk_umem__get_data(umem_info->buffer, addr);
        process_packet(pkt, len);
    }
    xsk_ring_cons__release(&xsk_info->rx, rcvd);

    // Return frames to fill ring
    refill_fill_ring(umem_info, rcvd);
}
6. コピーとゼロコピー
モードフラグ要件
コピーXDP_COPY(デフォルト)あらゆるドライバーに対応。カーネルが UMEM にコピーします
ゼロコピーXDP_ZEROCOPYドライバーの対応が必要(i40e、ixgbe、mlx5 など)
# Check driver ZC support
ethtool -i eth0
# Kernel log on bind:
dmesg | grep xsk
# "Zero-copy enabled" or "Copy mode"

ゼロコピー:NIC が UMEM のフレームに直接 DMA するため、レイテンシーが最小になります。コピー:より安全で、あらゆる環境で使用できます。

7. libbpf の xsk.h ヘルパー
# Modern libbpf includes xsk API
pkg-config --libs libbpf
# -lbpf -lxdp (if separate libxdp installed)

主な関数:

  • xsk_umem__create / xsk_umem__delete
  • xsk_socket__create / xsk_socket__delete
  • xsk_umem__get_data — フレームアドレスからポインターを取得します
  • xsk_socket__fd — epoll/poll との統合に使用します
8. DPDK との性能比較
要素AF_XDPDPDK
セットアップの複雑さ中程度高い(hugepages、EAL)
カーネルとの統合カーネル内の XDP フィルター完全なバイパス
一般的なスループットZC で DPDK に近い最高
NIC のバインドカーネルドライバーのままvfio/uio にバインド
適したユースケースフィルタリングと選択的なユーザー空間処理データプレーンの全面的な引き継ぎ
9. 実運用パターン
Common deployments
├── CDN edge cache — XDP_DROP junk, redirect cacheable to XSK
├── DDoS mitigation — XDP_DROP attack patterns
├── Load balancer — XDP_TX hairpin or redirect to backend XSK
└── Observability — mirror subset to XSK for analysis
# Multi-queue: one XSK per RX queue, pinned to CPU
taskset -c 2 ./xsk_app --queue 2

よくある問題

症状原因対処方法
RX ring にパケットがないXDP プログラムがリダイレクトしていないキューインデックスに対応する xsks_map エントリーを確認します
ソケット作成時に EBUSY が発生するすでに XDP がアタッチされている先に ip link set dev eth0 xdp off を実行します
ゼロコピーからコピーにフォールバックするドライバーが ZC に対応していないdmesg を確認し、対応する NIC を使用します
パケットがドロップされるFill ring が空積極的に補充し、NUM_FRAMES を増やします
TX が動作しないCompletion ring がポーリングされていないcomp ring を処理してフレームを再利用します
権限が拒否されるCAP_NET_RAW が必要適切なケイパビリティを付与して実行します

関連スキル

  • skills/observability/ebpf — XDP/BPF プログラムの開発
  • skills/async-io/dpdk — カーネルを完全にバイパスする代替手段
  • skills/async-io/io-uring — パケット以外のワークロード向け非同期 I/O
  • skills/observability/ebpf-rust — Rust で XDP を使うための Aya
  • skills/profilers/linux-perf — XDP プログラムの CPU 使用率をプロファイリング
  • skills/allocators/numa-programming — NUMA ローカルな UMEM の割り当て

コメント