From e3b8fad9faa52e9b8a7ca48ef38afbf8ecd42f98 Mon Sep 17 00:00:00 2001 From: Sjors Hettinga Date: Tue, 7 Jun 2022 07:58:11 +0200 Subject: [PATCH] net: tcp: Fix accidental removal of data from send_data In the function net_tcp_queue_data. When an -ENOBUFS by tcp_send_queued_data is returned, it throws away the whole block of size len from the send_data. If the len is > MSS, it could happen that the first section is transmitted, but at the second an -ENOBUFS occurs. In that case the data is transmitted, but later on removed from the send_data. To circumvent this problem, check if the len + unacked_len is smaller then the send_data_total. If so, the data can safely be removed from send_data. Otherwise, just pretend the transmission went OK. The acknowledgment and retransmit path will eventually take care of it. Signed-off-by: Sjors Hettinga --- subsys/net/ip/tcp.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index a073edd3de0..ce854b651a6 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -2351,6 +2351,19 @@ int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt) goto out; } + if ((ret == -ENOBUFS) && + (conn->send_data_total < (conn->unacked_len + len))) { + /* Some of the data has been sent, we cannot remove the + * whole chunk, the remainder portion is already + * in the send_data and will be transmitted upon a + * received ack or the next send call + * + * Set the return code back to 0 to pretend we just + * transmitted the chunk + */ + ret = 0; + } + if (ret == -ENOBUFS) { /* Restore the original data so that we do not resend the pkt * data multiple times.