blob: e7461a17d71e042e9548cb2618349a64b9297fa3 [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) */
84 struct htb_class *parent; /* parent class */
Stephen Hemminger87990462006-08-10 23:35:16 -070085 struct list_head sibling; /* sibling list item */
86 struct list_head children; /* children list */
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Stephen Hemminger87990462006-08-10 23:35:16 -070088 union {
89 struct htb_class_leaf {
90 struct Qdisc *q;
91 int prio;
92 int aprio;
93 int quantum;
94 int deficit[TC_HTB_MAXDEPTH];
95 struct list_head drop_list;
96 } leaf;
97 struct htb_class_inner {
98 struct rb_root feed[TC_HTB_NUMPRIO]; /* feed trees */
99 struct rb_node *ptr[TC_HTB_NUMPRIO]; /* current class ptr */
100 /* When class changes from state 1->2 and disconnects from
101 parent's feed then we lost ptr value and start from the
102 first child again. Here we store classid of the
103 last valid ptr (used when ptr is NULL). */
104 u32 last_ptr_id[TC_HTB_NUMPRIO];
105 } inner;
106 } un;
107 struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */
108 struct rb_node pq_node; /* node for event queue */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700109 psched_time_t pq_key;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
Stephen Hemminger87990462006-08-10 23:35:16 -0700111 int prio_activity; /* for which prios are we active */
112 enum htb_cmode cmode; /* current mode of the class */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
Stephen Hemminger87990462006-08-10 23:35:16 -0700114 /* class attached filters */
115 struct tcf_proto *filter_list;
116 int filter_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
Stephen Hemminger87990462006-08-10 23:35:16 -0700118 int warned; /* only one warning about non work conserving .. */
119
120 /* token bucket parameters */
121 struct qdisc_rate_table *rate; /* rate table of the class itself */
122 struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */
123 long buffer, cbuffer; /* token bucket depth/rate */
124 psched_tdiff_t mbuffer; /* max wait time */
125 long tokens, ctokens; /* current number of tokens */
126 psched_time_t t_c; /* checkpoint time */
Jarek Poplawski160d5e12006-12-08 00:26:56 -0800127
128 int prio; /* For parent to leaf return possible here */
129 int quantum; /* we do backup. Finally full replacement */
130 /* of un.leaf originals should be done. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131};
132
Stephen Hemminger87990462006-08-10 23:35:16 -0700133static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate,
134 int size)
135{
Jesper Dangaard Brouere9bef552007-09-12 16:35:24 +0200136 long result = qdisc_l2t(rate, size);
137 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138}
139
Stephen Hemminger87990462006-08-10 23:35:16 -0700140struct htb_sched {
141 struct list_head root; /* root classes list */
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700142 struct Qdisc_class_hash clhash;
Stephen Hemminger0cef2962006-08-10 23:35:38 -0700143 struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
Stephen Hemminger87990462006-08-10 23:35:16 -0700145 /* self list - roots of self generating tree */
146 struct rb_root row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
147 int row_mask[TC_HTB_MAXDEPTH];
148 struct rb_node *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
149 u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Stephen Hemminger87990462006-08-10 23:35:16 -0700151 /* self wait list - roots of wait PQs per row */
152 struct rb_root wait_pq[TC_HTB_MAXDEPTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
Stephen Hemminger87990462006-08-10 23:35:16 -0700154 /* time of nearest event per level (row) */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700155 psched_time_t near_ev_cache[TC_HTB_MAXDEPTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
Stephen Hemminger87990462006-08-10 23:35:16 -0700157 /* whether we hit non-work conserving class during this dequeue; we use */
158 int nwc_hit; /* this to disable mindelay complaint in dequeue */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
Stephen Hemminger87990462006-08-10 23:35:16 -0700160 int defcls; /* class where unclassified flows go to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
Stephen Hemminger87990462006-08-10 23:35:16 -0700162 /* filters for qdisc itself */
163 struct tcf_proto *filter_list;
164 int filter_cnt;
165
166 int rate2quantum; /* quant = rate / rate2quantum */
167 psched_time_t now; /* cached dequeue time */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700168 struct qdisc_watchdog watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169
Stephen Hemminger87990462006-08-10 23:35:16 -0700170 /* non shaped skbs; let them go directly thru */
171 struct sk_buff_head direct_queue;
172 int direct_qlen; /* max qlen of above */
173
174 long direct_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175};
176
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177/* find class in global hash table using given handle */
Stephen Hemminger87990462006-08-10 23:35:16 -0700178static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179{
180 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700181 struct Qdisc_class_common *clc;
Stephen Hemminger0cef2962006-08-10 23:35:38 -0700182
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700183 clc = qdisc_class_find(&q->clhash, handle);
184 if (clc == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 return NULL;
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700186 return container_of(clc, struct htb_class, common);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187}
188
189/**
190 * htb_classify - classify a packet into class
191 *
192 * It returns NULL if the packet should be dropped or -1 if the packet
193 * should be passed directly thru. In all other cases leaf class is returned.
194 * We allow direct class selection by classid in priority. The we examine
195 * filters in qdisc and in inner nodes (if higher filter points to the inner
196 * node). If we end up with classid MAJOR:0 we enqueue the skb into special
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900197 * internal fifo (direct). These packets then go directly thru. If we still
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessfull
199 * then finish and return direct queue.
200 */
201#define HTB_DIRECT (struct htb_class*)-1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202
Stephen Hemminger87990462006-08-10 23:35:16 -0700203static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
204 int *qerr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205{
206 struct htb_sched *q = qdisc_priv(sch);
207 struct htb_class *cl;
208 struct tcf_result res;
209 struct tcf_proto *tcf;
210 int result;
211
212 /* allow to select class by setting skb->priority to valid classid;
213 note that nfmark can be used too by attaching filter fw with no
214 rules in it */
215 if (skb->priority == sch->handle)
Stephen Hemminger87990462006-08-10 23:35:16 -0700216 return HTB_DIRECT; /* X:0 (direct flow) selected */
217 if ((cl = htb_find(skb->priority, sch)) != NULL && cl->level == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 return cl;
219
Jamal Hadi Salim29f1df62006-01-08 22:35:55 -0800220 *qerr = NET_XMIT_BYPASS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 tcf = q->filter_list;
222 while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
223#ifdef CONFIG_NET_CLS_ACT
224 switch (result) {
225 case TC_ACT_QUEUED:
Stephen Hemminger87990462006-08-10 23:35:16 -0700226 case TC_ACT_STOLEN:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 *qerr = NET_XMIT_SUCCESS;
228 case TC_ACT_SHOT:
229 return NULL;
230 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231#endif
Stephen Hemminger87990462006-08-10 23:35:16 -0700232 if ((cl = (void *)res.class) == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 if (res.classid == sch->handle)
Stephen Hemminger87990462006-08-10 23:35:16 -0700234 return HTB_DIRECT; /* X:0 (direct flow) */
235 if ((cl = htb_find(res.classid, sch)) == NULL)
236 break; /* filter selected invalid classid */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 }
238 if (!cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700239 return cl; /* we hit leaf; return it */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240
241 /* we have got inner class; apply inner filter chain */
242 tcf = cl->filter_list;
243 }
244 /* classification failed; try to use default class */
Stephen Hemminger87990462006-08-10 23:35:16 -0700245 cl = htb_find(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 if (!cl || cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700247 return HTB_DIRECT; /* bad default .. this is safe bet */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 return cl;
249}
250
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251/**
252 * htb_add_to_id_tree - adds class to the round robin list
253 *
254 * Routine adds class to the list (actually tree) sorted by classid.
255 * Make sure that class is not already on such list for given prio.
256 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700257static void htb_add_to_id_tree(struct rb_root *root,
258 struct htb_class *cl, int prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259{
260 struct rb_node **p = &root->rb_node, *parent = NULL;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700261
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 while (*p) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700263 struct htb_class *c;
264 parent = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 c = rb_entry(parent, struct htb_class, node[prio]);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700266
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700267 if (cl->common.classid > c->common.classid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 p = &parent->rb_right;
Stephen Hemminger87990462006-08-10 23:35:16 -0700269 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 p = &parent->rb_left;
271 }
272 rb_link_node(&cl->node[prio], parent, p);
273 rb_insert_color(&cl->node[prio], root);
274}
275
276/**
277 * htb_add_to_wait_tree - adds class to the event queue with delay
278 *
279 * The class is added to priority event queue to indicate that class will
280 * change its mode in cl->pq_key microseconds. Make sure that class is not
281 * already in the queue.
282 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700283static void htb_add_to_wait_tree(struct htb_sched *q,
284 struct htb_class *cl, long delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285{
286 struct rb_node **p = &q->wait_pq[cl->level].rb_node, *parent = NULL;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700287
Patrick McHardyfb983d42007-03-16 01:22:39 -0700288 cl->pq_key = q->now + delay;
289 if (cl->pq_key == q->now)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 cl->pq_key++;
291
292 /* update the nearest event cache */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700293 if (q->near_ev_cache[cl->level] > cl->pq_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 q->near_ev_cache[cl->level] = cl->pq_key;
Stephen Hemminger87990462006-08-10 23:35:16 -0700295
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 while (*p) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700297 struct htb_class *c;
298 parent = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 c = rb_entry(parent, struct htb_class, pq_node);
Patrick McHardyfb983d42007-03-16 01:22:39 -0700300 if (cl->pq_key >= c->pq_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 p = &parent->rb_right;
Stephen Hemminger87990462006-08-10 23:35:16 -0700302 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 p = &parent->rb_left;
304 }
305 rb_link_node(&cl->pq_node, parent, p);
306 rb_insert_color(&cl->pq_node, &q->wait_pq[cl->level]);
307}
308
309/**
310 * htb_next_rb_node - finds next node in binary tree
311 *
312 * When we are past last key we return NULL.
313 * Average complexity is 2 steps per call.
314 */
Stephen Hemminger3696f622006-08-10 23:36:01 -0700315static inline void htb_next_rb_node(struct rb_node **n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316{
317 *n = rb_next(*n);
318}
319
320/**
321 * htb_add_class_to_row - add class to its row
322 *
323 * The class is added to row at priorities marked in mask.
324 * It does nothing if mask == 0.
325 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700326static inline void htb_add_class_to_row(struct htb_sched *q,
327 struct htb_class *cl, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 q->row_mask[cl->level] |= mask;
330 while (mask) {
331 int prio = ffz(~mask);
332 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700333 htb_add_to_id_tree(q->row[cl->level] + prio, cl, prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 }
335}
336
Stephen Hemminger3696f622006-08-10 23:36:01 -0700337/* If this triggers, it is a bug in this code, but it need not be fatal */
338static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root)
339{
Ismail Donmez81771b32006-10-03 13:49:10 -0700340 if (RB_EMPTY_NODE(rb)) {
Stephen Hemminger3696f622006-08-10 23:36:01 -0700341 WARN_ON(1);
342 } else {
343 rb_erase(rb, root);
344 RB_CLEAR_NODE(rb);
345 }
346}
347
348
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349/**
350 * htb_remove_class_from_row - removes class from its row
351 *
352 * The class is removed from row at priorities marked in mask.
353 * It does nothing if mask == 0.
354 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700355static inline void htb_remove_class_from_row(struct htb_sched *q,
356 struct htb_class *cl, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357{
358 int m = 0;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700359
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 while (mask) {
361 int prio = ffz(~mask);
Stephen Hemminger3696f622006-08-10 23:36:01 -0700362
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700364 if (q->ptr[cl->level][prio] == cl->node + prio)
365 htb_next_rb_node(q->ptr[cl->level] + prio);
Stephen Hemminger3696f622006-08-10 23:36:01 -0700366
367 htb_safe_rb_erase(cl->node + prio, q->row[cl->level] + prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700368 if (!q->row[cl->level][prio].rb_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 m |= 1 << prio;
370 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 q->row_mask[cl->level] &= ~m;
372}
373
374/**
375 * htb_activate_prios - creates active classe's feed chain
376 *
377 * The class is connected to ancestors and/or appropriate rows
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900378 * for priorities it is participating on. cl->cmode must be new
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 * (activated) mode. It does nothing if cl->prio_activity == 0.
380 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700381static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382{
383 struct htb_class *p = cl->parent;
Stephen Hemminger87990462006-08-10 23:35:16 -0700384 long m, mask = cl->prio_activity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385
386 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700387 m = mask;
388 while (m) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 int prio = ffz(~m);
390 m &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700391
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 if (p->un.inner.feed[prio].rb_node)
393 /* parent already has its feed in use so that
394 reset bit in mask as parent is already ok */
395 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700396
397 htb_add_to_id_tree(p->un.inner.feed + prio, cl, prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 p->prio_activity |= mask;
Stephen Hemminger87990462006-08-10 23:35:16 -0700400 cl = p;
401 p = cl->parent;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700402
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 }
404 if (cl->cmode == HTB_CAN_SEND && mask)
Stephen Hemminger87990462006-08-10 23:35:16 -0700405 htb_add_class_to_row(q, cl, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406}
407
408/**
409 * htb_deactivate_prios - remove class from feed chain
410 *
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900411 * cl->cmode must represent old mode (before deactivation). It does
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 * nothing if cl->prio_activity == 0. Class is removed from all feed
413 * chains and rows.
414 */
415static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl)
416{
417 struct htb_class *p = cl->parent;
Stephen Hemminger87990462006-08-10 23:35:16 -0700418 long m, mask = cl->prio_activity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
420 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700421 m = mask;
422 mask = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 while (m) {
424 int prio = ffz(~m);
425 m &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700426
427 if (p->un.inner.ptr[prio] == cl->node + prio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 /* we are removing child which is pointed to from
429 parent feed - forget the pointer but remember
430 classid */
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700431 p->un.inner.last_ptr_id[prio] = cl->common.classid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 p->un.inner.ptr[prio] = NULL;
433 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700434
Stephen Hemminger3696f622006-08-10 23:36:01 -0700435 htb_safe_rb_erase(cl->node + prio, p->un.inner.feed + prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700436
437 if (!p->un.inner.feed[prio].rb_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 mask |= 1 << prio;
439 }
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 p->prio_activity &= ~mask;
Stephen Hemminger87990462006-08-10 23:35:16 -0700442 cl = p;
443 p = cl->parent;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700444
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700446 if (cl->cmode == HTB_CAN_SEND && mask)
447 htb_remove_class_from_row(q, cl, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448}
449
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700450static inline long htb_lowater(const struct htb_class *cl)
451{
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700452 if (htb_hysteresis)
453 return cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : 0;
454 else
455 return 0;
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700456}
457static inline long htb_hiwater(const struct htb_class *cl)
458{
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700459 if (htb_hysteresis)
460 return cl->cmode == HTB_CAN_SEND ? -cl->buffer : 0;
461 else
462 return 0;
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700463}
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700464
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700465
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466/**
467 * htb_class_mode - computes and returns current class mode
468 *
469 * It computes cl's mode at time cl->t_c+diff and returns it. If mode
470 * is not HTB_CAN_SEND then cl->pq_key is updated to time difference
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900471 * from now to time when cl will change its state.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 * Also it is worth to note that class mode doesn't change simply
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900473 * at cl->{c,}tokens == 0 but there can rather be hysteresis of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 * 0 .. -cl->{c,}buffer range. It is meant to limit number of
475 * mode transitions per time unit. The speed gain is about 1/6.
476 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700477static inline enum htb_cmode
478htb_class_mode(struct htb_class *cl, long *diff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479{
Stephen Hemminger87990462006-08-10 23:35:16 -0700480 long toks;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
Stephen Hemminger87990462006-08-10 23:35:16 -0700482 if ((toks = (cl->ctokens + *diff)) < htb_lowater(cl)) {
483 *diff = -toks;
484 return HTB_CANT_SEND;
485 }
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700486
Stephen Hemminger87990462006-08-10 23:35:16 -0700487 if ((toks = (cl->tokens + *diff)) >= htb_hiwater(cl))
488 return HTB_CAN_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
Stephen Hemminger87990462006-08-10 23:35:16 -0700490 *diff = -toks;
491 return HTB_MAY_BORROW;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492}
493
494/**
495 * htb_change_class_mode - changes classe's mode
496 *
497 * This should be the only way how to change classe's mode under normal
498 * cirsumstances. Routine will update feed lists linkage, change mode
499 * and add class to the wait event queue if appropriate. New mode should
500 * be different from old one and cl->pq_key has to be valid if changing
501 * to mode other than HTB_CAN_SEND (see htb_add_to_wait_tree).
502 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700503static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long *diff)
Stephen Hemminger87990462006-08-10 23:35:16 -0700505{
506 enum htb_cmode new_mode = htb_class_mode(cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
508 if (new_mode == cl->cmode)
Stephen Hemminger87990462006-08-10 23:35:16 -0700509 return;
510
511 if (cl->prio_activity) { /* not necessary: speed optimization */
512 if (cl->cmode != HTB_CANT_SEND)
513 htb_deactivate_prios(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 cl->cmode = new_mode;
Stephen Hemminger87990462006-08-10 23:35:16 -0700515 if (new_mode != HTB_CANT_SEND)
516 htb_activate_prios(q, cl);
517 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 cl->cmode = new_mode;
519}
520
521/**
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900522 * htb_activate - inserts leaf cl into appropriate active feeds
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 *
524 * Routine learns (new) priority of leaf and activates feed chain
525 * for the prio. It can be called on already active leaf safely.
526 * It also adds leaf into droplist.
527 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700528static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529{
530 BUG_TRAP(!cl->level && cl->un.leaf.q && cl->un.leaf.q->q.qlen);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700531
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 if (!cl->prio_activity) {
533 cl->prio_activity = 1 << (cl->un.leaf.aprio = cl->un.leaf.prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700534 htb_activate_prios(q, cl);
535 list_add_tail(&cl->un.leaf.drop_list,
536 q->drops + cl->un.leaf.aprio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 }
538}
539
540/**
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900541 * htb_deactivate - remove leaf cl from active feeds
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 *
543 * Make sure that leaf is active. In the other words it can't be called
544 * with non-active leaf. It also removes class from the drop list.
545 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700546static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547{
548 BUG_TRAP(cl->prio_activity);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700549
Stephen Hemminger87990462006-08-10 23:35:16 -0700550 htb_deactivate_prios(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 cl->prio_activity = 0;
552 list_del_init(&cl->un.leaf.drop_list);
553}
554
555static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
556{
Stephen Hemminger87990462006-08-10 23:35:16 -0700557 int ret;
558 struct htb_sched *q = qdisc_priv(sch);
559 struct htb_class *cl = htb_classify(skb, sch, &ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
Stephen Hemminger87990462006-08-10 23:35:16 -0700561 if (cl == HTB_DIRECT) {
562 /* enqueue to helper queue */
563 if (q->direct_queue.qlen < q->direct_qlen) {
564 __skb_queue_tail(&q->direct_queue, skb);
565 q->direct_pkts++;
566 } else {
567 kfree_skb(skb);
568 sch->qstats.drops++;
569 return NET_XMIT_DROP;
570 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571#ifdef CONFIG_NET_CLS_ACT
Stephen Hemminger87990462006-08-10 23:35:16 -0700572 } else if (!cl) {
573 if (ret == NET_XMIT_BYPASS)
574 sch->qstats.drops++;
575 kfree_skb(skb);
576 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577#endif
Stephen Hemminger87990462006-08-10 23:35:16 -0700578 } else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) !=
579 NET_XMIT_SUCCESS) {
580 sch->qstats.drops++;
581 cl->qstats.drops++;
582 return NET_XMIT_DROP;
583 } else {
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700584 cl->bstats.packets +=
585 skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
Stephen Hemminger87990462006-08-10 23:35:16 -0700586 cl->bstats.bytes += skb->len;
587 htb_activate(q, cl);
588 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
Stephen Hemminger87990462006-08-10 23:35:16 -0700590 sch->q.qlen++;
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700591 sch->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
Stephen Hemminger87990462006-08-10 23:35:16 -0700592 sch->bstats.bytes += skb->len;
593 return NET_XMIT_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594}
595
596/* TODO: requeuing packet charges it to policers again !! */
597static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch)
598{
Jarek Poplawski21347452008-02-09 23:44:00 -0800599 int ret;
Stephen Hemminger87990462006-08-10 23:35:16 -0700600 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -0700601 struct htb_class *cl = htb_classify(skb, sch, &ret);
602 struct sk_buff *tskb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603
Jarek Poplawski21347452008-02-09 23:44:00 -0800604 if (cl == HTB_DIRECT) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700605 /* enqueue to helper queue */
Jarek Poplawski21347452008-02-09 23:44:00 -0800606 if (q->direct_queue.qlen < q->direct_qlen) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700607 __skb_queue_head(&q->direct_queue, skb);
608 } else {
609 __skb_queue_head(&q->direct_queue, skb);
610 tskb = __skb_dequeue_tail(&q->direct_queue);
611 kfree_skb(tskb);
612 sch->qstats.drops++;
613 return NET_XMIT_CN;
614 }
Jarek Poplawski21347452008-02-09 23:44:00 -0800615#ifdef CONFIG_NET_CLS_ACT
616 } else if (!cl) {
617 if (ret == NET_XMIT_BYPASS)
618 sch->qstats.drops++;
619 kfree_skb(skb);
620 return ret;
621#endif
Stephen Hemminger87990462006-08-10 23:35:16 -0700622 } else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) !=
623 NET_XMIT_SUCCESS) {
624 sch->qstats.drops++;
625 cl->qstats.drops++;
626 return NET_XMIT_DROP;
627 } else
628 htb_activate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
Stephen Hemminger87990462006-08-10 23:35:16 -0700630 sch->q.qlen++;
631 sch->qstats.requeues++;
632 return NET_XMIT_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633}
634
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635/**
636 * htb_charge_class - charges amount "bytes" to leaf and ancestors
637 *
638 * Routine assumes that packet "bytes" long was dequeued from leaf cl
639 * borrowing from "level". It accounts bytes to ceil leaky bucket for
640 * leaf and all ancestors and to rate bucket for ancestors at levels
641 * "level" and higher. It also handles possible change of mode resulting
642 * from the update. Note that mode can also increase here (MAY_BORROW to
643 * CAN_SEND) because we can use more precise clock that event queue here.
644 * In such case we remove class from event queue first.
645 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700646static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700647 int level, struct sk_buff *skb)
Stephen Hemminger87990462006-08-10 23:35:16 -0700648{
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700649 int bytes = skb->len;
Stephen Hemminger87990462006-08-10 23:35:16 -0700650 long toks, diff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 enum htb_cmode old_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
653#define HTB_ACCNT(T,B,R) toks = diff + cl->T; \
654 if (toks > cl->B) toks = cl->B; \
655 toks -= L2T(cl, cl->R, bytes); \
656 if (toks <= -cl->mbuffer) toks = 1-cl->mbuffer; \
657 cl->T = toks
658
659 while (cl) {
Patrick McHardy03cc45c2007-03-23 11:29:11 -0700660 diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 if (cl->level >= level) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700662 if (cl->level == level)
663 cl->xstats.lends++;
664 HTB_ACCNT(tokens, buffer, rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 } else {
666 cl->xstats.borrows++;
Stephen Hemminger87990462006-08-10 23:35:16 -0700667 cl->tokens += diff; /* we moved t_c; update tokens */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700669 HTB_ACCNT(ctokens, cbuffer, ceil);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 cl->t_c = q->now;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671
Stephen Hemminger87990462006-08-10 23:35:16 -0700672 old_mode = cl->cmode;
673 diff = 0;
674 htb_change_class_mode(q, cl, &diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 if (old_mode != cl->cmode) {
676 if (old_mode != HTB_CAN_SEND)
Stephen Hemminger3696f622006-08-10 23:36:01 -0700677 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 if (cl->cmode != HTB_CAN_SEND)
Stephen Hemminger87990462006-08-10 23:35:16 -0700679 htb_add_to_wait_tree(q, cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
682 /* update byte stats except for leaves which are already updated */
683 if (cl->level) {
684 cl->bstats.bytes += bytes;
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700685 cl->bstats.packets += skb_is_gso(skb)?
686 skb_shinfo(skb)->gso_segs:1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 }
688 cl = cl->parent;
689 }
690}
691
692/**
693 * htb_do_events - make mode changes to classes at the level
694 *
Patrick McHardyfb983d42007-03-16 01:22:39 -0700695 * Scans event queue for pending events and applies them. Returns time of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 * next pending event (0 for no event in pq).
Patrick McHardyfb983d42007-03-16 01:22:39 -0700697 * Note: Applied are events whose have cl->pq_key <= q->now.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700699static psched_time_t htb_do_events(struct htb_sched *q, int level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700{
Martin Devera8f3ea332008-03-23 22:00:38 -0700701 /* don't run for longer than 2 jiffies; 2 is used instead of
702 1 to simplify things when jiffy is going to be incremented
703 too soon */
704 unsigned long stop_at = jiffies + 2;
705 while (time_before(jiffies, stop_at)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 struct htb_class *cl;
707 long diff;
Akinbou Mita30bdbe32006-10-12 01:52:05 -0700708 struct rb_node *p = rb_first(&q->wait_pq[level]);
709
Stephen Hemminger87990462006-08-10 23:35:16 -0700710 if (!p)
711 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712
713 cl = rb_entry(p, struct htb_class, pq_node);
Patrick McHardyfb983d42007-03-16 01:22:39 -0700714 if (cl->pq_key > q->now)
715 return cl->pq_key;
716
Stephen Hemminger3696f622006-08-10 23:36:01 -0700717 htb_safe_rb_erase(p, q->wait_pq + level);
Patrick McHardy03cc45c2007-03-23 11:29:11 -0700718 diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
Stephen Hemminger87990462006-08-10 23:35:16 -0700719 htb_change_class_mode(q, cl, &diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 if (cl->cmode != HTB_CAN_SEND)
Stephen Hemminger87990462006-08-10 23:35:16 -0700721 htb_add_to_wait_tree(q, cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 }
Martin Devera8f3ea332008-03-23 22:00:38 -0700723 /* too much load - let's continue on next jiffie */
724 return q->now + PSCHED_TICKS_PER_SEC / HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725}
726
727/* Returns class->node+prio from id-tree where classe's id is >= id. NULL
728 is no such one exists. */
Stephen Hemminger87990462006-08-10 23:35:16 -0700729static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n,
730 u32 id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731{
732 struct rb_node *r = NULL;
733 while (n) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700734 struct htb_class *cl =
735 rb_entry(n, struct htb_class, node[prio]);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700736 if (id == cl->common.classid)
Stephen Hemminger87990462006-08-10 23:35:16 -0700737 return n;
738
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700739 if (id > cl->common.classid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 n = n->rb_right;
741 } else {
742 r = n;
743 n = n->rb_left;
744 }
745 }
746 return r;
747}
748
749/**
750 * htb_lookup_leaf - returns next leaf class in DRR order
751 *
752 * Find leaf where current feed pointers points to.
753 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700754static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
755 struct rb_node **pptr, u32 * pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756{
757 int i;
758 struct {
759 struct rb_node *root;
760 struct rb_node **pptr;
761 u32 *pid;
Stephen Hemminger87990462006-08-10 23:35:16 -0700762 } stk[TC_HTB_MAXDEPTH], *sp = stk;
763
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 BUG_TRAP(tree->rb_node);
765 sp->root = tree->rb_node;
766 sp->pptr = pptr;
767 sp->pid = pid;
768
769 for (i = 0; i < 65535; i++) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700770 if (!*sp->pptr && *sp->pid) {
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900771 /* ptr was invalidated but id is valid - try to recover
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 the original or next ptr */
Stephen Hemminger87990462006-08-10 23:35:16 -0700773 *sp->pptr =
774 htb_id_find_next_upper(prio, sp->root, *sp->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700776 *sp->pid = 0; /* ptr is valid now so that remove this hint as it
777 can become out of date quickly */
778 if (!*sp->pptr) { /* we are at right end; rewind & go up */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 *sp->pptr = sp->root;
Stephen Hemminger87990462006-08-10 23:35:16 -0700780 while ((*sp->pptr)->rb_left)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 *sp->pptr = (*sp->pptr)->rb_left;
782 if (sp > stk) {
783 sp--;
Stephen Hemminger87990462006-08-10 23:35:16 -0700784 BUG_TRAP(*sp->pptr);
785 if (!*sp->pptr)
786 return NULL;
787 htb_next_rb_node(sp->pptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 }
789 } else {
790 struct htb_class *cl;
Stephen Hemminger87990462006-08-10 23:35:16 -0700791 cl = rb_entry(*sp->pptr, struct htb_class, node[prio]);
792 if (!cl->level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 return cl;
794 (++sp)->root = cl->un.inner.feed[prio].rb_node;
Stephen Hemminger87990462006-08-10 23:35:16 -0700795 sp->pptr = cl->un.inner.ptr + prio;
796 sp->pid = cl->un.inner.last_ptr_id + prio;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 }
798 }
799 BUG_TRAP(0);
800 return NULL;
801}
802
803/* dequeues packet at given priority and level; call only if
804 you are sure that there is active class at prio/level */
Stephen Hemminger87990462006-08-10 23:35:16 -0700805static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio,
806 int level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807{
808 struct sk_buff *skb = NULL;
Stephen Hemminger87990462006-08-10 23:35:16 -0700809 struct htb_class *cl, *start;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 /* look initial class up in the row */
Stephen Hemminger87990462006-08-10 23:35:16 -0700811 start = cl = htb_lookup_leaf(q->row[level] + prio, prio,
812 q->ptr[level] + prio,
813 q->last_ptr_id[level] + prio);
814
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 do {
816next:
Stephen Hemminger87990462006-08-10 23:35:16 -0700817 BUG_TRAP(cl);
818 if (!cl)
819 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
821 /* class can be empty - it is unlikely but can be true if leaf
822 qdisc drops packets in enqueue routine or if someone used
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900823 graft operation on the leaf since last dequeue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 simply deactivate and skip such class */
825 if (unlikely(cl->un.leaf.q->q.qlen == 0)) {
826 struct htb_class *next;
Stephen Hemminger87990462006-08-10 23:35:16 -0700827 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828
829 /* row/level might become empty */
830 if ((q->row_mask[level] & (1 << prio)) == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -0700831 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832
Stephen Hemminger87990462006-08-10 23:35:16 -0700833 next = htb_lookup_leaf(q->row[level] + prio,
834 prio, q->ptr[level] + prio,
835 q->last_ptr_id[level] + prio);
836
837 if (cl == start) /* fix start if we just deleted it */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 start = next;
839 cl = next;
840 goto next;
841 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700842
843 skb = cl->un.leaf.q->dequeue(cl->un.leaf.q);
844 if (likely(skb != NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 break;
846 if (!cl->warned) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700847 printk(KERN_WARNING
848 "htb: class %X isn't work conserving ?!\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700849 cl->common.classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 cl->warned = 1;
851 }
852 q->nwc_hit++;
Stephen Hemminger87990462006-08-10 23:35:16 -0700853 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
854 ptr[0]) + prio);
855 cl = htb_lookup_leaf(q->row[level] + prio, prio,
856 q->ptr[level] + prio,
857 q->last_ptr_id[level] + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858
859 } while (cl != start);
860
861 if (likely(skb != NULL)) {
862 if ((cl->un.leaf.deficit[level] -= skb->len) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 cl->un.leaf.deficit[level] += cl->un.leaf.quantum;
Stephen Hemminger87990462006-08-10 23:35:16 -0700864 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
865 ptr[0]) + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 }
867 /* this used to be after charge_class but this constelation
868 gives us slightly better performance */
869 if (!cl->un.leaf.q->q.qlen)
Stephen Hemminger87990462006-08-10 23:35:16 -0700870 htb_deactivate(q, cl);
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700871 htb_charge_class(q, cl, level, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 }
873 return skb;
874}
875
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876static struct sk_buff *htb_dequeue(struct Qdisc *sch)
877{
878 struct sk_buff *skb = NULL;
879 struct htb_sched *q = qdisc_priv(sch);
880 int level;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700881 psched_time_t next_event;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
883 /* try to dequeue direct packets as high prio (!) to minimize cpu work */
Stephen Hemminger87990462006-08-10 23:35:16 -0700884 skb = __skb_dequeue(&q->direct_queue);
885 if (skb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 sch->flags &= ~TCQ_F_THROTTLED;
887 sch->q.qlen--;
888 return skb;
889 }
890
Stephen Hemminger87990462006-08-10 23:35:16 -0700891 if (!sch->q.qlen)
892 goto fin;
Patrick McHardy3bebcda2007-03-23 11:29:25 -0700893 q->now = psched_get_time();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894
Patrick McHardyfb983d42007-03-16 01:22:39 -0700895 next_event = q->now + 5 * PSCHED_TICKS_PER_SEC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 q->nwc_hit = 0;
897 for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
898 /* common case optimization - skip event handler quickly */
899 int m;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700900 psched_time_t event;
Stephen Hemminger87990462006-08-10 23:35:16 -0700901
Patrick McHardyfb983d42007-03-16 01:22:39 -0700902 if (q->now >= q->near_ev_cache[level]) {
903 event = htb_do_events(q, level);
Patrick McHardy2e4b3b02007-05-23 23:39:54 -0700904 if (!event)
905 event = q->now + PSCHED_TICKS_PER_SEC;
906 q->near_ev_cache[level] = event;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700907 } else
908 event = q->near_ev_cache[level];
909
910 if (event && next_event > event)
911 next_event = event;
912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 m = ~q->row_mask[level];
914 while (m != (int)(-1)) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700915 int prio = ffz(m);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 m |= 1 << prio;
Stephen Hemminger87990462006-08-10 23:35:16 -0700917 skb = htb_dequeue_tree(q, prio, level);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 if (likely(skb != NULL)) {
919 sch->q.qlen--;
920 sch->flags &= ~TCQ_F_THROTTLED;
921 goto fin;
922 }
923 }
924 }
Patrick McHardyfb983d42007-03-16 01:22:39 -0700925 sch->qstats.overlimits++;
926 qdisc_watchdog_schedule(&q->watchdog, next_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927fin:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 return skb;
929}
930
931/* try to drop from each class (by prio) until one succeed */
Stephen Hemminger87990462006-08-10 23:35:16 -0700932static unsigned int htb_drop(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933{
934 struct htb_sched *q = qdisc_priv(sch);
935 int prio;
936
937 for (prio = TC_HTB_NUMPRIO - 1; prio >= 0; prio--) {
938 struct list_head *p;
Stephen Hemminger87990462006-08-10 23:35:16 -0700939 list_for_each(p, q->drops + prio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 struct htb_class *cl = list_entry(p, struct htb_class,
941 un.leaf.drop_list);
942 unsigned int len;
Stephen Hemminger87990462006-08-10 23:35:16 -0700943 if (cl->un.leaf.q->ops->drop &&
944 (len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 sch->q.qlen--;
946 if (!cl->un.leaf.q->q.qlen)
Stephen Hemminger87990462006-08-10 23:35:16 -0700947 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 return len;
949 }
950 }
951 }
952 return 0;
953}
954
955/* reset all classes */
956/* always caled under BH & queue lock */
Stephen Hemminger87990462006-08-10 23:35:16 -0700957static void htb_reset(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958{
959 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700960 struct htb_class *cl;
961 struct hlist_node *n;
962 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700964 for (i = 0; i < q->clhash.hashsize; i++) {
965 hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 if (cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700967 memset(&cl->un.inner, 0, sizeof(cl->un.inner));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 else {
Stephen Hemminger87990462006-08-10 23:35:16 -0700969 if (cl->un.leaf.q)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 qdisc_reset(cl->un.leaf.q);
971 INIT_LIST_HEAD(&cl->un.leaf.drop_list);
972 }
973 cl->prio_activity = 0;
974 cl->cmode = HTB_CAN_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
976 }
977 }
Patrick McHardyfb983d42007-03-16 01:22:39 -0700978 qdisc_watchdog_cancel(&q->watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 __skb_queue_purge(&q->direct_queue);
980 sch->q.qlen = 0;
Stephen Hemminger87990462006-08-10 23:35:16 -0700981 memset(q->row, 0, sizeof(q->row));
982 memset(q->row_mask, 0, sizeof(q->row_mask));
983 memset(q->wait_pq, 0, sizeof(q->wait_pq));
984 memset(q->ptr, 0, sizeof(q->ptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 for (i = 0; i < TC_HTB_NUMPRIO; i++)
Stephen Hemminger87990462006-08-10 23:35:16 -0700986 INIT_LIST_HEAD(q->drops + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987}
988
Patrick McHardy27a34212008-01-23 20:35:39 -0800989static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
990 [TCA_HTB_PARMS] = { .len = sizeof(struct tc_htb_opt) },
991 [TCA_HTB_INIT] = { .len = sizeof(struct tc_htb_glob) },
992 [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
993 [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
994};
995
Patrick McHardy1e904742008-01-22 22:11:17 -0800996static int htb_init(struct Qdisc *sch, struct nlattr *opt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997{
998 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardy1e904742008-01-22 22:11:17 -0800999 struct nlattr *tb[TCA_HTB_INIT + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 struct tc_htb_glob *gopt;
Patrick McHardycee63722008-01-23 20:33:32 -08001001 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 int i;
Patrick McHardycee63722008-01-23 20:33:32 -08001003
1004 if (!opt)
1005 return -EINVAL;
1006
Patrick McHardy27a34212008-01-23 20:35:39 -08001007 err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy);
Patrick McHardycee63722008-01-23 20:33:32 -08001008 if (err < 0)
1009 return err;
1010
Patrick McHardy27a34212008-01-23 20:35:39 -08001011 if (tb[TCA_HTB_INIT] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
1013 return -EINVAL;
1014 }
Patrick McHardy1e904742008-01-22 22:11:17 -08001015 gopt = nla_data(tb[TCA_HTB_INIT]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 if (gopt->version != HTB_VER >> 16) {
Stephen Hemminger87990462006-08-10 23:35:16 -07001017 printk(KERN_ERR
1018 "HTB: need tc/htb version %d (minor is %d), you have %d\n",
1019 HTB_VER >> 16, HTB_VER & 0xffff, gopt->version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 return -EINVAL;
1021 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
1023 INIT_LIST_HEAD(&q->root);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001024 err = qdisc_class_hash_init(&q->clhash);
1025 if (err < 0)
1026 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 for (i = 0; i < TC_HTB_NUMPRIO; i++)
Stephen Hemminger87990462006-08-10 23:35:16 -07001028 INIT_LIST_HEAD(q->drops + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
Patrick McHardyfb983d42007-03-16 01:22:39 -07001030 qdisc_watchdog_init(&q->watchdog, sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 skb_queue_head_init(&q->direct_queue);
1032
1033 q->direct_qlen = sch->dev->tx_queue_len;
Stephen Hemminger87990462006-08-10 23:35:16 -07001034 if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 q->direct_qlen = 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 if ((q->rate2quantum = gopt->rate2quantum) < 1)
1038 q->rate2quantum = 1;
1039 q->defcls = gopt->defcls;
1040
1041 return 0;
1042}
1043
1044static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
1045{
1046 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001047 struct nlattr *nest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 struct tc_htb_glob gopt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001050 spin_lock_bh(&sch->dev->queue_lock);
1051
1052 gopt.direct_pkts = q->direct_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 gopt.version = HTB_VER;
1054 gopt.rate2quantum = q->rate2quantum;
1055 gopt.defcls = q->defcls;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001056 gopt.debug = 0;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001057
1058 nest = nla_nest_start(skb, TCA_OPTIONS);
1059 if (nest == NULL)
1060 goto nla_put_failure;
Patrick McHardy1e904742008-01-22 22:11:17 -08001061 NLA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001062 nla_nest_end(skb, nest);
1063
Stephen Hemminger9ac961e2006-08-10 23:33:16 -07001064 spin_unlock_bh(&sch->dev->queue_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 return skb->len;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001066
Patrick McHardy1e904742008-01-22 22:11:17 -08001067nla_put_failure:
Stephen Hemminger9ac961e2006-08-10 23:33:16 -07001068 spin_unlock_bh(&sch->dev->queue_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001069 nla_nest_cancel(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 return -1;
1071}
1072
1073static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
Stephen Hemminger87990462006-08-10 23:35:16 -07001074 struct sk_buff *skb, struct tcmsg *tcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075{
Stephen Hemminger87990462006-08-10 23:35:16 -07001076 struct htb_class *cl = (struct htb_class *)arg;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001077 struct nlattr *nest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 struct tc_htb_opt opt;
1079
Stephen Hemminger9ac961e2006-08-10 23:33:16 -07001080 spin_lock_bh(&sch->dev->queue_lock);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001081 tcm->tcm_parent = cl->parent ? cl->parent->common.classid : TC_H_ROOT;
1082 tcm->tcm_handle = cl->common.classid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 if (!cl->level && cl->un.leaf.q)
1084 tcm->tcm_info = cl->un.leaf.q->handle;
1085
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001086 nest = nla_nest_start(skb, TCA_OPTIONS);
1087 if (nest == NULL)
1088 goto nla_put_failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
Stephen Hemminger87990462006-08-10 23:35:16 -07001090 memset(&opt, 0, sizeof(opt));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
Stephen Hemminger87990462006-08-10 23:35:16 -07001092 opt.rate = cl->rate->rate;
1093 opt.buffer = cl->buffer;
1094 opt.ceil = cl->ceil->rate;
1095 opt.cbuffer = cl->cbuffer;
1096 opt.quantum = cl->un.leaf.quantum;
1097 opt.prio = cl->un.leaf.prio;
1098 opt.level = cl->level;
Patrick McHardy1e904742008-01-22 22:11:17 -08001099 NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001100
1101 nla_nest_end(skb, nest);
Stephen Hemminger9ac961e2006-08-10 23:33:16 -07001102 spin_unlock_bh(&sch->dev->queue_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 return skb->len;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001104
Patrick McHardy1e904742008-01-22 22:11:17 -08001105nla_put_failure:
Stephen Hemminger9ac961e2006-08-10 23:33:16 -07001106 spin_unlock_bh(&sch->dev->queue_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001107 nla_nest_cancel(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 return -1;
1109}
1110
1111static int
Stephen Hemminger87990462006-08-10 23:35:16 -07001112htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113{
Stephen Hemminger87990462006-08-10 23:35:16 -07001114 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 if (!cl->level && cl->un.leaf.q)
1117 cl->qstats.qlen = cl->un.leaf.q->q.qlen;
1118 cl->xstats.tokens = cl->tokens;
1119 cl->xstats.ctokens = cl->ctokens;
1120
1121 if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
1122 gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
1123 gnet_stats_copy_queue(d, &cl->qstats) < 0)
1124 return -1;
1125
1126 return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
1127}
1128
1129static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
Stephen Hemminger87990462006-08-10 23:35:16 -07001130 struct Qdisc **old)
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
1134 if (cl && !cl->level) {
Patrick McHardy9f9afec2006-11-29 17:35:18 -08001135 if (new == NULL &&
1136 (new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001137 cl->common.classid))
Stephen Hemminger87990462006-08-10 23:35:16 -07001138 == NULL)
1139 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 sch_tree_lock(sch);
1141 if ((*old = xchg(&cl->un.leaf.q, new)) != NULL) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001142 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 qdisc_reset(*old);
1144 }
1145 sch_tree_unlock(sch);
1146 return 0;
1147 }
1148 return -ENOENT;
1149}
1150
Stephen Hemminger87990462006-08-10 23:35:16 -07001151static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152{
Stephen Hemminger87990462006-08-10 23:35:16 -07001153 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 return (cl && !cl->level) ? cl->un.leaf.q : NULL;
1155}
1156
Patrick McHardy256d61b2006-11-29 17:37:05 -08001157static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg)
1158{
1159 struct htb_class *cl = (struct htb_class *)arg;
1160
1161 if (cl->un.leaf.q->q.qlen == 0)
1162 htb_deactivate(qdisc_priv(sch), cl);
1163}
1164
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165static unsigned long htb_get(struct Qdisc *sch, u32 classid)
1166{
Stephen Hemminger87990462006-08-10 23:35:16 -07001167 struct htb_class *cl = htb_find(classid, sch);
1168 if (cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 cl->refcnt++;
1170 return (unsigned long)cl;
1171}
1172
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001173static inline int htb_parent_last_child(struct htb_class *cl)
1174{
1175 if (!cl->parent)
1176 /* the root class */
1177 return 0;
1178
1179 if (!(cl->parent->children.next == &cl->sibling &&
1180 cl->parent->children.prev == &cl->sibling))
1181 /* not the last child */
1182 return 0;
1183
1184 return 1;
1185}
1186
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001187static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
1188 struct Qdisc *new_q)
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001189{
1190 struct htb_class *parent = cl->parent;
1191
1192 BUG_TRAP(!cl->level && cl->un.leaf.q && !cl->prio_activity);
1193
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001194 if (parent->cmode != HTB_CAN_SEND)
1195 htb_safe_rb_erase(&parent->pq_node, q->wait_pq + parent->level);
1196
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001197 parent->level = 0;
1198 memset(&parent->un.inner, 0, sizeof(parent->un.inner));
1199 INIT_LIST_HEAD(&parent->un.leaf.drop_list);
1200 parent->un.leaf.q = new_q ? new_q : &noop_qdisc;
1201 parent->un.leaf.quantum = parent->quantum;
1202 parent->un.leaf.prio = parent->prio;
1203 parent->tokens = parent->buffer;
1204 parent->ctokens = parent->cbuffer;
Patrick McHardy3bebcda2007-03-23 11:29:25 -07001205 parent->t_c = psched_get_time();
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001206 parent->cmode = HTB_CAN_SEND;
1207}
1208
Stephen Hemminger87990462006-08-10 23:35:16 -07001209static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 if (!cl->level) {
1212 BUG_TRAP(cl->un.leaf.q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 qdisc_destroy(cl->un.leaf.q);
1214 }
Patrick McHardyee39e102007-07-02 22:48:13 -07001215 gen_kill_estimator(&cl->bstats, &cl->rate_est);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 qdisc_put_rtab(cl->rate);
1217 qdisc_put_rtab(cl->ceil);
Stephen Hemminger87990462006-08-10 23:35:16 -07001218
Patrick McHardyff31ab52008-07-01 19:52:38 -07001219 tcf_destroy_chain(&cl->filter_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 kfree(cl);
1221}
1222
1223/* always caled under BH & queue lock */
Stephen Hemminger87990462006-08-10 23:35:16 -07001224static void htb_destroy(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225{
1226 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001227 struct hlist_node *n, *next;
1228 struct htb_class *cl;
1229 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
Patrick McHardyfb983d42007-03-16 01:22:39 -07001231 qdisc_watchdog_cancel(&q->watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 /* This line used to be after htb_destroy_class call below
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +09001233 and surprisingly it worked in 2.4. But it must precede it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 because filter need its target class alive to be able to call
1235 unbind_filter on it (without Oops). */
Patrick McHardyff31ab52008-07-01 19:52:38 -07001236 tcf_destroy_chain(&q->filter_list);
Stephen Hemminger87990462006-08-10 23:35:16 -07001237
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001238 for (i = 0; i < q->clhash.hashsize; i++) {
1239 hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode)
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001240 tcf_destroy_chain(&cl->filter_list);
1241 }
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001242 for (i = 0; i < q->clhash.hashsize; i++) {
1243 hlist_for_each_entry_safe(cl, n, next, &q->clhash.hash[i],
1244 common.hnode)
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001245 htb_destroy_class(sch, cl);
1246 }
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001247 qdisc_class_hash_destroy(&q->clhash);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 __skb_queue_purge(&q->direct_queue);
1249}
1250
1251static int htb_delete(struct Qdisc *sch, unsigned long arg)
1252{
1253 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001254 struct htb_class *cl = (struct htb_class *)arg;
Patrick McHardy256d61b2006-11-29 17:37:05 -08001255 unsigned int qlen;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001256 struct Qdisc *new_q = NULL;
1257 int last_child = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
1259 // TODO: why don't allow to delete subtree ? references ? does
1260 // tc subsys quarantee us that in htb_destroy it holds no class
1261 // refs so that we can remove children safely there ?
1262 if (!list_empty(&cl->children) || cl->filter_cnt)
1263 return -EBUSY;
Stephen Hemminger87990462006-08-10 23:35:16 -07001264
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001265 if (!cl->level && htb_parent_last_child(cl)) {
1266 new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001267 cl->parent->common.classid);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001268 last_child = 1;
1269 }
1270
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 sch_tree_lock(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001272
Patrick McHardy814a175e2006-11-29 17:34:50 -08001273 if (!cl->level) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001274 qlen = cl->un.leaf.q->q.qlen;
Patrick McHardy814a175e2006-11-29 17:34:50 -08001275 qdisc_reset(cl->un.leaf.q);
Patrick McHardy256d61b2006-11-29 17:37:05 -08001276 qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen);
Patrick McHardy814a175e2006-11-29 17:34:50 -08001277 }
1278
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001279 /* delete from hash and active; remainder in destroy_class */
1280 qdisc_class_hash_remove(&q->clhash, &cl->common);
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001281 list_del(&cl->sibling);
Patrick McHardyc38c83c2007-03-27 14:04:24 -07001282
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 if (cl->prio_activity)
Stephen Hemminger87990462006-08-10 23:35:16 -07001284 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001286 if (cl->cmode != HTB_CAN_SEND)
1287 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
1288
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001289 if (last_child)
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001290 htb_parent_to_leaf(q, cl, new_q);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001291
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 if (--cl->refcnt == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -07001293 htb_destroy_class(sch, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294
1295 sch_tree_unlock(sch);
1296 return 0;
1297}
1298
1299static void htb_put(struct Qdisc *sch, unsigned long arg)
1300{
Stephen Hemminger87990462006-08-10 23:35:16 -07001301 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302
1303 if (--cl->refcnt == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -07001304 htb_destroy_class(sch, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305}
1306
Stephen Hemminger87990462006-08-10 23:35:16 -07001307static int htb_change_class(struct Qdisc *sch, u32 classid,
Patrick McHardy1e904742008-01-22 22:11:17 -08001308 u32 parentid, struct nlattr **tca,
Stephen Hemminger87990462006-08-10 23:35:16 -07001309 unsigned long *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310{
1311 int err = -EINVAL;
1312 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001313 struct htb_class *cl = (struct htb_class *)*arg, *parent;
Patrick McHardy1e904742008-01-22 22:11:17 -08001314 struct nlattr *opt = tca[TCA_OPTIONS];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
Patrick McHardy1e904742008-01-22 22:11:17 -08001316 struct nlattr *tb[TCA_HTB_RTAB + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 struct tc_htb_opt *hopt;
1318
1319 /* extract all subattrs from opt attr */
Patrick McHardycee63722008-01-23 20:33:32 -08001320 if (!opt)
1321 goto failure;
1322
Patrick McHardy27a34212008-01-23 20:35:39 -08001323 err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, htb_policy);
Patrick McHardycee63722008-01-23 20:33:32 -08001324 if (err < 0)
1325 goto failure;
1326
1327 err = -EINVAL;
Patrick McHardy27a34212008-01-23 20:35:39 -08001328 if (tb[TCA_HTB_PARMS] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 goto failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
Stephen Hemminger87990462006-08-10 23:35:16 -07001331 parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001332
Patrick McHardy1e904742008-01-22 22:11:17 -08001333 hopt = nla_data(tb[TCA_HTB_PARMS]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
Patrick McHardy1e904742008-01-22 22:11:17 -08001335 rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]);
1336 ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]);
Stephen Hemminger87990462006-08-10 23:35:16 -07001337 if (!rtab || !ctab)
1338 goto failure;
1339
1340 if (!cl) { /* new class */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 struct Qdisc *new_q;
Stephen Hemminger3696f622006-08-10 23:36:01 -07001342 int prio;
Patrick McHardyee39e102007-07-02 22:48:13 -07001343 struct {
Patrick McHardy1e904742008-01-22 22:11:17 -08001344 struct nlattr nla;
Patrick McHardyee39e102007-07-02 22:48:13 -07001345 struct gnet_estimator opt;
1346 } est = {
Patrick McHardy1e904742008-01-22 22:11:17 -08001347 .nla = {
1348 .nla_len = nla_attr_size(sizeof(est.opt)),
1349 .nla_type = TCA_RATE,
Patrick McHardyee39e102007-07-02 22:48:13 -07001350 },
1351 .opt = {
1352 /* 4s interval, 16s averaging constant */
1353 .interval = 2,
1354 .ewma_log = 2,
1355 },
1356 };
Stephen Hemminger3696f622006-08-10 23:36:01 -07001357
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 /* check for valid classid */
Stephen Hemminger87990462006-08-10 23:35:16 -07001359 if (!classid || TC_H_MAJ(classid ^ sch->handle)
1360 || htb_find(classid, sch))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 goto failure;
1362
1363 /* check maximal depth */
1364 if (parent && parent->parent && parent->parent->level < 2) {
1365 printk(KERN_ERR "htb: tree is too deep\n");
1366 goto failure;
1367 }
1368 err = -ENOBUFS;
Panagiotis Issaris0da974f2006-07-21 14:51:30 -07001369 if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 goto failure;
Stephen Hemminger87990462006-08-10 23:35:16 -07001371
Patrick McHardyee39e102007-07-02 22:48:13 -07001372 gen_new_estimator(&cl->bstats, &cl->rate_est,
1373 &sch->dev->queue_lock,
Patrick McHardy1e904742008-01-22 22:11:17 -08001374 tca[TCA_RATE] ? : &est.nla);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 cl->refcnt = 1;
1376 INIT_LIST_HEAD(&cl->sibling);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 INIT_LIST_HEAD(&cl->children);
1378 INIT_LIST_HEAD(&cl->un.leaf.drop_list);
Stephen Hemminger3696f622006-08-10 23:36:01 -07001379 RB_CLEAR_NODE(&cl->pq_node);
1380
1381 for (prio = 0; prio < TC_HTB_NUMPRIO; prio++)
1382 RB_CLEAR_NODE(&cl->node[prio]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383
1384 /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
1385 so that can't be used inside of sch_tree_lock
1386 -- thanks to Karlis Peisenieks */
Patrick McHardy9f9afec2006-11-29 17:35:18 -08001387 new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 sch_tree_lock(sch);
1389 if (parent && !parent->level) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001390 unsigned int qlen = parent->un.leaf.q->q.qlen;
1391
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 /* turn parent into inner node */
Patrick McHardy256d61b2006-11-29 17:37:05 -08001393 qdisc_reset(parent->un.leaf.q);
1394 qdisc_tree_decrease_qlen(parent->un.leaf.q, qlen);
Stephen Hemminger87990462006-08-10 23:35:16 -07001395 qdisc_destroy(parent->un.leaf.q);
1396 if (parent->prio_activity)
1397 htb_deactivate(q, parent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
1399 /* remove from evt list because of level change */
1400 if (parent->cmode != HTB_CAN_SEND) {
Stephen Hemminger3696f622006-08-10 23:36:01 -07001401 htb_safe_rb_erase(&parent->pq_node, q->wait_pq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 parent->cmode = HTB_CAN_SEND;
1403 }
1404 parent->level = (parent->parent ? parent->parent->level
Stephen Hemminger87990462006-08-10 23:35:16 -07001405 : TC_HTB_MAXDEPTH) - 1;
1406 memset(&parent->un.inner, 0, sizeof(parent->un.inner));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 }
1408 /* leaf (we) needs elementary qdisc */
1409 cl->un.leaf.q = new_q ? new_q : &noop_qdisc;
1410
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001411 cl->common.classid = classid;
Stephen Hemminger87990462006-08-10 23:35:16 -07001412 cl->parent = parent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
1414 /* set class to be in HTB_CAN_SEND state */
1415 cl->tokens = hopt->buffer;
1416 cl->ctokens = hopt->cbuffer;
Patrick McHardy00c04af2007-03-16 01:23:02 -07001417 cl->mbuffer = 60 * PSCHED_TICKS_PER_SEC; /* 1min */
Patrick McHardy3bebcda2007-03-23 11:29:25 -07001418 cl->t_c = psched_get_time();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 cl->cmode = HTB_CAN_SEND;
1420
1421 /* attach to the hash list and parent's family */
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001422 qdisc_class_hash_insert(&q->clhash, &cl->common);
Stephen Hemminger87990462006-08-10 23:35:16 -07001423 list_add_tail(&cl->sibling,
1424 parent ? &parent->children : &q->root);
Patrick McHardyee39e102007-07-02 22:48:13 -07001425 } else {
Patrick McHardy1e904742008-01-22 22:11:17 -08001426 if (tca[TCA_RATE])
Patrick McHardyee39e102007-07-02 22:48:13 -07001427 gen_replace_estimator(&cl->bstats, &cl->rate_est,
1428 &sch->dev->queue_lock,
Patrick McHardy1e904742008-01-22 22:11:17 -08001429 tca[TCA_RATE]);
Stephen Hemminger87990462006-08-10 23:35:16 -07001430 sch_tree_lock(sch);
Patrick McHardyee39e102007-07-02 22:48:13 -07001431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432
1433 /* it used to be a nasty bug here, we have to check that node
Stephen Hemminger87990462006-08-10 23:35:16 -07001434 is really leaf before changing cl->un.leaf ! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 if (!cl->level) {
1436 cl->un.leaf.quantum = rtab->rate.rate / q->rate2quantum;
1437 if (!hopt->quantum && cl->un.leaf.quantum < 1000) {
Stephen Hemminger87990462006-08-10 23:35:16 -07001438 printk(KERN_WARNING
1439 "HTB: quantum of class %X is small. Consider r2q change.\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001440 cl->common.classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 cl->un.leaf.quantum = 1000;
1442 }
1443 if (!hopt->quantum && cl->un.leaf.quantum > 200000) {
Stephen Hemminger87990462006-08-10 23:35:16 -07001444 printk(KERN_WARNING
1445 "HTB: quantum of class %X is big. Consider r2q change.\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001446 cl->common.classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 cl->un.leaf.quantum = 200000;
1448 }
1449 if (hopt->quantum)
1450 cl->un.leaf.quantum = hopt->quantum;
1451 if ((cl->un.leaf.prio = hopt->prio) >= TC_HTB_NUMPRIO)
1452 cl->un.leaf.prio = TC_HTB_NUMPRIO - 1;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001453
1454 /* backup for htb_parent_to_leaf */
1455 cl->quantum = cl->un.leaf.quantum;
1456 cl->prio = cl->un.leaf.prio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 }
1458
1459 cl->buffer = hopt->buffer;
1460 cl->cbuffer = hopt->cbuffer;
Stephen Hemminger87990462006-08-10 23:35:16 -07001461 if (cl->rate)
1462 qdisc_put_rtab(cl->rate);
1463 cl->rate = rtab;
1464 if (cl->ceil)
1465 qdisc_put_rtab(cl->ceil);
1466 cl->ceil = ctab;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 sch_tree_unlock(sch);
1468
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001469 qdisc_class_hash_grow(sch, &q->clhash);
1470
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 *arg = (unsigned long)cl;
1472 return 0;
1473
1474failure:
Stephen Hemminger87990462006-08-10 23:35:16 -07001475 if (rtab)
1476 qdisc_put_rtab(rtab);
1477 if (ctab)
1478 qdisc_put_rtab(ctab);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 return err;
1480}
1481
1482static struct tcf_proto **htb_find_tcf(struct Qdisc *sch, unsigned long arg)
1483{
1484 struct htb_sched *q = qdisc_priv(sch);
1485 struct htb_class *cl = (struct htb_class *)arg;
1486 struct tcf_proto **fl = cl ? &cl->filter_list : &q->filter_list;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001487
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 return fl;
1489}
1490
1491static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent,
Stephen Hemminger87990462006-08-10 23:35:16 -07001492 u32 classid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493{
1494 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001495 struct htb_class *cl = htb_find(classid, sch);
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001496
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 /*if (cl && !cl->level) return 0;
Stephen Hemminger87990462006-08-10 23:35:16 -07001498 The line above used to be there to prevent attaching filters to
1499 leaves. But at least tc_index filter uses this just to get class
1500 for other reasons so that we have to allow for it.
1501 ----
1502 19.6.2002 As Werner explained it is ok - bind filter is just
1503 another way to "lock" the class - unlike "get" this lock can
1504 be broken by class during destroy IIUC.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 */
Stephen Hemminger87990462006-08-10 23:35:16 -07001506 if (cl)
1507 cl->filter_cnt++;
1508 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 q->filter_cnt++;
1510 return (unsigned long)cl;
1511}
1512
1513static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg)
1514{
1515 struct htb_sched *q = qdisc_priv(sch);
1516 struct htb_class *cl = (struct htb_class *)arg;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001517
Stephen Hemminger87990462006-08-10 23:35:16 -07001518 if (cl)
1519 cl->filter_cnt--;
1520 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 q->filter_cnt--;
1522}
1523
1524static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg)
1525{
1526 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001527 struct htb_class *cl;
1528 struct hlist_node *n;
1529 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530
1531 if (arg->stop)
1532 return;
1533
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001534 for (i = 0; i < q->clhash.hashsize; i++) {
1535 hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 if (arg->count < arg->skip) {
1537 arg->count++;
1538 continue;
1539 }
1540 if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
1541 arg->stop = 1;
1542 return;
1543 }
1544 arg->count++;
1545 }
1546 }
1547}
1548
Eric Dumazet20fea082007-11-14 01:44:41 -08001549static const struct Qdisc_class_ops htb_class_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 .graft = htb_graft,
1551 .leaf = htb_leaf,
Patrick McHardy256d61b2006-11-29 17:37:05 -08001552 .qlen_notify = htb_qlen_notify,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 .get = htb_get,
1554 .put = htb_put,
1555 .change = htb_change_class,
1556 .delete = htb_delete,
1557 .walk = htb_walk,
1558 .tcf_chain = htb_find_tcf,
1559 .bind_tcf = htb_bind_filter,
1560 .unbind_tcf = htb_unbind_filter,
1561 .dump = htb_dump_class,
1562 .dump_stats = htb_dump_class_stats,
1563};
1564
Eric Dumazet20fea082007-11-14 01:44:41 -08001565static struct Qdisc_ops htb_qdisc_ops __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 .next = NULL,
1567 .cl_ops = &htb_class_ops,
1568 .id = "htb",
1569 .priv_size = sizeof(struct htb_sched),
1570 .enqueue = htb_enqueue,
1571 .dequeue = htb_dequeue,
1572 .requeue = htb_requeue,
1573 .drop = htb_drop,
1574 .init = htb_init,
1575 .reset = htb_reset,
1576 .destroy = htb_destroy,
1577 .change = NULL /* htb_change */,
1578 .dump = htb_dump,
1579 .owner = THIS_MODULE,
1580};
1581
1582static int __init htb_module_init(void)
1583{
Stephen Hemminger87990462006-08-10 23:35:16 -07001584 return register_qdisc(&htb_qdisc_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585}
Stephen Hemminger87990462006-08-10 23:35:16 -07001586static void __exit htb_module_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587{
Stephen Hemminger87990462006-08-10 23:35:16 -07001588 unregister_qdisc(&htb_qdisc_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589}
Stephen Hemminger87990462006-08-10 23:35:16 -07001590
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591module_init(htb_module_init)
1592module_exit(htb_module_exit)
1593MODULE_LICENSE("GPL");