Skip to content

Commit ec3bcd3

Browse files
jukkarcfriedt
authored andcommitted
net: tcp: Close all connections when interface goes down
If the network interface goes down, close all TCP connections that are bound to that interface. The reasoning here is that we need a way to remove IP address from the interface and it might not be possible if there is a TCP socket that is bound to that address. If the interface comes back on, we might get the same IP address in which case the socket closure was not really needed but it is not possible to know in advance. Signed-off-by: Jukka Rissanen <[email protected]>
1 parent 1f5c285 commit ec3bcd3

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

subsys/net/ip/net_if.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ LOG_MODULE_REGISTER(net_if, CONFIG_NET_IF_LOG_LEVEL);
3636
#include "net_private.h"
3737
#include "ipv4.h"
3838
#include "ipv6.h"
39+
#include "tcp_internal.h"
3940

4041
#include "net_stats.h"
4142

@@ -5761,6 +5762,7 @@ static void notify_iface_up(struct net_if *iface)
57615762

57625763
static void notify_iface_down(struct net_if *iface)
57635764
{
5765+
net_tcp_close_all_for_iface(iface);
57645766
net_if_flag_clear(iface, NET_IF_RUNNING);
57655767
net_mgmt_event_notify(NET_EVENT_IF_DOWN, iface);
57665768
net_virtual_disable(iface);

subsys/net/ip/tcp.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4751,6 +4751,28 @@ struct k_sem *net_tcp_conn_sem_get(struct net_context *context)
47514751
return &conn->connect_sem;
47524752
}
47534753

4754+
static void close_tcp_conn(struct tcp *conn, void *user_data)
4755+
{
4756+
struct net_if *iface = user_data;
4757+
struct net_context *context = conn->context;
4758+
4759+
if (!net_context_is_used(context)) {
4760+
return;
4761+
}
4762+
4763+
if (net_context_get_iface(context) != iface) {
4764+
return;
4765+
}
4766+
4767+
/* net_tcp_put() will handle decrementing refcount on stack's behalf */
4768+
net_tcp_put(context, true);
4769+
}
4770+
4771+
void net_tcp_close_all_for_iface(struct net_if *iface)
4772+
{
4773+
net_tcp_foreach(close_tcp_conn, iface);
4774+
}
4775+
47544776
void net_tcp_init(void)
47554777
{
47564778
int i;

subsys/net/ip/tcp_internal.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,24 @@ static inline void net_tcp_conn_accepted(struct net_context *child_ctx)
494494
}
495495
#endif
496496

497+
/**
498+
* @brief Close and unref all TCP context bound to an network interface.
499+
*
500+
* @details This releases all the TCP contexts that are bound to a specific
501+
* network interface. It is not possible to send or receive data via those
502+
* contexts after this call.
503+
*
504+
* @param iface The network interface to use to find out the bound contexts.
505+
*/
506+
#if defined(CONFIG_NET_NATIVE_TCP)
507+
void net_tcp_close_all_for_iface(struct net_if *iface);
508+
#else
509+
static inline void net_tcp_close_all_for_iface(struct net_if *iface)
510+
{
511+
ARG_UNUSED(iface);
512+
}
513+
#endif
514+
497515
#ifdef __cplusplus
498516
}
499517
#endif

0 commit comments

Comments
 (0)