From 1626b3f307f4fbc4c49ea4454a6445e71bbadf63 Mon Sep 17 00:00:00 2001 From: Lloyd Date: Wed, 22 Apr 2026 13:52:40 +0100 Subject: [PATCH] feat: add max flood hops configuration to repeater settings --- config.yaml.example | 4 ++++ repeater/engine.py | 8 +++++++- repeater/handler_helpers/mesh_cli.py | 2 +- repeater/handler_helpers/repeater_cli.py | 2 +- repeater/web/api_endpoints.py | 2 +- 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/config.yaml.example b/config.yaml.example index be3f464..1060e7b 100644 --- a/config.yaml.example +++ b/config.yaml.example @@ -31,6 +31,10 @@ repeater: # Duplicate packet cache TTL in seconds cache_ttl: 3600 + # Maximum number of hops a flood packet may have already traversed before + # this repeater forwards it. + max_flood_hops: 64 + # Score-based transmission filtering # Enable quality-based packet filtering and adaptive delays use_score_for_tx: false diff --git a/repeater/engine.py b/repeater/engine.py index cc4f0db..70cd6b0 100644 --- a/repeater/engine.py +++ b/repeater/engine.py @@ -70,6 +70,7 @@ class RepeaterHandler(BaseHandler): self.direct_tx_delay_factor = config.get("delays", {}).get("direct_tx_delay_factor", 0.5) self.use_score_for_tx = config.get("repeater", {}).get("use_score_for_tx", False) self.score_threshold = config.get("repeater", {}).get("score_threshold", 0.3) + self.max_flood_hops = config.get("repeater", {}).get("max_flood_hops", 64) self.send_advert_interval_hours = config.get("repeater", {}).get( "send_advert_interval_hours", 10 ) @@ -858,6 +859,10 @@ class RepeaterHandler(BaseHandler): hash_size = packet.get_path_hash_size() hop_count = packet.get_path_hash_count() + if self.max_flood_hops > 0 and hop_count >= self.max_flood_hops: + packet.drop_reason = f"Max flood hops limit reached ({hop_count}/{self.max_flood_hops})" + return None + # path_len encodes hop count in 6 bits (0-63); adding ourselves must not exceed 63 if hop_count >= 63: packet.drop_reason = "Path hop count at maximum (63), cannot append" @@ -1160,7 +1165,7 @@ class RepeaterHandler(BaseHandler): ), "latitude": repeater_config.get("latitude", 0.0), "longitude": repeater_config.get("longitude", 0.0), - "max_flood_hops": repeater_config.get("max_flood_hops", 3), + "max_flood_hops": repeater_config.get("max_flood_hops", 64), "advert_interval_minutes": repeater_config.get("advert_interval_minutes", 120), "advert_rate_limit": repeater_config.get("advert_rate_limit", {}), "advert_penalty_box": repeater_config.get("advert_penalty_box", {}), @@ -1313,6 +1318,7 @@ class RepeaterHandler(BaseHandler): self.score_threshold = repeater_config.get("score_threshold", 0.3) self.send_advert_interval_hours = repeater_config.get("send_advert_interval_hours", 10) self.cache_ttl = repeater_config.get("cache_ttl", 60) + self.max_flood_hops = repeater_config.get("max_flood_hops", 64) self.loop_detect_mode = self._normalize_loop_detect_mode( self.config.get("mesh", {}).get("loop_detect", LOOP_DETECT_OFF) ) diff --git a/repeater/handler_helpers/mesh_cli.py b/repeater/handler_helpers/mesh_cli.py index 0236a03..f56f1f6 100644 --- a/repeater/handler_helpers/mesh_cli.py +++ b/repeater/handler_helpers/mesh_cli.py @@ -413,7 +413,7 @@ class MeshCLI: return f"> {interval}" elif param == "flood.max": - max_flood = self.repeater_config.get("max_flood_hops", 3) + max_flood = self.repeater_config.get("max_flood_hops", 64) return f"> {max_flood}" elif param == "rxdelay": diff --git a/repeater/handler_helpers/repeater_cli.py b/repeater/handler_helpers/repeater_cli.py index c710cfc..6620606 100644 --- a/repeater/handler_helpers/repeater_cli.py +++ b/repeater/handler_helpers/repeater_cli.py @@ -401,7 +401,7 @@ class MeshCLI: return f"> {interval}" elif param == "flood.max": - max_flood = self.repeater_config.get("max_flood_hops", 3) + max_flood = self.repeater_config.get("max_flood_hops", 64) return f"> {max_flood}" elif param == "rxdelay": diff --git a/repeater/web/api_endpoints.py b/repeater/web/api_endpoints.py index 766ced0..4776038 100644 --- a/repeater/web/api_endpoints.py +++ b/repeater/web/api_endpoints.py @@ -1783,7 +1783,7 @@ class APIEndpoints: "node_name": "MyNode", # Node name "latitude": 0.0, # Latitude (-90 to 90) "longitude": 0.0, # Longitude (-180 to 180) - "max_flood_hops": 3, # Max flood hops (0-64) + "max_flood_hops": 64, # Max flood hops (0-64) "flood_advert_interval_hours": 10, # Flood advert interval (0 or 3-48) "advert_interval_minutes": 120 # Local advert interval (0 or 1-10080) }