mirror of
https://dev.iopsys.eu/feed/iopsys.git
synced 2025-12-10 07:44:50 +01:00
* applicable only for linux target * fix reload to setup qos properly and not overwrite queue on reload * fixed l2 classification broken in reload
693 lines
17 KiB
Bash
Executable file
693 lines
17 KiB
Bash
Executable file
#!/bin/sh
|
|
. /lib/functions.sh
|
|
#set -x
|
|
|
|
# include common code
|
|
. /lib/qos/ip_rule.sh
|
|
. /lib/qos/iptables.sh
|
|
. /lib/qos/ebtables.sh
|
|
. /lib/qos/classify.sh
|
|
|
|
MAJOR=""
|
|
|
|
POLICER_COUNT=0
|
|
Q_COUNT=0
|
|
SP_Q_PRIO=7
|
|
SOQ_wgt=0
|
|
|
|
get_max_burst_size_per_queue() {
|
|
# maximum burst size for tc class
|
|
echo "4289999999"
|
|
}
|
|
|
|
handle_q_weight() {
|
|
local qid="$1" #queue section ID
|
|
config_get ifname "$qid" "ifname"
|
|
# If ifname is empty that is good enough to break
|
|
if [ -z "$ifname" ];then
|
|
return
|
|
fi
|
|
|
|
config_get sc_alg "$qid" "scheduling"
|
|
config_get weight "$qid" "weight"
|
|
|
|
if [ "$ifname" == "$2" ] && [ "$sc_alg" == "WRR" ]; then
|
|
SOQ_wgt=`expr $SOQ_wgt + $weight`
|
|
fi
|
|
}
|
|
|
|
# Function to handle a queue order and
|
|
# update total number of queues
|
|
handle_q_order() {
|
|
local qid="$1" #queue section ID
|
|
|
|
config_get is_enable "$qid" "enable" 1
|
|
|
|
# No need to configure disabled queues
|
|
if [ $is_enable == '0' ]; then
|
|
return
|
|
fi
|
|
|
|
config_get ifname "$qid" "ifname"
|
|
# If ifname is empty that is good enough to break
|
|
if [ -z "$ifname" ];then
|
|
return
|
|
fi
|
|
|
|
# Create precedence file containing queue order per
|
|
# interface.
|
|
local precedence_file="/tmp/qos/$ifname/q_order"
|
|
local q_no=$(cat /tmp/qos/$ifname/q_idx)
|
|
|
|
config_get precedence "$qid" "precedence"
|
|
value=${precedence}_q${q_no}
|
|
echo $value >> $precedence_file
|
|
|
|
# Update the number of queues per interface.
|
|
q_no=$((q_no + 1))
|
|
echo $q_no > /tmp/qos/$ifname/q_idx
|
|
}
|
|
|
|
# Sort queue, lower value in uci means higher precedence, so this
|
|
# function sorts the precedence in decending order
|
|
sort_q_by_precedence() {
|
|
ifname="$1"
|
|
|
|
local order_file="/tmp/qos/$ifname/q_order"
|
|
local tmp_order_file="/tmp/qos/$ifname/q_order.tmp"
|
|
|
|
sort -n -k1 $order_file > $tmp_order_file
|
|
cp $tmp_order_file $order_file
|
|
rm -f $tmp_order_file
|
|
}
|
|
|
|
sort_by_precedence() {
|
|
for interf in $(jsonfilter -i /etc/board.json -e @.network.lan.ports[*] -e @.network.lan.device -e @.network.wan.device | xargs); do
|
|
sort_q_by_precedence $interf
|
|
done
|
|
}
|
|
|
|
# function to handle a queue section
|
|
handle_queue() {
|
|
local qid="$1" #queue section ID
|
|
local port="$2"
|
|
local port_bw="$3"
|
|
local root="$4"
|
|
local port_bs="$5"
|
|
local par_class="$6"
|
|
local priority=7
|
|
local bs=0
|
|
|
|
config_get is_enable "$qid" "enable"
|
|
|
|
# no need to configure disabled queues
|
|
if [ "$is_enable" == "0" ]; then
|
|
return
|
|
fi
|
|
|
|
config_get ifname "$qid" "ifname"
|
|
# if ifname is empty that is good enough to break
|
|
if [ -z "$ifname" ];then
|
|
return
|
|
fi
|
|
|
|
# This is to get the qid per interface.
|
|
if [ "$port" != "$ifname" ]; then
|
|
return
|
|
fi
|
|
|
|
local precedence_file="/tmp/qos/$ifname/q_order"
|
|
|
|
local temp_order=0
|
|
while read -r line; do
|
|
line_qid=${line: -1}
|
|
if [ "$line_qid" == "$Q_COUNT" ]; then
|
|
break
|
|
fi
|
|
temp_order=$((temp_order + 1))
|
|
done < "$precedence_file"
|
|
|
|
# precedence_file so the order is calculated accordingly.
|
|
local order=`expr $SP_Q_PRIO - $temp_order`
|
|
|
|
config_get sc_alg "$qid" "scheduling"
|
|
config_get wgt "$qid" "weight" 1
|
|
config_get rate "$qid" "rate"
|
|
config_get bs "$qid" "burst_size" 1500
|
|
config_get qsize "$qid" "queue_size" 1024
|
|
|
|
[ "$rate" == "0" ] && rate="$port_bw"
|
|
[ "$bs" == "0" ] && bs=1500
|
|
|
|
bs=$(( bs * 8 ))
|
|
rate_bs=$(( rate * 25 ))
|
|
if [ $rate_bs -gt $bs ]; then
|
|
bs=$rate_bs
|
|
fi
|
|
# burst size in tc class is given in bytes
|
|
bs=$(( bs * 1000 ))
|
|
local max_bs=$(get_max_burst_size_per_queue )
|
|
if [ $bs -gt $max_bs ]; then
|
|
bs=$max_bs
|
|
fi
|
|
|
|
local salg=1
|
|
|
|
case "$sc_alg" in
|
|
"SP") salg=1
|
|
;;
|
|
"WRR") salg=2
|
|
;;
|
|
"WDRR") salg=3
|
|
;;
|
|
"WFQ") salg=4
|
|
;;
|
|
esac
|
|
|
|
[ -f /etc/board.json ] || return 0
|
|
if [ $salg -ne 2 ]; then
|
|
priority=`expr 7 - $order`
|
|
fi
|
|
|
|
local ceil_rate=$port_bw
|
|
if [ "$rate" -lt "$port_bw" ]; then
|
|
ceil_rate=$rate
|
|
fi
|
|
|
|
local cls_priority=`expr $order + 1`
|
|
cls_priority=${cls_priority}0
|
|
|
|
if [ $salg -eq 2 ]; then
|
|
# maximum quantum value 60000
|
|
# quantum value calculate based on the configured weight value for the queue
|
|
quantum=`expr $wgt \* 60000 / $SOQ_wgt`
|
|
tc class add dev $port parent ${root}:${par_class} classid ${root}:${cls_priority} htb rate ${rate}kbit prio ${priority} ceil ${ceil_rate}kbit quantum ${quantum} burst $bs cburst $port_bs
|
|
tc qdisc add dev $port parent ${root}:${cls_priority} handle ${cls_priority}: sfq perturb 10
|
|
else
|
|
tc class add dev $port parent ${root}:${par_class} classid ${root}:${cls_priority} htb rate ${rate}kbit prio ${priority} ceil ${ceil_rate}kbit burst $bs cburst $port_bs
|
|
fi
|
|
tc filter add dev $port parent ${root}:0 prio $order u32 match mark $order 0xf flowid ${root}:${cls_priority}
|
|
|
|
Q_COUNT=$((Q_COUNT + 1))
|
|
}
|
|
|
|
iptables_set_traffic_class() {
|
|
IP_RULE="$IP_RULE -j MARK --set-mark $1"
|
|
}
|
|
|
|
# marking value be decimal for linux target as it uses set-mark whereas other
|
|
# targets uses set-xmark, hence this function can't make it common
|
|
ip_rule_get_converted_tos() {
|
|
echo $1
|
|
}
|
|
|
|
ebt_match_ipv6_dscp() {
|
|
#when ethertype is not configured by user then both proto rules of ipv4
|
|
#and ipv6 to be installed so update BR6_RULE string as well otherwise
|
|
#update BR_RULE only for installation of ipv6 proto rule only.
|
|
if [ ! -z "$BR6_RULE" ]; then
|
|
BR6_RULE="$BR6_RULE --ip6-tclass $1"
|
|
else
|
|
BR_RULE="$BR_RULE --ip6-tclass $1"
|
|
fi
|
|
}
|
|
|
|
broute_filter_on_dscp() {
|
|
BR_RULE="$BR_RULE --ip-tos $1"
|
|
}
|
|
|
|
broute_ipv4_rule_options()
|
|
{
|
|
local cid=$1
|
|
config_get protocol "$cid" "proto"
|
|
config_get dscp_filter "$cid" "dscp_filter"
|
|
|
|
set_ip_addr $cid ebt_match_src_ip ebt_match_dst_ip
|
|
|
|
if [ ! -z $dscp_filter ]; then
|
|
local tos_val
|
|
local tos_hex
|
|
|
|
tos_val=$((dscp_filter<<2))
|
|
tos_hex=$(printf "%x" $tos_val)
|
|
broute_filter_on_dscp "$tos_hex"
|
|
fi
|
|
|
|
if [ ! -z $protocol ]; then
|
|
local proto_num=$(protocol_string_to_num "$protocol")
|
|
ebt_match_ip_protocol "$proto_num"
|
|
|
|
#port installation for protol tcp/udp/sctp
|
|
if [ $proto_num = "6" ] || [ $proto_num = "17" ] || [ $proto_num = "132" ] ; then
|
|
set_ports "$cid" ebt_match_ip_src_port ebt_match_ip_dst_port
|
|
fi
|
|
fi
|
|
}
|
|
|
|
broute_ipv6_rule_options()
|
|
{
|
|
local cid=$1
|
|
|
|
config_get protocol "$cid" "proto"
|
|
config_get dscp_filter "$cid" "dscp_filter"
|
|
|
|
set_ip_addr $cid ebt_match_ipv6_src_ip ebt_match_ipv6_dst_ip
|
|
|
|
if [ ! -z $dscp_filter ]; then
|
|
local tos_val
|
|
local tos_hex
|
|
|
|
tos_val=$(($dscp_filter<<2))
|
|
tos_hex=$(printf "%x" $tos_val)
|
|
ebt_match_ipv6_dscp "$tos_hex"
|
|
fi
|
|
|
|
if [ ! -z $protocol ]; then
|
|
local proto_num=$(protocol_string_to_num "$protocol")
|
|
ebt_match_ipv6_protocol "$proto_num"
|
|
|
|
#port installation for protol tcp/udp/sctp
|
|
if [ $proto_num = "6" ] || [ $proto_num = "17" ] || [ $proto_num = "132" ]; then
|
|
set_ports "$cid" ebt_match_ipv6_src_port ebt_match_ipv6_dst_port
|
|
fi
|
|
fi
|
|
}
|
|
|
|
broute_rule_set_traffic_class() {
|
|
#when ethertype is not configured by user then both proto rules of ipv4
|
|
#and ipv6 to be installed so update BR6_RULE string as well otherwise
|
|
#update BR_RULE only for installation of ipv6 proto rule only.
|
|
BR_RULE="$BR_RULE -j mark --mark-or 0x$1 --mark-target ACCEPT"
|
|
if [ ! -z "$BR6_RULE" ]; then
|
|
BR6_RULE="$BR6_RULE -j mark --mark-or 0x$1 --mark-target ACCEPT"
|
|
fi
|
|
}
|
|
|
|
#function to handle a policer section
|
|
handle_policer() {
|
|
local p_sec="$1" # policer section ID
|
|
local dir=1 # default direction, upstream
|
|
|
|
config_get is_enable "$p_sec" "enable"
|
|
|
|
#no need to configure disabled policer
|
|
if [ $is_enable == '0' ]; then
|
|
return
|
|
fi
|
|
|
|
POLICER_COUNT=$((POLICER_COUNT + 1))
|
|
}
|
|
|
|
handle_policer_rules() {
|
|
local c_sec=$1
|
|
local policer_name
|
|
local ifname
|
|
local pname
|
|
local pindex=-1
|
|
local ingress_rate=0
|
|
local in_burst_size=0
|
|
|
|
config_get policer_name "$c_sec" "policer"
|
|
if [ -z "$policer_name" ];then
|
|
# no need to apply policer if policer not present in this
|
|
# classification rule
|
|
return
|
|
fi
|
|
|
|
config_get ifname "$c_sec" "ifname"
|
|
if [ -z "$ifname" ]; then
|
|
# cannot associate policer as interface is not mentioned
|
|
return
|
|
fi
|
|
|
|
local i=0
|
|
local max_policer_inst=$(cat /tmp/qos/max_policer_inst)
|
|
while :
|
|
do
|
|
if [ $i -eq $max_policer_inst ]; then
|
|
break
|
|
fi
|
|
|
|
pname="$(uci -q get qos.@policer[$i].name)"
|
|
if [ "$policer_name" == "$pname" ]; then
|
|
pindex=$i
|
|
ingress_rate=$(uci -q get qos.@policer[$i].committed_rate)
|
|
in_burst_rate=$(uci -q get qos.@policer[$i].committed_burst_size)
|
|
break
|
|
fi
|
|
i=$((i + 1))
|
|
done
|
|
|
|
if [ $pindex -lt 0 ]; then
|
|
# policer not found, no need to proceed further
|
|
return
|
|
fi
|
|
|
|
config_ingress_rate_limit $ifname $ingress_rate $in_burst_size $pindex
|
|
|
|
}
|
|
|
|
config_ingress_rate_limit() {
|
|
local ifname="$1"
|
|
local ingress_rate=$2
|
|
local in_burst_size=$3
|
|
local pindex="$4"
|
|
local wanport="$(jsonfilter -i /etc/board.json -e @.network.wan.device)"
|
|
|
|
# Unit in uci file is in bps while that accepted by ethswctl is kbits
|
|
if [ $ingress_rate -lt 1000 ]; then
|
|
return
|
|
fi
|
|
|
|
ingress_rate=$((ingress_rate / 1000))
|
|
|
|
local bs=0
|
|
local avg_bs=$(( ingress_rate * 25 ))
|
|
config_get b_size "$sid" "burst_size"
|
|
if [ "$in_burst_size" > "0" ]; then
|
|
bs=`expr $in_burst_size / 1000`
|
|
fi
|
|
bs=$(( bs * 8 ))
|
|
if [ $avg_bs -gt $bs ]; then
|
|
bs="$avg_bs"
|
|
fi
|
|
|
|
tc qdisc add dev $ifname ingress
|
|
|
|
tc filter add dev $ifname parent ffff: protocol ip prio $pindex u32 match ip src 0.0.0.0/0 police rate ${ingress_rate}kbit burst $bs drop flowid :$pindex
|
|
|
|
}
|
|
|
|
pre_configure_queue() {
|
|
# Delete queues
|
|
for intf in $(jsonfilter -i /etc/board.json -e @.network.lan.ports[*] -e @.network.lan.device -e @.network.wan.device | xargs); do
|
|
rm -rf /tmp/qos/$intf
|
|
|
|
mkdir -p /tmp/qos/$intf
|
|
touch /tmp/qos/$intf/q_order
|
|
touch /tmp/qos/$intf/q_idx
|
|
echo 0 > /tmp/qos/$intf/q_idx
|
|
|
|
tc qdisc del dev $intf root
|
|
tc qdisc del dev $intf ingress 2> /dev/null
|
|
done
|
|
}
|
|
|
|
get_link_rate() {
|
|
local ifname="$1"
|
|
local phycap="$(ethtool $ifname | grep -A 10 "Supported link modes" | grep 00 | tail -n 1 | awk '{print$NF}')"
|
|
local speed=1000
|
|
|
|
# Get the max capability of this port
|
|
case "$phycap" in
|
|
10000*) speed=10000 ;;
|
|
5000*) speed=5000 ;;
|
|
2500*) speed=2500 ;;
|
|
1000*) speed=1000 ;;
|
|
100*) speed=100 ;;
|
|
10*) speed=10 ;;
|
|
*) speed=1000 ;;
|
|
esac
|
|
|
|
echo "$speed"
|
|
}
|
|
|
|
configure_queue() {
|
|
qdisc_idx=0
|
|
local bs=1500
|
|
local rate=0
|
|
# Load UCI file
|
|
config_load qos
|
|
config_foreach handle_q_order queue
|
|
sort_by_precedence
|
|
|
|
get_intf_shaper_config() {
|
|
local b_size
|
|
sid="$1" #shaper section ID
|
|
|
|
config_get is_enable "$sid" "enable"
|
|
# no need to configure disabled queues
|
|
if [ "$is_enable" == "0" ]; then
|
|
return
|
|
fi
|
|
|
|
|
|
config_get ifname "$sid" "ifname"
|
|
# if ifname is empty that is good enough to break
|
|
if [ -z "$ifname" ] || ! [ "$ifname" == "$2" ];then
|
|
return
|
|
fi
|
|
|
|
config_get rate "$sid" "rate"
|
|
# Convert the rate from bps to kbps.
|
|
if [ $rate -lt 1000 ];then
|
|
return
|
|
fi
|
|
|
|
rate=$(( rate / 1000 ))
|
|
|
|
#burst size is either bitrate*0.00025 or max_packat_size in bit whichever is greater
|
|
local avg_bs=$(( rate * 25 ))
|
|
config_get b_size "$sid" "burst_size"
|
|
if [ "$b_size" > "0" ]; then
|
|
bs="$b_size"
|
|
fi
|
|
bs=$(( bs * 8 ))
|
|
if [ $avg_bs -gt $bs ]; then
|
|
bs="$avg_bs"
|
|
fi
|
|
bs=$(( bs / 1000 ))
|
|
}
|
|
local wanport="$(jsonfilter -i /etc/board.json -e @.network.wan.device)"
|
|
for interf in $(jsonfilter -i /etc/board.json -e @.network.lan.ports[*] -e @.network.lan.device -e @.network.wan.device | xargs); do
|
|
Q_COUNT=0
|
|
rate=0
|
|
# sp queue have max priority value = no. of queue configured on the port
|
|
# hence read and update SP_Q_PRIO here
|
|
local q_no=$(cat /tmp/qos/$interf/q_idx)
|
|
SP_Q_PRIO=`expr $q_no - 1`
|
|
qdisc_idx=`expr $qdisc_idx + 1`
|
|
# link_rate is in mbps and rate is in kbp
|
|
link_rate=$(get_link_rate "$interf")
|
|
# Read the shaper configuration for interface
|
|
config_foreach get_intf_shaper_config shaper $interf
|
|
if [ "$rate" == "0" ]; then
|
|
rate=$(( link_rate * 1000 ))
|
|
fi
|
|
|
|
p_qdisc_idx=`expr $qdisc_idx + 11`
|
|
# port shaper needs to add at root tbf qdisc, child class gets token based on rate & burst_size
|
|
tc qdisc add dev $interf root handle ${p_qdisc_idx}: tbf rate ${rate}kbit burst ${bs}k limit 1M
|
|
tc qdisc add dev $interf parent ${p_qdisc_idx}: handle ${qdisc_idx}: htb default 10
|
|
|
|
local par_class=1
|
|
tc class add dev $interf parent ${qdisc_idx}: classid ${qdisc_idx}:$par_class htb rate ${rate}kbit prio 8 ceil ${rate}kbit
|
|
tc filter add dev $interf parent ${qdisc_idx}:0 matchall flowid ${qdisc_idx}:$par_class
|
|
|
|
# if qdisc_idx is the index corresponds to WAN port, then
|
|
# it would be the MAJOR portion of the destination class ID.
|
|
# under the same qdisc. We are programming for WAN port only.
|
|
if [ "$interf" == "$wanport" ]; then
|
|
MAJOR="$qdisc_idx"
|
|
fi
|
|
|
|
#calculate sum of queue weight, to derive the quantum value
|
|
SOQ_wgt=0
|
|
config_foreach handle_q_weight queue $interf
|
|
|
|
config_foreach handle_queue queue $interf $rate $qdisc_idx $bs $par_class
|
|
done
|
|
}
|
|
|
|
configure_policer() {
|
|
|
|
# Delete policer
|
|
local i=0
|
|
local max_p_inst=0
|
|
if [ -f "/tmp/qos/max_policer_inst" ]; then
|
|
max_p_inst=$(cat /tmp/qos/max_policer_inst)
|
|
fi
|
|
|
|
# reset the policer counter
|
|
echo 0 > /tmp/qos/max_policer_inst
|
|
# Load UCI file
|
|
config_load qos
|
|
config_foreach handle_policer policer
|
|
echo $POLICER_COUNT > /tmp/qos/max_policer_inst
|
|
}
|
|
|
|
configure_qos() {
|
|
pre_configure_queue
|
|
configure_queue
|
|
configure_policer
|
|
configure_classify
|
|
if [ -f "/tmp/qos/classify.ebtables" ]; then
|
|
sh /tmp/qos/classify.ebtables
|
|
fi
|
|
}
|
|
|
|
reload_qos() {
|
|
local service_name="$1"
|
|
|
|
if [ -z "$service_name" ]; then
|
|
configure_qos
|
|
elif [ "$service_name" == "queue" ]; then
|
|
pre_configure_queue
|
|
configure_queue
|
|
elif [ "$service_name" == "classify" ]; then
|
|
configure_classify
|
|
if [ -f "/tmp/qos/classify.ebtables" ]; then
|
|
sh /tmp/qos/classify.ebtables
|
|
fi
|
|
elif [ "$service_name" == "policer" ]; then
|
|
configure_policer
|
|
fi
|
|
}
|
|
|
|
get_cfg_added_deleted()
|
|
{
|
|
# return true if there is difference in number of queue configuration
|
|
# in /etc/config/qos and /tmp/qos/qos, false is returned if both file
|
|
# has same count of queue configuration.
|
|
local queue=0
|
|
local classify=0
|
|
local shaper=0
|
|
local policer=0
|
|
local old_cfg="false"
|
|
|
|
config_cb() {
|
|
# invoked on the just previous config_load, get the count of
|
|
# queue configuration in /etc/config/qos and /tmp/qos/qos.
|
|
cfg_type="$1"
|
|
cfg_name="$2"
|
|
if [ -z $cfg_name ] || [ -z $cfg_type ]; then
|
|
return
|
|
fi
|
|
|
|
if [ "$old_cfg" == "false" ]; then
|
|
eval $cfg_type=$(($cfg_type + 1))
|
|
else
|
|
eval $cfg_type=$(($cfg_type - 1))
|
|
fi
|
|
option_cb() {
|
|
local option="$1"
|
|
local value="$2"
|
|
if [ -z "$option" ] || [ -z "$value" ]; then
|
|
return
|
|
fi
|
|
if [ "$old_cfg" == "false" ]; then
|
|
eval $cfg_type=$(($cfg_type + 1))
|
|
else
|
|
eval $cfg_type=$(($cfg_type - 1))
|
|
fi
|
|
}
|
|
}
|
|
# config_load will trigger call for config_cb that is getting count
|
|
# of qos configuration, respective config counts will come.
|
|
config_load qos
|
|
# config_load will trigger call for config_cb that is decreasing count
|
|
# of qos configuration.
|
|
old_cfg="true"
|
|
UCI_CONFIG_DIR="/tmp/qos"
|
|
config_load qos
|
|
UCI_CONFIG_DIR="/etc/config"
|
|
reset_cb
|
|
|
|
if [ $classify -ne 0 ]; then
|
|
modified_config="classify"
|
|
fi
|
|
if [ $shaper -ne 0 ]; then
|
|
modified_config="$modified_config shaper"
|
|
fi
|
|
if [ $policer -ne 0 ]; then
|
|
modified_config="$modified_config policer"
|
|
fi
|
|
if [ $queue -eq 0 ]; then
|
|
echo "$modified_config"
|
|
return
|
|
else
|
|
echo "queue"
|
|
return
|
|
fi
|
|
}
|
|
|
|
# reload_qos_service is invoked on qos service reload.
|
|
reload_qos_service() {
|
|
q_cfg_restart="false"
|
|
policer="false"
|
|
classify="false"
|
|
shaper="false"
|
|
|
|
setup_qos
|
|
|
|
if ! [[ -f "/etc/config/qos" && -f "/tmp/qos/qos" ]]; then
|
|
configure_qos
|
|
cp /etc/config/qos /tmp/qos/qos
|
|
fi
|
|
|
|
config_cb() {
|
|
# this is invoked when config_load is called.
|
|
cfg_type="$1"
|
|
cfg_name="$2"
|
|
if [ -z $cfg_name ] || [ -z $cfg_type ]; then
|
|
return
|
|
fi
|
|
option_cb() {
|
|
# checking for if any parameters value is modified in queue cfg
|
|
# comparsion is done between /etc/config/qos and /tmp/qos/qos
|
|
local option="$1"
|
|
local value="$2"
|
|
local old_value=""
|
|
if [ -z "$option" ] || [ -z "$value" ]; then
|
|
return
|
|
fi
|
|
old_value=$(uci -q -c "/tmp/qos" get qos.$cfg_name.$option)
|
|
if ! [ "$old_value" == "$value" ]; then
|
|
if [ "$cfg_type" == "queue" ]; then
|
|
q_cfg_restart="true"
|
|
else
|
|
eval $cfg_type="true"
|
|
fi
|
|
fi
|
|
}
|
|
}
|
|
# if there is new addition/deletion of queue configuration
|
|
# then return is queue to trigger restart of qos.
|
|
# Otehrwise shaper policer classify
|
|
# respective operation config is invoked that does not change queue statistics
|
|
cfg_added_deleted=$(get_cfg_added_deleted)
|
|
if [ "$cfg_added_deleted" == "queue" ]; then
|
|
configure_qos
|
|
else
|
|
q_cfg_restart="false"
|
|
# config_load will trigger call for config_cb that is checking
|
|
# for modification in config value of queue config.
|
|
# if change of value of queue config is there then q_cfg_restart
|
|
# is set as true, else other qos config flag is set as true.
|
|
config_load qos
|
|
reset_cb
|
|
if [ "$q_cfg_restart" == "true" ]; then
|
|
configure_qos
|
|
else
|
|
for config in $cfg_added_deleted
|
|
do
|
|
eval $config="true"
|
|
done
|
|
if [ "$shaper" == "true" ]; then
|
|
# for tc, shaper is implemented as part of q setup
|
|
# hence, if shaper is modified, reload queue
|
|
reload_qos "queue"
|
|
fi
|
|
if [ "$policer" == "true" ]; then
|
|
reload_qos "policer"
|
|
# change in policer config may need reconfiguration
|
|
# of classifier
|
|
reload_qos "classify"
|
|
fi
|
|
if [ "$classify" == "true" ]; then
|
|
reload_qos "classify"
|
|
fi
|
|
fi
|
|
fi
|
|
cp /etc/config/qos /tmp/qos/qos
|
|
}
|