XDP Hook点分析

XDP Hook点分析

首页休闲益智小猫钓鱼2更新时间:2024-05-05
XDP 支持三种操作模式

默认的工作模式,Native工作在网卡驱动的RX队列上。

offloaded 模式,XDP BPF程序直接工作在NIC中处理报文,一般是智能网卡的模式。

当上述两种模式都不支持的时候,可以使用通用模式。

今天我们将要分析的对象是 Native XDP 、Generic XDP在Linux内核中的挂载点。

网卡的两种工作模式

网卡有两种工作模式:

1) 软中断收包模式,该机制的特点是直接在软中断函数将报文传递到网络协议栈。

2)软中断唤醒轮询模式(NAPI),该机制的特点是在软中断函数中,唤醒网卡驱动注册的poll函数,通过poll函数轮询收包。

API 是一种新技术,目前不是所有网卡驱动都支持这种能力,你如果想确定网卡是不是支持NAPI,有很多方式,其中一种就是查一下网卡驱动是否有实现xxxx_poll函数,比如ixgbe的驱动实现了ixgbe_poll函数。

这两种模式分别对应了XDP的 Generic XDP 和 Native XDP模式。这两种模式的代码汇总点其实都在软中断函数中(比如ixgbe的ixgb_clean_rx_irq函数)。Generic XDP工作在上述的第一种模式,Native XDP则工作在上述的第二种模式。

Generic XDP hook

bpf_prog_run_xdp是XDP 程序的最终调用函数,想要跟踪Generic XDP的代码可以从该函数入手,很显然你不应该在drivers/,而是在net/目录下检索:

xxx@xxx grep -rn "bpf_prog_run_xdp" net net/core/dev.c:4349: act = bpf_prog_run_xdp(xdp_prog, xdp);

稍微过滤一下真相就呼之欲出了,函数的调用关系如下:

bpf_prog_run_xdp netif_receive_generic_xdp do_xdp_generic netif_rx_internal/netif_receive_skb_internal/netif_receive_skb_list_interna netif_receive_skb ixgb_clean_rx_irq //Send received data up the network stack

从调用关系上很容易推导出 Generic XDP的Hook点是在网卡中断的下半部。也即是在网卡软中断的收包流程中,软中断收到报文后直接传递给网络协议栈。

Native XDP hook

bpf_prog_run_xdp是XDP 程序的最终调用函数,想要跟踪Native XDP的代码可以从该函数入手,很显然你不应该在/,而是在drivers/目录下检索:

xxxxx@xxxx grep -rn "bpf_prog_run_xdp" . ./net/core/dev.c:4324: act = bpf_prog_run_xdp(xdp_prog, xdp); ./drivers/net/tun.c:1634: act = bpf_prog_run_xdp(xdp_prog, &xdp); ./drivers/net/ethernet/intel/i40e/i40e_txrx.c:2242: act = bpf_prog_run_xdp(xdp_prog, xdp); ./drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:2214: act = bpf_prog_run_xdp(xdp_prog, xdp); ./drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:1067: act = bpf_prog_run_xdp(xdp_prog, xdp); ./drivers/net/ethernet/qlogic/qede/qede_fp.c:1084: act = bpf_prog_run_xdp(prog, &xdp); ./drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c:106: act = bpf_prog_run_xdp(xdp_prog, &xdp); ./drivers/net/ethernet/mellanox/mlx4/en_rx.c:775: act = bpf_prog_run_xdp(xdp_prog, &xdp); ./drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c:71: act = bpf_prog_run_xdp(prog, &xdp); ./drivers/net/ethernet/netronome/nfp/nfp_net_common.c:1744: act = bpf_prog_run_xdp(xdp_prog, &xdp); ./drivers/net/ethernet/cavium/thunder/nicvf_main.c:538: action = bpf_prog_run_xdp(prog, &xdp); ./drivers/net/veth.c:399: act = bpf_prog_run_xdp(xdp_prog, &xdp); ./drivers/net/veth.c:525: act = bpf_prog_run_xdp(xdp_prog, &xdp); ./drivers/net/virtio_net.c:668: act = bpf_prog_run_xdp(xdp_prog, &xdp); ./drivers/net/virtio_net.c:823: act = bpf_prog_run_xdp(xdp_prog, &xdp); ./include/linux/filter.h:619:static __always_inline u32 bpf_prog_run_xdp(const struct bpf_prog *prog,

估计你检索出来的结果和我相同,但这不是重点,重点是我们发现bpf_prog_run_xdp确实是在网卡驱动中调用,印证了前面讲都Native XDP工作在网卡驱动中。

到这里我们只要找到网卡驱动中bpf_prog_run_xdp函数的调用关系就能找到Natvie XDP的hook点了,调用关系整理如下:

bpf_prog_run_xdp ixgbe_run_xdp ixgbe_poll ixgbe_clean_rx_irq

答案已经很明显了,在网卡的驱动函数中,网卡的两种工作模式分别实现了两种不同的XDP功能,很显然Native XDP的性能是高于Generic XDP的,一方面是由于网卡两种模式的性能差异,还有一方面是XDP本身hook路径的差异性造成的。

bpf_prog_run_xdp函数

顺着bpf_prog_run_xdp的调用关系我们找到了Generic XDP和Native XDP的hook点,bpf_prog_run_xdp这个函数很关键,下面我们具体看看这个函数代码:

static __always_inline u32 bpf_prog_run_xdp(const struct bpf_prog *prog, struct xdp_buff *xdp) { /* Caller needs to hold rcu_read_lock() (!), otherwise program * can be released while still running, or map elements could be * freed early while still having concurrent users. XDP fastpath * already takes rcu_read_lock() when fetching the program, so * it's not necessary here anymore. */ return BPF_PROG_RUN(prog, xdp); } #define BPF_PROG_RUN(filter, ctx) (*(filter)->bpf_func)(ctx, (filter)->insnsi)

从代码上很简单了,就是单纯地调用你注册的功能函数,仅此而已。当然BPF_PROG_RUN宏还告诉了你一个细节,那么就是一个网卡只能注册一个XDP功能程序,当然在这个代码片段不足以揭露细节,但确实是如此,你可以自己看看网卡的bpf_prog对象更新代码,就能明白一切。

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved