土法炼钢兴趣小组的算法知识备份

【Linux 网络子系统深度拆解】XDP 内核实现:在驱动层重编程网络栈

文章导航

分类入口
linuxnetworking
标签入口
#kernel#XDP#eBPF#AF_XDP#xdp_buff#xdp_frame#devmap#cpumap#zero-copy#bpftrace

目录

传统网络栈处理一个包的完整路径——从驱动到 socket——需要约 2-5 微秒。对于 DDoS 防护、负载均衡、包过滤等场景,大部分包在入口就应该被丢弃或转发,走完整协议栈是巨大的浪费。XDP(eXpress Data Path)把 eBPF 程序注入到网卡驱动的 NAPI 轮询中,在 sk_buff 分配之前就决定包的命运。这使得单核包处理速度从传统路径的 1-2 Mpps 提升到 24+ Mpps。

但 XDP 不是”旁路”——它是内核网络栈的一部分,与 page pool、NAPI、GRO、TC 紧密集成。理解 XDP 的内核实现,才能正确使用它而不引入诡异的 bug。

本文基于 Linux 6.6/6.8 源码,拆解 XDP 的完整内核实现。

XDP 内核实现全景

一、核心数据结构

1.1 xdp_buff:XDP 的包描述符

XDP 程序操作的不是 sk_buff,而是更轻量的 xdp_buff

// include/net/xdp.h
struct xdp_buff {
    void *data;            // 包数据起始(L2 头)
    void *data_end;        // 包数据结束
    void *data_meta;       // 元数据区域(data 之前)
    void *data_hard_start; // 帧缓冲区物理起始(含 headroom)
    struct xdp_rxq_info *rxq; // 接收队列信息
    struct xdp_txq_info *txq; // 发送队列信息(可选)
    u32 frame_sz;          // 帧总大小
    u32 flags;             // XDP_FLAGS_HAS_FRAGS 等
};

sk_buff(约 256 字节,包含路由缓存、conntrack 引用、socket 指针等)相比,xdp_buff 仅 40 字节,这是 XDP 性能优势的结构基础。

内存布局:

data_hard_start                    data_hard_end
│                                       │
▼                                       ▼
┌──────────┬──────────┬────────────┬──────────────────┐
│ headroom │ metadata │  数据 (L2→) │ skb_shared_info  │
└──────────┴──────────┴────────────┴──────────────────┘
            ▲          ▲            ▲
            data_meta  data         data_end

1.2 xdp_frame:传输用帧描述符

当 XDP 决定转发(XDP_TX/XDP_REDIRECT)时,xdp_buff 被转换为 xdp_frame,存储在 headroom 中:

// include/net/xdp.h
struct xdp_frame {
    void *data;               // 数据指针
    u16 len;                  // 数据长度
    u16 headroom;             // headroom 大小
    u32 metasize;             // 元数据大小(低 8 位)
    struct xdp_mem_info mem;  // 内存模型(page pool/UMEM 等)
    struct net_device *dev_rx; // 原始接收设备
    u32 frame_sz;             // 帧大小
    u32 flags;                // 标志
};

转换通过 xdp_convert_buff_to_frame() 完成,将 xdp_frame 结构体内联写入 headroom 区域,避免额外内存分配。

1.3 xdp_rxq_info:接收队列上下文

// include/net/xdp.h
struct xdp_rxq_info {
    struct net_device *dev;    // 接收设备
    u32 queue_index;           // 队列编号
    u32 reg_state;             // 注册状态
    struct xdp_mem_info mem;   // 内存模型
    unsigned int napi_id;      // NAPI 实例 ID
    u32 frag_size;             // fragment 大小
} ____cacheline_aligned;       // cache line 对齐(性能关键)

XDP 程序通过 ctx->rxq->dev 获取接收设备信息,通过 ctx->rxq->queue_index 获取队列编号(用于 RSS 感知路由)。

1.4 内存模型枚举

// include/net/xdp.h
enum xdp_mem_type {
    MEM_TYPE_PAGE_SHARED = 0, // 页引用计数模型
    MEM_TYPE_PAGE_ORDER0,     // 独占 order-0 页
    MEM_TYPE_PAGE_POOL,       // page pool 管理
    MEM_TYPE_XSK_BUFF_POOL,   // AF_XDP UMEM
};

page pool 模型(MEM_TYPE_PAGE_POOL)是现代驱动的首选:XDP_DROP 时页直接回到 page pool,无需走伙伴系统释放。

二、XDP 执行模式

2.1 三种模式对比

模式 钩子位置 sk_buff 性能 兼容性
Native 驱动 NAPI poll 未分配 最高(24+ Mpps) 需驱动支持
Generic netif_receive_skb() 已分配 较低(3-5 Mpps) 所有设备
Offloaded NIC 固件 不涉及 线速 SmartNIC

2.2 Native XDP:驱动级钩子

Native XDP 通过 ndo_bpf 回调注册:

// include/linux/netdevice.h
struct net_device_ops {
    // ...
    int (*ndo_bpf)(struct net_device *dev, struct netdev_bpf *bpf);
    // ...
};

驱动在 NAPI 轮询中执行 XDP 程序:

// 驱动 NAPI poll(概念性,以 ixgbe 风格为例)
static int driver_napi_poll(struct napi_struct *napi, int budget)
{
    while (budget > 0) {
        // 1. 从 ring buffer 取出 DMA 完成的帧
        struct xdp_buff xdp;
        xdp.data = page_address(page) + offset;
        xdp.data_end = xdp.data + len;
        xdp.data_hard_start = page_address(page);
        xdp.rxq = &rx_ring->xdp_rxq;
        xdp.frame_sz = PAGE_SIZE;

        // 2. 执行 XDP 程序
        u32 act = bpf_prog_run_xdp(xdp_prog, &xdp);

        // 3. 根据返回值处理
        switch (act) {
        case XDP_DROP:
            // 直接回收页到 page pool
            page_pool_recycle_direct(pool, page);
            break;
        case XDP_PASS:
            // 分配 sk_buff,走正常协议栈
            skb = xdp_build_skb_from_frame(...);
            napi_gro_receive(napi, skb);
            break;
        case XDP_TX:
            // 从同一设备发出
            driver_xdp_xmit(dev, &xdp);
            break;
        case XDP_REDIRECT:
            // 队列化重定向
            xdp_do_redirect(dev, &xdp, xdp_prog);
            break;
        case XDP_ABORTED:
            trace_xdp_exception(dev, xdp_prog, act);
            page_pool_recycle_direct(pool, page);
            break;
        }
        budget--;
    }

    // NAPI 轮询结束时 flush 重定向批次
    xdp_do_flush();
    return processed;
}

关键点:

2.3 bpf_prog_run_xdp:程序执行入口

// include/net/xdp.h
static __always_inline u32
bpf_prog_run_xdp(const struct bpf_prog *prog, struct xdp_buff *xdp)
{
    u32 act = __bpf_prog_run(prog, xdp, BPF_DISPATCHER_FUNC(xdp));

    // 特殊处理:bonding 设备的 XDP_TX
    if (static_branch_unlikely(&bpf_master_redirect_enabled_key)) {
        if (act == XDP_TX && netif_is_bond_slave(xdp->rxq->dev))
            act = xdp_master_redirect(xdp);
    }
    return act;
}

__bpf_prog_run() 调用 JIT 编译后的本地代码。在 x86_64 上,一个简单的 XDP_DROP 程序编译为约 10 条机器指令。

2.4 Generic XDP:通用兼容模式

Generic XDP 在 netif_receive_skb() 之后执行,此时 sk_buff 已经分配:

// net/core/dev.c (概念性)
static int netif_receive_skb_internal(struct sk_buff *skb)
{
    // ... 已分配 sk_buff ...

    // Generic XDP 执行点
    if (static_branch_unlikely(&generic_xdp_needed_key)) {
        struct bpf_prog *xdp_prog = rcu_dereference(skb->dev->xdp_prog);
        if (xdp_prog) {
            // 从 sk_buff 构建临时 xdp_buff
            // 执行 XDP 程序
            // 根据返回值决定继续或丢弃
        }
    }
    // ... 继续正常路径 ...
}

Generic XDP 的局限:

三、五种 XDP 动作路径

3.1 XDP_DROP:极速丢包

case XDP_DROP:
    page_pool_recycle_direct(pool, page);
    // 或 page_frag_free(data);

这是 XDP 最常见的用途——DDoS 防护。页直接回收到 page pool,不触发任何协议栈代码。

性能基准:单核约 24 Mpps(对比 iptables DROP ~3 Mpps)。

3.2 XDP_PASS:递交协议栈

case XDP_PASS:
    // xdp_buff → xdp_frame → sk_buff
    struct sk_buff *skb = xdp_build_skb_from_frame(xdpf, dev);
    if (skb)
        napi_gro_receive(napi, skb);

xdp_build_skb_from_frame() 的开销约 200-500ns,包括 sk_buff 分配和头部初始化。如果 XDP 程序只是做统计而不过滤,XDP_PASS 的额外开销使得 native XDP 不如不挂载 XDP 程序。

3.3 XDP_TX:原设备回发

case XDP_TX:
    // 从同一网卡的 TX 队列发出
    xdp_convert_buff_to_frame(&xdp);  // 转换为 xdp_frame
    driver_xdp_xmit(dev, 1, &xdpf, 0);

典型场景:负载均衡器修改 MAC/IP 头后原路返回。注意 XDP_TX 使用接收设备的 TX 队列,可能与正常发包路径竞争锁。

3.4 XDP_REDIRECT:重定向

case XDP_REDIRECT:
    xdp_do_redirect(dev, &xdp, xdp_prog);
    // 帧暂存在 per-CPU 批次队列中
    // NAPI 结束时 xdp_do_flush() 批量发送

XDP_REDIRECT 是最灵活的动作,通过 BPF map 指定目标:

Map 类型 目标 用途
BPF_MAP_TYPE_DEVMAP 其他网卡 跨设备转发
BPF_MAP_TYPE_DEVMAP_HASH 其他网卡(哈希索引) 灵活转发
BPF_MAP_TYPE_CPUMAP 其他 CPU 负载分摊
BPF_MAP_TYPE_XSKMAP AF_XDP socket 用户态收包

3.5 XDP_ABORTED:异常处理

case XDP_ABORTED:
    trace_xdp_exception(dev, xdp_prog, act);
    // 触发 tracepoint,便于调试
    page_pool_recycle_direct(pool, page);

XDP_ABORTED 在 BPF 程序返回无效值或调用 bpf_throw() 时触发。与 XDP_DROP 的区别是会触发 xdp:xdp_exception tracepoint。

四、重定向机制详解

4.1 批量重定向架构

XDP_REDIRECT 不是立即发送,而是暂存后批量 flush:

// include/net/xdp.h
#define XDP_BULK_QUEUE_SIZE 16

struct xdp_frame_bulk {
    int count;
    void *xa;                         // 当前目标设备
    void *q[XDP_BULK_QUEUE_SIZE];     // 帧缓冲区
};

流程:

包 1 → xdp_do_redirect() → 暂存到 bulk queue
包 2 → xdp_do_redirect() → 暂存到 bulk queue
...
包 N → NAPI 轮询结束
     → xdp_do_flush()
       → 对每个目标设备批量调用 ndo_xdp_xmit()

批量发送的优势:

4.2 DEVMAP:跨设备转发

// BPF 程序中
SEC("xdp")
int xdp_redirect_prog(struct xdp_md *ctx)
{
    // 查找目标设备
    return bpf_redirect_map(&devmap, ctx->rx_queue_index, 0);
}

// 用户态创建 devmap
struct bpf_map_def devmap = {
    .type = BPF_MAP_TYPE_DEVMAP,
    .key_size = sizeof(u32),
    .value_size = sizeof(u32),  // 目标 ifindex
    .max_entries = 64,
};

DEVMAP 支持附加 XDP 程序:每个 map 条目可以关联一个 XDP 程序,在重定向到目标设备前执行(用于修改头部)。

4.3 CPUMAP:跨 CPU 分发

CPUMAP 把 XDP 帧从一个 CPU 转移到另一个 CPU 处理,适用于:

// CPUMAP 内部使用 per-CPU FIFO 队列
// 源 CPU:xdp_do_redirect() → 放入目标 CPU 的队列
// 目标 CPU:kthread 或 NAPI 轮询 → 从队列取帧
//   → 可选:执行附加的 XDP 程序
//   → xdp_build_skb_from_frame() → 进入协议栈

CPUMAP 目标 CPU 上的帧会被转换为 sk_buff 后进入正常协议栈。这意味着 CPUMAP 主要用于把 XDP 前置过滤与后续协议栈处理分摊到不同核。

4.4 XSKMAP:AF_XDP 通道

XSKMAP 把帧重定向到 AF_XDP socket,实现内核到用户态的零拷贝传输。

// include/net/xdp_sock.h
struct xsk_map {
    struct bpf_map map;
    spinlock_t lock;
    atomic_t count;
    struct xdp_sock __rcu *xsk_map[];
};

五、AF_XDP:用户态高速收包

AF_XDP 是 XDP 生态中最具革命性的组件——它提供了一条从网卡到用户态的零拷贝数据通道,性能可达 100+ Mpps。

5.1 核心架构

// include/net/xdp_sock.h
struct xdp_sock {
    struct sock sk;              // 内嵌 socket
    struct xsk_queue *rx;        // 接收描述符环
    struct net_device *dev;      // 绑定设备
    struct xdp_umem *umem;       // 用户内存区域
    struct xsk_buff_pool *pool;  // 缓冲区池
    u16 queue_id;                // 绑定队列
    bool zc;                     // 零拷贝模式
    bool sg;                     // 散列聚集
    struct xsk_queue *tx;        // 发送描述符环
    u64 rx_dropped;              // 丢包计数
    u64 rx_queue_full;           // 队列满计数
};

5.2 UMEM:共享内存区域

// include/net/xdp_sock.h
struct xdp_umem {
    void *addrs;          // 内存映射地址
    u64 size;             // 总大小
    u32 headroom;         // 每帧预留 headroom
    u32 chunk_size;       // 每帧大小(通常 4096 或 2048)
    u32 chunks;           // 帧总数
    u32 npgs;             // 页数
    bool zc;              // 零拷贝标志
    struct page **pgs;    // 物理页数组
};

UMEM 是用户态和内核共享的内存区域。用户态通过 mmap() 映射,内核(驱动)直接 DMA 写入。

5.3 四环架构

AF_XDP 使用四个无锁环形缓冲区在用户态和内核之间传递帧描述符:

                  用户态                        内核
              ┌───────────┐               ┌───────────┐
     应用填充 │ Fill Ring │ ──空帧描述符─→ │  驱动 RX   │
              └───────────┘               └───────────┘
              ┌───────────┐               ┌───────────┐
     应用消费 │  RX Ring  │ ←─已填充帧──── │  驱动 RX   │
              └───────────┘               └───────────┘
              ┌───────────┐               ┌───────────┐
     应用提交 │  TX Ring  │ ──待发送帧──→ │  驱动 TX   │
              └───────────┘               └───────────┘
              ┌───────────┐               ┌───────────┐
     应用回收 │Comp. Ring │ ←─已发送帧──── │  驱动 TX   │
              └───────────┘               └───────────┘

5.4 零拷贝 vs 拷贝模式

// 零拷贝模式
// 驱动直接 DMA 到 UMEM 页面
// 用户态读取时无数据拷贝
// 要求:驱动实现 ndo_xsk_wakeup
// 性能:100+ Mpps

// 拷贝模式
// 驱动 DMA 到普通页,内核拷贝到 UMEM
// 兼容所有设备
// 性能:20-50 Mpps

零拷贝模式需要驱动实现 ndo_xsk_wakeup() 回调,目前支持的主流驱动包括 i40e、ice、mlx5、ixgbe 等。

5.5 AF_XDP 选项

// include/uapi/linux/if_xdp.h
#define XDP_SHARED_UMEM     (1 << 0)  // 多 socket 共享 UMEM
#define XDP_COPY            (1 << 1)  // 强制拷贝模式
#define XDP_ZEROCOPY        (1 << 2)  // 强制零拷贝
#define XDP_USE_NEED_WAKEUP (1 << 3)  // 唤醒标志优化
#define XDP_USE_SG          (1 << 4)  // 散列聚集(多缓冲区)

XDP_USE_NEED_WAKEUP 是重要的功率优化:用户态在 Fill Ring 空时不盲目 poll,而是通过 need_wakeup 标志判断是否需要调用 sendto() 唤醒内核。

六、多缓冲区支持

6.1 问题背景

早期 XDP 要求整个包在一个连续帧中(通常 4KB)。这限制了 XDP 无法处理:

6.2 XDP multi-buffer 实现

// include/net/xdp.h
// 通过 flags 标志启用
#define XDP_FLAGS_HAS_FRAGS  BIT(0)

// 检测多缓冲区
static inline bool xdp_buff_has_frags(struct xdp_buff *xdp)
{
    return !!(xdp->flags & XDP_FLAGS_HAS_FRAGS);
}

// 获取完整长度(含 fragment)
static inline u32 xdp_get_buff_len(struct xdp_buff *xdp)
{
    u32 len = xdp->data_end - xdp->data;
    if (xdp_buff_has_frags(xdp)) {
        struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
        len += sinfo->xdp_frags_size;
    }
    return len;
}

// fragment 存储在帧尾部的 skb_shared_info 中
#define xdp_data_hard_end(xdp) \
    ((xdp)->data_hard_start + (xdp)->frame_sz - \
     SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))

多缓冲区的 XDP 包由头部帧 + N 个 fragment 组成,fragment 信息复用 skb_shared_info 结构体。BPF 程序通过 helper 函数访问各 fragment 的数据。

七、XDP 元数据

7.1 驱动到 BPF 的元数据传递

驱动可以在 data_meta 区域存储硬件信息,供 XDP 程序读取:

// 驱动设置元数据
xdp.data_meta = xdp.data - sizeof(struct my_metadata);
struct my_metadata *meta = xdp.data_meta;
meta->rx_timestamp = hw_timestamp;
meta->rx_hash = hw_rss_hash;

// BPF 程序读取
SEC("xdp")
int prog(struct xdp_md *ctx) {
    void *data = (void *)(long)ctx->data;
    void *meta = (void *)(long)ctx->data_meta;
    if (meta + sizeof(struct my_metadata) > data)
        return XDP_PASS;
    struct my_metadata *m = meta;
    // 使用 m->rx_timestamp, m->rx_hash
}

7.2 标准元数据操作

// include/net/xdp.h
struct xdp_metadata_ops {
    int (*xmo_rx_timestamp)(const struct xdp_md *ctx, u64 *timestamp);
    int (*xmo_rx_hash)(const struct xdp_md *ctx, u32 *hash,
                       enum xdp_rss_hash_type *rss_type);
    int (*xmo_rx_vlan_tag)(const struct xdp_md *ctx, __be16 *vlan_proto,
                           u16 *vlan_tci);
};

6.x 内核标准化了元数据接口,驱动通过 kfunc 向 BPF 程序暴露硬件信息。BPF 程序使用 bpf_xdp_metadata_rx_timestamp() 等 kfunc 获取数据,无需了解底层驱动细节。

7.3 BPF 头部调整

// XDP 程序可以调整包头部和元数据区域
bpf_xdp_adjust_head(xdp, delta);  // 扩展/收缩头部
bpf_xdp_adjust_meta(xdp, delta);  // 扩展/收缩元数据
bpf_xdp_adjust_tail(xdp, delta);  // 扩展/收缩尾部

bpf_xdp_adjust_head() 是封装/解封装的基础:负 delta 扩展 headroom(添加外层头),正 delta 收缩(剥离头部)。

八、XDP 与内核子系统的集成

8.1 XDP 与 page pool

现代 XDP 驱动使用 page pool 管理帧页面:

page_pool 分配 → DMA 映射 → 网卡 ring buffer
  → DMA 完成 → XDP 程序执行
    → XDP_DROP: page_pool_recycle_direct()    // 直接回收
    → XDP_PASS: 页转移给 sk_buff(skb_mark_for_recycle)
    → XDP_TX:   页在 TX 完成后回收
    → XDP_REDIRECT: 页转移给目标设备

XDP_DROP + page pool 组合是性能最优路径:无 sk_buff 分配、无 DMA 解映射、无伙伴系统调用。

8.2 XDP 与 GRO 的关系

时间线:
  驱动 NAPI poll
    → 每个包执行 XDP 程序(逐包处理)
    → XDP_PASS → napi_gro_receive()(GRO 聚合)
    → XDP_DROP → 直接回收(跳过 GRO)

XDP 在 GRO 之前执行,这意味着 XDP 程序看到的是原始小包,不是 GRO 聚合后的大包。这既是优势(可以精确过滤单个包)也是限制(无法利用 GRO 的聚合减少处理次数)。

8.3 XDP 与 TC 的关系

收包路径:
  XDP(驱动层)→ GRO → TC ingress(qdisc 层)→ Netfilter → 协议栈

发包路径:
  协议栈 → Netfilter → TC egress → 驱动 xmit

XDP 在 TC 之前,两者可以配合使用:XDP 做快速过滤,TC BPF 做精细分类。

九、可观测性实战

9.1 XDP tracepoint

# 追踪 XDP 动作分布
bpftrace -e '
tracepoint:xdp:xdp_redirect* {
    @redirect[probe] = count();
}
tracepoint:xdp:xdp_exception {
    @exception[args->act] = count();
}
interval:s:5 {
    print(@redirect);
    print(@exception);
    clear(@redirect);
    clear(@exception);
}
'

9.2 追踪 XDP 性能

# 测量 XDP 程序的执行延迟
bpftrace -e '
kprobe:bpf_prog_run_xdp {
    @start[tid] = nsecs;
}
kretprobe:bpf_prog_run_xdp /@start[tid]/ {
    @xdp_latency_ns = hist(nsecs - @start[tid]);
    delete(@start[tid]);
}
interval:s:10 { print(@xdp_latency_ns); clear(@xdp_latency_ns); }
'

9.3 AF_XDP 监控

# 查看 AF_XDP socket 统计
cat /proc/net/xsk

# 追踪 AF_XDP 丢包
bpftrace -e '
kprobe:xsk_rcv_check {
    @xsk_check = count();
}
kprobe:xsk_drop {
    @xsk_drop = count();
}
interval:s:5 {
    print(@xsk_check);
    print(@xsk_drop);
}
'

9.4 XDP 错误诊断

# 追踪 XDP_ABORTED(程序错误)
bpftrace -e '
tracepoint:xdp:xdp_exception {
    printf("XDP exception: dev=%s act=%d prog_id=%d\n",
           str(args->dev->name), args->act, args->prog_id);
    @exceptions = count();
}
'

# 查看 XDP 程序信息
bpftool prog show type xdp
bpftool net show

9.5 perf 分析 XDP CPU 开销

# XDP 与协议栈的 CPU 对比
perf record -g -C 0 -- sleep 10
perf report --no-children | head -30
# 观察 bpf_prog_run_xdp 与 netif_receive_skb 的比例

十、调优参数速查

参数 说明
XDP 模式选择 ip link set dev eth0 xdp obj prog.o(native)
ip link set dev eth0 xdpgeneric obj prog.o(generic)
AF_XDP 队列 ethtool -L eth0 combined N 调整队列数
AF_XDP chunk size UMEM chunk_size(2048 或 4096,影响内存效率)
Fill Ring 大小 建议 ≥ 2 × batch_size(避免饥饿)
批量大小 AF_XDP poll 返回批次(默认 64)
need_wakeup 开启 XDP_USE_NEED_WAKEUP(减少无效系统调用)
IRQ 亲和 XDP 处理 CPU = 中断 CPU

性能调优建议

# 1. 确保 native 模式
ip link show dev eth0 | grep xdp
# 应显示 xdp 而非 xdpgeneric

# 2. 绑定 XDP 处理到正确 CPU
# 通过 RSS/IRQ affinity 控制

# 3. 确保 page pool 启用
ethtool -S eth0 | grep page_pool

# 4. AF_XDP 零拷贝确认
# 创建 socket 时指定 XDP_ZEROCOPY
# 如果失败检查驱动支持

# 5. 批量大小优化
# 调整 NAPI weight 和 AF_XDP batch

十一、总结

XDP 的性能优势来自三个架构决策:

决策 传统路径 XDP
包描述符 sk_buff(256B) xdp_buff(40B)
分配时机 每包分配 sk_buff 仅 XDP_PASS 时分配
处理位置 协议栈全路径 驱动 NAPI 轮询

XDP 的五种动作覆盖了网络入口的所有需求:

AF_XDP 的四环零拷贝架构进一步打通了内核到用户态的数据通道,使得纯用户态网络应用(如 DPDK 风格但无需绕过内核)成为可能。

参考文献

  1. Linux 内核源码 include/net/xdp.h(XDP 核心结构体与函数)
  2. Linux 内核源码 include/net/xdp_sock.h(AF_XDP socket 实现)
  3. Linux 内核源码 include/net/xsk_buff_pool.h(XSK 缓冲区池)
  4. Jesper Dangaard Brouer, Toke Høiland-Jørgensen, “XDP — Scalable Packet Processing”, Netdev 2.1, 2017
  5. Björn Töpel, Magnus Karlsson, “AF_XDP — Scalable User-Space Networking”, Linux Plumbers Conference, 2018
  6. Toke Høiland-Jørgensen et al., “The eXpress Data Path: Fast Programmable Packet Processing in the Operating System Kernel”, CoNEXT, 2018

上一篇网络子系统内存管理:sk_buff 分配、page pool 与 NUMA

下一篇eBPF 网络钩子全景:TC/XDP/socket/cgroup

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2025-07-22 · linux / networking

【Linux 网络子系统深度拆解】eBPF 网络钩子全景:TC/XDP/socket/cgroup

从内核源码全面拆解 eBPF 在网络子系统中的所有挂载点:TC BPF direct-action 模式与 bpf_mprog 多程序链、XDP 驱动级钩子回顾、socket ops 回调与 TCP 生命周期事件、cgroup BPF 策略控制、sk_msg/sk_skb 的 sockmap 重定向引擎、struct_ops 实现自定义拥塞控制,以及 bpftrace 可观测实战。


By .