162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* net/sched/sch_ingress.c - Ingress and clsact qdisc 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Authors: Jamal Hadi Salim 1999 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/module.h> 862306a36Sopenharmony_ci#include <linux/types.h> 962306a36Sopenharmony_ci#include <linux/list.h> 1062306a36Sopenharmony_ci#include <linux/skbuff.h> 1162306a36Sopenharmony_ci#include <linux/rtnetlink.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <net/netlink.h> 1462306a36Sopenharmony_ci#include <net/pkt_sched.h> 1562306a36Sopenharmony_ci#include <net/pkt_cls.h> 1662306a36Sopenharmony_ci#include <net/tcx.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistruct ingress_sched_data { 1962306a36Sopenharmony_ci struct tcf_block *block; 2062306a36Sopenharmony_ci struct tcf_block_ext_info block_info; 2162306a36Sopenharmony_ci struct mini_Qdisc_pair miniqp; 2262306a36Sopenharmony_ci}; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci return NULL; 2762306a36Sopenharmony_ci} 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic unsigned long ingress_find(struct Qdisc *sch, u32 classid) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci return TC_H_MIN(classid) + 1; 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic unsigned long ingress_bind_filter(struct Qdisc *sch, 3562306a36Sopenharmony_ci unsigned long parent, u32 classid) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci return ingress_find(sch, classid); 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic void ingress_unbind_filter(struct Qdisc *sch, unsigned long cl) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic struct tcf_block *ingress_tcf_block(struct Qdisc *sch, unsigned long cl, 4962306a36Sopenharmony_ci struct netlink_ext_ack *extack) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci struct ingress_sched_data *q = qdisc_priv(sch); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci return q->block; 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic void clsact_chain_head_change(struct tcf_proto *tp_head, void *priv) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci struct mini_Qdisc_pair *miniqp = priv; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci mini_qdisc_pair_swap(miniqp, tp_head); 6162306a36Sopenharmony_ci}; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistatic void ingress_ingress_block_set(struct Qdisc *sch, u32 block_index) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci struct ingress_sched_data *q = qdisc_priv(sch); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci q->block_info.block_index = block_index; 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic u32 ingress_ingress_block_get(struct Qdisc *sch) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci struct ingress_sched_data *q = qdisc_priv(sch); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci return q->block_info.block_index; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic int ingress_init(struct Qdisc *sch, struct nlattr *opt, 7862306a36Sopenharmony_ci struct netlink_ext_ack *extack) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci struct ingress_sched_data *q = qdisc_priv(sch); 8162306a36Sopenharmony_ci struct net_device *dev = qdisc_dev(sch); 8262306a36Sopenharmony_ci struct bpf_mprog_entry *entry; 8362306a36Sopenharmony_ci bool created; 8462306a36Sopenharmony_ci int err; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci if (sch->parent != TC_H_INGRESS) 8762306a36Sopenharmony_ci return -EOPNOTSUPP; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci net_inc_ingress_queue(); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci entry = tcx_entry_fetch_or_create(dev, true, &created); 9262306a36Sopenharmony_ci if (!entry) 9362306a36Sopenharmony_ci return -ENOMEM; 9462306a36Sopenharmony_ci tcx_miniq_set_active(entry, true); 9562306a36Sopenharmony_ci mini_qdisc_pair_init(&q->miniqp, sch, &tcx_entry(entry)->miniq); 9662306a36Sopenharmony_ci if (created) 9762306a36Sopenharmony_ci tcx_entry_update(dev, entry, true); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci q->block_info.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS; 10062306a36Sopenharmony_ci q->block_info.chain_head_change = clsact_chain_head_change; 10162306a36Sopenharmony_ci q->block_info.chain_head_change_priv = &q->miniqp; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci err = tcf_block_get_ext(&q->block, sch, &q->block_info, extack); 10462306a36Sopenharmony_ci if (err) 10562306a36Sopenharmony_ci return err; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci mini_qdisc_pair_block_init(&q->miniqp, q->block); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci return 0; 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic void ingress_destroy(struct Qdisc *sch) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct ingress_sched_data *q = qdisc_priv(sch); 11562306a36Sopenharmony_ci struct net_device *dev = qdisc_dev(sch); 11662306a36Sopenharmony_ci struct bpf_mprog_entry *entry = rtnl_dereference(dev->tcx_ingress); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci if (sch->parent != TC_H_INGRESS) 11962306a36Sopenharmony_ci return; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci tcf_block_put_ext(q->block, sch, &q->block_info); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci if (entry) { 12462306a36Sopenharmony_ci tcx_miniq_set_active(entry, false); 12562306a36Sopenharmony_ci if (!tcx_entry_is_active(entry)) { 12662306a36Sopenharmony_ci tcx_entry_update(dev, NULL, true); 12762306a36Sopenharmony_ci tcx_entry_free(entry); 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci net_dec_ingress_queue(); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic int ingress_dump(struct Qdisc *sch, struct sk_buff *skb) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci struct nlattr *nest; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci nest = nla_nest_start_noflag(skb, TCA_OPTIONS); 13962306a36Sopenharmony_ci if (nest == NULL) 14062306a36Sopenharmony_ci goto nla_put_failure; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci return nla_nest_end(skb, nest); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cinla_put_failure: 14562306a36Sopenharmony_ci nla_nest_cancel(skb, nest); 14662306a36Sopenharmony_ci return -1; 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic const struct Qdisc_class_ops ingress_class_ops = { 15062306a36Sopenharmony_ci .flags = QDISC_CLASS_OPS_DOIT_UNLOCKED, 15162306a36Sopenharmony_ci .leaf = ingress_leaf, 15262306a36Sopenharmony_ci .find = ingress_find, 15362306a36Sopenharmony_ci .walk = ingress_walk, 15462306a36Sopenharmony_ci .tcf_block = ingress_tcf_block, 15562306a36Sopenharmony_ci .bind_tcf = ingress_bind_filter, 15662306a36Sopenharmony_ci .unbind_tcf = ingress_unbind_filter, 15762306a36Sopenharmony_ci}; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic struct Qdisc_ops ingress_qdisc_ops __read_mostly = { 16062306a36Sopenharmony_ci .cl_ops = &ingress_class_ops, 16162306a36Sopenharmony_ci .id = "ingress", 16262306a36Sopenharmony_ci .priv_size = sizeof(struct ingress_sched_data), 16362306a36Sopenharmony_ci .static_flags = TCQ_F_INGRESS | TCQ_F_CPUSTATS, 16462306a36Sopenharmony_ci .init = ingress_init, 16562306a36Sopenharmony_ci .destroy = ingress_destroy, 16662306a36Sopenharmony_ci .dump = ingress_dump, 16762306a36Sopenharmony_ci .ingress_block_set = ingress_ingress_block_set, 16862306a36Sopenharmony_ci .ingress_block_get = ingress_ingress_block_get, 16962306a36Sopenharmony_ci .owner = THIS_MODULE, 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistruct clsact_sched_data { 17362306a36Sopenharmony_ci struct tcf_block *ingress_block; 17462306a36Sopenharmony_ci struct tcf_block *egress_block; 17562306a36Sopenharmony_ci struct tcf_block_ext_info ingress_block_info; 17662306a36Sopenharmony_ci struct tcf_block_ext_info egress_block_info; 17762306a36Sopenharmony_ci struct mini_Qdisc_pair miniqp_ingress; 17862306a36Sopenharmony_ci struct mini_Qdisc_pair miniqp_egress; 17962306a36Sopenharmony_ci}; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic unsigned long clsact_find(struct Qdisc *sch, u32 classid) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci switch (TC_H_MIN(classid)) { 18462306a36Sopenharmony_ci case TC_H_MIN(TC_H_MIN_INGRESS): 18562306a36Sopenharmony_ci case TC_H_MIN(TC_H_MIN_EGRESS): 18662306a36Sopenharmony_ci return TC_H_MIN(classid); 18762306a36Sopenharmony_ci default: 18862306a36Sopenharmony_ci return 0; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic unsigned long clsact_bind_filter(struct Qdisc *sch, 19362306a36Sopenharmony_ci unsigned long parent, u32 classid) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci return clsact_find(sch, classid); 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic struct tcf_block *clsact_tcf_block(struct Qdisc *sch, unsigned long cl, 19962306a36Sopenharmony_ci struct netlink_ext_ack *extack) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci struct clsact_sched_data *q = qdisc_priv(sch); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci switch (cl) { 20462306a36Sopenharmony_ci case TC_H_MIN(TC_H_MIN_INGRESS): 20562306a36Sopenharmony_ci return q->ingress_block; 20662306a36Sopenharmony_ci case TC_H_MIN(TC_H_MIN_EGRESS): 20762306a36Sopenharmony_ci return q->egress_block; 20862306a36Sopenharmony_ci default: 20962306a36Sopenharmony_ci return NULL; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_cistatic void clsact_ingress_block_set(struct Qdisc *sch, u32 block_index) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci struct clsact_sched_data *q = qdisc_priv(sch); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci q->ingress_block_info.block_index = block_index; 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic void clsact_egress_block_set(struct Qdisc *sch, u32 block_index) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci struct clsact_sched_data *q = qdisc_priv(sch); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci q->egress_block_info.block_index = block_index; 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic u32 clsact_ingress_block_get(struct Qdisc *sch) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci struct clsact_sched_data *q = qdisc_priv(sch); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci return q->ingress_block_info.block_index; 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic u32 clsact_egress_block_get(struct Qdisc *sch) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci struct clsact_sched_data *q = qdisc_priv(sch); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci return q->egress_block_info.block_index; 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic int clsact_init(struct Qdisc *sch, struct nlattr *opt, 24262306a36Sopenharmony_ci struct netlink_ext_ack *extack) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci struct clsact_sched_data *q = qdisc_priv(sch); 24562306a36Sopenharmony_ci struct net_device *dev = qdisc_dev(sch); 24662306a36Sopenharmony_ci struct bpf_mprog_entry *entry; 24762306a36Sopenharmony_ci bool created; 24862306a36Sopenharmony_ci int err; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci if (sch->parent != TC_H_CLSACT) 25162306a36Sopenharmony_ci return -EOPNOTSUPP; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci net_inc_ingress_queue(); 25462306a36Sopenharmony_ci net_inc_egress_queue(); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci entry = tcx_entry_fetch_or_create(dev, true, &created); 25762306a36Sopenharmony_ci if (!entry) 25862306a36Sopenharmony_ci return -ENOMEM; 25962306a36Sopenharmony_ci tcx_miniq_set_active(entry, true); 26062306a36Sopenharmony_ci mini_qdisc_pair_init(&q->miniqp_ingress, sch, &tcx_entry(entry)->miniq); 26162306a36Sopenharmony_ci if (created) 26262306a36Sopenharmony_ci tcx_entry_update(dev, entry, true); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci q->ingress_block_info.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS; 26562306a36Sopenharmony_ci q->ingress_block_info.chain_head_change = clsact_chain_head_change; 26662306a36Sopenharmony_ci q->ingress_block_info.chain_head_change_priv = &q->miniqp_ingress; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci err = tcf_block_get_ext(&q->ingress_block, sch, &q->ingress_block_info, 26962306a36Sopenharmony_ci extack); 27062306a36Sopenharmony_ci if (err) 27162306a36Sopenharmony_ci return err; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci mini_qdisc_pair_block_init(&q->miniqp_ingress, q->ingress_block); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci entry = tcx_entry_fetch_or_create(dev, false, &created); 27662306a36Sopenharmony_ci if (!entry) 27762306a36Sopenharmony_ci return -ENOMEM; 27862306a36Sopenharmony_ci tcx_miniq_set_active(entry, true); 27962306a36Sopenharmony_ci mini_qdisc_pair_init(&q->miniqp_egress, sch, &tcx_entry(entry)->miniq); 28062306a36Sopenharmony_ci if (created) 28162306a36Sopenharmony_ci tcx_entry_update(dev, entry, false); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci q->egress_block_info.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS; 28462306a36Sopenharmony_ci q->egress_block_info.chain_head_change = clsact_chain_head_change; 28562306a36Sopenharmony_ci q->egress_block_info.chain_head_change_priv = &q->miniqp_egress; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci return tcf_block_get_ext(&q->egress_block, sch, &q->egress_block_info, extack); 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic void clsact_destroy(struct Qdisc *sch) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci struct clsact_sched_data *q = qdisc_priv(sch); 29362306a36Sopenharmony_ci struct net_device *dev = qdisc_dev(sch); 29462306a36Sopenharmony_ci struct bpf_mprog_entry *ingress_entry = rtnl_dereference(dev->tcx_ingress); 29562306a36Sopenharmony_ci struct bpf_mprog_entry *egress_entry = rtnl_dereference(dev->tcx_egress); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci if (sch->parent != TC_H_CLSACT) 29862306a36Sopenharmony_ci return; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci tcf_block_put_ext(q->ingress_block, sch, &q->ingress_block_info); 30162306a36Sopenharmony_ci tcf_block_put_ext(q->egress_block, sch, &q->egress_block_info); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci if (ingress_entry) { 30462306a36Sopenharmony_ci tcx_miniq_set_active(ingress_entry, false); 30562306a36Sopenharmony_ci if (!tcx_entry_is_active(ingress_entry)) { 30662306a36Sopenharmony_ci tcx_entry_update(dev, NULL, true); 30762306a36Sopenharmony_ci tcx_entry_free(ingress_entry); 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci if (egress_entry) { 31262306a36Sopenharmony_ci tcx_miniq_set_active(egress_entry, false); 31362306a36Sopenharmony_ci if (!tcx_entry_is_active(egress_entry)) { 31462306a36Sopenharmony_ci tcx_entry_update(dev, NULL, false); 31562306a36Sopenharmony_ci tcx_entry_free(egress_entry); 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci net_dec_ingress_queue(); 32062306a36Sopenharmony_ci net_dec_egress_queue(); 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cistatic const struct Qdisc_class_ops clsact_class_ops = { 32462306a36Sopenharmony_ci .flags = QDISC_CLASS_OPS_DOIT_UNLOCKED, 32562306a36Sopenharmony_ci .leaf = ingress_leaf, 32662306a36Sopenharmony_ci .find = clsact_find, 32762306a36Sopenharmony_ci .walk = ingress_walk, 32862306a36Sopenharmony_ci .tcf_block = clsact_tcf_block, 32962306a36Sopenharmony_ci .bind_tcf = clsact_bind_filter, 33062306a36Sopenharmony_ci .unbind_tcf = ingress_unbind_filter, 33162306a36Sopenharmony_ci}; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cistatic struct Qdisc_ops clsact_qdisc_ops __read_mostly = { 33462306a36Sopenharmony_ci .cl_ops = &clsact_class_ops, 33562306a36Sopenharmony_ci .id = "clsact", 33662306a36Sopenharmony_ci .priv_size = sizeof(struct clsact_sched_data), 33762306a36Sopenharmony_ci .static_flags = TCQ_F_INGRESS | TCQ_F_CPUSTATS, 33862306a36Sopenharmony_ci .init = clsact_init, 33962306a36Sopenharmony_ci .destroy = clsact_destroy, 34062306a36Sopenharmony_ci .dump = ingress_dump, 34162306a36Sopenharmony_ci .ingress_block_set = clsact_ingress_block_set, 34262306a36Sopenharmony_ci .egress_block_set = clsact_egress_block_set, 34362306a36Sopenharmony_ci .ingress_block_get = clsact_ingress_block_get, 34462306a36Sopenharmony_ci .egress_block_get = clsact_egress_block_get, 34562306a36Sopenharmony_ci .owner = THIS_MODULE, 34662306a36Sopenharmony_ci}; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_cistatic int __init ingress_module_init(void) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci int ret; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci ret = register_qdisc(&ingress_qdisc_ops); 35362306a36Sopenharmony_ci if (!ret) { 35462306a36Sopenharmony_ci ret = register_qdisc(&clsact_qdisc_ops); 35562306a36Sopenharmony_ci if (ret) 35662306a36Sopenharmony_ci unregister_qdisc(&ingress_qdisc_ops); 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci return ret; 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic void __exit ingress_module_exit(void) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci unregister_qdisc(&ingress_qdisc_ops); 36562306a36Sopenharmony_ci unregister_qdisc(&clsact_qdisc_ops); 36662306a36Sopenharmony_ci} 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cimodule_init(ingress_module_init); 36962306a36Sopenharmony_cimodule_exit(ingress_module_exit); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ciMODULE_ALIAS("sch_clsact"); 37262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 373