Commit 03df156d authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

xdp: double protect netdev->xdp_flags with netdev->lock



Protect xdp_features with netdev->lock. This way pure readers
no longer have to take rtnl_lock to access the field.

This includes calling NETDEV_XDP_FEAT_CHANGE under the lock.
Looks like that's fine for bonding, the only "real" listener,
it's the same as ethtool feature change.

In terms of normal drivers - only GVE need special consideration
(other drivers don't use instance lock or don't support XDP).
It calls xdp_set_features_flag() helper from gve_init_priv() which
in turn is called from gve_reset_recovery() (locked), or prior
to netdev registration. So switch to _locked.

Reviewed-by: default avatarJoe Damato <jdamato@fastly.com>
Acked-by: default avatarStanislav Fomichev <sdf@fomichev.me>
Acked-by: default avatarHarshitha Ramamurthy <hramamurthy@google.com>
Acked-by: default avatarMartin KaFai Lau <martin.lau@kernel.org>
Link: https://patch.msgid.link/20250408195956.412733-6-kuba@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent d02e3b38
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -354,6 +354,7 @@ For devices with locked ops, currently only the following notifiers are
running under the lock:
* ``NETDEV_REGISTER``
* ``NETDEV_UP``
* ``NETDEV_XDP_FEAT_CHANGE``

The following notifiers are running without the lock:
* ``NETDEV_UNREGISTER``
+1 −1
Original line number Diff line number Diff line
@@ -2185,7 +2185,7 @@ static void gve_set_netdev_xdp_features(struct gve_priv *priv)
		xdp_features = 0;
	}

	xdp_set_features_flag(priv->dev, xdp_features);
	xdp_set_features_flag_locked(priv->dev, xdp_features);
}

static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
+1 −1
Original line number Diff line number Diff line
@@ -2526,7 +2526,7 @@ struct net_device {
	 *	@net_shaper_hierarchy, @reg_state, @threaded
	 *
	 * Double protects:
	 *	@up, @moving_ns, @nd_net
	 *	@up, @moving_ns, @nd_net, @xdp_flags
	 *
	 * Double ops protects:
	 *	@real_num_rx_queues, @real_num_tx_queues
+1 −0
Original line number Diff line number Diff line
@@ -616,6 +616,7 @@ struct xdp_metadata_ops {
u32 bpf_xdp_metadata_kfunc_id(int id);
bool bpf_dev_bound_kfunc_id(u32 btf_id);
void xdp_set_features_flag(struct net_device *dev, xdp_features_t val);
void xdp_set_features_flag_locked(struct net_device *dev, xdp_features_t val);
void xdp_features_set_redirect_target(struct net_device *dev, bool support_sg);
void xdp_features_clear_redirect_target(struct net_device *dev);
#else
+1 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ int netdev_debug_event(struct notifier_block *nb, unsigned long event,
	switch (cmd) {
	case NETDEV_REGISTER:
	case NETDEV_UP:
	case NETDEV_XDP_FEAT_CHANGE:
		netdev_ops_assert_locked(dev);
		fallthrough;
	case NETDEV_DOWN:
@@ -58,7 +59,6 @@ int netdev_debug_event(struct notifier_block *nb, unsigned long event,
	case NETDEV_OFFLOAD_XSTATS_DISABLE:
	case NETDEV_OFFLOAD_XSTATS_REPORT_USED:
	case NETDEV_OFFLOAD_XSTATS_REPORT_DELTA:
	case NETDEV_XDP_FEAT_CHANGE:
		ASSERT_RTNL();
		break;

Loading