From f241b021a23dcb4611beea9d2928cb695d71001d Mon Sep 17 00:00:00 2001 From: Koda YeenBean Date: Sun, 19 Jul 2026 23:01:16 +0200 Subject: [PATCH] moved wiki section --- Call-Graph.md | 411 +++++++++++++++++++++++++++++++++++++++++++++ Developer-Guide.md | 166 ++++++++++++++++++ Home.md | 13 ++ Runtime-Flow.md | 76 +++++++++ TESTNG.md | 1 - _Sidebar.md | 4 + 6 files changed, 670 insertions(+), 1 deletion(-) create mode 100644 Call-Graph.md create mode 100644 Developer-Guide.md create mode 100644 Home.md create mode 100644 Runtime-Flow.md delete mode 100644 TESTNG.md create mode 100644 _Sidebar.md diff --git a/Call-Graph.md b/Call-Graph.md new file mode 100644 index 0000000..cec69c7 --- /dev/null +++ b/Call-Graph.md @@ -0,0 +1,411 @@ +# Function Call Graph + +Generated from `src/**/*.c` by `scripts/docs/generate-wiki.py`. + +```mermaid +flowchart LR + subgraph module_0["src/announce.c"] + function_announce_c_tlv_append["tlv_append()"] + function_announce_c_tlv_str["tlv_str()"] + function_announce_c_put32be["put32be()"] + function_announce_c_parse_mac["parse_mac()"] + function_announce_c_parse_ip["parse_ip()"] + function_announce_c_announce_init["announce_init()"] + function_announce_c_announce_send["announce_send()"] + function_announce_c_announce_close["announce_close()"] + end + subgraph module_1["src/clients.c"] + function_clients_c_mac_lower["mac_lower()"] + function_clients_c_clients_mac_to_ip["clients_mac_to_ip()"] + function_clients_c_clients_mac_to_hostname["clients_mac_to_hostname()"] + function_clients_c_parse_rate_kbps["parse_rate_kbps()"] + function_clients_c_clients_read_wifi["clients_read_wifi()"] + function_clients_c_clients_build_sta_table["clients_build_sta_table()"] + end + subgraph module_2["src/config.c"] + function_config_c_config_load["config_load()"] + end + subgraph module_3["src/crypto.c"] + function_crypto_c_crypto_hex2bin["crypto_hex2bin()"] + function_crypto_c_crypto_bin2hex["crypto_bin2hex()"] + function_crypto_c_crypto_random_hex["crypto_random_hex()"] + function_crypto_c_crypto_encrypt["crypto_encrypt()"] + function_crypto_c_crypto_decrypt["crypto_decrypt()"] + function_crypto_c_crypto_gcm_encrypt["crypto_gcm_encrypt()"] + function_crypto_c_crypto_gcm_decrypt["crypto_gcm_decrypt()"] + end + subgraph module_4["src/http.c"] + function_http_c_parse_url["parse_url()"] + function_http_c_http_post["http_post()"] + end + subgraph module_5["src/inform/inform.c"] + function_inform_inform_c_inform_send["inform_send()"] + end + subgraph module_6["src/inform/packet.c"] + function_inform_packet_c_put32be["put32be()"] + function_inform_packet_c_put16be["put16be()"] + function_inform_packet_c_get32be["get32be()"] + function_inform_packet_c_get16be["get16be()"] + function_inform_packet_c_inform_packet_build["inform_packet_build()"] + function_inform_packet_c_inform_packet_parse["inform_packet_parse()"] + end + subgraph module_7["src/inform/payload.c"] + function_inform_payload_c_build_sys_stats["build_sys_stats()"] + function_inform_payload_c_build_system_stats["build_system_stats()"] + function_inform_payload_c_build_if_table["build_if_table()"] + function_inform_payload_c_radio_runtime_iface["radio_runtime_iface()"] + function_inform_payload_c_build_scan_table["build_scan_table()"] + function_inform_payload_c_build_athstats["build_athstats()"] + function_inform_payload_c_build_radio_table["build_radio_table()"] + function_inform_payload_c_build_radio_table_stats["build_radio_table_stats()"] + function_inform_payload_c_build_port_table["build_port_table()"] + function_inform_payload_c_build_eth_table["build_eth_table()"] + function_inform_payload_c_build_vap_table["build_vap_table()"] + function_inform_payload_c_collect_sta_table["collect_sta_table()"] + function_inform_payload_c_inform_build_payload["inform_build_payload()"] + end + subgraph module_8["src/inform/response.c"] + function_inform_response_c_inform_valid_auth_key["inform_valid_auth_key()"] + function_inform_response_c_inform_set_debug_level["inform_set_debug_level()"] + function_inform_response_c_inform_debug_level["inform_debug_level()"] + function_inform_response_c_inform_debug_system_cfg_key["inform_debug_system_cfg_key()"] + function_inform_response_c_inform_log_controller_response["inform_log_controller_response()"] + function_inform_response_c_reboot_openwrt["reboot_openwrt()"] + function_inform_response_c_inform_handle_response["inform_handle_response()"] + end + subgraph module_9["src/lldp.c"] + function_lldp_c_tlv_write["tlv_write()"] + function_lldp_c_tlv_str["tlv_str()"] + function_lldp_c_parse_mac["parse_mac()"] + function_lldp_c_lldp_send_frame["lldp_send_frame()"] + function_lldp_c_lldp_available["lldp_available()"] + function_lldp_c_lldp_read_neighbors["lldp_read_neighbors()"] + end + subgraph module_10["src/main.c"] + function_main_c_get_mac["get_mac()"] + function_main_c_get_ip["get_ip()"] + function_main_c_get_default_gateway["get_default_gateway()"] + function_main_c_main["main()"] + end + subgraph module_11["src/models.c"] + function_models_c_ufmodel_find["ufmodel_find()"] + end + subgraph module_12["src/state.c"] + function_state_c_state_defaults["state_defaults()"] + function_state_c_state_load["state_load()"] + function_state_c_state_save["state_save()"] + end + subgraph module_13["src/sysinfo.c"] + function_sysinfo_c_sysinfo_mem["sysinfo_mem()"] + function_sysinfo_c_read_cpu["read_cpu()"] + function_sysinfo_c_sysinfo_cpu_percent["sysinfo_cpu_percent()"] + function_sysinfo_c_read_sysfs_str["read_sysfs_str()"] + function_sysinfo_c_read_sysfs_int["read_sysfs_int()"] + function_sysinfo_c_read_ip_ioctl["read_ip_ioctl()"] + function_sysinfo_c_sysinfo_iface["sysinfo_iface()"] + function_sysinfo_c_utilization_percent["utilization_percent()"] + function_sysinfo_c_count_antenna_chains["count_antenna_chains()"] + function_sysinfo_c_sysinfo_radio["sysinfo_radio()"] + function_sysinfo_c_frequency_to_channel["frequency_to_channel()"] + function_sysinfo_c_sysinfo_wifi_scan_cache["sysinfo_wifi_scan_cache()"] + end + subgraph module_14["src/wlan/common.c"] + function_wlan_common_c_wlan_security_to_uci["wlan_security_to_uci()"] + function_wlan_common_c_wlan_security_to_unifi["wlan_security_to_unifi()"] + function_wlan_common_c_wlan_valid_object_id["wlan_valid_object_id()"] + function_wlan_common_c_wlan_ensure_vap_ids["wlan_ensure_vap_ids()"] + function_wlan_common_c_wlan_mobility_domain_for_ssid["wlan_mobility_domain_for_ssid()"] + function_wlan_common_c_wlan_radio_uses_ath9k["wlan_radio_uses_ath9k()"] + function_wlan_common_c_wlan_json_boolean_any["wlan_json_boolean_any()"] + function_wlan_common_c_wlan_feature_enabled["wlan_feature_enabled()"] + function_wlan_common_c_wlan_safe_section_name["wlan_safe_section_name()"] + end + subgraph module_15["src/wlan/legacy.c"] + function_wlan_legacy_c_system_cfg_get["system_cfg_get()"] + function_wlan_legacy_c_wlan_apply_system_cfg["wlan_apply_system_cfg()"] + end + subgraph module_16["src/wlan/provision.c"] + function_wlan_provision_c_apply_vap["apply_vap()"] + function_wlan_provision_c_force_wifi4_for_band["force_wifi4_for_band()"] + function_wlan_provision_c_wlan_apply_config["wlan_apply_config()"] + end + subgraph module_17["src/wlan/radio.c"] + function_wlan_radio_c_band_bit["band_bit()"] + function_wlan_radio_c_bit_count["bit_count()"] + function_wlan_radio_c_detect_radio_bands["detect_radio_bands()"] + function_wlan_radio_c_resolve_radio_map["resolve_radio_map()"] + function_wlan_radio_c_wlan_device_for_band["wlan_device_for_band()"] + function_wlan_radio_c_wlan_band_for_device["wlan_band_for_device()"] + function_wlan_radio_c_radio_max_standard["radio_max_standard()"] + function_wlan_radio_c_select_htmode["select_htmode()"] + function_wlan_radio_c_wlan_apply_radio["wlan_apply_radio()"] + end + subgraph module_18["src/wlan/telemetry.c"] + function_wlan_telemetry_c_find_runtime_vap["find_runtime_vap()"] + function_wlan_telemetry_c_wlan_get_vap_table["wlan_get_vap_table()"] + end + subgraph module_19["src/wlan/uci.c"] + function_wlan_uci_c_wlan_uci_set["wlan_uci_set()"] + function_wlan_uci_c_wlan_uci_set_required["wlan_uci_set_required()"] + function_wlan_uci_c_wlan_uci_add_list["wlan_uci_add_list()"] + function_wlan_uci_c_wlan_uci_ensure_section["wlan_uci_ensure_section()"] + function_wlan_uci_c_find_vlan_uplink["find_vlan_uplink()"] + function_wlan_uci_c_wlan_ensure_vlan_network["wlan_ensure_vlan_network()"] + function_wlan_uci_c_wlan_configure_band_steering["wlan_configure_band_steering()"] + function_wlan_uci_c_wlan_clear["wlan_clear()"] + end + function_announce_c_tlv_str --> function_announce_c_tlv_append + function_announce_c_announce_init --> function_announce_c_tlv_append + function_announce_c_announce_init --> function_announce_c_tlv_str + function_announce_c_announce_init --> function_announce_c_parse_mac + function_announce_c_announce_init --> function_announce_c_parse_ip + function_announce_c_announce_send --> function_announce_c_put32be + function_clients_c_clients_mac_to_ip --> function_clients_c_mac_lower + function_clients_c_clients_mac_to_hostname --> function_clients_c_mac_lower + function_clients_c_clients_read_wifi --> function_clients_c_clients_mac_to_ip + function_clients_c_clients_read_wifi --> function_clients_c_clients_mac_to_hostname + function_clients_c_clients_read_wifi --> function_clients_c_parse_rate_kbps + function_clients_c_clients_build_sta_table --> function_clients_c_clients_read_wifi + function_crypto_c_crypto_random_hex --> function_crypto_c_crypto_bin2hex + function_crypto_c_crypto_encrypt --> function_crypto_c_crypto_hex2bin + function_crypto_c_crypto_decrypt --> function_crypto_c_crypto_hex2bin + function_crypto_c_crypto_gcm_encrypt --> function_crypto_c_crypto_hex2bin + function_crypto_c_crypto_gcm_decrypt --> function_crypto_c_crypto_hex2bin + function_http_c_http_post --> function_http_c_parse_url + function_inform_inform_c_inform_send --> function_http_c_http_post + function_inform_inform_c_inform_send --> function_inform_packet_c_inform_packet_build + function_inform_inform_c_inform_send --> function_inform_packet_c_inform_packet_parse + function_inform_inform_c_inform_send --> function_inform_payload_c_inform_build_payload + function_inform_inform_c_inform_send --> function_inform_response_c_inform_log_controller_response + function_inform_inform_c_inform_send --> function_inform_response_c_inform_handle_response + function_inform_inform_c_inform_send --> function_state_c_state_save + function_inform_packet_c_inform_packet_build --> function_crypto_c_crypto_hex2bin + function_inform_packet_c_inform_packet_build --> function_crypto_c_crypto_random_hex + function_inform_packet_c_inform_packet_build --> function_crypto_c_crypto_encrypt + function_inform_packet_c_inform_packet_build --> function_crypto_c_crypto_gcm_encrypt + function_inform_packet_c_inform_packet_build --> function_inform_packet_c_put32be + function_inform_packet_c_inform_packet_build --> function_inform_packet_c_put16be + function_inform_packet_c_inform_packet_parse --> function_crypto_c_crypto_bin2hex + function_inform_packet_c_inform_packet_parse --> function_crypto_c_crypto_decrypt + function_inform_packet_c_inform_packet_parse --> function_crypto_c_crypto_gcm_decrypt + function_inform_packet_c_inform_packet_parse --> function_inform_packet_c_get32be + function_inform_packet_c_inform_packet_parse --> function_inform_packet_c_get16be + function_inform_payload_c_build_sys_stats --> function_sysinfo_c_sysinfo_mem + function_inform_payload_c_build_sys_stats --> function_sysinfo_c_sysinfo_cpu_percent + function_inform_payload_c_build_if_table --> function_sysinfo_c_sysinfo_iface + function_inform_payload_c_radio_runtime_iface --> function_wlan_radio_c_wlan_device_for_band + function_inform_payload_c_radio_runtime_iface --> function_wlan_telemetry_c_wlan_get_vap_table + function_inform_payload_c_build_scan_table --> function_sysinfo_c_sysinfo_wifi_scan_cache + function_inform_payload_c_build_radio_table --> function_inform_payload_c_radio_runtime_iface + function_inform_payload_c_build_radio_table --> function_inform_payload_c_build_scan_table + function_inform_payload_c_build_radio_table --> function_inform_payload_c_build_athstats + function_inform_payload_c_build_radio_table --> function_inform_response_c_inform_debug_level + function_inform_payload_c_build_radio_table_stats --> function_inform_payload_c_radio_runtime_iface + function_inform_payload_c_build_radio_table_stats --> function_sysinfo_c_sysinfo_radio + function_inform_payload_c_build_port_table --> function_sysinfo_c_sysinfo_iface + function_inform_payload_c_build_vap_table --> function_clients_c_clients_build_sta_table + function_inform_payload_c_build_vap_table --> function_sysinfo_c_sysinfo_iface + function_inform_payload_c_build_vap_table --> function_sysinfo_c_sysinfo_radio + function_inform_payload_c_build_vap_table --> function_wlan_radio_c_wlan_device_for_band + function_inform_payload_c_build_vap_table --> function_wlan_telemetry_c_wlan_get_vap_table + function_inform_payload_c_inform_build_payload --> function_inform_payload_c_build_sys_stats + function_inform_payload_c_inform_build_payload --> function_inform_payload_c_build_system_stats + function_inform_payload_c_inform_build_payload --> function_inform_payload_c_build_if_table + function_inform_payload_c_inform_build_payload --> function_inform_payload_c_build_radio_table + function_inform_payload_c_inform_build_payload --> function_inform_payload_c_build_radio_table_stats + function_inform_payload_c_inform_build_payload --> function_inform_payload_c_build_port_table + function_inform_payload_c_inform_build_payload --> function_inform_payload_c_build_eth_table + function_inform_payload_c_inform_build_payload --> function_inform_payload_c_build_vap_table + function_inform_payload_c_inform_build_payload --> function_inform_payload_c_collect_sta_table + function_inform_payload_c_inform_build_payload --> function_lldp_c_lldp_read_neighbors + function_inform_response_c_inform_log_controller_response --> function_inform_response_c_inform_debug_system_cfg_key + function_inform_response_c_inform_handle_response --> function_inform_response_c_inform_valid_auth_key + function_inform_response_c_inform_handle_response --> function_inform_response_c_reboot_openwrt + function_inform_response_c_inform_handle_response --> function_state_c_state_save + function_inform_response_c_inform_handle_response --> function_wlan_legacy_c_wlan_apply_system_cfg + function_inform_response_c_inform_handle_response --> function_wlan_provision_c_wlan_apply_config + function_lldp_c_tlv_str --> function_lldp_c_tlv_write + function_lldp_c_lldp_send_frame --> function_lldp_c_tlv_write + function_lldp_c_lldp_send_frame --> function_lldp_c_tlv_str + function_lldp_c_lldp_send_frame --> function_lldp_c_parse_mac + function_lldp_c_lldp_read_neighbors --> function_lldp_c_lldp_available + function_main_c_main --> function_announce_c_announce_init + function_main_c_main --> function_announce_c_announce_send + function_main_c_main --> function_announce_c_announce_close + function_main_c_main --> function_config_c_config_load + function_main_c_main --> function_inform_inform_c_inform_send + function_main_c_main --> function_inform_response_c_inform_set_debug_level + function_main_c_main --> function_lldp_c_lldp_send_frame + function_main_c_main --> function_lldp_c_lldp_available + function_main_c_main --> function_main_c_get_mac + function_main_c_main --> function_main_c_get_ip + function_main_c_main --> function_main_c_get_default_gateway + function_main_c_main --> function_models_c_ufmodel_find + function_main_c_main --> function_state_c_state_load + function_main_c_main --> function_state_c_state_save + function_state_c_state_load --> function_state_c_state_defaults + function_sysinfo_c_sysinfo_cpu_percent --> function_sysinfo_c_read_cpu + function_sysinfo_c_read_sysfs_int --> function_sysinfo_c_read_sysfs_str + function_sysinfo_c_sysinfo_iface --> function_sysinfo_c_read_sysfs_str + function_sysinfo_c_sysinfo_iface --> function_sysinfo_c_read_sysfs_int + function_sysinfo_c_sysinfo_iface --> function_sysinfo_c_read_ip_ioctl + function_sysinfo_c_sysinfo_radio --> function_sysinfo_c_utilization_percent + function_sysinfo_c_sysinfo_radio --> function_sysinfo_c_count_antenna_chains + function_sysinfo_c_sysinfo_wifi_scan_cache --> function_sysinfo_c_frequency_to_channel + function_wlan_common_c_wlan_ensure_vap_ids --> function_crypto_c_crypto_random_hex + function_wlan_common_c_wlan_ensure_vap_ids --> function_wlan_common_c_wlan_valid_object_id + function_wlan_legacy_c_wlan_apply_system_cfg --> function_wlan_common_c_wlan_valid_object_id + function_wlan_legacy_c_wlan_apply_system_cfg --> function_wlan_common_c_wlan_feature_enabled + function_wlan_legacy_c_wlan_apply_system_cfg --> function_wlan_legacy_c_system_cfg_get + function_wlan_legacy_c_wlan_apply_system_cfg --> function_wlan_provision_c_wlan_apply_config + function_wlan_provision_c_apply_vap --> function_wlan_common_c_wlan_security_to_uci + function_wlan_provision_c_apply_vap --> function_wlan_common_c_wlan_valid_object_id + function_wlan_provision_c_apply_vap --> function_wlan_common_c_wlan_mobility_domain_for_ssid + function_wlan_provision_c_apply_vap --> function_wlan_common_c_wlan_radio_uses_ath9k + function_wlan_provision_c_apply_vap --> function_wlan_common_c_wlan_json_boolean_any + function_wlan_provision_c_apply_vap --> function_wlan_common_c_wlan_safe_section_name + function_wlan_provision_c_apply_vap --> function_wlan_uci_c_wlan_uci_set_required + function_wlan_provision_c_apply_vap --> function_wlan_uci_c_wlan_uci_add_list + function_wlan_provision_c_apply_vap --> function_wlan_uci_c_wlan_uci_ensure_section + function_wlan_provision_c_apply_vap --> function_wlan_uci_c_wlan_ensure_vlan_network + function_wlan_provision_c_force_wifi4_for_band --> function_wlan_common_c_wlan_json_boolean_any + function_wlan_provision_c_wlan_apply_config --> function_wlan_common_c_wlan_ensure_vap_ids + function_wlan_provision_c_wlan_apply_config --> function_wlan_common_c_wlan_json_boolean_any + function_wlan_provision_c_wlan_apply_config --> function_wlan_provision_c_apply_vap + function_wlan_provision_c_wlan_apply_config --> function_wlan_provision_c_force_wifi4_for_band + function_wlan_provision_c_wlan_apply_config --> function_wlan_radio_c_wlan_device_for_band + function_wlan_provision_c_wlan_apply_config --> function_wlan_radio_c_wlan_apply_radio + function_wlan_provision_c_wlan_apply_config --> function_wlan_uci_c_wlan_configure_band_steering + function_wlan_provision_c_wlan_apply_config --> function_wlan_uci_c_wlan_clear + function_wlan_radio_c_resolve_radio_map --> function_wlan_radio_c_band_bit + function_wlan_radio_c_resolve_radio_map --> function_wlan_radio_c_bit_count + function_wlan_radio_c_resolve_radio_map --> function_wlan_radio_c_detect_radio_bands + function_wlan_radio_c_wlan_device_for_band --> function_wlan_radio_c_resolve_radio_map + function_wlan_radio_c_wlan_band_for_device --> function_wlan_radio_c_resolve_radio_map + function_wlan_radio_c_select_htmode --> function_wlan_radio_c_radio_max_standard + function_wlan_radio_c_wlan_apply_radio --> function_wlan_radio_c_select_htmode + function_wlan_telemetry_c_wlan_get_vap_table --> function_wlan_common_c_wlan_security_to_unifi + function_wlan_telemetry_c_wlan_get_vap_table --> function_wlan_common_c_wlan_valid_object_id + function_wlan_telemetry_c_wlan_get_vap_table --> function_wlan_radio_c_wlan_band_for_device + function_wlan_telemetry_c_wlan_get_vap_table --> function_wlan_telemetry_c_find_runtime_vap + function_wlan_uci_c_wlan_uci_set_required --> function_wlan_uci_c_wlan_uci_set + function_wlan_uci_c_wlan_ensure_vlan_network --> function_wlan_uci_c_wlan_uci_add_list + function_wlan_uci_c_wlan_ensure_vlan_network --> function_wlan_uci_c_wlan_uci_ensure_section + function_wlan_uci_c_wlan_ensure_vlan_network --> function_wlan_uci_c_find_vlan_uplink + function_wlan_uci_c_wlan_configure_band_steering --> function_wlan_uci_c_wlan_uci_ensure_section +``` + +## Caller/callee index + +| Source | Caller | Internal callees | +| --- | --- | --- | +| `src/announce.c:67` | `tlv_append()` | — | +| `src/announce.c:78` | `tlv_str()` | `tlv_append()` | +| `src/announce.c:85` | `put32be()` | — | +| `src/announce.c:94` | `parse_mac()` | — | +| `src/announce.c:102` | `parse_ip()` | — | +| `src/announce.c:110` | `announce_init()` | `tlv_append()`, `tlv_str()`, `parse_mac()`, `parse_ip()` | +| `src/announce.c:233` | `announce_send()` | `put32be()` | +| `src/announce.c:273` | `announce_close()` | — | +| `src/clients.c:45` | `mac_lower()` | — | +| `src/clients.c:55` | `clients_mac_to_ip()` | `mac_lower()` | +| `src/clients.c:86` | `clients_mac_to_hostname()` | `mac_lower()` | +| `src/clients.c:120` | `parse_rate_kbps()` | — | +| `src/clients.c:130` | `clients_read_wifi()` | `clients_mac_to_ip()`, `clients_mac_to_hostname()`, `parse_rate_kbps()` | +| `src/clients.c:247` | `clients_build_sta_table()` | `clients_read_wifi()` | +| `src/config.c:7` | `config_load()` | — | +| `src/crypto.c:13` | `crypto_hex2bin()` | — | +| `src/crypto.c:22` | `crypto_bin2hex()` | — | +| `src/crypto.c:30` | `crypto_random_hex()` | `crypto_bin2hex()` | +| `src/crypto.c:58` | `crypto_encrypt()` | `crypto_hex2bin()` | +| `src/crypto.c:93` | `crypto_decrypt()` | `crypto_hex2bin()` | +| `src/crypto.c:123` | `crypto_gcm_encrypt()` | `crypto_hex2bin()` | +| `src/crypto.c:144` | `crypto_gcm_decrypt()` | `crypto_hex2bin()` | +| `src/http.c:24` | `parse_url()` | — | +| `src/http.c:65` | `http_post()` | `parse_url()` | +| `src/inform/inform.c:26` | `inform_send()` | `http_post()`, `inform_packet_build()`, `inform_packet_parse()`, `inform_build_payload()`, `inform_log_controller_response()`, `inform_handle_response()`, `state_save()` | +| `src/inform/packet.c:26` | `put32be()` | — | +| `src/inform/packet.c:31` | `put16be()` | — | +| `src/inform/packet.c:35` | `get32be()` | — | +| `src/inform/packet.c:40` | `get16be()` | — | +| `src/inform/packet.c:45` | `inform_packet_build()` | `crypto_hex2bin()`, `crypto_random_hex()`, `crypto_encrypt()`, `crypto_gcm_encrypt()`, `put32be()`, `put16be()` | +| `src/inform/packet.c:103` | `inform_packet_parse()` | `crypto_bin2hex()`, `crypto_decrypt()`, `crypto_gcm_decrypt()`, `get32be()`, `get16be()` | +| `src/inform/payload.c:26` | `build_sys_stats()` | `sysinfo_mem()`, `sysinfo_cpu_percent()` | +| `src/inform/payload.c:69` | `build_system_stats()` | — | +| `src/inform/payload.c:91` | `build_if_table()` | `sysinfo_iface()` | +| `src/inform/payload.c:139` | `radio_runtime_iface()` | `wlan_device_for_band()`, `wlan_get_vap_table()` | +| `src/inform/payload.c:162` | `build_scan_table()` | `sysinfo_wifi_scan_cache()` | +| `src/inform/payload.c:191` | `build_athstats()` | — | +| `src/inform/payload.c:220` | `build_radio_table()` | `radio_runtime_iface()`, `build_scan_table()`, `build_athstats()`, `inform_debug_level()` | +| `src/inform/payload.c:296` | `build_radio_table_stats()` | `radio_runtime_iface()`, `sysinfo_radio()` | +| `src/inform/payload.c:373` | `build_port_table()` | `sysinfo_iface()` | +| `src/inform/payload.c:410` | `build_eth_table()` | — | +| `src/inform/payload.c:439` | `build_vap_table()` | `clients_build_sta_table()`, `sysinfo_iface()`, `sysinfo_radio()`, `wlan_device_for_band()`, `wlan_get_vap_table()` | +| `src/inform/payload.c:647` | `collect_sta_table()` | — | +| `src/inform/payload.c:668` | `inform_build_payload()` | `build_sys_stats()`, `build_system_stats()`, `build_if_table()`, `build_radio_table()`, `build_radio_table_stats()`, `build_port_table()`, `build_eth_table()`, `build_vap_table()`, `collect_sta_table()`, `lldp_read_neighbors()` | +| `src/inform/response.c:26` | `inform_valid_auth_key()` | — | +| `src/inform/response.c:38` | `inform_set_debug_level()` | — | +| `src/inform/response.c:43` | `inform_debug_level()` | — | +| `src/inform/response.c:48` | `inform_debug_system_cfg_key()` | — | +| `src/inform/response.c:57` | `inform_log_controller_response()` | `inform_debug_system_cfg_key()` | +| `src/inform/response.c:102` | `reboot_openwrt()` | — | +| `src/inform/response.c:120` | `inform_handle_response()` | `inform_valid_auth_key()`, `reboot_openwrt()`, `state_save()`, `wlan_apply_system_cfg()`, `wlan_apply_config()` | +| `src/lldp.c:75` | `tlv_write()` | — | +| `src/lldp.c:86` | `tlv_str()` | `tlv_write()` | +| `src/lldp.c:94` | `parse_mac()` | — | +| `src/lldp.c:104` | `lldp_send_frame()` | `tlv_write()`, `tlv_str()`, `parse_mac()` | +| `src/lldp.c:193` | `lldp_available()` | — | +| `src/lldp.c:210` | `lldp_read_neighbors()` | `lldp_available()` | +| `src/main.c:36` | `get_mac()` | — | +| `src/main.c:51` | `get_ip()` | — | +| `src/main.c:70` | `get_default_gateway()` | — | +| `src/main.c:116` | `main()` | `announce_init()`, `announce_send()`, `announce_close()`, `config_load()`, `inform_send()`, `inform_set_debug_level()`, `lldp_send_frame()`, `lldp_available()`, `get_mac()`, `get_ip()`, `get_default_gateway()`, `ufmodel_find()`, `state_load()`, `state_save()` | +| `src/models.c:179` | `ufmodel_find()` | — | +| `src/state.c:16` | `state_defaults()` | — | +| `src/state.c:27` | `state_load()` | `state_defaults()` | +| `src/state.c:102` | `state_save()` | — | +| `src/sysinfo.c:53` | `sysinfo_mem()` | — | +| `src/sysinfo.c:81` | `read_cpu()` | — | +| `src/sysinfo.c:92` | `sysinfo_cpu_percent()` | `read_cpu()` | +| `src/sysinfo.c:115` | `read_sysfs_str()` | — | +| `src/sysinfo.c:130` | `read_sysfs_int()` | `read_sysfs_str()` | +| `src/sysinfo.c:137` | `read_ip_ioctl()` | — | +| `src/sysinfo.c:151` | `sysinfo_iface()` | `read_sysfs_str()`, `read_sysfs_int()`, `read_ip_ioctl()` | +| `src/sysinfo.c:238` | `utilization_percent()` | — | +| `src/sysinfo.c:247` | `count_antenna_chains()` | — | +| `src/sysinfo.c:277` | `sysinfo_radio()` | `utilization_percent()`, `count_antenna_chains()` | +| `src/sysinfo.c:486` | `frequency_to_channel()` | — | +| `src/sysinfo.c:498` | `sysinfo_wifi_scan_cache()` | `frequency_to_channel()` | +| `src/wlan/common.c:20` | `wlan_security_to_uci()` | — | +| `src/wlan/common.c:34` | `wlan_security_to_unifi()` | — | +| `src/wlan/common.c:48` | `wlan_valid_object_id()` | — | +| `src/wlan/common.c:65` | `wlan_ensure_vap_ids()` | `crypto_random_hex()`, `wlan_valid_object_id()` | +| `src/wlan/common.c:157` | `wlan_mobility_domain_for_ssid()` | — | +| `src/wlan/common.c:169` | `wlan_radio_uses_ath9k()` | — | +| `src/wlan/common.c:187` | `wlan_json_boolean_any()` | — | +| `src/wlan/common.c:209` | `wlan_feature_enabled()` | — | +| `src/wlan/common.c:217` | `wlan_safe_section_name()` | — | +| `src/wlan/legacy.c:20` | `system_cfg_get()` | — | +| `src/wlan/legacy.c:44` | `wlan_apply_system_cfg()` | `wlan_valid_object_id()`, `wlan_feature_enabled()`, `system_cfg_get()`, `wlan_apply_config()` | +| `src/wlan/provision.c:20` | `apply_vap()` | `wlan_security_to_uci()`, `wlan_valid_object_id()`, `wlan_mobility_domain_for_ssid()`, `wlan_radio_uses_ath9k()`, `wlan_json_boolean_any()`, `wlan_safe_section_name()`, `wlan_uci_set_required()`, `wlan_uci_add_list()`, `wlan_uci_ensure_section()`, `wlan_ensure_vlan_network()` | +| `src/wlan/provision.c:291` | `force_wifi4_for_band()` | `wlan_json_boolean_any()` | +| `src/wlan/provision.c:335` | `wlan_apply_config()` | `wlan_ensure_vap_ids()`, `wlan_json_boolean_any()`, `apply_vap()`, `force_wifi4_for_band()`, `wlan_device_for_band()`, `wlan_apply_radio()`, `wlan_configure_band_steering()`, `wlan_clear()` | +| `src/wlan/radio.c:29` | `band_bit()` | — | +| `src/wlan/radio.c:38` | `bit_count()` | — | +| `src/wlan/radio.c:50` | `detect_radio_bands()` | — | +| `src/wlan/radio.c:85` | `resolve_radio_map()` | `band_bit()`, `bit_count()`, `detect_radio_bands()` | +| `src/wlan/radio.c:135` | `wlan_device_for_band()` | `resolve_radio_map()` | +| `src/wlan/radio.c:146` | `wlan_band_for_device()` | `resolve_radio_map()` | +| `src/wlan/radio.c:162` | `radio_max_standard()` | — | +| `src/wlan/radio.c:195` | `select_htmode()` | `radio_max_standard()` | +| `src/wlan/radio.c:241` | `wlan_apply_radio()` | `select_htmode()` | +| `src/wlan/telemetry.c:25` | `find_runtime_vap()` | — | +| `src/wlan/telemetry.c:58` | `wlan_get_vap_table()` | `wlan_security_to_unifi()`, `wlan_valid_object_id()`, `wlan_band_for_device()`, `find_runtime_vap()` | +| `src/wlan/uci.c:21` | `wlan_uci_set()` | — | +| `src/wlan/uci.c:36` | `wlan_uci_set_required()` | `wlan_uci_set()` | +| `src/wlan/uci.c:56` | `wlan_uci_add_list()` | — | +| `src/wlan/uci.c:72` | `wlan_uci_ensure_section()` | — | +| `src/wlan/uci.c:100` | `find_vlan_uplink()` | — | +| `src/wlan/uci.c:143` | `wlan_ensure_vlan_network()` | `wlan_uci_add_list()`, `wlan_uci_ensure_section()`, `find_vlan_uplink()` | +| `src/wlan/uci.c:208` | `wlan_configure_band_steering()` | `wlan_uci_ensure_section()` | +| `src/wlan/uci.c:268` | `wlan_clear()` | — | diff --git a/Developer-Guide.md b/Developer-Guide.md new file mode 100644 index 0000000..311ef2d --- /dev/null +++ b/Developer-Guide.md @@ -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. diff --git a/Home.md b/Home.md new file mode 100644 index 0000000..1e77b19 --- /dev/null +++ b/Home.md @@ -0,0 +1,13 @@ +# openUF Developer Wiki + +This Wiki is generated from the current source tree and maintained in the main +repository so architecture documentation changes can be reviewed with code. + +- [[Developer Guide|Developer-Guide]] — architecture, invariants, extension + points, build validation, and Wiki publishing. +- [[Runtime Flow|Runtime-Flow]] — lifecycle, inform, response, and Wi-Fi + provisioning flow charts. +- [[Function Call Graph|Call-Graph]] — generated internal caller/callee graph + and searchable function table. + +Run `./scripts/docs/generate-wiki.py --check` to verify these pages are current. diff --git a/Runtime-Flow.md b/Runtime-Flow.md new file mode 100644 index 0000000..0f82a57 --- /dev/null +++ b/Runtime-Flow.md @@ -0,0 +1,76 @@ +# Runtime Flow + +The flow is generated alongside the call graph. Function names are validated +against the current C sources so renamed or removed stages fail documentation +checks. + +## Daemon scheduler + +```mermaid +flowchart TD + start([main]) --> config[config_load] + config --> state[state_load] + state --> model[ufmodel_find] + model --> identity[Read LAN MAC, IP, and default gateway] + identity --> persist[state_save] + persist --> announceInit[announce_init when enabled] + announceInit --> loop{One-second main loop} + loop -->|announce due| announce[announce_send] + announce --> loop + loop -->|LLDP due| ports{For every model port} + ports --> lldp[lldp_send_frame] + lldp --> loop + loop -->|inform due| refresh[Refresh controller URL and device IP] + refresh --> inform[inform_send] + inform --> loop + loop -->|nothing due| sleep[sleep 1 second] + sleep --> loop +``` + +## Inform exchange + +```mermaid +flowchart TD + send([inform_send]) --> url{inform URL available?} + url -->|no| error[Return an error] + url -->|yes| key{Device adopted?} + key -->|no| defaultKey[Use DEFAULT_AUTH_KEY] + key -->|yes| stateKey[Use persisted device key] + defaultKey --> payload[inform_build_payload] + stateKey --> payload + payload --> packet[inform_packet_build] + packet --> post[http_post] + post --> status{HTTP 200?} + status -->|no, first attempt| retry[Retry with alternate CBC or GCM cipher] + retry --> packet + status -->|no, final attempt| error + status -->|yes| decode[inform_packet_parse] + decode --> json[Parse controller JSON] + json --> handle[inform_handle_response] +``` + +## Controller response and provisioning + +```mermaid +flowchart TD + response([inform_handle_response]) --> type{_type} + type -->|noop| done[No state change] + type -->|upgrade| version[Persist requested firmware version] + type -->|reboot or reset| reboot[reboot_openwrt] + type -->|cmd adopt| adopt[Persist key, URL, and adopted state] + type -->|setparam| params[Parse management parameters] + params --> legacy{system_cfg present?} + legacy -->|yes| legacyApply[wlan_apply_system_cfg] + legacyApply --> normalize[Build radio_table and vap_table JSON] + normalize --> apply[wlan_apply_config] + type -->|setstate| apply + apply --> ids[wlan_ensure_vap_ids] + ids --> clear[wlan_clear managed openuf_ VAPs] + clear --> radios[wlan_apply_radio for each band] + radios --> vaps[Create controller VAP sections] + vaps --> commit[Commit UCI and configure usteer] + commit --> start[Start and verify radios sequentially] + start --> result{Apply succeeded?} + result -->|yes| saved[Save cfgversion and config schema] + result -->|no| retryConfig[Reset cfgversion to 0] +``` diff --git a/TESTNG.md b/TESTNG.md deleted file mode 100644 index 5d08b7b..0000000 --- a/TESTNG.md +++ /dev/null @@ -1 +0,0 @@ -Welcome to the Wiki. \ No newline at end of file diff --git a/_Sidebar.md b/_Sidebar.md new file mode 100644 index 0000000..8a9ac4c --- /dev/null +++ b/_Sidebar.md @@ -0,0 +1,4 @@ +- [[Home]] +- [[Developer Guide|Developer-Guide]] +- [[Runtime Flow|Runtime-Flow]] +- [[Function Call Graph|Call-Graph]]