Commit b81c6c99 authored by Matthieu Baerts (NGI0)'s avatar Matthieu Baerts (NGI0) Committed by Gang Yan
Browse files

tcp: socket option to check for MPTCP fallback to TCP

mainline inclusion
from mainline-v6.10-rc1
commit c084ebd77a00b1a16d9daa57b6ecdfdf1f43c78a
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I9VYQ9
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=c084ebd77a00b1a16d9daa57b6ecdfdf1f43c78a



--------------------------------

A way for an application to know if an MPTCP connection fell back to TCP
is to use getsockopt(MPTCP_INFO) and look for errors. The issue with
this technique is that the same errors -- EOPNOTSUPP (IPv4) and
ENOPROTOOPT (IPv6) -- are returned if there was a fallback, *or* if the
kernel doesn't support this socket option. The userspace then has to
look at the kernel version to understand what the errors mean.

It is not clean, and it doesn't take into account older kernels where
the socket option has been backported. A cleaner way would be to expose
this info to the TCP socket level. In case of MPTCP socket where no
fallback happened, the socket options for the TCP level will be handled
in MPTCP code, in mptcp_getsockopt_sol_tcp(). If not, that will be in
TCP code, in do_tcp_getsockopt(). So MPTCP simply has to set the value
1, while TCP has to set 0.

If the socket option is not supported, one of these two errors will be
reported:
- EOPNOTSUPP (95 - Operation not supported) for MPTCP sockets
- ENOPROTOOPT (92 - Protocol not available) for TCP sockets, e.g. on the
  socket received after an 'accept()', when the client didn't request to
  use MPTCP: this socket will be a TCP one, even if the listen socket
  was an MPTCP one.

With this new option, the kernel can return a clear answer to both "Is
this kernel new enough to tell me the fallback status?" and "If it is
new enough, is it currently a TCP or MPTCP socket?" questions, while not
breaking the previous method.

Acked-by: default avatarMat Martineau <martineau@kernel.org>
Signed-off-by: default avatarMatthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://lore.kernel.org/r/20240509-upstream-net-next-20240509-mptcp-tcp_is_mptcp-v1-1-f846df999202@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarGang Yan <yangang@kylinos.cn>
parent 8e007b4d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -129,6 +129,7 @@ enum {

#define TCP_TX_DELAY		37	/* delay outgoing packets by XX usec */

#define TCP_IS_MPTCP		43

#define TCP_REPAIR_ON		1
#define TCP_REPAIR_OFF		0
+3 −0
Original line number Diff line number Diff line
@@ -4297,6 +4297,9 @@ int do_tcp_getsockopt(struct sock *sk, int level,
		return err;
	}
#endif
	case TCP_IS_MPTCP:
		val = 0;
		break;
	default:
		return -ENOPROTOOPT;
	}
+2 −0
Original line number Diff line number Diff line
@@ -1401,6 +1401,8 @@ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
					    READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_probes));
	case TCP_NOTSENT_LOWAT:
		return mptcp_put_int_option(msk, optval, optlen, msk->notsent_lowat);
	case TCP_IS_MPTCP:
		return mptcp_put_int_option(msk, optval, optlen, 1);
	}
	return -EOPNOTSUPP;
}