Blame view
net/sched/act_gact.c
7.43 KB
2874c5fd2 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4c Linux-2.6.12-rc2 |
2 |
/* |
0c6965dd3 sched: fix act fi... |
3 |
* net/sched/act_gact.c Generic actions |
1da177e4c Linux-2.6.12-rc2 |
4 |
* |
1da177e4c Linux-2.6.12-rc2 |
5 |
* copyright Jamal Hadi Salim (2002-4) |
1da177e4c Linux-2.6.12-rc2 |
6 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
7 8 |
#include <linux/types.h> #include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
9 |
#include <linux/string.h> |
1da177e4c Linux-2.6.12-rc2 |
10 |
#include <linux/errno.h> |
1da177e4c Linux-2.6.12-rc2 |
11 12 13 14 |
#include <linux/skbuff.h> #include <linux/rtnetlink.h> #include <linux/module.h> #include <linux/init.h> |
dc5fc579b [NETLINK]: Use nl... |
15 |
#include <net/netlink.h> |
1da177e4c Linux-2.6.12-rc2 |
16 |
#include <net/pkt_sched.h> |
0da2dbd60 net/sched: act_ga... |
17 |
#include <net/pkt_cls.h> |
1da177e4c Linux-2.6.12-rc2 |
18 19 |
#include <linux/tc_act/tc_gact.h> #include <net/tc_act/tc_gact.h> |
c7d03a00b netns: make struc... |
20 |
static unsigned int gact_net_id; |
a85a970af net_sched: move t... |
21 |
static struct tc_action_ops act_gact_ops; |
ddf97ccdd net_sched: add ne... |
22 |
|
1da177e4c Linux-2.6.12-rc2 |
23 |
#ifdef CONFIG_GACT_PROB |
e9ce1cd3c [PKT_SCHED]: Kill... |
24 |
static int gact_net_rand(struct tcf_gact *gact) |
1da177e4c Linux-2.6.12-rc2 |
25 |
{ |
cef5ecf96 net_sched: act_ga... |
26 27 |
smp_rmb(); /* coupled with smp_wmb() in tcf_gact_init() */ if (prandom_u32() % gact->tcfg_pval) |
e9ce1cd3c [PKT_SCHED]: Kill... |
28 29 |
return gact->tcf_action; return gact->tcfg_paction; |
1da177e4c Linux-2.6.12-rc2 |
30 |
} |
e9ce1cd3c [PKT_SCHED]: Kill... |
31 |
static int gact_determ(struct tcf_gact *gact) |
1da177e4c Linux-2.6.12-rc2 |
32 |
{ |
cc6510a95 net_sched: act_ga... |
33 |
u32 pack = atomic_inc_return(&gact->packets); |
cef5ecf96 net_sched: act_ga... |
34 |
smp_rmb(); /* coupled with smp_wmb() in tcf_gact_init() */ |
cc6510a95 net_sched: act_ga... |
35 |
if (pack % gact->tcfg_pval) |
e9ce1cd3c [PKT_SCHED]: Kill... |
36 37 |
return gact->tcf_action; return gact->tcfg_paction; |
1da177e4c Linux-2.6.12-rc2 |
38 |
} |
e9ce1cd3c [PKT_SCHED]: Kill... |
39 |
typedef int (*g_rand)(struct tcf_gact *gact); |
cc7ec456f net_sched: cleanups |
40 |
static g_rand gact_rand[MAX_RAND] = { NULL, gact_net_rand, gact_determ }; |
e9ce1cd3c [PKT_SCHED]: Kill... |
41 |
#endif /* CONFIG_GACT_PROB */ |
1da177e4c Linux-2.6.12-rc2 |
42 |
|
53b2bf3f8 [NET_SCHED]: Use ... |
43 44 45 46 |
static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = { [TCA_GACT_PARMS] = { .len = sizeof(struct tc_gact) }, [TCA_GACT_PROB] = { .len = sizeof(struct tc_gact_p) }, }; |
c1b52739e pkt_sched: namesp... |
47 |
static int tcf_gact_init(struct net *net, struct nlattr *nla, |
a85a970af net_sched: move t... |
48 |
struct nlattr *est, struct tc_action **a, |
789871bb2 net: sched: imple... |
49 |
int ovr, int bind, bool rtnl_held, |
abbb0d336 net: sched: exten... |
50 51 |
struct tcf_proto *tp, u32 flags, struct netlink_ext_ack *extack) |
1da177e4c Linux-2.6.12-rc2 |
52 |
{ |
ddf97ccdd net_sched: add ne... |
53 |
struct tc_action_net *tn = net_generic(net, gact_net_id); |
7ba699c60 [NET_SCHED]: Conv... |
54 |
struct nlattr *tb[TCA_GACT_MAX + 1]; |
0da2dbd60 net/sched: act_ga... |
55 |
struct tcf_chain *goto_ch = NULL; |
1da177e4c Linux-2.6.12-rc2 |
56 |
struct tc_gact *parm; |
e9ce1cd3c [PKT_SCHED]: Kill... |
57 |
struct tcf_gact *gact; |
1da177e4c Linux-2.6.12-rc2 |
58 |
int ret = 0; |
7be8ef2cd net: sched: use t... |
59 |
u32 index; |
cee63723b [NET_SCHED]: Prop... |
60 |
int err; |
696ecdc10 net_sched: gact: ... |
61 62 63 |
#ifdef CONFIG_GACT_PROB struct tc_gact_p *p_parm = NULL; #endif |
1da177e4c Linux-2.6.12-rc2 |
64 |
|
cee63723b [NET_SCHED]: Prop... |
65 |
if (nla == NULL) |
1da177e4c Linux-2.6.12-rc2 |
66 |
return -EINVAL; |
8cb081746 netlink: make val... |
67 68 |
err = nla_parse_nested_deprecated(tb, TCA_GACT_MAX, nla, gact_policy, NULL); |
cee63723b [NET_SCHED]: Prop... |
69 70 |
if (err < 0) return err; |
53b2bf3f8 [NET_SCHED]: Use ... |
71 |
if (tb[TCA_GACT_PARMS] == NULL) |
1da177e4c Linux-2.6.12-rc2 |
72 |
return -EINVAL; |
7ba699c60 [NET_SCHED]: Conv... |
73 |
parm = nla_data(tb[TCA_GACT_PARMS]); |
7be8ef2cd net: sched: use t... |
74 |
index = parm->index; |
1da177e4c Linux-2.6.12-rc2 |
75 |
|
53b2bf3f8 [NET_SCHED]: Use ... |
76 |
#ifndef CONFIG_GACT_PROB |
7ba699c60 [NET_SCHED]: Conv... |
77 |
if (tb[TCA_GACT_PROB] != NULL) |
1da177e4c Linux-2.6.12-rc2 |
78 |
return -EOPNOTSUPP; |
696ecdc10 net_sched: gact: ... |
79 80 81 82 83 |
#else if (tb[TCA_GACT_PROB]) { p_parm = nla_data(tb[TCA_GACT_PROB]); if (p_parm->ptype >= MAX_RAND) return -EINVAL; |
9469f375a net/sched: act_ga... |
84 85 86 87 88 |
if (TC_ACT_EXT_CMP(p_parm->paction, TC_ACT_GOTO_CHAIN)) { NL_SET_ERR_MSG(extack, "goto chain not allowed on fallback"); return -EINVAL; } |
696ecdc10 net_sched: gact: ... |
89 |
} |
1da177e4c Linux-2.6.12-rc2 |
90 |
#endif |
7be8ef2cd net: sched: use t... |
91 |
err = tcf_idr_check_alloc(tn, &index, a, bind); |
0190c1d45 net: sched: atomi... |
92 |
if (!err) { |
e38226786 net: sched: updat... |
93 94 |
ret = tcf_idr_create_from_flags(tn, index, est, a, &act_gact_ops, bind, flags); |
0190c1d45 net: sched: atomi... |
95 |
if (ret) { |
7be8ef2cd net: sched: use t... |
96 |
tcf_idr_cleanup(tn, index); |
86062033f net_sched: act: h... |
97 |
return ret; |
0190c1d45 net: sched: atomi... |
98 |
} |
1da177e4c Linux-2.6.12-rc2 |
99 |
ret = ACT_P_CREATED; |
0190c1d45 net: sched: atomi... |
100 |
} else if (err > 0) { |
1a29321ed net_sched: act: D... |
101 102 |
if (bind)/* dont override defaults */ return 0; |
4e8ddd7f1 net: sched: don't... |
103 104 |
if (!ovr) { tcf_idr_release(*a, bind); |
1da177e4c Linux-2.6.12-rc2 |
105 |
return -EEXIST; |
4e8ddd7f1 net: sched: don't... |
106 |
} |
0190c1d45 net: sched: atomi... |
107 108 |
} else { return err; |
1da177e4c Linux-2.6.12-rc2 |
109 |
} |
0da2dbd60 net/sched: act_ga... |
110 111 112 |
err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); if (err < 0) goto release_idr; |
a85a970af net_sched: move t... |
113 |
gact = to_gact(*a); |
e9ce1cd3c [PKT_SCHED]: Kill... |
114 |
|
653cd284a net: sched: alway... |
115 |
spin_lock_bh(&gact->tcf_lock); |
0da2dbd60 net/sched: act_ga... |
116 |
goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
1da177e4c Linux-2.6.12-rc2 |
117 |
#ifdef CONFIG_GACT_PROB |
696ecdc10 net_sched: gact: ... |
118 |
if (p_parm) { |
e9ce1cd3c [PKT_SCHED]: Kill... |
119 |
gact->tcfg_paction = p_parm->paction; |
cef5ecf96 net_sched: act_ga... |
120 121 122 123 124 |
gact->tcfg_pval = max_t(u16, 1, p_parm->pval); /* Make sure tcfg_pval is written before tcfg_ptype * coupled with smp_rmb() in gact_net_rand() & gact_determ() */ smp_wmb(); |
e9ce1cd3c [PKT_SCHED]: Kill... |
125 |
gact->tcfg_ptype = p_parm->ptype; |
1da177e4c Linux-2.6.12-rc2 |
126 127 |
} #endif |
653cd284a net: sched: alway... |
128 |
spin_unlock_bh(&gact->tcf_lock); |
e8917f437 net: sched: act_g... |
129 |
|
0da2dbd60 net/sched: act_ga... |
130 131 |
if (goto_ch) tcf_chain_put_by_act(goto_ch); |
1da177e4c Linux-2.6.12-rc2 |
132 |
return ret; |
0da2dbd60 net/sched: act_ga... |
133 134 135 |
release_idr: tcf_idr_release(*a, bind); return err; |
1da177e4c Linux-2.6.12-rc2 |
136 |
} |
1740005e2 net: sched: act_g... |
137 138 |
static int tcf_gact_act(struct sk_buff *skb, const struct tc_action *a, struct tcf_result *res) |
1da177e4c Linux-2.6.12-rc2 |
139 |
{ |
a85a970af net_sched: move t... |
140 |
struct tcf_gact *gact = to_gact(a); |
56e5d1ca1 net_sched: act_ga... |
141 |
int action = READ_ONCE(gact->tcf_action); |
1da177e4c Linux-2.6.12-rc2 |
142 |
|
1da177e4c Linux-2.6.12-rc2 |
143 |
#ifdef CONFIG_GACT_PROB |
8f2ae965b net_sched: act_ga... |
144 145 146 147 148 149 |
{ u32 ptype = READ_ONCE(gact->tcfg_ptype); if (ptype) action = gact_rand[ptype](gact); } |
1da177e4c Linux-2.6.12-rc2 |
150 |
#endif |
5e1ad95b6 net: sched: extra... |
151 |
tcf_action_update_bstats(&gact->common, skb); |
1da177e4c Linux-2.6.12-rc2 |
152 |
if (action == TC_ACT_SHOT) |
26b537a88 net: sched: extra... |
153 |
tcf_action_inc_drop_qstats(&gact->common); |
56e5d1ca1 net_sched: act_ga... |
154 155 |
tcf_lastuse_update(&gact->tcf_tm); |
1da177e4c Linux-2.6.12-rc2 |
156 157 158 |
return action; } |
4b61d3e8d net: qos offload ... |
159 160 |
static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u64 packets, u64 drops, u64 lastuse, bool hw) |
9fea47d93 net/sched: act_ga... |
161 |
{ |
a85a970af net_sched: move t... |
162 |
struct tcf_gact *gact = to_gact(a); |
9fea47d93 net/sched: act_ga... |
163 164 |
int action = READ_ONCE(gact->tcf_action); struct tcf_t *tm = &gact->tcf_tm; |
4b61d3e8d net: qos offload ... |
165 166 |
tcf_action_update_stats(a, bytes, packets, action == TC_ACT_SHOT ? packets : drops, hw); |
3bb23421a net/sched: Fix up... |
167 |
tm->lastuse = max_t(u64, tm->lastuse, lastuse); |
9fea47d93 net/sched: act_ga... |
168 |
} |
0b0f43fe2 net sched: indent... |
169 170 |
static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) |
1da177e4c Linux-2.6.12-rc2 |
171 |
{ |
27a884dc3 [SK_BUFF]: Conver... |
172 |
unsigned char *b = skb_tail_pointer(skb); |
a85a970af net_sched: move t... |
173 |
struct tcf_gact *gact = to_gact(a); |
1c40be12f net sched: fix so... |
174 175 |
struct tc_gact opt = { .index = gact->tcf_index, |
036bb4432 net: sched: chang... |
176 177 |
.refcnt = refcount_read(&gact->tcf_refcnt) - ref, .bindcnt = atomic_read(&gact->tcf_bindcnt) - bind, |
1c40be12f net sched: fix so... |
178 |
}; |
1da177e4c Linux-2.6.12-rc2 |
179 |
struct tcf_t t; |
653cd284a net: sched: alway... |
180 |
spin_lock_bh(&gact->tcf_lock); |
e8917f437 net: sched: act_g... |
181 |
opt.action = gact->tcf_action; |
1b34ec43c pkt_sched: Stop u... |
182 183 |
if (nla_put(skb, TCA_GACT_PARMS, sizeof(opt), &opt)) goto nla_put_failure; |
1da177e4c Linux-2.6.12-rc2 |
184 |
#ifdef CONFIG_GACT_PROB |
e9ce1cd3c [PKT_SCHED]: Kill... |
185 |
if (gact->tcfg_ptype) { |
1c40be12f net sched: fix so... |
186 187 188 189 190 |
struct tc_gact_p p_opt = { .paction = gact->tcfg_paction, .pval = gact->tcfg_pval, .ptype = gact->tcfg_ptype, }; |
1b34ec43c pkt_sched: Stop u... |
191 192 |
if (nla_put(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt)) goto nla_put_failure; |
1da177e4c Linux-2.6.12-rc2 |
193 194 |
} #endif |
48d8ee169 net sched actions... |
195 |
tcf_tm_dump(&t, &gact->tcf_tm); |
9854518ea sched: align nlat... |
196 |
if (nla_put_64bit(skb, TCA_GACT_TM, sizeof(t), &t, TCA_GACT_PAD)) |
1b34ec43c pkt_sched: Stop u... |
197 |
goto nla_put_failure; |
653cd284a net: sched: alway... |
198 |
spin_unlock_bh(&gact->tcf_lock); |
e8917f437 net: sched: act_g... |
199 |
|
1da177e4c Linux-2.6.12-rc2 |
200 |
return skb->len; |
7ba699c60 [NET_SCHED]: Conv... |
201 |
nla_put_failure: |
653cd284a net: sched: alway... |
202 |
spin_unlock_bh(&gact->tcf_lock); |
dc5fc579b [NETLINK]: Use nl... |
203 |
nlmsg_trim(skb, b); |
1da177e4c Linux-2.6.12-rc2 |
204 205 |
return -1; } |
ddf97ccdd net_sched: add ne... |
206 207 |
static int tcf_gact_walker(struct net *net, struct sk_buff *skb, struct netlink_callback *cb, int type, |
417801055 net: sched: act: ... |
208 209 |
const struct tc_action_ops *ops, struct netlink_ext_ack *extack) |
ddf97ccdd net_sched: add ne... |
210 211 |
{ struct tc_action_net *tn = net_generic(net, gact_net_id); |
b36201455 net: sched: act: ... |
212 |
return tcf_generic_walker(tn, skb, cb, type, ops, extack); |
ddf97ccdd net_sched: add ne... |
213 |
} |
f061b48c1 Revert "net: sche... |
214 |
static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index) |
ddf97ccdd net_sched: add ne... |
215 216 |
{ struct tc_action_net *tn = net_generic(net, gact_net_id); |
65a206c01 net/sched: Change... |
217 |
return tcf_idr_search(tn, a, index); |
ddf97ccdd net_sched: add ne... |
218 |
} |
9c5c9c573 net sched actions... |
219 220 221 222 223 224 225 226 227 228 229 230 |
static size_t tcf_gact_get_fill_size(const struct tc_action *act) { size_t sz = nla_total_size(sizeof(struct tc_gact)); /* TCA_GACT_PARMS */ #ifdef CONFIG_GACT_PROB if (to_gact(act)->tcfg_ptype) /* TCA_GACT_PROB */ sz += nla_total_size(sizeof(struct tc_gact_p)); #endif return sz; } |
1da177e4c Linux-2.6.12-rc2 |
231 232 |
static struct tc_action_ops act_gact_ops = { .kind = "gact", |
eddd2cf19 net: Change TCA_A... |
233 |
.id = TCA_ID_GACT, |
1da177e4c Linux-2.6.12-rc2 |
234 |
.owner = THIS_MODULE, |
1740005e2 net: sched: act_g... |
235 |
.act = tcf_gact_act, |
9fea47d93 net/sched: act_ga... |
236 |
.stats_update = tcf_gact_stats_update, |
1da177e4c Linux-2.6.12-rc2 |
237 |
.dump = tcf_gact_dump, |
1da177e4c Linux-2.6.12-rc2 |
238 |
.init = tcf_gact_init, |
ddf97ccdd net_sched: add ne... |
239 240 |
.walk = tcf_gact_walker, .lookup = tcf_gact_search, |
9c5c9c573 net sched actions... |
241 |
.get_fill_size = tcf_gact_get_fill_size, |
a85a970af net_sched: move t... |
242 |
.size = sizeof(struct tcf_gact), |
ddf97ccdd net_sched: add ne... |
243 244 245 246 247 |
}; static __net_init int gact_init_net(struct net *net) { struct tc_action_net *tn = net_generic(net, gact_net_id); |
981471bd3 net_sched: fix a ... |
248 |
return tc_action_net_init(net, tn, &act_gact_ops); |
ddf97ccdd net_sched: add ne... |
249 |
} |
039af9c66 net_sched: switch... |
250 |
static void __net_exit gact_exit_net(struct list_head *net_list) |
ddf97ccdd net_sched: add ne... |
251 |
{ |
039af9c66 net_sched: switch... |
252 |
tc_action_net_exit(net_list, gact_net_id); |
ddf97ccdd net_sched: add ne... |
253 254 255 256 |
} static struct pernet_operations gact_net_ops = { .init = gact_init_net, |
039af9c66 net_sched: switch... |
257 |
.exit_batch = gact_exit_net, |
ddf97ccdd net_sched: add ne... |
258 259 |
.id = &gact_net_id, .size = sizeof(struct tc_action_net), |
1da177e4c Linux-2.6.12-rc2 |
260 261 262 263 264 |
}; MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); MODULE_DESCRIPTION("Generic Classifier actions"); MODULE_LICENSE("GPL"); |
e9ce1cd3c [PKT_SCHED]: Kill... |
265 |
static int __init gact_init_module(void) |
1da177e4c Linux-2.6.12-rc2 |
266 267 |
{ #ifdef CONFIG_GACT_PROB |
cc7ec456f net_sched: cleanups |
268 269 |
pr_info("GACT probability on "); |
1da177e4c Linux-2.6.12-rc2 |
270 |
#else |
cc7ec456f net_sched: cleanups |
271 272 |
pr_info("GACT probability NOT on "); |
1da177e4c Linux-2.6.12-rc2 |
273 |
#endif |
ddf97ccdd net_sched: add ne... |
274 275 |
return tcf_register_action(&act_gact_ops, &gact_net_ops); |
1da177e4c Linux-2.6.12-rc2 |
276 |
} |
e9ce1cd3c [PKT_SCHED]: Kill... |
277 |
static void __exit gact_cleanup_module(void) |
1da177e4c Linux-2.6.12-rc2 |
278 |
{ |
ddf97ccdd net_sched: add ne... |
279 |
tcf_unregister_action(&act_gact_ops, &gact_net_ops); |
1da177e4c Linux-2.6.12-rc2 |
280 281 282 283 |
} module_init(gact_init_module); module_exit(gact_cleanup_module); |