Skip to content

Commit 2c5ebd0

Browse files
Paolo Abenidavem330
authored andcommitted
mptcp: refactor token container
Replace the radix tree with a hash table allocated at boot time. The radix tree has some shortcoming: a single lock is contented by all the mptcp operation, the lookup currently use such lock, and traversing all the items would require a lock, too. With hash table instead we trade a little memory to address all the above - a per bucket lock is used. To hash the MPTCP sockets, we re-use the msk' sk_node entry: the MPTCP sockets are never hashed by the stack. Replace the existing hash proto callbacks with a dummy implementation, annotating the above constraint. Additionally refactor the token creation to code to: - limit the number of consecutive attempts to a fixed maximum. Hitting a hash bucket with a long chain is considered a failed attempt - accept() no longer can fail to token management. - if token creation fails at connect() time, we do fallback to TCP (before the connection was closed) v1 -> v2: - fix "no newline at end of file" - Jakub Signed-off-by: Paolo Abeni <[email protected]> Reviewed-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d39dcec commit 2c5ebd0

File tree

4 files changed

+236
-113
lines changed

4 files changed

+236
-113
lines changed

net/mptcp/protocol.c

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,20 +1448,6 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
14481448
msk->token = subflow_req->token;
14491449
msk->subflow = NULL;
14501450

1451-
if (unlikely(mptcp_token_new_accept(subflow_req->token, nsk))) {
1452-
nsk->sk_state = TCP_CLOSE;
1453-
bh_unlock_sock(nsk);
1454-
1455-
/* we can't call into mptcp_close() here - possible BH context
1456-
* free the sock directly.
1457-
* sk_clone_lock() sets nsk refcnt to two, hence call sk_free()
1458-
* too.
1459-
*/
1460-
sk_common_release(nsk);
1461-
sk_free(nsk);
1462-
return NULL;
1463-
}
1464-
14651451
msk->write_seq = subflow_req->idsn + 1;
14661452
atomic64_set(&msk->snd_una, msk->write_seq);
14671453
if (mp_opt->mp_capable) {
@@ -1547,7 +1533,7 @@ static void mptcp_destroy(struct sock *sk)
15471533
{
15481534
struct mptcp_sock *msk = mptcp_sk(sk);
15491535

1550-
mptcp_token_destroy(msk->token);
1536+
mptcp_token_destroy(msk);
15511537
if (msk->cached_ext)
15521538
__skb_ext_put(msk->cached_ext);
15531539

@@ -1636,6 +1622,20 @@ static void mptcp_release_cb(struct sock *sk)
16361622
}
16371623
}
16381624

1625+
static int mptcp_hash(struct sock *sk)
1626+
{
1627+
/* should never be called,
1628+
* we hash the TCP subflows not the master socket
1629+
*/
1630+
WARN_ON_ONCE(1);
1631+
return 0;
1632+
}
1633+
1634+
static void mptcp_unhash(struct sock *sk)
1635+
{
1636+
/* called from sk_common_release(), but nothing to do here */
1637+
}
1638+
16391639
static int mptcp_get_port(struct sock *sk, unsigned short snum)
16401640
{
16411641
struct mptcp_sock *msk = mptcp_sk(sk);
@@ -1679,7 +1679,6 @@ void mptcp_finish_connect(struct sock *ssk)
16791679
*/
16801680
WRITE_ONCE(msk->remote_key, subflow->remote_key);
16811681
WRITE_ONCE(msk->local_key, subflow->local_key);
1682-
WRITE_ONCE(msk->token, subflow->token);
16831682
WRITE_ONCE(msk->write_seq, subflow->idsn + 1);
16841683
WRITE_ONCE(msk->ack_seq, ack_seq);
16851684
WRITE_ONCE(msk->can_ack, 1);
@@ -1761,8 +1760,8 @@ static struct proto mptcp_prot = {
17611760
.sendmsg = mptcp_sendmsg,
17621761
.recvmsg = mptcp_recvmsg,
17631762
.release_cb = mptcp_release_cb,
1764-
.hash = inet_hash,
1765-
.unhash = inet_unhash,
1763+
.hash = mptcp_hash,
1764+
.unhash = mptcp_unhash,
17661765
.get_port = mptcp_get_port,
17671766
.sockets_allocated = &mptcp_sockets_allocated,
17681767
.memory_allocated = &tcp_memory_allocated,
@@ -1771,6 +1770,7 @@ static struct proto mptcp_prot = {
17711770
.sysctl_wmem_offset = offsetof(struct net, ipv4.sysctl_tcp_wmem),
17721771
.sysctl_mem = sysctl_tcp_mem,
17731772
.obj_size = sizeof(struct mptcp_sock),
1773+
.slab_flags = SLAB_TYPESAFE_BY_RCU,
17741774
.no_autobind = true,
17751775
};
17761776

@@ -1800,6 +1800,7 @@ static int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
18001800
int addr_len, int flags)
18011801
{
18021802
struct mptcp_sock *msk = mptcp_sk(sock->sk);
1803+
struct mptcp_subflow_context *subflow;
18031804
struct socket *ssock;
18041805
int err;
18051806

@@ -1812,19 +1813,23 @@ static int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
18121813
goto do_connect;
18131814
}
18141815

1816+
mptcp_token_destroy(msk);
18151817
ssock = __mptcp_socket_create(msk, TCP_SYN_SENT);
18161818
if (IS_ERR(ssock)) {
18171819
err = PTR_ERR(ssock);
18181820
goto unlock;
18191821
}
18201822

1823+
subflow = mptcp_subflow_ctx(ssock->sk);
18211824
#ifdef CONFIG_TCP_MD5SIG
18221825
/* no MPTCP if MD5SIG is enabled on this socket or we may run out of
18231826
* TCP option space.
18241827
*/
18251828
if (rcu_access_pointer(tcp_sk(ssock->sk)->md5sig_info))
1826-
mptcp_subflow_ctx(ssock->sk)->request_mptcp = 0;
1829+
subflow->request_mptcp = 0;
18271830
#endif
1831+
if (subflow->request_mptcp && mptcp_token_new_connect(ssock->sk))
1832+
subflow->request_mptcp = 0;
18281833

18291834
do_connect:
18301835
err = ssock->ops->connect(ssock, uaddr, addr_len, flags);
@@ -1888,6 +1893,7 @@ static int mptcp_listen(struct socket *sock, int backlog)
18881893
pr_debug("msk=%p", msk);
18891894

18901895
lock_sock(sock->sk);
1896+
mptcp_token_destroy(msk);
18911897
ssock = __mptcp_socket_create(msk, TCP_LISTEN);
18921898
if (IS_ERR(ssock)) {
18931899
err = PTR_ERR(ssock);
@@ -2086,6 +2092,7 @@ void __init mptcp_proto_init(void)
20862092

20872093
mptcp_subflow_init();
20882094
mptcp_pm_init();
2095+
mptcp_token_init();
20892096

20902097
if (proto_register(&mptcp_prot, 1) != 0)
20912098
panic("Failed to register MPTCP proto.\n");

net/mptcp/protocol.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ struct mptcp_subflow_request_sock {
250250
u32 local_nonce;
251251
u32 remote_nonce;
252252
struct mptcp_sock *msk;
253+
struct hlist_nulls_node token_node;
253254
};
254255

255256
static inline struct mptcp_subflow_request_sock *
@@ -372,12 +373,19 @@ bool mptcp_finish_join(struct sock *sk);
372373
void mptcp_data_acked(struct sock *sk);
373374
void mptcp_subflow_eof(struct sock *sk);
374375

376+
void __init mptcp_token_init(void);
377+
static inline void mptcp_token_init_request(struct request_sock *req)
378+
{
379+
mptcp_subflow_rsk(req)->token_node.pprev = NULL;
380+
}
381+
375382
int mptcp_token_new_request(struct request_sock *req);
376-
void mptcp_token_destroy_request(u32 token);
383+
void mptcp_token_destroy_request(struct request_sock *req);
377384
int mptcp_token_new_connect(struct sock *sk);
378-
int mptcp_token_new_accept(u32 token, struct sock *conn);
385+
void mptcp_token_accept(struct mptcp_subflow_request_sock *r,
386+
struct mptcp_sock *msk);
379387
struct mptcp_sock *mptcp_token_get_sock(u32 token);
380-
void mptcp_token_destroy(u32 token);
388+
void mptcp_token_destroy(struct mptcp_sock *msk);
381389

382390
void mptcp_crypto_key_sha(u64 key, u32 *token, u64 *idsn);
383391
static inline void mptcp_crypto_key_gen_sha(u64 *key, u32 *token, u64 *idsn)

net/mptcp/subflow.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,9 @@ static void SUBFLOW_REQ_INC_STATS(struct request_sock *req,
3232
static int subflow_rebuild_header(struct sock *sk)
3333
{
3434
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
35-
int local_id, err = 0;
35+
int local_id;
3636

37-
if (subflow->request_mptcp && !subflow->token) {
38-
pr_debug("subflow=%p", sk);
39-
err = mptcp_token_new_connect(sk);
40-
} else if (subflow->request_join && !subflow->local_nonce) {
37+
if (subflow->request_join && !subflow->local_nonce) {
4138
struct mptcp_sock *msk = (struct mptcp_sock *)subflow->conn;
4239

4340
pr_debug("subflow=%p", sk);
@@ -57,9 +54,6 @@ static int subflow_rebuild_header(struct sock *sk)
5754
}
5855

5956
out:
60-
if (err)
61-
return err;
62-
6357
return subflow->icsk_af_ops->rebuild_header(sk);
6458
}
6559

@@ -72,8 +66,7 @@ static void subflow_req_destructor(struct request_sock *req)
7266
if (subflow_req->msk)
7367
sock_put((struct sock *)subflow_req->msk);
7468

75-
if (subflow_req->mp_capable)
76-
mptcp_token_destroy_request(subflow_req->token);
69+
mptcp_token_destroy_request(req);
7770
tcp_request_sock_ops.destructor(req);
7871
}
7972

@@ -135,6 +128,7 @@ static void subflow_init_req(struct request_sock *req,
135128
subflow_req->mp_capable = 0;
136129
subflow_req->mp_join = 0;
137130
subflow_req->msk = NULL;
131+
mptcp_token_init_request(req);
138132

139133
#ifdef CONFIG_TCP_MD5SIG
140134
/* no MPTCP if MD5SIG is enabled on this socket or we may run out of
@@ -250,7 +244,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
250244
subflow->remote_nonce = mp_opt.nonce;
251245
pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u", subflow,
252246
subflow->thmac, subflow->remote_nonce);
253-
} else if (subflow->request_mptcp) {
247+
} else {
254248
tp->is_mptcp = 0;
255249
}
256250

@@ -386,7 +380,7 @@ static void mptcp_sock_destruct(struct sock *sk)
386380
sock_orphan(sk);
387381
}
388382

389-
mptcp_token_destroy(mptcp_sk(sk)->token);
383+
mptcp_token_destroy(mptcp_sk(sk));
390384
inet_sock_destruct(sk);
391385
}
392386

@@ -505,6 +499,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
505499
*/
506500
new_msk->sk_destruct = mptcp_sock_destruct;
507501
mptcp_pm_new_connection(mptcp_sk(new_msk), 1);
502+
mptcp_token_accept(subflow_req, mptcp_sk(new_msk));
508503
ctx->conn = new_msk;
509504
new_msk = NULL;
510505

0 commit comments

Comments
 (0)