Commit 7945fe48 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-add-data-race-annotations-around-dst-fields'

Eric Dumazet says:

====================
net: add data-race annotations around dst fields

Add annotations around various dst fields, which can change under us.

Add four helpers to prepare better dst->dev protection,
and start using them. More to come later.

v1: https://lore.kernel.org/20250627112526.3615031-1-edumazet@google.com
====================

Link: https://patch.msgid.link/20250630121934.3399505-1-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 8077b9a9 46a94e44
Loading
Loading
Loading
Loading
+30 −8
Original line number Diff line number Diff line
@@ -240,9 +240,9 @@ static inline void dst_hold(struct dst_entry *dst)

static inline void dst_use_noref(struct dst_entry *dst, unsigned long time)
{
	if (unlikely(time != dst->lastuse)) {
	if (unlikely(time != READ_ONCE(dst->lastuse))) {
		dst->__use++;
		dst->lastuse = time;
		WRITE_ONCE(dst->lastuse, time);
	}
}

@@ -431,13 +431,15 @@ static inline void dst_link_failure(struct sk_buff *skb)

static inline void dst_set_expires(struct dst_entry *dst, int timeout)
{
	unsigned long expires = jiffies + timeout;
	unsigned long old, expires = jiffies + timeout;

	if (expires == 0)
		expires = 1;

	if (dst->expires == 0 || time_before(expires, dst->expires))
		dst->expires = expires;
	old = READ_ONCE(dst->expires);

	if (!old || time_before(expires, old))
		WRITE_ONCE(dst->expires, expires);
}

static inline unsigned int dst_dev_overhead(struct dst_entry *dst,
@@ -456,7 +458,7 @@ INDIRECT_CALLABLE_DECLARE(int ip_output(struct net *, struct sock *,
/* Output packet to network from transport.  */
static inline int dst_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
	return INDIRECT_CALL_INET(skb_dst(skb)->output,
	return INDIRECT_CALL_INET(READ_ONCE(skb_dst(skb)->output),
				  ip6_output, ip_output,
				  net, sk, skb);
}
@@ -466,7 +468,7 @@ INDIRECT_CALLABLE_DECLARE(int ip_local_deliver(struct sk_buff *));
/* Input packet from network to transport.  */
static inline int dst_input(struct sk_buff *skb)
{
	return INDIRECT_CALL_INET(skb_dst(skb)->input,
	return INDIRECT_CALL_INET(READ_ONCE(skb_dst(skb)->input),
				  ip6_input, ip_local_deliver, skb);
}

@@ -476,7 +478,7 @@ INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *,
							   u32));
static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie)
{
	if (dst->obsolete)
	if (READ_ONCE(dst->obsolete))
		dst = INDIRECT_CALL_INET(dst->ops->check, ip6_dst_check,
					 ipv4_dst_check, dst, cookie);
	return dst;
@@ -561,6 +563,26 @@ static inline void skb_dst_update_pmtu_no_confirm(struct sk_buff *skb, u32 mtu)
		dst->ops->update_pmtu(dst, NULL, skb, mtu, false);
}

static inline struct net_device *dst_dev(const struct dst_entry *dst)
{
	return READ_ONCE(dst->dev);
}

static inline struct net_device *skb_dst_dev(const struct sk_buff *skb)
{
	return dst_dev(skb_dst(skb));
}

static inline struct net *skb_dst_dev_net(const struct sk_buff *skb)
{
	return dev_net(skb_dst_dev(skb));
}

static inline struct net *skb_dst_dev_net_rcu(const struct sk_buff *skb)
{
	return dev_net_rcu(skb_dst_dev(skb));
}

struct dst_entry *dst_blackhole_check(struct dst_entry *dst, u32 cookie);
void dst_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk,
			       struct sk_buff *skb, u32 mtu, bool confirm_neigh);
+1 −1
Original line number Diff line number Diff line
@@ -150,7 +150,7 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
					      int iif, int sdif,
					      bool *refcounted)
{
	struct net *net = dev_net_rcu(skb_dst(skb)->dev);
	struct net *net = skb_dst_dev_net_rcu(skb);
	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
	struct sock *sk;

+1 −1
Original line number Diff line number Diff line
@@ -481,7 +481,7 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
					     const int sdif,
					     bool *refcounted)
{
	struct net *net = dev_net_rcu(skb_dst(skb)->dev);
	struct net *net = skb_dst_dev_net_rcu(skb);
	const struct iphdr *iph = ip_hdr(skb);
	struct sock *sk;

+7 −6
Original line number Diff line number Diff line
@@ -472,12 +472,12 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,

	rcu_read_lock();

	net = dev_net_rcu(dst->dev);
	net = dev_net_rcu(dst_dev(dst));
	if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) ||
	    ip_mtu_locked(dst) ||
	    !forwarding) {
		mtu = rt->rt_pmtu;
		if (mtu && time_before(jiffies, rt->dst.expires))
		if (mtu && time_before(jiffies, READ_ONCE(rt->dst.expires)))
			goto out;
	}

@@ -486,7 +486,7 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
	if (mtu)
		goto out;

	mtu = READ_ONCE(dst->dev->mtu);
	mtu = READ_ONCE(dst_dev(dst)->mtu);

	if (unlikely(ip_mtu_locked(dst))) {
		if (rt->rt_uses_gateway && mtu > 576)
@@ -506,16 +506,17 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
					  const struct sk_buff *skb)
{
	const struct dst_entry *dst = skb_dst(skb);
	unsigned int mtu;

	if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) {
		bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;

		return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
		return ip_dst_mtu_maybe_forward(dst, forwarding);
	}

	mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
	return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
	mtu = min(READ_ONCE(dst_dev(dst)->mtu), IP_MAX_MTU);
	return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
}

struct dst_metrics *ip_fib_metrics_init(struct nlattr *fc_mx, int fc_mx_len,
+2 −2
Original line number Diff line number Diff line
@@ -274,7 +274,7 @@ static inline unsigned int ip6_skb_dst_mtu(const struct sk_buff *skb)
	unsigned int mtu;

	if (np && READ_ONCE(np->pmtudisc) >= IPV6_PMTUDISC_PROBE) {
		mtu = READ_ONCE(dst->dev->mtu);
		mtu = READ_ONCE(dst_dev(dst)->mtu);
		mtu -= lwtunnel_headroom(dst->lwtstate, mtu);
	} else {
		mtu = dst_mtu(dst);
@@ -337,7 +337,7 @@ static inline unsigned int ip6_dst_mtu_maybe_forward(const struct dst_entry *dst

	mtu = IPV6_MIN_MTU;
	rcu_read_lock();
	idev = __in6_dev_get(dst->dev);
	idev = __in6_dev_get(dst_dev(dst));
	if (idev)
		mtu = READ_ONCE(idev->cnf.mtu6);
	rcu_read_unlock();
Loading