blob: ce8b1ade8376a5ab2ec70dc6376f0b5c4022e494 [file] [log] [blame]
Stephen Hemminger87990462006-08-10 23:35:16 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * net/sched/sch_htb.c Hierarchical token bucket, feed tree version
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: Martin Devera, <devik@cdi.cz>
10 *
11 * Credits (in time order) for older HTB versions:
12 * Stef Coene <stef.coene@docum.org>
13 * HTB support at LARTC mailing list
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +090014 * Ondrej Kraus, <krauso@barr.cz>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 * found missing INIT_QDISC(htb)
16 * Vladimir Smelhaus, Aamer Akhter, Bert Hubert
17 * helped a lot to locate nasty class stall bug
18 * Andi Kleen, Jamal Hadi, Bert Hubert
19 * code review and helpful comments on shaping
20 * Tomasz Wrona, <tw@eter.tym.pl>
21 * created test case so that I was able to fix nasty bug
22 * Wilfried Weissmann
23 * spotted bug in dequeue code and helped with fix
24 * Jiri Fojtasek
25 * fixed requeue routine
26 * and many others. thanks.
Linus Torvalds1da177e2005-04-16 15:20:36 -070027 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/module.h>
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -070029#include <linux/moduleparam.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/types.h>
31#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/string.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/skbuff.h>
35#include <linux/list.h>
36#include <linux/compiler.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/rbtree.h>
Patrick McHardy0ba48052007-07-02 22:49:07 -070038#include <net/netlink.h>
39#include <net/pkt_sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
41/* HTB algorithm.
42 Author: devik@cdi.cz
43 ========================================================================
44 HTB is like TBF with multiple classes. It is also similar to CBQ because
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +090045 it allows to assign priority to each class in hierarchy.
Linus Torvalds1da177e2005-04-16 15:20:36 -070046 In fact it is another implementation of Floyd's formal sharing.
47
48 Levels:
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +090049 Each class is assigned level. Leaf has ALWAYS level 0 and root
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 classes have level TC_HTB_MAXDEPTH-1. Interior nodes has level
51 one less than their parent.
52*/
53
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -070054static int htb_hysteresis __read_mostly = 0; /* whether to use mode hysteresis for speedup */
Stephen Hemminger87990462006-08-10 23:35:16 -070055#define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57#if HTB_VER >> 16 != TC_HTB_PROTOVER
58#error "Mismatched sch_htb.c and pkt_sch.h"
59#endif
60
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -070061/* Module parameter and sysfs export */
62module_param (htb_hysteresis, int, 0640);
63MODULE_PARM_DESC(htb_hysteresis, "Hysteresis mode, less CPU load, less accurate");
64
Linus Torvalds1da177e2005-04-16 15:20:36 -070065/* used internaly to keep status of single class */
66enum htb_cmode {
Stephen Hemminger87990462006-08-10 23:35:16 -070067 HTB_CANT_SEND, /* class can't send and can't borrow */
68 HTB_MAY_BORROW, /* class can't send but may borrow */
69 HTB_CAN_SEND /* class can send */
Linus Torvalds1da177e2005-04-16 15:20:36 -070070};
71
72/* interior & leaf nodes; props specific to leaves are marked L: */
Stephen Hemminger87990462006-08-10 23:35:16 -070073struct htb_class {
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -070074 struct Qdisc_class_common common;
Stephen Hemminger87990462006-08-10 23:35:16 -070075 /* general class parameters */
Stephen Hemminger87990462006-08-10 23:35:16 -070076 struct gnet_stats_basic bstats;
77 struct gnet_stats_queue qstats;
78 struct gnet_stats_rate_est rate_est;
79 struct tc_htb_xstats xstats; /* our special stats */
80 int refcnt; /* usage count of this class */
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
Stephen Hemminger87990462006-08-10 23:35:16 -070082 /* topology */
83 int level; /* our level (see above) */
Patrick McHardy42077592008-07-05 23:22:53 -070084 unsigned int children;
Stephen Hemminger87990462006-08-10 23:35:16 -070085 struct htb_class *parent; /* parent class */
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
Stephen Hemminger87990462006-08-10 23:35:16 -070087 union {
88 struct htb_class_leaf {
89 struct Qdisc *q;
90 int prio;
Stephen Hemminger87990462006-08-10 23:35:16 -070091 int quantum;
92 int deficit[TC_HTB_MAXDEPTH];
93 struct list_head drop_list;
94 } leaf;
95 struct htb_class_inner {
96 struct rb_root feed[TC_HTB_NUMPRIO]; /* feed trees */
97 struct rb_node *ptr[TC_HTB_NUMPRIO]; /* current class ptr */
98 /* When class changes from state 1->2 and disconnects from
99 parent's feed then we lost ptr value and start from the
100 first child again. Here we store classid of the
101 last valid ptr (used when ptr is NULL). */
102 u32 last_ptr_id[TC_HTB_NUMPRIO];
103 } inner;
104 } un;
105 struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */
106 struct rb_node pq_node; /* node for event queue */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700107 psched_time_t pq_key;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
Stephen Hemminger87990462006-08-10 23:35:16 -0700109 int prio_activity; /* for which prios are we active */
110 enum htb_cmode cmode; /* current mode of the class */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
Stephen Hemminger87990462006-08-10 23:35:16 -0700112 /* class attached filters */
113 struct tcf_proto *filter_list;
114 int filter_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
Stephen Hemminger87990462006-08-10 23:35:16 -0700116 int warned; /* only one warning about non work conserving .. */
117
118 /* token bucket parameters */
119 struct qdisc_rate_table *rate; /* rate table of the class itself */
120 struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */
121 long buffer, cbuffer; /* token bucket depth/rate */
122 psched_tdiff_t mbuffer; /* max wait time */
123 long tokens, ctokens; /* current number of tokens */
124 psched_time_t t_c; /* checkpoint time */
Jarek Poplawski160d5e12006-12-08 00:26:56 -0800125
126 int prio; /* For parent to leaf return possible here */
127 int quantum; /* we do backup. Finally full replacement */
128 /* of un.leaf originals should be done. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129};
130
Stephen Hemminger87990462006-08-10 23:35:16 -0700131static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate,
132 int size)
133{
Jesper Dangaard Brouere9bef552007-09-12 16:35:24 +0200134 long result = qdisc_l2t(rate, size);
135 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136}
137
Stephen Hemminger87990462006-08-10 23:35:16 -0700138struct htb_sched {
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700139 struct Qdisc_class_hash clhash;
Stephen Hemminger0cef2962006-08-10 23:35:38 -0700140 struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
Stephen Hemminger87990462006-08-10 23:35:16 -0700142 /* self list - roots of self generating tree */
143 struct rb_root row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
144 int row_mask[TC_HTB_MAXDEPTH];
145 struct rb_node *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
146 u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
Stephen Hemminger87990462006-08-10 23:35:16 -0700148 /* self wait list - roots of wait PQs per row */
149 struct rb_root wait_pq[TC_HTB_MAXDEPTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Stephen Hemminger87990462006-08-10 23:35:16 -0700151 /* time of nearest event per level (row) */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700152 psched_time_t near_ev_cache[TC_HTB_MAXDEPTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
Stephen Hemminger87990462006-08-10 23:35:16 -0700154 /* whether we hit non-work conserving class during this dequeue; we use */
155 int nwc_hit; /* this to disable mindelay complaint in dequeue */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
Stephen Hemminger87990462006-08-10 23:35:16 -0700157 int defcls; /* class where unclassified flows go to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
Stephen Hemminger87990462006-08-10 23:35:16 -0700159 /* filters for qdisc itself */
160 struct tcf_proto *filter_list;
Stephen Hemminger87990462006-08-10 23:35:16 -0700161
162 int rate2quantum; /* quant = rate / rate2quantum */
163 psched_time_t now; /* cached dequeue time */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700164 struct qdisc_watchdog watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165
Stephen Hemminger87990462006-08-10 23:35:16 -0700166 /* non shaped skbs; let them go directly thru */
167 struct sk_buff_head direct_queue;
168 int direct_qlen; /* max qlen of above */
169
170 long direct_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171};
172
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173/* find class in global hash table using given handle */
Stephen Hemminger87990462006-08-10 23:35:16 -0700174static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175{
176 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700177 struct Qdisc_class_common *clc;
Stephen Hemminger0cef2962006-08-10 23:35:38 -0700178
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700179 clc = qdisc_class_find(&q->clhash, handle);
180 if (clc == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 return NULL;
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700182 return container_of(clc, struct htb_class, common);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183}
184
185/**
186 * htb_classify - classify a packet into class
187 *
188 * It returns NULL if the packet should be dropped or -1 if the packet
189 * should be passed directly thru. In all other cases leaf class is returned.
190 * We allow direct class selection by classid in priority. The we examine
191 * filters in qdisc and in inner nodes (if higher filter points to the inner
192 * node). If we end up with classid MAJOR:0 we enqueue the skb into special
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900193 * internal fifo (direct). These packets then go directly thru. If we still
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessfull
195 * then finish and return direct queue.
196 */
197#define HTB_DIRECT (struct htb_class*)-1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
Stephen Hemminger87990462006-08-10 23:35:16 -0700199static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
200 int *qerr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
202 struct htb_sched *q = qdisc_priv(sch);
203 struct htb_class *cl;
204 struct tcf_result res;
205 struct tcf_proto *tcf;
206 int result;
207
208 /* allow to select class by setting skb->priority to valid classid;
209 note that nfmark can be used too by attaching filter fw with no
210 rules in it */
211 if (skb->priority == sch->handle)
Stephen Hemminger87990462006-08-10 23:35:16 -0700212 return HTB_DIRECT; /* X:0 (direct flow) selected */
213 if ((cl = htb_find(skb->priority, sch)) != NULL && cl->level == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 return cl;
215
Jarek Poplawskic27f3392008-08-04 22:39:11 -0700216 *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 tcf = q->filter_list;
218 while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
219#ifdef CONFIG_NET_CLS_ACT
220 switch (result) {
221 case TC_ACT_QUEUED:
Stephen Hemminger87990462006-08-10 23:35:16 -0700222 case TC_ACT_STOLEN:
Jarek Poplawski378a2f02008-08-04 22:31:03 -0700223 *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 case TC_ACT_SHOT:
225 return NULL;
226 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227#endif
Stephen Hemminger87990462006-08-10 23:35:16 -0700228 if ((cl = (void *)res.class) == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 if (res.classid == sch->handle)
Stephen Hemminger87990462006-08-10 23:35:16 -0700230 return HTB_DIRECT; /* X:0 (direct flow) */
231 if ((cl = htb_find(res.classid, sch)) == NULL)
232 break; /* filter selected invalid classid */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 }
234 if (!cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700235 return cl; /* we hit leaf; return it */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
237 /* we have got inner class; apply inner filter chain */
238 tcf = cl->filter_list;
239 }
240 /* classification failed; try to use default class */
Stephen Hemminger87990462006-08-10 23:35:16 -0700241 cl = htb_find(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 if (!cl || cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700243 return HTB_DIRECT; /* bad default .. this is safe bet */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 return cl;
245}
246
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247/**
248 * htb_add_to_id_tree - adds class to the round robin list
249 *
250 * Routine adds class to the list (actually tree) sorted by classid.
251 * Make sure that class is not already on such list for given prio.
252 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700253static void htb_add_to_id_tree(struct rb_root *root,
254 struct htb_class *cl, int prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255{
256 struct rb_node **p = &root->rb_node, *parent = NULL;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700257
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 while (*p) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700259 struct htb_class *c;
260 parent = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 c = rb_entry(parent, struct htb_class, node[prio]);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700262
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700263 if (cl->common.classid > c->common.classid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 p = &parent->rb_right;
Stephen Hemminger87990462006-08-10 23:35:16 -0700265 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 p = &parent->rb_left;
267 }
268 rb_link_node(&cl->node[prio], parent, p);
269 rb_insert_color(&cl->node[prio], root);
270}
271
272/**
273 * htb_add_to_wait_tree - adds class to the event queue with delay
274 *
275 * The class is added to priority event queue to indicate that class will
276 * change its mode in cl->pq_key microseconds. Make sure that class is not
277 * already in the queue.
278 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700279static void htb_add_to_wait_tree(struct htb_sched *q,
280 struct htb_class *cl, long delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281{
282 struct rb_node **p = &q->wait_pq[cl->level].rb_node, *parent = NULL;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700283
Patrick McHardyfb983d42007-03-16 01:22:39 -0700284 cl->pq_key = q->now + delay;
285 if (cl->pq_key == q->now)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 cl->pq_key++;
287
288 /* update the nearest event cache */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700289 if (q->near_ev_cache[cl->level] > cl->pq_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 q->near_ev_cache[cl->level] = cl->pq_key;
Stephen Hemminger87990462006-08-10 23:35:16 -0700291
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 while (*p) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700293 struct htb_class *c;
294 parent = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 c = rb_entry(parent, struct htb_class, pq_node);
Patrick McHardyfb983d42007-03-16 01:22:39 -0700296 if (cl->pq_key >= c->pq_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 p = &parent->rb_right;
Stephen Hemminger87990462006-08-10 23:35:16 -0700298 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 p = &parent->rb_left;
300 }
301 rb_link_node(&cl->pq_node, parent, p);
302 rb_insert_color(&cl->pq_node, &q->wait_pq[cl->level]);
303}
304
305/**
306 * htb_next_rb_node - finds next node in binary tree
307 *
308 * When we are past last key we return NULL.
309 * Average complexity is 2 steps per call.
310 */
Stephen Hemminger3696f622006-08-10 23:36:01 -0700311static inline void htb_next_rb_node(struct rb_node **n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312{
313 *n = rb_next(*n);
314}
315
316/**
317 * htb_add_class_to_row - add class to its row
318 *
319 * The class is added to row at priorities marked in mask.
320 * It does nothing if mask == 0.
321 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700322static inline void htb_add_class_to_row(struct htb_sched *q,
323 struct htb_class *cl, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 q->row_mask[cl->level] |= mask;
326 while (mask) {
327 int prio = ffz(~mask);
328 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700329 htb_add_to_id_tree(q->row[cl->level] + prio, cl, prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 }
331}
332
Stephen Hemminger3696f622006-08-10 23:36:01 -0700333/* If this triggers, it is a bug in this code, but it need not be fatal */
334static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root)
335{
Ismail Donmez81771b32006-10-03 13:49:10 -0700336 if (RB_EMPTY_NODE(rb)) {
Stephen Hemminger3696f622006-08-10 23:36:01 -0700337 WARN_ON(1);
338 } else {
339 rb_erase(rb, root);
340 RB_CLEAR_NODE(rb);
341 }
342}
343
344
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345/**
346 * htb_remove_class_from_row - removes class from its row
347 *
348 * The class is removed from row at priorities marked in mask.
349 * It does nothing if mask == 0.
350 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700351static inline void htb_remove_class_from_row(struct htb_sched *q,
352 struct htb_class *cl, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353{
354 int m = 0;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700355
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 while (mask) {
357 int prio = ffz(~mask);
Stephen Hemminger3696f622006-08-10 23:36:01 -0700358
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700360 if (q->ptr[cl->level][prio] == cl->node + prio)
361 htb_next_rb_node(q->ptr[cl->level] + prio);
Stephen Hemminger3696f622006-08-10 23:36:01 -0700362
363 htb_safe_rb_erase(cl->node + prio, q->row[cl->level] + prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700364 if (!q->row[cl->level][prio].rb_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 m |= 1 << prio;
366 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 q->row_mask[cl->level] &= ~m;
368}
369
370/**
371 * htb_activate_prios - creates active classe's feed chain
372 *
373 * The class is connected to ancestors and/or appropriate rows
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900374 * for priorities it is participating on. cl->cmode must be new
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 * (activated) mode. It does nothing if cl->prio_activity == 0.
376 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700377static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378{
379 struct htb_class *p = cl->parent;
Stephen Hemminger87990462006-08-10 23:35:16 -0700380 long m, mask = cl->prio_activity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
382 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700383 m = mask;
384 while (m) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 int prio = ffz(~m);
386 m &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700387
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 if (p->un.inner.feed[prio].rb_node)
389 /* parent already has its feed in use so that
390 reset bit in mask as parent is already ok */
391 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700392
393 htb_add_to_id_tree(p->un.inner.feed + prio, cl, prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 p->prio_activity |= mask;
Stephen Hemminger87990462006-08-10 23:35:16 -0700396 cl = p;
397 p = cl->parent;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700398
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 }
400 if (cl->cmode == HTB_CAN_SEND && mask)
Stephen Hemminger87990462006-08-10 23:35:16 -0700401 htb_add_class_to_row(q, cl, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402}
403
404/**
405 * htb_deactivate_prios - remove class from feed chain
406 *
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900407 * cl->cmode must represent old mode (before deactivation). It does
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 * nothing if cl->prio_activity == 0. Class is removed from all feed
409 * chains and rows.
410 */
411static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl)
412{
413 struct htb_class *p = cl->parent;
Stephen Hemminger87990462006-08-10 23:35:16 -0700414 long m, mask = cl->prio_activity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
416 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700417 m = mask;
418 mask = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 while (m) {
420 int prio = ffz(~m);
421 m &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700422
423 if (p->un.inner.ptr[prio] == cl->node + prio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 /* we are removing child which is pointed to from
425 parent feed - forget the pointer but remember
426 classid */
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700427 p->un.inner.last_ptr_id[prio] = cl->common.classid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 p->un.inner.ptr[prio] = NULL;
429 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700430
Stephen Hemminger3696f622006-08-10 23:36:01 -0700431 htb_safe_rb_erase(cl->node + prio, p->un.inner.feed + prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700432
433 if (!p->un.inner.feed[prio].rb_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 mask |= 1 << prio;
435 }
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700436
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 p->prio_activity &= ~mask;
Stephen Hemminger87990462006-08-10 23:35:16 -0700438 cl = p;
439 p = cl->parent;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700442 if (cl->cmode == HTB_CAN_SEND && mask)
443 htb_remove_class_from_row(q, cl, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444}
445
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700446static inline long htb_lowater(const struct htb_class *cl)
447{
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700448 if (htb_hysteresis)
449 return cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : 0;
450 else
451 return 0;
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700452}
453static inline long htb_hiwater(const struct htb_class *cl)
454{
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700455 if (htb_hysteresis)
456 return cl->cmode == HTB_CAN_SEND ? -cl->buffer : 0;
457 else
458 return 0;
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700459}
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700460
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700461
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462/**
463 * htb_class_mode - computes and returns current class mode
464 *
465 * It computes cl's mode at time cl->t_c+diff and returns it. If mode
466 * is not HTB_CAN_SEND then cl->pq_key is updated to time difference
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900467 * from now to time when cl will change its state.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 * Also it is worth to note that class mode doesn't change simply
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900469 * at cl->{c,}tokens == 0 but there can rather be hysteresis of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 * 0 .. -cl->{c,}buffer range. It is meant to limit number of
471 * mode transitions per time unit. The speed gain is about 1/6.
472 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700473static inline enum htb_cmode
474htb_class_mode(struct htb_class *cl, long *diff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475{
Stephen Hemminger87990462006-08-10 23:35:16 -0700476 long toks;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
Stephen Hemminger87990462006-08-10 23:35:16 -0700478 if ((toks = (cl->ctokens + *diff)) < htb_lowater(cl)) {
479 *diff = -toks;
480 return HTB_CANT_SEND;
481 }
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700482
Stephen Hemminger87990462006-08-10 23:35:16 -0700483 if ((toks = (cl->tokens + *diff)) >= htb_hiwater(cl))
484 return HTB_CAN_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Stephen Hemminger87990462006-08-10 23:35:16 -0700486 *diff = -toks;
487 return HTB_MAY_BORROW;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488}
489
490/**
491 * htb_change_class_mode - changes classe's mode
492 *
493 * This should be the only way how to change classe's mode under normal
494 * cirsumstances. Routine will update feed lists linkage, change mode
495 * and add class to the wait event queue if appropriate. New mode should
496 * be different from old one and cl->pq_key has to be valid if changing
497 * to mode other than HTB_CAN_SEND (see htb_add_to_wait_tree).
498 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700499static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long *diff)
Stephen Hemminger87990462006-08-10 23:35:16 -0700501{
502 enum htb_cmode new_mode = htb_class_mode(cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
504 if (new_mode == cl->cmode)
Stephen Hemminger87990462006-08-10 23:35:16 -0700505 return;
506
507 if (cl->prio_activity) { /* not necessary: speed optimization */
508 if (cl->cmode != HTB_CANT_SEND)
509 htb_deactivate_prios(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 cl->cmode = new_mode;
Stephen Hemminger87990462006-08-10 23:35:16 -0700511 if (new_mode != HTB_CANT_SEND)
512 htb_activate_prios(q, cl);
513 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 cl->cmode = new_mode;
515}
516
517/**
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900518 * htb_activate - inserts leaf cl into appropriate active feeds
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 *
520 * Routine learns (new) priority of leaf and activates feed chain
521 * for the prio. It can be called on already active leaf safely.
522 * It also adds leaf into droplist.
523 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700524static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525{
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700526 WARN_ON(cl->level || !cl->un.leaf.q || !cl->un.leaf.q->q.qlen);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700527
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 if (!cl->prio_activity) {
Jarek Poplawski4164d662008-12-03 21:08:44 -0800529 cl->prio_activity = 1 << cl->un.leaf.prio;
Stephen Hemminger87990462006-08-10 23:35:16 -0700530 htb_activate_prios(q, cl);
531 list_add_tail(&cl->un.leaf.drop_list,
Jarek Poplawski4164d662008-12-03 21:08:44 -0800532 q->drops + cl->un.leaf.prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 }
534}
535
536/**
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900537 * htb_deactivate - remove leaf cl from active feeds
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 *
539 * Make sure that leaf is active. In the other words it can't be called
540 * with non-active leaf. It also removes class from the drop list.
541 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700542static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543{
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700544 WARN_ON(!cl->prio_activity);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700545
Stephen Hemminger87990462006-08-10 23:35:16 -0700546 htb_deactivate_prios(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 cl->prio_activity = 0;
548 list_del_init(&cl->un.leaf.drop_list);
549}
550
551static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
552{
Jarek Poplawskif30ab412008-11-13 22:56:30 -0800553 int uninitialized_var(ret);
Stephen Hemminger87990462006-08-10 23:35:16 -0700554 struct htb_sched *q = qdisc_priv(sch);
555 struct htb_class *cl = htb_classify(skb, sch, &ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
Stephen Hemminger87990462006-08-10 23:35:16 -0700557 if (cl == HTB_DIRECT) {
558 /* enqueue to helper queue */
559 if (q->direct_queue.qlen < q->direct_qlen) {
560 __skb_queue_tail(&q->direct_queue, skb);
561 q->direct_pkts++;
562 } else {
563 kfree_skb(skb);
564 sch->qstats.drops++;
565 return NET_XMIT_DROP;
566 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567#ifdef CONFIG_NET_CLS_ACT
Stephen Hemminger87990462006-08-10 23:35:16 -0700568 } else if (!cl) {
Jarek Poplawskic27f3392008-08-04 22:39:11 -0700569 if (ret & __NET_XMIT_BYPASS)
Stephen Hemminger87990462006-08-10 23:35:16 -0700570 sch->qstats.drops++;
571 kfree_skb(skb);
572 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573#endif
Jarek Poplawski378a2f02008-08-04 22:31:03 -0700574 } else if ((ret = qdisc_enqueue(skb, cl->un.leaf.q)) != NET_XMIT_SUCCESS) {
575 if (net_xmit_drop_count(ret)) {
576 sch->qstats.drops++;
577 cl->qstats.drops++;
578 }
David S. Miller69747652008-08-17 23:55:36 -0700579 return ret;
Stephen Hemminger87990462006-08-10 23:35:16 -0700580 } else {
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700581 cl->bstats.packets +=
582 skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700583 cl->bstats.bytes += qdisc_pkt_len(skb);
Stephen Hemminger87990462006-08-10 23:35:16 -0700584 htb_activate(q, cl);
585 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586
Stephen Hemminger87990462006-08-10 23:35:16 -0700587 sch->q.qlen++;
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700588 sch->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700589 sch->bstats.bytes += qdisc_pkt_len(skb);
Stephen Hemminger87990462006-08-10 23:35:16 -0700590 return NET_XMIT_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591}
592
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593/**
594 * htb_charge_class - charges amount "bytes" to leaf and ancestors
595 *
596 * Routine assumes that packet "bytes" long was dequeued from leaf cl
597 * borrowing from "level". It accounts bytes to ceil leaky bucket for
598 * leaf and all ancestors and to rate bucket for ancestors at levels
599 * "level" and higher. It also handles possible change of mode resulting
600 * from the update. Note that mode can also increase here (MAY_BORROW to
601 * CAN_SEND) because we can use more precise clock that event queue here.
602 * In such case we remove class from event queue first.
603 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700604static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700605 int level, struct sk_buff *skb)
Stephen Hemminger87990462006-08-10 23:35:16 -0700606{
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700607 int bytes = qdisc_pkt_len(skb);
Stephen Hemminger87990462006-08-10 23:35:16 -0700608 long toks, diff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 enum htb_cmode old_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
611#define HTB_ACCNT(T,B,R) toks = diff + cl->T; \
612 if (toks > cl->B) toks = cl->B; \
613 toks -= L2T(cl, cl->R, bytes); \
614 if (toks <= -cl->mbuffer) toks = 1-cl->mbuffer; \
615 cl->T = toks
616
617 while (cl) {
Patrick McHardy03cc45c2007-03-23 11:29:11 -0700618 diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 if (cl->level >= level) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700620 if (cl->level == level)
621 cl->xstats.lends++;
622 HTB_ACCNT(tokens, buffer, rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 } else {
624 cl->xstats.borrows++;
Stephen Hemminger87990462006-08-10 23:35:16 -0700625 cl->tokens += diff; /* we moved t_c; update tokens */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700627 HTB_ACCNT(ctokens, cbuffer, ceil);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 cl->t_c = q->now;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
Stephen Hemminger87990462006-08-10 23:35:16 -0700630 old_mode = cl->cmode;
631 diff = 0;
632 htb_change_class_mode(q, cl, &diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 if (old_mode != cl->cmode) {
634 if (old_mode != HTB_CAN_SEND)
Stephen Hemminger3696f622006-08-10 23:36:01 -0700635 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 if (cl->cmode != HTB_CAN_SEND)
Stephen Hemminger87990462006-08-10 23:35:16 -0700637 htb_add_to_wait_tree(q, cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639
640 /* update byte stats except for leaves which are already updated */
641 if (cl->level) {
642 cl->bstats.bytes += bytes;
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700643 cl->bstats.packets += skb_is_gso(skb)?
644 skb_shinfo(skb)->gso_segs:1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 }
646 cl = cl->parent;
647 }
648}
649
650/**
651 * htb_do_events - make mode changes to classes at the level
652 *
Patrick McHardyfb983d42007-03-16 01:22:39 -0700653 * Scans event queue for pending events and applies them. Returns time of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 * next pending event (0 for no event in pq).
Patrick McHardyfb983d42007-03-16 01:22:39 -0700655 * Note: Applied are events whose have cl->pq_key <= q->now.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700657static psched_time_t htb_do_events(struct htb_sched *q, int level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658{
Martin Devera8f3ea332008-03-23 22:00:38 -0700659 /* don't run for longer than 2 jiffies; 2 is used instead of
660 1 to simplify things when jiffy is going to be incremented
661 too soon */
662 unsigned long stop_at = jiffies + 2;
663 while (time_before(jiffies, stop_at)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 struct htb_class *cl;
665 long diff;
Akinbou Mita30bdbe32006-10-12 01:52:05 -0700666 struct rb_node *p = rb_first(&q->wait_pq[level]);
667
Stephen Hemminger87990462006-08-10 23:35:16 -0700668 if (!p)
669 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670
671 cl = rb_entry(p, struct htb_class, pq_node);
Patrick McHardyfb983d42007-03-16 01:22:39 -0700672 if (cl->pq_key > q->now)
673 return cl->pq_key;
674
Stephen Hemminger3696f622006-08-10 23:36:01 -0700675 htb_safe_rb_erase(p, q->wait_pq + level);
Patrick McHardy03cc45c2007-03-23 11:29:11 -0700676 diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
Stephen Hemminger87990462006-08-10 23:35:16 -0700677 htb_change_class_mode(q, cl, &diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 if (cl->cmode != HTB_CAN_SEND)
Stephen Hemminger87990462006-08-10 23:35:16 -0700679 htb_add_to_wait_tree(q, cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 }
Martin Devera8f3ea332008-03-23 22:00:38 -0700681 /* too much load - let's continue on next jiffie */
682 return q->now + PSCHED_TICKS_PER_SEC / HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683}
684
685/* Returns class->node+prio from id-tree where classe's id is >= id. NULL
686 is no such one exists. */
Stephen Hemminger87990462006-08-10 23:35:16 -0700687static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n,
688 u32 id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689{
690 struct rb_node *r = NULL;
691 while (n) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700692 struct htb_class *cl =
693 rb_entry(n, struct htb_class, node[prio]);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700694 if (id == cl->common.classid)
Stephen Hemminger87990462006-08-10 23:35:16 -0700695 return n;
696
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700697 if (id > cl->common.classid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 n = n->rb_right;
699 } else {
700 r = n;
701 n = n->rb_left;
702 }
703 }
704 return r;
705}
706
707/**
708 * htb_lookup_leaf - returns next leaf class in DRR order
709 *
710 * Find leaf where current feed pointers points to.
711 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700712static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
713 struct rb_node **pptr, u32 * pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714{
715 int i;
716 struct {
717 struct rb_node *root;
718 struct rb_node **pptr;
719 u32 *pid;
Stephen Hemminger87990462006-08-10 23:35:16 -0700720 } stk[TC_HTB_MAXDEPTH], *sp = stk;
721
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700722 WARN_ON(!tree->rb_node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 sp->root = tree->rb_node;
724 sp->pptr = pptr;
725 sp->pid = pid;
726
727 for (i = 0; i < 65535; i++) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700728 if (!*sp->pptr && *sp->pid) {
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900729 /* ptr was invalidated but id is valid - try to recover
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 the original or next ptr */
Stephen Hemminger87990462006-08-10 23:35:16 -0700731 *sp->pptr =
732 htb_id_find_next_upper(prio, sp->root, *sp->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700734 *sp->pid = 0; /* ptr is valid now so that remove this hint as it
735 can become out of date quickly */
736 if (!*sp->pptr) { /* we are at right end; rewind & go up */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 *sp->pptr = sp->root;
Stephen Hemminger87990462006-08-10 23:35:16 -0700738 while ((*sp->pptr)->rb_left)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 *sp->pptr = (*sp->pptr)->rb_left;
740 if (sp > stk) {
741 sp--;
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700742 WARN_ON(!*sp->pptr);
Stephen Hemminger87990462006-08-10 23:35:16 -0700743 if (!*sp->pptr)
744 return NULL;
745 htb_next_rb_node(sp->pptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 }
747 } else {
748 struct htb_class *cl;
Stephen Hemminger87990462006-08-10 23:35:16 -0700749 cl = rb_entry(*sp->pptr, struct htb_class, node[prio]);
750 if (!cl->level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 return cl;
752 (++sp)->root = cl->un.inner.feed[prio].rb_node;
Stephen Hemminger87990462006-08-10 23:35:16 -0700753 sp->pptr = cl->un.inner.ptr + prio;
754 sp->pid = cl->un.inner.last_ptr_id + prio;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 }
756 }
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700757 WARN_ON(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 return NULL;
759}
760
761/* dequeues packet at given priority and level; call only if
762 you are sure that there is active class at prio/level */
Stephen Hemminger87990462006-08-10 23:35:16 -0700763static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio,
764 int level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765{
766 struct sk_buff *skb = NULL;
Stephen Hemminger87990462006-08-10 23:35:16 -0700767 struct htb_class *cl, *start;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 /* look initial class up in the row */
Stephen Hemminger87990462006-08-10 23:35:16 -0700769 start = cl = htb_lookup_leaf(q->row[level] + prio, prio,
770 q->ptr[level] + prio,
771 q->last_ptr_id[level] + prio);
772
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 do {
774next:
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700775 WARN_ON(!cl);
Stephen Hemminger87990462006-08-10 23:35:16 -0700776 if (!cl)
777 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778
779 /* class can be empty - it is unlikely but can be true if leaf
780 qdisc drops packets in enqueue routine or if someone used
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900781 graft operation on the leaf since last dequeue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 simply deactivate and skip such class */
783 if (unlikely(cl->un.leaf.q->q.qlen == 0)) {
784 struct htb_class *next;
Stephen Hemminger87990462006-08-10 23:35:16 -0700785 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
787 /* row/level might become empty */
788 if ((q->row_mask[level] & (1 << prio)) == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -0700789 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
Stephen Hemminger87990462006-08-10 23:35:16 -0700791 next = htb_lookup_leaf(q->row[level] + prio,
792 prio, q->ptr[level] + prio,
793 q->last_ptr_id[level] + prio);
794
795 if (cl == start) /* fix start if we just deleted it */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 start = next;
797 cl = next;
798 goto next;
799 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700800
801 skb = cl->un.leaf.q->dequeue(cl->un.leaf.q);
802 if (likely(skb != NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 break;
804 if (!cl->warned) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700805 printk(KERN_WARNING
806 "htb: class %X isn't work conserving ?!\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700807 cl->common.classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 cl->warned = 1;
809 }
810 q->nwc_hit++;
Stephen Hemminger87990462006-08-10 23:35:16 -0700811 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
812 ptr[0]) + prio);
813 cl = htb_lookup_leaf(q->row[level] + prio, prio,
814 q->ptr[level] + prio,
815 q->last_ptr_id[level] + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
817 } while (cl != start);
818
819 if (likely(skb != NULL)) {
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700820 cl->un.leaf.deficit[level] -= qdisc_pkt_len(skb);
821 if (cl->un.leaf.deficit[level] < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 cl->un.leaf.deficit[level] += cl->un.leaf.quantum;
Stephen Hemminger87990462006-08-10 23:35:16 -0700823 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
824 ptr[0]) + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 }
826 /* this used to be after charge_class but this constelation
827 gives us slightly better performance */
828 if (!cl->un.leaf.q->q.qlen)
Stephen Hemminger87990462006-08-10 23:35:16 -0700829 htb_deactivate(q, cl);
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700830 htb_charge_class(q, cl, level, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 }
832 return skb;
833}
834
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835static struct sk_buff *htb_dequeue(struct Qdisc *sch)
836{
837 struct sk_buff *skb = NULL;
838 struct htb_sched *q = qdisc_priv(sch);
839 int level;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700840 psched_time_t next_event;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
842 /* try to dequeue direct packets as high prio (!) to minimize cpu work */
Stephen Hemminger87990462006-08-10 23:35:16 -0700843 skb = __skb_dequeue(&q->direct_queue);
844 if (skb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 sch->flags &= ~TCQ_F_THROTTLED;
846 sch->q.qlen--;
847 return skb;
848 }
849
Stephen Hemminger87990462006-08-10 23:35:16 -0700850 if (!sch->q.qlen)
851 goto fin;
Patrick McHardy3bebcda2007-03-23 11:29:25 -0700852 q->now = psched_get_time();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853
Patrick McHardyfb983d42007-03-16 01:22:39 -0700854 next_event = q->now + 5 * PSCHED_TICKS_PER_SEC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 q->nwc_hit = 0;
856 for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
857 /* common case optimization - skip event handler quickly */
858 int m;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700859 psched_time_t event;
Stephen Hemminger87990462006-08-10 23:35:16 -0700860
Patrick McHardyfb983d42007-03-16 01:22:39 -0700861 if (q->now >= q->near_ev_cache[level]) {
862 event = htb_do_events(q, level);
Patrick McHardy2e4b3b02007-05-23 23:39:54 -0700863 if (!event)
864 event = q->now + PSCHED_TICKS_PER_SEC;
865 q->near_ev_cache[level] = event;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700866 } else
867 event = q->near_ev_cache[level];
868
869 if (event && next_event > event)
870 next_event = event;
871
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 m = ~q->row_mask[level];
873 while (m != (int)(-1)) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700874 int prio = ffz(m);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 m |= 1 << prio;
Stephen Hemminger87990462006-08-10 23:35:16 -0700876 skb = htb_dequeue_tree(q, prio, level);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 if (likely(skb != NULL)) {
878 sch->q.qlen--;
879 sch->flags &= ~TCQ_F_THROTTLED;
880 goto fin;
881 }
882 }
883 }
Patrick McHardyfb983d42007-03-16 01:22:39 -0700884 sch->qstats.overlimits++;
885 qdisc_watchdog_schedule(&q->watchdog, next_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886fin:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 return skb;
888}
889
890/* try to drop from each class (by prio) until one succeed */
Stephen Hemminger87990462006-08-10 23:35:16 -0700891static unsigned int htb_drop(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892{
893 struct htb_sched *q = qdisc_priv(sch);
894 int prio;
895
896 for (prio = TC_HTB_NUMPRIO - 1; prio >= 0; prio--) {
897 struct list_head *p;
Stephen Hemminger87990462006-08-10 23:35:16 -0700898 list_for_each(p, q->drops + prio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 struct htb_class *cl = list_entry(p, struct htb_class,
900 un.leaf.drop_list);
901 unsigned int len;
Stephen Hemminger87990462006-08-10 23:35:16 -0700902 if (cl->un.leaf.q->ops->drop &&
903 (len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 sch->q.qlen--;
905 if (!cl->un.leaf.q->q.qlen)
Stephen Hemminger87990462006-08-10 23:35:16 -0700906 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 return len;
908 }
909 }
910 }
911 return 0;
912}
913
914/* reset all classes */
915/* always caled under BH & queue lock */
Stephen Hemminger87990462006-08-10 23:35:16 -0700916static void htb_reset(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917{
918 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700919 struct htb_class *cl;
920 struct hlist_node *n;
921 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700923 for (i = 0; i < q->clhash.hashsize; i++) {
924 hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 if (cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700926 memset(&cl->un.inner, 0, sizeof(cl->un.inner));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 else {
Stephen Hemminger87990462006-08-10 23:35:16 -0700928 if (cl->un.leaf.q)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 qdisc_reset(cl->un.leaf.q);
930 INIT_LIST_HEAD(&cl->un.leaf.drop_list);
931 }
932 cl->prio_activity = 0;
933 cl->cmode = HTB_CAN_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934
935 }
936 }
Patrick McHardyfb983d42007-03-16 01:22:39 -0700937 qdisc_watchdog_cancel(&q->watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 __skb_queue_purge(&q->direct_queue);
939 sch->q.qlen = 0;
Stephen Hemminger87990462006-08-10 23:35:16 -0700940 memset(q->row, 0, sizeof(q->row));
941 memset(q->row_mask, 0, sizeof(q->row_mask));
942 memset(q->wait_pq, 0, sizeof(q->wait_pq));
943 memset(q->ptr, 0, sizeof(q->ptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 for (i = 0; i < TC_HTB_NUMPRIO; i++)
Stephen Hemminger87990462006-08-10 23:35:16 -0700945 INIT_LIST_HEAD(q->drops + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946}
947
Patrick McHardy27a34212008-01-23 20:35:39 -0800948static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
949 [TCA_HTB_PARMS] = { .len = sizeof(struct tc_htb_opt) },
950 [TCA_HTB_INIT] = { .len = sizeof(struct tc_htb_glob) },
951 [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
952 [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
953};
954
Patrick McHardy1e904742008-01-22 22:11:17 -0800955static int htb_init(struct Qdisc *sch, struct nlattr *opt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956{
957 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardy1e904742008-01-22 22:11:17 -0800958 struct nlattr *tb[TCA_HTB_INIT + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 struct tc_htb_glob *gopt;
Patrick McHardycee63722008-01-23 20:33:32 -0800960 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 int i;
Patrick McHardycee63722008-01-23 20:33:32 -0800962
963 if (!opt)
964 return -EINVAL;
965
Patrick McHardy27a34212008-01-23 20:35:39 -0800966 err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy);
Patrick McHardycee63722008-01-23 20:33:32 -0800967 if (err < 0)
968 return err;
969
Patrick McHardy27a34212008-01-23 20:35:39 -0800970 if (tb[TCA_HTB_INIT] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
972 return -EINVAL;
973 }
Patrick McHardy1e904742008-01-22 22:11:17 -0800974 gopt = nla_data(tb[TCA_HTB_INIT]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 if (gopt->version != HTB_VER >> 16) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700976 printk(KERN_ERR
977 "HTB: need tc/htb version %d (minor is %d), you have %d\n",
978 HTB_VER >> 16, HTB_VER & 0xffff, gopt->version);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 return -EINVAL;
980 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700982 err = qdisc_class_hash_init(&q->clhash);
983 if (err < 0)
984 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 for (i = 0; i < TC_HTB_NUMPRIO; i++)
Stephen Hemminger87990462006-08-10 23:35:16 -0700986 INIT_LIST_HEAD(q->drops + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987
Patrick McHardyfb983d42007-03-16 01:22:39 -0700988 qdisc_watchdog_init(&q->watchdog, sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 skb_queue_head_init(&q->direct_queue);
990
David S. Miller5ce2d482008-07-08 17:06:30 -0700991 q->direct_qlen = qdisc_dev(sch)->tx_queue_len;
Stephen Hemminger87990462006-08-10 23:35:16 -0700992 if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 q->direct_qlen = 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 if ((q->rate2quantum = gopt->rate2quantum) < 1)
996 q->rate2quantum = 1;
997 q->defcls = gopt->defcls;
998
999 return 0;
1000}
1001
1002static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
1003{
Jarek Poplawski102396a2008-08-29 14:21:52 -07001004 spinlock_t *root_lock = qdisc_root_sleeping_lock(sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001006 struct nlattr *nest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 struct tc_htb_glob gopt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008
David S. Miller7698b4f2008-07-16 01:42:40 -07001009 spin_lock_bh(root_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001010
1011 gopt.direct_pkts = q->direct_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 gopt.version = HTB_VER;
1013 gopt.rate2quantum = q->rate2quantum;
1014 gopt.defcls = q->defcls;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001015 gopt.debug = 0;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001016
1017 nest = nla_nest_start(skb, TCA_OPTIONS);
1018 if (nest == NULL)
1019 goto nla_put_failure;
Patrick McHardy1e904742008-01-22 22:11:17 -08001020 NLA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001021 nla_nest_end(skb, nest);
1022
David S. Miller7698b4f2008-07-16 01:42:40 -07001023 spin_unlock_bh(root_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 return skb->len;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001025
Patrick McHardy1e904742008-01-22 22:11:17 -08001026nla_put_failure:
David S. Miller7698b4f2008-07-16 01:42:40 -07001027 spin_unlock_bh(root_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001028 nla_nest_cancel(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 return -1;
1030}
1031
1032static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
Stephen Hemminger87990462006-08-10 23:35:16 -07001033 struct sk_buff *skb, struct tcmsg *tcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034{
Stephen Hemminger87990462006-08-10 23:35:16 -07001035 struct htb_class *cl = (struct htb_class *)arg;
Jarek Poplawski102396a2008-08-29 14:21:52 -07001036 spinlock_t *root_lock = qdisc_root_sleeping_lock(sch);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001037 struct nlattr *nest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 struct tc_htb_opt opt;
1039
David S. Miller7698b4f2008-07-16 01:42:40 -07001040 spin_lock_bh(root_lock);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001041 tcm->tcm_parent = cl->parent ? cl->parent->common.classid : TC_H_ROOT;
1042 tcm->tcm_handle = cl->common.classid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 if (!cl->level && cl->un.leaf.q)
1044 tcm->tcm_info = cl->un.leaf.q->handle;
1045
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001046 nest = nla_nest_start(skb, TCA_OPTIONS);
1047 if (nest == NULL)
1048 goto nla_put_failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
Stephen Hemminger87990462006-08-10 23:35:16 -07001050 memset(&opt, 0, sizeof(opt));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
Stephen Hemminger87990462006-08-10 23:35:16 -07001052 opt.rate = cl->rate->rate;
1053 opt.buffer = cl->buffer;
1054 opt.ceil = cl->ceil->rate;
1055 opt.cbuffer = cl->cbuffer;
1056 opt.quantum = cl->un.leaf.quantum;
1057 opt.prio = cl->un.leaf.prio;
1058 opt.level = cl->level;
Patrick McHardy1e904742008-01-22 22:11:17 -08001059 NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001060
1061 nla_nest_end(skb, nest);
David S. Miller7698b4f2008-07-16 01:42:40 -07001062 spin_unlock_bh(root_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 return skb->len;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001064
Patrick McHardy1e904742008-01-22 22:11:17 -08001065nla_put_failure:
David S. Miller7698b4f2008-07-16 01:42:40 -07001066 spin_unlock_bh(root_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001067 nla_nest_cancel(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 return -1;
1069}
1070
1071static int
Stephen Hemminger87990462006-08-10 23:35:16 -07001072htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073{
Stephen Hemminger87990462006-08-10 23:35:16 -07001074 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 if (!cl->level && cl->un.leaf.q)
1077 cl->qstats.qlen = cl->un.leaf.q->q.qlen;
1078 cl->xstats.tokens = cl->tokens;
1079 cl->xstats.ctokens = cl->ctokens;
1080
1081 if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
1082 gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
1083 gnet_stats_copy_queue(d, &cl->qstats) < 0)
1084 return -1;
1085
1086 return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
1087}
1088
1089static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
Stephen Hemminger87990462006-08-10 23:35:16 -07001090 struct Qdisc **old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091{
Stephen Hemminger87990462006-08-10 23:35:16 -07001092 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093
1094 if (cl && !cl->level) {
Patrick McHardy9f9afec2006-11-29 17:35:18 -08001095 if (new == NULL &&
David S. Miller5ce2d482008-07-08 17:06:30 -07001096 (new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
David S. Millerbb949fb2008-07-08 16:55:56 -07001097 &pfifo_qdisc_ops,
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001098 cl->common.classid))
Stephen Hemminger87990462006-08-10 23:35:16 -07001099 == NULL)
1100 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 sch_tree_lock(sch);
Patrick McHardyb94c8af2008-11-20 04:11:36 -08001102 *old = cl->un.leaf.q;
1103 cl->un.leaf.q = new;
1104 if (*old != NULL) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001105 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 qdisc_reset(*old);
1107 }
1108 sch_tree_unlock(sch);
1109 return 0;
1110 }
1111 return -ENOENT;
1112}
1113
Stephen Hemminger87990462006-08-10 23:35:16 -07001114static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115{
Stephen Hemminger87990462006-08-10 23:35:16 -07001116 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 return (cl && !cl->level) ? cl->un.leaf.q : NULL;
1118}
1119
Patrick McHardy256d61b2006-11-29 17:37:05 -08001120static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg)
1121{
1122 struct htb_class *cl = (struct htb_class *)arg;
1123
1124 if (cl->un.leaf.q->q.qlen == 0)
1125 htb_deactivate(qdisc_priv(sch), cl);
1126}
1127
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128static unsigned long htb_get(struct Qdisc *sch, u32 classid)
1129{
Stephen Hemminger87990462006-08-10 23:35:16 -07001130 struct htb_class *cl = htb_find(classid, sch);
1131 if (cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 cl->refcnt++;
1133 return (unsigned long)cl;
1134}
1135
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001136static inline int htb_parent_last_child(struct htb_class *cl)
1137{
1138 if (!cl->parent)
1139 /* the root class */
1140 return 0;
Patrick McHardy42077592008-07-05 23:22:53 -07001141 if (cl->parent->children > 1)
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001142 /* not the last child */
1143 return 0;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001144 return 1;
1145}
1146
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001147static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
1148 struct Qdisc *new_q)
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001149{
1150 struct htb_class *parent = cl->parent;
1151
Ilpo Järvinen547b7922008-07-25 21:43:18 -07001152 WARN_ON(cl->level || !cl->un.leaf.q || cl->prio_activity);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001153
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001154 if (parent->cmode != HTB_CAN_SEND)
1155 htb_safe_rb_erase(&parent->pq_node, q->wait_pq + parent->level);
1156
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001157 parent->level = 0;
1158 memset(&parent->un.inner, 0, sizeof(parent->un.inner));
1159 INIT_LIST_HEAD(&parent->un.leaf.drop_list);
1160 parent->un.leaf.q = new_q ? new_q : &noop_qdisc;
1161 parent->un.leaf.quantum = parent->quantum;
1162 parent->un.leaf.prio = parent->prio;
1163 parent->tokens = parent->buffer;
1164 parent->ctokens = parent->cbuffer;
Patrick McHardy3bebcda2007-03-23 11:29:25 -07001165 parent->t_c = psched_get_time();
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001166 parent->cmode = HTB_CAN_SEND;
1167}
1168
Stephen Hemminger87990462006-08-10 23:35:16 -07001169static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 if (!cl->level) {
Ilpo Järvinen547b7922008-07-25 21:43:18 -07001172 WARN_ON(!cl->un.leaf.q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 qdisc_destroy(cl->un.leaf.q);
1174 }
Patrick McHardyee39e102007-07-02 22:48:13 -07001175 gen_kill_estimator(&cl->bstats, &cl->rate_est);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 qdisc_put_rtab(cl->rate);
1177 qdisc_put_rtab(cl->ceil);
Stephen Hemminger87990462006-08-10 23:35:16 -07001178
Patrick McHardyff31ab52008-07-01 19:52:38 -07001179 tcf_destroy_chain(&cl->filter_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 kfree(cl);
1181}
1182
1183/* always caled under BH & queue lock */
Stephen Hemminger87990462006-08-10 23:35:16 -07001184static void htb_destroy(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185{
1186 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001187 struct hlist_node *n, *next;
1188 struct htb_class *cl;
1189 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190
Patrick McHardyfb983d42007-03-16 01:22:39 -07001191 qdisc_watchdog_cancel(&q->watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 /* This line used to be after htb_destroy_class call below
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +09001193 and surprisingly it worked in 2.4. But it must precede it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 because filter need its target class alive to be able to call
1195 unbind_filter on it (without Oops). */
Patrick McHardyff31ab52008-07-01 19:52:38 -07001196 tcf_destroy_chain(&q->filter_list);
Stephen Hemminger87990462006-08-10 23:35:16 -07001197
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001198 for (i = 0; i < q->clhash.hashsize; i++) {
1199 hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode)
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001200 tcf_destroy_chain(&cl->filter_list);
1201 }
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001202 for (i = 0; i < q->clhash.hashsize; i++) {
1203 hlist_for_each_entry_safe(cl, n, next, &q->clhash.hash[i],
1204 common.hnode)
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001205 htb_destroy_class(sch, cl);
1206 }
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001207 qdisc_class_hash_destroy(&q->clhash);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 __skb_queue_purge(&q->direct_queue);
1209}
1210
1211static int htb_delete(struct Qdisc *sch, unsigned long arg)
1212{
1213 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001214 struct htb_class *cl = (struct htb_class *)arg;
Patrick McHardy256d61b2006-11-29 17:37:05 -08001215 unsigned int qlen;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001216 struct Qdisc *new_q = NULL;
1217 int last_child = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218
1219 // TODO: why don't allow to delete subtree ? references ? does
1220 // tc subsys quarantee us that in htb_destroy it holds no class
1221 // refs so that we can remove children safely there ?
Patrick McHardy42077592008-07-05 23:22:53 -07001222 if (cl->children || cl->filter_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 return -EBUSY;
Stephen Hemminger87990462006-08-10 23:35:16 -07001224
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001225 if (!cl->level && htb_parent_last_child(cl)) {
David S. Miller5ce2d482008-07-08 17:06:30 -07001226 new_q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
David S. Millerbb949fb2008-07-08 16:55:56 -07001227 &pfifo_qdisc_ops,
1228 cl->parent->common.classid);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001229 last_child = 1;
1230 }
1231
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 sch_tree_lock(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001233
Patrick McHardy814a175e2006-11-29 17:34:50 -08001234 if (!cl->level) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001235 qlen = cl->un.leaf.q->q.qlen;
Patrick McHardy814a175e2006-11-29 17:34:50 -08001236 qdisc_reset(cl->un.leaf.q);
Patrick McHardy256d61b2006-11-29 17:37:05 -08001237 qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen);
Patrick McHardy814a175e2006-11-29 17:34:50 -08001238 }
1239
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001240 /* delete from hash and active; remainder in destroy_class */
1241 qdisc_class_hash_remove(&q->clhash, &cl->common);
Jarek Poplawski26b284d2008-08-13 15:16:43 -07001242 if (cl->parent)
1243 cl->parent->children--;
Patrick McHardyc38c83c2007-03-27 14:04:24 -07001244
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 if (cl->prio_activity)
Stephen Hemminger87990462006-08-10 23:35:16 -07001246 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001248 if (cl->cmode != HTB_CAN_SEND)
1249 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
1250
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001251 if (last_child)
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001252 htb_parent_to_leaf(q, cl, new_q);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001253
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 if (--cl->refcnt == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -07001255 htb_destroy_class(sch, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
1257 sch_tree_unlock(sch);
1258 return 0;
1259}
1260
1261static void htb_put(struct Qdisc *sch, unsigned long arg)
1262{
Stephen Hemminger87990462006-08-10 23:35:16 -07001263 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
1265 if (--cl->refcnt == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -07001266 htb_destroy_class(sch, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267}
1268
Stephen Hemminger87990462006-08-10 23:35:16 -07001269static int htb_change_class(struct Qdisc *sch, u32 classid,
Patrick McHardy1e904742008-01-22 22:11:17 -08001270 u32 parentid, struct nlattr **tca,
Stephen Hemminger87990462006-08-10 23:35:16 -07001271 unsigned long *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272{
1273 int err = -EINVAL;
1274 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001275 struct htb_class *cl = (struct htb_class *)*arg, *parent;
Patrick McHardy1e904742008-01-22 22:11:17 -08001276 struct nlattr *opt = tca[TCA_OPTIONS];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
Patrick McHardy1e904742008-01-22 22:11:17 -08001278 struct nlattr *tb[TCA_HTB_RTAB + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 struct tc_htb_opt *hopt;
1280
1281 /* extract all subattrs from opt attr */
Patrick McHardycee63722008-01-23 20:33:32 -08001282 if (!opt)
1283 goto failure;
1284
Patrick McHardy27a34212008-01-23 20:35:39 -08001285 err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, htb_policy);
Patrick McHardycee63722008-01-23 20:33:32 -08001286 if (err < 0)
1287 goto failure;
1288
1289 err = -EINVAL;
Patrick McHardy27a34212008-01-23 20:35:39 -08001290 if (tb[TCA_HTB_PARMS] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 goto failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292
Stephen Hemminger87990462006-08-10 23:35:16 -07001293 parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001294
Patrick McHardy1e904742008-01-22 22:11:17 -08001295 hopt = nla_data(tb[TCA_HTB_PARMS]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296
Patrick McHardy1e904742008-01-22 22:11:17 -08001297 rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]);
1298 ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]);
Stephen Hemminger87990462006-08-10 23:35:16 -07001299 if (!rtab || !ctab)
1300 goto failure;
1301
1302 if (!cl) { /* new class */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 struct Qdisc *new_q;
Stephen Hemminger3696f622006-08-10 23:36:01 -07001304 int prio;
Patrick McHardyee39e102007-07-02 22:48:13 -07001305 struct {
Patrick McHardy1e904742008-01-22 22:11:17 -08001306 struct nlattr nla;
Patrick McHardyee39e102007-07-02 22:48:13 -07001307 struct gnet_estimator opt;
1308 } est = {
Patrick McHardy1e904742008-01-22 22:11:17 -08001309 .nla = {
1310 .nla_len = nla_attr_size(sizeof(est.opt)),
1311 .nla_type = TCA_RATE,
Patrick McHardyee39e102007-07-02 22:48:13 -07001312 },
1313 .opt = {
1314 /* 4s interval, 16s averaging constant */
1315 .interval = 2,
1316 .ewma_log = 2,
1317 },
1318 };
Stephen Hemminger3696f622006-08-10 23:36:01 -07001319
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 /* check for valid classid */
Stephen Hemminger87990462006-08-10 23:35:16 -07001321 if (!classid || TC_H_MAJ(classid ^ sch->handle)
1322 || htb_find(classid, sch))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 goto failure;
1324
1325 /* check maximal depth */
1326 if (parent && parent->parent && parent->parent->level < 2) {
1327 printk(KERN_ERR "htb: tree is too deep\n");
1328 goto failure;
1329 }
1330 err = -ENOBUFS;
Panagiotis Issaris0da974f2006-07-21 14:51:30 -07001331 if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 goto failure;
Stephen Hemminger87990462006-08-10 23:35:16 -07001333
Stephen Hemminger71bcb092008-11-25 21:13:31 -08001334 err = gen_new_estimator(&cl->bstats, &cl->rate_est,
1335 qdisc_root_sleeping_lock(sch),
1336 tca[TCA_RATE] ? : &est.nla);
1337 if (err) {
1338 kfree(cl);
1339 goto failure;
1340 }
1341
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 cl->refcnt = 1;
Patrick McHardy42077592008-07-05 23:22:53 -07001343 cl->children = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 INIT_LIST_HEAD(&cl->un.leaf.drop_list);
Stephen Hemminger3696f622006-08-10 23:36:01 -07001345 RB_CLEAR_NODE(&cl->pq_node);
1346
1347 for (prio = 0; prio < TC_HTB_NUMPRIO; prio++)
1348 RB_CLEAR_NODE(&cl->node[prio]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349
1350 /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
1351 so that can't be used inside of sch_tree_lock
1352 -- thanks to Karlis Peisenieks */
David S. Miller5ce2d482008-07-08 17:06:30 -07001353 new_q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
David S. Millerbb949fb2008-07-08 16:55:56 -07001354 &pfifo_qdisc_ops, classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 sch_tree_lock(sch);
1356 if (parent && !parent->level) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001357 unsigned int qlen = parent->un.leaf.q->q.qlen;
1358
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 /* turn parent into inner node */
Patrick McHardy256d61b2006-11-29 17:37:05 -08001360 qdisc_reset(parent->un.leaf.q);
1361 qdisc_tree_decrease_qlen(parent->un.leaf.q, qlen);
Stephen Hemminger87990462006-08-10 23:35:16 -07001362 qdisc_destroy(parent->un.leaf.q);
1363 if (parent->prio_activity)
1364 htb_deactivate(q, parent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
1366 /* remove from evt list because of level change */
1367 if (parent->cmode != HTB_CAN_SEND) {
Stephen Hemminger3696f622006-08-10 23:36:01 -07001368 htb_safe_rb_erase(&parent->pq_node, q->wait_pq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 parent->cmode = HTB_CAN_SEND;
1370 }
1371 parent->level = (parent->parent ? parent->parent->level
Stephen Hemminger87990462006-08-10 23:35:16 -07001372 : TC_HTB_MAXDEPTH) - 1;
1373 memset(&parent->un.inner, 0, sizeof(parent->un.inner));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 }
1375 /* leaf (we) needs elementary qdisc */
1376 cl->un.leaf.q = new_q ? new_q : &noop_qdisc;
1377
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001378 cl->common.classid = classid;
Stephen Hemminger87990462006-08-10 23:35:16 -07001379 cl->parent = parent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380
1381 /* set class to be in HTB_CAN_SEND state */
1382 cl->tokens = hopt->buffer;
1383 cl->ctokens = hopt->cbuffer;
Patrick McHardy00c04af2007-03-16 01:23:02 -07001384 cl->mbuffer = 60 * PSCHED_TICKS_PER_SEC; /* 1min */
Patrick McHardy3bebcda2007-03-23 11:29:25 -07001385 cl->t_c = psched_get_time();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 cl->cmode = HTB_CAN_SEND;
1387
1388 /* attach to the hash list and parent's family */
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001389 qdisc_class_hash_insert(&q->clhash, &cl->common);
Patrick McHardy42077592008-07-05 23:22:53 -07001390 if (parent)
1391 parent->children++;
Patrick McHardyee39e102007-07-02 22:48:13 -07001392 } else {
Stephen Hemminger71bcb092008-11-25 21:13:31 -08001393 if (tca[TCA_RATE]) {
1394 err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
1395 qdisc_root_sleeping_lock(sch),
1396 tca[TCA_RATE]);
1397 if (err)
1398 return err;
1399 }
Stephen Hemminger87990462006-08-10 23:35:16 -07001400 sch_tree_lock(sch);
Patrick McHardyee39e102007-07-02 22:48:13 -07001401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
1403 /* it used to be a nasty bug here, we have to check that node
Stephen Hemminger87990462006-08-10 23:35:16 -07001404 is really leaf before changing cl->un.leaf ! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 if (!cl->level) {
1406 cl->un.leaf.quantum = rtab->rate.rate / q->rate2quantum;
1407 if (!hopt->quantum && cl->un.leaf.quantum < 1000) {
Stephen Hemminger87990462006-08-10 23:35:16 -07001408 printk(KERN_WARNING
1409 "HTB: quantum of class %X is small. Consider r2q change.\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001410 cl->common.classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 cl->un.leaf.quantum = 1000;
1412 }
1413 if (!hopt->quantum && cl->un.leaf.quantum > 200000) {
Stephen Hemminger87990462006-08-10 23:35:16 -07001414 printk(KERN_WARNING
1415 "HTB: quantum of class %X is big. Consider r2q change.\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001416 cl->common.classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 cl->un.leaf.quantum = 200000;
1418 }
1419 if (hopt->quantum)
1420 cl->un.leaf.quantum = hopt->quantum;
1421 if ((cl->un.leaf.prio = hopt->prio) >= TC_HTB_NUMPRIO)
1422 cl->un.leaf.prio = TC_HTB_NUMPRIO - 1;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001423
1424 /* backup for htb_parent_to_leaf */
1425 cl->quantum = cl->un.leaf.quantum;
1426 cl->prio = cl->un.leaf.prio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 }
1428
1429 cl->buffer = hopt->buffer;
1430 cl->cbuffer = hopt->cbuffer;
Stephen Hemminger87990462006-08-10 23:35:16 -07001431 if (cl->rate)
1432 qdisc_put_rtab(cl->rate);
1433 cl->rate = rtab;
1434 if (cl->ceil)
1435 qdisc_put_rtab(cl->ceil);
1436 cl->ceil = ctab;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 sch_tree_unlock(sch);
1438
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001439 qdisc_class_hash_grow(sch, &q->clhash);
1440
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 *arg = (unsigned long)cl;
1442 return 0;
1443
1444failure:
Stephen Hemminger87990462006-08-10 23:35:16 -07001445 if (rtab)
1446 qdisc_put_rtab(rtab);
1447 if (ctab)
1448 qdisc_put_rtab(ctab);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 return err;
1450}
1451
1452static struct tcf_proto **htb_find_tcf(struct Qdisc *sch, unsigned long arg)
1453{
1454 struct htb_sched *q = qdisc_priv(sch);
1455 struct htb_class *cl = (struct htb_class *)arg;
1456 struct tcf_proto **fl = cl ? &cl->filter_list : &q->filter_list;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001457
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 return fl;
1459}
1460
1461static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent,
Stephen Hemminger87990462006-08-10 23:35:16 -07001462 u32 classid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463{
Stephen Hemminger87990462006-08-10 23:35:16 -07001464 struct htb_class *cl = htb_find(classid, sch);
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001465
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 /*if (cl && !cl->level) return 0;
Stephen Hemminger87990462006-08-10 23:35:16 -07001467 The line above used to be there to prevent attaching filters to
1468 leaves. But at least tc_index filter uses this just to get class
1469 for other reasons so that we have to allow for it.
1470 ----
1471 19.6.2002 As Werner explained it is ok - bind filter is just
1472 another way to "lock" the class - unlike "get" this lock can
1473 be broken by class during destroy IIUC.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 */
Stephen Hemminger87990462006-08-10 23:35:16 -07001475 if (cl)
1476 cl->filter_cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 return (unsigned long)cl;
1478}
1479
1480static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg)
1481{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 struct htb_class *cl = (struct htb_class *)arg;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001483
Stephen Hemminger87990462006-08-10 23:35:16 -07001484 if (cl)
1485 cl->filter_cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486}
1487
1488static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg)
1489{
1490 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001491 struct htb_class *cl;
1492 struct hlist_node *n;
1493 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494
1495 if (arg->stop)
1496 return;
1497
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001498 for (i = 0; i < q->clhash.hashsize; i++) {
1499 hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 if (arg->count < arg->skip) {
1501 arg->count++;
1502 continue;
1503 }
1504 if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
1505 arg->stop = 1;
1506 return;
1507 }
1508 arg->count++;
1509 }
1510 }
1511}
1512
Eric Dumazet20fea082007-11-14 01:44:41 -08001513static const struct Qdisc_class_ops htb_class_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 .graft = htb_graft,
1515 .leaf = htb_leaf,
Patrick McHardy256d61b2006-11-29 17:37:05 -08001516 .qlen_notify = htb_qlen_notify,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 .get = htb_get,
1518 .put = htb_put,
1519 .change = htb_change_class,
1520 .delete = htb_delete,
1521 .walk = htb_walk,
1522 .tcf_chain = htb_find_tcf,
1523 .bind_tcf = htb_bind_filter,
1524 .unbind_tcf = htb_unbind_filter,
1525 .dump = htb_dump_class,
1526 .dump_stats = htb_dump_class_stats,
1527};
1528
Eric Dumazet20fea082007-11-14 01:44:41 -08001529static struct Qdisc_ops htb_qdisc_ops __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 .next = NULL,
1531 .cl_ops = &htb_class_ops,
1532 .id = "htb",
1533 .priv_size = sizeof(struct htb_sched),
1534 .enqueue = htb_enqueue,
1535 .dequeue = htb_dequeue,
Jarek Poplawski77be1552008-10-31 00:47:01 -07001536 .peek = qdisc_peek_dequeued,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 .drop = htb_drop,
1538 .init = htb_init,
1539 .reset = htb_reset,
1540 .destroy = htb_destroy,
1541 .change = NULL /* htb_change */,
1542 .dump = htb_dump,
1543 .owner = THIS_MODULE,
1544};
1545
1546static int __init htb_module_init(void)
1547{
Stephen Hemminger87990462006-08-10 23:35:16 -07001548 return register_qdisc(&htb_qdisc_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549}
Stephen Hemminger87990462006-08-10 23:35:16 -07001550static void __exit htb_module_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551{
Stephen Hemminger87990462006-08-10 23:35:16 -07001552 unregister_qdisc(&htb_qdisc_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553}
Stephen Hemminger87990462006-08-10 23:35:16 -07001554
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555module_init(htb_module_init)
1556module_exit(htb_module_exit)
1557MODULE_LICENSE("GPL");