Blame view
net/sched/sch_htb.c
42.4 KB
87990467d [HTB]: Lindent |
1 |
/* |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 8 9 10 11 12 13 |
* net/sched/sch_htb.c Hierarchical token bucket, feed tree version * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Authors: Martin Devera, <devik@cdi.cz> * * Credits (in time order) for older HTB versions: * Stef Coene <stef.coene@docum.org> * HTB support at LARTC mailing list |
10297b993 [NET] SCHED: Fix ... |
14 |
* Ondrej Kraus, <krauso@barr.cz> |
1da177e4c Linux-2.6.12-rc2 |
15 16 17 18 19 20 21 22 23 24 25 26 |
* found missing INIT_QDISC(htb) * Vladimir Smelhaus, Aamer Akhter, Bert Hubert * helped a lot to locate nasty class stall bug * Andi Kleen, Jamal Hadi, Bert Hubert * code review and helpful comments on shaping * Tomasz Wrona, <tw@eter.tym.pl> * created test case so that I was able to fix nasty bug * Wilfried Weissmann * spotted bug in dequeue code and helped with fix * Jiri Fojtasek * fixed requeue routine * and many others. thanks. |
1da177e4c Linux-2.6.12-rc2 |
27 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
28 |
#include <linux/module.h> |
47083fc07 pkt_sched: Change... |
29 |
#include <linux/moduleparam.h> |
1da177e4c Linux-2.6.12-rc2 |
30 31 |
#include <linux/types.h> #include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
32 |
#include <linux/string.h> |
1da177e4c Linux-2.6.12-rc2 |
33 |
#include <linux/errno.h> |
1da177e4c Linux-2.6.12-rc2 |
34 35 36 |
#include <linux/skbuff.h> #include <linux/list.h> #include <linux/compiler.h> |
0ba480538 [NET_SCHED]: Remo... |
37 |
#include <linux/rbtree.h> |
1224736d9 pkt_sched: sch_ht... |
38 |
#include <linux/workqueue.h> |
5a0e3ad6a include cleanup: ... |
39 |
#include <linux/slab.h> |
dc5fc579b [NETLINK]: Use nl... |
40 |
#include <net/netlink.h> |
292f1c7ff sch: make htb_rat... |
41 |
#include <net/sch_generic.h> |
1da177e4c Linux-2.6.12-rc2 |
42 |
#include <net/pkt_sched.h> |
cf1facda2 sched: move tcf_p... |
43 |
#include <net/pkt_cls.h> |
1da177e4c Linux-2.6.12-rc2 |
44 45 46 47 48 |
/* HTB algorithm. Author: devik@cdi.cz ======================================================================== HTB is like TBF with multiple classes. It is also similar to CBQ because |
10297b993 [NET] SCHED: Fix ... |
49 |
it allows to assign priority to each class in hierarchy. |
1da177e4c Linux-2.6.12-rc2 |
50 51 52 |
In fact it is another implementation of Floyd's formal sharing. Levels: |
10297b993 [NET] SCHED: Fix ... |
53 |
Each class is assigned level. Leaf has ALWAYS level 0 and root |
1da177e4c Linux-2.6.12-rc2 |
54 55 56 |
classes have level TC_HTB_MAXDEPTH-1. Interior nodes has level one less than their parent. */ |
47083fc07 pkt_sched: Change... |
57 |
static int htb_hysteresis __read_mostly = 0; /* whether to use mode hysteresis for speedup */ |
87990467d [HTB]: Lindent |
58 |
#define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */ |
1da177e4c Linux-2.6.12-rc2 |
59 60 61 62 |
#if HTB_VER >> 16 != TC_HTB_PROTOVER #error "Mismatched sch_htb.c and pkt_sch.h" #endif |
47083fc07 pkt_sched: Change... |
63 64 65 |
/* Module parameter and sysfs export */ module_param (htb_hysteresis, int, 0640); MODULE_PARM_DESC(htb_hysteresis, "Hysteresis mode, less CPU load, less accurate"); |
64153ce0a net_sched: htb: d... |
66 67 68 |
static int htb_rate_est = 0; /* htb classes have a default rate estimator */ module_param(htb_rate_est, int, 0640); MODULE_PARM_DESC(htb_rate_est, "setup a default rate estimator (4sec 16sec) for htb classes"); |
1da177e4c Linux-2.6.12-rc2 |
69 70 |
/* used internaly to keep status of single class */ enum htb_cmode { |
87990467d [HTB]: Lindent |
71 72 73 |
HTB_CANT_SEND, /* class can't send and can't borrow */ HTB_MAY_BORROW, /* class can't send but may borrow */ HTB_CAN_SEND /* class can send */ |
1da177e4c Linux-2.6.12-rc2 |
74 |
}; |
c9364636d htb: refactor str... |
75 76 77 78 79 80 81 82 83 84 85 86 87 |
struct htb_prio { union { struct rb_root row; struct rb_root feed; }; struct rb_node *ptr; /* When class changes from state 1->2 and disconnects from * parent's feed then we lost ptr value and start from the * first child again. Here we store classid of the * last valid ptr (used when ptr is NULL). */ u32 last_ptr_id; }; |
ca4ec90b3 htb: reorder stru... |
88 89 90 91 |
/* interior & leaf nodes; props specific to leaves are marked L: * To reduce false sharing, place mostly read fields at beginning, * and mostly written ones at the end. */ |
87990467d [HTB]: Lindent |
92 |
struct htb_class { |
f4c1f3e0c net-sched: sch_ht... |
93 |
struct Qdisc_class_common common; |
ca4ec90b3 htb: reorder stru... |
94 95 96 97 |
struct psched_ratecfg rate; struct psched_ratecfg ceil; s64 buffer, cbuffer;/* token bucket depth/rate */ s64 mbuffer; /* max wait time */ |
cbd375567 htb: fix sign ext... |
98 |
u32 prio; /* these two are used only by leaves... */ |
ca4ec90b3 htb: reorder stru... |
99 |
int quantum; /* but stored for parent-to-leaf return */ |
25d8c0d55 net: rcu-ify tcf_... |
100 |
struct tcf_proto __rcu *filter_list; /* class attached filters */ |
6529eaba3 net: sched: intro... |
101 |
struct tcf_block *block; |
ca4ec90b3 htb: reorder stru... |
102 |
int filter_cnt; |
ca4ec90b3 htb: reorder stru... |
103 104 105 106 |
int level; /* our level (see above) */ unsigned int children; struct htb_class *parent; /* parent class */ |
1c0d32fde net_sched: gen_es... |
107 |
struct net_rate_estimator __rcu *rate_est; |
1da177e4c Linux-2.6.12-rc2 |
108 |
|
ca4ec90b3 htb: reorder stru... |
109 110 111 112 |
/* * Written often fields */ struct gnet_stats_basic_packed bstats; |
ca4ec90b3 htb: reorder stru... |
113 |
struct tc_htb_xstats xstats; /* our special stats */ |
87990467d [HTB]: Lindent |
114 |
|
ca4ec90b3 htb: reorder stru... |
115 116 117 |
/* token bucket parameters */ s64 tokens, ctokens;/* current number of tokens */ s64 t_c; /* checkpoint time */ |
c19f7a34f pkt_sched: sch_ht... |
118 |
|
87990467d [HTB]: Lindent |
119 120 |
union { struct htb_class_leaf { |
87990467d [HTB]: Lindent |
121 |
struct list_head drop_list; |
c9364636d htb: refactor str... |
122 123 |
int deficit[TC_HTB_MAXDEPTH]; struct Qdisc *q; |
87990467d [HTB]: Lindent |
124 125 |
} leaf; struct htb_class_inner { |
c9364636d htb: refactor str... |
126 |
struct htb_prio clprio[TC_HTB_NUMPRIO]; |
87990467d [HTB]: Lindent |
127 128 |
} inner; } un; |
ca4ec90b3 htb: reorder stru... |
129 |
s64 pq_key; |
87990467d [HTB]: Lindent |
130 |
|
ca4ec90b3 htb: reorder stru... |
131 132 133 134 |
int prio_activity; /* for which prios are we active */ enum htb_cmode cmode; /* current mode of the class */ struct rb_node pq_node; /* node for event queue */ struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */ |
338ed9b4d net_sched: sch_ht... |
135 136 |
unsigned int drops ____cacheline_aligned_in_smp; |
1da177e4c Linux-2.6.12-rc2 |
137 |
}; |
c9364636d htb: refactor str... |
138 139 140 141 |
struct htb_level { struct rb_root wait_pq; struct htb_prio hprio[TC_HTB_NUMPRIO]; }; |
87990467d [HTB]: Lindent |
142 |
struct htb_sched { |
f4c1f3e0c net-sched: sch_ht... |
143 |
struct Qdisc_class_hash clhash; |
c9364636d htb: refactor str... |
144 145 |
int defcls; /* class where unclassified flows go to */ int rate2quantum; /* quant = rate / rate2quantum */ |
1da177e4c Linux-2.6.12-rc2 |
146 |
|
c9364636d htb: refactor str... |
147 |
/* filters for qdisc itself */ |
25d8c0d55 net: rcu-ify tcf_... |
148 |
struct tcf_proto __rcu *filter_list; |
6529eaba3 net: sched: intro... |
149 |
struct tcf_block *block; |
1da177e4c Linux-2.6.12-rc2 |
150 |
|
c9364636d htb: refactor str... |
151 152 153 154 |
#define HTB_WARN_TOOMANYEVENTS 0x1 unsigned int warned; /* only one warning */ int direct_qlen; struct work_struct work; |
1da177e4c Linux-2.6.12-rc2 |
155 |
|
c9364636d htb: refactor str... |
156 |
/* non shaped skbs; let them go directly thru */ |
48da34b7a sched: add and us... |
157 |
struct qdisc_skb_head direct_queue; |
c9364636d htb: refactor str... |
158 |
long direct_pkts; |
1da177e4c Linux-2.6.12-rc2 |
159 |
|
c9364636d htb: refactor str... |
160 |
struct qdisc_watchdog watchdog; |
1da177e4c Linux-2.6.12-rc2 |
161 |
|
c9364636d htb: refactor str... |
162 163 |
s64 now; /* cached dequeue time */ struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */ |
1da177e4c Linux-2.6.12-rc2 |
164 |
|
c9364636d htb: refactor str... |
165 166 |
/* time of nearest event per level (row) */ s64 near_ev_cache[TC_HTB_MAXDEPTH]; |
87990467d [HTB]: Lindent |
167 |
|
c9364636d htb: refactor str... |
168 |
int row_mask[TC_HTB_MAXDEPTH]; |
e82181de5 pkt_sched: sch_ht... |
169 |
|
c9364636d htb: refactor str... |
170 |
struct htb_level hlevel[TC_HTB_MAXDEPTH]; |
1da177e4c Linux-2.6.12-rc2 |
171 |
}; |
1da177e4c Linux-2.6.12-rc2 |
172 |
/* find class in global hash table using given handle */ |
87990467d [HTB]: Lindent |
173 |
static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch) |
1da177e4c Linux-2.6.12-rc2 |
174 175 |
{ struct htb_sched *q = qdisc_priv(sch); |
f4c1f3e0c net-sched: sch_ht... |
176 |
struct Qdisc_class_common *clc; |
0cef296da [HTB]: Use hlist ... |
177 |
|
f4c1f3e0c net-sched: sch_ht... |
178 179 |
clc = qdisc_class_find(&q->clhash, handle); if (clc == NULL) |
1da177e4c Linux-2.6.12-rc2 |
180 |
return NULL; |
f4c1f3e0c net-sched: sch_ht... |
181 |
return container_of(clc, struct htb_class, common); |
1da177e4c Linux-2.6.12-rc2 |
182 |
} |
143976ce9 net_sched: remove... |
183 184 185 186 |
static unsigned long htb_search(struct Qdisc *sch, u32 handle) { return (unsigned long)htb_find(handle, sch); } |
1da177e4c Linux-2.6.12-rc2 |
187 188 189 190 191 192 193 194 |
/** * htb_classify - classify a packet into class * * It returns NULL if the packet should be dropped or -1 if the packet * should be passed directly thru. In all other cases leaf class is returned. * We allow direct class selection by classid in priority. The we examine * filters in qdisc and in inner nodes (if higher filter points to the inner * node). If we end up with classid MAJOR:0 we enqueue the skb into special |
10297b993 [NET] SCHED: Fix ... |
195 |
* internal fifo (direct). These packets then go directly thru. If we still |
25985edce Fix common misspe... |
196 |
* have no valid leaf we try to use MAJOR:default leaf. It still unsuccessful |
1da177e4c Linux-2.6.12-rc2 |
197 198 |
* then finish and return direct queue. */ |
cc7ec456f net_sched: cleanups |
199 |
#define HTB_DIRECT ((struct htb_class *)-1L) |
1da177e4c Linux-2.6.12-rc2 |
200 |
|
87990467d [HTB]: Lindent |
201 202 |
static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) |
1da177e4c Linux-2.6.12-rc2 |
203 204 205 206 207 208 209 210 |
{ struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl; struct tcf_result res; struct tcf_proto *tcf; int result; /* allow to select class by setting skb->priority to valid classid; |
cc7ec456f net_sched: cleanups |
211 212 213 |
* note that nfmark can be used too by attaching filter fw with no * rules in it */ |
1da177e4c Linux-2.6.12-rc2 |
214 |
if (skb->priority == sch->handle) |
87990467d [HTB]: Lindent |
215 |
return HTB_DIRECT; /* X:0 (direct flow) selected */ |
cc7ec456f net_sched: cleanups |
216 |
cl = htb_find(skb->priority, sch); |
29824310c sch_htb: let skb-... |
217 218 219 220 |
if (cl) { if (cl->level == 0) return cl; /* Start with inner filter chain if a non-leaf class is selected */ |
25d8c0d55 net: rcu-ify tcf_... |
221 |
tcf = rcu_dereference_bh(cl->filter_list); |
29824310c sch_htb: let skb-... |
222 |
} else { |
25d8c0d55 net: rcu-ify tcf_... |
223 |
tcf = rcu_dereference_bh(q->filter_list); |
29824310c sch_htb: let skb-... |
224 |
} |
1da177e4c Linux-2.6.12-rc2 |
225 |
|
c27f339af net_sched: Add qd... |
226 |
*qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; |
87d83093b net: sched: move ... |
227 |
while (tcf && (result = tcf_classify(skb, tcf, &res, false)) >= 0) { |
1da177e4c Linux-2.6.12-rc2 |
228 229 230 |
#ifdef CONFIG_NET_CLS_ACT switch (result) { case TC_ACT_QUEUED: |
87990467d [HTB]: Lindent |
231 |
case TC_ACT_STOLEN: |
e25ea21ff net: sched: intro... |
232 |
case TC_ACT_TRAP: |
378a2f090 net_sched: Add qd... |
233 |
*qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; |
1da177e4c Linux-2.6.12-rc2 |
234 235 236 |
case TC_ACT_SHOT: return NULL; } |
1da177e4c Linux-2.6.12-rc2 |
237 |
#endif |
cc7ec456f net_sched: cleanups |
238 239 |
cl = (void *)res.class; if (!cl) { |
1da177e4c Linux-2.6.12-rc2 |
240 |
if (res.classid == sch->handle) |
87990467d [HTB]: Lindent |
241 |
return HTB_DIRECT; /* X:0 (direct flow) */ |
cc7ec456f net_sched: cleanups |
242 243 |
cl = htb_find(res.classid, sch); if (!cl) |
87990467d [HTB]: Lindent |
244 |
break; /* filter selected invalid classid */ |
1da177e4c Linux-2.6.12-rc2 |
245 246 |
} if (!cl->level) |
87990467d [HTB]: Lindent |
247 |
return cl; /* we hit leaf; return it */ |
1da177e4c Linux-2.6.12-rc2 |
248 249 |
/* we have got inner class; apply inner filter chain */ |
25d8c0d55 net: rcu-ify tcf_... |
250 |
tcf = rcu_dereference_bh(cl->filter_list); |
1da177e4c Linux-2.6.12-rc2 |
251 252 |
} /* classification failed; try to use default class */ |
87990467d [HTB]: Lindent |
253 |
cl = htb_find(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch); |
1da177e4c Linux-2.6.12-rc2 |
254 |
if (!cl || cl->level) |
87990467d [HTB]: Lindent |
255 |
return HTB_DIRECT; /* bad default .. this is safe bet */ |
1da177e4c Linux-2.6.12-rc2 |
256 257 |
return cl; } |
1da177e4c Linux-2.6.12-rc2 |
258 259 260 261 262 263 |
/** * htb_add_to_id_tree - adds class to the round robin list * * Routine adds class to the list (actually tree) sorted by classid. * Make sure that class is not already on such list for given prio. */ |
87990467d [HTB]: Lindent |
264 265 |
static void htb_add_to_id_tree(struct rb_root *root, struct htb_class *cl, int prio) |
1da177e4c Linux-2.6.12-rc2 |
266 267 |
{ struct rb_node **p = &root->rb_node, *parent = NULL; |
3bf72957d [HTB]: Remove bro... |
268 |
|
1da177e4c Linux-2.6.12-rc2 |
269 |
while (*p) { |
87990467d [HTB]: Lindent |
270 271 |
struct htb_class *c; parent = *p; |
1da177e4c Linux-2.6.12-rc2 |
272 |
c = rb_entry(parent, struct htb_class, node[prio]); |
3bf72957d [HTB]: Remove bro... |
273 |
|
f4c1f3e0c net-sched: sch_ht... |
274 |
if (cl->common.classid > c->common.classid) |
1da177e4c Linux-2.6.12-rc2 |
275 |
p = &parent->rb_right; |
87990467d [HTB]: Lindent |
276 |
else |
1da177e4c Linux-2.6.12-rc2 |
277 278 279 280 281 282 283 284 285 286 287 288 289 |
p = &parent->rb_left; } rb_link_node(&cl->node[prio], parent, p); rb_insert_color(&cl->node[prio], root); } /** * htb_add_to_wait_tree - adds class to the event queue with delay * * The class is added to priority event queue to indicate that class will * change its mode in cl->pq_key microseconds. Make sure that class is not * already in the queue. */ |
87990467d [HTB]: Lindent |
290 |
static void htb_add_to_wait_tree(struct htb_sched *q, |
56b765b79 htb: improved acc... |
291 |
struct htb_class *cl, s64 delay) |
1da177e4c Linux-2.6.12-rc2 |
292 |
{ |
c9364636d htb: refactor str... |
293 |
struct rb_node **p = &q->hlevel[cl->level].wait_pq.rb_node, *parent = NULL; |
3bf72957d [HTB]: Remove bro... |
294 |
|
fb983d457 [NET_SCHED]: sch_... |
295 296 |
cl->pq_key = q->now + delay; if (cl->pq_key == q->now) |
1da177e4c Linux-2.6.12-rc2 |
297 298 299 |
cl->pq_key++; /* update the nearest event cache */ |
fb983d457 [NET_SCHED]: sch_... |
300 |
if (q->near_ev_cache[cl->level] > cl->pq_key) |
1da177e4c Linux-2.6.12-rc2 |
301 |
q->near_ev_cache[cl->level] = cl->pq_key; |
87990467d [HTB]: Lindent |
302 |
|
1da177e4c Linux-2.6.12-rc2 |
303 |
while (*p) { |
87990467d [HTB]: Lindent |
304 305 |
struct htb_class *c; parent = *p; |
1da177e4c Linux-2.6.12-rc2 |
306 |
c = rb_entry(parent, struct htb_class, pq_node); |
fb983d457 [NET_SCHED]: sch_... |
307 |
if (cl->pq_key >= c->pq_key) |
1da177e4c Linux-2.6.12-rc2 |
308 |
p = &parent->rb_right; |
87990467d [HTB]: Lindent |
309 |
else |
1da177e4c Linux-2.6.12-rc2 |
310 311 312 |
p = &parent->rb_left; } rb_link_node(&cl->pq_node, parent, p); |
c9364636d htb: refactor str... |
313 |
rb_insert_color(&cl->pq_node, &q->hlevel[cl->level].wait_pq); |
1da177e4c Linux-2.6.12-rc2 |
314 315 316 317 318 319 320 321 |
} /** * htb_next_rb_node - finds next node in binary tree * * When we are past last key we return NULL. * Average complexity is 2 steps per call. */ |
3696f625e [HTB]: rbtree cle... |
322 |
static inline void htb_next_rb_node(struct rb_node **n) |
1da177e4c Linux-2.6.12-rc2 |
323 324 325 326 327 328 329 330 331 332 |
{ *n = rb_next(*n); } /** * htb_add_class_to_row - add class to its row * * The class is added to row at priorities marked in mask. * It does nothing if mask == 0. */ |
87990467d [HTB]: Lindent |
333 334 |
static inline void htb_add_class_to_row(struct htb_sched *q, struct htb_class *cl, int mask) |
1da177e4c Linux-2.6.12-rc2 |
335 |
{ |
1da177e4c Linux-2.6.12-rc2 |
336 337 338 339 |
q->row_mask[cl->level] |= mask; while (mask) { int prio = ffz(~mask); mask &= ~(1 << prio); |
c9364636d htb: refactor str... |
340 |
htb_add_to_id_tree(&q->hlevel[cl->level].hprio[prio].row, cl, prio); |
1da177e4c Linux-2.6.12-rc2 |
341 342 |
} } |
3696f625e [HTB]: rbtree cle... |
343 344 345 |
/* If this triggers, it is a bug in this code, but it need not be fatal */ static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root) { |
81771b3b2 [NET_SCHED]: Reve... |
346 |
if (RB_EMPTY_NODE(rb)) { |
3696f625e [HTB]: rbtree cle... |
347 348 349 350 351 352 |
WARN_ON(1); } else { rb_erase(rb, root); RB_CLEAR_NODE(rb); } } |
1da177e4c Linux-2.6.12-rc2 |
353 354 355 356 357 358 |
/** * htb_remove_class_from_row - removes class from its row * * The class is removed from row at priorities marked in mask. * It does nothing if mask == 0. */ |
87990467d [HTB]: Lindent |
359 360 |
static inline void htb_remove_class_from_row(struct htb_sched *q, struct htb_class *cl, int mask) |
1da177e4c Linux-2.6.12-rc2 |
361 362 |
{ int m = 0; |
c9364636d htb: refactor str... |
363 |
struct htb_level *hlevel = &q->hlevel[cl->level]; |
3bf72957d [HTB]: Remove bro... |
364 |
|
1da177e4c Linux-2.6.12-rc2 |
365 366 |
while (mask) { int prio = ffz(~mask); |
c9364636d htb: refactor str... |
367 |
struct htb_prio *hprio = &hlevel->hprio[prio]; |
3696f625e [HTB]: rbtree cle... |
368 |
|
1da177e4c Linux-2.6.12-rc2 |
369 |
mask &= ~(1 << prio); |
c9364636d htb: refactor str... |
370 371 |
if (hprio->ptr == cl->node + prio) htb_next_rb_node(&hprio->ptr); |
3696f625e [HTB]: rbtree cle... |
372 |
|
c9364636d htb: refactor str... |
373 374 |
htb_safe_rb_erase(cl->node + prio, &hprio->row); if (!hprio->row.rb_node) |
1da177e4c Linux-2.6.12-rc2 |
375 376 |
m |= 1 << prio; } |
1da177e4c Linux-2.6.12-rc2 |
377 378 379 380 381 382 383 |
q->row_mask[cl->level] &= ~m; } /** * htb_activate_prios - creates active classe's feed chain * * The class is connected to ancestors and/or appropriate rows |
10297b993 [NET] SCHED: Fix ... |
384 |
* for priorities it is participating on. cl->cmode must be new |
1da177e4c Linux-2.6.12-rc2 |
385 386 |
* (activated) mode. It does nothing if cl->prio_activity == 0. */ |
87990467d [HTB]: Lindent |
387 |
static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl) |
1da177e4c Linux-2.6.12-rc2 |
388 389 |
{ struct htb_class *p = cl->parent; |
87990467d [HTB]: Lindent |
390 |
long m, mask = cl->prio_activity; |
1da177e4c Linux-2.6.12-rc2 |
391 392 |
while (cl->cmode == HTB_MAY_BORROW && p && mask) { |
87990467d [HTB]: Lindent |
393 394 |
m = mask; while (m) { |
1da177e4c Linux-2.6.12-rc2 |
395 396 |
int prio = ffz(~m); m &= ~(1 << prio); |
87990467d [HTB]: Lindent |
397 |
|
c9364636d htb: refactor str... |
398 |
if (p->un.inner.clprio[prio].feed.rb_node) |
1da177e4c Linux-2.6.12-rc2 |
399 |
/* parent already has its feed in use so that |
cc7ec456f net_sched: cleanups |
400 401 |
* reset bit in mask as parent is already ok */ |
1da177e4c Linux-2.6.12-rc2 |
402 |
mask &= ~(1 << prio); |
87990467d [HTB]: Lindent |
403 |
|
c9364636d htb: refactor str... |
404 |
htb_add_to_id_tree(&p->un.inner.clprio[prio].feed, cl, prio); |
1da177e4c Linux-2.6.12-rc2 |
405 |
} |
1da177e4c Linux-2.6.12-rc2 |
406 |
p->prio_activity |= mask; |
87990467d [HTB]: Lindent |
407 408 |
cl = p; p = cl->parent; |
3bf72957d [HTB]: Remove bro... |
409 |
|
1da177e4c Linux-2.6.12-rc2 |
410 411 |
} if (cl->cmode == HTB_CAN_SEND && mask) |
87990467d [HTB]: Lindent |
412 |
htb_add_class_to_row(q, cl, mask); |
1da177e4c Linux-2.6.12-rc2 |
413 414 415 416 417 |
} /** * htb_deactivate_prios - remove class from feed chain * |
10297b993 [NET] SCHED: Fix ... |
418 |
* cl->cmode must represent old mode (before deactivation). It does |
1da177e4c Linux-2.6.12-rc2 |
419 420 421 422 423 424 |
* nothing if cl->prio_activity == 0. Class is removed from all feed * chains and rows. */ static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl) { struct htb_class *p = cl->parent; |
87990467d [HTB]: Lindent |
425 |
long m, mask = cl->prio_activity; |
1da177e4c Linux-2.6.12-rc2 |
426 427 |
while (cl->cmode == HTB_MAY_BORROW && p && mask) { |
87990467d [HTB]: Lindent |
428 429 |
m = mask; mask = 0; |
1da177e4c Linux-2.6.12-rc2 |
430 431 432 |
while (m) { int prio = ffz(~m); m &= ~(1 << prio); |
87990467d [HTB]: Lindent |
433 |
|
c9364636d htb: refactor str... |
434 |
if (p->un.inner.clprio[prio].ptr == cl->node + prio) { |
1da177e4c Linux-2.6.12-rc2 |
435 |
/* we are removing child which is pointed to from |
cc7ec456f net_sched: cleanups |
436 437 438 |
* parent feed - forget the pointer but remember * classid */ |
c9364636d htb: refactor str... |
439 440 |
p->un.inner.clprio[prio].last_ptr_id = cl->common.classid; p->un.inner.clprio[prio].ptr = NULL; |
1da177e4c Linux-2.6.12-rc2 |
441 |
} |
87990467d [HTB]: Lindent |
442 |
|
c9364636d htb: refactor str... |
443 444 |
htb_safe_rb_erase(cl->node + prio, &p->un.inner.clprio[prio].feed); |
87990467d [HTB]: Lindent |
445 |
|
c9364636d htb: refactor str... |
446 |
if (!p->un.inner.clprio[prio].feed.rb_node) |
1da177e4c Linux-2.6.12-rc2 |
447 448 |
mask |= 1 << prio; } |
3bf72957d [HTB]: Remove bro... |
449 |
|
1da177e4c Linux-2.6.12-rc2 |
450 |
p->prio_activity &= ~mask; |
87990467d [HTB]: Lindent |
451 452 |
cl = p; p = cl->parent; |
3bf72957d [HTB]: Remove bro... |
453 |
|
1da177e4c Linux-2.6.12-rc2 |
454 |
} |
87990467d [HTB]: Lindent |
455 456 |
if (cl->cmode == HTB_CAN_SEND && mask) htb_remove_class_from_row(q, cl, mask); |
1da177e4c Linux-2.6.12-rc2 |
457 |
} |
56b765b79 htb: improved acc... |
458 |
static inline s64 htb_lowater(const struct htb_class *cl) |
18a63e868 [HTB]: HTB_HYSTER... |
459 |
{ |
47083fc07 pkt_sched: Change... |
460 461 462 463 |
if (htb_hysteresis) return cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : 0; else return 0; |
18a63e868 [HTB]: HTB_HYSTER... |
464 |
} |
56b765b79 htb: improved acc... |
465 |
static inline s64 htb_hiwater(const struct htb_class *cl) |
18a63e868 [HTB]: HTB_HYSTER... |
466 |
{ |
47083fc07 pkt_sched: Change... |
467 468 469 470 |
if (htb_hysteresis) return cl->cmode == HTB_CAN_SEND ? -cl->buffer : 0; else return 0; |
18a63e868 [HTB]: HTB_HYSTER... |
471 |
} |
47083fc07 pkt_sched: Change... |
472 |
|
18a63e868 [HTB]: HTB_HYSTER... |
473 |
|
1da177e4c Linux-2.6.12-rc2 |
474 475 476 477 478 |
/** * htb_class_mode - computes and returns current class mode * * It computes cl's mode at time cl->t_c+diff and returns it. If mode * is not HTB_CAN_SEND then cl->pq_key is updated to time difference |
10297b993 [NET] SCHED: Fix ... |
479 |
* from now to time when cl will change its state. |
1da177e4c Linux-2.6.12-rc2 |
480 |
* Also it is worth to note that class mode doesn't change simply |
10297b993 [NET] SCHED: Fix ... |
481 |
* at cl->{c,}tokens == 0 but there can rather be hysteresis of |
1da177e4c Linux-2.6.12-rc2 |
482 483 484 |
* 0 .. -cl->{c,}buffer range. It is meant to limit number of * mode transitions per time unit. The speed gain is about 1/6. */ |
87990467d [HTB]: Lindent |
485 |
static inline enum htb_cmode |
56b765b79 htb: improved acc... |
486 |
htb_class_mode(struct htb_class *cl, s64 *diff) |
1da177e4c Linux-2.6.12-rc2 |
487 |
{ |
56b765b79 htb: improved acc... |
488 |
s64 toks; |
1da177e4c Linux-2.6.12-rc2 |
489 |
|
87990467d [HTB]: Lindent |
490 491 492 493 |
if ((toks = (cl->ctokens + *diff)) < htb_lowater(cl)) { *diff = -toks; return HTB_CANT_SEND; } |
18a63e868 [HTB]: HTB_HYSTER... |
494 |
|
87990467d [HTB]: Lindent |
495 496 |
if ((toks = (cl->tokens + *diff)) >= htb_hiwater(cl)) return HTB_CAN_SEND; |
1da177e4c Linux-2.6.12-rc2 |
497 |
|
87990467d [HTB]: Lindent |
498 499 |
*diff = -toks; return HTB_MAY_BORROW; |
1da177e4c Linux-2.6.12-rc2 |
500 501 502 503 504 505 506 507 508 509 510 |
} /** * htb_change_class_mode - changes classe's mode * * This should be the only way how to change classe's mode under normal * cirsumstances. Routine will update feed lists linkage, change mode * and add class to the wait event queue if appropriate. New mode should * be different from old one and cl->pq_key has to be valid if changing * to mode other than HTB_CAN_SEND (see htb_add_to_wait_tree). */ |
87990467d [HTB]: Lindent |
511 |
static void |
56b765b79 htb: improved acc... |
512 |
htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, s64 *diff) |
87990467d [HTB]: Lindent |
513 514 |
{ enum htb_cmode new_mode = htb_class_mode(cl, diff); |
1da177e4c Linux-2.6.12-rc2 |
515 516 |
if (new_mode == cl->cmode) |
87990467d [HTB]: Lindent |
517 518 519 520 521 |
return; if (cl->prio_activity) { /* not necessary: speed optimization */ if (cl->cmode != HTB_CANT_SEND) htb_deactivate_prios(q, cl); |
1da177e4c Linux-2.6.12-rc2 |
522 |
cl->cmode = new_mode; |
87990467d [HTB]: Lindent |
523 524 525 |
if (new_mode != HTB_CANT_SEND) htb_activate_prios(q, cl); } else |
1da177e4c Linux-2.6.12-rc2 |
526 527 528 529 |
cl->cmode = new_mode; } /** |
10297b993 [NET] SCHED: Fix ... |
530 |
* htb_activate - inserts leaf cl into appropriate active feeds |
1da177e4c Linux-2.6.12-rc2 |
531 532 533 534 535 |
* * Routine learns (new) priority of leaf and activates feed chain * for the prio. It can be called on already active leaf safely. * It also adds leaf into droplist. */ |
87990467d [HTB]: Lindent |
536 |
static inline void htb_activate(struct htb_sched *q, struct htb_class *cl) |
1da177e4c Linux-2.6.12-rc2 |
537 |
{ |
547b792ca net: convert BUG_... |
538 |
WARN_ON(cl->level || !cl->un.leaf.q || !cl->un.leaf.q->q.qlen); |
3bf72957d [HTB]: Remove bro... |
539 |
|
1da177e4c Linux-2.6.12-rc2 |
540 |
if (!cl->prio_activity) { |
c19f7a34f pkt_sched: sch_ht... |
541 |
cl->prio_activity = 1 << cl->prio; |
87990467d [HTB]: Lindent |
542 543 |
htb_activate_prios(q, cl); list_add_tail(&cl->un.leaf.drop_list, |
c19f7a34f pkt_sched: sch_ht... |
544 |
q->drops + cl->prio); |
1da177e4c Linux-2.6.12-rc2 |
545 546 547 548 |
} } /** |
10297b993 [NET] SCHED: Fix ... |
549 |
* htb_deactivate - remove leaf cl from active feeds |
1da177e4c Linux-2.6.12-rc2 |
550 551 552 553 |
* * Make sure that leaf is active. In the other words it can't be called * with non-active leaf. It also removes class from the drop list. */ |
87990467d [HTB]: Lindent |
554 |
static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl) |
1da177e4c Linux-2.6.12-rc2 |
555 |
{ |
547b792ca net: convert BUG_... |
556 |
WARN_ON(!cl->prio_activity); |
3bf72957d [HTB]: Remove bro... |
557 |
|
87990467d [HTB]: Lindent |
558 |
htb_deactivate_prios(q, cl); |
1da177e4c Linux-2.6.12-rc2 |
559 560 561 |
cl->prio_activity = 0; list_del_init(&cl->un.leaf.drop_list); } |
48da34b7a sched: add and us... |
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 |
static void htb_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch, struct qdisc_skb_head *qh) { struct sk_buff *last = qh->tail; if (last) { skb->next = NULL; last->next = skb; qh->tail = skb; } else { qh->tail = skb; qh->head = skb; } qh->qlen++; } |
520ac30f4 net_sched: drop p... |
577 578 |
static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) |
1da177e4c Linux-2.6.12-rc2 |
579 |
{ |
f30ab418a pkt_sched: Remove... |
580 |
int uninitialized_var(ret); |
87990467d [HTB]: Lindent |
581 582 583 584 585 586 |
struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl = htb_classify(skb, sch, &ret); if (cl == HTB_DIRECT) { /* enqueue to helper queue */ if (q->direct_queue.qlen < q->direct_qlen) { |
48da34b7a sched: add and us... |
587 |
htb_enqueue_tail(skb, sch, &q->direct_queue); |
87990467d [HTB]: Lindent |
588 589 |
q->direct_pkts++; } else { |
520ac30f4 net_sched: drop p... |
590 |
return qdisc_drop(skb, sch, to_free); |
87990467d [HTB]: Lindent |
591 |
} |
1da177e4c Linux-2.6.12-rc2 |
592 |
#ifdef CONFIG_NET_CLS_ACT |
87990467d [HTB]: Lindent |
593 |
} else if (!cl) { |
c27f339af net_sched: Add qd... |
594 |
if (ret & __NET_XMIT_BYPASS) |
25331d6ce net: sched: imple... |
595 |
qdisc_qstats_drop(sch); |
520ac30f4 net_sched: drop p... |
596 |
__qdisc_drop(skb, to_free); |
87990467d [HTB]: Lindent |
597 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
598 |
#endif |
520ac30f4 net_sched: drop p... |
599 600 |
} else if ((ret = qdisc_enqueue(skb, cl->un.leaf.q, to_free)) != NET_XMIT_SUCCESS) { |
378a2f090 net_sched: Add qd... |
601 |
if (net_xmit_drop_count(ret)) { |
25331d6ce net: sched: imple... |
602 |
qdisc_qstats_drop(sch); |
338ed9b4d net_sched: sch_ht... |
603 |
cl->drops++; |
378a2f090 net_sched: Add qd... |
604 |
} |
69747650c pkt_sched: Fix re... |
605 |
return ret; |
87990467d [HTB]: Lindent |
606 |
} else { |
87990467d [HTB]: Lindent |
607 608 |
htb_activate(q, cl); } |
431e3a8e3 sch_htb: update b... |
609 |
qdisc_qstats_backlog_inc(sch, skb); |
87990467d [HTB]: Lindent |
610 |
sch->q.qlen++; |
87990467d [HTB]: Lindent |
611 |
return NET_XMIT_SUCCESS; |
1da177e4c Linux-2.6.12-rc2 |
612 |
} |
56b765b79 htb: improved acc... |
613 |
static inline void htb_accnt_tokens(struct htb_class *cl, int bytes, s64 diff) |
59e4220a1 pkt_sched: sch_ht... |
614 |
{ |
56b765b79 htb: improved acc... |
615 |
s64 toks = diff + cl->tokens; |
59e4220a1 pkt_sched: sch_ht... |
616 617 618 |
if (toks > cl->buffer) toks = cl->buffer; |
292f1c7ff sch: make htb_rat... |
619 |
toks -= (s64) psched_l2t_ns(&cl->rate, bytes); |
59e4220a1 pkt_sched: sch_ht... |
620 621 622 623 624 |
if (toks <= -cl->mbuffer) toks = 1 - cl->mbuffer; cl->tokens = toks; } |
56b765b79 htb: improved acc... |
625 |
static inline void htb_accnt_ctokens(struct htb_class *cl, int bytes, s64 diff) |
59e4220a1 pkt_sched: sch_ht... |
626 |
{ |
56b765b79 htb: improved acc... |
627 |
s64 toks = diff + cl->ctokens; |
59e4220a1 pkt_sched: sch_ht... |
628 629 630 |
if (toks > cl->cbuffer) toks = cl->cbuffer; |
292f1c7ff sch: make htb_rat... |
631 |
toks -= (s64) psched_l2t_ns(&cl->ceil, bytes); |
59e4220a1 pkt_sched: sch_ht... |
632 633 634 635 636 |
if (toks <= -cl->mbuffer) toks = 1 - cl->mbuffer; cl->ctokens = toks; } |
1da177e4c Linux-2.6.12-rc2 |
637 638 639 640 641 642 643 644 645 646 647 |
/** * htb_charge_class - charges amount "bytes" to leaf and ancestors * * Routine assumes that packet "bytes" long was dequeued from leaf cl * borrowing from "level". It accounts bytes to ceil leaky bucket for * leaf and all ancestors and to rate bucket for ancestors at levels * "level" and higher. It also handles possible change of mode resulting * from the update. Note that mode can also increase here (MAY_BORROW to * CAN_SEND) because we can use more precise clock that event queue here. * In such case we remove class from event queue first. */ |
87990467d [HTB]: Lindent |
648 |
static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, |
c9726d689 [NET_SCHED]: Make... |
649 |
int level, struct sk_buff *skb) |
87990467d [HTB]: Lindent |
650 |
{ |
0abf77e55 net_sched: Add ac... |
651 |
int bytes = qdisc_pkt_len(skb); |
1da177e4c Linux-2.6.12-rc2 |
652 |
enum htb_cmode old_mode; |
56b765b79 htb: improved acc... |
653 |
s64 diff; |
1da177e4c Linux-2.6.12-rc2 |
654 655 |
while (cl) { |
56b765b79 htb: improved acc... |
656 |
diff = min_t(s64, q->now - cl->t_c, cl->mbuffer); |
1da177e4c Linux-2.6.12-rc2 |
657 |
if (cl->level >= level) { |
87990467d [HTB]: Lindent |
658 659 |
if (cl->level == level) cl->xstats.lends++; |
59e4220a1 pkt_sched: sch_ht... |
660 |
htb_accnt_tokens(cl, bytes, diff); |
1da177e4c Linux-2.6.12-rc2 |
661 662 |
} else { cl->xstats.borrows++; |
87990467d [HTB]: Lindent |
663 |
cl->tokens += diff; /* we moved t_c; update tokens */ |
1da177e4c Linux-2.6.12-rc2 |
664 |
} |
59e4220a1 pkt_sched: sch_ht... |
665 |
htb_accnt_ctokens(cl, bytes, diff); |
1da177e4c Linux-2.6.12-rc2 |
666 |
cl->t_c = q->now; |
1da177e4c Linux-2.6.12-rc2 |
667 |
|
87990467d [HTB]: Lindent |
668 669 670 |
old_mode = cl->cmode; diff = 0; htb_change_class_mode(q, cl, &diff); |
1da177e4c Linux-2.6.12-rc2 |
671 672 |
if (old_mode != cl->cmode) { if (old_mode != HTB_CAN_SEND) |
c9364636d htb: refactor str... |
673 |
htb_safe_rb_erase(&cl->pq_node, &q->hlevel[cl->level].wait_pq); |
1da177e4c Linux-2.6.12-rc2 |
674 |
if (cl->cmode != HTB_CAN_SEND) |
87990467d [HTB]: Lindent |
675 |
htb_add_to_wait_tree(q, cl, diff); |
1da177e4c Linux-2.6.12-rc2 |
676 |
} |
1da177e4c Linux-2.6.12-rc2 |
677 |
|
bfe0d0298 net_sched: factor... |
678 679 680 |
/* update basic stats except for leaves which are already updated */ if (cl->level) bstats_update(&cl->bstats, skb); |
1da177e4c Linux-2.6.12-rc2 |
681 682 683 684 685 686 687 |
cl = cl->parent; } } /** * htb_do_events - make mode changes to classes at the level * |
fb983d457 [NET_SCHED]: sch_... |
688 |
* Scans event queue for pending events and applies them. Returns time of |
1224736d9 pkt_sched: sch_ht... |
689 |
* next pending event (0 for no event in pq, q->now for too many events). |
fb983d457 [NET_SCHED]: sch_... |
690 |
* Note: Applied are events whose have cl->pq_key <= q->now. |
1da177e4c Linux-2.6.12-rc2 |
691 |
*/ |
c9364636d htb: refactor str... |
692 |
static s64 htb_do_events(struct htb_sched *q, const int level, |
5343a7f8b net_sched: htb: d... |
693 |
unsigned long start) |
1da177e4c Linux-2.6.12-rc2 |
694 |
{ |
8f3ea33a5 sch_htb: fix "too... |
695 |
/* don't run for longer than 2 jiffies; 2 is used instead of |
cc7ec456f net_sched: cleanups |
696 697 698 |
* 1 to simplify things when jiffy is going to be incremented * too soon */ |
a73be0406 pkt_sched: sch_ht... |
699 |
unsigned long stop_at = start + 2; |
c9364636d htb: refactor str... |
700 |
struct rb_root *wait_pq = &q->hlevel[level].wait_pq; |
8f3ea33a5 sch_htb: fix "too... |
701 |
while (time_before(jiffies, stop_at)) { |
1da177e4c Linux-2.6.12-rc2 |
702 |
struct htb_class *cl; |
56b765b79 htb: improved acc... |
703 |
s64 diff; |
c9364636d htb: refactor str... |
704 |
struct rb_node *p = rb_first(wait_pq); |
30bdbe397 [PKT_SCHED] sch_h... |
705 |
|
87990467d [HTB]: Lindent |
706 707 |
if (!p) return 0; |
1da177e4c Linux-2.6.12-rc2 |
708 709 |
cl = rb_entry(p, struct htb_class, pq_node); |
fb983d457 [NET_SCHED]: sch_... |
710 711 |
if (cl->pq_key > q->now) return cl->pq_key; |
c9364636d htb: refactor str... |
712 |
htb_safe_rb_erase(p, wait_pq); |
56b765b79 htb: improved acc... |
713 |
diff = min_t(s64, q->now - cl->t_c, cl->mbuffer); |
87990467d [HTB]: Lindent |
714 |
htb_change_class_mode(q, cl, &diff); |
1da177e4c Linux-2.6.12-rc2 |
715 |
if (cl->cmode != HTB_CAN_SEND) |
87990467d [HTB]: Lindent |
716 |
htb_add_to_wait_tree(q, cl, diff); |
1da177e4c Linux-2.6.12-rc2 |
717 |
} |
1224736d9 pkt_sched: sch_ht... |
718 719 |
/* too much load - let's continue after a break for scheduling */ |
e82181de5 pkt_sched: sch_ht... |
720 |
if (!(q->warned & HTB_WARN_TOOMANYEVENTS)) { |
c17988a90 net_sched: replac... |
721 722 |
pr_warn("htb: too many events! "); |
e82181de5 pkt_sched: sch_ht... |
723 724 |
q->warned |= HTB_WARN_TOOMANYEVENTS; } |
1224736d9 pkt_sched: sch_ht... |
725 726 |
return q->now; |
1da177e4c Linux-2.6.12-rc2 |
727 728 729 |
} /* Returns class->node+prio from id-tree where classe's id is >= id. NULL |
cc7ec456f net_sched: cleanups |
730 731 |
* is no such one exists. */ |
87990467d [HTB]: Lindent |
732 733 |
static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n, u32 id) |
1da177e4c Linux-2.6.12-rc2 |
734 735 736 |
{ struct rb_node *r = NULL; while (n) { |
87990467d [HTB]: Lindent |
737 738 |
struct htb_class *cl = rb_entry(n, struct htb_class, node[prio]); |
87990467d [HTB]: Lindent |
739 |
|
f4c1f3e0c net-sched: sch_ht... |
740 |
if (id > cl->common.classid) { |
1da177e4c Linux-2.6.12-rc2 |
741 |
n = n->rb_right; |
1b5c0077e pkt_sched: sch_ht... |
742 |
} else if (id < cl->common.classid) { |
1da177e4c Linux-2.6.12-rc2 |
743 744 |
r = n; n = n->rb_left; |
1b5c0077e pkt_sched: sch_ht... |
745 746 |
} else { return n; |
1da177e4c Linux-2.6.12-rc2 |
747 748 749 750 751 752 753 754 755 756 |
} } return r; } /** * htb_lookup_leaf - returns next leaf class in DRR order * * Find leaf where current feed pointers points to. */ |
c9364636d htb: refactor str... |
757 |
static struct htb_class *htb_lookup_leaf(struct htb_prio *hprio, const int prio) |
1da177e4c Linux-2.6.12-rc2 |
758 759 760 761 762 763 |
{ int i; struct { struct rb_node *root; struct rb_node **pptr; u32 *pid; |
87990467d [HTB]: Lindent |
764 |
} stk[TC_HTB_MAXDEPTH], *sp = stk; |
c9364636d htb: refactor str... |
765 766 767 768 |
BUG_ON(!hprio->row.rb_node); sp->root = hprio->row.rb_node; sp->pptr = &hprio->ptr; sp->pid = &hprio->last_ptr_id; |
1da177e4c Linux-2.6.12-rc2 |
769 770 |
for (i = 0; i < 65535; i++) { |
87990467d [HTB]: Lindent |
771 |
if (!*sp->pptr && *sp->pid) { |
10297b993 [NET] SCHED: Fix ... |
772 |
/* ptr was invalidated but id is valid - try to recover |
cc7ec456f net_sched: cleanups |
773 774 |
* the original or next ptr */ |
87990467d [HTB]: Lindent |
775 776 |
*sp->pptr = htb_id_find_next_upper(prio, sp->root, *sp->pid); |
1da177e4c Linux-2.6.12-rc2 |
777 |
} |
87990467d [HTB]: Lindent |
778 |
*sp->pid = 0; /* ptr is valid now so that remove this hint as it |
cc7ec456f net_sched: cleanups |
779 780 |
* can become out of date quickly */ |
87990467d [HTB]: Lindent |
781 |
if (!*sp->pptr) { /* we are at right end; rewind & go up */ |
1da177e4c Linux-2.6.12-rc2 |
782 |
*sp->pptr = sp->root; |
87990467d [HTB]: Lindent |
783 |
while ((*sp->pptr)->rb_left) |
1da177e4c Linux-2.6.12-rc2 |
784 785 786 |
*sp->pptr = (*sp->pptr)->rb_left; if (sp > stk) { sp--; |
512bb43eb pkt_sched: sch_ht... |
787 788 |
if (!*sp->pptr) { WARN_ON(1); |
87990467d [HTB]: Lindent |
789 |
return NULL; |
512bb43eb pkt_sched: sch_ht... |
790 |
} |
87990467d [HTB]: Lindent |
791 |
htb_next_rb_node(sp->pptr); |
1da177e4c Linux-2.6.12-rc2 |
792 793 794 |
} } else { struct htb_class *cl; |
c9364636d htb: refactor str... |
795 |
struct htb_prio *clp; |
87990467d [HTB]: Lindent |
796 797 |
cl = rb_entry(*sp->pptr, struct htb_class, node[prio]); if (!cl->level) |
1da177e4c Linux-2.6.12-rc2 |
798 |
return cl; |
c9364636d htb: refactor str... |
799 800 801 802 |
clp = &cl->un.inner.clprio[prio]; (++sp)->root = clp->feed.rb_node; sp->pptr = &clp->ptr; sp->pid = &clp->last_ptr_id; |
1da177e4c Linux-2.6.12-rc2 |
803 804 |
} } |
547b792ca net: convert BUG_... |
805 |
WARN_ON(1); |
1da177e4c Linux-2.6.12-rc2 |
806 807 808 809 |
return NULL; } /* dequeues packet at given priority and level; call only if |
cc7ec456f net_sched: cleanups |
810 811 |
* you are sure that there is active class at prio/level */ |
c9364636d htb: refactor str... |
812 813 |
static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, const int prio, const int level) |
1da177e4c Linux-2.6.12-rc2 |
814 815 |
{ struct sk_buff *skb = NULL; |
87990467d [HTB]: Lindent |
816 |
struct htb_class *cl, *start; |
c9364636d htb: refactor str... |
817 818 |
struct htb_level *hlevel = &q->hlevel[level]; struct htb_prio *hprio = &hlevel->hprio[prio]; |
1da177e4c Linux-2.6.12-rc2 |
819 |
/* look initial class up in the row */ |
c9364636d htb: refactor str... |
820 |
start = cl = htb_lookup_leaf(hprio, prio); |
87990467d [HTB]: Lindent |
821 |
|
1da177e4c Linux-2.6.12-rc2 |
822 823 |
do { next: |
512bb43eb pkt_sched: sch_ht... |
824 |
if (unlikely(!cl)) |
87990467d [HTB]: Lindent |
825 |
return NULL; |
1da177e4c Linux-2.6.12-rc2 |
826 827 |
/* class can be empty - it is unlikely but can be true if leaf |
cc7ec456f net_sched: cleanups |
828 829 830 831 |
* qdisc drops packets in enqueue routine or if someone used * graft operation on the leaf since last dequeue; * simply deactivate and skip such class */ |
1da177e4c Linux-2.6.12-rc2 |
832 833 |
if (unlikely(cl->un.leaf.q->q.qlen == 0)) { struct htb_class *next; |
87990467d [HTB]: Lindent |
834 |
htb_deactivate(q, cl); |
1da177e4c Linux-2.6.12-rc2 |
835 836 837 |
/* row/level might become empty */ if ((q->row_mask[level] & (1 << prio)) == 0) |
87990467d [HTB]: Lindent |
838 |
return NULL; |
1da177e4c Linux-2.6.12-rc2 |
839 |
|
c9364636d htb: refactor str... |
840 |
next = htb_lookup_leaf(hprio, prio); |
87990467d [HTB]: Lindent |
841 842 |
if (cl == start) /* fix start if we just deleted it */ |
1da177e4c Linux-2.6.12-rc2 |
843 844 845 846 |
start = next; cl = next; goto next; } |
87990467d [HTB]: Lindent |
847 848 849 |
skb = cl->un.leaf.q->dequeue(cl->un.leaf.q); if (likely(skb != NULL)) |
1da177e4c Linux-2.6.12-rc2 |
850 |
break; |
633fe66ed pkt_sched: sch_ht... |
851 |
|
b00355db3 pkt_sched: sch_hf... |
852 |
qdisc_warn_nonwc("htb", cl->un.leaf.q); |
c9364636d htb: refactor str... |
853 854 855 |
htb_next_rb_node(level ? &cl->parent->un.inner.clprio[prio].ptr: &q->hlevel[0].hprio[prio].ptr); cl = htb_lookup_leaf(hprio, prio); |
1da177e4c Linux-2.6.12-rc2 |
856 857 858 859 |
} while (cl != start); if (likely(skb != NULL)) { |
196d97f6b htb: fix two bugs |
860 |
bstats_update(&cl->bstats, skb); |
0abf77e55 net_sched: Add ac... |
861 862 |
cl->un.leaf.deficit[level] -= qdisc_pkt_len(skb); if (cl->un.leaf.deficit[level] < 0) { |
c19f7a34f pkt_sched: sch_ht... |
863 |
cl->un.leaf.deficit[level] += cl->quantum; |
c9364636d htb: refactor str... |
864 865 |
htb_next_rb_node(level ? &cl->parent->un.inner.clprio[prio].ptr : &q->hlevel[0].hprio[prio].ptr); |
1da177e4c Linux-2.6.12-rc2 |
866 867 |
} /* this used to be after charge_class but this constelation |
cc7ec456f net_sched: cleanups |
868 869 |
* gives us slightly better performance */ |
1da177e4c Linux-2.6.12-rc2 |
870 |
if (!cl->un.leaf.q->q.qlen) |
87990467d [HTB]: Lindent |
871 |
htb_deactivate(q, cl); |
c9726d689 [NET_SCHED]: Make... |
872 |
htb_charge_class(q, cl, level, skb); |
1da177e4c Linux-2.6.12-rc2 |
873 874 875 |
} return skb; } |
1da177e4c Linux-2.6.12-rc2 |
876 877 |
static struct sk_buff *htb_dequeue(struct Qdisc *sch) { |
9190b3b32 net_sched: accura... |
878 |
struct sk_buff *skb; |
1da177e4c Linux-2.6.12-rc2 |
879 880 |
struct htb_sched *q = qdisc_priv(sch); int level; |
5343a7f8b net_sched: htb: d... |
881 |
s64 next_event; |
a73be0406 pkt_sched: sch_ht... |
882 |
unsigned long start_at; |
1da177e4c Linux-2.6.12-rc2 |
883 884 |
/* try to dequeue direct packets as high prio (!) to minimize cpu work */ |
48da34b7a sched: add and us... |
885 |
skb = __qdisc_dequeue_head(&q->direct_queue); |
87990467d [HTB]: Lindent |
886 |
if (skb != NULL) { |
9190b3b32 net_sched: accura... |
887 888 |
ok: qdisc_bstats_update(sch, skb); |
431e3a8e3 sch_htb: update b... |
889 |
qdisc_qstats_backlog_dec(sch, skb); |
1da177e4c Linux-2.6.12-rc2 |
890 891 892 |
sch->q.qlen--; return skb; } |
87990467d [HTB]: Lindent |
893 894 |
if (!sch->q.qlen) goto fin; |
d2de875c6 net: use ktime_ge... |
895 |
q->now = ktime_get_ns(); |
a73be0406 pkt_sched: sch_ht... |
896 |
start_at = jiffies; |
1da177e4c Linux-2.6.12-rc2 |
897 |
|
d2fe85da5 net: sched: integ... |
898 |
next_event = q->now + 5LLU * NSEC_PER_SEC; |
633fe66ed pkt_sched: sch_ht... |
899 |
|
1da177e4c Linux-2.6.12-rc2 |
900 901 902 |
for (level = 0; level < TC_HTB_MAXDEPTH; level++) { /* common case optimization - skip event handler quickly */ int m; |
c9364636d htb: refactor str... |
903 |
s64 event = q->near_ev_cache[level]; |
fb983d457 [NET_SCHED]: sch_... |
904 |
|
c9364636d htb: refactor str... |
905 |
if (q->now >= event) { |
a73be0406 pkt_sched: sch_ht... |
906 |
event = htb_do_events(q, level, start_at); |
2e4b3b0e8 [NET_SCHED]: sch_... |
907 |
if (!event) |
56b765b79 htb: improved acc... |
908 |
event = q->now + NSEC_PER_SEC; |
2e4b3b0e8 [NET_SCHED]: sch_... |
909 |
q->near_ev_cache[level] = event; |
c9364636d htb: refactor str... |
910 |
} |
fb983d457 [NET_SCHED]: sch_... |
911 |
|
c08513471 pkt_sched: sch_ht... |
912 |
if (next_event > event) |
fb983d457 [NET_SCHED]: sch_... |
913 |
next_event = event; |
87990467d [HTB]: Lindent |
914 |
|
1da177e4c Linux-2.6.12-rc2 |
915 916 |
m = ~q->row_mask[level]; while (m != (int)(-1)) { |
87990467d [HTB]: Lindent |
917 |
int prio = ffz(m); |
cc7ec456f net_sched: cleanups |
918 |
|
1da177e4c Linux-2.6.12-rc2 |
919 |
m |= 1 << prio; |
87990467d [HTB]: Lindent |
920 |
skb = htb_dequeue_tree(q, prio, level); |
9190b3b32 net_sched: accura... |
921 922 |
if (likely(skb != NULL)) goto ok; |
1da177e4c Linux-2.6.12-rc2 |
923 924 |
} } |
25331d6ce net: sched: imple... |
925 |
qdisc_qstats_overlimit(sch); |
a9efad8b2 net_sched: avoid ... |
926 |
if (likely(next_event > q->now)) |
45f50bed1 net_sched: remove... |
927 |
qdisc_watchdog_schedule_ns(&q->watchdog, next_event); |
a9efad8b2 net_sched: avoid ... |
928 |
else |
1224736d9 pkt_sched: sch_ht... |
929 |
schedule_work(&q->work); |
1da177e4c Linux-2.6.12-rc2 |
930 |
fin: |
1da177e4c Linux-2.6.12-rc2 |
931 932 |
return skb; } |
1da177e4c Linux-2.6.12-rc2 |
933 934 |
/* reset all classes */ /* always caled under BH & queue lock */ |
87990467d [HTB]: Lindent |
935 |
static void htb_reset(struct Qdisc *sch) |
1da177e4c Linux-2.6.12-rc2 |
936 937 |
{ struct htb_sched *q = qdisc_priv(sch); |
f4c1f3e0c net-sched: sch_ht... |
938 |
struct htb_class *cl; |
f4c1f3e0c net-sched: sch_ht... |
939 |
unsigned int i; |
0cef296da [HTB]: Use hlist ... |
940 |
|
f4c1f3e0c net-sched: sch_ht... |
941 |
for (i = 0; i < q->clhash.hashsize; i++) { |
b67bfe0d4 hlist: drop the n... |
942 |
hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode) { |
1da177e4c Linux-2.6.12-rc2 |
943 |
if (cl->level) |
87990467d [HTB]: Lindent |
944 |
memset(&cl->un.inner, 0, sizeof(cl->un.inner)); |
1da177e4c Linux-2.6.12-rc2 |
945 |
else { |
87990467d [HTB]: Lindent |
946 |
if (cl->un.leaf.q) |
1da177e4c Linux-2.6.12-rc2 |
947 948 949 950 951 |
qdisc_reset(cl->un.leaf.q); INIT_LIST_HEAD(&cl->un.leaf.drop_list); } cl->prio_activity = 0; cl->cmode = HTB_CAN_SEND; |
1da177e4c Linux-2.6.12-rc2 |
952 953 |
} } |
fb983d457 [NET_SCHED]: sch_... |
954 |
qdisc_watchdog_cancel(&q->watchdog); |
a5a9f5346 net_sched: sch_ht... |
955 |
__qdisc_reset_queue(&q->direct_queue); |
1da177e4c Linux-2.6.12-rc2 |
956 |
sch->q.qlen = 0; |
431e3a8e3 sch_htb: update b... |
957 |
sch->qstats.backlog = 0; |
c9364636d htb: refactor str... |
958 |
memset(q->hlevel, 0, sizeof(q->hlevel)); |
87990467d [HTB]: Lindent |
959 |
memset(q->row_mask, 0, sizeof(q->row_mask)); |
1da177e4c Linux-2.6.12-rc2 |
960 |
for (i = 0; i < TC_HTB_NUMPRIO; i++) |
87990467d [HTB]: Lindent |
961 |
INIT_LIST_HEAD(q->drops + i); |
1da177e4c Linux-2.6.12-rc2 |
962 |
} |
27a3421e4 [NET_SCHED]: Use ... |
963 964 965 966 967 |
static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = { [TCA_HTB_PARMS] = { .len = sizeof(struct tc_htb_opt) }, [TCA_HTB_INIT] = { .len = sizeof(struct tc_htb_glob) }, [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, |
6906f4ed6 htb: add HTB_DIRE... |
968 |
[TCA_HTB_DIRECT_QLEN] = { .type = NLA_U32 }, |
df62cdf34 net_sched: htb: s... |
969 970 |
[TCA_HTB_RATE64] = { .type = NLA_U64 }, [TCA_HTB_CEIL64] = { .type = NLA_U64 }, |
27a3421e4 [NET_SCHED]: Use ... |
971 |
}; |
1224736d9 pkt_sched: sch_ht... |
972 973 974 975 |
static void htb_work_func(struct work_struct *work) { struct htb_sched *q = container_of(work, struct htb_sched, work); struct Qdisc *sch = q->watchdog.qdisc; |
0ee13627f htb: call qdisc_r... |
976 |
rcu_read_lock(); |
1224736d9 pkt_sched: sch_ht... |
977 |
__netif_schedule(qdisc_root(sch)); |
0ee13627f htb: call qdisc_r... |
978 |
rcu_read_unlock(); |
1224736d9 pkt_sched: sch_ht... |
979 |
} |
1e90474c3 [NET_SCHED]: Conv... |
980 |
static int htb_init(struct Qdisc *sch, struct nlattr *opt) |
1da177e4c Linux-2.6.12-rc2 |
981 982 |
{ struct htb_sched *q = qdisc_priv(sch); |
6906f4ed6 htb: add HTB_DIRE... |
983 |
struct nlattr *tb[TCA_HTB_MAX + 1]; |
1da177e4c Linux-2.6.12-rc2 |
984 |
struct tc_htb_glob *gopt; |
cee63723b [NET_SCHED]: Prop... |
985 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
986 |
int i; |
cee63723b [NET_SCHED]: Prop... |
987 |
|
88c2ace69 sch_htb: fix cras... |
988 989 |
qdisc_watchdog_init(&q->watchdog, sch); INIT_WORK(&q->work, htb_work_func); |
cee63723b [NET_SCHED]: Prop... |
990 991 |
if (!opt) return -EINVAL; |
6529eaba3 net: sched: intro... |
992 993 994 |
err = tcf_block_get(&q->block, &q->filter_list); if (err) return err; |
fceb6435e netlink: pass ext... |
995 |
err = nla_parse_nested(tb, TCA_HTB_MAX, opt, htb_policy, NULL); |
cee63723b [NET_SCHED]: Prop... |
996 997 |
if (err < 0) return err; |
6906f4ed6 htb: add HTB_DIRE... |
998 |
if (!tb[TCA_HTB_INIT]) |
1da177e4c Linux-2.6.12-rc2 |
999 |
return -EINVAL; |
6906f4ed6 htb: add HTB_DIRE... |
1000 |
|
1e90474c3 [NET_SCHED]: Conv... |
1001 |
gopt = nla_data(tb[TCA_HTB_INIT]); |
6906f4ed6 htb: add HTB_DIRE... |
1002 |
if (gopt->version != HTB_VER >> 16) |
1da177e4c Linux-2.6.12-rc2 |
1003 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
1004 |
|
f4c1f3e0c net-sched: sch_ht... |
1005 1006 1007 |
err = qdisc_class_hash_init(&q->clhash); if (err < 0) return err; |
1da177e4c Linux-2.6.12-rc2 |
1008 |
for (i = 0; i < TC_HTB_NUMPRIO; i++) |
87990467d [HTB]: Lindent |
1009 |
INIT_LIST_HEAD(q->drops + i); |
1da177e4c Linux-2.6.12-rc2 |
1010 |
|
48da34b7a sched: add and us... |
1011 |
qdisc_skb_head_init(&q->direct_queue); |
1da177e4c Linux-2.6.12-rc2 |
1012 |
|
6906f4ed6 htb: add HTB_DIRE... |
1013 1014 |
if (tb[TCA_HTB_DIRECT_QLEN]) q->direct_qlen = nla_get_u32(tb[TCA_HTB_DIRECT_QLEN]); |
348e3435c net: sched: drop ... |
1015 |
else |
6906f4ed6 htb: add HTB_DIRE... |
1016 |
q->direct_qlen = qdisc_dev(sch)->tx_queue_len; |
348e3435c net: sched: drop ... |
1017 |
|
1da177e4c Linux-2.6.12-rc2 |
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 |
if ((q->rate2quantum = gopt->rate2quantum) < 1) q->rate2quantum = 1; q->defcls = gopt->defcls; return 0; } static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) { struct htb_sched *q = qdisc_priv(sch); |
4b3550ef5 [NET_SCHED]: Use ... |
1028 |
struct nlattr *nest; |
1da177e4c Linux-2.6.12-rc2 |
1029 |
struct tc_htb_glob gopt; |
4b3550ef5 [NET_SCHED]: Use ... |
1030 |
|
6f542efcb net_sched: htb: d... |
1031 1032 1033 |
/* Its safe to not acquire qdisc lock. As we hold RTNL, * no change can happen on the qdisc parameters. */ |
1da177e4c Linux-2.6.12-rc2 |
1034 |
|
4b3550ef5 [NET_SCHED]: Use ... |
1035 |
gopt.direct_pkts = q->direct_pkts; |
1da177e4c Linux-2.6.12-rc2 |
1036 1037 1038 |
gopt.version = HTB_VER; gopt.rate2quantum = q->rate2quantum; gopt.defcls = q->defcls; |
3bf72957d [HTB]: Remove bro... |
1039 |
gopt.debug = 0; |
4b3550ef5 [NET_SCHED]: Use ... |
1040 1041 1042 1043 |
nest = nla_nest_start(skb, TCA_OPTIONS); if (nest == NULL) goto nla_put_failure; |
6906f4ed6 htb: add HTB_DIRE... |
1044 1045 |
if (nla_put(skb, TCA_HTB_INIT, sizeof(gopt), &gopt) || nla_put_u32(skb, TCA_HTB_DIRECT_QLEN, q->direct_qlen)) |
1b34ec43c pkt_sched: Stop u... |
1046 |
goto nla_put_failure; |
4b3550ef5 [NET_SCHED]: Use ... |
1047 |
|
6f542efcb net_sched: htb: d... |
1048 |
return nla_nest_end(skb, nest); |
4b3550ef5 [NET_SCHED]: Use ... |
1049 |
|
1e90474c3 [NET_SCHED]: Conv... |
1050 |
nla_put_failure: |
4b3550ef5 [NET_SCHED]: Use ... |
1051 |
nla_nest_cancel(skb, nest); |
1da177e4c Linux-2.6.12-rc2 |
1052 1053 1054 1055 |
return -1; } static int htb_dump_class(struct Qdisc *sch, unsigned long arg, |
87990467d [HTB]: Lindent |
1056 |
struct sk_buff *skb, struct tcmsg *tcm) |
1da177e4c Linux-2.6.12-rc2 |
1057 |
{ |
87990467d [HTB]: Lindent |
1058 |
struct htb_class *cl = (struct htb_class *)arg; |
4b3550ef5 [NET_SCHED]: Use ... |
1059 |
struct nlattr *nest; |
1da177e4c Linux-2.6.12-rc2 |
1060 |
struct tc_htb_opt opt; |
6f542efcb net_sched: htb: d... |
1061 1062 1063 |
/* Its safe to not acquire qdisc lock. As we hold RTNL, * no change can happen on the class parameters. */ |
f4c1f3e0c net-sched: sch_ht... |
1064 1065 |
tcm->tcm_parent = cl->parent ? cl->parent->common.classid : TC_H_ROOT; tcm->tcm_handle = cl->common.classid; |
1da177e4c Linux-2.6.12-rc2 |
1066 1067 |
if (!cl->level && cl->un.leaf.q) tcm->tcm_info = cl->un.leaf.q->handle; |
4b3550ef5 [NET_SCHED]: Use ... |
1068 1069 1070 |
nest = nla_nest_start(skb, TCA_OPTIONS); if (nest == NULL) goto nla_put_failure; |
1da177e4c Linux-2.6.12-rc2 |
1071 |
|
87990467d [HTB]: Lindent |
1072 |
memset(&opt, 0, sizeof(opt)); |
1da177e4c Linux-2.6.12-rc2 |
1073 |
|
01cb71d2d net_sched: restor... |
1074 |
psched_ratecfg_getrate(&opt.rate, &cl->rate); |
9c10f4115 htb: fix values i... |
1075 |
opt.buffer = PSCHED_NS2TICKS(cl->buffer); |
01cb71d2d net_sched: restor... |
1076 |
psched_ratecfg_getrate(&opt.ceil, &cl->ceil); |
9c10f4115 htb: fix values i... |
1077 |
opt.cbuffer = PSCHED_NS2TICKS(cl->cbuffer); |
c19f7a34f pkt_sched: sch_ht... |
1078 1079 |
opt.quantum = cl->quantum; opt.prio = cl->prio; |
87990467d [HTB]: Lindent |
1080 |
opt.level = cl->level; |
1b34ec43c pkt_sched: Stop u... |
1081 1082 |
if (nla_put(skb, TCA_HTB_PARMS, sizeof(opt), &opt)) goto nla_put_failure; |
df62cdf34 net_sched: htb: s... |
1083 |
if ((cl->rate.rate_bytes_ps >= (1ULL << 32)) && |
2a51c1e8e sched: use nla_pu... |
1084 1085 |
nla_put_u64_64bit(skb, TCA_HTB_RATE64, cl->rate.rate_bytes_ps, TCA_HTB_PAD)) |
df62cdf34 net_sched: htb: s... |
1086 1087 |
goto nla_put_failure; if ((cl->ceil.rate_bytes_ps >= (1ULL << 32)) && |
2a51c1e8e sched: use nla_pu... |
1088 1089 |
nla_put_u64_64bit(skb, TCA_HTB_CEIL64, cl->ceil.rate_bytes_ps, TCA_HTB_PAD)) |
df62cdf34 net_sched: htb: s... |
1090 |
goto nla_put_failure; |
4b3550ef5 [NET_SCHED]: Use ... |
1091 |
|
6f542efcb net_sched: htb: d... |
1092 |
return nla_nest_end(skb, nest); |
4b3550ef5 [NET_SCHED]: Use ... |
1093 |
|
1e90474c3 [NET_SCHED]: Conv... |
1094 |
nla_put_failure: |
4b3550ef5 [NET_SCHED]: Use ... |
1095 |
nla_nest_cancel(skb, nest); |
1da177e4c Linux-2.6.12-rc2 |
1096 1097 1098 1099 |
return -1; } static int |
87990467d [HTB]: Lindent |
1100 |
htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d) |
1da177e4c Linux-2.6.12-rc2 |
1101 |
{ |
87990467d [HTB]: Lindent |
1102 |
struct htb_class *cl = (struct htb_class *)arg; |
338ed9b4d net_sched: sch_ht... |
1103 1104 1105 |
struct gnet_stats_queue qs = { .drops = cl->drops, }; |
640158536 net: sched: restr... |
1106 |
__u32 qlen = 0; |
1da177e4c Linux-2.6.12-rc2 |
1107 |
|
338ed9b4d net_sched: sch_ht... |
1108 |
if (!cl->level && cl->un.leaf.q) { |
640158536 net: sched: restr... |
1109 |
qlen = cl->un.leaf.q->q.qlen; |
338ed9b4d net_sched: sch_ht... |
1110 1111 |
qs.backlog = cl->un.leaf.q->qstats.backlog; } |
0564bf0af net/sched/sch_htb... |
1112 1113 1114 1115 |
cl->xstats.tokens = clamp_t(s64, PSCHED_NS2TICKS(cl->tokens), INT_MIN, INT_MAX); cl->xstats.ctokens = clamp_t(s64, PSCHED_NS2TICKS(cl->ctokens), INT_MIN, INT_MAX); |
1da177e4c Linux-2.6.12-rc2 |
1116 |
|
edb09eb17 net: sched: do no... |
1117 1118 |
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch), d, NULL, &cl->bstats) < 0 || |
1c0d32fde net_sched: gen_es... |
1119 |
gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 || |
338ed9b4d net_sched: sch_ht... |
1120 |
gnet_stats_copy_queue(d, NULL, &qs, qlen) < 0) |
1da177e4c Linux-2.6.12-rc2 |
1121 1122 1123 1124 1125 1126 |
return -1; return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats)); } static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, |
87990467d [HTB]: Lindent |
1127 |
struct Qdisc **old) |
1da177e4c Linux-2.6.12-rc2 |
1128 |
{ |
87990467d [HTB]: Lindent |
1129 |
struct htb_class *cl = (struct htb_class *)arg; |
1da177e4c Linux-2.6.12-rc2 |
1130 |
|
5b9a9ccfa net_sched: remove... |
1131 1132 1133 |
if (cl->level) return -EINVAL; if (new == NULL && |
3511c9132 net_sched: remove... |
1134 |
(new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, |
5b9a9ccfa net_sched: remove... |
1135 1136 |
cl->common.classid)) == NULL) return -ENOBUFS; |
86a7996cc net_sched: introd... |
1137 |
*old = qdisc_replace(sch, new, &cl->un.leaf.q); |
5b9a9ccfa net_sched: remove... |
1138 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1139 |
} |
87990467d [HTB]: Lindent |
1140 |
static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg) |
1da177e4c Linux-2.6.12-rc2 |
1141 |
{ |
87990467d [HTB]: Lindent |
1142 |
struct htb_class *cl = (struct htb_class *)arg; |
5b9a9ccfa net_sched: remove... |
1143 |
return !cl->level ? cl->un.leaf.q : NULL; |
1da177e4c Linux-2.6.12-rc2 |
1144 |
} |
256d61b87 [NET_SCHED]: Fix ... |
1145 1146 1147 |
static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg) { struct htb_class *cl = (struct htb_class *)arg; |
959466588 net_sched: call q... |
1148 |
htb_deactivate(qdisc_priv(sch), cl); |
256d61b87 [NET_SCHED]: Fix ... |
1149 |
} |
160d5e10f [NET_SCHED] sch_h... |
1150 1151 1152 1153 1154 |
static inline int htb_parent_last_child(struct htb_class *cl) { if (!cl->parent) /* the root class */ return 0; |
420775993 net-sched: sch_ht... |
1155 |
if (cl->parent->children > 1) |
160d5e10f [NET_SCHED] sch_h... |
1156 1157 |
/* not the last child */ return 0; |
160d5e10f [NET_SCHED] sch_h... |
1158 1159 |
return 1; } |
3ba08b00e sch_htb: remove f... |
1160 1161 |
static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl, struct Qdisc *new_q) |
160d5e10f [NET_SCHED] sch_h... |
1162 1163 |
{ struct htb_class *parent = cl->parent; |
547b792ca net: convert BUG_... |
1164 |
WARN_ON(cl->level || !cl->un.leaf.q || cl->prio_activity); |
160d5e10f [NET_SCHED] sch_h... |
1165 |
|
3ba08b00e sch_htb: remove f... |
1166 |
if (parent->cmode != HTB_CAN_SEND) |
c9364636d htb: refactor str... |
1167 1168 |
htb_safe_rb_erase(&parent->pq_node, &q->hlevel[parent->level].wait_pq); |
3ba08b00e sch_htb: remove f... |
1169 |
|
160d5e10f [NET_SCHED] sch_h... |
1170 1171 1172 1173 |
parent->level = 0; memset(&parent->un.inner, 0, sizeof(parent->un.inner)); INIT_LIST_HEAD(&parent->un.leaf.drop_list); parent->un.leaf.q = new_q ? new_q : &noop_qdisc; |
160d5e10f [NET_SCHED] sch_h... |
1174 1175 |
parent->tokens = parent->buffer; parent->ctokens = parent->cbuffer; |
d2de875c6 net: use ktime_ge... |
1176 |
parent->t_c = ktime_get_ns(); |
160d5e10f [NET_SCHED] sch_h... |
1177 1178 |
parent->cmode = HTB_CAN_SEND; } |
87990467d [HTB]: Lindent |
1179 |
static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) |
1da177e4c Linux-2.6.12-rc2 |
1180 |
{ |
1da177e4c Linux-2.6.12-rc2 |
1181 |
if (!cl->level) { |
547b792ca net: convert BUG_... |
1182 |
WARN_ON(!cl->un.leaf.q); |
1da177e4c Linux-2.6.12-rc2 |
1183 1184 |
qdisc_destroy(cl->un.leaf.q); } |
1c0d32fde net_sched: gen_es... |
1185 |
gen_kill_estimator(&cl->rate_est); |
6529eaba3 net: sched: intro... |
1186 |
tcf_block_put(cl->block); |
1da177e4c Linux-2.6.12-rc2 |
1187 1188 |
kfree(cl); } |
87990467d [HTB]: Lindent |
1189 |
static void htb_destroy(struct Qdisc *sch) |
1da177e4c Linux-2.6.12-rc2 |
1190 1191 |
{ struct htb_sched *q = qdisc_priv(sch); |
b67bfe0d4 hlist: drop the n... |
1192 |
struct hlist_node *next; |
fbd8f1379 net-sched: sch_ht... |
1193 1194 |
struct htb_class *cl; unsigned int i; |
1da177e4c Linux-2.6.12-rc2 |
1195 |
|
1224736d9 pkt_sched: sch_ht... |
1196 |
cancel_work_sync(&q->work); |
fb983d457 [NET_SCHED]: sch_... |
1197 |
qdisc_watchdog_cancel(&q->watchdog); |
1da177e4c Linux-2.6.12-rc2 |
1198 |
/* This line used to be after htb_destroy_class call below |
cc7ec456f net_sched: cleanups |
1199 1200 1201 1202 |
* and surprisingly it worked in 2.4. But it must precede it * because filter need its target class alive to be able to call * unbind_filter on it (without Oops). */ |
6529eaba3 net: sched: intro... |
1203 |
tcf_block_put(q->block); |
87990467d [HTB]: Lindent |
1204 |
|
f4c1f3e0c net-sched: sch_ht... |
1205 |
for (i = 0; i < q->clhash.hashsize; i++) { |
898904226 net_sched: reset ... |
1206 |
hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode) { |
6529eaba3 net: sched: intro... |
1207 |
tcf_block_put(cl->block); |
898904226 net_sched: reset ... |
1208 1209 |
cl->block = NULL; } |
fbd8f1379 net-sched: sch_ht... |
1210 |
} |
f4c1f3e0c net-sched: sch_ht... |
1211 |
for (i = 0; i < q->clhash.hashsize; i++) { |
b67bfe0d4 hlist: drop the n... |
1212 |
hlist_for_each_entry_safe(cl, next, &q->clhash.hash[i], |
f4c1f3e0c net-sched: sch_ht... |
1213 |
common.hnode) |
fbd8f1379 net-sched: sch_ht... |
1214 1215 |
htb_destroy_class(sch, cl); } |
f4c1f3e0c net-sched: sch_ht... |
1216 |
qdisc_class_hash_destroy(&q->clhash); |
a5a9f5346 net_sched: sch_ht... |
1217 |
__qdisc_reset_queue(&q->direct_queue); |
1da177e4c Linux-2.6.12-rc2 |
1218 1219 1220 1221 1222 |
} static int htb_delete(struct Qdisc *sch, unsigned long arg) { struct htb_sched *q = qdisc_priv(sch); |
87990467d [HTB]: Lindent |
1223 |
struct htb_class *cl = (struct htb_class *)arg; |
160d5e10f [NET_SCHED] sch_h... |
1224 1225 |
struct Qdisc *new_q = NULL; int last_child = 0; |
1da177e4c Linux-2.6.12-rc2 |
1226 |
|
a071d2724 sch_htb: use /* c... |
1227 1228 1229 1230 |
/* TODO: why don't allow to delete subtree ? references ? does * tc subsys guarantee us that in htb_destroy it holds no class * refs so that we can remove children safely there ? */ |
420775993 net-sched: sch_ht... |
1231 |
if (cl->children || cl->filter_cnt) |
1da177e4c Linux-2.6.12-rc2 |
1232 |
return -EBUSY; |
87990467d [HTB]: Lindent |
1233 |
|
160d5e10f [NET_SCHED] sch_h... |
1234 |
if (!cl->level && htb_parent_last_child(cl)) { |
3511c9132 net_sched: remove... |
1235 |
new_q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, |
bb949fbd1 netdev: Create ne... |
1236 |
cl->parent->common.classid); |
160d5e10f [NET_SCHED] sch_h... |
1237 1238 |
last_child = 1; } |
1da177e4c Linux-2.6.12-rc2 |
1239 |
sch_tree_lock(sch); |
87990467d [HTB]: Lindent |
1240 |
|
814a175e7 [NET_SCHED]: sch_... |
1241 |
if (!cl->level) { |
2ccccf5fb net_sched: update... |
1242 1243 |
unsigned int qlen = cl->un.leaf.q->q.qlen; unsigned int backlog = cl->un.leaf.q->qstats.backlog; |
814a175e7 [NET_SCHED]: sch_... |
1244 |
qdisc_reset(cl->un.leaf.q); |
2ccccf5fb net_sched: update... |
1245 |
qdisc_tree_reduce_backlog(cl->un.leaf.q, qlen, backlog); |
814a175e7 [NET_SCHED]: sch_... |
1246 |
} |
f4c1f3e0c net-sched: sch_ht... |
1247 1248 |
/* delete from hash and active; remainder in destroy_class */ qdisc_class_hash_remove(&q->clhash, &cl->common); |
26b284de5 pkt_sched: Fix oo... |
1249 1250 |
if (cl->parent) cl->parent->children--; |
c38c83cb7 [NET_SCHED]: sch_... |
1251 |
|
1da177e4c Linux-2.6.12-rc2 |
1252 |
if (cl->prio_activity) |
87990467d [HTB]: Lindent |
1253 |
htb_deactivate(q, cl); |
1da177e4c Linux-2.6.12-rc2 |
1254 |
|
fbd8f1379 net-sched: sch_ht... |
1255 |
if (cl->cmode != HTB_CAN_SEND) |
c9364636d htb: refactor str... |
1256 1257 |
htb_safe_rb_erase(&cl->pq_node, &q->hlevel[cl->level].wait_pq); |
fbd8f1379 net-sched: sch_ht... |
1258 |
|
160d5e10f [NET_SCHED] sch_h... |
1259 |
if (last_child) |
3ba08b00e sch_htb: remove f... |
1260 |
htb_parent_to_leaf(q, cl, new_q); |
160d5e10f [NET_SCHED] sch_h... |
1261 |
|
1da177e4c Linux-2.6.12-rc2 |
1262 |
sch_tree_unlock(sch); |
1da177e4c Linux-2.6.12-rc2 |
1263 |
|
143976ce9 net_sched: remove... |
1264 1265 |
htb_destroy_class(sch, cl); return 0; |
1da177e4c Linux-2.6.12-rc2 |
1266 |
} |
87990467d [HTB]: Lindent |
1267 |
static int htb_change_class(struct Qdisc *sch, u32 classid, |
1e90474c3 [NET_SCHED]: Conv... |
1268 |
u32 parentid, struct nlattr **tca, |
87990467d [HTB]: Lindent |
1269 |
unsigned long *arg) |
1da177e4c Linux-2.6.12-rc2 |
1270 1271 1272 |
{ int err = -EINVAL; struct htb_sched *q = qdisc_priv(sch); |
87990467d [HTB]: Lindent |
1273 |
struct htb_class *cl = (struct htb_class *)*arg, *parent; |
1e90474c3 [NET_SCHED]: Conv... |
1274 |
struct nlattr *opt = tca[TCA_OPTIONS]; |
6906f4ed6 htb: add HTB_DIRE... |
1275 |
struct nlattr *tb[TCA_HTB_MAX + 1]; |
1da177e4c Linux-2.6.12-rc2 |
1276 |
struct tc_htb_opt *hopt; |
df62cdf34 net_sched: htb: s... |
1277 |
u64 rate64, ceil64; |
1da177e4c Linux-2.6.12-rc2 |
1278 1279 |
/* extract all subattrs from opt attr */ |
cee63723b [NET_SCHED]: Prop... |
1280 1281 |
if (!opt) goto failure; |
fceb6435e netlink: pass ext... |
1282 |
err = nla_parse_nested(tb, TCA_HTB_MAX, opt, htb_policy, NULL); |
cee63723b [NET_SCHED]: Prop... |
1283 1284 1285 1286 |
if (err < 0) goto failure; err = -EINVAL; |
27a3421e4 [NET_SCHED]: Use ... |
1287 |
if (tb[TCA_HTB_PARMS] == NULL) |
1da177e4c Linux-2.6.12-rc2 |
1288 |
goto failure; |
1da177e4c Linux-2.6.12-rc2 |
1289 |
|
87990467d [HTB]: Lindent |
1290 |
parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch); |
1e90474c3 [NET_SCHED]: Conv... |
1291 |
hopt = nla_data(tb[TCA_HTB_PARMS]); |
196d97f6b htb: fix two bugs |
1292 |
if (!hopt->rate.rate || !hopt->ceil.rate) |
87990467d [HTB]: Lindent |
1293 |
goto failure; |
1da177e4c Linux-2.6.12-rc2 |
1294 |
|
8a8e3d84b net_sched: restor... |
1295 |
/* Keeping backward compatible with rate_table based iproute2 tc */ |
6b1dd8560 sch_htb: remove u... |
1296 1297 1298 1299 1300 |
if (hopt->rate.linklayer == TC_LINKLAYER_UNAWARE) qdisc_put_rtab(qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB])); if (hopt->ceil.linklayer == TC_LINKLAYER_UNAWARE) qdisc_put_rtab(qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB])); |
8a8e3d84b net_sched: restor... |
1301 |
|
87990467d [HTB]: Lindent |
1302 |
if (!cl) { /* new class */ |
1da177e4c Linux-2.6.12-rc2 |
1303 |
struct Qdisc *new_q; |
3696f625e [HTB]: rbtree cle... |
1304 |
int prio; |
ee39e10c2 [NET_SCHED]: sch_... |
1305 |
struct { |
1e90474c3 [NET_SCHED]: Conv... |
1306 |
struct nlattr nla; |
ee39e10c2 [NET_SCHED]: sch_... |
1307 1308 |
struct gnet_estimator opt; } est = { |
1e90474c3 [NET_SCHED]: Conv... |
1309 1310 1311 |
.nla = { .nla_len = nla_attr_size(sizeof(est.opt)), .nla_type = TCA_RATE, |
ee39e10c2 [NET_SCHED]: sch_... |
1312 1313 1314 1315 1316 1317 1318 |
}, .opt = { /* 4s interval, 16s averaging constant */ .interval = 2, .ewma_log = 2, }, }; |
3696f625e [HTB]: rbtree cle... |
1319 |
|
1da177e4c Linux-2.6.12-rc2 |
1320 |
/* check for valid classid */ |
f64f9e719 net: Move && and ... |
1321 1322 |
if (!classid || TC_H_MAJ(classid ^ sch->handle) || htb_find(classid, sch)) |
1da177e4c Linux-2.6.12-rc2 |
1323 1324 1325 1326 |
goto failure; /* check maximal depth */ if (parent && parent->parent && parent->parent->level < 2) { |
cc7ec456f net_sched: cleanups |
1327 1328 |
pr_err("htb: tree is too deep "); |
1da177e4c Linux-2.6.12-rc2 |
1329 1330 1331 |
goto failure; } err = -ENOBUFS; |
cc7ec456f net_sched: cleanups |
1332 1333 |
cl = kzalloc(sizeof(*cl), GFP_KERNEL); if (!cl) |
1da177e4c Linux-2.6.12-rc2 |
1334 |
goto failure; |
87990467d [HTB]: Lindent |
1335 |
|
6529eaba3 net: sched: intro... |
1336 1337 1338 1339 1340 |
err = tcf_block_get(&cl->block, &cl->filter_list); if (err) { kfree(cl); goto failure; } |
64153ce0a net_sched: htb: d... |
1341 |
if (htb_rate_est || tca[TCA_RATE]) { |
22e0f8b93 net: sched: make ... |
1342 1343 |
err = gen_new_estimator(&cl->bstats, NULL, &cl->rate_est, |
edb09eb17 net: sched: do no... |
1344 1345 |
NULL, qdisc_root_sleeping_running(sch), |
64153ce0a net_sched: htb: d... |
1346 1347 |
tca[TCA_RATE] ? : &est.nla); if (err) { |
6529eaba3 net: sched: intro... |
1348 |
tcf_block_put(cl->block); |
64153ce0a net_sched: htb: d... |
1349 1350 1351 |
kfree(cl); goto failure; } |
71bcb09a5 tc: check for err... |
1352 |
} |
420775993 net-sched: sch_ht... |
1353 |
cl->children = 0; |
1da177e4c Linux-2.6.12-rc2 |
1354 |
INIT_LIST_HEAD(&cl->un.leaf.drop_list); |
3696f625e [HTB]: rbtree cle... |
1355 1356 1357 1358 |
RB_CLEAR_NODE(&cl->pq_node); for (prio = 0; prio < TC_HTB_NUMPRIO; prio++) RB_CLEAR_NODE(&cl->node[prio]); |
1da177e4c Linux-2.6.12-rc2 |
1359 1360 |
/* create leaf qdisc early because it uses kmalloc(GFP_KERNEL) |
cc7ec456f net_sched: cleanups |
1361 1362 1363 |
* so that can't be used inside of sch_tree_lock * -- thanks to Karlis Peisenieks */ |
3511c9132 net_sched: remove... |
1364 |
new_q = qdisc_create_dflt(sch->dev_queue, |
bb949fbd1 netdev: Create ne... |
1365 |
&pfifo_qdisc_ops, classid); |
1da177e4c Linux-2.6.12-rc2 |
1366 1367 |
sch_tree_lock(sch); if (parent && !parent->level) { |
256d61b87 [NET_SCHED]: Fix ... |
1368 |
unsigned int qlen = parent->un.leaf.q->q.qlen; |
2ccccf5fb net_sched: update... |
1369 |
unsigned int backlog = parent->un.leaf.q->qstats.backlog; |
256d61b87 [NET_SCHED]: Fix ... |
1370 |
|
1da177e4c Linux-2.6.12-rc2 |
1371 |
/* turn parent into inner node */ |
256d61b87 [NET_SCHED]: Fix ... |
1372 |
qdisc_reset(parent->un.leaf.q); |
2ccccf5fb net_sched: update... |
1373 |
qdisc_tree_reduce_backlog(parent->un.leaf.q, qlen, backlog); |
87990467d [HTB]: Lindent |
1374 1375 1376 |
qdisc_destroy(parent->un.leaf.q); if (parent->prio_activity) htb_deactivate(q, parent); |
1da177e4c Linux-2.6.12-rc2 |
1377 1378 1379 |
/* remove from evt list because of level change */ if (parent->cmode != HTB_CAN_SEND) { |
c9364636d htb: refactor str... |
1380 |
htb_safe_rb_erase(&parent->pq_node, &q->hlevel[0].wait_pq); |
1da177e4c Linux-2.6.12-rc2 |
1381 1382 1383 |
parent->cmode = HTB_CAN_SEND; } parent->level = (parent->parent ? parent->parent->level |
87990467d [HTB]: Lindent |
1384 1385 |
: TC_HTB_MAXDEPTH) - 1; memset(&parent->un.inner, 0, sizeof(parent->un.inner)); |
1da177e4c Linux-2.6.12-rc2 |
1386 1387 1388 |
} /* leaf (we) needs elementary qdisc */ cl->un.leaf.q = new_q ? new_q : &noop_qdisc; |
f4c1f3e0c net-sched: sch_ht... |
1389 |
cl->common.classid = classid; |
87990467d [HTB]: Lindent |
1390 |
cl->parent = parent; |
1da177e4c Linux-2.6.12-rc2 |
1391 1392 |
/* set class to be in HTB_CAN_SEND state */ |
b9a7afdef htb: initialize c... |
1393 1394 |
cl->tokens = PSCHED_TICKS2NS(hopt->buffer); cl->ctokens = PSCHED_TICKS2NS(hopt->cbuffer); |
5343a7f8b net_sched: htb: d... |
1395 |
cl->mbuffer = 60ULL * NSEC_PER_SEC; /* 1min */ |
d2de875c6 net: use ktime_ge... |
1396 |
cl->t_c = ktime_get_ns(); |
1da177e4c Linux-2.6.12-rc2 |
1397 1398 1399 |
cl->cmode = HTB_CAN_SEND; /* attach to the hash list and parent's family */ |
f4c1f3e0c net-sched: sch_ht... |
1400 |
qdisc_class_hash_insert(&q->clhash, &cl->common); |
420775993 net-sched: sch_ht... |
1401 1402 |
if (parent) parent->children++; |
49b499718 net: sched: make ... |
1403 1404 |
if (cl->un.leaf.q != &noop_qdisc) qdisc_hash_add(cl->un.leaf.q, true); |
ee39e10c2 [NET_SCHED]: sch_... |
1405 |
} else { |
71bcb09a5 tc: check for err... |
1406 |
if (tca[TCA_RATE]) { |
22e0f8b93 net: sched: make ... |
1407 1408 |
err = gen_replace_estimator(&cl->bstats, NULL, &cl->rate_est, |
edb09eb17 net: sched: do no... |
1409 1410 |
NULL, qdisc_root_sleeping_running(sch), |
71bcb09a5 tc: check for err... |
1411 1412 1413 1414 |
tca[TCA_RATE]); if (err) return err; } |
87990467d [HTB]: Lindent |
1415 |
sch_tree_lock(sch); |
ee39e10c2 [NET_SCHED]: sch_... |
1416 |
} |
1da177e4c Linux-2.6.12-rc2 |
1417 |
|
1598f7cb4 net: sched: htb: ... |
1418 1419 1420 1421 1422 1423 |
rate64 = tb[TCA_HTB_RATE64] ? nla_get_u64(tb[TCA_HTB_RATE64]) : 0; ceil64 = tb[TCA_HTB_CEIL64] ? nla_get_u64(tb[TCA_HTB_CEIL64]) : 0; psched_ratecfg_precompute(&cl->rate, &hopt->rate, rate64); psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, ceil64); |
1da177e4c Linux-2.6.12-rc2 |
1424 |
/* it used to be a nasty bug here, we have to check that node |
cc7ec456f net_sched: cleanups |
1425 1426 |
* is really leaf before changing cl->un.leaf ! */ |
1da177e4c Linux-2.6.12-rc2 |
1427 |
if (!cl->level) { |
1598f7cb4 net: sched: htb: ... |
1428 1429 1430 1431 |
u64 quantum = cl->rate.rate_bytes_ps; do_div(quantum, q->rate2quantum); cl->quantum = min_t(u64, quantum, INT_MAX); |
c19f7a34f pkt_sched: sch_ht... |
1432 |
if (!hopt->quantum && cl->quantum < 1000) { |
c17988a90 net_sched: replac... |
1433 1434 1435 |
pr_warn("HTB: quantum of class %X is small. Consider r2q change. ", cl->common.classid); |
c19f7a34f pkt_sched: sch_ht... |
1436 |
cl->quantum = 1000; |
1da177e4c Linux-2.6.12-rc2 |
1437 |
} |
c19f7a34f pkt_sched: sch_ht... |
1438 |
if (!hopt->quantum && cl->quantum > 200000) { |
c17988a90 net_sched: replac... |
1439 1440 1441 |
pr_warn("HTB: quantum of class %X is big. Consider r2q change. ", cl->common.classid); |
c19f7a34f pkt_sched: sch_ht... |
1442 |
cl->quantum = 200000; |
1da177e4c Linux-2.6.12-rc2 |
1443 1444 |
} if (hopt->quantum) |
c19f7a34f pkt_sched: sch_ht... |
1445 1446 1447 |
cl->quantum = hopt->quantum; if ((cl->prio = hopt->prio) >= TC_HTB_NUMPRIO) cl->prio = TC_HTB_NUMPRIO - 1; |
1da177e4c Linux-2.6.12-rc2 |
1448 |
} |
324f5aa52 htb: use PSCHED_T... |
1449 |
cl->buffer = PSCHED_TICKS2NS(hopt->buffer); |
f3ad857e3 net_sched: htb: f... |
1450 |
cl->cbuffer = PSCHED_TICKS2NS(hopt->cbuffer); |
56b765b79 htb: improved acc... |
1451 |
|
1da177e4c Linux-2.6.12-rc2 |
1452 |
sch_tree_unlock(sch); |
f4c1f3e0c net-sched: sch_ht... |
1453 |
qdisc_class_hash_grow(sch, &q->clhash); |
1da177e4c Linux-2.6.12-rc2 |
1454 1455 1456 1457 |
*arg = (unsigned long)cl; return 0; failure: |
1da177e4c Linux-2.6.12-rc2 |
1458 1459 |
return err; } |
6529eaba3 net: sched: intro... |
1460 |
static struct tcf_block *htb_tcf_block(struct Qdisc *sch, unsigned long arg) |
1da177e4c Linux-2.6.12-rc2 |
1461 1462 1463 |
{ struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl = (struct htb_class *)arg; |
3bf72957d [HTB]: Remove bro... |
1464 |
|
6529eaba3 net: sched: intro... |
1465 |
return cl ? cl->block : q->block; |
1da177e4c Linux-2.6.12-rc2 |
1466 1467 1468 |
} static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent, |
87990467d [HTB]: Lindent |
1469 |
u32 classid) |
1da177e4c Linux-2.6.12-rc2 |
1470 |
{ |
87990467d [HTB]: Lindent |
1471 |
struct htb_class *cl = htb_find(classid, sch); |
3bf72957d [HTB]: Remove bro... |
1472 |
|
1da177e4c Linux-2.6.12-rc2 |
1473 |
/*if (cl && !cl->level) return 0; |
cc7ec456f net_sched: cleanups |
1474 1475 1476 1477 1478 1479 1480 |
* The line above used to be there to prevent attaching filters to * leaves. But at least tc_index filter uses this just to get class * for other reasons so that we have to allow for it. * ---- * 19.6.2002 As Werner explained it is ok - bind filter is just * another way to "lock" the class - unlike "get" this lock can * be broken by class during destroy IIUC. |
1da177e4c Linux-2.6.12-rc2 |
1481 |
*/ |
87990467d [HTB]: Lindent |
1482 1483 |
if (cl) cl->filter_cnt++; |
1da177e4c Linux-2.6.12-rc2 |
1484 1485 1486 1487 1488 |
return (unsigned long)cl; } static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg) { |
1da177e4c Linux-2.6.12-rc2 |
1489 |
struct htb_class *cl = (struct htb_class *)arg; |
3bf72957d [HTB]: Remove bro... |
1490 |
|
87990467d [HTB]: Lindent |
1491 1492 |
if (cl) cl->filter_cnt--; |
1da177e4c Linux-2.6.12-rc2 |
1493 1494 1495 1496 1497 |
} static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg) { struct htb_sched *q = qdisc_priv(sch); |
f4c1f3e0c net-sched: sch_ht... |
1498 |
struct htb_class *cl; |
f4c1f3e0c net-sched: sch_ht... |
1499 |
unsigned int i; |
1da177e4c Linux-2.6.12-rc2 |
1500 1501 1502 |
if (arg->stop) return; |
f4c1f3e0c net-sched: sch_ht... |
1503 |
for (i = 0; i < q->clhash.hashsize; i++) { |
b67bfe0d4 hlist: drop the n... |
1504 |
hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode) { |
1da177e4c Linux-2.6.12-rc2 |
1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 |
if (arg->count < arg->skip) { arg->count++; continue; } if (arg->fn(sch, (unsigned long)cl, arg) < 0) { arg->stop = 1; return; } arg->count++; } } } |
20fea08b5 [NET]: Move Qdisc... |
1517 |
static const struct Qdisc_class_ops htb_class_ops = { |
1da177e4c Linux-2.6.12-rc2 |
1518 1519 |
.graft = htb_graft, .leaf = htb_leaf, |
256d61b87 [NET_SCHED]: Fix ... |
1520 |
.qlen_notify = htb_qlen_notify, |
143976ce9 net_sched: remove... |
1521 |
.find = htb_search, |
1da177e4c Linux-2.6.12-rc2 |
1522 1523 1524 |
.change = htb_change_class, .delete = htb_delete, .walk = htb_walk, |
6529eaba3 net: sched: intro... |
1525 |
.tcf_block = htb_tcf_block, |
1da177e4c Linux-2.6.12-rc2 |
1526 1527 1528 1529 1530 |
.bind_tcf = htb_bind_filter, .unbind_tcf = htb_unbind_filter, .dump = htb_dump_class, .dump_stats = htb_dump_class_stats, }; |
20fea08b5 [NET]: Move Qdisc... |
1531 |
static struct Qdisc_ops htb_qdisc_ops __read_mostly = { |
1da177e4c Linux-2.6.12-rc2 |
1532 1533 1534 1535 1536 |
.cl_ops = &htb_class_ops, .id = "htb", .priv_size = sizeof(struct htb_sched), .enqueue = htb_enqueue, .dequeue = htb_dequeue, |
77be155cb pkt_sched: Add pe... |
1537 |
.peek = qdisc_peek_dequeued, |
1da177e4c Linux-2.6.12-rc2 |
1538 1539 1540 |
.init = htb_init, .reset = htb_reset, .destroy = htb_destroy, |
1da177e4c Linux-2.6.12-rc2 |
1541 1542 1543 1544 1545 1546 |
.dump = htb_dump, .owner = THIS_MODULE, }; static int __init htb_module_init(void) { |
87990467d [HTB]: Lindent |
1547 |
return register_qdisc(&htb_qdisc_ops); |
1da177e4c Linux-2.6.12-rc2 |
1548 |
} |
87990467d [HTB]: Lindent |
1549 |
static void __exit htb_module_exit(void) |
1da177e4c Linux-2.6.12-rc2 |
1550 |
{ |
87990467d [HTB]: Lindent |
1551 |
unregister_qdisc(&htb_qdisc_ops); |
1da177e4c Linux-2.6.12-rc2 |
1552 |
} |
87990467d [HTB]: Lindent |
1553 |
|
1da177e4c Linux-2.6.12-rc2 |
1554 1555 1556 |
module_init(htb_module_init) module_exit(htb_module_exit) MODULE_LICENSE("GPL"); |