blob: 9ccc1b89b0d998d4b6069ff19a6d48206c505fe3 [file] [log] [blame]
Daniel Borkmann1f211a12016-01-07 22:29:47 +01001/* net/sched/sch_ingress.c - Ingress and clsact qdisc
2 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License
5 * as published by the Free Software Foundation; either version
6 * 2 of the License, or (at your option) any later version.
7 *
8 * Authors: Jamal Hadi Salim 1999
9 */
10
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <linux/module.h>
12#include <linux/types.h>
Patrick McHardy0ba48052007-07-02 22:49:07 -070013#include <linux/list.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <linux/rtnetlink.h>
Daniel Borkmannd2788d32015-05-09 22:51:32 +020016
Arnaldo Carvalho de Melodc5fc572007-03-25 23:06:12 -070017#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <net/pkt_sched.h>
Jiri Pirkocf1facd2017-02-09 14:38:56 +010019#include <net/pkt_cls.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
Jiri Pirko6529eab2017-05-17 11:07:55 +020021struct ingress_sched_data {
22 struct tcf_block *block;
23};
24
Linus Torvalds1da177e2005-04-16 15:20:36 -070025static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
26{
27 return NULL;
28}
29
WANG Cong143976c2017-08-24 16:51:29 -070030static unsigned long ingress_find(struct Qdisc *sch, u32 classid)
Linus Torvalds1da177e2005-04-16 15:20:36 -070031{
Linus Torvalds1da177e2005-04-16 15:20:36 -070032 return TC_H_MIN(classid) + 1;
33}
34
Linus Torvalds1da177e2005-04-16 15:20:36 -070035static unsigned long ingress_bind_filter(struct Qdisc *sch,
Patrick McHardy58f4df42008-01-21 00:11:01 -080036 unsigned long parent, u32 classid)
Linus Torvalds1da177e2005-04-16 15:20:36 -070037{
WANG Cong143976c2017-08-24 16:51:29 -070038 return ingress_find(sch, classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -070039}
40
WANG Cong143976c2017-08-24 16:51:29 -070041static void ingress_unbind_filter(struct Qdisc *sch, unsigned long cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -070042{
43}
44
Patrick McHardy58f4df42008-01-21 00:11:01 -080045static void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker)
Linus Torvalds1da177e2005-04-16 15:20:36 -070046{
Linus Torvalds1da177e2005-04-16 15:20:36 -070047}
48
Jiri Pirko6529eab2017-05-17 11:07:55 +020049static struct tcf_block *ingress_tcf_block(struct Qdisc *sch, unsigned long cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -070050{
Jiri Pirko6529eab2017-05-17 11:07:55 +020051 struct ingress_sched_data *q = qdisc_priv(sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
Jiri Pirko6529eab2017-05-17 11:07:55 +020053 return q->block;
Linus Torvalds1da177e2005-04-16 15:20:36 -070054}
55
Daniel Borkmann45771392015-04-10 23:07:54 +020056static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
57{
Jiri Pirko6529eab2017-05-17 11:07:55 +020058 struct ingress_sched_data *q = qdisc_priv(sch);
59 struct net_device *dev = qdisc_dev(sch);
60 int err;
61
Jiri Pirko69d78ef2017-10-13 14:00:57 +020062 err = tcf_block_get(&q->block, &dev->ingress_cl_list, sch);
Jiri Pirko6529eab2017-05-17 11:07:55 +020063 if (err)
64 return err;
65
Daniel Borkmann45771392015-04-10 23:07:54 +020066 net_inc_ingress_queue();
Alexei Starovoitov087c1a62015-04-30 20:14:07 -070067 sch->flags |= TCQ_F_CPUSTATS;
Daniel Borkmann45771392015-04-10 23:07:54 +020068
69 return 0;
70}
71
Linus Torvalds1da177e2005-04-16 15:20:36 -070072static void ingress_destroy(struct Qdisc *sch)
73{
Jiri Pirko6529eab2017-05-17 11:07:55 +020074 struct ingress_sched_data *q = qdisc_priv(sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Jiri Pirko6529eab2017-05-17 11:07:55 +020076 tcf_block_put(q->block);
Daniel Borkmann45771392015-04-10 23:07:54 +020077 net_dec_ingress_queue();
Linus Torvalds1da177e2005-04-16 15:20:36 -070078}
79
Linus Torvalds1da177e2005-04-16 15:20:36 -070080static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
81{
Patrick McHardy4b3550ef2008-01-23 20:34:11 -080082 struct nlattr *nest;
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
Patrick McHardy4b3550ef2008-01-23 20:34:11 -080084 nest = nla_nest_start(skb, TCA_OPTIONS);
85 if (nest == NULL)
86 goto nla_put_failure;
Daniel Borkmannd2788d32015-05-09 22:51:32 +020087
Yang Yingliangd59b7d82014-03-12 10:20:32 +080088 return nla_nest_end(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
Patrick McHardy1e904742008-01-22 22:11:17 -080090nla_put_failure:
Patrick McHardy4b3550ef2008-01-23 20:34:11 -080091 nla_nest_cancel(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 return -1;
93}
94
Eric Dumazet20fea082007-11-14 01:44:41 -080095static const struct Qdisc_class_ops ingress_class_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 .leaf = ingress_leaf,
WANG Cong143976c2017-08-24 16:51:29 -070097 .find = ingress_find,
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 .walk = ingress_walk,
Jiri Pirko6529eab2017-05-17 11:07:55 +020099 .tcf_block = ingress_tcf_block,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100 .bind_tcf = ingress_bind_filter,
WANG Cong143976c2017-08-24 16:51:29 -0700101 .unbind_tcf = ingress_unbind_filter,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102};
103
Eric Dumazet20fea082007-11-14 01:44:41 -0800104static struct Qdisc_ops ingress_qdisc_ops __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 .cl_ops = &ingress_class_ops,
106 .id = "ingress",
Jiri Pirko6529eab2017-05-17 11:07:55 +0200107 .priv_size = sizeof(struct ingress_sched_data),
Daniel Borkmann45771392015-04-10 23:07:54 +0200108 .init = ingress_init,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 .destroy = ingress_destroy,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 .dump = ingress_dump,
111 .owner = THIS_MODULE,
112};
113
Jiri Pirko6529eab2017-05-17 11:07:55 +0200114struct clsact_sched_data {
115 struct tcf_block *ingress_block;
116 struct tcf_block *egress_block;
117};
118
WANG Cong143976c2017-08-24 16:51:29 -0700119static unsigned long clsact_find(struct Qdisc *sch, u32 classid)
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100120{
121 switch (TC_H_MIN(classid)) {
122 case TC_H_MIN(TC_H_MIN_INGRESS):
123 case TC_H_MIN(TC_H_MIN_EGRESS):
124 return TC_H_MIN(classid);
125 default:
126 return 0;
127 }
128}
129
130static unsigned long clsact_bind_filter(struct Qdisc *sch,
131 unsigned long parent, u32 classid)
132{
WANG Cong143976c2017-08-24 16:51:29 -0700133 return clsact_find(sch, classid);
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100134}
135
Jiri Pirko6529eab2017-05-17 11:07:55 +0200136static struct tcf_block *clsact_tcf_block(struct Qdisc *sch, unsigned long cl)
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100137{
Jiri Pirko6529eab2017-05-17 11:07:55 +0200138 struct clsact_sched_data *q = qdisc_priv(sch);
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100139
140 switch (cl) {
141 case TC_H_MIN(TC_H_MIN_INGRESS):
Jiri Pirko6529eab2017-05-17 11:07:55 +0200142 return q->ingress_block;
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100143 case TC_H_MIN(TC_H_MIN_EGRESS):
Jiri Pirko6529eab2017-05-17 11:07:55 +0200144 return q->egress_block;
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100145 default:
146 return NULL;
147 }
148}
149
150static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
151{
Jiri Pirko6529eab2017-05-17 11:07:55 +0200152 struct clsact_sched_data *q = qdisc_priv(sch);
153 struct net_device *dev = qdisc_dev(sch);
154 int err;
155
Jiri Pirko69d78ef2017-10-13 14:00:57 +0200156 err = tcf_block_get(&q->ingress_block, &dev->ingress_cl_list, sch);
Jiri Pirko6529eab2017-05-17 11:07:55 +0200157 if (err)
158 return err;
159
Jiri Pirko69d78ef2017-10-13 14:00:57 +0200160 err = tcf_block_get(&q->egress_block, &dev->egress_cl_list, sch);
Jiri Pirko6529eab2017-05-17 11:07:55 +0200161 if (err)
162 return err;
163
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100164 net_inc_ingress_queue();
165 net_inc_egress_queue();
166
167 sch->flags |= TCQ_F_CPUSTATS;
168
169 return 0;
170}
171
172static void clsact_destroy(struct Qdisc *sch)
173{
Jiri Pirko6529eab2017-05-17 11:07:55 +0200174 struct clsact_sched_data *q = qdisc_priv(sch);
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100175
Jiri Pirko6529eab2017-05-17 11:07:55 +0200176 tcf_block_put(q->egress_block);
177 tcf_block_put(q->ingress_block);
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100178
179 net_dec_ingress_queue();
180 net_dec_egress_queue();
181}
182
183static const struct Qdisc_class_ops clsact_class_ops = {
184 .leaf = ingress_leaf,
WANG Cong143976c2017-08-24 16:51:29 -0700185 .find = clsact_find,
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100186 .walk = ingress_walk,
Jiri Pirko6529eab2017-05-17 11:07:55 +0200187 .tcf_block = clsact_tcf_block,
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100188 .bind_tcf = clsact_bind_filter,
WANG Cong143976c2017-08-24 16:51:29 -0700189 .unbind_tcf = ingress_unbind_filter,
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100190};
191
192static struct Qdisc_ops clsact_qdisc_ops __read_mostly = {
193 .cl_ops = &clsact_class_ops,
194 .id = "clsact",
Jiri Pirko6529eab2017-05-17 11:07:55 +0200195 .priv_size = sizeof(struct clsact_sched_data),
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100196 .init = clsact_init,
197 .destroy = clsact_destroy,
198 .dump = ingress_dump,
199 .owner = THIS_MODULE,
200};
201
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202static int __init ingress_module_init(void)
203{
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100204 int ret;
205
206 ret = register_qdisc(&ingress_qdisc_ops);
207 if (!ret) {
208 ret = register_qdisc(&clsact_qdisc_ops);
209 if (ret)
210 unregister_qdisc(&ingress_qdisc_ops);
211 }
212
213 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214}
Patrick McHardy58f4df42008-01-21 00:11:01 -0800215
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900216static void __exit ingress_module_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217{
218 unregister_qdisc(&ingress_qdisc_ops);
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100219 unregister_qdisc(&clsact_qdisc_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220}
Patrick McHardy58f4df42008-01-21 00:11:01 -0800221
Daniel Borkmannd2788d32015-05-09 22:51:32 +0200222module_init(ingress_module_init);
223module_exit(ingress_module_exit);
224
Daniel Borkmann1f211a12016-01-07 22:29:47 +0100225MODULE_ALIAS("sch_clsact");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226MODULE_LICENSE("GPL");