0001
0002 #include <linux/skbuff.h>
0003
0004 #include "protocol.h"
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 struct join_entry {
0024 u32 token;
0025 u32 remote_nonce;
0026 u32 local_nonce;
0027 u8 join_id;
0028 u8 local_id;
0029 u8 backup;
0030 u8 valid;
0031 };
0032
0033 #define COOKIE_JOIN_SLOTS 1024
0034
0035 static struct join_entry join_entries[COOKIE_JOIN_SLOTS] __cacheline_aligned_in_smp;
0036 static spinlock_t join_entry_locks[COOKIE_JOIN_SLOTS] __cacheline_aligned_in_smp;
0037
0038 static u32 mptcp_join_entry_hash(struct sk_buff *skb, struct net *net)
0039 {
0040 static u32 mptcp_join_hash_secret __read_mostly;
0041 struct tcphdr *th = tcp_hdr(skb);
0042 u32 seq, i;
0043
0044 net_get_random_once(&mptcp_join_hash_secret,
0045 sizeof(mptcp_join_hash_secret));
0046
0047 if (th->syn)
0048 seq = TCP_SKB_CB(skb)->seq;
0049 else
0050 seq = TCP_SKB_CB(skb)->seq - 1;
0051
0052 i = jhash_3words(seq, net_hash_mix(net),
0053 (__force __u32)th->source << 16 | (__force __u32)th->dest,
0054 mptcp_join_hash_secret);
0055
0056 return i % ARRAY_SIZE(join_entries);
0057 }
0058
0059 static void mptcp_join_store_state(struct join_entry *entry,
0060 const struct mptcp_subflow_request_sock *subflow_req)
0061 {
0062 entry->token = subflow_req->token;
0063 entry->remote_nonce = subflow_req->remote_nonce;
0064 entry->local_nonce = subflow_req->local_nonce;
0065 entry->backup = subflow_req->backup;
0066 entry->join_id = subflow_req->remote_id;
0067 entry->local_id = subflow_req->local_id;
0068 entry->valid = 1;
0069 }
0070
0071 void subflow_init_req_cookie_join_save(const struct mptcp_subflow_request_sock *subflow_req,
0072 struct sk_buff *skb)
0073 {
0074 struct net *net = read_pnet(&subflow_req->sk.req.ireq_net);
0075 u32 i = mptcp_join_entry_hash(skb, net);
0076
0077
0078
0079
0080 spin_lock_bh(&join_entry_locks[i]);
0081 mptcp_join_store_state(&join_entries[i], subflow_req);
0082 spin_unlock_bh(&join_entry_locks[i]);
0083 }
0084
0085
0086
0087
0088
0089
0090
0091
0092 bool mptcp_token_join_cookie_init_state(struct mptcp_subflow_request_sock *subflow_req,
0093 struct sk_buff *skb)
0094 {
0095 struct net *net = read_pnet(&subflow_req->sk.req.ireq_net);
0096 u32 i = mptcp_join_entry_hash(skb, net);
0097 struct mptcp_sock *msk;
0098 struct join_entry *e;
0099
0100 e = &join_entries[i];
0101
0102 spin_lock_bh(&join_entry_locks[i]);
0103
0104 if (e->valid == 0) {
0105 spin_unlock_bh(&join_entry_locks[i]);
0106 return false;
0107 }
0108
0109 e->valid = 0;
0110
0111 msk = mptcp_token_get_sock(net, e->token);
0112 if (!msk) {
0113 spin_unlock_bh(&join_entry_locks[i]);
0114 return false;
0115 }
0116
0117 subflow_req->remote_nonce = e->remote_nonce;
0118 subflow_req->local_nonce = e->local_nonce;
0119 subflow_req->backup = e->backup;
0120 subflow_req->remote_id = e->join_id;
0121 subflow_req->token = e->token;
0122 subflow_req->msk = msk;
0123 spin_unlock_bh(&join_entry_locks[i]);
0124 return true;
0125 }
0126
0127 void __init mptcp_join_cookie_init(void)
0128 {
0129 int i;
0130
0131 for (i = 0; i < COOKIE_JOIN_SLOTS; i++)
0132 spin_lock_init(&join_entry_locks[i]);
0133 }