]> www.infradead.org Git - users/hch/misc.git/commitdiff
ipv6: start using dst_dev_rcu()
authorEric Dumazet <edumazet@google.com>
Thu, 28 Aug 2025 19:58:17 +0000 (19:58 +0000)
committerJakub Kicinski <kuba@kernel.org>
Sat, 30 Aug 2025 02:36:32 +0000 (19:36 -0700)
Refactor icmpv6_xrlim_allow() and ip6_dst_hoplimit()
so that we acquire rcu_read_lock() a bit longer
to be able to use dst_dev_rcu() instead of dst_dev().

__ip6_rt_update_pmtu() and rt6_do_redirect can directly
use dst_dev_rcu() in sections already holding rcu_read_lock().

Small changes to use dst_dev_net_rcu() in
ip6_default_advmss(), ipv6_sock_ac_join(),
ip6_mc_find_dev() and ndisc_send_skb().

Fixes: 4a6ce2b6f2ec ("net: introduce a new function dst_dev_put()")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20250828195823.3958522-3-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv6/anycast.c
net/ipv6/icmp.c
net/ipv6/mcast.c
net/ipv6/ndisc.c
net/ipv6/output_core.c
net/ipv6/route.c

index f8a8e46286b8ee6e39d2d4c2e4149d528d7aef18..52599584422bf4168e37ea48b575c058b1309c7c 100644 (file)
@@ -104,7 +104,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
                rcu_read_lock();
                rt = rt6_lookup(net, addr, NULL, 0, NULL, 0);
                if (rt) {
-                       dev = dst_dev(&rt->dst);
+                       dev = dst_dev_rcu(&rt->dst);
                        netdev_hold(dev, &dev_tracker, GFP_ATOMIC);
                        ip6_rt_put(rt);
                } else if (ishost) {
index 44550957fd4e360d78e6cb411c33d6bbf2359e1f..95cdd4cacb004fd4f2e569136a313afef3b25c58 100644 (file)
@@ -209,7 +209,8 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
         * this lookup should be more aggressive (not longer than timeout).
         */
        dst = ip6_route_output(net, sk, fl6);
-       dev = dst_dev(dst);
+       rcu_read_lock();
+       dev = dst_dev_rcu(dst);
        if (dst->error) {
                IP6_INC_STATS(net, ip6_dst_idev(dst),
                              IPSTATS_MIB_OUTNOROUTES);
@@ -224,11 +225,10 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
                if (rt->rt6i_dst.plen < 128)
                        tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
 
-               rcu_read_lock();
                peer = inet_getpeer_v6(net->ipv6.peers, &fl6->daddr);
                res = inet_peer_xrlim_allow(peer, tmo);
-               rcu_read_unlock();
        }
+       rcu_read_unlock();
        if (!res)
                __ICMP6_INC_STATS(net, ip6_dst_idev(dst),
                                  ICMP6_MIB_RATELIMITHOST);
index 55c49dc14b1bd9815128bbd07c80837adc19e7ec..016b572e7d6f0289657bda2a51a70153e98ed4fe 100644 (file)
@@ -180,7 +180,7 @@ static struct net_device *ip6_mc_find_dev(struct net *net,
                rcu_read_lock();
                rt = rt6_lookup(net, group, NULL, 0, NULL, 0);
                if (rt) {
-                       dev = dst_dev(&rt->dst);
+                       dev = dst_dev_rcu(&rt->dst);
                        dev_hold(dev);
                        ip6_rt_put(rt);
                }
index 57aaa7ae8ac3109d808dd46e8cfe54b57e48b214..f427e41e9c49bf342869bea4444f308a5ac03a26 100644 (file)
@@ -505,7 +505,7 @@ void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr,
 
        ip6_nd_hdr(skb, saddr, daddr, READ_ONCE(inet6_sk(sk)->hop_limit), skb->len);
 
-       dev = dst_dev(dst);
+       dev = dst_dev_rcu(dst);
        idev = __in6_dev_get(dev);
        IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
 
index d21fe27fe21e344b694e0378214fbad04c4844d2..1c9b283a4132dc4b3a8241b9e9255b407e03fe49 100644 (file)
@@ -104,18 +104,20 @@ EXPORT_SYMBOL(ip6_find_1stfragopt);
 int ip6_dst_hoplimit(struct dst_entry *dst)
 {
        int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
+
+       rcu_read_lock();
        if (hoplimit == 0) {
-               struct net_device *dev = dst_dev(dst);
+               struct net_device *dev = dst_dev_rcu(dst);
                struct inet6_dev *idev;
 
-               rcu_read_lock();
                idev = __in6_dev_get(dev);
                if (idev)
                        hoplimit = READ_ONCE(idev->cnf.hop_limit);
                else
                        hoplimit = READ_ONCE(dev_net(dev)->ipv6.devconf_all->hop_limit);
-               rcu_read_unlock();
        }
+       rcu_read_unlock();
+
        return hoplimit;
 }
 EXPORT_SYMBOL(ip6_dst_hoplimit);
index 3299cfa12e21c96ecb5c4dea5f305d5f7ce16084..3371f16b7a3e615bbb41ee0d1a7c9187a761fc0c 100644 (file)
@@ -2943,7 +2943,7 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
 
                if (res.f6i->nh) {
                        struct fib6_nh_match_arg arg = {
-                               .dev = dst_dev(dst),
+                               .dev = dst_dev_rcu(dst),
                                .gw = &rt6->rt6i_gateway,
                        };
 
@@ -3238,7 +3238,6 @@ EXPORT_SYMBOL_GPL(ip6_sk_redirect);
 
 static unsigned int ip6_default_advmss(const struct dst_entry *dst)
 {
-       struct net_device *dev = dst_dev(dst);
        unsigned int mtu = dst_mtu(dst);
        struct net *net;
 
@@ -3246,7 +3245,7 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)
 
        rcu_read_lock();
 
-       net = dev_net_rcu(dev);
+       net = dst_dev_net_rcu(dst);
        if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss)
                mtu = net->ipv6.sysctl.ip6_rt_min_advmss;
 
@@ -4301,7 +4300,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
 
        if (res.f6i->nh) {
                struct fib6_nh_match_arg arg = {
-                       .dev = dst_dev(dst),
+                       .dev = dst_dev_rcu(dst),
                        .gw = &rt->rt6i_gateway,
                };