From 0cbffdc842f56bda2ab32b58480098ab5cc94993 Mon Sep 17 00:00:00 2001
From: Filip Matusiak <filip.matusiak@iopsys.eu>
Date: Thu, 30 Jan 2025 11:28:39 +0100
Subject: [PATCH] Trigger Una STA Metrics Query when STA connected
---
src/cntlr.c | 1 +
src/cntlr_map.c | 163 ++++++++++++++++++++++++++++++------------------
src/sta.c | 1 +
3 files changed, 103 insertions(+), 62 deletions(-)
diff --git a/src/cntlr.c b/src/cntlr.c
index 70d702f4..912bf202 100644
--- a/src/cntlr.c
+++ b/src/cntlr.c
@@ -484,6 +484,7 @@ void cntlr_bcn_metrics_timer_cb(atimer_t *t)
void node_add_sta(struct node *n, struct sta *s)
{
+ memcpy(s->agent_almacaddr, n->almacaddr, 6);
list_add(&s->list, &n->stalist);
n->sta_count++;
}
diff --git a/src/cntlr_map.c b/src/cntlr_map.c
index ba27a41c..e8af47f5 100644
--- a/src/cntlr_map.c
+++ b/src/cntlr_map.c
@@ -170,6 +170,95 @@ int handle_topology_discovery(void *cntlr, struct cmdu_buff *cmdu,
return 0;
}
+int cntlr_request_usta_metrics_radio(struct controller *c, struct node *n,
+ struct netif_radio *r, uint8_t *sta_macaddr)
+{
+ struct unassoc_sta_metric metrics[1] = {};
+ struct cmdu_buff *cmdu = NULL;
+ int i;
+
+ dbg("%s: Node " MACFMT ": ap_cap = 0x%02x\n",
+ __func__, MAC2STR(n->almacaddr), n->ap_cap);
+
+ if (!(n->ap_cap & UNASSOC_STA_REPORTING_ONCHAN)) {
+ dbg("%s: Unassoc STA metric not supported by " MACFMT "\n",
+ __func__, MAC2STR(n->almacaddr));
+
+ return 0;
+ }
+
+ if (n->ap_cap & UNASSOC_STA_REPORTING_OFFCHAN) {
+ /* Off-channel set in caps, but only on-channel metrics are requested */
+ dbg("%s: Node " MACFMT " will only report On-Channel Unassoc STA metrics!\n",
+ __func__, MAC2STR(n->almacaddr));
+ }
+
+ /* Only one opclass allowed per TLV, only one TLV allowed per CMDU */
+ for (i = 0; i < r->radio_el->cur_opclass.num_opclass; i++) {
+ metrics[0].channel = r->radio_el->cur_opclass.opclass[0].channel[0].channel;
+ metrics[0].num_sta = 1;
+ memcpy(metrics[0].sta[0].macaddr, sta_macaddr, 6);
+
+ cmdu = cntlr_gen_unassoc_sta_metric_query(c,
+ n->almacaddr,
+ r->radio_el->cur_opclass.opclass[i].id,
+ 1, metrics);
+
+ if (cmdu) {
+ dbg("%s: sending usta metric query: STA " MACFMT ", NODE "\
+ MACFMT " OPCLASS %d CHANNEL %d\n", __func__,
+ MAC2STR(sta_macaddr), MAC2STR(n->almacaddr),
+ r->radio_el->cur_opclass.opclass[i].id,
+ r->radio_el->cur_opclass.opclass[i].channel[0].channel);
+ send_cmdu(c, cmdu);
+ cmdu_free(cmdu);
+ }
+ }
+
+ return 0;
+}
+
+int cntlr_request_usta_metrics(struct controller *c, struct sta *s)
+{
+ trace("%s: --->\n", __func__);
+
+ struct node *n = NULL;
+ struct netif_radio *r = NULL;
+ enum wifi_band band;
+
+ if (!c || !s)
+ return -1;
+
+ dbg("%s: STA " MACFMT "\n", __func__, MAC2STR(s->macaddr));
+
+ r = cntlr_find_radio_with_bssid(c, s->bssid);
+ if (!r) {
+ dbg("%s: Radio not found for STA " MACFMT "\n",
+ __func__, MAC2STR(s->macaddr));
+ return -1;
+ }
+
+ band = r->radio_el->band;
+
+ list_for_each_entry(n, &c->nodelist, list) {
+
+ if (hwaddr_equal(n->almacaddr, s->agent_almacaddr))
+ /* STA associated to given node, skip */
+ continue;
+
+ r = cntlr_find_radio_in_node_by_band(c, n, band);
+ if (!r) {
+ dbg("%s: Radio not found for Node " MACFMT "\n",
+ __func__, MAC2STR(n->almacaddr));
+ continue;
+ }
+
+ cntlr_request_usta_metrics_radio(c, n, r, s->macaddr);
+ }
+
+ return 0;
+}
+
int handle_topology_notification(void *cntlr, struct cmdu_buff *cmdu,
struct node *n)
{
@@ -243,8 +332,8 @@ int handle_topology_notification(void *cntlr, struct cmdu_buff *cmdu,
time(&s->assoc_time);
s->state = STA_ASSOCIATED;
- memcpy(s->agent_almacaddr, almacaddr, 6);
node_add_sta(n, s);
+ cntlr_request_usta_metrics(c, s);
return 0;
}
@@ -261,8 +350,8 @@ int handle_topology_notification(void *cntlr, struct cmdu_buff *cmdu,
if (!node_find_sta(n, ev->macaddr)) {
time(&s->assoc_time);
s->state = STA_ASSOCIATED;
- memcpy(s->agent_almacaddr, almacaddr, 6);
node_add_sta(n, s);
+ cntlr_request_usta_metrics(c, s);
}
} else {
if (!s) {
@@ -572,6 +661,7 @@ int handle_topology_response(void *cntlr, struct cmdu_buff *cmdu, struct node *n
struct netif_iface *bsta_iface = NULL;
uint8_t macaddr[6] = {0};
uint16_t conntime;
+ enum sta_state old_state;
struct sta *s;
memcpy(macaddr, &tv_data[offset], 6);
@@ -590,12 +680,12 @@ int handle_topology_response(void *cntlr, struct cmdu_buff *cmdu, struct node *n
continue;
}
- node_add_sta(n, s);
- memcpy(s->agent_almacaddr, n->almacaddr, 6);
cntlr_dbg(LOG_STA, "%s: STA " MACFMT " connected to Node " MACFMT "\n",
__func__, MAC2STR(s->macaddr), MAC2STR(n->almacaddr));
}
+ old_state = s->state;
+
s->is_bsta = bsta_iface || bss_iface->bss->is_bbss ? true : false;
memcpy(s->bssid, bssid, 6);
memset(s->ssid, 0, sizeof(s->ssid));
@@ -604,10 +694,15 @@ int handle_topology_response(void *cntlr, struct cmdu_buff *cmdu, struct node *n
s->de_sta->conn_time = conntime;
s->state = conntime != 0 ? STA_ASSOCIATED : STA_DISCONNECTED;
- if (s->state == STA_ASSOCIATED)
+ if (s->state == STA_ASSOCIATED) {
+ node_add_sta(n, s);
time(&s->assoc_time);
- else
+
+ cntlr_request_usta_metrics(c, s);
+ } else if (old_state != STA_DISCONNECTED && s->state == STA_DISCONNECTED) {
+ node_del_sta(n, s);
time(&s->disassoc_time);
+ }
if (bsta_iface) {
memcpy(bsta_iface->upstream_bssid, bssid, 6);
@@ -2152,62 +2247,6 @@ int handle_ap_metrics_response(void *cntlr, struct cmdu_buff *cmdu, struct node
return 0;
}
-int cntlr_request_usta_metrics(struct controller *c, uint8_t *agent_almacaddr,
- uint8_t *sta_macaddr, enum wifi_band band)
-{
- struct unassoc_sta_metric metrics[1] = {};
- struct cmdu_buff *cmdu = NULL;
- struct netif_radio *r;
- struct node *n;
- int j;
-
- trace("%s: --->\n", __func__);
- if (!c)
- return -1;
-
- n = cntlr_find_node(c, agent_almacaddr);
- if (!n)
- return -1;
-
- dbg("%s: Node " MACFMT ": ap_cap = 0x%02x\n", __func__, MAC2STR(n->almacaddr), n->ap_cap);
-
- if (n->ap_cap & UNASSOC_STA_REPORTING_OFFCHAN) {
- dbg("%s: Node " MACFMT " does not support Off-Channel USTA metric collection",
- __func__, MAC2STR(n->almacaddr));
- }
-
- if (!(n->ap_cap & UNASSOC_STA_REPORTING_ONCHAN)) {
- dbg("%s: Unassoc STA metric not supported by " MACFMT "\n",
- __func__, MAC2STR(n->almacaddr));
-
- return 0;
- }
-
-
- r = cntlr_find_radio_in_node_by_band(c, n, band);
- if (!r)
- return -1;
-
- for (j = 0; j < r->radio_el->cur_opclass.num_opclass; j++) {
- /* TODO: allow more than one channel */
- metrics[0].channel = r->radio_el->cur_opclass.opclass[0].channel[0].channel;
- metrics[0].num_sta = 1;
- memcpy(metrics[0].sta[0].macaddr, sta_macaddr, 6);
-
- cmdu = cntlr_gen_unassoc_sta_metric_query(c,
- n->almacaddr,
- r->radio_el->cur_opclass.opclass[j].id,
- 1, metrics);
-
- if (cmdu) {
- send_cmdu(c, cmdu);
- cmdu_free(cmdu);
- }
- }
-
- return 0;
-}
-
void cntlr_request_bcn_metrics_bsta(struct controller *c, struct sta *s, char *ssid)
{
struct cmdu_buff *bcn_cmdu;
diff --git a/src/sta.c b/src/sta.c
index 861826fb..a4577be6 100644
--- a/src/sta.c
+++ b/src/sta.c
@@ -119,6 +119,7 @@ struct sta *cntlr_add_sta(void *cntlr, struct hlist_head *table, uint8_t *macadd
idx = sta_hash(macaddr);
hlist_add_head(&s->hlist, &table[idx]);
s->cntlr = cntlr;
+ s->state = STA_UNKNOWN;
return s;
}
--
GitLab