Skip to content

Traffic Management Module for packet forwarding logic#9358

Merged
thebentern merged 43 commits into
meshtastic:developfrom
h3lix1:traffic_module
Mar 11, 2026
Merged

Traffic Management Module for packet forwarding logic#9358
thebentern merged 43 commits into
meshtastic:developfrom
h3lix1:traffic_module

Conversation

@h3lix1

@h3lix1 h3lix1 commented Jan 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Large Mesh networks can get noisy fast: repeated position packets, bursty senders, and unknown/undecryptable traffic all consume limited airtime and power. When reaching 1000+ nodes, there needs to be more controls around handling a lot of broadcast traffic.

This PR introduces an optional TrafficManagementModule to reduce that noise without hard-coding one policy for all devices. It gives routers and clients controllable guardrails so they can prioritize useful traffic and keep the mesh healthier under load.

Why?

  • Less unnecessary traffic: position deduplication, rate limiting, and unknown-packet suppression reduce avoidable rebroadcasts.
  • Better routing behavior: hop controls let deployments preserve range for useful packets while still containing telemetry/position spread when desired.
  • Predictable embedded resource usage: a fixed-size 10-byte cache entry and O(1) cuckoo lookups keep memory and per-packet cost bounded.
  • Operational visibility and control: new protobuf config/stats are exposed through Admin and Phone APIs for tuning and monitoring.
  • Safer rollout: feature enablement is gated at both build time (HAS_TRAFFIC_MANAGEMENT, TRAFFIC_MANAGEMENT_CACHE_SIZE) and runtime (moduleConfig.traffic_management.enabled). It is about as self contained as it can be for a new feature.

New Module: TrafficManagementModule

Architecture

classDiagram
    class MeshModule {
        +handleReceived(MeshPacket) ProcessMessage
        +alterReceived(MeshPacket)
        +wantPacket(MeshPacket) bool
        #isPromiscuous bool
        #encryptedOk bool
    }

    class OSThread {
        +runOnce() int32_t
        #setIntervalFromNow(ms)
    }

    class TrafficManagementModule {
        -cacheLock Lock
        -cache UnifiedCacheEntry*
        -stats TrafficManagementStats
        -cacheEpochMs uint32_t
        +getStats() TrafficManagementStats
        +resetStats()
        +recordRouterHopPreserved()
        -shouldDropPosition() bool
        -shouldDropUnknown() bool
        -isRateLimited() bool
        -shouldRespondToNodeInfo() bool
        -computePositionFingerprint()$ uint8_t
    }

    MeshModule <|-- TrafficManagementModule
    OSThread <|-- TrafficManagementModule

    TrafficManagementModule --> Router : allocForSending
    TrafficManagementModule --> MeshService : sendToMesh
Loading
  • Dual inheritance: MeshModule (packet handling) + concurrency::OSThread (periodic maintenance)
  • Location: src/modules/TrafficManagementModule.cpp and src/modules/TrafficManagementModule.h
  • Thread model: Runs as a cooperative OSThread with 60-second maintenance intervals (kMaintenanceIntervalMs)
  • Promiscuous mode: isPromiscuous = true allows inspection of all packets, not just those addressed to this node
  • Encrypted packet support: encryptedOk = true permits handling undecryptable packets for unknown-packet tracking

Compile-Time Gating

Module instantiation in setupModules() requires all three conditions:

flowchart TD
    A[setupModules called] --> B{HAS_TRAFFIC_MANAGEMENT<br/>== 1?}
    B -->|No| Z[Module not compiled]
    B -->|Yes| C{MESHTASTIC_EXCLUDE_<br/>TRAFFIC_MANAGEMENT?}
    C -->|Yes| Z
    C -->|No| D{moduleConfig.<br/>traffic_management.<br/>enabled?}
    D -->|No| Y[Module compiled but<br/>not instantiated]
    D -->|Yes| E[new TrafficManagementModule]
    E --> F[trafficManagementModule = instance]
Loading
  1. HAS_TRAFFIC_MANAGEMENT defined as 1 (variant-level)
  2. !MESHTASTIC_EXCLUDE_TRAFFIC_MANAGEMENT (build exclusion flag)
  3. moduleConfig.traffic_management.enabled (runtime config)

Memory Management for Embedded Devices

Unified Cache with Cuckoo Hashing

The module uses a unified cache combining all per-node tracking into a single 10-byte structure with cuckoo hashing for O(1) lookups. This provides:

  • O(1) lookup via cuckoo hashing - critical at packet processing rates
  • 10 bytes per entry - unified across all platforms
  • Position fingerprinting - deterministic 8-bit fingerprint from truncated coordinates
  • Adaptive timestamp resolution - 8-bit timestamps with ~24 hour range
  • Saturating counters - uint8_t (max 255) for rate/unknown counts

UnifiedCacheEntry Structure (10 bytes) - All Platforms

A single compact structure used across ESP32, NRF52, and all other platforms:

struct __attribute__((packed)) UnifiedCacheEntry {
    NodeNum node;            // 4 bytes - Node identifier (0 = empty)
    uint8_t pos_fingerprint; // 1 byte  - Lower 4 bits of lat + 4 bits of lon
    uint8_t rate_count;      // 1 byte  - Packet count (saturates at 255)
    uint8_t unknown_count;   // 1 byte  - Unknown packet count
    uint8_t pos_time;        // 1 byte  - Position timestamp (adaptive resolution)
    uint8_t rate_time;       // 1 byte  - Rate window start (adaptive resolution)
    uint8_t unknown_time;    // 1 byte  - Unknown tracking start (adaptive resolution)
};
static_assert(sizeof(UnifiedCacheEntry) == 10);

Position Fingerprinting

Instead of storing full coordinates (8 bytes) or using a computed hash, the module uses a deterministic 8-bit fingerprint derived from the truncated lat/lon:

fingerprint = (lat_low4 << 4) | lon_low4

Where lat_low4 and lon_low4 are the lower 4 significant bits of each truncated coordinate.

Benefits over hash-based approach:

  • No hash collisions for adjacent positions: Sequential grid cells have sequential fingerprints
  • Deterministic: Same input always produces same output
  • Collision only at distance: Two positions collide only if they differ by 16+ grid cells in BOTH dimensions

Guard for low precision: If position_precision_bits < 4, uses min(precision, 4) bits from each coordinate.

Adaptive Timestamp Resolution

All timestamps use 8-bit values with adaptive resolution calculated from config at startup:

resolution = max(60, min(339, interval / 2))
  • 60 second minimum ensures reasonable precision for all intervals
  • 339 second maximum allows ~24 hour range (255 × 339 ≈ 86400 seconds)
  • interval/2 ensures at least 2 ticks per configured interval for accuracy

Since config changes require reboot, resolution is calculated once in the constructor.

Memory Efficiency vs NodeDB:

The traffic management cache is dramatically more memory-efficient than full NodeDB entries:

Structure Per-Entry Size 2048 Entries Contents
meshtastic_NodeInfoLite 196 bytes ~400 KB Full node: user info, position, device metrics, public key, etc.
UnifiedCacheEntry 10 bytes ~20 KB Traffic state only: fingerprint, counters, timestamps

The unified cache achieves ~20x memory reduction compared to duplicating NodeDB data because it stores only the minimal state needed for traffic decisions:

  • No encryption keys (32 bytes saved)
  • No user strings (long_name, short_name - ~50 bytes saved)
  • No device metrics (~24 bytes saved)
  • No full coordinates (8 bytes → 1 byte fingerprint)
  • Adaptive 8-bit timestamps with ~24 hour range
  • Saturating counters (8-bit vs 32-bit)

Cuckoo Hashing Algorithm

Cuckoo hashing provides O(1) worst-case lookup using two hash functions:

flowchart TD
    A[lookup node] --> B{cache h1 node == node?}
    B -->|Yes| C[Return entry at h1]
    B -->|No| D{cache h2 node == node?}
    D -->|Yes| E[Return entry at h2]
    D -->|No| F[Not found]

    G[insert node] --> H{slot h1 empty?}
    H -->|Yes| I[Insert at h1]
    H -->|No| J{slot h2 empty?}
    J -->|Yes| K[Insert at h2]
    J -->|No| L[Kick entry from h1]
    L --> M[Place kicked entry at its alternate]
    M --> N{Max kicks reached?}
    N -->|No| L
    N -->|Yes| O[Drop displaced entry]
Loading

Hash functions:

// h1: Simple mask for sequential NodeNums
uint16_t cuckooHash1(NodeNum n) { return n & cacheMask(); }

// h2: Golden ratio multiplicative hash (decorrelated from h1)
uint16_t cuckooHash2(NodeNum n) {
    return ((n * 2654435769u) >> (32 - bits)) & cacheMask();
}

Cuckoo displacement algorithm:

  1. Insert new entry at h1, displacing existing entry
  2. Move displaced entry to its alternate location (h2 if was at h1, or vice versa)
  3. If alternate location occupied, repeat displacement
  4. After 16 kicks (cycle detected), drop the displaced entry to preserve cache integrity

The displaced entry is dropped (not placed at an arbitrary slot) because placing it outside its two valid cuckoo locations would make it unreachable by findEntry(), corrupting the cache. This is the standard resolution for cuckoo cycles with fixed-size tables.

This O(1) lookup is critical for packet processing performance:

  • Predictable latency: Every lookup checks exactly 2 slots (vs O(n) linear scan)
  • Scales with cache size: 1000 entries has same lookup cost as 100 entries
  • No dynamic allocation: All operations work on pre-allocated array
  • Cache-friendly: Sequential memory access for displacement chain

Performance comparison:

Operation Old (Linear Scan) New (Cuckoo Hash)
Lookup O(n) = ~1000 ops O(1) = 2 ops
Insert O(n) = ~1000 ops O(1) amortized

Cache Sizing

Cache size rounds up to power-of-2 for efficient cuckoo hash indexing:

// TRAFFIC_MANAGEMENT_CACHE_SIZE=1000 → cacheSize()=1024
constexpr uint16_t cacheSize() {
    uint16_t n = TRAFFIC_MANAGEMENT_CACHE_SIZE;
    n--; n |= n >> 1; n |= n >> 2; n |= n >> 4; n |= n >> 8;
    return n + 1;
}

Memory Budget Calculations

Cache memory at 2048 entries (unified 10-byte structure):

Platform Allocation Default Entries Total Memory
ESP32 + PSRAM PSRAM 2048 20 KB
ESP32 (no PSRAM) Heap 2048 20 KB
nRF52840 Heap 1024 10 KB
Native/Portduino Heap 2048 20 KB

Note: TRAFFIC_MANAGEMENT_CACHE_SIZE can be overridden per-variant. The value rounds up to the next power of 2 for efficient cuckoo hash indexing (e.g., 1000 → 1024, 2000 → 2048).

Typical available RAM by platform:

Platform Total RAM Free After Boot NodeDB Overhead
ESP32 + PSRAM 320KB DRAM + 4-8MB PSRAM 80-150KB DRAM ~16.6KB (100 nodes)
ESP32 no PSRAM ~320KB 80-150KB ~16.6KB (100 nodes)
nRF52840 256KB 50-80KB ~13.3KB (80 nodes)

Risk assessment:

Platform Free Heap Cache Size % of Free RAM
ESP32 + PSRAM PSRAM: 4-8MB 20KB → PSRAM <1%
ESP32 no PSRAM 80-150KB 20KB → heap 13-25%
nRF52840 ~160KB 10KB → heap ~6%

Current Enablement Status

Traffic management is enabled on:

  • Heltec V4 (ESP32-S3 with PSRAM) - 2048 entries, cache in PSRAM
  • Station G2 (ESP32-S3) - 2048 entries
  • Tracker T1000-E (nRF52840) - 1024 entries, cache in heap
  • Native/Portduino - 2048 entries

Other variants can enable via HAS_TRAFFIC_MANAGEMENT=1 in their variant.h.

Example variant enablement:

// In variant.h
#ifndef HAS_TRAFFIC_MANAGEMENT
#define HAS_TRAFFIC_MANAGEMENT 1
#endif
#ifndef TRAFFIC_MANAGEMENT_CACHE_SIZE
#define TRAFFIC_MANAGEMENT_CACHE_SIZE 2048  // ~20KB with 10-byte entries
#endif

Thread Safety

Lock Architecture

The module uses a single mutable concurrency::Lock cacheLock member to protect all cache and statistics operations.

Codebase Lock Pattern Comparison:

Pattern Declaration Usage Used By
Global pointer extern Lock *spiLock; LockGuard g(spiLock); SPI bus, crypto
Member by value Lock mutex; LockGuard g(&mutex); PhoneAPI, Screen
Mutable member mutable Lock cacheLock; LockGuard g(&cacheLock); TrafficManagementModule

Why mutable? The getStats() method is const but must acquire a lock. Declaring the lock as mutable allows locking in const methods without requiring a dangerous const_cast. This is semantically correct: locking doesn't affect the logical const-ness of the object.

Critical Sections Analysis

Function Lock Scope Duration Notes
getStats() Entire function ~32 byte copy Returns copy to prevent torn reads
resetStats() Entire function Single memset Fast zero-initialization
incrementStat() Entire function Single increment Called frequently
runOnce() Full cache sweep O(CACHE_SIZE) Runs every 60s on OSThread
shouldDropPosition() Cache lookup + update O(1) cuckoo lookup Per-packet cost
isRateLimited() Cache lookup + update O(1) cuckoo lookup Per-packet cost
shouldDropUnknown() Cache lookup + update O(1) cuckoo lookup Per-packet cost

Statistics Counters

  • Protected increment via incrementStat() with lock guard
  • Statistics struct (meshtastic_TrafficManagementStats) is 32 bytes (8 x uint32_t)
  • getStats() returns copy under lock to prevent torn reads across multiple counters

Packet Handling Flow

handleReceived() Processing Order

flowchart TD
    A[Packet Received] --> B{Module Enabled?}
    B -->|No| Z[Return CONTINUE]
    B -->|Yes| C[Increment packets_inspected]

    C --> D{Undecoded Packet?}
    D -->|Yes| E{drop_unknown enabled?}
    E -->|Yes| F{Threshold exceeded?}
    F -->|Yes| G[/"Drop: unknown_packet_drops++<br/>Return STOP"/]
    F -->|No| H[Track in cache]
    E -->|No| H
    H --> Z
    D -->|No| I{NodeInfo Request?}

    I -->|Yes| J{nodeinfo_direct_response<br/>enabled?}
    J -->|Yes| K{want_response &&<br/>!broadcast && !toUs?}
    K -->|Yes| L{hopsAway <= maxHops?}
    L -->|Yes| M[/"Send cached User<br/>nodeinfo_cache_hits++<br/>Return STOP"/]
    L -->|No - too far| N[Continue to next check]
    K -->|No| N
    J -->|No| N
    I -->|No| N

    N --> O{Position Packet?<br/>Not from us?}
    O -->|Yes| P{position_dedup_enabled?}
    P -->|Yes| Q[Decode & truncate lat/lon]
    Q --> R{Duplicate within<br/>min_interval?}
    R -->|Yes| S[/"Drop: position_dedup_drops++<br/>Return STOP"/]
    R -->|No| T[Update cache]
    T --> U
    P -->|No| U
    O -->|No| U

    U{Rate limit check?<br/>Not from us?<br/>Not ROUTING/ADMIN?}
    U -->|Yes| V{rate_limit_enabled?}
    V -->|Yes| W{Limit exceeded?}
    W -->|Yes| X[/"Drop: rate_limit_drops++<br/>Return STOP"/]
    W -->|No| Y[Increment counter]
    Y --> Z
    V -->|No| Z
    U -->|No| Z

    Z[Return CONTINUE]
Loading

NodeInfo Direct Response - Role-Based Limits

Both routers and clients use maxHops logic: respond when hopsAway <= threshold.
Role determines the enforced maximum (not just a default).

Device Role Max Limit Responds to
ROUTER, ROUTER_LATE, CLIENT_BASE 3 Nodes within 0-3 hops
All other roles (clients) 0 Direct neighbors only (0 hops)

Examples:

  • Router with config=0: uses limit (3) → responds to 0, 1, 2, 3 hops
  • Router with config=2: uses 2 → responds to 0, 1, 2 hops
  • Router with config=5: clamped to 3 → responds to 0, 1, 2, 3 hops
  • Client with config=0: uses limit (0) → responds to 0 hops only
  • Client with config=2: clamped to 0 → responds to 0 hops only

Note: nodeinfo_direct_response must be enabled separately for this feature to work.

Adjustable constants in TrafficManagementModule.cpp:

  • kRouterDefaultMaxHops = 3 - Router limit: max 3 hops
  • kClientDefaultMaxHops = 0 - Client limit: direct only (cannot increase)

alterReceived() - Relayed Broadcast Hop Exhaustion

For relayed broadcasts from other nodes (!isFromUs(&mp) && isBroadcast(mp.to)):

  • If exhaust_hop_telemetry and port is TELEMETRY_APP: exhaust hops
  • If exhaust_hop_position and port is POSITION_APP: exhaust hops
  • Sets hop_start = hop_start - hop_limit + 1 to preserve correct hopsAway for the one remaining relay hop
  • Sets hop_limit = 0 and signals exhaustRequested to perhapsRebroadcast()
  • Prevents relayed telemetry/position from propagating further through the mesh
  • Our own outgoing packets are unaffected

Position Truncation Algorithm

Coordinates are truncated to configurable precision for deduplication:

int32_t truncateLatLon(int32_t value, uint8_t precision)
{
    if (precision == 0 || precision >= 32)
        return value;

    uint32_t mask = UINT32_MAX << (32 - precision);
    uint32_t truncated = static_cast<uint32_t>(value) & mask;
    truncated += (1u << (31 - precision));  // Round to center of cell
    return static_cast<int32_t>(truncated);
}

Precision examples (approximate):

Bits Grid Size Use Case
32 ~1cm No truncation
24 ~10m Default - pedestrian/general
20 ~40m Vehicle
16 ~600m City block
12 ~10km Regional

Default Values

Defaults are defined in src/mesh/Default.h and applied at runtime via Default::getConfiguredOrDefault():

Setting Default Meaning
position_precision_bits 24 ~10m grid cells
position_min_interval_secs 86400 (ONE_DAY) 1 day between identical positions

These defaults provide aggressive deduplication suitable for reducing network traffic while still allowing meaningful position updates. Users can adjust via app settings.


Router Hop Preservation

Router.cpp Changes

When traffic_management.router_preserve_hops is enabled and the local device is a router role (ROUTER, ROUTER_LATE, or CLIENT_BASE), hops are preserved for decoded packets except position and telemetry (which have their own exhaust_hop_* controls).

This is a "best effort" approach that does not attempt to identify whether the previous relay was also a router, since the relay_node field only contains the last byte of the node ID (8 bits), making reliable identification impossible due to collision risk.

The feature preserves hop budget when router-role devices relay non-sensor packets (text messages, nodeinfo, routing, etc.), extending effective mesh range through infrastructure routers while still allowing position/telemetry to be managed independently via the exhaust hop settings.


Protocol Buffer Definitions

TrafficManagementConfig (module_config.proto)

14 configuration fields using nanopb STATIC encoding:

message TrafficManagementConfig {
    bool enabled = 1;
    bool position_dedup_enabled = 2;
    uint32 position_precision_bits = 3;
    uint32 position_min_interval_secs = 4;
    bool nodeinfo_direct_response = 5;
    uint32 nodeinfo_direct_response_max_hops = 6;
    bool rate_limit_enabled = 7;
    uint32 rate_limit_window_secs = 8;
    uint32 rate_limit_max_packets = 9;
    bool drop_unknown_enabled = 10;
    uint32 unknown_packet_threshold = 11;
    bool exhaust_hop_telemetry = 12;
    bool exhaust_hop_position = 13;
    bool router_preserve_hops = 14;
}

Generated C struct: meshtastic_ModuleConfig_TrafficManagementConfig (~36 bytes)

TrafficManagementStats (telemetry.proto)

7 counter fields for telemetry reporting:

message TrafficManagementStats {
    uint32 packets_inspected = 1;
    uint32 position_dedup_drops = 2;
    uint32 nodeinfo_cache_hits = 3;
    uint32 rate_limit_drops = 4;
    uint32 unknown_packet_drops = 5;
    uint32 hop_exhausted_packets = 6;
    uint32 router_hops_preserved = 7;
}

Generated C struct: meshtastic_TrafficManagementStats (28 bytes)


Admin/Phone API Integration

AdminModule.cpp Changes

Get handler (handleGetModuleConfig):

case meshtastic_AdminMessage_ModuleConfigType_TRAFFICMANAGEMENT_CONFIG:
    res.get_module_config_response.which_payload_variant =
        meshtastic_ModuleConfig_traffic_management_tag;
    res.get_module_config_response.payload_variant.traffic_management =
        moduleConfig.traffic_management;
    break;

Set handler (handleSetModuleConfig):

case meshtastic_ModuleConfig_traffic_management_tag:
    moduleConfig.has_traffic_management = true;
    moduleConfig.traffic_management = c.payload_variant.traffic_management;
    break;

PhoneAPI.cpp Changes

Traffic management config included in module config enumeration sent to connected clients. The enumeration loop uses the auto-updating _meshtastic_AdminMessage_ModuleConfigType_MAX + 1 pattern to detect when all module configs have been sent.


Periodic Maintenance Thread

The runOnce() method executes every 60 seconds to garbage-collect stale cache entries.

For each cache entry, individual tracking data (position, rate, unknown) is checked against its TTL:

  • Position data: 4x the configured position_min_interval_secs
  • Rate limit data: 2x the configured rate_limit_window_secs (or 10 minutes if unconfigured)
  • Unknown tracking data: 5x the unknown reset window (5 minutes)

If all tracking data for an entry has expired, the entire slot is freed. The epoch is also checked and reset when relative timestamps approach 8-bit overflow (~19 hours at maximum resolution).


Build/Variant Enablement

mesh-pb-constants.h Additions

// Default disabled; variants opt-in
#ifndef HAS_TRAFFIC_MANAGEMENT
#define HAS_TRAFFIC_MANAGEMENT 0
#endif

// Default cache size when enabled
#ifndef TRAFFIC_MANAGEMENT_CACHE_SIZE
#if HAS_TRAFFIC_MANAGEMENT
#define TRAFFIC_MANAGEMENT_CACHE_SIZE 1000
#else
#define TRAFFIC_MANAGEMENT_CACHE_SIZE 0
#endif
#endif

Variant Example: Heltec V4

variants/esp32s3/heltec_v4/variant.h:

#ifndef HAS_TRAFFIC_MANAGEMENT
#define HAS_TRAFFIC_MANAGEMENT 1
#endif
#ifndef TRAFFIC_MANAGEMENT_CACHE_SIZE
#define TRAFFIC_MANAGEMENT_CACHE_SIZE 2048
#endif

@h3lix1 h3lix1 marked this pull request as draft January 19, 2026 09:34
@h3lix1 h3lix1 force-pushed the traffic_module branch 2 times, most recently from 27759c2 to 9beb6db Compare January 19, 2026 23:45
@h3lix1 h3lix1 force-pushed the traffic_module branch 5 times, most recently from 566f048 to e87d7a7 Compare February 15, 2026 03:40
@garthvh garthvh requested a review from Copilot February 16, 2026 22:31

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

This PR introduces a new Traffic Management Module to optimize mesh network packet forwarding and reduce unnecessary traffic. The module provides position deduplication, per-node rate limiting, unknown packet filtering, NodeInfo direct response from cache, and hop exhaustion for telemetry/position broadcasts.

Changes:

  • Implements a memory-efficient unified cache with cuckoo hashing providing O(1) lookups, using 10 bytes per entry across all platforms
  • Enables the module on four hardware variants (Heltec V4, Station G2, Tracker T1000-E, and Native/Portduino) with appropriate cache sizes based on available RAM
  • Adds comprehensive unit tests covering all traffic management features and edge cases

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
variants/nrf52840/tracker-t1000-e/variant.h Enables traffic management with 1024-entry cache for NRF52840 platform
variants/native/portduino/variant.h Enables traffic management with 2048-entry cache for native/testing platform
variants/esp32s3/station-g2/variant.h Enables traffic management with 2048-entry cache for Station G2 device
variants/esp32s3/heltec_v4/variant.h Enables traffic management with 2048-entry cache and removes trailing whitespace
test/test_traffic_management/test_main.cpp Adds 22 unit tests covering all module features and edge cases
src/modules/TrafficManagementModule.h Defines module interface with unified cache structure and cuckoo hashing
src/modules/TrafficManagementModule.cpp Implements traffic management logic with packet filtering and cache operations
src/modules/Modules.cpp Adds conditional module instantiation when enabled
src/modules/AdminModule.cpp Adds get/set handlers for traffic management configuration
src/mesh/mesh-pb-constants.h Defines compile-time flags and default cache size
src/mesh/Router.cpp Adds router hop preservation logic for non-sensor packets
src/mesh/PhoneAPI.cpp Adds traffic management config to phone API enumeration
src/mesh/NextHopRouter.cpp Integrates hop exhaustion into packet rebroadcast logic
src/mesh/Default.h Defines default position precision and interval values
src/configuration.h Adds exclusion flag for minimal builds
protobufs Updates submodule reference for traffic management protobuf definitions
Comments suppressed due to low confidence (3)

src/modules/TrafficManagementModule.h:1

  • The comment claims '56% memory reduction' but doesn't specify what this is compared to. The PR description mentions '~20x memory reduction' compared to duplicating NodeDB entries, which is more accurate. Either remove the '56%' figure or clarify what baseline it refers to (e.g., 'compared to separate per-feature caches').
#pragma once

src/modules/TrafficManagementModule.h:1

  • The comment states timestamps are '16-bit relative' but the implementation uses 8-bit timestamps (uint8_t pos_time, rate_time, unknown_time) as documented elsewhere in the file. Update to '8-bit relative offsets'.
#pragma once

src/modules/TrafficManagementModule.cpp:1

  • The comment mentions '~3.5 hours' but the actual threshold in needsEpochReset() is 200 ticks × max resolution. With max resolution of 339 seconds, this is 200 × 339 = 67,800 seconds = ~18.8 hours, not 3.5 hours. Update the comment to match the implementation: '~19 hours (approaching 8-bit overflow with adaptive resolution)'.
#include "TrafficManagementModule.h"

Comment thread variants/nrf52840/tracker-t1000-e/variant.h Outdated
Comment thread src/modules/TrafficManagementModule.cpp Outdated
@thebentern thebentern requested a review from Copilot February 16, 2026 22:39

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 16 out of 16 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

src/modules/TrafficManagementModule.h:1

  • The comment states timestamps are stored as 16-bit values, but the actual implementation uses 8-bit timestamps (uint8_t pos_time, rate_time, unknown_time in UnifiedCacheEntry). This should be corrected to '8-bit relative offsets' to match the implementation.
#pragma once

src/modules/TrafficManagementModule.cpp:1

  • The comment mentions '8-bit minute overflow' and '~3.5 hours', but the needsEpochReset() function checks for 200 ticks at maximum resolution of 339 seconds, which equals ~19 hours (200 * 339 / 3600 ≈ 18.8 hours), not 3.5 hours. The comment should be updated to reflect the actual ~19 hour threshold.
#include "TrafficManagementModule.h"

@h3lix1 h3lix1 marked this pull request as ready for review February 16, 2026 22:59
@h3lix1 h3lix1 force-pushed the traffic_module branch 2 times, most recently from 8e40cfe to 8a7320a Compare February 27, 2026 07:58
Comment thread src/modules/TrafficManagementModule.cpp
Comment thread src/modules/TrafficManagementModule.cpp Outdated
Comment thread src/modules/TrafficManagementModule.cpp Outdated
Comment thread src/modules/TrafficManagementModule.cpp Outdated
@h3lix1

h3lix1 commented Mar 2, 2026

Copy link
Copy Markdown
Contributor Author

@robekl Feel free to send me your ko-fi (or the like) for apprecaition of finding these.

@robekl

robekl commented Mar 3, 2026

Copy link
Copy Markdown

@robekl Feel free to send me your ko-fi (or the like) for apprecaition of finding these.

Thanks, not necessary. I have also been asked to stop reviewing code. 🤷‍♂️

… and position deduplication logic. Added tests to ensure local packets bypass transit filters and that NodeInfo requests correctly update the requester information in the cache. Updated deduplication checks to prevent dropping valid position packets under certain conditions.
@thebentern thebentern added the enhancement New feature or request label Mar 9, 2026
@thebentern thebentern merged commit 016e68e into meshtastic:develop Mar 11, 2026
77 checks passed
// Adjust hop_start so downstream nodes compute correct hopsAway (hop_start - hop_limit).
// Without this, hop_limit=0 with original hop_start would show inflated hopsAway.
mp.hop_start = mp.hop_start - mp.hop_limit + 1;
mp.hop_limit = 0;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm slightly concerned that this is a universal block, and I'm not happy with it.

I suggest (in no particular order):

  • Rather than block, exclude from free hops on routers
  • Rather than block, enforce a maximum hops (make them the equivalent of hopstart =3 or something)
  • Gracefully throttle based on chutil
  • Gracefully throttle based on frequency (enforce a minimum interval)
  • Rather than block, charge additional hops, e.g. hops remaining-2

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I would also ask that the role of the originator be considered. What is the point of sensor or tracker roles if not to send telemetry and position packets?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'll answer, but in the particular order provided.

It's not a universal block, but it does limit the number of hops left. I should probably gate this behind ROUTER-like roles though to enforce that it's only for nodes that can send packets with a large radius. My expectation is that it will take a couple hops to get to a router, and that it will likely be heard by multiple routers before the hops are limited.

  • Position and telemetry packets are already excluded from free hops on routers (at least with this feature)
  • This is possible.. for our mesh that's still a very large radius, and this will run amuck with "overheard hoptimization". Thus the reason why hop_limit of 0 was chosen..
  • chutil is a metric that I'd like to stay away from to base these decisions on.. Meshes considering using this module are likely already in the weeds when it comes to chutil.
  • Tracking that will likely exceed memory constraints. I can see what can be done here.
  • I think this goes with point 2, where overheard hoptimization will start reverting hops back on un-updated nodes.

I agree about the originator to be considered, but to do that we'll need to increase the size of nodedb. The meshes that would want this are likely much larger than than MAX_NUM_NODES, making knowing if a node is a SENSOR or TRACKER role difficult.

I think we can look into this as a solution for now for large meshes until someone can think of something better. It's a bit heavy handed, but I think that's necessary for now until more clients are updated with better congestion management.

korbinianbauer pushed a commit to korbinianbauer/firmware that referenced this pull request Mar 23, 2026
* Add ESP32 Power Management lessons learned document

Documents our experimentation with ESP-IDF DFS and why it doesn't
work well for Meshtastic (RTOS locks, BLE locks, USB issues).

Proposes simpler alternative: manual setCpuFrequencyMhz() control
with explicit triggers for when to go fast vs slow.

* Addition of traffic management module

* Fixing compile issues, but may still need to update protobufs.

* Fixing log2Floor in cuckoo hash function

* Adding support for traffic management in PhoneAPI.

* Making router_preserve_hops work without checking if the previous hop was a router. Also works for CLIENT_BASE.

* Adding station-g2 and portduino varients to be able to use this module.

* Spoofing from address for nodeinfo cache

* Changing name and behavior for zero_hop_telemetry / zero_hop_position

* Name change for exhausting telemetry packets and setting hop_limit to 1 so it will be 0 when sent.

* Updated hop logic, including exhaustRequested flag to bypass some checks later in the code.

* Reducing memory on nrf52 nodes further to 12 bytes per entry, 12KB total using 8 bit hashes with 0.4% collision. Probably ok. Adding portduino to the platforms that don't need to worry about memory as much.

* Fixing hopsAway for nodeinfo responses.

* traffic_management.nodeinfo_direct_response_min_hops -> traffic_management.nodeinfo_direct_response_max_hops

* Removing dry run mode

* Updates to UnifiedCacheEntry to use a common cache, created defaults for some values, reduced a couple bytes per entry by using a resolution-scale time selection based on configuration value.

* Enhance traffic management logging and configuration. Updated log messages in NextHopRouter and Router to include more context. Adjusted traffic management configuration checks in AdminModule and improved cache handling in TrafficManagementModule. Ensured consistent enabling of traffic management across various variants.

* Implement destructor for TrafficManagementModule and improve cache allocation handling. The destructor ensures proper deallocation of cache memory based on its allocation source (PSRAM or heap). Additionally, updated cache allocation logic to log warnings only when PSRAM allocation fails.

* Update TrafficManagementModule with enhanced comments for clarity and improve cache handling logic. Update protobuf submodule to latest commit.

* Creating consistent log messages

* Remove docs/ESP32_Power_Management.md from traffic_module

* Add unit tests for Traffic Management Module functionality

* Fixing compile issues, but may still need to update protobufs.

* Adding support for traffic management in PhoneAPI.

* Making router_preserve_hops work without checking if the previous hop was a router. Also works for CLIENT_BASE.

* Enhance traffic management logging and configuration. Updated log messages in NextHopRouter and Router to include more context. Adjusted traffic management configuration checks in AdminModule and improved cache handling in TrafficManagementModule. Ensured consistent enabling of traffic management across various variants.

* Implement destructor for TrafficManagementModule and improve cache allocation handling. The destructor ensures proper deallocation of cache memory based on its allocation source (PSRAM or heap). Additionally, updated cache allocation logic to log warnings only when PSRAM allocation fails.

* Update TrafficManagementModule with enhanced comments for clarity and improve cache handling logic. Update protobuf submodule to latest commit.

* Add mock classes and unit tests for Traffic Management Module functionality.

* Refactor setup and loop functions in test_main.cpp to include extern "C" linkage

* Update comment to include reduced  memory requirements

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Re-arranging comments for programmers with the attention span of less than 5 lines of code.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update comments in TrafficManagementModule to reflect changes in timestamp epoch handling and memory optimization details.

* bug: Use node-wide config_ok_to_mqtt setting for cached NodeInfo replies.

* Better way to handle clearing the ok_to_mqtt bit

* Add bucketing to cuckoo hashing, allowing for 95% occupied rate before major eviction problems.

* Extend nodeinfo cache for psram devices.

* Refactor traffic management to make hop exhaustion packet-scoped. Nice catch.

* Implement better position precision sanitization in TrafficManagementModule.

* Added logic in TrafficManagementModule to invalidate stale traffic state. Also, added some tests to avoid future me from creating a regression here.

* Fixing tests for native

* Enhance TrafficManagementModule to improve NodeInfo response handling and position deduplication logic. Added tests to ensure local packets bypass transit filters and that NodeInfo requests correctly update the requester information in the cache. Updated deduplication checks to prevent dropping valid position packets under certain conditions.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
korbinianbauer pushed a commit to korbinianbauer/firmware that referenced this pull request Mar 23, 2026
* Add ESP32 Power Management lessons learned document

Documents our experimentation with ESP-IDF DFS and why it doesn't
work well for Meshtastic (RTOS locks, BLE locks, USB issues).

Proposes simpler alternative: manual setCpuFrequencyMhz() control
with explicit triggers for when to go fast vs slow.

* Addition of traffic management module

* Fixing compile issues, but may still need to update protobufs.

* Fixing log2Floor in cuckoo hash function

* Adding support for traffic management in PhoneAPI.

* Making router_preserve_hops work without checking if the previous hop was a router. Also works for CLIENT_BASE.

* Adding station-g2 and portduino varients to be able to use this module.

* Spoofing from address for nodeinfo cache

* Changing name and behavior for zero_hop_telemetry / zero_hop_position

* Name change for exhausting telemetry packets and setting hop_limit to 1 so it will be 0 when sent.

* Updated hop logic, including exhaustRequested flag to bypass some checks later in the code.

* Reducing memory on nrf52 nodes further to 12 bytes per entry, 12KB total using 8 bit hashes with 0.4% collision. Probably ok. Adding portduino to the platforms that don't need to worry about memory as much.

* Fixing hopsAway for nodeinfo responses.

* traffic_management.nodeinfo_direct_response_min_hops -> traffic_management.nodeinfo_direct_response_max_hops

* Removing dry run mode

* Updates to UnifiedCacheEntry to use a common cache, created defaults for some values, reduced a couple bytes per entry by using a resolution-scale time selection based on configuration value.

* Enhance traffic management logging and configuration. Updated log messages in NextHopRouter and Router to include more context. Adjusted traffic management configuration checks in AdminModule and improved cache handling in TrafficManagementModule. Ensured consistent enabling of traffic management across various variants.

* Implement destructor for TrafficManagementModule and improve cache allocation handling. The destructor ensures proper deallocation of cache memory based on its allocation source (PSRAM or heap). Additionally, updated cache allocation logic to log warnings only when PSRAM allocation fails.

* Update TrafficManagementModule with enhanced comments for clarity and improve cache handling logic. Update protobuf submodule to latest commit.

* Creating consistent log messages

* Remove docs/ESP32_Power_Management.md from traffic_module

* Add unit tests for Traffic Management Module functionality

* Fixing compile issues, but may still need to update protobufs.

* Adding support for traffic management in PhoneAPI.

* Making router_preserve_hops work without checking if the previous hop was a router. Also works for CLIENT_BASE.

* Enhance traffic management logging and configuration. Updated log messages in NextHopRouter and Router to include more context. Adjusted traffic management configuration checks in AdminModule and improved cache handling in TrafficManagementModule. Ensured consistent enabling of traffic management across various variants.

* Implement destructor for TrafficManagementModule and improve cache allocation handling. The destructor ensures proper deallocation of cache memory based on its allocation source (PSRAM or heap). Additionally, updated cache allocation logic to log warnings only when PSRAM allocation fails.

* Update TrafficManagementModule with enhanced comments for clarity and improve cache handling logic. Update protobuf submodule to latest commit.

* Add mock classes and unit tests for Traffic Management Module functionality.

* Refactor setup and loop functions in test_main.cpp to include extern "C" linkage

* Update comment to include reduced  memory requirements

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Re-arranging comments for programmers with the attention span of less than 5 lines of code.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update comments in TrafficManagementModule to reflect changes in timestamp epoch handling and memory optimization details.

* bug: Use node-wide config_ok_to_mqtt setting for cached NodeInfo replies.

* Better way to handle clearing the ok_to_mqtt bit

* Add bucketing to cuckoo hashing, allowing for 95% occupied rate before major eviction problems.

* Extend nodeinfo cache for psram devices.

* Refactor traffic management to make hop exhaustion packet-scoped. Nice catch.

* Implement better position precision sanitization in TrafficManagementModule.

* Added logic in TrafficManagementModule to invalidate stale traffic state. Also, added some tests to avoid future me from creating a regression here.

* Fixing tests for native

* Enhance TrafficManagementModule to improve NodeInfo response handling and position deduplication logic. Added tests to ensure local packets bypass transit filters and that NodeInfo requests correctly update the requester information in the cache. Updated deduplication checks to prevent dropping valid position packets under certain conditions.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
oumike pushed a commit to oumike/firmware that referenced this pull request Mar 25, 2026
* Add ESP32 Power Management lessons learned document

Documents our experimentation with ESP-IDF DFS and why it doesn't
work well for Meshtastic (RTOS locks, BLE locks, USB issues).

Proposes simpler alternative: manual setCpuFrequencyMhz() control
with explicit triggers for when to go fast vs slow.

* Addition of traffic management module

* Fixing compile issues, but may still need to update protobufs.

* Fixing log2Floor in cuckoo hash function

* Adding support for traffic management in PhoneAPI.

* Making router_preserve_hops work without checking if the previous hop was a router. Also works for CLIENT_BASE.

* Adding station-g2 and portduino varients to be able to use this module.

* Spoofing from address for nodeinfo cache

* Changing name and behavior for zero_hop_telemetry / zero_hop_position

* Name change for exhausting telemetry packets and setting hop_limit to 1 so it will be 0 when sent.

* Updated hop logic, including exhaustRequested flag to bypass some checks later in the code.

* Reducing memory on nrf52 nodes further to 12 bytes per entry, 12KB total using 8 bit hashes with 0.4% collision. Probably ok. Adding portduino to the platforms that don't need to worry about memory as much.

* Fixing hopsAway for nodeinfo responses.

* traffic_management.nodeinfo_direct_response_min_hops -> traffic_management.nodeinfo_direct_response_max_hops

* Removing dry run mode

* Updates to UnifiedCacheEntry to use a common cache, created defaults for some values, reduced a couple bytes per entry by using a resolution-scale time selection based on configuration value.

* Enhance traffic management logging and configuration. Updated log messages in NextHopRouter and Router to include more context. Adjusted traffic management configuration checks in AdminModule and improved cache handling in TrafficManagementModule. Ensured consistent enabling of traffic management across various variants.

* Implement destructor for TrafficManagementModule and improve cache allocation handling. The destructor ensures proper deallocation of cache memory based on its allocation source (PSRAM or heap). Additionally, updated cache allocation logic to log warnings only when PSRAM allocation fails.

* Update TrafficManagementModule with enhanced comments for clarity and improve cache handling logic. Update protobuf submodule to latest commit.

* Creating consistent log messages

* Remove docs/ESP32_Power_Management.md from traffic_module

* Add unit tests for Traffic Management Module functionality

* Fixing compile issues, but may still need to update protobufs.

* Adding support for traffic management in PhoneAPI.

* Making router_preserve_hops work without checking if the previous hop was a router. Also works for CLIENT_BASE.

* Enhance traffic management logging and configuration. Updated log messages in NextHopRouter and Router to include more context. Adjusted traffic management configuration checks in AdminModule and improved cache handling in TrafficManagementModule. Ensured consistent enabling of traffic management across various variants.

* Implement destructor for TrafficManagementModule and improve cache allocation handling. The destructor ensures proper deallocation of cache memory based on its allocation source (PSRAM or heap). Additionally, updated cache allocation logic to log warnings only when PSRAM allocation fails.

* Update TrafficManagementModule with enhanced comments for clarity and improve cache handling logic. Update protobuf submodule to latest commit.

* Add mock classes and unit tests for Traffic Management Module functionality.

* Refactor setup and loop functions in test_main.cpp to include extern "C" linkage

* Update comment to include reduced  memory requirements

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Re-arranging comments for programmers with the attention span of less than 5 lines of code.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update comments in TrafficManagementModule to reflect changes in timestamp epoch handling and memory optimization details.

* bug: Use node-wide config_ok_to_mqtt setting for cached NodeInfo replies.

* Better way to handle clearing the ok_to_mqtt bit

* Add bucketing to cuckoo hashing, allowing for 95% occupied rate before major eviction problems.

* Extend nodeinfo cache for psram devices.

* Refactor traffic management to make hop exhaustion packet-scoped. Nice catch.

* Implement better position precision sanitization in TrafficManagementModule.

* Added logic in TrafficManagementModule to invalidate stale traffic state. Also, added some tests to avoid future me from creating a regression here.

* Fixing tests for native

* Enhance TrafficManagementModule to improve NodeInfo response handling and position deduplication logic. Added tests to ensure local packets bypass transit filters and that NodeInfo requests correctly update the requester information in the cache. Updated deduplication checks to prevent dropping valid position packets under certain conditions.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
oumike pushed a commit to oumike/firmware that referenced this pull request Mar 27, 2026
* Add ESP32 Power Management lessons learned document

Documents our experimentation with ESP-IDF DFS and why it doesn't
work well for Meshtastic (RTOS locks, BLE locks, USB issues).

Proposes simpler alternative: manual setCpuFrequencyMhz() control
with explicit triggers for when to go fast vs slow.

* Addition of traffic management module

* Fixing compile issues, but may still need to update protobufs.

* Fixing log2Floor in cuckoo hash function

* Adding support for traffic management in PhoneAPI.

* Making router_preserve_hops work without checking if the previous hop was a router. Also works for CLIENT_BASE.

* Adding station-g2 and portduino varients to be able to use this module.

* Spoofing from address for nodeinfo cache

* Changing name and behavior for zero_hop_telemetry / zero_hop_position

* Name change for exhausting telemetry packets and setting hop_limit to 1 so it will be 0 when sent.

* Updated hop logic, including exhaustRequested flag to bypass some checks later in the code.

* Reducing memory on nrf52 nodes further to 12 bytes per entry, 12KB total using 8 bit hashes with 0.4% collision. Probably ok. Adding portduino to the platforms that don't need to worry about memory as much.

* Fixing hopsAway for nodeinfo responses.

* traffic_management.nodeinfo_direct_response_min_hops -> traffic_management.nodeinfo_direct_response_max_hops

* Removing dry run mode

* Updates to UnifiedCacheEntry to use a common cache, created defaults for some values, reduced a couple bytes per entry by using a resolution-scale time selection based on configuration value.

* Enhance traffic management logging and configuration. Updated log messages in NextHopRouter and Router to include more context. Adjusted traffic management configuration checks in AdminModule and improved cache handling in TrafficManagementModule. Ensured consistent enabling of traffic management across various variants.

* Implement destructor for TrafficManagementModule and improve cache allocation handling. The destructor ensures proper deallocation of cache memory based on its allocation source (PSRAM or heap). Additionally, updated cache allocation logic to log warnings only when PSRAM allocation fails.

* Update TrafficManagementModule with enhanced comments for clarity and improve cache handling logic. Update protobuf submodule to latest commit.

* Creating consistent log messages

* Remove docs/ESP32_Power_Management.md from traffic_module

* Add unit tests for Traffic Management Module functionality

* Fixing compile issues, but may still need to update protobufs.

* Adding support for traffic management in PhoneAPI.

* Making router_preserve_hops work without checking if the previous hop was a router. Also works for CLIENT_BASE.

* Enhance traffic management logging and configuration. Updated log messages in NextHopRouter and Router to include more context. Adjusted traffic management configuration checks in AdminModule and improved cache handling in TrafficManagementModule. Ensured consistent enabling of traffic management across various variants.

* Implement destructor for TrafficManagementModule and improve cache allocation handling. The destructor ensures proper deallocation of cache memory based on its allocation source (PSRAM or heap). Additionally, updated cache allocation logic to log warnings only when PSRAM allocation fails.

* Update TrafficManagementModule with enhanced comments for clarity and improve cache handling logic. Update protobuf submodule to latest commit.

* Add mock classes and unit tests for Traffic Management Module functionality.

* Refactor setup and loop functions in test_main.cpp to include extern "C" linkage

* Update comment to include reduced  memory requirements

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Re-arranging comments for programmers with the attention span of less than 5 lines of code.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update comments in TrafficManagementModule to reflect changes in timestamp epoch handling and memory optimization details.

* bug: Use node-wide config_ok_to_mqtt setting for cached NodeInfo replies.

* Better way to handle clearing the ok_to_mqtt bit

* Add bucketing to cuckoo hashing, allowing for 95% occupied rate before major eviction problems.

* Extend nodeinfo cache for psram devices.

* Refactor traffic management to make hop exhaustion packet-scoped. Nice catch.

* Implement better position precision sanitization in TrafficManagementModule.

* Added logic in TrafficManagementModule to invalidate stale traffic state. Also, added some tests to avoid future me from creating a regression here.

* Fixing tests for native

* Enhance TrafficManagementModule to improve NodeInfo response handling and position deduplication logic. Added tests to ensure local packets bypass transit filters and that NodeInfo requests correctly update the requester information in the cache. Updated deduplication checks to prevent dropping valid position packets under certain conditions.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@h3lix1

h3lix1 commented Apr 10, 2026

Copy link
Copy Markdown
Contributor Author

@thebentern @NomDeTom What are the blockers left to getting this into .21 or .22? This with #9921 puts a good guard rail in place for misconfiguration on small networks that don't need it.

mariotti pushed a commit to mariotti/firmware that referenced this pull request May 6, 2026
* Add ESP32 Power Management lessons learned document

Documents our experimentation with ESP-IDF DFS and why it doesn't
work well for Meshtastic (RTOS locks, BLE locks, USB issues).

Proposes simpler alternative: manual setCpuFrequencyMhz() control
with explicit triggers for when to go fast vs slow.

* Addition of traffic management module

* Fixing compile issues, but may still need to update protobufs.

* Fixing log2Floor in cuckoo hash function

* Adding support for traffic management in PhoneAPI.

* Making router_preserve_hops work without checking if the previous hop was a router. Also works for CLIENT_BASE.

* Adding station-g2 and portduino varients to be able to use this module.

* Spoofing from address for nodeinfo cache

* Changing name and behavior for zero_hop_telemetry / zero_hop_position

* Name change for exhausting telemetry packets and setting hop_limit to 1 so it will be 0 when sent.

* Updated hop logic, including exhaustRequested flag to bypass some checks later in the code.

* Reducing memory on nrf52 nodes further to 12 bytes per entry, 12KB total using 8 bit hashes with 0.4% collision. Probably ok. Adding portduino to the platforms that don't need to worry about memory as much.

* Fixing hopsAway for nodeinfo responses.

* traffic_management.nodeinfo_direct_response_min_hops -> traffic_management.nodeinfo_direct_response_max_hops

* Removing dry run mode

* Updates to UnifiedCacheEntry to use a common cache, created defaults for some values, reduced a couple bytes per entry by using a resolution-scale time selection based on configuration value.

* Enhance traffic management logging and configuration. Updated log messages in NextHopRouter and Router to include more context. Adjusted traffic management configuration checks in AdminModule and improved cache handling in TrafficManagementModule. Ensured consistent enabling of traffic management across various variants.

* Implement destructor for TrafficManagementModule and improve cache allocation handling. The destructor ensures proper deallocation of cache memory based on its allocation source (PSRAM or heap). Additionally, updated cache allocation logic to log warnings only when PSRAM allocation fails.

* Update TrafficManagementModule with enhanced comments for clarity and improve cache handling logic. Update protobuf submodule to latest commit.

* Creating consistent log messages

* Remove docs/ESP32_Power_Management.md from traffic_module

* Add unit tests for Traffic Management Module functionality

* Fixing compile issues, but may still need to update protobufs.

* Adding support for traffic management in PhoneAPI.

* Making router_preserve_hops work without checking if the previous hop was a router. Also works for CLIENT_BASE.

* Enhance traffic management logging and configuration. Updated log messages in NextHopRouter and Router to include more context. Adjusted traffic management configuration checks in AdminModule and improved cache handling in TrafficManagementModule. Ensured consistent enabling of traffic management across various variants.

* Implement destructor for TrafficManagementModule and improve cache allocation handling. The destructor ensures proper deallocation of cache memory based on its allocation source (PSRAM or heap). Additionally, updated cache allocation logic to log warnings only when PSRAM allocation fails.

* Update TrafficManagementModule with enhanced comments for clarity and improve cache handling logic. Update protobuf submodule to latest commit.

* Add mock classes and unit tests for Traffic Management Module functionality.

* Refactor setup and loop functions in test_main.cpp to include extern "C" linkage

* Update comment to include reduced  memory requirements

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Re-arranging comments for programmers with the attention span of less than 5 lines of code.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update comments in TrafficManagementModule to reflect changes in timestamp epoch handling and memory optimization details.

* bug: Use node-wide config_ok_to_mqtt setting for cached NodeInfo replies.

* Better way to handle clearing the ok_to_mqtt bit

* Add bucketing to cuckoo hashing, allowing for 95% occupied rate before major eviction problems.

* Extend nodeinfo cache for psram devices.

* Refactor traffic management to make hop exhaustion packet-scoped. Nice catch.

* Implement better position precision sanitization in TrafficManagementModule.

* Added logic in TrafficManagementModule to invalidate stale traffic state. Also, added some tests to avoid future me from creating a regression here.

* Fixing tests for native

* Enhance TrafficManagementModule to improve NodeInfo response handling and position deduplication logic. Added tests to ensure local packets bypass transit filters and that NodeInfo requests correctly update the requester information in the cache. Updated deduplication checks to prevent dropping valid position packets under certain conditions.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants