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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* net/sched/sch_ingress.c - Ingress qdisc 
  2.  *              This program is free software; you can redistribute it and/or
  3.  *              modify it under the terms of the GNU General Public License
  4.  *              as published by the Free Software Foundation; either version
  5.  *              2 of the License, or (at your option) any later version.
  6.  *
  7.  * Authors:     Jamal Hadi Salim 1999
  8.  */
  9. #include <linux/config.h>
  10. #include <linux/module.h>
  11. #include <linux/types.h>
  12. #include <linux/skbuff.h>
  13. #include <linux/netdevice.h>
  14. #include <linux/rtnetlink.h>
  15. #include <linux/netfilter_ipv4.h>
  16. #include <linux/netfilter.h>
  17. #include <net/pkt_sched.h>
  18. #include <asm/byteorder.h>
  19. #include <asm/uaccess.h>
  20. #include <asm/smp.h>
  21. #include <linux/kmod.h>
  22. #include <linux/stat.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/list.h>
  25. #undef DEBUG_INGRESS
  26. #ifdef DEBUG_INGRESS  /* control */
  27. #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
  28. #else
  29. #define DPRINTK(format,args...)
  30. #endif
  31. #if 0  /* data */
  32. #define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
  33. #else
  34. #define D2PRINTK(format,args...)
  35. #endif
  36. #define PRIV(sch) ((struct ingress_qdisc_data *) (sch)->data)
  37. struct ingress_qdisc_data {
  38. struct Qdisc *q;
  39. struct tcf_proto *filter_list;
  40. };
  41. /* ------------------------- Class/flow operations ------------------------- */
  42. static int ingress_graft(struct Qdisc *sch,unsigned long arg,
  43.     struct Qdisc *new,struct Qdisc **old)
  44. {
  45. #ifdef DEBUG_INGRESS
  46. struct ingress_qdisc_data *p = PRIV(sch);
  47. #endif
  48. DPRINTK("ingress_graft(sch %p,[qdisc %p],new %p,old %p)n",
  49. sch, p, new, old);
  50. DPRINTK("n ingress_graft: You cannot add qdiscs to classes");
  51.         return 1;
  52. }
  53. static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
  54. {
  55. return NULL;
  56. }
  57. static unsigned long ingress_get(struct Qdisc *sch,u32 classid)
  58. {
  59. #ifdef DEBUG_INGRESS
  60. struct ingress_qdisc_data *p = PRIV(sch);
  61. #endif
  62. DPRINTK("ingress_get(sch %p,[qdisc %p],classid %x)n", sch, p, classid);
  63. return TC_H_MIN(classid) + 1;
  64. }
  65. static unsigned long ingress_bind_filter(struct Qdisc *sch,
  66.     unsigned long parent, u32 classid)
  67. {
  68. return ingress_get(sch, classid);
  69. }
  70. static void ingress_put(struct Qdisc *sch, unsigned long cl)
  71. {
  72. }
  73. static int ingress_change(struct Qdisc *sch, u32 classid, u32 parent,
  74.     struct rtattr **tca, unsigned long *arg)
  75. {
  76. #ifdef DEBUG_INGRESS
  77. struct ingress_qdisc_data *p = PRIV(sch);
  78. #endif
  79. DPRINTK("ingress_change(sch %p,[qdisc %p],classid %x,parent %x),"
  80. "arg 0x%lxn", sch, p, classid, parent, *arg);
  81. DPRINTK("No effect. sch_ingress doesnt maintain classes at the moment");
  82. return 0;
  83. }
  84. static void ingress_walk(struct Qdisc *sch,struct qdisc_walker *walker)
  85. {
  86. #ifdef DEBUG_INGRESS
  87. struct ingress_qdisc_data *p = PRIV(sch);
  88. #endif
  89. DPRINTK("ingress_walk(sch %p,[qdisc %p],walker %p)n", sch, p, walker);
  90. DPRINTK("No effect. sch_ingress doesnt maintain classes at the moment");
  91. }
  92. static struct tcf_proto **ingress_find_tcf(struct Qdisc *sch,unsigned long cl)
  93. {
  94. struct ingress_qdisc_data *p = PRIV(sch);
  95. return &p->filter_list;
  96. }
  97. /* --------------------------- Qdisc operations ---------------------------- */
  98. static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch)
  99. {
  100. struct ingress_qdisc_data *p = PRIV(sch);
  101. struct tcf_result res;
  102. int result;
  103. D2PRINTK("ingress_enqueue(skb %p,sch %p,[qdisc %p])n", skb, sch, p);
  104. result = tc_classify(skb, p->filter_list, &res);
  105. D2PRINTK("result %d class 0x%04xn", result, res.classid);
  106. /*
  107.  * Unlike normal "enqueue" functions, ingress_enqueue returns a
  108.  * firewall FW_* code.
  109.  */
  110. switch (result) {
  111. #ifdef CONFIG_NET_CLS_POLICE
  112. case TC_POLICE_SHOT:
  113. result = NF_DROP;
  114. break;
  115. case TC_POLICE_RECLASSIFY: /* DSCP remarking here ? */
  116. case TC_POLICE_OK:
  117. case TC_POLICE_UNSPEC:
  118. default:
  119. result = NF_ACCEPT;
  120. break;
  121. #endif
  122. };
  123. skb->tc_index = TC_H_MIN(res.classid);
  124. return result;
  125. }
  126. static struct sk_buff *ingress_dequeue(struct Qdisc *sch)
  127. {
  128. /*
  129. struct ingress_qdisc_data *p = PRIV(sch);
  130. D2PRINTK("ingress_dequeue(sch %p,[qdisc %p])n",sch,PRIV(p));
  131. */
  132. return NULL;
  133. }
  134. static int ingress_requeue(struct sk_buff *skb,struct Qdisc *sch)
  135. {
  136. /*
  137. struct ingress_qdisc_data *p = PRIV(sch);
  138. D2PRINTK("ingress_requeue(skb %p,sch %p,[qdisc %p])n",skb,sch,PRIV(p));
  139. */
  140. return 0;
  141. }
  142. static int ingress_drop(struct Qdisc *sch)
  143. {
  144. #ifdef DEBUG_INGRESS
  145. struct ingress_qdisc_data *p = PRIV(sch);
  146. #endif
  147. DPRINTK("ingress_drop(sch %p,[qdisc %p])n", sch, p);
  148. return 0;
  149. }
  150. static unsigned int
  151. ing_hook(unsigned int hook, struct sk_buff **pskb,
  152.                              const struct net_device *indev,
  153.                              const struct net_device *outdev,
  154.                      int (*okfn)(struct sk_buff *))
  155. {
  156. struct Qdisc *q;
  157. struct sk_buff *skb = *pskb;
  158.         struct net_device *dev = skb->dev;
  159. int fwres=NF_ACCEPT;
  160. DPRINTK("ing_hook: skb %s dev=%s len=%un",
  161. skb->sk ? "(owned)" : "(unowned)",
  162. skb->dev ? (*pskb)->dev->name : "(no dev)",
  163. skb->len);
  164. /* 
  165. revisit later: Use a private since lock dev->queue_lock is also
  166. used on the egress (might slow things for an iota)
  167. */
  168. if (dev->qdisc_ingress) {
  169. spin_lock(&dev->queue_lock);
  170. if ((q = dev->qdisc_ingress) != NULL)
  171. fwres = q->enqueue(skb, q);
  172. spin_unlock(&dev->queue_lock);
  173.         }
  174. return fwres;
  175. }
  176. /* after ipt_filter */
  177. static struct nf_hook_ops ing_ops =
  178. {
  179. { NULL, NULL},
  180. ing_hook,
  181. PF_INET,
  182. NF_IP_PRE_ROUTING,
  183. NF_IP_PRI_FILTER + 1
  184. };
  185. int ingress_init(struct Qdisc *sch,struct rtattr *opt)
  186. {
  187. struct ingress_qdisc_data *p = PRIV(sch);
  188. DPRINTK("ingress_init(sch %p,[qdisc %p],opt %p)n",sch,p,opt);
  189. memset(p, 0, sizeof(*p));
  190. p->filter_list = NULL;
  191. p->q = &noop_qdisc;
  192. #ifndef MODULE
  193. if (nf_register_hook(&ing_ops) < 0) {
  194. printk("Unable to register ingress n");
  195. goto error;
  196. }
  197. #endif
  198. DPRINTK("ingress_init: qdisc %pn", sch);
  199. MOD_INC_USE_COUNT;
  200. return 0;
  201. #ifndef MODULE
  202. error:
  203. #endif
  204. return -EINVAL;
  205. }
  206. static void ingress_reset(struct Qdisc *sch)
  207. {
  208. struct ingress_qdisc_data *p = PRIV(sch);
  209. DPRINTK("ingress_reset(sch %p,[qdisc %p])n", sch, p);
  210. /*
  211. #if 0
  212. */
  213. /* for future use */
  214. qdisc_reset(p->q);
  215. /*
  216. #endif
  217. */
  218. }
  219. /* ------------------------------------------------------------- */
  220. /* ------------------------------------------------------------- */
  221. static void ingress_destroy(struct Qdisc *sch)
  222. {
  223. struct ingress_qdisc_data *p = PRIV(sch);
  224. struct tcf_proto *tp;
  225. DPRINTK("ingress_destroy(sch %p,[qdisc %p])n", sch, p);
  226. while (p->filter_list) {
  227. tp = p->filter_list;
  228. p->filter_list = tp->next;
  229. tp->ops->destroy(tp);
  230. }
  231. memset(p, 0, sizeof(*p));
  232. p->filter_list = NULL;
  233. #if 0
  234. /* for future use */
  235. qdisc_destroy(p->q);
  236. #endif
  237. #ifndef MODULE
  238. nf_unregister_hook(&ing_ops);
  239. #endif
  240. MOD_DEC_USE_COUNT;
  241. }
  242. static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
  243. {
  244. unsigned char *b = skb->tail;
  245. struct rtattr *rta;
  246. rta = (struct rtattr *) b;
  247. RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
  248. rta->rta_len = skb->tail - b;
  249. return skb->len;
  250. rtattr_failure:
  251. skb_trim(skb, b - skb->data);
  252. return -1;
  253. }
  254. static struct Qdisc_class_ops ingress_class_ops =
  255. {
  256. ingress_graft, /* graft */
  257. ingress_leaf, /* leaf */
  258. ingress_get, /* get */
  259. ingress_put, /* put */
  260. ingress_change, /* change */
  261. NULL, /* delete */
  262. ingress_walk, /* walk */
  263. ingress_find_tcf, /* tcf_chain */
  264. ingress_bind_filter, /* bind_tcf */
  265. ingress_put, /* unbind_tcf */
  266. NULL, /* dump */
  267. };
  268. struct Qdisc_ops ingress_qdisc_ops =
  269. {
  270. NULL, /* next */
  271. &ingress_class_ops, /* cl_ops */
  272. "ingress",
  273. sizeof(struct ingress_qdisc_data),
  274. ingress_enqueue, /* enqueue */
  275. ingress_dequeue, /* dequeue */
  276. ingress_requeue, /* requeue */
  277. ingress_drop, /* drop */
  278. ingress_init, /* init */
  279. ingress_reset, /* reset */
  280. ingress_destroy, /* destroy */
  281. NULL, /* change */
  282. ingress_dump, /* dump */
  283. };
  284. #ifdef MODULE
  285. int init_module(void)
  286. {
  287. int ret = 0;
  288. if ((ret = register_qdisc(&ingress_qdisc_ops)) < 0) {
  289. printk("Unable to register Ingress qdiscn");
  290. return ret;
  291. }
  292.         if (nf_register_hook(&ing_ops) < 0) {
  293. printk("Unable to register ingress on hook n");
  294. unregister_qdisc(&ingress_qdisc_ops);
  295. return 0;
  296. }
  297. return ret;
  298. }
  299. void cleanup_module(void) 
  300. {
  301. nf_unregister_hook(&ing_ops);
  302. unregister_qdisc(&ingress_qdisc_ops);
  303. }
  304. #endif
  305. MODULE_LICENSE("GPL");