X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=plugins%2Fwifi.c;h=7c159963cd501ee4e8bf269216910bcb9a233673;hb=refs%2Ftags%2Fsubmit%2Ftizen%2F20211230.103710;hp=96c84b135b03a8a530bc4d163e4b0f478b5fd29e;hpb=d0e647678d78604a042c5a607697b43a2342c916;p=platform%2Fupstream%2Fconnman.git diff --git a/plugins/wifi.c b/plugins/wifi.c index 96c84b1..7c15996 100755 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -83,6 +83,29 @@ #if defined TIZEN_EXT #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */ + + /* Wi-Fi Signal Strength (for 2.4G (dB)) + * Excellent : ~ -63 + * Good : -64 ~ -74 + * Weak : -75 ~ -82 + * Very weak : -83 ~ -88 + * No signal : -89 ~ + * + * Wi-Fi Signal Strength (for 5G (dB)) + * Excellent : ~ -67 + * Good : -68 ~ -76 + * Weak : -77 ~ -82 + * Very weak : -83 ~ -88 + * No signal : -89 ~ + */ +#define RSSI_LEVEL_2_5G -77 +#define RSSI_LEVEL_2_24G -75 +#define RSSI_LEVEL_3_5G -68 +#define RSSI_LEVEL_3_24G -64 +#define WIFI_BSSID_STR_LEN 18 +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" +#define ROAM_SCAN_INTERVAL 60 /* 60 seconds */ #endif static struct connman_technology *wifi_technology = NULL; @@ -2086,8 +2109,57 @@ static void service_state_changed(struct connman_service *service, } } +static gboolean need_bss_transition(uint16_t freq, int snr, int strength) +{ + /* + * Since bssid->strength is a positive value, + * it need to be changed to its original value. + */ + int signal = strength - 120; + + /* + * If the currently connected AP matches the following conditions, + * scan for BSS transition is started. + * - SNR is less than 20 or RSSI level is less than 3 + */ + if (snr < 20 && snr != 0) + return TRUE; + else if (freq > 4900 && signal <= RSSI_LEVEL_2_5G) + return TRUE; + else if (freq <= 4900 && signal <= RSSI_LEVEL_2_24G) + return TRUE; + + return FALSE; +} + +static gboolean check_bss_condition(uint16_t freq, int snr, uint16_t strength) +{ + /* + * Since bssid->strength is a positive value, + * it need to be changed to its original value. + */ + int signal = strength - 120; + + /* + * If the AP that matches the following conditions exists in the SCAN result, + * BSS transition is started. + * - SNR is 25 or more and RSSI level is greater than 3 + */ + if (snr < 25 && snr != 0) + return FALSE; + + if (freq > 4900 && signal > RSSI_LEVEL_3_5G) + return TRUE; + else if (freq <= 4900 && signal > RSSI_LEVEL_3_24G) + return TRUE; + + return FALSE; +} + static void scan_callback_hidden(int result, GSupplicantInterface *interface, void *user_data); + +static int network_disconnect(struct connman_network *network); #endif static void scan_callback(int result, GSupplicantInterface *interface, @@ -2097,7 +2169,10 @@ static void scan_callback(int result, GSupplicantInterface *interface, struct wifi_data *wifi = connman_device_get_data(device); bool scanning; #if defined TIZEN_EXT + bool roaming_needed = false; + bool roaming_ap_found = false; GSList *list = NULL; + GSList *bssid_list = NULL; bool favorite_exists = false; struct connman_network *network = NULL; struct connman_service *service = NULL; @@ -2157,7 +2232,8 @@ static void scan_callback(int result, GSupplicantInterface *interface, if (service != NULL && (connman_service_get_favorite(service) == true) && (connman_service_get_autoconnect(service) == true)) { - DBG("Favorite service exists [%s]", connman_network_get_string(network, "Name")); + DBG("Favorite service exists [%s]", + connman_network_get_string(network, "Name")); favorite_exists = true; break; } @@ -2178,7 +2254,8 @@ static void scan_callback(int result, GSupplicantInterface *interface, /* On error, let's recall scan_callback, which will cleanup */ return scan_callback(ret, interface, user_data); } - } + } else + wifi->allow_full_scan = false; #endif scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI); @@ -2209,8 +2286,49 @@ static void scan_callback(int result, GSupplicantInterface *interface, network_connect(wifi->scan_pending_network); wifi->scan_pending_network = NULL; connman_network_set_connecting(wifi->network); + } else if (connman_setting_get_bool("WifiRoaming") && wifi->network) { + bssid_list = connman_network_get_bssid_list(wifi->network); + + if (g_slist_length(bssid_list) <= 1) + goto done; + + if (!connman_network_get_connected(wifi->network)) + goto done; + + if (connman_network_get_bool(wifi->network, "WiFi.Roaming")) + goto done; + + if (!need_bss_transition( + connman_network_get_frequency(wifi->network), + connman_network_get_snr(wifi->network), + connman_network_get_strength(wifi->network))) + goto done; + + for (bssid_list; bssid_list; bssid_list = bssid_list->next) { + struct g_connman_bssids *bssid = bssid_list->data; + + if (check_bss_condition(bssid->frequency, + bssid->score_snr, bssid->strength)) + roaming_ap_found = true; + } + + if (roaming_ap_found) { + char bssid_buff[WIFI_BSSID_STR_LEN] = {0,}; + char *bssid_str = bssid_buff; + unsigned char *bssid; + + bssid = connman_network_get_bssid(wifi->network); + snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid)); + connman_network_set_string(wifi->network, + "WiFi.RoamingCurBSSID", bssid_str); + + network_disconnect(wifi->network); + wifi->pending_network = wifi->network; + connman_network_set_bool(wifi->network, "WiFi.Roaming", true); + } } +done: if (is_wifi_notifier_registered != true && wifi_first_scan == true && found_with_first_scan == true) { wifi_first_scan = false; @@ -3524,6 +3642,38 @@ static void connect_callback(int result, GSupplicantInterface *interface, return; found: + if (connman_network_get_bool(network, "WiFi.Roaming")) { + if (result < 0 ) { + connman_network_set_bool(network, "WiFi.Roaming", false); + connman_network_set_string(network, + "WiFi.RoamingCurBSSID", NULL); + } else { + char bssid_buff[WIFI_BSSID_STR_LEN] = {0,}; + char *bssid_str = bssid_buff; + unsigned char *bssid; + const char *cur_bssid; + + bssid = g_supplicant_interface_get_add_network_bssid(interface); + if (!bssid) { + connman_network_set_bool(network, "WiFi.Roaming", false); + connman_network_set_string(network, + "WiFi.RoamingCurBSSID", NULL); + } else { + snprintf(bssid_str, + WIFI_BSSID_STR_LEN, + MACSTR, MAC2STR(bssid)); + + connman_network_set_string(network, + "WiFi.RoamingDstBSSID", bssid_str); + + cur_bssid = connman_network_get_string(network, + "WiFi.RoamingCurBSSID"); + + __connman_technology_notify_roaming_state(ifname, + "started", cur_bssid, bssid_str); + } + } + } #endif if (result == -ENOKEY) { connman_network_set_error(network, @@ -3817,7 +3967,13 @@ found: return; } +#if defined TIZEN_EXT + if (wifi->network && + (wifi->network != wifi->pending_network || + connman_network_get_bool(wifi->network, "WiFi.Roaming"))) +#else if (wifi->network && wifi->network != wifi->pending_network) +#endif connman_network_set_connected(wifi->network, false); wifi->network = NULL; @@ -3964,9 +4120,17 @@ static void set_connection_mode(struct connman_network *network, } static void signalpoll_callback(int result, int maxspeed, int strength, - void *user_data) -{ + int snr, void *user_data) +{ + char bssid_buff[WIFI_BSSID_STR_LEN] = {0,}; + char *bssid_str = bssid_buff; + unsigned char *bssid; + struct timespec curr_time = {0}; + __time_t roam_scan_time; + const char *interface = NULL; + struct connman_device *device; struct connman_network *network = user_data; + uint16_t freq = connman_network_get_frequency(network); if (result != 0) { DBG("Failed to get maxspeed from signalpoll !"); @@ -3978,12 +4142,35 @@ static void signalpoll_callback(int result, int maxspeed, int strength, if (strength > 100) strength = 100; - DBG("maxspeed = %d, strength = %d", maxspeed, strength); + DBG("freq = %u, maxspeed = %d, strength = %d, snr = %d", freq, maxspeed, strength, snr); connman_network_set_strength(network, (uint8_t)strength); + connman_network_set_snr(network, snr); connman_network_set_maxspeed(network, maxspeed); set_connection_mode(network, maxspeed); + clock_gettime(CLOCK_MONOTONIC, &curr_time); + roam_scan_time = connman_network_get_roam_scan_time(network); + if (curr_time.tv_sec <= roam_scan_time + ROAM_SCAN_INTERVAL) + goto done; + + if (need_bss_transition(freq, snr, strength)) { + device = connman_network_get_device(network); + if (device) + interface = connman_device_get_string(device, "Interface"); + + bssid = connman_network_get_bssid(network); + snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid)); + __connman_technology_notify_roaming_state(interface, "required", bssid_str, NULL); + + if (connman_setting_get_bool("WifiRoamingScan") == false) + goto done; + + throw_wifi_scan(device, scan_callback); + connman_network_set_roam_scan_time(network, curr_time.tv_sec); + } + +done: connman_network_unref(network); } @@ -4021,6 +4208,7 @@ static gboolean autosignalpoll_timeout(gpointer data) if (wifi->network) connman_network_unref(wifi->network); + return FALSE; } @@ -4371,6 +4559,13 @@ static void interface_state(GSupplicantInterface *interface) switch (state) { case G_SUPPLICANT_STATE_SCANNING: +#if defined TIZEN_EXT + if (wifi->automaxspeed_timeout != 0) { + g_source_remove(wifi->automaxspeed_timeout); + wifi->automaxspeed_timeout = 0; + DBG("Remove signalpoll timer!!"); + } +#endif if (wifi->connected) connman_network_set_connected(network, false); @@ -4908,6 +5103,59 @@ static void mesh_peer_removed(GSupplicantNetwork *supplicant_network) } #endif + +#if defined TIZEN_EXT +static GSList *get_supported_security_list(unsigned int keymgmt, + bool owe_transition_mode, + GSupplicantNetwork *supplicant_network) +{ + GSList *sec_list = NULL; + dbus_bool_t privacy = g_supplicant_network_get_privacy(supplicant_network); + const char *enc_mode = g_supplicant_network_get_enc_mode(supplicant_network); + + if (keymgmt & + (G_SUPPLICANT_KEYMGMT_WPA_EAP | + G_SUPPLICANT_KEYMGMT_WPA_EAP_256)) + sec_list = g_slist_prepend (sec_list, "ieee8021x"); + else if (keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP) + sec_list = g_slist_prepend (sec_list, "ft_ieee8021x"); + + if (sec_list) + return sec_list; + + if (keymgmt & + (G_SUPPLICANT_KEYMGMT_WPA_PSK | + G_SUPPLICANT_KEYMGMT_WPA_PSK_256)) { + if (!g_strcmp0(enc_mode, "aes")) + sec_list = g_slist_prepend (sec_list, "rsn"); + else if (!g_strcmp0(enc_mode, "tkip")) + sec_list = g_slist_prepend (sec_list, "psk"); + else if (!g_strcmp0(enc_mode, "mixed")) { + sec_list = g_slist_prepend (sec_list, "psk"); + sec_list = g_slist_prepend (sec_list, "rsn"); + } + } else if (keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK) + sec_list = g_slist_prepend (sec_list, "ft_psk"); + + if (keymgmt & G_SUPPLICANT_KEYMGMT_SAE) + sec_list = g_slist_prepend (sec_list, "sae"); + if (keymgmt & G_SUPPLICANT_KEYMGMT_OWE || owe_transition_mode) + sec_list = g_slist_prepend (sec_list, "owe"); + if (keymgmt & G_SUPPLICANT_KEYMGMT_DPP) + sec_list = g_slist_prepend (sec_list, "dpp"); + + if (sec_list) + return sec_list; + + if (privacy) + sec_list = g_slist_prepend (sec_list, "wep"); + else + sec_list = g_slist_prepend (sec_list, "none"); + + return sec_list; +} +#endif + static void network_added(GSupplicantNetwork *supplicant_network) { struct connman_network *network; @@ -4926,7 +5174,9 @@ static void network_added(GSupplicantNetwork *supplicant_network) const unsigned char *transition_mode_ssid; const unsigned char *transition_mode_bssid; unsigned int transition_mode_ssid_len; + unsigned int keymgmt; GSList *vsie_list = NULL; + GSList *sec_list = NULL; const unsigned char *country_code; ieee80211_modes_e phy_mode; #endif @@ -5030,6 +5280,7 @@ static void network_added(GSupplicantNetwork *supplicant_network) g_supplicant_network_get_frequency(supplicant_network)); #if defined TIZEN_EXT + keymgmt = g_supplicant_network_get_keymgmt(supplicant_network); connman_network_set_bssid(network, g_supplicant_network_get_bssid(supplicant_network)); owe_transition_mode = (bool)g_supplicant_network_get_transition_mode(supplicant_network); @@ -5041,14 +5292,18 @@ static void network_added(GSupplicantNetwork *supplicant_network) transition_mode_bssid = g_supplicant_network_get_transition_mode_bssid(supplicant_network); connman_network_set_transition_mode_bssid(network, transition_mode_bssid); } + + sec_list = get_supported_security_list(keymgmt, + owe_transition_mode, supplicant_network); + + connman_network_set_sec_list(network, sec_list); connman_network_set_maxrate(network, g_supplicant_network_get_maxrate(supplicant_network)); connman_network_set_enc_mode(network, g_supplicant_network_get_enc_mode(supplicant_network)); connman_network_set_rsn_mode(network, g_supplicant_network_get_rsn_mode(supplicant_network)); - connman_network_set_keymgmt(network, - g_supplicant_network_get_keymgmt(supplicant_network)); + connman_network_set_keymgmt(network, keymgmt); connman_network_set_bool(network, "WiFi.HS20AP", g_supplicant_network_is_hs20AP(supplicant_network)); connman_network_set_bssid_list(network,