From 5289903690e941a964d9f8ac221b758acbbf9136 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Wed, 4 Feb 2026 10:10:37 +0100 Subject: [PATCH] knet_manager: fix deadlock on port creation When creating ports in knet_manager::create_portdev(), they are created with tn_mutex held, and calls knet_manager::change_port_status() to set the initial config to down. Since commit cefce264a657 ("knet_manager: do not try to set state for non-existing links"), knet_manager::change_port_status() also takes the mutex, leading to a deadlock on port creation. Fix this by providing a non-locking variant of knet_manager::change_port_status() to use by knet_manager::create_portdev(). Fixes: cefce264a657 ("knet_manager: do not try to set state for non-existing links") Signed-off-by: Jonas Gorski --- src/netlink/knet_manager.cc | 25 +++++++++++++++---------- src/netlink/knet_manager.h | 2 ++ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/netlink/knet_manager.cc b/src/netlink/knet_manager.cc index 76a203a6..9180c5ea 100644 --- a/src/netlink/knet_manager.cc +++ b/src/netlink/knet_manager.cc @@ -86,7 +86,7 @@ int knet_manager::create_portdev(uint32_t port_id, const std::string &port_name, if (r != 0) LOG(FATAL) << __FUNCTION__ << ": failed to create knet netif for port_id " << port_id; - change_port_status(port_name, false); + change_port_status_unlocked(port_name, false); } } catch (std::exception &e) { @@ -231,6 +231,19 @@ bool knet_manager::portdev_removed(rtnl_link *link) { return true; } +int knet_manager::change_port_status_unlocked(const std::string name, + bool status) { + std::ofstream file("/proc/bcm/knet/link"); + + if (file.is_open()) { + file << (name + "=" + (status ? "up" : "down")); + file.close(); + return 0; + } + + return 1; +} + /* * set netif link state according to open flow link state * Status is determined via the portstatus/port_desc_reply message @@ -249,15 +262,7 @@ int knet_manager::change_port_status(const std::string name, bool status) { } } - std::ofstream file("/proc/bcm/knet/link"); - - if (file.is_open()) { - file << (name + "=" + (status ? "up" : "down")); - file.close(); - return 0; - } - - return 1; + return change_port_status_unlocked(name, status); } /* diff --git a/src/netlink/knet_manager.h b/src/netlink/knet_manager.h index 878436e0..ecc43132 100644 --- a/src/netlink/knet_manager.h +++ b/src/netlink/knet_manager.h @@ -47,6 +47,8 @@ class knet_manager final : public port_manager { knet_manager(const knet_manager &other) = delete; // non construction-copyable knet_manager &operator=(const knet_manager &) = delete; // non copyable + int change_port_status_unlocked(const std::string name, bool status); + std::bitset<128> netif_ids_in_use; int get_next_netif_id();