Skip to content

Commit d582484

Browse files
Paolo Abenikuba-moo
authored andcommitted
mptcp: fix fallback for MP_JOIN subflows
Additional/MP_JOIN subflows that do not pass some initial handshake tests currently causes fallback to TCP. That is an RFC violation: we should instead reset the subflow and leave the the msk untouched. Closes: multipath-tcp/mptcp_net-next#91 Fixes: f296234 ("mptcp: Add handling of incoming MP_JOIN requests") Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 16cb365 commit d582484

File tree

3 files changed

+34
-9
lines changed

3 files changed

+34
-9
lines changed

net/mptcp/options.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,12 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
626626
if (unlikely(mptcp_check_fallback(sk)))
627627
return false;
628628

629+
/* prevent adding of any MPTCP related options on reset packet
630+
* until we support MP_TCPRST/MP_FASTCLOSE
631+
*/
632+
if (unlikely(skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST))
633+
return false;
634+
629635
if (mptcp_established_options_mp(sk, skb, &opt_size, remaining, opts))
630636
ret = true;
631637
else if (mptcp_established_options_dss(sk, skb, &opt_size, remaining,
@@ -676,7 +682,7 @@ bool mptcp_synack_options(const struct request_sock *req, unsigned int *size,
676682
return false;
677683
}
678684

679-
static bool check_fully_established(struct mptcp_sock *msk, struct sock *sk,
685+
static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
680686
struct mptcp_subflow_context *subflow,
681687
struct sk_buff *skb,
682688
struct mptcp_options_received *mp_opt)
@@ -693,15 +699,20 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *sk,
693699
TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq &&
694700
subflow->mp_join && mp_opt->mp_join &&
695701
READ_ONCE(msk->pm.server_side))
696-
tcp_send_ack(sk);
702+
tcp_send_ack(ssk);
697703
goto fully_established;
698704
}
699705

700-
/* we should process OoO packets before the first subflow is fully
701-
* established, but not expected for MP_JOIN subflows
706+
/* we must process OoO packets before the first subflow is fully
707+
* established. OoO packets are instead a protocol violation
708+
* for MP_JOIN subflows as the peer must not send any data
709+
* before receiving the forth ack - cfr. RFC 8684 section 3.2.
702710
*/
703-
if (TCP_SKB_CB(skb)->seq != subflow->ssn_offset + 1)
711+
if (TCP_SKB_CB(skb)->seq != subflow->ssn_offset + 1) {
712+
if (subflow->mp_join)
713+
goto reset;
704714
return subflow->mp_capable;
715+
}
705716

706717
if (mp_opt->dss && mp_opt->use_ack) {
707718
/* subflows are fully established as soon as we get any
@@ -713,9 +724,12 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *sk,
713724
}
714725

715726
/* If the first established packet does not contain MP_CAPABLE + data
716-
* then fallback to TCP
727+
* then fallback to TCP. Fallback scenarios requires a reset for
728+
* MP_JOIN subflows.
717729
*/
718730
if (!mp_opt->mp_capable) {
731+
if (subflow->mp_join)
732+
goto reset;
719733
subflow->mp_capable = 0;
720734
pr_fallback(msk);
721735
__mptcp_do_fallback(msk);
@@ -732,12 +746,16 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *sk,
732746

733747
subflow->pm_notified = 1;
734748
if (subflow->mp_join) {
735-
clear_3rdack_retransmission(sk);
749+
clear_3rdack_retransmission(ssk);
736750
mptcp_pm_subflow_established(msk, subflow);
737751
} else {
738752
mptcp_pm_fully_established(msk);
739753
}
740754
return true;
755+
756+
reset:
757+
mptcp_subflow_reset(ssk);
758+
return false;
741759
}
742760

743761
static u64 expand_ack(u64 old_ack, u64 cur_ack, bool use_64bit)

net/mptcp/protocol.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
348348
struct mptcp_options_received *mp_opt);
349349
bool mptcp_subflow_data_available(struct sock *sk);
350350
void __init mptcp_subflow_init(void);
351+
void mptcp_subflow_reset(struct sock *ssk);
351352

352353
/* called with sk socket lock held */
353354
int __mptcp_subflow_connect(struct sock *sk, int ifindex,

net/mptcp/subflow.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,13 @@ static bool subflow_thmac_valid(struct mptcp_subflow_context *subflow)
270270
return thmac == subflow->thmac;
271271
}
272272

273+
void mptcp_subflow_reset(struct sock *ssk)
274+
{
275+
tcp_set_state(ssk, TCP_CLOSE);
276+
tcp_send_active_reset(ssk, GFP_ATOMIC);
277+
tcp_done(ssk);
278+
}
279+
273280
static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
274281
{
275282
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
@@ -342,8 +349,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
342349
return;
343350

344351
do_reset:
345-
tcp_send_active_reset(sk, GFP_ATOMIC);
346-
tcp_done(sk);
352+
mptcp_subflow_reset(sk);
347353
}
348354

349355
struct request_sock_ops mptcp_subflow_request_sock_ops;

0 commit comments

Comments
 (0)