Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'mptcp-add-tcp_maxseg-sockopt-support'

Matthieu Baerts says:

====================
mptcp: add TCP_MAXSEG sockopt support

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

- Patch 1 is a small cleanup patch in the MPTCP sockopt file.

- Patch 2 expose some code from TCP, to avoid duplicating it in MPTCP.

- Patch 3 adds TCP_MAXSEG sockopt support in MPTCP.

- Patch 4 is not related to the others, it fixes a typo in a comment.

Note that the new TCP_MAXSEG sockopt support has been validated by a new
packetdrill script on the MPTCP CI:

https://github.com/multipath-tcp/packetdrill/pull/161

v1: https://lore.kernel.org/20250716-net-next-mptcp-tcp_maxseg-v1-0-548d3a5666f6@kernel.org
====================

Link: https://patch.msgid.link/20250719-net-next-mptcp-tcp_maxseg-v2-0-8c910fbc5307@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+46 -14
+1
include/linux/tcp.h
··· 621 621 void tcp_sock_set_quickack(struct sock *sk, int val); 622 622 int tcp_sock_set_syncnt(struct sock *sk, int val); 623 623 int tcp_sock_set_user_timeout(struct sock *sk, int val); 624 + int tcp_sock_set_maxseg(struct sock *sk, int val); 624 625 625 626 static inline bool dst_tcp_usec_ts(const struct dst_entry *dst) 626 627 {
+14 -9
net/ipv4/tcp.c
··· 3751 3751 return 0; 3752 3752 } 3753 3753 3754 + int tcp_sock_set_maxseg(struct sock *sk, int val) 3755 + { 3756 + /* Values greater than interface MTU won't take effect. However 3757 + * at the point when this call is done we typically don't yet 3758 + * know which interface is going to be used 3759 + */ 3760 + if (val && (val < TCP_MIN_MSS || val > MAX_TCP_WINDOW)) 3761 + return -EINVAL; 3762 + 3763 + tcp_sk(sk)->rx_opt.user_mss = val; 3764 + return 0; 3765 + } 3766 + 3754 3767 /* 3755 3768 * Socket option code for TCP. 3756 3769 */ ··· 3896 3883 3897 3884 switch (optname) { 3898 3885 case TCP_MAXSEG: 3899 - /* Values greater than interface MTU won't take effect. However 3900 - * at the point when this call is done we typically don't yet 3901 - * know which interface is going to be used 3902 - */ 3903 - if (val && (val < TCP_MIN_MSS || val > MAX_TCP_WINDOW)) { 3904 - err = -EINVAL; 3905 - break; 3906 - } 3907 - tp->rx_opt.user_mss = val; 3886 + err = tcp_sock_set_maxseg(sk, val); 3908 3887 break; 3909 3888 3910 3889 case TCP_NODELAY:
+1 -1
net/mptcp/protocol.c
··· 1387 1387 * - estimate the faster flow linger time 1388 1388 * - use the above to estimate the amount of byte transferred 1389 1389 * by the faster flow 1390 - * - check that the amount of queued data is greter than the above, 1390 + * - check that the amount of queued data is greater than the above, 1391 1391 * otherwise do not use the picked, slower, subflow 1392 1392 * We select the subflow with the shorter estimated time to flush 1393 1393 * the queued mem, which basically ensure the above. We just need
+1
net/mptcp/protocol.h
··· 326 326 int keepalive_cnt; 327 327 int keepalive_idle; 328 328 int keepalive_intvl; 329 + int maxseg; 329 330 struct work_struct work; 330 331 struct sk_buff *ooo_last_skb; 331 332 struct rb_root out_of_order_queue;
+29 -4
net/mptcp/sockopt.c
··· 798 798 return ret; 799 799 } 800 800 801 + static int mptcp_setsockopt_all_sf(struct mptcp_sock *msk, int level, 802 + int optname, sockptr_t optval, 803 + unsigned int optlen) 804 + { 805 + struct mptcp_subflow_context *subflow; 806 + int ret = 0; 807 + 808 + mptcp_for_each_subflow(msk, subflow) { 809 + struct sock *ssk = mptcp_subflow_tcp_sock(subflow); 810 + 811 + ret = tcp_setsockopt(ssk, level, optname, optval, optlen); 812 + if (ret) 813 + break; 814 + } 815 + return ret; 816 + } 817 + 801 818 static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname, 802 819 sockptr_t optval, unsigned int optlen) 803 820 { ··· 876 859 &msk->keepalive_cnt, 877 860 val); 878 861 break; 862 + case TCP_MAXSEG: 863 + msk->maxseg = val; 864 + ret = mptcp_setsockopt_all_sf(msk, SOL_TCP, optname, optval, 865 + optlen); 866 + break; 879 867 default: 880 868 ret = -ENOPROTOOPT; 881 869 } ··· 936 914 937 915 lock_sock(sk); 938 916 ssk = msk->first; 939 - if (ssk) { 940 - ret = tcp_getsockopt(ssk, level, optname, optval, optlen); 941 - goto out; 942 - } 917 + if (ssk) 918 + goto get; 943 919 944 920 ssk = __mptcp_nmpc_sk(msk); 945 921 if (IS_ERR(ssk)) { ··· 945 925 goto out; 946 926 } 947 927 928 + get: 948 929 ret = tcp_getsockopt(ssk, level, optname, optval, optlen); 949 930 950 931 out: ··· 1428 1407 return mptcp_put_int_option(msk, optval, optlen, msk->notsent_lowat); 1429 1408 case TCP_IS_MPTCP: 1430 1409 return mptcp_put_int_option(msk, optval, optlen, 1); 1410 + case TCP_MAXSEG: 1411 + return mptcp_getsockopt_first_sf_only(msk, SOL_TCP, optname, 1412 + optval, optlen); 1431 1413 } 1432 1414 return -EOPNOTSUPP; 1433 1415 } ··· 1577 1553 tcp_sock_set_keepidle_locked(ssk, msk->keepalive_idle); 1578 1554 tcp_sock_set_keepintvl(ssk, msk->keepalive_intvl); 1579 1555 tcp_sock_set_keepcnt(ssk, msk->keepalive_cnt); 1556 + tcp_sock_set_maxseg(ssk, msk->maxseg); 1580 1557 1581 1558 inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk)); 1582 1559 inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));