diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index 6b77ad8c173..5c8c0fd9733 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -1173,11 +1173,21 @@ int net_context_connect(struct net_context *context, #define ACK_TIMEOUT MSEC_PER_SEC +static void ack_timer_cancel(struct net_tcp *tcp) +{ + tcp->ack_timer_cancelled = true; + k_delayed_work_cancel(&tcp->ack_timer); +} + static void ack_timeout(struct k_work *work) { /* This means that we did not receive ACK response in time. */ struct net_tcp *tcp = CONTAINER_OF(work, struct net_tcp, ack_timer); + if (tcp->ack_timer_cancelled) { + return; + } + NET_DBG("Did not receive ACK in %dms", ACK_TIMEOUT); send_reset(tcp->context, &tcp->context->remote); @@ -1281,10 +1291,13 @@ NET_CONN_CB(tcp_syn_rcvd) * if the SYN is sent more than once. So we need to cancel * any pending timers. */ - k_delayed_work_cancel(&tcp->ack_timer); + ack_timer_cancel(tcp); + k_delayed_work_init(&tcp->ack_timer, ack_timeout); k_delayed_work_submit(&tcp->ack_timer, ACK_TIMEOUT); + tcp->ack_timer_cancelled = false; + return NET_DROP; } @@ -1292,7 +1305,7 @@ NET_CONN_CB(tcp_syn_rcvd) * If we receive RST, we go back to LISTEN state. */ if (NET_TCP_FLAGS(pkt) == NET_TCP_RST) { - k_delayed_work_cancel(&tcp->ack_timer); + ack_timer_cancel(tcp); net_tcp_print_recv_info("RST", pkt, NET_TCP_HDR(pkt)->src_port); @@ -1316,7 +1329,7 @@ NET_CONN_CB(tcp_syn_rcvd) * So if we are not in SYN_RCVD state, then it is an error. */ if (net_tcp_get_state(tcp) != NET_TCP_SYN_RCVD) { - k_delayed_work_cancel(&tcp->ack_timer); + ack_timer_cancel(tcp); NET_DBG("Not in SYN_RCVD state, sending RST"); goto reset; } @@ -1438,7 +1451,7 @@ NET_CONN_CB(tcp_syn_rcvd) net_tcp_change_state(new_context->tcp, NET_TCP_ESTABLISHED); net_context_set_state(new_context, NET_CONTEXT_CONNECTED); - k_delayed_work_cancel(&tcp->ack_timer); + ack_timer_cancel(tcp); context->tcp->accept_cb(new_context, &new_context->remote, diff --git a/subsys/net/ip/tcp.h b/subsys/net/ip/tcp.h index f63dfdf4bb9..a4201db8fab 100644 --- a/subsys/net/ip/tcp.h +++ b/subsys/net/ip/tcp.h @@ -134,8 +134,13 @@ struct net_tcp { uint32_t fin_sent : 1; /* An inbound FIN packet has been received */ uint32_t fin_rcvd : 1; + /* Tells if ack timer has been already cancelled. It might happen + * that the timer is executed even if it is cancelled, this is because + * of various timing issues when timer is scheduled to run. + */ + uint32_t ack_timer_cancelled : 1; /** Remaining bits in this uint32_t */ - uint32_t _padding : 12; + uint32_t _padding : 11; /** Accept callback to be called when the connection has been * established.