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

嵌入式Linux

开发平台:

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