Blame view

net/sched/act_simple.c 5.14 KB
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
1
2
3
4
5
6
7
8
  /*
   * net/sched/simp.c	Simple example of an action
   *
   *		This program is free software; you can redistribute it and/or
   *		modify it under the terms of the GNU General Public License
   *		as published by the Free Software Foundation; either version
   *		2 of the License, or (at your option) any later version.
   *
fa1b1cff3   Jamal Hadi Salim   net_cls_act: Make...
9
   * Authors:	Jamal Hadi Salim (2005-8)
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
10
11
   *
   */
cbdbf00aa   David S. Miller   [PKT_SCHED]: Elim...
12
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
13
  #include <linux/slab.h>
cbdbf00aa   David S. Miller   [PKT_SCHED]: Elim...
14
  #include <linux/init.h>
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
15
  #include <linux/kernel.h>
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
16
17
  #include <linux/skbuff.h>
  #include <linux/rtnetlink.h>
dc5fc579b   Arnaldo Carvalho de Melo   [NETLINK]: Use nl...
18
  #include <net/netlink.h>
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
19
20
21
  #include <net/pkt_sched.h>
  
  #define TCA_ACT_SIMP 22
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
22
23
  #include <linux/tc_act/tc_defact.h>
  #include <net/tc_act/tc_defact.h>
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
24
25
26
  #define SIMP_TAB_MASK     7
  static struct tcf_common *tcf_simp_ht[SIMP_TAB_MASK + 1];
  static u32 simp_idx_gen;
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
27
  static DEFINE_RWLOCK(simp_lock);
28a7b327b   Adrian Bunk   [PKT_SCHED] act_s...
28
  static struct tcf_hashinfo simp_hash_info = {
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
29
30
31
32
  	.htab	=	tcf_simp_ht,
  	.hmask	=	SIMP_TAB_MASK,
  	.lock	=	&simp_lock,
  };
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
33

fa1b1cff3   Jamal Hadi Salim   net_cls_act: Make...
34
  #define SIMP_MAX_DATA	32
dc7f9f6e8   Eric Dumazet   net: sched: const...
35
36
  static int tcf_simp(struct sk_buff *skb, const struct tc_action *a,
  		    struct tcf_result *res)
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
37
  {
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
38
  	struct tcf_defact *d = a->priv;
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
39

e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
40
41
  	spin_lock(&d->tcf_lock);
  	d->tcf_tm.lastuse = jiffies;
bfe0d0298   Eric Dumazet   net_sched: factor...
42
  	bstats_update(&d->tcf_bstats, skb);
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
43

10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
44
45
46
  	/* 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
47
  	 */
6ff9c3644   stephen hemminger   net sched: printk...
48
49
  	pr_info("simple: %s_%d
  ",
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  	       (char *)d->tcfd_defdata, d->tcf_bstats.packets);
  	spin_unlock(&d->tcf_lock);
  	return d->tcf_action;
  }
  
  static int tcf_simp_release(struct tcf_defact *d, int bind)
  {
  	int ret = 0;
  	if (d) {
  		if (bind)
  			d->tcf_bindcnt--;
  		d->tcf_refcnt--;
  		if (d->tcf_bindcnt <= 0 && d->tcf_refcnt <= 0) {
  			kfree(d->tcfd_defdata);
  			tcf_hash_destroy(&d->common, &simp_hash_info);
  			ret = 1;
  		}
  	}
  	return ret;
  }
fa1b1cff3   Jamal Hadi Salim   net_cls_act: Make...
70
  static int alloc_defdata(struct tcf_defact *d, char *defdata)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
71
  {
0eff683f7   Dan Carpenter   net/sched: potent...
72
  	d->tcfd_defdata = kzalloc(SIMP_MAX_DATA, GFP_KERNEL);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
73
74
  	if (unlikely(!d->tcfd_defdata))
  		return -ENOMEM;
0eff683f7   Dan Carpenter   net/sched: potent...
75
  	strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
76
77
  	return 0;
  }
9d1045ad6   Jamal Hadi Salim   net_cls_act: act_...
78
79
  static void reset_policy(struct tcf_defact *d, char *defdata,
  			 struct tc_defact *p)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
80
  {
9d1045ad6   Jamal Hadi Salim   net_cls_act: act_...
81
82
83
84
85
  	spin_lock_bh(&d->tcf_lock);
  	d->tcf_action = p->action;
  	memset(d->tcfd_defdata, 0, SIMP_MAX_DATA);
  	strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
  	spin_unlock_bh(&d->tcf_lock);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
86
  }
53b2bf3f8   Patrick McHardy   [NET_SCHED]: Use ...
87
88
  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...
89
  	[TCA_DEF_DATA]	= { .type = NLA_STRING, .len = SIMP_MAX_DATA },
53b2bf3f8   Patrick McHardy   [NET_SCHED]: Use ...
90
  };
7ba699c60   Patrick McHardy   [NET_SCHED]: Conv...
91
  static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
92
93
  			 struct tc_action *a, int ovr, int bind)
  {
7ba699c60   Patrick McHardy   [NET_SCHED]: Conv...
94
  	struct nlattr *tb[TCA_DEF_MAX + 1];
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
95
96
97
  	struct tc_defact *parm;
  	struct tcf_defact *d;
  	struct tcf_common *pc;
fa1b1cff3   Jamal Hadi Salim   net_cls_act: Make...
98
  	char *defdata;
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
99
  	int ret = 0, err;
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
100

cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
101
  	if (nla == NULL)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
102
  		return -EINVAL;
fa1b1cff3   Jamal Hadi Salim   net_cls_act: Make...
103
  	err = nla_parse_nested(tb, TCA_DEF_MAX, nla, simple_policy);
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
104
105
  	if (err < 0)
  		return err;
53b2bf3f8   Patrick McHardy   [NET_SCHED]: Use ...
106
  	if (tb[TCA_DEF_PARMS] == NULL)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
107
  		return -EINVAL;
fa1b1cff3   Jamal Hadi Salim   net_cls_act: Make...
108
  	if (tb[TCA_DEF_DATA] == NULL)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
109
  		return -EINVAL;
fa1b1cff3   Jamal Hadi Salim   net_cls_act: Make...
110
111
  	parm = nla_data(tb[TCA_DEF_PARMS]);
  	defdata = nla_data(tb[TCA_DEF_DATA]);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
112
113
114
115
116
  
  	pc = tcf_hash_check(parm->index, a, bind, &simp_hash_info);
  	if (!pc) {
  		pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind,
  				     &simp_idx_gen, &simp_hash_info);
0e991ec6a   Stephen Hemminger   tc: propogate err...
117
  		if (IS_ERR(pc))
cc7ec456f   Eric Dumazet   net_sched: cleanups
118
  			return PTR_ERR(pc);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
119
120
  
  		d = to_defact(pc);
fa1b1cff3   Jamal Hadi Salim   net_cls_act: Make...
121
  		ret = alloc_defdata(d, defdata);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
122
123
124
125
  		if (ret < 0) {
  			kfree(pc);
  			return ret;
  		}
9d1045ad6   Jamal Hadi Salim   net_cls_act: act_...
126
  		d->tcf_action = parm->action;
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
127
128
129
130
131
132
133
  		ret = ACT_P_CREATED;
  	} else {
  		d = to_defact(pc);
  		if (!ovr) {
  			tcf_simp_release(d, bind);
  			return -EEXIST;
  		}
9d1045ad6   Jamal Hadi Salim   net_cls_act: act_...
134
  		reset_policy(d, defdata, parm);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
135
  	}
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
136
137
138
139
  	if (ret == ACT_P_CREATED)
  		tcf_hash_insert(pc, &simp_hash_info);
  	return ret;
  }
cc7ec456f   Eric Dumazet   net_sched: cleanups
140
  static int tcf_simp_cleanup(struct tc_action *a, int bind)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
141
142
143
144
145
146
147
  {
  	struct tcf_defact *d = a->priv;
  
  	if (d)
  		return tcf_simp_release(d, bind);
  	return 0;
  }
cc7ec456f   Eric Dumazet   net_sched: cleanups
148
149
  static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
  			 int bind, int ref)
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
150
  {
27a884dc3   Arnaldo Carvalho de Melo   [SK_BUFF]: Conver...
151
  	unsigned char *b = skb_tail_pointer(skb);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
152
  	struct tcf_defact *d = a->priv;
1c40be12f   Eric Dumazet   net sched: fix so...
153
154
155
156
157
158
  	struct tc_defact opt = {
  		.index   = d->tcf_index,
  		.refcnt  = d->tcf_refcnt - ref,
  		.bindcnt = d->tcf_bindcnt - bind,
  		.action  = d->tcf_action,
  	};
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
159
  	struct tcf_t t;
7ba699c60   Patrick McHardy   [NET_SCHED]: Conv...
160
  	NLA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);
fa1b1cff3   Jamal Hadi Salim   net_cls_act: Make...
161
  	NLA_PUT_STRING(skb, TCA_DEF_DATA, d->tcfd_defdata);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
162
163
164
  	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);
7ba699c60   Patrick McHardy   [NET_SCHED]: Conv...
165
  	NLA_PUT(skb, TCA_DEF_TM, sizeof(t), &t);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
166
  	return skb->len;
7ba699c60   Patrick McHardy   [NET_SCHED]: Conv...
167
  nla_put_failure:
dc5fc579b   Arnaldo Carvalho de Melo   [NETLINK]: Use nl...
168
  	nlmsg_trim(skb, b);
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
169
  	return -1;
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
170
171
172
  }
  
  static struct tc_action_ops act_simp_ops = {
e9ce1cd3c   David S. Miller   [PKT_SCHED]: Kill...
173
174
175
176
177
178
179
180
181
182
  	.kind		=	"simple",
  	.hinfo		=	&simp_hash_info,
  	.type		=	TCA_ACT_SIMP,
  	.capab		=	TCA_CAP_NONE,
  	.owner		=	THIS_MODULE,
  	.act		=	tcf_simp,
  	.dump		=	tcf_simp_dump,
  	.cleanup	=	tcf_simp_cleanup,
  	.init		=	tcf_simp_init,
  	.walk		=	tcf_generic_walker,
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
183
184
185
186
187
188
189
190
191
192
  };
  
  MODULE_AUTHOR("Jamal Hadi Salim(2005)");
  MODULE_DESCRIPTION("Simple example action");
  MODULE_LICENSE("GPL");
  
  static int __init simp_init_module(void)
  {
  	int ret = tcf_register_action(&act_simp_ops);
  	if (!ret)
6ff9c3644   stephen hemminger   net sched: printk...
193
194
  		pr_info("Simple TC action Loaded
  ");
db7530797   Jamal Hadi Salim   [PKT_SCHED]: Intr...
195
196
197
198
199
200
201
202
203
204
  	return ret;
  }
  
  static void __exit simp_cleanup_module(void)
  {
  	tcf_unregister_action(&act_simp_ops);
  }
  
  module_init(simp_init_module);
  module_exit(simp_cleanup_module);