[PATCH net-next v6 09/11] net: sctp: convert sctp_v{4,6}_xmit to use a noref dst when possible
From: Marek Mietus <hidden>
Date: 2026-01-20 16:38:13
Subsystem:
networking [general], sctp protocol, the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marcelo Ricardo Leitner, Xin Long, Linus Torvalds
sctp_v{4,6}_xmit unnecessarily clone the dst from the transport when
sending an encapsulated skb.
Reduce this overhead by avoiding the refcount increment introduced by
cloning the dst.
Since t->dst is already assumed to be valid throughout both functions,
it's safe to use the dst without incrementing the refcount.
Signed-off-by: Marek Mietus <redacted>
---
net/sctp/ipv6.c | 7 ++++---
net/sctp/protocol.c | 8 +++++---
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 38fd1cf3148f..71fb9ff6276f 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c@@ -219,7 +219,7 @@ int sctp_udp_v6_err(struct sock *sk, struct sk_buff *skb) static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *t) { - struct dst_entry *dst = dst_clone(t->dst); + struct dst_entry *dst = t->dst; struct flowi6 *fl6 = &t->fl.u.ip6; struct sock *sk = skb->sk; struct ipv6_pinfo *np = inet6_sk(sk);
@@ -243,7 +243,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *t) if (!t->encap_port || !sctp_sk(sk)->udp_port) { int res; - skb_dst_set(skb, dst); + skb_dst_set(skb, dst_clone(dst)); rcu_read_lock(); res = ip6_xmit(sk, skb, fl6, sk->sk_mark, rcu_dereference(np->opt),
@@ -261,10 +261,11 @@ 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); - dst_release(dst); + rcu_read_unlock(); return 0; }
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index ff18ed0a65ff..fb26b927391b 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c@@ -1038,7 +1038,7 @@ static int sctp_inet_supported_addrs(const struct sctp_sock *opt, /* Wrapper routine that calls the ip transmit routine. */ static inline int sctp_v4_xmit(struct sk_buff *skb, struct sctp_transport *t) { - struct dst_entry *dst = dst_clone(t->dst); + struct dst_entry *dst = t->dst; struct flowi4 *fl4 = &t->fl.u.ip4; struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(sk);
@@ -1056,7 +1056,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, struct sctp_transport *t) SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); if (!t->encap_port || !sctp_sk(sk)->udp_port) { - skb_dst_set(skb, dst); + skb_dst_set(skb, dst_clone(dst)); return __ip_queue_xmit(sk, skb, &t->fl, dscp); }
@@ -1070,11 +1070,13 @@ 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); - dst_release(dst); + rcu_read_unlock(); return 0; }
--
2.51.0