patch-2.1.99 linux/net/sched/sch_fifo.c
Next file: linux/net/sched/sch_generic.c
Previous file: linux/net/sched/sch_csz.c
Back to the patch index
Back to the overall index
- Lines: 275
- Date:
Tue Apr 28 11:10:11 1998
- Orig file:
v2.1.98/linux/net/sched/sch_fifo.c
- Orig date:
Thu Feb 12 20:56:15 1998
diff -u --recursive --new-file v2.1.98/linux/net/sched/sch_fifo.c linux/net/sched/sch_fifo.c
@@ -1,9 +1,15 @@
/*
- * net/sched/sch_fifo.c Simple FIFO "scheduler"
+ * 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/config.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/bitops.h>
@@ -32,9 +38,7 @@
struct fifo_sched_data
{
- int qmaxbytes;
- int qmaxlen;
- int qbytes;
+ unsigned limit;
};
static int
@@ -42,41 +46,62 @@
{
struct fifo_sched_data *q = (struct fifo_sched_data *)sch->data;
- if (q->qbytes <= q->qmaxbytes) {
- skb_queue_tail(&sch->q, skb);
- q->qbytes += skb->len;
- return 0;
+ if (sch->stats.backlog <= q->limit) {
+ __skb_queue_tail(&sch->q, skb);
+ sch->stats.backlog += skb->len;
+ sch->stats.bytes += skb->len;
+ sch->stats.packets++;
+ return 1;
}
- kfree_skb(skb);
+ sch->stats.drops++;
+#ifdef CONFIG_NET_CLS_POLICE
+ if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch))
+#endif
+ kfree_skb(skb);
+ return 0;
+}
+
+static int
+bfifo_requeue(struct sk_buff *skb, struct Qdisc* sch)
+{
+ __skb_queue_head(&sch->q, skb);
+ sch->stats.backlog += skb->len;
return 1;
}
static struct sk_buff *
bfifo_dequeue(struct Qdisc* sch)
{
- struct fifo_sched_data *q = (struct fifo_sched_data *)sch->data;
struct sk_buff *skb;
- skb = skb_dequeue(&sch->q);
+ skb = __skb_dequeue(&sch->q);
if (skb)
- q->qbytes -= skb->len;
+ sch->stats.backlog -= skb->len;
return skb;
}
-static void
-bfifo_reset(struct Qdisc* sch)
+static int
+fifo_drop(struct Qdisc* sch)
{
- struct fifo_sched_data *q = (struct fifo_sched_data *)sch->data;
struct sk_buff *skb;
- while((skb=skb_dequeue(&sch->q)) != NULL) {
- q->qbytes -= skb->len;
+ skb = __skb_dequeue_tail(&sch->q);
+ if (skb) {
+ sch->stats.backlog -= skb->len;
kfree_skb(skb);
+ return 1;
}
- if (q->qbytes) {
- printk("fifo_reset: qbytes=%d\n", q->qbytes);
- q->qbytes = 0;
- }
+ return 0;
+}
+
+static void
+fifo_reset(struct Qdisc* sch)
+{
+ struct sk_buff *skb;
+
+ while ((skb=__skb_dequeue(&sch->q)) != NULL)
+ kfree_skb(skb);
+ sch->stats.backlog = 0;
}
static int
@@ -84,96 +109,106 @@
{
struct fifo_sched_data *q = (struct fifo_sched_data *)sch->data;
- if (sch->q.qlen <= q->qmaxlen) {
- skb_queue_tail(&sch->q, skb);
- return 0;
+ if (sch->q.qlen <= q->limit) {
+ __skb_queue_tail(&sch->q, skb);
+ sch->stats.bytes += skb->len;
+ sch->stats.packets++;
+ return 1;
}
- kfree_skb(skb);
+ sch->stats.drops++;
+#ifdef CONFIG_NET_CLS_POLICE
+ if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch))
+#endif
+ kfree_skb(skb);
+ return 0;
+}
+
+static int
+pfifo_requeue(struct sk_buff *skb, struct Qdisc* sch)
+{
+ __skb_queue_head(&sch->q, skb);
return 1;
}
+
static struct sk_buff *
pfifo_dequeue(struct Qdisc* sch)
{
- return skb_dequeue(&sch->q);
+ return __skb_dequeue(&sch->q);
}
-static void
-pfifo_reset(struct Qdisc* sch)
+
+static int fifo_init(struct Qdisc *sch, struct rtattr *opt)
{
- struct sk_buff *skb;
+ struct fifo_sched_data *q = (void*)sch->data;
- while((skb=skb_dequeue(&sch->q))!=NULL)
- kfree_skb(skb);
+ if (opt == NULL) {
+ q->limit = sch->dev->tx_queue_len;
+ if (sch->ops == &bfifo_qdisc_ops)
+ q->limit *= sch->dev->mtu;
+ } else {
+ struct tc_fifo_qopt *ctl = RTA_DATA(opt);
+ if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
+ return -EINVAL;
+ q->limit = ctl->limit;
+ }
+ return 0;
}
-
-static int fifo_init(struct Qdisc *sch, void *arg /* int bytes, int pkts */)
+#ifdef CONFIG_RTNETLINK
+static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb)
{
- struct fifo_sched_data *q;
-/*
- struct device *dev = sch->dev;
- */
+ struct fifo_sched_data *q = (void*)sch->data;
+ unsigned char *b = skb->tail;
+ struct tc_fifo_qopt opt;
- q = (struct fifo_sched_data *)sch->data;
-/*
- if (pkts<0)
- pkts = dev->tx_queue_len;
- if (bytes<0)
- bytes = pkts*dev->mtu;
- q->qmaxbytes = bytes;
- q->qmaxlen = pkts;
- */
- return 0;
+ opt.limit = q->limit;
+ RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+
+ return skb->len;
+
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
}
+#endif
-struct Qdisc_ops pfifo_ops =
+struct Qdisc_ops pfifo_qdisc_ops =
{
NULL,
+ NULL,
"pfifo",
- 0,
sizeof(struct fifo_sched_data),
+
pfifo_enqueue,
pfifo_dequeue,
- pfifo_reset,
- NULL,
+ pfifo_requeue,
+ fifo_drop,
+
fifo_init,
+ fifo_reset,
+ NULL,
+#ifdef CONFIG_RTNETLINK
+ fifo_dump,
+#endif
};
-struct Qdisc_ops bfifo_ops =
+struct Qdisc_ops bfifo_qdisc_ops =
{
NULL,
- "pfifo",
- 0,
+ NULL,
+ "bfifo",
sizeof(struct fifo_sched_data),
+
bfifo_enqueue,
bfifo_dequeue,
- bfifo_reset,
- NULL,
- fifo_init,
-};
+ bfifo_requeue,
+ fifo_drop,
-#ifdef MODULE
-#include <linux/module.h>
-int init_module(void)
-{
- int err;
-
- /* Load once and never free it. */
- MOD_INC_USE_COUNT;
-
- err = register_qdisc(&pfifo_ops);
- if (err == 0) {
- err = register_qdisc(&bfifo_ops);
- if (err)
- unregister_qdisc(&pfifo_ops);
- }
- if (err)
- MOD_DEC_USE_COUNT;
- return err;
-}
-
-void cleanup_module(void)
-{
-}
+ fifo_init,
+ fifo_reset,
+ NULL,
+#ifdef CONFIG_RTNETLINK
+ fifo_dump,
#endif
+};
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov