Skip to content

Commit 25b0872

Browse files
author
CKI KWF Bot
committed
Merge: IPv6: drop rtnl from mcast and anycast
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1474 JIRA: https://issues.redhat.com/browse/RHEL-115325 * 54568a8 net: introduce EXPORT_IPV6_MOD() and EXPORT_IPV6_MOD_GPL() * a527750 ipv6: mcast: add RCU protection to mld_newpack() * fb60b74 ipv6: ndisc: Remove __in6_dev_get() in pndisc_{constructor,destructor}(). * 818ae1a ipv6: mcast: Replace locking comments with lockdep annotations. * dbd40f3 ipv6: mcast: Check inet6_dev->dead under idev->mc_lock in __ipv6_dev_mc_inc(). * d22faae ipv6: mcast: Remove mca_get(). * e01b193 ipv6: mcast: Use in6_dev_get() in ipv6_dev_mc_dec(). * 1767bb2 ipv6: mcast: Don't hold RTNL for IPV6_ADD_MEMBERSHIP and MCAST_JOIN_GROUP. * 2ceb71c ipv6: mcast: Don't hold RTNL for IPV6_DROP_MEMBERSHIP and MCAST_LEAVE_GROUP. * 1e589db ipv6: mcast: Don't hold RTNL in ipv6_sock_mc_close(). * e6e14d5 ipv6: mcast: Don't hold RTNL for MCAST_ socket options. * 49b8223 ipv6: mcast: Remove unnecessary ASSERT_RTNL and comment. * 7b6b53a ipv6: anycast: Don't use rtnl_dereference(). * f7fdf13 ipv6: anycast: Don't hold RTNL for IPV6_LEAVE_ANYCAST and IPV6_ADDRFORM. * 976fa9b ipv6: anycast: Unify two error paths in ipv6_sock_ac_join(). * eb1ac9f ipv6: anycast: Don't hold RTNL for IPV6_JOIN_ANYCAST. * db38443 ipv6: Remove setsockopt_needs_rtnl(). * 2a683d0 dev: Pass netdevice_tracker to dev_get_by_flags_rcu(). * ae3264a ipv6: mcast: Delay put pmc->idev in mld_del_delrec() Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com> Signed-off-by: Hangbin Liu <haliu@redhat.com> --- <small>Created 2025-09-22 10:22 UTC by backporter - [KWF FAQ](https://red.ht/kernel_workflow_doc) - [Slack #team-kernel-workflow](https://redhat-internal.slack.com/archives/C04LRUPMJQ5) - [Source](https://gitlab.com/cki-project/kernel-workflow/-/blob/main/webhook/utils/backporter.py) - [Documentation](https://gitlab.com/cki-project/kernel-workflow/-/blob/main/docs/README.backporter.md) - [Report an issue](https://issues.redhat.com/secure/CreateIssueDetails!init.jspa?pid=12334433&issuetype=1&priority=4&summary=backporter+webhook+issue&components=kernel-workflow+/+backporter)</small> Approved-by: Sabrina Dubroca <sdubroca@redhat.com> Approved-by: Paolo Abeni <pabeni@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents 40321a6 + 53cd014 commit 25b0872

File tree

15 files changed

+324
-291
lines changed

15 files changed

+324
-291
lines changed

include/linux/netdevice.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3246,8 +3246,6 @@ int dev_get_iflink(const struct net_device *dev);
32463246
int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
32473247
int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
32483248
struct net_device_path_stack *stack);
3249-
struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags,
3250-
unsigned short mask);
32513249
struct net_device *dev_get_by_name(struct net *net, const char *name);
32523250
struct net_device *dev_get_by_name_rcu(struct net *net, const char *name);
32533251
struct net_device *__dev_get_by_name(struct net *net, const char *name);
@@ -3307,6 +3305,8 @@ struct net_device *netdev_get_by_index(struct net *net, int ifindex,
33073305
netdevice_tracker *tracker, gfp_t gfp);
33083306
struct net_device *netdev_get_by_name(struct net *net, const char *name,
33093307
netdevice_tracker *tracker, gfp_t gfp);
3308+
struct net_device *netdev_get_by_flags_rcu(struct net *net, netdevice_tracker *tracker,
3309+
unsigned short flags, unsigned short mask);
33103310
struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex);
33113311
void netdev_copy_name(struct net_device *dev, char *name);
33123312

include/net/dst.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ INDIRECT_CALLABLE_DECLARE(int ip_output(struct net *, struct sock *,
456456
/* Output packet to network from transport. */
457457
static inline int dst_output(struct net *net, struct sock *sk, struct sk_buff *skb)
458458
{
459-
return INDIRECT_CALL_INET(skb_dst(skb)->output,
459+
return INDIRECT_CALL_INET(READ_ONCE(skb_dst(skb)->output),
460460
ip6_output, ip_output,
461461
net, sk, skb);
462462
}
@@ -466,7 +466,7 @@ INDIRECT_CALLABLE_DECLARE(int ip_local_deliver(struct sk_buff *));
466466
/* Input packet from network to transport. */
467467
static inline int dst_input(struct sk_buff *skb)
468468
{
469-
return INDIRECT_CALL_INET(skb_dst(skb)->input,
469+
return INDIRECT_CALL_INET(READ_ONCE(skb_dst(skb)->input),
470470
ip6_input, ip_local_deliver, skb);
471471
}
472472

@@ -561,6 +561,26 @@ static inline void skb_dst_update_pmtu_no_confirm(struct sk_buff *skb, u32 mtu)
561561
dst->ops->update_pmtu(dst, NULL, skb, mtu, false);
562562
}
563563

564+
static inline struct net_device *dst_dev(const struct dst_entry *dst)
565+
{
566+
return READ_ONCE(dst->dev);
567+
}
568+
569+
static inline struct net_device *skb_dst_dev(const struct sk_buff *skb)
570+
{
571+
return dst_dev(skb_dst(skb));
572+
}
573+
574+
static inline struct net *skb_dst_dev_net(const struct sk_buff *skb)
575+
{
576+
return dev_net(skb_dst_dev(skb));
577+
}
578+
579+
static inline struct net *skb_dst_dev_net_rcu(const struct sk_buff *skb)
580+
{
581+
return dev_net_rcu(skb_dst_dev(skb));
582+
}
583+
564584
struct dst_entry *dst_blackhole_check(struct dst_entry *dst, u32 cookie);
565585
void dst_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk,
566586
struct sk_buff *skb, u32 mtu, bool confirm_neigh);

include/net/inet_connection_sock.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ struct inet_connection_sock {
117117
#define ATO_BITS 8
118118
__u32 ato:ATO_BITS, /* Predicted tick of soft clock */
119119
lrcv_flowlabel:20, /* last received ipv6 flowlabel */
120-
unused:4;
120+
dst_quick_ack:1, /* cache dst RTAX_QUICKACK */
121+
unused:3;
121122
unsigned long timeout; /* Currently scheduled timeout */
122123
__u32 lrcvtime; /* timestamp of last received data packet */
123124
__u16 last_seg_size; /* Size of last incoming segment */

include/net/ip.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,14 @@ static __inline__ void inet_reset_saddr(struct sock *sk)
687687

688688
#endif
689689

690+
#if IS_MODULE(CONFIG_IPV6)
691+
#define EXPORT_IPV6_MOD(X) EXPORT_SYMBOL(X)
692+
#define EXPORT_IPV6_MOD_GPL(X) EXPORT_SYMBOL_GPL(X)
693+
#else
694+
#define EXPORT_IPV6_MOD(X)
695+
#define EXPORT_IPV6_MOD_GPL(X)
696+
#endif
697+
690698
static inline unsigned int ipv4_addr_hash(__be32 ip)
691699
{
692700
return (__force unsigned int) ip;

include/net/lwtunnel.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,12 @@ int bpf_lwt_push_ip_encap(struct sk_buff *skb, void *hdr, u32 len,
138138
static inline void lwtunnel_set_redirect(struct dst_entry *dst)
139139
{
140140
if (lwtunnel_output_redirect(dst->lwtstate)) {
141-
dst->lwtstate->orig_output = dst->output;
142-
dst->output = lwtunnel_output;
141+
dst->lwtstate->orig_output = READ_ONCE(dst->output);
142+
WRITE_ONCE(dst->output, lwtunnel_output);
143143
}
144144
if (lwtunnel_input_redirect(dst->lwtstate)) {
145-
dst->lwtstate->orig_input = dst->input;
146-
dst->input = lwtunnel_input;
145+
dst->lwtstate->orig_input = READ_ONCE(dst->input);
146+
WRITE_ONCE(dst->input, lwtunnel_input);
147147
}
148148
}
149149
#else

net/core/dev.c

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,33 +1213,32 @@ struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type)
12131213
EXPORT_SYMBOL(dev_getfirstbyhwtype);
12141214

12151215
/**
1216-
* __dev_get_by_flags - find any device with given flags
1217-
* @net: the applicable net namespace
1218-
* @if_flags: IFF_* values
1219-
* @mask: bitmask of bits in if_flags to check
1216+
* netdev_get_by_flags_rcu - find any device with given flags
1217+
* @net: the applicable net namespace
1218+
* @tracker: tracking object for the acquired reference
1219+
* @if_flags: IFF_* values
1220+
* @mask: bitmask of bits in if_flags to check
12201221
*
1221-
* Search for any interface with the given flags. Returns NULL if a device
1222-
* is not found or a pointer to the device. Must be called inside
1223-
* rtnl_lock(), and result refcount is unchanged.
1222+
* Search for any interface with the given flags.
1223+
*
1224+
* Context: rcu_read_lock() must be held.
1225+
* Returns: NULL if a device is not found or a pointer to the device.
12241226
*/
1225-
1226-
struct net_device *__dev_get_by_flags(struct net *net, unsigned short if_flags,
1227-
unsigned short mask)
1227+
struct net_device *netdev_get_by_flags_rcu(struct net *net, netdevice_tracker *tracker,
1228+
unsigned short if_flags, unsigned short mask)
12281229
{
1229-
struct net_device *dev, *ret;
1230-
1231-
ASSERT_RTNL();
1230+
struct net_device *dev;
12321231

1233-
ret = NULL;
1234-
for_each_netdev(net, dev) {
1235-
if (((dev->flags ^ if_flags) & mask) == 0) {
1236-
ret = dev;
1237-
break;
1232+
for_each_netdev_rcu(net, dev) {
1233+
if (((READ_ONCE(dev->flags) ^ if_flags) & mask) == 0) {
1234+
netdev_hold(dev, tracker, GFP_ATOMIC);
1235+
return dev;
12381236
}
12391237
}
1240-
return ret;
1238+
1239+
return NULL;
12411240
}
1242-
EXPORT_SYMBOL(__dev_get_by_flags);
1241+
EXPORT_IPV6_MOD(netdev_get_by_flags_rcu);
12431242

12441243
/**
12451244
* dev_valid_name - check if name is okay for network device

net/core/dst.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,9 @@ void dst_dev_put(struct dst_entry *dst)
148148
dst->obsolete = DST_OBSOLETE_DEAD;
149149
if (dst->ops->ifdown)
150150
dst->ops->ifdown(dst, dev);
151-
dst->input = dst_discard;
152-
dst->output = dst_discard_out;
153-
dst->dev = blackhole_netdev;
151+
WRITE_ONCE(dst->input, dst_discard);
152+
WRITE_ONCE(dst->output, dst_discard_out);
153+
WRITE_ONCE(dst->dev, blackhole_netdev);
154154
netdev_ref_replace(dev, blackhole_netdev, &dst->dev_tracker,
155155
GFP_ATOMIC);
156156
}
@@ -263,7 +263,7 @@ unsigned int dst_blackhole_mtu(const struct dst_entry *dst)
263263
{
264264
unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
265265

266-
return mtu ? : dst->dev->mtu;
266+
return mtu ? : dst_dev(dst)->mtu;
267267
}
268268
EXPORT_SYMBOL_GPL(dst_blackhole_mtu);
269269

net/core/sock.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2532,8 +2532,8 @@ static u32 sk_dst_gso_max_size(struct sock *sk, struct dst_entry *dst)
25322532
!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr));
25332533
#endif
25342534
/* pairs with the WRITE_ONCE() in netif_set_gso(_ipv4)_max_size() */
2535-
max_size = is_ipv6 ? READ_ONCE(dst->dev->gso_max_size) :
2536-
READ_ONCE(dst->dev->gso_ipv4_max_size);
2535+
max_size = is_ipv6 ? READ_ONCE(dst_dev(dst)->gso_max_size) :
2536+
READ_ONCE(dst_dev(dst)->gso_ipv4_max_size);
25372537
if (max_size > GSO_LEGACY_MAX_SIZE && !sk_is_tcp(sk))
25382538
max_size = GSO_LEGACY_MAX_SIZE;
25392539

@@ -2544,9 +2544,13 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
25442544
{
25452545
u32 max_segs = 1;
25462546

2547-
sk->sk_route_caps = dst->dev->features;
2548-
if (sk_is_tcp(sk))
2547+
sk->sk_route_caps = dst_dev(dst)->features;
2548+
if (sk_is_tcp(sk)) {
2549+
struct inet_connection_sock *icsk = inet_csk(sk);
2550+
25492551
sk->sk_route_caps |= NETIF_F_GSO;
2552+
icsk->icsk_ack.dst_quick_ack = dst_metric(dst, RTAX_QUICKACK);
2553+
}
25502554
if (sk->sk_route_caps & NETIF_F_GSO)
25512555
sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
25522556
if (unlikely(sk->sk_gso_disabled))
@@ -2558,7 +2562,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
25582562
sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
25592563
sk->sk_gso_max_size = sk_dst_gso_max_size(sk, dst);
25602564
/* pairs with the WRITE_ONCE() in netif_set_gso_max_segs() */
2561-
max_segs = max_t(u32, READ_ONCE(dst->dev->gso_max_segs), 1);
2565+
max_segs = max_t(u32, READ_ONCE(dst_dev(dst)->gso_max_segs), 1);
25622566
}
25632567
}
25642568
sk->sk_gso_max_segs = max_segs;

net/ipv4/route.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,8 +1667,8 @@ struct rtable *rt_dst_clone(struct net_device *dev, struct rtable *rt)
16671667
else if (rt->rt_gw_family == AF_INET6)
16681668
new_rt->rt_gw6 = rt->rt_gw6;
16691669

1670-
new_rt->dst.input = rt->dst.input;
1671-
new_rt->dst.output = rt->dst.output;
1670+
new_rt->dst.input = READ_ONCE(rt->dst.input);
1671+
new_rt->dst.output = READ_ONCE(rt->dst.output);
16721672
new_rt->dst.error = rt->dst.error;
16731673
new_rt->dst.lastuse = jiffies;
16741674
new_rt->dst.lwtstate = lwtstate_get(rt->dst.lwtstate);

net/ipv4/tcp_input.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,8 @@ static void tcp_enter_quickack_mode(struct sock *sk, unsigned int max_quickacks)
333333
static bool tcp_in_quickack_mode(struct sock *sk)
334334
{
335335
const struct inet_connection_sock *icsk = inet_csk(sk);
336-
const struct dst_entry *dst = __sk_dst_get(sk);
337336

338-
return (dst && dst_metric(dst, RTAX_QUICKACK)) ||
337+
return icsk->icsk_ack.dst_quick_ack ||
339338
(icsk->icsk_ack.quick && !inet_csk_in_pingpong_mode(sk));
340339
}
341340

0 commit comments

Comments
 (0)