blob: 7a71e9412e03a164d3dfad3f2cdc76399946a863 [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 int defcls; /* class where unclassified flows go to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
Stephen Hemminger87990462006-08-10 23:35:16 -0700156 /* filters for qdisc itself */
157 struct tcf_proto *filter_list;
Stephen Hemminger87990462006-08-10 23:35:16 -0700158
159 int rate2quantum; /* quant = rate / rate2quantum */
160 psched_time_t now; /* cached dequeue time */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700161 struct qdisc_watchdog watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162
Stephen Hemminger87990462006-08-10 23:35:16 -0700163 /* non shaped skbs; let them go directly thru */
164 struct sk_buff_head direct_queue;
165 int direct_qlen; /* max qlen of above */
166
167 long direct_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168};
169
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170/* find class in global hash table using given handle */
Stephen Hemminger87990462006-08-10 23:35:16 -0700171static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172{
173 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700174 struct Qdisc_class_common *clc;
Stephen Hemminger0cef2962006-08-10 23:35:38 -0700175
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700176 clc = qdisc_class_find(&q->clhash, handle);
177 if (clc == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 return NULL;
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700179 return container_of(clc, struct htb_class, common);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180}
181
182/**
183 * htb_classify - classify a packet into class
184 *
185 * It returns NULL if the packet should be dropped or -1 if the packet
186 * should be passed directly thru. In all other cases leaf class is returned.
187 * We allow direct class selection by classid in priority. The we examine
188 * filters in qdisc and in inner nodes (if higher filter points to the inner
189 * node). If we end up with classid MAJOR:0 we enqueue the skb into special
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900190 * internal fifo (direct). These packets then go directly thru. If we still
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessfull
192 * then finish and return direct queue.
193 */
194#define HTB_DIRECT (struct htb_class*)-1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195
Stephen Hemminger87990462006-08-10 23:35:16 -0700196static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
197 int *qerr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198{
199 struct htb_sched *q = qdisc_priv(sch);
200 struct htb_class *cl;
201 struct tcf_result res;
202 struct tcf_proto *tcf;
203 int result;
204
205 /* allow to select class by setting skb->priority to valid classid;
206 note that nfmark can be used too by attaching filter fw with no
207 rules in it */
208 if (skb->priority == sch->handle)
Stephen Hemminger87990462006-08-10 23:35:16 -0700209 return HTB_DIRECT; /* X:0 (direct flow) selected */
210 if ((cl = htb_find(skb->priority, sch)) != NULL && cl->level == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 return cl;
212
Jarek Poplawskic27f3392008-08-04 22:39:11 -0700213 *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 tcf = q->filter_list;
215 while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
216#ifdef CONFIG_NET_CLS_ACT
217 switch (result) {
218 case TC_ACT_QUEUED:
Stephen Hemminger87990462006-08-10 23:35:16 -0700219 case TC_ACT_STOLEN:
Jarek Poplawski378a2f02008-08-04 22:31:03 -0700220 *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 case TC_ACT_SHOT:
222 return NULL;
223 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224#endif
Stephen Hemminger87990462006-08-10 23:35:16 -0700225 if ((cl = (void *)res.class) == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 if (res.classid == sch->handle)
Stephen Hemminger87990462006-08-10 23:35:16 -0700227 return HTB_DIRECT; /* X:0 (direct flow) */
228 if ((cl = htb_find(res.classid, sch)) == NULL)
229 break; /* filter selected invalid classid */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 }
231 if (!cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700232 return cl; /* we hit leaf; return it */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
234 /* we have got inner class; apply inner filter chain */
235 tcf = cl->filter_list;
236 }
237 /* classification failed; try to use default class */
Stephen Hemminger87990462006-08-10 23:35:16 -0700238 cl = htb_find(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 if (!cl || cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700240 return HTB_DIRECT; /* bad default .. this is safe bet */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 return cl;
242}
243
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244/**
245 * htb_add_to_id_tree - adds class to the round robin list
246 *
247 * Routine adds class to the list (actually tree) sorted by classid.
248 * Make sure that class is not already on such list for given prio.
249 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700250static void htb_add_to_id_tree(struct rb_root *root,
251 struct htb_class *cl, int prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252{
253 struct rb_node **p = &root->rb_node, *parent = NULL;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700254
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 while (*p) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700256 struct htb_class *c;
257 parent = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 c = rb_entry(parent, struct htb_class, node[prio]);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700259
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700260 if (cl->common.classid > c->common.classid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 p = &parent->rb_right;
Stephen Hemminger87990462006-08-10 23:35:16 -0700262 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 p = &parent->rb_left;
264 }
265 rb_link_node(&cl->node[prio], parent, p);
266 rb_insert_color(&cl->node[prio], root);
267}
268
269/**
270 * htb_add_to_wait_tree - adds class to the event queue with delay
271 *
272 * The class is added to priority event queue to indicate that class will
273 * change its mode in cl->pq_key microseconds. Make sure that class is not
274 * already in the queue.
275 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700276static void htb_add_to_wait_tree(struct htb_sched *q,
277 struct htb_class *cl, long delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278{
279 struct rb_node **p = &q->wait_pq[cl->level].rb_node, *parent = NULL;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700280
Patrick McHardyfb983d42007-03-16 01:22:39 -0700281 cl->pq_key = q->now + delay;
282 if (cl->pq_key == q->now)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 cl->pq_key++;
284
285 /* update the nearest event cache */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700286 if (q->near_ev_cache[cl->level] > cl->pq_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 q->near_ev_cache[cl->level] = cl->pq_key;
Stephen Hemminger87990462006-08-10 23:35:16 -0700288
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 while (*p) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700290 struct htb_class *c;
291 parent = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 c = rb_entry(parent, struct htb_class, pq_node);
Patrick McHardyfb983d42007-03-16 01:22:39 -0700293 if (cl->pq_key >= c->pq_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 p = &parent->rb_right;
Stephen Hemminger87990462006-08-10 23:35:16 -0700295 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 p = &parent->rb_left;
297 }
298 rb_link_node(&cl->pq_node, parent, p);
299 rb_insert_color(&cl->pq_node, &q->wait_pq[cl->level]);
300}
301
302/**
303 * htb_next_rb_node - finds next node in binary tree
304 *
305 * When we are past last key we return NULL.
306 * Average complexity is 2 steps per call.
307 */
Stephen Hemminger3696f622006-08-10 23:36:01 -0700308static inline void htb_next_rb_node(struct rb_node **n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309{
310 *n = rb_next(*n);
311}
312
313/**
314 * htb_add_class_to_row - add class to its row
315 *
316 * The class is added to row at priorities marked in mask.
317 * It does nothing if mask == 0.
318 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700319static inline void htb_add_class_to_row(struct htb_sched *q,
320 struct htb_class *cl, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 q->row_mask[cl->level] |= mask;
323 while (mask) {
324 int prio = ffz(~mask);
325 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700326 htb_add_to_id_tree(q->row[cl->level] + prio, cl, prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 }
328}
329
Stephen Hemminger3696f622006-08-10 23:36:01 -0700330/* If this triggers, it is a bug in this code, but it need not be fatal */
331static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root)
332{
Ismail Donmez81771b32006-10-03 13:49:10 -0700333 if (RB_EMPTY_NODE(rb)) {
Stephen Hemminger3696f622006-08-10 23:36:01 -0700334 WARN_ON(1);
335 } else {
336 rb_erase(rb, root);
337 RB_CLEAR_NODE(rb);
338 }
339}
340
341
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342/**
343 * htb_remove_class_from_row - removes class from its row
344 *
345 * The class is removed from row at priorities marked in mask.
346 * It does nothing if mask == 0.
347 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700348static inline void htb_remove_class_from_row(struct htb_sched *q,
349 struct htb_class *cl, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350{
351 int m = 0;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 while (mask) {
354 int prio = ffz(~mask);
Stephen Hemminger3696f622006-08-10 23:36:01 -0700355
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700357 if (q->ptr[cl->level][prio] == cl->node + prio)
358 htb_next_rb_node(q->ptr[cl->level] + prio);
Stephen Hemminger3696f622006-08-10 23:36:01 -0700359
360 htb_safe_rb_erase(cl->node + prio, q->row[cl->level] + prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700361 if (!q->row[cl->level][prio].rb_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 m |= 1 << prio;
363 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 q->row_mask[cl->level] &= ~m;
365}
366
367/**
368 * htb_activate_prios - creates active classe's feed chain
369 *
370 * The class is connected to ancestors and/or appropriate rows
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900371 * for priorities it is participating on. cl->cmode must be new
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 * (activated) mode. It does nothing if cl->prio_activity == 0.
373 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700374static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375{
376 struct htb_class *p = cl->parent;
Stephen Hemminger87990462006-08-10 23:35:16 -0700377 long m, mask = cl->prio_activity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700380 m = mask;
381 while (m) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 int prio = ffz(~m);
383 m &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700384
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 if (p->un.inner.feed[prio].rb_node)
386 /* parent already has its feed in use so that
387 reset bit in mask as parent is already ok */
388 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700389
390 htb_add_to_id_tree(p->un.inner.feed + prio, cl, prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 p->prio_activity |= mask;
Stephen Hemminger87990462006-08-10 23:35:16 -0700393 cl = p;
394 p = cl->parent;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700395
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 }
397 if (cl->cmode == HTB_CAN_SEND && mask)
Stephen Hemminger87990462006-08-10 23:35:16 -0700398 htb_add_class_to_row(q, cl, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399}
400
401/**
402 * htb_deactivate_prios - remove class from feed chain
403 *
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900404 * cl->cmode must represent old mode (before deactivation). It does
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 * nothing if cl->prio_activity == 0. Class is removed from all feed
406 * chains and rows.
407 */
408static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl)
409{
410 struct htb_class *p = cl->parent;
Stephen Hemminger87990462006-08-10 23:35:16 -0700411 long m, mask = cl->prio_activity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
413 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700414 m = mask;
415 mask = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 while (m) {
417 int prio = ffz(~m);
418 m &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700419
420 if (p->un.inner.ptr[prio] == cl->node + prio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 /* we are removing child which is pointed to from
422 parent feed - forget the pointer but remember
423 classid */
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700424 p->un.inner.last_ptr_id[prio] = cl->common.classid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 p->un.inner.ptr[prio] = NULL;
426 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700427
Stephen Hemminger3696f622006-08-10 23:36:01 -0700428 htb_safe_rb_erase(cl->node + prio, p->un.inner.feed + prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700429
430 if (!p->un.inner.feed[prio].rb_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 mask |= 1 << prio;
432 }
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700433
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 p->prio_activity &= ~mask;
Stephen Hemminger87990462006-08-10 23:35:16 -0700435 cl = p;
436 p = cl->parent;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700437
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700439 if (cl->cmode == HTB_CAN_SEND && mask)
440 htb_remove_class_from_row(q, cl, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441}
442
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700443static inline long htb_lowater(const struct htb_class *cl)
444{
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700445 if (htb_hysteresis)
446 return cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : 0;
447 else
448 return 0;
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700449}
450static inline long htb_hiwater(const struct htb_class *cl)
451{
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700452 if (htb_hysteresis)
453 return cl->cmode == HTB_CAN_SEND ? -cl->buffer : 0;
454 else
455 return 0;
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700456}
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700457
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700458
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459/**
460 * htb_class_mode - computes and returns current class mode
461 *
462 * It computes cl's mode at time cl->t_c+diff and returns it. If mode
463 * is not HTB_CAN_SEND then cl->pq_key is updated to time difference
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900464 * from now to time when cl will change its state.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 * Also it is worth to note that class mode doesn't change simply
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900466 * at cl->{c,}tokens == 0 but there can rather be hysteresis of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 * 0 .. -cl->{c,}buffer range. It is meant to limit number of
468 * mode transitions per time unit. The speed gain is about 1/6.
469 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700470static inline enum htb_cmode
471htb_class_mode(struct htb_class *cl, long *diff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
Stephen Hemminger87990462006-08-10 23:35:16 -0700473 long toks;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474
Stephen Hemminger87990462006-08-10 23:35:16 -0700475 if ((toks = (cl->ctokens + *diff)) < htb_lowater(cl)) {
476 *diff = -toks;
477 return HTB_CANT_SEND;
478 }
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700479
Stephen Hemminger87990462006-08-10 23:35:16 -0700480 if ((toks = (cl->tokens + *diff)) >= htb_hiwater(cl))
481 return HTB_CAN_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
Stephen Hemminger87990462006-08-10 23:35:16 -0700483 *diff = -toks;
484 return HTB_MAY_BORROW;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485}
486
487/**
488 * htb_change_class_mode - changes classe's mode
489 *
490 * This should be the only way how to change classe's mode under normal
491 * cirsumstances. Routine will update feed lists linkage, change mode
492 * and add class to the wait event queue if appropriate. New mode should
493 * be different from old one and cl->pq_key has to be valid if changing
494 * to mode other than HTB_CAN_SEND (see htb_add_to_wait_tree).
495 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700496static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long *diff)
Stephen Hemminger87990462006-08-10 23:35:16 -0700498{
499 enum htb_cmode new_mode = htb_class_mode(cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
501 if (new_mode == cl->cmode)
Stephen Hemminger87990462006-08-10 23:35:16 -0700502 return;
503
504 if (cl->prio_activity) { /* not necessary: speed optimization */
505 if (cl->cmode != HTB_CANT_SEND)
506 htb_deactivate_prios(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 cl->cmode = new_mode;
Stephen Hemminger87990462006-08-10 23:35:16 -0700508 if (new_mode != HTB_CANT_SEND)
509 htb_activate_prios(q, cl);
510 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 cl->cmode = new_mode;
512}
513
514/**
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900515 * htb_activate - inserts leaf cl into appropriate active feeds
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 *
517 * Routine learns (new) priority of leaf and activates feed chain
518 * for the prio. It can be called on already active leaf safely.
519 * It also adds leaf into droplist.
520 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700521static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522{
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700523 WARN_ON(cl->level || !cl->un.leaf.q || !cl->un.leaf.q->q.qlen);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700524
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 if (!cl->prio_activity) {
Jarek Poplawski4164d662008-12-03 21:08:44 -0800526 cl->prio_activity = 1 << cl->un.leaf.prio;
Stephen Hemminger87990462006-08-10 23:35:16 -0700527 htb_activate_prios(q, cl);
528 list_add_tail(&cl->un.leaf.drop_list,
Jarek Poplawski4164d662008-12-03 21:08:44 -0800529 q->drops + cl->un.leaf.prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 }
531}
532
533/**
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900534 * htb_deactivate - remove leaf cl from active feeds
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 *
536 * Make sure that leaf is active. In the other words it can't be called
537 * with non-active leaf. It also removes class from the drop list.
538 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700539static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540{
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700541 WARN_ON(!cl->prio_activity);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700542
Stephen Hemminger87990462006-08-10 23:35:16 -0700543 htb_deactivate_prios(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 cl->prio_activity = 0;
545 list_del_init(&cl->un.leaf.drop_list);
546}
547
548static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
549{
Jarek Poplawskif30ab412008-11-13 22:56:30 -0800550 int uninitialized_var(ret);
Stephen Hemminger87990462006-08-10 23:35:16 -0700551 struct htb_sched *q = qdisc_priv(sch);
552 struct htb_class *cl = htb_classify(skb, sch, &ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553
Stephen Hemminger87990462006-08-10 23:35:16 -0700554 if (cl == HTB_DIRECT) {
555 /* enqueue to helper queue */
556 if (q->direct_queue.qlen < q->direct_qlen) {
557 __skb_queue_tail(&q->direct_queue, skb);
558 q->direct_pkts++;
559 } else {
560 kfree_skb(skb);
561 sch->qstats.drops++;
562 return NET_XMIT_DROP;
563 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564#ifdef CONFIG_NET_CLS_ACT
Stephen Hemminger87990462006-08-10 23:35:16 -0700565 } else if (!cl) {
Jarek Poplawskic27f3392008-08-04 22:39:11 -0700566 if (ret & __NET_XMIT_BYPASS)
Stephen Hemminger87990462006-08-10 23:35:16 -0700567 sch->qstats.drops++;
568 kfree_skb(skb);
569 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570#endif
Jarek Poplawski378a2f02008-08-04 22:31:03 -0700571 } else if ((ret = qdisc_enqueue(skb, cl->un.leaf.q)) != NET_XMIT_SUCCESS) {
572 if (net_xmit_drop_count(ret)) {
573 sch->qstats.drops++;
574 cl->qstats.drops++;
575 }
David S. Miller69747652008-08-17 23:55:36 -0700576 return ret;
Stephen Hemminger87990462006-08-10 23:35:16 -0700577 } else {
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700578 cl->bstats.packets +=
579 skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700580 cl->bstats.bytes += qdisc_pkt_len(skb);
Stephen Hemminger87990462006-08-10 23:35:16 -0700581 htb_activate(q, cl);
582 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583
Stephen Hemminger87990462006-08-10 23:35:16 -0700584 sch->q.qlen++;
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700585 sch->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700586 sch->bstats.bytes += qdisc_pkt_len(skb);
Stephen Hemminger87990462006-08-10 23:35:16 -0700587 return NET_XMIT_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588}
589
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590/**
591 * htb_charge_class - charges amount "bytes" to leaf and ancestors
592 *
593 * Routine assumes that packet "bytes" long was dequeued from leaf cl
594 * borrowing from "level". It accounts bytes to ceil leaky bucket for
595 * leaf and all ancestors and to rate bucket for ancestors at levels
596 * "level" and higher. It also handles possible change of mode resulting
597 * from the update. Note that mode can also increase here (MAY_BORROW to
598 * CAN_SEND) because we can use more precise clock that event queue here.
599 * In such case we remove class from event queue first.
600 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700601static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700602 int level, struct sk_buff *skb)
Stephen Hemminger87990462006-08-10 23:35:16 -0700603{
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700604 int bytes = qdisc_pkt_len(skb);
Stephen Hemminger87990462006-08-10 23:35:16 -0700605 long toks, diff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 enum htb_cmode old_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
608#define HTB_ACCNT(T,B,R) toks = diff + cl->T; \
609 if (toks > cl->B) toks = cl->B; \
610 toks -= L2T(cl, cl->R, bytes); \
611 if (toks <= -cl->mbuffer) toks = 1-cl->mbuffer; \
612 cl->T = toks
613
614 while (cl) {
Patrick McHardy03cc45c2007-03-23 11:29:11 -0700615 diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 if (cl->level >= level) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700617 if (cl->level == level)
618 cl->xstats.lends++;
619 HTB_ACCNT(tokens, buffer, rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 } else {
621 cl->xstats.borrows++;
Stephen Hemminger87990462006-08-10 23:35:16 -0700622 cl->tokens += diff; /* we moved t_c; update tokens */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700624 HTB_ACCNT(ctokens, cbuffer, ceil);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 cl->t_c = q->now;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
Stephen Hemminger87990462006-08-10 23:35:16 -0700627 old_mode = cl->cmode;
628 diff = 0;
629 htb_change_class_mode(q, cl, &diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 if (old_mode != cl->cmode) {
631 if (old_mode != HTB_CAN_SEND)
Stephen Hemminger3696f622006-08-10 23:36:01 -0700632 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 if (cl->cmode != HTB_CAN_SEND)
Stephen Hemminger87990462006-08-10 23:35:16 -0700634 htb_add_to_wait_tree(q, cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
637 /* update byte stats except for leaves which are already updated */
638 if (cl->level) {
639 cl->bstats.bytes += bytes;
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700640 cl->bstats.packets += skb_is_gso(skb)?
641 skb_shinfo(skb)->gso_segs:1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 }
643 cl = cl->parent;
644 }
645}
646
647/**
648 * htb_do_events - make mode changes to classes at the level
649 *
Patrick McHardyfb983d42007-03-16 01:22:39 -0700650 * Scans event queue for pending events and applies them. Returns time of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 * next pending event (0 for no event in pq).
Patrick McHardyfb983d42007-03-16 01:22:39 -0700652 * Note: Applied are events whose have cl->pq_key <= q->now.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700654static psched_time_t htb_do_events(struct htb_sched *q, int level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655{
Martin Devera8f3ea332008-03-23 22:00:38 -0700656 /* don't run for longer than 2 jiffies; 2 is used instead of
657 1 to simplify things when jiffy is going to be incremented
658 too soon */
659 unsigned long stop_at = jiffies + 2;
660 while (time_before(jiffies, stop_at)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 struct htb_class *cl;
662 long diff;
Akinbou Mita30bdbe32006-10-12 01:52:05 -0700663 struct rb_node *p = rb_first(&q->wait_pq[level]);
664
Stephen Hemminger87990462006-08-10 23:35:16 -0700665 if (!p)
666 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667
668 cl = rb_entry(p, struct htb_class, pq_node);
Patrick McHardyfb983d42007-03-16 01:22:39 -0700669 if (cl->pq_key > q->now)
670 return cl->pq_key;
671
Stephen Hemminger3696f622006-08-10 23:36:01 -0700672 htb_safe_rb_erase(p, q->wait_pq + level);
Patrick McHardy03cc45c2007-03-23 11:29:11 -0700673 diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
Stephen Hemminger87990462006-08-10 23:35:16 -0700674 htb_change_class_mode(q, cl, &diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 if (cl->cmode != HTB_CAN_SEND)
Stephen Hemminger87990462006-08-10 23:35:16 -0700676 htb_add_to_wait_tree(q, cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 }
Martin Devera8f3ea332008-03-23 22:00:38 -0700678 /* too much load - let's continue on next jiffie */
679 return q->now + PSCHED_TICKS_PER_SEC / HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680}
681
682/* Returns class->node+prio from id-tree where classe's id is >= id. NULL
683 is no such one exists. */
Stephen Hemminger87990462006-08-10 23:35:16 -0700684static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n,
685 u32 id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686{
687 struct rb_node *r = NULL;
688 while (n) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700689 struct htb_class *cl =
690 rb_entry(n, struct htb_class, node[prio]);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700691 if (id == cl->common.classid)
Stephen Hemminger87990462006-08-10 23:35:16 -0700692 return n;
693
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700694 if (id > cl->common.classid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 n = n->rb_right;
696 } else {
697 r = n;
698 n = n->rb_left;
699 }
700 }
701 return r;
702}
703
704/**
705 * htb_lookup_leaf - returns next leaf class in DRR order
706 *
707 * Find leaf where current feed pointers points to.
708 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700709static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
710 struct rb_node **pptr, u32 * pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711{
712 int i;
713 struct {
714 struct rb_node *root;
715 struct rb_node **pptr;
716 u32 *pid;
Stephen Hemminger87990462006-08-10 23:35:16 -0700717 } stk[TC_HTB_MAXDEPTH], *sp = stk;
718
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700719 WARN_ON(!tree->rb_node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 sp->root = tree->rb_node;
721 sp->pptr = pptr;
722 sp->pid = pid;
723
724 for (i = 0; i < 65535; i++) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700725 if (!*sp->pptr && *sp->pid) {
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900726 /* ptr was invalidated but id is valid - try to recover
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 the original or next ptr */
Stephen Hemminger87990462006-08-10 23:35:16 -0700728 *sp->pptr =
729 htb_id_find_next_upper(prio, sp->root, *sp->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700731 *sp->pid = 0; /* ptr is valid now so that remove this hint as it
732 can become out of date quickly */
733 if (!*sp->pptr) { /* we are at right end; rewind & go up */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 *sp->pptr = sp->root;
Stephen Hemminger87990462006-08-10 23:35:16 -0700735 while ((*sp->pptr)->rb_left)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 *sp->pptr = (*sp->pptr)->rb_left;
737 if (sp > stk) {
738 sp--;
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700739 WARN_ON(!*sp->pptr);
Stephen Hemminger87990462006-08-10 23:35:16 -0700740 if (!*sp->pptr)
741 return NULL;
742 htb_next_rb_node(sp->pptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 }
744 } else {
745 struct htb_class *cl;
Stephen Hemminger87990462006-08-10 23:35:16 -0700746 cl = rb_entry(*sp->pptr, struct htb_class, node[prio]);
747 if (!cl->level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 return cl;
749 (++sp)->root = cl->un.inner.feed[prio].rb_node;
Stephen Hemminger87990462006-08-10 23:35:16 -0700750 sp->pptr = cl->un.inner.ptr + prio;
751 sp->pid = cl->un.inner.last_ptr_id + prio;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 }
753 }
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700754 WARN_ON(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 return NULL;
756}
757
758/* dequeues packet at given priority and level; call only if
759 you are sure that there is active class at prio/level */
Stephen Hemminger87990462006-08-10 23:35:16 -0700760static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio,
761 int level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762{
763 struct sk_buff *skb = NULL;
Stephen Hemminger87990462006-08-10 23:35:16 -0700764 struct htb_class *cl, *start;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 /* look initial class up in the row */
Stephen Hemminger87990462006-08-10 23:35:16 -0700766 start = cl = htb_lookup_leaf(q->row[level] + prio, prio,
767 q->ptr[level] + prio,
768 q->last_ptr_id[level] + prio);
769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 do {
771next:
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700772 WARN_ON(!cl);
Stephen Hemminger87990462006-08-10 23:35:16 -0700773 if (!cl)
774 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
776 /* class can be empty - it is unlikely but can be true if leaf
777 qdisc drops packets in enqueue routine or if someone used
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900778 graft operation on the leaf since last dequeue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 simply deactivate and skip such class */
780 if (unlikely(cl->un.leaf.q->q.qlen == 0)) {
781 struct htb_class *next;
Stephen Hemminger87990462006-08-10 23:35:16 -0700782 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783
784 /* row/level might become empty */
785 if ((q->row_mask[level] & (1 << prio)) == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -0700786 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787
Stephen Hemminger87990462006-08-10 23:35:16 -0700788 next = htb_lookup_leaf(q->row[level] + prio,
789 prio, q->ptr[level] + prio,
790 q->last_ptr_id[level] + prio);
791
792 if (cl == start) /* fix start if we just deleted it */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 start = next;
794 cl = next;
795 goto next;
796 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700797
798 skb = cl->un.leaf.q->dequeue(cl->un.leaf.q);
799 if (likely(skb != NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 break;
801 if (!cl->warned) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700802 printk(KERN_WARNING
803 "htb: class %X isn't work conserving ?!\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700804 cl->common.classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 cl->warned = 1;
806 }
Jarek Poplawski633fe662008-12-03 21:09:10 -0800807
Stephen Hemminger87990462006-08-10 23:35:16 -0700808 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
809 ptr[0]) + prio);
810 cl = htb_lookup_leaf(q->row[level] + prio, prio,
811 q->ptr[level] + prio,
812 q->last_ptr_id[level] + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
814 } while (cl != start);
815
816 if (likely(skb != NULL)) {
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700817 cl->un.leaf.deficit[level] -= qdisc_pkt_len(skb);
818 if (cl->un.leaf.deficit[level] < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 cl->un.leaf.deficit[level] += cl->un.leaf.quantum;
Stephen Hemminger87990462006-08-10 23:35:16 -0700820 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
821 ptr[0]) + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 }
823 /* this used to be after charge_class but this constelation
824 gives us slightly better performance */
825 if (!cl->un.leaf.q->q.qlen)
Stephen Hemminger87990462006-08-10 23:35:16 -0700826 htb_deactivate(q, cl);
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700827 htb_charge_class(q, cl, level, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 }
829 return skb;
830}
831
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832static struct sk_buff *htb_dequeue(struct Qdisc *sch)
833{
834 struct sk_buff *skb = NULL;
835 struct htb_sched *q = qdisc_priv(sch);
836 int level;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700837 psched_time_t next_event;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838
839 /* try to dequeue direct packets as high prio (!) to minimize cpu work */
Stephen Hemminger87990462006-08-10 23:35:16 -0700840 skb = __skb_dequeue(&q->direct_queue);
841 if (skb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 sch->flags &= ~TCQ_F_THROTTLED;
843 sch->q.qlen--;
844 return skb;
845 }
846
Stephen Hemminger87990462006-08-10 23:35:16 -0700847 if (!sch->q.qlen)
848 goto fin;
Patrick McHardy3bebcda2007-03-23 11:29:25 -0700849 q->now = psched_get_time();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850
Patrick McHardyfb983d42007-03-16 01:22:39 -0700851 next_event = q->now + 5 * PSCHED_TICKS_PER_SEC;
Jarek Poplawski633fe662008-12-03 21:09:10 -0800852
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
854 /* common case optimization - skip event handler quickly */
855 int m;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700856 psched_time_t event;
Stephen Hemminger87990462006-08-10 23:35:16 -0700857
Patrick McHardyfb983d42007-03-16 01:22:39 -0700858 if (q->now >= q->near_ev_cache[level]) {
859 event = htb_do_events(q, level);
Patrick McHardy2e4b3b02007-05-23 23:39:54 -0700860 if (!event)
861 event = q->now + PSCHED_TICKS_PER_SEC;
862 q->near_ev_cache[level] = event;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700863 } else
864 event = q->near_ev_cache[level];
865
866 if (event && next_event > event)
867 next_event = event;
868
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 m = ~q->row_mask[level];
870 while (m != (int)(-1)) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700871 int prio = ffz(m);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 m |= 1 << prio;
Stephen Hemminger87990462006-08-10 23:35:16 -0700873 skb = htb_dequeue_tree(q, prio, level);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 if (likely(skb != NULL)) {
875 sch->q.qlen--;
876 sch->flags &= ~TCQ_F_THROTTLED;
877 goto fin;
878 }
879 }
880 }
Patrick McHardyfb983d42007-03-16 01:22:39 -0700881 sch->qstats.overlimits++;
882 qdisc_watchdog_schedule(&q->watchdog, next_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883fin:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 return skb;
885}
886
887/* try to drop from each class (by prio) until one succeed */
Stephen Hemminger87990462006-08-10 23:35:16 -0700888static unsigned int htb_drop(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889{
890 struct htb_sched *q = qdisc_priv(sch);
891 int prio;
892
893 for (prio = TC_HTB_NUMPRIO - 1; prio >= 0; prio--) {
894 struct list_head *p;
Stephen Hemminger87990462006-08-10 23:35:16 -0700895 list_for_each(p, q->drops + prio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 struct htb_class *cl = list_entry(p, struct htb_class,
897 un.leaf.drop_list);
898 unsigned int len;
Stephen Hemminger87990462006-08-10 23:35:16 -0700899 if (cl->un.leaf.q->ops->drop &&
900 (len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 sch->q.qlen--;
902 if (!cl->un.leaf.q->q.qlen)
Stephen Hemminger87990462006-08-10 23:35:16 -0700903 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 return len;
905 }
906 }
907 }
908 return 0;
909}
910
911/* reset all classes */
912/* always caled under BH & queue lock */
Stephen Hemminger87990462006-08-10 23:35:16 -0700913static void htb_reset(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914{
915 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700916 struct htb_class *cl;
917 struct hlist_node *n;
918 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700920 for (i = 0; i < q->clhash.hashsize; i++) {
921 hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 if (cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700923 memset(&cl->un.inner, 0, sizeof(cl->un.inner));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 else {
Stephen Hemminger87990462006-08-10 23:35:16 -0700925 if (cl->un.leaf.q)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 qdisc_reset(cl->un.leaf.q);
927 INIT_LIST_HEAD(&cl->un.leaf.drop_list);
928 }
929 cl->prio_activity = 0;
930 cl->cmode = HTB_CAN_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931
932 }
933 }
Patrick McHardyfb983d42007-03-16 01:22:39 -0700934 qdisc_watchdog_cancel(&q->watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 __skb_queue_purge(&q->direct_queue);
936 sch->q.qlen = 0;
Stephen Hemminger87990462006-08-10 23:35:16 -0700937 memset(q->row, 0, sizeof(q->row));
938 memset(q->row_mask, 0, sizeof(q->row_mask));
939 memset(q->wait_pq, 0, sizeof(q->wait_pq));
940 memset(q->ptr, 0, sizeof(q->ptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 for (i = 0; i < TC_HTB_NUMPRIO; i++)
Stephen Hemminger87990462006-08-10 23:35:16 -0700942 INIT_LIST_HEAD(q->drops + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943}
944
Patrick McHardy27a34212008-01-23 20:35:39 -0800945static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
946 [TCA_HTB_PARMS] = { .len = sizeof(struct tc_htb_opt) },
947 [TCA_HTB_INIT] = { .len = sizeof(struct tc_htb_glob) },
948 [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
949 [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
950};
951
Patrick McHardy1e904742008-01-22 22:11:17 -0800952static int htb_init(struct Qdisc *sch, struct nlattr *opt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953{
954 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardy1e904742008-01-22 22:11:17 -0800955 struct nlattr *tb[TCA_HTB_INIT + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 struct tc_htb_glob *gopt;
Patrick McHardycee63722008-01-23 20:33:32 -0800957 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 int i;
Patrick McHardycee63722008-01-23 20:33:32 -0800959
960 if (!opt)
961 return -EINVAL;
962
Patrick McHardy27a34212008-01-23 20:35:39 -0800963 err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy);
Patrick McHardycee63722008-01-23 20:33:32 -0800964 if (err < 0)
965 return err;
966
Patrick McHardy27a34212008-01-23 20:35:39 -0800967 if (tb[TCA_HTB_INIT] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
969 return -EINVAL;
970 }
Patrick McHardy1e904742008-01-22 22:11:17 -0800971 gopt = nla_data(tb[TCA_HTB_INIT]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 if (gopt->version != HTB_VER >> 16) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700973 printk(KERN_ERR
974 "HTB: need tc/htb version %d (minor is %d), you have %d\n",
975 HTB_VER >> 16, HTB_VER & 0xffff, gopt->version);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 return -EINVAL;
977 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700979 err = qdisc_class_hash_init(&q->clhash);
980 if (err < 0)
981 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 for (i = 0; i < TC_HTB_NUMPRIO; i++)
Stephen Hemminger87990462006-08-10 23:35:16 -0700983 INIT_LIST_HEAD(q->drops + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984
Patrick McHardyfb983d42007-03-16 01:22:39 -0700985 qdisc_watchdog_init(&q->watchdog, sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 skb_queue_head_init(&q->direct_queue);
987
David S. Miller5ce2d482008-07-08 17:06:30 -0700988 q->direct_qlen = qdisc_dev(sch)->tx_queue_len;
Stephen Hemminger87990462006-08-10 23:35:16 -0700989 if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 q->direct_qlen = 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 if ((q->rate2quantum = gopt->rate2quantum) < 1)
993 q->rate2quantum = 1;
994 q->defcls = gopt->defcls;
995
996 return 0;
997}
998
999static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
1000{
Jarek Poplawski102396a2008-08-29 14:21:52 -07001001 spinlock_t *root_lock = qdisc_root_sleeping_lock(sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001003 struct nlattr *nest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 struct tc_htb_glob gopt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
David S. Miller7698b4f2008-07-16 01:42:40 -07001006 spin_lock_bh(root_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001007
1008 gopt.direct_pkts = q->direct_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 gopt.version = HTB_VER;
1010 gopt.rate2quantum = q->rate2quantum;
1011 gopt.defcls = q->defcls;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001012 gopt.debug = 0;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001013
1014 nest = nla_nest_start(skb, TCA_OPTIONS);
1015 if (nest == NULL)
1016 goto nla_put_failure;
Patrick McHardy1e904742008-01-22 22:11:17 -08001017 NLA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001018 nla_nest_end(skb, nest);
1019
David S. Miller7698b4f2008-07-16 01:42:40 -07001020 spin_unlock_bh(root_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 return skb->len;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001022
Patrick McHardy1e904742008-01-22 22:11:17 -08001023nla_put_failure:
David S. Miller7698b4f2008-07-16 01:42:40 -07001024 spin_unlock_bh(root_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001025 nla_nest_cancel(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 return -1;
1027}
1028
1029static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
Stephen Hemminger87990462006-08-10 23:35:16 -07001030 struct sk_buff *skb, struct tcmsg *tcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031{
Stephen Hemminger87990462006-08-10 23:35:16 -07001032 struct htb_class *cl = (struct htb_class *)arg;
Jarek Poplawski102396a2008-08-29 14:21:52 -07001033 spinlock_t *root_lock = qdisc_root_sleeping_lock(sch);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001034 struct nlattr *nest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 struct tc_htb_opt opt;
1036
David S. Miller7698b4f2008-07-16 01:42:40 -07001037 spin_lock_bh(root_lock);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001038 tcm->tcm_parent = cl->parent ? cl->parent->common.classid : TC_H_ROOT;
1039 tcm->tcm_handle = cl->common.classid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 if (!cl->level && cl->un.leaf.q)
1041 tcm->tcm_info = cl->un.leaf.q->handle;
1042
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001043 nest = nla_nest_start(skb, TCA_OPTIONS);
1044 if (nest == NULL)
1045 goto nla_put_failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
Stephen Hemminger87990462006-08-10 23:35:16 -07001047 memset(&opt, 0, sizeof(opt));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
Stephen Hemminger87990462006-08-10 23:35:16 -07001049 opt.rate = cl->rate->rate;
1050 opt.buffer = cl->buffer;
1051 opt.ceil = cl->ceil->rate;
1052 opt.cbuffer = cl->cbuffer;
1053 opt.quantum = cl->un.leaf.quantum;
1054 opt.prio = cl->un.leaf.prio;
1055 opt.level = cl->level;
Patrick McHardy1e904742008-01-22 22:11:17 -08001056 NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001057
1058 nla_nest_end(skb, nest);
David S. Miller7698b4f2008-07-16 01:42:40 -07001059 spin_unlock_bh(root_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 return skb->len;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001061
Patrick McHardy1e904742008-01-22 22:11:17 -08001062nla_put_failure:
David S. Miller7698b4f2008-07-16 01:42:40 -07001063 spin_unlock_bh(root_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001064 nla_nest_cancel(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 return -1;
1066}
1067
1068static int
Stephen Hemminger87990462006-08-10 23:35:16 -07001069htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070{
Stephen Hemminger87990462006-08-10 23:35:16 -07001071 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 if (!cl->level && cl->un.leaf.q)
1074 cl->qstats.qlen = cl->un.leaf.q->q.qlen;
1075 cl->xstats.tokens = cl->tokens;
1076 cl->xstats.ctokens = cl->ctokens;
1077
1078 if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
1079 gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
1080 gnet_stats_copy_queue(d, &cl->qstats) < 0)
1081 return -1;
1082
1083 return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
1084}
1085
1086static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
Stephen Hemminger87990462006-08-10 23:35:16 -07001087 struct Qdisc **old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088{
Stephen Hemminger87990462006-08-10 23:35:16 -07001089 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090
1091 if (cl && !cl->level) {
Patrick McHardy9f9afec2006-11-29 17:35:18 -08001092 if (new == NULL &&
David S. Miller5ce2d482008-07-08 17:06:30 -07001093 (new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
David S. Millerbb949fb2008-07-08 16:55:56 -07001094 &pfifo_qdisc_ops,
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001095 cl->common.classid))
Stephen Hemminger87990462006-08-10 23:35:16 -07001096 == NULL)
1097 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 sch_tree_lock(sch);
Patrick McHardyb94c8af2008-11-20 04:11:36 -08001099 *old = cl->un.leaf.q;
1100 cl->un.leaf.q = new;
1101 if (*old != NULL) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001102 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 qdisc_reset(*old);
1104 }
1105 sch_tree_unlock(sch);
1106 return 0;
1107 }
1108 return -ENOENT;
1109}
1110
Stephen Hemminger87990462006-08-10 23:35:16 -07001111static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112{
Stephen Hemminger87990462006-08-10 23:35:16 -07001113 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 return (cl && !cl->level) ? cl->un.leaf.q : NULL;
1115}
1116
Patrick McHardy256d61b2006-11-29 17:37:05 -08001117static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg)
1118{
1119 struct htb_class *cl = (struct htb_class *)arg;
1120
1121 if (cl->un.leaf.q->q.qlen == 0)
1122 htb_deactivate(qdisc_priv(sch), cl);
1123}
1124
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125static unsigned long htb_get(struct Qdisc *sch, u32 classid)
1126{
Stephen Hemminger87990462006-08-10 23:35:16 -07001127 struct htb_class *cl = htb_find(classid, sch);
1128 if (cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 cl->refcnt++;
1130 return (unsigned long)cl;
1131}
1132
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001133static inline int htb_parent_last_child(struct htb_class *cl)
1134{
1135 if (!cl->parent)
1136 /* the root class */
1137 return 0;
Patrick McHardy42077592008-07-05 23:22:53 -07001138 if (cl->parent->children > 1)
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001139 /* not the last child */
1140 return 0;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001141 return 1;
1142}
1143
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001144static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
1145 struct Qdisc *new_q)
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001146{
1147 struct htb_class *parent = cl->parent;
1148
Ilpo Järvinen547b7922008-07-25 21:43:18 -07001149 WARN_ON(cl->level || !cl->un.leaf.q || cl->prio_activity);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001150
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001151 if (parent->cmode != HTB_CAN_SEND)
1152 htb_safe_rb_erase(&parent->pq_node, q->wait_pq + parent->level);
1153
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001154 parent->level = 0;
1155 memset(&parent->un.inner, 0, sizeof(parent->un.inner));
1156 INIT_LIST_HEAD(&parent->un.leaf.drop_list);
1157 parent->un.leaf.q = new_q ? new_q : &noop_qdisc;
1158 parent->un.leaf.quantum = parent->quantum;
1159 parent->un.leaf.prio = parent->prio;
1160 parent->tokens = parent->buffer;
1161 parent->ctokens = parent->cbuffer;
Patrick McHardy3bebcda2007-03-23 11:29:25 -07001162 parent->t_c = psched_get_time();
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001163 parent->cmode = HTB_CAN_SEND;
1164}
1165
Stephen Hemminger87990462006-08-10 23:35:16 -07001166static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 if (!cl->level) {
Ilpo Järvinen547b7922008-07-25 21:43:18 -07001169 WARN_ON(!cl->un.leaf.q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 qdisc_destroy(cl->un.leaf.q);
1171 }
Patrick McHardyee39e102007-07-02 22:48:13 -07001172 gen_kill_estimator(&cl->bstats, &cl->rate_est);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 qdisc_put_rtab(cl->rate);
1174 qdisc_put_rtab(cl->ceil);
Stephen Hemminger87990462006-08-10 23:35:16 -07001175
Patrick McHardyff31ab52008-07-01 19:52:38 -07001176 tcf_destroy_chain(&cl->filter_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 kfree(cl);
1178}
1179
1180/* always caled under BH & queue lock */
Stephen Hemminger87990462006-08-10 23:35:16 -07001181static void htb_destroy(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182{
1183 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001184 struct hlist_node *n, *next;
1185 struct htb_class *cl;
1186 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187
Patrick McHardyfb983d42007-03-16 01:22:39 -07001188 qdisc_watchdog_cancel(&q->watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 /* This line used to be after htb_destroy_class call below
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +09001190 and surprisingly it worked in 2.4. But it must precede it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 because filter need its target class alive to be able to call
1192 unbind_filter on it (without Oops). */
Patrick McHardyff31ab52008-07-01 19:52:38 -07001193 tcf_destroy_chain(&q->filter_list);
Stephen Hemminger87990462006-08-10 23:35:16 -07001194
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001195 for (i = 0; i < q->clhash.hashsize; i++) {
1196 hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode)
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001197 tcf_destroy_chain(&cl->filter_list);
1198 }
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001199 for (i = 0; i < q->clhash.hashsize; i++) {
1200 hlist_for_each_entry_safe(cl, n, next, &q->clhash.hash[i],
1201 common.hnode)
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001202 htb_destroy_class(sch, cl);
1203 }
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001204 qdisc_class_hash_destroy(&q->clhash);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 __skb_queue_purge(&q->direct_queue);
1206}
1207
1208static int htb_delete(struct Qdisc *sch, unsigned long arg)
1209{
1210 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001211 struct htb_class *cl = (struct htb_class *)arg;
Patrick McHardy256d61b2006-11-29 17:37:05 -08001212 unsigned int qlen;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001213 struct Qdisc *new_q = NULL;
1214 int last_child = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
1216 // TODO: why don't allow to delete subtree ? references ? does
1217 // tc subsys quarantee us that in htb_destroy it holds no class
1218 // refs so that we can remove children safely there ?
Patrick McHardy42077592008-07-05 23:22:53 -07001219 if (cl->children || cl->filter_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 return -EBUSY;
Stephen Hemminger87990462006-08-10 23:35:16 -07001221
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001222 if (!cl->level && htb_parent_last_child(cl)) {
David S. Miller5ce2d482008-07-08 17:06:30 -07001223 new_q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
David S. Millerbb949fb2008-07-08 16:55:56 -07001224 &pfifo_qdisc_ops,
1225 cl->parent->common.classid);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001226 last_child = 1;
1227 }
1228
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 sch_tree_lock(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001230
Patrick McHardy814a175e2006-11-29 17:34:50 -08001231 if (!cl->level) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001232 qlen = cl->un.leaf.q->q.qlen;
Patrick McHardy814a175e2006-11-29 17:34:50 -08001233 qdisc_reset(cl->un.leaf.q);
Patrick McHardy256d61b2006-11-29 17:37:05 -08001234 qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen);
Patrick McHardy814a175e2006-11-29 17:34:50 -08001235 }
1236
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001237 /* delete from hash and active; remainder in destroy_class */
1238 qdisc_class_hash_remove(&q->clhash, &cl->common);
Jarek Poplawski26b284d2008-08-13 15:16:43 -07001239 if (cl->parent)
1240 cl->parent->children--;
Patrick McHardyc38c83c2007-03-27 14:04:24 -07001241
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 if (cl->prio_activity)
Stephen Hemminger87990462006-08-10 23:35:16 -07001243 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001245 if (cl->cmode != HTB_CAN_SEND)
1246 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
1247
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001248 if (last_child)
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001249 htb_parent_to_leaf(q, cl, new_q);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001250
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 if (--cl->refcnt == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -07001252 htb_destroy_class(sch, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
1254 sch_tree_unlock(sch);
1255 return 0;
1256}
1257
1258static void htb_put(struct Qdisc *sch, unsigned long arg)
1259{
Stephen Hemminger87990462006-08-10 23:35:16 -07001260 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
1262 if (--cl->refcnt == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -07001263 htb_destroy_class(sch, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264}
1265
Stephen Hemminger87990462006-08-10 23:35:16 -07001266static int htb_change_class(struct Qdisc *sch, u32 classid,
Patrick McHardy1e904742008-01-22 22:11:17 -08001267 u32 parentid, struct nlattr **tca,
Stephen Hemminger87990462006-08-10 23:35:16 -07001268 unsigned long *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269{
1270 int err = -EINVAL;
1271 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001272 struct htb_class *cl = (struct htb_class *)*arg, *parent;
Patrick McHardy1e904742008-01-22 22:11:17 -08001273 struct nlattr *opt = tca[TCA_OPTIONS];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
Patrick McHardy1e904742008-01-22 22:11:17 -08001275 struct nlattr *tb[TCA_HTB_RTAB + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 struct tc_htb_opt *hopt;
1277
1278 /* extract all subattrs from opt attr */
Patrick McHardycee63722008-01-23 20:33:32 -08001279 if (!opt)
1280 goto failure;
1281
Patrick McHardy27a34212008-01-23 20:35:39 -08001282 err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, htb_policy);
Patrick McHardycee63722008-01-23 20:33:32 -08001283 if (err < 0)
1284 goto failure;
1285
1286 err = -EINVAL;
Patrick McHardy27a34212008-01-23 20:35:39 -08001287 if (tb[TCA_HTB_PARMS] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 goto failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
Stephen Hemminger87990462006-08-10 23:35:16 -07001290 parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001291
Patrick McHardy1e904742008-01-22 22:11:17 -08001292 hopt = nla_data(tb[TCA_HTB_PARMS]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
Patrick McHardy1e904742008-01-22 22:11:17 -08001294 rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]);
1295 ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]);
Stephen Hemminger87990462006-08-10 23:35:16 -07001296 if (!rtab || !ctab)
1297 goto failure;
1298
1299 if (!cl) { /* new class */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 struct Qdisc *new_q;
Stephen Hemminger3696f622006-08-10 23:36:01 -07001301 int prio;
Patrick McHardyee39e102007-07-02 22:48:13 -07001302 struct {
Patrick McHardy1e904742008-01-22 22:11:17 -08001303 struct nlattr nla;
Patrick McHardyee39e102007-07-02 22:48:13 -07001304 struct gnet_estimator opt;
1305 } est = {
Patrick McHardy1e904742008-01-22 22:11:17 -08001306 .nla = {
1307 .nla_len = nla_attr_size(sizeof(est.opt)),
1308 .nla_type = TCA_RATE,
Patrick McHardyee39e102007-07-02 22:48:13 -07001309 },
1310 .opt = {
1311 /* 4s interval, 16s averaging constant */
1312 .interval = 2,
1313 .ewma_log = 2,
1314 },
1315 };
Stephen Hemminger3696f622006-08-10 23:36:01 -07001316
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 /* check for valid classid */
Stephen Hemminger87990462006-08-10 23:35:16 -07001318 if (!classid || TC_H_MAJ(classid ^ sch->handle)
1319 || htb_find(classid, sch))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 goto failure;
1321
1322 /* check maximal depth */
1323 if (parent && parent->parent && parent->parent->level < 2) {
1324 printk(KERN_ERR "htb: tree is too deep\n");
1325 goto failure;
1326 }
1327 err = -ENOBUFS;
Panagiotis Issaris0da974f2006-07-21 14:51:30 -07001328 if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 goto failure;
Stephen Hemminger87990462006-08-10 23:35:16 -07001330
Stephen Hemminger71bcb092008-11-25 21:13:31 -08001331 err = gen_new_estimator(&cl->bstats, &cl->rate_est,
1332 qdisc_root_sleeping_lock(sch),
1333 tca[TCA_RATE] ? : &est.nla);
1334 if (err) {
1335 kfree(cl);
1336 goto failure;
1337 }
1338
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 cl->refcnt = 1;
Patrick McHardy42077592008-07-05 23:22:53 -07001340 cl->children = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 INIT_LIST_HEAD(&cl->un.leaf.drop_list);
Stephen Hemminger3696f622006-08-10 23:36:01 -07001342 RB_CLEAR_NODE(&cl->pq_node);
1343
1344 for (prio = 0; prio < TC_HTB_NUMPRIO; prio++)
1345 RB_CLEAR_NODE(&cl->node[prio]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346
1347 /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
1348 so that can't be used inside of sch_tree_lock
1349 -- thanks to Karlis Peisenieks */
David S. Miller5ce2d482008-07-08 17:06:30 -07001350 new_q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
David S. Millerbb949fb2008-07-08 16:55:56 -07001351 &pfifo_qdisc_ops, classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 sch_tree_lock(sch);
1353 if (parent && !parent->level) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001354 unsigned int qlen = parent->un.leaf.q->q.qlen;
1355
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 /* turn parent into inner node */
Patrick McHardy256d61b2006-11-29 17:37:05 -08001357 qdisc_reset(parent->un.leaf.q);
1358 qdisc_tree_decrease_qlen(parent->un.leaf.q, qlen);
Stephen Hemminger87990462006-08-10 23:35:16 -07001359 qdisc_destroy(parent->un.leaf.q);
1360 if (parent->prio_activity)
1361 htb_deactivate(q, parent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
1363 /* remove from evt list because of level change */
1364 if (parent->cmode != HTB_CAN_SEND) {
Stephen Hemminger3696f622006-08-10 23:36:01 -07001365 htb_safe_rb_erase(&parent->pq_node, q->wait_pq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 parent->cmode = HTB_CAN_SEND;
1367 }
1368 parent->level = (parent->parent ? parent->parent->level
Stephen Hemminger87990462006-08-10 23:35:16 -07001369 : TC_HTB_MAXDEPTH) - 1;
1370 memset(&parent->un.inner, 0, sizeof(parent->un.inner));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 }
1372 /* leaf (we) needs elementary qdisc */
1373 cl->un.leaf.q = new_q ? new_q : &noop_qdisc;
1374
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001375 cl->common.classid = classid;
Stephen Hemminger87990462006-08-10 23:35:16 -07001376 cl->parent = parent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
1378 /* set class to be in HTB_CAN_SEND state */
1379 cl->tokens = hopt->buffer;
1380 cl->ctokens = hopt->cbuffer;
Patrick McHardy00c04af2007-03-16 01:23:02 -07001381 cl->mbuffer = 60 * PSCHED_TICKS_PER_SEC; /* 1min */
Patrick McHardy3bebcda2007-03-23 11:29:25 -07001382 cl->t_c = psched_get_time();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 cl->cmode = HTB_CAN_SEND;
1384
1385 /* attach to the hash list and parent's family */
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001386 qdisc_class_hash_insert(&q->clhash, &cl->common);
Patrick McHardy42077592008-07-05 23:22:53 -07001387 if (parent)
1388 parent->children++;
Patrick McHardyee39e102007-07-02 22:48:13 -07001389 } else {
Stephen Hemminger71bcb092008-11-25 21:13:31 -08001390 if (tca[TCA_RATE]) {
1391 err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
1392 qdisc_root_sleeping_lock(sch),
1393 tca[TCA_RATE]);
1394 if (err)
1395 return err;
1396 }
Stephen Hemminger87990462006-08-10 23:35:16 -07001397 sch_tree_lock(sch);
Patrick McHardyee39e102007-07-02 22:48:13 -07001398 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399
1400 /* it used to be a nasty bug here, we have to check that node
Stephen Hemminger87990462006-08-10 23:35:16 -07001401 is really leaf before changing cl->un.leaf ! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 if (!cl->level) {
1403 cl->un.leaf.quantum = rtab->rate.rate / q->rate2quantum;
1404 if (!hopt->quantum && cl->un.leaf.quantum < 1000) {
Stephen Hemminger87990462006-08-10 23:35:16 -07001405 printk(KERN_WARNING
1406 "HTB: quantum of class %X is small. Consider r2q change.\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001407 cl->common.classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 cl->un.leaf.quantum = 1000;
1409 }
1410 if (!hopt->quantum && cl->un.leaf.quantum > 200000) {
Stephen Hemminger87990462006-08-10 23:35:16 -07001411 printk(KERN_WARNING
1412 "HTB: quantum of class %X is big. Consider r2q change.\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001413 cl->common.classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 cl->un.leaf.quantum = 200000;
1415 }
1416 if (hopt->quantum)
1417 cl->un.leaf.quantum = hopt->quantum;
1418 if ((cl->un.leaf.prio = hopt->prio) >= TC_HTB_NUMPRIO)
1419 cl->un.leaf.prio = TC_HTB_NUMPRIO - 1;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001420
1421 /* backup for htb_parent_to_leaf */
1422 cl->quantum = cl->un.leaf.quantum;
1423 cl->prio = cl->un.leaf.prio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 }
1425
1426 cl->buffer = hopt->buffer;
1427 cl->cbuffer = hopt->cbuffer;
Stephen Hemminger87990462006-08-10 23:35:16 -07001428 if (cl->rate)
1429 qdisc_put_rtab(cl->rate);
1430 cl->rate = rtab;
1431 if (cl->ceil)
1432 qdisc_put_rtab(cl->ceil);
1433 cl->ceil = ctab;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 sch_tree_unlock(sch);
1435
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001436 qdisc_class_hash_grow(sch, &q->clhash);
1437
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 *arg = (unsigned long)cl;
1439 return 0;
1440
1441failure:
Stephen Hemminger87990462006-08-10 23:35:16 -07001442 if (rtab)
1443 qdisc_put_rtab(rtab);
1444 if (ctab)
1445 qdisc_put_rtab(ctab);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 return err;
1447}
1448
1449static struct tcf_proto **htb_find_tcf(struct Qdisc *sch, unsigned long arg)
1450{
1451 struct htb_sched *q = qdisc_priv(sch);
1452 struct htb_class *cl = (struct htb_class *)arg;
1453 struct tcf_proto **fl = cl ? &cl->filter_list : &q->filter_list;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001454
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 return fl;
1456}
1457
1458static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent,
Stephen Hemminger87990462006-08-10 23:35:16 -07001459 u32 classid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460{
Stephen Hemminger87990462006-08-10 23:35:16 -07001461 struct htb_class *cl = htb_find(classid, sch);
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001462
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 /*if (cl && !cl->level) return 0;
Stephen Hemminger87990462006-08-10 23:35:16 -07001464 The line above used to be there to prevent attaching filters to
1465 leaves. But at least tc_index filter uses this just to get class
1466 for other reasons so that we have to allow for it.
1467 ----
1468 19.6.2002 As Werner explained it is ok - bind filter is just
1469 another way to "lock" the class - unlike "get" this lock can
1470 be broken by class during destroy IIUC.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 */
Stephen Hemminger87990462006-08-10 23:35:16 -07001472 if (cl)
1473 cl->filter_cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 return (unsigned long)cl;
1475}
1476
1477static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg)
1478{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 struct htb_class *cl = (struct htb_class *)arg;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001480
Stephen Hemminger87990462006-08-10 23:35:16 -07001481 if (cl)
1482 cl->filter_cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483}
1484
1485static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg)
1486{
1487 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001488 struct htb_class *cl;
1489 struct hlist_node *n;
1490 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
1492 if (arg->stop)
1493 return;
1494
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001495 for (i = 0; i < q->clhash.hashsize; i++) {
1496 hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 if (arg->count < arg->skip) {
1498 arg->count++;
1499 continue;
1500 }
1501 if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
1502 arg->stop = 1;
1503 return;
1504 }
1505 arg->count++;
1506 }
1507 }
1508}
1509
Eric Dumazet20fea082007-11-14 01:44:41 -08001510static const struct Qdisc_class_ops htb_class_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 .graft = htb_graft,
1512 .leaf = htb_leaf,
Patrick McHardy256d61b2006-11-29 17:37:05 -08001513 .qlen_notify = htb_qlen_notify,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 .get = htb_get,
1515 .put = htb_put,
1516 .change = htb_change_class,
1517 .delete = htb_delete,
1518 .walk = htb_walk,
1519 .tcf_chain = htb_find_tcf,
1520 .bind_tcf = htb_bind_filter,
1521 .unbind_tcf = htb_unbind_filter,
1522 .dump = htb_dump_class,
1523 .dump_stats = htb_dump_class_stats,
1524};
1525
Eric Dumazet20fea082007-11-14 01:44:41 -08001526static struct Qdisc_ops htb_qdisc_ops __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 .next = NULL,
1528 .cl_ops = &htb_class_ops,
1529 .id = "htb",
1530 .priv_size = sizeof(struct htb_sched),
1531 .enqueue = htb_enqueue,
1532 .dequeue = htb_dequeue,
Jarek Poplawski77be1552008-10-31 00:47:01 -07001533 .peek = qdisc_peek_dequeued,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 .drop = htb_drop,
1535 .init = htb_init,
1536 .reset = htb_reset,
1537 .destroy = htb_destroy,
1538 .change = NULL /* htb_change */,
1539 .dump = htb_dump,
1540 .owner = THIS_MODULE,
1541};
1542
1543static int __init htb_module_init(void)
1544{
Stephen Hemminger87990462006-08-10 23:35:16 -07001545 return register_qdisc(&htb_qdisc_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546}
Stephen Hemminger87990462006-08-10 23:35:16 -07001547static void __exit htb_module_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548{
Stephen Hemminger87990462006-08-10 23:35:16 -07001549 unregister_qdisc(&htb_qdisc_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550}
Stephen Hemminger87990462006-08-10 23:35:16 -07001551
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552module_init(htb_module_init)
1553module_exit(htb_module_exit)
1554MODULE_LICENSE("GPL");