So just to re-cap, at the moment we have:
# 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
dl_avg_owd_delta_thr_ms=60.0 # (milliseconds)
ul_avg_owd_delta_thr_ms=60.0 # (milliseconds)
# 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.04 # 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
And we calculate compensated thresholds for the thresholds:
compensated_owd_delta_thr_us[dl]=dl_owd_delta_thr_us + dl_compensation_us,
compensated_owd_delta_thr_us[ul]=ul_owd_delta_thr_us + ul_compensation_us,
compensated_avg_owd_delta_thr_us[dl]=dl_avg_owd_delta_thr_us + dl_compensation_us,
compensated_avg_owd_delta_thr_us[ul]=ul_avg_owd_delta_thr_us + ul_compensation_us,
For each reflector, we determine whether the OWD exceeds the compensated_owd_delta_thr_us, and then we classify bufferbloat as follows:
bufferbloat_detected[dl] = sum_dl_delays >= bufferbloat_detection_thr ? 1 : 0,
bufferbloat_detected[ul] = sum_ul_delays >= bufferbloat_detection_thr ? 1 : 0,
And then, in terms of adjusting the shaper rate, we use:
# 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 (( compensated_avg_owd_delta_thr_us[${direction}] <= compensated_owd_delta_thr_us[${direction}] ))
then
shaper_rate_adjust_down_bufferbloat_factor=1000
elif (( (avg_owd_delta_us[${direction}]-compensated_owd_delta_thr_us[${direction}]) > 0 ))
then
((
shaper_rate_adjust_down_bufferbloat_factor=1000*(avg_owd_delta_us[${direction}]-compensated_owd_delta_thr_us[${direction}])/(compensated_avg_owd_delta_thr_us[${direction}]-compensated_owd_delta_thr_us[${direction}]),
shaper_rate_adjust_down_bufferbloat_factor > 1000 && (shaper_rate_adjust_down_bufferbloat_factor=1000)
))
else
shaper_rate_adjust_down_bufferbloat_factor=0
fi
((
shaper_rate_adjust_down_bufferbloat=1000*shaper_rate_min_adjust_down_bufferbloat-shaper_rate_adjust_down_bufferbloat_factor*(shaper_rate_min_adjust_down_bufferbloat-shaper_rate_max_adjust_down_bufferbloat),
shaper_rate_kbps[${direction}]=shaper_rate_kbps[${direction}]*shaper_rate_adjust_down_bufferbloat/1000000,
t_last_bufferbloat_us[${direction}]=t_start_us,
t_last_decay_us[${direction}]=t_start_us
))
fi
;;
# high load, so increase rate providing not inside bufferbloat refractory period
*high*)
if (( achieved_rate_updated[${direction}] && 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,
achieved_rate_updated[${direction}]=0,
t_last_decay_us[${direction}]=t_start_us
))
fi
;;
That is, if bufferbloat is detected, we ensure we're not in a refractory period and then apply the shaper rate adjustment in dependence upon where the average OWD delta sits between compensated_owd_delta_thr_us and compensated_avg_owd_delta_thr_us.
Or, on high load (without bufferbloat), we check we've not already updated since the last load update and ensure we're not inside a bufferbloat refractory period and simply increase by our shaper_rate_adjust_up_load_high (1.04) factor.
At the moment I'm thinking of the following. Set the new thresholds as:
# 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_max_adjust_up_load_high=1.04 # how rapidly to increase shaper rate upon high load detected (max increase)
shaper_rate_min_adjust_up_load_high=1.0 # how rapidly to increase shaper rate upon high load detected (min increase)
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
# 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_up_load_high is applied
dl_min_avg_owd_delta_thr_ms=20.0 # (milliseconds)
ul_min_avg_owd_delta_thr_ms=20.0 # (milliseconds)
# average owd delta threshold in ms at which maximum adjust_down_bufferbloat is applied
dl_max_avg_owd_delta_thr_ms=60.0 # (milliseconds)
ul_max_avg_owd_delta_thr_ms=60.0 # (milliseconds)
And then apply the shaper rate adjustments accordingly. How does this all seem to you?
Should:
dl_min_avg_owd_delta_thr_ms=20.0 # (milliseconds)
ul_min_avg_owd_delta_thr_ms=20.0 # (milliseconds)
also be compensated as in:
compensated_avg_owd_delta_thr_us[dl]=dl_min_avg_owd_delta_thr_us + dl_compensation_us,
compensated_avg_owd_delta_thr_us[ul]=ul_min_avg_owd_delta_thr_us + ul_compensation_us,