mirror of
https://github.com/Ysurac/openmptcprouter-feeds.git
synced 2025-02-15 03:51:51 +00:00
Update SQM autorate
This commit is contained in:
parent
a3fc59f80e
commit
063a468465
11 changed files with 2526 additions and 695 deletions
|
@ -260,6 +260,10 @@ return view.extend({
|
||||||
o.default = false;
|
o.default = false;
|
||||||
o.depends("autorate","1");
|
o.depends("autorate","1");
|
||||||
|
|
||||||
|
o = s.taboption("tab_autorate", form.Flag, "sss_compensation", _("Starlink support"));
|
||||||
|
o.default = false;
|
||||||
|
o.depends("autorate","1");
|
||||||
|
|
||||||
o = s.taboption("tab_autorate", form.Value, "reflector_ping_interval_s", _("Reflector ping interval in seconds:"));
|
o = s.taboption("tab_autorate", form.Value, "reflector_ping_interval_s", _("Reflector ping interval in seconds:"));
|
||||||
o.default = "0.2";
|
o.default = "0.2";
|
||||||
o.depends("autorate","1");
|
o.depends("autorate","1");
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
. /usr/lib/unbound/iptools.sh
|
. /usr/lib/unbound/iptools.sh
|
||||||
. /lib/functions/network.sh
|
. /lib/functions/network.sh
|
||||||
|
|
||||||
_launch_autorate() {
|
_config_autorate() {
|
||||||
logger -t "SQM-autorate" "Launch on $1"
|
logger -t "SQM-autorate" "Set config for $1"
|
||||||
config_get enabled "$1" enabled
|
config_get enabled "$1" enabled
|
||||||
[ "${enabled}" != "1" ] && return
|
[ "${enabled}" != "1" ] && return
|
||||||
config_get autorate "$1" autorate
|
config_get autorate "$1" autorate
|
||||||
|
@ -29,20 +29,36 @@ _launch_autorate() {
|
||||||
config_get upload "$1" upload
|
config_get upload "$1" upload
|
||||||
config_get max_upload "$1" max_upload
|
config_get max_upload "$1" max_upload
|
||||||
[ "${min_upload}" == "0" ] || [ "${max_upload}" == "0" ] || [ "${upload}" == "0" ] && return
|
[ "${min_upload}" == "0" ] || [ "${max_upload}" == "0" ] || [ "${upload}" == "0" ] && return
|
||||||
|
config_get interface "$1" interface
|
||||||
|
cp /usr/share/sqm-autorate/cake-autorate_template.sh /usr/share/sqm-autorate/cake-autorate_config.${interface}.sh
|
||||||
|
}
|
||||||
|
|
||||||
|
_launch_autorate() {
|
||||||
|
logger -t "SQM-autorate" "Launch..."
|
||||||
procd_open_instance
|
procd_open_instance
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
procd_set_param command /usr/share/sqm-autorate/CAKE-autorate.sh "$1"
|
procd_set_param command /usr/share/sqm-autorate/cake-autorate_launcher.sh
|
||||||
# procd_append_param env "OMR_TRACKER_SERVER_HTTP_TEST=$server_http_test"
|
|
||||||
procd_set_param limits nofile="51200 51200"
|
procd_set_param limits nofile="51200 51200"
|
||||||
procd_set_param respawn 0 10 0
|
procd_set_param respawn 0 10 0
|
||||||
procd_set_param stderr 1
|
procd_set_param stderr 1
|
||||||
procd_close_instance
|
procd_close_instance
|
||||||
sleep 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start_service() {
|
start_service() {
|
||||||
config_load sqm
|
config_load sqm
|
||||||
config_foreach _launch_autorate queue
|
config_foreach _config_autorate queue
|
||||||
|
_launch_autorate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stop_service() {
|
||||||
|
rm -f /usr/share/sqm-autorate/cake-autorate_config.*.sh
|
||||||
|
}
|
||||||
|
|
||||||
|
reload_service() {
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
}
|
||||||
|
|
||||||
|
service_triggers() {
|
||||||
|
procd_add_reload_trigger sqm
|
||||||
|
}
|
1
luci-app-sqm-autorate/root/root/cake-autorate
Symbolic link
1
luci-app-sqm-autorate/root/root/cake-autorate
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../usr/share/sqm-autorate
|
|
@ -1,658 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# CAKE-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and OWD/RTT
|
|
||||||
# requires packages: bash; and iputils-ping
|
|
||||||
|
|
||||||
# Author: @Lynx (OpenWrt forum)
|
|
||||||
# Inspiration taken from: @moeller0 (OpenWrt forum)
|
|
||||||
# Modified by Ycarus (Yannick Chabanois) for OpenMPTCProuter:
|
|
||||||
# * Add multiples interfaces support
|
|
||||||
|
|
||||||
# Possible performance improvement
|
|
||||||
export LC_ALL=C
|
|
||||||
export TZ=UTC
|
|
||||||
|
|
||||||
trap cleanup_and_killall INT TERM EXIT
|
|
||||||
|
|
||||||
cleanup_and_killall()
|
|
||||||
{
|
|
||||||
echo "Killing all background processes and cleaning up /tmp files."
|
|
||||||
trap - INT TERM EXIT
|
|
||||||
kill $monitor_achieved_rates_pid 2> /dev/null
|
|
||||||
# Initiate termination of ping processes and wait until complete
|
|
||||||
kill $maintain_pingers_pid 2> /dev/null
|
|
||||||
wait $maintain_pingers_pid
|
|
||||||
[[ -d /tmp/CAKE-autorate-${dl_if} ]] && rm -r /tmp/CAKE-autorate-${dl_if}
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
install_dir="/usr/share/sqm-autorate/"
|
|
||||||
|
|
||||||
. $install_dir"config.sh" "$1"
|
|
||||||
|
|
||||||
# test if stdout is a tty (terminal)
|
|
||||||
[[ ! -t 1 ]] && exec &> /tmp/cake-autorate-${dl_if}.log
|
|
||||||
|
|
||||||
get_next_shaper_rate()
|
|
||||||
{
|
|
||||||
local min_shaper_rate_kbps=$1
|
|
||||||
local base_shaper_rate_kbps=$2
|
|
||||||
local max_shaper_rate_kbps=$3
|
|
||||||
local achieved_rate_kbps=$4
|
|
||||||
local load_condition=$5
|
|
||||||
local t_next_rate_us=$6
|
|
||||||
local -n t_last_bufferbloat_us=$7
|
|
||||||
local -n t_last_decay_us=$8
|
|
||||||
local -n shaper_rate_kbps=$9
|
|
||||||
|
|
||||||
case $load_condition in
|
|
||||||
|
|
||||||
# upload Starlink satelite switching compensation, so drop down to minimum rate for upload through switching period
|
|
||||||
ul*sss)
|
|
||||||
shaper_rate_kbps=$min_shaper_rate_kbps
|
|
||||||
;;
|
|
||||||
# download Starlink satelite switching compensation, so drop down to base rate for download through switching period
|
|
||||||
dl*sss)
|
|
||||||
shaper_rate_kbps=$base_shaper_rate_kbps
|
|
||||||
;;
|
|
||||||
# bufferbloat detected, so decrease the rate providing not inside bufferbloat refractory period
|
|
||||||
*bb*)
|
|
||||||
if (( $t_next_rate_us > ($t_last_bufferbloat_us+$bufferbloat_refractory_period_us) )); then
|
|
||||||
adjusted_achieved_rate_kbps=$(( ($achieved_rate_kbps*$achieved_rate_adjust_down_bufferbloat)/1000 ))
|
|
||||||
adjusted_shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_down_bufferbloat)/1000 ))
|
|
||||||
shaper_rate_kbps=$(( $adjusted_achieved_rate_kbps < $adjusted_shaper_rate_kbps ? $adjusted_achieved_rate_kbps : $adjusted_shaper_rate_kbps ))
|
|
||||||
t_last_bufferbloat_us=${EPOCHREALTIME/./}
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
# high load, so increase rate providing not inside bufferbloat refractory period
|
|
||||||
*high*)
|
|
||||||
if (( $t_next_rate_us > ($t_last_bufferbloat_us+$bufferbloat_refractory_period_us) )); then
|
|
||||||
shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_up_load_high)/1000 ))
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
# medium load, so just maintain rate as is, i.e. do nothing
|
|
||||||
*med*)
|
|
||||||
:
|
|
||||||
;;
|
|
||||||
# low or idle load, so determine whether to decay down towards base rate, decay up towards base rate, or set as base rate
|
|
||||||
*low*|*idle*)
|
|
||||||
if (($t_next_rate_us > ($t_last_decay_us+$decay_refractory_period_us) )); then
|
|
||||||
|
|
||||||
if (($shaper_rate_kbps > $base_shaper_rate_kbps)); then
|
|
||||||
decayed_shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_down_load_low)/1000 ))
|
|
||||||
shaper_rate_kbps=$(( $decayed_shaper_rate_kbps > $base_shaper_rate_kbps ? $decayed_shaper_rate_kbps : $base_shaper_rate_kbps))
|
|
||||||
elif (($shaper_rate_kbps < $base_shaper_rate_kbps)); then
|
|
||||||
decayed_shaper_rate_kbps=$(( ($shaper_rate_kbps*$shaper_rate_adjust_up_load_low)/1000 ))
|
|
||||||
shaper_rate_kbps=$(( $decayed_shaper_rate_kbps < $base_shaper_rate_kbps ? $decayed_shaper_rate_kbps : $base_shaper_rate_kbps))
|
|
||||||
fi
|
|
||||||
|
|
||||||
t_last_decay_us=${EPOCHREALTIME/./}
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
# make sure to only return rates between cur_min_rate and cur_max_rate
|
|
||||||
(($shaper_rate_kbps < $min_shaper_rate_kbps)) && shaper_rate_kbps=$min_shaper_rate_kbps;
|
|
||||||
(($shaper_rate_kbps > $max_shaper_rate_kbps)) && shaper_rate_kbps=$max_shaper_rate_kbps;
|
|
||||||
}
|
|
||||||
|
|
||||||
monitor_achieved_rates()
|
|
||||||
{
|
|
||||||
# track rx and tx bytes transfered and divide by time since last update
|
|
||||||
# to determine achieved dl and ul transfer rates
|
|
||||||
|
|
||||||
local rx_bytes_path=$1
|
|
||||||
local tx_bytes_path=$2
|
|
||||||
local monitor_achieved_rates_interval_us=$3 # (microseconds)
|
|
||||||
|
|
||||||
compensated_monitor_achieved_rates_interval_us=$monitor_achieved_rates_interval_us
|
|
||||||
|
|
||||||
[[ -f $rx_bytes_path ]] && { read -r prev_rx_bytes < $rx_bytes_path; } 2> /dev/null || prev_rx_bytes=0
|
|
||||||
[[ -f $tx_bytes_path ]] && { read -r prev_tx_bytes < $tx_bytes_path; } 2> /dev/null || prev_tx_bytes=0
|
|
||||||
|
|
||||||
while true
|
|
||||||
do
|
|
||||||
t_start_us=${EPOCHREALTIME/./}
|
|
||||||
|
|
||||||
# If rx/tx bytes file exists, read it in, otherwise set to prev_bytes
|
|
||||||
# This addresses interfaces going down and back up
|
|
||||||
[[ -f $rx_bytes_path ]] && { read -r rx_bytes < $rx_bytes_path; } 2> /dev/null || rx_bytes=$prev_rx_bytes
|
|
||||||
[[ -f $tx_bytes_path ]] && { read -r tx_bytes < $tx_bytes_path; } 2> /dev/null || tx_bytes=$prev_tx_bytes
|
|
||||||
|
|
||||||
dl_achieved_rate_kbps=$(( ((8000*($rx_bytes - $prev_rx_bytes)) / $compensated_monitor_achieved_rates_interval_us ) ))
|
|
||||||
ul_achieved_rate_kbps=$(( ((8000*($tx_bytes - $prev_tx_bytes)) / $compensated_monitor_achieved_rates_interval_us ) ))
|
|
||||||
|
|
||||||
(($dl_achieved_rate_kbps<0)) && dl_achieved_rate_kbps=0
|
|
||||||
(($ul_achieved_rate_kbps<0)) && ul_achieved_rate_kbps=0
|
|
||||||
|
|
||||||
printf '%s' "$dl_achieved_rate_kbps" > /tmp/CAKE-autorate-${dl_if}/dl_achieved_rate_kbps
|
|
||||||
printf '%s' "$ul_achieved_rate_kbps" > /tmp/CAKE-autorate-${dl_if}/ul_achieved_rate_kbps
|
|
||||||
|
|
||||||
prev_rx_bytes=$rx_bytes
|
|
||||||
prev_tx_bytes=$tx_bytes
|
|
||||||
|
|
||||||
# read in the max_wire_packet_rtt_us
|
|
||||||
concurrent_read_positive_integer max_wire_packet_rtt_us /tmp/CAKE-autorate-${dl_if}/max_wire_packet_rtt_us
|
|
||||||
|
|
||||||
compensated_monitor_achieved_rates_interval_us=$(( (($monitor_achieved_rates_interval_us>(10*$max_wire_packet_rtt_us) )) ? $monitor_achieved_rates_interval_us : $((10*$max_wire_packet_rtt_us)) ))
|
|
||||||
|
|
||||||
sleep_remaining_tick_time $t_start_us $compensated_monitor_achieved_rates_interval_us
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
get_loads()
|
|
||||||
{
|
|
||||||
# read in the dl/ul achived rates and determine the loads
|
|
||||||
|
|
||||||
concurrent_read_positive_integer dl_achieved_rate_kbps /tmp/CAKE-autorate-${dl_if}/dl_achieved_rate_kbps
|
|
||||||
concurrent_read_positive_integer ul_achieved_rate_kbps /tmp/CAKE-autorate-${dl_if}/ul_achieved_rate_kbps
|
|
||||||
|
|
||||||
dl_load_percent=$(((100*10#${dl_achieved_rate_kbps})/$dl_shaper_rate_kbps))
|
|
||||||
ul_load_percent=$(((100*10#${ul_achieved_rate_kbps})/$ul_shaper_rate_kbps))
|
|
||||||
}
|
|
||||||
|
|
||||||
classify_load()
|
|
||||||
{
|
|
||||||
# classify the load according to high/low/medium/idle and add _delayed if delayed
|
|
||||||
# thus ending up with high_delayed, low_delayed, etc.
|
|
||||||
local load_percent=$1
|
|
||||||
local achieved_rate_kbps=$2
|
|
||||||
local -n load_condition=$3
|
|
||||||
|
|
||||||
if (( $load_percent > $high_load_thr_percent )); then
|
|
||||||
load_condition="high"
|
|
||||||
elif (( $load_percent > $medium_load_thr_percent )); then
|
|
||||||
load_condition="med"
|
|
||||||
elif (( $achieved_rate_kbps > $connection_active_thr_kbps )); then
|
|
||||||
load_condition="low"
|
|
||||||
else
|
|
||||||
load_condition="idle"
|
|
||||||
fi
|
|
||||||
|
|
||||||
(($bufferbloat_detected)) && load_condition=$load_condition"_bb"
|
|
||||||
|
|
||||||
if ((sss_compensation)); then
|
|
||||||
for sss_time_us in "${sss_times_us[@]}"
|
|
||||||
do
|
|
||||||
((timestamp_usecs_past_minute=${EPOCHREALTIME/./}%60000000))
|
|
||||||
if (( ($timestamp_usecs_past_minute > ($sss_time_us-$sss_compensation_pre_duration_us)) && ($timestamp_usecs_past_minute < ($sss_time_us+$sss_compensation_post_duration_us)) )); then
|
|
||||||
load_condition=$load_condition"_sss"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
monitor_reflector_responses()
|
|
||||||
{
|
|
||||||
# ping reflector, maintain baseline and output deltas to a common fifo
|
|
||||||
|
|
||||||
local pinger=$1
|
|
||||||
local rtt_baseline_us=$2
|
|
||||||
|
|
||||||
while read -r timestamp _ _ _ reflector seq_rtt
|
|
||||||
do
|
|
||||||
# If no match then skip onto the next one
|
|
||||||
[[ $seq_rtt =~ icmp_[s|r]eq=([0-9]+).*time=([0-9]+)\.?([0-9]+)?[[:space:]]ms ]] || continue
|
|
||||||
|
|
||||||
seq=${BASH_REMATCH[1]}
|
|
||||||
|
|
||||||
rtt_us=${BASH_REMATCH[3]}000
|
|
||||||
rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3}))
|
|
||||||
|
|
||||||
reflector=${reflector//:/}
|
|
||||||
|
|
||||||
rtt_delta_us=$(( $rtt_us-$rtt_baseline_us ))
|
|
||||||
|
|
||||||
alpha=$(( (( $rtt_delta_us >=0 )) ? $alpha_baseline_increase : $alpha_baseline_decrease ))
|
|
||||||
|
|
||||||
rtt_baseline_us=$(( ( (1000-$alpha)*$rtt_baseline_us+$alpha*$rtt_us )/1000 ))
|
|
||||||
|
|
||||||
printf '%s %s %s %s %s %s\n' "$timestamp" "$reflector" "$seq" "$rtt_baseline_us" "$rtt_us" "$rtt_delta_us" > /tmp/CAKE-autorate-${dl_if}/ping_fifo
|
|
||||||
|
|
||||||
printf '%s' "${timestamp//[[\[\].]}" > /tmp/CAKE-autorate-${dl_if}/reflector_${pinger}_last_timestamp_us
|
|
||||||
|
|
||||||
done</tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo
|
|
||||||
}
|
|
||||||
|
|
||||||
kill_pingers()
|
|
||||||
{
|
|
||||||
for (( pinger=0; pinger<$no_pingers; pinger++))
|
|
||||||
do
|
|
||||||
kill ${pinger_pids[$pinger]} 2> /dev/null
|
|
||||||
[[ -p /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo ]] && rm /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo
|
|
||||||
done
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
maintain_pingers()
|
|
||||||
{
|
|
||||||
# this initiates the pingers and monitors reflector health, rotating reflectors as necessary
|
|
||||||
|
|
||||||
trap kill_pingers TERM
|
|
||||||
|
|
||||||
declare -A pinger_pids
|
|
||||||
declare -A rtt_baselines_us
|
|
||||||
|
|
||||||
reflector_offences_idx=0
|
|
||||||
|
|
||||||
# For each pinger: create fifos, get baselines and initialize record of offences
|
|
||||||
for ((pinger=0; pinger<$no_pingers; pinger++))
|
|
||||||
do
|
|
||||||
mkfifo /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo
|
|
||||||
[[ $(ping -B -I ${dl_if} -q -c 5 -i 0.1 ${reflectors[$pinger]} | tail -1) =~ ([0-9.]+)/ ]] && printf -v rtt_baselines_us[$pinger] %.0f\\n "${BASH_REMATCH[1]}e3" || rtt_baselines_us[$pinger]=0
|
|
||||||
|
|
||||||
declare -n reflector_offences="reflector_${pinger}_offences"
|
|
||||||
for ((i=0; i<$reflector_misbehaving_detection_window; i++)) do reflector_offences[i]=0; done
|
|
||||||
|
|
||||||
sum_reflector_offences[$pinger]=0
|
|
||||||
done
|
|
||||||
|
|
||||||
pingers_t_start_us=${EPOCHREALTIME/./}
|
|
||||||
|
|
||||||
# Initiate pingers
|
|
||||||
for ((pinger=0; pinger<$no_pingers; pinger++))
|
|
||||||
do
|
|
||||||
printf '%s' "$pingers_t_start_us" > /tmp/CAKE-autorate-${dl_if}/reflector_${pinger}_last_timestamp_us
|
|
||||||
start_pinger_next_pinger_time_slot $pinger pid
|
|
||||||
pinger_pids[$pinger]=$pid
|
|
||||||
done
|
|
||||||
|
|
||||||
# Reflector health check loop - verifies reflectors have not gone stale and rotates reflectors as necessary
|
|
||||||
while true
|
|
||||||
do
|
|
||||||
sleep_s $reflector_health_check_interval_s
|
|
||||||
|
|
||||||
for ((pinger=0; pinger<$no_pingers; pinger++))
|
|
||||||
do
|
|
||||||
reflector_check_time_us=${EPOCHREALTIME/./}
|
|
||||||
concurrent_read_positive_integer reflector_last_timestamp_us /tmp/CAKE-autorate-${dl_if}/reflector_${pinger}_last_timestamp_us
|
|
||||||
declare -n reflector_offences="reflector_${pinger}_offences"
|
|
||||||
|
|
||||||
(( ${reflector_offences[$reflector_offences_idx]} )) && ((sum_reflector_offences[$pinger]--))
|
|
||||||
reflector_offences[$reflector_offences_idx]=$(( (((${EPOCHREALTIME/./}-$reflector_last_timestamp_us) > $reflector_response_deadline_us)) ? 1 : 0 ))
|
|
||||||
((reflector_offences[$reflector_offences_idx])) && ((sum_reflector_offences[$pinger]++))
|
|
||||||
|
|
||||||
if ((sum_reflector_offences[$pinger]>=$reflector_misbehaving_detection_thr)); then
|
|
||||||
|
|
||||||
(($debug)) && echo "DEBUG: Warning: reflector: "${reflectors[$pinger]}" seems to be misbehaving."
|
|
||||||
|
|
||||||
if(($no_reflectors>$no_pingers)); then
|
|
||||||
|
|
||||||
# pingers always use reflectors[0]..[$no_pingers-1] as the initial set
|
|
||||||
# and the additional reflectors are spare reflectors should any from initial set go stale
|
|
||||||
# a bad reflector in the initial set is replaced with $reflectors[$no_pingers]
|
|
||||||
# $reflectors[$no_pingers] is then unset
|
|
||||||
# and the the bad reflector moved to the back of the queue (last element in $reflectors[])
|
|
||||||
# and finally the indices for $reflectors are updated to reflect the new order
|
|
||||||
|
|
||||||
(($debug)) && echo "DEBUG: Replacing reflector: "${reflectors[$pinger]}" with "${reflectors[$no_pingers]}"."
|
|
||||||
kill ${pinger_pids[$pinger]} 2> /dev/null
|
|
||||||
bad_reflector=${reflectors[$pinger]}
|
|
||||||
# overwrite the bad reflector with the reflector that is next in the queue (the one after 0..$no_pingers-1)
|
|
||||||
reflectors[$pinger]=${reflectors[$no_pingers]}
|
|
||||||
# remove the new reflector from the list of additional reflectors beginning from $reflectors[$no_pingers]
|
|
||||||
unset reflectors[$no_pingers]
|
|
||||||
# bad reflector goes to the back of the queue
|
|
||||||
reflectors+=($bad_reflector)
|
|
||||||
# reset array indices
|
|
||||||
reflectors=(${reflectors[*]})
|
|
||||||
# set up the new pinger with the new reflector and retain pid
|
|
||||||
start_pinger_next_pinger_time_slot $pinger pid
|
|
||||||
pinger_pids[$pinger]=$pid
|
|
||||||
|
|
||||||
else
|
|
||||||
(($debug)) && echo "DEBUG: No additional reflectors specified so just retaining: "${reflectors[$pinger]}"."
|
|
||||||
reflector_offences[$pinger]=0
|
|
||||||
fi
|
|
||||||
|
|
||||||
for ((i=0; i<$reflector_misbehaving_detection_window; i++)) do reflector_offences[i]=0; done
|
|
||||||
sum_reflector_offences[$pinger]=0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
((reflector_offences_idx=(reflector_offences_idx+1)%$reflector_misbehaving_detection_window))
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
start_pinger_next_pinger_time_slot()
|
|
||||||
{
|
|
||||||
# wait until next pinger time slot and start pinger in its slot
|
|
||||||
# this allows pingers to be stopped and started (e.g. during sleep or reflector rotation)
|
|
||||||
# whilst ensuring pings will remain spaced out appropriately to maintain granularity
|
|
||||||
|
|
||||||
local pinger=$1
|
|
||||||
local -n pinger_pid=$2
|
|
||||||
t_start_us=${EPOCHREALTIME/./}
|
|
||||||
time_to_next_time_slot_us=$(( ($reflector_ping_interval_us-($t_start_us-$pingers_t_start_us)%$reflector_ping_interval_us) + $pinger*$ping_response_interval_us ))
|
|
||||||
sleep_remaining_tick_time $t_start_us $time_to_next_time_slot_us
|
|
||||||
if (($debug)); then
|
|
||||||
ping -B -I ${dl_if} -D -i $reflector_ping_interval_s ${reflectors[$pinger]} > /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo &
|
|
||||||
pinger_pid=$!
|
|
||||||
else
|
|
||||||
ping -B -I ${dl_if} -D -i $reflector_ping_interval_s ${reflectors[$pinger]} > /tmp/CAKE-autorate-${dl_if}/pinger_${pinger}_fifo 2> /dev/null &
|
|
||||||
pinger_pid=$!
|
|
||||||
fi
|
|
||||||
monitor_reflector_responses $pinger ${rtt_baselines_us[$pinger]} &
|
|
||||||
}
|
|
||||||
|
|
||||||
set_cake_rate()
|
|
||||||
{
|
|
||||||
local interface=$1
|
|
||||||
local shaper_rate_kbps=$2
|
|
||||||
local -n time_rate_set_us=$3
|
|
||||||
|
|
||||||
(($output_cake_changes)) && echo "tc qdisc change root dev ${interface} cake bandwidth ${shaper_rate_kbps}Kbit"
|
|
||||||
|
|
||||||
if (($debug)); then
|
|
||||||
tc qdisc change root dev $interface cake bandwidth ${shaper_rate_kbps}Kbit
|
|
||||||
else
|
|
||||||
tc qdisc change root dev $interface cake bandwidth ${shaper_rate_kbps}Kbit 2> /dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
time_rate_set_us=${EPOCHREALTIME/./}
|
|
||||||
}
|
|
||||||
|
|
||||||
set_shaper_rates()
|
|
||||||
{
|
|
||||||
if (( $dl_shaper_rate_kbps != $last_dl_shaper_rate_kbps || $ul_shaper_rate_kbps != $last_ul_shaper_rate_kbps )); then
|
|
||||||
|
|
||||||
# fire up tc in each direction if there are rates to change, and if rates change in either direction then update max wire calcs
|
|
||||||
(( $dl_shaper_rate_kbps != $last_dl_shaper_rate_kbps )) && { set_cake_rate $dl_if $dl_shaper_rate_kbps t_prev_dl_rate_set_us; last_dl_shaper_rate_kbps=$dl_shaper_rate_kbps; }
|
|
||||||
(( $ul_shaper_rate_kbps != $last_ul_shaper_rate_kbps )) && { set_cake_rate $ul_if $ul_shaper_rate_kbps t_prev_ul_rate_set_us; last_ul_shaper_rate_kbps=$ul_shaper_rate_kbps; }
|
|
||||||
|
|
||||||
update_max_wire_packet_compensation
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
get_max_wire_packet_size_bits()
|
|
||||||
{
|
|
||||||
local interface=$1
|
|
||||||
local -n max_wire_packet_size_bits=$2
|
|
||||||
|
|
||||||
read -r max_wire_packet_size_bits < "/sys/class/net/${interface}/mtu"
|
|
||||||
[[ $(tc qdisc show dev $interface) =~ (atm|noatm)[[:space:]]overhead[[:space:]]([0-9]+) ]]
|
|
||||||
[[ ! -z "${BASH_REMATCH[2]}" ]] && max_wire_packet_size_bits=$((8*($max_wire_packet_size_bits+${BASH_REMATCH[2]})))
|
|
||||||
# atm compensation = 53*ceil(X/48) bytes = 8*53*((X+8*(48-1)/(8*48)) bits = 424*((X+376)/384) bits
|
|
||||||
[[ "${BASH_REMATCH[1]}" == "atm" ]] && max_wire_packet_size_bits=$(( 424*(($max_wire_packet_size_bits+376)/384) ))
|
|
||||||
}
|
|
||||||
|
|
||||||
update_max_wire_packet_compensation()
|
|
||||||
{
|
|
||||||
# Compensate for delays imposed by active traffic shaper
|
|
||||||
# This will serve to increase the delay thr at rates below around 12Mbit/s
|
|
||||||
|
|
||||||
max_wire_packet_rtt_us=$(( (1000*$dl_max_wire_packet_size_bits)/$dl_shaper_rate_kbps + (1000*$ul_max_wire_packet_size_bits)/$ul_shaper_rate_kbps ))
|
|
||||||
compensated_delay_thr_us=$(( $delay_thr_us + $max_wire_packet_rtt_us ))
|
|
||||||
|
|
||||||
# write out max_wire_packet_rtt_us
|
|
||||||
printf '%s' "$max_wire_packet_rtt_us" > /tmp/CAKE-autorate-${dl_if}/max_wire_packet_rtt_us
|
|
||||||
}
|
|
||||||
|
|
||||||
concurrent_read_positive_integer()
|
|
||||||
{
|
|
||||||
# in the context of separate processes writing using > and reading form file
|
|
||||||
# it seems costly calls to the external flock binary can be avoided
|
|
||||||
# read either succeeds as expected or occassionally reads in bank value
|
|
||||||
# so just test for blank value and re-read until not blank
|
|
||||||
|
|
||||||
local -n value=$1
|
|
||||||
local path=$2
|
|
||||||
while true
|
|
||||||
do
|
|
||||||
read -r value < $path;
|
|
||||||
if [[ -z "${value##*[!0-9]*}" ]]; then
|
|
||||||
if (($debug)); then
|
|
||||||
read -r caller_output< <(caller)
|
|
||||||
echo "DEBUG concurrent_read_positive_integer() misfire with the following particulars:"
|
|
||||||
echo "DEBUG caller="$caller_output"; value="$value"; and path="$path
|
|
||||||
fi
|
|
||||||
sleep_us $concurrent_read_positive_integer_interval_us
|
|
||||||
continue
|
|
||||||
else
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
verify_ifs_up()
|
|
||||||
{
|
|
||||||
# Check the rx/tx paths exist and give extra time for ifb's to come up if needed
|
|
||||||
# This will block if ifs never come up
|
|
||||||
|
|
||||||
while [[ ! -f $rx_bytes_path || ! -f $tx_bytes_path ]]
|
|
||||||
do
|
|
||||||
(($debug)) && [[ ! -f $rx_bytes_path ]] && echo "DEBUG Warning: $rx_bytes_path does not exist. Waiting "$if_up_check_interval_s" seconds for interface to come up."
|
|
||||||
(($debug)) && [[ ! -f $tx_bytes_path ]] && echo "DEBUG Warning: $tx_bytes_path does not exist. Waiting "$if_up_check_interval_s" seconds for interface to come up."
|
|
||||||
sleep_s $if_up_check_interval_s
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
sleep_s()
|
|
||||||
{
|
|
||||||
# calling external sleep binary is slow
|
|
||||||
# bash does have a loadable sleep
|
|
||||||
# but read's timeout can more portably be exploited and this is apparently even faster anyway
|
|
||||||
|
|
||||||
local sleep_duration_s=$1 # (seconds, e.g. 0.5, 1 or 1.5)
|
|
||||||
|
|
||||||
read -t $sleep_duration_s < /tmp/CAKE-autorate-${dl_if}/sleep_fifo
|
|
||||||
}
|
|
||||||
|
|
||||||
sleep_us()
|
|
||||||
{
|
|
||||||
# calling external sleep binary is slow
|
|
||||||
# bash does have a loadable sleep
|
|
||||||
# but read's timeout can more portably be exploited and this is apparently even fastera anyway
|
|
||||||
|
|
||||||
local sleep_duration_us=$1 # (microseconds)
|
|
||||||
|
|
||||||
sleep_duration_s=000000$sleep_duration_us
|
|
||||||
sleep_duration_s=${sleep_duration_s::-6}.${sleep_duration_s: -6}
|
|
||||||
read -t $sleep_duration_s < /tmp/CAKE-autorate-${dl_if}/sleep_fifo
|
|
||||||
}
|
|
||||||
|
|
||||||
sleep_remaining_tick_time()
|
|
||||||
{
|
|
||||||
# sleeps until the end of the tick duration
|
|
||||||
|
|
||||||
local t_start_us=$1 # (microseconds)
|
|
||||||
local tick_duration_us=$2 # (microseconds)
|
|
||||||
|
|
||||||
sleep_duration_us=$(( $t_start_us + $tick_duration_us - ${EPOCHREALTIME/./} ))
|
|
||||||
|
|
||||||
if (( $sleep_duration_us > 0 )); then
|
|
||||||
sleep_us $sleep_duration_us
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Set up tmp directory, sleep fifo and perform various sanity checks
|
|
||||||
|
|
||||||
# /tmp/CAKE-autorate-${dl_if}/ is used to store temporary files
|
|
||||||
# it should not exist on startup so if it does exit, else create the directory
|
|
||||||
if [[ -d /tmp/CAKE-autorate-${dl_if} ]]; then
|
|
||||||
echo "Error: /tmp/CAKE-autorate-${dl_if} already exists. Is another instance running? Exiting script."
|
|
||||||
trap - INT TERM EXIT
|
|
||||||
exit
|
|
||||||
else
|
|
||||||
mkdir /tmp/CAKE-autorate-${dl_if}
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkfifo /tmp/CAKE-autorate-${dl_if}/sleep_fifo
|
|
||||||
exec 3<> /tmp/CAKE-autorate-${dl_if}/sleep_fifo
|
|
||||||
|
|
||||||
no_reflectors=${#reflectors[@]}
|
|
||||||
|
|
||||||
# Check no_pingers <= no_reflectors
|
|
||||||
(( $no_pingers > $no_reflectors)) && { echo "Error: number of pingers cannot be greater than number of reflectors. Exiting script."; exit; }
|
|
||||||
|
|
||||||
# Check dl/if interface not the same
|
|
||||||
[[ $dl_if == $ul_if ]] && { echo "Error: download interface and upload interface are both set to: '"$dl_if"', but cannot be the same. Exiting script."; exit; }
|
|
||||||
|
|
||||||
# Check bufferbloat detection threshold not greater than window length
|
|
||||||
(( $bufferbloat_detection_thr > $bufferbloat_detection_window )) && { echo "Error: bufferbloat_detection_thr cannot be greater than bufferbloat_detection_window. Exiting script."; exit; }
|
|
||||||
|
|
||||||
# Wait if $startup_wait_s > 0
|
|
||||||
if (($startup_wait_s>0)); then
|
|
||||||
(($debug)) && echo "DEBUG Waiting "$startup_wait_s" seconds before startup."
|
|
||||||
sleep_s $startup_wait_s
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check interfaces are up and wait if necessary for them to come up
|
|
||||||
verify_ifs_up
|
|
||||||
|
|
||||||
# Initialize variables
|
|
||||||
|
|
||||||
# Convert human readable parameters to values that work with integer arithmetic
|
|
||||||
printf -v alpha_baseline_increase %.0f\\n "${alpha_baseline_increase}e3"
|
|
||||||
printf -v alpha_baseline_decrease %.0f\\n "${alpha_baseline_decrease}e3"
|
|
||||||
printf -v achieved_rate_adjust_down_bufferbloat %.0f\\n "${achieved_rate_adjust_down_bufferbloat}e3"
|
|
||||||
printf -v shaper_rate_adjust_down_bufferbloat %.0f\\n "${shaper_rate_adjust_down_bufferbloat}e3"
|
|
||||||
printf -v shaper_rate_adjust_up_load_high %.0f\\n "${shaper_rate_adjust_up_load_high}e3"
|
|
||||||
printf -v shaper_rate_adjust_down_load_low %.0f\\n "${shaper_rate_adjust_down_load_low}e3"
|
|
||||||
printf -v shaper_rate_adjust_up_load_low %.0f\\n "${shaper_rate_adjust_up_load_low}e3"
|
|
||||||
printf -v high_load_thr_percent %.0f\\n "${high_load_thr}e2"
|
|
||||||
printf -v medium_load_thr_percent %.0f\\n "${medium_load_thr}e2"
|
|
||||||
printf -v reflector_ping_interval_us %.0f\\n "${reflector_ping_interval_s}e6"
|
|
||||||
printf -v monitor_achieved_rates_interval_us %.0f\\n "${monitor_achieved_rates_interval_ms}e3"
|
|
||||||
printf -v sustained_idle_sleep_thr_us %.0f\\n "${sustained_idle_sleep_thr_s}e6"
|
|
||||||
printf -v reflector_response_deadline_us %.0f\\n "${reflector_response_deadline_s}e6"
|
|
||||||
bufferbloat_refractory_period_us=$(( 1000*$bufferbloat_refractory_period_ms ))
|
|
||||||
decay_refractory_period_us=$(( 1000*$decay_refractory_period_ms ))
|
|
||||||
delay_thr_us=$(( 1000*$delay_thr_ms ))
|
|
||||||
|
|
||||||
for (( i=0; i<${#sss_times_s[@]}; i++ ));
|
|
||||||
do
|
|
||||||
printf -v sss_times_us[i] %.0f\\n "${sss_times_s[i]}e6"
|
|
||||||
done
|
|
||||||
printf -v sss_compensation_pre_duration_us %.0f\\n "${sss_compensation_pre_duration_ms}e3"
|
|
||||||
printf -v sss_compensation_post_duration_us %.0f\\n "${sss_compensation_post_duration_ms}e3"
|
|
||||||
|
|
||||||
ping_response_interval_us=$(($reflector_ping_interval_us/$no_pingers))
|
|
||||||
|
|
||||||
concurrent_read_positive_integer_interval_us=$(($ping_response_interval_us/4))
|
|
||||||
|
|
||||||
dl_shaper_rate_kbps=$base_dl_shaper_rate_kbps
|
|
||||||
ul_shaper_rate_kbps=$base_ul_shaper_rate_kbps
|
|
||||||
|
|
||||||
last_dl_shaper_rate_kbps=$dl_shaper_rate_kbps
|
|
||||||
last_ul_shaper_rate_kbps=$ul_shaper_rate_kbps
|
|
||||||
|
|
||||||
get_max_wire_packet_size_bits $dl_if dl_max_wire_packet_size_bits
|
|
||||||
get_max_wire_packet_size_bits $ul_if ul_max_wire_packet_size_bits
|
|
||||||
|
|
||||||
set_cake_rate $dl_if $dl_shaper_rate_kbps t_prev_dl_rate_set_us
|
|
||||||
set_cake_rate $ul_if $ul_shaper_rate_kbps t_prev_ul_rate_set_us
|
|
||||||
|
|
||||||
update_max_wire_packet_compensation
|
|
||||||
|
|
||||||
t_start_us=${EPOCHREALTIME/./}
|
|
||||||
t_end_us=${EPOCHREALTIME/./}
|
|
||||||
t_prev_ul_rate_set_us=$t_start_us
|
|
||||||
t_prev_dl_rate_set_us=$t_start_us
|
|
||||||
t_ul_last_bufferbloat_us=$t_start_us
|
|
||||||
t_ul_last_decay_us=$t_start_us
|
|
||||||
t_dl_last_bufferbloat_us=$t_start_us
|
|
||||||
t_dl_last_decay_us=$t_start_us
|
|
||||||
|
|
||||||
t_sustained_connection_idle_us=0
|
|
||||||
|
|
||||||
declare -a delays=( $(for i in {1..$bufferbloat_detection_window}; do echo 0; done) )
|
|
||||||
delays_idx=0
|
|
||||||
sum_delays=0
|
|
||||||
|
|
||||||
mkfifo /tmp/CAKE-autorate-${dl_if}/ping_fifo
|
|
||||||
exec 4<> /tmp/CAKE-autorate-${dl_if}/ping_fifo
|
|
||||||
|
|
||||||
maintain_pingers &
|
|
||||||
maintain_pingers_pid=$!
|
|
||||||
|
|
||||||
# Initiate achived rate monitor
|
|
||||||
monitor_achieved_rates $rx_bytes_path $tx_bytes_path $monitor_achieved_rates_interval_us&
|
|
||||||
monitor_achieved_rates_pid=$!
|
|
||||||
|
|
||||||
prev_timestamp=0
|
|
||||||
|
|
||||||
if (($debug)); then
|
|
||||||
if (( $bufferbloat_refractory_period_us <= ($bufferbloat_detection_window*$ping_response_interval_us) )); then
|
|
||||||
echo "DEBUG Warning: bufferbloat refractory period: " $bufferbloat_refractory_period_us " us."
|
|
||||||
echo "DEBUG Warning: but expected time to overwrite samples in bufferbloat detection window is: " $(($bufferbloat_detection_window*$ping_response_interval_us)) " us."
|
|
||||||
echo "DEBUG Warning: Consider increasing bufferbloat refractory period or decreasing bufferbloat detection window."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
while true
|
|
||||||
do
|
|
||||||
while read -t $global_ping_response_timeout_s -r timestamp reflector seq rtt_baseline_us rtt_us rtt_delta_us
|
|
||||||
do
|
|
||||||
t_start_us=${EPOCHREALTIME/./}
|
|
||||||
if ((($t_start_us - 10#"${timestamp//[[\[\].]}")>500000)); then
|
|
||||||
(($debug)) && echo "DEBUG processed response from [" $reflector "] that is > 500ms old. Skipping."
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Keep track of number of delays across detection window
|
|
||||||
(( ${delays[$delays_idx]} )) && ((sum_delays--))
|
|
||||||
delays[$delays_idx]=$(( $rtt_delta_us > $compensated_delay_thr_us ? 1 : 0 ))
|
|
||||||
((delays[$delays_idx])) && ((sum_delays++))
|
|
||||||
(( delays_idx=(delays_idx+1)%$bufferbloat_detection_window ))
|
|
||||||
|
|
||||||
bufferbloat_detected=$(( (($sum_delays>=$bufferbloat_detection_thr)) ? 1 : 0 ))
|
|
||||||
|
|
||||||
get_loads
|
|
||||||
|
|
||||||
classify_load $dl_load_percent $dl_achieved_rate_kbps dl_load_condition
|
|
||||||
classify_load $ul_load_percent $ul_achieved_rate_kbps ul_load_condition
|
|
||||||
|
|
||||||
dl_load_condition="dl_"$dl_load_condition
|
|
||||||
ul_load_condition="ul_"$ul_load_condition
|
|
||||||
|
|
||||||
get_next_shaper_rate $min_dl_shaper_rate_kbps $base_dl_shaper_rate_kbps $max_dl_shaper_rate_kbps $dl_achieved_rate_kbps $dl_load_condition $t_start_us t_dl_last_bufferbloat_us t_dl_last_decay_us dl_shaper_rate_kbps
|
|
||||||
get_next_shaper_rate $min_ul_shaper_rate_kbps $base_ul_shaper_rate_kbps $max_ul_shaper_rate_kbps $ul_achieved_rate_kbps $ul_load_condition $t_start_us t_ul_last_bufferbloat_us t_ul_last_decay_us ul_shaper_rate_kbps
|
|
||||||
|
|
||||||
(($output_processing_stats)) && printf '%s %-6s %-6s %-3s %-3s %s %-15s %-6s %-6s %-6s %-6s %-6s %s %-14s %-14s %-6s %-6s\n' $EPOCHREALTIME $dl_achieved_rate_kbps $ul_achieved_rate_kbps $dl_load_percent $ul_load_percent $timestamp $reflector $seq $rtt_baseline_us $rtt_us $rtt_delta_us $compensated_delay_thr_us $sum_delays $dl_load_condition $ul_load_condition $dl_shaper_rate_kbps $ul_shaper_rate_kbps
|
|
||||||
|
|
||||||
set_shaper_rates
|
|
||||||
|
|
||||||
# If base rate is sustained, increment sustained base rate timer (and break out of processing loop if enough time passes)
|
|
||||||
if (($enable_sleep_function)); then
|
|
||||||
if [[ $dl_load_condition == idle* && $ul_load_condition == idle* ]]; then
|
|
||||||
((t_sustained_connection_idle_us+=$((${EPOCHREALTIME/./}-$t_end_us))))
|
|
||||||
(($t_sustained_connection_idle_us>$sustained_idle_sleep_thr_us)) && break
|
|
||||||
else
|
|
||||||
# reset timer
|
|
||||||
t_sustained_connection_idle_us=0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
t_end_us=${EPOCHREALTIME/./}
|
|
||||||
|
|
||||||
done</tmp/CAKE-autorate-${dl_if}/ping_fifo
|
|
||||||
|
|
||||||
(($debug)) && {(( ${PIPESTATUS[0]} == 142 )) && echo "DEBUG Warning: global ping response timeout. Enforcing minimum shaper rates." || echo "DEBUG Connection idle. Enforcing minimum shaper rates.";}
|
|
||||||
|
|
||||||
# in any case, we broke out of processing loop, so conservatively set hard minimums and wait until there is a load increase again
|
|
||||||
dl_shaper_rate_kbps=$min_dl_shaper_rate_kbps
|
|
||||||
ul_shaper_rate_kbps=$min_ul_shaper_rate_kbps
|
|
||||||
set_shaper_rates
|
|
||||||
|
|
||||||
# Initiate termination of ping processes and wait until complete
|
|
||||||
kill $maintain_pingers_pid 2> /dev/null
|
|
||||||
wait $maintain_pingers_pid
|
|
||||||
|
|
||||||
# reset idle timer
|
|
||||||
t_sustained_connection_idle_us=0
|
|
||||||
|
|
||||||
# verify interfaces are up (e.g. following ping response timeout from interfaces going down)
|
|
||||||
verify_ifs_up
|
|
||||||
|
|
||||||
# wait until load increases again
|
|
||||||
while true
|
|
||||||
do
|
|
||||||
t_start_us=${EPOCHREALTIME/./}
|
|
||||||
get_loads
|
|
||||||
(($dl_load_percent>$medium_load_thr_percent || $ul_load_percent>$medium_load_thr_percent)) && break
|
|
||||||
sleep_remaining_tick_time $t_start_us $reflector_ping_interval_us
|
|
||||||
done
|
|
||||||
|
|
||||||
# Start up ping processes
|
|
||||||
maintain_pingers &
|
|
||||||
maintain_pingers_pid=$!
|
|
||||||
done
|
|
1790
luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh
Executable file
1790
luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh
Executable file
File diff suppressed because it is too large
Load diff
209
luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh
Executable file
209
luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh
Executable file
|
@ -0,0 +1,209 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# cake-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and RTT
|
||||||
|
|
||||||
|
# cake-autorate_config.sh is a script that sets up defaults for cake-autorate
|
||||||
|
|
||||||
|
# Author: @Lynx (OpenWrt forum)
|
||||||
|
# Inspiration taken from: @moeller0 (OpenWrt forum)
|
||||||
|
|
||||||
|
cake_autorate_version="2.0.0"
|
||||||
|
|
||||||
|
# *** OUTPUT AND LOGGING OPTIONS ***
|
||||||
|
|
||||||
|
output_processing_stats=1 # enable (1) or disable (0) output monitoring lines showing processing stats
|
||||||
|
output_load_stats=1 # enable (1) or disable (0) output monitoring lines showing achieved loads
|
||||||
|
output_reflector_stats=1 # enable (1) or disable (0) output monitoring lines showing reflector stats
|
||||||
|
output_cake_changes=0 # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes
|
||||||
|
debug=1 # enable (1) or disable (0) out of debug lines
|
||||||
|
|
||||||
|
# This can generate a LOT of records so be careful:
|
||||||
|
log_DEBUG_messages_to_syslog=0 # enable (1) or disable (0) logging of all DEBUG records into the system log.
|
||||||
|
|
||||||
|
# ** Take care with these settings to ensure you won't run into OOM issues on your router ***
|
||||||
|
# every write the cumulative write time and bytes associated with each log line are checked
|
||||||
|
# and if either exceeds the configured values below, the log log file is rotated
|
||||||
|
log_to_file=1 # enable (1) or disable (0) output logging to file (/tmp/cake-autorate.log)
|
||||||
|
log_file_max_time_mins=10 # maximum time between log file rotations
|
||||||
|
log_file_max_size_KB=2000 # maximum KB (i.e. bytes/1024) worth of log lines between log file rotations
|
||||||
|
|
||||||
|
# log file path defaults to /var/log/
|
||||||
|
# or, if set below, then ${log_file_path_override}
|
||||||
|
log_file_path_override=""
|
||||||
|
|
||||||
|
# *** STANDARD CONFIGURATION OPTIONS ***
|
||||||
|
|
||||||
|
### For multihomed setups, it is the responsibility of the user to ensure that the probes
|
||||||
|
### sent by this instance of cake-autorate actually travel through these interfaces.
|
||||||
|
### See ping_extra_args and ping_prefix_string
|
||||||
|
|
||||||
|
dl_if=ifb-wan # download interface
|
||||||
|
ul_if=wan # upload interface
|
||||||
|
|
||||||
|
# pinger selection can be any of:
|
||||||
|
# fping - round robin pinging (rtts)
|
||||||
|
# ping - (iputils-ping) individual pinging (rtts)
|
||||||
|
# hping3 - individidual pinging (owds)
|
||||||
|
pinger_binary=ping
|
||||||
|
|
||||||
|
# list of reflectors to use and number of pingers to initiate
|
||||||
|
# pingers will be initiated with reflectors in the order specified in the list
|
||||||
|
# additional reflectors will be used to replace any reflectors that go stale
|
||||||
|
# so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially
|
||||||
|
# and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad
|
||||||
|
# a bad reflector will go to the back of the queue on reflector rotation
|
||||||
|
reflectors=(
|
||||||
|
"1.1.1.1" "1.0.0.1" # Cloudflare
|
||||||
|
"8.8.8.8" "8.8.4.4" # Google
|
||||||
|
"9.9.9.9" "9.9.9.10" "9.9.9.11" # Quad9
|
||||||
|
"94.140.14.15" "94.140.14.140" "94.140.14.141" "94.140.15.15" "94.140.15.16" # AdGuard
|
||||||
|
"64.6.65.6" "156.154.70.1" "156.154.70.2" "156.154.70.3" "156.154.70.4" "156.154.70.5" "156.154.71.1" "156.154.71.2" "156.154.71.3" "156.154.71.4" "156.154.71.5" # Neustar
|
||||||
|
"208.67.220.2" "208.67.220.123" "208.67.220.220" "208.67.222.2" "208.67.222.123" # OpenDNS
|
||||||
|
"185.228.168.9" "185.228.168.10" # CleanBrowsing
|
||||||
|
)
|
||||||
|
|
||||||
|
randomize_reflectors=1 # enable (1) or disable (0) randomization of reflectors on startup
|
||||||
|
|
||||||
|
# Think carefully about the following settings
|
||||||
|
# to avoid excessive CPU use (proportional with ping interval / number of pingers)
|
||||||
|
# and to avoid abusive network activity (excessive ICMP frequency to one reflector)
|
||||||
|
# The author has found an ICMP rate of 1/(0.2/4) = 20 Hz to give satisfactory performance on 4G
|
||||||
|
no_pingers=6 # number of pingers to maintain
|
||||||
|
reflector_ping_interval_s=0.3 # (seconds, e.g. 0.2s or 2s)
|
||||||
|
|
||||||
|
# delay threshold in ms is the extent of OWD increase to classify as a delay
|
||||||
|
# these are automatically adjusted based on maximum on the wire packet size
|
||||||
|
# (adjustment significant at sub 12Mbit/s rates, else negligible)
|
||||||
|
dl_delay_thr_ms=30 # (milliseconds)
|
||||||
|
ul_delay_thr_ms=30 # (milliseconds)
|
||||||
|
|
||||||
|
# Set either of the below to 0 to adjust one direction only
|
||||||
|
# or alternatively set both to 0 to simply use cake-autorate to monitor a connection
|
||||||
|
adjust_dl_shaper_rate=1 # enable (1) or disable (0) actually changing the dl shaper rate
|
||||||
|
adjust_ul_shaper_rate=1 # enable (1) or disable (0) actually changing the ul shaper rate
|
||||||
|
|
||||||
|
min_dl_shaper_rate_kbps=5000 # minimum bandwidth for download (Kbit/s)
|
||||||
|
base_dl_shaper_rate_kbps=20000 # steady state bandwidth for download (Kbit/s)
|
||||||
|
max_dl_shaper_rate_kbps=80000 # maximum bandwidth for download (Kbit/s)
|
||||||
|
|
||||||
|
min_ul_shaper_rate_kbps=5000 # minimum bandwidth for upload (Kbit/s)
|
||||||
|
base_ul_shaper_rate_kbps=20000 # steady state bandwidth for upload (KBit/s)
|
||||||
|
max_ul_shaper_rate_kbps=35000 # maximum bandwidth for upload (Kbit/s)
|
||||||
|
|
||||||
|
# sleep functionality saves unecessary pings and CPU cycles by
|
||||||
|
# pausing all active pingers when connection is not in active use
|
||||||
|
enable_sleep_function=1 # enable (1) or disable (0) sleep functonality
|
||||||
|
connection_active_thr_kbps=1000 # threshold in Kbit/s below which dl/ul is considered idle
|
||||||
|
sustained_idle_sleep_thr_s=60.0 # time threshold to put pingers to sleep on sustained dl/ul achieved rate < idle_thr (seconds)
|
||||||
|
|
||||||
|
min_shaper_rates_enforcement=0 # enable (1) or disable (0) dropping down to minimum shaper rates on connection idle or stall
|
||||||
|
|
||||||
|
startup_wait_s=0.0 # number of seconds to wait on startup (e.g. to wait for things to settle on router reboot)
|
||||||
|
|
||||||
|
# *** ADVANCED CONFIGURATION OPTIONS ***
|
||||||
|
|
||||||
|
log_file_export_compress=1 # compress log file exports using gzip and append .gz to export filename
|
||||||
|
|
||||||
|
### In multi-homed setups, it is mandatory to use either ping_extra_args
|
||||||
|
### or ping_prefix_string to direct the pings through $dl_if and $ul_if.
|
||||||
|
### No universal recommendation exists, because there are multiple
|
||||||
|
### policy-routing packages available (e.g. vpn-policy-routing and mwan3).
|
||||||
|
### Typically they either react to a firewall mark set on the pings, or
|
||||||
|
### provide a convenient wrapper.
|
||||||
|
###
|
||||||
|
### In a traditional single-homed setup, there is usually no need for these parameters.
|
||||||
|
###
|
||||||
|
### These arguments can also be used for any other purpose - e.g. for setting a
|
||||||
|
### particular QoS mark.
|
||||||
|
|
||||||
|
# extra arguments for ping or fping
|
||||||
|
# e.g., here is how you can set the correct outgoing interface and
|
||||||
|
# the firewall mark for ping:
|
||||||
|
# ping_extra_args="-I wwan0 -m $((0x300))"
|
||||||
|
# Unfortunately, fping does not offer a command line switch to set
|
||||||
|
# the firewall mark.
|
||||||
|
# WARNING: no error checking so use at own risk!
|
||||||
|
ping_extra_args=""
|
||||||
|
|
||||||
|
# a wrapper for ping binary - used as a prefix for the real command
|
||||||
|
# e.g., when using mwan3, it is recommended to set it like this:
|
||||||
|
# ping_prefix_string="mwan3 use gpon exec"
|
||||||
|
# WARNING: the wrapper must exec ping as the final step, not run it as a subprocess.
|
||||||
|
# Running ping or fping as a subprocess will lead to problems stopping it.
|
||||||
|
# WARNING: no error checking - so use at own risk!
|
||||||
|
ping_prefix_string=""
|
||||||
|
|
||||||
|
# interval in ms for monitoring achieved rx/tx rates
|
||||||
|
# this is automatically adjusted based on maximum on the wire packet size
|
||||||
|
# (adjustment significant at sub 12Mbit/s rates, else negligible)
|
||||||
|
monitor_achieved_rates_interval_ms=200 # (milliseconds)
|
||||||
|
|
||||||
|
# bufferbloat is detected when (bufferbloat_detection_thr) samples
|
||||||
|
# out of the last (bufferbloat detection window) samples are delayed
|
||||||
|
bufferbloat_detection_window=6 # number of samples to retain in detection window
|
||||||
|
bufferbloat_detection_thr=3 # number of delayed samples for bufferbloat detection
|
||||||
|
|
||||||
|
# OWD baseline against which to measure delays
|
||||||
|
# the idea is that the baseline is allowed to increase slowly to allow for path changes
|
||||||
|
# and slowly enough such that bufferbloat will be corrected well before the baseline increases,
|
||||||
|
# but it will decrease very rapidly to ensure delays are measured against the shortest path
|
||||||
|
alpha_baseline_increase=0.001 # how rapidly baseline RTT is allowed to increase
|
||||||
|
alpha_baseline_decrease=0.9 # how rapidly baseline RTT is allowed to decrease
|
||||||
|
|
||||||
|
# OWD delta from baseline is tracked using ewma with alpha set below
|
||||||
|
alpha_delta_ewma=0.095
|
||||||
|
|
||||||
|
# rate adjustment parameters
|
||||||
|
# bufferbloat adjustment works with the lower of the adjusted achieved rate and adjusted shaper rate
|
||||||
|
# to exploit that transfer rates during bufferbloat provide an indication of line capacity
|
||||||
|
# otherwise shaper rate is adjusted up on load high, and down on load idle or low
|
||||||
|
achieved_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce achieved rate upon detection of bufferbloat
|
||||||
|
shaper_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce shaper rate upon detection of bufferbloat
|
||||||
|
shaper_rate_adjust_up_load_high=1.01 # how rapidly to increase shaper rate upon high load detected
|
||||||
|
shaper_rate_adjust_down_load_low=0.99 # how rapidly to return down to base shaper rate upon idle or low load detected
|
||||||
|
shaper_rate_adjust_up_load_low=1.01 # how rapidly to return up to base shaper rate upon idle or low load detected
|
||||||
|
|
||||||
|
# the load is categoried as low if < high_load_thr and high if > high_load_thr relative to the current shaper rate
|
||||||
|
high_load_thr=0.75 # % of currently set bandwidth for detecting high load
|
||||||
|
|
||||||
|
# refractory periods between successive bufferbloat/decay rate changes
|
||||||
|
# the bufferbloat refractory period should be greater than the
|
||||||
|
# average time it would take to replace the bufferbloat
|
||||||
|
# detection window with new samples upon a bufferbloat event
|
||||||
|
bufferbloat_refractory_period_ms=300 # (milliseconds)
|
||||||
|
decay_refractory_period_ms=1000 # (milliseconds)
|
||||||
|
|
||||||
|
# interval for checking reflector health
|
||||||
|
reflector_health_check_interval_s=1.0 # (seconds)
|
||||||
|
# deadline for reflector response not to be classified as an offence against reflector
|
||||||
|
reflector_response_deadline_s=1.0 # (seconds)
|
||||||
|
|
||||||
|
# reflector misbehaving is detected when $reflector_misbehaving_detection_thr samples
|
||||||
|
# out of the last (reflector misbehaving detection window) samples are offences
|
||||||
|
# thus with a 1s interval, window 60 and detection_thr 3, this is tantamount to
|
||||||
|
# 3 offences within the last 60s
|
||||||
|
reflector_misbehaving_detection_window=60
|
||||||
|
reflector_misbehaving_detection_thr=3
|
||||||
|
|
||||||
|
reflector_replacement_interval_mins=60 # how often to replace a random reflector from the present list
|
||||||
|
|
||||||
|
reflector_comparison_interval_mins=1 # how often to compare reflectors
|
||||||
|
reflector_owd_baseline_delta_thr_ms=10 # max increase from min baseline before reflector rotated
|
||||||
|
reflector_owd_delta_ewma_delta_thr_ms=10 # mac increase from min delta ewma before reflector rotated
|
||||||
|
|
||||||
|
# stall is detected when the following two conditions are met:
|
||||||
|
# 1) no reflector responses within $stall_detection_thr*$ping_response_interval_us; and
|
||||||
|
# 2) either $rx_achieved_rate or $tx_achieved_rate < $connection_stall_thr
|
||||||
|
stall_detection_thr=5
|
||||||
|
connection_stall_thr_kbps=10
|
||||||
|
|
||||||
|
global_ping_response_timeout_s=10.0 # timeout to set shaper rates to min on no ping response whatsoever (seconds)
|
||||||
|
|
||||||
|
if_up_check_interval_s=10.0 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state or sleep recovery)
|
||||||
|
|
||||||
|
# Starlink satellite switch (sss) compensation options
|
||||||
|
sss_compensation=0 # enable (1) or disable (0) Starlink handling
|
||||||
|
# satellite switch compensation start times in seconds of each minute
|
||||||
|
sss_times_s=("12.0" "27.0" "42.0" "57.0")
|
||||||
|
sss_compensation_pre_duration_ms=300
|
||||||
|
sss_compensation_post_duration_ms=200
|
26
luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_launcher.sh
Executable file
26
luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_launcher.sh
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cake_instances=(/usr/share/sqm-autorate/cake-autorate_config*sh)
|
||||||
|
cake_instance_pids=()
|
||||||
|
|
||||||
|
trap kill_cake_instances INT TERM EXIT
|
||||||
|
|
||||||
|
kill_cake_instances()
|
||||||
|
{
|
||||||
|
trap - INT TERM EXIT
|
||||||
|
|
||||||
|
echo "Killing all instances of cake one-by-one now."
|
||||||
|
|
||||||
|
for ((cake_instance=0; cake_instance<${#cake_instances[@]}; cake_instance++))
|
||||||
|
do
|
||||||
|
kill "${cake_instance_pids[${cake_instance}]}" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
wait
|
||||||
|
}
|
||||||
|
|
||||||
|
for cake_instance in "${cake_instances[@]}"
|
||||||
|
do
|
||||||
|
/usr/share/sqm-autorate/cake-autorate.sh "${cake_instance}" &
|
||||||
|
cake_instance_pids+=(${!})
|
||||||
|
done
|
||||||
|
wait
|
257
luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh
Executable file
257
luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh
Executable file
|
@ -0,0 +1,257 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# cake-autorate_lib.sh -- common functions for use by cake-autorate.sh
|
||||||
|
# This file is part of cake-autorate.
|
||||||
|
|
||||||
|
__set_e=0
|
||||||
|
if [[ ! ${-} =~ e ]]; then
|
||||||
|
set -e
|
||||||
|
__set_e=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec {__sleep_fd}<> <(:) || true
|
||||||
|
|
||||||
|
sleep_s()
|
||||||
|
{
|
||||||
|
# Calling the external sleep binary could be rather slow,
|
||||||
|
# especially as it is called very frequently and typically on mediocre hardware.
|
||||||
|
#
|
||||||
|
# bash's loadable sleep module is not typically available
|
||||||
|
# in OpenWRT and most embedded systems, and use of the bash
|
||||||
|
# read command with a timeout offers performance that is
|
||||||
|
# at least on a par with bash's sleep module.
|
||||||
|
#
|
||||||
|
# For benchmarks, check the following links:
|
||||||
|
# - https://github.com/lynxthecat/cake-autorate/issues/174#issuecomment-1460057382
|
||||||
|
# - https://github.com/lynxthecat/cake-autorate/issues/174#issuecomment-1460074498
|
||||||
|
|
||||||
|
local sleep_duration_s=${1} # (seconds, e.g. 0.5, 1 or 1.5)
|
||||||
|
read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || : &
|
||||||
|
wait "${!}"
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep_us()
|
||||||
|
{
|
||||||
|
local sleep_duration_us=${1} # (microseconds)
|
||||||
|
|
||||||
|
sleep_duration_s=000000${sleep_duration_us}
|
||||||
|
sleep_duration_s=$((10#${sleep_duration_s::-6})).${sleep_duration_s: -6}
|
||||||
|
sleep_s "${sleep_duration_s}"
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep_remaining_tick_time()
|
||||||
|
{
|
||||||
|
# sleeps until the end of the tick duration
|
||||||
|
|
||||||
|
local t_start_us=${1} # (microseconds)
|
||||||
|
local tick_duration_us=${2} # (microseconds)
|
||||||
|
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
sleep_duration_us=$(( t_start_us + tick_duration_us - ${EPOCHREALTIME/./} ))
|
||||||
|
|
||||||
|
if (( sleep_duration_us > 0 )); then
|
||||||
|
sleep_us "${sleep_duration_us}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
randomize_array()
|
||||||
|
{
|
||||||
|
local -n array=${1}
|
||||||
|
|
||||||
|
subset=("${array[@]}")
|
||||||
|
array=()
|
||||||
|
for ((set=${#subset[@]}; set>0; set--))
|
||||||
|
do
|
||||||
|
idx=$((RANDOM%set))
|
||||||
|
array+=("${subset[idx]}")
|
||||||
|
unset "subset[idx]"
|
||||||
|
subset=("${subset[@]}")
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
lock()
|
||||||
|
{
|
||||||
|
local path=${1}
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
( set -o noclobber; echo "$$" > "${path:?}" ) 2> /dev/null && return 0
|
||||||
|
sleep_us 100000
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock()
|
||||||
|
{
|
||||||
|
local path=${1}
|
||||||
|
|
||||||
|
rm -f "${path:?}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_proc_man_set_key()
|
||||||
|
{
|
||||||
|
local key=${1}
|
||||||
|
local value=${2}
|
||||||
|
|
||||||
|
lock "${PROC_STATE_FILE_LOCK:?}"
|
||||||
|
trap 'unlock "${PROC_STATE_FILE_LOCK:?}"' RETURN
|
||||||
|
|
||||||
|
local entered=0
|
||||||
|
while read -r line; do
|
||||||
|
if [[ ${line} =~ ^${key}= ]]; then
|
||||||
|
printf '%s\n' "${key}=${value}"
|
||||||
|
entered=1
|
||||||
|
else
|
||||||
|
printf '%s\n' "${line}"
|
||||||
|
fi
|
||||||
|
done < "${PROC_STATE_FILE:?}" > "${PROC_STATE_FILE:?}.tmp"
|
||||||
|
if (( entered == 0 )); then
|
||||||
|
printf '%s\n' "${key}=${value}" >> "${PROC_STATE_FILE:?}.tmp"
|
||||||
|
fi
|
||||||
|
mv "${PROC_STATE_FILE:?}.tmp" "${PROC_STATE_FILE:?}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
_proc_man_get_key_value()
|
||||||
|
{
|
||||||
|
local key=${1}
|
||||||
|
|
||||||
|
lock "${PROC_STATE_FILE_LOCK:?}"
|
||||||
|
trap 'unlock "${PROC_STATE_FILE_LOCK:?}"' RETURN
|
||||||
|
|
||||||
|
while read -r line; do
|
||||||
|
if [[ ${line} =~ ^${key}= ]]; then
|
||||||
|
printf '%s\n' "${line#*=}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done < "${PROC_STATE_FILE:?}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_man()
|
||||||
|
{
|
||||||
|
local action=${1}
|
||||||
|
local name=${2}
|
||||||
|
shift 2
|
||||||
|
|
||||||
|
if [[ ! -f "${PROC_STATE_FILE:?}" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC2311
|
||||||
|
case "${action}" in
|
||||||
|
"start")
|
||||||
|
pid=$(_proc_man_get_key_value "${name}")
|
||||||
|
if (( pid && pid > 0 )) && kill -0 "${pid}" 2> /dev/null; then
|
||||||
|
return 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
"${@}" &
|
||||||
|
local pid=${!}
|
||||||
|
_proc_man_set_key "${name}" "${pid}"
|
||||||
|
;;
|
||||||
|
"stop")
|
||||||
|
local pid
|
||||||
|
pid=$(_proc_man_get_key_value "${name}")
|
||||||
|
if ! (( pid && pid > 0 )); then
|
||||||
|
return 0;
|
||||||
|
fi
|
||||||
|
|
||||||
|
kill "${pid}" 2> /dev/null || true
|
||||||
|
|
||||||
|
# wait for process to die
|
||||||
|
killed=0
|
||||||
|
for ((i=0; i<10; i++));
|
||||||
|
do
|
||||||
|
if kill -0 "${pid}" 2> /dev/null; then
|
||||||
|
sleep_us 100000
|
||||||
|
else
|
||||||
|
killed=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# if process still alive, kill it with fire
|
||||||
|
if (( killed == 0 )); then
|
||||||
|
kill -9 "${pid}" 2> /dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
_proc_man_set_key "${name}" "-1" "${PROC_STATE_FILE:?}"
|
||||||
|
;;
|
||||||
|
"status")
|
||||||
|
local pid
|
||||||
|
pid=$(_proc_man_get_key_value "${name}")
|
||||||
|
if (( pid && pid > 0 )); then
|
||||||
|
if kill -0 "${pid}" 2> /dev/null; then
|
||||||
|
printf '%s\n' "running"
|
||||||
|
else
|
||||||
|
printf '%s\n' "dead"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
printf '%s\n' "stopped"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
"wait")
|
||||||
|
local pid
|
||||||
|
pid=$(_proc_man_get_key_value "${name}")
|
||||||
|
if (( pid && pid > 0 )); then
|
||||||
|
wait "${pid}" && return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
"signal")
|
||||||
|
shift 3
|
||||||
|
|
||||||
|
local pid
|
||||||
|
pid=$(_proc_man_get_key_value "${name}")
|
||||||
|
if (( pid && pid > 0 )); then
|
||||||
|
kill -s "${1}" "${pid}" 2>/dev/null && return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
"initialize")
|
||||||
|
proc_man_initialize
|
||||||
|
return $?
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
printf '%s\n' "unknown action: ${action}" >&2
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_man_initialize()
|
||||||
|
{
|
||||||
|
true > "${PROC_STATE_FILE:?}"
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_man_start()
|
||||||
|
{
|
||||||
|
proc_man start "${@}"
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_man_stop()
|
||||||
|
{
|
||||||
|
proc_man stop "${@}"
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_man_status()
|
||||||
|
{
|
||||||
|
proc_man status "${@}"
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_man_wait()
|
||||||
|
{
|
||||||
|
proc_man wait "${@}"
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_man_signal()
|
||||||
|
{
|
||||||
|
proc_man signal "${@}"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (( __set_e == 1 )); then
|
||||||
|
set +e
|
||||||
|
fi
|
||||||
|
unset __set_e
|
213
luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh
Executable file
213
luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh
Executable file
|
@ -0,0 +1,213 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# cake-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and RTT
|
||||||
|
|
||||||
|
# cake-autorate_config.sh is a script that sets up defaults for cake-autorate
|
||||||
|
|
||||||
|
# Author: @Lynx (OpenWrt forum)
|
||||||
|
# Inspiration taken from: @moeller0 (OpenWrt forum)
|
||||||
|
|
||||||
|
INTERFACE=$(basename "$0" | cut -d. -f2)
|
||||||
|
|
||||||
|
cake_autorate_version="2.0.0"
|
||||||
|
|
||||||
|
# *** OUTPUT AND LOGGING OPTIONS ***
|
||||||
|
|
||||||
|
output_processing_stats=$(uci -q get sqm.${INTERFACE}.output_processing_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing processing stats
|
||||||
|
output_load_stats=$(uci -q get sqm.${INTERFACE}.output_load_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing achieved loads
|
||||||
|
output_reflector_stats=$(uci -q get sqm.${INTERFACE}.output_reflector_stats || echo '0') # enable (1) or disable (0) output monitoring lines showing reflector stats
|
||||||
|
output_cake_changes=$(uci -q get sqm.${INTERFACE}.output_cake_changes || echo '0') # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes
|
||||||
|
debug=$(uci -q get sqm.${INTERFACE}.debug || echo '0') # enable (1) or disable (0) out of debug lines
|
||||||
|
|
||||||
|
# This can generate a LOT of records so be careful:
|
||||||
|
log_DEBUG_messages_to_syslog=0 # enable (1) or disable (0) logging of all DEBUG records into the system log.
|
||||||
|
|
||||||
|
# ** Take care with these settings to ensure you won't run into OOM issues on your router ***
|
||||||
|
# every write the cumulative write time and bytes associated with each log line are checked
|
||||||
|
# and if either exceeds the configured values below, the log log file is rotated
|
||||||
|
log_to_file=1 # enable (1) or disable (0) output logging to file (/tmp/cake-autorate.log)
|
||||||
|
log_file_max_time_mins=10 # maximum time between log file rotations
|
||||||
|
log_file_max_size_KB=2000 # maximum KB (i.e. bytes/1024) worth of log lines between log file rotations
|
||||||
|
|
||||||
|
# log file path defaults to /var/log/
|
||||||
|
# or, if set below, then ${log_file_path_override}
|
||||||
|
log_file_path_override=""
|
||||||
|
|
||||||
|
# *** STANDARD CONFIGURATION OPTIONS ***
|
||||||
|
|
||||||
|
### For multihomed setups, it is the responsibility of the user to ensure that the probes
|
||||||
|
### sent by this instance of cake-autorate actually travel through these interfaces.
|
||||||
|
### See ping_extra_args and ping_prefix_string
|
||||||
|
|
||||||
|
dl_if=ifb4$(uci -q get sqm.${INTERFACE}.interface) # download interface
|
||||||
|
ul_if=$(uci -q get sqm.${INTERFACE}.interface) # upload interface
|
||||||
|
|
||||||
|
# pinger selection can be any of:
|
||||||
|
# fping - round robin pinging (rtts)
|
||||||
|
# ping - (iputils-ping) individual pinging (rtts)
|
||||||
|
# hping3 - individidual pinging (owds)
|
||||||
|
pinger_binary=ping
|
||||||
|
|
||||||
|
# list of reflectors to use and number of pingers to initiate
|
||||||
|
# pingers will be initiated with reflectors in the order specified in the list
|
||||||
|
# additional reflectors will be used to replace any reflectors that go stale
|
||||||
|
# so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially
|
||||||
|
# and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad
|
||||||
|
# a bad reflector will go to the back of the queue on reflector rotation
|
||||||
|
reflectors=($(uci -q get omr-tracker.defaults.hosts))
|
||||||
|
#reflectors=(
|
||||||
|
#"1.1.1.1" "1.0.0.1" # Cloudflare
|
||||||
|
#"8.8.8.8" "8.8.4.4" # Google
|
||||||
|
#"9.9.9.9" "9.9.9.10" "9.9.9.11" # Quad9
|
||||||
|
#"94.140.14.15" "94.140.14.140" "94.140.14.141" "94.140.15.15" "94.140.15.16" # AdGuard
|
||||||
|
#"64.6.65.6" "156.154.70.1" "156.154.70.2" "156.154.70.3" "156.154.70.4" "156.154.70.5" "156.154.71.1" "156.154.71.2" "156.154.71.3" "156.154.71.4" "156.154.71.5" # Neustar
|
||||||
|
#"208.67.220.2" "208.67.220.123" "208.67.220.220" "208.67.222.2" "208.67.222.123" # OpenDNS
|
||||||
|
#"185.228.168.9" "185.228.168.10" # CleanBrowsing
|
||||||
|
#)
|
||||||
|
|
||||||
|
randomize_reflectors=1 # enable (1) or disable (0) randomization of reflectors on startup
|
||||||
|
|
||||||
|
# Think carefully about the following settings
|
||||||
|
# to avoid excessive CPU use (proportional with ping interval / number of pingers)
|
||||||
|
# and to avoid abusive network activity (excessive ICMP frequency to one reflector)
|
||||||
|
# The author has found an ICMP rate of 1/(0.2/4) = 20 Hz to give satisfactory performance on 4G
|
||||||
|
no_pingers=$(uci -q get sqm.${INTERFACE}.no_pingers || echo "6") # number of pingers to maintain
|
||||||
|
reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_s || echo "0.3") # (seconds, e.g. 0.2s or 2s)
|
||||||
|
|
||||||
|
# delay threshold in ms is the extent of OWD increase to classify as a delay
|
||||||
|
# these are automatically adjusted based on maximum on the wire packet size
|
||||||
|
# (adjustment significant at sub 12Mbit/s rates, else negligible)
|
||||||
|
dl_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "30") # (milliseconds)
|
||||||
|
ul_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "30") # (milliseconds)
|
||||||
|
|
||||||
|
# Set either of the below to 0 to adjust one direction only
|
||||||
|
# or alternatively set both to 0 to simply use cake-autorate to monitor a connection
|
||||||
|
adjust_dl_shaper_rate=1 # enable (1) or disable (0) actually changing the dl shaper rate
|
||||||
|
adjust_ul_shaper_rate=1 # enable (1) or disable (0) actually changing the ul shaper rate
|
||||||
|
|
||||||
|
min_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.min_download || echo "5000") # minimum bandwidth for download (Kbit/s)
|
||||||
|
base_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.download || echo "40000") # steady state bandwidth for download (Kbit/s)
|
||||||
|
max_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.max_download || echo "80000") # maximum bandwidth for download (Kbit/s)
|
||||||
|
|
||||||
|
min_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.min_upload || echo "5000") # minimum bandwidth for upload (Kbit/s)
|
||||||
|
base_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.upload || echo "20000") # steady state bandwidth for upload (KBit/s)
|
||||||
|
max_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.max_upload || echo "35000") # maximum bandwidth for upload (Kbit/s)
|
||||||
|
|
||||||
|
# sleep functionality saves unecessary pings and CPU cycles by
|
||||||
|
# pausing all active pingers when connection is not in active use
|
||||||
|
enable_sleep_function=$(uci -q get sqm.${INTERFACE}.enable_sleep_functions || echo "1") # enable (1) or disable (0) sleep functonality
|
||||||
|
connection_active_thr_kbps=$(uci -q get sqm.${INTERFACE}.connection_active_thr_kpbs || echo "1000") # threshold in Kbit/s below which dl/ul is considered idle
|
||||||
|
sustained_idle_sleep_thr_s=$(uci -q get sqm.${INTERFACE}.sustained_idle_sleep_thr || echo "60.0") # time threshold to put pingers to sleep on sustained dl/ul achieved rate < idle_thr (seconds)
|
||||||
|
|
||||||
|
min_shaper_rates_enforcement=$(uci -q get sqm.${INTERFACE}.min_shaper_rates_enforcement || echo "0") # enable (1) or disable (0) dropping down to minimum shaper rates on connection idle or stall
|
||||||
|
|
||||||
|
startup_wait_s=$(uci -q get sqm.${INTERFACE}.startup_wait_s || echo "60.0") # number of seconds to wait on startup (e.g. to wait for things to settle on router reboot)
|
||||||
|
|
||||||
|
# *** ADVANCED CONFIGURATION OPTIONS ***
|
||||||
|
|
||||||
|
log_file_export_compress=1 # compress log file exports using gzip and append .gz to export filename
|
||||||
|
|
||||||
|
### In multi-homed setups, it is mandatory to use either ping_extra_args
|
||||||
|
### or ping_prefix_string to direct the pings through $dl_if and $ul_if.
|
||||||
|
### No universal recommendation exists, because there are multiple
|
||||||
|
### policy-routing packages available (e.g. vpn-policy-routing and mwan3).
|
||||||
|
### Typically they either react to a firewall mark set on the pings, or
|
||||||
|
### provide a convenient wrapper.
|
||||||
|
###
|
||||||
|
### In a traditional single-homed setup, there is usually no need for these parameters.
|
||||||
|
###
|
||||||
|
### These arguments can also be used for any other purpose - e.g. for setting a
|
||||||
|
### particular QoS mark.
|
||||||
|
|
||||||
|
# extra arguments for ping or fping
|
||||||
|
# e.g., here is how you can set the correct outgoing interface and
|
||||||
|
# the firewall mark for ping:
|
||||||
|
# ping_extra_args="-I wwan0 -m $((0x300))"
|
||||||
|
# Unfortunately, fping does not offer a command line switch to set
|
||||||
|
# the firewall mark.
|
||||||
|
# WARNING: no error checking so use at own risk!
|
||||||
|
ping_extra_args="- B -I ${INTERFACE}"
|
||||||
|
|
||||||
|
# a wrapper for ping binary - used as a prefix for the real command
|
||||||
|
# e.g., when using mwan3, it is recommended to set it like this:
|
||||||
|
# ping_prefix_string="mwan3 use gpon exec"
|
||||||
|
# WARNING: the wrapper must exec ping as the final step, not run it as a subprocess.
|
||||||
|
# Running ping or fping as a subprocess will lead to problems stopping it.
|
||||||
|
# WARNING: no error checking - so use at own risk!
|
||||||
|
ping_prefix_string=""
|
||||||
|
# interval in ms for monitoring achieved rx/tx rates
|
||||||
|
# this is automatically adjusted based on maximum on the wire packet size
|
||||||
|
# (adjustment significant at sub 12Mbit/s rates, else negligible)
|
||||||
|
monitor_achieved_rates_interval_ms=200 # (milliseconds)
|
||||||
|
|
||||||
|
# bufferbloat is detected when (bufferbloat_detection_thr) samples
|
||||||
|
# out of the last (bufferbloat detection window) samples are delayed
|
||||||
|
bufferbloat_detection_window=6 # number of samples to retain in detection window
|
||||||
|
bufferbloat_detection_thr=3 # number of delayed samples for bufferbloat detection
|
||||||
|
|
||||||
|
# OWD baseline against which to measure delays
|
||||||
|
# the idea is that the baseline is allowed to increase slowly to allow for path changes
|
||||||
|
# and slowly enough such that bufferbloat will be corrected well before the baseline increases,
|
||||||
|
# but it will decrease very rapidly to ensure delays are measured against the shortest path
|
||||||
|
alpha_baseline_increase=0.001 # how rapidly baseline RTT is allowed to increase
|
||||||
|
alpha_baseline_decrease=0.9 # how rapidly baseline RTT is allowed to decrease
|
||||||
|
|
||||||
|
# OWD delta from baseline is tracked using ewma with alpha set below
|
||||||
|
alpha_delta_ewma=0.095
|
||||||
|
|
||||||
|
# rate adjustment parameters
|
||||||
|
# bufferbloat adjustment works with the lower of the adjusted achieved rate and adjusted shaper rate
|
||||||
|
# to exploit that transfer rates during bufferbloat provide an indication of line capacity
|
||||||
|
# otherwise shaper rate is adjusted up on load high, and down on load idle or low
|
||||||
|
achieved_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce achieved rate upon detection of bufferbloat
|
||||||
|
shaper_rate_adjust_down_bufferbloat=0.9 # how rapidly to reduce shaper rate upon detection of bufferbloat
|
||||||
|
shaper_rate_adjust_up_load_high=1.01 # how rapidly to increase shaper rate upon high load detected
|
||||||
|
shaper_rate_adjust_down_load_low=0.99 # how rapidly to return down to base shaper rate upon idle or low load detected
|
||||||
|
shaper_rate_adjust_up_load_low=1.01 # how rapidly to return up to base shaper rate upon idle or low load detected
|
||||||
|
|
||||||
|
# the load is categoried as low if < high_load_thr and high if > high_load_thr relative to the current shaper rate
|
||||||
|
high_load_thr=0.75 # % of currently set bandwidth for detecting high load
|
||||||
|
|
||||||
|
# refractory periods between successive bufferbloat/decay rate changes
|
||||||
|
# the bufferbloat refractory period should be greater than the
|
||||||
|
# average time it would take to replace the bufferbloat
|
||||||
|
# detection window with new samples upon a bufferbloat event
|
||||||
|
bufferbloat_refractory_period_ms=300 # (milliseconds)
|
||||||
|
decay_refractory_period_ms=1000 # (milliseconds)
|
||||||
|
|
||||||
|
# interval for checking reflector health
|
||||||
|
reflector_health_check_interval_s=1.0 # (seconds)
|
||||||
|
# deadline for reflector response not to be classified as an offence against reflector
|
||||||
|
reflector_response_deadline_s=1.0 # (seconds)
|
||||||
|
|
||||||
|
# reflector misbehaving is detected when $reflector_misbehaving_detection_thr samples
|
||||||
|
# out of the last (reflector misbehaving detection window) samples are offences
|
||||||
|
# thus with a 1s interval, window 60 and detection_thr 3, this is tantamount to
|
||||||
|
# 3 offences within the last 60s
|
||||||
|
reflector_misbehaving_detection_window=60
|
||||||
|
reflector_misbehaving_detection_thr=3
|
||||||
|
|
||||||
|
reflector_replacement_interval_mins=60 # how often to replace a random reflector from the present list
|
||||||
|
|
||||||
|
reflector_comparison_interval_mins=1 # how often to compare reflectors
|
||||||
|
reflector_owd_baseline_delta_thr_ms=10 # max increase from min baseline before reflector rotated
|
||||||
|
reflector_owd_delta_ewma_delta_thr_ms=10 # mac increase from min delta ewma before reflector rotated
|
||||||
|
|
||||||
|
# stall is detected when the following two conditions are met:
|
||||||
|
# 1) no reflector responses within $stall_detection_thr*$ping_response_interval_us; and
|
||||||
|
# 2) either $rx_achieved_rate or $tx_achieved_rate < $connection_stall_thr
|
||||||
|
stall_detection_thr=5
|
||||||
|
connection_stall_thr_kbps=10
|
||||||
|
|
||||||
|
global_ping_response_timeout_s=10.0 # timeout to set shaper rates to min on no ping response whatsoever (seconds)
|
||||||
|
|
||||||
|
if_up_check_interval_s=10.0 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state or sleep recovery)
|
||||||
|
|
||||||
|
# Starlink satellite switch (sss) compensation options
|
||||||
|
sss_compensation=$(uci -q get sqm.${INTERFACE}.sss_compensation || echo "0") # enable (1) or disable (0) Starlink handling
|
||||||
|
# satellite switch compensation start times in seconds of each minute
|
||||||
|
sss_times_s=("12.0" "27.0" "42.0" "57.0")
|
||||||
|
sss_compensation_pre_duration_ms=300
|
||||||
|
sss_compensation_post_duration_ms=200
|
||||||
|
|
||||||
|
config_file_check="cake-autorate"
|
32
luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh
Normal file → Executable file
32
luci-app-sqm-autorate/root/usr/share/sqm-autorate/config.sh
Normal file → Executable file
|
@ -19,7 +19,8 @@ output_processing_stats=$(uci -q get sqm.${INTERFACE}.output_processing_stats ||
|
||||||
#output_cake_changes=0 # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes
|
#output_cake_changes=0 # enable (1) or disable (0) output monitoring lines showing cake bandwidth changes
|
||||||
output_cake_changes=$(uci -q get sqm.${INTERFACE}.output_cake_changes || echo "0")
|
output_cake_changes=$(uci -q get sqm.${INTERFACE}.output_cake_changes || echo "0")
|
||||||
#debug=0 # enable (1) or disable (0) out of debug lines
|
#debug=0 # enable (1) or disable (0) out of debug lines
|
||||||
debug=$(uci -q get sqm.common.debug || echo "0")
|
#debug=$(uci -q get sqm.common.debug || echo "0")
|
||||||
|
debug=1
|
||||||
|
|
||||||
# *** STANDARD CONFIGURATION OPTIONS ***
|
# *** STANDARD CONFIGURATION OPTIONS ***
|
||||||
|
|
||||||
|
@ -128,32 +129,3 @@ global_ping_response_timeout_s=10 # timeout to set shaper rates to min on no pin
|
||||||
|
|
||||||
if_up_check_interval_s=10 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state)
|
if_up_check_interval_s=10 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state)
|
||||||
|
|
||||||
# verify these are correct using 'cat /sys/class/...'
|
|
||||||
case "${dl_if}" in
|
|
||||||
\veth*)
|
|
||||||
rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes"
|
|
||||||
;;
|
|
||||||
\ifb*)
|
|
||||||
rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
rx_bytes_path="/sys/class/net/${dl_if}/statistics/rx_bytes"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
case "${ul_if}" in
|
|
||||||
\veth*)
|
|
||||||
tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes"
|
|
||||||
;;
|
|
||||||
\ifb*)
|
|
||||||
tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
tx_bytes_path="/sys/class/net/${ul_if}/statistics/tx_bytes"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if (( $debug )) ; then
|
|
||||||
echo "DEBUG: rx_bytes_path: $rx_bytes_path"
|
|
||||||
echo "DEBUG: tx_bytes_path: $tx_bytes_path"
|
|
||||||
fi
|
|
||||||
|
|
|
@ -1010,6 +1010,7 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om
|
||||||
uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY"
|
uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY"
|
||||||
#if [ "$(uci -q get glorytun.vpn.enable)" != "1" ] || [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then
|
#if [ "$(uci -q get glorytun.vpn.enable)" != "1" ] || [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then
|
||||||
OMR_NETWORK_DEVICE=$(find_network_device ${OMR_TRACKER_INTERFACE})
|
OMR_NETWORK_DEVICE=$(find_network_device ${OMR_TRACKER_INTERFACE})
|
||||||
|
#_log "OMR_NETWORK_DEVICE: $OMR_NETWORK_DEVICE for $OMR_TRACKER_DEVICE - $OMR_TRACKER_INTERFACE"
|
||||||
if [ -n "$OMR_NETWORK_DEVICE" ] && [ -n "$(uci -q get network.$OMR_NETWORK_DEVICE.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then
|
if [ -n "$OMR_NETWORK_DEVICE" ] && [ -n "$(uci -q get network.$OMR_NETWORK_DEVICE.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then
|
||||||
mtu=$(uci -q get network.$OMR_NETWORK_DEVICE.mtu)
|
mtu=$(uci -q get network.$OMR_NETWORK_DEVICE.mtu)
|
||||||
uci -q set openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu=$mtu
|
uci -q set openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu=$mtu
|
||||||
|
@ -1751,7 +1752,7 @@ if [ "$(pgrep -f openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprout
|
||||||
sleep 5
|
sleep 5
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.enabled)" = "1" ] && [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ] && [ -z $(pgrep -f "autorate.sh ${OMR_TRACKER_INTERFACE}") ]; then
|
if [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.enabled)" = "1" ] && [ "$(uci -q get sqm.${OMR_TRACKER_INTERFACE}.autorate)" = "1" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -z $(pgrep -f "autorate.*${OMR_TRACKER_DEVICE}") ]; then
|
||||||
/etc/init.d/sqm-autorate restart >/dev/null 2>&1
|
/etc/init.d/sqm-autorate restart >/dev/null 2>&1
|
||||||
sleep 5
|
sleep 5
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Reference in a new issue