sch_sfq.c 22.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * net/sched/sch_sfq.c	Stochastic Fairness Queueing discipline.
 *
 *		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:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
 */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/string.h>
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/skbuff.h>
21
#include <linux/jhash.h>
22
#include <linux/slab.h>
23
#include <linux/vmalloc.h>
24
#include <net/netlink.h>
L
Linus Torvalds 已提交
25
#include <net/pkt_sched.h>
26
#include <net/pkt_cls.h>
27
#include <net/red.h>
L
Linus Torvalds 已提交
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45


/*	Stochastic Fairness Queuing algorithm.
	=======================================

	Source:
	Paul E. McKenney "Stochastic Fairness Queuing",
	IEEE INFOCOMM'90 Proceedings, San Francisco, 1990.

	Paul E. McKenney "Stochastic Fairness Queuing",
	"Interworking: Research and Experience", v.2, 1991, p.113-131.


	See also:
	M. Shreedhar and George Varghese "Efficient Fair
	Queuing using Deficit Round Robin", Proc. SIGCOMM 95.


46
	This is not the thing that is usually called (W)FQ nowadays.
L
Linus Torvalds 已提交
47 48 49 50 51 52 53 54 55
	It does not use any timestamp mechanism, but instead
	processes queues in round-robin order.

	ADVANTAGE:

	- It is very cheap. Both CPU and memory requirements are minimal.

	DRAWBACKS:

56
	- "Stochastic" -> It is not 100% fair.
L
Linus Torvalds 已提交
57 58 59 60 61 62 63 64 65 66 67 68 69
	When hash collisions occur, several flows are considered as one.

	- "Round-robin" -> It introduces larger delays than virtual clock
	based schemes, and should not be used for isolating interactive
	traffic	from non-interactive. It means, that this scheduler
	should be used as leaf of CBQ or P3, which put interactive traffic
	to higher priority band.

	We still need true WFQ for top level CSZ, but using WFQ
	for the best effort traffic is absolutely pointless:
	SFQ is superior for this purpose.

	IMPLEMENTATION:
E
Eric Dumazet 已提交
70 71 72 73 74
	This implementation limits :
	- maximal queue length per flow to 127 packets.
	- max mtu to 2^18-1;
	- max 65408 flows,
	- number of hash buckets to 65536.
L
Linus Torvalds 已提交
75 76 77

	It is easy to increase these values, but not in flight.  */

E
Eric Dumazet 已提交
78 79 80 81
#define SFQ_MAX_DEPTH		127 /* max number of packets per flow */
#define SFQ_DEFAULT_FLOWS	128
#define SFQ_MAX_FLOWS		(0x10000 - SFQ_MAX_DEPTH - 1) /* max number of flows */
#define SFQ_EMPTY_SLOT		0xffff
82 83
#define SFQ_DEFAULT_HASH_DIVISOR 1024

84 85 86 87 88
/* We use 16 bits to store allot, and want to handle packets up to 64K
 * Scale allot by 8 (1<<3) so that no overflow occurs.
 */
#define SFQ_ALLOT_SHIFT		3
#define SFQ_ALLOT_SIZE(X)	DIV_ROUND_UP(X, 1 << SFQ_ALLOT_SHIFT)
L
Linus Torvalds 已提交
89

E
Eric Dumazet 已提交
90 91
/* This type should contain at least SFQ_MAX_DEPTH + 1 + SFQ_MAX_FLOWS values */
typedef u16 sfq_index;
L
Linus Torvalds 已提交
92

93 94
/*
 * We dont use pointers to save space.
E
Eric Dumazet 已提交
95 96
 * Small indexes [0 ... SFQ_MAX_FLOWS - 1] are 'pointers' to slots[] array
 * while following values [SFQ_MAX_FLOWS ... SFQ_MAX_FLOWS + SFQ_MAX_DEPTH]
97 98
 * are 'pointers' to dep[] array
 */
E
Eric Dumazet 已提交
99
struct sfq_head {
L
Linus Torvalds 已提交
100 101 102 103
	sfq_index	next;
	sfq_index	prev;
};

104 105 106 107
struct sfq_slot {
	struct sk_buff	*skblist_next;
	struct sk_buff	*skblist_prev;
	sfq_index	qlen; /* number of skbs in skblist */
E
Eric Dumazet 已提交
108
	sfq_index	next; /* next slot in sfq RR chain */
109 110 111
	struct sfq_head dep; /* anchor in dep[] chains */
	unsigned short	hash; /* hash value (index in ht[]) */
	short		allot; /* credit for this slot */
112 113 114

	unsigned int    backlog;
	struct red_vars vars;
115 116
};

E
Eric Dumazet 已提交
117
struct sfq_sched_data {
E
Eric Dumazet 已提交
118 119
/* frequently used fields */
	int		limit;		/* limit of total number of packets in this qdisc */
120
	unsigned int	divisor;	/* number of slots in hash table */
121 122
	u8		headdrop;
	u8		maxdepth;	/* limit of packets per flow */
E
Eric Dumazet 已提交
123

124
	u32		perturbation;
125 126
	u8		cur_depth;	/* depth of longest slot */
	u8		flags;
127
	unsigned short  scaled_quantum; /* SFQ_ALLOT_SIZE(quantum) */
J
John Fastabend 已提交
128
	struct tcf_proto __rcu *filter_list;
129
	struct tcf_block *block;
E
Eric Dumazet 已提交
130 131 132
	sfq_index	*ht;		/* Hash table ('divisor' slots) */
	struct sfq_slot	*slots;		/* Flows table ('maxflows' entries) */

133 134 135 136
	struct red_parms *red_parms;
	struct tc_sfqred_stats stats;
	struct sfq_slot *tail;		/* current slot in round */

E
Eric Dumazet 已提交
137 138 139 140 141 142 143
	struct sfq_head	dep[SFQ_MAX_DEPTH + 1];
					/* Linked lists of slots, indexed by depth
					 * dep[0] : list of unused flows
					 * dep[1] : list of flows with 1 packet
					 * dep[X] : list of flows with X packets
					 */

144
	unsigned int	maxflows;	/* number of flows in flows array */
E
Eric Dumazet 已提交
145 146 147
	int		perturb_period;
	unsigned int	quantum;	/* Allotment per round: MUST BE >= MTU */
	struct timer_list perturb_timer;
L
Linus Torvalds 已提交
148 149
};

150 151 152 153 154
/*
 * sfq_head are either in a sfq_slot or in dep[] array
 */
static inline struct sfq_head *sfq_dep_head(struct sfq_sched_data *q, sfq_index val)
{
E
Eric Dumazet 已提交
155
	if (val < SFQ_MAX_FLOWS)
156
		return &q->slots[val].dep;
E
Eric Dumazet 已提交
157
	return &q->dep[val - SFQ_MAX_FLOWS];
158 159
}

E
Eric Dumazet 已提交
160 161
static unsigned int sfq_hash(const struct sfq_sched_data *q,
			     const struct sk_buff *skb)
L
Linus Torvalds 已提交
162
{
163
	return skb_get_hash_perturb(skb, q->perturbation) & (q->divisor - 1);
L
Linus Torvalds 已提交
164 165
}

166 167 168 169 170
static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch,
				 int *qerr)
{
	struct sfq_sched_data *q = qdisc_priv(sch);
	struct tcf_result res;
J
John Fastabend 已提交
171
	struct tcf_proto *fl;
172 173 174 175
	int result;

	if (TC_H_MAJ(skb->priority) == sch->handle &&
	    TC_H_MIN(skb->priority) > 0 &&
176
	    TC_H_MIN(skb->priority) <= q->divisor)
177 178
		return TC_H_MIN(skb->priority);

J
John Fastabend 已提交
179
	fl = rcu_dereference_bh(q->filter_list);
180
	if (!fl)
181 182
		return sfq_hash(q, skb) + 1;

183
	*qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
184
	result = tcf_classify(skb, fl, &res, false);
185 186 187 188 189
	if (result >= 0) {
#ifdef CONFIG_NET_CLS_ACT
		switch (result) {
		case TC_ACT_STOLEN:
		case TC_ACT_QUEUED:
190
		case TC_ACT_TRAP:
191
			*qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
192 193 194 195
		case TC_ACT_SHOT:
			return 0;
		}
#endif
196
		if (TC_H_MIN(res.classid) <= q->divisor)
197 198 199 200 201
			return TC_H_MIN(res.classid);
	}
	return 0;
}

202
/*
E
Eric Dumazet 已提交
203
 * x : slot number [0 .. SFQ_MAX_FLOWS - 1]
204
 */
L
Linus Torvalds 已提交
205 206 207
static inline void sfq_link(struct sfq_sched_data *q, sfq_index x)
{
	sfq_index p, n;
E
Eric Dumazet 已提交
208 209
	struct sfq_slot *slot = &q->slots[x];
	int qlen = slot->qlen;
210

E
Eric Dumazet 已提交
211
	p = qlen + SFQ_MAX_FLOWS;
212
	n = q->dep[qlen].next;
L
Linus Torvalds 已提交
213

E
Eric Dumazet 已提交
214 215
	slot->dep.next = n;
	slot->dep.prev = p;
216 217 218

	q->dep[qlen].next = x;		/* sfq_dep_head(q, p)->next = x */
	sfq_dep_head(q, n)->prev = x;
L
Linus Torvalds 已提交
219 220
}

221
#define sfq_unlink(q, x, n, p)			\
222 223 224 225 226 227
	do {					\
		n = q->slots[x].dep.next;	\
		p = q->slots[x].dep.prev;	\
		sfq_dep_head(q, p)->next = n;	\
		sfq_dep_head(q, n)->prev = p;	\
	} while (0)
228 229


L
Linus Torvalds 已提交
230 231 232
static inline void sfq_dec(struct sfq_sched_data *q, sfq_index x)
{
	sfq_index p, n;
233
	int d;
L
Linus Torvalds 已提交
234

235
	sfq_unlink(q, x, n, p);
L
Linus Torvalds 已提交
236

237 238 239
	d = q->slots[x].qlen--;
	if (n == p && q->cur_depth == d)
		q->cur_depth--;
L
Linus Torvalds 已提交
240 241 242 243 244 245 246 247
	sfq_link(q, x);
}

static inline void sfq_inc(struct sfq_sched_data *q, sfq_index x)
{
	sfq_index p, n;
	int d;

248
	sfq_unlink(q, x, n, p);
L
Linus Torvalds 已提交
249

250 251 252
	d = ++q->slots[x].qlen;
	if (q->cur_depth < d)
		q->cur_depth = d;
L
Linus Torvalds 已提交
253 254 255
	sfq_link(q, x);
}

256 257 258 259 260 261 262 263
/* helper functions : might be changed when/if skb use a standard list_head */

/* remove one skb from tail of slot queue */
static inline struct sk_buff *slot_dequeue_tail(struct sfq_slot *slot)
{
	struct sk_buff *skb = slot->skblist_prev;

	slot->skblist_prev = skb->prev;
E
Eric Dumazet 已提交
264
	skb->prev->next = (struct sk_buff *)slot;
265 266 267 268 269 270 271 272 273 274
	skb->next = skb->prev = NULL;
	return skb;
}

/* remove one skb from head of slot queue */
static inline struct sk_buff *slot_dequeue_head(struct sfq_slot *slot)
{
	struct sk_buff *skb = slot->skblist_next;

	slot->skblist_next = skb->next;
E
Eric Dumazet 已提交
275
	skb->next->prev = (struct sk_buff *)slot;
276 277 278 279 280 281
	skb->next = skb->prev = NULL;
	return skb;
}

static inline void slot_queue_init(struct sfq_slot *slot)
{
E
Eric Dumazet 已提交
282
	memset(slot, 0, sizeof(*slot));
283 284 285 286 287 288 289 290 291 292 293 294
	slot->skblist_prev = slot->skblist_next = (struct sk_buff *)slot;
}

/* add skb to slot queue (tail add) */
static inline void slot_queue_add(struct sfq_slot *slot, struct sk_buff *skb)
{
	skb->prev = slot->skblist_prev;
	skb->next = (struct sk_buff *)slot;
	slot->skblist_prev->next = skb;
	slot->skblist_prev = skb;
}

295
static unsigned int sfq_drop(struct Qdisc *sch, struct sk_buff **to_free)
L
Linus Torvalds 已提交
296 297
{
	struct sfq_sched_data *q = qdisc_priv(sch);
298
	sfq_index x, d = q->cur_depth;
L
Linus Torvalds 已提交
299 300
	struct sk_buff *skb;
	unsigned int len;
301
	struct sfq_slot *slot;
L
Linus Torvalds 已提交
302

303
	/* Queue is full! Find the longest slot and drop tail packet from it */
L
Linus Torvalds 已提交
304
	if (d > 1) {
305 306 307
		x = q->dep[d].next;
		slot = &q->slots[x];
drop:
E
Eric Dumazet 已提交
308
		skb = q->headdrop ? slot_dequeue_head(slot) : slot_dequeue_tail(slot);
309
		len = qdisc_pkt_len(skb);
310
		slot->backlog -= len;
L
Linus Torvalds 已提交
311 312
		sfq_dec(q, x);
		sch->q.qlen--;
313
		qdisc_qstats_backlog_dec(sch, skb);
314
		qdisc_drop(skb, sch, to_free);
L
Linus Torvalds 已提交
315 316 317 318 319
		return len;
	}

	if (d == 1) {
		/* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
320 321 322 323 324
		x = q->tail->next;
		slot = &q->slots[x];
		q->tail->next = slot->next;
		q->ht[slot->hash] = SFQ_EMPTY_SLOT;
		goto drop;
L
Linus Torvalds 已提交
325 326 327 328 329
	}

	return 0;
}

330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
/* Is ECN parameter configured */
static int sfq_prob_mark(const struct sfq_sched_data *q)
{
	return q->flags & TC_RED_ECN;
}

/* Should packets over max threshold just be marked */
static int sfq_hard_mark(const struct sfq_sched_data *q)
{
	return (q->flags & (TC_RED_ECN | TC_RED_HARDDROP)) == TC_RED_ECN;
}

static int sfq_headdrop(const struct sfq_sched_data *q)
{
	return q->headdrop;
}

L
Linus Torvalds 已提交
347
static int
348
sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
L
Linus Torvalds 已提交
349 350
{
	struct sfq_sched_data *q = qdisc_priv(sch);
351
	unsigned int hash, dropped;
352
	sfq_index x, qlen;
353
	struct sfq_slot *slot;
354
	int uninitialized_var(ret);
355 356
	struct sk_buff *head;
	int delta;
357 358 359

	hash = sfq_classify(skb, sch, &ret);
	if (hash == 0) {
360
		if (ret & __NET_XMIT_BYPASS)
361
			qdisc_qstats_drop(sch);
362
		__qdisc_drop(skb, to_free);
363 364 365
		return ret;
	}
	hash--;
L
Linus Torvalds 已提交
366 367

	x = q->ht[hash];
368 369 370
	slot = &q->slots[x];
	if (x == SFQ_EMPTY_SLOT) {
		x = q->dep[0].next; /* get a free slot */
E
Eric Dumazet 已提交
371
		if (x >= SFQ_MAX_FLOWS)
372
			return qdisc_drop(skb, sch, to_free);
373 374 375
		q->ht[hash] = x;
		slot = &q->slots[x];
		slot->hash = hash;
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
		slot->backlog = 0; /* should already be 0 anyway... */
		red_set_vars(&slot->vars);
		goto enqueue;
	}
	if (q->red_parms) {
		slot->vars.qavg = red_calc_qavg_no_idle_time(q->red_parms,
							&slot->vars,
							slot->backlog);
		switch (red_action(q->red_parms,
				   &slot->vars,
				   slot->vars.qavg)) {
		case RED_DONT_MARK:
			break;

		case RED_PROB_MARK:
391
			qdisc_qstats_overlimit(sch);
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
			if (sfq_prob_mark(q)) {
				/* We know we have at least one packet in queue */
				if (sfq_headdrop(q) &&
				    INET_ECN_set_ce(slot->skblist_next)) {
					q->stats.prob_mark_head++;
					break;
				}
				if (INET_ECN_set_ce(skb)) {
					q->stats.prob_mark++;
					break;
				}
			}
			q->stats.prob_drop++;
			goto congestion_drop;

		case RED_HARD_MARK:
408
			qdisc_qstats_overlimit(sch);
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
			if (sfq_hard_mark(q)) {
				/* We know we have at least one packet in queue */
				if (sfq_headdrop(q) &&
				    INET_ECN_set_ce(slot->skblist_next)) {
					q->stats.forced_mark_head++;
					break;
				}
				if (INET_ECN_set_ce(skb)) {
					q->stats.forced_mark++;
					break;
				}
			}
			q->stats.forced_drop++;
			goto congestion_drop;
		}
L
Linus Torvalds 已提交
424
	}
425

E
Eric Dumazet 已提交
426
	if (slot->qlen >= q->maxdepth) {
427 428
congestion_drop:
		if (!sfq_headdrop(q))
429
			return qdisc_drop(skb, sch, to_free);
E
Eric Dumazet 已提交
430

431
		/* We know we have at least one packet in queue */
E
Eric Dumazet 已提交
432
		head = slot_dequeue_head(slot);
433 434 435
		delta = qdisc_pkt_len(head) - qdisc_pkt_len(skb);
		sch->qstats.backlog -= delta;
		slot->backlog -= delta;
436
		qdisc_drop(head, sch, to_free);
E
Eric Dumazet 已提交
437 438

		slot_queue_add(slot, skb);
439
		qdisc_tree_reduce_backlog(sch, 0, delta);
E
Eric Dumazet 已提交
440 441
		return NET_XMIT_CN;
	}
442

443
enqueue:
444
	qdisc_qstats_backlog_inc(sch, skb);
445
	slot->backlog += qdisc_pkt_len(skb);
446
	slot_queue_add(slot, skb);
L
Linus Torvalds 已提交
447
	sfq_inc(q, x);
448 449 450
	if (slot->qlen == 1) {		/* The flow is new */
		if (q->tail == NULL) {	/* It is the first flow */
			slot->next = x;
L
Linus Torvalds 已提交
451
		} else {
452 453
			slot->next = q->tail->next;
			q->tail->next = x;
L
Linus Torvalds 已提交
454
		}
455 456 457 458 459
		/* We put this flow at the end of our flow list.
		 * This might sound unfair for a new flow to wait after old ones,
		 * but we could endup servicing new flows only, and freeze old ones.
		 */
		q->tail = slot;
460
		/* We could use a bigger initial quantum for new flows */
461
		slot->allot = q->scaled_quantum;
L
Linus Torvalds 已提交
462
	}
463
	if (++sch->q.qlen <= q->limit)
464
		return NET_XMIT_SUCCESS;
L
Linus Torvalds 已提交
465

466
	qlen = slot->qlen;
467
	dropped = sfq_drop(sch, to_free);
468 469 470
	/* Return Congestion Notification only if we dropped a packet
	 * from this flow.
	 */
471 472
	if (qlen != slot->qlen) {
		qdisc_tree_reduce_backlog(sch, 0, dropped - qdisc_pkt_len(skb));
E
Eric Dumazet 已提交
473
		return NET_XMIT_CN;
474
	}
E
Eric Dumazet 已提交
475 476

	/* As we dropped a packet, better let upper stack know this */
477
	qdisc_tree_reduce_backlog(sch, 1, dropped);
E
Eric Dumazet 已提交
478
	return NET_XMIT_SUCCESS;
L
Linus Torvalds 已提交
479 480 481
}

static struct sk_buff *
482
sfq_dequeue(struct Qdisc *sch)
L
Linus Torvalds 已提交
483 484 485
{
	struct sfq_sched_data *q = qdisc_priv(sch);
	struct sk_buff *skb;
486
	sfq_index a, next_a;
487
	struct sfq_slot *slot;
L
Linus Torvalds 已提交
488 489

	/* No active slots */
490
	if (q->tail == NULL)
L
Linus Torvalds 已提交
491 492
		return NULL;

493
next_slot:
494 495
	a = q->tail->next;
	slot = &q->slots[a];
496 497 498 499 500
	if (slot->allot <= 0) {
		q->tail = slot;
		slot->allot += q->scaled_quantum;
		goto next_slot;
	}
501
	skb = slot_dequeue_head(slot);
L
Linus Torvalds 已提交
502
	sfq_dec(q, a);
503
	qdisc_bstats_update(sch, skb);
L
Linus Torvalds 已提交
504
	sch->q.qlen--;
505
	qdisc_qstats_backlog_dec(sch, skb);
506
	slot->backlog -= qdisc_pkt_len(skb);
L
Linus Torvalds 已提交
507
	/* Is the slot empty? */
508 509 510
	if (slot->qlen == 0) {
		q->ht[slot->hash] = SFQ_EMPTY_SLOT;
		next_a = slot->next;
511
		if (a == next_a) {
512
			q->tail = NULL; /* no more active slots */
L
Linus Torvalds 已提交
513 514
			return skb;
		}
515
		q->tail->next = next_a;
516 517
	} else {
		slot->allot -= SFQ_ALLOT_SIZE(qdisc_pkt_len(skb));
L
Linus Torvalds 已提交
518 519 520 521 522
	}
	return skb;
}

static void
523
sfq_reset(struct Qdisc *sch)
L
Linus Torvalds 已提交
524 525 526 527
{
	struct sk_buff *skb;

	while ((skb = sfq_dequeue(sch)) != NULL)
528
		rtnl_kfree_skbs(skb, skb);
L
Linus Torvalds 已提交
529 530
}

531 532 533 534 535 536
/*
 * When q->perturbation is changed, we rehash all queued skbs
 * to avoid OOO (Out Of Order) effects.
 * We dont use sfq_dequeue()/sfq_enqueue() because we dont want to change
 * counters.
 */
E
Eric Dumazet 已提交
537
static void sfq_rehash(struct Qdisc *sch)
538
{
E
Eric Dumazet 已提交
539
	struct sfq_sched_data *q = qdisc_priv(sch);
540 541 542 543
	struct sk_buff *skb;
	int i;
	struct sfq_slot *slot;
	struct sk_buff_head list;
E
Eric Dumazet 已提交
544
	int dropped = 0;
545
	unsigned int drop_len = 0;
546 547 548

	__skb_queue_head_init(&list);

E
Eric Dumazet 已提交
549
	for (i = 0; i < q->maxflows; i++) {
550 551 552 553 554 555 556 557
		slot = &q->slots[i];
		if (!slot->qlen)
			continue;
		while (slot->qlen) {
			skb = slot_dequeue_head(slot);
			sfq_dec(q, i);
			__skb_queue_tail(&list, skb);
		}
558 559
		slot->backlog = 0;
		red_set_vars(&slot->vars);
560 561 562 563 564 565 566 567 568 569 570
		q->ht[slot->hash] = SFQ_EMPTY_SLOT;
	}
	q->tail = NULL;

	while ((skb = __skb_dequeue(&list)) != NULL) {
		unsigned int hash = sfq_hash(q, skb);
		sfq_index x = q->ht[hash];

		slot = &q->slots[x];
		if (x == SFQ_EMPTY_SLOT) {
			x = q->dep[0].next; /* get a free slot */
E
Eric Dumazet 已提交
571
			if (x >= SFQ_MAX_FLOWS) {
572 573
drop:
				qdisc_qstats_backlog_dec(sch, skb);
574
				drop_len += qdisc_pkt_len(skb);
E
Eric Dumazet 已提交
575 576 577 578
				kfree_skb(skb);
				dropped++;
				continue;
			}
579 580 581 582
			q->ht[hash] = x;
			slot = &q->slots[x];
			slot->hash = hash;
		}
E
Eric Dumazet 已提交
583 584
		if (slot->qlen >= q->maxdepth)
			goto drop;
585
		slot_queue_add(slot, skb);
586 587 588 589 590
		if (q->red_parms)
			slot->vars.qavg = red_calc_qavg(q->red_parms,
							&slot->vars,
							slot->backlog);
		slot->backlog += qdisc_pkt_len(skb);
591 592 593 594 595 596 597 598 599 600 601 602
		sfq_inc(q, x);
		if (slot->qlen == 1) {		/* The flow is new */
			if (q->tail == NULL) {	/* It is the first flow */
				slot->next = x;
			} else {
				slot->next = q->tail->next;
				q->tail->next = x;
			}
			q->tail = slot;
			slot->allot = q->scaled_quantum;
		}
	}
E
Eric Dumazet 已提交
603
	sch->q.qlen -= dropped;
604
	qdisc_tree_reduce_backlog(sch, dropped, drop_len);
605 606
}

L
Linus Torvalds 已提交
607 608
static void sfq_perturbation(unsigned long arg)
{
609
	struct Qdisc *sch = (struct Qdisc *)arg;
L
Linus Torvalds 已提交
610
	struct sfq_sched_data *q = qdisc_priv(sch);
611
	spinlock_t *root_lock = qdisc_lock(qdisc_root_sleeping(sch));
L
Linus Torvalds 已提交
612

613
	spin_lock(root_lock);
614
	q->perturbation = prandom_u32();
615
	if (!q->filter_list && q->tail)
E
Eric Dumazet 已提交
616
		sfq_rehash(sch);
617
	spin_unlock(root_lock);
L
Linus Torvalds 已提交
618

619 620
	if (q->perturb_period)
		mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
L
Linus Torvalds 已提交
621 622
}

623
static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
L
Linus Torvalds 已提交
624 625
{
	struct sfq_sched_data *q = qdisc_priv(sch);
626
	struct tc_sfq_qopt *ctl = nla_data(opt);
E
Eric Dumazet 已提交
627
	struct tc_sfq_qopt_v1 *ctl_v1 = NULL;
628
	unsigned int qlen, dropped = 0;
629
	struct red_parms *p = NULL;
630 631
	struct sk_buff *to_free = NULL;
	struct sk_buff *tail = NULL;
L
Linus Torvalds 已提交
632

633
	if (opt->nla_len < nla_attr_size(sizeof(*ctl)))
L
Linus Torvalds 已提交
634
		return -EINVAL;
E
Eric Dumazet 已提交
635 636
	if (opt->nla_len >= nla_attr_size(sizeof(*ctl_v1)))
		ctl_v1 = nla_data(opt);
S
stephen hemminger 已提交
637 638 639
	if (ctl->divisor &&
	    (!is_power_of_2(ctl->divisor) || ctl->divisor > 65536))
		return -EINVAL;
640 641 642 643 644
	if (ctl_v1 && ctl_v1->qth_min) {
		p = kmalloc(sizeof(*p), GFP_KERNEL);
		if (!p)
			return -ENOMEM;
	}
L
Linus Torvalds 已提交
645
	sch_tree_lock(sch);
E
Eric Dumazet 已提交
646 647 648 649
	if (ctl->quantum) {
		q->quantum = ctl->quantum;
		q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum);
	}
650
	q->perturb_period = ctl->perturb_period * HZ;
E
Eric Dumazet 已提交
651 652 653
	if (ctl->flows)
		q->maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS);
	if (ctl->divisor) {
654
		q->divisor = ctl->divisor;
E
Eric Dumazet 已提交
655 656 657 658 659
		q->maxflows = min_t(u32, q->maxflows, q->divisor);
	}
	if (ctl_v1) {
		if (ctl_v1->depth)
			q->maxdepth = min_t(u32, ctl_v1->depth, SFQ_MAX_DEPTH);
660 661 662 663 664 665 666 667 668 669
		if (p) {
			swap(q->red_parms, p);
			red_set_parms(q->red_parms,
				      ctl_v1->qth_min, ctl_v1->qth_max,
				      ctl_v1->Wlog,
				      ctl_v1->Plog, ctl_v1->Scell_log,
				      NULL,
				      ctl_v1->max_P);
		}
		q->flags = ctl_v1->flags;
E
Eric Dumazet 已提交
670 671 672 673 674 675 676
		q->headdrop = ctl_v1->headdrop;
	}
	if (ctl->limit) {
		q->limit = min_t(u32, ctl->limit, q->maxdepth * q->maxflows);
		q->maxflows = min_t(u32, q->maxflows, q->limit);
	}

677
	qlen = sch->q.qlen;
678 679 680 681 682 683 684
	while (sch->q.qlen > q->limit) {
		dropped += sfq_drop(sch, &to_free);
		if (!tail)
			tail = to_free;
	}

	rtnl_kfree_skbs(to_free, tail);
685
	qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped);
L
Linus Torvalds 已提交
686 687 688

	del_timer(&q->perturb_timer);
	if (q->perturb_period) {
689
		mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
690
		q->perturbation = prandom_u32();
L
Linus Torvalds 已提交
691 692
	}
	sch_tree_unlock(sch);
693
	kfree(p);
L
Linus Torvalds 已提交
694 695 696
	return 0;
}

697 698
static void *sfq_alloc(size_t sz)
{
699
	return  kvmalloc(sz, GFP_KERNEL);
700 701 702 703
}

static void sfq_free(void *addr)
{
W
WANG Cong 已提交
704
	kvfree(addr);
705 706 707 708 709 710
}

static void sfq_destroy(struct Qdisc *sch)
{
	struct sfq_sched_data *q = qdisc_priv(sch);

711
	tcf_block_put(q->block);
712 713 714
	q->perturb_period = 0;
	del_timer_sync(&q->perturb_timer);
	sfq_free(q->ht);
E
Eric Dumazet 已提交
715
	sfq_free(q->slots);
716
	kfree(q->red_parms);
717 718
}

719
static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
L
Linus Torvalds 已提交
720 721 722
{
	struct sfq_sched_data *q = qdisc_priv(sch);
	int i;
723 724
	int err;

725 726 727
	setup_deferrable_timer(&q->perturb_timer, sfq_perturbation,
			       (unsigned long)sch);

728
	err = tcf_block_get(&q->block, &q->filter_list, sch);
729 730
	if (err)
		return err;
L
Linus Torvalds 已提交
731

E
Eric Dumazet 已提交
732 733 734
	for (i = 0; i < SFQ_MAX_DEPTH + 1; i++) {
		q->dep[i].next = i + SFQ_MAX_FLOWS;
		q->dep[i].prev = i + SFQ_MAX_FLOWS;
L
Linus Torvalds 已提交
735
	}
736

E
Eric Dumazet 已提交
737 738
	q->limit = SFQ_MAX_DEPTH;
	q->maxdepth = SFQ_MAX_DEPTH;
739 740
	q->cur_depth = 0;
	q->tail = NULL;
741
	q->divisor = SFQ_DEFAULT_HASH_DIVISOR;
E
Eric Dumazet 已提交
742
	q->maxflows = SFQ_DEFAULT_FLOWS;
743 744 745
	q->quantum = psched_mtu(qdisc_dev(sch));
	q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum);
	q->perturb_period = 0;
746
	q->perturbation = prandom_u32();
747 748

	if (opt) {
L
Linus Torvalds 已提交
749 750 751 752
		int err = sfq_change(sch, opt);
		if (err)
			return err;
	}
753

754
	q->ht = sfq_alloc(sizeof(q->ht[0]) * q->divisor);
E
Eric Dumazet 已提交
755 756
	q->slots = sfq_alloc(sizeof(q->slots[0]) * q->maxflows);
	if (!q->ht || !q->slots) {
757
		/* Note: sfq_destroy() will be called by our caller */
758
		return -ENOMEM;
759
	}
760

761 762 763
	for (i = 0; i < q->divisor; i++)
		q->ht[i] = SFQ_EMPTY_SLOT;

E
Eric Dumazet 已提交
764
	for (i = 0; i < q->maxflows; i++) {
E
Eric Dumazet 已提交
765
		slot_queue_init(&q->slots[i]);
L
Linus Torvalds 已提交
766
		sfq_link(q, i);
E
Eric Dumazet 已提交
767
	}
768 769 770 771
	if (q->limit >= 1)
		sch->flags |= TCQ_F_CAN_BYPASS;
	else
		sch->flags &= ~TCQ_F_CAN_BYPASS;
L
Linus Torvalds 已提交
772 773 774 775 776 777
	return 0;
}

static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
{
	struct sfq_sched_data *q = qdisc_priv(sch);
778
	unsigned char *b = skb_tail_pointer(skb);
E
Eric Dumazet 已提交
779
	struct tc_sfq_qopt_v1 opt;
780
	struct red_parms *p = q->red_parms;
E
Eric Dumazet 已提交
781 782 783 784 785 786 787 788 789

	memset(&opt, 0, sizeof(opt));
	opt.v0.quantum	= q->quantum;
	opt.v0.perturb_period = q->perturb_period / HZ;
	opt.v0.limit	= q->limit;
	opt.v0.divisor	= q->divisor;
	opt.v0.flows	= q->maxflows;
	opt.depth	= q->maxdepth;
	opt.headdrop	= q->headdrop;
L
Linus Torvalds 已提交
790

791 792 793 794 795 796 797 798 799 800 801
	if (p) {
		opt.qth_min	= p->qth_min >> p->Wlog;
		opt.qth_max	= p->qth_max >> p->Wlog;
		opt.Wlog	= p->Wlog;
		opt.Plog	= p->Plog;
		opt.Scell_log	= p->Scell_log;
		opt.max_P	= p->max_P;
	}
	memcpy(&opt.stats, &q->stats, sizeof(opt.stats));
	opt.flags	= q->flags;

802 803
	if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt))
		goto nla_put_failure;
L
Linus Torvalds 已提交
804 805 806

	return skb->len;

807
nla_put_failure:
808
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
809 810 811
	return -1;
}

812 813 814 815 816
static struct Qdisc *sfq_leaf(struct Qdisc *sch, unsigned long arg)
{
	return NULL;
}

817
static unsigned long sfq_find(struct Qdisc *sch, u32 classid)
818 819 820 821
{
	return 0;
}

822 823 824
static unsigned long sfq_bind(struct Qdisc *sch, unsigned long parent,
			      u32 classid)
{
825 826
	/* we cannot bypass queue discipline anymore */
	sch->flags &= ~TCQ_F_CAN_BYPASS;
827 828 829
	return 0;
}

830
static void sfq_unbind(struct Qdisc *q, unsigned long cl)
831 832 833
{
}

834
static struct tcf_block *sfq_tcf_block(struct Qdisc *sch, unsigned long cl)
835 836 837 838 839
{
	struct sfq_sched_data *q = qdisc_priv(sch);

	if (cl)
		return NULL;
840
	return q->block;
841 842
}

843 844 845 846 847 848 849 850 851 852 853
static int sfq_dump_class(struct Qdisc *sch, unsigned long cl,
			  struct sk_buff *skb, struct tcmsg *tcm)
{
	tcm->tcm_handle |= TC_H_MIN(cl);
	return 0;
}

static int sfq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
				struct gnet_dump *d)
{
	struct sfq_sched_data *q = qdisc_priv(sch);
E
Eric Dumazet 已提交
854 855 856
	sfq_index idx = q->ht[cl - 1];
	struct gnet_stats_queue qs = { 0 };
	struct tc_sfq_xstats xstats = { 0 };
857

E
Eric Dumazet 已提交
858 859
	if (idx != SFQ_EMPTY_SLOT) {
		const struct sfq_slot *slot = &q->slots[idx];
860

861
		xstats.allot = slot->allot << SFQ_ALLOT_SHIFT;
E
Eric Dumazet 已提交
862
		qs.qlen = slot->qlen;
863
		qs.backlog = slot->backlog;
E
Eric Dumazet 已提交
864
	}
865
	if (gnet_stats_copy_queue(d, NULL, &qs, qs.qlen) < 0)
866 867 868 869
		return -1;
	return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
}

870 871
static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
{
872 873 874 875 876 877
	struct sfq_sched_data *q = qdisc_priv(sch);
	unsigned int i;

	if (arg->stop)
		return;

878
	for (i = 0; i < q->divisor; i++) {
879
		if (q->ht[i] == SFQ_EMPTY_SLOT ||
880 881 882 883 884 885 886 887 888 889
		    arg->count < arg->skip) {
			arg->count++;
			continue;
		}
		if (arg->fn(sch, i + 1, arg) < 0) {
			arg->stop = 1;
			break;
		}
		arg->count++;
	}
890 891 892
}

static const struct Qdisc_class_ops sfq_class_ops = {
893
	.leaf		=	sfq_leaf,
894
	.find		=	sfq_find,
895
	.tcf_block	=	sfq_tcf_block,
896
	.bind_tcf	=	sfq_bind,
897
	.unbind_tcf	=	sfq_unbind,
898 899
	.dump		=	sfq_dump_class,
	.dump_stats	=	sfq_dump_class_stats,
900 901 902
	.walk		=	sfq_walk,
};

903
static struct Qdisc_ops sfq_qdisc_ops __read_mostly = {
904
	.cl_ops		=	&sfq_class_ops,
L
Linus Torvalds 已提交
905 906 907 908
	.id		=	"sfq",
	.priv_size	=	sizeof(struct sfq_sched_data),
	.enqueue	=	sfq_enqueue,
	.dequeue	=	sfq_dequeue,
909
	.peek		=	qdisc_peek_dequeued,
L
Linus Torvalds 已提交
910 911 912 913 914 915 916 917 918 919 920 921
	.init		=	sfq_init,
	.reset		=	sfq_reset,
	.destroy	=	sfq_destroy,
	.change		=	NULL,
	.dump		=	sfq_dump,
	.owner		=	THIS_MODULE,
};

static int __init sfq_module_init(void)
{
	return register_qdisc(&sfq_qdisc_ops);
}
922
static void __exit sfq_module_exit(void)
L
Linus Torvalds 已提交
923 924 925 926 927 928
{
	unregister_qdisc(&sfq_qdisc_ops);
}
module_init(sfq_module_init)
module_exit(sfq_module_exit)
MODULE_LICENSE("GPL");