From 2bc567e0feac9d6d471f07b9477c7540a88c1852 Mon Sep 17 00:00:00 2001 From: Ben P Date: Thu, 18 Jun 2026 12:27:22 -0500 Subject: [PATCH] Add support for restricting flood request, flood anon_request, and flood response packets by the number of hops. --- examples/simple_repeater/MyMesh.cpp | 6 ++++ examples/simple_room_server/MyMesh.cpp | 8 +++++ src/helpers/CommonCLI.cpp | 43 ++++++++++++++++++++++++-- src/helpers/CommonCLI.h | 3 ++ 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index 5cc3a9a11e..24414aeba3 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -432,6 +432,9 @@ bool MyMesh::allowPacketForward(const mesh::Packet *packet) { if (packet->getPathHashCount() >= _prefs.flood_max) return false; if (packet->getRouteType() == ROUTE_TYPE_FLOOD && packet->getPathHashCount() >= _prefs.flood_max_unscoped) return false; if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && packet->getPathHashCount() >= _prefs.flood_max_advert) return false; + if (packet->getPayloadType() == PAYLOAD_TYPE_REQ && packet->getPathHashCount() >= _prefs.flood_max_request) return false; + if (packet->getPayloadType() == PAYLOAD_TYPE_ANON_REQ && packet->getPathHashCount() >= _prefs.flood_max_anon_request) return false; + if (packet->getPayloadType() == PAYLOAD_TYPE_RESPONSE && packet->getPathHashCount() >= _prefs.flood_max_response) return false; } if (packet->isRouteFlood() && recv_pkt_region == NULL) { MESH_DEBUG_PRINTLN("allowPacketForward: unknown transport code, or wildcard not allowed for FLOOD packet"); @@ -892,6 +895,9 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc _prefs.flood_max = 64; _prefs.flood_max_unscoped = 64; _prefs.flood_max_advert = 8; + _prefs.flood_max_request = 64; + _prefs.flood_max_anon_request = 64; + _prefs.flood_max_response = 64; _prefs.interference_threshold = 0; // disabled _prefs.cad_enabled = 0; // hardware CAD before TX (off by default; 'set cad on') diff --git a/examples/simple_room_server/MyMesh.cpp b/examples/simple_room_server/MyMesh.cpp index 12d0b0c318..1a38d0505a 100644 --- a/examples/simple_room_server/MyMesh.cpp +++ b/examples/simple_room_server/MyMesh.cpp @@ -286,6 +286,10 @@ bool MyMesh::allowPacketForward(const mesh::Packet *packet) { if (packet->getPathHashCount() >= _prefs.flood_max) return false; if (packet->getRouteType() == ROUTE_TYPE_FLOOD && packet->getPathHashCount() >= _prefs.flood_max_unscoped) return false; if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && packet->getPathHashCount() >= _prefs.flood_max_advert) return false; + if (packet->getPayloadType() == PAYLOAD_TYPE_REQ && packet->getPathHashCount() >= _prefs.flood_max_request) return false; + if (packet->getPayloadType() == PAYLOAD_TYPE_ANON_REQ && packet->getPathHashCount() >= _prefs.flood_max_anon_request) return false; + if (packet->getPayloadType() == PAYLOAD_TYPE_RESPONSE && packet->getPathHashCount() >= _prefs.flood_max_response) return false; + } return true; } @@ -649,6 +653,10 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc _prefs.flood_max = 64; _prefs.flood_max_unscoped = 64; _prefs.flood_max_advert = 8; + _prefs.flood_max_request = 64; + _prefs.flood_max_anon_request = 64; + _prefs.flood_max_response = 64; + _prefs.interference_threshold = 0; // disabled _prefs.cad_enabled = 0; // hardware CAD before TX (off by default; 'set cad on') #ifdef ROOM_PASSWORD diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 82e5374352..82a44f561d 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -93,7 +93,10 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { file.read((uint8_t *)&_prefs->flood_max_advert, sizeof(_prefs->flood_max_advert)); // 292 file.read((uint8_t *)&_prefs->radio_fem_rxgain, sizeof(_prefs->radio_fem_rxgain)); // 293 file.read((uint8_t *)&_prefs->cad_enabled, sizeof(_prefs->cad_enabled)); // 294 - // next: 295 + file.read((uint8_t *)&_prefs->flood_max_request, sizeof(_prefs->flood_max_request)); // 295 + file.read((uint8_t *)&_prefs->flood_max_anon_request, sizeof(_prefs->flood_max_anon_request)); // 296 + file.read((uint8_t *)&_prefs->flood_max_response, sizeof(_prefs->flood_max_response)); // 297 + // next: 298 // sanitise bad pref values _prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f); @@ -190,7 +193,10 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) { file.write((uint8_t *)&_prefs->flood_max_advert, sizeof(_prefs->flood_max_advert)); // 292 file.write((uint8_t *)&_prefs->radio_fem_rxgain, sizeof(_prefs->radio_fem_rxgain)); // 293 file.write((uint8_t *)&_prefs->cad_enabled, sizeof(_prefs->cad_enabled)); // 294 - // next: 295 + file.write((uint8_t *)&_prefs->flood_max_request, sizeof(_prefs->flood_max_request)); // 295 + file.write((uint8_t *)&_prefs->flood_max_anon_request, sizeof(_prefs->flood_max_anon_request)); // 296 + file.write((uint8_t *)&_prefs->flood_max_response, sizeof(_prefs->flood_max_response)); // 297 + // next: 298 file.close(); } @@ -662,6 +668,33 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep } else { strcpy(reply, "Error, max 64"); } + } else if (memcmp(config, "flood.max.request ", 18) == 0) { + uint8_t m = atoi(&config[18]); + if (m <= 64) { + _prefs->flood_max_request = m; + savePrefs(); + strcpy(reply, "OK"); + } else { + strcpy(reply, "Error, max 64"); + } + } else if (memcmp(config, "flood.max.anon.request ", 23) == 0) { + uint8_t m = atoi(&config[23]); + if (m <= 64) { + _prefs->flood_max_anon_request = m; + savePrefs(); + strcpy(reply, "OK"); + } else { + strcpy(reply, "Error, max 64"); + } + } else if (memcmp(config, "flood.max.response ", 19) == 0) { + uint8_t m = atoi(&config[18]); + if (m <= 64) { + _prefs->flood_max_response = m; + savePrefs(); + strcpy(reply, "OK"); + } else { + strcpy(reply, "Error, max 64"); + } } else if (memcmp(config, "flood.max ", 10) == 0) { uint8_t m = atoi(&config[10]); if (m <= 64) { @@ -858,6 +891,12 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep sprintf(reply, "> %d", (uint32_t)_prefs->flood_max_advert); } else if (memcmp(config, "flood.max.unscoped", 18) == 0) { sprintf(reply, "> %d", (uint32_t)_prefs->flood_max_unscoped); + } else if (memcmp(config, "flood.max.request", 17) == 0) { + sprintf(reply, "> %d", (uint32_t)_prefs->flood_max_request); + } else if (memcmp(config, "flood.max.anon.request", 22) == 0) { + sprintf(reply, "> %d", (uint32_t)_prefs->flood_max_anon_request); + } else if (memcmp(config, "flood.max.response", 18) == 0) { + sprintf(reply, "> %d", (uint32_t)_prefs->flood_max_response); } else if (memcmp(config, "flood.max", 9) == 0) { sprintf(reply, "> %d", (uint32_t)_prefs->flood_max); } else if (memcmp(config, "direct.txdelay", 14) == 0) { diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index 10cb00c776..885a822d27 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -42,6 +42,9 @@ struct NodePrefs { // persisted to file uint8_t flood_max; uint8_t flood_max_unscoped; uint8_t flood_max_advert; + uint8_t flood_max_request; + uint8_t flood_max_anon_request; + uint8_t flood_max_response; uint8_t interference_threshold; uint8_t agc_reset_interval; // secs / 4 // Bridge settings