OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [sched/] [sch_hfsc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Copyright (c) 2003 Patrick McHardy, <kaber@trash.net>
3
 *
4
 * This program is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU General Public License
6
 * as published by the Free Software Foundation; either version 2
7
 * of the License, or (at your option) any later version.
8
 *
9
 * 2003-10-17 - Ported from altq
10
 */
11
/*
12
 * Copyright (c) 1997-1999 Carnegie Mellon University. All Rights Reserved.
13
 *
14
 * Permission to use, copy, modify, and distribute this software and
15
 * its documentation is hereby granted (including for commercial or
16
 * for-profit use), provided that both the copyright notice and this
17
 * permission notice appear in all copies of the software, derivative
18
 * works, or modified versions, and any portions thereof.
19
 *
20
 * THIS SOFTWARE IS EXPERIMENTAL AND IS KNOWN TO HAVE BUGS, SOME OF
21
 * WHICH MAY HAVE SERIOUS CONSEQUENCES.  CARNEGIE MELLON PROVIDES THIS
22
 * SOFTWARE IN ITS ``AS IS'' CONDITION, AND ANY EXPRESS OR IMPLIED
23
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
 * DISCLAIMED.  IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
28
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
32
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33
 * DAMAGE.
34
 *
35
 * Carnegie Mellon encourages (but does not require) users of this
36
 * software to return any improvements or extensions that they make,
37
 * and to grant Carnegie Mellon the rights to redistribute these
38
 * changes without encumbrance.
39
 */
40
/*
41
 * H-FSC is described in Proceedings of SIGCOMM'97,
42
 * "A Hierarchical Fair Service Curve Algorithm for Link-Sharing,
43
 * Real-Time and Priority Service"
44
 * by Ion Stoica, Hui Zhang, and T. S. Eugene Ng.
45
 *
46
 * Oleg Cherevko <olwi@aq.ml.com.ua> added the upperlimit for link-sharing.
47
 * when a class has an upperlimit, the fit-time is computed from the
48
 * upperlimit service curve.  the link-sharing scheduler does not schedule
49
 * a class whose fit-time exceeds the current time.
50
 */
51
 
52
#include <linux/kernel.h>
53
#include <linux/config.h>
54
#include <linux/module.h>
55
#include <linux/types.h>
56
#include <linux/errno.h>
57
#include <linux/compiler.h>
58
#include <linux/spinlock.h>
59
#include <linux/skbuff.h>
60
#include <linux/string.h>
61
#include <linux/slab.h>
62
#include <linux/timer.h>
63
#include <linux/list.h>
64
#include <linux/init.h>
65
#include <linux/netdevice.h>
66
#include <linux/rtnetlink.h>
67
#include <linux/pkt_sched.h>
68
#include <net/pkt_sched.h>
69
#include <net/pkt_cls.h>
70
#include <asm/system.h>
71
#include <asm/div64.h>
72
 
73
#define HFSC_DEBUG 1
74
 
75
/*
76
 * kernel internal service curve representation:
77
 *   coordinates are given by 64 bit unsigned integers.
78
 *   x-axis: unit is clock count.
79
 *   y-axis: unit is byte.
80
 *
81
 *   The service curve parameters are converted to the internal
82
 *   representation. The slope values are scaled to avoid overflow.
83
 *   the inverse slope values as well as the y-projection of the 1st
84
 *   segment are kept in order to to avoid 64-bit divide operations
85
 *   that are expensive on 32-bit architectures.
86
 */
87
 
88
struct internal_sc
89
{
90
        u64     sm1;    /* scaled slope of the 1st segment */
91
        u64     ism1;   /* scaled inverse-slope of the 1st segment */
92
        u64     dx;     /* the x-projection of the 1st segment */
93
        u64     dy;     /* the y-projection of the 1st segment */
94
        u64     sm2;    /* scaled slope of the 2nd segment */
95
        u64     ism2;   /* scaled inverse-slope of the 2nd segment */
96
};
97
 
98
/* runtime service curve */
99
struct runtime_sc
100
{
101
        u64     x;      /* current starting position on x-axis */
102
        u64     y;      /* current starting position on y-axis */
103
        u64     sm1;    /* scaled slope of the 1st segment */
104
        u64     ism1;   /* scaled inverse-slope of the 1st segment */
105
        u64     dx;     /* the x-projection of the 1st segment */
106
        u64     dy;     /* the y-projection of the 1st segment */
107
        u64     sm2;    /* scaled slope of the 2nd segment */
108
        u64     ism2;   /* scaled inverse-slope of the 2nd segment */
109
};
110
 
111
enum hfsc_class_flags
112
{
113
        HFSC_RSC = 0x1,
114
        HFSC_FSC = 0x2,
115
        HFSC_USC = 0x4
116
};
117
 
118
struct hfsc_class
119
{
120
        u32             classid;        /* class id */
121
        unsigned int    refcnt;         /* usage count */
122
 
123
        struct tc_stats stats;          /* generic statistics */
124
        unsigned int    level;          /* class level in hierarchy */
125
        struct tcf_proto *filter_list;  /* filter list */
126
        unsigned int    filter_cnt;     /* filter count */
127
 
128
        struct hfsc_sched *sched;       /* scheduler data */
129
        struct hfsc_class *cl_parent;   /* parent class */
130
        struct list_head siblings;      /* sibling classes */
131
        struct list_head children;      /* child classes */
132
        struct Qdisc    *qdisc;         /* leaf qdisc */
133
 
134
        struct list_head actlist;       /* active children list */
135
        struct list_head alist;         /* active children list member */
136
        struct list_head ellist;        /* eligible list member */
137
        struct list_head hlist;         /* hash list member */
138
        struct list_head dlist;         /* drop list member */
139
 
140
        u64     cl_total;               /* total work in bytes */
141
        u64     cl_cumul;               /* cumulative work in bytes done by
142
                                           real-time criteria */
143
 
144
        u64     cl_d;                   /* deadline*/
145
        u64     cl_e;                   /* eligible time */
146
        u64     cl_vt;                  /* virtual time */
147
        u64     cl_f;                   /* time when this class will fit for
148
                                           link-sharing, max(myf, cfmin) */
149
        u64     cl_myf;                 /* my fit-time (calculated from this
150
                                           class's own upperlimit curve) */
151
        u64     cl_myfadj;              /* my fit-time adjustment (to cancel
152
                                           history dependence) */
153
        u64     cl_cfmin;               /* earliest children's fit-time (used
154
                                           with cl_myf to obtain cl_f) */
155
        u64     cl_cvtmin;              /* minimal virtual time among the
156
                                           children fit for link-sharing
157
                                           (monotonic within a period) */
158
        u64     cl_vtadj;               /* intra-period cumulative vt
159
                                           adjustment */
160
        u64     cl_vtoff;               /* inter-period cumulative vt offset */
161
        u64     cl_cvtmax;              /* max child's vt in the last period */
162
 
163
        struct internal_sc cl_rsc;      /* internal real-time service curve */
164
        struct internal_sc cl_fsc;      /* internal fair service curve */
165
        struct internal_sc cl_usc;      /* internal upperlimit service curve */
166
        struct runtime_sc cl_deadline;  /* deadline curve */
167
        struct runtime_sc cl_eligible;  /* eligible curve */
168
        struct runtime_sc cl_virtual;   /* virtual curve */
169
        struct runtime_sc cl_ulimit;    /* upperlimit curve */
170
 
171
        unsigned long   cl_flags;       /* which curves are valid */
172
        unsigned long   cl_vtperiod;    /* vt period sequence number */
173
        unsigned long   cl_parentperiod;/* parent's vt period sequence number*/
174
        unsigned long   cl_nactive;     /* number of active children */
175
};
176
 
177
#define HFSC_HSIZE      16
178
 
179
struct hfsc_sched
180
{
181
        u16     defcls;                         /* default class id */
182
        struct hfsc_class root;                 /* root class */
183
        struct list_head clhash[HFSC_HSIZE];    /* class hash */
184
        struct list_head eligible;              /* eligible list */
185
        struct list_head droplist;              /* active leaf class list (for
186
                                                   dropping) */
187
        struct sk_buff_head requeue;            /* requeued packet */
188
        struct timer_list wd_timer;             /* watchdog timer */
189
};
190
 
191
/*
192
 * macros
193
 */
194
#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY
195
#include <linux/time.h>
196
#undef PSCHED_GET_TIME
197
#define PSCHED_GET_TIME(stamp)                                          \
198
do {                                                                    \
199
        struct timeval tv;                                              \
200
        do_gettimeofday(&tv);                                           \
201
        (stamp) = 1000000ULL * tv.tv_sec + tv.tv_usec;                  \
202
} while (0)
203
#endif
204
 
205
#if HFSC_DEBUG
206
#define ASSERT(cond)                                                    \
207
do {                                                                    \
208
        if (unlikely(!(cond)))                                          \
209
                printk("assertion %s failed at %s:%i (%s)\n",           \
210
                       #cond, __FILE__, __LINE__, __FUNCTION__);        \
211
} while (0)
212
#else
213
#define ASSERT(cond)
214
#endif /* HFSC_DEBUG */
215
 
216
#define HT_INFINITY     0xffffffffffffffffULL   /* infinite time value */
217
 
218
 
219
/*
220
 * eligible list holds backlogged classes being sorted by their eligible times.
221
 * there is one eligible list per hfsc instance.
222
 */
223
 
224
static void
225
ellist_insert(struct hfsc_class *cl)
226
{
227
        struct list_head *head = &cl->sched->eligible;
228
        struct hfsc_class *p;
229
 
230
        /* check the last entry first */
231
        if (list_empty(head) ||
232
            ((p = list_entry(head->prev, struct hfsc_class, ellist)) &&
233
             p->cl_e <= cl->cl_e)) {
234
                list_add_tail(&cl->ellist, head);
235
                return;
236
        }
237
 
238
        list_for_each_entry(p, head, ellist) {
239
                if (cl->cl_e < p->cl_e) {
240
                        /* insert cl before p */
241
                        list_add_tail(&cl->ellist, &p->ellist);
242
                        return;
243
                }
244
        }
245
        ASSERT(0); /* should not reach here */
246
}
247
 
248
static inline void
249
ellist_remove(struct hfsc_class *cl)
250
{
251
        list_del(&cl->ellist);
252
}
253
 
254
static void
255
ellist_update(struct hfsc_class *cl)
256
{
257
        struct list_head *head = &cl->sched->eligible;
258
        struct hfsc_class *p, *last;
259
 
260
        /*
261
         * the eligible time of a class increases monotonically.
262
         * if the next entry has a larger eligible time, nothing to do.
263
         */
264
        if (cl->ellist.next == head ||
265
            ((p = list_entry(cl->ellist.next, struct hfsc_class, ellist)) &&
266
             cl->cl_e <= p->cl_e))
267
                return;
268
 
269
        /* check the last entry */
270
        last = list_entry(head->prev, struct hfsc_class, ellist);
271
        if (last->cl_e <= cl->cl_e) {
272
                list_move_tail(&cl->ellist, head);
273
                return;
274
        }
275
 
276
        /*
277
         * the new position must be between the next entry
278
         * and the last entry
279
         */
280
        list_for_each_entry_continue(p, head, ellist) {
281
                if (cl->cl_e < p->cl_e) {
282
                        list_move_tail(&cl->ellist, &p->ellist);
283
                        return;
284
                }
285
        }
286
        ASSERT(0); /* should not reach here */
287
}
288
 
289
/* find the class with the minimum deadline among the eligible classes */
290
static inline struct hfsc_class *
291
ellist_get_mindl(struct list_head *head, u64 cur_time)
292
{
293
        struct hfsc_class *p, *cl = NULL;
294
 
295
        list_for_each_entry(p, head, ellist) {
296
                if (p->cl_e > cur_time)
297
                        break;
298
                if (cl == NULL || p->cl_d < cl->cl_d)
299
                        cl = p;
300
        }
301
        return cl;
302
}
303
 
304
/* find the class with minimum eligible time among the eligible classes */
305
static inline struct hfsc_class *
306
ellist_get_minel(struct list_head *head)
307
{
308
        if (list_empty(head))
309
                return NULL;
310
        return list_entry(head->next, struct hfsc_class, ellist);
311
}
312
 
313
/*
314
 * active children list holds backlogged child classes being sorted
315
 * by their virtual time. each intermediate class has one active
316
 * children list.
317
 */
318
static void
319
actlist_insert(struct hfsc_class *cl)
320
{
321
        struct list_head *head = &cl->cl_parent->actlist;
322
        struct hfsc_class *p;
323
 
324
        /* check the last entry first */
325
        if (list_empty(head) ||
326
            ((p = list_entry(head->prev, struct hfsc_class, alist)) &&
327
             p->cl_vt <= cl->cl_vt)) {
328
                list_add_tail(&cl->alist, head);
329
                return;
330
        }
331
 
332
        list_for_each_entry(p, head, alist) {
333
                if (cl->cl_vt < p->cl_vt) {
334
                        /* insert cl before p */
335
                        list_add_tail(&cl->alist, &p->alist);
336
                        return;
337
                }
338
        }
339
        ASSERT(0); /* should not reach here */
340
}
341
 
342
static inline void
343
actlist_remove(struct hfsc_class *cl)
344
{
345
        list_del(&cl->alist);
346
}
347
 
348
static void
349
actlist_update(struct hfsc_class *cl)
350
{
351
        struct list_head *head = &cl->cl_parent->actlist;
352
        struct hfsc_class *p, *last;
353
 
354
        /*
355
         * the virtual time of a class increases monotonically.
356
         * if the next entry has a larger virtual time, nothing to do.
357
         */
358
        if (cl->alist.next == head ||
359
            ((p = list_entry(cl->alist.next, struct hfsc_class, alist)) &&
360
             cl->cl_vt <= p->cl_vt))
361
                return;
362
 
363
        /* check the last entry */
364
        last = list_entry(head->prev, struct hfsc_class, alist);
365
        if (last->cl_vt <= cl->cl_vt) {
366
                list_move_tail(&cl->alist, head);
367
                return;
368
        }
369
 
370
        /*
371
         * the new position must be between the next entry
372
         * and the last entry
373
         */
374
        list_for_each_entry_continue(p, head, alist) {
375
                if (cl->cl_vt < p->cl_vt) {
376
                        list_move_tail(&cl->alist, &p->alist);
377
                        return;
378
                }
379
        }
380
        ASSERT(0); /* should not reach here */
381
}
382
 
383
static inline struct hfsc_class *
384
actlist_firstfit(struct hfsc_class *cl, u64 cur_time)
385
{
386
        struct hfsc_class *p;
387
 
388
        list_for_each_entry(p, &cl->actlist, alist) {
389
                if (p->cl_f <= cur_time) {
390
                        return p;
391
                }
392
        }
393
        return NULL;
394
}
395
 
396
/*
397
 * get the leaf class with the minimum vt in the hierarchy
398
 */
399
static struct hfsc_class *
400
actlist_get_minvt(struct hfsc_class *cl, u64 cur_time)
401
{
402
        /* if root-class's cfmin is bigger than cur_time nothing to do */
403
        if (cl->cl_cfmin > cur_time)
404
                return NULL;
405
 
406
        while (cl->level > 0) {
407
                cl = actlist_firstfit(cl, cur_time);
408
                if (cl == NULL)
409
                        return NULL;
410
                /*
411
                 * update parent's cl_cvtmin.
412
                 */
413
                if (cl->cl_parent->cl_cvtmin < cl->cl_vt)
414
                        cl->cl_parent->cl_cvtmin = cl->cl_vt;
415
        }
416
        return cl;
417
}
418
 
419
/*
420
 * service curve support functions
421
 *
422
 *  external service curve parameters
423
 *      m: bps
424
 *      d: us
425
 *  internal service curve parameters
426
 *      sm: (bytes/psched_us) << SM_SHIFT
427
 *      ism: (psched_us/byte) << ISM_SHIFT
428
 *      dx: psched_us
429
 *
430
 * Time source resolution
431
 *  PSCHED_JIFFIES: for 48<=HZ<=1534 resolution is between 0.63us and 1.27us.
432
 *  PSCHED_CPU: resolution is between 0.5us and 1us.
433
 *  PSCHED_GETTIMEOFDAY: resolution is exactly 1us.
434
 *
435
 * sm and ism are scaled in order to keep effective digits.
436
 * SM_SHIFT and ISM_SHIFT are selected to keep at least 4 effective
437
 * digits in decimal using the following table.
438
 *
439
 * Note: We can afford the additional accuracy (altq hfsc keeps at most
440
 * 3 effective digits) thanks to the fact that linux clock is bounded
441
 * much more tightly.
442
 *
443
 *  bits/sec      100Kbps     1Mbps     10Mbps     100Mbps    1Gbps
444
 *  ------------+-------------------------------------------------------
445
 *  bytes/0.5us   6.25e-3    62.5e-3    625e-3     6250e-e    62500e-3
446
 *  bytes/us      12.5e-3    125e-3     1250e-3    12500e-3   125000e-3
447
 *  bytes/1.27us  15.875e-3  158.75e-3  1587.5e-3  15875e-3   158750e-3
448
 *
449
 *  0.5us/byte    160        16         1.6        0.16       0.016
450
 *  us/byte       80         8          0.8        0.08       0.008
451
 *  1.27us/byte   63         6.3        0.63       0.063      0.0063
452
 */
453
#define SM_SHIFT        20
454
#define ISM_SHIFT       18
455
 
456
#define SM_MASK         ((1ULL << SM_SHIFT) - 1)
457
#define ISM_MASK        ((1ULL << ISM_SHIFT) - 1)
458
 
459
static inline u64
460
seg_x2y(u64 x, u64 sm)
461
{
462
        u64 y;
463
 
464
        /*
465
         * compute
466
         *      y = x * sm >> SM_SHIFT
467
         * but divide it for the upper and lower bits to avoid overflow
468
         */
469
        y = (x >> SM_SHIFT) * sm + (((x & SM_MASK) * sm) >> SM_SHIFT);
470
        return y;
471
}
472
 
473
static inline u64
474
seg_y2x(u64 y, u64 ism)
475
{
476
        u64 x;
477
 
478
        if (y == 0)
479
                x = 0;
480
        else if (ism == HT_INFINITY)
481
                x = HT_INFINITY;
482
        else {
483
                x = (y >> ISM_SHIFT) * ism
484
                    + (((y & ISM_MASK) * ism) >> ISM_SHIFT);
485
        }
486
        return x;
487
}
488
 
489
/* Convert m (bps) into sm (bytes/psched us) */
490
static u64
491
m2sm(u32 m)
492
{
493
        u64 sm;
494
 
495
        sm = ((u64)m << SM_SHIFT);
496
        sm += PSCHED_JIFFIE2US(HZ) - 1;
497
        do_div(sm, PSCHED_JIFFIE2US(HZ));
498
        return sm;
499
}
500
 
501
/* convert m (bps) into ism (psched us/byte) */
502
static u64
503
m2ism(u32 m)
504
{
505
        u64 ism;
506
 
507
        if (m == 0)
508
                ism = HT_INFINITY;
509
        else {
510
                ism = ((u64)PSCHED_JIFFIE2US(HZ) << ISM_SHIFT);
511
                ism += m - 1;
512
                do_div(ism, m);
513
        }
514
        return ism;
515
}
516
 
517
/* convert d (us) into dx (psched us) */
518
static u64
519
d2dx(u32 d)
520
{
521
        u64 dx;
522
 
523
        dx = ((u64)d * PSCHED_JIFFIE2US(HZ));
524
        dx += 1000000 - 1;
525
        do_div(dx, 1000000);
526
        return dx;
527
}
528
 
529
/* convert sm (bytes/psched us) into m (bps) */
530
static u32
531
sm2m(u64 sm)
532
{
533
        u64 m;
534
 
535
        m = (sm * PSCHED_JIFFIE2US(HZ)) >> SM_SHIFT;
536
        return (u32)m;
537
}
538
 
539
/* convert dx (psched us) into d (us) */
540
static u32
541
dx2d(u64 dx)
542
{
543
        u64 d;
544
 
545
        d = dx * 1000000;
546
        do_div(d, PSCHED_JIFFIE2US(HZ));
547
        return (u32)d;
548
}
549
 
550
static void
551
sc2isc(struct tc_service_curve *sc, struct internal_sc *isc)
552
{
553
        isc->sm1  = m2sm(sc->m1);
554
        isc->ism1 = m2ism(sc->m1);
555
        isc->dx   = d2dx(sc->d);
556
        isc->dy   = seg_x2y(isc->dx, isc->sm1);
557
        isc->sm2  = m2sm(sc->m2);
558
        isc->ism2 = m2ism(sc->m2);
559
}
560
 
561
/*
562
 * initialize the runtime service curve with the given internal
563
 * service curve starting at (x, y).
564
 */
565
static void
566
rtsc_init(struct runtime_sc *rtsc, struct internal_sc *isc, u64 x, u64 y)
567
{
568
        rtsc->x    = x;
569
        rtsc->y    = y;
570
        rtsc->sm1  = isc->sm1;
571
        rtsc->ism1 = isc->ism1;
572
        rtsc->dx   = isc->dx;
573
        rtsc->dy   = isc->dy;
574
        rtsc->sm2  = isc->sm2;
575
        rtsc->ism2 = isc->ism2;
576
}
577
 
578
/*
579
 * calculate the y-projection of the runtime service curve by the
580
 * given x-projection value
581
 */
582
static u64
583
rtsc_y2x(struct runtime_sc *rtsc, u64 y)
584
{
585
        u64 x;
586
 
587
        if (y < rtsc->y)
588
                x = rtsc->x;
589
        else if (y <= rtsc->y + rtsc->dy) {
590
                /* x belongs to the 1st segment */
591
                if (rtsc->dy == 0)
592
                        x = rtsc->x + rtsc->dx;
593
                else
594
                        x = rtsc->x + seg_y2x(y - rtsc->y, rtsc->ism1);
595
        } else {
596
                /* x belongs to the 2nd segment */
597
                x = rtsc->x + rtsc->dx
598
                    + seg_y2x(y - rtsc->y - rtsc->dy, rtsc->ism2);
599
        }
600
        return x;
601
}
602
 
603
static u64
604
rtsc_x2y(struct runtime_sc *rtsc, u64 x)
605
{
606
        u64 y;
607
 
608
        if (x <= rtsc->x)
609
                y = rtsc->y;
610
        else if (x <= rtsc->x + rtsc->dx)
611
                /* y belongs to the 1st segment */
612
                y = rtsc->y + seg_x2y(x - rtsc->x, rtsc->sm1);
613
        else
614
                /* y belongs to the 2nd segment */
615
                y = rtsc->y + rtsc->dy
616
                    + seg_x2y(x - rtsc->x - rtsc->dx, rtsc->sm2);
617
        return y;
618
}
619
 
620
/*
621
 * update the runtime service curve by taking the minimum of the current
622
 * runtime service curve and the service curve starting at (x, y).
623
 */
624
static void
625
rtsc_min(struct runtime_sc *rtsc, struct internal_sc *isc, u64 x, u64 y)
626
{
627
        u64 y1, y2, dx, dy;
628
        u32 dsm;
629
 
630
        if (isc->sm1 <= isc->sm2) {
631
                /* service curve is convex */
632
                y1 = rtsc_x2y(rtsc, x);
633
                if (y1 < y)
634
                        /* the current rtsc is smaller */
635
                        return;
636
                rtsc->x = x;
637
                rtsc->y = y;
638
                return;
639
        }
640
 
641
        /*
642
         * service curve is concave
643
         * compute the two y values of the current rtsc
644
         *      y1: at x
645
         *      y2: at (x + dx)
646
         */
647
        y1 = rtsc_x2y(rtsc, x);
648
        if (y1 <= y) {
649
                /* rtsc is below isc, no change to rtsc */
650
                return;
651
        }
652
 
653
        y2 = rtsc_x2y(rtsc, x + isc->dx);
654
        if (y2 >= y + isc->dy) {
655
                /* rtsc is above isc, replace rtsc by isc */
656
                rtsc->x = x;
657
                rtsc->y = y;
658
                rtsc->dx = isc->dx;
659
                rtsc->dy = isc->dy;
660
                return;
661
        }
662
 
663
        /*
664
         * the two curves intersect
665
         * compute the offsets (dx, dy) using the reverse
666
         * function of seg_x2y()
667
         *      seg_x2y(dx, sm1) == seg_x2y(dx, sm2) + (y1 - y)
668
         */
669
        dx = (y1 - y) << SM_SHIFT;
670
        dsm = isc->sm1 - isc->sm2;
671
        do_div(dx, dsm);
672
        /*
673
         * check if (x, y1) belongs to the 1st segment of rtsc.
674
         * if so, add the offset.
675
         */
676
        if (rtsc->x + rtsc->dx > x)
677
                dx += rtsc->x + rtsc->dx - x;
678
        dy = seg_x2y(dx, isc->sm1);
679
 
680
        rtsc->x = x;
681
        rtsc->y = y;
682
        rtsc->dx = dx;
683
        rtsc->dy = dy;
684
        return;
685
}
686
 
687
static void
688
init_ed(struct hfsc_class *cl, unsigned int next_len)
689
{
690
        u64 cur_time;
691
 
692
        PSCHED_GET_TIME(cur_time);
693
 
694
        /* update the deadline curve */
695
        rtsc_min(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul);
696
 
697
        /*
698
         * update the eligible curve.
699
         * for concave, it is equal to the deadline curve.
700
         * for convex, it is a linear curve with slope m2.
701
         */
702
        cl->cl_eligible = cl->cl_deadline;
703
        if (cl->cl_rsc.sm1 <= cl->cl_rsc.sm2) {
704
                cl->cl_eligible.dx = 0;
705
                cl->cl_eligible.dy = 0;
706
        }
707
 
708
        /* compute e and d */
709
        cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
710
        cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
711
 
712
        ellist_insert(cl);
713
}
714
 
715
static void
716
update_ed(struct hfsc_class *cl, unsigned int next_len)
717
{
718
        cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
719
        cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
720
 
721
        ellist_update(cl);
722
}
723
 
724
static inline void
725
update_d(struct hfsc_class *cl, unsigned int next_len)
726
{
727
        cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
728
}
729
 
730
static void
731
update_cfmin(struct hfsc_class *cl)
732
{
733
        struct hfsc_class *p;
734
        u64 cfmin;
735
 
736
        if (list_empty(&cl->actlist)) {
737
                cl->cl_cfmin = 0;
738
                return;
739
        }
740
        cfmin = HT_INFINITY;
741
        list_for_each_entry(p, &cl->actlist, alist) {
742
                if (p->cl_f == 0) {
743
                        cl->cl_cfmin = 0;
744
                        return;
745
                }
746
                if (p->cl_f < cfmin)
747
                        cfmin = p->cl_f;
748
        }
749
        cl->cl_cfmin = cfmin;
750
}
751
 
752
static void
753
init_vf(struct hfsc_class *cl, unsigned int len)
754
{
755
        struct hfsc_class *max_cl, *p;
756
        u64 vt, f, cur_time;
757
        int go_active;
758
 
759
        cur_time = 0;
760
        go_active = 1;
761
        for (; cl->cl_parent != NULL; cl = cl->cl_parent) {
762
                if (go_active && cl->cl_nactive++ == 0)
763
                        go_active = 1;
764
                else
765
                        go_active = 0;
766
 
767
                if (go_active) {
768
                        if (!list_empty(&cl->cl_parent->actlist)) {
769
                                max_cl = list_entry(cl->cl_parent->actlist.prev,
770
                                                    struct hfsc_class, alist);
771
                                /*
772
                                 * set vt to the average of the min and max
773
                                 * classes.  if the parent's period didn't
774
                                 * change, don't decrease vt of the class.
775
                                 */
776
                                vt = max_cl->cl_vt;
777
                                if (cl->cl_parent->cl_cvtmin != 0)
778
                                        vt = (cl->cl_parent->cl_cvtmin + vt)/2;
779
 
780
                                if (cl->cl_parent->cl_vtperiod !=
781
                                    cl->cl_parentperiod || vt > cl->cl_vt)
782
                                        cl->cl_vt = vt;
783
                        } else {
784
                                /*
785
                                 * first child for a new parent backlog period.
786
                                 * add parent's cvtmax to vtoff of children
787
                                 * to make a new vt (vtoff + vt) larger than
788
                                 * the vt in the last period for all children.
789
                                 */
790
                                vt = cl->cl_parent->cl_cvtmax;
791
                                list_for_each_entry(p, &cl->cl_parent->children,
792
                                                                       siblings)
793
                                        p->cl_vtoff += vt;
794
                                cl->cl_vt = 0;
795
                                cl->cl_parent->cl_cvtmax = 0;
796
                                cl->cl_parent->cl_cvtmin = 0;
797
                        }
798
 
799
                        /* update the virtual curve */
800
                        vt = cl->cl_vt + cl->cl_vtoff;
801
                        rtsc_min(&cl->cl_virtual, &cl->cl_fsc, vt,
802
                                                      cl->cl_total);
803
                        if (cl->cl_virtual.x == vt) {
804
                                cl->cl_virtual.x -= cl->cl_vtoff;
805
                                cl->cl_vtoff = 0;
806
                        }
807
                        cl->cl_vtadj = 0;
808
 
809
                        cl->cl_vtperiod++;  /* increment vt period */
810
                        cl->cl_parentperiod = cl->cl_parent->cl_vtperiod;
811
                        if (cl->cl_parent->cl_nactive == 0)
812
                                cl->cl_parentperiod++;
813
                        cl->cl_f = 0;
814
 
815
                        actlist_insert(cl);
816
 
817
                        if (cl->cl_flags & HFSC_USC) {
818
                                /* class has upper limit curve */
819
                                if (cur_time == 0)
820
                                        PSCHED_GET_TIME(cur_time);
821
 
822
                                /* update the ulimit curve */
823
                                rtsc_min(&cl->cl_ulimit, &cl->cl_usc, cur_time,
824
                                         cl->cl_total);
825
                                /* compute myf */
826
                                cl->cl_myf = rtsc_y2x(&cl->cl_ulimit,
827
                                                      cl->cl_total);
828
                                cl->cl_myfadj = 0;
829
                        }
830
                }
831
 
832
                f = max(cl->cl_myf, cl->cl_cfmin);
833
                if (f != cl->cl_f) {
834
                        cl->cl_f = f;
835
                        update_cfmin(cl->cl_parent);
836
                }
837
        }
838
}
839
 
840
static void
841
update_vf(struct hfsc_class *cl, unsigned int len, u64 cur_time)
842
{
843
        u64 f; /* , myf_bound, delta; */
844
        int go_passive = 0;
845
 
846
        if (cl->qdisc->q.qlen == 0 && cl->cl_flags & HFSC_FSC)
847
                go_passive = 1;
848
 
849
        for (; cl->cl_parent != NULL; cl = cl->cl_parent) {
850
                cl->cl_total += len;
851
 
852
                if (!(cl->cl_flags & HFSC_FSC) || cl->cl_nactive == 0)
853
                        continue;
854
 
855
                if (go_passive && --cl->cl_nactive == 0)
856
                        go_passive = 1;
857
                else
858
                        go_passive = 0;
859
 
860
                if (go_passive) {
861
                        /* no more active child, going passive */
862
 
863
                        /* update cvtmax of the parent class */
864
                        if (cl->cl_vt > cl->cl_parent->cl_cvtmax)
865
                                cl->cl_parent->cl_cvtmax = cl->cl_vt;
866
 
867
                        /* remove this class from the vt list */
868
                        actlist_remove(cl);
869
 
870
                        update_cfmin(cl->cl_parent);
871
 
872
                        continue;
873
                }
874
 
875
                /*
876
                 * update vt and f
877
                 */
878
                cl->cl_vt = rtsc_y2x(&cl->cl_virtual, cl->cl_total)
879
                            - cl->cl_vtoff + cl->cl_vtadj;
880
 
881
                /*
882
                 * if vt of the class is smaller than cvtmin,
883
                 * the class was skipped in the past due to non-fit.
884
                 * if so, we need to adjust vtadj.
885
                 */
886
                if (cl->cl_vt < cl->cl_parent->cl_cvtmin) {
887
                        cl->cl_vtadj += cl->cl_parent->cl_cvtmin - cl->cl_vt;
888
                        cl->cl_vt = cl->cl_parent->cl_cvtmin;
889
                }
890
 
891
                /* update the vt list */
892
                actlist_update(cl);
893
 
894
                if (cl->cl_flags & HFSC_USC) {
895
                        cl->cl_myf = cl->cl_myfadj + rtsc_y2x(&cl->cl_ulimit,
896
                                                              cl->cl_total);
897
#if 0
898
                        /*
899
                         * This code causes classes to stay way under their
900
                         * limit when multiple classes are used at gigabit
901
                         * speed. needs investigation. -kaber
902
                         */
903
                        /*
904
                         * if myf lags behind by more than one clock tick
905
                         * from the current time, adjust myfadj to prevent
906
                         * a rate-limited class from going greedy.
907
                         * in a steady state under rate-limiting, myf
908
                         * fluctuates within one clock tick.
909
                         */
910
                        myf_bound = cur_time - PSCHED_JIFFIE2US(1);
911
                        if (cl->cl_myf < myf_bound) {
912
                                delta = cur_time - cl->cl_myf;
913
                                cl->cl_myfadj += delta;
914
                                cl->cl_myf += delta;
915
                        }
916
#endif
917
                }
918
 
919
                f = max(cl->cl_myf, cl->cl_cfmin);
920
                if (f != cl->cl_f) {
921
                        cl->cl_f = f;
922
                        update_cfmin(cl->cl_parent);
923
                }
924
        }
925
}
926
 
927
static void
928
set_active(struct hfsc_class *cl, unsigned int len)
929
{
930
        if (cl->cl_flags & HFSC_RSC)
931
                init_ed(cl, len);
932
        if (cl->cl_flags & HFSC_FSC)
933
                init_vf(cl, len);
934
 
935
        list_add_tail(&cl->dlist, &cl->sched->droplist);
936
}
937
 
938
static void
939
set_passive(struct hfsc_class *cl)
940
{
941
        if (cl->cl_flags & HFSC_RSC)
942
                ellist_remove(cl);
943
 
944
        list_del(&cl->dlist);
945
 
946
        /*
947
         * actlist is now handled in update_vf() so that update_vf(cl, 0, 0)
948
         * needs to be called explicitly to remove a class from actlist
949
         */
950
}
951
 
952
/*
953
 * hack to get length of first packet in queue.
954
 */
955
static unsigned int
956
qdisc_peek_len(struct Qdisc *sch)
957
{
958
        struct sk_buff *skb;
959
        unsigned int len;
960
 
961
        skb = sch->dequeue(sch);
962
        if (skb == NULL) {
963
                if (net_ratelimit())
964
                        printk("qdisc_peek_len: non work-conserving qdisc ?\n");
965
                return 0;
966
        }
967
        len = skb->len;
968
        if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) {
969
                if (net_ratelimit())
970
                        printk("qdisc_peek_len: failed to requeue\n");
971
                return 0;
972
        }
973
        return len;
974
}
975
 
976
static void
977
hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl)
978
{
979
        unsigned int len = cl->qdisc->q.qlen;
980
 
981
        qdisc_reset(cl->qdisc);
982
        if (len > 0) {
983
                update_vf(cl, 0, 0);
984
                set_passive(cl);
985
                sch->q.qlen -= len;
986
        }
987
}
988
 
989
static void
990
hfsc_adjust_levels(struct hfsc_class *cl)
991
{
992
        struct hfsc_class *p;
993
        unsigned int level;
994
 
995
        do {
996
                level = 0;
997
                list_for_each_entry(p, &cl->children, siblings) {
998
                        if (p->level > level)
999
                                level = p->level;
1000
                }
1001
                cl->level = level + 1;
1002
        } while ((cl = cl->cl_parent) != NULL);
1003
}
1004
 
1005
static inline unsigned int
1006
hfsc_hash(u32 h)
1007
{
1008
        h ^= h >> 8;
1009
        h ^= h >> 4;
1010
 
1011
        return h & (HFSC_HSIZE - 1);
1012
}
1013
 
1014
static inline struct hfsc_class *
1015
hfsc_find_class(u32 classid, struct Qdisc *sch)
1016
{
1017
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1018
        struct hfsc_class *cl;
1019
 
1020
        list_for_each_entry(cl, &q->clhash[hfsc_hash(classid)], hlist) {
1021
                if (cl->classid == classid)
1022
                        return cl;
1023
        }
1024
        return NULL;
1025
}
1026
 
1027
static void
1028
hfsc_change_rsc(struct hfsc_class *cl, struct tc_service_curve *rsc,
1029
                u64 cur_time)
1030
{
1031
        sc2isc(rsc, &cl->cl_rsc);
1032
        rtsc_init(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul);
1033
        cl->cl_eligible = cl->cl_deadline;
1034
        if (cl->cl_rsc.sm1 <= cl->cl_rsc.sm2) {
1035
                cl->cl_eligible.dx = 0;
1036
                cl->cl_eligible.dy = 0;
1037
        }
1038
        cl->cl_flags |= HFSC_RSC;
1039
}
1040
 
1041
static void
1042
hfsc_change_fsc(struct hfsc_class *cl, struct tc_service_curve *fsc)
1043
{
1044
        sc2isc(fsc, &cl->cl_fsc);
1045
        rtsc_init(&cl->cl_virtual, &cl->cl_fsc, cl->cl_vt, cl->cl_total);
1046
        cl->cl_flags |= HFSC_FSC;
1047
}
1048
 
1049
static void
1050
hfsc_change_usc(struct hfsc_class *cl, struct tc_service_curve *usc,
1051
                u64 cur_time)
1052
{
1053
        sc2isc(usc, &cl->cl_usc);
1054
        rtsc_init(&cl->cl_ulimit, &cl->cl_usc, cur_time, cl->cl_total);
1055
        cl->cl_flags |= HFSC_USC;
1056
}
1057
 
1058
static int
1059
hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
1060
                  struct rtattr **tca, unsigned long *arg)
1061
{
1062
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1063
        struct hfsc_class *cl = (struct hfsc_class *)*arg;
1064
        struct hfsc_class *parent = NULL;
1065
        struct rtattr *opt = tca[TCA_OPTIONS-1];
1066
        struct rtattr *tb[TCA_HFSC_MAX];
1067
        struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL;
1068
        u64 cur_time;
1069
 
1070
        if (opt == NULL ||
1071
            rtattr_parse(tb, TCA_HFSC_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)))
1072
                return -EINVAL;
1073
 
1074
        if (tb[TCA_HFSC_RSC-1]) {
1075
                if (RTA_PAYLOAD(tb[TCA_HFSC_RSC-1]) < sizeof(*rsc))
1076
                        return -EINVAL;
1077
                rsc = RTA_DATA(tb[TCA_HFSC_RSC-1]);
1078
                if (rsc->m1 == 0 && rsc->m2 == 0)
1079
                        rsc = NULL;
1080
        }
1081
 
1082
        if (tb[TCA_HFSC_FSC-1]) {
1083
                if (RTA_PAYLOAD(tb[TCA_HFSC_FSC-1]) < sizeof(*fsc))
1084
                        return -EINVAL;
1085
                fsc = RTA_DATA(tb[TCA_HFSC_FSC-1]);
1086
                if (fsc->m1 == 0 && fsc->m2 == 0)
1087
                        fsc = NULL;
1088
        }
1089
 
1090
        if (tb[TCA_HFSC_USC-1]) {
1091
                if (RTA_PAYLOAD(tb[TCA_HFSC_USC-1]) < sizeof(*usc))
1092
                        return -EINVAL;
1093
                usc = RTA_DATA(tb[TCA_HFSC_USC-1]);
1094
                if (usc->m1 == 0 && usc->m2 == 0)
1095
                        usc = NULL;
1096
        }
1097
 
1098
        if (cl != NULL) {
1099
                if (parentid) {
1100
                        if (cl->cl_parent && cl->cl_parent->classid != parentid)
1101
                                return -EINVAL;
1102
                        if (cl->cl_parent == NULL && parentid != TC_H_ROOT)
1103
                                return -EINVAL;
1104
                }
1105
                PSCHED_GET_TIME(cur_time);
1106
 
1107
                sch_tree_lock(sch);
1108
                if (rsc != NULL)
1109
                        hfsc_change_rsc(cl, rsc, cur_time);
1110
                if (fsc != NULL)
1111
                        hfsc_change_fsc(cl, fsc);
1112
                if (usc != NULL)
1113
                        hfsc_change_usc(cl, usc, cur_time);
1114
 
1115
                if (cl->qdisc->q.qlen != 0) {
1116
                        if (cl->cl_flags & HFSC_RSC)
1117
                                update_ed(cl, qdisc_peek_len(cl->qdisc));
1118
                        if (cl->cl_flags & HFSC_FSC)
1119
                                update_vf(cl, 0, cur_time);
1120
                }
1121
                sch_tree_unlock(sch);
1122
 
1123
#ifdef CONFIG_NET_ESTIMATOR
1124
                if (tca[TCA_RATE-1]) {
1125
                        qdisc_kill_estimator(&cl->stats);
1126
                        qdisc_new_estimator(&cl->stats, tca[TCA_RATE-1]);
1127
                }
1128
#endif
1129
                return 0;
1130
        }
1131
 
1132
        if (parentid == TC_H_ROOT)
1133
                return -EEXIST;
1134
 
1135
        parent = &q->root;
1136
        if (parentid) {
1137
                parent = hfsc_find_class(parentid, sch);
1138
                if (parent == NULL)
1139
                        return -ENOENT;
1140
        }
1141
 
1142
        if (classid == 0 || TC_H_MAJ(classid ^ sch->handle) != 0)
1143
                return -EINVAL;
1144
        if (hfsc_find_class(classid, sch))
1145
                return -EEXIST;
1146
 
1147
        if (rsc == NULL && fsc == NULL)
1148
                return -EINVAL;
1149
 
1150
        cl = kmalloc(sizeof(struct hfsc_class), GFP_KERNEL);
1151
        if (cl == NULL)
1152
                return -ENOBUFS;
1153
        memset(cl, 0, sizeof(struct hfsc_class));
1154
 
1155
        if (rsc != NULL)
1156
                hfsc_change_rsc(cl, rsc, 0);
1157
        if (fsc != NULL)
1158
                hfsc_change_fsc(cl, fsc);
1159
        if (usc != NULL)
1160
                hfsc_change_usc(cl, usc, 0);
1161
 
1162
        cl->refcnt    = 1;
1163
        cl->classid   = classid;
1164
        cl->sched     = q;
1165
        cl->cl_parent = parent;
1166
        cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
1167
        if (cl->qdisc == NULL)
1168
                cl->qdisc = &noop_qdisc;
1169
        cl->stats.lock = &sch->dev->queue_lock;
1170
        INIT_LIST_HEAD(&cl->children);
1171
        INIT_LIST_HEAD(&cl->actlist);
1172
 
1173
        sch_tree_lock(sch);
1174
        list_add_tail(&cl->hlist, &q->clhash[hfsc_hash(classid)]);
1175
        list_add_tail(&cl->siblings, &parent->children);
1176
        if (parent->level == 0)
1177
                hfsc_purge_queue(sch, parent);
1178
        hfsc_adjust_levels(parent);
1179
        sch_tree_unlock(sch);
1180
 
1181
#ifdef CONFIG_NET_ESTIMATOR
1182
        if (tca[TCA_RATE-1])
1183
                qdisc_new_estimator(&cl->stats, tca[TCA_RATE-1]);
1184
#endif
1185
        *arg = (unsigned long)cl;
1186
        return 0;
1187
}
1188
 
1189
static void
1190
hfsc_destroy_filters(struct tcf_proto **fl)
1191
{
1192
        struct tcf_proto *tp;
1193
 
1194
        while ((tp = *fl) != NULL) {
1195
                *fl = tp->next;
1196
                tcf_destroy(tp);
1197
        }
1198
}
1199
 
1200
static void
1201
hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl)
1202
{
1203
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1204
 
1205
        hfsc_destroy_filters(&cl->filter_list);
1206
        qdisc_destroy(cl->qdisc);
1207
#ifdef CONFIG_NET_ESTIMATOR
1208
        qdisc_kill_estimator(&cl->stats);
1209
#endif
1210
        if (cl != &q->root)
1211
                kfree(cl);
1212
}
1213
 
1214
static int
1215
hfsc_delete_class(struct Qdisc *sch, unsigned long arg)
1216
{
1217
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1218
        struct hfsc_class *cl = (struct hfsc_class *)arg;
1219
 
1220
        if (cl->level > 0 || cl->filter_cnt > 0 || cl == &q->root)
1221
                return -EBUSY;
1222
 
1223
        sch_tree_lock(sch);
1224
 
1225
        list_del(&cl->hlist);
1226
        list_del(&cl->siblings);
1227
        hfsc_adjust_levels(cl->cl_parent);
1228
        hfsc_purge_queue(sch, cl);
1229
        if (--cl->refcnt == 0)
1230
                hfsc_destroy_class(sch, cl);
1231
 
1232
        sch_tree_unlock(sch);
1233
        return 0;
1234
}
1235
 
1236
static struct hfsc_class *
1237
hfsc_classify(struct sk_buff *skb, struct Qdisc *sch)
1238
{
1239
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1240
        struct hfsc_class *cl;
1241
        struct tcf_result res;
1242
        struct tcf_proto *tcf;
1243
        int result;
1244
 
1245
        if (TC_H_MAJ(skb->priority ^ sch->handle) == 0 &&
1246
            (cl = hfsc_find_class(skb->priority, sch)) != NULL)
1247
                if (cl->level == 0)
1248
                        return cl;
1249
 
1250
        tcf = q->root.filter_list;
1251
        while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
1252
#ifdef CONFIG_NET_CLS_POLICE
1253
                if (result == TC_POLICE_SHOT)
1254
                        return NULL;
1255
#endif
1256
                if ((cl = (struct hfsc_class *)res.class) == NULL) {
1257
                        if ((cl = hfsc_find_class(res.classid, sch)) == NULL)
1258
                                break; /* filter selected invalid classid */
1259
                }
1260
 
1261
                if (cl->level == 0)
1262
                        return cl; /* hit leaf class */
1263
 
1264
                /* apply inner filter chain */
1265
                tcf = cl->filter_list;
1266
        }
1267
 
1268
        /* classification failed, try default class */
1269
        cl = hfsc_find_class(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch);
1270
        if (cl == NULL || cl->level > 0)
1271
                return NULL;
1272
 
1273
        return cl;
1274
}
1275
 
1276
static int
1277
hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
1278
                 struct Qdisc **old)
1279
{
1280
        struct hfsc_class *cl = (struct hfsc_class *)arg;
1281
 
1282
        if (cl == NULL)
1283
                return -ENOENT;
1284
        if (cl->level > 0)
1285
                return -EINVAL;
1286
        if (new == NULL) {
1287
                new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
1288
                if (new == NULL)
1289
                        new = &noop_qdisc;
1290
        }
1291
 
1292
        sch_tree_lock(sch);
1293
        hfsc_purge_queue(sch, cl);
1294
        *old = xchg(&cl->qdisc, new);
1295
        sch_tree_unlock(sch);
1296
        return 0;
1297
}
1298
 
1299
static struct Qdisc *
1300
hfsc_class_leaf(struct Qdisc *sch, unsigned long arg)
1301
{
1302
        struct hfsc_class *cl = (struct hfsc_class *)arg;
1303
 
1304
        if (cl != NULL && cl->level == 0)
1305
                return cl->qdisc;
1306
 
1307
        return NULL;
1308
}
1309
 
1310
static unsigned long
1311
hfsc_get_class(struct Qdisc *sch, u32 classid)
1312
{
1313
        struct hfsc_class *cl = hfsc_find_class(classid, sch);
1314
 
1315
        if (cl != NULL)
1316
                cl->refcnt++;
1317
 
1318
        return (unsigned long)cl;
1319
}
1320
 
1321
static void
1322
hfsc_put_class(struct Qdisc *sch, unsigned long arg)
1323
{
1324
        struct hfsc_class *cl = (struct hfsc_class *)arg;
1325
 
1326
        if (--cl->refcnt == 0)
1327
                hfsc_destroy_class(sch, cl);
1328
}
1329
 
1330
static unsigned long
1331
hfsc_bind_tcf(struct Qdisc *sch, unsigned long parent, u32 classid)
1332
{
1333
        struct hfsc_class *p = (struct hfsc_class *)parent;
1334
        struct hfsc_class *cl = hfsc_find_class(classid, sch);
1335
 
1336
        if (cl != NULL) {
1337
                if (p != NULL && p->level <= cl->level)
1338
                        return 0;
1339
                cl->filter_cnt++;
1340
        }
1341
 
1342
        return (unsigned long)cl;
1343
}
1344
 
1345
static void
1346
hfsc_unbind_tcf(struct Qdisc *sch, unsigned long arg)
1347
{
1348
        struct hfsc_class *cl = (struct hfsc_class *)arg;
1349
 
1350
        cl->filter_cnt--;
1351
}
1352
 
1353
static struct tcf_proto **
1354
hfsc_tcf_chain(struct Qdisc *sch, unsigned long arg)
1355
{
1356
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1357
        struct hfsc_class *cl = (struct hfsc_class *)arg;
1358
 
1359
        if (cl == NULL)
1360
                cl = &q->root;
1361
 
1362
        return &cl->filter_list;
1363
}
1364
 
1365
static int
1366
hfsc_dump_sc(struct sk_buff *skb, int attr, struct internal_sc *sc)
1367
{
1368
        struct tc_service_curve tsc;
1369
 
1370
        tsc.m1 = sm2m(sc->sm1);
1371
        tsc.d  = dx2d(sc->dx);
1372
        tsc.m2 = sm2m(sc->sm2);
1373
        RTA_PUT(skb, attr, sizeof(tsc), &tsc);
1374
 
1375
        return skb->len;
1376
 
1377
 rtattr_failure:
1378
        return -1;
1379
}
1380
 
1381
static inline int
1382
hfsc_dump_curves(struct sk_buff *skb, struct hfsc_class *cl)
1383
{
1384
        if ((cl->cl_flags & HFSC_RSC) &&
1385
            (hfsc_dump_sc(skb, TCA_HFSC_RSC, &cl->cl_rsc) < 0))
1386
                goto rtattr_failure;
1387
 
1388
        if ((cl->cl_flags & HFSC_FSC) &&
1389
            (hfsc_dump_sc(skb, TCA_HFSC_FSC, &cl->cl_fsc) < 0))
1390
                goto rtattr_failure;
1391
 
1392
        if ((cl->cl_flags & HFSC_USC) &&
1393
            (hfsc_dump_sc(skb, TCA_HFSC_USC, &cl->cl_usc) < 0))
1394
                goto rtattr_failure;
1395
 
1396
        return skb->len;
1397
 
1398
 rtattr_failure:
1399
        return -1;
1400
}
1401
 
1402
static inline int
1403
hfsc_dump_stats(struct sk_buff *skb, struct hfsc_class *cl)
1404
{
1405
        cl->stats.qlen = cl->qdisc->q.qlen;
1406
        if (qdisc_copy_stats(skb, &cl->stats) < 0)
1407
                goto rtattr_failure;
1408
 
1409
        return skb->len;
1410
 
1411
 rtattr_failure:
1412
        return -1;
1413
}
1414
 
1415
static inline int
1416
hfsc_dump_xstats(struct sk_buff *skb, struct hfsc_class *cl)
1417
{
1418
        struct tc_hfsc_stats xstats;
1419
 
1420
        xstats.level  = cl->level;
1421
        xstats.period = cl->cl_vtperiod;
1422
        xstats.work   = cl->cl_total;
1423
        xstats.rtwork = cl->cl_cumul;
1424
        RTA_PUT(skb, TCA_XSTATS, sizeof(xstats), &xstats);
1425
 
1426
        return skb->len;
1427
 
1428
 rtattr_failure:
1429
        return -1;
1430
}
1431
 
1432
static int
1433
hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb,
1434
                struct tcmsg *tcm)
1435
{
1436
        struct hfsc_class *cl = (struct hfsc_class *)arg;
1437
        unsigned char *b = skb->tail;
1438
        struct rtattr *rta = (struct rtattr *)b;
1439
 
1440
        tcm->tcm_parent = cl->cl_parent ? cl->cl_parent->classid : TC_H_ROOT;
1441
        tcm->tcm_handle = cl->classid;
1442
        if (cl->level == 0)
1443
                tcm->tcm_info = cl->qdisc->handle;
1444
 
1445
        RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
1446
        if (hfsc_dump_curves(skb, cl) < 0)
1447
                goto rtattr_failure;
1448
        rta->rta_len = skb->tail - b;
1449
 
1450
        if ((hfsc_dump_stats(skb, cl) < 0) ||
1451
            (hfsc_dump_xstats(skb, cl) < 0))
1452
                goto rtattr_failure;
1453
 
1454
        return skb->len;
1455
 
1456
 rtattr_failure:
1457
        skb_trim(skb, b - skb->data);
1458
        return -1;
1459
}
1460
 
1461
static void
1462
hfsc_walk(struct Qdisc *sch, struct qdisc_walker *arg)
1463
{
1464
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1465
        struct hfsc_class *cl;
1466
        unsigned int i;
1467
 
1468
        if (arg->stop)
1469
                return;
1470
 
1471
        for (i = 0; i < HFSC_HSIZE; i++) {
1472
                list_for_each_entry(cl, &q->clhash[i], hlist) {
1473
                        if (arg->count < arg->skip) {
1474
                                arg->count++;
1475
                                continue;
1476
                        }
1477
                        if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
1478
                                arg->stop = 1;
1479
                                return;
1480
                        }
1481
                        arg->count++;
1482
                }
1483
        }
1484
}
1485
 
1486
static void
1487
hfsc_watchdog(unsigned long arg)
1488
{
1489
        struct Qdisc *sch = (struct Qdisc *)arg;
1490
 
1491
        sch->flags &= ~TCQ_F_THROTTLED;
1492
        netif_schedule(sch->dev);
1493
}
1494
 
1495
static void
1496
hfsc_schedule_watchdog(struct Qdisc *sch, u64 cur_time)
1497
{
1498
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1499
        struct hfsc_class *cl;
1500
        u64 next_time = 0;
1501
        long delay;
1502
 
1503
        if ((cl = ellist_get_minel(&q->eligible)) != NULL)
1504
                next_time = cl->cl_e;
1505
        if (q->root.cl_cfmin != 0) {
1506
                if (next_time == 0 || next_time > q->root.cl_cfmin)
1507
                        next_time = q->root.cl_cfmin;
1508
        }
1509
        ASSERT(next_time != 0);
1510
        delay = next_time - cur_time;
1511
        delay = PSCHED_US2JIFFIE(delay);
1512
 
1513
        sch->flags |= TCQ_F_THROTTLED;
1514
        mod_timer(&q->wd_timer, jiffies + delay);
1515
}
1516
 
1517
static int
1518
hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
1519
{
1520
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1521
        struct tc_hfsc_qopt *qopt;
1522
        unsigned int i;
1523
 
1524
        if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
1525
                return -EINVAL;
1526
        qopt = RTA_DATA(opt);
1527
 
1528
        memset(q, 0, sizeof(struct hfsc_sched));
1529
        sch->stats.lock = &sch->dev->queue_lock;
1530
 
1531
        q->defcls = qopt->defcls;
1532
        for (i = 0; i < HFSC_HSIZE; i++)
1533
                INIT_LIST_HEAD(&q->clhash[i]);
1534
        INIT_LIST_HEAD(&q->eligible);
1535
        INIT_LIST_HEAD(&q->droplist);
1536
        skb_queue_head_init(&q->requeue);
1537
 
1538
        q->root.refcnt  = 1;
1539
        q->root.classid = sch->handle;
1540
        q->root.sched   = q;
1541
        q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
1542
        if (q->root.qdisc == NULL)
1543
                q->root.qdisc = &noop_qdisc;
1544
        q->root.stats.lock = &sch->dev->queue_lock;
1545
        INIT_LIST_HEAD(&q->root.children);
1546
        INIT_LIST_HEAD(&q->root.actlist);
1547
 
1548
        list_add(&q->root.hlist, &q->clhash[hfsc_hash(q->root.classid)]);
1549
 
1550
        init_timer(&q->wd_timer);
1551
        q->wd_timer.function = hfsc_watchdog;
1552
        q->wd_timer.data = (unsigned long)sch;
1553
 
1554
        MOD_INC_USE_COUNT;
1555
        return 0;
1556
}
1557
 
1558
static int
1559
hfsc_change_qdisc(struct Qdisc *sch, struct rtattr *opt)
1560
{
1561
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1562
        struct tc_hfsc_qopt *qopt;
1563
 
1564
        if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
1565
                return -EINVAL;;
1566
        qopt = RTA_DATA(opt);
1567
 
1568
        sch_tree_lock(sch);
1569
        q->defcls = qopt->defcls;
1570
        sch_tree_unlock(sch);
1571
 
1572
        return 0;
1573
}
1574
 
1575
static void
1576
hfsc_reset_class(struct hfsc_class *cl)
1577
{
1578
        cl->cl_total        = 0;
1579
        cl->cl_cumul        = 0;
1580
        cl->cl_d            = 0;
1581
        cl->cl_e            = 0;
1582
        cl->cl_vt           = 0;
1583
        cl->cl_vtadj        = 0;
1584
        cl->cl_vtoff        = 0;
1585
        cl->cl_cvtmin       = 0;
1586
        cl->cl_cvtmax       = 0;
1587
        cl->cl_vtperiod     = 0;
1588
        cl->cl_parentperiod = 0;
1589
        cl->cl_f            = 0;
1590
        cl->cl_myf          = 0;
1591
        cl->cl_myfadj       = 0;
1592
        cl->cl_cfmin        = 0;
1593
        cl->cl_nactive      = 0;
1594
        INIT_LIST_HEAD(&cl->actlist);
1595
        qdisc_reset(cl->qdisc);
1596
 
1597
        if (cl->cl_flags & HFSC_RSC)
1598
                rtsc_init(&cl->cl_deadline, &cl->cl_rsc, 0, 0);
1599
        if (cl->cl_flags & HFSC_FSC)
1600
                rtsc_init(&cl->cl_virtual, &cl->cl_fsc, 0, 0);
1601
        if (cl->cl_flags & HFSC_USC)
1602
                rtsc_init(&cl->cl_ulimit, &cl->cl_usc, 0, 0);
1603
}
1604
 
1605
static void
1606
hfsc_reset_qdisc(struct Qdisc *sch)
1607
{
1608
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1609
        struct hfsc_class *cl;
1610
        unsigned int i;
1611
 
1612
        for (i = 0; i < HFSC_HSIZE; i++) {
1613
                list_for_each_entry(cl, &q->clhash[i], hlist)
1614
                        hfsc_reset_class(cl);
1615
        }
1616
        __skb_queue_purge(&q->requeue);
1617
        INIT_LIST_HEAD(&q->eligible);
1618
        INIT_LIST_HEAD(&q->droplist);
1619
        del_timer(&q->wd_timer);
1620
        sch->flags &= ~TCQ_F_THROTTLED;
1621
        sch->q.qlen = 0;
1622
}
1623
 
1624
static void
1625
hfsc_destroy_qdisc(struct Qdisc *sch)
1626
{
1627
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1628
        struct hfsc_class *cl, *next;
1629
        unsigned int i;
1630
 
1631
        for (i = 0; i < HFSC_HSIZE; i++) {
1632
                list_for_each_entry_safe(cl, next, &q->clhash[i], hlist)
1633
                        hfsc_destroy_class(sch, cl);
1634
        }
1635
        __skb_queue_purge(&q->requeue);
1636
        del_timer(&q->wd_timer);
1637
        MOD_DEC_USE_COUNT;
1638
}
1639
 
1640
static int
1641
hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
1642
{
1643
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1644
        unsigned char *b = skb->tail;
1645
        struct tc_hfsc_qopt qopt;
1646
 
1647
        qopt.defcls = q->defcls;
1648
        RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
1649
 
1650
        sch->stats.qlen = sch->q.qlen;
1651
        if (qdisc_copy_stats(skb, &sch->stats) < 0)
1652
                goto rtattr_failure;
1653
 
1654
        return skb->len;
1655
 
1656
 rtattr_failure:
1657
        skb_trim(skb, b - skb->data);
1658
        return -1;
1659
}
1660
 
1661
static int
1662
hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
1663
{
1664
        struct hfsc_class *cl = hfsc_classify(skb, sch);
1665
        unsigned int len = skb->len;
1666
        int err;
1667
 
1668
        if (cl == NULL) {
1669
                kfree_skb(skb);
1670
                sch->stats.drops++;
1671
                return NET_XMIT_DROP;
1672
        }
1673
 
1674
        err = cl->qdisc->enqueue(skb, cl->qdisc);
1675
        if (unlikely(err != NET_XMIT_SUCCESS)) {
1676
                cl->stats.drops++;
1677
                sch->stats.drops++;
1678
                return err;
1679
        }
1680
 
1681
        if (cl->qdisc->q.qlen == 1)
1682
                set_active(cl, len);
1683
 
1684
        cl->stats.packets++;
1685
        cl->stats.bytes += len;
1686
        sch->stats.packets++;
1687
        sch->stats.bytes += len;
1688
        sch->q.qlen++;
1689
 
1690
        return NET_XMIT_SUCCESS;
1691
}
1692
 
1693
static struct sk_buff *
1694
hfsc_dequeue(struct Qdisc *sch)
1695
{
1696
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1697
        struct hfsc_class *cl;
1698
        struct sk_buff *skb;
1699
        u64 cur_time;
1700
        unsigned int next_len;
1701
        int realtime = 0;
1702
 
1703
        if (sch->q.qlen == 0)
1704
                return NULL;
1705
        if ((skb = __skb_dequeue(&q->requeue)))
1706
                goto out;
1707
 
1708
        PSCHED_GET_TIME(cur_time);
1709
 
1710
        /*
1711
         * if there are eligible classes, use real-time criteria.
1712
         * find the class with the minimum deadline among
1713
         * the eligible classes.
1714
         */
1715
        if ((cl = ellist_get_mindl(&q->eligible, cur_time)) != NULL) {
1716
                realtime = 1;
1717
        } else {
1718
                /*
1719
                 * use link-sharing criteria
1720
                 * get the class with the minimum vt in the hierarchy
1721
                 */
1722
                cl = actlist_get_minvt(&q->root, cur_time);
1723
                if (cl == NULL) {
1724
                        sch->stats.overlimits++;
1725
                        if (!netif_queue_stopped(sch->dev))
1726
                                hfsc_schedule_watchdog(sch, cur_time);
1727
                        return NULL;
1728
                }
1729
        }
1730
 
1731
        skb = cl->qdisc->dequeue(cl->qdisc);
1732
        if (skb == NULL) {
1733
                if (net_ratelimit())
1734
                        printk("HFSC: Non-work-conserving qdisc ?\n");
1735
                return NULL;
1736
        }
1737
 
1738
        update_vf(cl, skb->len, cur_time);
1739
        if (realtime)
1740
                cl->cl_cumul += skb->len;
1741
 
1742
        if (cl->qdisc->q.qlen != 0) {
1743
                if (cl->cl_flags & HFSC_RSC) {
1744
                        /* update ed */
1745
                        next_len = qdisc_peek_len(cl->qdisc);
1746
                        if (realtime)
1747
                                update_ed(cl, next_len);
1748
                        else
1749
                                update_d(cl, next_len);
1750
                }
1751
        } else {
1752
                /* the class becomes passive */
1753
                set_passive(cl);
1754
        }
1755
 
1756
 out:
1757
        sch->flags &= ~TCQ_F_THROTTLED;
1758
        sch->q.qlen--;
1759
 
1760
        return skb;
1761
}
1762
 
1763
static int
1764
hfsc_requeue(struct sk_buff *skb, struct Qdisc *sch)
1765
{
1766
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1767
 
1768
        __skb_queue_head(&q->requeue, skb);
1769
        sch->q.qlen++;
1770
        return NET_XMIT_SUCCESS;
1771
}
1772
 
1773
static unsigned int
1774
hfsc_drop(struct Qdisc *sch)
1775
{
1776
        struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
1777
        struct hfsc_class *cl;
1778
        unsigned int len;
1779
 
1780
        list_for_each_entry(cl, &q->droplist, dlist) {
1781
                if (cl->qdisc->ops->drop != NULL &&
1782
                    (len = cl->qdisc->ops->drop(cl->qdisc)) > 0) {
1783
                        if (cl->qdisc->q.qlen == 0) {
1784
                                update_vf(cl, 0, 0);
1785
                                set_passive(cl);
1786
                        } else {
1787
                                list_move_tail(&cl->dlist, &q->droplist);
1788
                        }
1789
                        cl->stats.drops++;
1790
                        sch->stats.drops++;
1791
                        sch->q.qlen--;
1792
                        return len;
1793
                }
1794
        }
1795
        return 0;
1796
}
1797
 
1798
static struct Qdisc_class_ops hfsc_class_ops = {
1799
        .change         = hfsc_change_class,
1800
        .delete         = hfsc_delete_class,
1801
        .graft          = hfsc_graft_class,
1802
        .leaf           = hfsc_class_leaf,
1803
        .get            = hfsc_get_class,
1804
        .put            = hfsc_put_class,
1805
        .bind_tcf       = hfsc_bind_tcf,
1806
        .unbind_tcf     = hfsc_unbind_tcf,
1807
        .tcf_chain      = hfsc_tcf_chain,
1808
        .dump           = hfsc_dump_class,
1809
        .walk           = hfsc_walk
1810
};
1811
 
1812
struct Qdisc_ops hfsc_qdisc_ops = {
1813
        .id             = "hfsc",
1814
        .init           = hfsc_init_qdisc,
1815
        .change         = hfsc_change_qdisc,
1816
        .reset          = hfsc_reset_qdisc,
1817
        .destroy        = hfsc_destroy_qdisc,
1818
        .dump           = hfsc_dump_qdisc,
1819
        .enqueue        = hfsc_enqueue,
1820
        .dequeue        = hfsc_dequeue,
1821
        .requeue        = hfsc_requeue,
1822
        .drop           = hfsc_drop,
1823
        .cl_ops         = &hfsc_class_ops,
1824
        .priv_size      = sizeof(struct hfsc_sched)
1825
};
1826
 
1827
static int __init
1828
hfsc_init(void)
1829
{
1830
        return register_qdisc(&hfsc_qdisc_ops);
1831
}
1832
 
1833
static void __exit
1834
hfsc_cleanup(void)
1835
{
1836
        unregister_qdisc(&hfsc_qdisc_ops);
1837
}
1838
 
1839
MODULE_LICENSE("GPL");
1840
module_init(hfsc_init);
1841
module_exit(hfsc_cleanup);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.