Opened 22 months ago

Closed 22 months ago

Last modified 22 months ago

#2424 closed defect (invalid)

quic_bpf failed

Reported by: LyraWang@… Owned by:
Priority: minor Milestone: nginx-1.23
Component: nginx-core Version: 1.21.x
Keywords: ebpf BPF_MAP_CREATE ngx_bpf_map_create Cc:
uname -a: Linux h3c-R4900 5.4.0-126-generic #142~18.04.1-Ubuntu SMP Thu Sep 1 16:25:16 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.23.1
built by gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)
built with OpenSSL 1.1.1 (compatible; BoringSSL) (running with BoringSSL)
TLS SNI support enabled
configure arguments: --with-debug --prefix=/home/nginx --with-http_ssl_module --with-http_v2_module --with-http_v3_module --with-cc-opt=-I../boringssl-master/include --with-ld-opt='-L../boringssl-master/build/ssl -L../boringssl-master/build/crypto'

Description

when "quic_bpf on;"
there comes "nginx: [alert] failed to create BPF map (22: Invalid argument)" when ngx_bpf_map_create.

Change History (7)

comment:1 by Maxim Dounin, 22 months ago

Priority: criticalminor

Could you please check if the kernel header files used during nginx-quic compilation match the kernel being used?

comment:2 by LyraWang@…, 22 months ago

Actually they may not match. I couldn't find BPF_MAP_TYPE_SOCKHASH in /usr/include/linux/bpf.h, But I found it in "/usr/src/linux-hwe-5.4-headers-5.4.0-126/include/uapi/linux/bpf.h". I was confused why are they not matched. I copied /usr/src/linux-hwe-5.4-headers-5.4.0-126/include/uapi/linux/bpf.h to /usr/include/linux/bpf.h, so my compilation passed. But invalid arguement seems told that the kernel can't recognize it. So do I need to recompile the kernel with any bpf related option or what other things could be done to make it work?

comment:3 by Maxim Dounin, 22 months ago

Resolution: invalid
Status: newclosed

As long as the 5.4.0 kernel is actually installed, BPF_MAP_TYPE_SOCKHASH should be recognized properly. But overwriting just a single file in /usr/include/linux with a newer version might not be a good idea, and might result in arbitrary unexpected issues, including the one you are seeing.

I don't think there is an easy way to compile nginx with linux kernel headers different from the ones provided in /usr/include/linux by the libc. A better approach might be to actually upgrade to an OS version which provides BPF_MAP_TYPE_SOCKHASH.

comment:4 by LyraWang@…, 22 months ago

Yes, when the OS version upgrade to ubuntu2204, problem solved. But it can't even work in ubuntu2104. BPF_MAP_TYPE_SOCKHASH has been supported in kernel 4.18, while kernel of ubuntu1804 is 5.4 and kernel of ubuntu2104 if 5.11. I'm so confused, is operating system do any thing to the kernel? And Is there anything could be done to make the lower OS work?

comment:5 by Maxim Dounin, 22 months ago

Appropriate headers are shipped by Ubuntu in the linux-libc-dev package. These match the GA kernel as shipped in the particular OS version, and not updated with HWE kernels. In particular, in Ubuntu 18.04 these headers are from kernel 4.15, so BPF_MAP_TYPE_SOCKHASH is not expected to work there.

As for Ubuntu 21.04, not sure what goes wrong there. Note though that this Ubuntu version is EOLed and no longer supported.

On Ubuntu 20.04 LTS it compiles fine, but only works with HWE kernel 5.15. With GA kernel 5.4 it results in the EINVAL errors from bpf(BPF_MAP_TYPE_SOCKHASH), similarly to what you've seen on Ubuntu 18.04 with the same kernel, as originally reported. Looks like an issue in the kernel and/or some incompatibility in the headers, this commit (appeared in kernel 5.6) might be related.

comment:6 by LyraWang@…, 22 months ago

Thank you very much. I've solved the problem by recompiling linux kernel. It seems original installed OS missed some BPF configs when installed. I almost turned on every bpf related config while compiling kernel, since I don't know which one really make impact.

comment:7 by vl, 22 months ago

The EINVAL comes from passing 64-bit for values.
This was not allowed till this commit:

commit c1cdf65da060a8e047a9f4433306fd6dac1f51a6
Author: Jakub Sitnicki <jakub@…>
Date: Tue Feb 18 17:10:18 2020 +0000

bpf, sockmap: Return socket cookie on lookup from syscall


Tooling that populates the SOCK{MAP,HASH} with sockets from user-space
needs a way to inspect its contents. Returning the struct sock * that the
map holds to user-space is neither safe nor useful. An approach established
by REUSEPORT_SOCKARRAY is to return a socket cookie (a unique identifier)
instead.


Since socket cookies are u64 values, SOCK{MAP,HASH} need to support such a
value size for lookup to be possible. This requires special handling on
update, though. Attempts to do a lookup on a map holding u32 values will be
met with ENOSPC error.

The corresponding kernel version is 5.7

nginx uses sockhash map to deal with socket cookies, i.e. exactly the case described.

This explains why it doesn't work with 5.4 and works with later 5.15.

Note: See TracTickets for help on using tickets.