Reviewed-on: #36 Co-authored-by: Koda YeenBean <n122330@gmail.com>
This commit was merged in pull request #36.
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user