Add Preference-based Network Selection 09/301609/2 accepted/tizen/7.0/unified/20231124.024935
authorJaehyun Kim <jeik01.kim@samsung.com>
Mon, 20 Nov 2023 15:23:10 +0000 (00:23 +0900)
committerJaehyun Kim <jeik01.kim@samsung.com>
Mon, 20 Nov 2023 15:38:17 +0000 (00:38 +0900)
PNS(Preference-based Network Selectio) feature has been added
as a method for selecting AP.

Change-Id: I73b2a37acb3ccd6c4d2daf9d98ef48732f3d776f
Signed-off-by: Jaehyun Kim <jeik01.kim@samsung.com>
gsupplicant/gsupplicant.h
gsupplicant/supplicant.c
include/setting.h
plugins/wifi.c
src/main.c
src/main.conf
src/main_robot.conf
src/service.c

index 954bbf5..fc58034 100755 (executable)
@@ -616,6 +616,7 @@ struct _GSupplicantCallbacks {
 typedef struct _GSupplicantCallbacks GSupplicantCallbacks;
 
 #if defined TIZEN_EXT
+void g_supplicant_set_pns_settings(void *pns_setting_info);
 void g_supplicant_set_ins_settings(GSupplicantINSPreferredFreq preferred_freq_bssid,
                bool last_connected_bssid, bool assoc_reject, bool signal_bssid,
                unsigned int preferred_freq_bssid_score, unsigned int last_connected_bssid_score,
index 05f67f1..cf9b7e0 100755 (executable)
@@ -54,9 +54,7 @@
 #define WLAN_EID_SUPP_RATES 1
 #define WLAN_EID_EXT_SUPP_RATES 50
 #define COUNTRY_CODE_LENGTH    2
-#endif
 
-#if defined TIZEN_EXT
 #define LAST_CONNECTED_TIMEOUT       (5 * 60)
 #define ASSOC_REJECT_TIMEOUT         10
 #define FREQ_RANGE_24GHZ_CHANNEL_1   2412
@@ -189,6 +187,7 @@ struct _GSupplicantINSSettings {
 };
 
 static struct _GSupplicantINSSettings ins_settings;
+static connman_pns_settings *pns_settings;
 
 static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00
@@ -2181,6 +2180,65 @@ static int calculate_score(bool is_last_connected, uint16_t assoc_reject_cnt,
        return score;
 }
 
+static enum connman_wifi_band get_bss_band(unsigned int frequency)
+{
+       if (frequency > FREQUENCY_6G_BASE)
+               return CONNMAN_WIFI_BAND_6GHZ;
+       else if (frequency > FREQUENCY_5G_BASE)
+               return CONNMAN_WIFI_BAND_5GHZ;
+       else
+               return CONNMAN_WIFI_BAND_2_4GHZ;
+}
+
+static int get_bss_signal_weight(enum connman_wifi_band band)
+{
+       switch (band) {
+       case CONNMAN_WIFI_BAND_2_4GHZ:
+               return pns_settings->signal_weight_2_4ghz;
+       case CONNMAN_WIFI_BAND_5GHZ:
+               return pns_settings->signal_weight_5ghz;
+       case CONNMAN_WIFI_BAND_6GHZ:
+               return pns_settings->signal_weight_6ghz;
+       default:
+               return 0;
+       }
+}
+
+static int compare_bss_with_pns(int freq_a, int signal_a, int freq_b, int signal_b)
+{
+       if (!pns_settings)
+               return signal_b - signal_a;
+
+       enum connman_wifi_band bss_band_a = get_bss_band(freq_a);
+       enum connman_wifi_band bss_band_b = get_bss_band(freq_b);
+       GSList *pref_networks = (GSList *) pns_settings->preferred_networks;
+
+       if (bss_band_a == bss_band_b)
+               return signal_b - signal_a;
+
+       for (; pref_networks; pref_networks = pref_networks->next) {
+               preferred_pns_network *pns_network = pref_networks->data;
+
+               if (pns_network->band == bss_band_a &&
+                               pns_network->signal < signal_a)
+                       return -1;
+
+               if (pns_network->band == bss_band_b &&
+                               pns_network->signal < signal_b)
+                       return 1;
+       }
+
+       signal_a += get_bss_signal_weight(bss_band_a);
+       signal_b += get_bss_signal_weight(bss_band_b);
+
+       if (bss_band_a == pns_settings->preferred_band)
+               signal_a++;
+       else if (bss_band_b == pns_settings->preferred_band)
+               signal_b++;
+
+       return signal_b - signal_a;
+}
+
 static void update_bssid_list(gpointer key, gpointer value, gpointer user_data)
 {
        struct g_supplicant_bss *bss = value;
@@ -2229,6 +2287,10 @@ static gint cmp_bss(gconstpointer a, gconstpointer b)
        struct g_connman_bssids *entry_a = (struct g_connman_bssids *)a;
        struct g_connman_bssids *entry_b = (struct g_connman_bssids *)b;
 
+       if (TIZEN_PNS_ENABLED)
+               return compare_bss_with_pns(entry_a->frequency, entry_a->strength - 120,
+                               entry_b->frequency, entry_b->strength - 120);
+
        if (entry_a->ins_score > entry_b->ins_score)
                return -1;
 
@@ -2654,6 +2716,9 @@ static bool update_best_bss(GSupplicantNetwork *network,
        int score_new;
        int score_best;
 
+       if (bss == best_bss)
+               return false;
+
        if (network->best_bss == NULL) {
                update_network_with_best_bss(network, bss);
                return true;
@@ -2670,6 +2735,10 @@ static bool update_best_bss(GSupplicantNetwork *network,
                                get_assoc_reject_cnt(network->assoc_reject_table, network->best_bss->bssid),
                                network->best_bss->frequency, network->best_bss->signal,
                                network->best_bss->snr, network->best_bss->est_throughput);
+       } else if (TIZEN_PNS_ENABLED) {
+               score_new = 0;
+               score_best = compare_bss_with_pns(bss->frequency, bss->signal,
+                               best_bss->frequency, best_bss->signal);
        } else {
                score_new = bss->signal;
                score_best = network->best_bss->signal;
@@ -4518,14 +4587,15 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
        if (network == interface->current_network && bss != network->best_bss)
                return;
 
-       if (bss->signal == network->signal)
-#ifndef TIZEN_EXT
-               return;
-#else
-       {
+#if defined TIZEN_EXT
+       if (bss->signal == network->signal &&
+                       !TIZEN_PNS_ENABLED && !TIZEN_INS_ENABLED) {
                callback_network_changed(network, "");
                return;
        }
+#else
+       if (bss->signal == network->signal)
+               return;
 #endif
 
        /*
@@ -8796,6 +8866,26 @@ static void invoke_introspect_method(void)
 }
 
 #if defined TIZEN_EXT
+void g_supplicant_set_pns_settings(void *pns_setting_info)
+{
+       GSList *pref_networks;
+
+       pns_settings = (connman_pns_settings *) pns_setting_info;
+
+       SUPPLICANT_DBG("signal_weight_2_4ghz [%d]", pns_settings->signal_weight_2_4ghz);
+       SUPPLICANT_DBG("signal_weight_5ghz [%d]", pns_settings->signal_weight_5ghz);
+       SUPPLICANT_DBG("signal_weight_6ghz [%d]", pns_settings->signal_weight_6ghz);
+       SUPPLICANT_DBG("preferred_band [%d]", pns_settings->preferred_band);
+
+       pref_networks = (GSList *) pns_settings->preferred_networks;
+
+       for (; pref_networks; pref_networks = pref_networks->next) {
+               preferred_pns_network *pns_network = pref_networks->data;
+               SUPPLICANT_DBG("preferred_networks: Wi-Fi band [%d], signal [%d]",
+                               pns_network->band, pns_network->signal);
+       }
+}
+
 void g_supplicant_set_ins_settings(GSupplicantINSPreferredFreq preferred_freq_bssid,
                bool last_connected_bssid, bool assoc_reject, bool signal_bssid,
                unsigned int preferred_freq_bssid_score, unsigned int last_connected_bssid_score,
index 4fb4957..80a033e 100755 (executable)
@@ -29,15 +29,43 @@ extern "C" {
 #endif
 
 #if defined TIZEN_EXT
+
+#define FREQUENCY_5G_BASE 5000
+#define FREQUENCY_6G_BASE 5925
+
+#define TIZEN_INS_ENABLED \
+       (connman_setting_get_int("ApSelectionMethod") == AP_SELECTION_METHOD_INS)
+
+#define TIZEN_PNS_ENABLED \
+       (connman_setting_get_int("ApSelectionMethod") == AP_SELECTION_METHOD_PNS)
+
 /* AP selection method to be used */
-typedef enum {
+enum ap_selection_method {
        AP_SELECTION_METHOD_NORMAL = 0,
        AP_SELECTION_METHOD_INS = 1,
-} ap_selection_method_e;
+       AP_SELECTION_METHOD_PNS = 2,
+};
 
-#define TIZEN_INS_ENABLED \
-       (connman_setting_get_int("ApSelectionMethod") == AP_SELECTION_METHOD_INS)
+enum connman_wifi_band{
+       CONNMAN_WIFI_BAND_2_4GHZ = 1,
+       CONNMAN_WIFI_BAND_5GHZ,
+       CONNMAN_WIFI_BAND_6GHZ,
+};
+
+typedef struct {
+       enum connman_wifi_band band;
+       int signal;
+} preferred_pns_network;
+
+typedef struct {
+       void *preferred_networks;
+       int signal_weight_2_4ghz;
+       int signal_weight_5ghz;
+       int signal_weight_6ghz;
+       enum connman_wifi_band preferred_band;
+} connman_pns_settings;
 
+connman_pns_settings *connman_get_pns_settings(void);
 int connman_setting_get_int(const char *key);
 #endif
 
index 01d119e..d7f4e88 100755 (executable)
@@ -6819,6 +6819,8 @@ static int wifi_init(void)
        DBG("RoamScan Int: %d, Min SNR: %d, Min RSSI: %d(2.4GHz), %d(5GHz)",
                        roam_scan_interval, min_snr, min_rssi_2_4GHz, min_rssi_5GHz);
 
+       if (TIZEN_PNS_ENABLED)
+               g_supplicant_set_pns_settings(connman_get_pns_settings());
 
        if (TIZEN_INS_ENABLED)
                supp_ins_init();
index bf78690..91f5038 100755 (executable)
@@ -176,6 +176,20 @@ static struct {
 
 #if defined TIZEN_EXT
 static struct {
+       char **preferred_networks;
+       int signal_weight_2_4ghz;
+       int signal_weight_5ghz;
+       int signal_weight_6ghz;
+       char *preferred_band;
+} connman_pns_settings_conf = {
+       .preferred_networks = NULL,
+       .signal_weight_2_4ghz = 0,
+       .signal_weight_5ghz = 0,
+       .signal_weight_6ghz = 0,
+       .preferred_band = NULL,
+};
+
+static struct {
        /* BSSID */
        char *ins_preferred_freq_bssid;
        bool ins_last_connected_bssid;
@@ -272,9 +286,13 @@ static struct {
 #define CONF_WIFI_ROAM_MIN_RSSI_5       "WifiRoamingMinRSSI_5GHz"
 #define CONF_WIFI_AUTO_CONNECTION_SCAN  "AutoConnectionScan"
 #define CONF_WIFI_AP_SELECTION_METHOD   "ApSelectionMethod"
-#endif
 
-#if defined TIZEN_EXT
+#define CONF_PNS_PREFERRED_NETWORKS       "PNSPreferredNetworks"
+#define CONF_PNS_SIGNAL_WEIGHT_2_4GHZ     "PNSSignalWeight_2_4GHz"
+#define CONF_PNS_SIGNAL_WEIGHT_5GHZ       "PNSSignalWeight_5GHz"
+#define CONF_PNS_SIGNAL_WEIGHT_6GHZ       "PNSSignalWeight_6GHz"
+#define CONF_PNS_PREFERRED_BAND           "PNSPreferredBand"
+
 /* BSSID */
 #define CONF_INS_PREFERRED_FREQ_BSSID        "INSPreferredFreqBSSID"
 #define CONF_INS_PREFERRED_FREQ_BSSID_SCORE  "INSPreferredFreqBSSIDScore"
@@ -350,6 +368,15 @@ static const char *supported_options[] = {
 };
 
 #if defined TIZEN_EXT
+static const char *supported_pns_options[] = {
+               CONF_PNS_PREFERRED_NETWORKS,
+               CONF_PNS_SIGNAL_WEIGHT_2_4GHZ,
+               CONF_PNS_SIGNAL_WEIGHT_5GHZ,
+               CONF_PNS_SIGNAL_WEIGHT_6GHZ,
+               CONF_PNS_PREFERRED_BAND,
+               NULL
+};
+
 static const char *supported_ins_options[] = {
        /* BSSID */
        CONF_INS_PREFERRED_FREQ_BSSID,
@@ -465,7 +492,8 @@ static void check_config(GKeyFile *config)
        for (j = 0; keys && keys[j]; j++) {
 #if defined TIZEN_EXT
                if (g_strcmp0(keys[j], "General") != 0 &&
-                       g_strcmp0(keys[j], "INS") != 0)
+                       g_strcmp0(keys[j], "INS") != 0 &&
+                       g_strcmp0(keys[j], "PNS") != 0)
 #else
                if (g_strcmp0(keys[j], "General") != 0)
 #endif
@@ -496,6 +524,26 @@ static void check_config(GKeyFile *config)
        g_strfreev(keys);
 
 #if defined TIZEN_EXT
+       keys = g_key_file_get_keys(config, "PNS", NULL, NULL);
+
+       for (j = 0; keys && keys[j]; j++) {
+               bool found;
+               int i;
+
+               found = false;
+               for (i = 0; supported_pns_options[i]; i++) {
+                       if (g_strcmp0(keys[j], supported_pns_options[i]) == 0) {
+                               found = true;
+                               break;
+                       }
+               }
+               if (!found && !supported_pns_options[i])
+                       connman_warn("Unknown option %s in %s",
+                                               keys[j], MAINFILE);
+       }
+
+       g_strfreev(keys);
+
        keys = g_key_file_get_keys(config, "INS", NULL, NULL);
 
        for (j = 0; keys && keys[j]; j++) {
@@ -519,6 +567,51 @@ static void check_config(GKeyFile *config)
 }
 
 #if defined TIZEN_EXT
+static void check_tizen_pns_configuration(GKeyFile *config)
+{
+       GError *error = NULL;
+       char **pns_string_list;
+       char *pns_string;
+       int integer;
+       gsize len;
+
+       pns_string_list = g_key_file_get_string_list(config, "PNS",
+                       CONF_PNS_PREFERRED_NETWORKS, &len, &error);
+
+       if (error == NULL)
+               connman_pns_settings_conf.preferred_networks = pns_string_list;
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "PNS",
+                       CONF_PNS_SIGNAL_WEIGHT_2_4GHZ, &error);
+       if (!error)
+               connman_pns_settings_conf.signal_weight_2_4ghz = integer;
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "PNS",
+                       CONF_PNS_SIGNAL_WEIGHT_5GHZ, &error);
+       if (!error)
+               connman_pns_settings_conf.signal_weight_5ghz = integer;
+
+       g_clear_error(&error);
+
+       integer = g_key_file_get_integer(config, "PNS",
+                       CONF_PNS_SIGNAL_WEIGHT_6GHZ, &error);
+       if (!error)
+               connman_pns_settings_conf.signal_weight_6ghz = integer;
+
+       g_clear_error(&error);
+
+       pns_string = __connman_config_get_string(config, "PNS",
+                       CONF_PNS_PREFERRED_BAND, &error);
+       if (!error)
+               connman_pns_settings_conf.preferred_band = pns_string;
+
+       g_clear_error(&error);
+}
+
 static void check_tizen_ins_configuration(GKeyFile *config)
 {
        GError *error = NULL;
@@ -811,6 +904,7 @@ static void check_tizen_configuration(GKeyFile *config)
        g_clear_error(&error);
 
        check_tizen_ins_configuration(config);
+       check_tizen_pns_configuration(config);
 }
 
 static void set_nofile_inc(void)
@@ -1277,6 +1371,9 @@ char *connman_setting_get_string(const char *key)
 
        if (g_str_equal(key, CONF_WIFI_DEF_IFNAME))
                return connman_settings.def_wifi_ifname;
+
+       if (g_str_equal(key, CONF_PNS_PREFERRED_BAND))
+               return connman_pns_settings_conf.preferred_band;
 #endif
        return NULL;
 }
@@ -1432,6 +1529,15 @@ int connman_setting_get_int(const char *key)
        if (g_str_equal(key, CONF_WIFI_ROAM_SCAN_INTERVAL))
                return connman_settings.wifi_roam_scan_interval;
 
+       if (g_str_equal(key, CONF_PNS_SIGNAL_WEIGHT_2_4GHZ))
+               return connman_pns_settings_conf.signal_weight_2_4ghz;
+
+       if (g_str_equal(key, CONF_PNS_SIGNAL_WEIGHT_5GHZ))
+               return connman_pns_settings_conf.signal_weight_5ghz;
+
+       if (g_str_equal(key, CONF_PNS_SIGNAL_WEIGHT_6GHZ))
+               return connman_pns_settings_conf.signal_weight_6ghz;
+
        return 0;
 }
 #endif
@@ -1453,11 +1559,12 @@ char **connman_setting_get_string_list(const char *key)
 #if defined TIZEN_EXT
        if (g_str_equal(key, CONF_CELLULAR_INTERFACE))
                return connman_settings.cellular_interfaces;
-#endif
 
-#if defined TIZEN_EXT
        if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY))
                return connman_ins_settings.ins_security_priority;
+
+       if (g_str_equal(key, CONF_PNS_PREFERRED_NETWORKS))
+               return connman_pns_settings_conf.preferred_networks;
 #endif
 
        return NULL;
@@ -1703,6 +1810,10 @@ int main(int argc, char *argv[])
        g_free(connman_ins_settings.ins_preferred_freq);
        if (connman_ins_settings.ins_security_priority)
                g_strfreev(connman_ins_settings.ins_security_priority);
+
+       g_free(connman_pns_settings_conf.preferred_band);
+       if (connman_pns_settings_conf.preferred_networks)
+               g_strfreev(connman_pns_settings_conf.preferred_networks);
 #endif
 
        g_free(option_debug);
index c25eb6f..0fc9658 100755 (executable)
@@ -237,8 +237,34 @@ DefaultWifiInterface = wlan0
 # This value indicates which AP selection method to be used.
 # 0: Normal(Signal strength)
 # 1: INS
+# 2: PNS
 ApSelectionMethod = 0
 
+[PNS]
+# PNS(Preference-based Network Selection) configurations
+
+# List of Preferred Network separated by ",".
+# APs that meet these conditions are selected with the highest priority.
+# Priorities are given in the order written.
+# For example, 5GHz:-68 refers to APs with a signal of -68dBm or higher in the 5GHz band.
+# PNSPreferredNetworks = 5GHz:-55,2.4GHz:-66
+
+# Signal weights for APs in the each band.
+# These values are added to the actual signal strength to calculate priority.
+#
+# For APs that do not meet PNSPreferredNetworks conditions,
+# selection is made in order of signal strength.
+# At this time, the weights below are applied to each band.
+#
+# PNSSignalWeight_2_4GHz = 11
+# PNSSignalWeight_5GHz = 0
+# PNSSignalWeight_6GHz = 0
+
+# Preferred Band(One of 2.4GHz, 5GHz or 6GHz).
+# If the signal strength is the same, the band below is selected.
+# PNSPreferredBand = 2.4GHz
+
+
 [INS]
 # INS(Intelligent Network Selection) configuration: BSSID Selection.
 INSPreferredFreqBSSID = 5GHz
index 8b2a6d5..95d2b5c 100755 (executable)
@@ -237,8 +237,34 @@ DefaultWifiInterface = wlan0
 # This value indicates which AP selection method to be used.
 # 0: Normal(Signal strength)
 # 1: INS
+# 2: PNS
 ApSelectionMethod = 0
 
+[PNS]
+# PNS(Preference-based Network Selection) configurations
+
+# List of Preferred Network separated by ",".
+# APs that meet these conditions are selected with the highest priority.
+# Priorities are given in the order written.
+# For example, 5GHz:-68 refers to APs with a signal of -68dBm or higher in the 5GHz band.
+# PNSPreferredNetworks = 5GHz:-55,2.4GHz:-66
+
+# Signal weights for APs in the each band.
+# These values are added to the actual signal strength to calculate priority.
+#
+# For APs that do not meet PNSPreferredNetworks conditions,
+# selection is made in order of signal strength.
+# At this time, the weights below are applied to each band.
+#
+# PNSSignalWeight_2_4GHz = 11
+# PNSSignalWeight_5GHz = 0
+# PNSSignalWeight_6GHz = 0
+
+# Preferred Band(One of 2.4GHz, 5GHz or 6GHz).
+# If the signal strength is the same, the band below is selected.
+# PNSPreferredBand = 2.4GHz
+
+
 [INS]
 # INS(Intelligent Network Selection) configuration: BSSID Selection.
 INSPreferredFreqBSSID = 5GHz
index bbd40ae..b5e099d 100755 (executable)
@@ -111,6 +111,7 @@ struct connman_ins_settings {
 };
 
 static struct connman_ins_settings ins_settings;
+static connman_pns_settings pns_settings;
 #endif /* defined TIZEN_EXT */
 
 struct connman_stats {
@@ -8231,6 +8232,75 @@ static int calculate_score(struct connman_service *service)
        service->ins_score = score;
        return score;
 }
+
+static enum connman_wifi_band get_service_band(unsigned int frequency)
+{
+       if (frequency > FREQUENCY_6G_BASE)
+               return CONNMAN_WIFI_BAND_6GHZ;
+       else if (frequency > FREQUENCY_5G_BASE)
+               return CONNMAN_WIFI_BAND_5GHZ;
+       else
+               return CONNMAN_WIFI_BAND_2_4GHZ;
+}
+
+static int get_signal_weight(enum connman_wifi_band band)
+{
+       switch (band) {
+       case CONNMAN_WIFI_BAND_2_4GHZ:
+               return pns_settings.signal_weight_2_4ghz;
+       case CONNMAN_WIFI_BAND_5GHZ:
+               return pns_settings.signal_weight_5ghz;
+       case CONNMAN_WIFI_BAND_6GHZ:
+               return pns_settings.signal_weight_6ghz;
+       default:
+               return 0;
+       }
+}
+
+static int compare_service_with_pns(struct connman_service *service_a,
+               struct connman_service *service_b)
+{
+       int ret;
+       int strength_a = connman_network_get_strength(service_a->network) - 120;
+       int strength_b = connman_network_get_strength(service_b->network) - 120;
+
+       enum connman_wifi_band band_a = get_service_band(
+                       connman_network_get_frequency(service_a->network));
+       enum connman_wifi_band band_b = get_service_band(
+                       connman_network_get_frequency(service_b->network));
+
+       GSList *pref_networks = (GSList *) pns_settings.preferred_networks;
+
+       if (band_a == band_b)
+               goto done;
+
+       for (; pref_networks; pref_networks = pref_networks->next) {
+               preferred_pns_network *pns_network = pref_networks->data;
+
+               if (pns_network->band == band_a &&
+                               pns_network->signal < strength_a)
+                       return -1;
+
+               if (pns_network->band == band_b &&
+                               pns_network->signal < strength_b)
+                       return 1;
+       }
+
+       strength_a += get_signal_weight(band_a);
+       strength_b += get_signal_weight(band_b);
+
+       if (band_a == pns_settings.preferred_band)
+               strength_a++;
+       else if (band_b == pns_settings.preferred_band)
+               strength_b++;
+
+done:
+       ret = strength_b - strength_a;
+       if (ret)
+               return ret;
+
+       return g_strcmp0(service_a->name, service_b->name);
+}
 #endif /* defined TIZEN_EXT */
 
 static gint service_compare(gconstpointer a, gconstpointer b);
@@ -8410,12 +8480,13 @@ static gint service_compare(gconstpointer a, gconstpointer b)
                        if (strength)
                                return strength;
                }
+       } else if (TIZEN_PNS_ENABLED) {
+               return compare_service_with_pns(service_a, service_b);
        }
-#else /* defined TIZEN_EXT */
+#endif /* defined TIZEN_EXT */
        strength = (gint) service_b->strength - (gint) service_a->strength;
        if (strength)
                return strength;
-#endif /* defined TIZEN_EXT */
 
        return g_strcmp0(service_a->name, service_b->name);
 }
@@ -11472,6 +11543,95 @@ static struct connman_agent_driver agent_driver = {
 };
 
 #if defined TIZEN_EXT
+static enum connman_wifi_band pns_get_wifi_band(char *band_string)
+{
+       if (!band_string)
+               return 0;
+
+       if (g_ascii_strcasecmp(band_string, "2.4GHz") == 0)
+               return CONNMAN_WIFI_BAND_2_4GHZ;
+       else if (g_ascii_strcasecmp(band_string, "5GHz") == 0)
+               return CONNMAN_WIFI_BAND_5GHZ;
+       else if (g_ascii_strcasecmp(band_string, "6GHz") == 0)
+               return CONNMAN_WIFI_BAND_6GHZ;
+       else
+               return 0;
+}
+
+static bool pns_parse_network_info(char *network_string, GSList **pref_networks)
+{
+       preferred_pns_network *pns_network = NULL;
+       bool ret = false;
+       char *pns_string;
+       char **network_info = g_strsplit(network_string, ":", 0);
+
+       if (!network_info)
+               return false;
+
+       pns_string = network_info[0];
+       if (!pns_string || pns_string[0] == '\0')
+               goto out;
+
+       pns_network = g_try_malloc0(sizeof(preferred_pns_network));
+       if (!pns_network)
+               goto out;
+
+       pns_network->band = pns_get_wifi_band(pns_string);
+       if (pns_network->band == 0)
+               goto out;
+
+       pns_string = network_info[1];
+       if (!pns_string || pns_string[0] == '\0')
+               goto out;
+
+       pns_network->signal = strtol(pns_string, NULL, 10);
+       if (pns_network->signal >= 0 || errno == ERANGE)
+               goto out;
+
+       *pref_networks = g_slist_append(*pref_networks, pns_network);
+       pns_network = NULL;
+       ret = true;
+
+out:
+       g_strfreev(network_info);
+       g_free(pns_network);
+
+       return ret;
+}
+
+static void pns_setting_init(void)
+{
+       int i;
+       char *pns_string;
+       char **network_list;
+       GSList *pref_networks = NULL;
+
+       pns_settings.signal_weight_2_4ghz = connman_setting_get_int("PNSSignalWeight_2_4GHz");
+       pns_settings.signal_weight_5ghz = connman_setting_get_int("PNSSignalWeight_5GHz");
+       pns_settings.signal_weight_6ghz = connman_setting_get_int("PNSSignalWeight_6GHz");
+
+       network_list = connman_setting_get_string_list("PNSPreferredNetworks");
+
+       for (i = 0; network_list && network_list[i]; i++)
+               if (!pns_parse_network_info(network_list[i], &pref_networks))
+                       break;
+
+       pns_settings.preferred_networks = pref_networks;
+
+       pns_string = connman_setting_get_string("PNSPreferredBand");
+       if (!pns_string) {
+               pns_settings.preferred_band = 0;
+               return;
+       }
+
+       pns_settings.preferred_band = pns_get_wifi_band(pns_string);
+}
+
+connman_pns_settings *connman_get_pns_settings(void)
+{
+       return &pns_settings;
+}
+
 static void ins_setting_init(void)
 {
        int i;
@@ -11592,8 +11752,14 @@ int __connman_service_init(void)
        remove_unprovisioned_services();
 
 #if defined TIZEN_EXT
+       if (TIZEN_PNS_ENABLED)
+               pns_setting_init();
+
        if (TIZEN_INS_ENABLED)
                ins_setting_init();
+
+       DBG("TIZEN_PNS_ENABLED [%s]", TIZEN_PNS_ENABLED ? "TRUE" : "FALSE");
+       DBG("TIZEN_INS_ENABLED [%s]", TIZEN_INS_ENABLED ? "TRUE" : "FALSE");
 #endif /* defined TIZEN_EXT */
 
        return 0;
@@ -11634,4 +11800,11 @@ void __connman_service_cleanup(void)
        g_free(services_notify);
 
        dbus_connection_unref(connection);
+
+#if defined TIZEN_EXT
+       if (TIZEN_PNS_ENABLED && pns_settings.preferred_networks) {
+               g_slist_free_full((GSList *) pns_settings.preferred_networks, g_free);
+               pns_settings.preferred_networks = NULL;
+       }
+#endif
 }