root/net/sched/sch_ingress.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ingress_leaf
  2. ingress_find
  3. ingress_bind_filter
  4. ingress_unbind_filter
  5. ingress_walk
  6. ingress_tcf_block
  7. clsact_chain_head_change
  8. ingress_ingress_block_set
  9. ingress_ingress_block_get
  10. ingress_init
  11. ingress_destroy
  12. ingress_dump
  13. clsact_find
  14. clsact_bind_filter
  15. clsact_tcf_block
  16. clsact_ingress_block_set
  17. clsact_egress_block_set
  18. clsact_ingress_block_get
  19. clsact_egress_block_get
  20. clsact_init
  21. clsact_destroy
  22. ingress_module_init
  23. ingress_module_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /* net/sched/sch_ingress.c - Ingress and clsact qdisc
   3  *
   4  * Authors:     Jamal Hadi Salim 1999
   5  */
   6 
   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>
  12 
  13 #include <net/netlink.h>
  14 #include <net/pkt_sched.h>
  15 #include <net/pkt_cls.h>
  16 
  17 struct ingress_sched_data {
  18         struct tcf_block *block;
  19         struct tcf_block_ext_info block_info;
  20         struct mini_Qdisc_pair miniqp;
  21 };
  22 
  23 static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
  24 {
  25         return NULL;
  26 }
  27 
  28 static unsigned long ingress_find(struct Qdisc *sch, u32 classid)
  29 {
  30         return TC_H_MIN(classid) + 1;
  31 }
  32 
  33 static unsigned long ingress_bind_filter(struct Qdisc *sch,
  34                                          unsigned long parent, u32 classid)
  35 {
  36         return ingress_find(sch, classid);
  37 }
  38 
  39 static void ingress_unbind_filter(struct Qdisc *sch, unsigned long cl)
  40 {
  41 }
  42 
  43 static void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker)
  44 {
  45 }
  46 
  47 static struct tcf_block *ingress_tcf_block(struct Qdisc *sch, unsigned long cl,
  48                                            struct netlink_ext_ack *extack)
  49 {
  50         struct ingress_sched_data *q = qdisc_priv(sch);
  51 
  52         return q->block;
  53 }
  54 
  55 static void clsact_chain_head_change(struct tcf_proto *tp_head, void *priv)
  56 {
  57         struct mini_Qdisc_pair *miniqp = priv;
  58 
  59         mini_qdisc_pair_swap(miniqp, tp_head);
  60 };
  61 
  62 static void ingress_ingress_block_set(struct Qdisc *sch, u32 block_index)
  63 {
  64         struct ingress_sched_data *q = qdisc_priv(sch);
  65 
  66         q->block_info.block_index = block_index;
  67 }
  68 
  69 static u32 ingress_ingress_block_get(struct Qdisc *sch)
  70 {
  71         struct ingress_sched_data *q = qdisc_priv(sch);
  72 
  73         return q->block_info.block_index;
  74 }
  75 
  76 static int ingress_init(struct Qdisc *sch, struct nlattr *opt,
  77                         struct netlink_ext_ack *extack)
  78 {
  79         struct ingress_sched_data *q = qdisc_priv(sch);
  80         struct net_device *dev = qdisc_dev(sch);
  81 
  82         net_inc_ingress_queue();
  83 
  84         mini_qdisc_pair_init(&q->miniqp, sch, &dev->miniq_ingress);
  85 
  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;
  89 
  90         return tcf_block_get_ext(&q->block, sch, &q->block_info, extack);
  91 }
  92 
  93 static void ingress_destroy(struct Qdisc *sch)
  94 {
  95         struct ingress_sched_data *q = qdisc_priv(sch);
  96 
  97         tcf_block_put_ext(q->block, sch, &q->block_info);
  98         net_dec_ingress_queue();
  99 }
 100 
 101 static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
 102 {
 103         struct nlattr *nest;
 104 
 105         nest = nla_nest_start_noflag(skb, TCA_OPTIONS);
 106         if (nest == NULL)
 107                 goto nla_put_failure;
 108 
 109         return nla_nest_end(skb, nest);
 110 
 111 nla_put_failure:
 112         nla_nest_cancel(skb, nest);
 113         return -1;
 114 }
 115 
 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,
 124 };
 125 
 126 static struct Qdisc_ops ingress_qdisc_ops __read_mostly = {
 127         .cl_ops                 =       &ingress_class_ops,
 128         .id                     =       "ingress",
 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,
 137 };
 138 
 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;
 146 };
 147 
 148 static unsigned long clsact_find(struct Qdisc *sch, u32 classid)
 149 {
 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);
 154         default:
 155                 return 0;
 156         }
 157 }
 158 
 159 static unsigned long clsact_bind_filter(struct Qdisc *sch,
 160                                         unsigned long parent, u32 classid)
 161 {
 162         return clsact_find(sch, classid);
 163 }
 164 
 165 static struct tcf_block *clsact_tcf_block(struct Qdisc *sch, unsigned long cl,
 166                                           struct netlink_ext_ack *extack)
 167 {
 168         struct clsact_sched_data *q = qdisc_priv(sch);
 169 
 170         switch (cl) {
 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;
 175         default:
 176                 return NULL;
 177         }
 178 }
 179 
 180 static void clsact_ingress_block_set(struct Qdisc *sch, u32 block_index)
 181 {
 182         struct clsact_sched_data *q = qdisc_priv(sch);
 183 
 184         q->ingress_block_info.block_index = block_index;
 185 }
 186 
 187 static void clsact_egress_block_set(struct Qdisc *sch, u32 block_index)
 188 {
 189         struct clsact_sched_data *q = qdisc_priv(sch);
 190 
 191         q->egress_block_info.block_index = block_index;
 192 }
 193 
 194 static u32 clsact_ingress_block_get(struct Qdisc *sch)
 195 {
 196         struct clsact_sched_data *q = qdisc_priv(sch);
 197 
 198         return q->ingress_block_info.block_index;
 199 }
 200 
 201 static u32 clsact_egress_block_get(struct Qdisc *sch)
 202 {
 203         struct clsact_sched_data *q = qdisc_priv(sch);
 204 
 205         return q->egress_block_info.block_index;
 206 }
 207 
 208 static int clsact_init(struct Qdisc *sch, struct nlattr *opt,
 209                        struct netlink_ext_ack *extack)
 210 {
 211         struct clsact_sched_data *q = qdisc_priv(sch);
 212         struct net_device *dev = qdisc_dev(sch);
 213         int err;
 214 
 215         net_inc_ingress_queue();
 216         net_inc_egress_queue();
 217 
 218         mini_qdisc_pair_init(&q->miniqp_ingress, sch, &dev->miniq_ingress);
 219 
 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;
 223 
 224         err = tcf_block_get_ext(&q->ingress_block, sch, &q->ingress_block_info,
 225                                 extack);
 226         if (err)
 227                 return err;
 228 
 229         mini_qdisc_pair_init(&q->miniqp_egress, sch, &dev->miniq_egress);
 230 
 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;
 234 
 235         return tcf_block_get_ext(&q->egress_block, sch, &q->egress_block_info, extack);
 236 }
 237 
 238 static void clsact_destroy(struct Qdisc *sch)
 239 {
 240         struct clsact_sched_data *q = qdisc_priv(sch);
 241 
 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);
 244 
 245         net_dec_ingress_queue();
 246         net_dec_egress_queue();
 247 }
 248 
 249 static const struct Qdisc_class_ops clsact_class_ops = {
 250         .flags          =       QDISC_CLASS_OPS_DOIT_UNLOCKED,
 251         .leaf           =       ingress_leaf,
 252         .find           =       clsact_find,
 253         .walk           =       ingress_walk,
 254         .tcf_block      =       clsact_tcf_block,
 255         .bind_tcf       =       clsact_bind_filter,
 256         .unbind_tcf     =       ingress_unbind_filter,
 257 };
 258 
 259 static struct Qdisc_ops clsact_qdisc_ops __read_mostly = {
 260         .cl_ops                 =       &clsact_class_ops,
 261         .id                     =       "clsact",
 262         .priv_size              =       sizeof(struct clsact_sched_data),
 263         .static_flags           =       TCQ_F_CPUSTATS,
 264         .init                   =       clsact_init,
 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,
 272 };
 273 
 274 static int __init ingress_module_init(void)
 275 {
 276         int ret;
 277 
 278         ret = register_qdisc(&ingress_qdisc_ops);
 279         if (!ret) {
 280                 ret = register_qdisc(&clsact_qdisc_ops);
 281                 if (ret)
 282                         unregister_qdisc(&ingress_qdisc_ops);
 283         }
 284 
 285         return ret;
 286 }
 287 
 288 static void __exit ingress_module_exit(void)
 289 {
 290         unregister_qdisc(&ingress_qdisc_ops);
 291         unregister_qdisc(&clsact_qdisc_ops);
 292 }
 293 
 294 module_init(ingress_module_init);
 295 module_exit(ingress_module_exit);
 296 
 297 MODULE_ALIAS("sch_clsact");
 298 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */