Problem
Every timeout, retry count, and window size in the MAVLink request/response protocols is a compile-time constant:
FTPManager::_ackOrNakTimeoutMsecs = 3000, fixed burst size, fixed session-reopen count
ParameterManager::kWaitForParamValueAckMs = 1000, kIndexBatchMaxOutstanding = 10, kMaxInitialLoadRetrySingleParam = 5, kUnresponsiveSilentCycles = 2
RequestMetaDataTypeStateMachine "slow download" heuristic: abort if elapsed > 5 s && progress < 0.5 && projected > 40 s
_ftpDownloadComplete "FTP too slow, fall back to stream" heuristic: 0.0001 < progress < 0.01
The only link awareness is LinkConfiguration::isHighLatency(), a boolean meaning "satellite — skip parameter load entirely."
These constants were tuned for a healthy SiK radio and happen to also work on WiFi because everything completes well inside them. They fail in the middle: a SiK link at range, a congested WiFi/ESP bridge with a few percent loss, a slow DroneCAN node behind the autopilot. That is the environment #15114 came from, and it is why #15120 needed five review rounds of hand-tuned retry/give-up flags.
MockLink has zero latency and zero loss unless a test asks for a specific failure mode, so CI never exercises the constants against a realistic link and cannot catch this class of bug.
Proposal
Measure the link; stop configuring it.
-
Per-link RTT / loss / throughput estimator on LinkInterface (or a small LinkStats object it owns).
- RTT samples come for free from request/response pairs we already do:
PARAM_REQUEST_READ→PARAM_VALUE, FTP request→ack (seq-numbered), COMMAND_LONG→COMMAND_ACK, TIMESYNC/PING.
- Keep SRTT / RTTVAR (Jacobson–Karels) and a loss-rate EWMA. Expose
rto() = SRTT + 4·RTTVAR clamped to a sane range (e.g. 250 ms … 10 s), lossRate(), bytesPerSecond().
- Throughput estimator can build on the existing
DataRateTracker.
-
Protocols consume rto() instead of constants.
- FTP ack/nak timeout, PARAM_REQUEST_READ / PARAM_SET ack timeout, metadata download stall detection.
- Retries use exponential backoff on
rto(); fixed retry counts stop being the tuning knob.
-
Outstanding-request window driven by loss (AIMD).
- Replace
kIndexBatchMaxOutstanding and the fixed FTP burst size with a congestion window: grow on ack, halve on timeout. WiFi opens to a large window and finishes fast; SiK settles at a few outstanding and stops flooding the radio.
- "Component unresponsive" becomes "loss estimate to that component is 100% over N RTOs," replacing
kUnresponsiveSilentCycles / kUnresponsiveMinOutstanding.
-
Transport selection from measured throughput. Decide FTP param.pck vs. PARAM_REQUEST_LIST stream up front from bytesPerSecond() and the known compressed size, instead of starting FTP, watching it crawl, and falling back.
-
Testability. Protocols take the stats provider by injection. MockLink gains link profiles (e.g. WiFi: 20 ms RTT / 0 % loss; SiKAtRange: 800 ± 300 ms RTT / 20 % loss; Congested: 200 ms / 5 %) and the existing FTPManagerTest / ParameterManagerTest suites run under each profile via _data() rows. Tests that only pass at zero latency are bugs.
Acceptance
- No
static constexpr int k*Ms timeouts remain in FTPManager, ParameterManager initial load, or RequestMetaDataTypeStateMachine; all derive from the link estimator.
- Existing
FTPManagerTest and ParameterManagerTest pass unchanged under the zero-latency profile, and also pass under a lossy/slow profile.
- Full PX4 parameter load over a simulated 57.6 kbps / 10 % loss link completes without declaring the autopilot or a DroneCAN component unresponsive.
Dependencies
Context
Follow-up from #15120 / #15114 design discussion.
Problem
Every timeout, retry count, and window size in the MAVLink request/response protocols is a compile-time constant:
FTPManager::_ackOrNakTimeoutMsecs = 3000, fixed burst size, fixed session-reopen countParameterManager::kWaitForParamValueAckMs = 1000,kIndexBatchMaxOutstanding = 10,kMaxInitialLoadRetrySingleParam = 5,kUnresponsiveSilentCycles = 2RequestMetaDataTypeStateMachine"slow download" heuristic: abort ifelapsed > 5 s && progress < 0.5 && projected > 40 s_ftpDownloadComplete"FTP too slow, fall back to stream" heuristic:0.0001 < progress < 0.01The only link awareness is
LinkConfiguration::isHighLatency(), a boolean meaning "satellite — skip parameter load entirely."These constants were tuned for a healthy SiK radio and happen to also work on WiFi because everything completes well inside them. They fail in the middle: a SiK link at range, a congested WiFi/ESP bridge with a few percent loss, a slow DroneCAN node behind the autopilot. That is the environment #15114 came from, and it is why #15120 needed five review rounds of hand-tuned retry/give-up flags.
MockLinkhas zero latency and zero loss unless a test asks for a specific failure mode, so CI never exercises the constants against a realistic link and cannot catch this class of bug.Proposal
Measure the link; stop configuring it.
Per-link RTT / loss / throughput estimator on
LinkInterface(or a smallLinkStatsobject it owns).PARAM_REQUEST_READ→PARAM_VALUE, FTP request→ack (seq-numbered),COMMAND_LONG→COMMAND_ACK,TIMESYNC/PING.rto()= SRTT + 4·RTTVAR clamped to a sane range (e.g. 250 ms … 10 s),lossRate(),bytesPerSecond().DataRateTracker.Protocols consume
rto()instead of constants.rto(); fixed retry counts stop being the tuning knob.Outstanding-request window driven by loss (AIMD).
kIndexBatchMaxOutstandingand the fixed FTP burst size with a congestion window: grow on ack, halve on timeout. WiFi opens to a large window and finishes fast; SiK settles at a few outstanding and stops flooding the radio.kUnresponsiveSilentCycles/kUnresponsiveMinOutstanding.Transport selection from measured throughput. Decide FTP
param.pckvs.PARAM_REQUEST_LISTstream up front frombytesPerSecond()and the known compressed size, instead of starting FTP, watching it crawl, and falling back.Testability. Protocols take the stats provider by injection.
MockLinkgains link profiles (e.g.WiFi: 20 ms RTT / 0 % loss;SiKAtRange: 800 ± 300 ms RTT / 20 % loss;Congested: 200 ms / 5 %) and the existingFTPManagerTest/ParameterManagerTestsuites run under each profile via_data()rows. Tests that only pass at zero latency are bugs.Acceptance
static constexpr int k*Mstimeouts remain inFTPManager,ParameterManagerinitial load, orRequestMetaDataTypeStateMachine; all derive from the link estimator.FTPManagerTestandParameterManagerTestpass unchanged under the zero-latency profile, and also pass under a lossy/slow profile.Dependencies
Context
Follow-up from #15120 / #15114 design discussion.