mirror of
https://gitlab.com/shorewall/code.git
synced 2024-11-27 18:13:13 +01:00
f35c0922c6
git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@2653 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
253 lines
7.7 KiB
Bash
Executable File
253 lines
7.7 KiB
Bash
Executable File
#! /bin/sh
|
|
|
|
# tcstart from tc4shorewall Version 0.5
|
|
# (c) 2005 Arne Bernin <arne@ucbering.de>
|
|
# published under GPL Version 2
|
|
|
|
if [ -z "$COMMAND" ]; then
|
|
SHOREWALL_DIR=.
|
|
SHARED_DIR=/usr/share/shorewall
|
|
FUNCTIONS=$SHARED_DIR/functions
|
|
|
|
. $FUNCTIONS
|
|
|
|
ensure_and_save_command()
|
|
{
|
|
if ! eval $* ; then
|
|
[ -n "$TMP_DIR" ] && rm -rf $TMP_DIR
|
|
exit 2
|
|
fi
|
|
}
|
|
|
|
run_and_save_command() { eval $*; }
|
|
|
|
save_progress_message() { echo $@; }
|
|
|
|
fatal_error()
|
|
{
|
|
echo " ERROR: $@" >&2
|
|
[ -n "$TMP_DIR" ] && rm -rf $TMP_DIR
|
|
exit 2
|
|
}
|
|
|
|
TMP_DIR=
|
|
TMP_DIR=$(mktempdir)
|
|
fi
|
|
|
|
setup_traffic_shaping()
|
|
{
|
|
local mtu r2q tc_all_devices device mark rate ceil prio options
|
|
mtu=1500
|
|
r2q=10
|
|
|
|
rate_to_kbit() {
|
|
local rateunit rate
|
|
rate=$1
|
|
rateunit=$( echo $rate | sed -e 's/[0-9]*//')
|
|
rate=$( echo $rate | sed -e 's/[a-z]*//g')
|
|
|
|
case $rateunit in
|
|
kbit)
|
|
rate=$rate
|
|
;;
|
|
mbit)
|
|
rate=$(expr $rate \* 1024)
|
|
;;
|
|
mbps)
|
|
rate=$(expr $rate \* 8192)
|
|
;;
|
|
kbps)
|
|
rate=$(expr $rate \* 8)
|
|
;;
|
|
*)
|
|
rate=$(expr $rate / 128)
|
|
;;
|
|
esac
|
|
echo $rate
|
|
}
|
|
|
|
calculate_quantum() {
|
|
local rate
|
|
rate=$1
|
|
rate=$(rate_to_kbit $rate)
|
|
rate=$(expr $rate \* 128 / $r2q )
|
|
if [ $rate -lt $mtu ] ; then
|
|
echo $mtu
|
|
else
|
|
echo $rate
|
|
fi
|
|
}
|
|
|
|
# get given outbandwidth for device
|
|
get_outband_for_dev() {
|
|
local device inband outband
|
|
while read device inband outband; do
|
|
expandv device inband outband
|
|
tcdev="$device $inband $outband"
|
|
if [ "$1" = "$device" ] ; then
|
|
echo $outband
|
|
return
|
|
fi
|
|
done < $TMP_DIR/tcdevices
|
|
}
|
|
|
|
check_tcclasses_options() {
|
|
while [ $# -gt 1 ]; do
|
|
shift
|
|
case $1 in
|
|
default|tcp-ack|tos-minimize-delay|tos-maximize-throughput|tos-maximize-reliability|tos-minimize-cost|tos-normal-service)
|
|
;;
|
|
*)
|
|
echo $1
|
|
return 1
|
|
;;
|
|
esac
|
|
done
|
|
return 0
|
|
}
|
|
|
|
get_defmark_for_dev() {
|
|
local searchdev searchmark device ceil prio options
|
|
searchdev=$1
|
|
|
|
while read device mark rate ceil prio options; do
|
|
expandv device mark rate ceil prio options
|
|
options=$(separate_list $options | tr '[A-Z]' '[a-z]')
|
|
tcdev="$device $mark $rate $ceil $prio $options"
|
|
if [ "$searchdev" = "$device" ] ; then
|
|
list_search "default" $options && echo $mark &&return 0
|
|
fi
|
|
done < $TMP_DIR/tcclasses
|
|
|
|
return 1
|
|
}
|
|
|
|
check_defmark_for_dev() {
|
|
get_defmark_for_dev $1 >/dev/null
|
|
}
|
|
|
|
validate_tcdevices_file() {
|
|
echo "Validating tcdevices file..."
|
|
local device local device inband outband
|
|
while read device inband outband; do
|
|
expandv device inband outband
|
|
tcdev="$device $inband $outband"
|
|
check_defmark_for_dev $device || fatal_error "Option default is not defined for any class in tcclasses for interface $device"
|
|
case $interface in
|
|
*:*|+)
|
|
fatal_error "Invalid Interface Name: $interface"
|
|
;;
|
|
esac
|
|
list_search $device $devices && fatal_error "Interface $device is defined more than once in tcdevices"
|
|
tc_all_devices="$tc_all_devices $device"
|
|
done < $TMP_DIR/tcdevices
|
|
}
|
|
|
|
validate_tcclasses_file() {
|
|
echo "Validating tcclasses file..."
|
|
local classlist device mark rate ceil prio bandw wrongopt allopts opt
|
|
allopts=""
|
|
while read device mark rate ceil prio options; do
|
|
expandv device mark rate ceil prio options
|
|
tcdev="$device $mark $rate $ceil $prio $options"
|
|
ratew=$(get_outband_for_dev $device)
|
|
options=$(separate_list $options | tr '[A-Z]' '[a-z]')
|
|
for opt in $options; do
|
|
list_search "$device-$opt" $allopts && fatal_error "option $opt already defined in a chain for interface $device in tcclasses"
|
|
allopts="$allopts $device-$opt"
|
|
done
|
|
wrongopt=$(check_tcclasses_options $options) || fatal_error "unknown option $wrongopt for class iface $device mark $mark in tcclasses file"
|
|
if [ -z "$ratew" ] ; then
|
|
fatal_error "device $device seems not to be configured in tcdevices"
|
|
fi
|
|
list_search "$device-$mark" $classlist && fatal_error "Mark $mark for interface $device defined more than once in tcclasses"
|
|
classlist="$classlist $device-$mark"
|
|
done < $TMP_DIR/tcclasses
|
|
}
|
|
|
|
|
|
|
|
add_root_tc() {
|
|
local defmark
|
|
defmark=$(get_defmark_for_dev $device)
|
|
run_and_save_command qt tc qdisc del dev $device root
|
|
run_and_save_command qt tc qdisc del dev $device ingress
|
|
ensure_and_save_command tc qdisc add dev $device root handle 1: htb default 1$defmark
|
|
ensure_and_save_command tc class add dev $device parent 1: classid 1:1 htb rate $outband
|
|
ensure_and_save_command tc qdisc add dev $device handle ffff: ingress
|
|
ensure_and_save_command tc filter add dev $device parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate ${inband} burst 10k drop flowid :1
|
|
}
|
|
|
|
add_tc_class() {
|
|
local full
|
|
full=$(get_outband_for_dev $device)
|
|
full=$(rate_to_kbit $full)
|
|
#set -x
|
|
if [ -z "$prio" ] ; then
|
|
prio=1
|
|
fi
|
|
|
|
case $rate in
|
|
*full*)
|
|
rate=$(echo $rate | sed -e "s/full/$full/")
|
|
rate="$(($rate))kbit"
|
|
;;
|
|
esac
|
|
|
|
case $ceil in
|
|
*full*)
|
|
ceil=$(echo $ceil | sed -e "s/full/$full/")
|
|
ceil="$(($ceil))kbit"
|
|
;;
|
|
esac
|
|
|
|
ensure_and_save_command tc class add dev $device parent 1:1 classid 1:1$mark htb rate $rate ceil $ceil prio $prio quantum $(calculate_quantum $rate)
|
|
ensure_and_save_command tc qdisc add dev $device parent 1:1$mark handle 1$mark: sfq perturb 10
|
|
# add filters
|
|
ensure_and_save_command tc filter add dev $device protocol ip parent 1:0 prio 1 handle $mark fw classid 1:1$mark
|
|
# options
|
|
list_search "tcp-ack" $options && ensure_and_save_command tc filter add dev $device parent 1:0 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 flowid 1:1$mark
|
|
list_search "tos-minimize-delay" $options && ensure_and_save_command tc filter add dev $device parent 1:0 protocol ip prio 10 u32 match ip tos 0x10 0xff flowid 1:1$mark
|
|
list_search "tos-minimize-cost" $options && ensure_and_save_command tc filter add dev $device parent 1:0 protocol ip prio 10 u32 match ip tos 0x02 0xff flowid 1:1$mark
|
|
list_search "tos-maximize-troughput" $options && ensure_and_save_command tc filter add dev $device parent 1:0 protocol ip prio 10 u32 match ip tos 0x08 0xff flowid 1:1$mark
|
|
list_search "tos-minimize-reliability" $options && ensure_and_save_command tc filter add dev $device parent 1:0 protocol ip prio 10 u32 match ip tos 0x04 0xff flowid 1:1$mark
|
|
list_search "tos-normal-service" $options && ensure_and_save_command tc filter add dev $device parent 1:0 protocol ip prio 10 u32 match ip tos 0x00 0xff flowid 1:1$mark
|
|
# tcp
|
|
}
|
|
|
|
strip_file tcdevices
|
|
strip_file tcclasses
|
|
|
|
validate_tcdevices_file
|
|
validate_tcclasses_file
|
|
|
|
if [ -s $TMP_DIR/tcdevices ]; then
|
|
save_progress_message "Restoring Traffic Control..."
|
|
echo "Processing tcdevices..."
|
|
|
|
while read device inband outband defmark ackmark; do
|
|
expandv device inband outband defmark ackmark
|
|
tcdev="$device $inband $outband"
|
|
add_root_tc
|
|
progress_message " TC Device $tcdev Added."
|
|
done < $TMP_DIR/tcdevices
|
|
fi
|
|
|
|
if [ -s $TMP_DIR/tcclasses ]; then
|
|
echo "Processing tcclasses..."
|
|
|
|
while read device mark rate ceil prio options; do
|
|
expandv device mark rate ceil prio options
|
|
tcdev="$device $mark $rate $ceil $prio $options"
|
|
options=$(separate_list $options | tr '[A-Z]' '[a-z]')
|
|
add_tc_class
|
|
progress_message " TC Class \"$tcdev\" Added."
|
|
done < $TMP_DIR/tcclasses
|
|
fi
|
|
|
|
}
|
|
|
|
setup_traffic_shaping
|
|
|
|
[ -n "$COMMAND" ] || rm -rf $TMP_DIR
|