[PATCH net-next v8 03/11] net: tunnel: convert udp_tunnel{6,}_xmit_skb to noref
From: Marek Mietus <hidden>
Date: 2026-03-12 16:08:27
Subsystem:
amt (automatic multicast tunneling), gtp (gprs tunneling protocol), networking drivers, networking [general], networking [ipv4/ipv6], openvpn data channel offload, sctp protocol, the rest, tipc network layer, wireguard secure network tunnel · Maintainers:
Taehee Yoo, Pablo Neira Ayuso, Harald Welte, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, David Ahern, Ido Schimmel, Antonio Quartulli, Marcelo Ricardo Leitner, Xin Long, Linus Torvalds, Jon Maloy, Jason A. Donenfeld
udp_tunnel{6,}_xmit_skb assume that a reference was taken on the dst
passed to them, and use that reference.
This forces callers to reference the dst, preventing noref optimizations.
Convert udp_tunnel{6,}_xmit_skb to be noref and drop the requirement
that a ref be taken on the dst.
Signed-off-by: Marek Mietus <redacted>
---
drivers/net/amt.c | 3 +++
drivers/net/bareudp.c | 2 ++
drivers/net/geneve.c | 2 ++
drivers/net/gtp.c | 7 +++++++
drivers/net/ovpn/udp.c | 2 ++
drivers/net/vxlan/vxlan_core.c | 2 ++
drivers/net/wireguard/socket.c | 2 ++
net/ipv4/udp_tunnel_core.c | 3 ---
net/ipv6/ip6_udp_tunnel.c | 2 +-
net/sctp/ipv6.c | 3 +++
net/sctp/protocol.c | 4 ++++
net/tipc/udp_media.c | 2 ++
12 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/drivers/net/amt.c b/drivers/net/amt.c
index f2f3139e38a5..a9fd2b864a1a 100644
--- a/drivers/net/amt.c
+++ b/drivers/net/amt.c@@ -1050,6 +1050,7 @@ static bool amt_send_membership_update(struct amt_dev *amt, false, false, 0); + ip_rt_put(rt); amt_update_gw_status(amt, AMT_STATUS_SENT_UPDATE, true); return false; }
@@ -1108,6 +1109,7 @@ static void amt_send_multicast_data(struct amt_dev *amt, false, false, 0); + ip_rt_put(rt); } static bool amt_send_membership_query(struct amt_dev *amt,
@@ -1167,6 +1169,7 @@ static bool amt_send_membership_query(struct amt_dev *amt, false, false, 0); + ip_rt_put(rt); amt_update_relay_status(tunnel, AMT_STATUS_SENT_QUERY, true); return false; }
diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c
index 0df3208783ad..92ee4a36f86f 100644
--- a/drivers/net/bareudp.c
+++ b/drivers/net/bareudp.c@@ -364,6 +364,7 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev, !net_eq(bareudp->net, dev_net(bareudp->dev)), !test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags), 0); + ip_rt_put(rt); return 0; free_dst:
@@ -433,6 +434,7 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev, !test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags), 0); + dst_release(dst); return 0; free_dst:
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 01cdd06102e0..4216a8ffd591 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c@@ -1396,6 +1396,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, !net_eq(geneve->net, dev_net(geneve->dev)), !test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags), 0); + ip_rt_put(rt); return 0; }
@@ -1487,6 +1488,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, !test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags), 0); + dst_release(dst); return 0; } #endif
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index e8949f556209..09b774eed6c7 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c@@ -449,6 +449,7 @@ static int gtp0_send_echo_resp_ip(struct gtp_dev *gtp, struct sk_buff *skb) dev_net(gtp->dev)), false, 0); + ip_rt_put(rt); return 0; }
@@ -708,6 +709,7 @@ static int gtp1u_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb) dev_net(gtp->dev)), false, 0); + ip_rt_put(rt); return 0; }
@@ -1308,6 +1310,7 @@ static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev) !net_eq(sock_net(pktinfo.pctx->sk), dev_net(dev)), false, 0); + ip_rt_put(pktinfo.rt); break; case AF_INET6: #if IS_ENABLED(CONFIG_IPV6)
@@ -1318,6 +1321,7 @@ static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev) 0, pktinfo.gtph_port, pktinfo.gtph_port, false, 0); + dst_release(&pktinfo.rt6->dst); #else goto tx_err; #endif
@@ -2400,6 +2404,7 @@ static int gtp_genl_send_echo_req(struct sk_buff *skb, struct genl_info *info) return -ENODEV; } + rcu_read_lock(); udp_tunnel_xmit_skb(rt, sk, skb_to_send, fl4.saddr, fl4.daddr, inet_dscp_to_dsfield(fl4.flowi4_dscp),
@@ -2409,6 +2414,8 @@ static int gtp_genl_send_echo_req(struct sk_buff *skb, struct genl_info *info) !net_eq(sock_net(sk), dev_net(gtp->dev)), false, 0); + rcu_read_unlock(); + ip_rt_put(rt); return 0; }
diff --git a/drivers/net/ovpn/udp.c b/drivers/net/ovpn/udp.c
index 272b535ecaad..2e202bd2b73f 100644
--- a/drivers/net/ovpn/udp.c
+++ b/drivers/net/ovpn/udp.c@@ -200,6 +200,7 @@ static int ovpn_udp4_output(struct ovpn_peer *peer, struct ovpn_bind *bind, udp_tunnel_xmit_skb(rt, sk, skb, fl.saddr, fl.daddr, 0, ip4_dst_hoplimit(&rt->dst), 0, fl.fl4_sport, fl.fl4_dport, false, sk->sk_no_check_tx, 0); + ip_rt_put(rt); ret = 0; err: local_bh_enable();
@@ -275,6 +276,7 @@ static int ovpn_udp6_output(struct ovpn_peer *peer, struct ovpn_bind *bind, udp_tunnel6_xmit_skb(dst, sk, skb, skb->dev, &fl.saddr, &fl.daddr, 0, ip6_dst_hoplimit(dst), 0, fl.fl6_sport, fl.fl6_dport, udp_get_no_check6_tx(sk), 0); + dst_release(dst); ret = 0; err: local_bh_enable();
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 17c941aac32d..4482a47dbe15 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c@@ -2545,6 +2545,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, pkey->u.ipv4.dst, tos, ttl, df, src_port, dst_port, xnet, !udp_sum, ipcb_flags); + ip_rt_put(rt); #if IS_ENABLED(CONFIG_IPV6) } else { struct vxlan_sock *sock6;
@@ -2620,6 +2621,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, &saddr, &pkey->u.ipv6.dst, tos, ttl, pkey->label, src_port, dst_port, !udp_sum, ip6cb_flags); + dst_release(ndst); #endif } vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX, pkt_len);
diff --git a/drivers/net/wireguard/socket.c b/drivers/net/wireguard/socket.c
index 253488f8c00f..ee7d9c675909 100644
--- a/drivers/net/wireguard/socket.c
+++ b/drivers/net/wireguard/socket.c@@ -85,6 +85,7 @@ static int send4(struct wg_device *wg, struct sk_buff *skb, udp_tunnel_xmit_skb(rt, sock, skb, fl.saddr, fl.daddr, ds, ip4_dst_hoplimit(&rt->dst), 0, fl.fl4_sport, fl.fl4_dport, false, false, 0); + ip_rt_put(rt); goto out; err:
@@ -152,6 +153,7 @@ static int send6(struct wg_device *wg, struct sk_buff *skb, udp_tunnel6_xmit_skb(dst, sock, skb, skb->dev, &fl.saddr, &fl.daddr, ds, ip6_dst_hoplimit(dst), 0, fl.fl6_sport, fl.fl6_dport, false, 0); + dst_release(dst); goto out; err:
diff --git a/net/ipv4/udp_tunnel_core.c b/net/ipv4/udp_tunnel_core.c
index 8a91f36cc052..b1f667c52cb2 100644
--- a/net/ipv4/udp_tunnel_core.c
+++ b/net/ipv4/udp_tunnel_core.c@@ -190,11 +190,8 @@ void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb udp_set_csum(nocheck, skb, src, dst, skb->len); - rcu_read_lock(); iptunnel_xmit(sk, rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df, xnet, ipcb_flags); - rcu_read_unlock(); - ip_rt_put(rt); } EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb);
diff --git a/net/ipv6/ip6_udp_tunnel.c b/net/ipv6/ip6_udp_tunnel.c
index cef3e0210744..d58815db8182 100644
--- a/net/ipv6/ip6_udp_tunnel.c
+++ b/net/ipv6/ip6_udp_tunnel.c@@ -95,7 +95,7 @@ void udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk, uh->len = htons(skb->len); - skb_dst_set(skb, dst); + skb_dst_set_noref(skb, dst); udp6_set_csum(nocheck, skb, saddr, daddr, skb->len);
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 53a5c027f8e3..43340eac8ec5 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c@@ -261,9 +261,12 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *t) skb_set_inner_ipproto(skb, IPPROTO_SCTP); label = ip6_make_flowlabel(sock_net(sk), skb, fl6->flowlabel, true, fl6); + rcu_read_lock(); udp_tunnel6_xmit_skb(dst, sk, skb, NULL, &fl6->saddr, &fl6->daddr, tclass, ip6_dst_hoplimit(dst), label, sctp_sk(sk)->udp_port, t->encap_port, false, 0); + rcu_read_unlock(); + dst_release(dst); return 0; }
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 828a59b8e7bf..815279410bf9 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c@@ -1070,10 +1070,14 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, struct sctp_transport *t) skb_reset_inner_mac_header(skb); skb_reset_inner_transport_header(skb); skb_set_inner_ipproto(skb, IPPROTO_SCTP); + + rcu_read_lock(); udp_tunnel_xmit_skb(dst_rtable(dst), sk, skb, fl4->saddr, fl4->daddr, dscp, ip4_dst_hoplimit(dst), df, sctp_sk(sk)->udp_port, t->encap_port, false, false, 0); + rcu_read_unlock(); + dst_release(dst); return 0; }
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index 2b8e385d1e51..df0d82fed02e 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c@@ -198,6 +198,7 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb, udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, src->ipv4.s_addr, dst->ipv4.s_addr, 0, ttl, 0, src->port, dst->port, false, true, 0); + ip_rt_put(rt); #if IS_ENABLED(CONFIG_IPV6) } else { if (!ndst) {
@@ -220,6 +221,7 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb, udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, NULL, &src->ipv6, &dst->ipv6, 0, ttl, 0, src->port, dst->port, false, 0); + dst_release(ndst); #endif } local_bh_enable();
--
2.51.0