diff --git a/src/cntlr.c b/src/cntlr.c index 70d702f40d85e5d1185c7d3bc437bfc1a55d0a4a..912bf202881ce837d53cde572f760a0fbee75ce5 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 ba27a41cbdfdfba233929c51e217b4d8183b783b..e8af47f5ca251c38fbae791d8e01155cd77c7479 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 861826fbe7a9aeb6ed5fd4745285bdb224920cb5..a4577be66776930fe03f880974b8183b2f477bd3 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; }