In rST markup, single backticks `like this` represent "interpreted text", which can be handled as a bunch of different things if tagged with a specific "role": https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#interpreted-text (the most common one for us is "reference to a URL, which gets hyperlinked"). The default "role" if none is specified is "title_reference", intended for references to book or article titles, and it renders into the HTML as <cite>...</cite> (usually comes out as italics). To format a literal (generally rendered as fixed-width font), double-backticks are required. ebpf_rss.rst gets this wrong in a few places; correct them. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-id: 20210726142338.31872-4-peter.maydell@linaro.org
		
			
				
	
	
		
			126 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| ===========================
 | |
| 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.
 |