OWM Integrator Guide

OWM Integrator Guide

General

This guide explains the key components that integrators need to understand when working with OWM (One Wifi Manager). It covers the three main subsystems: Confsync, Stats, and Steering.



Title: OWM Integrator Guide

Overview

This guide explains the key components that integrators need to understand when working with OWM (One Wifi Manager). It covers the three main subsystems: Confsync, Stats, and Steering.


1. Confsync

What is Confsync?

Confsync is the configuration synchronization engine that continuously ensures intended configuration (desired state) matches actual hardware state (current state) by detecting mismatches and applying necessary changes.

Architecture

┌────────────────────────────────────────┐ │ │ │ ▼ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ osw_conf │ │ osw_confsync │ │ osw_state │ │ (Intended │────▶│ (Sync │────▶│ (Actual │ │ Config) │ │ Engine) │ │ State) │ └──────────────┘ └──────────────┘ └──────────────┘ ┌──────────────┐ │ osw_mux │ │ (Driver │ │ Multiplexer) │ └──────────────┘ Hardware

How It Works

  1. Intended Config (osw_conf):

    • Supplemented from OVSDB tables (Wifi_Radio_Config, Wifi_VIF_Config)

    • Represents what the cloud/user wants

    • Updated when cloud sends new configuration

  2. Actual State (osw_state):

    • Populated from driver/netlink events

    • Represents what hardware is actually doing

    • Updated automatically when hardware events occur

  3. Sync Process:

    • Confsync observes changes in osw_conf or osw_state

    • Compares intended configuration vs actual state

    • Generates minimal command set to reconcile differences

    • Sends commands through osw_mux to hardware drivers

    • Verifies hardware applied changes correctly

State Machine

Confsync uses a state machine to track the configuration process:

enum osw_confsync_state { OSW_CONFSYNC_IDLE, // No configuration in progress OSW_CONFSYNC_REQUESTING, // Preparing configuration OSW_CONFSYNC_WAITING, // Waiting for hardware response OSW_CONFSYNC_VERIFYING, // Verifying configuration was applied };

State Transitions:

  1. IDLE → Changes detected in config or state

  2. REQUESTING → Building configuration diff

  3. WAITING → Commands sent to hardware

  4. VERIFYING → Checking hardware applied changes

  5. IDLE → Configuration matches state

Configuration Process

Step 1: Config Update

When OVSDB is updated:

// Cloud updates Wifi_Radio_Config OVSDB UPDATE on Wifi_Radio_Config ow_ovsdb receives OVSDB update ow_conf translates configuration osw_conf updates internal structures osw_confsync detects change osw_confsync_set_state(OSW_CONFSYNC_REQUESTING)

Step 2: Build Configuration

// Build target configuration struct osw_drv_phy_config { char *phy_name; struct osw_hwaddr addr; uint32_t tx_chainmask; uint32_t rx_chainmask; struct osw_channel channel; // ... other fields }; // Generate commands for each phy: compare target_config vs current_state if different: prepare command to apply

Step 3: Apply to Hardware

// Send to hardware via nl80211 driver through osw_mux osw_mux_request_phy_set_config( phy_name, &target_config );

Step 4: Verify

// State is updated automatically via netlink events // osw_state reflects current hardware state // Compare if (config_matches_state) { osw_confsync_set_state(OSW_CONFSYNC_IDLE); } else { // Retry or report error }

Confsync Watchdog

Confsync includes a watchdog that monitors configuration health and prevents configuration problems. The watchdog detects two types of issues:

  1. Configuration happening too frequently - Device is constantly reconfiguring

  2. Device can't configure - Device is unable to apply configuration successfully

Monitored Conditions:

  1. Confsync not settled in 3 minutes

  2. Spent >75% of last 5 minutes in UNSETTLED state

Actions:
When problems are detected, the watchdog takes the safest approach:

  • Logs error message

  • Sends Linux signal 6 (SIGABRT) to OWM process, which triggers OWM restart, clearing any stuck states and allowing fresh configuration attempt

Purpose:
The watchdog prevents the device from getting stuck in an unconfigured or constantly-reconfiguring state, ensuring configuration reliability and system stability. It also prevents the continuation of bogus states and other convoluted state combinations that could lead to unpredictable system behavior.

Scenarios of Watchdog Triggering:

The confsync watchdog will "bark" (trigger restart) in scenarios such as:

  1. State reporting not implemented:

    • Driver fails to report current hardware state

    • Report function not implemented, returns wrong value, or memory not passed correctly

    • Result: Confsync can't verify if configuration was applied

  2. Configuration request not implemented:

    • Driver missing configuration handlers

    • Configuration commands not implemented for certain features

    • Hardware can't configure - is it properly reported/value returned?

    • Result: Configuration requests are ignored, confsync keeps retrying

  3. Broken comparison or returned value:

    • Incorrect state comparison logic in osw_confsync

    • Driver returns inconsistent or malformed state data

    • Mismatched data types or invalid values

    • Value incorrectly passes through abstraction layers

    • Configuration never matches state due to comparison bugs

    • Result: Perpetual UNSETTLED state

Real-World Example:

ACL Limit Exceeded on BCM Platform:

On the BCM platform, the ACL (Access Control List) limit is 64 entries. In one scenario:

  • Cloud configured 85 ACLs in OVSDB

  • All abstraction layers correctly passed 85 to the driver

  • However, osw_plat_bcm only read and configured the first 64 ACLs (hardware limit)

  • The state reported 64 configured ACLs

  • Confsync compared: intended (85) ≠ actual (64)

  • Confsync couldn't settle and kept retrying to configure the remaining 21 ACLs

  • After repeated attempts, the confsync watchdog detected the perpetual UNSETTLED state

  • Watchdog restarted OWM to clear the stuck configuration

This demonstrates how hardware limitations can trigger the watchdog when the intended configuration exceeds platform capabilities and the mismatch isn't properly handled.

Debugging

Enable detailed logging:

Insert:

# Insert debug entry ovsh i AW_Debug name:=OW log_severity:=Trace # Monitor whole OW logread -f | grep ow # Monitor confsync logread -f | grep confsync # Monitor settled states logread -f | grep settle

2. Stats

What is Stats?

The Stats subsystem collects, processes, and reports wireless statistics including channel survey data, neighbor information, client metrics, and device performance. It uses an actor-based architecture where statistics are published to subscribers in a decoupled, asynchronous manner. Statistics may arrive at any point in time from various sources (driver, netlink, hardware counters).

Architecture

┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Wifi_Stats_ │ │ow_stats_conf │ │ osw_stats │ │ Config │────▶│ (Config, │────▶│ (Publisher) │ │ (OVSDB) │ │ Subscriber) │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ ▲ │ │ ▼ ┌──────────────┐ ┌────┴───────────┐ │ Driver │ │ Subscribers │ │ (Collector) │──────▶ (ow_stats_conf,│ └──────────────┘ │ ow_steer, │ │ dpp, etc.) │ └────────────────┘

Statistics Types

1. Survey Statistics

Channel utilization information.

OVSDB Configuration (Wifi_Stats_Config):

stats_type : survey survey_type : on-chan | off-chan | full radio_type : 2.4G | 5G | 5GL | 5GU | 6G sampling_interval : integer (seconds) reporting_interval : integer (seconds) channel_list : integer[] (1-233, max 64 channels) survey_interval_ms : integer (milliseconds)

2. Neighbor Statistics

Information about neighboring BSSs.

OVSDB Configuration (Wifi_Stats_Config):

stats_type : neighbor radio_type : 2.4G | 5G | 5GL | 5GU | 6G survey_type : on-chan | off-chan | full sampling_interval : integer (seconds) reporting_interval : integer (seconds)

3. Client Statistics

Per-client performance metrics.

OVSDB Configuration (Wifi_Stats_Config):

stats_type : client radio_type : 2.4G | 5G | 5GL | 5GU | 6G sampling_interval : integer (seconds) reporting_interval : integer (seconds)

Collected Metrics:

  • Client association/disassociation events

  • Per-client counters from driver (TX/RX bytes, frames, retries, errors, rates)

  • SNR measurements

4. Device Statistics

Aggregate device metrics.

OVSDB Configuration (Wifi_Stats_Config):

stats_type : device sampling_interval : integer (seconds) reporting_interval : integer (seconds)

Collected Metrics:

  • Temperature (gathered by OWM)

  • CPU usage, Memory usage, Uptime (handled by SM - Statistics Manager)

Configuration (Wifi_Stats_Config)

OVSDB Table Fields

_uuid : UUID (unique identifier) _version : UUID (version identifier) stats_type : neighbor | client | survey | device | radius_stats | latency | capacity | radio | essid | quality | rssi | steering | client_auth_fails radio_type : 2.4G | 5G | 5GL | 5GU | 6G survey_type : on-chan | off-chan | full | ["set",[]] sampling_interval : integer (seconds, 0 = disabled) reporting_interval : integer (seconds) reporting_count : integer survey_interval_ms : integer (milliseconds) | ["set",[]] channel_list : ["set",[<channels>]] (e.g., ["set",[1,6,11]]) if_name : ["set",[<interfaces>]] report_type : ["set",[]] | ["set",["raw","average","histogram","percentile","diff"]] sample_policy : ["set",[]] | ["set",["separate","merge"]] threshold : ["map",[]] | ["map",[["max_delay",<seconds>],["util",<percentage>]]] latency_dscp : ["set",[]] | ["set",["do_not_report","report_per_dscp"]] latency_kinds : ["set",[]] | ["set",["min","max","avg","last","num","perc"]]

Key Fields

  • stats_type: Type of statistics to collect

  • radio_type: Radio band (2.4G, 5G, 5GL, 5GU, 6G)

  • survey_type: Scan method (on-chan, off-chan, full)

  • sampling_interval: Collection frequency in seconds (0 = disabled)

  • reporting_interval: Reporting frequency to cloud in seconds

  • channel_list: Specific channels to monitor (e.g., ["set",[1,6,11]])

  • survey_interval_ms: Time spent per channel in milliseconds

  • threshold: Conditions for withholding reports (e.g., ["map",[["max_delay",600],["util",10]]])

Example Configuration

# View current configuration ovsh s Wifi_Stats_Config # Example output shows multiple stat types configured per radio # neighbor stats on 2.4G, 5GL, 5GU # client stats on 2.4G, 5GL, 5GU # survey stats on 2.4G (with channel_list) # device stats (no radio_type)

Example: Creating a Statistics Module

Here's how to create a new module that gathers specific statistics:

Step 1: Create the subscriber module

// my_stats_module.c #include <osw_stats.h> #include <log.h> struct my_stats_module { struct osw_stats_subscriber *subscriber; // Add your module-specific data here }; // Callback when statistics arrive static void my_stats_cb(enum osw_stats_id id, const struct osw_tlv *data, const struct osw_tlv *last, void *priv) { // Statistics arrive asynchronously at any time // Only process client statistics if (id != OSW_STATS_STA) return; struct my_stats_module *module = priv; // Get statistics definitions for parsing const struct osw_stats_defs *stats_defs = osw_stats_defs_lookup(OSW_STATS_STA); if (stats_defs == NULL) return; // Parse TLV data const struct osw_tlv_hdr *tb[OSW_STATS_STA_MAX__] = {0}; osw_tlv_parse(data->data, data->used, stats_defs->tpolicy, tb, OSW_STATS_STA_MAX__); // Extract fields we're interested in const struct osw_tlv_hdr *snr_db_t = tb[OSW_STATS_STA_SNR_DB]; const struct osw_tlv_hdr *sta_addr_t = tb[OSW_STATS_STA_MAC_ADDRESS]; if (snr_db_t == NULL) return; if (sta_addr_t == NULL) return; const uint32_t snr_db = osw_tlv_get_u32(snr_db_t); struct osw_hwaddr sta_addr; osw_tlv_get_hwaddr(&sta_addr, sta_addr_t); LOGI("my_stats: client: " OSW_HWADDR_FMT " snr=%u", OSW_HWADDR_ARG(&sta_addr), snr_db); } // Initialize: allocate struct and fill in data static void my_stats_module_init(struct my_stats_module *module) { // Allocate subscriber module->subscriber = osw_stats_subscriber_alloc(); // Configure subscriber osw_stats_subscriber_set_report_fn(module->subscriber, my_stats_cb, module); osw_stats_subscriber_set_report_seconds(module->subscriber, 10.0); osw_stats_subscriber_set_sta(module->subscriber, true); LOGI("my_stats: initialized"); } // Attach: connect to the outside world static void my_stats_module_attach(struct my_stats_module *module) { // Register to receive statistics osw_stats_register_subscriber(module->subscriber); LOGI("my_stats: attached and subscribed"); }

Step 2: Register the module

Use the OSW_MODULE macro with separate init and attach phases:

OSW_MODULE(my_stats_module) { static struct my_stats_module m; my_stats_module_init(&m); my_stats_module_attach(&m); }

Key Points:

  • Statistics use actor-based architecture with publisher-subscriber pattern

  • Stats arrive asynchronously at any point in time from various sources

  • Use TLV format for efficient, extensible data representation

  • Multiple subscribers can receive the same statistics independently

  • No need to poll - statistics are pushed to your module when available

  • Reference implementation: See src/lib/osw/src/osw_sta_snr.c for a complete real-world example

Debugging Statistics

# Enable OW debug logs ovsh i AW_Debug name:=OW log_severity:=Debug # Monitor statistics collection in logs logread -f | grep "my_stats" # View MQTT statistics reports # Use OSRT to display MQTT Statistics

3. Steering

What is Steering?

Steering manages client distribution across radios and bands to optimize wireless performance. It includes band steering (automatic distribution based on signal strength) and client steering (cloud-directed optimization for static devices).

Architecture

┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │Band_Steering_ │ │Band_Steering_ │ │Wifi_VIF_ │ │Config │ │Clients │ │Neighbours │ │(OVSDB) │ │(OVSDB) │ │(OVSDB) │ └──────────────────┘ └──────────────────┘ └──────────────────┘ │ │ │ └─────────────────────┼──────────────────────┘ ┌─────────────────┐ │ ow_steer_bm │ │ (Band Manager) │ └─────────────────┘ ┌──────────────┼──────────────┐ │ │ │ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Policies │ │ Candidates │ │ Executors │ │ (Decisions) │ │ (Targets) │ │ (Actions) │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ └──────────────┼──────────────┘ ┌─────────────────┐ │ osw_mux/btm │ │ (Hardware) │ └─────────────────┘

Steering Types

OWM implements two distinct steering mechanisms:

Band Steering

  • Scope: Local on the device (AP/gateway), without cloud intervention

  • Target: Moving/mobile devices (not static clients)

  • Triggers:

    • SNR crossing events (RSSI XING): Client signal strength crosses HWM/LWM thresholds

    • VIF shutdown (defer_vif_down): VIF is being disabled (10-second grace period allows steering clients to other VIFs before service interruption)

  • Methods:

    • Pre-association blocking (e.g., blocking 2.4GHz probe responses to force 5GHz association)

    • SNR threshold-based decisions (HWM/LWM/BOWM)

      • HWM (High Water Mark): Steer up to 5GHz when signal is strong

      • LWM (Low Water Mark): Steer down or away when signal degrades

      • BOWM (Bottom LWM): Force disconnect legacy (non-11v) clients on 2.4G when signal is critically low

Client Steering (Throughput Optimized Steering - TOS)

  • Scope: Cloud-triggered steering decisions

  • Target: Static devices (devices with little SNR variation)

  • Eligibility:

    • Stationary devices (e.g., Roku, MacBooks, Windows laptops)

    • Static classification determined nightly based on RSSI data over last 24 hours and majority of last 10 days

    • Only static devices are eligible unless they have a specific device profile

  • Methods:

    • 802.11v BSS Transition Management (BTM)

    • Legacy deauth kicks

  • Idle Period Requirement:

    • Steering may be deferred during high traffic (video streaming, VoIP) to avoid user disruption

Device Profiles

When a client connects, the cloud identifies its device type (manufacturer, model) via MAC address and assigns a steering profile with customized thresholds and policies optimized for that device class. The profile is pushed to the AP via OVSDB.

Cloud Override Behavior:

  • Claimed pods in multi-AP topology: Cloud may override local settings (e.g., force pref_5g:=always)

  • Single-AP testing: Unclaim all pods to enable local HWM-based steering decisions

Steering Policies

Band Steering Policies

1. Pre-Association Policy

Blocks association to specific BSSs before connection (part of Band Steering).

Use Case: Prevent 2.4GHz connections for capable clients

Implementation: src/lib/ow/src/ow_steer_policy_pre_assoc.c

Key Fields:

  • pref_5g: Steering preference (always, never, hwm)

  • pref_6g: 6GHz steering preference (always, never)

  • pre_assoc_auth_block: Block pre-association auth requests (boolean)

  • max_rejects: Maximum pre-association rejections (0 = unlimited)

  • rejects_tmout_secs: Timeout to reset rejection counter (0 = no timeout)

  • pref_5g_pre_assoc_block_timeout_msecs: Timeout for 5GHz blocking (milliseconds, default: 4000)

  • reject_detection: Detection method (probe_all, probe_null, auth)

  • preq_snr_thr: Probe request SNR threshold

Configuration:

# Always prefer 5GHz (block 2.4GHz probes) ovsh i Band_Steering_Clients pref_5g:='always' pre_assoc_auth_block:=true mac:=AA:BB:CC:DD:EE:FF # Use HWM-based logic ovsh i Band_Steering_Clients pref_5g:='hwm' mac:=AA:BB:CC:DD:EE:FF

Note: Use ovsh i (insert) over ovsh u (update). Insert verifies parameters and values during insertion, catching configuration errors early. Update only works on existing records

Verify:

ovsh s Band_Steering_Clients -w mac==AA:BB:CC:DD:EE:FF pref_5g pre_assoc_auth_block max_rejects

2. High Water Mark Policy

Steers clients when SNR exceeds threshold (Band Steering).

Use Case: Distribute load across APs, steer capable clients from 2.4GHz to 5GHz when signal is strong

Implementation: src/lib/ow/src/ow_steer_bm_policy_hwm_2g.c

Key Fields:

  • hwm: High Water Mark SNR threshold in dB (default: 30)

  • backoff_secs: Wait time before retrying steering (default: 120)

  • kick_type: Mechanism for steering (btm_deauth, deauth, none)

  • kick_debounce_period: Delay before kicking again in seconds (default: 60)

  • steering_btm_params: BTM parameters (abridged, bss_term, btm_max_retries, btm_retry_interval, disassoc_imminent, pref, valid_interval)

  • steering_kick_guard_time: Guard time before allowing kick (default: 10)

  • steering_kick_backoff_time: Backoff time after kick failure (default: 1800)

  • steer_during_backoff: Allow steering during backoff period (boolean)

Configuration:

# Standard band steering setup ovsh i Band_Steering_Clients hwm:=35 lwm:=20 backoff_secs:=120 kick_type:=btm_deauth mac:=AA:BB:CC:DD:EE:FF # Testing: Force upsteering to 5GHz ovsh i Band_Steering_Clients hwm:=100 mac:=AA:BB:CC:DD:EE:FF

Verify:

ovsh s Band_Steering_Clients -w mac==AA:BB:CC:DD:EE:FF hwm backoff_secs kick_type

3. Low Water Mark Policy

Steers clients when signal quality drops below threshold (Band Steering).

Use Case: Move clients to better APs or bands when signal degrades

Implementation: src/lib/ow/src/ow_steer_policy_snr_xing.c

Key Fields:

  • lwm: Low Water Mark SNR threshold in dB (default: 10)

  • bottom_lwm: Bottom LWM threshold for legacy clients (default: 5)

  • sticky_kick_type: Kick mechanism for sticky steering (btm_deauth, deauth)

  • sticky_btm_params: BTM parameters (abridged, bss_term, btm_max_retries, btm_retry_interval, disassoc_imminent, inc_neigh, pref, valid_interval)

  • sticky_kick_debounce_period: Debounce period for sticky kicks (default: 60)

  • sticky_kick_guard_time: Guard time for sticky kicks

  • sticky_kick_reason: Reason code for sticky kicks (default: 1)

  • backoff_exp_base: Exponential backoff base multiplier (default: 3)

Configuration:

# Configure LWM steering ovsh i Band_Steering_Clients lwm:=20 hwm:=35 bottom_lwm:=5 mac:=AA:BB:CC:DD:EE:FF # Testing: Force downsteering to 2.4GHz ovsh i Band_Steering_Clients lwm:=1 mac:=AA:BB:CC:DD:EE:FF

Verify:

ovsh s Band_Steering_Clients -w mac==AA:BB:CC:DD:EE:FF lwm bottom_lwm hwm sticky_kick_type backoff_exp_base

Client Steering Policies

Cloud-triggered steering for static devices (Throughput Optimized Steering).

Use Case: Optimal AP selection for stationary devices (Roku, MacBooks, Windows laptops)

Implementation: src/lib/ow/src/ow_steer_policy_force_kick.c

1. Force Kick Mode

Controls proactive steering behavior.

Field: force_kick

Values:

  • speculative: Proactive steering based on prediction

  • directed: Cloud-directed steering to specific AP

  • none: Disabled

2. Client Steering Mode

Controls when client steering is enabled.

Field: cs_mode

Values:

  • home: Enable steering in home network

  • away: Enable steering in away network

  • off: Disabled

3. Idle Steering

Controls whether to steer only idle clients.

Field: kick_upon_idle

Values:

  • true: Only steer when client is idle (< 200 PPDUs/min)

  • false: Steer regardless of traffic

4. Kick Type

Selects steering mechanism.

Field: sc_kick_type

Values:

  • btm_deauth: Try BTM first, fall back to deauth

  • deauth: Use deauth directly

Additional Fields:

  • cs_state: Current steering state (read-only: steering, none, expired, failed)

  • cs_params: Client steering parameters

  • sc_btm_params: BTM parameters for client steering

  • sc_kick_debounce_period: Debounce period for client steering kicks

  • sc_kick_reason: Reason code for client steering kicks

  • btm_max_neighbors: Maximum neighbors in BTM request (default: 3)

  • neighbor_list_filter_by_beacon_report: Filter neighbor list by beacon report (boolean, default: true)

  • neighbor_list_filter_by_btm_status: Filter neighbor list by BTM status (boolean, default: true)

Configuration Examples:

# Enable directed client steering with idle check ovsh i Band_Steering_Clients force_kick:='directed' cs_mode:='home' kick_upon_idle:=true sc_kick_type:='btm_deauth' mac:=AA:BB:CC:DD:EE:FF # Disable client steering ovsh i Band_Steering_Clients force_kick:='none' cs_mode:='off' mac:=AA:BB:CC:DD:EE:FF

Requirements:

  • Device classified as static (low RSSI variation over 24h + majority of 10 days)

  • Device must be idle when kick_upon_idle:=true (< 200 PPDUs/min over 3-minute window)

  • Classification updated nightly by cloud

Verify:

ovsh s Band_Steering_Clients -w mac==AA:BB:CC:DD:EE:FF force_kick cs_mode cs_state kick_upon_idle sc_kick_type

Steering Actions

1. ACL Block

Block client via access control list.

2. BTM Request

Send BTM (802.11v) steering request.

3. Deauth

Force disassociation.

Steering Flow

For every client, the steering system maintains a list of candidate APs (alternative BSSs the client could connect to). Steering policies then edit this AP candidate list based on various criteria:

  1. Candidate List Initialization:

    • System builds a list of potential target APs for each client

    • Consists of BSSs configured by Cloud in Wifi_VIF_Neighbour and local APs from Wifi_VIF_State

  2. Policy Evaluation:

    • Each active steering policy examines the candidate list sequentially

    • Policies filter out unsuitable candidates based on their criteria (SNR, load, capabilities)

  3. Candidate Selection:

    • After all policies evaluate the list, the best remaining candidate is selected

    • Selection considers signal strength, band preference, and load balancing

    • If no suitable candidate exists, no steering action is taken

  4. Action Execution:

    • Executor component performs the steering action using BTM, ACL, or deauth

    • Success/failure monitored and reported

    • Consequences and retry logic are executor-specific

Verifying Steering Configuration

Check all steering groups:

ovsh s Band_Steering_Config

Check all client policies:

ovsh s Band_Steering_Clients

Check specific client configuration:

# View all steering settings for a client ovsh s Band_Steering_Clients -w mac==AA:BB:CC:DD:EE:FF # Check specific policy fields ovsh s Band_Steering_Clients -w mac==AA:BB:CC:DD:EE:FF pref_5g hwm lwm force_kick

Common Policy Combinations:

Band Steering (local, moving devices):

ovsh i Band_Steering_Clients pref_5g:='hwm' hwm:=35 lwm:=20 mac:=AA:BB:CC:DD:EE:FF

Client Steering (cloud, static devices):