summaryrefslogtreecommitdiffstats
path: root/include/net/pkt_sched.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/pkt_sched.h')
-rw-r--r--include/net/pkt_sched.h164
1 files changed, 164 insertions, 0 deletions
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
new file mode 100644
index 000000000..b83c1048b
--- /dev/null
+++ b/include/net/pkt_sched.h
@@ -0,0 +1,164 @@
+#ifndef __NET_PKT_SCHED_H
+#define __NET_PKT_SCHED_H
+
+#include <linux/pkt_sched.h>
+
+struct Qdisc_ops
+{
+ struct Qdisc_ops *next;
+ char id[IFNAMSIZ];
+ int refcnt;
+ int priv_size;
+ int (*enqueue)(struct sk_buff *skb, struct Qdisc *);
+ struct sk_buff * (*dequeue)(struct Qdisc *);
+ void (*reset)(struct Qdisc *);
+ void (*destroy)(struct Qdisc *);
+ int (*init)(struct Qdisc *, void *arg);
+ int (*control)(struct Qdisc *, void *);
+};
+
+struct Qdisc_head
+{
+ struct Qdisc_head *forw;
+};
+
+extern struct Qdisc_head qdisc_head;
+
+struct Qdisc
+{
+ struct Qdisc_head h;
+ int (*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
+ struct sk_buff * (*dequeue)(struct Qdisc *dev);
+ struct Qdisc_ops *ops;
+ int handle;
+ struct Qdisc *parent;
+ struct sk_buff_head q;
+ struct device *dev;
+ struct sk_buff_head failure_q;
+ unsigned long dropped;
+ unsigned long tx_last;
+ unsigned long tx_timeo;
+
+ char data[0];
+};
+
+
+/* Yes, it is slow for [34]86, but we have no choice.
+ 10 msec resolution is appropriate only for bandwidth < 32Kbit/sec.
+
+ RULE:
+ Timer resolution MUST BE < 10% of min_schedulable_packet_size/bandwidth
+
+ Normal IP packet size ~ 512byte, hence:
+
+ 0.5Kbyte/1Mbyte/sec = 0.5msec, so that we need 50usec timer for
+ 10Mbit ethernet.
+
+ 10msec resolution -> <50Kbit/sec.
+
+ The result: [34]86 is not good choice for QoS router :-(
+ */
+
+
+typedef struct timeval psched_time_t;
+
+/* On 64bit architecures it would be clever to define:
+typedef u64 psched_time_t;
+ and make all this boring arithmetics directly
+ */
+
+#ifndef SCHEDULE_ONLY_LOW_BANDWIDTH
+#define PSCHED_GET_TIME(stamp) do_gettimeofday(&(stamp))
+#else
+#define PSCHED_GET_TIME(stamp) ((stamp) = xtime)
+#endif
+
+#define PSCHED_TDIFF(tv1, tv2) \
+({ \
+ int __delta_sec = (tv1).tv_sec - (tv2).tv_sec; \
+ int __delta = (tv1).tv_usec - (tv2).tv_usec; \
+ if (__delta_sec) { \
+ switch (__delta_sec) { \
+ default: \
+ __delta = 0; \
+ case 2: \
+ __delta += 1000000; \
+ case 1: \
+ __delta += 1000000; \
+ } \
+ } \
+ __delta; \
+})
+
+#define PSCHED_TDIFF_SAFE(tv1, tv2, bound, guard) \
+({ \
+ int __delta_sec = (tv1).tv_sec - (tv2).tv_sec; \
+ int __delta = (tv1).tv_usec - (tv2).tv_usec; \
+ switch (__delta_sec) { \
+ default: \
+ __delta = (bound); guard; break; \
+ case 2: \
+ __delta += 1000000; \
+ case 1: \
+ __delta += 1000000; \
+ case 0: ; \
+ } \
+ __delta; \
+})
+
+#define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ))
+
+#define PSCHED_TLESS(tv1, tv2) (((tv1).tv_usec < (tv2).tv_usec && \
+ (tv1).tv_sec < (tv2).tv_sec) || \
+ (tv1).tv_sec < (tv2).tv_sec)
+
+#define PSCHED_TADD2(tv, delta, tv_res) \
+({ \
+ int __delta = (tv).tv_usec + (delta); \
+ (tv_res).tv_sec = (tv).tv_sec; \
+ if (__delta > 1000000) { (tv_res).tv_sec++; __delta -= 1000000; } \
+ (tv_res).tv_sec = __delta; \
+})
+
+#define PSCHED_TADD(tv, delta) \
+({ \
+ (tv).tv_usec += (delta); \
+ if ((tv).tv_usec > 1000000) { (tv).tv_sec++; \
+ (tv).tv_usec -= 1000000; } \
+})
+
+/* Set/check that undertime is in the "past perfect";
+ it depends on concrete representation of system time
+ */
+
+#define PSCHED_SET_PASTPERFECT(t) ((t).tv_sec = 0)
+#define PSCHED_IS_PASTPERFECT(t) ((t).tv_sec == 0)
+
+
+extern struct Qdisc noop_qdisc;
+
+int register_qdisc(struct Qdisc_ops *qops);
+int unregister_qdisc(struct Qdisc_ops *qops);
+void dev_init_scheduler(struct device *dev);
+void dev_shutdown(struct device *dev);
+void dev_activate(struct device *dev);
+void dev_deactivate(struct device *dev);
+void qdisc_reset(struct Qdisc *qdisc);
+void qdisc_destroy(struct Qdisc *qdisc);
+int pktsched_init(void);
+
+void qdisc_run_queues(void);
+int qdisc_restart(struct device *dev);
+
+extern __inline__ void qdisc_wakeup(struct device *dev)
+{
+ if (!dev->tbusy) {
+ struct Qdisc *q = dev->qdisc;
+ if (qdisc_restart(dev) && q->h.forw == NULL) {
+ q->h.forw = qdisc_head.forw;
+ qdisc_head.forw = &q->h;
+ }
+ }
+}
+
+#endif