Traffic Management Module for packet forwarding logic#9358
Conversation
27759c2 to
9beb6db
Compare
566f048 to
e87d7a7
Compare
There was a problem hiding this comment.
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"
There was a problem hiding this comment.
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"
8e40cfe to
8a7320a
Compare
|
@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. 🤷♂️ |
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.
… was a router. Also works for CLIENT_BASE.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
… than 5 lines of code. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…stamp epoch handling and memory optimization details.
…e major eviction problems.
…ate. Also, added some tests to avoid future me from creating a regression here.
… 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.
| // 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; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
* 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>
* 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>
* 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>
* 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>
|
@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. |
* 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>
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
TrafficManagementModuleto 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?
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 : sendToMeshMeshModule(packet handling) +concurrency::OSThread(periodic maintenance)src/modules/TrafficManagementModule.cppandsrc/modules/TrafficManagementModule.hkMaintenanceIntervalMs)isPromiscuous = trueallows inspection of all packets, not just those addressed to this nodeencryptedOk = truepermits handling undecryptable packets for unknown-packet trackingCompile-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]HAS_TRAFFIC_MANAGEMENTdefined as 1 (variant-level)!MESHTASTIC_EXCLUDE_TRAFFIC_MANAGEMENT(build exclusion flag)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:
UnifiedCacheEntry Structure (10 bytes) - All Platforms
A single compact structure used across ESP32, NRF52, and all other platforms:
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_low4Where
lat_low4andlon_low4are the lower 4 significant bits of each truncated coordinate.Benefits over hash-based approach:
Guard for low precision: If
position_precision_bits < 4, usesmin(precision, 4)bits from each coordinate.Adaptive Timestamp Resolution
All timestamps use 8-bit values with adaptive resolution calculated from config at startup:
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:
meshtastic_NodeInfoLiteUnifiedCacheEntryThe unified cache achieves ~20x memory reduction compared to duplicating NodeDB data because it stores only the minimal state needed for traffic decisions:
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]Hash functions:
Cuckoo displacement algorithm:
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:
Performance comparison:
Cache Sizing
Cache size rounds up to power-of-2 for efficient cuckoo hash indexing:
Memory Budget Calculations
Cache memory at 2048 entries (unified 10-byte structure):
Note:
TRAFFIC_MANAGEMENT_CACHE_SIZEcan 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:
Risk assessment:
Current Enablement Status
Traffic management is enabled on:
Other variants can enable via
HAS_TRAFFIC_MANAGEMENT=1in theirvariant.h.Example variant enablement:
Thread Safety
Lock Architecture
The module uses a single
mutable concurrency::Lock cacheLockmember to protect all cache and statistics operations.Codebase Lock Pattern Comparison:
extern Lock *spiLock;LockGuard g(spiLock);Lock mutex;LockGuard g(&mutex);mutable Lock cacheLock;LockGuard g(&cacheLock);Why
mutable? ThegetStats()method isconstbut must acquire a lock. Declaring the lock asmutableallows locking in const methods without requiring a dangerousconst_cast. This is semantically correct: locking doesn't affect the logical const-ness of the object.Critical Sections Analysis
getStats()resetStats()incrementStat()runOnce()shouldDropPosition()isRateLimited()shouldDropUnknown()Statistics Counters
incrementStat()with lock guardmeshtastic_TrafficManagementStats) is 32 bytes (8 x uint32_t)getStats()returns copy under lock to prevent torn reads across multiple countersPacket 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]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).
Examples:
Note:
nodeinfo_direct_responsemust be enabled separately for this feature to work.Adjustable constants in
TrafficManagementModule.cpp:kRouterDefaultMaxHops = 3- Router limit: max 3 hopskClientDefaultMaxHops = 0- Client limit: direct only (cannot increase)alterReceived() - Relayed Broadcast Hop Exhaustion
For relayed broadcasts from other nodes (
!isFromUs(&mp) && isBroadcast(mp.to)):exhaust_hop_telemetryand port isTELEMETRY_APP: exhaust hopsexhaust_hop_positionand port isPOSITION_APP: exhaust hopshop_start = hop_start - hop_limit + 1to preserve correcthopsAwayfor the one remaining relay hophop_limit = 0and signalsexhaustRequestedtoperhapsRebroadcast()Position Truncation Algorithm
Coordinates are truncated to configurable precision for deduplication:
Precision examples (approximate):
Default Values
Defaults are defined in
src/mesh/Default.hand applied at runtime viaDefault::getConfiguredOrDefault():position_precision_bitsposition_min_interval_secsThese 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_hopsis 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 ownexhaust_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_nodefield 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:
Generated C struct:
meshtastic_ModuleConfig_TrafficManagementConfig(~36 bytes)TrafficManagementStats (telemetry.proto)
7 counter fields for telemetry reporting:
Generated C struct:
meshtastic_TrafficManagementStats(28 bytes)Admin/Phone API Integration
AdminModule.cpp Changes
Get handler (
handleGetModuleConfig):Set handler (
handleSetModuleConfig):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 + 1pattern 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_min_interval_secsrate_limit_window_secs(or 10 minutes if unconfigured)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
Variant Example: Heltec V4
variants/esp32s3/heltec_v4/variant.h: