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