]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ipv6: ip6_mc_input() and ip6_mr_input() cleanups
authorEric Dumazet <edumazet@google.com>
Mon, 30 Jun 2025 12:19:34 +0000 (12:19 +0000)
committerJakub Kicinski <kuba@kernel.org>
Wed, 2 Jul 2025 21:32:30 +0000 (14:32 -0700)
Both functions are always called under RCU.

We remove the extra rcu_read_lock()/rcu_read_unlock().

We use skb_dst_dev_net_rcu() instead of skb_dst_dev_net().

We use dev_net_rcu() instead of dev_net().

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20250630121934.3399505-11-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv6/ip6_input.c
net/ipv6/ip6mr.c

index 16953bd0096047f9b5fbb8e66bf9cc591e6693aa..0b3b81fd4a58ad62a83b807f38fd51ff24d47117 100644 (file)
@@ -501,38 +501,32 @@ EXPORT_SYMBOL_GPL(ip6_input);
 
 int ip6_mc_input(struct sk_buff *skb)
 {
+       struct net_device *dev = skb->dev;
        int sdif = inet6_sdif(skb);
        const struct ipv6hdr *hdr;
-       struct net_device *dev;
        bool deliver;
 
-       __IP6_UPD_PO_STATS(skb_dst_dev_net(skb),
-                        __in6_dev_get_safely(skb->dev), IPSTATS_MIB_INMCAST,
-                        skb->len);
+       __IP6_UPD_PO_STATS(skb_dst_dev_net_rcu(skb),
+                          __in6_dev_get_safely(dev), IPSTATS_MIB_INMCAST,
+                          skb->len);
 
        /* skb->dev passed may be master dev for vrfs. */
        if (sdif) {
-               rcu_read_lock();
-               dev = dev_get_by_index_rcu(dev_net(skb->dev), sdif);
+               dev = dev_get_by_index_rcu(dev_net_rcu(dev), sdif);
                if (!dev) {
-                       rcu_read_unlock();
                        kfree_skb(skb);
                        return -ENODEV;
                }
-       } else {
-               dev = skb->dev;
        }
 
        hdr = ipv6_hdr(skb);
        deliver = ipv6_chk_mcast_addr(dev, &hdr->daddr, NULL);
-       if (sdif)
-               rcu_read_unlock();
 
 #ifdef CONFIG_IPV6_MROUTE
        /*
         *      IPv6 multicast router mode is now supported ;)
         */
-       if (atomic_read(&dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding) &&
+       if (atomic_read(&dev_net_rcu(skb->dev)->ipv6.devconf_all->mc_forwarding) &&
            !(ipv6_addr_type(&hdr->daddr) &
              (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) &&
            likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {
@@ -573,22 +567,21 @@ int ip6_mc_input(struct sk_buff *skb)
                        /* unknown RA - process it normally */
                }
 
-               if (deliver)
+               if (deliver) {
                        skb2 = skb_clone(skb, GFP_ATOMIC);
-               else {
+               else {
                        skb2 = skb;
                        skb = NULL;
                }
 
-               if (skb2) {
+               if (skb2)
                        ip6_mr_input(skb2);
-               }
        }
 out:
 #endif
-       if (likely(deliver))
+       if (likely(deliver)) {
                ip6_input(skb);
-       else {
+       else {
                /* discard */
                kfree_skb(skb);
        }
index eb6a00262510f1cd6a9d48fab80bdd0d496bb7ee..e047a4680ab0e0fd06b81451bdfd0ebd47459f2e 100644 (file)
@@ -2301,21 +2301,20 @@ dont_forward:
 
 int ip6_mr_input(struct sk_buff *skb)
 {
+       struct net_device *dev = skb->dev;
+       struct net *net = dev_net_rcu(dev);
        struct mfc6_cache *cache;
-       struct net *net = dev_net(skb->dev);
        struct mr_table *mrt;
        struct flowi6 fl6 = {
-               .flowi6_iif     = skb->dev->ifindex,
+               .flowi6_iif     = dev->ifindex,
                .flowi6_mark    = skb->mark,
        };
        int err;
-       struct net_device *dev;
 
        /* skb->dev passed in is the master dev for vrfs.
         * Get the proper interface that does have a vif associated with it.
         */
-       dev = skb->dev;
-       if (netif_is_l3_master(skb->dev)) {
+       if (netif_is_l3_master(dev)) {
                dev = dev_get_by_index_rcu(net, IPCB(skb)->iif);
                if (!dev) {
                        kfree_skb(skb);