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