Blame view
net/sched/act_skbedit.c
7.15 KB
ca9b0e27e pkt_action: add n... |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* * 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 |
c057b190b net/*: Fix FSF ad... |
14 |
* this program; if not, see <http://www.gnu.org/licenses/>. |
ca9b0e27e pkt_action: add n... |
15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
* * 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> |
c7d03a00b netns: make struc... |
29 |
static unsigned int skbedit_net_id; |
a85a970af net_sched: move t... |
30 |
static struct tc_action_ops act_skbedit_ops; |
ddf97ccdd net_sched: add ne... |
31 |
|
dc7f9f6e8 net: sched: const... |
32 |
static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a, |
ca9b0e27e pkt_action: add n... |
33 34 |
struct tcf_result *res) { |
a85a970af net_sched: move t... |
35 |
struct tcf_skbedit *d = to_skbedit(a); |
ca9b0e27e pkt_action: add n... |
36 37 |
spin_lock(&d->tcf_lock); |
9c4a4e488 net sched: action... |
38 |
tcf_lastuse_update(&d->tcf_tm); |
bfe0d0298 net_sched: factor... |
39 |
bstats_update(&d->tcf_bstats, skb); |
ca9b0e27e pkt_action: add n... |
40 41 42 43 44 45 |
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); |
4fe77d82e skbedit: allow th... |
46 47 48 49 |
if (d->flags & SKBEDIT_F_MARK) { skb->mark &= ~d->mask; skb->mark |= d->mark & d->mask; } |
ff202ee1e net sched actions... |
50 51 |
if (d->flags & SKBEDIT_F_PTYPE) skb->pkt_type = d->ptype; |
ca9b0e27e pkt_action: add n... |
52 53 54 55 56 57 58 59 60 |
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... |
61 |
[TCA_SKBEDIT_MARK] = { .len = sizeof(u32) }, |
ff202ee1e net sched actions... |
62 |
[TCA_SKBEDIT_PTYPE] = { .len = sizeof(u16) }, |
4fe77d82e skbedit: allow th... |
63 |
[TCA_SKBEDIT_MASK] = { .len = sizeof(u32) }, |
ca9b0e27e pkt_action: add n... |
64 |
}; |
c1b52739e pkt_sched: namesp... |
65 |
static int tcf_skbedit_init(struct net *net, struct nlattr *nla, |
a85a970af net_sched: move t... |
66 |
struct nlattr *est, struct tc_action **a, |
c1b52739e pkt_sched: namesp... |
67 |
int ovr, int bind) |
ca9b0e27e pkt_action: add n... |
68 |
{ |
ddf97ccdd net_sched: add ne... |
69 |
struct tc_action_net *tn = net_generic(net, skbedit_net_id); |
ca9b0e27e pkt_action: add n... |
70 71 72 |
struct nlattr *tb[TCA_SKBEDIT_MAX + 1]; struct tc_skbedit *parm; struct tcf_skbedit *d; |
4fe77d82e skbedit: allow th... |
73 |
u32 flags = 0, *priority = NULL, *mark = NULL, *mask = NULL; |
ff202ee1e net sched actions... |
74 |
u16 *queue_mapping = NULL, *ptype = NULL; |
b2313077e net_sched: make t... |
75 76 |
bool exists = false; int ret = 0, err; |
ca9b0e27e pkt_action: add n... |
77 78 79 |
if (nla == NULL) return -EINVAL; |
fceb6435e netlink: pass ext... |
80 |
err = nla_parse_nested(tb, TCA_SKBEDIT_MAX, nla, skbedit_policy, NULL); |
ca9b0e27e pkt_action: add n... |
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
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... |
96 |
|
ff202ee1e net sched actions... |
97 98 99 100 101 102 |
if (tb[TCA_SKBEDIT_PTYPE] != NULL) { ptype = nla_data(tb[TCA_SKBEDIT_PTYPE]); if (!skb_pkt_type_ok(*ptype)) return -EINVAL; flags |= SKBEDIT_F_PTYPE; } |
1c55d62e7 pkt_sched: skbedi... |
103 104 105 106 |
if (tb[TCA_SKBEDIT_MARK] != NULL) { flags |= SKBEDIT_F_MARK; mark = nla_data(tb[TCA_SKBEDIT_MARK]); } |
4fe77d82e skbedit: allow th... |
107 108 109 110 |
if (tb[TCA_SKBEDIT_MASK] != NULL) { flags |= SKBEDIT_F_MASK; mask = nla_data(tb[TCA_SKBEDIT_MASK]); } |
ca9b0e27e pkt_action: add n... |
111 |
parm = nla_data(tb[TCA_SKBEDIT_PARMS]); |
65a206c01 net/sched: Change... |
112 |
exists = tcf_idr_check(tn, parm->index, a, bind); |
5e1567aeb net sched: skbedi... |
113 114 115 116 |
if (exists && bind) return 0; if (!flags) { |
869007543 net sched actions... |
117 118 |
if (exists) tcf_idr_release(*a, bind); |
5e1567aeb net sched: skbedi... |
119 120 121 122 |
return -EINVAL; } if (!exists) { |
65a206c01 net/sched: Change... |
123 124 |
ret = tcf_idr_create(tn, parm->index, est, a, &act_skbedit_ops, bind, false); |
86062033f net_sched: act: h... |
125 126 |
if (ret) return ret; |
ca9b0e27e pkt_action: add n... |
127 |
|
a85a970af net_sched: move t... |
128 |
d = to_skbedit(*a); |
ca9b0e27e pkt_action: add n... |
129 130 |
ret = ACT_P_CREATED; } else { |
a85a970af net_sched: move t... |
131 |
d = to_skbedit(*a); |
65a206c01 net/sched: Change... |
132 |
tcf_idr_release(*a, bind); |
1a29321ed net_sched: act: D... |
133 |
if (!ovr) |
ca9b0e27e pkt_action: add n... |
134 |
return -EEXIST; |
ca9b0e27e pkt_action: add n... |
135 136 137 138 139 140 141 142 143 |
} 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... |
144 145 |
if (flags & SKBEDIT_F_MARK) d->mark = *mark; |
ff202ee1e net sched actions... |
146 147 |
if (flags & SKBEDIT_F_PTYPE) d->ptype = *ptype; |
4fe77d82e skbedit: allow th... |
148 149 150 151 |
/* default behaviour is to use all the bits */ d->mask = 0xffffffff; if (flags & SKBEDIT_F_MASK) d->mask = *mask; |
1c55d62e7 pkt_sched: skbedi... |
152 |
|
ca9b0e27e pkt_action: add n... |
153 154 155 156 157 |
d->tcf_action = parm->action; spin_unlock_bh(&d->tcf_lock); if (ret == ACT_P_CREATED) |
65a206c01 net/sched: Change... |
158 |
tcf_idr_insert(tn, *a); |
ca9b0e27e pkt_action: add n... |
159 160 |
return ret; } |
cc7ec456f net_sched: cleanups |
161 162 |
static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
ca9b0e27e pkt_action: add n... |
163 164 |
{ unsigned char *b = skb_tail_pointer(skb); |
a85a970af net_sched: move t... |
165 |
struct tcf_skbedit *d = to_skbedit(a); |
1c40be12f net sched: fix so... |
166 167 168 169 170 171 |
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... |
172 |
struct tcf_t t; |
1b34ec43c pkt_sched: Stop u... |
173 174 175 |
if (nla_put(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt)) goto nla_put_failure; if ((d->flags & SKBEDIT_F_PRIORITY) && |
61cc535de net sched actions... |
176 |
nla_put_u32(skb, TCA_SKBEDIT_PRIORITY, d->priority)) |
1b34ec43c pkt_sched: Stop u... |
177 178 |
goto nla_put_failure; if ((d->flags & SKBEDIT_F_QUEUE_MAPPING) && |
61cc535de net sched actions... |
179 |
nla_put_u16(skb, TCA_SKBEDIT_QUEUE_MAPPING, d->queue_mapping)) |
1b34ec43c pkt_sched: Stop u... |
180 181 |
goto nla_put_failure; if ((d->flags & SKBEDIT_F_MARK) && |
61cc535de net sched actions... |
182 |
nla_put_u32(skb, TCA_SKBEDIT_MARK, d->mark)) |
1b34ec43c pkt_sched: Stop u... |
183 |
goto nla_put_failure; |
ff202ee1e net sched actions... |
184 |
if ((d->flags & SKBEDIT_F_PTYPE) && |
61cc535de net sched actions... |
185 |
nla_put_u16(skb, TCA_SKBEDIT_PTYPE, d->ptype)) |
ff202ee1e net sched actions... |
186 |
goto nla_put_failure; |
4fe77d82e skbedit: allow th... |
187 188 189 |
if ((d->flags & SKBEDIT_F_MASK) && nla_put_u32(skb, TCA_SKBEDIT_MASK, d->mask)) goto nla_put_failure; |
48d8ee169 net sched actions... |
190 191 |
tcf_tm_dump(&t, &d->tcf_tm); |
9854518ea sched: align nlat... |
192 |
if (nla_put_64bit(skb, TCA_SKBEDIT_TM, sizeof(t), &t, TCA_SKBEDIT_PAD)) |
1b34ec43c pkt_sched: Stop u... |
193 |
goto nla_put_failure; |
ca9b0e27e pkt_action: add n... |
194 195 196 197 198 199 |
return skb->len; nla_put_failure: nlmsg_trim(skb, b); return -1; } |
ddf97ccdd net_sched: add ne... |
200 201 |
static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb, struct netlink_callback *cb, int type, |
a85a970af net_sched: move t... |
202 |
const struct tc_action_ops *ops) |
ddf97ccdd net_sched: add ne... |
203 204 |
{ struct tc_action_net *tn = net_generic(net, skbedit_net_id); |
a85a970af net_sched: move t... |
205 |
return tcf_generic_walker(tn, skb, cb, type, ops); |
ddf97ccdd net_sched: add ne... |
206 |
} |
a85a970af net_sched: move t... |
207 |
static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index) |
ddf97ccdd net_sched: add ne... |
208 209 |
{ struct tc_action_net *tn = net_generic(net, skbedit_net_id); |
65a206c01 net/sched: Change... |
210 |
return tcf_idr_search(tn, a, index); |
ddf97ccdd net_sched: add ne... |
211 |
} |
ca9b0e27e pkt_action: add n... |
212 213 |
static struct tc_action_ops act_skbedit_ops = { .kind = "skbedit", |
ca9b0e27e pkt_action: add n... |
214 |
.type = TCA_ACT_SKBEDIT, |
ca9b0e27e pkt_action: add n... |
215 216 217 |
.owner = THIS_MODULE, .act = tcf_skbedit, .dump = tcf_skbedit_dump, |
ca9b0e27e pkt_action: add n... |
218 |
.init = tcf_skbedit_init, |
ddf97ccdd net_sched: add ne... |
219 220 |
.walk = tcf_skbedit_walker, .lookup = tcf_skbedit_search, |
a85a970af net_sched: move t... |
221 |
.size = sizeof(struct tcf_skbedit), |
ddf97ccdd net_sched: add ne... |
222 223 224 225 226 |
}; static __net_init int skbedit_init_net(struct net *net) { struct tc_action_net *tn = net_generic(net, skbedit_net_id); |
c7e460ce5 Revert "net_sched... |
227 |
return tc_action_net_init(tn, &act_skbedit_ops); |
ddf97ccdd net_sched: add ne... |
228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
} static void __net_exit skbedit_exit_net(struct net *net) { struct tc_action_net *tn = net_generic(net, skbedit_net_id); tc_action_net_exit(tn); } static struct pernet_operations skbedit_net_ops = { .init = skbedit_init_net, .exit = skbedit_exit_net, .id = &skbedit_net_id, .size = sizeof(struct tc_action_net), |
ca9b0e27e pkt_action: add n... |
242 243 244 245 246 247 248 249 |
}; MODULE_AUTHOR("Alexander Duyck, <alexander.h.duyck@intel.com>"); MODULE_DESCRIPTION("SKB Editing"); MODULE_LICENSE("GPL"); static int __init skbedit_init_module(void) { |
ddf97ccdd net_sched: add ne... |
250 |
return tcf_register_action(&act_skbedit_ops, &skbedit_net_ops); |
ca9b0e27e pkt_action: add n... |
251 252 253 254 |
} static void __exit skbedit_cleanup_module(void) { |
ddf97ccdd net_sched: add ne... |
255 |
tcf_unregister_action(&act_skbedit_ops, &skbedit_net_ops); |
ca9b0e27e pkt_action: add n... |
256 257 258 259 |
} module_init(skbedit_init_module); module_exit(skbedit_cleanup_module); |