From 739e072ec404d169a22608d86f3fd00d04331243 Mon Sep 17 00:00:00 2001 From: Lejla <lejla.murselovic@iopsys.eu> Date: Tue, 13 Apr 2021 13:44:09 +0200 Subject: [PATCH] map-agent: Requested Channel Scan - Fresh --- src/core/agent.c | 25 ++++ src/core/agent.h | 6 + src/core/agent_map.c | 314 ++++++++++++++++++++++++++++++------------- 3 files changed, 254 insertions(+), 91 deletions(-) diff --git a/src/core/agent.c b/src/core/agent.c index 936b33c98..1f14adccf 100644 --- a/src/core/agent.c +++ b/src/core/agent.c @@ -1941,6 +1941,30 @@ out_str: static void wifi_radio_event_handler(void *c, struct blob_attr *msg) { dbg("%s --->\n", __func__); + struct agent *agent = (struct agent *) c; + struct blob_attr *tb[2]; + char radio[18] = {0}, action[14] = {0}; + bool scan_finished; + static const struct blobmsg_policy ev_attr[2] = { + [0] = { .name = "radio", .type = BLOBMSG_TYPE_STRING }, + [1] = { .name = "action", .type = BLOBMSG_TYPE_STRING }, + }; + + blobmsg_parse(ev_attr, 2, tb, blob_data(msg), blob_len(msg)); + if (!tb[0] || !tb[1]) + dbg("Wifi event parse error.\n"); + else { + strncpy(radio, blobmsg_data(tb[0]), sizeof(radio) - 1); + strncpy(action, blobmsg_data(tb[1]), sizeof(action) - 1); + dbg("%s for %s\n", action, radio); + + scan_finished = !strcmp(action, "scan_finished"); + if (scan_finished) { + struct wifi_radio_element *current_radio = wifi_ifname_to_radio_element(agent, radio); + current_radio->scanned = 1; + handle_wifi_radio_scan_finished(agent); + } + } } int wifi_mod_bridge(struct agent *a, char *ifname, char *action) @@ -2413,6 +2437,7 @@ static void ieee1905_cmdu_event_handler(void *c, struct blob_attr *msg) } strtob(tlvstr, len, tlv); + free(tlvstr); } diff --git a/src/core/agent.h b/src/core/agent.h index 65f5d5bab..dd99093c2 100644 --- a/src/core/agent.h +++ b/src/core/agent.h @@ -394,6 +394,9 @@ struct wifi_radio_element { bool configured; uint16_t mid; struct wsc_data autconfig; + + /* requested channel scan with event handling */ + bool scanned; }; struct wifi_netdev { @@ -453,6 +456,9 @@ struct agent { } loop_detection; uint8_t depth; + + /* requested channel scan with event handling */ + struct cmdu_cstruct *req_channel_scan_cmdu; }; 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 1fbcee44e..508104320 100644 --- a/src/core/agent_map.c +++ b/src/core/agent_map.c @@ -3050,8 +3050,97 @@ int handle_channel_scan_request(void *agent, struct cmdu_cstruct *cmdu) int opclass_index; int channel_index; - struct cmdu_cstruct *cmdu_data; - int ret, ri; + struct cmdu_cstruct *cmdu_copy = NULL; + uint8_t *ss = NULL; // binary cmdu->tlvs + char *tlv_str = NULL; // string cmdu->tlvs + uint8_t *tlvs = NULL; // binary resulting tlvs + char *endtlvstr = NULL; // end_of_mes tlv string + char *restlvstr = NULL; // string resulting tlvs + uint16_t len, leng; + + // Get the string value of cmdu->tlvs + if (cmdu->num_tlvs > 0) { + for (int it = 0; it < cmdu->num_tlvs; it++) { + len = 0; + ss = map_put_tlv_cstruct(cmdu->tlvs[it], &len); + if (ss) { + tlv_str = (char *)calloc((2 * len) + 1, + sizeof(char)); + if (!tlv_str) { + dbg("|%s:%d| out of memory!\n", __func__, __LINE__); + free(ss); + return 0; + } + btostr(ss, len, tlv_str); + } + } + } + + // End of message tlv + endtlvstr = calloc(7, 1); + if (!endtlvstr) { + dbg("|%s:%d| out of memory!\n", __func__, __LINE__); + free(tlv_str); + free(ss); + return 0; + } + endtlvstr = "000000"; + + // Append the cmdu->tlvs string with end of message tlv + // Get resulting tlvs string + const size_t len1 = strlen(tlv_str); + const size_t len2 = strlen(endtlvstr); + restlvstr = malloc(len1 + len2 + 1); + if (!restlvstr) { + dbg("|%s:%d| out of memory!\n", __func__, __LINE__); + free(tlv_str); + free(ss); + free(endtlvstr); + return 0; + } + memcpy(restlvstr, tlv_str, len1); + memcpy(restlvstr + len1, endtlvstr, len2 + 1); + + // Resulting tlvs string to binary value + leng = len1 + len2; + leng = (leng - 1) / 2; + tlvs = calloc(leng, sizeof(uint8_t)); + if (!tlvs) { + dbg("|%s:%d| out of memory!\n", __func__, __LINE__); + free(tlv_str); + free(ss); + free(endtlvstr); + free(restlvstr); + return 0; + } + strtob(restlvstr, leng, tlvs); + + // Deep copy of cmdu + cmdu_copy = map_build_cmdu(cmdu->message_type, + cmdu->message_id, cmdu->intf_name, cmdu->origin, tlvs); + if (cmdu_copy) { + fprintf(stderr, "agent: %s: map_build_cmdu() successful!\n", __func__); + } else { + fprintf(stderr, "agent: %s: map_build_cmdu() failed!\n", __func__); + free(tlv_str); + free(ss); + free(endtlvstr); + free(restlvstr); + free(tlvs); + return 0; + } + + // Saving the cmdu with the agent + a->req_channel_scan_cmdu = cmdu_copy; + cmdu_copy = NULL; + fprintf(stderr, "DONE ADDING CMDU TO AGENT\n"); + dbg("\n%s L-%d | cmdu mid: %d\n", __func__, + __LINE__, a->req_channel_scan_cmdu->message_id); + dbg("%s L-%d | cmdu typs: %s\n", __func__, + __LINE__, map_stringify_cmdu_type(a->req_channel_scan_cmdu->message_type)); + + // struct cmdu_cstruct *cmdu_data; + int ret = 0, ri = 0; // The received TLV uint8_t *tmp = NULL; @@ -3082,93 +3171,117 @@ int handle_channel_scan_request(void *agent, struct cmdu_cstruct *cmdu) ubus_call_object(a, r_wobj, "scan", NULL, &a->radios[ri]); trace("Scaning radio %s neighbors...\n", wifi_get_radio_by_mac(a, query->radio_data[i].radio_id)); } - sleep(5); + return 1; +} + +bool all_channel_scanned(struct agent *a, struct tlv_ch_scan_req *query) +{ + int ri, i; for (i = 0; i < query->nbr_radios; i++) { - snprintf(r_objname, 31, r_fmt, wifi_get_radio_by_mac(a, query->radio_data[i].radio_id)); //a->radios[ri].name - r_wobj = ubus_get_object(a->ubus_ctx, r_objname); - if (r_wobj == WIFI_OBJECT_INVALID) - continue; ri = wifi_get_radio_index_by_mac(a, query->radio_data[i].radio_id); - trace("...done scanning radio %s neighbors.\n", wifi_get_radio_by_mac(a, query->radio_data[i].radio_id)); - // ubus call wifi.radio.wl0 scanresults - ubus_call_object(a, r_wobj, "scanresults", parse_scanresults, &a->radios[ri]); + if (!a->radios[ri].scanned) + return 0; } + return 1; +} - // Allocate the cmdu - cmdu_data = (struct cmdu_cstruct *)calloc(1, sizeof(struct cmdu_cstruct)); - if (!cmdu_data) { - dbg("Out of memory!\n"); - return -1; - } - // Define the cmdu - cmdu_data->message_type = CMDU_CHANNEL_SCAN_REPORT; - cmdu_data->message_id = cmdu->message_id; - strcpy(cmdu_data->intf_name, cmdu->intf_name); - memcpy(cmdu_data->origin, cmdu->origin, 6); - cmdu_data->num_tlvs = 1; // timestamp tlv - for (m = 0; m < query->nbr_radios; m++) { // for each radio - if (query->radio_data[m].op_class_data->nbr_ch == 0) { // all_ch_scan - radio_index = wifi_get_radio_index_by_mac(a, query->radio_data[m].radio_id); - for (i = 0; i < radio[radio_index].scanlist->num_opclass_scanned; i++) { - if (radio[radio_index].scanlist->opclass_scanlist[i].bandwidth == 20) { - for (j = 0; j < radio[radio_index].scanlist->opclass_scanlist[i].num_channels_scanned; j++) - cmdu_data->num_tlvs++; - } - } - } else // specified channels - cmdu_data->num_tlvs += query->radio_data[m].op_class_data->nbr_ch; // ch scan res tlvs - } - trace("Number of tlvs: %d\n", cmdu_data->num_tlvs); - // Allocate the TLVs - cmdu_data->tlvs = (uint8_t **)calloc(cmdu_data->num_tlvs, sizeof(uint8_t *)); - if (!cmdu_data->tlvs) { - map_free_cmdu(cmdu_data); +int handle_wifi_radio_scan_finished(void *agent) +{ + trace("%s ---> scan_finished\n", __func__); + struct agent *a = (struct agent *) agent; + struct wifi_radio_element *radio = a->radios; + uint16_t tlv_index = 0; + uint32_t i, j, k, m; + int ret = 0, ri = 0; + int radio_index, opclass_index, channel_index; + // The received (request) cmdu + struct cmdu_cstruct *cmdu = a->req_channel_scan_cmdu; + // The response cmdu + struct cmdu_cstruct *cmdu_data = NULL; + // The received TLV + uint8_t *tmp = NULL; + + tmp = cmdu->tlvs[0]; + if (*tmp != MAP_TLV_CHANNEL_SCAN_REQ) { + dbg("Wrong received TLV type!\n"); return -1; } - // Define the TLVs - /* Timestamp */ - struct tlv_timestamp *p = (struct tlv_timestamp *)calloc(1, sizeof(struct tlv_timestamp)); + struct tlv_ch_scan_req *query = (struct tlv_ch_scan_req *)tmp; - if (p) { - p->tlv_type = MAP_TLV_TIMESTAMP; - get_timestamp(NULL, &p->time); - p->time_len = strlen(p->time); - cmdu_data->tlvs[tlv_index++] = (uint8_t *)p; - trace("|%s:%d| Added %s\n", __func__, __LINE__, map_stringify_tlv_type(*cmdu_data->tlvs[tlv_index-1])); - } - - /* Channel scan result */ - // Multiple radio - for (m = 0; m < query->nbr_radios; m++) { - dbg("\tRadio_id in %d iteration: " MACFMT "\n", m, MAC2STR(query->radio_data[m].radio_id)); - radio_index = wifi_get_radio_index_by_mac(a, query->radio_data[m].radio_id); - // All channels scan request - if (query->radio_data[m].op_class_data->nbr_ch == 0) { - for (i = 0; i < radio[radio_index].scanlist->num_opclass_scanned; i++) { - if (radio[radio_index].scanlist->opclass_scanlist[i].bandwidth == 20) { - for (j = 0; j < radio[radio_index].scanlist->opclass_scanlist[i].num_channels_scanned; j++) { - opclass_index = i; - channel_index = j; - struct tlv_ch_scan_res *p1 = (struct tlv_ch_scan_res *)calloc(1, sizeof(struct tlv_ch_scan_res)); - - if (p1) { - p1->tlv_type = MAP_TLV_CHANNEL_SCAN_RES; - scan_results(a, p1, radio_index, opclass_index, channel_index); - cmdu_data->tlvs[tlv_index++] = (uint8_t *)p1; - trace("|%s:%d| Added %s for channel %d\n", __func__, __LINE__, map_stringify_tlv_type(*cmdu_data->tlvs[tlv_index-1]), - radio[radio_index].scanlist->opclass_scanlist[i].channel_scanlist[j].channel); - } + // Response only when all channels are scanned + if (all_channel_scanned(a, query)) { + dbg("All radios have been scanned!\n"); + + // Parse channel scanresults + char r_objname[32] = {0}; + const char *r_fmt = "wifi.radio.%s"; + char *radio_name; + wifi_object_t r_wobj = WIFI_OBJECT_INVALID; + + for (i = 0; i < query->nbr_radios; i++) { + snprintf(r_objname, 31, r_fmt, wifi_get_radio_by_mac(a, query->radio_data[i].radio_id)); //a->radios[ri].name + r_wobj = ubus_get_object(a->ubus_ctx, r_objname); + if (r_wobj == WIFI_OBJECT_INVALID) + continue; + ri = wifi_get_radio_index_by_mac(a, query->radio_data[i].radio_id); + trace("...done scanning radio %s neighbors.\n", wifi_get_radio_by_mac(a, query->radio_data[i].radio_id)); + // ubus call wifi.radio.wl0 scanresults + ubus_call_object(a, r_wobj, "scanresults", parse_scanresults, &a->radios[ri]); + } + + // Allocate the cmdu + cmdu_data = (struct cmdu_cstruct *)calloc(1, sizeof(struct cmdu_cstruct)); + if (!cmdu_data) { + dbg("Out of memory!\n"); + return -1; + } + // Define the cmdu + cmdu_data->message_type = CMDU_CHANNEL_SCAN_REPORT; + cmdu_data->message_id = cmdu->message_id; + strcpy(cmdu_data->intf_name, cmdu->intf_name); + memcpy(cmdu_data->origin, cmdu->origin, 6); + cmdu_data->num_tlvs = 1; // timestamp tlv + for (m = 0; m < query->nbr_radios; m++) { // for each radio + if (query->radio_data[m].op_class_data->nbr_ch == 0) { // all_ch_scan + radio_index = wifi_get_radio_index_by_mac(a, query->radio_data[m].radio_id); + for (i = 0; i < radio[radio_index].scanlist->num_opclass_scanned; i++) { + if (radio[radio_index].scanlist->opclass_scanlist[i].bandwidth == 20) { + for (j = 0; j < radio[radio_index].scanlist->opclass_scanlist[i].num_channels_scanned; j++) + cmdu_data->num_tlvs++; } } - } - } else { - for (k = 0; k < query->radio_data[m].op_class_data->nbr_ch; k++) { - uint8_t query_channel = query->radio_data[m].op_class_data->ch[k]; + } else // specified channels + cmdu_data->num_tlvs += query->radio_data[m].op_class_data->nbr_ch; // ch scan res tlvs + } + trace("Number of tlvs: %d\n", cmdu_data->num_tlvs); + // Allocate the TLVs + cmdu_data->tlvs = (uint8_t **)calloc(cmdu_data->num_tlvs, sizeof(uint8_t *)); + if (!cmdu_data->tlvs) { + map_free_cmdu(cmdu_data); + return -1; + } + // Define the TLVs + /* Timestamp */ + struct tlv_timestamp *p = (struct tlv_timestamp *)calloc(1, sizeof(struct tlv_timestamp)); + + if (p) { + p->tlv_type = MAP_TLV_TIMESTAMP; + get_timestamp(NULL, &p->time); + p->time_len = strlen(p->time); + cmdu_data->tlvs[tlv_index++] = (uint8_t *)p; + trace("|%s:%d| Added %s\n", __func__, __LINE__, map_stringify_tlv_type(*cmdu_data->tlvs[tlv_index-1])); + } + /* Channel scan result */ + // Multiple radio + for (m = 0; m < query->nbr_radios; m++) { + dbg("\tRadio_id in %d iteration: " MACFMT "\n", m, MAC2STR(query->radio_data[m].radio_id)); + radio_index = wifi_get_radio_index_by_mac(a, query->radio_data[m].radio_id); + // All channels scan request + if (query->radio_data[m].op_class_data->nbr_ch == 0) { for (i = 0; i < radio[radio_index].scanlist->num_opclass_scanned; i++) { - dbg("Numbre of scaned channels for the radio %d\n", radio[radio_index].scanlist->num_opclass_scanned); - for (j = 0; j < radio[radio_index].scanlist->opclass_scanlist[i].num_channels_scanned; j++) { - if (radio[radio_index].scanlist->opclass_scanlist[i].channel_scanlist[j].channel == query_channel) { + if (radio[radio_index].scanlist->opclass_scanlist[i].bandwidth == 20) { + for (j = 0; j < radio[radio_index].scanlist->opclass_scanlist[i].num_channels_scanned; j++) { opclass_index = i; channel_index = j; struct tlv_ch_scan_res *p1 = (struct tlv_ch_scan_res *)calloc(1, sizeof(struct tlv_ch_scan_res)); @@ -3178,27 +3291,46 @@ int handle_channel_scan_request(void *agent, struct cmdu_cstruct *cmdu) scan_results(a, p1, radio_index, opclass_index, channel_index); cmdu_data->tlvs[tlv_index++] = (uint8_t *)p1; trace("|%s:%d| Added %s for channel %d\n", __func__, __LINE__, map_stringify_tlv_type(*cmdu_data->tlvs[tlv_index-1]), - query_channel); - goto found; + radio[radio_index].scanlist->opclass_scanlist[i].channel_scanlist[j].channel); } } } } + } else { + for (k = 0; k < query->radio_data[m].op_class_data->nbr_ch; k++) { + uint8_t query_channel = query->radio_data[m].op_class_data->ch[k]; + + for (i = 0; i < radio[radio_index].scanlist->num_opclass_scanned; i++) { + for (j = 0; j < radio[radio_index].scanlist->opclass_scanlist[i].num_channels_scanned; j++) { + if (radio[radio_index].scanlist->opclass_scanlist[i].channel_scanlist[j].channel == query_channel) { + opclass_index = i; + channel_index = j; + struct tlv_ch_scan_res *p1 = (struct tlv_ch_scan_res *)calloc(1, sizeof(struct tlv_ch_scan_res)); + + if (p1) { + p1->tlv_type = MAP_TLV_CHANNEL_SCAN_RES; + scan_results(a, p1, radio_index, opclass_index, channel_index); + cmdu_data->tlvs[tlv_index++] = (uint8_t *)p1; + trace("|%s:%d| Added %s for channel %d\n", __func__, __LINE__, map_stringify_tlv_type(*cmdu_data->tlvs[tlv_index-1]), + query_channel); + goto found; + } + } + } + } found: - continue; + continue; + } } } + // TODO: memory leak from tlvs + // Send cmdu + ret = agent_send_cmdu(a, cmdu_data); + map_free_cmdu(cmdu_data); + map_free_cmdu(a->req_channel_scan_cmdu); + return ret; } - // TODO: memory leak from tlvs - // Send cmdu - ret = agent_send_cmdu(a, cmdu_data); - map_free_cmdu(cmdu_data); - return ret; -} - -int handle_wifi_radio_scan_finished(void *agent) //, struct cmdu_cstruct *cmdu) // LEJLA -{ - trace("%s ---> scan_finished\n", __func__); + dbg("Not all radios have been scanned.\n"); return 0; } -- GitLab