mirror of
				https://passt.top/passt
				synced 2025-10-26 00:59:13 +02:00 
			
		
		
		
	passt, pasta: Run-time selection of AVX2 build
Build-time selection of AVX2 flags and routines is not practical for distributions, but limiting AVX2 usage to checksum routines with specific run-time detection doesn't allow for easy performance gains from auto-vectorisation of batched packet handling routines. For x86_64, build non-AVX2 and AVX2 binaries, and implement a simple wrapper replacing the current executable with the AVX2 build if it's available, and if AVX2 is supported by the current CPU. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
		
					parent
					
						
							
								deca1ebe50
							
						
					
				
			
			
				commit
				
					
						213c397492
					
				
			
		
					 9 changed files with 92 additions and 48 deletions
				
			
		
							
								
								
									
										38
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										38
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -14,8 +14,11 @@ ifeq ($(RLIMIT_STACK_VAL),unlimited) | |||
| RLIMIT_STACK_VAL := 1024 | ||||
| endif | ||||
| 
 | ||||
| AUDIT_ARCH := $(shell uname -m | tr [a-z] [A-Z]) | ||||
| AUDIT_ARCH := $(shell echo $(AUDIT_ARCH) | sed 's/^ARM.*/ARM/') | ||||
| # Get 'uname -m'-like architecture description for target
 | ||||
| TARGET_ARCH := $(shell $(CC) -dumpmachine | cut -f1 -d- | tr [a-z] [A-Z]) | ||||
| TARGET_ARCH := $(shell echo $(TARGET_ARCH) | sed 's/POWERPC/PPC/') | ||||
| 
 | ||||
| AUDIT_ARCH := $(shell echo $(TARGET_ARCH) | sed 's/^ARM.*/ARM/') | ||||
| AUDIT_ARCH := $(shell echo $(AUDIT_ARCH) | sed 's/I[456]86/I386/') | ||||
| AUDIT_ARCH := $(shell echo $(AUDIT_ARCH) | sed 's/PPC64/PPC/') | ||||
| AUDIT_ARCH := $(shell echo $(AUDIT_ARCH) | sed 's/PPCLE/PPC64LE/') | ||||
|  | @ -25,7 +28,7 @@ CFLAGS += -DPAGE_SIZE=$(shell getconf PAGE_SIZE) | |||
| CFLAGS += -DNETNS_RUN_DIR=\"/run/netns\" | ||||
| CFLAGS += -DPASST_AUDIT_ARCH=AUDIT_ARCH_$(AUDIT_ARCH) | ||||
| CFLAGS += -DRLIMIT_STACK_VAL=$(RLIMIT_STACK_VAL) | ||||
| CFLAGS += -DARCH=\"$(shell uname -m)\" | ||||
| CFLAGS += -DARCH=\"$(TARGET_ARCH)\" | ||||
| 
 | ||||
| # On gcc 11.2, with -O2 and -flto, tcp_hash() and siphash_20b(), if inlined,
 | ||||
| # seem to be hitting something similar to:
 | ||||
|  | @ -63,10 +66,13 @@ endif | |||
| 
 | ||||
| prefix ?= /usr/local | ||||
| 
 | ||||
| ifeq ($(TARGET_ARCH),X86_64) | ||||
| all: passt passt.avx2 pasta pasta.avx2 qrap | ||||
| BIN := passt passt.avx2 pasta pasta.avx2 qrap | ||||
| else | ||||
| all: passt pasta qrap | ||||
| 
 | ||||
| avx2: CFLAGS += -Ofast -mavx2 -ftree-vectorize -funroll-loops | ||||
| avx2: clean all | ||||
| BIN := passt pasta qrap | ||||
| endif | ||||
| 
 | ||||
| static: CFLAGS += -static -DGLIBC_NO_STATIC_NSS | ||||
| static: clean all | ||||
|  | @ -78,6 +84,16 @@ passt: $(filter-out qrap.c,$(wildcard *.c)) \ | |||
| 	$(filter-out qrap.h,$(wildcard *.h)) seccomp.h | ||||
| 	$(CC) $(CFLAGS) $(filter-out qrap.c,$(wildcard *.c)) -o passt | ||||
| 
 | ||||
| passt.avx2: CFLAGS += -Ofast -mavx2 -ftree-vectorize -funroll-loops | ||||
| passt.avx2: $(filter-out qrap.c,$(wildcard *.c)) \ | ||||
| 	$(filter-out qrap.h,$(wildcard *.h)) seccomp.h | ||||
| 	$(CC) $(CFLAGS) $(filter-out qrap.c,$(wildcard *.c)) -o passt.avx2 | ||||
| 
 | ||||
| passt.avx2: passt | ||||
| 
 | ||||
| pasta.avx2: passt.avx2 | ||||
| 	ln -s passt.avx2 pasta.avx2 | ||||
| 
 | ||||
| pasta: passt | ||||
| 	ln -s passt pasta | ||||
| 	ln -s passt.1 pasta.1 | ||||
|  | @ -88,24 +104,26 @@ qrap: qrap.c passt.h | |||
| 
 | ||||
| .PHONY: clean | ||||
| clean: | ||||
| 	-${RM} passt *.o seccomp.h qrap pasta pasta.1 \
 | ||||
| 	-${RM} passt passt.avx2 *.o seccomp.h qrap pasta pasta.avx2 pasta.1 \
 | ||||
| 		passt.tar passt.tar.gz *.deb *.rpm | ||||
| 
 | ||||
| install: passt pasta qrap | ||||
| install: $(BIN) | ||||
| 	mkdir -p $(DESTDIR)$(prefix)/bin $(DESTDIR)$(prefix)/share/man/man1 | ||||
| 	cp -d passt pasta qrap $(DESTDIR)$(prefix)/bin | ||||
| 	cp -d $(BIN) $(DESTDIR)$(prefix)/bin | ||||
| 	cp -d passt.1 pasta.1 qrap.1 $(DESTDIR)$(prefix)/share/man/man1 | ||||
| 
 | ||||
| uninstall: | ||||
| 	-${RM} $(DESTDIR)$(prefix)/bin/passt | ||||
| 	-${RM} $(DESTDIR)$(prefix)/bin/passt.avx2 | ||||
| 	-${RM} $(DESTDIR)$(prefix)/bin/pasta | ||||
| 	-${RM} $(DESTDIR)$(prefix)/bin/pasta.avx2 | ||||
| 	-${RM} $(DESTDIR)$(prefix)/bin/qrap | ||||
| 	-${RM} $(DESTDIR)$(prefix)/share/man/man1/passt.1 | ||||
| 	-${RM} $(DESTDIR)$(prefix)/share/man/man1/pasta.1 | ||||
| 	-${RM} $(DESTDIR)$(prefix)/share/man/man1/qrap.1 | ||||
| 
 | ||||
| pkgs: | ||||
| 	tar cf passt.tar -P --xform 's//\/usr\/bin\//' passt pasta qrap | ||||
| 	tar cf passt.tar -P --xform 's//\/usr\/bin\//' $(BIN) | ||||
| 	tar rf passt.tar -P --xform 's//\/usr\/share\/man\/man1\//' \
 | ||||
| 		passt.1 pasta.1 qrap.1 | ||||
| 	gzip passt.tar | ||||
|  |  | |||
							
								
								
									
										28
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										28
									
								
								README.md
									
										
									
									
									
								
							|  | @ -220,7 +220,7 @@ speeding up local connections, and usually requiring NAT. _pasta_: | |||
| * Linux | ||||
|     * ✅ starting from 4.18 kernel version | ||||
|     * ✅ starting from 3.13 kernel version | ||||
| * 🛠 build-time selection of AVX2 instructions (as much as possible) | ||||
| * ✅ run-time selection of AVX2 build | ||||
| * ⌚ [_musl_](https://bugs.passt.top/show_bug.cgi?id=4) and | ||||
|   [_uClibc-ng_](https://bugs.passt.top/show_bug.cgi?id=5) | ||||
| * ⌚ [FreeBSD](https://bugs.passt.top/show_bug.cgi?id=6), | ||||
|  | @ -467,15 +467,12 @@ Test logs [here](/builds/latest/test/). | |||
|         cd passt | ||||
|         make | ||||
| 
 | ||||
|     * alternatively, static builds for x86_64, with or without AVX2 instructions, | ||||
|       as of the latest commit are also available for convenience | ||||
|       [here](/builds/latest/x86_64/avx2/) and | ||||
|       [here](/builds/latest/x86_64/). Convenience, non-official | ||||
|       packages for Debian (and derivatives) and RPM-based distributions are also | ||||
|       available there. These binaries and packages are simply built with: | ||||
|     * alternatively, static builds for x86_64 as of the latest commit are also | ||||
|       available for convenience [here](/builds/latest/x86_64/). Convenience, | ||||
|       non-official packages for Debian (and derivatives) and RPM-based | ||||
|       distributions are also available there. These binaries and packages are | ||||
|       simply built with: | ||||
| 
 | ||||
|             CFLAGS="-static" make avx2 | ||||
|             make pkgs | ||||
|             make static | ||||
|             make pkgs | ||||
| 
 | ||||
|  | @ -530,15 +527,12 @@ Test logs [here](/builds/latest/test/). | |||
|         cd passt | ||||
|         make | ||||
| 
 | ||||
|     * alternatively, static builds for x86_64, with or without AVX2 instructions, | ||||
|       as of the latest commit are also available for convenience | ||||
|       [here](/builds/latest/x86_64/avx2/) and | ||||
|       [here](/builds/latest/x86_64/). Convenience, non-official | ||||
|       packages for Debian (and derivatives) and RPM-based distributions are also | ||||
|       available there. These binaries and packages are simply built with: | ||||
|     * alternatively, static builds for x86_64 as of the latest commit are also | ||||
|       available for convenience [here](/builds/latest/x86_64/). Convenience, | ||||
|       non-official packages for Debian (and derivatives) and RPM-based | ||||
|       distributions are also available there. These binaries and packages are | ||||
|       simply built with: | ||||
| 
 | ||||
|             CFLAGS="-static" make avx2 | ||||
|             make pkgs | ||||
|             make static | ||||
|             make pkgs | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										42
									
								
								arch.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								arch.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | |||
| // SPDX-License-Identifier: AGPL-3.0-or-later
 | ||||
| 
 | ||||
| /* PASST - Plug A Simple Socket Transport
 | ||||
|  *  for qemu/UNIX domain socket mode | ||||
|  * | ||||
|  * PASTA - Pack A Subtle Tap Abstraction | ||||
|  *  for network namespace/tap device mode | ||||
|  * | ||||
|  * arch.c - Architecture-specific implementations | ||||
|  * | ||||
|  * Copyright (c) 2022 Red Hat GmbH | ||||
|  * Author: Stefano Brivio <sbrivio@redhat.com> | ||||
|  */ | ||||
| 
 | ||||
| #include <limits.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| /**
 | ||||
|  * arch_avx2_exec() - Run AVX2 build if supported, drop suffix from argv[0] | ||||
|  * @argv:	Arguments from command line | ||||
|  */ | ||||
| #ifdef __x86_64__ | ||||
| void arch_avx2_exec(char **argv) | ||||
| { | ||||
| 	char *p = strstr(argv[0], ".avx2"); | ||||
| 
 | ||||
| 	if (p) { | ||||
| 		*p = 0; | ||||
| 	} else if (__builtin_cpu_supports("avx2")) { | ||||
| 		char path[PATH_MAX]; | ||||
| 
 | ||||
| 		snprintf(path, PATH_MAX, "%s.avx2", argv[0]); | ||||
| 		argv[0] = path; | ||||
| 		execve(path, argv, environ); | ||||
| 		perror("Can't run AVX2 build, using non-AVX2 version"); | ||||
| 	} | ||||
| } | ||||
| #else | ||||
| void arch_avx2_exec(char **argv) { (void)argv; } | ||||
| #endif | ||||
							
								
								
									
										6
									
								
								arch.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								arch.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| /* SPDX-License-Identifier: AGPL-3.0-or-later
 | ||||
|  * Copyright (c) 2022 Red Hat GmbH | ||||
|  * Author: Stefano Brivio <sbrivio@redhat.com> | ||||
|  */ | ||||
| 
 | ||||
| void arch_avx2_exec(char **argv); | ||||
|  | @ -58,15 +58,6 @@ ssh "${USER_HOST}" 				"rm -f ${BIN}/*.deb" | |||
| ssh "${USER_HOST}"				"rm -f ${BIN}/*.rpm" | ||||
| scp *.deb *.rpm					"${USER_HOST}:${BIN}/" | ||||
| 
 | ||||
| CFLAGS="-static -DGLIBC_NO_STATIC_NSS" make avx2 | ||||
| ssh "${USER_HOST}"				"mkdir -p ${BIN}/avx2" | ||||
| scp passt pasta qrap passt.1 pasta.1 qrap.1	"${USER_HOST}:${BIN}/avx2/" | ||||
| 
 | ||||
| make pkgs | ||||
| ssh "${USER_HOST}"				"rm -f ${BIN}/avx2/*.deb" | ||||
| ssh "${USER_HOST}"				"rm -f ${BIN}/avx2/*.rpm" | ||||
| scp *.deb *.rpm					"${USER_HOST}:${BIN}/avx2/" | ||||
| 
 | ||||
| ssh "${USER_HOST}"				"mv ${LATEST} ${AWAY}" | ||||
| ssh "${USER_HOST}"				"mv ${TEMP} ${LATEST}" | ||||
| ssh "${USER_HOST}"				"rm -rf ${AWAY}" | ||||
|  |  | |||
							
								
								
									
										3
									
								
								passt.c
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								passt.c
									
										
									
									
									
								
							|  | @ -69,6 +69,7 @@ | |||
| #include "tap.h" | ||||
| #include "conf.h" | ||||
| #include "pasta.h" | ||||
| #include "arch.h" | ||||
| 
 | ||||
| #define EPOLL_EVENTS		8 | ||||
| 
 | ||||
|  | @ -313,6 +314,8 @@ int main(int argc, char **argv) | |||
| 	struct sigaction sa; | ||||
| 	char *log_name; | ||||
| 
 | ||||
| 	arch_avx2_exec(argv); | ||||
| 
 | ||||
| 	check_root(); | ||||
| 	drop_caps(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -40,13 +40,3 @@ host	CFLAGS="-Werror" make | |||
| check	[ -f passt ] | ||||
| check	[ -h pasta ] | ||||
| check	[ -f qrap ] | ||||
| 
 | ||||
| test	Build AVX2 | ||||
| host	make clean | ||||
| check	! [ -e passt ] | ||||
| check	! [ -e pasta ] | ||||
| check	! [ -e qrap ] | ||||
| host	CFLAGS="-Werror" make avx2 | ||||
| check	[ -f passt ] | ||||
| check	[ -h pasta ] | ||||
| check	[ -f qrap ] | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ sleep	1 | |||
| say	 and build it. | ||||
| sleep	1 | ||||
| host	cd passt | ||||
| host	make avx2 | ||||
| host	make | ||||
| sleep	1 | ||||
| 
 | ||||
| nl | ||||
|  |  | |||
|  | @ -169,7 +169,7 @@ say	  more in the "Performance" section below. | |||
| sleep	3 | ||||
| ns	exit | ||||
| passt	exit | ||||
| passt	CFLAGS="-g" make avx2 | ||||
| passt	CFLAGS="-g" make | ||||
| sleep	2 | ||||
| passtb	perf record -g ./pasta | ||||
| sleep	2 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Stefano Brivio
				Stefano Brivio