From 6c4a515a58f893272dd9df50311825b6f1840a95 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 10 Oct 2019 15:38:46 +0300 Subject: [PATCH] net: tcp: When closing the connection send FIN without extra delays The earlier code was always queuing the FIN that is sent when connection is closed. This caused long delay (200 ms) before the peer at the other end noticed that the connection was actually closed. Now check if there is nothing in the queue, then send the FIN immediately. If there is some data in the queue, flush it when a valid ack has been received. Fixes #19678 Signed-off-by: Jukka Rissanen --- subsys/net/ip/tcp.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 842027f66e54..1ad31c2b6d2a 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -972,6 +972,11 @@ int net_tcp_send_pkt(struct net_pkt *pkt) return net_send_data(pkt); } +static void flush_queue(struct net_context *context) +{ + (void)net_tcp_send_data(context, NULL, NULL); +} + static void restart_timer(struct net_tcp *tcp) { if (!sys_slist_is_empty(&tcp->sent_list)) { @@ -1134,6 +1139,11 @@ bool net_tcp_ack_received(struct net_context *ctx, u32_t ack) */ if (valid_ack) { restart_timer(ctx->tcp); + + /* Flush anything pending. This is important as if there + * is FIN waiting in the queue, it gets sent asap. + */ + flush_queue(ctx); } return true; @@ -1377,6 +1387,7 @@ int net_tcp_recv(struct net_context *context, net_context_recv_cb_t cb, static void queue_fin(struct net_context *ctx) { struct net_pkt *pkt = NULL; + bool flush = false; int ret; ret = net_tcp_prepare_segment(ctx->tcp, NET_TCP_FIN, NULL, 0, @@ -1385,7 +1396,15 @@ static void queue_fin(struct net_context *ctx) return; } + if (sys_slist_is_empty(&ctx->tcp->sent_list)) { + flush = true; + } + net_tcp_queue_pkt(ctx, pkt); + + if (flush) { + flush_queue(ctx); + } } int net_tcp_put(struct net_context *context)