Skip to content

Commit 969bf05

Browse files
4astdavem330
authored andcommitted
bpf: direct packet access
Extended BPF carried over two instructions from classic to access packet data: LD_ABS and LD_IND. They're highly optimized in JITs, but due to their design they have to do length check for every access. When BPF is processing 20M packets per second single LD_ABS after JIT is consuming 3% cpu. Hence the need to optimize it further by amortizing the cost of 'off < skb_headlen' over multiple packet accesses. One option is to introduce two new eBPF instructions LD_ABS_DW and LD_IND_DW with similar usage as skb_header_pointer(). The kernel part for interpreter and x64 JIT was implemented in [1], but such new insns behave like old ld_abs and abort the program with 'return 0' if access is beyond linear data. Such hidden control flow is hard to workaround plus changing JITs and rolling out new llvm is incovenient. Therefore allow cls_bpf/act_bpf program access skb->data directly: int bpf_prog(struct __sk_buff *skb) { struct iphdr *ip; if (skb->data + sizeof(struct iphdr) + ETH_HLEN > skb->data_end) /* packet too small */ return 0; ip = skb->data + ETH_HLEN; /* access IP header fields with direct loads */ if (ip->version != 4 || ip->saddr == 0x7f000001) return 1; [...] } This solution avoids introduction of new instructions. llvm stays the same and all JITs stay the same, but verifier has to work extra hard to prove safety of the above program. For XDP the direct store instructions can be allowed as well. The skb->data is NET_IP_ALIGNED, so for common cases the verifier can check the alignment. The complex packet parsers where packet pointer is adjusted incrementally cannot be tracked for alignment, so allow byte access in such cases and misaligned access on architectures that define efficient_unaligned_access [1] https://git.kernel.org/cgit/linux/kernel/git/ast/bpf.git/?h=ld_abs_dw Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Daniel Borkmann <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1a0dc1a commit 969bf05

File tree

3 files changed

+440
-8
lines changed

3 files changed

+440
-8
lines changed

include/uapi/linux/bpf.h

+2
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,8 @@ struct __sk_buff {
370370
__u32 cb[5];
371371
__u32 hash;
372372
__u32 tc_classid;
373+
__u32 data;
374+
__u32 data_end;
373375
};
374376

375377
struct bpf_tunnel_key {

kernel/bpf/core.c

+5
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,11 @@ void __weak bpf_int_jit_compile(struct bpf_prog *prog)
794794
{
795795
}
796796

797+
bool __weak bpf_helper_changes_skb_data(void *func)
798+
{
799+
return false;
800+
}
801+
797802
/* To execute LD_ABS/LD_IND instructions __bpf_prog_run() may call
798803
* skb_copy_bits(), so provide a weak definition of it for NET-less config.
799804
*/

0 commit comments

Comments
 (0)