Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /* Multipath TCP token management
3 : : * Copyright (c) 2017 - 2019, Intel Corporation.
4 : : *
5 : : * Note: This code is based on mptcp_ctrl.c from multipath-tcp.org,
6 : : * authored by:
7 : : *
8 : : * Sébastien Barré <sebastien.barre@uclouvain.be>
9 : : * Christoph Paasch <christoph.paasch@uclouvain.be>
10 : : * Jaakko Korkeaniemi <jaakko.korkeaniemi@aalto.fi>
11 : : * Gregory Detal <gregory.detal@uclouvain.be>
12 : : * Fabien Duchêne <fabien.duchene@uclouvain.be>
13 : : * Andreas Seelinger <Andreas.Seelinger@rwth-aachen.de>
14 : : * Lavkesh Lahngir <lavkesh51@gmail.com>
15 : : * Andreas Ripke <ripke@neclab.eu>
16 : : * Vlad Dogaru <vlad.dogaru@intel.com>
17 : : * Octavian Purdila <octavian.purdila@intel.com>
18 : : * John Ronan <jronan@tssg.org>
19 : : * Catalin Nicutar <catalin.nicutar@gmail.com>
20 : : * Brandon Heller <brandonh@stanford.edu>
21 : : */
22 : :
23 : : #define pr_fmt(fmt) "MPTCP: " fmt
24 : :
25 : : #include <linux/kernel.h>
26 : : #include <linux/module.h>
27 : : #include <linux/memblock.h>
28 : : #include <linux/ip.h>
29 : : #include <linux/tcp.h>
30 : : #include <net/sock.h>
31 : : #include <net/inet_common.h>
32 : : #include <net/protocol.h>
33 : : #include <net/mptcp.h>
34 : : #include "protocol.h"
35 : :
36 : : #define TOKEN_MAX_CHAIN_LEN 4
37 : :
38 : : struct token_bucket {
39 : : spinlock_t lock;
40 : : int chain_len;
41 : : struct hlist_nulls_head req_chain;
42 : : struct hlist_nulls_head msk_chain;
43 : : };
44 : :
45 : : static struct token_bucket *token_hash __read_mostly;
46 : : static unsigned int token_mask __read_mostly;
47 : :
48 : 0 : static struct token_bucket *token_bucket(u32 token)
49 : : {
50 : 6351 : return &token_hash[token & token_mask];
51 : : }
52 : :
53 : : /* called with bucket lock held */
54 : : static struct mptcp_subflow_request_sock *
55 : 0 : __token_lookup_req(struct token_bucket *t, u32 token)
56 : : {
57 : 3458 : struct mptcp_subflow_request_sock *req;
58 : 3458 : struct hlist_nulls_node *pos;
59 : :
60 [ + - + - : 3650 : hlist_nulls_for_each_entry_rcu(req, pos, &t->req_chain, token_node)
- + ]
61 [ - + - + : 1192 : if (req->token == token)
- - ]
62 : : return req;
63 : : return NULL;
64 : : }
65 : :
66 : : /* called with bucket lock held */
67 : : static struct mptcp_sock *
68 : 4816 : __token_lookup_msk(struct token_bucket *t, u32 token)
69 : : {
70 : 4816 : struct hlist_nulls_node *pos;
71 : 4816 : struct sock *sk;
72 : :
73 [ + + ]: 4835 : sk_nulls_for_each_rcu(sk, pos, &t->msk_chain)
74 [ + + - + ]: 2377 : if (mptcp_sk(sk)->token == token)
75 [ - + ]: 2358 : return mptcp_sk(sk);
76 : : return NULL;
77 : : }
78 : :
79 : 2458 : static bool __token_bucket_busy(struct token_bucket *t, u32 token)
80 : : {
81 [ - + - + ]: 4790 : return !token || t->chain_len >= TOKEN_MAX_CHAIN_LEN ||
82 [ + - - + : 4916 : __token_lookup_req(t, token) || __token_lookup_msk(t, token);
- + ]
83 : : }
84 : :
85 : 1266 : static void mptcp_crypto_key_gen_sha(u64 *key, u32 *token, u64 *idsn)
86 : : {
87 : : /* we might consider a faster version that computes the key as a
88 : : * hash of some information available in the MPTCP socket. Use
89 : : * random data at the moment, as it's probably the safest option
90 : : * in case multiple sockets are opened in different namespaces at
91 : : * the same time.
92 : : */
93 : 1266 : get_random_bytes(key, sizeof(u64));
94 : 1266 : mptcp_crypto_key_sha(*key, token, idsn);
95 : 1266 : }
96 : :
97 : : /**
98 : : * mptcp_token_new_request - create new key/idsn/token for subflow_request
99 : : * @req: the request socket
100 : : *
101 : : * This function is called when a new mptcp connection is coming in.
102 : : *
103 : : * It creates a unique token to identify the new mptcp connection,
104 : : * a secret local key and the initial data sequence number (idsn).
105 : : *
106 : : * Returns 0 on success.
107 : : */
108 : 1192 : int mptcp_token_new_request(struct request_sock *req)
109 : : {
110 : 1192 : struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
111 : 1192 : struct token_bucket *bucket;
112 : 1192 : u32 token;
113 : :
114 : 1192 : mptcp_crypto_key_sha(subflow_req->local_key,
115 : : &subflow_req->token,
116 : : &subflow_req->idsn);
117 [ - + ]: 1192 : pr_debug("req=%p local_key=%llu, token=%u, idsn=%llu\n",
118 : : req, subflow_req->local_key, subflow_req->token,
119 : : subflow_req->idsn);
120 : :
121 : 1192 : token = subflow_req->token;
122 : 1192 : bucket = token_bucket(token);
123 : 1192 : spin_lock_bh(&bucket->lock);
124 [ - + ]: 1192 : if (__token_bucket_busy(bucket, token)) {
125 : 0 : spin_unlock_bh(&bucket->lock);
126 : 0 : return -EBUSY;
127 : : }
128 : :
129 : 1192 : hlist_nulls_add_head_rcu(&subflow_req->token_node, &bucket->req_chain);
130 : 1192 : bucket->chain_len++;
131 : 1192 : spin_unlock_bh(&bucket->lock);
132 : 1192 : return 0;
133 : : }
134 : :
135 : : /**
136 : : * mptcp_token_new_connect - create new key/idsn/token for subflow
137 : : * @ssk: the socket that will initiate a connection
138 : : *
139 : : * This function is called when a new outgoing mptcp connection is
140 : : * initiated.
141 : : *
142 : : * It creates a unique token to identify the new mptcp connection,
143 : : * a secret local key and the initial data sequence number (idsn).
144 : : *
145 : : * On success, the mptcp connection can be found again using
146 : : * the computed token at a later time, this is needed to process
147 : : * join requests.
148 : : *
149 : : * returns 0 on success.
150 : : */
151 : 1266 : int mptcp_token_new_connect(struct sock *ssk)
152 : : {
153 [ - + ]: 1266 : struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
154 [ - + ]: 1266 : struct mptcp_sock *msk = mptcp_sk(subflow->conn);
155 : 60 : int retries = MPTCP_TOKEN_MAX_RETRIES;
156 : : struct sock *sk = subflow->conn;
157 : 60 : struct token_bucket *bucket;
158 : :
159 : 1266 : again:
160 : 1266 : mptcp_crypto_key_gen_sha(&subflow->local_key, &subflow->token,
161 : : &subflow->idsn);
162 : :
163 : 1266 : bucket = token_bucket(subflow->token);
164 : 1266 : spin_lock_bh(&bucket->lock);
165 [ - + ]: 1266 : if (__token_bucket_busy(bucket, subflow->token)) {
166 : 0 : spin_unlock_bh(&bucket->lock);
167 [ # # ]: 0 : if (!--retries)
168 : : return -EBUSY;
169 : 0 : goto again;
170 : : }
171 : :
172 [ - + ]: 1266 : pr_debug("ssk=%p, local_key=%llu, token=%u, idsn=%llu\n",
173 : : ssk, subflow->local_key, subflow->token, subflow->idsn);
174 : :
175 : 1266 : WRITE_ONCE(msk->token, subflow->token);
176 : 1266 : __sk_nulls_add_node_rcu((struct sock *)msk, &bucket->msk_chain);
177 : 1266 : bucket->chain_len++;
178 : 1266 : spin_unlock_bh(&bucket->lock);
179 : 1266 : sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
180 : 1266 : return 0;
181 : : }
182 : :
183 : : /**
184 : : * mptcp_token_accept - replace a req sk with full sock in token hash
185 : : * @req: the request socket to be removed
186 : : * @msk: the just cloned socket linked to the new connection
187 : : *
188 : : * Called when a SYN packet creates a new logical connection, i.e.
189 : : * is not a join request.
190 : : */
191 : 1166 : void mptcp_token_accept(struct mptcp_subflow_request_sock *req,
192 : : struct mptcp_sock *msk)
193 : : {
194 : 1166 : struct mptcp_subflow_request_sock *pos;
195 : 1166 : struct sock *sk = (struct sock *)msk;
196 : 1166 : struct token_bucket *bucket;
197 : :
198 : 1166 : sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
199 : 1166 : bucket = token_bucket(req->token);
200 : 1166 : spin_lock_bh(&bucket->lock);
201 : :
202 : : /* pedantic lookup check for the moved token */
203 : 1166 : pos = __token_lookup_req(bucket, req->token);
204 [ - + + - ]: 1166 : if (!WARN_ON_ONCE(pos != req))
205 : 1166 : hlist_nulls_del_init_rcu(&req->token_node);
206 : 1166 : __sk_nulls_add_node_rcu((struct sock *)msk, &bucket->msk_chain);
207 : 1166 : spin_unlock_bh(&bucket->lock);
208 : 1166 : }
209 : :
210 : 28 : bool mptcp_token_exists(u32 token)
211 : : {
212 : 28 : struct hlist_nulls_node *pos;
213 : 28 : struct token_bucket *bucket;
214 : 28 : struct mptcp_sock *msk;
215 : 28 : struct sock *sk;
216 : :
217 : 28 : rcu_read_lock();
218 : 28 : bucket = token_bucket(token);
219 : :
220 : 28 : again:
221 [ - + ]: 28 : sk_nulls_for_each_rcu(sk, pos, &bucket->msk_chain) {
222 [ # # ]: 0 : msk = mptcp_sk(sk);
223 [ # # ]: 0 : if (READ_ONCE(msk->token) == token)
224 : 0 : goto found;
225 : : }
226 [ - + ]: 28 : if (get_nulls_value(pos) != (token & token_mask))
227 : 0 : goto again;
228 : :
229 : 28 : rcu_read_unlock();
230 : 28 : return false;
231 : 0 : found:
232 : 0 : rcu_read_unlock();
233 : 0 : return true;
234 : : }
235 : :
236 : : /**
237 : : * mptcp_token_get_sock - retrieve mptcp connection sock using its token
238 : : * @net: restrict to this namespace
239 : : * @token: token of the mptcp connection to retrieve
240 : : *
241 : : * This function returns the mptcp connection structure with the given token.
242 : : * A reference count on the mptcp socket returned is taken.
243 : : *
244 : : * returns NULL if no connection with the given token value exists.
245 : : */
246 : 693 : struct mptcp_sock *mptcp_token_get_sock(struct net *net, u32 token)
247 : : {
248 : 693 : struct hlist_nulls_node *pos;
249 : 693 : struct token_bucket *bucket;
250 : 693 : struct mptcp_sock *msk;
251 : 693 : struct sock *sk;
252 : :
253 : 693 : rcu_read_lock();
254 : 693 : bucket = token_bucket(token);
255 : :
256 : : again:
257 [ + + ]: 693 : sk_nulls_for_each_rcu(sk, pos, &bucket->msk_chain) {
258 [ - + ]: 679 : msk = mptcp_sk(sk);
259 [ + - - + ]: 988 : if (READ_ONCE(msk->token) != token ||
260 [ - + ]: 60 : !net_eq(sock_net(sk), net))
261 : 0 : continue;
262 : :
263 [ + + ]: 679 : if (!refcount_inc_not_zero(&sk->sk_refcnt))
264 : 2 : goto not_found;
265 : :
266 [ + - - + ]: 985 : if (READ_ONCE(msk->token) != token ||
267 [ - + ]: 60 : !net_eq(sock_net(sk), net)) {
268 : 0 : sock_put(sk);
269 : 0 : goto again;
270 : : }
271 : 677 : goto found;
272 : : }
273 [ - + ]: 14 : if (get_nulls_value(pos) != (token & token_mask))
274 : 0 : goto again;
275 : :
276 : 14 : not_found:
277 : : msk = NULL;
278 : :
279 : 693 : found:
280 : 693 : rcu_read_unlock();
281 : 693 : return msk;
282 : : }
283 : : EXPORT_SYMBOL_GPL(mptcp_token_get_sock);
284 : :
285 : : /**
286 : : * mptcp_token_iter_next - iterate over the token container from given pos
287 : : * @net: namespace to be iterated
288 : : * @s_slot: start slot number
289 : : * @s_num: start number inside the given lock
290 : : *
291 : : * This function returns the first mptcp connection structure found inside the
292 : : * token container starting from the specified position, or NULL.
293 : : *
294 : : * On successful iteration, the iterator is moved to the next position and
295 : : * a reference to the returned socket is acquired.
296 : : */
297 : 5518 : struct mptcp_sock *mptcp_token_iter_next(const struct net *net, long *s_slot,
298 : : long *s_num)
299 : : {
300 : 5518 : struct mptcp_sock *ret = NULL;
301 : 5518 : struct hlist_nulls_node *pos;
302 : 5518 : int slot, num = 0;
303 : :
304 [ + + ]: 9196942 : for (slot = *s_slot; slot <= token_mask; *s_num = 0, slot++) {
305 : 9194464 : struct token_bucket *bucket = &token_hash[slot];
306 : 9194464 : struct sock *sk;
307 : :
308 : 9194464 : num = 0;
309 : :
310 [ + + ]: 9194464 : if (hlist_nulls_empty(&bucket->msk_chain))
311 : 9186495 : continue;
312 : :
313 : 7969 : rcu_read_lock();
314 [ + + ]: 13001 : sk_nulls_for_each_rcu(sk, pos, &bucket->msk_chain) {
315 : 8072 : ++num;
316 [ + + ]: 8072 : if (!net_eq(sock_net(sk), net))
317 : 1956 : continue;
318 : :
319 [ + + ]: 6116 : if (num <= *s_num)
320 : 3076 : continue;
321 : :
322 [ - + ]: 3040 : if (!refcount_inc_not_zero(&sk->sk_refcnt))
323 : 0 : continue;
324 : :
325 [ - + ]: 3040 : if (!net_eq(sock_net(sk), net)) {
326 : 0 : sock_put(sk);
327 : 0 : continue;
328 : : }
329 : :
330 [ - + ]: 3040 : ret = mptcp_sk(sk);
331 : 3040 : rcu_read_unlock();
332 : 3040 : goto out;
333 : : }
334 : 4929 : rcu_read_unlock();
335 : : }
336 : :
337 : 2478 : out:
338 : 5518 : *s_slot = slot;
339 : 5518 : *s_num = num;
340 : 5518 : return ret;
341 : : }
342 : : EXPORT_SYMBOL_GPL(mptcp_token_iter_next);
343 : :
344 : : /**
345 : : * mptcp_token_destroy_request - remove mptcp connection/token
346 : : * @req: mptcp request socket dropping the token
347 : : *
348 : : * Remove the token associated to @req.
349 : : */
350 : 1837 : void mptcp_token_destroy_request(struct request_sock *req)
351 : : {
352 : 1837 : struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
353 : 1837 : struct mptcp_subflow_request_sock *pos;
354 : 1837 : struct token_bucket *bucket;
355 : :
356 [ + + ]: 1837 : if (hlist_nulls_unhashed(&subflow_req->token_node))
357 : : return;
358 : :
359 : 26 : bucket = token_bucket(subflow_req->token);
360 : 26 : spin_lock_bh(&bucket->lock);
361 : 26 : pos = __token_lookup_req(bucket, subflow_req->token);
362 [ - + + - ]: 26 : if (!WARN_ON_ONCE(pos != subflow_req)) {
363 : 26 : hlist_nulls_del_init_rcu(&pos->token_node);
364 : 26 : bucket->chain_len--;
365 : : }
366 : 26 : spin_unlock_bh(&bucket->lock);
367 : : }
368 : :
369 : : /**
370 : : * mptcp_token_destroy - remove mptcp connection/token
371 : : * @msk: mptcp connection dropping the token
372 : : *
373 : : * Remove the token associated to @msk
374 : : */
375 : 3885 : void mptcp_token_destroy(struct mptcp_sock *msk)
376 : : {
377 : 3885 : struct sock *sk = (struct sock *)msk;
378 : 3885 : struct token_bucket *bucket;
379 : 3885 : struct mptcp_sock *pos;
380 : :
381 [ + + ]: 3885 : if (sk_unhashed((struct sock *)msk))
382 : : return;
383 : :
384 : 2358 : sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
385 : 2358 : bucket = token_bucket(msk->token);
386 : 2358 : spin_lock_bh(&bucket->lock);
387 : 2358 : pos = __token_lookup_msk(bucket, msk->token);
388 [ - + + - ]: 2358 : if (!WARN_ON_ONCE(pos != msk)) {
389 [ + - ]: 2358 : __sk_nulls_del_node_init_rcu((struct sock *)pos);
390 : 2358 : bucket->chain_len--;
391 : : }
392 : 2358 : spin_unlock_bh(&bucket->lock);
393 : 2358 : WRITE_ONCE(msk->token, 0);
394 : : }
395 : :
396 : 4 : void __init mptcp_token_init(void)
397 : : {
398 : 4 : int i;
399 : :
400 : 4 : token_hash = alloc_large_system_hash("MPTCP token",
401 : : sizeof(struct token_bucket),
402 : : 0,
403 : : 20,/* one slot per 1MB of memory */
404 : : HASH_ZERO,
405 : : NULL,
406 : : &token_mask,
407 : : 0,
408 : : 64 * 1024);
409 [ + + ]: 16388 : for (i = 0; i < token_mask + 1; ++i) {
410 : 16384 : INIT_HLIST_NULLS_HEAD(&token_hash[i].req_chain, i);
411 : 16384 : INIT_HLIST_NULLS_HEAD(&token_hash[i].msk_chain, i);
412 : 16384 : spin_lock_init(&token_hash[i].lock);
413 : : }
414 : 4 : }
415 : :
416 : : #if IS_MODULE(CONFIG_MPTCP_KUNIT_TEST)
417 : : EXPORT_SYMBOL_GPL(mptcp_token_new_request);
418 : : EXPORT_SYMBOL_GPL(mptcp_token_new_connect);
419 : : EXPORT_SYMBOL_GPL(mptcp_token_accept);
420 : : EXPORT_SYMBOL_GPL(mptcp_token_destroy_request);
421 : : EXPORT_SYMBOL_GPL(mptcp_token_destroy);
422 : : #endif
|