Skip to content

Commit

Permalink
mptcp: Do TCP fallback on early DSS checksum failure
Browse files Browse the repository at this point in the history
commit ae66fb2 upstream.

RFC 8684 section 3.7 describes several opportunities for a MPTCP
connection to "fall back" to regular TCP early in the connection
process, before it has been confirmed that MPTCP options can be
successfully propagated on all SYN, SYN/ACK, and data packets. If a peer
acknowledges the first received data packet with a regular TCP header
(no MPTCP options), fallback is allowed.

If the recipient of that first data packet finds a MPTCP DSS checksum
error, this provides an opportunity to fail gracefully with a TCP
fallback rather than resetting the connection (as might happen if a
checksum failure were detected later).

This commit modifies the checksum failure code to attempt fallback on
the initial subflow of a MPTCP connection, only if it's a failure in the
first data mapping. In cases where the peer initiates the connection,
requests checksums, is the first to send data, and the peer is sending
incorrect checksums (see
multipath-tcp/mptcp_net-next#275), this allows
the connection to proceed as TCP rather than reset.

Fixes: dd8bcd1 ("mptcp: validate the data checksum")
Acked-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[mathew.j.martineau: backport: Resolved bitfield conflict in protocol.h]
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
mjmartineau authored and gregkh committed May 25, 2022
1 parent 6c468bb commit 2973647
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 4 deletions.
3 changes: 2 additions & 1 deletion net/mptcp/protocol.h
Expand Up @@ -442,7 +442,8 @@ struct mptcp_subflow_context {
rx_eof : 1,
can_ack : 1, /* only after processing the remote a key */
disposable : 1, /* ctx can be free at ulp release time */
stale : 1; /* unable to snd/rcv data, do not use for xmit */
stale : 1, /* unable to snd/rcv data, do not use for xmit */
valid_csum_seen : 1; /* at least one csum validated */
enum mptcp_data_avail data_avail;
u32 remote_nonce;
u64 thmac;
Expand Down
21 changes: 18 additions & 3 deletions net/mptcp/subflow.c
Expand Up @@ -913,11 +913,14 @@ static enum mapping_status validate_data_csum(struct sock *ssk, struct sk_buff *
subflow->map_data_csum);
if (unlikely(csum)) {
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DATACSUMERR);
subflow->send_mp_fail = 1;
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPFAILTX);
if (subflow->mp_join || subflow->valid_csum_seen) {
subflow->send_mp_fail = 1;
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPFAILTX);
}
return subflow->mp_join ? MAPPING_INVALID : MAPPING_DUMMY;
}

subflow->valid_csum_seen = 1;
return MAPPING_OK;
}

Expand Down Expand Up @@ -1099,6 +1102,18 @@ static void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ss
}
}

static bool subflow_can_fallback(struct mptcp_subflow_context *subflow)
{
struct mptcp_sock *msk = mptcp_sk(subflow->conn);

if (subflow->mp_join)
return false;
else if (READ_ONCE(msk->csum_enabled))
return !subflow->valid_csum_seen;
else
return !subflow->fully_established;
}

static bool subflow_check_data_avail(struct sock *ssk)
{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
Expand Down Expand Up @@ -1176,7 +1191,7 @@ static bool subflow_check_data_avail(struct sock *ssk)
return true;
}

if (subflow->mp_join || subflow->fully_established) {
if (!subflow_can_fallback(subflow)) {
/* fatal protocol error, close the socket.
* subflow_error_report() will introduce the appropriate barriers
*/
Expand Down

0 comments on commit 2973647

Please sign in to comment.