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>
This commit is contained in:
Andrei Emeltchenko 2022-11-22 18:12:15 +02:00 committed by Carles Cufí
commit a5400407fc

View file

@ -114,17 +114,24 @@ void conn_register_debug(struct net_conn *conn,
#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 @@ static void conn_set_used(struct net_conn *conn)
{
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 @@ static struct net_conn *conn_find_handler(uint16_t proto, uint8_t family,
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 @@ static struct net_conn *conn_find_handler(uint16_t proto, uint8_t family,
continue;
}
k_mutex_unlock(&conn_lock);
return conn;
}
k_mutex_unlock(&conn_lock);
return NULL;
}
@ -380,7 +395,9 @@ int net_conn_unregister(struct net_conn_handle *handle)
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 @@ void net_conn_foreach(net_conn_foreach_cb_t cb, void *user_data)
{
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)