net: conn: Fix issues with SMP in connection code
When testing on qemu_x86_64 with e1000 Ethernet driver, there are
several crashes due to list management simultaneously executing on
different cores. Add mutexes similar to other parts on networking
stack, for example tcp_lock.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
diff --git a/subsys/net/ip/connection.c b/subsys/net/ip/connection.c
index 454543a..b370bc1 100644
--- a/subsys/net/ip/connection.c
+++ b/subsys/net/ip/connection.c
@@ -114,17 +114,24 @@
#define conn_register_debug(...)
#endif /* (CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG) */
+static K_MUTEX_DEFINE(conn_lock);
+
static struct net_conn *conn_get_unused(void)
{
sys_snode_t *node;
+ k_mutex_lock(&conn_lock, K_FOREVER);
+
node = sys_slist_peek_head(&conn_unused);
if (!node) {
+ k_mutex_unlock(&conn_lock);
return NULL;
}
sys_slist_remove(&conn_unused, NULL, node);
+ k_mutex_unlock(&conn_lock);
+
return CONTAINER_OF(node, struct net_conn, node);
}
@@ -132,14 +139,18 @@
{
conn->flags |= NET_CONN_IN_USE;
+ k_mutex_lock(&conn_lock, K_FOREVER);
sys_slist_prepend(&conn_used, &conn->node);
+ k_mutex_unlock(&conn_lock);
}
static void conn_set_unused(struct net_conn *conn)
{
(void)memset(conn, 0, sizeof(*conn));
+ k_mutex_lock(&conn_lock, K_FOREVER);
sys_slist_prepend(&conn_unused, &conn->node);
+ k_mutex_unlock(&conn_lock);
}
/* Check if we already have identical connection handler installed. */
@@ -152,6 +163,8 @@
struct net_conn *conn;
struct net_conn *tmp;
+ k_mutex_lock(&conn_lock, K_FOREVER);
+
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&conn_used, conn, tmp, node) {
if (conn->proto != proto) {
continue;
@@ -235,9 +248,11 @@
continue;
}
+ k_mutex_unlock(&conn_lock);
return conn;
}
+ k_mutex_unlock(&conn_lock);
return NULL;
}
@@ -380,7 +395,9 @@
NET_DBG("Connection handler %p removed", conn);
+ k_mutex_lock(&conn_lock, K_FOREVER);
sys_slist_find_and_remove(&conn_used, &conn->node);
+ k_mutex_unlock(&conn_lock);
conn_set_unused(conn);
@@ -824,9 +841,13 @@
{
struct net_conn *conn;
+ k_mutex_lock(&conn_lock, K_FOREVER);
+
SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) {
cb(conn, user_data);
}
+
+ k_mutex_unlock(&conn_lock);
}
void net_conn_init(void)