sch_sfq.c 22.0 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;
E
Eric Dumazet 已提交
129 130 131
	sfq_index	*ht;		/* Hash table ('divisor' slots) */
	struct sfq_slot	*slots;		/* Flows table ('maxflows' entries) */

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

static inline void slot_queue_init(struct sfq_slot *slot)
{
E
Eric Dumazet 已提交
280
	memset(slot, 0, sizeof(*slot));
281 282 283 284 285 286 287 288 289 290 291 292
	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 已提交
293 294 295
static unsigned int sfq_drop(struct Qdisc *sch)
{
	struct sfq_sched_data *q = qdisc_priv(sch);
296
	sfq_index x, d = q->cur_depth;
L
Linus Torvalds 已提交
297 298
	struct sk_buff *skb;
	unsigned int len;
299
	struct sfq_slot *slot;
L
Linus Torvalds 已提交
300

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

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

	return 0;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

	while ((skb = sfq_dequeue(sch)) != NULL)
524
		rtnl_kfree_skbs(skb, skb);
L
Linus Torvalds 已提交
525 526
}

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

	__skb_queue_head_init(&list);

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

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

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

615 616
	if (q->perturb_period)
		mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
L
Linus Torvalds 已提交
617 618
}

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

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

671
	qlen = sch->q.qlen;
672
	while (sch->q.qlen > q->limit)
673 674
		dropped += sfq_drop(sch);
	qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped);
L
Linus Torvalds 已提交
675 676 677

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

686 687 688 689 690 691 692 693 694 695 696
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 已提交
697
	kvfree(addr);
698 699 700 701 702 703 704 705 706 707
}

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 已提交
708
	sfq_free(q->slots);
709
	kfree(q->red_parms);
710 711
}

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

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

E
Eric Dumazet 已提交
721 722 723
	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 已提交
724
	}
725

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

	if (opt) {
L
Linus Torvalds 已提交
738 739 740 741
		int err = sfq_change(sch, opt);
		if (err)
			return err;
	}
742

743
	q->ht = sfq_alloc(sizeof(q->ht[0]) * q->divisor);
E
Eric Dumazet 已提交
744 745
	q->slots = sfq_alloc(sizeof(q->slots[0]) * q->maxflows);
	if (!q->ht || !q->slots) {
746
		/* Note: sfq_destroy() will be called by our caller */
747
		return -ENOMEM;
748
	}
749

750 751 752
	for (i = 0; i < q->divisor; i++)
		q->ht[i] = SFQ_EMPTY_SLOT;

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

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

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

780 781 782 783 784 785 786 787 788 789 790
	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;

791 792
	if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt))
		goto nla_put_failure;
L
Linus Torvalds 已提交
793 794 795

	return skb->len;

796
nla_put_failure:
797
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
798 799 800
	return -1;
}

801 802 803 804 805
static struct Qdisc *sfq_leaf(struct Qdisc *sch, unsigned long arg)
{
	return NULL;
}

806 807 808 809 810
static unsigned long sfq_get(struct Qdisc *sch, u32 classid)
{
	return 0;
}

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

819 820 821 822
static void sfq_put(struct Qdisc *q, unsigned long cl)
{
}

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

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

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

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

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

860 861
static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
{
862 863 864 865 866 867
	struct sfq_sched_data *q = qdisc_priv(sch);
	unsigned int i;

	if (arg->stop)
		return;

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

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

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