162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* /proc/net/ support for AF_RXRPC 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 562306a36Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/module.h> 962306a36Sopenharmony_ci#include <net/sock.h> 1062306a36Sopenharmony_ci#include <net/af_rxrpc.h> 1162306a36Sopenharmony_ci#include "ar-internal.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES] = { 1462306a36Sopenharmony_ci [RXRPC_CONN_UNUSED] = "Unused ", 1562306a36Sopenharmony_ci [RXRPC_CONN_CLIENT_UNSECURED] = "ClUnsec ", 1662306a36Sopenharmony_ci [RXRPC_CONN_CLIENT] = "Client ", 1762306a36Sopenharmony_ci [RXRPC_CONN_SERVICE_PREALLOC] = "SvPrealc", 1862306a36Sopenharmony_ci [RXRPC_CONN_SERVICE_UNSECURED] = "SvUnsec ", 1962306a36Sopenharmony_ci [RXRPC_CONN_SERVICE_CHALLENGING] = "SvChall ", 2062306a36Sopenharmony_ci [RXRPC_CONN_SERVICE] = "SvSecure", 2162306a36Sopenharmony_ci [RXRPC_CONN_ABORTED] = "Aborted ", 2262306a36Sopenharmony_ci}; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* 2562306a36Sopenharmony_ci * generate a list of extant and dead calls in /proc/net/rxrpc_calls 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_cistatic void *rxrpc_call_seq_start(struct seq_file *seq, loff_t *_pos) 2862306a36Sopenharmony_ci __acquires(rcu) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci rcu_read_lock(); 3362306a36Sopenharmony_ci return seq_list_start_head_rcu(&rxnet->calls, *_pos); 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic void *rxrpc_call_seq_next(struct seq_file *seq, void *v, loff_t *pos) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci return seq_list_next_rcu(v, &rxnet->calls, pos); 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic void rxrpc_call_seq_stop(struct seq_file *seq, void *v) 4462306a36Sopenharmony_ci __releases(rcu) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci rcu_read_unlock(); 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic int rxrpc_call_seq_show(struct seq_file *seq, void *v) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci struct rxrpc_local *local; 5262306a36Sopenharmony_ci struct rxrpc_call *call; 5362306a36Sopenharmony_ci struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 5462306a36Sopenharmony_ci enum rxrpc_call_state state; 5562306a36Sopenharmony_ci unsigned long timeout = 0; 5662306a36Sopenharmony_ci rxrpc_seq_t acks_hard_ack; 5762306a36Sopenharmony_ci char lbuff[50], rbuff[50]; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci if (v == &rxnet->calls) { 6062306a36Sopenharmony_ci seq_puts(seq, 6162306a36Sopenharmony_ci "Proto Local " 6262306a36Sopenharmony_ci " Remote " 6362306a36Sopenharmony_ci " SvID ConnID CallID End Use State Abort " 6462306a36Sopenharmony_ci " DebugId TxSeq TW RxSeq RW RxSerial CW RxTimo\n"); 6562306a36Sopenharmony_ci return 0; 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci call = list_entry(v, struct rxrpc_call, link); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci local = call->local; 7162306a36Sopenharmony_ci if (local) 7262306a36Sopenharmony_ci sprintf(lbuff, "%pISpc", &local->srx.transport); 7362306a36Sopenharmony_ci else 7462306a36Sopenharmony_ci strcpy(lbuff, "no_local"); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci sprintf(rbuff, "%pISpc", &call->dest_srx.transport); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci state = rxrpc_call_state(call); 7962306a36Sopenharmony_ci if (state != RXRPC_CALL_SERVER_PREALLOC) { 8062306a36Sopenharmony_ci timeout = READ_ONCE(call->expect_rx_by); 8162306a36Sopenharmony_ci timeout -= jiffies; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci acks_hard_ack = READ_ONCE(call->acks_hard_ack); 8562306a36Sopenharmony_ci seq_printf(seq, 8662306a36Sopenharmony_ci "UDP %-47.47s %-47.47s %4x %08x %08x %s %3u" 8762306a36Sopenharmony_ci " %-8.8s %08x %08x %08x %02x %08x %02x %08x %02x %06lx\n", 8862306a36Sopenharmony_ci lbuff, 8962306a36Sopenharmony_ci rbuff, 9062306a36Sopenharmony_ci call->dest_srx.srx_service, 9162306a36Sopenharmony_ci call->cid, 9262306a36Sopenharmony_ci call->call_id, 9362306a36Sopenharmony_ci rxrpc_is_service_call(call) ? "Svc" : "Clt", 9462306a36Sopenharmony_ci refcount_read(&call->ref), 9562306a36Sopenharmony_ci rxrpc_call_states[state], 9662306a36Sopenharmony_ci call->abort_code, 9762306a36Sopenharmony_ci call->debug_id, 9862306a36Sopenharmony_ci acks_hard_ack, READ_ONCE(call->tx_top) - acks_hard_ack, 9962306a36Sopenharmony_ci call->ackr_window, call->ackr_wtop - call->ackr_window, 10062306a36Sopenharmony_ci call->rx_serial, 10162306a36Sopenharmony_ci call->cong_cwnd, 10262306a36Sopenharmony_ci timeout); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci return 0; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ciconst struct seq_operations rxrpc_call_seq_ops = { 10862306a36Sopenharmony_ci .start = rxrpc_call_seq_start, 10962306a36Sopenharmony_ci .next = rxrpc_call_seq_next, 11062306a36Sopenharmony_ci .stop = rxrpc_call_seq_stop, 11162306a36Sopenharmony_ci .show = rxrpc_call_seq_show, 11262306a36Sopenharmony_ci}; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/* 11562306a36Sopenharmony_ci * generate a list of extant virtual connections in /proc/net/rxrpc_conns 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_cistatic void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos) 11862306a36Sopenharmony_ci __acquires(rxnet->conn_lock) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci read_lock(&rxnet->conn_lock); 12362306a36Sopenharmony_ci return seq_list_start_head(&rxnet->conn_proc_list, *_pos); 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic void *rxrpc_connection_seq_next(struct seq_file *seq, void *v, 12762306a36Sopenharmony_ci loff_t *pos) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci return seq_list_next(v, &rxnet->conn_proc_list, pos); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic void rxrpc_connection_seq_stop(struct seq_file *seq, void *v) 13562306a36Sopenharmony_ci __releases(rxnet->conn_lock) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci read_unlock(&rxnet->conn_lock); 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic int rxrpc_connection_seq_show(struct seq_file *seq, void *v) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci struct rxrpc_connection *conn; 14562306a36Sopenharmony_ci struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 14662306a36Sopenharmony_ci const char *state; 14762306a36Sopenharmony_ci char lbuff[50], rbuff[50]; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci if (v == &rxnet->conn_proc_list) { 15062306a36Sopenharmony_ci seq_puts(seq, 15162306a36Sopenharmony_ci "Proto Local " 15262306a36Sopenharmony_ci " Remote " 15362306a36Sopenharmony_ci " SvID ConnID End Ref Act State Key " 15462306a36Sopenharmony_ci " Serial ISerial CallId0 CallId1 CallId2 CallId3\n" 15562306a36Sopenharmony_ci ); 15662306a36Sopenharmony_ci return 0; 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci conn = list_entry(v, struct rxrpc_connection, proc_link); 16062306a36Sopenharmony_ci if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) { 16162306a36Sopenharmony_ci strcpy(lbuff, "no_local"); 16262306a36Sopenharmony_ci strcpy(rbuff, "no_connection"); 16362306a36Sopenharmony_ci goto print; 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci sprintf(lbuff, "%pISpc", &conn->local->srx.transport); 16762306a36Sopenharmony_ci sprintf(rbuff, "%pISpc", &conn->peer->srx.transport); 16862306a36Sopenharmony_ciprint: 16962306a36Sopenharmony_ci state = rxrpc_is_conn_aborted(conn) ? 17062306a36Sopenharmony_ci rxrpc_call_completions[conn->completion] : 17162306a36Sopenharmony_ci rxrpc_conn_states[conn->state]; 17262306a36Sopenharmony_ci seq_printf(seq, 17362306a36Sopenharmony_ci "UDP %-47.47s %-47.47s %4x %08x %s %3u %3d" 17462306a36Sopenharmony_ci " %s %08x %08x %08x %08x %08x %08x %08x\n", 17562306a36Sopenharmony_ci lbuff, 17662306a36Sopenharmony_ci rbuff, 17762306a36Sopenharmony_ci conn->service_id, 17862306a36Sopenharmony_ci conn->proto.cid, 17962306a36Sopenharmony_ci rxrpc_conn_is_service(conn) ? "Svc" : "Clt", 18062306a36Sopenharmony_ci refcount_read(&conn->ref), 18162306a36Sopenharmony_ci atomic_read(&conn->active), 18262306a36Sopenharmony_ci state, 18362306a36Sopenharmony_ci key_serial(conn->key), 18462306a36Sopenharmony_ci conn->tx_serial, 18562306a36Sopenharmony_ci conn->hi_serial, 18662306a36Sopenharmony_ci conn->channels[0].call_id, 18762306a36Sopenharmony_ci conn->channels[1].call_id, 18862306a36Sopenharmony_ci conn->channels[2].call_id, 18962306a36Sopenharmony_ci conn->channels[3].call_id); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return 0; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ciconst struct seq_operations rxrpc_connection_seq_ops = { 19562306a36Sopenharmony_ci .start = rxrpc_connection_seq_start, 19662306a36Sopenharmony_ci .next = rxrpc_connection_seq_next, 19762306a36Sopenharmony_ci .stop = rxrpc_connection_seq_stop, 19862306a36Sopenharmony_ci .show = rxrpc_connection_seq_show, 19962306a36Sopenharmony_ci}; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci/* 20262306a36Sopenharmony_ci * generate a list of extant virtual peers in /proc/net/rxrpc/peers 20362306a36Sopenharmony_ci */ 20462306a36Sopenharmony_cistatic int rxrpc_peer_seq_show(struct seq_file *seq, void *v) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci struct rxrpc_peer *peer; 20762306a36Sopenharmony_ci time64_t now; 20862306a36Sopenharmony_ci char lbuff[50], rbuff[50]; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci if (v == SEQ_START_TOKEN) { 21162306a36Sopenharmony_ci seq_puts(seq, 21262306a36Sopenharmony_ci "Proto Local " 21362306a36Sopenharmony_ci " Remote " 21462306a36Sopenharmony_ci " Use SST MTU LastUse RTT RTO\n" 21562306a36Sopenharmony_ci ); 21662306a36Sopenharmony_ci return 0; 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci peer = list_entry(v, struct rxrpc_peer, hash_link); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci sprintf(lbuff, "%pISpc", &peer->local->srx.transport); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci sprintf(rbuff, "%pISpc", &peer->srx.transport); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci now = ktime_get_seconds(); 22662306a36Sopenharmony_ci seq_printf(seq, 22762306a36Sopenharmony_ci "UDP %-47.47s %-47.47s %3u" 22862306a36Sopenharmony_ci " %3u %5u %6llus %8u %8u\n", 22962306a36Sopenharmony_ci lbuff, 23062306a36Sopenharmony_ci rbuff, 23162306a36Sopenharmony_ci refcount_read(&peer->ref), 23262306a36Sopenharmony_ci peer->cong_ssthresh, 23362306a36Sopenharmony_ci peer->mtu, 23462306a36Sopenharmony_ci now - peer->last_tx_at, 23562306a36Sopenharmony_ci peer->srtt_us >> 3, 23662306a36Sopenharmony_ci jiffies_to_usecs(peer->rto_j)); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci return 0; 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic void *rxrpc_peer_seq_start(struct seq_file *seq, loff_t *_pos) 24262306a36Sopenharmony_ci __acquires(rcu) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 24562306a36Sopenharmony_ci unsigned int bucket, n; 24662306a36Sopenharmony_ci unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash); 24762306a36Sopenharmony_ci void *p; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci rcu_read_lock(); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci if (*_pos >= UINT_MAX) 25262306a36Sopenharmony_ci return NULL; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci n = *_pos & ((1U << shift) - 1); 25562306a36Sopenharmony_ci bucket = *_pos >> shift; 25662306a36Sopenharmony_ci for (;;) { 25762306a36Sopenharmony_ci if (bucket >= HASH_SIZE(rxnet->peer_hash)) { 25862306a36Sopenharmony_ci *_pos = UINT_MAX; 25962306a36Sopenharmony_ci return NULL; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci if (n == 0) { 26262306a36Sopenharmony_ci if (bucket == 0) 26362306a36Sopenharmony_ci return SEQ_START_TOKEN; 26462306a36Sopenharmony_ci *_pos += 1; 26562306a36Sopenharmony_ci n++; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1); 26962306a36Sopenharmony_ci if (p) 27062306a36Sopenharmony_ci return p; 27162306a36Sopenharmony_ci bucket++; 27262306a36Sopenharmony_ci n = 1; 27362306a36Sopenharmony_ci *_pos = (bucket << shift) | n; 27462306a36Sopenharmony_ci } 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cistatic void *rxrpc_peer_seq_next(struct seq_file *seq, void *v, loff_t *_pos) 27862306a36Sopenharmony_ci{ 27962306a36Sopenharmony_ci struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 28062306a36Sopenharmony_ci unsigned int bucket, n; 28162306a36Sopenharmony_ci unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash); 28262306a36Sopenharmony_ci void *p; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (*_pos >= UINT_MAX) 28562306a36Sopenharmony_ci return NULL; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci bucket = *_pos >> shift; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci p = seq_hlist_next_rcu(v, &rxnet->peer_hash[bucket], _pos); 29062306a36Sopenharmony_ci if (p) 29162306a36Sopenharmony_ci return p; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci for (;;) { 29462306a36Sopenharmony_ci bucket++; 29562306a36Sopenharmony_ci n = 1; 29662306a36Sopenharmony_ci *_pos = (bucket << shift) | n; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci if (bucket >= HASH_SIZE(rxnet->peer_hash)) { 29962306a36Sopenharmony_ci *_pos = UINT_MAX; 30062306a36Sopenharmony_ci return NULL; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci if (n == 0) { 30362306a36Sopenharmony_ci *_pos += 1; 30462306a36Sopenharmony_ci n++; 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1); 30862306a36Sopenharmony_ci if (p) 30962306a36Sopenharmony_ci return p; 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_cistatic void rxrpc_peer_seq_stop(struct seq_file *seq, void *v) 31462306a36Sopenharmony_ci __releases(rcu) 31562306a36Sopenharmony_ci{ 31662306a36Sopenharmony_ci rcu_read_unlock(); 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ciconst struct seq_operations rxrpc_peer_seq_ops = { 32162306a36Sopenharmony_ci .start = rxrpc_peer_seq_start, 32262306a36Sopenharmony_ci .next = rxrpc_peer_seq_next, 32362306a36Sopenharmony_ci .stop = rxrpc_peer_seq_stop, 32462306a36Sopenharmony_ci .show = rxrpc_peer_seq_show, 32562306a36Sopenharmony_ci}; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci/* 32862306a36Sopenharmony_ci * Generate a list of extant virtual local endpoints in /proc/net/rxrpc/locals 32962306a36Sopenharmony_ci */ 33062306a36Sopenharmony_cistatic int rxrpc_local_seq_show(struct seq_file *seq, void *v) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci struct rxrpc_local *local; 33362306a36Sopenharmony_ci char lbuff[50]; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci if (v == SEQ_START_TOKEN) { 33662306a36Sopenharmony_ci seq_puts(seq, 33762306a36Sopenharmony_ci "Proto Local " 33862306a36Sopenharmony_ci " Use Act RxQ\n"); 33962306a36Sopenharmony_ci return 0; 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci local = hlist_entry(v, struct rxrpc_local, link); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci sprintf(lbuff, "%pISpc", &local->srx.transport); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci seq_printf(seq, 34762306a36Sopenharmony_ci "UDP %-47.47s %3u %3u %3u\n", 34862306a36Sopenharmony_ci lbuff, 34962306a36Sopenharmony_ci refcount_read(&local->ref), 35062306a36Sopenharmony_ci atomic_read(&local->active_users), 35162306a36Sopenharmony_ci local->rx_queue.qlen); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci return 0; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic void *rxrpc_local_seq_start(struct seq_file *seq, loff_t *_pos) 35762306a36Sopenharmony_ci __acquires(rcu) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 36062306a36Sopenharmony_ci unsigned int n; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci rcu_read_lock(); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci if (*_pos >= UINT_MAX) 36562306a36Sopenharmony_ci return NULL; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci n = *_pos; 36862306a36Sopenharmony_ci if (n == 0) 36962306a36Sopenharmony_ci return SEQ_START_TOKEN; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci return seq_hlist_start_rcu(&rxnet->local_endpoints, n - 1); 37262306a36Sopenharmony_ci} 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_cistatic void *rxrpc_local_seq_next(struct seq_file *seq, void *v, loff_t *_pos) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci if (*_pos >= UINT_MAX) 37962306a36Sopenharmony_ci return NULL; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci return seq_hlist_next_rcu(v, &rxnet->local_endpoints, _pos); 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_cistatic void rxrpc_local_seq_stop(struct seq_file *seq, void *v) 38562306a36Sopenharmony_ci __releases(rcu) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci rcu_read_unlock(); 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ciconst struct seq_operations rxrpc_local_seq_ops = { 39162306a36Sopenharmony_ci .start = rxrpc_local_seq_start, 39262306a36Sopenharmony_ci .next = rxrpc_local_seq_next, 39362306a36Sopenharmony_ci .stop = rxrpc_local_seq_stop, 39462306a36Sopenharmony_ci .show = rxrpc_local_seq_show, 39562306a36Sopenharmony_ci}; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci/* 39862306a36Sopenharmony_ci * Display stats in /proc/net/rxrpc/stats 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_ciint rxrpc_stats_show(struct seq_file *seq, void *v) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci struct rxrpc_net *rxnet = rxrpc_net(seq_file_single_net(seq)); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci seq_printf(seq, 40562306a36Sopenharmony_ci "Data : send=%u sendf=%u fail=%u\n", 40662306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_data_send), 40762306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_data_send_frag), 40862306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_data_send_fail)); 40962306a36Sopenharmony_ci seq_printf(seq, 41062306a36Sopenharmony_ci "Data-Tx : nr=%u retrans=%u uf=%u cwr=%u\n", 41162306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_data), 41262306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_data_retrans), 41362306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_data_underflow), 41462306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_data_cwnd_reset)); 41562306a36Sopenharmony_ci seq_printf(seq, 41662306a36Sopenharmony_ci "Data-Rx : nr=%u reqack=%u jumbo=%u\n", 41762306a36Sopenharmony_ci atomic_read(&rxnet->stat_rx_data), 41862306a36Sopenharmony_ci atomic_read(&rxnet->stat_rx_data_reqack), 41962306a36Sopenharmony_ci atomic_read(&rxnet->stat_rx_data_jumbo)); 42062306a36Sopenharmony_ci seq_printf(seq, 42162306a36Sopenharmony_ci "Ack : fill=%u send=%u skip=%u\n", 42262306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_ack_fill), 42362306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_ack_send), 42462306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_ack_skip)); 42562306a36Sopenharmony_ci seq_printf(seq, 42662306a36Sopenharmony_ci "Ack-Tx : req=%u dup=%u oos=%u exw=%u nos=%u png=%u prs=%u dly=%u idl=%u\n", 42762306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_REQUESTED]), 42862306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_DUPLICATE]), 42962306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_OUT_OF_SEQUENCE]), 43062306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_EXCEEDS_WINDOW]), 43162306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_NOSPACE]), 43262306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_PING]), 43362306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_PING_RESPONSE]), 43462306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_DELAY]), 43562306a36Sopenharmony_ci atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_IDLE])); 43662306a36Sopenharmony_ci seq_printf(seq, 43762306a36Sopenharmony_ci "Ack-Rx : req=%u dup=%u oos=%u exw=%u nos=%u png=%u prs=%u dly=%u idl=%u\n", 43862306a36Sopenharmony_ci atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_REQUESTED]), 43962306a36Sopenharmony_ci atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_DUPLICATE]), 44062306a36Sopenharmony_ci atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_OUT_OF_SEQUENCE]), 44162306a36Sopenharmony_ci atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_EXCEEDS_WINDOW]), 44262306a36Sopenharmony_ci atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_NOSPACE]), 44362306a36Sopenharmony_ci atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_PING]), 44462306a36Sopenharmony_ci atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_PING_RESPONSE]), 44562306a36Sopenharmony_ci atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_DELAY]), 44662306a36Sopenharmony_ci atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_IDLE])); 44762306a36Sopenharmony_ci seq_printf(seq, 44862306a36Sopenharmony_ci "Why-Req-A: acklost=%u already=%u mrtt=%u ortt=%u\n", 44962306a36Sopenharmony_ci atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_ack_lost]), 45062306a36Sopenharmony_ci atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_already_on]), 45162306a36Sopenharmony_ci atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_more_rtt]), 45262306a36Sopenharmony_ci atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_old_rtt])); 45362306a36Sopenharmony_ci seq_printf(seq, 45462306a36Sopenharmony_ci "Why-Req-A: nolast=%u retx=%u slows=%u smtxw=%u\n", 45562306a36Sopenharmony_ci atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_no_srv_last]), 45662306a36Sopenharmony_ci atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_retrans]), 45762306a36Sopenharmony_ci atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_slow_start]), 45862306a36Sopenharmony_ci atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_small_txwin])); 45962306a36Sopenharmony_ci seq_printf(seq, 46062306a36Sopenharmony_ci "Buffers : txb=%u rxb=%u\n", 46162306a36Sopenharmony_ci atomic_read(&rxrpc_nr_txbuf), 46262306a36Sopenharmony_ci atomic_read(&rxrpc_n_rx_skbs)); 46362306a36Sopenharmony_ci seq_printf(seq, 46462306a36Sopenharmony_ci "IO-thread: loops=%u\n", 46562306a36Sopenharmony_ci atomic_read(&rxnet->stat_io_loop)); 46662306a36Sopenharmony_ci return 0; 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci/* 47062306a36Sopenharmony_ci * Clear stats if /proc/net/rxrpc/stats is written to. 47162306a36Sopenharmony_ci */ 47262306a36Sopenharmony_ciint rxrpc_stats_clear(struct file *file, char *buf, size_t size) 47362306a36Sopenharmony_ci{ 47462306a36Sopenharmony_ci struct seq_file *m = file->private_data; 47562306a36Sopenharmony_ci struct rxrpc_net *rxnet = rxrpc_net(seq_file_single_net(m)); 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci if (size > 1 || (size == 1 && buf[0] != '\n')) 47862306a36Sopenharmony_ci return -EINVAL; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci atomic_set(&rxnet->stat_tx_data, 0); 48162306a36Sopenharmony_ci atomic_set(&rxnet->stat_tx_data_retrans, 0); 48262306a36Sopenharmony_ci atomic_set(&rxnet->stat_tx_data_underflow, 0); 48362306a36Sopenharmony_ci atomic_set(&rxnet->stat_tx_data_cwnd_reset, 0); 48462306a36Sopenharmony_ci atomic_set(&rxnet->stat_tx_data_send, 0); 48562306a36Sopenharmony_ci atomic_set(&rxnet->stat_tx_data_send_frag, 0); 48662306a36Sopenharmony_ci atomic_set(&rxnet->stat_tx_data_send_fail, 0); 48762306a36Sopenharmony_ci atomic_set(&rxnet->stat_rx_data, 0); 48862306a36Sopenharmony_ci atomic_set(&rxnet->stat_rx_data_reqack, 0); 48962306a36Sopenharmony_ci atomic_set(&rxnet->stat_rx_data_jumbo, 0); 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci atomic_set(&rxnet->stat_tx_ack_fill, 0); 49262306a36Sopenharmony_ci atomic_set(&rxnet->stat_tx_ack_send, 0); 49362306a36Sopenharmony_ci atomic_set(&rxnet->stat_tx_ack_skip, 0); 49462306a36Sopenharmony_ci memset(&rxnet->stat_tx_acks, 0, sizeof(rxnet->stat_tx_acks)); 49562306a36Sopenharmony_ci memset(&rxnet->stat_rx_acks, 0, sizeof(rxnet->stat_rx_acks)); 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci memset(&rxnet->stat_why_req_ack, 0, sizeof(rxnet->stat_why_req_ack)); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci atomic_set(&rxnet->stat_io_loop, 0); 50062306a36Sopenharmony_ci return size; 50162306a36Sopenharmony_ci} 502