Add edge clock sync diagnostics
This commit is contained in:
1 parent
836af4b623
commit
6c99ae39a9
6 files changed
+274
-76
No files matched your search
+49
-14
@@ -588,8 +588,12 @@ send text.flood checking ridge link
|
||||
**Usage:**
|
||||
- `get clock.sync`
|
||||
- `get clock.sync.status`
|
||||
- `get clock.sync.status.table`
|
||||
- `get clock.sync.status.<1-16>`
|
||||
- `get clock.sync.mesh`
|
||||
- `set clock.sync.mesh <on|off>`
|
||||
- `get clock.sync.mesh.edge`
|
||||
- `set clock.sync.mesh.edge <on|off>`
|
||||
- `clock.sync.mesh now`
|
||||
- `get clock.sync.internet`
|
||||
- `set clock.sync.internet <on|off>`
|
||||
@@ -600,6 +604,7 @@ send text.flood checking ridge link
|
||||
|
||||
**Defaults:**
|
||||
- `clock.sync.mesh`: `on` for nRF52 repeaters; `off` for other builds
|
||||
- `clock.sync.mesh.edge`: `on`
|
||||
- `clock.sync.internet`: `off`
|
||||
- `clock.sync.drift`: `3600` seconds
|
||||
- `clock.sync.samples`: `9`
|
||||
@@ -633,17 +638,44 @@ a different full received path; all direct, zero-hop receptions count as the
|
||||
same empty path. This prevents repeated packets or multiple names arriving over
|
||||
one route from increasing the vote count.
|
||||
|
||||
At least the configured number of distinct fresh paths (nine by default) and a
|
||||
strict majority of all fresh samples must fall within ten minutes of the
|
||||
median. The effective quorum is therefore the larger of `clock.sync.samples`
|
||||
and half the fresh sample count plus one. For example, a 9-vs-7 split can
|
||||
succeed but an 8-vs-8 split cannot. The median is used. `clock.sync.samples`
|
||||
accepts `3` through `16`; samples older than two hours are ignored. Status
|
||||
reports `collecting` when fewer than the configured number of paths exist, and
|
||||
`no consensus` when enough paths exist but the effective quorum does not agree.
|
||||
Mesh collection begins immediately after boot. Following a successful estimate,
|
||||
it resumes two hours before the next seven-day deadline so only evidence that
|
||||
can still be fresh at evaluation time is processed.
|
||||
For a node at the edge of the network where every packet arrives through one
|
||||
relay path, `set clock.sync.mesh.edge on` changes the evidence requirement from
|
||||
distinct receive paths to distinct sources. Signature-verified adverts are
|
||||
deduplicated by public key, and Public-channel timestamps are deduplicated by
|
||||
case-insensitive display name. Repeated packets from one source still count
|
||||
once. Changing edge mode clears the in-memory sample table so evidence collected
|
||||
under the other policy is not reused. The setting is persistent and defaults on.
|
||||
|
||||
At least the configured number of distinct fresh evidence sources (nine by
|
||||
default) and a strict majority of all fresh samples must fall within ten minutes
|
||||
of the median. In normal mode each source must use a distinct receive path. In
|
||||
edge mode signed adverts are distinct by public key and Public-channel messages
|
||||
are distinct by display name, but all may use the same receive path. The
|
||||
effective quorum is therefore the larger of
|
||||
`clock.sync.samples` and half the fresh sample count plus one. For example, a
|
||||
9-vs-7 split can succeed but an 8-vs-8 split cannot. The median is used.
|
||||
`clock.sync.samples` accepts `3` through `16`; samples older than two hours are
|
||||
ignored. Status reports `mode=paths` or `mode=edge` and labels the collected
|
||||
evidence as `paths` or `sources`. It reports `reason=need-more-paths` or
|
||||
`reason=need-more-sources` when fewer than the configured number exist, and
|
||||
`reason=no-consensus` when enough evidence exists but the effective quorum does
|
||||
not agree. Mesh collection begins immediately after boot. Following a
|
||||
successful estimate, it resumes two hours before the next seven-day deadline so
|
||||
only evidence that can still be fresh at evaluation time is processed.
|
||||
|
||||
`get clock.sync.status` reports whether the clock was set and a `reason` when it
|
||||
was not. Common reasons include `waiting-deadline`, `need-more-sources`,
|
||||
`need-more-paths`, `no-consensus`, `within-drift`, `mesh-off`, and suppression
|
||||
by CLI, GPS, or internet time. It also reports whether collection is active, the
|
||||
fresh evidence count, the number of occupied table slots, and the next
|
||||
evaluation deadline.
|
||||
|
||||
`get clock.sync.status.table` shows the active sample table in compact form.
|
||||
Each item is `slot:type:id-prefix:age`, where type `A` is a signed advert and
|
||||
type `P` is a Public-channel message. A trailing `!` marks a stale sample. If
|
||||
the compact reply is truncated, query any slot with
|
||||
`get clock.sync.status.<1-16>`. The detail view reports the full source and path
|
||||
hashes, age-adjusted epoch, difference from the local clock, and freshness.
|
||||
|
||||
A timestamp is eligible for a clock-sync sample only when it falls between the
|
||||
UTC build epoch embedded by `build.sh` and that time plus ten calendar years.
|
||||
@@ -679,7 +711,9 @@ path hashes are also truncated, unauthenticated routing hints; requiring unique
|
||||
paths prevents ordinary duplicate-route inflation but is not a cryptographic
|
||||
identity check. Signed adverts authenticate the advert contents but do not
|
||||
prove that the advertising node's own clock is correct. Mesh time is therefore
|
||||
a consensus estimate, not an authoritative time service.
|
||||
a consensus estimate, not an authoritative time service. Edge mode intentionally
|
||||
gives up receive-path diversity. Public-channel display names can be spoofed, so
|
||||
one sender can claim multiple names and inflate the edge-mode vote count.
|
||||
|
||||
`clock.sync.internet` is available on WiFi MQTT repeater-observer builds. Its
|
||||
initial and seven-day queries run on the MQTT/WiFi task and are read-only until
|
||||
@@ -700,9 +734,10 @@ replays until corrected time passes the previously observed value.
|
||||
**Example:**
|
||||
```text
|
||||
set clock.sync.drift 1800
|
||||
set clock.sync.samples 9
|
||||
set clock.sync.samples 3
|
||||
set clock.sync.mesh on
|
||||
set clock.sync.internet on
|
||||
set clock.sync.mesh.edge on
|
||||
clock.sync.mesh now
|
||||
get clock.sync.status
|
||||
```
|
||||
|
||||
|
||||
@@ -86,10 +86,11 @@ set flood.retry.ignore none
|
||||
| `flood.channel.scope` | Assigns a transport-region scope to received unscoped floods. Exact channel keys beat `txt:*`; `login:*` covers the remote-login family, and `other:*` covers every remaining flood type except TRACE, including OTA. TRACE remains unchanged across scope boundaries. ACL permission `4` can manage the table. | `get flood.channel.scope[.n]`, `set flood.channel.scope[.n] <channel|txt:*|login:*|other:*> <region>`, `del flood.channel.scope.<n>|all` | `set flood.channel.scope login:* west` |
|
||||
| `flood.filter` | Persistent repeater-only forwarding rules for flood routes `0x00`/`0x01`, selected by payload type and optional received hop count/range (omitted means `all`). New tables seed slot 1 with `ota all suspend=tempradio`; only rows marked `suspend=tempradio` are skipped during temporary-radio operation. Login-capable `anon_req`/`path`/`response` types become filterable at hop `7`; flood `txt_msg` becomes filterable at hop `5`. Standard direct traceroute, other direct routing, and local receive/logging are unchanged. | `get flood.filter[.n]`, `set flood.filter[.n] <type> [N|N+|N-M|all] [suspend=tempradio]`, `del flood.filter.<n>|all` | `set flood.filter.1 0x0C all suspend=tempradio` |
|
||||
| `flood.moderation` | Decrypts keyed `GRP_TXT` channels and applies drop, per-username messages/minute, and maximum-hop controls, optionally matched against the first 1-3 path hashes. Supports `public`, `#channel`, and 128/256-bit channel keys. Sender names and truncated path hashes are moderation hints, not authenticated identities. | `get flood.moderation[.n]`, `set flood.moderation[.n] <channel> <sender> <drop|rate=X/min|hops=N> [path=...]`, `del flood.moderation.<n>|all` | `set flood.moderation public "Noisy User" rate=5/min hops=4` |
|
||||
| `clock.sync.mesh` | Defaults on for nRF52 repeaters and off for other builds; a saved setting overrides that default. After 30 minutes of uptime, it estimates UTC from a configurable consensus of fresh signed-advert or valid Public-channel sources, then repeats lazily seven days after each successful estimate. Failed attempts retry every 30 minutes; `clock.sync.mesh now` queues an immediate LoRa-only attempt without bypassing quorum or source suppression. Only timestamps from firmware build time through build time plus ten years are recorded. Successful CLI, GPS, or WiFi/NTP clock updates suppress LoRa time collection until reboot; after reboot LoRa is the fallback if NTP cannot sync. | `get clock.sync.mesh`, `set clock.sync.mesh <on|off>`, `clock.sync.mesh now`, `get clock.sync.status` | `set clock.sync.mesh on` |
|
||||
| `clock.sync.mesh` | Defaults on for nRF52 repeaters and off for other builds; a saved setting overrides that default. After 30 minutes of uptime, it estimates UTC from a configurable consensus of fresh signed-advert or valid Public-channel sources, then repeats lazily seven days after each successful estimate. Failed attempts retry every 30 minutes; `clock.sync.mesh now` queues an immediate LoRa-only attempt without bypassing quorum or source suppression. Only timestamps from firmware build time through build time plus ten years are recorded. Successful CLI, GPS, or WiFi/NTP clock updates suppress LoRa time collection until reboot; after reboot LoRa is the fallback if NTP cannot sync. Status reports the reason a clock was not set; its `.table` and `.1` through `.16` forms inspect collected samples. | `get clock.sync.mesh`, `set clock.sync.mesh <on|off>`, `clock.sync.mesh now`, `get clock.sync.status[.table|.1-.16]` | `set clock.sync.mesh on` |
|
||||
| `clock.sync.mesh.edge` | Defaults on so edge repeaters can collect clock evidence when all packets arrive through one relay path. Signed adverts are deduplicated by public key and Public-channel timestamps by case-insensitive display name; all may share one receive path. Public display names are unauthenticated and can be spoofed. Changing this setting clears current clock samples. | `get clock.sync.mesh.edge`, `set clock.sync.mesh.edge <on|off>` | `set clock.sync.mesh.edge on` |
|
||||
| `clock.sync.internet` | Adds a read-only internet/NTP estimate at the same initial and seven-day checks on WiFi MQTT repeater-observer builds. Other builds retain the setting but report internet unavailable. | `get clock.sync.internet`, `set clock.sync.internet <on|off>` | `set clock.sync.internet on` |
|
||||
| `clock.sync.drift` | Absolute correction threshold in seconds. The clock is moved forward or backward only when the estimate differs by more than this value. | `get clock.sync.drift`, `set clock.sync.drift <30-86400>` | `set clock.sync.drift 3600` |
|
||||
| `clock.sync.samples` | Minimum number of distinct, in-window receive paths that must agree before mesh time can be used. A strict majority of all fresh samples is also required. Range `3-16`; default `9`. | `get clock.sync.samples`, `set clock.sync.samples <3-16>` | `set clock.sync.samples 9` |
|
||||
| `clock.sync.samples` | Minimum fresh evidence count before mesh time can be used: distinct receive paths in normal mode or distinct advert keys/Public-channel display names in edge mode. A strict majority of all fresh samples is also required. Range `3-16`; default `9`. | `get clock.sync.samples`, `set clock.sync.samples <3-16>` | `set clock.sync.samples 9` |
|
||||
| `outpath` | Overrides the primary direct route used for replies to the current remote client. | `get outpath`, `set outpath <hops>`, `set outpath direct`, `set outpath clear`, `set outpath flood` | `set outpath A1B2C3,D4E5F6` |
|
||||
| `altpath` | Adds a secondary direct route for repeater replies to the current remote client. | `get altpath`, `set altpath <hops>`, `set altpath direct`, `set altpath clear`, `set altpath flood` | `set altpath 71CE82,BA09F0` |
|
||||
|
||||
|
||||
Reference in new issue
Block a user