aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/act_ipt.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-08-22 02:54:55 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 17:55:10 -0400
commite9ce1cd3cf6cf35b21d0ce990f2e738f35907386 (patch)
tree22a3ee7b78ae7cbf00520c66dcc389d87740069c /net/sched/act_ipt.c
parent2e4ca75b31b6851dcc036c2cdebf3ecfe279a653 (diff)
[PKT_SCHED]: Kill pkt_act.h inlining.
This was simply making templates of functions and mostly causing a lot of code duplication in the classifier action modules. We solve this more cleanly by having a common "struct tcf_common" that hash worker functions contained once in act_api.c can work with. Callers work with real action objects that have the common struct plus their module specific struct members. You go from a common object to the higher level one using a "to_foo()" macro which makes use of container_of() to do the dirty work. This also kills off act_generic.h which was only used by act_simple.c and keeping it around was more work than the it's value. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/act_ipt.c')
-rw-r--r--net/sched/act_ipt.c175
1 files changed, 79 insertions, 96 deletions
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index d799e01248c4..224c078a398e 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -38,25 +38,19 @@
38 38
39#include <linux/netfilter_ipv4/ip_tables.h> 39#include <linux/netfilter_ipv4/ip_tables.h>
40 40
41/* use generic hash table */
42#define MY_TAB_SIZE 16
43#define MY_TAB_MASK 15
44 41
45static u32 idx_gen; 42#define IPT_TAB_MASK 15
46static struct tcf_ipt *tcf_ipt_ht[MY_TAB_SIZE]; 43static struct tcf_common *tcf_ipt_ht[IPT_TAB_MASK + 1];
47/* ipt hash table lock */ 44static u32 ipt_idx_gen;
48static DEFINE_RWLOCK(ipt_lock); 45static DEFINE_RWLOCK(ipt_lock);
49 46
50/* ovewrride the defaults */ 47static struct tcf_hashinfo ipt_hash_info = {
51#define tcf_st tcf_ipt 48 .htab = tcf_ipt_ht,
52#define tcf_t_lock ipt_lock 49 .hmask = IPT_TAB_MASK,
53#define tcf_ht tcf_ipt_ht 50 .lock = &ipt_lock,
54 51};
55#define CONFIG_NET_ACT_INIT
56#include <net/pkt_act.h>
57 52
58static int 53static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
59ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
60{ 54{
61 struct ipt_target *target; 55 struct ipt_target *target;
62 int ret = 0; 56 int ret = 0;
@@ -65,7 +59,6 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
65 if (!target) 59 if (!target)
66 return -ENOENT; 60 return -ENOENT;
67 61
68 DPRINTK("ipt_init_target: found %s\n", target->name);
69 t->u.kernel.target = target; 62 t->u.kernel.target = target;
70 63
71 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), 64 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
@@ -78,8 +71,6 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
78 t->u.kernel.target, t->data, 71 t->u.kernel.target, t->data,
79 t->u.target_size - sizeof(*t), 72 t->u.target_size - sizeof(*t),
80 hook)) { 73 hook)) {
81 DPRINTK("ipt_init_target: check failed for `%s'.\n",
82 t->u.kernel.target->name);
83 module_put(t->u.kernel.target->me); 74 module_put(t->u.kernel.target->me);
84 ret = -EINVAL; 75 ret = -EINVAL;
85 } 76 }
@@ -87,8 +78,7 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
87 return ret; 78 return ret;
88} 79}
89 80
90static void 81static void ipt_destroy_target(struct ipt_entry_target *t)
91ipt_destroy_target(struct ipt_entry_target *t)
92{ 82{
93 if (t->u.kernel.target->destroy) 83 if (t->u.kernel.target->destroy)
94 t->u.kernel.target->destroy(t->u.kernel.target, t->data, 84 t->u.kernel.target->destroy(t->u.kernel.target, t->data,
@@ -96,31 +86,30 @@ ipt_destroy_target(struct ipt_entry_target *t)
96 module_put(t->u.kernel.target->me); 86 module_put(t->u.kernel.target->me);
97} 87}
98 88
99static int 89static int tcf_ipt_release(struct tcf_ipt *ipt, int bind)
100tcf_ipt_release(struct tcf_ipt *p, int bind)
101{ 90{
102 int ret = 0; 91 int ret = 0;
103 if (p) { 92 if (ipt) {
104 if (bind) 93 if (bind)
105 p->bindcnt--; 94 ipt->tcf_bindcnt--;
106 p->refcnt--; 95 ipt->tcf_refcnt--;
107 if (p->bindcnt <= 0 && p->refcnt <= 0) { 96 if (ipt->tcf_bindcnt <= 0 && ipt->tcf_refcnt <= 0) {
108 ipt_destroy_target(p->t); 97 ipt_destroy_target(ipt->tcfi_t);
109 kfree(p->tname); 98 kfree(ipt->tcfi_tname);
110 kfree(p->t); 99 kfree(ipt->tcfi_t);
111 tcf_hash_destroy(p); 100 tcf_hash_destroy(&ipt->common, &ipt_hash_info);
112 ret = ACT_P_DELETED; 101 ret = ACT_P_DELETED;
113 } 102 }
114 } 103 }
115 return ret; 104 return ret;
116} 105}
117 106
118static int 107static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est,
119tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, 108 struct tc_action *a, int ovr, int bind)
120 int ovr, int bind)
121{ 109{
122 struct rtattr *tb[TCA_IPT_MAX]; 110 struct rtattr *tb[TCA_IPT_MAX];
123 struct tcf_ipt *p; 111 struct tcf_ipt *ipt;
112 struct tcf_common *pc;
124 struct ipt_entry_target *td, *t; 113 struct ipt_entry_target *td, *t;
125 char *tname; 114 char *tname;
126 int ret = 0, err; 115 int ret = 0, err;
@@ -144,49 +133,51 @@ tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
144 RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32)) 133 RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32))
145 index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]); 134 index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]);
146 135
147 p = tcf_hash_check(index, a, ovr, bind); 136 pc = tcf_hash_check(index, a, bind, &ipt_hash_info);
148 if (p == NULL) { 137 if (!pc) {
149 p = tcf_hash_create(index, est, a, sizeof(*p), ovr, bind); 138 pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind,
150 if (p == NULL) 139 &ipt_idx_gen, &ipt_hash_info);
140 if (unlikely(!pc))
151 return -ENOMEM; 141 return -ENOMEM;
152 ret = ACT_P_CREATED; 142 ret = ACT_P_CREATED;
153 } else { 143 } else {
154 if (!ovr) { 144 if (!ovr) {
155 tcf_ipt_release(p, bind); 145 tcf_ipt_release(to_ipt(pc), bind);
156 return -EEXIST; 146 return -EEXIST;
157 } 147 }
158 } 148 }
149 ipt = to_ipt(pc);
159 150
160 hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]); 151 hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]);
161 152
162 err = -ENOMEM; 153 err = -ENOMEM;
163 tname = kmalloc(IFNAMSIZ, GFP_KERNEL); 154 tname = kmalloc(IFNAMSIZ, GFP_KERNEL);
164 if (tname == NULL) 155 if (unlikely(!tname))
165 goto err1; 156 goto err1;
166 if (tb[TCA_IPT_TABLE - 1] == NULL || 157 if (tb[TCA_IPT_TABLE - 1] == NULL ||
167 rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ) 158 rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ)
168 strcpy(tname, "mangle"); 159 strcpy(tname, "mangle");
169 160
170 t = kmalloc(td->u.target_size, GFP_KERNEL); 161 t = kmalloc(td->u.target_size, GFP_KERNEL);
171 if (t == NULL) 162 if (unlikely(!t))
172 goto err2; 163 goto err2;
173 memcpy(t, td, td->u.target_size); 164 memcpy(t, td, td->u.target_size);
174 165
175 if ((err = ipt_init_target(t, tname, hook)) < 0) 166 if ((err = ipt_init_target(t, tname, hook)) < 0)
176 goto err3; 167 goto err3;
177 168
178 spin_lock_bh(&p->lock); 169 spin_lock_bh(&ipt->tcf_lock);
179 if (ret != ACT_P_CREATED) { 170 if (ret != ACT_P_CREATED) {
180 ipt_destroy_target(p->t); 171 ipt_destroy_target(ipt->tcfi_t);
181 kfree(p->tname); 172 kfree(ipt->tcfi_tname);
182 kfree(p->t); 173 kfree(ipt->tcfi_t);
183 } 174 }
184 p->tname = tname; 175 ipt->tcfi_tname = tname;
185 p->t = t; 176 ipt->tcfi_t = t;
186 p->hook = hook; 177 ipt->tcfi_hook = hook;
187 spin_unlock_bh(&p->lock); 178 spin_unlock_bh(&ipt->tcf_lock);
188 if (ret == ACT_P_CREATED) 179 if (ret == ACT_P_CREATED)
189 tcf_hash_insert(p); 180 tcf_hash_insert(pc, &ipt_hash_info);
190 return ret; 181 return ret;
191 182
192err3: 183err3:
@@ -194,33 +185,32 @@ err3:
194err2: 185err2:
195 kfree(tname); 186 kfree(tname);
196err1: 187err1:
197 kfree(p); 188 kfree(pc);
198 return err; 189 return err;
199} 190}
200 191
201static int 192static int tcf_ipt_cleanup(struct tc_action *a, int bind)
202tcf_ipt_cleanup(struct tc_action *a, int bind)
203{ 193{
204 struct tcf_ipt *p = PRIV(a, ipt); 194 struct tcf_ipt *ipt = a->priv;
205 return tcf_ipt_release(p, bind); 195 return tcf_ipt_release(ipt, bind);
206} 196}
207 197
208static int 198static int tcf_ipt(struct sk_buff *skb, struct tc_action *a,
209tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) 199 struct tcf_result *res)
210{ 200{
211 int ret = 0, result = 0; 201 int ret = 0, result = 0;
212 struct tcf_ipt *p = PRIV(a, ipt); 202 struct tcf_ipt *ipt = a->priv;
213 203
214 if (skb_cloned(skb)) { 204 if (skb_cloned(skb)) {
215 if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) 205 if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
216 return TC_ACT_UNSPEC; 206 return TC_ACT_UNSPEC;
217 } 207 }
218 208
219 spin_lock(&p->lock); 209 spin_lock(&ipt->tcf_lock);
220 210
221 p->tm.lastuse = jiffies; 211 ipt->tcf_tm.lastuse = jiffies;
222 p->bstats.bytes += skb->len; 212 ipt->tcf_bstats.bytes += skb->len;
223 p->bstats.packets++; 213 ipt->tcf_bstats.packets++;
224 214
225 /* yes, we have to worry about both in and out dev 215 /* yes, we have to worry about both in and out dev
226 worry later - danger - this API seems to have changed 216 worry later - danger - this API seems to have changed
@@ -229,16 +219,17 @@ tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
229 /* iptables targets take a double skb pointer in case the skb 219 /* iptables targets take a double skb pointer in case the skb
230 * needs to be replaced. We don't own the skb, so this must not 220 * needs to be replaced. We don't own the skb, so this must not
231 * happen. The pskb_expand_head above should make sure of this */ 221 * happen. The pskb_expand_head above should make sure of this */
232 ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, p->hook, 222 ret = ipt->tcfi_t->u.kernel.target->target(&skb, skb->dev, NULL,
233 p->t->u.kernel.target, p->t->data, 223 ipt->tcfi_hook,
234 NULL); 224 ipt->tcfi_t->u.kernel.target,
225 ipt->tcfi_t->data, NULL);
235 switch (ret) { 226 switch (ret) {
236 case NF_ACCEPT: 227 case NF_ACCEPT:
237 result = TC_ACT_OK; 228 result = TC_ACT_OK;
238 break; 229 break;
239 case NF_DROP: 230 case NF_DROP:
240 result = TC_ACT_SHOT; 231 result = TC_ACT_SHOT;
241 p->qstats.drops++; 232 ipt->tcf_qstats.drops++;
242 break; 233 break;
243 case IPT_CONTINUE: 234 case IPT_CONTINUE:
244 result = TC_ACT_PIPE; 235 result = TC_ACT_PIPE;
@@ -249,53 +240,46 @@ tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
249 result = TC_POLICE_OK; 240 result = TC_POLICE_OK;
250 break; 241 break;
251 } 242 }
252 spin_unlock(&p->lock); 243 spin_unlock(&ipt->tcf_lock);
253 return result; 244 return result;
254 245
255} 246}
256 247
257static int 248static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
258tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
259{ 249{
250 unsigned char *b = skb->tail;
251 struct tcf_ipt *ipt = a->priv;
260 struct ipt_entry_target *t; 252 struct ipt_entry_target *t;
261 struct tcf_t tm; 253 struct tcf_t tm;
262 struct tc_cnt c; 254 struct tc_cnt c;
263 unsigned char *b = skb->tail;
264 struct tcf_ipt *p = PRIV(a, ipt);
265 255
266 /* for simple targets kernel size == user size 256 /* for simple targets kernel size == user size
267 ** user name = target name 257 ** user name = target name
268 ** for foolproof you need to not assume this 258 ** for foolproof you need to not assume this
269 */ 259 */
270 260
271 t = kmalloc(p->t->u.user.target_size, GFP_ATOMIC); 261 t = kmalloc(ipt->tcfi_t->u.user.target_size, GFP_ATOMIC);
272 if (t == NULL) 262 if (unlikely(!t))
273 goto rtattr_failure; 263 goto rtattr_failure;
274 264
275 c.bindcnt = p->bindcnt - bind; 265 c.bindcnt = ipt->tcf_bindcnt - bind;
276 c.refcnt = p->refcnt - ref; 266 c.refcnt = ipt->tcf_refcnt - ref;
277 memcpy(t, p->t, p->t->u.user.target_size); 267 memcpy(t, ipt->tcfi_t, ipt->tcfi_t->u.user.target_size);
278 strcpy(t->u.user.name, p->t->u.kernel.target->name); 268 strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name);
279 269
280 DPRINTK("\ttcf_ipt_dump tablename %s length %d\n", p->tname, 270 RTA_PUT(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t);
281 strlen(p->tname)); 271 RTA_PUT(skb, TCA_IPT_INDEX, 4, &ipt->tcf_index);
282 DPRINTK("\tdump target name %s size %d size user %d " 272 RTA_PUT(skb, TCA_IPT_HOOK, 4, &ipt->tcfi_hook);
283 "data[0] %x data[1] %x\n", p->t->u.kernel.target->name,
284 p->t->u.target_size, p->t->u.user.target_size,
285 p->t->data[0], p->t->data[1]);
286 RTA_PUT(skb, TCA_IPT_TARG, p->t->u.user.target_size, t);
287 RTA_PUT(skb, TCA_IPT_INDEX, 4, &p->index);
288 RTA_PUT(skb, TCA_IPT_HOOK, 4, &p->hook);
289 RTA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c); 273 RTA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c);
290 RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, p->tname); 274 RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, ipt->tcfi_tname);
291 tm.install = jiffies_to_clock_t(jiffies - p->tm.install); 275 tm.install = jiffies_to_clock_t(jiffies - ipt->tcf_tm.install);
292 tm.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); 276 tm.lastuse = jiffies_to_clock_t(jiffies - ipt->tcf_tm.lastuse);
293 tm.expires = jiffies_to_clock_t(p->tm.expires); 277 tm.expires = jiffies_to_clock_t(ipt->tcf_tm.expires);
294 RTA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm); 278 RTA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm);
295 kfree(t); 279 kfree(t);
296 return skb->len; 280 return skb->len;
297 281
298 rtattr_failure: 282rtattr_failure:
299 skb_trim(skb, b - skb->data); 283 skb_trim(skb, b - skb->data);
300 kfree(t); 284 kfree(t);
301 return -1; 285 return -1;
@@ -303,6 +287,7 @@ tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
303 287
304static struct tc_action_ops act_ipt_ops = { 288static struct tc_action_ops act_ipt_ops = {
305 .kind = "ipt", 289 .kind = "ipt",
290 .hinfo = &ipt_hash_info,
306 .type = TCA_ACT_IPT, 291 .type = TCA_ACT_IPT,
307 .capab = TCA_CAP_NONE, 292 .capab = TCA_CAP_NONE,
308 .owner = THIS_MODULE, 293 .owner = THIS_MODULE,
@@ -318,14 +303,12 @@ MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
318MODULE_DESCRIPTION("Iptables target actions"); 303MODULE_DESCRIPTION("Iptables target actions");
319MODULE_LICENSE("GPL"); 304MODULE_LICENSE("GPL");
320 305
321static int __init 306static int __init ipt_init_module(void)
322ipt_init_module(void)
323{ 307{
324 return tcf_register_action(&act_ipt_ops); 308 return tcf_register_action(&act_ipt_ops);
325} 309}
326 310
327static void __exit 311static void __exit ipt_cleanup_module(void)
328ipt_cleanup_module(void)
329{ 312{
330 tcf_unregister_action(&act_ipt_ops); 313 tcf_unregister_action(&act_ipt_ops);
331} 314}