diff --git a/src/core/agent.c b/src/core/agent.c index 6b84b84ca5ecf746b13a9a5fb2be7e760175526d..32e63dae0ad7d8029afaafa7b1c4d3436e5a2361 100644 --- a/src/core/agent.c +++ b/src/core/agent.c @@ -150,7 +150,7 @@ static void wifiagent_log_stainfo(struct agent *a, struct sta *s) s->tx_pkts, s->rx_pkts, s->tx_fail_pkts, s->rx_fail_pkts); - trace("stainfo: %s\n", ev); + //trace("stainfo: %s\n", ev); wifiagent_notify_event(a, "wifi.sta", ev); } @@ -569,11 +569,10 @@ static int update_sta_entry(struct netif_fh *vif, struct sta *e) s->tx_fail_pkts = e->tx_fail_pkts; s->rx_fail_pkts = e->rx_fail_pkts; - loud("STA: " MACFMT " (rssi = %d) " \ + /*loud("STA: " MACFMT " (rssi = %d) " \ "Tx-bytes/sec = %u Rx-bytes/sec = %u\n", MAC2STR(s->macaddr), s->rssi[0], - s->tx_thput, s->rx_thput); - + s->tx_thput, s->rx_thput);*/ wifiagent_log_stainfo(vif->agent, s); return 0; } @@ -1121,8 +1120,8 @@ static void wifi_sta_periodic_run(struct uloop_timeout *t) if (!vif->cfg->enabled) return; - trace("%s: STA = " MACFMT " ref = %d\n", __func__, - MAC2STR(s->macaddr), s->ref); + //trace("%s: STA = " MACFMT " ref = %d\n", __func__, + // MAC2STR(s->macaddr), s->ref); if (s->legacy_steered && s->ref == 2) goto rearm_periodic; @@ -1157,6 +1156,37 @@ rearm_periodic: uloop_timeout_set(&s->sta_timer, STA_PERIODIC_RUN_INTERVAL); } +static int wifi_send_sta_report(struct agent *a, const char *vif, + uint8_t *macaddr, uint32_t status, uint8_t *bssid) +{ + uint8_t src_bssid[6] = { 0 }; + char ifname[IFNAMESIZE] = {0}; + uint8_t origin[6] = { 0 }; + uint8_t ret = 0; + struct netif_fh *ifptr; + bool ifready = false; + + list_for_each_entry(ifptr, &a->fhlist, list) { + if (!strcmp(ifptr->name, vif)) { + ifready = true; + memcpy(src_bssid, ifptr->bssid, 6); + break; + } + } + + if (!ifready) + return -1; + + //TODO use the cntl ifname and origin address + strcpy(ifname, "lo"); + + /* Here we get need to send the steering report */ + ret = send_steer_btm_report(a, origin, ifname, + bssid, src_bssid, macaddr, status); + + return ret; +} + static int wifi_add_sta(struct agent *a, const char *vif, unsigned char *macaddr) { @@ -1452,6 +1482,8 @@ static void wifi_sta_event_handler(void *c, struct blob_attr *msg) if (!hwaddr_aton(bssid_str, bssid)) return; + wifi_send_sta_report(a, ifname, mac, status, bssid); + /* TODO: which status toggle corresponds to what? */ if (status) { /* TODO: @@ -2815,6 +2847,7 @@ static void parse_ap(struct ubus_request *req, int type, return; strncpy(ifname, blobmsg_data(tb[0]), 15); + strncpy(fh->name, blobmsg_data(tb[0]), 15); strncpy(bssid, blobmsg_data(tb[1]), 17); hwaddr_aton(bssid, fh->bssid); @@ -2983,6 +3016,24 @@ static void agent_periodic_run(struct uloop_timeout *t) } } +/* send the steering compled message this function also resets the value of + * steering opportunity + */ +static void agent_steering_opp_timeout(struct uloop_timeout *t) +{ + trace("agent: %s: --->\n", __func__); + struct agent *a = container_of(t, struct agent, sta_steer_req_timer); + uint8_t src_bssid[6] = { 0 }; + char ifname[IFNAMESIZE] = { 0 }; + uint8_t origin[6] = { 0 }; + + //TODO here we need to fill the controller + //src and interface to which the message needs to be sent + + strcpy(ifname, "lo"); + send_sta_steer_complete((void *)a, origin, ifname); +} + static struct msg *agent_msg_enqueue(struct agent *a, int id, char *data, int len) { @@ -3121,6 +3172,11 @@ int start_agent(void) run_agent(w); } + /*Here we need to set the callback for the steering opportunity timer */ + w->is_sta_steer_start = 0; + w->sta_steerlist_count = 0; + w->sta_steer_req_timer.cb = agent_steering_opp_timeout; + uloop_run(); /* out_and_exit: */ diff --git a/src/core/agent.h b/src/core/agent.h index 1216e6521685bc7cfaf349494af41dbc40961c1d..8c10a5ac4f5e3dafa6e0b494fa7c80f15c22a22e 100644 --- a/src/core/agent.h +++ b/src/core/agent.h @@ -16,10 +16,10 @@ // TODO: TODO: fixme: remove this include //#include <ieee1905/1905_tlvs.h> - +#define MAX_STA 20 typedef char timestamp_t[32]; -typedef struct ip_address { +typedef struct ipaddress { uint8_t ver; uint8_t addr[16]; } ipaddr_t; @@ -380,6 +380,11 @@ struct wifi_netdev { } iface[WIFI_IFACE_MAX_NUM]; }; +struct wifi_sta_steer_list { + uint8_t sta_mac[6]; + uint8_t complete; +}; + /** struct agent - wifi agent */ struct agent { int debug; @@ -404,6 +409,12 @@ struct agent { /* plugins */ struct list_head pluginlist; + + /* steering opportunity */ + bool is_sta_steer_start; /* To know whether STA steering is on going */ + struct uloop_timeout sta_steer_req_timer; /** steer opportunity timer */ + uint32_t sta_steerlist_count; + struct wifi_sta_steer_list sta_steer_list[MAX_STA]; }; struct netif_bk *find_bkhaul_by_bssid(struct agent *a, uint8_t *bssid); diff --git a/src/core/agent_map.c b/src/core/agent_map.c index c3630d219dd541da79ef516bccae542ff44f03d0..f409ef2eb0c4b83bbb3eb6274548a01cce28c612 100644 --- a/src/core/agent_map.c +++ b/src/core/agent_map.c @@ -58,11 +58,17 @@ #define UBUS_TIMEOUT 1000 #define MAX_RADIO 20 +#define MAX_STA 30 struct channel_response { uint8_t radio_id[6]; uint8_t response; }; +struct sta_error_response { + uint8_t sta_mac[6]; + uint8_t response; +}; + #define for_each_tlv(e, _buf, _len) \ for ((e) = (struct tlv *)(_buf); \ (e)->len && (_buf) + (_len) - (uint8_t *)(e) - 3 - (e)->len >= 0; \ @@ -270,6 +276,94 @@ int send_oper_channel_report(void *agent, struct cmdu_cstruct *rec_cmdu) return ret; } +int send_steer_btm_report(void *agent, uint8_t *origin, const char *intf_name, + uint8_t *target_bssid, uint8_t *src_bssid, + uint8_t *sta, uint8_t status_code) +{ + + trace("agent: %s: --->\n", __func__); + struct agent *a = (struct agent *) agent; + uint16_t tlv_index = 0; + uint32_t j; + struct cmdu_cstruct *cmdu_data; + int ret = 0, all_complete = 1; + + cmdu_data = (struct cmdu_cstruct *)calloc(1, + sizeof(struct cmdu_cstruct)); + + if (!cmdu_data) { + fprintf(stderr, "Out of memory!\n"); + return -1; + } + + cmdu_data->message_type = CMDU_CLIENT_STEERING_BTM_REPORT; + memcpy(cmdu_data->origin, origin, 6); + //cmdu_data->message_id = 15; + strcpy(cmdu_data->intf_name, intf_name); + + cmdu_data->num_tlvs = 1; /* (Steering BTM report) */ + cmdu_data->tlvs = (uint8_t **)calloc(cmdu_data->num_tlvs, + sizeof(uint8_t *)); + + if (!cmdu_data->tlvs) { + map_free_cmdu(cmdu_data); + return -1; + } + + /* Clent Steering BTM Report TLV 17.2.30 */ + struct tlv_steer_btm_report *p = + p = agent_gen_steer_btm_report(a, target_bssid, + src_bssid, sta, status_code); + if (!p) { + map_free_cmdu(cmdu_data); + return -1; + } + + cmdu_data->tlvs[tlv_index++] = (uint8_t *)p; + + ret = agent_send_cmdu(a, cmdu_data); + map_free_cmdu(cmdu_data); + + trace("is_steer is %d steer count %d\n", + a->is_sta_steer_start, a->sta_steerlist_count); + + /** + * Check that the report is sent for a steering opportunity. + * Here we store the status in the sta list and check + * if the steering completed message can be sent + */ + if (a->is_sta_steer_start) { + int i; + + /* iterate list of clients attempted to be steered */ + for (i = 0; i < a->sta_steerlist_count; i++) { + + /* mark all steered clients as completed */ + ret = memcmp(sta, a->sta_steer_list[i].sta_mac, 6); + if (ret == 0) + a->sta_steer_list[i].complete = 1; + } + + /** + * Now we need to check if the steering completed + * message can be sent + */ + for (i = 0; i < a->sta_steerlist_count; i++) { + if (a->sta_steer_list[i].complete != 1) { + all_complete = 0; + break; + } + } + + if (all_complete) { + /* Here we need to send the steering completed CMDU */ + send_sta_steer_complete(agent, origin, intf_name); + } + } + + return ret; +} + int send_sta_caps_report(void *agent, struct cmdu_cstruct *cmdu) { return 0; @@ -296,9 +390,44 @@ int send_beacon_metrics_response(void *agent, struct cmdu_cstruct *cmdu) return 0; } -int send_sta_steer_complete(void *agent, struct cmdu_cstruct *cmdu) +int send_sta_steer_complete(void *agent, uint8_t *origin, const char *intf_name) { - return 0; + trace("agent: %s: --->\n", __func__); + struct agent *a = (struct agent *) agent; + uint16_t tlv_index = 0; + uint32_t j; + struct cmdu_cstruct *cmdu_data; + int ret = 0, res = 0, i = 0; + + cmdu_data = (struct cmdu_cstruct *)calloc(1, + sizeof(struct cmdu_cstruct)); + if (!cmdu_data) { + fprintf(stderr, "Out of memory!\n"); + return -1; + } + + cmdu_data->message_type = CMDU_STEERING_COMPLETED; + memcpy(cmdu_data->origin, origin, 6); + //cmdu_data->message_id = 19; + strcpy(cmdu_data->intf_name, intf_name); + + cmdu_data->num_tlvs = 0; /* (No TLVs) */ + if (a->is_sta_steer_start) { + /** + * Here we are sending the steering completed message + * so we need to reset all the values of the + * steering opportunity + */ + a->is_sta_steer_start = 0; + a->sta_steerlist_count = 0; + memset(a->sta_steer_list, 0, sizeof(a->sta_steer_list)); + /* stop the timer if it is running */ + uloop_timeout_cancel(&a->sta_steer_req_timer); + } + + agent_send_cmdu(a, cmdu_data); + map_free_cmdu(cmdu_data); + return ret; } int send_backhaul_sta_steer_response(void *agent, struct cmdu_cstruct *cmdu) @@ -356,7 +485,8 @@ static const map_cmdu_sendfunc_t agent_maptxftable[] = { [0x0e] = send_sta_link_metrics_response, [0x10] = send_unassoc_sta_link_metrics_response, [0x12] = send_beacon_metrics_response, - [0x17] = send_sta_steer_complete, + //[0x15] = send_steer_btm_report, + //[0x17] = send_sta_steer_complete, [0x1a] = send_backhaul_sta_steer_response, [0x1c] = send_channel_scan_report, [0x22] = send_sta_disassoc_stats, @@ -1300,15 +1430,489 @@ int handle_combined_infra_metrics(void *agent, struct cmdu_cstruct *cmdu) int handle_sta_steer_request(void *agent, struct cmdu_cstruct *cmdu) { trace("%s: --->\n", __func__); + struct agent *a = (struct agent *) agent; + int ret = 0; + struct channel_response channel_resp[MAX_RADIO]; + uint32_t channel_resp_nr = 0, match = 0, found = 0; + int i, j, k, l, m; + uint8_t *tlv = NULL; + struct wifi_radio_element *radio; + uint32_t pref_tlv_present = 0; + + /* Here we first parse the steer request */ + if (cmdu->num_tlvs != 0) { + for (i = 0; i < cmdu->num_tlvs; i++) { + tlv = (uint8_t *) cmdu->tlvs[i]; + switch (*tlv) { + case MAP_TLV_STEERING_REQUEST: + { + struct tlv_steer_Req *p = + (struct tlv_steer_Req *)tlv; + + ret = agent_process_steer_request_tlv(agent, + p, cmdu); + } +//#ifdef profile2 + case MAP_TLV_PROFILE2_STEERING_REQ: + { + //TODO here we need to call the request transmission for the + //STAs are Agile Multiband capable + struct tlv_profile2_steer_req *p = + (struct tlv_profile2_steer_req *)tlv; + } +//#endif + default: + break; + } + } + } + return ret; +} + +int validate_sta_bssid_assoc(struct netif_fh *fh, struct tlv_steer_Req *p, + struct sta_error_response *sta_resp, uint32_t *cnt, + struct agent *a) +{ + int l = 0; + struct sta *s; + uint32_t count = 0; + uint32_t res = 0, found = 0; + + for (l = 0; l < p->sta_list_cnt; l++) { + list_for_each_entry(s, &fh->stalist, list) { + trace("stalist :" MACFMT "\n", + MAC2STR(s->macaddr)); + res = memcmp(s->macaddr, p->steering_req_macs[l].addr, 6); + if (res == 0) { + found = 1; + /** + * Here as the sta is present check that in this case + * for steering opportunity put that in the array + */ + if (p->request_mode == 0x00) { + memcpy(a->sta_steer_list[a->sta_steerlist_count].sta_mac, + p->steering_req_macs[l].addr, 6); + a->sta_steerlist_count = a->sta_steerlist_count + 1; + } + break; + } + } + if (found == 0 || !s) { + dbg("Missing STA client!\n"); + memcpy(sta_resp[count].sta_mac, p->steering_req_macs[l].addr, 6); + sta_resp[count].response = 0x02; + count++; + } + } + *cnt += count; return 0; } -int handle_sta_steer_btm_report(void *agent, struct cmdu_cstruct *cmdu) +int agent_transition_sta(struct agent *a, struct tlv_steer_Req *p, struct netif_fh *fh, + int l, int m) { - trace("%s: --->\n", __func__); + uint8_t wildcard[6]; + uint8_t wildcard_bssid[6]; + int result = 0; + char wildcard_str[18] = { 0x0 }; + int ret = 0; + + trace("agent: %s: --->\n", __func__); + snprintf(wildcard_str, 18, "FF:FF:FF:FF:FF:FF"); + hwaddr_aton(wildcard_str, wildcard); + + result = memcmp(p->steering_req_target_bssids[l].bssid, wildcard, 6); + if (result == 0) { + /** + * code to search bssid as the bssid is a + * wildcard + */ + trace("[%s:%d] bssid id wildcard\n", + __func__, __LINE__); + ret = agent_search_bssid_for_sta(a, + p->steering_req_macs[l].addr, + wildcard_bssid, p->bssid); + if (ret == 0) + ret = agent_send_request_transition(a, + p->steering_req_macs[l].addr, + fh, wildcard_bssid, 0); + } else { + ret = agent_send_request_transition(a, + p->steering_req_macs[l].addr, + fh, p->steering_req_target_bssids[m].bssid, 0); + } return 0; } +/* Add the rcpi based check according to section + * 11.3 + */ +bool agent_rcpi_steer(void) +{ + /** + * TODO: Implement proper logic to trigger steer + */ + trace("agent: %s: --->\n", __func__); + return false; +} + + +int agent_process_steer_request_tlv(void *agent, struct tlv_steer_Req *p, + struct cmdu_cstruct *cmdu) +{ + trace("agent: %s: --->\n", __func__); + struct agent *a = (struct agent *) agent; + int ret = 0, result = 0; + uint32_t match = 0, found = 0; + int i, j, k, l, m; + struct netif_fh *fh; + struct sta *s; + struct sta_error_response sta_resp[MAX_STA]; + uint32_t count = 0; + char wildcard_str[18] = { 0x0 }; + uint8_t wildcard[6]; + uint8_t wildcard_bssid[6]; + uint32_t res = 0, present = 0; + + snprintf(wildcard_str, 18, "FF:FF:FF:FF:FF:FF"); + hwaddr_aton(wildcard_str, wildcard); + + trace("request_mode: %d\n", + p->request_mode); + + if (p->request_mode == 0x00) { + /* Here we start the steer opportunity timer */ + if (a->is_sta_steer_start == 1) { + trace("Error steering opportunity timer already running\n"); + return 1; + } + + /** + * Here we need to check the three conditions that needs to be + * satisfied according to section 11.2 + */ + if (p->steer_opp_window == 0) { + trace("Error steering opportunity timer value is zero\n"); + return 1; + } + + /** + * TODO check that the sta mac address is not included + * in the Local Steering Disallowed STA List in the Steering + * Policy TLV + */ + a->is_sta_steer_start = 1; + a->sta_steerlist_count = 0; + uloop_timeout_set(&a->sta_steer_req_timer, p->steer_opp_window * 1000); + + } else if (p->request_mode != 0x01) { + trace("Invalid request mode"); + return 1; + } + + /* TODO check the rcpi based steering rule section 11.3*/ + agent_rcpi_steer(); + + /** + * The src bssid is with which the STA is associated so + * Here we need to check that the STA is associated with the + * src_bssid according to section 11.1 of the steer mandate + * Here we trace the values + */ + trace("btm_disassoc_imminent: %d\n", + p->btm_disassoc_imminent); + trace("btm_abridged: %d\n", + p->btm_abridged); + trace("reserved: %d\n", + p->reserved); + trace("steer_opp_window: %d\n", + p->steer_opp_window); + trace("btm_disassoc_timer: %d\n", + p->btm_disassoc_timer); + trace("sta_list_cnt: %d\n", + p->sta_list_cnt); + trace("target_bssid_list_cnt: %d\n", + p->target_bssid_list_cnt); + trace("src_bssid: " MACFMT "\n", + MAC2STR(p->bssid)); + + /* Here we validate if the sta is associated with the src bssid */ + fh = get_netif_by_bssid(a, p->bssid); + if (!fh) { + trace("[%s:%d] Error BSSID not present", __func__, __LINE__); + for (l = 0; l < p->sta_list_cnt; l++) { + memcpy(sta_resp[count].sta_mac, p->steering_req_macs[l].addr, 6); + sta_resp[count].response = 0x02; + count++; + goto send_ack; + } + } + + ret = validate_sta_bssid_assoc(fh, p, sta_resp, &count, a); + if (ret == -1) + goto send_ack; + + /* Number of STAs and BSSIDs are equal, map STA to BSSID */ + if (p->sta_list_cnt > 0 && p->sta_list_cnt == p->target_bssid_list_cnt) { + for (l = 0; l < p->sta_list_cnt; l++) { + trace("sta_addr: " MACFMT "\n", + MAC2STR(p->steering_req_macs[l].addr)); + trace("target bssid: " MACFMT "\n", + MAC2STR(p->steering_req_target_bssids[l].bssid)); + trace("op_class: %d\n", + p->steering_req_target_bssids[l].op_class); + trace("channel: %d\n", + p->steering_req_target_bssids[l].channel); + /** + * Here we need to check that the STA is associated with the + * src bssid or not + */ + present = 0; + trace("count of error code sta %d\n", count); + for (m = 0; m < count; m++) { + trace("steer mac: " MACFMT "\n", + MAC2STR(p->steering_req_macs[l].addr)); + trace("sta error mac: " MACFMT "\n", + MAC2STR(sta_resp[m].sta_mac)); + res = memcmp(p->steering_req_macs[l].addr, + sta_resp[m].sta_mac, 6); + if (res == 0) { + present = 1; + break; + } + } + if (present != 1) { + /*Here we call for transition of sta*/ + ret = agent_transition_sta(a, p, fh, l, l); + } + } + } + /* Multiple STAs and single BSSID, send all STAs to same BSSID */ + else if (p->sta_list_cnt > 0 && p->target_bssid_list_cnt == 1) { + trace("target bssid: " MACFMT "\n", + MAC2STR(p->steering_req_target_bssids[0].bssid)); + trace("op_class: %d\n", + p->steering_req_target_bssids[0].op_class); + trace("channel: %d\n", + p->steering_req_target_bssids[0].channel); + + for (l = 0; l < p->sta_list_cnt; l++) { + /* Here we need to call the ubus method */ + trace("sta_addr: " MACFMT "\n", + MAC2STR(p->steering_req_macs[l].addr)); + /** + * Here we need to check that the STA is associated with + * the src bssid or not + */ + present = 0; + for (m = 0; m < count; m++) { + res = memcmp(p->steering_req_macs[l].addr, + sta_resp[m].sta_mac, 6); + if (res == 0) { + present = 1; + break; + } + } + if (present != 1) { + /*Here we call for transition of sta*/ + ret = agent_transition_sta(a, p, fh, l, 0); + } + } + } + /** + * No STA provided, Steering request applies to all associated STAs + * in the BSS, per policy setting. + */ + else if (p->sta_list_cnt == 0 && p->target_bssid_list_cnt == 1) { + result = memcmp(p->steering_req_target_bssids[0].bssid, wildcard, 6); + if (result == 0) { + trace("[%s:%d] bssid id wildcard", __func__, __LINE__); + ret = agent_search_bssid_for_sta(a, + p->steering_req_macs[l].addr, wildcard_bssid, p->bssid); + if (ret != 0) { + list_for_each_entry(s, &fh->stalist, list) { + ret = agent_send_request_transition( + agent, s->macaddr, + fh, wildcard_bssid, 0); + } + } + } else { + list_for_each_entry(s, &fh->stalist, list) { + ret = agent_send_request_transition( + agent, s->macaddr, + fh, p->steering_req_target_bssids[0].bssid, 0); + } + } + } + /* No BSSID specified for the STAs */ + else if (p->sta_list_cnt > 0 && p->target_bssid_list_cnt == 0) { + if (p->request_mode != 0x00) { + trace("[%s:%d]Error steer mandate target BSSID not present\n", + __func__, __LINE__); + return 1; + } + trace("[%s:%d] target BSSID not present\n", __func__, __LINE__); + for (l = 0; l < p->sta_list_cnt; l++) { + trace("sta_addr: " MACFMT "\n", + MAC2STR(p->steering_req_macs[l].addr)); + /** + * Here we need to check that the STA is associated with the + * src bssid or not + */ + present = 0; + for (m = 0; m < count; m++) { + res = memcmp(p->steering_req_macs[l].addr, sta_resp[m].sta_mac, 6); + if (res == 0) { + present = 1; + break; + } + } + if (present != 1) { + /** + * Here we need to get the bssids that are best + * for the STAs in case of steering opportunity + */ + ret = agent_search_bssid_for_sta(a, + p->steering_req_macs[l].addr, + wildcard_bssid, p->bssid); + if (ret != 0) + ret = agent_send_request_transition( + agent, p->steering_req_macs[l].addr, + fh, wildcard_bssid, 0); + } + } + } + /* No BSSID or STAs */ + else if (p->sta_list_cnt == 0 && p->target_bssid_list_cnt == 0) { + trace("[%s:%d] Error No STA and target BSSID present\n", __func__, __LINE__); + return 1; + } else { + trace("[%s:%d] Error condition\n", __func__, __LINE__); + return 1; + } + +send_ack: + send_1905_acknowledge(agent, p, cmdu, sta_resp, count); + return ret; +} + +//TODO search BSSID incase of wildcard or in case need to get the +//implementation specific policy section 11.4 +int agent_search_bssid_for_sta(struct agent *a, uint8_t *sta, uint8_t *bssid, + uint8_t *src_bssid) +{ + + struct netif_fh *p; + int ret = 0; + + trace("agent: %s: --->\n", __func__); + list_for_each_entry(p, &a->fhlist, list) { + trace("bssid = " MACFMT " pbssid = " MACFMT "\n", + MAC2STR(bssid), MAC2STR(p->bssid)); + ret = memcmp(src_bssid, p->bssid, 6); + if (ret != 0) { + memcpy(bssid, p->bssid, 6); + return 0; + } + } + memcpy(bssid, src_bssid, 6); + return 0; +} + +int send_1905_acknowledge(void *agent, struct tlv_error_code *p, + struct cmdu_cstruct *rec_cmdu, + struct sta_error_response *sta_resp, uint32_t sta_count) +{ + struct agent *a = (struct agent *) agent; + uint16_t tlv_index = 0; + uint32_t j; + struct cmdu_cstruct *cmdu_data; + int ret = 0; + + trace("agent: %s: --->\n", __func__); + cmdu_data = (struct cmdu_cstruct *)calloc(1, + sizeof(struct cmdu_cstruct)); + + if (!cmdu_data) { + fprintf(stderr, "Out of memory!\n"); + return -1; + } + + cmdu_data->message_type = CMDU_1905_ACK; + memcpy(cmdu_data->origin, rec_cmdu->origin, 6); + //cmdu_data->message_id = 11; + strcpy(cmdu_data->intf_name, rec_cmdu->intf_name); + + cmdu_data->num_tlvs = sta_count; /* (TLV for error) */ + cmdu_data->tlvs = (uint8_t **)calloc(cmdu_data->num_tlvs, + sizeof(uint8_t *)); + + if (!cmdu_data->tlvs) { + map_free_cmdu(cmdu_data); + return -1; + } + + /* Error Code TLV 17.2.36 */ + for (j = 0; j < sta_count; j++) { + struct tlv_error_code *p = NULL; + /** + * Here we need to check that the sta error + * response + */ + p = agent_gen_tlv_error_code(a, rec_cmdu, + sta_resp[j].sta_mac, sta_resp[j].response); + if (!p) + continue; + cmdu_data->tlvs[tlv_index++] = (uint8_t *)p; + } + ret = agent_send_cmdu(a, cmdu_data); + map_free_cmdu(cmdu_data); + return 0; +} + +int agent_send_request_transition(void *agent, uint8_t *client_sta, + struct netif_fh *fh, uint8_t *bssid, uint32_t timeout) +{ + struct agent *a = (struct agent *) agent; + char client_macstr[18] = { 0 }; + char bssid_str[18] = { 0 }; + struct blob_buf bb = { 0 }; + int ret = 0; + uint32_t id; + char ap_ifname[30] = { 0 }; + void *tbl; + + trace("agent: %s: --->\n", __func__); + if (!client_sta || !bssid) + return -1; + + blob_buf_init(&bb, 0); + + hwaddr_ntoa(client_sta, client_macstr); + blobmsg_add_string(&bb, "client", client_macstr); + + hwaddr_ntoa(bssid, bssid_str); + tbl = blobmsg_open_array(&bb, "bssid"); + blobmsg_add_string(&bb, NULL, bssid_str); + blobmsg_close_table(&bb, tbl); + + if (timeout) { + //fill the timeout + } + + ret = ubus_invoke(a->ubus_ctx, fh->wifi, "request_transition", bb.head, + NULL, NULL, UBUS_TIMEOUT); + if (ret) { + trace("[%s:%d] ubus call failed for |wifi.ap. send|", + __func__, __LINE__); + goto out; + } + +out: + blob_buf_free(&bb); + return ret; +} + int handle_sta_assoc_control_request(void *agent, struct cmdu_cstruct *cmdu) { trace("%s: --->\n", __func__); @@ -1457,7 +2061,7 @@ static const map_cmdu_handler_t agent_mapftable[] = { [0x12] = handle_beacon_metrics_response, [0x13] = handle_combined_infra_metrics, [0x14] = handle_sta_steer_request, - [0x15] = handle_sta_steer_btm_report, + /*[0x15] = handle_sta_steer_btm_report,*/ [0x16] = handle_sta_assoc_control_request, /* [0x17] = handle_sta_steer_complete, */ [0x18] = handle_hld_message, @@ -1563,7 +2167,7 @@ bool is_cmdu_for_us(struct agent *a, uint16_t type) // until then, the following should be okay.. - if (type >= CMDU_TYPE_1905_START && type <= CMDU_TYPE_MAP_START) { + if (type >= CMDU_TYPE_1905_START && type <= CMDU_TYPE_1905_END) { if (i1905ftable[type]) return true; } else if (type >= CMDU_TYPE_MAP_START && type <= CMDU_TYPE_MAP_END) { diff --git a/src/core/agent_tlv_generator.c b/src/core/agent_tlv_generator.c index 5f8a77a08ebdf7da1827d2a7601e0f6697c8c0dc..0d83c425beb38e333d2a04666078fc12f298468e 100644 --- a/src/core/agent_tlv_generator.c +++ b/src/core/agent_tlv_generator.c @@ -630,3 +630,45 @@ void agent_gen_cac_comp_report(struct agent *a, p->radio_data[j].nbr_pairs = 0; //dummy value TODO } } + +struct tlv_error_code *agent_gen_tlv_error_code(struct agent *a, + struct cmdu_cstruct *cmdu, uint8_t *sta_mac, uint8_t reason_code) +{ + struct tlv_error_code *p; + + p = (struct tlv_error_code *)calloc(1, + sizeof(struct tlv_error_code)); + + if (!p) + return NULL; + + p->tlv_type = MAP_TLV_ERROR_CODE; + p->reason_code = reason_code; + memcpy(p->addr, sta_mac, 6); + + return p; +} + +struct tlv_steer_btm_report *agent_gen_steer_btm_report(struct agent *a, + uint8_t *target_bssid, uint8_t *src_bssid, + uint8_t *sta, uint8_t status_code) +{ + struct tlv_steer_btm_report *p; + + p = (struct tlv_steer_btm_report *)calloc(1, + sizeof(struct tlv_steer_btm_report)); + + if (!p) + return NULL; + + p->tlv_type = MAP_TLV_STEERING_BTM_REPORT; + memcpy(p->bssid, src_bssid, 6); + p->status_code = status_code; + + if (p->status_code == 0x00) + memcpy(p->target_bssid, target_bssid, 6); + + memcpy(p->sta_mac_addr, sta, 6); + + return p; +} diff --git a/src/core/agent_tlv_generator.h b/src/core/agent_tlv_generator.h index d14c63a778f4770ee3669f2d7fe10775d5ccf86a..c5ef25efc3817cdb31da7419826c8726cee73f65 100644 --- a/src/core/agent_tlv_generator.h +++ b/src/core/agent_tlv_generator.h @@ -38,4 +38,9 @@ void agent_gen_radio_restrict_channel(struct agent *a, uint32_t radio_index); void agent_gen_cac_comp_report(struct agent *a, struct tlv_cac_comp_report *p); +struct tlv_error_code *agent_gen_tlv_error_code(struct agent *a, + struct cmdu_cstruct *cmdu, uint8_t *sta_mac, uint8_t reason_code); +struct tlv_steer_btm_report *agent_gen_steer_btm_report(struct agent *a, + uint8_t *target_bssid, uint8_t *src_bssid, + uint8_t *sta, uint8_t status_code); #endif