X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=include%2Fnet%2Fpkt_sched.h;h=825e11014edb9c3dc61cdd21a6d51d4111e99814;hb=1731da41698a0b4ce0b124c3771426720490471d;hp=bce3aaf91235ce16f09d0c65c5196924aab18879;hpb=a91482bdcc2e0f6035702e46f1b99043a0893346;p=linux-2.6.git diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index bce3aaf91..825e11014 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -1,6 +1,12 @@ #ifndef __NET_PKT_SCHED_H #define __NET_PKT_SCHED_H +#define PSCHED_GETTIMEOFDAY 1 +#define PSCHED_JIFFIES 2 +#define PSCHED_CPU 3 + +#define PSCHED_CLOCK_SOURCE PSCHED_JIFFIES + #include #include #include @@ -10,6 +16,11 @@ #include #include +#ifdef CONFIG_X86_TSC +#include +#endif + + struct rtattr; struct Qdisc; @@ -77,13 +88,12 @@ struct Qdisc #define TCQ_F_BUILTIN 1 #define TCQ_F_THROTTLED 2 #define TCQ_F_INGRES 4 - int padded; struct Qdisc_ops *ops; + struct Qdisc *next; u32 handle; atomic_t refcnt; struct sk_buff_head q; struct net_device *dev; - struct list_head list; struct tc_stats stats; spinlock_t *stats_lock; @@ -94,16 +104,9 @@ struct Qdisc * and it will live until better solution will be invented. */ struct Qdisc *__parent; -}; - -#define QDISC_ALIGN 32 -#define QDISC_ALIGN_CONST (QDISC_ALIGN - 1) -static inline void *qdisc_priv(struct Qdisc *q) -{ - return (char *)q + ((sizeof(struct Qdisc) + QDISC_ALIGN_CONST) - & ~QDISC_ALIGN_CONST); -} + char data[0]; +}; struct qdisc_rate_table { @@ -113,15 +116,43 @@ struct qdisc_rate_table int refcnt; }; -extern void qdisc_lock_tree(struct net_device *dev); -extern void qdisc_unlock_tree(struct net_device *dev); +static inline void sch_tree_lock(struct Qdisc *q) +{ + write_lock(&qdisc_tree_lock); + spin_lock_bh(&q->dev->queue_lock); +} + +static inline void sch_tree_unlock(struct Qdisc *q) +{ + spin_unlock_bh(&q->dev->queue_lock); + write_unlock(&qdisc_tree_lock); +} + +static inline void tcf_tree_lock(struct tcf_proto *tp) +{ + write_lock(&qdisc_tree_lock); + spin_lock_bh(&tp->q->dev->queue_lock); +} + +static inline void tcf_tree_unlock(struct tcf_proto *tp) +{ + spin_unlock_bh(&tp->q->dev->queue_lock); + write_unlock(&qdisc_tree_lock); +} + + +static inline unsigned long +cls_set_class(struct tcf_proto *tp, unsigned long *clp, unsigned long cl) +{ + unsigned long old_cl; -#define sch_tree_lock(q) qdisc_lock_tree((q)->dev) -#define sch_tree_unlock(q) qdisc_unlock_tree((q)->dev) -#define tcf_tree_lock(tp) qdisc_lock_tree((tp)->q->dev) -#define tcf_tree_unlock(tp) qdisc_unlock_tree((tp)->q->dev) + tcf_tree_lock(tp); + old_cl = *clp; + *clp = cl; + tcf_tree_unlock(tp); + return old_cl; +} -#define cls_set_class(tp, clp, cl) tcf_set_class(tp, clp, cl) static inline unsigned long __cls_set_class(unsigned long *clp, unsigned long cl) { @@ -153,19 +184,25 @@ __cls_set_class(unsigned long *clp, unsigned long cl) The reason is that, when it is not the same thing as gettimeofday, it returns invalid timestamp, which is not updated, when net_bh is active. + + So, use PSCHED_CLOCK_SOURCE = PSCHED_CPU on alpha and pentiums + with rtdsc. And PSCHED_JIFFIES on all other architectures, including [34]86 + and pentiums without rtdsc. + You can use PSCHED_GETTIMEOFDAY on another architectures, + which have fast and precise clock source, but it is too expensive. */ /* General note about internal clock. Any clock source returns time intervals, measured in units - close to 1usec. With source CONFIG_NET_SCH_CLK_GETTIMEOFDAY it is precisely + close to 1usec. With source PSCHED_GETTIMEOFDAY it is precisely microseconds, otherwise something close but different chosen to minimize arithmetic cost. Ratio usec/internal untis in form nominator/denominator may be read from /proc/net/psched. */ -#ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY +#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY typedef struct timeval psched_time_t; typedef long psched_tdiff_t; @@ -174,12 +211,14 @@ typedef long psched_tdiff_t; #define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ)) #define PSCHED_JIFFIE2US(delay) ((delay)*(1000000/HZ)) -#else /* !CONFIG_NET_SCH_CLK_GETTIMEOFDAY */ +#else /* PSCHED_CLOCK_SOURCE != PSCHED_GETTIMEOFDAY */ typedef u64 psched_time_t; typedef long psched_tdiff_t; -#ifdef CONFIG_NET_SCH_CLK_JIFFIES +extern psched_time_t psched_time_base; + +#if PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES #if HZ < 96 #define PSCHED_JSCALE 14 @@ -197,35 +236,47 @@ typedef long psched_tdiff_t; #define PSCHED_US2JIFFIE(delay) (((delay)+(1<>PSCHED_JSCALE) #define PSCHED_JIFFIE2US(delay) ((delay)< +#elif PSCHED_CLOCK_SOURCE == PSCHED_CPU extern psched_tdiff_t psched_clock_per_hz; extern int psched_clock_scale; -extern psched_time_t psched_time_base; -extern cycles_t psched_time_mark; - -#define PSCHED_GET_TIME(stamp) \ -do { \ - cycles_t cur = get_cycles(); \ - if (sizeof(cycles_t) == sizeof(u32)) { \ - if (cur <= psched_time_mark) \ - psched_time_base += 0x100000000ULL; \ - psched_time_mark = cur; \ - (stamp) = (psched_time_base + cur)>>psched_clock_scale; \ - } else { \ - (stamp) = cur>>psched_clock_scale; \ - } \ -} while (0) + #define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz) #define PSCHED_JIFFIE2US(delay) ((delay)*psched_clock_per_hz) -#endif /* CONFIG_NET_SCH_CLK_CPU */ +#ifdef CONFIG_X86_TSC + +#define PSCHED_GET_TIME(stamp) \ +({ u64 __cur; \ + rdtscll(__cur); \ + (stamp) = __cur>>psched_clock_scale; \ +}) + +#elif defined (__alpha__) + +#define PSCHED_WATCHER u32 -#endif /* !CONFIG_NET_SCH_CLK_GETTIMEOFDAY */ +extern PSCHED_WATCHER psched_time_mark; -#ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY +#define PSCHED_GET_TIME(stamp) \ +({ u32 __res; \ + __asm__ __volatile__ ("rpcc %0" : "r="(__res)); \ + if (__res <= psched_time_mark) psched_time_base += 0x100000000UL; \ + psched_time_mark = __res; \ + (stamp) = (psched_time_base + __res)>>psched_clock_scale; \ +}) + +#else + +#error PSCHED_CLOCK_SOURCE=PSCHED_CPU is not supported on this arch. + +#endif /* ARCH */ + +#endif /* PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES */ + +#endif /* PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY */ + +#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY #define PSCHED_TDIFF(tv1, tv2) \ ({ \ int __delta_sec = (tv1).tv_sec - (tv2).tv_sec; \ @@ -289,7 +340,7 @@ extern int psched_tod_diff(int delta_sec, int bound); #define PSCHED_AUDIT_TDIFF(t) ({ if ((t) > 2000000) (t) = 2000000; }) -#else /* !CONFIG_NET_SCH_CLK_GETTIMEOFDAY */ +#else #define PSCHED_TDIFF(tv1, tv2) (long)((tv1) - (tv2)) #define PSCHED_TDIFF_SAFE(tv1, tv2, bound) \ @@ -303,7 +354,7 @@ extern int psched_tod_diff(int delta_sec, int bound); #define PSCHED_IS_PASTPERFECT(t) ((t) == 0) #define PSCHED_AUDIT_TDIFF(t) -#endif /* !CONFIG_NET_SCH_CLK_GETTIMEOFDAY */ +#endif struct tcf_police { @@ -387,8 +438,6 @@ extern int tcf_act_police_dump(struct sk_buff *, struct tc_action *, int, int); extern int tcf_act_police(struct sk_buff **skb, struct tc_action *a); #endif -extern unsigned long tcf_set_class(struct tcf_proto *tp, unsigned long *clp, - unsigned long cl); extern int tcf_police(struct sk_buff *skb, struct tcf_police *p); extern int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st, spinlock_t *lock); extern void tcf_police_destroy(struct tcf_police *p); @@ -440,6 +489,13 @@ void qdisc_put_rtab(struct qdisc_rate_table *tab); extern int qdisc_restart(struct net_device *dev); +static inline void qdisc_run(struct net_device *dev) +{ + while (!netif_queue_stopped(dev) && + qdisc_restart(dev)<0) + /* NOTHING */; +} + /* Calculate maximal size of packet seen by hard_start_xmit routine of this device. */