Skip to content

Commit e1ff9e8

Browse files
dcarattidavem330
authored andcommitted
net: mptcp: improve fallback to TCP
Keep using MPTCP sockets and a use "dummy mapping" in case of fallback to regular TCP. When fallback is triggered, skip addition of the MPTCP option on send. Closes: multipath-tcp/mptcp_net-next#11 Closes: multipath-tcp/mptcp_net-next#22 Co-developed-by: Paolo Abeni <[email protected]> Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Davide Caratti <[email protected]> Reviewed-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e117033 commit e1ff9e8

File tree

4 files changed

+98
-89
lines changed

4 files changed

+98
-89
lines changed

net/mptcp/options.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,9 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
624624

625625
opts->suboptions = 0;
626626

627+
if (unlikely(mptcp_check_fallback(sk)))
628+
return false;
629+
627630
if (mptcp_established_options_mp(sk, skb, &opt_size, remaining, opts))
628631
ret = true;
629632
else if (mptcp_established_options_dss(sk, skb, &opt_size, remaining,
@@ -714,7 +717,8 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *sk,
714717
*/
715718
if (!mp_opt->mp_capable) {
716719
subflow->mp_capable = 0;
717-
tcp_sk(sk)->is_mptcp = 0;
720+
pr_fallback(msk);
721+
__mptcp_do_fallback(msk);
718722
return false;
719723
}
720724

@@ -814,6 +818,9 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
814818
struct mptcp_options_received mp_opt;
815819
struct mptcp_ext *mpext;
816820

821+
if (__mptcp_check_fallback(msk))
822+
return;
823+
817824
mptcp_get_options(skb, &mp_opt);
818825
if (!check_fully_established(msk, sk, subflow, skb, &mp_opt))
819826
return;

net/mptcp/protocol.c

Lines changed: 26 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,6 @@ static struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk)
5252
return msk->subflow;
5353
}
5454

55-
static bool __mptcp_needs_tcp_fallback(const struct mptcp_sock *msk)
56-
{
57-
return msk->first && !sk_is_mptcp(msk->first);
58-
}
59-
6055
static struct socket *mptcp_is_tcpsk(struct sock *sk)
6156
{
6257
struct socket *sock = sk->sk_socket;
@@ -94,7 +89,7 @@ static struct socket *__mptcp_tcp_fallback(struct mptcp_sock *msk)
9489
if (unlikely(sock))
9590
return sock;
9691

97-
if (likely(!__mptcp_needs_tcp_fallback(msk)))
92+
if (likely(!__mptcp_check_fallback(msk)))
9893
return NULL;
9994

10095
return msk->subflow;
@@ -133,6 +128,11 @@ static struct socket *__mptcp_socket_create(struct mptcp_sock *msk, int state)
133128
list_add(&subflow->node, &msk->conn_list);
134129
subflow->request_mptcp = 1;
135130

131+
/* accept() will wait on first subflow sk_wq, and we always wakes up
132+
* via msk->sk_socket
133+
*/
134+
RCU_INIT_POINTER(msk->first->sk_wq, &sk->sk_socket->wq);
135+
136136
set_state:
137137
if (state != MPTCP_SAME_STATE)
138138
inet_sk_state_store(sk, state);
@@ -229,6 +229,15 @@ static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,
229229
if (!skb)
230230
break;
231231

232+
if (__mptcp_check_fallback(msk)) {
233+
/* if we are running under the workqueue, TCP could have
234+
* collapsed skbs between dummy map creation and now
235+
* be sure to adjust the size
236+
*/
237+
map_remaining = skb->len;
238+
subflow->map_data_len = skb->len;
239+
}
240+
232241
offset = seq - TCP_SKB_CB(skb)->seq;
233242
fin = TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN;
234243
if (fin) {
@@ -466,8 +475,15 @@ static void mptcp_clean_una(struct sock *sk)
466475
{
467476
struct mptcp_sock *msk = mptcp_sk(sk);
468477
struct mptcp_data_frag *dtmp, *dfrag;
469-
u64 snd_una = atomic64_read(&msk->snd_una);
470478
bool cleaned = false;
479+
u64 snd_una;
480+
481+
/* on fallback we just need to ignore snd_una, as this is really
482+
* plain TCP
483+
*/
484+
if (__mptcp_check_fallback(msk))
485+
atomic64_set(&msk->snd_una, msk->write_seq);
486+
snd_una = atomic64_read(&msk->snd_una);
471487

472488
list_for_each_entry_safe(dfrag, dtmp, &msk->rtx_queue, list) {
473489
if (after64(dfrag->data_seq + dfrag->data_len, snd_una))
@@ -740,7 +756,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
740756
int mss_now = 0, size_goal = 0, ret = 0;
741757
struct mptcp_sock *msk = mptcp_sk(sk);
742758
struct page_frag *pfrag;
743-
struct socket *ssock;
744759
size_t copied = 0;
745760
struct sock *ssk;
746761
bool tx_ok;
@@ -759,15 +774,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
759774
goto out;
760775
}
761776

762-
fallback:
763-
ssock = __mptcp_tcp_fallback(msk);
764-
if (unlikely(ssock)) {
765-
release_sock(sk);
766-
pr_debug("fallback passthrough");
767-
ret = sock_sendmsg(ssock, msg);
768-
return ret >= 0 ? ret + copied : (copied ? copied : ret);
769-
}
770-
771777
pfrag = sk_page_frag(sk);
772778
restart:
773779
mptcp_clean_una(sk);
@@ -819,17 +825,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
819825
}
820826
break;
821827
}
822-
if (ret == 0 && unlikely(__mptcp_needs_tcp_fallback(msk))) {
823-
/* Can happen for passive sockets:
824-
* 3WHS negotiated MPTCP, but first packet after is
825-
* plain TCP (e.g. due to middlebox filtering unknown
826-
* options).
827-
*
828-
* Fall back to TCP.
829-
*/
830-
release_sock(ssk);
831-
goto fallback;
832-
}
833828

834829
copied += ret;
835830

@@ -972,7 +967,6 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
972967
int nonblock, int flags, int *addr_len)
973968
{
974969
struct mptcp_sock *msk = mptcp_sk(sk);
975-
struct socket *ssock;
976970
int copied = 0;
977971
int target;
978972
long timeo;
@@ -981,16 +975,6 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
981975
return -EOPNOTSUPP;
982976

983977
lock_sock(sk);
984-
ssock = __mptcp_tcp_fallback(msk);
985-
if (unlikely(ssock)) {
986-
fallback:
987-
release_sock(sk);
988-
pr_debug("fallback-read subflow=%p",
989-
mptcp_subflow_ctx(ssock->sk));
990-
copied = sock_recvmsg(ssock, msg, flags);
991-
return copied;
992-
}
993-
994978
timeo = sock_rcvtimeo(sk, nonblock);
995979

996980
len = min_t(size_t, len, INT_MAX);
@@ -1056,9 +1040,6 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
10561040

10571041
pr_debug("block timeout %ld", timeo);
10581042
mptcp_wait_data(sk, &timeo);
1059-
ssock = __mptcp_tcp_fallback(msk);
1060-
if (unlikely(ssock))
1061-
goto fallback;
10621043
}
10631044

10641045
if (skb_queue_empty(&sk->sk_receive_queue)) {
@@ -1335,8 +1316,6 @@ static void mptcp_subflow_shutdown(struct sock *ssk, int how,
13351316
break;
13361317
}
13371318

1338-
/* Wake up anyone sleeping in poll. */
1339-
ssk->sk_state_change(ssk);
13401319
release_sock(ssk);
13411320
}
13421321

@@ -1660,12 +1639,6 @@ void mptcp_finish_connect(struct sock *ssk)
16601639
sk = subflow->conn;
16611640
msk = mptcp_sk(sk);
16621641

1663-
if (!subflow->mp_capable) {
1664-
MPTCP_INC_STATS(sock_net(sk),
1665-
MPTCP_MIB_MPCAPABLEACTIVEFALLBACK);
1666-
return;
1667-
}
1668-
16691642
pr_debug("msk=%p, token=%u", sk, subflow->token);
16701643

16711644
mptcp_crypto_key_sha(subflow->remote_key, NULL, &ack_seq);
@@ -1971,23 +1944,10 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
19711944
{
19721945
struct sock *sk = sock->sk;
19731946
struct mptcp_sock *msk;
1974-
struct socket *ssock;
19751947
__poll_t mask = 0;
19761948

19771949
msk = mptcp_sk(sk);
1978-
lock_sock(sk);
1979-
ssock = __mptcp_tcp_fallback(msk);
1980-
if (!ssock)
1981-
ssock = __mptcp_nmpc_socket(msk);
1982-
if (ssock) {
1983-
mask = ssock->ops->poll(file, ssock, wait);
1984-
release_sock(sk);
1985-
return mask;
1986-
}
1987-
1988-
release_sock(sk);
19891950
sock_poll_wait(file, sock, wait);
1990-
lock_sock(sk);
19911951

19921952
if (test_bit(MPTCP_DATA_READY, &msk->flags))
19931953
mask = EPOLLIN | EPOLLRDNORM;
@@ -1997,27 +1957,18 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
19971957
if (sk->sk_shutdown & RCV_SHUTDOWN)
19981958
mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
19991959

2000-
release_sock(sk);
2001-
20021960
return mask;
20031961
}
20041962

20051963
static int mptcp_shutdown(struct socket *sock, int how)
20061964
{
20071965
struct mptcp_sock *msk = mptcp_sk(sock->sk);
20081966
struct mptcp_subflow_context *subflow;
2009-
struct socket *ssock;
20101967
int ret = 0;
20111968

20121969
pr_debug("sk=%p, how=%d", msk, how);
20131970

20141971
lock_sock(sock->sk);
2015-
ssock = __mptcp_tcp_fallback(msk);
2016-
if (ssock) {
2017-
release_sock(sock->sk);
2018-
return inet_shutdown(ssock, how);
2019-
}
2020-
20211972
if (how == SHUT_WR || how == SHUT_RDWR)
20221973
inet_sk_state_store(sock->sk, TCP_FIN_WAIT1);
20231974

@@ -2043,6 +1994,9 @@ static int mptcp_shutdown(struct socket *sock, int how)
20431994
mptcp_subflow_shutdown(tcp_sk, how, 1, msk->write_seq);
20441995
}
20451996

1997+
/* Wake up anyone sleeping in poll. */
1998+
sock->sk->sk_state_change(sock->sk);
1999+
20462000
out_unlock:
20472001
release_sock(sock->sk);
20482002

net/mptcp/protocol.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
#define MPTCP_SEND_SPACE 1
9090
#define MPTCP_WORK_RTX 2
9191
#define MPTCP_WORK_EOF 3
92+
#define MPTCP_FALLBACK_DONE 4
9293

9394
struct mptcp_options_received {
9495
u64 sndr_key;
@@ -457,4 +458,36 @@ static inline bool before64(__u64 seq1, __u64 seq2)
457458

458459
void mptcp_diag_subflow_init(struct tcp_ulp_ops *ops);
459460

461+
static inline bool __mptcp_check_fallback(struct mptcp_sock *msk)
462+
{
463+
return test_bit(MPTCP_FALLBACK_DONE, &msk->flags);
464+
}
465+
466+
static inline bool mptcp_check_fallback(struct sock *sk)
467+
{
468+
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
469+
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
470+
471+
return __mptcp_check_fallback(msk);
472+
}
473+
474+
static inline void __mptcp_do_fallback(struct mptcp_sock *msk)
475+
{
476+
if (test_bit(MPTCP_FALLBACK_DONE, &msk->flags)) {
477+
pr_debug("TCP fallback already done (msk=%p)", msk);
478+
return;
479+
}
480+
set_bit(MPTCP_FALLBACK_DONE, &msk->flags);
481+
}
482+
483+
static inline void mptcp_do_fallback(struct sock *sk)
484+
{
485+
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
486+
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
487+
488+
__mptcp_do_fallback(msk);
489+
}
490+
491+
#define pr_fallback(a) pr_debug("%s:fallback to TCP (msk=%p)", __func__, a)
492+
460493
#endif /* __MPTCP_PROTOCOL_H */

0 commit comments

Comments
 (0)