1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* net/sched/sch_ingress.c - Ingress and clsact qdisc
4 * Authors: Jamal Hadi Salim 1999
7 #include <linux/module.h>
8 #include <linux/types.h>
9 #include <linux/list.h>
10 #include <linux/skbuff.h>
11 #include <linux/rtnetlink.h>
13 #include <net/netlink.h>
14 #include <net/pkt_sched.h>
15 #include <net/pkt_cls.h>
17 struct ingress_sched_data
{
18 struct tcf_block
*block
;
19 struct tcf_block_ext_info block_info
;
20 struct mini_Qdisc_pair miniqp
;
23 static struct Qdisc
*ingress_leaf(struct Qdisc
*sch
, unsigned long arg
)
28 static unsigned long ingress_find(struct Qdisc
*sch
, u32 classid
)
30 return TC_H_MIN(classid
) + 1;
33 static unsigned long ingress_bind_filter(struct Qdisc
*sch
,
34 unsigned long parent
, u32 classid
)
36 return ingress_find(sch
, classid
);
39 static void ingress_unbind_filter(struct Qdisc
*sch
, unsigned long cl
)
43 static void ingress_walk(struct Qdisc
*sch
, struct qdisc_walker
*walker
)
47 static struct tcf_block
*ingress_tcf_block(struct Qdisc
*sch
, unsigned long cl
,
48 struct netlink_ext_ack
*extack
)
50 struct ingress_sched_data
*q
= qdisc_priv(sch
);
55 static void clsact_chain_head_change(struct tcf_proto
*tp_head
, void *priv
)
57 struct mini_Qdisc_pair
*miniqp
= priv
;
59 mini_qdisc_pair_swap(miniqp
, tp_head
);
62 static void ingress_ingress_block_set(struct Qdisc
*sch
, u32 block_index
)
64 struct ingress_sched_data
*q
= qdisc_priv(sch
);
66 q
->block_info
.block_index
= block_index
;
69 static u32
ingress_ingress_block_get(struct Qdisc
*sch
)
71 struct ingress_sched_data
*q
= qdisc_priv(sch
);
73 return q
->block_info
.block_index
;
76 static int ingress_init(struct Qdisc
*sch
, struct nlattr
*opt
,
77 struct netlink_ext_ack
*extack
)
79 struct ingress_sched_data
*q
= qdisc_priv(sch
);
80 struct net_device
*dev
= qdisc_dev(sch
);
83 net_inc_ingress_queue();
85 mini_qdisc_pair_init(&q
->miniqp
, sch
, &dev
->miniq_ingress
);
87 q
->block_info
.binder_type
= FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS
;
88 q
->block_info
.chain_head_change
= clsact_chain_head_change
;
89 q
->block_info
.chain_head_change_priv
= &q
->miniqp
;
91 err
= tcf_block_get_ext(&q
->block
, sch
, &q
->block_info
, extack
);
95 mini_qdisc_pair_block_init(&q
->miniqp
, q
->block
);
100 static void ingress_destroy(struct Qdisc
*sch
)
102 struct ingress_sched_data
*q
= qdisc_priv(sch
);
104 tcf_block_put_ext(q
->block
, sch
, &q
->block_info
);
105 net_dec_ingress_queue();
108 static int ingress_dump(struct Qdisc
*sch
, struct sk_buff
*skb
)
112 nest
= nla_nest_start_noflag(skb
, TCA_OPTIONS
);
114 goto nla_put_failure
;
116 return nla_nest_end(skb
, nest
);
119 nla_nest_cancel(skb
, nest
);
123 static const struct Qdisc_class_ops ingress_class_ops
= {
124 .flags
= QDISC_CLASS_OPS_DOIT_UNLOCKED
,
125 .leaf
= ingress_leaf
,
126 .find
= ingress_find
,
127 .walk
= ingress_walk
,
128 .tcf_block
= ingress_tcf_block
,
129 .bind_tcf
= ingress_bind_filter
,
130 .unbind_tcf
= ingress_unbind_filter
,
133 static struct Qdisc_ops ingress_qdisc_ops __read_mostly
= {
134 .cl_ops
= &ingress_class_ops
,
136 .priv_size
= sizeof(struct ingress_sched_data
),
137 .static_flags
= TCQ_F_CPUSTATS
,
138 .init
= ingress_init
,
139 .destroy
= ingress_destroy
,
140 .dump
= ingress_dump
,
141 .ingress_block_set
= ingress_ingress_block_set
,
142 .ingress_block_get
= ingress_ingress_block_get
,
143 .owner
= THIS_MODULE
,
146 struct clsact_sched_data
{
147 struct tcf_block
*ingress_block
;
148 struct tcf_block
*egress_block
;
149 struct tcf_block_ext_info ingress_block_info
;
150 struct tcf_block_ext_info egress_block_info
;
151 struct mini_Qdisc_pair miniqp_ingress
;
152 struct mini_Qdisc_pair miniqp_egress
;
155 static unsigned long clsact_find(struct Qdisc
*sch
, u32 classid
)
157 switch (TC_H_MIN(classid
)) {
158 case TC_H_MIN(TC_H_MIN_INGRESS
):
159 case TC_H_MIN(TC_H_MIN_EGRESS
):
160 return TC_H_MIN(classid
);
166 static unsigned long clsact_bind_filter(struct Qdisc
*sch
,
167 unsigned long parent
, u32 classid
)
169 return clsact_find(sch
, classid
);
172 static struct tcf_block
*clsact_tcf_block(struct Qdisc
*sch
, unsigned long cl
,
173 struct netlink_ext_ack
*extack
)
175 struct clsact_sched_data
*q
= qdisc_priv(sch
);
178 case TC_H_MIN(TC_H_MIN_INGRESS
):
179 return q
->ingress_block
;
180 case TC_H_MIN(TC_H_MIN_EGRESS
):
181 return q
->egress_block
;
187 static void clsact_ingress_block_set(struct Qdisc
*sch
, u32 block_index
)
189 struct clsact_sched_data
*q
= qdisc_priv(sch
);
191 q
->ingress_block_info
.block_index
= block_index
;
194 static void clsact_egress_block_set(struct Qdisc
*sch
, u32 block_index
)
196 struct clsact_sched_data
*q
= qdisc_priv(sch
);
198 q
->egress_block_info
.block_index
= block_index
;
201 static u32
clsact_ingress_block_get(struct Qdisc
*sch
)
203 struct clsact_sched_data
*q
= qdisc_priv(sch
);
205 return q
->ingress_block_info
.block_index
;
208 static u32
clsact_egress_block_get(struct Qdisc
*sch
)
210 struct clsact_sched_data
*q
= qdisc_priv(sch
);
212 return q
->egress_block_info
.block_index
;
215 static int clsact_init(struct Qdisc
*sch
, struct nlattr
*opt
,
216 struct netlink_ext_ack
*extack
)
218 struct clsact_sched_data
*q
= qdisc_priv(sch
);
219 struct net_device
*dev
= qdisc_dev(sch
);
222 net_inc_ingress_queue();
223 net_inc_egress_queue();
225 mini_qdisc_pair_init(&q
->miniqp_ingress
, sch
, &dev
->miniq_ingress
);
227 q
->ingress_block_info
.binder_type
= FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS
;
228 q
->ingress_block_info
.chain_head_change
= clsact_chain_head_change
;
229 q
->ingress_block_info
.chain_head_change_priv
= &q
->miniqp_ingress
;
231 err
= tcf_block_get_ext(&q
->ingress_block
, sch
, &q
->ingress_block_info
,
236 mini_qdisc_pair_block_init(&q
->miniqp_ingress
, q
->ingress_block
);
238 mini_qdisc_pair_init(&q
->miniqp_egress
, sch
, &dev
->miniq_egress
);
240 q
->egress_block_info
.binder_type
= FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS
;
241 q
->egress_block_info
.chain_head_change
= clsact_chain_head_change
;
242 q
->egress_block_info
.chain_head_change_priv
= &q
->miniqp_egress
;
244 return tcf_block_get_ext(&q
->egress_block
, sch
, &q
->egress_block_info
, extack
);
247 static void clsact_destroy(struct Qdisc
*sch
)
249 struct clsact_sched_data
*q
= qdisc_priv(sch
);
251 tcf_block_put_ext(q
->egress_block
, sch
, &q
->egress_block_info
);
252 tcf_block_put_ext(q
->ingress_block
, sch
, &q
->ingress_block_info
);
254 net_dec_ingress_queue();
255 net_dec_egress_queue();
258 static const struct Qdisc_class_ops clsact_class_ops
= {
259 .flags
= QDISC_CLASS_OPS_DOIT_UNLOCKED
,
260 .leaf
= ingress_leaf
,
262 .walk
= ingress_walk
,
263 .tcf_block
= clsact_tcf_block
,
264 .bind_tcf
= clsact_bind_filter
,
265 .unbind_tcf
= ingress_unbind_filter
,
268 static struct Qdisc_ops clsact_qdisc_ops __read_mostly
= {
269 .cl_ops
= &clsact_class_ops
,
271 .priv_size
= sizeof(struct clsact_sched_data
),
272 .static_flags
= TCQ_F_CPUSTATS
,
274 .destroy
= clsact_destroy
,
275 .dump
= ingress_dump
,
276 .ingress_block_set
= clsact_ingress_block_set
,
277 .egress_block_set
= clsact_egress_block_set
,
278 .ingress_block_get
= clsact_ingress_block_get
,
279 .egress_block_get
= clsact_egress_block_get
,
280 .owner
= THIS_MODULE
,
283 static int __init
ingress_module_init(void)
287 ret
= register_qdisc(&ingress_qdisc_ops
);
289 ret
= register_qdisc(&clsact_qdisc_ops
);
291 unregister_qdisc(&ingress_qdisc_ops
);
297 static void __exit
ingress_module_exit(void)
299 unregister_qdisc(&ingress_qdisc_ops
);
300 unregister_qdisc(&clsact_qdisc_ops
);
303 module_init(ingress_module_init
);
304 module_exit(ingress_module_exit
);
306 MODULE_ALIAS("sch_clsact");
307 MODULE_LICENSE("GPL");