226 lines
5.7 KiB
Bash
226 lines
5.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
|
|
tc qdisc add dev $lan root handle 1: htb
|
|
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))
|
|
echo setup tc for $lan @lan rxbytes=$rxbytes quantum=$quantum qos_id=$qos_id
|
|
tc class add dev $lan parent 1: classid 1:${qos_id} htb rate ${rxbytes}Bps quantum $quantum
|
|
tc filter add dev $lan parent 1: protocol ip prio 1 handle ${qos_id} fw classid 1:${qos_id}
|
|
tc filter add dev $lan parent 1: protocol 0x8864 prio 2 handle ${qos_id} fw classid 1:${qos_id}
|
|
done
|
|
fi
|
|
done
|
|
;;
|
|
wan_zone)
|
|
ifconfig -a | grep "^$IFN " | awk '{print $1}' | while read wan; do
|
|
if [ "${wan}" = "${wan//:}" ]; then
|
|
qos_id=0
|
|
tc qdisc add dev $wan root handle 1: htb
|
|
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))
|
|
echo setup tc for $wan @wan txbytes=$txbytes quantum=$quantum qos_id=$qos_id
|
|
tc class add dev $wan parent 1: classid 1:${qos_id} htb rate ${txbytes}Bps quantum $quantum
|
|
tc filter add dev $wan parent 1: protocol ip prio 1 handle ${qos_id} fw classid 1:${qos_id}
|
|
tc filter add dev $wan parent 1: protocol 0x8864 prio 2 handle ${qos_id} fw classid 1:${qos_id}
|
|
done
|
|
fi
|
|
done
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
natflow_qos_clear_tc()
|
|
{
|
|
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" ]; 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
|
|
}
|
|
|
|
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
|
|
}
|