Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/sctp/proc.c
15109 views
1
/* SCTP kernel implementation
2
* Copyright (c) 2003 International Business Machines, Corp.
3
*
4
* This file is part of the SCTP kernel implementation
5
*
6
* This SCTP implementation is free software;
7
* you can redistribute it and/or modify it under the terms of
8
* the GNU General Public License as published by
9
* the Free Software Foundation; either version 2, or (at your option)
10
* any later version.
11
*
12
* This SCTP implementation is distributed in the hope that it
13
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
14
* ************************
15
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
* See the GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU General Public License
19
* along with GNU CC; see the file COPYING. If not, write to
20
* the Free Software Foundation, 59 Temple Place - Suite 330,
21
* Boston, MA 02111-1307, USA.
22
*
23
* Please send any bug reports or fixes you make to the
24
* email address(es):
25
* lksctp developers <[email protected]>
26
*
27
* Or submit a bug report through the following website:
28
* http://www.sf.net/projects/lksctp
29
*
30
* Written or modified by:
31
* Sridhar Samudrala <[email protected]>
32
*
33
* Any bugs reported given to us we will try to fix... any fixes shared will
34
* be incorporated into the next SCTP release.
35
*/
36
37
#include <linux/types.h>
38
#include <linux/seq_file.h>
39
#include <linux/init.h>
40
#include <net/sctp/sctp.h>
41
#include <net/ip.h> /* for snmp_fold_field */
42
43
static const struct snmp_mib sctp_snmp_list[] = {
44
SNMP_MIB_ITEM("SctpCurrEstab", SCTP_MIB_CURRESTAB),
45
SNMP_MIB_ITEM("SctpActiveEstabs", SCTP_MIB_ACTIVEESTABS),
46
SNMP_MIB_ITEM("SctpPassiveEstabs", SCTP_MIB_PASSIVEESTABS),
47
SNMP_MIB_ITEM("SctpAborteds", SCTP_MIB_ABORTEDS),
48
SNMP_MIB_ITEM("SctpShutdowns", SCTP_MIB_SHUTDOWNS),
49
SNMP_MIB_ITEM("SctpOutOfBlues", SCTP_MIB_OUTOFBLUES),
50
SNMP_MIB_ITEM("SctpChecksumErrors", SCTP_MIB_CHECKSUMERRORS),
51
SNMP_MIB_ITEM("SctpOutCtrlChunks", SCTP_MIB_OUTCTRLCHUNKS),
52
SNMP_MIB_ITEM("SctpOutOrderChunks", SCTP_MIB_OUTORDERCHUNKS),
53
SNMP_MIB_ITEM("SctpOutUnorderChunks", SCTP_MIB_OUTUNORDERCHUNKS),
54
SNMP_MIB_ITEM("SctpInCtrlChunks", SCTP_MIB_INCTRLCHUNKS),
55
SNMP_MIB_ITEM("SctpInOrderChunks", SCTP_MIB_INORDERCHUNKS),
56
SNMP_MIB_ITEM("SctpInUnorderChunks", SCTP_MIB_INUNORDERCHUNKS),
57
SNMP_MIB_ITEM("SctpFragUsrMsgs", SCTP_MIB_FRAGUSRMSGS),
58
SNMP_MIB_ITEM("SctpReasmUsrMsgs", SCTP_MIB_REASMUSRMSGS),
59
SNMP_MIB_ITEM("SctpOutSCTPPacks", SCTP_MIB_OUTSCTPPACKS),
60
SNMP_MIB_ITEM("SctpInSCTPPacks", SCTP_MIB_INSCTPPACKS),
61
SNMP_MIB_ITEM("SctpT1InitExpireds", SCTP_MIB_T1_INIT_EXPIREDS),
62
SNMP_MIB_ITEM("SctpT1CookieExpireds", SCTP_MIB_T1_COOKIE_EXPIREDS),
63
SNMP_MIB_ITEM("SctpT2ShutdownExpireds", SCTP_MIB_T2_SHUTDOWN_EXPIREDS),
64
SNMP_MIB_ITEM("SctpT3RtxExpireds", SCTP_MIB_T3_RTX_EXPIREDS),
65
SNMP_MIB_ITEM("SctpT4RtoExpireds", SCTP_MIB_T4_RTO_EXPIREDS),
66
SNMP_MIB_ITEM("SctpT5ShutdownGuardExpireds", SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS),
67
SNMP_MIB_ITEM("SctpDelaySackExpireds", SCTP_MIB_DELAY_SACK_EXPIREDS),
68
SNMP_MIB_ITEM("SctpAutocloseExpireds", SCTP_MIB_AUTOCLOSE_EXPIREDS),
69
SNMP_MIB_ITEM("SctpT3Retransmits", SCTP_MIB_T3_RETRANSMITS),
70
SNMP_MIB_ITEM("SctpPmtudRetransmits", SCTP_MIB_PMTUD_RETRANSMITS),
71
SNMP_MIB_ITEM("SctpFastRetransmits", SCTP_MIB_FAST_RETRANSMITS),
72
SNMP_MIB_ITEM("SctpInPktSoftirq", SCTP_MIB_IN_PKT_SOFTIRQ),
73
SNMP_MIB_ITEM("SctpInPktBacklog", SCTP_MIB_IN_PKT_BACKLOG),
74
SNMP_MIB_ITEM("SctpInPktDiscards", SCTP_MIB_IN_PKT_DISCARDS),
75
SNMP_MIB_ITEM("SctpInDataChunkDiscards", SCTP_MIB_IN_DATA_CHUNK_DISCARDS),
76
SNMP_MIB_SENTINEL
77
};
78
79
/* Display sctp snmp mib statistics(/proc/net/sctp/snmp). */
80
static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
81
{
82
int i;
83
84
for (i = 0; sctp_snmp_list[i].name != NULL; i++)
85
seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name,
86
snmp_fold_field((void __percpu **)sctp_statistics,
87
sctp_snmp_list[i].entry));
88
89
return 0;
90
}
91
92
/* Initialize the seq file operations for 'snmp' object. */
93
static int sctp_snmp_seq_open(struct inode *inode, struct file *file)
94
{
95
return single_open(file, sctp_snmp_seq_show, NULL);
96
}
97
98
static const struct file_operations sctp_snmp_seq_fops = {
99
.owner = THIS_MODULE,
100
.open = sctp_snmp_seq_open,
101
.read = seq_read,
102
.llseek = seq_lseek,
103
.release = single_release,
104
};
105
106
/* Set up the proc fs entry for 'snmp' object. */
107
int __init sctp_snmp_proc_init(void)
108
{
109
struct proc_dir_entry *p;
110
111
p = proc_create("snmp", S_IRUGO, proc_net_sctp, &sctp_snmp_seq_fops);
112
if (!p)
113
return -ENOMEM;
114
115
return 0;
116
}
117
118
/* Cleanup the proc fs entry for 'snmp' object. */
119
void sctp_snmp_proc_exit(void)
120
{
121
remove_proc_entry("snmp", proc_net_sctp);
122
}
123
124
/* Dump local addresses of an association/endpoint. */
125
static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb)
126
{
127
struct sctp_association *asoc;
128
struct sctp_sockaddr_entry *laddr;
129
struct sctp_transport *peer;
130
union sctp_addr *addr, *primary = NULL;
131
struct sctp_af *af;
132
133
if (epb->type == SCTP_EP_TYPE_ASSOCIATION) {
134
asoc = sctp_assoc(epb);
135
peer = asoc->peer.primary_path;
136
primary = &peer->saddr;
137
}
138
139
list_for_each_entry(laddr, &epb->bind_addr.address_list, list) {
140
addr = &laddr->a;
141
af = sctp_get_af_specific(addr->sa.sa_family);
142
if (primary && af->cmp_addr(addr, primary)) {
143
seq_printf(seq, "*");
144
}
145
af->seq_dump_addr(seq, addr);
146
}
147
}
148
149
/* Dump remote addresses of an association. */
150
static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_association *assoc)
151
{
152
struct sctp_transport *transport;
153
union sctp_addr *addr, *primary;
154
struct sctp_af *af;
155
156
primary = &assoc->peer.primary_addr;
157
list_for_each_entry(transport, &assoc->peer.transport_addr_list,
158
transports) {
159
addr = &transport->ipaddr;
160
af = sctp_get_af_specific(addr->sa.sa_family);
161
if (af->cmp_addr(addr, primary)) {
162
seq_printf(seq, "*");
163
}
164
af->seq_dump_addr(seq, addr);
165
}
166
}
167
168
static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
169
{
170
if (*pos >= sctp_ep_hashsize)
171
return NULL;
172
173
if (*pos < 0)
174
*pos = 0;
175
176
if (*pos == 0)
177
seq_printf(seq, " ENDPT SOCK STY SST HBKT LPORT UID INODE LADDRS\n");
178
179
return (void *)pos;
180
}
181
182
static void sctp_eps_seq_stop(struct seq_file *seq, void *v)
183
{
184
}
185
186
187
static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
188
{
189
if (++*pos >= sctp_ep_hashsize)
190
return NULL;
191
192
return pos;
193
}
194
195
196
/* Display sctp endpoints (/proc/net/sctp/eps). */
197
static int sctp_eps_seq_show(struct seq_file *seq, void *v)
198
{
199
struct sctp_hashbucket *head;
200
struct sctp_ep_common *epb;
201
struct sctp_endpoint *ep;
202
struct sock *sk;
203
struct hlist_node *node;
204
int hash = *(loff_t *)v;
205
206
if (hash >= sctp_ep_hashsize)
207
return -ENOMEM;
208
209
head = &sctp_ep_hashtable[hash];
210
sctp_local_bh_disable();
211
read_lock(&head->lock);
212
sctp_for_each_hentry(epb, node, &head->chain) {
213
ep = sctp_ep(epb);
214
sk = epb->sk;
215
seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
216
sctp_sk(sk)->type, sk->sk_state, hash,
217
epb->bind_addr.port,
218
sock_i_uid(sk), sock_i_ino(sk));
219
220
sctp_seq_dump_local_addrs(seq, epb);
221
seq_printf(seq, "\n");
222
}
223
read_unlock(&head->lock);
224
sctp_local_bh_enable();
225
226
return 0;
227
}
228
229
static const struct seq_operations sctp_eps_ops = {
230
.start = sctp_eps_seq_start,
231
.next = sctp_eps_seq_next,
232
.stop = sctp_eps_seq_stop,
233
.show = sctp_eps_seq_show,
234
};
235
236
237
/* Initialize the seq file operations for 'eps' object. */
238
static int sctp_eps_seq_open(struct inode *inode, struct file *file)
239
{
240
return seq_open(file, &sctp_eps_ops);
241
}
242
243
static const struct file_operations sctp_eps_seq_fops = {
244
.open = sctp_eps_seq_open,
245
.read = seq_read,
246
.llseek = seq_lseek,
247
.release = seq_release,
248
};
249
250
/* Set up the proc fs entry for 'eps' object. */
251
int __init sctp_eps_proc_init(void)
252
{
253
struct proc_dir_entry *p;
254
255
p = proc_create("eps", S_IRUGO, proc_net_sctp, &sctp_eps_seq_fops);
256
if (!p)
257
return -ENOMEM;
258
259
return 0;
260
}
261
262
/* Cleanup the proc fs entry for 'eps' object. */
263
void sctp_eps_proc_exit(void)
264
{
265
remove_proc_entry("eps", proc_net_sctp);
266
}
267
268
269
static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
270
{
271
if (*pos >= sctp_assoc_hashsize)
272
return NULL;
273
274
if (*pos < 0)
275
*pos = 0;
276
277
if (*pos == 0)
278
seq_printf(seq, " ASSOC SOCK STY SST ST HBKT "
279
"ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
280
"RPORT LADDRS <-> RADDRS "
281
"HBINT INS OUTS MAXRT T1X T2X RTXC\n");
282
283
return (void *)pos;
284
}
285
286
static void sctp_assocs_seq_stop(struct seq_file *seq, void *v)
287
{
288
}
289
290
291
static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
292
{
293
if (++*pos >= sctp_assoc_hashsize)
294
return NULL;
295
296
return pos;
297
}
298
299
/* Display sctp associations (/proc/net/sctp/assocs). */
300
static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
301
{
302
struct sctp_hashbucket *head;
303
struct sctp_ep_common *epb;
304
struct sctp_association *assoc;
305
struct sock *sk;
306
struct hlist_node *node;
307
int hash = *(loff_t *)v;
308
309
if (hash >= sctp_assoc_hashsize)
310
return -ENOMEM;
311
312
head = &sctp_assoc_hashtable[hash];
313
sctp_local_bh_disable();
314
read_lock(&head->lock);
315
sctp_for_each_hentry(epb, node, &head->chain) {
316
assoc = sctp_assoc(epb);
317
sk = epb->sk;
318
seq_printf(seq,
319
"%8pK %8pK %-3d %-3d %-2d %-4d "
320
"%4d %8d %8d %7d %5lu %-5d %5d ",
321
assoc, sk, sctp_sk(sk)->type, sk->sk_state,
322
assoc->state, hash,
323
assoc->assoc_id,
324
assoc->sndbuf_used,
325
atomic_read(&assoc->rmem_alloc),
326
sock_i_uid(sk), sock_i_ino(sk),
327
epb->bind_addr.port,
328
assoc->peer.port);
329
seq_printf(seq, " ");
330
sctp_seq_dump_local_addrs(seq, epb);
331
seq_printf(seq, "<-> ");
332
sctp_seq_dump_remote_addrs(seq, assoc);
333
seq_printf(seq, "\t%8lu %5d %5d %4d %4d %4d %8d ",
334
assoc->hbinterval, assoc->c.sinit_max_instreams,
335
assoc->c.sinit_num_ostreams, assoc->max_retrans,
336
assoc->init_retries, assoc->shutdown_retries,
337
assoc->rtx_data_chunks);
338
seq_printf(seq, "\n");
339
}
340
read_unlock(&head->lock);
341
sctp_local_bh_enable();
342
343
return 0;
344
}
345
346
static const struct seq_operations sctp_assoc_ops = {
347
.start = sctp_assocs_seq_start,
348
.next = sctp_assocs_seq_next,
349
.stop = sctp_assocs_seq_stop,
350
.show = sctp_assocs_seq_show,
351
};
352
353
/* Initialize the seq file operations for 'assocs' object. */
354
static int sctp_assocs_seq_open(struct inode *inode, struct file *file)
355
{
356
return seq_open(file, &sctp_assoc_ops);
357
}
358
359
static const struct file_operations sctp_assocs_seq_fops = {
360
.open = sctp_assocs_seq_open,
361
.read = seq_read,
362
.llseek = seq_lseek,
363
.release = seq_release,
364
};
365
366
/* Set up the proc fs entry for 'assocs' object. */
367
int __init sctp_assocs_proc_init(void)
368
{
369
struct proc_dir_entry *p;
370
371
p = proc_create("assocs", S_IRUGO, proc_net_sctp,
372
&sctp_assocs_seq_fops);
373
if (!p)
374
return -ENOMEM;
375
376
return 0;
377
}
378
379
/* Cleanup the proc fs entry for 'assocs' object. */
380
void sctp_assocs_proc_exit(void)
381
{
382
remove_proc_entry("assocs", proc_net_sctp);
383
}
384
385
static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos)
386
{
387
if (*pos >= sctp_assoc_hashsize)
388
return NULL;
389
390
if (*pos < 0)
391
*pos = 0;
392
393
if (*pos == 0)
394
seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX "
395
"REM_ADDR_RTX START\n");
396
397
return (void *)pos;
398
}
399
400
static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos)
401
{
402
if (++*pos >= sctp_assoc_hashsize)
403
return NULL;
404
405
return pos;
406
}
407
408
static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v)
409
{
410
}
411
412
static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
413
{
414
struct sctp_hashbucket *head;
415
struct sctp_ep_common *epb;
416
struct sctp_association *assoc;
417
struct hlist_node *node;
418
struct sctp_transport *tsp;
419
int hash = *(loff_t *)v;
420
421
if (hash >= sctp_assoc_hashsize)
422
return -ENOMEM;
423
424
head = &sctp_assoc_hashtable[hash];
425
sctp_local_bh_disable();
426
read_lock(&head->lock);
427
sctp_for_each_hentry(epb, node, &head->chain) {
428
assoc = sctp_assoc(epb);
429
list_for_each_entry(tsp, &assoc->peer.transport_addr_list,
430
transports) {
431
/*
432
* The remote address (ADDR)
433
*/
434
tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr);
435
seq_printf(seq, " ");
436
437
/*
438
* The association ID (ASSOC_ID)
439
*/
440
seq_printf(seq, "%d ", tsp->asoc->assoc_id);
441
442
/*
443
* If the Heartbeat is active (HB_ACT)
444
* Note: 1 = Active, 0 = Inactive
445
*/
446
seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer));
447
448
/*
449
* Retransmit time out (RTO)
450
*/
451
seq_printf(seq, "%lu ", tsp->rto);
452
453
/*
454
* Maximum path retransmit count (PATH_MAX_RTX)
455
*/
456
seq_printf(seq, "%d ", tsp->pathmaxrxt);
457
458
/*
459
* remote address retransmit count (REM_ADDR_RTX)
460
* Note: We don't have a way to tally this at the moment
461
* so lets just leave it as zero for the moment
462
*/
463
seq_printf(seq, "0 ");
464
465
/*
466
* remote address start time (START). This is also not
467
* currently implemented, but we can record it with a
468
* jiffies marker in a subsequent patch
469
*/
470
seq_printf(seq, "0");
471
472
seq_printf(seq, "\n");
473
}
474
}
475
476
read_unlock(&head->lock);
477
sctp_local_bh_enable();
478
479
return 0;
480
481
}
482
483
static const struct seq_operations sctp_remaddr_ops = {
484
.start = sctp_remaddr_seq_start,
485
.next = sctp_remaddr_seq_next,
486
.stop = sctp_remaddr_seq_stop,
487
.show = sctp_remaddr_seq_show,
488
};
489
490
/* Cleanup the proc fs entry for 'remaddr' object. */
491
void sctp_remaddr_proc_exit(void)
492
{
493
remove_proc_entry("remaddr", proc_net_sctp);
494
}
495
496
static int sctp_remaddr_seq_open(struct inode *inode, struct file *file)
497
{
498
return seq_open(file, &sctp_remaddr_ops);
499
}
500
501
static const struct file_operations sctp_remaddr_seq_fops = {
502
.open = sctp_remaddr_seq_open,
503
.read = seq_read,
504
.llseek = seq_lseek,
505
.release = seq_release,
506
};
507
508
int __init sctp_remaddr_proc_init(void)
509
{
510
struct proc_dir_entry *p;
511
512
p = proc_create("remaddr", S_IRUGO, proc_net_sctp, &sctp_remaddr_seq_fops);
513
if (!p)
514
return -ENOMEM;
515
return 0;
516
}
517
518