sync: auto-sync from HOWARD-HOME at 2026-06-18 18:35:03

Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-18 18:35:03
This commit is contained in:
2026-06-18 18:35:12 -07:00
parent 5beb322ac2
commit 347980a245
3 changed files with 111 additions and 4 deletions

View File

@@ -85,12 +85,20 @@ expect retry back down from ~23% and satisfaction recovering.
for z in "Floor 3" "Floor 1" "Floor 2" "Floor 4"; do \
apply-radio.sh cascades na width 40 --zone "$z" --apply; done # rollback: na width 80
```
**3b. Channel plan** (decision: INCLUDE clean-DFS for diversity vs non-DFS-only for resilience — DFS is
empirically clean here, 0 radar):
**3b. Channel plan — NON-DFS ONLY (decided 2026-06-18 after rigorous DFS verification).**
Use **UNII-1 (3648) + UNII-3 (149165) only**; do NOT use DFS channels (52144) on this voice-critical
network. A precise radar-detection sweep (real `radar found`/`NOL` signatures, CAC/control housekeeping
excluded) found **ZERO genuine hits across all 53 DFS APs** — BUT the window was only ~2123h (APs rebooted
~23h ago, the 6/17 outage). Near Davis-Monthan AFB + TUS (~10 mi), military radar is sporadic and a single
hit forces a 30-min channel vacate = **dropped calls** — unacceptable for voice. **Resilience > diversity.**
The lost 5 GHz channel count is covered by **6 GHz (Phase 2a) absorbing capacity** — this is WHY 6 GHz comes first.
```
SURVEY=.claude/tmp/cascades-survey.json; SURVEY_JSON=$SURVEY survey-collect.sh cascades
SURVEY_JSON=$SURVEY channel-plan.sh cascades na # dry-run; review; apply per zone w/ validation
SURVEY_JSON=$SURVEY channel-plan.sh cascades na # dry-run; CONSTRAIN to non-DFS (36-48,149-165); review; apply per zone
```
**Periodic DFS monitoring:** the ~1-day window isn't conclusive, so add a recurring precise `dfs-check.sh`
(fold into the network-logging plan). Staying on non-DFS means a future hit can't affect us; the monitor just
confirms the choice stays right.
**3c. Relieve AP 103 specifically** (it now carries Lauren + 11 others on a 75%-busy ch149): move it off 149 to
a clean channel from the plan, 40 MHz. Verify Lauren `.202` retry drops after.
**Gate:** 5 GHz retry down on the busy APs; AP 103 cu_total well under 50%; no client stranded.
@@ -134,7 +142,7 @@ a clean channel from the plan, 40 MHz. Verify Lauren `.202` retry drops after.
- The 6 straggler phones — Howard re-keying separately; they'll benefit from the RF work regardless.
## 7. Open decisions for Howard
1. **5 GHz channel plan:** include clean-DFS (more diversity, tiny resilience risk) vs non-DFS-only (max resilience, more co-channel)? Recommendation: include clean-DFS.
1. ~~**5 GHz channel plan:** clean-DFS vs non-DFS-only~~**RESOLVED 2026-06-18: NON-DFS ONLY** (UNII-1 3648 + UNII-3 149165). DFS sweep was clean but only a ~1-day window near Davis-Monthan/TUS; a radar vacate = dropped calls, so resilience wins. 6 GHz covers the capacity gap. (See Phase 3b.)
2. **QoS depth:** UniFi WMM + DSCP-honor only, or also a pfSense WAN priority queue/limiter for RTP? Recommendation: both (additive).
3. **802.11r** on CSCNet: enable for seamless voice roaming, or k/v only (safer for mixed phones)? Recommendation: k/v now, test r on one phone first.
4. Tonight's stopping point: Phases 12 alone are a legitimate, lower-risk night; 34 can be a second night.

View File

@@ -0,0 +1,97 @@
# Cascades — Phase 1: Voice QoS Design (VLAN 30)
- **Created:** 2026-06-18 (Howard-Home / claude-main). Part of `network-optimization-master-plan.md` Phase 1.
- **Status:** DESIGN — for review, then build (Howard drives pfSense GUI). Nothing applied.
- **Risk:** LOW — additive, voice-only prioritization; rollback = disable the shaper. Main caution: size the
shaper bandwidth correctly (a wrong value can throttle throughput) → test before/after.
## Objective
Guarantee voice quality under load by prioritizing VLAN 30 traffic end-to-end. **The phones register to a
CLOUD PBX (Vertical) over the internet**, so the bottleneck that breaks calls is **WAN upload saturation**
(someone uploading / cloud backup / OneDrive sync fills the uplink → voice RTP queues → jitter, dropped
audio). QoS keeps voice ahead of bulk data on the WAN.
## The big advantage of the VLAN move
**All voice is now one subnet: `10.0.30.0/24`.** So QoS can match *all* voice by **source subnet** — no
need to guess SIP/RTP port ranges per PBX. This is the cleanest, most robust match criterion and it only
became possible because we isolated voice onto VLAN 30.
## Current state (verified 2026-06-18)
- **No traffic shaper / limiter configured** on pfSense (clean build).
- **Dual-WAN:** WAN1 `igc0` (Cox Fiber, primary, 1G link), WAN2 `igc3` (Cox Coax, 2.5G link); `WAN_Group`
failover (`downlosslatency`). Shaping must be applied on **both** WAN interfaces.
- pfSense Plus 25.07 (ALTQ shaper + dummynet limiters available).
## Three layers (in priority order)
### Layer 1 — pfSense WAN shaper (PRIMARY — this is where calls break)
**Type: HFSC** (hierarchical, lets us guarantee voice a floor while letting it borrow idle bandwidth).
Per WAN interface, three queues:
| Queue | Role | HFSC settings (starting point) |
|---|---|---|
| `qVoice` | voice (VLAN 30 / DSCP EF) | **priority 7**, realtime ~30% of WAN-up, link-share 30%, NOT default |
| `qACK` | TCP ACKs (keeps downloads snappy) | priority 6, ~10% |
| `qDefault` | everything else | **default**, link-share ~60% |
**Match rule (floating, WAN, direction out):** source `10.0.30.0/24``qVoice`. (Optionally also match
DSCP EF if phones mark it — see Layer 4.) One floating rule per WAN, or interface = WAN_Group.
**Download side:** RTP from the PBX *to* the phones is shaped on the **LAN-side** queues. The wizard builds
both directions; if hand-building, mirror a `qVoice` on the internal interfaces too. Upload is the more
critical direction for cloud-PBX voice, but do both.
**Build path (GUI — Howard drives):**
- Easiest: **Firewall → Traffic Shaper → Wizard → "Multiple Lan/Wan"** — set #WAN=2, #LAN as needed,
enter each WAN's bandwidth (below), on the VoIP page choose **"prioritize by address" = `10.0.30.0/24`**
with a guaranteed %; the wizard generates HFSC queues + the float rules. Then tune.
- Or manual: Firewall → Traffic Shaper → By Interface → add HFSC on WAN1 + WAN2, create the 3 queues,
then Firewall → Rules → Floating → match `10.0.30.0/24` out → Ackqueue/Queue = qACK/qVoice.
> **INPUT NEEDED (the one missing number):** the **Cox plan UPLOAD speed** for WAN1 (fiber) and WAN2 (coax).
> Shape `qVoice`'s parent to ~**9095% of actual upload** so the queue forms in pfSense (where we control
> priority), not at the ISP. The physical link is 1G/2.5G but the *plan* upload is what to shape to — get it
> from the Cox bill / a speedtest from a LAN host. Without it the shaper can't be sized correctly.
### Layer 2 — UniFi WMM (the WiFi phones — Poly)
Over the air, **WMM** maps DSCP → WiFi access categories; voice (DSCP EF/46) → **WMM Voice AC** (gets TXOP
priority over data). WMM is ON by default on UniFi — **verify it's enabled on CSCNet** and that the U7 APs
honor DSCP→WMM. This is what protects the 22 Poly phones over the air during WiFi congestion. (Ties into the
RF work — a clean 5/6 GHz + WMM = good wireless voice.)
### Layer 3 — UniFi switch QoS (the wired AudioCodes)
UniFi switches honor 802.1p/DSCP and queue tagged voice to a high-priority egress queue — mostly automatic
once the phones mark DSCP. LAN links are gig and rarely congested, so this is the least critical layer, but
confirm the USW isn't stripping DSCP and that voice VLAN 30 frames get the priority queue.
### Layer 4 — DSCP marking (make the above reliable)
- **Verify the phones mark voice:** AudioCodes + Poly typically tag RTP **EF (46)** and signaling **CS3 (24)**
by default, often set via the PBX/provisioning. Confirm with Vertical (Richard) or capture a packet.
- **If they DON'T mark (or inconsistently):** add a pfSense floating rule that **SETS DSCP EF** on
`10.0.30.0/24` traffic (Advanced → "Match/Set DSCP"). Then Layer 1/2/3 can all match on EF too.
- **Match-by-subnet (Layer 1) works regardless of DSCP** — it's the safety net. DSCP makes WMM (Layer 2)
and switch QoS (Layer 3) automatic.
## Implementation order
1. Get the Cox WAN upload numbers (blocker for Layer 1 sizing).
2. Confirm phones mark DSCP EF (Vertical) — decides whether we add the pfSense set-DSCP rule.
3. Build Layer 1 (pfSense HFSC + float rule) — dry-run mindset: set it, then validate.
4. Verify Layer 2 (WMM on CSCNet) + Layer 3 (switch honoring DSCP).
5. Validate (below). Tune `qVoice` % if needed.
## Validation (prove it works)
- **Baseline:** from a LAN host, saturate the WAN upload (big upload / `iperf3 -u` / speedtest) WHILE on a
call from a voice phone — note the breakup *without* QoS.
- **After:** repeat the same saturation; call stays clean. Check Firewall → Traffic Shaper → Queues: `qVoice`
carrying voice with ~0 drops while `qDefault` absorbs the saturation + drops.
- Confirm both WANs (test on primary; fail to WAN2 and re-test).
## Rollback
Firewall → Traffic Shaper → disable/remove the shaper; delete the floating rule. Zero residual effect
(QoS only orders packets under congestion; removing it reverts to FIFO). The set-DSCP rule (if added) can stay
or go independently.
## Notes / interplay with the rest of the plan
- QoS is **independent of the RF work** — it helps wired + WiFi voice immediately and can be built tonight
regardless of the 2.4/5/6 GHz changes.
- It does NOT fix RF problems (a phone on a 50%-retry 2.4 GHz radio still suffers) — QoS handles *congestion/
contention for bandwidth*, RF tuning handles *the air*. Both are needed; they're complementary.

View File

@@ -17,6 +17,8 @@ Categories (the `[type]` tag): _(none)_ = skill/command execution failure ·
<!-- Append entries below this line -->
2026-06-19 | Howard-Home | git/sync-temp-files | [friction] RECURRED (3rd time): .fleet325.dev controller-scratch swept into commit by git add -A; my earlier fix only ignored specific names (.sta/.dev/.q*), missed .fleet*. Real fix: write API scratch OUTSIDE the repo (e.g. $TMPDIR), not CWD-relative dotfiles [ctx: ref=git/sync-temp-files prior entry; recurring]
2026-06-18 | GURU-5070 | agy/search | gemini CLI threw ineligible/projectId setup error (throwIneligibleOrProjectIdError), empty response after 3 attempts [ctx: mode=search host=GURU-5070]
2026-06-18 | GURU-5070 | agy | gemini returned no response (empty after 3 attempts) [ctx: mode=search err= at process.processTicksAndRejections (node:internal/process/task_queues:104:]