This commit is contained in:
Gabriel Clima 2026-05-26 17:24:34 +02:00 committed by GitHub
commit 631a2953be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 1746 additions and 462 deletions

View file

@ -1421,11 +1421,11 @@ if [ $USE_OPENSSL_QUIC = YES ]; then
. auto/module
if [ $QUIC_BPF = YES -a $SO_COOKIE_FOUND = YES ]; then
if [ $QUIC_BPF = YES ]; then
ngx_module_type=CORE
ngx_module_name=ngx_quic_bpf_module
ngx_module_incs=
ngx_module_deps=
ngx_module_deps=src/event/quic/ngx_event_quic_bpf.h
ngx_module_srcs="src/event/quic/ngx_event_quic_bpf.c \
src/event/quic/ngx_event_quic_bpf_code.c"
ngx_module_libs=

View file

@ -175,8 +175,6 @@ USE_GEOIP=NO
NGX_GOOGLE_PERFTOOLS=NO
NGX_CPP_TEST=NO
SO_COOKIE_FOUND=NO
NGX_LIBATOMIC=NO
NGX_CPU_CACHE_LINE=

View file

@ -236,9 +236,9 @@ fi
ngx_include="sys/vfs.h"; . auto/include
# BPF sockhash
# BPF maps
ngx_feature="BPF sockhash"
ngx_feature="BPF maps"
ngx_feature_name="NGX_HAVE_BPF"
ngx_feature_run=no
ngx_feature_incs="#include <linux/bpf.h>
@ -249,7 +249,18 @@ ngx_feature_test="union bpf_attr attr = { 0 };
attr.map_flags = 0;
attr.map_type = BPF_MAP_TYPE_SOCKHASH;
syscall(__NR_bpf, 0, &attr, 0);
attr.map_flags = 0;
attr.map_type = BPF_MAP_TYPE_SOCKMAP;
syscall(__NR_bpf, 0, &attr, 0);
attr.map_flags = 0;
attr.map_type = BPF_MAP_TYPE_ARRAY_OF_MAPS;
syscall(__NR_bpf, 0, &attr, 0);
attr.map_flags = 0;
attr.map_type = BPF_MAP_TYPE_ARRAY;
syscall(__NR_bpf, 0, &attr, 0);"
. auto/feature
@ -263,23 +274,6 @@ if [ $ngx_found = yes ]; then
fi
ngx_feature="SO_COOKIE"
ngx_feature_name="NGX_HAVE_SO_COOKIE"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
$NGX_INCLUDE_INTTYPES_H"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="socklen_t optlen = sizeof(uint64_t);
uint64_t cookie;
getsockopt(0, SOL_SOCKET, SO_COOKIE, &cookie, &optlen)"
. auto/feature
if [ $ngx_found = yes ]; then
SO_COOKIE_FOUND=YES
fi
# UDP segmentation offloading
ngx_feature="UDP_SEGMENT"

View file

@ -98,6 +98,33 @@ ngx_bpf_map_create(ngx_log_t *log, enum bpf_map_type type, int key_size,
}
int
ngx_bpf_map_create_outer(ngx_log_t *log, enum bpf_map_type type,
int max_entries, uint32_t map_flags, int template_fd)
{
int fd;
union bpf_attr attr;
ngx_memzero(&attr, sizeof(union bpf_attr));
attr.map_type = type;
attr.key_size = sizeof(uint32_t);
attr.value_size = sizeof(uint32_t);
attr.max_entries = max_entries;
attr.map_flags = map_flags;
attr.inner_map_fd = template_fd;
fd = ngx_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
if (fd < 0) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
"failed to create outer BPF map");
return NGX_ERROR;
}
return fd;
}
int
ngx_bpf_map_update(int fd, const void *key, const void *value, uint64_t flags)
{

View file

@ -35,6 +35,8 @@ int ngx_bpf_load_program(ngx_log_t *log, ngx_bpf_program_t *program);
int ngx_bpf_map_create(ngx_log_t *log, enum bpf_map_type type, int key_size,
int value_size, int max_entries, uint32_t map_flags);
int ngx_bpf_map_create_outer(ngx_log_t *log, enum bpf_map_type type,
int max_entries, uint32_t map_flags, int template_fd);
int ngx_bpf_map_update(int fd, const void *key, const void *value,
uint64_t flags);
int ngx_bpf_map_delete(int fd, const void *key);

View file

@ -8,6 +8,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
#include <ngx_event_quic.h>
ngx_os_io_t ngx_io;
@ -1143,7 +1144,34 @@ ngx_close_listening_sockets(ngx_cycle_t *cycle)
#if (NGX_QUIC)
if (ls[i].quic) {
continue;
if (!ngx_quic_bpf_enabled(cycle)) {
#if (NGX_HAVE_REUSEPORT)
/*
* during graceful shutdown, close QUIC reuseport sockets
* not owned by this worker to remove them from the reuseport
* group, preventing new connections from being routed to
* shutting-down workers by the kernel or BPF program
*/
if (ls[i].reuseport
&& ngx_process == NGX_PROCESS_WORKER
&& ls[i].worker != ngx_worker)
{
ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
"quic close reuseport %V #%d",
&ls[i].addr_text, ls[i].fd);
if (ngx_close_socket(ls[i].fd) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log,
ngx_socket_errno,
ngx_close_socket_n " %V failed",
&ls[i].addr_text);
}
ls[i].fd = (ngx_socket_t) -1;
}
#endif
continue;
}
}
#endif

View file

@ -73,6 +73,7 @@ struct ngx_event_s {
/* to test on worker exit */
unsigned channel:1;
unsigned resolver:1;
unsigned quic:1;
unsigned cancelable:1;

View file

@ -1,4 +1,4 @@
CFLAGS=-O2 -Wall
CFLAGS=-O2 -Wall $(MAKE_CFLAGS)
LICENSE=BSD

View file

@ -0,0 +1,220 @@
/* AUTO-GENERATED, DO NOT EDIT. */
#include <stddef.h>
#include <stdint.h>
#include "ngx_bpf.h"
static ngx_bpf_reloc_t bpf_reloc_prog_ngx_quic_reuseport_helper[] = {
{ "ngx_quic_connections", 119 },
{ "ngx_quic_master_state", 135 },
{ "ngx_quic_master_state", 149 },
{ "ngx_quic_master_state", 157 },
{ "ngx_quic_listen_maps", 164 },
};
static struct bpf_insn bpf_insn_prog_ngx_quic_reuseport_helper[] = {
/* opcode dst src offset imm */
{ 0xbf, BPF_REG_6, BPF_REG_1, (int16_t) 0, 0x0 },
{ 0x79, BPF_REG_9, BPF_REG_6, (int16_t) 8, 0x0 },
{ 0x79, BPF_REG_8, BPF_REG_6, (int16_t) 0, 0x0 },
{ 0xbf, BPF_REG_1, BPF_REG_8, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x9 },
{ 0x3d, BPF_REG_9, BPF_REG_1, (int16_t) 13, 0x0 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x61, BPF_REG_1, BPF_REG_6, (int16_t) 16, 0x0 },
{ 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xa },
{ 0x2d, BPF_REG_2, BPF_REG_1, (int16_t) 176, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xffffffe0 },
{ 0xbf, BPF_REG_1, BPF_REG_6, (int16_t) 0, 0x0 },
{ 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0xb7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1a },
{ 0x55, BPF_REG_0, BPF_REG_0, (int16_t) 169, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_10, (int16_t) 65504, 0x0 },
{ 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 1, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_8, (int16_t) 8, 0x0 },
{ 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x9 },
{ 0x67, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x38 },
{ 0xc7, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x38 },
{ 0x65, BPF_REG_1, BPF_REG_0, (int16_t) 19, 0xffffffff },
{ 0xbf, BPF_REG_1, BPF_REG_8, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0xe },
{ 0x3d, BPF_REG_9, BPF_REG_1, (int16_t) 13, 0x0 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x61, BPF_REG_1, BPF_REG_6, (int16_t) 16, 0x0 },
{ 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xf },
{ 0x2d, BPF_REG_2, BPF_REG_1, (int16_t) 155, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xffffffe0 },
{ 0xbf, BPF_REG_1, BPF_REG_6, (int16_t) 0, 0x0 },
{ 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xd },
{ 0xb7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1a },
{ 0x55, BPF_REG_0, BPF_REG_0, (int16_t) 148, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_10, (int16_t) 65504, 0x0 },
{ 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 1, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_8, (int16_t) 13, 0x0 },
{ 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xe },
{ 0x55, BPF_REG_1, BPF_REG_0, (int16_t) 88, 0x14 },
{ 0xf, BPF_REG_8, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0xbf, BPF_REG_1, BPF_REG_8, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x14 },
{ 0x3d, BPF_REG_9, BPF_REG_1, (int16_t) 12, 0x0 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x61, BPF_REG_1, BPF_REG_6, (int16_t) 16, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x14 },
{ 0x3d, BPF_REG_3, BPF_REG_1, (int16_t) 134, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xffffffe0 },
{ 0xbf, BPF_REG_1, BPF_REG_6, (int16_t) 0, 0x0 },
{ 0xb7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x14 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1a },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 58, 0x0 },
{ 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 127, 0x0 },
{ 0x71, BPF_REG_2, BPF_REG_8, (int16_t) 13, 0x0 },
{ 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_1, BPF_REG_8, (int16_t) 12, 0x0 },
{ 0x4f, BPF_REG_2, BPF_REG_1, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_8, (int16_t) 15, 0x0 },
{ 0x67, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 14, 0x0 },
{ 0x4f, BPF_REG_1, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_4, BPF_REG_8, (int16_t) 9, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 8, 0x0 },
{ 0x4f, BPF_REG_4, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 11, 0x0 },
{ 0x67, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_5, BPF_REG_8, (int16_t) 10, 0x0 },
{ 0x4f, BPF_REG_3, BPF_REG_5, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x10 },
{ 0x4f, BPF_REG_3, BPF_REG_4, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x10 },
{ 0x4f, BPF_REG_1, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_2, BPF_REG_8, (int16_t) 17, 0x0 },
{ 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_4, BPF_REG_8, (int16_t) 16, 0x0 },
{ 0x4f, BPF_REG_2, BPF_REG_4, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_4, BPF_REG_8, (int16_t) 19, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_5, BPF_REG_8, (int16_t) 18, 0x0 },
{ 0x4f, BPF_REG_4, BPF_REG_5, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x20 },
{ 0x4f, BPF_REG_1, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x10 },
{ 0x4f, BPF_REG_4, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 1, 0x0 },
{ 0x67, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_2, BPF_REG_8, (int16_t) 0, 0x0 },
{ 0x4f, BPF_REG_3, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_2, BPF_REG_8, (int16_t) 3, 0x0 },
{ 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_5, BPF_REG_8, (int16_t) 2, 0x0 },
{ 0x4f, BPF_REG_2, BPF_REG_5, (int16_t) 0, 0x0 },
{ 0x63, BPF_REG_10, BPF_REG_4, (int16_t) 65520, 0x0 },
{ 0x7b, BPF_REG_10, BPF_REG_1, (int16_t) 65512, 0x0 },
{ 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x10 },
{ 0x4f, BPF_REG_2, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_8, (int16_t) 5, 0x0 },
{ 0x67, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 4, 0x0 },
{ 0x4f, BPF_REG_1, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 6, 0x0 },
{ 0x71, BPF_REG_4, BPF_REG_8, (int16_t) 7, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x4f, BPF_REG_4, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x10 },
{ 0x4f, BPF_REG_4, BPF_REG_1, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x20 },
{ 0x4f, BPF_REG_4, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x7b, BPF_REG_10, BPF_REG_4, (int16_t) 65504, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xffffffe0 },
{ 0xbf, BPF_REG_1, BPF_REG_6, (int16_t) 0, 0x0 },
{ 0x18, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0xb7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x52 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x67, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x20 },
{ 0x77, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x20 },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 59, 0x0 },
{ 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0xfffffffe },
{ 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x1d, BPF_REG_0, BPF_REG_1, (int16_t) 1, 0x0 },
{ 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 54, 0x0 },
{ 0xb7, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x2 },
{ 0x63, BPF_REG_10, BPF_REG_1, (int16_t) 65532, 0x0 },
{ 0xbf, BPF_REG_2, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xfffffffc },
{ 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 46, 0x0 },
{ 0x61, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x55, BPF_REG_1, BPF_REG_0, (int16_t) 3, 0x2 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x7 },
{ 0x57, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 9, 0x0 },
{ 0xb7, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x3 },
{ 0x63, BPF_REG_10, BPF_REG_1, (int16_t) 65532, 0x0 },
{ 0xbf, BPF_REG_2, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xfffffffc },
{ 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 33, 0x0 },
{ 0x61, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x63, BPF_REG_10, BPF_REG_0, (int16_t) 65524, 0x0 },
{ 0xbf, BPF_REG_2, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xfffffff4 },
{ 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 25, 0x0 },
{ 0x61, BPF_REG_8, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0xbf, BPF_REG_2, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xfffffff4 },
{ 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 18, 0x0 },
{ 0xbf, BPF_REG_1, BPF_REG_8, (int16_t) 0, 0x0 },
{ 0x61, BPF_REG_2, BPF_REG_6, (int16_t) 32, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x3f, BPF_REG_3, BPF_REG_1, (int16_t) 0, 0x0 },
{ 0x2f, BPF_REG_3, BPF_REG_8, (int16_t) 0, 0x0 },
{ 0x1f, BPF_REG_2, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x63, BPF_REG_10, BPF_REG_2, (int16_t) 65528, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xfffffff8 },
{ 0xbf, BPF_REG_1, BPF_REG_6, (int16_t) 0, 0x0 },
{ 0xbf, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0xb7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x52 },
{ 0x67, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x20 },
{ 0x77, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x20 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 1, 0x0 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0xbf, BPF_REG_0, BPF_REG_7, (int16_t) 0, 0x0 },
{ 0x95, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
};
ngx_bpf_program_t ngx_quic_reuseport_helper = {
.relocs = bpf_reloc_prog_ngx_quic_reuseport_helper,
.nrelocs = sizeof(bpf_reloc_prog_ngx_quic_reuseport_helper)
/ sizeof(bpf_reloc_prog_ngx_quic_reuseport_helper[0]),
.ins = bpf_insn_prog_ngx_quic_reuseport_helper,
.nins = sizeof(bpf_insn_prog_ngx_quic_reuseport_helper)
/ sizeof(bpf_insn_prog_ngx_quic_reuseport_helper[0]),
.license = "BSD",
.type = BPF_PROG_TYPE_SK_REUSEPORT,
};

View file

@ -1,11 +1,12 @@
/*
* Copyright (C) Nginx, Inc.
*/
#include <errno.h>
#include <linux/string.h>
#include <linux/udp.h>
#include <linux/bpf.h>
/*
* the bpf_helpers.h is not included into linux-headers, only available
* with kernel sources in "tools/lib/bpf/bpf_helpers.h" or in libbpf.
*/
#include <bpf/bpf_helpers.h>
@ -43,98 +44,191 @@ char _license[] SEC("license") = LICENSE;
#define NGX_QUIC_PKT_LONG 0x80 /* header form */
#define NGX_QUIC_SERVER_CID_LEN 20
#define advance_data(nbytes) \
offset += nbytes; \
if (start + offset > end) { \
debugmsg("cannot read %ld bytes at offset %ld", nbytes, offset); \
goto failed; \
} \
data = start + offset - 1;
#define NGX_QUIC_BPF_NMASTERS_IDX 2
#define NGX_QUIC_BPF_ACT_MASTER_IDX 3
#define ngx_quic_parse_uint64(p) \
(((__u64)(p)[0] << 56) | \
((__u64)(p)[1] << 48) | \
((__u64)(p)[2] << 40) | \
((__u64)(p)[3] << 32) | \
((__u64)(p)[4] << 24) | \
((__u64)(p)[5] << 16) | \
((__u64)(p)[6] << 8) | \
((__u64)(p)[7]))
/*
* actual map object is created by the "bpf" system call,
* all pointers to this variable are replaced by the bpf loader
*/
extern int ngx_quic_sockmap;
struct {} ngx_quic_master_state SEC(".maps") ;
struct {} ngx_quic_listen_maps SEC(".maps") ;
struct {} ngx_quic_connections SEC(".maps") ;
SEC(PROGNAME)
int ngx_quic_select_socket_by_dcid(struct sk_reuseport_md *ctx)
{
int rc;
__u64 key;
int rc, flags;
long err;
__u32 idx, *val, *lmap_ptr, nwrk, ns, active;
size_t len, offset;
unsigned char *start, *end, *data, *dcid;
unsigned char *start, *end, dcid[NGX_QUIC_SERVER_CID_LEN];
/* direct packet access pointers, [s..e] may be less than ctx->len */
start = ctx->data;
end = (unsigned char *) ctx->data_end;
offset = 0;
end = ctx->data_end;
advance_data(sizeof(struct udphdr)); /* data at UDP header */
advance_data(1); /* data at QUIC flags */
offset = sizeof(struct udphdr) + 1; /* UDP header + QUIC flags */
if (data[0] & NGX_QUIC_PKT_LONG) {
if (start + offset > end) {
advance_data(4); /* data at QUIC version */
advance_data(1); /* data at DCID len */
/* direct access is not guaranteed, we may need to load data */
if (offset >= ctx->len) {
goto bad_dgram;
}
len = data[0]; /* read DCID length */
err = bpf_skb_load_bytes(ctx, offset - 1, dcid, 1);
if (err != 0) {
goto bad_dgram;
}
if (len < 8) {
/* it's useless to search for key in such short DCID */
return SK_PASS;
flags = dcid[0];
} else {
flags = start[offset - 1];
}
if (flags & NGX_QUIC_PKT_LONG) {
offset += 5; /* QUIC version + DCID len */
if (start + offset > end) {
if (offset >= ctx->len) {
goto bad_dgram;
}
err = bpf_skb_load_bytes(ctx, offset - 1, dcid, 1);
if (err != 0) {
goto bad_dgram;
}
len = dcid[0];
} else {
len = start[offset - 1];
}
if (len != NGX_QUIC_SERVER_CID_LEN) {
goto new_conn;
}
}
if (start + offset + NGX_QUIC_SERVER_CID_LEN > end) {
if ((offset + NGX_QUIC_SERVER_CID_LEN) >= ctx->len) {
goto bad_dgram;
}
err = bpf_skb_load_bytes(ctx, offset, dcid, NGX_QUIC_SERVER_CID_LEN);
if (err != 0) {
goto bad_dgram;
}
} else {
len = NGX_QUIC_SERVER_CID_LEN;
memcpy(dcid, start + offset, NGX_QUIC_SERVER_CID_LEN);
}
dcid = &data[1];
advance_data(len); /* we expect the packet to have full DCID */
rc = bpf_sk_select_reuseport(ctx, &ngx_quic_connections, dcid, 0);
/* make verifier happy */
if (dcid + sizeof(__u64) > end) {
goto failed;
}
key = ngx_quic_parse_uint64(dcid);
rc = bpf_sk_select_reuseport(ctx, &ngx_quic_sockmap, &key, 0);
switch (rc) {
case 0:
debugmsg("nginx quic socket selected by key 0x%llx", key);
if (rc == 0) {
debugmsg("nginx quic socket selected by dcid");
return SK_PASS;
/* kernel returns positive error numbers, errno.h defines positive */
case -ENOENT:
debugmsg("nginx quic default route for key 0x%llx", key);
/* let the default reuseport logic decide which socket to choose */
return SK_PASS;
default:
debugmsg("nginx quic bpf_sk_select_reuseport err: %d key 0x%llx",
rc, key);
goto failed;
}
failed:
/*
* SK_DROP will generate ICMP, but we may want to process "invalid" packet
* in userspace quic to investigate further and finally react properly
* (maybe ignore, maybe send something in response or close connection)
*/
return SK_PASS;
if (rc != -ENOENT) {
debugmsg("nginx quic bpf_sk_select_reuseport() failed:%d", rc);
/*
* we don't know which worker owns the connection
* - consider this packet a martian and drop
*/
return SK_DROP;
}
new_conn:
debugmsg("nginx quic new connection");
idx = NGX_QUIC_BPF_NMASTERS_IDX;
val = bpf_map_lookup_elem(&ngx_quic_master_state, &idx);
if (val == NULL) {
/*
* we expect that map always has entries at predefined indexes;
* map is constructed and updated before the program is attached,
* so something is very wrong here;
* drop the packet, so anyone will notice the problem and read logs
*/
debugmsg("nginx quic master_state map is inconsistent");
return SK_DROP;
}
debugmsg("nginx quic master count %d", *val);
if (*val == 2) {
/* two masters, select randomly which to use */
active = (bpf_get_prandom_u32() % 2);
debugmsg("nginx quic selected randomly master #%d", active);
} else {
/* single master running, choose active */
idx = NGX_QUIC_BPF_ACT_MASTER_IDX;
val = bpf_map_lookup_elem(&ngx_quic_master_state, &idx);
if (val == NULL) {
/*
* shouldn't normally happen, but in case of abnormal
* process termination this could be left in inconsistent
* state;
* we don't know how to pass packet to proper worker,
* so just drop it
*/
debugmsg("nginx quic master_state map state is inconsistent");
return SK_DROP;
}
active = *val;
debugmsg("nginx quic selected active master: #%d", active);
}
/* select the number of workers in active master */
val = bpf_map_lookup_elem(&ngx_quic_master_state, &active);
if (val == NULL) {
/* again, map state is inconsistent, drop the packet */
debugmsg("nginx quic master_state map state is inconsistent");
return SK_DROP;
}
nwrk = *val;
debugmsg(" nginx quic nworkers is %d", nwrk);
/* get the pointer to the inner map - with listen sockets */
lmap_ptr = bpf_map_lookup_elem(&ngx_quic_listen_maps, &active);
if (lmap_ptr == NULL) {
/*
* the active master entry does not point to valid inner map;
* something is very bad, drop it
*/
debugmsg("nginx quic listen_maps failed");
return SK_DROP;
}
/* select the worker to use */
ns = ctx->hash % nwrk;
rc = bpf_sk_select_reuseport(ctx, lmap_ptr, &ns, 0);
if (rc == 0) {
debugmsg("nginx quic socket selected by hash:%d of %d", (int) ns, nwrk);
return SK_PASS;
}
/* again, our map is in inconsistent state, drop the packet */
debugmsg("nginx quic select_reuseport failed:%d", rc);
return SK_DROP;
bad_dgram:
debugmsg("nginx quic bad datagram");
/* we cannot even parse this as QUIC - drop it */
return SK_DROP;
}

View file

@ -323,6 +323,12 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf,
+ conf->max_concurrent_streams_bidi)
* conf->stream_buffer_size / 2000;
if (c->fd == c->listening->fd
&& ngx_quic_bpf_enabled((ngx_cycle_t *) ngx_cycle))
{
qc->listen_bound = 1;
}
if (pkt->validated && pkt->retried) {
qc->tp.retry_scid.len = pkt->dcid.len;
qc->tp.retry_scid.data = ngx_pstrdup(c->pool, &pkt->dcid);
@ -433,6 +439,15 @@ ngx_quic_input_handler(ngx_event_t *rev)
return;
}
if (qc->listen_bound) {
c->fd = (ngx_socket_t) -1;
qc->error = NGX_QUIC_ERR_NO_ERROR;
qc->error_reason = "graceful shutdown";
ngx_quic_close_connection(c, NGX_ERROR);
return;
}
if (!qc->closing && qc->conf->shutdown) {
qc->conf->shutdown(c);
}
@ -935,7 +950,9 @@ ngx_quic_handle_packet(ngx_connection_t *c, ngx_quic_conf_t *conf,
pkt->odcid = pkt->dcid;
}
if (ngx_terminate || ngx_exiting) {
if ((ngx_terminate || ngx_exiting)
&& !ngx_quic_bpf_enabled((ngx_cycle_t *) ngx_cycle))
{
if (conf->retry) {
return ngx_quic_send_retry(c, conf, pkt);
}

View file

@ -142,4 +142,10 @@ ngx_int_t ngx_quic_get_packet_dcid(ngx_log_t *log, u_char *data, size_t len,
ngx_int_t ngx_quic_derive_key(ngx_log_t *log, const char *label,
ngx_str_t *secret, ngx_str_t *salt, u_char *out, size_t len);
#if (NGX_QUIC_BPF)
ngx_uint_t ngx_quic_bpf_enabled(ngx_cycle_t *cycle);
#else
#define ngx_quic_bpf_enabled(c) 0
#endif
#endif /* _NGX_EVENT_QUIC_H_INCLUDED_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,23 @@
/*
* Copyright (C) Nginx, Inc.
*/
#ifndef _NGX_EVENT_QUIC_BPF_H_INCLUDED_
#define _NGX_EVENT_QUIC_BPF_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
ngx_int_t ngx_quic_bpf_get_client_connection(ngx_connection_t *lc,
ngx_connection_t **pc);
ngx_int_t ngx_quic_bpf_insert(ngx_connection_t *c, ngx_quic_connection_t *qc,
ngx_quic_socket_t *qsock);
ngx_int_t ngx_quic_bpf_delete(ngx_connection_t *c, ngx_quic_connection_t *qc,
ngx_quic_socket_t *qsock);
#endif /* _NGX_EVENT_QUIC_BPF_H_INCLUDED_ */

View file

@ -7,75 +7,202 @@
static ngx_bpf_reloc_t bpf_reloc_prog_ngx_quic_reuseport_helper[] = {
{ "ngx_quic_sockmap", 59 },
{ "ngx_quic_connections", 119 },
{ "ngx_quic_master_state", 135 },
{ "ngx_quic_master_state", 149 },
{ "ngx_quic_master_state", 157 },
{ "ngx_quic_listen_maps", 164 },
};
static struct bpf_insn bpf_insn_prog_ngx_quic_reuseport_helper[] = {
/* opcode dst src offset imm */
{ 0x79, BPF_REG_2, BPF_REG_1, (int16_t) 0, 0x0 },
{ 0x79, BPF_REG_3, BPF_REG_1, (int16_t) 8, 0x0 },
{ 0xbf, BPF_REG_6, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_6, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x2d, BPF_REG_6, BPF_REG_3, (int16_t) 58, 0x0 },
{ 0xbf, BPF_REG_4, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x9 },
{ 0x2d, BPF_REG_4, BPF_REG_3, (int16_t) 55, 0x0 },
{ 0xb7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0xb7, BPF_REG_5, BPF_REG_0, (int16_t) 0, 0x14 },
{ 0xb7, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x9 },
{ 0x71, BPF_REG_6, BPF_REG_6, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_6, BPF_REG_0, (int16_t) 0, 0x38 },
{ 0xc7, BPF_REG_6, BPF_REG_0, (int16_t) 0, 0x38 },
{ 0x65, BPF_REG_6, BPF_REG_0, (int16_t) 11, 0xffffffff },
{ 0xbf, BPF_REG_5, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_5, BPF_REG_0, (int16_t) 0, 0xd },
{ 0x2d, BPF_REG_5, BPF_REG_3, (int16_t) 45, 0x0 },
{ 0xbf, BPF_REG_4, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0xe },
{ 0x2d, BPF_REG_4, BPF_REG_3, (int16_t) 42, 0x0 },
{ 0xb7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0xd },
{ 0xb7, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0xe },
{ 0x71, BPF_REG_5, BPF_REG_5, (int16_t) 0, 0x0 },
{ 0xb7, BPF_REG_6, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x2d, BPF_REG_6, BPF_REG_5, (int16_t) 37, 0x0 },
{ 0xbf, BPF_REG_6, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0xf, BPF_REG_6, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0xf, BPF_REG_6, BPF_REG_5, (int16_t) 0, 0x0 },
{ 0x2d, BPF_REG_6, BPF_REG_3, (int16_t) 33, 0x0 },
{ 0xf, BPF_REG_2, BPF_REG_4, (int16_t) 0, 0x0 },
{ 0xbf, BPF_REG_4, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x9 },
{ 0x2d, BPF_REG_4, BPF_REG_3, (int16_t) 29, 0x0 },
{ 0x71, BPF_REG_4, BPF_REG_2, (int16_t) 1, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x38 },
{ 0x71, BPF_REG_3, BPF_REG_2, (int16_t) 2, 0x0 },
{ 0x67, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x30 },
{ 0x4f, BPF_REG_3, BPF_REG_4, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_4, BPF_REG_2, (int16_t) 3, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x28 },
{ 0x4f, BPF_REG_3, BPF_REG_4, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_4, BPF_REG_2, (int16_t) 4, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x20 },
{ 0x4f, BPF_REG_3, BPF_REG_4, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_4, BPF_REG_2, (int16_t) 5, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x18 },
{ 0x4f, BPF_REG_3, BPF_REG_4, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_4, BPF_REG_2, (int16_t) 6, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x10 },
{ 0x4f, BPF_REG_3, BPF_REG_4, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_4, BPF_REG_2, (int16_t) 7, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x4f, BPF_REG_3, BPF_REG_4, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_2, BPF_REG_2, (int16_t) 8, 0x0 },
{ 0x4f, BPF_REG_3, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x7b, BPF_REG_10, BPF_REG_3, (int16_t) 65528, 0x0 },
{ 0xbf, BPF_REG_6, BPF_REG_1, (int16_t) 0, 0x0 },
{ 0x79, BPF_REG_9, BPF_REG_6, (int16_t) 8, 0x0 },
{ 0x79, BPF_REG_8, BPF_REG_6, (int16_t) 0, 0x0 },
{ 0xbf, BPF_REG_1, BPF_REG_8, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x9 },
{ 0x3d, BPF_REG_9, BPF_REG_1, (int16_t) 13, 0x0 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x61, BPF_REG_1, BPF_REG_6, (int16_t) 16, 0x0 },
{ 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xa },
{ 0x2d, BPF_REG_2, BPF_REG_1, (int16_t) 176, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xfffffff8 },
{ 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xffffffe0 },
{ 0xbf, BPF_REG_1, BPF_REG_6, (int16_t) 0, 0x0 },
{ 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0xb7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1a },
{ 0x55, BPF_REG_0, BPF_REG_0, (int16_t) 169, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_10, (int16_t) 65504, 0x0 },
{ 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 1, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_8, (int16_t) 8, 0x0 },
{ 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x9 },
{ 0x67, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x38 },
{ 0xc7, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x38 },
{ 0x65, BPF_REG_1, BPF_REG_0, (int16_t) 19, 0xffffffff },
{ 0xbf, BPF_REG_1, BPF_REG_8, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0xe },
{ 0x3d, BPF_REG_9, BPF_REG_1, (int16_t) 13, 0x0 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x61, BPF_REG_1, BPF_REG_6, (int16_t) 16, 0x0 },
{ 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xf },
{ 0x2d, BPF_REG_2, BPF_REG_1, (int16_t) 155, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xffffffe0 },
{ 0xbf, BPF_REG_1, BPF_REG_6, (int16_t) 0, 0x0 },
{ 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xd },
{ 0xb7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1a },
{ 0x55, BPF_REG_0, BPF_REG_0, (int16_t) 148, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_10, (int16_t) 65504, 0x0 },
{ 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 1, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_8, (int16_t) 13, 0x0 },
{ 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xe },
{ 0x55, BPF_REG_1, BPF_REG_0, (int16_t) 88, 0x14 },
{ 0xf, BPF_REG_8, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0xbf, BPF_REG_1, BPF_REG_8, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x14 },
{ 0x3d, BPF_REG_9, BPF_REG_1, (int16_t) 12, 0x0 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x61, BPF_REG_1, BPF_REG_6, (int16_t) 16, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x14 },
{ 0x3d, BPF_REG_3, BPF_REG_1, (int16_t) 134, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xffffffe0 },
{ 0xbf, BPF_REG_1, BPF_REG_6, (int16_t) 0, 0x0 },
{ 0xb7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x14 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1a },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 58, 0x0 },
{ 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 127, 0x0 },
{ 0x71, BPF_REG_2, BPF_REG_8, (int16_t) 13, 0x0 },
{ 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_1, BPF_REG_8, (int16_t) 12, 0x0 },
{ 0x4f, BPF_REG_2, BPF_REG_1, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_8, (int16_t) 15, 0x0 },
{ 0x67, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 14, 0x0 },
{ 0x4f, BPF_REG_1, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_4, BPF_REG_8, (int16_t) 9, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 8, 0x0 },
{ 0x4f, BPF_REG_4, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 11, 0x0 },
{ 0x67, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_5, BPF_REG_8, (int16_t) 10, 0x0 },
{ 0x4f, BPF_REG_3, BPF_REG_5, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x10 },
{ 0x4f, BPF_REG_3, BPF_REG_4, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x10 },
{ 0x4f, BPF_REG_1, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_2, BPF_REG_8, (int16_t) 17, 0x0 },
{ 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_4, BPF_REG_8, (int16_t) 16, 0x0 },
{ 0x4f, BPF_REG_2, BPF_REG_4, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_4, BPF_REG_8, (int16_t) 19, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_5, BPF_REG_8, (int16_t) 18, 0x0 },
{ 0x4f, BPF_REG_4, BPF_REG_5, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x20 },
{ 0x4f, BPF_REG_1, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x10 },
{ 0x4f, BPF_REG_4, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 1, 0x0 },
{ 0x67, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_2, BPF_REG_8, (int16_t) 0, 0x0 },
{ 0x4f, BPF_REG_3, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_2, BPF_REG_8, (int16_t) 3, 0x0 },
{ 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_5, BPF_REG_8, (int16_t) 2, 0x0 },
{ 0x4f, BPF_REG_2, BPF_REG_5, (int16_t) 0, 0x0 },
{ 0x63, BPF_REG_10, BPF_REG_4, (int16_t) 65520, 0x0 },
{ 0x7b, BPF_REG_10, BPF_REG_1, (int16_t) 65512, 0x0 },
{ 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x10 },
{ 0x4f, BPF_REG_2, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_8, (int16_t) 5, 0x0 },
{ 0x67, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 4, 0x0 },
{ 0x4f, BPF_REG_1, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 6, 0x0 },
{ 0x71, BPF_REG_4, BPF_REG_8, (int16_t) 7, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x8 },
{ 0x4f, BPF_REG_4, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x10 },
{ 0x4f, BPF_REG_4, BPF_REG_1, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x20 },
{ 0x4f, BPF_REG_4, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x7b, BPF_REG_10, BPF_REG_4, (int16_t) 65504, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xffffffe0 },
{ 0xbf, BPF_REG_1, BPF_REG_6, (int16_t) 0, 0x0 },
{ 0x18, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0xb7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x52 },
{ 0xb7, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x67, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x20 },
{ 0x77, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x20 },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 59, 0x0 },
{ 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0xfffffffe },
{ 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x1d, BPF_REG_0, BPF_REG_1, (int16_t) 1, 0x0 },
{ 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 54, 0x0 },
{ 0xb7, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x2 },
{ 0x63, BPF_REG_10, BPF_REG_1, (int16_t) 65532, 0x0 },
{ 0xbf, BPF_REG_2, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xfffffffc },
{ 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 46, 0x0 },
{ 0x61, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x55, BPF_REG_1, BPF_REG_0, (int16_t) 3, 0x2 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x7 },
{ 0x57, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 9, 0x0 },
{ 0xb7, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x3 },
{ 0x63, BPF_REG_10, BPF_REG_1, (int16_t) 65532, 0x0 },
{ 0xbf, BPF_REG_2, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xfffffffc },
{ 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 33, 0x0 },
{ 0x61, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x63, BPF_REG_10, BPF_REG_0, (int16_t) 65524, 0x0 },
{ 0xbf, BPF_REG_2, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xfffffff4 },
{ 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 25, 0x0 },
{ 0x61, BPF_REG_8, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0xbf, BPF_REG_2, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xfffffff4 },
{ 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 18, 0x0 },
{ 0xbf, BPF_REG_1, BPF_REG_8, (int16_t) 0, 0x0 },
{ 0x61, BPF_REG_2, BPF_REG_6, (int16_t) 32, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_2, (int16_t) 0, 0x0 },
{ 0x3f, BPF_REG_3, BPF_REG_1, (int16_t) 0, 0x0 },
{ 0x2f, BPF_REG_3, BPF_REG_8, (int16_t) 0, 0x0 },
{ 0x1f, BPF_REG_2, BPF_REG_3, (int16_t) 0, 0x0 },
{ 0x63, BPF_REG_10, BPF_REG_2, (int16_t) 65528, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
{ 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xfffffff8 },
{ 0xbf, BPF_REG_1, BPF_REG_6, (int16_t) 0, 0x0 },
{ 0xbf, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0xb7, BPF_REG_4, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x85, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x52 },
{ 0x67, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x20 },
{ 0x77, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x20 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x1 },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 1, 0x0 },
{ 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0xbf, BPF_REG_0, BPF_REG_7, (int16_t) 0, 0x0 },
{ 0x95, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0x0 },
};
@ -90,4 +217,3 @@ ngx_bpf_program_t ngx_quic_reuseport_helper = {
.license = "BSD",
.type = BPF_PROG_TYPE_SK_REUSEPORT,
};

View file

@ -48,6 +48,9 @@ typedef struct ngx_quic_keys_s ngx_quic_keys_t;
#include <ngx_event_quic_ack.h>
#include <ngx_event_quic_output.h>
#include <ngx_event_quic_socket.h>
#if (NGX_QUIC_BPF)
#include <ngx_event_quic_bpf.h>
#endif
/* RFC 9002, 6.2.2. Handshakes and New Paths: kInitialRtt */
@ -55,6 +58,8 @@ typedef struct ngx_quic_keys_s ngx_quic_keys_t;
#define NGX_QUIC_UNSET_PN (uint64_t) -1
#define NGX_QUIC_MAX_SERVER_IDS 8
/* 0-RTT and 1-RTT data exist in the same packet number space,
* so we have 3 packet number spaces:
*
@ -306,6 +311,7 @@ struct ngx_quic_connection_s {
unsigned read_level:2;
unsigned write_level:2;
#endif
unsigned listen_bound:1;
};

View file

@ -9,12 +9,7 @@
#include <ngx_event.h>
#include <ngx_event_quic_connection.h>
#define NGX_QUIC_MAX_SERVER_IDS 8
#if (NGX_QUIC_BPF)
static ngx_int_t ngx_quic_bpf_attach_id(ngx_connection_t *c, u_char *id);
#endif
static ngx_int_t ngx_quic_retire_client_id(ngx_connection_t *c,
ngx_quic_client_id_t *cid);
static ngx_quic_client_id_t *ngx_quic_alloc_client_id(ngx_connection_t *c,
@ -30,46 +25,10 @@ ngx_quic_create_server_id(ngx_connection_t *c, u_char *id)
return NGX_ERROR;
}
#if (NGX_QUIC_BPF)
if (ngx_quic_bpf_attach_id(c, id) != NGX_OK) {
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"quic bpf failed to generate socket key");
/* ignore error, things still may work */
}
#endif
return NGX_OK;
}
#if (NGX_QUIC_BPF)
static ngx_int_t
ngx_quic_bpf_attach_id(ngx_connection_t *c, u_char *id)
{
int fd;
uint64_t cookie;
socklen_t optlen;
fd = c->listening->fd;
optlen = sizeof(cookie);
if (getsockopt(fd, SOL_SOCKET, SO_COOKIE, &cookie, &optlen) == -1) {
ngx_log_error(NGX_LOG_ERR, c->log, ngx_socket_errno,
"quic getsockopt(SO_COOKIE) failed");
return NGX_ERROR;
}
ngx_quic_dcid_encode_key(id, cookie);
return NGX_OK;
}
#endif
ngx_int_t
ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c,
ngx_quic_new_conn_id_frame_t *f)

View file

@ -75,6 +75,10 @@ ngx_quic_output(ngx_connection_t *c)
ngx_quic_congestion_t *cg;
ngx_quic_connection_t *qc;
if (c->fd == (ngx_socket_t) -1) {
return NGX_ERROR;
}
c->log->action = "sending frames";
qc = ngx_quic_get_connection(c);
@ -1085,7 +1089,6 @@ ngx_quic_send_retry(ngx_connection_t *c, ngx_quic_conf_t *conf,
pkt.odcid = inpkt->dcid;
pkt.dcid = inpkt->scid;
/* TODO: generate routable dcid */
if (RAND_bytes(dcid, NGX_QUIC_SERVER_CID_LEN) != 1) {
return NGX_ERROR;
}

View file

@ -105,6 +105,11 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc,
failed:
ngx_rbtree_delete(&c->listening->rbtree, &qsock->udp.node);
#if (NGX_QUIC_BPF)
if (ngx_quic_bpf_delete(c, qc, qsock) != NGX_OK) {
return NGX_ERROR;
}
#endif
c->udp = NULL;
return NGX_ERROR;
@ -156,6 +161,11 @@ ngx_quic_close_socket(ngx_connection_t *c, ngx_quic_socket_t *qsock)
ngx_queue_insert_head(&qc->free_sockets, &qsock->queue);
ngx_rbtree_delete(&c->listening->rbtree, &qsock->udp.node);
#if (NGX_QUIC_BPF)
if (ngx_quic_bpf_delete(c, qc, qsock) != NGX_OK) {
return;
}
#endif
qc->nsockets--;
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
@ -180,6 +190,12 @@ ngx_quic_listen(ngx_connection_t *c, ngx_quic_connection_t *qc,
qsock->udp.node.key = ngx_crc32_long(id.data, id.len);
qsock->udp.key = id;
#if (NGX_QUIC_BPF)
if (ngx_quic_bpf_insert(c, qc, qsock) != NGX_OK) {
return NGX_ERROR;
}
#endif
ngx_rbtree_insert(&c->listening->rbtree, &qsock->udp.node);
ngx_queue_insert_tail(&qc->sockets, &qsock->queue);

View file

@ -168,7 +168,7 @@ ngx_quic_recvmsg(ngx_event_t *ev)
c->log->handler = NULL;
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic recvmsg: fd:%d n:%z", c->fd, n);
"quic recvmsg: fd:%d n:%z", lc->fd, n);
c->log->handler = handler;
}
@ -211,12 +211,23 @@ ngx_quic_recvmsg(ngx_event_t *ev)
ngx_accept_disabled = ngx_cycle->connection_n / 8
- ngx_cycle->free_connection_n;
c = ngx_get_connection(lc->fd, ev->log);
if (c == NULL) {
c = NULL;
#if (NGX_QUIC_BPF)
if (ngx_quic_bpf_get_client_connection(lc, &c) != NGX_OK) {
return;
}
#endif
if (c == NULL) {
c = ngx_get_connection(lc->fd, ev->log);
if (c == NULL) {
return;
}
c->shared = 1;
}
c->shared = 1;
c->type = SOCK_DGRAM;
c->socklen = socklen;
@ -327,7 +338,7 @@ ngx_quic_recvmsg(ngx_event_t *ev)
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, log, 0,
"*%uA quic recvmsg: %V fd:%d n:%z",
c->number, &addr, c->fd, n);
c->number, &addr, lc->fd, n);
}
}

View file

@ -955,7 +955,8 @@ ngx_worker_process_exit(ngx_cycle_t *cycle)
&& c[i].read
&& !c[i].read->accept
&& !c[i].read->channel
&& !c[i].read->resolver)
&& !c[i].read->resolver
&& !c[i].read->quic)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"*%uA open socket #%d left in connection %ui",