net-sched: add dynamically sized qdisc class hash helpers
[safe/jmp/linux-2.6] / net / sched / sch_api.c
1 /*
2  * net/sched/sch_api.c  Packet scheduler API.
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
7  *              2 of the License, or (at your option) any later version.
8  *
9  * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10  *
11  * Fixes:
12  *
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
15  * Jamal Hadi Salim <hadi@nortelnetworks.com>: 990601: ingress support
16  */
17
18 #include <linux/module.h>
19 #include <linux/types.h>
20 #include <linux/kernel.h>
21 #include <linux/string.h>
22 #include <linux/errno.h>
23 #include <linux/skbuff.h>
24 #include <linux/init.h>
25 #include <linux/proc_fs.h>
26 #include <linux/seq_file.h>
27 #include <linux/kmod.h>
28 #include <linux/list.h>
29 #include <linux/hrtimer.h>
30
31 #include <net/net_namespace.h>
32 #include <net/sock.h>
33 #include <net/netlink.h>
34 #include <net/pkt_sched.h>
35
36 static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid,
37                         struct Qdisc *old, struct Qdisc *new);
38 static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n,
39                          struct Qdisc *q, unsigned long cl, int event);
40
41 /*
42
43    Short review.
44    -------------
45
46    This file consists of two interrelated parts:
47
48    1. queueing disciplines manager frontend.
49    2. traffic classes manager frontend.
50
51    Generally, queueing discipline ("qdisc") is a black box,
52    which is able to enqueue packets and to dequeue them (when
53    device is ready to send something) in order and at times
54    determined by algorithm hidden in it.
55
56    qdisc's are divided to two categories:
57    - "queues", which have no internal structure visible from outside.
58    - "schedulers", which split all the packets to "traffic classes",
59      using "packet classifiers" (look at cls_api.c)
60
61    In turn, classes may have child qdiscs (as rule, queues)
62    attached to them etc. etc. etc.
63
64    The goal of the routines in this file is to translate
65    information supplied by user in the form of handles
66    to more intelligible for kernel form, to make some sanity
67    checks and part of work, which is common to all qdiscs
68    and to provide rtnetlink notifications.
69
70    All real intelligent work is done inside qdisc modules.
71
72
73
74    Every discipline has two major routines: enqueue and dequeue.
75
76    ---dequeue
77
78    dequeue usually returns a skb to send. It is allowed to return NULL,
79    but it does not mean that queue is empty, it just means that
80    discipline does not want to send anything this time.
81    Queue is really empty if q->q.qlen == 0.
82    For complicated disciplines with multiple queues q->q is not
83    real packet queue, but however q->q.qlen must be valid.
84
85    ---enqueue
86
87    enqueue returns 0, if packet was enqueued successfully.
88    If packet (this one or another one) was dropped, it returns
89    not zero error code.
90    NET_XMIT_DROP        - this packet dropped
91      Expected action: do not backoff, but wait until queue will clear.
92    NET_XMIT_CN          - probably this packet enqueued, but another one dropped.
93      Expected action: backoff or ignore
94    NET_XMIT_POLICED     - dropped by police.
95      Expected action: backoff or error to real-time apps.
96
97    Auxiliary routines:
98
99    ---requeue
100
101    requeues once dequeued packet. It is used for non-standard or
102    just buggy devices, which can defer output even if dev->tbusy=0.
103
104    ---reset
105
106    returns qdisc to initial state: purge all buffers, clear all
107    timers, counters (except for statistics) etc.
108
109    ---init
110
111    initializes newly created qdisc.
112
113    ---destroy
114
115    destroys resources allocated by init and during lifetime of qdisc.
116
117    ---change
118
119    changes qdisc parameters.
120  */
121
122 /* Protects list of registered TC modules. It is pure SMP lock. */
123 static DEFINE_RWLOCK(qdisc_mod_lock);
124
125
126 /************************************************
127  *      Queueing disciplines manipulation.      *
128  ************************************************/
129
130
131 /* The list of all installed queueing disciplines. */
132
133 static struct Qdisc_ops *qdisc_base;
134
135 /* Register/uregister queueing discipline */
136
137 int register_qdisc(struct Qdisc_ops *qops)
138 {
139         struct Qdisc_ops *q, **qp;
140         int rc = -EEXIST;
141
142         write_lock(&qdisc_mod_lock);
143         for (qp = &qdisc_base; (q = *qp) != NULL; qp = &q->next)
144                 if (!strcmp(qops->id, q->id))
145                         goto out;
146
147         if (qops->enqueue == NULL)
148                 qops->enqueue = noop_qdisc_ops.enqueue;
149         if (qops->requeue == NULL)
150                 qops->requeue = noop_qdisc_ops.requeue;
151         if (qops->dequeue == NULL)
152                 qops->dequeue = noop_qdisc_ops.dequeue;
153
154         qops->next = NULL;
155         *qp = qops;
156         rc = 0;
157 out:
158         write_unlock(&qdisc_mod_lock);
159         return rc;
160 }
161 EXPORT_SYMBOL(register_qdisc);
162
163 int unregister_qdisc(struct Qdisc_ops *qops)
164 {
165         struct Qdisc_ops *q, **qp;
166         int err = -ENOENT;
167
168         write_lock(&qdisc_mod_lock);
169         for (qp = &qdisc_base; (q=*qp)!=NULL; qp = &q->next)
170                 if (q == qops)
171                         break;
172         if (q) {
173                 *qp = q->next;
174                 q->next = NULL;
175                 err = 0;
176         }
177         write_unlock(&qdisc_mod_lock);
178         return err;
179 }
180 EXPORT_SYMBOL(unregister_qdisc);
181
182 /* We know handle. Find qdisc among all qdisc's attached to device
183    (root qdisc, all its children, children of children etc.)
184  */
185
186 struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
187 {
188         struct Qdisc *q;
189
190         list_for_each_entry(q, &dev->qdisc_list, list) {
191                 if (q->handle == handle)
192                         return q;
193         }
194         return NULL;
195 }
196
197 static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid)
198 {
199         unsigned long cl;
200         struct Qdisc *leaf;
201         const struct Qdisc_class_ops *cops = p->ops->cl_ops;
202
203         if (cops == NULL)
204                 return NULL;
205         cl = cops->get(p, classid);
206
207         if (cl == 0)
208                 return NULL;
209         leaf = cops->leaf(p, cl);
210         cops->put(p, cl);
211         return leaf;
212 }
213
214 /* Find queueing discipline by name */
215
216 static struct Qdisc_ops *qdisc_lookup_ops(struct nlattr *kind)
217 {
218         struct Qdisc_ops *q = NULL;
219
220         if (kind) {
221                 read_lock(&qdisc_mod_lock);
222                 for (q = qdisc_base; q; q = q->next) {
223                         if (nla_strcmp(kind, q->id) == 0) {
224                                 if (!try_module_get(q->owner))
225                                         q = NULL;
226                                 break;
227                         }
228                 }
229                 read_unlock(&qdisc_mod_lock);
230         }
231         return q;
232 }
233
234 static struct qdisc_rate_table *qdisc_rtab_list;
235
236 struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *tab)
237 {
238         struct qdisc_rate_table *rtab;
239
240         for (rtab = qdisc_rtab_list; rtab; rtab = rtab->next) {
241                 if (memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) == 0) {
242                         rtab->refcnt++;
243                         return rtab;
244                 }
245         }
246
247         if (tab == NULL || r->rate == 0 || r->cell_log == 0 ||
248             nla_len(tab) != TC_RTAB_SIZE)
249                 return NULL;
250
251         rtab = kmalloc(sizeof(*rtab), GFP_KERNEL);
252         if (rtab) {
253                 rtab->rate = *r;
254                 rtab->refcnt = 1;
255                 memcpy(rtab->data, nla_data(tab), 1024);
256                 rtab->next = qdisc_rtab_list;
257                 qdisc_rtab_list = rtab;
258         }
259         return rtab;
260 }
261 EXPORT_SYMBOL(qdisc_get_rtab);
262
263 void qdisc_put_rtab(struct qdisc_rate_table *tab)
264 {
265         struct qdisc_rate_table *rtab, **rtabp;
266
267         if (!tab || --tab->refcnt)
268                 return;
269
270         for (rtabp = &qdisc_rtab_list; (rtab=*rtabp) != NULL; rtabp = &rtab->next) {
271                 if (rtab == tab) {
272                         *rtabp = rtab->next;
273                         kfree(rtab);
274                         return;
275                 }
276         }
277 }
278 EXPORT_SYMBOL(qdisc_put_rtab);
279
280 static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer)
281 {
282         struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog,
283                                                  timer);
284         struct net_device *dev = wd->qdisc->dev;
285
286         wd->qdisc->flags &= ~TCQ_F_THROTTLED;
287         smp_wmb();
288         netif_schedule(dev);
289
290         return HRTIMER_NORESTART;
291 }
292
293 void qdisc_watchdog_init(struct qdisc_watchdog *wd, struct Qdisc *qdisc)
294 {
295         hrtimer_init(&wd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
296         wd->timer.function = qdisc_watchdog;
297         wd->qdisc = qdisc;
298 }
299 EXPORT_SYMBOL(qdisc_watchdog_init);
300
301 void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires)
302 {
303         ktime_t time;
304
305         wd->qdisc->flags |= TCQ_F_THROTTLED;
306         time = ktime_set(0, 0);
307         time = ktime_add_ns(time, PSCHED_US2NS(expires));
308         hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS);
309 }
310 EXPORT_SYMBOL(qdisc_watchdog_schedule);
311
312 void qdisc_watchdog_cancel(struct qdisc_watchdog *wd)
313 {
314         hrtimer_cancel(&wd->timer);
315         wd->qdisc->flags &= ~TCQ_F_THROTTLED;
316 }
317 EXPORT_SYMBOL(qdisc_watchdog_cancel);
318
319 struct hlist_head *qdisc_class_hash_alloc(unsigned int n)
320 {
321         unsigned int size = n * sizeof(struct hlist_head), i;
322         struct hlist_head *h;
323
324         if (size <= PAGE_SIZE)
325                 h = kmalloc(size, GFP_KERNEL);
326         else
327                 h = (struct hlist_head *)
328                         __get_free_pages(GFP_KERNEL, get_order(size));
329
330         if (h != NULL) {
331                 for (i = 0; i < n; i++)
332                         INIT_HLIST_HEAD(&h[i]);
333         }
334         return h;
335 }
336
337 static void qdisc_class_hash_free(struct hlist_head *h, unsigned int n)
338 {
339         unsigned int size = n * sizeof(struct hlist_head);
340
341         if (size <= PAGE_SIZE)
342                 kfree(h);
343         else
344                 free_pages((unsigned long)h, get_order(size));
345 }
346
347 void qdisc_class_hash_grow(struct Qdisc *sch, struct Qdisc_class_hash *clhash)
348 {
349         struct Qdisc_class_common *cl;
350         struct hlist_node *n, *next;
351         struct hlist_head *nhash, *ohash;
352         unsigned int nsize, nmask, osize;
353         unsigned int i, h;
354
355         /* Rehash when load factor exceeds 0.75 */
356         if (clhash->hashelems * 4 <= clhash->hashsize * 3)
357                 return;
358         nsize = clhash->hashsize * 2;
359         nmask = nsize - 1;
360         nhash = qdisc_class_hash_alloc(nsize);
361         if (nhash == NULL)
362                 return;
363
364         ohash = clhash->hash;
365         osize = clhash->hashsize;
366
367         sch_tree_lock(sch);
368         for (i = 0; i < osize; i++) {
369                 hlist_for_each_entry_safe(cl, n, next, &ohash[i], hnode) {
370                         h = qdisc_class_hash(cl->classid, nmask);
371                         hlist_add_head(&cl->hnode, &nhash[h]);
372                 }
373         }
374         clhash->hash     = nhash;
375         clhash->hashsize = nsize;
376         clhash->hashmask = nmask;
377         sch_tree_unlock(sch);
378
379         qdisc_class_hash_free(ohash, osize);
380 }
381 EXPORT_SYMBOL(qdisc_class_hash_grow);
382
383 int qdisc_class_hash_init(struct Qdisc_class_hash *clhash)
384 {
385         unsigned int size = 4;
386
387         clhash->hash = qdisc_class_hash_alloc(size);
388         if (clhash->hash == NULL)
389                 return -ENOMEM;
390         clhash->hashsize  = size;
391         clhash->hashmask  = size - 1;
392         clhash->hashelems = 0;
393         return 0;
394 }
395 EXPORT_SYMBOL(qdisc_class_hash_init);
396
397 void qdisc_class_hash_destroy(struct Qdisc_class_hash *clhash)
398 {
399         qdisc_class_hash_free(clhash->hash, clhash->hashsize);
400 }
401 EXPORT_SYMBOL(qdisc_class_hash_destroy);
402
403 void qdisc_class_hash_insert(struct Qdisc_class_hash *clhash,
404                              struct Qdisc_class_common *cl)
405 {
406         unsigned int h;
407
408         INIT_HLIST_NODE(&cl->hnode);
409         h = qdisc_class_hash(cl->classid, clhash->hashmask);
410         hlist_add_head(&cl->hnode, &clhash->hash[h]);
411         clhash->hashelems++;
412 }
413 EXPORT_SYMBOL(qdisc_class_hash_insert);
414
415 void qdisc_class_hash_remove(struct Qdisc_class_hash *clhash,
416                              struct Qdisc_class_common *cl)
417 {
418         hlist_del(&cl->hnode);
419         clhash->hashelems--;
420 }
421 EXPORT_SYMBOL(qdisc_class_hash_remove);
422
423 /* Allocate an unique handle from space managed by kernel */
424
425 static u32 qdisc_alloc_handle(struct net_device *dev)
426 {
427         int i = 0x10000;
428         static u32 autohandle = TC_H_MAKE(0x80000000U, 0);
429
430         do {
431                 autohandle += TC_H_MAKE(0x10000U, 0);
432                 if (autohandle == TC_H_MAKE(TC_H_ROOT, 0))
433                         autohandle = TC_H_MAKE(0x80000000U, 0);
434         } while (qdisc_lookup(dev, autohandle) && --i > 0);
435
436         return i>0 ? autohandle : 0;
437 }
438
439 /* Attach toplevel qdisc to device dev */
440
441 static struct Qdisc *
442 dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc)
443 {
444         struct Qdisc *oqdisc;
445
446         if (dev->flags & IFF_UP)
447                 dev_deactivate(dev);
448
449         qdisc_lock_tree(dev);
450         if (qdisc && qdisc->flags&TCQ_F_INGRESS) {
451                 oqdisc = dev->qdisc_ingress;
452                 /* Prune old scheduler */
453                 if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) {
454                         /* delete */
455                         qdisc_reset(oqdisc);
456                         dev->qdisc_ingress = NULL;
457                 } else {  /* new */
458                         dev->qdisc_ingress = qdisc;
459                 }
460
461         } else {
462
463                 oqdisc = dev->qdisc_sleeping;
464
465                 /* Prune old scheduler */
466                 if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
467                         qdisc_reset(oqdisc);
468
469                 /* ... and graft new one */
470                 if (qdisc == NULL)
471                         qdisc = &noop_qdisc;
472                 dev->qdisc_sleeping = qdisc;
473                 dev->qdisc = &noop_qdisc;
474         }
475
476         qdisc_unlock_tree(dev);
477
478         if (dev->flags & IFF_UP)
479                 dev_activate(dev);
480
481         return oqdisc;
482 }
483
484 void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
485 {
486         const struct Qdisc_class_ops *cops;
487         unsigned long cl;
488         u32 parentid;
489
490         if (n == 0)
491                 return;
492         while ((parentid = sch->parent)) {
493                 if (TC_H_MAJ(parentid) == TC_H_MAJ(TC_H_INGRESS))
494                         return;
495
496                 sch = qdisc_lookup(sch->dev, TC_H_MAJ(parentid));
497                 if (sch == NULL) {
498                         WARN_ON(parentid != TC_H_ROOT);
499                         return;
500                 }
501                 cops = sch->ops->cl_ops;
502                 if (cops->qlen_notify) {
503                         cl = cops->get(sch, parentid);
504                         cops->qlen_notify(sch, cl);
505                         cops->put(sch, cl);
506                 }
507                 sch->q.qlen -= n;
508         }
509 }
510 EXPORT_SYMBOL(qdisc_tree_decrease_qlen);
511
512 /* Graft qdisc "new" to class "classid" of qdisc "parent" or
513    to device "dev".
514
515    Old qdisc is not destroyed but returned in *old.
516  */
517
518 static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
519                        u32 classid,
520                        struct Qdisc *new, struct Qdisc **old)
521 {
522         int err = 0;
523         struct Qdisc *q = *old;
524
525
526         if (parent == NULL) {
527                 if (q && q->flags&TCQ_F_INGRESS) {
528                         *old = dev_graft_qdisc(dev, q);
529                 } else {
530                         *old = dev_graft_qdisc(dev, new);
531                 }
532         } else {
533                 const struct Qdisc_class_ops *cops = parent->ops->cl_ops;
534
535                 err = -EINVAL;
536
537                 if (cops) {
538                         unsigned long cl = cops->get(parent, classid);
539                         if (cl) {
540                                 err = cops->graft(parent, cl, new, old);
541                                 cops->put(parent, cl);
542                         }
543                 }
544         }
545         return err;
546 }
547
548 /*
549    Allocate and initialize new qdisc.
550
551    Parameters are passed via opt.
552  */
553
554 static struct Qdisc *
555 qdisc_create(struct net_device *dev, u32 parent, u32 handle,
556            struct nlattr **tca, int *errp)
557 {
558         int err;
559         struct nlattr *kind = tca[TCA_KIND];
560         struct Qdisc *sch;
561         struct Qdisc_ops *ops;
562
563         ops = qdisc_lookup_ops(kind);
564 #ifdef CONFIG_KMOD
565         if (ops == NULL && kind != NULL) {
566                 char name[IFNAMSIZ];
567                 if (nla_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
568                         /* We dropped the RTNL semaphore in order to
569                          * perform the module load.  So, even if we
570                          * succeeded in loading the module we have to
571                          * tell the caller to replay the request.  We
572                          * indicate this using -EAGAIN.
573                          * We replay the request because the device may
574                          * go away in the mean time.
575                          */
576                         rtnl_unlock();
577                         request_module("sch_%s", name);
578                         rtnl_lock();
579                         ops = qdisc_lookup_ops(kind);
580                         if (ops != NULL) {
581                                 /* We will try again qdisc_lookup_ops,
582                                  * so don't keep a reference.
583                                  */
584                                 module_put(ops->owner);
585                                 err = -EAGAIN;
586                                 goto err_out;
587                         }
588                 }
589         }
590 #endif
591
592         err = -ENOENT;
593         if (ops == NULL)
594                 goto err_out;
595
596         sch = qdisc_alloc(dev, ops);
597         if (IS_ERR(sch)) {
598                 err = PTR_ERR(sch);
599                 goto err_out2;
600         }
601
602         sch->parent = parent;
603
604         if (handle == TC_H_INGRESS) {
605                 sch->flags |= TCQ_F_INGRESS;
606                 sch->stats_lock = &dev->ingress_lock;
607                 handle = TC_H_MAKE(TC_H_INGRESS, 0);
608         } else {
609                 sch->stats_lock = &dev->queue_lock;
610                 if (handle == 0) {
611                         handle = qdisc_alloc_handle(dev);
612                         err = -ENOMEM;
613                         if (handle == 0)
614                                 goto err_out3;
615                 }
616         }
617
618         sch->handle = handle;
619
620         if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS])) == 0) {
621                 if (tca[TCA_RATE]) {
622                         err = gen_new_estimator(&sch->bstats, &sch->rate_est,
623                                                 sch->stats_lock,
624                                                 tca[TCA_RATE]);
625                         if (err) {
626                                 /*
627                                  * Any broken qdiscs that would require
628                                  * a ops->reset() here? The qdisc was never
629                                  * in action so it shouldn't be necessary.
630                                  */
631                                 if (ops->destroy)
632                                         ops->destroy(sch);
633                                 goto err_out3;
634                         }
635                 }
636                 qdisc_lock_tree(dev);
637                 list_add_tail(&sch->list, &dev->qdisc_list);
638                 qdisc_unlock_tree(dev);
639
640                 return sch;
641         }
642 err_out3:
643         dev_put(dev);
644         kfree((char *) sch - sch->padded);
645 err_out2:
646         module_put(ops->owner);
647 err_out:
648         *errp = err;
649         return NULL;
650 }
651
652 static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
653 {
654         if (tca[TCA_OPTIONS]) {
655                 int err;
656
657                 if (sch->ops->change == NULL)
658                         return -EINVAL;
659                 err = sch->ops->change(sch, tca[TCA_OPTIONS]);
660                 if (err)
661                         return err;
662         }
663         if (tca[TCA_RATE])
664                 gen_replace_estimator(&sch->bstats, &sch->rate_est,
665                         sch->stats_lock, tca[TCA_RATE]);
666         return 0;
667 }
668
669 struct check_loop_arg
670 {
671         struct qdisc_walker     w;
672         struct Qdisc            *p;
673         int                     depth;
674 };
675
676 static int check_loop_fn(struct Qdisc *q, unsigned long cl, struct qdisc_walker *w);
677
678 static int check_loop(struct Qdisc *q, struct Qdisc *p, int depth)
679 {
680         struct check_loop_arg   arg;
681
682         if (q->ops->cl_ops == NULL)
683                 return 0;
684
685         arg.w.stop = arg.w.skip = arg.w.count = 0;
686         arg.w.fn = check_loop_fn;
687         arg.depth = depth;
688         arg.p = p;
689         q->ops->cl_ops->walk(q, &arg.w);
690         return arg.w.stop ? -ELOOP : 0;
691 }
692
693 static int
694 check_loop_fn(struct Qdisc *q, unsigned long cl, struct qdisc_walker *w)
695 {
696         struct Qdisc *leaf;
697         const struct Qdisc_class_ops *cops = q->ops->cl_ops;
698         struct check_loop_arg *arg = (struct check_loop_arg *)w;
699
700         leaf = cops->leaf(q, cl);
701         if (leaf) {
702                 if (leaf == arg->p || arg->depth > 7)
703                         return -ELOOP;
704                 return check_loop(leaf, arg->p, arg->depth + 1);
705         }
706         return 0;
707 }
708
709 /*
710  * Delete/get qdisc.
711  */
712
713 static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
714 {
715         struct net *net = sock_net(skb->sk);
716         struct tcmsg *tcm = NLMSG_DATA(n);
717         struct nlattr *tca[TCA_MAX + 1];
718         struct net_device *dev;
719         u32 clid = tcm->tcm_parent;
720         struct Qdisc *q = NULL;
721         struct Qdisc *p = NULL;
722         int err;
723
724         if (net != &init_net)
725                 return -EINVAL;
726
727         if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
728                 return -ENODEV;
729
730         err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
731         if (err < 0)
732                 return err;
733
734         if (clid) {
735                 if (clid != TC_H_ROOT) {
736                         if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) {
737                                 if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
738                                         return -ENOENT;
739                                 q = qdisc_leaf(p, clid);
740                         } else { /* ingress */
741                                 q = dev->qdisc_ingress;
742                         }
743                 } else {
744                         q = dev->qdisc_sleeping;
745                 }
746                 if (!q)
747                         return -ENOENT;
748
749                 if (tcm->tcm_handle && q->handle != tcm->tcm_handle)
750                         return -EINVAL;
751         } else {
752                 if ((q = qdisc_lookup(dev, tcm->tcm_handle)) == NULL)
753                         return -ENOENT;
754         }
755
756         if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id))
757                 return -EINVAL;
758
759         if (n->nlmsg_type == RTM_DELQDISC) {
760                 if (!clid)
761                         return -EINVAL;
762                 if (q->handle == 0)
763                         return -ENOENT;
764                 if ((err = qdisc_graft(dev, p, clid, NULL, &q)) != 0)
765                         return err;
766                 if (q) {
767                         qdisc_notify(skb, n, clid, q, NULL);
768                         qdisc_lock_tree(dev);
769                         qdisc_destroy(q);
770                         qdisc_unlock_tree(dev);
771                 }
772         } else {
773                 qdisc_notify(skb, n, clid, NULL, q);
774         }
775         return 0;
776 }
777
778 /*
779    Create/change qdisc.
780  */
781
782 static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
783 {
784         struct net *net = sock_net(skb->sk);
785         struct tcmsg *tcm;
786         struct nlattr *tca[TCA_MAX + 1];
787         struct net_device *dev;
788         u32 clid;
789         struct Qdisc *q, *p;
790         int err;
791
792         if (net != &init_net)
793                 return -EINVAL;
794
795 replay:
796         /* Reinit, just in case something touches this. */
797         tcm = NLMSG_DATA(n);
798         clid = tcm->tcm_parent;
799         q = p = NULL;
800
801         if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
802                 return -ENODEV;
803
804         err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
805         if (err < 0)
806                 return err;
807
808         if (clid) {
809                 if (clid != TC_H_ROOT) {
810                         if (clid != TC_H_INGRESS) {
811                                 if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
812                                         return -ENOENT;
813                                 q = qdisc_leaf(p, clid);
814                         } else { /*ingress */
815                                 q = dev->qdisc_ingress;
816                         }
817                 } else {
818                         q = dev->qdisc_sleeping;
819                 }
820
821                 /* It may be default qdisc, ignore it */
822                 if (q && q->handle == 0)
823                         q = NULL;
824
825                 if (!q || !tcm->tcm_handle || q->handle != tcm->tcm_handle) {
826                         if (tcm->tcm_handle) {
827                                 if (q && !(n->nlmsg_flags&NLM_F_REPLACE))
828                                         return -EEXIST;
829                                 if (TC_H_MIN(tcm->tcm_handle))
830                                         return -EINVAL;
831                                 if ((q = qdisc_lookup(dev, tcm->tcm_handle)) == NULL)
832                                         goto create_n_graft;
833                                 if (n->nlmsg_flags&NLM_F_EXCL)
834                                         return -EEXIST;
835                                 if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id))
836                                         return -EINVAL;
837                                 if (q == p ||
838                                     (p && check_loop(q, p, 0)))
839                                         return -ELOOP;
840                                 atomic_inc(&q->refcnt);
841                                 goto graft;
842                         } else {
843                                 if (q == NULL)
844                                         goto create_n_graft;
845
846                                 /* This magic test requires explanation.
847                                  *
848                                  *   We know, that some child q is already
849                                  *   attached to this parent and have choice:
850                                  *   either to change it or to create/graft new one.
851                                  *
852                                  *   1. We are allowed to create/graft only
853                                  *   if CREATE and REPLACE flags are set.
854                                  *
855                                  *   2. If EXCL is set, requestor wanted to say,
856                                  *   that qdisc tcm_handle is not expected
857                                  *   to exist, so that we choose create/graft too.
858                                  *
859                                  *   3. The last case is when no flags are set.
860                                  *   Alas, it is sort of hole in API, we
861                                  *   cannot decide what to do unambiguously.
862                                  *   For now we select create/graft, if
863                                  *   user gave KIND, which does not match existing.
864                                  */
865                                 if ((n->nlmsg_flags&NLM_F_CREATE) &&
866                                     (n->nlmsg_flags&NLM_F_REPLACE) &&
867                                     ((n->nlmsg_flags&NLM_F_EXCL) ||
868                                      (tca[TCA_KIND] &&
869                                       nla_strcmp(tca[TCA_KIND], q->ops->id))))
870                                         goto create_n_graft;
871                         }
872                 }
873         } else {
874                 if (!tcm->tcm_handle)
875                         return -EINVAL;
876                 q = qdisc_lookup(dev, tcm->tcm_handle);
877         }
878
879         /* Change qdisc parameters */
880         if (q == NULL)
881                 return -ENOENT;
882         if (n->nlmsg_flags&NLM_F_EXCL)
883                 return -EEXIST;
884         if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id))
885                 return -EINVAL;
886         err = qdisc_change(q, tca);
887         if (err == 0)
888                 qdisc_notify(skb, n, clid, NULL, q);
889         return err;
890
891 create_n_graft:
892         if (!(n->nlmsg_flags&NLM_F_CREATE))
893                 return -ENOENT;
894         if (clid == TC_H_INGRESS)
895                 q = qdisc_create(dev, tcm->tcm_parent, tcm->tcm_parent,
896                                  tca, &err);
897         else
898                 q = qdisc_create(dev, tcm->tcm_parent, tcm->tcm_handle,
899                                  tca, &err);
900         if (q == NULL) {
901                 if (err == -EAGAIN)
902                         goto replay;
903                 return err;
904         }
905
906 graft:
907         if (1) {
908                 struct Qdisc *old_q = NULL;
909                 err = qdisc_graft(dev, p, clid, q, &old_q);
910                 if (err) {
911                         if (q) {
912                                 qdisc_lock_tree(dev);
913                                 qdisc_destroy(q);
914                                 qdisc_unlock_tree(dev);
915                         }
916                         return err;
917                 }
918                 qdisc_notify(skb, n, clid, old_q, q);
919                 if (old_q) {
920                         qdisc_lock_tree(dev);
921                         qdisc_destroy(old_q);
922                         qdisc_unlock_tree(dev);
923                 }
924         }
925         return 0;
926 }
927
928 static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
929                          u32 pid, u32 seq, u16 flags, int event)
930 {
931         struct tcmsg *tcm;
932         struct nlmsghdr  *nlh;
933         unsigned char *b = skb_tail_pointer(skb);
934         struct gnet_dump d;
935
936         nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
937         tcm = NLMSG_DATA(nlh);
938         tcm->tcm_family = AF_UNSPEC;
939         tcm->tcm__pad1 = 0;
940         tcm->tcm__pad2 = 0;
941         tcm->tcm_ifindex = q->dev->ifindex;
942         tcm->tcm_parent = clid;
943         tcm->tcm_handle = q->handle;
944         tcm->tcm_info = atomic_read(&q->refcnt);
945         NLA_PUT_STRING(skb, TCA_KIND, q->ops->id);
946         if (q->ops->dump && q->ops->dump(q, skb) < 0)
947                 goto nla_put_failure;
948         q->qstats.qlen = q->q.qlen;
949
950         if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
951                         TCA_XSTATS, q->stats_lock, &d) < 0)
952                 goto nla_put_failure;
953
954         if (q->ops->dump_stats && q->ops->dump_stats(q, &d) < 0)
955                 goto nla_put_failure;
956
957         if (gnet_stats_copy_basic(&d, &q->bstats) < 0 ||
958             gnet_stats_copy_rate_est(&d, &q->rate_est) < 0 ||
959             gnet_stats_copy_queue(&d, &q->qstats) < 0)
960                 goto nla_put_failure;
961
962         if (gnet_stats_finish_copy(&d) < 0)
963                 goto nla_put_failure;
964
965         nlh->nlmsg_len = skb_tail_pointer(skb) - b;
966         return skb->len;
967
968 nlmsg_failure:
969 nla_put_failure:
970         nlmsg_trim(skb, b);
971         return -1;
972 }
973
974 static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n,
975                         u32 clid, struct Qdisc *old, struct Qdisc *new)
976 {
977         struct sk_buff *skb;
978         u32 pid = oskb ? NETLINK_CB(oskb).pid : 0;
979
980         skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
981         if (!skb)
982                 return -ENOBUFS;
983
984         if (old && old->handle) {
985                 if (tc_fill_qdisc(skb, old, clid, pid, n->nlmsg_seq, 0, RTM_DELQDISC) < 0)
986                         goto err_out;
987         }
988         if (new) {
989                 if (tc_fill_qdisc(skb, new, clid, pid, n->nlmsg_seq, old ? NLM_F_REPLACE : 0, RTM_NEWQDISC) < 0)
990                         goto err_out;
991         }
992
993         if (skb->len)
994                 return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
995
996 err_out:
997         kfree_skb(skb);
998         return -EINVAL;
999 }
1000
1001 static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
1002 {
1003         struct net *net = sock_net(skb->sk);
1004         int idx, q_idx;
1005         int s_idx, s_q_idx;
1006         struct net_device *dev;
1007         struct Qdisc *q;
1008
1009         if (net != &init_net)
1010                 return 0;
1011
1012         s_idx = cb->args[0];
1013         s_q_idx = q_idx = cb->args[1];
1014         read_lock(&dev_base_lock);
1015         idx = 0;
1016         for_each_netdev(&init_net, dev) {
1017                 if (idx < s_idx)
1018                         goto cont;
1019                 if (idx > s_idx)
1020                         s_q_idx = 0;
1021                 q_idx = 0;
1022                 list_for_each_entry(q, &dev->qdisc_list, list) {
1023                         if (q_idx < s_q_idx) {
1024                                 q_idx++;
1025                                 continue;
1026                         }
1027                         if (tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid,
1028                                           cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0)
1029                                 goto done;
1030                         q_idx++;
1031                 }
1032 cont:
1033                 idx++;
1034         }
1035
1036 done:
1037         read_unlock(&dev_base_lock);
1038
1039         cb->args[0] = idx;
1040         cb->args[1] = q_idx;
1041
1042         return skb->len;
1043 }
1044
1045
1046
1047 /************************************************
1048  *      Traffic classes manipulation.           *
1049  ************************************************/
1050
1051
1052
1053 static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1054 {
1055         struct net *net = sock_net(skb->sk);
1056         struct tcmsg *tcm = NLMSG_DATA(n);
1057         struct nlattr *tca[TCA_MAX + 1];
1058         struct net_device *dev;
1059         struct Qdisc *q = NULL;
1060         const struct Qdisc_class_ops *cops;
1061         unsigned long cl = 0;
1062         unsigned long new_cl;
1063         u32 pid = tcm->tcm_parent;
1064         u32 clid = tcm->tcm_handle;
1065         u32 qid = TC_H_MAJ(clid);
1066         int err;
1067
1068         if (net != &init_net)
1069                 return -EINVAL;
1070
1071         if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
1072                 return -ENODEV;
1073
1074         err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
1075         if (err < 0)
1076                 return err;
1077
1078         /*
1079            parent == TC_H_UNSPEC - unspecified parent.
1080            parent == TC_H_ROOT   - class is root, which has no parent.
1081            parent == X:0         - parent is root class.
1082            parent == X:Y         - parent is a node in hierarchy.
1083            parent == 0:Y         - parent is X:Y, where X:0 is qdisc.
1084
1085            handle == 0:0         - generate handle from kernel pool.
1086            handle == 0:Y         - class is X:Y, where X:0 is qdisc.
1087            handle == X:Y         - clear.
1088            handle == X:0         - root class.
1089          */
1090
1091         /* Step 1. Determine qdisc handle X:0 */
1092
1093         if (pid != TC_H_ROOT) {
1094                 u32 qid1 = TC_H_MAJ(pid);
1095
1096                 if (qid && qid1) {
1097                         /* If both majors are known, they must be identical. */
1098                         if (qid != qid1)
1099                                 return -EINVAL;
1100                 } else if (qid1) {
1101                         qid = qid1;
1102                 } else if (qid == 0)
1103                         qid = dev->qdisc_sleeping->handle;
1104
1105                 /* Now qid is genuine qdisc handle consistent
1106                    both with parent and child.
1107
1108                    TC_H_MAJ(pid) still may be unspecified, complete it now.
1109                  */
1110                 if (pid)
1111                         pid = TC_H_MAKE(qid, pid);
1112         } else {
1113                 if (qid == 0)
1114                         qid = dev->qdisc_sleeping->handle;
1115         }
1116
1117         /* OK. Locate qdisc */
1118         if ((q = qdisc_lookup(dev, qid)) == NULL)
1119                 return -ENOENT;
1120
1121         /* An check that it supports classes */
1122         cops = q->ops->cl_ops;
1123         if (cops == NULL)
1124                 return -EINVAL;
1125
1126         /* Now try to get class */
1127         if (clid == 0) {
1128                 if (pid == TC_H_ROOT)
1129                         clid = qid;
1130         } else
1131                 clid = TC_H_MAKE(qid, clid);
1132
1133         if (clid)
1134                 cl = cops->get(q, clid);
1135
1136         if (cl == 0) {
1137                 err = -ENOENT;
1138                 if (n->nlmsg_type != RTM_NEWTCLASS || !(n->nlmsg_flags&NLM_F_CREATE))
1139                         goto out;
1140         } else {
1141                 switch (n->nlmsg_type) {
1142                 case RTM_NEWTCLASS:
1143                         err = -EEXIST;
1144                         if (n->nlmsg_flags&NLM_F_EXCL)
1145                                 goto out;
1146                         break;
1147                 case RTM_DELTCLASS:
1148                         err = cops->delete(q, cl);
1149                         if (err == 0)
1150                                 tclass_notify(skb, n, q, cl, RTM_DELTCLASS);
1151                         goto out;
1152                 case RTM_GETTCLASS:
1153                         err = tclass_notify(skb, n, q, cl, RTM_NEWTCLASS);
1154                         goto out;
1155                 default:
1156                         err = -EINVAL;
1157                         goto out;
1158                 }
1159         }
1160
1161         new_cl = cl;
1162         err = cops->change(q, clid, pid, tca, &new_cl);
1163         if (err == 0)
1164                 tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS);
1165
1166 out:
1167         if (cl)
1168                 cops->put(q, cl);
1169
1170         return err;
1171 }
1172
1173
1174 static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q,
1175                           unsigned long cl,
1176                           u32 pid, u32 seq, u16 flags, int event)
1177 {
1178         struct tcmsg *tcm;
1179         struct nlmsghdr  *nlh;
1180         unsigned char *b = skb_tail_pointer(skb);
1181         struct gnet_dump d;
1182         const struct Qdisc_class_ops *cl_ops = q->ops->cl_ops;
1183
1184         nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
1185         tcm = NLMSG_DATA(nlh);
1186         tcm->tcm_family = AF_UNSPEC;
1187         tcm->tcm_ifindex = q->dev->ifindex;
1188         tcm->tcm_parent = q->handle;
1189         tcm->tcm_handle = q->handle;
1190         tcm->tcm_info = 0;
1191         NLA_PUT_STRING(skb, TCA_KIND, q->ops->id);
1192         if (cl_ops->dump && cl_ops->dump(q, cl, skb, tcm) < 0)
1193                 goto nla_put_failure;
1194
1195         if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
1196                         TCA_XSTATS, q->stats_lock, &d) < 0)
1197                 goto nla_put_failure;
1198
1199         if (cl_ops->dump_stats && cl_ops->dump_stats(q, cl, &d) < 0)
1200                 goto nla_put_failure;
1201
1202         if (gnet_stats_finish_copy(&d) < 0)
1203                 goto nla_put_failure;
1204
1205         nlh->nlmsg_len = skb_tail_pointer(skb) - b;
1206         return skb->len;
1207
1208 nlmsg_failure:
1209 nla_put_failure:
1210         nlmsg_trim(skb, b);
1211         return -1;
1212 }
1213
1214 static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n,
1215                           struct Qdisc *q, unsigned long cl, int event)
1216 {
1217         struct sk_buff *skb;
1218         u32 pid = oskb ? NETLINK_CB(oskb).pid : 0;
1219
1220         skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1221         if (!skb)
1222                 return -ENOBUFS;
1223
1224         if (tc_fill_tclass(skb, q, cl, pid, n->nlmsg_seq, 0, event) < 0) {
1225                 kfree_skb(skb);
1226                 return -EINVAL;
1227         }
1228
1229         return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
1230 }
1231
1232 struct qdisc_dump_args
1233 {
1234         struct qdisc_walker w;
1235         struct sk_buff *skb;
1236         struct netlink_callback *cb;
1237 };
1238
1239 static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walker *arg)
1240 {
1241         struct qdisc_dump_args *a = (struct qdisc_dump_args *)arg;
1242
1243         return tc_fill_tclass(a->skb, q, cl, NETLINK_CB(a->cb->skb).pid,
1244                               a->cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWTCLASS);
1245 }
1246
1247 static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
1248 {
1249         struct net *net = sock_net(skb->sk);
1250         int t;
1251         int s_t;
1252         struct net_device *dev;
1253         struct Qdisc *q;
1254         struct tcmsg *tcm = (struct tcmsg*)NLMSG_DATA(cb->nlh);
1255         struct qdisc_dump_args arg;
1256
1257         if (net != &init_net)
1258                 return 0;
1259
1260         if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm)))
1261                 return 0;
1262         if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
1263                 return 0;
1264
1265         s_t = cb->args[0];
1266         t = 0;
1267
1268         list_for_each_entry(q, &dev->qdisc_list, list) {
1269                 if (t < s_t || !q->ops->cl_ops ||
1270                     (tcm->tcm_parent &&
1271                      TC_H_MAJ(tcm->tcm_parent) != q->handle)) {
1272                         t++;
1273                         continue;
1274                 }
1275                 if (t > s_t)
1276                         memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
1277                 arg.w.fn = qdisc_class_dump;
1278                 arg.skb = skb;
1279                 arg.cb = cb;
1280                 arg.w.stop  = 0;
1281                 arg.w.skip = cb->args[1];
1282                 arg.w.count = 0;
1283                 q->ops->cl_ops->walk(q, &arg.w);
1284                 cb->args[1] = arg.w.count;
1285                 if (arg.w.stop)
1286                         break;
1287                 t++;
1288         }
1289
1290         cb->args[0] = t;
1291
1292         dev_put(dev);
1293         return skb->len;
1294 }
1295
1296 /* Main classifier routine: scans classifier chain attached
1297    to this qdisc, (optionally) tests for protocol and asks
1298    specific classifiers.
1299  */
1300 int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp,
1301                        struct tcf_result *res)
1302 {
1303         __be16 protocol = skb->protocol;
1304         int err = 0;
1305
1306         for (; tp; tp = tp->next) {
1307                 if ((tp->protocol == protocol ||
1308                      tp->protocol == htons(ETH_P_ALL)) &&
1309                     (err = tp->classify(skb, tp, res)) >= 0) {
1310 #ifdef CONFIG_NET_CLS_ACT
1311                         if (err != TC_ACT_RECLASSIFY && skb->tc_verd)
1312                                 skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0);
1313 #endif
1314                         return err;
1315                 }
1316         }
1317         return -1;
1318 }
1319 EXPORT_SYMBOL(tc_classify_compat);
1320
1321 int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
1322                 struct tcf_result *res)
1323 {
1324         int err = 0;
1325         __be16 protocol;
1326 #ifdef CONFIG_NET_CLS_ACT
1327         struct tcf_proto *otp = tp;
1328 reclassify:
1329 #endif
1330         protocol = skb->protocol;
1331
1332         err = tc_classify_compat(skb, tp, res);
1333 #ifdef CONFIG_NET_CLS_ACT
1334         if (err == TC_ACT_RECLASSIFY) {
1335                 u32 verd = G_TC_VERD(skb->tc_verd);
1336                 tp = otp;
1337
1338                 if (verd++ >= MAX_REC_LOOP) {
1339                         printk("rule prio %u protocol %02x reclassify loop, "
1340                                "packet dropped\n",
1341                                tp->prio&0xffff, ntohs(tp->protocol));
1342                         return TC_ACT_SHOT;
1343                 }
1344                 skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd);
1345                 goto reclassify;
1346         }
1347 #endif
1348         return err;
1349 }
1350 EXPORT_SYMBOL(tc_classify);
1351
1352 void tcf_destroy(struct tcf_proto *tp)
1353 {
1354         tp->ops->destroy(tp);
1355         module_put(tp->ops->owner);
1356         kfree(tp);
1357 }
1358
1359 void tcf_destroy_chain(struct tcf_proto **fl)
1360 {
1361         struct tcf_proto *tp;
1362
1363         while ((tp = *fl) != NULL) {
1364                 *fl = tp->next;
1365                 tcf_destroy(tp);
1366         }
1367 }
1368 EXPORT_SYMBOL(tcf_destroy_chain);
1369
1370 #ifdef CONFIG_PROC_FS
1371 static int psched_show(struct seq_file *seq, void *v)
1372 {
1373         struct timespec ts;
1374
1375         hrtimer_get_res(CLOCK_MONOTONIC, &ts);
1376         seq_printf(seq, "%08x %08x %08x %08x\n",
1377                    (u32)NSEC_PER_USEC, (u32)PSCHED_US2NS(1),
1378                    1000000,
1379                    (u32)NSEC_PER_SEC/(u32)ktime_to_ns(timespec_to_ktime(ts)));
1380
1381         return 0;
1382 }
1383
1384 static int psched_open(struct inode *inode, struct file *file)
1385 {
1386         return single_open(file, psched_show, PDE(inode)->data);
1387 }
1388
1389 static const struct file_operations psched_fops = {
1390         .owner = THIS_MODULE,
1391         .open = psched_open,
1392         .read  = seq_read,
1393         .llseek = seq_lseek,
1394         .release = single_release,
1395 };
1396 #endif
1397
1398 static int __init pktsched_init(void)
1399 {
1400         register_qdisc(&pfifo_qdisc_ops);
1401         register_qdisc(&bfifo_qdisc_ops);
1402         proc_net_fops_create(&init_net, "psched", 0, &psched_fops);
1403
1404         rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL);
1405         rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL);
1406         rtnl_register(PF_UNSPEC, RTM_GETQDISC, tc_get_qdisc, tc_dump_qdisc);
1407         rtnl_register(PF_UNSPEC, RTM_NEWTCLASS, tc_ctl_tclass, NULL);
1408         rtnl_register(PF_UNSPEC, RTM_DELTCLASS, tc_ctl_tclass, NULL);
1409         rtnl_register(PF_UNSPEC, RTM_GETTCLASS, tc_ctl_tclass, tc_dump_tclass);
1410
1411         return 0;
1412 }
1413
1414 subsys_initcall(pktsched_init);