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