sch_sfq.c 22.4 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>
E
Eric Dumazet 已提交
26
#include <net/flow_keys.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
}

159 160 161 162 163 164 165 166 167 168
/*
 * In order to be able to quickly rehash our queue when timer changes
 * q->perturbation, we store flow_keys in skb->cb[]
 */
struct sfq_skb_cb {
       struct flow_keys        keys;
};

static inline struct sfq_skb_cb *sfq_skb_cb(const struct sk_buff *skb)
{
169 170
	qdisc_cb_private_validate(skb, sizeof(struct sfq_skb_cb));
	return (struct sfq_skb_cb *)qdisc_skb_cb(skb)->data;
171 172
}

E
Eric Dumazet 已提交
173 174
static unsigned int sfq_hash(const struct sfq_sched_data *q,
			     const struct sk_buff *skb)
L
Linus Torvalds 已提交
175
{
176
	const struct flow_keys *keys = &sfq_skb_cb(skb)->keys;
E
Eric Dumazet 已提交
177 178
	unsigned int hash;

179 180 181
	hash = jhash_3words((__force u32)keys->dst,
			    (__force u32)keys->src ^ keys->ip_proto,
			    (__force u32)keys->ports, q->perturbation);
E
Eric Dumazet 已提交
182
	return hash & (q->divisor - 1);
L
Linus Torvalds 已提交
183 184
}

185 186 187 188 189
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 已提交
190
	struct tcf_proto *fl;
191 192 193 194
	int result;

	if (TC_H_MAJ(skb->priority) == sch->handle &&
	    TC_H_MIN(skb->priority) > 0 &&
195
	    TC_H_MIN(skb->priority) <= q->divisor)
196 197
		return TC_H_MIN(skb->priority);

J
John Fastabend 已提交
198 199
	fl = rcu_dereference_bh(q->filter_list);
	if (!fl) {
200
		skb_flow_dissect(skb, &sfq_skb_cb(skb)->keys);
201
		return sfq_hash(q, skb) + 1;
202
	}
203

204
	*qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
J
John Fastabend 已提交
205
	result = tc_classify(skb, fl, &res);
206 207 208 209 210
	if (result >= 0) {
#ifdef CONFIG_NET_CLS_ACT
		switch (result) {
		case TC_ACT_STOLEN:
		case TC_ACT_QUEUED:
211
			*qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
212 213 214 215
		case TC_ACT_SHOT:
			return 0;
		}
#endif
216
		if (TC_H_MIN(res.classid) <= q->divisor)
217 218 219 220 221
			return TC_H_MIN(res.classid);
	}
	return 0;
}

222
/*
E
Eric Dumazet 已提交
223
 * x : slot number [0 .. SFQ_MAX_FLOWS - 1]
224
 */
L
Linus Torvalds 已提交
225 226 227
static inline void sfq_link(struct sfq_sched_data *q, sfq_index x)
{
	sfq_index p, n;
E
Eric Dumazet 已提交
228 229
	struct sfq_slot *slot = &q->slots[x];
	int qlen = slot->qlen;
230

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

E
Eric Dumazet 已提交
234 235
	slot->dep.next = n;
	slot->dep.prev = p;
236 237 238

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

241
#define sfq_unlink(q, x, n, p)			\
242 243 244 245 246 247
	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)
248 249


L
Linus Torvalds 已提交
250 251 252
static inline void sfq_dec(struct sfq_sched_data *q, sfq_index x)
{
	sfq_index p, n;
253
	int d;
L
Linus Torvalds 已提交
254

255
	sfq_unlink(q, x, n, p);
L
Linus Torvalds 已提交
256

257 258 259
	d = q->slots[x].qlen--;
	if (n == p && q->cur_depth == d)
		q->cur_depth--;
L
Linus Torvalds 已提交
260 261 262 263 264 265 266 267
	sfq_link(q, x);
}

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

268
	sfq_unlink(q, x, n, p);
L
Linus Torvalds 已提交
269

270 271 272
	d = ++q->slots[x].qlen;
	if (q->cur_depth < d)
		q->cur_depth = d;
L
Linus Torvalds 已提交
273 274 275
	sfq_link(q, x);
}

276 277 278 279 280 281 282 283
/* 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 已提交
284
	skb->prev->next = (struct sk_buff *)slot;
285 286 287 288 289 290 291 292 293 294
	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 已提交
295
	skb->next->prev = (struct sk_buff *)slot;
296 297 298 299 300 301
	skb->next = skb->prev = NULL;
	return skb;
}

static inline void slot_queue_init(struct sfq_slot *slot)
{
E
Eric Dumazet 已提交
302
	memset(slot, 0, sizeof(*slot));
303 304 305 306 307 308 309 310 311 312 313 314
	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 已提交
315 316 317
static unsigned int sfq_drop(struct Qdisc *sch)
{
	struct sfq_sched_data *q = qdisc_priv(sch);
318
	sfq_index x, d = q->cur_depth;
L
Linus Torvalds 已提交
319 320
	struct sk_buff *skb;
	unsigned int len;
321
	struct sfq_slot *slot;
L
Linus Torvalds 已提交
322

323
	/* Queue is full! Find the longest slot and drop tail packet from it */
L
Linus Torvalds 已提交
324
	if (d > 1) {
325 326 327
		x = q->dep[d].next;
		slot = &q->slots[x];
drop:
E
Eric Dumazet 已提交
328
		skb = q->headdrop ? slot_dequeue_head(slot) : slot_dequeue_tail(slot);
329
		len = qdisc_pkt_len(skb);
330
		slot->backlog -= len;
L
Linus Torvalds 已提交
331
		sfq_dec(q, x);
332
		kfree_skb(skb);
L
Linus Torvalds 已提交
333
		sch->q.qlen--;
334 335
		qdisc_qstats_drop(sch);
		qdisc_qstats_backlog_dec(sch, skb);
L
Linus Torvalds 已提交
336 337 338 339 340
		return len;
	}

	if (d == 1) {
		/* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
341 342 343 344 345
		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 已提交
346 347 348 349 350
	}

	return 0;
}

351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
/* 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 已提交
368
static int
369
sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
L
Linus Torvalds 已提交
370 371
{
	struct sfq_sched_data *q = qdisc_priv(sch);
372
	unsigned int hash;
373
	sfq_index x, qlen;
374
	struct sfq_slot *slot;
375
	int uninitialized_var(ret);
376 377
	struct sk_buff *head;
	int delta;
378 379 380

	hash = sfq_classify(skb, sch, &ret);
	if (hash == 0) {
381
		if (ret & __NET_XMIT_BYPASS)
382
			qdisc_qstats_drop(sch);
383 384 385 386
		kfree_skb(skb);
		return ret;
	}
	hash--;
L
Linus Torvalds 已提交
387 388

	x = q->ht[hash];
389 390 391
	slot = &q->slots[x];
	if (x == SFQ_EMPTY_SLOT) {
		x = q->dep[0].next; /* get a free slot */
E
Eric Dumazet 已提交
392 393
		if (x >= SFQ_MAX_FLOWS)
			return qdisc_drop(skb, sch);
394 395 396
		q->ht[hash] = x;
		slot = &q->slots[x];
		slot->hash = hash;
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
		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:
412
			qdisc_qstats_overlimit(sch);
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
			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:
429
			qdisc_qstats_overlimit(sch);
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
			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 已提交
445
	}
446

E
Eric Dumazet 已提交
447
	if (slot->qlen >= q->maxdepth) {
448 449
congestion_drop:
		if (!sfq_headdrop(q))
E
Eric Dumazet 已提交
450 451
			return qdisc_drop(skb, sch);

452
		/* We know we have at least one packet in queue */
E
Eric Dumazet 已提交
453
		head = slot_dequeue_head(slot);
454 455 456
		delta = qdisc_pkt_len(head) - qdisc_pkt_len(skb);
		sch->qstats.backlog -= delta;
		slot->backlog -= delta;
E
Eric Dumazet 已提交
457 458 459 460 461
		qdisc_drop(head, sch);

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

463
enqueue:
464
	qdisc_qstats_backlog_inc(sch, skb);
465
	slot->backlog += qdisc_pkt_len(skb);
466
	slot_queue_add(slot, skb);
L
Linus Torvalds 已提交
467
	sfq_inc(q, x);
468 469 470
	if (slot->qlen == 1) {		/* The flow is new */
		if (q->tail == NULL) {	/* It is the first flow */
			slot->next = x;
L
Linus Torvalds 已提交
471
		} else {
472 473
			slot->next = q->tail->next;
			q->tail->next = x;
L
Linus Torvalds 已提交
474
		}
475 476 477 478 479
		/* 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;
480
		/* We could use a bigger initial quantum for new flows */
481
		slot->allot = q->scaled_quantum;
L
Linus Torvalds 已提交
482
	}
483
	if (++sch->q.qlen <= q->limit)
484
		return NET_XMIT_SUCCESS;
L
Linus Torvalds 已提交
485

486
	qlen = slot->qlen;
L
Linus Torvalds 已提交
487
	sfq_drop(sch);
488 489 490
	/* Return Congestion Notification only if we dropped a packet
	 * from this flow.
	 */
E
Eric Dumazet 已提交
491 492 493 494 495 496
	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 已提交
497 498 499
}

static struct sk_buff *
500
sfq_dequeue(struct Qdisc *sch)
L
Linus Torvalds 已提交
501 502 503
{
	struct sfq_sched_data *q = qdisc_priv(sch);
	struct sk_buff *skb;
504
	sfq_index a, next_a;
505
	struct sfq_slot *slot;
L
Linus Torvalds 已提交
506 507

	/* No active slots */
508
	if (q->tail == NULL)
L
Linus Torvalds 已提交
509 510
		return NULL;

511
next_slot:
512 513
	a = q->tail->next;
	slot = &q->slots[a];
514 515 516 517 518
	if (slot->allot <= 0) {
		q->tail = slot;
		slot->allot += q->scaled_quantum;
		goto next_slot;
	}
519
	skb = slot_dequeue_head(slot);
L
Linus Torvalds 已提交
520
	sfq_dec(q, a);
521
	qdisc_bstats_update(sch, skb);
L
Linus Torvalds 已提交
522
	sch->q.qlen--;
523
	qdisc_qstats_backlog_dec(sch, skb);
524
	slot->backlog -= qdisc_pkt_len(skb);
L
Linus Torvalds 已提交
525
	/* Is the slot empty? */
526 527 528
	if (slot->qlen == 0) {
		q->ht[slot->hash] = SFQ_EMPTY_SLOT;
		next_a = slot->next;
529
		if (a == next_a) {
530
			q->tail = NULL; /* no more active slots */
L
Linus Torvalds 已提交
531 532
			return skb;
		}
533
		q->tail->next = next_a;
534 535
	} else {
		slot->allot -= SFQ_ALLOT_SIZE(qdisc_pkt_len(skb));
L
Linus Torvalds 已提交
536 537 538 539 540
	}
	return skb;
}

static void
541
sfq_reset(struct Qdisc *sch)
L
Linus Torvalds 已提交
542 543 544 545 546 547 548
{
	struct sk_buff *skb;

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

549 550 551 552 553 554
/*
 * 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 已提交
555
static void sfq_rehash(struct Qdisc *sch)
556
{
E
Eric Dumazet 已提交
557
	struct sfq_sched_data *q = qdisc_priv(sch);
558 559 560 561
	struct sk_buff *skb;
	int i;
	struct sfq_slot *slot;
	struct sk_buff_head list;
E
Eric Dumazet 已提交
562
	int dropped = 0;
563 564 565

	__skb_queue_head_init(&list);

E
Eric Dumazet 已提交
566
	for (i = 0; i < q->maxflows; i++) {
567 568 569 570 571 572 573 574
		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);
		}
575 576
		slot->backlog = 0;
		red_set_vars(&slot->vars);
577 578 579 580 581 582 583 584 585 586 587
		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 已提交
588
			if (x >= SFQ_MAX_FLOWS) {
589 590
drop:
				qdisc_qstats_backlog_dec(sch, skb);
E
Eric Dumazet 已提交
591 592 593 594
				kfree_skb(skb);
				dropped++;
				continue;
			}
595 596 597 598
			q->ht[hash] = x;
			slot = &q->slots[x];
			slot->hash = hash;
		}
E
Eric Dumazet 已提交
599 600
		if (slot->qlen >= q->maxdepth)
			goto drop;
601
		slot_queue_add(slot, skb);
602 603 604 605 606
		if (q->red_parms)
			slot->vars.qavg = red_calc_qavg(q->red_parms,
							&slot->vars,
							slot->backlog);
		slot->backlog += qdisc_pkt_len(skb);
607 608 609 610 611 612 613 614 615 616 617 618
		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 已提交
619 620
	sch->q.qlen -= dropped;
	qdisc_tree_decrease_qlen(sch, dropped);
621 622
}

L
Linus Torvalds 已提交
623 624
static void sfq_perturbation(unsigned long arg)
{
625
	struct Qdisc *sch = (struct Qdisc *)arg;
L
Linus Torvalds 已提交
626
	struct sfq_sched_data *q = qdisc_priv(sch);
627
	spinlock_t *root_lock = qdisc_lock(qdisc_root_sleeping(sch));
L
Linus Torvalds 已提交
628

629
	spin_lock(root_lock);
630
	q->perturbation = prandom_u32();
631
	if (!q->filter_list && q->tail)
E
Eric Dumazet 已提交
632
		sfq_rehash(sch);
633
	spin_unlock(root_lock);
L
Linus Torvalds 已提交
634

635 636
	if (q->perturb_period)
		mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
L
Linus Torvalds 已提交
637 638
}

639
static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
L
Linus Torvalds 已提交
640 641
{
	struct sfq_sched_data *q = qdisc_priv(sch);
642
	struct tc_sfq_qopt *ctl = nla_data(opt);
E
Eric Dumazet 已提交
643
	struct tc_sfq_qopt_v1 *ctl_v1 = NULL;
644
	unsigned int qlen;
645
	struct red_parms *p = NULL;
L
Linus Torvalds 已提交
646

647
	if (opt->nla_len < nla_attr_size(sizeof(*ctl)))
L
Linus Torvalds 已提交
648
		return -EINVAL;
E
Eric Dumazet 已提交
649 650
	if (opt->nla_len >= nla_attr_size(sizeof(*ctl_v1)))
		ctl_v1 = nla_data(opt);
S
stephen hemminger 已提交
651 652 653
	if (ctl->divisor &&
	    (!is_power_of_2(ctl->divisor) || ctl->divisor > 65536))
		return -EINVAL;
654 655 656 657 658
	if (ctl_v1 && ctl_v1->qth_min) {
		p = kmalloc(sizeof(*p), GFP_KERNEL);
		if (!p)
			return -ENOMEM;
	}
L
Linus Torvalds 已提交
659
	sch_tree_lock(sch);
E
Eric Dumazet 已提交
660 661 662 663
	if (ctl->quantum) {
		q->quantum = ctl->quantum;
		q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum);
	}
664
	q->perturb_period = ctl->perturb_period * HZ;
E
Eric Dumazet 已提交
665 666 667
	if (ctl->flows)
		q->maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS);
	if (ctl->divisor) {
668
		q->divisor = ctl->divisor;
E
Eric Dumazet 已提交
669 670 671 672 673
		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);
674 675 676 677 678 679 680 681 682 683
		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 已提交
684 685 686 687 688 689 690
		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);
	}

691
	qlen = sch->q.qlen;
692
	while (sch->q.qlen > q->limit)
L
Linus Torvalds 已提交
693
		sfq_drop(sch);
694
	qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
L
Linus Torvalds 已提交
695 696 697

	del_timer(&q->perturb_timer);
	if (q->perturb_period) {
698
		mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
699
		q->perturbation = prandom_u32();
L
Linus Torvalds 已提交
700 701
	}
	sch_tree_unlock(sch);
702
	kfree(p);
L
Linus Torvalds 已提交
703 704 705
	return 0;
}

706 707 708 709 710 711 712 713 714 715 716
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 已提交
717
	kvfree(addr);
718 719 720 721 722 723 724 725 726 727
}

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 已提交
728
	sfq_free(q->slots);
729
	kfree(q->red_parms);
730 731
}

732
static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
L
Linus Torvalds 已提交
733 734 735 736
{
	struct sfq_sched_data *q = qdisc_priv(sch);
	int i;

737
	q->perturb_timer.function = sfq_perturbation;
738
	q->perturb_timer.data = (unsigned long)sch;
739
	init_timer_deferrable(&q->perturb_timer);
L
Linus Torvalds 已提交
740

E
Eric Dumazet 已提交
741 742 743
	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 已提交
744
	}
745

E
Eric Dumazet 已提交
746 747
	q->limit = SFQ_MAX_DEPTH;
	q->maxdepth = SFQ_MAX_DEPTH;
748 749
	q->cur_depth = 0;
	q->tail = NULL;
750
	q->divisor = SFQ_DEFAULT_HASH_DIVISOR;
E
Eric Dumazet 已提交
751
	q->maxflows = SFQ_DEFAULT_FLOWS;
752 753 754
	q->quantum = psched_mtu(qdisc_dev(sch));
	q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum);
	q->perturb_period = 0;
755
	q->perturbation = prandom_u32();
756 757

	if (opt) {
L
Linus Torvalds 已提交
758 759 760 761
		int err = sfq_change(sch, opt);
		if (err)
			return err;
	}
762

763
	q->ht = sfq_alloc(sizeof(q->ht[0]) * q->divisor);
E
Eric Dumazet 已提交
764 765
	q->slots = sfq_alloc(sizeof(q->slots[0]) * q->maxflows);
	if (!q->ht || !q->slots) {
766
		sfq_destroy(sch);
767
		return -ENOMEM;
768
	}
769 770 771
	for (i = 0; i < q->divisor; i++)
		q->ht[i] = SFQ_EMPTY_SLOT;

E
Eric Dumazet 已提交
772
	for (i = 0; i < q->maxflows; i++) {
E
Eric Dumazet 已提交
773
		slot_queue_init(&q->slots[i]);
L
Linus Torvalds 已提交
774
		sfq_link(q, i);
E
Eric Dumazet 已提交
775
	}
776 777 778 779
	if (q->limit >= 1)
		sch->flags |= TCQ_F_CAN_BYPASS;
	else
		sch->flags &= ~TCQ_F_CAN_BYPASS;
L
Linus Torvalds 已提交
780 781 782 783 784 785
	return 0;
}

static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
{
	struct sfq_sched_data *q = qdisc_priv(sch);
786
	unsigned char *b = skb_tail_pointer(skb);
E
Eric Dumazet 已提交
787
	struct tc_sfq_qopt_v1 opt;
788
	struct red_parms *p = q->red_parms;
E
Eric Dumazet 已提交
789 790 791 792 793 794 795 796 797

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

799 800 801 802 803 804 805 806 807 808 809
	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;

810 811
	if (nla_put(skb, TCA_OPTIONS, sizeof(opt), &opt))
		goto nla_put_failure;
L
Linus Torvalds 已提交
812 813 814

	return skb->len;

815
nla_put_failure:
816
	nlmsg_trim(skb, b);
L
Linus Torvalds 已提交
817 818 819
	return -1;
}

820 821 822 823 824
static struct Qdisc *sfq_leaf(struct Qdisc *sch, unsigned long arg)
{
	return NULL;
}

825 826 827 828 829
static unsigned long sfq_get(struct Qdisc *sch, u32 classid)
{
	return 0;
}

830 831 832
static unsigned long sfq_bind(struct Qdisc *sch, unsigned long parent,
			      u32 classid)
{
833 834
	/* we cannot bypass queue discipline anymore */
	sch->flags &= ~TCQ_F_CAN_BYPASS;
835 836 837
	return 0;
}

838 839 840 841
static void sfq_put(struct Qdisc *q, unsigned long cl)
{
}

J
John Fastabend 已提交
842 843
static struct tcf_proto __rcu **sfq_find_tcf(struct Qdisc *sch,
					     unsigned long cl)
844 845 846 847 848 849 850 851
{
	struct sfq_sched_data *q = qdisc_priv(sch);

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

852 853 854 855 856 857 858 859 860 861 862
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 已提交
863 864 865
	sfq_index idx = q->ht[cl - 1];
	struct gnet_stats_queue qs = { 0 };
	struct tc_sfq_xstats xstats = { 0 };
866

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

870
		xstats.allot = slot->allot << SFQ_ALLOT_SHIFT;
E
Eric Dumazet 已提交
871
		qs.qlen = slot->qlen;
872
		qs.backlog = slot->backlog;
E
Eric Dumazet 已提交
873
	}
874
	if (gnet_stats_copy_queue(d, &qs, qs.qlen) < 0)
875 876 877 878
		return -1;
	return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
}

879 880
static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
{
881 882 883 884 885 886
	struct sfq_sched_data *q = qdisc_priv(sch);
	unsigned int i;

	if (arg->stop)
		return;

887
	for (i = 0; i < q->divisor; i++) {
888
		if (q->ht[i] == SFQ_EMPTY_SLOT ||
889 890 891 892 893 894 895 896 897 898
		    arg->count < arg->skip) {
			arg->count++;
			continue;
		}
		if (arg->fn(sch, i + 1, arg) < 0) {
			arg->stop = 1;
			break;
		}
		arg->count++;
	}
899 900 901
}

static const struct Qdisc_class_ops sfq_class_ops = {
902
	.leaf		=	sfq_leaf,
903
	.get		=	sfq_get,
904
	.put		=	sfq_put,
905
	.tcf_chain	=	sfq_find_tcf,
906
	.bind_tcf	=	sfq_bind,
907
	.unbind_tcf	=	sfq_put,
908 909
	.dump		=	sfq_dump_class,
	.dump_stats	=	sfq_dump_class_stats,
910 911 912
	.walk		=	sfq_walk,
};

913
static struct Qdisc_ops sfq_qdisc_ops __read_mostly = {
914
	.cl_ops		=	&sfq_class_ops,
L
Linus Torvalds 已提交
915 916 917 918
	.id		=	"sfq",
	.priv_size	=	sizeof(struct sfq_sched_data),
	.enqueue	=	sfq_enqueue,
	.dequeue	=	sfq_dequeue,
919
	.peek		=	qdisc_peek_dequeued,
L
Linus Torvalds 已提交
920 921 922 923 924 925 926 927 928 929 930 931 932
	.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);
}
933
static void __exit sfq_module_exit(void)
L
Linus Torvalds 已提交
934 935 936 937 938 939
{
	unregister_qdisc(&sfq_qdisc_ops);
}
module_init(sfq_module_init)
module_exit(sfq_module_exit)
MODULE_LICENSE("GPL");