netfilter conntrack sysctls pernet support
Subsystems (4)
cover netfilter conntrack sysctls pernet support
Hi here are a few patches to bring in per-net functionality for several conntrack protocols: DCCP, SCTP, UDPlite.
Since these protos could be built as modules I've put per-net operations to module init/exit routines. The change I would like you point the attention is that module static variables being marked as __read_mostly become now as dynamically allocated -- is it acceptable trade off?
For protocols being built in (like TCP, UDP, ICMP) for which I made patches too but they are in a bit 'rought' state: in original code there some kind of reference counter to sysctl tables being registered (and they don't have any kind of mb, didn't check if it could be a problem for SMP since they are mostly __init functions) so I need some kind of same functionality to count per-net calls. Will send RFC for these protocols soon.
So eventually I would like to hear some kind of feedback on this. Ideas and any kind of comments are highly appreciated.
The patches are on top of -net-next-2.6
Cyrill
RFC 1/4 net: sysctl_net - use net_eq to compare nets
---
Btw, wouldn't be better to have a special macro/inline to check if net is init_net? Something like is_init_net()
net/sysctl_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sysctl_net.c +1 -1
@@ -61,7 +61,7 @@ static struct ctl_table_root net_sysctl_static int net_ctl_ro_header_perms (struct ctl_table_root *root,struct nsproxy *namespaces,struct ctl_table *table) { -if (namespaces->net_ns == &init_net) +if (net_eq (namespaces->net_ns, &init_net))return table->mode;else return table->mode & ~0222 ;
RFC 2/4 net: netfilter conntrack - add per-net functionality for DCCP protocol
In reply to Cyrill GorcunovModule specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
--- net/netfilter/nf_conntrack_proto_dccp.c | 148 ++++++++++++++++++++++++-------- 1 file changed, 111 insertions(+), 37 deletions(-)
net/netfilter/nf_conntrack_proto_dccp.c +111 -37
@@ -16,6 +16,9 @@#include <linux/skbuff.h> #include <linux/dccp.h> +#include <net/net_namespace.h> +#include <net/netns/generic.h> +#include <linux/netfilter/nfnetlink_conntrack.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_l4proto.h>
@@ -23,8 +26,6 @@static DEFINE_RWLOCK (dccp_lock); -static int nf_ct_dccp_loose__read_mostly =1 ; -/* Timeouts are based on values from RFC4340: * * - REQUEST:
@@ -72,16 +73,6 @@ static int nf_ct_dccp_loose __read_mostl#define DCCP_MSL (2 * 60 * HZ) -static unsigned int dccp_timeout[CT_DCCP_MAX +1 ]__read_mostly = { - [CT_DCCP_REQUEST ] =2 *DCCP_MSL , - [CT_DCCP_RESPOND ] =4 *DCCP_MSL , - [CT_DCCP_PARTOPEN ] =4 *DCCP_MSL , - [CT_DCCP_OPEN ] =12 *3600 *HZ , - [CT_DCCP_CLOSEREQ ] =64 *HZ , - [CT_DCCP_CLOSING ] =64 *HZ , - [CT_DCCP_TIMEWAIT ] =2 *DCCP_MSL , -}; -static const char *const dccp_state_names[] = { [CT_DCCP_NONE ] ="NONE" , [CT_DCCP_REQUEST ] ="REQUEST" ,
@@ -393,6 +384,22 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][D }, }; +/* this module per-net specifics */ +static int dccp_net_id; +struct dccp_net { +int dccp_loose; +unsigned int dccp_timeout[CT_DCCP_MAX +1 ]; +#ifdef CONFIG_SYSCTL +struct ctl_table_header *sysctl_header; +struct ctl_table *sysctl_table; +#endif +}; + +static inline struct dccp_net *dccp_pernet (struct net *net) +{ +return net_generic (net, dccp_net_id); +} +static bool dccp_pkt_to_tuple (const struct sk_buff *skb,unsigned int dataoff,struct nf_conntrack_tuple *tuple) {
@@ -419,6 +426,7 @@ static bool dccp_new(struct nf_conn *ct, unsigned int dataoff) {struct net *net =nf_ct_net (ct); +struct dccp_net *dn;struct dccp_hdr _dh, *dh;const char *msg;u_int8_t state;
@@ -429,7 +437,8 @@ static bool dccp_new(struct nf_conn *ct, state = dccp_state_table[CT_DCCP_ROLE_CLIENT ][dh->dccph_type][CT_DCCP_NONE ];switch (state) {default : -if (nf_ct_dccp_loose ==0 ) { + dn =dccp_pernet (net); +if (dn->dccp_loose ==0 ) { msg ="nf_ct_dccp: not picking up existing connection " ; goto out_invalid; }
@@ -465,6 +474,7 @@ static int dccp_packet(struct nf_conn *c u_int8_t pf, unsigned int hooknum) {struct net *net =nf_ct_net (ct); +struct dccp_net *dn;enum ip_conntrack_dir dir =CTINFO2DIR (ctinfo);struct dccp_hdr _dh, *dh;u_int8_t type, old_state, new_state;
@@ -542,7 +552,9 @@ static int dccp_packet(struct nf_conn *c ct->proto.dccp.last_pkt = type; ct->proto.dccp.state = new_state;write_unlock_bh (&dccp_lock); -nf_ct_refresh_acct (ct, ctinfo, skb, dccp_timeout[new_state]); + + dn =dccp_pernet (net); +nf_ct_refresh_acct (ct, ctinfo, skb, dn->dccp_timeout[new_state]);return NF_ACCEPT ; }
@@ -660,13 +672,14 @@ static int nlattr_to_dccp(struct nlattr#endif #ifdef CONFIG_SYSCTL -static unsigned int dccp_sysctl_table_users; -static struct ctl_table_header *dccp_sysctl_header; -static ctl_table dccp_sysctl_table[] = { +/* + * we use it as a template when create per-net syctl table + * table data will be assigned later + */ +static struct ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_request", - .data = &dccp_timeout[CT_DCCP_REQUEST], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -674,7 +687,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_respond", - .data = &dccp_timeout[CT_DCCP_RESPOND], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -682,7 +694,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_partopen", - .data = &dccp_timeout[CT_DCCP_PARTOPEN], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -690,7 +701,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_open", - .data = &dccp_timeout[CT_DCCP_OPEN], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -698,7 +708,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_closereq", - .data = &dccp_timeout[CT_DCCP_CLOSEREQ], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -706,7 +715,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_closing", - .data = &dccp_timeout[CT_DCCP_CLOSING], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -714,7 +722,6 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_timeout_timewait", - .data = &dccp_timeout[CT_DCCP_TIMEWAIT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -722,8 +729,7 @@ static ctl_table dccp_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_dccp_loose", - .data = &nf_ct_dccp_loose, - .maxlen = sizeof(nf_ct_dccp_loose), + .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec, },
@@ -751,11 +757,6 @@ static struct nf_conntrack_l4proto dccp_ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif -#ifdef CONFIG_SYSCTL - .ctl_table_users = &dccp_sysctl_table_users, - .ctl_table_header = &dccp_sysctl_header, - .ctl_table = dccp_sysctl_table, -#endif };static struct nf_conntrack_l4proto dccp_proto6__read_mostly = {
@@ -776,34 +777,107 @@ static struct nf_conntrack_l4proto dccp_ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif +}; + +static __net_init int dccp_net_init (struct net *net) +{ +struct dccp_net *dn; +int err; + + dn =kmalloc (sizeof (*dn),GFP_KERNEL ); +if (!dn) +return -ENOMEM ; + +/* default values */ + dn->dccp_loose =1 ; + dn->dccp_timeout[CT_DCCP_REQUEST ] =2 *DCCP_MSL ; + dn->dccp_timeout[CT_DCCP_RESPOND ] =4 *DCCP_MSL ; + dn->dccp_timeout[CT_DCCP_PARTOPEN ] =4 *DCCP_MSL ; + dn->dccp_timeout[CT_DCCP_OPEN ] =12 *3600 *HZ ; + dn->dccp_timeout[CT_DCCP_CLOSEREQ ] =64 *HZ ; + dn->dccp_timeout[CT_DCCP_CLOSING ] =64 *HZ ; + dn->dccp_timeout[CT_DCCP_TIMEWAIT ] =2 *DCCP_MSL ; + + err =net_assign_generic (net, dccp_net_id, dn); +if (err) + goto out; +#ifdef CONFIG_SYSCTL - .ctl_table_users = &dccp_sysctl_table_users, - .ctl_table_header = &dccp_sysctl_header, - .ctl_table = dccp_sysctl_table, + err = -ENOMEM ; + dn->sysctl_table =kmemdup (dccp_sysctl_table, +sizeof (dccp_sysctl_table),GFP_KERNEL ); +if (!dn->sysctl_table) + goto out; + + dn->sysctl_table[0 ].data = &dn->dccp_timeout[CT_DCCP_REQUEST ]; + dn->sysctl_table[1 ].data = &dn->dccp_timeout[CT_DCCP_RESPOND ]; + dn->sysctl_table[2 ].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN ]; + dn->sysctl_table[3 ].data = &dn->dccp_timeout[CT_DCCP_OPEN ]; + dn->sysctl_table[4 ].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ ]; + dn->sysctl_table[5 ].data = &dn->dccp_timeout[CT_DCCP_CLOSING ]; + dn->sysctl_table[6 ].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT ]; + dn->sysctl_table[7 ].data = &dn->dccp_loose; + + dn->sysctl_header =register_net_sysctl_table (net, + nf_net_netfilter_sysctl_path, dn->sysctl_table); +if (!dn->sysctl_header) { +kfree (dn->sysctl_table); + goto out; + }#endif + +return 0 ; + +out: +kfree (dn); +return err; +} + +static __net_exit void dccp_net_exit(struct net *net) +{ +struct dccp_net *dn =dccp_pernet (net); +#ifdef CONFIG_SYSCTL +unregister_net_sysctl_table (dn->sysctl_header); +kfree (dn->sysctl_table); +#endif +kfree (dn); + +net_assign_generic (net, dccp_net_id,NULL ); +} + +static struct pernet_operations dccp_net_ops = { + .init = dccp_net_init, + .exit = dccp_net_exit, };static int __init nf_conntrack_proto_dccp_init (void ) {int err; - err =nf_conntrack_l4proto_register (&dccp_proto4); + err =register_pernet_gen_device (&dccp_net_id, &dccp_net_ops);if (err <0 ) goto err1; - err =nf_conntrack_l4proto_register (&dccp_proto6); + err =nf_conntrack_l4proto_register (&dccp_proto4);if (err <0 ) goto err2; + + err =nf_conntrack_l4proto_register (&dccp_proto6); +if (err <0 ) + goto err3;return 0 ; -err2: +err3:nf_conntrack_l4proto_unregister (&dccp_proto4); +err2: +unregister_pernet_gen_device (dccp_net_id, &dccp_net_ops); err1:return err; } static void __exit nf_conntrack_proto_dccp_fini(void) { +unregister_pernet_gen_device (dccp_net_id, &dccp_net_ops);nf_conntrack_l4proto_unregister (&dccp_proto6);nf_conntrack_l4proto_unregister (&dccp_proto4); }
RFC 3/4 net: netfilter conntrack - add per-net functionality for SCTP protocol
In reply to Cyrill GorcunovModule specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
--- net/netfilter/nf_conntrack_proto_sctp.c | 179 ++++++++++++++++++++++++-------- 1 file changed, 139 insertions(+), 40 deletions(-)
net/netfilter/nf_conntrack_proto_sctp.c +139 -40
@@ -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 *cconst struct sctp_chunkhdr *sch;struct sctp_chunkhdr _sch;u_int32_t offset, count; +struct sctp_net *sn;unsigned long map[256 /sizeof (unsigned long )] = {0 }; sh =skb_header_pointer (skb, dataoff,sizeof (_sctph), &_sctph);
@@ -373,7 +386,8 @@ static int sctp_packet(struct nf_conn *c }write_unlock_bh (&sctp_lock); -nf_ct_refresh_acct (ct, ctinfo, skb, sctp_timeouts[new_state]); + sn =sctp_pernet (nf_ct_net (ct)); +nf_ct_refresh_acct (ct, ctinfo, skb, sn->sctp_timeouts[new_state]); if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED && dir == IP_CT_DIR_REPLY &&
@@ -540,54 +554,49 @@ static int nlattr_to_sctp(struct nlattr#endif #ifdef CONFIG_SYSCTL -static unsigned int sctp_sysctl_table_users; -static struct ctl_table_header *sctp_sysctl_header; +/* + * we use these tables as templates when create per-net syctl tables + * tables data will be assigned later + */ static struct ctl_table sctp_sysctl_table[] = { { .procname = "nf_conntrack_sctp_timeout_closed", - .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_cookie_wait", - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_cookie_echoed", - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_established", - .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_shutdown_sent", - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_shutdown_recd", - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent", - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -601,49 +610,42 @@ static struct ctl_table sctp_sysctl_tablstatic struct ctl_table sctp_compat_sysctl_table[] = { { .procname ="ip_conntrack_sctp_timeout_closed" , - .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_cookie_wait" , - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_cookie_echoed" , - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_established" , - .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_shutdown_sent" , - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_shutdown_recd" , - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_shutdown_ack_sent" , - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies,
@@ -653,7 +655,7 @@ static struct ctl_table sctp_compat_sysc } };#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ -#endif +#endif /* CONFIG_SYSCTL */ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4__read_mostly = { .l3proto =PF_INET ,
@@ -673,14 +675,6 @@ static struct nf_conntrack_l4proto nf_co .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif -#ifdef CONFIG_SYSCTL - .ctl_table_users = &sctp_sysctl_table_users, - .ctl_table_header = &sctp_sysctl_header, - .ctl_table = sctp_sysctl_table, -#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT - .ctl_compat_table = sctp_compat_sysctl_table, -#endif -#endif };static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6__read_mostly = {
@@ -701,21 +695,123 @@ static struct nf_conntrack_l4proto nf_co .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif +}; + +static __net_init int sctp_net_init (struct net *net) +{ +struct sctp_net *sn; +int err; + + sn =kmalloc (sizeof (*sn),GFP_KERNEL ); +if (!sn) +return -ENOMEM ; + +/* default values */ + sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED] = 10 SECS; + sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS; + sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS; + sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED] = 5 DAYS; + sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000; + sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000; + sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS; + + err =net_assign_generic (net, sctp_net_id, sn); +if (err) + goto out; +#ifdef CONFIG_SYSCTL - .ctl_table_users = &sctp_sysctl_table_users, - .ctl_table_header = &sctp_sysctl_header, - .ctl_table = sctp_sysctl_table, + err = -ENOMEM ; + sn->sysctl_table =kmemdup (sctp_sysctl_table, +sizeof (sctp_sysctl_table),GFP_KERNEL ); +if (!sn->sysctl_table) + goto out; + + sn->sysctl_table[0 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED ]; + sn->sysctl_table[1 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT ]; + sn->sysctl_table[2 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED ]; + sn->sysctl_table[3 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED ]; + sn->sysctl_table[4 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT ]; + sn->sysctl_table[5 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD ]; + sn->sysctl_table[6 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ]; + + sn->sysctl_header =register_net_sysctl_table (net, + nf_net_netfilter_sysctl_path, sn->sysctl_table); +if (!sn->sysctl_header) + goto out_free; + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + sn->compat_sysctl_table =kmemdup (sctp_compat_sysctl_table, +sizeof (sctp_compat_sysctl_table),GFP_KERNEL ); +if (!sn->compat_sysctl_table) + goto out_sysctl; + + sn->compat_sysctl_table[0 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED ]; + sn->compat_sysctl_table[1 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT ]; + sn->compat_sysctl_table[2 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED ]; + sn->compat_sysctl_table[3 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED ]; + sn->compat_sysctl_table[4 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT ]; + sn->compat_sysctl_table[5 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD ]; + sn->compat_sysctl_table[6 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ]; + + sn->compat_sysctl_header =register_net_sysctl_table (net, + nf_net_ipv4_netfilter_sysctl_path, sn->compat_sysctl_table); +if (!sn->compat_sysctl_header) + goto out_free_compat; +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ +#endif /* CONFIG_SYSCTL */ + +return 0 ; + +#ifdef CONFIG_SYSCTL + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +out_free_compat: +kfree (sn->compat_sysctl_table); +#endif +out_sysctl: +unregister_net_sysctl_table (sn->sysctl_header); +out_free: +kfree (sn->sysctl_table); +#endif + +out: +kfree (sn); +return err; +} + +static __net_exit void sctp_net_exit(struct net *net) +{ +struct sctp_net *sn =sctp_pernet (net); +#ifdef CONFIG_SYSCTL +unregister_net_sysctl_table (sn->sysctl_header); +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +unregister_net_sysctl_table (sn->compat_sysctl_header); +kfree (sn->compat_sysctl_table); +#endif +kfree (sn->sysctl_table);#endif +kfree (sn); + +net_assign_generic (net, sctp_net_id,NULL ); +} + +static struct pernet_operations sctp_net_ops = { + .init = sctp_net_init, + .exit = sctp_net_exit, };static int __init nf_conntrack_proto_sctp_init (void ) {int ret; + ret =register_pernet_gen_device (&sctp_net_id, &sctp_net_ops); +if (ret <0 ) + goto out; + ret =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_sctp4);if (ret) {printk ("nf_conntrack_l4proto_sctp4: protocol register failed\n" ); - goto out; + goto cleanup_net; } ret =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_sctp6);if (ret) {
@@ -727,12 +823,15 @@ static int __init nf_conntrack_proto_sct cleanup_sctp4:nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_sctp4); + cleanup_net: +unregister_pernet_gen_device (sctp_net_id, &sctp_net_ops); out:return ret; } static void __exit nf_conntrack_proto_sctp_fini(void) { +unregister_pernet_gen_device (sctp_net_id, &sctp_net_ops);nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_sctp6);nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_sctp4); }
RFC 4/4 net: netfilter conntrack - add per-net functionality for UDPLITE protocol
In reply to Cyrill GorcunovModule specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
--- net/netfilter/nf_conntrack_proto_udplite.c | 118 ++++++++++++++++++++++++----- 1 file changed, 99 insertions(+), 19 deletions(-)
net/netfilter/nf_conntrack_proto_udplite.c +99 -19
@@ -17,6 +17,9 @@#include <net/ip6_checksum.h> #include <net/checksum.h> +#include <net/net_namespace.h> +#include <net/netns/generic.h> +#include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv6.h>
@@ -24,8 +27,21 @@#include <net/netfilter/nf_conntrack_ecache.h> #include <net/netfilter/nf_log.h> -static unsigned int nf_ct_udplite_timeout__read_mostly =30 *HZ ; -static unsigned int nf_ct_udplite_timeout_stream__read_mostly =180 *HZ ; +/* this module per-net specifics */ +static int udplite_net_id; +struct udplite_net { +unsigned int udplite_timeout; +unsigned int udplite_timeout_stream; +#ifdef CONFIG_SYSCTL +struct ctl_table_header *sysctl_header; +struct ctl_table *sysctl_table; +#endif +}; + +static inline struct udplite_net *udplite_pernet (struct net *net) +{ +return net_generic (net, udplite_net_id); +} static bool udplite_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
@@ -68,16 +84,18 @@ static int udplite_packet(struct nf_conn u_int8_t pf, unsigned int hooknum) { +struct udplite_net *un =udplite_pernet (nf_ct_net (ct)); +/* If we've seen traffic both ways, this is some kind of UDP stream. Extend timeout. */ if (test_bit (IPS_SEEN_REPLY_BIT , &ct->status)) {nf_ct_refresh_acct (ct, ctinfo, skb, - nf_ct_udplite_timeout_stream); + un->udplite_timeout_stream);/* Also, more likely to be important, and not a probe */ if (!test_and_set_bit (IPS_ASSURED_BIT , &ct->status))nf_conntrack_event_cache (IPCT_STATUS , ct); }else -nf_ct_refresh_acct (ct, ctinfo, skb, nf_ct_udplite_timeout); +nf_ct_refresh_acct (ct, ctinfo, skb, un->udplite_timeout);return NF_ACCEPT ; }
@@ -142,13 +160,14 @@ static int udplite_error(struct net *net } #ifdef CONFIG_SYSCTL -static unsigned int udplite_sysctl_table_users; -static struct ctl_table_header *udplite_sysctl_header; +/* + * we use it as a template when create per-net syctl table + * table data will be assigned later + */ static struct ctl_table udplite_sysctl_table[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_udplite_timeout", - .data = &nf_ct_udplite_timeout, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -156,7 +175,6 @@ static struct ctl_table udplite_sysctl_t { .ctl_name = CTL_UNNUMBERED, .procname = "nf_conntrack_udplite_timeout_stream", - .data = &nf_ct_udplite_timeout_stream, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,
@@ -183,11 +201,6 @@ static struct nf_conntrack_l4proto nf_co .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif -#ifdef CONFIG_SYSCTL - .ctl_table_users = &udplite_sysctl_table_users, - .ctl_table_header = &udplite_sysctl_header, - .ctl_table = udplite_sysctl_table, -#endif }; static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
@@ -206,32 +219,99 @@ static struct nf_conntrack_l4proto nf_co .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif +}; + +static __net_init int udplite_net_init (struct net *net) +{ +struct udplite_net *un; +int err; + + un =kmalloc (sizeof (*un),GFP_KERNEL ); +if (!un) +return -ENOMEM ; + +/* default values */ + un->udplite_timeout =30 *HZ ; + un->udplite_timeout_stream =180 *HZ ; + + err =net_assign_generic (net, udplite_net_id, un); +if (err) + goto out; + +#ifdef CONFIG_SYSCTL + err = -ENOMEM ; + un->sysctl_table =kmemdup (udplite_sysctl_table, +sizeof (udplite_sysctl_table),GFP_KERNEL ); +if (!un->sysctl_table) + goto out; + + un->sysctl_table[0 ].data = &un->udplite_timeout; + un->sysctl_table[1 ].data = &un->udplite_timeout_stream; + + un->sysctl_header =register_net_sysctl_table (net, + nf_net_netfilter_sysctl_path, un->sysctl_table); +if (!un->sysctl_header) + goto out_free; +#endif /* CONFIG_SYSCTL */ + +return 0 ; + +#ifdef CONFIG_SYSCTL +out_free: +kfree (un->sysctl_table); +#endif + +out: +kfree (un); +return err; +} + +static __net_exit void udplite_net_exit(struct net *net) +{ +struct udplite_net *un =udplite_pernet (net);#ifdef CONFIG_SYSCTL - .ctl_table_users = &udplite_sysctl_table_users, - .ctl_table_header = &udplite_sysctl_header, - .ctl_table = udplite_sysctl_table, +unregister_net_sysctl_table (un->sysctl_header); +kfree (un->sysctl_table);#endif +kfree (un); + +net_assign_generic (net, udplite_net_id,NULL ); +} + +static struct pernet_operations udplite_net_ops = { + .init = udplite_net_init, + .exit = udplite_net_exit, };static int __init nf_conntrack_proto_udplite_init (void ) {int err; - err =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_udplite4); + err =register_pernet_gen_device (&udplite_net_id, &udplite_net_ops);if (err <0 ) goto err1; - err =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_udplite6); + + err =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_udplite4);if (err <0 ) goto err2; + + err =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_udplite6); +if (err <0 ) + goto err3; +return 0 ; -err2: + +err3:nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_udplite4); +err2: +unregister_pernet_gen_device (udplite_net_id, &udplite_net_ops); err1:return err; } static void __exit nf_conntrack_proto_udplite_exit(void) { +unregister_pernet_gen_device (udplite_net_id, &udplite_net_ops);nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_udplite6);nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_udplite4); }
First off, *please* CC netfilter-devel on patches relating to netfilter. I've said this a hundred times in direction of the container guys (not sure whether you specifically) and it keeps getting ignored.
Quoted 8 lines · Cyrill Gorcunov
Hi here are a few patches to bring in per-net functionality for several conntrack protocols: DCCP, SCTP, UDPlite.
Since these protos could be built as modules I've put per-net operations to module init/exit routines. The change I would like you point the attention is that module static variables being marked as
__read_mostlybecome now as dynamically allocated -- is it acceptable trade off?
Well, there's no other choice I guess.
Quoted 6 lines
For protocols being built in (like TCP, UDP, ICMP) for which I made patches too but they are in a bit 'rought' state: in original code there some kind of reference counter to sysctl tables being registered (and they don't have any kind of mb, didn't check if it could be a problem for SMP since they are mostly
__initfunctions) so I need some kind of same functionality to count per-net calls.
The tables are shared between IPv4 and IPv6, this keeps track of the number of current users to avoid unregistering it while the AF-specific module for either one is loaded. This would still be a global counter with containers I think since module loading is global and they should be visible in all containers if IPv4 or IPv6 conntrack is loaded.
Review
Quoted 12 lines
Will send RFC for these protocols soon.
So eventually I would like to hear some kind of feedback on this. Ideas and any kind of comments are highly appreciated.
(quoted diff) +7
-0+ sn->sysctl_table[0].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED]; + sn->sysctl_table[1].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT]; + sn->sysctl_table[2].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED]; + sn->sysctl_table[3].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED]; + sn->sysctl_table[4].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT]; + sn->sysctl_table[5].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD]; + sn->sysctl_table[6].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];
Please use an iteration to avoid these repetitve overly long lines.
[Patrick McHardy - Mon, Mar 09, 2009 at 07:47:28PM +0100]
Quoted 3 lines
First off, *please* CC netfilter-devel on patches relating to netfilter. I've said this a hundred times in direction of the container guys (not sure whether you specifically) and it keeps getting ignored.
Ugh... sorry Patrick, my fault, I've noticed this address in MAINTEINERS but NETFILTER section contains 3 list so I messed in which one I should choose. Sorry again.
Quoted 5 lines
Quoted 3 lines · Cyrill Gorcunov
Hi here are a few patches to bring in per-net functionality for several conntrack protocols: DCCP, SCTP, UDPlite.
Quoted 7 lines
Quoted 5 lines
Since these protos could be built as modules I've put per-net operations to module init/exit routines. The change I would like you point the attention is that module static variables being marked as
__read_mostlybecome now as dynamically allocated -- is it acceptable trade off?Well, there's no other choice I guess.
Actually, the possibility I see is to make some union on _all_ structures I put in pernet section so this union will contain max possible size of structure allocated and then create one global slab for this (HW cache aligned). But it would be ugly hack I believe and until we have no other choise I would prefer to not play with this idea :)
Quoted 8 lines
Quoted 7 lines
For protocols being built in (like TCP, UDP, ICMP) for which I made patches too but they are in a bit 'rought' state: in original code there some kind of reference counter to sysctl tables being registered (and they don't have any kind of mb, didn't check if it could be a problem for SMP since they are mostly
__initfunctions) so I need some kind of same functionality to count per-net calls.
Quoted 5 lines
The tables are shared between IPv4 and IPv6, this keeps track of the number of current users to avoid unregistering it while the AF-specific module for either one is loaded. This would still be a global counter with containers I think since module loading is global and they should be visible in all containers if IPv4 or IPv6 conntrack is loaded.
Yes, I even thought about kref usage here but kref doesn't have a few function I need.
Quoted 6 lines
Quoted 5 lines
Will send RFC for these protocols soon.
So eventually I would like to hear some kind of feedback on this. Ideas and any kind of comments are highly appreciated.
Quoted 10 lines
Review
Quoted 7 lines
(quoted diff) +7
-0+ sn->sysctl_table[0].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED]; + sn->sysctl_table[1].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT]; + sn->sysctl_table[2].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED]; + sn->sysctl_table[3].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED]; + sn->sysctl_table[4].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT]; + sn->sysctl_table[5].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD]; + sn->sysctl_table[6].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];Please use an iteration to avoid these repetitve overly long lines.
Ah, thanks a lot! Indeed.
- Cyrill -
[Cyrill Gorcunov - Mon, Mar 09, 2009 at 10:07:44PM +0300]
...
| >> + sn->sysctl_table[0].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED]; | >> + sn->sysctl_table[1].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT]; | >> + sn->sysctl_table[2].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED]; | >> + sn->sysctl_table[3].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED]; | >> + sn->sysctl_table[4].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT]; | >> + sn->sysctl_table[5].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD]; | >> + sn->sysctl_table[6].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT]; | > | > Please use an iteration to avoid these repetitve overly long lines. | > | | Ah, thanks a lot! Indeed. | | - Cyrill -
Patrick, if I make it like that (iterations)
... BUILD_BUG_ON(ARRAY_SIZE(sctp_compat_sysctl_table) != SCTP_CONNTRACK_MAX); for (i = 0; i < ARRAY_SIZE(sctp_compat_sysctl_table) - 1; i++) sn->compat_sysctl_table[i].data = &sn->sctp_timeouts[i + 1]; ...
it seems the code become hard to follow. Yes it was long (repetitive) lines but it was obvious what is set for every table entry and easy to find what should be changed if SCTP_ enumeration is changed or table entry removed (for some reason). I could make it shorter in length but remain the same explicit assignment. How do you think?
- Cyrill -
Re: [RFC 3/4] net: netfilter conntrack - add per-net functionality for SCTP protocol
In reply to Cyrill GorcunovQuoted 324 lines · Cyrill Gorcunov
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
Signed-off-by Cyrill Gorcunov <[email protected]>--- net/netfilter/nf_conntrack_proto_sctp.c | 179 ++++++++++++++++++++++++-------- 1 file changed, 139 insertions(+), 40 deletions(-)Index:
linux-2.6.git/net/netfilter/nf_conntrack_proto_sctp.c
===================================================================net/netfilter/nf_conntrack_proto_sctp.c +129
-39@@ -21,6 +21,9 @@#include <linux/spinlock.h> #include <linux/interrupt.h> +#include <net/net_namespace.h> +#include <net/netns/generic.h> +#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_ecache.h> @@ -49,16 +52,6 @@ static const char *const sctp_conntrack_#define HOURS * 60 MINS#define DAYS * 24 HOURS -static unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX ]__read_mostly = { - [SCTP_CONNTRACK_CLOSED] = 10 SECS, - [SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS, - [SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS, - [SCTP_CONNTRACK_ESTABLISHED] = 5 DAYS, - [SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000, - [SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000, - [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS, -}; -#define sNO SCTP_CONNTRACK_NONE#define sCL SCTP_CONNTRACK_CLOSED#define sCW SCTP_CONNTRACK_COOKIE_WAIT@@ -130,6 +123,25 @@ static const u8 sctp_conntracks[2][9][SC } }; +/* this module per-net specifics */ +static int sctp_net_id; +struct sctp_net { +unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX ]; +#ifdef CONFIG_SYSCTL +struct ctl_table_header *sysctl_header; +struct ctl_table *sysctl_table; +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +struct ctl_table_header *compat_sysctl_header; +struct ctl_table *compat_sysctl_table; +#endif +#endif +}; + +static inline struct sctp_net *sctp_pernet (struct net *net) +{ +return net_generic (net, sctp_net_id); +} +static bool sctp_pkt_to_tuple (const struct sk_buff *skb,unsigned int dataoff,struct nf_conntrack_tuple *tuple) {@@ -297,6 +309,7 @@ static int sctp_packet(struct nf_conn *cconst struct sctp_chunkhdr *sch;struct sctp_chunkhdr _sch;u_int32_t offset, count; +struct sctp_net *sn;unsigned long map[256 /sizeof (unsigned long )] = {0 }; sh =skb_header_pointer (skb, dataoff,sizeof (_sctph), &_sctph);@@ -373,7 +386,8 @@ static int sctp_packet(struct nf_conn *c }write_unlock_bh (&sctp_lock); -nf_ct_refresh_acct (ct, ctinfo, skb, sctp_timeouts[new_state]); + sn =sctp_pernet (nf_ct_net (ct)); +nf_ct_refresh_acct (ct, ctinfo, skb, sn->sctp_timeouts[new_state]); if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED && dir == IP_CT_DIR_REPLY &&@@ -540,54 +554,49 @@ static int nlattr_to_sctp(struct nlattr#endif #ifdef CONFIG_SYSCTL -static unsigned int sctp_sysctl_table_users; -static struct ctl_table_header *sctp_sysctl_header; +/* + * we use these tables as templates when create per-net syctl tables + * tables data will be assigned later + */ static struct ctl_table sctp_sysctl_table[] = { { .procname = "nf_conntrack_sctp_timeout_closed", - .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_cookie_wait", - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_cookie_echoed", - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_established", - .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_shutdown_sent", - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_shutdown_recd", - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, { .procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent", - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT], .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec_jiffies,@@ -601,49 +610,42 @@ static struct ctl_table sctp_sysctl_tablstatic struct ctl_table sctp_compat_sysctl_table[] = { { .procname ="ip_conntrack_sctp_timeout_closed" , - .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_cookie_wait" , - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_cookie_echoed" , - .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_established" , - .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_shutdown_sent" , - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_shutdown_recd" , - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies, }, { .procname ="ip_conntrack_sctp_timeout_shutdown_ack_sent" , - .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ], .maxlen =sizeof (unsigned int ), .mode =0644 , .proc_handler = proc_dointvec_jiffies,@@ -653,7 +655,7 @@ static struct ctl_table sctp_compat_sysc } };#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ -#endif +#endif /* CONFIG_SYSCTL */ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4__read_mostly = { .l3proto =PF_INET ,@@ -673,14 +675,6 @@ static struct nf_conntrack_l4proto nf_co .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif -#ifdef CONFIG_SYSCTL - .ctl_table_users = &sctp_sysctl_table_users, - .ctl_table_header = &sctp_sysctl_header, - .ctl_table = sctp_sysctl_table, -#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT - .ctl_compat_table = sctp_compat_sysctl_table, -#endif -#endif };static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6__read_mostly = {@@ -701,21 +695,123 @@ static struct nf_conntrack_l4proto nf_co .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy,#endif +}; + +static __net_init int sctp_net_init (struct net *net) +{ +struct sctp_net *sn; +int err; + + sn =kmalloc (sizeof (*sn),GFP_KERNEL ); +if (!sn) +return -ENOMEM ; + +/* default values */ + sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED] = 10 SECS; + sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS; + sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS; + sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED] = 5 DAYS; + sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000; + sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000; + sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS; + + err =net_assign_generic (net, sctp_net_id, sn); +if (err) + goto out; +#ifdef CONFIG_SYSCTL - .ctl_table_users = &sctp_sysctl_table_users, - .ctl_table_header = &sctp_sysctl_header, - .ctl_table = sctp_sysctl_table, + err = -ENOMEM ; + sn->sysctl_table =kmemdup (sctp_sysctl_table, +sizeof (sctp_sysctl_table),GFP_KERNEL ); +if (!sn->sysctl_table) + goto out; + + sn->sysctl_table[0 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED ]; + sn->sysctl_table[1 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT ]; + sn->sysctl_table[2 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED ]; + sn->sysctl_table[3 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED ]; + sn->sysctl_table[4 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT ]; + sn->sysctl_table[5 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD ]; + sn->sysctl_table[6 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ]; + + sn->sysctl_header =register_net_sysctl_table (net, + nf_net_netfilter_sysctl_path, sn->sysctl_table); +if (!sn->sysctl_header) + goto out_free; + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + sn->compat_sysctl_table =kmemdup (sctp_compat_sysctl_table, +sizeof (sctp_compat_sysctl_table),GFP_KERNEL ); +if (!sn->compat_sysctl_table) + goto out_sysctl; + + sn->compat_sysctl_table[0 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_CLOSED ]; + sn->compat_sysctl_table[1 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT ]; + sn->compat_sysctl_table[2 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED ]; + sn->compat_sysctl_table[3 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED ]; + sn->compat_sysctl_table[4 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT ]; + sn->compat_sysctl_table[5 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD ]; + sn->compat_sysctl_table[6 ].data = &sn->sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT ]; + + sn->compat_sysctl_header =register_net_sysctl_table (net, + nf_net_ipv4_netfilter_sysctl_path, sn->compat_sysctl_table); +if (!sn->compat_sysctl_header) + goto out_free_compat; +#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ +#endif /* CONFIG_SYSCTL */ + +return 0 ; + +#ifdef CONFIG_SYSCTL + +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +out_free_compat: +kfree (sn->compat_sysctl_table); +#endif +out_sysctl: +unregister_net_sysctl_table (sn->sysctl_header); +out_free: +kfree (sn->sysctl_table); +#endif + +out: +kfree (sn); +return err; +} + +static __net_exit void sctp_net_exit(struct net *net) +{ +struct sctp_net *sn =sctp_pernet (net); +#ifdef CONFIG_SYSCTL +unregister_net_sysctl_table (sn->sysctl_header); +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT +unregister_net_sysctl_table (sn->compat_sysctl_header); +kfree (sn->compat_sysctl_table); +#endif +kfree (sn->sysctl_table);#endif +kfree (sn); + +net_assign_generic (net, sctp_net_id,NULL ); +} + +static struct pernet_operations sctp_net_ops = {
net/netfilter/nf_conntrack_proto_sctp.c static struct nf_conntrack_l4proto nf_co · line 808
Quoted 10 lines
net/netfilter/nf_conntrack_proto_sctp.c +3
-0+ .init = sctp_net_init, + .exit = sctp_net_exit, };static int __init nf_conntrack_proto_sctp_init (void ) {int ret; + ret =register_pernet_gen_device (&sctp_net_id, &sctp_net_ops);
register_pernet_gen_subsys ?
Quoted 35 lines
net/netfilter/nf_conntrack_proto_sctp.c +4
-1+if (ret <0 ) + goto out; + ret =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_sctp4);if (ret) {printk ("nf_conntrack_l4proto_sctp4: protocol register failed\n" ); - goto out; + goto cleanup_net; } ret =nf_conntrack_l4proto_register (&nf_conntrack_l4proto_sctp6);net/netfilter/nf_conntrack_proto_sctp.c +3
-1if (ret) {@@ -727,12 +823,15 @@ static int __init nf_conntrack_proto_sct cleanup_sctp4:nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_sctp4); + cleanup_net: +unregister_pernet_gen_device (sctp_net_id, &sctp_net_ops); out:return ret; } static void __exit nf_conntrack_proto_sctp_fini(void) { +unregister_pernet_gen_device (sctp_net_id, &sctp_net_ops);nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_sctp6);nf_conntrack_l4proto_unregister (&nf_conntrack_l4proto_sctp4); } --To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol
In reply to a message not in the archiveQuoted 19 lines · Daniel Lezcano
Quoted 18 lines · Cyrill Gorcunov
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
Signed-off-by Cyrill Gorcunov <[email protected]>--- net/netfilter/nf_conntrack_proto_dccp.c | 148 ++++++++++++++++++++++++-------- 1 file changed, 111 insertions(+), 37 deletions(-)static int
__initnf_conntrack_proto_dccp_init(void){ int err;net/netfilter/nf_conntrack_proto_dccp.c +1
-1- err =nf_conntrack_l4proto_register (&dccp_proto4); + err =register_pernet_gen_device (&dccp_net_id, &dccp_net_ops);
[ cut ]
Quoted 1 line
Shouldn't it be
register_pernet_gen_subsys?
If you use register_pernet_gen_device, your subsystem will be deleted before the network devices and potentially you can receive a packet even if your subsystem is already freed.
Eric did a fix for tcp and icmp a few weeks ago. I thing its explanation is better than mine :) it is the commit 6eb0777228f31932fc941eafe8b08848466630a1 for net-2.6
Thanks.
-- Daniel
Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol
Quoted 21 lines · Daniel Lezcano
Quoted 13 lines · Daniel Lezcano
Quoted 11 lines · Cyrill Gorcunov
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
Signed-off-by Cyrill Gorcunov <[email protected]>--- net/netfilter/nf_conntrack_proto_dccp.c | 148 ++++++++++++++++++++++++-------- 1 file changed, 111 insertions(+), 37 deletions(-)Quoted 6 lines
Quoted 6 lines
static int
__initnf_conntrack_proto_dccp_init(void){ int err;- err =
nf_conntrack_l4proto_register(&dccp_proto4);
+ err =register_pernet_gen_device(&dccp_net_id, &dccp_net_ops);
Quoted 3 lines
[ cut ]
Quoted 2 lines
Shouldn't it be
register_pernet_gen_subsys?
No, I believe. By using register_pernet_gen_device I'm allowed to not modify 'struct net' and friends and keep all I need in my own pointer retrieved thru per-net gen-device id I've registered.
Quoted 5 lines
If you use
register_pernet_gen_device, your subsystem will be deleted before the network devices and potentially you can receive a packet even if your subsystem is already freed.
Quoted 7 lines
Eric did a fix for tcp and icmp a few weeks ago. I thing its explanation is better than mine :)
it is the commit6eb0777228f31932fc941eafe8b08848466630a1for net-2.6Thanks.
-- Daniel
Thanks a lot Daniel, will check!
David Miller
maintainerRe: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol
In reply to a message not in the archiveFrom: Daniel Lezcano <[email protected]>
Date: Tue, 10 Mar 2009 11:19:18 +0100
Quoted 8 lines
net/netfilter/nf_conntrack_proto_dccp.c static struct nf_conntrack_l4proto dccp_ · line 857
Quoted 6 lines
static int
__initnf_conntrack_proto_dccp_init(void){net/netfilter/nf_conntrack_proto_dccp.c +1
-0int err; - err =nf_conntrack_l4proto_register (&dccp_proto4); + err =register_pernet_gen_device (&dccp_net_id, &dccp_net_ops);Shouldn't it be
register_pernet_gen_subsys?
Do I really have to carefully and meticuliously scan down hundreds and hundreds of irrelevant quoted patch text just to see what bit you're commenting on?
Please, just provide the necessary context of the patch for your comments, don't quote the whole thing :-(
Thanks.
Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol
In reply to Cyrill GorcunovQuoted 19 lines · Cyrill Gorcunov
Quoted 18 lines · Daniel Lezcano
Quoted 17 lines · Daniel Lezcano
Quoted 16 lines · Cyrill Gorcunov
Module specific data moved into per-net site and being allocated/freed during net namespace creation/deletion.
Signed-off-by Cyrill Gorcunov <[email protected]>--- net/netfilter/nf_conntrack_proto_dccp.c | 148 ++++++++++++++++++++++++-------- 1 file changed, 111 insertions(+), 37 deletions(-)static int
__initnf_conntrack_proto_dccp_init(void){ int err;- err =
nf_conntrack_l4proto_register(&dccp_proto4);
+ err =register_pernet_gen_device(&dccp_net_id, &dccp_net_ops);
Quoted 6 lines
Quoted 2 lines
[ cut ]
Quoted 1 line
Shouldn't it be
register_pernet_gen_subsys?No, I believe. By using
register_pernet_gen_deviceI'm allowed to not modify 'struct net' and friends and keep all I need in my own pointer retrieved thru per-net gen-device id I've registered.
I believe Daniel means, that we need the register_xxx_get_subsys call for subsystems, rather than devices, that will behave according to the generic net pointers.
Daniel, am I right with this suggestion?
Quoted 14 lines
Quoted 11 lines
If you use
register_pernet_gen_device, your subsystem will be deleted before the network devices and potentially you can receive a packet even if your subsystem is already freed.Eric did a fix for tcp and icmp a few weeks ago. I thing its explanation is better than mine :)
it is the commit6eb0777228f31932fc941eafe8b08848466630a1for net-2.6Thanks.
-- DanielThanks a lot Daniel, will check!
Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol
On Tue, Mar 10, 2009 at 2:35 PM, Pavel Emelyanov <[email protected]> wrote:
...
Quoted 13 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
static int
__initnf_conntrack_proto_dccp_init(void){ int err;- err =
nf_conntrack_l4proto_register(&dccp_proto4);
+ err =register_pernet_gen_device(&dccp_net_id, &dccp_net_ops);Quoted 6 lines
Quoted 2 lines
[ cut ]
Quoted 1 line
Shouldn't it be
register_pernet_gen_subsys?No, I believe. By using
register_pernet_gen_deviceI'm allowed to not modify 'struct net' and friends and keep all I need in my own pointer retrieved thru per-net gen-device id I've registered.
Quoted 6 lines
I believe Daniel means, that we need the
register_xxx_get_subsyscall for subsystems, rather than devices, that will behave according to the generic net pointers.Daniel, am I right with this suggestion?
...
Ah, yes, just checked register_pernet_gen_subsys -- it's what I need. Thanks!
Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol
Quoted 9 lines
Quoted 6 lines
I believe Daniel means, that we need the
register_xxx_get_subsyscall for subsystems, rather than devices, that will behave according to the generic net pointers.Daniel, am I right with this suggestion?
...
Ah, yes, just checkedregister_pernet_gen_subsys-- it's what I need. Thanks!
Good. This would require some factorization work as well. Cyrill, your turn ;)
Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol
In reply to Cyrill GorcunovQuoted 25 lines · Cyrill Gorcunov
On Tue, Mar 10, 2009 at 2:35 PM, Pavel Emelyanov <[email protected]> wrote:
...Quoted 22 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
static int
__initnf_conntrack_proto_dccp_init(void){ int err;- err =
nf_conntrack_l4proto_register(&dccp_proto4);
+ err =register_pernet_gen_device(&dccp_net_id, &dccp_net_ops);Quoted 8 lines
Quoted 4 lines
[ cut ]
Quoted 2 lines
Shouldn't it be
register_pernet_gen_subsys?No, I believe. By using
register_pernet_gen_deviceI'm allowed to not modify 'struct net' and friends and keep all I need in my own pointer retrieved thru per-net gen-device id I've registered.I believe Daniel means, that we need the
register_xxx_get_subsyscall for subsystems, rather than devices, that will behave according to the generic net pointers.Daniel, am I right with this suggestion?
Correct, otherwise that can lead to a kernel panic if you receive a packet while the namespace is exiting.
Quoted 3 lines
...
Ah, yes, just checkedregister_pernet_gen_subsys-- it's what I need. Thanks!
You are welcome :)
-- Daniel
Re: [RFC 2/4] net: netfilter conntrack - add per-net functionality for DCCP protocol
In reply to David MillerQuoted 14 lines · David Miller
From: Daniel Lezcano <[email protected]>
Date: Tue, 10 Mar 2009 11:19:18 +0100Quoted 9 lines
net/netfilter/nf_conntrack_proto_dccp.c static struct nf_conntrack_l4proto dccp_ · line 857
Quoted 7 lines
static int
__initnf_conntrack_proto_dccp_init(void){net/netfilter/nf_conntrack_proto_dccp.c +1
-0int err; - err =nf_conntrack_l4proto_register (&dccp_proto4); + err =register_pernet_gen_device (&dccp_net_id, &dccp_net_ops);Shouldn't it be
register_pernet_gen_subsys?
Quoted 7 lines
Do I really have to carefully and meticuliously scan down hundreds and hundreds of irrelevant quoted patch text just to see what bit you're commenting on?
Please, just provide the necessary context of the patch for your comments, don't quote the whole thing :-(
Sorry, I will do that in the future.
-- Daniel