Skip to content
Snippets Groups Projects
Commit fe6dce8b authored by Filip Matusiak's avatar Filip Matusiak
Browse files

Update STA steering documentation

parent 3df04b23
Branches
No related tags found
1 merge request!155Update STA steering documentation
Pipeline #68215 passed
# STA steering
Current version of software supports controller initiated mandate steering based on beacon measurement. For STA to be able to be steered its drivers must support 802.11k (RRM for beacon measurements) and 802.11v (this is usually implemented in MAC, needed for BTM steering).
## Usage & UCI Configuration
In order to enable STA steering please set at least *enable_sta_steer* and *use_bcn_metrics* in mapcontroller file to **1** .
......@@ -20,9 +22,26 @@ config controller 'controller'
# use rcpi from beacon metrics to decide on best bssid to steer to
option use_usta_metrics '0'
# use ul_rcpi measured as an unassociated sta as additional trigger for steering (experimental)
list steer_module 'rcpi'
# the name must match the /usr/lib/mapcontroller/<name>.so plugin file
...
```
Please note, that the steer_module must be present in the system, that is the map-controller is expecting to find rcpi plugin in /usr/lib/mapcontroller/rcpi.so. Otherwise it will not be able to load the steering decision plugin, and therefore the steering will be effectively disabled.
**/etc/config/mapcontroller**
``` shell
...
config radio 'radio_44d4376af4cf'
option agent_id '46:d4:37:6a:f4:c0'
option macaddr '44:d4:37:6a:f4:cf'
option band '5'
option rcpi_threshold '86'
...
```
This will be synchronized to mapagents in the mesh – radio sections in /etc/config/mapagent for each agent will be updated accordingly.
**/etc/config/mapagent**
......@@ -47,10 +66,64 @@ config wifi-radio
...
```
In case the rcpi_threshold is not set explicitly in configuration file it will default to:
#define CONFIG_DEFAULT_RCPI_TH_6G 86
#define CONFIG_DEFAULT_RCPI_TH_5G 86
#define CONFIG_DEFAULT_RCPI_TH_2G 70
## Working functionality (automatic beacon metrcis based BTM steering)
## Working functionality (automatic steering)
Controller initiated mandate steering is now working as follows:
Depending on the settings there'll be more or less frequent checks done by the controller. - Frequency of the checks depends on the frequency of the associated sta link metrics responses received from the nodes, which depends on the settings as explained earlier (util_threshold, rcpi_threshold, include_sta_metric). Controller will check if RCPI goes below some threshold (currently defined to 160 in controller). If so, then controller will request for beacon metrics and/or unassociated STA link metrics for given client. After some time it will then compare current RCPI of that given station with the values obtained in metrics and only try to (BTM) steer that station if there's a better candidate found. - The delta RCPI of at least 10 is required.
Once the STA – AP rcpi goes below given value, map-agent sends the Associated STA Link Metrics Response to the map-controller. This in turn will cause map-controller to send beacon metrics request for given STA on all operating classes/channels of nodes operating in the mesh and SSID value set to current network. After some time (depends on number of opclass/channel pairs) – the beacon metrics results will be parsed. Once there’s a better (at least 10 diffsnr - difference in RSSI) BSS found for given STA, controller will try to to move STA to that BSS using BTM request.
Depending on the settings there'll be more or less frequent checks done by the controller. - Frequency of the checks depends on the frequency of the associated sta link metrics responses received from the nodes, which depends on the settings as explained earlier (util_threshold, rcpi_threshold, include_sta_metric). Controller will check if RCPI goes below the reporting threshold. If so, then controller will request for beacon metrics and/or unassociated STA link metrics for given client. After some time it will then compare current RCPI of that given station with the values obtained in metrics and only try to (BTM) steer that station if there's a better candidate found. - The delta RCPI of at least 8 is required.
## Unassociated STA link metrics (experimental)
Additionally one can try to use unassociated STA link metrics on top or instead of beacon metrics for getting of the (uplink) rcpi of given STA, for that one must set following in map-controller config
**/etc/config/mapcontroller**
``` shell
option use_usta_metrics '1'
```
This will enable unassociated STA link metrics as an additional trigger for mandate steering.
The check is triggered on same occasion as for beacon metrics –upon drop of the signal strength below given threshold. In such case if there’s a BSS with better link towards steered STA found (in terms of better uplink RCPI - difference of at least 10) controller will send BTM steer request towards this STA.
## Steer exclusion lists
Additionally there’re two steering disallowed lists maintained in the controller:
- steer_exclude (per node) – exclude STA from steering completely
- steer_exclude_btm (per node) – do not allow to steer of the STA using BTM steering (but association control based opportunity steering will be possible in the future – once implemented). To put the STA on either of two lists one must just add a list entry per node in controller UCI config as in example:
**/etc/config/mapcontroller**
``` shell
config node 'node_46d4376af4c0'
option agent_id '46:d4:37:6a:f4:c0'
list steer_exclude 'e0:d4:e8:79:c4:ee'
list steer_exclude 'e0:d4:e8:79:c4:11'
list steer_exclude_btm 'aa:bb:cc:dd:ee:ff'
```
Removing STA MAC from the list will result in immediate allowing of the STA to be (BTM) steered again.
## RCPI plugin
The plugin is used for separating steering decision algorithm from the steering code itself. Current example implementation is using diffsnr and rcpi_threshold values (hardcoded in map-controller, but to be passed as additional parameters in the future) in order for the map-controller rcpi plugin to decide if there’s a better bssid found in per-STA measurements list.
The source for the default rcpi plugin can be found in map-controller source under plugins/steer/rcpi. If one wants to use their own decision algorithm they need to create new directory under plugins/steer/<plugin name> and update appropriate Makefiles.
## Band steer
There’s an additional option in controller section of map-controller config
**(/etc/config/mapcontroller)**
``` shell
option bandsteer ‘1’
```
This option is also passed down to rcpi plugin. If set then rcpi plugin will allow for steering between bands (from 2.4 to 5 and from 5 to 2.4), basing its decision only on the difference in rssi. If not set then only steering across BSSs operating on current band will be allowed.
## UBUS call inititated steering
In order to steer the STA one can also use a map-controller UBUS API as follows
......@@ -67,3 +140,162 @@ The parameters are:
- steer_req_mode - true for mandate, false for opportunity (experimental)
- target_bssid - target BSSID to which the STA is requested to connect
## Other UBUS commands
Get independent (from the algorithm) beacon metrics for one opclass/channel pair:
``` shell
ubus call map.controller bcn_metrics_query '{"agent":"46:d4:37:6a:f4:c0", "sta":"e0:d4:e8:79:c4:ee", "ssid":"44:d4:37:6a:f4:cf", "opclass":115, "channel":36}'
```
Get independent (from the algorithm) beacon metrics for more than one opclass/channel:
``` shell
ubus call map.controller bcn_metrics_query '{"agent":"46:d4:37:6a:f4:c0", "sta":"e0:d4:e8:79:c4:ee", "bssid":"ff:ff:ff:ff:ff:ff", "opclass":0, "channel":255, "ssid":"iopsysWrt-44D4376AF4C0", "channel_report":[{"opclass":115,"channels":[36,40,44,48]}, {"opclass":118,"channels":[52,56,60,64]}]}'
```
Displaying of the currently stored beacon metrics:
``` shell
ubus call map.controller bcn_metrics_resp
ubus call map.controller bcn_metrics_resp '{"sta":"e0:d4:e8:79:c4:ee"}
```
## Known issues & limitations
- The rssi delta of 8dB ('diffsnr') is currently hardcoded.
- report_rcpi_threshold & rcpi_threshold are set separately per radio in controller config and can only be set after succesfull onboarding.
- hysteresis parameter is not implemented.
- There's no initial channel scan - independent channel scan must be executed on each node.
i.e. `ubus call wifi.radio.wl0 list_neighbor` must include target (to:) bss when run on src (from:) node
One shall set the
``` shell
option initial_channel_scan ‘1’
```
in controller section of the controller config (/etc/config/mapcontroller) in order for the BTM steering to work robustly all the times.
Otherwise the neighbor_list on target interface may be empty, causing the BTM steering to that given BSSID to fail by ESL (“bssid not on neighbor list” type of error).
We’re currently working on removal of that check in ESL, so that neighbor_list can be empty on given interface (ubus call wifi.ap.wlX list_neighbor), as we already know the neighbors in map. We’ll then provide all the necessary neighbor data directly from the map daemons (bssid, channel, opclass, phy & bssid_info) – without depending on the channel scan functionality that would normally cause the neighbor list in wifi to be filled in.
- Only beacon metrics that were obtained after steering request sent are being used as steering data base. Others are marked 'stale'.
- One must set RCPI (report_rcpi_threshold) using /etc/config/mapcontroller separately for each device & radio.
- One must remember to set up following configuration in controller, as it's not there by default:
``` shell
list steer_module 'rcpi'
```
- bandsteer check is not implemented in 6.5
## Source code guide
Function(s) from where the steering method of the steer plugin gets called & how the result/verdict is handled
if (RCPI < rcfg.report_rcpi_threshold)
then send 'Associated STA Link Metrics Response' to the Controller
**src/agent.c**
``` C
w->rcpi_threshold_timer.cb = agent_rcpi_thresold_timer_cb;
agent_rcpi_thresold_timer_cb()
list_for_each_entry(s, &fh->stalist, list) {
rcpi = rssi_to_rcpi(s->rssi[0]);
if (rcpi < rcfg->rcpi_threshold) {
cmdu = agent_gen_assoc_sta_metric_responsex(a, a->cntlr_almac, s, fh);
```
**src/cntlr_map.c**
``` C
handle_sta_link_metrics_response()
```
if (c->cfg.use_bcn_metrics)
then
1. num_req = cntlr_request_bcn_metrics_sta(c, s);
2. uloop_timeout_set(&s->bcn_metrics_timer, num_req * 3 * 1000);
**src/cntlr.c**
``` C
s->bcn_metrics_timer.cb = cntlr_bcn_metrics_parse;
```
in cntlr_bcn_metrics_parse():
1. verdict = cntlr_maybe_steer_sta()
2. if (verdict == OK)
then
cntlr_steer_sta() => cntlr_gen_client_steer_request() => issue BTM in ESL via hostap
**src/steer_module.c**
cntlr_maybe_steer_sta() is the function, that uses plugin in following way
``` C
cntlr_maybe_steer_sta()
struct steer_control *sc
sc->steer(sc->priv, s);
```
**src/plugins/steer/rcpi/rcpi.c**
``` C
struct steer_control rcpi = {
.name = "rcpi",
.init = rcpi_steer_init,
.config = rcpi_steer_config,
.exit = rcpi_steer_exit,
.steer = rcpi_steer,
};
```
``` C
int rcpi_steer(void *priv, struct steer_sta *s)
if ((b->rcpi - s->best->rcpi) > sctrl->diffsnr)
s->best = b;
s->reason = STEER_REASON_LOW_RCPI;
s->verdict = STEER_VERDICT_OK;
return 0;
```
Functions where the conditions for reporting a probable STA steering candidate is set
- We only configure bandsteer (allow steering to another band) via config for now.
- The RCPI we use in config is only used for STA Link trigger in agents, the rcpi_threshold is however not directly used in example plugin code as of now.
- diffsnr is hardcoded to 10, not set by config yet.
- these are the only configurable checks we have in plugin:
a. if (b->rcpi - s->best->rcpi) > sctrl->diffsnr)
b. if (sctrl->bandsteer)
**src/cntlr.c**
``` C
void run_controller(void)
if (!list_empty(&c->sclist)) {
scfg.rcpi_threshold = 100; /* unused! */
scfg.rcpi_hysteresis = 5; /* unused! */
scfg.rcpi_diffsnr = 10; /* hardcoded */
scfg.bandsteer = c->cfg.bandsteer;
cntlr_configure_steer_module(c, &scfg);
```
**src/steer_module.c**
``` C
int cntlr_configure_steer_module(struct controller *c, struct steer_config *cfg)
return sc->config(sc->priv, cfg);
```
**src/plugins/steer/rcpi/rcpi.c**
``` C
struct steer_control rcpi = {
.name = "rcpi",
.init = rcpi_steer_init,
.config = rcpi_steer_config,
.exit = rcpi_steer_exit,
.steer = rcpi_steer,
};
```
``` C
static int rcpi_steer_config(void *priv, struct steer_config *cfg)
{
p->rcpi_threshold = cfg->rcpi_threshold;
p->hysteresis = cfg->rcpi_hysteresis;
p->diffsnr = cfg->rcpi_diffsnr;
p->bandsteer = cfg->bandsteer;
}
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment