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 #define RXRPC_PROC_ADDRBUF_SIZE \ 14 (sizeof("[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255]") + \ 15 sizeof(":12345")) 16 17 static const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES] = { 18 [RXRPC_CONN_UNUSED] = "Unused ", 19 [RXRPC_CONN_CLIENT_UNSECURED] = "ClUnsec ", 20 [RXRPC_CONN_CLIENT] = "Client ", 21 [RXRPC_CONN_SERVICE_PREALLOC] = "SvPrealc", 22 [RXRPC_CONN_SERVICE_UNSECURED] = "SvUnsec ", 23 [RXRPC_CONN_SERVICE_CHALLENGING] = "SvChall ", 24 [RXRPC_CONN_SERVICE] = "SvSecure", 25 [RXRPC_CONN_ABORTED] = "Aborted ", 26 }; 27 28 /* 29 * generate a list of extant and dead calls in /proc/net/rxrpc_calls 30 */ 31 static void *rxrpc_call_seq_start(struct seq_file *seq, loff_t *_pos) 32 __acquires(rcu) 33 { 34 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 35 36 rcu_read_lock(); 37 return seq_list_start_head_rcu(&rxnet->calls, *_pos); 38 } 39 40 static void *rxrpc_call_seq_next(struct seq_file *seq, void *v, loff_t *pos) 41 { 42 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 43 44 return seq_list_next_rcu(v, &rxnet->calls, pos); 45 } 46 47 static void rxrpc_call_seq_stop(struct seq_file *seq, void *v) 48 __releases(rcu) 49 { 50 rcu_read_unlock(); 51 } 52 53 static int rxrpc_call_seq_show(struct seq_file *seq, void *v) 54 { 55 struct rxrpc_local *local; 56 struct rxrpc_call *call; 57 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 58 enum rxrpc_call_state state; 59 rxrpc_seq_t tx_bottom; 60 char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE]; 61 long timeout = 0; 62 63 if (v == &rxnet->calls) { 64 seq_puts(seq, 65 "Proto Local " 66 " Remote " 67 " SvID ConnID CallID End Use State Abort " 68 " DebugId TxSeq TW RxSeq RW RxSerial CW RxTimo\n"); 69 return 0; 70 } 71 72 call = list_entry(v, struct rxrpc_call, link); 73 74 local = call->local; 75 if (local) 76 scnprintf(lbuff, sizeof(lbuff), "%pISpc", &local->srx.transport); 77 else 78 strcpy(lbuff, "no_local"); 79 80 scnprintf(rbuff, sizeof(rbuff), "%pISpc", &call->dest_srx.transport); 81 82 state = rxrpc_call_state(call); 83 if (state != RXRPC_CALL_SERVER_PREALLOC) 84 timeout = ktime_ms_delta(READ_ONCE(call->expect_rx_by), ktime_get_real()); 85 86 tx_bottom = READ_ONCE(call->tx_bottom); 87 seq_printf(seq, 88 "UDP %-47.47s %-47.47s %4x %08x %08x %s %3u" 89 " %-8.8s %08x %08x %08x %02x %08x %02x %08x %02x %06lx\n", 90 lbuff, 91 rbuff, 92 call->dest_srx.srx_service, 93 call->cid, 94 call->call_id, 95 rxrpc_is_service_call(call) ? "Svc" : "Clt", 96 refcount_read(&call->ref), 97 rxrpc_call_states[state], 98 call->abort_code, 99 call->debug_id, 100 tx_bottom, READ_ONCE(call->tx_top) - tx_bottom, 101 call->ackr_window, call->ackr_wtop - call->ackr_window, 102 call->rx_serial, 103 call->cong_cwnd, 104 timeout); 105 106 return 0; 107 } 108 109 const struct seq_operations rxrpc_call_seq_ops = { 110 .start = rxrpc_call_seq_start, 111 .next = rxrpc_call_seq_next, 112 .stop = rxrpc_call_seq_stop, 113 .show = rxrpc_call_seq_show, 114 }; 115 116 /* 117 * generate a list of extant virtual connections in /proc/net/rxrpc_conns 118 */ 119 static void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos) 120 __acquires(rxnet->conn_lock) 121 { 122 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 123 124 read_lock(&rxnet->conn_lock); 125 return seq_list_start_head(&rxnet->conn_proc_list, *_pos); 126 } 127 128 static void *rxrpc_connection_seq_next(struct seq_file *seq, void *v, 129 loff_t *pos) 130 { 131 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 132 133 return seq_list_next(v, &rxnet->conn_proc_list, pos); 134 } 135 136 static void rxrpc_connection_seq_stop(struct seq_file *seq, void *v) 137 __releases(rxnet->conn_lock) 138 { 139 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 140 141 read_unlock(&rxnet->conn_lock); 142 } 143 144 static int rxrpc_connection_seq_show(struct seq_file *seq, void *v) 145 { 146 struct rxrpc_connection *conn; 147 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 148 const char *state; 149 char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE]; 150 151 if (v == &rxnet->conn_proc_list) { 152 seq_puts(seq, 153 "Proto Local " 154 " Remote " 155 " SvID ConnID End Ref Act State Key " 156 " Serial ISerial CallId0 CallId1 CallId2 CallId3\n" 157 ); 158 return 0; 159 } 160 161 conn = list_entry(v, struct rxrpc_connection, proc_link); 162 if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) { 163 strcpy(lbuff, "no_local"); 164 strcpy(rbuff, "no_connection"); 165 goto print; 166 } 167 168 scnprintf(lbuff, sizeof(lbuff), "%pISpc", &conn->local->srx.transport); 169 scnprintf(rbuff, sizeof(rbuff), "%pISpc", &conn->peer->srx.transport); 170 print: 171 state = rxrpc_is_conn_aborted(conn) ? 172 rxrpc_call_completions[conn->completion] : 173 rxrpc_conn_states[conn->state]; 174 seq_printf(seq, 175 "UDP %-47.47s %-47.47s %4x %08x %s %3u %3d" 176 " %s %08x %08x %08x %08x %08x %08x %08x\n", 177 lbuff, 178 rbuff, 179 conn->service_id, 180 conn->proto.cid, 181 rxrpc_conn_is_service(conn) ? "Svc" : "Clt", 182 refcount_read(&conn->ref), 183 atomic_read(&conn->active), 184 state, 185 key_serial(conn->key), 186 conn->tx_serial, 187 conn->hi_serial, 188 conn->channels[0].call_id, 189 conn->channels[1].call_id, 190 conn->channels[2].call_id, 191 conn->channels[3].call_id); 192 193 return 0; 194 } 195 196 const struct seq_operations rxrpc_connection_seq_ops = { 197 .start = rxrpc_connection_seq_start, 198 .next = rxrpc_connection_seq_next, 199 .stop = rxrpc_connection_seq_stop, 200 .show = rxrpc_connection_seq_show, 201 }; 202 203 /* 204 * generate a list of extant virtual bundles in /proc/net/rxrpc/bundles 205 */ 206 static void *rxrpc_bundle_seq_start(struct seq_file *seq, loff_t *_pos) 207 __acquires(rxnet->conn_lock) 208 { 209 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 210 211 read_lock(&rxnet->conn_lock); 212 return seq_list_start_head(&rxnet->bundle_proc_list, *_pos); 213 } 214 215 static void *rxrpc_bundle_seq_next(struct seq_file *seq, void *v, 216 loff_t *pos) 217 { 218 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 219 220 return seq_list_next(v, &rxnet->bundle_proc_list, pos); 221 } 222 223 static void rxrpc_bundle_seq_stop(struct seq_file *seq, void *v) 224 __releases(rxnet->conn_lock) 225 { 226 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 227 228 read_unlock(&rxnet->conn_lock); 229 } 230 231 static int rxrpc_bundle_seq_show(struct seq_file *seq, void *v) 232 { 233 struct rxrpc_bundle *bundle; 234 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 235 char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE]; 236 237 if (v == &rxnet->bundle_proc_list) { 238 seq_puts(seq, 239 "Proto Local " 240 " Remote " 241 " SvID Ref Act Flg Key |" 242 " Bundle Conn_0 Conn_1 Conn_2 Conn_3\n" 243 ); 244 return 0; 245 } 246 247 bundle = list_entry(v, struct rxrpc_bundle, proc_link); 248 249 scnprintf(lbuff, sizeof(lbuff), "%pISpc", &bundle->local->srx.transport); 250 scnprintf(rbuff, sizeof(rbuff), "%pISpc", &bundle->peer->srx.transport); 251 seq_printf(seq, 252 "UDP %-47.47s %-47.47s %4x %3u %3d" 253 " %c%c%c %08x | %08x %08x %08x %08x %08x\n", 254 lbuff, 255 rbuff, 256 bundle->service_id, 257 refcount_read(&bundle->ref), 258 atomic_read(&bundle->active), 259 bundle->try_upgrade ? 'U' : '-', 260 bundle->exclusive ? 'e' : '-', 261 bundle->upgrade ? 'u' : '-', 262 key_serial(bundle->key), 263 bundle->debug_id, 264 bundle->conn_ids[0], 265 bundle->conn_ids[1], 266 bundle->conn_ids[2], 267 bundle->conn_ids[3]); 268 269 return 0; 270 } 271 272 const struct seq_operations rxrpc_bundle_seq_ops = { 273 .start = rxrpc_bundle_seq_start, 274 .next = rxrpc_bundle_seq_next, 275 .stop = rxrpc_bundle_seq_stop, 276 .show = rxrpc_bundle_seq_show, 277 }; 278 279 /* 280 * generate a list of extant virtual peers in /proc/net/rxrpc/peers 281 */ 282 static int rxrpc_peer_seq_show(struct seq_file *seq, void *v) 283 { 284 struct rxrpc_peer *peer; 285 time64_t now; 286 char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE]; 287 288 if (v == SEQ_START_TOKEN) { 289 seq_puts(seq, 290 "Proto Local Remote Use SST Maxd LastUse RTT RTO\n" 291 ); 292 return 0; 293 } 294 295 peer = list_entry(v, struct rxrpc_peer, hash_link); 296 297 scnprintf(lbuff, sizeof(lbuff), "%pISpc", &peer->local->srx.transport); 298 299 scnprintf(rbuff, sizeof(rbuff), "%pISpc", &peer->srx.transport); 300 301 now = ktime_get_seconds(); 302 seq_printf(seq, 303 "UDP %-47.47s %-47.47s %3u %4u %5u %6ds %8d %8d\n", 304 lbuff, 305 rbuff, 306 refcount_read(&peer->ref), 307 peer->cong_ssthresh, 308 peer->max_data, 309 (s32)now - (s32)READ_ONCE(peer->last_tx_at), 310 READ_ONCE(peer->recent_srtt_us), 311 READ_ONCE(peer->recent_rto_us)); 312 313 return 0; 314 } 315 316 static void *rxrpc_peer_seq_start(struct seq_file *seq, loff_t *_pos) 317 __acquires(rcu) 318 { 319 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 320 unsigned int bucket, n; 321 unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash); 322 void *p; 323 324 rcu_read_lock(); 325 326 if (*_pos >= UINT_MAX) 327 return NULL; 328 329 n = *_pos & ((1U << shift) - 1); 330 bucket = *_pos >> shift; 331 for (;;) { 332 if (bucket >= HASH_SIZE(rxnet->peer_hash)) { 333 *_pos = UINT_MAX; 334 return NULL; 335 } 336 if (n == 0) { 337 if (bucket == 0) 338 return SEQ_START_TOKEN; 339 *_pos += 1; 340 n++; 341 } 342 343 p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1); 344 if (p) 345 return p; 346 bucket++; 347 n = 1; 348 *_pos = (bucket << shift) | n; 349 } 350 } 351 352 static void *rxrpc_peer_seq_next(struct seq_file *seq, void *v, loff_t *_pos) 353 { 354 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 355 unsigned int bucket, n; 356 unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash); 357 void *p; 358 359 if (*_pos >= UINT_MAX) 360 return NULL; 361 362 bucket = *_pos >> shift; 363 364 p = seq_hlist_next_rcu(v, &rxnet->peer_hash[bucket], _pos); 365 if (p) 366 return p; 367 368 for (;;) { 369 bucket++; 370 n = 1; 371 *_pos = (bucket << shift) | n; 372 373 if (bucket >= HASH_SIZE(rxnet->peer_hash)) { 374 *_pos = UINT_MAX; 375 return NULL; 376 } 377 if (n == 0) { 378 *_pos += 1; 379 n++; 380 } 381 382 p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1); 383 if (p) 384 return p; 385 } 386 } 387 388 static void rxrpc_peer_seq_stop(struct seq_file *seq, void *v) 389 __releases(rcu) 390 { 391 rcu_read_unlock(); 392 } 393 394 395 const struct seq_operations rxrpc_peer_seq_ops = { 396 .start = rxrpc_peer_seq_start, 397 .next = rxrpc_peer_seq_next, 398 .stop = rxrpc_peer_seq_stop, 399 .show = rxrpc_peer_seq_show, 400 }; 401 402 /* 403 * Generate a list of extant virtual local endpoints in /proc/net/rxrpc/locals 404 */ 405 static int rxrpc_local_seq_show(struct seq_file *seq, void *v) 406 { 407 struct rxrpc_local *local; 408 char lbuff[RXRPC_PROC_ADDRBUF_SIZE]; 409 410 if (v == SEQ_START_TOKEN) { 411 seq_puts(seq, 412 "Proto Local " 413 " Use Act RxQ\n"); 414 return 0; 415 } 416 417 local = hlist_entry(v, struct rxrpc_local, link); 418 419 scnprintf(lbuff, sizeof(lbuff), "%pISpc", &local->srx.transport); 420 421 seq_printf(seq, 422 "UDP %-47.47s %3u %3u %3u\n", 423 lbuff, 424 refcount_read(&local->ref), 425 atomic_read(&local->active_users), 426 local->rx_queue.qlen); 427 428 return 0; 429 } 430 431 static void *rxrpc_local_seq_start(struct seq_file *seq, loff_t *_pos) 432 __acquires(rcu) 433 { 434 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 435 unsigned int n; 436 437 rcu_read_lock(); 438 439 if (*_pos >= UINT_MAX) 440 return NULL; 441 442 n = *_pos; 443 if (n == 0) 444 return SEQ_START_TOKEN; 445 446 return seq_hlist_start_rcu(&rxnet->local_endpoints, n - 1); 447 } 448 449 static void *rxrpc_local_seq_next(struct seq_file *seq, void *v, loff_t *_pos) 450 { 451 struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); 452 453 if (*_pos >= UINT_MAX) 454 return NULL; 455 456 return seq_hlist_next_rcu(v, &rxnet->local_endpoints, _pos); 457 } 458 459 static void rxrpc_local_seq_stop(struct seq_file *seq, void *v) 460 __releases(rcu) 461 { 462 rcu_read_unlock(); 463 } 464 465 const struct seq_operations rxrpc_local_seq_ops = { 466 .start = rxrpc_local_seq_start, 467 .next = rxrpc_local_seq_next, 468 .stop = rxrpc_local_seq_stop, 469 .show = rxrpc_local_seq_show, 470 }; 471 472 /* 473 * Display stats in /proc/net/rxrpc/stats 474 */ 475 int rxrpc_stats_show(struct seq_file *seq, void *v) 476 { 477 struct rxrpc_net *rxnet = rxrpc_net(seq_file_single_net(seq)); 478 479 seq_printf(seq, 480 "Data : send=%u sendf=%u fail=%u emsz=%u\n", 481 atomic_read(&rxnet->stat_tx_data_send), 482 atomic_read(&rxnet->stat_tx_data_send_frag), 483 atomic_read(&rxnet->stat_tx_data_send_fail), 484 atomic_read(&rxnet->stat_tx_data_send_msgsize)); 485 seq_printf(seq, 486 "Data-Tx : nr=%u retrans=%u uf=%u cwr=%u\n", 487 atomic_read(&rxnet->stat_tx_data), 488 atomic_read(&rxnet->stat_tx_data_retrans), 489 atomic_read(&rxnet->stat_tx_data_underflow), 490 atomic_read(&rxnet->stat_tx_data_cwnd_reset)); 491 seq_printf(seq, 492 "Data-Rx : nr=%u reqack=%u jumbo=%u\n", 493 atomic_read(&rxnet->stat_rx_data), 494 atomic_read(&rxnet->stat_rx_data_reqack), 495 atomic_read(&rxnet->stat_rx_data_jumbo)); 496 seq_printf(seq, 497 "Ack : fill=%u send=%u skip=%u\n", 498 atomic_read(&rxnet->stat_tx_ack_fill), 499 atomic_read(&rxnet->stat_tx_ack_send), 500 atomic_read(&rxnet->stat_tx_ack_skip)); 501 seq_printf(seq, 502 "Ack-Tx : req=%u dup=%u oos=%u exw=%u nos=%u png=%u prs=%u dly=%u idl=%u\n", 503 atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_REQUESTED]), 504 atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_DUPLICATE]), 505 atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_OUT_OF_SEQUENCE]), 506 atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_EXCEEDS_WINDOW]), 507 atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_NOSPACE]), 508 atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_PING]), 509 atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_PING_RESPONSE]), 510 atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_DELAY]), 511 atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_IDLE])); 512 seq_printf(seq, 513 "Ack-Rx : req=%u dup=%u oos=%u exw=%u nos=%u png=%u prs=%u dly=%u idl=%u z=%u\n", 514 atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_REQUESTED]), 515 atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_DUPLICATE]), 516 atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_OUT_OF_SEQUENCE]), 517 atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_EXCEEDS_WINDOW]), 518 atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_NOSPACE]), 519 atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_PING]), 520 atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_PING_RESPONSE]), 521 atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_DELAY]), 522 atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_IDLE]), 523 atomic_read(&rxnet->stat_rx_acks[0])); 524 seq_printf(seq, 525 "Why-Req-A: acklost=%u mrtt=%u ortt=%u stall=%u jwin=%u\n", 526 atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_ack_lost]), 527 atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_more_rtt]), 528 atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_old_rtt]), 529 atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_app_stall]), 530 atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_jumbo_win])); 531 seq_printf(seq, 532 "Why-Req-A: nolast=%u retx=%u slows=%u smtxw=%u\n", 533 atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_no_srv_last]), 534 atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_retrans]), 535 atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_slow_start]), 536 atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_small_txwin])); 537 seq_printf(seq, 538 "Jumbo-Tx : %u,%u,%u,%u,%u,%u,%u,%u,%u,%u\n", 539 atomic_read(&rxnet->stat_tx_jumbo[0]), 540 atomic_read(&rxnet->stat_tx_jumbo[1]), 541 atomic_read(&rxnet->stat_tx_jumbo[2]), 542 atomic_read(&rxnet->stat_tx_jumbo[3]), 543 atomic_read(&rxnet->stat_tx_jumbo[4]), 544 atomic_read(&rxnet->stat_tx_jumbo[5]), 545 atomic_read(&rxnet->stat_tx_jumbo[6]), 546 atomic_read(&rxnet->stat_tx_jumbo[7]), 547 atomic_read(&rxnet->stat_tx_jumbo[8]), 548 atomic_read(&rxnet->stat_tx_jumbo[9])); 549 seq_printf(seq, 550 "Jumbo-Rx : %u,%u,%u,%u,%u,%u,%u,%u,%u,%u\n", 551 atomic_read(&rxnet->stat_rx_jumbo[0]), 552 atomic_read(&rxnet->stat_rx_jumbo[1]), 553 atomic_read(&rxnet->stat_rx_jumbo[2]), 554 atomic_read(&rxnet->stat_rx_jumbo[3]), 555 atomic_read(&rxnet->stat_rx_jumbo[4]), 556 atomic_read(&rxnet->stat_rx_jumbo[5]), 557 atomic_read(&rxnet->stat_rx_jumbo[6]), 558 atomic_read(&rxnet->stat_rx_jumbo[7]), 559 atomic_read(&rxnet->stat_rx_jumbo[8]), 560 atomic_read(&rxnet->stat_rx_jumbo[9])); 561 seq_printf(seq, 562 "Buffers : txb=%u rxb=%u\n", 563 atomic_read(&rxrpc_nr_txbuf), 564 atomic_read(&rxrpc_n_rx_skbs)); 565 seq_printf(seq, 566 "IO-thread: loops=%u\n", 567 atomic_read(&rxnet->stat_io_loop)); 568 return 0; 569 } 570 571 /* 572 * Clear stats if /proc/net/rxrpc/stats is written to. 573 */ 574 int rxrpc_stats_clear(struct file *file, char *buf, size_t size) 575 { 576 struct seq_file *m = file->private_data; 577 struct rxrpc_net *rxnet = rxrpc_net(seq_file_single_net(m)); 578 579 if (size > 1 || (size == 1 && buf[0] != '\n')) 580 return -EINVAL; 581 582 atomic_set(&rxnet->stat_tx_data, 0); 583 atomic_set(&rxnet->stat_tx_data_retrans, 0); 584 atomic_set(&rxnet->stat_tx_data_underflow, 0); 585 atomic_set(&rxnet->stat_tx_data_cwnd_reset, 0); 586 atomic_set(&rxnet->stat_tx_data_send, 0); 587 atomic_set(&rxnet->stat_tx_data_send_frag, 0); 588 atomic_set(&rxnet->stat_tx_data_send_fail, 0); 589 atomic_set(&rxnet->stat_rx_data, 0); 590 atomic_set(&rxnet->stat_rx_data_reqack, 0); 591 atomic_set(&rxnet->stat_rx_data_jumbo, 0); 592 593 atomic_set(&rxnet->stat_tx_ack_fill, 0); 594 atomic_set(&rxnet->stat_tx_ack_send, 0); 595 atomic_set(&rxnet->stat_tx_ack_skip, 0); 596 memset(&rxnet->stat_tx_acks, 0, sizeof(rxnet->stat_tx_acks)); 597 memset(&rxnet->stat_rx_acks, 0, sizeof(rxnet->stat_rx_acks)); 598 memset(&rxnet->stat_tx_jumbo, 0, sizeof(rxnet->stat_tx_jumbo)); 599 memset(&rxnet->stat_rx_jumbo, 0, sizeof(rxnet->stat_rx_jumbo)); 600 601 memset(&rxnet->stat_why_req_ack, 0, sizeof(rxnet->stat_why_req_ack)); 602 603 atomic_set(&rxnet->stat_io_loop, 0); 604 return size; 605 } 606