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
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
#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>
  • Loading branch information
mjmartineau authored and matttbe committed May 19, 2022
1 parent bbf84da commit 235188e
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 @@ -443,7 +443,8 @@ struct mptcp_subflow_context {
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 */
local_id_valid : 1; /* local_id is correctly initialized */
local_id_valid : 1, /* local_id is correctly initialized */
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 @@ -955,11 +955,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 @@ -1141,6 +1144,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 @@ -1218,7 +1233,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 235188e

Please sign in to comment.