Skip to content

feat: VLAN-style region tagging for untagged flood packets#2073

Open
dale-ruane wants to merge 8 commits into
meshcore-dev:devfrom
dale-ruane:dev
Open

feat: VLAN-style region tagging for untagged flood packets#2073
dale-ruane wants to merge 8 commits into
meshcore-dev:devfrom
dale-ruane:dev

Conversation

@dale-ruane

@dale-ruane dale-ruane commented Mar 17, 2026

Copy link
Copy Markdown

Summary

Closes #2041

  • Repeaters can now opt in to automatically tagging untagged flood packets (ROUTE_TYPE_FLOOD) with their home region's transport code, converting them to ROUTE_TYPE_TRANSPORT_FLOOD
  • Auto-tagging is off by default and must be explicitly enabled via set region.autotag on — having a home region set alone does not activate it
  • A configurable hop limit (set region.autotag.max.hops <0-8>, default 1) prevents mis-tagging packets that have already traversed multiple repeaters, since the further a packet has travelled the less likely the tagging repeater's home region is correct
  • Adds TRANSPORT_CODE_ALL (0xFFFF) as a reserved code that bypasses region filtering, allowing mesh-wide flooding when explicitly requested
  • Fully backwards compatible: repeaters with auto-tagging off (the default) behave exactly as before

New CLI commands

Command Description
get/set region.autotag on|off Enable/disable auto-tagging of untagged flood packets (default: off)
get/set region.autotag.max.hops <0-8> Only auto-tag packets with a path hash count ≤ this value (default: 1). 0 = zero-hop (direct) only

How it works

  • Untagged flood arrives + auto-tagging on + home region set + hop count within limit → tagged with home region's transport code and forwarded
  • Untagged flood arrives + auto-tagging off or no home region → forwarded as-is (existing behaviour)
  • Untagged flood arrives + hop count exceeds region.autotag.max.hops → forwarded as-is, not tagged
  • Tagged flood with ALL (0xFFFF) → always forwarded regardless of region config
  • Tagged flood with region code → existing region matching (unchanged)

Test plan

  • Repeater with region.autotag off (default) forwards untagged floods as before, even with a home region set
  • Repeater with region.autotag on and home region set tags untagged floods with correct transport code
  • Packets with getPathHashCount() > region.autotag.max.hops are forwarded without tagging
  • Already-tagged packets pass through unchanged
  • TRANSPORT_CODE_ALL packets are forwarded by all repeaters
  • set region.autotag.max.hops rejects values outside 0-8
  • Builds clean on ESP32 and NRF52 platforms

Repeaters with a home region configured now automatically tag untagged
flood packets (ROUTE_TYPE_FLOOD) with the home region's transport code,
converting them to ROUTE_TYPE_TRANSPORT_FLOOD. Also adds TRANSPORT_CODE_ALL
(0xFFFF) as a reserved code that bypasses region filtering, allowing
mesh-wide flooding when explicitly requested.
@awhite2000

Copy link
Copy Markdown

@weebl2000 @ViezeVingertjes could someone please review this? it's a very important improvement to the way scoping works, which allows for a gentler and more flexible adoption of regions.

@ViezeVingertjes ViezeVingertjes left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, and imho it does make sense to have this.

Just a sanity check; Did you check if any documentation requires an update for this change?

@awhite2000

Copy link
Copy Markdown

It definitely needs good docs, it's a new feature. IMHO docs on regions need to be beefed up anyway, explaining the concepts and not just the config syntax.
If @dale-ruane can provide it in this PR then that's great, if not then I think, given the backlog and how long this has been sitting, this PR should be merged and a new PR for improving docs on regions should be created, which I can take if no one else does.

@AI7NC

AI7NC commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

I think this is the best way to bootstrap region use adoption.

@skyepn

skyepn commented Apr 13, 2026

Copy link
Copy Markdown

It looks like this also solves PR1810 "Allow direct message paths when denyf * is set"
#1810

Because recv_pkt_region is being set in filterRecvFloodPacket? This would be a very good thing, PR1810 is currently the top upvoted PR and many people in large meshes are using custom repeater builds with that PR which is not an ideal solution because it breaks the semantics of "deny flood packets with unset scope"

@skyepn

skyepn commented Apr 13, 2026

Copy link
Copy Markdown

Should there be a new repeater CLI setting boolean to control this behaviour? Even though not setting a home region is a defacto way of turning it off, it should probably be explicit.

@skyepn

skyepn commented Apr 13, 2026

Copy link
Copy Markdown

Just thinking about this a little more, especially in the case where a "boundary" repeater can hear nodes in other regions it is essential that the choice of home region is correct so that unscoped flood packets are not tagged with an incorrect region.

For this reason I think there should be a new repeater setting for this feature and the default being off, as the choice of home region requires the repeater admin to think carefully about the intended behaviour.

To that end, it will be important for the region home command documentation to describe the process for choosing very clearly, which I believe should be "the most specific region in the local region hierarchy that includes ALL nodes that the repeater can possibly hear"

Local example using the Pacific Northwest MeshCore Region Strategy and a repeater on Mt Baker, Whatcom County, WA USA. The physical location of the repeater would be bli but it would also be able to hear other counties, so you move up the tree to w-wa. But it can also hear packets from across the border in BC, Canada so the correct home region would be pnw as that is the most specific level where it is not possible to hear unscoped packets from any neighboring regions at that level (specifically ca ie California)

Writing this now, it seems like it might actually be better to only apply this to a configurable number of hops to avoid tagging flood packets that originated in distant regions and were forwarded by repeaters that did not have unscoped tagging turned on (or older firmwares that wouldn't support it). I see that _prefs.flood_max is checked at the top of allowPacketForward but this new tagging behaviour should probably have it's own setting, and actually maybe only apply to zero hop flood packets received? Haven't thought this part through completely, but NOT restricting to direct/zero hop flood packets would almost guarantee that some flood packets received would be tagged incorrectly as there would be no way to choose the home region properly.

In other words, the repeater admin must know what geographical area they will receive flood packets from in order to choose the correct home region.

@AI7NC

AI7NC commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

This definitely needs some thought, repeater operators opting in seems like a good idea outside just setting the home region. I myself would be against tagging traffic for a repeater between two regions as the pnw region. That's way to wide of a scope to auto-tag traffic, it may as well be * at that point.

I do think there should be a auto-tag max hop setting where a repeater operator can tone down the auto tagging depending on where the repeater is located and what it hears. If scoping at a sub-region or state level, going up to 3 or 4 hops may make sense, while other areas even a zero hop will have some mis-tag issues. Allowing the admin to tune for best affect I think is most practical.

Despite the above controls, some situations will not be fully be able to control 100% accuracy of the auto tagging. At some point it'll need to boil down to If originators want their traffic tagged correctly, they need to configure the region scope for their traffic at origination.

@skyepn

skyepn commented Apr 14, 2026

Copy link
Copy Markdown

Yeah, the more I think about it, a repeater admin can't be expected to know the geographical reach even 1 or 2 hops out, it's hard enough to keep track of the location your own (direct, zero hop) contacts over time.

I think it auto-scoping should only be applied if the new setting is on and getPathHashCount() == 0?

@awhite2000

awhite2000 commented Apr 14, 2026

Copy link
Copy Markdown

I agree that this limit is useful but let's make it configurable with the default 1 or 2. I know that in my area's topology no harm would be done even with 2-3.

EDIT: and we have to document it really well :)

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.
@dale-ruane

dale-ruane commented Apr 14, 2026

Copy link
Copy Markdown
Author

Great suggestions all - I've added the opt-in and hop-limit. Docs coming in the next commit. Would appreciate feedback on the Docs and commit above

Adds CLI reference entries for the new region.autotag and
region.autotag.max.hops settings, and expands the region home
documentation with guidance on how to choose a home region so
that auto-tagged flood packets are scoped correctly. Also notes
the reserved TRANSPORT_CODE_ALL (0xFFFF) bypass behaviour.
Comment thread docs/cli_commands.md Outdated
Comment thread docs/cli_commands.md Outdated
Comment thread docs/cli_commands.md
- Drop VLAN analogy; describe the behaviour directly so the docs
  stand on their own.
- Clarify region.autotag.max.hops value description to refer to
  "packets without scope" explicitly.
Comment thread src/Packet.h
#define ROUTE_TYPE_DIRECT 0x02 // direct route, 'path' is supplied
#define ROUTE_TYPE_TRANSPORT_DIRECT 0x03 // direct route + transport codes

#define TRANSPORT_CODE_ALL 0xFFFF // special transport code: forward to all regions

@awhite2000 awhite2000 Apr 14, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Client apps will need to support sending packets with this code, which is different from sending without a scope. @liamcottle

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I had hoped that maybe this could be implemented in the client apps. Perhaps a one-time toggle for a message which then reverts? Just to gently encourage people not to just scope every message to all

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm against '0xFFFF'; that can way to easily be abused to DDOS the whole network. I'd say a large region can decide on their own whether to agree on a region wide flood code for emergencies or not.

Clarify that with no home region configured, auto-tagging is
effectively disabled regardless of the region.autotag setting,
and untagged floods fall back to the wildcard region's flood
permission.
Comment thread src/helpers/CommonCLI.cpp Outdated
Comment thread src/helpers/CommonCLI.cpp Outdated
Replace the magic 8 used in both the load-time sanitize and the CLI
set handler with REGION_AUTOTAG_MAX_HOPS_LIMIT, and surface the cap
in the "Error, range is 0-N" reply so the CLI and the constant can
never drift apart.

Also expand the docs to call out the range explicitly, the clamp-on-
load behaviour, and the rationale for the 8 upper bound (well below
flood.max so auto-tagging can't silently scope distant traffic).
Comment thread docs/cli_commands.md
- `value`: Maximum path hash count (0-8). `0` means only auto-tag packets without scope received directly (zero-hop); higher values also auto-tag packets without scope that already traversed that many repeaters.
- `value`: Maximum path hash count. `0` means only auto-tag packets without scope received directly (zero-hop); higher values also auto-tag packets without scope that already traversed that many repeaters.

**Range:** `0` to `8` (inclusive). Values outside this range are rejected by `set` and clamped to this range on load. The upper bound of `8` is intentionally well below the default `flood.max` of `64`, because auto-tagging packets from far across the mesh almost always produces incorrect region assignments — the limit exists to keep admins honest about the geographic scope they can actually account for.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, nice.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8 hops max is very arbitrary. why cap it at 8 hops when it is already configurable by repeater owners? Let the repeater owners decide what max hop fits their needs. there is no one number that works for all meshes.

It is OK to have some recommendations for repeater owners of what values to use based on some other mesh variables.

@ripplebiz

Copy link
Copy Markdown
Member

OK, the TRANSPORT_CODE_ALL doesn't make much sense, to me. It's yet another rule change that would take time to percolate around with firmware version updates. And there already a rule that covers it (well, repeaters that allow un-scoped). Also, strikes me as something that would be abused, ie. if repeaters will all allow 0xFFFF ?

Also, auto-assigning the home region for un-scoped, seems more like a work-around for the current problem of most clients sending un-scoped floods (eg. for DM's, logins, requests, etc). But, this should soon be solved with the 'default scope' feature. (currently in the default-scope branch)

@AI7NC

AI7NC commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

I think this feature is needed. It'll be much easier to get the large-coverage repeater operators to region tag untagged traffic than to get all the users to. Once the majority is tagged then we can move to start blocking * traffic more quickly to better control our airtimes. Without this feature we're at the mercy of every client in the PNW RF network to decide to start tagging their traffic.

There needs to be an incentive to do so and there's no way of doing that right now than blocking * which is much more impactful than tagging their * traffic as the local region. I'm all for this feature.

@awhite2000

awhite2000 commented Apr 15, 2026

Copy link
Copy Markdown

But, this should soon be solved with the 'default scope' feature. (currently in the default-scope branch)

@ripplebiz Please explain how is that different from the auto-tagging that this PR implements? I briefly looked at your branch (which doesn't have a corresponding PR nor any writeup so it's hard to tell what's the end goal) and it seems less robust than this implementation.

@AI7NC

AI7NC commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

@dale-ruane Can you edit your top comment to include the added hop control? Some folks are reading the top comment proposal and are missing that you're including a hop max include setting to keep repeaters from tagging traffic from outside their region based on hops.

@LitBomb

LitBomb commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

8 hops max is very arbitrary. why cap it at 8 hops when it is already configurable by repeater owners? Let the repeater owners decide what max hop fits their needs. there is no one number that works for all meshes.

It is OK to have some recommendations for repeater owners of what values to use based on some other mesh variables.

@skyepn

skyepn commented Apr 17, 2026

Copy link
Copy Markdown

Also, auto-assigning the home region for un-scoped, seems more like a work-around for the current problem of most clients sending un-scoped floods (eg. for DM's, logins, requests, etc). But, this should soon be solved with the 'default scope' feature. (currently in the default-scope branch)

Keep in mind Liam’s app is not the only app, all the apps and bots will have to be updated, plus all the repeaters, plus there’s no guarantee any new app or new bot will implement it, so unscoped flood will still be around for a very long time., probably forever.

Flood traffic control is a big problem now and this would allow key backbone repeater admins to add flood control immediately. I don’t really see any downside other than the possibility of applying the wrong scope to a few packets which we’ve discussed above.

This is a needed workaround imho, repeater owners should be able to tag the traffic going through their own repeaters.

…eSetCmd)

Resolves conflict in src/helpers/CommonCLI.cpp where upstream extracted
the get/set handlers into separate methods. Our region.autotag and
region.autotag.max.hops commands are now placed in the new handleGetCmd
and handleSetCmd methods.
@dale-ruane

Copy link
Copy Markdown
Author

@dale-ruane Can you edit your top comment to include the added hop control? Some folks are reading the top comment proposal and are missing that you're including a hop max include setting to keep repeaters from tagging traffic from outside their region based on hops.

All done.

Also resolved conflicts caused by new upstream release :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants