Bring tc4shorewall code into the firewall script

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@2806 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2005-10-05 22:51:29 +00:00
parent 692dc5bda4
commit 7870f16cb7
6 changed files with 254 additions and 306 deletions

View File

@ -5,6 +5,10 @@
# This program is under GPL [http://www.gnu.org/copyleft/gpl.htm]
#
# (c) 1999,2000,2001,2002,2003,2004,2005 - Tom Eastep (teastep@shorewall.net)
# tcstart from tc4shorewall Version 0.5
# (c) 2005 Arne Bernin <arne@ucbering.de>
# Modified by Tom Eastep for integration into the Shorewall distribution
# published under GPL Version 2#
#
# Complete documentation is available at http://shorewall.net
#
@ -1261,8 +1265,6 @@ setup_providers()
add_a_provider() {
local t n iface option
[ -z "$TC_ENABLED" ] && fatal_error "Providers require TC_ENABLED=Yes in shorewall.conf"
for t in $PROVIDERS; do
if [ "$t" = "$table" ]; then
fatal_error "Duplicate Provider: $table, provider: \"$provider\""
@ -3122,6 +3124,217 @@ build_exclusion_chain() # $1 = variable to store chain name into $2 = table, $3
eval $1=$c
}
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)
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
}
#
# Process a TC Rule - $MARKING_CHAIN is assumed to contain the name of the
# default marking chain
@ -3442,10 +3655,10 @@ setup_tc1() {
f=$(find_file tcstart) # In case the script used this variable
if [ $f != /usr/share/shorewall/tcstart ]; then
save_progress_message "Restoring Traffic Control..."
save_command . $f
fi
save_progress_message "Restoring Traffic Control..."
save_command . $f
else
setup_traffic_shaping
fi
}
@ -3853,20 +4066,24 @@ refresh_tc() {
#
strip_file tcrules
while read mark sources dests proto ports sports; do
expandv mark sources dests proto ports sports
rule=$(echo "$mark $sources $dests $proto $ports $sports")
while read mark sources dests proto ports sports user testval; do
expandv mark sources dests proto ports sports user testval
rule=$(echo "$mark $sources $dests $proto $ports $sports $user $testval")
process_tc_rule
done < $TMP_DIR/tcrules
else
setup_tc1
fi
f=$(find_file tcstart)
if [ -n "$TC_ENABLED" ]; THEN
f=$(find_file tcstart)
if [ -x $f ]; then
export CONFIG_PATH SHOREWALL_DIR
eval $f
if [ -x $f ]; then
export CONFIG_PATH SHOREWALL_DIR
eval $f
fi
else
setup_traffic_shaping
fi
}
@ -8379,7 +8596,7 @@ define_firewall() # $1 = Command (Start or Restart)
ecn=$(find_file ecn)
[ -f $ecn ] && [ -n "$MANGLE_ENABLED" ] && setup_ecn $ecn
[ -n "$TC_ENABLED" ] && setup_tc
setup_tc
echo "Activating Rules..."; activate_rules
@ -8453,7 +8670,7 @@ refresh_firewall()
#
# Refresh Traffic Control
#
[ -n "$TC_ENABLED" ] && refresh_tc
refresh_tc
report "Shorewall Refreshed"
@ -9045,11 +9262,7 @@ do_initialize() {
IP_FORWARDING=On
fi
if [ -n "$TC_ENABLED" -a -z "$MANGLE_ENABLED" ]; then
startup_error "Traffic Control requires Mangle"
fi
[ -n "${BLACKLIST_DISPOSITION:=DROP}" ]
[ -n "${BLACKLIST_DISPOSITION:=DROP}" ]
case "$CLAMPMSS" in
[0-9]*)
@ -9103,11 +9316,7 @@ do_initialize() {
MARK_IN_FORWARD_CHAIN=$(added_param_value_no MARK_IN_FORWARD_CHAIN $MARK_IN_FORWARD_CHAIN)
[ -n "$MARK_IN_FORWARD_CHAIN" ] && MARKING_CHAIN=tcfor || MARKING_CHAIN=tcpre
if [ -n "$TC_ENABLED" ]; then
CLEAR_TC=$(added_param_value_yes CLEAR_TC $CLEAR_TC)
else
CLEAR_TC=
fi
CLEAR_TC=$(added_param_value_yes CLEAR_TC $CLEAR_TC)
if [ -n "$LOGFORMAT" ]; then
if [ -n "$(echo $LOGFORMAT | grep '%d')" ]; then

View File

@ -85,14 +85,7 @@ backup_file() # $1 = file to backup, $2 = (optional) Directory in which to creat
delete_file() # $1 = file to delete
{
if [ -z "$PREFIX" -a -f $1 -a ! -f ${1}-${VERSION}.bkout ]; then
if (mv $1 ${1}-${VERSION}.bkout); then
echo
echo "$1 moved to ${1}-${VERSION}.bkout"
else
exit 1
fi
fi
rm -f $1
}
install_file() # $1 = source $2 = target $3 = mode
@ -265,14 +258,6 @@ install_file help ${PREFIX}/usr/share/shorewall/help 0544
echo
echo "Help command executor installed in ${PREFIX}/usr/share/shorewall/help"
#
# Install the tcstart file
#
install_file tcstart ${PREFIX}/usr/share/shorewall/tcstart 0544
echo
echo "Traffic Shaper installed in ${PREFIX}/usr/share/shorewall/tcstart"
#
# Install the policy file
#
@ -414,7 +399,12 @@ fi
#
# Delete the Routes file
#
delete_file /etc/shorewall/routes
delete_file ${PREFIX}/etc/shorewall/routes
#
# Delete the tcstart file
#
delete_file ${PREFIX}/usr/share/shorewall/tcstart
#
# Install the Providers file

View File

@ -250,6 +250,13 @@ Migration Considerations:
/etc/shorewall/providers then you must set MARK_IN_FORWARD_CHAIN=Yes in
shorewall.conf.
13) The meaning of TC_ENABLED has been changed to coincide with the
integration of tc4shorewall. Beginning with this release,
the /etc/shorewall/tcrules file will be processed unconditionally.
TC_ENABLED=Yes will cause Shorewall to look for an external tcstart
script as it does today. TC_ENABLED=No will cause Shorewall to use
its internal traffic shaper (tc4shorewall).
New Features in Shorewall 2.5.*
1) Error and warning messages are made easier to spot by using

View File

@ -396,11 +396,13 @@ RETAIN_ALIASES=No
#
# ENABLE TRAFFIC SHAPING
#
# If you say "Yes" or "yes" here, Traffic Shaping is enabled in the firewall.
# If you say "No" or "no" then traffic shaping is not enabled.
# If you say "Yes" or "yes" here, Shorewall will look for an executable script
# in the CONFIG_PATH to execute to configure traffic shaping.
# If you say "No" or "no" then Shorewall will use it's internal traffic shaper
# "tc4shorewall" by Arne Bernin.
#
TC_ENABLED=Yes
TC_ENABLED=No
#
# Clear Traffic Shapping/Control
@ -409,7 +411,7 @@ TC_ENABLED=Yes
# traffic control rules during [re]start. This setting is intended
# for use by people that prefer to configure traffic shaping when
# the network interfaces come up rather than when the firewall
# is started. If that is what you want to do, set TC_ENABLED=Yes and
# is started. If that is what you want to do, set TC_ENABLED=No and
# CLEAR_TC=No and do not supply an /etc/shorewall/tcstart file. That
# way, your traffic shaping rules can still use the 'fwmark'
# classifier based on packet marking defined in /etc/shorewall/tcrules.

View File

@ -110,7 +110,6 @@ fi
%attr(0600,root,root) /usr/share/shorewall/action.template
%attr(0444,root,root) /usr/share/shorewall/functions
%attr(0544,root,root) /usr/share/shorewall/firewall
%attr(0544,root,root) /usr/share/shorewall/tcstart
%attr(0544,root,root) /usr/share/shorewall/help
%attr(0600,root,root) /usr/share/shorewall/macro.AllowICMPs
%attr(0600,root,root) /usr/share/shorewall/macro.Amanda

View File

@ -1,259 +0,0 @@
#! /bin/sh
# tcstart from tc4shorewall Version 0.5
# (c) 2005 Arne Bernin <arne@ucbering.de>
# Modified by Tom Eastep for integration into the Shorewall distribution
# published under GPL Version 2
created_tmp_dir=
if [ "$SHOREWALL_LIBRARY" != Loaded ]; then
SHARED_DIR=/usr/share/shorewall
FUNCTIONS=$SHARED_DIR/functions
CONFIG_DIR=/etc/shorewall
. $FUNCTIONS
PARAMS=$(find_file params)
[ -f $PARAMS ] && . $PARAMS
[ -n "${SHOREWALL_DIR:=.}" ]
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)
created_tmp_dir=Yes
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)
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 "$created_tmp_dir" ] && rm -rf $TMP_DIR