blob: 571f1d211f4d52482c137f6a80aa02e3496e7984 [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>
Jarek Poplawski12247362009-02-01 01:13:22 -080038#include <linux/workqueue.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090039#include <linux/slab.h>
Patrick McHardy0ba48052007-07-02 22:49:07 -070040#include <net/netlink.h>
Jiri Pirko292f1c72013-02-12 00:12:03 +000041#include <net/sch_generic.h>
Patrick McHardy0ba48052007-07-02 22:49:07 -070042#include <net/pkt_sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
44/* HTB algorithm.
45 Author: devik@cdi.cz
46 ========================================================================
47 HTB is like TBF with multiple classes. It is also similar to CBQ because
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +090048 it allows to assign priority to each class in hierarchy.
Linus Torvalds1da177e2005-04-16 15:20:36 -070049 In fact it is another implementation of Floyd's formal sharing.
50
51 Levels:
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +090052 Each class is assigned level. Leaf has ALWAYS level 0 and root
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 classes have level TC_HTB_MAXDEPTH-1. Interior nodes has level
54 one less than their parent.
55*/
56
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -070057static int htb_hysteresis __read_mostly = 0; /* whether to use mode hysteresis for speedup */
Stephen Hemminger87990462006-08-10 23:35:16 -070058#define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60#if HTB_VER >> 16 != TC_HTB_PROTOVER
61#error "Mismatched sch_htb.c and pkt_sch.h"
62#endif
63
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -070064/* Module parameter and sysfs export */
65module_param (htb_hysteresis, int, 0640);
66MODULE_PARM_DESC(htb_hysteresis, "Hysteresis mode, less CPU load, less accurate");
67
Linus Torvalds1da177e2005-04-16 15:20:36 -070068/* used internaly to keep status of single class */
69enum htb_cmode {
Stephen Hemminger87990462006-08-10 23:35:16 -070070 HTB_CANT_SEND, /* class can't send and can't borrow */
71 HTB_MAY_BORROW, /* class can't send but may borrow */
72 HTB_CAN_SEND /* class can send */
Linus Torvalds1da177e2005-04-16 15:20:36 -070073};
74
75/* interior & leaf nodes; props specific to leaves are marked L: */
Stephen Hemminger87990462006-08-10 23:35:16 -070076struct htb_class {
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -070077 struct Qdisc_class_common common;
Stephen Hemminger87990462006-08-10 23:35:16 -070078 /* general class parameters */
Eric Dumazetc1a8f1f2009-08-16 09:36:49 +000079 struct gnet_stats_basic_packed bstats;
Stephen Hemminger87990462006-08-10 23:35:16 -070080 struct gnet_stats_queue qstats;
81 struct gnet_stats_rate_est rate_est;
82 struct tc_htb_xstats xstats; /* our special stats */
83 int refcnt; /* usage count of this class */
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
Stephen Hemminger87990462006-08-10 23:35:16 -070085 /* topology */
86 int level; /* our level (see above) */
Patrick McHardy42077592008-07-05 23:22:53 -070087 unsigned int children;
Stephen Hemminger87990462006-08-10 23:35:16 -070088 struct htb_class *parent; /* parent class */
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
Jarek Poplawskic19f7a32008-12-03 21:09:45 -080090 int prio; /* these two are used only by leaves... */
91 int quantum; /* but stored for parent-to-leaf return */
92
Stephen Hemminger87990462006-08-10 23:35:16 -070093 union {
94 struct htb_class_leaf {
95 struct Qdisc *q;
Stephen Hemminger87990462006-08-10 23:35:16 -070096 int deficit[TC_HTB_MAXDEPTH];
97 struct list_head drop_list;
98 } leaf;
99 struct htb_class_inner {
100 struct rb_root feed[TC_HTB_NUMPRIO]; /* feed trees */
101 struct rb_node *ptr[TC_HTB_NUMPRIO]; /* current class ptr */
102 /* When class changes from state 1->2 and disconnects from
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000103 * parent's feed then we lost ptr value and start from the
104 * first child again. Here we store classid of the
105 * last valid ptr (used when ptr is NULL).
106 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700107 u32 last_ptr_id[TC_HTB_NUMPRIO];
108 } inner;
109 } un;
110 struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */
111 struct rb_node pq_node; /* node for event queue */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700112 psched_time_t pq_key;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
Stephen Hemminger87990462006-08-10 23:35:16 -0700114 int prio_activity; /* for which prios are we active */
115 enum htb_cmode cmode; /* current mode of the class */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
Stephen Hemminger87990462006-08-10 23:35:16 -0700117 /* class attached filters */
118 struct tcf_proto *filter_list;
119 int filter_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
Stephen Hemminger87990462006-08-10 23:35:16 -0700121 /* token bucket parameters */
Jiri Pirko292f1c72013-02-12 00:12:03 +0000122 struct psched_ratecfg rate;
123 struct psched_ratecfg ceil;
Vimalkumar56b765b2012-10-31 06:04:11 +0000124 s64 buffer, cbuffer; /* token bucket depth/rate */
Stephen Hemminger87990462006-08-10 23:35:16 -0700125 psched_tdiff_t mbuffer; /* max wait time */
Vimalkumar56b765b2012-10-31 06:04:11 +0000126 s64 tokens, ctokens; /* current number of tokens */
Stephen Hemminger87990462006-08-10 23:35:16 -0700127 psched_time_t t_c; /* checkpoint time */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128};
129
Stephen Hemminger87990462006-08-10 23:35:16 -0700130struct htb_sched {
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700131 struct Qdisc_class_hash clhash;
Stephen Hemminger0cef2962006-08-10 23:35:38 -0700132 struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
Stephen Hemminger87990462006-08-10 23:35:16 -0700134 /* self list - roots of self generating tree */
135 struct rb_root row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
136 int row_mask[TC_HTB_MAXDEPTH];
137 struct rb_node *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
138 u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Stephen Hemminger87990462006-08-10 23:35:16 -0700140 /* self wait list - roots of wait PQs per row */
141 struct rb_root wait_pq[TC_HTB_MAXDEPTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
Stephen Hemminger87990462006-08-10 23:35:16 -0700143 /* time of nearest event per level (row) */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700144 psched_time_t near_ev_cache[TC_HTB_MAXDEPTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
Stephen Hemminger87990462006-08-10 23:35:16 -0700146 int defcls; /* class where unclassified flows go to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
Stephen Hemminger87990462006-08-10 23:35:16 -0700148 /* filters for qdisc itself */
149 struct tcf_proto *filter_list;
Stephen Hemminger87990462006-08-10 23:35:16 -0700150
151 int rate2quantum; /* quant = rate / rate2quantum */
152 psched_time_t now; /* cached dequeue time */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700153 struct qdisc_watchdog watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154
Stephen Hemminger87990462006-08-10 23:35:16 -0700155 /* non shaped skbs; let them go directly thru */
156 struct sk_buff_head direct_queue;
157 int direct_qlen; /* max qlen of above */
158
159 long direct_pkts;
Jarek Poplawskie82181d2009-02-01 01:13:05 -0800160
161#define HTB_WARN_TOOMANYEVENTS 0x1
162 unsigned int warned; /* only one warning */
Jarek Poplawski12247362009-02-01 01:13:22 -0800163 struct work_struct work;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164};
165
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166/* find class in global hash table using given handle */
Stephen Hemminger87990462006-08-10 23:35:16 -0700167static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168{
169 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700170 struct Qdisc_class_common *clc;
Stephen Hemminger0cef2962006-08-10 23:35:38 -0700171
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700172 clc = qdisc_class_find(&q->clhash, handle);
173 if (clc == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 return NULL;
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700175 return container_of(clc, struct htb_class, common);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176}
177
178/**
179 * htb_classify - classify a packet into class
180 *
181 * It returns NULL if the packet should be dropped or -1 if the packet
182 * should be passed directly thru. In all other cases leaf class is returned.
183 * We allow direct class selection by classid in priority. The we examine
184 * filters in qdisc and in inner nodes (if higher filter points to the inner
185 * node). If we end up with classid MAJOR:0 we enqueue the skb into special
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900186 * internal fifo (direct). These packets then go directly thru. If we still
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300187 * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessful
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 * then finish and return direct queue.
189 */
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000190#define HTB_DIRECT ((struct htb_class *)-1L)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191
Stephen Hemminger87990462006-08-10 23:35:16 -0700192static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
193 int *qerr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194{
195 struct htb_sched *q = qdisc_priv(sch);
196 struct htb_class *cl;
197 struct tcf_result res;
198 struct tcf_proto *tcf;
199 int result;
200
201 /* allow to select class by setting skb->priority to valid classid;
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000202 * note that nfmark can be used too by attaching filter fw with no
203 * rules in it
204 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 if (skb->priority == sch->handle)
Stephen Hemminger87990462006-08-10 23:35:16 -0700206 return HTB_DIRECT; /* X:0 (direct flow) selected */
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000207 cl = htb_find(skb->priority, sch);
208 if (cl && cl->level == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 return cl;
210
Jarek Poplawskic27f3392008-08-04 22:39:11 -0700211 *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 tcf = q->filter_list;
213 while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
214#ifdef CONFIG_NET_CLS_ACT
215 switch (result) {
216 case TC_ACT_QUEUED:
Stephen Hemminger87990462006-08-10 23:35:16 -0700217 case TC_ACT_STOLEN:
Jarek Poplawski378a2f02008-08-04 22:31:03 -0700218 *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 case TC_ACT_SHOT:
220 return NULL;
221 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222#endif
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000223 cl = (void *)res.class;
224 if (!cl) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 if (res.classid == sch->handle)
Stephen Hemminger87990462006-08-10 23:35:16 -0700226 return HTB_DIRECT; /* X:0 (direct flow) */
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000227 cl = htb_find(res.classid, sch);
228 if (!cl)
Stephen Hemminger87990462006-08-10 23:35:16 -0700229 break; /* filter selected invalid classid */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 }
231 if (!cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700232 return cl; /* we hit leaf; return it */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
234 /* we have got inner class; apply inner filter chain */
235 tcf = cl->filter_list;
236 }
237 /* classification failed; try to use default class */
Stephen Hemminger87990462006-08-10 23:35:16 -0700238 cl = htb_find(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 if (!cl || cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700240 return HTB_DIRECT; /* bad default .. this is safe bet */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 return cl;
242}
243
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244/**
245 * htb_add_to_id_tree - adds class to the round robin list
246 *
247 * Routine adds class to the list (actually tree) sorted by classid.
248 * Make sure that class is not already on such list for given prio.
249 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700250static void htb_add_to_id_tree(struct rb_root *root,
251 struct htb_class *cl, int prio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252{
253 struct rb_node **p = &root->rb_node, *parent = NULL;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700254
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 while (*p) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700256 struct htb_class *c;
257 parent = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 c = rb_entry(parent, struct htb_class, node[prio]);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700259
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700260 if (cl->common.classid > c->common.classid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 p = &parent->rb_right;
Stephen Hemminger87990462006-08-10 23:35:16 -0700262 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 p = &parent->rb_left;
264 }
265 rb_link_node(&cl->node[prio], parent, p);
266 rb_insert_color(&cl->node[prio], root);
267}
268
269/**
270 * htb_add_to_wait_tree - adds class to the event queue with delay
271 *
272 * The class is added to priority event queue to indicate that class will
273 * change its mode in cl->pq_key microseconds. Make sure that class is not
274 * already in the queue.
275 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700276static void htb_add_to_wait_tree(struct htb_sched *q,
Vimalkumar56b765b2012-10-31 06:04:11 +0000277 struct htb_class *cl, s64 delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278{
279 struct rb_node **p = &q->wait_pq[cl->level].rb_node, *parent = NULL;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700280
Patrick McHardyfb983d42007-03-16 01:22:39 -0700281 cl->pq_key = q->now + delay;
282 if (cl->pq_key == q->now)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 cl->pq_key++;
284
285 /* update the nearest event cache */
Patrick McHardyfb983d42007-03-16 01:22:39 -0700286 if (q->near_ev_cache[cl->level] > cl->pq_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 q->near_ev_cache[cl->level] = cl->pq_key;
Stephen Hemminger87990462006-08-10 23:35:16 -0700288
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 while (*p) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700290 struct htb_class *c;
291 parent = *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 c = rb_entry(parent, struct htb_class, pq_node);
Patrick McHardyfb983d42007-03-16 01:22:39 -0700293 if (cl->pq_key >= c->pq_key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 p = &parent->rb_right;
Stephen Hemminger87990462006-08-10 23:35:16 -0700295 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 p = &parent->rb_left;
297 }
298 rb_link_node(&cl->pq_node, parent, p);
299 rb_insert_color(&cl->pq_node, &q->wait_pq[cl->level]);
300}
301
302/**
303 * htb_next_rb_node - finds next node in binary tree
304 *
305 * When we are past last key we return NULL.
306 * Average complexity is 2 steps per call.
307 */
Stephen Hemminger3696f622006-08-10 23:36:01 -0700308static inline void htb_next_rb_node(struct rb_node **n)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309{
310 *n = rb_next(*n);
311}
312
313/**
314 * htb_add_class_to_row - add class to its row
315 *
316 * The class is added to row at priorities marked in mask.
317 * It does nothing if mask == 0.
318 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700319static inline void htb_add_class_to_row(struct htb_sched *q,
320 struct htb_class *cl, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 q->row_mask[cl->level] |= mask;
323 while (mask) {
324 int prio = ffz(~mask);
325 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700326 htb_add_to_id_tree(q->row[cl->level] + prio, cl, prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 }
328}
329
Stephen Hemminger3696f622006-08-10 23:36:01 -0700330/* If this triggers, it is a bug in this code, but it need not be fatal */
331static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root)
332{
Ismail Donmez81771b32006-10-03 13:49:10 -0700333 if (RB_EMPTY_NODE(rb)) {
Stephen Hemminger3696f622006-08-10 23:36:01 -0700334 WARN_ON(1);
335 } else {
336 rb_erase(rb, root);
337 RB_CLEAR_NODE(rb);
338 }
339}
340
341
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342/**
343 * htb_remove_class_from_row - removes class from its row
344 *
345 * The class is removed from row at priorities marked in mask.
346 * It does nothing if mask == 0.
347 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700348static inline void htb_remove_class_from_row(struct htb_sched *q,
349 struct htb_class *cl, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350{
351 int m = 0;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 while (mask) {
354 int prio = ffz(~mask);
Stephen Hemminger3696f622006-08-10 23:36:01 -0700355
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700357 if (q->ptr[cl->level][prio] == cl->node + prio)
358 htb_next_rb_node(q->ptr[cl->level] + prio);
Stephen Hemminger3696f622006-08-10 23:36:01 -0700359
360 htb_safe_rb_erase(cl->node + prio, q->row[cl->level] + prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700361 if (!q->row[cl->level][prio].rb_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 m |= 1 << prio;
363 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 q->row_mask[cl->level] &= ~m;
365}
366
367/**
368 * htb_activate_prios - creates active classe's feed chain
369 *
370 * The class is connected to ancestors and/or appropriate rows
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900371 * for priorities it is participating on. cl->cmode must be new
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 * (activated) mode. It does nothing if cl->prio_activity == 0.
373 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700374static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375{
376 struct htb_class *p = cl->parent;
Stephen Hemminger87990462006-08-10 23:35:16 -0700377 long m, mask = cl->prio_activity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700380 m = mask;
381 while (m) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 int prio = ffz(~m);
383 m &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700384
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 if (p->un.inner.feed[prio].rb_node)
386 /* parent already has its feed in use so that
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000387 * reset bit in mask as parent is already ok
388 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 mask &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700390
391 htb_add_to_id_tree(p->un.inner.feed + prio, cl, prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 p->prio_activity |= mask;
Stephen Hemminger87990462006-08-10 23:35:16 -0700394 cl = p;
395 p = cl->parent;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700396
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 }
398 if (cl->cmode == HTB_CAN_SEND && mask)
Stephen Hemminger87990462006-08-10 23:35:16 -0700399 htb_add_class_to_row(q, cl, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400}
401
402/**
403 * htb_deactivate_prios - remove class from feed chain
404 *
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900405 * cl->cmode must represent old mode (before deactivation). It does
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 * nothing if cl->prio_activity == 0. Class is removed from all feed
407 * chains and rows.
408 */
409static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl)
410{
411 struct htb_class *p = cl->parent;
Stephen Hemminger87990462006-08-10 23:35:16 -0700412 long m, mask = cl->prio_activity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
414 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700415 m = mask;
416 mask = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 while (m) {
418 int prio = ffz(~m);
419 m &= ~(1 << prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700420
421 if (p->un.inner.ptr[prio] == cl->node + prio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 /* we are removing child which is pointed to from
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000423 * parent feed - forget the pointer but remember
424 * classid
425 */
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700426 p->un.inner.last_ptr_id[prio] = cl->common.classid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 p->un.inner.ptr[prio] = NULL;
428 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700429
Stephen Hemminger3696f622006-08-10 23:36:01 -0700430 htb_safe_rb_erase(cl->node + prio, p->un.inner.feed + prio);
Stephen Hemminger87990462006-08-10 23:35:16 -0700431
432 if (!p->un.inner.feed[prio].rb_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 mask |= 1 << prio;
434 }
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700435
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 p->prio_activity &= ~mask;
Stephen Hemminger87990462006-08-10 23:35:16 -0700437 cl = p;
438 p = cl->parent;
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700439
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700441 if (cl->cmode == HTB_CAN_SEND && mask)
442 htb_remove_class_from_row(q, cl, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443}
444
Vimalkumar56b765b2012-10-31 06:04:11 +0000445static inline s64 htb_lowater(const struct htb_class *cl)
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700446{
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700447 if (htb_hysteresis)
448 return cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : 0;
449 else
450 return 0;
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700451}
Vimalkumar56b765b2012-10-31 06:04:11 +0000452static inline s64 htb_hiwater(const struct htb_class *cl)
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700453{
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700454 if (htb_hysteresis)
455 return cl->cmode == HTB_CAN_SEND ? -cl->buffer : 0;
456 else
457 return 0;
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700458}
Jesper Dangaard Brouer47083fc2008-06-16 16:39:32 -0700459
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700460
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461/**
462 * htb_class_mode - computes and returns current class mode
463 *
464 * It computes cl's mode at time cl->t_c+diff and returns it. If mode
465 * is not HTB_CAN_SEND then cl->pq_key is updated to time difference
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900466 * from now to time when cl will change its state.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 * Also it is worth to note that class mode doesn't change simply
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900468 * at cl->{c,}tokens == 0 but there can rather be hysteresis of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 * 0 .. -cl->{c,}buffer range. It is meant to limit number of
470 * mode transitions per time unit. The speed gain is about 1/6.
471 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700472static inline enum htb_cmode
Vimalkumar56b765b2012-10-31 06:04:11 +0000473htb_class_mode(struct htb_class *cl, s64 *diff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
Vimalkumar56b765b2012-10-31 06:04:11 +0000475 s64 toks;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476
Stephen Hemminger87990462006-08-10 23:35:16 -0700477 if ((toks = (cl->ctokens + *diff)) < htb_lowater(cl)) {
478 *diff = -toks;
479 return HTB_CANT_SEND;
480 }
Stephen Hemminger18a63e82006-08-10 23:34:02 -0700481
Stephen Hemminger87990462006-08-10 23:35:16 -0700482 if ((toks = (cl->tokens + *diff)) >= htb_hiwater(cl))
483 return HTB_CAN_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
Stephen Hemminger87990462006-08-10 23:35:16 -0700485 *diff = -toks;
486 return HTB_MAY_BORROW;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487}
488
489/**
490 * htb_change_class_mode - changes classe's mode
491 *
492 * This should be the only way how to change classe's mode under normal
493 * cirsumstances. Routine will update feed lists linkage, change mode
494 * and add class to the wait event queue if appropriate. New mode should
495 * be different from old one and cl->pq_key has to be valid if changing
496 * to mode other than HTB_CAN_SEND (see htb_add_to_wait_tree).
497 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700498static void
Vimalkumar56b765b2012-10-31 06:04:11 +0000499htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, s64 *diff)
Stephen Hemminger87990462006-08-10 23:35:16 -0700500{
501 enum htb_cmode new_mode = htb_class_mode(cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
503 if (new_mode == cl->cmode)
Stephen Hemminger87990462006-08-10 23:35:16 -0700504 return;
505
506 if (cl->prio_activity) { /* not necessary: speed optimization */
507 if (cl->cmode != HTB_CANT_SEND)
508 htb_deactivate_prios(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 cl->cmode = new_mode;
Stephen Hemminger87990462006-08-10 23:35:16 -0700510 if (new_mode != HTB_CANT_SEND)
511 htb_activate_prios(q, cl);
512 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 cl->cmode = new_mode;
514}
515
516/**
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900517 * htb_activate - inserts leaf cl into appropriate active feeds
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 *
519 * Routine learns (new) priority of leaf and activates feed chain
520 * for the prio. It can be called on already active leaf safely.
521 * It also adds leaf into droplist.
522 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700523static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524{
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700525 WARN_ON(cl->level || !cl->un.leaf.q || !cl->un.leaf.q->q.qlen);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700526
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 if (!cl->prio_activity) {
Jarek Poplawskic19f7a32008-12-03 21:09:45 -0800528 cl->prio_activity = 1 << cl->prio;
Stephen Hemminger87990462006-08-10 23:35:16 -0700529 htb_activate_prios(q, cl);
530 list_add_tail(&cl->un.leaf.drop_list,
Jarek Poplawskic19f7a32008-12-03 21:09:45 -0800531 q->drops + cl->prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 }
533}
534
535/**
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900536 * htb_deactivate - remove leaf cl from active feeds
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 *
538 * Make sure that leaf is active. In the other words it can't be called
539 * with non-active leaf. It also removes class from the drop list.
540 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700541static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542{
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700543 WARN_ON(!cl->prio_activity);
Stephen Hemminger3bf72952006-08-10 23:31:08 -0700544
Stephen Hemminger87990462006-08-10 23:35:16 -0700545 htb_deactivate_prios(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 cl->prio_activity = 0;
547 list_del_init(&cl->un.leaf.drop_list);
548}
549
550static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
551{
Jarek Poplawskif30ab412008-11-13 22:56:30 -0800552 int uninitialized_var(ret);
Stephen Hemminger87990462006-08-10 23:35:16 -0700553 struct htb_sched *q = qdisc_priv(sch);
554 struct htb_class *cl = htb_classify(skb, sch, &ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
Stephen Hemminger87990462006-08-10 23:35:16 -0700556 if (cl == HTB_DIRECT) {
557 /* enqueue to helper queue */
558 if (q->direct_queue.qlen < q->direct_qlen) {
559 __skb_queue_tail(&q->direct_queue, skb);
560 q->direct_pkts++;
561 } else {
Eric Dumazet17045752012-05-04 04:37:21 +0000562 return qdisc_drop(skb, sch);
Stephen Hemminger87990462006-08-10 23:35:16 -0700563 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564#ifdef CONFIG_NET_CLS_ACT
Stephen Hemminger87990462006-08-10 23:35:16 -0700565 } else if (!cl) {
Jarek Poplawskic27f3392008-08-04 22:39:11 -0700566 if (ret & __NET_XMIT_BYPASS)
Stephen Hemminger87990462006-08-10 23:35:16 -0700567 sch->qstats.drops++;
568 kfree_skb(skb);
569 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570#endif
Jarek Poplawski378a2f02008-08-04 22:31:03 -0700571 } else if ((ret = qdisc_enqueue(skb, cl->un.leaf.q)) != NET_XMIT_SUCCESS) {
572 if (net_xmit_drop_count(ret)) {
573 sch->qstats.drops++;
574 cl->qstats.drops++;
575 }
David S. Miller69747652008-08-17 23:55:36 -0700576 return ret;
Stephen Hemminger87990462006-08-10 23:35:16 -0700577 } else {
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++;
Stephen Hemminger87990462006-08-10 23:35:16 -0700582 return NET_XMIT_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583}
584
Vimalkumar56b765b2012-10-31 06:04:11 +0000585static inline void htb_accnt_tokens(struct htb_class *cl, int bytes, s64 diff)
Jarek Poplawski59e42202008-12-03 21:17:27 -0800586{
Vimalkumar56b765b2012-10-31 06:04:11 +0000587 s64 toks = diff + cl->tokens;
Jarek Poplawski59e42202008-12-03 21:17:27 -0800588
589 if (toks > cl->buffer)
590 toks = cl->buffer;
Jiri Pirko292f1c72013-02-12 00:12:03 +0000591 toks -= (s64) psched_l2t_ns(&cl->rate, bytes);
Jarek Poplawski59e42202008-12-03 21:17:27 -0800592 if (toks <= -cl->mbuffer)
593 toks = 1 - cl->mbuffer;
594
595 cl->tokens = toks;
596}
597
Vimalkumar56b765b2012-10-31 06:04:11 +0000598static inline void htb_accnt_ctokens(struct htb_class *cl, int bytes, s64 diff)
Jarek Poplawski59e42202008-12-03 21:17:27 -0800599{
Vimalkumar56b765b2012-10-31 06:04:11 +0000600 s64 toks = diff + cl->ctokens;
Jarek Poplawski59e42202008-12-03 21:17:27 -0800601
602 if (toks > cl->cbuffer)
603 toks = cl->cbuffer;
Jiri Pirko292f1c72013-02-12 00:12:03 +0000604 toks -= (s64) psched_l2t_ns(&cl->ceil, bytes);
Jarek Poplawski59e42202008-12-03 21:17:27 -0800605 if (toks <= -cl->mbuffer)
606 toks = 1 - cl->mbuffer;
607
608 cl->ctokens = toks;
609}
610
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611/**
612 * htb_charge_class - charges amount "bytes" to leaf and ancestors
613 *
614 * Routine assumes that packet "bytes" long was dequeued from leaf cl
615 * borrowing from "level". It accounts bytes to ceil leaky bucket for
616 * leaf and all ancestors and to rate bucket for ancestors at levels
617 * "level" and higher. It also handles possible change of mode resulting
618 * from the update. Note that mode can also increase here (MAY_BORROW to
619 * CAN_SEND) because we can use more precise clock that event queue here.
620 * In such case we remove class from event queue first.
621 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700622static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700623 int level, struct sk_buff *skb)
Stephen Hemminger87990462006-08-10 23:35:16 -0700624{
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700625 int bytes = qdisc_pkt_len(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 enum htb_cmode old_mode;
Vimalkumar56b765b2012-10-31 06:04:11 +0000627 s64 diff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
629 while (cl) {
Vimalkumar56b765b2012-10-31 06:04:11 +0000630 diff = min_t(s64, q->now - cl->t_c, cl->mbuffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 if (cl->level >= level) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700632 if (cl->level == level)
633 cl->xstats.lends++;
Jarek Poplawski59e42202008-12-03 21:17:27 -0800634 htb_accnt_tokens(cl, bytes, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 } else {
636 cl->xstats.borrows++;
Stephen Hemminger87990462006-08-10 23:35:16 -0700637 cl->tokens += diff; /* we moved t_c; update tokens */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 }
Jarek Poplawski59e42202008-12-03 21:17:27 -0800639 htb_accnt_ctokens(cl, bytes, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 cl->t_c = q->now;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
Stephen Hemminger87990462006-08-10 23:35:16 -0700642 old_mode = cl->cmode;
643 diff = 0;
644 htb_change_class_mode(q, cl, &diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 if (old_mode != cl->cmode) {
646 if (old_mode != HTB_CAN_SEND)
Stephen Hemminger3696f622006-08-10 23:36:01 -0700647 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 if (cl->cmode != HTB_CAN_SEND)
Stephen Hemminger87990462006-08-10 23:35:16 -0700649 htb_add_to_wait_tree(q, cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
Eric Dumazetbfe0d022011-01-09 08:30:54 +0000652 /* update basic stats except for leaves which are already updated */
653 if (cl->level)
654 bstats_update(&cl->bstats, skb);
655
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 cl = cl->parent;
657 }
658}
659
660/**
661 * htb_do_events - make mode changes to classes at the level
662 *
Patrick McHardyfb983d42007-03-16 01:22:39 -0700663 * Scans event queue for pending events and applies them. Returns time of
Jarek Poplawski12247362009-02-01 01:13:22 -0800664 * next pending event (0 for no event in pq, q->now for too many events).
Patrick McHardyfb983d42007-03-16 01:22:39 -0700665 * Note: Applied are events whose have cl->pq_key <= q->now.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 */
Jarek Poplawskia73be042009-01-12 21:54:40 -0800667static psched_time_t htb_do_events(struct htb_sched *q, int level,
668 unsigned long start)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669{
Martin Devera8f3ea332008-03-23 22:00:38 -0700670 /* don't run for longer than 2 jiffies; 2 is used instead of
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000671 * 1 to simplify things when jiffy is going to be incremented
672 * too soon
673 */
Jarek Poplawskia73be042009-01-12 21:54:40 -0800674 unsigned long stop_at = start + 2;
Martin Devera8f3ea332008-03-23 22:00:38 -0700675 while (time_before(jiffies, stop_at)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 struct htb_class *cl;
Vimalkumar56b765b2012-10-31 06:04:11 +0000677 s64 diff;
Akinbou Mita30bdbe32006-10-12 01:52:05 -0700678 struct rb_node *p = rb_first(&q->wait_pq[level]);
679
Stephen Hemminger87990462006-08-10 23:35:16 -0700680 if (!p)
681 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
683 cl = rb_entry(p, struct htb_class, pq_node);
Patrick McHardyfb983d42007-03-16 01:22:39 -0700684 if (cl->pq_key > q->now)
685 return cl->pq_key;
686
Stephen Hemminger3696f622006-08-10 23:36:01 -0700687 htb_safe_rb_erase(p, q->wait_pq + level);
Vimalkumar56b765b2012-10-31 06:04:11 +0000688 diff = min_t(s64, q->now - cl->t_c, cl->mbuffer);
Stephen Hemminger87990462006-08-10 23:35:16 -0700689 htb_change_class_mode(q, cl, &diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 if (cl->cmode != HTB_CAN_SEND)
Stephen Hemminger87990462006-08-10 23:35:16 -0700691 htb_add_to_wait_tree(q, cl, diff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 }
Jarek Poplawski12247362009-02-01 01:13:22 -0800693
694 /* too much load - let's continue after a break for scheduling */
Jarek Poplawskie82181d2009-02-01 01:13:05 -0800695 if (!(q->warned & HTB_WARN_TOOMANYEVENTS)) {
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000696 pr_warning("htb: too many events!\n");
Jarek Poplawskie82181d2009-02-01 01:13:05 -0800697 q->warned |= HTB_WARN_TOOMANYEVENTS;
698 }
Jarek Poplawski12247362009-02-01 01:13:22 -0800699
700 return q->now;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701}
702
703/* Returns class->node+prio from id-tree where classe's id is >= id. NULL
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000704 * is no such one exists.
705 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700706static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n,
707 u32 id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708{
709 struct rb_node *r = NULL;
710 while (n) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700711 struct htb_class *cl =
712 rb_entry(n, struct htb_class, node[prio]);
Stephen Hemminger87990462006-08-10 23:35:16 -0700713
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700714 if (id > cl->common.classid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 n = n->rb_right;
Jarek Poplawski1b5c0072008-12-09 22:34:40 -0800716 } else if (id < cl->common.classid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 r = n;
718 n = n->rb_left;
Jarek Poplawski1b5c0072008-12-09 22:34:40 -0800719 } else {
720 return n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 }
722 }
723 return r;
724}
725
726/**
727 * htb_lookup_leaf - returns next leaf class in DRR order
728 *
729 * Find leaf where current feed pointers points to.
730 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700731static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
732 struct rb_node **pptr, u32 * pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733{
734 int i;
735 struct {
736 struct rb_node *root;
737 struct rb_node **pptr;
738 u32 *pid;
Stephen Hemminger87990462006-08-10 23:35:16 -0700739 } stk[TC_HTB_MAXDEPTH], *sp = stk;
740
Jarek Poplawski512bb432008-12-09 22:35:02 -0800741 BUG_ON(!tree->rb_node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 sp->root = tree->rb_node;
743 sp->pptr = pptr;
744 sp->pid = pid;
745
746 for (i = 0; i < 65535; i++) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700747 if (!*sp->pptr && *sp->pid) {
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900748 /* ptr was invalidated but id is valid - try to recover
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000749 * the original or next ptr
750 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700751 *sp->pptr =
752 htb_id_find_next_upper(prio, sp->root, *sp->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700754 *sp->pid = 0; /* ptr is valid now so that remove this hint as it
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000755 * can become out of date quickly
756 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700757 if (!*sp->pptr) { /* we are at right end; rewind & go up */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 *sp->pptr = sp->root;
Stephen Hemminger87990462006-08-10 23:35:16 -0700759 while ((*sp->pptr)->rb_left)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 *sp->pptr = (*sp->pptr)->rb_left;
761 if (sp > stk) {
762 sp--;
Jarek Poplawski512bb432008-12-09 22:35:02 -0800763 if (!*sp->pptr) {
764 WARN_ON(1);
Stephen Hemminger87990462006-08-10 23:35:16 -0700765 return NULL;
Jarek Poplawski512bb432008-12-09 22:35:02 -0800766 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700767 htb_next_rb_node(sp->pptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 }
769 } else {
770 struct htb_class *cl;
Stephen Hemminger87990462006-08-10 23:35:16 -0700771 cl = rb_entry(*sp->pptr, struct htb_class, node[prio]);
772 if (!cl->level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 return cl;
774 (++sp)->root = cl->un.inner.feed[prio].rb_node;
Stephen Hemminger87990462006-08-10 23:35:16 -0700775 sp->pptr = cl->un.inner.ptr + prio;
776 sp->pid = cl->un.inner.last_ptr_id + prio;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 }
778 }
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700779 WARN_ON(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 return NULL;
781}
782
783/* dequeues packet at given priority and level; call only if
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000784 * you are sure that there is active class at prio/level
785 */
Stephen Hemminger87990462006-08-10 23:35:16 -0700786static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio,
787 int level)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788{
789 struct sk_buff *skb = NULL;
Stephen Hemminger87990462006-08-10 23:35:16 -0700790 struct htb_class *cl, *start;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 /* look initial class up in the row */
Stephen Hemminger87990462006-08-10 23:35:16 -0700792 start = cl = htb_lookup_leaf(q->row[level] + prio, prio,
793 q->ptr[level] + prio,
794 q->last_ptr_id[level] + prio);
795
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 do {
797next:
Jarek Poplawski512bb432008-12-09 22:35:02 -0800798 if (unlikely(!cl))
Stephen Hemminger87990462006-08-10 23:35:16 -0700799 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800
801 /* class can be empty - it is unlikely but can be true if leaf
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000802 * qdisc drops packets in enqueue routine or if someone used
803 * graft operation on the leaf since last dequeue;
804 * simply deactivate and skip such class
805 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 if (unlikely(cl->un.leaf.q->q.qlen == 0)) {
807 struct htb_class *next;
Stephen Hemminger87990462006-08-10 23:35:16 -0700808 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809
810 /* row/level might become empty */
811 if ((q->row_mask[level] & (1 << prio)) == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -0700812 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
Stephen Hemminger87990462006-08-10 23:35:16 -0700814 next = htb_lookup_leaf(q->row[level] + prio,
815 prio, q->ptr[level] + prio,
816 q->last_ptr_id[level] + prio);
817
818 if (cl == start) /* fix start if we just deleted it */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 start = next;
820 cl = next;
821 goto next;
822 }
Stephen Hemminger87990462006-08-10 23:35:16 -0700823
824 skb = cl->un.leaf.q->dequeue(cl->un.leaf.q);
825 if (likely(skb != NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 break;
Jarek Poplawski633fe662008-12-03 21:09:10 -0800827
Jarek Poplawskib00355d2009-02-01 01:12:42 -0800828 qdisc_warn_nonwc("htb", cl->un.leaf.q);
Stephen Hemminger87990462006-08-10 23:35:16 -0700829 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
830 ptr[0]) + prio);
831 cl = htb_lookup_leaf(q->row[level] + prio, prio,
832 q->ptr[level] + prio,
833 q->last_ptr_id[level] + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834
835 } while (cl != start);
836
837 if (likely(skb != NULL)) {
Eric Dumazet196d97f2012-11-05 16:40:49 +0000838 bstats_update(&cl->bstats, skb);
Jussi Kivilinna0abf77e2008-07-20 00:08:27 -0700839 cl->un.leaf.deficit[level] -= qdisc_pkt_len(skb);
840 if (cl->un.leaf.deficit[level] < 0) {
Jarek Poplawskic19f7a32008-12-03 21:09:45 -0800841 cl->un.leaf.deficit[level] += cl->quantum;
Stephen Hemminger87990462006-08-10 23:35:16 -0700842 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
843 ptr[0]) + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 }
845 /* this used to be after charge_class but this constelation
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000846 * gives us slightly better performance
847 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 if (!cl->un.leaf.q->q.qlen)
Stephen Hemminger87990462006-08-10 23:35:16 -0700849 htb_deactivate(q, cl);
Ranjit Manomohanc9726d62007-07-10 22:43:16 -0700850 htb_charge_class(q, cl, level, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 }
852 return skb;
853}
854
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855static struct sk_buff *htb_dequeue(struct Qdisc *sch)
856{
Eric Dumazet9190b3b2011-01-20 23:31:33 -0800857 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 struct htb_sched *q = qdisc_priv(sch);
859 int level;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700860 psched_time_t next_event;
Jarek Poplawskia73be042009-01-12 21:54:40 -0800861 unsigned long start_at;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
863 /* try to dequeue direct packets as high prio (!) to minimize cpu work */
Stephen Hemminger87990462006-08-10 23:35:16 -0700864 skb = __skb_dequeue(&q->direct_queue);
865 if (skb != NULL) {
Eric Dumazet9190b3b2011-01-20 23:31:33 -0800866ok:
867 qdisc_bstats_update(sch, skb);
Eric Dumazetfd245a42011-01-20 05:27:16 +0000868 qdisc_unthrottled(sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 sch->q.qlen--;
870 return skb;
871 }
872
Stephen Hemminger87990462006-08-10 23:35:16 -0700873 if (!sch->q.qlen)
874 goto fin;
Vimalkumar56b765b2012-10-31 06:04:11 +0000875 q->now = ktime_to_ns(ktime_get());
Jarek Poplawskia73be042009-01-12 21:54:40 -0800876 start_at = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877
Stefan Haskod2fe85d2012-12-21 15:04:59 +0000878 next_event = q->now + 5LLU * NSEC_PER_SEC;
Jarek Poplawski633fe662008-12-03 21:09:10 -0800879
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
881 /* common case optimization - skip event handler quickly */
882 int m;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700883 psched_time_t event;
Stephen Hemminger87990462006-08-10 23:35:16 -0700884
Patrick McHardyfb983d42007-03-16 01:22:39 -0700885 if (q->now >= q->near_ev_cache[level]) {
Jarek Poplawskia73be042009-01-12 21:54:40 -0800886 event = htb_do_events(q, level, start_at);
Patrick McHardy2e4b3b02007-05-23 23:39:54 -0700887 if (!event)
Vimalkumar56b765b2012-10-31 06:04:11 +0000888 event = q->now + NSEC_PER_SEC;
Patrick McHardy2e4b3b02007-05-23 23:39:54 -0700889 q->near_ev_cache[level] = event;
Patrick McHardyfb983d42007-03-16 01:22:39 -0700890 } else
891 event = q->near_ev_cache[level];
892
Jarek Poplawskic0851342009-01-12 21:54:16 -0800893 if (next_event > event)
Patrick McHardyfb983d42007-03-16 01:22:39 -0700894 next_event = event;
895
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 m = ~q->row_mask[level];
897 while (m != (int)(-1)) {
Stephen Hemminger87990462006-08-10 23:35:16 -0700898 int prio = ffz(m);
Eric Dumazetcc7ec452011-01-19 19:26:56 +0000899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 m |= 1 << prio;
Stephen Hemminger87990462006-08-10 23:35:16 -0700901 skb = htb_dequeue_tree(q, prio, level);
Eric Dumazet9190b3b2011-01-20 23:31:33 -0800902 if (likely(skb != NULL))
903 goto ok;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 }
905 }
Patrick McHardyfb983d42007-03-16 01:22:39 -0700906 sch->qstats.overlimits++;
Vimalkumar56b765b2012-10-31 06:04:11 +0000907 if (likely(next_event > q->now)) {
908 if (!test_bit(__QDISC_STATE_DEACTIVATED,
909 &qdisc_root_sleeping(q->watchdog.qdisc)->state)) {
910 ktime_t time = ns_to_ktime(next_event);
911 qdisc_throttled(q->watchdog.qdisc);
912 hrtimer_start(&q->watchdog.timer, time,
913 HRTIMER_MODE_ABS);
914 }
915 } else {
Jarek Poplawski12247362009-02-01 01:13:22 -0800916 schedule_work(&q->work);
Vimalkumar56b765b2012-10-31 06:04:11 +0000917 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918fin:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 return skb;
920}
921
922/* try to drop from each class (by prio) until one succeed */
Stephen Hemminger87990462006-08-10 23:35:16 -0700923static unsigned int htb_drop(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924{
925 struct htb_sched *q = qdisc_priv(sch);
926 int prio;
927
928 for (prio = TC_HTB_NUMPRIO - 1; prio >= 0; prio--) {
929 struct list_head *p;
Stephen Hemminger87990462006-08-10 23:35:16 -0700930 list_for_each(p, q->drops + prio) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 struct htb_class *cl = list_entry(p, struct htb_class,
932 un.leaf.drop_list);
933 unsigned int len;
Stephen Hemminger87990462006-08-10 23:35:16 -0700934 if (cl->un.leaf.q->ops->drop &&
935 (len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 sch->q.qlen--;
937 if (!cl->un.leaf.q->q.qlen)
Stephen Hemminger87990462006-08-10 23:35:16 -0700938 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 return len;
940 }
941 }
942 }
943 return 0;
944}
945
946/* reset all classes */
947/* always caled under BH & queue lock */
Stephen Hemminger87990462006-08-10 23:35:16 -0700948static void htb_reset(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949{
950 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700951 struct htb_class *cl;
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700952 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -0700954 for (i = 0; i < q->clhash.hashsize; i++) {
Sasha Levinb67bfe02013-02-27 17:06:00 -0800955 hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 if (cl->level)
Stephen Hemminger87990462006-08-10 23:35:16 -0700957 memset(&cl->un.inner, 0, sizeof(cl->un.inner));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 else {
Stephen Hemminger87990462006-08-10 23:35:16 -0700959 if (cl->un.leaf.q)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 qdisc_reset(cl->un.leaf.q);
961 INIT_LIST_HEAD(&cl->un.leaf.drop_list);
962 }
963 cl->prio_activity = 0;
964 cl->cmode = HTB_CAN_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965
966 }
967 }
Patrick McHardyfb983d42007-03-16 01:22:39 -0700968 qdisc_watchdog_cancel(&q->watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 __skb_queue_purge(&q->direct_queue);
970 sch->q.qlen = 0;
Stephen Hemminger87990462006-08-10 23:35:16 -0700971 memset(q->row, 0, sizeof(q->row));
972 memset(q->row_mask, 0, sizeof(q->row_mask));
973 memset(q->wait_pq, 0, sizeof(q->wait_pq));
974 memset(q->ptr, 0, sizeof(q->ptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 for (i = 0; i < TC_HTB_NUMPRIO; i++)
Stephen Hemminger87990462006-08-10 23:35:16 -0700976 INIT_LIST_HEAD(q->drops + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977}
978
Patrick McHardy27a34212008-01-23 20:35:39 -0800979static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
980 [TCA_HTB_PARMS] = { .len = sizeof(struct tc_htb_opt) },
981 [TCA_HTB_INIT] = { .len = sizeof(struct tc_htb_glob) },
982 [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
983 [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
984};
985
Jarek Poplawski12247362009-02-01 01:13:22 -0800986static void htb_work_func(struct work_struct *work)
987{
988 struct htb_sched *q = container_of(work, struct htb_sched, work);
989 struct Qdisc *sch = q->watchdog.qdisc;
990
991 __netif_schedule(qdisc_root(sch));
992}
993
Patrick McHardy1e904742008-01-22 22:11:17 -0800994static int htb_init(struct Qdisc *sch, struct nlattr *opt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995{
996 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardy1e904742008-01-22 22:11:17 -0800997 struct nlattr *tb[TCA_HTB_INIT + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 struct tc_htb_glob *gopt;
Patrick McHardycee63722008-01-23 20:33:32 -0800999 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 int i;
Patrick McHardycee63722008-01-23 20:33:32 -08001001
1002 if (!opt)
1003 return -EINVAL;
1004
Patrick McHardy27a34212008-01-23 20:35:39 -08001005 err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy);
Patrick McHardycee63722008-01-23 20:33:32 -08001006 if (err < 0)
1007 return err;
1008
Patrick McHardy27a34212008-01-23 20:35:39 -08001009 if (tb[TCA_HTB_INIT] == NULL) {
Eric Dumazetcc7ec452011-01-19 19:26:56 +00001010 pr_err("HTB: hey probably you have bad tc tool ?\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 return -EINVAL;
1012 }
Patrick McHardy1e904742008-01-22 22:11:17 -08001013 gopt = nla_data(tb[TCA_HTB_INIT]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 if (gopt->version != HTB_VER >> 16) {
Eric Dumazetcc7ec452011-01-19 19:26:56 +00001015 pr_err("HTB: need tc/htb version %d (minor is %d), you have %d\n",
Stephen Hemminger87990462006-08-10 23:35:16 -07001016 HTB_VER >> 16, HTB_VER & 0xffff, gopt->version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 return -EINVAL;
1018 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001020 err = qdisc_class_hash_init(&q->clhash);
1021 if (err < 0)
1022 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 for (i = 0; i < TC_HTB_NUMPRIO; i++)
Stephen Hemminger87990462006-08-10 23:35:16 -07001024 INIT_LIST_HEAD(q->drops + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
Patrick McHardyfb983d42007-03-16 01:22:39 -07001026 qdisc_watchdog_init(&q->watchdog, sch);
Jarek Poplawski12247362009-02-01 01:13:22 -08001027 INIT_WORK(&q->work, htb_work_func);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 skb_queue_head_init(&q->direct_queue);
1029
David S. Miller5ce2d482008-07-08 17:06:30 -07001030 q->direct_qlen = qdisc_dev(sch)->tx_queue_len;
Stephen Hemminger87990462006-08-10 23:35:16 -07001031 if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 q->direct_qlen = 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 if ((q->rate2quantum = gopt->rate2quantum) < 1)
1035 q->rate2quantum = 1;
1036 q->defcls = gopt->defcls;
1037
1038 return 0;
1039}
1040
1041static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
1042{
Jarek Poplawski102396a2008-08-29 14:21:52 -07001043 spinlock_t *root_lock = qdisc_root_sleeping_lock(sch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001045 struct nlattr *nest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 struct tc_htb_glob gopt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
David S. Miller7698b4f2008-07-16 01:42:40 -07001048 spin_lock_bh(root_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001049
1050 gopt.direct_pkts = q->direct_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 gopt.version = HTB_VER;
1052 gopt.rate2quantum = q->rate2quantum;
1053 gopt.defcls = q->defcls;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001054 gopt.debug = 0;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001055
1056 nest = nla_nest_start(skb, TCA_OPTIONS);
1057 if (nest == NULL)
1058 goto nla_put_failure;
David S. Miller1b34ec42012-03-29 05:11:39 -04001059 if (nla_put(skb, TCA_HTB_INIT, sizeof(gopt), &gopt))
1060 goto nla_put_failure;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001061 nla_nest_end(skb, nest);
1062
David S. Miller7698b4f2008-07-16 01:42:40 -07001063 spin_unlock_bh(root_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 return skb->len;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001065
Patrick McHardy1e904742008-01-22 22:11:17 -08001066nla_put_failure:
David S. Miller7698b4f2008-07-16 01:42:40 -07001067 spin_unlock_bh(root_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001068 nla_nest_cancel(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 return -1;
1070}
1071
1072static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
Stephen Hemminger87990462006-08-10 23:35:16 -07001073 struct sk_buff *skb, struct tcmsg *tcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074{
Stephen Hemminger87990462006-08-10 23:35:16 -07001075 struct htb_class *cl = (struct htb_class *)arg;
Jarek Poplawski102396a2008-08-29 14:21:52 -07001076 spinlock_t *root_lock = qdisc_root_sleeping_lock(sch);
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
David S. Miller7698b4f2008-07-16 01:42:40 -07001080 spin_lock_bh(root_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
Jiri Pirko292f1c72013-02-12 00:12:03 +00001092 opt.rate.rate = psched_ratecfg_getrate(&cl->rate);
Jiri Pirko9c10f412013-02-12 00:12:00 +00001093 opt.buffer = PSCHED_NS2TICKS(cl->buffer);
Jiri Pirko292f1c72013-02-12 00:12:03 +00001094 opt.ceil.rate = psched_ratecfg_getrate(&cl->ceil);
Jiri Pirko9c10f412013-02-12 00:12:00 +00001095 opt.cbuffer = PSCHED_NS2TICKS(cl->cbuffer);
Jarek Poplawskic19f7a32008-12-03 21:09:45 -08001096 opt.quantum = cl->quantum;
1097 opt.prio = cl->prio;
Stephen Hemminger87990462006-08-10 23:35:16 -07001098 opt.level = cl->level;
David S. Miller1b34ec42012-03-29 05:11:39 -04001099 if (nla_put(skb, TCA_HTB_PARMS, sizeof(opt), &opt))
1100 goto nla_put_failure;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001101
1102 nla_nest_end(skb, nest);
David S. Miller7698b4f2008-07-16 01:42:40 -07001103 spin_unlock_bh(root_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 return skb->len;
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001105
Patrick McHardy1e904742008-01-22 22:11:17 -08001106nla_put_failure:
David S. Miller7698b4f2008-07-16 01:42:40 -07001107 spin_unlock_bh(root_lock);
Patrick McHardy4b3550ef2008-01-23 20:34:11 -08001108 nla_nest_cancel(skb, nest);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 return -1;
1110}
1111
1112static int
Stephen Hemminger87990462006-08-10 23:35:16 -07001113htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114{
Stephen Hemminger87990462006-08-10 23:35:16 -07001115 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 if (!cl->level && cl->un.leaf.q)
1118 cl->qstats.qlen = cl->un.leaf.q->q.qlen;
1119 cl->xstats.tokens = cl->tokens;
1120 cl->xstats.ctokens = cl->ctokens;
1121
1122 if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
Eric Dumazetd250a5f2009-10-02 10:32:18 +00001123 gnet_stats_copy_rate_est(d, NULL, &cl->rate_est) < 0 ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 gnet_stats_copy_queue(d, &cl->qstats) < 0)
1125 return -1;
1126
1127 return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
1128}
1129
1130static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
Stephen Hemminger87990462006-08-10 23:35:16 -07001131 struct Qdisc **old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132{
Stephen Hemminger87990462006-08-10 23:35:16 -07001133 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134
Patrick McHardy5b9a9cc2009-09-04 06:41:17 +00001135 if (cl->level)
1136 return -EINVAL;
1137 if (new == NULL &&
Changli Gao3511c912010-10-16 13:04:08 +00001138 (new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
Patrick McHardy5b9a9cc2009-09-04 06:41:17 +00001139 cl->common.classid)) == NULL)
1140 return -ENOBUFS;
1141
1142 sch_tree_lock(sch);
1143 *old = cl->un.leaf.q;
1144 cl->un.leaf.q = new;
1145 if (*old != NULL) {
1146 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
1147 qdisc_reset(*old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 }
Patrick McHardy5b9a9cc2009-09-04 06:41:17 +00001149 sch_tree_unlock(sch);
1150 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151}
1152
Stephen Hemminger87990462006-08-10 23:35:16 -07001153static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154{
Stephen Hemminger87990462006-08-10 23:35:16 -07001155 struct htb_class *cl = (struct htb_class *)arg;
Patrick McHardy5b9a9cc2009-09-04 06:41:17 +00001156 return !cl->level ? cl->un.leaf.q : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157}
1158
Patrick McHardy256d61b2006-11-29 17:37:05 -08001159static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg)
1160{
1161 struct htb_class *cl = (struct htb_class *)arg;
1162
1163 if (cl->un.leaf.q->q.qlen == 0)
1164 htb_deactivate(qdisc_priv(sch), cl);
1165}
1166
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167static unsigned long htb_get(struct Qdisc *sch, u32 classid)
1168{
Stephen Hemminger87990462006-08-10 23:35:16 -07001169 struct htb_class *cl = htb_find(classid, sch);
1170 if (cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 cl->refcnt++;
1172 return (unsigned long)cl;
1173}
1174
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001175static inline int htb_parent_last_child(struct htb_class *cl)
1176{
1177 if (!cl->parent)
1178 /* the root class */
1179 return 0;
Patrick McHardy42077592008-07-05 23:22:53 -07001180 if (cl->parent->children > 1)
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001181 /* not the last child */
1182 return 0;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001183 return 1;
1184}
1185
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001186static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
1187 struct Qdisc *new_q)
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001188{
1189 struct htb_class *parent = cl->parent;
1190
Ilpo Järvinen547b7922008-07-25 21:43:18 -07001191 WARN_ON(cl->level || !cl->un.leaf.q || cl->prio_activity);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001192
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001193 if (parent->cmode != HTB_CAN_SEND)
1194 htb_safe_rb_erase(&parent->pq_node, q->wait_pq + parent->level);
1195
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001196 parent->level = 0;
1197 memset(&parent->un.inner, 0, sizeof(parent->un.inner));
1198 INIT_LIST_HEAD(&parent->un.leaf.drop_list);
1199 parent->un.leaf.q = new_q ? new_q : &noop_qdisc;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001200 parent->tokens = parent->buffer;
1201 parent->ctokens = parent->cbuffer;
Patrick McHardy3bebcda2007-03-23 11:29:25 -07001202 parent->t_c = psched_get_time();
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001203 parent->cmode = HTB_CAN_SEND;
1204}
1205
Stephen Hemminger87990462006-08-10 23:35:16 -07001206static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 if (!cl->level) {
Ilpo Järvinen547b7922008-07-25 21:43:18 -07001209 WARN_ON(!cl->un.leaf.q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 qdisc_destroy(cl->un.leaf.q);
1211 }
Patrick McHardyee39e102007-07-02 22:48:13 -07001212 gen_kill_estimator(&cl->bstats, &cl->rate_est);
Patrick McHardyff31ab52008-07-01 19:52:38 -07001213 tcf_destroy_chain(&cl->filter_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 kfree(cl);
1215}
1216
Stephen Hemminger87990462006-08-10 23:35:16 -07001217static void htb_destroy(struct Qdisc *sch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218{
1219 struct htb_sched *q = qdisc_priv(sch);
Sasha Levinb67bfe02013-02-27 17:06:00 -08001220 struct hlist_node *next;
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001221 struct htb_class *cl;
1222 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
Jarek Poplawski12247362009-02-01 01:13:22 -08001224 cancel_work_sync(&q->work);
Patrick McHardyfb983d42007-03-16 01:22:39 -07001225 qdisc_watchdog_cancel(&q->watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 /* This line used to be after htb_destroy_class call below
Eric Dumazetcc7ec452011-01-19 19:26:56 +00001227 * and surprisingly it worked in 2.4. But it must precede it
1228 * because filter need its target class alive to be able to call
1229 * unbind_filter on it (without Oops).
1230 */
Patrick McHardyff31ab52008-07-01 19:52:38 -07001231 tcf_destroy_chain(&q->filter_list);
Stephen Hemminger87990462006-08-10 23:35:16 -07001232
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001233 for (i = 0; i < q->clhash.hashsize; i++) {
Sasha Levinb67bfe02013-02-27 17:06:00 -08001234 hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode)
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001235 tcf_destroy_chain(&cl->filter_list);
1236 }
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001237 for (i = 0; i < q->clhash.hashsize; i++) {
Sasha Levinb67bfe02013-02-27 17:06:00 -08001238 hlist_for_each_entry_safe(cl, next, &q->clhash.hash[i],
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001239 common.hnode)
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001240 htb_destroy_class(sch, cl);
1241 }
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001242 qdisc_class_hash_destroy(&q->clhash);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 __skb_queue_purge(&q->direct_queue);
1244}
1245
1246static int htb_delete(struct Qdisc *sch, unsigned long arg)
1247{
1248 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001249 struct htb_class *cl = (struct htb_class *)arg;
Patrick McHardy256d61b2006-11-29 17:37:05 -08001250 unsigned int qlen;
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001251 struct Qdisc *new_q = NULL;
1252 int last_child = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
1254 // TODO: why don't allow to delete subtree ? references ? does
1255 // tc subsys quarantee us that in htb_destroy it holds no class
1256 // refs so that we can remove children safely there ?
Patrick McHardy42077592008-07-05 23:22:53 -07001257 if (cl->children || cl->filter_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 return -EBUSY;
Stephen Hemminger87990462006-08-10 23:35:16 -07001259
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001260 if (!cl->level && htb_parent_last_child(cl)) {
Changli Gao3511c912010-10-16 13:04:08 +00001261 new_q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
David S. Millerbb949fb2008-07-08 16:55:56 -07001262 cl->parent->common.classid);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001263 last_child = 1;
1264 }
1265
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 sch_tree_lock(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001267
Patrick McHardy814a175e2006-11-29 17:34:50 -08001268 if (!cl->level) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001269 qlen = cl->un.leaf.q->q.qlen;
Patrick McHardy814a175e2006-11-29 17:34:50 -08001270 qdisc_reset(cl->un.leaf.q);
Patrick McHardy256d61b2006-11-29 17:37:05 -08001271 qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen);
Patrick McHardy814a175e2006-11-29 17:34:50 -08001272 }
1273
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001274 /* delete from hash and active; remainder in destroy_class */
1275 qdisc_class_hash_remove(&q->clhash, &cl->common);
Jarek Poplawski26b284d2008-08-13 15:16:43 -07001276 if (cl->parent)
1277 cl->parent->children--;
Patrick McHardyc38c83c2007-03-27 14:04:24 -07001278
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 if (cl->prio_activity)
Stephen Hemminger87990462006-08-10 23:35:16 -07001280 htb_deactivate(q, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
Patrick McHardyfbd8f132008-07-05 23:22:19 -07001282 if (cl->cmode != HTB_CAN_SEND)
1283 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
1284
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001285 if (last_child)
Jarek Poplawski3ba08b02008-05-03 20:46:29 -07001286 htb_parent_to_leaf(q, cl, new_q);
Jarek Poplawski160d5e12006-12-08 00:26:56 -08001287
Jarek Poplawski7cd0a632009-03-15 20:00:19 -07001288 BUG_ON(--cl->refcnt == 0);
1289 /*
1290 * This shouldn't happen: we "hold" one cops->get() when called
1291 * from tc_ctl_tclass; the destroy method is done from cops->put().
1292 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
1294 sch_tree_unlock(sch);
1295 return 0;
1296}
1297
1298static void htb_put(struct Qdisc *sch, unsigned long arg)
1299{
Stephen Hemminger87990462006-08-10 23:35:16 -07001300 struct htb_class *cl = (struct htb_class *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301
1302 if (--cl->refcnt == 0)
Stephen Hemminger87990462006-08-10 23:35:16 -07001303 htb_destroy_class(sch, cl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304}
1305
Stephen Hemminger87990462006-08-10 23:35:16 -07001306static int htb_change_class(struct Qdisc *sch, u32 classid,
Patrick McHardy1e904742008-01-22 22:11:17 -08001307 u32 parentid, struct nlattr **tca,
Stephen Hemminger87990462006-08-10 23:35:16 -07001308 unsigned long *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309{
1310 int err = -EINVAL;
1311 struct htb_sched *q = qdisc_priv(sch);
Stephen Hemminger87990462006-08-10 23:35:16 -07001312 struct htb_class *cl = (struct htb_class *)*arg, *parent;
Patrick McHardy1e904742008-01-22 22:11:17 -08001313 struct nlattr *opt = tca[TCA_OPTIONS];
Changli Gaoe18434c2010-09-30 06:17:44 +00001314 struct nlattr *tb[__TCA_HTB_MAX];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 struct tc_htb_opt *hopt;
1316
1317 /* extract all subattrs from opt attr */
Patrick McHardycee63722008-01-23 20:33:32 -08001318 if (!opt)
1319 goto failure;
1320
Changli Gaoe18434c2010-09-30 06:17:44 +00001321 err = nla_parse_nested(tb, TCA_HTB_MAX, opt, htb_policy);
Patrick McHardycee63722008-01-23 20:33:32 -08001322 if (err < 0)
1323 goto failure;
1324
1325 err = -EINVAL;
Patrick McHardy27a34212008-01-23 20:35:39 -08001326 if (tb[TCA_HTB_PARMS] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 goto failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
Stephen Hemminger87990462006-08-10 23:35:16 -07001329 parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001330
Patrick McHardy1e904742008-01-22 22:11:17 -08001331 hopt = nla_data(tb[TCA_HTB_PARMS]);
Eric Dumazet196d97f2012-11-05 16:40:49 +00001332 if (!hopt->rate.rate || !hopt->ceil.rate)
Stephen Hemminger87990462006-08-10 23:35:16 -07001333 goto failure;
1334
1335 if (!cl) { /* new class */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 struct Qdisc *new_q;
Stephen Hemminger3696f622006-08-10 23:36:01 -07001337 int prio;
Patrick McHardyee39e102007-07-02 22:48:13 -07001338 struct {
Patrick McHardy1e904742008-01-22 22:11:17 -08001339 struct nlattr nla;
Patrick McHardyee39e102007-07-02 22:48:13 -07001340 struct gnet_estimator opt;
1341 } est = {
Patrick McHardy1e904742008-01-22 22:11:17 -08001342 .nla = {
1343 .nla_len = nla_attr_size(sizeof(est.opt)),
1344 .nla_type = TCA_RATE,
Patrick McHardyee39e102007-07-02 22:48:13 -07001345 },
1346 .opt = {
1347 /* 4s interval, 16s averaging constant */
1348 .interval = 2,
1349 .ewma_log = 2,
1350 },
1351 };
Stephen Hemminger3696f622006-08-10 23:36:01 -07001352
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 /* check for valid classid */
Joe Perchesf64f9e72009-11-29 16:55:45 -08001354 if (!classid || TC_H_MAJ(classid ^ sch->handle) ||
1355 htb_find(classid, sch))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 goto failure;
1357
1358 /* check maximal depth */
1359 if (parent && parent->parent && parent->parent->level < 2) {
Eric Dumazetcc7ec452011-01-19 19:26:56 +00001360 pr_err("htb: tree is too deep\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 goto failure;
1362 }
1363 err = -ENOBUFS;
Eric Dumazetcc7ec452011-01-19 19:26:56 +00001364 cl = kzalloc(sizeof(*cl), GFP_KERNEL);
1365 if (!cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 goto failure;
Stephen Hemminger87990462006-08-10 23:35:16 -07001367
Stephen Hemminger71bcb092008-11-25 21:13:31 -08001368 err = gen_new_estimator(&cl->bstats, &cl->rate_est,
1369 qdisc_root_sleeping_lock(sch),
1370 tca[TCA_RATE] ? : &est.nla);
1371 if (err) {
1372 kfree(cl);
1373 goto failure;
1374 }
1375
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 cl->refcnt = 1;
Patrick McHardy42077592008-07-05 23:22:53 -07001377 cl->children = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 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)
Eric Dumazetcc7ec452011-01-19 19:26:56 +00001385 * so that can't be used inside of sch_tree_lock
1386 * -- thanks to Karlis Peisenieks
1387 */
Changli Gao3511c912010-10-16 13:04:08 +00001388 new_q = qdisc_create_dflt(sch->dev_queue,
David S. Millerbb949fb2008-07-08 16:55:56 -07001389 &pfifo_qdisc_ops, classid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 sch_tree_lock(sch);
1391 if (parent && !parent->level) {
Patrick McHardy256d61b2006-11-29 17:37:05 -08001392 unsigned int qlen = parent->un.leaf.q->q.qlen;
1393
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 /* turn parent into inner node */
Patrick McHardy256d61b2006-11-29 17:37:05 -08001395 qdisc_reset(parent->un.leaf.q);
1396 qdisc_tree_decrease_qlen(parent->un.leaf.q, qlen);
Stephen Hemminger87990462006-08-10 23:35:16 -07001397 qdisc_destroy(parent->un.leaf.q);
1398 if (parent->prio_activity)
1399 htb_deactivate(q, parent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
1401 /* remove from evt list because of level change */
1402 if (parent->cmode != HTB_CAN_SEND) {
Stephen Hemminger3696f622006-08-10 23:36:01 -07001403 htb_safe_rb_erase(&parent->pq_node, q->wait_pq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 parent->cmode = HTB_CAN_SEND;
1405 }
1406 parent->level = (parent->parent ? parent->parent->level
Stephen Hemminger87990462006-08-10 23:35:16 -07001407 : TC_HTB_MAXDEPTH) - 1;
1408 memset(&parent->un.inner, 0, sizeof(parent->un.inner));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 }
1410 /* leaf (we) needs elementary qdisc */
1411 cl->un.leaf.q = new_q ? new_q : &noop_qdisc;
1412
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001413 cl->common.classid = classid;
Stephen Hemminger87990462006-08-10 23:35:16 -07001414 cl->parent = parent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
1416 /* set class to be in HTB_CAN_SEND state */
Jiri Pirkob9a7afd2013-02-12 00:12:02 +00001417 cl->tokens = PSCHED_TICKS2NS(hopt->buffer);
1418 cl->ctokens = PSCHED_TICKS2NS(hopt->cbuffer);
Patrick McHardy00c04af2007-03-16 01:23:02 -07001419 cl->mbuffer = 60 * PSCHED_TICKS_PER_SEC; /* 1min */
Patrick McHardy3bebcda2007-03-23 11:29:25 -07001420 cl->t_c = psched_get_time();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 cl->cmode = HTB_CAN_SEND;
1422
1423 /* attach to the hash list and parent's family */
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001424 qdisc_class_hash_insert(&q->clhash, &cl->common);
Patrick McHardy42077592008-07-05 23:22:53 -07001425 if (parent)
1426 parent->children++;
Patrick McHardyee39e102007-07-02 22:48:13 -07001427 } else {
Stephen Hemminger71bcb092008-11-25 21:13:31 -08001428 if (tca[TCA_RATE]) {
1429 err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
1430 qdisc_root_sleeping_lock(sch),
1431 tca[TCA_RATE]);
1432 if (err)
1433 return err;
1434 }
Stephen Hemminger87990462006-08-10 23:35:16 -07001435 sch_tree_lock(sch);
Patrick McHardyee39e102007-07-02 22:48:13 -07001436 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437
1438 /* it used to be a nasty bug here, we have to check that node
Eric Dumazetcc7ec452011-01-19 19:26:56 +00001439 * is really leaf before changing cl->un.leaf !
1440 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 if (!cl->level) {
Eric Dumazet196d97f2012-11-05 16:40:49 +00001442 cl->quantum = hopt->rate.rate / q->rate2quantum;
Jarek Poplawskic19f7a32008-12-03 21:09:45 -08001443 if (!hopt->quantum && cl->quantum < 1000) {
Eric Dumazetcc7ec452011-01-19 19:26:56 +00001444 pr_warning(
Stephen Hemminger87990462006-08-10 23:35:16 -07001445 "HTB: quantum of class %X is small. Consider r2q change.\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001446 cl->common.classid);
Jarek Poplawskic19f7a32008-12-03 21:09:45 -08001447 cl->quantum = 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 }
Jarek Poplawskic19f7a32008-12-03 21:09:45 -08001449 if (!hopt->quantum && cl->quantum > 200000) {
Eric Dumazetcc7ec452011-01-19 19:26:56 +00001450 pr_warning(
Stephen Hemminger87990462006-08-10 23:35:16 -07001451 "HTB: quantum of class %X is big. Consider r2q change.\n",
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001452 cl->common.classid);
Jarek Poplawskic19f7a32008-12-03 21:09:45 -08001453 cl->quantum = 200000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 }
1455 if (hopt->quantum)
Jarek Poplawskic19f7a32008-12-03 21:09:45 -08001456 cl->quantum = hopt->quantum;
1457 if ((cl->prio = hopt->prio) >= TC_HTB_NUMPRIO)
1458 cl->prio = TC_HTB_NUMPRIO - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459 }
1460
Jiri Pirko292f1c72013-02-12 00:12:03 +00001461 psched_ratecfg_precompute(&cl->rate, hopt->rate.rate);
1462 psched_ratecfg_precompute(&cl->ceil, hopt->ceil.rate);
Vimalkumar56b765b2012-10-31 06:04:11 +00001463
Jiri Pirko324f5aa2013-02-12 00:11:59 +00001464 cl->buffer = PSCHED_TICKS2NS(hopt->buffer);
1465 cl->cbuffer = PSCHED_TICKS2NS(hopt->buffer);
Vimalkumar56b765b2012-10-31 06:04:11 +00001466
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:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 return err;
1476}
1477
1478static struct tcf_proto **htb_find_tcf(struct Qdisc *sch, unsigned long arg)
1479{
1480 struct htb_sched *q = qdisc_priv(sch);
1481 struct htb_class *cl = (struct htb_class *)arg;
1482 struct tcf_proto **fl = cl ? &cl->filter_list : &q->filter_list;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001483
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 return fl;
1485}
1486
1487static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent,
Stephen Hemminger87990462006-08-10 23:35:16 -07001488 u32 classid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489{
Stephen Hemminger87990462006-08-10 23:35:16 -07001490 struct htb_class *cl = htb_find(classid, sch);
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001491
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 /*if (cl && !cl->level) return 0;
Eric Dumazetcc7ec452011-01-19 19:26:56 +00001493 * The line above used to be there to prevent attaching filters to
1494 * leaves. But at least tc_index filter uses this just to get class
1495 * for other reasons so that we have to allow for it.
1496 * ----
1497 * 19.6.2002 As Werner explained it is ok - bind filter is just
1498 * another way to "lock" the class - unlike "get" this lock can
1499 * be broken by class during destroy IIUC.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 */
Stephen Hemminger87990462006-08-10 23:35:16 -07001501 if (cl)
1502 cl->filter_cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 return (unsigned long)cl;
1504}
1505
1506static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg)
1507{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 struct htb_class *cl = (struct htb_class *)arg;
Stephen Hemminger3bf72952006-08-10 23:31:08 -07001509
Stephen Hemminger87990462006-08-10 23:35:16 -07001510 if (cl)
1511 cl->filter_cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512}
1513
1514static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg)
1515{
1516 struct htb_sched *q = qdisc_priv(sch);
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001517 struct htb_class *cl;
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001518 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
1520 if (arg->stop)
1521 return;
1522
Patrick McHardyf4c1f3e2008-07-05 23:22:35 -07001523 for (i = 0; i < q->clhash.hashsize; i++) {
Sasha Levinb67bfe02013-02-27 17:06:00 -08001524 hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 if (arg->count < arg->skip) {
1526 arg->count++;
1527 continue;
1528 }
1529 if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
1530 arg->stop = 1;
1531 return;
1532 }
1533 arg->count++;
1534 }
1535 }
1536}
1537
Eric Dumazet20fea082007-11-14 01:44:41 -08001538static const struct Qdisc_class_ops htb_class_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 .graft = htb_graft,
1540 .leaf = htb_leaf,
Patrick McHardy256d61b2006-11-29 17:37:05 -08001541 .qlen_notify = htb_qlen_notify,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 .get = htb_get,
1543 .put = htb_put,
1544 .change = htb_change_class,
1545 .delete = htb_delete,
1546 .walk = htb_walk,
1547 .tcf_chain = htb_find_tcf,
1548 .bind_tcf = htb_bind_filter,
1549 .unbind_tcf = htb_unbind_filter,
1550 .dump = htb_dump_class,
1551 .dump_stats = htb_dump_class_stats,
1552};
1553
Eric Dumazet20fea082007-11-14 01:44:41 -08001554static struct Qdisc_ops htb_qdisc_ops __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 .cl_ops = &htb_class_ops,
1556 .id = "htb",
1557 .priv_size = sizeof(struct htb_sched),
1558 .enqueue = htb_enqueue,
1559 .dequeue = htb_dequeue,
Jarek Poplawski77be1552008-10-31 00:47:01 -07001560 .peek = qdisc_peek_dequeued,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 .drop = htb_drop,
1562 .init = htb_init,
1563 .reset = htb_reset,
1564 .destroy = htb_destroy,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 .dump = htb_dump,
1566 .owner = THIS_MODULE,
1567};
1568
1569static int __init htb_module_init(void)
1570{
Stephen Hemminger87990462006-08-10 23:35:16 -07001571 return register_qdisc(&htb_qdisc_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572}
Stephen Hemminger87990462006-08-10 23:35:16 -07001573static void __exit htb_module_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574{
Stephen Hemminger87990462006-08-10 23:35:16 -07001575 unregister_qdisc(&htb_qdisc_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576}
Stephen Hemminger87990462006-08-10 23:35:16 -07001577
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578module_init(htb_module_init)
1579module_exit(htb_module_exit)
1580MODULE_LICENSE("GPL");