1

I started coding in ebpf and XDP. I am using python bcc to load the XDP program to the NICs. I am trying to work with __sk_buff structure, but when I am trying to access any filed of skb the verifier failed to load the program.

int xdp_test(struct sk_buff *skb)
{
    void *data = (void*)(long)skb->data;
    void *data_end = (void*)(long)skb->data_end;

    if (data + sizeof(struct ethhdr) + sizeof(struct iphdr) < data_end)
    {
        struct iphdr * ip = ip_hdr(skb);
        // according to my checks, it failed because of this line. I cant access to ip->protocol (or any other fileds)
        if (ip->protocol == IPPROTO_TCP)
        {
               return XDP_PASS;
        }
    }
    ...
    return XDP_PASS
}

I just want to calculates layer 4 checksum on my program using bpf_l4_csum_replace Which takes skb as the first argument.

Why is that happening? Can I even use __sk_buff structure in XDP? Or I have to use the xdp_md struct?

UPDATE: Thanks to Qeole, I understood that I cannot use sk_buff using XDP. There is a way to calculate TCP checksum using xdp_md?

Lidorelias3
  • 27
  • 1
  • 10

1 Answers1

2

Indeed you cannot use the struct __sk_buff in XDP programs. You have to use the struct xdp_md instead. XDP performance is due for a great part to the kernel calling the eBPF program before the allocation and initialisation of the socket buffer (struct sk_buff in the kernel), which saves time and resources, but also means you don't have access to that structure in your XDP program.

pchaigno
  • 11,313
  • 2
  • 29
  • 54
Qeole
  • 8,284
  • 1
  • 24
  • 52
  • Oh, I got it.. can you share with me a function that calculates the checksum for layer 4 when using struct xdp_md? – Lidorelias3 Feb 08 '21 at 09:42
  • [Cilium](https://github.com/cilium/cilium) has one to update L4 checksums when programs are attached to the XDP hook. I know that [this repo](https://github.com/Netronome/bpf-samples) also had an example with a similar function in the past, but I can't see it anymore :(. – Qeole Feb 08 '21 at 10:48
  • There is no easy way to calculate TCP checksum? I saw what they did in Cilium but it uses so many things. I think it's a common need to calculate the checksum. – Lidorelias3 Feb 08 '21 at 11:33
  • Not to my knowledge, I'm afraid :/. The helper is only available at higher-level hooks that get the skb, and there is no direct equivalent for XDP (I'm not sure why). So you have to reimplement the checksum computation in eBPF. Cilium's version looks complex because it has been optimised a lot to fit as well as possible in the project's datapath, but you could probably come up with something simpler/more readable. – Qeole Feb 08 '21 at 12:04
  • I found this implementation for UDP: https://github.com/iovisor/bcc/issues/2463#issuecomment-718800510 , but when I trying to print csum or put it into udp->check, the verifier failed again. Why is that happening? And for my knowledge, how can I debug and understand the verifier errors? :/ – Lidorelias3 Feb 08 '21 at 12:14
  • Hard to tell. Maybe your kernel is too old to support bounded loops. Generally you want to pass a log buffer when injecting your program, so you can get logs from the verifier. – Qeole Feb 08 '21 at 13:25
  • Ok, I managed to make this code works, but it isn’t the right checksum. If someone know why, please tell me :( – Lidorelias3 Feb 08 '21 at 14:21