Commit 26064408 authored by Kirk Webb's avatar Kirk Webb
Browse files

This commit represents the culmination of my work on linux traffic shaping.

Both changes to the kernel, and to userland control applications are included
in this checkin.  At present, these files are combined patches; I'll be
separating out the Emulab specific additions/changes in the near future.

The best resource (currently) for understanding the Linux traffic control
mechanisms is at the Linux Diffserv project home page (under Documentation):
http://diffserv.sourceforge.net/

The most noteworthy contributions I've made are the PLR module and DELAY
module port and enhancement.  These two modules are classful (though they
don't use classification filters) and can be chained together with other
modules such as the Heirarchical Token Bucket (used for limiting bandwith).
See: http://luxik.cdi.cz/~devik/qos/htb/

Note that this checkin also includes the patches necessary to obtain
Intermediate Queueing Devices (IMQ) and HTB control under iproute2+tc.  The
IMQ devices allow the attachment of qdiscs on the incoming side of a real
interface (can't do this without them). See: http://trash.net/~kaber/imq/

The Linux Advanced Routing HOWTO is another good source of information:
http://lartc.org
parent 233de852
This directory contains modules that were added or changed in Linux in
order to accomodate testbed link shaping and emulation.
kmods - kernel or kernel module changes / additions
tc_mods - updates to iproute2+tc, the userland app used to control
link shaping.
iptables_mods - updates to the Linux userland firewall control app
diff -urN iptables-1.2.6a-clean/extensions/.IMQ-test iptables-1.2.6a-imq/extensions/.IMQ-test
--- iptables-1.2.6a-clean/extensions/.IMQ-test Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/extensions/.IMQ-test Mon Apr 29 01:34:33 2002
@@ -0,0 +1,3 @@
+#!/bin/sh
+# True if IMQ target patch is applied.
+[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_IMQ.c ] && echo IMQ
diff -urN iptables-1.2.6a-clean/extensions/.IMQ-test6 iptables-1.2.6a-imq/extensions/.IMQ-test6
--- iptables-1.2.6a-clean/extensions/.IMQ-test6 Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/extensions/.IMQ-test6 Mon Apr 29 01:34:33 2002
@@ -0,0 +1,3 @@
+#!/bin/sh
+# True if IMQ target patch is applied.
+[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_IMQ.c ] && echo IMQ
diff -urN iptables-1.2.6a-clean/extensions/libip6t_IMQ.c iptables-1.2.6a-imq/extensions/libip6t_IMQ.c
--- iptables-1.2.6a-clean/extensions/libip6t_IMQ.c Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/extensions/libip6t_IMQ.c Mon Apr 29 01:34:33 2002
@@ -0,0 +1,102 @@
+/* Shared library add-on to iptables to add IMQ target support. */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <ip6tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_IMQ.h>
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+ printf(
+"IMQ target v%s options:\n"
+" --todev <N> enqueue to imq<N>, defaults to 0\n",
+NETFILTER_VERSION);
+}
+
+static struct option opts[] = {
+ { "todev", 1, 0, '1' },
+ { 0 }
+};
+
+/* Initialize the target. */
+static void
+init(struct ip6t_entry_target *t, unsigned int *nfcache)
+{
+ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)t->data;
+
+ mr->todev = 0;
+ *nfcache |= NFC_UNKNOWN;
+}
+
+/* Function which parses command options; returns true if it
+ ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+ const struct ip6t_entry *entry,
+ struct ip6t_entry_target **target)
+{
+ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)(*target)->data;
+
+ switch(c) {
+ case '1':
+ if (check_inverse(optarg, &invert, NULL, 0))
+ exit_error(PARAMETER_PROBLEM,
+ "Unexpected `!' after --todev");
+ mr->todev=atoi(optarg);
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void
+final_check(unsigned int flags)
+{
+}
+
+/* Prints out the targinfo. */
+static void
+print(const struct ip6t_ip6 *ip,
+ const struct ip6t_entry_target *target,
+ int numeric)
+{
+ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)target->data;
+
+ printf("IMQ: todev %u ", mr->todev);
+}
+
+/* Saves the union ipt_targinfo in parsable form to stdout. */
+static void
+save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
+{
+ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)target->data;
+
+ printf("--todev %u", mr->todev);
+}
+
+static
+struct ip6tables_target imq
+= { NULL,
+ "IMQ",
+ NETFILTER_VERSION,
+ IP6T_ALIGN(sizeof(struct ip6t_imq_info)),
+ IP6T_ALIGN(sizeof(struct ip6t_imq_info)),
+ &help,
+ &init,
+ &parse,
+ &final_check,
+ &print,
+ &save,
+ opts
+};
+
+void _init(void)
+{
+ register_target6(&imq);
+}
diff -urN iptables-1.2.6a-clean/extensions/libipt_IMQ.c iptables-1.2.6a-imq/extensions/libipt_IMQ.c
--- iptables-1.2.6a-clean/extensions/libipt_IMQ.c Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/extensions/libipt_IMQ.c Mon Apr 29 01:34:33 2002
@@ -0,0 +1,102 @@
+/* Shared library add-on to iptables to add IMQ target support. */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <iptables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_IMQ.h>
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+ printf(
+"IMQ target v%s options:\n"
+" --todev <N> enqueue to imq<N>, defaults to 0\n",
+NETFILTER_VERSION);
+}
+
+static struct option opts[] = {
+ { "todev", 1, 0, '1' },
+ { 0 }
+};
+
+/* Initialize the target. */
+static void
+init(struct ipt_entry_target *t, unsigned int *nfcache)
+{
+ struct ipt_imq_info *mr = (struct ipt_imq_info*)t->data;
+
+ mr->todev = 0;
+ *nfcache |= NFC_UNKNOWN;
+}
+
+/* Function which parses command options; returns true if it
+ ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+ const struct ipt_entry *entry,
+ struct ipt_entry_target **target)
+{
+ struct ipt_imq_info *mr = (struct ipt_imq_info*)(*target)->data;
+
+ switch(c) {
+ case '1':
+ if (check_inverse(optarg, &invert, NULL, 0))
+ exit_error(PARAMETER_PROBLEM,
+ "Unexpected `!' after --todev");
+ mr->todev=atoi(optarg);
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void
+final_check(unsigned int flags)
+{
+}
+
+/* Prints out the targinfo. */
+static void
+print(const struct ipt_ip *ip,
+ const struct ipt_entry_target *target,
+ int numeric)
+{
+ struct ipt_imq_info *mr = (struct ipt_imq_info*)target->data;
+
+ printf("IMQ: todev %u ", mr->todev);
+}
+
+/* Saves the union ipt_targinfo in parsable form to stdout. */
+static void
+save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+{
+ struct ipt_imq_info *mr = (struct ipt_imq_info*)target->data;
+
+ printf("--todev %u", mr->todev);
+}
+
+static
+struct iptables_target imq
+= { NULL,
+ "IMQ",
+ NETFILTER_VERSION,
+ IPT_ALIGN(sizeof(struct ipt_imq_info)),
+ IPT_ALIGN(sizeof(struct ipt_imq_info)),
+ &help,
+ &init,
+ &parse,
+ &final_check,
+ &print,
+ &save,
+ opts
+};
+
+void _init(void)
+{
+ register_target(&imq);
+}
diff -urN iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch
--- iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch Mon Apr 29 01:34:33 2002
@@ -0,0 +1,94 @@
+diff -urN linux-2.4.18-clean/include/linux/netfilter_ipv4/ipt_IMQ.h linux-2.4.18-imq-nf/include/linux/netfilter_ipv4/ipt_IMQ.h
+--- linux-2.4.18-clean/include/linux/netfilter_ipv4/ipt_IMQ.h Thu Jan 1 01:00:00 1970
++++ linux-2.4.18-imq-nf/include/linux/netfilter_ipv4/ipt_IMQ.h Tue Apr 2 21:35:20 2002
+@@ -0,0 +1,8 @@
++#ifndef _IPT_IMQ_H
++#define _IPT_IMQ_H
++
++struct ipt_imq_info {
++ unsigned int todev; /* target imq device */
++};
++
++#endif /* _IPT_IMQ_H */
+diff -urN linux-2.4.18-clean/net/ipv4/netfilter/ipt_IMQ.c linux-2.4.18-imq-nf/net/ipv4/netfilter/ipt_IMQ.c
+--- linux-2.4.18-clean/net/ipv4/netfilter/ipt_IMQ.c Thu Jan 1 01:00:00 1970
++++ linux-2.4.18-imq-nf/net/ipv4/netfilter/ipt_IMQ.c Tue Apr 2 21:34:15 2002
+@@ -0,0 +1,78 @@
++/* This target marks packets to be enqueued to an imq device */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_IMQ.h>
++#include <linux/imq.h>
++
++static unsigned int imq_target(struct sk_buff **pskb,
++ unsigned int hooknum,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *targinfo,
++ void *userinfo)
++{
++ struct ipt_imq_info *mr = (struct ipt_imq_info*)targinfo;
++
++ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
++ (*pskb)->nfcache |= NFC_ALTERED;
++
++ return IPT_CONTINUE;
++}
++
++static int imq_checkentry(const char *tablename,
++ const struct ipt_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ struct ipt_imq_info *mr;
++
++ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_imq_info))) {
++ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
++ return 0;
++ }
++ mr = (struct ipt_imq_info*)targinfo;
++
++ if (strcmp(tablename, "mangle") != 0) {
++ printk(KERN_WARNING
++ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
++ tablename);
++ return 0;
++ }
++
++ if (mr->todev > IMQ_MAX_DEVS) {
++ printk(KERN_WARNING
++ "IMQ: invalid device specified, highest is %u\n",
++ IMQ_MAX_DEVS);
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct ipt_target ipt_imq_reg = {
++ { NULL, NULL},
++ "IMQ",
++ imq_target,
++ imq_checkentry,
++ NULL,
++ THIS_MODULE
++};
++
++static int __init init(void)
++{
++ if (ipt_register_target(&ipt_imq_reg))
++ return -EINVAL;
++
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_target(&ipt_imq_reg);
++}
++
++module_init(init);
++module_exit(fini);
++MODULE_LICENSE("GPL");
diff -urN iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.config.in iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.config.in
--- iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.config.in Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.config.in Mon Apr 29 01:34:33 2002
@@ -0,0 +1,2 @@
+ dep_tristate ' MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
+ dep_tristate ' IMQ target support' CONFIG_IP_NF_TARGET_IMQ $CONFIG_IP_NF_MANGLE
diff -urN iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.configure.help iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.configure.help
--- iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.configure.help Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.configure.help Mon Apr 29 01:34:33 2002
@@ -0,0 +1,8 @@
+CONFIG_IP_NF_TARGET_MARK
+IMQ target support
+CONFIG_IP_NF_TARGET_IMQ
+ This option adds a `IMQ' target which is used to specify if and
+ to which imq device packets should get enqueued/dequeued.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
diff -urN iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.help iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.help
--- iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.help Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.help Mon Apr 29 01:34:33 2002
@@ -0,0 +1,5 @@
+Author: Patrick McHardy <kaber@trash.net>
+Status: Working
+
+ This patch adds a new target 'IMQ' which is required
+ to direct packets through an imq device.
diff -urN iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.ipv6 iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.ipv6
--- iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.ipv6 Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.ipv6 Mon Apr 29 01:34:33 2002
@@ -0,0 +1,94 @@
+diff -urN linux-2.4.18-clean/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-2.4.18-imq/include/linux/netfilter_ipv6/ip6t_IMQ.h
+--- linux-2.4.18-clean/include/linux/netfilter_ipv6/ip6t_IMQ.h Thu Jan 1 01:00:00 1970
++++ linux-2.4.18-imq/include/linux/netfilter_ipv6/ip6t_IMQ.h Sun Apr 28 23:34:53 2002
+@@ -0,0 +1,8 @@
++#ifndef _IP6T_IMQ_H
++#define _IP6T_IMQ_H
++
++struct ip6t_imq_info {
++ unsigned int todev; /* target imq device */
++};
++
++#endif /* _IP6T_IMQ_H */
+diff -urN linux-2.4.18-clean/net/ipv6/netfilter/ip6t_IMQ.c linux-2.4.18-imq/net/ipv6/netfilter/ip6t_IMQ.c
+--- linux-2.4.18-clean/net/ipv6/netfilter/ip6t_IMQ.c Thu Jan 1 01:00:00 1970
++++ linux-2.4.18-imq/net/ipv6/netfilter/ip6t_IMQ.c Sun Apr 28 23:34:11 2002
+@@ -0,0 +1,78 @@
++/* This target marks packets to be enqueued to an imq device */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter_ipv6/ip6_tables.h>
++#include <linux/netfilter_ipv6/ip6t_IMQ.h>
++#include <linux/imq.h>
++
++static unsigned int imq_target(struct sk_buff **pskb,
++ unsigned int hooknum,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *targinfo,
++ void *userinfo)
++{
++ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)targinfo;
++
++ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
++ (*pskb)->nfcache |= NFC_ALTERED;
++
++ return IP6T_CONTINUE;
++}
++
++static int imq_checkentry(const char *tablename,
++ const struct ip6t_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ struct ip6t_imq_info *mr;
++
++ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_imq_info))) {
++ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
++ return 0;
++ }
++ mr = (struct ip6t_imq_info*)targinfo;
++
++ if (strcmp(tablename, "mangle") != 0) {
++ printk(KERN_WARNING
++ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
++ tablename);
++ return 0;
++ }
++
++ if (mr->todev > IMQ_MAX_DEVS) {
++ printk(KERN_WARNING
++ "IMQ: invalid device specified, highest is %u\n",
++ IMQ_MAX_DEVS);
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct ip6t_target ip6t_imq_reg = {
++ { NULL, NULL},
++ "IMQ",
++ imq_target,
++ imq_checkentry,
++ NULL,
++ THIS_MODULE
++};
++
++static int __init init(void)
++{
++ if (ip6t_register_target(&ip6t_imq_reg))
++ return -EINVAL;
++
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ ip6t_unregister_target(&ip6t_imq_reg);
++}
++
++module_init(init);
++module_exit(fini);
++MODULE_LICENSE("GPL");
diff -urN iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.ipv6.config.in iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.ipv6.config.in
--- iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.ipv6.config.in Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.ipv6.config.in Mon Apr 29 01:34:33 2002
@@ -0,0 +1,2 @@
+ dep_tristate ' MARK target support' CONFIG_IP6_NF_TARGET_MARK $CONFIG_IP6_NF_MANGLE
+ dep_tristate ' IMQ target support' CONFIG_IP6_NF_TARGET_IMQ $CONFIG_IP6_NF_MANGLE
diff -urN iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.ipv6.configure.help iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.ipv6.configure.help
--- iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.ipv6.configure.help Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.ipv6.configure.help Mon Apr 29 01:34:33 2002
@@ -0,0 +1,8 @@
+CONFIG_IP6_NF_TARGET_MARK
+IMQ target support
+CONFIG_IP6_NF_TARGET_IMQ
+ This option adds a `IMQ' target which is used to specify if and
+ to which imq device packets should get enqueued/dequeued.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
diff -urN iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.ipv6.help iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.ipv6.help
--- iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.ipv6.help Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.ipv6.help Mon Apr 29 01:34:33 2002
@@ -0,0 +1,5 @@
+Author: Patrick McHardy <kaber@trash.net>
+Status: Working
+
+ This patch adds a new target 'IMQ' which is required
+ to direct packets through an imq device.
diff -urN iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.ipv6.makefile iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.ipv6.makefile
--- iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.ipv6.makefile Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.ipv6.makefile Mon Apr 29 01:34:33 2002
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
+obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o
diff -urN iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.makefile iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.makefile
--- iptables-1.2.6a-clean/patch-o-matic/extra/IMQ.patch.makefile Thu Jan 1 01:00:00 1970
+++ iptables-1.2.6a-imq/patch-o-matic/extra/IMQ.patch.makefile Mon Apr 29 01:34:33 2002
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
+obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
This diff is collapsed.
diff -ru --new-file iproute2/Config iproute2-linkdelays/Config
--- iproute2/Config Sun Apr 16 11:42:46 2000
+++ iproute2-linkdelays/Config Tue Jun 17 14:23:53 2003
@@ -1,2 +1,4 @@
TC_CONFIG_DIFFSERV=n
+TC_CONFIG_DELAY=y
+TC_CONFIG_PLR=y
TC_CONFIG_ATM=n
diff -ru --new-file iproute2/examples/delay.eth0 iproute2-linkdelays/examples/delay.eth0
--- iproute2/examples/delay.eth0 Wed Dec 31 17:00:00 1969
+++ iproute2-linkdelays/examples/delay.eth0 Tue May 13 16:46:57 2003
@@ -0,0 +1,17 @@
+#! /bin/sh
+
+##
+# Point this to your tc binary.
+#
+TC=/home/root/tc
+##
+# Affect all packets on eth0
+#
+DEVICE=eth0
+##
+# Approx 1 second packet delay.
+#
+USECS=1000000
+
+${TC} qdisc add dev ${DEVICE} root delay ${USECS}
+
diff -ru --new-file iproute2/tc/Makefile iproute2-linkdelays/tc/Makefile
--- iproute2/tc/Makefile Wed Jan 9 20:08:18 2002
+++ iproute2-linkdelays/tc/Makefile Tue Jun 17 14:23:17 2003
@@ -13,6 +13,12 @@
TCMODULES += f_u32.o
TCMODULES += f_route.o
TCMODULES += f_fw.o
+ifeq ($(TC_CONFIG_DELAY),y)
+ TCMODULES += q_delay.o
+endif
+ifeq ($(TC_CONFIG_PLR),y)
+ TCMODULES += q_plr.o
+endif
ifeq ($(TC_CONFIG_DIFFSERV),y)
TCMODULES += q_dsmark.o
TCMODULES += q_gred.o
@@ -25,6 +31,7 @@
endif
#TCMODULES += q_csz.o
+TCMODULES += q_htb.o
#TCMODULES += q_hpfq.o
#TCMODULES += q_hfsc.o
diff -ru --new-file iproute2/tc/q_delay.c iproute2-linkdelays/tc/q_delay.c
--- iproute2/tc/q_delay.c Wed Dec 31 17:00:00 1969
+++ iproute2-linkdelays/tc/q_delay.c Thu Jul 10 18:19:51 2003
@@ -0,0 +1,133 @@
+/*
+ * q_delay.c 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: David T. McWherter, <dtm@vramp.net>
+ * Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include "utils.h"
+#include "tc_util.h"
+
+static void explain(void)
+{
+ fprintf(stderr, "Usage: ... delay <microseconds> [reset_time (0|1)]\n");
+}
+
+static void explain1(char *arg)
+{
+ fprintf(stderr, "Illegal \"%s\"\n", arg);
+}
+
+
+#define usage() return(-1)
+
+static int
+delay_parse_opt
+ (struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
+{
+ struct tc_delay_qopt opt;
+ char *end;
+
+ memset(&opt, 0, sizeof(opt));
+
+ if ( argc > 4 ) {
+ fprintf(stderr, "Too many arguments (seen: %d, expected: 2 or 4)\n",
+ argc);
+ return -1;
+ } else if ( argc < 2 ) {
+ fprintf(stderr, "Too few arguments (seen: %d, expected: 2 or 4)\n",
+ argc);
+ return -1;
+ } else {
+
+ while ( argc > 0 ) {
+ if (!strcmp(*argv, "usecs")) {
+ NEXT_ARG();
+ opt.delay_usec = strtoul(*argv,&end,0);
+ if (*end) {
+ explain1("microseconds");
+ return -1;
+ }