@colo I have not tried your work, but have a non-zero motivation to start my own project on this, due to disagreements with the existing ones. Since the heuristic controlling the choice of which direction to blame for the bufferbloat is one of my disagreements with @Lynx, and you are going to experiment anyway, let me just share my considerations.
The root of the problem is that, given only regular pings, one cannot be sure whether the bloat is in the upstream or downstream direction. @Lynx's implementation, upon encountering bufferbloat, resets the shaper speed in both directions to 90% of the achieved rate at the moment, under the mistaken but apparently necessary assumption that the other direction would be quick to recover. Yes I understand that nobody has suggested anything better except OWD.
Here is a bad sequence of events. Assume that the minimum speed is set to 200 kbps (because it is that bad in the Philippines around 9PM) in both directions. The base rate is 500 kbps, but even 10000 kbps is sometimes achievable. There are 4 reflectors, and the reflector ping interval is 4 seconds, so that there is only 1 ping per second total. With such low speeds, resetting to the minimum just because "there is no other idea" is a painful event that takes a lot of time to recover from, and must be avoided, even at the cost of some bloat getting through.
-
Watch a few YouTube videos on a good day, see how the DL shaper rate is steadily increasing to, let's say, 4200 kbps, while the UL is still 500 kbps.
-
Upload a few photos to Google Drive. Let's say that 3000 kbps upload is achieved before there is bufferbloat.
-
The script detects bufferbloat. At this point, the achieved rate is around 3000 kbps and something less than 200 kbps down. Result: the script will restrict the upload to 2700 kbps and download to the miserable worst-case 200 kbps.
This result (that performing an upload totally kills the well-earned download speed) is something why I patch @Lynx's script to never try resetting the shaper rate in the idle direction (but still reset the epoch).
This works well for a one-user scenario, because there is never simultaneous uploading and downloading, but this will fail if, during the upload of photos, there is indeed a concurrent slow download (e.g. internet radio).
I tried investigating some ideas in my head, but so far, without OWD, have nothing better. One of the ideas investigated was to restrict the ratios of the rates. E.g., given that we achieve 3000 kbps up, assume that we have at least 1500 kbps down, and do not set the down shaper below that. Similarly, if we achieve 4200 kbps down, assume that we have at least 2100 kbps up, and don't set the shaper below that. Obviously this needs to be generalized to break the symmetry - we need two achieved-to-assumed rate ratios, one for going from achieved upload rate to assumed-to-be-achievable download rate, and the other one for the other way round. But @Lynx's approach already has too many tweakable parameters, that's why I am not really fond of this idea.
EDIT: on a good day such as today, here is what's achieved without SQM: https://www.waveform.com/tools/bufferbloat?test-id=42ad86e8-3041-4a4c-aef5-737b9aff8167. Also please take into account that this LTE connection is only a backup. My primary connection is using GPON.