blob: 4f862e824f5a486ec29ba72616819b3db18e58ff [file] [log] [blame]
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