mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-07-28 17:39:21 +00:00
Improve flood retry bridge buckets
This commit is contained in:
Regular → Executable
+12
-11
@@ -1,10 +1,11 @@
|
||||
# sh ./build-repeaters-iotthinks.sh
|
||||
#!/usr/bin/env bash
|
||||
# ./build-iotthinks.sh
|
||||
export FIRMWARE_VERSION="PowerSaving15"
|
||||
|
||||
############# Repeaters #############
|
||||
# Commonly-used boards
|
||||
## ESP32 - 12 boards
|
||||
sh build.sh build-firmware \
|
||||
./build.sh build-firmware \
|
||||
Heltec_v3_repeater \
|
||||
Heltec_WSL3_repeater \
|
||||
heltec_v4_repeater \
|
||||
@@ -19,7 +20,7 @@ Heltec_E290_repeater \
|
||||
Heltec_Wireless_Tracker_repeater
|
||||
|
||||
## NRF52 - 13 boards
|
||||
sh build.sh build-firmware \
|
||||
./build.sh build-firmware \
|
||||
RAK_4631_repeater \
|
||||
Heltec_t114_repeater \
|
||||
Xiao_nrf52_repeater \
|
||||
@@ -35,25 +36,25 @@ GAT562_30S_Mesh_Kit_repeater \
|
||||
GAT562_Mesh_Tracker_Pro_repeater
|
||||
|
||||
## ESP32, SX1276 - 3 boards
|
||||
sh build.sh build-firmware \
|
||||
./build.sh build-firmware \
|
||||
Heltec_v2_repeater \
|
||||
LilyGo_TLora_V2_1_1_6_repeater \
|
||||
Tbeam_SX1276_repeater
|
||||
|
||||
## Ikoka - 3 boards
|
||||
sh build.sh build-firmware \
|
||||
./build.sh build-firmware \
|
||||
ikoka_nano_nrf_22dbm_repeater \
|
||||
ikoka_nano_nrf_30dbm_repeater \
|
||||
ikoka_nano_nrf_33dbm_repeater
|
||||
|
||||
############# Room Server #############
|
||||
# ESP32
|
||||
sh build.sh build-firmware \
|
||||
./build.sh build-firmware \
|
||||
Heltec_v3_room_server \
|
||||
heltec_v4_room_server
|
||||
|
||||
# NRF52
|
||||
sh build.sh build-firmware \
|
||||
./build.sh build-firmware \
|
||||
RAK_4631_room_server \
|
||||
Heltec_t114_room_server \
|
||||
Xiao_nrf52_room_server \
|
||||
@@ -63,7 +64,7 @@ RAK_3401_room_server
|
||||
|
||||
############# Companions BLE #############
|
||||
# ESP32
|
||||
sh build.sh build-firmware \
|
||||
./build.sh build-firmware \
|
||||
Heltec_v3_companion_radio_ble_ps \
|
||||
heltec_v4_companion_radio_ble_ps \
|
||||
heltec_v4_companion_radio_ble_ps_femoff \
|
||||
@@ -71,7 +72,7 @@ Xiao_S3_WIO_companion_radio_ble \
|
||||
Heltec_Wireless_Paper_companion_radio_ble
|
||||
|
||||
# NRF52
|
||||
sh build.sh build-firmware \
|
||||
./build.sh build-firmware \
|
||||
RAK_4631_companion_radio_ble \
|
||||
Heltec_t114_companion_radio_ble \
|
||||
Xiao_nrf52_companion_radio_ble \
|
||||
@@ -82,11 +83,11 @@ RAK_3401_companion_radio_ble \
|
||||
RAK_WisMesh_Tag_companion_radio_ble
|
||||
|
||||
############# Companions USB #############
|
||||
sh build.sh build-firmware \
|
||||
./build.sh build-firmware \
|
||||
Heltec_v3_companion_radio_usb
|
||||
|
||||
############# Companions BLE PS #############
|
||||
sh build.sh build-firmware \
|
||||
./build.sh build-firmware \
|
||||
Heltec_v3_companion_radio_ble_ps \
|
||||
heltec_v4_companion_radio_ble_ps \
|
||||
heltec_v4_3_companion_radio_ble_ps_femoff \
|
||||
|
||||
+16
-2
@@ -821,7 +821,7 @@ This document provides an overview of CLI commands that can be sent to MeshCore
|
||||
|
||||
**Default:** `off`
|
||||
|
||||
**Note:** Bridge mode uses bucket definitions instead of the single `flood.retry.prefixes` target list. If a flood comes from one fresh bucket, retry continues until every other fresh configured bucket has been heard or `flood.retry.count` is exhausted.
|
||||
**Note:** Bridge mode uses bucket definitions instead of the single `flood.retry.prefixes` target list. It also has an implicit unconfigured catch-all bucket. If a flood comes from one fresh configured bucket, retry continues until every other fresh configured bucket plus the catch-all bucket has been heard or `flood.retry.count` is exhausted. If a flood comes from an unconfigured or pathless source, retry targets every fresh configured bucket. This means one configured bucket bridges between that bucket and everything else. Prefixes in `flood.retry.ignore` never count as heard bridge targets.
|
||||
|
||||
---
|
||||
|
||||
@@ -832,7 +832,7 @@ This document provides an overview of CLI commands that can be sent to MeshCore
|
||||
|
||||
**Parameters:**
|
||||
- `bucket`: Bucket number (`1`-`6`)
|
||||
- `prefixes`: Up to 8 comma-separated 3-byte hex prefixes, such as `AABBCC,223344`; use `none` or `off` to clear
|
||||
- `prefixes`: Up to 17 comma-separated 3-byte hex prefixes, such as `AABBCC,223344`; use `none` or `off` to clear
|
||||
|
||||
**Default:** all buckets empty
|
||||
|
||||
@@ -840,6 +840,20 @@ This document provides an overview of CLI commands that can be sent to MeshCore
|
||||
|
||||
---
|
||||
|
||||
#### View or change flood retry ignored prefixes
|
||||
**Usage:**
|
||||
- `get flood.retry.ignore`
|
||||
- `set flood.retry.ignore <prefixes>`
|
||||
|
||||
**Parameters:**
|
||||
- `prefixes`: Up to 8 comma-separated 3-byte hex prefixes, such as `AABBCC,223344`; use `none` or `off` to clear
|
||||
|
||||
**Default:** empty
|
||||
|
||||
**Note:** Ignored prefixes do not count as a heard bridge bucket or as the implicit catch-all bucket when bridge retry decides whether every target has repeated the flood.
|
||||
|
||||
---
|
||||
|
||||
### ACL
|
||||
|
||||
#### Add, update or remove permissions for a companion
|
||||
|
||||
@@ -912,6 +912,19 @@ bool MyMesh::floodRetryPrefixMatches(const mesh::Packet* packet) const {
|
||||
|
||||
return false;
|
||||
}
|
||||
bool MyMesh::floodRetryPrefixIgnored(const uint8_t* prefix, uint8_t prefix_len) const {
|
||||
if (prefix == NULL || prefix_len == 0 || prefix_len > MAX_ROUTE_HASH_BYTES) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < FLOOD_RETRY_IGNORE_PREFIXES; i++) {
|
||||
const uint8_t* ignored = _prefs.flood_retry_ignore_prefixes[i];
|
||||
if ((ignored[0] != 0 || ignored[1] != 0 || ignored[2] != 0)
|
||||
&& memcmp(ignored, prefix, prefix_len) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool MyMesh::floodRetryPrefixFresh(const uint8_t* prefix, uint8_t prefix_len) const {
|
||||
const auto* recent = ((const SimpleMeshTables *)getTables())->findRecentRepeaterByHash(prefix, prefix_len);
|
||||
if (recent == NULL || recent->last_heard_millis == 0) {
|
||||
@@ -919,10 +932,22 @@ bool MyMesh::floodRetryPrefixFresh(const uint8_t* prefix, uint8_t prefix_len) co
|
||||
}
|
||||
return (uint32_t)(millis() - recent->last_heard_millis) <= 3600000UL;
|
||||
}
|
||||
int MyMesh::floodRetryBucketForPrefix(const uint8_t* prefix, uint8_t prefix_len, bool require_fresh) const {
|
||||
static const uint8_t FLOOD_RETRY_BRIDGE_OTHER_BUCKET = FLOOD_RETRY_BRIDGE_BUCKETS;
|
||||
|
||||
static uint8_t floodRetryBucketMask(uint8_t bucket) {
|
||||
if (bucket >= 8) {
|
||||
return 0;
|
||||
}
|
||||
return (uint8_t)(1U << bucket);
|
||||
}
|
||||
int MyMesh::floodRetryBucketForPrefix(const uint8_t* prefix, uint8_t prefix_len, bool require_fresh,
|
||||
bool include_other) const {
|
||||
if (prefix == NULL || prefix_len == 0 || prefix_len > MAX_ROUTE_HASH_BYTES) {
|
||||
return -1;
|
||||
}
|
||||
if (floodRetryPrefixIgnored(prefix, prefix_len)) {
|
||||
return -1;
|
||||
}
|
||||
if (require_fresh && !floodRetryPrefixFresh(prefix, prefix_len)) {
|
||||
return -1;
|
||||
}
|
||||
@@ -935,18 +960,28 @@ int MyMesh::floodRetryBucketForPrefix(const uint8_t* prefix, uint8_t prefix_len,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (include_other) {
|
||||
return FLOOD_RETRY_BRIDGE_OTHER_BUCKET;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int MyMesh::floodRetryBucketForPathHop(const uint8_t* prefix, uint8_t prefix_len, uint8_t hop,
|
||||
uint8_t progress_marker) const {
|
||||
return floodRetryBucketForPrefix(prefix, prefix_len, hop < progress_marker, true);
|
||||
}
|
||||
int MyMesh::floodRetrySourceBucket(const mesh::Packet* packet) const {
|
||||
if (packet == NULL || packet->getPathHashCount() < 2) {
|
||||
if (packet == NULL) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t hash_size = packet->getPathHashSize();
|
||||
if (hash_size == 0 || hash_size > MAX_ROUTE_HASH_BYTES) {
|
||||
return -1;
|
||||
}
|
||||
if (packet->getPathHashCount() < 2) {
|
||||
return FLOOD_RETRY_BRIDGE_OTHER_BUCKET;
|
||||
}
|
||||
const uint8_t* source_prefix = &packet->path[(packet->getPathHashCount() - 2) * hash_size];
|
||||
return floodRetryBucketForPrefix(source_prefix, hash_size, true);
|
||||
return floodRetryBucketForPrefix(source_prefix, hash_size, true, true);
|
||||
}
|
||||
uint8_t MyMesh::floodRetryBridgeTargetMask(uint8_t source_bucket) const {
|
||||
uint8_t mask = 0;
|
||||
@@ -957,15 +992,20 @@ uint8_t MyMesh::floodRetryBridgeTargetMask(uint8_t source_bucket) const {
|
||||
for (int i = 0; i < FLOOD_RETRY_BUCKET_PREFIXES; i++) {
|
||||
const uint8_t* configured = _prefs.flood_retry_bridge_buckets[bucket][i];
|
||||
if ((configured[0] != 0 || configured[1] != 0 || configured[2] != 0)
|
||||
&& !floodRetryPrefixIgnored(configured, FLOOD_RETRY_PREFIX_LEN)
|
||||
&& floodRetryPrefixFresh(configured, FLOOD_RETRY_PREFIX_LEN)) {
|
||||
mask |= (uint8_t)(1U << bucket);
|
||||
mask |= floodRetryBucketMask((uint8_t)bucket);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (source_bucket != FLOOD_RETRY_BRIDGE_OTHER_BUCKET) {
|
||||
mask |= floodRetryBucketMask(FLOOD_RETRY_BRIDGE_OTHER_BUCKET);
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
uint8_t MyMesh::floodRetryBridgeHeardMask(const mesh::Packet* packet, uint8_t source_bucket) const {
|
||||
uint8_t MyMesh::floodRetryBridgeHeardMask(const mesh::Packet* packet, uint8_t source_bucket,
|
||||
uint8_t progress_marker) const {
|
||||
if (packet == NULL || packet->getPathHashCount() == 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -977,9 +1017,13 @@ uint8_t MyMesh::floodRetryBridgeHeardMask(const mesh::Packet* packet, uint8_t so
|
||||
uint8_t mask = 0;
|
||||
const uint8_t* path = packet->path;
|
||||
for (int hop = 0; hop < packet->getPathHashCount(); hop++) {
|
||||
int bucket = floodRetryBucketForPrefix(path, hash_size, true);
|
||||
if (progress_marker > 0 && hop == progress_marker - 1) {
|
||||
path += hash_size;
|
||||
continue;
|
||||
}
|
||||
int bucket = floodRetryBucketForPathHop(path, hash_size, (uint8_t)hop, progress_marker);
|
||||
if (bucket >= 0 && bucket != source_bucket) {
|
||||
mask |= (uint8_t)(1U << bucket);
|
||||
mask |= floodRetryBucketMask((uint8_t)bucket);
|
||||
}
|
||||
path += hash_size;
|
||||
}
|
||||
@@ -1019,7 +1063,8 @@ MyMesh::FloodRetryBridgeState* MyMesh::floodRetryBridgeStateFor(const mesh::Pack
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t heard_mask = floodRetryBridgeHeardMask(packet, (uint8_t)source_bucket) & target_mask;
|
||||
uint8_t progress_marker = packet->getPathHashCount();
|
||||
uint8_t heard_mask = floodRetryBridgeHeardMask(packet, (uint8_t)source_bucket, progress_marker) & target_mask;
|
||||
if ((heard_mask & target_mask) == target_mask) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -1029,6 +1074,7 @@ MyMesh::FloodRetryBridgeState* MyMesh::floodRetryBridgeStateFor(const mesh::Pack
|
||||
free_slot->source_bucket = (uint8_t)source_bucket;
|
||||
free_slot->target_mask = target_mask;
|
||||
free_slot->heard_mask = heard_mask;
|
||||
free_slot->progress_marker = progress_marker;
|
||||
free_slot->active = true;
|
||||
return free_slot;
|
||||
}
|
||||
@@ -1088,8 +1134,13 @@ void MyMesh::refreshFloodRetryHeardRecent(const mesh::Packet* packet) {
|
||||
FloodRetryBridgeState* state = floodRetryBridgeStateFor(packet, false);
|
||||
if (state != NULL) {
|
||||
for (int hop = 0; hop < packet->getPathHashCount(); hop++) {
|
||||
int bucket = floodRetryBucketForPrefix(path, hash_size, true);
|
||||
if (bucket >= 0 && bucket != state->source_bucket && (state->target_mask & (uint8_t)(1U << bucket))) {
|
||||
if (state->progress_marker > 0 && hop == state->progress_marker - 1) {
|
||||
path += hash_size;
|
||||
continue;
|
||||
}
|
||||
int bucket = floodRetryBucketForPathHop(path, hash_size, (uint8_t)hop, state->progress_marker);
|
||||
uint8_t bucket_mask = bucket >= 0 ? floodRetryBucketMask((uint8_t)bucket) : 0;
|
||||
if (bucket >= 0 && bucket != state->source_bucket && (state->target_mask & bucket_mask)) {
|
||||
tables->setRecentRepeater(path, hash_size, packet->_snr, false, true);
|
||||
}
|
||||
path += hash_size;
|
||||
@@ -1161,9 +1212,20 @@ bool MyMesh::formatFloodRetryHeard(char* dest, size_t dest_len, const mesh::Pack
|
||||
}
|
||||
const uint8_t* path = packet->path;
|
||||
for (int hop = 0; hop < packet->getPathHashCount(); hop++) {
|
||||
int bucket = floodRetryBucketForPrefix(path, hash_size, true);
|
||||
if (bucket >= 0 && bucket != state->source_bucket && (state->target_mask & (uint8_t)(1U << bucket))) {
|
||||
size_t needed = (first ? 0 : 1) + 2 + 1 + ((size_t)hash_size * 2) + 1;
|
||||
if (state->progress_marker > 0 && hop == state->progress_marker - 1) {
|
||||
path += hash_size;
|
||||
continue;
|
||||
}
|
||||
int bucket = floodRetryBucketForPathHop(path, hash_size, (uint8_t)hop, state->progress_marker);
|
||||
uint8_t bucket_mask = bucket >= 0 ? floodRetryBucketMask((uint8_t)bucket) : 0;
|
||||
if (bucket >= 0 && bucket != state->source_bucket && (state->target_mask & bucket_mask)) {
|
||||
char bucket_label[8];
|
||||
if ((uint8_t)bucket == FLOOD_RETRY_BRIDGE_OTHER_BUCKET) {
|
||||
strcpy(bucket_label, "other");
|
||||
} else {
|
||||
snprintf(bucket_label, sizeof(bucket_label), "b%d", bucket + 1);
|
||||
}
|
||||
size_t needed = (first ? 0 : 1) + strlen(bucket_label) + 1 + ((size_t)hash_size * 2) + 1;
|
||||
if (remaining < needed) {
|
||||
if (remaining > 4) {
|
||||
strcpy(out, "...");
|
||||
@@ -1174,7 +1236,7 @@ bool MyMesh::formatFloodRetryHeard(char* dest, size_t dest_len, const mesh::Pack
|
||||
*out++ = ',';
|
||||
remaining--;
|
||||
}
|
||||
int n = snprintf(out, remaining, "b%d:", bucket + 1);
|
||||
int n = snprintf(out, remaining, "%s:", bucket_label);
|
||||
if (n < 0 || (size_t)n >= remaining) {
|
||||
return dest[0] != 0;
|
||||
}
|
||||
@@ -1298,7 +1360,7 @@ bool MyMesh::isFloodRetryEchoTarget(const mesh::Packet* packet, uint8_t progress
|
||||
if (state == NULL) {
|
||||
return false;
|
||||
}
|
||||
state->heard_mask |= floodRetryBridgeHeardMask(packet, state->source_bucket) & state->target_mask;
|
||||
state->heard_mask |= floodRetryBridgeHeardMask(packet, state->source_bucket, state->progress_marker) & state->target_mask;
|
||||
return (state->heard_mask & state->target_mask) == state->target_mask;
|
||||
}
|
||||
if (hasFloodRetryPrefixes()) {
|
||||
|
||||
@@ -104,6 +104,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
|
||||
uint8_t source_bucket;
|
||||
uint8_t target_mask;
|
||||
uint8_t heard_mask;
|
||||
uint8_t progress_marker;
|
||||
bool active;
|
||||
};
|
||||
mutable FloodRetryBridgeState flood_retry_bridge_states[MAX_FLOOD_RETRY_SLOTS];
|
||||
@@ -138,11 +139,16 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
|
||||
bool hasFloodRetryPrefixes() const;
|
||||
bool floodRetryPrefixMatches(const mesh::Packet* packet) const;
|
||||
bool floodRetryLastHopMatches(const mesh::Packet* packet) const;
|
||||
bool floodRetryPrefixIgnored(const uint8_t* prefix, uint8_t prefix_len) const;
|
||||
bool floodRetryPrefixFresh(const uint8_t* prefix, uint8_t prefix_len) const;
|
||||
int floodRetryBucketForPrefix(const uint8_t* prefix, uint8_t prefix_len, bool require_fresh) const;
|
||||
int floodRetryBucketForPrefix(const uint8_t* prefix, uint8_t prefix_len, bool require_fresh,
|
||||
bool include_other) const;
|
||||
int floodRetryBucketForPathHop(const uint8_t* prefix, uint8_t prefix_len, uint8_t hop,
|
||||
uint8_t progress_marker) const;
|
||||
int floodRetrySourceBucket(const mesh::Packet* packet) const;
|
||||
uint8_t floodRetryBridgeTargetMask(uint8_t source_bucket) const;
|
||||
uint8_t floodRetryBridgeHeardMask(const mesh::Packet* packet, uint8_t source_bucket) const;
|
||||
uint8_t floodRetryBridgeHeardMask(const mesh::Packet* packet, uint8_t source_bucket,
|
||||
uint8_t progress_marker) const;
|
||||
FloodRetryBridgeState* floodRetryBridgeStateFor(const mesh::Packet* packet, bool create) const;
|
||||
void clearFloodRetryBridgeState(const mesh::Packet* packet);
|
||||
void refreshFloodRetryHeardRecent(const mesh::Packet* packet);
|
||||
|
||||
+55
-29
@@ -213,11 +213,12 @@ static void formatFloodRetryPathGate(char* dest, uint8_t path_gate) {
|
||||
}
|
||||
}
|
||||
|
||||
static void formatFloodRetryPrefixes(char* dest, const NodePrefs* prefs) {
|
||||
static void formatFloodRetryPrefixList(char* dest, const uint8_t prefixes[][FLOOD_RETRY_PREFIX_LEN],
|
||||
uint8_t max_prefixes) {
|
||||
char* out = dest;
|
||||
bool first = true;
|
||||
for (int i = 0; i < FLOOD_RETRY_PREFIX_SLOTS; i++) {
|
||||
const uint8_t* prefix = prefs->flood_retry_prefixes[i];
|
||||
for (int i = 0; i < max_prefixes; i++) {
|
||||
const uint8_t* prefix = prefixes[i];
|
||||
if (prefix[0] == 0 && prefix[1] == 0 && prefix[2] == 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -231,26 +232,16 @@ static void formatFloodRetryPrefixes(char* dest, const NodePrefs* prefs) {
|
||||
*out = 0;
|
||||
}
|
||||
|
||||
static void formatFloodRetryPrefixes(char* dest, const NodePrefs* prefs) {
|
||||
formatFloodRetryPrefixList(dest, prefs->flood_retry_prefixes, FLOOD_RETRY_PREFIX_SLOTS);
|
||||
}
|
||||
|
||||
static void formatFloodRetryBridgeBucket(char* dest, const NodePrefs* prefs, uint8_t bucket) {
|
||||
char* out = dest;
|
||||
bool first = true;
|
||||
if (bucket >= FLOOD_RETRY_BRIDGE_BUCKETS) {
|
||||
*out = 0;
|
||||
dest[0] = 0;
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < FLOOD_RETRY_BUCKET_PREFIXES; i++) {
|
||||
const uint8_t* prefix = prefs->flood_retry_bridge_buckets[bucket][i];
|
||||
if (prefix[0] == 0 && prefix[1] == 0 && prefix[2] == 0) {
|
||||
continue;
|
||||
}
|
||||
if (!first) {
|
||||
*out++ = ',';
|
||||
}
|
||||
mesh::Utils::toHex(out, prefix, FLOOD_RETRY_PREFIX_LEN);
|
||||
out += FLOOD_RETRY_PREFIX_LEN * 2;
|
||||
first = false;
|
||||
}
|
||||
*out = 0;
|
||||
formatFloodRetryPrefixList(dest, prefs->flood_retry_bridge_buckets[bucket], FLOOD_RETRY_BUCKET_PREFIXES);
|
||||
}
|
||||
|
||||
static bool parseFloodRetryPrefixes(NodePrefs* prefs, const char* value) {
|
||||
@@ -261,7 +252,7 @@ static bool parseFloodRetryPrefixes(NodePrefs* prefs, const char* value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char tmp[96];
|
||||
char tmp[FLOOD_RETRY_LIST_TEXT_MAX];
|
||||
StrHelper::strncpy(tmp, value, sizeof(tmp));
|
||||
const char* parts[FLOOD_RETRY_PREFIX_SLOTS + 1];
|
||||
int num = mesh::Utils::parseTextParts(tmp, parts, FLOOD_RETRY_PREFIX_SLOTS + 1);
|
||||
@@ -290,20 +281,20 @@ static bool parseFloodRetryPrefixes(NodePrefs* prefs, const char* value) {
|
||||
}
|
||||
|
||||
static bool parseFloodRetryPrefixList(uint8_t dest[][FLOOD_RETRY_PREFIX_LEN], uint8_t max_prefixes, const char* value) {
|
||||
if (max_prefixes > FLOOD_RETRY_BUCKET_PREFIXES) {
|
||||
if (max_prefixes > FLOOD_RETRY_LIST_PREFIXES) {
|
||||
return false;
|
||||
}
|
||||
uint8_t parsed[FLOOD_RETRY_BUCKET_PREFIXES][FLOOD_RETRY_PREFIX_LEN];
|
||||
uint8_t parsed[FLOOD_RETRY_LIST_PREFIXES][FLOOD_RETRY_PREFIX_LEN];
|
||||
memset(parsed, 0, sizeof(parsed));
|
||||
if (value == NULL || value[0] == 0 || strcmp(value, "none") == 0 || strcmp(value, "off") == 0) {
|
||||
memcpy(dest, parsed, max_prefixes * FLOOD_RETRY_PREFIX_LEN);
|
||||
return true;
|
||||
}
|
||||
|
||||
char tmp[96];
|
||||
char tmp[FLOOD_RETRY_LIST_TEXT_MAX];
|
||||
StrHelper::strncpy(tmp, value, sizeof(tmp));
|
||||
const char* parts[FLOOD_RETRY_BUCKET_PREFIXES + 1];
|
||||
int num = mesh::Utils::parseTextParts(tmp, parts, FLOOD_RETRY_BUCKET_PREFIXES + 1);
|
||||
const char* parts[FLOOD_RETRY_LIST_PREFIXES + 1];
|
||||
int num = mesh::Utils::parseTextParts(tmp, parts, FLOOD_RETRY_LIST_PREFIXES + 1);
|
||||
if (num > max_prefixes) {
|
||||
return false;
|
||||
}
|
||||
@@ -436,7 +427,11 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
file.read((uint8_t *)&_prefs->flood_retry_prefs_magic[0], sizeof(_prefs->flood_retry_prefs_magic)); // 302
|
||||
file.read((uint8_t *)&_prefs->flood_retry_prefixes[0][0], sizeof(_prefs->flood_retry_prefixes)); // 304
|
||||
file.read((uint8_t *)&_prefs->flood_retry_bridge_enabled, sizeof(_prefs->flood_retry_bridge_enabled)); // 328
|
||||
memset(_prefs->flood_retry_bridge_buckets, 0, sizeof(_prefs->flood_retry_bridge_buckets));
|
||||
memset(_prefs->flood_retry_ignore_prefixes, 0, sizeof(_prefs->flood_retry_ignore_prefixes));
|
||||
file.read((uint8_t *)&_prefs->flood_retry_bridge_buckets[0][0][0], sizeof(_prefs->flood_retry_bridge_buckets)); // 329
|
||||
size_t flood_retry_ignore_read = file.read((uint8_t *)&_prefs->flood_retry_ignore_prefixes[0][0],
|
||||
sizeof(_prefs->flood_retry_ignore_prefixes)); // 635
|
||||
// PowerSaving-only prefs stored radio_fem_rxgain at 291, before direct retry timing existed.
|
||||
if (radio_fem_rxgain_read != sizeof(_prefs->radio_fem_rxgain)
|
||||
&& legacy_retry_attempts_read == sizeof(legacy_retry_attempts_or_radio_fem_rxgain)
|
||||
@@ -444,7 +439,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
|| _prefs->direct_retry_timing_magic[1] != DIRECT_RETRY_TIMING_MAGIC_1)) {
|
||||
_prefs->radio_fem_rxgain = constrain(legacy_retry_attempts_or_radio_fem_rxgain, 0, 1);
|
||||
}
|
||||
// next: 473
|
||||
// next: 659
|
||||
|
||||
// sanitise bad pref values
|
||||
_prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f);
|
||||
@@ -505,12 +500,16 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
memset(_prefs->flood_retry_prefixes, 0, sizeof(_prefs->flood_retry_prefixes));
|
||||
_prefs->flood_retry_bridge_enabled = 0;
|
||||
memset(_prefs->flood_retry_bridge_buckets, 0, sizeof(_prefs->flood_retry_bridge_buckets));
|
||||
memset(_prefs->flood_retry_ignore_prefixes, 0, sizeof(_prefs->flood_retry_ignore_prefixes));
|
||||
} else {
|
||||
_prefs->flood_retry_attempts = constrain(_prefs->flood_retry_attempts, FLOOD_RETRY_COUNT_MIN, FLOOD_RETRY_COUNT_MAX);
|
||||
if (_prefs->flood_retry_path_gate > 63 && _prefs->flood_retry_path_gate != FLOOD_RETRY_PATH_GATE_DISABLED) {
|
||||
_prefs->flood_retry_path_gate = floodRetryPresetPathDefault(_prefs->direct_retry_preset);
|
||||
}
|
||||
_prefs->flood_retry_bridge_enabled = constrain(_prefs->flood_retry_bridge_enabled, 0, 1);
|
||||
if (flood_retry_ignore_read != sizeof(_prefs->flood_retry_ignore_prefixes)) {
|
||||
memset(_prefs->flood_retry_ignore_prefixes, 0, sizeof(_prefs->flood_retry_ignore_prefixes));
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
@@ -591,7 +590,8 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
|
||||
file.write((uint8_t *)&_prefs->flood_retry_prefixes[0][0], sizeof(_prefs->flood_retry_prefixes)); // 304
|
||||
file.write((uint8_t *)&_prefs->flood_retry_bridge_enabled, sizeof(_prefs->flood_retry_bridge_enabled)); // 328
|
||||
file.write((uint8_t *)&_prefs->flood_retry_bridge_buckets[0][0][0], sizeof(_prefs->flood_retry_bridge_buckets)); // 329
|
||||
// next: 473
|
||||
file.write((uint8_t *)&_prefs->flood_retry_ignore_prefixes[0][0], sizeof(_prefs->flood_retry_ignore_prefixes)); // 635
|
||||
// next: 659
|
||||
|
||||
file.close();
|
||||
}
|
||||
@@ -756,6 +756,9 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
|
||||
} else if (memcmp(config, "flood.retry.prefixes", 20) == 0) {
|
||||
formatFloodRetryPrefixes(tmp, _prefs);
|
||||
sprintf(reply, "> %s", tmp[0] ? tmp : "none");
|
||||
} else if (memcmp(config, "flood.retry.ignore", 18) == 0) {
|
||||
formatFloodRetryPrefixList(tmp, _prefs->flood_retry_ignore_prefixes, FLOOD_RETRY_IGNORE_PREFIXES);
|
||||
sprintf(reply, "> %s", tmp[0] ? tmp : "none");
|
||||
} else if (memcmp(config, "flood.retry.bridge", 18) == 0) {
|
||||
sprintf(reply, "> %s", _prefs->flood_retry_bridge_enabled ? "on" : "off");
|
||||
} else if (memcmp(config, "flood.retry.bucket.", 19) == 0) {
|
||||
@@ -1061,6 +1064,15 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
|
||||
} else {
|
||||
strcpy(reply, "Error, use comma-separated 3-byte hex prefixes");
|
||||
}
|
||||
} else if (memcmp(config, "flood.retry.ignore ", 19) == 0) {
|
||||
if (parseFloodRetryPrefixList(_prefs->flood_retry_ignore_prefixes,
|
||||
FLOOD_RETRY_IGNORE_PREFIXES, &config[19])) {
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
sprintf(reply, "Error, use up to %u comma-separated 3-byte hex prefixes",
|
||||
(unsigned int)FLOOD_RETRY_IGNORE_PREFIXES);
|
||||
}
|
||||
} else if (memcmp(config, "flood.retry.bridge ", 19) == 0) {
|
||||
if (memcmp(&config[19], "on", 2) == 0) {
|
||||
_prefs->flood_retry_bridge_enabled = 1;
|
||||
@@ -1084,7 +1096,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, use up to 8 comma-separated 3-byte hex prefixes");
|
||||
sprintf(reply, "Error, use up to %u comma-separated 3-byte hex prefixes",
|
||||
(unsigned int)FLOOD_RETRY_BUCKET_PREFIXES);
|
||||
}
|
||||
} else if (memcmp(config, "direct.txdelay ", 15) == 0) {
|
||||
float f = atof(&config[15]);
|
||||
@@ -1674,6 +1687,15 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
} else {
|
||||
strcpy(reply, "Error, use comma-separated 3-byte hex prefixes");
|
||||
}
|
||||
} else if (memcmp(config, "flood.retry.ignore ", 19) == 0) {
|
||||
if (parseFloodRetryPrefixList(_prefs->flood_retry_ignore_prefixes,
|
||||
FLOOD_RETRY_IGNORE_PREFIXES, &config[19])) {
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
sprintf(reply, "Error, use up to %u comma-separated 3-byte hex prefixes",
|
||||
(unsigned int)FLOOD_RETRY_IGNORE_PREFIXES);
|
||||
}
|
||||
} else if (memcmp(config, "flood.retry.bridge ", 19) == 0) {
|
||||
if (memcmp(&config[19], "on", 2) == 0) {
|
||||
_prefs->flood_retry_bridge_enabled = 1;
|
||||
@@ -1697,7 +1719,8 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, use up to 8 comma-separated 3-byte hex prefixes");
|
||||
sprintf(reply, "Error, use up to %u comma-separated 3-byte hex prefixes",
|
||||
(unsigned int)FLOOD_RETRY_BUCKET_PREFIXES);
|
||||
}
|
||||
} else if (memcmp(config, "direct.txdelay ", 15) == 0) {
|
||||
float f = atof(&config[15]);
|
||||
@@ -1947,6 +1970,9 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
} else if (memcmp(config, "flood.retry.prefixes", 20) == 0) {
|
||||
formatFloodRetryPrefixes(tmp, _prefs);
|
||||
sprintf(reply, "> %s", tmp[0] ? tmp : "none");
|
||||
} else if (memcmp(config, "flood.retry.ignore", 18) == 0) {
|
||||
formatFloodRetryPrefixList(tmp, _prefs->flood_retry_ignore_prefixes, FLOOD_RETRY_IGNORE_PREFIXES);
|
||||
sprintf(reply, "> %s", tmp[0] ? tmp : "none");
|
||||
} else if (memcmp(config, "flood.retry.bridge", 18) == 0) {
|
||||
sprintf(reply, "> %s", _prefs->flood_retry_bridge_enabled ? "on" : "off");
|
||||
} else if (memcmp(config, "flood.retry.bucket.", 19) == 0) {
|
||||
|
||||
+15
-2
@@ -48,7 +48,19 @@
|
||||
#define FLOOD_RETRY_BRIDGE_BUCKETS 6
|
||||
#endif
|
||||
#ifndef FLOOD_RETRY_BUCKET_PREFIXES
|
||||
#define FLOOD_RETRY_BUCKET_PREFIXES 8
|
||||
#define FLOOD_RETRY_BUCKET_PREFIXES 17
|
||||
#endif
|
||||
#ifndef FLOOD_RETRY_IGNORE_PREFIXES
|
||||
#define FLOOD_RETRY_IGNORE_PREFIXES 8
|
||||
#endif
|
||||
#ifndef FLOOD_RETRY_LIST_PREFIXES
|
||||
#define FLOOD_RETRY_LIST_PREFIXES ((FLOOD_RETRY_IGNORE_PREFIXES > FLOOD_RETRY_BUCKET_PREFIXES) ? FLOOD_RETRY_IGNORE_PREFIXES : FLOOD_RETRY_BUCKET_PREFIXES)
|
||||
#endif
|
||||
#ifndef FLOOD_RETRY_LIST_TEXT_MAX
|
||||
#define FLOOD_RETRY_LIST_TEXT_MAX (FLOOD_RETRY_LIST_PREFIXES * FLOOD_RETRY_PREFIX_LEN * 2 + FLOOD_RETRY_LIST_PREFIXES)
|
||||
#endif
|
||||
#ifndef COMMON_CLI_TMP_LEN
|
||||
#define COMMON_CLI_TMP_LEN ((FLOOD_RETRY_LIST_TEXT_MAX > (PRV_KEY_SIZE * 2 + 4)) ? FLOOD_RETRY_LIST_TEXT_MAX : (PRV_KEY_SIZE * 2 + 4))
|
||||
#endif
|
||||
|
||||
struct NodePrefs { // persisted to file
|
||||
@@ -107,6 +119,7 @@ struct NodePrefs { // persisted to file
|
||||
uint8_t flood_retry_prefixes[FLOOD_RETRY_PREFIX_SLOTS][FLOOD_RETRY_PREFIX_LEN];
|
||||
uint8_t flood_retry_bridge_enabled;
|
||||
uint8_t flood_retry_bridge_buckets[FLOOD_RETRY_BRIDGE_BUCKETS][FLOOD_RETRY_BUCKET_PREFIXES][FLOOD_RETRY_PREFIX_LEN];
|
||||
uint8_t flood_retry_ignore_prefixes[FLOOD_RETRY_IGNORE_PREFIXES][FLOOD_RETRY_PREFIX_LEN];
|
||||
};
|
||||
|
||||
class CommonCLICallbacks {
|
||||
@@ -166,7 +179,7 @@ class CommonCLI {
|
||||
SensorManager* _sensors;
|
||||
RegionMap* _region_map;
|
||||
ClientACL* _acl;
|
||||
char tmp[PRV_KEY_SIZE*2 + 4];
|
||||
char tmp[COMMON_CLI_TMP_LEN];
|
||||
|
||||
mesh::RTCClock* getRTCClock() { return _rtc; }
|
||||
void savePrefs();
|
||||
|
||||
@@ -175,8 +175,6 @@ public:
|
||||
f.write((const uint8_t *) &_next_idx, sizeof(_next_idx));
|
||||
f.write((const uint8_t *) &_acks[0], sizeof(_acks));
|
||||
f.write((const uint8_t *) &_next_ack_idx, sizeof(_next_ack_idx));
|
||||
f.write((const uint8_t *) &_recent_repeaters[0], sizeof(_recent_repeaters));
|
||||
f.write((const uint8_t *) &_next_recent_repeater_idx, sizeof(_next_recent_repeater_idx));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user