• A
    bpf: direct packet access · 969bf05e
    Alexei Starovoitov 提交于
    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_dwSigned-off-by: NAlexei Starovoitov <ast@kernel.org>
    Acked-by: NDaniel Borkmann <daniel@iogearbox.net>
    Signed-off-by: NDavid S. Miller <davem@davemloft.net>
    969bf05e
bpf.h 10.8 KB