server: add configuration option for enabling socket affinity

This commit is contained in:
Daniel Salzman 2021-01-18 11:19:35 +01:00
parent 3101a3d488
commit 2f4d05ecd1
10 changed files with 84 additions and 13 deletions

View file

@ -190,6 +190,7 @@ server:
tcp\-remote\-io\-timeout: INT
tcp\-max\-clients: INT
tcp\-reuseport: BOOL
socket\-affinity: BOOL
udp\-max\-payload: SIZE
udp\-max\-payload\-ipv4: SIZE
udp\-max\-payload\-ipv6: SIZE
@ -332,6 +333,16 @@ advisable to use this option on slave servers.
Change of this parameter requires restart of the Knot server to take effect.
.sp
\fIDefault:\fP off
.SS socket\-affinity
.sp
If enabled and if SO_REUSEPORT is available on Linux, all configured network
sockets are bound to UDP and TCP workers in order to increase the networking performance.
This mode isn\(aqt recommended for setups where the number of network card queues
is lower than the number of UDP or TCP workers.
.sp
Change of this parameter requires restart of the Knot server to take effect.
.sp
\fIDefault:\fP off
.SS tcp\-max\-clients
.sp
A maximum number of TCP clients connected in parallel, set this below the file

View file

@ -141,6 +141,7 @@ General options related to the server.
tcp-remote-io-timeout: INT
tcp-max-clients: INT
tcp-reuseport: BOOL
socket-affinity: BOOL
udp-max-payload: SIZE
udp-max-payload-ipv4: SIZE
udp-max-payload-ipv6: SIZE
@ -328,6 +329,20 @@ Change of this parameter requires restart of the Knot server to take effect.
*Default:* off
.. _server_socket-affinity:
socket-affinity
---------------
If enabled and if SO_REUSEPORT is available on Linux, all configured network
sockets are bound to UDP and TCP workers in order to increase the networking performance.
This mode isn't recommended for setups where the number of network card queues
is lower than the number of UDP or TCP workers.
Change of this parameter requires restart of the Knot server to take effect.
*Default:* off
.. _server_tcp-max-clients:
tcp-max-clients

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -124,6 +124,7 @@ static void init_cache(
static bool first_init = true;
static bool running_tcp_reuseport;
static bool running_socket_affinity;
static size_t running_udp_threads;
static size_t running_tcp_threads;
static size_t running_xdp_threads;
@ -131,6 +132,7 @@ static void init_cache(
if (first_init || reinit_cache) {
running_tcp_reuseport = conf_tcp_reuseport(conf);
running_socket_affinity = conf_socket_affinity(conf);
running_udp_threads = conf_udp_threads(conf);
running_tcp_threads = conf_tcp_threads(conf);
running_xdp_threads = conf_xdp_threads(conf);
@ -183,6 +185,8 @@ static void init_cache(
conf->cache.srv_tcp_reuseport = running_tcp_reuseport;
conf->cache.srv_socket_affinity = running_socket_affinity;
conf->cache.srv_udp_threads = running_udp_threads;
conf->cache.srv_tcp_threads = running_tcp_threads;

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -114,6 +114,7 @@ typedef struct {
int srv_tcp_io_timeout;
int srv_tcp_remote_io_timeout;
bool srv_tcp_reuseport;
bool srv_socket_affinity;
size_t srv_udp_threads;
size_t srv_tcp_threads;
size_t srv_xdp_threads;

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1174,6 +1174,14 @@ bool conf_tcp_reuseport_txn(
return conf_bool(&val);
}
bool conf_socket_affinity_txn(
conf_t *conf,
knot_db_txn_t *txn)
{
conf_val_t val = conf_get_txn(conf, txn, C_SRV, C_SOCKET_AFFINITY);
return conf_bool(&val);
}
size_t conf_udp_threads_txn(
conf_t *conf,
knot_db_txn_t *txn)

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -686,6 +686,24 @@ static inline bool conf_tcp_reuseport(
return conf_tcp_reuseport_txn(conf, &conf->read_txn);
}
/*!
* Gets the configured setting of the socket affinity switch.
*
* \param[in] conf Configuration.
* \param[in] txn Configuration DB transaction.
*
* \return True if enabled, false otherwise.
*/
bool conf_socket_affinity_txn(
conf_t *conf,
knot_db_txn_t *txn
);
static inline bool conf_socket_affinity(
conf_t *conf)
{
return conf_socket_affinity_txn(conf, &conf->read_txn);
}
/*!
* Gets the configured number of UDP threads.
*

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -171,6 +171,7 @@ static const yp_item_t desc_server[] = {
{ C_TCP_RMT_IO_TIMEOUT, YP_TINT, YP_VINT = { 0, INT32_MAX, 5000 } },
{ C_TCP_MAX_CLIENTS, YP_TINT, YP_VINT = { 0, INT32_MAX, YP_NIL } },
{ C_TCP_REUSEPORT, YP_TBOOL, YP_VNONE },
{ C_SOCKET_AFFINITY, YP_TBOOL, YP_VNONE },
{ C_UDP_MAX_PAYLOAD, YP_TINT, YP_VINT = { KNOT_EDNS_MIN_DNSSEC_PAYLOAD,
KNOT_EDNS_MAX_UDP_PAYLOAD,
1232, YP_SSIZE } },

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -105,6 +105,7 @@
#define C_SERVER "\x06""server"
#define C_SIGNING_THREADS "\x0F""signing-threads"
#define C_SINGLE_TYPE_SIGNING "\x13""single-type-signing"
#define C_SOCKET_AFFINITY "\x0F""socket-affinity"
#define C_SRV "\x06""server"
#define C_STATS "\x0A""statistics"
#define C_STORAGE "\x07""storage"

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -307,13 +307,14 @@ static iface_t *server_init_xdp_iface(struct sockaddr_storage *addr, unsigned *t
* \param udp_thread_count Number of created UDP workers.
* \param tcp_thread_count Number of created TCP workers.
* \param tcp_reuseport Indication if reuseport on TCP is enabled.
* \param socket_affinity Indication if CBPF should be attached.
*
* \retval Pointer to a new initialized inteface.
* \retval NULL if error.
*/
static iface_t *server_init_iface(struct sockaddr_storage *addr,
int udp_thread_count, int tcp_thread_count,
bool tcp_reuseport)
bool tcp_reuseport, bool socket_affinity)
{
iface_t *new_if = calloc(1, sizeof(*new_if));
if (new_if == NULL) {
@ -374,7 +375,7 @@ static iface_t *server_init_iface(struct sockaddr_storage *addr,
return NULL;
}
if (udp_bind_flags & NET_BIND_MULTIPLE) {
if ((udp_bind_flags & NET_BIND_MULTIPLE) && socket_affinity) {
if (!server_attach_reuseport_bpf(sock, udp_socket_count) &&
warn_cbpf) {
log_warning("cannot ensure optimal CPU locality for UDP");
@ -446,7 +447,7 @@ static iface_t *server_init_iface(struct sockaddr_storage *addr,
return NULL;
}
if (tcp_bind_flags & NET_BIND_MULTIPLE) {
if ((tcp_bind_flags & NET_BIND_MULTIPLE) && socket_affinity) {
if (!server_attach_reuseport_bpf(sock, tcp_socket_count) &&
warn_cbpf) {
log_warning("cannot ensure optimal CPU locality for TCP");
@ -475,7 +476,9 @@ static int configure_sockets(conf_t *conf, server_t *s)
#ifdef ENABLE_REUSEPORT
/* Log info if reuseport is used and for what protocols. */
log_info("using reuseport for UDP%s", conf->cache.srv_tcp_reuseport ? " and TCP" : "");
log_info("using reuseport%s for UDP%s",
conf->cache.srv_socket_affinity ? " with socket affinity" : "",
conf->cache.srv_tcp_reuseport ? " and TCP" : "");
#endif
/* Update bound interfaces. */
@ -505,6 +508,7 @@ static int configure_sockets(conf_t *conf, server_t *s)
unsigned size_udp = s->handlers[IO_UDP].handler.unit->size;
unsigned size_tcp = s->handlers[IO_TCP].handler.unit->size;
bool tcp_reuseport = conf->cache.srv_tcp_reuseport;
bool socket_affinity = conf->cache.srv_socket_affinity;
char *rundir = conf_abs_path(&rundir_val, NULL);
while (listen_val.code == KNOT_EOK) {
struct sockaddr_storage addr = conf_addr(&listen_val, rundir);
@ -513,7 +517,7 @@ static int configure_sockets(conf_t *conf, server_t *s)
log_info("binding to interface %s", addr_str);
iface_t *new_if = server_init_iface(&addr, size_udp, size_tcp,
tcp_reuseport);
tcp_reuseport, socket_affinity);
if (new_if == NULL) {
server_deinit_iface_list(newlist, nifs);
free(rundir);
@ -861,6 +865,7 @@ static void warn_server_reconfigure(conf_t *conf, server_t *server)
const char *msg = "changes of %s require restart to take effect";
static bool warn_tcp_reuseport = true;
static bool warn_socket_affinity = true;
static bool warn_udp = true;
static bool warn_tcp = true;
static bool warn_bg = true;
@ -871,6 +876,11 @@ static void warn_server_reconfigure(conf_t *conf, server_t *server)
warn_tcp_reuseport = false;
}
if (warn_socket_affinity && conf->cache.srv_socket_affinity != conf_socket_affinity(conf)) {
log_warning(msg, &C_SOCKET_AFFINITY[1]);
warn_socket_affinity = false;
}
if (warn_udp && server->handlers[IO_UDP].size != conf_udp_threads(conf)) {
log_warning(msg, &C_UDP_WORKERS[1]);
warn_udp = false;

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -908,6 +908,7 @@ static void test_conf_io_list(void)
"server.tcp-remote-io-timeout\n"
"server.tcp-max-clients\n"
"server.tcp-reuseport\n"
"server.socket-affinity\n"
"server.udp-workers\n"
"server.tcp-workers\n"
"server.background-workers\n"
@ -930,6 +931,7 @@ static const yp_item_t desc_server[] = {
{ C_TCP_RMT_IO_TIMEOUT, YP_TINT, YP_VNONE },
{ C_TCP_MAX_CLIENTS, YP_TINT, YP_VNONE },
{ C_TCP_REUSEPORT, YP_TBOOL, YP_VNONE },
{ C_SOCKET_AFFINITY, YP_TBOOL, YP_VNONE },
{ C_UDP_WORKERS, YP_TINT, YP_VNONE },
{ C_TCP_WORKERS, YP_TINT, YP_VNONE },
{ C_BG_WORKERS, YP_TINT, YP_VNONE },