* [LARTC] [PATCH 2.6] update to network emulation QOS scheduler
@ 2004-07-01 18:33 Stephen Hemminger
2004-07-01 20:11 ` [LARTC] [PATCH 2.4] " Stephen Hemminger
2004-07-02 20:44 ` [LARTC] Re: [PATCH 2.6] " Stephen Hemminger
0 siblings, 2 replies; 10+ messages in thread
From: Stephen Hemminger @ 2004-07-01 18:33 UTC (permalink / raw)
To: David S. Miller; +Cc: Catalin BOIE, netdev, lartc
This patch updates the network emulation packet scheduler.
* name changed from delay to netem since it does more than just delay
* Catalin's merged code to do packet reordering
* uses a socket queue's directly rather than layering on qdisc(fifo)
because this is used in performance tests.
* adds placeholder in API for future enhancements (rate and duplicate).
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
diff -urNp -X dontdiff linux-2.6/include/linux/pkt_sched.h sched-2.6/include/linux/pkt_sched.h
--- linux-2.6/include/linux/pkt_sched.h 2004-06-24 08:52:58.000000000 -0700
+++ sched-2.6/include/linux/pkt_sched.h 2004-07-01 03:53:31.185482832 -0700
@@ -439,11 +439,14 @@ enum {
#define TCA_ATM_MAX TCA_ATM_STATE
-/* Delay section */
-struct tc_dly_qopt
+/* Network emulator */
+struct tc_netem_qopt
{
- __u32 latency;
- __u32 limit;
- __u32 loss;
+ __u32 latency; /* added delay (us) */
+ __u32 limit; /* fifo limit (packets) */
+ __u32 loss; /* random packet loss (0=none ~0\x100%) */
+ __u32 gap; /* re-ordering gap (0 for delay all) */
+ __u32 duplicate; /* random packet dup (0=none ~0\x100%) */
+ __u32 rate; /* maximum transmit rate (bytes/sec) */
};
#endif
diff -urNp -X dontdiff linux-2.6/net/sched/Kconfig sched-2.6/net/sched/Kconfig
--- linux-2.6/net/sched/Kconfig 2004-06-25 09:41:00.000000000 -0700
+++ sched-2.6/net/sched/Kconfig 2004-06-28 09:17:19.000000000 -0700
@@ -164,12 +164,12 @@ config NET_SCH_DSMARK
To compile this code as a module, choose M here: the
module will be called sch_dsmark.
-config NET_SCH_DELAY
- tristate "Delay simulator"
+config NET_SCH_NETEM
+ tristate "Network emulator"
depends on NET_SCHED
help
- Say Y if you want to delay packets by a fixed amount of
- time. This is often useful to simulate network delay when
+ Say Y if you want to emulate network delay, loss, and packet
+ re-ordering. This is often useful to simulate networks when
testing applications or protocols.
To compile this driver as a module, choose M here: the module
diff -urNp -X dontdiff linux-2.6/net/sched/Makefile sched-2.6/net/sched/Makefile
--- linux-2.6/net/sched/Makefile 2004-06-24 08:52:58.000000000 -0700
+++ sched-2.6/net/sched/Makefile 2004-06-28 09:17:49.000000000 -0700
@@ -24,7 +24,7 @@ obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o
obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
obj-$(CONFIG_NET_SCH_ATM) += sch_atm.o
-obj-$(CONFIG_NET_SCH_DELAY) += sch_delay.o
+obj-$(CONFIG_NET_SCH_NETEM) += sch_netem.o
obj-$(CONFIG_NET_CLS_U32) += cls_u32.o
obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o
obj-$(CONFIG_NET_CLS_FW) += cls_fw.o
diff -urNp -X dontdiff linux-2.6/net/sched/sch_delay.c sched-2.6/net/sched/sch_delay.c
--- linux-2.6/net/sched/sch_delay.c 2004-06-21 09:23:15.000000000 -0700
+++ sched-2.6/net/sched/sch_delay.c 1969-12-31 16:00:00.000000000 -0800
@@ -1,281 +0,0 @@
-/*
- * net/sched/sch_delay.c Simple constant delay
- *
- * 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: Stephen Hemminger <shemminger@osdl.org>
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/route.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/pkt_sched.h>
-
-/* Network delay simulator
- This scheduler adds a fixed delay to all packets.
- Similar to NISTnet and BSD Dummynet.
-
- It uses byte fifo underneath similar to TBF */
-struct dly_sched_data {
- u32 latency;
- u32 limit;
- u32 loss;
- struct timer_list timer;
- struct Qdisc *qdisc;
-};
-
-/* Time stamp put into socket buffer control block */
-struct dly_skb_cb {
- psched_time_t queuetime;
-};
-
-/* Enqueue packets with underlying discipline (fifo)
- * but mark them with current time first.
- */
-static int dly_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
- struct dly_skb_cb *cb = (struct dly_skb_cb *)skb->cb;
- int ret;
-
- /* Random packet drop 0 => none, ~0 => all */
- if (q->loss >= net_random()) {
- sch->stats.drops++;
- return 0; /* lie about loss so TCP doesn't know */
- }
-
- PSCHED_GET_TIME(cb->queuetime);
-
- /* Queue to underlying scheduler */
- ret = q->qdisc->enqueue(skb, q->qdisc);
- if (ret)
- sch->stats.drops++;
- else {
- sch->q.qlen++;
- sch->stats.bytes += skb->len;
- sch->stats.packets++;
- }
- return ret;
-}
-
-/* Requeue packets but don't change time stamp */
-static int dly_requeue(struct sk_buff *skb, struct Qdisc *sch)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
- int ret;
-
- ret = q->qdisc->ops->requeue(skb, q->qdisc);
- if (ret = 0)
- sch->q.qlen++;
- return ret;
-}
-
-static unsigned int dly_drop(struct Qdisc *sch)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
- unsigned int len;
-
- len = q->qdisc->ops->drop(q->qdisc);
- if (len) {
- sch->q.qlen--;
- sch->stats.drops++;
- }
- return len;
-}
-
-/* Dequeue packet.
- * If packet needs to be held up, then stop the
- * queue and set timer to wakeup later.
- */
-static struct sk_buff *dly_dequeue(struct Qdisc *sch)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
- struct sk_buff *skb;
-
- retry:
- skb = q->qdisc->dequeue(q->qdisc);
- if (skb) {
- struct dly_skb_cb *cb = (struct dly_skb_cb *)skb->cb;
- psched_time_t now;
- long diff, delay;
-
- PSCHED_GET_TIME(now);
- diff = q->latency - PSCHED_TDIFF(now, cb->queuetime);
-
- if (diff <= 0) {
- sch->q.qlen--;
- sch->flags &= ~TCQ_F_THROTTLED;
- return skb;
- }
-
- if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
- sch->q.qlen--;
- sch->stats.drops++;
- goto retry;
- }
-
- delay = PSCHED_US2JIFFIE(diff);
- if (delay <= 0)
- delay = 1;
- mod_timer(&q->timer, jiffies+delay);
-
- sch->flags |= TCQ_F_THROTTLED;
- }
- return NULL;
-}
-
-static void dly_reset(struct Qdisc *sch)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
-
- qdisc_reset(q->qdisc);
- sch->q.qlen = 0;
- sch->flags &= ~TCQ_F_THROTTLED;
- del_timer(&q->timer);
-}
-
-static void dly_timer(unsigned long arg)
-{
- struct Qdisc *sch = (struct Qdisc *)arg;
-
- sch->flags &= ~TCQ_F_THROTTLED;
- netif_schedule(sch->dev);
-}
-
-/* Tell Fifo the new limit. */
-static int change_limit(struct Qdisc *q, u32 limit)
-{
- struct rtattr *rta;
- int ret;
-
- rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
- if (!rta)
- return -ENOMEM;
-
- rta->rta_type = RTM_NEWQDISC;
- rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt));
- ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit;
- ret = q->ops->change(q, rta);
- kfree(rta);
-
- return ret;
-}
-
-/* Setup underlying FIFO discipline */
-static int dly_change(struct Qdisc *sch, struct rtattr *opt)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
- struct tc_dly_qopt *qopt = RTA_DATA(opt);
- int err;
-
- if (q->qdisc = &noop_qdisc) {
- struct Qdisc *child
- = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops);
- if (!child)
- return -EINVAL;
- q->qdisc = child;
- }
-
- err = change_limit(q->qdisc, qopt->limit);
- if (err) {
- qdisc_destroy(q->qdisc);
- q->qdisc = &noop_qdisc;
- } else {
- q->latency = qopt->latency;
- q->limit = qopt->limit;
- q->loss = qopt->loss;
- }
- return err;
-}
-
-static int dly_init(struct Qdisc *sch, struct rtattr *opt)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
-
- if (!opt)
- return -EINVAL;
-
- init_timer(&q->timer);
- q->timer.function = dly_timer;
- q->timer.data = (unsigned long) sch;
- q->qdisc = &noop_qdisc;
-
- return dly_change(sch, opt);
-}
-
-static void dly_destroy(struct Qdisc *sch)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
-
- del_timer(&q->timer);
- qdisc_destroy(q->qdisc);
- q->qdisc = &noop_qdisc;
-}
-
-static int dly_dump(struct Qdisc *sch, struct sk_buff *skb)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
- unsigned char *b = skb->tail;
- struct tc_dly_qopt qopt;
-
- qopt.latency = q->latency;
- qopt.limit = q->limit;
- qopt.loss = q->loss;
-
- RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
-
- return skb->len;
-
-rtattr_failure:
- skb_trim(skb, b - skb->data);
- return -1;
-}
-
-static struct Qdisc_ops dly_qdisc_ops = {
- .id = "delay",
- .priv_size = sizeof(struct dly_sched_data),
- .enqueue = dly_enqueue,
- .dequeue = dly_dequeue,
- .requeue = dly_requeue,
- .drop = dly_drop,
- .init = dly_init,
- .reset = dly_reset,
- .destroy = dly_destroy,
- .change = dly_change,
- .dump = dly_dump,
- .owner = THIS_MODULE,
-};
-
-
-static int __init dly_module_init(void)
-{
- return register_qdisc(&dly_qdisc_ops);
-}
-static void __exit dly_module_exit(void)
-{
- unregister_qdisc(&dly_qdisc_ops);
-}
-module_init(dly_module_init)
-module_exit(dly_module_exit)
-MODULE_LICENSE("GPL");
diff -urNp -X dontdiff linux-2.6/net/sched/sch_netem.c sched-2.6/net/sched/sch_netem.c
--- linux-2.6/net/sched/sch_netem.c 1969-12-31 16:00:00.000000000 -0800
+++ sched-2.6/net/sched/sch_netem.c 2004-06-30 14:05:13.000000000 -0700
@@ -0,0 +1,255 @@
+/*
+ * net/sched/sch_netem.c Network emulator
+ *
+ * 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: Stephen Hemminger <shemminger@osdl.org>
+ * Catalin(ux aka Dino) BOIE <catab at umbrella dot ro>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/bitops.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>
+
+/* Network emulator
+ *
+ * This scheduler can alters spacing and order
+ * Similar to NISTnet and BSD Dummynet.
+ */
+
+struct netem_sched_data {
+ struct sk_buff_head qnormal;
+ struct sk_buff_head qdelay;
+ struct timer_list timer;
+
+ u32 latency;
+ u32 loss;
+ u32 counter;
+ u32 gap;
+};
+
+/* Time stamp put into socket buffer control block */
+struct netem_skb_cb {
+ psched_time_t time_to_send;
+};
+
+/* Enqueue packets with underlying discipline (fifo)
+ * but mark them with current time first.
+ */
+static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+ struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
+
+ pr_debug("netem_enqueue skb=%p @%lu\n", skb, jiffies);
+
+ /* Random packet drop 0 => none, ~0 => all */
+ if (q->loss >= net_random()) {
+ sch->stats.drops++;
+ return 0; /* lie about loss so TCP doesn't know */
+ }
+
+ if (q->qnormal.qlen < sch->dev->tx_queue_len) {
+ PSCHED_GET_TIME(cb->time_to_send);
+ PSCHED_TADD(cb->time_to_send, q->latency);
+
+ __skb_queue_tail(&q->qnormal, skb);
+ sch->q.qlen++;
+ sch->stats.bytes += skb->len;
+ sch->stats.packets++;
+ return 0;
+ }
+
+ sch->stats.drops++;
+ kfree_skb(skb);
+ return NET_XMIT_DROP;
+}
+
+/* Requeue packets but don't change time stamp */
+static int netem_requeue(struct sk_buff *skb, struct Qdisc *sch)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+
+ __skb_queue_head(&q->qnormal, skb);
+ sch->q.qlen++;
+ return 0;
+}
+
+/*
+ * Check the look aside buffer list, and see if any freshly baked buffers.
+ * If head of queue is not baked, set timer.
+ */
+static struct sk_buff *netem_get_delayed(struct netem_sched_data *q)
+{
+ struct sk_buff *skb;
+ psched_time_t now;
+ long delay;
+
+ skb = skb_peek(&q->qdelay);
+ if (skb) {
+ const struct netem_skb_cb *cb
+ = (const struct netem_skb_cb *)skb->cb;
+
+ PSCHED_GET_TIME(now);
+ delay = PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now));
+ pr_debug("netem_dequeue: delay queue %p@%lu %ld\n",
+ skb, jiffies, delay);
+
+ /* it's baked enough */
+ if (delay <= 0) {
+ __skb_unlink(skb, &q->qdelay);
+ del_timer(&q->timer);
+ return skb;
+ }
+
+ if (!timer_pending(&q->timer)) {
+ q->timer.expires = jiffies + delay;
+ add_timer(&q->timer);
+ }
+ }
+ return NULL;
+}
+
+/* Dequeue packet.
+ * If packet needs to be held up, then put in the delay
+ * queue and set timer to wakeup later.
+ */
+static struct sk_buff *netem_dequeue(struct Qdisc *sch)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+ struct sk_buff *skb;
+
+ skb = netem_get_delayed(q);
+ if (!skb && (skb = __skb_dequeue(&q->qnormal))) {
+ /* are we doing out of order packet skip? */
+ if (q->counter < q->gap) {
+ pr_debug("netem_dequeue: send %p normally\n", skb);
+ q->counter++;
+ } else {
+ /* don't send now hold for later */
+ pr_debug("netem_dequeue: hold [%p]@%lu\n", skb, jiffies);
+ __skb_queue_tail(&q->qdelay, skb);
+ q->counter = 0;
+ skb = netem_get_delayed(q);
+ }
+ }
+
+ if (skb)
+ sch->q.qlen--;
+ return skb;
+}
+
+static void netem_timer(unsigned long arg)
+{
+ struct Qdisc *sch = (struct Qdisc *)arg;
+
+ pr_debug("netem_timer: fired @%lu\n", jiffies);
+ netif_schedule(sch->dev);
+}
+
+static void netem_reset(struct Qdisc *sch)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+
+ skb_queue_purge(&q->qnormal);
+ skb_queue_purge(&q->qdelay);
+
+ sch->q.qlen = 0;
+ del_timer_sync(&q->timer);
+}
+
+static int netem_change(struct Qdisc *sch, struct rtattr *opt)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+ struct tc_netem_qopt *qopt = RTA_DATA(opt);
+
+ if (qopt->limit)
+ sch->dev->tx_queue_len = qopt->limit;
+
+ q->gap = qopt->gap;
+ q->loss = qopt->loss;
+ q->latency = qopt->latency;
+
+ return 0;
+}
+
+static int netem_init(struct Qdisc *sch, struct rtattr *opt)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+
+ if (!opt)
+ return -EINVAL;
+
+ skb_queue_head_init(&q->qnormal);
+ skb_queue_head_init(&q->qdelay);
+ init_timer(&q->timer);
+ q->timer.function = netem_timer;
+ q->timer.data = (unsigned long) sch;
+ q->counter = 0;
+
+ return netem_change(sch, opt);
+}
+
+static void netem_destroy(struct Qdisc *sch)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+
+ del_timer_sync(&q->timer);
+}
+
+static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+ unsigned char *b = skb->tail;
+ struct tc_netem_qopt qopt;
+
+ qopt.latency = q->latency;
+ qopt.limit = sch->dev->tx_queue_len;
+ qopt.loss = q->loss;
+ qopt.gap = q->gap;
+
+ RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
+
+ return skb->len;
+
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+static struct Qdisc_ops netem_qdisc_ops = {
+ .id = "netem",
+ .priv_size = sizeof(struct netem_sched_data),
+ .enqueue = netem_enqueue,
+ .dequeue = netem_dequeue,
+ .requeue = netem_requeue,
+ .init = netem_init,
+ .reset = netem_reset,
+ .destroy = netem_destroy,
+ .change = netem_change,
+ .dump = netem_dump,
+ .owner = THIS_MODULE,
+};
+
+
+static int __init netem_module_init(void)
+{
+ return register_qdisc(&netem_qdisc_ops);
+}
+static void __exit netem_module_exit(void)
+{
+ unregister_qdisc(&netem_qdisc_ops);
+}
+module_init(netem_module_init)
+module_exit(netem_module_exit)
+MODULE_LICENSE("GPL");
_______________________________________________
LARTC mailing list / LARTC@mailman.ds9a.nl
http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/
^ permalink raw reply [flat|nested] 10+ messages in thread* [LARTC] [PATCH 2.4] update to network emulation QOS scheduler
2004-07-01 18:33 [LARTC] [PATCH 2.6] update to network emulation QOS scheduler Stephen Hemminger
@ 2004-07-01 20:11 ` Stephen Hemminger
2004-07-02 20:44 ` [LARTC] Re: [PATCH 2.6] " Stephen Hemminger
1 sibling, 0 replies; 10+ messages in thread
From: Stephen Hemminger @ 2004-07-01 20:11 UTC (permalink / raw)
To: David S. Miller; +Cc: Catalin BOIE, netdev, lartc
This is the 2.4 version of the conversion of simple network delay scheduler to
network emulator.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
diff -Nru a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
--- a/include/linux/pkt_sched.h 2004-07-01 13:06:36 -07:00
+++ b/include/linux/pkt_sched.h 2004-07-01 13:06:36 -07:00
@@ -432,12 +432,15 @@
#define TCA_ATM_MAX TCA_ATM_STATE
-/* Delay section */
-struct tc_dly_qopt
+/* Network emulator */
+struct tc_netem_qopt
{
- __u32 latency;
- __u32 limit;
- __u32 loss;
+ __u32 latency; /* added delay (us) */
+ __u32 limit; /* fifo limit (packets) */
+ __u32 loss; /* random packet loss (0=none ~0\x100%) */
+ __u32 gap; /* re-ordering gap (0 for delay all) */
+ __u32 duplicate; /* random packet dup (0=none ~0\x100%) */
+ __u32 rate; /* maximum transmit rate (bytes/sec) */
};
#endif
diff -Nru a/net/sched/Config.in b/net/sched/Config.in
--- a/net/sched/Config.in 2004-07-01 13:06:36 -07:00
+++ b/net/sched/Config.in 2004-07-01 13:06:36 -07:00
@@ -15,7 +15,7 @@
tristate ' TEQL queue' CONFIG_NET_SCH_TEQL
tristate ' TBF queue' CONFIG_NET_SCH_TBF
tristate ' GRED queue' CONFIG_NET_SCH_GRED
-tristate ' Network delay simulator' CONFIG_NET_SCH_DELAY
+tristate ' Network emulator' CONFIG_NET_SCH_NETEM
tristate ' Diffserv field marker' CONFIG_NET_SCH_DSMARK
if [ "$CONFIG_NETFILTER" = "y" ]; then
tristate ' Ingress Qdisc' CONFIG_NET_SCH_INGRESS
diff -Nru a/net/sched/Makefile b/net/sched/Makefile
--- a/net/sched/Makefile 2004-07-01 13:06:36 -07:00
+++ b/net/sched/Makefile 2004-07-01 13:06:36 -07:00
@@ -14,7 +14,7 @@
obj-$(CONFIG_NET_SCH_INGRESS) += sch_ingress.o
obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o
obj-$(CONFIG_NET_SCH_CSZ) += sch_csz.o
-obj-$(CONFIG_NET_SCH_DELAY) += sch_delay.o
+obj-$(CONFIG_NET_SCH_NETEM) += sch_netem.o
obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o
obj-$(CONFIG_NET_SCH_HFSC) += sch_hfsc.o
obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o
diff -Nru a/net/sched/sch_delay.c b/net/sched/sch_delay.c
--- a/net/sched/sch_delay.c 2004-07-01 13:06:36 -07:00
+++ /dev/null Wed Dec 31 16:00:00 196900
@@ -1,289 +0,0 @@
-/*
- * net/sched/sch_delay.c Simple constant delay
- *
- * 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: Stephen Hemminger <shemminger@osdl.org>
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/route.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/pkt_sched.h>
-
-/* Network delay simulator
- This scheduler adds a fixed delay to all packets.
- Similar to NISTnet and BSD Dummynet.
-
- It uses byte fifo underneath similar to TBF */
-struct dly_sched_data {
- u32 latency;
- u32 limit;
- u32 loss;
- struct timer_list timer;
- struct Qdisc *qdisc;
-};
-
-/* Time stamp put into socket buffer control block */
-struct dly_skb_cb {
- psched_time_t queuetime;
-};
-
-/* Enqueue packets with underlying discipline (fifo)
- * but mark them with current time first.
- */
-static int dly_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
- struct dly_skb_cb *cb = (struct dly_skb_cb *)skb->cb;
- int ret;
-
- /* Random packet drop 0 => none, ~0 => all */
- if (q->loss >= net_random()) {
- sch->stats.drops++;
- return 0; /* lie about loss so TCP doesn't know */
- }
-
- PSCHED_GET_TIME(cb->queuetime);
-
- /* Queue to underlying scheduler */
- ret = q->qdisc->enqueue(skb, q->qdisc);
- if (ret)
- sch->stats.drops++;
- else {
- sch->q.qlen++;
- sch->stats.bytes += skb->len;
- sch->stats.packets++;
- }
- return ret;
-}
-
-/* Requeue packets but don't change time stamp */
-static int dly_requeue(struct sk_buff *skb, struct Qdisc *sch)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
- int ret;
-
- ret = q->qdisc->ops->requeue(skb, q->qdisc);
- if (ret = 0)
- sch->q.qlen++;
- return ret;
-}
-
-static unsigned int dly_drop(struct Qdisc *sch)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
- unsigned int len;
-
- len = q->qdisc->ops->drop(q->qdisc);
- if (len) {
- sch->q.qlen--;
- sch->stats.drops++;
- }
- return len;
-}
-
-/* Dequeue packet.
- * If packet needs to be held up, then stop the
- * queue and set timer to wakeup later.
- */
-static struct sk_buff *dly_dequeue(struct Qdisc *sch)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
- struct sk_buff *skb;
-
- retry:
- skb = q->qdisc->dequeue(q->qdisc);
- if (skb) {
- struct dly_skb_cb *cb = (struct dly_skb_cb *)skb->cb;
- psched_time_t now;
- long diff, delay;
-
- PSCHED_GET_TIME(now);
- diff = q->latency - PSCHED_TDIFF(now, cb->queuetime);
-
- if (diff <= 0) {
- sch->q.qlen--;
- sch->flags &= ~TCQ_F_THROTTLED;
- return skb;
- }
-
- if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
- sch->q.qlen--;
- sch->stats.drops++;
- goto retry;
- }
-
- delay = PSCHED_US2JIFFIE(diff);
- if (delay <= 0)
- delay = 1;
- mod_timer(&q->timer, jiffies+delay);
-
- sch->flags |= TCQ_F_THROTTLED;
- }
- return NULL;
-}
-
-static void dly_reset(struct Qdisc *sch)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
-
- qdisc_reset(q->qdisc);
- sch->q.qlen = 0;
- sch->flags &= ~TCQ_F_THROTTLED;
- del_timer(&q->timer);
-}
-
-static void dly_timer(unsigned long arg)
-{
- struct Qdisc *sch = (struct Qdisc *)arg;
-
- sch->flags &= ~TCQ_F_THROTTLED;
- netif_schedule(sch->dev);
-}
-
-/* Tell Fifo the new limit. */
-static int change_limit(struct Qdisc *q, u32 limit)
-{
- struct rtattr *rta;
- int ret;
-
- rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
- if (!rta)
- return -ENOMEM;
-
- rta->rta_type = RTM_NEWQDISC;
- rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt));
- ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit;
- ret = q->ops->change(q, rta);
- kfree(rta);
-
- return ret;
-}
-
-/* Setup underlying FIFO discipline */
-static int dly_change(struct Qdisc *sch, struct rtattr *opt)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
- struct tc_dly_qopt *qopt = RTA_DATA(opt);
- int err;
-
- if (q->qdisc = &noop_qdisc) {
- struct Qdisc *child
- = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops);
- if (!child)
- return -EINVAL;
- q->qdisc = child;
- }
-
- err = change_limit(q->qdisc, qopt->limit);
- if (err) {
- qdisc_destroy(q->qdisc);
- q->qdisc = &noop_qdisc;
- } else {
- q->latency = qopt->latency;
- q->limit = qopt->limit;
- q->loss = qopt->loss;
- }
- return err;
-}
-
-static int dly_init(struct Qdisc *sch, struct rtattr *opt)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
- int err;
-
- if (!opt)
- return -EINVAL;
-
- MOD_INC_USE_COUNT;
-
- init_timer(&q->timer);
- q->timer.function = dly_timer;
- q->timer.data = (unsigned long) sch;
- q->qdisc = &noop_qdisc;
-
- err = dly_change(sch, opt);
- if (err)
- MOD_DEC_USE_COUNT;
-
- return err;
-}
-
-static void dly_destroy(struct Qdisc *sch)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
-
- del_timer(&q->timer);
- qdisc_destroy(q->qdisc);
- q->qdisc = &noop_qdisc;
-
- MOD_DEC_USE_COUNT;
-}
-
-static int dly_dump(struct Qdisc *sch, struct sk_buff *skb)
-{
- struct dly_sched_data *q = (struct dly_sched_data *)sch->data;
- unsigned char *b = skb->tail;
- struct tc_dly_qopt qopt;
-
- qopt.latency = q->latency;
- qopt.limit = q->limit;
- qopt.loss = q->loss;
-
- RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
-
- return skb->len;
-
-rtattr_failure:
- skb_trim(skb, b - skb->data);
- return -1;
-}
-
-struct Qdisc_ops dly_qdisc_ops = {
- .id = "delay",
- .priv_size = sizeof(struct dly_sched_data),
- .enqueue = dly_enqueue,
- .dequeue = dly_dequeue,
- .requeue = dly_requeue,
- .drop = dly_drop,
- .init = dly_init,
- .reset = dly_reset,
- .destroy = dly_destroy,
- .change = dly_change,
- .dump = dly_dump,
-};
-
-#ifdef MODULE
-int init_module(void)
-{
- return register_qdisc(&dly_qdisc_ops);
-}
-
-void cleanup_module(void)
-{
- unregister_qdisc(&dly_qdisc_ops);
-}
-#endif
-MODULE_LICENSE("GPL");
diff -Nru a/net/sched/sch_netem.c b/net/sched/sch_netem.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/net/sched/sch_netem.c 2004-07-01 13:06:36 -07:00
@@ -0,0 +1,255 @@
+/*
+ * net/sched/sch_netem.c Network emulator
+ *
+ * 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: Stephen Hemminger <shemminger@osdl.org>
+ * Catalin(ux aka Dino) BOIE <catab at umbrella dot ro>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+
+#include <net/pkt_sched.h>
+
+/* Network emulator
+ *
+ * This scheduler can alters spacing and order
+ * Similar to NISTnet and BSD Dummynet.
+ */
+
+struct netem_sched_data {
+ struct sk_buff_head qnormal;
+ struct sk_buff_head qdelay;
+ struct timer_list timer;
+
+ u32 latency;
+ u32 loss;
+ u32 counter;
+ u32 gap;
+};
+
+/* Time stamp put into socket buffer control block */
+struct netem_skb_cb {
+ psched_time_t time_to_send;
+};
+
+/* Enqueue packets with underlying discipline (fifo)
+ * but mark them with current time first.
+ */
+static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+ struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
+
+ pr_debug("netem_enqueue skb=%p @%lu\n", skb, jiffies);
+
+ /* Random packet drop 0 => none, ~0 => all */
+ if (q->loss >= net_random()) {
+ sch->stats.drops++;
+ return 0; /* lie about loss so TCP doesn't know */
+ }
+
+ if (q->qnormal.qlen < sch->dev->tx_queue_len) {
+ PSCHED_GET_TIME(cb->time_to_send);
+ PSCHED_TADD(cb->time_to_send, q->latency);
+
+ __skb_queue_tail(&q->qnormal, skb);
+ sch->q.qlen++;
+ sch->stats.bytes += skb->len;
+ sch->stats.packets++;
+ return 0;
+ }
+
+ sch->stats.drops++;
+ kfree_skb(skb);
+ return NET_XMIT_DROP;
+}
+
+/* Requeue packets but don't change time stamp */
+static int netem_requeue(struct sk_buff *skb, struct Qdisc *sch)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+
+ __skb_queue_head(&q->qnormal, skb);
+ sch->q.qlen++;
+ return 0;
+}
+
+/*
+ * Check the look aside buffer list, and see if any freshly baked buffers.
+ * If head of queue is not baked, set timer.
+ */
+static struct sk_buff *netem_get_delayed(struct netem_sched_data *q)
+{
+ struct sk_buff *skb;
+ psched_time_t now;
+ long delay;
+
+ skb = skb_peek(&q->qdelay);
+ if (skb) {
+ const struct netem_skb_cb *cb
+ = (const struct netem_skb_cb *)skb->cb;
+
+ PSCHED_GET_TIME(now);
+ delay = PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now));
+ pr_debug("netem_dequeue: delay queue %p@%lu %ld\n",
+ skb, jiffies, delay);
+
+ /* it's baked enough */
+ if (delay <= 0) {
+ __skb_unlink(skb, &q->qdelay);
+ del_timer(&q->timer);
+ return skb;
+ }
+
+ if (!timer_pending(&q->timer)) {
+ q->timer.expires = jiffies + delay;
+ add_timer(&q->timer);
+ }
+ }
+ return NULL;
+}
+
+/* Dequeue packet.
+ * If packet needs to be held up, then put in the delay
+ * queue and set timer to wakeup later.
+ */
+static struct sk_buff *netem_dequeue(struct Qdisc *sch)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+ struct sk_buff *skb;
+
+ skb = netem_get_delayed(q);
+ if (!skb && (skb = __skb_dequeue(&q->qnormal))) {
+ /* are we doing out of order packet skip? */
+ if (q->counter < q->gap) {
+ pr_debug("netem_dequeue: send %p normally\n", skb);
+ q->counter++;
+ } else {
+ /* don't send now hold for later */
+ pr_debug("netem_dequeue: hold [%p]@%lu\n", skb, jiffies);
+ __skb_queue_tail(&q->qdelay, skb);
+ q->counter = 0;
+ skb = netem_get_delayed(q);
+ }
+ }
+
+ if (skb)
+ sch->q.qlen--;
+ return skb;
+}
+
+static void netem_timer(unsigned long arg)
+{
+ struct Qdisc *sch = (struct Qdisc *)arg;
+
+ pr_debug("netem_timer: fired @%lu\n", jiffies);
+ netif_schedule(sch->dev);
+}
+
+static void netem_reset(struct Qdisc *sch)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+
+ skb_queue_purge(&q->qnormal);
+ skb_queue_purge(&q->qdelay);
+
+ sch->q.qlen = 0;
+ del_timer_sync(&q->timer);
+}
+
+static int netem_change(struct Qdisc *sch, struct rtattr *opt)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+ struct tc_netem_qopt *qopt = RTA_DATA(opt);
+
+ if (qopt->limit)
+ sch->dev->tx_queue_len = qopt->limit;
+
+ q->gap = qopt->gap;
+ q->loss = qopt->loss;
+ q->latency = qopt->latency;
+
+ return 0;
+}
+
+static int netem_init(struct Qdisc *sch, struct rtattr *opt)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+
+ if (!opt)
+ return -EINVAL;
+
+ skb_queue_head_init(&q->qnormal);
+ skb_queue_head_init(&q->qdelay);
+ init_timer(&q->timer);
+ q->timer.function = netem_timer;
+ q->timer.data = (unsigned long) sch;
+ q->counter = 0;
+
+ return netem_change(sch, opt);
+}
+
+static void netem_destroy(struct Qdisc *sch)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+
+ del_timer_sync(&q->timer);
+}
+
+static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+ struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+ unsigned char *b = skb->tail;
+ struct tc_netem_qopt qopt;
+
+ qopt.latency = q->latency;
+ qopt.limit = sch->dev->tx_queue_len;
+ qopt.loss = q->loss;
+ qopt.gap = q->gap;
+
+ RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
+
+ return skb->len;
+
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+static struct Qdisc_ops netem_qdisc_ops = {
+ .id = "netem",
+ .priv_size = sizeof(struct netem_sched_data),
+ .enqueue = netem_enqueue,
+ .dequeue = netem_dequeue,
+ .requeue = netem_requeue,
+ .init = netem_init,
+ .reset = netem_reset,
+ .destroy = netem_destroy,
+ .change = netem_change,
+ .dump = netem_dump,
+};
+
+
+static int __init netem_module_init(void)
+{
+ return register_qdisc(&netem_qdisc_ops);
+}
+static void __exit netem_module_exit(void)
+{
+ unregister_qdisc(&netem_qdisc_ops);
+}
+module_init(netem_module_init)
+module_exit(netem_module_exit)
+MODULE_LICENSE("GPL");
_______________________________________________
LARTC mailing list / LARTC@mailman.ds9a.nl
http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/
^ permalink raw reply [flat|nested] 10+ messages in thread* [LARTC] Re: [PATCH 2.6] update to network emulation QOS scheduler
2004-07-01 18:33 [LARTC] [PATCH 2.6] update to network emulation QOS scheduler Stephen Hemminger
2004-07-01 20:11 ` [LARTC] [PATCH 2.4] " Stephen Hemminger
@ 2004-07-02 20:44 ` Stephen Hemminger
2004-07-03 13:32 ` Ed Wildgoose
[not found] ` <1088824432.1043.271.camel@jzny.localdomain>
1 sibling, 2 replies; 10+ messages in thread
From: Stephen Hemminger @ 2004-07-02 20:44 UTC (permalink / raw)
To: David S. Miller; +Cc: Catalin BOIE, netdev, lartc
Here is an enhancement to netem to do allow emulating lower speed
networks. The resolution is close, but obviously limited by the
granularity of timers and size of packets.
Also, fixes a rtnetlink dependency which showed up in some configurations
and optimizes for the non-loss case by avoiding net_random call.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
diff -Nru a/net/sched/sch_netem.c b/net/sched/sch_netem.c
--- a/net/sched/sch_netem.c 2004-07-02 13:40:11 -07:00
+++ b/net/sched/sch_netem.c 2004-07-02 13:40:11 -07:00
@@ -18,6 +18,7 @@
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
#include <net/pkt_sched.h>
@@ -31,11 +32,13 @@
struct sk_buff_head qnormal;
struct sk_buff_head qdelay;
struct timer_list timer;
+ psched_time_t last;
u32 latency;
u32 loss;
u32 counter;
u32 gap;
+ u32 rate;
};
/* Time stamp put into socket buffer control block */
@@ -54,13 +57,23 @@
pr_debug("netem_enqueue skb=%p @%lu\n", skb, jiffies);
/* Random packet drop 0 => none, ~0 => all */
- if (q->loss >= net_random()) {
+ if (q->loss && q->loss >= net_random()) {
sch->stats.drops++;
return 0; /* lie about loss so TCP doesn't know */
}
if (q->qnormal.qlen < sch->dev->tx_queue_len) {
PSCHED_GET_TIME(cb->time_to_send);
+ if (q->rate) {
+ if (!PSCHED_IS_PASTPERFECT(q->last) &&
+ PSCHED_TLESS(cb->time_to_send, q->last))
+ cb->time_to_send = q->last;
+
+ PSCHED_TADD(cb->time_to_send,
+ (USEC_PER_SEC * skb->len) / q->rate);
+ q->last = cb->time_to_send;
+ }
+
PSCHED_TADD(cb->time_to_send, q->latency);
__skb_queue_tail(&q->qnormal, skb);
@@ -179,6 +192,7 @@
q->gap = qopt->gap;
q->loss = qopt->loss;
q->latency = qopt->latency;
+ q->rate = qopt->rate;
return 0;
}
@@ -196,6 +210,7 @@
q->timer.function = netem_timer;
q->timer.data = (unsigned long) sch;
q->counter = 0;
+ PSCHED_SET_PASTPERFECT(q->last);
return netem_change(sch, opt);
}
@@ -217,6 +232,7 @@
qopt.limit = sch->dev->tx_queue_len;
qopt.loss = q->loss;
qopt.gap = q->gap;
+ qopt.rate = q->rate;
RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
_______________________________________________
LARTC mailing list / LARTC@mailman.ds9a.nl
http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [LARTC] Re: [PATCH 2.6] update to network emulation QOS scheduler
2004-07-02 20:44 ` [LARTC] Re: [PATCH 2.6] " Stephen Hemminger
@ 2004-07-03 13:32 ` Ed Wildgoose
[not found] ` <1088824432.1043.271.camel@jzny.localdomain>
1 sibling, 0 replies; 10+ messages in thread
From: Ed Wildgoose @ 2004-07-03 13:32 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev, lartc
>Here is an enhancement to netem to do allow emulating lower speed
>networks. The resolution is close, but obviously limited by the
>granularity of timers and size of packets.
>
>
Hi Stephen,
This looks extremely useful.
I have a need for a simulator for the Iridium Satellite phone network,
this is at most 2,400 baud with perhaps 1 sec or more latency. Do you
expect this scheduler to be able to do this slow?
On a related note, for better accuracy I currently need a bit of
stochastic variability on the latency, ie assume a 1 sec min delay, but
also to vary that a little through time. Have you considered adding
that as a feature?
Thanks
Ed W
_______________________________________________
LARTC mailing list / LARTC@mailman.ds9a.nl
http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/
^ permalink raw reply [flat|nested] 10+ messages in thread[parent not found: <1088824432.1043.271.camel@jzny.localdomain>]
* [LARTC] Re: [PATCH 2.6] update to network emulation QOS scheduler
[not found] ` <1088824432.1043.271.camel@jzny.localdomain>
@ 2004-07-06 16:09 ` Stephen Hemminger
[not found] ` <1089164179.1039.26.camel@jzny.localdomain>
[not found] ` <20040705194925.37b7efcb.davem@redhat.com>
2004-07-07 18:10 ` Stephen Hemminger
2 siblings, 1 reply; 10+ messages in thread
From: Stephen Hemminger @ 2004-07-06 16:09 UTC (permalink / raw)
To: hadi; +Cc: David S. Miller, Catalin BOIE, netdev, lartc
On 02 Jul 2004 23:13:52 -0400
jamal <hadi@cyberus.ca> wrote:
> On Fri, 2004-07-02 at 16:44, Stephen Hemminger wrote:
> > Here is an enhancement to netem to do allow emulating lower speed
> > networks. The resolution is close, but obviously limited by the
> > granularity of timers and size of packets.
> >
> > Also, fixes a rtnetlink dependency which showed up in some configurations
> > and optimizes for the non-loss case by avoiding net_random call.
> >
>
> I think its time i illustrate my comments earlier with some example
> hopefully this will curb the amount of features on this qdisc.
> I do think theres value in having this thing do delay and jitter, but
> you have gone waay beyond that now;
> Let illustrate things which apply to what you are trying to do in
> network condituions emulation. Although i show ingress qdisc , this
> applies to egress just the same.
>
> #drop 1 out 10 packets randomly using the netrand generator
> tc filter add dev eth0 parent ffff: protocol ip prio 6 u32 \
> match ip src 10.0.0.21/32 flowid 1:16 \
> action drop random netrand ok 0xa
Your examples made me think about this more. The netfilter seem best
suited to things that effect the flow of packets (dropping, reordering,
even corrupting), and the qdisc seems best when the timing needs to change.
The limit match in netfilter is not the same as the rate in the qdisc.
The netem scheduler acts as if the link is a slow fixed rate. The netfilter
limit is usually targeted to drop packets over the rate which is not the same.
Reordering is also hard without going out to a user log or building a custom
target.
So, you have convinced me that loss is unnecessary but not the rate, or delay.
If we can figure out how to re-ordering with netfilter then that could go too,
which would make it possible to use a layered qdisc again.
_______________________________________________
LARTC mailing list / LARTC@mailman.ds9a.nl
http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/
^ permalink raw reply [flat|nested] 10+ messages in thread[parent not found: <20040705194925.37b7efcb.davem@redhat.com>]
* [LARTC] Re: [PATCH 2.6] update to network emulation QOS scheduler
[not found] ` <1088824432.1043.271.camel@jzny.localdomain>
2004-07-06 16:09 ` Stephen Hemminger
[not found] ` <20040705194925.37b7efcb.davem@redhat.com>
@ 2004-07-07 18:10 ` Stephen Hemminger
[not found] ` <1089226667.1027.411.camel@jzny.localdomain>
2 siblings, 1 reply; 10+ messages in thread
From: Stephen Hemminger @ 2004-07-07 18:10 UTC (permalink / raw)
To: hadi; +Cc: David S. Miller, Catalin BOIE, netdev, lartc
Ok, I'll bite how would you do:
Rate limit packet egress on a ethernet device (eth0) so it looks like a slow DSL link (25 Kbps)
by not dropping packets but by pacing the data.
_______________________________________________
LARTC mailing list / LARTC@mailman.ds9a.nl
http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2004-07-07 21:22 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-07-01 18:33 [LARTC] [PATCH 2.6] update to network emulation QOS scheduler Stephen Hemminger
2004-07-01 20:11 ` [LARTC] [PATCH 2.4] " Stephen Hemminger
2004-07-02 20:44 ` [LARTC] Re: [PATCH 2.6] " Stephen Hemminger
2004-07-03 13:32 ` Ed Wildgoose
[not found] ` <1088824432.1043.271.camel@jzny.localdomain>
2004-07-06 16:09 ` Stephen Hemminger
[not found] ` <1089164179.1039.26.camel@jzny.localdomain>
2004-07-07 7:01 ` Catalin BOIE
[not found] ` <20040705194925.37b7efcb.davem@redhat.com>
[not found] ` <1089119090.4260.2.camel@jzny.localdomain>
2004-07-07 6:39 ` Catalin BOIE
2004-07-07 18:10 ` Stephen Hemminger
[not found] ` <1089226667.1027.411.camel@jzny.localdomain>
2004-07-07 20:58 ` Stephen Hemminger
[not found] ` <1089234699.1026.448.camel@jzny.localdomain>
2004-07-07 21:22 ` Stephen Hemminger
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.