]> git.ipfire.org Git - thirdparty/linux.git/blame - net/rxrpc/peer_object.c
Merge tag 'x86-fpu-2020-06-01' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
[thirdparty/linux.git] / net / rxrpc / peer_object.c
CommitLineData
2874c5fd 1// SPDX-License-Identifier: GPL-2.0-or-later
be6e6707 2/* RxRPC remote transport endpoint record management
17926a79 3 *
be6e6707 4 * Copyright (C) 2007, 2016 Red Hat, Inc. All Rights Reserved.
17926a79 5 * Written by David Howells (dhowells@redhat.com)
17926a79
DH
6 */
7
9b6d5398
JP
8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9
17926a79
DH
10#include <linux/module.h>
11#include <linux/net.h>
12#include <linux/skbuff.h>
13#include <linux/udp.h>
14#include <linux/in.h>
75b54cb5 15#include <linux/in6.h>
5a0e3ad6 16#include <linux/slab.h>
be6e6707 17#include <linux/hashtable.h>
17926a79
DH
18#include <net/sock.h>
19#include <net/af_rxrpc.h>
20#include <net/ip.h>
224711df 21#include <net/route.h>
75b54cb5 22#include <net/ip6_route.h>
17926a79
DH
23#include "ar-internal.h"
24
be6e6707
DH
25/*
26 * Hash a peer key.
27 */
28static unsigned long rxrpc_peer_hash_key(struct rxrpc_local *local,
29 const struct sockaddr_rxrpc *srx)
30{
31 const u16 *p;
32 unsigned int i, size;
33 unsigned long hash_key;
34
35 _enter("");
36
37 hash_key = (unsigned long)local / __alignof__(*local);
38 hash_key += srx->transport_type;
39 hash_key += srx->transport_len;
40 hash_key += srx->transport.family;
41
42 switch (srx->transport.family) {
43 case AF_INET:
44 hash_key += (u16 __force)srx->transport.sin.sin_port;
45 size = sizeof(srx->transport.sin.sin_addr);
46 p = (u16 *)&srx->transport.sin.sin_addr;
47 break;
d1912747 48#ifdef CONFIG_AF_RXRPC_IPV6
75b54cb5
DH
49 case AF_INET6:
50 hash_key += (u16 __force)srx->transport.sin.sin_port;
51 size = sizeof(srx->transport.sin6.sin6_addr);
52 p = (u16 *)&srx->transport.sin6.sin6_addr;
53 break;
d1912747 54#endif
2f9f9f52
AB
55 default:
56 WARN(1, "AF_RXRPC: Unsupported transport address family\n");
57 return 0;
be6e6707
DH
58 }
59
60 /* Step through the peer address in 16-bit portions for speed */
61 for (i = 0; i < size; i += sizeof(*p), p++)
62 hash_key += *p;
63
64 _leave(" 0x%lx", hash_key);
65 return hash_key;
66}
67
68/*
69 * Compare a peer to a key. Return -ve, 0 or +ve to indicate less than, same
70 * or greater than.
71 *
72 * Unfortunately, the primitives in linux/hashtable.h don't allow for sorted
73 * buckets and mid-bucket insertion, so we don't make full use of this
74 * information at this point.
75 */
76static long rxrpc_peer_cmp_key(const struct rxrpc_peer *peer,
77 struct rxrpc_local *local,
78 const struct sockaddr_rxrpc *srx,
79 unsigned long hash_key)
80{
81 long diff;
82
83 diff = ((peer->hash_key - hash_key) ?:
84 ((unsigned long)peer->local - (unsigned long)local) ?:
85 (peer->srx.transport_type - srx->transport_type) ?:
86 (peer->srx.transport_len - srx->transport_len) ?:
87 (peer->srx.transport.family - srx->transport.family));
88 if (diff != 0)
89 return diff;
90
91 switch (srx->transport.family) {
92 case AF_INET:
93 return ((u16 __force)peer->srx.transport.sin.sin_port -
94 (u16 __force)srx->transport.sin.sin_port) ?:
95 memcmp(&peer->srx.transport.sin.sin_addr,
96 &srx->transport.sin.sin_addr,
97 sizeof(struct in_addr));
d1912747 98#ifdef CONFIG_AF_RXRPC_IPV6
75b54cb5
DH
99 case AF_INET6:
100 return ((u16 __force)peer->srx.transport.sin6.sin6_port -
101 (u16 __force)srx->transport.sin6.sin6_port) ?:
102 memcmp(&peer->srx.transport.sin6.sin6_addr,
103 &srx->transport.sin6.sin6_addr,
104 sizeof(struct in6_addr));
d1912747 105#endif
be6e6707
DH
106 default:
107 BUG();
108 }
109}
110
111/*
112 * Look up a remote transport endpoint for the specified address using RCU.
113 */
114static struct rxrpc_peer *__rxrpc_lookup_peer_rcu(
115 struct rxrpc_local *local,
116 const struct sockaddr_rxrpc *srx,
117 unsigned long hash_key)
118{
119 struct rxrpc_peer *peer;
2baec2c3 120 struct rxrpc_net *rxnet = local->rxnet;
be6e6707 121
2baec2c3 122 hash_for_each_possible_rcu(rxnet->peer_hash, peer, hash_link, hash_key) {
0099dc58
DH
123 if (rxrpc_peer_cmp_key(peer, local, srx, hash_key) == 0 &&
124 atomic_read(&peer->usage) > 0)
be6e6707 125 return peer;
be6e6707
DH
126 }
127
128 return NULL;
129}
130
131/*
132 * Look up a remote transport endpoint for the specified address using RCU.
133 */
134struct rxrpc_peer *rxrpc_lookup_peer_rcu(struct rxrpc_local *local,
135 const struct sockaddr_rxrpc *srx)
136{
137 struct rxrpc_peer *peer;
138 unsigned long hash_key = rxrpc_peer_hash_key(local, srx);
139
140 peer = __rxrpc_lookup_peer_rcu(local, srx, hash_key);
141 if (peer) {
75b54cb5 142 _net("PEER %d {%pISp}", peer->debug_id, &peer->srx.transport);
be6e6707
DH
143 _leave(" = %p {u=%d}", peer, atomic_read(&peer->usage));
144 }
145 return peer;
146}
17926a79 147
224711df
DH
148/*
149 * assess the MTU size for the network interface through which this peer is
150 * reached
151 */
5e33a23b
DH
152static void rxrpc_assess_MTU_size(struct rxrpc_sock *rx,
153 struct rxrpc_peer *peer)
224711df 154{
5e33a23b 155 struct net *net = sock_net(&rx->sk);
75b54cb5 156 struct dst_entry *dst;
224711df 157 struct rtable *rt;
75b54cb5
DH
158 struct flowi fl;
159 struct flowi4 *fl4 = &fl.u.ip4;
d1912747 160#ifdef CONFIG_AF_RXRPC_IPV6
75b54cb5 161 struct flowi6 *fl6 = &fl.u.ip6;
d1912747 162#endif
224711df
DH
163
164 peer->if_mtu = 1500;
165
75b54cb5
DH
166 memset(&fl, 0, sizeof(fl));
167 switch (peer->srx.transport.family) {
168 case AF_INET:
169 rt = ip_route_output_ports(
5e33a23b 170 net, fl4, NULL,
75b54cb5
DH
171 peer->srx.transport.sin.sin_addr.s_addr, 0,
172 htons(7000), htons(7001), IPPROTO_UDP, 0, 0);
173 if (IS_ERR(rt)) {
174 _leave(" [route err %ld]", PTR_ERR(rt));
175 return;
176 }
177 dst = &rt->dst;
178 break;
179
d1912747 180#ifdef CONFIG_AF_RXRPC_IPV6
75b54cb5
DH
181 case AF_INET6:
182 fl6->flowi6_iif = LOOPBACK_IFINDEX;
183 fl6->flowi6_scope = RT_SCOPE_UNIVERSE;
184 fl6->flowi6_proto = IPPROTO_UDP;
185 memcpy(&fl6->daddr, &peer->srx.transport.sin6.sin6_addr,
186 sizeof(struct in6_addr));
187 fl6->fl6_dport = htons(7001);
188 fl6->fl6_sport = htons(7000);
5e33a23b 189 dst = ip6_route_output(net, NULL, fl6);
07096f61
DH
190 if (dst->error) {
191 _leave(" [route err %d]", dst->error);
75b54cb5
DH
192 return;
193 }
194 break;
d1912747 195#endif
75b54cb5
DH
196
197 default:
198 BUG();
224711df
DH
199 }
200
75b54cb5
DH
201 peer->if_mtu = dst_mtu(dst);
202 dst_release(dst);
224711df 203
a6a62b69 204 _leave(" [if_mtu %u]", peer->if_mtu);
224711df
DH
205}
206
17926a79 207/*
be6e6707 208 * Allocate a peer.
17926a79 209 */
be6e6707 210struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *local, gfp_t gfp)
17926a79 211{
033b2c7f 212 const void *here = __builtin_return_address(0);
17926a79
DH
213 struct rxrpc_peer *peer;
214
215 _enter("");
216
217 peer = kzalloc(sizeof(struct rxrpc_peer), gfp);
218 if (peer) {
be6e6707 219 atomic_set(&peer->usage, 1);
9ebeddef 220 peer->local = rxrpc_get_local(local);
f66d7490 221 INIT_HLIST_HEAD(&peer->error_targets);
aa390bbe 222 peer->service_conns = RB_ROOT;
8496af50 223 seqlock_init(&peer->service_conn_lock);
17926a79 224 spin_lock_init(&peer->lock);
c1e15b49 225 spin_lock_init(&peer->rtt_input_lock);
17926a79 226 peer->debug_id = atomic_inc_return(&rxrpc_debug_id);
f7aec129 227
c410bf01
DH
228 rxrpc_peer_init_rtt(peer);
229
f7aec129
DH
230 if (RXRPC_TX_SMSS > 2190)
231 peer->cong_cwnd = 2;
232 else if (RXRPC_TX_SMSS > 1095)
233 peer->cong_cwnd = 3;
234 else
235 peer->cong_cwnd = 4;
2f184393 236 trace_rxrpc_peer(peer->debug_id, rxrpc_peer_new, 1, here);
be6e6707
DH
237 }
238
239 _leave(" = %p", peer);
240 return peer;
241}
242
248f219c
DH
243/*
244 * Initialise peer record.
245 */
5e33a23b
DH
246static void rxrpc_init_peer(struct rxrpc_sock *rx, struct rxrpc_peer *peer,
247 unsigned long hash_key)
248f219c 248{
08a39685 249 peer->hash_key = hash_key;
5e33a23b 250 rxrpc_assess_MTU_size(rx, peer);
248f219c 251 peer->mtu = peer->if_mtu;
0d4b103c 252 peer->rtt_last_req = ktime_get_real();
248f219c 253
75b54cb5
DH
254 switch (peer->srx.transport.family) {
255 case AF_INET:
248f219c 256 peer->hdrsize = sizeof(struct iphdr);
75b54cb5 257 break;
d1912747 258#ifdef CONFIG_AF_RXRPC_IPV6
75b54cb5
DH
259 case AF_INET6:
260 peer->hdrsize = sizeof(struct ipv6hdr);
261 break;
d1912747 262#endif
75b54cb5
DH
263 default:
264 BUG();
265 }
266
267 switch (peer->srx.transport_type) {
268 case SOCK_DGRAM:
269 peer->hdrsize += sizeof(struct udphdr);
270 break;
271 default:
248f219c
DH
272 BUG();
273 }
274
275 peer->hdrsize += sizeof(struct rxrpc_wire_header);
276 peer->maxdata = peer->mtu - peer->hdrsize;
277}
278
be6e6707
DH
279/*
280 * Set up a new peer.
281 */
5e33a23b
DH
282static struct rxrpc_peer *rxrpc_create_peer(struct rxrpc_sock *rx,
283 struct rxrpc_local *local,
be6e6707
DH
284 struct sockaddr_rxrpc *srx,
285 unsigned long hash_key,
286 gfp_t gfp)
287{
288 struct rxrpc_peer *peer;
289
290 _enter("");
291
292 peer = rxrpc_alloc_peer(local, gfp);
293 if (peer) {
17926a79 294 memcpy(&peer->srx, srx, sizeof(*srx));
5e33a23b 295 rxrpc_init_peer(rx, peer, hash_key);
248f219c 296 }
17926a79 297
248f219c
DH
298 _leave(" = %p", peer);
299 return peer;
300}
17926a79 301
248f219c 302/*
0099dc58
DH
303 * Set up a new incoming peer. There shouldn't be any other matching peers
304 * since we've already done a search in the list from the non-reentrant context
305 * (the data_ready handler) that is the only place we can add new peers.
248f219c 306 */
5e33a23b
DH
307void rxrpc_new_incoming_peer(struct rxrpc_sock *rx, struct rxrpc_local *local,
308 struct rxrpc_peer *peer)
248f219c 309{
2baec2c3 310 struct rxrpc_net *rxnet = local->rxnet;
248f219c
DH
311 unsigned long hash_key;
312
0099dc58 313 hash_key = rxrpc_peer_hash_key(local, &peer->srx);
5e33a23b 314 rxrpc_init_peer(rx, peer, hash_key);
248f219c 315
2baec2c3 316 spin_lock(&rxnet->peer_hash_lock);
0099dc58
DH
317 hash_add_rcu(rxnet->peer_hash, &peer->hash_link, hash_key);
318 list_add_tail(&peer->keepalive_link, &rxnet->peer_keepalive_new);
2baec2c3 319 spin_unlock(&rxnet->peer_hash_lock);
17926a79
DH
320}
321
322/*
323 * obtain a remote transport endpoint for the specified address
324 */
5e33a23b
DH
325struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_sock *rx,
326 struct rxrpc_local *local,
be6e6707 327 struct sockaddr_rxrpc *srx, gfp_t gfp)
17926a79
DH
328{
329 struct rxrpc_peer *peer, *candidate;
2baec2c3 330 struct rxrpc_net *rxnet = local->rxnet;
be6e6707 331 unsigned long hash_key = rxrpc_peer_hash_key(local, srx);
17926a79 332
75b54cb5 333 _enter("{%pISp}", &srx->transport);
17926a79
DH
334
335 /* search the peer list first */
be6e6707
DH
336 rcu_read_lock();
337 peer = __rxrpc_lookup_peer_rcu(local, srx, hash_key);
338 if (peer && !rxrpc_get_peer_maybe(peer))
339 peer = NULL;
340 rcu_read_unlock();
341
342 if (!peer) {
343 /* The peer is not yet present in hash - create a candidate
344 * for a new record and then redo the search.
345 */
5e33a23b 346 candidate = rxrpc_create_peer(rx, local, srx, hash_key, gfp);
be6e6707
DH
347 if (!candidate) {
348 _leave(" = NULL [nomem]");
349 return NULL;
350 }
17926a79 351
2baec2c3 352 spin_lock_bh(&rxnet->peer_hash_lock);
17926a79 353
be6e6707
DH
354 /* Need to check that we aren't racing with someone else */
355 peer = __rxrpc_lookup_peer_rcu(local, srx, hash_key);
356 if (peer && !rxrpc_get_peer_maybe(peer))
357 peer = NULL;
ace45bec 358 if (!peer) {
2baec2c3 359 hash_add_rcu(rxnet->peer_hash,
be6e6707 360 &candidate->hash_link, hash_key);
330bdcfa
DH
361 list_add_tail(&candidate->keepalive_link,
362 &rxnet->peer_keepalive_new);
ace45bec 363 }
17926a79 364
2baec2c3 365 spin_unlock_bh(&rxnet->peer_hash_lock);
17926a79 366
be6e6707
DH
367 if (peer)
368 kfree(candidate);
369 else
370 peer = candidate;
371 }
17926a79 372
75b54cb5 373 _net("PEER %d {%pISp}", peer->debug_id, &peer->srx.transport);
17926a79 374
be6e6707 375 _leave(" = %p {u=%d}", peer, atomic_read(&peer->usage));
17926a79 376 return peer;
17926a79
DH
377}
378
379/*
1159d4b4 380 * Get a ref on a peer record.
17926a79 381 */
1159d4b4
DH
382struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *peer)
383{
384 const void *here = __builtin_return_address(0);
385 int n;
386
387 n = atomic_inc_return(&peer->usage);
55f6c98e 388 trace_rxrpc_peer(peer->debug_id, rxrpc_peer_got, n, here);
1159d4b4
DH
389 return peer;
390}
391
392/*
393 * Get a ref on a peer record unless its usage has already reached 0.
394 */
395struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *peer)
396{
397 const void *here = __builtin_return_address(0);
398
399 if (peer) {
bfc18e38 400 int n = atomic_fetch_add_unless(&peer->usage, 1, 0);
1159d4b4 401 if (n > 0)
55f6c98e 402 trace_rxrpc_peer(peer->debug_id, rxrpc_peer_got, n + 1, here);
1159d4b4
DH
403 else
404 peer = NULL;
405 }
406 return peer;
407}
408
1159d4b4
DH
409/*
410 * Discard a peer record.
411 */
412static void __rxrpc_put_peer(struct rxrpc_peer *peer)
17926a79 413{
2baec2c3
DH
414 struct rxrpc_net *rxnet = peer->local->rxnet;
415
f66d7490 416 ASSERT(hlist_empty(&peer->error_targets));
17926a79 417
2baec2c3 418 spin_lock_bh(&rxnet->peer_hash_lock);
be6e6707 419 hash_del_rcu(&peer->hash_link);
330bdcfa 420 list_del_init(&peer->keepalive_link);
2baec2c3 421 spin_unlock_bh(&rxnet->peer_hash_lock);
17926a79 422
9ebeddef 423 rxrpc_put_local(peer->local);
be6e6707 424 kfree_rcu(peer, rcu);
17926a79 425}
8324f0bc 426
1159d4b4
DH
427/*
428 * Drop a ref on a peer record.
429 */
430void rxrpc_put_peer(struct rxrpc_peer *peer)
431{
432 const void *here = __builtin_return_address(0);
55f6c98e 433 unsigned int debug_id;
1159d4b4
DH
434 int n;
435
436 if (peer) {
55f6c98e 437 debug_id = peer->debug_id;
1159d4b4 438 n = atomic_dec_return(&peer->usage);
55f6c98e 439 trace_rxrpc_peer(debug_id, rxrpc_peer_put, n, here);
1159d4b4
DH
440 if (n == 0)
441 __rxrpc_put_peer(peer);
442 }
443}
444
60034d3d
DH
445/*
446 * Drop a ref on a peer record where the caller already holds the
447 * peer_hash_lock.
448 */
449void rxrpc_put_peer_locked(struct rxrpc_peer *peer)
450{
451 const void *here = __builtin_return_address(0);
55f6c98e 452 unsigned int debug_id = peer->debug_id;
60034d3d
DH
453 int n;
454
455 n = atomic_dec_return(&peer->usage);
55f6c98e 456 trace_rxrpc_peer(debug_id, rxrpc_peer_put, n, here);
60034d3d
DH
457 if (n == 0) {
458 hash_del_rcu(&peer->hash_link);
459 list_del_init(&peer->keepalive_link);
9ebeddef 460 rxrpc_put_local(peer->local);
60034d3d
DH
461 kfree_rcu(peer, rcu);
462 }
463}
464
17226f12
DH
465/*
466 * Make sure all peer records have been discarded.
467 */
468void rxrpc_destroy_all_peers(struct rxrpc_net *rxnet)
469{
470 struct rxrpc_peer *peer;
471 int i;
472
473 for (i = 0; i < HASH_SIZE(rxnet->peer_hash); i++) {
474 if (hlist_empty(&rxnet->peer_hash[i]))
475 continue;
476
477 hlist_for_each_entry(peer, &rxnet->peer_hash[i], hash_link) {
478 pr_err("Leaked peer %u {%u} %pISp\n",
479 peer->debug_id,
480 atomic_read(&peer->usage),
481 &peer->srx.transport);
482 }
483 }
484}
485
8324f0bc
DH
486/**
487 * rxrpc_kernel_get_peer - Get the peer address of a call
488 * @sock: The socket on which the call is in progress.
489 * @call: The call to query
490 * @_srx: Where to place the result
491 *
492 * Get the address of the remote peer in a call.
493 */
494void rxrpc_kernel_get_peer(struct socket *sock, struct rxrpc_call *call,
495 struct sockaddr_rxrpc *_srx)
496{
497 *_srx = call->peer->srx;
498}
499EXPORT_SYMBOL(rxrpc_kernel_get_peer);
f4d15fb6
DH
500
501/**
c410bf01 502 * rxrpc_kernel_get_srtt - Get a call's peer smoothed RTT
f4d15fb6
DH
503 * @sock: The socket on which the call is in progress.
504 * @call: The call to query
505 *
c410bf01 506 * Get the call's peer smoothed RTT.
f4d15fb6 507 */
c410bf01 508u32 rxrpc_kernel_get_srtt(struct socket *sock, struct rxrpc_call *call)
f4d15fb6 509{
c410bf01 510 return call->peer->srtt_us >> 3;
f4d15fb6 511}
c410bf01 512EXPORT_SYMBOL(rxrpc_kernel_get_srtt);