refactor #1 + adding documentation
Validate source documentation / generated-wiki (pull_request) Failing after 10s

This commit is contained in:
2026-07-19 20:25:12 +00:00
parent db81260d7f
commit b37e0d6bce
31 changed files with 4068 additions and 2598 deletions
+166
View File
@@ -0,0 +1,166 @@
# Developer Guide
This guide describes the current openUF implementation. The daemon is a
single-process, single-threaded OpenWrt service. Its main loop wakes once per
second and schedules discovery, LLDP, and controller inform work.
## Safety first
openUF runs as root. It can replace managed Wi-Fi configuration, create VLAN
devices, send raw Ethernet frames, reboot the device, and persist adoption
credentials. Do not run the daemon itself on a development workstation.
Compile it with the OpenWrt toolchain and perform runtime tests on a disposable
OpenWrt access point.
Protocol debug level 2 can log decrypted credentials. Never enable it by
default, attach those logs to issues, or commit controller payload captures.
## Source layout
| Module | Responsibility |
| --- | --- |
| `src/announce.c` | UniFi layer-2 UDP discovery. |
| `src/clients.c` | Wireless and bridge client telemetry. |
| `src/config.c` | Static daemon configuration parser and defaults. |
| `src/crypto.c` | AES-CBC, AES-GCM, and encoding helpers. |
| `src/http.c` | Minimal HTTP/1.0 transport. |
| `src/inform/inform.c` | One inform request/response exchange. |
| `src/inform/packet.c` | TNBU binary envelope codec. |
| `src/inform/payload.c` | Inform JSON telemetry assembly. |
| `src/inform/response.c` | Controller command and provisioning dispatch. |
| `src/lldp.c` | LLDP frame transmission and neighbor collection. |
| `src/main.c` | Daemon lifecycle and one-second scheduler. |
| `src/models.c` | Emulated hardware model registry. |
| `src/state.c` | Persistent adoption and controller state. |
| `src/sysinfo.c` | Kernel and nl80211 device telemetry. |
| `src/wlan/common.c` | Shared Wi-Fi translations and validators. |
| `src/wlan/legacy.c` | Legacy system_cfg translation. |
| `src/wlan/provision.c` | Modern setstate Wi-Fi provisioning. |
| `src/wlan/radio.c` | Runtime radio mapping and radio settings. |
| `src/wlan/telemetry.c` | Managed VAP telemetry from UCI and nl80211. |
| `src/wlan/uci.c` | Reusable UCI, VLAN, steering, and cleanup operations. |
Public contracts remain in `src/*.h`. The `src/inform/` and `src/wlan/`
directories contain private implementation units; their `*_internal.h` files
are not stable interfaces for other subsystems.
## Runtime architecture
`main()` loads static configuration, persistent controller state, and the
emulated model. It discovers the LAN MAC/IP and an initial controller from the
default route when no explicit controller is configured. The main loop then
schedules:
1. `announce_send()` for UniFi UDP discovery.
2. `lldp_send_frame()` for each model Ethernet port.
3. `inform_send()` for adoption, telemetry, commands, and provisioning.
See [[Runtime Flow|Runtime-Flow]] for the decision flow and
[[Function Call Graph|Call-Graph]] for generated caller/callee relationships.
## Inform and adoption invariants
- The TNBU layout, big-endian fields, flag meanings, authenticated header, and
cipher selection are controller compatibility constraints.
- An unadopted device always encrypts with `DEFAULT_AUTH_KEY`, even if stale
state contains another key.
- The controller response is decoded before command dispatch. Adoption can be
completed through either legacy `set-adopt` or modern `setparam` data.
- `cfgversion` records configuration that was successfully applied locally.
Failed provisioning resets it to `"0"` so the controller retries.
- Increase `OPENUF_CONFIG_SCHEMA` only when an existing persisted
configuration must be reapplied after an upgrade.
## Wi-Fi ownership and provisioning
Only UCI `wifi-iface` sections prefixed with `openuf_` belong to this daemon.
Cleanup must preserve every unrelated section. Controller VAP ObjectIds are
stored in `openuf_vap_id` so client topology remains stable across reprovision.
Modern `setstate` data is applied by `wlan_apply_config()`. Legacy
newline-separated `system_cfg` data is first translated to the same JSON shape
by `wlan_apply_system_cfg()`, keeping one provisioning path responsible for UCI
commits and radio startup.
Model band and port assumptions belong in `models.c`. The runtime radio mapper
may resolve a model band to a different local PHY, but protocol and telemetry
code must not invent model-specific mappings.
## Common development tasks
### Add telemetry
1. Add a bounded reader to `sysinfo.c`, `clients.c`, or another focused module.
2. Add the controller field in `inform/payload.c`.
3. Document units, fallback behavior, ownership, and any sensitive content.
4. Regenerate this Wiki and cross-build the package.
### Add a controller command
1. Extend dispatch in `inform/response.c`.
2. Validate controller values before changing state or invoking a command.
3. Save state only after a coherent transition.
4. Preserve adoption-key and `cfgversion` behavior.
### Add a Wi-Fi setting
1. Parse controller aliases in `wlan/provision.c` or `wlan/legacy.c`.
2. Put reusable UCI work in `wlan/uci.c` and translations in `wlan/common.c`.
3. Report the effective value from `wlan/telemetry.c` when the controller
expects it in `vap_table`.
4. Test on device; a successful cross-build cannot validate netifd/hostapd
behavior.
### Add or change a model
Update `ufmodel.h`, the complete model entry in `models.c`, and every affected
telemetry or WLAN consumer together. Do not scatter model checks across the
protocol implementation.
## Build and validation
From the OpenWrt root:
```sh
make package/OpenUniFi/compile
```
Use `V=s` for detailed compiler diagnostics. If a clean package rebuild is
needed, clean only this package:
```sh
make package/OpenUniFi/clean
make package/OpenUniFi/compile
```
`Makefile.standalone` is only for compiling directly on an OpenWrt device with
development packages installed. It is not a host-side test substitute.
## Documentation workflow
Generate pages after changing C code or architecture:
```sh
./scripts/docs/generate-wiki.py
```
Run the linter-style drift and structure check in CI or before committing:
```sh
./scripts/docs/generate-wiki.py --check
```
The checker parses C functions recursively, rebuilds internal call edges,
validates required runtime entry points, rejects known non-English comment
fragments, and limits each implementation unit to
900 lines.
## Publishing to the Gitea Wiki
Gitea stores a repository Wiki in a separate Git repository whose URL normally
ends in `.wiki.git`. The generated `wiki/` directory is ready for that remote.
Run `scripts/docs/publish-wiki.sh` from a trusted machine with suitable
credentials. It derives the Wiki remote from `origin`; an explicit URL may be
passed when needed. The publisher regenerates and checks the pages,
updates only the generated Markdown files, commits changed pages, and pushes
them to the Wiki repository.