sch_ingress.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /* net/sched/sch_ingress.c - Ingress and clsact qdisc
  2. *
  3. * 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. #include <linux/module.h>
  11. #include <linux/types.h>
  12. #include <linux/list.h>
  13. #include <linux/skbuff.h>
  14. #include <linux/rtnetlink.h>
  15. #include <net/netlink.h>
  16. #include <net/pkt_sched.h>
  17. #include <net/pkt_cls.h>
  18. struct ingress_sched_data {
  19. struct tcf_block *block;
  20. };
  21. static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
  22. {
  23. return NULL;
  24. }
  25. static unsigned long ingress_find(struct Qdisc *sch, u32 classid)
  26. {
  27. return TC_H_MIN(classid) + 1;
  28. }
  29. static unsigned long ingress_bind_filter(struct Qdisc *sch,
  30. unsigned long parent, u32 classid)
  31. {
  32. return ingress_find(sch, classid);
  33. }
  34. static void ingress_unbind_filter(struct Qdisc *sch, unsigned long cl)
  35. {
  36. }
  37. static void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker)
  38. {
  39. }
  40. static struct tcf_block *ingress_tcf_block(struct Qdisc *sch, unsigned long cl)
  41. {
  42. struct ingress_sched_data *q = qdisc_priv(sch);
  43. return q->block;
  44. }
  45. static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
  46. {
  47. struct ingress_sched_data *q = qdisc_priv(sch);
  48. struct net_device *dev = qdisc_dev(sch);
  49. int err;
  50. net_inc_ingress_queue();
  51. err = tcf_block_get(&q->block, &dev->ingress_cl_list);
  52. if (err)
  53. return err;
  54. sch->flags |= TCQ_F_CPUSTATS;
  55. return 0;
  56. }
  57. static void ingress_destroy(struct Qdisc *sch)
  58. {
  59. struct ingress_sched_data *q = qdisc_priv(sch);
  60. tcf_block_put(q->block);
  61. net_dec_ingress_queue();
  62. }
  63. static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
  64. {
  65. struct nlattr *nest;
  66. nest = nla_nest_start(skb, TCA_OPTIONS);
  67. if (nest == NULL)
  68. goto nla_put_failure;
  69. return nla_nest_end(skb, nest);
  70. nla_put_failure:
  71. nla_nest_cancel(skb, nest);
  72. return -1;
  73. }
  74. static const struct Qdisc_class_ops ingress_class_ops = {
  75. .leaf = ingress_leaf,
  76. .find = ingress_find,
  77. .walk = ingress_walk,
  78. .tcf_block = ingress_tcf_block,
  79. .bind_tcf = ingress_bind_filter,
  80. .unbind_tcf = ingress_unbind_filter,
  81. };
  82. static struct Qdisc_ops ingress_qdisc_ops __read_mostly = {
  83. .cl_ops = &ingress_class_ops,
  84. .id = "ingress",
  85. .priv_size = sizeof(struct ingress_sched_data),
  86. .init = ingress_init,
  87. .destroy = ingress_destroy,
  88. .dump = ingress_dump,
  89. .owner = THIS_MODULE,
  90. };
  91. struct clsact_sched_data {
  92. struct tcf_block *ingress_block;
  93. struct tcf_block *egress_block;
  94. };
  95. static unsigned long clsact_find(struct Qdisc *sch, u32 classid)
  96. {
  97. switch (TC_H_MIN(classid)) {
  98. case TC_H_MIN(TC_H_MIN_INGRESS):
  99. case TC_H_MIN(TC_H_MIN_EGRESS):
  100. return TC_H_MIN(classid);
  101. default:
  102. return 0;
  103. }
  104. }
  105. static unsigned long clsact_bind_filter(struct Qdisc *sch,
  106. unsigned long parent, u32 classid)
  107. {
  108. return clsact_find(sch, classid);
  109. }
  110. static struct tcf_block *clsact_tcf_block(struct Qdisc *sch, unsigned long cl)
  111. {
  112. struct clsact_sched_data *q = qdisc_priv(sch);
  113. switch (cl) {
  114. case TC_H_MIN(TC_H_MIN_INGRESS):
  115. return q->ingress_block;
  116. case TC_H_MIN(TC_H_MIN_EGRESS):
  117. return q->egress_block;
  118. default:
  119. return NULL;
  120. }
  121. }
  122. static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
  123. {
  124. struct clsact_sched_data *q = qdisc_priv(sch);
  125. struct net_device *dev = qdisc_dev(sch);
  126. int err;
  127. net_inc_ingress_queue();
  128. net_inc_egress_queue();
  129. err = tcf_block_get(&q->ingress_block, &dev->ingress_cl_list);
  130. if (err)
  131. return err;
  132. err = tcf_block_get(&q->egress_block, &dev->egress_cl_list);
  133. if (err)
  134. return err;
  135. sch->flags |= TCQ_F_CPUSTATS;
  136. return 0;
  137. }
  138. static void clsact_destroy(struct Qdisc *sch)
  139. {
  140. struct clsact_sched_data *q = qdisc_priv(sch);
  141. tcf_block_put(q->egress_block);
  142. tcf_block_put(q->ingress_block);
  143. net_dec_ingress_queue();
  144. net_dec_egress_queue();
  145. }
  146. static const struct Qdisc_class_ops clsact_class_ops = {
  147. .leaf = ingress_leaf,
  148. .find = clsact_find,
  149. .walk = ingress_walk,
  150. .tcf_block = clsact_tcf_block,
  151. .bind_tcf = clsact_bind_filter,
  152. .unbind_tcf = ingress_unbind_filter,
  153. };
  154. static struct Qdisc_ops clsact_qdisc_ops __read_mostly = {
  155. .cl_ops = &clsact_class_ops,
  156. .id = "clsact",
  157. .priv_size = sizeof(struct clsact_sched_data),
  158. .init = clsact_init,
  159. .destroy = clsact_destroy,
  160. .dump = ingress_dump,
  161. .owner = THIS_MODULE,
  162. };
  163. static int __init ingress_module_init(void)
  164. {
  165. int ret;
  166. ret = register_qdisc(&ingress_qdisc_ops);
  167. if (!ret) {
  168. ret = register_qdisc(&clsact_qdisc_ops);
  169. if (ret)
  170. unregister_qdisc(&ingress_qdisc_ops);
  171. }
  172. return ret;
  173. }
  174. static void __exit ingress_module_exit(void)
  175. {
  176. unregister_qdisc(&ingress_qdisc_ops);
  177. unregister_qdisc(&clsact_qdisc_ops);
  178. }
  179. module_init(ingress_module_init);
  180. module_exit(ingress_module_exit);
  181. MODULE_ALIAS("sch_clsact");
  182. MODULE_LICENSE("GPL");