7.0 KiB
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
rogueaggregate = 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,
devicex/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, avgcu_interf, avgnum_stafromstat_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 74–94%, cu_interf 61–81%, ~0.3–2.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 unambiguous → optimize-radios.sh cascades ng recommends
power-down on 74/75 2.4 radios (all 74–94% utilized, 61–81% 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 table → the 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.sh— v1 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.