]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon: set options on sockets towards clients (optionally)
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 15:57:47 +0000 (17:57 +0200)
daemon/io.c
daemon/network.c
daemon/network.h

index cf3727875569fbc0e7ef7431ecee1a1114762ca1..1154d77df6dd2a61d264945fabb37bdbad4476b5 100644 (file)
@@ -261,6 +261,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) {
@@ -272,6 +283,9 @@ int io_listen_udp(uv_loop_t *loop, uv_udp_t *handle, int fd)
        ret = uv_udp_open(handle, fd);
        if (ret) return ret;
 
+       set_so(fd, SO_SNDBUF, the_network->listen_udp_buflens.snd, "UDP send buffer size");
+       set_so(fd, SO_RCVBUF, the_network->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. */
@@ -464,6 +478,17 @@ 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). */
+       set_so(fd, SO_SNDBUF, the_network->listen_tcp_buflens.snd, "TCP send buffer size");
+       set_so(fd, SO_RCVBUF, the_network->listen_tcp_buflens.rcv, "TCP receive buffer size");
+#ifdef TCP_USER_TIMEOUT
+       val = the_network->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 7d1d5155234523f79909a62aa67b58bb87f2c557..59d478093e11e659e6dcb2eb7f375ab1f42f78bb 100644 (file)
@@ -76,7 +76,12 @@ void network_init(uv_loop_t *loop, int tcp_backlog)
                        tls_session_ticket_ctx_create(loop, NULL, 0);
        the_network->tcp.in_idle_timeout = 10000;
        the_network->tcp.tls_handshake_timeout = TLS_MAX_HANDSHAKE_TIME;
+       the_network->tcp.user_timeout = 1000; // 1s should be more than enough
        the_network->tcp_backlog = tcp_backlog;
+
+       // On Linux, unset means some auto-tuning mechanism also depending on RAM,
+       // which might be OK default (together with the user_timeout above)
+       //the_network->listen_{tcp,udp}_buflens.{snd,rcv}
 }
 
 /** Notify the registered function about endpoint getting open.
index 9c667dbdce97c84f28641ed67a450177275bdaba..83d1b6f4816b4ae6de231bc528eac10baba09ddb 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;
 };
 
 /** Pointer to the singleton network state. NULL if not initialized. */