eBPF Talk: packet range check

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

在 XDP 或者 tc-bpf 中,经常要直接访问网络包内容;而在访问网络包内容之前,总是需要先检查访问的内容是否在 data_end 之内。

So,学习一下 packet range check 相关 commit 的历史;以史为镜,可以更好地掌握知识。

  • bpf: direct packet access[1] since 4.7 kernel
  • bpf: improve verifier packet range checks[2] since 4.11 kernel
  • bpf: Handle multiple variable additions into packet pointers in verifier[3] since 4.12 kernel

如果判断一个网络包是不是 IPv4 的 TCP 包的目的端口是不是 8080,可以这样写:

static __always_inline bool
__is_ipv4_tcp_udp(struct xdp_md *xdp)
{
    void *data_end = (void *)(long)xdp->data_end;
    void *data = (void *)(long)xdp->data;
    struct ethhdr *eth;
    struct iphdr *iph;
    struct tcphdr *tcph;

    eth = data;
    if ((void *)eth + sizeof(*eth) > data_end)
        return false;

    if (eth->h_proto != bpf_htons(ETH_P_IP))
        return false;

    iph = data + sizeof(*eth);
    if ((void *)iph + sizeof(*iph) > data_end)
        return false;

    if (iph->protocol != IPPROTO_TCP)
        return false;

    tcph = data + sizeof(*eth) + sizeof(*iph);
    if ((void *)tcph + sizeof(*tcph) > data_end)
        return false;

    return tcph->dest == bpf_htons(8080);
}

不过,根据 "improve verifier packet range checks",可以减少 2 次 packet range check,改为这样写:

static __always_inline bool
__is_ipv4_tcp_udp(struct xdp_md *xdp)
{
    void *data_end = (void *)(long)xdp->data_end;
    void *data = (void *)(long)xdp->data;
    struct ethhdr *eth;
    struct iphdr *iph;
    struct tcphdr *tcph;

    eth = data;
    iph = data + sizeof(*eth);
    tcph = data + sizeof(*eth) + sizeof(*iph);
    if ((void *)tcph + sizeof(*tcph) > data_end)
        return false;

    if (eth->h_proto != bpf_htons(ETH_P_IP) || iph->protocol != IPPROTO_TCP)
        return false;

    return tcph->dest == bpf_htons(8080);
}

该做法同样适用于 tc-bpf。

小结

简而言之,可以将多次 packet range check 合并为一次 packet range check,只需要检查偏移量最大的那一次即可。

参考资料

[1]

bpf: direct packet access: https://github.com/torvalds/linux/commit/969bf05eb3cedd5a8d4b7c346a85c2ede87a6d6d

[2]

bpf: improve verifier packet range checks: https://github.com/torvalds/linux/commit/b1977682a3858b5584ffea7cfb7bd863f68db18d

[3]

bpf: Handle multiple variable additions into packet pointers in verifier: https://github.com/torvalds/linux/commit/6832a333ed4a7cc4fcb170c045d1d96d0976fdd4

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