]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
xdp/tcp: avoid dynarray in favour of resizeable array
authorLibor Peltan <libor.peltan@nic.cz>
Tue, 22 Dec 2020 15:12:09 +0000 (16:12 +0100)
committerDaniel Salzman <daniel.salzman@nic.cz>
Fri, 29 Jan 2021 08:46:57 +0000 (09:46 +0100)
src/libknot/xdp/tcp.c
src/libknot/xdp/tcp.h
src/utils/kxdpgun/main.c

index c7ec424950d7af4e44bcc9dd8a7c692134467f3c..9f34996363623f09e837d9b52f55e92bff46a0dd 100644 (file)
 #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;
                }
index fcb37bc798d9159f640dfdd6a10495054cd50e9a..ca8372374c79781fc026fcabd706d209d0255fed 100644 (file)
@@ -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);
index ec1cf27981fb417d3bffba2bca52eb0f6575dd23..09f5b0e5d3c103c44ef7818215c0cca92224308a 100644 (file)
@@ -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);