eBPF Talk: packet range check
在 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
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/smAZOASTfZIkmnVNLOW4tA