Merge tag 'mfd-next-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
[linux-2.6-microblaze.git] / net / rxrpc / proc.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* /proc/net/ support for AF_RXRPC
3  *
4  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7
8 #include <linux/module.h>
9 #include <net/sock.h>
10 #include <net/af_rxrpc.h>
11 #include "ar-internal.h"
12
13 static const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES] = {
14         [RXRPC_CONN_UNUSED]                     = "Unused  ",
15         [RXRPC_CONN_CLIENT]                     = "Client  ",
16         [RXRPC_CONN_SERVICE_PREALLOC]           = "SvPrealc",
17         [RXRPC_CONN_SERVICE_UNSECURED]          = "SvUnsec ",
18         [RXRPC_CONN_SERVICE_CHALLENGING]        = "SvChall ",
19         [RXRPC_CONN_SERVICE]                    = "SvSecure",
20         [RXRPC_CONN_REMOTELY_ABORTED]           = "RmtAbort",
21         [RXRPC_CONN_LOCALLY_ABORTED]            = "LocAbort",
22 };
23
24 /*
25  * generate a list of extant and dead calls in /proc/net/rxrpc_calls
26  */
27 static void *rxrpc_call_seq_start(struct seq_file *seq, loff_t *_pos)
28         __acquires(rcu)
29 {
30         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
31
32         rcu_read_lock();
33         return seq_list_start_head_rcu(&rxnet->calls, *_pos);
34 }
35
36 static void *rxrpc_call_seq_next(struct seq_file *seq, void *v, loff_t *pos)
37 {
38         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
39
40         return seq_list_next_rcu(v, &rxnet->calls, pos);
41 }
42
43 static void rxrpc_call_seq_stop(struct seq_file *seq, void *v)
44         __releases(rcu)
45 {
46         rcu_read_unlock();
47 }
48
49 static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
50 {
51         struct rxrpc_local *local;
52         struct rxrpc_sock *rx;
53         struct rxrpc_peer *peer;
54         struct rxrpc_call *call;
55         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
56         unsigned long timeout = 0;
57         rxrpc_seq_t tx_hard_ack, rx_hard_ack;
58         char lbuff[50], rbuff[50];
59
60         if (v == &rxnet->calls) {
61                 seq_puts(seq,
62                          "Proto Local                                          "
63                          " Remote                                         "
64                          " SvID ConnID   CallID   End Use State    Abort   "
65                          " DebugId  TxSeq    TW RxSeq    RW RxSerial RxTimo\n");
66                 return 0;
67         }
68
69         call = list_entry(v, struct rxrpc_call, link);
70
71         rx = rcu_dereference(call->socket);
72         if (rx) {
73                 local = READ_ONCE(rx->local);
74                 if (local)
75                         sprintf(lbuff, "%pISpc", &local->srx.transport);
76                 else
77                         strcpy(lbuff, "no_local");
78         } else {
79                 strcpy(lbuff, "no_socket");
80         }
81
82         peer = call->peer;
83         if (peer)
84                 sprintf(rbuff, "%pISpc", &peer->srx.transport);
85         else
86                 strcpy(rbuff, "no_connection");
87
88         if (call->state != RXRPC_CALL_SERVER_PREALLOC) {
89                 timeout = READ_ONCE(call->expect_rx_by);
90                 timeout -= jiffies;
91         }
92
93         tx_hard_ack = READ_ONCE(call->tx_hard_ack);
94         rx_hard_ack = READ_ONCE(call->rx_hard_ack);
95         seq_printf(seq,
96                    "UDP   %-47.47s %-47.47s %4x %08x %08x %s %3u"
97                    " %-8.8s %08x %08x %08x %02x %08x %02x %08x %06lx\n",
98                    lbuff,
99                    rbuff,
100                    call->service_id,
101                    call->cid,
102                    call->call_id,
103                    rxrpc_is_service_call(call) ? "Svc" : "Clt",
104                    refcount_read(&call->ref),
105                    rxrpc_call_states[call->state],
106                    call->abort_code,
107                    call->debug_id,
108                    tx_hard_ack, READ_ONCE(call->tx_top) - tx_hard_ack,
109                    rx_hard_ack, READ_ONCE(call->rx_top) - rx_hard_ack,
110                    call->rx_serial,
111                    timeout);
112
113         return 0;
114 }
115
116 const struct seq_operations rxrpc_call_seq_ops = {
117         .start  = rxrpc_call_seq_start,
118         .next   = rxrpc_call_seq_next,
119         .stop   = rxrpc_call_seq_stop,
120         .show   = rxrpc_call_seq_show,
121 };
122
123 /*
124  * generate a list of extant virtual connections in /proc/net/rxrpc_conns
125  */
126 static void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos)
127         __acquires(rxnet->conn_lock)
128 {
129         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
130
131         read_lock(&rxnet->conn_lock);
132         return seq_list_start_head(&rxnet->conn_proc_list, *_pos);
133 }
134
135 static void *rxrpc_connection_seq_next(struct seq_file *seq, void *v,
136                                        loff_t *pos)
137 {
138         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
139
140         return seq_list_next(v, &rxnet->conn_proc_list, pos);
141 }
142
143 static void rxrpc_connection_seq_stop(struct seq_file *seq, void *v)
144         __releases(rxnet->conn_lock)
145 {
146         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
147
148         read_unlock(&rxnet->conn_lock);
149 }
150
151 static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
152 {
153         struct rxrpc_connection *conn;
154         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
155         char lbuff[50], rbuff[50];
156
157         if (v == &rxnet->conn_proc_list) {
158                 seq_puts(seq,
159                          "Proto Local                                          "
160                          " Remote                                         "
161                          " SvID ConnID   End Use State    Key     "
162                          " Serial   ISerial  CallId0  CallId1  CallId2  CallId3\n"
163                          );
164                 return 0;
165         }
166
167         conn = list_entry(v, struct rxrpc_connection, proc_link);
168         if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) {
169                 strcpy(lbuff, "no_local");
170                 strcpy(rbuff, "no_connection");
171                 goto print;
172         }
173
174         sprintf(lbuff, "%pISpc", &conn->params.local->srx.transport);
175
176         sprintf(rbuff, "%pISpc", &conn->params.peer->srx.transport);
177 print:
178         seq_printf(seq,
179                    "UDP   %-47.47s %-47.47s %4x %08x %s %3u"
180                    " %s %08x %08x %08x %08x %08x %08x %08x\n",
181                    lbuff,
182                    rbuff,
183                    conn->service_id,
184                    conn->proto.cid,
185                    rxrpc_conn_is_service(conn) ? "Svc" : "Clt",
186                    refcount_read(&conn->ref),
187                    rxrpc_conn_states[conn->state],
188                    key_serial(conn->params.key),
189                    atomic_read(&conn->serial),
190                    conn->hi_serial,
191                    conn->channels[0].call_id,
192                    conn->channels[1].call_id,
193                    conn->channels[2].call_id,
194                    conn->channels[3].call_id);
195
196         return 0;
197 }
198
199 const struct seq_operations rxrpc_connection_seq_ops = {
200         .start  = rxrpc_connection_seq_start,
201         .next   = rxrpc_connection_seq_next,
202         .stop   = rxrpc_connection_seq_stop,
203         .show   = rxrpc_connection_seq_show,
204 };
205
206 /*
207  * generate a list of extant virtual peers in /proc/net/rxrpc/peers
208  */
209 static int rxrpc_peer_seq_show(struct seq_file *seq, void *v)
210 {
211         struct rxrpc_peer *peer;
212         time64_t now;
213         char lbuff[50], rbuff[50];
214
215         if (v == SEQ_START_TOKEN) {
216                 seq_puts(seq,
217                          "Proto Local                                          "
218                          " Remote                                         "
219                          " Use  CW   MTU LastUse      RTT      RTO\n"
220                          );
221                 return 0;
222         }
223
224         peer = list_entry(v, struct rxrpc_peer, hash_link);
225
226         sprintf(lbuff, "%pISpc", &peer->local->srx.transport);
227
228         sprintf(rbuff, "%pISpc", &peer->srx.transport);
229
230         now = ktime_get_seconds();
231         seq_printf(seq,
232                    "UDP   %-47.47s %-47.47s %3u"
233                    " %3u %5u %6llus %8u %8u\n",
234                    lbuff,
235                    rbuff,
236                    refcount_read(&peer->ref),
237                    peer->cong_cwnd,
238                    peer->mtu,
239                    now - peer->last_tx_at,
240                    peer->srtt_us >> 3,
241                    jiffies_to_usecs(peer->rto_j));
242
243         return 0;
244 }
245
246 static void *rxrpc_peer_seq_start(struct seq_file *seq, loff_t *_pos)
247         __acquires(rcu)
248 {
249         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
250         unsigned int bucket, n;
251         unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash);
252         void *p;
253
254         rcu_read_lock();
255
256         if (*_pos >= UINT_MAX)
257                 return NULL;
258
259         n = *_pos & ((1U << shift) - 1);
260         bucket = *_pos >> shift;
261         for (;;) {
262                 if (bucket >= HASH_SIZE(rxnet->peer_hash)) {
263                         *_pos = UINT_MAX;
264                         return NULL;
265                 }
266                 if (n == 0) {
267                         if (bucket == 0)
268                                 return SEQ_START_TOKEN;
269                         *_pos += 1;
270                         n++;
271                 }
272
273                 p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1);
274                 if (p)
275                         return p;
276                 bucket++;
277                 n = 1;
278                 *_pos = (bucket << shift) | n;
279         }
280 }
281
282 static void *rxrpc_peer_seq_next(struct seq_file *seq, void *v, loff_t *_pos)
283 {
284         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
285         unsigned int bucket, n;
286         unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash);
287         void *p;
288
289         if (*_pos >= UINT_MAX)
290                 return NULL;
291
292         bucket = *_pos >> shift;
293
294         p = seq_hlist_next_rcu(v, &rxnet->peer_hash[bucket], _pos);
295         if (p)
296                 return p;
297
298         for (;;) {
299                 bucket++;
300                 n = 1;
301                 *_pos = (bucket << shift) | n;
302
303                 if (bucket >= HASH_SIZE(rxnet->peer_hash)) {
304                         *_pos = UINT_MAX;
305                         return NULL;
306                 }
307                 if (n == 0) {
308                         *_pos += 1;
309                         n++;
310                 }
311
312                 p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1);
313                 if (p)
314                         return p;
315         }
316 }
317
318 static void rxrpc_peer_seq_stop(struct seq_file *seq, void *v)
319         __releases(rcu)
320 {
321         rcu_read_unlock();
322 }
323
324
325 const struct seq_operations rxrpc_peer_seq_ops = {
326         .start  = rxrpc_peer_seq_start,
327         .next   = rxrpc_peer_seq_next,
328         .stop   = rxrpc_peer_seq_stop,
329         .show   = rxrpc_peer_seq_show,
330 };
331
332 /*
333  * Generate a list of extant virtual local endpoints in /proc/net/rxrpc/locals
334  */
335 static int rxrpc_local_seq_show(struct seq_file *seq, void *v)
336 {
337         struct rxrpc_local *local;
338         char lbuff[50];
339
340         if (v == SEQ_START_TOKEN) {
341                 seq_puts(seq,
342                          "Proto Local                                          "
343                          " Use Act\n");
344                 return 0;
345         }
346
347         local = hlist_entry(v, struct rxrpc_local, link);
348
349         sprintf(lbuff, "%pISpc", &local->srx.transport);
350
351         seq_printf(seq,
352                    "UDP   %-47.47s %3u %3u\n",
353                    lbuff,
354                    refcount_read(&local->ref),
355                    atomic_read(&local->active_users));
356
357         return 0;
358 }
359
360 static void *rxrpc_local_seq_start(struct seq_file *seq, loff_t *_pos)
361         __acquires(rcu)
362 {
363         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
364         unsigned int n;
365
366         rcu_read_lock();
367
368         if (*_pos >= UINT_MAX)
369                 return NULL;
370
371         n = *_pos;
372         if (n == 0)
373                 return SEQ_START_TOKEN;
374
375         return seq_hlist_start_rcu(&rxnet->local_endpoints, n - 1);
376 }
377
378 static void *rxrpc_local_seq_next(struct seq_file *seq, void *v, loff_t *_pos)
379 {
380         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
381
382         if (*_pos >= UINT_MAX)
383                 return NULL;
384
385         return seq_hlist_next_rcu(v, &rxnet->local_endpoints, _pos);
386 }
387
388 static void rxrpc_local_seq_stop(struct seq_file *seq, void *v)
389         __releases(rcu)
390 {
391         rcu_read_unlock();
392 }
393
394 const struct seq_operations rxrpc_local_seq_ops = {
395         .start  = rxrpc_local_seq_start,
396         .next   = rxrpc_local_seq_next,
397         .stop   = rxrpc_local_seq_stop,
398         .show   = rxrpc_local_seq_show,
399 };