netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 0/5] nf protos pernet functionality fresh attempt
@ 2009-03-26 16:05 Cyrill Gorcunov
  2009-03-26 16:05 ` [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol Cyrill Gorcunov
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Cyrill Gorcunov @ 2009-03-26 16:05 UTC (permalink / raw)
  To: kaber, netfilter-devel, xemul, daniel.lezcano

Here is freshly ported patches over nf-next-2.6 tree

Cyrill

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol
  2009-03-26 16:05 [patch 0/5] nf protos pernet functionality fresh attempt Cyrill Gorcunov
@ 2009-03-26 16:05 ` Cyrill Gorcunov
  2009-03-26 16:16   ` Patrick McHardy
  2009-03-26 16:05 ` [patch 2/5] net: netfilter conntrack - add per-net functionality for SCTP protocol Cyrill Gorcunov
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Cyrill Gorcunov @ 2009-03-26 16:05 UTC (permalink / raw)
  To: kaber, netfilter-devel, xemul, daniel.lezcano; +Cc: Cyrill Gorcunov

[-- Attachment #1: net-nf-conntrack-proto-icmp --]
[-- Type: text/plain, Size: 5389 bytes --]

Module specific data moved into per-net site and being allocated/freed
during net namespace creation/deletion. For this reason module_init/exit
calls added.

Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
 net/ipv4/netfilter/nf_conntrack_proto_icmp.c |  128 +++++++++++++++++++++++++--
 1 file changed, 120 insertions(+), 8 deletions(-)

Index: linux-2.6.git/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
===================================================================
--- linux-2.6.git.orig/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ linux-2.6.git/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
+#include <linux/module.h>
 #include <linux/in.h>
 #include <linux/icmp.h>
 #include <linux/seq_file.h>
@@ -20,7 +21,27 @@
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_log.h>
 
-static unsigned int nf_ct_icmp_timeout __read_mostly = 30*HZ;
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
+/* per-net specifics */
+static int icmp_net_id;
+struct icmp_net {
+	unsigned int icmp_timeout;
+#ifdef CONFIG_SYSCTL
+	struct ctl_table_header *sysctl_header;
+	struct ctl_table *sysctl_table;
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	struct ctl_table_header *compat_sysctl_header;
+	struct ctl_table *compat_sysctl_table;
+#endif
+#endif
+};
+
+static inline struct icmp_net *icmp_pernet(struct net *net)
+{
+	return net_generic(net, icmp_net_id);
+}
 
 static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
 			      struct nf_conntrack_tuple *tuple)
@@ -90,9 +111,10 @@ static int icmp_packet(struct nf_conn *c
 		if (atomic_dec_and_test(&ct->proto.icmp.count))
 			nf_ct_kill_acct(ct, ctinfo, skb);
 	} else {
+		struct icmp_net *in = icmp_pernet(nf_ct_net(ct));
 		atomic_inc(&ct->proto.icmp.count);
 		nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct);
-		nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout);
+		nf_ct_refresh_acct(ct, ctinfo, skb, in->icmp_timeout);
 	}
 
 	return NF_ACCEPT;
@@ -270,11 +292,10 @@ static int icmp_nlattr_tuple_size(void)
 #endif
 
 #ifdef CONFIG_SYSCTL
-static struct ctl_table_header *icmp_sysctl_header;
+/* templates, data assigned later */
 static struct ctl_table icmp_sysctl_table[] = {
 	{
 		.procname	= "nf_conntrack_icmp_timeout",
-		.data		= &nf_ct_icmp_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -287,7 +308,6 @@ static struct ctl_table icmp_sysctl_tabl
 static struct ctl_table icmp_compat_sysctl_table[] = {
 	{
 		.procname	= "ip_conntrack_icmp_timeout",
-		.data		= &nf_ct_icmp_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -318,11 +338,103 @@ struct nf_conntrack_l4proto nf_conntrack
 	.nlattr_to_tuple	= icmp_nlattr_to_tuple,
 	.nla_policy		= icmp_nla_policy,
 #endif
+};
+
+static __net_init int icmp_net_init(struct net *net)
+{
+	struct icmp_net *in;
+	int err;
+
+	in = kmalloc(sizeof(*in), GFP_KERNEL);
+	if (!in)
+		return -ENOMEM;
+
+	/* default values */
+	in->icmp_timeout = 30 * HZ;
+
+	err = net_assign_generic(net, icmp_net_id, in);
+	if (err)
+		goto out;
+
+#ifdef CONFIG_SYSCTL
+	err = -ENOMEM;
+	in->sysctl_table = kmemdup(icmp_sysctl_table,
+			sizeof(icmp_sysctl_table), GFP_KERNEL);
+	if (!in->sysctl_table)
+		goto out;
+
+	in->sysctl_table[0].data = &in->icmp_timeout;
+
+	in->sysctl_header = register_net_sysctl_table(net,
+			nf_net_netfilter_sysctl_path, in->sysctl_table);
+	if (!in->sysctl_header)
+		goto out_free;
+
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	in->compat_sysctl_table = kmemdup(icmp_compat_sysctl_table,
+			sizeof(icmp_compat_sysctl_table), GFP_KERNEL);
+	if (!in->compat_sysctl_table)
+		goto out_sysctl;
+
+	in->compat_sysctl_table[0].data = &in->icmp_timeout;
+
+	in->compat_sysctl_header = register_net_sysctl_table(net,
+			nf_net_ipv4_netfilter_sysctl_path,
+			in->compat_sysctl_table);
+	if (!in->compat_sysctl_header)
+		goto out_free_compat;
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+#endif /* CONFIG_SYSCTL */
+
+	return 0;
+
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+out_free_compat:
+	kfree(in->compat_sysctl_table);
+#endif
+out_sysctl:
+	unregister_net_sysctl_table(in->sysctl_header);
+out_free:
+	kfree(in->sysctl_table);
+#endif
+
+out:
+	kfree(in);
+	return err;
+}
+
+static __net_exit void icmp_net_exit(struct net *net)
+{
+	struct icmp_net *in = icmp_pernet(net);
 #ifdef CONFIG_SYSCTL
-	.ctl_table_header	= &icmp_sysctl_header,
-	.ctl_table		= icmp_sysctl_table,
+	unregister_net_sysctl_table(in->sysctl_header);
+	kfree(in->sysctl_table);
 #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
-	.ctl_compat_table	= icmp_compat_sysctl_table,
+	unregister_net_sysctl_table(in->compat_sysctl_header);
+	kfree(in->compat_sysctl_table);
 #endif
 #endif
+	kfree(in);
+
+	net_assign_generic(net, icmp_net_id, NULL);
+}
+
+static struct pernet_operations icmp_net_ops = {
+	.init = icmp_net_init,
+	.exit = icmp_net_exit,
 };
+
+int __init nf_ct_icmp_proto_init(void)
+{
+	return register_pernet_gen_subsys(&icmp_net_id, &icmp_net_ops);
+}
+
+void __exit nf_ct_icmp_proto_fini(void)
+{
+	unregister_pernet_gen_subsys(icmp_net_id, &icmp_net_ops);
+}
+
+module_init(nf_ct_icmp_proto_init);
+module_exit(nf_ct_icmp_proto_fini);
+MODULE_LICENSE("GPL");


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [patch 2/5] net: netfilter conntrack - add per-net functionality for SCTP protocol
  2009-03-26 16:05 [patch 0/5] nf protos pernet functionality fresh attempt Cyrill Gorcunov
  2009-03-26 16:05 ` [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol Cyrill Gorcunov
@ 2009-03-26 16:05 ` Cyrill Gorcunov
  2009-03-26 16:05 ` [patch 3/5] net: netfilter conntrack - add per-net functionality for TCP protocol Cyrill Gorcunov
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 14+ messages in thread
From: Cyrill Gorcunov @ 2009-03-26 16:05 UTC (permalink / raw)
  To: kaber, netfilter-devel, xemul, daniel.lezcano; +Cc: Cyrill Gorcunov

[-- Attachment #1: net-nf-conntrack-proto-sctp --]
[-- Type: text/plain, Size: 11164 bytes --]

Module specific data moved into per-net site and being allocated/freed
during net namespace creation/deletion.

Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
 net/netfilter/nf_conntrack_proto_sctp.c |  179 ++++++++++++++++++++++++--------
 1 file changed, 139 insertions(+), 40 deletions(-)

Index: linux-2.6.git/net/netfilter/nf_conntrack_proto_sctp.c
===================================================================
--- linux-2.6.git.orig/net/netfilter/nf_conntrack_proto_sctp.c
+++ linux-2.6.git/net/netfilter/nf_conntrack_proto_sctp.c
@@ -21,6 +21,9 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
@@ -49,16 +52,6 @@ static const char *const sctp_conntrack_
 #define HOURS * 60 MINS
 #define DAYS  * 24 HOURS
 
-static unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX] __read_mostly = {
-	[SCTP_CONNTRACK_CLOSED]			= 10 SECS,
-	[SCTP_CONNTRACK_COOKIE_WAIT]		= 3 SECS,
-	[SCTP_CONNTRACK_COOKIE_ECHOED]		= 3 SECS,
-	[SCTP_CONNTRACK_ESTABLISHED]		= 5 DAYS,
-	[SCTP_CONNTRACK_SHUTDOWN_SENT]		= 300 SECS / 1000,
-	[SCTP_CONNTRACK_SHUTDOWN_RECD]		= 300 SECS / 1000,
-	[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT]	= 3 SECS,
-};
-
 #define sNO SCTP_CONNTRACK_NONE
 #define	sCL SCTP_CONNTRACK_CLOSED
 #define	sCW SCTP_CONNTRACK_COOKIE_WAIT
@@ -130,6 +123,25 @@ static const u8 sctp_conntracks[2][9][SC
 	}
 };
 
+/* this module per-net specifics */
+static int sctp_net_id;
+struct sctp_net {
+	unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX];
+#ifdef CONFIG_SYSCTL
+	struct ctl_table_header *sysctl_header;
+	struct ctl_table *sysctl_table;
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	struct ctl_table_header *compat_sysctl_header;
+	struct ctl_table *compat_sysctl_table;
+#endif
+#endif
+};
+
+static inline struct sctp_net *sctp_pernet(struct net *net)
+{
+	return net_generic(net, sctp_net_id);
+}
+
 static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
 			      struct nf_conntrack_tuple *tuple)
 {
@@ -297,6 +309,7 @@ static int sctp_packet(struct nf_conn *c
 	const struct sctp_chunkhdr *sch;
 	struct sctp_chunkhdr _sch;
 	u_int32_t offset, count;
+	struct sctp_net *sn;
 	unsigned long map[256 / sizeof(unsigned long)] = { 0 };
 
 	sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
@@ -373,7 +386,8 @@ static int sctp_packet(struct nf_conn *c
 	}
 	write_unlock_bh(&sctp_lock);
 
-	nf_ct_refresh_acct(ct, ctinfo, skb, sctp_timeouts[new_state]);
+	sn = sctp_pernet(nf_ct_net(ct));
+	nf_ct_refresh_acct(ct, ctinfo, skb, sn->sctp_timeouts[new_state]);
 
 	if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED &&
 	    dir == IP_CT_DIR_REPLY &&
@@ -546,54 +560,46 @@ static int sctp_nlattr_size(void)
 #endif
 
 #ifdef CONFIG_SYSCTL
-static unsigned int sctp_sysctl_table_users;
-static struct ctl_table_header *sctp_sysctl_header;
+/* templates, data assigned later */
 static struct ctl_table sctp_sysctl_table[] = {
 	{
 		.procname	= "nf_conntrack_sctp_timeout_closed",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_sctp_timeout_cookie_wait",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_sctp_timeout_cookie_echoed",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_sctp_timeout_established",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_sctp_timeout_shutdown_sent",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_sctp_timeout_shutdown_recd",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_sctp_timeout_shutdown_ack_sent",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -607,49 +613,42 @@ static struct ctl_table sctp_sysctl_tabl
 static struct ctl_table sctp_compat_sysctl_table[] = {
 	{
 		.procname	= "ip_conntrack_sctp_timeout_closed",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_sctp_timeout_cookie_wait",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_sctp_timeout_cookie_echoed",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_sctp_timeout_established",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_sctp_timeout_shutdown_sent",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_sctp_timeout_shutdown_recd",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_sctp_timeout_shutdown_ack_sent",
-		.data		= &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -659,7 +658,7 @@ static struct ctl_table sctp_compat_sysc
 	}
 };
 #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
-#endif
+#endif /* CONFIG_SYSCTL */
 
 static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
 	.l3proto		= PF_INET,
@@ -681,14 +680,6 @@ static struct nf_conntrack_l4proto nf_co
 	.nlattr_to_tuple	= nf_ct_port_nlattr_to_tuple,
 	.nla_policy		= nf_ct_port_nla_policy,
 #endif
-#ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &sctp_sysctl_table_users,
-	.ctl_table_header	= &sctp_sysctl_header,
-	.ctl_table		= sctp_sysctl_table,
-#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
-	.ctl_compat_table	= sctp_compat_sysctl_table,
-#endif
-#endif
 };
 
 static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
@@ -711,21 +702,126 @@ static struct nf_conntrack_l4proto nf_co
 	.nlattr_to_tuple	= nf_ct_port_nlattr_to_tuple,
 	.nla_policy		= nf_ct_port_nla_policy,
 #endif
+};
+
+static __net_init int sctp_net_init(struct net *net)
+{
+	struct sctp_net *sn;
+	int err;
+
+	sn = kmalloc(sizeof(*sn), GFP_KERNEL);
+	if (!sn)
+		return -ENOMEM;
+
+	/* default values */
+	sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED]	= 10 SECS;
+	sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT]	= 3 SECS;
+	sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED]	= 3 SECS;
+	sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED]	= 5 DAYS;
+	sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT]	= 300 SECS / 1000;
+	sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD]	= 300 SECS / 1000;
+	sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS;
+
+	err = net_assign_generic(net, sctp_net_id, sn);
+	if (err)
+		goto out;
+
+	/*
+	 * Pin per-net data to sysctl tables
+	 *
+	 * We allocate new ctrl tables from predefined templates
+	 * and then assign .data fields iteratively, we allowed
+	 * to do so since SCTP_CONNTRACK_... (enum sctp_conntrack)
+	 * is a part of userspace ABI and it's hardly that the enum
+	 * entries will be rearranged
+	 */
+
 #ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &sctp_sysctl_table_users,
-	.ctl_table_header	= &sctp_sysctl_header,
-	.ctl_table		= sctp_sysctl_table,
+	{
+	int i;
+	err = -ENOMEM;
+	sn->sysctl_table = kmemdup(sctp_sysctl_table,
+			sizeof(sctp_sysctl_table), GFP_KERNEL);
+	if (!sn->sysctl_table)
+		goto out;
+
+	for (i = SCTP_CONNTRACK_CLOSED; i < SCTP_CONNTRACK_MAX; i++)
+		sn->sysctl_table[i - 1].data = &sn->sctp_timeouts[i];
+
+	sn->sysctl_header = register_net_sysctl_table(net,
+			nf_net_netfilter_sysctl_path, sn->sysctl_table);
+	if (!sn->sysctl_header)
+		goto out_free;
+
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	sn->compat_sysctl_table = kmemdup(sctp_compat_sysctl_table,
+			sizeof(sctp_compat_sysctl_table), GFP_KERNEL);
+	if (!sn->compat_sysctl_table)
+		goto out_sysctl;
+
+	for (i = SCTP_CONNTRACK_CLOSED; i < SCTP_CONNTRACK_MAX; i++)
+		sn->compat_sysctl_table[err - 1].data = &sn->sctp_timeouts[i];
+
+	sn->compat_sysctl_header = register_net_sysctl_table(net,
+			nf_net_ipv4_netfilter_sysctl_path, sn->compat_sysctl_table);
+	if (!sn->compat_sysctl_header)
+		goto out_free_compat;
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+	}
+#endif /* CONFIG_SYSCTL */
+
+	return 0;
+
+#ifdef CONFIG_SYSCTL
+
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+out_free_compat:
+	kfree(sn->compat_sysctl_table);
+#endif
+out_sysctl:
+	unregister_net_sysctl_table(sn->sysctl_header);
+out_free:
+	kfree(sn->sysctl_table);
+#endif
+
+out:
+	kfree(sn);
+	return err;
+}
+
+static __net_exit void sctp_net_exit(struct net *net)
+{
+	struct sctp_net *sn = sctp_pernet(net);
+#ifdef CONFIG_SYSCTL
+	unregister_net_sysctl_table(sn->sysctl_header);
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	unregister_net_sysctl_table(sn->compat_sysctl_header);
+	kfree(sn->compat_sysctl_table);
 #endif
+	kfree(sn->sysctl_table);
+#endif
+	kfree(sn);
+
+	net_assign_generic(net, sctp_net_id, NULL);
+}
+
+static struct pernet_operations sctp_net_ops = {
+	.init = sctp_net_init,
+	.exit = sctp_net_exit,
 };
 
 static int __init nf_conntrack_proto_sctp_init(void)
 {
 	int ret;
 
+	ret = register_pernet_gen_subsys(&sctp_net_id, &sctp_net_ops);
+	if (ret < 0)
+		goto out;
+
 	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp4);
 	if (ret) {
 		printk("nf_conntrack_l4proto_sctp4: protocol register failed\n");
-		goto out;
+		goto cleanup_net;
 	}
 	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp6);
 	if (ret) {
@@ -737,6 +833,8 @@ static int __init nf_conntrack_proto_sct
 
  cleanup_sctp4:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
+ cleanup_net:
+	unregister_pernet_gen_subsys(sctp_net_id, &sctp_net_ops);
  out:
 	return ret;
 }
@@ -745,6 +843,7 @@ static void __exit nf_conntrack_proto_sc
 {
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
+	unregister_pernet_gen_subsys(sctp_net_id, &sctp_net_ops);
 }
 
 module_init(nf_conntrack_proto_sctp_init);


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [patch 3/5] net: netfilter conntrack - add per-net functionality for TCP protocol
  2009-03-26 16:05 [patch 0/5] nf protos pernet functionality fresh attempt Cyrill Gorcunov
  2009-03-26 16:05 ` [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol Cyrill Gorcunov
  2009-03-26 16:05 ` [patch 2/5] net: netfilter conntrack - add per-net functionality for SCTP protocol Cyrill Gorcunov
@ 2009-03-26 16:05 ` Cyrill Gorcunov
  2009-03-26 16:05 ` [patch 4/5] net: netfilter conntrack - add per-net functionality for UDP protocol Cyrill Gorcunov
  2009-03-26 16:05 ` [patch 5/5] net: netfilter conntrack - add per-net functionality for UDPLITE protocol Cyrill Gorcunov
  4 siblings, 0 replies; 14+ messages in thread
From: Cyrill Gorcunov @ 2009-03-26 16:05 UTC (permalink / raw)
  To: kaber, netfilter-devel, xemul, daniel.lezcano; +Cc: Cyrill Gorcunov

[-- Attachment #1: net-nf-conntrack-proto-tcp --]
[-- Type: text/plain, Size: 17781 bytes --]

Module specific data moved into per-net site and being allocated/freed
during net namespace creation/deletion. For this reason module_init/exit
calls added.

Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
 net/netfilter/nf_conntrack_proto_tcp.c |  281 +++++++++++++++++++++++----------
 1 file changed, 203 insertions(+), 78 deletions(-)

Index: linux-2.6.git/net/netfilter/nf_conntrack_proto_tcp.c
===================================================================
--- linux-2.6.git.orig/net/netfilter/nf_conntrack_proto_tcp.c
+++ linux-2.6.git/net/netfilter/nf_conntrack_proto_tcp.c
@@ -18,6 +18,9 @@
 
 #include <net/tcp.h>
 
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
@@ -31,20 +34,6 @@
 /* Protects ct->proto.tcp */
 static DEFINE_RWLOCK(tcp_lock);
 
-/* "Be conservative in what you do,
-    be liberal in what you accept from others."
-    If it's non-zero, we mark only out of window RST segments as INVALID. */
-static int nf_ct_tcp_be_liberal __read_mostly = 0;
-
-/* If it is set to zero, we disable picking up already established
-   connections. */
-static int nf_ct_tcp_loose __read_mostly = 1;
-
-/* Max number of the retransmitted packets without receiving an (acceptable)
-   ACK from the destination. If this number is reached, a shorter timer
-   will be started. */
-static int nf_ct_tcp_max_retrans __read_mostly = 3;
-
   /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
      closely.  They're more complex. --RR */
 
@@ -66,23 +55,6 @@ static const char *const tcp_conntrack_n
 #define HOURS * 60 MINS
 #define DAYS * 24 HOURS
 
-/* RFC1122 says the R2 limit should be at least 100 seconds.
-   Linux uses 15 packets as limit, which corresponds
-   to ~13-30min depending on RTO. */
-static unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly    =   5 MINS;
-static unsigned int nf_ct_tcp_timeout_unacknowledged __read_mostly =   5 MINS;
-
-static unsigned int tcp_timeouts[TCP_CONNTRACK_MAX] __read_mostly = {
-	[TCP_CONNTRACK_SYN_SENT]	= 2 MINS,
-	[TCP_CONNTRACK_SYN_RECV]	= 60 SECS,
-	[TCP_CONNTRACK_ESTABLISHED]	= 5 DAYS,
-	[TCP_CONNTRACK_FIN_WAIT]	= 2 MINS,
-	[TCP_CONNTRACK_CLOSE_WAIT]	= 60 SECS,
-	[TCP_CONNTRACK_LAST_ACK]	= 30 SECS,
-	[TCP_CONNTRACK_TIME_WAIT]	= 2 MINS,
-	[TCP_CONNTRACK_CLOSE]		= 10 SECS,
-};
-
 #define sNO TCP_CONNTRACK_NONE
 #define sSS TCP_CONNTRACK_SYN_SENT
 #define sSR TCP_CONNTRACK_SYN_RECV
@@ -260,6 +232,51 @@ static const u8 tcp_conntracks[2][6][TCP
 	}
 };
 
+/* per-net specifics */
+static int tcp_net_id;
+struct tcp_net {
+	/*
+	 * "Be conservative in what you do,
+	 * be liberal in what you accept from others."
+	 * If it's non-zero, we mark only out of window
+	 * RST segments as INVALID.
+	 */
+	int tcp_be_liberal;
+	/*
+	 * If it is set to zero, we disable picking up
+	 * already established connections.
+	 */
+	int tcp_loose;
+	/*
+	 * Max number of the retransmitted packets without
+	 * receiving an (acceptable) ACK from the destination.
+	 * If this number is reached, a shorter timer will be started.
+	 */
+	int tcp_max_retrans;
+	/*
+	 * RFC1122 says the R2 limit should be at least 100 seconds.
+	 * Linux uses 15 packets as limit, which corresponds
+	 * to ~13-30min depending on RTO.
+	 */
+	unsigned int tcp_timeout_max_retrans;
+	unsigned int tcp_timeout_unacknowledged;
+
+	unsigned int tcp_timeouts[TCP_CONNTRACK_MAX];
+#ifdef CONFIG_SYSCTL
+	struct ctl_table_header *sysctl_header;
+	struct ctl_table *sysctl_table;
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	struct ctl_table_header *compat_sysctl_header;
+	struct ctl_table *compat_sysctl_table;
+#endif
+#endif
+};
+
+static inline struct tcp_net *tcp_pernet(struct net *net)
+{
+	return net_generic(net, tcp_net_id);
+}
+
 static bool tcp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
 			     struct nf_conntrack_tuple *tuple)
 {
@@ -491,6 +508,7 @@ static bool tcp_in_window(const struct n
 			  u_int8_t pf)
 {
 	struct net *net = nf_ct_net(ct);
+	struct tcp_net *tn;
 	struct ip_ct_tcp_state *sender = &state->seen[dir];
 	struct ip_ct_tcp_state *receiver = &state->seen[!dir];
 	const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
@@ -668,8 +686,9 @@ static bool tcp_in_window(const struct n
 		res = true;
 	} else {
 		res = false;
+		tn = tcp_pernet(net);
 		if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
-		    nf_ct_tcp_be_liberal)
+		    tn->tcp_be_liberal)
 			res = true;
 		if (!res && LOG_INVALID(net, IPPROTO_TCP))
 			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
@@ -812,6 +831,7 @@ static int tcp_packet(struct nf_conn *ct
 		      unsigned int hooknum)
 {
 	struct net *net = nf_ct_net(ct);
+	struct tcp_net *tn;
 	struct nf_conntrack_tuple *tuple;
 	enum tcp_conntrack new_state, old_state;
 	enum ip_conntrack_dir dir;
@@ -950,6 +970,8 @@ static int tcp_packet(struct nf_conn *ct
 	ct->proto.tcp.last_index = index;
 	ct->proto.tcp.last_dir = dir;
 
+	tn = tcp_pernet(net);
+
 	pr_debug("tcp_conntracks: ");
 	nf_ct_dump_tuple(tuple);
 	pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
@@ -962,15 +984,15 @@ static int tcp_packet(struct nf_conn *ct
 	    && new_state == TCP_CONNTRACK_FIN_WAIT)
 		ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
 
-	if (ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans &&
-	    tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans)
-		timeout = nf_ct_tcp_timeout_max_retrans;
+	if (ct->proto.tcp.retrans >= tn->tcp_max_retrans &&
+	    tn->tcp_timeouts[new_state] > tn->tcp_timeout_max_retrans)
+		timeout = tn->tcp_timeout_max_retrans;
 	else if ((ct->proto.tcp.seen[0].flags | ct->proto.tcp.seen[1].flags) &
 		 IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED &&
-		 tcp_timeouts[new_state] > nf_ct_tcp_timeout_unacknowledged)
-		timeout = nf_ct_tcp_timeout_unacknowledged;
+		 tn->tcp_timeouts[new_state] > tn->tcp_timeout_unacknowledged)
+		timeout = tn->tcp_timeout_unacknowledged;
 	else
-		timeout = tcp_timeouts[new_state];
+		timeout = tn->tcp_timeouts[new_state];
 	write_unlock_bh(&tcp_lock);
 
 	nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct);
@@ -1007,6 +1029,7 @@ static bool tcp_new(struct nf_conn *ct, 
 {
 	enum tcp_conntrack new_state;
 	const struct tcphdr *th;
+	struct tcp_net *tn;
 	struct tcphdr _tcph;
 	const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[0];
 	const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[1];
@@ -1025,6 +1048,8 @@ static bool tcp_new(struct nf_conn *ct, 
 		return false;
 	}
 
+	tn = tcp_pernet(nf_ct_net(ct));
+
 	if (new_state == TCP_CONNTRACK_SYN_SENT) {
 		/* SYN packet */
 		ct->proto.tcp.seen[0].td_end =
@@ -1038,7 +1063,7 @@ static bool tcp_new(struct nf_conn *ct, 
 
 		tcp_options(skb, dataoff, th, &ct->proto.tcp.seen[0]);
 		ct->proto.tcp.seen[1].flags = 0;
-	} else if (nf_ct_tcp_loose == 0) {
+	} else if (tn->tcp_loose == 0) {
 		/* Don't try to pick up connections. */
 		return false;
 	} else {
@@ -1197,75 +1222,64 @@ static int tcp_nlattr_tuple_size(void)
 #endif
 
 #ifdef CONFIG_SYSCTL
-static unsigned int tcp_sysctl_table_users;
-static struct ctl_table_header *tcp_sysctl_header;
+/* templates, data assigned later */
 static struct ctl_table tcp_sysctl_table[] = {
 	{
 		.procname	= "nf_conntrack_tcp_timeout_syn_sent",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_SYN_SENT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_syn_recv",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_SYN_RECV],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_established",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_ESTABLISHED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_fin_wait",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_FIN_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_close_wait",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_last_ack",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_LAST_ACK],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_time_wait",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_TIME_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_close",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_CLOSE],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_max_retrans",
-		.data		= &nf_ct_tcp_timeout_max_retrans,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_tcp_timeout_unacknowledged",
-		.data		= &nf_ct_tcp_timeout_unacknowledged,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -1273,7 +1287,6 @@ static struct ctl_table tcp_sysctl_table
 	{
 		.ctl_name	= NET_NF_CONNTRACK_TCP_LOOSE,
 		.procname	= "nf_conntrack_tcp_loose",
-		.data		= &nf_ct_tcp_loose,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
@@ -1281,7 +1294,6 @@ static struct ctl_table tcp_sysctl_table
 	{
 		.ctl_name	= NET_NF_CONNTRACK_TCP_BE_LIBERAL,
 		.procname       = "nf_conntrack_tcp_be_liberal",
-		.data           = &nf_ct_tcp_be_liberal,
 		.maxlen         = sizeof(unsigned int),
 		.mode           = 0644,
 		.proc_handler   = proc_dointvec,
@@ -1289,7 +1301,6 @@ static struct ctl_table tcp_sysctl_table
 	{
 		.ctl_name	= NET_NF_CONNTRACK_TCP_MAX_RETRANS,
 		.procname	= "nf_conntrack_tcp_max_retrans",
-		.data		= &nf_ct_tcp_max_retrans,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
@@ -1303,63 +1314,54 @@ static struct ctl_table tcp_sysctl_table
 static struct ctl_table tcp_compat_sysctl_table[] = {
 	{
 		.procname	= "ip_conntrack_tcp_timeout_syn_sent",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_SYN_SENT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_syn_recv",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_SYN_RECV],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_established",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_ESTABLISHED],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_fin_wait",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_FIN_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_close_wait",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_last_ack",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_LAST_ACK],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_time_wait",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_TIME_WAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_close",
-		.data		= &tcp_timeouts[TCP_CONNTRACK_CLOSE],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_tcp_timeout_max_retrans",
-		.data		= &nf_ct_tcp_timeout_max_retrans,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -1367,7 +1369,6 @@ static struct ctl_table tcp_compat_sysct
 	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_LOOSE,
 		.procname	= "ip_conntrack_tcp_loose",
-		.data		= &nf_ct_tcp_loose,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
@@ -1375,7 +1376,6 @@ static struct ctl_table tcp_compat_sysct
 	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL,
 		.procname	= "ip_conntrack_tcp_be_liberal",
-		.data		= &nf_ct_tcp_be_liberal,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
@@ -1383,7 +1383,6 @@ static struct ctl_table tcp_compat_sysct
 	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS,
 		.procname	= "ip_conntrack_tcp_max_retrans",
-		.data		= &nf_ct_tcp_max_retrans,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
@@ -1416,14 +1415,6 @@ struct nf_conntrack_l4proto nf_conntrack
 	.nlattr_tuple_size	= tcp_nlattr_tuple_size,
 	.nla_policy		= nf_ct_port_nla_policy,
 #endif
-#ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &tcp_sysctl_table_users,
-	.ctl_table_header	= &tcp_sysctl_header,
-	.ctl_table		= tcp_sysctl_table,
-#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
-	.ctl_compat_table	= tcp_compat_sysctl_table,
-#endif
-#endif
 };
 EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4);
 
@@ -1448,10 +1439,144 @@ struct nf_conntrack_l4proto nf_conntrack
 	.nlattr_tuple_size	= tcp_nlattr_tuple_size,
 	.nla_policy		= nf_ct_port_nla_policy,
 #endif
+};
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp6);
+
+static __net_init int tcp_net_init(struct net *net)
+{
+	struct tcp_net *tn;
+	int err;
+
+	tn = kmalloc(sizeof(*tn), GFP_KERNEL);
+	if (!tn)
+		return -ENOMEM;
+
+	/* default values */
+	tn->tcp_be_liberal	= 0;
+	tn->tcp_loose		= 1;
+	tn->tcp_max_retrans	= 3;
+
+	tn->tcp_timeout_max_retrans	= 5 MINS;
+	tn->tcp_timeout_unacknowledged	= 5 MINS;
+
+	tn->tcp_timeouts[TCP_CONNTRACK_SYN_SENT]	= 2 MINS;
+	tn->tcp_timeouts[TCP_CONNTRACK_SYN_RECV]	= 60 SECS;
+	tn->tcp_timeouts[TCP_CONNTRACK_ESTABLISHED]	= 5 DAYS;
+	tn->tcp_timeouts[TCP_CONNTRACK_FIN_WAIT]	= 2 MINS;
+	tn->tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT]	= 60 SECS;
+	tn->tcp_timeouts[TCP_CONNTRACK_LAST_ACK]	= 30 SECS;
+	tn->tcp_timeouts[TCP_CONNTRACK_TIME_WAIT]	= 2 MINS;
+	tn->tcp_timeouts[TCP_CONNTRACK_CLOSE]		= 10 SECS;
+
+	err = net_assign_generic(net, tcp_net_id, tn);
+	if (err)
+		goto out;
+
+	/*
+	 * Pin per-net data to sysctl tables
+	 *
+	 * We allocate new ctrl tables from predefined templates
+	 * and then assign .data fields iteratively, we allowed
+	 * to do so since TCP_CONNTRACK_... (enum tcp_conntrack)
+	 * is a part of userspace ABI and it's hardly that the enum
+	 * entries will be rearranged
+	 */
+
+#ifdef CONFIG_SYSCTL
+	{
+	int i;
+	err = -ENOMEM;
+	tn->sysctl_table = kmemdup(tcp_sysctl_table,
+			sizeof(tcp_sysctl_table), GFP_KERNEL);
+	if (!tn->sysctl_table)
+		goto out;
+
+	for (i = TCP_CONNTRACK_SYN_SENT; i < TCP_CONNTRACK_LISTEN; i++)
+		tn->sysctl_table[i - 1].data = &tn->tcp_timeouts[i];
+
+	tn->sysctl_table[8].data = &tn->tcp_timeout_max_retrans;
+	tn->sysctl_table[9].data = &tn->tcp_timeout_unacknowledged;
+	tn->sysctl_table[10].data = &tn->tcp_loose;
+	tn->sysctl_table[11].data = &tn->tcp_be_liberal;
+	tn->sysctl_table[12].data = &tn->tcp_max_retrans;
+
+	tn->sysctl_header = register_net_sysctl_table(net,
+			nf_net_netfilter_sysctl_path, tn->sysctl_table);
+	if (!tn->sysctl_header)
+		goto out_free;
+
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	tn->compat_sysctl_table = kmemdup(tcp_compat_sysctl_table,
+			sizeof(tcp_compat_sysctl_table), GFP_KERNEL);
+	if (!tn->compat_sysctl_table)
+		goto out_sysctl;
+
+	for (i = TCP_CONNTRACK_SYN_SENT; i < TCP_CONNTRACK_LISTEN; i++)
+		tn->compat_sysctl_table[i - 1].data = &tn->tcp_timeouts[i];
+
+	tn->compat_sysctl_table[8].data = &tn->tcp_timeout_max_retrans;
+	tn->compat_sysctl_table[9].data = &tn->tcp_loose;
+	tn->compat_sysctl_table[10].data = &tn->tcp_be_liberal;
+	tn->compat_sysctl_table[11].data = &tn->tcp_max_retrans;
+
+	tn->compat_sysctl_header = register_net_sysctl_table(net,
+			nf_net_ipv4_netfilter_sysctl_path,
+			tn->compat_sysctl_table);
+	if (!tn->compat_sysctl_header)
+		goto out_free_compat;
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+	}
+#endif /* CONFIG_SYSCTL */
+
+	return 0;
+
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+out_free_compat:
+	kfree(tn->compat_sysctl_table);
+#endif
+out_sysctl:
+	unregister_net_sysctl_table(tn->sysctl_header);
+out_free:
+	kfree(tn->sysctl_table);
+#endif
+
+out:
+	kfree(tn);
+	return err;
+}
+
+static __net_exit void tcp_net_exit(struct net *net)
+{
+	struct tcp_net *tn = tcp_pernet(net);
 #ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &tcp_sysctl_table_users,
-	.ctl_table_header	= &tcp_sysctl_header,
-	.ctl_table		= tcp_sysctl_table,
+	unregister_net_sysctl_table(tn->sysctl_header);
+	kfree(tn->sysctl_table);
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	unregister_net_sysctl_table(tn->compat_sysctl_header);
+	kfree(tn->compat_sysctl_table);
 #endif
+#endif
+	kfree(tn);
+
+	net_assign_generic(net, tcp_net_id, NULL);
 };
-EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp6);
+
+static struct pernet_operations tcp_net_ops = {
+	.init = tcp_net_init,
+	.exit = tcp_net_exit,
+};
+
+static int __init nf_ct_tcp_proto_init(void)
+{
+	return register_pernet_gen_subsys(&tcp_net_id, &tcp_net_ops);
+}
+
+static void __exit nf_ct_tcp_proto_fini(void)
+{
+	unregister_pernet_gen_subsys(tcp_net_id, &tcp_net_ops);
+}
+
+module_init(nf_ct_tcp_proto_init);
+module_exit(nf_ct_tcp_proto_fini);
+MODULE_LICENSE("GPL");


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [patch 4/5] net: netfilter conntrack - add per-net functionality for UDP protocol
  2009-03-26 16:05 [patch 0/5] nf protos pernet functionality fresh attempt Cyrill Gorcunov
                   ` (2 preceding siblings ...)
  2009-03-26 16:05 ` [patch 3/5] net: netfilter conntrack - add per-net functionality for TCP protocol Cyrill Gorcunov
@ 2009-03-26 16:05 ` Cyrill Gorcunov
  2009-03-26 16:05 ` [patch 5/5] net: netfilter conntrack - add per-net functionality for UDPLITE protocol Cyrill Gorcunov
  4 siblings, 0 replies; 14+ messages in thread
From: Cyrill Gorcunov @ 2009-03-26 16:05 UTC (permalink / raw)
  To: kaber, netfilter-devel, xemul, daniel.lezcano; +Cc: Cyrill Gorcunov

[-- Attachment #1: net-nf-conntrack-proto-udp --]
[-- Type: text/plain, Size: 6903 bytes --]

Module specific data moved into per-net site and being allocated/freed
during net namespace creation/deletion. For this reason module_init/exit
calls added.

Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
 net/netfilter/nf_conntrack_proto_udp.c |  152 ++++++++++++++++++++++++++++-----
 1 file changed, 130 insertions(+), 22 deletions(-)

Index: linux-2.6.git/net/netfilter/nf_conntrack_proto_udp.c
===================================================================
--- linux-2.6.git.orig/net/netfilter/nf_conntrack_proto_udp.c
+++ linux-2.6.git/net/netfilter/nf_conntrack_proto_udp.c
@@ -16,6 +16,9 @@
 #include <net/ip6_checksum.h>
 #include <net/checksum.h>
 
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
@@ -25,8 +28,25 @@
 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
 
-static unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
-static unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
+/* per-net specifics */
+static int udp_net_id;
+struct udp_net {
+	unsigned int udp_timeout;
+	unsigned int udp_timeout_stream;
+#ifdef CONFIG_SYSCTL
+	struct ctl_table_header *sysctl_header;
+	struct ctl_table *sysctl_table;
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	struct ctl_table_header *compat_sysctl_header;
+	struct ctl_table *compat_sysctl_table;
+#endif
+#endif
+};
+
+static inline struct udp_net *udp_pernet(struct net *net)
+{
+	return net_generic(net, udp_net_id);
+}
 
 static bool udp_pkt_to_tuple(const struct sk_buff *skb,
 			     unsigned int dataoff,
@@ -71,15 +91,17 @@ static int udp_packet(struct nf_conn *ct
 		      u_int8_t pf,
 		      unsigned int hooknum)
 {
+	struct udp_net *un = udp_pernet(nf_ct_net(ct));
+
 	/* If we've seen traffic both ways, this is some kind of UDP
 	   stream.  Extend timeout. */
 	if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
-		nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout_stream);
+		nf_ct_refresh_acct(ct, ctinfo, skb, un->udp_timeout_stream);
 		/* Also, more likely to be important, and not a probe */
 		if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
 			nf_conntrack_event_cache(IPCT_STATUS, ct);
 	} else
-		nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout);
+		nf_ct_refresh_acct(ct, ctinfo, skb, un->udp_timeout);
 
 	return NF_ACCEPT;
 }
@@ -137,19 +159,16 @@ static int udp_error(struct net *net, st
 }
 
 #ifdef CONFIG_SYSCTL
-static unsigned int udp_sysctl_table_users;
-static struct ctl_table_header *udp_sysctl_header;
+/* templates, data assigned later */
 static struct ctl_table udp_sysctl_table[] = {
 	{
 		.procname	= "nf_conntrack_udp_timeout",
-		.data		= &nf_ct_udp_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_udp_timeout_stream",
-		.data		= &nf_ct_udp_timeout_stream,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -162,14 +181,12 @@ static struct ctl_table udp_sysctl_table
 static struct ctl_table udp_compat_sysctl_table[] = {
 	{
 		.procname	= "ip_conntrack_udp_timeout",
-		.data		= &nf_ct_udp_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_udp_timeout_stream",
-		.data		= &nf_ct_udp_timeout_stream,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -198,14 +215,7 @@ struct nf_conntrack_l4proto nf_conntrack
 	.nlattr_tuple_size	= nf_ct_port_nlattr_tuple_size,
 	.nla_policy		= nf_ct_port_nla_policy,
 #endif
-#ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &udp_sysctl_table_users,
-	.ctl_table_header	= &udp_sysctl_header,
-	.ctl_table		= udp_sysctl_table,
-#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
-	.ctl_compat_table	= udp_compat_sysctl_table,
-#endif
-#endif
+	.me			= THIS_MODULE,
 };
 EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4);
 
@@ -226,10 +236,108 @@ struct nf_conntrack_l4proto nf_conntrack
 	.nlattr_tuple_size	= nf_ct_port_nlattr_tuple_size,
 	.nla_policy		= nf_ct_port_nla_policy,
 #endif
+	.me			= THIS_MODULE,
+};
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6);
+
+static __net_init int udp_net_init(struct net *net)
+{
+	struct udp_net *un;
+	int err;
+
+	un = kmalloc(sizeof(*un), GFP_KERNEL);
+	if (!un)
+		return -ENOMEM;
+
+	/* default values */
+	un->udp_timeout		= 30 * HZ;
+	un->udp_timeout_stream	= 180 * HZ;
+
+	err = net_assign_generic(net, udp_net_id, un);
+	if (err)
+		goto out;
+
+#ifdef CONFIG_SYSCTL
+	err = -ENOMEM;
+	un->sysctl_table = kmemdup(udp_sysctl_table,
+			sizeof(udp_sysctl_table), GFP_KERNEL);
+	if (!un->sysctl_table)
+		goto out;
+
+	un->sysctl_table[0].data = &un->udp_timeout;
+	un->sysctl_table[1].data = &un->udp_timeout_stream;
+
+	un->sysctl_header = register_net_sysctl_table(net,
+			nf_net_netfilter_sysctl_path, un->sysctl_table);
+	if (!un->sysctl_header)
+		goto out_free;
+
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	un->compat_sysctl_table = kmemdup(udp_compat_sysctl_table,
+			sizeof(udp_compat_sysctl_table), GFP_KERNEL);
+	if (!un->compat_sysctl_table)
+		goto out_sysctl;
+
+	un->compat_sysctl_table[0].data = &un->udp_timeout;
+	un->compat_sysctl_table[1].data = &un->udp_timeout_stream;
+
+	un->compat_sysctl_header = register_net_sysctl_table(net,
+			nf_net_ipv4_netfilter_sysctl_path,
+			un->compat_sysctl_table);
+	if (!un->compat_sysctl_header)
+		goto out_free_compat;
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+#endif /* CONFIG_SYSCTL */
+
+	return 0;
+
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+out_free_compat:
+	kfree(un->compat_sysctl_table);
+#endif
+out_sysctl:
+	unregister_net_sysctl_table(un->sysctl_header);
+out_free:
+	kfree(un->sysctl_table);
+#endif
+
+out:
+	kfree(un);
+	return err;
+}
+
+static __net_exit void udp_net_exit(struct net *net)
+{
+	struct udp_net *un = udp_pernet(net);
 #ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &udp_sysctl_table_users,
-	.ctl_table_header	= &udp_sysctl_header,
-	.ctl_table		= udp_sysctl_table,
+	unregister_net_sysctl_table(un->sysctl_header);
+	kfree(un->sysctl_table);
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	unregister_net_sysctl_table(un->compat_sysctl_header);
+	kfree(un->compat_sysctl_table);
 #endif
+#endif
+	kfree(un);
+
+	net_assign_generic(net, udp_net_id, NULL);
+}
+
+static struct pernet_operations udp_net_ops = {
+	.init = udp_net_init,
+	.exit = udp_net_exit,
 };
-EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6);
+
+int __init nf_ct_udp_proto_init(void)
+{
+	return register_pernet_gen_subsys(&udp_net_id, &udp_net_ops);
+}
+
+void __exit nf_ct_udp_proto_fini(void)
+{
+	unregister_pernet_gen_subsys(udp_net_id, &udp_net_ops);
+}
+
+module_init(nf_ct_udp_proto_init);
+module_exit(nf_ct_udp_proto_fini);
+MODULE_LICENSE("GPL");


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [patch 5/5] net: netfilter conntrack - add per-net functionality for UDPLITE protocol
  2009-03-26 16:05 [patch 0/5] nf protos pernet functionality fresh attempt Cyrill Gorcunov
                   ` (3 preceding siblings ...)
  2009-03-26 16:05 ` [patch 4/5] net: netfilter conntrack - add per-net functionality for UDP protocol Cyrill Gorcunov
@ 2009-03-26 16:05 ` Cyrill Gorcunov
  4 siblings, 0 replies; 14+ messages in thread
From: Cyrill Gorcunov @ 2009-03-26 16:05 UTC (permalink / raw)
  To: kaber, netfilter-devel, xemul, daniel.lezcano; +Cc: Cyrill Gorcunov

[-- Attachment #1: net-nf-conntrack-proto-udplite --]
[-- Type: text/plain, Size: 6149 bytes --]

Module specific data moved into per-net site and being allocated/freed
during net namespace creation/deletion.

Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
 net/netfilter/nf_conntrack_proto_udplite.c |  115 ++++++++++++++++++++++++-----
 1 file changed, 96 insertions(+), 19 deletions(-)

Index: linux-2.6.git/net/netfilter/nf_conntrack_proto_udplite.c
===================================================================
--- linux-2.6.git.orig/net/netfilter/nf_conntrack_proto_udplite.c
+++ linux-2.6.git/net/netfilter/nf_conntrack_proto_udplite.c
@@ -17,6 +17,9 @@
 #include <net/ip6_checksum.h>
 #include <net/checksum.h>
 
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
@@ -24,8 +27,21 @@
 #include <net/netfilter/nf_conntrack_ecache.h>
 #include <net/netfilter/nf_log.h>
 
-static unsigned int nf_ct_udplite_timeout __read_mostly = 30*HZ;
-static unsigned int nf_ct_udplite_timeout_stream __read_mostly = 180*HZ;
+/* this module per-net specifics */
+static int udplite_net_id;
+struct udplite_net {
+	unsigned int udplite_timeout;
+	unsigned int udplite_timeout_stream;
+#ifdef CONFIG_SYSCTL
+	struct ctl_table_header *sysctl_header;
+	struct ctl_table *sysctl_table;
+#endif
+};
+
+static inline struct udplite_net *udplite_pernet(struct net *net)
+{
+	return net_generic(net, udplite_net_id);
+}
 
 static bool udplite_pkt_to_tuple(const struct sk_buff *skb,
 				 unsigned int dataoff,
@@ -68,16 +84,18 @@ static int udplite_packet(struct nf_conn
 			  u_int8_t pf,
 			  unsigned int hooknum)
 {
+	struct udplite_net *un = udplite_pernet(nf_ct_net(ct));
+
 	/* If we've seen traffic both ways, this is some kind of UDP
 	   stream.  Extend timeout. */
 	if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
 		nf_ct_refresh_acct(ct, ctinfo, skb,
-				   nf_ct_udplite_timeout_stream);
+				   un->udplite_timeout_stream);
 		/* Also, more likely to be important, and not a probe */
 		if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
 			nf_conntrack_event_cache(IPCT_STATUS, ct);
 	} else
-		nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udplite_timeout);
+		nf_ct_refresh_acct(ct, ctinfo, skb, un->udplite_timeout);
 
 	return NF_ACCEPT;
 }
@@ -142,13 +160,11 @@ static int udplite_error(struct net *net
 }
 
 #ifdef CONFIG_SYSCTL
-static unsigned int udplite_sysctl_table_users;
-static struct ctl_table_header *udplite_sysctl_header;
+/* template, data assigned later */
 static struct ctl_table udplite_sysctl_table[] = {
 	{
 		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "nf_conntrack_udplite_timeout",
-		.data		= &nf_ct_udplite_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -156,7 +172,6 @@ static struct ctl_table udplite_sysctl_t
 	{
 		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "nf_conntrack_udplite_timeout_stream",
-		.data		= &nf_ct_udplite_timeout_stream,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -184,11 +199,6 @@ static struct nf_conntrack_l4proto nf_co
 	.nlattr_to_tuple	= nf_ct_port_nlattr_to_tuple,
 	.nla_policy		= nf_ct_port_nla_policy,
 #endif
-#ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &udplite_sysctl_table_users,
-	.ctl_table_header	= &udplite_sysctl_header,
-	.ctl_table		= udplite_sysctl_table,
-#endif
 };
 
 static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
@@ -207,26 +217,92 @@ static struct nf_conntrack_l4proto nf_co
 	.nlattr_to_tuple	= nf_ct_port_nlattr_to_tuple,
 	.nla_policy		= nf_ct_port_nla_policy,
 #endif
+};
+
+static __net_init int udplite_net_init(struct net *net)
+{
+	struct udplite_net *un;
+	int err;
+
+	un = kmalloc(sizeof(*un), GFP_KERNEL);
+	if (!un)
+		return -ENOMEM;
+
+	/* default values */
+	un->udplite_timeout		= 30 * HZ;
+	un->udplite_timeout_stream	= 180 * HZ;
+
+	err = net_assign_generic(net, udplite_net_id, un);
+	if (err)
+		goto out;
+
+#ifdef CONFIG_SYSCTL
+	err = -ENOMEM;
+	un->sysctl_table = kmemdup(udplite_sysctl_table,
+			sizeof(udplite_sysctl_table), GFP_KERNEL);
+	if (!un->sysctl_table)
+		goto out;
+
+	un->sysctl_table[0].data = &un->udplite_timeout;
+	un->sysctl_table[1].data = &un->udplite_timeout_stream;
+
+	un->sysctl_header = register_net_sysctl_table(net,
+			nf_net_netfilter_sysctl_path, un->sysctl_table);
+	if (!un->sysctl_header)
+		goto out_free;
+#endif /* CONFIG_SYSCTL */
+
+	return 0;
+
+#ifdef CONFIG_SYSCTL
+out_free:
+	kfree(un->sysctl_table);
+#endif
+
+out:
+	kfree(un);
+	return err;
+}
+
+static __net_exit void udplite_net_exit(struct net *net)
+{
+	struct udplite_net *un = udplite_pernet(net);
 #ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &udplite_sysctl_table_users,
-	.ctl_table_header	= &udplite_sysctl_header,
-	.ctl_table		= udplite_sysctl_table,
+	unregister_net_sysctl_table(un->sysctl_header);
+	kfree(un->sysctl_table);
 #endif
+	kfree(un);
+
+	net_assign_generic(net, udplite_net_id, NULL);
+}
+
+static struct pernet_operations udplite_net_ops = {
+	.init = udplite_net_init,
+	.exit = udplite_net_exit,
 };
 
 static int __init nf_conntrack_proto_udplite_init(void)
 {
 	int err;
 
-	err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite4);
+	err = register_pernet_gen_subsys(&udplite_net_id, &udplite_net_ops);
 	if (err < 0)
 		goto err1;
-	err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite6);
+
+	err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite4);
 	if (err < 0)
 		goto err2;
+
+	err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite6);
+	if (err < 0)
+		goto err3;
+
 	return 0;
-err2:
+
+err3:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
+err2:
+	unregister_pernet_gen_subsys(udplite_net_id, &udplite_net_ops);
 err1:
 	return err;
 }
@@ -235,6 +311,7 @@ static void __exit nf_conntrack_proto_ud
 {
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
+	unregister_pernet_gen_subsys(udplite_net_id, &udplite_net_ops);
 }
 
 module_init(nf_conntrack_proto_udplite_init);


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol
  2009-03-26 16:05 ` [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol Cyrill Gorcunov
@ 2009-03-26 16:16   ` Patrick McHardy
  2009-03-26 16:21     ` Cyrill Gorcunov
                       ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Patrick McHardy @ 2009-03-26 16:16 UTC (permalink / raw)
  To: Cyrill Gorcunov; +Cc: netfilter-devel, xemul, daniel.lezcano

Cyrill Gorcunov wrote:
> Module specific data moved into per-net site and being allocated/freed
> during net namespace creation/deletion. For this reason module_init/exit
> calls added.

This doesn't work. You can't have multiple module_init functions
in one module and nf_connntrack_ivp4 already includes one.

Please test your patches with a modular built before resubmitting.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol
  2009-03-26 16:16   ` Patrick McHardy
@ 2009-03-26 16:21     ` Cyrill Gorcunov
  2009-03-26 16:34     ` Alexey Dobriyan
  2009-03-26 17:37     ` Cyrill Gorcunov
  2 siblings, 0 replies; 14+ messages in thread
From: Cyrill Gorcunov @ 2009-03-26 16:21 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel, xemul, daniel.lezcano

[Patrick McHardy - Thu, Mar 26, 2009 at 05:16:31PM +0100]
> Cyrill Gorcunov wrote:
>> Module specific data moved into per-net site and being allocated/freed
>> during net namespace creation/deletion. For this reason module_init/exit
>> calls added.
>
> This doesn't work. You can't have multiple module_init functions
> in one module and nf_connntrack_ivp4 already includes one.
>
> Please test your patches with a modular built before resubmitting.
>

Hmm... thanks! Will check -- other patches (except one have the
same problems -- drop this series for now)

        Cyrill

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol
  2009-03-26 16:16   ` Patrick McHardy
  2009-03-26 16:21     ` Cyrill Gorcunov
@ 2009-03-26 16:34     ` Alexey Dobriyan
  2009-03-26 16:59       ` Cyrill Gorcunov
  2009-03-26 21:05       ` Cyrill Gorcunov
  2009-03-26 17:37     ` Cyrill Gorcunov
  2 siblings, 2 replies; 14+ messages in thread
From: Alexey Dobriyan @ 2009-03-26 16:34 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Cyrill Gorcunov, netfilter-devel, xemul, daniel.lezcano

On Thu, Mar 26, 2009 at 05:16:31PM +0100, Patrick McHardy wrote:
> Cyrill Gorcunov wrote:
>> Module specific data moved into per-net site and being allocated/freed
>> during net namespace creation/deletion. For this reason module_init/exit
>> calls added.
>
> This doesn't work. You can't have multiple module_init functions
> in one module and nf_connntrack_ivp4 already includes one.

I thought all sysctl code would be generic in sense it will be done
during L3 and L4 proto registration, so all those ifdefs will be in one
place and so on.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol
  2009-03-26 16:34     ` Alexey Dobriyan
@ 2009-03-26 16:59       ` Cyrill Gorcunov
  2009-03-26 18:23         ` Cyrill Gorcunov
  2009-03-26 21:05       ` Cyrill Gorcunov
  1 sibling, 1 reply; 14+ messages in thread
From: Cyrill Gorcunov @ 2009-03-26 16:59 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: Patrick McHardy, netfilter-devel, xemul, daniel.lezcano

[Alexey Dobriyan - Thu, Mar 26, 2009 at 07:34:44PM +0300]
| On Thu, Mar 26, 2009 at 05:16:31PM +0100, Patrick McHardy wrote:
| > Cyrill Gorcunov wrote:
| >> Module specific data moved into per-net site and being allocated/freed
| >> during net namespace creation/deletion. For this reason module_init/exit
| >> calls added.
| >
| > This doesn't work. You can't have multiple module_init functions
| > in one module and nf_connntrack_ivp4 already includes one.
| 
| I thought all sysctl code would be generic in sense it will be done
| during L3 and L4 proto registration, so all those ifdefs will be in one
| place and so on.
| 

It's a really good idea but it requires some logic to be changed --
for example I would need some kind of net-namespace sysctl hook
so sysctl tables will be static and pinned to a particular source
file and so on. Will think about. Thanks!

        Cyrill

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol
  2009-03-26 16:16   ` Patrick McHardy
  2009-03-26 16:21     ` Cyrill Gorcunov
  2009-03-26 16:34     ` Alexey Dobriyan
@ 2009-03-26 17:37     ` Cyrill Gorcunov
  2 siblings, 0 replies; 14+ messages in thread
From: Cyrill Gorcunov @ 2009-03-26 17:37 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel, xemul, daniel.lezcano, Alexey Dobriyan

[Patrick McHardy - Thu, Mar 26, 2009 at 05:16:31PM +0100]
> Cyrill Gorcunov wrote:
>> Module specific data moved into per-net site and being allocated/freed
>> during net namespace creation/deletion. For this reason module_init/exit
>> calls added.
>
> This doesn't work. You can't have multiple module_init functions
> in one module and nf_connntrack_ivp4 already includes one.
>
> Please test your patches with a modular built before resubmitting.
>

Btw, the patches

	[patch 2/5] net: netfilter conntrack - add per-net functionality for SCTP protocol
	[patch 5/5] net: netfilter conntrack - add per-net functionality for UDPLITE protocol

are not affected by multiple module_init/exit issue (except general idea
Alexey mentioned)

        Cyrill

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol
  2009-03-26 16:59       ` Cyrill Gorcunov
@ 2009-03-26 18:23         ` Cyrill Gorcunov
  0 siblings, 0 replies; 14+ messages in thread
From: Cyrill Gorcunov @ 2009-03-26 18:23 UTC (permalink / raw)
  To: Alexey Dobriyan, Patrick McHardy, netfilter-devel, xemul,
	daniel.lezcano

[Cyrill Gorcunov - Thu, Mar 26, 2009 at 07:59:28PM +0300]
| [Alexey Dobriyan - Thu, Mar 26, 2009 at 07:34:44PM +0300]
| | On Thu, Mar 26, 2009 at 05:16:31PM +0100, Patrick McHardy wrote:
| | > Cyrill Gorcunov wrote:
| | >> Module specific data moved into per-net site and being allocated/freed
| | >> during net namespace creation/deletion. For this reason module_init/exit
| | >> calls added.
| | >
| | > This doesn't work. You can't have multiple module_init functions
| | > in one module and nf_connntrack_ivp4 already includes one.
| | 
| | I thought all sysctl code would be generic in sense it will be done
| | during L3 and L4 proto registration, so all those ifdefs will be in one
| | place and so on.
| | 
| 
| It's a really good idea but it requires some logic to be changed --
| for example I would need some kind of net-namespace sysctl hook
| so sysctl tables will be static and pinned to a particular source
| file and so on. Will think about. Thanks!
| 
|         Cyrill

One more problem is that several protocols share single net-namespace
functionality and I either should add ref counter to eliminate double
initialization. I was in idea to use kref for that (since it has
all memory barriers for that) but unfortunately it doesn't has kref_test
routine.

        Cyrill

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol
  2009-03-26 16:34     ` Alexey Dobriyan
  2009-03-26 16:59       ` Cyrill Gorcunov
@ 2009-03-26 21:05       ` Cyrill Gorcunov
  1 sibling, 0 replies; 14+ messages in thread
From: Cyrill Gorcunov @ 2009-03-26 21:05 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: Patrick McHardy, netfilter-devel, xemul, daniel.lezcano

[Alexey Dobriyan - Thu, Mar 26, 2009 at 07:34:44PM +0300]
| On Thu, Mar 26, 2009 at 05:16:31PM +0100, Patrick McHardy wrote:
| > Cyrill Gorcunov wrote:
| >> Module specific data moved into per-net site and being allocated/freed
| >> during net namespace creation/deletion. For this reason module_init/exit
| >> calls added.
| >
| > This doesn't work. You can't have multiple module_init functions
| > in one module and nf_connntrack_ivp4 already includes one.
| 
| I thought all sysctl code would be generic in sense it will be done
| during L3 and L4 proto registration, so all those ifdefs will be in one
| place and so on.
| 

Patrick, Alexey,

the temporal solution could be like the inlined below.
Frankly, I don't like it that much but you could take
a look on and maybe some idea reveals?

So I introduced additional calls while registering proto.
Since ICMP is called only once -- no need for ref counter.

For TCP/UDP the same thing is done except call counter added
(we have v4 and v6 protos which are sharing namespace functionality
 and since proto registering/unregisterding is under mutex protection
 reference counter is done via plain int type. I didn't post those
 patches since they are same in idea)

Yes, it seems to look ugly -- but at moment I cant imagine something
else. Brain is almost off. Maybe you could give an advice?

        Cyrill
---
net: netfilter conntrack - add per-net functionality for ICMP protocol

Protocol specific data moved into per-net site and being allocated/freed
during net namespace creation/deletion.

For this we inject register/unregister_hook function pointers
into nf_conntrack_l4proto structure itself and happily use it.

Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
 include/net/netfilter/nf_conntrack_l4proto.h |    3 
 net/ipv4/netfilter/nf_conntrack_proto_icmp.c |  129 +++++++++++++++++++++++++--
 net/netfilter/nf_conntrack_proto.c           |   17 +++
 3 files changed, 140 insertions(+), 9 deletions(-)

Index: linux-2.6.git/include/net/netfilter/nf_conntrack_l4proto.h
===================================================================
--- linux-2.6.git.orig/include/net/netfilter/nf_conntrack_l4proto.h
+++ linux-2.6.git/include/net/netfilter/nf_conntrack_l4proto.h
@@ -80,6 +80,9 @@ struct nf_conntrack_l4proto
 
 	size_t nla_size;
 
+	int (*register_hook)(struct nf_conntrack_l4proto *proto);
+	void (*unregister_hook)(struct nf_conntrack_l4proto *proto);
+
 #ifdef CONFIG_SYSCTL
 	struct ctl_table_header	**ctl_table_header;
 	struct ctl_table	*ctl_table;
Index: linux-2.6.git/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
===================================================================
--- linux-2.6.git.orig/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ linux-2.6.git/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/netfilter.h>
+#include <linux/module.h>
 #include <linux/in.h>
 #include <linux/icmp.h>
 #include <linux/seq_file.h>
@@ -20,7 +21,30 @@
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_log.h>
 
-static unsigned int nf_ct_icmp_timeout __read_mostly = 30*HZ;
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
+static int nf_ct_icmp_proto_init(struct nf_conntrack_l4proto *l4proto);
+static void nf_ct_icmp_proto_fini(struct nf_conntrack_l4proto *l4proto);
+
+/* per-net specifics */
+static int icmp_net_id;
+struct icmp_net {
+	unsigned int icmp_timeout;
+#ifdef CONFIG_SYSCTL
+	struct ctl_table_header *sysctl_header;
+	struct ctl_table *sysctl_table;
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	struct ctl_table_header *compat_sysctl_header;
+	struct ctl_table *compat_sysctl_table;
+#endif
+#endif
+};
+
+static inline struct icmp_net *icmp_pernet(struct net *net)
+{
+	return net_generic(net, icmp_net_id);
+}
 
 static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
 			      struct nf_conntrack_tuple *tuple)
@@ -90,9 +114,10 @@ static int icmp_packet(struct nf_conn *c
 		if (atomic_dec_and_test(&ct->proto.icmp.count))
 			nf_ct_kill_acct(ct, ctinfo, skb);
 	} else {
+		struct icmp_net *in = icmp_pernet(nf_ct_net(ct));
 		atomic_inc(&ct->proto.icmp.count);
 		nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct);
-		nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout);
+		nf_ct_refresh_acct(ct, ctinfo, skb, in->icmp_timeout);
 	}
 
 	return NF_ACCEPT;
@@ -270,11 +295,10 @@ static int icmp_nlattr_tuple_size(void)
 #endif
 
 #ifdef CONFIG_SYSCTL
-static struct ctl_table_header *icmp_sysctl_header;
+/* templates, data assigned later */
 static struct ctl_table icmp_sysctl_table[] = {
 	{
 		.procname	= "nf_conntrack_icmp_timeout",
-		.data		= &nf_ct_icmp_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -287,7 +311,6 @@ static struct ctl_table icmp_sysctl_tabl
 static struct ctl_table icmp_compat_sysctl_table[] = {
 	{
 		.procname	= "ip_conntrack_icmp_timeout",
-		.data		= &nf_ct_icmp_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -318,11 +341,101 @@ struct nf_conntrack_l4proto nf_conntrack
 	.nlattr_to_tuple	= icmp_nlattr_to_tuple,
 	.nla_policy		= icmp_nla_policy,
 #endif
+	.register_hook		= nf_ct_icmp_proto_init,
+	.unregister_hook	= nf_ct_icmp_proto_fini,
+};
+
+static __net_init int icmp_net_init(struct net *net)
+{
+	struct icmp_net *in;
+	int err;
+
+	in = kmalloc(sizeof(*in), GFP_KERNEL);
+	if (!in)
+		return -ENOMEM;
+
+	/* default values */
+	in->icmp_timeout = 30 * HZ;
+
+	err = net_assign_generic(net, icmp_net_id, in);
+	if (err)
+		goto out;
+
+#ifdef CONFIG_SYSCTL
+	err = -ENOMEM;
+	in->sysctl_table = kmemdup(icmp_sysctl_table,
+			sizeof(icmp_sysctl_table), GFP_KERNEL);
+	if (!in->sysctl_table)
+		goto out;
+
+	in->sysctl_table[0].data = &in->icmp_timeout;
+
+	in->sysctl_header = register_net_sysctl_table(net,
+			nf_net_netfilter_sysctl_path, in->sysctl_table);
+	if (!in->sysctl_header)
+		goto out_free;
+
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	in->compat_sysctl_table = kmemdup(icmp_compat_sysctl_table,
+			sizeof(icmp_compat_sysctl_table), GFP_KERNEL);
+	if (!in->compat_sysctl_table)
+		goto out_sysctl;
+
+	in->compat_sysctl_table[0].data = &in->icmp_timeout;
+
+	in->compat_sysctl_header = register_net_sysctl_table(net,
+			nf_net_ipv4_netfilter_sysctl_path,
+			in->compat_sysctl_table);
+	if (!in->compat_sysctl_header)
+		goto out_free_compat;
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+#endif /* CONFIG_SYSCTL */
+
+	return 0;
+
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+out_free_compat:
+	kfree(in->compat_sysctl_table);
+#endif
+out_sysctl:
+	unregister_net_sysctl_table(in->sysctl_header);
+out_free:
+	kfree(in->sysctl_table);
+#endif
+
+out:
+	kfree(in);
+	return err;
+}
+
+static __net_exit void icmp_net_exit(struct net *net)
+{
+	struct icmp_net *in = icmp_pernet(net);
 #ifdef CONFIG_SYSCTL
-	.ctl_table_header	= &icmp_sysctl_header,
-	.ctl_table		= icmp_sysctl_table,
+	unregister_net_sysctl_table(in->sysctl_header);
+	kfree(in->sysctl_table);
 #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
-	.ctl_compat_table	= icmp_compat_sysctl_table,
+	unregister_net_sysctl_table(in->compat_sysctl_header);
+	kfree(in->compat_sysctl_table);
 #endif
 #endif
+	kfree(in);
+
+	net_assign_generic(net, icmp_net_id, NULL);
+}
+
+static struct pernet_operations icmp_net_ops = {
+	.init = icmp_net_init,
+	.exit = icmp_net_exit,
 };
+
+static int nf_ct_icmp_proto_init(struct nf_conntrack_l4proto *l4proto)
+{
+	return register_pernet_gen_subsys(&icmp_net_id, &icmp_net_ops);
+}
+
+static void nf_ct_icmp_proto_fini(struct nf_conntrack_l4proto *l4proto)
+{
+	unregister_pernet_gen_subsys(icmp_net_id, &icmp_net_ops);
+}
Index: linux-2.6.git/net/netfilter/nf_conntrack_proto.c
===================================================================
--- linux-2.6.git.orig/net/netfilter/nf_conntrack_proto.c
+++ linux-2.6.git/net/netfilter/nf_conntrack_proto.c
@@ -296,9 +296,14 @@ int nf_conntrack_l4proto_register(struct
 		goto out_unlock;
 	}
 
+	if (l4proto->register_hook)
+		ret = l4proto->register_hook(l4proto);
+		if (ret < 0)
+			goto out_unlock;
+
 	ret = nf_ct_l4proto_register_sysctl(l4proto);
 	if (ret < 0)
-		goto out_unlock;
+		goto out_unregister_hook;
 
 	l4proto->nla_size = 0;
 	if (l4proto->nlattr_size)
@@ -309,6 +314,10 @@ int nf_conntrack_l4proto_register(struct
 	rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
 			   l4proto);
 
+out_unregister_hook:
+	if (l4proto->unregister_hook)
+		l4proto->unregister_hook(l4proto);
+
 out_unlock:
 	mutex_unlock(&nf_ct_proto_mutex);
 	return ret;
@@ -335,6 +344,12 @@ void nf_conntrack_l4proto_unregister(str
 	for_each_net(net)
 		nf_ct_iterate_cleanup(net, kill_l4proto, l4proto);
 	rtnl_unlock();
+
+	if (l4proto->unregister_hook) {
+		mutex_lock(&nf_ct_proto_mutex);
+		l4proto->unregister_hook(l4proto);
+		mutex_unlock(&nf_ct_proto_mutex);
+	}
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister);
 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [patch 4/5] net: netfilter conntrack - add per-net functionality for UDP protocol
  2009-03-28 22:33 [patch 0/5] nf conntrack protos pernet functionality v3 Cyrill Gorcunov
@ 2009-03-28 22:33 ` Cyrill Gorcunov
  0 siblings, 0 replies; 14+ messages in thread
From: Cyrill Gorcunov @ 2009-03-28 22:33 UTC (permalink / raw)
  To: kaber, adobriyan; +Cc: netfilter-devel, xemul, daniel.lezcano, Cyrill Gorcunov

[-- Attachment #1: net-nf-conntrack-proto-udp --]
[-- Type: text/plain, Size: 11238 bytes --]

Protocol specific data moved into per-net site and being allocated/freed
during net namespace creation/deletion.

Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
 include/net/netfilter/ipv4/nf_conntrack_ipv4.h |    3 
 include/net/netfilter/ipv6/nf_conntrack_ipv6.h |    3 
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |   11 +
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |   11 +
 net/netfilter/nf_conntrack_proto_udp.c         |  163 +++++++++++++++++++++----
 5 files changed, 167 insertions(+), 24 deletions(-)

Index: linux-2.6.git/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
===================================================================
--- linux-2.6.git.orig/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
+++ linux-2.6.git/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -27,4 +27,7 @@ extern void nf_ct_icmp_proto_fini(void);
 extern int nf_ct_tcp_proto_init(void);
 extern void nf_ct_tcp_proto_fini(void);
 
+extern int nf_ct_udp_proto_init(void);
+extern void nf_ct_udp_proto_fini(void);
+
 #endif /*_NF_CONNTRACK_IPV4_H*/
Index: linux-2.6.git/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
===================================================================
--- linux-2.6.git.orig/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
+++ linux-2.6.git/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -23,4 +23,7 @@ extern struct ctl_table nf_ct_ipv6_sysct
 extern int nf_ct_tcp_proto_init(void);
 extern void nf_ct_tcp_proto_fini(void);
 
+extern int nf_ct_udp_proto_init(void);
+extern void nf_ct_udp_proto_fini(void);
+
 #endif /* _NF_CONNTRACK_IPV6_H*/
Index: linux-2.6.git/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
===================================================================
--- linux-2.6.git.orig/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ linux-2.6.git/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -395,10 +395,16 @@ static int __init nf_conntrack_l3proto_i
 		goto uninit_tcp;
 	}
 
+	ret = nf_ct_udp_proto_init();
+	if (ret < 0) {
+		printk("nf_conntrack_ipv4: can't initialize udp.\n");
+		goto cleanup_tcp;
+	}
+
 	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp4);
 	if (ret < 0) {
 		printk("nf_conntrack_ipv4: can't register udp.\n");
-		goto cleanup_tcp;
+		goto uninit_udp;
 	}
 
 	ret = nf_ct_icmp_proto_init();
@@ -443,6 +449,8 @@ static int __init nf_conntrack_l3proto_i
 	nf_ct_icmp_proto_fini();
  cleanup_udp:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
+ uninit_udp:
+	nf_ct_udp_proto_fini();
  cleanup_tcp:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
  uninit_tcp:
@@ -463,6 +471,7 @@ static void __exit nf_conntrack_l3proto_
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
 	nf_ct_icmp_proto_fini();
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
+	nf_ct_udp_proto_fini();
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
 	nf_ct_tcp_proto_fini();
 	nf_unregister_sockopt(&so_getorigdst);
Index: linux-2.6.git/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
===================================================================
--- linux-2.6.git.orig/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ linux-2.6.git/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -397,10 +397,16 @@ static int __init nf_conntrack_l3proto_i
 		goto uninit_tcp;
 	}
 
+	ret = nf_ct_udp_proto_init();
+	if (ret < 0) {
+		printk("nf_conntrack_ipv6: can't initialize udp.\n");
+		goto cleanup_tcp;
+	}
+
 	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6);
 	if (ret < 0) {
 		printk("nf_conntrack_ipv6: can't register udp.\n");
-		goto cleanup_tcp;
+		goto uninit_udp;
 	}
 
 	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmpv6);
@@ -430,6 +436,8 @@ static int __init nf_conntrack_l3proto_i
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
  cleanup_udp:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
+ uninit_udp:
+	nf_ct_udp_proto_fini();
  cleanup_tcp:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
  uninit_tcp:
@@ -446,6 +454,7 @@ static void __exit nf_conntrack_l3proto_
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
+	nf_ct_udp_proto_fini();
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
 	nf_ct_tcp_proto_fini();
 	nf_ct_frag6_cleanup();
Index: linux-2.6.git/net/netfilter/nf_conntrack_proto_udp.c
===================================================================
--- linux-2.6.git.orig/net/netfilter/nf_conntrack_proto_udp.c
+++ linux-2.6.git/net/netfilter/nf_conntrack_proto_udp.c
@@ -16,6 +16,9 @@
 #include <net/ip6_checksum.h>
 #include <net/checksum.h>
 
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
@@ -25,8 +28,28 @@
 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
 
-static unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
-static unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
+static DEFINE_MUTEX(proto_ref_lock);
+static int proto_ref;
+
+/* per-net specifics */
+static int udp_net_id;
+struct udp_net {
+	unsigned int udp_timeout;
+	unsigned int udp_timeout_stream;
+#ifdef CONFIG_SYSCTL
+	struct ctl_table_header *sysctl_header;
+	struct ctl_table *sysctl_table;
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	struct ctl_table_header *compat_sysctl_header;
+	struct ctl_table *compat_sysctl_table;
+#endif
+#endif
+};
+
+static inline struct udp_net *udp_pernet(struct net *net)
+{
+	return net_generic(net, udp_net_id);
+}
 
 static bool udp_pkt_to_tuple(const struct sk_buff *skb,
 			     unsigned int dataoff,
@@ -71,15 +94,17 @@ static int udp_packet(struct nf_conn *ct
 		      u_int8_t pf,
 		      unsigned int hooknum)
 {
+	struct udp_net *un = udp_pernet(nf_ct_net(ct));
+
 	/* If we've seen traffic both ways, this is some kind of UDP
 	   stream.  Extend timeout. */
 	if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
-		nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout_stream);
+		nf_ct_refresh_acct(ct, ctinfo, skb, un->udp_timeout_stream);
 		/* Also, more likely to be important, and not a probe */
 		if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
 			nf_conntrack_event_cache(IPCT_STATUS, ct);
 	} else
-		nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout);
+		nf_ct_refresh_acct(ct, ctinfo, skb, un->udp_timeout);
 
 	return NF_ACCEPT;
 }
@@ -137,19 +162,16 @@ static int udp_error(struct net *net, st
 }
 
 #ifdef CONFIG_SYSCTL
-static unsigned int udp_sysctl_table_users;
-static struct ctl_table_header *udp_sysctl_header;
+/* templates, data assigned later */
 static struct ctl_table udp_sysctl_table[] = {
 	{
 		.procname	= "nf_conntrack_udp_timeout",
-		.data		= &nf_ct_udp_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "nf_conntrack_udp_timeout_stream",
-		.data		= &nf_ct_udp_timeout_stream,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -162,14 +184,12 @@ static struct ctl_table udp_sysctl_table
 static struct ctl_table udp_compat_sysctl_table[] = {
 	{
 		.procname	= "ip_conntrack_udp_timeout",
-		.data		= &nf_ct_udp_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
 		.procname	= "ip_conntrack_udp_timeout_stream",
-		.data		= &nf_ct_udp_timeout_stream,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -198,14 +218,7 @@ struct nf_conntrack_l4proto nf_conntrack
 	.nlattr_tuple_size	= nf_ct_port_nlattr_tuple_size,
 	.nla_policy		= nf_ct_port_nla_policy,
 #endif
-#ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &udp_sysctl_table_users,
-	.ctl_table_header	= &udp_sysctl_header,
-	.ctl_table		= udp_sysctl_table,
-#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
-	.ctl_compat_table	= udp_compat_sysctl_table,
-#endif
-#endif
+	.me			= THIS_MODULE,
 };
 EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4);
 
@@ -226,10 +239,116 @@ struct nf_conntrack_l4proto nf_conntrack
 	.nlattr_tuple_size	= nf_ct_port_nlattr_tuple_size,
 	.nla_policy		= nf_ct_port_nla_policy,
 #endif
+	.me			= THIS_MODULE,
+};
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6);
+
+static __net_init int udp_net_init(struct net *net)
+{
+	struct udp_net *un;
+	int err;
+
+	un = kmalloc(sizeof(*un), GFP_KERNEL);
+	if (!un)
+		return -ENOMEM;
+
+	/* default values */
+	un->udp_timeout		= 30 * HZ;
+	un->udp_timeout_stream	= 180 * HZ;
+
+	err = net_assign_generic(net, udp_net_id, un);
+	if (err)
+		goto out;
+
+#ifdef CONFIG_SYSCTL
+	err = -ENOMEM;
+	un->sysctl_table = kmemdup(udp_sysctl_table,
+			sizeof(udp_sysctl_table), GFP_KERNEL);
+	if (!un->sysctl_table)
+		goto out;
+
+	un->sysctl_table[0].data = &un->udp_timeout;
+	un->sysctl_table[1].data = &un->udp_timeout_stream;
+
+	un->sysctl_header = register_net_sysctl_table(net,
+			nf_net_netfilter_sysctl_path, un->sysctl_table);
+	if (!un->sysctl_header)
+		goto out_free;
+
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	un->compat_sysctl_table = kmemdup(udp_compat_sysctl_table,
+			sizeof(udp_compat_sysctl_table), GFP_KERNEL);
+	if (!un->compat_sysctl_table)
+		goto out_sysctl;
+
+	un->compat_sysctl_table[0].data = &un->udp_timeout;
+	un->compat_sysctl_table[1].data = &un->udp_timeout_stream;
+
+	un->compat_sysctl_header = register_net_sysctl_table(net,
+			nf_net_ipv4_netfilter_sysctl_path,
+			un->compat_sysctl_table);
+	if (!un->compat_sysctl_header)
+		goto out_free_compat;
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+#endif /* CONFIG_SYSCTL */
+
+	return 0;
+
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+out_free_compat:
+	kfree(un->compat_sysctl_table);
+#endif
+out_sysctl:
+	unregister_net_sysctl_table(un->sysctl_header);
+out_free:
+	kfree(un->sysctl_table);
+#endif
+
+out:
+	kfree(un);
+	return err;
+}
+
+static __net_exit void udp_net_exit(struct net *net)
+{
+	struct udp_net *un = udp_pernet(net);
 #ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &udp_sysctl_table_users,
-	.ctl_table_header	= &udp_sysctl_header,
-	.ctl_table		= udp_sysctl_table,
+	unregister_net_sysctl_table(un->sysctl_header);
+	kfree(un->sysctl_table);
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+	unregister_net_sysctl_table(un->compat_sysctl_header);
+	kfree(un->compat_sysctl_table);
+#endif
 #endif
+	kfree(un);
+
+	net_assign_generic(net, udp_net_id, NULL);
+}
+
+static struct pernet_operations udp_net_ops = {
+	.init = udp_net_init,
+	.exit = udp_net_exit,
 };
-EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6);
+
+int nf_ct_udp_proto_init(void)
+{
+	int err = 0;
+
+	mutex_lock(&proto_ref_lock);
+	if (!proto_ref++)
+		err = register_pernet_gen_subsys(&udp_net_id, &udp_net_ops);
+	mutex_unlock(&proto_ref_lock);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(nf_ct_udp_proto_init);
+
+void nf_ct_udp_proto_fini(void)
+{
+	mutex_lock(&proto_ref_lock);
+	if (!--proto_ref)
+		unregister_pernet_gen_subsys(udp_net_id, &udp_net_ops);
+	mutex_unlock(&proto_ref_lock);
+}
+EXPORT_SYMBOL_GPL(nf_ct_udp_proto_fini);


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2009-03-28 22:38 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-03-26 16:05 [patch 0/5] nf protos pernet functionality fresh attempt Cyrill Gorcunov
2009-03-26 16:05 ` [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol Cyrill Gorcunov
2009-03-26 16:16   ` Patrick McHardy
2009-03-26 16:21     ` Cyrill Gorcunov
2009-03-26 16:34     ` Alexey Dobriyan
2009-03-26 16:59       ` Cyrill Gorcunov
2009-03-26 18:23         ` Cyrill Gorcunov
2009-03-26 21:05       ` Cyrill Gorcunov
2009-03-26 17:37     ` Cyrill Gorcunov
2009-03-26 16:05 ` [patch 2/5] net: netfilter conntrack - add per-net functionality for SCTP protocol Cyrill Gorcunov
2009-03-26 16:05 ` [patch 3/5] net: netfilter conntrack - add per-net functionality for TCP protocol Cyrill Gorcunov
2009-03-26 16:05 ` [patch 4/5] net: netfilter conntrack - add per-net functionality for UDP protocol Cyrill Gorcunov
2009-03-26 16:05 ` [patch 5/5] net: netfilter conntrack - add per-net functionality for UDPLITE protocol Cyrill Gorcunov
  -- strict thread matches above, loose matches on Subject: below --
2009-03-28 22:33 [patch 0/5] nf conntrack protos pernet functionality v3 Cyrill Gorcunov
2009-03-28 22:33 ` [patch 4/5] net: netfilter conntrack - add per-net functionality for UDP protocol Cyrill Gorcunov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).