From b46b28d18f243f2406ae8f511cdede865cad8428 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 15 Apr 2014 16:25:39 -0500 Subject: [PATCH 01/14] wifi: remove old ipw rfkill polling functionality Older Intel "ipw" devices (ipw2100, ipw2200, and ipw2915) only gained kernel rfkill subsystem integration with 2.6.33. Before then their custom rfkill functionality had to be polled via sysfs. Since we now require at least a 3.x kernel, remove this old code. --- src/devices/nm-device-wifi.c | 119 ----------------------------------- src/devices/nm-device-wifi.h | 4 -- src/nm-manager.c | 79 +++++------------------ 3 files changed, 15 insertions(+), 187 deletions(-) diff --git a/src/devices/nm-device-wifi.c b/src/devices/nm-device-wifi.c index a1e8bed66e..9fa56d44ea 100644 --- a/src/devices/nm-device-wifi.c +++ b/src/devices/nm-device-wifi.c @@ -96,7 +96,6 @@ enum { PROP_ACTIVE_ACCESS_POINT, PROP_CAPABILITIES, PROP_SCANNING, - PROP_IPW_RFKILL_STATE, LAST_PROP }; @@ -129,11 +128,6 @@ struct _NMDeviceWifiPrivate { guint8 perm_hw_addr[ETH_ALEN]; /* Permanent MAC address */ guint8 initial_hw_addr[ETH_ALEN]; /* Initial MAC address (as seen when NM starts) */ - /* Legacy rfkill for ipw2x00; will be fixed with 2.6.33 kernel */ - char * ipw_rfkill_path; - guint ipw_rfkill_id; - RfKillState ipw_rfkill_state; - gint8 invalid_strength_counter; GSList * ap_list; @@ -218,68 +212,6 @@ nm_wifi_error_quark (void) /*****************************************************************/ -/* IPW rfkill handling (until 2.6.33) */ -RfKillState -nm_device_wifi_get_ipw_rfkill_state (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - char *contents = NULL; - RfKillState state = RFKILL_UNBLOCKED; - const char *str_state = NULL; - - if ( priv->ipw_rfkill_path - && (contents = nm_platform_sysctl_get (priv->ipw_rfkill_path))) { - - if (strlen (contents) != 1) - contents[0] = 0; - - /* 0 - RF kill not enabled - * 1 - SW based RF kill active (sysfs) - * 2 - HW based RF kill active - * 3 - Both HW and SW baed RF kill active - */ - switch (contents[0]) { - case '1': - state = RFKILL_SOFT_BLOCKED; - str_state = "soft-blocked"; - break; - case '2': - case '3': - state = RFKILL_HARD_BLOCKED; - str_state = "hard-blocked"; - break; - case '0': - str_state = "unblocked"; - default: - break; - } - g_free (contents); - - nm_log_dbg (LOGD_RFKILL, "(%s): ipw rfkill state '%s'", - nm_device_get_iface (NM_DEVICE (self)), - str_state ? str_state : "(unknown)"); - } - - return state; -} - -static gboolean -ipw_rfkill_state_work (gpointer user_data) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - RfKillState old_state; - - old_state = priv->ipw_rfkill_state; - priv->ipw_rfkill_state = nm_device_wifi_get_ipw_rfkill_state (self); - if (priv->ipw_rfkill_state != old_state) - g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_IPW_RFKILL_STATE); - - return TRUE; -} - -/*****************************************************************/ - static GObject* constructor (GType type, guint n_construct_params, @@ -319,22 +251,6 @@ constructor (GType type, priv->supplicant.mgr = nm_supplicant_manager_get (); g_assert (priv->supplicant.mgr); - /* The ipw2x00 drivers don't integrate with the kernel rfkill subsystem until - * 2.6.33. Thus all our nice libgudev magic is useless. So we get to poll. - * - * FIXME: when 2.6.33 comes lands, we can do some sysfs parkour to figure out - * if we need to poll or not by matching /sys/class/net/ethX/device to one - * of the /sys/class/rfkill/rfkillX/device links. If there's a match, we - * don't have to poll. - */ - priv->ipw_rfkill_path = g_strdup_printf ("/sys/class/net/%s/device/rf_kill", - ASSERT_VALID_PATH_COMPONENT (nm_device_get_iface (NM_DEVICE (self)))); - if (!g_file_test (priv->ipw_rfkill_path, G_FILE_TEST_IS_REGULAR)) { - g_free (priv->ipw_rfkill_path); - priv->ipw_rfkill_path = NULL; - } - priv->ipw_rfkill_state = nm_device_wifi_get_ipw_rfkill_state (self); - return object; } @@ -3388,19 +3304,6 @@ device_state_changed (NMDevice *device, remove_all_aps (self); } - /* Start or stop the rfkill poll worker for ipw cards */ - if (priv->ipw_rfkill_path) { - if (new_state > NM_DEVICE_STATE_UNMANAGED) { - if (!priv->ipw_rfkill_id) - priv->ipw_rfkill_id = g_timeout_add_seconds (3, ipw_rfkill_state_work, self); - } else if (new_state <= NM_DEVICE_STATE_UNMANAGED) { - if (priv->ipw_rfkill_id) { - g_source_remove (priv->ipw_rfkill_id); - priv->ipw_rfkill_id = 0; - } - } - } - switch (new_state) { case NM_DEVICE_STATE_UNMANAGED: clear_aps = TRUE; @@ -3551,12 +3454,6 @@ dispose (GObject *object) remove_all_aps (self); - g_free (priv->ipw_rfkill_path); - if (priv->ipw_rfkill_id) { - g_source_remove (priv->ipw_rfkill_id); - priv->ipw_rfkill_id = 0; - } - G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object); } @@ -3597,9 +3494,6 @@ get_property (GObject *object, guint prop_id, case PROP_SCANNING: g_value_set_boolean (value, nm_supplicant_interface_get_scanning (priv->supplicant.iface)); break; - case PROP_IPW_RFKILL_STATE: - g_value_set_uint (value, nm_device_wifi_get_ipw_rfkill_state (device)); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3610,13 +3504,7 @@ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object); - switch (prop_id) { - case PROP_IPW_RFKILL_STATE: - /* construct only */ - priv->ipw_rfkill_state = g_value_get_uint (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3714,13 +3602,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) FALSE, G_PARAM_READABLE)); - g_object_class_install_property (object_class, PROP_IPW_RFKILL_STATE, - g_param_spec_uint (NM_DEVICE_WIFI_IPW_RFKILL_STATE, - "IpwRfkillState", - "ipw rf-kill state", - RFKILL_UNBLOCKED, RFKILL_HARD_BLOCKED, RFKILL_UNBLOCKED, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - /* Signals */ signals[ACCESS_POINT_ADDED] = g_signal_new ("access-point-added", diff --git a/src/devices/nm-device-wifi.h b/src/devices/nm-device-wifi.h index 18d26e463d..5e4b1a61dd 100644 --- a/src/devices/nm-device-wifi.h +++ b/src/devices/nm-device-wifi.h @@ -26,7 +26,6 @@ #include #include -#include "nm-rfkill-manager.h" #include "nm-device.h" #include "nm-wifi-ap.h" @@ -58,7 +57,6 @@ typedef enum { #define NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT "active-access-point" #define NM_DEVICE_WIFI_CAPABILITIES "wireless-capabilities" #define NM_DEVICE_WIFI_SCANNING "scanning" -#define NM_DEVICE_WIFI_IPW_RFKILL_STATE "ipw-rfkill-state" #ifndef NM_DEVICE_WIFI_DEFINED #define NM_DEVICE_WIFI_DEFINED @@ -92,8 +90,6 @@ GType nm_device_wifi_get_type (void); NMDevice *nm_device_wifi_new (NMPlatformLink *platform_device); -RfKillState nm_device_wifi_get_ipw_rfkill_state (NMDeviceWifi *self); - G_END_DECLS #endif /* NM_DEVICE_WIFI_H */ diff --git a/src/nm-manager.c b/src/nm-manager.c index 97228cc001..f82967094b 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -168,7 +168,6 @@ typedef struct { const char *key; const char *prop; const char *hw_prop; - RfKillState (*other_enabled_func) (NMManager *); } RadioState; typedef struct { @@ -1343,40 +1342,25 @@ manager_hidden_ap_found (NMDevice *device, g_slist_free (connections); } -static RfKillState -nm_manager_get_ipw_rfkill_state (NMManager *self) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GSList *iter; - RfKillState ipw_state = RFKILL_UNBLOCKED; - - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - NMDevice *candidate = NM_DEVICE (iter->data); - RfKillState candidate_state; - - if (nm_device_get_device_type (candidate) == NM_DEVICE_TYPE_WIFI) { - candidate_state = nm_device_wifi_get_ipw_rfkill_state (NM_DEVICE_WIFI (candidate)); - - if (candidate_state > ipw_state) - ipw_state = candidate_state; - } - } - - return ipw_state; -} - static void -update_rstate_from_rfkill (RadioState *rstate, RfKillState rfkill) +update_rstate_from_rfkill (NMRfkillManager *rfkill_mgr, RadioState *rstate) { - if (rfkill == RFKILL_UNBLOCKED) { + switch (nm_rfkill_manager_get_rfkill_state (rfkill_mgr, rstate->rtype)) { + case RFKILL_UNBLOCKED: rstate->sw_enabled = TRUE; rstate->hw_enabled = TRUE; - } else if (rfkill == RFKILL_SOFT_BLOCKED) { + break; + case RFKILL_SOFT_BLOCKED: rstate->sw_enabled = FALSE; rstate->hw_enabled = TRUE; - } else if (rfkill == RFKILL_HARD_BLOCKED) { + break; + case RFKILL_HARD_BLOCKED: rstate->sw_enabled = FALSE; rstate->hw_enabled = FALSE; + break; + default: + g_warn_if_reached (); + break; } } @@ -1386,29 +1370,14 @@ manager_rfkill_update_one_type (NMManager *self, RfKillType rtype) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - RfKillState udev_state = RFKILL_UNBLOCKED; - RfKillState other_state = RFKILL_UNBLOCKED; - RfKillState composite; gboolean old_enabled, new_enabled, old_rfkilled, new_rfkilled, old_hwe; old_enabled = radio_enabled_for_rstate (rstate, TRUE); old_rfkilled = rstate->hw_enabled && rstate->sw_enabled; old_hwe = rstate->hw_enabled; - udev_state = nm_rfkill_manager_get_rfkill_state (priv->rfkill_mgr, rtype); - - if (rstate->other_enabled_func) - other_state = rstate->other_enabled_func (self); - - /* The composite state is the "worst" of either udev or other states */ - if (udev_state == RFKILL_HARD_BLOCKED || other_state == RFKILL_HARD_BLOCKED) - composite = RFKILL_HARD_BLOCKED; - else if (udev_state == RFKILL_SOFT_BLOCKED || other_state == RFKILL_SOFT_BLOCKED) - composite = RFKILL_SOFT_BLOCKED; - else - composite = RFKILL_UNBLOCKED; - - update_rstate_from_rfkill (rstate, composite); + /* recheck kernel rfkill state */ + update_rstate_from_rfkill (priv->rfkill_mgr, rstate); /* Print out all states affecting device enablement */ if (rstate->desc) { @@ -1455,14 +1424,6 @@ nm_manager_rfkill_update (NMManager *self, RfKillType rtype) } } -static void -manager_ipw_rfkill_state_changed (NMDeviceWifi *device, - GParamSpec *pspec, - gpointer user_data) -{ - nm_manager_rfkill_update (NM_MANAGER (user_data), RFKILL_TYPE_WLAN); -} - static void device_auth_done_cb (NMAuthChain *chain, GError *auth_error, @@ -1735,13 +1696,6 @@ add_device (NMManager *self, NMDevice *device, gboolean generate_con) g_signal_connect (device, "hidden-ap-found", G_CALLBACK (manager_hidden_ap_found), self); - - /* Hook up rfkill handling for ipw-based cards until they get converted - * to use the kernel's rfkill subsystem in 2.6.33. - */ - g_signal_connect (device, "notify::" NM_DEVICE_WIFI_IPW_RFKILL_STATE, - G_CALLBACK (manager_ipw_rfkill_state_changed), - self); } /* Update global rfkill state for this device type with the device's @@ -4100,14 +4054,13 @@ nm_manager_start (NMManager *self) /* Set initial radio enabled/disabled state */ for (i = 0; i < RFKILL_TYPE_MAX; i++) { RadioState *rstate = &priv->radio_states[i]; - RfKillState udev_state; gboolean enabled; if (!rstate->desc) continue; - udev_state = nm_rfkill_manager_get_rfkill_state (priv->rfkill_mgr, i); - update_rstate_from_rfkill (rstate, udev_state); + /* recheck kernel rfkill state */ + update_rstate_from_rfkill (priv->rfkill_mgr, rstate); if (rstate->desc) { nm_log_info (LOGD_RFKILL, "%s %s by radio killswitch; %s by state file", @@ -4730,7 +4683,6 @@ nm_manager_init (NMManager *manager) priv->radio_states[RFKILL_TYPE_WLAN].prop = NM_MANAGER_WIRELESS_ENABLED; priv->radio_states[RFKILL_TYPE_WLAN].hw_prop = NM_MANAGER_WIRELESS_HARDWARE_ENABLED; priv->radio_states[RFKILL_TYPE_WLAN].desc = "WiFi"; - priv->radio_states[RFKILL_TYPE_WLAN].other_enabled_func = nm_manager_get_ipw_rfkill_state; priv->radio_states[RFKILL_TYPE_WLAN].rtype = RFKILL_TYPE_WLAN; priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = TRUE; @@ -4745,7 +4697,6 @@ nm_manager_init (NMManager *manager) priv->radio_states[RFKILL_TYPE_WIMAX].prop = NM_MANAGER_WIMAX_ENABLED; priv->radio_states[RFKILL_TYPE_WIMAX].hw_prop = NM_MANAGER_WIMAX_HARDWARE_ENABLED; priv->radio_states[RFKILL_TYPE_WIMAX].desc = "WiMAX"; - priv->radio_states[RFKILL_TYPE_WIMAX].other_enabled_func = NULL; priv->radio_states[RFKILL_TYPE_WIMAX].rtype = RFKILL_TYPE_WIMAX; for (i = 0; i < RFKILL_TYPE_MAX; i++) From 06e3c6d02fe997e715345d3ce6a290be3862346e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 15 Apr 2014 17:12:13 -0500 Subject: [PATCH 02/14] wifi: make Wi-Fi support a plugin Make Wi-Fi support a plugin using the new device factory interface. Provides a 7% size reduction in the core NM binary. Before After NM: 1154104 1071992 (-7%) Wi-Fi: 0 110464 (all results from stripped files) --- .gitignore | 1 + configure.ac | 2 + po/POTFILES.in | 2 +- src/Makefile.am | 11 +- src/devices/wifi/Makefile.am | 78 ++++++++++++ src/devices/wifi/exports.ver | 7 ++ src/devices/{ => wifi}/nm-device-olpc-mesh.c | 1 + src/devices/{ => wifi}/nm-device-olpc-mesh.h | 0 src/devices/{ => wifi}/nm-device-wifi.c | 44 +++++-- src/devices/{ => wifi}/nm-device-wifi.h | 1 - src/{ => devices/wifi}/nm-wifi-ap-utils.c | 0 src/{ => devices/wifi}/nm-wifi-ap-utils.h | 0 src/{ => devices/wifi}/nm-wifi-ap.c | 0 src/{ => devices/wifi}/nm-wifi-ap.h | 0 src/devices/wifi/nm-wifi-factory.c | 114 ++++++++++++++++++ src/devices/wifi/tests/Makefile.am | 28 +++++ .../wifi}/tests/test-wifi-ap-utils.c | 0 src/nm-manager.c | 53 -------- src/nm-policy.c | 1 - src/tests/Makefile.am | 11 +- 20 files changed, 266 insertions(+), 88 deletions(-) create mode 100644 src/devices/wifi/Makefile.am create mode 100644 src/devices/wifi/exports.ver rename src/devices/{ => wifi}/nm-device-olpc-mesh.c (99%) rename src/devices/{ => wifi}/nm-device-olpc-mesh.h (100%) rename src/devices/{ => wifi}/nm-device-wifi.c (99%) rename src/devices/{ => wifi}/nm-device-wifi.h (97%) rename src/{ => devices/wifi}/nm-wifi-ap-utils.c (100%) rename src/{ => devices/wifi}/nm-wifi-ap-utils.h (100%) rename src/{ => devices/wifi}/nm-wifi-ap.c (100%) rename src/{ => devices/wifi}/nm-wifi-ap.h (100%) create mode 100644 src/devices/wifi/nm-wifi-factory.c create mode 100644 src/devices/wifi/tests/Makefile.am rename src/{ => devices/wifi}/tests/test-wifi-ap-utils.c (100%) diff --git a/.gitignore b/.gitignore index 3678dc36e1..b3245af97b 100644 --- a/.gitignore +++ b/.gitignore @@ -186,6 +186,7 @@ valgrind-*.log /src/tests/test-ip6-config /src/tests/test-wifi-ap-utils /src/tests/test-resolvconf-capture +/src/devices/wifi/tests/test-wifi-ap-utils /src/dnsmasq-manager/tests/test-dnsmasq-utils /src/dhcp-manager/tests/test-dhcp-dhclient /src/dhcp-manager/tests/test-dnsmasq-utils diff --git a/configure.ac b/configure.ac index 74db8c1129..cfccfc2e00 100644 --- a/configure.ac +++ b/configure.ac @@ -800,6 +800,8 @@ src/rdisc/tests/Makefile src/devices/adsl/Makefile src/devices/wimax/Makefile src/devices/bluetooth/Makefile +src/devices/wifi/Makefile +src/devices/wifi/tests/Makefile src/devices/wwan/Makefile libnm-util/libnm-util.pc libnm-util/Makefile diff --git a/po/POTFILES.in b/po/POTFILES.in index 36bc69ffa0..6368a9f59f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -53,9 +53,9 @@ src/devices/nm-device-bond.c src/devices/nm-device-bridge.c src/devices/nm-device-ethernet.c src/devices/nm-device-infiniband.c -src/devices/nm-device-olpc-mesh.c src/devices/nm-device-team.c src/devices/nm-device-vlan.c +src/devices/wifi/nm-device-olpc-mesh.c src/devices/wwan/nm-modem-broadband.c src/devices/wwan/nm-modem-old.c src/nm-manager.c diff --git a/src/Makefile.am b/src/Makefile.am index d467e803ca..53fc35c1fb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,7 @@ SUBDIRS = \ devices/adsl \ devices/wwan \ devices/bluetooth \ + devices/wifi \ dhcp-manager \ ppp-manager \ settings/plugins @@ -78,8 +79,6 @@ nm_sources = \ devices/nm-device-infiniband.h \ devices/nm-device-macvlan.c \ devices/nm-device-macvlan.h \ - devices/nm-device-olpc-mesh.c \ - devices/nm-device-olpc-mesh.h \ devices/nm-device-private.h \ devices/nm-device-team.c \ devices/nm-device-team.h \ @@ -91,8 +90,6 @@ nm_sources = \ devices/nm-device-vlan.h \ devices/nm-device-vxlan.c \ devices/nm-device-vxlan.h \ - devices/nm-device-wifi.c \ - devices/nm-device-wifi.h \ \ dhcp-manager/nm-dhcp-client.c \ dhcp-manager/nm-dhcp-client.h \ @@ -241,10 +238,6 @@ nm_sources = \ nm-session-utils.h \ nm-sleep-monitor.h \ nm-types.h \ - nm-wifi-ap-utils.c \ - nm-wifi-ap-utils.h \ - nm-wifi-ap.c \ - nm-wifi-ap.h \ NetworkManagerUtils.c \ NetworkManagerUtils.h @@ -297,13 +290,11 @@ glue_sources = \ nm-device-gre-glue.h \ nm-device-infiniband-glue.h \ nm-device-macvlan-glue.h \ - nm-device-olpc-mesh-glue.h \ nm-device-team-glue.h \ nm-device-tun-glue.h \ nm-device-veth-glue.h \ nm-device-vlan-glue.h \ nm-device-vxlan-glue.h \ - nm-device-wifi-glue.h \ nm-dhcp4-config-glue.h \ nm-dhcp6-config-glue.h \ nm-ip4-config-glue.h \ diff --git a/src/devices/wifi/Makefile.am b/src/devices/wifi/Makefile.am new file mode 100644 index 0000000000..5f3ce286b7 --- /dev/null +++ b/src/devices/wifi/Makefile.am @@ -0,0 +1,78 @@ +include $(GLIB_MAKEFILE) + +@GNOME_CODE_COVERAGE_RULES@ + +SUBDIRS=. tests + +AM_CPPFLAGS = \ + -I${top_srcdir}/src \ + -I${top_builddir}/src \ + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/devices \ + -I${top_srcdir}/src/settings \ + -I${top_srcdir}/src/platform \ + -I${top_srcdir}/src/supplicant-manager \ + -I${top_builddir}/include \ + -I${top_srcdir}/include \ + -I${top_builddir}/libnm-util \ + -I${top_srcdir}/libnm-util \ + -DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(DBUS_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(LIBNL_CFLAGS) \ + $(GUDEV_CFLAGS) + +GLIB_GENERATED = nm-wifi-enum-types.h nm-wifi-enum-types.c +GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +nm_wifi_enum_types_sources = \ + $(srcdir)/nm-device-wifi.h \ + $(srcdir)/nm-wifi-ap.h \ + $(srcdir)/nm-device-olpc-mesh.h + +glue_sources = \ + nm-device-wifi-glue.h \ + nm-device-olpc-mesh-glue.h + +%-glue.h: $(top_srcdir)/introspection/%.xml + $(AM_V_GEN) dbus-binding-tool --prefix=$(subst -,_,$(subst -glue.h,,$@)) --mode=glib-server --output=$@ $< + +BUILT_SOURCES = $(GLIB_GENERATED) $(glue_sources) + +pkglib_LTLIBRARIES = libnm-device-plugin-wifi.la + +libnm_device_plugin_wifi_la_SOURCES = \ + nm-wifi-factory.c \ + nm-device-wifi.c \ + nm-device-wifi.h \ + nm-wifi-ap.c \ + nm-wifi-ap.h \ + nm-wifi-ap-utils.c \ + nm-wifi-ap-utils.h \ + nm-device-olpc-mesh.c \ + nm-device-olpc-mesh.h \ + \ + $(BUILT_SOURCES) + +SYMBOL_VIS_FILE=$(srcdir)/exports.ver + +libnm_device_plugin_wifi_la_LDFLAGS = \ + -module -avoid-version \ + -Wl,--version-script=$(SYMBOL_VIS_FILE) + +libnm_device_plugin_wifi_la_LIBADD = \ + $(DBUS_LIBS) \ + $(GUDEV_LIBS) + +CLEANFILES = $(BUILT_SOURCES) + +EXTRA_DIST = $(SYMBOL_VIS_FILE) + +if ENABLE_TESTS + +check-local: + $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wifi.so $(SYMBOL_VIS_FILE) + +endif + diff --git a/src/devices/wifi/exports.ver b/src/devices/wifi/exports.ver new file mode 100644 index 0000000000..d2c451244b --- /dev/null +++ b/src/devices/wifi/exports.ver @@ -0,0 +1,7 @@ +{ +global: + nm_device_factory_create; + nm_device_factory_get_device_type; +local: + *; +}; diff --git a/src/devices/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c similarity index 99% rename from src/devices/nm-device-olpc-mesh.c rename to src/devices/wifi/nm-device-olpc-mesh.c index 19c86975c2..cfb12fc086 100644 --- a/src/devices/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -53,6 +53,7 @@ #include "nm-manager.h" #include "nm-enum-types.h" #include "nm-dbus-manager.h" +#include "nm-wifi-enum-types.h" /* This is a bug; but we can't really change API now... */ #include "NetworkManagerVPN.h" diff --git a/src/devices/nm-device-olpc-mesh.h b/src/devices/wifi/nm-device-olpc-mesh.h similarity index 100% rename from src/devices/nm-device-olpc-mesh.h rename to src/devices/wifi/nm-device-olpc-mesh.h diff --git a/src/devices/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c similarity index 99% rename from src/devices/nm-device-wifi.c rename to src/devices/wifi/nm-device-wifi.c index 9fa56d44ea..231b2681ca 100644 --- a/src/devices/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -58,6 +58,8 @@ #include "nm-settings-connection.h" #include "nm-enum-types.h" #include "nm-dbus-glib-types.h" +#include "nm-wifi-enum-types.h" +#include "nm-connection-provider.h" static gboolean impl_device_get_access_points (NMDeviceWifi *device, @@ -103,7 +105,6 @@ enum { enum { ACCESS_POINT_ADDED, ACCESS_POINT_REMOVED, - HIDDEN_AP_FOUND, SCANNING_ALLOWED, LAST_SIGNAL @@ -1748,6 +1749,34 @@ supplicant_iface_scan_done_cb (NMSupplicantInterface *iface, * */ +static void +try_fill_ssid_for_hidden_ap (NMAccessPoint *ap) +{ + const struct ether_addr *bssid; + const GSList *connections, *iter; + + g_return_if_fail (nm_ap_get_ssid (ap) == NULL); + + bssid = nm_ap_get_address (ap); + g_assert (bssid); + + /* Look for this AP's BSSID in the seen-bssids list of a connection, + * and if a match is found, copy over the SSID */ + connections = nm_connection_provider_get_connections (nm_connection_provider_get ()); + for (iter = connections; iter; iter = g_slist_next (iter)) { + NMConnection *connection = NM_CONNECTION (iter->data); + NMSettingWireless *s_wifi; + + s_wifi = nm_connection_get_setting_wireless (connection); + if (s_wifi) { + if (nm_settings_connection_has_seen_bssid (NM_SETTINGS_CONNECTION (connection), bssid)) { + nm_ap_set_ssid (ap, nm_setting_wireless_get_ssid (s_wifi)); + break; + } + } + } +} + #define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" #define MAC_ARG(x) ((guint8*)(x))[0],((guint8*)(x))[1],((guint8*)(x))[2],((guint8*)(x))[3],((guint8*)(x))[4],((guint8*)(x))[5] @@ -1777,8 +1806,8 @@ merge_scanned_ap (NMDeviceWifi *self, bssid = nm_ap_get_address (merge_ap); ssid = nm_ap_get_ssid (merge_ap); if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) { - /* Let the manager try to fill the AP's SSID from the database */ - g_signal_emit (self, signals[HIDDEN_AP_FOUND], 0, merge_ap); + /* Try to fill the SSID from the AP database */ + try_fill_ssid_for_hidden_ap (merge_ap); ssid = nm_ap_get_ssid (merge_ap); if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) { @@ -3621,15 +3650,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) G_TYPE_NONE, 1, G_TYPE_OBJECT); - signals[HIDDEN_AP_FOUND] = - g_signal_new ("hidden-ap-found", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceWifiClass, hidden_ap_found), - NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - signals[SCANNING_ALLOWED] = g_signal_new ("scanning-allowed", G_OBJECT_CLASS_TYPE (object_class), diff --git a/src/devices/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h similarity index 97% rename from src/devices/nm-device-wifi.h rename to src/devices/wifi/nm-device-wifi.h index 5e4b1a61dd..f0a1beacde 100644 --- a/src/devices/nm-device-wifi.h +++ b/src/devices/wifi/nm-device-wifi.h @@ -81,7 +81,6 @@ struct _NMDeviceWifiClass /* Signals */ void (*access_point_added) (NMDeviceWifi *device, NMAccessPoint *ap); void (*access_point_removed) (NMDeviceWifi *device, NMAccessPoint *ap); - void (*hidden_ap_found) (NMDeviceWifi *device, NMAccessPoint *ap); gboolean (*scanning_allowed) (NMDeviceWifi *device); }; diff --git a/src/nm-wifi-ap-utils.c b/src/devices/wifi/nm-wifi-ap-utils.c similarity index 100% rename from src/nm-wifi-ap-utils.c rename to src/devices/wifi/nm-wifi-ap-utils.c diff --git a/src/nm-wifi-ap-utils.h b/src/devices/wifi/nm-wifi-ap-utils.h similarity index 100% rename from src/nm-wifi-ap-utils.h rename to src/devices/wifi/nm-wifi-ap-utils.h diff --git a/src/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c similarity index 100% rename from src/nm-wifi-ap.c rename to src/devices/wifi/nm-wifi-ap.c diff --git a/src/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h similarity index 100% rename from src/nm-wifi-ap.h rename to src/devices/wifi/nm-wifi-ap.h diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c new file mode 100644 index 0000000000..e4a140a324 --- /dev/null +++ b/src/devices/wifi/nm-wifi-factory.c @@ -0,0 +1,114 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 - 2014 Red Hat, Inc. + */ + +#include + +#include "nm-device-factory.h" +#include "nm-device-wifi.h" +#include "nm-device-olpc-mesh.h" +#include "nm-settings-connection.h" + +#define NM_TYPE_WIFI_FACTORY (nm_wifi_factory_get_type ()) +#define NM_WIFI_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIFI_FACTORY, NMWifiFactory)) + +typedef struct { + GObject parent; +} NMWifiFactory; + +typedef struct { + GObjectClass parent; +} NMWifiFactoryClass; + +static GType nm_wifi_factory_get_type (void); + +static void device_factory_interface_init (NMDeviceFactory *factory_iface); + +G_DEFINE_TYPE_EXTENDED (NMWifiFactory, nm_wifi_factory, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init)) + +enum { + PROP_0, + PROP_DEVICE_TYPE, +}; + +/**************************************************************************/ + +#define PLUGIN_TYPE NM_DEVICE_TYPE_WIFI + +G_MODULE_EXPORT NMDeviceFactory * +nm_device_factory_create (GError **error) +{ + return (NMDeviceFactory *) g_object_new (NM_TYPE_WIFI_FACTORY, NULL); +} + +G_MODULE_EXPORT NMDeviceType +nm_device_factory_get_device_type (void) +{ + return PLUGIN_TYPE; +} + +/**************************************************************************/ + +static NMDevice * +new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error) +{ + if (plink->type == NM_LINK_TYPE_WIFI) + return nm_device_wifi_new (plink); + else if (plink->type == NM_LINK_TYPE_OLPC_MESH) + return nm_device_olpc_mesh_new (plink); + return NULL; +} + +static void +get_property (GObject *object, guint prop, GValue *value, GParamSpec *pspec) +{ + switch (prop) { + case PROP_DEVICE_TYPE: + g_value_set_uint (value, PLUGIN_TYPE); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop, pspec); + break; + } +} + +static void +device_factory_interface_init (NMDeviceFactory *factory_iface) +{ + factory_iface->new_link = new_link; +} + +static void +nm_wifi_factory_init (NMWifiFactory *self) +{ +} + +static void +nm_wifi_factory_class_init (NMWifiFactoryClass *wf_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (wf_class); + + object_class->get_property = get_property; + + g_object_class_override_property (object_class, + PROP_DEVICE_TYPE, + NM_DEVICE_FACTORY_DEVICE_TYPE); +} + diff --git a/src/devices/wifi/tests/Makefile.am b/src/devices/wifi/tests/Makefile.am new file mode 100644 index 0000000000..2667c5f12d --- /dev/null +++ b/src/devices/wifi/tests/Makefile.am @@ -0,0 +1,28 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/libnm-util \ + -I$(top_builddir)/libnm-util \ + -I$(top_srcdir)/src/platform \ + -I$(top_srcdir)/src/logging \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/devices/wifi \ + -I$(top_builddir)/src \ + -DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) + +noinst_PROGRAMS = test-wifi-ap-utils + +test_wifi_ap_utils_SOURCES = \ + test-wifi-ap-utils.c \ + $(srcdir)/../nm-wifi-ap.c \ + $(srcdir)/../nm-wifi-ap.h \ + $(srcdir)/../nm-wifi-ap-utils.c \ + $(srcdir)/../nm-wifi-ap-utils.h + +test_wifi_ap_utils_LDADD = $(top_builddir)/src/libNetworkManager.la + +TESTS = test-wifi-ap-utils + diff --git a/src/tests/test-wifi-ap-utils.c b/src/devices/wifi/tests/test-wifi-ap-utils.c similarity index 100% rename from src/tests/test-wifi-ap-utils.c rename to src/devices/wifi/tests/test-wifi-ap-utils.c diff --git a/src/nm-manager.c b/src/nm-manager.c index f82967094b..dde273923d 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -41,8 +41,6 @@ #include "nm-vpn-manager.h" #include "nm-device.h" #include "nm-device-ethernet.h" -#include "nm-device-wifi.h" -#include "nm-device-olpc-mesh.h" #include "nm-device-infiniband.h" #include "nm-device-bond.h" #include "nm-device-team.h" @@ -1309,39 +1307,6 @@ manager_update_radio_enabled (NMManager *self, } } -static void -manager_hidden_ap_found (NMDevice *device, - NMAccessPoint *ap, - gpointer user_data) -{ - NMManager *manager = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - const struct ether_addr *bssid; - GSList *iter; - GSList *connections; - gboolean done = FALSE; - - g_return_if_fail (nm_ap_get_ssid (ap) == NULL); - - bssid = nm_ap_get_address (ap); - g_assert (bssid); - - /* Look for this AP's BSSID in the seen-bssids list of a connection, - * and if a match is found, copy over the SSID */ - connections = nm_settings_get_connections (priv->settings); - for (iter = connections; iter && !done; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - NMSettingWireless *s_wifi; - - s_wifi = nm_connection_get_setting_wireless (connection); - if (s_wifi) { - if (nm_settings_connection_has_seen_bssid (NM_SETTINGS_CONNECTION (connection), bssid)) - nm_ap_set_ssid (ap, nm_setting_wireless_get_ssid (s_wifi)); - } - } - g_slist_free (connections); -} - static void update_rstate_from_rfkill (NMRfkillManager *rfkill_mgr, RadioState *rstate) { @@ -1644,11 +1609,8 @@ add_device (NMManager *self, NMDevice *device, gboolean generate_con) NMConnection *connection = NULL; gboolean enabled = FALSE; RfKillType rtype; - NMDeviceType devtype; GSList *iter, *remove = NULL; - devtype = nm_device_get_device_type (device); - /* No duplicates */ if (nm_manager_get_device_by_udi (self, nm_device_get_udi (device))) return; @@ -1689,15 +1651,6 @@ add_device (NMManager *self, NMDevice *device, gboolean generate_con) self); } - if (devtype == NM_DEVICE_TYPE_WIFI) { - /* Attach to the access-point-added signal so that the manager can fill - * non-SSID-broadcasting APs with an SSID. - */ - g_signal_connect (device, "hidden-ap-found", - G_CALLBACK (manager_hidden_ap_found), - self); - } - /* Update global rfkill state for this device type with the device's * rfkill state, and then set this device's rfkill state based on the * global state. @@ -2007,12 +1960,6 @@ platform_link_added (NMManager *self, case NM_LINK_TYPE_INFINIBAND: device = nm_device_infiniband_new (plink); break; - case NM_LINK_TYPE_OLPC_MESH: - device = nm_device_olpc_mesh_new (plink); - break; - case NM_LINK_TYPE_WIFI: - device = nm_device_wifi_new (plink); - break; case NM_LINK_TYPE_BOND: device = nm_device_bond_new (plink); break; diff --git a/src/nm-policy.c b/src/nm-policy.c index 88bc31a161..d751606ed8 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -29,7 +29,6 @@ #include "nm-policy.h" #include "NetworkManagerUtils.h" -#include "nm-wifi-ap.h" #include "nm-activation-request.h" #include "nm-logging.h" #include "nm-device.h" diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index e23ad68761..ee5be17d7b 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -16,7 +16,6 @@ AM_CPPFLAGS = \ noinst_PROGRAMS = \ test-dhcp-options \ test-general \ - test-wifi-ap-utils \ test-ip4-config \ test-ip6-config \ test-dcb \ @@ -35,14 +34,6 @@ test_dhcp_options_CPPFLAGS = \ test_dhcp_options_LDADD = \ $(top_builddir)/src/libNetworkManager.la -####### wifi ap utils test ####### - -test_wifi_ap_utils_SOURCES = \ - test-wifi-ap-utils.c - -test_wifi_ap_utils_LDADD = \ - $(top_builddir)/src/libNetworkManager.la - ####### ip4 config test ####### test_ip4_config_SOURCES = \ @@ -89,5 +80,5 @@ EXTRA_DIST = test-secret-agent.py ########################################### -TESTS = test-dhcp-options test-wifi-ap-utils test-ip4-config test-ip6-config test-dcb test-resolvconf-capture test-general +TESTS = test-dhcp-options test-ip4-config test-ip6-config test-dcb test-resolvconf-capture test-general From 864a0dbb589e30a3f243dc127ed0abc0b1d54a64 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 15 Apr 2014 17:17:54 -0500 Subject: [PATCH 03/14] wifi: use nm_device_get_connection() to simplify some code --- src/devices/wifi/nm-device-wifi.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 231b2681ca..eb154fb8ec 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -536,7 +536,6 @@ done: static void update_seen_bssids_cache (NMDeviceWifi *self, NMAccessPoint *ap) { - NMActRequest *req; NMConnection *connection; g_return_if_fail (NM_IS_DEVICE_WIFI (self)); @@ -549,9 +548,8 @@ update_seen_bssids_cache (NMDeviceWifi *self, NMAccessPoint *ap) return; if (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED) { - req = nm_device_get_act_request (NM_DEVICE (self)); - if (req) { - connection = nm_act_request_get_connection (req); + connection = nm_device_get_connection (NM_DEVICE (self)); + if (connection) { nm_settings_connection_add_seen_bssid (NM_SETTINGS_CONNECTION (connection), nm_ap_get_address (ap)); } @@ -769,13 +767,11 @@ deactivate (NMDevice *dev) NMDeviceWifi *self = NM_DEVICE_WIFI (dev); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); int ifindex = nm_device_get_ifindex (dev); - NMActRequest *req; NMConnection *connection; NM80211Mode old_mode = priv->mode; - req = nm_device_get_act_request (dev); - if (req) { - connection = nm_act_request_get_connection (req); + connection = nm_device_get_connection (dev); + if (connection) { /* Clear wireless secrets tries when deactivating */ g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL); } @@ -1446,7 +1442,7 @@ scanning_allowed (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); guint32 sup_state; - NMActRequest *req; + NMConnection *connection; g_return_val_if_fail (priv->supplicant.iface != NULL, FALSE); @@ -1485,15 +1481,13 @@ scanning_allowed (NMDeviceWifi *self) || nm_supplicant_interface_get_scanning (priv->supplicant.iface)) return FALSE; - req = nm_device_get_act_request (NM_DEVICE (self)); - if (req) { - NMConnection *connection; + connection = nm_device_get_connection (NM_DEVICE (self)); + if (connection) { NMSettingWireless *s_wifi; const char *ip4_method = NULL; const GByteArray *bssid; /* Don't scan when a shared connection is active; it makes drivers mad */ - connection = nm_act_request_get_connection (req); ip4_method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); if (!strcmp (ip4_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) From 0e72c9ef4d005bff829ac66fc50cf9741c588ee2 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Apr 2014 11:41:31 -0500 Subject: [PATCH 04/14] wifi: simplify supplicant error signal handling The only reason for the small struct was the idle handler, and the only reason for the idle handler was to ensure that state was changed from an idle handler. We've got nm_device_queue_state() to do that for us now, so use it. --- src/devices/wifi/nm-device-wifi.c | 77 +++++-------------------------- 1 file changed, 12 insertions(+), 65 deletions(-) diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index eb154fb8ec..ec0a8875b5 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -119,7 +119,6 @@ typedef struct Supplicant { guint iface_error_id; /* Timeouts and idles */ - guint iface_con_error_cb_id; guint con_timeout_id; } Supplicant; @@ -316,11 +315,6 @@ remove_supplicant_interface_error_handler (NMDeviceWifi *self) g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id); priv->supplicant.iface_error_id = 0; } - - if (priv->supplicant.iface_con_error_cb_id > 0) { - g_source_remove (priv->supplicant.iface_con_error_cb_id); - priv->supplicant.iface_con_error_cb_id = 0; - } } static void @@ -2386,69 +2380,22 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, g_object_notify (G_OBJECT (self), "scanning"); } -struct iface_con_error_cb_data { - NMDeviceWifi *self; - char *name; - char *message; -}; - -static gboolean -supplicant_iface_connection_error_cb_handler (gpointer user_data) -{ - NMDeviceWifi *self; - NMDeviceWifiPrivate *priv; - struct iface_con_error_cb_data * cb_data = (struct iface_con_error_cb_data *) user_data; - - g_return_val_if_fail (cb_data != NULL, FALSE); - - self = cb_data->self; - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - if (!nm_device_is_activating (NM_DEVICE (self))) - goto out; - - nm_log_info (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): association request to the supplicant " - "failed: %s - %s", - nm_device_get_iface (NM_DEVICE (self)), - cb_data->name, - cb_data->message); - - cleanup_association_attempt (self, TRUE); - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - -out: - priv->supplicant.iface_con_error_cb_id = 0; - g_free (cb_data->name); - g_free (cb_data->message); - g_slice_free (struct iface_con_error_cb_data, cb_data); - return FALSE; -} - - static void -supplicant_iface_connection_error_cb (NMSupplicantInterface * iface, - const char * name, - const char * message, - NMDeviceWifi * self) +supplicant_iface_connection_error_cb (NMSupplicantInterface *iface, + const char *name, + const char *message, + NMDeviceWifi *self) { - NMDeviceWifiPrivate *priv; - struct iface_con_error_cb_data *cb_data; - guint id; + NMDevice *device = NM_DEVICE (self); - g_return_if_fail (self != NULL); - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + if (nm_device_is_activating (device)) { + nm_log_warn (LOGD_DEVICE | LOGD_WIFI, + "Activation (%s/wireless): supplicant association failed: %s - %s", + nm_device_get_iface (device), name, message); - cb_data = g_slice_new0 (struct iface_con_error_cb_data); - cb_data->self = self; - cb_data->name = g_strdup (name); - cb_data->message = g_strdup (message); - - if (priv->supplicant.iface_con_error_cb_id) - g_source_remove (priv->supplicant.iface_con_error_cb_id); - - id = g_idle_add (supplicant_iface_connection_error_cb_handler, cb_data); - priv->supplicant.iface_con_error_cb_id = id; + cleanup_association_attempt (self, TRUE); + nm_device_queue_state (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + } } static void From 9cc1f1b79a42bb41ad9938c9805f5b3324e123d1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Apr 2014 11:51:00 -0500 Subject: [PATCH 05/14] wifi: use g_signal_handlers_disconnect_by_* to clean up code a bit --- src/devices/wifi/nm-device-wifi.c | 47 ++++++++++++++----------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index ec0a8875b5..9bf2b30b81 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -116,8 +116,6 @@ typedef struct Supplicant { NMSupplicantManager *mgr; NMSupplicantInterface *iface; - guint iface_error_id; - /* Timeouts and idles */ guint con_timeout_id; } Supplicant; @@ -197,6 +195,8 @@ static gboolean request_wireless_scan (gpointer user_data); static void remove_access_point (NMDeviceWifi *device, NMAccessPoint *ap); +static void remove_supplicant_interface_error_handler (NMDeviceWifi *self); + /*****************************************************************/ #define NM_WIFI_ERROR (nm_wifi_error_quark ()) @@ -303,20 +303,6 @@ supplicant_interface_acquire (NMDeviceWifi *self) return TRUE; } -static void -remove_supplicant_interface_error_handler (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - if (!priv->supplicant.iface) - return; - - if (priv->supplicant.iface_error_id > 0) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id); - priv->supplicant.iface_error_id = 0; - } -} - static void supplicant_interface_release (NMDeviceWifi *self) { @@ -334,17 +320,16 @@ supplicant_interface_release (NMDeviceWifi *self) nm_device_get_iface (NM_DEVICE (self)), priv->scan_interval); - remove_supplicant_interface_error_handler (self); - if (priv->scanlist_cull_id) { g_source_remove (priv->scanlist_cull_id); priv->scanlist_cull_id = 0; } if (priv->supplicant.iface) { + remove_supplicant_interface_error_handler (self); + /* Clear supplicant interface signal handlers */ - g_signal_handlers_disconnect_matched (priv->supplicant.iface, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, self); + g_signal_handlers_disconnect_by_data (priv->supplicant.iface, self); /* Tell the supplicant to disconnect from the current AP */ nm_supplicant_interface_disconnect (priv->supplicant.iface); @@ -2398,6 +2383,18 @@ supplicant_iface_connection_error_cb (NMSupplicantInterface *iface, } } +static void +remove_supplicant_interface_error_handler (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + if (priv->supplicant.iface) { + g_signal_handlers_disconnect_by_func (priv->supplicant.iface, + supplicant_iface_connection_error_cb, + self); + } +} + static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface, GParamSpec *pspec, @@ -2866,7 +2863,6 @@ act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; const char *iface = nm_device_get_iface (dev); NMSupplicantConfig *config = NULL; - gulong id = 0; NMActRequest *req; NMAccessPoint *ap; NMConnection *connection; @@ -2939,11 +2935,10 @@ act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) } /* Hook up error signal handler to capture association errors */ - id = g_signal_connect (priv->supplicant.iface, - NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR, - G_CALLBACK (supplicant_iface_connection_error_cb), - self); - priv->supplicant.iface_error_id = id; + g_signal_connect (priv->supplicant.iface, + NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR, + G_CALLBACK (supplicant_iface_connection_error_cb), + self); if (!nm_supplicant_interface_set_config (priv->supplicant.iface, config)) { nm_log_err (LOGD_DEVICE | LOGD_WIFI, From 0171315c78f766a61f28762b966345cdccf28177 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Apr 2014 12:02:46 -0500 Subject: [PATCH 06/14] wifi: collapse Supplicant struct and clean up timeouts There used to be many more members of the Supplicant struct, but now that there are only three, collapse the struct into the NMDeviceWifiPrivate struct, renaming them slightly at the same time to shorten the names. Second, consolidate timeout cleanup since the two remaining timeouts don't need their own cleanup functions. Third, start_supplicant_connection_timeout() doesn't need its own function since g_timeout_add() never returns 0, so we don't need to check for it. --- src/devices/wifi/nm-device-wifi.c | 195 ++++++++++-------------------- 1 file changed, 67 insertions(+), 128 deletions(-) diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 9bf2b30b81..d3b0bcf4c0 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -112,14 +112,6 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -typedef struct Supplicant { - NMSupplicantManager *mgr; - NMSupplicantInterface *iface; - - /* Timeouts and idles */ - guint con_timeout_id; -} Supplicant; - struct _NMDeviceWifiPrivate { gboolean disposed; @@ -139,7 +131,10 @@ struct _NMDeviceWifiPrivate { guint scanlist_cull_id; gboolean requested_scan; - Supplicant supplicant; + NMSupplicantManager *sup_mgr; + NMSupplicantInterface *sup_iface; + guint sup_timeout_id; /* supplicant association timeout */ + gboolean ssid_found; NM80211Mode mode; @@ -159,8 +154,6 @@ static void cancel_pending_scan (NMDeviceWifi *self); static void cleanup_association_attempt (NMDeviceWifi * self, gboolean disconnect); -static void remove_supplicant_timeouts (NMDeviceWifi *self); - static void supplicant_iface_state_cb (NMSupplicantInterface *iface, guint32 new_state, guint32 old_state, @@ -248,8 +241,8 @@ constructor (GType type, } /* Connect to the supplicant manager */ - priv->supplicant.mgr = nm_supplicant_manager_get (); - g_assert (priv->supplicant.mgr); + priv->sup_mgr = nm_supplicant_manager_get (); + g_assert (priv->sup_mgr); return object; } @@ -261,41 +254,41 @@ supplicant_interface_acquire (NMDeviceWifi *self) g_return_val_if_fail (self != NULL, FALSE); /* interface already acquired? */ - g_return_val_if_fail (priv->supplicant.iface == NULL, TRUE); + g_return_val_if_fail (priv->sup_iface == NULL, TRUE); - priv->supplicant.iface = nm_supplicant_manager_iface_get (priv->supplicant.mgr, - nm_device_get_iface (NM_DEVICE (self)), - TRUE); - if (priv->supplicant.iface == NULL) { + priv->sup_iface = nm_supplicant_manager_iface_get (priv->sup_mgr, + nm_device_get_iface (NM_DEVICE (self)), + TRUE); + if (priv->sup_iface == NULL) { nm_log_err (LOGD_WIFI, "Couldn't initialize supplicant interface for %s.", nm_device_get_iface (NM_DEVICE (self))); return FALSE; } - if (nm_supplicant_interface_get_state (priv->supplicant.iface) < NM_SUPPLICANT_INTERFACE_STATE_READY) + if (nm_supplicant_interface_get_state (priv->sup_iface) < NM_SUPPLICANT_INTERFACE_STATE_READY) nm_device_add_pending_action (NM_DEVICE (self), "waiting for supplicant", TRUE); - g_signal_connect (priv->supplicant.iface, + g_signal_connect (priv->sup_iface, NM_SUPPLICANT_INTERFACE_STATE, G_CALLBACK (supplicant_iface_state_cb), self); - g_signal_connect (priv->supplicant.iface, + g_signal_connect (priv->sup_iface, NM_SUPPLICANT_INTERFACE_NEW_BSS, G_CALLBACK (supplicant_iface_new_bss_cb), self); - g_signal_connect (priv->supplicant.iface, + g_signal_connect (priv->sup_iface, NM_SUPPLICANT_INTERFACE_BSS_UPDATED, G_CALLBACK (supplicant_iface_bss_updated_cb), self); - g_signal_connect (priv->supplicant.iface, + g_signal_connect (priv->sup_iface, NM_SUPPLICANT_INTERFACE_BSS_REMOVED, G_CALLBACK (supplicant_iface_bss_removed_cb), self); - g_signal_connect (priv->supplicant.iface, + g_signal_connect (priv->sup_iface, NM_SUPPLICANT_INTERFACE_SCAN_DONE, G_CALLBACK (supplicant_iface_scan_done_cb), self); - g_signal_connect (priv->supplicant.iface, + g_signal_connect (priv->sup_iface, "notify::scanning", G_CALLBACK (supplicant_iface_notify_scanning_cb), self); @@ -325,17 +318,17 @@ supplicant_interface_release (NMDeviceWifi *self) priv->scanlist_cull_id = 0; } - if (priv->supplicant.iface) { + if (priv->sup_iface) { remove_supplicant_interface_error_handler (self); /* Clear supplicant interface signal handlers */ - g_signal_handlers_disconnect_by_data (priv->supplicant.iface, self); + g_signal_handlers_disconnect_by_data (priv->sup_iface, self); /* Tell the supplicant to disconnect from the current AP */ - nm_supplicant_interface_disconnect (priv->supplicant.iface); + nm_supplicant_interface_disconnect (priv->sup_iface); - nm_supplicant_manager_iface_release (priv->supplicant.mgr, priv->supplicant.iface); - priv->supplicant.iface = NULL; + nm_supplicant_manager_iface_release (priv->sup_mgr, priv->sup_iface); + priv->sup_iface = NULL; } } @@ -600,10 +593,10 @@ periodic_update (NMDeviceWifi *self, NMAccessPoint *ignore_ap) * assume the old one (if any) is still valid until we're told otherwise or * the connection fails. */ - supplicant_state = nm_supplicant_interface_get_state (priv->supplicant.iface); + supplicant_state = nm_supplicant_interface_get_state (priv->sup_iface); if ( supplicant_state < NM_SUPPLICANT_INTERFACE_STATE_AUTHENTICATING || supplicant_state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED - || nm_supplicant_interface_get_scanning (priv->supplicant.iface)) + || nm_supplicant_interface_get_scanning (priv->sup_iface)) return; /* In AP mode we currently have nothing to do. */ @@ -917,8 +910,8 @@ check_connection_compatible (NMDevice *device, return FALSE; } - if (priv->supplicant.iface) { - switch (nm_supplicant_interface_get_ap_support (priv->supplicant.iface)) { + if (priv->sup_iface) { + switch (nm_supplicant_interface_get_ap_support (priv->sup_iface)) { case AP_SUPPORT_NO: g_set_error_literal (error, NM_WIFI_ERROR, @@ -1229,7 +1222,7 @@ is_available (NMDevice *dev) return FALSE; } - sup_iface = priv->supplicant.iface; + sup_iface = priv->sup_iface; if (!sup_iface) { nm_log_dbg (LOGD_WIFI, "(%s): not available because supplicant not running", nm_device_get_iface (dev)); @@ -1376,7 +1369,7 @@ impl_device_request_scan (NMDeviceWifi *self, GError *error; if ( !priv->enabled - || !priv->supplicant.iface + || !priv->sup_iface || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED || nm_device_is_activating (device)) { error = g_error_new_literal (NM_WIFI_ERROR, @@ -1385,14 +1378,14 @@ impl_device_request_scan (NMDeviceWifi *self, goto error; } - if (nm_supplicant_interface_get_scanning (priv->supplicant.iface)) { + if (nm_supplicant_interface_get_scanning (priv->sup_iface)) { error = g_error_new_literal (NM_WIFI_ERROR, NM_WIFI_ERROR_SCAN_NOT_ALLOWED, "Scanning not allowed while already scanning"); goto error; } - last_scan = nm_supplicant_interface_get_last_scan_time (priv->supplicant.iface); + last_scan = nm_supplicant_interface_get_last_scan_time (priv->sup_iface); if (last_scan && (nm_utils_get_monotonic_timestamp_s () - last_scan) < 10) { error = g_error_new_literal (NM_WIFI_ERROR, NM_WIFI_ERROR_SCAN_NOT_ALLOWED, @@ -1423,7 +1416,7 @@ scanning_allowed (NMDeviceWifi *self) guint32 sup_state; NMConnection *connection; - g_return_val_if_fail (priv->supplicant.iface != NULL, FALSE); + g_return_val_if_fail (priv->sup_iface != NULL, FALSE); /* Scanning not done in AP mode */ if (priv->mode == NM_802_11_MODE_AP) @@ -1452,12 +1445,12 @@ scanning_allowed (NMDeviceWifi *self) } /* Don't scan if the supplicant is busy */ - sup_state = nm_supplicant_interface_get_state (priv->supplicant.iface); + sup_state = nm_supplicant_interface_get_state (priv->sup_iface); if ( sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING || sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED || sup_state == NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE || sup_state == NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE - || nm_supplicant_interface_get_scanning (priv->supplicant.iface)) + || nm_supplicant_interface_get_scanning (priv->sup_iface)) return FALSE; connection = nm_device_get_connection (NM_DEVICE (self)); @@ -1531,7 +1524,7 @@ static GPtrArray * build_hidden_probe_list (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - guint max_scan_ssids = nm_supplicant_interface_get_max_scan_ssids (priv->supplicant.iface); + guint max_scan_ssids = nm_supplicant_interface_get_max_scan_ssids (priv->sup_iface); GSList *connections, *iter; GPtrArray *ssids = NULL; static GByteArray *nullssid = NULL; @@ -1608,7 +1601,7 @@ request_wireless_scan (gpointer user_data) } } - if (nm_supplicant_interface_request_scan (priv->supplicant.iface, ssids)) { + if (nm_supplicant_interface_request_scan (priv->sup_iface, ssids)) { /* success */ backoff = TRUE; priv->requested_scan = TRUE; @@ -2015,6 +2008,21 @@ supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface, g_object_set_data (G_OBJECT (ap), WPAS_REMOVED_TAG, GUINT_TO_POINTER (TRUE)); } +static void +remove_supplicant_timeouts (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + if (priv->sup_timeout_id) { + g_source_remove (priv->sup_timeout_id); + priv->sup_timeout_id = 0; + } + + if (priv->link_timeout_id) { + g_source_remove (priv->link_timeout_id); + priv->link_timeout_id = 0; + } +} static void cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect) @@ -2023,8 +2031,8 @@ cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect) remove_supplicant_interface_error_handler (self); remove_supplicant_timeouts (self); - if (disconnect && priv->supplicant.iface) - nm_supplicant_interface_disconnect (priv->supplicant.iface); + if (disconnect && priv->sup_iface) + nm_supplicant_interface_disconnect (priv->sup_iface); } static void @@ -2049,21 +2057,6 @@ wifi_secrets_cb (NMActRequest *req, nm_device_activate_schedule_stage1_device_prepare (dev); } -static void -remove_link_timeout (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv; - - g_return_if_fail (self != NULL); - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - if (priv->link_timeout_id) { - g_source_remove (priv->link_timeout_id); - priv->link_timeout_id = 0; - } -} - - /* * link_timeout_cb * @@ -2388,8 +2381,8 @@ remove_supplicant_interface_error_handler (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - if (priv->supplicant.iface) { - g_signal_handlers_disconnect_by_func (priv->supplicant.iface, + if (priv->sup_iface) { + g_signal_handlers_disconnect_by_func (priv->sup_iface, supplicant_iface_connection_error_cb, self); } @@ -2416,21 +2409,6 @@ supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface, periodic_update (self, NULL); } -static void -remove_supplicant_connection_timeout (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv; - - g_return_if_fail (self != NULL); - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - /* Remove any pending timeouts on the request */ - if (priv->supplicant.con_timeout_id) { - g_source_remove (priv->supplicant.con_timeout_id); - priv->supplicant.con_timeout_id = 0; - } -} - static NMActStageReturn handle_auth_or_fail (NMDeviceWifi *self, NMActRequest *req, @@ -2564,40 +2542,6 @@ supplicant_connection_timeout_cb (gpointer user_data) return FALSE; } - -static gboolean -start_supplicant_connection_timeout (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv; - guint id; - - g_return_val_if_fail (self != NULL, FALSE); - - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - /* Set up a timeout on the connection attempt to fail it after 25 seconds */ - id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self); - if (id == 0) { - nm_log_err (LOGD_DEVICE | LOGD_WIFI, - "Activation (%s/wireless): couldn't start supplicant " - "timeout timer.", - nm_device_get_iface (NM_DEVICE (self))); - return FALSE; - } - priv->supplicant.con_timeout_id = id; - return TRUE; -} - - -static void -remove_supplicant_timeouts (NMDeviceWifi *self) -{ - g_return_if_fail (self != NULL); - - remove_supplicant_connection_timeout (self); - remove_link_timeout (self); -} - static NMSupplicantConfig * build_supplicant_config (NMDeviceWifi *self, NMConnection *connection, @@ -2619,7 +2563,7 @@ build_supplicant_config (NMDeviceWifi *self, /* Warn if AP mode may not be supported */ if ( g_strcmp0 (nm_setting_wireless_get_mode (s_wireless), NM_SETTING_WIRELESS_MODE_AP) == 0 - && nm_supplicant_interface_get_ap_support (priv->supplicant.iface) == AP_SUPPORT_UNKNOWN) { + && nm_supplicant_interface_get_ap_support (priv->sup_iface) == AP_SUPPORT_UNKNOWN) { nm_log_warn (LOGD_WIFI, "Supplicant may not support AP mode; connection may time out."); } @@ -2935,12 +2879,12 @@ act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) } /* Hook up error signal handler to capture association errors */ - g_signal_connect (priv->supplicant.iface, + g_signal_connect (priv->sup_iface, NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR, G_CALLBACK (supplicant_iface_connection_error_cb), self); - if (!nm_supplicant_interface_set_config (priv->supplicant.iface, config)) { + if (!nm_supplicant_interface_set_config (priv->sup_iface, config)) { nm_log_err (LOGD_DEVICE | LOGD_WIFI, "Activation (%s/wireless): couldn't send wireless " "configuration to the supplicant.", iface); @@ -2948,10 +2892,8 @@ act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) goto out; } - if (!start_supplicant_connection_timeout (self)) { - *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; - goto out; - } + /* Set up a timeout on the association attempt to fail after 25 seconds */ + priv->sup_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self); if (!priv->periodic_source_id) priv->periodic_source_id = g_timeout_add_seconds (6, periodic_update_cb, self); @@ -3257,7 +3199,7 @@ device_state_changed (NMDevice *device, /* Clean up the supplicant interface because in these states the * device cannot be used. */ - if (priv->supplicant.iface) + if (priv->sup_iface) supplicant_interface_release (self); if (priv->periodic_source_id) { @@ -3279,14 +3221,14 @@ device_state_changed (NMDevice *device, * the device is now ready to use. */ if (priv->enabled && (nm_device_get_firmware_missing (device) == FALSE)) { - if (!priv->supplicant.iface) + if (!priv->sup_iface) supplicant_interface_acquire (self); } clear_aps = TRUE; break; case NM_DEVICE_STATE_NEED_AUTH: - if (priv->supplicant.iface) - nm_supplicant_interface_disconnect (priv->supplicant.iface); + if (priv->sup_iface) + nm_supplicant_interface_disconnect (priv->sup_iface); break; case NM_DEVICE_STATE_IP_CHECK: /* Clear any critical protocol notification in the wifi stack */ @@ -3356,7 +3298,7 @@ set_enabled (NMDevice *device, gboolean enabled) } /* Re-initialize the supplicant interface and wait for it to be ready */ - if (priv->supplicant.iface) + if (priv->sup_iface) supplicant_interface_release (self); supplicant_interface_acquire (self); @@ -3412,10 +3354,7 @@ dispose (GObject *object) cleanup_association_attempt (self, TRUE); supplicant_interface_release (self); - if (priv->supplicant.mgr) { - g_object_unref (priv->supplicant.mgr); - priv->supplicant.mgr = NULL; - } + g_clear_object (&priv->sup_mgr); remove_all_aps (self); @@ -3457,7 +3396,7 @@ get_property (GObject *object, guint prop_id, g_value_set_boxed (value, "/"); break; case PROP_SCANNING: - g_value_set_boolean (value, nm_supplicant_interface_get_scanning (priv->supplicant.iface)); + g_value_set_boolean (value, nm_supplicant_interface_get_scanning (priv->sup_iface)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); From a9fa1bd9e281d6c20df7a25da0cc2c6921560f1d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Apr 2014 14:12:39 -0500 Subject: [PATCH 07/14] platform: don't crash on link_change() error when ifname is NULL to_string_link() logs link details and creates a new link to do this, filling in the various filed in init_link(). init_link() attempts to fill in the driver name, and might call ethtool to do that. Well, ethtool API only accepts an interface name (which we don't have) and not an ifindex (which we do have), and dies. Ensure that the ethtool functions bail out instead of crashing if they don't get an interface name. Unfortunately, most callers of link_change() don't bother setting ifindex or ifname on the link that ends up getting passed to to_string_link(), because libnl doesn't require that when calling rtnl_link_change(). Modify all callers to at least set the ifindex so that to_string_link() has something useful to log. NetworkManager[10651]: (msh0): device state change: unmanaged -> unavailable (reason 'managed') [10 20 2] NetworkManager[10651]: (platform/nm-linux-platform.c:684):link_extract_type: runtime check failed: (ifname != NULL) NetworkManager[10651]: [1398107504.807205] [platform/nm-linux-platform.c:1856] link_change(): Netlink error changing link 12: mtu 0 (1) driver 'usb8xxx' udi '/sys/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/net/msh0': Message sequence number mismatch at platform/nm-linux-platform.c:691 at platform/nm-linux-platform.c:1850 at devices/nm-device.c:5523 NM_DEVICE_STATE_REASON_NOW_MANAGED) at devices/nm-device.c:6662 at nm-manager.c:2115 --- src/platform/nm-linux-platform.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 82c2fed26c..ee62e49890 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -623,6 +623,8 @@ ethtool_get_driver (const char *ifname) { struct ethtool_drvinfo drvinfo = { 0 }; + g_return_val_if_fail (ifname != NULL, NULL); + drvinfo.cmd = ETHTOOL_GDRVINFO; if (!ethtool_get (ifname, &drvinfo)) return NULL; @@ -665,13 +667,15 @@ link_extract_type (NMPlatform *platform, struct rtnl_link *rtnllink, const char const char *driver; const char *ifname; - if (arptype == ARPHRD_LOOPBACK) return_type (NM_LINK_TYPE_LOOPBACK, "loopback"); else if (arptype == ARPHRD_INFINIBAND) return_type (NM_LINK_TYPE_INFINIBAND, "infiniband"); ifname = rtnl_link_get_name (rtnllink); + if (!ifname) + return_type (NM_LINK_TYPE_UNKNOWN, type); + if (arptype == 256) { /* Some s390 CTC-type devices report 256 for the encapsulation type * for some reason, but we need to call them Ethernet. FIXME: use @@ -1818,6 +1822,7 @@ link_change (NMPlatform *platform, int ifindex, struct rtnl_link *change) if (!rtnllink) return FALSE; + g_return_val_if_fail (rtnl_link_get_ifindex (change) > 0, FALSE); nle = rtnl_link_change (priv->nlh, rtnllink, change, 0); @@ -1943,6 +1948,7 @@ link_change_flags (NMPlatform *platform, int ifindex, unsigned int flags, gboole auto_nl_object struct rtnl_link *change = rtnl_link_alloc (); g_return_val_if_fail (change != NULL, FALSE); + rtnl_link_set_ifindex (change, ifindex); if (value) rtnl_link_set_flags (change, flags); @@ -2093,6 +2099,7 @@ link_set_address (NMPlatform *platform, int ifindex, gconstpointer address, size change = rtnl_link_alloc (); g_return_val_if_fail (change, FALSE); + rtnl_link_set_ifindex (change, ifindex); nladdr = nl_addr_build (AF_LLC, address, length); g_return_val_if_fail (nladdr, FALSE); @@ -2129,6 +2136,7 @@ link_set_mtu (NMPlatform *platform, int ifindex, guint32 mtu) auto_nl_object struct rtnl_link *change = rtnl_link_alloc (); g_return_val_if_fail (change != NULL, FALSE); + rtnl_link_set_ifindex (change, ifindex); rtnl_link_set_mtu (change, mtu); debug ("link: change %d: mtu %lu", ifindex, (unsigned long)mtu); @@ -2240,6 +2248,7 @@ link_enslave (NMPlatform *platform, int master, int slave) g_return_val_if_fail (change != NULL, FALSE); + rtnl_link_set_ifindex (change, slave); rtnl_link_set_master (change, master); debug ("link: change %d: enslave to master %d", slave, master); From ee6febf297ac485b131b4c49d1b7feb55e22192b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Apr 2014 12:24:42 -0500 Subject: [PATCH 08/14] olpc-mesh: use g_signal_handlers_disconnect_by_data() --- src/devices/wifi/nm-device-olpc-mesh.c | 46 ++++++-------------------- 1 file changed, 11 insertions(+), 35 deletions(-) diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index cfb12fc086..08afa25e66 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -84,10 +84,6 @@ struct _NMDeviceOlpcMeshPrivate { gboolean stage1_waiting; guint device_added_id; guint device_removed_id; - guint cmp_state_changed_id; - guint cmp_scanning_id; - guint cmp_scanning_allowed_id; - guint cmp_autoconnect_allowed_id; }; static void state_changed (NMDevice *device, NMDeviceState new_state, @@ -314,30 +310,10 @@ companion_cleanup (NMDeviceOlpcMesh *self) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - if (priv->companion == NULL) - return; - - if (priv->cmp_state_changed_id) { - g_signal_handler_disconnect (priv->companion, priv->cmp_state_changed_id); - priv->cmp_state_changed_id = 0; + if (priv->companion) { + g_signal_handlers_disconnect_by_data (priv->companion, self); + priv->companion = NULL; } - - if (priv->cmp_scanning_id) { - g_signal_handler_disconnect (priv->companion, priv->cmp_scanning_id); - priv->cmp_scanning_id = 0; - } - - if (priv->cmp_scanning_allowed_id) { - g_signal_handler_disconnect (priv->companion, priv->cmp_scanning_allowed_id); - priv->cmp_scanning_allowed_id = 0; - } - - if (priv->cmp_autoconnect_allowed_id) { - g_signal_handler_disconnect (priv->companion, priv->cmp_autoconnect_allowed_id); - priv->cmp_autoconnect_allowed_id = 0; - } - - priv->companion = NULL; g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_COMPANION); } @@ -540,17 +516,17 @@ is_companion (NMDeviceOlpcMesh *self, NMDevice *other) nm_device_get_iface (NM_DEVICE (self)), nm_device_get_iface (other)); - priv->cmp_state_changed_id = g_signal_connect (G_OBJECT (other), "state-changed", - G_CALLBACK (companion_state_changed_cb), self); + g_signal_connect (G_OBJECT (other), "state-changed", + G_CALLBACK (companion_state_changed_cb), self); - priv->cmp_scanning_id = g_signal_connect (G_OBJECT (other), "notify::scanning", - G_CALLBACK (companion_notify_cb), self); + g_signal_connect (G_OBJECT (other), "notify::scanning", + G_CALLBACK (companion_notify_cb), self); - priv->cmp_scanning_allowed_id = g_signal_connect (G_OBJECT (other), "scanning-allowed", - G_CALLBACK (companion_scan_allowed_cb), self); + g_signal_connect (G_OBJECT (other), "scanning-allowed", + G_CALLBACK (companion_scan_allowed_cb), self); - priv->cmp_autoconnect_allowed_id = g_signal_connect (G_OBJECT (other), "autoconnect-allowed", - G_CALLBACK (companion_autoconnect_allowed_cb), self); + g_signal_connect (G_OBJECT (other), "autoconnect-allowed", + G_CALLBACK (companion_autoconnect_allowed_cb), self); g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_COMPANION); From b486c630346d1206ea6296780d3cb99502d9586f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Apr 2014 12:25:52 -0500 Subject: [PATCH 09/14] olpc-mesh: clean up dispose() Allow it to be called multiple times. --- src/devices/wifi/nm-device-olpc-mesh.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index 08afa25e66..00a0b7f8b8 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -78,8 +78,6 @@ enum { struct _NMDeviceOlpcMeshPrivate { - gboolean dispose_has_run; - NMDevice * companion; gboolean stage1_waiting; guint device_added_id; @@ -101,11 +99,6 @@ nm_olpc_mesh_error_quark (void) static void nm_device_olpc_mesh_init (NMDeviceOlpcMesh * self) { - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - - priv->dispose_has_run = FALSE; - priv->companion = NULL; - priv->stage1_waiting = FALSE; } static GObject* @@ -323,18 +316,16 @@ dispose (GObject *object) NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - if (priv->dispose_has_run) { - G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); - return; - } - priv->dispose_has_run = TRUE; - companion_cleanup (self); - if (priv->device_added_id) + if (priv->device_added_id) { g_signal_handler_disconnect (nm_manager_get (), priv->device_added_id); - if (priv->device_removed_id) + priv->device_added_id = 0; + } + if (priv->device_removed_id) { g_signal_handler_disconnect (nm_manager_get (), priv->device_removed_id); + priv->device_removed_id = 0; + } G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); } From 98bd65c6e9f7ed6d3d1892818e7180854079290f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Apr 2014 12:58:53 -0500 Subject: [PATCH 10/14] olpc-mesh: rework companion detection Just listen to manager signals all the time, but only respond to them when necessary. Clean up companion detection to be a bit clearer, and use nm_device_queue_state() so that we don't need an idle handler when detecting the companion from a state change handler. --- src/devices/wifi/nm-device-olpc-mesh.c | 119 +++++++++---------------- 1 file changed, 40 insertions(+), 79 deletions(-) diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index 00a0b7f8b8..64ed6acb6d 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -19,7 +19,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * (C) Copyright 2005 - 2011 Red Hat, Inc. + * (C) Copyright 2005 - 2014 Red Hat, Inc. * (C) Copyright 2008 Collabora Ltd. * (C) Copyright 2009 One Laptop per Child */ @@ -78,15 +78,16 @@ enum { struct _NMDeviceOlpcMeshPrivate { - NMDevice * companion; - gboolean stage1_waiting; - guint device_added_id; - guint device_removed_id; + NMDevice *companion; + gboolean stage1_waiting; }; static void state_changed (NMDevice *device, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason); +static void device_added_cb (NMManager *manager, NMDevice *other, gpointer user_data); +static void device_removed_cb (NMManager *manager, NMDevice *other, gpointer user_data); + static GQuark nm_olpc_mesh_error_quark (void) { @@ -129,6 +130,9 @@ constructor (GType type, return NULL; } + g_signal_connect (nm_manager_get (), "device-added", G_CALLBACK (device_added_cb), self); + g_signal_connect (nm_manager_get (), "device-removed", G_CALLBACK (device_removed_cb), self); + /* shorter timeout for mesh connectivity */ nm_device_set_dhcp_timeout (NM_DEVICE (self), 20); return object; @@ -305,7 +309,7 @@ companion_cleanup (NMDeviceOlpcMesh *self) if (priv->companion) { g_signal_handlers_disconnect_by_data (priv->companion, self); - priv->companion = NULL; + g_clear_object (&priv->companion); } g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_COMPANION); } @@ -314,18 +318,10 @@ static void dispose (GObject *object) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object); - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); companion_cleanup (self); - - if (priv->device_added_id) { - g_signal_handler_disconnect (nm_manager_get (), priv->device_added_id); - priv->device_added_id = 0; - } - if (priv->device_removed_id) { - g_signal_handler_disconnect (nm_manager_get (), priv->device_removed_id); - priv->device_removed_id = 0; - } + g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_added_cb), self); + g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_removed_cb), self); G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); } @@ -476,7 +472,7 @@ companion_autoconnect_allowed_cb (NMDeviceWifi *companion, gpointer user_data) } static gboolean -is_companion (NMDeviceOlpcMesh *self, NMDevice *other) +check_companion (NMDeviceOlpcMesh *self, NMDevice *other) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); const guint8 *my_addr, *their_addr; @@ -491,17 +487,8 @@ is_companion (NMDeviceOlpcMesh *self, NMDevice *other) || (memcmp (my_addr, their_addr, ETH_ALEN) != 0)) return FALSE; - priv->companion = other; - - /* When we've found the companion, stop listening for other devices */ - if (priv->device_added_id) { - g_signal_handler_disconnect (nm_manager_get (), priv->device_added_id); - priv->device_added_id = 0; - } - - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); + g_assert (priv->companion == NULL); + priv->companion = g_object_ref (other); nm_log_info (LOGD_OLPC, "(%s): found companion WiFi device %s", nm_device_get_iface (NM_DEVICE (self)), @@ -528,8 +515,14 @@ static void device_added_cb (NMManager *manager, NMDevice *other, gpointer user_data) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - is_companion (self, other); + if (!priv->companion && check_companion (self, other)) { + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NONE); + nm_device_remove_pending_action (NM_DEVICE (self), "waiting for companion", TRUE); + } } static void @@ -541,69 +534,37 @@ device_removed_cb (NMManager *manager, NMDevice *other, gpointer user_data) companion_cleanup (self); } -static gboolean -check_companion_cb (gpointer user_data) +static void +find_companion (NMDeviceOlpcMesh *self) { - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - NMManager *manager; GSList *list; - if (priv->companion != NULL) { - nm_device_state_changed (NM_DEVICE (user_data), - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); - goto done; - } + if (priv->companion) + return; - if (priv->device_added_id != 0) - goto done; - - manager = nm_manager_get (); - - priv->device_added_id = g_signal_connect (manager, "device-added", - G_CALLBACK (device_added_cb), self); - if (!priv->device_removed_id) { - priv->device_removed_id = g_signal_connect (manager, "device-removed", - G_CALLBACK (device_removed_cb), self); - } + nm_device_add_pending_action (NM_DEVICE (self), "waiting for companion", TRUE); /* Try to find the companion if it's already known to the NMManager */ - for (list = nm_manager_get_devices (manager); list ; list = g_slist_next (list)) { - if (is_companion (self, NM_DEVICE (list->data))) + for (list = nm_manager_get_devices (nm_manager_get ()); list ; list = g_slist_next (list)) { + if (check_companion (self, NM_DEVICE (list->data))) { + nm_device_queue_state (NM_DEVICE (self), + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NONE); + nm_device_remove_pending_action (NM_DEVICE (self), "waiting for companion", TRUE); break; + } } - - done: - nm_device_remove_pending_action (NM_DEVICE (self), "waiting for companion", TRUE); - return FALSE; } static void -state_changed (NMDevice *device, NMDeviceState new_state, - NMDeviceState old_state, NMDeviceStateReason reason) +state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason) { - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device); - - switch (new_state) { - case NM_DEVICE_STATE_UNMANAGED: - break; - case NM_DEVICE_STATE_UNAVAILABLE: - /* If transitioning to UNAVAILABLE and the companion device is known then - * transition to DISCONNECTED otherwise wait for our companion. - */ - g_idle_add (check_companion_cb, self); - nm_device_add_pending_action (device, "waiting for companion", TRUE); - break; - case NM_DEVICE_STATE_ACTIVATED: - break; - case NM_DEVICE_STATE_FAILED: - break; - case NM_DEVICE_STATE_DISCONNECTED: - break; - default: - break; - } + if (new_state == NM_DEVICE_STATE_UNAVAILABLE) + find_companion (NM_DEVICE_OLPC_MESH (device)); } From 8ab45e3e5c4276ed2367827dbc1e7e28212921c2 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Apr 2014 14:24:47 -0500 Subject: [PATCH 11/14] olpc-mesh: reorganize functions (trivial) Move GObject related stuff to the bottom and get rid of forward declarations that are no longer. No code changes, only code movement. --- src/devices/wifi/nm-device-olpc-mesh.c | 281 ++++++++++++------------- 1 file changed, 140 insertions(+), 141 deletions(-) diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index 64ed6acb6d..c79f85d80c 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -65,7 +65,6 @@ G_DEFINE_TYPE (NMDeviceOlpcMesh, nm_device_olpc_mesh, NM_TYPE_DEVICE) #define NM_DEVICE_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshPrivate)) - enum { PROP_0, PROP_COMPANION, @@ -74,19 +73,12 @@ enum { LAST_PROP }; -#define NM_OLPC_MESH_ERROR (nm_olpc_mesh_error_quark ()) - - struct _NMDeviceOlpcMeshPrivate { NMDevice *companion; gboolean stage1_waiting; }; -static void state_changed (NMDevice *device, NMDeviceState new_state, - NMDeviceState old_state, NMDeviceStateReason reason); - -static void device_added_cb (NMManager *manager, NMDevice *other, gpointer user_data); -static void device_removed_cb (NMManager *manager, NMDevice *other, gpointer user_data); +/*******************************************************************/ static GQuark nm_olpc_mesh_error_quark (void) @@ -97,46 +89,9 @@ nm_olpc_mesh_error_quark (void) return quark; } -static void -nm_device_olpc_mesh_init (NMDeviceOlpcMesh * self) -{ -} +#define NM_OLPC_MESH_ERROR (nm_olpc_mesh_error_quark ()) -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - GObjectClass *klass; - NMDeviceOlpcMesh *self; - NMDeviceWifiCapabilities caps; - - klass = G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class); - object = klass->constructor (type, n_construct_params, construct_params); - if (!object) - return NULL; - - self = NM_DEVICE_OLPC_MESH (object); - - nm_log_dbg (LOGD_HW | LOGD_OLPC, "(%s): kernel ifindex %d", - nm_device_get_iface (NM_DEVICE (self)), - nm_device_get_ifindex (NM_DEVICE (self))); - - if (!nm_platform_wifi_get_capabilities (nm_device_get_ifindex (NM_DEVICE (self)), &caps)) { - nm_log_warn (LOGD_HW | LOGD_OLPC, "(%s): failed to initialize WiFi driver", - nm_device_get_iface (NM_DEVICE (self))); - g_object_unref (object); - return NULL; - } - - g_signal_connect (nm_manager_get (), "device-added", G_CALLBACK (device_added_cb), self); - g_signal_connect (nm_manager_get (), "device-removed", G_CALLBACK (device_removed_cb), self); - - /* shorter timeout for mesh connectivity */ - nm_device_set_dhcp_timeout (NM_DEVICE (self), 20); - return object; -} +/*******************************************************************/ static gboolean check_connection_compatible (NMDevice *device, @@ -302,6 +257,8 @@ act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) return NM_ACT_STAGE_RETURN_SUCCESS; } +/*******************************************************************/ + static void companion_cleanup (NMDeviceOlpcMesh *self) { @@ -314,99 +271,6 @@ companion_cleanup (NMDeviceOlpcMesh *self) g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_COMPANION); } -static void -dispose (GObject *object) -{ - NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object); - - companion_cleanup (self); - g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_added_cb), self); - g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_removed_cb), self); - - G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceOlpcMesh *device = NM_DEVICE_OLPC_MESH (object); - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (device); - - switch (prop_id) { - case PROP_COMPANION: - if (priv->companion) - g_value_set_boxed (value, nm_device_get_path (priv->companion)); - else - g_value_set_boxed (value, "/"); - break; - case PROP_ACTIVE_CHANNEL: - g_value_set_uint (value, nm_platform_mesh_get_channel (nm_device_get_ifindex (NM_DEVICE (device)))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMDeviceOlpcMeshPrivate)); - - object_class->constructor = constructor; - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->dispose = dispose; - - parent_class->check_connection_compatible = check_connection_compatible; - parent_class->can_auto_connect = can_auto_connect; - parent_class->complete_connection = complete_connection; - - parent_class->act_stage1_prepare = act_stage1_prepare; - parent_class->act_stage2_config = act_stage2_config; - - parent_class->state_changed = state_changed; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_COMPANION, - g_param_spec_boxed (NM_DEVICE_OLPC_MESH_COMPANION, - "Companion device", - "Companion device object path", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_ACTIVE_CHANNEL, - g_param_spec_uint (NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL, - "Active channel", - "Active channel", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE)); - - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_olpc_mesh_object_info); - - dbus_g_error_domain_register (NM_OLPC_MESH_ERROR, NULL, - NM_TYPE_OLPC_MESH_ERROR); -} - static void companion_notify_cb (NMDeviceWifi *companion, GParamSpec *pspec, gpointer user_data) { @@ -567,6 +431,7 @@ state_changed (NMDevice *device, find_companion (NM_DEVICE_OLPC_MESH (device)); } +/*******************************************************************/ NMDevice * nm_device_olpc_mesh_new (NMPlatformLink *platform_device) @@ -579,3 +444,137 @@ nm_device_olpc_mesh_new (NMPlatformLink *platform_device) NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_OLPC_MESH, NULL); } + +static void +nm_device_olpc_mesh_init (NMDeviceOlpcMesh * self) +{ +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + GObjectClass *klass; + NMDeviceOlpcMesh *self; + NMDeviceWifiCapabilities caps; + + klass = G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class); + object = klass->constructor (type, n_construct_params, construct_params); + if (!object) + return NULL; + + self = NM_DEVICE_OLPC_MESH (object); + + nm_log_dbg (LOGD_HW | LOGD_OLPC, "(%s): kernel ifindex %d", + nm_device_get_iface (NM_DEVICE (self)), + nm_device_get_ifindex (NM_DEVICE (self))); + + if (!nm_platform_wifi_get_capabilities (nm_device_get_ifindex (NM_DEVICE (self)), &caps)) { + nm_log_warn (LOGD_HW | LOGD_OLPC, "(%s): failed to initialize WiFi driver", + nm_device_get_iface (NM_DEVICE (self))); + g_object_unref (object); + return NULL; + } + + g_signal_connect (nm_manager_get (), "device-added", G_CALLBACK (device_added_cb), self); + g_signal_connect (nm_manager_get (), "device-removed", G_CALLBACK (device_removed_cb), self); + + /* shorter timeout for mesh connectivity */ + nm_device_set_dhcp_timeout (NM_DEVICE (self), 20); + return object; +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceOlpcMesh *device = NM_DEVICE_OLPC_MESH (object); + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (device); + + switch (prop_id) { + case PROP_COMPANION: + if (priv->companion) + g_value_set_boxed (value, nm_device_get_path (priv->companion)); + else + g_value_set_boxed (value, "/"); + break; + case PROP_ACTIVE_CHANNEL: + g_value_set_uint (value, nm_platform_mesh_get_channel (nm_device_get_ifindex (NM_DEVICE (device)))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object); + + companion_cleanup (self); + g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_added_cb), self); + g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_removed_cb), self); + + G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); +} + +static void +nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceOlpcMeshPrivate)); + + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + + parent_class->check_connection_compatible = check_connection_compatible; + parent_class->can_auto_connect = can_auto_connect; + parent_class->complete_connection = complete_connection; + + parent_class->act_stage1_prepare = act_stage1_prepare; + parent_class->act_stage2_config = act_stage2_config; + + parent_class->state_changed = state_changed; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_COMPANION, + g_param_spec_boxed (NM_DEVICE_OLPC_MESH_COMPANION, + "Companion device", + "Companion device object path", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, PROP_ACTIVE_CHANNEL, + g_param_spec_uint (NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL, + "Active channel", + "Active channel", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE)); + + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_olpc_mesh_object_info); + + dbus_g_error_domain_register (NM_OLPC_MESH_ERROR, NULL, NM_TYPE_OLPC_MESH_ERROR); +} + From 085bc0876c35e0d82ea65476df55f6e99a012366 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Apr 2014 14:39:55 -0500 Subject: [PATCH 12/14] platform: better detection of OLPC Mesh interfaces Instead of just looking at the udev tags, also look for sysfs entries that the libertas driver uses when mesh is enabled. --- src/platform/nm-linux-platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index ee62e49890..95f9854805 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -564,8 +564,8 @@ link_type_from_udev (NMPlatform *platform, int ifindex, const char *ifname, int if (!udev_device) return_type (NM_LINK_TYPE_UNKNOWN, "unknown"); - prop = g_udev_device_get_property (udev_device, "ID_NM_OLPC_MESH"); - if (prop) + if ( g_udev_device_get_property (udev_device, "ID_NM_OLPC_MESH") + || g_udev_device_get_sysfs_attr (udev_device, "anycast_mask")) return_type (NM_LINK_TYPE_OLPC_MESH, "olpc-mesh"); prop = g_udev_device_get_property (udev_device, "DEVTYPE"); From 7be2627b698531f0db1014e2708c1c2db3dee191 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Apr 2014 14:48:09 -0500 Subject: [PATCH 13/14] wifi: remove supplicant pending action if supplicant init fails If the supplicant interface object never successfully initialized, remove the pending action to prevent warnings about "pending action already added" when supplicant_interface_acquire() adds the pending action again. --- src/devices/wifi/nm-device-wifi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index d3b0bcf4c0..24403eaaad 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -2336,6 +2336,9 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, case NM_SUPPLICANT_INTERFACE_STATE_DOWN: cleanup_association_attempt (self, FALSE); + if (old_state < NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_remove_pending_action (device, "waiting for supplicant", TRUE); + /* If the device is already in UNAVAILABLE state then the state change * is a NOP and the interface won't be re-acquired in the device state * change handler. So ensure we have a new one here so that we're From 9e542faec1614c948ab7385869bdf8814262da51 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Apr 2014 14:49:19 -0500 Subject: [PATCH 14/14] olpc-mesh: mesh device is only available when Wi-Fi companion is found The mesh and Wi-Fi companion share radio hardware and firmware resources and you need both to exist for the mesh to function properly and to ensure that the Wi-Fi and mesh sides cooperate correctly for scanning and activation. --- src/devices/wifi/nm-device-olpc-mesh.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index c79f85d80c..9c25fd026a 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -257,6 +257,20 @@ act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) return NM_ACT_STAGE_RETURN_SUCCESS; } +static gboolean +is_available (NMDevice *dev) +{ + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); + + if (!NM_DEVICE_OLPC_MESH_GET_PRIVATE (self)->companion) { + nm_log_dbg (LOGD_WIFI, "(%s): not available because companion not found", + nm_device_get_iface (dev)); + return FALSE; + } + + return TRUE; +} + /*******************************************************************/ static void @@ -549,6 +563,7 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) parent_class->can_auto_connect = can_auto_connect; parent_class->complete_connection = complete_connection; + parent_class->is_available = is_available; parent_class->act_stage1_prepare = act_stage1_prepare; parent_class->act_stage2_config = act_stage2_config;