* [PATCH v3 1/4] nvmet-tcp: unify sockopt with do_sock_setsockopt
2026-08-16 0:59 [PATCH v3 0/4] nvme-tcp: add IPv6 traffic class support Geliang Tang
@ 2026-08-16 0:59 ` Geliang Tang
2026-08-16 0:59 ` [PATCH v3 2/4] nvme-tcp: " Geliang Tang
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Geliang Tang @ 2026-08-16 0:59 UTC (permalink / raw)
To: Keith Busch, Jens Axboe, Christoph Hellwig, Sagi Grimberg,
Chaitanya Kulkarni, David Ahern, Ido Schimmel, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Hannes Reinecke, Stanislav Fomichev
Cc: Geliang Tang, linux-nvme, netdev, mptcp
From: Geliang Tang <tanggeliang@kylinos.cn>
This patch consolidates socket option settings in nvmet-tcp by utilizing
the generic do_sock_setsockopt() helper for options including SO_LINGER,
SO_PRIORITY, SO_REUSEADDR, TCP_NODELAY, and IP_TOS. This change eliminates
the need to export and use specialized helpers for each individual socket
option.
A key benefit of this refactoring is that it decouples the socket option
configuration from the underlying transport protocol. This makes it
easier to extend nvmet-tcp to support other protocols, such as MPTCP, in
the future, as do_sock_setsockopt() abstracts away protocol-specific
differences without requiring per-option protocol-specific wrappers.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
drivers/nvme/target/tcp.c | 53 +++++++++++++++++++++++++++++++++------
1 file changed, 45 insertions(+), 8 deletions(-)
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index 75a276d73be3..e64592b79257 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -1696,10 +1696,48 @@ static void nvmet_tcp_state_change(struct sock *sk)
read_unlock_bh(&sk->sk_callback_lock);
}
+static void nvmet_tcp_sock_no_linger(struct sock *sk)
+{
+ struct linger ling = { .l_onoff = 1, .l_linger = 0 };
+
+ do_sock_setsockopt(sk->sk_socket, false, SOL_SOCKET, SO_LINGER,
+ KERNEL_SOCKPTR(&ling), sizeof(ling));
+}
+
+static void nvmet_tcp_sock_set_priority(struct sock *sk, u32 priority)
+{
+ do_sock_setsockopt(sk->sk_socket, false, SOL_SOCKET, SO_PRIORITY,
+ KERNEL_SOCKPTR(&priority), sizeof(priority));
+}
+
+static void nvmet_tcp_sock_set_reuseaddr(struct sock *sk)
+{
+ int val = SK_CAN_REUSE;
+
+ do_sock_setsockopt(sk->sk_socket, false, SOL_SOCKET, SO_REUSEADDR,
+ KERNEL_SOCKPTR(&val), sizeof(val));
+}
+
+static void nvmet_tcp_sock_set_nodelay(struct sock *sk)
+{
+ int val = 1;
+
+ do_sock_setsockopt(sk->sk_socket, false, SOL_TCP, TCP_NODELAY,
+ KERNEL_SOCKPTR(&val), sizeof(val));
+}
+
+static void nvmet_tcp_sock_set_tos(struct sock *sk)
+{
+ u8 tos = inet_sk(sk)->rcv_tos;
+
+ if (tos > 0)
+ do_sock_setsockopt(sk->sk_socket, false, SOL_IP, IP_TOS,
+ KERNEL_SOCKPTR(&tos), sizeof(tos));
+}
+
static int nvmet_tcp_set_queue_sock(struct nvmet_tcp_queue *queue)
{
struct socket *sock = queue->sock;
- struct inet_sock *inet = inet_sk(sock->sk);
int ret;
ret = kernel_getsockname(sock,
@@ -1717,14 +1755,13 @@ static int nvmet_tcp_set_queue_sock(struct nvmet_tcp_queue *queue)
* close. This is done to prevent stale data from being sent should
* the network connection be restored before TCP times out.
*/
- sock_no_linger(sock->sk);
+ nvmet_tcp_sock_no_linger(sock->sk);
if (so_priority > 0)
- sock_set_priority(sock->sk, so_priority);
+ nvmet_tcp_sock_set_priority(sock->sk, so_priority);
/* Set socket type of service */
- if (inet->rcv_tos > 0)
- ip_sock_set_tos(sock->sk, inet->rcv_tos);
+ nvmet_tcp_sock_set_tos(sock->sk);
ret = 0;
write_lock_bh(&sock->sk->sk_callback_lock);
@@ -2098,10 +2135,10 @@ static int nvmet_tcp_add_port(struct nvmet_port *nport)
port->sock->sk->sk_user_data = port;
port->data_ready = port->sock->sk->sk_data_ready;
port->sock->sk->sk_data_ready = nvmet_tcp_listen_data_ready;
- sock_set_reuseaddr(port->sock->sk);
- tcp_sock_set_nodelay(port->sock->sk);
+ nvmet_tcp_sock_set_reuseaddr(port->sock->sk);
+ nvmet_tcp_sock_set_nodelay(port->sock->sk);
if (so_priority > 0)
- sock_set_priority(port->sock->sk, so_priority);
+ nvmet_tcp_sock_set_priority(port->sock->sk, so_priority);
ret = kernel_bind(port->sock, (struct sockaddr_unsized *)&port->addr,
sizeof(port->addr));
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v3 2/4] nvme-tcp: unify sockopt with do_sock_setsockopt
2026-08-16 0:59 [PATCH v3 0/4] nvme-tcp: add IPv6 traffic class support Geliang Tang
2026-08-16 0:59 ` [PATCH v3 1/4] nvmet-tcp: unify sockopt with do_sock_setsockopt Geliang Tang
@ 2026-08-16 0:59 ` Geliang Tang
2026-08-16 1:16 ` sashiko-bot
2026-08-16 0:59 ` [PATCH v3 3/4] nvmet-tcp: support IPv6 traffic class Geliang Tang
` (2 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Geliang Tang @ 2026-08-16 0:59 UTC (permalink / raw)
To: Keith Busch, Jens Axboe, Christoph Hellwig, Sagi Grimberg,
Chaitanya Kulkarni, David Ahern, Ido Schimmel, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Hannes Reinecke, Stanislav Fomichev
Cc: Geliang Tang, linux-nvme, netdev, mptcp
From: Geliang Tang <tanggeliang@kylinos.cn>
This patch consolidates socket option settings in nvme-tcp by utilizing
the generic do_sock_setsockopt() helper for options including SO_LINGER,
SO_PRIORITY, TCP_NODELAY, IP_TOS, SO_BINDTODEVICE, and TCP_SYNCNT.
Compared to the target-side implementation, this patch additionally
converts SO_BINDTODEVICE and TCP_SYNCNT to use the same unified mechanism.
This change eliminates the need to export and use specialized helpers for
each individual socket option.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
drivers/nvme/host/tcp.c | 55 +++++++++++++++++++++++++++++++++++------
1 file changed, 47 insertions(+), 8 deletions(-)
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index ba5c7b3e2a7c..89a82e8248d2 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -1774,6 +1774,47 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
return ret;
}
+static void nvme_tcp_sock_no_linger(struct sock *sk)
+{
+ struct linger ling = { .l_onoff = 1, .l_linger = 0 };
+
+ do_sock_setsockopt(sk->sk_socket, false, SOL_SOCKET, SO_LINGER,
+ KERNEL_SOCKPTR(&ling), sizeof(ling));
+}
+
+static void nvme_tcp_sock_set_priority(struct sock *sk, u32 priority)
+{
+ do_sock_setsockopt(sk->sk_socket, false, SOL_SOCKET, SO_PRIORITY,
+ KERNEL_SOCKPTR(&priority), sizeof(priority));
+}
+
+static int nvme_tcp_sock_set_bindtodevice(struct sock *sk, char *iface)
+{
+ return do_sock_setsockopt(sk->sk_socket, false, SOL_SOCKET,
+ SO_BINDTODEVICE, KERNEL_SOCKPTR(iface),
+ strlen(iface));
+}
+
+static void nvme_tcp_sock_set_nodelay(struct sock *sk)
+{
+ int val = 1;
+
+ do_sock_setsockopt(sk->sk_socket, false, SOL_TCP, TCP_NODELAY,
+ KERNEL_SOCKPTR(&val), sizeof(val));
+}
+
+static int nvme_tcp_sock_set_syncnt(struct sock *sk, int val)
+{
+ return do_sock_setsockopt(sk->sk_socket, false, SOL_TCP, TCP_SYNCNT,
+ KERNEL_SOCKPTR(&val), sizeof(val));
+}
+
+static void nvme_tcp_sock_set_tos(struct sock *sk, int tos)
+{
+ do_sock_setsockopt(sk->sk_socket, false, SOL_IP, IP_TOS,
+ KERNEL_SOCKPTR(&tos), sizeof(tos));
+}
+
static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
key_serial_t pskid)
{
@@ -1819,24 +1860,24 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
#endif
/* Single syn retry */
- tcp_sock_set_syncnt(queue->sock->sk, 1);
+ nvme_tcp_sock_set_syncnt(queue->sock->sk, 1);
/* Set TCP no delay */
- tcp_sock_set_nodelay(queue->sock->sk);
+ nvme_tcp_sock_set_nodelay(queue->sock->sk);
/*
* Cleanup whatever is sitting in the TCP transmit queue on socket
* close. This is done to prevent stale data from being sent should
* the network connection be restored before TCP times out.
*/
- sock_no_linger(queue->sock->sk);
+ nvme_tcp_sock_no_linger(queue->sock->sk);
if (so_priority > 0)
- sock_set_priority(queue->sock->sk, so_priority);
+ nvme_tcp_sock_set_priority(queue->sock->sk, so_priority);
/* Set socket type of service */
if (nctrl->opts->tos >= 0)
- ip_sock_set_tos(queue->sock->sk, nctrl->opts->tos);
+ nvme_tcp_sock_set_tos(queue->sock->sk, nctrl->opts->tos);
/* Set 10 seconds timeout for icresp recvmsg */
queue->sock->sk->sk_rcvtimeo = 10 * HZ;
@@ -1864,10 +1905,8 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
if (nctrl->opts->mask & NVMF_OPT_HOST_IFACE) {
char *iface = nctrl->opts->host_iface;
- sockptr_t optval = KERNEL_SOCKPTR(iface);
- ret = sock_setsockopt(queue->sock, SOL_SOCKET, SO_BINDTODEVICE,
- optval, strlen(iface));
+ ret = nvme_tcp_sock_set_bindtodevice(queue->sock->sk, iface);
if (ret) {
dev_err(nctrl->device,
"failed to bind to interface %s queue %d err %d\n",
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v3 2/4] nvme-tcp: unify sockopt with do_sock_setsockopt
2026-08-16 0:59 ` [PATCH v3 2/4] nvme-tcp: " Geliang Tang
@ 2026-08-16 1:16 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-08-16 1:16 UTC (permalink / raw)
To: Geliang Tang; +Cc: mptcp
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Routing internal kernel socket configuration through user-facing do_sock_setsockopt() ignores return values and subjects critical NVMe settings to userspace BPF hooks.
--
--- Patch [2]: [PATCH v3 2/4] nvme-tcp: unify sockopt with do_sock_setsockopt ---
commit 2f6cd2b103bf52f5964e62f02552a246d7faa461
Author: Geliang Tang <geliang@kernel.org>
nvme-tcp: unify sockopt with do_sock_setsockopt
This patch consolidates socket option settings in nvme-tcp by utilizing
the generic do_sock_setsockopt() helper. It converts several direct socket
configuration calls to this unified mechanism.
> diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
> index ce03a0ea4ded7..3bc41a4735d94 100644
> --- a/drivers/nvme/host/tcp.c
> +++ b/drivers/nvme/host/tcp.c
> @@ -1774,6 +1774,47 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
> return ret;
> }
>
> +static void nvme_tcp_sock_no_linger(struct sock *sk)
> +{
> + struct linger ling = { .l_onoff = 1, .l_linger = 0 };
> +
> + do_sock_setsockopt(sk->sk_socket, false, SOL_SOCKET, SO_LINGER,
> + KERNEL_SOCKPTR(&ling), sizeof(ling));
> +}
[Severity: High]
Does routing internal socket configuration through do_sock_setsockopt() expose
these settings to userspace BPF hooks and LSMs?
Since the kernel socket inherits the calling process's cgroup, a
BPF_CGROUP_SETSOCKOPT hook or LSM rule could intercept and deny the
operation. Because the return value is ignored here, would this silently
fail to apply SO_LINGER?
[ ... ]
> +static void nvme_tcp_sock_set_nodelay(struct sock *sk)
> +{
> + int val = 1;
> +
> + do_sock_setsockopt(sk->sk_socket, false, SOL_TCP, TCP_NODELAY,
> + KERNEL_SOCKPTR(&val), sizeof(val));
> +}
[Severity: High]
If do_sock_setsockopt() is intercepted or fails, this also ignores the return
value. Could this leave Nagle's algorithm enabled on a storage protocol,
leading to severe performance regressions?
[ ... ]
> @@ -1819,24 +1860,24 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
> #endif
>
> /* Single syn retry */
> - tcp_sock_set_syncnt(queue->sock->sk, 1);
> + nvme_tcp_sock_set_syncnt(queue->sock->sk, 1);
>
> /* Set TCP no delay */
> - tcp_sock_set_nodelay(queue->sock->sk);
> + nvme_tcp_sock_set_nodelay(queue->sock->sk);
[Severity: High]
Executing these wrappers in sequence without checking for errors means that
failures are silently ignored. Can this result in an incorrectly configured
socket being used for NVMe over TCP connections?
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1786841319.git.tanggeliang@kylinos.cn?part=2
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 3/4] nvmet-tcp: support IPv6 traffic class
2026-08-16 0:59 [PATCH v3 0/4] nvme-tcp: add IPv6 traffic class support Geliang Tang
2026-08-16 0:59 ` [PATCH v3 1/4] nvmet-tcp: unify sockopt with do_sock_setsockopt Geliang Tang
2026-08-16 0:59 ` [PATCH v3 2/4] nvme-tcp: " Geliang Tang
@ 2026-08-16 0:59 ` Geliang Tang
2026-08-16 1:12 ` sashiko-bot
2026-08-16 1:00 ` [PATCH v3 4/4] nvme-tcp: " Geliang Tang
2026-08-16 2:13 ` [PATCH v3 0/4] nvme-tcp: add IPv6 traffic class support MPTCP CI
4 siblings, 1 reply; 9+ messages in thread
From: Geliang Tang @ 2026-08-16 0:59 UTC (permalink / raw)
To: Keith Busch, Jens Axboe, Christoph Hellwig, Sagi Grimberg,
Chaitanya Kulkarni, David Ahern, Ido Schimmel, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Hannes Reinecke, Stanislav Fomichev
Cc: Geliang Tang, linux-nvme, netdev, mptcp
From: Geliang Tang <tanggeliang@kylinos.cn>
Currently, nvmet-tcp only applies the received IPv4 TOS value when setting
up a queue socket, but does not handle the IPv6 traffic class.
Extend the queue socket setup to handle AF_INET6 sockets. Obtain the
traffic class from the IPv6 socket's rcv_flowinfo and apply it through
IPV6_TCLASS using do_sock_setsockopt().
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
drivers/nvme/target/tcp.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index e64592b79257..d34249cf3756 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -1735,6 +1735,20 @@ static void nvmet_tcp_sock_set_tos(struct sock *sk)
KERNEL_SOCKPTR(&tos), sizeof(tos));
}
+static void nvmet_tcp_sock_set_tclass(struct sock *sk)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+ if (sk->sk_family == AF_INET6) {
+ u8 tclass = ip6_tclass(inet6_sk(sk)->rcv_flowinfo);
+
+ if (tclass > 0)
+ do_sock_setsockopt(sk->sk_socket, false, SOL_IPV6,
+ IPV6_TCLASS, KERNEL_SOCKPTR(&tclass),
+ sizeof(tclass));
+ }
+#endif
+}
+
static int nvmet_tcp_set_queue_sock(struct nvmet_tcp_queue *queue)
{
struct socket *sock = queue->sock;
@@ -1762,6 +1776,7 @@ static int nvmet_tcp_set_queue_sock(struct nvmet_tcp_queue *queue)
/* Set socket type of service */
nvmet_tcp_sock_set_tos(sock->sk);
+ nvmet_tcp_sock_set_tclass(sock->sk);
ret = 0;
write_lock_bh(&sock->sk->sk_callback_lock);
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v3 3/4] nvmet-tcp: support IPv6 traffic class
2026-08-16 0:59 ` [PATCH v3 3/4] nvmet-tcp: support IPv6 traffic class Geliang Tang
@ 2026-08-16 1:12 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-08-16 1:12 UTC (permalink / raw)
To: Geliang Tang; +Cc: mptcp
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The nvmet_tcp_sock_set_tclass function attempts to configure the IPv6 Traffic Class by passing a 1-byte length to do_sock_setsockopt. However, do_ipv6_setsockopt rigidly requires the option length to be at least 4 bytes for IPV6_TCLASS. As a result, the operation fails with -EINVAL, which is silently ignored, and the traffic class is never applied.
--
--- Patch [3]: [PATCH v3 3/4] nvmet-tcp: support IPv6 traffic class ---
commit 97f9471c35e4e1cd4f5b7c6f1f3a6b3f8e13683a
Author: Geliang Tang <geliang@kernel.org>
nvmet-tcp: support IPv6 traffic class
Currently, nvmet-tcp only applies the received IPv4 TOS value when setting
up a queue socket, but does not handle the IPv6 traffic class. This patch
extends the queue socket setup to handle AF_INET6 sockets.
> diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
> index e64592b792577..d34249cf37564 100644
> --- a/drivers/nvme/target/tcp.c
> +++ b/drivers/nvme/target/tcp.c
> @@ -1735,6 +1735,20 @@ static void nvmet_tcp_sock_set_tos(struct sock *sk)
> KERNEL_SOCKPTR(&tos), sizeof(tos));
> }
>
> +static void nvmet_tcp_sock_set_tclass(struct sock *sk)
> +{
> +#if IS_ENABLED(CONFIG_IPV6)
> + if (sk->sk_family == AF_INET6) {
> + u8 tclass = ip6_tclass(inet6_sk(sk)->rcv_flowinfo);
> +
> + if (tclass > 0)
> + do_sock_setsockopt(sk->sk_socket, false, SOL_IPV6,
> + IPV6_TCLASS, KERNEL_SOCKPTR(&tclass),
> + sizeof(tclass));
[Severity: Medium]
Will this silently fail to set the traffic class?
Looking at do_ipv6_setsockopt() in net/ipv6/ipv6_sockglue.c, the IPV6_TCLASS
handler explicitly requires a minimum optlen of sizeof(int):
case IPV6_TCLASS:
if (optlen < sizeof(int))
goto e_inval;
Since tclass is a u8, sizeof(tclass) is 1. This causes the internal
setsockopt implementation to reject the option with -EINVAL, leaving the
traffic class unset.
Would it be better to store the traffic class in an int variable before
passing it to do_sock_setsockopt()?
> + }
> +#endif
> +}
> +
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1786841319.git.tanggeliang@kylinos.cn?part=3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 4/4] nvme-tcp: support IPv6 traffic class
2026-08-16 0:59 [PATCH v3 0/4] nvme-tcp: add IPv6 traffic class support Geliang Tang
` (2 preceding siblings ...)
2026-08-16 0:59 ` [PATCH v3 3/4] nvmet-tcp: support IPv6 traffic class Geliang Tang
@ 2026-08-16 1:00 ` Geliang Tang
2026-08-16 1:09 ` sashiko-bot
2026-08-16 2:13 ` [PATCH v3 0/4] nvme-tcp: add IPv6 traffic class support MPTCP CI
4 siblings, 1 reply; 9+ messages in thread
From: Geliang Tang @ 2026-08-16 1:00 UTC (permalink / raw)
To: Keith Busch, Jens Axboe, Christoph Hellwig, Sagi Grimberg,
Chaitanya Kulkarni, David Ahern, Ido Schimmel, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Hannes Reinecke, Stanislav Fomichev
Cc: Geliang Tang, linux-nvme, netdev, mptcp
From: Geliang Tang <tanggeliang@kylinos.cn>
Currently, nvme-tcp host only supports setting the IPv4 TOS value when a
TOS is specified, but does not handle the IPv6 traffic class.
Extend the queue socket setup to handle AF_INET6 sockets by applying the
TOS value to both IPv4 and IPv6 sockets. For IPv6, the TOS value is set
as the IPv6 traffic class via IPV6_TCLASS using do_sock_setsockopt().
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
drivers/nvme/host/tcp.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index 89a82e8248d2..657acae9e4a4 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -1815,6 +1815,15 @@ static void nvme_tcp_sock_set_tos(struct sock *sk, int tos)
KERNEL_SOCKPTR(&tos), sizeof(tos));
}
+static void nvme_tcp_sock_set_tclass(struct sock *sk, int tclass)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+ if (sk->sk_family == AF_INET6)
+ do_sock_setsockopt(sk->sk_socket, false, SOL_IPV6, IPV6_TCLASS,
+ KERNEL_SOCKPTR(&tclass), sizeof(tclass));
+#endif
+}
+
static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
key_serial_t pskid)
{
@@ -1876,8 +1885,10 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
nvme_tcp_sock_set_priority(queue->sock->sk, so_priority);
/* Set socket type of service */
- if (nctrl->opts->tos >= 0)
+ if (nctrl->opts->tos >= 0) {
nvme_tcp_sock_set_tos(queue->sock->sk, nctrl->opts->tos);
+ nvme_tcp_sock_set_tclass(queue->sock->sk, nctrl->opts->tos);
+ }
/* Set 10 seconds timeout for icresp recvmsg */
queue->sock->sk->sk_rcvtimeo = 10 * HZ;
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v3 4/4] nvme-tcp: support IPv6 traffic class
2026-08-16 1:00 ` [PATCH v3 4/4] nvme-tcp: " Geliang Tang
@ 2026-08-16 1:09 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-08-16 1:09 UTC (permalink / raw)
To: Geliang Tang; +Cc: mptcp
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The NVMe TCP target silently fails to set the IPv6 traffic class because it passes a 1-byte option length for IPV6_TCLASS.
--
--- Patch [4]: [PATCH v3 4/4] nvme-tcp: support IPv6 traffic class ---
commit f06d75be38a565495a1d84b7e856f1a1a552b88e
Author: Geliang Tang <geliang@kernel.org>
nvme-tcp: support IPv6 traffic class
This commit extends the NVMe TCP host queue socket setup to support the IPv6
traffic class. It applies the TOS value to IPv6 sockets via the IPV6_TCLASS
socket option.
> diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
> index 3bc41a4735d94..feedd46bd3a2b 100644
> --- a/drivers/nvme/host/tcp.c
> +++ b/drivers/nvme/host/tcp.c
[ ... ]
> @@ -1815,6 +1815,15 @@ static void nvme_tcp_sock_set_tos(struct sock *sk, int tos)
> KERNEL_SOCKPTR(&tos), sizeof(tos));
> }
>
> +static void nvme_tcp_sock_set_tclass(struct sock *sk, int tclass)
> +{
> +#if IS_ENABLED(CONFIG_IPV6)
> + if (sk->sk_family == AF_INET6)
> + do_sock_setsockopt(sk->sk_socket, false, SOL_IPV6, IPV6_TCLASS,
> + KERNEL_SOCKPTR(&tclass), sizeof(tclass));
While reviewing this patch, I noticed a related bug in the target implementation
which handles this exact same logic.
In drivers/nvme/target/tcp.c:nvmet_tcp_sock_set_tclass():
u8 tclass = ip6_tclass(inet6_sk(sk)->rcv_flowinfo);
if (tclass > 0)
do_sock_setsockopt(sk->sk_socket, false, SOL_IPV6,
IPV6_TCLASS, KERNEL_SOCKPTR(&tclass),
sizeof(tclass));
^^^^^^^^^^^^^^
[Severity: Medium]
Will this setsockopt call fail silently in the target code?
The tclass variable is declared as a u8, so sizeof(tclass) evaluates to 1. The
IPv6 networking core strictly requires an option length of at least 4 bytes for
IPV6_TCLASS.
Passing sizeof(u8) causes do_ipv6_setsockopt() to return -EINVAL, which means
the IPv6 traffic class is silently ignored instead of being applied to the
socket, leading to incorrect QoS behavior without alerting the user.
Does the target code need to be updated to pass a 4-byte length?
> +#endif
> +}
> +
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1786841319.git.tanggeliang@kylinos.cn?part=4
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 0/4] nvme-tcp: add IPv6 traffic class support
2026-08-16 0:59 [PATCH v3 0/4] nvme-tcp: add IPv6 traffic class support Geliang Tang
` (3 preceding siblings ...)
2026-08-16 1:00 ` [PATCH v3 4/4] nvme-tcp: " Geliang Tang
@ 2026-08-16 2:13 ` MPTCP CI
4 siblings, 0 replies; 9+ messages in thread
From: MPTCP CI @ 2026-08-16 2:13 UTC (permalink / raw)
To: Geliang Tang; +Cc: mptcp
Hi Geliang,
Thank you for your modifications, that's great!
Our CI did some validations and here is its report:
- KVM Validation: normal (except selftest_mptcp_join): Success! ✅
- KVM Validation: normal (only selftest_mptcp_join): Success! ✅
- KVM Validation: debug (except selftest_mptcp_join): Success! ✅
- KVM Validation: debug (only selftest_mptcp_join): Success! ✅
- KVM Validation: btf-normal (only bpftest_all): Success! ✅
- KVM Validation: btf-debug (only bpftest_all): Success! ✅
- Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/31919377372
Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/58af0bc691a8
Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=1146638
If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:
$ cd [kernel source code]
$ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
--pull always mptcp/mptcp-upstream-virtme-docker:latest \
auto-normal
For more details:
https://github.com/multipath-tcp/mptcp-upstream-virtme-docker
Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)
Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)
^ permalink raw reply [flat|nested] 9+ messages in thread