Commit 998b5d96 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'mpls-remove-rtnl-dependency'

Kuniyuki Iwashima says:

====================
mpls: Remove RTNL dependency.

MPLS uses RTNL

  1) to guarantee the lifetime of struct mpls_nh.nh_dev
  2) to protect net->mpls.platform_label

, but neither actually requires RTNL.

If struct mpls_nh holds a refcnt for nh_dev, we do not need RTNL,
and it can be replaced with a dedicated mutex.

The series removes RTNL from net/mpls/.

Overview:

  Patch 1 is misc cleanup.

  Patch 2 - 9 are prep to drop RTNL for RTM_{NEW,DEL,GET}ROUTE
  handlers.

  Patch 10 & 11 converts mpls_dump_routes() and RTM_GETNETCONF to RCU.

  Patch 12 replaces RTNL with a new per-netns mutex.

  Patch 13 drops RTNL from RTM_{NEW,DEL,GET}ROUTE.
====================

Link: https://patch.msgid.link/20251029173344.2934622-1-kuniyu@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 209ff7af 7d99a7c6
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -347,6 +347,11 @@ static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev)
	return rcu_dereference_rtnl(dev->ip6_ptr);
}

static inline struct inet6_dev *in6_dev_rcu(const struct net_device *dev)
{
	return rcu_dereference(dev->ip6_ptr);
}

static inline struct inet6_dev *__in6_dev_get_rtnl_net(const struct net_device *dev)
{
	return rtnl_net_dereference(dev_net(dev), dev->ip6_ptr);
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ struct netns_mpls {
	int default_ttl;
	size_t platform_labels;
	struct mpls_route __rcu * __rcu *platform_label;
	struct mutex platform_mutex;

	struct ctl_table_header *ctl;
};
+199 −122

File changed.

Preview size limit exceeded, changes collapsed.

+16 −3
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ enum mpls_payload_type {

struct mpls_nh { /* next hop label forwarding entry */
	struct net_device	*nh_dev;
	netdevice_tracker	nh_dev_tracker;

	/* nh_flags is accessed under RCU in the packet path; it is
	 * modified handling netdev events with rtnl lock held
@@ -184,9 +185,20 @@ static inline struct mpls_entry_decoded mpls_entry_decode(struct mpls_shim_hdr *
	return result;
}

static inline struct mpls_dev *mpls_dev_get(const struct net_device *dev)
#define mpls_dereference(net, p)					\
	rcu_dereference_protected(					\
		(p),							\
		lockdep_is_held(&(net)->mpls.platform_mutex))

static inline struct mpls_dev *mpls_dev_rcu(const struct net_device *dev)
{
	return rcu_dereference(dev->mpls_ptr);
}

static inline struct mpls_dev *mpls_dev_get(const struct net *net,
					    const struct net_device *dev)
{
	return rcu_dereference_rtnl(dev->mpls_ptr);
	return mpls_dereference(net, dev->mpls_ptr);
}

int nla_put_labels(struct sk_buff *skb, int attrtype,  u8 labels,
@@ -196,7 +208,8 @@ int nla_get_labels(const struct nlattr *nla, u8 max_labels, u8 *labels,
bool mpls_output_possible(const struct net_device *dev);
unsigned int mpls_dev_mtu(const struct net_device *dev);
bool mpls_pkt_too_big(const struct sk_buff *skb, unsigned int mtu);
void mpls_stats_inc_outucastpkts(struct net_device *dev,
void mpls_stats_inc_outucastpkts(struct net *net,
				 struct net_device *dev,
				 const struct sk_buff *skb);

#endif /* MPLS_INTERNAL_H */
+3 −3
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ static int mpls_xmit(struct sk_buff *skb)

	/* Find the output device */
	out_dev = dst->dev;
	net = dev_net(out_dev);
	net = dev_net_rcu(out_dev);

	if (!mpls_output_possible(out_dev) ||
	    !dst->lwtstate || skb_warn_if_lro(skb))
@@ -128,7 +128,7 @@ static int mpls_xmit(struct sk_buff *skb)
		bos = false;
	}

	mpls_stats_inc_outucastpkts(out_dev, skb);
	mpls_stats_inc_outucastpkts(net, out_dev, skb);

	if (rt) {
		if (rt->rt_gw_family == AF_INET6)
@@ -153,7 +153,7 @@ static int mpls_xmit(struct sk_buff *skb)
	return LWTUNNEL_XMIT_DONE;

drop:
	out_mdev = out_dev ? mpls_dev_get(out_dev) : NULL;
	out_mdev = out_dev ? mpls_dev_rcu(out_dev) : NULL;
	if (out_mdev)
		MPLS_INC_STATS(out_mdev, tx_errors);
	kfree_skb(skb);