mirror of
https://github.com/Ysurac/openmptcprouter-feeds.git
synced 2025-03-09 15:40:03 +00:00
Update sqm autorate
This commit is contained in:
parent
8b270e7264
commit
ecf0b89798
6 changed files with 407 additions and 253 deletions
|
@ -31,14 +31,14 @@ _config_autorate() {
|
|||
[ "${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
|
||||
cp /usr/share/sqm-autorate/cake-autorate_template.sh /usr/share/sqm-autorate/cake-autorate_config.$1.sh
|
||||
cp /usr/share/sqm-autorate/config_template.sh /usr/share/sqm-autorate/config.$1.sh
|
||||
}
|
||||
|
||||
_launch_autorate() {
|
||||
logger -t "SQM-autorate" "Launch..."
|
||||
procd_open_instance
|
||||
# shellcheck disable=SC2086
|
||||
procd_set_param command /usr/share/sqm-autorate/cake-autorate_launcher.sh
|
||||
procd_set_param command /usr/share/sqm-autorate/launcher.sh
|
||||
procd_set_param limits nofile="51200 51200"
|
||||
procd_set_param respawn 0 10 0
|
||||
procd_set_param stderr 1
|
||||
|
@ -46,16 +46,12 @@ _launch_autorate() {
|
|||
}
|
||||
|
||||
start_service() {
|
||||
rm -f /usr/share/sqm-autorate/config.*.sh
|
||||
config_load sqm
|
||||
config_foreach _config_autorate queue
|
||||
_launch_autorate
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
rm -f /usr/share/sqm-autorate/cake-autorate_config.*.sh
|
||||
pkill -9 cake-autorate
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
stop
|
||||
start
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
#!/bin/bash
|
||||
|
||||
# CAKE-autorate automatically adjusts CAKE bandwidth(s)
|
||||
# cake-autorate automatically adjusts CAKE bandwidth(s)
|
||||
# in dependence on: a) receive and transmit transfer rates; and b) latency
|
||||
# (or can just be used to monitor and log transfer rates and latency)
|
||||
|
||||
# requires packages: bash; and one of the supported ping binaries
|
||||
# requires: bash; and one of the supported ping binaries
|
||||
|
||||
# each cake-autorate instance must be configured using a corresponding config file
|
||||
|
||||
# Project homepage: https://github.com/lynxthecat/cake-autorate
|
||||
# Licence details: https://github.com/lynxthecat/cake-autorate/blob/master/LICENCE.md
|
||||
|
||||
# Author: @Lynx (OpenWrt forum)
|
||||
# Inspiration taken from: @moeller0 (OpenWrt forum)
|
||||
# Author and maintainer: lynxthecat
|
||||
# Contributors: rany2; moeller0; richb-hanover
|
||||
|
||||
cake_autorate_version="2.0.0"
|
||||
|
||||
## cake-autorate uses multiple asynchronous processes including
|
||||
## cake-autorate uses multiple asynchronous processes including:
|
||||
## main - main process
|
||||
## monitor_achieved_rates - monitor network transfer rates
|
||||
## maintain_pingers - manage pingers and active reflectors
|
||||
|
@ -26,7 +26,7 @@ cake_autorate_version="2.0.0"
|
|||
##
|
||||
## IPC is facilitated via FIFOs in the form of anonymous pipes
|
||||
## accessible via fds in the form: ${process_name_fd}
|
||||
## thereby to enable transferring commands and data between processes
|
||||
## thereby to enable transferring instructions and data between processes
|
||||
|
||||
# Initialize file descriptors
|
||||
## -1 signifies that the log file fd will not be used and
|
||||
|
@ -60,15 +60,20 @@ export LC_ALL=C
|
|||
# Set PREFIX
|
||||
PREFIX=/root/cake-autorate
|
||||
|
||||
# shellcheck source=cake-autorate_lib.sh
|
||||
. "${PREFIX}/cake-autorate_lib.sh"
|
||||
# shellcheck source=cake-autorate_defaults.sh
|
||||
. "${PREFIX}/cake-autorate_defaults.sh"
|
||||
# shellcheck source=lib.sh
|
||||
. "${PREFIX}/lib.sh"
|
||||
# shellcheck source=defaults.sh
|
||||
. "${PREFIX}/defaults.sh"
|
||||
# get valid config overrides
|
||||
mapfile -t valid_config_entries < <(grep -E '^[^(#| )].*=' "${PREFIX}/defaults.sh" | sed -e 's/[\t ]*\#.*//g' -e 's/=.*//g')
|
||||
|
||||
trap cleanup_and_killall INT TERM EXIT
|
||||
|
||||
cleanup_and_killall()
|
||||
{
|
||||
# Do not fail on error for this critical cleanup code
|
||||
set +e
|
||||
|
||||
trap true INT TERM EXIT
|
||||
|
||||
log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}"
|
||||
|
@ -88,13 +93,19 @@ cleanup_and_killall()
|
|||
|
||||
# terminate any processes that remain, save for main and intercept_stderr
|
||||
unset "proc_pids[main]"
|
||||
intercept_stderr_pid="${proc_pids[intercept_stderr]}"
|
||||
intercept_stderr_pid="${proc_pids[intercept_stderr]:-}"
|
||||
if [[ -n "${intercept_stderr_pid}" ]]
|
||||
then
|
||||
unset "proc_pids[intercept_stderr]"
|
||||
fi
|
||||
terminate "${proc_pids[@]}"
|
||||
|
||||
# restore original stderr, and terminate intercept_stderr
|
||||
if [[ -n "${intercept_stderr_pid}" ]]
|
||||
then
|
||||
exec 2>&"${original_stderr_fd}"
|
||||
terminate "${intercept_stderr_pid}"
|
||||
fi
|
||||
|
||||
log_msg "SYSLOG" "Stopped cake-autorate with PID: ${BASHPID} and config: ${config_path}"
|
||||
|
||||
|
@ -109,33 +120,31 @@ log_msg()
|
|||
local type="${1}"
|
||||
local msg="${2}"
|
||||
local instance_id="${instance_id:-"unknown"}"
|
||||
local log_timestamp=${EPOCHREALTIME}
|
||||
|
||||
case ${type} in
|
||||
|
||||
DEBUG)
|
||||
[[ "${debug}" == "0" ]] && return # skip over DEBUG messages where debug disabled
|
||||
log_timestamp=${EPOCHREALTIME}
|
||||
((debug == 0)) && return # skip over DEBUG messages where debug disabled
|
||||
((log_DEBUG_messages_to_syslog)) && ((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}"
|
||||
;;
|
||||
|
||||
ERROR)
|
||||
log_timestamp=${EPOCHREALTIME}
|
||||
((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}"
|
||||
;;
|
||||
|
||||
SYSLOG)
|
||||
log_timestamp=${EPOCHREALTIME}
|
||||
((use_logger)) && logger -t "cake-autorate.${instance_id}" "INFO: ${log_timestamp} ${msg}"
|
||||
;;
|
||||
|
||||
*)
|
||||
log_timestamp=${EPOCHREALTIME}
|
||||
;;
|
||||
esac
|
||||
|
||||
# Output to the log file fifo if available (for rotation handling)
|
||||
# else output directly to the log file
|
||||
if (( log_fd >= 0 )); then
|
||||
if (( log_fd >= 0 ))
|
||||
then
|
||||
((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >&"${log_fd}"
|
||||
else
|
||||
((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >> "${log_file_path}"
|
||||
|
@ -211,7 +220,8 @@ generate_log_file_scripts()
|
|||
while [[ ! -f "${run_path}/last_log_file_export" ]]
|
||||
do
|
||||
sleep 1
|
||||
if (( ++read_try >= \${timeout_s} )); then
|
||||
if (( ++read_try >= \${timeout_s} ))
|
||||
then
|
||||
printf "ERROR: Timeout (\${timeout_s}s) reached before new log file export identified.\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
@ -249,16 +259,19 @@ export_log_file()
|
|||
log_msg "DEBUG" "Exporting log file with path: ${log_file_path/.log/_${log_file_export_datetime}.log}"
|
||||
|
||||
# Now export with or without compression to the appropriate export path
|
||||
if ((log_file_export_compress)); then
|
||||
if ((log_file_export_compress))
|
||||
then
|
||||
log_file_export_path="${log_file_export_path}.gz"
|
||||
if [[ -f "${log_file_path}.old" ]]; then
|
||||
if [[ -f "${log_file_path}.old" ]]
|
||||
then
|
||||
gzip -c "${log_file_path}.old" > "${log_file_export_path}"
|
||||
gzip -c "${log_file_path}" >> "${log_file_export_path}"
|
||||
else
|
||||
gzip -c "${log_file_path}" > "${log_file_export_path}"
|
||||
fi
|
||||
else
|
||||
if [[ -f "${log_file_path}.old" ]]; then
|
||||
if [[ -f "${log_file_path}.old" ]]
|
||||
then
|
||||
cp "${log_file_path}.old" "${log_file_export_path}"
|
||||
cat "${log_file_path}" >> "${log_file_export_path}"
|
||||
else
|
||||
|
@ -272,8 +285,9 @@ export_log_file()
|
|||
flush_log_fd()
|
||||
{
|
||||
log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}"
|
||||
while read -r -t 0.01 -u "${log_fd}" log_line
|
||||
while read -r -t 0 -u "${log_fd}"
|
||||
do
|
||||
read -r -u "${log_fd}" log_line
|
||||
printf '%s\n' "${log_line}" >> "${log_file_path}"
|
||||
done
|
||||
}
|
||||
|
@ -342,7 +356,7 @@ maintain_log_file()
|
|||
done
|
||||
}
|
||||
|
||||
get_next_shaper_rate()
|
||||
update_shaper_rate()
|
||||
{
|
||||
local direction="${1}" # 'dl' or 'ul'
|
||||
|
||||
|
@ -358,7 +372,8 @@ get_next_shaper_rate()
|
|||
;;
|
||||
# bufferbloat detected, so decrease the rate providing not inside bufferbloat refractory period
|
||||
*bb*)
|
||||
if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )); then
|
||||
if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) ))
|
||||
then
|
||||
adjusted_achieved_rate_kbps=$(( (achieved_rate_kbps["${direction}"]*achieved_rate_adjust_down_bufferbloat)/1000 ))
|
||||
adjusted_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_bufferbloat)/1000 ))
|
||||
shaper_rate_kbps["${direction}"]=$(( adjusted_achieved_rate_kbps > min_shaper_rate_kbps["${direction}"] && adjusted_achieved_rate_kbps < adjusted_shaper_rate_kbps ? adjusted_achieved_rate_kbps : adjusted_shaper_rate_kbps ))
|
||||
|
@ -367,18 +382,22 @@ get_next_shaper_rate()
|
|||
;;
|
||||
# high load, so increase rate providing not inside bufferbloat refractory period
|
||||
*high*)
|
||||
if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )); then
|
||||
if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) ))
|
||||
then
|
||||
shaper_rate_kbps["${direction}"]=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_high)/1000 ))
|
||||
fi
|
||||
;;
|
||||
# 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_start_us > (t_last_decay_us["${direction}"]+decay_refractory_period_us) )); then
|
||||
if (( t_start_us > (t_last_decay_us["${direction}"]+decay_refractory_period_us) ))
|
||||
then
|
||||
|
||||
if ((shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"])); then
|
||||
if ((shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"]))
|
||||
then
|
||||
decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_load_low)/1000 ))
|
||||
shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps > base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"]))
|
||||
elif ((shaper_rate_kbps["${direction}"] < base_shaper_rate_kbps["${direction}"])); then
|
||||
elif ((shaper_rate_kbps["${direction}"] < base_shaper_rate_kbps["${direction}"]))
|
||||
then
|
||||
decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_low)/1000 ))
|
||||
shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps < base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"]))
|
||||
fi
|
||||
|
@ -387,7 +406,7 @@ get_next_shaper_rate()
|
|||
fi
|
||||
;;
|
||||
*)
|
||||
log_msg "ERROR" "unknown load condition: ${load_condition[${direction}]} in get_next_shaper_rate"
|
||||
log_msg "ERROR" "unknown load condition: ${load_condition[${direction}]} in update_shaper_rate"
|
||||
kill $$ 2>/dev/null
|
||||
;;
|
||||
esac
|
||||
|
@ -431,13 +450,13 @@ monitor_achieved_rates()
|
|||
case "${command[0]:-}" in
|
||||
|
||||
SET_VAR)
|
||||
if [[ "${command[1]:-}" && "${command[2]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 3 ]]
|
||||
then
|
||||
export -n "${command[1]}=${command[2]}"
|
||||
fi
|
||||
;;
|
||||
SET_ARRAY_ELEMENT)
|
||||
if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 4 ]]
|
||||
then
|
||||
declare -A "${command[1]}"+="([${command[2]}]=${command[3]})"
|
||||
fi
|
||||
|
@ -457,8 +476,8 @@ monitor_achieved_rates()
|
|||
[[ -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}"
|
||||
|
||||
achieved_rate_kbps[dl]=$(( ((8000*(rx_bytes - prev_rx_bytes)) / compensated_monitor_achieved_rates_interval_us ) ))
|
||||
achieved_rate_kbps[ul]=$(( ((8000*(tx_bytes - prev_tx_bytes)) / compensated_monitor_achieved_rates_interval_us ) ))
|
||||
achieved_rate_kbps[dl]=$(( (8000*(rx_bytes - prev_rx_bytes)) / compensated_monitor_achieved_rates_interval_us ))
|
||||
achieved_rate_kbps[ul]=$(( (8000*(tx_bytes - prev_tx_bytes)) / compensated_monitor_achieved_rates_interval_us ))
|
||||
|
||||
((achieved_rate_kbps[dl]<0)) && achieved_rate_kbps[dl]=0
|
||||
((achieved_rate_kbps[ul]<0)) && achieved_rate_kbps[ul]=0
|
||||
|
@ -475,7 +494,8 @@ monitor_achieved_rates()
|
|||
printf "SET_ARRAY_ELEMENT load_percent ul %s\n" "${load_percent[ul]}" >&"${pinger_fd}"
|
||||
done
|
||||
|
||||
if ((output_load_stats)); then
|
||||
if ((output_load_stats))
|
||||
then
|
||||
|
||||
printf -v load_stats '%s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}"
|
||||
log_msg "LOAD" "${load_stats}"
|
||||
|
@ -498,9 +518,11 @@ classify_load()
|
|||
# thus ending up with high_delayed, low_delayed, etc.
|
||||
local direction="${1}"
|
||||
|
||||
if (( load_percent["${direction}"] > high_load_thr_percent )); then
|
||||
if (( load_percent["${direction}"] > high_load_thr_percent ))
|
||||
then
|
||||
load_condition["${direction}"]="high"
|
||||
elif (( achieved_rate_kbps["${direction}"] > connection_active_thr_kbps )); then
|
||||
elif (( achieved_rate_kbps["${direction}"] > connection_active_thr_kbps ))
|
||||
then
|
||||
load_condition["${direction}"]="low"
|
||||
else
|
||||
load_condition["${direction}"]="idle"
|
||||
|
@ -508,12 +530,14 @@ classify_load()
|
|||
|
||||
((bufferbloat_detected["${direction}"])) && load_condition["${direction}"]="${load_condition[${direction}]}_bb"
|
||||
|
||||
if ((sss_compensation)); then
|
||||
if ((sss_compensation))
|
||||
then
|
||||
# shellcheck disable=SC2154
|
||||
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
|
||||
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["${direction}"]="${load_condition[${direction}]}_sss"
|
||||
break
|
||||
fi
|
||||
|
@ -609,7 +633,7 @@ parse_tsping()
|
|||
|
||||
SET_VAR)
|
||||
|
||||
if [[ "${command[1]:-}" && "${command[2]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 3 ]]
|
||||
then
|
||||
export -n "${command[1]}=${command[2]}"
|
||||
fi
|
||||
|
@ -618,7 +642,7 @@ parse_tsping()
|
|||
|
||||
SET_ARRAY_ELEMENT)
|
||||
|
||||
if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 4 ]]
|
||||
then
|
||||
declare -A "${command[1]}"+="([${command[2]}]=${command[3]})"
|
||||
fi
|
||||
|
@ -781,7 +805,7 @@ parse_fping()
|
|||
|
||||
SET_VAR)
|
||||
|
||||
if [[ "${command[1]:-}" && "${command[2]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 3 ]]
|
||||
then
|
||||
export -n "${command[1]}=${command[2]}"
|
||||
fi
|
||||
|
@ -790,7 +814,7 @@ parse_fping()
|
|||
|
||||
SET_ARRAY_ELEMENT)
|
||||
|
||||
if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 4 ]]
|
||||
then
|
||||
declare -A "${command[1]}"+="([${command[2]}]=${command[3]})"
|
||||
fi
|
||||
|
@ -914,7 +938,7 @@ parse_ping()
|
|||
|
||||
SET_REFLECTOR)
|
||||
|
||||
if [[ "${command[1]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 2 ]]
|
||||
then
|
||||
reflector="${command[1]}"
|
||||
log_msg "DEBUG" "Read in new reflector: ${reflector}"
|
||||
|
@ -928,7 +952,7 @@ parse_ping()
|
|||
|
||||
SET_VAR)
|
||||
|
||||
if [[ "${command[1]:-}" && "${command[2]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 3 ]]
|
||||
then
|
||||
export -n "${command[1]}=${command[2]}"
|
||||
fi
|
||||
|
@ -937,7 +961,7 @@ parse_ping()
|
|||
|
||||
SET_ARRAY_ELEMENT)
|
||||
|
||||
if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 4 ]]
|
||||
then
|
||||
declare -A "${command[1]}"+="([${command[2]}]=${command[3]})"
|
||||
fi
|
||||
|
@ -1034,8 +1058,8 @@ start_pinger()
|
|||
|
||||
start_pingers()
|
||||
{
|
||||
# Initiate pingers
|
||||
log_msg "DEBUG" "Starting pingers."
|
||||
log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}"
|
||||
|
||||
case ${pinger_binary} in
|
||||
|
||||
tsping|fping)
|
||||
|
@ -1079,7 +1103,6 @@ kill_pinger()
|
|||
;;
|
||||
|
||||
*)
|
||||
:
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -1088,6 +1111,8 @@ kill_pinger()
|
|||
|
||||
kill_pingers()
|
||||
{
|
||||
log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}"
|
||||
|
||||
case "${pinger_binary}" in
|
||||
|
||||
tsping|fping)
|
||||
|
@ -1121,7 +1146,8 @@ replace_pinger_reflector()
|
|||
|
||||
log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}"
|
||||
|
||||
if ((no_reflectors > no_pingers)); then
|
||||
if ((no_reflectors > no_pingers))
|
||||
then
|
||||
log_msg "DEBUG" "replacing reflector: ${reflectors[pinger]} with ${reflectors[no_pingers]}."
|
||||
kill_pinger "${pinger}"
|
||||
bad_reflector=${reflectors[pinger]}
|
||||
|
@ -1198,13 +1224,14 @@ change_state_maintain_pingers()
|
|||
|
||||
START|STOP|PAUSED|RUNNING)
|
||||
|
||||
if [[ "${maintain_pingers_state}" != "${maintain_pingers_next_state}" ]]
|
||||
if [[ "${maintain_pingers_state}" == "${maintain_pingers_next_state}" ]]
|
||||
then
|
||||
log_msg "ERROR" "Received request to change maintain_pingers state to existing state."
|
||||
return
|
||||
fi
|
||||
|
||||
log_msg "DEBUG" "Changing maintain_pingers state from: ${maintain_pingers_state} to: ${maintain_pingers_next_state}"
|
||||
maintain_pingers_state=${maintain_pingers_next_state}
|
||||
else
|
||||
log_msg "ERROR" "Received request to change maintain_pingers state to existing state."
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
|
@ -1292,7 +1319,7 @@ maintain_pingers()
|
|||
case "${command[0]:-}" in
|
||||
|
||||
CHANGE_STATE)
|
||||
if [[ "${command[1]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 2 ]]
|
||||
then
|
||||
change_state_maintain_pingers "${command[1]}"
|
||||
# break out of reading any new IPC commands to handle next state
|
||||
|
@ -1308,13 +1335,13 @@ maintain_pingers()
|
|||
fi
|
||||
;;
|
||||
SET_ARRAY_ELEMENT)
|
||||
if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 4 ]]
|
||||
then
|
||||
declare -A "${command[1]}"+="([${command[2]}]=${command[3]})"
|
||||
fi
|
||||
;;
|
||||
SET_VAR)
|
||||
if [[ "${command[1]:-}" && "${command[2]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 3 ]]
|
||||
then
|
||||
export -n "${command[1]}=${command[2]}"
|
||||
fi
|
||||
|
@ -1363,7 +1390,8 @@ maintain_pingers()
|
|||
continue
|
||||
fi
|
||||
|
||||
if (( t_start_us>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) )); then
|
||||
if (( t_start_us>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) ))
|
||||
then
|
||||
|
||||
t_last_reflector_comparison_us=${EPOCHREALTIME/./}
|
||||
|
||||
|
@ -1431,16 +1459,19 @@ maintain_pingers()
|
|||
# shellcheck disable=SC2154
|
||||
reflector_offences[reflector_offences_idx]=$(( (${EPOCHREALTIME/./}-last_timestamp_reflectors_us[${reflectors[pinger]}]) > reflector_response_deadline_us ? 1 : 0 ))
|
||||
|
||||
if (( reflector_offences[reflector_offences_idx] )); then
|
||||
if (( reflector_offences[reflector_offences_idx] ))
|
||||
then
|
||||
((sum_reflector_offences[pinger]++))
|
||||
log_msg "DEBUG" "no ping response from reflector: ${reflectors[pinger]} within reflector_response_deadline: ${reflector_response_deadline_s}s"
|
||||
log_msg "DEBUG" "reflector=${reflectors[pinger]}, sum_reflector_offences=${sum_reflector_offences[pinger]} and reflector_misbehaving_detection_thr=${reflector_misbehaving_detection_thr}"
|
||||
fi
|
||||
|
||||
if (( sum_reflector_offences[pinger] >= reflector_misbehaving_detection_thr )); then
|
||||
if (( sum_reflector_offences[pinger] >= reflector_misbehaving_detection_thr ))
|
||||
then
|
||||
|
||||
log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} seems to be misbehaving."
|
||||
if ((replace_pinger_reflector_enabled)); then
|
||||
if ((replace_pinger_reflector_enabled))
|
||||
then
|
||||
replace_pinger_reflector "${pinger}"
|
||||
replace_pinger_reflector_enabled=0
|
||||
else
|
||||
|
@ -1462,38 +1493,25 @@ maintain_pingers()
|
|||
done
|
||||
}
|
||||
|
||||
set_cake_rate()
|
||||
set_shaper_rate()
|
||||
{
|
||||
local interface="${1}"
|
||||
local shaper_rate_kbps="${2}"
|
||||
local adjust_shaper_rate="${3}"
|
||||
# fire up tc and update max_wire_packet_compensation if there are rates to change for the given direction
|
||||
|
||||
((output_cake_changes)) && log_msg "SHAPER" "tc qdisc change root dev ${interface} cake bandwidth ${shaper_rate_kbps}Kbit"
|
||||
local direction="${1}" # 'dl' or 'ul'
|
||||
|
||||
if ((adjust_shaper_rate)); then
|
||||
|
||||
tc qdisc change root dev "${interface}" cake bandwidth "${shaper_rate_kbps}Kbit" 2> /dev/null
|
||||
if (( shaper_rate_kbps["${direction}"] != last_shaper_rate_kbps["${direction}"] ))
|
||||
then
|
||||
((output_cake_changes)) && log_msg "SHAPER" "tc qdisc change root dev ${interface[${direction}]} cake bandwidth ${shaper_rate_kbps[${direction}]}Kbit"
|
||||
|
||||
if ((adjust_shaper_rate["${direction}"]))
|
||||
then
|
||||
tc qdisc change root dev "${interface[${direction}]}" cake bandwidth "${shaper_rate_kbps[${direction}]}Kbit" 2> /dev/null
|
||||
else
|
||||
((output_cake_changes)) && log_msg "DEBUG" "adjust_shaper_rate set to 0 in config, so skipping the tc qdisc change call"
|
||||
((output_cake_changes)) && log_msg "DEBUG" "adjust_${direction}_shaper_rate set to 0 in config, so skipping the corresponding tc qdisc change call."
|
||||
fi
|
||||
}
|
||||
|
||||
set_shaper_rates()
|
||||
{
|
||||
if (( shaper_rate_kbps[dl] != last_shaper_rate_kbps[dl] || shaper_rate_kbps[ul] != last_shaper_rate_kbps[ul] )); 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
|
||||
if (( shaper_rate_kbps[dl] != last_shaper_rate_kbps[dl] )); then
|
||||
set_cake_rate "${dl_if}" "${shaper_rate_kbps[dl]}" adjust_dl_shaper_rate
|
||||
printf "SET_ARRAY_ELEMENT shaper_rate_kbps dl %s\n" "${shaper_rate_kbps[dl]}" >&"${monitor_achieved_rates_fd}"
|
||||
last_shaper_rate_kbps[dl]="${shaper_rate_kbps[dl]}"
|
||||
fi
|
||||
if (( shaper_rate_kbps[ul] != last_shaper_rate_kbps[ul] )); then
|
||||
set_cake_rate "${ul_if}" "${shaper_rate_kbps[ul]}" adjust_ul_shaper_rate
|
||||
printf "SET_ARRAY_ELEMENT shaper_rate_kbps ul %s\n" "${shaper_rate_kbps[ul]}" >&"${monitor_achieved_rates_fd}"
|
||||
last_shaper_rate_kbps[ul]="${shaper_rate_kbps[ul]}"
|
||||
fi
|
||||
printf "SET_ARRAY_ELEMENT shaper_rate_kbps ${direction} %s\n" "${shaper_rate_kbps[${direction}]}" >&"${monitor_achieved_rates_fd}"
|
||||
last_shaper_rate_kbps["${direction}"]="${shaper_rate_kbps[${direction}]}"
|
||||
|
||||
update_max_wire_packet_compensation
|
||||
fi
|
||||
|
@ -1504,7 +1522,8 @@ set_min_shaper_rates()
|
|||
log_msg "DEBUG" "Enforcing minimum shaper rates."
|
||||
shaper_rate_kbps[dl]=${min_dl_shaper_rate_kbps}
|
||||
shaper_rate_kbps[ul]=${min_ul_shaper_rate_kbps}
|
||||
set_shaper_rates
|
||||
set_shaper_rate "dl"
|
||||
set_shaper_rate "ul"
|
||||
}
|
||||
|
||||
get_max_wire_packet_size_bits()
|
||||
|
@ -1564,6 +1583,8 @@ change_state_main()
|
|||
{
|
||||
local main_next_state="${1}"
|
||||
|
||||
log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}"
|
||||
|
||||
case ${main_next_state} in
|
||||
|
||||
RUNNING|IDLE|STALL)
|
||||
|
@ -1624,7 +1645,8 @@ debug_cmd()
|
|||
|
||||
err_type="ERROR"
|
||||
|
||||
if ((err_silence)); then
|
||||
if ((err_silence))
|
||||
then
|
||||
err_type="DEBUG"
|
||||
fi
|
||||
|
||||
|
@ -1633,7 +1655,8 @@ debug_cmd()
|
|||
|
||||
caller_id=$(caller)
|
||||
|
||||
if ((ret==0)); then
|
||||
if ((ret==0))
|
||||
then
|
||||
log_msg "DEBUG" "debug_cmd: err_silence=${err_silence}; debug_msg=${debug_msg}; caller_id=${caller_id}; command=${cmd} ${args[*]}; result=SUCCESS"
|
||||
else
|
||||
[[ "${err_type}" == "DEBUG" && "${debug}" == "0" ]] && return # if debug disabled, then skip on DEBUG but not on ERROR
|
||||
|
@ -1650,6 +1673,52 @@ debug_cmd()
|
|||
fi
|
||||
}
|
||||
|
||||
# shellcheck disable=SC1090,SC2311
|
||||
validate_config_entry() {
|
||||
# Must be called before loading config_path into the global scope.
|
||||
#
|
||||
# When the entry is invalid, two types are returned with the first type
|
||||
# being the invalid user type and second type is the default type with
|
||||
# the user needing to adapt the config file so that the entry uses the
|
||||
# default type.
|
||||
#
|
||||
# When the entry is valid, one type is returned and it will be the
|
||||
# the type of either the default or user type. However because in that
|
||||
# case they are both valid. It doesn't matter as they'd both have the
|
||||
# same type.
|
||||
|
||||
local config_path="${1}"
|
||||
|
||||
local user_type
|
||||
local valid_type
|
||||
|
||||
user_type=$(unset "${2}" && . "${config_path}" && typeof "${2}")
|
||||
valid_type=$(typeof "${2}")
|
||||
|
||||
if [[ "${user_type}" != "${valid_type}" ]]
|
||||
then
|
||||
printf '%s' "${user_type} ${valid_type}"
|
||||
return
|
||||
elif [[ "${user_type}" != "string" ]]
|
||||
then
|
||||
printf '%s' "${valid_type}"
|
||||
return
|
||||
fi
|
||||
|
||||
# extra validation for string, check for empty string
|
||||
local -n default_value=${2}
|
||||
local user_value
|
||||
user_value=$(. "${config_path}" && local -n x="${2}" && printf '%s' "${x}")
|
||||
|
||||
# if user is empty but default is not, invalid entry
|
||||
if [[ -z "${user_value}" && -n "${default_value}" ]]
|
||||
then
|
||||
printf '%s' "${user_type} ${valid_type}"
|
||||
else
|
||||
printf '%s' "${valid_type}"
|
||||
fi
|
||||
}
|
||||
|
||||
# ======= Start of the Main Routine ========
|
||||
|
||||
[[ -t 1 ]] && terminal=1 || terminal=0
|
||||
|
@ -1663,35 +1732,78 @@ log_file_path=/var/log/cake-autorate.log
|
|||
run_path=/var/run/cake-autorate/
|
||||
|
||||
# cake-autorate first argument is config file path
|
||||
if [[ -n ${1-} ]]; then
|
||||
if [[ -n "${1-}" ]]
|
||||
then
|
||||
config_path="${1}"
|
||||
else
|
||||
config_path="${PREFIX}/cake-autorate_config.primary.sh"
|
||||
config_path="${PREFIX}/config.primary.sh"
|
||||
fi
|
||||
|
||||
if [[ ! -f "${config_path}" ]]; then
|
||||
if [[ ! -f "${config_path}" ]]
|
||||
then
|
||||
log_msg "ERROR" "No config file found. Exiting now."
|
||||
exit
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# shellcheck source=cake-autorate_config.primary.sh
|
||||
# validate config entries before loading
|
||||
mapfile -t user_config < <(grep -E '^[^(#| )].*=' "${config_path}" | sed -e 's/[\t ]*\#.*//g' -e 's/=.*//g')
|
||||
config_error_count=0
|
||||
for key in "${user_config[@]}"
|
||||
do
|
||||
# Despite the fact that config_file_check is no longer required,
|
||||
# we make an exemption just in this case as that variable in
|
||||
# particular does not have any real impact to the operation
|
||||
# of the script.
|
||||
[[ "${key}" == "config_file_check" ]] && continue
|
||||
|
||||
# shellcheck disable=SC2076
|
||||
if [[ ! " ${valid_config_entries[*]} " =~ " ${key} " ]]
|
||||
then
|
||||
((config_error_count++))
|
||||
log_msg "ERROR" "The key: '${key}' in config file: '${config_path}' is not a valid config entry."
|
||||
else
|
||||
# shellcheck disable=SC2311
|
||||
read -r user supposed <<< "$(validate_config_entry "${config_path}" "${key}")"
|
||||
if [[ -n "${supposed}" ]]
|
||||
then
|
||||
error_msg="The value of '${key}' in config file: '${config_path}' is not a valid value of type: '${supposed}'."
|
||||
|
||||
case "${user}" in
|
||||
negative-*) error_msg="${error_msg} Also, negative numbers are not supported." ;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
log_msg "ERROR" "${error_msg}"
|
||||
unset error_msg
|
||||
|
||||
((config_error_count++))
|
||||
fi
|
||||
unset user supposed
|
||||
fi
|
||||
done
|
||||
if ((config_error_count))
|
||||
then
|
||||
log_msg "ERROR" "The config file: '${config_path}' contains ${config_error_count} error(s). Exiting now."
|
||||
exit 1
|
||||
fi
|
||||
unset valid_config_entries user_config config_error_count key
|
||||
|
||||
# shellcheck source=config.primary.sh
|
||||
. "${config_path}"
|
||||
|
||||
if [[ ${config_file_check} != "cake-autorate" ]]; then
|
||||
log_msg "ERROR" "Config file error. Please check config file entries."
|
||||
exit
|
||||
fi
|
||||
|
||||
if [[ ${config_path} =~ cake-autorate_config\.(.*)\.sh ]]; then
|
||||
instance_id=${BASH_REMATCH[1]}
|
||||
run_path=/var/run/cake-autorate/${instance_id}
|
||||
if [[ ${config_path} =~ config\.(.*)\.sh ]]
|
||||
then
|
||||
instance_id="${BASH_REMATCH[1]}"
|
||||
run_path="/var/run/cake-autorate/${instance_id}"
|
||||
else
|
||||
log_msg "ERROR" "Instance identifier 'X' set by cake-autorate_config.X.sh cannot be empty. Exiting now."
|
||||
exit
|
||||
log_msg "ERROR" "Instance identifier 'X' set by config.X.sh cannot be empty. Exiting now."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -n "${log_file_path_override-}" ]]; then
|
||||
if [[ ! -d ${log_file_path_override} ]]; then
|
||||
if [[ -n "${log_file_path_override-}" ]]
|
||||
then
|
||||
if [[ ! -d ${log_file_path_override} ]]
|
||||
then
|
||||
broken_log_file_path_override=${log_file_path_override}
|
||||
log_file_path=/var/log/cake-autorate${instance_id:+.${instance_id}}.log
|
||||
log_msg "ERROR" "Log file path override: '${broken_log_file_path_override}' does not exist. Exiting now."
|
||||
|
@ -1714,7 +1826,8 @@ log_msg "SYSLOG" "Starting cake-autorate with PID: ${BASHPID} and config: ${conf
|
|||
|
||||
# ${run_path}/ is used to store temporary files
|
||||
# it should not exist on startup so if it does exit, else create the directory
|
||||
if [[ -d "${run_path}" ]]; then
|
||||
if [[ -d "${run_path}" ]]
|
||||
then
|
||||
if [[ -f "${run_path}/proc_pids" ]] && running_main_pid=$(awk -F= '/^main=/ {print $2}' "${run_path}/proc_pids") && [[ -d "/proc/${running_main_pid}" ]]
|
||||
then
|
||||
log_msg "ERROR" "${run_path} already exists and an instance appears to be running with main process pid ${running_main_pid}. Exiting script."
|
||||
|
@ -1747,7 +1860,8 @@ command -v "${pinger_binary}" &> /dev/null || { log_msg "ERROR" "ping binary ${p
|
|||
|
||||
# Passed error checks
|
||||
|
||||
if ((log_to_file)); then
|
||||
if ((log_to_file))
|
||||
then
|
||||
log_file_max_time_us=$((log_file_max_time_mins*60000000))
|
||||
log_file_max_size_bytes=$((log_file_max_size_KB*1024))
|
||||
exec {log_fd}<> <(:)
|
||||
|
@ -1756,13 +1870,15 @@ if ((log_to_file)); then
|
|||
fi
|
||||
|
||||
# test if stdout is a tty (terminal)
|
||||
if ! ((terminal)); then
|
||||
if ! ((terminal))
|
||||
then
|
||||
echo "stdout not a terminal so redirecting output to: ${log_file_path}"
|
||||
((log_to_file)) && exec 1>&"${log_fd}"
|
||||
fi
|
||||
|
||||
# Initialize rx_bytes_path and tx_bytes_path if not set
|
||||
if [[ -z "${rx_bytes_path-}" ]]; then
|
||||
if [[ -z "${rx_bytes_path-}" ]]
|
||||
then
|
||||
case "${dl_if}" in
|
||||
veth*)
|
||||
rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes"
|
||||
|
@ -1775,7 +1891,8 @@ if [[ -z "${rx_bytes_path-}" ]]; then
|
|||
;;
|
||||
esac
|
||||
fi
|
||||
if [[ -z "${tx_bytes_path-}" ]]; then
|
||||
if [[ -z "${tx_bytes_path-}" ]]
|
||||
then
|
||||
case "${ul_if}" in
|
||||
veth*)
|
||||
tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes"
|
||||
|
@ -1789,7 +1906,8 @@ if [[ -z "${tx_bytes_path-}" ]]; then
|
|||
esac
|
||||
fi
|
||||
|
||||
if ((debug)) ; then
|
||||
if ((debug))
|
||||
then
|
||||
log_msg "DEBUG" "CAKE-autorate version: ${cake_autorate_version}"
|
||||
log_msg "DEBUG" "config_path: ${config_path}"
|
||||
log_msg "DEBUG" "run_path: ${run_path}"
|
||||
|
@ -1856,6 +1974,8 @@ declare -A last_shaper_rate_kbps
|
|||
declare -A base_shaper_rate_kbps
|
||||
declare -A min_shaper_rate_kbps
|
||||
declare -A max_shaper_rate_kbps
|
||||
declare -A interface
|
||||
declare -A adjust_shaper_rate
|
||||
|
||||
base_shaper_rate_kbps[dl]="${base_dl_shaper_rate_kbps}"
|
||||
base_shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}"
|
||||
|
@ -1872,10 +1992,19 @@ shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}"
|
|||
last_shaper_rate_kbps[dl]=0
|
||||
last_shaper_rate_kbps[ul]=0
|
||||
|
||||
interface[dl]="${dl_if}"
|
||||
interface[ul]="${ul_if}"
|
||||
|
||||
adjust_shaper_rate[dl]="${adjust_dl_shaper_rate}"
|
||||
adjust_shaper_rate[ul]="${adjust_ul_shaper_rate}"
|
||||
|
||||
dl_max_wire_packet_size_bits=0
|
||||
ul_max_wire_packet_size_bits=0
|
||||
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_shaper_rates
|
||||
set_shaper_rate "dl"
|
||||
set_shaper_rate "ul"
|
||||
|
||||
update_max_wire_packet_compensation
|
||||
|
||||
|
@ -1899,13 +2028,16 @@ delays_idx=0
|
|||
sum_dl_delays=0
|
||||
sum_ul_delays=0
|
||||
|
||||
if ((debug)); then
|
||||
if (( bufferbloat_refractory_period_us < (bufferbloat_detection_window*ping_response_interval_us) )); then
|
||||
if ((debug))
|
||||
then
|
||||
if (( bufferbloat_refractory_period_us < (bufferbloat_detection_window*ping_response_interval_us) ))
|
||||
then
|
||||
log_msg "DEBUG" "Warning: bufferbloat refractory period: ${bufferbloat_refractory_period_us} us."
|
||||
log_msg "DEBUG" "Warning: but expected time to overwrite samples in bufferbloat detection window is: $((bufferbloat_detection_window*ping_response_interval_us)) us."
|
||||
log_msg "DEBUG" "Warning: Consider increasing bufferbloat refractory period or decreasing bufferbloat detection window."
|
||||
fi
|
||||
if (( reflector_response_deadline_us < 2*reflector_ping_interval_us )); then
|
||||
if (( reflector_response_deadline_us < 2*reflector_ping_interval_us ))
|
||||
then
|
||||
log_msg "DEBUG" "Warning: reflector_response_deadline_s < 2*reflector_ping_interval_s"
|
||||
log_msg "DEBUG" "Warning: consider setting an increased reflector_response_deadline."
|
||||
fi
|
||||
|
@ -1915,7 +2047,8 @@ fi
|
|||
((randomize_reflectors)) && randomize_array reflectors
|
||||
|
||||
# Wait if ${startup_wait_s} > 0
|
||||
if ((startup_wait_us>0)); then
|
||||
if ((startup_wait_us>0))
|
||||
then
|
||||
log_msg "DEBUG" "Waiting ${startup_wait_s} seconds before startup."
|
||||
sleep_us "${startup_wait_us}"
|
||||
fi
|
||||
|
@ -1925,6 +2058,7 @@ case "${pinger_binary}" in
|
|||
tsping|fping)
|
||||
exec {pinger_fds[0]}<> <(:)
|
||||
;;
|
||||
|
||||
ping)
|
||||
for ((pinger=0; pinger<=no_pingers; pinger++))
|
||||
do
|
||||
|
@ -1934,7 +2068,7 @@ case "${pinger_binary}" in
|
|||
|
||||
*)
|
||||
log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}"
|
||||
kill $$ 2>/dev/null
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -1964,19 +2098,19 @@ do
|
|||
;;
|
||||
|
||||
SET_VAR)
|
||||
if [[ ${command[1]:-} && ${command[2]:-} ]]
|
||||
if [[ "${#command[@]}" -eq 3 ]]
|
||||
then
|
||||
export -n "${command[1]}=${command[2]}"
|
||||
fi
|
||||
;;
|
||||
SET_ARRAY_ELEMENT)
|
||||
if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 4 ]]
|
||||
then
|
||||
declare -A "${command[1]}"+="([${command[2]}]=${command[3]})"
|
||||
fi
|
||||
;;
|
||||
SET_PROC_PID)
|
||||
if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]]
|
||||
if [[ "${#command[@]}" -eq 4 ]]
|
||||
then
|
||||
declare -A "${command[1]}"+="([${command[2]}]=${command[3]})"
|
||||
fi
|
||||
|
@ -2002,7 +2136,8 @@ do
|
|||
|
||||
reflectors_last_timestamp_us="${timestamp//[.]}"
|
||||
|
||||
if (( (t_start_us - 10#"${reflectors_last_timestamp_us}")>500000 )); then
|
||||
if (( (t_start_us - 10#"${reflectors_last_timestamp_us}")>500000 ))
|
||||
then
|
||||
log_msg "DEBUG" "processed response from [${reflector}] that is > 500ms old. Skipping."
|
||||
continue
|
||||
fi
|
||||
|
@ -2028,19 +2163,23 @@ do
|
|||
classify_load "dl"
|
||||
classify_load "ul"
|
||||
|
||||
get_next_shaper_rate "dl"
|
||||
get_next_shaper_rate "ul"
|
||||
update_shaper_rate "dl"
|
||||
update_shaper_rate "ul"
|
||||
|
||||
set_shaper_rates
|
||||
set_shaper_rate "dl"
|
||||
set_shaper_rate "ul"
|
||||
|
||||
if (( output_processing_stats )); then
|
||||
if (( output_processing_stats ))
|
||||
then
|
||||
printf -v processing_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${load_percent[dl]}" "${load_percent[ul]}" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${compensated_dl_delay_thr_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" "${compensated_ul_delay_thr_us}" "${sum_dl_delays}" "${sum_ul_delays}" "${load_condition[dl]}" "${load_condition[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}"
|
||||
log_msg "DATA" "${processing_stats}"
|
||||
fi
|
||||
|
||||
# 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 [[ ${load_condition[dl]} == *idle* && ${load_condition[ul]} == *idle* ]]; then
|
||||
if (( enable_sleep_function ))
|
||||
then
|
||||
if [[ ${load_condition[dl]} == *idle* && ${load_condition[ul]} == *idle* ]]
|
||||
then
|
||||
((t_sustained_connection_idle_us += (${EPOCHREALTIME/./}-t_end_us) ))
|
||||
if ((t_sustained_connection_idle_us > sustained_idle_sleep_thr_us))
|
||||
then
|
||||
|
@ -2124,7 +2263,7 @@ do
|
|||
*)
|
||||
|
||||
log_msg "ERROR" "Unrecognized main state: ${main_state}. Exiting now."
|
||||
kill $$ 2>/dev/null
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
INTERFACE=$(basename "$1" | cut -d. -f2)
|
||||
|
||||
cake_autorate_version="2.0.0"
|
||||
#cake_autorate_version="2.0.0"
|
||||
|
||||
# *** OUTPUT AND LOGGING OPTIONS ***
|
||||
|
||||
|
@ -46,7 +46,7 @@ ul_if=$(uci -q get sqm.${INTERFACE}.interface) # upload interface
|
|||
# fping - round robin pinging (rtts)
|
||||
# ping - (iputils-ping) individual pinging (rtts)
|
||||
# hping3 - individidual pinging (owds)
|
||||
pinger_binary=tsping
|
||||
pinger_binary=$(uci -q get sqm.${INTERFACE}.pinger || echo 'tsping')
|
||||
|
||||
# list of reflectors to use and number of pingers to initiate
|
||||
# pingers will be initiated with reflectors in the order specified in the list
|
||||
|
@ -77,12 +77,8 @@ reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_
|
|||
# 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)
|
||||
latency=$(uci -q get sqm.${INTERFACE}.delay_thr_ms)
|
||||
[ -z "$latency" ] && latency="$(($(ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | cut -d '.' -f1 | tr -d '\n' 2>/dev/null)+30))"
|
||||
[ -z "$latency" ] && latency="100"
|
||||
logger -t "sqm" "latency $INTERFACE: $latency"
|
||||
dl_delay_thr_ms="$latency" # (milliseconds)
|
||||
ul_delay_thr_ms="$latency" # (milliseconds)
|
||||
dl_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms) || $(($(ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | cut -d '.' -f1 | tr -d '\n' 2>/dev/null)+30)) || echo 100 # (milliseconds)
|
||||
ul_delay_thr_ms=${dl_delay_thr_ms}
|
||||
|
||||
# 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
|
||||
|
@ -195,7 +191,7 @@ 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_sum_owd_baseline_delta_thr_ms=30 # max increase from min sum owd baselines before reflector rotated
|
||||
#reflector_sum_owd_baseline_delta_thr_ms=30 # max increase from min sum owd baselines 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:
|
|
@ -7,6 +7,8 @@
|
|||
# Author: @Lynx (OpenWrt forum)
|
||||
# Inspiration taken from: @moeller0 (OpenWrt forum)
|
||||
|
||||
INTERFACE=""
|
||||
|
||||
# *** OUTPUT AND LOGGING OPTIONS ***
|
||||
|
||||
output_processing_stats=1 # enable (1) or disable (0) output monitoring lines showing processing stats
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
cake_instances=(/usr/share/sqm-autorate/cake-autorate_config*sh)
|
||||
cake_instances=(/root/cake-autorate/config.*.sh)
|
||||
cake_instance_pids=()
|
||||
|
||||
trap kill_cake_instances INT TERM EXIT
|
||||
|
@ -20,7 +20,7 @@ kill_cake_instances()
|
|||
|
||||
for cake_instance in "${cake_instances[@]}"
|
||||
do
|
||||
/usr/share/sqm-autorate/cake-autorate.sh "${cake_instance}" &
|
||||
/root/cake-autorate/cake-autorate.sh "${cake_instance}" &
|
||||
cake_instance_pids+=(${!})
|
||||
done
|
||||
wait
|
|
@ -1,14 +1,63 @@
|
|||
#!/bin/bash
|
||||
# cake-autorate_lib.sh -- common functions for use by cake-autorate.sh
|
||||
|
||||
# lib.sh -- common functions for use by cake-autorate.sh
|
||||
#
|
||||
# This file is part of cake-autorate.
|
||||
|
||||
__set_e=0
|
||||
if [[ ! ${-} =~ e ]]; then
|
||||
if [[ ! ${-} =~ e ]]
|
||||
then
|
||||
set -e
|
||||
__set_e=1
|
||||
fi
|
||||
|
||||
exec {__sleep_fd}<> <(:) || true
|
||||
if [[ -z "${__sleep_fd:-}" ]]
|
||||
then
|
||||
exec {__sleep_fd}<> <(:)
|
||||
fi
|
||||
|
||||
typeof() {
|
||||
# typeof -- returns the type of a variable
|
||||
|
||||
local type_sig
|
||||
type_sig=$(declare -p "${1}" 2>/dev/null)
|
||||
if [[ "${type_sig}" =~ "declare --" ]]
|
||||
then
|
||||
str_type "${1}"
|
||||
elif [[ "${type_sig}" =~ "declare -a" ]]
|
||||
then
|
||||
printf "array"
|
||||
elif [[ "${type_sig}" =~ "declare -A" ]]
|
||||
then
|
||||
printf "map"
|
||||
else
|
||||
printf "none"
|
||||
fi
|
||||
}
|
||||
|
||||
str_type() {
|
||||
# str_type -- returns the type of a string
|
||||
|
||||
local -n str="${1}"
|
||||
|
||||
if [[ "${str}" =~ ^[0-9]+$ ]]
|
||||
then
|
||||
printf "integer"
|
||||
elif [[ "${str}" =~ ^[0-9]*\.[0-9]+$ ]]
|
||||
then
|
||||
printf "float"
|
||||
elif [[ "${str}" =~ ^-[0-9]+$ ]]
|
||||
then
|
||||
printf "negative-integer"
|
||||
elif [[ "${str}" =~ ^-[0-9]*\.[0-9]+$ ]]
|
||||
then
|
||||
printf "negative-float"
|
||||
else
|
||||
# technically not validated, user is just trusted to call
|
||||
# this function with valid strings
|
||||
printf "string"
|
||||
fi
|
||||
}
|
||||
|
||||
sleep_s()
|
||||
{
|
||||
|
@ -25,7 +74,7 @@ sleep_s()
|
|||
# - 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}" || :
|
||||
read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || true
|
||||
}
|
||||
|
||||
sleep_us()
|
||||
|
@ -52,21 +101,10 @@ sleep_remaining_tick_time()
|
|||
fi
|
||||
}
|
||||
|
||||
get_remaining_tick_time()
|
||||
{
|
||||
# updates sleep_duration_s remaining to end of tick duration
|
||||
|
||||
local t_start_us=${1} # (microseconds)
|
||||
local tick_duration_us=${2} # (microseconds)
|
||||
|
||||
sleep_duration_us=$(( t_start_us + tick_duration_us - ${EPOCHREALTIME/./} ))
|
||||
((sleep_duration_us<0)) && sleep_duration_us=0
|
||||
sleep_duration_s=000000${sleep_duration_us}
|
||||
sleep_duration_s=$((10#${sleep_duration_s::-6})).${sleep_duration_s: -6}
|
||||
}
|
||||
|
||||
randomize_array()
|
||||
{
|
||||
# randomize the order of the elements of an array
|
||||
|
||||
local -n array=${1}
|
||||
|
||||
subset=("${array[@]}")
|
||||
|
@ -80,23 +118,6 @@ randomize_array()
|
|||
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:?}"
|
||||
}
|
||||
|
||||
terminate()
|
||||
{
|
||||
# Send regular kill to processes and monitor terminations;
|
||||
|
@ -121,8 +142,8 @@ terminate()
|
|||
kill -9 "${pids[@]}" 2> /dev/null
|
||||
}
|
||||
|
||||
|
||||
if (( __set_e == 1 )); then
|
||||
if (( __set_e == 1 ))
|
||||
then
|
||||
set +e
|
||||
fi
|
||||
unset __set_e
|
Loading…
Add table
Add a link
Reference in a new issue