aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/proc.c')
-rw-r--r--net/sctp/proc.c316
1 files changed, 173 insertions, 143 deletions
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 0697eda5aed8..dfa7eeccb537 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -281,88 +281,136 @@ void sctp_eps_proc_exit(struct net *net)
281 remove_proc_entry("eps", net->sctp.proc_net_sctp); 281 remove_proc_entry("eps", net->sctp.proc_net_sctp);
282} 282}
283 283
284struct sctp_ht_iter {
285 struct seq_net_private p;
286 struct rhashtable_iter hti;
287};
284 288
285static void *sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos) 289static struct sctp_transport *sctp_transport_get_next(struct seq_file *seq)
286{ 290{
287 if (*pos >= sctp_assoc_hashsize) 291 struct sctp_ht_iter *iter = seq->private;
288 return NULL; 292 struct sctp_transport *t;
289 293
290 if (*pos < 0) 294 t = rhashtable_walk_next(&iter->hti);
291 *pos = 0; 295 for (; t; t = rhashtable_walk_next(&iter->hti)) {
296 if (IS_ERR(t)) {
297 if (PTR_ERR(t) == -EAGAIN)
298 continue;
299 break;
300 }
292 301
293 if (*pos == 0) 302 if (net_eq(sock_net(t->asoc->base.sk), seq_file_net(seq)) &&
294 seq_printf(seq, " ASSOC SOCK STY SST ST HBKT " 303 t->asoc->peer.primary_path == t)
295 "ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT " 304 break;
296 "RPORT LADDRS <-> RADDRS " 305 }
297 "HBINT INS OUTS MAXRT T1X T2X RTXC "
298 "wmema wmemq sndbuf rcvbuf\n");
299 306
300 return (void *)pos; 307 return t;
301} 308}
302 309
303static void sctp_assocs_seq_stop(struct seq_file *seq, void *v) 310static struct sctp_transport *sctp_transport_get_idx(struct seq_file *seq,
311 loff_t pos)
312{
313 void *obj;
314
315 while (pos && (obj = sctp_transport_get_next(seq)) && !IS_ERR(obj))
316 pos--;
317
318 return obj;
319}
320
321static int sctp_transport_walk_start(struct seq_file *seq)
304{ 322{
323 struct sctp_ht_iter *iter = seq->private;
324 int err;
325
326 err = rhashtable_walk_init(&sctp_transport_hashtable, &iter->hti);
327 if (err)
328 return err;
329
330 err = rhashtable_walk_start(&iter->hti);
331
332 return err == -EAGAIN ? 0 : err;
305} 333}
306 334
335static void sctp_transport_walk_stop(struct seq_file *seq)
336{
337 struct sctp_ht_iter *iter = seq->private;
338
339 rhashtable_walk_stop(&iter->hti);
340 rhashtable_walk_exit(&iter->hti);
341}
342
343static void *sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
344{
345 int err = sctp_transport_walk_start(seq);
346
347 if (err)
348 return ERR_PTR(err);
349
350 return *pos ? sctp_transport_get_idx(seq, *pos) : SEQ_START_TOKEN;
351}
352
353static void sctp_assocs_seq_stop(struct seq_file *seq, void *v)
354{
355 sctp_transport_walk_stop(seq);
356}
307 357
308static void *sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos) 358static void *sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
309{ 359{
310 if (++*pos >= sctp_assoc_hashsize) 360 ++*pos;
311 return NULL;
312 361
313 return pos; 362 return sctp_transport_get_next(seq);
314} 363}
315 364
316/* Display sctp associations (/proc/net/sctp/assocs). */ 365/* Display sctp associations (/proc/net/sctp/assocs). */
317static int sctp_assocs_seq_show(struct seq_file *seq, void *v) 366static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
318{ 367{
319 struct sctp_hashbucket *head; 368 struct sctp_transport *transport;
320 struct sctp_ep_common *epb;
321 struct sctp_association *assoc; 369 struct sctp_association *assoc;
370 struct sctp_ep_common *epb;
322 struct sock *sk; 371 struct sock *sk;
323 int hash = *(loff_t *)v;
324
325 if (hash >= sctp_assoc_hashsize)
326 return -ENOMEM;
327 372
328 head = &sctp_assoc_hashtable[hash]; 373 if (v == SEQ_START_TOKEN) {
329 local_bh_disable(); 374 seq_printf(seq, " ASSOC SOCK STY SST ST HBKT "
330 read_lock(&head->lock); 375 "ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
331 sctp_for_each_hentry(epb, &head->chain) { 376 "RPORT LADDRS <-> RADDRS "
332 assoc = sctp_assoc(epb); 377 "HBINT INS OUTS MAXRT T1X T2X RTXC "
333 sk = epb->sk; 378 "wmema wmemq sndbuf rcvbuf\n");
334 if (!net_eq(sock_net(sk), seq_file_net(seq))) 379 return 0;
335 continue;
336 seq_printf(seq,
337 "%8pK %8pK %-3d %-3d %-2d %-4d "
338 "%4d %8d %8d %7u %5lu %-5d %5d ",
339 assoc, sk, sctp_sk(sk)->type, sk->sk_state,
340 assoc->state, hash,
341 assoc->assoc_id,
342 assoc->sndbuf_used,
343 atomic_read(&assoc->rmem_alloc),
344 from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
345 sock_i_ino(sk),
346 epb->bind_addr.port,
347 assoc->peer.port);
348 seq_printf(seq, " ");
349 sctp_seq_dump_local_addrs(seq, epb);
350 seq_printf(seq, "<-> ");
351 sctp_seq_dump_remote_addrs(seq, assoc);
352 seq_printf(seq, "\t%8lu %5d %5d %4d %4d %4d %8d "
353 "%8d %8d %8d %8d",
354 assoc->hbinterval, assoc->c.sinit_max_instreams,
355 assoc->c.sinit_num_ostreams, assoc->max_retrans,
356 assoc->init_retries, assoc->shutdown_retries,
357 assoc->rtx_data_chunks,
358 atomic_read(&sk->sk_wmem_alloc),
359 sk->sk_wmem_queued,
360 sk->sk_sndbuf,
361 sk->sk_rcvbuf);
362 seq_printf(seq, "\n");
363 } 380 }
364 read_unlock(&head->lock); 381
365 local_bh_enable(); 382 transport = (struct sctp_transport *)v;
383 assoc = transport->asoc;
384 epb = &assoc->base;
385 sk = epb->sk;
386
387 seq_printf(seq,
388 "%8pK %8pK %-3d %-3d %-2d %-4d "
389 "%4d %8d %8d %7u %5lu %-5d %5d ",
390 assoc, sk, sctp_sk(sk)->type, sk->sk_state,
391 assoc->state, 0,
392 assoc->assoc_id,
393 assoc->sndbuf_used,
394 atomic_read(&assoc->rmem_alloc),
395 from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)),
396 sock_i_ino(sk),
397 epb->bind_addr.port,
398 assoc->peer.port);
399 seq_printf(seq, " ");
400 sctp_seq_dump_local_addrs(seq, epb);
401 seq_printf(seq, "<-> ");
402 sctp_seq_dump_remote_addrs(seq, assoc);
403 seq_printf(seq, "\t%8lu %5d %5d %4d %4d %4d %8d "
404 "%8d %8d %8d %8d",
405 assoc->hbinterval, assoc->c.sinit_max_instreams,
406 assoc->c.sinit_num_ostreams, assoc->max_retrans,
407 assoc->init_retries, assoc->shutdown_retries,
408 assoc->rtx_data_chunks,
409 atomic_read(&sk->sk_wmem_alloc),
410 sk->sk_wmem_queued,
411 sk->sk_sndbuf,
412 sk->sk_rcvbuf);
413 seq_printf(seq, "\n");
366 414
367 return 0; 415 return 0;
368} 416}
@@ -378,7 +426,7 @@ static const struct seq_operations sctp_assoc_ops = {
378static int sctp_assocs_seq_open(struct inode *inode, struct file *file) 426static int sctp_assocs_seq_open(struct inode *inode, struct file *file)
379{ 427{
380 return seq_open_net(inode, file, &sctp_assoc_ops, 428 return seq_open_net(inode, file, &sctp_assoc_ops,
381 sizeof(struct seq_net_private)); 429 sizeof(struct sctp_ht_iter));
382} 430}
383 431
384static const struct file_operations sctp_assocs_seq_fops = { 432static const struct file_operations sctp_assocs_seq_fops = {
@@ -409,112 +457,94 @@ void sctp_assocs_proc_exit(struct net *net)
409 457
410static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos) 458static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos)
411{ 459{
412 if (*pos >= sctp_assoc_hashsize) 460 int err = sctp_transport_walk_start(seq);
413 return NULL;
414
415 if (*pos < 0)
416 *pos = 0;
417 461
418 if (*pos == 0) 462 if (err)
419 seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX " 463 return ERR_PTR(err);
420 "REM_ADDR_RTX START STATE\n");
421 464
422 return (void *)pos; 465 return *pos ? sctp_transport_get_idx(seq, *pos) : SEQ_START_TOKEN;
423} 466}
424 467
425static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos) 468static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos)
426{ 469{
427 if (++*pos >= sctp_assoc_hashsize) 470 ++*pos;
428 return NULL;
429 471
430 return pos; 472 return sctp_transport_get_next(seq);
431} 473}
432 474
433static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v) 475static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v)
434{ 476{
477 sctp_transport_walk_stop(seq);
435} 478}
436 479
437static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) 480static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
438{ 481{
439 struct sctp_hashbucket *head;
440 struct sctp_ep_common *epb;
441 struct sctp_association *assoc; 482 struct sctp_association *assoc;
442 struct sctp_transport *tsp; 483 struct sctp_transport *tsp;
443 int hash = *(loff_t *)v;
444 484
445 if (hash >= sctp_assoc_hashsize) 485 if (v == SEQ_START_TOKEN) {
446 return -ENOMEM; 486 seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX "
487 "REM_ADDR_RTX START STATE\n");
488 return 0;
489 }
447 490
448 head = &sctp_assoc_hashtable[hash]; 491 tsp = (struct sctp_transport *)v;
449 local_bh_disable(); 492 assoc = tsp->asoc;
450 read_lock(&head->lock); 493
451 rcu_read_lock(); 494 list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list,
452 sctp_for_each_hentry(epb, &head->chain) { 495 transports) {
453 if (!net_eq(sock_net(epb->sk), seq_file_net(seq))) 496 if (tsp->dead)
454 continue; 497 continue;
455 assoc = sctp_assoc(epb); 498 /*
456 list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list, 499 * The remote address (ADDR)
457 transports) { 500 */
458 if (tsp->dead) 501 tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr);
459 continue; 502 seq_printf(seq, " ");
503 /*
504 * The association ID (ASSOC_ID)
505 */
506 seq_printf(seq, "%d ", tsp->asoc->assoc_id);
507
508 /*
509 * If the Heartbeat is active (HB_ACT)
510 * Note: 1 = Active, 0 = Inactive
511 */
512 seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer));
513
514 /*
515 * Retransmit time out (RTO)
516 */
517 seq_printf(seq, "%lu ", tsp->rto);
518
519 /*
520 * Maximum path retransmit count (PATH_MAX_RTX)
521 */
522 seq_printf(seq, "%d ", tsp->pathmaxrxt);
523
524 /*
525 * remote address retransmit count (REM_ADDR_RTX)
526 * Note: We don't have a way to tally this at the moment
527 * so lets just leave it as zero for the moment
528 */
529 seq_puts(seq, "0 ");
530
531 /*
532 * remote address start time (START). This is also not
533 * currently implemented, but we can record it with a
534 * jiffies marker in a subsequent patch
535 */
536 seq_puts(seq, "0 ");
537
538 /*
539 * The current state of this destination. I.e.
540 * SCTP_ACTIVE, SCTP_INACTIVE, ...
541 */
542 seq_printf(seq, "%d", tsp->state);
460 543
461 /* 544 seq_printf(seq, "\n");
462 * The remote address (ADDR)
463 */
464 tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr);
465 seq_printf(seq, " ");
466
467 /*
468 * The association ID (ASSOC_ID)
469 */
470 seq_printf(seq, "%d ", tsp->asoc->assoc_id);
471
472 /*
473 * If the Heartbeat is active (HB_ACT)
474 * Note: 1 = Active, 0 = Inactive
475 */
476 seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer));
477
478 /*
479 * Retransmit time out (RTO)
480 */
481 seq_printf(seq, "%lu ", tsp->rto);
482
483 /*
484 * Maximum path retransmit count (PATH_MAX_RTX)
485 */
486 seq_printf(seq, "%d ", tsp->pathmaxrxt);
487
488 /*
489 * remote address retransmit count (REM_ADDR_RTX)
490 * Note: We don't have a way to tally this at the moment
491 * so lets just leave it as zero for the moment
492 */
493 seq_puts(seq, "0 ");
494
495 /*
496 * remote address start time (START). This is also not
497 * currently implemented, but we can record it with a
498 * jiffies marker in a subsequent patch
499 */
500 seq_puts(seq, "0 ");
501
502 /*
503 * The current state of this destination. I.e.
504 * SCTP_ACTIVE, SCTP_INACTIVE, ...
505 */
506 seq_printf(seq, "%d", tsp->state);
507
508 seq_printf(seq, "\n");
509 }
510 } 545 }
511 546
512 rcu_read_unlock();
513 read_unlock(&head->lock);
514 local_bh_enable();
515
516 return 0; 547 return 0;
517
518} 548}
519 549
520static const struct seq_operations sctp_remaddr_ops = { 550static const struct seq_operations sctp_remaddr_ops = {
@@ -533,7 +563,7 @@ void sctp_remaddr_proc_exit(struct net *net)
533static int sctp_remaddr_seq_open(struct inode *inode, struct file *file) 563static int sctp_remaddr_seq_open(struct inode *inode, struct file *file)
534{ 564{
535 return seq_open_net(inode, file, &sctp_remaddr_ops, 565 return seq_open_net(inode, file, &sctp_remaddr_ops,
536 sizeof(struct seq_net_private)); 566 sizeof(struct sctp_ht_iter));
537} 567}
538 568
539static const struct file_operations sctp_remaddr_seq_fops = { 569static const struct file_operations sctp_remaddr_seq_fops = {