]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.fixes/pkt_action-skbedit
Move xen patchset to new version's subdir.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / pkt_action-skbedit
diff --git a/src/patches/suse-2.6.27.31/patches.fixes/pkt_action-skbedit b/src/patches/suse-2.6.27.31/patches.fixes/pkt_action-skbedit
new file mode 100644 (file)
index 0000000..2c6b44e
--- /dev/null
@@ -0,0 +1,388 @@
+From 1a1cc3a15bba18bae3c29f4eb475aae0df9ef5bd Mon Sep 17 00:00:00 2001
+From: Hannes Reinecke <hare@suse.de>
+Date: Wed, 17 Sep 2008 16:47:10 +0200
+Subject: [PATCH] pkt_action: add new action skbedit
+
+This new action will have the ability to change the priority and/or
+queue_mapping fields on an sk_buff.
+
+Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+---
+ Documentation/networking/multiqueue.txt |    9 ++-
+ include/linux/tc_act/Kbuild             |    1 +
+ include/linux/tc_act/tc_skbedit.h       |   44 +++++++
+ include/net/tc_act/tc_skbedit.h         |   34 +++++
+ net/sched/Kconfig                       |   11 ++
+ net/sched/Makefile                      |    1 +
+ net/sched/act_skbedit.c                 |  203 +++++++++++++++++++++++++++++++
+ 7 files changed, 302 insertions(+), 1 deletions(-)
+ create mode 100644 include/linux/tc_act/tc_skbedit.h
+ create mode 100644 include/net/tc_act/tc_skbedit.h
+ create mode 100644 net/sched/act_skbedit.c
+
+diff --git a/Documentation/networking/multiqueue.txt b/Documentation/networking/multiqueue.txt
+index 5787ee6..10113ff 100644
+--- a/Documentation/networking/multiqueue.txt
++++ b/Documentation/networking/multiqueue.txt
+@@ -66,7 +66,14 @@ band 3 => queue 3
+ Traffic will begin flowing through each queue if your base device has either
+ the default simple_tx_hash or a custom netdev->select_queue() defined.
+-The behavior of tc filters remains the same.
++The behavior of tc filters remains the same.  However a new tc action,
++skbedit, has been added.  Assuming you wanted to route all traffic to a
++specific host, for example 192.168.0.3, though a specific queue you could use
++this action and establish a filter such as:
++
++tc filter add dev eth0 parent 1: protocol ip prio 1 u32 \
++      match ip dst 192.168.0.3 \
++      action skbedit queue_mapping 3
+ Author: Alexander Duyck <alexander.h.duyck@intel.com>
+ Original Author: Peter P. Waskiewicz Jr. <peter.p.waskiewicz.jr@intel.com>
+diff --git a/include/linux/tc_act/Kbuild b/include/linux/tc_act/Kbuild
+index 6dac0d7..7699093 100644
+--- a/include/linux/tc_act/Kbuild
++++ b/include/linux/tc_act/Kbuild
+@@ -3,3 +3,4 @@ header-y += tc_ipt.h
+ header-y += tc_mirred.h
+ header-y += tc_pedit.h
+ header-y += tc_nat.h
++header-y += tc_skbedit.h
+diff --git a/include/linux/tc_act/tc_skbedit.h b/include/linux/tc_act/tc_skbedit.h
+new file mode 100644
+index 0000000..a14e461
+--- /dev/null
++++ b/include/linux/tc_act/tc_skbedit.h
+@@ -0,0 +1,44 @@
++/*
++ * Copyright (c) 2008, Intel Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
++ * Place - Suite 330, Boston, MA 02111-1307 USA.
++ *
++ * Author: Alexander Duyck <alexander.h.duyck@intel.com>
++ */
++
++#ifndef __LINUX_TC_SKBEDIT_H
++#define __LINUX_TC_SKBEDIT_H
++
++#include <linux/pkt_cls.h>
++
++#define TCA_ACT_SKBEDIT 11
++
++#define SKBEDIT_F_PRIORITY            0x1
++#define SKBEDIT_F_QUEUE_MAPPING               0x2
++
++struct tc_skbedit {
++      tc_gen;
++};
++
++enum {
++      TCA_SKBEDIT_UNSPEC,
++      TCA_SKBEDIT_TM,
++      TCA_SKBEDIT_PARMS,
++      TCA_SKBEDIT_PRIORITY,
++      TCA_SKBEDIT_QUEUE_MAPPING,
++      __TCA_SKBEDIT_MAX
++};
++#define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
++
++#endif
+diff --git a/include/net/tc_act/tc_skbedit.h b/include/net/tc_act/tc_skbedit.h
+new file mode 100644
+index 0000000..6abb3ed
+--- /dev/null
++++ b/include/net/tc_act/tc_skbedit.h
+@@ -0,0 +1,34 @@
++/*
++ * Copyright (c) 2008, Intel Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
++ * Place - Suite 330, Boston, MA 02111-1307 USA.
++ *
++ * Author: Alexander Duyck <alexander.h.duyck@intel.com>
++ */
++
++#ifndef __NET_TC_SKBEDIT_H
++#define __NET_TC_SKBEDIT_H
++
++#include <net/act_api.h>
++
++struct tcf_skbedit {
++      struct tcf_common       common;
++      u32                     flags;
++      u32                     priority;
++      u16                     queue_mapping;
++};
++#define to_skbedit(pc) \
++      container_of(pc, struct tcf_skbedit, common)
++
++#endif /* __NET_TC_SKBEDIT_H */
+diff --git a/net/sched/Kconfig b/net/sched/Kconfig
+index efaa7a7..6767e54 100644
+--- a/net/sched/Kconfig
++++ b/net/sched/Kconfig
+@@ -485,6 +485,17 @@ config NET_ACT_SIMP
+         To compile this code as a module, choose M here: the
+         module will be called simple.
++config NET_ACT_SKBEDIT
++        tristate "SKB Editing"
++        depends on NET_CLS_ACT
++        ---help---
++        Say Y here to change skb priority or queue_mapping settings.
++
++        If unsure, say N.
++
++        To compile this code as a module, choose M here: the
++        module will be called skbedit.
++
+ config NET_CLS_IND
+       bool "Incoming device classification"
+       depends on NET_CLS_U32 || NET_CLS_FW
+diff --git a/net/sched/Makefile b/net/sched/Makefile
+index 3d9b953..e60c992 100644
+--- a/net/sched/Makefile
++++ b/net/sched/Makefile
+@@ -14,6 +14,7 @@ obj-$(CONFIG_NET_ACT_IPT)    += act_ipt.o
+ obj-$(CONFIG_NET_ACT_NAT)     += act_nat.o
+ obj-$(CONFIG_NET_ACT_PEDIT)   += act_pedit.o
+ obj-$(CONFIG_NET_ACT_SIMP)    += act_simple.o
++obj-$(CONFIG_NET_ACT_SKBEDIT) += act_skbedit.o
+ obj-$(CONFIG_NET_SCH_FIFO)    += sch_fifo.o
+ obj-$(CONFIG_NET_SCH_CBQ)     += sch_cbq.o
+ obj-$(CONFIG_NET_SCH_HTB)     += sch_htb.o
+diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
+new file mode 100644
+index 0000000..fe9777e
+--- /dev/null
++++ b/net/sched/act_skbedit.c
+@@ -0,0 +1,203 @@
++/*
++ * Copyright (c) 2008, Intel Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
++ * Place - Suite 330, Boston, MA 02111-1307 USA.
++ *
++ * Author: Alexander Duyck <alexander.h.duyck@intel.com>
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/skbuff.h>
++#include <linux/rtnetlink.h>
++#include <net/netlink.h>
++#include <net/pkt_sched.h>
++
++#include <linux/tc_act/tc_skbedit.h>
++#include <net/tc_act/tc_skbedit.h>
++
++#define SKBEDIT_TAB_MASK     15
++static struct tcf_common *tcf_skbedit_ht[SKBEDIT_TAB_MASK + 1];
++static u32 skbedit_idx_gen;
++static DEFINE_RWLOCK(skbedit_lock);
++
++static struct tcf_hashinfo skbedit_hash_info = {
++      .htab   =       tcf_skbedit_ht,
++      .hmask  =       SKBEDIT_TAB_MASK,
++      .lock   =       &skbedit_lock,
++};
++
++static int tcf_skbedit(struct sk_buff *skb, struct tc_action *a,
++                     struct tcf_result *res)
++{
++      struct tcf_skbedit *d = a->priv;
++
++      spin_lock(&d->tcf_lock);
++      d->tcf_tm.lastuse = jiffies;
++      d->tcf_bstats.bytes += qdisc_pkt_len(skb);
++      d->tcf_bstats.packets++;
++
++      if (d->flags & SKBEDIT_F_PRIORITY)
++              skb->priority = d->priority;
++      if (d->flags & SKBEDIT_F_QUEUE_MAPPING &&
++          skb->dev->real_num_tx_queues > d->queue_mapping)
++              skb_set_queue_mapping(skb, d->queue_mapping);
++
++      spin_unlock(&d->tcf_lock);
++      return d->tcf_action;
++}
++
++static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
++      [TCA_SKBEDIT_PARMS]             = { .len = sizeof(struct tc_skbedit) },
++      [TCA_SKBEDIT_PRIORITY]          = { .len = sizeof(u32) },
++      [TCA_SKBEDIT_QUEUE_MAPPING]     = { .len = sizeof(u16) },
++};
++
++static int tcf_skbedit_init(struct nlattr *nla, struct nlattr *est,
++                       struct tc_action *a, int ovr, int bind)
++{
++      struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
++      struct tc_skbedit *parm;
++      struct tcf_skbedit *d;
++      struct tcf_common *pc;
++      u32 flags = 0, *priority = NULL;
++      u16 *queue_mapping = NULL;
++      int ret = 0, err;
++
++      if (nla == NULL)
++              return -EINVAL;
++
++      err = nla_parse_nested(tb, TCA_SKBEDIT_MAX, nla, skbedit_policy);
++      if (err < 0)
++              return err;
++
++      if (tb[TCA_SKBEDIT_PARMS] == NULL)
++              return -EINVAL;
++
++      if (tb[TCA_SKBEDIT_PRIORITY] != NULL) {
++              flags |= SKBEDIT_F_PRIORITY;
++              priority = nla_data(tb[TCA_SKBEDIT_PRIORITY]);
++      }
++
++      if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) {
++              flags |= SKBEDIT_F_QUEUE_MAPPING;
++              queue_mapping = nla_data(tb[TCA_SKBEDIT_QUEUE_MAPPING]);
++      }
++      if (!flags)
++              return -EINVAL;
++
++      parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
++
++      pc = tcf_hash_check(parm->index, a, bind, &skbedit_hash_info);
++      if (!pc) {
++              pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind,
++                                   &skbedit_idx_gen, &skbedit_hash_info);
++              if (unlikely(!pc))
++                      return -ENOMEM;
++
++              d = to_skbedit(pc);
++              ret = ACT_P_CREATED;
++      } else {
++              d = to_skbedit(pc);
++              if (!ovr) {
++                      tcf_hash_release(pc, bind, &skbedit_hash_info);
++                      return -EEXIST;
++              }
++      }
++
++      spin_lock_bh(&d->tcf_lock);
++
++      d->flags = flags;
++      if (flags & SKBEDIT_F_PRIORITY)
++              d->priority = *priority;
++      if (flags & SKBEDIT_F_QUEUE_MAPPING)
++              d->queue_mapping = *queue_mapping;
++      d->tcf_action = parm->action;
++
++      spin_unlock_bh(&d->tcf_lock);
++
++      if (ret == ACT_P_CREATED)
++              tcf_hash_insert(pc, &skbedit_hash_info);
++      return ret;
++}
++
++static inline int tcf_skbedit_cleanup(struct tc_action *a, int bind)
++{
++      struct tcf_skbedit *d = a->priv;
++
++      if (d)
++              return tcf_hash_release(&d->common, bind, &skbedit_hash_info);
++      return 0;
++}
++
++static inline int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
++                              int bind, int ref)
++{
++      unsigned char *b = skb_tail_pointer(skb);
++      struct tcf_skbedit *d = a->priv;
++      struct tc_skbedit opt;
++      struct tcf_t t;
++
++      opt.index = d->tcf_index;
++      opt.refcnt = d->tcf_refcnt - ref;
++      opt.bindcnt = d->tcf_bindcnt - bind;
++      opt.action = d->tcf_action;
++      NLA_PUT(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt);
++      if (d->flags & SKBEDIT_F_PRIORITY)
++              NLA_PUT(skb, TCA_SKBEDIT_PRIORITY, sizeof(d->priority),
++                      &d->priority);
++      if (d->flags & SKBEDIT_F_QUEUE_MAPPING)
++              NLA_PUT(skb, TCA_SKBEDIT_QUEUE_MAPPING,
++                      sizeof(d->queue_mapping), &d->queue_mapping);
++      t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install);
++      t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse);
++      t.expires = jiffies_to_clock_t(d->tcf_tm.expires);
++      NLA_PUT(skb, TCA_SKBEDIT_TM, sizeof(t), &t);
++      return skb->len;
++
++nla_put_failure:
++      nlmsg_trim(skb, b);
++      return -1;
++}
++
++static struct tc_action_ops act_skbedit_ops = {
++      .kind           =       "skbedit",
++      .hinfo          =       &skbedit_hash_info,
++      .type           =       TCA_ACT_SKBEDIT,
++      .capab          =       TCA_CAP_NONE,
++      .owner          =       THIS_MODULE,
++      .act            =       tcf_skbedit,
++      .dump           =       tcf_skbedit_dump,
++      .cleanup        =       tcf_skbedit_cleanup,
++      .init           =       tcf_skbedit_init,
++      .walk           =       tcf_generic_walker,
++};
++
++MODULE_AUTHOR("Alexander Duyck, <alexander.h.duyck@intel.com>");
++MODULE_DESCRIPTION("SKB Editing");
++MODULE_LICENSE("GPL");
++
++static int __init skbedit_init_module(void)
++{
++      return tcf_register_action(&act_skbedit_ops);
++}
++
++static void __exit skbedit_cleanup_module(void)
++{
++      tcf_unregister_action(&act_skbedit_ops);
++}
++
++module_init(skbedit_init_module);
++module_exit(skbedit_cleanup_module);
+-- 
+1.5.2.4
+