From a45061da1e88679904406eeb2bda186a77b2458a Mon Sep 17 00:00:00 2001
From: Janusz Dziedzic <janusz.dziedzic@iopsys.eu>
Date: Mon, 20 Dec 2021 20:14:54 +0100
Subject: [PATCH] acs - channels with same performance
choose random channel from channels
with same/best performance.
Signed-off-by: Janusz Dziedzic <janusz.dziedzic@iopsys.eu>
---
src/cntlr_acs.c | 71 ++++++++++++++++++++++++++++++++++++++++++-------
src/cntlr_acs.h | 1 +
2 files changed, 62 insertions(+), 10 deletions(-)
diff --git a/src/cntlr_acs.c b/src/cntlr_acs.c
index be4d5d1c..9fc916ae 100644
--- a/src/cntlr_acs.c
+++ b/src/cntlr_acs.c
@@ -38,11 +38,15 @@
int cntlr_acs_radio_channel_recalc(struct netif_radio *radio, struct acs_params *params)
{
+ struct acs_params acs_params[64] = {};
+ int acs_params_num = 0;
struct opclass_entry *entry;
struct opclass *opclass;
int chan, pref, reas;
int pref_best = 0;
- int i, j;
+ int pref_cur = 0;
+ int prefered[64] = {0};
+ int i, j, r;
opclass = &radio->opclass;
@@ -84,23 +88,69 @@ int cntlr_acs_radio_channel_recalc(struct netif_radio *radio, struct acs_params
if (params->skip_dfs_not_available && reas != CHANNEL_PREF_REASON_DFS_AVAILABLE)
continue;
- /* Finally we are here, choose best value */
- if (pref > pref_best) {
+ if (WARN_ON(acs_params_num >= ARRAY_SIZE(acs_params)))
+ break;
+
+ /* Current channel preference */
+ if (chan == params->best_channel)
+ pref_cur = pref;
+
+ /* Kick best value */
+ if (pref > pref_best)
pref_best = pref;
- params->best_channel = chan;
- params->best_opclass = entry->opclass;
- params->best_bw = entry->bw;
- }
+ acs_params[acs_params_num].best_channel = chan;
+ acs_params[acs_params_num].best_opclass = entry->opclass;
+ acs_params[acs_params_num].best_bw = entry->bw;
+ acs_params[acs_params_num].best_pref = pref;
+
+ acs_params_num++;
}
}
- dbg("acs radio " MACFMT " best chan %d/%d opclass %d\n", MAC2STR(radio->macaddr),
- params->best_channel, params->best_bw, params->best_opclass);
-
if (!pref_best)
return -1;
+ dbg("acs radio " MACFMT " best pref %d vs current pref %d\n", MAC2STR(radio->macaddr), pref_best, pref_cur);
+
+ /* If current channel equal to best don't switch */
+ if (pref_cur == pref_best) {
+ dbg("acs skip - current channel %d is the best\n", params->best_channel);
+ return -1;
+ }
+
+ /* Get random channel from best performance */
+ for (i = 0, j = 0; i < acs_params_num; i++) {
+ if (acs_params[i].best_pref != pref_best)
+ continue;
+
+ if (j >= ARRAY_SIZE(prefered) - 1)
+ break;
+
+ /* Save index in table */
+ prefered[j] = i;
+ j++;
+ }
+
+ if (WARN_ON(!j))
+ return -1;
+
+ srand(time(NULL));
+ r = rand() % j;
+
+ dbg("acs radio " MACFMT " table size %d - rand %d, index %d\n",
+ MAC2STR(radio->macaddr), j, r, prefered[r]);
+
+ if (prefered[r] >= acs_params_num)
+ return -1;
+
+ params->best_channel = acs_params[prefered[r]].best_channel;
+ params->best_bw = acs_params[prefered[r]].best_bw;
+ params->best_opclass = acs_params[prefered[r]].best_opclass;
+
+ dbg("acs radio " MACFMT " best chan %d/%d opclass %d\n", MAC2STR(radio->macaddr),
+ params->best_channel, params->best_bw, params->best_opclass);
+
return 0;
}
@@ -155,6 +205,7 @@ void cntlr_acs_node_channel_recalc(struct node *node, bool skip_dfs)
/* Use current opclass - TODO: if no opclass check 80/40/20 */
acs_params.opclass = cur_acs_params.opclass;
+ acs_params.best_channel = cur_acs_params.best_channel;
ret = cntlr_acs_radio_channel_recalc(radio, &acs_params);
if (WARN_ON(ret))
diff --git a/src/cntlr_acs.h b/src/cntlr_acs.h
index fb1aec3c..a4788100 100644
--- a/src/cntlr_acs.h
+++ b/src/cntlr_acs.h
@@ -17,6 +17,7 @@ struct acs_params {
int best_channel;
int best_opclass;
int best_bw;
+ int best_pref;
};
int cntlr_acs_radio_channel_recalc(struct netif_radio *radio, struct acs_params *params);
--
GitLab