2 * net/sched/sch_api.c Packet scheduler API.
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
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
13 * Rani Assaf <rani@magic.metawire.com> :980802: JIFFIES and CPU clock sources are repaired.
14 * Eduardo J. Blanco <ejbs@netlabs.com.uy> :990222: kmod support
17 #include <linux/config.h>
18 #include <linux/types.h>
19 #include <linux/kernel.h>
20 #include <linux/sched.h>
21 #include <linux/string.h>
23 #include <linux/socket.h>
24 #include <linux/sockios.h>
26 #include <linux/errno.h>
27 #include <linux/interrupt.h>
28 #include <linux/netdevice.h>
29 #include <linux/skbuff.h>
30 #include <linux/rtnetlink.h>
31 #include <linux/init.h>
32 #include <linux/proc_fs.h>
33 #include <linux/kmod.h>
36 #include <net/pkt_sched.h>
38 #include <asm/processor.h>
39 #include <asm/uaccess.h>
40 #include <asm/system.h>
41 #include <asm/bitops.h>
43 #define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
45 #ifdef CONFIG_RTNETLINK
46 static int qdisc_notify(struct sk_buff
*oskb
, struct nlmsghdr
*n
, u32 clid
,
47 struct Qdisc
*old
, struct Qdisc
*new);
48 static int tclass_notify(struct sk_buff
*oskb
, struct nlmsghdr
*n
,
49 struct Qdisc
*q
, unsigned long cl
, int event
);
57 This file consists of two interrelated parts:
59 1. queueing disciplines manager frontend.
60 2. traffic classes manager frontend.
62 Generally, queueing discipline ("qdisc") is a black box,
63 which is able to enqueue packets and to dequeue them (when
64 device is ready to send something) in order and at times
65 determined by algorithm hidden in it.
67 qdisc's are divided to two categories:
68 - "queues", which have no internal structure visible from outside.
69 - "schedulers", which split all the packets to "traffic classes",
70 using "packet classifiers" (look at cls_api.c)
72 In turn, classes may have child qdiscs (as rule, queues)
73 attached to them etc. etc. etc.
75 The goal of the routines in this file is to translate
76 information supplied by user in the form of handles
77 to more intelligible for kernel form, to make some sanity
78 checks and part of work, which is common to all qdiscs
79 and to provide rtnetlink notifications.
81 All real intelligent work is done inside qdisc modules.
85 Every discipline has two major routines: enqueue and dequeue.
89 dequeue usually returns a skb to send. It is allowed to return NULL,
90 but it does not mean that queue is empty, it just means that
91 discipline does not want to send anything this time.
92 Queue is really empty if q->q.qlen == 0.
93 For complicated disciplines with multiple queues q->q is not
94 real packet queue, but however q->q.qlen must be valid.
98 enqueue returns number of enqueued packets i.e. this number is 1,
99 if packet was enqueued successfully and <1 if something (not
100 necessary THIS packet) was dropped.
106 requeues once dequeued packet. It is used for non-standard or
107 just buggy devices, which can defer output even if dev->tbusy=0.
111 returns qdisc to initial state: purge all buffers, clear all
112 timers, counters (except for statistics) etc.
116 initializes newly created qdisc.
120 destroys resources allocated by init and during lifetime of qdisc.
124 changes qdisc parameters.
127 /************************************************
128 * Queueing disciplines manipulation. *
129 ************************************************/
132 /* The list of all installed queueing disciplines. */
134 static struct Qdisc_ops
*qdisc_base
= NULL
;
136 /* Register/uregister queueing discipline */
138 int register_qdisc(struct Qdisc_ops
*qops
)
140 struct Qdisc_ops
*q
, **qp
;
142 for (qp
= &qdisc_base
; (q
=*qp
)!=NULL
; qp
= &q
->next
)
143 if (strcmp(qops
->id
, q
->id
) == 0)
146 if (qops
->enqueue
== NULL
)
147 qops
->enqueue
= noop_qdisc_ops
.enqueue
;
148 if (qops
->requeue
== NULL
)
149 qops
->requeue
= noop_qdisc_ops
.requeue
;
150 if (qops
->dequeue
== NULL
)
151 qops
->dequeue
= noop_qdisc_ops
.dequeue
;
158 int unregister_qdisc(struct Qdisc_ops
*qops
)
160 struct Qdisc_ops
*q
, **qp
;
161 for (qp
= &qdisc_base
; (q
=*qp
)!=NULL
; qp
= &q
->next
)
171 /* We know handle. Find qdisc among all qdisc's attached to device
172 (root qdisc, all its children, children of children etc.)
175 struct Qdisc
*qdisc_lookup(struct device
*dev
, u32 handle
)
179 for (q
= dev
->qdisc_list
; q
; q
= q
->next
) {
180 if (q
->handle
== handle
)
186 struct Qdisc
*qdisc_leaf(struct Qdisc
*p
, u32 classid
)
190 struct Qdisc_class_ops
*cops
= p
->ops
->cl_ops
;
194 cl
= cops
->get(p
, classid
);
197 leaf
= cops
->leaf(p
, cl
);
202 /* Find queueing discipline by name */
204 struct Qdisc_ops
*qdisc_lookup_ops(struct rtattr
*kind
)
209 for (q
= qdisc_base
; q
; q
= q
->next
) {
210 if (rtattr_strcmp(kind
, q
->id
) == 0)
217 static struct qdisc_rate_table
*qdisc_rtab_list
;
219 struct qdisc_rate_table
*qdisc_get_rtab(struct tc_ratespec
*r
, struct rtattr
*tab
)
221 struct qdisc_rate_table
*rtab
;
223 for (rtab
= qdisc_rtab_list
; rtab
; rtab
= rtab
->next
) {
224 if (memcmp(&rtab
->rate
, r
, sizeof(struct tc_ratespec
)) == 0) {
230 if (tab
== NULL
|| r
->rate
== 0 || r
->cell_log
== 0 || RTA_PAYLOAD(tab
) != 1024)
233 rtab
= kmalloc(sizeof(*rtab
), GFP_KERNEL
);
237 memcpy(rtab
->data
, RTA_DATA(tab
), 1024);
238 rtab
->next
= qdisc_rtab_list
;
239 qdisc_rtab_list
= rtab
;
244 void qdisc_put_rtab(struct qdisc_rate_table
*tab
)
246 struct qdisc_rate_table
*rtab
, **rtabp
;
248 if (!tab
|| --tab
->refcnt
)
251 for (rtabp
= &qdisc_rtab_list
; (rtab
=*rtabp
) != NULL
; rtabp
= &rtab
->next
) {
261 /* Allocate an unique handle from space managed by kernel */
263 u32
qdisc_alloc_handle(struct device
*dev
)
266 static u32 autohandle
= TC_H_MAKE(0x80000000U
, 0);
269 autohandle
+= TC_H_MAKE(0x10000U
, 0);
270 if (autohandle
== TC_H_MAKE(TC_H_ROOT
, 0))
271 autohandle
= TC_H_MAKE(0x80000000U
, 0);
272 } while (qdisc_lookup(dev
, autohandle
) && --i
> 0);
274 return i
>0 ? autohandle
: 0;
277 /* Attach toplevel qdisc to device dev */
279 static struct Qdisc
*
280 dev_graft_qdisc(struct device
*dev
, struct Qdisc
*qdisc
)
282 struct Qdisc
*oqdisc
;
284 if (dev
->flags
& IFF_UP
)
288 oqdisc
= dev
->qdisc_sleeping
;
290 /* Prune old scheduler */
291 if (oqdisc
&& atomic_read(&oqdisc
->refcnt
) <= 1)
294 /* ... and graft new one */
297 dev
->qdisc_sleeping
= qdisc
;
298 dev
->qdisc
= &noop_qdisc
;
301 if (dev
->flags
& IFF_UP
)
308 /* Graft qdisc "new" to class "classid" of qdisc "parent" or
311 Old qdisc is not destroyed but returned in *old.
314 int qdisc_graft(struct device
*dev
, struct Qdisc
*parent
, u32 classid
,
315 struct Qdisc
*new, struct Qdisc
**old
)
319 if (parent
== NULL
) {
320 *old
= dev_graft_qdisc(dev
, new);
322 struct Qdisc_class_ops
*cops
= parent
->ops
->cl_ops
;
327 unsigned long cl
= cops
->get(parent
, classid
);
329 err
= cops
->graft(parent
, cl
, new, old
);
330 cops
->put(parent
, cl
);
337 #ifdef CONFIG_RTNETLINK
340 Allocate and initialize new qdisc.
342 Parameters are passed via opt.
345 static struct Qdisc
*
346 qdisc_create(struct device
*dev
, u32 handle
, struct rtattr
**tca
, int *errp
)
349 struct rtattr
*kind
= tca
[TCA_KIND
-1];
350 struct Qdisc
*sch
= NULL
;
351 struct Qdisc_ops
*ops
;
354 ops
= qdisc_lookup_ops(kind
);
356 if (ops
==NULL
&& tca
[TCA_KIND
-1] != NULL
) {
357 char module_name
[4 + IFNAMSIZ
+ 1];
359 if (RTA_PAYLOAD(kind
) <= IFNAMSIZ
) {
360 sprintf(module_name
, "sch_%s", (char*)RTA_DATA(kind
));
361 request_module (module_name
);
362 ops
= qdisc_lookup_ops(kind
);
371 size
= sizeof(*sch
) + ops
->priv_size
;
373 sch
= kmalloc(size
, GFP_KERNEL
);
378 /* Grrr... Resolve race condition with module unload */
381 if (ops
!= qdisc_lookup_ops(kind
))
384 memset(sch
, 0, size
);
386 skb_queue_head_init(&sch
->q
);
388 sch
->enqueue
= ops
->enqueue
;
389 sch
->dequeue
= ops
->dequeue
;
391 atomic_set(&sch
->refcnt
, 1);
393 handle
= qdisc_alloc_handle(dev
);
398 sch
->handle
= handle
;
400 if (!ops
->init
|| (err
= ops
->init(sch
, tca
[TCA_OPTIONS
-1])) == 0) {
401 sch
->next
= dev
->qdisc_list
;
402 dev
->qdisc_list
= sch
;
403 #ifdef CONFIG_NET_ESTIMATOR
405 qdisc_new_estimator(&sch
->stats
, tca
[TCA_RATE
-1]);
417 static int qdisc_change(struct Qdisc
*sch
, struct rtattr
**tca
)
419 if (tca
[TCA_OPTIONS
-1]) {
422 if (sch
->ops
->change
== NULL
)
424 err
= sch
->ops
->change(sch
, tca
[TCA_OPTIONS
-1]);
428 #ifdef CONFIG_NET_ESTIMATOR
429 if (tca
[TCA_RATE
-1]) {
430 qdisc_kill_estimator(&sch
->stats
);
431 qdisc_new_estimator(&sch
->stats
, tca
[TCA_RATE
-1]);
437 struct check_loop_arg
439 struct qdisc_walker w
;
444 static int check_loop_fn(struct Qdisc
*q
, unsigned long cl
, struct qdisc_walker
*w
);
446 static int check_loop(struct Qdisc
*q
, struct Qdisc
*p
, int depth
)
448 struct check_loop_arg arg
;
450 if (q
->ops
->cl_ops
== NULL
)
453 arg
.w
.stop
= arg
.w
.skip
= arg
.w
.count
= 0;
454 arg
.w
.fn
= check_loop_fn
;
457 q
->ops
->cl_ops
->walk(q
, &arg
.w
);
458 return arg
.w
.stop
? -ELOOP
: 0;
462 check_loop_fn(struct Qdisc
*q
, unsigned long cl
, struct qdisc_walker
*w
)
465 struct Qdisc_class_ops
*cops
= q
->ops
->cl_ops
;
466 struct check_loop_arg
*arg
= (struct check_loop_arg
*)w
;
468 leaf
= cops
->leaf(q
, cl
);
470 if (leaf
== arg
->p
|| arg
->depth
> 7)
472 return check_loop(leaf
, arg
->p
, arg
->depth
+ 1);
481 static int tc_get_qdisc(struct sk_buff
*skb
, struct nlmsghdr
*n
, void *arg
)
483 struct tcmsg
*tcm
= NLMSG_DATA(n
);
484 struct rtattr
**tca
= arg
;
486 u32 clid
= tcm
->tcm_parent
;
487 struct Qdisc
*q
= NULL
;
488 struct Qdisc
*p
= NULL
;
491 if ((dev
= dev_get_by_index(tcm
->tcm_ifindex
)) == NULL
)
495 if (clid
!= TC_H_ROOT
) {
496 if ((p
= qdisc_lookup(dev
, TC_H_MAJ(clid
))) == NULL
)
498 q
= qdisc_leaf(p
, clid
);
500 q
= dev
->qdisc_sleeping
;
505 if (tcm
->tcm_handle
&& q
->handle
!= tcm
->tcm_handle
)
508 if ((q
= qdisc_lookup(dev
, tcm
->tcm_handle
)) == NULL
)
512 if (tca
[TCA_KIND
-1] && rtattr_strcmp(tca
[TCA_KIND
-1], q
->ops
->id
))
515 if (n
->nlmsg_type
== RTM_DELQDISC
) {
520 if ((err
= qdisc_graft(dev
, p
, clid
, NULL
, &q
)) != 0)
523 qdisc_notify(skb
, n
, clid
, q
, NULL
);
527 qdisc_notify(skb
, n
, clid
, NULL
, q
);
536 static int tc_modify_qdisc(struct sk_buff
*skb
, struct nlmsghdr
*n
, void *arg
)
538 struct tcmsg
*tcm
= NLMSG_DATA(n
);
539 struct rtattr
**tca
= arg
;
541 u32 clid
= tcm
->tcm_parent
;
542 struct Qdisc
*q
= NULL
;
543 struct Qdisc
*p
= NULL
;
546 if ((dev
= dev_get_by_index(tcm
->tcm_ifindex
)) == NULL
)
550 if (clid
!= TC_H_ROOT
) {
551 if ((p
= qdisc_lookup(dev
, TC_H_MAJ(clid
))) == NULL
)
553 q
= qdisc_leaf(p
, clid
);
555 q
= dev
->qdisc_sleeping
;
558 /* It may be default qdisc, ignore it */
559 if (q
&& q
->handle
== 0)
562 if (!q
|| !tcm
->tcm_handle
|| q
->handle
!= tcm
->tcm_handle
) {
563 if (tcm
->tcm_handle
) {
564 if (q
&& !(n
->nlmsg_flags
&NLM_F_REPLACE
))
566 if (TC_H_MIN(tcm
->tcm_handle
))
568 if ((q
= qdisc_lookup(dev
, tcm
->tcm_handle
)) == NULL
)
570 if (n
->nlmsg_flags
&NLM_F_EXCL
)
572 if (tca
[TCA_KIND
-1] && rtattr_strcmp(tca
[TCA_KIND
-1], q
->ops
->id
))
575 (p
&& check_loop(q
, p
, 0)))
577 atomic_inc(&q
->refcnt
);
583 /* This magic test requires explanation.
585 * We know, that some child q is already
586 * attached to this parent and have choice:
587 * either to change it or to create/graft new one.
589 * 1. We are allowed to create/graft only
590 * if CREATE and REPLACE flags are set.
592 * 2. If EXCL is set, requestor wanted to say,
593 * that qdisc tcm_handle is not expected
594 * to exist, so that we choose create/graft too.
596 * 3. The last case is when no flags are set.
597 * Alas, it is sort of hole in API, we
598 * cannot decide what to do unambiguously.
599 * For now we select create/graft, if
600 * user gave KIND, which does not match existing.
602 if ((n
->nlmsg_flags
&NLM_F_CREATE
) &&
603 (n
->nlmsg_flags
&NLM_F_REPLACE
) &&
604 ((n
->nlmsg_flags
&NLM_F_EXCL
) ||
606 rtattr_strcmp(tca
[TCA_KIND
-1], q
->ops
->id
))))
611 if (!tcm
->tcm_handle
)
613 q
= qdisc_lookup(dev
, tcm
->tcm_handle
);
616 /* Change qdisc parameters */
619 if (n
->nlmsg_flags
&NLM_F_EXCL
)
621 if (tca
[TCA_KIND
-1] && rtattr_strcmp(tca
[TCA_KIND
-1], q
->ops
->id
))
623 err
= qdisc_change(q
, tca
);
625 qdisc_notify(skb
, n
, clid
, NULL
, q
);
629 if (!(n
->nlmsg_flags
&NLM_F_CREATE
))
631 q
= qdisc_create(dev
, tcm
->tcm_handle
, tca
, &err
);
637 struct Qdisc
*old_q
= NULL
;
638 err
= qdisc_graft(dev
, p
, clid
, q
, &old_q
);
644 qdisc_notify(skb
, n
, clid
, old_q
, q
);
646 qdisc_destroy(old_q
);
651 static int tc_fill_qdisc(struct sk_buff
*skb
, struct Qdisc
*q
, u32 clid
,
652 u32 pid
, u32 seq
, unsigned flags
, int event
)
655 struct nlmsghdr
*nlh
;
656 unsigned char *b
= skb
->tail
;
658 nlh
= NLMSG_PUT(skb
, pid
, seq
, event
, sizeof(*tcm
));
659 nlh
->nlmsg_flags
= flags
;
660 tcm
= NLMSG_DATA(nlh
);
661 tcm
->tcm_family
= AF_UNSPEC
;
662 tcm
->tcm_ifindex
= q
->dev
? q
->dev
->ifindex
: 0;
663 tcm
->tcm_parent
= clid
;
664 tcm
->tcm_handle
= q
->handle
;
665 tcm
->tcm_info
= atomic_read(&q
->refcnt
);
666 RTA_PUT(skb
, TCA_KIND
, IFNAMSIZ
, q
->ops
->id
);
667 if (q
->ops
->dump
&& q
->ops
->dump(q
, skb
) < 0)
669 q
->stats
.qlen
= q
->q
.qlen
;
670 RTA_PUT(skb
, TCA_STATS
, sizeof(q
->stats
), &q
->stats
);
671 nlh
->nlmsg_len
= skb
->tail
- b
;
676 skb_trim(skb
, b
- skb
->data
);
680 static int qdisc_notify(struct sk_buff
*oskb
, struct nlmsghdr
*n
,
681 u32 clid
, struct Qdisc
*old
, struct Qdisc
*new)
684 u32 pid
= oskb
? NETLINK_CB(oskb
).pid
: 0;
686 skb
= alloc_skb(NLMSG_GOODSIZE
, GFP_KERNEL
);
690 if (old
&& old
->handle
) {
691 if (tc_fill_qdisc(skb
, old
, clid
, pid
, n
->nlmsg_seq
, 0, RTM_DELQDISC
) < 0)
695 if (tc_fill_qdisc(skb
, new, clid
, pid
, n
->nlmsg_seq
, old
? NLM_F_REPLACE
: 0, RTM_NEWQDISC
) < 0)
700 return rtnetlink_send(skb
, pid
, RTMGRP_TC
, n
->nlmsg_flags
&NLM_F_ECHO
);
707 static int tc_dump_qdisc(struct sk_buff
*skb
, struct netlink_callback
*cb
)
715 s_q_idx
= q_idx
= cb
->args
[1];
716 read_lock_bh(&dev_base_lock
);
717 for (dev
=dev_base
, idx
=0; dev
; dev
= dev
->next
, idx
++) {
722 for (q
= dev
->qdisc_list
, q_idx
= 0; q
;
723 q
= q
->next
, q_idx
++) {
726 if (tc_fill_qdisc(skb
, q
, 0, NETLINK_CB(cb
->skb
).pid
,
727 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
, RTM_NEWQDISC
) <= 0)
733 read_unlock_bh(&dev_base_lock
);
743 /************************************************
744 * Traffic classes manipulation. *
745 ************************************************/
749 static int tc_ctl_tclass(struct sk_buff
*skb
, struct nlmsghdr
*n
, void *arg
)
751 struct tcmsg
*tcm
= NLMSG_DATA(n
);
752 struct rtattr
**tca
= arg
;
754 struct Qdisc
*q
= NULL
;
755 struct Qdisc_class_ops
*cops
;
756 unsigned long cl
= 0;
757 unsigned long new_cl
;
758 u32 pid
= tcm
->tcm_parent
;
759 u32 clid
= tcm
->tcm_handle
;
760 u32 qid
= TC_H_MAJ(clid
);
763 if ((dev
= dev_get_by_index(tcm
->tcm_ifindex
)) == NULL
)
767 parent == TC_H_UNSPEC - unspecified parent.
768 parent == TC_H_ROOT - class is root, which has no parent.
769 parent == X:0 - parent is root class.
770 parent == X:Y - parent is a node in hierarchy.
771 parent == 0:Y - parent is X:Y, where X:0 is qdisc.
773 handle == 0:0 - generate handle from kernel pool.
774 handle == 0:Y - class is X:Y, where X:0 is qdisc.
775 handle == X:Y - clear.
776 handle == X:0 - root class.
779 /* Step 1. Determine qdisc handle X:0 */
781 if (pid
!= TC_H_ROOT
) {
782 u32 qid1
= TC_H_MAJ(pid
);
785 /* If both majors are known, they must be identical. */
791 qid
= dev
->qdisc_sleeping
->handle
;
793 /* Now qid is genuine qdisc handle consistent
794 both with parent and child.
796 TC_H_MAJ(pid) still may be unspecified, complete it now.
799 pid
= TC_H_MAKE(qid
, pid
);
802 qid
= dev
->qdisc_sleeping
->handle
;
805 /* OK. Locate qdisc */
806 if ((q
= qdisc_lookup(dev
, qid
)) == NULL
)
809 /* An check that it supports classes */
810 cops
= q
->ops
->cl_ops
;
814 /* Now try to get class */
816 if (pid
== TC_H_ROOT
)
819 clid
= TC_H_MAKE(qid
, clid
);
822 cl
= cops
->get(q
, clid
);
826 if (n
->nlmsg_type
!= RTM_NEWTCLASS
|| !(n
->nlmsg_flags
&NLM_F_CREATE
))
829 switch (n
->nlmsg_type
) {
832 if (n
->nlmsg_flags
&NLM_F_EXCL
)
836 err
= cops
->delete(q
, cl
);
838 tclass_notify(skb
, n
, q
, cl
, RTM_DELTCLASS
);
841 err
= tclass_notify(skb
, n
, q
, cl
, RTM_NEWTCLASS
);
850 err
= cops
->change(q
, clid
, pid
, tca
, &new_cl
);
852 tclass_notify(skb
, n
, q
, new_cl
, RTM_NEWTCLASS
);
862 static int tc_fill_tclass(struct sk_buff
*skb
, struct Qdisc
*q
,
864 u32 pid
, u32 seq
, unsigned flags
, int event
)
867 struct nlmsghdr
*nlh
;
868 unsigned char *b
= skb
->tail
;
870 nlh
= NLMSG_PUT(skb
, pid
, seq
, event
, sizeof(*tcm
));
871 nlh
->nlmsg_flags
= flags
;
872 tcm
= NLMSG_DATA(nlh
);
873 tcm
->tcm_family
= AF_UNSPEC
;
874 tcm
->tcm_ifindex
= q
->dev
? q
->dev
->ifindex
: 0;
875 tcm
->tcm_parent
= q
->handle
;
876 tcm
->tcm_handle
= q
->handle
;
878 RTA_PUT(skb
, TCA_KIND
, IFNAMSIZ
, q
->ops
->id
);
879 if (q
->ops
->cl_ops
->dump
&& q
->ops
->cl_ops
->dump(q
, cl
, skb
, tcm
) < 0)
881 nlh
->nlmsg_len
= skb
->tail
- b
;
886 skb_trim(skb
, b
- skb
->data
);
890 static int tclass_notify(struct sk_buff
*oskb
, struct nlmsghdr
*n
,
891 struct Qdisc
*q
, unsigned long cl
, int event
)
894 u32 pid
= oskb
? NETLINK_CB(oskb
).pid
: 0;
896 skb
= alloc_skb(NLMSG_GOODSIZE
, GFP_KERNEL
);
900 if (tc_fill_tclass(skb
, q
, cl
, pid
, n
->nlmsg_seq
, 0, event
) < 0) {
905 return rtnetlink_send(skb
, pid
, RTMGRP_TC
, n
->nlmsg_flags
&NLM_F_ECHO
);
908 struct qdisc_dump_args
910 struct qdisc_walker w
;
912 struct netlink_callback
*cb
;
915 static int qdisc_class_dump(struct Qdisc
*q
, unsigned long cl
, struct qdisc_walker
*arg
)
917 struct qdisc_dump_args
*a
= (struct qdisc_dump_args
*)arg
;
919 return tc_fill_tclass(a
->skb
, q
, cl
, NETLINK_CB(a
->cb
->skb
).pid
,
920 a
->cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
, RTM_NEWTCLASS
);
923 static int tc_dump_tclass(struct sk_buff
*skb
, struct netlink_callback
*cb
)
929 struct tcmsg
*tcm
= (struct tcmsg
*)NLMSG_DATA(cb
->nlh
);
930 struct qdisc_dump_args arg
;
932 if (cb
->nlh
->nlmsg_len
< NLMSG_LENGTH(sizeof(*tcm
)))
934 if ((dev
= dev_get_by_index(tcm
->tcm_ifindex
)) == NULL
)
939 for (q
=dev
->qdisc_list
, t
=0; q
; q
= q
->next
, t
++) {
940 if (t
< s_t
) continue;
941 if (!q
->ops
->cl_ops
) continue;
942 if (tcm
->tcm_parent
&& TC_H_MAJ(tcm
->tcm_parent
) != q
->handle
)
945 memset(&cb
->args
[1], 0, sizeof(cb
->args
)-sizeof(cb
->args
[0]));
946 arg
.w
.fn
= qdisc_class_dump
;
950 arg
.w
.skip
= cb
->args
[1];
952 q
->ops
->cl_ops
->walk(q
, &arg
.w
);
953 cb
->args
[1] = arg
.w
.count
;
964 int psched_us_per_tick
= 1;
965 int psched_tick_per_us
= 1;
967 #ifdef CONFIG_PROC_FS
968 static int psched_read_proc(char *buffer
, char **start
, off_t offset
,
969 int length
, int *eof
, void *data
)
973 len
= sprintf(buffer
, "%08x %08x\n",
974 psched_tick_per_us
, psched_us_per_tick
);
983 *start
= buffer
+ offset
;
990 #if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY
991 int psched_tod_diff(int delta_sec
, int bound
)
995 if (bound
<= 1000000 || delta_sec
> (0x7FFFFFFF/1000000)-1)
997 delta
= delta_sec
* 1000000;
1004 psched_time_t psched_time_base
;
1006 #if PSCHED_CLOCK_SOURCE == PSCHED_CPU
1007 psched_tdiff_t psched_clock_per_hz
;
1008 int psched_clock_scale
;
1011 #ifdef PSCHED_WATCHER
1012 PSCHED_WATCHER psched_time_mark
;
1014 static void psched_tick(unsigned long);
1016 static struct timer_list psched_timer
=
1017 { NULL
, NULL
, 0, 0L, psched_tick
};
1019 static void psched_tick(unsigned long dummy
)
1021 #if PSCHED_CLOCK_SOURCE == PSCHED_CPU
1022 psched_time_t dummy_stamp
;
1023 PSCHED_GET_TIME(dummy_stamp
);
1024 /* It is OK up to 4GHz cpu */
1025 psched_timer
.expires
= jiffies
+ 1*HZ
;
1027 unsigned long now
= jiffies
;
1028 psched_time_base
= ((u64
)now
)<<PSCHED_JSCALE
;
1029 psched_time_mark
= now
;
1030 psched_timer
.expires
= now
+ 60*60*HZ
;
1032 add_timer(&psched_timer
);
1036 #if PSCHED_CLOCK_SOURCE == PSCHED_CPU
1037 __initfunc(int psched_calibrate_clock(void))
1039 psched_time_t stamp
, stamp1
;
1040 struct timeval tv
, tv1
;
1041 psched_tdiff_t delay
;
1045 #if CPU == 586 || CPU == 686
1046 if (!(boot_cpu_data
.x86_capability
& X86_FEATURE_TSC
))
1050 #ifdef PSCHED_WATCHER
1053 stop
= jiffies
+ HZ
/10;
1054 PSCHED_GET_TIME(stamp
);
1055 do_gettimeofday(&tv
);
1056 while (time_before(jiffies
, stop
))
1058 PSCHED_GET_TIME(stamp1
);
1059 do_gettimeofday(&tv1
);
1061 delay
= PSCHED_TDIFF(stamp1
, stamp
);
1062 rdelay
= tv1
.tv_usec
- tv
.tv_usec
;
1063 rdelay
+= (tv1
.tv_sec
- tv
.tv_sec
)*1000000;
1067 psched_tick_per_us
= delay
;
1068 while ((delay
>>=1) != 0)
1069 psched_clock_scale
++;
1070 psched_us_per_tick
= 1<<psched_clock_scale
;
1071 psched_clock_per_hz
= (psched_tick_per_us
*(1000000/HZ
))>>psched_clock_scale
;
1076 __initfunc(int pktsched_init(void))
1078 #ifdef CONFIG_RTNETLINK
1079 struct rtnetlink_link
*link_p
;
1081 #ifdef CONFIG_PROC_FS
1082 struct proc_dir_entry
*ent
;
1085 #if PSCHED_CLOCK_SOURCE == PSCHED_CPU
1086 if (psched_calibrate_clock() < 0)
1088 #elif PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES
1089 psched_tick_per_us
= HZ
<<PSCHED_JSCALE
;
1090 psched_us_per_tick
= 1000000;
1091 #ifdef PSCHED_WATCHER
1096 #ifdef CONFIG_RTNETLINK
1097 link_p
= rtnetlink_links
[PF_UNSPEC
];
1099 /* Setup rtnetlink links. It is made here to avoid
1100 exporting large number of public symbols.
1104 link_p
[RTM_NEWQDISC
-RTM_BASE
].doit
= tc_modify_qdisc
;
1105 link_p
[RTM_DELQDISC
-RTM_BASE
].doit
= tc_get_qdisc
;
1106 link_p
[RTM_GETQDISC
-RTM_BASE
].doit
= tc_get_qdisc
;
1107 link_p
[RTM_GETQDISC
-RTM_BASE
].dumpit
= tc_dump_qdisc
;
1108 link_p
[RTM_NEWTCLASS
-RTM_BASE
].doit
= tc_ctl_tclass
;
1109 link_p
[RTM_DELTCLASS
-RTM_BASE
].doit
= tc_ctl_tclass
;
1110 link_p
[RTM_GETTCLASS
-RTM_BASE
].doit
= tc_ctl_tclass
;
1111 link_p
[RTM_GETTCLASS
-RTM_BASE
].dumpit
= tc_dump_tclass
;
1115 #define INIT_QDISC(name) { \
1116 extern struct Qdisc_ops name##_qdisc_ops; \
1117 register_qdisc(&##name##_qdisc_ops); \
1123 #ifdef CONFIG_NET_SCH_CBQ
1126 #ifdef CONFIG_NET_SCH_CSZ
1129 #ifdef CONFIG_NET_SCH_HPFQ
1132 #ifdef CONFIG_NET_SCH_HFSC
1135 #ifdef CONFIG_NET_SCH_RED
1138 #ifdef CONFIG_NET_SCH_GRED
1141 #ifdef CONFIG_NET_SCH_DSMARK
1144 #ifdef CONFIG_NET_SCH_SFQ
1147 #ifdef CONFIG_NET_SCH_TBF
1150 #ifdef CONFIG_NET_SCH_TEQL
1153 #ifdef CONFIG_NET_SCH_PRIO
1156 #ifdef CONFIG_NET_CLS
1160 #ifdef CONFIG_PROC_FS
1161 ent
= create_proc_entry("net/psched", 0, 0);
1162 ent
->read_proc
= psched_read_proc
;