[PATCH v2 1/3] ipv6: extract and export ip6_sock_set_tclass helpers
Geliang Tang
geliang at kernel.org
Fri Aug 7 23:54:59 PDT 2026
From: Geliang Tang <tanggeliang at kylinos.cn>
IPV6_TCLASS handling in do_ipv6_setsockopt() inlines the same ECN mask
logic and inet6_sk(sk)->tclass write that callers need when propagating
a tclass value onto a newly created socket.
Pull this into small helpers __ip6_sock_set_tclass()/ip6_sock_set_tclass()
exported via <net/ipv6.h>, so external modules can apply IPV6_TCLASS
without duplicating the ECN handling.
__ip6_sock_set_tclass() will be used by MPTCP's sockopt implementation
(similar to __ip_sock_set_tos), while ip6_sock_set_tclass() will be used
by nvme-tcp (similar to ip_sock_set_tos).
Signed-off-by: Geliang Tang <tanggeliang at kylinos.cn>
---
include/net/ipv6.h | 3 +++
net/ipv6/ipv6_sockglue.c | 31 +++++++++++++++++++++++--------
2 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 3de07e738538..82e57b34ba57 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -1252,6 +1252,9 @@ static inline void ip6_sock_set_recverr(struct sock *sk)
inet6_set_bit(RECVERR6, sk);
}
+void __ip6_sock_set_tclass(struct sock *sk, int val);
+void ip6_sock_set_tclass(struct sock *sk, int val);
+
#define IPV6_PREFER_SRC_MASK (IPV6_PREFER_SRC_TMP | IPV6_PREFER_SRC_PUBLIC | \
IPV6_PREFER_SRC_COA)
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index b4c977434c2e..c59f25fbb336 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -373,6 +373,28 @@ static int ipv6_set_opt_hdr(struct sock *sk, int optname, sockptr_t optval,
return err;
}
+void __ip6_sock_set_tclass(struct sock *sk, int val)
+{
+ u8 old_tclass = inet6_sk(sk)->tclass;
+
+ if (sk->sk_type == SOCK_STREAM) {
+ val &= ~INET_ECN_MASK;
+ val |= old_tclass & INET_ECN_MASK;
+ }
+ if (old_tclass != val) {
+ WRITE_ONCE(inet6_sk(sk)->tclass, val);
+ sk_dst_reset(sk);
+ }
+}
+
+void ip6_sock_set_tclass(struct sock *sk, int val)
+{
+ sockopt_lock_sock(sk);
+ __ip6_sock_set_tclass(sk, val);
+ sockopt_release_sock(sk);
+}
+EXPORT_SYMBOL(ip6_sock_set_tclass);
+
int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
sockptr_t optval, unsigned int optlen)
{
@@ -713,14 +735,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
/* RFC 3542, 6.5: default traffic class of 0x0 */
if (val == -1)
val = 0;
- if (sk->sk_type == SOCK_STREAM) {
- val &= ~INET_ECN_MASK;
- val |= np->tclass & INET_ECN_MASK;
- }
- if (np->tclass != val) {
- np->tclass = val;
- sk_dst_reset(sk);
- }
+ __ip6_sock_set_tclass(sk, val);
retv = 0;
break;
--
2.53.0
More information about the Linux-nvme
mailing list