mirror of
https://github.com/qemu/qemu.git
synced 2024-12-12 05:03:42 +08:00
docs: Added eBPF documentation.
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com> Signed-off-by: Andrew Melnychenko <andrew@daynix.com> Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
parent
0145c39348
commit
946456200e
125
docs/devel/ebpf_rss.rst
Normal file
125
docs/devel/ebpf_rss.rst
Normal file
@ -0,0 +1,125 @@
|
||||
===========================
|
||||
eBPF RSS virtio-net support
|
||||
===========================
|
||||
|
||||
RSS(Receive Side Scaling) is used to distribute network packets to guest virtqueues
|
||||
by calculating packet hash. Usually every queue is processed then by a specific guest CPU core.
|
||||
|
||||
For now there are 2 RSS implementations in qemu:
|
||||
- 'in-qemu' RSS (functions if qemu receives network packets, i.e. vhost=off)
|
||||
- eBPF RSS (can function with also with vhost=on)
|
||||
|
||||
eBPF support (CONFIG_EBPF) is enabled by 'configure' script.
|
||||
To enable eBPF RSS support use './configure --enable-bpf'.
|
||||
|
||||
If steering BPF is not set for kernel's TUN module, the TUN uses automatic selection
|
||||
of rx virtqueue based on lookup table built according to calculated symmetric hash
|
||||
of transmitted packets.
|
||||
If steering BPF is set for TUN the BPF code calculates the hash of packet header and
|
||||
returns the virtqueue number to place the packet to.
|
||||
|
||||
Simplified decision formula:
|
||||
|
||||
.. code:: C
|
||||
|
||||
queue_index = indirection_table[hash(<packet data>)%<indirection_table size>]
|
||||
|
||||
|
||||
Not for all packets, the hash can/should be calculated.
|
||||
|
||||
Note: currently, eBPF RSS does not support hash reporting.
|
||||
|
||||
eBPF RSS turned on by different combinations of vhost-net, vitrio-net and tap configurations:
|
||||
|
||||
- eBPF is used:
|
||||
|
||||
tap,vhost=off & virtio-net-pci,rss=on,hash=off
|
||||
|
||||
- eBPF is used:
|
||||
|
||||
tap,vhost=on & virtio-net-pci,rss=on,hash=off
|
||||
|
||||
- 'in-qemu' RSS is used:
|
||||
|
||||
tap,vhost=off & virtio-net-pci,rss=on,hash=on
|
||||
|
||||
- eBPF is used, hash population feature is not reported to the guest:
|
||||
|
||||
tap,vhost=on & virtio-net-pci,rss=on,hash=on
|
||||
|
||||
If CONFIG_EBPF is not set then only 'in-qemu' RSS is supported.
|
||||
Also 'in-qemu' RSS, as a fallback, is used if the eBPF program failed to load or set to TUN.
|
||||
|
||||
RSS eBPF program
|
||||
----------------
|
||||
|
||||
RSS program located in ebpf/rss.bpf.skeleton.h generated by bpftool.
|
||||
So the program is part of the qemu binary.
|
||||
Initially, the eBPF program was compiled by clang and source code located at tools/ebpf/rss.bpf.c.
|
||||
Prerequisites to recompile the eBPF program (regenerate ebpf/rss.bpf.skeleton.h):
|
||||
|
||||
llvm, clang, kernel source tree, bpftool
|
||||
Adjust Makefile.ebpf to reflect the location of the kernel source tree
|
||||
|
||||
$ cd tools/ebpf
|
||||
$ make -f Makefile.ebpf
|
||||
|
||||
Current eBPF RSS implementation uses 'bounded loops' with 'backward jump instructions' which present in the last kernels.
|
||||
Overall eBPF RSS works on kernels 5.8+.
|
||||
|
||||
eBPF RSS implementation
|
||||
-----------------------
|
||||
|
||||
eBPF RSS loading functionality located in ebpf/ebpf_rss.c and ebpf/ebpf_rss.h.
|
||||
|
||||
The `struct EBPFRSSContext` structure that holds 4 file descriptors:
|
||||
|
||||
- ctx - pointer of the libbpf context.
|
||||
- program_fd - file descriptor of the eBPF RSS program.
|
||||
- map_configuration - file descriptor of the 'configuration' map. This map contains one element of 'struct EBPFRSSConfig'. This configuration determines eBPF program behavior.
|
||||
- map_toeplitz_key - file descriptor of the 'Toeplitz key' map. One element of the 40byte key prepared for the hashing algorithm.
|
||||
- map_indirections_table - 128 elements of queue indexes.
|
||||
|
||||
`struct EBPFRSSConfig` fields:
|
||||
|
||||
- redirect - "boolean" value, should the hash be calculated, on false - `default_queue` would be used as the final decision.
|
||||
- populate_hash - for now, not used. eBPF RSS doesn't support hash reporting.
|
||||
- hash_types - binary mask of different hash types. See `VIRTIO_NET_RSS_HASH_TYPE_*` defines. If for packet hash should not be calculated - `default_queue` would be used.
|
||||
- indirections_len - length of the indirections table, maximum 128.
|
||||
- default_queue - the queue index that used for packet that shouldn't be hashed. For some packets, the hash can't be calculated(g.e ARP).
|
||||
|
||||
Functions:
|
||||
|
||||
- `ebpf_rss_init()` - sets ctx to NULL, which indicates that EBPFRSSContext is not loaded.
|
||||
- `ebpf_rss_load()` - creates 3 maps and loads eBPF program from the rss.bpf.skeleton.h. Returns 'true' on success. After that, program_fd can be used to set steering for TAP.
|
||||
- `ebpf_rss_set_all()` - sets values for eBPF maps. `indirections_table` length is in EBPFRSSConfig. `toeplitz_key` is VIRTIO_NET_RSS_MAX_KEY_SIZE aka 40 bytes array.
|
||||
- `ebpf_rss_unload()` - close all file descriptors and set ctx to NULL.
|
||||
|
||||
Simplified eBPF RSS workflow:
|
||||
|
||||
.. code:: C
|
||||
|
||||
struct EBPFRSSConfig config;
|
||||
config.redirect = 1;
|
||||
config.hash_types = VIRTIO_NET_RSS_HASH_TYPE_UDPv4 | VIRTIO_NET_RSS_HASH_TYPE_TCPv4;
|
||||
config.indirections_len = VIRTIO_NET_RSS_MAX_TABLE_LEN;
|
||||
config.default_queue = 0;
|
||||
|
||||
uint16_t table[VIRTIO_NET_RSS_MAX_TABLE_LEN] = {...};
|
||||
uint8_t key[VIRTIO_NET_RSS_MAX_KEY_SIZE] = {...};
|
||||
|
||||
struct EBPFRSSContext ctx;
|
||||
ebpf_rss_init(&ctx);
|
||||
ebpf_rss_load(&ctx);
|
||||
ebpf_rss_set_all(&ctx, &config, table, key);
|
||||
if (net_client->info->set_steering_ebpf != NULL) {
|
||||
net_client->info->set_steering_ebpf(net_client, ctx->program_fd);
|
||||
}
|
||||
...
|
||||
ebpf_unload(&ctx);
|
||||
|
||||
|
||||
NetClientState SetSteeringEBPF()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For now, `set_steering_ebpf()` method supported by Linux TAP NetClientState. The method requires an eBPF program file descriptor as an argument.
|
@ -43,3 +43,4 @@ Contents:
|
||||
qom
|
||||
block-coroutine-wrapper
|
||||
multi-process
|
||||
ebpf_rss
|
||||
|
Loading…
Reference in New Issue
Block a user