| From 4592e371528abdf4804c116760059b0a0fb4dbc6 Mon Sep 17 00:00:00 2001 |
| From: "Allen.Ye" <allen.ye@mediatek.com> |
| Date: Tue, 2 Aug 2022 17:23:06 +0800 |
| Subject: [PATCH] HAL: refactor NeighboringWiFiDiagnosticResult2 scan part and |
| add scan filter function |
| |
| --- |
| source/wifi/wifi_hal.c | 289 ++++++++++++++++++++++++++++++++++++----- |
| 1 file changed, 259 insertions(+), 30 deletions(-) |
| |
| diff --git a/source/wifi/wifi_hal.c b/source/wifi/wifi_hal.c |
| index e49f22f..44f167b 100644 |
| --- a/source/wifi/wifi_hal.c |
| +++ b/source/wifi/wifi_hal.c |
| @@ -73,6 +73,8 @@ Licensed under the ISC license |
| //#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention |
| #define SOCK_PREFIX "/var/run/hostapd/wifi" |
| #define VAP_STATUS_FILE "/tmp/vap-status" |
| +#define ESSID_FILE "/tmp/essid" |
| + |
| #ifdef MTK_IMPL |
| #define DRIVER_2GHZ "mt7915e" |
| #define DRIVER_5GHZ "mt7915e" |
| @@ -3037,47 +3039,243 @@ INT wifi_applySSIDSettings(INT ssidIndex) |
| return ret; |
| } |
| |
| +struct channels_noise { |
| + int channel; |
| + int noise; |
| +}; |
| + |
| +// Return noise array for each channel |
| +int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num) |
| +{ |
| + FILE *f = NULL; |
| + char cmd[128] = {0}; |
| + char *line = NULL; |
| + size_t len = 0; |
| + ssize_t read = 0; |
| + int tmp = 0, arr_index = -1; |
| + |
| + sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex); |
| + |
| + if ((f = popen(cmd, "r")) == NULL) { |
| + wifi_dbg_printf("%s: popen %s error\n", __func__, cmd); |
| + return RETURN_ERR; |
| + } |
| + |
| + while((read = getline(&line, &len, f)) != -1) { |
| + sscanf(line, "%d", &tmp); |
| + if (tmp > 0) { // channel frequency, the first line must be frequency |
| + arr_index++; |
| + channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp); |
| + } else { // noise |
| + channels_noise_arr[arr_index].noise = tmp; |
| + } |
| + } |
| + free(line); |
| + pclose(f); |
| + return RETURN_OK; |
| +} |
| + |
| //Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list |
| //HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array" |
| INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181 |
| { |
| - INT status = RETURN_ERR; |
| - UINT index; |
| - wifi_neighbor_ap2_t *pt=NULL; |
| - char cmd[128]={0}; |
| - char buf[8192]={0}; |
| + int index = -1; |
| + wifi_neighbor_ap2_t *scan_array = NULL; |
| + char cmd[256]={0}; |
| + char buf[128]={0}; |
| + char file_name[32] = {0}; |
| + char filter_SSID[32] = {0}; |
| + int freq=0; |
| + FILE *f = NULL; |
| + size_t len=0; |
| + ssize_t read = 0; |
| + char *line =NULL; |
| + // int noise_arr[channels_num] = {0}; |
| + int channels_num = 0; |
| + int vht_channel_width = 0; |
| + bool get_nosie_ret = false; |
| + bool filter_enable = false; |
| + bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd. |
| |
| WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__); |
| - sprintf(cmd, "iwlist %s%d scan",AP_PREFIX,(radioIndex==0)?0:1); //suppose ap0 mapping to radio0 |
| + |
| + snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex); |
| + f = fopen(file_name, "r"); |
| + if (f != NULL) { |
| + fgets(filter_SSID, sizeof(file_name), f); |
| + if (strlen(filter_SSID) != 0) |
| + filter_enable = true; |
| + fclose(f); |
| + } |
| + |
| + snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex); |
| _syscmd(cmd, buf, sizeof(buf)); |
| + channels_num = atoi(buf); |
| |
| + struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise)); |
| + get_nosie_ret = get_noise(radioIndex, channels_noise_arr, channels_num); |
| + |
| + sprintf(cmd, "iw dev %s%d scan | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \ |
| + // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE160' | grep -v -e '*.*BSS'", AP_PREFIX, radioIndex, AP_PREFIX, radioIndex); |
| + fprintf(stderr, "cmd: %s\n", cmd); |
| + if ((f = popen(cmd, "r")) == NULL) { |
| + wifi_dbg_printf("%s: popen %s error\n", __func__, cmd); |
| + return RETURN_ERR; |
| + } |
| |
| - *output_array_size=2; |
| - //zqiu: HAL alloc the array and return to caller. Caller response to free it. |
| - *neighbor_ap_array=(wifi_neighbor_ap2_t *)calloc(sizeof(wifi_neighbor_ap2_t), *output_array_size); |
| - for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) { |
| - strcpy(pt->ap_SSID,""); |
| - strcpy(pt->ap_BSSID,""); |
| - strcpy(pt->ap_Mode,""); |
| - pt->ap_Channel=1; |
| - pt->ap_SignalStrength=0; |
| - strcpy(pt->ap_SecurityModeEnabled,""); |
| - strcpy(pt->ap_EncryptionMode,""); |
| - strcpy(pt->ap_OperatingFrequencyBand,""); |
| - strcpy(pt->ap_SupportedStandards,""); |
| - strcpy(pt->ap_OperatingStandards,""); |
| - strcpy(pt->ap_OperatingChannelBandwidth,""); |
| - pt->ap_BeaconPeriod=1; |
| - pt->ap_Noise=0; |
| - strcpy(pt->ap_BasicDataTransferRates,""); |
| - strcpy(pt->ap_SupportedDataTransferRates,""); |
| - pt->ap_DTIMPeriod=1; |
| - pt->ap_ChannelUtilization=0; |
| + while ((read = getline(&line, &len, f)) != -1) { |
| + if(strstr(line, "BSS") != NULL) { // new neighbor info |
| + // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag. |
| + // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop. |
| + // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS. |
| + |
| + if (!filter_BSS) { |
| + index++; |
| + wifi_neighbor_ap2_t *tmp; |
| + tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1)); |
| + if (tmp == NULL) { // no more memory to use |
| + index--; |
| + wifi_dbg_printf("%s: realloc failed\n", __func__); |
| + break; |
| + } |
| + scan_array = tmp; |
| + } |
| + memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t)); |
| + |
| + filter_BSS = false; |
| + sscanf(line, "BSS %17s", scan_array[index].ap_BSSID); |
| + strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure")); |
| + strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None")); |
| + strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None")); |
| + } else if (strstr(line, "freq") != NULL) { |
| + sscanf(line," freq: %d", &freq); |
| + scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq); |
| + |
| + if (freq >= 2412 && freq <= 2484) { |
| + strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")); |
| + strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g")); |
| + strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g")); |
| + } |
| + else if (freq >= 5160 && freq <= 5805) { |
| + strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")); |
| + strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a")); |
| + strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a")); |
| + } |
| + |
| + scan_array[index].ap_Noise = 0; |
| + if (get_nosie_ret) { |
| + for (int i = 0; i < channels_num; i++) { |
| + if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) { |
| + scan_array[index].ap_Noise = channels_noise_arr[i].noise; |
| + break; |
| + } |
| + } |
| + } |
| + } else if (strstr(line, "beacon interval") != NULL) { |
| + sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod)); |
| + } else if (strstr(line, "signal") != NULL) { |
| + sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength)); |
| + } else if (strstr(line,"SSID") != NULL) { |
| + sscanf(line," SSID: %s", scan_array[index].ap_SSID); |
| + if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) { |
| + filter_BSS = true; |
| + } |
| + } else if (strstr(line, "Supported rates") != NULL) { |
| + char SRate[64] = {0}, *tmp = NULL; |
| + memset(buf, 0, sizeof(buf)); |
| + strcpy(SRate, line); |
| + tmp = strtok(SRate, ":"); |
| + tmp = strtok(NULL, ":"); |
| + strcpy(buf, tmp); |
| + memset(SRate, 0, sizeof(SRate)); |
| + |
| + tmp = strtok(buf, " \n"); |
| + while (tmp != NULL) { |
| + strcat(SRate, tmp); |
| + if (SRate[strlen(SRate) - 1] == '*') { |
| + SRate[strlen(SRate) - 1] = '\0'; |
| + } |
| + strcat(SRate, ","); |
| + |
| + tmp = strtok(NULL, " \n"); |
| + } |
| + SRate[strlen(SRate) - 1] = '\0'; |
| + strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate); |
| + } else if (strstr(line, "DTIM") != NULL) { |
| + sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf); |
| + } else if (strstr(line, "VHT capabilities") != NULL) { |
| + strcat(scan_array[index].ap_SupportedStandards, ",ac"); |
| + strcpy(scan_array[index].ap_OperatingStandards, "ac"); |
| + } else if (strstr(line, "HT capabilities") != NULL) { |
| + strcat(scan_array[index].ap_SupportedStandards, ",n"); |
| + strcpy(scan_array[index].ap_OperatingStandards, "n"); |
| + } else if (strstr(line, "VHT operation") != NULL) { |
| + read = getline(&line, &len, f); |
| + sscanf(line," * channel width: %d", &vht_channel_width); |
| + if(vht_channel_width == 1) { |
| + snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80"); |
| + } else { |
| + snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40"); |
| + } |
| + if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information |
| + continue; |
| + } else if (strstr(line, "HT operation") != NULL) { |
| + read = getline(&line, &len, f); |
| + sscanf(line," * secondary channel offset: %s", &buf); |
| + if (!strcmp(buf, "above")) { |
| + //40Mhz + |
| + snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G"); |
| + } |
| + else if (!strcmp(buf, "below")) { |
| + //40Mhz - |
| + snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G"); |
| + } else { |
| + //20Mhz |
| + snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G"); |
| + } |
| + if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information |
| + continue; |
| + } else if (strstr(line, "HE capabilities") != NULL) { |
| + strncat(scan_array[index].ap_SupportedStandards, ",ax", strlen(",ax")); |
| + strncpy(scan_array[index].ap_OperatingStandards, "ax", strlen("ax")); |
| + } else if (strstr(line, "HE PHY Capabilities") != NULL) { |
| + if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) { |
| + if (strstr(line, "HE40/2.4GHz") != NULL) |
| + strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS", strlen("11AXHE40PLUS")); |
| + else |
| + strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20", strlen("11AXHE20")); |
| + |
| + } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) { |
| + strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80", strlen("11AXHE80")); // AP must always support |
| + read = getline(&line, &len, f); |
| + if (strstr(line, "HE160/5GHz") != NULL) |
| + strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160", strlen("11AXHE160")); |
| + } |
| + if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information |
| + continue; |
| + } else if (strstr(line, "WPA") != NULL) { |
| + strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA"); |
| + } else if (strstr(line, "RSN") != NULL) { |
| + strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN"); |
| + } else if (strstr(line, "Group cipher") != NULL) { |
| + sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode); |
| + if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) { |
| + strcpy(scan_array[index].ap_EncryptionMode, "AES"); |
| + } |
| + } |
| } |
| |
| - status = RETURN_OK; |
| + if (!filter_BSS) { |
| + *output_array_size = index + 1; |
| + } else { |
| + memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t)); |
| + *output_array_size = index; |
| + } |
| + *neighbor_ap_array = scan_array; |
| + free(line); |
| + pclose(f); |
| WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__); |
| - return status; |
| + return RETURN_OK; |
| } |
| |
| //>> Deprecated: used for old RDKB code. |
| @@ -7635,7 +7833,38 @@ INT wifi_setApCsaDeauth(INT apIndex, INT mode) |
| |
| INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid) |
| { |
| - // TODO Implement me! |
| + char file_name[128] = {0}; |
| + char buf[128] = {0}; |
| + FILE *f = NULL; |
| + |
| + WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__); |
| + |
| + if (essid == NULL || strlen(essid) == 0 || apIndex == -1) { |
| + for (int index = 0; index < NUMBER_OF_RADIOS; index++) { |
| + snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index); |
| + f = fopen(file_name, "w"); |
| + if (f == NULL) |
| + return RETURN_ERR; |
| + // For mode == 0 is to disable filter, just don't write to the file. |
| + if (mode) |
| + fprintf(f, "%s", essid); |
| + |
| + fclose(f); |
| + } |
| + } else { // special case, need to set AP's SSID as filter for each radio. |
| + snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex); |
| + f = fopen(file_name, "w"); |
| + if (f == NULL) |
| + return RETURN_ERR; |
| + |
| + // For mode == 0 is to disable filter, just don't write to the file. |
| + if (mode) |
| + fprintf(f, "%s", essid); |
| + |
| + fclose(f); |
| + } |
| + |
| + WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__); |
| return RETURN_OK; |
| } |
| |
| -- |
| 2.18.0 |
| |