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
);
82 net_inc_ingress_queue();
84 mini_qdisc_pair_init(&q
->miniqp
, sch
, &dev
->miniq_ingress
);
86 q
->block_info
.binder_type
= FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS
;
87 q
->block_info
.chain_head_change
= clsact_chain_head_change
;
88 q
->block_info
.chain_head_change_priv
= &q
->miniqp
;
90 return tcf_block_get_ext(&q
->block
, sch
, &q
->block_info
, extack
);
93 static void ingress_destroy(struct Qdisc
*sch
)
95 struct ingress_sched_data
*q
= qdisc_priv(sch
);
97 tcf_block_put_ext(q
->block
, sch
, &q
->block_info
);
98 net_dec_ingress_queue();
101 static int ingress_dump(struct Qdisc
*sch
, struct sk_buff
*skb
)
105 nest
= nla_nest_start_noflag(skb
, TCA_OPTIONS
);
107 goto nla_put_failure
;
109 return nla_nest_end(skb
, nest
);
112 nla_nest_cancel(skb
, nest
);
116 static const struct Qdisc_class_ops ingress_class_ops
= {
117 .flags
= QDISC_CLASS_OPS_DOIT_UNLOCKED
,
118 .leaf
= ingress_leaf
,
119 .find
= ingress_find
,
120 .walk
= ingress_walk
,
121 .tcf_block
= ingress_tcf_block
,
122 .bind_tcf
= ingress_bind_filter
,
123 .unbind_tcf
= ingress_unbind_filter
,
126 static struct Qdisc_ops ingress_qdisc_ops __read_mostly
= {
127 .cl_ops
= &ingress_class_ops
,
129 .priv_size
= sizeof(struct ingress_sched_data
),
130 .static_flags
= TCQ_F_CPUSTATS
,
131 .init
= ingress_init
,
132 .destroy
= ingress_destroy
,
133 .dump
= ingress_dump
,
134 .ingress_block_set
= ingress_ingress_block_set
,
135 .ingress_block_get
= ingress_ingress_block_get
,
136 .owner
= THIS_MODULE
,
139 struct clsact_sched_data
{
140 struct tcf_block
*ingress_block
;
141 struct tcf_block
*egress_block
;
142 struct tcf_block_ext_info ingress_block_info
;
143 struct tcf_block_ext_info egress_block_info
;
144 struct mini_Qdisc_pair miniqp_ingress
;
145 struct mini_Qdisc_pair miniqp_egress
;
148 static unsigned long clsact_find(struct Qdisc
*sch
, u32 classid
)
150 switch (TC_H_MIN(classid
)) {
151 case TC_H_MIN(TC_H_MIN_INGRESS
):
152 case TC_H_MIN(TC_H_MIN_EGRESS
):
153 return TC_H_MIN(classid
);
159 static unsigned long clsact_bind_filter(struct Qdisc
*sch
,
160 unsigned long parent
, u32 classid
)
162 return clsact_find(sch
, classid
);
165 static struct tcf_block
*clsact_tcf_block(struct Qdisc
*sch
, unsigned long cl
,
166 struct netlink_ext_ack
*extack
)
168 struct clsact_sched_data
*q
= qdisc_priv(sch
);
171 case TC_H_MIN(TC_H_MIN_INGRESS
):
172 return q
->ingress_block
;
173 case TC_H_MIN(TC_H_MIN_EGRESS
):
174 return q
->egress_block
;
180 static void clsact_ingress_block_set(struct Qdisc
*sch
, u32 block_index
)
182 struct clsact_sched_data
*q
= qdisc_priv(sch
);
184 q
->ingress_block_info
.block_index
= block_index
;
187 static void clsact_egress_block_set(struct Qdisc
*sch
, u32 block_index
)
189 struct clsact_sched_data
*q
= qdisc_priv(sch
);
191 q
->egress_block_info
.block_index
= block_index
;
194 static u32
clsact_ingress_block_get(struct Qdisc
*sch
)
196 struct clsact_sched_data
*q
= qdisc_priv(sch
);
198 return q
->ingress_block_info
.block_index
;
201 static u32
clsact_egress_block_get(struct Qdisc
*sch
)
203 struct clsact_sched_data
*q
= qdisc_priv(sch
);
205 return q
->egress_block_info
.block_index
;
208 static int clsact_init(struct Qdisc
*sch
, struct nlattr
*opt
,
209 struct netlink_ext_ack
*extack
)
211 struct clsact_sched_data
*q
= qdisc_priv(sch
);
212 struct net_device
*dev
= qdisc_dev(sch
);
215 net_inc_ingress_queue();
216 net_inc_egress_queue();
218 mini_qdisc_pair_init(&q
->miniqp_ingress
, sch
, &dev
->miniq_ingress
);
220 q
->ingress_block_info
.binder_type
= FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS
;
221 q
->ingress_block_info
.chain_head_change
= clsact_chain_head_change
;
222 q
->ingress_block_info
.chain_head_change_priv
= &q
->miniqp_ingress
;
224 err
= tcf_block_get_ext(&q
->ingress_block
, sch
, &q
->ingress_block_info
,
229 mini_qdisc_pair_init(&q
->miniqp_egress
, sch
, &dev
->miniq_egress
);
231 q
->egress_block_info
.binder_type
= FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS
;
232 q
->egress_block_info
.chain_head_change
= clsact_chain_head_change
;
233 q
->egress_block_info
.chain_head_change_priv
= &q
->miniqp_egress
;
235 return tcf_block_get_ext(&q
->egress_block
, sch
, &q
->egress_block_info
, extack
);
238 static void clsact_destroy(struct Qdisc
*sch
)
240 struct clsact_sched_data
*q
= qdisc_priv(sch
);
242 tcf_block_put_ext(q
->egress_block
, sch
, &q
->egress_block_info
);
243 tcf_block_put_ext(q
->ingress_block
, sch
, &q
->ingress_block_info
);
245 net_dec_ingress_queue();
246 net_dec_egress_queue();
249 static const struct Qdisc_class_ops clsact_class_ops
= {
250 .flags
= QDISC_CLASS_OPS_DOIT_UNLOCKED
,
251 .leaf
= ingress_leaf
,
253 .walk
= ingress_walk
,
254 .tcf_block
= clsact_tcf_block
,
255 .bind_tcf
= clsact_bind_filter
,
256 .unbind_tcf
= ingress_unbind_filter
,
259 static struct Qdisc_ops clsact_qdisc_ops __read_mostly
= {
260 .cl_ops
= &clsact_class_ops
,
262 .priv_size
= sizeof(struct clsact_sched_data
),
263 .static_flags
= TCQ_F_CPUSTATS
,
265 .destroy
= clsact_destroy
,
266 .dump
= ingress_dump
,
267 .ingress_block_set
= clsact_ingress_block_set
,
268 .egress_block_set
= clsact_egress_block_set
,
269 .ingress_block_get
= clsact_ingress_block_get
,
270 .egress_block_get
= clsact_egress_block_get
,
271 .owner
= THIS_MODULE
,
274 static int __init
ingress_module_init(void)
278 ret
= register_qdisc(&ingress_qdisc_ops
);
280 ret
= register_qdisc(&clsact_qdisc_ops
);
282 unregister_qdisc(&ingress_qdisc_ops
);
288 static void __exit
ingress_module_exit(void)
290 unregister_qdisc(&ingress_qdisc_ops
);
291 unregister_qdisc(&clsact_qdisc_ops
);
294 module_init(ingress_module_init
);
295 module_exit(ingress_module_exit
);
297 MODULE_ALIAS("sch_clsact");
298 MODULE_LICENSE("GPL");