Blame view
net/sched/act_skbedit.c
5.71 KB
ca9b0e27e pkt_action: add n... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
/* * 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, }; |
dc7f9f6e8 net: sched: const... |
41 |
static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a, |
ca9b0e27e pkt_action: add n... |
42 43 44 45 46 47 |
struct tcf_result *res) { struct tcf_skbedit *d = a->priv; spin_lock(&d->tcf_lock); d->tcf_tm.lastuse = jiffies; |
bfe0d0298 net_sched: factor... |
48 |
bstats_update(&d->tcf_bstats, skb); |
ca9b0e27e pkt_action: add n... |
49 50 51 52 53 54 |
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); |
1c55d62e7 pkt_sched: skbedi... |
55 56 |
if (d->flags & SKBEDIT_F_MARK) skb->mark = d->mark; |
ca9b0e27e pkt_action: add n... |
57 58 59 60 61 62 63 64 65 |
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) }, |
1c55d62e7 pkt_sched: skbedi... |
66 |
[TCA_SKBEDIT_MARK] = { .len = sizeof(u32) }, |
ca9b0e27e pkt_action: add n... |
67 68 69 70 71 72 73 74 75 |
}; 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; |
1c55d62e7 pkt_sched: skbedi... |
76 |
u32 flags = 0, *priority = NULL, *mark = NULL; |
ca9b0e27e pkt_action: add n... |
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
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]); } |
1c55d62e7 pkt_sched: skbedi... |
99 100 101 102 103 |
if (tb[TCA_SKBEDIT_MARK] != NULL) { flags |= SKBEDIT_F_MARK; mark = nla_data(tb[TCA_SKBEDIT_MARK]); } |
ca9b0e27e pkt_action: add n... |
104 105 106 107 108 109 110 111 112 |
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); |
0e991ec6a tc: propogate err... |
113 |
if (IS_ERR(pc)) |
cc7ec456f net_sched: cleanups |
114 |
return PTR_ERR(pc); |
ca9b0e27e pkt_action: add n... |
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
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; |
1c55d62e7 pkt_sched: skbedi... |
133 134 |
if (flags & SKBEDIT_F_MARK) d->mark = *mark; |
ca9b0e27e pkt_action: add n... |
135 136 137 138 139 140 141 142 |
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; } |
cc7ec456f net_sched: cleanups |
143 |
static int tcf_skbedit_cleanup(struct tc_action *a, int bind) |
ca9b0e27e pkt_action: add n... |
144 145 146 147 148 149 150 |
{ struct tcf_skbedit *d = a->priv; if (d) return tcf_hash_release(&d->common, bind, &skbedit_hash_info); return 0; } |
cc7ec456f net_sched: cleanups |
151 152 |
static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
ca9b0e27e pkt_action: add n... |
153 154 155 |
{ unsigned char *b = skb_tail_pointer(skb); struct tcf_skbedit *d = a->priv; |
1c40be12f net sched: fix so... |
156 157 158 159 160 161 |
struct tc_skbedit opt = { .index = d->tcf_index, .refcnt = d->tcf_refcnt - ref, .bindcnt = d->tcf_bindcnt - bind, .action = d->tcf_action, }; |
ca9b0e27e pkt_action: add n... |
162 |
struct tcf_t t; |
ca9b0e27e pkt_action: add n... |
163 164 165 166 167 168 169 |
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); |
1c55d62e7 pkt_sched: skbedi... |
170 171 172 |
if (d->flags & SKBEDIT_F_MARK) NLA_PUT(skb, TCA_SKBEDIT_MARK, sizeof(d->mark), &d->mark); |
ca9b0e27e pkt_action: add n... |
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
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); |