police.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * net/sched/police.c Input police filter.
  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.  * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  10.  */
  11. #include <asm/uaccess.h>
  12. #include <asm/system.h>
  13. #include <asm/bitops.h>
  14. #include <linux/config.h>
  15. #include <linux/types.h>
  16. #include <linux/kernel.h>
  17. #include <linux/sched.h>
  18. #include <linux/string.h>
  19. #include <linux/mm.h>
  20. #include <linux/socket.h>
  21. #include <linux/sockios.h>
  22. #include <linux/in.h>
  23. #include <linux/errno.h>
  24. #include <linux/interrupt.h>
  25. #include <linux/netdevice.h>
  26. #include <linux/skbuff.h>
  27. #include <linux/rtnetlink.h>
  28. #include <linux/init.h>
  29. #include <linux/proc_fs.h>
  30. #include <net/sock.h>
  31. #include <net/pkt_sched.h>
  32. #define L2T(p,L)   ((p)->R_tab->data[(L)>>(p)->R_tab->rate.cell_log])
  33. #define L2T_P(p,L) ((p)->P_tab->data[(L)>>(p)->P_tab->rate.cell_log])
  34. static u32 idx_gen;
  35. static struct tcf_police *tcf_police_ht[16];
  36. /* Policer hash table lock */
  37. static rwlock_t police_lock = RW_LOCK_UNLOCKED;
  38. /* Each policer is serialized by its individual spinlock */
  39. static __inline__ unsigned tcf_police_hash(u32 index)
  40. {
  41. return index&0xF;
  42. }
  43. static __inline__ struct tcf_police * tcf_police_lookup(u32 index)
  44. {
  45. struct tcf_police *p;
  46. read_lock(&police_lock);
  47. for (p = tcf_police_ht[tcf_police_hash(index)]; p; p = p->next) {
  48. if (p->index == index)
  49. break;
  50. }
  51. read_unlock(&police_lock);
  52. return p;
  53. }
  54. static __inline__ u32 tcf_police_new_index(void)
  55. {
  56. do {
  57. if (++idx_gen == 0)
  58. idx_gen = 1;
  59. } while (tcf_police_lookup(idx_gen));
  60. return idx_gen;
  61. }
  62. void tcf_police_destroy(struct tcf_police *p)
  63. {
  64. unsigned h = tcf_police_hash(p->index);
  65. struct tcf_police **p1p;
  66. for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->next) {
  67. if (*p1p == p) {
  68. write_lock_bh(&police_lock);
  69. *p1p = p->next;
  70. write_unlock_bh(&police_lock);
  71. #ifdef CONFIG_NET_ESTIMATOR
  72. qdisc_kill_estimator(&p->stats);
  73. #endif
  74. if (p->R_tab)
  75. qdisc_put_rtab(p->R_tab);
  76. if (p->P_tab)
  77. qdisc_put_rtab(p->P_tab);
  78. kfree(p);
  79. return;
  80. }
  81. }
  82. BUG_TRAP(0);
  83. }
  84. struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est)
  85. {
  86. unsigned h;
  87. struct tcf_police *p;
  88. struct rtattr *tb[TCA_POLICE_MAX];
  89. struct tc_police *parm;
  90. if (rtattr_parse(tb, TCA_POLICE_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
  91. return NULL;
  92. if (tb[TCA_POLICE_TBF-1] == NULL)
  93. return NULL;
  94. parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
  95. if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) {
  96. p->refcnt++;
  97. return p;
  98. }
  99. p = kmalloc(sizeof(*p), GFP_KERNEL);
  100. if (p == NULL)
  101. return NULL;
  102. memset(p, 0, sizeof(*p));
  103. p->refcnt = 1;
  104. spin_lock_init(&p->lock);
  105. p->stats.lock = &p->lock;
  106. if (parm->rate.rate) {
  107. if ((p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1])) == NULL)
  108. goto failure;
  109. if (parm->peakrate.rate &&
  110.     (p->P_tab = qdisc_get_rtab(&parm->peakrate, tb[TCA_POLICE_PEAKRATE-1])) == NULL)
  111. goto failure;
  112. }
  113. if (tb[TCA_POLICE_RESULT-1])
  114. p->result = *(int*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
  115. #ifdef CONFIG_NET_ESTIMATOR
  116. if (tb[TCA_POLICE_AVRATE-1])
  117. p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
  118. #endif
  119. p->toks = p->burst = parm->burst;
  120. p->mtu = parm->mtu;
  121. if (p->mtu == 0) {
  122. p->mtu = ~0;
  123. if (p->R_tab)
  124. p->mtu = 255<<p->R_tab->rate.cell_log;
  125. }
  126. if (p->P_tab)
  127. p->ptoks = L2T_P(p, p->mtu);
  128. PSCHED_GET_TIME(p->t_c);
  129. p->index = parm->index ? : tcf_police_new_index();
  130. p->action = parm->action;
  131. #ifdef CONFIG_NET_ESTIMATOR
  132. if (est)
  133. qdisc_new_estimator(&p->stats, est);
  134. #endif
  135. h = tcf_police_hash(p->index);
  136. write_lock_bh(&police_lock);
  137. p->next = tcf_police_ht[h];
  138. tcf_police_ht[h] = p;
  139. write_unlock_bh(&police_lock);
  140. return p;
  141. failure:
  142. if (p->R_tab)
  143. qdisc_put_rtab(p->R_tab);
  144. kfree(p);
  145. return NULL;
  146. }
  147. int tcf_police(struct sk_buff *skb, struct tcf_police *p)
  148. {
  149. psched_time_t now;
  150. long toks;
  151. long ptoks = 0;
  152. spin_lock(&p->lock);
  153. p->stats.bytes += skb->len;
  154. p->stats.packets++;
  155. #ifdef CONFIG_NET_ESTIMATOR
  156. if (p->ewma_rate && p->stats.bps >= p->ewma_rate) {
  157. p->stats.overlimits++;
  158. spin_unlock(&p->lock);
  159. return p->action;
  160. }
  161. #endif
  162. if (skb->len <= p->mtu) {
  163. if (p->R_tab == NULL) {
  164. spin_unlock(&p->lock);
  165. return p->result;
  166. }
  167. PSCHED_GET_TIME(now);
  168. toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst, 0);
  169. if (p->P_tab) {
  170. ptoks = toks + p->ptoks;
  171. if (ptoks > (long)L2T_P(p, p->mtu))
  172. ptoks = (long)L2T_P(p, p->mtu);
  173. ptoks -= L2T_P(p, skb->len);
  174. }
  175. toks += p->toks;
  176. if (toks > (long)p->burst)
  177. toks = p->burst;
  178. toks -= L2T(p, skb->len);
  179. if ((toks|ptoks) >= 0) {
  180. p->t_c = now;
  181. p->toks = toks;
  182. p->ptoks = ptoks;
  183. spin_unlock(&p->lock);
  184. return p->result;
  185. }
  186. }
  187. p->stats.overlimits++;
  188. spin_unlock(&p->lock);
  189. return p->action;
  190. }
  191. int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p)
  192. {
  193. unsigned char  *b = skb->tail;
  194. struct tc_police opt;
  195. opt.index = p->index;
  196. opt.action = p->action;
  197. opt.mtu = p->mtu;
  198. opt.burst = p->burst;
  199. if (p->R_tab)
  200. opt.rate = p->R_tab->rate;
  201. else
  202. memset(&opt.rate, 0, sizeof(opt.rate));
  203. if (p->P_tab)
  204. opt.peakrate = p->P_tab->rate;
  205. else
  206. memset(&opt.peakrate, 0, sizeof(opt.peakrate));
  207. RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
  208. if (p->result)
  209. RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result);
  210. #ifdef CONFIG_NET_ESTIMATOR
  211. if (p->ewma_rate)
  212. RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate);
  213. #endif
  214. return skb->len;
  215. rtattr_failure:
  216. skb_trim(skb, b - skb->data);
  217. return -1;
  218. }