* [patch 3/5] net: netfilter conntrack - add per-net functionality for TCP protocol
2009-03-26 16:05 [patch 0/5] nf protos pernet functionality fresh attempt Cyrill Gorcunov
@ 2009-03-26 16:05 ` Cyrill Gorcunov
0 siblings, 0 replies; 7+ messages in thread
From: Cyrill Gorcunov @ 2009-03-26 16:05 UTC (permalink / raw)
To: kaber, netfilter-devel, xemul, daniel.lezcano; +Cc: Cyrill Gorcunov
[-- Attachment #1: net-nf-conntrack-proto-tcp --]
[-- Type: text/plain, Size: 17781 bytes --]
Module specific data moved into per-net site and being allocated/freed
during net namespace creation/deletion. For this reason module_init/exit
calls added.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
net/netfilter/nf_conntrack_proto_tcp.c | 281 +++++++++++++++++++++++----------
1 file changed, 203 insertions(+), 78 deletions(-)
Index: linux-2.6.git/net/netfilter/nf_conntrack_proto_tcp.c
===================================================================
--- linux-2.6.git.orig/net/netfilter/nf_conntrack_proto_tcp.c
+++ linux-2.6.git/net/netfilter/nf_conntrack_proto_tcp.c
@@ -18,6 +18,9 @@
#include <net/tcp.h>
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
@@ -31,20 +34,6 @@
/* Protects ct->proto.tcp */
static DEFINE_RWLOCK(tcp_lock);
-/* "Be conservative in what you do,
- be liberal in what you accept from others."
- If it's non-zero, we mark only out of window RST segments as INVALID. */
-static int nf_ct_tcp_be_liberal __read_mostly = 0;
-
-/* If it is set to zero, we disable picking up already established
- connections. */
-static int nf_ct_tcp_loose __read_mostly = 1;
-
-/* Max number of the retransmitted packets without receiving an (acceptable)
- ACK from the destination. If this number is reached, a shorter timer
- will be started. */
-static int nf_ct_tcp_max_retrans __read_mostly = 3;
-
/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
closely. They're more complex. --RR */
@@ -66,23 +55,6 @@ static const char *const tcp_conntrack_n
#define HOURS * 60 MINS
#define DAYS * 24 HOURS
-/* RFC1122 says the R2 limit should be at least 100 seconds.
- Linux uses 15 packets as limit, which corresponds
- to ~13-30min depending on RTO. */
-static unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS;
-static unsigned int nf_ct_tcp_timeout_unacknowledged __read_mostly = 5 MINS;
-
-static unsigned int tcp_timeouts[TCP_CONNTRACK_MAX] __read_mostly = {
- [TCP_CONNTRACK_SYN_SENT] = 2 MINS,
- [TCP_CONNTRACK_SYN_RECV] = 60 SECS,
- [TCP_CONNTRACK_ESTABLISHED] = 5 DAYS,
- [TCP_CONNTRACK_FIN_WAIT] = 2 MINS,
- [TCP_CONNTRACK_CLOSE_WAIT] = 60 SECS,
- [TCP_CONNTRACK_LAST_ACK] = 30 SECS,
- [TCP_CONNTRACK_TIME_WAIT] = 2 MINS,
- [TCP_CONNTRACK_CLOSE] = 10 SECS,
-};
-
#define sNO TCP_CONNTRACK_NONE
#define sSS TCP_CONNTRACK_SYN_SENT
#define sSR TCP_CONNTRACK_SYN_RECV
@@ -260,6 +232,51 @@ static const u8 tcp_conntracks[2][6][TCP
}
};
+/* per-net specifics */
+static int tcp_net_id;
+struct tcp_net {
+ /*
+ * "Be conservative in what you do,
+ * be liberal in what you accept from others."
+ * If it's non-zero, we mark only out of window
+ * RST segments as INVALID.
+ */
+ int tcp_be_liberal;
+ /*
+ * If it is set to zero, we disable picking up
+ * already established connections.
+ */
+ int tcp_loose;
+ /*
+ * Max number of the retransmitted packets without
+ * receiving an (acceptable) ACK from the destination.
+ * If this number is reached, a shorter timer will be started.
+ */
+ int tcp_max_retrans;
+ /*
+ * RFC1122 says the R2 limit should be at least 100 seconds.
+ * Linux uses 15 packets as limit, which corresponds
+ * to ~13-30min depending on RTO.
+ */
+ unsigned int tcp_timeout_max_retrans;
+ unsigned int tcp_timeout_unacknowledged;
+
+ unsigned int tcp_timeouts[TCP_CONNTRACK_MAX];
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_header *sysctl_header;
+ struct ctl_table *sysctl_table;
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ struct ctl_table_header *compat_sysctl_header;
+ struct ctl_table *compat_sysctl_table;
+#endif
+#endif
+};
+
+static inline struct tcp_net *tcp_pernet(struct net *net)
+{
+ return net_generic(net, tcp_net_id);
+}
+
static bool tcp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
struct nf_conntrack_tuple *tuple)
{
@@ -491,6 +508,7 @@ static bool tcp_in_window(const struct n
u_int8_t pf)
{
struct net *net = nf_ct_net(ct);
+ struct tcp_net *tn;
struct ip_ct_tcp_state *sender = &state->seen[dir];
struct ip_ct_tcp_state *receiver = &state->seen[!dir];
const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
@@ -668,8 +686,9 @@ static bool tcp_in_window(const struct n
res = true;
} else {
res = false;
+ tn = tcp_pernet(net);
if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
- nf_ct_tcp_be_liberal)
+ tn->tcp_be_liberal)
res = true;
if (!res && LOG_INVALID(net, IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
@@ -812,6 +831,7 @@ static int tcp_packet(struct nf_conn *ct
unsigned int hooknum)
{
struct net *net = nf_ct_net(ct);
+ struct tcp_net *tn;
struct nf_conntrack_tuple *tuple;
enum tcp_conntrack new_state, old_state;
enum ip_conntrack_dir dir;
@@ -950,6 +970,8 @@ static int tcp_packet(struct nf_conn *ct
ct->proto.tcp.last_index = index;
ct->proto.tcp.last_dir = dir;
+ tn = tcp_pernet(net);
+
pr_debug("tcp_conntracks: ");
nf_ct_dump_tuple(tuple);
pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
@@ -962,15 +984,15 @@ static int tcp_packet(struct nf_conn *ct
&& new_state == TCP_CONNTRACK_FIN_WAIT)
ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
- if (ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans &&
- tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans)
- timeout = nf_ct_tcp_timeout_max_retrans;
+ if (ct->proto.tcp.retrans >= tn->tcp_max_retrans &&
+ tn->tcp_timeouts[new_state] > tn->tcp_timeout_max_retrans)
+ timeout = tn->tcp_timeout_max_retrans;
else if ((ct->proto.tcp.seen[0].flags | ct->proto.tcp.seen[1].flags) &
IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED &&
- tcp_timeouts[new_state] > nf_ct_tcp_timeout_unacknowledged)
- timeout = nf_ct_tcp_timeout_unacknowledged;
+ tn->tcp_timeouts[new_state] > tn->tcp_timeout_unacknowledged)
+ timeout = tn->tcp_timeout_unacknowledged;
else
- timeout = tcp_timeouts[new_state];
+ timeout = tn->tcp_timeouts[new_state];
write_unlock_bh(&tcp_lock);
nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct);
@@ -1007,6 +1029,7 @@ static bool tcp_new(struct nf_conn *ct,
{
enum tcp_conntrack new_state;
const struct tcphdr *th;
+ struct tcp_net *tn;
struct tcphdr _tcph;
const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[0];
const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[1];
@@ -1025,6 +1048,8 @@ static bool tcp_new(struct nf_conn *ct,
return false;
}
+ tn = tcp_pernet(nf_ct_net(ct));
+
if (new_state == TCP_CONNTRACK_SYN_SENT) {
/* SYN packet */
ct->proto.tcp.seen[0].td_end =
@@ -1038,7 +1063,7 @@ static bool tcp_new(struct nf_conn *ct,
tcp_options(skb, dataoff, th, &ct->proto.tcp.seen[0]);
ct->proto.tcp.seen[1].flags = 0;
- } else if (nf_ct_tcp_loose == 0) {
+ } else if (tn->tcp_loose == 0) {
/* Don't try to pick up connections. */
return false;
} else {
@@ -1197,75 +1222,64 @@ static int tcp_nlattr_tuple_size(void)
#endif
#ifdef CONFIG_SYSCTL
-static unsigned int tcp_sysctl_table_users;
-static struct ctl_table_header *tcp_sysctl_header;
+/* templates, data assigned later */
static struct ctl_table tcp_sysctl_table[] = {
{
.procname = "nf_conntrack_tcp_timeout_syn_sent",
- .data = &tcp_timeouts[TCP_CONNTRACK_SYN_SENT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_syn_recv",
- .data = &tcp_timeouts[TCP_CONNTRACK_SYN_RECV],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_established",
- .data = &tcp_timeouts[TCP_CONNTRACK_ESTABLISHED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_fin_wait",
- .data = &tcp_timeouts[TCP_CONNTRACK_FIN_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_close_wait",
- .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_last_ack",
- .data = &tcp_timeouts[TCP_CONNTRACK_LAST_ACK],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_time_wait",
- .data = &tcp_timeouts[TCP_CONNTRACK_TIME_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_close",
- .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_max_retrans",
- .data = &nf_ct_tcp_timeout_max_retrans,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_unacknowledged",
- .data = &nf_ct_tcp_timeout_unacknowledged,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
@@ -1273,7 +1287,6 @@ static struct ctl_table tcp_sysctl_table
{
.ctl_name = NET_NF_CONNTRACK_TCP_LOOSE,
.procname = "nf_conntrack_tcp_loose",
- .data = &nf_ct_tcp_loose,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec,
@@ -1281,7 +1294,6 @@ static struct ctl_table tcp_sysctl_table
{
.ctl_name = NET_NF_CONNTRACK_TCP_BE_LIBERAL,
.procname = "nf_conntrack_tcp_be_liberal",
- .data = &nf_ct_tcp_be_liberal,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec,
@@ -1289,7 +1301,6 @@ static struct ctl_table tcp_sysctl_table
{
.ctl_name = NET_NF_CONNTRACK_TCP_MAX_RETRANS,
.procname = "nf_conntrack_tcp_max_retrans",
- .data = &nf_ct_tcp_max_retrans,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec,
@@ -1303,63 +1314,54 @@ static struct ctl_table tcp_sysctl_table
static struct ctl_table tcp_compat_sysctl_table[] = {
{
.procname = "ip_conntrack_tcp_timeout_syn_sent",
- .data = &tcp_timeouts[TCP_CONNTRACK_SYN_SENT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_syn_recv",
- .data = &tcp_timeouts[TCP_CONNTRACK_SYN_RECV],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_established",
- .data = &tcp_timeouts[TCP_CONNTRACK_ESTABLISHED],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_fin_wait",
- .data = &tcp_timeouts[TCP_CONNTRACK_FIN_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_close_wait",
- .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_last_ack",
- .data = &tcp_timeouts[TCP_CONNTRACK_LAST_ACK],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_time_wait",
- .data = &tcp_timeouts[TCP_CONNTRACK_TIME_WAIT],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_close",
- .data = &tcp_timeouts[TCP_CONNTRACK_CLOSE],
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "ip_conntrack_tcp_timeout_max_retrans",
- .data = &nf_ct_tcp_timeout_max_retrans,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
@@ -1367,7 +1369,6 @@ static struct ctl_table tcp_compat_sysct
{
.ctl_name = NET_IPV4_NF_CONNTRACK_TCP_LOOSE,
.procname = "ip_conntrack_tcp_loose",
- .data = &nf_ct_tcp_loose,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec,
@@ -1375,7 +1376,6 @@ static struct ctl_table tcp_compat_sysct
{
.ctl_name = NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL,
.procname = "ip_conntrack_tcp_be_liberal",
- .data = &nf_ct_tcp_be_liberal,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec,
@@ -1383,7 +1383,6 @@ static struct ctl_table tcp_compat_sysct
{
.ctl_name = NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS,
.procname = "ip_conntrack_tcp_max_retrans",
- .data = &nf_ct_tcp_max_retrans,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec,
@@ -1416,14 +1415,6 @@ struct nf_conntrack_l4proto nf_conntrack
.nlattr_tuple_size = tcp_nlattr_tuple_size,
.nla_policy = nf_ct_port_nla_policy,
#endif
-#ifdef CONFIG_SYSCTL
- .ctl_table_users = &tcp_sysctl_table_users,
- .ctl_table_header = &tcp_sysctl_header,
- .ctl_table = tcp_sysctl_table,
-#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
- .ctl_compat_table = tcp_compat_sysctl_table,
-#endif
-#endif
};
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4);
@@ -1448,10 +1439,144 @@ struct nf_conntrack_l4proto nf_conntrack
.nlattr_tuple_size = tcp_nlattr_tuple_size,
.nla_policy = nf_ct_port_nla_policy,
#endif
+};
+EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp6);
+
+static __net_init int tcp_net_init(struct net *net)
+{
+ struct tcp_net *tn;
+ int err;
+
+ tn = kmalloc(sizeof(*tn), GFP_KERNEL);
+ if (!tn)
+ return -ENOMEM;
+
+ /* default values */
+ tn->tcp_be_liberal = 0;
+ tn->tcp_loose = 1;
+ tn->tcp_max_retrans = 3;
+
+ tn->tcp_timeout_max_retrans = 5 MINS;
+ tn->tcp_timeout_unacknowledged = 5 MINS;
+
+ tn->tcp_timeouts[TCP_CONNTRACK_SYN_SENT] = 2 MINS;
+ tn->tcp_timeouts[TCP_CONNTRACK_SYN_RECV] = 60 SECS;
+ tn->tcp_timeouts[TCP_CONNTRACK_ESTABLISHED] = 5 DAYS;
+ tn->tcp_timeouts[TCP_CONNTRACK_FIN_WAIT] = 2 MINS;
+ tn->tcp_timeouts[TCP_CONNTRACK_CLOSE_WAIT] = 60 SECS;
+ tn->tcp_timeouts[TCP_CONNTRACK_LAST_ACK] = 30 SECS;
+ tn->tcp_timeouts[TCP_CONNTRACK_TIME_WAIT] = 2 MINS;
+ tn->tcp_timeouts[TCP_CONNTRACK_CLOSE] = 10 SECS;
+
+ err = net_assign_generic(net, tcp_net_id, tn);
+ if (err)
+ goto out;
+
+ /*
+ * Pin per-net data to sysctl tables
+ *
+ * We allocate new ctrl tables from predefined templates
+ * and then assign .data fields iteratively, we allowed
+ * to do so since TCP_CONNTRACK_... (enum tcp_conntrack)
+ * is a part of userspace ABI and it's hardly that the enum
+ * entries will be rearranged
+ */
+
+#ifdef CONFIG_SYSCTL
+ {
+ int i;
+ err = -ENOMEM;
+ tn->sysctl_table = kmemdup(tcp_sysctl_table,
+ sizeof(tcp_sysctl_table), GFP_KERNEL);
+ if (!tn->sysctl_table)
+ goto out;
+
+ for (i = TCP_CONNTRACK_SYN_SENT; i < TCP_CONNTRACK_LISTEN; i++)
+ tn->sysctl_table[i - 1].data = &tn->tcp_timeouts[i];
+
+ tn->sysctl_table[8].data = &tn->tcp_timeout_max_retrans;
+ tn->sysctl_table[9].data = &tn->tcp_timeout_unacknowledged;
+ tn->sysctl_table[10].data = &tn->tcp_loose;
+ tn->sysctl_table[11].data = &tn->tcp_be_liberal;
+ tn->sysctl_table[12].data = &tn->tcp_max_retrans;
+
+ tn->sysctl_header = register_net_sysctl_table(net,
+ nf_net_netfilter_sysctl_path, tn->sysctl_table);
+ if (!tn->sysctl_header)
+ goto out_free;
+
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ tn->compat_sysctl_table = kmemdup(tcp_compat_sysctl_table,
+ sizeof(tcp_compat_sysctl_table), GFP_KERNEL);
+ if (!tn->compat_sysctl_table)
+ goto out_sysctl;
+
+ for (i = TCP_CONNTRACK_SYN_SENT; i < TCP_CONNTRACK_LISTEN; i++)
+ tn->compat_sysctl_table[i - 1].data = &tn->tcp_timeouts[i];
+
+ tn->compat_sysctl_table[8].data = &tn->tcp_timeout_max_retrans;
+ tn->compat_sysctl_table[9].data = &tn->tcp_loose;
+ tn->compat_sysctl_table[10].data = &tn->tcp_be_liberal;
+ tn->compat_sysctl_table[11].data = &tn->tcp_max_retrans;
+
+ tn->compat_sysctl_header = register_net_sysctl_table(net,
+ nf_net_ipv4_netfilter_sysctl_path,
+ tn->compat_sysctl_table);
+ if (!tn->compat_sysctl_header)
+ goto out_free_compat;
+#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
+ }
+#endif /* CONFIG_SYSCTL */
+
+ return 0;
+
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+out_free_compat:
+ kfree(tn->compat_sysctl_table);
+#endif
+out_sysctl:
+ unregister_net_sysctl_table(tn->sysctl_header);
+out_free:
+ kfree(tn->sysctl_table);
+#endif
+
+out:
+ kfree(tn);
+ return err;
+}
+
+static __net_exit void tcp_net_exit(struct net *net)
+{
+ struct tcp_net *tn = tcp_pernet(net);
#ifdef CONFIG_SYSCTL
- .ctl_table_users = &tcp_sysctl_table_users,
- .ctl_table_header = &tcp_sysctl_header,
- .ctl_table = tcp_sysctl_table,
+ unregister_net_sysctl_table(tn->sysctl_header);
+ kfree(tn->sysctl_table);
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ unregister_net_sysctl_table(tn->compat_sysctl_header);
+ kfree(tn->compat_sysctl_table);
#endif
+#endif
+ kfree(tn);
+
+ net_assign_generic(net, tcp_net_id, NULL);
};
-EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp6);
+
+static struct pernet_operations tcp_net_ops = {
+ .init = tcp_net_init,
+ .exit = tcp_net_exit,
+};
+
+static int __init nf_ct_tcp_proto_init(void)
+{
+ return register_pernet_gen_subsys(&tcp_net_id, &tcp_net_ops);
+}
+
+static void __exit nf_ct_tcp_proto_fini(void)
+{
+ unregister_pernet_gen_subsys(tcp_net_id, &tcp_net_ops);
+}
+
+module_init(nf_ct_tcp_proto_init);
+module_exit(nf_ct_tcp_proto_fini);
+MODULE_LICENSE("GPL");
^ permalink raw reply [flat|nested] 7+ messages in thread
* [patch 0/5] nf conntrack protos pernet functionality v3
@ 2009-03-28 22:33 Cyrill Gorcunov
2009-03-28 22:33 ` [patch 1/5] net: netfilter conntrack - add per-net functionality for ICMP protocol Cyrill Gorcunov
` (4 more replies)
0 siblings, 5 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
Hi,
here is a new attempt of bringing in per-net functionality
into nf conntrack protos. Please review and test if possible.
It's quite far from ideal solution Alexey proposed (to try to
shrink sysctl's manipulation in one place with all #ifdef
guardians we need) but I didn't manage to implement it right
way yet. So mostly at moment it looks like a code _bloat_ so
rejecting this series would be acceptable solution :)
ICMP v6 is not covered yet as well. Will be done.
Cyrill
^ permalink raw reply [flat|nested] 7+ messages in thread
* [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
end of thread, other threads:[~2009-03-28 22:38 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [patch 3/5] net: netfilter conntrack - add per-net functionality for TCP protocol 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
-- strict thread matches above, loose matches on Subject: below --
2009-03-26 16:05 [patch 0/5] nf protos pernet functionality fresh attempt Cyrill Gorcunov
2009-03-26 16:05 ` [patch 3/5] net: netfilter conntrack - add per-net functionality for TCP protocol Cyrill Gorcunov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).