Skip to content

Commit 7896248

Browse files
Florian Westphaldavem330
authored andcommitted
mptcp: add skeleton to sync msk socket options to subflows
Handle following cases: 1. setsockopt is called with multiple subflows. Change might have to be mirrored to all of them. This is done directly in process context/setsockopt call. 2. Outgoing subflow is created after one or several setsockopt() calls have been made. Old setsockopt changes should be synced to the new socket. 3. Incoming subflow, after setsockopt call(s). Cases 2 and 3 are handled right after the join list is spliced to the conn list. Not all sockopt values can be just be copied by value, some require helper calls. Those can acquire socket lock (which can sleep). If the join->conn list splicing is done from preemptible context, synchronization can be done right away, otherwise its deferred to work queue. Acked-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d9e4c12 commit 7896248

File tree

4 files changed

+60
-8
lines changed

4 files changed

+60
-8
lines changed

net/mptcp/protocol.c

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -730,18 +730,42 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk)
730730
sk->sk_data_ready(sk);
731731
}
732732

733-
void __mptcp_flush_join_list(struct mptcp_sock *msk)
733+
static bool mptcp_do_flush_join_list(struct mptcp_sock *msk)
734734
{
735735
struct mptcp_subflow_context *subflow;
736736

737737
if (likely(list_empty(&msk->join_list)))
738-
return;
738+
return false;
739739

740740
spin_lock_bh(&msk->join_list_lock);
741741
list_for_each_entry(subflow, &msk->join_list, node)
742742
mptcp_propagate_sndbuf((struct sock *)msk, mptcp_subflow_tcp_sock(subflow));
743+
743744
list_splice_tail_init(&msk->join_list, &msk->conn_list);
744745
spin_unlock_bh(&msk->join_list_lock);
746+
747+
return true;
748+
}
749+
750+
void __mptcp_flush_join_list(struct mptcp_sock *msk)
751+
{
752+
if (likely(!mptcp_do_flush_join_list(msk)))
753+
return;
754+
755+
if (!test_and_set_bit(MPTCP_WORK_SYNC_SETSOCKOPT, &msk->flags))
756+
mptcp_schedule_work((struct sock *)msk);
757+
}
758+
759+
static void mptcp_flush_join_list(struct mptcp_sock *msk)
760+
{
761+
bool sync_needed = test_and_clear_bit(MPTCP_WORK_SYNC_SETSOCKOPT, &msk->flags);
762+
763+
might_sleep();
764+
765+
if (!mptcp_do_flush_join_list(msk) && !sync_needed)
766+
return;
767+
768+
mptcp_sockopt_sync_all(msk);
745769
}
746770

747771
static bool mptcp_timer_pending(struct sock *sk)
@@ -1457,7 +1481,7 @@ static void __mptcp_push_pending(struct sock *sk, unsigned int flags)
14571481
int ret = 0;
14581482

14591483
prev_ssk = ssk;
1460-
__mptcp_flush_join_list(msk);
1484+
mptcp_flush_join_list(msk);
14611485
ssk = mptcp_subflow_get_send(msk);
14621486

14631487
/* try to keep the subflow socket lock across
@@ -1883,7 +1907,7 @@ static bool __mptcp_move_skbs(struct mptcp_sock *msk)
18831907
unsigned int moved = 0;
18841908
bool ret, done;
18851909

1886-
__mptcp_flush_join_list(msk);
1910+
mptcp_flush_join_list(msk);
18871911
do {
18881912
struct sock *ssk = mptcp_subflow_recv_lookup(msk);
18891913
bool slowpath;
@@ -2307,7 +2331,7 @@ static void mptcp_worker(struct work_struct *work)
23072331
goto unlock;
23082332

23092333
mptcp_check_data_fin_ack(sk);
2310-
__mptcp_flush_join_list(msk);
2334+
mptcp_flush_join_list(msk);
23112335

23122336
mptcp_check_fastclose(msk);
23132337

@@ -2507,7 +2531,7 @@ static void __mptcp_check_send_data_fin(struct sock *sk)
25072531
}
25082532
}
25092533

2510-
__mptcp_flush_join_list(msk);
2534+
mptcp_flush_join_list(msk);
25112535
mptcp_for_each_subflow(msk, subflow) {
25122536
struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow);
25132537

@@ -2644,7 +2668,8 @@ static int mptcp_disconnect(struct sock *sk, int flags)
26442668
struct mptcp_subflow_context *subflow;
26452669
struct mptcp_sock *msk = mptcp_sk(sk);
26462670

2647-
__mptcp_flush_join_list(msk);
2671+
mptcp_do_flush_join_list(msk);
2672+
26482673
mptcp_for_each_subflow(msk, subflow) {
26492674
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
26502675

@@ -3210,7 +3235,7 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
32103235
/* set ssk->sk_socket of accept()ed flows to mptcp socket.
32113236
* This is needed so NOSPACE flag can be set from tcp stack.
32123237
*/
3213-
__mptcp_flush_join_list(msk);
3238+
mptcp_flush_join_list(msk);
32143239
mptcp_for_each_subflow(msk, subflow) {
32153240
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
32163241

net/mptcp/protocol.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
#define MPTCP_CLEAN_UNA 7
109109
#define MPTCP_ERROR_REPORT 8
110110
#define MPTCP_RETRANSMIT 9
111+
#define MPTCP_WORK_SYNC_SETSOCKOPT 10
111112

112113
static inline bool before64(__u64 seq1, __u64 seq2)
113114
{
@@ -735,6 +736,12 @@ unsigned int mptcp_pm_get_add_addr_accept_max(struct mptcp_sock *msk);
735736
unsigned int mptcp_pm_get_subflows_max(struct mptcp_sock *msk);
736737
unsigned int mptcp_pm_get_local_addr_max(struct mptcp_sock *msk);
737738

739+
int mptcp_setsockopt(struct sock *sk, int level, int optname,
740+
sockptr_t optval, unsigned int optlen);
741+
742+
void mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk);
743+
void mptcp_sockopt_sync_all(struct mptcp_sock *msk);
744+
738745
static inline struct mptcp_ext *mptcp_get_ext(const struct sk_buff *skb)
739746
{
740747
return (struct mptcp_ext *)skb_ext_find(skb, SKB_EXT_MPTCP);

net/mptcp/sockopt.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,3 +350,22 @@ int mptcp_getsockopt(struct sock *sk, int level, int optname,
350350
return -EOPNOTSUPP;
351351
}
352352

353+
void mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk)
354+
{
355+
msk_owned_by_me(msk);
356+
}
357+
358+
void mptcp_sockopt_sync_all(struct mptcp_sock *msk)
359+
{
360+
struct mptcp_subflow_context *subflow;
361+
362+
msk_owned_by_me(msk);
363+
364+
mptcp_for_each_subflow(msk, subflow) {
365+
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
366+
367+
mptcp_sockopt_sync(msk, ssk);
368+
369+
cond_resched();
370+
}
371+
}

net/mptcp/subflow.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,6 +1317,7 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
13171317
mptcp_info2sockaddr(remote, &addr, ssk->sk_family);
13181318

13191319
mptcp_add_pending_subflow(msk, subflow);
1320+
mptcp_sockopt_sync(msk, ssk);
13201321
err = kernel_connect(sf, (struct sockaddr *)&addr, addrlen, O_NONBLOCK);
13211322
if (err && err != -EINPROGRESS)
13221323
goto failed_unlink;

0 commit comments

Comments
 (0)