Found while tracing #712. The identity was a different fault (the bridge's 32-bit strtoul), but the hypothesis in that issue, "the startup is passing the same noise to each node", is true of everything except the identity.
Since MeshBench/meshcore-native 0f43543 the native binary runs MeshCore's own CustomSX1262 over RadioLib over the vendored virtual-sx1262 model, linked into the process. randomByte() is RadioLib's real SX126x::randomByte(), and the model answers it from refreshNoise(): splitmix64 over noiseSeed_ + K * (++noiseCounter_). noiseSeed_ defaults to 0 and nothing in meshcore-native ever calls setNoiseSeed / vsx_set_noise_seed. There is no --noise-seed flag and no MESHBENCH_NOISE_SEED read (bridge/main.cpp accepts --bridge --seed --sf --bw-khz --cr --stuck-irq-ms --print-airtime).
So every native node runs the identical noise stream from counter 0, and because boot is deterministic they read the same bytes at the same points. The identity survives because the host variant bypasses the radio there (radio_new_identity() uses HostRNG(g_identity_seed)). What does not survive:
simple_repeater/main.cpp:68 does fast_rng.begin(radio_driver.getRngSeed()), and RadioLibWrappers.cpp:46-48 implements that as _radio->random(0x7FFFFFFF): four randomByte() calls, 32 reads of the noise register. Every native node's StdRNG is seeded identically. That is CSMA backoff, advert jitter, retry timing: the things whose independence between nodes the channel model depends on.
This is the native-side instance of #556, which gave the emulated chip a per-node noise stream (internal/firmware/emulated/noiseseed.go, MESHBENCH_NOISE_SEED, FNV-1a over run seed + name + board + position).
What would fix it
- meshcore-native:
--noise-seed N in bridge/main.cpp, calling sim_hal.chip().setNoiseSeed(N) before setup().
- MeshBench: send it from
internal/firmware/native/native.go, derived the way noiseSeedFor already does for emulated nodes rather than from the node index.
Needs a meshcore-native release, so it is not in the #712 fix. Until then, native nodes' backoff and jitter are correlated across the whole mesh, and any result that depends on two nodes not choosing the same slot is optimistic or pessimistic in a way nobody has measured.
Found while tracing #712. The identity was a different fault (the bridge's 32-bit
strtoul), but the hypothesis in that issue, "the startup is passing the same noise to each node", is true of everything except the identity.Since MeshBench/meshcore-native
0f43543the native binary runs MeshCore's ownCustomSX1262over RadioLib over the vendoredvirtual-sx1262model, linked into the process.randomByte()is RadioLib's realSX126x::randomByte(), and the model answers it fromrefreshNoise(): splitmix64 overnoiseSeed_ + K * (++noiseCounter_).noiseSeed_defaults to 0 and nothing in meshcore-native ever callssetNoiseSeed/vsx_set_noise_seed. There is no--noise-seedflag and noMESHBENCH_NOISE_SEEDread (bridge/main.cppaccepts--bridge --seed --sf --bw-khz --cr --stuck-irq-ms --print-airtime).So every native node runs the identical noise stream from counter 0, and because boot is deterministic they read the same bytes at the same points. The identity survives because the host variant bypasses the radio there (
radio_new_identity()usesHostRNG(g_identity_seed)). What does not survive:simple_repeater/main.cpp:68doesfast_rng.begin(radio_driver.getRngSeed()), andRadioLibWrappers.cpp:46-48implements that as_radio->random(0x7FFFFFFF): fourrandomByte()calls, 32 reads of the noise register. Every native node'sStdRNGis seeded identically. That is CSMA backoff, advert jitter, retry timing: the things whose independence between nodes the channel model depends on.This is the native-side instance of #556, which gave the emulated chip a per-node noise stream (
internal/firmware/emulated/noiseseed.go,MESHBENCH_NOISE_SEED, FNV-1a over run seed + name + board + position).What would fix it
--noise-seed Ninbridge/main.cpp, callingsim_hal.chip().setNoiseSeed(N)beforesetup().internal/firmware/native/native.go, derived the waynoiseSeedForalready does for emulated nodes rather than from the node index.Needs a meshcore-native release, so it is not in the #712 fix. Until then, native nodes' backoff and jitter are correlated across the whole mesh, and any result that depends on two nodes not choosing the same slot is optimistic or pessimistic in a way nobody has measured.