aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/sctp/sctp.h2
-rw-r--r--net/sctp/proc.c141
-rw-r--r--net/sctp/protocol.c3
3 files changed, 146 insertions, 0 deletions
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 90b1e8d23b16..5672d489e924 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -179,6 +179,8 @@ int sctp_eps_proc_init(void);
179void sctp_eps_proc_exit(void); 179void sctp_eps_proc_exit(void);
180int sctp_assocs_proc_init(void); 180int sctp_assocs_proc_init(void);
181void sctp_assocs_proc_exit(void); 181void sctp_assocs_proc_exit(void);
182int sctp_remaddr_proc_init(void);
183void sctp_remaddr_proc_exit(void);
182 184
183 185
184/* 186/*
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 0aba759cb9b7..5dd89831eceb 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -383,3 +383,144 @@ void sctp_assocs_proc_exit(void)
383{ 383{
384 remove_proc_entry("assocs", proc_net_sctp); 384 remove_proc_entry("assocs", proc_net_sctp);
385} 385}
386
387static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos)
388{
389 if (*pos >= sctp_assoc_hashsize)
390 return NULL;
391
392 if (*pos < 0)
393 *pos = 0;
394
395 if (*pos == 0)
396 seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX "
397 "REM_ADDR_RTX START\n");
398
399 return (void *)pos;
400}
401
402static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos)
403{
404 if (++*pos >= sctp_assoc_hashsize)
405 return NULL;
406
407 return pos;
408}
409
410static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v)
411{
412 return;
413}
414
415static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
416{
417 struct sctp_hashbucket *head;
418 struct sctp_ep_common *epb;
419 struct sctp_association *assoc;
420 struct hlist_node *node;
421 struct sctp_transport *tsp;
422 int hash = *(loff_t *)v;
423
424 if (hash >= sctp_assoc_hashsize)
425 return -ENOMEM;
426
427 head = &sctp_assoc_hashtable[hash];
428 sctp_local_bh_disable();
429 read_lock(&head->lock);
430 sctp_for_each_hentry(epb, node, &head->chain) {
431 assoc = sctp_assoc(epb);
432 list_for_each_entry(tsp, &assoc->peer.transport_addr_list,
433 transports) {
434 /*
435 * The remote address (ADDR)
436 */
437 tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr);
438 seq_printf(seq, " ");
439
440 /*
441 * The association ID (ASSOC_ID)
442 */
443 seq_printf(seq, "%d ", tsp->asoc->assoc_id);
444
445 /*
446 * If the Heartbeat is active (HB_ACT)
447 * Note: 1 = Active, 0 = Inactive
448 */
449 seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer));
450
451 /*
452 * Retransmit time out (RTO)
453 */
454 seq_printf(seq, "%lu ", tsp->rto);
455
456 /*
457 * Maximum path retransmit count (PATH_MAX_RTX)
458 */
459 seq_printf(seq, "%d ", tsp->pathmaxrxt);
460
461 /*
462 * remote address retransmit count (REM_ADDR_RTX)
463 * Note: We don't have a way to tally this at the moment
464 * so lets just leave it as zero for the moment
465 */
466 seq_printf(seq, "0 ");
467
468 /*
469 * remote address start time (START). This is also not
470 * currently implemented, but we can record it with a
471 * jiffies marker in a subsequent patch
472 */
473 seq_printf(seq, "0");
474
475 seq_printf(seq, "\n");
476 }
477 }
478
479 read_unlock(&head->lock);
480 sctp_local_bh_enable();
481
482 return 0;
483
484}
485
486static const struct seq_operations sctp_remaddr_ops = {
487 .start = sctp_remaddr_seq_start,
488 .next = sctp_remaddr_seq_next,
489 .stop = sctp_remaddr_seq_stop,
490 .show = sctp_remaddr_seq_show,
491};
492
493/* Cleanup the proc fs entry for 'remaddr' object. */
494void sctp_remaddr_proc_exit(void)
495{
496 remove_proc_entry("remaddr", proc_net_sctp);
497}
498
499static int sctp_remaddr_seq_open(struct inode *inode, struct file *file)
500{
501 return seq_open(file, &sctp_remaddr_ops);
502}
503
504static const struct file_operations sctp_remaddr_seq_fops = {
505 .open = sctp_remaddr_seq_open,
506 .read = seq_read,
507 .llseek = seq_lseek,
508 .release = seq_release,
509};
510
511int __init sctp_remaddr_proc_init(void)
512{
513 struct proc_dir_entry *p;
514
515 p = create_proc_entry("remaddr", S_IRUGO, proc_net_sctp);
516 if (!p)
517 return -ENOMEM;
518 p->proc_fops = &sctp_remaddr_seq_fops;
519
520 return 0;
521}
522
523void sctp_assoc_proc_exit(void)
524{
525 remove_proc_entry("remaddr", proc_net_sctp);
526}
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 0ec234b762c2..b8bd9e014498 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -113,6 +113,8 @@ static __init int sctp_proc_init(void)
113 goto out_nomem; 113 goto out_nomem;
114 if (sctp_assocs_proc_init()) 114 if (sctp_assocs_proc_init())
115 goto out_nomem; 115 goto out_nomem;
116 if (sctp_remaddr_proc_init())
117 goto out_nomem;
116 118
117 return 0; 119 return 0;
118 120
@@ -129,6 +131,7 @@ static void sctp_proc_exit(void)
129 sctp_snmp_proc_exit(); 131 sctp_snmp_proc_exit();
130 sctp_eps_proc_exit(); 132 sctp_eps_proc_exit();
131 sctp_assocs_proc_exit(); 133 sctp_assocs_proc_exit();
134 sctp_remaddr_proc_exit();
132 135
133 if (proc_net_sctp) { 136 if (proc_net_sctp) {
134 proc_net_sctp = NULL; 137 proc_net_sctp = NULL;