diff --git a/doc/man/knot.conf.5in b/doc/man/knot.conf.5in index b032e555c61088fcd58e5407b3a255b82f800f29..0b5e78fc5c3907e558d6281f7f86036a21bd97bd 100644 --- a/doc/man/knot.conf.5in +++ b/doc/man/knot.conf.5in @@ -200,6 +200,7 @@ server: xdp\-route\-check: BOOL listen: ADDR[@INT] ... listen\-xdp: STR[@INT] | ADDR[@INT] ... + xdp\-tcp: BOOL .ft P .fi .UNINDENT @@ -476,6 +477,17 @@ intended to offer the DNS service, at least to fulfil the DNS requirement for working TCP. .UNINDENT .UNINDENT +.SS xdp\-tcp +.sp +Also answer TCP traffic (queries) with XDP workers. +.sp +\fBWARNING:\fP +.INDENT 0.0 +.INDENT 3.5 +This feature is highly experimental and it may eat your hamster as well as any +other hamsters connected to the network. +.UNINDENT +.UNINDENT .SH CONTROL SECTION .sp Configuration of the server control interface. diff --git a/doc/reference.rst b/doc/reference.rst index 2cde3bcde01bcfd70546cb643b3d8427a682ec55..2006edd4d1788a498ee402e0d9a2b2dfc670e992 100644 --- a/doc/reference.rst +++ b/doc/reference.rst @@ -151,6 +151,7 @@ General options related to the server. xdp-route-check: BOOL listen: ADDR[@INT] ... listen-xdp: STR[@INT] | ADDR[@INT] ... + xdp-tcp: BOOL .. CAUTION:: When you change configuration parameters dynamically or via configuration file @@ -493,6 +494,17 @@ Change of this parameter requires restart of the Knot server to take effect. intended to offer the DNS service, at least to fulfil the DNS requirement for working TCP. +.. _server_xdp-tcp: + +xdp-tcp +------- + +Also answer TCP traffic (queries) with XDP workers. + +.. WARNING:: + This feature is highly experimental and it may eat your hamster as well as any + other hamsters connected to the network. + .. _Control section: Control section diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c index 693c3fe8c69d1e4d37ebf8b8214d06882cca23a5..108d88589308e99a5c0cfffc7f42d9cd4616be57 100644 --- a/src/knot/conf/conf.c +++ b/src/knot/conf/conf.c @@ -1188,7 +1188,7 @@ size_t conf_xdp_threads_txn( while (val.code == KNOT_EOK) { struct sockaddr_storage addr = conf_addr(&val, NULL); conf_xdp_iface_t iface; - int ret = conf_xdp_iface(&addr, &iface); + int ret = conf_xdp_iface(&addr, false, &iface); if (ret == KNOT_EOK) { workers += iface.queues; } @@ -1351,6 +1351,7 @@ conf_remote_t conf_remote_txn( int conf_xdp_iface( struct sockaddr_storage *addr, + bool tcp, conf_xdp_iface_t *iface) { #ifndef ENABLE_XDP @@ -1367,12 +1368,14 @@ int conf_xdp_iface( const char *port = strchr(addr_str, '@'); if (port != NULL) { iface->name[port - addr_str] = '\0'; - int ret = str_to_u16(port + 1, &iface->port); + uint16_t res = 0; + int ret = str_to_u16(port + 1, &res); if (ret != KNOT_EOK) { return ret; - } else if (iface->port == 0) { + } else if (res == 0) { return KNOT_EINVAL; } + iface->port = res; } else { iface->port = 53; } @@ -1395,6 +1398,10 @@ int conf_xdp_iface( } iface->queues = queues; + if (tcp) { + iface->port |= KNOT_XDP_LISTEN_PORT_TCP; + } + return KNOT_EOK; #endif } diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h index 24755a2405115f784fa12542121ff70a8f96adec..1353b3fc25300b5f88e9d10927f2dbede94ef671 100644 --- a/src/knot/conf/conf.h +++ b/src/knot/conf/conf.h @@ -828,8 +828,8 @@ static inline conf_remote_t conf_remote( typedef struct { /*! Interface name. */ char name[32]; - /*! UDP port to listen on. */ - uint16_t port; + /*! UDP port to listen on, including XDP flags. */ + uint32_t port; /*! Number of active IO queues. */ uint16_t queues; } conf_xdp_iface_t; @@ -838,11 +838,13 @@ typedef struct { * Gets the XDP interface parameters for a given configuration value. * * \param[in] addr XDP interface name stored in the configuration. + * \param[in] tcp Allow TCP listening on this XDP iface. * \param[out] iface Interface parameters. * * \return Error code, KNOT_EOK if success. */ int conf_xdp_iface( struct sockaddr_storage *addr, + bool tcp, conf_xdp_iface_t *iface ); diff --git a/src/knot/conf/schema.c b/src/knot/conf/schema.c index 88cee943e6dc6ef2674caa97f6d22be4f6ae2b44..adbb8520c1f656b78c2bac3d4d46b8c713febfa6 100644 --- a/src/knot/conf/schema.c +++ b/src/knot/conf/schema.c @@ -209,6 +209,7 @@ static const yp_item_t desc_server[] = { { C_XDP_ROUTE_CHECK, YP_TBOOL, YP_VNONE }, { C_LISTEN, YP_TADDR, YP_VADDR = { 53 }, YP_FMULTI, { check_listen } }, { C_LISTEN_XDP, YP_TADDR, YP_VADDR = { 53 }, YP_FMULTI, { check_xdp } }, + { C_XDP_TCP, YP_TBOOL, YP_VNONE }, { C_COMMENT, YP_TSTR, YP_VNONE }, // Legacy items. { C_MAX_TCP_CLIENTS, YP_TINT, YP_VINT = { 0, INT32_MAX, YP_NIL } }, diff --git a/src/knot/conf/schema.h b/src/knot/conf/schema.h index b09ded0a77e4098522bb1433642ad6a3fdf1be0a..f3157d62314684ee923e107b60fac15432dbaae9 100644 --- a/src/knot/conf/schema.h +++ b/src/knot/conf/schema.h @@ -135,6 +135,7 @@ #define C_VERSION "\x07""version" #define C_VIA "\x03""via" #define C_XDP_ROUTE_CHECK "\x0F""xdp-route-check" +#define C_XDP_TCP "\x07""xdp-tcp" #define C_ZONE "\x04""zone" #define C_ZONEFILE_LOAD "\x0D""zonefile-load" #define C_ZONEFILE_SYNC "\x0D""zonefile-sync" diff --git a/src/knot/conf/tools.c b/src/knot/conf/tools.c index ae6de6f07adc4af40f0452bfde3c6b97c8972b74..922cc58b2b708bb7be1f792f04e574887cebf2e3 100644 --- a/src/knot/conf/tools.c +++ b/src/knot/conf/tools.c @@ -256,7 +256,7 @@ int check_xdp( bool no_port; struct sockaddr_storage ss = yp_addr(args->data, &no_port); conf_xdp_iface_t if_new; - int ret = conf_xdp_iface(&ss, &if_new); + int ret = conf_xdp_iface(&ss, false, &if_new); if (ret != KNOT_EOK) { args->err_str = "invalid XDP interface specification"; return ret; @@ -268,7 +268,7 @@ int check_xdp( while (xdp.code == KNOT_EOK && count-- > 1) { struct sockaddr_storage addr = conf_addr(&xdp, NULL); conf_xdp_iface_t if_prev; - ret = conf_xdp_iface(&addr, &if_prev); + ret = conf_xdp_iface(&addr, false, &if_prev); if (ret != KNOT_EOK) { return ret; } @@ -382,7 +382,7 @@ static void check_mtu(knotd_conf_check_args_t *args, conf_val_t *xdp) while (xdp->code == KNOT_EOK) { struct sockaddr_storage addr = conf_addr(xdp, NULL); conf_xdp_iface_t iface; - int ret = conf_xdp_iface(&addr, &iface); + int ret = conf_xdp_iface(&addr, false, &iface); if (ret != KNOT_EOK) { CONF_LOG(LOG_WARNING, "failed to check XDP interface MTU"); return; diff --git a/src/knot/server/server.c b/src/knot/server/server.c index b6fd988eb27b2736ad74b57cbfb77bf58bd7d7ce..325eb750c77a9e9cc9131bda8c1b06072ae0b00e 100644 --- a/src/knot/server/server.c +++ b/src/knot/server/server.c @@ -221,14 +221,14 @@ static int disable_pmtudisc(int sock, int family) } static iface_t *server_init_xdp_iface(struct sockaddr_storage *addr, bool route_check, - unsigned *thread_id_start) + unsigned *thread_id_start, bool tcp) { #ifndef ENABLE_XDP assert(0); return NULL; #else conf_xdp_iface_t iface; - int ret = conf_xdp_iface(addr, &iface); + int ret = conf_xdp_iface(addr, tcp, &iface); if (ret != KNOT_EOK) { log_error("failed to initialize XDP interface (%s)", knot_strerror(ret)); @@ -559,12 +559,15 @@ static int configure_sockets(conf_t *conf, server_t *s) unsigned thread_id = s->handlers[IO_UDP].handler.unit->size + s->handlers[IO_TCP].handler.unit->size; while (lisxdp_val.code == KNOT_EOK) { + conf_val_t xdp_tcp_val = conf_get(conf, C_SRV, C_XDP_TCP); + bool xdp_tcp = conf_bool(&xdp_tcp_val); + struct sockaddr_storage addr = conf_addr(&lisxdp_val, NULL); char addr_str[SOCKADDR_STRLEN] = { 0 }; sockaddr_tostr(addr_str, sizeof(addr_str), &addr); - log_info("binding to XDP interface %s", addr_str); + log_info("binding to XDP interface %s%s", addr_str, xdp_tcp ? " with TCP" : ""); - iface_t *new_if = server_init_xdp_iface(&addr, route_check, &thread_id); + iface_t *new_if = server_init_xdp_iface(&addr, route_check, &thread_id, xdp_tcp); if (new_if == NULL) { server_deinit_iface_list(newlist, nifs); return KNOT_ERROR;