sch_fifo.c 2.5 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 21 22
/*
 * net/sched/sch_fifo.c	The simplest FIFO queue.
 *
 *		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/errno.h>
#include <linux/skbuff.h>
#include <net/pkt_sched.h>

/* 1 band FIFO pseudo-"scheduler" */

struct fifo_sched_data
{
23
	u32 limit;
L
Linus Torvalds 已提交
24 25
};

26
static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
L
Linus Torvalds 已提交
27 28 29
{
	struct fifo_sched_data *q = qdisc_priv(sch);

30 31
	if (likely(sch->qstats.backlog + skb->len <= q->limit))
		return qdisc_enqueue_tail(skb, sch);
L
Linus Torvalds 已提交
32

33
	return qdisc_reshape_fail(skb, sch);
L
Linus Torvalds 已提交
34 35
}

36
static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
L
Linus Torvalds 已提交
37 38 39
{
	struct fifo_sched_data *q = qdisc_priv(sch);

40 41
	if (likely(skb_queue_len(&sch->q) < q->limit))
		return qdisc_enqueue_tail(skb, sch);
L
Linus Torvalds 已提交
42

43
	return qdisc_reshape_fail(skb, sch);
L
Linus Torvalds 已提交
44 45 46 47 48 49 50
}

static int fifo_init(struct Qdisc *sch, struct rtattr *opt)
{
	struct fifo_sched_data *q = qdisc_priv(sch);

	if (opt == NULL) {
51
		u32 limit = sch->dev->tx_queue_len ? : 1;
L
Linus Torvalds 已提交
52 53

		if (sch->ops == &bfifo_qdisc_ops)
54 55 56
			limit *= sch->dev->mtu;

		q->limit = limit;
L
Linus Torvalds 已提交
57 58
	} else {
		struct tc_fifo_qopt *ctl = RTA_DATA(opt);
59 60

		if (RTA_PAYLOAD(opt) < sizeof(*ctl))
L
Linus Torvalds 已提交
61
			return -EINVAL;
62

L
Linus Torvalds 已提交
63 64
		q->limit = ctl->limit;
	}
65

L
Linus Torvalds 已提交
66 67 68 69 70 71
	return 0;
}

static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb)
{
	struct fifo_sched_data *q = qdisc_priv(sch);
72
	struct tc_fifo_qopt opt = { .limit = q->limit };
L
Linus Torvalds 已提交
73 74 75 76 77 78 79 80 81 82 83 84

	RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
	return skb->len;

rtattr_failure:
	return -1;
}

struct Qdisc_ops pfifo_qdisc_ops = {
	.id		=	"pfifo",
	.priv_size	=	sizeof(struct fifo_sched_data),
	.enqueue	=	pfifo_enqueue,
85 86 87
	.dequeue	=	qdisc_dequeue_head,
	.requeue	=	qdisc_requeue,
	.drop		=	qdisc_queue_drop,
L
Linus Torvalds 已提交
88
	.init		=	fifo_init,
89
	.reset		=	qdisc_reset_queue,
L
Linus Torvalds 已提交
90 91 92 93 94 95 96 97 98
	.change		=	fifo_init,
	.dump		=	fifo_dump,
	.owner		=	THIS_MODULE,
};

struct Qdisc_ops bfifo_qdisc_ops = {
	.id		=	"bfifo",
	.priv_size	=	sizeof(struct fifo_sched_data),
	.enqueue	=	bfifo_enqueue,
99 100 101
	.dequeue	=	qdisc_dequeue_head,
	.requeue	=	qdisc_requeue,
	.drop		=	qdisc_queue_drop,
L
Linus Torvalds 已提交
102
	.init		=	fifo_init,
103
	.reset		=	qdisc_reset_queue,
L
Linus Torvalds 已提交
104 105 106 107 108 109 110
	.change		=	fifo_init,
	.dump		=	fifo_dump,
	.owner		=	THIS_MODULE,
};

EXPORT_SYMBOL(bfifo_qdisc_ops);
EXPORT_SYMBOL(pfifo_qdisc_ops);