blob: 80cb94d9c29920291dff04eec6b99892288d82f0 [file] [log] [blame]
Stephen Hemminger87990462006-08-10 23:35:16 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * net/sched/sch_htb.c Hierarchical token bucket, feed tree version
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Martin Devera, <devik@cdi.cz>
10 *
11 * Credits (in time order) for older HTB versions:
12 * Stef Coene <stef.coene@docum.org>
13 * HTB support at LARTC mailing list
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +090014 * Ondrej Kraus, <krauso@barr.cz>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 * found missing INIT_QDISC(htb)
16 * Vladimir Smelhaus, Aamer Akhter, Bert Hubert
17 * helped a lot to locate nasty class stall bug
18 * Andi Kleen, Jamal Hadi, Bert Hubert
19 * code review and helpful comments on shaping
20 * Tomasz Wrona, <tw@eter.tym.pl>
21 * created test case so that I was able to fix nasty bug
22 * Wilfried Weissmann
23 * spotted bug in dequeue code and helped with fix
24 * Jiri Fojtasek
25 * fixed requeue routine
26 * and many others. thanks.
Linus Torvalds1da177e2005-04-16 15:20:36 -070027 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/module.h>
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -070029#include <linux/moduleparam.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/types.h>
31#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/string.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/skbuff.h>
35#include <linux/list.h>
36#include <linux/compiler.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/rbtree.h>
Patrick McHardy0ba48052007-07-02 22:49:07 -070038#include <net/netlink.h>
39#include <net/pkt_sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
41/* HTB algorithm.
42 Author: devik@cdi.cz
43 ========================================================================
44 HTB is like TBF with multiple classes. It is also similar to CBQ because
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +090045 it allows to assign priority to each class in hierarchy.
Linus Torvalds1da177e2005-04-16 15:20:36 -070046 In fact it is another implementation of Floyd's formal sharing.
47
48 Levels:
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +090049 Each class is assigned level. Leaf has ALWAYS level 0 and root
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 classes have level TC_HTB_MAXDEPTH-1. Interior nodes has level
51 one less than their parent.
52*/
53
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -070054static int htb_hysteresis __read_mostly = 0; /* whether to use mode hysteresis for speedup */
Stephen Hemminger87990462006-08-10 23:35:16 -070055#define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57#if HTB_VER >> 16 != TC_HTB_PROTOVER
58#error "Mismatched sch_htb.c and pkt_sch.h"
59#endif
60
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -070061/* Module parameter and sysfs export */
62module_param (htb_hysteresis, int, 0640);
63MODULE_PARM_DESC(htb_hysteresis, "Hysteresis mode, less CPU load, less accurate");
64
Linus Torvalds1da177e2005-04-16 15:20:36 -070065/* used internaly to keep status of single class */
66enum htb_cmode {
Stephen Hemminger87990462006-08-10 23:35:16 -070067 HTB_CANT_SEND, /* class can't send and can't borrow */
68 HTB_MAY_BORROW, /* class can't send but may borrow */
69 HTB_CAN_SEND /* class can send */
Linus Torvalds1da177e2005-04-16 15:20:36 -070070};
71
72/* interior & leaf nodes; props specific to leaves are marked L: */
Stephen Hemminger87990462006-08-10 23:35:16 -070073struct htb_class {
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -070074 struct Qdisc_class_common common;
Stephen Hemminger87990462006-08-10 23:35:16 -070075 /* general class parameters */
Stephen Hemminger87990462006-08-10 23:35:16 -070076 struct gnet_stats_basic bstats;
77 struct gnet_stats_queue qstats;
78 struct gnet_stats_rate_est rate_est;
79 struct tc_htb_xstats xstats; /* our special stats */
80 int refcnt; /* usage count of this class */
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
Stephen Hemminger87990462006-08-10 23:35:16 -070082 /* topology */
83 int level; /* our level (see above) */
Patrick McHardy42077592008-07-05 23:22:53 -070084 unsigned int children;
Stephen Hemminger87990462006-08-10 23:35:16 -070085 struct htb_class *parent; /* parent class */
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
Jarek Poplawskic19f7a32008-12-03 21:09:45 -080087 int prio; /* these two are used only by leaves... */
88 int quantum; /* but stored for parent-to-leaf return */
89
Stephen Hemminger87990462006-08-10 23:35:16 -070090 union {
91 struct htb_class_leaf {
92 struct Qdisc *q;
Stephen Hemminger87990462006-08-10 23:35:16 -070093 int deficit[TC_HTB_MAXDEPTH];
94 struct list_head drop_list;
95 } leaf;
96 struct htb_class_inner {
97 struct rb_root feed[TC_HTB_NUMPRIO]; /* feed trees */
98 struct rb_node *ptr[TC_HTB_NUMPRIO]; /* current class ptr */
99 /* When class changes from state 1->2 and disconnects from
100 parent's feed then we lost ptr value and start from the
101 first child again. Here we store classid of the
102 last valid ptr (used when ptr is NULL). */
103 u32 last_ptr_id[TC_HTB_NUMPRIO];
104 } inner;
105 } un;
106 struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */
107 struct rb_node pq_node; /* node for event queue */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700108 psched_time_t pq_key;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
Stephen Hemminger87990462006-08-10 23:35:16 -0700110 int prio_activity; /* for which prios are we active */
111 enum htb_cmode cmode; /* current mode of the class */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
Stephen Hemminger87990462006-08-10 23:35:16 -0700113 /* class attached filters */
114 struct tcf_proto *filter_list;
115 int filter_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
Stephen Hemminger87990462006-08-10 23:35:16 -0700117 int warned; /* only one warning about non work conserving .. */
118
119 /* token bucket parameters */
120 struct qdisc_rate_table *rate; /* rate table of the class itself */
121 struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */
122 long buffer, cbuffer; /* token bucket depth/rate */
123 psched_tdiff_t mbuffer; /* max wait time */
124 long tokens, ctokens; /* current number of tokens */
125 psched_time_t t_c; /* checkpoint time */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126};
127
Stephen Hemminger87990462006-08-10 23:35:16 -0700128static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate,
129 int size)
130{
Jesper Dangaard Brouere9bef552007-09-12 16:35:24 +0200131 long result = qdisc_l2t(rate, size);
132 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133}
134
Stephen Hemminger87990462006-08-10 23:35:16 -0700135struct htb_sched {
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700136 struct Qdisc_class_hash clhash;
Stephen Hemminger0cef2962006-08-10 23:35:38 -0700137 struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
Stephen Hemminger87990462006-08-10 23:35:16 -0700139 /* self list - roots of self generating tree */
140 struct rb_root row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
141 int row_mask[TC_HTB_MAXDEPTH];
142 struct rb_node *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
143 u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
Stephen Hemminger87990462006-08-10 23:35:16 -0700145 /* self wait list - roots of wait PQs per row */
146 struct rb_root wait_pq[TC_HTB_MAXDEPTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
Stephen Hemminger87990462006-08-10 23:35:16 -0700148 /* time of nearest event per level (row) */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700149 psched_time_t near_ev_cache[TC_HTB_MAXDEPTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Stephen Hemminger87990462006-08-10 23:35:16 -0700151 int defcls; /* class where unclassified flows go to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152
Stephen Hemminger87990462006-08-10 23:35:16 -0700153 /* filters for qdisc itself */
154 struct tcf_proto *filter_list;
Stephen Hemminger87990462006-08-10 23:35:16 -0700155
156 int rate2quantum; /* quant = rate / rate2quantum */
157 psched_time_t now; /* cached dequeue time */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700158 struct qdisc_watchdog watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
Stephen Hemminger87990462006-08-10 23:35:16 -0700160 /* non shaped skbs; let them go directly thru */
161 struct sk_buff_head direct_queue;
162 int direct_qlen; /* max qlen of above */
163
164 long direct_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165};
166
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167/* find class in global hash table using given handle */
Stephen Hemminger87990462006-08-10 23:35:16 -0700168static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169{
170 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700171 struct Qdisc_class_common *clc;
Stephen Hemminger0cef2962006-08-10 23:35:38 -0700172
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700173 clc = qdisc_class_find(&q->clhash, handle);
174 if (clc == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 return NULL;
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700176 return container_of(clc, struct htb_class, common);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177}
178
179/**
180 * htb_classify - classify a packet into class
181 *
182 * It returns NULL if the packet should be dropped or -1 if the packet
183 * should be passed directly thru. In all other cases leaf class is returned.
184 * We allow direct class selection by classid in priority. The we examine
185 * filters in qdisc and in inner nodes (if higher filter points to the inner
186 * node). If we end up with classid MAJOR:0 we enqueue the skb into special
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900187 * internal fifo (direct). These packets then go directly thru. If we still
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessfull
189 * then finish and return direct queue.
190 */
191#define HTB_DIRECT (struct htb_class*)-1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
Stephen Hemminger87990462006-08-10 23:35:16 -0700193static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
194 int *qerr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195{
196 struct htb_sched *q = qdisc_priv(sch);
197 struct htb_class *cl;
198 struct tcf_result res;
199 struct tcf_proto *tcf;
200 int result;
201
202 /* allow to select class by setting skb->priority to valid classid;
203 note that nfmark can be used too by attaching filter fw with no
204 rules in it */
205 if (skb->priority == sch->handle)
Stephen Hemminger87990462006-08-10 23:35:16 -0700206 return HTB_DIRECT; /* X:0 (direct flow) selected */
207 if ((cl = htb_find(skb->priority, sch)) != NULL && cl->level == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 return cl;
209
Jarek Poplawskic27f3392008-08-04 22:39:11 -0700210 *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 tcf = q->filter_list;
212 while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
213#ifdef CONFIG_NET_CLS_ACT
214 switch (result) {
215 case TC_ACT_QUEUED:
Stephen Hemminger87990462006-08-10 23:35:16 -0700216 case TC_ACT_STOLEN:
Jarek Poplawski378a2f02008-08-04 22:31:03 -0700217 *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 case TC_ACT_SHOT:
219 return NULL;
220 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221#endif
Stephen Hemminger87990462006-08-10 23:35:16 -0700222 if ((cl = (void *)res.class) == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 if (res.classid == sch->handle)
Stephen Hemminger87990462006-08-10 23:35:16 -0700224 return HTB_DIRECT; /* X:0 (direct flow) */
225 if ((cl = htb_find(res.classid, sch)) == NULL)
226 break; /* filter selected invalid classid */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 }
228 if (!cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700229 return cl; /* we hit leaf; return it */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
231 /* we have got inner class; apply inner filter chain */
232 tcf = cl->filter_list;
233 }
234 /* classification failed; try to use default class */
Stephen Hemminger87990462006-08-10 23:35:16 -0700235 cl = htb_find(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 if (!cl || cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700237 return HTB_DIRECT; /* bad default .. this is safe bet */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 return cl;
239}
240
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241/**
242 * htb_add_to_id_tree - adds class to the round robin list
243 *
244 * Routine adds class to the list (actually tree) sorted by classid.
245 * Make sure that class is not already on such list for given prio.
246 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700247static void htb_add_to_id_tree(struct rb_root *root,
248 struct htb_class *cl, int prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249{
250 struct rb_node **p = &root->rb_node, *parent = NULL;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700251
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 while (*p) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700253 struct htb_class *c;
254 parent = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 c = rb_entry(parent, struct htb_class, node[prio]);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700256
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700257 if (cl->common.classid > c->common.classid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 p = &parent->rb_right;
Stephen Hemminger87990462006-08-10 23:35:16 -0700259 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 p = &parent->rb_left;
261 }
262 rb_link_node(&cl->node[prio], parent, p);
263 rb_insert_color(&cl->node[prio], root);
264}
265
266/**
267 * htb_add_to_wait_tree - adds class to the event queue with delay
268 *
269 * The class is added to priority event queue to indicate that class will
270 * change its mode in cl->pq_key microseconds. Make sure that class is not
271 * already in the queue.
272 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700273static void htb_add_to_wait_tree(struct htb_sched *q,
274 struct htb_class *cl, long delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275{
276 struct rb_node **p = &q->wait_pq[cl->level].rb_node, *parent = NULL;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700277
Patrick McHardyfb983d42007-03-16 01:22:39 -0700278 cl->pq_key = q->now + delay;
279 if (cl->pq_key == q->now)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 cl->pq_key++;
281
282 /* update the nearest event cache */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700283 if (q->near_ev_cache[cl->level] > cl->pq_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 q->near_ev_cache[cl->level] = cl->pq_key;
Stephen Hemminger87990462006-08-10 23:35:16 -0700285
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 while (*p) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700287 struct htb_class *c;
288 parent = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 c = rb_entry(parent, struct htb_class, pq_node);
Patrick McHardyfb983d42007-03-16 01:22:39 -0700290 if (cl->pq_key >= c->pq_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 p = &parent->rb_right;
Stephen Hemminger87990462006-08-10 23:35:16 -0700292 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 p = &parent->rb_left;
294 }
295 rb_link_node(&cl->pq_node, parent, p);
296 rb_insert_color(&cl->pq_node, &q->wait_pq[cl->level]);
297}
298
299/**
300 * htb_next_rb_node - finds next node in binary tree
301 *
302 * When we are past last key we return NULL.
303 * Average complexity is 2 steps per call.
304 */
Stephen Hemminger3696f622006-08-10 23:36:01 -0700305static inline void htb_next_rb_node(struct rb_node **n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306{
307 *n = rb_next(*n);
308}
309
310/**
311 * htb_add_class_to_row - add class to its row
312 *
313 * The class is added to row at priorities marked in mask.
314 * It does nothing if mask == 0.
315 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700316static inline void htb_add_class_to_row(struct htb_sched *q,
317 struct htb_class *cl, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 q->row_mask[cl->level] |= mask;
320 while (mask) {
321 int prio = ffz(~mask);
322 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700323 htb_add_to_id_tree(q->row[cl->level] + prio, cl, prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 }
325}
326
Stephen Hemminger3696f622006-08-10 23:36:01 -0700327/* If this triggers, it is a bug in this code, but it need not be fatal */
328static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root)
329{
Ismail Donmez81771b32006-10-03 13:49:10 -0700330 if (RB_EMPTY_NODE(rb)) {
Stephen Hemminger3696f622006-08-10 23:36:01 -0700331 WARN_ON(1);
332 } else {
333 rb_erase(rb, root);
334 RB_CLEAR_NODE(rb);
335 }
336}
337
338
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339/**
340 * htb_remove_class_from_row - removes class from its row
341 *
342 * The class is removed from row at priorities marked in mask.
343 * It does nothing if mask == 0.
344 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700345static inline void htb_remove_class_from_row(struct htb_sched *q,
346 struct htb_class *cl, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347{
348 int m = 0;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 while (mask) {
351 int prio = ffz(~mask);
Stephen Hemminger3696f622006-08-10 23:36:01 -0700352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700354 if (q->ptr[cl->level][prio] == cl->node + prio)
355 htb_next_rb_node(q->ptr[cl->level] + prio);
Stephen Hemminger3696f622006-08-10 23:36:01 -0700356
357 htb_safe_rb_erase(cl->node + prio, q->row[cl->level] + prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700358 if (!q->row[cl->level][prio].rb_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 m |= 1 << prio;
360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 q->row_mask[cl->level] &= ~m;
362}
363
364/**
365 * htb_activate_prios - creates active classe's feed chain
366 *
367 * The class is connected to ancestors and/or appropriate rows
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900368 * for priorities it is participating on. cl->cmode must be new
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 * (activated) mode. It does nothing if cl->prio_activity == 0.
370 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700371static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372{
373 struct htb_class *p = cl->parent;
Stephen Hemminger87990462006-08-10 23:35:16 -0700374 long m, mask = cl->prio_activity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
376 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700377 m = mask;
378 while (m) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 int prio = ffz(~m);
380 m &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700381
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 if (p->un.inner.feed[prio].rb_node)
383 /* parent already has its feed in use so that
384 reset bit in mask as parent is already ok */
385 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700386
387 htb_add_to_id_tree(p->un.inner.feed + prio, cl, prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 p->prio_activity |= mask;
Stephen Hemminger87990462006-08-10 23:35:16 -0700390 cl = p;
391 p = cl->parent;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700392
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 }
394 if (cl->cmode == HTB_CAN_SEND && mask)
Stephen Hemminger87990462006-08-10 23:35:16 -0700395 htb_add_class_to_row(q, cl, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396}
397
398/**
399 * htb_deactivate_prios - remove class from feed chain
400 *
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900401 * cl->cmode must represent old mode (before deactivation). It does
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 * nothing if cl->prio_activity == 0. Class is removed from all feed
403 * chains and rows.
404 */
405static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl)
406{
407 struct htb_class *p = cl->parent;
Stephen Hemminger87990462006-08-10 23:35:16 -0700408 long m, mask = cl->prio_activity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
410 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700411 m = mask;
412 mask = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 while (m) {
414 int prio = ffz(~m);
415 m &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700416
417 if (p->un.inner.ptr[prio] == cl->node + prio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 /* we are removing child which is pointed to from
419 parent feed - forget the pointer but remember
420 classid */
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700421 p->un.inner.last_ptr_id[prio] = cl->common.classid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 p->un.inner.ptr[prio] = NULL;
423 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700424
Stephen Hemminger3696f622006-08-10 23:36:01 -0700425 htb_safe_rb_erase(cl->node + prio, p->un.inner.feed + prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700426
427 if (!p->un.inner.feed[prio].rb_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 mask |= 1 << prio;
429 }
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700430
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 p->prio_activity &= ~mask;
Stephen Hemminger87990462006-08-10 23:35:16 -0700432 cl = p;
433 p = cl->parent;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700434
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700436 if (cl->cmode == HTB_CAN_SEND && mask)
437 htb_remove_class_from_row(q, cl, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438}
439
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700440static inline long htb_lowater(const struct htb_class *cl)
441{
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700442 if (htb_hysteresis)
443 return cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : 0;
444 else
445 return 0;
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700446}
447static inline long htb_hiwater(const struct htb_class *cl)
448{
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700449 if (htb_hysteresis)
450 return cl->cmode == HTB_CAN_SEND ? -cl->buffer : 0;
451 else
452 return 0;
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700453}
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700454
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700455
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456/**
457 * htb_class_mode - computes and returns current class mode
458 *
459 * It computes cl's mode at time cl->t_c+diff and returns it. If mode
460 * is not HTB_CAN_SEND then cl->pq_key is updated to time difference
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900461 * from now to time when cl will change its state.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 * Also it is worth to note that class mode doesn't change simply
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900463 * at cl->{c,}tokens == 0 but there can rather be hysteresis of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 * 0 .. -cl->{c,}buffer range. It is meant to limit number of
465 * mode transitions per time unit. The speed gain is about 1/6.
466 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700467static inline enum htb_cmode
468htb_class_mode(struct htb_class *cl, long *diff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469{
Stephen Hemminger87990462006-08-10 23:35:16 -0700470 long toks;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
Stephen Hemminger87990462006-08-10 23:35:16 -0700472 if ((toks = (cl->ctokens + *diff)) < htb_lowater(cl)) {
473 *diff = -toks;
474 return HTB_CANT_SEND;
475 }
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700476
Stephen Hemminger87990462006-08-10 23:35:16 -0700477 if ((toks = (cl->tokens + *diff)) >= htb_hiwater(cl))
478 return HTB_CAN_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479
Stephen Hemminger87990462006-08-10 23:35:16 -0700480 *diff = -toks;
481 return HTB_MAY_BORROW;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482}
483
484/**
485 * htb_change_class_mode - changes classe's mode
486 *
487 * This should be the only way how to change classe's mode under normal
488 * cirsumstances. Routine will update feed lists linkage, change mode
489 * and add class to the wait event queue if appropriate. New mode should
490 * be different from old one and cl->pq_key has to be valid if changing
491 * to mode other than HTB_CAN_SEND (see htb_add_to_wait_tree).
492 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700493static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long *diff)
Stephen Hemminger87990462006-08-10 23:35:16 -0700495{
496 enum htb_cmode new_mode = htb_class_mode(cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497
498 if (new_mode == cl->cmode)
Stephen Hemminger87990462006-08-10 23:35:16 -0700499 return;
500
501 if (cl->prio_activity) { /* not necessary: speed optimization */
502 if (cl->cmode != HTB_CANT_SEND)
503 htb_deactivate_prios(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 cl->cmode = new_mode;
Stephen Hemminger87990462006-08-10 23:35:16 -0700505 if (new_mode != HTB_CANT_SEND)
506 htb_activate_prios(q, cl);
507 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 cl->cmode = new_mode;
509}
510
511/**
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900512 * htb_activate - inserts leaf cl into appropriate active feeds
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 *
514 * Routine learns (new) priority of leaf and activates feed chain
515 * for the prio. It can be called on already active leaf safely.
516 * It also adds leaf into droplist.
517 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700518static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519{
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700520 WARN_ON(cl->level || !cl->un.leaf.q || !cl->un.leaf.q->q.qlen);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700521
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 if (!cl->prio_activity) {
Jarek Poplawskic19f7a32008-12-03 21:09:45 -0800523 cl->prio_activity = 1 << cl->prio;
Stephen Hemminger87990462006-08-10 23:35:16 -0700524 htb_activate_prios(q, cl);
525 list_add_tail(&cl->un.leaf.drop_list,
Jarek Poplawskic19f7a32008-12-03 21:09:45 -0800526 q->drops + cl->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 }
528}
529
530/**
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900531 * htb_deactivate - remove leaf cl from active feeds
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 *
533 * Make sure that leaf is active. In the other words it can't be called
534 * with non-active leaf. It also removes class from the drop list.
535 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700536static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537{
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700538 WARN_ON(!cl->prio_activity);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700539
Stephen Hemminger87990462006-08-10 23:35:16 -0700540 htb_deactivate_prios(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 cl->prio_activity = 0;
542 list_del_init(&cl->un.leaf.drop_list);
543}
544
545static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
546{
Jarek Poplawskif30ab412008-11-13 22:56:30 -0800547 int uninitialized_var(ret);
Stephen Hemminger87990462006-08-10 23:35:16 -0700548 struct htb_sched *q = qdisc_priv(sch);
549 struct htb_class *cl = htb_classify(skb, sch, &ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Stephen Hemminger87990462006-08-10 23:35:16 -0700551 if (cl == HTB_DIRECT) {
552 /* enqueue to helper queue */
553 if (q->direct_queue.qlen < q->direct_qlen) {
554 __skb_queue_tail(&q->direct_queue, skb);
555 q->direct_pkts++;
556 } else {
557 kfree_skb(skb);
558 sch->qstats.drops++;
559 return NET_XMIT_DROP;
560 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561#ifdef CONFIG_NET_CLS_ACT
Stephen Hemminger87990462006-08-10 23:35:16 -0700562 } else if (!cl) {
Jarek Poplawskic27f3392008-08-04 22:39:11 -0700563 if (ret & __NET_XMIT_BYPASS)
Stephen Hemminger87990462006-08-10 23:35:16 -0700564 sch->qstats.drops++;
565 kfree_skb(skb);
566 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567#endif
Jarek Poplawski378a2f02008-08-04 22:31:03 -0700568 } else if ((ret = qdisc_enqueue(skb, cl->un.leaf.q)) != NET_XMIT_SUCCESS) {
569 if (net_xmit_drop_count(ret)) {
570 sch->qstats.drops++;
571 cl->qstats.drops++;
572 }
David S. Miller69747652008-08-17 23:55:36 -0700573 return ret;
Stephen Hemminger87990462006-08-10 23:35:16 -0700574 } else {
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700575 cl->bstats.packets +=
576 skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700577 cl->bstats.bytes += qdisc_pkt_len(skb);
Stephen Hemminger87990462006-08-10 23:35:16 -0700578 htb_activate(q, cl);
579 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580
Stephen Hemminger87990462006-08-10 23:35:16 -0700581 sch->q.qlen++;
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700582 sch->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700583 sch->bstats.bytes += qdisc_pkt_len(skb);
Stephen Hemminger87990462006-08-10 23:35:16 -0700584 return NET_XMIT_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585}
586
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587/**
588 * htb_charge_class - charges amount "bytes" to leaf and ancestors
589 *
590 * Routine assumes that packet "bytes" long was dequeued from leaf cl
591 * borrowing from "level". It accounts bytes to ceil leaky bucket for
592 * leaf and all ancestors and to rate bucket for ancestors at levels
593 * "level" and higher. It also handles possible change of mode resulting
594 * from the update. Note that mode can also increase here (MAY_BORROW to
595 * CAN_SEND) because we can use more precise clock that event queue here.
596 * In such case we remove class from event queue first.
597 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700598static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700599 int level, struct sk_buff *skb)
Stephen Hemminger87990462006-08-10 23:35:16 -0700600{
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700601 int bytes = qdisc_pkt_len(skb);
Stephen Hemminger87990462006-08-10 23:35:16 -0700602 long toks, diff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 enum htb_cmode old_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604
605#define HTB_ACCNT(T,B,R) toks = diff + cl->T; \
606 if (toks > cl->B) toks = cl->B; \
607 toks -= L2T(cl, cl->R, bytes); \
608 if (toks <= -cl->mbuffer) toks = 1-cl->mbuffer; \
609 cl->T = toks
610
611 while (cl) {
Patrick McHardy03cc45c2007-03-23 11:29:11 -0700612 diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 if (cl->level >= level) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700614 if (cl->level == level)
615 cl->xstats.lends++;
616 HTB_ACCNT(tokens, buffer, rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 } else {
618 cl->xstats.borrows++;
Stephen Hemminger87990462006-08-10 23:35:16 -0700619 cl->tokens += diff; /* we moved t_c; update tokens */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700621 HTB_ACCNT(ctokens, cbuffer, ceil);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 cl->t_c = q->now;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
Stephen Hemminger87990462006-08-10 23:35:16 -0700624 old_mode = cl->cmode;
625 diff = 0;
626 htb_change_class_mode(q, cl, &diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 if (old_mode != cl->cmode) {
628 if (old_mode != HTB_CAN_SEND)
Stephen Hemminger3696f622006-08-10 23:36:01 -0700629 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 if (cl->cmode != HTB_CAN_SEND)
Stephen Hemminger87990462006-08-10 23:35:16 -0700631 htb_add_to_wait_tree(q, cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
634 /* update byte stats except for leaves which are already updated */
635 if (cl->level) {
636 cl->bstats.bytes += bytes;
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700637 cl->bstats.packets += skb_is_gso(skb)?
638 skb_shinfo(skb)->gso_segs:1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 }
640 cl = cl->parent;
641 }
642}
643
644/**
645 * htb_do_events - make mode changes to classes at the level
646 *
Patrick McHardyfb983d42007-03-16 01:22:39 -0700647 * Scans event queue for pending events and applies them. Returns time of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 * next pending event (0 for no event in pq).
Patrick McHardyfb983d42007-03-16 01:22:39 -0700649 * Note: Applied are events whose have cl->pq_key <= q->now.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700651static psched_time_t htb_do_events(struct htb_sched *q, int level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652{
Martin Devera8f3ea332008-03-23 22:00:38 -0700653 /* don't run for longer than 2 jiffies; 2 is used instead of
654 1 to simplify things when jiffy is going to be incremented
655 too soon */
656 unsigned long stop_at = jiffies + 2;
657 while (time_before(jiffies, stop_at)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 struct htb_class *cl;
659 long diff;
Akinbou Mita30bdbe32006-10-12 01:52:05 -0700660 struct rb_node *p = rb_first(&q->wait_pq[level]);
661
Stephen Hemminger87990462006-08-10 23:35:16 -0700662 if (!p)
663 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664
665 cl = rb_entry(p, struct htb_class, pq_node);
Patrick McHardyfb983d42007-03-16 01:22:39 -0700666 if (cl->pq_key > q->now)
667 return cl->pq_key;
668
Stephen Hemminger3696f622006-08-10 23:36:01 -0700669 htb_safe_rb_erase(p, q->wait_pq + level);
Patrick McHardy03cc45c2007-03-23 11:29:11 -0700670 diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
Stephen Hemminger87990462006-08-10 23:35:16 -0700671 htb_change_class_mode(q, cl, &diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 if (cl->cmode != HTB_CAN_SEND)
Stephen Hemminger87990462006-08-10 23:35:16 -0700673 htb_add_to_wait_tree(q, cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 }
Martin Devera8f3ea332008-03-23 22:00:38 -0700675 /* too much load - let's continue on next jiffie */
676 return q->now + PSCHED_TICKS_PER_SEC / HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677}
678
679/* Returns class->node+prio from id-tree where classe's id is >= id. NULL
680 is no such one exists. */
Stephen Hemminger87990462006-08-10 23:35:16 -0700681static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n,
682 u32 id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683{
684 struct rb_node *r = NULL;
685 while (n) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700686 struct htb_class *cl =
687 rb_entry(n, struct htb_class, node[prio]);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700688 if (id == cl->common.classid)
Stephen Hemminger87990462006-08-10 23:35:16 -0700689 return n;
690
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700691 if (id > cl->common.classid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 n = n->rb_right;
693 } else {
694 r = n;
695 n = n->rb_left;
696 }
697 }
698 return r;
699}
700
701/**
702 * htb_lookup_leaf - returns next leaf class in DRR order
703 *
704 * Find leaf where current feed pointers points to.
705 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700706static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
707 struct rb_node **pptr, u32 * pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708{
709 int i;
710 struct {
711 struct rb_node *root;
712 struct rb_node **pptr;
713 u32 *pid;
Stephen Hemminger87990462006-08-10 23:35:16 -0700714 } stk[TC_HTB_MAXDEPTH], *sp = stk;
715
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700716 WARN_ON(!tree->rb_node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 sp->root = tree->rb_node;
718 sp->pptr = pptr;
719 sp->pid = pid;
720
721 for (i = 0; i < 65535; i++) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700722 if (!*sp->pptr && *sp->pid) {
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900723 /* ptr was invalidated but id is valid - try to recover
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 the original or next ptr */
Stephen Hemminger87990462006-08-10 23:35:16 -0700725 *sp->pptr =
726 htb_id_find_next_upper(prio, sp->root, *sp->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700728 *sp->pid = 0; /* ptr is valid now so that remove this hint as it
729 can become out of date quickly */
730 if (!*sp->pptr) { /* we are at right end; rewind & go up */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 *sp->pptr = sp->root;
Stephen Hemminger87990462006-08-10 23:35:16 -0700732 while ((*sp->pptr)->rb_left)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 *sp->pptr = (*sp->pptr)->rb_left;
734 if (sp > stk) {
735 sp--;
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700736 WARN_ON(!*sp->pptr);
Stephen Hemminger87990462006-08-10 23:35:16 -0700737 if (!*sp->pptr)
738 return NULL;
739 htb_next_rb_node(sp->pptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 }
741 } else {
742 struct htb_class *cl;
Stephen Hemminger87990462006-08-10 23:35:16 -0700743 cl = rb_entry(*sp->pptr, struct htb_class, node[prio]);
744 if (!cl->level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 return cl;
746 (++sp)->root = cl->un.inner.feed[prio].rb_node;
Stephen Hemminger87990462006-08-10 23:35:16 -0700747 sp->pptr = cl->un.inner.ptr + prio;
748 sp->pid = cl->un.inner.last_ptr_id + prio;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 }
750 }
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700751 WARN_ON(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 return NULL;
753}
754
755/* dequeues packet at given priority and level; call only if
756 you are sure that there is active class at prio/level */
Stephen Hemminger87990462006-08-10 23:35:16 -0700757static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio,
758 int level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759{
760 struct sk_buff *skb = NULL;
Stephen Hemminger87990462006-08-10 23:35:16 -0700761 struct htb_class *cl, *start;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 /* look initial class up in the row */
Stephen Hemminger87990462006-08-10 23:35:16 -0700763 start = cl = htb_lookup_leaf(q->row[level] + prio, prio,
764 q->ptr[level] + prio,
765 q->last_ptr_id[level] + prio);
766
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 do {
768next:
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700769 WARN_ON(!cl);
Stephen Hemminger87990462006-08-10 23:35:16 -0700770 if (!cl)
771 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
773 /* class can be empty - it is unlikely but can be true if leaf
774 qdisc drops packets in enqueue routine or if someone used
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900775 graft operation on the leaf since last dequeue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 simply deactivate and skip such class */
777 if (unlikely(cl->un.leaf.q->q.qlen == 0)) {
778 struct htb_class *next;
Stephen Hemminger87990462006-08-10 23:35:16 -0700779 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
781 /* row/level might become empty */
782 if ((q->row_mask[level] & (1 << prio)) == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -0700783 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784
Stephen Hemminger87990462006-08-10 23:35:16 -0700785 next = htb_lookup_leaf(q->row[level] + prio,
786 prio, q->ptr[level] + prio,
787 q->last_ptr_id[level] + prio);
788
789 if (cl == start) /* fix start if we just deleted it */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 start = next;
791 cl = next;
792 goto next;
793 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700794
795 skb = cl->un.leaf.q->dequeue(cl->un.leaf.q);
796 if (likely(skb != NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 break;
798 if (!cl->warned) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700799 printk(KERN_WARNING
800 "htb: class %X isn't work conserving ?!\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700801 cl->common.classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 cl->warned = 1;
803 }
Jarek Poplawski633fe662008-12-03 21:09:10 -0800804
Stephen Hemminger87990462006-08-10 23:35:16 -0700805 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
806 ptr[0]) + prio);
807 cl = htb_lookup_leaf(q->row[level] + prio, prio,
808 q->ptr[level] + prio,
809 q->last_ptr_id[level] + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810
811 } while (cl != start);
812
813 if (likely(skb != NULL)) {
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700814 cl->un.leaf.deficit[level] -= qdisc_pkt_len(skb);
815 if (cl->un.leaf.deficit[level] < 0) {
Jarek Poplawskic19f7a32008-12-03 21:09:45 -0800816 cl->un.leaf.deficit[level] += cl->quantum;
Stephen Hemminger87990462006-08-10 23:35:16 -0700817 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
818 ptr[0]) + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 }
820 /* this used to be after charge_class but this constelation
821 gives us slightly better performance */
822 if (!cl->un.leaf.q->q.qlen)
Stephen Hemminger87990462006-08-10 23:35:16 -0700823 htb_deactivate(q, cl);
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700824 htb_charge_class(q, cl, level, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 }
826 return skb;
827}
828
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829static struct sk_buff *htb_dequeue(struct Qdisc *sch)
830{
831 struct sk_buff *skb = NULL;
832 struct htb_sched *q = qdisc_priv(sch);
833 int level;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700834 psched_time_t next_event;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835
836 /* try to dequeue direct packets as high prio (!) to minimize cpu work */
Stephen Hemminger87990462006-08-10 23:35:16 -0700837 skb = __skb_dequeue(&q->direct_queue);
838 if (skb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 sch->flags &= ~TCQ_F_THROTTLED;
840 sch->q.qlen--;
841 return skb;
842 }
843
Stephen Hemminger87990462006-08-10 23:35:16 -0700844 if (!sch->q.qlen)
845 goto fin;
Patrick McHardy3bebcda2007-03-23 11:29:25 -0700846 q->now = psched_get_time();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847
Patrick McHardyfb983d42007-03-16 01:22:39 -0700848 next_event = q->now + 5 * PSCHED_TICKS_PER_SEC;
Jarek Poplawski633fe662008-12-03 21:09:10 -0800849
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
851 /* common case optimization - skip event handler quickly */
852 int m;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700853 psched_time_t event;
Stephen Hemminger87990462006-08-10 23:35:16 -0700854
Patrick McHardyfb983d42007-03-16 01:22:39 -0700855 if (q->now >= q->near_ev_cache[level]) {
856 event = htb_do_events(q, level);
Patrick McHardy2e4b3b02007-05-23 23:39:54 -0700857 if (!event)
858 event = q->now + PSCHED_TICKS_PER_SEC;
859 q->near_ev_cache[level] = event;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700860 } else
861 event = q->near_ev_cache[level];
862
863 if (event && next_event > event)
864 next_event = event;
865
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 m = ~q->row_mask[level];
867 while (m != (int)(-1)) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700868 int prio = ffz(m);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 m |= 1 << prio;
Stephen Hemminger87990462006-08-10 23:35:16 -0700870 skb = htb_dequeue_tree(q, prio, level);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 if (likely(skb != NULL)) {
872 sch->q.qlen--;
873 sch->flags &= ~TCQ_F_THROTTLED;
874 goto fin;
875 }
876 }
877 }
Patrick McHardyfb983d42007-03-16 01:22:39 -0700878 sch->qstats.overlimits++;
879 qdisc_watchdog_schedule(&q->watchdog, next_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880fin:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 return skb;
882}
883
884/* try to drop from each class (by prio) until one succeed */
Stephen Hemminger87990462006-08-10 23:35:16 -0700885static unsigned int htb_drop(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886{
887 struct htb_sched *q = qdisc_priv(sch);
888 int prio;
889
890 for (prio = TC_HTB_NUMPRIO - 1; prio >= 0; prio--) {
891 struct list_head *p;
Stephen Hemminger87990462006-08-10 23:35:16 -0700892 list_for_each(p, q->drops + prio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 struct htb_class *cl = list_entry(p, struct htb_class,
894 un.leaf.drop_list);
895 unsigned int len;
Stephen Hemminger87990462006-08-10 23:35:16 -0700896 if (cl->un.leaf.q->ops->drop &&
897 (len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 sch->q.qlen--;
899 if (!cl->un.leaf.q->q.qlen)
Stephen Hemminger87990462006-08-10 23:35:16 -0700900 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 return len;
902 }
903 }
904 }
905 return 0;
906}
907
908/* reset all classes */
909/* always caled under BH & queue lock */
Stephen Hemminger87990462006-08-10 23:35:16 -0700910static void htb_reset(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911{
912 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700913 struct htb_class *cl;
914 struct hlist_node *n;
915 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700917 for (i = 0; i < q->clhash.hashsize; i++) {
918 hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 if (cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700920 memset(&cl->un.inner, 0, sizeof(cl->un.inner));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 else {
Stephen Hemminger87990462006-08-10 23:35:16 -0700922 if (cl->un.leaf.q)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 qdisc_reset(cl->un.leaf.q);
924 INIT_LIST_HEAD(&cl->un.leaf.drop_list);
925 }
926 cl->prio_activity = 0;
927 cl->cmode = HTB_CAN_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928
929 }
930 }
Patrick McHardyfb983d42007-03-16 01:22:39 -0700931 qdisc_watchdog_cancel(&q->watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 __skb_queue_purge(&q->direct_queue);
933 sch->q.qlen = 0;
Stephen Hemminger87990462006-08-10 23:35:16 -0700934 memset(q->row, 0, sizeof(q->row));
935 memset(q->row_mask, 0, sizeof(q->row_mask));
936 memset(q->wait_pq, 0, sizeof(q->wait_pq));
937 memset(q->ptr, 0, sizeof(q->ptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 for (i = 0; i < TC_HTB_NUMPRIO; i++)
Stephen Hemminger87990462006-08-10 23:35:16 -0700939 INIT_LIST_HEAD(q->drops + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940}
941
Patrick McHardy27a34212008-01-23 20:35:39 -0800942static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
943 [TCA_HTB_PARMS] = { .len = sizeof(struct tc_htb_opt) },
944 [TCA_HTB_INIT] = { .len = sizeof(struct tc_htb_glob) },
945 [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
946 [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
947};
948
Patrick McHardy1e904742008-01-22 22:11:17 -0800949static int htb_init(struct Qdisc *sch, struct nlattr *opt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950{
951 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardy1e904742008-01-22 22:11:17 -0800952 struct nlattr *tb[TCA_HTB_INIT + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 struct tc_htb_glob *gopt;
Patrick McHardycee63722008-01-23 20:33:32 -0800954 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 int i;
Patrick McHardycee63722008-01-23 20:33:32 -0800956
957 if (!opt)
958 return -EINVAL;
959
Patrick McHardy27a34212008-01-23 20:35:39 -0800960 err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy);
Patrick McHardycee63722008-01-23 20:33:32 -0800961 if (err < 0)
962 return err;
963
Patrick McHardy27a34212008-01-23 20:35:39 -0800964 if (tb[TCA_HTB_INIT] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
966 return -EINVAL;
967 }
Patrick McHardy1e904742008-01-22 22:11:17 -0800968 gopt = nla_data(tb[TCA_HTB_INIT]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 if (gopt->version != HTB_VER >> 16) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700970 printk(KERN_ERR
971 "HTB: need tc/htb version %d (minor is %d), you have %d\n",
972 HTB_VER >> 16, HTB_VER & 0xffff, gopt->version);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 return -EINVAL;
974 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700976 err = qdisc_class_hash_init(&q->clhash);
977 if (err < 0)
978 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 for (i = 0; i < TC_HTB_NUMPRIO; i++)
Stephen Hemminger87990462006-08-10 23:35:16 -0700980 INIT_LIST_HEAD(q->drops + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
Patrick McHardyfb983d42007-03-16 01:22:39 -0700982 qdisc_watchdog_init(&q->watchdog, sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 skb_queue_head_init(&q->direct_queue);
984
David S. Miller5ce2d482008-07-08 17:06:30 -0700985 q->direct_qlen = qdisc_dev(sch)->tx_queue_len;
Stephen Hemminger87990462006-08-10 23:35:16 -0700986 if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 q->direct_qlen = 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 if ((q->rate2quantum = gopt->rate2quantum) < 1)
990 q->rate2quantum = 1;
991 q->defcls = gopt->defcls;
992
993 return 0;
994}
995
996static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
997{
Jarek Poplawski102396a2008-08-29 14:21:52 -0700998 spinlock_t *root_lock = qdisc_root_sleeping_lock(sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001000 struct nlattr *nest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 struct tc_htb_glob gopt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
David S. Miller7698b4f2008-07-16 01:42:40 -07001003 spin_lock_bh(root_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001004
1005 gopt.direct_pkts = q->direct_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 gopt.version = HTB_VER;
1007 gopt.rate2quantum = q->rate2quantum;
1008 gopt.defcls = q->defcls;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001009 gopt.debug = 0;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001010
1011 nest = nla_nest_start(skb, TCA_OPTIONS);
1012 if (nest == NULL)
1013 goto nla_put_failure;
Patrick McHardy1e904742008-01-22 22:11:17 -08001014 NLA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001015 nla_nest_end(skb, nest);
1016
David S. Miller7698b4f2008-07-16 01:42:40 -07001017 spin_unlock_bh(root_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 return skb->len;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001019
Patrick McHardy1e904742008-01-22 22:11:17 -08001020nla_put_failure:
David S. Miller7698b4f2008-07-16 01:42:40 -07001021 spin_unlock_bh(root_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001022 nla_nest_cancel(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 return -1;
1024}
1025
1026static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
Stephen Hemminger87990462006-08-10 23:35:16 -07001027 struct sk_buff *skb, struct tcmsg *tcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028{
Stephen Hemminger87990462006-08-10 23:35:16 -07001029 struct htb_class *cl = (struct htb_class *)arg;
Jarek Poplawski102396a2008-08-29 14:21:52 -07001030 spinlock_t *root_lock = qdisc_root_sleeping_lock(sch);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001031 struct nlattr *nest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 struct tc_htb_opt opt;
1033
David S. Miller7698b4f2008-07-16 01:42:40 -07001034 spin_lock_bh(root_lock);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001035 tcm->tcm_parent = cl->parent ? cl->parent->common.classid : TC_H_ROOT;
1036 tcm->tcm_handle = cl->common.classid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 if (!cl->level && cl->un.leaf.q)
1038 tcm->tcm_info = cl->un.leaf.q->handle;
1039
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001040 nest = nla_nest_start(skb, TCA_OPTIONS);
1041 if (nest == NULL)
1042 goto nla_put_failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
Stephen Hemminger87990462006-08-10 23:35:16 -07001044 memset(&opt, 0, sizeof(opt));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045
Stephen Hemminger87990462006-08-10 23:35:16 -07001046 opt.rate = cl->rate->rate;
1047 opt.buffer = cl->buffer;
1048 opt.ceil = cl->ceil->rate;
1049 opt.cbuffer = cl->cbuffer;
Jarek Poplawskic19f7a32008-12-03 21:09:45 -08001050 opt.quantum = cl->quantum;
1051 opt.prio = cl->prio;
Stephen Hemminger87990462006-08-10 23:35:16 -07001052 opt.level = cl->level;
Patrick McHardy1e904742008-01-22 22:11:17 -08001053 NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001054
1055 nla_nest_end(skb, nest);
David S. Miller7698b4f2008-07-16 01:42:40 -07001056 spin_unlock_bh(root_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 return skb->len;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001058
Patrick McHardy1e904742008-01-22 22:11:17 -08001059nla_put_failure:
David S. Miller7698b4f2008-07-16 01:42:40 -07001060 spin_unlock_bh(root_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001061 nla_nest_cancel(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 return -1;
1063}
1064
1065static int
Stephen Hemminger87990462006-08-10 23:35:16 -07001066htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067{
Stephen Hemminger87990462006-08-10 23:35:16 -07001068 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 if (!cl->level && cl->un.leaf.q)
1071 cl->qstats.qlen = cl->un.leaf.q->q.qlen;
1072 cl->xstats.tokens = cl->tokens;
1073 cl->xstats.ctokens = cl->ctokens;
1074
1075 if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
1076 gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
1077 gnet_stats_copy_queue(d, &cl->qstats) < 0)
1078 return -1;
1079
1080 return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
1081}
1082
1083static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
Stephen Hemminger87990462006-08-10 23:35:16 -07001084 struct Qdisc **old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085{
Stephen Hemminger87990462006-08-10 23:35:16 -07001086 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
1088 if (cl && !cl->level) {
Patrick McHardy9f9afec2006-11-29 17:35:18 -08001089 if (new == NULL &&
David S. Miller5ce2d482008-07-08 17:06:30 -07001090 (new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
David S. Millerbb949fb2008-07-08 16:55:56 -07001091 &pfifo_qdisc_ops,
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001092 cl->common.classid))
Stephen Hemminger87990462006-08-10 23:35:16 -07001093 == NULL)
1094 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 sch_tree_lock(sch);
Patrick McHardyb94c8af2008-11-20 04:11:36 -08001096 *old = cl->un.leaf.q;
1097 cl->un.leaf.q = new;
1098 if (*old != NULL) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001099 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 qdisc_reset(*old);
1101 }
1102 sch_tree_unlock(sch);
1103 return 0;
1104 }
1105 return -ENOENT;
1106}
1107
Stephen Hemminger87990462006-08-10 23:35:16 -07001108static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109{
Stephen Hemminger87990462006-08-10 23:35:16 -07001110 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 return (cl && !cl->level) ? cl->un.leaf.q : NULL;
1112}
1113
Patrick McHardy256d61b2006-11-29 17:37:05 -08001114static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg)
1115{
1116 struct htb_class *cl = (struct htb_class *)arg;
1117
1118 if (cl->un.leaf.q->q.qlen == 0)
1119 htb_deactivate(qdisc_priv(sch), cl);
1120}
1121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122static unsigned long htb_get(struct Qdisc *sch, u32 classid)
1123{
Stephen Hemminger87990462006-08-10 23:35:16 -07001124 struct htb_class *cl = htb_find(classid, sch);
1125 if (cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 cl->refcnt++;
1127 return (unsigned long)cl;
1128}
1129
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001130static inline int htb_parent_last_child(struct htb_class *cl)
1131{
1132 if (!cl->parent)
1133 /* the root class */
1134 return 0;
Patrick McHardy42077592008-07-05 23:22:53 -07001135 if (cl->parent->children > 1)
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001136 /* not the last child */
1137 return 0;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001138 return 1;
1139}
1140
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001141static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
1142 struct Qdisc *new_q)
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001143{
1144 struct htb_class *parent = cl->parent;
1145
Ilpo Järvinen547b7922008-07-25 21:43:18 -07001146 WARN_ON(cl->level || !cl->un.leaf.q || cl->prio_activity);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001147
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001148 if (parent->cmode != HTB_CAN_SEND)
1149 htb_safe_rb_erase(&parent->pq_node, q->wait_pq + parent->level);
1150
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001151 parent->level = 0;
1152 memset(&parent->un.inner, 0, sizeof(parent->un.inner));
1153 INIT_LIST_HEAD(&parent->un.leaf.drop_list);
1154 parent->un.leaf.q = new_q ? new_q : &noop_qdisc;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001155 parent->tokens = parent->buffer;
1156 parent->ctokens = parent->cbuffer;
Patrick McHardy3bebcda2007-03-23 11:29:25 -07001157 parent->t_c = psched_get_time();
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001158 parent->cmode = HTB_CAN_SEND;
1159}
1160
Stephen Hemminger87990462006-08-10 23:35:16 -07001161static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 if (!cl->level) {
Ilpo Järvinen547b7922008-07-25 21:43:18 -07001164 WARN_ON(!cl->un.leaf.q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 qdisc_destroy(cl->un.leaf.q);
1166 }
Patrick McHardyee39e102007-07-02 22:48:13 -07001167 gen_kill_estimator(&cl->bstats, &cl->rate_est);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 qdisc_put_rtab(cl->rate);
1169 qdisc_put_rtab(cl->ceil);
Stephen Hemminger87990462006-08-10 23:35:16 -07001170
Patrick McHardyff31ab52008-07-01 19:52:38 -07001171 tcf_destroy_chain(&cl->filter_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 kfree(cl);
1173}
1174
1175/* always caled under BH & queue lock */
Stephen Hemminger87990462006-08-10 23:35:16 -07001176static void htb_destroy(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177{
1178 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001179 struct hlist_node *n, *next;
1180 struct htb_class *cl;
1181 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182
Patrick McHardyfb983d42007-03-16 01:22:39 -07001183 qdisc_watchdog_cancel(&q->watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 /* This line used to be after htb_destroy_class call below
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +09001185 and surprisingly it worked in 2.4. But it must precede it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 because filter need its target class alive to be able to call
1187 unbind_filter on it (without Oops). */
Patrick McHardyff31ab52008-07-01 19:52:38 -07001188 tcf_destroy_chain(&q->filter_list);
Stephen Hemminger87990462006-08-10 23:35:16 -07001189
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001190 for (i = 0; i < q->clhash.hashsize; i++) {
1191 hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode)
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001192 tcf_destroy_chain(&cl->filter_list);
1193 }
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001194 for (i = 0; i < q->clhash.hashsize; i++) {
1195 hlist_for_each_entry_safe(cl, n, next, &q->clhash.hash[i],
1196 common.hnode)
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001197 htb_destroy_class(sch, cl);
1198 }
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001199 qdisc_class_hash_destroy(&q->clhash);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 __skb_queue_purge(&q->direct_queue);
1201}
1202
1203static int htb_delete(struct Qdisc *sch, unsigned long arg)
1204{
1205 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001206 struct htb_class *cl = (struct htb_class *)arg;
Patrick McHardy256d61b2006-11-29 17:37:05 -08001207 unsigned int qlen;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001208 struct Qdisc *new_q = NULL;
1209 int last_child = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 // TODO: why don't allow to delete subtree ? references ? does
1212 // tc subsys quarantee us that in htb_destroy it holds no class
1213 // refs so that we can remove children safely there ?
Patrick McHardy42077592008-07-05 23:22:53 -07001214 if (cl->children || cl->filter_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 return -EBUSY;
Stephen Hemminger87990462006-08-10 23:35:16 -07001216
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001217 if (!cl->level && htb_parent_last_child(cl)) {
David S. Miller5ce2d482008-07-08 17:06:30 -07001218 new_q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
David S. Millerbb949fb2008-07-08 16:55:56 -07001219 &pfifo_qdisc_ops,
1220 cl->parent->common.classid);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001221 last_child = 1;
1222 }
1223
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 sch_tree_lock(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001225
Patrick McHardy814a175e2006-11-29 17:34:50 -08001226 if (!cl->level) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001227 qlen = cl->un.leaf.q->q.qlen;
Patrick McHardy814a175e2006-11-29 17:34:50 -08001228 qdisc_reset(cl->un.leaf.q);
Patrick McHardy256d61b2006-11-29 17:37:05 -08001229 qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen);
Patrick McHardy814a175e2006-11-29 17:34:50 -08001230 }
1231
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001232 /* delete from hash and active; remainder in destroy_class */
1233 qdisc_class_hash_remove(&q->clhash, &cl->common);
Jarek Poplawski26b284d2008-08-13 15:16:43 -07001234 if (cl->parent)
1235 cl->parent->children--;
Patrick McHardyc38c83c2007-03-27 14:04:24 -07001236
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 if (cl->prio_activity)
Stephen Hemminger87990462006-08-10 23:35:16 -07001238 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001240 if (cl->cmode != HTB_CAN_SEND)
1241 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
1242
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001243 if (last_child)
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001244 htb_parent_to_leaf(q, cl, new_q);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001245
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 if (--cl->refcnt == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -07001247 htb_destroy_class(sch, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248
1249 sch_tree_unlock(sch);
1250 return 0;
1251}
1252
1253static void htb_put(struct Qdisc *sch, unsigned long arg)
1254{
Stephen Hemminger87990462006-08-10 23:35:16 -07001255 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
1257 if (--cl->refcnt == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -07001258 htb_destroy_class(sch, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259}
1260
Stephen Hemminger87990462006-08-10 23:35:16 -07001261static int htb_change_class(struct Qdisc *sch, u32 classid,
Patrick McHardy1e904742008-01-22 22:11:17 -08001262 u32 parentid, struct nlattr **tca,
Stephen Hemminger87990462006-08-10 23:35:16 -07001263 unsigned long *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264{
1265 int err = -EINVAL;
1266 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001267 struct htb_class *cl = (struct htb_class *)*arg, *parent;
Patrick McHardy1e904742008-01-22 22:11:17 -08001268 struct nlattr *opt = tca[TCA_OPTIONS];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
Patrick McHardy1e904742008-01-22 22:11:17 -08001270 struct nlattr *tb[TCA_HTB_RTAB + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 struct tc_htb_opt *hopt;
1272
1273 /* extract all subattrs from opt attr */
Patrick McHardycee63722008-01-23 20:33:32 -08001274 if (!opt)
1275 goto failure;
1276
Patrick McHardy27a34212008-01-23 20:35:39 -08001277 err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, htb_policy);
Patrick McHardycee63722008-01-23 20:33:32 -08001278 if (err < 0)
1279 goto failure;
1280
1281 err = -EINVAL;
Patrick McHardy27a34212008-01-23 20:35:39 -08001282 if (tb[TCA_HTB_PARMS] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 goto failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
Stephen Hemminger87990462006-08-10 23:35:16 -07001285 parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001286
Patrick McHardy1e904742008-01-22 22:11:17 -08001287 hopt = nla_data(tb[TCA_HTB_PARMS]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288
Patrick McHardy1e904742008-01-22 22:11:17 -08001289 rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]);
1290 ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]);
Stephen Hemminger87990462006-08-10 23:35:16 -07001291 if (!rtab || !ctab)
1292 goto failure;
1293
1294 if (!cl) { /* new class */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 struct Qdisc *new_q;
Stephen Hemminger3696f622006-08-10 23:36:01 -07001296 int prio;
Patrick McHardyee39e102007-07-02 22:48:13 -07001297 struct {
Patrick McHardy1e904742008-01-22 22:11:17 -08001298 struct nlattr nla;
Patrick McHardyee39e102007-07-02 22:48:13 -07001299 struct gnet_estimator opt;
1300 } est = {
Patrick McHardy1e904742008-01-22 22:11:17 -08001301 .nla = {
1302 .nla_len = nla_attr_size(sizeof(est.opt)),
1303 .nla_type = TCA_RATE,
Patrick McHardyee39e102007-07-02 22:48:13 -07001304 },
1305 .opt = {
1306 /* 4s interval, 16s averaging constant */
1307 .interval = 2,
1308 .ewma_log = 2,
1309 },
1310 };
Stephen Hemminger3696f622006-08-10 23:36:01 -07001311
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 /* check for valid classid */
Stephen Hemminger87990462006-08-10 23:35:16 -07001313 if (!classid || TC_H_MAJ(classid ^ sch->handle)
1314 || htb_find(classid, sch))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 goto failure;
1316
1317 /* check maximal depth */
1318 if (parent && parent->parent && parent->parent->level < 2) {
1319 printk(KERN_ERR "htb: tree is too deep\n");
1320 goto failure;
1321 }
1322 err = -ENOBUFS;
Panagiotis Issaris0da974f2006-07-21 14:51:30 -07001323 if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 goto failure;
Stephen Hemminger87990462006-08-10 23:35:16 -07001325
Stephen Hemminger71bcb092008-11-25 21:13:31 -08001326 err = gen_new_estimator(&cl->bstats, &cl->rate_est,
1327 qdisc_root_sleeping_lock(sch),
1328 tca[TCA_RATE] ? : &est.nla);
1329 if (err) {
1330 kfree(cl);
1331 goto failure;
1332 }
1333
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 cl->refcnt = 1;
Patrick McHardy42077592008-07-05 23:22:53 -07001335 cl->children = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 INIT_LIST_HEAD(&cl->un.leaf.drop_list);
Stephen Hemminger3696f622006-08-10 23:36:01 -07001337 RB_CLEAR_NODE(&cl->pq_node);
1338
1339 for (prio = 0; prio < TC_HTB_NUMPRIO; prio++)
1340 RB_CLEAR_NODE(&cl->node[prio]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
1342 /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
1343 so that can't be used inside of sch_tree_lock
1344 -- thanks to Karlis Peisenieks */
David S. Miller5ce2d482008-07-08 17:06:30 -07001345 new_q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
David S. Millerbb949fb2008-07-08 16:55:56 -07001346 &pfifo_qdisc_ops, classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 sch_tree_lock(sch);
1348 if (parent && !parent->level) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001349 unsigned int qlen = parent->un.leaf.q->q.qlen;
1350
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 /* turn parent into inner node */
Patrick McHardy256d61b2006-11-29 17:37:05 -08001352 qdisc_reset(parent->un.leaf.q);
1353 qdisc_tree_decrease_qlen(parent->un.leaf.q, qlen);
Stephen Hemminger87990462006-08-10 23:35:16 -07001354 qdisc_destroy(parent->un.leaf.q);
1355 if (parent->prio_activity)
1356 htb_deactivate(q, parent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
1358 /* remove from evt list because of level change */
1359 if (parent->cmode != HTB_CAN_SEND) {
Stephen Hemminger3696f622006-08-10 23:36:01 -07001360 htb_safe_rb_erase(&parent->pq_node, q->wait_pq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 parent->cmode = HTB_CAN_SEND;
1362 }
1363 parent->level = (parent->parent ? parent->parent->level
Stephen Hemminger87990462006-08-10 23:35:16 -07001364 : TC_HTB_MAXDEPTH) - 1;
1365 memset(&parent->un.inner, 0, sizeof(parent->un.inner));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 }
1367 /* leaf (we) needs elementary qdisc */
1368 cl->un.leaf.q = new_q ? new_q : &noop_qdisc;
1369
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001370 cl->common.classid = classid;
Stephen Hemminger87990462006-08-10 23:35:16 -07001371 cl->parent = parent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
1373 /* set class to be in HTB_CAN_SEND state */
1374 cl->tokens = hopt->buffer;
1375 cl->ctokens = hopt->cbuffer;
Patrick McHardy00c04af2007-03-16 01:23:02 -07001376 cl->mbuffer = 60 * PSCHED_TICKS_PER_SEC; /* 1min */
Patrick McHardy3bebcda2007-03-23 11:29:25 -07001377 cl->t_c = psched_get_time();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 cl->cmode = HTB_CAN_SEND;
1379
1380 /* attach to the hash list and parent's family */
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001381 qdisc_class_hash_insert(&q->clhash, &cl->common);
Patrick McHardy42077592008-07-05 23:22:53 -07001382 if (parent)
1383 parent->children++;
Patrick McHardyee39e102007-07-02 22:48:13 -07001384 } else {
Stephen Hemminger71bcb092008-11-25 21:13:31 -08001385 if (tca[TCA_RATE]) {
1386 err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
1387 qdisc_root_sleeping_lock(sch),
1388 tca[TCA_RATE]);
1389 if (err)
1390 return err;
1391 }
Stephen Hemminger87990462006-08-10 23:35:16 -07001392 sch_tree_lock(sch);
Patrick McHardyee39e102007-07-02 22:48:13 -07001393 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
1395 /* it used to be a nasty bug here, we have to check that node
Stephen Hemminger87990462006-08-10 23:35:16 -07001396 is really leaf before changing cl->un.leaf ! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 if (!cl->level) {
Jarek Poplawskic19f7a32008-12-03 21:09:45 -08001398 cl->quantum = rtab->rate.rate / q->rate2quantum;
1399 if (!hopt->quantum && cl->quantum < 1000) {
Stephen Hemminger87990462006-08-10 23:35:16 -07001400 printk(KERN_WARNING
1401 "HTB: quantum of class %X is small. Consider r2q change.\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001402 cl->common.classid);
Jarek Poplawskic19f7a32008-12-03 21:09:45 -08001403 cl->quantum = 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 }
Jarek Poplawskic19f7a32008-12-03 21:09:45 -08001405 if (!hopt->quantum && cl->quantum > 200000) {
Stephen Hemminger87990462006-08-10 23:35:16 -07001406 printk(KERN_WARNING
1407 "HTB: quantum of class %X is big. Consider r2q change.\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001408 cl->common.classid);
Jarek Poplawskic19f7a32008-12-03 21:09:45 -08001409 cl->quantum = 200000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 }
1411 if (hopt->quantum)
Jarek Poplawskic19f7a32008-12-03 21:09:45 -08001412 cl->quantum = hopt->quantum;
1413 if ((cl->prio = hopt->prio) >= TC_HTB_NUMPRIO)
1414 cl->prio = TC_HTB_NUMPRIO - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 }
1416
1417 cl->buffer = hopt->buffer;
1418 cl->cbuffer = hopt->cbuffer;
Stephen Hemminger87990462006-08-10 23:35:16 -07001419 if (cl->rate)
1420 qdisc_put_rtab(cl->rate);
1421 cl->rate = rtab;
1422 if (cl->ceil)
1423 qdisc_put_rtab(cl->ceil);
1424 cl->ceil = ctab;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 sch_tree_unlock(sch);
1426
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001427 qdisc_class_hash_grow(sch, &q->clhash);
1428
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 *arg = (unsigned long)cl;
1430 return 0;
1431
1432failure:
Stephen Hemminger87990462006-08-10 23:35:16 -07001433 if (rtab)
1434 qdisc_put_rtab(rtab);
1435 if (ctab)
1436 qdisc_put_rtab(ctab);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 return err;
1438}
1439
1440static struct tcf_proto **htb_find_tcf(struct Qdisc *sch, unsigned long arg)
1441{
1442 struct htb_sched *q = qdisc_priv(sch);
1443 struct htb_class *cl = (struct htb_class *)arg;
1444 struct tcf_proto **fl = cl ? &cl->filter_list : &q->filter_list;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001445
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 return fl;
1447}
1448
1449static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent,
Stephen Hemminger87990462006-08-10 23:35:16 -07001450 u32 classid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451{
Stephen Hemminger87990462006-08-10 23:35:16 -07001452 struct htb_class *cl = htb_find(classid, sch);
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001453
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 /*if (cl && !cl->level) return 0;
Stephen Hemminger87990462006-08-10 23:35:16 -07001455 The line above used to be there to prevent attaching filters to
1456 leaves. But at least tc_index filter uses this just to get class
1457 for other reasons so that we have to allow for it.
1458 ----
1459 19.6.2002 As Werner explained it is ok - bind filter is just
1460 another way to "lock" the class - unlike "get" this lock can
1461 be broken by class during destroy IIUC.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 */
Stephen Hemminger87990462006-08-10 23:35:16 -07001463 if (cl)
1464 cl->filter_cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 return (unsigned long)cl;
1466}
1467
1468static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg)
1469{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 struct htb_class *cl = (struct htb_class *)arg;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001471
Stephen Hemminger87990462006-08-10 23:35:16 -07001472 if (cl)
1473 cl->filter_cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474}
1475
1476static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg)
1477{
1478 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001479 struct htb_class *cl;
1480 struct hlist_node *n;
1481 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
1483 if (arg->stop)
1484 return;
1485
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001486 for (i = 0; i < q->clhash.hashsize; i++) {
1487 hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 if (arg->count < arg->skip) {
1489 arg->count++;
1490 continue;
1491 }
1492 if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
1493 arg->stop = 1;
1494 return;
1495 }
1496 arg->count++;
1497 }
1498 }
1499}
1500
Eric Dumazet20fea082007-11-14 01:44:41 -08001501static const struct Qdisc_class_ops htb_class_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 .graft = htb_graft,
1503 .leaf = htb_leaf,
Patrick McHardy256d61b2006-11-29 17:37:05 -08001504 .qlen_notify = htb_qlen_notify,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 .get = htb_get,
1506 .put = htb_put,
1507 .change = htb_change_class,
1508 .delete = htb_delete,
1509 .walk = htb_walk,
1510 .tcf_chain = htb_find_tcf,
1511 .bind_tcf = htb_bind_filter,
1512 .unbind_tcf = htb_unbind_filter,
1513 .dump = htb_dump_class,
1514 .dump_stats = htb_dump_class_stats,
1515};
1516
Eric Dumazet20fea082007-11-14 01:44:41 -08001517static struct Qdisc_ops htb_qdisc_ops __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 .next = NULL,
1519 .cl_ops = &htb_class_ops,
1520 .id = "htb",
1521 .priv_size = sizeof(struct htb_sched),
1522 .enqueue = htb_enqueue,
1523 .dequeue = htb_dequeue,
Jarek Poplawski77be1552008-10-31 00:47:01 -07001524 .peek = qdisc_peek_dequeued,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 .drop = htb_drop,
1526 .init = htb_init,
1527 .reset = htb_reset,
1528 .destroy = htb_destroy,
1529 .change = NULL /* htb_change */,
1530 .dump = htb_dump,
1531 .owner = THIS_MODULE,
1532};
1533
1534static int __init htb_module_init(void)
1535{
Stephen Hemminger87990462006-08-10 23:35:16 -07001536 return register_qdisc(&htb_qdisc_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537}
Stephen Hemminger87990462006-08-10 23:35:16 -07001538static void __exit htb_module_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539{
Stephen Hemminger87990462006-08-10 23:35:16 -07001540 unregister_qdisc(&htb_qdisc_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541}
Stephen Hemminger87990462006-08-10 23:35:16 -07001542
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543module_init(htb_module_init)
1544module_exit(htb_module_exit)
1545MODULE_LICENSE("GPL");