Skip to content

Commit a79c838

Browse files
committed
Merge branch 'mptcp-simplify-mptcp_accept'
Paolo Abeni says: ==================== mptcp: simplify mptcp_accept() Currently we allocate the MPTCP master socket at accept time. The above makes mptcp_accept() quite complex, and requires checks is several places for NULL MPTCP master socket. These series simplify the MPTCP accept implementation, moving the master socket allocation at syn-ack time, so that we drop unneeded checks with the follow-up patch. v1 -> v2: - rebased on top of 2398e39 ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 7a1d0e6 + dc093db commit a79c838

File tree

5 files changed

+79
-103
lines changed

5 files changed

+79
-103
lines changed

net/mptcp/options.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,6 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
336336
unsigned int ack_size;
337337
bool ret = false;
338338
bool can_ack;
339-
u64 ack_seq;
340339
u8 tcp_fin;
341340

342341
if (skb) {
@@ -368,16 +367,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
368367
can_ack = true;
369368
opts->ext_copy.use_ack = 0;
370369
msk = mptcp_sk(subflow->conn);
371-
if (likely(msk && READ_ONCE(msk->can_ack))) {
372-
ack_seq = msk->ack_seq;
373-
} else if (subflow->can_ack) {
374-
mptcp_crypto_key_sha(subflow->remote_key, NULL, &ack_seq);
375-
ack_seq++;
376-
} else {
377-
can_ack = false;
378-
}
379-
380-
if (unlikely(!can_ack)) {
370+
if (!READ_ONCE(msk->can_ack)) {
381371
*size = ALIGN(dss_size, 4);
382372
return ret;
383373
}
@@ -390,7 +380,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
390380

391381
dss_size += ack_size;
392382

393-
opts->ext_copy.data_ack = ack_seq;
383+
opts->ext_copy.data_ack = msk->ack_seq;
394384
opts->ext_copy.ack64 = 1;
395385
opts->ext_copy.use_ack = 1;
396386

net/mptcp/protocol.c

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -820,9 +820,12 @@ static struct ipv6_pinfo *mptcp_inet6_sk(const struct sock *sk)
820820
}
821821
#endif
822822

823-
static struct sock *mptcp_sk_clone_lock(const struct sock *sk)
823+
struct sock *mptcp_sk_clone(const struct sock *sk, struct request_sock *req)
824824
{
825+
struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
825826
struct sock *nsk = sk_clone_lock(sk, GFP_ATOMIC);
827+
struct mptcp_sock *msk;
828+
u64 ack_seq;
826829

827830
if (!nsk)
828831
return NULL;
@@ -832,6 +835,36 @@ static struct sock *mptcp_sk_clone_lock(const struct sock *sk)
832835
inet_sk(nsk)->pinet6 = mptcp_inet6_sk(nsk);
833836
#endif
834837

838+
__mptcp_init_sock(nsk);
839+
840+
msk = mptcp_sk(nsk);
841+
msk->local_key = subflow_req->local_key;
842+
msk->token = subflow_req->token;
843+
msk->subflow = NULL;
844+
845+
if (unlikely(mptcp_token_new_accept(subflow_req->token, nsk))) {
846+
bh_unlock_sock(nsk);
847+
848+
/* we can't call into mptcp_close() here - possible BH context
849+
* free the sock directly
850+
*/
851+
nsk->sk_prot->destroy(nsk);
852+
sk_free(nsk);
853+
return NULL;
854+
}
855+
856+
msk->write_seq = subflow_req->idsn + 1;
857+
if (subflow_req->remote_key_valid) {
858+
msk->can_ack = true;
859+
msk->remote_key = subflow_req->remote_key;
860+
mptcp_crypto_key_sha(msk->remote_key, NULL, &ack_seq);
861+
ack_seq++;
862+
msk->ack_seq = ack_seq;
863+
}
864+
bh_unlock_sock(nsk);
865+
866+
/* keep a single reference */
867+
__sock_put(nsk);
835868
return nsk;
836869
}
837870

@@ -859,40 +892,26 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
859892
struct mptcp_subflow_context *subflow;
860893
struct sock *new_mptcp_sock;
861894
struct sock *ssk = newsk;
862-
u64 ack_seq;
863895

864896
subflow = mptcp_subflow_ctx(newsk);
865-
lock_sock(sk);
897+
new_mptcp_sock = subflow->conn;
866898

867-
local_bh_disable();
868-
new_mptcp_sock = mptcp_sk_clone_lock(sk);
869-
if (!new_mptcp_sock) {
870-
*err = -ENOBUFS;
871-
local_bh_enable();
872-
release_sock(sk);
873-
mptcp_subflow_shutdown(newsk, SHUT_RDWR + 1, 0, 0);
874-
tcp_close(newsk, 0);
875-
return NULL;
899+
/* is_mptcp should be false if subflow->conn is missing, see
900+
* subflow_syn_recv_sock()
901+
*/
902+
if (WARN_ON_ONCE(!new_mptcp_sock)) {
903+
tcp_sk(newsk)->is_mptcp = 0;
904+
return newsk;
876905
}
877906

878-
__mptcp_init_sock(new_mptcp_sock);
907+
/* acquire the 2nd reference for the owning socket */
908+
sock_hold(new_mptcp_sock);
879909

910+
local_bh_disable();
911+
bh_lock_sock(new_mptcp_sock);
880912
msk = mptcp_sk(new_mptcp_sock);
881-
msk->local_key = subflow->local_key;
882-
msk->token = subflow->token;
883-
msk->subflow = NULL;
884913
msk->first = newsk;
885914

886-
mptcp_token_update_accept(newsk, new_mptcp_sock);
887-
888-
msk->write_seq = subflow->idsn + 1;
889-
if (subflow->can_ack) {
890-
msk->can_ack = true;
891-
msk->remote_key = subflow->remote_key;
892-
mptcp_crypto_key_sha(msk->remote_key, NULL, &ack_seq);
893-
ack_seq++;
894-
msk->ack_seq = ack_seq;
895-
}
896915
newsk = new_mptcp_sock;
897916
mptcp_copy_inaddrs(newsk, ssk);
898917
list_add(&subflow->node, &msk->conn_list);
@@ -903,18 +922,6 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
903922
inet_sk_state_store(new_mptcp_sock, TCP_SYN_RECV);
904923
bh_unlock_sock(new_mptcp_sock);
905924
local_bh_enable();
906-
release_sock(sk);
907-
908-
/* the subflow can already receive packet, avoid racing with
909-
* the receive path and process the pending ones
910-
*/
911-
lock_sock(ssk);
912-
subflow->rel_write_seq = 1;
913-
subflow->tcp_sock = ssk;
914-
subflow->conn = new_mptcp_sock;
915-
if (unlikely(!skb_queue_empty(&ssk->sk_receive_queue)))
916-
mptcp_subflow_data_available(ssk);
917-
release_sock(ssk);
918925
}
919926

920927
return newsk;

net/mptcp/protocol.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ void mptcp_proto_init(void);
193193
int mptcp_proto_v6_init(void);
194194
#endif
195195

196+
struct sock *mptcp_sk_clone(const struct sock *sk, struct request_sock *req);
196197
void mptcp_get_options(const struct sk_buff *skb,
197198
struct tcp_options_received *opt_rx);
198199

@@ -202,8 +203,7 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk);
202203
int mptcp_token_new_request(struct request_sock *req);
203204
void mptcp_token_destroy_request(u32 token);
204205
int mptcp_token_new_connect(struct sock *sk);
205-
int mptcp_token_new_accept(u32 token);
206-
void mptcp_token_update_accept(struct sock *sk, struct sock *conn);
206+
int mptcp_token_new_accept(u32 token, struct sock *conn);
207207
void mptcp_token_destroy(u32 token);
208208

209209
void mptcp_crypto_key_sha(u64 key, u32 *token, u64 *idsn);

net/mptcp/subflow.c

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
112112

113113
subflow->icsk_af_ops->sk_rx_dst_set(sk, skb);
114114

115-
if (subflow->conn && !subflow->conn_finished) {
115+
if (!subflow->conn_finished) {
116116
pr_debug("subflow=%p, remote_key=%llu", mptcp_subflow_ctx(sk),
117117
subflow->remote_key);
118118
mptcp_finish_connect(sk);
@@ -182,6 +182,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
182182
struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk);
183183
struct mptcp_subflow_request_sock *subflow_req;
184184
struct tcp_options_received opt_rx;
185+
struct sock *new_msk = NULL;
185186
struct sock *child;
186187

187188
pr_debug("listener=%p, req=%p, conn=%p", listener, req, listener->conn);
@@ -197,7 +198,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
197198
* out-of-order pkt, which will not carry the MP_CAPABLE
198199
* opt even on mptcp enabled paths
199200
*/
200-
goto create_child;
201+
goto create_msk;
201202
}
202203

203204
opt_rx.mptcp.mp_capable = 0;
@@ -207,7 +208,13 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
207208
subflow_req->remote_key_valid = 1;
208209
} else {
209210
subflow_req->mp_capable = 0;
211+
goto create_child;
210212
}
213+
214+
create_msk:
215+
new_msk = mptcp_sk_clone(listener->conn, req);
216+
if (!new_msk)
217+
subflow_req->mp_capable = 0;
211218
}
212219

213220
create_child:
@@ -221,22 +228,22 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
221228
* handshake
222229
*/
223230
if (!ctx)
224-
return child;
231+
goto out;
225232

226233
if (ctx->mp_capable) {
227-
if (mptcp_token_new_accept(ctx->token))
228-
goto close_child;
234+
/* new mpc subflow takes ownership of the newly
235+
* created mptcp socket
236+
*/
237+
ctx->conn = new_msk;
238+
new_msk = NULL;
229239
}
230240
}
231241

242+
out:
243+
/* dispose of the left over mptcp master, if any */
244+
if (unlikely(new_msk))
245+
sock_put(new_msk);
232246
return child;
233-
234-
close_child:
235-
pr_debug("closing child socket");
236-
tcp_send_active_reset(child, GFP_ATOMIC);
237-
inet_csk_prepare_forced_close(child);
238-
tcp_done(child);
239-
return NULL;
240247
}
241248

242249
static struct inet_connection_sock_af_ops subflow_specific;
@@ -432,9 +439,6 @@ static bool subflow_check_data_avail(struct sock *ssk)
432439
if (subflow->data_avail)
433440
return true;
434441

435-
if (!subflow->conn)
436-
return false;
437-
438442
msk = mptcp_sk(subflow->conn);
439443
for (;;) {
440444
u32 map_remaining;
@@ -554,11 +558,10 @@ static void subflow_data_ready(struct sock *sk)
554558
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
555559
struct sock *parent = subflow->conn;
556560

557-
if (!parent || !subflow->mp_capable) {
561+
if (!subflow->mp_capable) {
558562
subflow->tcp_data_ready(sk);
559563

560-
if (parent)
561-
parent->sk_data_ready(parent);
564+
parent->sk_data_ready(parent);
562565
return;
563566
}
564567

@@ -572,7 +575,7 @@ static void subflow_write_space(struct sock *sk)
572575
struct sock *parent = subflow->conn;
573576

574577
sk_stream_write_space(sk);
575-
if (parent && sk_stream_is_writeable(sk)) {
578+
if (sk_stream_is_writeable(sk)) {
576579
set_bit(MPTCP_SEND_SPACE, &mptcp_sk(parent)->flags);
577580
smp_mb__after_atomic();
578581
/* set SEND_SPACE before sk_stream_write_space clears NOSPACE */
@@ -687,18 +690,18 @@ static bool subflow_is_done(const struct sock *sk)
687690
static void subflow_state_change(struct sock *sk)
688691
{
689692
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
690-
struct sock *parent = READ_ONCE(subflow->conn);
693+
struct sock *parent = subflow->conn;
691694

692695
__subflow_state_change(sk);
693696

694697
/* as recvmsg() does not acquire the subflow socket for ssk selection
695698
* a fin packet carrying a DSS can be unnoticed if we don't trigger
696699
* the data available machinery here.
697700
*/
698-
if (parent && subflow->mp_capable && mptcp_subflow_data_available(sk))
701+
if (subflow->mp_capable && mptcp_subflow_data_available(sk))
699702
mptcp_data_ready(parent, sk);
700703

701-
if (parent && !(parent->sk_shutdown & RCV_SHUTDOWN) &&
704+
if (!(parent->sk_shutdown & RCV_SHUTDOWN) &&
702705
!subflow->rx_eof && subflow_is_done(sk)) {
703706
subflow->rx_eof = 1;
704707
parent->sk_shutdown |= RCV_SHUTDOWN;
@@ -793,6 +796,9 @@ static void subflow_ulp_clone(const struct request_sock *req,
793796
new_ctx->tcp_data_ready = old_ctx->tcp_data_ready;
794797
new_ctx->tcp_state_change = old_ctx->tcp_state_change;
795798
new_ctx->tcp_write_space = old_ctx->tcp_write_space;
799+
new_ctx->rel_write_seq = 1;
800+
new_ctx->tcp_sock = newsk;
801+
796802
new_ctx->mp_capable = 1;
797803
new_ctx->fourth_ack = subflow_req->remote_key_valid;
798804
new_ctx->can_ack = subflow_req->remote_key_valid;

net/mptcp/token.c

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -128,45 +128,18 @@ int mptcp_token_new_connect(struct sock *sk)
128128
*
129129
* Called when a SYN packet creates a new logical connection, i.e.
130130
* is not a join request.
131-
*
132-
* We don't have an mptcp socket yet at that point.
133-
* This is paired with mptcp_token_update_accept, called on accept().
134131
*/
135-
int mptcp_token_new_accept(u32 token)
132+
int mptcp_token_new_accept(u32 token, struct sock *conn)
136133
{
137134
int err;
138135

139136
spin_lock_bh(&token_tree_lock);
140-
err = radix_tree_insert(&token_tree, token, &token_used);
137+
err = radix_tree_insert(&token_tree, token, conn);
141138
spin_unlock_bh(&token_tree_lock);
142139

143140
return err;
144141
}
145142

146-
/**
147-
* mptcp_token_update_accept - update token to map to mptcp socket
148-
* @conn: the new struct mptcp_sock
149-
* @sk: the initial subflow for this mptcp socket
150-
*
151-
* Called when the first mptcp socket is created on accept to
152-
* refresh the dummy mapping (done to reserve the token) with
153-
* the mptcp_socket structure that wasn't allocated before.
154-
*/
155-
void mptcp_token_update_accept(struct sock *sk, struct sock *conn)
156-
{
157-
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
158-
void __rcu **slot;
159-
160-
spin_lock_bh(&token_tree_lock);
161-
slot = radix_tree_lookup_slot(&token_tree, subflow->token);
162-
WARN_ON_ONCE(!slot);
163-
if (slot) {
164-
WARN_ON_ONCE(rcu_access_pointer(*slot) != &token_used);
165-
radix_tree_replace_slot(&token_tree, slot, conn);
166-
}
167-
spin_unlock_bh(&token_tree_lock);
168-
}
169-
170143
/**
171144
* mptcp_token_destroy_request - remove mptcp connection/token
172145
* @token - token of mptcp connection to remove

0 commit comments

Comments
 (0)