net: tcp: Preallocate TX packet for TCP context
TCP context cannot operate w/o a TX packet for buffering transmitted
data. So far this net_pkt was allocated at runtime from the common
packet pool, but this created some not-obvious memory requirement on TCP
and could lead to TX packet starvation in case many TCP connections are
open in parallel. Therefore, allocate this packet structure statically,
as a part of the TCP context instead.
This increases the memory requirement of the TCP context by ~64 bytes,
however if that's a concern for the application, the maximum number of
TX packets can be lowered instead. In return, we get a clear separation
between the number of TCP connections opened, and the amount of packets
that can be transmitted.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
(cherry picked from commit eda76ad21b1748725c6d590204ee25d88caa9a82)
diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c
index 607b4a3..7525208 100644
--- a/subsys/net/ip/tcp.c
+++ b/subsys/net/ip/tcp.c
@@ -794,7 +794,9 @@
tcp_send_queue_flush(conn);
(void)k_work_cancel_delayable(&conn->send_data_timer);
- tcp_pkt_unref(conn->send_data);
+ if (conn->send_data.frags != NULL) {
+ net_pkt_frag_unref(conn->send_data.frags);
+ }
if (CONFIG_NET_TCP_RECV_QUEUE_TIMEOUT) {
if (conn->queue_recv_data != NULL) {
@@ -1686,7 +1688,7 @@
goto out;
}
- ret = tcp_pkt_peek(pkt, conn->send_data, conn->unacked_len, len);
+ ret = tcp_pkt_peek(pkt, &conn->send_data, conn->unacked_len, len);
if (ret < 0) {
tcp_pkt_unref(pkt);
ret = -ENOBUFS;
@@ -2023,12 +2025,7 @@
}
memset(conn, 0, sizeof(*conn));
-
- conn->send_data = tcp_pkt_alloc(conn, 0);
- if (conn->send_data == NULL) {
- NET_ERR("Cannot allocate %s queue for conn %p", "send", conn);
- goto fail;
- }
+ net_pkt_tx_init(&conn->send_data);
k_mutex_init(&conn->lock);
k_fifo_init(&conn->recv_data);
@@ -2080,10 +2077,6 @@
NET_DBG("conn: %p", conn);
return conn;
-
-fail:
- k_mem_slab_free(&tcp_conns_slab, (void *)conn);
- return NULL;
}
int net_tcp_get(struct net_context *context)
@@ -3153,7 +3146,7 @@
NET_DBG("conn: %p len_acked=%u", conn, len_acked);
if ((conn->send_data_total < len_acked) ||
- (tcp_pkt_pull(conn->send_data,
+ (tcp_pkt_pull(&conn->send_data,
len_acked) < 0)) {
NET_ERR("conn: %p, Invalid len_acked=%u "
"(total=%zu)", conn, len_acked,
@@ -3642,7 +3635,7 @@
for (int i = 0; i < msg->msg_iovlen; i++) {
int iovlen = MIN(msg->msg_iov[i].iov_len, len);
- ret = tcp_pkt_append(conn->send_data,
+ ret = tcp_pkt_append(&conn->send_data,
msg->msg_iov[i].iov_base,
iovlen);
if (ret < 0) {
@@ -3661,7 +3654,7 @@
}
}
} else {
- ret = tcp_pkt_append(conn->send_data, data, len);
+ ret = tcp_pkt_append(&conn->send_data, data, len);
if (ret < 0) {
goto out;
}
diff --git a/subsys/net/ip/tcp_private.h b/subsys/net/ip/tcp_private.h
index 466910f..9040252 100644
--- a/subsys/net/ip/tcp_private.h
+++ b/subsys/net/ip/tcp_private.h
@@ -149,7 +149,7 @@
({ \
NET_DBG("conn: %p total=%zd, unacked_len=%d, " \
"send_win=%hu, mss=%hu", \
- (_conn), net_pkt_get_len((_conn)->send_data), \
+ (_conn), net_pkt_get_len(&(_conn)->send_data), \
_conn->unacked_len, _conn->send_win, \
(uint16_t)conn_mss((_conn))); \
NET_DBG("conn: %p send_data_timer=%hu, send_data_retries=%hu", \
@@ -258,7 +258,7 @@
struct tcp { /* TCP connection */
sys_snode_t next;
struct net_context *context;
- struct net_pkt *send_data;
+ struct net_pkt send_data;
struct net_buf *queue_recv_data;
struct net_if *iface;
void *recv_user_data;