]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon: set options on sockets towards clients (optionally) docs-develop-tmp-xva6ir/deployments/4625
authorVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 10 Jun 2024 13:03:23 +0000 (15:03 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 22 Jul 2024 10:56:01 +0000 (12:56 +0200)
daemon/io.c
daemon/network.c
daemon/network.h

index 48ee96bba7493c08e18ba34ca26c1a66287d399a..5d4e7f9a5bdf94abb6cc4fa2c83e6168cafbcabb 100644 (file)
@@ -251,6 +251,17 @@ int io_bind(const struct sockaddr *addr, int type, const endpoint_flags_t *flags
        return fd;
 }
 
+/// Optionally set a socket option and log error on failure.
+static void set_so(int fd, int so_option, int value, const char *descr)
+{
+       if (!value) return;
+       if (setsockopt(fd, SOL_SOCKET, so_option, &value, sizeof(value))) {
+               kr_log_error(IO, "failed to set %s to %d: %s\n",
+                               descr, value, strerror(errno));
+               // we treat this as non-critical failure
+       }
+}
+
 int io_listen_udp(uv_loop_t *loop, uv_udp_t *handle, int fd)
 {
        if (!handle) {
@@ -262,6 +273,10 @@ int io_listen_udp(uv_loop_t *loop, uv_udp_t *handle, int fd)
        ret = uv_udp_open(handle, fd);
        if (ret) return ret;
 
+       struct network *net = &the_worker->engine->net;
+       set_so(fd, SO_SNDBUF, net->listen_udp_buflens.snd, "UDP send buffer size");
+       set_so(fd, SO_RCVBUF, net->listen_udp_buflens.rcv, "UDP receive buffer size");
+
        uv_handle_t *h = (uv_handle_t *)handle;
        check_bufsize(h);
        /* Handle is already created, just create context. */
@@ -702,6 +717,18 @@ int io_listen_tcp(uv_loop_t *loop, uv_tcp_t *handle, int fd, int tcp_backlog, bo
        }
 #endif
 
+       /* These get inherited into the individual connections (on Linux at least). */
+       struct network *net = &the_worker->engine->net;
+       set_so(fd, SO_SNDBUF, net->listen_tcp_buflens.snd, "TCP send buffer size");
+       set_so(fd, SO_RCVBUF, net->listen_tcp_buflens.rcv, "TCP receive buffer size");
+#ifdef TCP_USER_TIMEOUT
+       val = net->tcp.user_timeout;
+       if (val && setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &val, sizeof(val))) {
+               kr_log_error(IO, "listen TCP (user_timeout): %s\n", strerror(errno));
+       }
+       // TODO: also for upstream connections, at least this one option?
+#endif
+
        handle->data = NULL;
        return 0;
 }
index a20b1e453afec4dc57dd7787740585d53647031d..598b1dcd4054d588d620fb199ad7b5656ac1f53f 100644 (file)
@@ -73,6 +73,11 @@ void network_init(struct network *net, uv_loop_t *loop, int tcp_backlog)
                net->tcp.in_idle_timeout = 10000;
                net->tcp.tls_handshake_timeout = TLS_MAX_HANDSHAKE_TIME;
                net->tcp_backlog = tcp_backlog;
+               net->tcp.user_timeout = 1000; // 1s should be more than enough
+
+               // On Linux, unset means some auto-tuning mechanism also depending on RAM,
+               // which might be OK default (together with the user_timeout above)
+               //net->listen_{tcp,udp}_buflens.{snd,rcv}
        }
 }
 
index e21651fdd0e9bdd4bd69dd8f08e74d1bdeba129c..c9cd621bb08afb8a5a6694b04b4d8fc71622270f 100644 (file)
@@ -67,6 +67,10 @@ typedef array_t(struct endpoint) endpoint_array_t;
 struct net_tcp_param {
        uint64_t in_idle_timeout;
        uint64_t tls_handshake_timeout;
+
+       /** Milliseconds of unacknowledged data; see TCP_USER_TIMEOUT in man tcp.7
+        * Linux only, probably. */
+       unsigned int user_timeout;
 };
 
 /** Information about an address that is allowed to use PROXYv2. */
@@ -104,6 +108,13 @@ struct network {
        struct tls_session_ticket_ctx *tls_session_ticket_ctx;
        struct net_tcp_param tcp;
        int tcp_backlog;
+
+       /** Kernel-side buffer sizes for sending and receiving. (in bytes)
+        * They are per socket, so in the TCP case they are per connection.
+        * See SO_SNDBUF and SO_RCVBUF in man socket.7  These are in POSIX. */
+       struct {
+               int snd, rcv;
+       } listen_udp_buflens, listen_tcp_buflens;
 };
 
 void network_init(struct network *net, uv_loop_t *loop, int tcp_backlog);