root/net/rxrpc/proc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rxrpc_call_seq_start
  2. rxrpc_call_seq_next
  3. rxrpc_call_seq_stop
  4. rxrpc_call_seq_show
  5. rxrpc_connection_seq_start
  6. rxrpc_connection_seq_next
  7. rxrpc_connection_seq_stop
  8. rxrpc_connection_seq_show
  9. rxrpc_peer_seq_show
  10. rxrpc_peer_seq_start
  11. rxrpc_peer_seq_next
  12. rxrpc_peer_seq_stop

   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         __acquires(rxnet->call_lock)
  30 {
  31         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  32 
  33         rcu_read_lock();
  34         read_lock(&rxnet->call_lock);
  35         return seq_list_start_head(&rxnet->calls, *_pos);
  36 }
  37 
  38 static void *rxrpc_call_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  39 {
  40         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  41 
  42         return seq_list_next(v, &rxnet->calls, pos);
  43 }
  44 
  45 static void rxrpc_call_seq_stop(struct seq_file *seq, void *v)
  46         __releases(rxnet->call_lock)
  47         __releases(rcu)
  48 {
  49         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  50 
  51         read_unlock(&rxnet->call_lock);
  52         rcu_read_unlock();
  53 }
  54 
  55 static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
  56 {
  57         struct rxrpc_local *local;
  58         struct rxrpc_sock *rx;
  59         struct rxrpc_peer *peer;
  60         struct rxrpc_call *call;
  61         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
  62         unsigned long timeout = 0;
  63         rxrpc_seq_t tx_hard_ack, rx_hard_ack;
  64         char lbuff[50], rbuff[50];
  65 
  66         if (v == &rxnet->calls) {
  67                 seq_puts(seq,
  68                          "Proto Local                                          "
  69                          " Remote                                         "
  70                          " SvID ConnID   CallID   End Use State    Abort   "
  71                          " UserID           TxSeq    TW RxSeq    RW RxSerial RxTimo\n");
  72                 return 0;
  73         }
  74 
  75         call = list_entry(v, struct rxrpc_call, link);
  76 
  77         rx = rcu_dereference(call->socket);
  78         if (rx) {
  79                 local = READ_ONCE(rx->local);
  80                 if (local)
  81                         sprintf(lbuff, "%pISpc", &local->srx.transport);
  82                 else
  83                         strcpy(lbuff, "no_local");
  84         } else {
  85                 strcpy(lbuff, "no_socket");
  86         }
  87 
  88         peer = call->peer;
  89         if (peer)
  90                 sprintf(rbuff, "%pISpc", &peer->srx.transport);
  91         else
  92                 strcpy(rbuff, "no_connection");
  93 
  94         if (call->state != RXRPC_CALL_SERVER_PREALLOC) {
  95                 timeout = READ_ONCE(call->expect_rx_by);
  96                 timeout -= jiffies;
  97         }
  98 
  99         tx_hard_ack = READ_ONCE(call->tx_hard_ack);
 100         rx_hard_ack = READ_ONCE(call->rx_hard_ack);
 101         seq_printf(seq,
 102                    "UDP   %-47.47s %-47.47s %4x %08x %08x %s %3u"
 103                    " %-8.8s %08x %lx %08x %02x %08x %02x %08x %06lx\n",
 104                    lbuff,
 105                    rbuff,
 106                    call->service_id,
 107                    call->cid,
 108                    call->call_id,
 109                    rxrpc_is_service_call(call) ? "Svc" : "Clt",
 110                    atomic_read(&call->usage),
 111                    rxrpc_call_states[call->state],
 112                    call->abort_code,
 113                    call->user_call_ID,
 114                    tx_hard_ack, READ_ONCE(call->tx_top) - tx_hard_ack,
 115                    rx_hard_ack, READ_ONCE(call->rx_top) - rx_hard_ack,
 116                    call->rx_serial,
 117                    timeout);
 118 
 119         return 0;
 120 }
 121 
 122 const struct seq_operations rxrpc_call_seq_ops = {
 123         .start  = rxrpc_call_seq_start,
 124         .next   = rxrpc_call_seq_next,
 125         .stop   = rxrpc_call_seq_stop,
 126         .show   = rxrpc_call_seq_show,
 127 };
 128 
 129 /*
 130  * generate a list of extant virtual connections in /proc/net/rxrpc_conns
 131  */
 132 static void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos)
 133         __acquires(rxnet->conn_lock)
 134 {
 135         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 136 
 137         read_lock(&rxnet->conn_lock);
 138         return seq_list_start_head(&rxnet->conn_proc_list, *_pos);
 139 }
 140 
 141 static void *rxrpc_connection_seq_next(struct seq_file *seq, void *v,
 142                                        loff_t *pos)
 143 {
 144         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 145 
 146         return seq_list_next(v, &rxnet->conn_proc_list, pos);
 147 }
 148 
 149 static void rxrpc_connection_seq_stop(struct seq_file *seq, void *v)
 150         __releases(rxnet->conn_lock)
 151 {
 152         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 153 
 154         read_unlock(&rxnet->conn_lock);
 155 }
 156 
 157 static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
 158 {
 159         struct rxrpc_connection *conn;
 160         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 161         char lbuff[50], rbuff[50];
 162 
 163         if (v == &rxnet->conn_proc_list) {
 164                 seq_puts(seq,
 165                          "Proto Local                                          "
 166                          " Remote                                         "
 167                          " SvID ConnID   End Use State    Key     "
 168                          " Serial   ISerial\n"
 169                          );
 170                 return 0;
 171         }
 172 
 173         conn = list_entry(v, struct rxrpc_connection, proc_link);
 174         if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) {
 175                 strcpy(lbuff, "no_local");
 176                 strcpy(rbuff, "no_connection");
 177                 goto print;
 178         }
 179 
 180         sprintf(lbuff, "%pISpc", &conn->params.local->srx.transport);
 181 
 182         sprintf(rbuff, "%pISpc", &conn->params.peer->srx.transport);
 183 print:
 184         seq_printf(seq,
 185                    "UDP   %-47.47s %-47.47s %4x %08x %s %3u"
 186                    " %s %08x %08x %08x %08x %08x %08x %08x\n",
 187                    lbuff,
 188                    rbuff,
 189                    conn->service_id,
 190                    conn->proto.cid,
 191                    rxrpc_conn_is_service(conn) ? "Svc" : "Clt",
 192                    atomic_read(&conn->usage),
 193                    rxrpc_conn_states[conn->state],
 194                    key_serial(conn->params.key),
 195                    atomic_read(&conn->serial),
 196                    conn->hi_serial,
 197                    conn->channels[0].call_id,
 198                    conn->channels[1].call_id,
 199                    conn->channels[2].call_id,
 200                    conn->channels[3].call_id);
 201 
 202         return 0;
 203 }
 204 
 205 const struct seq_operations rxrpc_connection_seq_ops = {
 206         .start  = rxrpc_connection_seq_start,
 207         .next   = rxrpc_connection_seq_next,
 208         .stop   = rxrpc_connection_seq_stop,
 209         .show   = rxrpc_connection_seq_show,
 210 };
 211 
 212 /*
 213  * generate a list of extant virtual peers in /proc/net/rxrpc/peers
 214  */
 215 static int rxrpc_peer_seq_show(struct seq_file *seq, void *v)
 216 {
 217         struct rxrpc_peer *peer;
 218         time64_t now;
 219         char lbuff[50], rbuff[50];
 220 
 221         if (v == SEQ_START_TOKEN) {
 222                 seq_puts(seq,
 223                          "Proto Local                                          "
 224                          " Remote                                         "
 225                          " Use  CW   MTU LastUse      RTT      RTO\n"
 226                          );
 227                 return 0;
 228         }
 229 
 230         peer = list_entry(v, struct rxrpc_peer, hash_link);
 231 
 232         sprintf(lbuff, "%pISpc", &peer->local->srx.transport);
 233 
 234         sprintf(rbuff, "%pISpc", &peer->srx.transport);
 235 
 236         now = ktime_get_seconds();
 237         seq_printf(seq,
 238                    "UDP   %-47.47s %-47.47s %3u"
 239                    " %3u %5u %6llus %8u %8u\n",
 240                    lbuff,
 241                    rbuff,
 242                    atomic_read(&peer->usage),
 243                    peer->cong_cwnd,
 244                    peer->mtu,
 245                    now - peer->last_tx_at,
 246                    peer->srtt_us >> 3,
 247                    jiffies_to_usecs(peer->rto_j));
 248 
 249         return 0;
 250 }
 251 
 252 static void *rxrpc_peer_seq_start(struct seq_file *seq, loff_t *_pos)
 253         __acquires(rcu)
 254 {
 255         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 256         unsigned int bucket, n;
 257         unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash);
 258         void *p;
 259 
 260         rcu_read_lock();
 261 
 262         if (*_pos >= UINT_MAX)
 263                 return NULL;
 264 
 265         n = *_pos & ((1U << shift) - 1);
 266         bucket = *_pos >> shift;
 267         for (;;) {
 268                 if (bucket >= HASH_SIZE(rxnet->peer_hash)) {
 269                         *_pos = UINT_MAX;
 270                         return NULL;
 271                 }
 272                 if (n == 0) {
 273                         if (bucket == 0)
 274                                 return SEQ_START_TOKEN;
 275                         *_pos += 1;
 276                         n++;
 277                 }
 278 
 279                 p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1);
 280                 if (p)
 281                         return p;
 282                 bucket++;
 283                 n = 1;
 284                 *_pos = (bucket << shift) | n;
 285         }
 286 }
 287 
 288 static void *rxrpc_peer_seq_next(struct seq_file *seq, void *v, loff_t *_pos)
 289 {
 290         struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
 291         unsigned int bucket, n;
 292         unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash);
 293         void *p;
 294 
 295         if (*_pos >= UINT_MAX)
 296                 return NULL;
 297 
 298         bucket = *_pos >> shift;
 299 
 300         p = seq_hlist_next_rcu(v, &rxnet->peer_hash[bucket], _pos);
 301         if (p)
 302                 return p;
 303 
 304         for (;;) {
 305                 bucket++;
 306                 n = 1;
 307                 *_pos = (bucket << shift) | n;
 308 
 309                 if (bucket >= HASH_SIZE(rxnet->peer_hash)) {
 310                         *_pos = UINT_MAX;
 311                         return NULL;
 312                 }
 313                 if (n == 0) {
 314                         *_pos += 1;
 315                         n++;
 316                 }
 317 
 318                 p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1);
 319                 if (p)
 320                         return p;
 321         }
 322 }
 323 
 324 static void rxrpc_peer_seq_stop(struct seq_file *seq, void *v)
 325         __releases(rcu)
 326 {
 327         rcu_read_unlock();
 328 }
 329 
 330 
 331 const struct seq_operations rxrpc_peer_seq_ops = {
 332         .start  = rxrpc_peer_seq_start,
 333         .next   = rxrpc_peer_seq_next,
 334         .stop   = rxrpc_peer_seq_stop,
 335         .show   = rxrpc_peer_seq_show,
 336 };

/* [<][>][^][v][top][bottom][index][help] */