Use SNR and estimated throughput for BSS scoring
[platform/upstream/connman.git] / gsupplicant / supplicant.c
index cfdb183..906f0ea 100755 (executable)
@@ -304,6 +304,8 @@ struct g_supplicant_bss {
        dbus_bool_t hs20;
        unsigned char country_code[COUNTRY_CODE_LENGTH];
        GSupplicantPhy_mode phy_mode;
+       dbus_int16_t snr;
+       dbus_uint32_t est_throughput;
 #endif
        unsigned int wps_capabilities;
 #if defined TIZEN_EXT
@@ -398,6 +400,11 @@ struct interface_create_data {
        char *ifname;
        char *driver;
        char *bridge;
+#if defined TIZEN_EXT
+       unsigned int mac_addr;
+       unsigned int preassoc_mac_addr;
+       unsigned int random_mac_lifetime;
+#endif /* TIZEN_EXT */
 #if defined TIZEN_EXT_WIFI_MESH
        char *parent_ifname;
        bool is_mesh_interface;
@@ -438,6 +445,8 @@ struct g_connman_bssids {
        int score_assoc_reject;
        int score_frequency;
        int score_strength;
+       int score_snr;
+       int score_est_throughput;
 #endif
        int ins_score;
 };
@@ -2105,8 +2114,22 @@ static int calculate_score_strength(dbus_int16_t strength)
        return score;
 }
 
+static int calculate_score_est_throughput(dbus_uint32_t est_throughput)
+{
+       int score = 0;
+
+       if (est_throughput >= 10000)
+               score = est_throughput / 10000;
+
+       if (score > 40)
+               score = 40;
+
+       return score;
+}
+
 static int calculate_score(bool is_last_connected, uint16_t assoc_reject_cnt,
-               dbus_int16_t strength, dbus_uint16_t frequency)
+               dbus_uint16_t frequency, dbus_int16_t strength,
+               dbus_int16_t snr, dbus_uint32_t est_throughput)
 {
        int score = 0;
 
@@ -2114,6 +2137,8 @@ static int calculate_score(bool is_last_connected, uint16_t assoc_reject_cnt,
        score += calculate_score_assoc_reject(assoc_reject_cnt);
        score += calculate_score_frequency(strength, frequency);
        score += calculate_score_strength(strength);
+       score += (int)snr;
+       score += calculate_score_est_throughput(est_throughput);
 
        return score;
 }
@@ -2146,10 +2171,13 @@ static void update_bssid_list(gpointer key, gpointer value, gpointer user_data)
                bssids->score_assoc_reject = calculate_score_assoc_reject(bssids->assoc_reject_cnt);
                bssids->score_frequency = calculate_score_frequency(bss->signal, bssids->frequency);
                bssids->score_strength = calculate_score_strength(bssids->strength);
+               bssids->score_snr = (int)bss->snr;
+               bssids->score_est_throughput = calculate_score_est_throughput(bss->est_throughput);
 #endif
 
                bssids->ins_score = calculate_score(bssids->is_last_connected,
-                       bssids->assoc_reject_cnt, bssids->frequency, bss->signal);
+                       bssids->assoc_reject_cnt, bssids->frequency, bss->signal,
+                       bss->snr, bss->est_throughput);
 
                bssid_data->bssid_list = g_slist_append(bssid_data->bssid_list, bssids);
        } else
@@ -2536,12 +2564,13 @@ static bool update_best_bss(GSupplicantNetwork *network,
        score_new = calculate_score(
                compare_bssid(bss->bssid, network->last_connected_bssid),
                get_assoc_reject_cnt(network->assoc_reject_table, bss->bssid),
-               bss->frequency, bss->signal);
+               bss->frequency, bss->signal, bss->snr, bss->est_throughput);
 
        score_best = calculate_score(
                compare_bssid(network->best_bss->bssid, network->last_connected_bssid),
                get_assoc_reject_cnt(network->assoc_reject_table, network->best_bss->bssid),
-               network->best_bss->frequency, network->best_bss->signal);
+               network->best_bss->frequency, network->best_bss->signal,
+               network->best_bss->snr, network->best_bss->est_throughput);
 
        if (score_new > score_best) {
                SUPPLICANT_DBG("new[" MACSTR "][%u] : best[" MACSTR "][%u]",
@@ -3111,6 +3140,10 @@ static void bss_compute_security(struct g_supplicant_bss *bss)
 
        if (bss->ieee8021x)
                bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
+#if defined TIZEN_EXT
+       else if (bss->sae)
+               bss->security = G_SUPPLICANT_SECURITY_SAE;
+#endif
        else if (bss->psk)
                bss->security = G_SUPPLICANT_SECURITY_PSK;
 #if defined TIZEN_EXT
@@ -3118,8 +3151,6 @@ static void bss_compute_security(struct g_supplicant_bss *bss)
                bss->security = G_SUPPLICANT_SECURITY_FT_PSK;
        else if (bss->ft_ieee8021x == TRUE)
                bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
-       else if (bss->sae)
-               bss->security = G_SUPPLICANT_SECURITY_SAE;
        else if (bss->owe || bss->owe_transition_mode)
                bss->security = G_SUPPLICANT_SECURITY_OWE;
        else if (bss->dpp)
@@ -3233,6 +3264,17 @@ static void bss_property(const char *key, DBusMessageIter *iter,
                dbus_bool_t hs20 = FALSE;
                dbus_message_iter_get_basic(iter, &hs20);
                bss->hs20 = hs20;
+       } else if (g_strcmp0(key, "SNR") == 0) {
+               dbus_int16_t snr = 0;
+
+               dbus_message_iter_get_basic(iter, &snr);
+               bss->snr = snr;
+       } else if (g_strcmp0(key, "EstThroughput") == 0) {
+               dbus_uint32_t est_throughput = 0;
+
+               dbus_message_iter_get_basic(iter, &est_throughput);
+               if (est_throughput != 0)
+                       bss->est_throughput = est_throughput;
 #endif
        } else if (g_strcmp0(key, "IEs") == 0)
                bss_process_ies(iter, bss);
@@ -5354,7 +5396,7 @@ static void country_result(const char *error,
                regdom->callback(result, regdom->alpha2,
                                        (void *) regdom->user_data);
 
-       g_free(regdom);
+       dbus_free(regdom);
 }
 
 static void country_params(DBusMessageIter *iter, void *user_data)
@@ -5686,6 +5728,19 @@ static void interface_create_params(DBusMessageIter *iter, void *user_data)
                                        DBUS_TYPE_STRING, &config_file);
        }
 
+#ifdef TIZEN_EXT
+       if (data->driver && g_strstr_len(data->driver, strlen(data->driver), "nl80211")) {
+               supplicant_dbus_dict_append_basic(&dict, "MacAddr",
+                               DBUS_TYPE_UINT32, &data->mac_addr);
+
+               supplicant_dbus_dict_append_basic(&dict, "PreassocMacAddr",
+                               DBUS_TYPE_UINT32, &data->preassoc_mac_addr);
+
+               supplicant_dbus_dict_append_basic(&dict, "RandAddrLifetime",
+                               DBUS_TYPE_UINT32, &data->random_mac_lifetime);
+       }
+#endif /* TIZEN_EXT */
+
 #if defined TIZEN_EXT_WIFI_MESH
        if (data->is_mesh_interface) {
                if (data->parent_ifname)
@@ -5949,6 +6004,11 @@ int g_supplicant_interface_mesh_peer_change_status(
 
 int g_supplicant_interface_create(const char *ifname, const char *driver,
                                        const char *bridge,
+#ifdef TIZEN_EXT
+                                       unsigned int mac_policy,
+                                       unsigned int preassoc_mac_policy,
+                                       unsigned int random_mac_lifetime,
+#endif /* TIZEN_EXT */
                                        GSupplicantInterfaceCallback callback,
                                                        void *user_data)
 {
@@ -5971,6 +6031,11 @@ int g_supplicant_interface_create(const char *ifname, const char *driver,
        data->driver = g_strdup(driver);
        data->bridge = g_strdup(bridge);
        data->callback = callback;
+#ifdef TIZEN_EXT
+       data->mac_addr = mac_policy;
+       data->preassoc_mac_addr = preassoc_mac_policy;
+       data->random_mac_lifetime = random_mac_lifetime;
+#endif /* TIZEN_EXT */
        data->user_data = user_data;
 
        ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
@@ -6368,7 +6433,12 @@ static void interface_signalpoll_result(const char *error,
                goto out;
        }
 
-       dbus_message_iter_get_arg_type(iter);
+       if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) {
+               err = -EINVAL;
+               SUPPLICANT_DBG("invalid reply");
+               goto out;
+       }
+
        dbus_message_iter_recurse(iter, &sub_iter);
        dbus_message_iter_recurse(&sub_iter, &dict);
 
@@ -7765,7 +7835,7 @@ int g_supplicant_interface_connect(GSupplicantInterface *interface,
                                        interface_add_network_result, data,
                                        interface);
                }
-        }
+       }
 
        if (ret < 0) {
                g_free(data->path);
@@ -8680,3 +8750,176 @@ void g_supplicant_unregister(const GSupplicantCallbacks *callbacks)
        callbacks_pointer = NULL;
        eap_methods = 0;
 }
+
+#ifdef TIZEN_EXT
+struct supplicant_mac_policy {
+       GSupplicantMacPolicyCallback callback;
+       dbus_uint32_t policy;
+       const void *user_data;
+};
+
+static void mac_policy_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct supplicant_mac_policy *data = user_data;
+       int result = 0;
+
+       if (!user_data)
+               return;
+
+       if (error) {
+               SUPPLICANT_DBG("Mac policy setting failure %s", error);
+               result = -EINVAL;
+       }
+
+       if (data->callback)
+               data->callback(result, data->policy,
+                                       (void *) data->user_data);
+
+       dbus_free(data);
+}
+
+static void mac_policy_params(DBusMessageIter *iter, void *user_data)
+{
+       struct supplicant_mac_policy *data = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &(data->policy));
+}
+
+int g_supplicant_interface_set_mac_policy(GSupplicantInterface *interface,
+                                       GSupplicantMacPolicyCallback callback,
+                                                       unsigned int policy,
+                                                       void *user_data)
+{
+       struct supplicant_mac_policy *data = NULL;
+       int ret;
+
+       if (!system_available)
+               return -EFAULT;
+
+       if (!interface)
+               return -EINVAL;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->callback = callback;
+       data->policy = policy;
+       data->user_data = user_data;
+
+       ret =  supplicant_dbus_property_set(interface->path,
+                               SUPPLICANT_INTERFACE ".Interface",
+                               "MacAddr", DBUS_TYPE_INT32_AS_STRING,
+                               mac_policy_params, mac_policy_result, data, NULL);
+       if (ret < 0) {
+               SUPPLICANT_DBG("Unable to set MacAddr configuration");
+               dbus_free(data);
+       }
+
+       return ret;
+}
+
+int g_supplicant_interface_set_preassoc_mac_policy(GSupplicantInterface *interface,
+                                       GSupplicantMacPolicyCallback callback,
+                                                       unsigned int policy,
+                                                       void *user_data)
+{
+       struct supplicant_mac_policy *data;
+       int ret;
+
+       if (!system_available)
+               return -EFAULT;
+
+       if (!interface)
+               return -EINVAL;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->callback = callback;
+       data->policy = policy;
+       data->user_data = user_data;
+
+       ret =  supplicant_dbus_property_set(interface->path,
+                               SUPPLICANT_INTERFACE ".Interface",
+                               "PreassocMacAddr", DBUS_TYPE_INT32_AS_STRING,
+                               mac_policy_params, mac_policy_result, data, NULL);
+       if (ret < 0) {
+               SUPPLICANT_DBG("Unable to set PreassocMacAddr configuration");
+               dbus_free(data);
+       }
+
+       return ret;
+}
+
+struct supplicant_random_mac_lifetime {
+       GSupplicantRandomMaclifetimeCallback callback;
+       dbus_uint32_t lifetime;
+       const void *user_data;
+};
+
+static void random_mac_lifetime_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct supplicant_random_mac_lifetime *data = user_data;
+       int result = 0;
+
+       if (!user_data)
+               return;
+
+       if (error) {
+               SUPPLICANT_DBG("Random Mac lifetime setting failure %s", error);
+               result = -EINVAL;
+       }
+
+       if (data->callback)
+               data->callback(result, data->lifetime,
+                                       (void *) data->user_data);
+
+       dbus_free(data);
+}
+
+static void random_mac_lifetime_params(DBusMessageIter *iter, void *user_data)
+{
+       struct supplicant_random_mac_lifetime *data = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &(data->lifetime));
+}
+
+int g_supplicant_interface_set_random_mac_lifetime(GSupplicantInterface *interface,
+                                       GSupplicantRandomMaclifetimeCallback callback,
+                                                       unsigned int lifetime,
+                                                       void *user_data)
+{
+       struct supplicant_random_mac_lifetime *data;
+       int ret;
+
+       if (!system_available)
+               return -EFAULT;
+
+       if (!interface)
+               return -EINVAL;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->callback = callback;
+       data->lifetime = lifetime;
+       data->user_data = user_data;
+
+       ret =  supplicant_dbus_property_set(interface->path,
+                               SUPPLICANT_INTERFACE ".Interface",
+                               "RandAddrLifetime", DBUS_TYPE_UINT32_AS_STRING,
+                               random_mac_lifetime_params, random_mac_lifetime_result,
+                               data, NULL);
+       if (ret < 0) {
+               SUPPLICANT_DBG("Unable to set RandAddrLifetime configuration");
+               dbus_free(data);
+       }
+
+       return ret;
+}
+#endif