diff --git a/README.md b/README.md index ebad1f6f..7f02f43c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,18 @@ + +## About MeshCore-Evo + +This is a friendly fork of the MeshCore project. +Its aim is to provide repeater firmwares with a few additional pending upstream PRs/improvements (i.e. PRs/improvements that are available to the MeshCore project but have not yet been merged in the upstream repo or PRs that might never be merged upstream for some reason). +These changes are intended to help mitigating challenges in big or dense meshes, e.g.: + +- Dealing with flood advert traffic +- improving `denyf *` handling + +This list might change any time. +Refer to the [release notes](https://github.com/mattzzw/MeshCore-Evo/releases) for an up-to-date list of the applied changes. + + + ## About MeshCore MeshCore is a lightweight, portable C++ library that enables multi-hop packet routing for embedded projects using LoRa and other packet radios. It is designed for developers who want to create resilient, decentralized communication networks that work without the internet. diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index 666f79fc..069fad49 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -447,6 +447,15 @@ bool MyMesh::allowPacketForward(const mesh::Packet *packet) { return false; } } + // Limit flood advert paket forwarding using a probabilistic reduction defined by P(h) = 0.308^(hops-1) + // https://github.com/meshcore-dev/MeshCore/issues/1223 + if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && packet->isRouteFlood()) { + double roll_dice = (double)rand() / RAND_MAX; + double forw_prob = pow(_prefs.flood_advert_base, packet->path_len - 1); + if (roll_dice > forw_prob) + return false; + } + return true; } @@ -885,6 +894,7 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc _prefs.tx_power_dbm = LORA_TX_POWER; _prefs.advert_interval = 1; // default to 2 minutes for NEW installs _prefs.flood_advert_interval = 12; // 12 hours + _prefs.flood_advert_base = 0.308f; _prefs.flood_max = 64; _prefs.interference_threshold = 0; // disabled diff --git a/examples/simple_room_server/MyMesh.cpp b/examples/simple_room_server/MyMesh.cpp index 145fb0fd..1822d00c 100644 --- a/examples/simple_room_server/MyMesh.cpp +++ b/examples/simple_room_server/MyMesh.cpp @@ -282,7 +282,17 @@ uint32_t MyMesh::getDirectRetransmitDelay(const mesh::Packet *packet) { bool MyMesh::allowPacketForward(const mesh::Packet *packet) { if (_prefs.disable_fwd) return false; - if (packet->isRouteFlood() && packet->getPathHashCount() >= _prefs.flood_max) return false; + if (packet->isRouteFlood() && packet->path_len >= _prefs.flood_max) return false; + + // Limit flood advert packet forwarding using a probabilistic reduction defined by P(h) = base^(hops-1) + // https://github.com/meshcore-dev/MeshCore/issues/1223 + if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && packet->isRouteFlood()) { + double roll_dice = (double)rand() / RAND_MAX; + double forw_prob = pow(_prefs.flood_advert_base, packet->path_len - 1); + if (roll_dice > forw_prob) + return false; + } + return true; } @@ -642,6 +652,7 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc _prefs.disable_fwd = 1; _prefs.advert_interval = 1; // default to 2 minutes for NEW installs _prefs.flood_advert_interval = 12; // 12 hours + _prefs.flood_advert_base = 0.308f; _prefs.flood_max = 64; _prefs.interference_threshold = 0; // disabled #ifdef ROOM_PASSWORD diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index b71afc72..3bbef5fd 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -88,8 +88,8 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { file.read((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162 file.read((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166 file.read((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170 - file.read((uint8_t *)&_prefs->rx_boosted_gain, sizeof(_prefs->rx_boosted_gain)); // 290 - // next: 291 + file.read((uint8_t *)&_prefs->flood_advert_base, sizeof(_prefs->flood_advert_base)); // 290 + file.read((uint8_t *)&_prefs->rx_boosted_gain, sizeof(_prefs->rx_boosted_gain)); // 294 // sanitise bad pref values _prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f); @@ -119,6 +119,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { // sanitise settings _prefs->rx_boosted_gain = constrain(_prefs->rx_boosted_gain, 0, 1); // boolean + _prefs->flood_advert_base = constrain(_prefs->flood_advert_base, 0, 1); file.close(); } @@ -179,8 +180,8 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) { file.write((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162 file.write((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166 file.write((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170 - file.write((uint8_t *)&_prefs->rx_boosted_gain, sizeof(_prefs->rx_boosted_gain)); // 290 - // next: 291 + file.write((uint8_t *)&_prefs->flood_advert_base, sizeof(_prefs->flood_advert_base)); // 290 + file.write((uint8_t *)&_prefs->rx_boosted_gain, sizeof(_prefs->rx_boosted_gain)); // 294 file.close(); } @@ -607,6 +608,15 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep } else { strcpy(reply, "Error, max 64"); } + } else if (memcmp(config, "flood.advert.base ", 18) == 0) { + float f = atof(&config[18]); + if (f >= 0.0f && f <= 1.0f) { + _prefs->flood_advert_base = f; + savePrefs(); + strcpy(reply, "OK"); + } else { + strcpy(reply, "Error: base must be between 0 and 1"); + } } else if (memcmp(config, "direct.txdelay ", 15) == 0) { float f = atof(&config[15]); if (f >= 0) { @@ -784,6 +794,8 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep sprintf(reply, "> %s", StrHelper::ftoa(_prefs->tx_delay_factor)); } else if (memcmp(config, "flood.max", 9) == 0) { sprintf(reply, "> %d", (uint32_t)_prefs->flood_max); + } else if (memcmp(config, "flood.advert.base", 17) == 0) { + sprintf(reply, "> %s", StrHelper::ftoa(_prefs->flood_advert_base)); } else if (memcmp(config, "direct.txdelay", 14) == 0) { sprintf(reply, "> %s", StrHelper::ftoa(_prefs->direct_tx_delay_factor)); } else if (memcmp(config, "owner.info", 10) == 0) { diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index ffdc7c65..1defcd92 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -42,6 +42,7 @@ struct NodePrefs { // persisted to file uint8_t flood_max; uint8_t interference_threshold; uint8_t agc_reset_interval; // secs / 4 + float flood_advert_base; // Bridge settings uint8_t bridge_enabled; // boolean uint16_t bridge_delay; // milliseconds (default 500 ms)