[PATCH net-next] openvswitch: enable ops lock for internal ports
From: Wang Zhan <hidden>
Date: 2026-08-12 12:31:28
Also in:
lkml
Subsystem:
networking [general], openvswitch, the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Aaron Conole, Eelco Chaudron, Ilya Maximets, Linus Torvalds
Open vSwitch internal ports currently use RTNL as their ops compatibility lock. Opt them in to netdev instance locking so eligible control operations can be serialized per device instead of contending on the global RTNL lock. The internal port ethtool operations implement get_drvinfo and get_link. The latter uses ethtool_op_get_link(), which synchronizes linkwatch state and requires RTNL. Allow get_drvinfo to run under the instance lock, but set ETHTOOL_OP_NEEDS_RTNL_GLINK to retain RTNL for get_link. Feature synchronization can acquire a lower device's ops lock while holding an internal port's lock. Assign these software upper devices a distinct lockdep class to describe the nesting. Signed-off-by: Wang Zhan <redacted> --- net/openvswitch/vport-internal_dev.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 125d310871e93..eb2e83a3e16f1 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c@@ -11,6 +11,7 @@ #include <linux/skbuff.h> #include <net/dst.h> +#include <net/netdev_lock.h> #include <net/xfrm.h> #include <net/rtnetlink.h>
@@ -29,6 +30,12 @@ static struct internal_dev *internal_dev_priv(struct net_device *netdev) return netdev_priv(netdev); } +static int internal_dev_init(struct net_device *netdev) +{ + netdev_lockdep_set_classes(netdev); + return 0; +} + /* Called with rcu_read_lock_bh. */ static netdev_tx_t internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
@@ -69,6 +76,7 @@ static void internal_dev_getinfo(struct net_device *netdev, } static const struct ethtool_ops internal_dev_ethtool_ops = { + .op_needs_rtnl = ETHTOOL_OP_NEEDS_RTNL_GLINK, .get_drvinfo = internal_dev_getinfo, .get_link = ethtool_op_get_link, };
@@ -81,6 +89,7 @@ static void internal_dev_destructor(struct net_device *dev) } static const struct net_device_ops internal_dev_netdev_ops = { + .ndo_init = internal_dev_init, .ndo_open = internal_dev_open, .ndo_stop = internal_dev_stop, .ndo_start_xmit = internal_dev_xmit,
@@ -106,6 +115,7 @@ static void do_setup(struct net_device *netdev) netdev->needs_free_netdev = true; netdev->priv_destructor = NULL; netdev->ethtool_ops = &internal_dev_ethtool_ops; + netdev->request_ops_lock = true; netdev->rtnl_link_ops = &internal_dev_link_ops; netdev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
base-commit: ac155a26750a595703e7dadff84735456d75a479 -- 2.47.3