diff --git a/src/cntlr.c b/src/cntlr.c index c0f6f7cce879bbec9be3150414c872d18a5ae04d..98e20bdbc4c5cbb33746a1457aadf20323e7bc47 100644 --- a/src/cntlr.c +++ b/src/cntlr.c @@ -521,6 +521,27 @@ struct sta *node_find_sta(struct node *n, uint8_t *macaddr) return NULL; } +void node_update_stalist(struct node *n, uint8_t *stalist, int num) +{ + struct sta *s = NULL, *tmp; + + list_for_each_entry_safe(s, tmp, &n->stalist, list) { + bool found = false; + + for (int i = 0; i < num; i++) { + if (!memcmp(s->macaddr, &stalist[i*6], 6)) { + found = true; + break; + } + } + + if (!found) { + list_del(&s->list); + n->sta_count--; + } + } +} + struct unassoc_sta_metrics *cntlr_find_usta_metric(struct controller *c, struct sta *s, uint8_t *agent_macaddr) diff --git a/src/cntlr.h b/src/cntlr.h index bdbf67292a861b7ea2755e4a1fb468ad6068da52..7b3595b9d7fde3bfa500a21da8ea59879be60b66 100644 --- a/src/cntlr.h +++ b/src/cntlr.h @@ -416,6 +416,7 @@ void cntrl_send_max_wifi_bh_hops_policy(struct controller *c); void node_add_sta(struct node *n, struct sta *s); void node_del_sta(struct node *n, struct sta *s); struct sta *node_find_sta(struct node *n, uint8_t *sta_macaddr); +void node_update_stalist(struct node *n, uint8_t *stalist, int num); int cntlr_register_steer_module(struct controller *c, const char *name); int cntlr_unregister_steer_module(struct controller *c, char *name); diff --git a/src/cntlr_map.c b/src/cntlr_map.c index 4a537ddb2b9cc73145f996cb7a351734e59976b4..7fcd2d82289f6c5dc4ba9f65c926a809782da147 100644 --- a/src/cntlr_map.c +++ b/src/cntlr_map.c @@ -566,19 +566,15 @@ int handle_topology_response(void *cntlr, struct cmdu_buff *cmdu, struct node *n #endif if (tv[TOPOLOGY_RESPONSE_ASSOCIATED_CLIENTS_IDX][0]) { - struct tlv_assoc_client *tlv; - uint8_t *tv_data; + struct tlv_assoc_client *tlv = (struct tlv_assoc_client *) + tv[TOPOLOGY_RESPONSE_ASSOCIATED_CLIENTS_IDX][0]->data; + uint8_t *tv_data = (uint8_t *)tlv; int i, offset = 0; - tlv = (struct tlv_assoc_client *) - tv[TOPOLOGY_RESPONSE_ASSOCIATED_CLIENTS_IDX][0]->data; if (!tlv) return -1; - tv_data = (uint8_t *)tlv; - offset += 1; /* num_bss */ - for (i = 0; i < tlv->num_bss; i++) { struct netif_iface *bss_iface; uint8_t bssid[6] = {0}; @@ -597,70 +593,81 @@ int handle_topology_response(void *cntlr, struct cmdu_buff *cmdu, struct node *n continue; } - for (j = 0; j < num_client; j++) { - struct netif_iface *bsta_iface = NULL; - uint8_t macaddr[6] = {0}; - uint16_t conntime; - enum sta_state old_state; - struct sta *s; + if (num_client > 0) { + uint8_t stas[num_client * 6]; + int idx = 0; - memcpy(macaddr, &tv_data[offset], 6); - offset += 6; /* macaddr */ - conntime = BUF_GET_BE16(tv_data[offset]); - offset += 2; /* conntime */ + memset(stas, 0, sizeof(stas)); - bsta_iface = cntlr_find_iface_type(c, macaddr, MAC_ENTRY_BSTA); + for (j = 0; j < num_client; j++) { + struct netif_iface *bsta_iface = NULL; + uint8_t macaddr[6] = {0}; + uint16_t conntime; + struct sta *s; - s = cntlr_find_sta(c->sta_table, macaddr); - if (!s) { - s = cntlr_add_sta(c, c->sta_table, macaddr); + memcpy(macaddr, &tv_data[offset], 6); + memcpy(&stas[6*idx++], &tv_data[offset], 6); + offset += 6; /* macaddr */ + conntime = BUF_GET_BE16(tv_data[offset]); + offset += 2; /* conntime */ + + bsta_iface = cntlr_find_iface_type(c, macaddr, MAC_ENTRY_BSTA); + + s = cntlr_find_sta(c->sta_table, macaddr); if (!s) { - cntlr_dbg(LOG_STA, "%s: failed to add STA " MACFMT "\n", - __func__, MAC2STR(macaddr)); - continue; + struct cmdu_buff *txcmdu; + + s = cntlr_add_sta(c, c->sta_table, macaddr); + if (!s) { + cntlr_dbg(LOG_STA, "%s: failed to add STA " MACFMT "\n", + __func__, MAC2STR(macaddr)); + continue; + } + + s->state = STA_CONNECTED; + memcpy(s->bssid, bssid, 6); + memset(s->ssid, 0, sizeof(s->ssid)); + memcpy(s->ssid, bss_iface->bss->ssid, bss_iface->bss->ssidlen); + s->ssidlen = bss_iface->bss->ssidlen; + s->de_sta->conn_time = conntime; + s->assoc_time = time(NULL) - conntime; + + node_add_sta(n, s); + cntlr_dbg(LOG_STA, "%s: STA " MACFMT " connected to Node " MACFMT "\n", + __func__, MAC2STR(s->macaddr), MAC2STR(n->almacaddr)); + + txcmdu = cntlr_gen_client_caps_query(c, + c->almacaddr, + s->macaddr, + s->bssid); + if (txcmdu) { + send_cmdu(c, txcmdu); + cmdu_free(txcmdu); + } + } else { + /* ignore conflicting STA-association from multiple Agents */ + if (memcmp(s->agent_almacaddr, n->almacaddr, 6) || + memcmp(s->bssid, bssid, 6)) { + continue; + } + + s->de_sta->conn_time = conntime; } - 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)); - memcpy(s->ssid, bss_iface->bss->ssid, bss_iface->bss->ssidlen); - s->ssidlen = bss_iface->bss->ssidlen; - - s->de_sta->conn_time = conntime; - s->state = conntime != 0 ? STA_ASSOCIATED : STA_DISCONNECTED; - if (old_state != STA_ASSOCIATED && s->state == STA_ASSOCIATED) { - struct cmdu_buff *txcmdu; - - node_add_sta(n, s); - time(&s->assoc_time); - txcmdu = cntlr_gen_client_caps_query(c, - c->almacaddr, - s->macaddr, - s->bssid); - if (txcmdu) { - send_cmdu(c, txcmdu); - cmdu_free(txcmdu); - } - } else if (old_state != STA_DISCONNECTED && s->state == STA_DISCONNECTED) { - node_del_sta(n, s); - time(&s->disassoc_time); - } + s->is_bsta = bsta_iface || bss_iface->bss->is_bbss ? true : false; + if (bsta_iface) { + memcpy(bsta_iface->upstream_bssid, bssid, 6); - if (bsta_iface) { - memcpy(bsta_iface->upstream_bssid, bssid, 6); + /* Since bsta interface, unset bbss & fbss */ + bsta_iface->bss->is_bbss = false; + bsta_iface->bss->is_fbss = false; + bsta_iface->bss->enabled = true; + } - /* Since bsta interface, unset bbss & fbss */ - bsta_iface->bss->is_bbss = false; - bsta_iface->bss->is_fbss = false; - bsta_iface->bss->enabled = true; + cntlr_update_sta_steer_data(c, s); } - cntlr_update_sta_steer_data(c, s); + node_update_stalist(n, stas, idx); } } }