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