act_gact.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * net/sched/act_gact.c Generic actions
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version
  7. * 2 of the License, or (at your option) any later version.
  8. *
  9. * copyright Jamal Hadi Salim (2002-4)
  10. *
  11. */
  12. #include <linux/types.h>
  13. #include <linux/kernel.h>
  14. #include <linux/string.h>
  15. #include <linux/errno.h>
  16. #include <linux/skbuff.h>
  17. #include <linux/rtnetlink.h>
  18. #include <linux/module.h>
  19. #include <linux/init.h>
  20. #include <net/netlink.h>
  21. #include <net/pkt_sched.h>
  22. #include <linux/tc_act/tc_gact.h>
  23. #include <net/tc_act/tc_gact.h>
  24. #define GACT_TAB_MASK 15
  25. #ifdef CONFIG_GACT_PROB
  26. static int gact_net_rand(struct tcf_gact *gact)
  27. {
  28. if (!gact->tcfg_pval || prandom_u32() % gact->tcfg_pval)
  29. return gact->tcf_action;
  30. return gact->tcfg_paction;
  31. }
  32. static int gact_determ(struct tcf_gact *gact)
  33. {
  34. if (!gact->tcfg_pval || gact->tcf_bstats.packets % gact->tcfg_pval)
  35. return gact->tcf_action;
  36. return gact->tcfg_paction;
  37. }
  38. typedef int (*g_rand)(struct tcf_gact *gact);
  39. static g_rand gact_rand[MAX_RAND] = { NULL, gact_net_rand, gact_determ };
  40. #endif /* CONFIG_GACT_PROB */
  41. static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
  42. [TCA_GACT_PARMS] = { .len = sizeof(struct tc_gact) },
  43. [TCA_GACT_PROB] = { .len = sizeof(struct tc_gact_p) },
  44. };
  45. static int tcf_gact_init(struct net *net, struct nlattr *nla,
  46. struct nlattr *est, struct tc_action *a,
  47. int ovr, int bind)
  48. {
  49. struct nlattr *tb[TCA_GACT_MAX + 1];
  50. struct tc_gact *parm;
  51. struct tcf_gact *gact;
  52. int ret = 0;
  53. int err;
  54. #ifdef CONFIG_GACT_PROB
  55. struct tc_gact_p *p_parm = NULL;
  56. #endif
  57. if (nla == NULL)
  58. return -EINVAL;
  59. err = nla_parse_nested(tb, TCA_GACT_MAX, nla, gact_policy);
  60. if (err < 0)
  61. return err;
  62. if (tb[TCA_GACT_PARMS] == NULL)
  63. return -EINVAL;
  64. parm = nla_data(tb[TCA_GACT_PARMS]);
  65. #ifndef CONFIG_GACT_PROB
  66. if (tb[TCA_GACT_PROB] != NULL)
  67. return -EOPNOTSUPP;
  68. #else
  69. if (tb[TCA_GACT_PROB]) {
  70. p_parm = nla_data(tb[TCA_GACT_PROB]);
  71. if (p_parm->ptype >= MAX_RAND)
  72. return -EINVAL;
  73. }
  74. #endif
  75. if (!tcf_hash_check(parm->index, a, bind)) {
  76. ret = tcf_hash_create(parm->index, est, a, sizeof(*gact), bind);
  77. if (ret)
  78. return ret;
  79. ret = ACT_P_CREATED;
  80. } else {
  81. if (bind)/* dont override defaults */
  82. return 0;
  83. tcf_hash_release(a, bind);
  84. if (!ovr)
  85. return -EEXIST;
  86. }
  87. gact = to_gact(a);
  88. spin_lock_bh(&gact->tcf_lock);
  89. gact->tcf_action = parm->action;
  90. #ifdef CONFIG_GACT_PROB
  91. if (p_parm) {
  92. gact->tcfg_paction = p_parm->paction;
  93. gact->tcfg_pval = p_parm->pval;
  94. gact->tcfg_ptype = p_parm->ptype;
  95. }
  96. #endif
  97. spin_unlock_bh(&gact->tcf_lock);
  98. if (ret == ACT_P_CREATED)
  99. tcf_hash_insert(a);
  100. return ret;
  101. }
  102. static int tcf_gact(struct sk_buff *skb, const struct tc_action *a,
  103. struct tcf_result *res)
  104. {
  105. struct tcf_gact *gact = a->priv;
  106. int action = TC_ACT_SHOT;
  107. spin_lock(&gact->tcf_lock);
  108. #ifdef CONFIG_GACT_PROB
  109. if (gact->tcfg_ptype)
  110. action = gact_rand[gact->tcfg_ptype](gact);
  111. else
  112. action = gact->tcf_action;
  113. #else
  114. action = gact->tcf_action;
  115. #endif
  116. gact->tcf_bstats.bytes += qdisc_pkt_len(skb);
  117. gact->tcf_bstats.packets++;
  118. if (action == TC_ACT_SHOT)
  119. gact->tcf_qstats.drops++;
  120. gact->tcf_tm.lastuse = jiffies;
  121. spin_unlock(&gact->tcf_lock);
  122. return action;
  123. }
  124. static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
  125. {
  126. unsigned char *b = skb_tail_pointer(skb);
  127. struct tcf_gact *gact = a->priv;
  128. struct tc_gact opt = {
  129. .index = gact->tcf_index,
  130. .refcnt = gact->tcf_refcnt - ref,
  131. .bindcnt = gact->tcf_bindcnt - bind,
  132. .action = gact->tcf_action,
  133. };
  134. struct tcf_t t;
  135. if (nla_put(skb, TCA_GACT_PARMS, sizeof(opt), &opt))
  136. goto nla_put_failure;
  137. #ifdef CONFIG_GACT_PROB
  138. if (gact->tcfg_ptype) {
  139. struct tc_gact_p p_opt = {
  140. .paction = gact->tcfg_paction,
  141. .pval = gact->tcfg_pval,
  142. .ptype = gact->tcfg_ptype,
  143. };
  144. if (nla_put(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt))
  145. goto nla_put_failure;
  146. }
  147. #endif
  148. t.install = jiffies_to_clock_t(jiffies - gact->tcf_tm.install);
  149. t.lastuse = jiffies_to_clock_t(jiffies - gact->tcf_tm.lastuse);
  150. t.expires = jiffies_to_clock_t(gact->tcf_tm.expires);
  151. if (nla_put(skb, TCA_GACT_TM, sizeof(t), &t))
  152. goto nla_put_failure;
  153. return skb->len;
  154. nla_put_failure:
  155. nlmsg_trim(skb, b);
  156. return -1;
  157. }
  158. static struct tc_action_ops act_gact_ops = {
  159. .kind = "gact",
  160. .type = TCA_ACT_GACT,
  161. .owner = THIS_MODULE,
  162. .act = tcf_gact,
  163. .dump = tcf_gact_dump,
  164. .init = tcf_gact_init,
  165. };
  166. MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
  167. MODULE_DESCRIPTION("Generic Classifier actions");
  168. MODULE_LICENSE("GPL");
  169. static int __init gact_init_module(void)
  170. {
  171. #ifdef CONFIG_GACT_PROB
  172. pr_info("GACT probability on\n");
  173. #else
  174. pr_info("GACT probability NOT on\n");
  175. #endif
  176. return tcf_register_action(&act_gact_ops, GACT_TAB_MASK);
  177. }
  178. static void __exit gact_cleanup_module(void)
  179. {
  180. tcf_unregister_action(&act_gact_ops);
  181. }
  182. module_init(gact_init_module);
  183. module_exit(gact_cleanup_module);