eBPF Talk: tc-bpf 转发网络包

文摘   科技   2023-05-01 08:10   新加坡  

在 tc-bpf 里转发网络包,跟 XDP 里转发网络包有什么不同呢?

呃,其实还是那个奇葩的需求,不过最近在给它做性能优化;而在优化的过程中,遇到了一些有趣的知识点。

redirect helpers 对比

helpersXDPtc-bpf
bpf_redirect
bpf_redirect_map
bpf_redirect_peer
bpf_redirect_neigh
bpf_clone_redirect

来源:${KERNEL}/net/core/filter.c 里的 xdp_verifier_opstc_cls_act_verifier_ops

tc-bpf 的 bpf_redirect

tc-bpf 使用 bpf_redirect 转发网络包也分为两个阶段:

  1. bpf_redirect() helpers 执行。
  2. TC_ACT_REDIRECT 的处理。

bpf_redirect() helpers 的源代码如下:

// ${KERNEL}/net/core/filter.c

BPF_CALL_2(bpf_redirect, u32, ifindex, u64, flags)
{
    struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);

    if (unlikely(flags & (~(BPF_F_INGRESS) | BPF_F_REDIRECT_INTERNAL)))
        return TC_ACT_SHOT;

    ri->flags = flags;
    ri->tgt_index = ifindex;

    return TC_ACT_REDIRECT;
}

接着,看下在 INGRESS 阶段 tc 对 TC_ACT_REDIRECT 的处理逻辑:

__netif_receive_skb_core()                          // ${KERNEL}/net/core/dev.c
|-->sch_handle_ingress()
    |-->tcf_classify() {                            // ${KERNEL}/net/sched/cls_api.c
        switch (tcf_classify(skb, miniq->block, miniq->filter_list, &cl_res, false)) {
        case TC_ACT_REDIRECT:
                /* skb_mac_header check was done by cls/act_bpf, so
                * we can safely push the L2 header back before
                * redirecting to another netdev
                */

                __skb_push(skb, skb->mac_len);
                if (skb_do_redirect(skb) == -EAGAIN) {
                    __skb_pull(skb, skb->mac_len);
                    *another = true;
                    break;
                }
                return NULL;
        }
        |-->skb_do_redirect()                       // ${KERNEL}/net/core/filter.c
            |-->__bpf_redirect()
                |-->__bpf_redirect_common()
                    |-->__bpf_tx_skb()
                        |-->dev_queue_xmit()        // ${KERNEL}/net/core/dev.c

最终,可以看到 tc-bpf 的 bpf_redirect 是调用 dev_queue_xmit() 发包的;从而,该网络包会经历目标网络设备的 tc EGRESS 处理阶段,并能够被 tcpdump 抓到。

而 XDP bpf_redirect 调用的是网卡驱动的发包函数 ops->ndo_start_xmit(skb, dev); 直接将网络包发送出去了。

小结

tc INGRESS 里使用 tc-bpf 转发网络包发送出去时,该网络包会经历目标网络设备的 tc EGRESS 处理阶段,并能够被 tcpdump 抓到。

eBPF Talk
专注于 eBPF 技术,以及 Linux 网络上的 eBPF 技术应用