[PATCH mptcp-next v2 2/3] mptcp: add TCP_MAXSEG sockopt support

Geliang Tang posted 3 patches 7 months, 3 weeks ago
There is a newer version of this series
[PATCH mptcp-next v2 2/3] mptcp: add TCP_MAXSEG sockopt support
Posted by Geliang Tang 7 months, 3 weeks ago
From: Geliang Tang <tanggeliang@kylinos.cn>

The TCP_MAXSEG socket option is currently not supported by MPTCP, mainly
because it has never been requested before. But there are still valid
use-cases, e.g. with HAProxy.

This patch adds its support in MPTCP by propagating the value to all
subflows.

Similar to mptcp_setsockopt_first_sf_only(), a generic helper
mptcp_setsockopt_all_subflows() is added to set sockopt for each
subflows of the mptcp socket.

Add a new member for struct mptcp_sock to store the TCP_MAXSEG value,
and return this value in getsockopt.

Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/515
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 net/mptcp/protocol.h |  1 +
 net/mptcp/sockopt.c  | 24 ++++++++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 64aa091cb685..91aaed17fe56 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -327,6 +327,7 @@ struct mptcp_sock {
 	int		keepalive_cnt;
 	int		keepalive_idle;
 	int		keepalive_intvl;
+	int		maxseg;
 	struct work_struct work;
 	struct sk_buff  *ooo_last_skb;
 	struct rb_root  out_of_order_queue;
diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
index 3caa0a9d3b38..a7992cbc5ed9 100644
--- a/net/mptcp/sockopt.c
+++ b/net/mptcp/sockopt.c
@@ -798,6 +798,22 @@ static int mptcp_setsockopt_first_sf_only(struct mptcp_sock *msk, int level, int
 	return ret;
 }
 
+static int mptcp_setsockopt_all_subflows(struct mptcp_sock *msk, int level, int optname,
+					 sockptr_t optval, unsigned int optlen)
+{
+	struct mptcp_subflow_context *subflow;
+
+	mptcp_for_each_subflow(msk, subflow) {
+		struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
+		int ret = 0;
+
+		ret = tcp_setsockopt(ssk, level, optname, optval, optlen);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
 static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
 				    sockptr_t optval, unsigned int optlen)
 {
@@ -859,6 +875,11 @@ static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
 						 &msk->keepalive_cnt,
 						 val);
 		break;
+	case TCP_MAXSEG:
+		msk->maxseg = val;
+		ret = mptcp_setsockopt_all_subflows(msk, SOL_TCP, optname,
+						    optval, optlen);
+		break;
 	default:
 		ret = -ENOPROTOOPT;
 	}
@@ -1407,6 +1428,8 @@ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
 		return mptcp_put_int_option(msk, optval, optlen, msk->notsent_lowat);
 	case TCP_IS_MPTCP:
 		return mptcp_put_int_option(msk, optval, optlen, 1);
+	case TCP_MAXSEG:
+		return mptcp_put_int_option(msk, optval, optlen, msk->maxseg);
 	}
 	return -EOPNOTSUPP;
 }
@@ -1553,6 +1576,7 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
 	tcp_sock_set_keepidle_locked(ssk, msk->keepalive_idle);
 	tcp_sock_set_keepintvl(ssk, msk->keepalive_intvl);
 	tcp_sock_set_keepcnt(ssk, msk->keepalive_cnt);
+	tcp_sock_set_maxseg(ssk, msk->maxseg);
 
 	inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
 	inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
-- 
2.43.0
Re: [PATCH mptcp-next v2 2/3] mptcp: add TCP_MAXSEG sockopt support
Posted by Matthieu Baerts 7 months, 2 weeks ago
Hi Geliang,

On 23/04/2025 11:40, Geliang Tang wrote:
> From: Geliang Tang <tanggeliang@kylinos.cn>
> 
> The TCP_MAXSEG socket option is currently not supported by MPTCP, mainly
> because it has never been requested before. But there are still valid
> use-cases, e.g. with HAProxy.
> 
> This patch adds its support in MPTCP by propagating the value to all
> subflows.
> 
> Similar to mptcp_setsockopt_first_sf_only(), a generic helper
> mptcp_setsockopt_all_subflows() is added to set sockopt for each
> subflows of the mptcp socket.
> 
> Add a new member for struct mptcp_sock to store the TCP_MAXSEG value,
> and return this value in getsockopt.
> 
> Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/515
> Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
> ---
>  net/mptcp/protocol.h |  1 +
>  net/mptcp/sockopt.c  | 24 ++++++++++++++++++++++++
>  2 files changed, 25 insertions(+)
> 
> diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> index 64aa091cb685..91aaed17fe56 100644
> --- a/net/mptcp/protocol.h
> +++ b/net/mptcp/protocol.h
> @@ -327,6 +327,7 @@ struct mptcp_sock {
>  	int		keepalive_cnt;
>  	int		keepalive_idle;
>  	int		keepalive_intvl;
> +	int		maxseg;
>  	struct work_struct work;
>  	struct sk_buff  *ooo_last_skb;
>  	struct rb_root  out_of_order_queue;
> diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
> index 3caa0a9d3b38..a7992cbc5ed9 100644
> --- a/net/mptcp/sockopt.c
> +++ b/net/mptcp/sockopt.c
> @@ -798,6 +798,22 @@ static int mptcp_setsockopt_first_sf_only(struct mptcp_sock *msk, int level, int
>  	return ret;
>  }
>  
> +static int mptcp_setsockopt_all_subflows(struct mptcp_sock *msk, int level, int optname,
> +					 sockptr_t optval, unsigned int optlen)
> +{
> +	struct mptcp_subflow_context *subflow;
> +
> +	mptcp_for_each_subflow(msk, subflow) {
> +		struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
> +		int ret = 0;
> +
> +		ret = tcp_setsockopt(ssk, level, optname, optval, optlen);
> +		if (ret)
> +			return ret;
> +	}
> +	return 0;
> +}
> +
>  static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
>  				    sockptr_t optval, unsigned int optlen)
>  {
> @@ -859,6 +875,11 @@ static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
>  						 &msk->keepalive_cnt,
>  						 val);
>  		break;
> +	case TCP_MAXSEG:
> +		msk->maxseg = val;
> +		ret = mptcp_setsockopt_all_subflows(msk, SOL_TCP, optname,
> +						    optval, optlen);
> +		break;
>  	default:
>  		ret = -ENOPROTOOPT;
>  	}
> @@ -1407,6 +1428,8 @@ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
>  		return mptcp_put_int_option(msk, optval, optlen, msk->notsent_lowat);
>  	case TCP_IS_MPTCP:
>  		return mptcp_put_int_option(msk, optval, optlen, 1);
> +	case TCP_MAXSEG:
> +		return mptcp_put_int_option(msk, optval, optlen, msk->maxseg);

I just checked what TCP is doing, and I see that this is different: with
TCP, the cached MSS is returned when the connection is not closed (and
something else for TCP_REPAIR). We should then do the same.

Should we then simply call mptcp_getsockopt_first_sf_only()?

>  	}
>  	return -EOPNOTSUPP;
>  }
> @@ -1553,6 +1576,7 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
>  	tcp_sock_set_keepidle_locked(ssk, msk->keepalive_idle);
>  	tcp_sock_set_keepintvl(ssk, msk->keepalive_intvl);
>  	tcp_sock_set_keepcnt(ssk, msk->keepalive_cnt);
> +	tcp_sock_set_maxseg(ssk, msk->maxseg);
>  
>  	inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
>  	inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));

Cheers,
Matt
-- 
Sponsored by the NGI0 Core fund.