diff options
author | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2011-02-21 00:03:20 +0000 |
---|---|---|
committer | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2011-02-21 00:03:20 +0000 |
commit | 5b934a6fcf88c52d872dbd7ecb9a0be4aeced5b6 (patch) | |
tree | 60d2028d39849ec2dbc5fe540addd1ef7b576204 /target/linux/generic | |
parent | 69f9eb90f800c74319aea3aaaadd205fbc9a7bd6 (diff) |
kernel: add a new scheduler action for restoring the connection tracking mark - useful for ingress shaping, will be used for replacing IMQ later
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@25639 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/generic')
6 files changed, 1026 insertions, 0 deletions
diff --git a/target/linux/generic/patches-2.6.32/280-sched_act_connmark.patch b/target/linux/generic/patches-2.6.32/280-sched_act_connmark.patch new file mode 100644 index 000000000..734fd1cd1 --- /dev/null +++ b/target/linux/generic/patches-2.6.32/280-sched_act_connmark.patch @@ -0,0 +1,171 @@ +--- /dev/null ++++ b/net/sched/act_connmark.c +@@ -0,0 +1,137 @@ ++/* ++ * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org> ++ * ++ * 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. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/skbuff.h> ++#include <linux/rtnetlink.h> ++#include <linux/pkt_cls.h> ++#include <linux/ip.h> ++#include <linux/ipv6.h> ++#include <net/netlink.h> ++#include <net/pkt_sched.h> ++#include <net/act_api.h> ++ ++#include <net/netfilter/nf_conntrack.h> ++#include <net/netfilter/nf_conntrack_core.h> ++ ++#define TCA_ACT_CONNMARK 20 ++ ++#define CONNMARK_TAB_MASK 3 ++static struct tcf_common *tcf_connmark_ht[CONNMARK_TAB_MASK + 1]; ++static u32 connmark_idx_gen; ++static DEFINE_RWLOCK(connmark_lock); ++ ++static struct tcf_hashinfo connmark_hash_info = { ++ .htab = tcf_connmark_ht, ++ .hmask = CONNMARK_TAB_MASK, ++ .lock = &connmark_lock, ++}; ++ ++static int tcf_connmark(struct sk_buff *skb, struct tc_action *a, ++ struct tcf_result *res) ++{ ++ struct nf_conn *c; ++ enum ip_conntrack_info ctinfo; ++ int proto; ++ int r; ++ ++ if (skb->protocol == htons(ETH_P_IP)) { ++ if (skb->len < sizeof(struct iphdr)) ++ goto out; ++ proto = PF_INET; ++ } else if (skb->protocol == htons(ETH_P_IPV6)) { ++ if (skb->len < sizeof(struct ipv6hdr)) ++ goto out; ++ proto = PF_INET6; ++ } else ++ goto out; ++ ++ r = nf_conntrack_in(dev_net(skb->dev), proto, NF_INET_PRE_ROUTING, skb); ++ if (r != NF_ACCEPT) ++ goto out; ++ ++ c = nf_ct_get(skb, &ctinfo); ++ if (!c) ++ goto out; ++ ++ skb->mark = c->mark; ++ nf_conntrack_put(skb->nfct); ++ skb->nfct = NULL; ++ ++out: ++ return TC_ACT_PIPE; ++} ++ ++static int tcf_connmark_init(struct nlattr *nla, struct nlattr *est, ++ struct tc_action *a, int ovr, int bind) ++{ ++ struct tcf_common *pc; ++ ++ pc = tcf_hash_create(0, est, a, sizeof(*pc), bind, ++ &connmark_idx_gen, &connmark_hash_info); ++ if (IS_ERR(pc)) ++ return PTR_ERR(pc); ++ ++ tcf_hash_insert(pc, &connmark_hash_info); ++ ++ return ACT_P_CREATED; ++} ++ ++static inline int tcf_connmark_cleanup(struct tc_action *a, int bind) ++{ ++ if (a->priv) ++ return tcf_hash_release(a->priv, bind, &connmark_hash_info); ++ return 0; ++} ++ ++static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, ++ int bind, int ref) ++{ ++ return skb->len; ++} ++ ++static struct tc_action_ops act_connmark_ops = { ++ .kind = "connmark", ++ .hinfo = &connmark_hash_info, ++ .type = TCA_ACT_CONNMARK, ++ .capab = TCA_CAP_NONE, ++ .owner = THIS_MODULE, ++ .act = tcf_connmark, ++ .dump = tcf_connmark_dump, ++ .cleanup = tcf_connmark_cleanup, ++ .init = tcf_connmark_init, ++ .walk = tcf_generic_walker, ++}; ++ ++MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>"); ++MODULE_DESCRIPTION("Connection tracking mark restoring"); ++MODULE_LICENSE("GPL"); ++ ++static int __init connmark_init_module(void) ++{ ++ return tcf_register_action(&act_connmark_ops); ++} ++ ++static void __exit connmark_cleanup_module(void) ++{ ++ tcf_unregister_action(&act_connmark_ops); ++} ++ ++module_init(connmark_init_module); ++module_exit(connmark_cleanup_module); +--- a/net/sched/Kconfig ++++ b/net/sched/Kconfig +@@ -546,6 +546,18 @@ config NET_ACT_SKBEDIT + To compile this code as a module, choose M here: the + module will be called skbedit. + ++config NET_ACT_CONNMARK ++ tristate "Connection Tracking Marking" ++ depends on NET_CLS_ACT ++ depends on NF_CONNTRACK ++ ---help--- ++ Say Y here to restore the connmark from a scheduler action ++ ++ If unsure, say N. ++ ++ To compile this code as a module, choose M here: the ++ module will be called act_connmark. ++ + config NET_CLS_IND + bool "Incoming device classification" + depends on NET_CLS_U32 || NET_CLS_FW +--- a/net/sched/Makefile ++++ b/net/sched/Makefile +@@ -15,6 +15,7 @@ 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_ACT_CONNMARK) += act_connmark.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/target/linux/generic/patches-2.6.34/280-sched_act_connmark.patch b/target/linux/generic/patches-2.6.34/280-sched_act_connmark.patch new file mode 100644 index 000000000..e02d1bc31 --- /dev/null +++ b/target/linux/generic/patches-2.6.34/280-sched_act_connmark.patch @@ -0,0 +1,171 @@ +--- /dev/null ++++ b/net/sched/act_connmark.c +@@ -0,0 +1,137 @@ ++/* ++ * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org> ++ * ++ * 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. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/skbuff.h> ++#include <linux/rtnetlink.h> ++#include <linux/pkt_cls.h> ++#include <linux/ip.h> ++#include <linux/ipv6.h> ++#include <net/netlink.h> ++#include <net/pkt_sched.h> ++#include <net/act_api.h> ++ ++#include <net/netfilter/nf_conntrack.h> ++#include <net/netfilter/nf_conntrack_core.h> ++ ++#define TCA_ACT_CONNMARK 20 ++ ++#define CONNMARK_TAB_MASK 3 ++static struct tcf_common *tcf_connmark_ht[CONNMARK_TAB_MASK + 1]; ++static u32 connmark_idx_gen; ++static DEFINE_RWLOCK(connmark_lock); ++ ++static struct tcf_hashinfo connmark_hash_info = { ++ .htab = tcf_connmark_ht, ++ .hmask = CONNMARK_TAB_MASK, ++ .lock = &connmark_lock, ++}; ++ ++static int tcf_connmark(struct sk_buff *skb, struct tc_action *a, ++ struct tcf_result *res) ++{ ++ struct nf_conn *c; ++ enum ip_conntrack_info ctinfo; ++ int proto; ++ int r; ++ ++ if (skb->protocol == htons(ETH_P_IP)) { ++ if (skb->len < sizeof(struct iphdr)) ++ goto out; ++ proto = PF_INET; ++ } else if (skb->protocol == htons(ETH_P_IPV6)) { ++ if (skb->len < sizeof(struct ipv6hdr)) ++ goto out; ++ proto = PF_INET6; ++ } else ++ goto out; ++ ++ r = nf_conntrack_in(dev_net(skb->dev), proto, NF_INET_PRE_ROUTING, skb); ++ if (r != NF_ACCEPT) ++ goto out; ++ ++ c = nf_ct_get(skb, &ctinfo); ++ if (!c) ++ goto out; ++ ++ skb->mark = c->mark; ++ nf_conntrack_put(skb->nfct); ++ skb->nfct = NULL; ++ ++out: ++ return TC_ACT_PIPE; ++} ++ ++static int tcf_connmark_init(struct nlattr *nla, struct nlattr *est, ++ struct tc_action *a, int ovr, int bind) ++{ ++ struct tcf_common *pc; ++ ++ pc = tcf_hash_create(0, est, a, sizeof(*pc), bind, ++ &connmark_idx_gen, &connmark_hash_info); ++ if (IS_ERR(pc)) ++ return PTR_ERR(pc); ++ ++ tcf_hash_insert(pc, &connmark_hash_info); ++ ++ return ACT_P_CREATED; ++} ++ ++static inline int tcf_connmark_cleanup(struct tc_action *a, int bind) ++{ ++ if (a->priv) ++ return tcf_hash_release(a->priv, bind, &connmark_hash_info); ++ return 0; ++} ++ ++static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, ++ int bind, int ref) ++{ ++ return skb->len; ++} ++ ++static struct tc_action_ops act_connmark_ops = { ++ .kind = "connmark", ++ .hinfo = &connmark_hash_info, ++ .type = TCA_ACT_CONNMARK, ++ .capab = TCA_CAP_NONE, ++ .owner = THIS_MODULE, ++ .act = tcf_connmark, ++ .dump = tcf_connmark_dump, ++ .cleanup = tcf_connmark_cleanup, ++ .init = tcf_connmark_init, ++ .walk = tcf_generic_walker, ++}; ++ ++MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>"); ++MODULE_DESCRIPTION("Connection tracking mark restoring"); ++MODULE_LICENSE("GPL"); ++ ++static int __init connmark_init_module(void) ++{ ++ return tcf_register_action(&act_connmark_ops); ++} ++ ++static void __exit connmark_cleanup_module(void) ++{ ++ tcf_unregister_action(&act_connmark_ops); ++} ++ ++module_init(connmark_init_module); ++module_exit(connmark_cleanup_module); +--- a/net/sched/Kconfig ++++ b/net/sched/Kconfig +@@ -549,6 +549,18 @@ + To compile this code as a module, choose M here: the + module will be called act_skbedit. + ++config NET_ACT_CONNMARK ++ tristate "Connection Tracking Marking" ++ depends on NET_CLS_ACT ++ depends on NF_CONNTRACK ++ ---help--- ++ Say Y here to restore the connmark from a scheduler action ++ ++ If unsure, say N. ++ ++ To compile this code as a module, choose M here: the ++ module will be called act_connmark. ++ + config NET_CLS_IND + bool "Incoming device classification" + depends on NET_CLS_U32 || NET_CLS_FW +--- a/net/sched/Makefile ++++ b/net/sched/Makefile +@@ -15,6 +15,7 @@ + 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_ACT_CONNMARK) += act_connmark.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/target/linux/generic/patches-2.6.35/290-sched_act_connmark.patch b/target/linux/generic/patches-2.6.35/290-sched_act_connmark.patch new file mode 100644 index 000000000..e02d1bc31 --- /dev/null +++ b/target/linux/generic/patches-2.6.35/290-sched_act_connmark.patch @@ -0,0 +1,171 @@ +--- /dev/null ++++ b/net/sched/act_connmark.c +@@ -0,0 +1,137 @@ ++/* ++ * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org> ++ * ++ * 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. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/skbuff.h> ++#include <linux/rtnetlink.h> ++#include <linux/pkt_cls.h> ++#include <linux/ip.h> ++#include <linux/ipv6.h> ++#include <net/netlink.h> ++#include <net/pkt_sched.h> ++#include <net/act_api.h> ++ ++#include <net/netfilter/nf_conntrack.h> ++#include <net/netfilter/nf_conntrack_core.h> ++ ++#define TCA_ACT_CONNMARK 20 ++ ++#define CONNMARK_TAB_MASK 3 ++static struct tcf_common *tcf_connmark_ht[CONNMARK_TAB_MASK + 1]; ++static u32 connmark_idx_gen; ++static DEFINE_RWLOCK(connmark_lock); ++ ++static struct tcf_hashinfo connmark_hash_info = { ++ .htab = tcf_connmark_ht, ++ .hmask = CONNMARK_TAB_MASK, ++ .lock = &connmark_lock, ++}; ++ ++static int tcf_connmark(struct sk_buff *skb, struct tc_action *a, ++ struct tcf_result *res) ++{ ++ struct nf_conn *c; ++ enum ip_conntrack_info ctinfo; ++ int proto; ++ int r; ++ ++ if (skb->protocol == htons(ETH_P_IP)) { ++ if (skb->len < sizeof(struct iphdr)) ++ goto out; ++ proto = PF_INET; ++ } else if (skb->protocol == htons(ETH_P_IPV6)) { ++ if (skb->len < sizeof(struct ipv6hdr)) ++ goto out; ++ proto = PF_INET6; ++ } else ++ goto out; ++ ++ r = nf_conntrack_in(dev_net(skb->dev), proto, NF_INET_PRE_ROUTING, skb); ++ if (r != NF_ACCEPT) ++ goto out; ++ ++ c = nf_ct_get(skb, &ctinfo); ++ if (!c) ++ goto out; ++ ++ skb->mark = c->mark; ++ nf_conntrack_put(skb->nfct); ++ skb->nfct = NULL; ++ ++out: ++ return TC_ACT_PIPE; ++} ++ ++static int tcf_connmark_init(struct nlattr *nla, struct nlattr *est, ++ struct tc_action *a, int ovr, int bind) ++{ ++ struct tcf_common *pc; ++ ++ pc = tcf_hash_create(0, est, a, sizeof(*pc), bind, ++ &connmark_idx_gen, &connmark_hash_info); ++ if (IS_ERR(pc)) ++ return PTR_ERR(pc); ++ ++ tcf_hash_insert(pc, &connmark_hash_info); ++ ++ return ACT_P_CREATED; ++} ++ ++static inline int tcf_connmark_cleanup(struct tc_action *a, int bind) ++{ ++ if (a->priv) ++ return tcf_hash_release(a->priv, bind, &connmark_hash_info); ++ return 0; ++} ++ ++static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, ++ int bind, int ref) ++{ ++ return skb->len; ++} ++ ++static struct tc_action_ops act_connmark_ops = { ++ .kind = "connmark", ++ .hinfo = &connmark_hash_info, ++ .type = TCA_ACT_CONNMARK, ++ .capab = TCA_CAP_NONE, ++ .owner = THIS_MODULE, ++ .act = tcf_connmark, ++ .dump = tcf_connmark_dump, ++ .cleanup = tcf_connmark_cleanup, ++ .init = tcf_connmark_init, ++ .walk = tcf_generic_walker, ++}; ++ ++MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>"); ++MODULE_DESCRIPTION("Connection tracking mark restoring"); ++MODULE_LICENSE("GPL"); ++ ++static int __init connmark_init_module(void) ++{ ++ return tcf_register_action(&act_connmark_ops); ++} ++ ++static void __exit connmark_cleanup_module(void) ++{ ++ tcf_unregister_action(&act_connmark_ops); ++} ++ ++module_init(connmark_init_module); ++module_exit(connmark_cleanup_module); +--- a/net/sched/Kconfig ++++ b/net/sched/Kconfig +@@ -549,6 +549,18 @@ + To compile this code as a module, choose M here: the + module will be called act_skbedit. + ++config NET_ACT_CONNMARK ++ tristate "Connection Tracking Marking" ++ depends on NET_CLS_ACT ++ depends on NF_CONNTRACK ++ ---help--- ++ Say Y here to restore the connmark from a scheduler action ++ ++ If unsure, say N. ++ ++ To compile this code as a module, choose M here: the ++ module will be called act_connmark. ++ + config NET_CLS_IND + bool "Incoming device classification" + depends on NET_CLS_U32 || NET_CLS_FW +--- a/net/sched/Makefile ++++ b/net/sched/Makefile +@@ -15,6 +15,7 @@ + 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_ACT_CONNMARK) += act_connmark.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/target/linux/generic/patches-2.6.36/290-sched_act_connmark.patch b/target/linux/generic/patches-2.6.36/290-sched_act_connmark.patch new file mode 100644 index 000000000..e02d1bc31 --- /dev/null +++ b/target/linux/generic/patches-2.6.36/290-sched_act_connmark.patch @@ -0,0 +1,171 @@ +--- /dev/null ++++ b/net/sched/act_connmark.c +@@ -0,0 +1,137 @@ ++/* ++ * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org> ++ * ++ * 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. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/skbuff.h> ++#include <linux/rtnetlink.h> ++#include <linux/pkt_cls.h> ++#include <linux/ip.h> ++#include <linux/ipv6.h> ++#include <net/netlink.h> ++#include <net/pkt_sched.h> ++#include <net/act_api.h> ++ ++#include <net/netfilter/nf_conntrack.h> ++#include <net/netfilter/nf_conntrack_core.h> ++ ++#define TCA_ACT_CONNMARK 20 ++ ++#define CONNMARK_TAB_MASK 3 ++static struct tcf_common *tcf_connmark_ht[CONNMARK_TAB_MASK + 1]; ++static u32 connmark_idx_gen; ++static DEFINE_RWLOCK(connmark_lock); ++ ++static struct tcf_hashinfo connmark_hash_info = { ++ .htab = tcf_connmark_ht, ++ .hmask = CONNMARK_TAB_MASK, ++ .lock = &connmark_lock, ++}; ++ ++static int tcf_connmark(struct sk_buff *skb, struct tc_action *a, ++ struct tcf_result *res) ++{ ++ struct nf_conn *c; ++ enum ip_conntrack_info ctinfo; ++ int proto; ++ int r; ++ ++ if (skb->protocol == htons(ETH_P_IP)) { ++ if (skb->len < sizeof(struct iphdr)) ++ goto out; ++ proto = PF_INET; ++ } else if (skb->protocol == htons(ETH_P_IPV6)) { ++ if (skb->len < sizeof(struct ipv6hdr)) ++ goto out; ++ proto = PF_INET6; ++ } else ++ goto out; ++ ++ r = nf_conntrack_in(dev_net(skb->dev), proto, NF_INET_PRE_ROUTING, skb); ++ if (r != NF_ACCEPT) ++ goto out; ++ ++ c = nf_ct_get(skb, &ctinfo); ++ if (!c) ++ goto out; ++ ++ skb->mark = c->mark; ++ nf_conntrack_put(skb->nfct); ++ skb->nfct = NULL; ++ ++out: ++ return TC_ACT_PIPE; ++} ++ ++static int tcf_connmark_init(struct nlattr *nla, struct nlattr *est, ++ struct tc_action *a, int ovr, int bind) ++{ ++ struct tcf_common *pc; ++ ++ pc = tcf_hash_create(0, est, a, sizeof(*pc), bind, ++ &connmark_idx_gen, &connmark_hash_info); ++ if (IS_ERR(pc)) ++ return PTR_ERR(pc); ++ ++ tcf_hash_insert(pc, &connmark_hash_info); ++ ++ return ACT_P_CREATED; ++} ++ ++static inline int tcf_connmark_cleanup(struct tc_action *a, int bind) ++{ ++ if (a->priv) ++ return tcf_hash_release(a->priv, bind, &connmark_hash_info); ++ return 0; ++} ++ ++static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, ++ int bind, int ref) ++{ ++ return skb->len; ++} ++ ++static struct tc_action_ops act_connmark_ops = { ++ .kind = "connmark", ++ .hinfo = &connmark_hash_info, ++ .type = TCA_ACT_CONNMARK, ++ .capab = TCA_CAP_NONE, ++ .owner = THIS_MODULE, ++ .act = tcf_connmark, ++ .dump = tcf_connmark_dump, ++ .cleanup = tcf_connmark_cleanup, ++ .init = tcf_connmark_init, ++ .walk = tcf_generic_walker, ++}; ++ ++MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>"); ++MODULE_DESCRIPTION("Connection tracking mark restoring"); ++MODULE_LICENSE("GPL"); ++ ++static int __init connmark_init_module(void) ++{ ++ return tcf_register_action(&act_connmark_ops); ++} ++ ++static void __exit connmark_cleanup_module(void) ++{ ++ tcf_unregister_action(&act_connmark_ops); ++} ++ ++module_init(connmark_init_module); ++module_exit(connmark_cleanup_module); +--- a/net/sched/Kconfig ++++ b/net/sched/Kconfig +@@ -549,6 +549,18 @@ + To compile this code as a module, choose M here: the + module will be called act_skbedit. + ++config NET_ACT_CONNMARK ++ tristate "Connection Tracking Marking" ++ depends on NET_CLS_ACT ++ depends on NF_CONNTRACK ++ ---help--- ++ Say Y here to restore the connmark from a scheduler action ++ ++ If unsure, say N. ++ ++ To compile this code as a module, choose M here: the ++ module will be called act_connmark. ++ + config NET_CLS_IND + bool "Incoming device classification" + depends on NET_CLS_U32 || NET_CLS_FW +--- a/net/sched/Makefile ++++ b/net/sched/Makefile +@@ -15,6 +15,7 @@ + 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_ACT_CONNMARK) += act_connmark.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/target/linux/generic/patches-2.6.37/290-sched_act_connmark.patch b/target/linux/generic/patches-2.6.37/290-sched_act_connmark.patch new file mode 100644 index 000000000..013c116c4 --- /dev/null +++ b/target/linux/generic/patches-2.6.37/290-sched_act_connmark.patch @@ -0,0 +1,171 @@ +--- /dev/null ++++ b/net/sched/act_connmark.c +@@ -0,0 +1,137 @@ ++/* ++ * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org> ++ * ++ * 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. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/skbuff.h> ++#include <linux/rtnetlink.h> ++#include <linux/pkt_cls.h> ++#include <linux/ip.h> ++#include <linux/ipv6.h> ++#include <net/netlink.h> ++#include <net/pkt_sched.h> ++#include <net/act_api.h> ++ ++#include <net/netfilter/nf_conntrack.h> ++#include <net/netfilter/nf_conntrack_core.h> ++ ++#define TCA_ACT_CONNMARK 20 ++ ++#define CONNMARK_TAB_MASK 3 ++static struct tcf_common *tcf_connmark_ht[CONNMARK_TAB_MASK + 1]; ++static u32 connmark_idx_gen; ++static DEFINE_RWLOCK(connmark_lock); ++ ++static struct tcf_hashinfo connmark_hash_info = { ++ .htab = tcf_connmark_ht, ++ .hmask = CONNMARK_TAB_MASK, ++ .lock = &connmark_lock, ++}; ++ ++static int tcf_connmark(struct sk_buff *skb, struct tc_action *a, ++ struct tcf_result *res) ++{ ++ struct nf_conn *c; ++ enum ip_conntrack_info ctinfo; ++ int proto; ++ int r; ++ ++ if (skb->protocol == htons(ETH_P_IP)) { ++ if (skb->len < sizeof(struct iphdr)) ++ goto out; ++ proto = PF_INET; ++ } else if (skb->protocol == htons(ETH_P_IPV6)) { ++ if (skb->len < sizeof(struct ipv6hdr)) ++ goto out; ++ proto = PF_INET6; ++ } else ++ goto out; ++ ++ r = nf_conntrack_in(dev_net(skb->dev), proto, NF_INET_PRE_ROUTING, skb); ++ if (r != NF_ACCEPT) ++ goto out; ++ ++ c = nf_ct_get(skb, &ctinfo); ++ if (!c) ++ goto out; ++ ++ skb->mark = c->mark; ++ nf_conntrack_put(skb->nfct); ++ skb->nfct = NULL; ++ ++out: ++ return TC_ACT_PIPE; ++} ++ ++static int tcf_connmark_init(struct nlattr *nla, struct nlattr *est, ++ struct tc_action *a, int ovr, int bind) ++{ ++ struct tcf_common *pc; ++ ++ pc = tcf_hash_create(0, est, a, sizeof(*pc), bind, ++ &connmark_idx_gen, &connmark_hash_info); ++ if (IS_ERR(pc)) ++ return PTR_ERR(pc); ++ ++ tcf_hash_insert(pc, &connmark_hash_info); ++ ++ return ACT_P_CREATED; ++} ++ ++static inline int tcf_connmark_cleanup(struct tc_action *a, int bind) ++{ ++ if (a->priv) ++ return tcf_hash_release(a->priv, bind, &connmark_hash_info); ++ return 0; ++} ++ ++static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, ++ int bind, int ref) ++{ ++ return skb->len; ++} ++ ++static struct tc_action_ops act_connmark_ops = { ++ .kind = "connmark", ++ .hinfo = &connmark_hash_info, ++ .type = TCA_ACT_CONNMARK, ++ .capab = TCA_CAP_NONE, ++ .owner = THIS_MODULE, ++ .act = tcf_connmark, ++ .dump = tcf_connmark_dump, ++ .cleanup = tcf_connmark_cleanup, ++ .init = tcf_connmark_init, ++ .walk = tcf_generic_walker, ++}; ++ ++MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>"); ++MODULE_DESCRIPTION("Connection tracking mark restoring"); ++MODULE_LICENSE("GPL"); ++ ++static int __init connmark_init_module(void) ++{ ++ return tcf_register_action(&act_connmark_ops); ++} ++ ++static void __exit connmark_cleanup_module(void) ++{ ++ tcf_unregister_action(&act_connmark_ops); ++} ++ ++module_init(connmark_init_module); ++module_exit(connmark_cleanup_module); +--- a/net/sched/Kconfig ++++ b/net/sched/Kconfig +@@ -559,6 +559,18 @@ + To compile this code as a module, choose M here: the + module will be called act_csum. + ++config NET_ACT_CONNMARK ++ tristate "Connection Tracking Marking" ++ depends on NET_CLS_ACT ++ depends on NF_CONNTRACK ++ ---help--- ++ Say Y here to restore the connmark from a scheduler action ++ ++ If unsure, say N. ++ ++ To compile this code as a module, choose M here: the ++ module will be called act_connmark. ++ + config NET_CLS_IND + bool "Incoming device classification" + depends on NET_CLS_U32 || NET_CLS_FW +--- a/net/sched/Makefile ++++ b/net/sched/Makefile +@@ -16,6 +16,7 @@ + obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o + obj-$(CONFIG_NET_ACT_SKBEDIT) += act_skbedit.o + obj-$(CONFIG_NET_ACT_CSUM) += act_csum.o ++obj-$(CONFIG_NET_ACT_CONNMARK) += act_connmark.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/target/linux/generic/patches-2.6.38/290-sched_act_connmark.patch b/target/linux/generic/patches-2.6.38/290-sched_act_connmark.patch new file mode 100644 index 000000000..013c116c4 --- /dev/null +++ b/target/linux/generic/patches-2.6.38/290-sched_act_connmark.patch @@ -0,0 +1,171 @@ +--- /dev/null ++++ b/net/sched/act_connmark.c +@@ -0,0 +1,137 @@ ++/* ++ * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org> ++ * ++ * 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. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/skbuff.h> ++#include <linux/rtnetlink.h> ++#include <linux/pkt_cls.h> ++#include <linux/ip.h> ++#include <linux/ipv6.h> ++#include <net/netlink.h> ++#include <net/pkt_sched.h> ++#include <net/act_api.h> ++ ++#include <net/netfilter/nf_conntrack.h> ++#include <net/netfilter/nf_conntrack_core.h> ++ ++#define TCA_ACT_CONNMARK 20 ++ ++#define CONNMARK_TAB_MASK 3 ++static struct tcf_common *tcf_connmark_ht[CONNMARK_TAB_MASK + 1]; ++static u32 connmark_idx_gen; ++static DEFINE_RWLOCK(connmark_lock); ++ ++static struct tcf_hashinfo connmark_hash_info = { ++ .htab = tcf_connmark_ht, ++ .hmask = CONNMARK_TAB_MASK, ++ .lock = &connmark_lock, ++}; ++ ++static int tcf_connmark(struct sk_buff *skb, struct tc_action *a, ++ struct tcf_result *res) ++{ ++ struct nf_conn *c; ++ enum ip_conntrack_info ctinfo; ++ int proto; ++ int r; ++ ++ if (skb->protocol == htons(ETH_P_IP)) { ++ if (skb->len < sizeof(struct iphdr)) ++ goto out; ++ proto = PF_INET; ++ } else if (skb->protocol == htons(ETH_P_IPV6)) { ++ if (skb->len < sizeof(struct ipv6hdr)) ++ goto out; ++ proto = PF_INET6; ++ } else ++ goto out; ++ ++ r = nf_conntrack_in(dev_net(skb->dev), proto, NF_INET_PRE_ROUTING, skb); ++ if (r != NF_ACCEPT) ++ goto out; ++ ++ c = nf_ct_get(skb, &ctinfo); ++ if (!c) ++ goto out; ++ ++ skb->mark = c->mark; ++ nf_conntrack_put(skb->nfct); ++ skb->nfct = NULL; ++ ++out: ++ return TC_ACT_PIPE; ++} ++ ++static int tcf_connmark_init(struct nlattr *nla, struct nlattr *est, ++ struct tc_action *a, int ovr, int bind) ++{ ++ struct tcf_common *pc; ++ ++ pc = tcf_hash_create(0, est, a, sizeof(*pc), bind, ++ &connmark_idx_gen, &connmark_hash_info); ++ if (IS_ERR(pc)) ++ return PTR_ERR(pc); ++ ++ tcf_hash_insert(pc, &connmark_hash_info); ++ ++ return ACT_P_CREATED; ++} ++ ++static inline int tcf_connmark_cleanup(struct tc_action *a, int bind) ++{ ++ if (a->priv) ++ return tcf_hash_release(a->priv, bind, &connmark_hash_info); ++ return 0; ++} ++ ++static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, ++ int bind, int ref) ++{ ++ return skb->len; ++} ++ ++static struct tc_action_ops act_connmark_ops = { ++ .kind = "connmark", ++ .hinfo = &connmark_hash_info, ++ .type = TCA_ACT_CONNMARK, ++ .capab = TCA_CAP_NONE, ++ .owner = THIS_MODULE, ++ .act = tcf_connmark, ++ .dump = tcf_connmark_dump, ++ .cleanup = tcf_connmark_cleanup, ++ .init = tcf_connmark_init, ++ .walk = tcf_generic_walker, ++}; ++ ++MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>"); ++MODULE_DESCRIPTION("Connection tracking mark restoring"); ++MODULE_LICENSE("GPL"); ++ ++static int __init connmark_init_module(void) ++{ ++ return tcf_register_action(&act_connmark_ops); ++} ++ ++static void __exit connmark_cleanup_module(void) ++{ ++ tcf_unregister_action(&act_connmark_ops); ++} ++ ++module_init(connmark_init_module); ++module_exit(connmark_cleanup_module); +--- a/net/sched/Kconfig ++++ b/net/sched/Kconfig +@@ -559,6 +559,18 @@ + To compile this code as a module, choose M here: the + module will be called act_csum. + ++config NET_ACT_CONNMARK ++ tristate "Connection Tracking Marking" ++ depends on NET_CLS_ACT ++ depends on NF_CONNTRACK ++ ---help--- ++ Say Y here to restore the connmark from a scheduler action ++ ++ If unsure, say N. ++ ++ To compile this code as a module, choose M here: the ++ module will be called act_connmark. ++ + config NET_CLS_IND + bool "Incoming device classification" + depends on NET_CLS_U32 || NET_CLS_FW +--- a/net/sched/Makefile ++++ b/net/sched/Makefile +@@ -16,6 +16,7 @@ + obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o + obj-$(CONFIG_NET_ACT_SKBEDIT) += act_skbedit.o + obj-$(CONFIG_NET_ACT_CSUM) += act_csum.o ++obj-$(CONFIG_NET_ACT_CONNMARK) += act_connmark.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 |