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>
This commit is contained in:
Eric Dumazet
2025-06-30 12:19:34 +00:00
committed by Jakub Kicinski
parent 93d1cff35a
commit 46a94e44b9
2 changed files with 15 additions and 23 deletions

View 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);
}

View 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);