Blame view

net/rxrpc/proc.c 8.05 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
17926a793   David Howells   [AF_RXRPC]: Provi...
2
3
4
5
  /* /proc/net/ support for AF_RXRPC
   *
   * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
17926a793   David Howells   [AF_RXRPC]: Provi...
6
7
8
9
10
11
   */
  
  #include <linux/module.h>
  #include <net/sock.h>
  #include <net/af_rxrpc.h>
  #include "ar-internal.h"
bba304db3   David Howells   rxrpc: Turn conne...
12
13
14
  static const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES] = {
  	[RXRPC_CONN_UNUSED]			= "Unused  ",
  	[RXRPC_CONN_CLIENT]			= "Client  ",
00e907127   David Howells   rxrpc: Preallocat...
15
  	[RXRPC_CONN_SERVICE_PREALLOC]		= "SvPrealc",
bba304db3   David Howells   rxrpc: Turn conne...
16
17
18
19
20
  	[RXRPC_CONN_SERVICE_UNSECURED]		= "SvUnsec ",
  	[RXRPC_CONN_SERVICE_CHALLENGING]	= "SvChall ",
  	[RXRPC_CONN_SERVICE]			= "SvSecure",
  	[RXRPC_CONN_REMOTELY_ABORTED]		= "RmtAbort",
  	[RXRPC_CONN_LOCALLY_ABORTED]		= "LocAbort",
17926a793   David Howells   [AF_RXRPC]: Provi...
21
  };
17926a793   David Howells   [AF_RXRPC]: Provi...
22
23
24
25
  /*
   * generate a list of extant and dead calls in /proc/net/rxrpc_calls
   */
  static void *rxrpc_call_seq_start(struct seq_file *seq, loff_t *_pos)
88f2a8257   David Howells   rxrpc: Fix checke...
26
27
  	__acquires(rcu)
  	__acquires(rxnet->call_lock)
17926a793   David Howells   [AF_RXRPC]: Provi...
28
  {
2baec2c3f   David Howells   rxrpc: Support ne...
29
  	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
8d94aa381   David Howells   rxrpc: Calls shou...
30
  	rcu_read_lock();
2baec2c3f   David Howells   rxrpc: Support ne...
31
32
  	read_lock(&rxnet->call_lock);
  	return seq_list_start_head(&rxnet->calls, *_pos);
17926a793   David Howells   [AF_RXRPC]: Provi...
33
34
35
36
  }
  
  static void *rxrpc_call_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
2baec2c3f   David Howells   rxrpc: Support ne...
37
38
39
  	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  
  	return seq_list_next(v, &rxnet->calls, pos);
17926a793   David Howells   [AF_RXRPC]: Provi...
40
41
42
  }
  
  static void rxrpc_call_seq_stop(struct seq_file *seq, void *v)
88f2a8257   David Howells   rxrpc: Fix checke...
43
44
  	__releases(rxnet->call_lock)
  	__releases(rcu)
17926a793   David Howells   [AF_RXRPC]: Provi...
45
  {
2baec2c3f   David Howells   rxrpc: Support ne...
46
47
48
  	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  
  	read_unlock(&rxnet->call_lock);
8d94aa381   David Howells   rxrpc: Calls shou...
49
  	rcu_read_unlock();
17926a793   David Howells   [AF_RXRPC]: Provi...
50
51
52
53
  }
  
  static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
  {
df5d8bf70   David Howells   rxrpc: Make /proc...
54
55
56
  	struct rxrpc_local *local;
  	struct rxrpc_sock *rx;
  	struct rxrpc_peer *peer;
17926a793   David Howells   [AF_RXRPC]: Provi...
57
  	struct rxrpc_call *call;
2baec2c3f   David Howells   rxrpc: Support ne...
58
  	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
770b26de1   Wei Yongjun   rxrpc: Remove set...
59
  	unsigned long timeout = 0;
3e018daf0   David Howells   rxrpc: Show a cal...
60
  	rxrpc_seq_t tx_hard_ack, rx_hard_ack;
75b54cb57   David Howells   rxrpc: Add IPv6 s...
61
  	char lbuff[50], rbuff[50];
17926a793   David Howells   [AF_RXRPC]: Provi...
62

2baec2c3f   David Howells   rxrpc: Support ne...
63
  	if (v == &rxnet->calls) {
17926a793   David Howells   [AF_RXRPC]: Provi...
64
  		seq_puts(seq,
75b54cb57   David Howells   rxrpc: Add IPv6 s...
65
66
  			 "Proto Local                                          "
  			 " Remote                                         "
17926a793   David Howells   [AF_RXRPC]: Provi...
67
  			 " SvID ConnID   CallID   End Use State    Abort   "
6b97bd7a2   David Howells   rxrpc: Show some ...
68
69
  			 " UserID           TxSeq    TW RxSeq    RW RxSerial RxTimo
  ");
17926a793   David Howells   [AF_RXRPC]: Provi...
70
71
72
73
  		return 0;
  	}
  
  	call = list_entry(v, struct rxrpc_call, link);
17926a793   David Howells   [AF_RXRPC]: Provi...
74

8d94aa381   David Howells   rxrpc: Calls shou...
75
  	rx = rcu_dereference(call->socket);
df5d8bf70   David Howells   rxrpc: Make /proc...
76
77
78
  	if (rx) {
  		local = READ_ONCE(rx->local);
  		if (local)
75b54cb57   David Howells   rxrpc: Add IPv6 s...
79
  			sprintf(lbuff, "%pISpc", &local->srx.transport);
df5d8bf70   David Howells   rxrpc: Make /proc...
80
81
82
83
84
  		else
  			strcpy(lbuff, "no_local");
  	} else {
  		strcpy(lbuff, "no_socket");
  	}
17926a793   David Howells   [AF_RXRPC]: Provi...
85

df5d8bf70   David Howells   rxrpc: Make /proc...
86
87
  	peer = call->peer;
  	if (peer)
75b54cb57   David Howells   rxrpc: Add IPv6 s...
88
  		sprintf(rbuff, "%pISpc", &peer->srx.transport);
f4e7da8cd   David Howells   rxrpc: Calls disp...
89
90
  	else
  		strcpy(rbuff, "no_connection");
17926a793   David Howells   [AF_RXRPC]: Provi...
91

887763bbc   David Howells   rxrpc: Display ca...
92
93
  	if (call->state != RXRPC_CALL_SERVER_PREALLOC) {
  		timeout = READ_ONCE(call->expect_rx_by);
887763bbc   David Howells   rxrpc: Display ca...
94
95
  		timeout -= jiffies;
  	}
3e018daf0   David Howells   rxrpc: Show a cal...
96
97
  	tx_hard_ack = READ_ONCE(call->tx_hard_ack);
  	rx_hard_ack = READ_ONCE(call->rx_hard_ack);
17926a793   David Howells   [AF_RXRPC]: Provi...
98
  	seq_printf(seq,
75b54cb57   David Howells   rxrpc: Add IPv6 s...
99
  		   "UDP   %-47.47s %-47.47s %4x %08x %08x %s %3u"
6b97bd7a2   David Howells   rxrpc: Show some ...
100
101
  		   " %-8.8s %08x %lx %08x %02x %08x %02x %08x %06lx
  ",
17926a793   David Howells   [AF_RXRPC]: Provi...
102
103
  		   lbuff,
  		   rbuff,
f4e7da8cd   David Howells   rxrpc: Calls disp...
104
  		   call->service_id,
0d12f8a40   David Howells   rxrpc: Keep the s...
105
106
  		   call->cid,
  		   call->call_id,
dabe5a790   David Howells   rxrpc: Tidy up th...
107
  		   rxrpc_is_service_call(call) ? "Svc" : "Clt",
17926a793   David Howells   [AF_RXRPC]: Provi...
108
109
  		   atomic_read(&call->usage),
  		   rxrpc_call_states[call->state],
f5c17aaeb   David Howells   rxrpc: Calls shou...
110
  		   call->abort_code,
3e018daf0   David Howells   rxrpc: Show a cal...
111
112
  		   call->user_call_ID,
  		   tx_hard_ack, READ_ONCE(call->tx_top) - tx_hard_ack,
887763bbc   David Howells   rxrpc: Display ca...
113
  		   rx_hard_ack, READ_ONCE(call->rx_top) - rx_hard_ack,
6b97bd7a2   David Howells   rxrpc: Show some ...
114
  		   call->rx_serial,
887763bbc   David Howells   rxrpc: Display ca...
115
  		   timeout);
17926a793   David Howells   [AF_RXRPC]: Provi...
116
117
118
  
  	return 0;
  }
c35063722   Christoph Hellwig   proc: introduce p...
119
  const struct seq_operations rxrpc_call_seq_ops = {
17926a793   David Howells   [AF_RXRPC]: Provi...
120
121
122
123
124
  	.start  = rxrpc_call_seq_start,
  	.next   = rxrpc_call_seq_next,
  	.stop   = rxrpc_call_seq_stop,
  	.show   = rxrpc_call_seq_show,
  };
17926a793   David Howells   [AF_RXRPC]: Provi...
125
126
127
128
  /*
   * generate a list of extant virtual connections in /proc/net/rxrpc_conns
   */
  static void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos)
88f2a8257   David Howells   rxrpc: Fix checke...
129
  	__acquires(rxnet->conn_lock)
17926a793   David Howells   [AF_RXRPC]: Provi...
130
  {
2baec2c3f   David Howells   rxrpc: Support ne...
131
132
133
134
  	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  
  	read_lock(&rxnet->conn_lock);
  	return seq_list_start_head(&rxnet->conn_proc_list, *_pos);
17926a793   David Howells   [AF_RXRPC]: Provi...
135
136
137
138
139
  }
  
  static void *rxrpc_connection_seq_next(struct seq_file *seq, void *v,
  				       loff_t *pos)
  {
2baec2c3f   David Howells   rxrpc: Support ne...
140
141
142
  	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  
  	return seq_list_next(v, &rxnet->conn_proc_list, pos);
17926a793   David Howells   [AF_RXRPC]: Provi...
143
144
145
  }
  
  static void rxrpc_connection_seq_stop(struct seq_file *seq, void *v)
88f2a8257   David Howells   rxrpc: Fix checke...
146
  	__releases(rxnet->conn_lock)
17926a793   David Howells   [AF_RXRPC]: Provi...
147
  {
2baec2c3f   David Howells   rxrpc: Support ne...
148
149
150
  	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  
  	read_unlock(&rxnet->conn_lock);
17926a793   David Howells   [AF_RXRPC]: Provi...
151
152
153
154
155
  }
  
  static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
  {
  	struct rxrpc_connection *conn;
2baec2c3f   David Howells   rxrpc: Support ne...
156
  	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
75b54cb57   David Howells   rxrpc: Add IPv6 s...
157
  	char lbuff[50], rbuff[50];
17926a793   David Howells   [AF_RXRPC]: Provi...
158

2baec2c3f   David Howells   rxrpc: Support ne...
159
  	if (v == &rxnet->conn_proc_list) {
17926a793   David Howells   [AF_RXRPC]: Provi...
160
  		seq_puts(seq,
75b54cb57   David Howells   rxrpc: Add IPv6 s...
161
162
  			 "Proto Local                                          "
  			 " Remote                                         "
a1399f8bb   David Howells   rxrpc: Call chann...
163
  			 " SvID ConnID   End Use State    Key     "
17926a793   David Howells   [AF_RXRPC]: Provi...
164
165
166
167
168
  			 " Serial   ISerial
  "
  			 );
  		return 0;
  	}
4d028b2c8   David Howells   rxrpc: Dup the ma...
169
  	conn = list_entry(v, struct rxrpc_connection, proc_link);
00e907127   David Howells   rxrpc: Preallocat...
170
171
172
173
174
  	if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) {
  		strcpy(lbuff, "no_local");
  		strcpy(rbuff, "no_connection");
  		goto print;
  	}
17926a793   David Howells   [AF_RXRPC]: Provi...
175

75b54cb57   David Howells   rxrpc: Add IPv6 s...
176
  	sprintf(lbuff, "%pISpc", &conn->params.local->srx.transport);
17926a793   David Howells   [AF_RXRPC]: Provi...
177

75b54cb57   David Howells   rxrpc: Add IPv6 s...
178
  	sprintf(rbuff, "%pISpc", &conn->params.peer->srx.transport);
00e907127   David Howells   rxrpc: Preallocat...
179
  print:
17926a793   David Howells   [AF_RXRPC]: Provi...
180
  	seq_printf(seq,
75b54cb57   David Howells   rxrpc: Add IPv6 s...
181
  		   "UDP   %-47.47s %-47.47s %4x %08x %s %3u"
6b97bd7a2   David Howells   rxrpc: Show some ...
182
183
  		   " %s %08x %08x %08x %08x %08x %08x %08x
  ",
17926a793   David Howells   [AF_RXRPC]: Provi...
184
185
  		   lbuff,
  		   rbuff,
68d6d1ae5   David Howells   rxrpc: Separate t...
186
  		   conn->service_id,
19ffa01c9   David Howells   rxrpc: Use struct...
187
  		   conn->proto.cid,
19ffa01c9   David Howells   rxrpc: Use struct...
188
  		   rxrpc_conn_is_service(conn) ? "Svc" : "Clt",
17926a793   David Howells   [AF_RXRPC]: Provi...
189
190
  		   atomic_read(&conn->usage),
  		   rxrpc_conn_states[conn->state],
19ffa01c9   David Howells   rxrpc: Use struct...
191
  		   key_serial(conn->params.key),
17926a793   David Howells   [AF_RXRPC]: Provi...
192
  		   atomic_read(&conn->serial),
6b97bd7a2   David Howells   rxrpc: Show some ...
193
194
195
196
197
  		   conn->hi_serial,
  		   conn->channels[0].call_id,
  		   conn->channels[1].call_id,
  		   conn->channels[2].call_id,
  		   conn->channels[3].call_id);
17926a793   David Howells   [AF_RXRPC]: Provi...
198
199
200
  
  	return 0;
  }
c35063722   Christoph Hellwig   proc: introduce p...
201
  const struct seq_operations rxrpc_connection_seq_ops = {
17926a793   David Howells   [AF_RXRPC]: Provi...
202
203
204
205
206
  	.start  = rxrpc_connection_seq_start,
  	.next   = rxrpc_connection_seq_next,
  	.stop   = rxrpc_connection_seq_stop,
  	.show   = rxrpc_connection_seq_show,
  };
bc0e7cf43   David Howells   rxrpc: Add /proc/...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  
  /*
   * generate a list of extant virtual peers in /proc/net/rxrpc/peers
   */
  static int rxrpc_peer_seq_show(struct seq_file *seq, void *v)
  {
  	struct rxrpc_peer *peer;
  	time64_t now;
  	char lbuff[50], rbuff[50];
  
  	if (v == SEQ_START_TOKEN) {
  		seq_puts(seq,
  			 "Proto Local                                          "
  			 " Remote                                         "
  			 " Use CW  MTU   LastUse          RTT Rc
  "
  			 );
  		return 0;
  	}
  
  	peer = list_entry(v, struct rxrpc_peer, hash_link);
  
  	sprintf(lbuff, "%pISpc", &peer->local->srx.transport);
  
  	sprintf(rbuff, "%pISpc", &peer->srx.transport);
  
  	now = ktime_get_seconds();
  	seq_printf(seq,
  		   "UDP   %-47.47s %-47.47s %3u"
  		   " %3u %5u %6llus %12llu %2u
  ",
  		   lbuff,
  		   rbuff,
  		   atomic_read(&peer->usage),
  		   peer->cong_cwnd,
  		   peer->mtu,
  		   now - peer->last_tx_at,
  		   peer->rtt,
  		   peer->rtt_cursor);
  
  	return 0;
  }
  
  static void *rxrpc_peer_seq_start(struct seq_file *seq, loff_t *_pos)
  	__acquires(rcu)
  {
  	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  	unsigned int bucket, n;
  	unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash);
  	void *p;
  
  	rcu_read_lock();
  
  	if (*_pos >= UINT_MAX)
  		return NULL;
  
  	n = *_pos & ((1U << shift) - 1);
  	bucket = *_pos >> shift;
  	for (;;) {
  		if (bucket >= HASH_SIZE(rxnet->peer_hash)) {
  			*_pos = UINT_MAX;
  			return NULL;
  		}
  		if (n == 0) {
  			if (bucket == 0)
  				return SEQ_START_TOKEN;
  			*_pos += 1;
  			n++;
  		}
  
  		p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1);
  		if (p)
  			return p;
  		bucket++;
  		n = 1;
  		*_pos = (bucket << shift) | n;
  	}
  }
  
  static void *rxrpc_peer_seq_next(struct seq_file *seq, void *v, loff_t *_pos)
  {
  	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  	unsigned int bucket, n;
  	unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash);
  	void *p;
  
  	if (*_pos >= UINT_MAX)
  		return NULL;
  
  	bucket = *_pos >> shift;
  
  	p = seq_hlist_next_rcu(v, &rxnet->peer_hash[bucket], _pos);
  	if (p)
  		return p;
  
  	for (;;) {
  		bucket++;
  		n = 1;
  		*_pos = (bucket << shift) | n;
  
  		if (bucket >= HASH_SIZE(rxnet->peer_hash)) {
  			*_pos = UINT_MAX;
  			return NULL;
  		}
  		if (n == 0) {
  			*_pos += 1;
  			n++;
  		}
  
  		p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1);
  		if (p)
  			return p;
  	}
  }
  
  static void rxrpc_peer_seq_stop(struct seq_file *seq, void *v)
  	__releases(rcu)
  {
  	rcu_read_unlock();
  }
  
  
  const struct seq_operations rxrpc_peer_seq_ops = {
  	.start  = rxrpc_peer_seq_start,
  	.next   = rxrpc_peer_seq_next,
  	.stop   = rxrpc_peer_seq_stop,
  	.show   = rxrpc_peer_seq_show,
  };