pkt_sched.h
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:12k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. #ifndef __NET_PKT_SCHED_H
  2. #define __NET_PKT_SCHED_H
  3. #define PSCHED_GETTIMEOFDAY 1
  4. #define PSCHED_JIFFIES  2
  5. #define PSCHED_CPU  3
  6. #define PSCHED_CLOCK_SOURCE PSCHED_JIFFIES
  7. #include <linux/config.h>
  8. #include <linux/types.h>
  9. #include <linux/pkt_sched.h>
  10. #include <net/pkt_cls.h>
  11. #ifdef CONFIG_X86_TSC
  12. #include <asm/msr.h>
  13. #endif
  14. struct rtattr;
  15. struct Qdisc;
  16. struct qdisc_walker
  17. {
  18. int stop;
  19. int skip;
  20. int count;
  21. int (*fn)(struct Qdisc *, unsigned long cl, struct qdisc_walker *);
  22. };
  23. struct Qdisc_class_ops
  24. {
  25. /* Child qdisc manipulation */
  26. int (*graft)(struct Qdisc *, unsigned long cl, struct Qdisc *, struct Qdisc **);
  27. struct Qdisc * (*leaf)(struct Qdisc *, unsigned long cl);
  28. /* Class manipulation routines */
  29. unsigned long (*get)(struct Qdisc *, u32 classid);
  30. void (*put)(struct Qdisc *, unsigned long);
  31. int (*change)(struct Qdisc *, u32, u32, struct rtattr **, unsigned long *);
  32. int (*delete)(struct Qdisc *, unsigned long);
  33. void (*walk)(struct Qdisc *, struct qdisc_walker * arg);
  34. /* Filter manipulation */
  35. struct tcf_proto ** (*tcf_chain)(struct Qdisc *, unsigned long);
  36. unsigned long (*bind_tcf)(struct Qdisc *, unsigned long, u32 classid);
  37. void (*unbind_tcf)(struct Qdisc *, unsigned long);
  38. /* rtnetlink specific */
  39. int (*dump)(struct Qdisc *, unsigned long, struct sk_buff *skb, struct tcmsg*);
  40. };
  41. struct Qdisc_ops
  42. {
  43. struct Qdisc_ops *next;
  44. struct Qdisc_class_ops *cl_ops;
  45. char id[IFNAMSIZ];
  46. int priv_size;
  47. int  (*enqueue)(struct sk_buff *, struct Qdisc *);
  48. struct sk_buff * (*dequeue)(struct Qdisc *);
  49. int  (*requeue)(struct sk_buff *, struct Qdisc *);
  50. int (*drop)(struct Qdisc *);
  51. int (*init)(struct Qdisc *, struct rtattr *arg);
  52. void (*reset)(struct Qdisc *);
  53. void (*destroy)(struct Qdisc *);
  54. int (*change)(struct Qdisc *, struct rtattr *arg);
  55. int (*dump)(struct Qdisc *, struct sk_buff *);
  56. };
  57. extern rwlock_t qdisc_tree_lock;
  58. struct Qdisc
  59. {
  60. int  (*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
  61. struct sk_buff * (*dequeue)(struct Qdisc *dev);
  62. unsigned flags;
  63. #define TCQ_F_BUILTIN 1
  64. #define TCQ_F_THROTTLED 2
  65. #define TCQ_F_INGRES 4
  66. struct Qdisc_ops *ops;
  67. struct Qdisc *next;
  68. u32 handle;
  69. atomic_t refcnt;
  70. struct sk_buff_head q;
  71. struct net_device *dev;
  72. struct tc_stats stats;
  73. int (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q);
  74. /* This field is deprecated, but it is still used by CBQ
  75.  * and it will live until better solution will be invented.
  76.  */
  77. struct Qdisc *__parent;
  78. char data[0];
  79. };
  80. struct qdisc_rate_table
  81. {
  82. struct tc_ratespec rate;
  83. u32 data[256];
  84. struct qdisc_rate_table *next;
  85. int refcnt;
  86. };
  87. static inline void sch_tree_lock(struct Qdisc *q)
  88. {
  89. write_lock(&qdisc_tree_lock);
  90. spin_lock_bh(&q->dev->queue_lock);
  91. }
  92. static inline void sch_tree_unlock(struct Qdisc *q)
  93. {
  94. spin_unlock_bh(&q->dev->queue_lock);
  95. write_unlock(&qdisc_tree_lock);
  96. }
  97. static inline void tcf_tree_lock(struct tcf_proto *tp)
  98. {
  99. write_lock(&qdisc_tree_lock);
  100. spin_lock_bh(&tp->q->dev->queue_lock);
  101. }
  102. static inline void tcf_tree_unlock(struct tcf_proto *tp)
  103. {
  104. spin_unlock_bh(&tp->q->dev->queue_lock);
  105. write_unlock(&qdisc_tree_lock);
  106. }
  107. static inline unsigned long
  108. cls_set_class(struct tcf_proto *tp, unsigned long *clp, unsigned long cl)
  109. {
  110. unsigned long old_cl;
  111. tcf_tree_lock(tp);
  112. old_cl = *clp;
  113. *clp = cl;
  114. tcf_tree_unlock(tp);
  115. return old_cl;
  116. }
  117. static inline unsigned long
  118. __cls_set_class(unsigned long *clp, unsigned long cl)
  119. {
  120. unsigned long old_cl;
  121. old_cl = *clp;
  122. *clp = cl;
  123. return old_cl;
  124. }
  125. /* 
  126.    Timer resolution MUST BE < 10% of min_schedulable_packet_size/bandwidth
  127.    
  128.    Normal IP packet size ~ 512byte, hence:
  129.    0.5Kbyte/1Mbyte/sec = 0.5msec, so that we need 50usec timer for
  130.    10Mbit ethernet.
  131.    10msec resolution -> <50Kbit/sec.
  132.    
  133.    The result: [34]86 is not good choice for QoS router :-(
  134.    The things are not so bad, because we may use artifical
  135.    clock evaluated by integration of network data flow
  136.    in the most critical places.
  137.    Note: we do not use fastgettimeofday.
  138.    The reason is that, when it is not the same thing as
  139.    gettimeofday, it returns invalid timestamp, which is
  140.    not updated, when net_bh is active.
  141.    So, use PSCHED_CLOCK_SOURCE = PSCHED_CPU on alpha and pentiums
  142.    with rtdsc. And PSCHED_JIFFIES on all other architectures, including [34]86
  143.    and pentiums without rtdsc.
  144.    You can use PSCHED_GETTIMEOFDAY on another architectures,
  145.    which have fast and precise clock source, but it is too expensive.
  146.  */
  147. /* General note about internal clock.
  148.    Any clock source returns time intervals, measured in units
  149.    close to 1usec. With source PSCHED_GETTIMEOFDAY it is precisely
  150.    microseconds, otherwise something close but different chosen to minimize
  151.    arithmetic cost. Ratio usec/internal untis in form nominator/denominator
  152.    may be read from /proc/net/psched.
  153.  */
  154. #if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY
  155. typedef struct timeval psched_time_t;
  156. typedef long psched_tdiff_t;
  157. #define PSCHED_GET_TIME(stamp) do_gettimeofday(&(stamp))
  158. #define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ))
  159. #define PSCHED_EXPORTLIST EXPORT_SYMBOL(psched_tod_diff);
  160. #else /* PSCHED_CLOCK_SOURCE != PSCHED_GETTIMEOFDAY */
  161. #define PSCHED_EXPORTLIST PSCHED_EXPORTLIST_1 PSCHED_EXPORTLIST_2
  162. typedef u64 psched_time_t;
  163. typedef long psched_tdiff_t;
  164. extern psched_time_t psched_time_base;
  165. #if PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES
  166. #if HZ == 100
  167. #define PSCHED_JSCALE 13
  168. #elif HZ == 1024
  169. #define PSCHED_JSCALE 10
  170. #else
  171. #define PSCHED_JSCALE 0
  172. #endif
  173. #define PSCHED_EXPORTLIST_2
  174. #if BITS_PER_LONG <= 32
  175. #define PSCHED_WATCHER unsigned long
  176. extern PSCHED_WATCHER psched_time_mark;
  177. #define PSCHED_GET_TIME(stamp) ((stamp) = psched_time_base + (((unsigned long)(jiffies-psched_time_mark))<<PSCHED_JSCALE))
  178. #define PSCHED_EXPORTLIST_1 EXPORT_SYMBOL(psched_time_base); 
  179.                             EXPORT_SYMBOL(psched_time_mark);
  180. #else
  181. #define PSCHED_GET_TIME(stamp) ((stamp) = (jiffies<<PSCHED_JSCALE))
  182. #define PSCHED_EXPORTLIST_1 
  183. #endif
  184. #define PSCHED_US2JIFFIE(delay) (((delay)+(1<<PSCHED_JSCALE)-1)>>PSCHED_JSCALE)
  185. #elif PSCHED_CLOCK_SOURCE == PSCHED_CPU
  186. extern psched_tdiff_t psched_clock_per_hz;
  187. extern int psched_clock_scale;
  188. #define PSCHED_EXPORTLIST_2 EXPORT_SYMBOL(psched_clock_per_hz); 
  189.                             EXPORT_SYMBOL(psched_clock_scale);
  190. #define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz)
  191. #ifdef CONFIG_X86_TSC
  192. #define PSCHED_GET_TIME(stamp) 
  193. ({ u64 __cur; 
  194.    rdtscll(__cur); 
  195.    (stamp) = __cur>>psched_clock_scale; 
  196. })
  197. #define PSCHED_EXPORTLIST_1
  198. #elif defined (__alpha__)
  199. #define PSCHED_WATCHER u32
  200. extern PSCHED_WATCHER psched_time_mark;
  201. #define PSCHED_GET_TIME(stamp) 
  202. ({ u32 __res; 
  203.    __asm__ __volatile__ ("rpcc %0" : "r="(__res)); 
  204.    if (__res <= psched_time_mark) psched_time_base += 0x100000000UL; 
  205.    psched_time_mark = __res; 
  206.    (stamp) = (psched_time_base + __res)>>psched_clock_scale; 
  207. })
  208. #define PSCHED_EXPORTLIST_1 EXPORT_SYMBOL(psched_time_base); 
  209.                             EXPORT_SYMBOL(psched_time_mark);
  210. #else
  211. #error PSCHED_CLOCK_SOURCE=PSCHED_CPU is not supported on this arch.
  212. #endif /* ARCH */
  213. #endif /* PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES */
  214. #endif /* PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY */
  215. #if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY
  216. #define PSCHED_TDIFF(tv1, tv2) 
  217. ({ 
  218.    int __delta_sec = (tv1).tv_sec - (tv2).tv_sec; 
  219.    int __delta = (tv1).tv_usec - (tv2).tv_usec; 
  220.    if (__delta_sec) { 
  221.            switch (__delta_sec) { 
  222.    default: 
  223.    __delta = 0; 
  224.    case 2: 
  225.    __delta += 1000000; 
  226.    case 1: 
  227.    __delta += 1000000; 
  228.            } 
  229.    } 
  230.    __delta; 
  231. })
  232. extern int psched_tod_diff(int delta_sec, int bound);
  233. #define PSCHED_TDIFF_SAFE(tv1, tv2, bound, guard) 
  234. ({ 
  235.    int __delta_sec = (tv1).tv_sec - (tv2).tv_sec; 
  236.    int __delta = (tv1).tv_usec - (tv2).tv_usec; 
  237.    switch (__delta_sec) { 
  238.    default: 
  239.    __delta = psched_tod_diff(__delta_sec, bound); guard; break; 
  240.    case 2: 
  241.    __delta += 1000000; 
  242.    case 1: 
  243.    __delta += 1000000; 
  244.    case 0: ; 
  245.    } 
  246.    __delta; 
  247. })
  248. #define PSCHED_TLESS(tv1, tv2) (((tv1).tv_usec < (tv2).tv_usec && 
  249. (tv1).tv_sec <= (tv2).tv_sec) || 
  250.  (tv1).tv_sec < (tv2).tv_sec)
  251. #define PSCHED_TADD2(tv, delta, tv_res) 
  252. ({ 
  253.    int __delta = (tv).tv_usec + (delta); 
  254.    (tv_res).tv_sec = (tv).tv_sec; 
  255.    if (__delta > 1000000) { (tv_res).tv_sec++; __delta -= 1000000; } 
  256.    (tv_res).tv_usec = __delta; 
  257. })
  258. #define PSCHED_TADD(tv, delta) 
  259. ({ 
  260.    (tv).tv_usec += (delta); 
  261.    if ((tv).tv_usec > 1000000) { (tv).tv_sec++; 
  262.  (tv).tv_usec -= 1000000; } 
  263. })
  264. /* Set/check that time is in the "past perfect";
  265.    it depends on concrete representation of system time
  266.  */
  267. #define PSCHED_SET_PASTPERFECT(t) ((t).tv_sec = 0)
  268. #define PSCHED_IS_PASTPERFECT(t) ((t).tv_sec == 0)
  269. #define PSCHED_AUDIT_TDIFF(t) ({ if ((t) > 2000000) (t) = 2000000; })
  270. #else
  271. #define PSCHED_TDIFF(tv1, tv2) (long)((tv1) - (tv2))
  272. #define PSCHED_TDIFF_SAFE(tv1, tv2, bound, guard) 
  273. ({ 
  274.    long long __delta = (tv1) - (tv2); 
  275.    if ( __delta > (long long)(bound)) {  __delta = (bound); guard; } 
  276.    __delta; 
  277. })
  278. #define PSCHED_TLESS(tv1, tv2) ((tv1) < (tv2))
  279. #define PSCHED_TADD2(tv, delta, tv_res) ((tv_res) = (tv) + (delta))
  280. #define PSCHED_TADD(tv, delta) ((tv) += (delta))
  281. #define PSCHED_SET_PASTPERFECT(t) ((t) = 0)
  282. #define PSCHED_IS_PASTPERFECT(t) ((t) == 0)
  283. #define PSCHED_AUDIT_TDIFF(t)
  284. #endif
  285. struct tcf_police
  286. {
  287. struct tcf_police *next;
  288. int refcnt;
  289. u32 index;
  290. int action;
  291. int result;
  292. u32 ewma_rate;
  293. u32 burst;
  294. u32 mtu;
  295. u32 toks;
  296. u32 ptoks;
  297. psched_time_t t_c;
  298. spinlock_t lock;
  299. struct qdisc_rate_table *R_tab;
  300. struct qdisc_rate_table *P_tab;
  301. struct tc_stats stats;
  302. };
  303. extern int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st);
  304. extern void tcf_police_destroy(struct tcf_police *p);
  305. extern struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est);
  306. extern int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p);
  307. extern int tcf_police(struct sk_buff *skb, struct tcf_police *p);
  308. static inline void tcf_police_release(struct tcf_police *p)
  309. {
  310. if (p && --p->refcnt == 0)
  311. tcf_police_destroy(p);
  312. }
  313. extern struct Qdisc noop_qdisc;
  314. extern struct Qdisc_ops noop_qdisc_ops;
  315. extern struct Qdisc_ops pfifo_qdisc_ops;
  316. extern struct Qdisc_ops bfifo_qdisc_ops;
  317. int register_qdisc(struct Qdisc_ops *qops);
  318. int unregister_qdisc(struct Qdisc_ops *qops);
  319. struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
  320. struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
  321. void dev_init_scheduler(struct net_device *dev);
  322. void dev_shutdown(struct net_device *dev);
  323. void dev_activate(struct net_device *dev);
  324. void dev_deactivate(struct net_device *dev);
  325. void qdisc_reset(struct Qdisc *qdisc);
  326. void qdisc_destroy(struct Qdisc *qdisc);
  327. struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops);
  328. int qdisc_new_estimator(struct tc_stats *stats, struct rtattr *opt);
  329. void qdisc_kill_estimator(struct tc_stats *stats);
  330. struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct rtattr *tab);
  331. void qdisc_put_rtab(struct qdisc_rate_table *tab);
  332. int teql_init(void);
  333. int tc_filter_init(void);
  334. int pktsched_init(void);
  335. extern int qdisc_restart(struct net_device *dev);
  336. static inline void qdisc_run(struct net_device *dev)
  337. {
  338. while (!netif_queue_stopped(dev) &&
  339.        qdisc_restart(dev)<0)
  340. /* NOTHING */;
  341. }
  342. /* Calculate maximal size of packet seen by hard_start_xmit
  343.    routine of this device.
  344.  */
  345. static inline unsigned psched_mtu(struct net_device *dev)
  346. {
  347. unsigned mtu = dev->mtu;
  348. return dev->hard_header ? mtu + dev->hard_header_len : mtu;
  349. }
  350. #endif