* [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol
2009-03-28 22:33 [patch 0/5] nf conntrack protos pernet functionality v3 Cyrill Gorcunov
@ 2009-03-28 22:33 ` Cyrill Gorcunov
2009-03-28 22:33 ` [patch 2/5] net: netfilter conntrack - add per-net functionality for SCTP protocol Cyrill Gorcunov
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ 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-icmp --]
[-- Type: text/plain, Size: 7266 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
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 11 ++
net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 125 +++++++++++++++++++++++--
3 files changed, 130 insertions(+), 9 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
@@ -21,4 +21,7 @@ extern void nf_conntrack_ipv4_compat_fin
extern void need_ipv4_conntrack(void);
+extern int nf_ct_icmp_proto_init(void);
+extern void nf_ct_icmp_proto_fini(void);
+
#endif /*_NF_CONNTRACK_IPV4_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 cleanup_tcp;
}
+ ret = nf_ct_icmp_proto_init();
+ if (ret < 0) {
+ printk("nf_conntrack_ipv4: can't initialize icmp\n");
+ goto cleanup_udp;
+ }
+
ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmp);
if (ret < 0) {
printk("nf_conntrack_ipv4: can't register icmp.\n");
- goto cleanup_udp;
+ goto uninit_icmp;
}
ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv4);
@@ -427,6 +433,8 @@ static int __init nf_conntrack_l3proto_i
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
cleanup_icmp:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
+ uninit_icmp:
+ nf_ct_icmp_proto_fini();
cleanup_udp:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
cleanup_tcp:
@@ -445,6 +453,7 @@ static void __exit nf_conntrack_l3proto_
nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
+ nf_ct_icmp_proto_fini();
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
nf_unregister_sockopt(&so_getorigdst);
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
@@ -20,7 +20,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 +110,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 +291,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 +307,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 +337,101 @@ 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
- .ctl_table_header = &icmp_sysctl_header,
- .ctl_table = icmp_sysctl_table,
+ 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
- .ctl_compat_table = icmp_compat_sysctl_table,
+ 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
+ unregister_net_sysctl_table(in->sysctl_header);
+ kfree(in->sysctl_table);
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ 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 nf_ct_icmp_proto_init(void)
+{
+ return register_pernet_gen_subsys(&icmp_net_id, &icmp_net_ops);
+}
+EXPORT_SYMBOL_GPL(nf_ct_icmp_proto_init);
+
+void nf_ct_icmp_proto_fini(void)
+{
+ unregister_pernet_gen_subsys(icmp_net_id, &icmp_net_ops);
+}
+EXPORT_SYMBOL_GPL(nf_ct_icmp_proto_fini);
^ permalink raw reply [flat|nested] 7+ messages in thread* [patch 2/5] net: netfilter conntrack - add per-net functionality for SCTP protocol
2009-03-28 22:33 [patch 0/5] nf conntrack protos pernet functionality v3 Cyrill Gorcunov
2009-03-28 22:33 ` [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol Cyrill Gorcunov
@ 2009-03-28 22:33 ` Cyrill Gorcunov
2009-03-28 22:33 ` [patch 3/5] net: netfilter conntrack - add per-net functionality for TCP protocol Cyrill Gorcunov
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ 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-sctp --]
[-- Type: text/plain, Size: 11164 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>
---
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[i - 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] 7+ messages in thread* [patch 3/5] net: netfilter conntrack - add per-net functionality for TCP protocol
2009-03-28 22:33 [patch 0/5] nf conntrack protos pernet functionality v3 Cyrill Gorcunov
2009-03-28 22:33 ` [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol Cyrill Gorcunov
2009-03-28 22:33 ` [patch 2/5] net: netfilter conntrack - add per-net functionality for SCTP protocol Cyrill Gorcunov
@ 2009-03-28 22:33 ` Cyrill Gorcunov
2009-03-28 22:33 ` [patch 4/5] net: netfilter conntrack - add per-net functionality for UDP protocol Cyrill Gorcunov
2009-03-28 22:33 ` [patch 5/5] net: netfilter conntrack - add per-net functionality for UDPLITE protocol Cyrill Gorcunov
4 siblings, 0 replies; 7+ 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-tcp --]
[-- Type: text/plain, Size: 21986 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 | 12 -
net/netfilter/nf_conntrack_proto_tcp.c | 292 ++++++++++++++++++-------
5 files changed, 241 insertions(+), 80 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
@@ -24,4 +24,7 @@ extern void need_ipv4_conntrack(void);
extern int nf_ct_icmp_proto_init(void);
extern void nf_ct_icmp_proto_fini(void);
+extern int nf_ct_tcp_proto_init(void);
+extern void nf_ct_tcp_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
@@ -20,4 +20,7 @@ struct inet_frags_ctl;
#include <linux/sysctl.h>
extern struct ctl_table nf_ct_ipv6_sysctl_table[];
+extern int nf_ct_tcp_proto_init(void);
+extern void nf_ct_tcp_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
@@ -383,10 +383,16 @@ static int __init nf_conntrack_l3proto_i
return ret;
}
+ ret = nf_ct_tcp_proto_init();
+ if (ret < 0) {
+ printk("nf_conntrack_ipv4: can't initialize tcp.\n");
+ goto cleanup_sockopt;
+ }
+
ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp4);
if (ret < 0) {
printk("nf_conntrack_ipv4: can't register tcp.\n");
- goto cleanup_sockopt;
+ goto uninit_tcp;
}
ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp4);
@@ -439,6 +445,8 @@ static int __init nf_conntrack_l3proto_i
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
cleanup_tcp:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
+ uninit_tcp:
+ nf_ct_tcp_proto_fini();
cleanup_sockopt:
nf_unregister_sockopt(&so_getorigdst);
return ret;
@@ -456,6 +464,7 @@ static void __exit nf_conntrack_l3proto_
nf_ct_icmp_proto_fini();
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
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
@@ -384,10 +384,17 @@ static int __init nf_conntrack_l3proto_i
printk("nf_conntrack_ipv6: can't initialize frag6.\n");
return ret;
}
+
+ ret = nf_ct_tcp_proto_init();
+ if (ret < 0) {
+ printk("nf_conntrack_ipv6: can't initialize tcp.\n");
+ goto cleanup_frag6;
+ }
+
ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6);
if (ret < 0) {
printk("nf_conntrack_ipv6: can't register tcp.\n");
- goto cleanup_frag6;
+ goto uninit_tcp;
}
ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6);
@@ -425,6 +432,8 @@ static int __init nf_conntrack_l3proto_i
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
cleanup_tcp:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
+ uninit_tcp:
+ nf_ct_tcp_proto_fini();
cleanup_frag6:
nf_ct_frag6_cleanup();
return ret;
@@ -438,6 +447,7 @@ static void __exit nf_conntrack_l3proto_
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
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_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,54 @@ static const u8 tcp_conntracks[2][6][TCP
}
};
+static DEFINE_MUTEX(proto_ref_lock);
+static int proto_ref;
+
+/* 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 +511,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 +689,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 +834,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 +973,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 +987,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 +1032,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 +1051,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 +1066,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 +1225,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 +1290,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 +1297,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 +1304,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 +1317,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 +1372,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 +1379,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 +1386,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 +1418,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 +1442,152 @@ 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
- .ctl_table_users = &tcp_sysctl_table_users,
- .ctl_table_header = &tcp_sysctl_header,
- .ctl_table = tcp_sysctl_table,
+#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
+ 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,
+};
+
+int nf_ct_tcp_proto_init(void)
+{
+ int err = 0;
+
+ mutex_lock(&proto_ref_lock);
+ if (!proto_ref++)
+ err = register_pernet_gen_subsys(&tcp_net_id, &tcp_net_ops);
+ mutex_unlock(&proto_ref_lock);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(nf_ct_tcp_proto_init);
+
+void nf_ct_tcp_proto_fini(void)
+{
+ mutex_lock(&proto_ref_lock);
+ if (!--proto_ref)
+ unregister_pernet_gen_subsys(tcp_net_id, &tcp_net_ops);
+ mutex_unlock(&proto_ref_lock);
+}
+EXPORT_SYMBOL_GPL(nf_ct_tcp_proto_fini);
^ permalink raw reply [flat|nested] 7+ 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
` (2 preceding siblings ...)
2009-03-28 22:33 ` [patch 3/5] net: netfilter conntrack - add per-net functionality for TCP protocol Cyrill Gorcunov
@ 2009-03-28 22:33 ` Cyrill Gorcunov
2009-03-28 22:33 ` [patch 5/5] net: netfilter conntrack - add per-net functionality for UDPLITE protocol Cyrill Gorcunov
4 siblings, 0 replies; 7+ 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] 7+ messages in thread* [patch 5/5] net: netfilter conntrack - add per-net functionality for UDPLITE protocol
2009-03-28 22:33 [patch 0/5] nf conntrack protos pernet functionality v3 Cyrill Gorcunov
` (3 preceding siblings ...)
2009-03-28 22:33 ` [patch 4/5] net: netfilter conntrack - add per-net functionality for UDP protocol Cyrill Gorcunov
@ 2009-03-28 22:33 ` Cyrill Gorcunov
4 siblings, 0 replies; 7+ 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-udplite --]
[-- Type: text/plain, Size: 6151 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>
---
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] 7+ messages in thread