Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* /proc/net/ support for AF_RXRPC
0003  *
0004  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
0005  * Written by David Howells (dhowells@redhat.com)
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <net/sock.h>
0010 #include <net/af_rxrpc.h>
0011 #include "ar-internal.h"
0012 
0013 static const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES] = {
0014     [RXRPC_CONN_UNUSED]         = "Unused  ",
0015     [RXRPC_CONN_CLIENT]         = "Client  ",
0016     [RXRPC_CONN_SERVICE_PREALLOC]       = "SvPrealc",
0017     [RXRPC_CONN_SERVICE_UNSECURED]      = "SvUnsec ",
0018     [RXRPC_CONN_SERVICE_CHALLENGING]    = "SvChall ",
0019     [RXRPC_CONN_SERVICE]            = "SvSecure",
0020     [RXRPC_CONN_REMOTELY_ABORTED]       = "RmtAbort",
0021     [RXRPC_CONN_LOCALLY_ABORTED]        = "LocAbort",
0022 };
0023 
0024 /*
0025  * generate a list of extant and dead calls in /proc/net/rxrpc_calls
0026  */
0027 static void *rxrpc_call_seq_start(struct seq_file *seq, loff_t *_pos)
0028     __acquires(rcu)
0029 {
0030     struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
0031 
0032     rcu_read_lock();
0033     return seq_list_start_head_rcu(&rxnet->calls, *_pos);
0034 }
0035 
0036 static void *rxrpc_call_seq_next(struct seq_file *seq, void *v, loff_t *pos)
0037 {
0038     struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
0039 
0040     return seq_list_next_rcu(v, &rxnet->calls, pos);
0041 }
0042 
0043 static void rxrpc_call_seq_stop(struct seq_file *seq, void *v)
0044     __releases(rcu)
0045 {
0046     rcu_read_unlock();
0047 }
0048 
0049 static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
0050 {
0051     struct rxrpc_local *local;
0052     struct rxrpc_sock *rx;
0053     struct rxrpc_peer *peer;
0054     struct rxrpc_call *call;
0055     struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
0056     unsigned long timeout = 0;
0057     rxrpc_seq_t tx_hard_ack, rx_hard_ack;
0058     char lbuff[50], rbuff[50];
0059 
0060     if (v == &rxnet->calls) {
0061         seq_puts(seq,
0062              "Proto Local                                          "
0063              " Remote                                         "
0064              " SvID ConnID   CallID   End Use State    Abort   "
0065              " DebugId  TxSeq    TW RxSeq    RW RxSerial RxTimo\n");
0066         return 0;
0067     }
0068 
0069     call = list_entry(v, struct rxrpc_call, link);
0070 
0071     rx = rcu_dereference(call->socket);
0072     if (rx) {
0073         local = READ_ONCE(rx->local);
0074         if (local)
0075             sprintf(lbuff, "%pISpc", &local->srx.transport);
0076         else
0077             strcpy(lbuff, "no_local");
0078     } else {
0079         strcpy(lbuff, "no_socket");
0080     }
0081 
0082     peer = call->peer;
0083     if (peer)
0084         sprintf(rbuff, "%pISpc", &peer->srx.transport);
0085     else
0086         strcpy(rbuff, "no_connection");
0087 
0088     if (call->state != RXRPC_CALL_SERVER_PREALLOC) {
0089         timeout = READ_ONCE(call->expect_rx_by);
0090         timeout -= jiffies;
0091     }
0092 
0093     tx_hard_ack = READ_ONCE(call->tx_hard_ack);
0094     rx_hard_ack = READ_ONCE(call->rx_hard_ack);
0095     seq_printf(seq,
0096            "UDP   %-47.47s %-47.47s %4x %08x %08x %s %3u"
0097            " %-8.8s %08x %08x %08x %02x %08x %02x %08x %06lx\n",
0098            lbuff,
0099            rbuff,
0100            call->service_id,
0101            call->cid,
0102            call->call_id,
0103            rxrpc_is_service_call(call) ? "Svc" : "Clt",
0104            refcount_read(&call->ref),
0105            rxrpc_call_states[call->state],
0106            call->abort_code,
0107            call->debug_id,
0108            tx_hard_ack, READ_ONCE(call->tx_top) - tx_hard_ack,
0109            rx_hard_ack, READ_ONCE(call->rx_top) - rx_hard_ack,
0110            call->rx_serial,
0111            timeout);
0112 
0113     return 0;
0114 }
0115 
0116 const struct seq_operations rxrpc_call_seq_ops = {
0117     .start  = rxrpc_call_seq_start,
0118     .next   = rxrpc_call_seq_next,
0119     .stop   = rxrpc_call_seq_stop,
0120     .show   = rxrpc_call_seq_show,
0121 };
0122 
0123 /*
0124  * generate a list of extant virtual connections in /proc/net/rxrpc_conns
0125  */
0126 static void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos)
0127     __acquires(rxnet->conn_lock)
0128 {
0129     struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
0130 
0131     read_lock(&rxnet->conn_lock);
0132     return seq_list_start_head(&rxnet->conn_proc_list, *_pos);
0133 }
0134 
0135 static void *rxrpc_connection_seq_next(struct seq_file *seq, void *v,
0136                        loff_t *pos)
0137 {
0138     struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
0139 
0140     return seq_list_next(v, &rxnet->conn_proc_list, pos);
0141 }
0142 
0143 static void rxrpc_connection_seq_stop(struct seq_file *seq, void *v)
0144     __releases(rxnet->conn_lock)
0145 {
0146     struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
0147 
0148     read_unlock(&rxnet->conn_lock);
0149 }
0150 
0151 static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
0152 {
0153     struct rxrpc_connection *conn;
0154     struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
0155     char lbuff[50], rbuff[50];
0156 
0157     if (v == &rxnet->conn_proc_list) {
0158         seq_puts(seq,
0159              "Proto Local                                          "
0160              " Remote                                         "
0161              " SvID ConnID   End Use State    Key     "
0162              " Serial   ISerial  CallId0  CallId1  CallId2  CallId3\n"
0163              );
0164         return 0;
0165     }
0166 
0167     conn = list_entry(v, struct rxrpc_connection, proc_link);
0168     if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) {
0169         strcpy(lbuff, "no_local");
0170         strcpy(rbuff, "no_connection");
0171         goto print;
0172     }
0173 
0174     sprintf(lbuff, "%pISpc", &conn->params.local->srx.transport);
0175 
0176     sprintf(rbuff, "%pISpc", &conn->params.peer->srx.transport);
0177 print:
0178     seq_printf(seq,
0179            "UDP   %-47.47s %-47.47s %4x %08x %s %3u"
0180            " %s %08x %08x %08x %08x %08x %08x %08x\n",
0181            lbuff,
0182            rbuff,
0183            conn->service_id,
0184            conn->proto.cid,
0185            rxrpc_conn_is_service(conn) ? "Svc" : "Clt",
0186            refcount_read(&conn->ref),
0187            rxrpc_conn_states[conn->state],
0188            key_serial(conn->params.key),
0189            atomic_read(&conn->serial),
0190            conn->hi_serial,
0191            conn->channels[0].call_id,
0192            conn->channels[1].call_id,
0193            conn->channels[2].call_id,
0194            conn->channels[3].call_id);
0195 
0196     return 0;
0197 }
0198 
0199 const struct seq_operations rxrpc_connection_seq_ops = {
0200     .start  = rxrpc_connection_seq_start,
0201     .next   = rxrpc_connection_seq_next,
0202     .stop   = rxrpc_connection_seq_stop,
0203     .show   = rxrpc_connection_seq_show,
0204 };
0205 
0206 /*
0207  * generate a list of extant virtual peers in /proc/net/rxrpc/peers
0208  */
0209 static int rxrpc_peer_seq_show(struct seq_file *seq, void *v)
0210 {
0211     struct rxrpc_peer *peer;
0212     time64_t now;
0213     char lbuff[50], rbuff[50];
0214 
0215     if (v == SEQ_START_TOKEN) {
0216         seq_puts(seq,
0217              "Proto Local                                          "
0218              " Remote                                         "
0219              " Use  CW   MTU LastUse      RTT      RTO\n"
0220              );
0221         return 0;
0222     }
0223 
0224     peer = list_entry(v, struct rxrpc_peer, hash_link);
0225 
0226     sprintf(lbuff, "%pISpc", &peer->local->srx.transport);
0227 
0228     sprintf(rbuff, "%pISpc", &peer->srx.transport);
0229 
0230     now = ktime_get_seconds();
0231     seq_printf(seq,
0232            "UDP   %-47.47s %-47.47s %3u"
0233            " %3u %5u %6llus %8u %8u\n",
0234            lbuff,
0235            rbuff,
0236            refcount_read(&peer->ref),
0237            peer->cong_cwnd,
0238            peer->mtu,
0239            now - peer->last_tx_at,
0240            peer->srtt_us >> 3,
0241            jiffies_to_usecs(peer->rto_j));
0242 
0243     return 0;
0244 }
0245 
0246 static void *rxrpc_peer_seq_start(struct seq_file *seq, loff_t *_pos)
0247     __acquires(rcu)
0248 {
0249     struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
0250     unsigned int bucket, n;
0251     unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash);
0252     void *p;
0253 
0254     rcu_read_lock();
0255 
0256     if (*_pos >= UINT_MAX)
0257         return NULL;
0258 
0259     n = *_pos & ((1U << shift) - 1);
0260     bucket = *_pos >> shift;
0261     for (;;) {
0262         if (bucket >= HASH_SIZE(rxnet->peer_hash)) {
0263             *_pos = UINT_MAX;
0264             return NULL;
0265         }
0266         if (n == 0) {
0267             if (bucket == 0)
0268                 return SEQ_START_TOKEN;
0269             *_pos += 1;
0270             n++;
0271         }
0272 
0273         p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1);
0274         if (p)
0275             return p;
0276         bucket++;
0277         n = 1;
0278         *_pos = (bucket << shift) | n;
0279     }
0280 }
0281 
0282 static void *rxrpc_peer_seq_next(struct seq_file *seq, void *v, loff_t *_pos)
0283 {
0284     struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
0285     unsigned int bucket, n;
0286     unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash);
0287     void *p;
0288 
0289     if (*_pos >= UINT_MAX)
0290         return NULL;
0291 
0292     bucket = *_pos >> shift;
0293 
0294     p = seq_hlist_next_rcu(v, &rxnet->peer_hash[bucket], _pos);
0295     if (p)
0296         return p;
0297 
0298     for (;;) {
0299         bucket++;
0300         n = 1;
0301         *_pos = (bucket << shift) | n;
0302 
0303         if (bucket >= HASH_SIZE(rxnet->peer_hash)) {
0304             *_pos = UINT_MAX;
0305             return NULL;
0306         }
0307         if (n == 0) {
0308             *_pos += 1;
0309             n++;
0310         }
0311 
0312         p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1);
0313         if (p)
0314             return p;
0315     }
0316 }
0317 
0318 static void rxrpc_peer_seq_stop(struct seq_file *seq, void *v)
0319     __releases(rcu)
0320 {
0321     rcu_read_unlock();
0322 }
0323 
0324 
0325 const struct seq_operations rxrpc_peer_seq_ops = {
0326     .start  = rxrpc_peer_seq_start,
0327     .next   = rxrpc_peer_seq_next,
0328     .stop   = rxrpc_peer_seq_stop,
0329     .show   = rxrpc_peer_seq_show,
0330 };
0331 
0332 /*
0333  * Generate a list of extant virtual local endpoints in /proc/net/rxrpc/locals
0334  */
0335 static int rxrpc_local_seq_show(struct seq_file *seq, void *v)
0336 {
0337     struct rxrpc_local *local;
0338     char lbuff[50];
0339 
0340     if (v == SEQ_START_TOKEN) {
0341         seq_puts(seq,
0342              "Proto Local                                          "
0343              " Use Act\n");
0344         return 0;
0345     }
0346 
0347     local = hlist_entry(v, struct rxrpc_local, link);
0348 
0349     sprintf(lbuff, "%pISpc", &local->srx.transport);
0350 
0351     seq_printf(seq,
0352            "UDP   %-47.47s %3u %3u\n",
0353            lbuff,
0354            refcount_read(&local->ref),
0355            atomic_read(&local->active_users));
0356 
0357     return 0;
0358 }
0359 
0360 static void *rxrpc_local_seq_start(struct seq_file *seq, loff_t *_pos)
0361     __acquires(rcu)
0362 {
0363     struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
0364     unsigned int n;
0365 
0366     rcu_read_lock();
0367 
0368     if (*_pos >= UINT_MAX)
0369         return NULL;
0370 
0371     n = *_pos;
0372     if (n == 0)
0373         return SEQ_START_TOKEN;
0374 
0375     return seq_hlist_start_rcu(&rxnet->local_endpoints, n - 1);
0376 }
0377 
0378 static void *rxrpc_local_seq_next(struct seq_file *seq, void *v, loff_t *_pos)
0379 {
0380     struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
0381 
0382     if (*_pos >= UINT_MAX)
0383         return NULL;
0384 
0385     return seq_hlist_next_rcu(v, &rxnet->local_endpoints, _pos);
0386 }
0387 
0388 static void rxrpc_local_seq_stop(struct seq_file *seq, void *v)
0389     __releases(rcu)
0390 {
0391     rcu_read_unlock();
0392 }
0393 
0394 const struct seq_operations rxrpc_local_seq_ops = {
0395     .start  = rxrpc_local_seq_start,
0396     .next   = rxrpc_local_seq_next,
0397     .stop   = rxrpc_local_seq_stop,
0398     .show   = rxrpc_local_seq_show,
0399 };