From 37c98dad5ce8f5e5144bc5412f7776d6a886fbbe Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Tue, 20 Oct 2009 13:01:40 +0000 Subject: main/iproute2-qos: misc bugfixes fixed couple bugs and changed some logic how packets are being inspected and classified. (cherry picked from commit 0732f85009f5ce5a820b0c2ace2dc46e059b53ff) --- main/iproute2-qos/APKBUILD | 10 ++-- main/iproute2-qos/qos.eth0.sample | 97 ++++++++++++++++++++++++--------------- main/iproute2-qos/qos.ifb0.sample | 92 ++++++++++++++++++++++--------------- main/iproute2-qos/qos.initd | 62 +++++++++++++++---------- 4 files changed, 158 insertions(+), 103 deletions(-) diff --git a/main/iproute2-qos/APKBUILD b/main/iproute2-qos/APKBUILD index 7190d5c7..bb0b27a6 100644 --- a/main/iproute2-qos/APKBUILD +++ b/main/iproute2-qos/APKBUILD @@ -1,8 +1,8 @@ # Contributor: Ilya Strelkin # Maintainer: Ilya Strelkin pkgname=iproute2-qos -pkgver=0.2 -pkgrel=1 +pkgver=0.3 +pkgrel=0 pkgdesc="Scripts to set up quality of service with iproute2" url="http://git.alpinelinux.org/cgit/aports" license="GPL" @@ -19,7 +19,7 @@ build() { "$pkgdir"/etc/conf.d/qos.ifb0.sample } -md5sums="78c8edd233e081a167788b6198560b13 qos.initd -aeb793e4e1e7219bf245c06e29212048 qos.eth0.sample -d9bbf66187a62485450397c4e93d1293 qos.ifb0.sample +md5sums="dda96b445c6e4fe377e918f860825fb1 qos.initd +79cecb47b3d1f623d2f6790044b3afee qos.eth0.sample +9f8d3514081624ea2ad2606c1564c759 qos.ifb0.sample 785aff5d4284c47038a009797c576e34 setup-qos" diff --git a/main/iproute2-qos/qos.eth0.sample b/main/iproute2-qos/qos.eth0.sample index a8d1d385..1578dfa5 100644 --- a/main/iproute2-qos/qos.eth0.sample +++ b/main/iproute2-qos/qos.eth0.sample @@ -5,8 +5,8 @@ DEV=eth0 IFB_DEV=ifb0 # Leave blank if $DEV is ifbX # Internet EGRESS/INGRES rates in kbit or mbit. Measure this on a free line to gain precise value -EGRESS_RATE=1000kbit # 128kbit, 256kbit, 512kbit -INGRESS_RATE=1000kbit # 256kbit, 512kbit, 1024kbit +EGRESS_RATE=512kbit # 128kbit, 256kbit, 512kbit +INGRESS_RATE=2048kbit # 256kbit, 512kbit, 1024kbit # In order to control a queue at the router/bridge side we will downgrade a real link speed on purpose RATE_SUB_PERCENT=5 # 20, 10 @@ -23,7 +23,7 @@ DEV_RATE=50mbit # prio: if rate is variable and you want to be sure that interactive traffic has ultimate priority # none: if link is not congested # -EGRESS_ALG=hfsc +EGRESS_ALG=htb # EGRESS leaf Queuing Disciplines # @@ -31,9 +31,9 @@ EGRESS_ALG=hfsc # sfq: TCP sessions or best-effort class traffic # red: hightly congested links or high-speed Internet [> 10Mbit/sec]) # -INTERACTIVE_LEAF_QDISC=pfifo +INTERACTIVE_LEAF_QDISC=pfifo PRIVILEGED_LEAF_QDISC=pfifo -BESTEFFORT_LEAF_QDISC=red +BESTEFFORT_LEAF_QDISC=red LAN_LEAF_QDISC=sfq # INGRESS treatment @@ -50,21 +50,19 @@ INGRESS_ALG=ifb # Maximum 100 filter items are allowed for each class. # By default ALL unclassified traffic is being assined to Best-Effort class. -# UDP -INTERACTIVE_FILTER_1="protocol ip prio 100 u32 match ip protocol 0x11 0xff" - -# ICMP -INTERACTIVE_FILTER_2="protocol ip prio 100 u32 match ip protocol 0x1 0xff" +################################### +### INTERACTIVE FILTERING RULES ### +################################### # ACK with payload < 64 bytes (32-bit version) -INTERACTIVE_FILTER_3="protocol ip prio 100 u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33" +INTERACTIVE_FILTER_10="protocol ip prio 10 u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33" # ACK with payload < 64 bytes -INTERACTIVE_FILTER_4="protocol ip prio 100 u32 match ip protocol 6 0xff match u8 0x10 0xff at nexthdr+13 match u16 0x0000 0xffc0 at 2" +INTERACTIVE_FILTER_11="protocol ip prio 11 u32 match ip protocol 6 0xff match u8 0x10 0xff at nexthdr+13 match u16 0x0000 0xffc0 at 2" -# PHB TOS HEX -# -------------------------- -# 0x10 +# PHB TOS HEX NOTES +# ---------------------------------------------- +# 0x10 SSH, IAX2 # 0x18 # CS1 PRIORITY 0x20 # AF11 0x28 @@ -77,54 +75,77 @@ INTERACTIVE_FILTER_4="protocol ip prio 100 u32 match ip protocol 6 0xff match u8 # AF23 0x58 # # CS5 CRITICAL 0xA0 -# EF 0xB8 +# EF 0xB8 IAX2, SIP Voice # -# CS6 INTERNETWORKCONTROL 0xC0 +# CS6 INTERNETWORKCNTRL 0xC0 BGP (by default) # CS7 NETWORKCONTROL 0xE0 -INTERACTIVE_FILTER_5="protocol ip prio 100 u32 match ip tos 0x10 0xff" -INTERACTIVE_FILTER_6="protocol ip prio 100 u32 match ip tos 0x18 0xff" -INTERACTIVE_FILTER_7="protocol ip prio 100 u32 match ip tos 0xa0 0xff" -INTERACTIVE_FILTER_8="protocol ip prio 100 u32 match ip tos 0xb8 0xff" +INTERACTIVE_FILTER_30="protocol ip prio 30 u32 match ip tos 0xb8 0xff" +INTERACTIVE_FILTER_31="protocol ip prio 31 u32 match ip tos 0x10 0xff" +INTERACTIVE_FILTER_32="protocol ip prio 32 u32 match ip tos 0x18 0xff" +INTERACTIVE_FILTER_33="protocol ip prio 33 u32 match ip tos 0xa0 0xff" + +# UDP +INTERACTIVE_FILTER_90="protocol ip prio 90 u32 match ip protocol 0x11 0xff" + +# ICMP +INTERACTIVE_FILTER_91="protocol ip prio 91 u32 match ip protocol 0x1 0xff" + +################################## +### PRIVILEGED FILTERING RULES ### +################################## # SSH -PRIVILEGED_FILTER_1="protocol ip prio 100 u32 match ip dport 22 0xffff" -PRIVILEGED_FILTER_2="protocol ip prio 100 u32 match ip sport 22 0xffff" +PRIVILEGED_FILTER_20="protocol ip prio 20 u32 match ip dport 22 0xffff" +PRIVILEGED_FILTER_21="protocol ip prio 21 u32 match ip sport 22 0xffff" # Remote Desktop -PRIVILEGED_FILTER_3="protocol ip prio 100 u32 match ip dport 3389 0xffff" -PRIVILEGED_FILTER_4="protocol ip prio 100 u32 match ip sport 3389 0xffff" +PRIVILEGED_FILTER_22="protocol ip prio 22 u32 match ip dport 3389 0xffff" +PRIVILEGED_FILTER_23="protocol ip prio 23 u32 match ip sport 3389 0xffff" # ESP -PRIVILEGED_FILTER_5="protocol ip prio 100 u32 match ip protocol 0x32 0xff" +PRIVILEGED_FILTER_50="protocol ip prio 50 u32 match ip protocol 0x32 0xff" # AH -PRIVILEGED_FILTER_6="protocol ip prio 100 u32 match ip protocol 0x33 0xff" +PRIVILEGED_FILTER_51="protocol ip prio 51 u32 match ip protocol 0x33 0xff" + +# IPSEC-NAT +PRIVILEGED_FILTER_52="protocol ip prio 52 u32 match ip protocol 0x11 0xff match ip dport 4500 0xffff" +PRIVILEGED_FILTER_53="protocol ip prio 53 u32 match ip protocol 0x11 0xff match ip sport 4500 0xffff" -# PHB TOS HEX -# -------------------------- -# CS3 FLASH 0x60 +# PHB TOS HEX NOTES +# -------------------------------------- +# CS3 FLASH 0x60 SIP signaling # AF31 0x68 # AF32 0x70 # AF33 0x78 # # CS4 FLASHOVERRIDE 0x80 -# AF41 0x88 +# AF41 0x88 SIP Video # AF42 0x90 # AF43 0x98 -PRIVILEGED_FILTER_7="protocol ip prio 100 u32 match ip tos 0x88 0xff" +PRIVILEGED_FILTER_80="protocol ip prio 80 u32 match ip tos 0x60 0xff" +PRIVILEGED_FILTER_81="protocol ip prio 81 u32 match ip tos 0x88 0xff" -# IPSEC-NAT -PRIVILEGED_FILTER_8="protocol ip prio 90 u32 match ip protocol 0x11 0xff match ip dport 4500 0xffff" -PRIVILEGED_FILTER_9="protocol ip prio 90 u32 match ip protocol 0x11 0xff match ip sport 4500 0xffff" +################################### +### BEST-EFFORT FILTERING RULES ### +################################### +BESTEFFORT_FILTER_85="protocol ip prio 85 u32 match ip tos 0x4 0xff" +BESTEFFORT_FILTER_86="protocol ip prio 86 u32 match ip tos 0x6 0xff" +BESTEFFORT_FILTER_87="protocol ip prio 87 u32 match ip tos 0x90 0xff" +BESTEFFORT_FILTER_88="protocol ip prio 88 u32 match ip tos 0x98 0xff" # Example: Any traffic from/to 192.168.1.0/24 network will be classified as best-effort # -### BESTEFFORT_FILTER_1="protocol ip prio 3 u32 match ip src 192.168.1.0/24" -### BESTEFFORT_FILTER_2="protocol ip prio 4 u32 match ip dst 192.168.1.0/24" +### BESTEFFORT_FILTER_5="protocol ip prio 10 u32 match ip src 192.168.1.0/24" +### BESTEFFORT_FILTER_6="protocol ip prio 11 u32 match ip dst 192.168.1.0/24" + +########################### +### LAN FILTERING RULES ### +########################### # Example: Traffic Originated from router # -###LAN_FILTER_1="protocol ip prio 10 u32 match ip src 192.168.1.10" \ No newline at end of file +###LAN_FILTER_10="protocol ip prio 10 u32 match ip src 192.168.1.10" diff --git a/main/iproute2-qos/qos.ifb0.sample b/main/iproute2-qos/qos.ifb0.sample index 2f382b27..f71ef68a 100644 --- a/main/iproute2-qos/qos.ifb0.sample +++ b/main/iproute2-qos/qos.ifb0.sample @@ -5,8 +5,8 @@ DEV=ifb0 IFB_DEV= # Leave it blank if $DEV is ifbX # Internet EGRESS/INGRES rates in kbit or mbit. Measure this on a free line to gain precise value -EGRESS_RATE=1000kbit # 128kbit, 256kbit, 512kbit -INGRESS_RATE=1000kbit # 256kbit, 512kbit, 1024kbit +EGRESS_RATE=2048bit # 256kbit, 512kbit, 1024kbit +INGRESS_RATE=512kbit # 128kbit, 256kbit, 512kbit # In order to control a queue at the router/bridge side we will downgrade a real link speed on purpose RATE_SUB_PERCENT=5 # 20, 10 @@ -50,21 +50,19 @@ INGRESS_ALG=none # Maximum 100 filter items are allowed for each class. # By default ALL unclassified traffic is being assined to Best-Effort class. -# UDP -INTERACTIVE_FILTER_1="protocol ip prio 100 u32 match ip protocol 0x11 0xff" - -# ICMP -INTERACTIVE_FILTER_2="protocol ip prio 100 u32 match ip protocol 0x1 0xff" +################################### +### INTERACTIVE FILTERING RULES ### +################################### # ACK with payload < 64 bytes (32-bit version) -INTERACTIVE_FILTER_3="protocol ip prio 100 u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33" +INTERACTIVE_FILTER_10="protocol ip prio 10 u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33" # ACK with payload < 64 bytes -INTERACTIVE_FILTER_4="protocol ip prio 100 u32 match ip protocol 6 0xff match u8 0x10 0xff at nexthdr+13 match u16 0x0000 0xffc0 at 2" +INTERACTIVE_FILTER_11="protocol ip prio 11 u32 match ip protocol 6 0xff match u8 0x10 0xff at nexthdr+13 match u16 0x0000 0xffc0 at 2" -# PHB TOS HEX -# -------------------------- -# 0x10 +# PHB TOS HEX NOTES +# ---------------------------------------------- +# 0x10 SSH, IAX2 # 0x18 # CS1 PRIORITY 0x20 # AF11 0x28 @@ -77,55 +75,77 @@ INTERACTIVE_FILTER_4="protocol ip prio 100 u32 match ip protocol 6 0xff match u8 # AF23 0x58 # # CS5 CRITICAL 0xA0 -# EF 0xB8 +# EF 0xB8 IAX2, SIP Voice # -# CS6 INTERNETWORKCONTROL 0xC0 +# CS6 INTERNETWORKCNTRL 0xC0 BGP (by default) # CS7 NETWORKCONTROL 0xE0 -INTERACTIVE_FILTER_5="protocol ip prio 100 u32 match ip tos 0x10 0xff" -INTERACTIVE_FILTER_6="protocol ip prio 100 u32 match ip tos 0x18 0xff" -INTERACTIVE_FILTER_7="protocol ip prio 100 u32 match ip tos 0xa0 0xff" -INTERACTIVE_FILTER_8="protocol ip prio 100 u32 match ip tos 0xb8 0xff" +INTERACTIVE_FILTER_30="protocol ip prio 30 u32 match ip tos 0xb8 0xff" +INTERACTIVE_FILTER_31="protocol ip prio 31 u32 match ip tos 0x10 0xff" +INTERACTIVE_FILTER_32="protocol ip prio 32 u32 match ip tos 0x18 0xff" +INTERACTIVE_FILTER_33="protocol ip prio 33 u32 match ip tos 0xa0 0xff" + +# UDP +INTERACTIVE_FILTER_90="protocol ip prio 90 u32 match ip protocol 0x11 0xff" + +# ICMP +INTERACTIVE_FILTER_91="protocol ip prio 91 u32 match ip protocol 0x1 0xff" +################################## +### PRIVILEGED FILTERING RULES ### +################################## # SSH -PRIVILEGED_FILTER_1="protocol ip prio 100 u32 match ip dport 22 0xffff" -PRIVILEGED_FILTER_2="protocol ip prio 100 u32 match ip sport 22 0xffff" +PRIVILEGED_FILTER_20="protocol ip prio 20 u32 match ip dport 22 0xffff" +PRIVILEGED_FILTER_21="protocol ip prio 21 u32 match ip sport 22 0xffff" # Remote Desktop -PRIVILEGED_FILTER_3="protocol ip prio 100 u32 match ip dport 3389 0xffff" -PRIVILEGED_FILTER_4="protocol ip prio 100 u32 match ip sport 3389 0xffff" +PRIVILEGED_FILTER_22="protocol ip prio 22 u32 match ip dport 3389 0xffff" +PRIVILEGED_FILTER_23="protocol ip prio 23 u32 match ip sport 3389 0xffff" # ESP -PRIVILEGED_FILTER_5="protocol ip prio 100 u32 match ip protocol 0x32 0xff" +PRIVILEGED_FILTER_50="protocol ip prio 50 u32 match ip protocol 0x32 0xff" # AH -PRIVILEGED_FILTER_6="protocol ip prio 100 u32 match ip protocol 0x33 0xff" +PRIVILEGED_FILTER_51="protocol ip prio 51 u32 match ip protocol 0x33 0xff" + +# IPSEC-NAT +PRIVILEGED_FILTER_52="protocol ip prio 52 u32 match ip protocol 0x11 0xff match ip dport 4500 0xffff" +PRIVILEGED_FILTER_53="protocol ip prio 53 u32 match ip protocol 0x11 0xff match ip sport 4500 0xffff" -# PHB TOS HEX -# -------------------------- -# CS3 FLASH 0x60 +# PHB TOS HEX NOTES +# -------------------------------------- +# CS3 FLASH 0x60 SIP signaling # AF31 0x68 # AF32 0x70 # AF33 0x78 # # CS4 FLASHOVERRIDE 0x80 -# AF41 0x88 +# AF41 0x88 SIP Video # AF42 0x90 # AF43 0x98 -PRIVILEGED_FILTER_7="protocol ip prio 100 u32 match ip tos 0x88 0xff" +PRIVILEGED_FILTER_80="protocol ip prio 80 u32 match ip tos 0x60 0xff" +PRIVILEGED_FILTER_81="protocol ip prio 81 u32 match ip tos 0x88 0xff" -# IPSEC-NAT -PRIVILEGED_FILTER_8="protocol ip prio 90 u32 match ip protocol 0x11 0xff match ip dport 4500 0xffff" -PRIVILEGED_FILTER_9="protocol ip prio 90 u32 match ip protocol 0x11 0xff match ip sport 4500 0xffff" +################################### +### BEST-EFFORT FILTERING RULES ### +################################### +BESTEFFORT_FILTER_85="protocol ip prio 85 u32 match ip tos 0x4 0xff" +BESTEFFORT_FILTER_86="protocol ip prio 86 u32 match ip tos 0x6 0xff" +BESTEFFORT_FILTER_87="protocol ip prio 87 u32 match ip tos 0x90 0xff" +BESTEFFORT_FILTER_88="protocol ip prio 88 u32 match ip tos 0x98 0xff" # Example: Any traffic from/to 192.168.1.0/24 network will be classified as best-effort -# -### BESTEFFORT_FILTER_1="protocol ip prio 3 u32 match ip src 192.168.1.0/24" -### BESTEFFORT_FILTER_2="protocol ip prio 4 u32 match ip dst 192.168.1.0/24" +# +### BESTEFFORT_FILTER_5="protocol ip prio 10 u32 match ip src 192.168.1.0/24" +### BESTEFFORT_FILTER_6="protocol ip prio 11 u32 match ip dst 192.168.1.0/24" + +########################### +### LAN FILTERING RULES ### +########################### # Example: Traffic Originated from router # -###LAN_FILTER_1="protocol ip prio 10 u32 match ip src 192.168.1.10" \ No newline at end of file +###LAN_FILTER_10="protocol ip prio 10 u32 match ip src 192.168.1.10" diff --git a/main/iproute2-qos/qos.initd b/main/iproute2-qos/qos.initd index b2d33f04..9986a8cc 100644 --- a/main/iproute2-qos/qos.initd +++ b/main/iproute2-qos/qos.initd @@ -84,8 +84,14 @@ configure() # Calculaton of WAN classes rates WAN_SUB_RATE=$((WAN_RATE - (RATE_SUB_PERCENT * WAN_RATE / 100))) INTERACTIVE_RATE=$((WAN_SUB_RATE / 5)) + if [ $INTERACTIVE_RATE -lt 75000 ]; then + INTERACTIVE_RATE=75000 + PRIVILEGED_RATE=$(((WAN_SUB_RATE - 75000) / 2)) + BESTEFFORT_RATE=$(((WAN_SUB_RATE - 75000) / 2)) + else PRIVILEGED_RATE=$((WAN_SUB_RATE / 2)) BESTEFFORT_RATE=$((WAN_SUB_RATE / 3)) + fi DEV_RATE=${DEV_RATE:-$EGRESS_RATE} DEV_RATE=`bits $DEV_RATE` @@ -99,12 +105,10 @@ configure() INTERACTIVE_PRIO_BURST=$((INTERACTIVE_RATE / 100 / 8)) INTERACTIVE_HFSC_DMAX=50000 - INTERACTIVE_HFSC_UMAX=$((INTERACTIVE_RATE * INTERACTIVE_HFSC_DMAX / 1000 / 1000)) - [ $INTERACTIVE_HFSC_UMAX -gt 1500 ] && INTERACTIVE_HFSC_UMAX=1500 + INTERACTIVE_HFSC_UMAX=1500 PRIVILEGED_HFSC_DMAX=100000 - PRIVILEGED_HFSC_UMAX=$((PRIVILEGED_RATE * PRIVILEGED_HFSC_DMAX / 1000 / 1000)) - [ $PRIVILEGED_HFSC_UMAX -gt 1500 ] && PRIVILEGED_HFSC_UMAX=1500 + PRIVILEGED_HFSC_UMAX=1500 # Random Early Detect (RED) parameters calculation: # min = maximum delay * rate (dalay ~ 200ms = 0.2sec) [b] @@ -123,9 +127,18 @@ configure() RED_LIMIT=$((8 * RED_MAX)) # Setting leaf Queuing Disciplines parameters - INTERACTIVE_LEAF_QDISC=`expand_leaf_qdisc $INTERACTIVE_LEAF_QDISC` - PRIVILEGED_LEAF_QDISC=`expand_leaf_qdisc $PRIVILEGED_LEAF_QDISC` + INTERACTIVE_LEAF_QDISC=pfifo + INTERACTIVE_LEAF_QDISC=`expand_leaf_qdisc $INTERACTIVE_LEAF_QDISC` + PRIVILEGED_LEAF_QDISC=pfifo + PRIVILEGED_LEAF_QDISC=`expand_leaf_qdisc $PRIVILEGED_LEAF_QDISC` + + # Force using SFQ in case rate is less than 2mbit + if [ $BESTEFFORT_RATE -lt 2097152 ]; then + BESTEFFORT_LEAF_QDISC=sfq + fi BESTEFFORT_LEAF_QDISC=`expand_leaf_qdisc $BESTEFFORT_LEAF_QDISC` + + LAN_LEAF_QDISC=sfq LAN_LEAF_QDISC=`expand_leaf_qdisc $LAN_LEAF_QDISC` fi } @@ -182,23 +195,26 @@ set_filters() BESTEFFORT_FILTER_FLOWID=60 LAN_FILTER_FLOWID=70 - for CLASS_TYPE in $CLASS_TYPES; do - if [ "$QDISC_CMD" = "prio" -a "$CLASS_TYPE" = "INTERACTIVE" ]; then - PARENT_CLASSID=1 - INTERACTIVE_FILTER_FLOWID=1 - else - PARENT_CLASSID=$1 - PARENT_CLASSID=${PARENT_CLASSID:-1} - INTERACTIVE_FILTER_FLOWID=40 - fi - - for FILTER_NUM in `seq 1 100`; do - eval FILTER="\$$CLASS_TYPE"_FILTER_$FILTER_NUM - [ -z "$FILTER" ] && break - eval FILTER_FLOWID="\$$CLASS_TYPE"_FILTER_FLOWID - $ECHO tc filter add dev $DEV parent $PARENT_CLASSID:0 $FILTER flowid $PARENT_CLASSID:$FILTER_FLOWID + { + for CLASS_TYPE in $CLASS_TYPES; do + if [ "$QDISC_CMD" = "prio" -a "$CLASS_TYPE" = "INTERACTIVE" ]; then + PARENT_CLASSID=1 + INTERACTIVE_FILTER_FLOWID=1 + else + PARENT_CLASSID=$1 + PARENT_CLASSID=${PARENT_CLASSID:-1} + INTERACTIVE_FILTER_FLOWID=40 + fi + + for FILTER_NUM in `seq 1 100`; do + eval FILTER="\$$CLASS_TYPE"_FILTER_$FILTER_NUM + if [ ! -z "$FILTER" ]; then + eval FILTER_FLOWID="\$$CLASS_TYPE"_FILTER_FLOWID + $ECHO tc filter add dev $DEV parent $PARENT_CLASSID:0 $FILTER flowid $PARENT_CLASSID:$FILTER_FLOWID + fi + done done - done + } | sort -g $ECHO } @@ -402,8 +418,6 @@ start() fi done -describe > /tmp/$$ - if [ $DEBUG -eq 0 ]; then eend $? fi -- cgit v1.2.3