feat: make region auto-tagging opt-in with configurable hop limit

Adds two new repeater prefs to give admins explicit control over
VLAN-style region tagging of untagged flood packets:

  region.autotag           on|off   (default: off)
  region.autotag.max.hops  0-8      (default: 1)

Auto-tagging now only occurs when the setting is enabled AND the
received packet's path hash count is <= the configured max hops.
This prevents mis-tagging distant-origin floods that arrived via
untagged / older-firmware repeaters, and ensures home-region
selection is a deliberate admin decision rather than an implicit
side-effect of configuring a home region.
This commit is contained in:
Dale Ruane 2026-04-14 10:26:18 +01:00
parent 85a3b1d6db
commit d93746e257
3 changed files with 32 additions and 4 deletions

View file

@ -87,7 +87,9 @@ 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
// next: 290
file.read((uint8_t *)&_prefs->region_autotag, sizeof(_prefs->region_autotag)); // 290
file.read((uint8_t *)&_prefs->region_autotag_max_hops, sizeof(_prefs->region_autotag_max_hops)); // 291
// next: 292
// sanitise bad pref values
_prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f);
@ -117,6 +119,8 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
// sanitise settings
_prefs->rx_boosted_gain = constrain(_prefs->rx_boosted_gain, 0, 1); // boolean
_prefs->region_autotag = constrain(_prefs->region_autotag, 0, 1); // boolean
_prefs->region_autotag_max_hops = constrain(_prefs->region_autotag_max_hops, 0, 8);
file.close();
}
@ -177,7 +181,9 @@ 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
// next: 290
file.write((uint8_t *)&_prefs->region_autotag, sizeof(_prefs->region_autotag)); // 290
file.write((uint8_t *)&_prefs->region_autotag_max_hops, sizeof(_prefs->region_autotag_max_hops)); // 291
// next: 292
file.close();
}
@ -349,6 +355,10 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
*reply = 0; // set null terminator
} else if (memcmp(config, "path.hash.mode", 14) == 0) {
sprintf(reply, "> %d", (uint32_t)_prefs->path_hash_mode);
} else if (memcmp(config, "region.autotag.max.hops", 23) == 0) {
sprintf(reply, "> %d", (uint32_t)_prefs->region_autotag_max_hops);
} else if (memcmp(config, "region.autotag", 14) == 0) {
sprintf(reply, "> %s", _prefs->region_autotag ? "on" : "off");
} else if (memcmp(config, "loop.detect", 11) == 0) {
if (_prefs->loop_detect == LOOP_DETECT_OFF) {
strcpy(reply, "> off");
@ -597,6 +607,19 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
*dp = 0;
savePrefs();
strcpy(reply, "OK");
} else if (memcmp(config, "region.autotag.max.hops ", 24) == 0) {
int h = atoi(&config[24]);
if (h >= 0 && h <= 8) {
_prefs->region_autotag_max_hops = (uint8_t)h;
savePrefs();
strcpy(reply, "OK");
} else {
strcpy(reply, "Error, range is 0-8");
}
} else if (memcmp(config, "region.autotag ", 15) == 0) {
_prefs->region_autotag = memcmp(&config[15], "on", 2) == 0;
savePrefs();
strcpy(reply, "OK");
} else if (memcmp(config, "path.hash.mode ", 15) == 0) {
config += 15;
uint8_t mode = atoi(config);

View file

@ -60,6 +60,8 @@ struct NodePrefs { // persisted to file
uint8_t rx_boosted_gain; // power settings
uint8_t path_hash_mode; // which path mode to use when sending
uint8_t loop_detect;
uint8_t region_autotag; // boolean: auto-tag untagged flood packets with home region's transport code
uint8_t region_autotag_max_hops; // only auto-tag packets received with pathHashCount <= this value (0 = zero-hop only)
};
class CommonCLICallbacks {