Skip to contentSkip to conversation

netfilter conntrack sysctls pernet support

RFC Superseded Cyrill Gorcunov 5 participants 17 messages Mar 9, 2009 – Mar 10, 2009 1 message not in the archive

Subsystems (4)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover netfilter conntrack sysctls pernet support

Hi here are a few patches to bring in per-net functionality for several conntrack protocols: DCCP, SCTP, UDPlite.

Since these protos could be built as modules I've put per-net operations to module init/exit routines. The change I would like you point the attention is that module static variables being marked as __read_mostly become now as dynamically allocated -- is it acceptable trade off?

For protocols being built in (like TCP, UDP, ICMP) for which I made patches too but they are in a bit 'rought' state: in original code there some kind of reference counter to sysctl tables being registered (and they don't have any kind of mb, didn't check if it could be a problem for SMP since they are mostly __init functions) so I need some kind of same functionality to count per-net calls. Will send RFC for these protocols soon.

So eventually I would like to hear some kind of feedback on this. Ideas and any kind of comments are highly appreciated.

The patches are on top of -net-next-2.6

Cyrill

#1 lore raw

RFC 1/4 net: sysctl_net - use net_eq to compare nets

---

Btw, wouldn't be better to have a special macro/inline to check if net is init_net? Something like is_init_net()

 net/sysctl_net.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/sysctl_net.c +1 -1
Index: linux-2.6.git/net/sysctl_net.c
===================================================================
@@ -61,7 +61,7 @@ static struct ctl_table_root net_sysctl_
 static int net_ctl_ro_header_perms(struct ctl_table_root *root,
 		struct nsproxy *namespaces, struct ctl_table *table)
 {
-	if (namespaces->net_ns == &init_net)
+	if (net_eq(namespaces->net_ns, &init_net))
 		return table->mode;
 	else
 		return table->mode & ~0222;
#2 lore raw

RFC 2/4 net: netfilter conntrack - add per-net functionality for DCCP protocol

In reply to Cyrill Gorcunov

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

---
 net/netfilter/nf_conntrack_proto_dccp.c |  148 ++++++++++++++++++++++++--------
 1 file changed, 111 insertions(+), 37 deletions(-)
net/netfilter/nf_conntrack_proto_dccp.c +111 -37
Index: linux-2.6.git/net/netfilter/nf_conntrack_proto_dccp.c
===================================================================
@@ -16,6 +16,9 @@
 #include <linux/skbuff.h>
 #include <linux/dccp.h>
 
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
 #include <linux/netfilter/nfnetlink_conntrack.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
@@ -23,8 +26,6 @@
 
 static DEFINE_RWLOCK(dccp_lock);
 
-static int nf_ct_dccp_loose __read_mostly = 1;
-
 /* Timeouts are based on values from RFC4340:
  *
  * - REQUEST:
@@ -72,16 +73,6 @@ static int nf_ct_dccp_loose __read_mostl
 
 #define DCCP_MSL (2 * 60 * HZ)
 
-static unsigned int dccp_timeout[CT_DCCP_MAX + 1] __read_mostly = {
-	[CT_DCCP_REQUEST]	= 2 * DCCP_MSL,
-	[CT_DCCP_RESPOND]	= 4 * DCCP_MSL,
-	[CT_DCCP_PARTOPEN]	= 4 * DCCP_MSL,
-	[CT_DCCP_OPEN]		= 12 * 3600 * HZ,
-	[CT_DCCP_CLOSEREQ]	= 64 * HZ,
-	[CT_DCCP_CLOSING]	= 64 * HZ,
-	[CT_DCCP_TIMEWAIT]	= 2 * DCCP_MSL,
-};
-
 static const char * const dccp_state_names[] = {
 	[CT_DCCP_NONE]		= "NONE",
 	[CT_DCCP_REQUEST]	= "REQUEST",
@@ -393,6 +384,22 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][D
 	},
 };
 
+/* this module per-net specifics */
+static int dccp_net_id;
+struct dccp_net {
+	int dccp_loose;
+	unsigned int dccp_timeout[CT_DCCP_MAX + 1];
+#ifdef CONFIG_SYSCTL
+	struct ctl_table_header *sysctl_header;
+	struct ctl_table *sysctl_table;
+#endif
+};
+
+static inline struct dccp_net *dccp_pernet(struct net *net)
+{
+	return net_generic(net, dccp_net_id);
+}
+
 static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
 			      struct nf_conntrack_tuple *tuple)
 {
@@ -419,6 +426,7 @@ static bool dccp_new(struct nf_conn *ct,
 		     unsigned int dataoff)
 {
 	struct net *net = nf_ct_net(ct);
+	struct dccp_net *dn;
 	struct dccp_hdr _dh, *dh;
 	const char *msg;
 	u_int8_t state;
@@ -429,7 +437,8 @@ static bool dccp_new(struct nf_conn *ct,
 	state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE];
 	switch (state) {
 	default:
-		if (nf_ct_dccp_loose == 0) {
+		dn = dccp_pernet(net);
+		if (dn->dccp_loose == 0) {
 			msg = "nf_ct_dccp: not picking up existing connection ";
 			goto out_invalid;
 		}
@@ -465,6 +474,7 @@ static int dccp_packet(struct nf_conn *c
 		       u_int8_t pf, unsigned int hooknum)
 {
 	struct net *net = nf_ct_net(ct);
+	struct dccp_net *dn;
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 	struct dccp_hdr _dh, *dh;
 	u_int8_t type, old_state, new_state;
@@ -542,7 +552,9 @@ static int dccp_packet(struct nf_conn *c
 	ct->proto.dccp.last_pkt = type;
 	ct->proto.dccp.state = new_state;
 	write_unlock_bh(&dccp_lock);
-	nf_ct_refresh_acct(ct, ctinfo, skb, dccp_timeout[new_state]);
+
+	dn = dccp_pernet(net);
+	nf_ct_refresh_acct(ct, ctinfo, skb, dn->dccp_timeout[new_state]);
 
 	return NF_ACCEPT;
 }
@@ -660,13 +672,14 @@ static int nlattr_to_dccp(struct nlattr 
 #endif
 
 #ifdef CONFIG_SYSCTL
-static unsigned int dccp_sysctl_table_users;
-static struct ctl_table_header *dccp_sysctl_header;
-static ctl_table dccp_sysctl_table[] = {
+/*
+ * we use it as a template when create per-net syctl table
+ * table data will be assigned later
+ */
+static struct ctl_table dccp_sysctl_table[] = {
 	{
 		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "nf_conntrack_dccp_timeout_request",
-		.data		= &dccp_timeout[CT_DCCP_REQUEST],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -674,7 +687,6 @@ static ctl_table dccp_sysctl_table[] = {
 	{
 		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "nf_conntrack_dccp_timeout_respond",
-		.data		= &dccp_timeout[CT_DCCP_RESPOND],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -682,7 +694,6 @@ static ctl_table dccp_sysctl_table[] = {
 	{
 		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "nf_conntrack_dccp_timeout_partopen",
-		.data		= &dccp_timeout[CT_DCCP_PARTOPEN],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -690,7 +701,6 @@ static ctl_table dccp_sysctl_table[] = {
 	{
 		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "nf_conntrack_dccp_timeout_open",
-		.data		= &dccp_timeout[CT_DCCP_OPEN],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -698,7 +708,6 @@ static ctl_table dccp_sysctl_table[] = {
 	{
 		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "nf_conntrack_dccp_timeout_closereq",
-		.data		= &dccp_timeout[CT_DCCP_CLOSEREQ],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -706,7 +715,6 @@ static ctl_table dccp_sysctl_table[] = {
 	{
 		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "nf_conntrack_dccp_timeout_closing",
-		.data		= &dccp_timeout[CT_DCCP_CLOSING],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -714,7 +722,6 @@ static ctl_table dccp_sysctl_table[] = {
 	{
 		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "nf_conntrack_dccp_timeout_timewait",
-		.data		= &dccp_timeout[CT_DCCP_TIMEWAIT],
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
@@ -722,8 +729,7 @@ static ctl_table dccp_sysctl_table[] = {
 	{
 		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "nf_conntrack_dccp_loose",
-		.data		= &nf_ct_dccp_loose,
-		.maxlen		= sizeof(nf_ct_dccp_loose),
+		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
 	},
@@ -751,11 +757,6 @@ static struct nf_conntrack_l4proto dccp_
 	.nlattr_to_tuple	= nf_ct_port_nlattr_to_tuple,
 	.nla_policy		= nf_ct_port_nla_policy,
 #endif
-#ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &dccp_sysctl_table_users,
-	.ctl_table_header	= &dccp_sysctl_header,
-	.ctl_table		= dccp_sysctl_table,
-#endif
 };
 
 static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
@@ -776,34 +777,107 @@ static struct nf_conntrack_l4proto dccp_
 	.nlattr_to_tuple	= nf_ct_port_nlattr_to_tuple,
 	.nla_policy		= nf_ct_port_nla_policy,
 #endif
+};
+
+static __net_init int dccp_net_init(struct net *net)
+{
+	struct dccp_net *dn;
+	int err;
+
+	dn = kmalloc(sizeof(*dn), GFP_KERNEL);
+	if (!dn)
+		return -ENOMEM;
+
+	/* default values */
+	dn->dccp_loose = 1;
+	dn->dccp_timeout[CT_DCCP_REQUEST]	= 2 * DCCP_MSL;
+	dn->dccp_timeout[CT_DCCP_RESPOND]	= 4 * DCCP_MSL;
+	dn->dccp_timeout[CT_DCCP_PARTOPEN]	= 4 * DCCP_MSL;
+	dn->dccp_timeout[CT_DCCP_OPEN]		= 12 * 3600 * HZ;
+	dn->dccp_timeout[CT_DCCP_CLOSEREQ]	= 64 * HZ;
+	dn->dccp_timeout[CT_DCCP_CLOSING]	= 64 * HZ;
+	dn->dccp_timeout[CT_DCCP_TIMEWAIT]	= 2 * DCCP_MSL;
+
+	err = net_assign_generic(net, dccp_net_id, dn);
+	if (err)
+		goto out;
+
 #ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &dccp_sysctl_table_users,
-	.ctl_table_header	= &dccp_sysctl_header,
-	.ctl_table		= dccp_sysctl_table,
+	err = -ENOMEM;
+	dn->sysctl_table = kmemdup(dccp_sysctl_table,
+			sizeof(dccp_sysctl_table), GFP_KERNEL);
+	if (!dn->sysctl_table)
+		goto out;
+
+	dn->sysctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST];
+	dn->sysctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND];
+	dn->sysctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN];
+	dn->sysctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN];
+	dn->sysctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ];
+	dn->sysctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING];
+	dn->sysctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT];
+	dn->sysctl_table[7].data = &dn->dccp_loose;
+
+	dn->sysctl_header = register_net_sysctl_table(net,
+			nf_net_netfilter_sysctl_path, dn->sysctl_table);
+	if (!dn->sysctl_header) {
+		kfree(dn->sysctl_table);
+		goto out;
+	}
 #endif
+
+	return 0;
+
+out:
+	kfree(dn);
+	return err;
+}
+
+static __net_exit void dccp_net_exit(struct net *net)
+{
+	struct dccp_net *dn = dccp_pernet(net);
+#ifdef CONFIG_SYSCTL
+	unregister_net_sysctl_table(dn->sysctl_header);
+	kfree(dn->sysctl_table);
+#endif
+	kfree(dn);
+
+	net_assign_generic(net, dccp_net_id, NULL);
+}
+
+static struct pernet_operations dccp_net_ops = {
+	.init = dccp_net_init,
+	.exit = dccp_net_exit,
 };
 
 static int __init nf_conntrack_proto_dccp_init(void)
 {
 	int err;
 
-	err = nf_conntrack_l4proto_register(&dccp_proto4);
+	err = register_pernet_gen_device(&dccp_net_id, &dccp_net_ops);
 	if (err < 0)
 		goto err1;
 
-	err = nf_conntrack_l4proto_register(&dccp_proto6);
+	err = nf_conntrack_l4proto_register(&dccp_proto4);
 	if (err < 0)
 		goto err2;
+
+	err = nf_conntrack_l4proto_register(&dccp_proto6);
+	if (err < 0)
+		goto err3;
 	return 0;
 
-err2:
+err3:
 	nf_conntrack_l4proto_unregister(&dccp_proto4);
+err2:
+	unregister_pernet_gen_device(dccp_net_id, &dccp_net_ops);
 err1:
 	return err;
 }
 
 static void __exit nf_conntrack_proto_dccp_fini(void)
 {
+	unregister_pernet_gen_device(dccp_net_id, &dccp_net_ops);
 	nf_conntrack_l4proto_unregister(&dccp_proto6);
 	nf_conntrack_l4proto_unregister(&dccp_proto4);
 }
#12 lore raw

RFC 3/4 net: netfilter conntrack - add per-net functionality for SCTP protocol

In reply to Cyrill Gorcunov

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

---
 net/netfilter/nf_conntrack_proto_sctp.c |  179 ++++++++++++++++++++++++--------
 1 file changed, 139 insertions(+), 40 deletions(-)
net/netfilter/nf_conntrack_proto_sctp.c +139 -40
Index: 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 &&
@@ -540,54 +554,49 @@ static int nlattr_to_sctp(struct nlattr 
 #endif
 
 #ifdef CONFIG_SYSCTL
-static unsigned int sctp_sysctl_table_users;
-static struct ctl_table_header *sctp_sysctl_header;
+/*
+ * we use these tables as templates when create per-net syctl tables
+ * tables data will be 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,
@@ -601,49 +610,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,
@@ -653,7 +655,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,
@@ -673,14 +675,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 = {
@@ -701,21 +695,123 @@ 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;
+
 #ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &sctp_sysctl_table_users,
-	.ctl_table_header	= &sctp_sysctl_header,
-	.ctl_table		= sctp_sysctl_table,
+	err = -ENOMEM;
+	sn->sysctl_table = kmemdup(sctp_sysctl_table,
+			sizeof(sctp_sysctl_table), GFP_KERNEL);
+	if (!sn->sysctl_table)
+		goto out;
+
+	sn->sysctl_table[0].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED];
+	sn->sysctl_table[1].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
+	sn->sysctl_table[2].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
+	sn->sysctl_table[3].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED];
+	sn->sysctl_table[4].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
+	sn->sysctl_table[5].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
+	sn->sysctl_table[6].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];
+
+	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;
+
+	sn->compat_sysctl_table[0].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED];
+	sn->compat_sysctl_table[1].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
+	sn->compat_sysctl_table[2].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
+	sn->compat_sysctl_table[3].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED];
+	sn->compat_sysctl_table[4].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
+	sn->compat_sysctl_table[5].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
+	sn->compat_sysctl_table[6].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];
+
+	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_device(&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) {
@@ -727,12 +823,15 @@ static int __init nf_conntrack_proto_sct
 
  cleanup_sctp4:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
+ cleanup_net:
+	unregister_pernet_gen_device(sctp_net_id, &sctp_net_ops);
  out:
 	return ret;
 }
 
 static void __exit nf_conntrack_proto_sctp_fini(void)
 {
+	unregister_pernet_gen_device(sctp_net_id, &sctp_net_ops);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
 }
#14 lore raw

RFC 4/4 net: netfilter conntrack - add per-net functionality for UDPLITE protocol

In reply to Cyrill Gorcunov

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

---
 net/netfilter/nf_conntrack_proto_udplite.c |  118 ++++++++++++++++++++++++-----
 1 file changed, 99 insertions(+), 19 deletions(-)
net/netfilter/nf_conntrack_proto_udplite.c +99 -19
Index: 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,14 @@ 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;
+/*
+ * we use it as a template when create per-net syctl table
+ * table data will be 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 +175,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,
@@ -183,11 +201,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 =
@@ -206,32 +219,99 @@ 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_device(&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_device(udplite_net_id, &udplite_net_ops);
 err1:
 	return err;
 }
 
 static void __exit nf_conntrack_proto_udplite_exit(void)
 {
+	unregister_pernet_gen_device(udplite_net_id, &udplite_net_ops);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
 }
#15 lore raw
In reply to Cyrill Gorcunov

First off, *please* CC netfilter-devel on patches relating to netfilter. I've said this a hundred times in direction of the container guys (not sure whether you specifically) and it keeps getting ignored.

Quoted 8 lines · Cyrill Gorcunov

Hi here are a few patches to bring in per-net functionality for several conntrack protocols: DCCP, SCTP, UDPlite.

Since these protos could be built as modules I've put per-net operations to module init/exit routines. The change I would like you point the attention is that module static variables being marked as __read_mostly become now as dynamically allocated -- is it acceptable trade off?

Well, there's no other choice I guess.

Quoted 6 lines

For protocols being built in (like TCP, UDP, ICMP) for which I made patches too but they are in a bit 'rought' state: in original code there some kind of reference counter to sysctl tables being registered (and they don't have any kind of mb, didn't check if it could be a problem for SMP since they are mostly __init functions) so I need some kind of same functionality to count per-net calls.

The tables are shared between IPv4 and IPv6, this keeps track of the number of current users to avoid unregistering it while the AF-specific module for either one is loaded. This would still be a global counter with containers I think since module loading is global and they should be visible in all containers if IPv4 or IPv6 conntrack is loaded.

Review

Quoted 12 lines

Will send RFC for these protocols soon.

So eventually I would like to hear some kind of feedback on this. Ideas and any kind of comments are highly appreciated.

(quoted diff) +7 -0
+	sn->sysctl_table[0].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED];
+	sn->sysctl_table[1].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
+	sn->sysctl_table[2].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
+	sn->sysctl_table[3].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED];
+	sn->sysctl_table[4].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
+	sn->sysctl_table[5].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
+	sn->sysctl_table[6].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];

Please use an iteration to avoid these repetitve overly long lines.

#16 lore raw

[Patrick McHardy - Mon, Mar 09, 2009 at 07:47:28PM +0100]

Quoted 3 lines

First off, *please* CC netfilter-devel on patches relating to netfilter. I've said this a hundred times in direction of the container guys (not sure whether you specifically) and it keeps getting ignored.

Ugh... sorry Patrick, my fault, I've noticed this address in MAINTEINERS but NETFILTER section contains 3 list so I messed in which one I should choose. Sorry again.

Quoted 5 lines
Quoted 3 lines · Cyrill Gorcunov

Hi here are a few patches to bring in per-net functionality for several conntrack protocols: DCCP, SCTP, UDPlite.

Quoted 7 lines
Quoted 5 lines

Since these protos could be built as modules I've put per-net operations to module init/exit routines. The change I would like you point the attention is that module static variables being marked as __read_mostly become now as dynamically allocated -- is it acceptable trade off?

Well, there's no other choice I guess.

Actually, the possibility I see is to make some union on _all_ structures I put in pernet section so this union will contain max possible size of structure allocated and then create one global slab for this (HW cache aligned). But it would be ugly hack I believe and until we have no other choise I would prefer to not play with this idea :)

Quoted 8 lines
Quoted 7 lines

For protocols being built in (like TCP, UDP, ICMP) for which I made patches too but they are in a bit 'rought' state: in original code there some kind of reference counter to sysctl tables being registered (and they don't have any kind of mb, didn't check if it could be a problem for SMP since they are mostly __init functions) so I need some kind of same functionality to count per-net calls.

Quoted 5 lines

The tables are shared between IPv4 and IPv6, this keeps track of the number of current users to avoid unregistering it while the AF-specific module for either one is loaded. This would still be a global counter with containers I think since module loading is global and they should be visible in all containers if IPv4 or IPv6 conntrack is loaded.

Yes, I even thought about kref usage here but kref doesn't have a few function I need.

Quoted 6 lines
Quoted 5 lines

Will send RFC for these protocols soon.

So eventually I would like to hear some kind of feedback on this. Ideas and any kind of comments are highly appreciated.

Quoted 10 lines

Review

Quoted 7 lines
(quoted diff) +7 -0
+	sn->sysctl_table[0].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED];
+	sn->sysctl_table[1].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
+	sn->sysctl_table[2].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
+	sn->sysctl_table[3].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED];
+	sn->sysctl_table[4].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
+	sn->sysctl_table[5].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
+	sn->sysctl_table[6].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];

Please use an iteration to avoid these repetitve overly long lines.

Ah, thanks a lot! Indeed.

- Cyrill -

#17 lore raw

[Cyrill Gorcunov - Mon, Mar 09, 2009 at 10:07:44PM +0300]
...

| >> +	sn->sysctl_table[0].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED];
| >> +	sn->sysctl_table[1].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
| >> +	sn->sysctl_table[2].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
| >> +	sn->sysctl_table[3].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED];
| >> +	sn->sysctl_table[4].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
| >> +	sn->sysctl_table[5].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
| >> +	sn->sysctl_table[6].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];
| >
| > Please use an iteration to avoid these repetitve overly long lines.
| >
| 
| Ah, thanks a lot! Indeed.
| 
| 	- Cyrill -

Patrick, if I make it like that (iterations)

	...
	BUILD_BUG_ON(ARRAY_SIZE(sctp_compat_sysctl_table) != SCTP_CONNTRACK_MAX);

	for (i = 0; i < ARRAY_SIZE(sctp_compat_sysctl_table) - 1; i++)
		sn->compat_sysctl_table[i].data = &sn->sctp_timeouts[i + 1];

	...

it seems the code become hard to follow. Yes it was long (repetitive) lines but it was obvious what is set for every table entry and easy to find what should be changed if SCTP_ enumeration is changed or table entry removed (for some reason). I could make it shorter in length but remain the same explicit assignment. How do you think?

- Cyrill -

#13 lore raw

Re: [RFC 3/4] net: netfilter conntrack - add per-net functionality for SCTP protocol

In reply to Cyrill Gorcunov
Quoted 324 lines · Cyrill Gorcunov

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

---
 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
===================================================================

net/netfilter/nf_conntrack_proto_sctp.c +129 -39
@@ -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 &&
@@ -540,54 +554,49 @@ static int nlattr_to_sctp(struct nlattr 
 #endif
 
 #ifdef CONFIG_SYSCTL
-static unsigned int sctp_sysctl_table_users;
-static struct ctl_table_header *sctp_sysctl_header;
+/*
+ * we use these tables as templates when create per-net syctl tables
+ * tables data will be 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,
@@ -601,49 +610,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,
@@ -653,7 +655,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,
@@ -673,14 +675,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 = {
@@ -701,21 +695,123 @@ 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;
+
 #ifdef CONFIG_SYSCTL
-	.ctl_table_users	= &sctp_sysctl_table_users,
-	.ctl_table_header	= &sctp_sysctl_header,
-	.ctl_table		= sctp_sysctl_table,
+	err = -ENOMEM;
+	sn->sysctl_table = kmemdup(sctp_sysctl_table,
+			sizeof(sctp_sysctl_table), GFP_KERNEL);
+	if (!sn->sysctl_table)
+		goto out;
+
+	sn->sysctl_table[0].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED];
+	sn->sysctl_table[1].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
+	sn->sysctl_table[2].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
+	sn->sysctl_table[3].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED];
+	sn->sysctl_table[4].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
+	sn->sysctl_table[5].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
+	sn->sysctl_table[6].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];
+
+	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;
+
+	sn->compat_sysctl_table[0].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED];
+	sn->compat_sysctl_table[1].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
+	sn->compat_sysctl_table[2].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
+	sn->compat_sysctl_table[3].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED];
+	sn->compat_sysctl_table[4].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
+	sn->compat_sysctl_table[5].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
+	sn->compat_sysctl_table[6].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];
+
+	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 = {

net/netfilter/nf_conntrack_proto_sctp.c static struct nf_conntrack_l4proto nf_co · line 808

Quoted 10 lines
net/netfilter/nf_conntrack_proto_sctp.c +3 -0
+	.init = sctp_net_init,
+	.exit = sctp_net_exit,
 };
 
 static int __init nf_conntrack_proto_sctp_init(void)
 {
 	int ret;
 
+	ret = register_pernet_gen_device(&sctp_net_id, &sctp_net_ops);
 

register_pernet_gen_subsys ?

Quoted 35 lines
net/netfilter/nf_conntrack_proto_sctp.c +4 -1
+	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);
net/netfilter/nf_conntrack_proto_sctp.c +3 -1
 	if (ret) {
@@ -727,12 +823,15 @@ static int __init nf_conntrack_proto_sct
 
  cleanup_sctp4:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
+ cleanup_net:
+	unregister_pernet_gen_device(sctp_net_id, &sctp_net_ops);
  out:
 	return ret;
 }
 
 static void __exit nf_conntrack_proto_sctp_fini(void)
 {
+	unregister_pernet_gen_device(sctp_net_id, &sctp_net_ops);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
 }
 
--

To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#4 lore raw

Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol

In reply to a message not in the archive
Quoted 19 lines · Daniel Lezcano
Quoted 18 lines · Cyrill Gorcunov

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

---
 net/netfilter/nf_conntrack_proto_dccp.c |  148 
++++++++++++++++++++++++--------
 1 file changed, 111 insertions(+), 37 deletions(-)

static int __init nf_conntrack_proto_dccp_init(void)

 {
     int err;
net/netfilter/nf_conntrack_proto_dccp.c +1 -1
-    err = nf_conntrack_l4proto_register(&dccp_proto4);
+    err = register_pernet_gen_device(&dccp_net_id, &dccp_net_ops);

[ cut ]

Quoted 1 line

Shouldn't it be register_pernet_gen_subsys ?

If you use register_pernet_gen_device, your subsystem will be deleted before the network devices and potentially you can receive a packet even if your subsystem is already freed.

Eric did a fix for tcp and icmp a few weeks ago. I thing its explanation is better than mine :) it is the commit 6eb0777228f31932fc941eafe8b08848466630a1 for net-2.6

Thanks.
-- Daniel

#5 lore raw

Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol

Quoted 21 lines · Daniel Lezcano
Quoted 13 lines · Daniel Lezcano
Quoted 11 lines · Cyrill Gorcunov

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

---
 net/netfilter/nf_conntrack_proto_dccp.c |  148
++++++++++++++++++++++++--------
 1 file changed, 111 insertions(+), 37 deletions(-)
Quoted 6 lines
Quoted 6 lines

static int __init nf_conntrack_proto_dccp_init(void)

 {
    int err;

- err = nf_conntrack_l4proto_register(&dccp_proto4);
+ err = register_pernet_gen_device(&dccp_net_id, &dccp_net_ops);

Quoted 3 lines

[ cut ]

Quoted 2 lines

Shouldn't it be register_pernet_gen_subsys ?

No, I believe. By using register_pernet_gen_device I'm allowed to not modify 'struct net' and friends and keep all I need in my own pointer retrieved thru per-net gen-device id I've registered.

Quoted 5 lines

If you use register_pernet_gen_device, your subsystem will be deleted before the network devices and potentially you can receive a packet even if your subsystem is already freed.

Quoted 7 lines

Eric did a fix for tcp and icmp a few weeks ago. I thing its explanation is better than mine :)
it is the commit 6eb0777228f31932fc941eafe8b08848466630a1 for net-2.6

Thanks.
-- Daniel

Thanks a lot Daniel, will check!

maintainer
#10 lore raw

Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol

In reply to a message not in the archive

From: Daniel Lezcano <[email protected]>
Date: Tue, 10 Mar 2009 11:19:18 +0100

Quoted 8 lines

net/netfilter/nf_conntrack_proto_dccp.c static struct nf_conntrack_l4proto dccp_ · line 857

Quoted 6 lines

static int __init nf_conntrack_proto_dccp_init(void) {

net/netfilter/nf_conntrack_proto_dccp.c +1 -0
 	int err;
 -	err = nf_conntrack_l4proto_register(&dccp_proto4);
+	err = register_pernet_gen_device(&dccp_net_id, &dccp_net_ops);

Shouldn't it be register_pernet_gen_subsys ?

Do I really have to carefully and meticuliously scan down hundreds and hundreds of irrelevant quoted patch text just to see what bit you're commenting on?

Please, just provide the necessary context of the patch for your comments, don't quote the whole thing :-(

Thanks.

#6 lore raw

Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol

In reply to Cyrill Gorcunov
Quoted 19 lines · Cyrill Gorcunov
Quoted 18 lines · Daniel Lezcano
Quoted 17 lines · Daniel Lezcano
Quoted 16 lines · Cyrill Gorcunov

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

---
 net/netfilter/nf_conntrack_proto_dccp.c |  148
++++++++++++++++++++++++--------
 1 file changed, 111 insertions(+), 37 deletions(-)

static int __init nf_conntrack_proto_dccp_init(void)

 {
    int err;

- err = nf_conntrack_l4proto_register(&dccp_proto4);
+ err = register_pernet_gen_device(&dccp_net_id, &dccp_net_ops);

Quoted 6 lines
Quoted 2 lines

[ cut ]

Quoted 1 line

Shouldn't it be register_pernet_gen_subsys ?

No, I believe. By using register_pernet_gen_device I'm allowed to not modify 'struct net' and friends and keep all I need in my own pointer retrieved thru per-net gen-device id I've registered.

I believe Daniel means, that we need the register_xxx_get_subsys call for subsystems, rather than devices, that will behave according to the generic net pointers.

Daniel, am I right with this suggestion?

Quoted 14 lines
Quoted 11 lines

If you use register_pernet_gen_device, your subsystem will be deleted before the network devices and potentially you can receive a packet even if your subsystem is already freed.

Eric did a fix for tcp and icmp a few weeks ago. I thing its explanation is better than mine :)
it is the commit 6eb0777228f31932fc941eafe8b08848466630a1 for net-2.6

Thanks.
-- Daniel

Thanks a lot Daniel, will check!

#7 lore raw

Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol

On Tue, Mar 10, 2009 at 2:35 PM, Pavel Emelyanov <[email protected]> wrote:
...

Quoted 13 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

static int __init nf_conntrack_proto_dccp_init(void)

 {
    int err;

- err = nf_conntrack_l4proto_register(&dccp_proto4);
+ err = register_pernet_gen_device(&dccp_net_id, &dccp_net_ops);

Quoted 6 lines
Quoted 2 lines

[ cut ]

Quoted 1 line

Shouldn't it be register_pernet_gen_subsys ?

No, I believe. By using register_pernet_gen_device I'm allowed to not modify 'struct net' and friends and keep all I need in my own pointer retrieved thru per-net gen-device id I've registered.

Quoted 6 lines

I believe Daniel means, that we need the register_xxx_get_subsys call for subsystems, rather than devices, that will behave according to the generic net pointers.

Daniel, am I right with this suggestion?

...
Ah, yes, just checked register_pernet_gen_subsys -- it's what I need. Thanks!

#8 lore raw

Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol

Quoted 9 lines
Quoted 6 lines

I believe Daniel means, that we need the register_xxx_get_subsys call for subsystems, rather than devices, that will behave according to the generic net pointers.

Daniel, am I right with this suggestion?

...
Ah, yes, just checked register_pernet_gen_subsys -- it's what I need. Thanks!

Good. This would require some factorization work as well. Cyrill, your turn ;)

#9 lore raw

Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol

In reply to Cyrill Gorcunov
Quoted 25 lines · Cyrill Gorcunov

On Tue, Mar 10, 2009 at 2:35 PM, Pavel Emelyanov <[email protected]> wrote:
...

Quoted 22 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

static int __init nf_conntrack_proto_dccp_init(void)

 {
    int err;

- err = nf_conntrack_l4proto_register(&dccp_proto4);
+ err = register_pernet_gen_device(&dccp_net_id, &dccp_net_ops);

Quoted 8 lines
Quoted 4 lines

[ cut ]

Quoted 2 lines

Shouldn't it be register_pernet_gen_subsys ?

No, I believe. By using register_pernet_gen_device I'm allowed to not modify 'struct net' and friends and keep all I need in my own pointer retrieved thru per-net gen-device id I've registered.

I believe Daniel means, that we need the register_xxx_get_subsys call for subsystems, rather than devices, that will behave according to the generic net pointers.

Daniel, am I right with this suggestion?

Correct, otherwise that can lead to a kernel panic if you receive a packet while the namespace is exiting.

Quoted 3 lines

...
Ah, yes, just checked register_pernet_gen_subsys -- it's what I need. Thanks!

You are welcome :)

-- Daniel

#11 lore raw

Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol

In reply to David Miller
Quoted 14 lines · David Miller

From: Daniel Lezcano <[email protected]>
Date: Tue, 10 Mar 2009 11:19:18 +0100

Quoted 9 lines

net/netfilter/nf_conntrack_proto_dccp.c static struct nf_conntrack_l4proto dccp_ · line 857

Quoted 7 lines

static int __init nf_conntrack_proto_dccp_init(void) {

net/netfilter/nf_conntrack_proto_dccp.c +1 -0
 	int err;
 -	err = nf_conntrack_l4proto_register(&dccp_proto4);
+	err = register_pernet_gen_device(&dccp_net_id, &dccp_net_ops);

Shouldn't it be register_pernet_gen_subsys ?

Quoted 7 lines

Do I really have to carefully and meticuliously scan down hundreds and hundreds of irrelevant quoted patch text just to see what bit you're commenting on?

Please, just provide the necessary context of the patch for your comments, don't quote the whole thing :-(

Sorry, I will do that in the future.

-- Daniel