diff --git a/src/netdev.c b/src/netdev.c index 1f1b9400..73fbf0c1 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -212,6 +212,8 @@ static bool mac_per_ssid; /* Threshold RSSI for roaming to trigger, configurable in main.conf */ static int LOW_SIGNAL_THRESHOLD; static int LOW_SIGNAL_THRESHOLD_5GHZ; +static int CRITICAL_SIGNAL_THRESHOLD; +static int CRITICAL_SIGNAL_THRESHOLD_5GHZ; static unsigned int iov_ie_append(struct iovec *iov, unsigned int n_iov, unsigned int c, @@ -841,6 +843,10 @@ static void netdev_connect_free(struct netdev *netdev) l_genl_family_cancel(nl80211, netdev->get_oci_cmd_id); netdev->get_oci_cmd_id = 0; } + + /* Reset thresholds back to default */ + netdev->low_signal_threshold = LOW_SIGNAL_THRESHOLD; + netdev->low_signal_threshold_5ghz = LOW_SIGNAL_THRESHOLD_5GHZ; } static void netdev_connect_failed(struct netdev *netdev, @@ -3674,6 +3680,39 @@ static int netdev_cqm_rssi_update(struct netdev *netdev) return 0; } +static int netdev_set_signal_thresholds(struct netdev *netdev, int threshold, + int threshold_5ghz) +{ + int current = netdev->frequency > 4000 ? + netdev->low_signal_threshold_5ghz : + netdev->low_signal_threshold; + int new = netdev->frequency > 4000 ? threshold_5ghz : threshold; + + if (current == new) + return -EALREADY; + + l_debug("changing low signal threshold to %d", new); + + netdev->low_signal_threshold = threshold; + netdev->low_signal_threshold_5ghz = threshold_5ghz; + + netdev_cqm_rssi_update(netdev); + + return 0; +} + +int netdev_lower_signal_threshold(struct netdev *netdev) +{ + return netdev_set_signal_thresholds(netdev, CRITICAL_SIGNAL_THRESHOLD, + CRITICAL_SIGNAL_THRESHOLD_5GHZ); +} + +int netdev_raise_signal_threshold(struct netdev *netdev) +{ + return netdev_set_signal_thresholds(netdev, LOW_SIGNAL_THRESHOLD, + LOW_SIGNAL_THRESHOLD_5GHZ); +} + static bool netdev_connection_work_ready(struct wiphy_radio_work_item *item) { struct netdev *netdev = l_container_of(item, struct netdev, work); @@ -3887,6 +3926,8 @@ done: netdev->handshake = hs; netdev->sm = sm; netdev->cur_rssi = bss->signal_strength / 100; + netdev->low_signal_threshold = LOW_SIGNAL_THRESHOLD; + netdev->low_signal_threshold_5ghz = LOW_SIGNAL_THRESHOLD_5GHZ; if (netdev->rssi_levels_num) netdev_set_rssi_level_idx(netdev); @@ -4260,6 +4301,8 @@ int netdev_ft_reassociate(struct netdev *netdev, netdev->event_filter = event_filter; netdev->connect_cb = cb; netdev->user_data = user_data; + netdev->low_signal_threshold = LOW_SIGNAL_THRESHOLD; + netdev->low_signal_threshold_5ghz = LOW_SIGNAL_THRESHOLD_5GHZ; /* * Cancel commands that could be running because of EAPoL activity @@ -6278,6 +6321,14 @@ static int netdev_init(void) &LOW_SIGNAL_THRESHOLD_5GHZ)) LOW_SIGNAL_THRESHOLD_5GHZ = -76; + if (!l_settings_get_int(settings, NETDEV_CRITICAL_ROAM_THRESHOLD, + &CRITICAL_SIGNAL_THRESHOLD)) + CRITICAL_SIGNAL_THRESHOLD = -80; + + if (!l_settings_get_int(settings, NETDEV_CRITICAL_ROAM_THRESHOLD_5G, + &CRITICAL_SIGNAL_THRESHOLD_5GHZ)) + CRITICAL_SIGNAL_THRESHOLD_5GHZ = -82; + rand_addr_str = l_settings_get_value(settings, NETDEV_ADDRESS_RANDOMIZATION); if (rand_addr_str && !strcmp(rand_addr_str, "network")) diff --git a/src/netdev.h b/src/netdev.h index c48b2c38..6299934e 100644 --- a/src/netdev.h +++ b/src/netdev.h @@ -33,6 +33,8 @@ struct diagnostic_station_info; #define NETDEV_ADDRESS_RANDOMIZATION GENERAL, "AddressRandomization" #define NETDEV_ROAM_THRESHOLD GENERAL, "RoamThreshold" #define NETDEV_ROAM_THRESHOLD_5G GENERAL, "RoamThreshold5G" +#define NETDEV_CRITICAL_ROAM_THRESHOLD GENERAL, "CriticalRoamThreshold" +#define NETDEV_CRITICAL_ROAM_THRESHOLD_5G GENERAL, "CriticalRoamThreshold5G" enum netdev_result { NETDEV_RESULT_OK, @@ -202,6 +204,8 @@ int netdev_neighbor_report_req(struct netdev *netdev, int netdev_set_rssi_report_levels(struct netdev *netdev, const int8_t *levels, size_t levels_num); +int netdev_lower_signal_threshold(struct netdev *netdev); +int netdev_raise_signal_threshold(struct netdev *netdev); int netdev_get_station(struct netdev *netdev, const uint8_t *mac, netdev_get_station_cb_t cb, void *user_data,