sch_sfq.c 21.7 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/red.h>
L
Linus Torvalds 已提交
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44


/*	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.


45
	This is not the thing that is usually called (W)FQ nowadays.
L
Linus Torvalds 已提交
46 47 48 49 50 51 52 53 54
	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:

55
	- "Stochastic" -> It is not 100% fair.
L
Linus Torvalds 已提交
56 57 58 59 60 61 62 63 64 65 66 67 68
	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 已提交
69 70 71 72 73
	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 已提交
74 75 76

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

E
Eric Dumazet 已提交
77 78 79 80
#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
81 82
#define SFQ_DEFAULT_HASH_DIVISOR 1024

83 84 85 86 87
/* 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 已提交
88

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

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

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

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

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

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

131 132 133 134
	struct red_parms *red_parms;
	struct tc_sfqred_stats stats;
	struct sfq_slot *tail;		/* current slot in round */

E
Eric Dumazet 已提交
135 136 137 138 139 140 141
	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
					 */

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

148 149 150 151 152
/*
 * 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 已提交
153
	if (val < SFQ_MAX_FLOWS)
154
		return &q->slots[val].dep;
E
Eric Dumazet 已提交
155
	return &q->dep[val - SFQ_MAX_FLOWS];
156 157
}

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

164 165 166 167 168
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 已提交
169
	struct tcf_proto *fl;
170 171 172 173
	int result;

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

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

181
	*qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
J
John Fastabend 已提交
182
	result = tc_classify(skb, fl, &res);
183 184 185 186 187
	if (result >= 0) {
#ifdef CONFIG_NET_CLS_ACT
		switch (result) {
		case TC_ACT_STOLEN:
		case TC_ACT_QUEUED:
188
			*qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
189 190 191 192
		case TC_ACT_SHOT:
			return 0;
		}
#endif
193
		if (TC_H_MIN(res.classid) <= q->divisor)
194 195 196 197 198
			return TC_H_MIN(res.classid);
	}
	return 0;
}

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

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

E
Eric Dumazet 已提交
211 212
	slot->dep.next = n;
	slot->dep.prev = p;
213 214 215

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

218
#define sfq_unlink(q, x, n, p)			\
219 220 221 222 223 224
	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)
225 226


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

232
	sfq_unlink(q, x, n, p);
L
Linus Torvalds 已提交
233

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

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

245
	sfq_unlink(q, x, n, p);
L
Linus Torvalds 已提交
246

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

253 254 255 256 257 258 259 260
/* 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 已提交
261
	skb->prev->next = (struct sk_buff *)slot;
262 263 264 265 266 267 268 269 270 271
	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 已提交
272
	skb->next->prev = (struct sk_buff *)slot;
273 274 275 276 277 278
	skb->next = skb->prev = NULL;
	return skb;
}

static inline void slot_queue_init(struct sfq_slot *slot)
{
E
Eric Dumazet 已提交
279
	memset(slot, 0, sizeof(*slot));
280 281 282 283 284 285 286 287 288 289 290 291
	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;
}

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

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

	if (d == 1) {
		/* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
318 319 320 321 322
		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 已提交
323 324 325 326 327
	}

	return 0;
}

328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
/* 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 已提交
345
static int
346
sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
L
Linus Torvalds 已提交
347 348
{
	struct sfq_sched_data *q = qdisc_priv(sch);
349
	unsigned int hash;
350
	sfq_index x, qlen;
351
	struct sfq_slot *slot;
352
	int uninitialized_var(ret);
353 354
	struct sk_buff *head;
	int delta;
355 356 357

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

	x = q->ht[hash];
366 367 368
	slot = &q->slots[x];
	if (x == SFQ_EMPTY_SLOT) {
		x = q->dep[0].next; /* get a free slot */
E
Eric Dumazet 已提交
369 370
		if (x >= SFQ_MAX_FLOWS)
			return qdisc_drop(skb, sch);
371 372 373
		q->ht[hash] = x;
		slot = &q->slots[x];
		slot->hash = hash;
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
		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:
389
			qdisc_qstats_overlimit(sch);
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
			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:
406
			qdisc_qstats_overlimit(sch);
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
			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 已提交
422
	}
423

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

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

		slot_queue_add(slot, skb);
		return NET_XMIT_CN;
	}
439

440
enqueue:
441
	qdisc_qstats_backlog_inc(sch, skb);
442
	slot->backlog += qdisc_pkt_len(skb);
443
	slot_queue_add(slot, skb);
L
Linus Torvalds 已提交
444
	sfq_inc(q, x);
445 446 447
	if (slot->qlen == 1) {		/* The flow is new */
		if (q->tail == NULL) {	/* It is the first flow */
			slot->next = x;
L
Linus Torvalds 已提交
448
		} else {
449 450
			slot->next = q->tail->next;
			q->tail->next = x;
L
Linus Torvalds 已提交
451
		}
452 453 454 455 456
		/* 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;
457
		/* We could use a bigger initial quantum for new flows */
458
		slot->allot = q->scaled_quantum;
L
Linus Torvalds 已提交
459
	}
460
	if (++sch->q.qlen <= q->limit)
461
		return NET_XMIT_SUCCESS;
L
Linus Torvalds 已提交
462

463
	qlen = slot->qlen;
L
Linus Torvalds 已提交
464
	sfq_drop(sch);
465 466 467
	/* Return Congestion Notification only if we dropped a packet
	 * from this flow.
	 */
E
Eric Dumazet 已提交
468 469 470 471 472 473
	if (qlen != slot->qlen)
		return NET_XMIT_CN;

	/* As we dropped a packet, better let upper stack know this */
	qdisc_tree_decrease_qlen(sch, 1);
	return NET_XMIT_SUCCESS;
L
Linus Torvalds 已提交
474 475 476
}

static struct sk_buff *
477
sfq_dequeue(struct Qdisc *sch)
L
Linus Torvalds 已提交
478 479 480
{
	struct sfq_sched_data *q = qdisc_priv(sch);
	struct sk_buff *skb;
481
	sfq_index a, next_a;
482
	struct sfq_slot *slot;
L
Linus Torvalds 已提交
483 484

	/* No active slots */
485
	if (q->tail == NULL)
L
Linus Torvalds 已提交
486 487
		return NULL;

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

static void
518
sfq_reset(struct Qdisc *sch)
L
Linus Torvalds 已提交
519 520 521 522 523 524 525
{
	struct sk_buff *skb;

	while ((skb = sfq_dequeue(sch)) != NULL)
		kfree_skb(skb);
}

526 527 528 529 530 531
/*
 * 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 已提交
532
static void sfq_rehash(struct Qdisc *sch)
533
{
E
Eric Dumazet 已提交
534
	struct sfq_sched_data *q = qdisc_priv(sch);
535 536 537 538
	struct sk_buff *skb;
	int i;
	struct sfq_slot *slot;
	struct sk_buff_head list;
E
Eric Dumazet 已提交
539
	int dropped = 0;
540 541 542

	__skb_queue_head_init(&list);

E
Eric Dumazet 已提交
543
	for (i = 0; i < q->maxflows; i++) {
544 545 546 547 548 549 550 551
		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);
		}
552 553
		slot->backlog = 0;
		red_set_vars(&slot->vars);
554 555 556 557 558 559 560 561 562 563 564
		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 已提交
565
			if (x >= SFQ_MAX_FLOWS) {
566 567
drop:
				qdisc_qstats_backlog_dec(sch, skb);
E
Eric Dumazet 已提交
568 569 570 571
				kfree_skb(skb);
				dropped++;
				continue;
			}
572 573 574 575
			q->ht[hash] = x;
			slot = &q->slots[x];
			slot->hash = hash;
		}
E
Eric Dumazet 已提交
576 577
		if (slot->qlen >= q->maxdepth)
			goto drop;
578
		slot_queue_add(slot, skb);
579 580 581 582 583
		if (q->red_parms)
			slot->vars.qavg = red_calc_qavg(q->red_parms,
							&slot->vars,
							slot->backlog);
		slot->backlog += qdisc_pkt_len(skb);
584 585 586 587 588 589 590 591 592 593 594 595
		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 已提交
596 597
	sch->q.qlen -= dropped;
	qdisc_tree_decrease_qlen(sch, dropped);
598 599
}

L
Linus Torvalds 已提交
600 601
static void sfq_perturbation(unsigned long arg)
{
602
	struct Qdisc *sch = (struct Qdisc *)arg;
L
Linus Torvalds 已提交
603
	struct sfq_sched_data *q = qdisc_priv(sch);
604
	spinlock_t *root_lock = qdisc_lock(qdisc_root_sleeping(sch));
L
Linus Torvalds 已提交
605

606
	spin_lock(root_lock);
607
	q->perturbation = prandom_u32();
608
	if (!q->filter_list && q->tail)
E
Eric Dumazet 已提交
609
		sfq_rehash(sch);
610
	spin_unlock(root_lock);
L
Linus Torvalds 已提交
611

612 613
	if (q->perturb_period)
		mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
L
Linus Torvalds 已提交
614 615
}

616
static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
L
Linus Torvalds 已提交
617 618
{
	struct sfq_sched_data *q = qdisc_priv(sch);
619
	struct tc_sfq_qopt *ctl = nla_data(opt);
E
Eric Dumazet 已提交
620
	struct tc_sfq_qopt_v1 *ctl_v1 = NULL;
621
	unsigned int qlen;
622
	struct red_parms *p = NULL;
L
Linus Torvalds 已提交
623

624
	if (opt->nla_len < nla_attr_size(sizeof(*ctl)))
L
Linus Torvalds 已提交
625
		return -EINVAL;
E
Eric Dumazet 已提交
626 627
	if (opt->nla_len >= nla_attr_size(sizeof(*ctl_v1)))
		ctl_v1 = nla_data(opt);
S
stephen hemminger 已提交
628 629 630
	if (ctl->divisor &&
	    (!is_power_of_2(ctl->divisor) || ctl->divisor > 65536))
		return -EINVAL;
631 632 633 634 635
	if (ctl_v1 && ctl_v1->qth_min) {
		p = kmalloc(sizeof(*p), GFP_KERNEL);
		if (!p)
			return -ENOMEM;
	}
L
Linus Torvalds 已提交
636
	sch_tree_lock(sch);
E
Eric Dumazet 已提交
637 638 639 640
	if (ctl->quantum) {
		q->quantum = ctl->quantum;
		q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum);
	}
641
	q->perturb_period = ctl->perturb_period * HZ;
E
Eric Dumazet 已提交
642 643 644
	if (ctl->flows)
		q->maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS);
	if (ctl->divisor) {
645
		q->divisor = ctl->divisor;
E
Eric Dumazet 已提交
646 647 648 649 650
		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);
651 652 653 654 655 656 657 658 659 660
		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 已提交
661 662 663 664 665 666 667
		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);
	}

668
	qlen = sch->q.qlen;
669
	while (sch->q.qlen > q->limit)
L
Linus Torvalds 已提交
670
		sfq_drop(sch);
671
	qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
L
Linus Torvalds 已提交
672 673 674

	del_timer(&q->perturb_timer);
	if (q->perturb_period) {
675
		mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
676
		q->perturbation = prandom_u32();
L
Linus Torvalds 已提交
677 678
	}
	sch_tree_unlock(sch);
679
	kfree(p);
L
Linus Torvalds 已提交
680 681 682
	return 0;
}

683 684 685 686 687 688 689 690 691 692 693
static void *sfq_alloc(size_t sz)
{
	void *ptr = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN);

	if (!ptr)
		ptr = vmalloc(sz);
	return ptr;
}

static void sfq_free(void *addr)
{
W
WANG Cong 已提交
694
	kvfree(addr);
695 696 697 698 699 700 701 702 703 704
}

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

	tcf_destroy_chain(&q->filter_list);
	q->perturb_period = 0;
	del_timer_sync(&q->perturb_timer);
	sfq_free(q->ht);
E
Eric Dumazet 已提交
705
	sfq_free(q->slots);
706
	kfree(q->red_parms);
707 708
}

709
static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
L
Linus Torvalds 已提交
710 711 712 713
{
	struct sfq_sched_data *q = qdisc_priv(sch);
	int i;

714
	q->perturb_timer.function = sfq_perturbation;
715
	q->perturb_timer.data = (unsigned long)sch;
716
	init_timer_deferrable(&q->perturb_timer);
L
Linus Torvalds 已提交
717

E
Eric Dumazet 已提交
718 719 720
	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 已提交
721
	}
722

E
Eric Dumazet 已提交
723 724
	q->limit = SFQ_MAX_DEPTH;
	q->maxdepth = SFQ_MAX_DEPTH;
725 726
	q->cur_depth = 0;
	q->tail = NULL;
727
	q->divisor = SFQ_DEFAULT_HASH_DIVISOR;
E
Eric Dumazet 已提交
728
	q->maxflows = SFQ_DEFAULT_FLOWS;
729 730 731
	q->quantum = psched_mtu(qdisc_dev(sch));
	q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum);
	q->perturb_period = 0;
732
	q->perturbation = prandom_u32();
733 734

	if (opt) {
L
Linus Torvalds 已提交
735 736 737 738
		int err = sfq_change(sch, opt);
		if (err)
			return err;
	}
739

740
	q->ht = sfq_alloc(sizeof(q->ht[0]) * q->divisor);
E
Eric Dumazet 已提交
741 742
	q->slots = sfq_alloc(sizeof(q->slots[0]) * q->maxflows);
	if (!q->ht || !q->slots) {
743
		sfq_destroy(sch);
744
		return -ENOMEM;
745
	}
746 747 748
	for (i = 0; i < q->divisor; i++)
		q->ht[i] = SFQ_EMPTY_SLOT;

E
Eric Dumazet 已提交
749
	for (i = 0; i < q->maxflows; i++) {
E
Eric Dumazet 已提交
750
		slot_queue_init(&q->slots[i]);
L
Linus Torvalds 已提交
751
		sfq_link(q, i);
E
Eric Dumazet 已提交
752
	}
753 754 755 756
	if (q->limit >= 1)
		sch->flags |= TCQ_F_CAN_BYPASS;
	else
		sch->flags &= ~TCQ_F_CAN_BYPASS;
L
Linus Torvalds 已提交
757 758 759 760 761 762
	return 0;
}

static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
{
	struct sfq_sched_data *q = qdisc_priv(sch);
763
	unsigned char *b = skb_tail_pointer(skb);
E
Eric Dumazet 已提交
764
	struct tc_sfq_qopt_v1 opt;
765
	struct red_parms *p = q->red_parms;
E
Eric Dumazet 已提交
766 767 768 769 770 771 772 773 774

	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 已提交
775

776 777 778 779 780 781 782 783 784 785 786
	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;

787 788
	if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt))
		goto nla_put_failure;
L
Linus Torvalds 已提交
789 790 791

	return skb->len;

792
nla_put_failure:
793
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
794 795 796
	return -1;
}

797 798 799 800 801
static struct Qdisc *sfq_leaf(struct Qdisc *sch, unsigned long arg)
{
	return NULL;
}

802 803 804 805 806
static unsigned long sfq_get(struct Qdisc *sch, u32 classid)
{
	return 0;
}

807 808 809
static unsigned long sfq_bind(struct Qdisc *sch, unsigned long parent,
			      u32 classid)
{
810 811
	/* we cannot bypass queue discipline anymore */
	sch->flags &= ~TCQ_F_CAN_BYPASS;
812 813 814
	return 0;
}

815 816 817 818
static void sfq_put(struct Qdisc *q, unsigned long cl)
{
}

J
John Fastabend 已提交
819 820
static struct tcf_proto __rcu **sfq_find_tcf(struct Qdisc *sch,
					     unsigned long cl)
821 822 823 824 825 826 827 828
{
	struct sfq_sched_data *q = qdisc_priv(sch);

	if (cl)
		return NULL;
	return &q->filter_list;
}

829 830 831 832 833 834 835 836 837 838 839
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 已提交
840 841 842
	sfq_index idx = q->ht[cl - 1];
	struct gnet_stats_queue qs = { 0 };
	struct tc_sfq_xstats xstats = { 0 };
843

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

847
		xstats.allot = slot->allot << SFQ_ALLOT_SHIFT;
E
Eric Dumazet 已提交
848
		qs.qlen = slot->qlen;
849
		qs.backlog = slot->backlog;
E
Eric Dumazet 已提交
850
	}
851
	if (gnet_stats_copy_queue(d, NULL, &qs, qs.qlen) < 0)
852 853 854 855
		return -1;
	return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
}

856 857
static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
{
858 859 860 861 862 863
	struct sfq_sched_data *q = qdisc_priv(sch);
	unsigned int i;

	if (arg->stop)
		return;

864
	for (i = 0; i < q->divisor; i++) {
865
		if (q->ht[i] == SFQ_EMPTY_SLOT ||
866 867 868 869 870 871 872 873 874 875
		    arg->count < arg->skip) {
			arg->count++;
			continue;
		}
		if (arg->fn(sch, i + 1, arg) < 0) {
			arg->stop = 1;
			break;
		}
		arg->count++;
	}
876 877 878
}

static const struct Qdisc_class_ops sfq_class_ops = {
879
	.leaf		=	sfq_leaf,
880
	.get		=	sfq_get,
881
	.put		=	sfq_put,
882
	.tcf_chain	=	sfq_find_tcf,
883
	.bind_tcf	=	sfq_bind,
884
	.unbind_tcf	=	sfq_put,
885 886
	.dump		=	sfq_dump_class,
	.dump_stats	=	sfq_dump_class_stats,
887 888 889
	.walk		=	sfq_walk,
};

890
static struct Qdisc_ops sfq_qdisc_ops __read_mostly = {
891
	.cl_ops		=	&sfq_class_ops,
L
Linus Torvalds 已提交
892 893 894 895
	.id		=	"sfq",
	.priv_size	=	sizeof(struct sfq_sched_data),
	.enqueue	=	sfq_enqueue,
	.dequeue	=	sfq_dequeue,
896
	.peek		=	qdisc_peek_dequeued,
L
Linus Torvalds 已提交
897 898 899 900 901 902 903 904 905 906 907 908 909
	.drop		=	sfq_drop,
	.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);
}
910
static void __exit sfq_module_exit(void)
L
Linus Torvalds 已提交
911 912 913 914 915 916
{
	unregister_qdisc(&sfq_qdisc_ops);
}
module_init(sfq_module_init)
module_exit(sfq_module_exit)
MODULE_LICENSE("GPL");