添加proc文件,控制sctp的debug输出

通过打开 kernel 的 menuconfig 的SCTP_DBG_MSG 选项可以输出sctp的debug日志。
但是debug消息输出较多,如果没有不需要定位sctp问题时最好能关闭debug日志。现有一需求,能在不更换kernel的情况下控制sctp debug是否开启。
记录下在/proc/sys/net/sctp下添加一配置文件以实现配置日志是否输出的功能。

首先看下SCTP_DBG_MSG 是如何控制日志是否输出的:

kernel\include\net\sctp\sctp.h

/* Print debugging messages.  */
#if SCTP_DEBUG
extern int sctp_debug_flag;
#define SCTP_DEBUG_PRINTK(fmt, args...)			\
do {							\
	if (sctp_debug_flag)				\
		printk(KERN_DEBUG pr_fmt(fmt), ##args);	\
} while (0)
#define SCTP_DEBUG_PRINTK_CONT(fmt, args...)		\
do {							\
	if (sctp_debug_flag)				\
		pr_cont(fmt, ##args);			\
} while (0)
#define SCTP_DEBUG_PRINTK_IPADDR(fmt_lead, fmt_trail,			\
				 args_lead, addr, args_trail...)	\
do {									\
	const union sctp_addr *_addr = (addr);				\
	if (sctp_debug_flag) {						\
		if (_addr->sa.sa_family == AF_INET6) {			\
			printk(KERN_DEBUG				\
			       pr_fmt(fmt_lead "%pI6" fmt_trail),	\
			       args_lead,				\
			       &_addr->v6.sin6_addr,			\
			       args_trail);				\
		} else {						\
			printk(KERN_DEBUG				\
			       pr_fmt(fmt_lead "%pI4" fmt_trail),	\
			       args_lead,				\
			       &_addr->v4.sin_addr.s_addr,		\
			       args_trail);				\
		}							\
	}								\
} while (0)
#define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; }
#define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; }

#define SCTP_ASSERT(expr, str, func) \
	if (!(expr)) { \
		SCTP_DEBUG_PRINTK("Assertion Failed: %s(%s) at %s:%s:%d\n", \
			str, (#expr), __FILE__, __func__, __LINE__); \
		func; \
	}

#else	/* SCTP_DEBUG */

#define SCTP_DEBUG_PRINTK(whatever...)
#define SCTP_DEBUG_PRINTK_CONT(fmt, args...)
#define SCTP_DEBUG_PRINTK_IPADDR(whatever...)
#define SCTP_ENABLE_DEBUG
#define SCTP_DISABLE_DEBUG
#define SCTP_ASSERT(expr, str, func)

#endif /* SCTP_DEBUG */

可以看出如果SCTP_DEBUG宏的值不为0的话就会将输出函数替换为printk,如果为0的话则这些函数为空。
值得注意的是将输出函数替换为printk时会先判断一下变量sctp_debug_flag

	if (sctp_debug_flag)				
		printk(KERN_DEBUG pr_fmt(fmt), ##args);	

这个变量会在定义时赋值为1
kernel\net\sctp\debug.c

#if SCTP_DEBUG
int sctp_debug_flag = 1;	/* Initially enable DEBUG */
#endif	/* SCTP_DEBUG */

那么如果只要将修改sctp_debug_flag的值就可实现开关debug日志的输出。
我们知道,内核和用户空间之间是隔离的,而常见的交互方法是通过/proc /sys等vfs。搜了一下,发现sctp在/proc/sys/net/sctp/下有专门的目录,里面已经放了一些配置选项了,而且有些配置和我们的需求很像,都是通过一个文件配置一个变量。
这些配置文件的实现方法:
LINUX\opensource\kernel\net\sctp\sysctl.c


static ctl_table sctp_net_table[] = {
	{
		.procname	= "rto_initial",
		.data		= &init_net.sctp.rto_initial,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
		.extra1         = &one,
		.extra2         = &timer_max
	},
	{
		.procname	= "rto_min",
		.data		= &init_net.sctp.rto_min,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
		.extra1         = &one,
		.extra2         = &timer_max
	},
	{
		.procname	= "rto_max",
		.data		= &init_net.sctp.rto_max,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
		.extra1         = &one,
		.extra2         = &timer_max
	},
	{
		.procname	= "rto_alpha_exp_divisor",
		.data		= &init_net.sctp.rto_alpha,
		.maxlen		= sizeof(int),
		.mode		= 0444,
		.proc_handler	= proc_dointvec,
	},
	{
		.procname	= "rto_beta_exp_divisor",
		.data		= &init_net.sctp.rto_beta,
		.maxlen		= sizeof(int),
		.mode		= 0444,
		.proc_handler	= proc_dointvec,
	},
	{
		.procname	= "max_burst",
		.data		= &init_net.sctp.max_burst,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
		.extra1		= &zero,
		.extra2		= &int_max
	},
	{
		.procname	= "cookie_preserve_enable",
		.data		= &init_net.sctp.cookie_preserve_enable,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
	{
		.procname	= "cookie_hmac_alg",
		.maxlen		= 8,
		.mode		= 0644,
		.proc_handler	= proc_sctp_do_hmac_alg,
	},
	{
		.procname	= "valid_cookie_life",
		.data		= &init_net.sctp.valid_cookie_life,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
		.extra1         = &one,
		.extra2         = &timer_max
	},
	{
		.procname	= "sack_timeout",
		.data		= &init_net.sctp.sack_timeout,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
		.extra1         = &sack_timer_min,
		.extra2         = &sack_timer_max,
	},
	{
		.procname	= "hb_interval",
		.data		= &init_net.sctp.hb_interval,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
		.extra1         = &one,
		.extra2         = &timer_max
	},
	{
		.procname	= "association_max_retrans",
		.data		= &init_net.sctp.max_retrans_association,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
		.extra1		= &one,
		.extra2		= &int_max
	},
	{
		.procname	= "path_max_retrans",
		.data		= &init_net.sctp.max_retrans_path,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
		.extra1		= &one,
		.extra2		= &int_max
	},
	{
		.procname	= "max_init_retransmits",
		.data		= &init_net.sctp.max_retrans_init,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
		.extra1		= &one,
		.extra2		= &int_max
	},
	{
		.procname	= "pf_retrans",
		.data		= &init_net.sctp.pf_retrans,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
		.extra1		= &zero,
		.extra2		= &int_max
	},
	{
		.procname	= "sndbuf_policy",
		.data		= &init_net.sctp.sndbuf_policy,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
	{
		.procname	= "rcvbuf_policy",
		.data		= &init_net.sctp.rcvbuf_policy,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
	{
		.procname	= "default_auto_asconf",
		.data		= &init_net.sctp.default_auto_asconf,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
	{
		.procname	= "addip_enable",
		.data		= &init_net.sctp.addip_enable,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
	{
		.procname	= "addip_noauth_enable",
		.data		= &init_net.sctp.addip_noauth,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
	{
		.procname	= "prsctp_enable",
		.data		= &init_net.sctp.prsctp_enable,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
	{
		.procname	= "auth_enable",
		.data		= &init_net.sctp.auth_enable,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_sctp_do_auth,
	},
	{
		.procname	= "addr_scope_policy",
		.data		= &init_net.sctp.scope_policy,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
		.extra1		= &zero,
		.extra2		= &addr_scope_max,
	},
	{
		.procname	= "rwnd_update_shift",
		.data		= &init_net.sctp.rwnd_upd_shift,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= &proc_dointvec_minmax,
		.extra1		= &one,
		.extra2		= &rwnd_scale_max,
	},
	{
		.procname	= "max_autoclose",
		.data		= &init_net.sctp.max_autoclose,
		.maxlen		= sizeof(unsigned long),
		.mode		= 0644,
		.proc_handler	= &proc_doulongvec_minmax,
		.extra1		= &max_autoclose_min,
		.extra2		= &max_autoclose_max,
	},

	{ /* sentinel */ }
};

prsctp_enable为例

.procname   文件名
.data          要修改的变量
.maxlen      变量大小
.mode        文件权限
.proc_handler    接口函数

仿照这个格式,添加我们自己的结构:

	{
		.procname	= "sctp_debug_print_enable",
		.data		= &sctp_debug_flag,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},

编译运行后果然生成了 /proc/sys/net/sctp/sctp_debug_print_enable 文件

使用方法

打开debug输出 echo 0 > /proc/sys/net/sctp/sctp_debug_print_enable
关闭debug输出 echo 1 > /proc/sys/net/sctp/sctp_debug_print_enable
查看debug状态 cat /proc/sys/net/sctp/sctp_debug_print_enable

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值