Skip to content

Commit 332e019

Browse files
Paolo Abenimatttbe
Paolo Abeni
authored andcommitted
mptcp: do not reset MP_CAPABLE subflow on mapping errors
When some mapping related errors occurs 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: #192 Reported-by: Matthieu Baerts <matthieu.baerts@tessares.net> Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent 0a589b4 commit 332e019

File tree

1 file changed

+32
-30
lines changed

1 file changed

+32
-30
lines changed

net/mptcp/subflow.c

+32-30
Original file line numberDiff line numberDiff line change
@@ -1011,21 +1011,11 @@ static bool subflow_check_data_avail(struct sock *ssk)
10111011

10121012
status = get_mapping_status(ssk, msk);
10131013
trace_subflow_check_data_avail(status, skb_peek(&ssk->sk_receive_queue));
1014-
if (status == MAPPING_INVALID) {
1015-
ssk->sk_err = EBADMSG;
1016-
goto fatal;
1017-
}
1018-
if (status == MAPPING_DUMMY) {
1019-
__mptcp_do_fallback(msk);
1020-
skb = skb_peek(&ssk->sk_receive_queue);
1021-
subflow->map_valid = 1;
1022-
subflow->map_seq = READ_ONCE(msk->ack_seq);
1023-
subflow->map_data_len = skb->len;
1024-
subflow->map_subflow_seq = tcp_sk(ssk)->copied_seq -
1025-
subflow->ssn_offset;
1026-
subflow->data_avail = MPTCP_SUBFLOW_DATA_AVAIL;
1027-
return true;
1028-
}
1014+
if (unlikely(status == MAPPING_INVALID))
1015+
goto fallback;
1016+
1017+
if (unlikely(status == MAPPING_DUMMY))
1018+
goto fallback;
10291019

10301020
if (status != MAPPING_OK)
10311021
goto no_data;
@@ -1038,10 +1028,8 @@ static bool subflow_check_data_avail(struct sock *ssk)
10381028
* MP_CAPABLE-based mapping
10391029
*/
10401030
if (unlikely(!READ_ONCE(msk->can_ack))) {
1041-
if (!subflow->mpc_map) {
1042-
ssk->sk_err = EBADMSG;
1043-
goto fatal;
1044-
}
1031+
if (!subflow->mpc_map)
1032+
goto fallback;
10451033
WRITE_ONCE(msk->remote_key, subflow->remote_key);
10461034
WRITE_ONCE(msk->ack_seq, subflow->map_seq);
10471035
WRITE_ONCE(msk->can_ack, true);
@@ -1069,17 +1057,31 @@ static bool subflow_check_data_avail(struct sock *ssk)
10691057
no_data:
10701058
subflow_sched_work_if_closed(msk, ssk);
10711059
return false;
1072-
fatal:
1073-
/* fatal protocol error, close the socket */
1074-
/* This barrier is coupled with smp_rmb() in tcp_poll() */
1075-
smp_wmb();
1076-
ssk->sk_error_report(ssk);
1077-
tcp_set_state(ssk, TCP_CLOSE);
1078-
subflow->reset_transient = 0;
1079-
subflow->reset_reason = MPTCP_RST_EMPTCP;
1080-
tcp_send_active_reset(ssk, GFP_ATOMIC);
1081-
subflow->data_avail = 0;
1082-
return false;
1060+
1061+
fallback:
1062+
/* RFC 8684 section 3.7. */
1063+
if (subflow->mp_join || subflow->fully_established) {
1064+
/* fatal protocol error, close the socket.
1065+
* subflow_error_report() will introduce the appropriate barriers
1066+
*/
1067+
ssk->sk_err = EBADMSG;
1068+
ssk->sk_error_report(ssk);
1069+
tcp_set_state(ssk, TCP_CLOSE);
1070+
subflow->reset_transient = 0;
1071+
subflow->reset_reason = MPTCP_RST_EMPTCP;
1072+
tcp_send_active_reset(ssk, GFP_ATOMIC);
1073+
subflow->data_avail = 0;
1074+
return false;
1075+
}
1076+
1077+
__mptcp_do_fallback(msk);
1078+
skb = skb_peek(&ssk->sk_receive_queue);
1079+
subflow->map_valid = 1;
1080+
subflow->map_seq = READ_ONCE(msk->ack_seq);
1081+
subflow->map_data_len = skb->len;
1082+
subflow->map_subflow_seq = tcp_sk(ssk)->copied_seq - subflow->ssn_offset;
1083+
subflow->data_avail = MPTCP_SUBFLOW_DATA_AVAIL;
1084+
return true;
10831085
}
10841086

10851087
bool mptcp_subflow_data_available(struct sock *sk)

0 commit comments

Comments
 (0)