Commit 718d6e86 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'tcp-user_mss-and-tcp_maxseg-series'

Eric Dumazet says:

====================
tcp: user_mss and TCP_MAXSEG series

Annotate data-races around tp->rx_opt.user_mss and make
TCP_MAXSEG lockless.
====================

Link: https://patch.msgid.link/20250821141901.18839-1-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 02614eee 9217146f
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -951,6 +951,7 @@ static unsigned int chtls_select_mss(const struct chtls_sock *csk,
	struct tcp_sock *tp;
	unsigned int mss;
	struct sock *sk;
	u16 user_mss;

	mss = ntohs(req->tcpopt.mss);
	sk = csk->sk;
@@ -969,8 +970,9 @@ static unsigned int chtls_select_mss(const struct chtls_sock *csk,
		tcpoptsz += round_up(TCPOLEN_TIMESTAMP, 4);

	tp->advmss = dst_metric_advmss(dst);
	if (USER_MSS(tp) && tp->advmss > USER_MSS(tp))
		tp->advmss = USER_MSS(tp);
	user_mss = USER_MSS(tp);
	if (user_mss && tp->advmss > user_mss)
		tp->advmss = user_mss;
	if (tp->advmss > pmtu - iphdrsz)
		tp->advmss = pmtu - iphdrsz;
	if (mss && tp->advmss > mss)
+1 −1
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ struct deferred_skb_cb {

#define SND_WSCALE(tp) ((tp)->rx_opt.snd_wscale)
#define RCV_WSCALE(tp) ((tp)->rx_opt.rcv_wscale)
#define USER_MSS(tp) ((tp)->rx_opt.user_mss)
#define USER_MSS(tp) (READ_ONCE((tp)->rx_opt.user_mss))
#define TS_RECENT_STAMP(tp) ((tp)->rx_opt.ts_recent_stamp)
#define WSCALE_OK(tp) ((tp)->rx_opt.wscale_ok)
#define TSTAMP_OK(tp) ((tp)->rx_opt.tstamp_ok)
+7 −7
Original line number Diff line number Diff line
@@ -3760,7 +3760,7 @@ int tcp_sock_set_maxseg(struct sock *sk, int val)
	if (val && (val < TCP_MIN_MSS || val > MAX_TCP_WINDOW))
		return -EINVAL;

	tcp_sk(sk)->rx_opt.user_mss = val;
	WRITE_ONCE(tcp_sk(sk)->rx_opt.user_mss, val);
	return 0;
}

@@ -3890,15 +3890,13 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
		WRITE_ONCE(inet_csk(sk)->icsk_delack_max, delack_max);
		return 0;
	}
	case TCP_MAXSEG:
		return tcp_sock_set_maxseg(sk, val);
	}

	sockopt_lock_sock(sk);

	switch (optname) {
	case TCP_MAXSEG:
		err = tcp_sock_set_maxseg(sk, val);
		break;

	case TCP_NODELAY:
		__tcp_sock_set_nodelay(sk, val);
		break;
@@ -4383,6 +4381,7 @@ int do_tcp_getsockopt(struct sock *sk, int level,
	struct inet_connection_sock *icsk = inet_csk(sk);
	struct tcp_sock *tp = tcp_sk(sk);
	struct net *net = sock_net(sk);
	int user_mss;
	int val, len;

	if (copy_from_sockptr(&len, optlen, sizeof(int)))
@@ -4396,9 +4395,10 @@ int do_tcp_getsockopt(struct sock *sk, int level,
	switch (optname) {
	case TCP_MAXSEG:
		val = tp->mss_cache;
		if (tp->rx_opt.user_mss &&
		user_mss = READ_ONCE(tp->rx_opt.user_mss);
		if (user_mss &&
		    ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)))
			val = tp->rx_opt.user_mss;
			val = user_mss;
		if (tp->repair)
			val = tp->rx_opt.mss_clamp;
		break;
+4 −4
Original line number Diff line number Diff line
@@ -6297,7 +6297,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
	u16 mss = tp->rx_opt.mss_clamp, try_exp = 0;
	bool syn_drop = false;

	if (mss == tp->rx_opt.user_mss) {
	if (mss == READ_ONCE(tp->rx_opt.user_mss)) {
		struct tcp_options_received opt;

		/* Get original SYNACK MSS value if user MSS sets mss_clamp */
@@ -7117,7 +7117,7 @@ u16 tcp_get_syncookie_mss(struct request_sock_ops *rsk_ops,
		return 0;
	}

	mss = tcp_parse_mss_option(th, tp->rx_opt.user_mss);
	mss = tcp_parse_mss_option(th, READ_ONCE(tp->rx_opt.user_mss));
	if (!mss)
		mss = af_ops->mss_clamp;

@@ -7131,7 +7131,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
{
	struct tcp_fastopen_cookie foc = { .len = -1 };
	struct tcp_options_received tmp_opt;
	struct tcp_sock *tp = tcp_sk(sk);
	const struct tcp_sock *tp = tcp_sk(sk);
	struct net *net = sock_net(sk);
	struct sock *fastopen_sk = NULL;
	struct request_sock *req;
@@ -7182,7 +7182,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,

	tcp_clear_options(&tmp_opt);
	tmp_opt.mss_clamp = af_ops->mss_clamp;
	tmp_opt.user_mss  = tp->rx_opt.user_mss;
	tmp_opt.user_mss  = READ_ONCE(tp->rx_opt.user_mss);
	tcp_parse_options(sock_net(sk), skb, &tmp_opt, 0,
			  want_cookie ? NULL : &foc);

+4 −2
Original line number Diff line number Diff line
@@ -3890,6 +3890,7 @@ static void tcp_connect_init(struct sock *sk)
	const struct dst_entry *dst = __sk_dst_get(sk);
	struct tcp_sock *tp = tcp_sk(sk);
	__u8 rcv_wscale;
	u16 user_mss;
	u32 rcv_wnd;

	/* We'll fix this up when we get a response from the other end.
@@ -3902,8 +3903,9 @@ static void tcp_connect_init(struct sock *sk)
	tcp_ao_connect_init(sk);

	/* If user gave his TCP_MAXSEG, record it to clamp */
	if (tp->rx_opt.user_mss)
		tp->rx_opt.mss_clamp = tp->rx_opt.user_mss;
	user_mss = READ_ONCE(tp->rx_opt.user_mss);
	if (user_mss)
		tp->rx_opt.mss_clamp = user_mss;
	tp->max_window = 0;
	tcp_mtup_init(sk);
	tcp_sync_mss(sk, dst_mtu(dst));