Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh
- # Shell script port of Asuswrt bandwidth limiter
- #
- # SOURCE: https://github.com/RMerl/asuswrt-merlin/blob/380.57/release/src/router/rc/qos.c
- # https://github.com/RMerl/asuswrt-merlin/blob/380.57/release/src/router/shared/model.c
- #
- #
- local action=$1
- local pcWANIF=$2
- local qos_bw_rulelist="$3"
- local GUEST_NETWORK_NAMES="wl* vlan*" # list of network interaces (space separated)
- local QOS_SCRIPT="/tmp/qos_custom"
- local MANGLE_SCRIPT="/tmp/mangle_rules_custom"
- local qos_enable=1
- local qos_type=2
- local addr_type=-1
- local addr_new=""
- local guest=0
- local TYPE_IP=0
- local TYPE_MAC=1
- local TYPE_IPRANGE=2
- local TYPE_GUEST=3
- address_checker()
- {
- local addr_old=$1
- addr_type=-1
- addr_new=""
- for name in $GUEST_NETWORK_NAMES; do
- if [ "${addr_old#$name}" != "$addr_old" ]; then
- addr_type=$TYPE_GUEST
- addr_new=$addr_old
- return 0
- fi
- done
- local second=${addr_old##*-}
- if [ "$second" != "$addr_old" ]; then
- addr_type=$TYPE_IPRANGE
- if [ "${second#.}" != "$second" ]; then
- # long notation
- addr_new=$addr_old
- else
- # short notation
- local first=${addr_old%%-*}
- local len_second=${#second}
- local len_first=${#first}
- local copy_first=${first:0:$((len_first-len_second))}
- addr_new=${first}-${copy_first}${second}
- fi
- else
- if [ ${#addr_old} == 17 ]; then
- addr_type=$TYPE_MAC
- else
- addr_type=$TYPE_IP
- fi
- addr_new=$addr_old
- fi
- }
- update_rule()
- {
- local CMD="$1"
- local CHAIN="$2"
- local RULENUM="$3"
- local RULE="$4"
- local ACTION="$5"
- #/bin/echo update_rule $CMD $CHAIN $RULENUM $RULE $DELETE
- if [ "${CMD%iptables}" != "$CMD" ]; then
- if [ "$ACTION" == "append" ]; then
- $CMD -C $CHAIN $RULE > /dev/null 2>&1 || $CMD -A $CHAIN $RULE
- elif [ "$ACTION" == "insert" ]; then
- $CMD -C $CHAIN $RULE > /dev/null 2>&1 || $CMD -I $CHAIN $RULENUM $RULE
- elif [ "$ACTION" == "delete" ]; then
- $CMD -C $CHAIN $RULE > /dev/null 2>&1 && $CMD -D $CHAIN $RULE
- else
- /bin/echo "Invalid action."
- fi
- elif [ "${CMD%ebtables}" != "$CMD" ]; then
- $CMD -D $CHAIN $RULE
- while [ $? == 0 ]; do
- $CMD -D $CHAIN $RULE
- done
- if [ "$ACTION" == "append" ]; then
- $CMD -A $CHAIN $RULE
- elif [ "$ACTION" == "insert" ]; then
- $CMD -I $CHAIN $RULENUM $RULE
- elif [ "$ACTION" != "delete" ]; then
- /bin/echo "Invalid action."
- fi
- fi
- }
- del_EbtablesRules()
- {
- /usr/sbin/ebtables -t nat -F
- }
- del_iQosRules()
- {
- # /usr/sbin/ip link set imq0 down
- del_EbtablesRules
- /usr/sbin/iptables -t mangle -F
- /usr/sbin/ip6tables -t mangle -F
- }
- add_bandwidth_limiter_rules()
- {
- /bin/rm -f $MANGLE_SCRIPT
- #del_iQosRules # flush all rules in mangle table
- local model=$(/usr/sbin/nvram get model)
- case ${model} in
- "DSL-N55U" | "DSL-N55U-B" | "RT-N13U" | "RT-N56UB1" | "RT-N56UB2" | "RT-N56U")
- local action="CONNMARK --set-return"
- local manual_return=0
- ;;
- *)
- local action="MARK --set-mark"
- local manual_return=1
- ;;
- esac
- local lan_ipaddr=$(/usr/sbin/nvram get lan_ipaddr)
- local lan_addr="${lan_ipaddr}/$(/usr/sbin/nvram get lan_netmask)"
- /usr/bin/printf "*mangle\n" >> $MANGLE_SCRIPT
- /usr/bin/printf ":PREROUTING ACCEPT [0:0]\n" >> $MANGLE_SCRIPT
- /usr/bin/printf ":OUTPUT ACCEPT [0:0]\n" >> $MANGLE_SCRIPT
- # access router : mark 9
- /usr/bin/printf "-A POSTROUTING -s %s -d %s -j %s 9\n" "$lan_ipaddr" "$lan_addr" "$action" >> $MANGLE_SCRIPT
- /usr/bin/printf "-A PREROUTING -s %s -d %s -j %s 9\n" "$lan_addr" "$lan_ipaddr" "$action" >> $MANGLE_SCRIPT
- if [ $manual_return == 1 ]; then
- /usr/bin/printf "-A POSTROUTING -s %s -d %s -j RETURN\n" "$lan_ipaddr" "$lan_addr" >> $MANGLE_SCRIPT
- /usr/bin/printf "-A PREROUTING -s %s -d %s -j RETURN\n" "$lan_addr" "$lan_ipaddr" >> $MANGLE_SCRIPT
- fi
- local N=1
- local g="${qos_bw_rulelist}<"
- local rule=$(/bin/echo ${g} | /usr/bin/cut -f${N} -d'<')
- while [ "$rule" != "" ]; do
- local enable=$(/bin/echo $rule | /usr/bin/cut -f1 -d'>')
- if [ "$enable" == "0" ]; then
- continue
- fi
- local addr=$(/bin/echo $rule | /usr/bin/cut -f2 -d'>')
- local dlc=$(/bin/echo $rule | /usr/bin/cut -f3 -d'>')
- local upc=$(/bin/echo $rule | /usr/bin/cut -f4 -d'>')
- local prio=$(/bin/echo $rule | /usr/bin/cut -f5 -d'>')
- address_checker $addr
- let local class=prio+10
- if [ $addr_type == $TYPE_IP ]; then
- printf "-A POSTROUTING ! -s %s -d %s -j %s %d\n" "$lan_addr" "$addr_new" "$action" "$class" >> $MANGLE_SCRIPT
- printf "-A PREROUTING -s %s ! -d %s -j %s %d\n" "$addr_new" "$lan_addr" "$action" "$class" >> $MANGLE_SCRIPT
- if [ $manual_return == 1 ]; then
- printf "-A POSTROUTING ! -s %s -d %s -j RETURN\n" "$lan_addr" "$addr_new" >> $MANGLE_SCRIPT
- printf "-A PREROUTING -s %s ! -d %s -j RETURN\n" "$addr_new" "$lan_addr" >> $MANGLE_SCRIPT
- fi
- elif [ $addr_type == $TYPE_MAC ]; then
- printf "-A PREROUTING -m mac --mac-source %s ! -d %s -j %s %d\n" "$addr_new" "$lan_addr" "$action" "$class" >> $MANGLE_SCRIPT
- if [ $manual_return == 1 ]; then
- printf "-A PREROUTING -m mac --mac-source %s ! -d %s -j RETURN\n" "$addr_new" "$lan_addr" >> $MANGLE_SCRIPT
- fi
- elif [ $addr_type == $TYPE_IPRANGE ]; then
- printf "-A POSTROUTING ! -s %s -m iprange --dst-range %s -j %s %d\n" "$lan_addr" "$addr_new" "$action" "$class" >> $MANGLE_SCRIPT
- printf "-A PREROUTING -m iprange --src-range %s ! -d %s -j %s %d\n" "$addr_new" "$lan_addr" "$action" "$class" >> $MANGLE_SCRIPT
- if [ $manual_return == 1 ]; then
- printf "-A POSTROUTING ! -s %s -m iprange --dst-range %s -j RETURN\n" "$lan_addr" "$addr_new" >> $MANGLE_SCRIPT
- printf "-A PREROUTING -m iprange --src-range %s ! -d %s -j RETURN\n" "$addr_new" "$lan_addr" >> $MANGLE_SCRIPT
- fi
- elif [ $addr_type == $TYPE_GUEST ]; then
- continue
- fi
- let local N++
- local rule=$(/bin/echo ${g} | /usr/bin/cut -f${N} -d'<')
- done
- /usr/bin/printf "COMMIT\n" >> $MANGLE_SCRIPT
- /bin/chmod 0700 $MANGLE_SCRIPT
- /usr/sbin/iptables-restore $MANGLE_SCRIPT
- }
- start_bandwidth_limiter()
- {
- # init guest 3: ~ 12: (9 guestnetwork), start number = 3
- guest=3
- /bin/rm -f $QOS_SCRIPT
- /usr/bin/printf "#!/bin/sh\n" >> $QOS_SCRIPT
- /usr/bin/printf "WAN=${pcWANIF}\n" >> $QOS_SCRIPT
- /usr/bin/printf "\n" >> $QOS_SCRIPT
- /usr/bin/printf "case \"\$1\" in\n" >> $QOS_SCRIPT
- /usr/bin/printf "start)\n" >> $QOS_SCRIPT
- if [ "$qos_bw_rulelist" != "" ]; then
- /usr/bin/printf "/usr/sbin/tc qdisc del dev \$WAN root 2>/dev/null\n" >> $QOS_SCRIPT
- /usr/bin/printf "/usr/sbin/tc qdisc del dev \$WAN ingress 2>/dev/null\n" >> $QOS_SCRIPT
- /usr/bin/printf "/usr/sbin/tc qdisc del dev br0 root 2>/dev/null\n" >> $QOS_SCRIPT
- /usr/bin/printf "/usr/sbin/tc qdisc del dev br0 ingress 2>/dev/null\n" >> $QOS_SCRIPT
- /usr/bin/printf "\n" >> $QOS_SCRIPT
- /usr/bin/printf "TQAU=\"/usr/sbin/tc qdisc add dev \$WAN\"\n" >> $QOS_SCRIPT
- /usr/bin/printf "TCAU=\"/usr/sbin/tc class add dev \$WAN\"\n" >> $QOS_SCRIPT
- /usr/bin/printf "TFAU=\"/usr/sbin/tc filter add dev \$WAN\"\n" >> $QOS_SCRIPT
- /usr/bin/printf "SFQ=\"sfq perturb 10\"\n" >> $QOS_SCRIPT
- /usr/bin/printf "TQA=\"/usr/sbin/tc qdisc add dev br0\"\n" >> $QOS_SCRIPT
- /usr/bin/printf "TCA=\"/usr/sbin/tc class add dev br0\"\n" >> $QOS_SCRIPT
- /usr/bin/printf "TFA=\"/usr/sbin/tc filter add dev br0\"\n" >> $QOS_SCRIPT
- /usr/bin/printf "\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TQA root handle 1: htb\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TCA parent 1: classid 1:1 htb rate 10240000kbit\n" >> $QOS_SCRIPT
- /usr/bin/printf "\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TQAU root handle 2: htb\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TCAU parent 2: classid 2:1 htb rate 10240000kbit\n" >> $QOS_SCRIPT
- # access router : mark 9
- # default : 10Gbps
- /usr/bin/printf "\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TCA parent 1:1 classid 1:9 htb rate 10240000kbit ceil 10240000kbit prio 1\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TQA parent 1:9 handle 9: \$SFQ\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TFA parent 1: prio 1 protocol ip handle 9 fw flowid 1:9\n" >> $QOS_SCRIPT
- /usr/bin/printf "\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TCAU parent 2:1 classid 2:9 htb rate 10240000kbit ceil 10240000kbit prio 1\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TQAU parent 2:9 handle 9: \$SFQ\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TFAU parent 2: prio 1 protocol ip handle 9 fw flowid 2:9\n" >> $QOS_SCRIPT
- fi
- local N=1
- local g="${qos_bw_rulelist}<"
- local rule=$(/bin/echo ${g} | /usr/bin/cut -f${N} -d'<')
- while [ "$rule" != "" ]; do
- local enable=$(/bin/echo $rule | /usr/bin/cut -f1 -d'>')
- if [ "$enable" == "0" ]; then
- continue
- fi
- local addr=$(/bin/echo $rule | /usr/bin/cut -f2 -d'>')
- local dlc=$(/bin/echo $rule | /usr/bin/cut -f3 -d'>')
- local upc=$(/bin/echo $rule | /usr/bin/cut -f4 -d'>')
- local prio=$(/bin/echo $rule | /usr/bin/cut -f5 -d'>')
- address_checker $addr
- let local class=prio+10
- if [ $addr_type == $TYPE_MAC ]; then
- for X in 1 2 3 4 5 6; do eval local s${X}=0x$(/bin/echo ${addr} | /usr/bin/cut -f${X} -d':'); done
- /usr/bin/printf "\$TCA parent 1:1 classid 1:%d htb rate %skbit ceil %skbit prio %s\n" "$class" "$dlc" "$dlc" "$prio" >> $QOS_SCRIPT
- /usr/bin/printf "\$TQA parent 1:%d handle %d: \$SFQ\n" "$class" "$class" >> $QOS_SCRIPT
- /usr/bin/printf "\$TFA parent 1: protocol ip prio %s u32 match u16 0x0800 0xFFFF at -2 match u32 0x%02X%02X%02X%02X 0xFFFFFFFF at -12 match u16 0x%02X%02X 0xFFFF at -14 flowid 1:%d\n" "$prio" "$s3" "$s4" "$s5" "$s6" "$s1" "$s2" "$class" >> $QOS_SCRIPT
- /usr/bin/printf "\$TCAU parent 2:1 classid 2:%d htb rate %skbit ceil %skbit prio %s\n" "$class" "$upc" "$upc" "$prio" >> $QOS_SCRIPT
- /usr/bin/printf "\$TQAU parent 2:%d handle %d: \$SFQ\n" "$class" "$class" >> $QOS_SCRIPT
- /usr/bin/printf "\$TFAU parent 2: prio %s protocol ip handle %d fw flowid 2:%d\n" "$prio" "$class" "$class" >> $QOS_SCRIPT
- elif [ $addr_type == $TYPE_IP ] || [ $addr_type == $TYPE_IPRANGE ]; then
- /usr/bin/printf "\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TCA parent 1:1 classid 1:%d htb rate %skbit ceil %skbit prio %s\n" "$class" "$dlc" "$dlc" "$prio" >> $QOS_SCRIPT
- /usr/bin/printf "\$TQA parent 1:%d handle %d: \$SFQ\n" "$class" "$class" >> $QOS_SCRIPT
- /usr/bin/printf "\$TFA parent 1: prio %s protocol ip handle %d fw flowid 1:%d\n" "$prio" "$class" "$class" >> $QOS_SCRIPT
- /usr/bin/printf "\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TCAU parent 2:1 classid 2:%d htb rate %skbit ceil %skbit prio %s\n" "$class" "$upc" "$upc" "$prio" >> $QOS_SCRIPT
- /usr/bin/printf "\$TQAU parent 2:%d handle %d: \$SFQ\n" "$class" "$class" >> $QOS_SCRIPT
- /usr/bin/printf "\$TFAU parent 2: prio %s protocol ip handle %d fw flowid 2:%d\n" "$prio" "$class" "$class" >> $QOS_SCRIPT
- elif [ $addr_type == $TYPE_GUEST ]; then
- local ij=${addr_new#wl*}
- local i=${ij%.*}
- local j=${ij#*.}
- mssid_mark="$class"
- if [ "$ij" != "$addr_new" ]; then
- if [ "$(/usr/sbin/nvram get model)" == "RT-AC87U" ] && [ $i == 1 ]; then
- [ $j == 1 ] && local wl_if="vlan4000"
- [ $j == 2 ] && local wl_if="vlan4001"
- [ $j == 3 ] && local wl_if="vlan4002"
- else
- local wl_if="$addr_new"
- fi
- else
- local wl_if="$addr_new"
- local i=990
- local j=${addr_new#vlan*}
- if [ "$j" == "$addr_new" ]; then
- local i=991
- local j=${addr_new#eth*}
- fi
- fi
- /usr/sbin/ebtables -t nat PREROUTING -i $wl_if -j mark --set-mark $mssid_mark --mark-target ACCEPT
- /usr/sbin/ebtables -t nat POSTROUTING -o $wl_if -j mark --set-mark $mssid_mark --mark-target ACCEPT
- /usr/bin/printf "\n" >> $QOS_SCRIPT
- /usr/bin/printf "/usr/sbin/tc qdisc del dev %s root 2>/dev/null\n" "$wl_if" >> $QOS_SCRIPT
- /usr/bin/printf "GUEST%d%d=%s\n" "$i" "$j" "$wl_if" >> $QOS_SCRIPT
- /usr/bin/printf "TQA%d%d=\"/usr/sbin/tc qdisc add dev \$GUEST%d%d\"\n" "$i" "$j" "$i" "$j" >> $QOS_SCRIPT
- /usr/bin/printf "TCA%d%d=\"/usr/sbin/tc class add dev \$GUEST%d%d\"\n" "$i" "$j" "$i" "$j" >> $QOS_SCRIPT
- /usr/bin/printf "TFA%d%d=\"/usr/sbin/tc filter add dev \$GUEST%d%d\"\n" "$i" "$j" "$i" "$j" >> $QOS_SCRIPT # 5
- /usr/bin/printf "\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TQA%d%d root handle %d: htb\n" "$i" "$j" "$guest" >> $QOS_SCRIPT
- /usr/bin/printf "\$TCA%d%d parent %d: classid %d:1 htb rate %skbit\n" "$i" "$j" "$guest" "$guest" "$dlc" >> $QOS_SCRIPT # 7
- /usr/bin/printf "\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TCA%d%d parent %d:1 classid %d:%d htb rate 1kbit ceil %skbit prio %d\n" "$i" "$j" "$guest" "$guest" "$class" "$dlc" "$class" >> $QOS_SCRIPT
- /usr/bin/printf "\$TQA%d%d parent %d:%d handle %d: \$SFQ\n" "$i" "$j" "$guest" "$class" "$class" >> $QOS_SCRIPT
- /usr/bin/printf "\$TFA%d%d parent %d: prio %d protocol ip handle %d fw flowid %d:%d\n" "$i" "$j" "$guest" "$class" "$class" "$guest" "$class" >> $QOS_SCRIPT # 10
- /usr/bin/printf "\n" >> $QOS_SCRIPT
- /usr/bin/printf "\$TCAU parent 2:1 classid 2:%d htb rate 1kbit ceil %skbit prio %d\n" "$class" "$upc" "$class" >> $QOS_SCRIPT
- /usr/bin/printf "\$TQAU parent 2:%d handle %d: \$SFQ\n" "$class" "$class" >> $QOS_SCRIPT
- /usr/bin/printf "\$TFAU parent 2: prio %d protocol ip handle %d fw flowid 2:%d\n" "$class" "$class" "$class" >> $QOS_SCRIPT # 13
- let local guest++; # add guest 3: ~ 12: (9 guestnetwork)
- fi
- let local N++
- local rule=$(/bin/echo ${g} | /usr/bin/cut -f${N} -d'<')
- done
- /usr/bin/printf ";;\n" >> $QOS_SCRIPT
- /usr/bin/printf "stop)\n" >> $QOS_SCRIPT
- /usr/bin/printf "/usr/sbin/tc qdisc del dev \$WAN root 2>/dev/null\n" >> $QOS_SCRIPT
- /usr/bin/printf "/usr/sbin/tc qdisc del dev \$WAN ingress 2>/dev/null\n" >> $QOS_SCRIPT
- /usr/bin/printf "/usr/sbin/tc qdisc del dev br0 root 2>/dev/null\n" >> $QOS_SCRIPT
- /usr/bin/printf "/usr/sbin/tc qdisc del dev br0 ingress 2>/dev/null\n" >> $QOS_SCRIPT
- /usr/bin/printf ";;\n" >> $QOS_SCRIPT
- /usr/bin/printf "*)\n" >> $QOS_SCRIPT
- /usr/bin/printf "/usr/sbin/tc -s -d class ls dev \$WAN\n" >> $QOS_SCRIPT
- /usr/bin/printf "/usr/sbin/tc -s -d class ls dev br0\n" >> $QOS_SCRIPT
- /usr/bin/printf "esac\n" >> $QOS_SCRIPT
- /bin/chmod 0700 $QOS_SCRIPT
- $QOS_SCRIPT start
- }
- add_iQosRules()
- {
- local status=0
- if [ "$pcWANIF" == "" ] || [ $qos_enable != 1 ] || [ $qos_type == 1 ]; then
- return -1
- fi
- if [ $qos_enable == 1 ] && [ $qos_type == 0 ]; then
- /bin/echo "TODO: add_qos_rules"; status=-1
- elif [ $qos_enable == 1 ] && [ $qos_type == 2 ]; then
- add_bandwidth_limiter_rules; status=$?
- fi
- if [ $status -lt 0 ]; then
- /bin/echo "add_iQosRules() returned $status"
- fi
- return $status
- }
- start_iQos()
- {
- local status=0
- if [ "$pcWANIF" == "" ] || [ $qos_enable != 1 ] || [ $qos_type == 1 ]; then
- return -1
- fi
- if [ $qos_enable == 1 ] && [ $qos_type == 0 ]; then
- /bin/echo "TODO: start_tqos"; status=-1
- elif [ $qos_enable == 1 ] && [ $qos_type == 2 ]; then
- start_bandwidth_limiter; status=$?
- fi
- if [ $status -lt 0 ]; then
- /bin/echo "start_iQos() returned $status"
- fi
- return $status
- }
- stop_iQos()
- {
- $QOS_SCRIPT stop
- }
- ##################################################################################
- if [ "$action" == "start" ]; then
- add_iQosRules
- start_iQos
- elif [ "$action" == "stop" ]; then
- stop_iQos
- fi
- ##################################################################################
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement