Commit 988998ac authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mptcp-tcp-fallback'



Mat Martineau says:

====================
mptcp: TCP fallback for established connections

RFC 8684 allows some MPTCP connections to fall back to regular TCP when
the MPTCP DSS checksum detects middlebox interference, there is only a
single subflow, and there is no unacknowledged out-of-sequence
data. When this condition is detected, the stack sends a MPTCP DSS
option with an "infinite mapping" to signal that a fallback is
happening, and the peers will stop sending MPTCP options in their TCP
headers. The Linux MPTCP stack has not yet supported this type of
fallback, instead closing the connection when the MPTCP checksum fails.

This series adds support for fallback to regular TCP in a more limited
scenario, for only MPTCP connections that have never connected
additional subflows or transmitted out-of-sequence data. The selftests
are also updated to check new MIBs that track infinite mappings.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 31693d02 8bd03be3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -35,7 +35,8 @@ struct mptcp_ext {
			frozen:1,
			reset_transient:1;
	u8		reset_reason:4,
			csum_reqd:1;
			csum_reqd:1,
			infinite_map:1;
};

#define MPTCP_RM_IDS_MAX	8
+4 −2
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
		__field(u8, reset_transient)
		__field(u8, reset_reason)
		__field(u8, csum_reqd)
		__field(u8, infinite_map)
	),

	TP_fast_assign(
@@ -102,9 +103,10 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
		__entry->reset_transient = mpext->reset_transient;
		__entry->reset_reason = mpext->reset_reason;
		__entry->csum_reqd = mpext->csum_reqd;
		__entry->infinite_map = mpext->infinite_map;
	),

	TP_printk("data_ack=%llu data_seq=%llu subflow_seq=%u data_len=%u csum=%x use_map=%u dsn64=%u data_fin=%u use_ack=%u ack64=%u mpc_map=%u frozen=%u reset_transient=%u reset_reason=%u csum_reqd=%u",
	TP_printk("data_ack=%llu data_seq=%llu subflow_seq=%u data_len=%u csum=%x use_map=%u dsn64=%u data_fin=%u use_ack=%u ack64=%u mpc_map=%u frozen=%u reset_transient=%u reset_reason=%u csum_reqd=%u infinite_map=%u",
		  __entry->data_ack, __entry->data_seq,
		  __entry->subflow_seq, __entry->data_len,
		  __entry->csum, __entry->use_map,
@@ -112,7 +114,7 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
		  __entry->use_ack, __entry->ack64,
		  __entry->mpc_map, __entry->frozen,
		  __entry->reset_transient, __entry->reset_reason,
		  __entry->csum_reqd)
		  __entry->csum_reqd, __entry->infinite_map)
);

DEFINE_EVENT(mptcp_dump_mpext, mptcp_sendmsg_frag,
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ static const struct snmp_mib mptcp_snmp_list[] = {
	SNMP_MIB_ITEM("MPJoinAckRx", MPTCP_MIB_JOINACKRX),
	SNMP_MIB_ITEM("MPJoinAckHMacFailure", MPTCP_MIB_JOINACKMAC),
	SNMP_MIB_ITEM("DSSNotMatching", MPTCP_MIB_DSSNOMATCH),
	SNMP_MIB_ITEM("InfiniteMapTx", MPTCP_MIB_INFINITEMAPTX),
	SNMP_MIB_ITEM("InfiniteMapRx", MPTCP_MIB_INFINITEMAPRX),
	SNMP_MIB_ITEM("DSSNoMatchTCP", MPTCP_MIB_DSSTCPMISMATCH),
	SNMP_MIB_ITEM("DataCsumErr", MPTCP_MIB_DATACSUMERR),
+1 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ enum linux_mptcp_mib_field {
	MPTCP_MIB_JOINACKRX,		/* Received an ACK + MP_JOIN */
	MPTCP_MIB_JOINACKMAC,		/* HMAC was wrong on ACK + MP_JOIN */
	MPTCP_MIB_DSSNOMATCH,		/* Received a new mapping that did not match the previous one */
	MPTCP_MIB_INFINITEMAPTX,	/* Sent an infinite mapping */
	MPTCP_MIB_INFINITEMAPRX,	/* Received an infinite mapping */
	MPTCP_MIB_DSSTCPMISMATCH,	/* DSS-mapping did not map with TCP's sequence numbers */
	MPTCP_MIB_DATACSUMERR,		/* The data checksum fail */
+6 −2
Original line number Diff line number Diff line
@@ -825,7 +825,7 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,

	opts->suboptions = 0;

	if (unlikely(__mptcp_check_fallback(msk)))
	if (unlikely(__mptcp_check_fallback(msk) && !mptcp_check_infinite_map(skb)))
		return false;

	if (unlikely(skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST)) {
@@ -1340,8 +1340,12 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
			put_unaligned_be32(mpext->subflow_seq, ptr);
			ptr += 1;
			if (opts->csum_reqd) {
				/* data_len == 0 is reserved for the infinite mapping,
				 * the checksum will also be set to 0.
				 */
				put_unaligned_be32(mpext->data_len << 16 |
						   mptcp_make_csum(mpext), ptr);
						   (mpext->data_len ? mptcp_make_csum(mpext) : 0),
						   ptr);
			} else {
				put_unaligned_be32(mpext->data_len << 16 |
						   TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
Loading