2005-04-17 02:20:36 +04:00
/*
* 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/netdevice.h>
# include <linux/skbuff.h>
# include <net/pkt_sched.h>
/* 1 band FIFO pseudo-"scheduler" */
struct fifo_sched_data
{
2005-06-19 09:58:00 +04:00
u32 limit ;
2005-04-17 02:20:36 +04:00
} ;
2005-06-19 09:58:00 +04:00
static int bfifo_enqueue ( struct sk_buff * skb , struct Qdisc * sch )
2005-04-17 02:20:36 +04:00
{
struct fifo_sched_data * q = qdisc_priv ( sch ) ;
2005-06-19 09:57:42 +04:00
if ( likely ( sch - > qstats . backlog + skb - > len < = q - > limit ) )
return qdisc_enqueue_tail ( skb , sch ) ;
2005-04-17 02:20:36 +04:00
2005-06-19 09:57:42 +04:00
return qdisc_reshape_fail ( skb , sch ) ;
2005-04-17 02:20:36 +04:00
}
2005-06-19 09:58:00 +04:00
static int pfifo_enqueue ( struct sk_buff * skb , struct Qdisc * sch )
2005-04-17 02:20:36 +04:00
{
struct fifo_sched_data * q = qdisc_priv ( sch ) ;
2005-06-19 09:57:42 +04:00
if ( likely ( skb_queue_len ( & sch - > q ) < q - > limit ) )
return qdisc_enqueue_tail ( skb , sch ) ;
2005-04-17 02:20:36 +04:00
2005-06-19 09:57:42 +04:00
return qdisc_reshape_fail ( skb , sch ) ;
2005-04-17 02:20:36 +04:00
}
static int fifo_init ( struct Qdisc * sch , struct rtattr * opt )
{
struct fifo_sched_data * q = qdisc_priv ( sch ) ;
if ( opt = = NULL ) {
2005-06-19 09:58:00 +04:00
u32 limit = sch - > dev - > tx_queue_len ? : 1 ;
2005-04-17 02:20:36 +04:00
if ( sch - > ops = = & bfifo_qdisc_ops )
2005-06-19 09:58:00 +04:00
limit * = sch - > dev - > mtu ;
q - > limit = limit ;
2005-04-17 02:20:36 +04:00
} else {
struct tc_fifo_qopt * ctl = RTA_DATA ( opt ) ;
2005-06-19 09:58:00 +04:00
if ( RTA_PAYLOAD ( opt ) < sizeof ( * ctl ) )
2005-04-17 02:20:36 +04:00
return - EINVAL ;
2005-06-19 09:58:00 +04:00
2005-04-17 02:20:36 +04:00
q - > limit = ctl - > limit ;
}
2005-06-19 09:58:00 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
}
static int fifo_dump ( struct Qdisc * sch , struct sk_buff * skb )
{
struct fifo_sched_data * q = qdisc_priv ( sch ) ;
2005-06-19 09:58:00 +04:00
struct tc_fifo_qopt opt = { . limit = q - > limit } ;
2005-04-17 02:20:36 +04:00
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 ,
2005-06-19 09:57:42 +04:00
. dequeue = qdisc_dequeue_head ,
. requeue = qdisc_requeue ,
. drop = qdisc_queue_drop ,
2005-04-17 02:20:36 +04:00
. init = fifo_init ,
2005-06-19 09:57:42 +04:00
. reset = qdisc_reset_queue ,
2005-04-17 02:20:36 +04:00
. 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 ,
2005-06-19 09:57:42 +04:00
. dequeue = qdisc_dequeue_head ,
. requeue = qdisc_requeue ,
. drop = qdisc_queue_drop ,
2005-04-17 02:20:36 +04:00
. init = fifo_init ,
2005-06-19 09:57:42 +04:00
. reset = qdisc_reset_queue ,
2005-04-17 02:20:36 +04:00
. change = fifo_init ,
. dump = fifo_dump ,
. owner = THIS_MODULE ,
} ;
EXPORT_SYMBOL ( bfifo_qdisc_ops ) ;
EXPORT_SYMBOL ( pfifo_qdisc_ops ) ;