small-package/natflow/files/natflow-qos.init

243 lines
6.7 KiB
Bash

#!/bin/sh /etc/rc.common
# Copyright (C) 2006-2011 OpenWrt.org
START=95
DEVCTL=/dev/qos_ctl
IPOPS="lua /usr/lib/lua/ipops.lua"
test -e /usr/share/natflow/ipops.lua && IPOPS="lua /usr/share/natflow/ipops.lua"
qos_idx=0
# ipset_add ipsetname net
ipv4set_add()
{
local ipsetname=$1
local net=$2
#hack for 0.0.0.0/0
[ "$net" = "0.0.0.0/0" ] && net="0.0.0.0/1 128.0.0.0/1"
for n in $net; do
ipset add $ipsetname $n
done
}
get_rate_data()
{
local cnt num unit
echo -n $1 | grep -qi "bps$" || {
num=$1
echo -n $((num)) # assume num B/s
return
}
cnt=`echo -n $1 | wc -c || echo 0`
test $cnt -le 4 && echo -n 0 && return # assume 0 B/s
num=`echo -n $1 | cut -c0-$((cnt-4))`
unit=`echo -n $1 | cut -c$((cnt-3))-$cnt | tr A-Z a-z`
case $unit in
"kbps")
num=$((num*128))
;;
"mbps")
num=$((num*128*1024))
;;
"gbps")
num=$((num*128*1024*1024))
;;
*)
num=$((num/8))
;;
esac
echo -n $num # assume num bps
}
natflow_qos_setup()
{
local idx=$qos_idx
qos_idx=$((qos_idx+1))
local cfg="$1"
local disabled user user_port remote remote_port proto rx_rate tx_rate
config_get disabled "$cfg" disabled 0
config_get user "$cfg" user
config_get user_port "$cfg" user_port
config_get remote "$cfg" remote
config_get remote_port "$cfg" remote_port
config_get proto "$cfg" proto
config_get rx_rate "$cfg" rx_rate 0
config_get tx_rate "$cfg" tx_rate 0
[ "$disabled" = "1" ] && return 0
#echo add user=<ipset/ip/ipcidr>,user_port=<portset/port>,remote=<ipset/ip/ipcidr>,remote_port=<portset/port>,proto=<tcp/udp>,rxbytes=Bytes,txbytes=Bytes
user=$($IPOPS netStrings2ipcidrStrings "$user")
if [ "$(echo $user | sed 's/,/ /g' | wc -w)" -gt 1 ]; then
ipset create qos_u$idx nethash 2>/dev/null
ipset flush qos_u$idx
for net in $(echo $user | sed 's/,/ /g'); do
ipv4set_add qos_u$idx $net
done
user=qos_u$idx
fi
if [ "$(echo $user_port | sed 's/,/ /g;s/-/ /g' | wc -w)" -gt 1 ]; then
ipset create qos_up$idx bitmap:port range 0-65535 2>/dev/null
ipset flush qos_up$idx
for port in $(echo $user_port | sed 's/,/ /g'); do
ipset add qos_up$idx $port
done
user_port=qos_up$idx
fi
remote=$($IPOPS netStrings2ipcidrStrings "$remote")
if [ "$(echo $remote | sed 's/,/ /g' | wc -w)" -gt 1 ]; then
ipset create qos_r$idx nethash 2>/dev/null
ipset flush qos_r$idx
for net in $(echo $remote | sed 's/,/ /g'); do
ipv4set_add qos_r$idx $net
done
remote=qos_r$idx
fi
if [ "$(echo $remote_port | sed 's/,/ /g;s/-/ /g' | wc -w)" -gt 1 ]; then
ipset create qos_rp$idx bitmap:port range 0-65535 2>/dev/null
ipset flush qos_rp$idx
for port in $(echo $remote_port | sed 's/,/ /g'); do
ipset add qos_rp$idx $port
done
remote_port=qos_rp$idx
fi
rx_rate=$(get_rate_data "$rx_rate")
tx_rate=$(get_rate_data "$tx_rate")
cmd="add user=$user,user_port=$user_port,remote=$remote,remote_port=$remote_port,proto=$proto,rxbytes=$rx_rate,txbytes=$tx_rate"
echo "$cmd" >$DEVCTL
}
natflow_qos_zone_setup_tc()
{
local idx=$zone_idx
zone_idx=$((zone_idx+1))
local cfg="$1"
local fw_zone ifname type
config_get fw_zone "$cfg" fw_zone
config_get ifname "$cfg" ifname
config_get type "$cfg" type
(for fwz in $fw_zone; do
fw3 -q zone $fwz
done; \
for ifn in $ifname; do
echo $ifn
done) | sed 's/+$/\.\*/' | sort | uniq | while read IFN; do
#echo $type $idx=$IFN >$DEVCTL
case $type in
lan_zone)
ifconfig -a | grep "^$IFN " | awk '{print $1}' | while read lan; do
if [ "${lan}" = "${lan//:}" ]; then
qos_id=0
cat /dev/qos_ctl | grep "^add user=" | while read line; do
line="${line/*rxbytes=}"
rxbytes="${line/,*}"
quantum=$(($rxbytes/1000))
if test $quantum -lt 256; then
quantum=256
fi
qos_id=$((qos_id+1))
QOSID=$((qos_id*2-1))
lower1=$(for vif in /sys/class/net/$lan/lower_*; do test -e $vif && echo ${vif##/sys/class/net/*/lower_}; done)
lower2=$(for dev in $lower1; do for vif in /sys/class/net/$dev/lower_*; do test -e $vif && echo ${vif##/sys/class/net/*/lower_}; done; done)
devs=$(for dev in $lan $lower1 $lower2; do echo $dev; done | sort | uniq);
echo setup tc for @lan=[`echo $devs`] rxbytes=$rxbytes quantum=$quantum rule_id=${qos_id} QOSID=${QOSID}
for DEVICE in $devs; do
tc qdisc add dev $DEVICE root handle 1: htb &>/dev/null
tc class add dev $DEVICE parent 1: classid 1:${QOSID} htb rate ${rxbytes}Bps quantum $quantum &>/dev/null
tc filter add dev $DEVICE parent 1: protocol all prio 1 handle ${QOSID} fw classid 1:${QOSID} &>/dev/null
done
done
fi
done
;;
wan_zone)
ifconfig -a | grep "^$IFN " | awk '{print $1}' | while read wan; do
if [ "${wan}" = "${wan//:}" ]; then
qos_id=0
cat /dev/qos_ctl | grep "^add user=" | while read line; do
txbytes="${line/*,txbytes=}"
quantum=$(($txbytes/1000))
if test $quantum -lt 256; then
quantum=256
fi
qos_id=$((qos_id+1))
QOSID=$((qos_id*2))
lower1=$(for vif in /sys/class/net/$wan/lower_*; do test -e $vif && echo ${vif##/sys/class/net/*/lower_}; done)
lower2=$(for dev in $lower1; do for vif in /sys/class/net/$dev/lower_*; do test -e $vif && echo ${vif##/sys/class/net/*/lower_}; done; done)
devs=$(for dev in $wan $lower1 $lower2; do echo $dev; done | sort | uniq);
echo setup tc for @wan=[`echo $devs`] txbytes=$txbytes quantum=$quantum rule_id=${qos_id} QOSID=${QOSID}
for DEVICE in $devs; do
tc qdisc add dev $DEVICE root handle 1: htb &>/dev/null
tc class add dev $DEVICE parent 1: classid 1:${QOSID} htb rate ${txbytes}Bps quantum $quantum &>/dev/null
tc filter add dev $DEVICE parent 1: protocol all prio 1 handle ${QOSID} fw classid 1:${QOSID} &>/dev/null
done
done
fi
done
;;
esac
done
}
natflow_qos_clear_tc()
{
which tc &>/dev/null || return
ifconfig | grep "^[^ ]" | awk '{print $1}' | while read ifname; do
if [ "${ifname}" = "${ifname//:}" ]; then
tc qdisc del dev $ifname root &>/dev/null
fi
done
}
start() {
test -c $DEVCTL || return 0
echo clear >$DEVCTL
config_load natflow
config_foreach natflow_qos_setup qos
natflow_qos_clear_tc
if [ "$(uci get natflow.main.tc_classid_mode 2>/dev/null || echo 0)" = "1" ] && which tc &>/dev/null; then
echo tc_classid_mode=1 >/dev/qos_ctl
config_foreach natflow_qos_zone_setup_tc zone
else
echo tc_classid_mode=0 >/dev/qos_ctl
fi
mkdir -p /tmp/config
touch /tmp/config/natflow-qos
ln -s /tmp/config/natflow-qos /etc/config/natflow-qos &>/dev/null
config_load natflow-qos
config_foreach natflow_qos_setup qos
}
stop() {
test -c $DEVCTL || return 0
echo clear >$DEVCTL
ipset list -n | grep ^qos_ | while read ipset; do
ipset destroy $ipset
done
natflow_qos_clear_tc
}
restart() {
stop
start
}