Skip to content

Commit

Permalink
mptcp: do not reset MP_CAPABLE subflow on mapping errors
Browse files Browse the repository at this point in the history
When some mapping related errors occours we close the main
MPC subflow with a RST. We should instead fallback gracefully
to TCP, and do the reset only for MPJ subflows.

Fixes: d22f498 ("mptcp: process MP_CAPABLE data option")
Closes: multipath-tcp/mptcp_net-next#192
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Paolo Abeni authored and intel-lab-lkp committed May 22, 2021
1 parent fe7fe52 commit a288133
Showing 1 changed file with 20 additions and 20 deletions.
40 changes: 20 additions & 20 deletions net/mptcp/subflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -1109,10 +1109,9 @@ static bool subflow_check_data_avail(struct sock *ssk)

status = get_mapping_status(ssk, msk);
trace_subflow_check_data_avail(status, skb_peek(&ssk->sk_receive_queue));
if (unlikely(status == MAPPING_INVALID)) {
ssk->sk_err = EBADMSG;
goto fatal;
}
if (unlikely(status == MAPPING_INVALID))
goto fallback;

if (unlikely(status == MAPPING_DUMMY))
goto fallback;

Expand All @@ -1127,10 +1126,8 @@ static bool subflow_check_data_avail(struct sock *ssk)
* MP_CAPABLE-based mapping
*/
if (unlikely(!READ_ONCE(msk->can_ack))) {
if (!subflow->mpc_map) {
ssk->sk_err = EBADMSG;
goto fatal;
}
if (!subflow->mpc_map)
goto fallback;
WRITE_ONCE(msk->remote_key, subflow->remote_key);
WRITE_ONCE(msk->ack_seq, subflow->map_seq);
WRITE_ONCE(msk->can_ack, true);
Expand Down Expand Up @@ -1159,19 +1156,22 @@ static bool subflow_check_data_avail(struct sock *ssk)
subflow_sched_work_if_closed(msk, ssk);
return false;

fatal:
/* fatal protocol error, close the socket */
/* This barrier is coupled with smp_rmb() in tcp_poll() */
smp_wmb();
ssk->sk_error_report(ssk);
tcp_set_state(ssk, TCP_CLOSE);
subflow->reset_transient = 0;
subflow->reset_reason = MPTCP_RST_EMPTCP;
tcp_send_active_reset(ssk, GFP_ATOMIC);
subflow->data_avail = 0;
return false;

fallback:
/* RFC 8684 section 3.7. */
if (subflow->mp_join || subflow->fully_established) {
/* fatal protocol error, close the socket.
* subflow_error_report() will introduce the apprpriate barriers
*/
ssk->sk_err = EBADMSG;
ssk->sk_error_report(ssk);
tcp_set_state(ssk, TCP_CLOSE);
subflow->reset_transient = 0;
subflow->reset_reason = MPTCP_RST_EMPTCP;
tcp_send_active_reset(ssk, GFP_ATOMIC);
subflow->data_avail = 0;
return false;
}

__mptcp_do_fallback(msk);
skb = skb_peek(&ssk->sk_receive_queue);
subflow->map_valid = 1;
Expand Down

0 comments on commit a288133

Please sign in to comment.