Netdev List
 help / color / mirror / Atom feed
From: Geliang Tang <geliang@kernel.org>
To: Jakub Kicinski <kuba@kernel.org>,
	Matthieu Baerts <matttbe@kernel.org>,
	 Nilay Shroff <nilay@linux.ibm.com>,
	Hannes Reinecke <hare@suse.de>, Christoph Hellwig <hch@lst.de>
Cc: Keith Busch <kbusch@kernel.org>, Jens Axboe <axboe@kernel.dk>,
	Sagi Grimberg <sagi@grimberg.me>,
	Chaitanya Kulkarni <kch@nvidia.com>,
	Mat Martineau <martineau@kernel.org>,
	 "David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
	Shuah Khan <shuah@kernel.org>,
	Geliang Tang <tanggeliang@kylinos.cn>,
		linux-nvme@lists.infradead.org, netdev@vger.kernel.org,
	mptcp@lists.linux.dev,  linux-kselftest@vger.kernel.org,
	John Meneghini <jmeneghi@redhat.com>,
	Randy Jennings <randyj@purestorage.com>,
	zhenwei pi <zhenwei.pi@linux.dev>, Hui Zhu <zhuhui@kylinos.cn>,
	 Gang Yan <yangang@kylinos.cn>
Subject: Re: [PATCH 02/11] nvmet-tcp: implement accept mptcp proto
Date: Wed, 29 Jul 2026 13:17:10 +0800	[thread overview]
Message-ID: <10356f7d8b0ffdba27987c79fc7f4b7574cf873b.camel@kernel.org> (raw)
In-Reply-To: <4df03cad08088fba7fb49beaeb6513cef5b87c2b.camel@kernel.org>

Hi,

Thank you all very much for your interest in "NVMe over MPTCP" and for
adding review comments to this version of the series. This has been
very helpful to me. There are indeed some issues with this version, but
the good news is that I have recently found a direction for improving
it.

On Fri, 2026-05-29 at 22:20 +0800, Geliang Tang wrote:
> Hi Jakub,
> 
> On Thu, 2026-05-28 at 08:23 -0700, Jakub Kicinski wrote:
> > On Thu, 28 May 2026 11:10:36 +0800 Geliang Tang wrote:
> > > Dedicated MPTCP helpers are introduced for setting accept socket
> > > options.
> > > These helpers (no_linger, set_priority, set_tos) set the values
> > > on
> > > all
> > > existing subflows using mptcp_for_each_subflow(). The values are
> > > then
> > > synchronized to other newly created subflows in
> > > sync_socket_options().
> > 
> > These are not protocol specific options, why do we have to export
> > MPTCP-specific functions for them?
> 
> Thank you for reading the code. In addition to the three MPTCP-
> specific
> functions implemented in this patch, I have implemented and exported
> the following six MPTCP-specific functions throughout the series:
> 
>     void mptcp_sock_set_nodelay(struct sock *sk)
>     int mptcp_sock_set_syncnt(struct sock *sk, int val)
>     void mptcp_sock_set_tos(struct sock *sk, int val)
>     void mptcp_sock_no_linger(struct sock *sk)
>     void mptcp_sock_set_priority(struct sock *sk, u32 priority)
>     void mptcp_sock_set_reuseaddr(struct sock *sk)
> 
> These correspond to the following six functions originally used for
> TCP:
> 
>     tcp_sock_set_nodelay()
>     tcp_sock_set_syncnt()
>     ip_sock_set_tos()
>     sock_no_linger()
>     sock_set_priority()
>     sock_set_reuseaddr()

Here I missed one option, SO_BINDTODEVICE. Currently, NVMe TCP sets 7
sockopts: TCP_NODELAY, TCP_SYNCNT, IP_TOS, SO_LINGER, SO_PRIORITY,
SO_REUSEADDR, and SO_BINDTODEVICE. The first 6 are called through the
following 6 functions:

    tcp_sock_set_nodelay()
    tcp_sock_set_syncnt()
    ip_sock_set_tos()
    sock_no_linger()
    sock_set_priority()
    sock_set_reuseaddr()

The last one is called through sock_setsockopt:

    ret = sock_setsockopt(queue->sock, SOL_SOCKET, SO_BINDTODEVICE,
                          optval, strlen(iface));

In NVMe TCP, the first three - TCP_NODELAY, TCP_SYNCNT, IP_TOS - are
protocol-specific, while the last four - SO_LINGER, SO_PRIORITY,
SO_REUSEADDR, SO_BINDTODEVICE - are protocol-independent.

When we add NVMe MPTCP support, all sockets created when using NVMe
MPTCP are MPTCP sockets. Using the above functions to set sockopts on
MPTCP sockets will not succeed. The implementations of these 7 sockopts
for MPTCP are all protocol-specific. MPTCP needs to set the sockopts
not only on the MPTCP socket itself but also synchronize them to all
subflow sockets, so that the sockopts actually take effect.

Therefore, in this version, I defined MPTCP-specific sockopt functions
for each option, and switched between TCP and MPTCP by defining the
struct nvmet_tcp_proto and struct nvme_tcp_proto structures.



A better design is to initiate protocol-specific sockopt settings from
the NVMe side by calling the sock_common_setsockopt() function. This
can automatically select the appropriate protocol and call each
protocol's .setsockopt implementation to set the sockopt, thus making
it compatible with both TCP and MPTCP, without needing to export
functions from the TCP or MPTCP side for NVMe to use.

For MPTCP, all 7 sockopt functions can be implemented by passing each
sockopt to sock_common_setsockopt(), similar to:

static void nvmet_tcp_sock_no_linger(struct sock *sk) 
{
    struct linger ling = { .l_onoff = 1, .l_linger = 0 }; 

    sock_common_setsockopt(sk->sk_socket, false, SOL_SOCKET, SO_LINGER,
                           KERNEL_SOCKPTR(&ling), sizeof(ling));
}

However, for TCP, the three protocol-specific options - TCP_NODELAY,
TCP_SYNCNT, IP_TOS - can be implemented by calling
sock_common_setsockopt(), but the other four protocol-independent ones
need to be called through sock_setsockopt(). To hide this difference,
we can call the higher-level do_sock_setsockopt() function instead,
like:

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));
}

In this way, this wrapper becomes protocol-independent and works
correctly for both TCP and MPTCP. Moreover, all 7 functions are
uniformly converted into wrappers that call do_sock_setsockopt(), so
every one of them becomes protocol-independent without needing to
distinguish between TCP and MPTCP internally.

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, int tos) 
{
    do_sock_setsockopt(sk->sk_socket, false, SOL_IP, IP_TOS,
                       KERNEL_SOCKPTR(&tos), sizeof(tos));
}

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 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));
}

With this approach, there is no longer any need to define structures
like struct nvmet_tcp_proto and struct nvme_tcp_proto, nor to export
special set-sockopt functions from the MPTCP side. We only need to
define these 7 wrappers for NVMe, and then replace the original
function calls with the wrapper calls to enable MPTCP support. For
example:

-   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);



With these changes, implementing NVMe MPTCP support is simplified to
just choosing which type of socket to create at socket creation time.
In addition, I am also pushing the company I work for to join the NVMe
membership, in preparation for submitting an MPTCP proposal to the NVMe
technical working group in the future.




I'm thinking that this approach of unifying NVMe sockopts via
do_sock_setsockopt() could actually serve as a general improvement, and
it would be valid even independently of this MPTCP series. If no one
objects, I will send these patches of do_sock_setsockopt() improvement
to the NVMe mailing list for review in the near future.



Thanks,
-Geliang

> 
> The first two functions - tcp_sock_set_nodelay() and
> tcp_sock_set_syncnt() - cannot be directly used with an MPTCP socket.
> In fact, passing an MPTCP socket to tcp_sock_set_nodelay() even
> causes
> a crash. Therefore I implemented these two MPTCP-specific functions.
> Actually, a better approach would be to add protocol-independent
> sock_set_nodelay() and sock_set_syncnt() in net/core/sock.c.
> 
> The third function, ip_sock_set_tos(), takes different arguments for
> TCP vs. MPTCP. For MPTCP, it needs to pass inet_sk(msk->first)-
> > rcv_tos, so I implemented an MPTCP-specific function.
> 
> The last three functions - sock_no_linger(), sock_set_priority(), and
> sock_set_reuseaddr() - are not protocol-specific, but attributes set
> on
> the MPTCP socket cannot be synchronized to its subflows because
> mptcp_sockopt_sync_locked() checks msk->setsockopt_seq. Thus I
> implemented these three MPTCP-specific functions, explicitly calling
> sockopt_seq_inc(msk) inside them to increment msk->setsockopt_seq, so
> that mptcp_sockopt_sync_locked() can properly synchronize the
> attributes to all subflows. There should be a better solution for
> this,
> and I will discuss it with @Matt.
> 
> Please give me some advice.
> 
> Thanks,
> -Geliang

  reply	other threads:[~2026-07-29  5:17 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-28  3:10 [PATCH 00/11] NVMe over MPTCP Geliang Tang
2026-05-28  3:10 ` [PATCH 01/11] nvmet-tcp: define accept tcp_proto struct Geliang Tang
2026-05-28  3:10 ` [PATCH 02/11] nvmet-tcp: implement accept mptcp proto Geliang Tang
2026-05-28 15:23   ` Jakub Kicinski
2026-05-29 14:20     ` Geliang Tang
2026-07-29  5:17       ` Geliang Tang [this message]
2026-05-31 14:56   ` Nilay Shroff
2026-05-28  3:10 ` [PATCH 03/11] nvmet-tcp: define listen socket ops Geliang Tang
2026-05-28  3:10 ` [PATCH 04/11] nvmet-tcp: register target mptcp transport Geliang Tang
2026-05-28  3:10 ` [PATCH 05/11] nvmet-tcp: implement mptcp listen socket ops Geliang Tang
2026-05-31 15:01   ` Nilay Shroff
2026-05-28  3:10 ` [PATCH 06/11] nvme-fabrics: compare transport in ip_options_match Geliang Tang
2026-05-28  3:10 ` [PATCH 07/11] nvme-tcp: define host tcp_proto struct Geliang Tang
2026-05-28  3:10 ` [PATCH 08/11] nvme-tcp: register host mptcp transport Geliang Tang
2026-05-28  3:10 ` [PATCH 09/11] nvme-tcp: implement host mptcp proto Geliang Tang
2026-05-31 15:08   ` Nilay Shroff
2026-05-28  3:10 ` [PATCH 10/11] selftests: mptcp: add nvme over mptcp test Geliang Tang
2026-05-28  3:10 ` [PATCH 11/11] selftests: mptcp: nvme: add iopolicy tests Geliang Tang
2026-05-31 14:04   ` Nilay Shroff
2026-05-31 14:50     ` Nilay Shroff
2026-05-28  8:42 ` [PATCH 00/11] NVMe over MPTCP Christoph Hellwig
2026-05-29 14:31   ` Geliang Tang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=10356f7d8b0ffdba27987c79fc7f4b7574cf873b.camel@kernel.org \
    --to=geliang@kernel.org \
    --cc=axboe@kernel.dk \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=hare@suse.de \
    --cc=hch@lst.de \
    --cc=horms@kernel.org \
    --cc=jmeneghi@redhat.com \
    --cc=kbusch@kernel.org \
    --cc=kch@nvidia.com \
    --cc=kuba@kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-nvme@lists.infradead.org \
    --cc=martineau@kernel.org \
    --cc=matttbe@kernel.org \
    --cc=mptcp@lists.linux.dev \
    --cc=netdev@vger.kernel.org \
    --cc=nilay@linux.ibm.com \
    --cc=pabeni@redhat.com \
    --cc=randyj@purestorage.com \
    --cc=sagi@grimberg.me \
    --cc=shuah@kernel.org \
    --cc=tanggeliang@kylinos.cn \
    --cc=yangang@kylinos.cn \
    --cc=zhenwei.pi@linux.dev \
    --cc=zhuhui@kylinos.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox