From 3d2c0e4ec6708d8f41ecd9603a556613a1ca8af2 Mon Sep 17 00:00:00 2001 From: jettwang Date: Fri, 12 Jun 2026 19:54:48 +0800 Subject: [PATCH] feat: raise default MAX_PEERS to 32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Operators now routinely need more than the previous default of 16 peers, so bump the `-Dmax-peers` default to 32 (the 1..128 range and 128 cap are unchanged). The derived `MAX_POLICY_ENTRIES` becomes 32 + MAX_ROUTES*2 + 224 = 272, and the static musl subnetrad grows ~20KB to ~284KB — well within the 512KB iron-law budget. Docs (EN + ZH) and the in-code comments are updated to state "default 32 → 272" and drop the now-obsolete "reproduces the historical 256-entry table" wording. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- build.zig | 6 +++--- docs-site/en/src/configuration/reference.md | 2 +- docs-site/en/src/getting-started/installation.md | 11 +++++------ docs-site/zh/src/configuration/reference.md | 2 +- docs-site/zh/src/getting-started/installation.md | 8 ++++---- src/config.zig | 5 ++--- src/uds.zig | 6 +++--- 7 files changed, 19 insertions(+), 21 deletions(-) diff --git a/build.zig b/build.zig index faedeb8..dfce452 100644 --- a/build.zig +++ b/build.zig @@ -16,11 +16,11 @@ pub fn build(b: *std.Build) void { // Compile-time peer-table capacity (`config.MAX_PEERS`). The peer registry // and parsed config are fixed-capacity, zero-allocation arrays, so the cap is // a build option rather than a runtime knob (matches the recompile-to-change - // ethos). Default 16; capped at 128 — beyond that the single-threaded + // ethos). Default 32; capped at 128 — beyond that the single-threaded // reactor's O(N)-per-packet peer/policy scans dominate and splitting into // multiple hubs is the right answer. `uds.MAX_POLICY_ENTRIES` is derived from - // this value (default 16 keeps the historical 256-entry table). - const max_peers = b.option(usize, "max-peers", "Max mesh peers per node (1..128, default 16)") orelse 16; + // this value (default 32 → a 272-entry policy table). + const max_peers = b.option(usize, "max-peers", "Max mesh peers per node (1..128, default 32)") orelse 32; if (max_peers < 1 or max_peers > 128) { std.log.err("-Dmax-peers must be in 1..128 (got {d})", .{max_peers}); std.process.exit(1); diff --git a/docs-site/en/src/configuration/reference.md b/docs-site/en/src/configuration/reference.md index 17f34b2..d6996f2 100644 --- a/docs-site/en/src/configuration/reference.md +++ b/docs-site/en/src/configuration/reference.md @@ -58,7 +58,7 @@ Each entry of `peers[]`: > peers is rejected with `DuplicatePsk`. > **Peer cap.** `peers[]` has a fixed, zero-allocation capacity chosen at build -> time by `-Dmax-peers` (default **16**, max **128**); a hub manages at most this +> time by `-Dmax-peers` (default **32**, max **128**); a hub manages at most this > many spokes, and the policy-table size scales with it. See > [Tuning the peer cap](../getting-started/installation.md#tuning-the-peer-cap). diff --git a/docs-site/en/src/getting-started/installation.md b/docs-site/en/src/getting-started/installation.md index 5701bc0..dc8ec52 100644 --- a/docs-site/en/src/getting-started/installation.md +++ b/docs-site/en/src/getting-started/installation.md @@ -182,7 +182,7 @@ Artifacts are placed in `zig-out/bin/`: `subnetrad` (daemon) and `subnetra` The peer registry and parsed config are fixed-capacity, zero-allocation arrays, so the maximum number of mesh peers a node can hold is a **compile-time** build -option (`-Dmax-peers`) — not a runtime config field. It defaults to **16** and +option (`-Dmax-peers`) — not a runtime config field. It defaults to **32** and is capped at **128**: ```bash @@ -191,11 +191,10 @@ zig build -Dmax-peers=128 -Dtarget=aarch64-linux-musl # combine with a target ``` A `hub` manages at most this many spokes. This is a **per-node** sizing knob — -it is never negotiated on the wire, so a spoke that only talks to one hub can -keep the default 16 even when the hub is built with a larger cap. The -control-plane policy-table size (`MAX_POLICY_ENTRIES`) is **derived** from this -value, so raising the cap grows the policy capacity automatically; the default -of 16 reproduces the historical 256-entry table exactly. +it is never negotiated on the wire, so a spoke that only talks to one hub does +not need the hub's larger cap. The control-plane policy-table size +(`MAX_POLICY_ENTRIES`) is **derived** from this value, so raising the cap grows +the policy capacity automatically (the default 32 yields a 272-entry table). Raising it much higher trades memory and latency for capacity: the reactor is a single-threaded, per-packet `O(N)` scan over peers (and, with `obfuscate` on, a diff --git a/docs-site/zh/src/configuration/reference.md b/docs-site/zh/src/configuration/reference.md index 22a5e07..a3e090e 100644 --- a/docs-site/zh/src/configuration/reference.md +++ b/docs-site/zh/src/configuration/reference.md @@ -55,7 +55,7 @@ > 拒绝;在多个对端间复用一把 PSK 以 `DuplicatePsk` 拒绝。 > **对端上限。** `peers[]` 的容量固定、零分配,由构建选项 `-Dmax-peers` 在编译期确定 -> (默认 **16**,上限 **128**);一个 hub 最多管理这么多 spoke,策略表大小随之伸缩。 +> (默认 **32**,上限 **128**);一个 hub 最多管理这么多 spoke,策略表大小随之伸缩。 > 见[调整对端数量上限](../getting-started/installation.md#调整对端数量上限)。 ## 防呆自检 diff --git a/docs-site/zh/src/getting-started/installation.md b/docs-site/zh/src/getting-started/installation.md index 45402dc..7cb835e 100644 --- a/docs-site/zh/src/getting-started/installation.md +++ b/docs-site/zh/src/getting-started/installation.md @@ -165,7 +165,7 @@ zig build run ### 调整对端数量上限 对端注册表与解析后的配置都是固定容量、零分配的数组,因此单个节点能容纳的最大网格对端 -数量是一个**编译期**构建选项(`-Dmax-peers`),而非运行时配置字段。默认 **16**,上限 +数量是一个**编译期**构建选项(`-Dmax-peers`),而非运行时配置字段。默认 **32**,上限 **128**: ```bash @@ -174,9 +174,9 @@ zig build -Dmax-peers=128 -Dtarget=aarch64-linux-musl # 与交叉编译目标 ``` 一个 `hub` 最多管理这么多 spoke。这是**逐节点**的容量旋钮——它不在链路上协商,因此一个 -只连接单个 hub 的 spoke,即使 hub 用更大的上限构建,自己仍可保持默认 16。控制面策略表 -大小(`MAX_POLICY_ENTRIES`)由该值**自动推导**,因此提升上限会自动增大策略容量;默认 -16 恰好复现历史上的 256 条策略表。 +只连接单个 hub 的 spoke 无需跟随 hub 的更大上限。控制面策略表大小 +(`MAX_POLICY_ENTRIES`)由该值**自动推导**,因此提升上限会自动增大策略容量(默认 32 +对应 272 条策略表)。 把它调得过高是在用内存与延迟换容量:reactor 是单线程、每包对对端做 `O(N)` 扫描(开启 `obfuscate` 时每个入站数据报还要逐对端试解掩),因此超大网格更应当**拆分为多个 hub**, diff --git a/src/config.zig b/src/config.zig index b8fda55..d6114f0 100644 --- a/src/config.zig +++ b/src/config.zig @@ -23,9 +23,8 @@ pub const DEFAULT_TUN_MTU: u16 = netplan.maxTunMtu(netplan.DEFAULT_PATH_MTU); /// Maximum number of mesh peers a single node can be configured with. Fixed at /// compile time so the registry and parsed config stay zero-allocation, /// fixed-capacity arrays (issue #5). Set via the `-Dmax-peers` build option -/// (default 16, capped at 128); a hub manages at most this many spokes. -/// `uds.MAX_POLICY_ENTRIES` is derived from this value, so the default 16 keeps -/// the historical 256-entry policy table. +/// (default 32, capped at 128); a hub manages at most this many spokes. +/// `uds.MAX_POLICY_ENTRIES` is derived from this value (default 32 → 272). pub const MAX_PEERS: usize = build_options.max_peers; /// Maximum length of an optional, human-readable peer name (e.g. `bj-office-gw`). diff --git a/src/uds.zig b/src/uds.zig index d59a179..be5c4a7 100644 --- a/src/uds.zig +++ b/src/uds.zig @@ -46,9 +46,9 @@ else "/run/subnetra/subnetra.policy"; /// Headroom for operator-added policy rules layered on top of the role-derived -/// table. Sized so the default `config.MAX_PEERS = 16` reproduces the historical -/// 256-entry table (16 + MAX_ROUTES*2 + 224 = 256), keeping the default build's -/// behavior unchanged. +/// table (one forward rule per spoke + route rules). 224 leaves ample room for +/// manual `policy add` rules; with the default `config.MAX_PEERS = 32` the table +/// is 32 + MAX_ROUTES*2 + 224 = 272 entries. const POLICY_HEADROOM: usize = 224; /// Upper bound on installed policy rules. Derived from `config.MAX_PEERS` so a