Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipv6: ip6_mc_input() and ip6_mr_input() cleanups

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>

authored by

Eric Dumazet and committed by
Jakub Kicinski
46a94e44 93d1cff3

+15 -23
+11 -18
net/ipv6/ip6_input.c
··· 501 501 502 502 int ip6_mc_input(struct sk_buff *skb) 503 503 { 504 + struct net_device *dev = skb->dev; 504 505 int sdif = inet6_sdif(skb); 505 506 const struct ipv6hdr *hdr; 506 - struct net_device *dev; 507 507 bool deliver; 508 508 509 - __IP6_UPD_PO_STATS(skb_dst_dev_net(skb), 510 - __in6_dev_get_safely(skb->dev), IPSTATS_MIB_INMCAST, 511 - skb->len); 509 + __IP6_UPD_PO_STATS(skb_dst_dev_net_rcu(skb), 510 + __in6_dev_get_safely(dev), IPSTATS_MIB_INMCAST, 511 + skb->len); 512 512 513 513 /* skb->dev passed may be master dev for vrfs. */ 514 514 if (sdif) { 515 - rcu_read_lock(); 516 - dev = dev_get_by_index_rcu(dev_net(skb->dev), sdif); 515 + dev = dev_get_by_index_rcu(dev_net_rcu(dev), sdif); 517 516 if (!dev) { 518 - rcu_read_unlock(); 519 517 kfree_skb(skb); 520 518 return -ENODEV; 521 519 } 522 - } else { 523 - dev = skb->dev; 524 520 } 525 521 526 522 hdr = ipv6_hdr(skb); 527 523 deliver = ipv6_chk_mcast_addr(dev, &hdr->daddr, NULL); 528 - if (sdif) 529 - rcu_read_unlock(); 530 524 531 525 #ifdef CONFIG_IPV6_MROUTE 532 526 /* 533 527 * IPv6 multicast router mode is now supported ;) 534 528 */ 535 - if (atomic_read(&dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding) && 529 + if (atomic_read(&dev_net_rcu(skb->dev)->ipv6.devconf_all->mc_forwarding) && 536 530 !(ipv6_addr_type(&hdr->daddr) & 537 531 (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) && 538 532 likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) { ··· 567 573 /* unknown RA - process it normally */ 568 574 } 569 575 570 - if (deliver) 576 + if (deliver) { 571 577 skb2 = skb_clone(skb, GFP_ATOMIC); 572 - else { 578 + } else { 573 579 skb2 = skb; 574 580 skb = NULL; 575 581 } 576 582 577 - if (skb2) { 583 + if (skb2) 578 584 ip6_mr_input(skb2); 579 - } 580 585 } 581 586 out: 582 587 #endif 583 - if (likely(deliver)) 588 + if (likely(deliver)) { 584 589 ip6_input(skb); 585 - else { 590 + } else { 586 591 /* discard */ 587 592 kfree_skb(skb); 588 593 }
+4 -5
net/ipv6/ip6mr.c
··· 2301 2301 2302 2302 int ip6_mr_input(struct sk_buff *skb) 2303 2303 { 2304 + struct net_device *dev = skb->dev; 2305 + struct net *net = dev_net_rcu(dev); 2304 2306 struct mfc6_cache *cache; 2305 - struct net *net = dev_net(skb->dev); 2306 2307 struct mr_table *mrt; 2307 2308 struct flowi6 fl6 = { 2308 - .flowi6_iif = skb->dev->ifindex, 2309 + .flowi6_iif = dev->ifindex, 2309 2310 .flowi6_mark = skb->mark, 2310 2311 }; 2311 2312 int err; 2312 - struct net_device *dev; 2313 2313 2314 2314 /* skb->dev passed in is the master dev for vrfs. 2315 2315 * Get the proper interface that does have a vif associated with it. 2316 2316 */ 2317 - dev = skb->dev; 2318 - if (netif_is_l3_master(skb->dev)) { 2317 + if (netif_is_l3_master(dev)) { 2319 2318 dev = dev_get_by_index_rcu(net, IPCB(skb)->iif); 2320 2319 if (!dev) { 2321 2320 kfree_skb(skb);