From 669c011f6b95f173facfafc7967d71e90c66cbe8 Mon Sep 17 00:00:00 2001 From: Jakob Olsson <jakob.olsson@iopsys.eu> Date: Tue, 5 Nov 2024 17:22:14 +0100 Subject: [PATCH] uband steer: steer from 2.4GHz to 5/6GHz --- src/cntlr.c | 34 +++++++++++++ src/cntlr.h | 4 ++ src/cntlr_map.c | 60 ++++++++++++++++++++++- src/cntlr_map.h | 2 +- src/config.c | 62 ++++++++++++++++++++++++ src/config.h | 5 ++ src/plugins/steer/rcpi/rcpi.c | 91 ++++++++++++++++++++++++++++++++++- src/steer.h | 3 ++ 8 files changed, 257 insertions(+), 4 deletions(-) diff --git a/src/cntlr.c b/src/cntlr.c index d2d619aa..d5764c25 100644 --- a/src/cntlr.c +++ b/src/cntlr.c @@ -696,6 +696,32 @@ static void cntlr_btm_req_timer_cb(atimer_t *t) } } +static void cntlr_uband_steer_timer_cb(atimer_t *t) +{ + trace("%s:--->\n", __func__); + + struct sta *s = container_of(t, struct sta, uband_steer_timer); + struct node *n = s->fh->agent; + struct controller *c = n->cntlr; + struct steer_control_config *scc; + + + scc = get_steer_control_config(c); + if (!scc) + return; + + if (!scc->enable_uband_steer) + return; + + cntlr_get_bcn_metrics(c, s, false); + + s->uband_steer_attmpts++; + s->uband_steer = true; + cntlr_err(LOG_STEER, "TRIGGER UBAND STEERING attempt:%d!!!\n", s->uband_steer_attmpts); + if (s->uband_steer_attmpts < scc->uband_max_retries) + timer_set(&s->uband_steer_timer, scc->uband_retry_interval * 1000); +} + static int cntlr_steer_sta(struct controller *c, struct sta *s, struct wifi_sta_meas_report *to, uint32_t mode, uint32_t reason) @@ -841,6 +867,9 @@ static void cntlr_configure_steer(struct controller *c, struct sta *s, /* bandsteer */ scfg.bandsteer = e->bandsteer; + /* ubandsteer */ + scfg.uband_min_rcpi = e->uband_min_rcpi; + scfg.uband_max_degradation = e->uband_max_degradation; /* maximum number of btm tries before assoc control */ /* TODO: use c->cfg */ scfg.max_btm_attempt = DEFAULT_MAX_BTM_ATTEMPT; @@ -863,7 +892,10 @@ static void cntlr_try_steer_sta(struct controller *c, struct sta *s) memcpy(candidate.bssid, s->bssid, 6); + candidate.uband_steer = s->uband_steer; + s->uband_steer = false; /* check if sta should be steered */ + cntlr_err(LOG_STEER, "uband_steer:%d\n", candidate.uband_steer); ret = cntlr_maybe_steer_sta(c, &candidate); if (ret) { cntlr_err(LOG_STEER, @@ -1036,6 +1068,7 @@ struct sta *cntlr_add_sta(struct controller *c, uint8_t *macaddr) list_add(&s->list, &c->stalist); timer_init(&s->bcn_metrics_timer, cntlr_bcn_metrics_parse); timer_init(&s->btm_req_timer, cntlr_btm_req_timer_cb); + timer_init(&s->uband_steer_timer, cntlr_uband_steer_timer_cb); allmac_insert(&c->mac_table, macaddr, MAC_ENTRY_BSTA, (void *)s); @@ -1326,6 +1359,7 @@ static void cntlr_remove_sta(struct controller *c, struct sta *s) cntlr_clean_bcnreqlist_sta(c, s); free(s->de_sta); timer_del(&s->bcn_metrics_timer); + timer_del(&s->uband_steer_timer); list_del(&s->list); /* remove from stalist */ free(s); diff --git a/src/cntlr.h b/src/cntlr.h index 96ee5b10..4a30dd9d 100644 --- a/src/cntlr.h +++ b/src/cntlr.h @@ -140,6 +140,10 @@ struct sta { #define BTM_RESP_EXP_TIMEOUT 5 atimer_t btm_req_timer; + bool uband_steer; + int uband_steer_attmpts; + atimer_t uband_steer_timer; + struct list_head list; }; diff --git a/src/cntlr_map.c b/src/cntlr_map.c index 51dde44b..42fd2efb 100644 --- a/src/cntlr_map.c +++ b/src/cntlr_map.c @@ -223,6 +223,52 @@ int handle_topology_notification(void *cntlr, struct cmdu_buff *cmdu, return -1; } + if (tv[1][0]) { + struct tlv_client_assoc_event *tlv = (struct tlv_client_assoc_event *) tv[1][0]->data; + struct sta *s; + struct netif_iface *fh, *bsta; + + fh = cntlr_iterate_fbss(c, tlv->bssid); + if (!fh) + return -1; + + s = cntlr_add_sta(c, tlv->macaddr); + if (!s) + return -1; + + if (!(tlv->event & CLIENT_EVENT_MASK)) { + timer_del(&s->uband_steer_timer); + return -1; + } + + err("|%s:%d|\n", __func__, __LINE__); + memcpy(s->bssid, tlv->bssid, 6); + s->fh = fh; + if (fh->band == BAND_2) { + struct steer_control_config *scc; + + s->uband_steer_attmpts = 0; + scc = get_steer_control_config(c); + if (scc && scc->enable_uband_steer) + timer_set(&s->uband_steer_timer, 0); + } else + timer_del(&s->uband_steer_timer); + + bsta = cntlr_iterate_fbss(c, tlv->macaddr); + if (bsta) { + /* The client is an agent and the iface is a bSTA */ + memcpy(bsta->upstream_bssid, tlv->bssid, 6); + /* bsta - unmark bbss & fbss */ + bsta->bss->is_bbss = false; + bsta->bss->is_fbss = false; + bsta->bss->enabled = true; + s->type = IEEE1905; + s->agent = bsta->agent; + //s->de_sta->mapsta.failed_steer_attempts = 0; + //timestamp_reset(s->stats.last_steer_time); + } + } + return 0; } @@ -613,6 +659,16 @@ int handle_topology_response(void *cntlr, struct cmdu_buff *cmdu, struct node *n memcpy(s->bssid, bssid, 6); s->fh = fh; + if (fh->band == BAND_2) { + struct steer_control_config *scc; + + scc = get_steer_control_config(c); + if (scc && scc->enable_uband_steer && + s->uband_steer_attmpts == 0) + timer_set(&s->uband_steer_timer, 0); + } else + timer_del(&s->uband_steer_timer); + s->de_sta->conn_time = conntime; bsta = cntlr_iterate_fbss(c, macaddr); @@ -2396,7 +2452,7 @@ void cntlr_mark_bcnlist_stale(struct controller *c, struct sta *s) } } -static void cntlr_get_bcn_metrics(struct controller *c, struct sta *s, bool match_band) +void cntlr_get_bcn_metrics(struct controller *c, struct sta *s, bool match_band) { int num_req = 0; int wt = BCN_REPORT_STALE_TIME; @@ -2551,7 +2607,7 @@ int handle_sta_link_metrics_response(void *cntlr, struct cmdu_buff *cmdu, } } } else if (s->type == NON_IEEE1905 && - s->de_sta->rcpi >= rp->report_rcpi_threshold) { + s->de_sta->rcpi >= rp->report_rcpi_threshold && !s->uband_steer) { if (scc->use_bcn_metrics && timer_pending(&s->bcn_metrics_timer)) { cntlr_mark_bcnlist_stale(c, s); timer_del(&s->bcn_metrics_timer); diff --git a/src/cntlr_map.h b/src/cntlr_map.h index 9ada0cb0..106f0143 100644 --- a/src/cntlr_map.h +++ b/src/cntlr_map.h @@ -21,7 +21,7 @@ uint16_t send_cmdu(struct controller *a, struct cmdu_buff *cmdu); extern int handle_link_metrics_response(struct controller *c, struct cmdu_buff *cmdu, struct node *n); int cntlr_set_link_profile(struct controller *c, struct node *n, struct cmdu_buff *cmdu); - +void cntlr_get_bcn_metrics(struct controller *c, struct sta *s, bool match_band); //struct cntlr_ackq_cookie *cntlr_alloc_ackq_cookie(struct cmdu_buff *cmdu); //void cntlr_free_ackq_cookie(struct agent_ackq_cookie *c); diff --git a/src/config.c b/src/config.c index 2d5f8d65..ef52565b 100644 --- a/src/config.c +++ b/src/config.c @@ -836,6 +836,13 @@ static int cntlr_config_get_steer_params(struct controller_config *cc, STEER_RETRY_ITV, STEER_ITV, STEER_DISABLE_ITV, +#if 1 + STEER_UBAND_MIN_RCPI, + STEER_UBAND_MAX_DEGRADATION, + STEER_UBAND_ENABLE, + STEER_UBAND_MAX_RETRIES, + STEER_UBAND_INTERVAL, +#endif NUM_STEER_ATTRS }; const struct uci_parse_option opts[] = { @@ -856,6 +863,13 @@ static int cntlr_config_get_steer_params(struct controller_config *cc, [STEER_RETRY_ITV] = { .name = "steer_retry_int", .type = UCI_TYPE_STRING }, [STEER_ITV] = { .name = "steer_int", .type = UCI_TYPE_STRING }, [STEER_DISABLE_ITV] = { .name = "steer_disable_int", .type = UCI_TYPE_STRING }, +#if 1 + [STEER_UBAND_MIN_RCPI] = { .name = "uband_steer_min_rcpi", .type = UCI_TYPE_STRING }, + [STEER_UBAND_MAX_DEGRADATION] = { .name = "uband_max_degradation", .type = UCI_TYPE_STRING }, + [STEER_UBAND_ENABLE] = { .name = "enable_uband_steer", .type = UCI_TYPE_STRING }, + [STEER_UBAND_MAX_RETRIES] = { .name = "uband_max_retries", .type = UCI_TYPE_STRING }, + [STEER_UBAND_INTERVAL] = { .name = "uband_retry_interval", .type = UCI_TYPE_STRING }, +#endif }; struct uci_option *tb[NUM_STEER_ATTRS]; struct steer_control_config *sc; @@ -904,6 +918,13 @@ static int cntlr_config_get_steer_params(struct controller_config *cc, sc->enable_bsta_steer = (atoi(val) == 1 ? true : false); } + if (tb[STEER_UBAND_ENABLE]) { + const char *val = tb[STEER_UBAND_ENABLE]->v.string; + + sc->enable_uband_steer = (atoi(val) == 1 ? true : false); + } + + if (tb[STEER_BCN_METRICS]) { const char *val = tb[STEER_BCN_METRICS]->v.string; @@ -1026,6 +1047,47 @@ static int cntlr_config_get_steer_params(struct controller_config *cc, sc->steer_disable_int = itv * 1000; } + sc->uband_min_rcpi = 130; + if (tb[STEER_UBAND_MIN_RCPI]) { + const char *val = tb[STEER_UBAND_MIN_RCPI]->v.string; + int rcpi; + + rcpi = atoi(val); + if (rcpi > 0 && rcpi <= 220) + sc->uband_min_rcpi = rcpi; + } + + sc->uband_max_degradation = 30; + if (tb[STEER_UBAND_MAX_DEGRADATION]) { + const char *val = tb[STEER_UBAND_MAX_DEGRADATION]->v.string; + int rcpi; + + rcpi = atoi(val); + if (rcpi > 0 && rcpi <= 220) + sc->uband_max_degradation = rcpi; + } + + + sc->uband_max_retries = 5; + if (tb[STEER_UBAND_MAX_RETRIES]) { + const char *val = tb[STEER_UBAND_MAX_RETRIES]->v.string; + int retries; + + retries = atoi(val); + if (retries > 0 && retries <= 255) + sc->uband_max_retries = retries; + } + + sc->uband_retry_interval = 120; + if (tb[STEER_UBAND_INTERVAL]) { + const char *val = tb[STEER_UBAND_INTERVAL]->v.string; + int intv; + + intv = atoi(val); + if (intv > 0) + sc->uband_retry_interval = intv; + } + return 0; } diff --git a/src/config.h b/src/config.h index cafd5437..095fad66 100644 --- a/src/config.h +++ b/src/config.h @@ -128,6 +128,7 @@ struct steer_control_config { bool plugin_enabled; bool enable_sta_steer; bool enable_bsta_steer; + bool enable_uband_steer; bool use_bcn_metrics; bool use_usta_metrics; bool bandsteer; @@ -144,6 +145,10 @@ struct steer_control_config { uint32_t steer_retry_int; /* milliseconds */ uint32_t steer_int; /* milliseconds */ uint32_t steer_disable_int; /* milliseconds */ + uint8_t uband_min_rcpi; + uint8_t uband_max_degradation; + uint8_t uband_max_retries; + int uband_retry_interval; struct list_head list; }; diff --git a/src/plugins/steer/rcpi/rcpi.c b/src/plugins/steer/rcpi/rcpi.c index 9034b0fd..f7f4b5c8 100644 --- a/src/plugins/steer/rcpi/rcpi.c +++ b/src/plugins/steer/rcpi/rcpi.c @@ -26,13 +26,16 @@ #define DEFAULT_RCPI_THRESHOLD 86 /* = -67 dBm */ #define DEFAULT_RCPI_HYSTERESIS 10 /* = 5dBm */ #define DEFAULT_RCPI_DIFFSNR 16 /* = 8dB */ - +#define DEFAULT_UBAND_MIN_RCPI 130 +#define DEFAULT_UBAND_MAX_DEGRADATION 30 struct rcpi_steer_control { uint8_t diffsnr; uint8_t low; uint8_t hysteresis; uint8_t rcpi_threshold; uint8_t max_btm_attempt; + uint8_t uband_max_degradation; + uint8_t uband_min_rcpi; bool bandsteer; void *self; }; @@ -77,6 +80,87 @@ int rcpi_steer(void *priv, struct steer_sta *s) "%s: Configured RCPI steering threshold = %u\n", __func__, sctrl->rcpi_threshold); +#if 1 /* extra band_stere logic */ + /* + band_steer_min '115' # minimum 115 RCPI acceptable as unsolicted band steer target + band_steer_degredation '10' # accept 10 RCPI signal strength degredation for unsolicited band steer + */ + /* unsolicited band steer attempt */ + if (s->uband_steer) { + cntlr_err(LOG_STEER, "%s: UBAND STEER ATTEMPT\n", __func__); + if (list_empty(s->meas_reportlist)) { + cntlr_err(LOG_STEER, + "%s: No Beacon reports available yet from STA " MACFMT "\n", + __func__, MAC2STR(s->sta->macaddr)); + s->verdict = STEER_VERDICT_NOK; + return 0; + } + + /* Set temporary best - fresh for current BSS */ + s->best = NULL; + list_for_each_entry(b, s->meas_reportlist, list) { + if (!b->stale && !memcmp(b->bssid, s->bssid, 6) && !s->best) { + /* Current BSS's measurement is set as best */ + current_bss_rcpi = b->rcpi; + s->best = b; + cntlr_err(LOG_STEER, + "%s: new best (local) rcpi:%u based on measurement report\n", + __func__, current_bss_rcpi); + break; + } + } + + list_for_each_entry(b, s->meas_reportlist, list) { + cntlr_err(LOG_STEER, "bcn-resp: {bssid:"MACFMT", rcpi:%u, opclass:%u, channel:%u}\n", MAC2STR(b->bssid), b->rcpi, b->opclass, b->channel); + + if (b->stale) + continue; + + cntlr_err(LOG_STEER, "|%s:%d| curr_bss_rcpi:%d\n", __func__, __LINE__, current_bss_rcpi); + + if (wifi_opclass_get_band(b->opclass) == BAND_2) + continue; + + cntlr_err(LOG_STEER, "b->rcpi:%u uband_min_rcpi:%u current_bss_rcpi:%u max_degradation:%u\n", b->rcpi, sctrl->uband_min_rcpi /* band_steer_min */, current_bss_rcpi, sctrl->uband_max_degradation); + + + if (!s->best || wifi_opclass_get_band(s->best->opclass) == BAND_2) { + + if (b->rcpi < sctrl->uband_min_rcpi /* band_steer_min */ || (current_bss_rcpi - b->rcpi) > sctrl->uband_max_degradation /* band_steer_degredation */) + continue; + } + + if (s->best && wifi_opclass_get_band(s->best->opclass) == BAND_5 && (b->rcpi < s->best->rcpi)) + continue; + + /* Current BSS's measurement is set as best */ + current_bss_rcpi = b->rcpi; + s->best = b; + cntlr_err(LOG_STEER, + "%s: new best (local) rcpi:%u based on measurement report\n", + __func__, current_bss_rcpi); + } + + if (!s->best) { + cntlr_err(LOG_STEER, "%s: no candidates found, NOK\n", __func__); + s->verdict = STEER_VERDICT_NOK; + return 0; + } + + /* Best bssid is a current one - no need to steer */ + if (!memcmp(s->best->bssid, s->bssid, 6)) { + cntlr_err(LOG_STEER, "%s: own BSS is best - no need to steer\n", __func__); + s->verdict = STEER_VERDICT_NOK; + return 0; + } + + s->reason = STEER_REASON_OTHER; + s->verdict = STEER_VERDICT_OK; + s->mode = STEER_MODE_BTM_REQ; + return 0; + } +#endif + if (current_bss_rcpi >= sctrl->rcpi_threshold) { /* RCPI stil above threshold level */ cntlr_err(LOG_STEER, @@ -228,6 +312,9 @@ static int rcpi_steer_init(void **priv) p->hysteresis = DEFAULT_RCPI_HYSTERESIS; p->diffsnr = DEFAULT_RCPI_DIFFSNR; p->max_btm_attempt = DEFAULT_MAX_BTM_ATTEMPT; + p->uband_min_rcpi = DEFAULT_UBAND_MIN_RCPI; + p->uband_max_degradation = DEFAULT_UBAND_MAX_DEGRADATION; + cntlr_info(LOG_STEER, "%s", "RCPI based STA steering initalized"); return 0; @@ -245,6 +332,8 @@ static int rcpi_steer_config(void *priv, struct steer_config *cfg) p->diffsnr = cfg->rcpi_diffsnr; p->bandsteer = cfg->bandsteer; p->max_btm_attempt = cfg->max_btm_attempt; + p->uband_min_rcpi = cfg->uband_min_rcpi; + p->uband_max_degradation = cfg->uband_max_degradation; cntlr_err(LOG_STEER, "%s\n", __func__); diff --git a/src/steer.h b/src/steer.h index 63d73dc8..c251d58d 100644 --- a/src/steer.h +++ b/src/steer.h @@ -62,6 +62,8 @@ struct steer_config { uint8_t rcpi_diffsnr; uint8_t ch_utilization; uint8_t max_btm_attempt; + uint8_t uband_min_rcpi; + uint8_t uband_max_degradation; bool bandsteer; }; @@ -75,6 +77,7 @@ struct steer_sta { uint32_t mode; uint8_t band; uint8_t bssid[6]; + bool uband_steer; }; struct steer_control { -- GitLab