diff --git a/src/agent.c b/src/agent.c index 5542f2c2c5dc866ef8df4818eec1f2b3c76751dd..3b3b85aa5d6b4ae51a127a5a23f356b7573cd22e 100644 --- a/src/agent.c +++ b/src/agent.c @@ -1065,12 +1065,23 @@ static int steer_sta_legacy(struct sta *s) return 0; } +/* Translate internal 'pref_neighbor' to wifi's 'nbr' struct */ +void agent_pref_neighbor_to_nbr(struct pref_neighbor *pref_nbr_src, + struct nbr *wifi_nbr_dst) +{ + memcpy(wifi_nbr_dst->bssid, pref_nbr_src->bssid, 6); + wifi_nbr_dst->bssid_info = pref_nbr_src->bssid_info; + wifi_nbr_dst->reg = pref_nbr_src->reg; + wifi_nbr_dst->channel = pref_nbr_src->channel; + wifi_nbr_dst->phy = pref_nbr_src->phy; +} + static int steer_sta(struct sta *s, struct pref_neighbor *pref_nbr) { struct netif_fh *vif = s->vif; struct agent *a = vif->agent; - struct pref_neighbor *wifi_nbr_el; - struct nbr pref_nbr_el = {}; + struct pref_neighbor *pref_nbr_el; + struct nbr wifi_nbr_el = {}; int ret = 0; s->steer_secs++; @@ -1078,7 +1089,7 @@ static int steer_sta(struct sta *s, struct pref_neighbor *pref_nbr) MAC2STR(s->macaddr), s->steer_secs); if (pref_nbr) { - wifi_nbr_el = pref_nbr; + pref_nbr_el = pref_nbr; } else { if (list_empty(&s->pref_nbrlist)) { trace("No better BSS for STA " MACFMT " found\n", @@ -1086,21 +1097,17 @@ static int steer_sta(struct sta *s, struct pref_neighbor *pref_nbr) return 0; } - wifi_nbr_el = list_first_entry(&s->pref_nbrlist, + pref_nbr_el = list_first_entry(&s->pref_nbrlist, struct pref_neighbor, list); } - if (!wifi_nbr_el) { - warn("Unexpected! wifi_nbr_el is NULL or empty!\n"); + if (!pref_nbr_el) { + warn("Unexpected! pref_nbr_el is NULL or empty!\n"); return -1; } /* Translate internal 'pref_neighbor' to wifi's 'nbr' struct */ - memcpy(pref_nbr_el.bssid, wifi_nbr_el->bssid, 6); - pref_nbr_el.bssid_info = wifi_nbr_el->bssid_info; - pref_nbr_el.reg = wifi_nbr_el->reg; - pref_nbr_el.channel = wifi_nbr_el->channel; - pref_nbr_el.phy = wifi_nbr_el->phy; + agent_pref_neighbor_to_nbr(pref_nbr_el, &wifi_nbr_el); /* btm steer ? */ if (!s->steer_btm_cnt) { @@ -1108,10 +1115,10 @@ static int steer_sta(struct sta *s, struct pref_neighbor *pref_nbr) info("Try {%d} to BTM Steer " MACFMT " =======>\n", s->steer_btm_cnt, MAC2STR(s->macaddr)); - ret = wifi_req_bss_transition(vif->name, s->macaddr, 1, &pref_nbr_el, 0); + ret = wifi_req_bss_transition(vif->name, s->macaddr, 1, &wifi_nbr_el, 0); if (!ret) { wifiagent_log_steer(a, s->macaddr, vif->name, - "steer_btmreq", pref_nbr_el.bssid); + "steer_btmreq", wifi_nbr_el.bssid); } else { warn("Failed to send BTM request to " MACFMT "\n", MAC2STR(s->macaddr)); @@ -1130,10 +1137,10 @@ static int steer_sta(struct sta *s, struct pref_neighbor *pref_nbr) s->steer_btm_cnt, MAC2STR(s->macaddr)); ret = wifi_req_bss_transition(vif->name, s->macaddr, - 1, &pref_nbr_el, 0); + 1, &wifi_nbr_el, 0); if (!ret) wifiagent_log_steer(a, s->macaddr, vif->name, - "steer_btmreq", pref_nbr_el.bssid); + "steer_btmreq", wifi_nbr_el.bssid); else warn("Failed to send BTM request to " MACFMT "\n", MAC2STR(s->macaddr)); @@ -7007,7 +7014,7 @@ int wifiagent_steer_sta(struct ubus_context *ctx, { struct agent *a = this_agent; struct sta *s; - struct nbr *pref_nbr_list = NULL; + struct nbr *wifi_nbr_list = NULL; int i; int ret = 0; @@ -7047,25 +7054,21 @@ int wifiagent_steer_sta(struct ubus_context *ctx, } /* Translate internal 'pref_neighbor' to wifi's 'nbr' struct */ - pref_nbr_list = calloc(prefcnt, sizeof(struct nbr)); - if (WARN_ON(!pref_nbr_list)) + wifi_nbr_list = calloc(prefcnt, sizeof(struct nbr)); + if (WARN_ON(!wifi_nbr_list)) return -ENOMEM; for (i = 0; i < prefcnt; i++) { - memcpy(pref_nbr_list[i].bssid, pref[i].bssid, 6); - pref_nbr_list[i].bssid_info = pref[i].bssid_info; - pref_nbr_list[i].reg = pref[i].reg; - pref_nbr_list[i].channel = pref[i].channel; - pref_nbr_list[i].phy = pref[i].phy; + agent_pref_neighbor_to_nbr(&pref[i], &wifi_nbr_list[i]); } - ret = wifi_req_bss_transition(ifname, s->macaddr, prefcnt, pref_nbr_list, 0); + ret = wifi_req_bss_transition(ifname, s->macaddr, prefcnt, wifi_nbr_list, 0); if (ret) dbg("Failed to send BTM request to " MACFMT "\n", MAC2STR(s->macaddr)); - free(pref_nbr_list); + free(wifi_nbr_list); return ret; } diff --git a/src/agent.h b/src/agent.h index 7bc09e57f9d4debef57e10901767fecd3804cfbc..5eb77567877f0479d09fa5aafa26a9b947402daf 100644 --- a/src/agent.h +++ b/src/agent.h @@ -905,5 +905,7 @@ struct netif_wds *netif_alloc_wds(struct agent *a, const char *ifname); void netif_free_wds(struct netif_wds *n); void netif_free_wds_by_ifname(struct agent *a, const char *ifname); struct netif_wds *find_wds_by_ifname(struct agent *a, const char *ifname); +void agent_pref_neighbor_to_nbr(struct pref_neighbor *pref_nbr_src, + struct nbr *wifi_nbr_dst); #endif /* AGENT_H */ diff --git a/src/agent_map.c b/src/agent_map.c index 6bc16308abf9958aed6b2c4e68db79031cb700ab..e2cf04f90da363da4d405e809959ad949f2b7bae 100644 --- a/src/agent_map.c +++ b/src/agent_map.c @@ -3822,7 +3822,7 @@ int agent_send_request_transition(void *agent, uint8_t *client_sta, * & channel utilization. */ int agent_find_best_bssid_for_sta(struct agent *a, uint8_t *sta, uint8_t *src_bssid, - uint8_t *out_bssid) + struct pref_neighbor *best_target) { struct netif_fh *p; int ret = 0; @@ -3835,11 +3835,11 @@ int agent_find_best_bssid_for_sta(struct agent *a, uint8_t *sta, uint8_t *src_bs /* FIXME: using first non-self fh bssid */ ret = memcmp(src_bssid, p->bssid, 6); if (ret != 0) { - memcpy(out_bssid, p->bssid, 6); + memcpy(best_target->bssid, p->bssid, 6); return 0; } } - memcpy(out_bssid, src_bssid, 6); + memcpy(best_target->bssid, src_bssid, 6); return 0; } @@ -4165,17 +4165,20 @@ static int agent_sta_disallowed(struct agent *a, } static int agent_try_steer_sta(struct agent *a, struct netif_fh *fh, - uint8_t *src_bssid, uint8_t *sta_mac, uint8_t *dst_bssid, + uint8_t *src_bssid, uint8_t *sta_mac, struct pref_neighbor *pref_target, struct sta_error_response *sta_resp, int count, uint8_t req_mode) { trace("agent: %s: --->\n", __func__); - uint8_t target_bssid[6] = { 0 }; + struct pref_neighbor target = {}; int ret = 0; int i; dbg("steered STA mac: " MACFMT "\n", MAC2STR(sta_mac)); - dbg("target bssid: " MACFMT "\n", MAC2STR(dst_bssid)); + if (pref_target) + dbg("target bssid: " MACFMT "\n", MAC2STR(pref_target->bssid)); + else + dbg("target bssid unspecified!\n"); /* Check if STA is allowed for steering */ ret = agent_sta_disallowed(a, sta_mac, STA_DISALLOWED_LOCAL); @@ -4195,23 +4198,22 @@ static int agent_try_steer_sta(struct agent *a, struct netif_fh *fh, return -1; } - /* Calculate target bssid for this STA */ - if (is_wildcard_bssid(dst_bssid)) - ret = agent_find_best_bssid_for_sta(a, sta_mac, src_bssid, target_bssid); - else - memcpy(target_bssid, dst_bssid, 6); - - if (ret) - return -1; + if (pref_target && !is_wildcard_bssid(pref_target->bssid)) + /* Target specified directly in Steering Request TLV */ + memcpy(&target, pref_target, sizeof(struct pref_neighbor)); + else { + /* Best target BSSID for this STA has to be found */ + ret = agent_find_best_bssid_for_sta(a, sta_mac, src_bssid, &target); + if (ret) + return -1; + } /* Check if STA is disallowed from BTM steering */ ret = agent_sta_disallowed(a, sta_mac, STA_DISALLOWED_BTM); if (!ret) { - struct nbr pref; - - memcpy(pref.bssid, target_bssid, 6); + struct nbr pref = {}; - /* TODO: pref.channel & pref.reg from controller */ + agent_pref_neighbor_to_nbr(&target, &pref); /* BTM steering */ ret = agent_send_request_transition(a, sta_mac, fh, &pref, 0); @@ -4224,7 +4226,7 @@ static int agent_try_steer_sta(struct agent *a, struct netif_fh *fh, ",\"dst_bssid\":\""MACFMT"\"}", MAC2STR(sta_mac), MAC2STR(src_bssid), - MAC2STR(target_bssid)); + MAC2STR(target.bssid)); agent_notify_iface_event(a, fh->name, "request_btm", ev_data); } @@ -4251,7 +4253,6 @@ int agent_process_steer_request_tlv(void *agent, struct sta *s; struct sta_error_response sta_resp[MAX_STA]; uint32_t count = 0; - uint8_t wildcard[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; uint8_t mode = 0x00; uint8_t req_mode = 0x00; uint16_t op_window; @@ -4259,11 +4260,7 @@ int agent_process_steer_request_tlv(void *agent, uint8_t num_sta; uint8_t *stalist = NULL; uint8_t num_bss; - struct bss_data{ - uint8_t bssid[6]; - uint8_t opclass; - uint8_t channel; - } *barray = NULL; + struct pref_neighbor *pref_arr = NULL; uint8_t *data = (uint8_t *)p; memcpy(bssid, &data[offset], 6); @@ -4348,8 +4345,8 @@ int agent_process_steer_request_tlv(void *agent, } if (num_bss > 0) { - barray = calloc(num_bss, sizeof(struct bss_data)); - if (!barray) { + pref_arr = calloc(num_bss, sizeof(struct pref_neighbor)); + if (!pref_arr) { dbg("%s:%d -ENOMEM\n", __func__, __LINE__); ret = -1; goto out; @@ -4357,10 +4354,14 @@ int agent_process_steer_request_tlv(void *agent, } for (i = 0; i < num_bss; i++) { - memcpy(barray[i].bssid, &data[offset], 6); + memcpy(pref_arr[i].bssid, &data[offset], 6); offset += 6; - barray[i].opclass = data[offset++]; - barray[i].channel = data[offset++]; + /* Target BSS Operating Class */ + pref_arr[i].reg = data[offset++]; + /* Target BSS Channel Number for channel on which + * the Target BSS is transmitting Beacon frames. + */ + pref_arr[i].channel = data[offset++]; } /* Check src bssid present */ @@ -4386,7 +4387,7 @@ int agent_process_steer_request_tlv(void *agent, list_for_each_entry(s, &fh->stalist, list) { /* Call for transition of sta */ ret = agent_try_steer_sta(a, fh, bssid, - s->macaddr, barray[0].bssid, + s->macaddr, &pref_arr[0], sta_resp, count, req_mode); if (ret) dbg("[%s:%d] Couldn't steer " MACFMT "\n", @@ -4415,7 +4416,7 @@ int agent_process_steer_request_tlv(void *agent, for (i = 0; i < num_sta; i++) { /* Call for transition of sta */ ret = agent_try_steer_sta(a, fh, bssid, - &stalist[i * 6], barray[i].bssid, + &stalist[i * 6], &pref_arr[i], sta_resp, count, req_mode); } } @@ -4425,7 +4426,7 @@ int agent_process_steer_request_tlv(void *agent, for (i = 0; i < num_sta; i++) { /* Call for transition of sta */ ret = agent_try_steer_sta(a, fh, bssid, - &stalist[i * 6], barray[0].bssid, + &stalist[i * 6], &pref_arr[0], sta_resp, count, req_mode); } } @@ -4435,7 +4436,7 @@ int agent_process_steer_request_tlv(void *agent, for (i = 0; i < num_sta; i++) { /* Call for transition of sta */ ret = agent_try_steer_sta(a, fh, bssid, - &stalist[i * 6], wildcard, + &stalist[i * 6], NULL, sta_resp, count, req_mode); } /* Unspecified error condition */ @@ -4452,8 +4453,8 @@ out: if (stalist) free(stalist); - if (barray) - free(barray); + if (pref_arr) + free(pref_arr); return ret; } diff --git a/src/wifi_ubus.c b/src/wifi_ubus.c index 9bab4b45d457f663ea34eaa11b8f442b6d12e8b6..f6c3e1c638926298467b72d673e10989100d57da 100644 --- a/src/wifi_ubus.c +++ b/src/wifi_ubus.c @@ -930,14 +930,32 @@ int wifi_ubus_request_transition(struct ubus_context *ubus_ctx, const char *ifna goto out; blob_buf_init(&bb, 0); + /* Client STA MAC addr */ blobmsg_add_string(&bb, "sta", macstr); + /* Target params: bssid, bssid_info, reg, channel & phy */ t = blobmsg_open_array(&bb, "target_ap"); + for (i = 0; i < pref_num; i++) { void *tt; tt = blobmsg_open_table(&bb, ""); + + /* skip if bssid is not provided */ + if (hwaddr_is_zero(pref[i].bssid)) + continue; + hwaddr_ntoa(pref[i].bssid, macstr); blobmsg_add_string(&bb, "bssid", macstr); + /* optional */ + if (pref[i].bssid_info) + blobmsg_add_u32(&bb, "bssid_info", pref[i].bssid_info); + if (pref[i].reg) + blobmsg_add_u32(&bb, "reg", pref[i].reg); + if (pref[i].channel) + blobmsg_add_u32(&bb, "channel", pref[i].channel); + if (pref[i].phy) + blobmsg_add_u32(&bb, "phy", pref[i].phy); + blobmsg_close_table(&bb, tt); } blobmsg_close_array(&bb, t);