Files
claudetools/.claude/skills/unifi-wifi/references/interference-model.md
Mike Swanson ca548687e7 sync: auto-sync from GURU-5070 at 2026-06-15 18:24:52
Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-06-15 18:24:52
2026-06-15 18:25:08 -07:00

7.0 KiB
Raw Blame History

AP interference / airtime-reduction model — design + data

Goal (per Mike): a fleet/site-level model that decides which AP radios to disable, and where to reduce power, to cut total airtime contention while preserving client coverage. Per AP per radio, all bands (not 2.4-only, not per-client). Inputs: each AP's neighbor/overlap relationships

  • historical client connections + airtime.

Data — it's ALL in the controller (corrected 2026-06-15)

First pass only checked the ace DB (config/current state) and wrongly concluded the history "isn't there." It is — in ace_stat (1.5 GB of accumulated time-series) and the wifi_connectivity_event collection. No external collector is needed; the controller already retains it. Three databases on the UOS Mongo (port 27117):

DB Holds Use
ace config + current state radio_table (channel/band/width/power/min_rssi), rogue (FOREIGN interference), channelplan, device/floorplan
ace_stat time-series history the model's airtime + client history (below)
ace_audit audit log

ace_stat.stat_hourly / stat_daily (o:'ap') — per-AP per-band airtime history

Flat per-band fields (ng=2.4, na=5, 6e=6): <band>-cu_total (channel utilization %), <band>-cu_interf (airtime lost to interference %), <band>-cu_self_rx/tx, <band>-num_sta, <band>-satisfaction, <band>-tx_retries. Plus ap (AP mac), site_id, time (ms epoch). This is the historical airtime/interference/load profile per AP per band — the core "who's contending" signal. (Also o:'user' per-client retries/anomalies; o:'site' rollups.)

ace_stat.wifi_connectivity_event — the roam graph (empirical AP adjacency)

Each doc: from_endpoint{mac(AP), channel, channel_width, band, rssi}, to_endpoint{mac(AP), ...}, client_mac, successful, time, _class:WIFI_ROAMING. Every roam is an edge between two APs a real client handed off between → empirical coverage overlap/adjacency, weighted by volume, with the handoff RSSI (coverage quality). This is the "historical connections → which APs cover the same space" signal, and it's better than a raw RF scan because it reflects where clients actually move.

Still useful from ace / setup

  • rogue aggregate = FOREIGN co-channel interference per channel (Plane-1 audit).
  • Floorplan coords: not set today (0/77 APs placed). Mike is willing to use the floorplan feature → once APs are placed, device x/y gives true physical distance for adjacency edges (complements the roam graph, esp. for APs that rarely roam-share).
  • Live Network API (stat/device/stat/sta) still adds current utilization + the AP's live RF-neighbor table; nice-to-have for before/after validation, not required to build the model.

Model

Per band b, over a history window (default 7d):

  • Per-radio airtime: avg cu_total, avg cu_interf, avg num_sta from stat_hourly.
  • Overlap/redundancy: roam volume per AP and per AP-pair from wifi_connectivity_event (high roam-share to neighbors ⇒ a client leaving this radio has somewhere to land ⇒ redundant).
  • Score (v1, model-rank.sh): (cu_total + cu_interf) * log(1+roams) / (clients+1) — high = this radio burns airtime in a contended band AND its clients are mobile/redundant ⇒ shrink or disable. Hint: DISABLE when high roam + near-zero clients; POWER-DOWN when busy but holds some unique load.
  • v2 (greedy, coverage-safe): iteratively disable the top candidate, recompute overlap so we never open a hole (stop when a radio's clients would lose their only good-RSSI neighbor), and add floorplan-distance edges once APs are placed. Output = ranked per-AP-per-radio actions with the metric that justified each, applied per zone with before/after validation.

v1 result (Cascades 2.4GHz, 7d) — the smoking gun

model-rank.sh cascades 7 ng: 2.4 radios run cu_total 7494%, cu_interf 6181%, ~0.32.6 clients each across 75 APs. Translation: 2.4 is saturated and mostly interference, serving almost no one — a textbook case to disable 2.4 on most APs and power down the rest. Run na/6e for the 5/6GHz picture (expected: keep, with 6GHz the clean capacity band).

Materials matter — and why the roam graph already handles them

Cascades has reinforced-concrete + steel-sheet walls across the hallways that kill signal on all bands (rooms either side of a hall, and floor-to-floor, behave normally; across a hall is nearly opaque). This is why geometric distance must never be the redundancy signal on its own: two APs on opposite sides of a hall are close but RF-isolated. The roam graph is materials-aware by construction — clients can't roam across the steel wall, so those APs simply never appear as neighbors, and the model won't call them redundant. Corollaries baked into the design:

  • Distance/floorplan (once APs are placed) is only a prior; an AP pair counts as redundant only with RF/roam evidence (bidirectional roams at adequate p25 RSSI). Never disable on proximity alone.
  • AP room parity (odd/even) ≈ hallway side at Cascades — a useful prior to avoid pairing across-hall APs.
  • The live AP-to-AP RF neighbor table (API wireup) directly measures this attenuation — the gold standard for the coverage graph, and the reason it's worth wiring.

Hardening from the multi-model review (Grok + Gemini)

Applied: bidirectional roam requirement (not one-way "escape"); band-specific p25 RSSI bars (2.4 68 / 5 72 / 6 75); load-shift simulation (only disable if a strong neighbor stays < 85% after absorbing the cu_self it inherits — avoids "capacity cascades"); benefit = cu_interf (+ a normalized tx_retries thrash term), with cu_self treated as transfer cost; 40%/zone disable cap; stepwise output (power-down → observe → disable). tx_retries is a raw count → normalized by wifi_tx_attempts.

Key empirical finding (Cascades): power-down now, disable later

The airtime data is rich and unambiguousoptimize-radios.sh cascades ng recommends power-down on 74/75 2.4 radios (all 7494% utilized, 6181% interference, ~1 client — the safe big win; power-down keeps the BSSID). But the roam data is too sparse to prove coverage redundancy for disables (almost no AP has a strong bidirectional roam-neighbor), so the optimizer correctly recommends 0 disables until coverage evidence exists. That evidence is exactly the live AP-to-AP RF neighbor tablethe API wireup is the enabler for confident radio disables (and for before/after validation). So the rollout is: Phase A power-down (now) → Phase B re-measure (live API) → Phase C disable the radios the RF table proves redundant.

Status

  • scripts/audit-site.sh — config + foreign-interference audit (Plane 1).
  • scripts/model-rank.shv1 airtime-reduction ranker from real history (this doc). Works now.
  • Next: v2 greedy coverage-safe optimizer + floorplan-distance edges (after APs are placed on the floorplan) + optional live-API before/after validation.