Skip to content

Pr2 tmm basic#10706

Merged
thebentern merged 2 commits into
meshtastic:developfrom
NomDeTom:pr2-tmm-basic
Jun 21, 2026
Merged

Pr2 tmm basic#10706
thebentern merged 2 commits into
meshtastic:developfrom
NomDeTom:pr2-tmm-basic

Conversation

@NomDeTom

@NomDeTom NomDeTom commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Reworks the TrafficManagementModule cache layer and adds a routing-hint overflow store.
Stacks on #10745 — review/merge after it; the shared NodeDB/WarmNodeStore files belong to #10745 .

What's in this PR

1. Position deduplication (TrafficManagementModule)

Fingerprints each relayed position broadcast (4-bit lat + 4-bit lon nibble from the truncated coordinates, remapped so 0x000xFF matching the relay_node sentinel idiom) and suppresses rebroadcasts of the same fingerprint within a configurable window (default 11 h). Only fires on well-known channels (modem-preset name + PSK size ≤ 1). The fingerprint occupies the pre-existing pos_fingerprint byte in the 10-byte cache entry — no struct growth.

2. Relayed-position precision clamp (TrafficManagementModule)

alterReceived() clamps the precision_bits of any relayed position broadcast down to the channel's configured module_settings.position_precision ceiling. Prevents a node from forwarding coordinates finer than the channel was configured to carry (e.g. a LongFast channel set to 13-bit / ~5 km). Ham mode is exempt; lost-and-found is not exempt (removed the prior exemption). Controlled by channels.isWellKnownChannel(); opt-in USERPREFS_TMM_APPLY_TO_PRIVATE_CHANNELS extends it to private channels.

3. Role-aware dedup exceptions

originRole() resolves a packet's originator via NodeDB::getNodeRole(), which falls through to the warm-tier cached role when the node has been evicted from the hot store (built on the warm-store role caching from PR1.5).

  • Tracker / TAK-tracker: dedup window capped at 1 h (vs 11 h default) — fresh track updates flow through even when position is nominally unchanged.
  • Lost-and-found: dedup window capped at 15 min — frequent heartbeat updates aren't suppressed. No longer exempt from the precision clamp.

New defaults in Default.h:

default_traffic_mgmt_position_min_interval_secs               = 11 h
default_traffic_mgmt_tracker_position_min_interval_secs       = 1 h
default_traffic_mgmt_lost_and_found_position_min_interval_secs = 15 min

4. Channels::isWellKnownChannel()

New predicate: PSK size ≤ 1 and channel name matches any modem-preset display name. Broader than isDefaultChannel (which requires the current preset name + PSK byte 0x01); catches user-named channels like a "LongFast" channel running under MediumFast modem settings.

5. PositionModule stationary / fixed-position floor

sendOurPosition() now applies a 12 h broadcast floor when the device is stationary (position unchanged within the broadcast precision cell) or has fixed_position = true. A real move still triggers the normal smart-broadcast path immediately.

Role nuances:

  • Lost-and-found: exempt — broadcasts freely at its configured interval regardless of stationarity.
  • Tracker / TAK-tracker: stationarity is judged at the configured (unclamped) precision rather than the on-wire precision, so finer movement still counts as "moved" and breaks out of the floor.
  • fixed_position = true: all roles hold to the 12 h floor; pinning yourself forfeits the tracker exception.

New helpers split out for unit-testability: positionUnchangedSinceLastSend(), positionWithinPrecisionCell(), effectiveBroadcastIntervalMs().

6. NodeDB::getNodeRole()

Hot-store (with-user) lookup → warm-tier lookupMeta() fallback → CLIENT. Lets role-aware TMM/PositionModule policy keep firing for tracker/L&F nodes aged out of the hot store.

7. AdminModule protected-node cap

set_favorite_node and set_ignored_node via remote admin now log a warning and refuse when the node is in the warm-tier protected category (groundwork for the hop-trimming protected-node path in PR2.5).

8. preloadNextHopsFromNodeDBbool

Return type changed from void to bool. Returns false when prerequisites aren't ready yet (NodeDB not initialized), so callers can retry on a later pass rather than silently doing nothing.


Compatibility

  • No protobuf or LoRa wire-format change. All new state is RAM-only (cache entries) or existing fields (precision_bits in the position payload, which was already populated).
  • isWellKnownChannel and the dedup/clamp features default to well-known channels only — custom-key channels are unaffected unless USERPREFS_TMM_APPLY_TO_PRIVATE_CHANNELS is set.

🤝 Attestations

  • I have tested that my proposed changes behave as described.
  • I have tested that my proposed changes do not cause any obvious regressions on the following devices:
    • Heltec (Lora32) V3
    • LilyGo T-Deck
    • LilyGo T-Beam
    • RAK WisBlock 4631
    • Seeed Studio T-1000E tracker card
    • Other (please specify below)

@NomDeTom NomDeTom requested a review from thebentern June 12, 2026 22:29
@NomDeTom NomDeTom added 2.8 needs-review Needs human review ai-generated Possible AI-generated low-quality content labels Jun 12, 2026
@github-actions github-actions Bot added the enhancement New feature or request label Jun 12, 2026
@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

⚡ Try this PR in the Web Flasher

Flash this PR in the Web Flasher

firmware commit boards expires

Warning

This is an automated, unreviewed CI test build. Back up your device configuration
before flashing, and only flash devices you are able to recover.

Supported boards built by this PR (24)
Device Board Platform
Crowpanel Adv 3.5 TFT elecrow-adv-35-tft esp32-s3
Heltec HT62 heltec-ht62-esp32c3-sx1262 esp32-c3
Heltec Mesh Node 096 heltec-mesh-node-t096 nrf52840
Heltec Mesh Node T1 heltec-mesh-node-t1 nrf52840
Heltec Mesh Node T114 heltec-mesh-node-t114 nrf52840
Heltec V3 heltec-v3 esp32-s3
Heltec V4 heltec-v4 esp32-s3
Raspberry Pi Pico pico rp2040
Raspberry Pi Pico W picow rp2040
RAK WisMesh Tag rak_wismeshtag nrf52840
RAK WisBlock 11200 rak11200 esp32
RAK WisBlock 11310 rak11310 rp2040
RAK3312 rak3312 esp32-s3
RAK WisBlock 4631 rak4631 nrf52840
Seeed Wio Tracker L1 seeed_wio_tracker_L1 nrf52840
Seeed Xiao NRF52840 Kit seeed_xiao_nrf52840_kit nrf52840
Seeed Xiao ESP32-S3 seeed-xiao-s3 esp32-s3
Station G2 station-g2 esp32-s3
Station G3 station-g3 esp32-s3
LILYGO T-Deck t-deck-tft esp32-s3
LILYGO T-Echo t-echo nrf52840
LILYGO T-Echo Plus t-echo-plus nrf52840
LilyGo T3-C6 tlora-c6 esp32-c6
Seeed SenseCAP T1000-E tracker-t1000-e nrf52840

Build artifacts expire on 2026-07-20. Updated for 1e49f67.

@NomDeTom NomDeTom removed the enhancement New feature or request label Jun 12, 2026
@NomDeTom NomDeTom added the enhancement New feature or request label Jun 13, 2026
@github-actions

github-actions Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Firmware Size Report

22 targets | vs develop: 22 increased, net +193,860 (+189.3 KB)

Target Size vs develop
rak3312 2,263,360 📈 +11,888 (+11.6 KB)
t-deck-tft 3,802,480 📈 +11,888 (+11.6 KB)
seeed-xiao-s3 2,267,184 📈 +11,776 (+11.5 KB)
t-eth-elite 2,482,176 📈 +11,728 (+11.5 KB)
heltec-vision-master-e213-inkhud 2,216,144 📈 +11,616 (+11.3 KB)
Show 17 more target(s)
Target Size vs develop
elecrow-adv-35-tft 3,407,360 📈 +10,864 (+10.6 KB)
station-g3 2,256,576 📈 +10,864 (+10.6 KB)
rak11200 1,851,728 📈 +10,848 (+10.6 KB)
heltec-v3 2,254,416 📈 +10,688 (+10.4 KB)
tlora-c6 2,359,312 📈 +10,320 (+10.1 KB)
heltec-ht62-esp32c3-sx1262 2,125,872 📈 +10,304 (+10.1 KB)
picow 1,236,296 📈 +9,972 (+9.7 KB)
pico2w 1,212,432 📈 +9,488 (+9.3 KB)
pico 774,912 📈 +9,344 (+9.1 KB)
rak11310 797,520 📈 +9,344 (+9.1 KB)
seeed_xiao_rp2040 773,112 📈 +9,344 (+9.1 KB)
seeed_xiao_rp2350 760,584 📈 +8,872 (+8.7 KB)
pico2 762,424 📈 +8,856 (+8.6 KB)
heltec-v4 2,266,432 📈 +2,128 (+2.1 KB)
station-g2 2,256,560 📈 +1,584 (+1.5 KB)
wio-e5 234,324 📈 +1,104 (+1.1 KB)
rak3172 182,068 📈 +1,040 (+1.0 KB)

Updated for c301941

@jp-bennett jp-bennett requested a review from Copilot June 13, 2026 18:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Reworks the TrafficManagementModule cache implementation (linear-scan unified cache + epoch rebase) and introduces persistence-backed “warm” long-tail node retention plus a next-hop overflow hint cache to keep routing/PKI working after NodeDB eviction.

Changes:

  • Replace TMM’s cuckoo-hash cache/indexing with flat arrays + linear scan, add sliding epoch rebase, and add next-hop overflow hint storage/preload.
  • Add WarmNodeStore (file-backed generally, raw-flash ring on nRF52840) and integrate it into NodeDB eviction/migration + PKI DM key lookup.
  • Add/adjust unit tests and nRF52 linker/build guards to reserve the warm-store flash region.

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
variants/nrf52840/nrf52840.ini Pins nRF52840 base env to a warm-store-safe linker script for S140 v6.
variants/nrf52840/nrf52.ini Adds a post-link build guard to prevent the image overlapping the warm-store flash region.
test/test_warm_store/test_main.cpp New unit tests for WarmNodeStore admission/eviction/take() and persistence.
test/test_traffic_management/test_main.cpp Extends TMM tests for congestion-gated hop exhaustion and next-hop overflow cache behavior.
test/test_nodedb_blocked/test_main.cpp New tests for NodeDB migration + favorite/ignored retention with warm-tier demotion.
src/platform/nrf52/nrf52840_s140_v7.ld Shrinks FLASH region to reserve 0xEA000–0xED000 for WarmNodeStore ring.
src/platform/nrf52/nrf52840_s140_v6.ld Adds a new S140 v6 linker script variant with the same warm-store reservation.
src/modules/TrafficManagementModule.h Updates docs and adds APIs/fields for next-hop cache + epoch rebase.
src/modules/TrafficManagementModule.cpp Implements flat caches, next-hop overflow cache, preload, and epoch rebase logic.
src/modules/TraceRouteModule.cpp Mirrors traceroute-derived next-hop info into TMM overflow cache.
src/modules/AdminModule.cpp Routes favorite/ignore changes through NodeDB’s protected-node cap enforcement.
src/mesh/mesh-pb-constants.h Adjusts MAX_NUM_NODES defaults, adds MAX_SATELLITE_NODES/WARM_NODE_COUNT, enables HAS_TRAFFIC_MANAGEMENT by default.
src/mesh/generated/meshtastic/deviceonly.pb.h Updates generated max size constant due to proto size changes.
src/mesh/WarmNodeStore.h Introduces WarmNodeStore API + persistence design and nRF52840 ring layout.
src/mesh/WarmNodeStore.cpp Implements WarmNodeStore memory/persistence (raw-flash ring or warm.dat snapshot).
src/mesh/Router.cpp Uses NodeDB::copyPublicKey() so PKI DMs can decrypt/encrypt for warm-tier nodes.
src/mesh/NodeDB.h Adds warm tier, protected-node cap API, satellite caps, and public key copy helper.
src/mesh/NodeDB.cpp Implements migration demotion to warm tier, satellite caps, protected-node cap, and warm-tier persistence.
src/mesh/NextHopRouter.cpp Stores ACK-confirmed next hops in both NodeDB and TMM, and consults TMM as fallback.
src/mesh/Default.h Changes default position-dedup grid precision (24 → 19 bits).
src/graphics/draw/MenuHandler.cpp Surfaces protected-node-cap failures when favoriting/ignoring via UI.
extra_scripts/nrf52_warm_region.py New post-link guard to fail builds that overlap reserved warm-store flash.

Comment thread src/modules/TrafficManagementModule.cpp Outdated
Comment thread test/test_traffic_management/test_main.cpp Outdated
Comment thread src/mesh/NodeDB.cpp
Comment thread src/mesh/NodeDB.cpp Outdated
Comment thread src/mesh/NodeDB.cpp
@hecatae

hecatae commented Jun 15, 2026

Copy link
Copy Markdown

We probably need to update the app and online maps to accommodate locations not updating over few hours. Currently the maps seem to lose a nodes location if it's not sent every 2 or 3 hours.
Likewise the app gets confused if it doesn't see it.

@NomDeTom NomDeTom force-pushed the pr2-tmm-basic branch 2 times, most recently from e28ef4b to 48a1b68 Compare June 17, 2026 08:33
@NomDeTom NomDeTom requested a review from Copilot June 17, 2026 08:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Comment thread src/modules/TrafficManagementModule.cpp Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 32 out of 32 changed files in this pull request and generated 4 comments.

Comment thread src/mesh/WarmNodeStore.h
Comment thread src/modules/TrafficManagementModule.h Outdated
Comment thread src/modules/AdminModule.cpp
Comment thread src/modules/AdminModule.cpp
@NomDeTom NomDeTom force-pushed the pr2-tmm-basic branch 3 times, most recently from 6ffdf97 to 09bd29d Compare June 17, 2026 23:35
@NomDeTom NomDeTom force-pushed the pr2-tmm-basic branch 5 times, most recently from 93d412f to 453eecf Compare June 20, 2026 03:36
@thebentern thebentern requested a review from Copilot June 20, 2026 13:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 26 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

src/modules/TrafficManagementModule.cpp:705

  • USERPREFS_TMM_APPLY_TO_PRIVATE_CHANNELS is documented (and used in alterReceived()) as extending both position dedup and precision clamping to private/custom-key channels, but the dedup gate here is hard-coded to channels.isWellKnownChannel(). As a result, compiling the flag still won't enable dedup on private channels.
    if (!isFromUs(&mp) && !isToUs(&mp)) {
        if (channels.isWellKnownChannel(mp.channel) && mp.decoded.portnum == meshtastic_PortNum_POSITION_APP) {
            meshtastic_Position pos = meshtastic_Position_init_zero;
            if (pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, &meshtastic_Position_msg, &pos)) {
                if (shouldDropPosition(&mp, &pos, nowMs)) {
                    logAction("drop", &mp, "position-dedup");
                    incrementStat(&stats.position_dedup_drops);
                    ignoreRequest = true;        // Suppress NAK
                    return ProcessMessage::STOP; // Consumed — duplicate will not be rebroadcast
                }

Comment thread src/modules/TrafficManagementModule.cpp
Comment thread src/modules/TrafficManagementModule.h Outdated
Comment thread src/modules/TrafficManagementModule.h
Comment thread test/test_traffic_management/test_main.cpp Outdated
@NomDeTom NomDeTom force-pushed the pr2-tmm-basic branch 2 times, most recently from 1e49f67 to 0c953c3 Compare June 20, 2026 18:25
Adds the Traffic Management module (TMM) plus the NodeDB/warm-store and
next-hop foundations it builds on:

- Unified per-node cache (flat array, 8-bit relative ticks) shared by all
  features; role-aware throttles for tracker / lost-and-found.
- Position deduplication: drop unchanged position rebroadcasts within a
  configurable interval; precision driven off the channel ceiling (clamped to
  the public-key max on well-known channels). Enabled by default at 11h.
- Per-node rate limiting and unknown-packet filtering (config-driven; a
  non-zero companion field enables each feature -- no bool toggles).
- NodeInfo direct response from cache with role-based hop clamps.
- Persistent next-hop overflow store: confirmed hops have no TTL, are seeded
  from NodeInfoLite at boot, and survive hot-store eviction.
- Three-tier sender-role resolution (hot NodeInfoLite -> warm store -> TMM
  cache). Role is cached write-time (seeded on first track, refreshed from
  NodeInfo), pins its cache entry like a next-hop hint, and is evicted last.
- Warm store caches device role + protected category across reboot/eviction.
- PositionModule stationary floor for tracker / lost-and-found.
- PSRAM gating for warm/satellite/TMM cache sizes; STM32WL excluded.

Protobufs: TrafficManagementConfig trimmed to the five uint32 fields actually
used; submodule repointed to protobufs develop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@thebentern thebentern merged commit c51c016 into meshtastic:develop Jun 21, 2026
75 of 77 checks passed
raghumad pushed a commit to raghumad/mezulla-firmware that referenced this pull request Jun 25, 2026
…eshtastic#10706)

Adds the Traffic Management module (TMM) plus the NodeDB/warm-store and
next-hop foundations it builds on:

- Unified per-node cache (flat array, 8-bit relative ticks) shared by all
  features; role-aware throttles for tracker / lost-and-found.
- Position deduplication: drop unchanged position rebroadcasts within a
  configurable interval; precision driven off the channel ceiling (clamped to
  the public-key max on well-known channels). Enabled by default at 11h.
- Per-node rate limiting and unknown-packet filtering (config-driven; a
  non-zero companion field enables each feature -- no bool toggles).
- NodeInfo direct response from cache with role-based hop clamps.
- Persistent next-hop overflow store: confirmed hops have no TTL, are seeded
  from NodeInfoLite at boot, and survive hot-store eviction.
- Three-tier sender-role resolution (hot NodeInfoLite -> warm store -> TMM
  cache). Role is cached write-time (seeded on first track, refreshed from
  NodeInfo), pins its cache entry like a next-hop hint, and is evicted last.
- Warm store caches device role + protected category across reboot/eviction.
- PositionModule stationary floor for tracker / lost-and-found.
- PSRAM gating for warm/satellite/TMM cache sizes; STM32WL excluded.

Protobufs: TrafficManagementConfig trimmed to the five uint32 fields actually
used; submodule repointed to protobufs develop.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2.8 ai-generated Possible AI-generated low-quality content enhancement New feature or request needs-review Needs human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants