Skip to content

Commit df00b08

Browse files
Florian Westphaldavem330
Florian Westphal
authored andcommitted
mptcp: tag sequence_seq with socket state
Paolo Abeni suggested to avoid re-syncing new subflows because they inherit options from listener. In case options were set on listener but are not set on mptcp-socket there is no need to do any synchronisation for new subflows. This change sets sockopt_seq of new mptcp sockets to the seq of the mptcp listener sock. Subflow sequence is set to the embedded tcp listener sk. Add a comment explaing why sk_state is involved in sockopt_seq generation. Acked-by: Paolo Abeni <[email protected]> Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7896248 commit df00b08

File tree

4 files changed

+62
-5
lines changed

4 files changed

+62
-5
lines changed

net/mptcp/protocol.c

+9-3
Original file line numberDiff line numberDiff line change
@@ -733,18 +733,23 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk)
733733
static bool mptcp_do_flush_join_list(struct mptcp_sock *msk)
734734
{
735735
struct mptcp_subflow_context *subflow;
736+
bool ret = false;
736737

737738
if (likely(list_empty(&msk->join_list)))
738739
return false;
739740

740741
spin_lock_bh(&msk->join_list_lock);
741-
list_for_each_entry(subflow, &msk->join_list, node)
742-
mptcp_propagate_sndbuf((struct sock *)msk, mptcp_subflow_tcp_sock(subflow));
742+
list_for_each_entry(subflow, &msk->join_list, node) {
743+
u32 sseq = READ_ONCE(subflow->setsockopt_seq);
743744

745+
mptcp_propagate_sndbuf((struct sock *)msk, mptcp_subflow_tcp_sock(subflow));
746+
if (READ_ONCE(msk->setsockopt_seq) != sseq)
747+
ret = true;
748+
}
744749
list_splice_tail_init(&msk->join_list, &msk->conn_list);
745750
spin_unlock_bh(&msk->join_list_lock);
746751

747-
return true;
752+
return ret;
748753
}
749754

750755
void __mptcp_flush_join_list(struct mptcp_sock *msk)
@@ -2718,6 +2723,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
27182723
msk->snd_nxt = msk->write_seq;
27192724
msk->snd_una = msk->write_seq;
27202725
msk->wnd_end = msk->snd_nxt + req->rsk_rcv_wnd;
2726+
msk->setsockopt_seq = mptcp_sk(sk)->setsockopt_seq;
27212727

27222728
if (mp_opt->mp_capable) {
27232729
msk->can_ack = true;

net/mptcp/protocol.h

+4
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ struct mptcp_sock {
256256
u64 time; /* start time of measurement window */
257257
u64 rtt_us; /* last maximum rtt of subflows */
258258
} rcvq_space;
259+
260+
u32 setsockopt_seq;
259261
};
260262

261263
#define mptcp_lock_sock(___sk, cb) do { \
@@ -414,6 +416,8 @@ struct mptcp_subflow_context {
414416
long delegated_status;
415417
struct list_head delegated_node; /* link into delegated_action, protected by local BH */
416418

419+
u32 setsockopt_seq;
420+
417421
struct sock *tcp_sock; /* tcp sk backpointer */
418422
struct sock *conn; /* parent mptcp_sock */
419423
const struct inet_connection_sock_af_ops *icsk_af_ops;

net/mptcp/sockopt.c

+45-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,27 @@ static struct sock *__mptcp_tcp_fallback(struct mptcp_sock *msk)
2424
return msk->first;
2525
}
2626

27+
static u32 sockopt_seq_reset(const struct sock *sk)
28+
{
29+
sock_owned_by_me(sk);
30+
31+
/* Highbits contain state. Allows to distinguish sockopt_seq
32+
* of listener and established:
33+
* s0 = new_listener()
34+
* sockopt(s0) - seq is 1
35+
* s1 = accept(s0) - s1 inherits seq 1 if listener sk (s0)
36+
* sockopt(s0) - seq increments to 2 on s0
37+
* sockopt(s1) // seq increments to 2 on s1 (different option)
38+
* new ssk completes join, inherits options from s0 // seq 2
39+
* Needs sync from mptcp join logic, but ssk->seq == msk->seq
40+
*
41+
* Set High order bits to sk_state so ssk->seq == msk->seq test
42+
* will fail.
43+
*/
44+
45+
return (u32)sk->sk_state << 24u;
46+
}
47+
2748
static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname,
2849
sockptr_t optval, unsigned int optlen)
2950
{
@@ -350,22 +371,44 @@ int mptcp_getsockopt(struct sock *sk, int level, int optname,
350371
return -EOPNOTSUPP;
351372
}
352373

374+
static void __mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk)
375+
{
376+
}
377+
353378
void mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk)
354379
{
380+
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
381+
355382
msk_owned_by_me(msk);
383+
384+
if (READ_ONCE(subflow->setsockopt_seq) != msk->setsockopt_seq) {
385+
__mptcp_sockopt_sync(msk, ssk);
386+
387+
subflow->setsockopt_seq = msk->setsockopt_seq;
388+
}
356389
}
357390

358391
void mptcp_sockopt_sync_all(struct mptcp_sock *msk)
359392
{
360393
struct mptcp_subflow_context *subflow;
394+
struct sock *sk = (struct sock *)msk;
395+
u32 seq;
361396

362-
msk_owned_by_me(msk);
397+
seq = sockopt_seq_reset(sk);
363398

364399
mptcp_for_each_subflow(msk, subflow) {
365400
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
401+
u32 sseq = READ_ONCE(subflow->setsockopt_seq);
366402

367-
mptcp_sockopt_sync(msk, ssk);
403+
if (sseq != msk->setsockopt_seq) {
404+
__mptcp_sockopt_sync(msk, ssk);
405+
WRITE_ONCE(subflow->setsockopt_seq, seq);
406+
} else if (sseq != seq) {
407+
WRITE_ONCE(subflow->setsockopt_seq, seq);
408+
}
368409

369410
cond_resched();
370411
}
412+
413+
msk->setsockopt_seq = seq;
371414
}

net/mptcp/subflow.c

+4
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,9 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
679679
goto out;
680680
}
681681

682+
/* ssk inherits options of listener sk */
683+
ctx->setsockopt_seq = listener->setsockopt_seq;
684+
682685
if (ctx->mp_capable) {
683686
/* this can't race with mptcp_close(), as the msk is
684687
* not yet exposted to user-space
@@ -694,6 +697,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
694697
* created mptcp socket
695698
*/
696699
new_msk->sk_destruct = mptcp_sock_destruct;
700+
mptcp_sk(new_msk)->setsockopt_seq = ctx->setsockopt_seq;
697701
mptcp_pm_new_connection(mptcp_sk(new_msk), child, 1);
698702
mptcp_token_accept(subflow_req, mptcp_sk(new_msk));
699703
ctx->conn = new_msk;

0 commit comments

Comments
 (0)