Also known as: SoapyRemote field notes, USRP over SoapyRemote, SoapySDRServer notes
USRP & SoapyRemote field notes cover the traps found while field-testing Ettus
hardware (B210, X310/TwinRX, N310) with GopherTrunk.
GopherTrunk is built with CGO disabled, so there is no native UHD backend: all
USRP devices are driven through a pure-Go
SoapyRemote wire-protocol client talking to a
SoapySDRServer process — over loopback for a locally attached device, or across the
network. The B210 is a USB device (type=b200); only the N- and X-series are
themselves networked.
Configuration traps
| Symptom | Looks like | Actually | Fix/Check |
|---|---|---|---|
Tuned remote:mtu=8000 (or remote:window, remote:prot) has no effect |
Server ignoring the client | These keys inside args are silently ignored — GopherTrunk builds the SETUP_STREAM frame itself and never forwards args into stream setup; the stream ran at the 1500-byte default |
Use the dedicated stream_mtu / stream_window keys; config load now hard-rejects the remote:* forms (#876) |
| High-rate USRP overruns even though server and client are the same Mac | Server too slow | macOS caps the MTU on lo0, so a server bound to 127.0.0.1 can never negotiate a jumbo stream_mtu |
Bind SoapySDRServer to the host’s real NIC IP, even for local use; Linux loopback has no such cap (#876) |
| Decode works but the rate isn’t what you configured | GopherTrunk bug | UHD silently coerces any sample rate that isn’t an integer decimation of the master clock; GopherTrunk reads the delivered rate back over RPC and clocks its DSP from it, so decode survives | For exactness set master_clock_rate: 61_440_000 and a dividing sample_rate — 6,144,000 (÷10) ran overrun-free on a B210 (#876) |
| Manual gain apparently ignored on a TwinRX | Gain bug | The TwinRX has no AGC hardware; setGainMode(false) throws, and an early driver returned on that error before ever applying manual gain |
Disabling AGC must be best-effort; fixed in #542 |
| Gain value behaves 10× off | Driver bug | Gain is in tenths of a dB: "300" = 30 dB, "30" = 3 dB |
See SDR gain & front-end overload |
Wire-protocol behaviors that look like bugs
Both of these were misdiagnosed repeatedly in
#542 — all three of the
originally proposed root causes (an Open() race, rate-after-frequency ordering, and
setGainMode(true)) turned out to be wrong.
- SETUP_STREAM is two-phase and two-socket. The server first replies with just the
bound port string, then blocks accepting two client connections (stream + status),
and only then sends a second reply with the stream id. A client that reads one reply
and opens one socket gets a short-response error — and retrying SETUP_STREAM on the
server’s still-bound graph can crash libuhd in the server process
(
Attempting to reconnect output port ...followed by a segfault). The segfault is downstream fallout, not the bug. - TCP mode still uses application-level flow control. The server’s sender thread
transmits zero samples until the client sends an initial 24-byte ACK, then stays
at most a window of sequences ahead. A missing ACK looks like a healthy connection
that delivers no IQ (
iq_observed=false iq_samples=0read timeouts, with the server logging overruns). It is not a UDP-only mechanism. - A cold X310 takes seconds before reply #1 while it compiles its RFNoC graph, so stream setup needs a long read deadline — otherwise the client fails with an RPC header read timeout against a perfectly healthy server.
- UHD’s own debug output misleads. Lines like
[DDC] Not setting frequency until sampling rate is setare internal UHD block-init chatter, not evidence about the client’s call ordering — treating them as a smoking gun sent #542 down a false path. The same pattern (UHD CIC-rolloff messages read as resampler failures) derailed #550.
Operational notes
- Run
SoapySDRServersupervised. It crashes on its own; a process supervisor (systemd, runit) that restarts it is part of any unattended deployment (#876). - Debugging incantation:
SOAPY_SDR_LOG_LEVEL=DEBUG SOAPY_REMOTE_IP=<gt-host-ip> SoapySDRServer --bind=<usrp-host-ip>:23313. - Throughput reference point: an N310 ran 20 MS/s overrun-free through the SoapyRemote flow control (#876).
signal_dbfson a recorded call is channel power in dBFS — not calibrated RSSI, and not SNR or EVM. Do not compare it across devices with different gain settings.
For gain selection on these front ends, see SDR gain & front-end overload; for the general capture-and-replay approach to qualifying a device/rate combination, see Airspy sample-rate selection and the diagnostic playbook.
Provenance
- #876 — USRP B210 field testing: ignored
remote:*stream args, the macOSlo0MTU cap, UHD rate coercion and the master-clock divisor rule, gain units, supervision advice. - #542 — SoapyRemote “segfault on connect”: the two-phase two-socket SETUP_STREAM handshake, TCP flow-control ACK, TwinRX best-effort AGC, cold-X310 RFNoC compile delay — after three confidently wrong root causes.