summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-03-20 17:53:34 +0100
committerThomas Haller <thaller@redhat.com>2020-04-02 12:02:33 +0200
commita233510ca6de18185151c16450da00645a4026d1 (patch)
treeb75f78b0325daa6466f09a8655e8be402a97c579
parent4e5bf6207ad621de474c5f61e9fba64506c4573b (diff)
downloadNetworkManager-th/fix-wifi-scan-1.tar.gz
wifi: rework scanning-prohibited tracking for Wi-Fi companion and OLPC deviceth/fix-wifi-scan-1
This was previously tracked via a signal "scanning-prohibited". However, I think it was buggy, because the signal didn't specify a GSignalAccumulator, so when a NMDeviceOlpcMesh registered a handler, NMDeviceWifi.scanning_prohibited() was ignored. In theory, a GObject signal decouples the target and source of the signal and is more abstract. But more abstraction is worse, if there is exactly one target who cares about this signal: the OLPC mesh. And that target is well known at compile time. So, don't pretend that NMDeviceWifi or NMDeviceOlpcMesh aren't aware that they are together in this. Another downside of the signal is that you don't know when scanning gets unblocked. You can only poll and asked whether it is blocked, but there was no mechanism how NMDeviceWifi would be notified when scanning is no longer blocked. Rework this. Instead, the OLPC mesh explicitly registers and unregisters its blocking state with nm_device_wifi_scanning_prohibited_track().
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.c36
-rw-r--r--src/devices/wifi/nm-device-wifi.c93
-rw-r--r--src/devices/wifi/nm-device-wifi.h5
3 files changed, 86 insertions, 48 deletions
diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c
index bcb75f84b2..770b53f60c 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.c
+++ b/src/devices/wifi/nm-device-olpc-mesh.c
@@ -235,6 +235,9 @@ companion_cleanup (NMDeviceOlpcMesh *self)
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
if (priv->companion) {
+ nm_device_wifi_scanning_prohibited_track (NM_DEVICE_WIFI (priv->companion),
+ self,
+ FALSE);
g_signal_handlers_disconnect_by_data (priv->companion, self);
g_clear_object (&priv->companion);
}
@@ -289,16 +292,6 @@ companion_state_changed_cb (NMDeviceWifi *companion,
}
static gboolean
-companion_scan_prohibited_cb (NMDeviceWifi *companion, gboolean periodic, gpointer user_data)
-{
- NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data);
- NMDeviceState state = nm_device_get_state (NM_DEVICE (self));
-
- /* Don't allow the companion to scan while configuring the mesh interface */
- return (state >= NM_DEVICE_STATE_PREPARE) && (state <= NM_DEVICE_STATE_IP_CONFIG);
-}
-
-static gboolean
companion_autoconnect_allowed_cb (NMDeviceWifi *companion, gpointer user_data)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data);
@@ -323,7 +316,7 @@ check_companion (NMDeviceOlpcMesh *self, NMDevice *other)
if (!nm_utils_hwaddr_matches (my_addr, -1, their_addr, -1))
return FALSE;
- g_assert (priv->companion == NULL);
+ nm_assert (priv->companion == NULL);
priv->companion = g_object_ref (other);
_LOGI (LOGD_OLPC, "found companion Wi-Fi device %s",
@@ -335,9 +328,6 @@ check_companion (NMDeviceOlpcMesh *self, NMDevice *other)
g_signal_connect (G_OBJECT (other), "notify::" NM_DEVICE_WIFI_SCANNING,
G_CALLBACK (companion_notify_cb), self);
- g_signal_connect (G_OBJECT (other), NM_DEVICE_WIFI_SCANNING_PROHIBITED,
- G_CALLBACK (companion_scan_prohibited_cb), self);
-
g_signal_connect (G_OBJECT (other), NM_DEVICE_AUTOCONNECT_ALLOWED,
G_CALLBACK (companion_autoconnect_allowed_cb), self);
@@ -399,8 +389,24 @@ state_changed (NMDevice *device,
NMDeviceState old_state,
NMDeviceStateReason reason)
{
+ NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device);
+ NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
+
if (new_state == NM_DEVICE_STATE_UNAVAILABLE)
- find_companion (NM_DEVICE_OLPC_MESH (device));
+ find_companion (self);
+
+ if (priv->companion) {
+ gboolean temporarily_prohibited = FALSE;
+
+ if ( new_state >= NM_DEVICE_STATE_PREPARE
+ && new_state <= NM_DEVICE_STATE_IP_CONFIG) {
+ /* Don't allow the companion to scan while configuring the mesh interface */
+ temporarily_prohibited = TRUE;
+ }
+ nm_device_wifi_scanning_prohibited_track (NM_DEVICE_WIFI (priv->companion),
+ self,
+ temporarily_prohibited);
+ }
}
static guint32
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 0885f2a5ae..266a842514 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -12,6 +12,7 @@
#include <unistd.h>
#include "nm-glib-aux/nm-ref-string.h"
+#include "nm-glib-aux/nm-c-list.h"
#include "nm-device-wifi-p2p.h"
#include "nm-wifi-ap.h"
#include "nm-libnm-core-intern/nm-common-macros.h"
@@ -62,7 +63,6 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceWifi,
);
enum {
- SCANNING_PROHIBITED,
P2P_DEVICE_CREATED,
LAST_SIGNAL
@@ -74,6 +74,8 @@ typedef struct {
CList aps_lst_head;
GHashTable *aps_idx_by_supplicant_path;
+ CList scanning_prohibited_lst_head;
+
NMWifiAP * current_ap;
guint32 rate;
bool enabled:1; /* rfkilled or not */
@@ -123,9 +125,6 @@ struct _NMDeviceWifi
struct _NMDeviceWifiClass
{
NMDeviceClass parent;
-
- /* Signals */
- gboolean (*scanning_prohibited) (NMDeviceWifi *device, gboolean periodic);
};
/*****************************************************************************/
@@ -194,6 +193,45 @@ static void recheck_p2p_availability (NMDeviceWifi *self);
/*****************************************************************************/
+void
+nm_device_wifi_scanning_prohibited_track (NMDeviceWifi *self,
+ gpointer tag,
+ gboolean temporarily_prohibited)
+{
+ NMDeviceWifiPrivate *priv;
+ NMCListElem *elem;
+
+ g_return_if_fail (NM_IS_DEVICE_WIFI (self));
+ nm_assert (tag);
+
+ priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+
+ /* We track these with a simple CList. This would be not efficient, if
+ * there would be many users that need to be tracked at the same time (there
+ * aren't). In fact, most of the time there is no NMDeviceOlpcMesh and
+ * nobody tracks itself here. Optimize for that and simplicity. */
+
+ elem = nm_c_list_elem_find_first (&priv->scanning_prohibited_lst_head,
+ iter,
+ iter == tag);
+
+ if (!temporarily_prohibited) {
+ if (!elem)
+ return;
+
+ nm_c_list_elem_free (elem);
+ return;
+ }
+
+ if (elem)
+ return;
+
+ c_list_link_tail (&priv->scanning_prohibited_lst_head,
+ &nm_c_list_elem_new_stale (tag)->lst);
+}
+
+/*****************************************************************************/
+
static void
_ap_dump (NMDeviceWifi *self,
NMLogLevel log_level,
@@ -230,7 +268,6 @@ _notify_scanning (NMDeviceWifi *self)
if (scanning == priv->is_scanning)
return;
- _LOGD (LOGD_WIFI, "wifi-scan: scanning-state: %s", scanning ? "scanning" : "idle");
priv->is_scanning = scanning;
if ( !scanning
@@ -239,6 +276,11 @@ _notify_scanning (NMDeviceWifi *self)
priv->last_scan_msec = nm_utils_get_monotonic_timestamp_msec ();
}
+ _LOGD (LOGD_WIFI,
+ "wifi-scan: scanning-state: %s%s",
+ scanning ? "scanning" : "idle",
+ last_scan_changed ? " (notify last-scan)" : "");
+
schedule_scan (self, TRUE);
nm_gobject_notify_together (self,
@@ -1292,12 +1334,15 @@ _nm_device_wifi_request_scan (NMDeviceWifi *self,
}
static gboolean
-scanning_prohibited (NMDeviceWifi *self, gboolean periodic)
+check_scanning_prohibited (NMDeviceWifi *self,
+ gboolean periodic)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
- NMSupplicantInterfaceState supplicant_state;
- g_return_val_if_fail (priv->sup_iface != NULL, TRUE);
+ nm_assert (NM_IS_SUPPLICANT_INTERFACE (priv->sup_iface));
+
+ if (!c_list_is_empty (&priv->scanning_prohibited_lst_head))
+ return TRUE;
/* Don't scan when a an AP or Ad-Hoc connection is active as it will
* disrupt connected clients or peers.
@@ -1334,11 +1379,11 @@ scanning_prohibited (NMDeviceWifi *self, gboolean periodic)
}
/* Prohibit scans if the supplicant is busy */
- supplicant_state = nm_supplicant_interface_get_state (priv->sup_iface);
- if ( supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING
- || supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED
- || supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE
- || supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE
+ if ( NM_IN_SET (nm_supplicant_interface_get_state (priv->sup_iface),
+ NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING,
+ NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED,
+ NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE,
+ NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE)
|| nm_supplicant_interface_get_scanning (priv->sup_iface))
return TRUE;
@@ -1347,15 +1392,6 @@ scanning_prohibited (NMDeviceWifi *self, gboolean periodic)
}
static gboolean
-check_scanning_prohibited (NMDeviceWifi *self, gboolean periodic)
-{
- gboolean prohibited = FALSE;
-
- g_signal_emit (self, signals[SCANNING_PROHIBITED], 0, periodic, &prohibited);
- return prohibited;
-}
-
-static gboolean
hidden_filter_func (NMSettings *settings,
NMSettingsConnection *set_con,
gpointer user_data)
@@ -3324,6 +3360,7 @@ nm_device_wifi_init (NMDeviceWifi *self)
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
c_list_init (&priv->aps_lst_head);
+ c_list_init (&priv->scanning_prohibited_lst_head);
priv->aps_idx_by_supplicant_path = g_hash_table_new (nm_direct_hash, NULL);
priv->hidden_probe_scan_warn = TRUE;
@@ -3365,6 +3402,8 @@ dispose (GObject *object)
NMDeviceWifi *self = NM_DEVICE_WIFI (object);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+ nm_assert (c_list_is_empty (&priv->scanning_prohibited_lst_head));
+
nm_clear_g_source (&priv->periodic_update_id);
wifi_secrets_cancel (self);
@@ -3443,8 +3482,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
device_class->state_changed = device_state_changed;
- klass->scanning_prohibited = scanning_prohibited;
-
obj_properties[PROP_MODE] =
g_param_spec_uint (NM_DEVICE_WIFI_MODE, "", "",
NM_802_11_MODE_UNKNOWN,
@@ -3491,14 +3528,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
- signals[SCANNING_PROHIBITED] =
- g_signal_new (NM_DEVICE_WIFI_SCANNING_PROHIBITED,
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_prohibited),
- NULL, NULL, NULL,
- G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN);
-
signals[P2P_DEVICE_CREATED] =
g_signal_new (NM_DEVICE_WIFI_P2P_DEVICE_CREATED,
G_OBJECT_CLASS_TYPE (object_class),
diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h
index 280856efaf..c9fce4e267 100644
--- a/src/devices/wifi/nm-device-wifi.h
+++ b/src/devices/wifi/nm-device-wifi.h
@@ -24,7 +24,6 @@
#define NM_DEVICE_WIFI_SCANNING "scanning"
#define NM_DEVICE_WIFI_LAST_SCAN "last-scan"
-#define NM_DEVICE_WIFI_SCANNING_PROHIBITED "scanning-prohibited"
#define NM_DEVICE_WIFI_P2P_DEVICE_CREATED "p2p-device-created"
typedef struct _NMDeviceWifi NMDeviceWifi;
@@ -44,4 +43,8 @@ GPtrArray *nmtst_ssids_options_to_ptrarray (GVariant *value, GError **error);
gboolean nm_device_wifi_get_scanning (NMDeviceWifi *self);
+void nm_device_wifi_scanning_prohibited_track (NMDeviceWifi *self,
+ gpointer tag,
+ gboolean temporarily_prohibited);
+
#endif /* __NETWORKMANAGER_DEVICE_WIFI_H__ */