Skip to content

Commit 9f1a988

Browse files
Paolo Abenidavem330
authored andcommitted
mptcp: process pending subflow error on close
On incoming TCP reset, subflow closing could happen before error propagation. That in turn could cause the socket error being ignored, and a missing socket state transition, as reported by Daire-Byrne. Address the issues explicitly checking for subflow socket error at close time. To avoid code duplication, factor-out of __mptcp_error_report() a new helper implementing the relevant bits. Closes: multipath-tcp/mptcp_net-next#429 Fixes: 15cc104 ("mptcp: deliver ssk errors to msk") Cc: [email protected] Signed-off-by: Paolo Abeni <[email protected]> Reviewed-by: Mat Martineau <[email protected]> Signed-off-by: Matthieu Baerts <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d5fbeff commit 9f1a988

File tree

1 file changed

+34
-29
lines changed

1 file changed

+34
-29
lines changed

net/mptcp/protocol.c

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -770,40 +770,44 @@ static bool __mptcp_ofo_queue(struct mptcp_sock *msk)
770770
return moved;
771771
}
772772

773-
void __mptcp_error_report(struct sock *sk)
773+
static bool __mptcp_subflow_error_report(struct sock *sk, struct sock *ssk)
774774
{
775-
struct mptcp_subflow_context *subflow;
776-
struct mptcp_sock *msk = mptcp_sk(sk);
775+
int err = sock_error(ssk);
776+
int ssk_state;
777777

778-
mptcp_for_each_subflow(msk, subflow) {
779-
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
780-
int err = sock_error(ssk);
781-
int ssk_state;
778+
if (!err)
779+
return false;
782780

783-
if (!err)
784-
continue;
781+
/* only propagate errors on fallen-back sockets or
782+
* on MPC connect
783+
*/
784+
if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(mptcp_sk(sk)))
785+
return false;
785786

786-
/* only propagate errors on fallen-back sockets or
787-
* on MPC connect
788-
*/
789-
if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(msk))
790-
continue;
787+
/* We need to propagate only transition to CLOSE state.
788+
* Orphaned socket will see such state change via
789+
* subflow_sched_work_if_closed() and that path will properly
790+
* destroy the msk as needed.
791+
*/
792+
ssk_state = inet_sk_state_load(ssk);
793+
if (ssk_state == TCP_CLOSE && !sock_flag(sk, SOCK_DEAD))
794+
inet_sk_state_store(sk, ssk_state);
795+
WRITE_ONCE(sk->sk_err, -err);
791796

792-
/* We need to propagate only transition to CLOSE state.
793-
* Orphaned socket will see such state change via
794-
* subflow_sched_work_if_closed() and that path will properly
795-
* destroy the msk as needed.
796-
*/
797-
ssk_state = inet_sk_state_load(ssk);
798-
if (ssk_state == TCP_CLOSE && !sock_flag(sk, SOCK_DEAD))
799-
inet_sk_state_store(sk, ssk_state);
800-
WRITE_ONCE(sk->sk_err, -err);
801-
802-
/* This barrier is coupled with smp_rmb() in mptcp_poll() */
803-
smp_wmb();
804-
sk_error_report(sk);
805-
break;
806-
}
797+
/* This barrier is coupled with smp_rmb() in mptcp_poll() */
798+
smp_wmb();
799+
sk_error_report(sk);
800+
return true;
801+
}
802+
803+
void __mptcp_error_report(struct sock *sk)
804+
{
805+
struct mptcp_subflow_context *subflow;
806+
struct mptcp_sock *msk = mptcp_sk(sk);
807+
808+
mptcp_for_each_subflow(msk, subflow)
809+
if (__mptcp_subflow_error_report(sk, mptcp_subflow_tcp_sock(subflow)))
810+
break;
807811
}
808812

809813
/* In most cases we will be able to lock the mptcp socket. If its already
@@ -2428,6 +2432,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
24282432
}
24292433

24302434
out_release:
2435+
__mptcp_subflow_error_report(sk, ssk);
24312436
release_sock(ssk);
24322437

24332438
sock_put(ssk);

0 commit comments

Comments
 (0)