diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2009-06-13 06:26:29 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2009-06-13 06:26:29 -0400 |
commit | a0891aa6a635f658f29bb061a00d6d3486941519 (patch) | |
tree | 40df3898f9f2e0892683c482d81deec4fd5a9257 /include/net/netfilter/nf_conntrack_ecache.h | |
parent | 65cb9fda32be613216f601a330b311c3bd7a8436 (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/net/netfilter/nf_conntrack_ecache.h')
-rw-r--r-- | include/net/netfilter/nf_conntrack_ecache.h | 130 |
1 files changed, 69 insertions, 61 deletions
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 1afb907e015..e7ae297ba38 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 */ |
14 | enum ip_conntrack_events | 16 | enum 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 */ | 29 | enum 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 */ | 33 | struct 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 */ | 37 | static inline struct nf_conntrack_ecache * |
41 | IPCT_MARK_BIT = 6, | 38 | nf_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 */ | 43 | static inline struct nf_conntrack_ecache * |
45 | IPCT_NATSEQADJ_BIT = 7, | 44 | nf_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 | ||
53 | enum 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 |
59 | struct 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 */ |
65 | struct nf_ct_event { | 56 | struct 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; | |||
76 | extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb); | 67 | extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb); |
77 | extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb); | 68 | extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb); |
78 | 69 | ||
79 | extern void nf_ct_deliver_cached_events(const struct nf_conn *ct); | 70 | extern void nf_ct_deliver_cached_events(struct nf_conn *ct); |
80 | extern void __nf_ct_event_cache_init(struct nf_conn *ct); | ||
81 | extern void nf_ct_event_cache_flush(struct net *net); | ||
82 | 71 | ||
83 | static inline void | 72 | static inline void |
84 | nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) | 73 | nf_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 | ||
97 | static inline void | 87 | static inline void |
98 | nf_conntrack_event_report(enum ip_conntrack_events event, | 88 | nf_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 | } |
118 | out_unlock: | 112 | out_unlock: |
119 | rcu_read_unlock(); | 113 | rcu_read_unlock(); |
120 | } | 114 | } |
121 | 115 | ||
122 | static inline void | 116 | static inline void |
117 | nf_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 | |||
123 | static inline void | ||
123 | nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) | 124 | nf_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 | ||
128 | struct nf_exp_event { | 129 | struct 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 | } |
163 | out_unlock: | 168 | out_unlock: |
164 | rcu_read_unlock(); | 169 | rcu_read_unlock(); |
@@ -178,6 +183,10 @@ extern void nf_conntrack_ecache_fini(struct net *net); | |||
178 | 183 | ||
179 | static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, | 184 | static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, |
180 | struct nf_conn *ct) {} | 185 | struct nf_conn *ct) {} |
186 | static inline void nf_conntrack_eventmask_report(unsigned int eventmask, | ||
187 | struct nf_conn *ct, | ||
188 | u32 pid, | ||
189 | int report) {} | ||
181 | static inline void nf_conntrack_event(enum ip_conntrack_events event, | 190 | static inline void nf_conntrack_event(enum ip_conntrack_events event, |
182 | struct nf_conn *ct) {} | 191 | struct nf_conn *ct) {} |
183 | static inline void nf_conntrack_event_report(enum ip_conntrack_events event, | 192 | static 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) {} |
194 | static inline void nf_ct_event_cache_flush(struct net *net) {} | ||
195 | 203 | ||
196 | static inline int nf_conntrack_ecache_init(struct net *net) | 204 | static inline int nf_conntrack_ecache_init(struct net *net) |
197 | { | 205 | { |