Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Alexander Duyck and committed by
David S. Miller
ca9b0e27 92651940

+302 -1
+8 -1
Documentation/networking/multiqueue.txt
··· 66 66 Traffic will begin flowing through each queue if your base device has either 67 67 the default simple_tx_hash or a custom netdev->select_queue() defined. 68 68 69 - The behavior of tc filters remains the same. 69 + The behavior of tc filters remains the same. However a new tc action, 70 + skbedit, has been added. Assuming you wanted to route all traffic to a 71 + specific host, for example 192.168.0.3, though a specific queue you could use 72 + this action and establish a filter such as: 73 + 74 + tc filter add dev eth0 parent 1: protocol ip prio 1 u32 \ 75 + match ip dst 192.168.0.3 \ 76 + action skbedit queue_mapping 3 70 77 71 78 Author: Alexander Duyck <alexander.h.duyck@intel.com> 72 79 Original Author: Peter P. Waskiewicz Jr. <peter.p.waskiewicz.jr@intel.com>
+1
include/linux/tc_act/Kbuild
··· 3 3 header-y += tc_mirred.h 4 4 header-y += tc_pedit.h 5 5 header-y += tc_nat.h 6 + header-y += tc_skbedit.h
+44
include/linux/tc_act/tc_skbedit.h
··· 1 + /* 2 + * Copyright (c) 2008, Intel Corporation. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 15 + * Place - Suite 330, Boston, MA 02111-1307 USA. 16 + * 17 + * Author: Alexander Duyck <alexander.h.duyck@intel.com> 18 + */ 19 + 20 + #ifndef __LINUX_TC_SKBEDIT_H 21 + #define __LINUX_TC_SKBEDIT_H 22 + 23 + #include <linux/pkt_cls.h> 24 + 25 + #define TCA_ACT_SKBEDIT 11 26 + 27 + #define SKBEDIT_F_PRIORITY 0x1 28 + #define SKBEDIT_F_QUEUE_MAPPING 0x2 29 + 30 + struct tc_skbedit { 31 + tc_gen; 32 + }; 33 + 34 + enum { 35 + TCA_SKBEDIT_UNSPEC, 36 + TCA_SKBEDIT_TM, 37 + TCA_SKBEDIT_PARMS, 38 + TCA_SKBEDIT_PRIORITY, 39 + TCA_SKBEDIT_QUEUE_MAPPING, 40 + __TCA_SKBEDIT_MAX 41 + }; 42 + #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1) 43 + 44 + #endif
+34
include/net/tc_act/tc_skbedit.h
··· 1 + /* 2 + * Copyright (c) 2008, Intel Corporation. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 15 + * Place - Suite 330, Boston, MA 02111-1307 USA. 16 + * 17 + * Author: Alexander Duyck <alexander.h.duyck@intel.com> 18 + */ 19 + 20 + #ifndef __NET_TC_SKBEDIT_H 21 + #define __NET_TC_SKBEDIT_H 22 + 23 + #include <net/act_api.h> 24 + 25 + struct tcf_skbedit { 26 + struct tcf_common common; 27 + u32 flags; 28 + u32 priority; 29 + u16 queue_mapping; 30 + }; 31 + #define to_skbedit(pc) \ 32 + container_of(pc, struct tcf_skbedit, common) 33 + 34 + #endif /* __NET_TC_SKBEDIT_H */
+11
net/sched/Kconfig
··· 485 485 To compile this code as a module, choose M here: the 486 486 module will be called simple. 487 487 488 + config NET_ACT_SKBEDIT 489 + tristate "SKB Editing" 490 + depends on NET_CLS_ACT 491 + ---help--- 492 + Say Y here to change skb priority or queue_mapping settings. 493 + 494 + If unsure, say N. 495 + 496 + To compile this code as a module, choose M here: the 497 + module will be called skbedit. 498 + 488 499 config NET_CLS_IND 489 500 bool "Incoming device classification" 490 501 depends on NET_CLS_U32 || NET_CLS_FW
+1
net/sched/Makefile
··· 14 14 obj-$(CONFIG_NET_ACT_NAT) += act_nat.o 15 15 obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit.o 16 16 obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o 17 + obj-$(CONFIG_NET_ACT_SKBEDIT) += act_skbedit.o 17 18 obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o 18 19 obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o 19 20 obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o
+203
net/sched/act_skbedit.c
··· 1 + /* 2 + * Copyright (c) 2008, Intel Corporation. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 15 + * Place - Suite 330, Boston, MA 02111-1307 USA. 16 + * 17 + * Author: Alexander Duyck <alexander.h.duyck@intel.com> 18 + */ 19 + 20 + #include <linux/module.h> 21 + #include <linux/init.h> 22 + #include <linux/kernel.h> 23 + #include <linux/skbuff.h> 24 + #include <linux/rtnetlink.h> 25 + #include <net/netlink.h> 26 + #include <net/pkt_sched.h> 27 + 28 + #include <linux/tc_act/tc_skbedit.h> 29 + #include <net/tc_act/tc_skbedit.h> 30 + 31 + #define SKBEDIT_TAB_MASK 15 32 + static struct tcf_common *tcf_skbedit_ht[SKBEDIT_TAB_MASK + 1]; 33 + static u32 skbedit_idx_gen; 34 + static DEFINE_RWLOCK(skbedit_lock); 35 + 36 + static struct tcf_hashinfo skbedit_hash_info = { 37 + .htab = tcf_skbedit_ht, 38 + .hmask = SKBEDIT_TAB_MASK, 39 + .lock = &skbedit_lock, 40 + }; 41 + 42 + static int tcf_skbedit(struct sk_buff *skb, struct tc_action *a, 43 + struct tcf_result *res) 44 + { 45 + struct tcf_skbedit *d = a->priv; 46 + 47 + spin_lock(&d->tcf_lock); 48 + d->tcf_tm.lastuse = jiffies; 49 + d->tcf_bstats.bytes += qdisc_pkt_len(skb); 50 + d->tcf_bstats.packets++; 51 + 52 + if (d->flags & SKBEDIT_F_PRIORITY) 53 + skb->priority = d->priority; 54 + if (d->flags & SKBEDIT_F_QUEUE_MAPPING && 55 + skb->dev->real_num_tx_queues > d->queue_mapping) 56 + skb_set_queue_mapping(skb, d->queue_mapping); 57 + 58 + spin_unlock(&d->tcf_lock); 59 + return d->tcf_action; 60 + } 61 + 62 + static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = { 63 + [TCA_SKBEDIT_PARMS] = { .len = sizeof(struct tc_skbedit) }, 64 + [TCA_SKBEDIT_PRIORITY] = { .len = sizeof(u32) }, 65 + [TCA_SKBEDIT_QUEUE_MAPPING] = { .len = sizeof(u16) }, 66 + }; 67 + 68 + static int tcf_skbedit_init(struct nlattr *nla, struct nlattr *est, 69 + struct tc_action *a, int ovr, int bind) 70 + { 71 + struct nlattr *tb[TCA_SKBEDIT_MAX + 1]; 72 + struct tc_skbedit *parm; 73 + struct tcf_skbedit *d; 74 + struct tcf_common *pc; 75 + u32 flags = 0, *priority = NULL; 76 + u16 *queue_mapping = NULL; 77 + int ret = 0, err; 78 + 79 + if (nla == NULL) 80 + return -EINVAL; 81 + 82 + err = nla_parse_nested(tb, TCA_SKBEDIT_MAX, nla, skbedit_policy); 83 + if (err < 0) 84 + return err; 85 + 86 + if (tb[TCA_SKBEDIT_PARMS] == NULL) 87 + return -EINVAL; 88 + 89 + if (tb[TCA_SKBEDIT_PRIORITY] != NULL) { 90 + flags |= SKBEDIT_F_PRIORITY; 91 + priority = nla_data(tb[TCA_SKBEDIT_PRIORITY]); 92 + } 93 + 94 + if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) { 95 + flags |= SKBEDIT_F_QUEUE_MAPPING; 96 + queue_mapping = nla_data(tb[TCA_SKBEDIT_QUEUE_MAPPING]); 97 + } 98 + if (!flags) 99 + return -EINVAL; 100 + 101 + parm = nla_data(tb[TCA_SKBEDIT_PARMS]); 102 + 103 + pc = tcf_hash_check(parm->index, a, bind, &skbedit_hash_info); 104 + if (!pc) { 105 + pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind, 106 + &skbedit_idx_gen, &skbedit_hash_info); 107 + if (unlikely(!pc)) 108 + return -ENOMEM; 109 + 110 + d = to_skbedit(pc); 111 + ret = ACT_P_CREATED; 112 + } else { 113 + d = to_skbedit(pc); 114 + if (!ovr) { 115 + tcf_hash_release(pc, bind, &skbedit_hash_info); 116 + return -EEXIST; 117 + } 118 + } 119 + 120 + spin_lock_bh(&d->tcf_lock); 121 + 122 + d->flags = flags; 123 + if (flags & SKBEDIT_F_PRIORITY) 124 + d->priority = *priority; 125 + if (flags & SKBEDIT_F_QUEUE_MAPPING) 126 + d->queue_mapping = *queue_mapping; 127 + d->tcf_action = parm->action; 128 + 129 + spin_unlock_bh(&d->tcf_lock); 130 + 131 + if (ret == ACT_P_CREATED) 132 + tcf_hash_insert(pc, &skbedit_hash_info); 133 + return ret; 134 + } 135 + 136 + static inline int tcf_skbedit_cleanup(struct tc_action *a, int bind) 137 + { 138 + struct tcf_skbedit *d = a->priv; 139 + 140 + if (d) 141 + return tcf_hash_release(&d->common, bind, &skbedit_hash_info); 142 + return 0; 143 + } 144 + 145 + static inline int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, 146 + int bind, int ref) 147 + { 148 + unsigned char *b = skb_tail_pointer(skb); 149 + struct tcf_skbedit *d = a->priv; 150 + struct tc_skbedit opt; 151 + struct tcf_t t; 152 + 153 + opt.index = d->tcf_index; 154 + opt.refcnt = d->tcf_refcnt - ref; 155 + opt.bindcnt = d->tcf_bindcnt - bind; 156 + opt.action = d->tcf_action; 157 + NLA_PUT(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt); 158 + if (d->flags & SKBEDIT_F_PRIORITY) 159 + NLA_PUT(skb, TCA_SKBEDIT_PRIORITY, sizeof(d->priority), 160 + &d->priority); 161 + if (d->flags & SKBEDIT_F_QUEUE_MAPPING) 162 + NLA_PUT(skb, TCA_SKBEDIT_QUEUE_MAPPING, 163 + sizeof(d->queue_mapping), &d->queue_mapping); 164 + t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install); 165 + t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse); 166 + t.expires = jiffies_to_clock_t(d->tcf_tm.expires); 167 + NLA_PUT(skb, TCA_SKBEDIT_TM, sizeof(t), &t); 168 + return skb->len; 169 + 170 + nla_put_failure: 171 + nlmsg_trim(skb, b); 172 + return -1; 173 + } 174 + 175 + static struct tc_action_ops act_skbedit_ops = { 176 + .kind = "skbedit", 177 + .hinfo = &skbedit_hash_info, 178 + .type = TCA_ACT_SKBEDIT, 179 + .capab = TCA_CAP_NONE, 180 + .owner = THIS_MODULE, 181 + .act = tcf_skbedit, 182 + .dump = tcf_skbedit_dump, 183 + .cleanup = tcf_skbedit_cleanup, 184 + .init = tcf_skbedit_init, 185 + .walk = tcf_generic_walker, 186 + }; 187 + 188 + MODULE_AUTHOR("Alexander Duyck, <alexander.h.duyck@intel.com>"); 189 + MODULE_DESCRIPTION("SKB Editing"); 190 + MODULE_LICENSE("GPL"); 191 + 192 + static int __init skbedit_init_module(void) 193 + { 194 + return tcf_register_action(&act_skbedit_ops); 195 + } 196 + 197 + static void __exit skbedit_cleanup_module(void) 198 + { 199 + tcf_unregister_action(&act_skbedit_ops); 200 + } 201 + 202 + module_init(skbedit_init_module); 203 + module_exit(skbedit_cleanup_module);