From 67d2c44f968dfbdf28133ac60b97fd7bfa7479d9 Mon Sep 17 00:00:00 2001 From: Anton Date: Fri, 21 Aug 2026 00:01:09 +0200 Subject: [PATCH] Make ML_DERP_REGION a Kconfig option instead of a hardcoded #define Fixes #19. Every deployment outside North America that depends on relayed traffic (CGNAT peers, i.e. most cellular clients) currently pays intercontinental RTT on every relayed byte, since the preferred DERP region is hardcoded to 9 (Dallas) with no way to change it short of patching this header. This is the interim fix suggested in #19: turn ML_DERP_REGION into a Kconfig int option (default unchanged at 9, so existing deployments are unaffected) instead of a #define, so users can set the closest region to their own deployment via `idf.py menuconfig` without patching library source. Region IDs are visible in a device's own boot log once the initial MapResponse is parsed (`ml_coord: DERP region N (code): ...`). ML_DERP_HOST/_PORT are deliberately left hardcoded - they're only a bootstrap fallback used before the first DERPMap arrives; ml_derp_connect() already uses the real per-region host from the parsed DERPMap once available, so they don't need to track the preferred region. Verified on real hardware (ESP32-S3, set to region 4/Frankfurt for a Germany-based deployment): clean boot shows "Home DERP region: 4 (default)" and "Connecting to DERP derp4j.tailscale.com:443 (region 4)" - the real DERPMap-resolved host for the configured region. A full STUN-probe-and-pick-lowest-latency implementation (what real Tailscale clients do) is a bigger change than this - deliberately scoped to just the interim fix #19 itself suggested. --- components/microlink/Kconfig | 19 +++++++++++++++++++ .../microlink/include/microlink_internal.h | 10 ++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/components/microlink/Kconfig b/components/microlink/Kconfig index a8e0a31..c80eaad 100644 --- a/components/microlink/Kconfig +++ b/components/microlink/Kconfig @@ -32,6 +32,25 @@ menu "MicroLink V2 Configuration" communicate with). For large tailnets, set this to the actual peer count needed, not the total tailnet size. + config ML_DERP_REGION + int "Preferred DERP region ID" + default 9 + help + Tailscale DERP region ID to advertise as this node's home region + (sent as Hostinfo.NetInfo.PreferredDERP) and to prefer for STUN + probing/relay fallback before any live latency measurement has + happened. Defaults to 9 (Dallas, Texas) - fine for North America, + but every deployment relying on DERP-relayed traffic (e.g. a peer + behind CGNAT with no direct path) from elsewhere in the world pays + needless latency relaying through Dallas instead of a nearby + region. Real Tailscale clients pick this by STUN-probing several + regions at startup and using whichever has the lowest measured + latency; this project doesn't do that yet, so pick the closest + region to this device's usual network by hand instead. Region IDs + are visible in this device's own boot log (`ml_coord: DERP region + N (code): ...`, printed once the initial MapResponse is parsed) - + e.g. 4 = Frankfurt, 14 = Amsterdam, 18 = Paris. + config ML_PRIORITY_PEER_IP string "Priority peer VPN IP" default "" diff --git a/components/microlink/include/microlink_internal.h b/components/microlink/include/microlink_internal.h index add69c7..438b175 100644 --- a/components/microlink/include/microlink_internal.h +++ b/components/microlink/include/microlink_internal.h @@ -73,8 +73,14 @@ extern "C" { #define ML_MAX_PACKET_SIZE 1500 #define ML_DERP_MAX_FRAME (ML_MAX_PACKET_SIZE + 64) -/* DERP */ -#define ML_DERP_REGION 9 /* Dallas (dfw) */ +/* DERP - preferred region is Kconfig-driven (default 9/Dallas) rather than + * hardcoded, so a deployment relying on DERP-relayed traffic (e.g. a peer + * behind CGNAT with no direct path) elsewhere in the world doesn't pay + * needless latency relaying through Dallas - see ML_DERP_REGION's Kconfig + * help text. ML_DERP_HOST/_PORT stay hardcoded: they're only a bootstrap + * fallback used before the first DERPMap arrives (ml_derp.c's ml_derp_connect + * uses the real per-region host from the parsed DERPMap once available). */ +#define ML_DERP_REGION CONFIG_ML_DERP_REGION #define ML_DERP_HOST "derp9e.tailscale.com" #define ML_DERP_PORT 443