* [RFC mptcp-next v12 01/15] tls: introduce struct tls_prot_ops
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 02/15] tls: add tls_prot_ops pointer to tls_context Geliang Tang
` (15 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Gang Yan
From: Geliang Tang <tanggeliang@kylinos.cn>
To extend MPTCP support based on TCP TLS, a tls_prot_ops structure has
been introduced for TLS, encapsulating TCP-specific helpers within this
structure.
Add registering, validating and finding functions for this structure to
add, validate and find a tls_prot_ops on the global list tls_prot_ops_list.
Register TCP-specific structure tls_tcp_ops in tls_init().
Co-developed-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
include/net/tls.h | 20 +++++++++++
net/tls/tls_main.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 109 insertions(+)
diff --git a/include/net/tls.h b/include/net/tls.h
index ebd2550280ae..cf85f7a0c931 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -220,6 +220,26 @@ struct tls_prot_info {
u16 tail_size;
};
+struct tls_prot_ops {
+ int protocol;
+ struct module *owner;
+ struct list_head list;
+
+ int (*inq)(struct sock *sk);
+ int (*sendmsg_locked)(struct sock *sk, struct msghdr *msg, size_t size);
+ struct sk_buff *(*recv_skb)(struct sock *sk, u32 *off);
+ bool (*lock_is_held)(struct sock *sk);
+ int (*read_sock)(struct sock *sk, read_descriptor_t *desc,
+ sk_read_actor_t recv_actor);
+ void (*read_done)(struct sock *sk, size_t len);
+ u32 (*get_skb_off)(struct sk_buff *skb);
+ u32 (*get_skb_seq)(struct sk_buff *skb);
+ __poll_t (*poll)(struct file *file, struct socket *sock,
+ struct poll_table_struct *wait);
+ bool (*epollin_ready)(const struct sock *sk);
+ void (*check_app_limited)(struct sock *sk);
+};
+
struct tls_context {
/* read-only cache line */
struct tls_prot_info prot_info;
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index fd39acf41a61..5ee7c7d60942 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -128,6 +128,24 @@ static struct proto_ops tls_proto_ops[TLS_NUM_PROTS][TLS_NUM_CONFIG][TLS_NUM_CON
static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG],
const struct proto *base);
+static DEFINE_SPINLOCK(tls_prot_ops_lock);
+static LIST_HEAD(tls_prot_ops_list);
+
+/* Must be called with rcu read lock held */
+static struct tls_prot_ops *tls_prot_ops_find(int protocol)
+{
+ struct tls_prot_ops *ops, *ret = NULL;
+
+ list_for_each_entry_rcu(ops, &tls_prot_ops_list, list) {
+ if (ops->protocol == protocol) {
+ ret = ops;
+ break;
+ }
+ }
+
+ return ret;
+}
+
void update_sk_prot(struct sock *sk, struct tls_context *ctx)
{
int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4;
@@ -1236,6 +1254,75 @@ static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = {
.get_info_size = tls_get_info_size,
};
+static int tls_validate_prot_ops(const struct tls_prot_ops *ops)
+{
+ if (!ops->inq || !ops->sendmsg_locked ||
+ !ops->recv_skb || !ops->lock_is_held ||
+ !ops->read_sock || !ops->read_done ||
+ !ops->get_skb_seq ||
+ !ops->poll || !ops->epollin_ready ||
+ !ops->check_app_limited) {
+ pr_err("%d does not implement required ops\n", ops->protocol);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tls_register_prot_ops(struct tls_prot_ops *ops)
+{
+ int ret;
+
+ ret = tls_validate_prot_ops(ops);
+ if (ret)
+ return ret;
+
+ spin_lock(&tls_prot_ops_lock);
+ if (tls_prot_ops_find(ops->protocol)) {
+ spin_unlock(&tls_prot_ops_lock);
+ return -EEXIST;
+ }
+ list_add_tail_rcu(&ops->list, &tls_prot_ops_list);
+ spin_unlock(&tls_prot_ops_lock);
+
+ pr_debug("tls_prot_ops %d registered\n", ops->protocol);
+ return 0;
+}
+
+static struct sk_buff *tls_tcp_recv_skb(struct sock *sk, u32 *off)
+{
+ return tcp_recv_skb(sk, tcp_sk(sk)->copied_seq, off);
+}
+
+static bool tls_tcp_lock_is_held(struct sock *sk)
+{
+ return sock_owned_by_user_nocheck(sk);
+}
+
+static u32 tls_tcp_get_skb_seq(struct sk_buff *skb)
+{
+ return TCP_SKB_CB(skb)->seq;
+}
+
+static bool tls_tcp_epollin_ready(const struct sock *sk)
+{
+ return tcp_epollin_ready(sk, INT_MAX);
+}
+
+static struct tls_prot_ops tls_tcp_ops = {
+ .protocol = IPPROTO_TCP,
+ .inq = tcp_inq,
+ .sendmsg_locked = tcp_sendmsg_locked,
+ .recv_skb = tls_tcp_recv_skb,
+ .lock_is_held = tls_tcp_lock_is_held,
+ .read_sock = tcp_read_sock,
+ .read_done = tcp_read_done,
+ .get_skb_seq = tls_tcp_get_skb_seq,
+ .poll = tcp_poll,
+ .epollin_ready = tls_tcp_epollin_ready,
+ .check_app_limited = tcp_rate_check_app_limited,
+};
+
static int __init tls_register(void)
{
int err;
@@ -1254,6 +1341,8 @@ static int __init tls_register(void)
tcp_register_ulp(&tcp_tls_ulp_ops);
+ tls_register_prot_ops(&tls_tcp_ops);
+
return 0;
err_strp:
tls_strp_dev_exit();
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 02/15] tls: add tls_prot_ops pointer to tls_context
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 01/15] tls: introduce struct tls_prot_ops Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 03/15] tls: add skb offset check for mptcp Geliang Tang
` (14 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Gang Yan
From: Geliang Tang <tanggeliang@kylinos.cn>
A pointer to struct tls_prot_ops, named 'ops', has been added to struct
tls_context. The places originally calling TLS-specific helpers have now
been modified to indirectly invoke them via 'ops' pointer in tls_context.
In do_tls_setsockopt_conf(), ctx->ops is assigned either 'tls_mptcp_ops'
or 'tls_tcp_ops' based on the socket protocol.
Co-developed-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
include/net/tls.h | 1 +
net/tls/tls_main.c | 15 +++++++++++----
net/tls/tls_strp.c | 33 ++++++++++++++++++++++-----------
net/tls/tls_sw.c | 7 +++++--
4 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/include/net/tls.h b/include/net/tls.h
index cf85f7a0c931..e323bfdeba4f 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -278,6 +278,7 @@ struct tls_context {
struct sock *sk;
void (*sk_destruct)(struct sock *sk);
+ const struct tls_prot_ops *ops;
union tls_crypto_context crypto_send;
union tls_crypto_context crypto_recv;
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index 5ee7c7d60942..5f324887390d 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -206,13 +206,13 @@ int tls_push_sg(struct sock *sk,
ctx->splicing_pages = true;
while (1) {
/* is sending application-limited? */
- tcp_rate_check_app_limited(sk);
+ ctx->ops->check_app_limited(sk);
p = sg_page(sg);
retry:
bvec_set_page(&bvec, p, size, offset);
iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, size);
- ret = tcp_sendmsg_locked(sk, &msg, size);
+ ret = ctx->ops->sendmsg_locked(sk, &msg, size);
if (ret != size) {
if (ret > 0) {
@@ -427,14 +427,14 @@ static __poll_t tls_sk_poll(struct file *file, struct socket *sock,
u8 shutdown;
int state;
- mask = tcp_poll(file, sock, wait);
+ tls_ctx = tls_get_ctx(sk);
+ mask = tls_ctx->ops->poll(file, sock, wait);
state = inet_sk_state_load(sk);
shutdown = READ_ONCE(sk->sk_shutdown);
if (unlikely(state != TCP_ESTABLISHED || shutdown & RCV_SHUTDOWN))
return mask;
- tls_ctx = tls_get_ctx(sk);
ctx = tls_sw_ctx_rx(tls_ctx);
psock = sk_psock_get(sk);
@@ -1094,6 +1094,13 @@ static int tls_init(struct sock *sk)
ctx->tx_conf = TLS_BASE;
ctx->rx_conf = TLS_BASE;
ctx->tx_max_payload_len = TLS_MAX_PAYLOAD_SIZE;
+ ctx->ops = tls_prot_ops_find(sk->sk_protocol);
+ if (!ctx->ops) {
+ tls_ctx_free(sk, ctx);
+ inet_csk(sk)->icsk_ulp_ops = NULL;
+ rc = -EINVAL;
+ goto out;
+ }
update_sk_prot(sk, ctx);
out:
write_unlock_bh(&sk->sk_callback_lock);
diff --git a/net/tls/tls_strp.c b/net/tls/tls_strp.c
index 98e12f0ff57e..71f44bf9ed59 100644
--- a/net/tls/tls_strp.c
+++ b/net/tls/tls_strp.c
@@ -120,6 +120,7 @@ struct sk_buff *tls_strp_msg_detach(struct tls_sw_context_rx *ctx)
int tls_strp_msg_cow(struct tls_sw_context_rx *ctx)
{
struct tls_strparser *strp = &ctx->strp;
+ struct tls_context *tls_ctx;
struct sk_buff *skb;
if (strp->copy_mode)
@@ -132,7 +133,8 @@ int tls_strp_msg_cow(struct tls_sw_context_rx *ctx)
tls_strp_anchor_free(strp);
strp->anchor = skb;
- tcp_read_done(strp->sk, strp->stm.full_len);
+ tls_ctx = tls_get_ctx(strp->sk);
+ tls_ctx->ops->read_done(strp->sk, strp->stm.full_len);
strp->copy_mode = 1;
return 0;
@@ -376,6 +378,7 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
static int tls_strp_read_copyin(struct tls_strparser *strp)
{
+ struct tls_context *ctx = tls_get_ctx(strp->sk);
read_descriptor_t desc;
desc.arg.data = strp;
@@ -383,13 +386,14 @@ static int tls_strp_read_copyin(struct tls_strparser *strp)
desc.count = 1; /* give more than one skb per call */
/* sk should be locked here, so okay to do read_sock */
- tcp_read_sock(strp->sk, &desc, tls_strp_copyin);
+ ctx->ops->read_sock(strp->sk, &desc, tls_strp_copyin);
return desc.error;
}
static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort)
{
+ struct tls_context *ctx = tls_get_ctx(strp->sk);
struct skb_shared_info *shinfo;
struct page *page;
int need_spc, len;
@@ -398,7 +402,7 @@ static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort)
* to read the data out. Otherwise the connection will stall.
* Without pressure threshold of INT_MAX will never be ready.
*/
- if (likely(qshort && !tcp_epollin_ready(strp->sk, INT_MAX)))
+ if (likely(qshort && !ctx->ops->epollin_ready(strp->sk)))
return 0;
shinfo = skb_shinfo(strp->anchor);
@@ -434,12 +438,13 @@ static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort)
static bool tls_strp_check_queue_ok(struct tls_strparser *strp)
{
unsigned int len = strp->stm.offset + strp->stm.full_len;
+ struct tls_context *ctx = tls_get_ctx(strp->sk);
struct sk_buff *first, *skb;
u32 seq;
first = skb_shinfo(strp->anchor)->frag_list;
skb = first;
- seq = TCP_SKB_CB(first)->seq;
+ seq = ctx->ops->get_skb_seq(first);
/* Make sure there's no duplicate data in the queue,
* and the decrypted status matches.
@@ -449,7 +454,7 @@ static bool tls_strp_check_queue_ok(struct tls_strparser *strp)
len -= skb->len;
skb = skb->next;
- if (TCP_SKB_CB(skb)->seq != seq)
+ if (ctx->ops->get_skb_seq(skb) != seq)
return false;
if (skb_cmp_decrypted(first, skb))
return false;
@@ -460,11 +465,11 @@ static bool tls_strp_check_queue_ok(struct tls_strparser *strp)
static void tls_strp_load_anchor_with_queue(struct tls_strparser *strp, int len)
{
- struct tcp_sock *tp = tcp_sk(strp->sk);
+ struct tls_context *ctx = tls_get_ctx(strp->sk);
struct sk_buff *first;
u32 offset;
- first = tcp_recv_skb(strp->sk, tp->copied_seq, &offset);
+ first = ctx->ops->recv_skb(strp->sk, &offset);
if (WARN_ON_ONCE(!first))
return;
@@ -483,6 +488,7 @@ static void tls_strp_load_anchor_with_queue(struct tls_strparser *strp, int len)
bool tls_strp_msg_load(struct tls_strparser *strp, bool force_refresh)
{
+ struct tls_context *ctx = tls_get_ctx(strp->sk);
struct strp_msg *rxm;
struct tls_msg *tlm;
@@ -490,7 +496,7 @@ bool tls_strp_msg_load(struct tls_strparser *strp, bool force_refresh)
DEBUG_NET_WARN_ON_ONCE(!strp->stm.full_len);
if (!strp->copy_mode && force_refresh) {
- if (unlikely(tcp_inq(strp->sk) < strp->stm.full_len)) {
+ if (unlikely(ctx->ops->inq(strp->sk) < strp->stm.full_len)) {
WRITE_ONCE(strp->msg_ready, 0);
memset(&strp->stm, 0, sizeof(strp->stm));
return false;
@@ -511,9 +517,10 @@ bool tls_strp_msg_load(struct tls_strparser *strp, bool force_refresh)
/* Called with lock held on lower socket */
static int tls_strp_read_sock(struct tls_strparser *strp)
{
+ struct tls_context *ctx = tls_get_ctx(strp->sk);
int sz, inq;
- inq = tcp_inq(strp->sk);
+ inq = ctx->ops->inq(strp->sk);
if (inq < 1)
return 0;
@@ -556,6 +563,8 @@ void tls_strp_check_rcv(struct tls_strparser *strp)
/* Lower sock lock held */
void tls_strp_data_ready(struct tls_strparser *strp)
{
+ struct tls_context *ctx = tls_get_ctx(strp->sk);
+
/* This check is needed to synchronize with do_tls_strp_work.
* do_tls_strp_work acquires a process lock (lock_sock) whereas
* the lock held here is bh_lock_sock. The two locks can be
@@ -563,7 +572,7 @@ void tls_strp_data_ready(struct tls_strparser *strp)
* allows a thread in BH context to safely check if the process
* lock is held. In this case, if the lock is held, queue work.
*/
- if (sock_owned_by_user_nocheck(strp->sk)) {
+ if (ctx->ops->lock_is_held(strp->sk)) {
queue_work(tls_strp_wq, &strp->work);
return;
}
@@ -583,10 +592,12 @@ static void tls_strp_work(struct work_struct *w)
void tls_strp_msg_done(struct tls_strparser *strp)
{
+ struct tls_context *ctx = tls_get_ctx(strp->sk);
+
WARN_ON(!strp->stm.full_len);
if (likely(!strp->copy_mode))
- tcp_read_done(strp->sk, strp->stm.full_len);
+ ctx->ops->read_done(strp->sk, strp->stm.full_len);
else
tls_strp_flush_anchor_copy(strp);
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 20f8fc84c5f5..ad8066c2e248 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -1953,13 +1953,14 @@ tls_read_flush_backlog(struct sock *sk, struct tls_prot_info *prot,
size_t len_left, size_t decrypted, ssize_t done,
size_t *flushed_at)
{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
size_t max_rec;
if (len_left <= decrypted)
return false;
max_rec = prot->overhead_size - prot->tail_size + TLS_MAX_PAYLOAD_SIZE;
- if (done - *flushed_at < SZ_128K && tcp_inq(sk) > max_rec)
+ if (done - *flushed_at < SZ_128K && tls_ctx->ops->inq(sk) > max_rec)
return false;
*flushed_at = done;
@@ -2445,6 +2446,7 @@ int tls_rx_msg_size(struct tls_strparser *strp, struct sk_buff *skb)
size_t cipher_overhead;
size_t data_len = 0;
int ret;
+ u32 seq;
/* Verify that we have a full TLS header, or wait for more data */
if (strp->stm.offset + prot->prepend_size > skb->len)
@@ -2487,8 +2489,9 @@ int tls_rx_msg_size(struct tls_strparser *strp, struct sk_buff *skb)
goto read_failure;
}
+ seq = tls_ctx->ops->get_skb_seq(skb);
tls_device_rx_resync_new_rec(strp->sk, data_len + TLS_HEADER_SIZE,
- TCP_SKB_CB(skb)->seq + strp->stm.offset);
+ seq + strp->stm.offset);
return data_len + TLS_HEADER_SIZE;
read_failure:
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 03/15] tls: add skb offset check for mptcp
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 01/15] tls: introduce struct tls_prot_ops Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 02/15] tls: add tls_prot_ops pointer to tls_context Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 04/15] mptcp: update mptcp_check_readable Geliang Tang
` (13 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Gang Yan, Geliang Tang
From: Gang Yan <yangang@kylinos.cn>
In MPTCP, subflow SKBs can have non-zero offsets due to out-of-order
handling or partial delivery. When walking the TLS strp queue for
sequence and decryption checks, validate each SKB's offset except the
first using get_skb_off() to ensure queue consistency. This is specific
to MPTCP, as TCP does not require offset checks.
If any invalid offset is found, return false to trigger resynchronization.
Co-developed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
---
net/tls/tls_strp.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/tls/tls_strp.c b/net/tls/tls_strp.c
index 71f44bf9ed59..feef440d49fd 100644
--- a/net/tls/tls_strp.c
+++ b/net/tls/tls_strp.c
@@ -454,6 +454,9 @@ static bool tls_strp_check_queue_ok(struct tls_strparser *strp)
len -= skb->len;
skb = skb->next;
+ if (ctx->ops->get_skb_off &&
+ ctx->ops->get_skb_off(skb))
+ return false;
if (ctx->ops->get_skb_seq(skb) != seq)
return false;
if (skb_cmp_decrypted(first, skb))
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 04/15] mptcp: update mptcp_check_readable
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (2 preceding siblings ...)
2026-04-02 7:47 ` [RFC mptcp-next v12 03/15] tls: add skb offset check for mptcp Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 05/15] mptcp: implement tls_mptcp_ops Geliang Tang
` (12 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Gang Yan, Geliang Tang
From: Gang Yan <yangang@kylinos.cn>
This patch makes mptcp_check_readable() aligned with TCP, and renames it to
mptcp_stream_is_readable(). It will be used in the case of KTLS, because
'prot' will be modified, tls_sw_sock_is_readable() is expected to be called
from prot->sock_is_readable().
Co-developed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
---
net/mptcp/protocol.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 3630a230be53..975c54f36f7a 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -3322,9 +3322,11 @@ void __mptcp_unaccepted_force_close(struct sock *sk)
__mptcp_destroy_sock(sk);
}
-static __poll_t mptcp_check_readable(struct sock *sk)
+static bool mptcp_stream_is_readable(struct sock *sk)
{
- return mptcp_epollin_ready(sk) ? EPOLLIN | EPOLLRDNORM : 0;
+ if (mptcp_epollin_ready(sk))
+ return true;
+ return sk_is_readable(sk);
}
static void mptcp_check_listen_stop(struct sock *sk)
@@ -4386,7 +4388,8 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
if (state != TCP_SYN_SENT && state != TCP_SYN_RECV) {
- mask |= mptcp_check_readable(sk);
+ if (mptcp_stream_is_readable(sk))
+ mask |= EPOLLIN | EPOLLRDNORM;
if (shutdown & SEND_SHUTDOWN)
mask |= EPOLLOUT | EPOLLWRNORM;
else
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 05/15] mptcp: implement tls_mptcp_ops
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (3 preceding siblings ...)
2026-04-02 7:47 ` [RFC mptcp-next v12 04/15] mptcp: update mptcp_check_readable Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 06/15] tls: disable device offload for mptcp sockets Geliang Tang
` (11 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Gang Yan
From: Geliang Tang <tanggeliang@kylinos.cn>
This patch implements the MPTCP-specific struct tls_prot_ops, named
'tls_mptcp_ops'.
Note that there is a slight difference between mptcp_inq() and
mptcp_inq_hint(), it does not return 1 when the socket is closed or
shut down; instead, it returns 0. Otherwise, it would break the
condition "inq < 1" in tls_strp_read_sock().
Passing an MPTCP socket to tcp_sock_rate_check_app_limited() can
trigger a crash. Here, an MPTCP version of check_app_limited() is
implemented, which calls tcp_sock_rate_check_app_limited() for each
subflow.
When MPTCP implements lock_is_held interface, it not only checks
sock_owned_by_user_nocheck(sk) as TCP does, but also needs to check
whether the MPTCP data lock is held.
Co-developed-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
include/net/mptcp.h | 2 +
include/net/tcp.h | 1 +
net/ipv4/tcp.c | 9 +++-
net/mptcp/protocol.c | 113 ++++++++++++++++++++++++++++++++++++++++---
net/tls/tls_main.c | 3 ++
5 files changed, 120 insertions(+), 8 deletions(-)
diff --git a/include/net/mptcp.h b/include/net/mptcp.h
index 4cf59e83c1c5..02564eceeb7e 100644
--- a/include/net/mptcp.h
+++ b/include/net/mptcp.h
@@ -132,6 +132,8 @@ struct mptcp_pm_ops {
void (*release)(struct mptcp_sock *msk);
} ____cacheline_aligned_in_smp;
+extern struct tls_prot_ops tls_mptcp_ops;
+
#ifdef CONFIG_MPTCP
void mptcp_init(void);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 6156d1d068e1..2a10bfffebf6 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -851,6 +851,7 @@ static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize)
/* tcp.c */
void tcp_get_info(struct sock *, struct tcp_info *);
+void tcp_sock_rate_check_app_limited(struct tcp_sock *tp);
void tcp_rate_check_app_limited(struct sock *sk);
/* Read 'sendfile()'-style from a TCP socket */
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index f2d2884652ea..4b8cf7ca2695 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1100,9 +1100,9 @@ int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *copied,
}
/* If a gap is detected between sends, mark the socket application-limited. */
-void tcp_rate_check_app_limited(struct sock *sk)
+void tcp_sock_rate_check_app_limited(struct tcp_sock *tp)
{
- struct tcp_sock *tp = tcp_sk(sk);
+ struct sock *sk = (struct sock *)tp;
if (/* We have less than one packet to send. */
tp->write_seq - tp->snd_nxt < tp->mss_cache &&
@@ -1115,6 +1115,11 @@ void tcp_rate_check_app_limited(struct sock *sk)
tp->app_limited =
(tp->delivered + tcp_packets_in_flight(tp)) ? : 1;
}
+
+void tcp_rate_check_app_limited(struct sock *sk)
+{
+ tcp_sock_rate_check_app_limited(tcp_sk(sk));
+}
EXPORT_SYMBOL_GPL(tcp_rate_check_app_limited);
int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 975c54f36f7a..7d567597f26b 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -24,11 +24,12 @@
#include <net/mptcp.h>
#include <net/hotdata.h>
#include <net/xfrm.h>
+#include <net/tls.h>
#include <asm/ioctls.h>
#include "protocol.h"
#include "mib.h"
-static unsigned int mptcp_inq_hint(const struct sock *sk);
+static unsigned int mptcp_inq_hint(struct sock *sk);
#define CREATE_TRACE_POINTS
#include <trace/events/mptcp.h>
@@ -1933,7 +1934,7 @@ static void mptcp_rps_record_subflows(const struct mptcp_sock *msk)
}
}
-static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+static int mptcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t len)
{
struct mptcp_sock *msk = mptcp_sk(sk);
struct page_frag *pfrag;
@@ -1944,8 +1945,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
/* silently ignore everything else */
msg->msg_flags &= MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL | MSG_FASTOPEN;
- lock_sock(sk);
-
mptcp_rps_record_subflows(msk);
if (unlikely(inet_test_bit(DEFER_CONNECT, sk) ||
@@ -2053,7 +2052,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
__mptcp_push_pending(sk, msg->msg_flags);
out:
- release_sock(sk);
return copied;
do_error:
@@ -2064,6 +2062,17 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
goto out;
}
+static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+{
+ int ret;
+
+ lock_sock(sk);
+ ret = mptcp_sendmsg_locked(sk, msg, len);
+ release_sock(sk);
+
+ return ret;
+}
+
static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied);
static void mptcp_eat_recv_skb(struct sock *sk, struct sk_buff *skb)
@@ -2324,7 +2333,7 @@ static bool mptcp_move_skbs(struct sock *sk)
return enqueued;
}
-static unsigned int mptcp_inq_hint(const struct sock *sk)
+static int mptcp_inq(struct sock *sk)
{
const struct mptcp_sock *msk = mptcp_sk(sk);
const struct sk_buff *skb;
@@ -2339,6 +2348,16 @@ static unsigned int mptcp_inq_hint(const struct sock *sk)
return (unsigned int)hint_val;
}
+ return 0;
+}
+
+static unsigned int mptcp_inq_hint(struct sock *sk)
+{
+ unsigned int inq = mptcp_inq(sk);
+
+ if (inq)
+ return inq;
+
if (sk->sk_state == TCP_CLOSE || (sk->sk_shutdown & RCV_SHUTDOWN))
return 1;
@@ -4762,3 +4781,85 @@ int __init mptcp_proto_v6_init(void)
return err;
}
#endif
+
+static bool mptcp_lock_is_held(struct sock *sk)
+{
+ return sock_owned_by_user_nocheck(sk) ||
+ lockdep_is_held(&sk->sk_lock.slock);
+}
+
+static void mptcp_read_done(struct sock *sk, size_t len)
+{
+ struct mptcp_sock *msk = mptcp_sk(sk);
+ struct sk_buff *skb;
+ size_t left;
+ u32 offset;
+
+ msk_owned_by_me(msk);
+
+ if (sk->sk_state == TCP_LISTEN)
+ return;
+
+ left = len;
+ while (left && (skb = mptcp_recv_skb(sk, &offset)) != NULL) {
+ int used;
+
+ used = min_t(size_t, skb->len - offset, left);
+ msk->bytes_consumed += used;
+ MPTCP_SKB_CB(skb)->offset += used;
+ MPTCP_SKB_CB(skb)->map_seq += used;
+ left -= used;
+
+ if (skb->len > offset + used)
+ break;
+
+ mptcp_eat_recv_skb(sk, skb);
+ }
+
+ mptcp_rcv_space_adjust(msk, len - left);
+
+ /* Clean up data we have read: This will do ACK frames. */
+ if (left != len)
+ mptcp_cleanup_rbuf(msk, len - left);
+}
+
+static u32 mptcp_get_skb_off(struct sk_buff *skb)
+{
+ return MPTCP_SKB_CB(skb)->offset;
+}
+
+static u32 mptcp_get_skb_seq(struct sk_buff *skb)
+{
+ return MPTCP_SKB_CB(skb)->map_seq;
+}
+
+static void mptcp_check_app_limited(struct sock *sk)
+{
+ struct mptcp_sock *msk = mptcp_sk(sk);
+ struct mptcp_subflow_context *subflow;
+
+ mptcp_for_each_subflow(msk, subflow) {
+ struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
+ bool slow;
+
+ slow = lock_sock_fast(ssk);
+ tcp_sock_rate_check_app_limited(tcp_sk(ssk));
+ unlock_sock_fast(ssk, slow);
+ }
+}
+
+struct tls_prot_ops tls_mptcp_ops = {
+ .protocol = IPPROTO_MPTCP,
+ .inq = mptcp_inq,
+ .sendmsg_locked = mptcp_sendmsg_locked,
+ .recv_skb = mptcp_recv_skb,
+ .lock_is_held = mptcp_lock_is_held,
+ .read_sock = mptcp_read_sock,
+ .read_done = mptcp_read_done,
+ .get_skb_off = mptcp_get_skb_off,
+ .get_skb_seq = mptcp_get_skb_seq,
+ .poll = mptcp_poll,
+ .epollin_ready = mptcp_epollin_ready,
+ .check_app_limited = mptcp_check_app_limited,
+};
+EXPORT_SYMBOL(tls_mptcp_ops);
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index 5f324887390d..8a9d8deb1f93 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -1349,6 +1349,9 @@ static int __init tls_register(void)
tcp_register_ulp(&tcp_tls_ulp_ops);
tls_register_prot_ops(&tls_tcp_ops);
+#ifdef CONFIG_MPTCP
+ tls_register_prot_ops(&tls_mptcp_ops);
+#endif
return 0;
err_strp:
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 06/15] tls: disable device offload for mptcp sockets
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (4 preceding siblings ...)
2026-04-02 7:47 ` [RFC mptcp-next v12 05/15] mptcp: implement tls_mptcp_ops Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 07/15] mptcp: update ulp getsockopt for tls support Geliang Tang
` (10 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Gang Yan
From: Geliang Tang <tanggeliang@kylinos.cn>
MPTCP TLS hardware offload is not yet implemented. Return -EOPNOTSUPP
when attempting to enable device offload on MPTCP sockets.
Co-developed-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
net/tls/tls_device.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index 99c8eff9783e..6744c2494740 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -1074,6 +1074,9 @@ int tls_set_device_offload(struct sock *sk)
ctx = tls_get_ctx(sk);
prot = &ctx->prot_info;
+ if (sk->sk_protocol == IPPROTO_MPTCP)
+ return -EOPNOTSUPP;
+
if (ctx->priv_ctx_tx)
return -EEXIST;
@@ -1196,6 +1199,9 @@ int tls_set_device_offload_rx(struct sock *sk, struct tls_context *ctx)
struct net_device *netdev;
int rc = 0;
+ if (sk->sk_protocol == IPPROTO_MPTCP)
+ return -EOPNOTSUPP;
+
if (ctx->crypto_recv.info.version != TLS_1_2_VERSION)
return -EOPNOTSUPP;
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 07/15] mptcp: update ulp getsockopt for tls support
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (5 preceding siblings ...)
2026-04-02 7:47 ` [RFC mptcp-next v12 06/15] tls: disable device offload for mptcp sockets Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 08/15] mptcp: enable ulp setsockopt " Geliang Tang
` (9 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Gang Yan
From: Geliang Tang <tanggeliang@kylinos.cn>
This patch extracts TCP_ULP getsockopt operation into a tcp_sock_get_ulp()
helper so that it can also be used in MPTCP.
TCP_ULP was obtained by calling mptcp_getsockopt_first_sf_only() to get
ULP of the first subflow. Now that the mechanism has changed, a new helper
mptcp_getsockopt_tcp_ulp() is added to get ULP of msk.
Co-developed-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
include/linux/tcp.h | 1 +
net/ipv4/tcp.c | 36 ++++++++++++++++++++++--------------
net/mptcp/sockopt.c | 12 ++++++++++++
3 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 6982f10e826b..2bb1cbd3eeab 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -653,6 +653,7 @@ void tcp_sock_set_quickack(struct sock *sk, int val);
int tcp_sock_set_syncnt(struct sock *sk, int val);
int tcp_sock_set_user_timeout(struct sock *sk, int val);
int tcp_sock_set_maxseg(struct sock *sk, int val);
+int tcp_sock_get_ulp(struct sock *sk, sockptr_t optval, sockptr_t optlen);
static inline bool dst_tcp_usec_ts(const struct dst_entry *dst)
{
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 4b8cf7ca2695..c3c6cd6ee95a 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -4473,6 +4473,27 @@ struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk,
return stats;
}
+int tcp_sock_get_ulp(struct sock *sk, sockptr_t optval, sockptr_t optlen)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ int len;
+
+ if (copy_from_sockptr(&len, optlen, sizeof(int)))
+ return -EFAULT;
+ len = min_t(unsigned int, len, TCP_ULP_NAME_MAX);
+ if (!icsk->icsk_ulp_ops) {
+ len = 0;
+ if (copy_to_sockptr(optlen, &len, sizeof(int)))
+ return -EFAULT;
+ return 0;
+ }
+ if (copy_to_sockptr(optlen, &len, sizeof(int)))
+ return -EFAULT;
+ if (copy_to_sockptr(optval, icsk->icsk_ulp_ops->name, len))
+ return -EFAULT;
+ return 0;
+}
+
int do_tcp_getsockopt(struct sock *sk, int level,
int optname, sockptr_t optval, sockptr_t optlen)
{
@@ -4582,20 +4603,7 @@ int do_tcp_getsockopt(struct sock *sk, int level,
return 0;
case TCP_ULP:
- if (copy_from_sockptr(&len, optlen, sizeof(int)))
- return -EFAULT;
- len = min_t(unsigned int, len, TCP_ULP_NAME_MAX);
- if (!icsk->icsk_ulp_ops) {
- len = 0;
- if (copy_to_sockptr(optlen, &len, sizeof(int)))
- return -EFAULT;
- return 0;
- }
- if (copy_to_sockptr(optlen, &len, sizeof(int)))
- return -EFAULT;
- if (copy_to_sockptr(optval, icsk->icsk_ulp_ops->name, len))
- return -EFAULT;
- return 0;
+ return tcp_sock_get_ulp(sk, optval, optlen);
case TCP_FASTOPEN_KEY: {
u64 key[TCP_FASTOPEN_KEY_BUF_LENGTH / sizeof(u64)];
diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
index de90a2897d2d..a6230f7910fd 100644
--- a/net/mptcp/sockopt.c
+++ b/net/mptcp/sockopt.c
@@ -1393,6 +1393,17 @@ static int mptcp_put_int_option(struct mptcp_sock *msk, char __user *optval,
return 0;
}
+static int mptcp_getsockopt_tcp_ulp(struct sock *sk, char __user *optval,
+ int __user *optlen)
+{
+ int ret;
+
+ lock_sock(sk);
+ ret = tcp_sock_get_ulp(sk, USER_SOCKPTR(optval), USER_SOCKPTR(optlen));
+ release_sock(sk);
+ return ret;
+}
+
static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
char __user *optval, int __user *optlen)
{
@@ -1400,6 +1411,7 @@ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
switch (optname) {
case TCP_ULP:
+ return mptcp_getsockopt_tcp_ulp(sk, optval, optlen);
case TCP_CONGESTION:
case TCP_INFO:
case TCP_CC_INFO:
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 08/15] mptcp: enable ulp setsockopt for tls support
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (6 preceding siblings ...)
2026-04-02 7:47 ` [RFC mptcp-next v12 07/15] mptcp: update ulp getsockopt for tls support Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 09/15] selftests: mptcp: connect: use espintcp for ulp test Geliang Tang
` (8 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Gang Yan
From: Geliang Tang <tanggeliang@kylinos.cn>
This patch extracts TCP_ULP setsockopt operation into a tcp_sock_set_ulp()
helper so that it can also be used in MPTCP.
Add MPTCP ULP setsockopt support in mptcp_setsockopt_sol_tcp().
This option cannot be set when the socket is in CLOSE or LISTEN state.
Co-developed-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
include/linux/tcp.h | 1 +
net/ipv4/tcp.c | 42 ++++++++++++++++++++++++------------------
net/mptcp/sockopt.c | 27 ++++++++++++++++++++++++++-
3 files changed, 51 insertions(+), 19 deletions(-)
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 2bb1cbd3eeab..00538b1aa2f0 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -654,6 +654,7 @@ int tcp_sock_set_syncnt(struct sock *sk, int val);
int tcp_sock_set_user_timeout(struct sock *sk, int val);
int tcp_sock_set_maxseg(struct sock *sk, int val);
int tcp_sock_get_ulp(struct sock *sk, sockptr_t optval, sockptr_t optlen);
+int tcp_sock_set_ulp(struct sock *sk, sockptr_t optval, unsigned int optlen);
static inline bool dst_tcp_usec_ts(const struct dst_entry *dst)
{
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c3c6cd6ee95a..94802d03c74b 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -3837,6 +3837,28 @@ int tcp_sock_set_maxseg(struct sock *sk, int val)
return 0;
}
+int tcp_sock_set_ulp(struct sock *sk, sockptr_t optval, unsigned int optlen)
+{
+ char name[TCP_ULP_NAME_MAX];
+ int err = 0;
+ size_t len;
+ int val;
+
+ if (optlen < 1)
+ return -EINVAL;
+
+ len = min_t(long, TCP_ULP_NAME_MAX - 1, optlen);
+ val = strncpy_from_sockptr(name, optval, len);
+ if (val < 0)
+ return -EFAULT;
+ name[val] = 0;
+
+ sockopt_lock_sock(sk);
+ err = tcp_set_ulp(sk, name);
+ sockopt_release_sock(sk);
+ return err;
+}
+
/*
* Socket option code for TCP.
*/
@@ -3870,24 +3892,8 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
sockopt_release_sock(sk);
return err;
}
- case TCP_ULP: {
- char name[TCP_ULP_NAME_MAX];
-
- if (optlen < 1)
- return -EINVAL;
-
- val = strncpy_from_sockptr(name, optval,
- min_t(long, TCP_ULP_NAME_MAX - 1,
- optlen));
- if (val < 0)
- return -EFAULT;
- name[val] = 0;
-
- sockopt_lock_sock(sk);
- err = tcp_set_ulp(sk, name);
- sockopt_release_sock(sk);
- return err;
- }
+ case TCP_ULP:
+ return tcp_sock_set_ulp(sk, optval, optlen);
case TCP_FASTOPEN_KEY: {
__u8 key[TCP_FASTOPEN_KEY_BUF_LENGTH];
__u8 *backup_key = NULL;
diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
index a6230f7910fd..d04eb98aaa32 100644
--- a/net/mptcp/sockopt.c
+++ b/net/mptcp/sockopt.c
@@ -12,6 +12,7 @@
#include <net/protocol.h>
#include <net/tcp.h>
#include <net/mptcp.h>
+#include <net/tls.h>
#include "protocol.h"
#define MIN_INFO_OPTLEN_SIZE 16
@@ -567,6 +568,7 @@ static bool mptcp_supported_sockopt(int level, int optname)
case TCP_FASTOPEN_CONNECT:
case TCP_FASTOPEN_KEY:
case TCP_FASTOPEN_NO_COOKIE:
+ case TCP_ULP:
return true;
}
@@ -815,6 +817,29 @@ static int mptcp_setsockopt_all_sf(struct mptcp_sock *msk, int level,
return ret;
}
+static int mptcp_setsockopt_tcp_ulp(struct sock *sk, sockptr_t optval,
+ unsigned int optlen)
+{
+ char name[TCP_ULP_NAME_MAX];
+ size_t len;
+ int val;
+
+ if (optlen < 1)
+ return -EINVAL;
+
+ len = min_t(long, TCP_ULP_NAME_MAX - 1, optlen);
+ val = strncpy_from_sockptr(name, optval, len);
+ if (val < 0)
+ return -EFAULT;
+ name[val] = 0;
+
+ if (strcmp(name, "tls\0"))
+ return -EOPNOTSUPP;
+ if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))
+ return -ENOTCONN;
+ return tcp_sock_set_ulp(sk, optval, optlen);
+}
+
static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
sockptr_t optval, unsigned int optlen)
{
@@ -823,7 +848,7 @@ static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
switch (optname) {
case TCP_ULP:
- return -EOPNOTSUPP;
+ return mptcp_setsockopt_tcp_ulp(sk, optval, optlen);
case TCP_CONGESTION:
return mptcp_setsockopt_sol_tcp_congestion(msk, optval, optlen);
case TCP_DEFER_ACCEPT:
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 09/15] selftests: mptcp: connect: use espintcp for ulp test
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (7 preceding siblings ...)
2026-04-02 7:47 ` [RFC mptcp-next v12 08/15] mptcp: enable ulp setsockopt " Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 10/15] selftests: tls: add mptcp variant for testing Geliang Tang
` (7 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Gang Yan
From: Geliang Tang <tanggeliang@kylinos.cn>
With KTLS being implemented, "tls" should no longer be used in
sock_test_tcpulp(), it breaks mptcp_connect.sh tests. Another ULP
name, "espintcp", is set instead in this patch.
Co-developed-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
tools/testing/selftests/net/mptcp/mptcp_connect.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c
index cbe573c4ab3a..0d4a944c4269 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c
@@ -289,7 +289,7 @@ static void sock_test_tcpulp(int sock, int proto, unsigned int line)
if (ret == 0)
X("setsockopt");
} else if (proto == IPPROTO_MPTCP) {
- ret = do_ulp_so(sock, "tls");
+ ret = do_ulp_so(sock, "espintcp");
if (ret != -1)
X("setsockopt");
}
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 10/15] selftests: tls: add mptcp variant for testing
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (8 preceding siblings ...)
2026-04-02 7:47 ` [RFC mptcp-next v12 09/15] selftests: mptcp: connect: use espintcp for ulp test Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 11/15] selftests: tls: increase pollin timeouts for mptcp Geliang Tang
` (6 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Gang Yan
From: Geliang Tang <tanggeliang@kylinos.cn>
To enable easy MPTCP socket creation in MPTCP TLS tests, two protocol
parameters (cli_proto and srv_proto) have been added to ulp_sock_pair().
These are passed as third arguments of socket(): 0 creates TCP sockets,
IPPROTO_MPTCP creates MPTCP sockets.
A new variant "mptcp" is added both in FIXTURE_VARIANT(tls) to control
whether to create MPTCP sockets or not for tests.
Co-developed-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
tools/testing/selftests/net/tls.c | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c
index 9e2ccea13d70..903e80c4267f 100644
--- a/tools/testing/selftests/net/tls.c
+++ b/tools/testing/selftests/net/tls.c
@@ -26,6 +26,10 @@
#define TLS_PAYLOAD_MAX_LEN 16384
#define SOL_TLS 282
+#ifndef IPPROTO_MPTCP
+#define IPPROTO_MPTCP 262
+#endif
+
static int fips_enabled;
struct tls_crypto_info_keys {
@@ -108,8 +112,9 @@ static void memrnd(void *s, size_t n)
*byte++ = rand();
}
-static void ulp_sock_pair(struct __test_metadata *_metadata,
- int *fd, int *cfd, bool *notls)
+static void __ulp_sock_pair(struct __test_metadata *_metadata,
+ int *fd, int *cfd, bool *notls,
+ int cli_proto, int srv_proto)
{
struct sockaddr_in addr;
socklen_t len;
@@ -122,8 +127,8 @@ static void ulp_sock_pair(struct __test_metadata *_metadata,
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = 0;
- *fd = socket(AF_INET, SOCK_STREAM, 0);
- sfd = socket(AF_INET, SOCK_STREAM, 0);
+ *fd = socket(AF_INET, SOCK_STREAM, cli_proto);
+ sfd = socket(AF_INET, SOCK_STREAM, srv_proto);
ret = bind(sfd, &addr, sizeof(addr));
ASSERT_EQ(ret, 0);
@@ -153,6 +158,12 @@ static void ulp_sock_pair(struct __test_metadata *_metadata,
ASSERT_EQ(ret, 0);
}
+static void ulp_sock_pair(struct __test_metadata *_metadata,
+ int *fd, int *cfd, bool *notls)
+{
+ return __ulp_sock_pair(_metadata, fd, cfd, notls, 0, 0);
+}
+
/* Produce a basic cmsg */
static int tls_send_cmsg(int fd, unsigned char record_type,
void *data, size_t len, int flags)
@@ -310,6 +321,7 @@ FIXTURE_VARIANT(tls)
uint16_t tls_version;
uint16_t cipher_type;
bool nopad, fips_non_compliant;
+ bool mptcp;
};
FIXTURE_VARIANT_ADD(tls, 12_aes_gcm)
@@ -407,7 +419,9 @@ FIXTURE_SETUP(tls)
tls_crypto_info_init(variant->tls_version, variant->cipher_type,
&tls12, 0);
- ulp_sock_pair(_metadata, &self->fd, &self->cfd, &self->notls);
+ __ulp_sock_pair(_metadata, &self->fd, &self->cfd, &self->notls,
+ variant->mptcp ? IPPROTO_MPTCP : 0,
+ variant->mptcp ? IPPROTO_MPTCP : 0);
if (self->notls)
return;
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 11/15] selftests: tls: increase pollin timeouts for mptcp
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (9 preceding siblings ...)
2026-04-02 7:47 ` [RFC mptcp-next v12 10/15] selftests: tls: add mptcp variant for testing Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 12/15] selftests: tls: increase nonblocking data size " Geliang Tang
` (5 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Gang Yan
From: Geliang Tang <tanggeliang@kylinos.cn>
MPTCP requires longer timeouts in pollin test due to subflow establishment
delays and slower state transitions. Increase timeout values to prevent
false failures:
# RUN tls.13_sm4_ccm_mptcp.pollin ...
# tls.c:1411:pollin:Expected poll(&fd, 1, 20) (0) == 1 (1)
# tls.c:1412:pollin:Expected fd.revents & POLLIN (0) == 1 (1)
# pollin: Test failed
# FAIL tls.13_sm4_ccm_mptcp.pollin
not ok 357 tls.13_sm4_ccm_mptcp.pollin
Co-developed-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
tools/testing/selftests/net/tls.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c
index 903e80c4267f..64e999c6e14d 100644
--- a/tools/testing/selftests/net/tls.c
+++ b/tools/testing/selftests/net/tls.c
@@ -1299,6 +1299,7 @@ TEST_F(tls, bidir)
TEST_F(tls, pollin)
{
+ int timeout = variant->mptcp ? 100 : 20;
char const *test_str = "test_poll";
struct pollfd fd = { 0, 0, 0 };
char buf[10];
@@ -1308,11 +1309,11 @@ TEST_F(tls, pollin)
fd.fd = self->cfd;
fd.events = POLLIN;
- EXPECT_EQ(poll(&fd, 1, 20), 1);
+ EXPECT_EQ(poll(&fd, 1, timeout), 1);
EXPECT_EQ(fd.revents & POLLIN, 1);
EXPECT_EQ(recv(self->cfd, buf, send_len, MSG_WAITALL), send_len);
/* Test timing out */
- EXPECT_EQ(poll(&fd, 1, 20), 0);
+ EXPECT_EQ(poll(&fd, 1, timeout), 0);
}
TEST_F(tls, poll_wait)
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 12/15] selftests: tls: increase nonblocking data size for mptcp
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (10 preceding siblings ...)
2026-04-02 7:47 ` [RFC mptcp-next v12 11/15] selftests: tls: increase pollin timeouts for mptcp Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 13/15] selftests: tls: wait close in shutdown_reuse " Geliang Tang
` (4 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Gang Yan
From: Geliang Tang <tanggeliang@kylinos.cn>
Increase the data size in nonblocking tests to accommodate MPTCP's
multi-subflow behavior and ensure sufficient data for testing,
avoiding the following errors:
# RUN tls.12_aria_gcm_mptcp.nonblocking ...
# tls.c:1534:nonblocking:Expected 0 (0) != eagain (0)
# nonblocking: Test failed
Co-developed-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
tools/testing/selftests/net/tls.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c
index 64e999c6e14d..c3227b718160 100644
--- a/tools/testing/selftests/net/tls.c
+++ b/tools/testing/selftests/net/tls.c
@@ -1405,6 +1405,9 @@ TEST_F(tls, nonblocking)
int flags;
int res;
+ if (variant->mptcp)
+ data *= 4;
+
flags = fcntl(self->fd, F_GETFL, 0);
fcntl(self->fd, F_SETFL, flags | O_NONBLOCK);
fcntl(self->cfd, F_SETFL, flags | O_NONBLOCK);
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 13/15] selftests: tls: wait close in shutdown_reuse for mptcp
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (11 preceding siblings ...)
2026-04-02 7:47 ` [RFC mptcp-next v12 12/15] selftests: tls: increase nonblocking data size " Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 14/15] selftests: tls: add mptcp test cases Geliang Tang
` (3 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Gang Yan
From: Geliang Tang <tanggeliang@kylinos.cn>
In shutdown_reuse tests, add a delay after shutdown to wait for
MPTCP sockets to reach TCP_CLOSE state before reuse via bind(),
avoiding the following errors:
# RUN tls.12_aes_gcm_mptcp.shutdown_reuse ...
# tls.c:1790:shutdown_reuse:Expected ret (-1) == 0 (0)
# shutdown_reuse: Test failed
# FAIL tls.12_aes_gcm_mptcp.shutdown_reuse
not ok 14 tls.12_aes_gcm_mptcp.shutdown_reuse
# RUN tls.13_aes_gcm_mptcp.shutdown_reuse ...
# tls.c:1790:shutdown_reuse:Expected ret (-1) == 0 (0)
# shutdown_reuse: Test failed
# FAIL tls.13_aes_gcm_mptcp.shutdown_reuse
not ok 15 tls.13_aes_gcm_mptcp.shutdown_reuse
# RUN tls.12_chacha_mptcp.shutdown_reuse ...
# OK tls.12_chacha_mptcp.shutdown_reuse
ok 16 tls.12_chacha_mptcp.shutdown_reuse
# RUN tls.13_chacha_mptcp.shutdown_reuse ...
# OK tls.13_chacha_mptcp.shutdown_reuse
ok 17 tls.13_chacha_mptcp.shutdown_reuse
# RUN tls.13_sm4_gcm_mptcp.shutdown_reuse ...
# tls.c:1790:shutdown_reuse:Expected ret (-1) == 0 (0)
# shutdown_reuse: Test failed
# FAIL tls.13_sm4_gcm_mptcp.shutdown_reuse
not ok 18 tls.13_sm4_gcm_mptcp.shutdown_reuse
Co-developed-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
tools/testing/selftests/net/tls.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c
index c3227b718160..f12744b178d5 100644
--- a/tools/testing/selftests/net/tls.c
+++ b/tools/testing/selftests/net/tls.c
@@ -30,6 +30,10 @@
#define IPPROTO_MPTCP 262
#endif
+#ifndef TCP_CLOSE
+#define TCP_CLOSE 7
+#endif
+
static int fips_enabled;
struct tls_crypto_info_keys {
@@ -1678,6 +1682,25 @@ TEST_F(tls, shutdown_unsent)
shutdown(self->cfd, SHUT_RDWR);
}
+static bool wait_for_tcp_close(struct __test_metadata *_metadata,
+ int fd, int max)
+{
+ struct tcp_info info;
+ socklen_t len;
+ int i, ret;
+
+ len = sizeof(info);
+ for (i = 0; i < max; i++) {
+ ret = getsockopt(fd, IPPROTO_TCP, TCP_INFO, &info, &len);
+ EXPECT_EQ(ret, 0);
+ if (info.tcpi_state == TCP_CLOSE)
+ return true;
+ usleep(1000);
+ }
+
+ return false;
+}
+
TEST_F(tls, shutdown_reuse)
{
struct sockaddr_in addr;
@@ -1687,6 +1710,9 @@ TEST_F(tls, shutdown_reuse)
shutdown(self->cfd, SHUT_RDWR);
close(self->cfd);
+ if (variant->mptcp)
+ EXPECT_TRUE(wait_for_tcp_close(_metadata, self->fd, 1000));
+
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = 0;
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 14/15] selftests: tls: add mptcp test cases
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (12 preceding siblings ...)
2026-04-02 7:47 ` [RFC mptcp-next v12 13/15] selftests: tls: wait close in shutdown_reuse " Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 7:47 ` [RFC mptcp-next v12 15/15] selftests: mptcp: cover mptcp tls tests Geliang Tang
` (2 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Gang Yan
From: Geliang Tang <tanggeliang@kylinos.cn>
This patch introduces MPTCP test cases for the TLS fixture. These "mptcp"
variants are configured to create MPTCP sockets specifically for MPTCP TLS
testing purposes.
Co-developed-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
tools/testing/selftests/net/tls.c | 96 +++++++++++++++++++++++++++++++
1 file changed, 96 insertions(+)
diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c
index f12744b178d5..b4ea696fefb0 100644
--- a/tools/testing/selftests/net/tls.c
+++ b/tools/testing/selftests/net/tls.c
@@ -411,6 +411,102 @@ FIXTURE_VARIANT_ADD(tls, 12_aria_gcm_256)
.cipher_type = TLS_CIPHER_ARIA_GCM_256,
};
+FIXTURE_VARIANT_ADD(tls, 12_aes_gcm_mptcp)
+{
+ .tls_version = TLS_1_2_VERSION,
+ .cipher_type = TLS_CIPHER_AES_GCM_128,
+ .mptcp = true,
+};
+
+FIXTURE_VARIANT_ADD(tls, 13_aes_gcm_mptcp)
+{
+ .tls_version = TLS_1_3_VERSION,
+ .cipher_type = TLS_CIPHER_AES_GCM_128,
+ .mptcp = true,
+};
+
+FIXTURE_VARIANT_ADD(tls, 12_chacha_mptcp)
+{
+ .tls_version = TLS_1_2_VERSION,
+ .cipher_type = TLS_CIPHER_CHACHA20_POLY1305,
+ .fips_non_compliant = true,
+ .mptcp = true,
+};
+
+FIXTURE_VARIANT_ADD(tls, 13_chacha_mptcp)
+{
+ .tls_version = TLS_1_3_VERSION,
+ .cipher_type = TLS_CIPHER_CHACHA20_POLY1305,
+ .fips_non_compliant = true,
+ .mptcp = true,
+};
+
+FIXTURE_VARIANT_ADD(tls, 13_sm4_gcm_mptcp)
+{
+ .tls_version = TLS_1_3_VERSION,
+ .cipher_type = TLS_CIPHER_SM4_GCM,
+ .fips_non_compliant = true,
+ .mptcp = true,
+};
+
+FIXTURE_VARIANT_ADD(tls, 13_sm4_ccm_mptcp)
+{
+ .tls_version = TLS_1_3_VERSION,
+ .cipher_type = TLS_CIPHER_SM4_CCM,
+ .fips_non_compliant = true,
+ .mptcp = true,
+};
+
+FIXTURE_VARIANT_ADD(tls, 12_aes_ccm_mptcp)
+{
+ .tls_version = TLS_1_2_VERSION,
+ .cipher_type = TLS_CIPHER_AES_CCM_128,
+ .mptcp = true,
+};
+
+FIXTURE_VARIANT_ADD(tls, 13_aes_ccm_mptcp)
+{
+ .tls_version = TLS_1_3_VERSION,
+ .cipher_type = TLS_CIPHER_AES_CCM_128,
+ .mptcp = true,
+};
+
+FIXTURE_VARIANT_ADD(tls, 12_aes_gcm_256_mptcp)
+{
+ .tls_version = TLS_1_2_VERSION,
+ .cipher_type = TLS_CIPHER_AES_GCM_256,
+ .mptcp = true,
+};
+
+FIXTURE_VARIANT_ADD(tls, 13_aes_gcm_256_mptcp)
+{
+ .tls_version = TLS_1_3_VERSION,
+ .cipher_type = TLS_CIPHER_AES_GCM_256,
+ .mptcp = true,
+};
+
+FIXTURE_VARIANT_ADD(tls, 13_nopad_mptcp)
+{
+ .tls_version = TLS_1_3_VERSION,
+ .cipher_type = TLS_CIPHER_AES_GCM_128,
+ .nopad = true,
+ .mptcp = true,
+};
+
+FIXTURE_VARIANT_ADD(tls, 12_aria_gcm_mptcp)
+{
+ .tls_version = TLS_1_2_VERSION,
+ .cipher_type = TLS_CIPHER_ARIA_GCM_128,
+ .mptcp = true,
+};
+
+FIXTURE_VARIANT_ADD(tls, 12_aria_gcm_256_mptcp)
+{
+ .tls_version = TLS_1_2_VERSION,
+ .cipher_type = TLS_CIPHER_ARIA_GCM_256,
+ .mptcp = true,
+};
+
FIXTURE_SETUP(tls)
{
struct tls_crypto_info_keys tls12;
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [RFC mptcp-next v12 15/15] selftests: mptcp: cover mptcp tls tests
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (13 preceding siblings ...)
2026-04-02 7:47 ` [RFC mptcp-next v12 14/15] selftests: tls: add mptcp test cases Geliang Tang
@ 2026-04-02 7:47 ` Geliang Tang
2026-04-02 8:17 ` [RFC mptcp-next v12 00/15] MPTCP KTLS support MPTCP CI
2026-04-02 9:21 ` MPTCP CI
16 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 7:47 UTC (permalink / raw)
To: mptcp; +Cc: Geliang Tang, Gang Yan
From: Geliang Tang <tanggeliang@kylinos.cn>
The mptcp tests for tls.c is available now, this patch adds mptcp_tls.sh
to test it in the MPTCP CI by default.
Co-developed-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Gang Yan <yangang@kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
tools/testing/selftests/net/mptcp/Makefile | 2 +
tools/testing/selftests/net/mptcp/config | 4 ++
.../testing/selftests/net/mptcp/mptcp_tls.sh | 55 +++++++++++++++++++
tools/testing/selftests/net/mptcp/tls.c | 1 +
4 files changed, 62 insertions(+)
create mode 100755 tools/testing/selftests/net/mptcp/mptcp_tls.sh
create mode 120000 tools/testing/selftests/net/mptcp/tls.c
diff --git a/tools/testing/selftests/net/mptcp/Makefile b/tools/testing/selftests/net/mptcp/Makefile
index 22ba0da2adb8..f7c959a25b3b 100644
--- a/tools/testing/selftests/net/mptcp/Makefile
+++ b/tools/testing/selftests/net/mptcp/Makefile
@@ -14,6 +14,7 @@ TEST_PROGS := \
mptcp_connect_splice.sh \
mptcp_join.sh \
mptcp_sockopt.sh \
+ mptcp_tls.sh \
pm_netlink.sh \
simult_flows.sh \
userspace_pm.sh \
@@ -25,6 +26,7 @@ TEST_GEN_FILES := \
mptcp_inq \
mptcp_sockopt \
pm_nl_ctl \
+ tls \
# end of TEST_GEN_FILES
TEST_FILES := \
diff --git a/tools/testing/selftests/net/mptcp/config b/tools/testing/selftests/net/mptcp/config
index 59051ee2a986..471c7e0ba2be 100644
--- a/tools/testing/selftests/net/mptcp/config
+++ b/tools/testing/selftests/net/mptcp/config
@@ -34,3 +34,7 @@ CONFIG_NFT_SOCKET=m
CONFIG_NFT_TPROXY=m
CONFIG_SYN_COOKIES=y
CONFIG_VETH=y
+CONFIG_TLS=y
+CONFIG_CRYPTO_ARIA=y
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_SM4_GENERIC=y
diff --git a/tools/testing/selftests/net/mptcp/mptcp_tls.sh b/tools/testing/selftests/net/mptcp/mptcp_tls.sh
new file mode 100755
index 000000000000..b35d17857393
--- /dev/null
+++ b/tools/testing/selftests/net/mptcp/mptcp_tls.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. "$(dirname "${0}")/mptcp_lib.sh"
+
+ret=0
+ns1=""
+
+# This function is used in the cleanup trap
+#shellcheck disable=SC2317,SC2329
+cleanup()
+{
+ if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
+ kill "$pid" 2>/dev/null
+ wait "$pid" 2>/dev/null
+ fi
+
+ mptcp_lib_ns_exit "$ns1"
+}
+
+init()
+{
+ mptcp_lib_ns_init ns1
+
+ mptcp_lib_pm_nl_set_limits "$ns1" 8 8
+
+ local i
+ for i in $(seq 1 4); do
+ mptcp_lib_pm_nl_add_endpoint "$ns1" \
+ "127.0.0.1" flags signal port 1000"$i"
+ done
+}
+
+init
+trap cleanup EXIT
+
+ip netns exec "$ns1" ./tls -v 12_aes_gcm_mptcp \
+ -v 13_aes_gcm_mptcp \
+ -v 12_chacha_mptcp \
+ -v 13_chacha_mptcp \
+ -v 13_sm4_gcm_mptcp \
+ -v 13_sm4_ccm_mptcp \
+ -v 12_aes_ccm_mptcp \
+ -v 13_aes_ccm_mptcp \
+ -v 12_aes_gcm_256_mptcp \
+ -v 13_aes_gcm_256_mptcp \
+ -v 13_nopad_mptcp \
+ -v 12_aria_gcm_mptcp \
+ -v 12_aria_gcm_256_mptcp &
+pid=$!
+wait $pid
+ret=$?
+
+mptcp_lib_result_print_all_tap
+exit $ret
diff --git a/tools/testing/selftests/net/mptcp/tls.c b/tools/testing/selftests/net/mptcp/tls.c
new file mode 120000
index 000000000000..724b1f047c89
--- /dev/null
+++ b/tools/testing/selftests/net/mptcp/tls.c
@@ -0,0 +1 @@
+../tls.c
\ No newline at end of file
--
2.51.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [RFC mptcp-next v12 00/15] MPTCP KTLS support
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (14 preceding siblings ...)
2026-04-02 7:47 ` [RFC mptcp-next v12 15/15] selftests: mptcp: cover mptcp tls tests Geliang Tang
@ 2026-04-02 8:17 ` MPTCP CI
2026-04-02 10:20 ` Geliang Tang
2026-04-02 9:21 ` MPTCP CI
16 siblings, 1 reply; 20+ messages in thread
From: MPTCP CI @ 2026-04-02 8:17 UTC (permalink / raw)
To: Geliang Tang; +Cc: mptcp
Hi Geliang,
Thank you for your modifications, that's great!
But sadly, our CI spotted some issues with it when trying to build it.
You can find more details there:
https://github.com/multipath-tcp/mptcp_net-next/actions/runs/23890722509
Status: failure
Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/88f07fcab32d
Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=1076267
Feel free to reply to this email if you cannot access logs, if you need
some support to fix the error, if this doesn't seem to be caused by your
modifications or if the error is a false positive one.
Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [RFC mptcp-next v12 00/15] MPTCP KTLS support
2026-04-02 8:17 ` [RFC mptcp-next v12 00/15] MPTCP KTLS support MPTCP CI
@ 2026-04-02 10:20 ` Geliang Tang
0 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 10:20 UTC (permalink / raw)
To: mptcp, Geliang Tang
On Thu, 2026-04-02 at 08:17 +0000, MPTCP CI wrote:
> Hi Geliang,
>
> Thank you for your modifications, that's great!
>
> But sadly, our CI spotted some issues with it when trying to build
> it.
Oops.
protocol.c:(.text+0x2675f7): undefined reference to `lockdep_is_held'
I should use spin_is_locked(), not lockdep_is_held().
Will update this in the next version.
Thanks,
-Geliang
>
> You can find more details there:
>
>
> https://github.com/multipath-tcp/mptcp_net-next/actions/runs/23890722509
>
> Status: failure
> Initiator: Patchew Applier
> Commits:
> https://github.com/multipath-tcp/mptcp_net-next/commits/88f07fcab32d
> Patchwork:
> https://patchwork.kernel.org/project/mptcp/list/?series=1076267
>
> Feel free to reply to this email if you cannot access logs, if you
> need
> some support to fix the error, if this doesn't seem to be caused by
> your
> modifications or if the error is a false positive one.
>
> Cheers,
> MPTCP GH Action bot
> Bot operated by Matthieu Baerts (NGI0 Core)
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC mptcp-next v12 00/15] MPTCP KTLS support
2026-04-02 7:47 [RFC mptcp-next v12 00/15] MPTCP KTLS support Geliang Tang
` (15 preceding siblings ...)
2026-04-02 8:17 ` [RFC mptcp-next v12 00/15] MPTCP KTLS support MPTCP CI
@ 2026-04-02 9:21 ` MPTCP CI
2026-04-02 10:26 ` Geliang Tang
16 siblings, 1 reply; 20+ messages in thread
From: MPTCP CI @ 2026-04-02 9:21 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): Script error! ❓
- KVM Validation: normal (only selftest_mptcp_join): Script error! ❓
- KVM Validation: debug (except selftest_mptcp_join): Unstable: 3 failed test(s): packetdrill_mp_capable packetdrill_sockopts selftest_mptcp_tls - Critical: KMemLeak ❌
- KVM Validation: debug (only selftest_mptcp_join): Success! ✅
- KVM Validation: btf-normal (only bpftest_all): Script error! ❓
- KVM Validation: btf-debug (only bpftest_all): Success! ✅
- Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/23890722536
Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/88f07fcab32d
Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=1076267
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] 20+ messages in thread* Re: [RFC mptcp-next v12 00/15] MPTCP KTLS support
2026-04-02 9:21 ` MPTCP CI
@ 2026-04-02 10:26 ` Geliang Tang
0 siblings, 0 replies; 20+ messages in thread
From: Geliang Tang @ 2026-04-02 10:26 UTC (permalink / raw)
To: mptcp, Geliang Tang
On Thu, 2026-04-02 at 09:21 +0000, MPTCP CI wrote:
> 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): Script error!
> ❓
> - KVM Validation: normal (only selftest_mptcp_join): Script error! ❓
> - KVM Validation: debug (except selftest_mptcp_join): Unstable: 3
> failed test(s): packetdrill_mp_capable packetdrill_sockopts
> selftest_mptcp_tls - Critical: KMemLeak ❌
It's strange.
Based-on: <cover.1775033340.git.yangang@kylinos.cn> tag didn't work,
this is "mptcp: fix stall because of data_ready" v5.
Without this set, the TLS tests failed. This resulted in a KMemLeak. If
this set is successfully applied, the tests will not fail, and there
will be no KMemLeak error.
Thanks,
-Geliang
> - KVM Validation: debug (only selftest_mptcp_join): Success! ✅
> - KVM Validation: btf-normal (only bpftest_all): Script error! ❓
> - KVM Validation: btf-debug (only bpftest_all): Success! ✅
> - Task:
> https://github.com/multipath-tcp/mptcp_net-next/actions/runs/23890722536
>
> Initiator: Patchew Applier
> Commits:
> https://github.com/multipath-tcp/mptcp_net-next/commits/88f07fcab32d
> Patchwork:
> https://patchwork.kernel.org/project/mptcp/list/?series=1076267
>
>
> 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] 20+ messages in thread