mirror of
				https://github.com/Ysurac/openmptcprouter-feeds.git
				synced 2025-03-09 15:40:03 +00:00 
			
		
		
		
	Merge branch 'develop' of https://github.com/Ysurac/openmptcprouter-feeds into test
This commit is contained in:
		
						commit
						f1d947c0be
					
				
					 36 changed files with 2617 additions and 11 deletions
				
			
		
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,131 +0,0 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| # config.sh sets up defaults for CAKE-autorate | ||||
| 
 | ||||
| # config.sh is a part of CAKE-autorate | ||||
| # CAKE-autorate automatically adjusts bandwidth for CAKE in dependence on detected load and RTT | ||||
| 
 | ||||
| # Author: @Lynx (OpenWrt forum) | ||||
| # Inspiration taken from: @moeller0 (OpenWrt forum) | ||||
| # Modified by Ycarus (Yannick Chabanois) for OpenMPTCProuter: | ||||
| #  * Get configuration via uci | ||||
| 
 | ||||
| INTERFACE=$1 | ||||
| 
 | ||||
| # *** OUTPUT OPTIONS *** | ||||
| 
 | ||||
| #output_processing_stats=1 # enable (1) or disable (0) output monitoring lines showing processing stats | ||||
| output_processing_stats=$(uci -q get sqm.${INTERFACE}.output_processing_stats || echo "0") | ||||
| #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") | ||||
| #debug=0			  # enable (1) or disable (0) out of debug lines | ||||
| #debug=$(uci -q get sqm.common.debug || echo "0") | ||||
| debug=1 | ||||
| 
 | ||||
| # *** STANDARD CONFIGURATION OPTIONS *** | ||||
| 
 | ||||
| #dl_if=ifb4eth1 # download interface | ||||
| #dl_if=$(uci -q get sqm.${INTERFACE}.download_interface) | ||||
| dl_if=ifb4$(uci -q get sqm.${INTERFACE}.interface) | ||||
| #ul_if=eth1        # upload interface | ||||
| #ul_if=$(uci -q get sqm.${INTERFACE}.upload_interface) | ||||
| ul_if=$(uci -q get sqm.${INTERFACE}.interface) | ||||
| 
 | ||||
| #reflector_ping_interval_s=0.2 # (seconds, e.g. 0.2s or 2s) | ||||
| reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_s || echo "0.2") | ||||
| 
 | ||||
| # 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" "8.8.8.8" "8.8.4.4" "9.9.9.9" "9.9.9.10") | ||||
| reflectors=($(uci get omr-tracker.defaults.hosts)) | ||||
| no_pingers=$(uci -q get sqm.${INTERFACE}.no_pingers || echo "4") | ||||
| 
 | ||||
| # delay threshold in ms is the extent of RTT increase to classify as a delay | ||||
| # this is automatically adjusted based on maximum on the wire packet size | ||||
| # (adjustment significant at sub 12Mbit/s rates, else negligible)   | ||||
| #delay_thr_ms=25 # (milliseconds) | ||||
| delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo "25") | ||||
| 
 | ||||
| #min_dl_shaper_rate_kbps=10000  # minimum bandwidth for download (Kbit/s) | ||||
| min_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.min_download) | ||||
| #base_dl_shaper_rate_kbps=100000 # steady state bandwidth for download (Kbit/s) | ||||
| base_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.download) | ||||
| #max_dl_shaper_rate_kbps=200000  # maximum bandwidth for download (Kbit/s) | ||||
| max_dl_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.max_download) | ||||
| 
 | ||||
| #min_ul_shaper_rate_kbps=10000  # minimum bandwidth for upload (Kbit/s) | ||||
| min_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.min_upload) | ||||
| #base_ul_shaper_rate_kbps=100000 # steady state bandwidth for upload (KBit/s) | ||||
| base_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.upload) | ||||
| #max_ul_shaper_rate_kbps=200000  # maximum bandwidth for upload (Kbit/s) | ||||
| max_ul_shaper_rate_kbps=$(uci -q get sqm.${INTERFACE}.max_upload) | ||||
| 
 | ||||
| # 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  | ||||
| enable_sleep_function=$(uci -q get sqm.${INTERFACE}.enable_sleep_functions || echo "1") | ||||
| #connection_active_thr_kbps=500 # threshold in Kbit/s below which dl/ul is considered idle | ||||
| connection_active_thr_kbps=$(uci -q get sqm.${INTERFACE}.connection_active_thr_kbps || echo "500") | ||||
| #sustained_idle_sleep_thr_s=60  # time threshold to put pingers to sleep on sustained dl/ul achieved rate < idle_thr (seconds) | ||||
| sustained_idle_sleep_thr_s=$(uci -q get sqm.${INTERFACE}.substained_idle_sleep_thr_s || echo "60") | ||||
| 
 | ||||
| #startup_wait_s=0 # number of seconds to wait on startup (e.g. to wait for things to settle on router reboot) | ||||
| startup_wait_s=$(uci -q get sqm.${INTERFACE}.startup_wait_s || echo "60") | ||||
| 
 | ||||
| # *** ADVANCED CONFIGURATION OPTIONS *** | ||||
| 
 | ||||
| # 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=100 # (milliseconds)  | ||||
| 
 | ||||
| # bufferbloat is detected when (bufferbloat_detection_thr) samples | ||||
| # out of the last (bufferbloat detection window) samples are delayed | ||||
| bufferbloat_detection_window=4  # number of samples to retain in detection window | ||||
| bufferbloat_detection_thr=2     # number of delayed samples for bufferbloat detection | ||||
| 
 | ||||
| # RTT 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 | ||||
| 
 | ||||
| # 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 | ||||
| # and held the same on load medium | ||||
| achieved_rate_adjust_bufferbloat=0.9 # how rapidly to reduce achieved rate upon detection of bufferbloat  | ||||
| shaper_rate_adjust_bufferbloat=0.9   # how rapidly to reduce shaper rate upon detection of bufferbloat  | ||||
| shaper_rate_adjust_load_high=1.01    # how rapidly to increase shaper rate upon high load detected  | ||||
| shaper_rate_adjust_load_low=0.98     # how rapidly to return to base shaper rate upon idle or low load detected  | ||||
| 
 | ||||
| # the load is categoried as low if < medium_load_thr, medium if > medium_load_thr and high if > high_load_thr relative to the current shaper rate | ||||
| medium_load_thr=0.25 # % of currently set bandwidth for detecting medium load | ||||
| high_load_thr=0.75   # % of currently set bandwidth for detecting high load | ||||
| 
 | ||||
| # refractory periods between successive bufferbloat/decay rate changes | ||||
| bufferbloat_refractory_period_ms=300 # (milliseconds) | ||||
| decay_refractory_period_ms=1000 # (milliseconds) | ||||
| 
 | ||||
| # interval for checking reflector health | ||||
| reflector_health_check_interval_s=1 # (seconds) | ||||
| # deadline for reflector response not to be classified as an offence against reflector | ||||
| reflector_response_deadline_s=1 # (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 | ||||
| 
 | ||||
| global_ping_response_timeout_s=10 # timeout to set shaper rates to min on no ping response whatsoever (seconds) | ||||
| 
 | ||||
| if_up_check_interval_s=10 # time to wait before re-checking if rx/tx bytes files exist (e.g. from boot state) | ||||
| 
 | ||||
|  | @ -1,219 +0,0 @@ | |||
| #!/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 "$1" | 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_summary_stats=1										# enable (1) or disable (0) output monitoring lines showing summary 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=10000  # 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=$(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  | ||||
| # 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 "4")					# number of pingers to maintain | ||||
| reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_s || echo "0.5")	# (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) | ||||
| #logger -t "sqm-autorate" "ping for ${INTERFACE} (${ul_if}): $(echo $(/sbin/uci -q get sqm.${INTERFACE}.delay_thr_ms || echo '100'))" | ||||
| dl_owd_delta_thr_ms=$(echo $(echo $(uci -q get sqm.${INTERFACE}.delay_thr_ms || echo $(($(/usr/bin/ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | tr -d '\n' 2>/dev/null)+30)) || echo "100")) + "0.1" | bc)  # (milliseconds) | ||||
| ul_owd_delta_thr_ms=${dl_owd_delta_thr_ms} | ||||
| 
 | ||||
| # average owd delta threshold in ms at which maximum adjust_down_bufferbloat is applied | ||||
| # set value(s) to 0 to disable and always apply maximum adjust_down_bufferbloat | ||||
| dl_avg_owd_delta_thr_ms=$(echo "$dl_owd_delta_thr_ms * 2" | bc) # (milliseconds) | ||||
| ul_avg_owd_delta_thr_ms=$(echo "$ul_owd_delta_thr_ms * 2" | bc) # (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 "150.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 "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="-B -I ${INTERFACE}" | ||||
| ping_extra_args="-i ${ul_if} -e" | ||||
| 
 | ||||
| # 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 | ||||
| #shaper_rate_adjust_down_bufferbloat=0.75   # 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=2000 # (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=2.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_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.0   # 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=${dl_owd_delta_thr_ms} # 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" | ||||
|  | @ -1,221 +0,0 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| # defaults.sh -- default configuration values for cake-autorate.sh | ||||
| # | ||||
| # This file is part of cake-autorate. | ||||
| # | ||||
| # CAKE-AUTORATE IS HIGHLY CONFIGURABLE AND THIS FILE MAY BE  | ||||
| # CONSULTED IN RESPECT OF OVERRIDING VARIABLES IN A CONFIG FILE. | ||||
| # | ||||
| # DO NOT MODIFY THIS FILE. ANY CHANGES NEED TO BE MADE TO | ||||
| # THE CONFIG FILE FOR A GIVEN INSTANCE OF CAKE-AUTORATE. | ||||
| # MODIFYING THIS FILE WILL RESULT IN THE LOSS OF ANY CHANGES | ||||
| # DURING AN UPDATE OR UNEXPECTED BEHAVIOR AFTER AN UPDATE | ||||
| # IF THE OLD DEFAULT FILE WAS IN USE. | ||||
| 
 | ||||
| INTERFACE="" | ||||
| 
 | ||||
| # *** 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_summary_stats=1          # enable (1) or disable (0) output monitoring lines showing summary 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 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 binary selection can be any of: | ||||
| # fping - round robin pinging (rtts) | ||||
| # tsping - round robin pinging using ICMP type 13 (owds) | ||||
| # ping - (iputils-ping) individual pinging (rtts) | ||||
| pinger_binary=fping | ||||
| 
 | ||||
| # 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) | ||||
| 
 | ||||
| # owd delta 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_owd_delta_thr_ms=30.0 # (milliseconds) | ||||
| ul_owd_delta_thr_ms=30.0 # (milliseconds) | ||||
| 
 | ||||
| # average owd delta threshold in ms at which maximum adjust_down_bufferbloat is applied | ||||
| # set value(s) to 0 to disable and always apply maximum adjust_down_bufferbloat | ||||
| dl_avg_owd_delta_thr_ms=60.0 # (milliseconds) | ||||
| ul_avg_owd_delta_thr_ms=60.0 # (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 | ||||
| # shaper rate is adjusted by a maximum of shaper_rate_max_adjust_down_bufferbloat on detection of bufferbloat | ||||
| # and this is scaled by the average delta owd / average owd delta threshold | ||||
| # otherwise shaper rate is adjusted up on load high, and down on load idle or low | ||||
| shaper_rate_min_adjust_down_bufferbloat=0.99    # how rapidly to reduce shaper rate upon detection of bufferbloat (min reduction) | ||||
| shaper_rate_max_adjust_down_bufferbloat=0.75	# how rapidly to reduce shaper rate upon detection of bufferbloat (max reduction) | ||||
| 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_sum_owd_baselines_delta_thr_ms=20.0	# max increase from min sum owd baselines before reflector rotated | ||||
| reflector_owd_delta_ewma_delta_thr_ms=10.0	# max 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 | ||||
|  | @ -1,26 +0,0 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| cake_instances=(/root/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 | ||||
| 	/root/cake-autorate/cake-autorate.sh "${cake_instance}" & | ||||
| 	cake_instance_pids+=(${!}) | ||||
| done | ||||
| wait | ||||
|  | @ -1,149 +0,0 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| # 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 | ||||
| 
 | ||||
| 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() | ||||
| { | ||||
| 	# 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}" || true | ||||
| } | ||||
| 
 | ||||
| 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() | ||||
| { | ||||
| 	# randomize the order of the elements of an 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 | ||||
| } | ||||
| 
 | ||||
| terminate() | ||||
| { | ||||
| 	# Send regular kill to processes and monitor terminations; | ||||
| 	# return as soon as all of the active processes terminate; | ||||
| 	# if any processes remain active after one second, kill with fire using kill -9; | ||||
| 	# and, finally, call wait on all processes to reap any zombie processes. | ||||
| 
 | ||||
| 	local pids=("${@:-}") | ||||
| 
 | ||||
| 	kill "${pids[@]}" 2> /dev/null | ||||
| 
 | ||||
| 	for((i=0; i<10; i++)) | ||||
| 	do | ||||
| 		for process in "${!pids[@]}" | ||||
| 		do | ||||
| 			kill -0 "${pids[${process}]}" 2> /dev/null || unset "pids[${process}]" | ||||
| 		done | ||||
| 		[[ "${pids[*]}" ]] || return | ||||
| 		sleep_s 0.1 | ||||
| 	done | ||||
| 
 | ||||
| 	kill -9 "${pids[@]}" 2> /dev/null | ||||
| } | ||||
| 
 | ||||
| if (( __set_e == 1 )) | ||||
| then | ||||
|     set +e | ||||
| fi | ||||
| unset __set_e | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue