Repository navigation
Troubleshooting
Start from what you see, follow the branch, and use the matching section
below. The full background is in
CAVEATS.md.
flowchart TB
START["Files do not arrive<br/>on the output box"] --> SVC{"Both services<br/>active?"}
SVC -- no --> FIXSVC["journalctl -u dyode-in / dyode-out<br/>config errors are named;<br/>see 'Service will not start'"]
SVC -- yes --> ANY{"Anything in the<br/>output box's log?"}
ANY -- "nothing at all" --> ARPQ{"Input box: ip neigh show<br/>out_ip is PERMANENT?"}
ARPQ -- no --> FIXARP["Check dyode_out.mac and the<br/>interface; the ARP keeper<br/>re-pins it every 60 s"]
ARPQ -- yes --> LINK["Check the cabling / diode;<br/>confirm IPs and interfaces;<br/>see 'Nothing received'"]
ANY -- "udp-receiver failed …<br/>Missed blocks" --> DROP{"Message says packets<br/>dropped on this box?"}
DROP -- yes --> LARGE["Receiver stalled:<br/>see 'Large transfers fail part-way'"]
DROP -- "no overflow on this box" --> LOSS["Loss before the box:<br/>NIC ring, optics, diode;<br/>lower bitrate"]
ANY -- "file … never arrived (timeout)" --> SLOW{"Was a transfer still<br/>running? (older than 1.4.3)"}
SLOW -- yes --> UPG["Upgrade to 1.4.3, or raise<br/>batch_timeout"]
SLOW -- no --> MISS["The file was lost in flight:<br/>re-send it from .dyode_sent"]
ANY -- "matching no expected file" --> DMG["Damaged in flight or<br/>changed after hashing:<br/>re-send"]
-
Configuration error. The message names the module and the key. Fix
config.yamland restart. -
Input box: "cannot set the static ARP entry … refusing to start".
The diode NIC is down, has no address, or
dyode_out.mac/dyode_in.interfaceis wrong. systemd keeps retrying, and DYODE starts by itself once the NIC is ready. -
"udp-sender not found". Install udpcast (
sudo ./install.sh).
- Run
ip addron both boxes. Each diode NIC must have the address inconfig.yaml(dyode_in.ip,dyode_out.ip), and they must be on the same subnet. - On the input box,
ip neigh show <out_ip>must show the output box's MAC asPERMANENT. - The input box's TX counters (
ip -s link) should rise during a send, and the output box's RX counters should rise too. A few TX drops on the output box are normal: it cannot send anything through the diode, so its own ARP, IPv6 and DHCP traffic is discarded. - An "idled out after 300 s with no sender" message on the output box is normal on a quiet link. It is logged once, then at debug level.
Symptom: small files arrive, but files from about 1 GB up fail after
roughly 30–40 s with Missed blocks: …, typically with a high bitrate and
an encrypted (LUKS) receive disk.
Cause: the receiving box wrote about 30 s of incoming data to disk in
one burst. That stalled udp-receiver long enough to overflow its socket
buffer. A diode cannot re-send, so the file was lost.
flowchart LR
A["0–30 s: data piles up<br/>in memory, nothing written"] --> B["~30 s: kernel writes<br/>~1 GB at once<br/>(encrypting it, on LUKS)"]
B --> C["udp-receiver stalls<br/>longer than its buffer lasts"]
C --> D["Packets dropped:<br/>more than FEC can repair"]
D --> E["File aborted"]
F["Fix: start writing at 64 MB<br/>+ an 8 MB socket buffer"] -.-> B
Fix: the receive-side kernel settings, which 1.4.2 and later install automatically:
sudo ./install.sh --tuning-only
sysctl vm.dirty_background_bytes vm.dirty_bytes net.core.rmem_defaultVerified in the field. This was tested on the pair that originally failed (gigabit diode, LUKS-encrypted receive disk), with each release's fix applied:
| File size | Before the fix | With the fix |
|---|---|---|
| 500 MB | arrived | arrived |
| 1.3 GB | failed at ~39 s | arrived intact (1.4.2 settings) |
| 5 GB | failed | arrived, SHA-256 identical on both ends (1.4.2 settings) |
| 10 GB | failed | arrived (1.4.3: batch timeout fix) |
| 20 GB | not tried | arrived, no errors (1.4.3) |
Diagnose: run this on the receive box during a test transfer.
s() { awk '/^Udp:/{n++; if(n==2) print $6}' /proc/net/snmp; }
while sleep 1; do
printf "%s rcvbuf_err=%s dirty=%s wb=%s\n" "$(date +%T)" "$(s)" \
"$(awk '/^Dirty:/{print $2"k"}' /proc/meminfo)" "$(awk '/^Writeback:/{print $2"k"}' /proc/meminfo)"
done| What you see | Meaning |
|---|---|
rcvbuf_err jumps as dirty spikes and wb surges |
Writeback bursts: apply the fix above |
rcvbuf_err jumps while dirty stays low |
A CPU stall: governor, IRQ affinity (see CAVEATS.md) |
dirty climbs steadily for the whole transfer |
The disk cannot sustain the link: lower bitrate
|
| Nothing rises, but transfers fail | Loss before the box: optics, NIC ring, diode |
Check the disk can keep up. Write more than your largest file, bypassing the cache:
dd if=/dev/zero of=./ddtest bs=1M count=20000 oflag=direct status=progress; rm ./ddtestKeep bitrate below the slowest sustained rate it shows. A gigabit diode
needs about 120 MB/s.
Before 1.4.3: a single file that took longer than batch_timeout
(300 s) to transfer had its batch closed while it was still arriving. It
was then discarded with "received a file with no manifest pending". At
the ~350 Mbit/s the default FEC allows, that hits files of about 10 GB.
Fix: upgrade to 1.4.3, where data still arriving keeps the batch open.
On older versions, set batch_timeout: 3600 in the receiving folder module.
- With the default FEC, about 350–400 Mbit/s on a gigabit link is the expected ceiling on server hardware. The single-threaded encoder is the limit, not the link.
-
fec: nonereaches line rate, but any lost packet then costs the whole file. Use it only on a short, clean, dedicated link. - Many small files are slowed by
autostart(hello packets before each file) andfile_gap. Lower them carefully; raise them again if files go missing.
- On the output box, "no update for Ns, serving stale values" means
updates stopped. Check the input box's log for PLC connection errors
(
ip,plc_port,unit). -
"outside datastore … ignored" means a configured range on one side does
not match the other. Both boxes must use the same
config.yaml.
DYODE Python 3 edition · documents release 1.5.0 · source pages are kept in docs/wiki/ of the main repository · GPLv3
DYODE (Python 3)
Modules
Running it
Repository