Skip to content

Commit e562d08

Browse files
committed
Merge branch 'mptcp-refactor-token-container'
Paolo Abeni says: ==================== mptcp: refactor token container Currently the msk sockets are stored in a single radix tree, protected by a global spin_lock. This series moves to an hash table, allocated at boot time, with per bucker spin_lock - alike inet_hashtables, but using a different key: the token itself. The above improves scalability, as write operations will have a far later chance to compete for lock acquisition, allows lockless lookup, and will allow easier msk traversing - e.g. for diag interface implementation's sake. This also introduces trivial, related, kunit tests and move the existing in kernel's one to kunit. v1 -> v2: - fixed a few extra and sparse warns ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents be7aa9f + a8ee9c9 commit e562d08

File tree

11 files changed

+487
-190
lines changed

11 files changed

+487
-190
lines changed

net/mptcp/Kconfig

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,20 @@ config MPTCP_IPV6
1818
select IPV6
1919
default y
2020

21-
config MPTCP_HMAC_TEST
22-
bool "Tests for MPTCP HMAC implementation"
21+
endif
22+
23+
config MPTCP_KUNIT_TESTS
24+
tristate "This builds the MPTCP KUnit tests" if !KUNIT_ALL_TESTS
25+
select MPTCP
26+
depends on KUNIT
27+
default KUNIT_ALL_TESTS
2328
help
24-
This option enable boot time self-test for the HMAC implementation
25-
used by the MPTCP code
29+
Currently covers the MPTCP crypto and token helpers.
30+
Only useful for kernel devs running KUnit test harness and are not
31+
for inclusion into a production build.
2632

27-
Say N if you are unsure.
33+
For more information on KUnit and unit tests in general please refer
34+
to the KUnit documentation in Documentation/dev-tools/kunit/.
35+
36+
If unsure, say N.
2837

29-
endif

net/mptcp/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@ obj-$(CONFIG_MPTCP) += mptcp.o
33

44
mptcp-y := protocol.o subflow.o options.o token.o crypto.o ctrl.o pm.o diag.o \
55
mib.o pm_netlink.o
6+
7+
mptcp_crypto_test-objs := crypto_test.o
8+
mptcp_token_test-objs := token_test.o
9+
obj-$(CONFIG_MPTCP_KUNIT_TESTS) += mptcp_crypto_test.o mptcp_token_test.o

net/mptcp/crypto.c

Lines changed: 2 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -87,65 +87,6 @@ void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u8 *msg, int len, void *hmac)
8787
sha256_final(&state, (u8 *)hmac);
8888
}
8989

90-
#ifdef CONFIG_MPTCP_HMAC_TEST
91-
struct test_cast {
92-
char *key;
93-
char *msg;
94-
char *result;
95-
};
96-
97-
/* we can't reuse RFC 4231 test vectors, as we have constraint on the
98-
* input and key size.
99-
*/
100-
static struct test_cast tests[] = {
101-
{
102-
.key = "0b0b0b0b0b0b0b0b",
103-
.msg = "48692054",
104-
.result = "8385e24fb4235ac37556b6b886db106284a1da671699f46db1f235ec622dcafa",
105-
},
106-
{
107-
.key = "aaaaaaaaaaaaaaaa",
108-
.msg = "dddddddd",
109-
.result = "2c5e219164ff1dca1c4a92318d847bb6b9d44492984e1eb71aff9022f71046e9",
110-
},
111-
{
112-
.key = "0102030405060708",
113-
.msg = "cdcdcdcd",
114-
.result = "e73b9ba9969969cefb04aa0d6df18ec2fcc075b6f23b4d8c4da736a5dbbc6e7d",
115-
},
116-
};
117-
118-
static int __init test_mptcp_crypto(void)
119-
{
120-
char hmac[32], hmac_hex[65];
121-
u32 nonce1, nonce2;
122-
u64 key1, key2;
123-
u8 msg[8];
124-
int i, j;
125-
126-
for (i = 0; i < ARRAY_SIZE(tests); ++i) {
127-
/* mptcp hmap will convert to be before computing the hmac */
128-
key1 = be64_to_cpu(*((__be64 *)&tests[i].key[0]));
129-
key2 = be64_to_cpu(*((__be64 *)&tests[i].key[8]));
130-
nonce1 = be32_to_cpu(*((__be32 *)&tests[i].msg[0]));
131-
nonce2 = be32_to_cpu(*((__be32 *)&tests[i].msg[4]));
132-
133-
put_unaligned_be32(nonce1, &msg[0]);
134-
put_unaligned_be32(nonce2, &msg[4]);
135-
136-
mptcp_crypto_hmac_sha(key1, key2, msg, 8, hmac);
137-
for (j = 0; j < 32; ++j)
138-
sprintf(&hmac_hex[j << 1], "%02x", hmac[j] & 0xff);
139-
hmac_hex[64] = 0;
140-
141-
if (memcmp(hmac_hex, tests[i].result, 64))
142-
pr_err("test %d failed, got %s expected %s", i,
143-
hmac_hex, tests[i].result);
144-
else
145-
pr_info("test %d [ ok ]", i);
146-
}
147-
return 0;
148-
}
149-
150-
late_initcall(test_mptcp_crypto);
90+
#if IS_MODULE(CONFIG_MPTCP_KUNIT_TESTS)
91+
EXPORT_SYMBOL_GPL(mptcp_crypto_hmac_sha);
15192
#endif

net/mptcp/crypto_test.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <kunit/test.h>
3+
4+
#include "protocol.h"
5+
6+
struct test_case {
7+
char *key;
8+
char *msg;
9+
char *result;
10+
};
11+
12+
/* we can't reuse RFC 4231 test vectors, as we have constraint on the
13+
* input and key size.
14+
*/
15+
static struct test_case tests[] = {
16+
{
17+
.key = "0b0b0b0b0b0b0b0b",
18+
.msg = "48692054",
19+
.result = "8385e24fb4235ac37556b6b886db106284a1da671699f46db1f235ec622dcafa",
20+
},
21+
{
22+
.key = "aaaaaaaaaaaaaaaa",
23+
.msg = "dddddddd",
24+
.result = "2c5e219164ff1dca1c4a92318d847bb6b9d44492984e1eb71aff9022f71046e9",
25+
},
26+
{
27+
.key = "0102030405060708",
28+
.msg = "cdcdcdcd",
29+
.result = "e73b9ba9969969cefb04aa0d6df18ec2fcc075b6f23b4d8c4da736a5dbbc6e7d",
30+
},
31+
};
32+
33+
static void mptcp_crypto_test_basic(struct kunit *test)
34+
{
35+
char hmac[32], hmac_hex[65];
36+
u32 nonce1, nonce2;
37+
u64 key1, key2;
38+
u8 msg[8];
39+
int i, j;
40+
41+
for (i = 0; i < ARRAY_SIZE(tests); ++i) {
42+
/* mptcp hmap will convert to be before computing the hmac */
43+
key1 = be64_to_cpu(*((__be64 *)&tests[i].key[0]));
44+
key2 = be64_to_cpu(*((__be64 *)&tests[i].key[8]));
45+
nonce1 = be32_to_cpu(*((__be32 *)&tests[i].msg[0]));
46+
nonce2 = be32_to_cpu(*((__be32 *)&tests[i].msg[4]));
47+
48+
put_unaligned_be32(nonce1, &msg[0]);
49+
put_unaligned_be32(nonce2, &msg[4]);
50+
51+
mptcp_crypto_hmac_sha(key1, key2, msg, 8, hmac);
52+
for (j = 0; j < 32; ++j)
53+
sprintf(&hmac_hex[j << 1], "%02x", hmac[j] & 0xff);
54+
hmac_hex[64] = 0;
55+
56+
KUNIT_EXPECT_STREQ(test, &hmac_hex[0], tests[i].result);
57+
}
58+
}
59+
60+
static struct kunit_case mptcp_crypto_test_cases[] = {
61+
KUNIT_CASE(mptcp_crypto_test_basic),
62+
{}
63+
};
64+
65+
static struct kunit_suite mptcp_crypto_suite = {
66+
.name = "mptcp-crypto",
67+
.test_cases = mptcp_crypto_test_cases,
68+
};
69+
70+
kunit_test_suite(mptcp_crypto_suite);
71+
72+
MODULE_LICENSE("GPL");

net/mptcp/pm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ void mptcp_pm_close(struct mptcp_sock *msk)
234234
sock_put((struct sock *)msk);
235235
}
236236

237-
void mptcp_pm_init(void)
237+
void __init mptcp_pm_init(void)
238238
{
239239
pm_wq = alloc_workqueue("pm_wq", WQ_UNBOUND | WQ_MEM_RECLAIM, 8);
240240
if (!pm_wq)

net/mptcp/pm_netlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ static struct pernet_operations mptcp_pm_pernet_ops = {
851851
.size = sizeof(struct pm_nl_pernet),
852852
};
853853

854-
void mptcp_pm_nl_init(void)
854+
void __init mptcp_pm_nl_init(void)
855855
{
856856
if (register_pernet_subsys(&mptcp_pm_pernet_ops) < 0)
857857
panic("Failed to register MPTCP PM pernet subsystem.\n");

net/mptcp/protocol.c

Lines changed: 28 additions & 21 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);
@@ -2077,7 +2083,7 @@ static struct inet_protosw mptcp_protosw = {
20772083
.flags = INET_PROTOSW_ICSK,
20782084
};
20792085

2080-
void mptcp_proto_init(void)
2086+
void __init mptcp_proto_init(void)
20812087
{
20822088
mptcp_prot.h.hashinfo = tcp_prot.h.hashinfo;
20832089

@@ -2086,6 +2092,7 @@ void 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");
@@ -2139,7 +2146,7 @@ static struct inet_protosw mptcp_v6_protosw = {
21392146
.flags = INET_PROTOSW_ICSK,
21402147
};
21412148

2142-
int mptcp_proto_v6_init(void)
2149+
int __init mptcp_proto_v6_init(void)
21432150
{
21442151
int err;
21452152

0 commit comments

Comments
 (0)