# Channel Planning

The Multi-AP EasyMesh Controller manages channels across all nodes using intelligent Automatic Channel Selection (ACS) and background Channel Availability Check (CAC) for DFS channels.

## Overview

The controller makes channel decisions based on operating class (opclass) preferences reported by each node, which include:
- **Busy factor** - Channel utilization from survey data (OBSS interference)
- **Noise level** - ANPI (Average Noise Plus Interference) measurements  
- **BSS number** - Number of nearby access points
- **Maximum TX power** - Regulatory and hardware limitations
- **DFS status** - Channel availability state (usable/available/NOP)

The controller proactively pre-clears DFS channels using background CAC and selects optimal channels based on real-time metrics. This eliminates the need for local ACS on individual nodes, allowing fast startup on non-DFS channels while background processes optimize channel usage.

## Key Features

### Intelligent Channel Selection
- **Preference-based scoring** - Channels rated 0-15 with higher scores preferred
- **Random selection from best candidates** - Prevents all nodes switching to identical channels
- **Bandwidth optimization** - Supports 20/40/80/160/320 MHz channel widths
- **DFS awareness** - Integrates CAC status into selection logic

### Real-time Monitoring
- **EWMA (Exponentially Weighted Moving Average)** metrics tracking
- **300-second sampling intervals** for trend detection
- **Automatic recalculation triggers**:
  - OBSS busy factor increase > 30 units
  - ANPI noise level increase > 20 units (≈0.5 dBm)
  - DFS channel becomes available (CAC completion)

### Backhaul-aware Operation
- **bSTA detection** - Skips channel switching for nodes with active wireless backhaul
- **Topology awareness** - Leaf nodes follow parent channel assignments

## Config options (main options):
    config channel_plan
            option preclear_dfs '1'
            option acs '1'


### Background CAC Support
**`preclear_dfs`** - Enable background Channel Availability Check cleaning

When a node supports background CAC (reported in radio CAC capability), the controller:
1. **Scans for usable DFS channels** - Identifies channels requiring CAC 
2. **Selects CAC method** - Chooses from available methods:
   - `MIMO_REDUCED` - MIMO dimension reduced CAC
   - `DEDICATED` - Dedicated radio CAC  
   - `TIME_SLICED` - Time-sliced CAC
3. **Monitors CAC progress** - Tracks channel state transitions:
   - `USABLE` → `CAC` (ongoing) → `AVAILABLE` (cleared) or `NOP` (radar detected)
4. **Prevents interference** - Ensures no AP interfaces conflict during CAC
5. **Triggers ACS recalc** - Automatically reconsiders channel selection when new channels become available

**CAC Status States:**
- `selected` - Channel chosen for background CAC
- `requested` - CAC request sent to node  
- `accepted` - Node confirmed CAC start
- `done` - CAC completed successfully
- `radar` - Radar detected, channel marked NOP
- `rejected` - Node cannot perform CAC
- `timeout` - CAC exceeded expected duration
- `all clean` - All DFS channels already cleared



### Automatic Channel Selection  
**`acs`** - Enable Automatic Channel Selection recalculation

The ACS process automatically triggers recalculation under these conditions:
- **DFS channel becomes available** - CAC completion provides new channel options
- **Radio metrics deterioration** - Environmental conditions warrant channel change
- **Timer-based intervals** - Periodic reassessment (configurable timeout)

#### ACS Process Flow:
1. **Trigger Detection** - System identifies need for channel reassessment
2. **Scan Request** - Controller requests fresh channel survey data:
   - **Fast scan** - Limited to key channels (1,6,11 for 2.4GHz; PSC channels for 6GHz)
   - **Full scan** - Complete channel sweep when no traffic detected
3. **Preference Collection** - Nodes report updated channel preferences with:
   - Current channel utilization measurements
   - Noise floor readings  
   - Detected BSS counts
   - DFS status updates
4. **Channel Selection Algorithm**:
   - Filter out disabled/NOP channels
   - Apply DFS and bandwidth constraints  
   - Score channels based on preference values (0-15 scale)
   - Randomly select from highest-scoring candidates
5. **Channel Switch Request** - Controller sends channel selection command
6. **Status Monitoring** - Track channel switch progress and completion

**ACS Status States:**
- `scan requested` - Channel survey initiated
- `scan done` - Survey data collected  
- `best_selected` - Optimal channel identified
- `best_requested` - Channel switch command sent
- `best_accepted` - Node confirmed switch request
- `best_set` - Channel change completed successfully
- `current_best` - No change needed, current channel optimal
- `skipped - bsta connected` - Wireless backhaul prevents channel change
- `insufficient_data` - Not enough preference data for decision

## Additional Automatic Channel Selection options:
```
    config channel_plan
            option preclear_dfs '1'
            option acs '1'
            option acs_timeout '3h'
            option acs_highest_bandwidth '0'
            option acs_skip_dfs '0'
            option acs_prevent_cac '1'
            option acs_scan_before_recalc '1'
```

### Advanced ACS Configuration Options

#### **`acs_timeout`** (default: disabled)
- **Purpose**: Timer-based recalculation intervals
- **Example**: `'3h'` triggers ACS every 3 hours regardless of metrics
- **Use case**: Periodic reassessment in stable environments

#### **`acs_highest_bandwidth`** (default: 0)
- **Purpose**: Bandwidth optimization strategy  
- **When enabled**: Controller selects maximum supported bandwidth when DFS channels are available
- **Example**: Node starts with 80MHz but supports 160MHz → controller switches to 160MHz after CAC
- **Implementation**: Uses `wifi_opclass_highest_bandwidth()` to determine maximum available bandwidth

#### **`acs_skip_dfs`** (default: 0)
- **Purpose**: DFS avoidance for latency-sensitive applications
- **When enabled**: Filters out all DFS channels from selection algorithm
- **Impact**: Limits channel options but ensures immediate availability
- **Channel filtering**: Excludes `CHANNEL_PREF_REASON_DFS_AVAILABLE` and `CHANNEL_PREF_REASON_DFS_USABLE`

#### **`acs_prevent_cac`** (default: 1)
- **Purpose**: Prevents service disruption from regular CAC
- **When enabled**: Skips channels requiring immediate CAC (only uses pre-cleared channels)
- **Advantage**: Maintains AP service during channel switches
- **Implementation**: Filters out `CHANNEL_PREF_REASON_DFS_USABLE` channels

#### **`acs_scan_before_recalc`** (default: 1)  
- **Purpose**: Fresh survey data collection before channel decisions
- **Scan strategy**:
  - **Smart scan selection**: Fast scan when radio has TX/RX traffic, full scan when idle
  - **Channel coverage**: Band-specific optimized channel sets
  - **Data freshness**: Ensures current environmental conditions
- **When disabled**: Uses cached preference data (faster but potentially stale)

### Scan Channel Selection Logic
- **2.4GHz (Class 81)**: Channels 1, 6, 11
- **5GHz Lower (Class 115)**: Channel 36  
- **5GHz DFS (Class 118)**: Channel 52
- **5GHz DFS Upper (Class 121)**: Channels 100, 116
- **5GHz Upper (Class 124)**: Channel 149
- **6GHz (Class 131)**: PSC channels 5,21,37,53,69,85,101,117,133,149,165,181,197



## Monitoring and Debugging

### Status Monitoring
Monitor ACS and DFS operations using the controller status interface:

```bash
# ubus call map.controller status
```

#### DFS Cleanup Status Example
```json
{
    "cleanup_request_age": 84,
    "cleanup_request": [{
        "status": "all clean",
        "channel": 58, 
        "opclass": 128,
        "agent": "aa:bb:cc:dd:ee:ff",
        "radio": "11:22:33:44:55:66"
    }]
}
```

**Status Fields:**
- `cleanup_request_age`: Seconds since last CAC request
- `status`: Current CAC operation state (see CAC Status States above)
- `channel`/`opclass`: Target channel and operating class
- `mid`: Message ID for tracking CMDU responses (when status = "requested")

#### ACS Status Examples  
```json
{
    "acs_request_age": 275,
    "acs_request": [{
        "status": "current_best",
        "channel": 11,
        "bandwidth": 20,
        "agent": "aa:bb:cc:dd:ee:ff", 
        "radio": "11:22:33:44:55:66"
    }]
}
```

```json
{
    "acs_request_age": 21,
    "acs_request": [{
        "status": "best_set", 
        "channel": 58,
        "bandwidth": 80,
        "agent": "aa:bb:cc:dd:ee:ff",
        "radio": "11:22:33:44:55:66"
    }]
}
```

### Channel Preference Details
Individual channel information includes:
- `channel`: Channel number
- `preference`: Score 0-15 (higher = better)  
- `reason`: Status reason (`dfs-available`, `dfs-usable`, `non-dfs`, etc.)
- `cac_methods`: Bitmask of supported CAC methods
- `cac_time`: Required CAC duration in seconds

### Logging Configuration
Enable detailed channel planning logs:
```bash
# Enable channel-specific logging
ubus call map.controller log '{"feature":"-all, +channel", "level":3}'

# View log output  
cat /tmp/mapcontroller.log
```

**Log Levels:**
- Level 1: Errors only
- Level 2: Warnings and errors  
- Level 3: Info, warnings, and errors
- Level 4: Debug information (verbose)

### Key Log Messages
- `acs radio channel recalc` - Channel selection algorithm execution
- `dfs radio preCAC` - Background CAC operations  
- `metrics` - Radio performance data updates
- `best_set` - Successful channel changes
- `skipped - bsta connected` - Backhaul-constrained decisions

## EasyMesh CMDU Messages

The ACS implementation uses several standardized EasyMesh Control and Management Data Units (CMDUs) for communication between the controller and agents:

### Channel Management CMDUs

- `Channel Scan Request/Report`
- `Channel Preference Query/Report`
- `Channel Selection Request/Response`
- `Operating Channel Report`

### DFS/CAC Management CMDUs

- `CAC Request`
- `CAC Termination`
- `CAC Completion Report`
- `CAC Status Report`

### Message Flow Examples

#### Typical ACS Cycle:
1. **Trigger** → `CMDU_CHANNEL_SCAN_REQUEST` → Agent surveys channels
2. **Scan complete** → `CMDU_CHANNEL_SCAN_REPORT` → Controller receives data  
3. **Fresh preferences** → `CMDU_CHANNEL_PREFERENCE_QUERY` → Agent reports scores
4. **Algorithm runs** → `CMDU_CHANNEL_SELECTION_REQ` → Agent switches channel
5. **Confirmation** → `CMDU_OPERATING_CHANNEL_REPORT` → Process complete

#### Background CAC Flow:
1. **DFS cleanup** → `CMDU_CAC_REQUEST` → Agent starts background CAC
2. **CAC progress** → `CMDU_CHANNEL_PREFERENCE_REPORT` → Status updates  
3. **CAC complete** → `CMDU_CHANNEL_PREFERENCE_REPORT` + CAC TLV → Channel available
4. **ACS trigger** → Channel selection cycle begins with new available channel

