blob: d01fe3a1a623bc2b7f7dc2baa48a8bb96fe17571 [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
Stephen Hemminger87990462006-08-10 23:35:16 -070054#define HTB_HSIZE 16 /* classid hash size */
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -070055static int htb_hysteresis __read_mostly = 0; /* whether to use mode hysteresis for speedup */
Stephen Hemminger87990462006-08-10 23:35:16 -070056#define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58#if HTB_VER >> 16 != TC_HTB_PROTOVER
59#error "Mismatched sch_htb.c and pkt_sch.h"
60#endif
61
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -070062/* Module parameter and sysfs export */
63module_param (htb_hysteresis, int, 0640);
64MODULE_PARM_DESC(htb_hysteresis, "Hysteresis mode, less CPU load, less accurate");
65
Linus Torvalds1da177e2005-04-16 15:20:36 -070066/* used internaly to keep status of single class */
67enum htb_cmode {
Stephen Hemminger87990462006-08-10 23:35:16 -070068 HTB_CANT_SEND, /* class can't send and can't borrow */
69 HTB_MAY_BORROW, /* class can't send but may borrow */
70 HTB_CAN_SEND /* class can send */
Linus Torvalds1da177e2005-04-16 15:20:36 -070071};
72
73/* interior & leaf nodes; props specific to leaves are marked L: */
Stephen Hemminger87990462006-08-10 23:35:16 -070074struct htb_class {
75 /* general class parameters */
76 u32 classid;
77 struct gnet_stats_basic bstats;
78 struct gnet_stats_queue qstats;
79 struct gnet_stats_rate_est rate_est;
80 struct tc_htb_xstats xstats; /* our special stats */
81 int refcnt; /* usage count of this class */
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
Stephen Hemminger87990462006-08-10 23:35:16 -070083 /* topology */
84 int level; /* our level (see above) */
85 struct htb_class *parent; /* parent class */
Stephen Hemminger0cef2962006-08-10 23:35:38 -070086 struct hlist_node hlist; /* classid hash list item */
Stephen Hemminger87990462006-08-10 23:35:16 -070087 struct list_head sibling; /* sibling list item */
88 struct list_head children; /* children list */
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
Stephen Hemminger87990462006-08-10 23:35:16 -070090 union {
91 struct htb_class_leaf {
92 struct Qdisc *q;
93 int prio;
94 int aprio;
95 int quantum;
96 int deficit[TC_HTB_MAXDEPTH];
97 struct list_head drop_list;
98 } leaf;
99 struct htb_class_inner {
100 struct rb_root feed[TC_HTB_NUMPRIO]; /* feed trees */
101 struct rb_node *ptr[TC_HTB_NUMPRIO]; /* current class ptr */
102 /* When class changes from state 1->2 and disconnects from
103 parent's feed then we lost ptr value and start from the
104 first child again. Here we store classid of the
105 last valid ptr (used when ptr is NULL). */
106 u32 last_ptr_id[TC_HTB_NUMPRIO];
107 } inner;
108 } un;
109 struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */
110 struct rb_node pq_node; /* node for event queue */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700111 psched_time_t pq_key;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
Stephen Hemminger87990462006-08-10 23:35:16 -0700113 int prio_activity; /* for which prios are we active */
114 enum htb_cmode cmode; /* current mode of the class */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
Stephen Hemminger87990462006-08-10 23:35:16 -0700116 /* class attached filters */
117 struct tcf_proto *filter_list;
118 int filter_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
Stephen Hemminger87990462006-08-10 23:35:16 -0700120 int warned; /* only one warning about non work conserving .. */
121
122 /* token bucket parameters */
123 struct qdisc_rate_table *rate; /* rate table of the class itself */
124 struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */
125 long buffer, cbuffer; /* token bucket depth/rate */
126 psched_tdiff_t mbuffer; /* max wait time */
127 long tokens, ctokens; /* current number of tokens */
128 psched_time_t t_c; /* checkpoint time */
Jarek Poplawski160d5e12006-12-08 00:26:56 -0800129
130 int prio; /* For parent to leaf return possible here */
131 int quantum; /* we do backup. Finally full replacement */
132 /* of un.leaf originals should be done. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133};
134
Stephen Hemminger87990462006-08-10 23:35:16 -0700135static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate,
136 int size)
137{
Jesper Dangaard Brouere9bef552007-09-12 16:35:24 +0200138 long result = qdisc_l2t(rate, size);
139 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140}
141
Stephen Hemminger87990462006-08-10 23:35:16 -0700142struct htb_sched {
143 struct list_head root; /* root classes list */
Stephen Hemminger0cef2962006-08-10 23:35:38 -0700144 struct hlist_head hash[HTB_HSIZE]; /* hashed by classid */
145 struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
Stephen Hemminger87990462006-08-10 23:35:16 -0700147 /* self list - roots of self generating tree */
148 struct rb_root row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
149 int row_mask[TC_HTB_MAXDEPTH];
150 struct rb_node *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
151 u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152
Stephen Hemminger87990462006-08-10 23:35:16 -0700153 /* self wait list - roots of wait PQs per row */
154 struct rb_root wait_pq[TC_HTB_MAXDEPTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
Stephen Hemminger87990462006-08-10 23:35:16 -0700156 /* time of nearest event per level (row) */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700157 psched_time_t near_ev_cache[TC_HTB_MAXDEPTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
Stephen Hemminger87990462006-08-10 23:35:16 -0700159 /* whether we hit non-work conserving class during this dequeue; we use */
160 int nwc_hit; /* this to disable mindelay complaint in dequeue */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
Stephen Hemminger87990462006-08-10 23:35:16 -0700162 int defcls; /* class where unclassified flows go to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163
Stephen Hemminger87990462006-08-10 23:35:16 -0700164 /* filters for qdisc itself */
165 struct tcf_proto *filter_list;
166 int filter_cnt;
167
168 int rate2quantum; /* quant = rate / rate2quantum */
169 psched_time_t now; /* cached dequeue time */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700170 struct qdisc_watchdog watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
Stephen Hemminger87990462006-08-10 23:35:16 -0700172 /* non shaped skbs; let them go directly thru */
173 struct sk_buff_head direct_queue;
174 int direct_qlen; /* max qlen of above */
175
176 long direct_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177};
178
179/* compute hash of size HTB_HSIZE for given handle */
Stephen Hemminger87990462006-08-10 23:35:16 -0700180static inline int htb_hash(u32 h)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181{
182#if HTB_HSIZE != 16
Stephen Hemminger87990462006-08-10 23:35:16 -0700183#error "Declare new hash for your HTB_HSIZE"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184#endif
Stephen Hemminger87990462006-08-10 23:35:16 -0700185 h ^= h >> 8; /* stolen from cbq_hash */
186 h ^= h >> 4;
187 return h & 0xf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188}
189
190/* find class in global hash table using given handle */
Stephen Hemminger87990462006-08-10 23:35:16 -0700191static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192{
193 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger0cef2962006-08-10 23:35:38 -0700194 struct hlist_node *p;
195 struct htb_class *cl;
196
Stephen Hemminger87990462006-08-10 23:35:16 -0700197 if (TC_H_MAJ(handle) != sch->handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 return NULL;
Stephen Hemminger87990462006-08-10 23:35:16 -0700199
Stephen Hemminger0cef2962006-08-10 23:35:38 -0700200 hlist_for_each_entry(cl, p, q->hash + htb_hash(handle), hlist) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 if (cl->classid == handle)
202 return cl;
203 }
204 return NULL;
205}
206
207/**
208 * htb_classify - classify a packet into class
209 *
210 * It returns NULL if the packet should be dropped or -1 if the packet
211 * should be passed directly thru. In all other cases leaf class is returned.
212 * We allow direct class selection by classid in priority. The we examine
213 * filters in qdisc and in inner nodes (if higher filter points to the inner
214 * node). If we end up with classid MAJOR:0 we enqueue the skb into special
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900215 * internal fifo (direct). These packets then go directly thru. If we still
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessfull
217 * then finish and return direct queue.
218 */
219#define HTB_DIRECT (struct htb_class*)-1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
Stephen Hemminger87990462006-08-10 23:35:16 -0700221static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
222 int *qerr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223{
224 struct htb_sched *q = qdisc_priv(sch);
225 struct htb_class *cl;
226 struct tcf_result res;
227 struct tcf_proto *tcf;
228 int result;
229
230 /* allow to select class by setting skb->priority to valid classid;
231 note that nfmark can be used too by attaching filter fw with no
232 rules in it */
233 if (skb->priority == sch->handle)
Stephen Hemminger87990462006-08-10 23:35:16 -0700234 return HTB_DIRECT; /* X:0 (direct flow) selected */
235 if ((cl = htb_find(skb->priority, sch)) != NULL && cl->level == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 return cl;
237
Jamal Hadi Salim29f1df62006-01-08 22:35:55 -0800238 *qerr = NET_XMIT_BYPASS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 tcf = q->filter_list;
240 while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
241#ifdef CONFIG_NET_CLS_ACT
242 switch (result) {
243 case TC_ACT_QUEUED:
Stephen Hemminger87990462006-08-10 23:35:16 -0700244 case TC_ACT_STOLEN:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 *qerr = NET_XMIT_SUCCESS;
246 case TC_ACT_SHOT:
247 return NULL;
248 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249#endif
Stephen Hemminger87990462006-08-10 23:35:16 -0700250 if ((cl = (void *)res.class) == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 if (res.classid == sch->handle)
Stephen Hemminger87990462006-08-10 23:35:16 -0700252 return HTB_DIRECT; /* X:0 (direct flow) */
253 if ((cl = htb_find(res.classid, sch)) == NULL)
254 break; /* filter selected invalid classid */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 }
256 if (!cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700257 return cl; /* we hit leaf; return it */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
259 /* we have got inner class; apply inner filter chain */
260 tcf = cl->filter_list;
261 }
262 /* classification failed; try to use default class */
Stephen Hemminger87990462006-08-10 23:35:16 -0700263 cl = htb_find(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 if (!cl || cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700265 return HTB_DIRECT; /* bad default .. this is safe bet */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 return cl;
267}
268
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269/**
270 * htb_add_to_id_tree - adds class to the round robin list
271 *
272 * Routine adds class to the list (actually tree) sorted by classid.
273 * Make sure that class is not already on such list for given prio.
274 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700275static void htb_add_to_id_tree(struct rb_root *root,
276 struct htb_class *cl, int prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277{
278 struct rb_node **p = &root->rb_node, *parent = NULL;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700279
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 while (*p) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700281 struct htb_class *c;
282 parent = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 c = rb_entry(parent, struct htb_class, node[prio]);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 if (cl->classid > c->classid)
286 p = &parent->rb_right;
Stephen Hemminger87990462006-08-10 23:35:16 -0700287 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 p = &parent->rb_left;
289 }
290 rb_link_node(&cl->node[prio], parent, p);
291 rb_insert_color(&cl->node[prio], root);
292}
293
294/**
295 * htb_add_to_wait_tree - adds class to the event queue with delay
296 *
297 * The class is added to priority event queue to indicate that class will
298 * change its mode in cl->pq_key microseconds. Make sure that class is not
299 * already in the queue.
300 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700301static void htb_add_to_wait_tree(struct htb_sched *q,
302 struct htb_class *cl, long delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303{
304 struct rb_node **p = &q->wait_pq[cl->level].rb_node, *parent = NULL;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700305
Patrick McHardyfb983d42007-03-16 01:22:39 -0700306 cl->pq_key = q->now + delay;
307 if (cl->pq_key == q->now)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 cl->pq_key++;
309
310 /* update the nearest event cache */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700311 if (q->near_ev_cache[cl->level] > cl->pq_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 q->near_ev_cache[cl->level] = cl->pq_key;
Stephen Hemminger87990462006-08-10 23:35:16 -0700313
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 while (*p) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700315 struct htb_class *c;
316 parent = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 c = rb_entry(parent, struct htb_class, pq_node);
Patrick McHardyfb983d42007-03-16 01:22:39 -0700318 if (cl->pq_key >= c->pq_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 p = &parent->rb_right;
Stephen Hemminger87990462006-08-10 23:35:16 -0700320 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 p = &parent->rb_left;
322 }
323 rb_link_node(&cl->pq_node, parent, p);
324 rb_insert_color(&cl->pq_node, &q->wait_pq[cl->level]);
325}
326
327/**
328 * htb_next_rb_node - finds next node in binary tree
329 *
330 * When we are past last key we return NULL.
331 * Average complexity is 2 steps per call.
332 */
Stephen Hemminger3696f622006-08-10 23:36:01 -0700333static inline void htb_next_rb_node(struct rb_node **n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334{
335 *n = rb_next(*n);
336}
337
338/**
339 * htb_add_class_to_row - add class to its row
340 *
341 * The class is added to row at priorities marked in mask.
342 * It does nothing if mask == 0.
343 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700344static inline void htb_add_class_to_row(struct htb_sched *q,
345 struct htb_class *cl, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 q->row_mask[cl->level] |= mask;
348 while (mask) {
349 int prio = ffz(~mask);
350 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700351 htb_add_to_id_tree(q->row[cl->level] + prio, cl, prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 }
353}
354
Stephen Hemminger3696f622006-08-10 23:36:01 -0700355/* If this triggers, it is a bug in this code, but it need not be fatal */
356static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root)
357{
Ismail Donmez81771b32006-10-03 13:49:10 -0700358 if (RB_EMPTY_NODE(rb)) {
Stephen Hemminger3696f622006-08-10 23:36:01 -0700359 WARN_ON(1);
360 } else {
361 rb_erase(rb, root);
362 RB_CLEAR_NODE(rb);
363 }
364}
365
366
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367/**
368 * htb_remove_class_from_row - removes class from its row
369 *
370 * The class is removed from row at priorities marked in mask.
371 * It does nothing if mask == 0.
372 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700373static inline void htb_remove_class_from_row(struct htb_sched *q,
374 struct htb_class *cl, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375{
376 int m = 0;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700377
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 while (mask) {
379 int prio = ffz(~mask);
Stephen Hemminger3696f622006-08-10 23:36:01 -0700380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700382 if (q->ptr[cl->level][prio] == cl->node + prio)
383 htb_next_rb_node(q->ptr[cl->level] + prio);
Stephen Hemminger3696f622006-08-10 23:36:01 -0700384
385 htb_safe_rb_erase(cl->node + prio, q->row[cl->level] + prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700386 if (!q->row[cl->level][prio].rb_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 m |= 1 << prio;
388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 q->row_mask[cl->level] &= ~m;
390}
391
392/**
393 * htb_activate_prios - creates active classe's feed chain
394 *
395 * The class is connected to ancestors and/or appropriate rows
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900396 * for priorities it is participating on. cl->cmode must be new
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 * (activated) mode. It does nothing if cl->prio_activity == 0.
398 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700399static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400{
401 struct htb_class *p = cl->parent;
Stephen Hemminger87990462006-08-10 23:35:16 -0700402 long m, mask = cl->prio_activity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
404 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700405 m = mask;
406 while (m) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 int prio = ffz(~m);
408 m &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700409
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 if (p->un.inner.feed[prio].rb_node)
411 /* parent already has its feed in use so that
412 reset bit in mask as parent is already ok */
413 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700414
415 htb_add_to_id_tree(p->un.inner.feed + prio, cl, prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 p->prio_activity |= mask;
Stephen Hemminger87990462006-08-10 23:35:16 -0700418 cl = p;
419 p = cl->parent;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700420
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 }
422 if (cl->cmode == HTB_CAN_SEND && mask)
Stephen Hemminger87990462006-08-10 23:35:16 -0700423 htb_add_class_to_row(q, cl, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424}
425
426/**
427 * htb_deactivate_prios - remove class from feed chain
428 *
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900429 * cl->cmode must represent old mode (before deactivation). It does
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 * nothing if cl->prio_activity == 0. Class is removed from all feed
431 * chains and rows.
432 */
433static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl)
434{
435 struct htb_class *p = cl->parent;
Stephen Hemminger87990462006-08-10 23:35:16 -0700436 long m, mask = cl->prio_activity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
438 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700439 m = mask;
440 mask = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 while (m) {
442 int prio = ffz(~m);
443 m &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700444
445 if (p->un.inner.ptr[prio] == cl->node + prio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 /* we are removing child which is pointed to from
447 parent feed - forget the pointer but remember
448 classid */
449 p->un.inner.last_ptr_id[prio] = cl->classid;
450 p->un.inner.ptr[prio] = NULL;
451 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700452
Stephen Hemminger3696f622006-08-10 23:36:01 -0700453 htb_safe_rb_erase(cl->node + prio, p->un.inner.feed + prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700454
455 if (!p->un.inner.feed[prio].rb_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 mask |= 1 << prio;
457 }
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700458
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 p->prio_activity &= ~mask;
Stephen Hemminger87990462006-08-10 23:35:16 -0700460 cl = p;
461 p = cl->parent;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700462
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700464 if (cl->cmode == HTB_CAN_SEND && mask)
465 htb_remove_class_from_row(q, cl, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466}
467
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700468static inline long htb_lowater(const struct htb_class *cl)
469{
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700470 if (htb_hysteresis)
471 return cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : 0;
472 else
473 return 0;
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700474}
475static inline long htb_hiwater(const struct htb_class *cl)
476{
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700477 if (htb_hysteresis)
478 return cl->cmode == HTB_CAN_SEND ? -cl->buffer : 0;
479 else
480 return 0;
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700481}
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700482
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700483
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484/**
485 * htb_class_mode - computes and returns current class mode
486 *
487 * It computes cl's mode at time cl->t_c+diff and returns it. If mode
488 * is not HTB_CAN_SEND then cl->pq_key is updated to time difference
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900489 * from now to time when cl will change its state.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 * Also it is worth to note that class mode doesn't change simply
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900491 * at cl->{c,}tokens == 0 but there can rather be hysteresis of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 * 0 .. -cl->{c,}buffer range. It is meant to limit number of
493 * mode transitions per time unit. The speed gain is about 1/6.
494 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700495static inline enum htb_cmode
496htb_class_mode(struct htb_class *cl, long *diff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497{
Stephen Hemminger87990462006-08-10 23:35:16 -0700498 long toks;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
Stephen Hemminger87990462006-08-10 23:35:16 -0700500 if ((toks = (cl->ctokens + *diff)) < htb_lowater(cl)) {
501 *diff = -toks;
502 return HTB_CANT_SEND;
503 }
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700504
Stephen Hemminger87990462006-08-10 23:35:16 -0700505 if ((toks = (cl->tokens + *diff)) >= htb_hiwater(cl))
506 return HTB_CAN_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
Stephen Hemminger87990462006-08-10 23:35:16 -0700508 *diff = -toks;
509 return HTB_MAY_BORROW;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510}
511
512/**
513 * htb_change_class_mode - changes classe's mode
514 *
515 * This should be the only way how to change classe's mode under normal
516 * cirsumstances. Routine will update feed lists linkage, change mode
517 * and add class to the wait event queue if appropriate. New mode should
518 * be different from old one and cl->pq_key has to be valid if changing
519 * to mode other than HTB_CAN_SEND (see htb_add_to_wait_tree).
520 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700521static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long *diff)
Stephen Hemminger87990462006-08-10 23:35:16 -0700523{
524 enum htb_cmode new_mode = htb_class_mode(cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
526 if (new_mode == cl->cmode)
Stephen Hemminger87990462006-08-10 23:35:16 -0700527 return;
528
529 if (cl->prio_activity) { /* not necessary: speed optimization */
530 if (cl->cmode != HTB_CANT_SEND)
531 htb_deactivate_prios(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 cl->cmode = new_mode;
Stephen Hemminger87990462006-08-10 23:35:16 -0700533 if (new_mode != HTB_CANT_SEND)
534 htb_activate_prios(q, cl);
535 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 cl->cmode = new_mode;
537}
538
539/**
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900540 * htb_activate - inserts leaf cl into appropriate active feeds
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 *
542 * Routine learns (new) priority of leaf and activates feed chain
543 * for the prio. It can be called on already active leaf safely.
544 * It also adds leaf into droplist.
545 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700546static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547{
548 BUG_TRAP(!cl->level && cl->un.leaf.q && cl->un.leaf.q->q.qlen);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700549
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 if (!cl->prio_activity) {
551 cl->prio_activity = 1 << (cl->un.leaf.aprio = cl->un.leaf.prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700552 htb_activate_prios(q, cl);
553 list_add_tail(&cl->un.leaf.drop_list,
554 q->drops + cl->un.leaf.aprio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 }
556}
557
558/**
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900559 * htb_deactivate - remove leaf cl from active feeds
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 *
561 * Make sure that leaf is active. In the other words it can't be called
562 * with non-active leaf. It also removes class from the drop list.
563 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700564static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565{
566 BUG_TRAP(cl->prio_activity);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700567
Stephen Hemminger87990462006-08-10 23:35:16 -0700568 htb_deactivate_prios(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 cl->prio_activity = 0;
570 list_del_init(&cl->un.leaf.drop_list);
571}
572
573static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
574{
Stephen Hemminger87990462006-08-10 23:35:16 -0700575 int ret;
576 struct htb_sched *q = qdisc_priv(sch);
577 struct htb_class *cl = htb_classify(skb, sch, &ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578
Stephen Hemminger87990462006-08-10 23:35:16 -0700579 if (cl == HTB_DIRECT) {
580 /* enqueue to helper queue */
581 if (q->direct_queue.qlen < q->direct_qlen) {
582 __skb_queue_tail(&q->direct_queue, skb);
583 q->direct_pkts++;
584 } else {
585 kfree_skb(skb);
586 sch->qstats.drops++;
587 return NET_XMIT_DROP;
588 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589#ifdef CONFIG_NET_CLS_ACT
Stephen Hemminger87990462006-08-10 23:35:16 -0700590 } else if (!cl) {
591 if (ret == NET_XMIT_BYPASS)
592 sch->qstats.drops++;
593 kfree_skb(skb);
594 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595#endif
Stephen Hemminger87990462006-08-10 23:35:16 -0700596 } else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) !=
597 NET_XMIT_SUCCESS) {
598 sch->qstats.drops++;
599 cl->qstats.drops++;
600 return NET_XMIT_DROP;
601 } else {
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700602 cl->bstats.packets +=
603 skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
Stephen Hemminger87990462006-08-10 23:35:16 -0700604 cl->bstats.bytes += skb->len;
605 htb_activate(q, cl);
606 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
Stephen Hemminger87990462006-08-10 23:35:16 -0700608 sch->q.qlen++;
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700609 sch->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
Stephen Hemminger87990462006-08-10 23:35:16 -0700610 sch->bstats.bytes += skb->len;
611 return NET_XMIT_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612}
613
614/* TODO: requeuing packet charges it to policers again !! */
615static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch)
616{
Jarek Poplawski21347452008-02-09 23:44:00 -0800617 int ret;
Stephen Hemminger87990462006-08-10 23:35:16 -0700618 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -0700619 struct htb_class *cl = htb_classify(skb, sch, &ret);
620 struct sk_buff *tskb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
Jarek Poplawski21347452008-02-09 23:44:00 -0800622 if (cl == HTB_DIRECT) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700623 /* enqueue to helper queue */
Jarek Poplawski21347452008-02-09 23:44:00 -0800624 if (q->direct_queue.qlen < q->direct_qlen) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700625 __skb_queue_head(&q->direct_queue, skb);
626 } else {
627 __skb_queue_head(&q->direct_queue, skb);
628 tskb = __skb_dequeue_tail(&q->direct_queue);
629 kfree_skb(tskb);
630 sch->qstats.drops++;
631 return NET_XMIT_CN;
632 }
Jarek Poplawski21347452008-02-09 23:44:00 -0800633#ifdef CONFIG_NET_CLS_ACT
634 } else if (!cl) {
635 if (ret == NET_XMIT_BYPASS)
636 sch->qstats.drops++;
637 kfree_skb(skb);
638 return ret;
639#endif
Stephen Hemminger87990462006-08-10 23:35:16 -0700640 } else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) !=
641 NET_XMIT_SUCCESS) {
642 sch->qstats.drops++;
643 cl->qstats.drops++;
644 return NET_XMIT_DROP;
645 } else
646 htb_activate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
Stephen Hemminger87990462006-08-10 23:35:16 -0700648 sch->q.qlen++;
649 sch->qstats.requeues++;
650 return NET_XMIT_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651}
652
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653/**
654 * htb_charge_class - charges amount "bytes" to leaf and ancestors
655 *
656 * Routine assumes that packet "bytes" long was dequeued from leaf cl
657 * borrowing from "level". It accounts bytes to ceil leaky bucket for
658 * leaf and all ancestors and to rate bucket for ancestors at levels
659 * "level" and higher. It also handles possible change of mode resulting
660 * from the update. Note that mode can also increase here (MAY_BORROW to
661 * CAN_SEND) because we can use more precise clock that event queue here.
662 * In such case we remove class from event queue first.
663 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700664static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700665 int level, struct sk_buff *skb)
Stephen Hemminger87990462006-08-10 23:35:16 -0700666{
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700667 int bytes = skb->len;
Stephen Hemminger87990462006-08-10 23:35:16 -0700668 long toks, diff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 enum htb_cmode old_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670
671#define HTB_ACCNT(T,B,R) toks = diff + cl->T; \
672 if (toks > cl->B) toks = cl->B; \
673 toks -= L2T(cl, cl->R, bytes); \
674 if (toks <= -cl->mbuffer) toks = 1-cl->mbuffer; \
675 cl->T = toks
676
677 while (cl) {
Patrick McHardy03cc45c2007-03-23 11:29:11 -0700678 diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 if (cl->level >= level) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700680 if (cl->level == level)
681 cl->xstats.lends++;
682 HTB_ACCNT(tokens, buffer, rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 } else {
684 cl->xstats.borrows++;
Stephen Hemminger87990462006-08-10 23:35:16 -0700685 cl->tokens += diff; /* we moved t_c; update tokens */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700687 HTB_ACCNT(ctokens, cbuffer, ceil);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 cl->t_c = q->now;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689
Stephen Hemminger87990462006-08-10 23:35:16 -0700690 old_mode = cl->cmode;
691 diff = 0;
692 htb_change_class_mode(q, cl, &diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 if (old_mode != cl->cmode) {
694 if (old_mode != HTB_CAN_SEND)
Stephen Hemminger3696f622006-08-10 23:36:01 -0700695 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 if (cl->cmode != HTB_CAN_SEND)
Stephen Hemminger87990462006-08-10 23:35:16 -0700697 htb_add_to_wait_tree(q, cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
700 /* update byte stats except for leaves which are already updated */
701 if (cl->level) {
702 cl->bstats.bytes += bytes;
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700703 cl->bstats.packets += skb_is_gso(skb)?
704 skb_shinfo(skb)->gso_segs:1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 }
706 cl = cl->parent;
707 }
708}
709
710/**
711 * htb_do_events - make mode changes to classes at the level
712 *
Patrick McHardyfb983d42007-03-16 01:22:39 -0700713 * Scans event queue for pending events and applies them. Returns time of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 * next pending event (0 for no event in pq).
Patrick McHardyfb983d42007-03-16 01:22:39 -0700715 * Note: Applied are events whose have cl->pq_key <= q->now.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700717static psched_time_t htb_do_events(struct htb_sched *q, int level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718{
Martin Devera8f3ea332008-03-23 22:00:38 -0700719 /* don't run for longer than 2 jiffies; 2 is used instead of
720 1 to simplify things when jiffy is going to be incremented
721 too soon */
722 unsigned long stop_at = jiffies + 2;
723 while (time_before(jiffies, stop_at)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 struct htb_class *cl;
725 long diff;
Akinbou Mita30bdbe32006-10-12 01:52:05 -0700726 struct rb_node *p = rb_first(&q->wait_pq[level]);
727
Stephen Hemminger87990462006-08-10 23:35:16 -0700728 if (!p)
729 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
731 cl = rb_entry(p, struct htb_class, pq_node);
Patrick McHardyfb983d42007-03-16 01:22:39 -0700732 if (cl->pq_key > q->now)
733 return cl->pq_key;
734
Stephen Hemminger3696f622006-08-10 23:36:01 -0700735 htb_safe_rb_erase(p, q->wait_pq + level);
Patrick McHardy03cc45c2007-03-23 11:29:11 -0700736 diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
Stephen Hemminger87990462006-08-10 23:35:16 -0700737 htb_change_class_mode(q, cl, &diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 if (cl->cmode != HTB_CAN_SEND)
Stephen Hemminger87990462006-08-10 23:35:16 -0700739 htb_add_to_wait_tree(q, cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 }
Martin Devera8f3ea332008-03-23 22:00:38 -0700741 /* too much load - let's continue on next jiffie */
742 return q->now + PSCHED_TICKS_PER_SEC / HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743}
744
745/* Returns class->node+prio from id-tree where classe's id is >= id. NULL
746 is no such one exists. */
Stephen Hemminger87990462006-08-10 23:35:16 -0700747static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n,
748 u32 id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749{
750 struct rb_node *r = NULL;
751 while (n) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700752 struct htb_class *cl =
753 rb_entry(n, struct htb_class, node[prio]);
754 if (id == cl->classid)
755 return n;
756
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 if (id > cl->classid) {
758 n = n->rb_right;
759 } else {
760 r = n;
761 n = n->rb_left;
762 }
763 }
764 return r;
765}
766
767/**
768 * htb_lookup_leaf - returns next leaf class in DRR order
769 *
770 * Find leaf where current feed pointers points to.
771 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700772static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
773 struct rb_node **pptr, u32 * pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774{
775 int i;
776 struct {
777 struct rb_node *root;
778 struct rb_node **pptr;
779 u32 *pid;
Stephen Hemminger87990462006-08-10 23:35:16 -0700780 } stk[TC_HTB_MAXDEPTH], *sp = stk;
781
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 BUG_TRAP(tree->rb_node);
783 sp->root = tree->rb_node;
784 sp->pptr = pptr;
785 sp->pid = pid;
786
787 for (i = 0; i < 65535; i++) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700788 if (!*sp->pptr && *sp->pid) {
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900789 /* ptr was invalidated but id is valid - try to recover
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 the original or next ptr */
Stephen Hemminger87990462006-08-10 23:35:16 -0700791 *sp->pptr =
792 htb_id_find_next_upper(prio, sp->root, *sp->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700794 *sp->pid = 0; /* ptr is valid now so that remove this hint as it
795 can become out of date quickly */
796 if (!*sp->pptr) { /* we are at right end; rewind & go up */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 *sp->pptr = sp->root;
Stephen Hemminger87990462006-08-10 23:35:16 -0700798 while ((*sp->pptr)->rb_left)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 *sp->pptr = (*sp->pptr)->rb_left;
800 if (sp > stk) {
801 sp--;
Stephen Hemminger87990462006-08-10 23:35:16 -0700802 BUG_TRAP(*sp->pptr);
803 if (!*sp->pptr)
804 return NULL;
805 htb_next_rb_node(sp->pptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 }
807 } else {
808 struct htb_class *cl;
Stephen Hemminger87990462006-08-10 23:35:16 -0700809 cl = rb_entry(*sp->pptr, struct htb_class, node[prio]);
810 if (!cl->level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 return cl;
812 (++sp)->root = cl->un.inner.feed[prio].rb_node;
Stephen Hemminger87990462006-08-10 23:35:16 -0700813 sp->pptr = cl->un.inner.ptr + prio;
814 sp->pid = cl->un.inner.last_ptr_id + prio;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 }
816 }
817 BUG_TRAP(0);
818 return NULL;
819}
820
821/* dequeues packet at given priority and level; call only if
822 you are sure that there is active class at prio/level */
Stephen Hemminger87990462006-08-10 23:35:16 -0700823static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio,
824 int level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825{
826 struct sk_buff *skb = NULL;
Stephen Hemminger87990462006-08-10 23:35:16 -0700827 struct htb_class *cl, *start;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 /* look initial class up in the row */
Stephen Hemminger87990462006-08-10 23:35:16 -0700829 start = cl = htb_lookup_leaf(q->row[level] + prio, prio,
830 q->ptr[level] + prio,
831 q->last_ptr_id[level] + prio);
832
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 do {
834next:
Stephen Hemminger87990462006-08-10 23:35:16 -0700835 BUG_TRAP(cl);
836 if (!cl)
837 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838
839 /* class can be empty - it is unlikely but can be true if leaf
840 qdisc drops packets in enqueue routine or if someone used
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900841 graft operation on the leaf since last dequeue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 simply deactivate and skip such class */
843 if (unlikely(cl->un.leaf.q->q.qlen == 0)) {
844 struct htb_class *next;
Stephen Hemminger87990462006-08-10 23:35:16 -0700845 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
847 /* row/level might become empty */
848 if ((q->row_mask[level] & (1 << prio)) == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -0700849 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850
Stephen Hemminger87990462006-08-10 23:35:16 -0700851 next = htb_lookup_leaf(q->row[level] + prio,
852 prio, q->ptr[level] + prio,
853 q->last_ptr_id[level] + prio);
854
855 if (cl == start) /* fix start if we just deleted it */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 start = next;
857 cl = next;
858 goto next;
859 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700860
861 skb = cl->un.leaf.q->dequeue(cl->un.leaf.q);
862 if (likely(skb != NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 break;
864 if (!cl->warned) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700865 printk(KERN_WARNING
866 "htb: class %X isn't work conserving ?!\n",
867 cl->classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 cl->warned = 1;
869 }
870 q->nwc_hit++;
Stephen Hemminger87990462006-08-10 23:35:16 -0700871 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
872 ptr[0]) + prio);
873 cl = htb_lookup_leaf(q->row[level] + prio, prio,
874 q->ptr[level] + prio,
875 q->last_ptr_id[level] + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
877 } while (cl != start);
878
879 if (likely(skb != NULL)) {
880 if ((cl->un.leaf.deficit[level] -= skb->len) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 cl->un.leaf.deficit[level] += cl->un.leaf.quantum;
Stephen Hemminger87990462006-08-10 23:35:16 -0700882 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
883 ptr[0]) + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 }
885 /* this used to be after charge_class but this constelation
886 gives us slightly better performance */
887 if (!cl->un.leaf.q->q.qlen)
Stephen Hemminger87990462006-08-10 23:35:16 -0700888 htb_deactivate(q, cl);
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700889 htb_charge_class(q, cl, level, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 }
891 return skb;
892}
893
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894static struct sk_buff *htb_dequeue(struct Qdisc *sch)
895{
896 struct sk_buff *skb = NULL;
897 struct htb_sched *q = qdisc_priv(sch);
898 int level;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700899 psched_time_t next_event;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900
901 /* try to dequeue direct packets as high prio (!) to minimize cpu work */
Stephen Hemminger87990462006-08-10 23:35:16 -0700902 skb = __skb_dequeue(&q->direct_queue);
903 if (skb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 sch->flags &= ~TCQ_F_THROTTLED;
905 sch->q.qlen--;
906 return skb;
907 }
908
Stephen Hemminger87990462006-08-10 23:35:16 -0700909 if (!sch->q.qlen)
910 goto fin;
Patrick McHardy3bebcda2007-03-23 11:29:25 -0700911 q->now = psched_get_time();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912
Patrick McHardyfb983d42007-03-16 01:22:39 -0700913 next_event = q->now + 5 * PSCHED_TICKS_PER_SEC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 q->nwc_hit = 0;
915 for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
916 /* common case optimization - skip event handler quickly */
917 int m;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700918 psched_time_t event;
Stephen Hemminger87990462006-08-10 23:35:16 -0700919
Patrick McHardyfb983d42007-03-16 01:22:39 -0700920 if (q->now >= q->near_ev_cache[level]) {
921 event = htb_do_events(q, level);
Patrick McHardy2e4b3b02007-05-23 23:39:54 -0700922 if (!event)
923 event = q->now + PSCHED_TICKS_PER_SEC;
924 q->near_ev_cache[level] = event;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700925 } else
926 event = q->near_ev_cache[level];
927
928 if (event && next_event > event)
929 next_event = event;
930
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 m = ~q->row_mask[level];
932 while (m != (int)(-1)) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700933 int prio = ffz(m);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 m |= 1 << prio;
Stephen Hemminger87990462006-08-10 23:35:16 -0700935 skb = htb_dequeue_tree(q, prio, level);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 if (likely(skb != NULL)) {
937 sch->q.qlen--;
938 sch->flags &= ~TCQ_F_THROTTLED;
939 goto fin;
940 }
941 }
942 }
Patrick McHardyfb983d42007-03-16 01:22:39 -0700943 sch->qstats.overlimits++;
944 qdisc_watchdog_schedule(&q->watchdog, next_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945fin:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 return skb;
947}
948
949/* try to drop from each class (by prio) until one succeed */
Stephen Hemminger87990462006-08-10 23:35:16 -0700950static unsigned int htb_drop(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951{
952 struct htb_sched *q = qdisc_priv(sch);
953 int prio;
954
955 for (prio = TC_HTB_NUMPRIO - 1; prio >= 0; prio--) {
956 struct list_head *p;
Stephen Hemminger87990462006-08-10 23:35:16 -0700957 list_for_each(p, q->drops + prio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 struct htb_class *cl = list_entry(p, struct htb_class,
959 un.leaf.drop_list);
960 unsigned int len;
Stephen Hemminger87990462006-08-10 23:35:16 -0700961 if (cl->un.leaf.q->ops->drop &&
962 (len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 sch->q.qlen--;
964 if (!cl->un.leaf.q->q.qlen)
Stephen Hemminger87990462006-08-10 23:35:16 -0700965 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 return len;
967 }
968 }
969 }
970 return 0;
971}
972
973/* reset all classes */
974/* always caled under BH & queue lock */
Stephen Hemminger87990462006-08-10 23:35:16 -0700975static void htb_reset(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976{
977 struct htb_sched *q = qdisc_priv(sch);
978 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
980 for (i = 0; i < HTB_HSIZE; i++) {
Stephen Hemminger0cef2962006-08-10 23:35:38 -0700981 struct hlist_node *p;
982 struct htb_class *cl;
983
984 hlist_for_each_entry(cl, p, q->hash + i, hlist) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 if (cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700986 memset(&cl->un.inner, 0, sizeof(cl->un.inner));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 else {
Stephen Hemminger87990462006-08-10 23:35:16 -0700988 if (cl->un.leaf.q)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 qdisc_reset(cl->un.leaf.q);
990 INIT_LIST_HEAD(&cl->un.leaf.drop_list);
991 }
992 cl->prio_activity = 0;
993 cl->cmode = HTB_CAN_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
995 }
996 }
Patrick McHardyfb983d42007-03-16 01:22:39 -0700997 qdisc_watchdog_cancel(&q->watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 __skb_queue_purge(&q->direct_queue);
999 sch->q.qlen = 0;
Stephen Hemminger87990462006-08-10 23:35:16 -07001000 memset(q->row, 0, sizeof(q->row));
1001 memset(q->row_mask, 0, sizeof(q->row_mask));
1002 memset(q->wait_pq, 0, sizeof(q->wait_pq));
1003 memset(q->ptr, 0, sizeof(q->ptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 for (i = 0; i < TC_HTB_NUMPRIO; i++)
Stephen Hemminger87990462006-08-10 23:35:16 -07001005 INIT_LIST_HEAD(q->drops + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006}
1007
Patrick McHardy27a34212008-01-23 20:35:39 -08001008static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
1009 [TCA_HTB_PARMS] = { .len = sizeof(struct tc_htb_opt) },
1010 [TCA_HTB_INIT] = { .len = sizeof(struct tc_htb_glob) },
1011 [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
1012 [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
1013};
1014
Patrick McHardy1e904742008-01-22 22:11:17 -08001015static int htb_init(struct Qdisc *sch, struct nlattr *opt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016{
1017 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardy1e904742008-01-22 22:11:17 -08001018 struct nlattr *tb[TCA_HTB_INIT + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 struct tc_htb_glob *gopt;
Patrick McHardycee63722008-01-23 20:33:32 -08001020 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 int i;
Patrick McHardycee63722008-01-23 20:33:32 -08001022
1023 if (!opt)
1024 return -EINVAL;
1025
Patrick McHardy27a34212008-01-23 20:35:39 -08001026 err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy);
Patrick McHardycee63722008-01-23 20:33:32 -08001027 if (err < 0)
1028 return err;
1029
Patrick McHardy27a34212008-01-23 20:35:39 -08001030 if (tb[TCA_HTB_INIT] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
1032 return -EINVAL;
1033 }
Patrick McHardy1e904742008-01-22 22:11:17 -08001034 gopt = nla_data(tb[TCA_HTB_INIT]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 if (gopt->version != HTB_VER >> 16) {
Stephen Hemminger87990462006-08-10 23:35:16 -07001036 printk(KERN_ERR
1037 "HTB: need tc/htb version %d (minor is %d), you have %d\n",
1038 HTB_VER >> 16, HTB_VER & 0xffff, gopt->version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 return -EINVAL;
1040 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041
1042 INIT_LIST_HEAD(&q->root);
1043 for (i = 0; i < HTB_HSIZE; i++)
Stephen Hemminger0cef2962006-08-10 23:35:38 -07001044 INIT_HLIST_HEAD(q->hash + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 for (i = 0; i < TC_HTB_NUMPRIO; i++)
Stephen Hemminger87990462006-08-10 23:35:16 -07001046 INIT_LIST_HEAD(q->drops + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
Patrick McHardyfb983d42007-03-16 01:22:39 -07001048 qdisc_watchdog_init(&q->watchdog, sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 skb_queue_head_init(&q->direct_queue);
1050
1051 q->direct_qlen = sch->dev->tx_queue_len;
Stephen Hemminger87990462006-08-10 23:35:16 -07001052 if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 q->direct_qlen = 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 if ((q->rate2quantum = gopt->rate2quantum) < 1)
1056 q->rate2quantum = 1;
1057 q->defcls = gopt->defcls;
1058
1059 return 0;
1060}
1061
1062static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
1063{
1064 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001065 struct nlattr *nest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 struct tc_htb_glob gopt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001068 spin_lock_bh(&sch->dev->queue_lock);
1069
1070 gopt.direct_pkts = q->direct_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 gopt.version = HTB_VER;
1072 gopt.rate2quantum = q->rate2quantum;
1073 gopt.defcls = q->defcls;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001074 gopt.debug = 0;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001075
1076 nest = nla_nest_start(skb, TCA_OPTIONS);
1077 if (nest == NULL)
1078 goto nla_put_failure;
Patrick McHardy1e904742008-01-22 22:11:17 -08001079 NLA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001080 nla_nest_end(skb, nest);
1081
Stephen Hemminger9ac961e2006-08-10 23:33:16 -07001082 spin_unlock_bh(&sch->dev->queue_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 return skb->len;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001084
Patrick McHardy1e904742008-01-22 22:11:17 -08001085nla_put_failure:
Stephen Hemminger9ac961e2006-08-10 23:33:16 -07001086 spin_unlock_bh(&sch->dev->queue_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001087 nla_nest_cancel(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 return -1;
1089}
1090
1091static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
Stephen Hemminger87990462006-08-10 23:35:16 -07001092 struct sk_buff *skb, struct tcmsg *tcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093{
Stephen Hemminger87990462006-08-10 23:35:16 -07001094 struct htb_class *cl = (struct htb_class *)arg;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001095 struct nlattr *nest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 struct tc_htb_opt opt;
1097
Stephen Hemminger9ac961e2006-08-10 23:33:16 -07001098 spin_lock_bh(&sch->dev->queue_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 tcm->tcm_parent = cl->parent ? cl->parent->classid : TC_H_ROOT;
1100 tcm->tcm_handle = cl->classid;
1101 if (!cl->level && cl->un.leaf.q)
1102 tcm->tcm_info = cl->un.leaf.q->handle;
1103
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001104 nest = nla_nest_start(skb, TCA_OPTIONS);
1105 if (nest == NULL)
1106 goto nla_put_failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
Stephen Hemminger87990462006-08-10 23:35:16 -07001108 memset(&opt, 0, sizeof(opt));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
Stephen Hemminger87990462006-08-10 23:35:16 -07001110 opt.rate = cl->rate->rate;
1111 opt.buffer = cl->buffer;
1112 opt.ceil = cl->ceil->rate;
1113 opt.cbuffer = cl->cbuffer;
1114 opt.quantum = cl->un.leaf.quantum;
1115 opt.prio = cl->un.leaf.prio;
1116 opt.level = cl->level;
Patrick McHardy1e904742008-01-22 22:11:17 -08001117 NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001118
1119 nla_nest_end(skb, nest);
Stephen Hemminger9ac961e2006-08-10 23:33:16 -07001120 spin_unlock_bh(&sch->dev->queue_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 return skb->len;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001122
Patrick McHardy1e904742008-01-22 22:11:17 -08001123nla_put_failure:
Stephen Hemminger9ac961e2006-08-10 23:33:16 -07001124 spin_unlock_bh(&sch->dev->queue_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001125 nla_nest_cancel(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 return -1;
1127}
1128
1129static int
Stephen Hemminger87990462006-08-10 23:35:16 -07001130htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131{
Stephen Hemminger87990462006-08-10 23:35:16 -07001132 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 if (!cl->level && cl->un.leaf.q)
1135 cl->qstats.qlen = cl->un.leaf.q->q.qlen;
1136 cl->xstats.tokens = cl->tokens;
1137 cl->xstats.ctokens = cl->ctokens;
1138
1139 if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
1140 gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
1141 gnet_stats_copy_queue(d, &cl->qstats) < 0)
1142 return -1;
1143
1144 return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
1145}
1146
1147static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
Stephen Hemminger87990462006-08-10 23:35:16 -07001148 struct Qdisc **old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149{
Stephen Hemminger87990462006-08-10 23:35:16 -07001150 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
1152 if (cl && !cl->level) {
Patrick McHardy9f9afec2006-11-29 17:35:18 -08001153 if (new == NULL &&
1154 (new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +09001155 cl->classid))
Stephen Hemminger87990462006-08-10 23:35:16 -07001156 == NULL)
1157 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 sch_tree_lock(sch);
1159 if ((*old = xchg(&cl->un.leaf.q, new)) != NULL) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001160 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 qdisc_reset(*old);
1162 }
1163 sch_tree_unlock(sch);
1164 return 0;
1165 }
1166 return -ENOENT;
1167}
1168
Stephen Hemminger87990462006-08-10 23:35:16 -07001169static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170{
Stephen Hemminger87990462006-08-10 23:35:16 -07001171 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 return (cl && !cl->level) ? cl->un.leaf.q : NULL;
1173}
1174
Patrick McHardy256d61b2006-11-29 17:37:05 -08001175static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg)
1176{
1177 struct htb_class *cl = (struct htb_class *)arg;
1178
1179 if (cl->un.leaf.q->q.qlen == 0)
1180 htb_deactivate(qdisc_priv(sch), cl);
1181}
1182
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183static unsigned long htb_get(struct Qdisc *sch, u32 classid)
1184{
Stephen Hemminger87990462006-08-10 23:35:16 -07001185 struct htb_class *cl = htb_find(classid, sch);
1186 if (cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 cl->refcnt++;
1188 return (unsigned long)cl;
1189}
1190
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001191static inline int htb_parent_last_child(struct htb_class *cl)
1192{
1193 if (!cl->parent)
1194 /* the root class */
1195 return 0;
1196
1197 if (!(cl->parent->children.next == &cl->sibling &&
1198 cl->parent->children.prev == &cl->sibling))
1199 /* not the last child */
1200 return 0;
1201
1202 return 1;
1203}
1204
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001205static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
1206 struct Qdisc *new_q)
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001207{
1208 struct htb_class *parent = cl->parent;
1209
1210 BUG_TRAP(!cl->level && cl->un.leaf.q && !cl->prio_activity);
1211
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001212 if (parent->cmode != HTB_CAN_SEND)
1213 htb_safe_rb_erase(&parent->pq_node, q->wait_pq + parent->level);
1214
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001215 parent->level = 0;
1216 memset(&parent->un.inner, 0, sizeof(parent->un.inner));
1217 INIT_LIST_HEAD(&parent->un.leaf.drop_list);
1218 parent->un.leaf.q = new_q ? new_q : &noop_qdisc;
1219 parent->un.leaf.quantum = parent->quantum;
1220 parent->un.leaf.prio = parent->prio;
1221 parent->tokens = parent->buffer;
1222 parent->ctokens = parent->cbuffer;
Patrick McHardy3bebcda2007-03-23 11:29:25 -07001223 parent->t_c = psched_get_time();
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001224 parent->cmode = HTB_CAN_SEND;
1225}
1226
Stephen Hemminger87990462006-08-10 23:35:16 -07001227static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 if (!cl->level) {
1230 BUG_TRAP(cl->un.leaf.q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 qdisc_destroy(cl->un.leaf.q);
1232 }
Patrick McHardyee39e102007-07-02 22:48:13 -07001233 gen_kill_estimator(&cl->bstats, &cl->rate_est);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 qdisc_put_rtab(cl->rate);
1235 qdisc_put_rtab(cl->ceil);
Stephen Hemminger87990462006-08-10 23:35:16 -07001236
Patrick McHardyff31ab52008-07-01 19:52:38 -07001237 tcf_destroy_chain(&cl->filter_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 kfree(cl);
1239}
1240
1241/* always caled under BH & queue lock */
Stephen Hemminger87990462006-08-10 23:35:16 -07001242static void htb_destroy(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243{
1244 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001245 struct hlist_node *n, *next;
1246 struct htb_class *cl;
1247 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248
Patrick McHardyfb983d42007-03-16 01:22:39 -07001249 qdisc_watchdog_cancel(&q->watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 /* This line used to be after htb_destroy_class call below
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +09001251 and surprisingly it worked in 2.4. But it must precede it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 because filter need its target class alive to be able to call
1253 unbind_filter on it (without Oops). */
Patrick McHardyff31ab52008-07-01 19:52:38 -07001254 tcf_destroy_chain(&q->filter_list);
Stephen Hemminger87990462006-08-10 23:35:16 -07001255
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001256 for (i = 0; i < HTB_HSIZE; i++) {
1257 hlist_for_each_entry(cl, n, q->hash + i, hlist)
1258 tcf_destroy_chain(&cl->filter_list);
1259 }
1260 for (i = 0; i < HTB_HSIZE; i++) {
1261 hlist_for_each_entry_safe(cl, n, next, q->hash + i, hlist)
1262 htb_destroy_class(sch, cl);
1263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 __skb_queue_purge(&q->direct_queue);
1265}
1266
1267static int htb_delete(struct Qdisc *sch, unsigned long arg)
1268{
1269 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001270 struct htb_class *cl = (struct htb_class *)arg;
Patrick McHardy256d61b2006-11-29 17:37:05 -08001271 unsigned int qlen;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001272 struct Qdisc *new_q = NULL;
1273 int last_child = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
1275 // TODO: why don't allow to delete subtree ? references ? does
1276 // tc subsys quarantee us that in htb_destroy it holds no class
1277 // refs so that we can remove children safely there ?
1278 if (!list_empty(&cl->children) || cl->filter_cnt)
1279 return -EBUSY;
Stephen Hemminger87990462006-08-10 23:35:16 -07001280
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001281 if (!cl->level && htb_parent_last_child(cl)) {
1282 new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
1283 cl->parent->classid);
1284 last_child = 1;
1285 }
1286
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 sch_tree_lock(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001288
Patrick McHardy814a175e2006-11-29 17:34:50 -08001289 if (!cl->level) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001290 qlen = cl->un.leaf.q->q.qlen;
Patrick McHardy814a175e2006-11-29 17:34:50 -08001291 qdisc_reset(cl->un.leaf.q);
Patrick McHardy256d61b2006-11-29 17:37:05 -08001292 qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen);
Patrick McHardy814a175e2006-11-29 17:34:50 -08001293 }
1294
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001295 /* delete from hash, sibling list and active */
1296 hlist_del(&cl->hlist);
1297 list_del(&cl->sibling);
Patrick McHardyc38c83c2007-03-27 14:04:24 -07001298
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 if (cl->prio_activity)
Stephen Hemminger87990462006-08-10 23:35:16 -07001300 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001302 if (cl->cmode != HTB_CAN_SEND)
1303 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
1304
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001305 if (last_child)
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001306 htb_parent_to_leaf(q, cl, new_q);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001307
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 if (--cl->refcnt == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -07001309 htb_destroy_class(sch, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
1311 sch_tree_unlock(sch);
1312 return 0;
1313}
1314
1315static void htb_put(struct Qdisc *sch, unsigned long arg)
1316{
Stephen Hemminger87990462006-08-10 23:35:16 -07001317 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318
1319 if (--cl->refcnt == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -07001320 htb_destroy_class(sch, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321}
1322
Stephen Hemminger87990462006-08-10 23:35:16 -07001323static int htb_change_class(struct Qdisc *sch, u32 classid,
Patrick McHardy1e904742008-01-22 22:11:17 -08001324 u32 parentid, struct nlattr **tca,
Stephen Hemminger87990462006-08-10 23:35:16 -07001325 unsigned long *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326{
1327 int err = -EINVAL;
1328 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001329 struct htb_class *cl = (struct htb_class *)*arg, *parent;
Patrick McHardy1e904742008-01-22 22:11:17 -08001330 struct nlattr *opt = tca[TCA_OPTIONS];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
Patrick McHardy1e904742008-01-22 22:11:17 -08001332 struct nlattr *tb[TCA_HTB_RTAB + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 struct tc_htb_opt *hopt;
1334
1335 /* extract all subattrs from opt attr */
Patrick McHardycee63722008-01-23 20:33:32 -08001336 if (!opt)
1337 goto failure;
1338
Patrick McHardy27a34212008-01-23 20:35:39 -08001339 err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, htb_policy);
Patrick McHardycee63722008-01-23 20:33:32 -08001340 if (err < 0)
1341 goto failure;
1342
1343 err = -EINVAL;
Patrick McHardy27a34212008-01-23 20:35:39 -08001344 if (tb[TCA_HTB_PARMS] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 goto failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346
Stephen Hemminger87990462006-08-10 23:35:16 -07001347 parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001348
Patrick McHardy1e904742008-01-22 22:11:17 -08001349 hopt = nla_data(tb[TCA_HTB_PARMS]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
Patrick McHardy1e904742008-01-22 22:11:17 -08001351 rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]);
1352 ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]);
Stephen Hemminger87990462006-08-10 23:35:16 -07001353 if (!rtab || !ctab)
1354 goto failure;
1355
1356 if (!cl) { /* new class */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 struct Qdisc *new_q;
Stephen Hemminger3696f622006-08-10 23:36:01 -07001358 int prio;
Patrick McHardyee39e102007-07-02 22:48:13 -07001359 struct {
Patrick McHardy1e904742008-01-22 22:11:17 -08001360 struct nlattr nla;
Patrick McHardyee39e102007-07-02 22:48:13 -07001361 struct gnet_estimator opt;
1362 } est = {
Patrick McHardy1e904742008-01-22 22:11:17 -08001363 .nla = {
1364 .nla_len = nla_attr_size(sizeof(est.opt)),
1365 .nla_type = TCA_RATE,
Patrick McHardyee39e102007-07-02 22:48:13 -07001366 },
1367 .opt = {
1368 /* 4s interval, 16s averaging constant */
1369 .interval = 2,
1370 .ewma_log = 2,
1371 },
1372 };
Stephen Hemminger3696f622006-08-10 23:36:01 -07001373
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 /* check for valid classid */
Stephen Hemminger87990462006-08-10 23:35:16 -07001375 if (!classid || TC_H_MAJ(classid ^ sch->handle)
1376 || htb_find(classid, sch))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 goto failure;
1378
1379 /* check maximal depth */
1380 if (parent && parent->parent && parent->parent->level < 2) {
1381 printk(KERN_ERR "htb: tree is too deep\n");
1382 goto failure;
1383 }
1384 err = -ENOBUFS;
Panagiotis Issaris0da974f2006-07-21 14:51:30 -07001385 if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 goto failure;
Stephen Hemminger87990462006-08-10 23:35:16 -07001387
Patrick McHardyee39e102007-07-02 22:48:13 -07001388 gen_new_estimator(&cl->bstats, &cl->rate_est,
1389 &sch->dev->queue_lock,
Patrick McHardy1e904742008-01-22 22:11:17 -08001390 tca[TCA_RATE] ? : &est.nla);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 cl->refcnt = 1;
1392 INIT_LIST_HEAD(&cl->sibling);
Stephen Hemminger0cef2962006-08-10 23:35:38 -07001393 INIT_HLIST_NODE(&cl->hlist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 INIT_LIST_HEAD(&cl->children);
1395 INIT_LIST_HEAD(&cl->un.leaf.drop_list);
Stephen Hemminger3696f622006-08-10 23:36:01 -07001396 RB_CLEAR_NODE(&cl->pq_node);
1397
1398 for (prio = 0; prio < TC_HTB_NUMPRIO; prio++)
1399 RB_CLEAR_NODE(&cl->node[prio]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
1401 /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
1402 so that can't be used inside of sch_tree_lock
1403 -- thanks to Karlis Peisenieks */
Patrick McHardy9f9afec2006-11-29 17:35:18 -08001404 new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 sch_tree_lock(sch);
1406 if (parent && !parent->level) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001407 unsigned int qlen = parent->un.leaf.q->q.qlen;
1408
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 /* turn parent into inner node */
Patrick McHardy256d61b2006-11-29 17:37:05 -08001410 qdisc_reset(parent->un.leaf.q);
1411 qdisc_tree_decrease_qlen(parent->un.leaf.q, qlen);
Stephen Hemminger87990462006-08-10 23:35:16 -07001412 qdisc_destroy(parent->un.leaf.q);
1413 if (parent->prio_activity)
1414 htb_deactivate(q, parent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
1416 /* remove from evt list because of level change */
1417 if (parent->cmode != HTB_CAN_SEND) {
Stephen Hemminger3696f622006-08-10 23:36:01 -07001418 htb_safe_rb_erase(&parent->pq_node, q->wait_pq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 parent->cmode = HTB_CAN_SEND;
1420 }
1421 parent->level = (parent->parent ? parent->parent->level
Stephen Hemminger87990462006-08-10 23:35:16 -07001422 : TC_HTB_MAXDEPTH) - 1;
1423 memset(&parent->un.inner, 0, sizeof(parent->un.inner));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 }
1425 /* leaf (we) needs elementary qdisc */
1426 cl->un.leaf.q = new_q ? new_q : &noop_qdisc;
1427
Stephen Hemminger87990462006-08-10 23:35:16 -07001428 cl->classid = classid;
1429 cl->parent = parent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
1431 /* set class to be in HTB_CAN_SEND state */
1432 cl->tokens = hopt->buffer;
1433 cl->ctokens = hopt->cbuffer;
Patrick McHardy00c04af2007-03-16 01:23:02 -07001434 cl->mbuffer = 60 * PSCHED_TICKS_PER_SEC; /* 1min */
Patrick McHardy3bebcda2007-03-23 11:29:25 -07001435 cl->t_c = psched_get_time();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 cl->cmode = HTB_CAN_SEND;
1437
1438 /* attach to the hash list and parent's family */
Stephen Hemminger0cef2962006-08-10 23:35:38 -07001439 hlist_add_head(&cl->hlist, q->hash + htb_hash(classid));
Stephen Hemminger87990462006-08-10 23:35:16 -07001440 list_add_tail(&cl->sibling,
1441 parent ? &parent->children : &q->root);
Patrick McHardyee39e102007-07-02 22:48:13 -07001442 } else {
Patrick McHardy1e904742008-01-22 22:11:17 -08001443 if (tca[TCA_RATE])
Patrick McHardyee39e102007-07-02 22:48:13 -07001444 gen_replace_estimator(&cl->bstats, &cl->rate_est,
1445 &sch->dev->queue_lock,
Patrick McHardy1e904742008-01-22 22:11:17 -08001446 tca[TCA_RATE]);
Stephen Hemminger87990462006-08-10 23:35:16 -07001447 sch_tree_lock(sch);
Patrick McHardyee39e102007-07-02 22:48:13 -07001448 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
1450 /* it used to be a nasty bug here, we have to check that node
Stephen Hemminger87990462006-08-10 23:35:16 -07001451 is really leaf before changing cl->un.leaf ! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 if (!cl->level) {
1453 cl->un.leaf.quantum = rtab->rate.rate / q->rate2quantum;
1454 if (!hopt->quantum && cl->un.leaf.quantum < 1000) {
Stephen Hemminger87990462006-08-10 23:35:16 -07001455 printk(KERN_WARNING
1456 "HTB: quantum of class %X is small. Consider r2q change.\n",
1457 cl->classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 cl->un.leaf.quantum = 1000;
1459 }
1460 if (!hopt->quantum && cl->un.leaf.quantum > 200000) {
Stephen Hemminger87990462006-08-10 23:35:16 -07001461 printk(KERN_WARNING
1462 "HTB: quantum of class %X is big. Consider r2q change.\n",
1463 cl->classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 cl->un.leaf.quantum = 200000;
1465 }
1466 if (hopt->quantum)
1467 cl->un.leaf.quantum = hopt->quantum;
1468 if ((cl->un.leaf.prio = hopt->prio) >= TC_HTB_NUMPRIO)
1469 cl->un.leaf.prio = TC_HTB_NUMPRIO - 1;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001470
1471 /* backup for htb_parent_to_leaf */
1472 cl->quantum = cl->un.leaf.quantum;
1473 cl->prio = cl->un.leaf.prio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 }
1475
1476 cl->buffer = hopt->buffer;
1477 cl->cbuffer = hopt->cbuffer;
Stephen Hemminger87990462006-08-10 23:35:16 -07001478 if (cl->rate)
1479 qdisc_put_rtab(cl->rate);
1480 cl->rate = rtab;
1481 if (cl->ceil)
1482 qdisc_put_rtab(cl->ceil);
1483 cl->ceil = ctab;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 sch_tree_unlock(sch);
1485
1486 *arg = (unsigned long)cl;
1487 return 0;
1488
1489failure:
Stephen Hemminger87990462006-08-10 23:35:16 -07001490 if (rtab)
1491 qdisc_put_rtab(rtab);
1492 if (ctab)
1493 qdisc_put_rtab(ctab);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 return err;
1495}
1496
1497static struct tcf_proto **htb_find_tcf(struct Qdisc *sch, unsigned long arg)
1498{
1499 struct htb_sched *q = qdisc_priv(sch);
1500 struct htb_class *cl = (struct htb_class *)arg;
1501 struct tcf_proto **fl = cl ? &cl->filter_list : &q->filter_list;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001502
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 return fl;
1504}
1505
1506static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent,
Stephen Hemminger87990462006-08-10 23:35:16 -07001507 u32 classid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508{
1509 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001510 struct htb_class *cl = htb_find(classid, sch);
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001511
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 /*if (cl && !cl->level) return 0;
Stephen Hemminger87990462006-08-10 23:35:16 -07001513 The line above used to be there to prevent attaching filters to
1514 leaves. But at least tc_index filter uses this just to get class
1515 for other reasons so that we have to allow for it.
1516 ----
1517 19.6.2002 As Werner explained it is ok - bind filter is just
1518 another way to "lock" the class - unlike "get" this lock can
1519 be broken by class during destroy IIUC.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 */
Stephen Hemminger87990462006-08-10 23:35:16 -07001521 if (cl)
1522 cl->filter_cnt++;
1523 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 q->filter_cnt++;
1525 return (unsigned long)cl;
1526}
1527
1528static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg)
1529{
1530 struct htb_sched *q = qdisc_priv(sch);
1531 struct htb_class *cl = (struct htb_class *)arg;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001532
Stephen Hemminger87990462006-08-10 23:35:16 -07001533 if (cl)
1534 cl->filter_cnt--;
1535 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 q->filter_cnt--;
1537}
1538
1539static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg)
1540{
1541 struct htb_sched *q = qdisc_priv(sch);
1542 int i;
1543
1544 if (arg->stop)
1545 return;
1546
1547 for (i = 0; i < HTB_HSIZE; i++) {
Stephen Hemminger0cef2962006-08-10 23:35:38 -07001548 struct hlist_node *p;
1549 struct htb_class *cl;
1550
1551 hlist_for_each_entry(cl, p, q->hash + i, hlist) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 if (arg->count < arg->skip) {
1553 arg->count++;
1554 continue;
1555 }
1556 if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
1557 arg->stop = 1;
1558 return;
1559 }
1560 arg->count++;
1561 }
1562 }
1563}
1564
Eric Dumazet20fea082007-11-14 01:44:41 -08001565static const struct Qdisc_class_ops htb_class_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 .graft = htb_graft,
1567 .leaf = htb_leaf,
Patrick McHardy256d61b2006-11-29 17:37:05 -08001568 .qlen_notify = htb_qlen_notify,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 .get = htb_get,
1570 .put = htb_put,
1571 .change = htb_change_class,
1572 .delete = htb_delete,
1573 .walk = htb_walk,
1574 .tcf_chain = htb_find_tcf,
1575 .bind_tcf = htb_bind_filter,
1576 .unbind_tcf = htb_unbind_filter,
1577 .dump = htb_dump_class,
1578 .dump_stats = htb_dump_class_stats,
1579};
1580
Eric Dumazet20fea082007-11-14 01:44:41 -08001581static struct Qdisc_ops htb_qdisc_ops __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 .next = NULL,
1583 .cl_ops = &htb_class_ops,
1584 .id = "htb",
1585 .priv_size = sizeof(struct htb_sched),
1586 .enqueue = htb_enqueue,
1587 .dequeue = htb_dequeue,
1588 .requeue = htb_requeue,
1589 .drop = htb_drop,
1590 .init = htb_init,
1591 .reset = htb_reset,
1592 .destroy = htb_destroy,
1593 .change = NULL /* htb_change */,
1594 .dump = htb_dump,
1595 .owner = THIS_MODULE,
1596};
1597
1598static int __init htb_module_init(void)
1599{
Stephen Hemminger87990462006-08-10 23:35:16 -07001600 return register_qdisc(&htb_qdisc_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601}
Stephen Hemminger87990462006-08-10 23:35:16 -07001602static void __exit htb_module_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603{
Stephen Hemminger87990462006-08-10 23:35:16 -07001604 unregister_qdisc(&htb_qdisc_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605}
Stephen Hemminger87990462006-08-10 23:35:16 -07001606
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607module_init(htb_module_init)
1608module_exit(htb_module_exit)
1609MODULE_LICENSE("GPL");