. 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=
NGX_GOOGLE_PERFTOOLS=NO
NGX_CPP_TEST=NO
-SO_COOKIE_FOUND=NO
-
NGX_LIBATOMIC=NO
NGX_CPU_CACHE_LINE=
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_ARRAY;
syscall(__NR_bpf, 0, &attr, 0);"
. auto/feature
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"
#include <ngx_config.h>
#include <ngx_core.h>
-#define NGX_BPF_LOGBUF_SIZE (16 * 1024)
+#define NGX_BPF_LOGBUF_SIZE (32 * 1024)
static ngx_inline int
for (i = 0; i < cycle->listening.nelts; i++) {
#if (NGX_QUIC)
- if (ls[i].quic) {
+ if (ls[i].quic
+ && (!ls[i].reuseport || !ngx_quic_bpf_enabled(cycle)))
+ {
continue;
}
#endif
/* to test on worker exit */
unsigned channel:1;
unsigned resolver:1;
+ unsigned quic:1;
unsigned cancelable:1;
-CFLAGS=-O2 -Wall
+
+# Copyright (C) Nginx, Inc.
+
+CFLAGS=-O2 -Wall $(MAKE_CFLAGS)
LICENSE=BSD
((__u64)(p)[6] << 8) | \
((__u64)(p)[7]))
+#define ngx_quic_bpf_listen_key(worker) \
+ (((__u64) 0xFF << 56) | ((__u64) (worker) & 0xFFFFFFFFFFFFULL))
+
+
/*
* 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_sockmap SEC(".maps");
+struct {} ngx_quic_worker_counts SEC(".maps");
SEC(PROGNAME)
int ngx_quic_select_socket_by_dcid(struct sk_reuseport_md *ctx)
{
- int rc;
+ int rc, worker_idx;
+ __u32 wc_key, *wc0, *wc1, n, m;
__u64 key;
size_t offset;
unsigned char *start, *end, *dcid, byte, buf[NGX_QUIC_SERVER_CID_LEN];
}
if (byte != NGX_QUIC_SERVER_CID_LEN) {
- return SK_PASS;
+ goto new;
}
}
key = ngx_quic_parse_uint64(dcid);
+ if ((key >> 56) == 0xFF) {
+ goto new;
+ }
+
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 worker socket selected by dcid");
return SK_PASS;
+ }
+
+ if (rc != -ENOENT) {
+ debugmsg("nginx quic bpf_sk_select_reuseport() failed: %d", rc);
+ return SK_DROP;
+ }
+
+new:
+
+ wc_key = 0;
+ wc0 = bpf_map_lookup_elem(&ngx_quic_worker_counts, &wc_key);
+ if (wc0 == NULL) {
+ debugmsg("nginx quic worker count 0 undefined");
+ return SK_DROP;
+ }
+
+ wc_key = 1;
+ wc1 = bpf_map_lookup_elem(&ngx_quic_worker_counts, &wc_key);
+ if (wc1 == NULL) {
+ debugmsg("nginx quic worker count 1 undefined");
+ return SK_DROP;
+ }
+
+ n = *wc0 > *wc1 ? *wc0 : *wc1;
+
+ if (n == 0) {
+ debugmsg("nginx quic no active workers");
+ return SK_DROP;
+ }
- /* 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 */
+ worker_idx = ctx->hash % n;
+ key = ngx_quic_bpf_listen_key(worker_idx);
+
+ rc = bpf_sk_select_reuseport(ctx, &ngx_quic_sockmap, &key, 0);
+
+ if (rc == 0) {
+ debugmsg("nginx quic listener socket selected worker index:%d",
+ worker_idx);
return SK_PASS;
+ }
- default:
- debugmsg("nginx quic bpf_sk_select_reuseport err: %d key 0x%llx",
- rc, key);
- goto failed;
+ if (rc != -ENOENT) {
+ debugmsg("nginx quic bpf_sk_select_reuseport() failed: %d", rc);
+ return SK_DROP;
}
+ m = *wc0 < *wc1 ? *wc0 : *wc1;
+
+ if (m && m != n) {
+ worker_idx = ctx->hash % m;
+ key = ngx_quic_bpf_listen_key(worker_idx);
+
+ rc = bpf_sk_select_reuseport(ctx, &ngx_quic_sockmap, &key, 0);
+
+ if (rc == 0) {
+ debugmsg("nginx quic listener socket selected "
+ "worker index:%d (fallback)", worker_idx);
+ return SK_PASS;
+ }
+
+ debugmsg("nginx quic bpf_sk_select_reuseport() fallback "
+ "failed: %d", rc);
+ }
+
+ return SK_DROP;
+
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;
+
+ debugmsg("nginx quic bad datagram");
+
+ return SK_DROP;
}
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_ */
#include <ngx_config.h>
#include <ngx_core.h>
+#include <ngx_event.h>
+#include <ngx_event_quic_connection.h>
#define NGX_QUIC_BPF_VARNAME "NGINX_BPF_MAPS"
#define ngx_core_get_conf(cycle) \
(ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module)
+#define ngx_quic_bpf_listen_key(worker) \
+ (((uint64_t) 0xFF << 56) \
+ | ((uint64_t) (worker) & 0xFFFFFFFFFFFFULL))
+
typedef struct {
ngx_queue_t queue;
- int map_fd;
+
+ int sock_map;
+ int worker_counts_map;
struct sockaddr *sockaddr;
socklen_t socklen;
- ngx_uint_t unused; /* unsigned unused:1; */
+
+ ngx_array_t listening;
} ngx_quic_sock_group_t;
+typedef struct {
+ ngx_socket_t fd;
+ uint64_t key;
+ ngx_listening_t *listening;
+ ngx_connection_t *connection;
+} ngx_quic_bpf_listening_t;
+
+
typedef struct {
ngx_flag_t enabled;
ngx_uint_t map_size;
+ ngx_uint_t master_index;
+ u_char *env;
ngx_queue_t groups; /* of ngx_quic_sock_group_t */
} ngx_quic_bpf_conf_t;
static void *ngx_quic_bpf_create_conf(ngx_cycle_t *cycle);
+static char *ngx_quic_bpf_init_conf(ngx_cycle_t *cycle, void *conf);
static ngx_int_t ngx_quic_bpf_module_init(ngx_cycle_t *cycle);
+static void ngx_quic_bpf_exit_master(ngx_cycle_t *cycle);
static void ngx_quic_bpf_cleanup(void *data);
static ngx_inline void ngx_quic_bpf_close(ngx_log_t *log, int fd,
const char *name);
+static ngx_inline ngx_int_t ngx_quic_bpf_map_update(ngx_log_t *log, int fd,
+ const void *key, const void *value, const char *name);
static ngx_quic_sock_group_t *ngx_quic_bpf_find_group(ngx_quic_bpf_conf_t *bcf,
ngx_listening_t *ls);
static ngx_quic_sock_group_t *ngx_quic_bpf_alloc_group(ngx_cycle_t *cycle,
- struct sockaddr *sa, socklen_t socklen);
+ ngx_listening_t *ls);
static ngx_quic_sock_group_t *ngx_quic_bpf_create_group(ngx_cycle_t *cycle,
ngx_listening_t *ls);
+static ngx_int_t ngx_quic_bpf_inherit_fd(ngx_cycle_t *cycle, int fd);
static ngx_quic_sock_group_t *ngx_quic_bpf_get_group(ngx_cycle_t *cycle,
ngx_listening_t *ls);
static ngx_int_t ngx_quic_bpf_group_add_socket(ngx_cycle_t *cycle,
ngx_listening_t *ls);
-static uint64_t ngx_quic_bpf_socket_key(ngx_fd_t fd, ngx_log_t *log);
+static ngx_int_t ngx_quic_bpf_add_worker_socket(ngx_cycle_t *cycle,
+ ngx_quic_sock_group_t *grp, ngx_listening_t *ls);
+static ngx_int_t ngx_quic_bpf_publish_workers(ngx_cycle_t *cycle,
+ ngx_quic_sock_group_t *grp, ngx_uint_t worker_count);
static ngx_int_t ngx_quic_bpf_export_maps(ngx_cycle_t *cycle);
static ngx_int_t ngx_quic_bpf_import_maps(ngx_cycle_t *cycle);
static ngx_core_module_t ngx_quic_bpf_module_ctx = {
ngx_string("quic_bpf"),
ngx_quic_bpf_create_conf,
- NULL
+ ngx_quic_bpf_init_conf
};
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
- NULL, /* exit master */
+ ngx_quic_bpf_exit_master, /* exit master */
NGX_MODULE_V1_PADDING
};
static void *
ngx_quic_bpf_create_conf(ngx_cycle_t *cycle)
{
+ size_t len;
+ u_char *env;
ngx_quic_bpf_conf_t *bcf;
bcf = ngx_pcalloc(cycle->pool, sizeof(ngx_quic_bpf_conf_t));
bcf->enabled = NGX_CONF_UNSET;
bcf->map_size = NGX_CONF_UNSET_UINT;
+ /*
+ * preserve environment variable value before it may be reset by
+ * some module, i.e. perl
+ */
+ env = (u_char *) getenv(NGX_QUIC_BPF_VARNAME);
+ if (env != NULL) {
+ len = ngx_strlen(env);
+ bcf->env = ngx_pnalloc(cycle->pool, len + 1);
+ if (bcf->env == NULL) {
+ return NULL;
+ }
+
+ ngx_memcpy(bcf->env, env, len + 1);
+ }
+
ngx_queue_init(&bcf->groups);
return bcf;
}
+static char *
+ngx_quic_bpf_init_conf(ngx_cycle_t *cycle, void *conf)
+{
+ ngx_quic_bpf_conf_t *bcf = conf;
+ ngx_quic_bpf_conf_t *obcf;
+
+ ngx_conf_init_value(bcf->enabled, 0);
+
+ if (cycle->old_cycle->conf_ctx == NULL) {
+ return NGX_CONF_OK;
+ }
+
+ obcf = ngx_quic_bpf_get_conf(cycle->old_cycle);
+ if (obcf == NULL) {
+ return NGX_CONF_OK;
+ }
+
+ if (obcf->enabled != bcf->enabled) {
+ ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
+ "cannot change \"quic_bpf\" after reload, ignoring");
+ bcf->enabled = obcf->enabled;
+ }
+
+ bcf->master_index = obcf->master_index;
+
+ return NGX_CONF_OK;
+}
+
+
static ngx_int_t
ngx_quic_bpf_module_init(ngx_cycle_t *cycle)
{
- ngx_uint_t i;
- ngx_listening_t *ls;
- ngx_core_conf_t *ccf;
- ngx_pool_cleanup_t *cln;
- ngx_quic_bpf_conf_t *bcf;
+ ngx_uint_t i;
+ ngx_queue_t *q;
+ ngx_listening_t *ls;
+ ngx_core_conf_t *ccf;
+ ngx_pool_cleanup_t *cln;
+ ngx_quic_bpf_conf_t *bcf;
+ ngx_quic_sock_group_t *grp;
if (ngx_test_config) {
/*
ccf = ngx_core_get_conf(cycle);
bcf = ngx_quic_bpf_get_conf(cycle);
- ngx_conf_init_value(bcf->enabled, 0);
+ if (!bcf->enabled) {
+
+ if (ngx_inherited && ngx_is_init_cycle(cycle->old_cycle)
+ && bcf->env != NULL)
+ {
+ ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
+ "\"quic_bpf\" cannot be disabled "
+ "during binary upgrade");
+ return NGX_ERROR;
+ }
- bcf->map_size = ccf->worker_processes * 4;
+ return NGX_OK;
+ }
+
+ bcf->map_size = ccf->worker_processes * 32;
cln = ngx_pool_cleanup_add(cycle->pool, 0);
if (cln == NULL) {
}
}
+ q = ngx_queue_head(&bcf->groups);
+
+ while (q != ngx_queue_sentinel(&bcf->groups)) {
+
+ grp = ngx_queue_data(q, ngx_quic_sock_group_t, queue);
+ q = ngx_queue_next(q);
+
+ if (grp->listening.nelts == 0) {
+
+ ngx_quic_bpf_close(cycle->log, grp->sock_map, "sockmap");
+ ngx_quic_bpf_close(cycle->log, grp->worker_counts_map,
+ "worker_counts");
+ ngx_queue_remove(&grp->queue);
+ continue;
+ }
+
+ if (ngx_quic_bpf_publish_workers(cycle, grp, ccf->worker_processes)
+ != NGX_OK)
+ {
+ goto failed;
+ }
+ }
+
if (ngx_quic_bpf_export_maps(cycle) != NGX_OK) {
goto failed;
}
}
+ngx_uint_t
+ngx_quic_bpf_enabled(ngx_cycle_t *cycle)
+{
+ ngx_quic_bpf_conf_t *bcf;
+
+ bcf = ngx_quic_bpf_get_conf(cycle);
+
+ if (bcf == NULL) {
+ return 0;
+ }
+
+ return bcf->enabled;
+}
+
+
static void
ngx_quic_bpf_cleanup(void *data)
{
ngx_quic_bpf_conf_t *bcf = (ngx_quic_bpf_conf_t *) data;
+ ngx_uint_t i;
+ ngx_log_t *log;
+ ngx_queue_t *q;
+ ngx_quic_sock_group_t *grp;
+ ngx_quic_bpf_listening_t *bls;
+
+ log = ngx_cycle->log;
+
+ for (q = ngx_queue_head(&bcf->groups);
+ q != ngx_queue_sentinel(&bcf->groups);
+ q = ngx_queue_next(q))
+ {
+ grp = ngx_queue_data(q, ngx_quic_sock_group_t, queue);
+
+ bls = grp->listening.elts;
+
+ for (i = 0; i < grp->listening.nelts; i++) {
+ if (bls[i].fd != (ngx_socket_t) -1) {
+ if (ngx_close_socket(bls[i].fd) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
+ ngx_close_socket_n " failed");
+ }
+ }
+ }
+
+ ngx_quic_bpf_close(log, grp->sock_map, "sockmap");
+ ngx_quic_bpf_close(log, grp->worker_counts_map, "worker_counts");
+ }
+}
+
+
+static void
+ngx_quic_bpf_exit_master(ngx_cycle_t *cycle)
+{
+ uint32_t key, value;
ngx_queue_t *q;
+ ngx_quic_bpf_conf_t *bcf;
ngx_quic_sock_group_t *grp;
+ bcf = ngx_quic_bpf_get_conf(cycle);
+ if (!bcf->enabled) {
+ return;
+ }
+
+ key = bcf->master_index;
+ value = 0;
+
for (q = ngx_queue_head(&bcf->groups);
q != ngx_queue_sentinel(&bcf->groups);
q = ngx_queue_next(q))
{
grp = ngx_queue_data(q, ngx_quic_sock_group_t, queue);
- ngx_quic_bpf_close(ngx_cycle->log, grp->map_fd, "map");
+ if (ngx_quic_bpf_map_update(cycle->log, grp->worker_counts_map,
+ &key, &value, "worker_counts")
+ != NGX_OK)
+ {
+ continue;
+ }
}
}
static ngx_inline void
ngx_quic_bpf_close(ngx_log_t *log, int fd, const char *name)
{
+ if (fd == -1) {
+ return;
+ }
+
if (close(fd) != -1) {
return;
}
}
+static ngx_inline ngx_int_t
+ngx_quic_bpf_map_update(ngx_log_t *log, int fd, const void *key,
+ const void *value, const char *name)
+{
+ if (ngx_bpf_map_update(fd, key, value, BPF_ANY) != -1) {
+ return NGX_OK;
+ }
+
+ ngx_log_error(NGX_LOG_ERR, log, ngx_errno,
+ "quic bpf failed to update %s map fd:%d", name, fd);
+
+ return NGX_ERROR;
+}
+
+
static ngx_quic_sock_group_t *
ngx_quic_bpf_find_group(ngx_quic_bpf_conf_t *bcf, ngx_listening_t *ls)
{
static ngx_quic_sock_group_t *
-ngx_quic_bpf_alloc_group(ngx_cycle_t *cycle, struct sockaddr *sa,
- socklen_t socklen)
+ngx_quic_bpf_alloc_group(ngx_cycle_t *cycle, ngx_listening_t *ls)
{
ngx_quic_bpf_conf_t *bcf;
ngx_quic_sock_group_t *grp;
return NULL;
}
- grp->socklen = socklen;
- grp->sockaddr = ngx_palloc(cycle->pool, socklen);
- if (grp->sockaddr == NULL) {
+ grp->sock_map = -1;
+ grp->worker_counts_map = -1;
+
+ grp->sockaddr = ls->sockaddr;
+ grp->socklen = ls->socklen;
+
+ if (ngx_array_init(&grp->listening, cycle->pool, 1,
+ sizeof(ngx_quic_bpf_listening_t))
+ != NGX_OK)
+ {
return NULL;
}
- ngx_memcpy(grp->sockaddr, sa, socklen);
ngx_queue_insert_tail(&bcf->groups, &grp->queue);
static ngx_quic_sock_group_t *
ngx_quic_bpf_create_group(ngx_cycle_t *cycle, ngx_listening_t *ls)
{
- int progfd, failed, flags, rc;
+ int progfd, failed;
ngx_quic_bpf_conf_t *bcf;
ngx_quic_sock_group_t *grp;
bcf = ngx_quic_bpf_get_conf(cycle);
- if (!bcf->enabled) {
- return NULL;
- }
-
- grp = ngx_quic_bpf_alloc_group(cycle, ls->sockaddr, ls->socklen);
+ grp = ngx_quic_bpf_alloc_group(cycle, ls);
if (grp == NULL) {
return NULL;
}
- grp->map_fd = ngx_bpf_map_create(cycle->log, BPF_MAP_TYPE_SOCKHASH,
- sizeof(uint64_t), sizeof(uint64_t),
- bcf->map_size, 0);
- if (grp->map_fd == -1) {
+ grp->sock_map = ngx_bpf_map_create(cycle->log,
+ BPF_MAP_TYPE_SOCKHASH,
+ sizeof(uint64_t),
+ sizeof(uint64_t),
+ bcf->map_size, 0);
+ if (grp->sock_map == -1) {
goto failed;
}
- flags = fcntl(grp->map_fd, F_GETFD);
- if (flags == -1) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, errno,
- "quic bpf getfd failed");
+ if (ngx_quic_bpf_inherit_fd(cycle, grp->sock_map) != NGX_OK) {
goto failed;
}
- /* need to inherit map during binary upgrade after exec */
- flags &= ~FD_CLOEXEC;
+ ngx_bpf_program_link(&ngx_quic_reuseport_helper,
+ "ngx_quic_sockmap", grp->sock_map);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
+ "quic bpf sockmap created fd:%d",
+ grp->sock_map);
+
+ grp->worker_counts_map = ngx_bpf_map_create(cycle->log,
+ BPF_MAP_TYPE_ARRAY,
+ sizeof(uint32_t),
+ sizeof(uint32_t), 2, 0);
+ if (grp->worker_counts_map == -1) {
+ goto failed;
+ }
- rc = fcntl(grp->map_fd, F_SETFD, flags);
- if (rc == -1) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, errno,
- "quic bpf setfd failed");
+ if (ngx_quic_bpf_inherit_fd(cycle, grp->worker_counts_map) != NGX_OK) {
goto failed;
}
ngx_bpf_program_link(&ngx_quic_reuseport_helper,
- "ngx_quic_sockmap", grp->map_fd);
+ "ngx_quic_worker_counts", grp->worker_counts_map);
progfd = ngx_bpf_load_program(cycle->log, &ngx_quic_reuseport_helper);
if (progfd < 0) {
goto failed;
}
- ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
- "quic bpf sockmap created fd:%d", grp->map_fd);
return grp;
failed:
- if (grp->map_fd != -1) {
- ngx_quic_bpf_close(cycle->log, grp->map_fd, "map");
- }
+ ngx_quic_bpf_close(cycle->log, grp->sock_map, "sockmap");
+ ngx_quic_bpf_close(cycle->log, grp->worker_counts_map, "worker_counts");
ngx_queue_remove(&grp->queue);
}
+static ngx_int_t
+ngx_quic_bpf_inherit_fd(ngx_cycle_t *cycle, int fd)
+{
+ int flags;
+
+ flags = fcntl(fd, F_GETFD);
+ if (flags == -1) {
+ ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+ "quic bpf fcntl(F_GETFD) failed");
+ return NGX_ERROR;
+ }
+
+ flags &= ~FD_CLOEXEC;
+
+ if (fcntl(fd, F_SETFD, flags) == -1) {
+ ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+ "quic bpf fcntl(F_SETFD) failed");
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+}
+
+
static ngx_quic_sock_group_t *
ngx_quic_bpf_get_group(ngx_cycle_t *cycle, ngx_listening_t *ls)
{
return ngx_quic_bpf_create_group(cycle, ls);
}
- grp = ngx_quic_bpf_alloc_group(cycle, ls->sockaddr, ls->socklen);
+ grp = ngx_quic_bpf_alloc_group(cycle, ls);
if (grp == NULL) {
return NULL;
}
- grp->map_fd = dup(ogrp->map_fd);
- if (grp->map_fd == -1) {
+ grp->sock_map = dup(ogrp->sock_map);
+ if (grp->sock_map == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
- "quic bpf failed to duplicate bpf map descriptor");
-
- ngx_queue_remove(&grp->queue);
-
- return NULL;
+ "quic bpf failed to duplicate sockmap");
+ goto failed;
}
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
- "quic bpf sockmap fd duplicated old:%d new:%d",
- ogrp->map_fd, grp->map_fd);
+ grp->worker_counts_map = dup(ogrp->worker_counts_map);
+ if (grp->worker_counts_map == -1) {
+ ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+ "quic bpf failed to duplicate worker counts map");
+ goto failed;
+ }
return grp;
+
+failed:
+
+ ngx_quic_bpf_close(cycle->log, grp->sock_map, "sockmap");
+ ngx_quic_bpf_close(cycle->log, grp->worker_counts_map, "worker_counts");
+
+ ngx_queue_remove(&grp->queue);
+
+ return NULL;
}
static ngx_int_t
-ngx_quic_bpf_group_add_socket(ngx_cycle_t *cycle, ngx_listening_t *ls)
+ngx_quic_bpf_group_add_socket(ngx_cycle_t *cycle, ngx_listening_t *ls)
{
- uint64_t cookie;
- ngx_quic_bpf_conf_t *bcf;
+ uint64_t key, value;
ngx_quic_sock_group_t *grp;
- bcf = ngx_quic_bpf_get_conf(cycle);
-
grp = ngx_quic_bpf_get_group(cycle, ls);
-
if (grp == NULL) {
- if (!bcf->enabled) {
- return NGX_OK;
- }
-
return NGX_ERROR;
}
- grp->unused = 0;
-
- cookie = ngx_quic_bpf_socket_key(ls->fd, cycle->log);
- if (cookie == (uint64_t) NGX_ERROR) {
+ if (ngx_quic_bpf_add_worker_socket(cycle, grp, ls) != NGX_OK) {
return NGX_ERROR;
}
- /* map[cookie] = socket; for use in kernel helper */
- if (ngx_bpf_map_update(grp->map_fd, &cookie, &ls->fd, BPF_ANY) == -1) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
- "quic bpf failed to update socket map key=%xL", cookie);
+ key = ngx_quic_bpf_listen_key(ls->worker);
+ value = ls->fd;
+
+ if (ngx_quic_bpf_map_update(cycle->log, grp->sock_map,
+ &key, &value, "listen")
+ != NGX_OK)
+ {
return NGX_ERROR;
}
- ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
- "quic bpf sockmap fd:%d add socket:%d cookie:0x%xL worker:%ui",
- grp->map_fd, ls->fd, cookie, ls->worker);
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_quic_bpf_publish_workers(ngx_cycle_t *cycle, ngx_quic_sock_group_t *grp,
+ ngx_uint_t worker_count)
+{
+ uint32_t key;
+ uint32_t value;
+ ngx_quic_bpf_conf_t *bcf;
+
+ bcf = ngx_quic_bpf_get_conf(cycle);
+
+ key = bcf->master_index;
+ value = worker_count;
- /* do not inherit this socket */
- ls->ignore = 1;
+ if (ngx_quic_bpf_map_update(cycle->log, grp->worker_counts_map,
+ &key, &value, "worker_counts")
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
return NGX_OK;
}
-static uint64_t
-ngx_quic_bpf_socket_key(ngx_fd_t fd, ngx_log_t *log)
+static ngx_int_t
+ngx_quic_bpf_add_worker_socket(ngx_cycle_t *cycle, ngx_quic_sock_group_t *grp,
+ ngx_listening_t *ls)
{
- uint64_t cookie;
- socklen_t optlen;
+ int value;
+ uint64_t key, map_value;
+ ngx_uint_t i, n, map_updated;
+ ngx_socket_t s;
+ ngx_quic_bpf_listening_t *bls;
+
+ s = ngx_socket(ls->sockaddr->sa_family, SOCK_DGRAM, 0);
+ if (s == (ngx_socket_t) -1) {
+ ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_socket_errno,
+ "quic bpf " ngx_socket_n " failed");
+ return NGX_ERROR;
+ }
- optlen = sizeof(cookie);
+ map_updated = 0;
- if (getsockopt(fd, SOL_SOCKET, SO_COOKIE, &cookie, &optlen) == -1) {
- ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
- "quic bpf getsockopt(SO_COOKIE) failed");
+ if (ngx_nonblocking(s) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf " ngx_nonblocking_n " failed");
+ goto failed;
+ }
+
+ if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ "quic bpf fcntl(FD_CLOEXEC) failed");
+ goto failed;
+ }
+
+ value = 1;
- return (ngx_uint_t) NGX_ERROR;
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+ (const void *) &value, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf setsockopt(SO_REUSEADDR) failed");
+ goto failed;
+ }
+
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT,
+ (const void *) &value, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf setsockopt(SO_REUSEPORT) failed");
+ goto failed;
+ }
+
+ if (ls->rcvbuf != -1) {
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
+ (const void *) &ls->rcvbuf, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf setsockopt(SO_RCVBUF, %d) failed",
+ ls->rcvbuf);
+ goto failed;
+ }
}
- return cookie;
+ if (ls->sndbuf != -1) {
+ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
+ (const void *) &ls->sndbuf, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf setsockopt(SO_SNDBUF, %d) failed",
+ ls->sndbuf);
+ goto failed;
+ }
+ }
+
+#if (NGX_HAVE_IP_PKTINFO)
+ if (ls->wildcard && ls->sockaddr->sa_family == AF_INET) {
+ if (setsockopt(s, IPPROTO_IP, IP_PKTINFO,
+ (const void *) &value, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf setsockopt(IP_PKTINFO) failed");
+ goto failed;
+ }
+ }
+#endif
+
+#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
+ if (ls->wildcard && ls->sockaddr->sa_family == AF_INET6) {
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+ (const void *) &value, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf setsockopt(IPV6_RECVPKTINFO) failed");
+ goto failed;
+ }
+ }
+#endif
+
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+
+ if (ls->sockaddr->sa_family == AF_INET6) {
+ int ipv6only;
+
+ ipv6only = ls->ipv6only;
+
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+ (const void *) &ipv6only, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf setsockopt(IPV6_V6ONLY) %V failed",
+ &ls->addr_text);
+ goto failed;
+ }
+ }
+
+#endif
+
+#if (NGX_HAVE_IP_MTU_DISCOVER)
+
+ if (ls->sockaddr->sa_family == AF_INET) {
+ value = IP_PMTUDISC_DO;
+
+ if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
+ (const void *) &value, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf setsockopt(IP_MTU_DISCOVER) "
+ "failed, ignored");
+ }
+ }
+
+#elif (NGX_HAVE_IP_DONTFRAG)
+
+ if (ls->sockaddr->sa_family == AF_INET) {
+ value = 1;
+
+ if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
+ (const void *) &value, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf setsockopt(IP_DONTFRAG) "
+ "failed, ignored");
+ }
+ }
+
+#endif
+
+#if (NGX_HAVE_INET6)
+
+#if (NGX_HAVE_IPV6_MTU_DISCOVER)
+
+ if (ls->sockaddr->sa_family == AF_INET6) {
+ value = IPV6_PMTUDISC_DO;
+
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
+ (const void *) &value, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf setsockopt(IPV6_MTU_DISCOVER) "
+ "failed, ignored");
+ }
+ }
+
+#elif (NGX_HAVE_IPV6_DONTFRAG)
+
+ if (ls->sockaddr->sa_family == AF_INET6) {
+ value = 1;
+
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_DONTFRAG,
+ (const void *) &value, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf setsockopt(IPV6_DONTFRAG) "
+ "failed, ignored");
+ }
+ }
+
+#endif
+
+#endif
+
+ if (bind(s, ls->sockaddr, ls->socklen) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf bind() failed");
+ goto failed;
+ }
+
+ if (RAND_bytes((u_char *) &key, sizeof(uint64_t)) != 1) {
+ ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
+ "quic bpf RAND_bytes() failed");
+ goto failed;
+ }
+
+ if ((key >> 56) == 0xFF) {
+ key &= ~((uint64_t) 0xFF << 56);
+ }
+
+ map_value = s;
+ if (ngx_quic_bpf_map_update(cycle->log, grp->sock_map,
+ &key, &map_value, "sockmap")
+ != NGX_OK)
+ {
+ goto failed;
+ }
+
+ map_updated = 1;
+
+ if (ls->worker >= grp->listening.nelts) {
+ n = ls->worker + 1 - grp->listening.nelts;
+
+ bls = ngx_array_push_n(&grp->listening, n);
+ if (bls == NULL) {
+ goto failed;
+ }
+
+ ngx_memzero(bls, n * sizeof(ngx_quic_bpf_listening_t));
+
+ for (i = 0; i < n; i++) {
+ bls[i].fd = (ngx_socket_t) -1;
+ }
+ }
+
+ bls = grp->listening.elts;
+ bls[ls->worker].fd = s;
+ bls[ls->worker].key = key;
+ bls[ls->worker].listening = ls;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
+ "quic bpf socket fd:%d key:%uL", s, key);
+
+ return NGX_OK;
+
+failed:
+
+ if (map_updated) {
+ if (ngx_bpf_map_delete(grp->sock_map, &key) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ "quic bpf failed to delete map entry");
+ }
+ }
+
+ if (ngx_close_socket(s) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "quic bpf " ngx_close_socket_n " failed");
+ }
+
+ return NGX_ERROR;
}
ccf = ngx_core_get_conf(cycle);
bcf = ngx_quic_bpf_get_conf(cycle);
+ if (!bcf->enabled) {
+ return NGX_OK;
+ }
- len = sizeof(NGX_QUIC_BPF_VARNAME) + 1;
-
- q = ngx_queue_head(&bcf->groups);
-
- while (q != ngx_queue_sentinel(&bcf->groups)) {
-
- grp = ngx_queue_data(q, ngx_quic_sock_group_t, queue);
-
- q = ngx_queue_next(q);
-
- if (grp->unused) {
- /*
- * map was inherited, but it is not used in this configuration;
- * do not pass such map further and drop the group to prevent
- * interference with changes during reload
- */
-
- ngx_quic_bpf_close(cycle->log, grp->map_fd, "map");
- ngx_queue_remove(&grp->queue);
+ if (ngx_queue_empty(&bcf->groups)) {
+ return NGX_OK;
+ }
- continue;
- }
+ len = sizeof(NGX_QUIC_BPF_VARNAME) + 1;
- len += NGX_INT32_LEN + 1 + NGX_SOCKADDR_STRLEN + 1;
+ for (q = ngx_queue_head(&bcf->groups);
+ q != ngx_queue_sentinel(&bcf->groups);
+ q = ngx_queue_next(q))
+ {
+ len += (NGX_INT32_LEN + 1) * 2 + NGX_SOCKADDR_STRLEN + 1;
}
len++;
p = ngx_cpymem(buf, NGX_QUIC_BPF_VARNAME "=",
sizeof(NGX_QUIC_BPF_VARNAME));
+ *p++ = bcf->master_index ? '-' : '+';
+
for (q = ngx_queue_head(&bcf->groups);
q != ngx_queue_sentinel(&bcf->groups);
q = ngx_queue_next(q))
{
grp = ngx_queue_data(q, ngx_quic_sock_group_t, queue);
- p = ngx_sprintf(p, "%ud", grp->map_fd);
+ p = ngx_sprintf(p, "%ud", grp->sock_map);
+ *p++ = NGX_QUIC_BPF_ADDRSEP;
+ p = ngx_sprintf(p, "%ud", grp->worker_counts_map);
*p++ = NGX_QUIC_BPF_ADDRSEP;
p += ngx_sock_ntop(grp->sockaddr, grp->socklen, p,
static ngx_int_t
ngx_quic_bpf_import_maps(ngx_cycle_t *cycle)
{
- int s;
+ int fds[2];
u_char *inherited, *p, *v;
- ngx_uint_t in_fd;
+ ngx_int_t fd;
+ ngx_uint_t i, nfd;
ngx_addr_t tmp;
ngx_quic_bpf_conf_t *bcf;
ngx_quic_sock_group_t *grp;
- inherited = (u_char *) getenv(NGX_QUIC_BPF_VARNAME);
+ bcf = ngx_quic_bpf_get_conf(cycle);
+ inherited = bcf->env;
if (inherited == NULL) {
return NGX_OK;
}
- bcf = ngx_quic_bpf_get_conf(cycle);
+ nfd = 0;
-#if (NGX_SUPPRESS_WARN)
- s = -1;
-#endif
+ ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
+ "quic bpf using inherited QUIC BPF maps from \"%s\"",
+ inherited);
+
+ switch (*inherited) {
- in_fd = 1;
+ case '+':
+ bcf->master_index = 1;
+ break;
+
+ case '-':
+ bcf->master_index = 0;
+ break;
+
+ default:
+ goto failed;
+ }
- for (p = inherited, v = p; *p; p++) {
+ for (p = inherited + 1, v = p; *p; p++) {
switch (*p) {
case NGX_QUIC_BPF_ADDRSEP:
- if (!in_fd) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
- "quic bpf failed to parse inherited env");
- return NGX_ERROR;
+ if (nfd > 1) {
+ goto failed;
}
- in_fd = 0;
- s = ngx_atoi(v, p - v);
- if (s == NGX_ERROR) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
- "quic bpf failed to parse inherited map fd");
- return NGX_ERROR;
+ fd = ngx_atoi(v, p - v);
+ if (fd == NGX_ERROR) {
+ goto failed;
}
+ fds[nfd++] = fd;
v = p + 1;
break;
case NGX_QUIC_BPF_VARSEP:
- if (in_fd) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
- "quic bpf failed to parse inherited env");
- return NGX_ERROR;
+ if (nfd != 2) {
+ goto failed;
}
- in_fd = 1;
- grp = ngx_pcalloc(cycle->pool,
- sizeof(ngx_quic_sock_group_t));
+ grp = ngx_pcalloc(cycle->pool, sizeof(ngx_quic_sock_group_t));
if (grp == NULL) {
- return NGX_ERROR;
+ goto failed;
}
- grp->map_fd = s;
-
- if (ngx_parse_addr_port(cycle->pool, &tmp, v, p - v)
+ if (ngx_array_init(&grp->listening, cycle->pool, 1,
+ sizeof(ngx_quic_bpf_listening_t))
!= NGX_OK)
{
- ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
- "quic bpf failed to parse inherited"
- " address '%*s'", p - v , v);
+ goto failed;
+ }
- ngx_quic_bpf_close(cycle->log, s, "inherited map");
+ grp->sock_map = fds[0];
+ grp->worker_counts_map = fds[1];
- return NGX_ERROR;
+ if (ngx_parse_addr_port(cycle->pool, &tmp, v, p - v) != NGX_OK) {
+ goto failed;
}
- grp->sockaddr = tmp.sockaddr;
- grp->socklen = tmp.socklen;
+ grp->sockaddr = ngx_pcalloc(cycle->pool, tmp.socklen);
+ if (grp->sockaddr == NULL) {
+ goto failed;
+ }
- grp->unused = 1;
+ ngx_memcpy(grp->sockaddr, tmp.sockaddr, tmp.socklen);
+ grp->socklen = tmp.socklen;
ngx_queue_insert_tail(&bcf->groups, &grp->queue);
- ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
+ ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"quic bpf sockmap inherited with "
- "fd:%d address:%*s",
- grp->map_fd, p - v, v);
+ "fds:%d/%d address:%*s",
+ fds[0], fds[1], p - v, v);
+
+ nfd = 0;
v = p + 1;
break;
}
}
+ return NGX_OK;
+
+failed:
+
+ for (i = 0; i < nfd; i++) {
+ ngx_quic_bpf_close(cycle->log, fds[i], "inherited");
+ }
+
+ ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
+ "quic bpf failed to parse inherited QUIC BPF variable");
+
+ return NGX_ERROR;
+}
+
+
+ngx_int_t
+ngx_quic_bpf_get_worker_fd(ngx_connection_t *lc, ngx_socket_t *fd)
+{
+ ngx_event_t *rev;
+ ngx_connection_t *c;
+ ngx_quic_bpf_conf_t *bcf;
+ ngx_quic_sock_group_t *grp;
+ ngx_quic_bpf_listening_t *bpf_listening, *bls;
+
+ bcf = ngx_quic_bpf_get_conf((ngx_cycle_t *) ngx_cycle);
+
+ if (!bcf->enabled || !lc->listening->quic || !lc->listening->reuseport) {
+ *fd = lc->fd;
+ return NGX_OK;
+ }
+
+ grp = ngx_quic_bpf_find_group(bcf, lc->listening);
+
+ if (grp == NULL) {
+ *fd = lc->fd;
+ return NGX_OK;
+ }
+
+ if (ngx_worker >= grp->listening.nelts) {
+ return NGX_ERROR;
+ }
+
+ bpf_listening = grp->listening.elts;
+ bls = &bpf_listening[ngx_worker];
+
+ if (bls->fd == (ngx_socket_t) -1) {
+ return NGX_ERROR;
+ }
+
+ if (bls->connection == NULL) {
+ c = ngx_get_connection(bls->fd, lc->log);
+ if (c == NULL) {
+ return NGX_ERROR;
+ }
+
+ c->type = SOCK_DGRAM;
+ c->log = lc->log;
+ c->listening = bls->listening;
+
+ rev = c->read;
+ rev->quic = 1;
+ rev->log = c->log;
+ rev->handler = ngx_quic_recvmsg;
+
+ if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
+ ngx_free_connection(c);
+ return NGX_ERROR;
+ }
+
+ bls->connection = c;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, lc->log, 0,
+ "quic bpf socket connection fd:%d", bls->fd);
+ }
+
+ *fd = bls->fd;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, lc->log, 0,
+ "quic bpf socket fd:%d", bls->fd);
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_quic_bpf_get_worker_key(ngx_connection_t *c, uint64_t *key)
+{
+ ngx_quic_bpf_conf_t *bcf;
+ ngx_quic_sock_group_t *grp;
+ ngx_quic_bpf_listening_t *bls;
+
+ bcf = ngx_quic_bpf_get_conf((ngx_cycle_t *) ngx_cycle);
+
+ if (!bcf->enabled || !c->listening->quic || !c->listening->reuseport) {
+ return NGX_DECLINED;
+ }
+
+ grp = ngx_quic_bpf_find_group(bcf, c->listening);
+
+ if (grp == NULL) {
+ return NGX_DECLINED;
+ }
+
+ if (ngx_worker >= grp->listening.nelts) {
+ return NGX_ERROR;
+ }
+
+ bls = grp->listening.elts;
+
+ if (bls[ngx_worker].fd == (ngx_socket_t) -1) {
+ return NGX_ERROR;
+ }
+
+ *key = bls[ngx_worker].key;
+
return NGX_OK;
}
--- /dev/null
+
+/*
+ * 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_worker_fd(ngx_connection_t *lc,
+ ngx_socket_t *fd);
+ngx_int_t ngx_quic_bpf_get_worker_key(ngx_connection_t *c, uint64_t *key);
+
+
+#endif /* _NGX_EVENT_QUIC_BPF_H_INCLUDED_ */
static ngx_bpf_reloc_t bpf_reloc_prog_ngx_quic_reuseport_helper[] = {
- { "ngx_quic_sockmap", 77 },
+ { "ngx_quic_sockmap", 81 },
+ { "ngx_quic_worker_counts", 97 },
+ { "ngx_quic_worker_counts", 106 },
+ { "ngx_quic_sockmap", 133 },
+ { "ngx_quic_sockmap", 170 },
};
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_8, BPF_REG_6, (int16_t) 8, 0x0 },
- { 0x79, BPF_REG_7, BPF_REG_6, (int16_t) 0, 0x0 },
- { 0xbf, BPF_REG_1, BPF_REG_7, (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, 0x8 },
- { 0x2d, BPF_REG_8, BPF_REG_1, (int16_t) 10, 0x0 },
+ { 0x2d, BPF_REG_9, BPF_REG_1, (int16_t) 11, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
- { 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xfffffff7 },
+ { 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xffffffef },
{ 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 },
+ { 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
{ 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 1, 0x0 },
- { 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 67, 0x0 },
- { 0x71, BPF_REG_1, BPF_REG_10, (int16_t) 65527, 0x0 },
+ { 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 163, 0x0 },
+ { 0x71, BPF_REG_1, BPF_REG_10, (int16_t) 65519, 0x0 },
{ 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 2, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_1, (int16_t) 0, 0x0 },
- { 0x73, BPF_REG_10, BPF_REG_1, (int16_t) 65527, 0x0 },
+ { 0x73, BPF_REG_10, BPF_REG_1, (int16_t) 65519, 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) 18, 0xffffffff },
- { 0xbf, BPF_REG_1, BPF_REG_7, (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, 0xd },
- { 0x2d, BPF_REG_8, BPF_REG_1, (int16_t) 11, 0x0 },
+ { 0x2d, BPF_REG_9, BPF_REG_1, (int16_t) 11, 0x0 },
{ 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
- { 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xfffffff7 },
+ { 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xffffffef },
{ 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) 49, 0x0 },
- { 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xe },
- { 0x71, BPF_REG_1, BPF_REG_10, (int16_t) 65527, 0x0 },
- { 0x15, BPF_REG_1, BPF_REG_0, (int16_t) 5, 0x14 },
- { 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 45, 0x0 },
- { 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xe },
+ { 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
+ { 0x15, BPF_REG_0, BPF_REG_0, (int16_t) 1, 0x0 },
+ { 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 143, 0x0 },
+ { 0x71, BPF_REG_1, BPF_REG_10, (int16_t) 65519, 0x0 },
+ { 0x5, BPF_REG_0, BPF_REG_0, (int16_t) 2, 0x0 },
{ 0x71, BPF_REG_1, BPF_REG_1, (int16_t) 0, 0x0 },
- { 0x73, BPF_REG_10, BPF_REG_1, (int16_t) 65527, 0x0 },
- { 0x55, BPF_REG_1, BPF_REG_0, (int16_t) 41, 0x14 },
- { 0xf, BPF_REG_7, BPF_REG_2, (int16_t) 0, 0x0 },
- { 0xbf, BPF_REG_1, BPF_REG_7, (int16_t) 0, 0x0 },
+ { 0x73, BPF_REG_10, BPF_REG_1, (int16_t) 65519, 0x0 },
+ { 0xb7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0xe },
+ { 0x55, BPF_REG_1, BPF_REG_0, (int16_t) 52, 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_8, BPF_REG_1, (int16_t) 7, 0x0 },
- { 0xbf, BPF_REG_7, BPF_REG_10, (int16_t) 0, 0x0 },
- { 0x7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0xffffffe3 },
+ { 0x3d, BPF_REG_9, BPF_REG_1, (int16_t) 8, 0x0 },
+ { 0xbf, BPF_REG_8, BPF_REG_10, (int16_t) 0, 0x0 },
+ { 0x7, BPF_REG_8, BPF_REG_0, (int16_t) 0, 0xffffffdb },
{ 0xbf, BPF_REG_1, BPF_REG_6, (int16_t) 0, 0x0 },
- { 0xbf, BPF_REG_3, BPF_REG_7, (int16_t) 0, 0x0 },
+ { 0xbf, BPF_REG_3, BPF_REG_8, (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 },
- { 0x55, BPF_REG_0, BPF_REG_0, (int16_t) 30, 0x0 },
- { 0x71, BPF_REG_2, BPF_REG_7, (int16_t) 0, 0x0 },
- { 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x38 },
- { 0x71, BPF_REG_1, BPF_REG_7, (int16_t) 1, 0x0 },
+ { 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
+ { 0x55, BPF_REG_0, BPF_REG_0, (int16_t) 125, 0x0 },
+ { 0x71, BPF_REG_1, BPF_REG_8, (int16_t) 1, 0x0 },
{ 0x67, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x30 },
- { 0x4f, BPF_REG_1, BPF_REG_2, (int16_t) 0, 0x0 },
- { 0x71, BPF_REG_2, BPF_REG_7, (int16_t) 2, 0x0 },
- { 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x28 },
- { 0x4f, BPF_REG_1, BPF_REG_2, (int16_t) 0, 0x0 },
- { 0x71, BPF_REG_2, BPF_REG_7, (int16_t) 3, 0x0 },
+ { 0x71, BPF_REG_2, BPF_REG_8, (int16_t) 0, 0x0 },
+ { 0xbf, BPF_REG_3, BPF_REG_2, (int16_t) 0, 0x0 },
+ { 0x67, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x38 },
+ { 0x4f, BPF_REG_1, BPF_REG_3, (int16_t) 0, 0x0 },
+ { 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 2, 0x0 },
+ { 0x67, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x28 },
+ { 0x4f, BPF_REG_1, BPF_REG_3, (int16_t) 0, 0x0 },
+ { 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 3, 0x0 },
+ { 0x67, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x20 },
+ { 0x4f, BPF_REG_1, BPF_REG_3, (int16_t) 0, 0x0 },
+ { 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 4, 0x0 },
+ { 0x67, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x18 },
+ { 0x4f, BPF_REG_1, BPF_REG_3, (int16_t) 0, 0x0 },
+ { 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 5, 0x0 },
+ { 0x67, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x10 },
+ { 0x4f, BPF_REG_1, BPF_REG_3, (int16_t) 0, 0x0 },
+ { 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 7, 0x0 },
+ { 0x4f, BPF_REG_1, BPF_REG_3, (int16_t) 0, 0x0 },
+ { 0x71, BPF_REG_3, BPF_REG_8, (int16_t) 6, 0x0 },
+ { 0x67, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0x8 },
+ { 0x4f, BPF_REG_1, BPF_REG_3, (int16_t) 0, 0x0 },
+ { 0x7b, BPF_REG_10, BPF_REG_1, (int16_t) 65520, 0x0 },
+ { 0x15, BPF_REG_2, BPF_REG_0, (int16_t) 15, 0xff },
+ { 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
+ { 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xfffffff0 },
+ { 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) 89, 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) 84, 0x0 },
+ { 0xb7, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
+ { 0x63, BPF_REG_10, BPF_REG_7, (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 },
+ { 0xbf, BPF_REG_8, BPF_REG_0, (int16_t) 0, 0x0 },
+ { 0x15, BPF_REG_8, BPF_REG_0, (int16_t) 76, 0x0 },
+ { 0xb7, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x1 },
+ { 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) 68, 0x0 },
+ { 0x61, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x0 },
+ { 0x61, BPF_REG_9, BPF_REG_8, (int16_t) 0, 0x0 },
+ { 0x2d, BPF_REG_9, BPF_REG_1, (int16_t) 1, 0x0 },
+ { 0xbf, BPF_REG_9, BPF_REG_1, (int16_t) 0, 0x0 },
+ { 0x15, BPF_REG_9, BPF_REG_0, (int16_t) 63, 0x0 },
+ { 0xbf, BPF_REG_1, BPF_REG_9, (int16_t) 0, 0x0 },
+ { 0x67, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x20 },
+ { 0x77, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x20 },
+ { 0xbf, BPF_REG_7, BPF_REG_0, (int16_t) 0, 0x0 },
+ { 0x61, BPF_REG_2, BPF_REG_6, (int16_t) 32, 0x0 },
+ { 0x9f, BPF_REG_2, BPF_REG_1, (int16_t) 0, 0x0 },
{ 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x20 },
- { 0x4f, BPF_REG_1, BPF_REG_2, (int16_t) 0, 0x0 },
- { 0x71, BPF_REG_2, BPF_REG_7, (int16_t) 4, 0x0 },
- { 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x18 },
- { 0x4f, BPF_REG_1, BPF_REG_2, (int16_t) 0, 0x0 },
- { 0x71, BPF_REG_2, BPF_REG_7, (int16_t) 5, 0x0 },
- { 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x10 },
- { 0x4f, BPF_REG_1, BPF_REG_2, (int16_t) 0, 0x0 },
- { 0x71, BPF_REG_2, BPF_REG_7, (int16_t) 6, 0x0 },
- { 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x8 },
- { 0x4f, BPF_REG_1, BPF_REG_2, (int16_t) 0, 0x0 },
- { 0x71, BPF_REG_2, BPF_REG_7, (int16_t) 7, 0x0 },
- { 0x4f, BPF_REG_1, BPF_REG_2, (int16_t) 0, 0x0 },
- { 0x7b, BPF_REG_10, BPF_REG_1, (int16_t) 65528, 0x0 },
+ { 0xc7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x20 },
+ { 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0xffffffff },
+ { 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0xffff },
+ { 0x5f, BPF_REG_2, BPF_REG_1, (int16_t) 0, 0x0 },
+ { 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x0 },
+ { 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0xff000000 },
+ { 0x4f, BPF_REG_2, BPF_REG_1, (int16_t) 0, 0x0 },
+ { 0x7b, BPF_REG_10, BPF_REG_2, (int16_t) 65520, 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, 0xfffffff0 },
{ 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 },
+ { 0xbf, BPF_REG_2, BPF_REG_7, (int16_t) 0, 0x0 },
+ { 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) 36, 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) 31, 0x0 },
+ { 0x61, BPF_REG_1, BPF_REG_8, (int16_t) 0, 0x0 },
+ { 0x61, BPF_REG_2, BPF_REG_2, (int16_t) 0, 0x0 },
+ { 0x2d, BPF_REG_2, BPF_REG_1, (int16_t) 1, 0x0 },
+ { 0xbf, BPF_REG_1, BPF_REG_2, (int16_t) 0, 0x0 },
+ { 0x15, BPF_REG_1, BPF_REG_0, (int16_t) 26, 0x0 },
+ { 0x67, BPF_REG_9, BPF_REG_0, (int16_t) 0, 0x20 },
+ { 0x77, BPF_REG_9, BPF_REG_0, (int16_t) 0, 0x20 },
+ { 0x67, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x20 },
+ { 0x77, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x20 },
+ { 0x1d, BPF_REG_1, BPF_REG_9, (int16_t) 21, 0x0 },
+ { 0x61, BPF_REG_2, BPF_REG_6, (int16_t) 32, 0x0 },
+ { 0x9f, BPF_REG_2, BPF_REG_1, (int16_t) 0, 0x0 },
+ { 0x67, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x20 },
+ { 0xc7, BPF_REG_2, BPF_REG_0, (int16_t) 0, 0x20 },
+ { 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0xffffffff },
+ { 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0xffff },
+ { 0x5f, BPF_REG_2, BPF_REG_1, (int16_t) 0, 0x0 },
+ { 0x18, BPF_REG_1, BPF_REG_0, (int16_t) 0, 0x0 },
+ { 0x0, BPF_REG_0, BPF_REG_0, (int16_t) 0, 0xff000000 },
+ { 0x4f, BPF_REG_2, BPF_REG_1, (int16_t) 0, 0x0 },
+ { 0x7b, BPF_REG_10, BPF_REG_2, (int16_t) 65520, 0x0 },
+ { 0xbf, BPF_REG_3, BPF_REG_10, (int16_t) 0, 0x0 },
+ { 0x7, BPF_REG_3, BPF_REG_0, (int16_t) 0, 0xfffffff0 },
+ { 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 },
+ { 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) 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 },
};
#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 */
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 */
+ return NGX_ERROR;
}
#endif
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;
+ uint64_t key;
+ ngx_int_t rc;
- optlen = sizeof(cookie);
+ rc = ngx_quic_bpf_get_worker_key(c, &key);
- 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");
+ if (rc == NGX_DECLINED) {
+ /* BPF not applicable for this listener, leave DCID as random */
+ return NGX_OK;
+ }
+ if (rc != NGX_OK) {
return NGX_ERROR;
}
- ngx_quic_dcid_encode_key(id, cookie);
+ ngx_quic_dcid_encode_key(id, key);
return NGX_OK;
}
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;
}
ngx_err_t err;
socklen_t socklen, local_socklen;
ngx_event_t *rev, *wev;
+ ngx_socket_t cfd;
struct iovec iov[1];
struct msghdr msg;
ngx_sockaddr_t sa, lsa;
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;
}
goto next;
}
+#if (NGX_QUIC_BPF)
+ if (lc->read->quic) {
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
+ "quic new connection on worker socket, dropped");
+ goto next;
+ }
+#endif
+
#if (NGX_STAT_STUB)
(void) ngx_atomic_fetch_add(ngx_stat_accepted, 1);
#endif
ngx_accept_disabled = ngx_cycle->connection_n / 8
- ngx_cycle->free_connection_n;
- c = ngx_get_connection(lc->fd, ev->log);
+ cfd = lc->fd;
+
+#if (NGX_QUIC_BPF)
+ if (ngx_quic_bpf_get_worker_fd(lc, &cfd) != NGX_OK) {
+ return;
+ }
+#endif
+
+ c = ngx_get_connection(cfd, ev->log);
if (c == NULL) {
return;
}
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);
}
}
&& 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",