[PATCH 05/13] SCTP: register per-namespace sysctl.

From: Jan Ariyasu
Date: Sat Aug 04 2012 - 17:33:14 EST


Updated sysctl registration to be per-netns and to use per-net
protocol parameters.

Signed-off-by: Jan Ariyasu <jan.ariyasu@xxxxxx>
---
include/net/sctp/sctp.h | 8 +-
net/sctp/protocol.c | 24 +++++-
net/sctp/sysctl.c | 218 +++++++++++++++++++++++++++++++++++++++++------
3 files changed, 221 insertions(+), 29 deletions(-)

diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index bda317a..eb2ec98 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -381,11 +381,15 @@ static inline void sctp_dbg_objcnt_exit(void) { return; }
#endif /* CONFIG_SCTP_DBG_OBJCOUNT */

#if defined CONFIG_SYSCTL
-void sctp_sysctl_register(void);
+int sctp_sysctl_register(void);
void sctp_sysctl_unregister(void);
+int __net_init sctp_sysctl_init_net(struct net *net);
+void __net_exit sctp_sysctl_exit_net(struct net *net);
#else
-static inline void sctp_sysctl_register(void) { return; }
+static inline int sctp_sysctl_register(void) { return 0; }
static inline void sctp_sysctl_unregister(void) { return; }
+static inline int sctp_sysctl_init_net(struct net *net) { return 0; };
+static inline void sctp_sysctl_exit_net(struct net *net) { return 0; };
#endif

/* Size of Supported Address Parameter for 'x' address types. */
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index dce07d6..32bb8f4e2 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1582,8 +1582,15 @@ static int __net_init sctp_net_init(struct net *net)
if (err)
goto err_param_init;

+#ifdef CONFIG_SYSCTL
+ err = sctp_sysctl_init_net(net);
+ if (err)
+ goto err_param_init;
+#endif
+
sctp_get_local_addr_list(net);
goto out;
+
err_param_init:
sctp_proc_exit(net);
err_proc_init:
@@ -1601,6 +1608,10 @@ static void __net_exit sctp_net_exit(struct net *net)
sctp_free_local_addr_list(net);
/* Clean up procfs */
sctp_proc_exit(net);
+#ifdef CONFIG_SYSCTL
+ /* Clean up sysfs */
+ sctp_sysctl_exit_net(net);
+#endif
}

static __net_initdata struct pernet_operations sctp_sk_ops = {
@@ -1671,7 +1682,11 @@ SCTP_STATIC __init int sctp_init(void)
goto err_v6_add_protocol;

/* Set up sysctl parameters. */
- sctp_sysctl_register();
+#ifdef CONFIG_SYSCTL
+ status = sctp_sysctl_register();
+ if (status)
+ goto err_sysctl_init;
+#endif

/*
* Register for pernet packet handling
@@ -1694,10 +1709,13 @@ SCTP_STATIC __init int sctp_init(void)
goto out;

err_mib_init:
- sctp_sysctl_unregister();
sctp_dbg_objcnt_exit();
sctp_ns_exit();
err_ns_init:
+#ifdef CONFIG_SYSCTL
+ sctp_sysctl_unregister();
+#endif
+err_sysctl_init:
sctp_v6_del_protocol();
err_v6_add_protocol:
sctp_v4_del_protocol();
@@ -1735,7 +1753,9 @@ SCTP_STATIC __exit void sctp_exit(void)
sctp_v6_pf_exit();
sctp_v4_pf_exit();

+#ifdef CONFIG_SYSCTL
sctp_sysctl_unregister();
+#endif
sctp_hashtable_globals_free();

sctp_dbg_objcnt_exit();
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 2b2bfe9..0d42d90 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -219,27 +219,6 @@ static ctl_table sctp_table[] = {
.extra2 = &sack_timer_max,
},
{
- .procname = "sctp_mem",
- .data = &sysctl_sctp_mem,
- .maxlen = sizeof(sysctl_sctp_mem),
- .mode = 0644,
- .proc_handler = proc_doulongvec_minmax
- },
- {
- .procname = "sctp_rmem",
- .data = &sysctl_sctp_rmem,
- .maxlen = sizeof(sysctl_sctp_rmem),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
- {
- .procname = "sctp_wmem",
- .data = &sysctl_sctp_wmem,
- .maxlen = sizeof(sysctl_sctp_wmem),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
- {
.procname = "auth_enable",
.data = &sctp_auth_enable,
.maxlen = sizeof(int),
@@ -284,16 +263,205 @@ static ctl_table sctp_table[] = {
{ /* sentinel */ }
};

-static struct ctl_table_header * sctp_sysctl_header;
+static struct ctl_table sctp_mem_table[] = {
+ {
+ .procname = "sctp_mem",
+ .data = &sysctl_sctp_mem,
+ .maxlen = sizeof(sysctl_sctp_mem),
+ .mode = 0644,
+ .proc_handler = proc_doulongvec_minmax
+ },
+ {
+ .procname = "sctp_rmem",
+ .data = &sysctl_sctp_rmem,
+ .maxlen = sizeof(sysctl_sctp_rmem),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
+ .procname = "sctp_wmem",
+ .data = &sysctl_sctp_wmem,
+ .maxlen = sizeof(sysctl_sctp_wmem),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+
+ { /* sentinel */ }
+};
+
+static struct ctl_path sctp_path[] = {
+ { .procname = "net", },
+ { .procname = "sctp", },
+ { }
+};
+
+static struct ctl_table_header *sctp_sysctl_mem_header;

/* Sysctl registration. */
-void sctp_sysctl_register(void)
+int sctp_sysctl_register(void)
{
- sctp_sysctl_header = register_net_sysctl(&init_net, "net/sctp", sctp_table);
+ int err = 0;
+ sctp_sysctl_mem_header = NULL;
+ sctp_sysctl_mem_header = register_sysctl_paths(sctp_path,
+ sctp_mem_table);
+ if (sctp_sysctl_mem_header == NULL) {
+ pr_err("Failed to register sctp_mem_table sysctl path\n");
+ err = -ENOMEM;
+ }
+ return err;
}

/* Sysctl deregistration. */
void sctp_sysctl_unregister(void)
{
- unregister_net_sysctl_table(sctp_sysctl_header);
+ unregister_net_sysctl_table(sctp_sysctl_mem_header);
+}
+
+/* Per-net sysctl registration */
+int __net_init sctp_sysctl_init_net(struct net *net)
+{
+ struct sctp_ns_globals *ns_globals = sctp_get_ns_globals(net);
+ struct sctp_net_params *net_params = sctp_get_params(net);
+ struct ctl_table *table, *tmp_tbl;
+
+ table = sctp_table;
+ if (!net_eq(net, &init_net)) {
+ table = kmemdup(table, sizeof(sctp_table), GFP_KERNEL);
+ if (table == NULL)
+ goto err_alloc;
+
+ for (tmp_tbl = table; tmp_tbl->procname; tmp_tbl++) {
+ if (strcmp(tmp_tbl->procname, "rto_initial") == 0) {
+ tmp_tbl->data = &net_params->rto_initial;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname, "rto_min") == 0) {
+ tmp_tbl->data = &net_params->rto_min;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname, "rto_max") == 0) {
+ tmp_tbl->data = &net_params->rto_max;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname,
+ "valid_cookie_life") == 0) {
+ tmp_tbl->data = &net_params->valid_cookie_life;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname, "max_burst") == 0) {
+ tmp_tbl->data = &net_params->max_burst;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname,
+ "association_max_retrans") == 0) {
+ tmp_tbl->data =
+ &net_params->max_retrans_association;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname, "sndbuf_policy") == 0) {
+ tmp_tbl->data = &net_params->sndbuf_policy;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname, "rcvbuf_policy") == 0) {
+ tmp_tbl->data = &net_params->rcvbuf_policy;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname,
+ "path_max_retrans") == 0) {
+ tmp_tbl->data = &net_params->max_retrans_path;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname, "pf_retrans") == 0) {
+ tmp_tbl->data = &net_params->pf_retrans;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname,
+ "max_init_retransmits") == 0) {
+ tmp_tbl->data = &net_params->max_retrans_init;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname, "hb_interval") == 0) {
+ tmp_tbl->data = &net_params->hb_interval;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname,
+ "cookie_preserve_enable") == 0) {
+ tmp_tbl->data =
+ &net_params->cookie_preserve_enable;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname,
+ "rto_alpha_exp_divisor") == 0) {
+ tmp_tbl->data = &net_params->rto_alpha;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname,
+ "rto_beta_exp_divisor") == 0) {
+ tmp_tbl->data = &net_params->rto_beta;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname, "addip_enable") == 0) {
+ tmp_tbl->data = &net_params->addip_enable;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname,
+ "default_auto_asconf") == 0) {
+ tmp_tbl->data =
+ &net_params->default_auto_asconf;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname, "prsctp_enable") == 0) {
+ tmp_tbl->data = &net_params->prsctp_enable;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname, "sack_timeout") == 0) {
+ tmp_tbl->data = &net_params->sack_timeout;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname, "auth_enable") == 0) {
+ tmp_tbl->data = &net_params->auth_enable;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname,
+ "addip_noauth_enable") == 0) {
+ tmp_tbl->data =
+ &net_params->addip_noauth_enable;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname,
+ "addr_scope_policy") == 0) {
+ tmp_tbl->data = &net_params->ipv4_scope_policy;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname,
+ "rwnd_update_shift") == 0) {
+ tmp_tbl->data = &net_params->rwnd_update_shift;
+ continue;
+ }
+ if (strcmp(tmp_tbl->procname, "max_autoclose") == 0) {
+ tmp_tbl->data = &net_params->max_autoclose;
+ continue;
+ }
+ }
+ }
+ ns_globals->sctp_sysctl_tbl = register_net_sysctl(net,
+ "net/sctp", table);
+ if (ns_globals->sctp_sysctl_tbl == NULL)
+ goto err_reg;
+
+ return 0;
+err_reg:
+ if (!net_eq(net, &init_net))
+ kfree(table);
+
+err_alloc:
+ return -ENOMEM;
+}
+
+void __net_exit sctp_sysctl_exit_net(struct net *net)
+{
+ struct sctp_ns_globals *ns_globals = sctp_get_ns_globals(net);
+ struct ctl_table *table = ns_globals->sctp_sysctl_tbl->ctl_table_arg;
+ unregister_net_sysctl_table(ns_globals->sctp_sysctl_tbl);
+ kfree(table);
}
--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/