xref: /openbmc/qemu/docs/devel/ebpf_rss.rst (revision 526f1f3a5c6726e3d3b893d8063d31fda091c7e0)
194645620SAndrew Melnychenko===========================
294645620SAndrew MelnychenkoeBPF RSS virtio-net support
394645620SAndrew Melnychenko===========================
494645620SAndrew Melnychenko
594645620SAndrew MelnychenkoRSS(Receive Side Scaling) is used to distribute network packets to guest virtqueues
694645620SAndrew Melnychenkoby calculating packet hash. Usually every queue is processed then by a specific guest CPU core.
794645620SAndrew Melnychenko
894645620SAndrew MelnychenkoFor now there are 2 RSS implementations in qemu:
994645620SAndrew Melnychenko- 'in-qemu' RSS (functions if qemu receives network packets, i.e. vhost=off)
1094645620SAndrew Melnychenko- eBPF RSS (can function with also with vhost=on)
1194645620SAndrew Melnychenko
1294645620SAndrew MelnychenkoeBPF support (CONFIG_EBPF) is enabled by 'configure' script.
1394645620SAndrew MelnychenkoTo enable eBPF RSS support use './configure --enable-bpf'.
1494645620SAndrew Melnychenko
1594645620SAndrew MelnychenkoIf steering BPF is not set for kernel's TUN module, the TUN uses automatic selection
1694645620SAndrew Melnychenkoof rx virtqueue based on lookup table built according to calculated symmetric hash
1794645620SAndrew Melnychenkoof transmitted packets.
1894645620SAndrew MelnychenkoIf steering BPF is set for TUN the BPF code calculates the hash of packet header and
1994645620SAndrew Melnychenkoreturns the virtqueue number to place the packet to.
2094645620SAndrew Melnychenko
2194645620SAndrew MelnychenkoSimplified decision formula:
2294645620SAndrew Melnychenko
2394645620SAndrew Melnychenko.. code:: C
2494645620SAndrew Melnychenko
2594645620SAndrew Melnychenko    queue_index = indirection_table[hash(<packet data>)%<indirection_table size>]
2694645620SAndrew Melnychenko
2794645620SAndrew Melnychenko
2894645620SAndrew MelnychenkoNot for all packets, the hash can/should be calculated.
2994645620SAndrew Melnychenko
3094645620SAndrew MelnychenkoNote: currently, eBPF RSS does not support hash reporting.
3194645620SAndrew Melnychenko
3294645620SAndrew MelnychenkoeBPF RSS turned on by different combinations of vhost-net, vitrio-net and tap configurations:
3394645620SAndrew Melnychenko
3494645620SAndrew Melnychenko- eBPF is used:
3594645620SAndrew Melnychenko
3694645620SAndrew Melnychenko        tap,vhost=off & virtio-net-pci,rss=on,hash=off
3794645620SAndrew Melnychenko
3894645620SAndrew Melnychenko- eBPF is used:
3994645620SAndrew Melnychenko
4094645620SAndrew Melnychenko        tap,vhost=on & virtio-net-pci,rss=on,hash=off
4194645620SAndrew Melnychenko
4294645620SAndrew Melnychenko- 'in-qemu' RSS is used:
4394645620SAndrew Melnychenko
4494645620SAndrew Melnychenko        tap,vhost=off & virtio-net-pci,rss=on,hash=on
4594645620SAndrew Melnychenko
4694645620SAndrew Melnychenko- eBPF is used, hash population feature is not reported to the guest:
4794645620SAndrew Melnychenko
4894645620SAndrew Melnychenko        tap,vhost=on & virtio-net-pci,rss=on,hash=on
4994645620SAndrew Melnychenko
5094645620SAndrew MelnychenkoIf CONFIG_EBPF is not set then only 'in-qemu' RSS is supported.
5194645620SAndrew MelnychenkoAlso 'in-qemu' RSS, as a fallback, is used if the eBPF program failed to load or set to TUN.
5294645620SAndrew Melnychenko
5394645620SAndrew MelnychenkoRSS eBPF program
5494645620SAndrew Melnychenko----------------
5594645620SAndrew Melnychenko
5694645620SAndrew MelnychenkoRSS program located in ebpf/rss.bpf.skeleton.h generated by bpftool.
5794645620SAndrew MelnychenkoSo the program is part of the qemu binary.
5894645620SAndrew MelnychenkoInitially, the eBPF program was compiled by clang and source code located at tools/ebpf/rss.bpf.c.
5994645620SAndrew MelnychenkoPrerequisites to recompile the eBPF program (regenerate ebpf/rss.bpf.skeleton.h):
6094645620SAndrew Melnychenko
6194645620SAndrew Melnychenko        llvm, clang, kernel source tree, bpftool
6294645620SAndrew Melnychenko        Adjust Makefile.ebpf to reflect the location of the kernel source tree
6394645620SAndrew Melnychenko
6494645620SAndrew Melnychenko        $ cd tools/ebpf
6594645620SAndrew Melnychenko        $ make -f Makefile.ebpf
6694645620SAndrew Melnychenko
6794645620SAndrew MelnychenkoCurrent eBPF RSS implementation uses 'bounded loops' with 'backward jump instructions' which present in the last kernels.
6894645620SAndrew MelnychenkoOverall eBPF RSS works on kernels 5.8+.
6994645620SAndrew Melnychenko
7094645620SAndrew MelnychenkoeBPF RSS implementation
7194645620SAndrew Melnychenko-----------------------
7294645620SAndrew Melnychenko
7394645620SAndrew MelnychenkoeBPF RSS loading functionality located in ebpf/ebpf_rss.c and ebpf/ebpf_rss.h.
7494645620SAndrew Melnychenko
75*f0d7b970SPeter MaydellThe ``struct EBPFRSSContext`` structure that holds 4 file descriptors:
7694645620SAndrew Melnychenko
7794645620SAndrew Melnychenko- ctx - pointer of the libbpf context.
7894645620SAndrew Melnychenko- program_fd - file descriptor of the eBPF RSS program.
7994645620SAndrew Melnychenko- map_configuration - file descriptor of the 'configuration' map. This map contains one element of 'struct EBPFRSSConfig'. This configuration determines eBPF program behavior.
8094645620SAndrew Melnychenko- map_toeplitz_key - file descriptor of the 'Toeplitz key' map. One element of the 40byte key prepared for the hashing algorithm.
8194645620SAndrew Melnychenko- map_indirections_table - 128 elements of queue indexes.
8294645620SAndrew Melnychenko
83*f0d7b970SPeter Maydell``struct EBPFRSSConfig`` fields:
8494645620SAndrew Melnychenko
85*f0d7b970SPeter Maydell- redirect - "boolean" value, should the hash be calculated, on false  - ``default_queue`` would be used as the final decision.
8694645620SAndrew Melnychenko- populate_hash - for now, not used. eBPF RSS doesn't support hash reporting.
87*f0d7b970SPeter Maydell- 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.
8894645620SAndrew Melnychenko- indirections_len - length of the indirections table, maximum 128.
8994645620SAndrew Melnychenko- 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).
9094645620SAndrew Melnychenko
9194645620SAndrew MelnychenkoFunctions:
9294645620SAndrew Melnychenko
93*f0d7b970SPeter Maydell- ``ebpf_rss_init()`` - sets ctx to NULL, which indicates that EBPFRSSContext is not loaded.
94*f0d7b970SPeter Maydell- ``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.
95*f0d7b970SPeter Maydell- ``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.
96*f0d7b970SPeter Maydell- ``ebpf_rss_unload()`` - close all file descriptors and set ctx to NULL.
9794645620SAndrew Melnychenko
9894645620SAndrew MelnychenkoSimplified eBPF RSS workflow:
9994645620SAndrew Melnychenko
10094645620SAndrew Melnychenko.. code:: C
10194645620SAndrew Melnychenko
10294645620SAndrew Melnychenko    struct EBPFRSSConfig config;
10394645620SAndrew Melnychenko    config.redirect = 1;
10494645620SAndrew Melnychenko    config.hash_types = VIRTIO_NET_RSS_HASH_TYPE_UDPv4 | VIRTIO_NET_RSS_HASH_TYPE_TCPv4;
10594645620SAndrew Melnychenko    config.indirections_len = VIRTIO_NET_RSS_MAX_TABLE_LEN;
10694645620SAndrew Melnychenko    config.default_queue = 0;
10794645620SAndrew Melnychenko
10894645620SAndrew Melnychenko    uint16_t table[VIRTIO_NET_RSS_MAX_TABLE_LEN] = {...};
10994645620SAndrew Melnychenko    uint8_t key[VIRTIO_NET_RSS_MAX_KEY_SIZE] = {...};
11094645620SAndrew Melnychenko
11194645620SAndrew Melnychenko    struct EBPFRSSContext ctx;
11294645620SAndrew Melnychenko    ebpf_rss_init(&ctx);
11394645620SAndrew Melnychenko    ebpf_rss_load(&ctx);
11494645620SAndrew Melnychenko    ebpf_rss_set_all(&ctx, &config, table, key);
11594645620SAndrew Melnychenko    if (net_client->info->set_steering_ebpf != NULL) {
11694645620SAndrew Melnychenko        net_client->info->set_steering_ebpf(net_client, ctx->program_fd);
11794645620SAndrew Melnychenko    }
11894645620SAndrew Melnychenko    ...
11994645620SAndrew Melnychenko    ebpf_unload(&ctx);
12094645620SAndrew Melnychenko
12194645620SAndrew Melnychenko
12294645620SAndrew MelnychenkoNetClientState SetSteeringEBPF()
12394645620SAndrew Melnychenko~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12494645620SAndrew Melnychenko
125*f0d7b970SPeter MaydellFor now, ``set_steering_ebpf()`` method supported by Linux TAP NetClientState. The method requires an eBPF program file descriptor as an argument.
126