developer | f4a4878 | 2022-08-02 18:22:33 +0800 | [diff] [blame] | 1 | From 4592e371528abdf4804c116760059b0a0fb4dbc6 Mon Sep 17 00:00:00 2001 |
| 2 | From: "Allen.Ye" <allen.ye@mediatek.com> |
| 3 | Date: Tue, 2 Aug 2022 17:23:06 +0800 |
| 4 | Subject: [PATCH] HAL: refactor NeighboringWiFiDiagnosticResult2 scan part and |
| 5 | add scan filter function |
| 6 | |
| 7 | --- |
| 8 | source/wifi/wifi_hal.c | 289 ++++++++++++++++++++++++++++++++++++----- |
| 9 | 1 file changed, 259 insertions(+), 30 deletions(-) |
| 10 | |
| 11 | diff --git a/source/wifi/wifi_hal.c b/source/wifi/wifi_hal.c |
| 12 | index e49f22f..44f167b 100644 |
| 13 | --- a/source/wifi/wifi_hal.c |
| 14 | +++ b/source/wifi/wifi_hal.c |
| 15 | @@ -73,6 +73,8 @@ Licensed under the ISC license |
| 16 | //#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention |
| 17 | #define SOCK_PREFIX "/var/run/hostapd/wifi" |
| 18 | #define VAP_STATUS_FILE "/tmp/vap-status" |
| 19 | +#define ESSID_FILE "/tmp/essid" |
| 20 | + |
| 21 | #ifdef MTK_IMPL |
| 22 | #define DRIVER_2GHZ "mt7915e" |
| 23 | #define DRIVER_5GHZ "mt7915e" |
| 24 | @@ -3037,47 +3039,243 @@ INT wifi_applySSIDSettings(INT ssidIndex) |
| 25 | return ret; |
| 26 | } |
| 27 | |
| 28 | +struct channels_noise { |
| 29 | + int channel; |
| 30 | + int noise; |
| 31 | +}; |
| 32 | + |
| 33 | +// Return noise array for each channel |
| 34 | +int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num) |
| 35 | +{ |
| 36 | + FILE *f = NULL; |
| 37 | + char cmd[128] = {0}; |
| 38 | + char *line = NULL; |
| 39 | + size_t len = 0; |
| 40 | + ssize_t read = 0; |
| 41 | + int tmp = 0, arr_index = -1; |
| 42 | + |
| 43 | + sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex); |
| 44 | + |
| 45 | + if ((f = popen(cmd, "r")) == NULL) { |
| 46 | + wifi_dbg_printf("%s: popen %s error\n", __func__, cmd); |
| 47 | + return RETURN_ERR; |
| 48 | + } |
| 49 | + |
| 50 | + while((read = getline(&line, &len, f)) != -1) { |
| 51 | + sscanf(line, "%d", &tmp); |
| 52 | + if (tmp > 0) { // channel frequency, the first line must be frequency |
| 53 | + arr_index++; |
| 54 | + channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp); |
| 55 | + } else { // noise |
| 56 | + channels_noise_arr[arr_index].noise = tmp; |
| 57 | + } |
| 58 | + } |
| 59 | + free(line); |
| 60 | + pclose(f); |
| 61 | + return RETURN_OK; |
| 62 | +} |
| 63 | + |
| 64 | //Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list |
| 65 | //HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array" |
| 66 | INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181 |
| 67 | { |
| 68 | - INT status = RETURN_ERR; |
| 69 | - UINT index; |
| 70 | - wifi_neighbor_ap2_t *pt=NULL; |
| 71 | - char cmd[128]={0}; |
| 72 | - char buf[8192]={0}; |
| 73 | + int index = -1; |
| 74 | + wifi_neighbor_ap2_t *scan_array = NULL; |
| 75 | + char cmd[256]={0}; |
| 76 | + char buf[128]={0}; |
| 77 | + char file_name[32] = {0}; |
| 78 | + char filter_SSID[32] = {0}; |
| 79 | + int freq=0; |
| 80 | + FILE *f = NULL; |
| 81 | + size_t len=0; |
| 82 | + ssize_t read = 0; |
| 83 | + char *line =NULL; |
| 84 | + // int noise_arr[channels_num] = {0}; |
| 85 | + int channels_num = 0; |
| 86 | + int vht_channel_width = 0; |
| 87 | + bool get_nosie_ret = false; |
| 88 | + bool filter_enable = false; |
| 89 | + bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd. |
| 90 | |
| 91 | WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__); |
| 92 | - sprintf(cmd, "iwlist %s%d scan",AP_PREFIX,(radioIndex==0)?0:1); //suppose ap0 mapping to radio0 |
| 93 | + |
| 94 | + snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex); |
| 95 | + f = fopen(file_name, "r"); |
| 96 | + if (f != NULL) { |
| 97 | + fgets(filter_SSID, sizeof(file_name), f); |
| 98 | + if (strlen(filter_SSID) != 0) |
| 99 | + filter_enable = true; |
| 100 | + fclose(f); |
| 101 | + } |
| 102 | + |
| 103 | + snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex); |
| 104 | _syscmd(cmd, buf, sizeof(buf)); |
| 105 | + channels_num = atoi(buf); |
| 106 | |
| 107 | + struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise)); |
| 108 | + get_nosie_ret = get_noise(radioIndex, channels_noise_arr, channels_num); |
| 109 | + |
| 110 | + sprintf(cmd, "iw dev %s%d scan | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \ |
| 111 | + // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE160' | grep -v -e '*.*BSS'", AP_PREFIX, radioIndex, AP_PREFIX, radioIndex); |
| 112 | + fprintf(stderr, "cmd: %s\n", cmd); |
| 113 | + if ((f = popen(cmd, "r")) == NULL) { |
| 114 | + wifi_dbg_printf("%s: popen %s error\n", __func__, cmd); |
| 115 | + return RETURN_ERR; |
| 116 | + } |
| 117 | |
| 118 | - *output_array_size=2; |
| 119 | - //zqiu: HAL alloc the array and return to caller. Caller response to free it. |
| 120 | - *neighbor_ap_array=(wifi_neighbor_ap2_t *)calloc(sizeof(wifi_neighbor_ap2_t), *output_array_size); |
| 121 | - for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) { |
| 122 | - strcpy(pt->ap_SSID,""); |
| 123 | - strcpy(pt->ap_BSSID,""); |
| 124 | - strcpy(pt->ap_Mode,""); |
| 125 | - pt->ap_Channel=1; |
| 126 | - pt->ap_SignalStrength=0; |
| 127 | - strcpy(pt->ap_SecurityModeEnabled,""); |
| 128 | - strcpy(pt->ap_EncryptionMode,""); |
| 129 | - strcpy(pt->ap_OperatingFrequencyBand,""); |
| 130 | - strcpy(pt->ap_SupportedStandards,""); |
| 131 | - strcpy(pt->ap_OperatingStandards,""); |
| 132 | - strcpy(pt->ap_OperatingChannelBandwidth,""); |
| 133 | - pt->ap_BeaconPeriod=1; |
| 134 | - pt->ap_Noise=0; |
| 135 | - strcpy(pt->ap_BasicDataTransferRates,""); |
| 136 | - strcpy(pt->ap_SupportedDataTransferRates,""); |
| 137 | - pt->ap_DTIMPeriod=1; |
| 138 | - pt->ap_ChannelUtilization=0; |
| 139 | + while ((read = getline(&line, &len, f)) != -1) { |
| 140 | + if(strstr(line, "BSS") != NULL) { // new neighbor info |
| 141 | + // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag. |
| 142 | + // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop. |
| 143 | + // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS. |
| 144 | + |
| 145 | + if (!filter_BSS) { |
| 146 | + index++; |
| 147 | + wifi_neighbor_ap2_t *tmp; |
| 148 | + tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1)); |
| 149 | + if (tmp == NULL) { // no more memory to use |
| 150 | + index--; |
| 151 | + wifi_dbg_printf("%s: realloc failed\n", __func__); |
| 152 | + break; |
| 153 | + } |
| 154 | + scan_array = tmp; |
| 155 | + } |
| 156 | + memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t)); |
| 157 | + |
| 158 | + filter_BSS = false; |
| 159 | + sscanf(line, "BSS %17s", scan_array[index].ap_BSSID); |
| 160 | + strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure")); |
| 161 | + strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None")); |
| 162 | + strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None")); |
| 163 | + } else if (strstr(line, "freq") != NULL) { |
| 164 | + sscanf(line," freq: %d", &freq); |
| 165 | + scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq); |
| 166 | + |
| 167 | + if (freq >= 2412 && freq <= 2484) { |
| 168 | + strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")); |
| 169 | + strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g")); |
| 170 | + strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g")); |
| 171 | + } |
| 172 | + else if (freq >= 5160 && freq <= 5805) { |
| 173 | + strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")); |
| 174 | + strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a")); |
| 175 | + strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a")); |
| 176 | + } |
| 177 | + |
| 178 | + scan_array[index].ap_Noise = 0; |
| 179 | + if (get_nosie_ret) { |
| 180 | + for (int i = 0; i < channels_num; i++) { |
| 181 | + if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) { |
| 182 | + scan_array[index].ap_Noise = channels_noise_arr[i].noise; |
| 183 | + break; |
| 184 | + } |
| 185 | + } |
| 186 | + } |
| 187 | + } else if (strstr(line, "beacon interval") != NULL) { |
| 188 | + sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod)); |
| 189 | + } else if (strstr(line, "signal") != NULL) { |
| 190 | + sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength)); |
| 191 | + } else if (strstr(line,"SSID") != NULL) { |
| 192 | + sscanf(line," SSID: %s", scan_array[index].ap_SSID); |
| 193 | + if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) { |
| 194 | + filter_BSS = true; |
| 195 | + } |
| 196 | + } else if (strstr(line, "Supported rates") != NULL) { |
| 197 | + char SRate[64] = {0}, *tmp = NULL; |
| 198 | + memset(buf, 0, sizeof(buf)); |
| 199 | + strcpy(SRate, line); |
| 200 | + tmp = strtok(SRate, ":"); |
| 201 | + tmp = strtok(NULL, ":"); |
| 202 | + strcpy(buf, tmp); |
| 203 | + memset(SRate, 0, sizeof(SRate)); |
| 204 | + |
| 205 | + tmp = strtok(buf, " \n"); |
| 206 | + while (tmp != NULL) { |
| 207 | + strcat(SRate, tmp); |
| 208 | + if (SRate[strlen(SRate) - 1] == '*') { |
| 209 | + SRate[strlen(SRate) - 1] = '\0'; |
| 210 | + } |
| 211 | + strcat(SRate, ","); |
| 212 | + |
| 213 | + tmp = strtok(NULL, " \n"); |
| 214 | + } |
| 215 | + SRate[strlen(SRate) - 1] = '\0'; |
| 216 | + strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate); |
| 217 | + } else if (strstr(line, "DTIM") != NULL) { |
| 218 | + sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf); |
| 219 | + } else if (strstr(line, "VHT capabilities") != NULL) { |
| 220 | + strcat(scan_array[index].ap_SupportedStandards, ",ac"); |
| 221 | + strcpy(scan_array[index].ap_OperatingStandards, "ac"); |
| 222 | + } else if (strstr(line, "HT capabilities") != NULL) { |
| 223 | + strcat(scan_array[index].ap_SupportedStandards, ",n"); |
| 224 | + strcpy(scan_array[index].ap_OperatingStandards, "n"); |
| 225 | + } else if (strstr(line, "VHT operation") != NULL) { |
| 226 | + read = getline(&line, &len, f); |
| 227 | + sscanf(line," * channel width: %d", &vht_channel_width); |
| 228 | + if(vht_channel_width == 1) { |
| 229 | + snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80"); |
| 230 | + } else { |
| 231 | + snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40"); |
| 232 | + } |
| 233 | + if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information |
| 234 | + continue; |
| 235 | + } else if (strstr(line, "HT operation") != NULL) { |
| 236 | + read = getline(&line, &len, f); |
| 237 | + sscanf(line," * secondary channel offset: %s", &buf); |
| 238 | + if (!strcmp(buf, "above")) { |
| 239 | + //40Mhz + |
| 240 | + snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G"); |
| 241 | + } |
| 242 | + else if (!strcmp(buf, "below")) { |
| 243 | + //40Mhz - |
| 244 | + snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G"); |
| 245 | + } else { |
| 246 | + //20Mhz |
| 247 | + snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G"); |
| 248 | + } |
| 249 | + if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information |
| 250 | + continue; |
| 251 | + } else if (strstr(line, "HE capabilities") != NULL) { |
| 252 | + strncat(scan_array[index].ap_SupportedStandards, ",ax", strlen(",ax")); |
| 253 | + strncpy(scan_array[index].ap_OperatingStandards, "ax", strlen("ax")); |
| 254 | + } else if (strstr(line, "HE PHY Capabilities") != NULL) { |
| 255 | + if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) { |
| 256 | + if (strstr(line, "HE40/2.4GHz") != NULL) |
| 257 | + strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS", strlen("11AXHE40PLUS")); |
| 258 | + else |
| 259 | + strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20", strlen("11AXHE20")); |
| 260 | + |
| 261 | + } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) { |
| 262 | + strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80", strlen("11AXHE80")); // AP must always support |
| 263 | + read = getline(&line, &len, f); |
| 264 | + if (strstr(line, "HE160/5GHz") != NULL) |
| 265 | + strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160", strlen("11AXHE160")); |
| 266 | + } |
| 267 | + if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information |
| 268 | + continue; |
| 269 | + } else if (strstr(line, "WPA") != NULL) { |
| 270 | + strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA"); |
| 271 | + } else if (strstr(line, "RSN") != NULL) { |
| 272 | + strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN"); |
| 273 | + } else if (strstr(line, "Group cipher") != NULL) { |
| 274 | + sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode); |
| 275 | + if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) { |
| 276 | + strcpy(scan_array[index].ap_EncryptionMode, "AES"); |
| 277 | + } |
| 278 | + } |
| 279 | } |
| 280 | |
| 281 | - status = RETURN_OK; |
| 282 | + if (!filter_BSS) { |
| 283 | + *output_array_size = index + 1; |
| 284 | + } else { |
| 285 | + memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t)); |
| 286 | + *output_array_size = index; |
| 287 | + } |
| 288 | + *neighbor_ap_array = scan_array; |
| 289 | + free(line); |
| 290 | + pclose(f); |
| 291 | WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__); |
| 292 | - return status; |
| 293 | + return RETURN_OK; |
| 294 | } |
| 295 | |
| 296 | //>> Deprecated: used for old RDKB code. |
| 297 | @@ -7635,7 +7833,38 @@ INT wifi_setApCsaDeauth(INT apIndex, INT mode) |
| 298 | |
| 299 | INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid) |
| 300 | { |
| 301 | - // TODO Implement me! |
| 302 | + char file_name[128] = {0}; |
| 303 | + char buf[128] = {0}; |
| 304 | + FILE *f = NULL; |
| 305 | + |
| 306 | + WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__); |
| 307 | + |
| 308 | + if (essid == NULL || strlen(essid) == 0 || apIndex == -1) { |
| 309 | + for (int index = 0; index < NUMBER_OF_RADIOS; index++) { |
| 310 | + snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index); |
| 311 | + f = fopen(file_name, "w"); |
| 312 | + if (f == NULL) |
| 313 | + return RETURN_ERR; |
| 314 | + // For mode == 0 is to disable filter, just don't write to the file. |
| 315 | + if (mode) |
| 316 | + fprintf(f, "%s", essid); |
| 317 | + |
| 318 | + fclose(f); |
| 319 | + } |
| 320 | + } else { // special case, need to set AP's SSID as filter for each radio. |
| 321 | + snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex); |
| 322 | + f = fopen(file_name, "w"); |
| 323 | + if (f == NULL) |
| 324 | + return RETURN_ERR; |
| 325 | + |
| 326 | + // For mode == 0 is to disable filter, just don't write to the file. |
| 327 | + if (mode) |
| 328 | + fprintf(f, "%s", essid); |
| 329 | + |
| 330 | + fclose(f); |
| 331 | + } |
| 332 | + |
| 333 | + WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__); |
| 334 | return RETURN_OK; |
| 335 | } |
| 336 | |
| 337 | -- |
| 338 | 2.18.0 |
| 339 | |