net/tcp: remove SYN_RCVD state conn by listener created when free listener

after the listener fd is closed, the half-open connections associated
with the listener are not reclaimed. According to the protocol standard,
they should be reclaimed in a timely manner.

Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
This commit is contained in:
zhanghongyu
2025-09-11 11:40:40 +08:00
committed by Xiang Xiao
parent 93cba3da64
commit 0588d08d75
3 changed files with 52 additions and 0 deletions
+11
View File
@@ -712,6 +712,17 @@ int tcp_connect(FAR struct tcp_conn_s *conn,
void tcp_removeconn(FAR struct tcp_conn_s *conn);
/****************************************************************************
* Name: tcp_remove_syn_backlog
*
* Description:
* This function is used to remove the currently SYN_RCVD connection
* created by the listener
*
****************************************************************************/
void tcp_remove_syn_backlog(FAR struct tcp_conn_s *listener);
/****************************************************************************
* Name: tcp_conn_list_lock
*
+40
View File
@@ -1539,4 +1539,44 @@ void tcp_removeconn(FAR struct tcp_conn_s *conn)
dq_rem(&conn->sconn.node, &g_active_tcp_connections);
}
/****************************************************************************
* Name: tcp_remove_syn_backlog
*
* Description:
* This function is used to remove the currently SYN_RCVD connection
* created by the listener
*
* Assumptions:
* This function is called from network logic with the tcp conn list
* locked.
*
****************************************************************************/
void tcp_remove_syn_backlog(FAR struct tcp_conn_s *listener)
{
FAR struct tcp_conn_s *conn;
FAR struct tcp_conn_s *next;
next = (FAR struct tcp_conn_s *)g_active_tcp_connections.head;
while (next)
{
conn = next;
next = (FAR struct tcp_conn_s *)conn->sconn.node.flink;
if (conn->tcpstateflags == TCP_SYN_RCVD &&
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
tcp_conn_cmp(listener->domain,
(FAR const union ip_addr_u *)&listener->u,
listener->lport, conn)
#else
tcp_conn_cmp((FAR const union ip_addr_u *)&listener->u,
listener->lport, conn)
#endif
)
{
conn->crefs = 0;
tcp_free(conn);
}
}
}
#endif /* CONFIG_NET && CONFIG_NET_TCP */
+1
View File
@@ -145,6 +145,7 @@ int tcp_unlisten(FAR struct tcp_conn_s *conn)
if (tcp_listenports[ndx] == conn)
{
tcp_listenports[ndx] = NULL;
tcp_remove_syn_backlog(conn);
ret = OK;
break;
}