Blame view

net/sched/sch_htb.c 42.6 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>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
46
47
  
  /* 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 ...
48
      it allows to assign priority to each class in hierarchy.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
      In fact it is another implementation of Floyd's formal sharing.
  
      Levels:
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
52
      Each class is assigned level. Leaf has ALWAYS level 0 and root
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
55
      classes have level TC_HTB_MAXDEPTH-1. Interior nodes has level
      one less than their parent.
  */
47083fc07   Jesper Dangaard Brouer   pkt_sched: Change...
56
  static int htb_hysteresis __read_mostly = 0; /* whether to use mode hysteresis for speedup */
87990467d   Stephen Hemminger   [HTB]: Lindent
57
  #define HTB_VER 0x30011		/* major must be matched with number suplied by TC as version */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
  
  #if HTB_VER >> 16 != TC_HTB_PROTOVER
  #error "Mismatched sch_htb.c and pkt_sch.h"
  #endif
47083fc07   Jesper Dangaard Brouer   pkt_sched: Change...
62
63
64
  /* 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...
65
66
67
  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
68
69
  /* used internaly to keep status of single class */
  enum htb_cmode {
87990467d   Stephen Hemminger   [HTB]: Lindent
70
71
72
  	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
73
  };
c9364636d   Eric Dumazet   htb: refactor str...
74
75
76
77
78
79
80
81
82
83
84
85
86
  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...
87
88
89
90
  /* 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
91
  struct htb_class {
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
92
  	struct Qdisc_class_common common;
ca4ec90b3   Eric Dumazet   htb: reorder stru...
93
94
95
96
  	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...
97
  	u32			prio;		/* these two are used only by leaves... */
ca4ec90b3   Eric Dumazet   htb: reorder stru...
98
  	int			quantum;	/* but stored for parent-to-leaf return */
25d8c0d55   John Fastabend   net: rcu-ify tcf_...
99
  	struct tcf_proto __rcu	*filter_list;	/* class attached filters */
ca4ec90b3   Eric Dumazet   htb: reorder stru...
100
101
102
103
104
105
  	int			filter_cnt;
  	int			refcnt;		/* usage count of this class */
  
  	int			level;		/* our level (see above) */
  	unsigned int		children;
  	struct htb_class	*parent;	/* parent class */
45203a3b3   Eric Dumazet   net_sched: add 64...
106
  	struct gnet_stats_rate_est64 rate_est;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107

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

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

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

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

c9364636d   Eric Dumazet   htb: refactor str...
146
  	/* filters for qdisc itself */
25d8c0d55   John Fastabend   net: rcu-ify tcf_...
147
  	struct tcf_proto __rcu	*filter_list;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148

c9364636d   Eric Dumazet   htb: refactor str...
149
150
151
152
  #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
153

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

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

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

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

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

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

f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
176
177
  	clc = qdisc_class_find(&q->clhash, handle);
  	if (clc == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
  		return NULL;
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
179
  	return container_of(clc, struct htb_class, common);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
183
184
185
186
187
188
189
  }
  
  /**
   * 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 ...
190
   * internal fifo (direct). These packets then go directly thru. If we still
25985edce   Lucas De Marchi   Fix common misspe...
191
   * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessful
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
   * then finish and return direct queue.
   */
cc7ec456f   Eric Dumazet   net_sched: cleanups
194
  #define HTB_DIRECT ((struct htb_class *)-1L)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  	while (*p) {
87990467d   Stephen Hemminger   [HTB]: Lindent
264
265
  		struct htb_class *c;
  		parent = *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
  		c = rb_entry(parent, struct htb_class, node[prio]);
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
267

f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
268
  		if (cl->common.classid > c->common.classid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  			p = &parent->rb_right;
87990467d   Stephen Hemminger   [HTB]: Lindent
270
  		else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
274
275
276
277
278
279
280
281
282
283
  			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
284
  static void htb_add_to_wait_tree(struct htb_sched *q,
56b765b79   Vimalkumar   htb: improved acc...
285
  				 struct htb_class *cl, s64 delay)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
  {
c9364636d   Eric Dumazet   htb: refactor str...
287
  	struct rb_node **p = &q->hlevel[cl->level].wait_pq.rb_node, *parent = NULL;
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
288

fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
289
290
  	cl->pq_key = q->now + delay;
  	if (cl->pq_key == q->now)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
293
  		cl->pq_key++;
  
  	/* update the nearest event cache */
fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
294
  	if (q->near_ev_cache[cl->level] > cl->pq_key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
  		q->near_ev_cache[cl->level] = cl->pq_key;
87990467d   Stephen Hemminger   [HTB]: Lindent
296

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
  	while (*p) {
87990467d   Stephen Hemminger   [HTB]: Lindent
298
299
  		struct htb_class *c;
  		parent = *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
  		c = rb_entry(parent, struct htb_class, pq_node);
fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
301
  		if (cl->pq_key >= c->pq_key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
  			p = &parent->rb_right;
87990467d   Stephen Hemminger   [HTB]: Lindent
303
  		else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
306
  			p = &parent->rb_left;
  	}
  	rb_link_node(&cl->pq_node, parent, p);
c9364636d   Eric Dumazet   htb: refactor str...
307
  	rb_insert_color(&cl->pq_node, &q->hlevel[cl->level].wait_pq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
309
310
311
312
313
314
315
  }
  
  /**
   * 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...
316
  static inline void htb_next_rb_node(struct rb_node **n)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
319
320
321
322
323
324
325
326
  {
  	*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
327
328
  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
329
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
331
332
333
  	q->row_mask[cl->level] |= mask;
  	while (mask) {
  		int prio = ffz(~mask);
  		mask &= ~(1 << prio);
c9364636d   Eric Dumazet   htb: refactor str...
334
  		htb_add_to_id_tree(&q->hlevel[cl->level].hprio[prio].row, cl, prio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
  	}
  }
3696f625e   Stephen Hemminger   [HTB]: rbtree cle...
337
338
339
  /* 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...
340
  	if (RB_EMPTY_NODE(rb)) {
3696f625e   Stephen Hemminger   [HTB]: rbtree cle...
341
342
343
344
345
346
  		WARN_ON(1);
  	} else {
  		rb_erase(rb, root);
  		RB_CLEAR_NODE(rb);
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
348
349
350
351
352
  /**
   * 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
353
354
  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
355
356
  {
  	int m = 0;
c9364636d   Eric Dumazet   htb: refactor str...
357
  	struct htb_level *hlevel = &q->hlevel[cl->level];
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
358

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

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

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

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

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

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

c9364636d   Eric Dumazet   htb: refactor str...
428
  			if (p->un.inner.clprio[prio].ptr == cl->node + prio) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
  				/* we are removing child which is pointed to from
cc7ec456f   Eric Dumazet   net_sched: cleanups
430
431
432
  				 * parent feed - forget the pointer but remember
  				 * classid
  				 */
c9364636d   Eric Dumazet   htb: refactor str...
433
434
  				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
435
  			}
87990467d   Stephen Hemminger   [HTB]: Lindent
436

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

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

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
471
472
  /**
   * 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 ...
473
   * from now to time when cl will change its state.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
   * Also it is worth to note that class mode doesn't change simply
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
475
   * at cl->{c,}tokens == 0 but there can rather be hysteresis of
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
477
478
   * 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
479
  static inline enum htb_cmode
56b765b79   Vimalkumar   htb: improved acc...
480
  htb_class_mode(struct htb_class *cl, s64 *diff)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
  {
56b765b79   Vimalkumar   htb: improved acc...
482
  	s64 toks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483

87990467d   Stephen Hemminger   [HTB]: Lindent
484
485
486
487
  	if ((toks = (cl->ctokens + *diff)) < htb_lowater(cl)) {
  		*diff = -toks;
  		return HTB_CANT_SEND;
  	}
18a63e868   Stephen Hemminger   [HTB]: HTB_HYSTER...
488

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

87990467d   Stephen Hemminger   [HTB]: Lindent
492
493
  	*diff = -toks;
  	return HTB_MAY_BORROW;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
495
496
497
498
499
500
501
502
503
504
  }
  
  /**
   * 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
505
  static void
56b765b79   Vimalkumar   htb: improved acc...
506
  htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, s64 *diff)
87990467d   Stephen Hemminger   [HTB]: Lindent
507
508
  {
  	enum htb_cmode new_mode = htb_class_mode(cl, diff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
510
  
  	if (new_mode == cl->cmode)
87990467d   Stephen Hemminger   [HTB]: Lindent
511
512
513
514
515
  		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
516
  		cl->cmode = new_mode;
87990467d   Stephen Hemminger   [HTB]: Lindent
517
518
519
  		if (new_mode != HTB_CANT_SEND)
  			htb_activate_prios(q, cl);
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
522
523
  		cl->cmode = new_mode;
  }
  
  /**
10297b993   YOSHIFUJI Hideaki   [NET] SCHED: Fix ...
524
   * htb_activate - inserts leaf cl into appropriate active feeds
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
526
527
528
529
   *
   * 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
530
  static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
  {
547b792ca   Ilpo Järvinen   net: convert BUG_...
532
  	WARN_ON(cl->level || !cl->un.leaf.q || !cl->un.leaf.q->q.qlen);
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
533

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

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

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

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

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

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

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

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894
895
896
  	for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
  		/* common case optimization - skip event handler quickly */
  		int m;
c9364636d   Eric Dumazet   htb: refactor str...
897
  		s64 event = q->near_ev_cache[level];
fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
898

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

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

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

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

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

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

f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
994
995
996
  	err = qdisc_class_hash_init(&q->clhash);
  	if (err < 0)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
997
  	for (i = 0; i < TC_HTB_NUMPRIO; i++)
87990467d   Stephen Hemminger   [HTB]: Lindent
998
  		INIT_LIST_HEAD(q->drops + i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
999

fb983d457   Patrick McHardy   [NET_SCHED]: sch_...
1000
  	qdisc_watchdog_init(&q->watchdog, sch);
1224736d9   Jarek Poplawski   pkt_sched: sch_ht...
1001
  	INIT_WORK(&q->work, htb_work_func);
48da34b7a   Florian Westphal   sched: add and us...
1002
  	qdisc_skb_head_init(&q->direct_queue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1003

6906f4ed6   Eric Dumazet   htb: add HTB_DIRE...
1004
1005
  	if (tb[TCA_HTB_DIRECT_QLEN])
  		q->direct_qlen = nla_get_u32(tb[TCA_HTB_DIRECT_QLEN]);
348e3435c   Phil Sutter   net: sched: drop ...
1006
  	else
6906f4ed6   Eric Dumazet   htb: add HTB_DIRE...
1007
  		q->direct_qlen = qdisc_dev(sch)->tx_queue_len;
348e3435c   Phil Sutter   net: sched: drop ...
1008

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
  	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 ...
1019
  	struct nlattr *nest;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1020
  	struct tc_htb_glob gopt;
4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1021

6f542efcb   Eric Dumazet   net_sched: htb: d...
1022
1023
1024
  	/* 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
1025

4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1026
  	gopt.direct_pkts = q->direct_pkts;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027
1028
1029
  	gopt.version = HTB_VER;
  	gopt.rate2quantum = q->rate2quantum;
  	gopt.defcls = q->defcls;
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
1030
  	gopt.debug = 0;
4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1031
1032
1033
1034
  
  	nest = nla_nest_start(skb, TCA_OPTIONS);
  	if (nest == NULL)
  		goto nla_put_failure;
6906f4ed6   Eric Dumazet   htb: add HTB_DIRE...
1035
1036
  	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...
1037
  		goto nla_put_failure;
4b3550ef5   Patrick McHardy   [NET_SCHED]: Use ...
1038

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

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

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

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

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

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

338ed9b4d   Eric Dumazet   net_sched: sch_ht...
1099
  	if (!cl->level && cl->un.leaf.q) {
640158536   John Fastabend   net: sched: restr...
1100
  		qlen = cl->un.leaf.q->q.qlen;
338ed9b4d   Eric Dumazet   net_sched: sch_ht...
1101
1102
  		qs.backlog = cl->un.leaf.q->qstats.backlog;
  	}
0564bf0af   Konstantin Khlebnikov   net/sched/sch_htb...
1103
1104
1105
1106
  	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
1107

edb09eb17   Eric Dumazet   net: sched: do no...
1108
1109
  	if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
  				  d, NULL, &cl->bstats) < 0 ||
d250a5f90   Eric Dumazet   pkt_sched: gen_es...
1110
  	    gnet_stats_copy_rate_est(d, NULL, &cl->rate_est) < 0 ||
338ed9b4d   Eric Dumazet   net_sched: sch_ht...
1111
  	    gnet_stats_copy_queue(d, NULL, &qs, qlen) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112
1113
1114
1115
1116
1117
  		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
1118
  		     struct Qdisc **old)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119
  {
87990467d   Stephen Hemminger   [HTB]: Lindent
1120
  	struct htb_class *cl = (struct htb_class *)arg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1121

5b9a9ccfa   Patrick McHardy   net_sched: remove...
1122
1123
1124
  	if (cl->level)
  		return -EINVAL;
  	if (new == NULL &&
3511c9132   Changli Gao   net_sched: remove...
1125
  	    (new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
5b9a9ccfa   Patrick McHardy   net_sched: remove...
1126
1127
  				     cl->common.classid)) == NULL)
  		return -ENOBUFS;
86a7996cc   WANG Cong   net_sched: introd...
1128
  	*old = qdisc_replace(sch, new, &cl->un.leaf.q);
5b9a9ccfa   Patrick McHardy   net_sched: remove...
1129
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130
  }
87990467d   Stephen Hemminger   [HTB]: Lindent
1131
  static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132
  {
87990467d   Stephen Hemminger   [HTB]: Lindent
1133
  	struct htb_class *cl = (struct htb_class *)arg;
5b9a9ccfa   Patrick McHardy   net_sched: remove...
1134
  	return !cl->level ? cl->un.leaf.q : NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
  }
256d61b87   Patrick McHardy   [NET_SCHED]: Fix ...
1136
1137
1138
1139
1140
1141
1142
  static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg)
  {
  	struct htb_class *cl = (struct htb_class *)arg;
  
  	if (cl->un.leaf.q->q.qlen == 0)
  		htb_deactivate(qdisc_priv(sch), cl);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143
1144
  static unsigned long htb_get(struct Qdisc *sch, u32 classid)
  {
87990467d   Stephen Hemminger   [HTB]: Lindent
1145
1146
  	struct htb_class *cl = htb_find(classid, sch);
  	if (cl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1147
1148
1149
  		cl->refcnt++;
  	return (unsigned long)cl;
  }
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);
  	}
ee39e10c2   Patrick McHardy   [NET_SCHED]: sch_...
1185
  	gen_kill_estimator(&cl->bstats, &cl->rate_est);
ff31ab56c   Patrick McHardy   net-sched: change...
1186
  	tcf_destroy_chain(&cl->filter_list);
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).
  	 */
ff31ab56c   Patrick McHardy   net-sched: change...
1203
  	tcf_destroy_chain(&q->filter_list);
87990467d   Stephen Hemminger   [HTB]: Lindent
1204

f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1205
  	for (i = 0; i < q->clhash.hashsize; i++) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
1206
  		hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode)
fbd8f1379   Patrick McHardy   net-sched: sch_ht...
1207
1208
  			tcf_destroy_chain(&cl->filter_list);
  	}
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1209
  	for (i = 0; i < q->clhash.hashsize; i++) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
1210
  		hlist_for_each_entry_safe(cl, next, &q->clhash.hash[i],
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1211
  					  common.hnode)
fbd8f1379   Patrick McHardy   net-sched: sch_ht...
1212
1213
  			htb_destroy_class(sch, cl);
  	}
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1214
  	qdisc_class_hash_destroy(&q->clhash);
a5a9f5346   Eric Dumazet   net_sched: sch_ht...
1215
  	__qdisc_reset_queue(&q->direct_queue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1216
1217
1218
1219
1220
  }
  
  static int htb_delete(struct Qdisc *sch, unsigned long arg)
  {
  	struct htb_sched *q = qdisc_priv(sch);
87990467d   Stephen Hemminger   [HTB]: Lindent
1221
  	struct htb_class *cl = (struct htb_class *)arg;
160d5e10f   Jarek Poplawski   [NET_SCHED] sch_h...
1222
1223
  	struct Qdisc *new_q = NULL;
  	int last_child = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224

a071d2724   Yang Yingliang   sch_htb: use /* c...
1225
1226
1227
1228
  	/* 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...
1229
  	if (cl->children || cl->filter_cnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1230
  		return -EBUSY;
87990467d   Stephen Hemminger   [HTB]: Lindent
1231

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

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

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

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

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

7cd0a6387   Jarek Poplawski   pkt_sched: Change...
1260
1261
1262
1263
1264
  	BUG_ON(--cl->refcnt == 0);
  	/*
  	 * This shouldn't happen: we "hold" one cops->get() when called
  	 * from tc_ctl_tclass; the destroy method is done from cops->put().
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1265
1266
1267
1268
1269
1270
1271
  
  	sch_tree_unlock(sch);
  	return 0;
  }
  
  static void htb_put(struct Qdisc *sch, unsigned long arg)
  {
87990467d   Stephen Hemminger   [HTB]: Lindent
1272
  	struct htb_class *cl = (struct htb_class *)arg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273
1274
  
  	if (--cl->refcnt == 0)
87990467d   Stephen Hemminger   [HTB]: Lindent
1275
  		htb_destroy_class(sch, cl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1276
  }
87990467d   Stephen Hemminger   [HTB]: Lindent
1277
  static int htb_change_class(struct Qdisc *sch, u32 classid,
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
1278
  			    u32 parentid, struct nlattr **tca,
87990467d   Stephen Hemminger   [HTB]: Lindent
1279
  			    unsigned long *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1280
1281
1282
  {
  	int err = -EINVAL;
  	struct htb_sched *q = qdisc_priv(sch);
87990467d   Stephen Hemminger   [HTB]: Lindent
1283
  	struct htb_class *cl = (struct htb_class *)*arg, *parent;
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
1284
  	struct nlattr *opt = tca[TCA_OPTIONS];
6906f4ed6   Eric Dumazet   htb: add HTB_DIRE...
1285
  	struct nlattr *tb[TCA_HTB_MAX + 1];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1286
  	struct tc_htb_opt *hopt;
df62cdf34   Eric Dumazet   net_sched: htb: s...
1287
  	u64 rate64, ceil64;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
1289
  
  	/* extract all subattrs from opt attr */
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
1290
1291
  	if (!opt)
  		goto failure;
e18434c45   Changli Gao   net_sched: use __...
1292
  	err = nla_parse_nested(tb, TCA_HTB_MAX, opt, htb_policy);
cee63723b   Patrick McHardy   [NET_SCHED]: Prop...
1293
1294
1295
1296
  	if (err < 0)
  		goto failure;
  
  	err = -EINVAL;
27a3421e4   Patrick McHardy   [NET_SCHED]: Use ...
1297
  	if (tb[TCA_HTB_PARMS] == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1298
  		goto failure;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1299

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

8a8e3d84b   Jesper Dangaard Brouer   net_sched: restor...
1305
  	/* Keeping backward compatible with rate_table based iproute2 tc */
6b1dd8560   Yang Yingliang   sch_htb: remove u...
1306
1307
1308
1309
1310
  	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...
1311

87990467d   Stephen Hemminger   [HTB]: Lindent
1312
  	if (!cl) {		/* new class */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1313
  		struct Qdisc *new_q;
3696f625e   Stephen Hemminger   [HTB]: rbtree cle...
1314
  		int prio;
ee39e10c2   Patrick McHardy   [NET_SCHED]: sch_...
1315
  		struct {
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
1316
  			struct nlattr		nla;
ee39e10c2   Patrick McHardy   [NET_SCHED]: sch_...
1317
1318
  			struct gnet_estimator	opt;
  		} est = {
1e90474c3   Patrick McHardy   [NET_SCHED]: Conv...
1319
1320
1321
  			.nla = {
  				.nla_len	= nla_attr_size(sizeof(est.opt)),
  				.nla_type	= TCA_RATE,
ee39e10c2   Patrick McHardy   [NET_SCHED]: sch_...
1322
1323
1324
1325
1326
1327
1328
  			},
  			.opt = {
  				/* 4s interval, 16s averaging constant */
  				.interval	= 2,
  				.ewma_log	= 2,
  			},
  		};
3696f625e   Stephen Hemminger   [HTB]: rbtree cle...
1329

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1330
  		/* check for valid classid */
f64f9e719   Joe Perches   net: Move && and ...
1331
1332
  		if (!classid || TC_H_MAJ(classid ^ sch->handle) ||
  		    htb_find(classid, sch))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333
1334
1335
1336
  			goto failure;
  
  		/* check maximal depth */
  		if (parent && parent->parent && parent->parent->level < 2) {
cc7ec456f   Eric Dumazet   net_sched: cleanups
1337
1338
  			pr_err("htb: tree is too deep
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1339
1340
1341
  			goto failure;
  		}
  		err = -ENOBUFS;
cc7ec456f   Eric Dumazet   net_sched: cleanups
1342
1343
  		cl = kzalloc(sizeof(*cl), GFP_KERNEL);
  		if (!cl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1344
  			goto failure;
87990467d   Stephen Hemminger   [HTB]: Lindent
1345

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1455
  	sch_tree_unlock(sch);
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1456
  	qdisc_class_hash_grow(sch, &q->clhash);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1457
1458
1459
1460
  	*arg = (unsigned long)cl;
  	return 0;
  
  failure:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1461
1462
  	return err;
  }
25d8c0d55   John Fastabend   net: rcu-ify tcf_...
1463
1464
  static struct tcf_proto __rcu **htb_find_tcf(struct Qdisc *sch,
  					     unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1465
1466
1467
  {
  	struct htb_sched *q = qdisc_priv(sch);
  	struct htb_class *cl = (struct htb_class *)arg;
25d8c0d55   John Fastabend   net: rcu-ify tcf_...
1468
  	struct tcf_proto __rcu **fl = cl ? &cl->filter_list : &q->filter_list;
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
1469

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1470
1471
1472
1473
  	return fl;
  }
  
  static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent,
87990467d   Stephen Hemminger   [HTB]: Lindent
1474
  				     u32 classid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1475
  {
87990467d   Stephen Hemminger   [HTB]: Lindent
1476
  	struct htb_class *cl = htb_find(classid, sch);
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
1477

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
  	/*if (cl && !cl->level) return 0;
cc7ec456f   Eric Dumazet   net_sched: cleanups
1479
1480
1481
1482
1483
1484
1485
  	 * 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
1486
  	 */
87990467d   Stephen Hemminger   [HTB]: Lindent
1487
1488
  	if (cl)
  		cl->filter_cnt++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1489
1490
1491
1492
1493
  	return (unsigned long)cl;
  }
  
  static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1494
  	struct htb_class *cl = (struct htb_class *)arg;
3bf72957d   Stephen Hemminger   [HTB]: Remove bro...
1495

87990467d   Stephen Hemminger   [HTB]: Lindent
1496
1497
  	if (cl)
  		cl->filter_cnt--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1498
1499
1500
1501
1502
  }
  
  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...
1503
  	struct htb_class *cl;
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1504
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1505
1506
1507
  
  	if (arg->stop)
  		return;
f4c1f3e0c   Patrick McHardy   net-sched: sch_ht...
1508
  	for (i = 0; i < q->clhash.hashsize; i++) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
1509
  		hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
  			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...
1522
  static const struct Qdisc_class_ops htb_class_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1523
1524
  	.graft		=	htb_graft,
  	.leaf		=	htb_leaf,
256d61b87   Patrick McHardy   [NET_SCHED]: Fix ...
1525
  	.qlen_notify	=	htb_qlen_notify,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
  	.get		=	htb_get,
  	.put		=	htb_put,
  	.change		=	htb_change_class,
  	.delete		=	htb_delete,
  	.walk		=	htb_walk,
  	.tcf_chain	=	htb_find_tcf,
  	.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...
1537
  static struct Qdisc_ops htb_qdisc_ops __read_mostly = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1538
1539
1540
1541
1542
  	.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...
1543
  	.peek		=	qdisc_peek_dequeued,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1544
1545
1546
  	.init		=	htb_init,
  	.reset		=	htb_reset,
  	.destroy	=	htb_destroy,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1547
1548
1549
1550
1551
1552
  	.dump		=	htb_dump,
  	.owner		=	THIS_MODULE,
  };
  
  static int __init htb_module_init(void)
  {
87990467d   Stephen Hemminger   [HTB]: Lindent
1553
  	return register_qdisc(&htb_qdisc_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1554
  }
87990467d   Stephen Hemminger   [HTB]: Lindent
1555
  static void __exit htb_module_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1556
  {
87990467d   Stephen Hemminger   [HTB]: Lindent
1557
  	unregister_qdisc(&htb_qdisc_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1558
  }
87990467d   Stephen Hemminger   [HTB]: Lindent
1559

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1560
1561
1562
  module_init(htb_module_init)
  module_exit(htb_module_exit)
  MODULE_LICENSE("GPL");