Blame view

net/sched/sch_htb.c 42.4 KB
87990467d   Stephen Hemminger   [HTB]: Lindent
1
  /*
1da177e4c   Linus Torvalds   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   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
14
   *		Ondrej Kraus, <krauso@barr.cz>
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
27
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  #include <linux/module.h>
47083fc07   Jesper Dangaard Brouer   pkt_sched: Change...
29
  #include <linux/moduleparam.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
  #include <linux/types.h>
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  #include <linux/string.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
  #include <linux/errno.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
  #include <linux/skbuff.h>
  #include <linux/list.h>
  #include <linux/compiler.h>
0ba480538   Patrick McHardy   [NET_SCHED]: Remo...
37
  #include <linux/rbtree.h>
1224736d9   Jarek Poplawski   pkt_sched: sch_ht...
38
  #include <linux/workqueue.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
39
  #include <linux/slab.h>
dc5fc579b   Arnaldo Carvalho de Melo   [NETLINK]: Use nl...
40
  #include <net/netlink.h>
292f1c7ff   Jiri Pirko   sch: make htb_rat...
41
  #include <net/sch_generic.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  #include <net/pkt_sched.h>
cf1facda2   Jiri Pirko   sched: move tcf_p...
43
  #include <net/pkt_cls.h>
1da177e4c   Linus Torvalds   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   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
49
      it allows to assign priority to each class in hierarchy.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
      In fact it is another implementation of Floyd's formal sharing.
  
      Levels:
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
53
      Each class is assigned level. Leaf has ALWAYS level 0 and root
1da177e4c   Linus Torvalds   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   Jesper Dangaard Brouer   pkt_sched: Change...
57
  static int htb_hysteresis __read_mostly = 0; /* whether to use mode hysteresis for speedup */
87990467d   Stephen Hemminger   [HTB]: Lindent
58
  #define HTB_VER 0x30011		/* major must be matched with number suplied by TC as version */
1da177e4c   Linus Torvalds   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   Jesper Dangaard Brouer   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   Eric Dumazet   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   Linus Torvalds   Linux-2.6.12-rc2
69
70
  /* used internaly to keep status of single class */
  enum htb_cmode {
87990467d   Stephen Hemminger   [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   Linus Torvalds   Linux-2.6.12-rc2
74
  };
c9364636d   Eric Dumazet   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   Eric Dumazet   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   Stephen Hemminger   [HTB]: Lindent
92
  struct htb_class {
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
93
  	struct Qdisc_class_common common;
ca4ec90b3   Eric Dumazet   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   stephen hemminger   htb: fix sign ext...
98
  	u32			prio;		/* these two are used only by leaves... */
ca4ec90b3   Eric Dumazet   htb: reorder stru...
99
  	int			quantum;	/* but stored for parent-to-leaf return */
25d8c0d55   John Fastabend   net: rcu-ify tcf_...
100
  	struct tcf_proto __rcu	*filter_list;	/* class attached filters */
6529eaba3   Jiri Pirko   net: sched: intro...
101
  	struct tcf_block	*block;
ca4ec90b3   Eric Dumazet   htb: reorder stru...
102
  	int			filter_cnt;
ca4ec90b3   Eric Dumazet   htb: reorder stru...
103
104
105
106
  
  	int			level;		/* our level (see above) */
  	unsigned int		children;
  	struct htb_class	*parent;	/* parent class */
1c0d32fde   Eric Dumazet   net_sched: gen_es...
107
  	struct net_rate_estimator __rcu *rate_est;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108

ca4ec90b3   Eric Dumazet   htb: reorder stru...
109
110
111
112
  	/*
  	 * Written often fields
  	 */
  	struct gnet_stats_basic_packed bstats;
ca4ec90b3   Eric Dumazet   htb: reorder stru...
113
  	struct tc_htb_xstats	xstats;	/* our special stats */
87990467d   Stephen Hemminger   [HTB]: Lindent
114

ca4ec90b3   Eric Dumazet   htb: reorder stru...
115
116
117
  	/* token bucket parameters */
  	s64			tokens, ctokens;/* current number of tokens */
  	s64			t_c;		/* checkpoint time */
c19f7a34f   Jarek Poplawski   pkt_sched: sch_ht...
118

87990467d   Stephen Hemminger   [HTB]: Lindent
119
120
  	union {
  		struct htb_class_leaf {
87990467d   Stephen Hemminger   [HTB]: Lindent
121
  			struct list_head drop_list;
c9364636d   Eric Dumazet   htb: refactor str...
122
123
  			int		deficit[TC_HTB_MAXDEPTH];
  			struct Qdisc	*q;
87990467d   Stephen Hemminger   [HTB]: Lindent
124
125
  		} leaf;
  		struct htb_class_inner {
c9364636d   Eric Dumazet   htb: refactor str...
126
  			struct htb_prio clprio[TC_HTB_NUMPRIO];
87990467d   Stephen Hemminger   [HTB]: Lindent
127
128
  		} inner;
  	} un;
ca4ec90b3   Eric Dumazet   htb: reorder stru...
129
  	s64			pq_key;
87990467d   Stephen Hemminger   [HTB]: Lindent
130

ca4ec90b3   Eric Dumazet   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   Eric Dumazet   net_sched: sch_ht...
135
136
  
  	unsigned int drops ____cacheline_aligned_in_smp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
  };
c9364636d   Eric Dumazet   htb: refactor str...
138
139
140
141
  struct htb_level {
  	struct rb_root	wait_pq;
  	struct htb_prio hprio[TC_HTB_NUMPRIO];
  };
87990467d   Stephen Hemminger   [HTB]: Lindent
142
  struct htb_sched {
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
143
  	struct Qdisc_class_hash clhash;
c9364636d   Eric Dumazet   htb: refactor str...
144
145
  	int			defcls;		/* class where unclassified flows go to */
  	int			rate2quantum;	/* quant = rate / rate2quantum */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146

c9364636d   Eric Dumazet   htb: refactor str...
147
  	/* filters for qdisc itself */
25d8c0d55   John Fastabend   net: rcu-ify tcf_...
148
  	struct tcf_proto __rcu	*filter_list;
6529eaba3   Jiri Pirko   net: sched: intro...
149
  	struct tcf_block	*block;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150

c9364636d   Eric Dumazet   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   Linus Torvalds   Linux-2.6.12-rc2
155

c9364636d   Eric Dumazet   htb: refactor str...
156
  	/* non shaped skbs; let them go directly thru */
48da34b7a   Florian Westphal   sched: add and us...
157
  	struct qdisc_skb_head	direct_queue;
c9364636d   Eric Dumazet   htb: refactor str...
158
  	long			direct_pkts;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159

c9364636d   Eric Dumazet   htb: refactor str...
160
  	struct qdisc_watchdog	watchdog;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161

c9364636d   Eric Dumazet   htb: refactor str...
162
163
  	s64			now;	/* cached dequeue time */
  	struct list_head	drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164

c9364636d   Eric Dumazet   htb: refactor str...
165
166
  	/* time of nearest event per level (row) */
  	s64			near_ev_cache[TC_HTB_MAXDEPTH];
87990467d   Stephen Hemminger   [HTB]: Lindent
167

c9364636d   Eric Dumazet   htb: refactor str...
168
  	int			row_mask[TC_HTB_MAXDEPTH];
e82181de5   Jarek Poplawski   pkt_sched: sch_ht...
169

c9364636d   Eric Dumazet   htb: refactor str...
170
  	struct htb_level	hlevel[TC_HTB_MAXDEPTH];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  /* find class in global hash table using given handle */
87990467d   Stephen Hemminger   [HTB]: Lindent
173
  static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
  {
  	struct htb_sched *q = qdisc_priv(sch);
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
176
  	struct Qdisc_class_common *clc;
0cef296da   Stephen Hemminger   [HTB]: Use hlist ...
177

f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
178
179
  	clc = qdisc_class_find(&q->clhash, handle);
  	if (clc == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
  		return NULL;
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
181
  	return container_of(clc, struct htb_class, common);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
  }
143976ce9   WANG Cong   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   Linus Torvalds   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   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
195
   * internal fifo (direct). These packets then go directly thru. If we still
25985edce   Lucas De Marchi   Fix common misspe...
196
   * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessful
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
198
   * then finish and return direct queue.
   */
cc7ec456f   Eric Dumazet   net_sched: cleanups
199
  #define HTB_DIRECT ((struct htb_class *)-1L)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200

87990467d   Stephen Hemminger   [HTB]: Lindent
201
202
  static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
  				      int *qerr)
1da177e4c   Linus Torvalds   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   Eric Dumazet   net_sched: cleanups
211
212
213
  	 * note that nfmark can be used too by attaching filter fw with no
  	 * rules in it
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  	if (skb->priority == sch->handle)
87990467d   Stephen Hemminger   [HTB]: Lindent
215
  		return HTB_DIRECT;	/* X:0 (direct flow) selected */
cc7ec456f   Eric Dumazet   net_sched: cleanups
216
  	cl = htb_find(skb->priority, sch);
29824310c   Harry Mason   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   John Fastabend   net: rcu-ify tcf_...
221
  		tcf = rcu_dereference_bh(cl->filter_list);
29824310c   Harry Mason   sch_htb: let skb-...
222
  	} else {
25d8c0d55   John Fastabend   net: rcu-ify tcf_...
223
  		tcf = rcu_dereference_bh(q->filter_list);
29824310c   Harry Mason   sch_htb: let skb-...
224
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225

c27f339af   Jarek Poplawski   net_sched: Add qd...
226
  	*qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
87d83093b   Jiri Pirko   net: sched: move ...
227
  	while (tcf && (result = tcf_classify(skb, tcf, &res, false)) >= 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
230
  #ifdef CONFIG_NET_CLS_ACT
  		switch (result) {
  		case TC_ACT_QUEUED:
87990467d   Stephen Hemminger   [HTB]: Lindent
231
  		case TC_ACT_STOLEN:
e25ea21ff   Jiri Pirko   net: sched: intro...
232
  		case TC_ACT_TRAP:
378a2f090   Jarek Poplawski   net_sched: Add qd...
233
  			*qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
236
  		case TC_ACT_SHOT:
  			return NULL;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
  #endif
cc7ec456f   Eric Dumazet   net_sched: cleanups
238
239
  		cl = (void *)res.class;
  		if (!cl) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
  			if (res.classid == sch->handle)
87990467d   Stephen Hemminger   [HTB]: Lindent
241
  				return HTB_DIRECT;	/* X:0 (direct flow) */
cc7ec456f   Eric Dumazet   net_sched: cleanups
242
243
  			cl = htb_find(res.classid, sch);
  			if (!cl)
87990467d   Stephen Hemminger   [HTB]: Lindent
244
  				break;	/* filter selected invalid classid */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
  		}
  		if (!cl->level)
87990467d   Stephen Hemminger   [HTB]: Lindent
247
  			return cl;	/* we hit leaf; return it */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
249
  
  		/* we have got inner class; apply inner filter chain */
25d8c0d55   John Fastabend   net: rcu-ify tcf_...
250
  		tcf = rcu_dereference_bh(cl->filter_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
252
  	}
  	/* classification failed; try to use default class */
87990467d   Stephen Hemminger   [HTB]: Lindent
253
  	cl = htb_find(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
  	if (!cl || cl->level)
87990467d   Stephen Hemminger   [HTB]: Lindent
255
  		return HTB_DIRECT;	/* bad default .. this is safe bet */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
257
  	return cl;
  }
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
264
265
  static void htb_add_to_id_tree(struct rb_root *root,
  			       struct htb_class *cl, int prio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
  {
  	struct rb_node **p = &root->rb_node, *parent = NULL;
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
268

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  	while (*p) {
87990467d   Stephen Hemminger   [HTB]: Lindent
270
271
  		struct htb_class *c;
  		parent = *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
  		c = rb_entry(parent, struct htb_class, node[prio]);
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
273

f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
274
  		if (cl->common.classid > c->common.classid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
  			p = &parent->rb_right;
87990467d   Stephen Hemminger   [HTB]: Lindent
276
  		else
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
290
  static void htb_add_to_wait_tree(struct htb_sched *q,
56b765b79   Vimalkumar   htb: improved acc...
291
  				 struct htb_class *cl, s64 delay)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
  {
c9364636d   Eric Dumazet   htb: refactor str...
293
  	struct rb_node **p = &q->hlevel[cl->level].wait_pq.rb_node, *parent = NULL;
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
294

fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
295
296
  	cl->pq_key = q->now + delay;
  	if (cl->pq_key == q->now)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
298
299
  		cl->pq_key++;
  
  	/* update the nearest event cache */
fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
300
  	if (q->near_ev_cache[cl->level] > cl->pq_key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
  		q->near_ev_cache[cl->level] = cl->pq_key;
87990467d   Stephen Hemminger   [HTB]: Lindent
302

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
  	while (*p) {
87990467d   Stephen Hemminger   [HTB]: Lindent
304
305
  		struct htb_class *c;
  		parent = *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
  		c = rb_entry(parent, struct htb_class, pq_node);
fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
307
  		if (cl->pq_key >= c->pq_key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
  			p = &parent->rb_right;
87990467d   Stephen Hemminger   [HTB]: Lindent
309
  		else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
311
312
  			p = &parent->rb_left;
  	}
  	rb_link_node(&cl->pq_node, parent, p);
c9364636d   Eric Dumazet   htb: refactor str...
313
  	rb_insert_color(&cl->pq_node, &q->hlevel[cl->level].wait_pq);
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: rbtree cle...
322
  static inline void htb_next_rb_node(struct rb_node **n)
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
333
334
  static inline void htb_add_class_to_row(struct htb_sched *q,
  					struct htb_class *cl, int mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
  {
1da177e4c   Linus Torvalds   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   Eric Dumazet   htb: refactor str...
340
  		htb_add_to_id_tree(&q->hlevel[cl->level].hprio[prio].row, cl, prio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
  	}
  }
3696f625e   Stephen Hemminger   [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   Ismail Donmez   [NET_SCHED]: Reve...
346
  	if (RB_EMPTY_NODE(rb)) {
3696f625e   Stephen Hemminger   [HTB]: rbtree cle...
347
348
349
350
351
352
  		WARN_ON(1);
  	} else {
  		rb_erase(rb, root);
  		RB_CLEAR_NODE(rb);
  	}
  }
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
359
360
  static inline void htb_remove_class_from_row(struct htb_sched *q,
  						 struct htb_class *cl, int mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
362
  {
  	int m = 0;
c9364636d   Eric Dumazet   htb: refactor str...
363
  	struct htb_level *hlevel = &q->hlevel[cl->level];
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
364

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
366
  	while (mask) {
  		int prio = ffz(~mask);
c9364636d   Eric Dumazet   htb: refactor str...
367
  		struct htb_prio *hprio = &hlevel->hprio[prio];
3696f625e   Stephen Hemminger   [HTB]: rbtree cle...
368

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
  		mask &= ~(1 << prio);
c9364636d   Eric Dumazet   htb: refactor str...
370
371
  		if (hprio->ptr == cl->node + prio)
  			htb_next_rb_node(&hprio->ptr);
3696f625e   Stephen Hemminger   [HTB]: rbtree cle...
372

c9364636d   Eric Dumazet   htb: refactor str...
373
374
  		htb_safe_rb_erase(cl->node + prio, &hprio->row);
  		if (!hprio->row.rb_node)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
  			m |= 1 << prio;
  	}
1da177e4c   Linus Torvalds   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   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
384
   * for priorities it is participating on. cl->cmode must be new
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
386
   * (activated) mode. It does nothing if cl->prio_activity == 0.
   */
87990467d   Stephen Hemminger   [HTB]: Lindent
387
  static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
389
  {
  	struct htb_class *p = cl->parent;
87990467d   Stephen Hemminger   [HTB]: Lindent
390
  	long m, mask = cl->prio_activity;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
392
  
  	while (cl->cmode == HTB_MAY_BORROW && p && mask) {
87990467d   Stephen Hemminger   [HTB]: Lindent
393
394
  		m = mask;
  		while (m) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
  			int prio = ffz(~m);
  			m &= ~(1 << prio);
87990467d   Stephen Hemminger   [HTB]: Lindent
397

c9364636d   Eric Dumazet   htb: refactor str...
398
  			if (p->un.inner.clprio[prio].feed.rb_node)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
  				/* parent already has its feed in use so that
cc7ec456f   Eric Dumazet   net_sched: cleanups
400
401
  				 * reset bit in mask as parent is already ok
  				 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
  				mask &= ~(1 << prio);
87990467d   Stephen Hemminger   [HTB]: Lindent
403

c9364636d   Eric Dumazet   htb: refactor str...
404
  			htb_add_to_id_tree(&p->un.inner.clprio[prio].feed, cl, prio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
  		p->prio_activity |= mask;
87990467d   Stephen Hemminger   [HTB]: Lindent
407
408
  		cl = p;
  		p = cl->parent;
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
409

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
  	}
  	if (cl->cmode == HTB_CAN_SEND && mask)
87990467d   Stephen Hemminger   [HTB]: Lindent
412
  		htb_add_class_to_row(q, cl, mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
415
416
417
  }
  
  /**
   * htb_deactivate_prios - remove class from feed chain
   *
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
418
   * cl->cmode must represent old mode (before deactivation). It does
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
425
  	long m, mask = cl->prio_activity;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
  
  	while (cl->cmode == HTB_MAY_BORROW && p && mask) {
87990467d   Stephen Hemminger   [HTB]: Lindent
428
429
  		m = mask;
  		mask = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
431
432
  		while (m) {
  			int prio = ffz(~m);
  			m &= ~(1 << prio);
87990467d   Stephen Hemminger   [HTB]: Lindent
433

c9364636d   Eric Dumazet   htb: refactor str...
434
  			if (p->un.inner.clprio[prio].ptr == cl->node + prio) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
  				/* we are removing child which is pointed to from
cc7ec456f   Eric Dumazet   net_sched: cleanups
436
437
438
  				 * parent feed - forget the pointer but remember
  				 * classid
  				 */
c9364636d   Eric Dumazet   htb: refactor str...
439
440
  				p->un.inner.clprio[prio].last_ptr_id = cl->common.classid;
  				p->un.inner.clprio[prio].ptr = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  			}
87990467d   Stephen Hemminger   [HTB]: Lindent
442

c9364636d   Eric Dumazet   htb: refactor str...
443
444
  			htb_safe_rb_erase(cl->node + prio,
  					  &p->un.inner.clprio[prio].feed);
87990467d   Stephen Hemminger   [HTB]: Lindent
445

c9364636d   Eric Dumazet   htb: refactor str...
446
  			if (!p->un.inner.clprio[prio].feed.rb_node)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
  				mask |= 1 << prio;
  		}
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
449

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
  		p->prio_activity &= ~mask;
87990467d   Stephen Hemminger   [HTB]: Lindent
451
452
  		cl = p;
  		p = cl->parent;
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
453

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
  	}
87990467d   Stephen Hemminger   [HTB]: Lindent
455
456
  	if (cl->cmode == HTB_CAN_SEND && mask)
  		htb_remove_class_from_row(q, cl, mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
  }
56b765b79   Vimalkumar   htb: improved acc...
458
  static inline s64 htb_lowater(const struct htb_class *cl)
18a63e868   Stephen Hemminger   [HTB]: HTB_HYSTER...
459
  {
47083fc07   Jesper Dangaard Brouer   pkt_sched: Change...
460
461
462
463
  	if (htb_hysteresis)
  		return cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : 0;
  	else
  		return 0;
18a63e868   Stephen Hemminger   [HTB]: HTB_HYSTER...
464
  }
56b765b79   Vimalkumar   htb: improved acc...
465
  static inline s64 htb_hiwater(const struct htb_class *cl)
18a63e868   Stephen Hemminger   [HTB]: HTB_HYSTER...
466
  {
47083fc07   Jesper Dangaard Brouer   pkt_sched: Change...
467
468
469
470
  	if (htb_hysteresis)
  		return cl->cmode == HTB_CAN_SEND ? -cl->buffer : 0;
  	else
  		return 0;
18a63e868   Stephen Hemminger   [HTB]: HTB_HYSTER...
471
  }
47083fc07   Jesper Dangaard Brouer   pkt_sched: Change...
472

18a63e868   Stephen Hemminger   [HTB]: HTB_HYSTER...
473

1da177e4c   Linus Torvalds   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   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
479
   * from now to time when cl will change its state.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
   * Also it is worth to note that class mode doesn't change simply
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
481
   * at cl->{c,}tokens == 0 but there can rather be hysteresis of
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
485
  static inline enum htb_cmode
56b765b79   Vimalkumar   htb: improved acc...
486
  htb_class_mode(struct htb_class *cl, s64 *diff)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
  {
56b765b79   Vimalkumar   htb: improved acc...
488
  	s64 toks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489

87990467d   Stephen Hemminger   [HTB]: Lindent
490
491
492
493
  	if ((toks = (cl->ctokens + *diff)) < htb_lowater(cl)) {
  		*diff = -toks;
  		return HTB_CANT_SEND;
  	}
18a63e868   Stephen Hemminger   [HTB]: HTB_HYSTER...
494

87990467d   Stephen Hemminger   [HTB]: Lindent
495
496
  	if ((toks = (cl->tokens + *diff)) >= htb_hiwater(cl))
  		return HTB_CAN_SEND;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497

87990467d   Stephen Hemminger   [HTB]: Lindent
498
499
  	*diff = -toks;
  	return HTB_MAY_BORROW;
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
511
  static void
56b765b79   Vimalkumar   htb: improved acc...
512
  htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, s64 *diff)
87990467d   Stephen Hemminger   [HTB]: Lindent
513
514
  {
  	enum htb_cmode new_mode = htb_class_mode(cl, diff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
  
  	if (new_mode == cl->cmode)
87990467d   Stephen Hemminger   [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   Linus Torvalds   Linux-2.6.12-rc2
522
  		cl->cmode = new_mode;
87990467d   Stephen Hemminger   [HTB]: Lindent
523
524
525
  		if (new_mode != HTB_CANT_SEND)
  			htb_activate_prios(q, cl);
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
527
528
529
  		cl->cmode = new_mode;
  }
  
  /**
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
530
   * htb_activate - inserts leaf cl into appropriate active feeds
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
536
  static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
  {
547b792ca   Ilpo Järvinen   net: convert BUG_...
538
  	WARN_ON(cl->level || !cl->un.leaf.q || !cl->un.leaf.q->q.qlen);
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
539

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
  	if (!cl->prio_activity) {
c19f7a34f   Jarek Poplawski   pkt_sched: sch_ht...
541
  		cl->prio_activity = 1 << cl->prio;
87990467d   Stephen Hemminger   [HTB]: Lindent
542
543
  		htb_activate_prios(q, cl);
  		list_add_tail(&cl->un.leaf.drop_list,
c19f7a34f   Jarek Poplawski   pkt_sched: sch_ht...
544
  			      q->drops + cl->prio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
546
547
548
  	}
  }
  
  /**
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
549
   * htb_deactivate - remove leaf cl from active feeds
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
554
  static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
  {
547b792ca   Ilpo Järvinen   net: convert BUG_...
556
  	WARN_ON(!cl->prio_activity);
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
557

87990467d   Stephen Hemminger   [HTB]: Lindent
558
  	htb_deactivate_prios(q, cl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
560
561
  	cl->prio_activity = 0;
  	list_del_init(&cl->un.leaf.drop_list);
  }
48da34b7a   Florian Westphal   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   Eric Dumazet   net_sched: drop p...
577
578
  static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
  		       struct sk_buff **to_free)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
  {
f30ab418a   Jarek Poplawski   pkt_sched: Remove...
580
  	int uninitialized_var(ret);
87990467d   Stephen Hemminger   [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   Florian Westphal   sched: add and us...
587
  			htb_enqueue_tail(skb, sch, &q->direct_queue);
87990467d   Stephen Hemminger   [HTB]: Lindent
588
589
  			q->direct_pkts++;
  		} else {
520ac30f4   Eric Dumazet   net_sched: drop p...
590
  			return qdisc_drop(skb, sch, to_free);
87990467d   Stephen Hemminger   [HTB]: Lindent
591
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
  #ifdef CONFIG_NET_CLS_ACT
87990467d   Stephen Hemminger   [HTB]: Lindent
593
  	} else if (!cl) {
c27f339af   Jarek Poplawski   net_sched: Add qd...
594
  		if (ret & __NET_XMIT_BYPASS)
25331d6ce   John Fastabend   net: sched: imple...
595
  			qdisc_qstats_drop(sch);
520ac30f4   Eric Dumazet   net_sched: drop p...
596
  		__qdisc_drop(skb, to_free);
87990467d   Stephen Hemminger   [HTB]: Lindent
597
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
  #endif
520ac30f4   Eric Dumazet   net_sched: drop p...
599
600
  	} else if ((ret = qdisc_enqueue(skb, cl->un.leaf.q,
  					to_free)) != NET_XMIT_SUCCESS) {
378a2f090   Jarek Poplawski   net_sched: Add qd...
601
  		if (net_xmit_drop_count(ret)) {
25331d6ce   John Fastabend   net: sched: imple...
602
  			qdisc_qstats_drop(sch);
338ed9b4d   Eric Dumazet   net_sched: sch_ht...
603
  			cl->drops++;
378a2f090   Jarek Poplawski   net_sched: Add qd...
604
  		}
69747650c   David S. Miller   pkt_sched: Fix re...
605
  		return ret;
87990467d   Stephen Hemminger   [HTB]: Lindent
606
  	} else {
87990467d   Stephen Hemminger   [HTB]: Lindent
607
608
  		htb_activate(q, cl);
  	}
431e3a8e3   WANG Cong   sch_htb: update b...
609
  	qdisc_qstats_backlog_inc(sch, skb);
87990467d   Stephen Hemminger   [HTB]: Lindent
610
  	sch->q.qlen++;
87990467d   Stephen Hemminger   [HTB]: Lindent
611
  	return NET_XMIT_SUCCESS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
  }
56b765b79   Vimalkumar   htb: improved acc...
613
  static inline void htb_accnt_tokens(struct htb_class *cl, int bytes, s64 diff)
59e4220a1   Jarek Poplawski   pkt_sched: sch_ht...
614
  {
56b765b79   Vimalkumar   htb: improved acc...
615
  	s64 toks = diff + cl->tokens;
59e4220a1   Jarek Poplawski   pkt_sched: sch_ht...
616
617
618
  
  	if (toks > cl->buffer)
  		toks = cl->buffer;
292f1c7ff   Jiri Pirko   sch: make htb_rat...
619
  	toks -= (s64) psched_l2t_ns(&cl->rate, bytes);
59e4220a1   Jarek Poplawski   pkt_sched: sch_ht...
620
621
622
623
624
  	if (toks <= -cl->mbuffer)
  		toks = 1 - cl->mbuffer;
  
  	cl->tokens = toks;
  }
56b765b79   Vimalkumar   htb: improved acc...
625
  static inline void htb_accnt_ctokens(struct htb_class *cl, int bytes, s64 diff)
59e4220a1   Jarek Poplawski   pkt_sched: sch_ht...
626
  {
56b765b79   Vimalkumar   htb: improved acc...
627
  	s64 toks = diff + cl->ctokens;
59e4220a1   Jarek Poplawski   pkt_sched: sch_ht...
628
629
630
  
  	if (toks > cl->cbuffer)
  		toks = cl->cbuffer;
292f1c7ff   Jiri Pirko   sch: make htb_rat...
631
  	toks -= (s64) psched_l2t_ns(&cl->ceil, bytes);
59e4220a1   Jarek Poplawski   pkt_sched: sch_ht...
632
633
634
635
636
  	if (toks <= -cl->mbuffer)
  		toks = 1 - cl->mbuffer;
  
  	cl->ctokens = toks;
  }
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
648
  static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
c9726d689   Ranjit Manomohan   [NET_SCHED]: Make...
649
  			     int level, struct sk_buff *skb)
87990467d   Stephen Hemminger   [HTB]: Lindent
650
  {
0abf77e55   Jussi Kivilinna   net_sched: Add ac...
651
  	int bytes = qdisc_pkt_len(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
  	enum htb_cmode old_mode;
56b765b79   Vimalkumar   htb: improved acc...
653
  	s64 diff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
  
  	while (cl) {
56b765b79   Vimalkumar   htb: improved acc...
656
  		diff = min_t(s64, q->now - cl->t_c, cl->mbuffer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
  		if (cl->level >= level) {
87990467d   Stephen Hemminger   [HTB]: Lindent
658
659
  			if (cl->level == level)
  				cl->xstats.lends++;
59e4220a1   Jarek Poplawski   pkt_sched: sch_ht...
660
  			htb_accnt_tokens(cl, bytes, diff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
662
  		} else {
  			cl->xstats.borrows++;
87990467d   Stephen Hemminger   [HTB]: Lindent
663
  			cl->tokens += diff;	/* we moved t_c; update tokens */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664
  		}
59e4220a1   Jarek Poplawski   pkt_sched: sch_ht...
665
  		htb_accnt_ctokens(cl, bytes, diff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
  		cl->t_c = q->now;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667

87990467d   Stephen Hemminger   [HTB]: Lindent
668
669
670
  		old_mode = cl->cmode;
  		diff = 0;
  		htb_change_class_mode(q, cl, &diff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
672
  		if (old_mode != cl->cmode) {
  			if (old_mode != HTB_CAN_SEND)
c9364636d   Eric Dumazet   htb: refactor str...
673
  				htb_safe_rb_erase(&cl->pq_node, &q->hlevel[cl->level].wait_pq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
674
  			if (cl->cmode != HTB_CAN_SEND)
87990467d   Stephen Hemminger   [HTB]: Lindent
675
  				htb_add_to_wait_tree(q, cl, diff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677

bfe0d0298   Eric Dumazet   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   Linus Torvalds   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   Patrick McHardy   [NET_SCHED]: sch_...
688
   * Scans event queue for pending events and applies them. Returns time of
1224736d9   Jarek Poplawski   pkt_sched: sch_ht...
689
   * next pending event (0 for no event in pq, q->now for too many events).
fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
690
   * Note: Applied are events whose have cl->pq_key <= q->now.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
   */
c9364636d   Eric Dumazet   htb: refactor str...
692
  static s64 htb_do_events(struct htb_sched *q, const int level,
5343a7f8b   Eric Dumazet   net_sched: htb: d...
693
  			 unsigned long start)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
  {
8f3ea33a5   Martin Devera   sch_htb: fix "too...
695
  	/* don't run for longer than 2 jiffies; 2 is used instead of
cc7ec456f   Eric Dumazet   net_sched: cleanups
696
697
698
  	 * 1 to simplify things when jiffy is going to be incremented
  	 * too soon
  	 */
a73be0406   Jarek Poplawski   pkt_sched: sch_ht...
699
  	unsigned long stop_at = start + 2;
c9364636d   Eric Dumazet   htb: refactor str...
700
  	struct rb_root *wait_pq = &q->hlevel[level].wait_pq;
8f3ea33a5   Martin Devera   sch_htb: fix "too...
701
  	while (time_before(jiffies, stop_at)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
  		struct htb_class *cl;
56b765b79   Vimalkumar   htb: improved acc...
703
  		s64 diff;
c9364636d   Eric Dumazet   htb: refactor str...
704
  		struct rb_node *p = rb_first(wait_pq);
30bdbe397   Akinbou Mita   [PKT_SCHED] sch_h...
705

87990467d   Stephen Hemminger   [HTB]: Lindent
706
707
  		if (!p)
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708
709
  
  		cl = rb_entry(p, struct htb_class, pq_node);
fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
710
711
  		if (cl->pq_key > q->now)
  			return cl->pq_key;
c9364636d   Eric Dumazet   htb: refactor str...
712
  		htb_safe_rb_erase(p, wait_pq);
56b765b79   Vimalkumar   htb: improved acc...
713
  		diff = min_t(s64, q->now - cl->t_c, cl->mbuffer);
87990467d   Stephen Hemminger   [HTB]: Lindent
714
  		htb_change_class_mode(q, cl, &diff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
  		if (cl->cmode != HTB_CAN_SEND)
87990467d   Stephen Hemminger   [HTB]: Lindent
716
  			htb_add_to_wait_tree(q, cl, diff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
  	}
1224736d9   Jarek Poplawski   pkt_sched: sch_ht...
718
719
  
  	/* too much load - let's continue after a break for scheduling */
e82181de5   Jarek Poplawski   pkt_sched: sch_ht...
720
  	if (!(q->warned & HTB_WARN_TOOMANYEVENTS)) {
c17988a90   Yang Yingliang   net_sched: replac...
721
722
  		pr_warn("htb: too many events!
  ");
e82181de5   Jarek Poplawski   pkt_sched: sch_ht...
723
724
  		q->warned |= HTB_WARN_TOOMANYEVENTS;
  	}
1224736d9   Jarek Poplawski   pkt_sched: sch_ht...
725
726
  
  	return q->now;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727
728
729
  }
  
  /* Returns class->node+prio from id-tree where classe's id is >= id. NULL
cc7ec456f   Eric Dumazet   net_sched: cleanups
730
731
   * is no such one exists.
   */
87990467d   Stephen Hemminger   [HTB]: Lindent
732
733
  static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n,
  					      u32 id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
736
  {
  	struct rb_node *r = NULL;
  	while (n) {
87990467d   Stephen Hemminger   [HTB]: Lindent
737
738
  		struct htb_class *cl =
  		    rb_entry(n, struct htb_class, node[prio]);
87990467d   Stephen Hemminger   [HTB]: Lindent
739

f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
740
  		if (id > cl->common.classid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
  			n = n->rb_right;
1b5c0077e   Jarek Poplawski   pkt_sched: sch_ht...
742
  		} else if (id < cl->common.classid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
744
  			r = n;
  			n = n->rb_left;
1b5c0077e   Jarek Poplawski   pkt_sched: sch_ht...
745
746
  		} else {
  			return n;
1da177e4c   Linus Torvalds   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   Eric Dumazet   htb: refactor str...
757
  static struct htb_class *htb_lookup_leaf(struct htb_prio *hprio, const int prio)
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
764
  	} stk[TC_HTB_MAXDEPTH], *sp = stk;
c9364636d   Eric Dumazet   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   Linus Torvalds   Linux-2.6.12-rc2
769
770
  
  	for (i = 0; i < 65535; i++) {
87990467d   Stephen Hemminger   [HTB]: Lindent
771
  		if (!*sp->pptr && *sp->pid) {
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
772
  			/* ptr was invalidated but id is valid - try to recover
cc7ec456f   Eric Dumazet   net_sched: cleanups
773
774
  			 * the original or next ptr
  			 */
87990467d   Stephen Hemminger   [HTB]: Lindent
775
776
  			*sp->pptr =
  			    htb_id_find_next_upper(prio, sp->root, *sp->pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
  		}
87990467d   Stephen Hemminger   [HTB]: Lindent
778
  		*sp->pid = 0;	/* ptr is valid now so that remove this hint as it
cc7ec456f   Eric Dumazet   net_sched: cleanups
779
780
  				 * can become out of date quickly
  				 */
87990467d   Stephen Hemminger   [HTB]: Lindent
781
  		if (!*sp->pptr) {	/* we are at right end; rewind & go up */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782
  			*sp->pptr = sp->root;
87990467d   Stephen Hemminger   [HTB]: Lindent
783
  			while ((*sp->pptr)->rb_left)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
785
786
  				*sp->pptr = (*sp->pptr)->rb_left;
  			if (sp > stk) {
  				sp--;
512bb43eb   Jarek Poplawski   pkt_sched: sch_ht...
787
788
  				if (!*sp->pptr) {
  					WARN_ON(1);
87990467d   Stephen Hemminger   [HTB]: Lindent
789
  					return NULL;
512bb43eb   Jarek Poplawski   pkt_sched: sch_ht...
790
  				}
87990467d   Stephen Hemminger   [HTB]: Lindent
791
  				htb_next_rb_node(sp->pptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
793
794
  			}
  		} else {
  			struct htb_class *cl;
c9364636d   Eric Dumazet   htb: refactor str...
795
  			struct htb_prio *clp;
87990467d   Stephen Hemminger   [HTB]: Lindent
796
797
  			cl = rb_entry(*sp->pptr, struct htb_class, node[prio]);
  			if (!cl->level)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
  				return cl;
c9364636d   Eric Dumazet   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   Linus Torvalds   Linux-2.6.12-rc2
803
804
  		}
  	}
547b792ca   Ilpo Järvinen   net: convert BUG_...
805
  	WARN_ON(1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
807
808
809
  	return NULL;
  }
  
  /* dequeues packet at given priority and level; call only if
cc7ec456f   Eric Dumazet   net_sched: cleanups
810
811
   * you are sure that there is active class at prio/level
   */
c9364636d   Eric Dumazet   htb: refactor str...
812
813
  static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, const int prio,
  					const int level)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
815
  {
  	struct sk_buff *skb = NULL;
87990467d   Stephen Hemminger   [HTB]: Lindent
816
  	struct htb_class *cl, *start;
c9364636d   Eric Dumazet   htb: refactor str...
817
818
  	struct htb_level *hlevel = &q->hlevel[level];
  	struct htb_prio *hprio = &hlevel->hprio[prio];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
  	/* look initial class up in the row */
c9364636d   Eric Dumazet   htb: refactor str...
820
  	start = cl = htb_lookup_leaf(hprio, prio);
87990467d   Stephen Hemminger   [HTB]: Lindent
821

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
823
  	do {
  next:
512bb43eb   Jarek Poplawski   pkt_sched: sch_ht...
824
  		if (unlikely(!cl))
87990467d   Stephen Hemminger   [HTB]: Lindent
825
  			return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826
827
  
  		/* class can be empty - it is unlikely but can be true if leaf
cc7ec456f   Eric Dumazet   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   Linus Torvalds   Linux-2.6.12-rc2
832
833
  		if (unlikely(cl->un.leaf.q->q.qlen == 0)) {
  			struct htb_class *next;
87990467d   Stephen Hemminger   [HTB]: Lindent
834
  			htb_deactivate(q, cl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835
836
837
  
  			/* row/level might become empty */
  			if ((q->row_mask[level] & (1 << prio)) == 0)
87990467d   Stephen Hemminger   [HTB]: Lindent
838
  				return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839

c9364636d   Eric Dumazet   htb: refactor str...
840
  			next = htb_lookup_leaf(hprio, prio);
87990467d   Stephen Hemminger   [HTB]: Lindent
841
842
  
  			if (cl == start)	/* fix start if we just deleted it */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
844
845
846
  				start = next;
  			cl = next;
  			goto next;
  		}
87990467d   Stephen Hemminger   [HTB]: Lindent
847
848
849
  
  		skb = cl->un.leaf.q->dequeue(cl->un.leaf.q);
  		if (likely(skb != NULL))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850
  			break;
633fe66ed   Jarek Poplawski   pkt_sched: sch_ht...
851

b00355db3   Jarek Poplawski   pkt_sched: sch_hf...
852
  		qdisc_warn_nonwc("htb", cl->un.leaf.q);
c9364636d   Eric Dumazet   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   Linus Torvalds   Linux-2.6.12-rc2
856
857
858
859
  
  	} while (cl != start);
  
  	if (likely(skb != NULL)) {
196d97f6b   Eric Dumazet   htb: fix two bugs
860
  		bstats_update(&cl->bstats, skb);
0abf77e55   Jussi Kivilinna   net_sched: Add ac...
861
862
  		cl->un.leaf.deficit[level] -= qdisc_pkt_len(skb);
  		if (cl->un.leaf.deficit[level] < 0) {
c19f7a34f   Jarek Poplawski   pkt_sched: sch_ht...
863
  			cl->un.leaf.deficit[level] += cl->quantum;
c9364636d   Eric Dumazet   htb: refactor str...
864
865
  			htb_next_rb_node(level ? &cl->parent->un.inner.clprio[prio].ptr :
  						 &q->hlevel[0].hprio[prio].ptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
866
867
  		}
  		/* this used to be after charge_class but this constelation
cc7ec456f   Eric Dumazet   net_sched: cleanups
868
869
  		 * gives us slightly better performance
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870
  		if (!cl->un.leaf.q->q.qlen)
87990467d   Stephen Hemminger   [HTB]: Lindent
871
  			htb_deactivate(q, cl);
c9726d689   Ranjit Manomohan   [NET_SCHED]: Make...
872
  		htb_charge_class(q, cl, level, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
873
874
875
  	}
  	return skb;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
876
877
  static struct sk_buff *htb_dequeue(struct Qdisc *sch)
  {
9190b3b32   Eric Dumazet   net_sched: accura...
878
  	struct sk_buff *skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
880
  	struct htb_sched *q = qdisc_priv(sch);
  	int level;
5343a7f8b   Eric Dumazet   net_sched: htb: d...
881
  	s64 next_event;
a73be0406   Jarek Poplawski   pkt_sched: sch_ht...
882
  	unsigned long start_at;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
884
  
  	/* try to dequeue direct packets as high prio (!) to minimize cpu work */
48da34b7a   Florian Westphal   sched: add and us...
885
  	skb = __qdisc_dequeue_head(&q->direct_queue);
87990467d   Stephen Hemminger   [HTB]: Lindent
886
  	if (skb != NULL) {
9190b3b32   Eric Dumazet   net_sched: accura...
887
888
  ok:
  		qdisc_bstats_update(sch, skb);
431e3a8e3   WANG Cong   sch_htb: update b...
889
  		qdisc_qstats_backlog_dec(sch, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
890
891
892
  		sch->q.qlen--;
  		return skb;
  	}
87990467d   Stephen Hemminger   [HTB]: Lindent
893
894
  	if (!sch->q.qlen)
  		goto fin;
d2de875c6   Eric Dumazet   net: use ktime_ge...
895
  	q->now = ktime_get_ns();
a73be0406   Jarek Poplawski   pkt_sched: sch_ht...
896
  	start_at = jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897

d2fe85da5   Stefan Hasko   net: sched: integ...
898
  	next_event = q->now + 5LLU * NSEC_PER_SEC;
633fe66ed   Jarek Poplawski   pkt_sched: sch_ht...
899

1da177e4c   Linus Torvalds   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   Eric Dumazet   htb: refactor str...
903
  		s64 event = q->near_ev_cache[level];
fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
904

c9364636d   Eric Dumazet   htb: refactor str...
905
  		if (q->now >= event) {
a73be0406   Jarek Poplawski   pkt_sched: sch_ht...
906
  			event = htb_do_events(q, level, start_at);
2e4b3b0e8   Patrick McHardy   [NET_SCHED]: sch_...
907
  			if (!event)
56b765b79   Vimalkumar   htb: improved acc...
908
  				event = q->now + NSEC_PER_SEC;
2e4b3b0e8   Patrick McHardy   [NET_SCHED]: sch_...
909
  			q->near_ev_cache[level] = event;
c9364636d   Eric Dumazet   htb: refactor str...
910
  		}
fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
911

c08513471   Jarek Poplawski   pkt_sched: sch_ht...
912
  		if (next_event > event)
fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
913
  			next_event = event;
87990467d   Stephen Hemminger   [HTB]: Lindent
914

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
915
916
  		m = ~q->row_mask[level];
  		while (m != (int)(-1)) {
87990467d   Stephen Hemminger   [HTB]: Lindent
917
  			int prio = ffz(m);
cc7ec456f   Eric Dumazet   net_sched: cleanups
918

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
  			m |= 1 << prio;
87990467d   Stephen Hemminger   [HTB]: Lindent
920
  			skb = htb_dequeue_tree(q, prio, level);
9190b3b32   Eric Dumazet   net_sched: accura...
921
922
  			if (likely(skb != NULL))
  				goto ok;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
924
  		}
  	}
25331d6ce   John Fastabend   net: sched: imple...
925
  	qdisc_qstats_overlimit(sch);
a9efad8b2   Eric Dumazet   net_sched: avoid ...
926
  	if (likely(next_event > q->now))
45f50bed1   Eric Dumazet   net_sched: remove...
927
  		qdisc_watchdog_schedule_ns(&q->watchdog, next_event);
a9efad8b2   Eric Dumazet   net_sched: avoid ...
928
  	else
1224736d9   Jarek Poplawski   pkt_sched: sch_ht...
929
  		schedule_work(&q->work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
  fin:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
932
  	return skb;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
933
934
  /* reset all classes */
  /* always caled under BH & queue lock */
87990467d   Stephen Hemminger   [HTB]: Lindent
935
  static void htb_reset(struct Qdisc *sch)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
937
  {
  	struct htb_sched *q = qdisc_priv(sch);
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
938
  	struct htb_class *cl;
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
939
  	unsigned int i;
0cef296da   Stephen Hemminger   [HTB]: Use hlist ...
940

f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
941
  	for (i = 0; i < q->clhash.hashsize; i++) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
942
  		hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
943
  			if (cl->level)
87990467d   Stephen Hemminger   [HTB]: Lindent
944
  				memset(&cl->un.inner, 0, sizeof(cl->un.inner));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
945
  			else {
87990467d   Stephen Hemminger   [HTB]: Lindent
946
  				if (cl->un.leaf.q)
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
952
953
  		}
  	}
fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
954
  	qdisc_watchdog_cancel(&q->watchdog);
a5a9f5346   Eric Dumazet   net_sched: sch_ht...
955
  	__qdisc_reset_queue(&q->direct_queue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956
  	sch->q.qlen = 0;
431e3a8e3   WANG Cong   sch_htb: update b...
957
  	sch->qstats.backlog = 0;
c9364636d   Eric Dumazet   htb: refactor str...
958
  	memset(q->hlevel, 0, sizeof(q->hlevel));
87990467d   Stephen Hemminger   [HTB]: Lindent
959
  	memset(q->row_mask, 0, sizeof(q->row_mask));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
  	for (i = 0; i < TC_HTB_NUMPRIO; i++)
87990467d   Stephen Hemminger   [HTB]: Lindent
961
  		INIT_LIST_HEAD(q->drops + i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962
  }
27a3421e4   Patrick McHardy   [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   Eric Dumazet   htb: add HTB_DIRE...
968
  	[TCA_HTB_DIRECT_QLEN] = { .type = NLA_U32 },
df62cdf34   Eric Dumazet   net_sched: htb: s...
969
970
  	[TCA_HTB_RATE64] = { .type = NLA_U64 },
  	[TCA_HTB_CEIL64] = { .type = NLA_U64 },
27a3421e4   Patrick McHardy   [NET_SCHED]: Use ...
971
  };
1224736d9   Jarek Poplawski   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   Florian Westphal   htb: call qdisc_r...
976
  	rcu_read_lock();
1224736d9   Jarek Poplawski   pkt_sched: sch_ht...
977
  	__netif_schedule(qdisc_root(sch));
0ee13627f   Florian Westphal   htb: call qdisc_r...
978
  	rcu_read_unlock();
1224736d9   Jarek Poplawski   pkt_sched: sch_ht...
979
  }
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
980
  static int htb_init(struct Qdisc *sch, struct nlattr *opt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981
982
  {
  	struct htb_sched *q = qdisc_priv(sch);
6906f4ed6   Eric Dumazet   htb: add HTB_DIRE...
983
  	struct nlattr *tb[TCA_HTB_MAX + 1];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984
  	struct tc_htb_glob *gopt;
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
985
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986
  	int i;
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
987

88c2ace69   Nikolay Aleksandrov   sch_htb: fix cras...
988
989
  	qdisc_watchdog_init(&q->watchdog, sch);
  	INIT_WORK(&q->work, htb_work_func);
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
990
991
  	if (!opt)
  		return -EINVAL;
6529eaba3   Jiri Pirko   net: sched: intro...
992
993
994
  	err = tcf_block_get(&q->block, &q->filter_list);
  	if (err)
  		return err;
fceb6435e   Johannes Berg   netlink: pass ext...
995
  	err = nla_parse_nested(tb, TCA_HTB_MAX, opt, htb_policy, NULL);
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
996
997
  	if (err < 0)
  		return err;
6906f4ed6   Eric Dumazet   htb: add HTB_DIRE...
998
  	if (!tb[TCA_HTB_INIT])
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
999
  		return -EINVAL;
6906f4ed6   Eric Dumazet   htb: add HTB_DIRE...
1000

1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
1001
  	gopt = nla_data(tb[TCA_HTB_INIT]);
6906f4ed6   Eric Dumazet   htb: add HTB_DIRE...
1002
  	if (gopt->version != HTB_VER >> 16)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1003
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004

f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1005
1006
1007
  	err = qdisc_class_hash_init(&q->clhash);
  	if (err < 0)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1008
  	for (i = 0; i < TC_HTB_NUMPRIO; i++)
87990467d   Stephen Hemminger   [HTB]: Lindent
1009
  		INIT_LIST_HEAD(q->drops + i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1010

48da34b7a   Florian Westphal   sched: add and us...
1011
  	qdisc_skb_head_init(&q->direct_queue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012

6906f4ed6   Eric Dumazet   htb: add HTB_DIRE...
1013
1014
  	if (tb[TCA_HTB_DIRECT_QLEN])
  		q->direct_qlen = nla_get_u32(tb[TCA_HTB_DIRECT_QLEN]);
348e3435c   Phil Sutter   net: sched: drop ...
1015
  	else
6906f4ed6   Eric Dumazet   htb: add HTB_DIRE...
1016
  		q->direct_qlen = qdisc_dev(sch)->tx_queue_len;
348e3435c   Phil Sutter   net: sched: drop ...
1017

1da177e4c   Linus Torvalds   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   Patrick McHardy   [NET_SCHED]: Use ...
1028
  	struct nlattr *nest;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1029
  	struct tc_htb_glob gopt;
4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1030

6f542efcb   Eric Dumazet   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   Linus Torvalds   Linux-2.6.12-rc2
1034

4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1035
  	gopt.direct_pkts = q->direct_pkts;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
1037
1038
  	gopt.version = HTB_VER;
  	gopt.rate2quantum = q->rate2quantum;
  	gopt.defcls = q->defcls;
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
1039
  	gopt.debug = 0;
4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1040
1041
1042
1043
  
  	nest = nla_nest_start(skb, TCA_OPTIONS);
  	if (nest == NULL)
  		goto nla_put_failure;
6906f4ed6   Eric Dumazet   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   David S. Miller   pkt_sched: Stop u...
1046
  		goto nla_put_failure;
4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1047

6f542efcb   Eric Dumazet   net_sched: htb: d...
1048
  	return nla_nest_end(skb, nest);
4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1049

1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
1050
  nla_put_failure:
4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1051
  	nla_nest_cancel(skb, nest);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1052
1053
1054
1055
  	return -1;
  }
  
  static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
87990467d   Stephen Hemminger   [HTB]: Lindent
1056
  			  struct sk_buff *skb, struct tcmsg *tcm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1057
  {
87990467d   Stephen Hemminger   [HTB]: Lindent
1058
  	struct htb_class *cl = (struct htb_class *)arg;
4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1059
  	struct nlattr *nest;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1060
  	struct tc_htb_opt opt;
6f542efcb   Eric Dumazet   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   Patrick McHardy   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   Linus Torvalds   Linux-2.6.12-rc2
1066
1067
  	if (!cl->level && cl->un.leaf.q)
  		tcm->tcm_info = cl->un.leaf.q->handle;
4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1068
1069
1070
  	nest = nla_nest_start(skb, TCA_OPTIONS);
  	if (nest == NULL)
  		goto nla_put_failure;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1071

87990467d   Stephen Hemminger   [HTB]: Lindent
1072
  	memset(&opt, 0, sizeof(opt));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073

01cb71d2d   Eric Dumazet   net_sched: restor...
1074
  	psched_ratecfg_getrate(&opt.rate, &cl->rate);
9c10f4115   Jiri Pirko   htb: fix values i...
1075
  	opt.buffer = PSCHED_NS2TICKS(cl->buffer);
01cb71d2d   Eric Dumazet   net_sched: restor...
1076
  	psched_ratecfg_getrate(&opt.ceil, &cl->ceil);
9c10f4115   Jiri Pirko   htb: fix values i...
1077
  	opt.cbuffer = PSCHED_NS2TICKS(cl->cbuffer);
c19f7a34f   Jarek Poplawski   pkt_sched: sch_ht...
1078
1079
  	opt.quantum = cl->quantum;
  	opt.prio = cl->prio;
87990467d   Stephen Hemminger   [HTB]: Lindent
1080
  	opt.level = cl->level;
1b34ec43c   David S. Miller   pkt_sched: Stop u...
1081
1082
  	if (nla_put(skb, TCA_HTB_PARMS, sizeof(opt), &opt))
  		goto nla_put_failure;
df62cdf34   Eric Dumazet   net_sched: htb: s...
1083
  	if ((cl->rate.rate_bytes_ps >= (1ULL << 32)) &&
2a51c1e8e   Nicolas Dichtel   sched: use nla_pu...
1084
1085
  	    nla_put_u64_64bit(skb, TCA_HTB_RATE64, cl->rate.rate_bytes_ps,
  			      TCA_HTB_PAD))
df62cdf34   Eric Dumazet   net_sched: htb: s...
1086
1087
  		goto nla_put_failure;
  	if ((cl->ceil.rate_bytes_ps >= (1ULL << 32)) &&
2a51c1e8e   Nicolas Dichtel   sched: use nla_pu...
1088
1089
  	    nla_put_u64_64bit(skb, TCA_HTB_CEIL64, cl->ceil.rate_bytes_ps,
  			      TCA_HTB_PAD))
df62cdf34   Eric Dumazet   net_sched: htb: s...
1090
  		goto nla_put_failure;
4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1091

6f542efcb   Eric Dumazet   net_sched: htb: d...
1092
  	return nla_nest_end(skb, nest);
4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1093

1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
1094
  nla_put_failure:
4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1095
  	nla_nest_cancel(skb, nest);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1096
1097
1098
1099
  	return -1;
  }
  
  static int
87990467d   Stephen Hemminger   [HTB]: Lindent
1100
  htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1101
  {
87990467d   Stephen Hemminger   [HTB]: Lindent
1102
  	struct htb_class *cl = (struct htb_class *)arg;
338ed9b4d   Eric Dumazet   net_sched: sch_ht...
1103
1104
1105
  	struct gnet_stats_queue qs = {
  		.drops = cl->drops,
  	};
640158536   John Fastabend   net: sched: restr...
1106
  	__u32 qlen = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1107

338ed9b4d   Eric Dumazet   net_sched: sch_ht...
1108
  	if (!cl->level && cl->un.leaf.q) {
640158536   John Fastabend   net: sched: restr...
1109
  		qlen = cl->un.leaf.q->q.qlen;
338ed9b4d   Eric Dumazet   net_sched: sch_ht...
1110
1111
  		qs.backlog = cl->un.leaf.q->qstats.backlog;
  	}
0564bf0af   Konstantin Khlebnikov   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   Linus Torvalds   Linux-2.6.12-rc2
1116

edb09eb17   Eric Dumazet   net: sched: do no...
1117
1118
  	if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
  				  d, NULL, &cl->bstats) < 0 ||
1c0d32fde   Eric Dumazet   net_sched: gen_es...
1119
  	    gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
338ed9b4d   Eric Dumazet   net_sched: sch_ht...
1120
  	    gnet_stats_copy_queue(d, NULL, &qs, qlen) < 0)
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
1127
  		     struct Qdisc **old)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1128
  {
87990467d   Stephen Hemminger   [HTB]: Lindent
1129
  	struct htb_class *cl = (struct htb_class *)arg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130

5b9a9ccfa   Patrick McHardy   net_sched: remove...
1131
1132
1133
  	if (cl->level)
  		return -EINVAL;
  	if (new == NULL &&
3511c9132   Changli Gao   net_sched: remove...
1134
  	    (new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
5b9a9ccfa   Patrick McHardy   net_sched: remove...
1135
1136
  				     cl->common.classid)) == NULL)
  		return -ENOBUFS;
86a7996cc   WANG Cong   net_sched: introd...
1137
  	*old = qdisc_replace(sch, new, &cl->un.leaf.q);
5b9a9ccfa   Patrick McHardy   net_sched: remove...
1138
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1139
  }
87990467d   Stephen Hemminger   [HTB]: Lindent
1140
  static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1141
  {
87990467d   Stephen Hemminger   [HTB]: Lindent
1142
  	struct htb_class *cl = (struct htb_class *)arg;
5b9a9ccfa   Patrick McHardy   net_sched: remove...
1143
  	return !cl->level ? cl->un.leaf.q : NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1144
  }
256d61b87   Patrick McHardy   [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   Konstantin Khlebnikov   net_sched: call q...
1148
  	htb_deactivate(qdisc_priv(sch), cl);
256d61b87   Patrick McHardy   [NET_SCHED]: Fix ...
1149
  }
160d5e10f   Jarek Poplawski   [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   Patrick McHardy   net-sched: sch_ht...
1155
  	if (cl->parent->children > 1)
160d5e10f   Jarek Poplawski   [NET_SCHED] sch_h...
1156
1157
  		/* not the last child */
  		return 0;
160d5e10f   Jarek Poplawski   [NET_SCHED] sch_h...
1158
1159
  	return 1;
  }
3ba08b00e   Jarek Poplawski   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   Jarek Poplawski   [NET_SCHED] sch_h...
1162
1163
  {
  	struct htb_class *parent = cl->parent;
547b792ca   Ilpo Järvinen   net: convert BUG_...
1164
  	WARN_ON(cl->level || !cl->un.leaf.q || cl->prio_activity);
160d5e10f   Jarek Poplawski   [NET_SCHED] sch_h...
1165

3ba08b00e   Jarek Poplawski   sch_htb: remove f...
1166
  	if (parent->cmode != HTB_CAN_SEND)
c9364636d   Eric Dumazet   htb: refactor str...
1167
1168
  		htb_safe_rb_erase(&parent->pq_node,
  				  &q->hlevel[parent->level].wait_pq);
3ba08b00e   Jarek Poplawski   sch_htb: remove f...
1169

160d5e10f   Jarek Poplawski   [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   Jarek Poplawski   [NET_SCHED] sch_h...
1174
1175
  	parent->tokens = parent->buffer;
  	parent->ctokens = parent->cbuffer;
d2de875c6   Eric Dumazet   net: use ktime_ge...
1176
  	parent->t_c = ktime_get_ns();
160d5e10f   Jarek Poplawski   [NET_SCHED] sch_h...
1177
1178
  	parent->cmode = HTB_CAN_SEND;
  }
87990467d   Stephen Hemminger   [HTB]: Lindent
1179
  static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1181
  	if (!cl->level) {
547b792ca   Ilpo Järvinen   net: convert BUG_...
1182
  		WARN_ON(!cl->un.leaf.q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183
1184
  		qdisc_destroy(cl->un.leaf.q);
  	}
1c0d32fde   Eric Dumazet   net_sched: gen_es...
1185
  	gen_kill_estimator(&cl->rate_est);
6529eaba3   Jiri Pirko   net: sched: intro...
1186
  	tcf_block_put(cl->block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1187
1188
  	kfree(cl);
  }
87990467d   Stephen Hemminger   [HTB]: Lindent
1189
  static void htb_destroy(struct Qdisc *sch)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190
1191
  {
  	struct htb_sched *q = qdisc_priv(sch);
b67bfe0d4   Sasha Levin   hlist: drop the n...
1192
  	struct hlist_node *next;
fbd8f1379   Patrick McHardy   net-sched: sch_ht...
1193
1194
  	struct htb_class *cl;
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195

1224736d9   Jarek Poplawski   pkt_sched: sch_ht...
1196
  	cancel_work_sync(&q->work);
fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
1197
  	qdisc_watchdog_cancel(&q->watchdog);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1198
  	/* This line used to be after htb_destroy_class call below
cc7ec456f   Eric Dumazet   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   Jiri Pirko   net: sched: intro...
1203
  	tcf_block_put(q->block);
87990467d   Stephen Hemminger   [HTB]: Lindent
1204

f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1205
  	for (i = 0; i < q->clhash.hashsize; i++) {
898904226   Konstantin Khlebnikov   net_sched: reset ...
1206
  		hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode) {
6529eaba3   Jiri Pirko   net: sched: intro...
1207
  			tcf_block_put(cl->block);
898904226   Konstantin Khlebnikov   net_sched: reset ...
1208
1209
  			cl->block = NULL;
  		}
fbd8f1379   Patrick McHardy   net-sched: sch_ht...
1210
  	}
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1211
  	for (i = 0; i < q->clhash.hashsize; i++) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
1212
  		hlist_for_each_entry_safe(cl, next, &q->clhash.hash[i],
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1213
  					  common.hnode)
fbd8f1379   Patrick McHardy   net-sched: sch_ht...
1214
1215
  			htb_destroy_class(sch, cl);
  	}
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1216
  	qdisc_class_hash_destroy(&q->clhash);
a5a9f5346   Eric Dumazet   net_sched: sch_ht...
1217
  	__qdisc_reset_queue(&q->direct_queue);
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
1223
  	struct htb_class *cl = (struct htb_class *)arg;
160d5e10f   Jarek Poplawski   [NET_SCHED] sch_h...
1224
1225
  	struct Qdisc *new_q = NULL;
  	int last_child = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226

a071d2724   Yang Yingliang   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   Patrick McHardy   net-sched: sch_ht...
1231
  	if (cl->children || cl->filter_cnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1232
  		return -EBUSY;
87990467d   Stephen Hemminger   [HTB]: Lindent
1233

160d5e10f   Jarek Poplawski   [NET_SCHED] sch_h...
1234
  	if (!cl->level && htb_parent_last_child(cl)) {
3511c9132   Changli Gao   net_sched: remove...
1235
  		new_q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
bb949fbd1   David S. Miller   netdev: Create ne...
1236
  					  cl->parent->common.classid);
160d5e10f   Jarek Poplawski   [NET_SCHED] sch_h...
1237
1238
  		last_child = 1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1239
  	sch_tree_lock(sch);
87990467d   Stephen Hemminger   [HTB]: Lindent
1240

814a175e7   Patrick McHardy   [NET_SCHED]: sch_...
1241
  	if (!cl->level) {
2ccccf5fb   WANG Cong   net_sched: update...
1242
1243
  		unsigned int qlen = cl->un.leaf.q->q.qlen;
  		unsigned int backlog = cl->un.leaf.q->qstats.backlog;
814a175e7   Patrick McHardy   [NET_SCHED]: sch_...
1244
  		qdisc_reset(cl->un.leaf.q);
2ccccf5fb   WANG Cong   net_sched: update...
1245
  		qdisc_tree_reduce_backlog(cl->un.leaf.q, qlen, backlog);
814a175e7   Patrick McHardy   [NET_SCHED]: sch_...
1246
  	}
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1247
1248
  	/* delete from hash and active; remainder in destroy_class */
  	qdisc_class_hash_remove(&q->clhash, &cl->common);
26b284de5   Jarek Poplawski   pkt_sched: Fix oo...
1249
1250
  	if (cl->parent)
  		cl->parent->children--;
c38c83cb7   Patrick McHardy   [NET_SCHED]: sch_...
1251

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1252
  	if (cl->prio_activity)
87990467d   Stephen Hemminger   [HTB]: Lindent
1253
  		htb_deactivate(q, cl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254

fbd8f1379   Patrick McHardy   net-sched: sch_ht...
1255
  	if (cl->cmode != HTB_CAN_SEND)
c9364636d   Eric Dumazet   htb: refactor str...
1256
1257
  		htb_safe_rb_erase(&cl->pq_node,
  				  &q->hlevel[cl->level].wait_pq);
fbd8f1379   Patrick McHardy   net-sched: sch_ht...
1258

160d5e10f   Jarek Poplawski   [NET_SCHED] sch_h...
1259
  	if (last_child)
3ba08b00e   Jarek Poplawski   sch_htb: remove f...
1260
  		htb_parent_to_leaf(q, cl, new_q);
160d5e10f   Jarek Poplawski   [NET_SCHED] sch_h...
1261

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1262
  	sch_tree_unlock(sch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1263

143976ce9   WANG Cong   net_sched: remove...
1264
1265
  	htb_destroy_class(sch, cl);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1266
  }
87990467d   Stephen Hemminger   [HTB]: Lindent
1267
  static int htb_change_class(struct Qdisc *sch, u32 classid,
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
1268
  			    u32 parentid, struct nlattr **tca,
87990467d   Stephen Hemminger   [HTB]: Lindent
1269
  			    unsigned long *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270
1271
1272
  {
  	int err = -EINVAL;
  	struct htb_sched *q = qdisc_priv(sch);
87990467d   Stephen Hemminger   [HTB]: Lindent
1273
  	struct htb_class *cl = (struct htb_class *)*arg, *parent;
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
1274
  	struct nlattr *opt = tca[TCA_OPTIONS];
6906f4ed6   Eric Dumazet   htb: add HTB_DIRE...
1275
  	struct nlattr *tb[TCA_HTB_MAX + 1];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1276
  	struct tc_htb_opt *hopt;
df62cdf34   Eric Dumazet   net_sched: htb: s...
1277
  	u64 rate64, ceil64;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278
1279
  
  	/* extract all subattrs from opt attr */
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
1280
1281
  	if (!opt)
  		goto failure;
fceb6435e   Johannes Berg   netlink: pass ext...
1282
  	err = nla_parse_nested(tb, TCA_HTB_MAX, opt, htb_policy, NULL);
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
1283
1284
1285
1286
  	if (err < 0)
  		goto failure;
  
  	err = -EINVAL;
27a3421e4   Patrick McHardy   [NET_SCHED]: Use ...
1287
  	if (tb[TCA_HTB_PARMS] == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
  		goto failure;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1289

87990467d   Stephen Hemminger   [HTB]: Lindent
1290
  	parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
1291
  	hopt = nla_data(tb[TCA_HTB_PARMS]);
196d97f6b   Eric Dumazet   htb: fix two bugs
1292
  	if (!hopt->rate.rate || !hopt->ceil.rate)
87990467d   Stephen Hemminger   [HTB]: Lindent
1293
  		goto failure;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1294

8a8e3d84b   Jesper Dangaard Brouer   net_sched: restor...
1295
  	/* Keeping backward compatible with rate_table based iproute2 tc */
6b1dd8560   Yang Yingliang   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   Jesper Dangaard Brouer   net_sched: restor...
1301

87990467d   Stephen Hemminger   [HTB]: Lindent
1302
  	if (!cl) {		/* new class */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1303
  		struct Qdisc *new_q;
3696f625e   Stephen Hemminger   [HTB]: rbtree cle...
1304
  		int prio;
ee39e10c2   Patrick McHardy   [NET_SCHED]: sch_...
1305
  		struct {
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
1306
  			struct nlattr		nla;
ee39e10c2   Patrick McHardy   [NET_SCHED]: sch_...
1307
1308
  			struct gnet_estimator	opt;
  		} est = {
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
1309
1310
1311
  			.nla = {
  				.nla_len	= nla_attr_size(sizeof(est.opt)),
  				.nla_type	= TCA_RATE,
ee39e10c2   Patrick McHardy   [NET_SCHED]: sch_...
1312
1313
1314
1315
1316
1317
1318
  			},
  			.opt = {
  				/* 4s interval, 16s averaging constant */
  				.interval	= 2,
  				.ewma_log	= 2,
  			},
  		};
3696f625e   Stephen Hemminger   [HTB]: rbtree cle...
1319

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
  		/* check for valid classid */
f64f9e719   Joe Perches   net: Move && and ...
1321
1322
  		if (!classid || TC_H_MAJ(classid ^ sch->handle) ||
  		    htb_find(classid, sch))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323
1324
1325
1326
  			goto failure;
  
  		/* check maximal depth */
  		if (parent && parent->parent && parent->parent->level < 2) {
cc7ec456f   Eric Dumazet   net_sched: cleanups
1327
1328
  			pr_err("htb: tree is too deep
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1329
1330
1331
  			goto failure;
  		}
  		err = -ENOBUFS;
cc7ec456f   Eric Dumazet   net_sched: cleanups
1332
1333
  		cl = kzalloc(sizeof(*cl), GFP_KERNEL);
  		if (!cl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1334
  			goto failure;
87990467d   Stephen Hemminger   [HTB]: Lindent
1335

6529eaba3   Jiri Pirko   net: sched: intro...
1336
1337
1338
1339
1340
  		err = tcf_block_get(&cl->block, &cl->filter_list);
  		if (err) {
  			kfree(cl);
  			goto failure;
  		}
64153ce0a   Eric Dumazet   net_sched: htb: d...
1341
  		if (htb_rate_est || tca[TCA_RATE]) {
22e0f8b93   John Fastabend   net: sched: make ...
1342
1343
  			err = gen_new_estimator(&cl->bstats, NULL,
  						&cl->rate_est,
edb09eb17   Eric Dumazet   net: sched: do no...
1344
1345
  						NULL,
  						qdisc_root_sleeping_running(sch),
64153ce0a   Eric Dumazet   net_sched: htb: d...
1346
1347
  						tca[TCA_RATE] ? : &est.nla);
  			if (err) {
6529eaba3   Jiri Pirko   net: sched: intro...
1348
  				tcf_block_put(cl->block);
64153ce0a   Eric Dumazet   net_sched: htb: d...
1349
1350
1351
  				kfree(cl);
  				goto failure;
  			}
71bcb09a5   Stephen Hemminger   tc: check for err...
1352
  		}
420775993   Patrick McHardy   net-sched: sch_ht...
1353
  		cl->children = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1354
  		INIT_LIST_HEAD(&cl->un.leaf.drop_list);
3696f625e   Stephen Hemminger   [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   Linus Torvalds   Linux-2.6.12-rc2
1359
1360
  
  		/* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
cc7ec456f   Eric Dumazet   net_sched: cleanups
1361
1362
1363
  		 * so that can't be used inside of sch_tree_lock
  		 * -- thanks to Karlis Peisenieks
  		 */
3511c9132   Changli Gao   net_sched: remove...
1364
  		new_q = qdisc_create_dflt(sch->dev_queue,
bb949fbd1   David S. Miller   netdev: Create ne...
1365
  					  &pfifo_qdisc_ops, classid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366
1367
  		sch_tree_lock(sch);
  		if (parent && !parent->level) {
256d61b87   Patrick McHardy   [NET_SCHED]: Fix ...
1368
  			unsigned int qlen = parent->un.leaf.q->q.qlen;
2ccccf5fb   WANG Cong   net_sched: update...
1369
  			unsigned int backlog = parent->un.leaf.q->qstats.backlog;
256d61b87   Patrick McHardy   [NET_SCHED]: Fix ...
1370

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
  			/* turn parent into inner node */
256d61b87   Patrick McHardy   [NET_SCHED]: Fix ...
1372
  			qdisc_reset(parent->un.leaf.q);
2ccccf5fb   WANG Cong   net_sched: update...
1373
  			qdisc_tree_reduce_backlog(parent->un.leaf.q, qlen, backlog);
87990467d   Stephen Hemminger   [HTB]: Lindent
1374
1375
1376
  			qdisc_destroy(parent->un.leaf.q);
  			if (parent->prio_activity)
  				htb_deactivate(q, parent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1377
1378
1379
  
  			/* remove from evt list because of level change */
  			if (parent->cmode != HTB_CAN_SEND) {
c9364636d   Eric Dumazet   htb: refactor str...
1380
  				htb_safe_rb_erase(&parent->pq_node, &q->hlevel[0].wait_pq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1381
1382
1383
  				parent->cmode = HTB_CAN_SEND;
  			}
  			parent->level = (parent->parent ? parent->parent->level
87990467d   Stephen Hemminger   [HTB]: Lindent
1384
1385
  					 : TC_HTB_MAXDEPTH) - 1;
  			memset(&parent->un.inner, 0, sizeof(parent->un.inner));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1386
1387
1388
  		}
  		/* leaf (we) needs elementary qdisc */
  		cl->un.leaf.q = new_q ? new_q : &noop_qdisc;
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1389
  		cl->common.classid = classid;
87990467d   Stephen Hemminger   [HTB]: Lindent
1390
  		cl->parent = parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1391
1392
  
  		/* set class to be in HTB_CAN_SEND state */
b9a7afdef   Jiri Pirko   htb: initialize c...
1393
1394
  		cl->tokens = PSCHED_TICKS2NS(hopt->buffer);
  		cl->ctokens = PSCHED_TICKS2NS(hopt->cbuffer);
5343a7f8b   Eric Dumazet   net_sched: htb: d...
1395
  		cl->mbuffer = 60ULL * NSEC_PER_SEC;	/* 1min */
d2de875c6   Eric Dumazet   net: use ktime_ge...
1396
  		cl->t_c = ktime_get_ns();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397
1398
1399
  		cl->cmode = HTB_CAN_SEND;
  
  		/* attach to the hash list and parent's family */
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1400
  		qdisc_class_hash_insert(&q->clhash, &cl->common);
420775993   Patrick McHardy   net-sched: sch_ht...
1401
1402
  		if (parent)
  			parent->children++;
49b499718   Jiri Kosina   net: sched: make ...
1403
1404
  		if (cl->un.leaf.q != &noop_qdisc)
  			qdisc_hash_add(cl->un.leaf.q, true);
ee39e10c2   Patrick McHardy   [NET_SCHED]: sch_...
1405
  	} else {
71bcb09a5   Stephen Hemminger   tc: check for err...
1406
  		if (tca[TCA_RATE]) {
22e0f8b93   John Fastabend   net: sched: make ...
1407
1408
  			err = gen_replace_estimator(&cl->bstats, NULL,
  						    &cl->rate_est,
edb09eb17   Eric Dumazet   net: sched: do no...
1409
1410
  						    NULL,
  						    qdisc_root_sleeping_running(sch),
71bcb09a5   Stephen Hemminger   tc: check for err...
1411
1412
1413
1414
  						    tca[TCA_RATE]);
  			if (err)
  				return err;
  		}
87990467d   Stephen Hemminger   [HTB]: Lindent
1415
  		sch_tree_lock(sch);
ee39e10c2   Patrick McHardy   [NET_SCHED]: sch_...
1416
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417

1598f7cb4   Yang Yingliang   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   Linus Torvalds   Linux-2.6.12-rc2
1424
  	/* it used to be a nasty bug here, we have to check that node
cc7ec456f   Eric Dumazet   net_sched: cleanups
1425
1426
  	 * is really leaf before changing cl->un.leaf !
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1427
  	if (!cl->level) {
1598f7cb4   Yang Yingliang   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   Jarek Poplawski   pkt_sched: sch_ht...
1432
  		if (!hopt->quantum && cl->quantum < 1000) {
c17988a90   Yang Yingliang   net_sched: replac...
1433
1434
1435
  			pr_warn("HTB: quantum of class %X is small. Consider r2q change.
  ",
  				cl->common.classid);
c19f7a34f   Jarek Poplawski   pkt_sched: sch_ht...
1436
  			cl->quantum = 1000;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437
  		}
c19f7a34f   Jarek Poplawski   pkt_sched: sch_ht...
1438
  		if (!hopt->quantum && cl->quantum > 200000) {
c17988a90   Yang Yingliang   net_sched: replac...
1439
1440
1441
  			pr_warn("HTB: quantum of class %X is big. Consider r2q change.
  ",
  				cl->common.classid);
c19f7a34f   Jarek Poplawski   pkt_sched: sch_ht...
1442
  			cl->quantum = 200000;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1443
1444
  		}
  		if (hopt->quantum)
c19f7a34f   Jarek Poplawski   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   Linus Torvalds   Linux-2.6.12-rc2
1448
  	}
324f5aa52   Jiri Pirko   htb: use PSCHED_T...
1449
  	cl->buffer = PSCHED_TICKS2NS(hopt->buffer);
f3ad857e3   Vimalkumar   net_sched: htb: f...
1450
  	cl->cbuffer = PSCHED_TICKS2NS(hopt->cbuffer);
56b765b79   Vimalkumar   htb: improved acc...
1451

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1452
  	sch_tree_unlock(sch);
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1453
  	qdisc_class_hash_grow(sch, &q->clhash);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1454
1455
1456
1457
  	*arg = (unsigned long)cl;
  	return 0;
  
  failure:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1458
1459
  	return err;
  }
6529eaba3   Jiri Pirko   net: sched: intro...
1460
  static struct tcf_block *htb_tcf_block(struct Qdisc *sch, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1461
1462
1463
  {
  	struct htb_sched *q = qdisc_priv(sch);
  	struct htb_class *cl = (struct htb_class *)arg;
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
1464

6529eaba3   Jiri Pirko   net: sched: intro...
1465
  	return cl ? cl->block : q->block;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1466
1467
1468
  }
  
  static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent,
87990467d   Stephen Hemminger   [HTB]: Lindent
1469
  				     u32 classid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1470
  {
87990467d   Stephen Hemminger   [HTB]: Lindent
1471
  	struct htb_class *cl = htb_find(classid, sch);
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
1472

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1473
  	/*if (cl && !cl->level) return 0;
cc7ec456f   Eric Dumazet   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   Linus Torvalds   Linux-2.6.12-rc2
1481
  	 */
87990467d   Stephen Hemminger   [HTB]: Lindent
1482
1483
  	if (cl)
  		cl->filter_cnt++;
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
1489
  	struct htb_class *cl = (struct htb_class *)arg;
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
1490

87990467d   Stephen Hemminger   [HTB]: Lindent
1491
1492
  	if (cl)
  		cl->filter_cnt--;
1da177e4c   Linus Torvalds   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   Patrick McHardy   net-sched: sch_ht...
1498
  	struct htb_class *cl;
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1499
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1500
1501
1502
  
  	if (arg->stop)
  		return;
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1503
  	for (i = 0; i < q->clhash.hashsize; i++) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
1504
  		hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode) {
1da177e4c   Linus Torvalds   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   Eric Dumazet   [NET]: Move Qdisc...
1517
  static const struct Qdisc_class_ops htb_class_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1518
1519
  	.graft		=	htb_graft,
  	.leaf		=	htb_leaf,
256d61b87   Patrick McHardy   [NET_SCHED]: Fix ...
1520
  	.qlen_notify	=	htb_qlen_notify,
143976ce9   WANG Cong   net_sched: remove...
1521
  	.find		=	htb_search,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1522
1523
1524
  	.change		=	htb_change_class,
  	.delete		=	htb_delete,
  	.walk		=	htb_walk,
6529eaba3   Jiri Pirko   net: sched: intro...
1525
  	.tcf_block	=	htb_tcf_block,
1da177e4c   Linus Torvalds   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   Eric Dumazet   [NET]: Move Qdisc...
1531
  static struct Qdisc_ops htb_qdisc_ops __read_mostly = {
1da177e4c   Linus Torvalds   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   Jarek Poplawski   pkt_sched: Add pe...
1537
  	.peek		=	qdisc_peek_dequeued,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1538
1539
1540
  	.init		=	htb_init,
  	.reset		=	htb_reset,
  	.destroy	=	htb_destroy,
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [HTB]: Lindent
1547
  	return register_qdisc(&htb_qdisc_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1548
  }
87990467d   Stephen Hemminger   [HTB]: Lindent
1549
  static void __exit htb_module_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
  {
87990467d   Stephen Hemminger   [HTB]: Lindent
1551
  	unregister_qdisc(&htb_qdisc_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1552
  }
87990467d   Stephen Hemminger   [HTB]: Lindent
1553

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1554
1555
1556
  module_init(htb_module_init)
  module_exit(htb_module_exit)
  MODULE_LICENSE("GPL");