mirror of
https://github.com/ruvnet/RuView
synced 2026-08-05 19:41:44 +00:00
feat(firmware): --channel and --filter-mac provisioning (ADR-060)
- provision.py: add --channel (CSI channel override) and --filter-mac (AA:BB:CC:DD:EE:FF format) arguments with validation - nvs_config: add csi_channel, filter_mac[6], filter_mac_set fields; read from NVS on boot - csi_collector: auto-detect AP channel when no NVS override is set; filter CSI frames by source MAC when filter_mac is configured - ADR-060 documents the design and rationale Fixes #247, fixes #229
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "csi_collector.h"
|
||||
#include "nvs_config.h"
|
||||
#include "stream_sender.h"
|
||||
#include "edge_processing.h"
|
||||
|
||||
@@ -21,6 +22,9 @@
|
||||
#include "esp_timer.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* ADR-060: Access the global NVS config for MAC filter and channel override. */
|
||||
extern nvs_config_t g_nvs_config;
|
||||
|
||||
/* ADR-057: Build-time guard — fail early if CSI is not enabled in sdkconfig.
|
||||
* Without this, the firmware compiles but crashes at runtime with:
|
||||
* "E (xxxx) wifi:CSI not enabled in menuconfig!"
|
||||
@@ -151,6 +155,14 @@ size_t csi_serialize_frame(const wifi_csi_info_t *info, uint8_t *buf, size_t buf
|
||||
static void wifi_csi_callback(void *ctx, wifi_csi_info_t *info)
|
||||
{
|
||||
(void)ctx;
|
||||
|
||||
/* ADR-060: MAC address filtering — drop frames from non-matching sources. */
|
||||
if (g_nvs_config.filter_mac_set) {
|
||||
if (memcmp(info->mac, g_nvs_config.filter_mac, 6) != 0) {
|
||||
return; /* Source MAC doesn't match filter — skip frame. */
|
||||
}
|
||||
}
|
||||
|
||||
s_cb_count++;
|
||||
|
||||
if (s_cb_count <= 3 || (s_cb_count % 100) == 0) {
|
||||
@@ -203,6 +215,29 @@ static void wifi_promiscuous_cb(void *buf, wifi_promiscuous_pkt_type_t type)
|
||||
|
||||
void csi_collector_init(void)
|
||||
{
|
||||
/* ADR-060: Determine the CSI channel.
|
||||
* Priority: 1) NVS override (--channel), 2) connected AP channel, 3) Kconfig default. */
|
||||
uint8_t csi_channel = (uint8_t)CONFIG_CSI_WIFI_CHANNEL;
|
||||
|
||||
if (g_nvs_config.csi_channel > 0) {
|
||||
/* Explicit NVS override via provision.py --channel */
|
||||
csi_channel = g_nvs_config.csi_channel;
|
||||
ESP_LOGI(TAG, "Using NVS channel override: %u", (unsigned)csi_channel);
|
||||
} else {
|
||||
/* Auto-detect from connected AP */
|
||||
wifi_ap_record_t ap_info;
|
||||
if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK && ap_info.primary > 0) {
|
||||
csi_channel = ap_info.primary;
|
||||
ESP_LOGI(TAG, "Auto-detected AP channel: %u", (unsigned)csi_channel);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Could not detect AP channel, using Kconfig default: %u",
|
||||
(unsigned)csi_channel);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the hop table's first channel to match. */
|
||||
s_hop_channels[0] = csi_channel;
|
||||
|
||||
/* Enable promiscuous mode — required for reliable CSI callbacks.
|
||||
* Without this, CSI only fires on frames destined to this station,
|
||||
* which may be very infrequent on a quiet network. */
|
||||
@@ -230,8 +265,15 @@ void csi_collector_init(void)
|
||||
ESP_ERROR_CHECK(esp_wifi_set_csi_rx_cb(wifi_csi_callback, NULL));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_csi(true));
|
||||
|
||||
ESP_LOGI(TAG, "CSI collection initialized (node_id=%d, channel=%d)",
|
||||
CONFIG_CSI_NODE_ID, CONFIG_CSI_WIFI_CHANNEL);
|
||||
if (g_nvs_config.filter_mac_set) {
|
||||
ESP_LOGI(TAG, "MAC filter active: %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
g_nvs_config.filter_mac[0], g_nvs_config.filter_mac[1],
|
||||
g_nvs_config.filter_mac[2], g_nvs_config.filter_mac[3],
|
||||
g_nvs_config.filter_mac[4], g_nvs_config.filter_mac[5]);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "CSI collection initialized (node_id=%d, channel=%u)",
|
||||
CONFIG_CSI_NODE_ID, (unsigned)csi_channel);
|
||||
}
|
||||
|
||||
/* ---- ADR-029: Channel hopping ---- */
|
||||
|
||||
@@ -91,6 +91,11 @@ void nvs_config_load(nvs_config_t *cfg)
|
||||
cfg->wasm_verify = 0; /* Kconfig disabled signature verification. */
|
||||
#endif
|
||||
|
||||
/* ADR-060: Channel override and MAC filter defaults. */
|
||||
cfg->csi_channel = 0; /* 0 = auto-detect from connected AP. */
|
||||
cfg->filter_mac_set = 0;
|
||||
memset(cfg->filter_mac, 0, 6);
|
||||
|
||||
/* Try to override from NVS */
|
||||
nvs_handle_t handle;
|
||||
esp_err_t err = nvs_open("csi_cfg", NVS_READONLY, &handle);
|
||||
@@ -277,6 +282,26 @@ void nvs_config_load(nvs_config_t *cfg)
|
||||
ESP_LOGW(TAG, "wasm_verify=1 but no wasm_pubkey in NVS — uploads will be rejected");
|
||||
}
|
||||
|
||||
/* ADR-060: CSI channel override. */
|
||||
uint8_t csi_ch_val;
|
||||
if (nvs_get_u8(handle, "csi_channel", &csi_ch_val) == ESP_OK) {
|
||||
if ((csi_ch_val >= 1 && csi_ch_val <= 14) || (csi_ch_val >= 36 && csi_ch_val <= 177)) {
|
||||
cfg->csi_channel = csi_ch_val;
|
||||
ESP_LOGI(TAG, "NVS override: csi_channel=%u", (unsigned)cfg->csi_channel);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "NVS csi_channel=%u invalid, ignored", (unsigned)csi_ch_val);
|
||||
}
|
||||
}
|
||||
|
||||
/* ADR-060: MAC address filter (6-byte blob). */
|
||||
size_t mac_len = 6;
|
||||
if (nvs_get_blob(handle, "filter_mac", cfg->filter_mac, &mac_len) == ESP_OK && mac_len == 6) {
|
||||
cfg->filter_mac_set = 1;
|
||||
ESP_LOGI(TAG, "NVS override: filter_mac=%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
cfg->filter_mac[0], cfg->filter_mac[1], cfg->filter_mac[2],
|
||||
cfg->filter_mac[3], cfg->filter_mac[4], cfg->filter_mac[5]);
|
||||
}
|
||||
|
||||
/* Validate tdm_slot_index < tdm_node_count */
|
||||
if (cfg->tdm_slot_index >= cfg->tdm_node_count) {
|
||||
ESP_LOGW(TAG, "tdm_slot_index=%u >= tdm_node_count=%u, clamping to 0",
|
||||
|
||||
@@ -50,6 +50,11 @@ typedef struct {
|
||||
uint8_t wasm_verify; /**< Require Ed25519 signature for uploads. */
|
||||
uint8_t wasm_pubkey[32]; /**< Ed25519 public key for WASM signature. */
|
||||
uint8_t wasm_pubkey_valid; /**< 1 if pubkey was loaded from NVS. */
|
||||
|
||||
/* ADR-060: Channel override and MAC address filtering */
|
||||
uint8_t csi_channel; /**< Explicit CSI channel override (0 = auto-detect). */
|
||||
uint8_t filter_mac[6]; /**< MAC address to filter CSI frames. */
|
||||
uint8_t filter_mac_set; /**< 1 if filter_mac was loaded from NVS. */
|
||||
} nvs_config_t;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user