diff options
Diffstat (limited to 'target/linux/generic/patches-3.13/621-sched_act_connmark.patch')
-rw-r--r-- | target/linux/generic/patches-3.13/621-sched_act_connmark.patch | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/target/linux/generic/patches-3.13/621-sched_act_connmark.patch b/target/linux/generic/patches-3.13/621-sched_act_connmark.patch new file mode 100644 index 0000000000..8185098d03 --- /dev/null +++ b/target/linux/generic/patches-3.13/621-sched_act_connmark.patch @@ -0,0 +1,183 @@ +--- /dev/null ++++ b/net/sched/act_connmark.c +@@ -0,0 +1,148 @@ ++/* ++ * 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, const 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 net *net, struct nlattr *nla, ++ struct nlattr *est, struct tc_action *a, ++ int ovr, int bind) ++{ ++ struct tcf_common *pc; ++ int ret = 0; ++ ++ pc = tcf_hash_check(0, a, bind, &connmark_hash_info); ++ if (!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); ++ ret = ACT_P_CREATED; ++ } else { ++ if (!ovr) { ++ tcf_hash_release(pc, bind, &connmark_hash_info); ++ return -EEXIST; ++ } ++ } ++ ++ return ret; ++} ++ ++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 +@@ -694,6 +694,19 @@ config NET_ACT_CSUM + 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 ++ depends on NF_CONNTRACK_MARK ++ ---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_PEDIT) += act_pedit + 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 |