Blame view

net/sched/act_simple.c 6.43 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
2
  /*
0c6965dd3   Jiri Pirko   sched: fix act fi...
3
   * net/sched/act_simple.c	Simple example of an action
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
4
   *
fa1b1cff3   Jamal Hadi Salim   net_cls_act: Make...
5
   * Authors:	Jamal Hadi Salim (2005-8)
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
6
   */
cbdbf00aa   David S. Miller   [PKT_SCHED]: Elim...
7
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
8
  #include <linux/slab.h>
cbdbf00aa   David S. Miller   [PKT_SCHED]: Elim...
9
  #include <linux/init.h>
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
10
  #include <linux/kernel.h>
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
11
12
  #include <linux/skbuff.h>
  #include <linux/rtnetlink.h>
dc5fc579b   Arnaldo Carvalho de Melo   [NETLINK]: Use nl...
13
  #include <net/netlink.h>
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
14
  #include <net/pkt_sched.h>
4b006b0c1   Davide Caratti   net/sched: act_si...
15
  #include <net/pkt_cls.h>
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
16

db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
17
18
  #include <linux/tc_act/tc_defact.h>
  #include <net/tc_act/tc_defact.h>
c7d03a00b   Alexey Dobriyan   netns: make struc...
19
  static unsigned int simp_net_id;
a85a970af   WANG Cong   net_sched: move t...
20
  static struct tc_action_ops act_simp_ops;
ddf97ccdd   WANG Cong   net_sched: add ne...
21

fa1b1cff3   Jamal Hadi Salim   net_cls_act: Make...
22
  #define SIMP_MAX_DATA	32
798de374e   Jamal Hadi Salim   net: sched: act_s...
23
24
  static int tcf_simp_act(struct sk_buff *skb, const struct tc_action *a,
  			struct tcf_result *res)
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
25
  {
a85a970af   WANG Cong   net_sched: move t...
26
  	struct tcf_defact *d = to_defact(a);
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
27

e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
28
  	spin_lock(&d->tcf_lock);
9c4a4e488   Jamal Hadi Salim   net sched: action...
29
  	tcf_lastuse_update(&d->tcf_tm);
bfe0d0298   Eric Dumazet   net_sched: factor...
30
  	bstats_update(&d->tcf_bstats, skb);
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
31

10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
32
33
34
  	/* print policy string followed by _ then packet count
  	 * Example if this was the 3rd packet and the string was "hello"
  	 * then it would look like "hello_3" (without quotes)
cc7ec456f   Eric Dumazet   net_sched: cleanups
35
  	 */
d0083d98f   Eric Dumazet   net_sched: extend...
36
37
  	pr_info("simple: %s_%llu
  ",
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
38
39
40
41
  	       (char *)d->tcfd_defdata, d->tcf_bstats.packets);
  	spin_unlock(&d->tcf_lock);
  	return d->tcf_action;
  }
9a63b255d   Cong Wang   net_sched: remove...
42
  static void tcf_simp_release(struct tc_action *a)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
43
  {
86062033f   WANG Cong   net_sched: act: h...
44
  	struct tcf_defact *d = to_defact(a);
a5b5c958f   WANG Cong   net_sched: act: r...
45
  	kfree(d->tcfd_defdata);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
46
  }
8d499533e   Davide Caratti   net/sched: act_si...
47
  static int alloc_defdata(struct tcf_defact *d, const struct nlattr *defdata)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
48
  {
0eff683f7   Dan Carpenter   net/sched: potent...
49
  	d->tcfd_defdata = kzalloc(SIMP_MAX_DATA, GFP_KERNEL);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
50
51
  	if (unlikely(!d->tcfd_defdata))
  		return -ENOMEM;
8d499533e   Davide Caratti   net/sched: act_si...
52
  	nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
53
54
  	return 0;
  }
4b006b0c1   Davide Caratti   net/sched: act_si...
55
56
57
  static int reset_policy(struct tc_action *a, const struct nlattr *defdata,
  			struct tc_defact *p, struct tcf_proto *tp,
  			struct netlink_ext_ack *extack)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
58
  {
4b006b0c1   Davide Caratti   net/sched: act_si...
59
60
61
62
63
64
65
66
  	struct tcf_chain *goto_ch = NULL;
  	struct tcf_defact *d;
  	int err;
  
  	err = tcf_action_check_ctrlact(p->action, tp, &goto_ch, extack);
  	if (err < 0)
  		return err;
  	d = to_defact(a);
9d1045ad6   Jamal Hadi Salim   net_cls_act: act_...
67
  	spin_lock_bh(&d->tcf_lock);
4b006b0c1   Davide Caratti   net/sched: act_si...
68
  	goto_ch = tcf_action_set_ctrlact(a, p->action, goto_ch);
9d1045ad6   Jamal Hadi Salim   net_cls_act: act_...
69
  	memset(d->tcfd_defdata, 0, SIMP_MAX_DATA);
8d499533e   Davide Caratti   net/sched: act_si...
70
  	nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
9d1045ad6   Jamal Hadi Salim   net_cls_act: act_...
71
  	spin_unlock_bh(&d->tcf_lock);
4b006b0c1   Davide Caratti   net/sched: act_si...
72
73
74
  	if (goto_ch)
  		tcf_chain_put_by_act(goto_ch);
  	return 0;
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
75
  }
53b2bf3f8   Patrick McHardy   [NET_SCHED]: Use ...
76
77
  static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = {
  	[TCA_DEF_PARMS]	= { .len = sizeof(struct tc_defact) },
fa1b1cff3   Jamal Hadi Salim   net_cls_act: Make...
78
  	[TCA_DEF_DATA]	= { .type = NLA_STRING, .len = SIMP_MAX_DATA },
53b2bf3f8   Patrick McHardy   [NET_SCHED]: Use ...
79
  };
c1b52739e   Benjamin LaHaise   pkt_sched: namesp...
80
  static int tcf_simp_init(struct net *net, struct nlattr *nla,
a85a970af   WANG Cong   net_sched: move t...
81
  			 struct nlattr *est, struct tc_action **a,
789871bb2   Vlad Buslov   net: sched: imple...
82
  			 int ovr, int bind, bool rtnl_held,
abbb0d336   Vlad Buslov   net: sched: exten...
83
84
  			 struct tcf_proto *tp, u32 flags,
  			 struct netlink_ext_ack *extack)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
85
  {
ddf97ccdd   WANG Cong   net_sched: add ne...
86
  	struct tc_action_net *tn = net_generic(net, simp_net_id);
7ba699c60   Patrick McHardy   [NET_SCHED]: Conv...
87
  	struct nlattr *tb[TCA_DEF_MAX + 1];
4b006b0c1   Davide Caratti   net/sched: act_si...
88
  	struct tcf_chain *goto_ch = NULL;
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
89
90
  	struct tc_defact *parm;
  	struct tcf_defact *d;
b2313077e   WANG Cong   net_sched: make t...
91
92
  	bool exists = false;
  	int ret = 0, err;
7be8ef2cd   Dmytro Linkin   net: sched: use t...
93
  	u32 index;
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
94

cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
95
  	if (nla == NULL)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
96
  		return -EINVAL;
8cb081746   Johannes Berg   netlink: make val...
97
98
  	err = nla_parse_nested_deprecated(tb, TCA_DEF_MAX, nla, simple_policy,
  					  NULL);
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
99
100
  	if (err < 0)
  		return err;
53b2bf3f8   Patrick McHardy   [NET_SCHED]: Use ...
101
  	if (tb[TCA_DEF_PARMS] == NULL)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
102
  		return -EINVAL;
fa1b1cff3   Jamal Hadi Salim   net_cls_act: Make...
103
  	parm = nla_data(tb[TCA_DEF_PARMS]);
7be8ef2cd   Dmytro Linkin   net: sched: use t...
104
105
  	index = parm->index;
  	err = tcf_idr_check_alloc(tn, &index, a, bind);
0190c1d45   Vlad Buslov   net: sched: atomi...
106
107
108
  	if (err < 0)
  		return err;
  	exists = err;
0e5538ab2   Jamal Hadi Salim   net sched: simple...
109
110
111
112
113
  	if (exists && bind)
  		return 0;
  
  	if (tb[TCA_DEF_DATA] == NULL) {
  		if (exists)
65a206c01   Chris Mi   net/sched: Change...
114
  			tcf_idr_release(*a, bind);
0190c1d45   Vlad Buslov   net: sched: atomi...
115
  		else
7be8ef2cd   Dmytro Linkin   net: sched: use t...
116
  			tcf_idr_cleanup(tn, index);
0e5538ab2   Jamal Hadi Salim   net sched: simple...
117
118
  		return -EINVAL;
  	}
0e5538ab2   Jamal Hadi Salim   net sched: simple...
119
  	if (!exists) {
7be8ef2cd   Dmytro Linkin   net: sched: use t...
120
  		ret = tcf_idr_create(tn, index, est, a,
e38226786   Vlad Buslov   net: sched: updat...
121
  				     &act_simp_ops, bind, false, 0);
0190c1d45   Vlad Buslov   net: sched: atomi...
122
  		if (ret) {
7be8ef2cd   Dmytro Linkin   net: sched: use t...
123
  			tcf_idr_cleanup(tn, index);
86062033f   WANG Cong   net_sched: act: h...
124
  			return ret;
0190c1d45   Vlad Buslov   net: sched: atomi...
125
  		}
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
126

a85a970af   WANG Cong   net_sched: move t...
127
  		d = to_defact(*a);
4b006b0c1   Davide Caratti   net/sched: act_si...
128
129
130
131
132
133
134
135
136
137
  		err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch,
  					       extack);
  		if (err < 0)
  			goto release_idr;
  
  		err = alloc_defdata(d, tb[TCA_DEF_DATA]);
  		if (err < 0)
  			goto put_chain;
  
  		tcf_action_set_ctrlact(*a, parm->action, goto_ch);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
138
139
  		ret = ACT_P_CREATED;
  	} else {
4e8ddd7f1   Vlad Buslov   net: sched: don't...
140
  		if (!ovr) {
4b006b0c1   Davide Caratti   net/sched: act_si...
141
142
  			err = -EEXIST;
  			goto release_idr;
4e8ddd7f1   Vlad Buslov   net: sched: don't...
143
  		}
1a29321ed   Jamal Hadi Salim   net_sched: act: D...
144

4b006b0c1   Davide Caratti   net/sched: act_si...
145
146
147
  		err = reset_policy(*a, tb[TCA_DEF_DATA], parm, tp, extack);
  		if (err)
  			goto release_idr;
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
148
  	}
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
149
  	if (ret == ACT_P_CREATED)
65a206c01   Chris Mi   net/sched: Change...
150
  		tcf_idr_insert(tn, *a);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
151
  	return ret;
4b006b0c1   Davide Caratti   net/sched: act_si...
152
153
154
155
156
157
  put_chain:
  	if (goto_ch)
  		tcf_chain_put_by_act(goto_ch);
  release_idr:
  	tcf_idr_release(*a, bind);
  	return err;
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
158
  }
cc7ec456f   Eric Dumazet   net_sched: cleanups
159
160
  static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
  			 int bind, int ref)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
161
  {
27a884dc3   Arnaldo Carvalho de Melo   [SK_BUFF]: Conver...
162
  	unsigned char *b = skb_tail_pointer(skb);
a85a970af   WANG Cong   net_sched: move t...
163
  	struct tcf_defact *d = to_defact(a);
1c40be12f   Eric Dumazet   net sched: fix so...
164
165
  	struct tc_defact opt = {
  		.index   = d->tcf_index,
036bb4432   Vlad Buslov   net: sched: chang...
166
167
  		.refcnt  = refcount_read(&d->tcf_refcnt) - ref,
  		.bindcnt = atomic_read(&d->tcf_bindcnt) - bind,
1c40be12f   Eric Dumazet   net sched: fix so...
168
  	};
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
169
  	struct tcf_t t;
5e48180ed   Vlad Buslov   net: sched: act_s...
170
171
  	spin_lock_bh(&d->tcf_lock);
  	opt.action = d->tcf_action;
1b34ec43c   David S. Miller   pkt_sched: Stop u...
172
173
174
  	if (nla_put(skb, TCA_DEF_PARMS, sizeof(opt), &opt) ||
  	    nla_put_string(skb, TCA_DEF_DATA, d->tcfd_defdata))
  		goto nla_put_failure;
48d8ee169   Jamal Hadi Salim   net sched actions...
175
176
  
  	tcf_tm_dump(&t, &d->tcf_tm);
9854518ea   Nicolas Dichtel   sched: align nlat...
177
  	if (nla_put_64bit(skb, TCA_DEF_TM, sizeof(t), &t, TCA_DEF_PAD))
1b34ec43c   David S. Miller   pkt_sched: Stop u...
178
  		goto nla_put_failure;
5e48180ed   Vlad Buslov   net: sched: act_s...
179
  	spin_unlock_bh(&d->tcf_lock);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
180
  	return skb->len;
7ba699c60   Patrick McHardy   [NET_SCHED]: Conv...
181
  nla_put_failure:
5e48180ed   Vlad Buslov   net: sched: act_s...
182
  	spin_unlock_bh(&d->tcf_lock);
dc5fc579b   Arnaldo Carvalho de Melo   [NETLINK]: Use nl...
183
  	nlmsg_trim(skb, b);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
184
  	return -1;
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
185
  }
ddf97ccdd   WANG Cong   net_sched: add ne...
186
187
  static int tcf_simp_walker(struct net *net, struct sk_buff *skb,
  			   struct netlink_callback *cb, int type,
417801055   Alexander Aring   net: sched: act: ...
188
189
  			   const struct tc_action_ops *ops,
  			   struct netlink_ext_ack *extack)
ddf97ccdd   WANG Cong   net_sched: add ne...
190
191
  {
  	struct tc_action_net *tn = net_generic(net, simp_net_id);
b36201455   Alexander Aring   net: sched: act: ...
192
  	return tcf_generic_walker(tn, skb, cb, type, ops, extack);
ddf97ccdd   WANG Cong   net_sched: add ne...
193
  }
f061b48c1   Cong Wang   Revert "net: sche...
194
  static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index)
ddf97ccdd   WANG Cong   net_sched: add ne...
195
196
  {
  	struct tc_action_net *tn = net_generic(net, simp_net_id);
65a206c01   Chris Mi   net/sched: Change...
197
  	return tcf_idr_search(tn, a, index);
ddf97ccdd   WANG Cong   net_sched: add ne...
198
  }
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
199
  static struct tc_action_ops act_simp_ops = {
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
200
  	.kind		=	"simple",
eddd2cf19   Eli Cohen   net: Change TCA_A...
201
  	.id		=	TCA_ID_SIMP,
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
202
  	.owner		=	THIS_MODULE,
798de374e   Jamal Hadi Salim   net: sched: act_s...
203
  	.act		=	tcf_simp_act,
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
204
  	.dump		=	tcf_simp_dump,
86062033f   WANG Cong   net_sched: act: h...
205
  	.cleanup	=	tcf_simp_release,
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
206
  	.init		=	tcf_simp_init,
ddf97ccdd   WANG Cong   net_sched: add ne...
207
208
  	.walk		=	tcf_simp_walker,
  	.lookup		=	tcf_simp_search,
a85a970af   WANG Cong   net_sched: move t...
209
  	.size		=	sizeof(struct tcf_defact),
ddf97ccdd   WANG Cong   net_sched: add ne...
210
211
212
213
214
  };
  
  static __net_init int simp_init_net(struct net *net)
  {
  	struct tc_action_net *tn = net_generic(net, simp_net_id);
981471bd3   Cong Wang   net_sched: fix a ...
215
  	return tc_action_net_init(net, tn, &act_simp_ops);
ddf97ccdd   WANG Cong   net_sched: add ne...
216
  }
039af9c66   Cong Wang   net_sched: switch...
217
  static void __net_exit simp_exit_net(struct list_head *net_list)
ddf97ccdd   WANG Cong   net_sched: add ne...
218
  {
039af9c66   Cong Wang   net_sched: switch...
219
  	tc_action_net_exit(net_list, simp_net_id);
ddf97ccdd   WANG Cong   net_sched: add ne...
220
221
222
223
  }
  
  static struct pernet_operations simp_net_ops = {
  	.init = simp_init_net,
039af9c66   Cong Wang   net_sched: switch...
224
  	.exit_batch = simp_exit_net,
ddf97ccdd   WANG Cong   net_sched: add ne...
225
226
  	.id   = &simp_net_id,
  	.size = sizeof(struct tc_action_net),
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
227
228
229
230
231
232
233
234
  };
  
  MODULE_AUTHOR("Jamal Hadi Salim(2005)");
  MODULE_DESCRIPTION("Simple example action");
  MODULE_LICENSE("GPL");
  
  static int __init simp_init_module(void)
  {
ddf97ccdd   WANG Cong   net_sched: add ne...
235
  	int ret = tcf_register_action(&act_simp_ops, &simp_net_ops);
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
236
  	if (!ret)
6ff9c3644   stephen hemminger   net sched: printk...
237
238
  		pr_info("Simple TC action Loaded
  ");
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
239
240
241
242
243
  	return ret;
  }
  
  static void __exit simp_cleanup_module(void)
  {
ddf97ccdd   WANG Cong   net_sched: add ne...
244
  	tcf_unregister_action(&act_simp_ops, &simp_net_ops);
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
245
246
247
248
  }
  
  module_init(simp_init_module);
  module_exit(simp_cleanup_module);