xref: /openbmc/linux/net/sched/sch_fifo.c (revision aaae3013d186d71a01e1059c9633c4ec8729d891)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * net/sched/sch_fifo.c	The simplest FIFO queue.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
51da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
61da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
71da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
101da177e4SLinus Torvalds  */
111da177e4SLinus Torvalds 
121da177e4SLinus Torvalds #include <linux/config.h>
131da177e4SLinus Torvalds #include <linux/module.h>
141da177e4SLinus Torvalds #include <asm/uaccess.h>
151da177e4SLinus Torvalds #include <asm/system.h>
161da177e4SLinus Torvalds #include <linux/bitops.h>
171da177e4SLinus Torvalds #include <linux/types.h>
181da177e4SLinus Torvalds #include <linux/kernel.h>
191da177e4SLinus Torvalds #include <linux/sched.h>
201da177e4SLinus Torvalds #include <linux/string.h>
211da177e4SLinus Torvalds #include <linux/mm.h>
221da177e4SLinus Torvalds #include <linux/socket.h>
231da177e4SLinus Torvalds #include <linux/sockios.h>
241da177e4SLinus Torvalds #include <linux/in.h>
251da177e4SLinus Torvalds #include <linux/errno.h>
261da177e4SLinus Torvalds #include <linux/interrupt.h>
271da177e4SLinus Torvalds #include <linux/if_ether.h>
281da177e4SLinus Torvalds #include <linux/inet.h>
291da177e4SLinus Torvalds #include <linux/netdevice.h>
301da177e4SLinus Torvalds #include <linux/etherdevice.h>
311da177e4SLinus Torvalds #include <linux/notifier.h>
321da177e4SLinus Torvalds #include <net/ip.h>
331da177e4SLinus Torvalds #include <net/route.h>
341da177e4SLinus Torvalds #include <linux/skbuff.h>
351da177e4SLinus Torvalds #include <net/sock.h>
361da177e4SLinus Torvalds #include <net/pkt_sched.h>
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds /* 1 band FIFO pseudo-"scheduler" */
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds struct fifo_sched_data
411da177e4SLinus Torvalds {
421da177e4SLinus Torvalds 	unsigned limit;
431da177e4SLinus Torvalds };
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds static int
461da177e4SLinus Torvalds bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
471da177e4SLinus Torvalds {
481da177e4SLinus Torvalds 	struct fifo_sched_data *q = qdisc_priv(sch);
491da177e4SLinus Torvalds 
50*aaae3013SThomas Graf 	if (likely(sch->qstats.backlog + skb->len <= q->limit))
51*aaae3013SThomas Graf 		return qdisc_enqueue_tail(skb, sch);
521da177e4SLinus Torvalds 
53*aaae3013SThomas Graf 	return qdisc_reshape_fail(skb, sch);
541da177e4SLinus Torvalds }
551da177e4SLinus Torvalds 
561da177e4SLinus Torvalds static int
571da177e4SLinus Torvalds pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
581da177e4SLinus Torvalds {
591da177e4SLinus Torvalds 	struct fifo_sched_data *q = qdisc_priv(sch);
601da177e4SLinus Torvalds 
61*aaae3013SThomas Graf 	if (likely(skb_queue_len(&sch->q) < q->limit))
62*aaae3013SThomas Graf 		return qdisc_enqueue_tail(skb, sch);
631da177e4SLinus Torvalds 
64*aaae3013SThomas Graf 	return qdisc_reshape_fail(skb, sch);
651da177e4SLinus Torvalds }
661da177e4SLinus Torvalds 
671da177e4SLinus Torvalds static int fifo_init(struct Qdisc *sch, struct rtattr *opt)
681da177e4SLinus Torvalds {
691da177e4SLinus Torvalds 	struct fifo_sched_data *q = qdisc_priv(sch);
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds 	if (opt == NULL) {
721da177e4SLinus Torvalds 		unsigned int limit = sch->dev->tx_queue_len ? : 1;
731da177e4SLinus Torvalds 
741da177e4SLinus Torvalds 		if (sch->ops == &bfifo_qdisc_ops)
751da177e4SLinus Torvalds 			q->limit = limit*sch->dev->mtu;
761da177e4SLinus Torvalds 		else
771da177e4SLinus Torvalds 			q->limit = limit;
781da177e4SLinus Torvalds 	} else {
791da177e4SLinus Torvalds 		struct tc_fifo_qopt *ctl = RTA_DATA(opt);
801da177e4SLinus Torvalds 		if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
811da177e4SLinus Torvalds 			return -EINVAL;
821da177e4SLinus Torvalds 		q->limit = ctl->limit;
831da177e4SLinus Torvalds 	}
841da177e4SLinus Torvalds 	return 0;
851da177e4SLinus Torvalds }
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb)
881da177e4SLinus Torvalds {
891da177e4SLinus Torvalds 	struct fifo_sched_data *q = qdisc_priv(sch);
901da177e4SLinus Torvalds 	unsigned char	 *b = skb->tail;
911da177e4SLinus Torvalds 	struct tc_fifo_qopt opt;
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds 	opt.limit = q->limit;
941da177e4SLinus Torvalds 	RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds 	return skb->len;
971da177e4SLinus Torvalds 
981da177e4SLinus Torvalds rtattr_failure:
991da177e4SLinus Torvalds 	skb_trim(skb, b - skb->data);
1001da177e4SLinus Torvalds 	return -1;
1011da177e4SLinus Torvalds }
1021da177e4SLinus Torvalds 
1031da177e4SLinus Torvalds struct Qdisc_ops pfifo_qdisc_ops = {
1041da177e4SLinus Torvalds 	.next		=	NULL,
1051da177e4SLinus Torvalds 	.cl_ops		=	NULL,
1061da177e4SLinus Torvalds 	.id		=	"pfifo",
1071da177e4SLinus Torvalds 	.priv_size	=	sizeof(struct fifo_sched_data),
1081da177e4SLinus Torvalds 	.enqueue	=	pfifo_enqueue,
109*aaae3013SThomas Graf 	.dequeue	=	qdisc_dequeue_head,
110*aaae3013SThomas Graf 	.requeue	=	qdisc_requeue,
111*aaae3013SThomas Graf 	.drop		=	qdisc_queue_drop,
1121da177e4SLinus Torvalds 	.init		=	fifo_init,
113*aaae3013SThomas Graf 	.reset		=	qdisc_reset_queue,
1141da177e4SLinus Torvalds 	.destroy	=	NULL,
1151da177e4SLinus Torvalds 	.change		=	fifo_init,
1161da177e4SLinus Torvalds 	.dump		=	fifo_dump,
1171da177e4SLinus Torvalds 	.owner		=	THIS_MODULE,
1181da177e4SLinus Torvalds };
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds struct Qdisc_ops bfifo_qdisc_ops = {
1211da177e4SLinus Torvalds 	.next		=	NULL,
1221da177e4SLinus Torvalds 	.cl_ops		=	NULL,
1231da177e4SLinus Torvalds 	.id		=	"bfifo",
1241da177e4SLinus Torvalds 	.priv_size	=	sizeof(struct fifo_sched_data),
1251da177e4SLinus Torvalds 	.enqueue	=	bfifo_enqueue,
126*aaae3013SThomas Graf 	.dequeue	=	qdisc_dequeue_head,
127*aaae3013SThomas Graf 	.requeue	=	qdisc_requeue,
128*aaae3013SThomas Graf 	.drop		=	qdisc_queue_drop,
1291da177e4SLinus Torvalds 	.init		=	fifo_init,
130*aaae3013SThomas Graf 	.reset		=	qdisc_reset_queue,
1311da177e4SLinus Torvalds 	.destroy	=	NULL,
1321da177e4SLinus Torvalds 	.change		=	fifo_init,
1331da177e4SLinus Torvalds 	.dump		=	fifo_dump,
1341da177e4SLinus Torvalds 	.owner		=	THIS_MODULE,
1351da177e4SLinus Torvalds };
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds EXPORT_SYMBOL(bfifo_qdisc_ops);
1381da177e4SLinus Torvalds EXPORT_SYMBOL(pfifo_qdisc_ops);
139