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;