18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/* SCTP kernel implementation
38c2ecf20Sopenharmony_ci * (C) Copyright IBM Corp. 2001, 2004
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This file is part of the SCTP kernel implementation
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Support for memory object debugging.  This allows one to monitor the
88c2ecf20Sopenharmony_ci * object allocations/deallocations for types instrumented for this
98c2ecf20Sopenharmony_ci * via the proc fs.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * Please send any bug reports or fixes you make to the
128c2ecf20Sopenharmony_ci * email address(es):
138c2ecf20Sopenharmony_ci *    lksctp developers <linux-sctp@vger.kernel.org>
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * Written or modified by:
168c2ecf20Sopenharmony_ci *    Jon Grimm             <jgrimm@us.ibm.com>
178c2ecf20Sopenharmony_ci */
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include <linux/kernel.h>
228c2ecf20Sopenharmony_ci#include <net/sctp/sctp.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci/*
258c2ecf20Sopenharmony_ci * Global counters to count raw object allocation counts.
268c2ecf20Sopenharmony_ci * To add new counters, choose a unique suffix for the variable
278c2ecf20Sopenharmony_ci * name as the helper macros key off this suffix to make
288c2ecf20Sopenharmony_ci * life easier for the programmer.
298c2ecf20Sopenharmony_ci */
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ciSCTP_DBG_OBJCNT(sock);
328c2ecf20Sopenharmony_ciSCTP_DBG_OBJCNT(ep);
338c2ecf20Sopenharmony_ciSCTP_DBG_OBJCNT(transport);
348c2ecf20Sopenharmony_ciSCTP_DBG_OBJCNT(assoc);
358c2ecf20Sopenharmony_ciSCTP_DBG_OBJCNT(bind_addr);
368c2ecf20Sopenharmony_ciSCTP_DBG_OBJCNT(bind_bucket);
378c2ecf20Sopenharmony_ciSCTP_DBG_OBJCNT(chunk);
388c2ecf20Sopenharmony_ciSCTP_DBG_OBJCNT(addr);
398c2ecf20Sopenharmony_ciSCTP_DBG_OBJCNT(datamsg);
408c2ecf20Sopenharmony_ciSCTP_DBG_OBJCNT(keys);
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* An array to make it easy to pretty print the debug information
438c2ecf20Sopenharmony_ci * to the proc fs.
448c2ecf20Sopenharmony_ci */
458c2ecf20Sopenharmony_cistatic struct sctp_dbg_objcnt_entry sctp_dbg_objcnt[] = {
468c2ecf20Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(sock),
478c2ecf20Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(ep),
488c2ecf20Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(assoc),
498c2ecf20Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(transport),
508c2ecf20Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(chunk),
518c2ecf20Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(bind_addr),
528c2ecf20Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(bind_bucket),
538c2ecf20Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(addr),
548c2ecf20Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(datamsg),
558c2ecf20Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(keys),
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/* Callback from procfs to read out objcount information.
598c2ecf20Sopenharmony_ci * Walk through the entries in the sctp_dbg_objcnt array, dumping
608c2ecf20Sopenharmony_ci * the raw object counts for each monitored type.
618c2ecf20Sopenharmony_ci */
628c2ecf20Sopenharmony_cistatic int sctp_objcnt_seq_show(struct seq_file *seq, void *v)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	int i;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	i = (int)*(loff_t *)v;
678c2ecf20Sopenharmony_ci	seq_setwidth(seq, 127);
688c2ecf20Sopenharmony_ci	seq_printf(seq, "%s: %d", sctp_dbg_objcnt[i].label,
698c2ecf20Sopenharmony_ci				atomic_read(sctp_dbg_objcnt[i].counter));
708c2ecf20Sopenharmony_ci	seq_pad(seq, '\n');
718c2ecf20Sopenharmony_ci	return 0;
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic void *sctp_objcnt_seq_start(struct seq_file *seq, loff_t *pos)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	return (*pos >= ARRAY_SIZE(sctp_dbg_objcnt)) ? NULL : (void *)pos;
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistatic void sctp_objcnt_seq_stop(struct seq_file *seq, void *v)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_cistatic void *sctp_objcnt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	++*pos;
868c2ecf20Sopenharmony_ci	return (*pos >= ARRAY_SIZE(sctp_dbg_objcnt)) ? NULL : (void *)pos;
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistatic const struct seq_operations sctp_objcnt_seq_ops = {
908c2ecf20Sopenharmony_ci	.start = sctp_objcnt_seq_start,
918c2ecf20Sopenharmony_ci	.next  = sctp_objcnt_seq_next,
928c2ecf20Sopenharmony_ci	.stop  = sctp_objcnt_seq_stop,
938c2ecf20Sopenharmony_ci	.show  = sctp_objcnt_seq_show,
948c2ecf20Sopenharmony_ci};
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci/* Initialize the objcount in the proc filesystem.  */
978c2ecf20Sopenharmony_civoid sctp_dbg_objcnt_init(struct net *net)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	struct proc_dir_entry *ent;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	ent = proc_create_seq("sctp_dbg_objcnt", 0,
1028c2ecf20Sopenharmony_ci			  net->sctp.proc_net_sctp, &sctp_objcnt_seq_ops);
1038c2ecf20Sopenharmony_ci	if (!ent)
1048c2ecf20Sopenharmony_ci		pr_warn("sctp_dbg_objcnt: Unable to create /proc entry.\n");
1058c2ecf20Sopenharmony_ci}
106