Ebpf function and doubts in its usage

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Dear Linux Kernel team,

I hope this message finds you well, I am seeking your assistance in the correct usage of the function bpf_dynptr_slice() please.

The program being developed is supposed to captures all the packets that pass through the Prerouting stage of the Netfilter packet flow, so the program is required to be of ebpf Netfilter program type. As the objective is to copy large portions of the captured packets to user-space for processing, without consuming them, a ringbuffer map type is used for storage and communication.

According to the ebpf official page (Link to the Netfilter program type page: https://docs.ebpf.io/linux/program-type/BPF_PROG_TYPE_NETFILTER/), this program type needs to read the packet with the dynptr interface, plus (Link to the bpf_dynptr_from_skb() function page: https://docs.ebpf.io/linux/kfuncs/bpf_dynptr_from_skb/) the correct and only way to access the packets captured is through the bpf_dynptr_slice() or bpf_dynptr_read() functions ("For reads and writes through the bpf_dynptr_read() and bpf_dynptr_write() interfaces, reading and writing from/to data in the head as well as from/to non-linear paged buffers is supported. Data slices through the bpf_dynptr_data API are not supported; instead bpf_dynptr_slice() and bpf_dynptr_slice_rdwr() should be used."). 

In order to write to the ringbuffer, the api provided needs to be respected (Link to the list of functions that ringbuffer maps support: https://docs.ebpf.io/linux/map-type/BPF_MAP_TYPE_RINGBUF/), so the bpf_dynptr_read() function can't be used, as it can't write to the ringbuffer, so it would need space to store the packet information, and some (most) of the packets need more space than the ebpf verifier allows (512 Bytes, this limit can be changed, however it is not the first option in this program). So, the bpf_dynptr_slice() was chosen.

I think I understand the description presented in the official page and the signature of the function, but if you see any mistakes or misunderstandings, please feel free to correct them. The current problem is with the verifier. According to it, the 4^th argument of bpf_dynptr_slice() needs to be a known constant at compile time (figure 1 in attachments). However, the packets received don't have the same size, and the data part's sizes the user-space will need also varies. The following attempts were tried in a Ubuntu 24.04.01 LTS with a kernel version 6.8.0-52:

1. Switch case with the possible sizes, with the maximum size as 1099 bytes per packet. (the clang optimizer placed a variable instead of the values of the 4^th argument)
2. Place bpf_dynptr_size() in the 4^th argument
3. Declare const unsigned int size=sz and use size as the 4^th argument
4. Create a function that returned an unsigned int and use it in the 4^th argument, and use it in the declaration of the const unsigned int size

The only way the code works is with brute force: Do the function, if it fails subtract one and do it again, always with the explicit value in the fourth argument, never with a variable. (figure 2 attached). This is not an optimal solution, but a better one wasn't found.

What is the intended way of doing this?

Thank you very much for your time and assistance, and I'm looking forward to your response.

Francisco Carvalho,
email: francisco.s.carvalho@xxxxxx

Attachment: Verifier_doesn't_allow_vars.png
Description: Verifier_doesn't_allow_vars.png

Attachment: Bad_solution.png
Description: Bad_solution.png


[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux