]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.fixes/pkt_action-skbedit
Move xen patchset to new version's subdir.
[ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / pkt_action-skbedit
CommitLineData
00e5a55c
BS
1From 1a1cc3a15bba18bae3c29f4eb475aae0df9ef5bd Mon Sep 17 00:00:00 2001
2From: Hannes Reinecke <hare@suse.de>
3Date: Wed, 17 Sep 2008 16:47:10 +0200
4Subject: [PATCH] pkt_action: add new action skbedit
5
6This new action will have the ability to change the priority and/or
7queue_mapping fields on an sk_buff.
8
9Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
10Signed-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
24diff --git a/Documentation/networking/multiqueue.txt b/Documentation/networking/multiqueue.txt
25index 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>
44diff --git a/include/linux/tc_act/Kbuild b/include/linux/tc_act/Kbuild
45index 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
53diff --git a/include/linux/tc_act/tc_skbedit.h b/include/linux/tc_act/tc_skbedit.h
54new file mode 100644
55index 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
103diff --git a/include/net/tc_act/tc_skbedit.h b/include/net/tc_act/tc_skbedit.h
104new file mode 100644
105index 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 */
143diff --git a/net/sched/Kconfig b/net/sched/Kconfig
144index 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
165diff --git a/net/sched/Makefile b/net/sched/Makefile
166index 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
177diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
178new file mode 100644
179index 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--
3871.5.2.4
388