aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2009-06-13 06:26:29 -0400
committerPatrick McHardy <kaber@trash.net>2009-06-13 06:26:29 -0400
commita0891aa6a635f658f29bb061a00d6d3486941519 (patch)
tree40df3898f9f2e0892683c482d81deec4fd5a9257 /include
parent65cb9fda32be613216f601a330b311c3bd7a8436 (diff)
netfilter: conntrack: move event caching to conntrack extension infrastructure
This patch reworks the per-cpu event caching to use the conntrack extension infrastructure. The main drawback is that we consume more memory per conntrack if event delivery is enabled. This patch is required by the reliable event delivery that follows to this patch. BTW, this patch allows you to enable/disable event delivery via /proc/sys/net/netfilter/nf_conntrack_events in runtime, although you can still disable event caching as compilation option. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'include')
-rw-r--r--include/net/netfilter/nf_conntrack_ecache.h130
-rw-r--r--include/net/netfilter/nf_conntrack_extend.h2
-rw-r--r--include/net/netns/conntrack.h5
3 files changed, 73 insertions, 64 deletions
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 1afb907e015a..e7ae297ba383 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -6,61 +6,52 @@
6#define _NF_CONNTRACK_ECACHE_H 6#define _NF_CONNTRACK_ECACHE_H
7#include <net/netfilter/nf_conntrack.h> 7#include <net/netfilter/nf_conntrack.h>
8 8
9#include <linux/interrupt.h>
10#include <net/net_namespace.h> 9#include <net/net_namespace.h>
11#include <net/netfilter/nf_conntrack_expect.h> 10#include <net/netfilter/nf_conntrack_expect.h>
11#include <linux/netfilter/nf_conntrack_common.h>
12#include <linux/netfilter/nf_conntrack_tuple_common.h>
13#include <net/netfilter/nf_conntrack_extend.h>
12 14
13/* Connection tracking event bits */ 15/* Connection tracking event types */
14enum ip_conntrack_events 16enum ip_conntrack_events
15{ 17{
16 /* New conntrack */ 18 IPCT_NEW = 0, /* new conntrack */
17 IPCT_NEW_BIT = 0, 19 IPCT_RELATED = 1, /* related conntrack */
18 IPCT_NEW = (1 << IPCT_NEW_BIT), 20 IPCT_DESTROY = 2, /* destroyed conntrack */
19 21 IPCT_STATUS = 3, /* status has changed */
20 /* Expected connection */ 22 IPCT_PROTOINFO = 4, /* protocol information has changed */
21 IPCT_RELATED_BIT = 1, 23 IPCT_HELPER = 5, /* new helper has been set */
22 IPCT_RELATED = (1 << IPCT_RELATED_BIT), 24 IPCT_MARK = 6, /* new mark has been set */
23 25 IPCT_NATSEQADJ = 7, /* NAT is doing sequence adjustment */
24 /* Destroyed conntrack */ 26 IPCT_SECMARK = 8, /* new security mark has been set */
25 IPCT_DESTROY_BIT = 2, 27};
26 IPCT_DESTROY = (1 << IPCT_DESTROY_BIT),
27
28 /* Status has changed */
29 IPCT_STATUS_BIT = 3,
30 IPCT_STATUS = (1 << IPCT_STATUS_BIT),
31 28
32 /* Update of protocol info */ 29enum ip_conntrack_expect_events {
33 IPCT_PROTOINFO_BIT = 4, 30 IPEXP_NEW = 0, /* new expectation */
34 IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT), 31};
35 32
36 /* New helper for conntrack */ 33struct nf_conntrack_ecache {
37 IPCT_HELPER_BIT = 5, 34 unsigned long cache; /* bitops want long */
38 IPCT_HELPER = (1 << IPCT_HELPER_BIT), 35};
39 36
40 /* Mark is set */ 37static inline struct nf_conntrack_ecache *
41 IPCT_MARK_BIT = 6, 38nf_ct_ecache_find(const struct nf_conn *ct)
42 IPCT_MARK = (1 << IPCT_MARK_BIT), 39{
40 return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE);
41}
43 42
44 /* NAT sequence adjustment */ 43static inline struct nf_conntrack_ecache *
45 IPCT_NATSEQADJ_BIT = 7, 44nf_ct_ecache_ext_add(struct nf_conn *ct, gfp_t gfp)
46 IPCT_NATSEQADJ = (1 << IPCT_NATSEQADJ_BIT), 45{
46 struct net *net = nf_ct_net(ct);
47 47
48 /* Secmark is set */ 48 if (!net->ct.sysctl_events)
49 IPCT_SECMARK_BIT = 8, 49 return NULL;
50 IPCT_SECMARK = (1 << IPCT_SECMARK_BIT),
51};
52 50
53enum ip_conntrack_expect_events { 51 return nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
54 IPEXP_NEW_BIT = 0,
55 IPEXP_NEW = (1 << IPEXP_NEW_BIT),
56}; 52};
57 53
58#ifdef CONFIG_NF_CONNTRACK_EVENTS 54#ifdef CONFIG_NF_CONNTRACK_EVENTS
59struct nf_conntrack_ecache {
60 struct nf_conn *ct;
61 unsigned int events;
62};
63
64/* This structure is passed to event handler */ 55/* This structure is passed to event handler */
65struct nf_ct_event { 56struct nf_ct_event {
66 struct nf_conn *ct; 57 struct nf_conn *ct;
@@ -76,30 +67,30 @@ extern struct nf_ct_event_notifier *nf_conntrack_event_cb;
76extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb); 67extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb);
77extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb); 68extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb);
78 69
79extern void nf_ct_deliver_cached_events(const struct nf_conn *ct); 70extern void nf_ct_deliver_cached_events(struct nf_conn *ct);
80extern void __nf_ct_event_cache_init(struct nf_conn *ct);
81extern void nf_ct_event_cache_flush(struct net *net);
82 71
83static inline void 72static inline void
84nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) 73nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
85{ 74{
86 struct net *net = nf_ct_net(ct); 75 struct nf_conntrack_ecache *e;
87 struct nf_conntrack_ecache *ecache; 76
88 77 if (nf_conntrack_event_cb == NULL)
89 local_bh_disable(); 78 return;
90 ecache = per_cpu_ptr(net->ct.ecache, raw_smp_processor_id()); 79
91 if (ct != ecache->ct) 80 e = nf_ct_ecache_find(ct);
92 __nf_ct_event_cache_init(ct); 81 if (e == NULL)
93 ecache->events |= event; 82 return;
94 local_bh_enable(); 83
84 set_bit(event, &e->cache);
95} 85}
96 86
97static inline void 87static inline void
98nf_conntrack_event_report(enum ip_conntrack_events event, 88nf_conntrack_eventmask_report(unsigned int eventmask,
99 struct nf_conn *ct, 89 struct nf_conn *ct,
100 u32 pid, 90 u32 pid,
101 int report) 91 int report)
102{ 92{
93 struct net *net = nf_ct_net(ct);
103 struct nf_ct_event_notifier *notify; 94 struct nf_ct_event_notifier *notify;
104 95
105 rcu_read_lock(); 96 rcu_read_lock();
@@ -107,22 +98,32 @@ nf_conntrack_event_report(enum ip_conntrack_events event,
107 if (notify == NULL) 98 if (notify == NULL)
108 goto out_unlock; 99 goto out_unlock;
109 100
101 if (!net->ct.sysctl_events)
102 goto out_unlock;
103
110 if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) { 104 if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) {
111 struct nf_ct_event item = { 105 struct nf_ct_event item = {
112 .ct = ct, 106 .ct = ct,
113 .pid = pid, 107 .pid = pid,
114 .report = report 108 .report = report
115 }; 109 };
116 notify->fcn(event, &item); 110 notify->fcn(eventmask, &item);
117 } 111 }
118out_unlock: 112out_unlock:
119 rcu_read_unlock(); 113 rcu_read_unlock();
120} 114}
121 115
122static inline void 116static inline void
117nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
118 u32 pid, int report)
119{
120 nf_conntrack_eventmask_report(1 << event, ct, pid, report);
121}
122
123static inline void
123nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) 124nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
124{ 125{
125 nf_conntrack_event_report(event, ct, 0, 0); 126 nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
126} 127}
127 128
128struct nf_exp_event { 129struct nf_exp_event {
@@ -145,6 +146,7 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
145 u32 pid, 146 u32 pid,
146 int report) 147 int report)
147{ 148{
149 struct net *net = nf_ct_exp_net(exp);
148 struct nf_exp_event_notifier *notify; 150 struct nf_exp_event_notifier *notify;
149 151
150 rcu_read_lock(); 152 rcu_read_lock();
@@ -152,13 +154,16 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
152 if (notify == NULL) 154 if (notify == NULL)
153 goto out_unlock; 155 goto out_unlock;
154 156
157 if (!net->ct.sysctl_events)
158 goto out_unlock;
159
155 { 160 {
156 struct nf_exp_event item = { 161 struct nf_exp_event item = {
157 .exp = exp, 162 .exp = exp,
158 .pid = pid, 163 .pid = pid,
159 .report = report 164 .report = report
160 }; 165 };
161 notify->fcn(event, &item); 166 notify->fcn(1 << event, &item);
162 } 167 }
163out_unlock: 168out_unlock:
164 rcu_read_unlock(); 169 rcu_read_unlock();
@@ -178,6 +183,10 @@ extern void nf_conntrack_ecache_fini(struct net *net);
178 183
179static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, 184static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
180 struct nf_conn *ct) {} 185 struct nf_conn *ct) {}
186static inline void nf_conntrack_eventmask_report(unsigned int eventmask,
187 struct nf_conn *ct,
188 u32 pid,
189 int report) {}
181static inline void nf_conntrack_event(enum ip_conntrack_events event, 190static inline void nf_conntrack_event(enum ip_conntrack_events event,
182 struct nf_conn *ct) {} 191 struct nf_conn *ct) {}
183static inline void nf_conntrack_event_report(enum ip_conntrack_events event, 192static inline void nf_conntrack_event_report(enum ip_conntrack_events event,
@@ -191,7 +200,6 @@ static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
191 struct nf_conntrack_expect *exp, 200 struct nf_conntrack_expect *exp,
192 u32 pid, 201 u32 pid,
193 int report) {} 202 int report) {}
194static inline void nf_ct_event_cache_flush(struct net *net) {}
195 203
196static inline int nf_conntrack_ecache_init(struct net *net) 204static inline int nf_conntrack_ecache_init(struct net *net)
197{ 205{
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h
index da8ee52613a5..7f8fc5d123c5 100644
--- a/include/net/netfilter/nf_conntrack_extend.h
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -8,12 +8,14 @@ enum nf_ct_ext_id
8 NF_CT_EXT_HELPER, 8 NF_CT_EXT_HELPER,
9 NF_CT_EXT_NAT, 9 NF_CT_EXT_NAT,
10 NF_CT_EXT_ACCT, 10 NF_CT_EXT_ACCT,
11 NF_CT_EXT_ECACHE,
11 NF_CT_EXT_NUM, 12 NF_CT_EXT_NUM,
12}; 13};
13 14
14#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help 15#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
15#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat 16#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
16#define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter 17#define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter
18#define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache
17 19
18/* Extensions: optional stuff which isn't permanently in struct. */ 20/* Extensions: optional stuff which isn't permanently in struct. */
19struct nf_ct_ext { 21struct nf_ct_ext {
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
index 9dc58402bc09..505a51cd8c63 100644
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -15,15 +15,14 @@ struct netns_ct {
15 struct hlist_head *expect_hash; 15 struct hlist_head *expect_hash;
16 struct hlist_nulls_head unconfirmed; 16 struct hlist_nulls_head unconfirmed;
17 struct ip_conntrack_stat *stat; 17 struct ip_conntrack_stat *stat;
18#ifdef CONFIG_NF_CONNTRACK_EVENTS 18 int sysctl_events;
19 struct nf_conntrack_ecache *ecache;
20#endif
21 int sysctl_acct; 19 int sysctl_acct;
22 int sysctl_checksum; 20 int sysctl_checksum;
23 unsigned int sysctl_log_invalid; /* Log invalid packets */ 21 unsigned int sysctl_log_invalid; /* Log invalid packets */
24#ifdef CONFIG_SYSCTL 22#ifdef CONFIG_SYSCTL
25 struct ctl_table_header *sysctl_header; 23 struct ctl_table_header *sysctl_header;
26 struct ctl_table_header *acct_sysctl_header; 24 struct ctl_table_header *acct_sysctl_header;
25 struct ctl_table_header *event_sysctl_header;
27#endif 26#endif
28 int hash_vmalloc; 27 int hash_vmalloc;
29 int expect_vmalloc; 28 int expect_vmalloc;