From: Libor Peltan Date: Tue, 22 Dec 2020 15:12:09 +0000 (+0100) Subject: xdp/tcp: avoid dynarray in favour of resizeable array X-Git-Tag: v3.1.0~249^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8e92f892dbd99624e64ef0936c5aef3d13abd8bb;p=thirdparty%2Fknot-dns.git xdp/tcp: avoid dynarray in favour of resizeable array --- diff --git a/src/libknot/xdp/tcp.c b/src/libknot/xdp/tcp.c index c7ec424950..9f34996363 100644 --- a/src/libknot/xdp/tcp.c +++ b/src/libknot/xdp/tcp.c @@ -22,24 +22,49 @@ #include "libknot/attribute.h" #include "libknot/error.h" -dynarray_define(tcprelay, knot_tcp_relay_t, DYNARRAY_VISIBILITY_LIBRARY) +static int add_relay(knot_tcp_relay_t *relays[], uint32_t *max_relays, + uint32_t *n_relays, knot_tcp_relay_t *to_add) +{ + assert(*n_relays <= *max_relays); + if (*relays == NULL) { + assert(*n_relays == 0); + *relays = malloc(*max_relays * sizeof(**relays)); + if (*relays == NULL) { + return KNOT_ENOMEM; + } + } else if (*n_relays == *max_relays) { + uint32_t new_max_relays = 2 * *max_relays; + knot_tcp_relay_t *new_relays = malloc(new_max_relays * sizeof(*new_relays)); + if (new_relays == NULL) { + return KNOT_ENOMEM; + } + memcpy(new_relays, *relays, *max_relays * sizeof(*new_relays)); + free(*relays); + *relays = new_relays; + *max_relays = new_max_relays; + } + memcpy(&(*relays)[(*n_relays)++], to_add, sizeof(*to_add)); + return KNOT_EOK; +} _public_ -int knot_xdp_tcp_relay(knot_xdp_msg_t *msgs, size_t n_msgs, - knot_xdp_socket_t *socket, tcprelay_dynarray_t *relays) +int knot_xdp_tcp_relay(knot_xdp_socket_t *socket, knot_xdp_msg_t msgs[], + uint32_t msg_count, knot_tcp_relay_t *relays[], + uint32_t *relay_count) { - if (n_msgs == 0) { + if (msg_count == 0) { return KNOT_EOK; } - if (msgs == NULL || socket == NULL || relays == NULL || - relays->capacity < 0 || relays->size != 0) { + if (socket == NULL || msgs == NULL || relays == NULL || + relay_count == NULL || *relay_count != 0) { return KNOT_EINVAL; } knot_xdp_send_prepare(socket); - knot_xdp_msg_t acks[n_msgs]; - size_t n_acks = 0; + knot_xdp_msg_t acks[msg_count]; + uint32_t n_acks = 0, max_relays = msg_count; + int ret = KNOT_EOK; #define resp_ack(msg) \ { \ @@ -53,7 +78,9 @@ int knot_xdp_tcp_relay(knot_xdp_msg_t *msgs, size_t n_msgs, ack->flags |= KNOT_XDP_MSG_ACK; \ } - for (size_t i = 0; i < n_msgs; i++) { +#define add_to_relays(relay) add_relay(relays, &max_relays, relay_count, (relay)); + + for (size_t i = 0; i < msg_count && ret == KNOT_EOK; i++) { knot_xdp_msg_t *msg = &msgs[i]; if (!(msg->flags & KNOT_XDP_MSG_TCP)) { continue; @@ -68,7 +95,7 @@ int knot_xdp_tcp_relay(knot_xdp_msg_t *msgs, size_t n_msgs, case (KNOT_XDP_MSG_SYN | KNOT_XDP_MSG_ACK): resp_ack(msg); relay.action = XDP_TCP_ESTABLISH; - tcprelay_dynarray_add(relays, &relay); + ret = add_to_relays(&relay); break; case KNOT_XDP_MSG_ACK: if (msg->payload.iov_len > 0) { @@ -79,12 +106,12 @@ int knot_xdp_tcp_relay(knot_xdp_msg_t *msgs, size_t n_msgs, uint8_t *payl = msg->payload.iov_base; size_t paylen = msg->payload.iov_len; - while (paylen >= sizeof(dns_len) && + while (ret == KNOT_EOK && paylen >= sizeof(dns_len) && paylen >= sizeof(dns_len) + (dns_len = be16toh(*(uint16_t *)payl))) { relay.data.iov_base = payl + sizeof(dns_len); relay.data.iov_len = dns_len - sizeof(dns_len); - tcprelay_dynarray_add(relays, &relay); + ret = add_to_relays(&relay); payl += sizeof(dns_len) + dns_len; paylen -= sizeof(dns_len) + dns_len; @@ -94,19 +121,18 @@ int knot_xdp_tcp_relay(knot_xdp_msg_t *msgs, size_t n_msgs, case (KNOT_XDP_MSG_FIN | KNOT_XDP_MSG_ACK): resp_ack(msg); relay.action = XDP_TCP_CLOSE; - tcprelay_dynarray_add(relays, &relay); + ret = add_to_relays(&relay); break; case KNOT_XDP_MSG_RST: relay.action = XDP_TCP_RESET; - tcprelay_dynarray_add(relays, &relay); + ret = add_to_relays(&relay); break; default: break; } } - int ret = KNOT_EOK; - if (n_acks > 0) { + if (n_acks > 0 && ret == KNOT_EOK) { uint32_t sent_unused; ret = knot_xdp_send(socket, acks, n_acks, &sent_unused); if (ret == KNOT_EOK) { @@ -118,18 +144,20 @@ int knot_xdp_tcp_relay(knot_xdp_msg_t *msgs, size_t n_msgs, } _public_ -int knot_xdp_tcp_send(knot_xdp_socket_t *socket, tcprelay_dynarray_t *relays) +int knot_xdp_tcp_send(knot_xdp_socket_t *socket, knot_tcp_relay_t relays[], + uint32_t relay_count) { - if (socket == NULL || relays == NULL || relays->capacity < 0) { + if (socket == NULL || relays == NULL) { return KNOT_EINVAL; } - knot_xdp_msg_t msgs[relays->size], *msg = &msgs[0]; + knot_xdp_msg_t msgs[relay_count], *msg = &msgs[0]; int ret = KNOT_EOK, n_msgs = 0; knot_xdp_send_prepare(socket); - dynarray_foreach(tcprelay, knot_tcp_relay_t, rl, *relays) { + for (size_t irl = 0; irl < relay_count; irl++) { + knot_tcp_relay_t *rl = &relays[irl]; if ((rl->answer & 0x07) == XDP_TCP_NOOP) { continue; } diff --git a/src/libknot/xdp/tcp.h b/src/libknot/xdp/tcp.h index fcb37bc798..ca8372374c 100644 --- a/src/libknot/xdp/tcp.h +++ b/src/libknot/xdp/tcp.h @@ -16,7 +16,6 @@ #pragma once -#include "contrib/dynarray.h" #include "libknot/xdp/msg.h" #include "libknot/xdp/xdp.h" @@ -36,27 +35,29 @@ typedef struct { struct iovec data; } knot_tcp_relay_t; -dynarray_declare(tcprelay, knot_tcp_relay_t, DYNARRAY_VISIBILITY_PUBLIC, 10) - /*! - * \brief Process received packets, send ACKs, pick incomming data. + * \brief Process received packets, send ACKs, pick incoming data. * - * \param msgs Packets received by knot_xdp_recv(). - * \param n_msgs Their count. - * \param socket XDP socket to answer through. - * \param relays Output: connection changes and data. + * \param socket XDP socket to answer through. + * \param msgs Packets received by knot_xdp_recv(). + * \param msg_count Number of received packets. + * \param relays Out: connection changes and data. + * \param relay_count Out: number of connection changes and data. * * \return KNOT_E* */ -int knot_xdp_tcp_relay(knot_xdp_msg_t *msgs, size_t n_msgs, - knot_xdp_socket_t *socket, tcprelay_dynarray_t *relays); +int knot_xdp_tcp_relay(knot_xdp_socket_t *socket, knot_xdp_msg_t msgs[], + uint32_t msg_count, knot_tcp_relay_t *relays[], + uint32_t *relay_count); /*! - * \brief Send TCp packets. + * \brief Send TCP packets. * - * \param socket XDP socket to send through. - * \param relays Connection changes and data. + * \param socket XDP socket to send through. + * \param relays Connection changes and data. + * \param relay_count Number of connection changes and data. * * \return KNOT_E* */ -int knot_xdp_tcp_send(knot_xdp_socket_t *socket, tcprelay_dynarray_t *relays); +int knot_xdp_tcp_send(knot_xdp_socket_t *socket, knot_tcp_relay_t relays[], + uint32_t relay_count); diff --git a/src/utils/kxdpgun/main.c b/src/utils/kxdpgun/main.c index ec1cf27981..09f5b0e5d3 100644 --- a/src/utils/kxdpgun/main.c +++ b/src/utils/kxdpgun/main.c @@ -301,14 +301,16 @@ void *xdp_gun_thread(void *_ctx) break; } if (ctx->tcp) { - tcprelay_dynarray_t relays = { 0 }; - ret = knot_xdp_tcp_relay(pkts, recvd, xsk, &relays); + knot_tcp_relay_t *relays = NULL; + uint32_t n_relays = 0; + ret = knot_xdp_tcp_relay(xsk, pkts, recvd, &relays, &n_relays); if (ret != KNOT_EOK) { errors++; break; } - dynarray_foreach(tcprelay, knot_tcp_relay_t, rl, relays) { + for (int irl = 0; irl < n_relays; irl++) { + knot_tcp_relay_t *rl = &relays[irl]; switch (rl->action) { case XDP_TCP_ESTABLISH: tot_synack++; @@ -331,12 +333,12 @@ void *xdp_gun_thread(void *_ctx) } } - ret = knot_xdp_tcp_send(xsk, &relays); + ret = knot_xdp_tcp_send(xsk, relays, n_relays); if (ret != KNOT_EOK) { errors++; } - tcprelay_dynarray_free(&relays); + free(relays); } else { for (int i = 0; i < recvd; i++) { (void)check_dns_payload(&pkts[i].payload, ctx, &tot_ans, &tot_size);