]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.fixes/pkt_action-skbedit
Merge branch 'master' of git://git.ipfire.org/ipfire-2.x
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / pkt_action-skbedit
1 From 1a1cc3a15bba18bae3c29f4eb475aae0df9ef5bd Mon Sep 17 00:00:00 2001
2 From: Hannes Reinecke <hare@suse.de>
3 Date: Wed, 17 Sep 2008 16:47:10 +0200
4 Subject: [PATCH] pkt_action: add new action skbedit
5
6 This new action will have the ability to change the priority and/or
7 queue_mapping fields on an sk_buff.
8
9 Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
10 Signed-off-by: Hannes Reinecke <hare@suse.de>
11 ---
12 Documentation/networking/multiqueue.txt | 9 ++-
13 include/linux/tc_act/Kbuild | 1 +
14 include/linux/tc_act/tc_skbedit.h | 44 +++++++
15 include/net/tc_act/tc_skbedit.h | 34 +++++
16 net/sched/Kconfig | 11 ++
17 net/sched/Makefile | 1 +
18 net/sched/act_skbedit.c | 203 +++++++++++++++++++++++++++++++
19 7 files changed, 302 insertions(+), 1 deletions(-)
20 create mode 100644 include/linux/tc_act/tc_skbedit.h
21 create mode 100644 include/net/tc_act/tc_skbedit.h
22 create mode 100644 net/sched/act_skbedit.c
23
24 diff --git a/Documentation/networking/multiqueue.txt b/Documentation/networking/multiqueue.txt
25 index 5787ee6..10113ff 100644
26 --- a/Documentation/networking/multiqueue.txt
27 +++ b/Documentation/networking/multiqueue.txt
28 @@ -66,7 +66,14 @@ band 3 => queue 3
29 Traffic will begin flowing through each queue if your base device has either
30 the default simple_tx_hash or a custom netdev->select_queue() defined.
31
32 -The behavior of tc filters remains the same.
33 +The behavior of tc filters remains the same. However a new tc action,
34 +skbedit, has been added. Assuming you wanted to route all traffic to a
35 +specific host, for example 192.168.0.3, though a specific queue you could use
36 +this action and establish a filter such as:
37 +
38 +tc filter add dev eth0 parent 1: protocol ip prio 1 u32 \
39 + match ip dst 192.168.0.3 \
40 + action skbedit queue_mapping 3
41
42 Author: Alexander Duyck <alexander.h.duyck@intel.com>
43 Original Author: Peter P. Waskiewicz Jr. <peter.p.waskiewicz.jr@intel.com>
44 diff --git a/include/linux/tc_act/Kbuild b/include/linux/tc_act/Kbuild
45 index 6dac0d7..7699093 100644
46 --- a/include/linux/tc_act/Kbuild
47 +++ b/include/linux/tc_act/Kbuild
48 @@ -3,3 +3,4 @@ header-y += tc_ipt.h
49 header-y += tc_mirred.h
50 header-y += tc_pedit.h
51 header-y += tc_nat.h
52 +header-y += tc_skbedit.h
53 diff --git a/include/linux/tc_act/tc_skbedit.h b/include/linux/tc_act/tc_skbedit.h
54 new file mode 100644
55 index 0000000..a14e461
56 --- /dev/null
57 +++ b/include/linux/tc_act/tc_skbedit.h
58 @@ -0,0 +1,44 @@
59 +/*
60 + * Copyright (c) 2008, Intel Corporation.
61 + *
62 + * This program is free software; you can redistribute it and/or modify it
63 + * under the terms and conditions of the GNU General Public License,
64 + * version 2, as published by the Free Software Foundation.
65 + *
66 + * This program is distributed in the hope it will be useful, but WITHOUT
67 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
68 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
69 + * more details.
70 + *
71 + * You should have received a copy of the GNU General Public License along with
72 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
73 + * Place - Suite 330, Boston, MA 02111-1307 USA.
74 + *
75 + * Author: Alexander Duyck <alexander.h.duyck@intel.com>
76 + */
77 +
78 +#ifndef __LINUX_TC_SKBEDIT_H
79 +#define __LINUX_TC_SKBEDIT_H
80 +
81 +#include <linux/pkt_cls.h>
82 +
83 +#define TCA_ACT_SKBEDIT 11
84 +
85 +#define SKBEDIT_F_PRIORITY 0x1
86 +#define SKBEDIT_F_QUEUE_MAPPING 0x2
87 +
88 +struct tc_skbedit {
89 + tc_gen;
90 +};
91 +
92 +enum {
93 + TCA_SKBEDIT_UNSPEC,
94 + TCA_SKBEDIT_TM,
95 + TCA_SKBEDIT_PARMS,
96 + TCA_SKBEDIT_PRIORITY,
97 + TCA_SKBEDIT_QUEUE_MAPPING,
98 + __TCA_SKBEDIT_MAX
99 +};
100 +#define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
101 +
102 +#endif
103 diff --git a/include/net/tc_act/tc_skbedit.h b/include/net/tc_act/tc_skbedit.h
104 new file mode 100644
105 index 0000000..6abb3ed
106 --- /dev/null
107 +++ b/include/net/tc_act/tc_skbedit.h
108 @@ -0,0 +1,34 @@
109 +/*
110 + * Copyright (c) 2008, Intel Corporation.
111 + *
112 + * This program is free software; you can redistribute it and/or modify it
113 + * under the terms and conditions of the GNU General Public License,
114 + * version 2, as published by the Free Software Foundation.
115 + *
116 + * This program is distributed in the hope it will be useful, but WITHOUT
117 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
118 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
119 + * more details.
120 + *
121 + * You should have received a copy of the GNU General Public License along with
122 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
123 + * Place - Suite 330, Boston, MA 02111-1307 USA.
124 + *
125 + * Author: Alexander Duyck <alexander.h.duyck@intel.com>
126 + */
127 +
128 +#ifndef __NET_TC_SKBEDIT_H
129 +#define __NET_TC_SKBEDIT_H
130 +
131 +#include <net/act_api.h>
132 +
133 +struct tcf_skbedit {
134 + struct tcf_common common;
135 + u32 flags;
136 + u32 priority;
137 + u16 queue_mapping;
138 +};
139 +#define to_skbedit(pc) \
140 + container_of(pc, struct tcf_skbedit, common)
141 +
142 +#endif /* __NET_TC_SKBEDIT_H */
143 diff --git a/net/sched/Kconfig b/net/sched/Kconfig
144 index efaa7a7..6767e54 100644
145 --- a/net/sched/Kconfig
146 +++ b/net/sched/Kconfig
147 @@ -485,6 +485,17 @@ config NET_ACT_SIMP
148 To compile this code as a module, choose M here: the
149 module will be called simple.
150
151 +config NET_ACT_SKBEDIT
152 + tristate "SKB Editing"
153 + depends on NET_CLS_ACT
154 + ---help---
155 + Say Y here to change skb priority or queue_mapping settings.
156 +
157 + If unsure, say N.
158 +
159 + To compile this code as a module, choose M here: the
160 + module will be called skbedit.
161 +
162 config NET_CLS_IND
163 bool "Incoming device classification"
164 depends on NET_CLS_U32 || NET_CLS_FW
165 diff --git a/net/sched/Makefile b/net/sched/Makefile
166 index 3d9b953..e60c992 100644
167 --- a/net/sched/Makefile
168 +++ b/net/sched/Makefile
169 @@ -14,6 +14,7 @@ obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o
170 obj-$(CONFIG_NET_ACT_NAT) += act_nat.o
171 obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit.o
172 obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o
173 +obj-$(CONFIG_NET_ACT_SKBEDIT) += act_skbedit.o
174 obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o
175 obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o
176 obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o
177 diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
178 new file mode 100644
179 index 0000000..fe9777e
180 --- /dev/null
181 +++ b/net/sched/act_skbedit.c
182 @@ -0,0 +1,203 @@
183 +/*
184 + * Copyright (c) 2008, Intel Corporation.
185 + *
186 + * This program is free software; you can redistribute it and/or modify it
187 + * under the terms and conditions of the GNU General Public License,
188 + * version 2, as published by the Free Software Foundation.
189 + *
190 + * This program is distributed in the hope it will be useful, but WITHOUT
191 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
192 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
193 + * more details.
194 + *
195 + * You should have received a copy of the GNU General Public License along with
196 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
197 + * Place - Suite 330, Boston, MA 02111-1307 USA.
198 + *
199 + * Author: Alexander Duyck <alexander.h.duyck@intel.com>
200 + */
201 +
202 +#include <linux/module.h>
203 +#include <linux/init.h>
204 +#include <linux/kernel.h>
205 +#include <linux/skbuff.h>
206 +#include <linux/rtnetlink.h>
207 +#include <net/netlink.h>
208 +#include <net/pkt_sched.h>
209 +
210 +#include <linux/tc_act/tc_skbedit.h>
211 +#include <net/tc_act/tc_skbedit.h>
212 +
213 +#define SKBEDIT_TAB_MASK 15
214 +static struct tcf_common *tcf_skbedit_ht[SKBEDIT_TAB_MASK + 1];
215 +static u32 skbedit_idx_gen;
216 +static DEFINE_RWLOCK(skbedit_lock);
217 +
218 +static struct tcf_hashinfo skbedit_hash_info = {
219 + .htab = tcf_skbedit_ht,
220 + .hmask = SKBEDIT_TAB_MASK,
221 + .lock = &skbedit_lock,
222 +};
223 +
224 +static int tcf_skbedit(struct sk_buff *skb, struct tc_action *a,
225 + struct tcf_result *res)
226 +{
227 + struct tcf_skbedit *d = a->priv;
228 +
229 + spin_lock(&d->tcf_lock);
230 + d->tcf_tm.lastuse = jiffies;
231 + d->tcf_bstats.bytes += qdisc_pkt_len(skb);
232 + d->tcf_bstats.packets++;
233 +
234 + if (d->flags & SKBEDIT_F_PRIORITY)
235 + skb->priority = d->priority;
236 + if (d->flags & SKBEDIT_F_QUEUE_MAPPING &&
237 + skb->dev->real_num_tx_queues > d->queue_mapping)
238 + skb_set_queue_mapping(skb, d->queue_mapping);
239 +
240 + spin_unlock(&d->tcf_lock);
241 + return d->tcf_action;
242 +}
243 +
244 +static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
245 + [TCA_SKBEDIT_PARMS] = { .len = sizeof(struct tc_skbedit) },
246 + [TCA_SKBEDIT_PRIORITY] = { .len = sizeof(u32) },
247 + [TCA_SKBEDIT_QUEUE_MAPPING] = { .len = sizeof(u16) },
248 +};
249 +
250 +static int tcf_skbedit_init(struct nlattr *nla, struct nlattr *est,
251 + struct tc_action *a, int ovr, int bind)
252 +{
253 + struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
254 + struct tc_skbedit *parm;
255 + struct tcf_skbedit *d;
256 + struct tcf_common *pc;
257 + u32 flags = 0, *priority = NULL;
258 + u16 *queue_mapping = NULL;
259 + int ret = 0, err;
260 +
261 + if (nla == NULL)
262 + return -EINVAL;
263 +
264 + err = nla_parse_nested(tb, TCA_SKBEDIT_MAX, nla, skbedit_policy);
265 + if (err < 0)
266 + return err;
267 +
268 + if (tb[TCA_SKBEDIT_PARMS] == NULL)
269 + return -EINVAL;
270 +
271 + if (tb[TCA_SKBEDIT_PRIORITY] != NULL) {
272 + flags |= SKBEDIT_F_PRIORITY;
273 + priority = nla_data(tb[TCA_SKBEDIT_PRIORITY]);
274 + }
275 +
276 + if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) {
277 + flags |= SKBEDIT_F_QUEUE_MAPPING;
278 + queue_mapping = nla_data(tb[TCA_SKBEDIT_QUEUE_MAPPING]);
279 + }
280 + if (!flags)
281 + return -EINVAL;
282 +
283 + parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
284 +
285 + pc = tcf_hash_check(parm->index, a, bind, &skbedit_hash_info);
286 + if (!pc) {
287 + pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind,
288 + &skbedit_idx_gen, &skbedit_hash_info);
289 + if (unlikely(!pc))
290 + return -ENOMEM;
291 +
292 + d = to_skbedit(pc);
293 + ret = ACT_P_CREATED;
294 + } else {
295 + d = to_skbedit(pc);
296 + if (!ovr) {
297 + tcf_hash_release(pc, bind, &skbedit_hash_info);
298 + return -EEXIST;
299 + }
300 + }
301 +
302 + spin_lock_bh(&d->tcf_lock);
303 +
304 + d->flags = flags;
305 + if (flags & SKBEDIT_F_PRIORITY)
306 + d->priority = *priority;
307 + if (flags & SKBEDIT_F_QUEUE_MAPPING)
308 + d->queue_mapping = *queue_mapping;
309 + d->tcf_action = parm->action;
310 +
311 + spin_unlock_bh(&d->tcf_lock);
312 +
313 + if (ret == ACT_P_CREATED)
314 + tcf_hash_insert(pc, &skbedit_hash_info);
315 + return ret;
316 +}
317 +
318 +static inline int tcf_skbedit_cleanup(struct tc_action *a, int bind)
319 +{
320 + struct tcf_skbedit *d = a->priv;
321 +
322 + if (d)
323 + return tcf_hash_release(&d->common, bind, &skbedit_hash_info);
324 + return 0;
325 +}
326 +
327 +static inline int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
328 + int bind, int ref)
329 +{
330 + unsigned char *b = skb_tail_pointer(skb);
331 + struct tcf_skbedit *d = a->priv;
332 + struct tc_skbedit opt;
333 + struct tcf_t t;
334 +
335 + opt.index = d->tcf_index;
336 + opt.refcnt = d->tcf_refcnt - ref;
337 + opt.bindcnt = d->tcf_bindcnt - bind;
338 + opt.action = d->tcf_action;
339 + NLA_PUT(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt);
340 + if (d->flags & SKBEDIT_F_PRIORITY)
341 + NLA_PUT(skb, TCA_SKBEDIT_PRIORITY, sizeof(d->priority),
342 + &d->priority);
343 + if (d->flags & SKBEDIT_F_QUEUE_MAPPING)
344 + NLA_PUT(skb, TCA_SKBEDIT_QUEUE_MAPPING,
345 + sizeof(d->queue_mapping), &d->queue_mapping);
346 + t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install);
347 + t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse);
348 + t.expires = jiffies_to_clock_t(d->tcf_tm.expires);
349 + NLA_PUT(skb, TCA_SKBEDIT_TM, sizeof(t), &t);
350 + return skb->len;
351 +
352 +nla_put_failure:
353 + nlmsg_trim(skb, b);
354 + return -1;
355 +}
356 +
357 +static struct tc_action_ops act_skbedit_ops = {
358 + .kind = "skbedit",
359 + .hinfo = &skbedit_hash_info,
360 + .type = TCA_ACT_SKBEDIT,
361 + .capab = TCA_CAP_NONE,
362 + .owner = THIS_MODULE,
363 + .act = tcf_skbedit,
364 + .dump = tcf_skbedit_dump,
365 + .cleanup = tcf_skbedit_cleanup,
366 + .init = tcf_skbedit_init,
367 + .walk = tcf_generic_walker,
368 +};
369 +
370 +MODULE_AUTHOR("Alexander Duyck, <alexander.h.duyck@intel.com>");
371 +MODULE_DESCRIPTION("SKB Editing");
372 +MODULE_LICENSE("GPL");
373 +
374 +static int __init skbedit_init_module(void)
375 +{
376 + return tcf_register_action(&act_skbedit_ops);
377 +}
378 +
379 +static void __exit skbedit_cleanup_module(void)
380 +{
381 + tcf_unregister_action(&act_skbedit_ops);
382 +}
383 +
384 +module_init(skbedit_init_module);
385 +module_exit(skbedit_cleanup_module);
386 --
387 1.5.2.4
388