about summary refs log tree commit diff
path: root/src/devices
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-06-04 00:08:31 +0200
committerMichael Biebl <biebl@debian.org>2018-06-04 00:08:31 +0200
commit0dd9df69fdbd475c48a0c8d5b0a1882550fe7321 (patch)
tree249cf25643b1fe408e10679bb61613bc6540e894 /src/devices
parent2e94a3b93171ab3fb95bf689aab1664d23988809 (diff)
parent04bc9e1cd3544445d883ad29ea108c1645c8e7b7 (diff)
Update upstream source from tag 'upstream/1.11.4'
Update to upstream version '1.11.4'
with Debian dir d0638aa2e32d5bae4e8daa021b9a66b7c4d6647e
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/adsl/meson.build2
-rw-r--r--src/devices/adsl/nm-atm-manager.c2
-rw-r--r--src/devices/adsl/nm-device-adsl.c4
-rw-r--r--src/devices/bluetooth/meson.build2
-rw-r--r--src/devices/bluetooth/nm-bluez-device.c2
-rw-r--r--src/devices/bluetooth/nm-bluez-manager.c4
-rw-r--r--src/devices/nm-acd-manager.c6
-rw-r--r--src/devices/nm-device-bond.c4
-rw-r--r--src/devices/nm-device-dummy.c1
-rw-r--r--src/devices/nm-device-ethernet.c3
-rw-r--r--src/devices/nm-device-macsec.c1
-rw-r--r--src/devices/nm-device-macvlan.c1
-rw-r--r--src/devices/nm-device-ppp.c2
-rw-r--r--src/devices/nm-device-private.h2
-rw-r--r--src/devices/nm-device-tun.c1
-rw-r--r--src/devices/nm-device-vlan.c11
-rw-r--r--src/devices/nm-device.c185
-rw-r--r--src/devices/nm-device.h6
-rw-r--r--src/devices/ovs/meson.build2
-rw-r--r--src/devices/ovs/nm-device-ovs-port.c1
-rw-r--r--src/devices/ovs/nm-ovsdb.c21
-rw-r--r--src/devices/team/meson.build2
-rw-r--r--src/devices/tests/test-lldp.c1
-rw-r--r--src/devices/wifi/meson.build2
-rw-r--r--src/devices/wifi/nm-device-iwd.c10
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.c1
-rw-r--r--src/devices/wifi/nm-device-wifi.c5
-rw-r--r--src/devices/wifi/nm-iwd-manager.c1
-rw-r--r--src/devices/wifi/nm-wifi-common.c1
-rw-r--r--src/devices/wwan/meson.build4
-rw-r--r--src/devices/wwan/nm-modem-broadband.c4
-rw-r--r--src/devices/wwan/nm-modem-ofono.c1
-rw-r--r--src/devices/wwan/nm-modem.c62
-rw-r--r--src/devices/wwan/nm-wwan-factory.c1
34 files changed, 215 insertions, 143 deletions
diff --git a/src/devices/adsl/meson.build b/src/devices/adsl/meson.build
index 4b0fade0..ee804d23 100644
--- a/src/devices/adsl/meson.build
+++ b/src/devices/adsl/meson.build
@@ -15,7 +15,7 @@ libnm_device_plugin_adsl = shared_module(
   link_args: ldflags_linker_script_devices,
   link_depends: linker_script_devices,
   install: true,
-  install_dir: nm_pkglibdir
+  install_dir: nm_plugindir
 )
 
 core_plugins += libnm_device_plugin_adsl
diff --git a/src/devices/adsl/nm-atm-manager.c b/src/devices/adsl/nm-atm-manager.c
index 32c4c386..0ff4603d 100644
--- a/src/devices/adsl/nm-atm-manager.c
+++ b/src/devices/adsl/nm-atm-manager.c
@@ -236,7 +236,7 @@ handle_uevent (NMUdevClient *client,
 	ifindex = udev_device_get_property_value (device, "IFINDEX");
 	seqnum = udev_device_get_seqnum (device);
 	nm_log_dbg (LOGD_PLATFORM, "UDEV event: action '%s' subsys '%s' device '%s' (%s); seqnum=%" G_GUINT64_FORMAT,
-	            action, subsys, udev_device_get_sysname (device), ifindex ? ifindex : "unknown", seqnum);
+	            action, subsys, udev_device_get_sysname (device), ifindex ?: "unknown", seqnum);
 
 	if (!strcmp (action, "add"))
 		adsl_add (self, device);
diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c
index 91331376..1450a836 100644
--- a/src/devices/adsl/nm-device-adsl.c
+++ b/src/devices/adsl/nm-device-adsl.c
@@ -194,7 +194,7 @@ br2684_assign_vcc (NMDeviceAdsl *self, NMSettingAdsl *s_adsl)
 
 	_LOGD (LOGD_ADSL, "assigning address %d.%d.%d encapsulation %s",
 	       priv->atm_index, addr.sap_addr.vpi, addr.sap_addr.vci,
-	       encapsulation ? encapsulation : "(none)");
+	       encapsulation ?: "(none)");
 
 	err = connect (priv->brfd, (struct sockaddr*) &addr, sizeof (addr));
 	if (err != 0) {
@@ -525,7 +525,7 @@ adsl_cleanup (NMDeviceAdsl *self)
 	if (priv->ppp_manager) {
 		g_signal_handlers_disconnect_by_func (priv->ppp_manager, G_CALLBACK (ppp_state_changed), self);
 		g_signal_handlers_disconnect_by_func (priv->ppp_manager, G_CALLBACK (ppp_ip4_config), self);
-		nm_ppp_manager_stop_sync (priv->ppp_manager);
+		nm_ppp_manager_stop (priv->ppp_manager, NULL, NULL);
 		g_clear_object (&priv->ppp_manager);
 	}
 
diff --git a/src/devices/bluetooth/meson.build b/src/devices/bluetooth/meson.build
index eb200679..30284f9e 100644
--- a/src/devices/bluetooth/meson.build
+++ b/src/devices/bluetooth/meson.build
@@ -26,7 +26,7 @@ libnm_device_plugin_bluetooth = shared_module(
   link_args: ldflags_linker_script_devices,
   link_depends: linker_script_devices,
   install: true,
-  install_dir: nm_pkglibdir
+  install_dir: nm_plugindir
 )
 
 core_plugins += libnm_device_plugin_bluetooth
diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c
index cc9e38c8..d8e40d6f 100644
--- a/src/devices/bluetooth/nm-bluez-device.c
+++ b/src/devices/bluetooth/nm-bluez-device.c
@@ -494,7 +494,7 @@ nm_bluez_device_disconnect (NMBluezDevice *self)
 	                        priv->path,
 	                        dbus_iface,
 	                        "Disconnect",
-	                        args ? args : g_variant_new ("()"),
+	                        args ?: g_variant_new("()"),
 	                        NULL,
 	                        G_DBUS_CALL_FLAGS_NONE,
 	                        10000,
diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c
index 96e80245..c74ecd81 100644
--- a/src/devices/bluetooth/nm-bluez-manager.c
+++ b/src/devices/bluetooth/nm-bluez-manager.c
@@ -125,7 +125,6 @@ async_data_unpack (struct AsyncData *async_data)
 	return self;
 }
 
-
 /**
  * Cancel any current attempt to detect the version and cleanup
  * the related fields.
@@ -145,7 +144,6 @@ cleanup_checking (NMBluezManager *self, gboolean do_unwatch_name)
 	}
 }
 
-
 static void
 manager_bdaddr_added_cb (GObject *manager,
                          NMBluezDevice *bt_device,
@@ -244,7 +242,6 @@ setup_bluez5 (NMBluezManager *self)
 	nm_bluez5_manager_query_devices (manager);
 }
 
-
 static void
 watch_name_on_appeared (GDBusConnection *connection,
                         const gchar *name,
@@ -254,7 +251,6 @@ watch_name_on_appeared (GDBusConnection *connection,
 	check_bluez_and_try_setup (NM_BLUEZ_MANAGER (user_data));
 }
 
-
 static void
 check_bluez_and_try_setup_final_step (NMBluezManager *self, int bluez_version, const char *reason)
 {
diff --git a/src/devices/nm-acd-manager.c b/src/devices/nm-acd-manager.c
index 1bade4ff..035487a3 100644
--- a/src/devices/nm-acd-manager.c
+++ b/src/devices/nm-acd-manager.c
@@ -274,7 +274,11 @@ acd_probe_start (NMAcdManager *self,
 		return FALSE;
 	}
 
-	_LOGD ("start probe for %s", nm_utils_inet4_ntop (info->address, NULL));
+	if (timeout) {
+		_LOGD ("started probe for %s with timeout %llu",
+		       nm_utils_inet4_ntop (info->address, NULL),
+		       (unsigned long long) timeout);
+	}
 
 	return TRUE;
 }
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index 2dd9494a..22f7cdde 100644
--- a/src/devices/nm-device-bond.c
+++ b/src/devices/nm-device-bond.c
@@ -314,7 +314,7 @@ apply_bonding_config (NMDevice *device)
 
 	/* Primary */
 	value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
-	set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_PRIMARY, value ? value : "");
+	set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_PRIMARY, value ?: "");
 
 	/* ARP targets: clear and initialize the list */
 	contents = nm_platform_sysctl_master_get_option (nm_device_get_platform (device), ifindex,
@@ -591,7 +591,7 @@ reapply_connection (NMDevice *device, NMConnection *con_old, NMConnection *con_n
 
 	/* Primary */
 	value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
-	set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_PRIMARY, value ? value : "");
+	set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_PRIMARY, value ?: "");
 
 	/* Active slave */
 	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE);
diff --git a/src/devices/nm-device-dummy.c b/src/devices/nm-device-dummy.c
index f8bc8e75..9be4d29f 100644
--- a/src/devices/nm-device-dummy.c
+++ b/src/devices/nm-device-dummy.c
@@ -187,7 +187,6 @@ nm_device_dummy_class_init (NMDeviceDummyClass *klass)
 	device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
 }
 
-
 /*****************************************************************************/
 
 #define NM_TYPE_DUMMY_DEVICE_FACTORY (nm_dummy_device_factory_get_type ())
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index 9b46545b..6c5e33e4 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -1117,7 +1117,6 @@ dcb_state (NMDevice *device, gboolean timeout)
 
 	g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_CONFIG);
 
-
 	carrier = nm_platform_link_is_connected (nm_device_get_platform (device), nm_device_get_ifindex (device));
 	_LOGD (LOGD_DCB, "dcb_state() wait %d carrier %d timeout %d", priv->dcb_wait, carrier, timeout);
 
@@ -1344,7 +1343,7 @@ deactivate (NMDevice *device)
 	nm_clear_g_source (&priv->pppoe_wait_id);
 
 	if (priv->ppp_manager) {
-		nm_ppp_manager_stop_sync (priv->ppp_manager);
+		nm_ppp_manager_stop (priv->ppp_manager, NULL, NULL);
 		g_clear_object (&priv->ppp_manager);
 	}
 
diff --git a/src/devices/nm-device-macsec.c b/src/devices/nm-device-macsec.c
index 895ea34f..4eaf5469 100644
--- a/src/devices/nm-device-macsec.c
+++ b/src/devices/nm-device-macsec.c
@@ -731,7 +731,6 @@ link_changed (NMDevice *device,
 	update_properties (device);
 }
 
-
 static void
 device_state_changed (NMDevice *device,
                       NMDeviceState new_state,
diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c
index b8e748d6..dc4fb3e8 100644
--- a/src/devices/nm-device-macvlan.c
+++ b/src/devices/nm-device-macvlan.c
@@ -389,7 +389,6 @@ update_connection (NMDevice *device, NMConnection *connection)
 	if (priv->props.no_promisc == nm_setting_macvlan_get_promiscuous (s_macvlan))
 		g_object_set (s_macvlan, NM_SETTING_MACVLAN_PROMISCUOUS, !priv->props.no_promisc, NULL);
 
-
 	if (priv->props.tap != nm_setting_macvlan_get_tap (s_macvlan))
 		g_object_set (s_macvlan, NM_SETTING_MACVLAN_TAP, !!priv->props.tap, NULL);
 
diff --git a/src/devices/nm-device-ppp.c b/src/devices/nm-device-ppp.c
index 94df0cae..a6abb228 100644
--- a/src/devices/nm-device-ppp.c
+++ b/src/devices/nm-device-ppp.c
@@ -239,7 +239,7 @@ deactivate (NMDevice *device)
 	NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self);
 
 	if (priv->ppp_manager) {
-		nm_ppp_manager_stop_sync (priv->ppp_manager);
+		nm_ppp_manager_stop (priv->ppp_manager, NULL, NULL);
 		g_clear_object (&priv->ppp_manager);
 	}
 }
diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h
index b0d3ffa4..0b844411 100644
--- a/src/devices/nm-device-private.h
+++ b/src/devices/nm-device-private.h
@@ -43,6 +43,8 @@ enum NMActStageReturn {
 
 #define NM_DEVICE_CAP_INTERNAL_MASK 0xc0000000
 
+void nm_device_arp_announce (NMDevice *self);
+
 NMSettings *nm_device_get_settings (NMDevice *self);
 
 gboolean nm_device_set_ip_ifindex (NMDevice *self, int ifindex);
diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c
index c3ce4b73..3846676c 100644
--- a/src/devices/nm-device-tun.c
+++ b/src/devices/nm-device-tun.c
@@ -480,7 +480,6 @@ nm_device_tun_class_init (NMDeviceTunClass *klass)
 	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 }
 
-
 /*****************************************************************************/
 
 #define NM_TYPE_TUN_DEVICE_FACTORY (nm_tun_device_factory_get_type ())
diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c
index ae6a0f36..a7f4c4bc 100644
--- a/src/devices/nm-device-vlan.c
+++ b/src/devices/nm-device-vlan.c
@@ -110,15 +110,15 @@ parent_hwaddr_maybe_changed (NMDevice *parent,
 	if (nm_device_sys_iface_state_is_external_or_assume (device))
 		return;
 
-	connection = nm_device_get_applied_connection ((NMDevice *) self);
+	connection = nm_device_get_applied_connection (device);
 	if (!connection)
 		return;
 
 	/* Update the VLAN MAC only if configuration does not specify one */
-	if (nm_device_hw_addr_is_explict ((NMDevice *) self))
+	if (nm_device_hw_addr_is_explict (device))
 		return;
 
-	old_mac = nm_device_get_hw_address ((NMDevice *) self);
+	old_mac = nm_device_get_hw_address (device);
 	new_mac = nm_device_get_hw_address (parent);
 	if (nm_streq0 (old_mac, new_mac))
 		return;
@@ -126,13 +126,14 @@ parent_hwaddr_maybe_changed (NMDevice *parent,
 	_LOGD (LOGD_VLAN, "parent hardware address changed to %s%s%s",
 	       NM_PRINT_FMT_QUOTE_STRING (new_mac));
 	if (new_mac) {
-		nm_device_hw_addr_set ((NMDevice *) self, new_mac, "vlan-parent", TRUE);
+		nm_device_hw_addr_set (device, new_mac, "vlan-parent", TRUE);
+		nm_device_arp_announce (device);
 		/* When changing the hw address the interface is taken down,
 		 * removing the IPv6 configuration; reapply it.
 		 */
 		s_ip6 = nm_connection_get_setting_ip6_config (connection);
 		if (s_ip6)
-			nm_device_reactivate_ip6_config (NM_DEVICE (self), s_ip6, s_ip6);
+			nm_device_reactivate_ip6_config (device, s_ip6, s_ip6);
 	}
 }
 
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 815de29a..9a40a0dd 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -1177,8 +1177,9 @@ _get_stable_id (NMDevice *self,
 		uuid = nm_connection_get_uuid (connection);
 
 		stable_type = nm_utils_stable_id_parse (stable_id,
-		                                        uuid,
+		                                        nm_device_get_ip_iface (self),
 		                                        NULL,
+		                                        uuid,
 		                                        &generated);
 
 		/* current_stable_id_type is a bitfield! */
@@ -1357,7 +1358,7 @@ nm_device_get_ip_iface (NMDevice *self)
 
 	priv = NM_DEVICE_GET_PRIVATE (self);
 	/* If it's not set, default to iface */
-	return priv->ip_iface ? priv->ip_iface : priv->iface;
+	return priv->ip_iface ?: priv->iface;
 }
 
 int
@@ -2133,8 +2134,20 @@ get_type_description (NMDevice *self)
 
 	nm_assert (NM_IS_DEVICE (self));
 
+	/* the default implementation for the description just returns the (modified)
+	 * class name and depends entirely on the type of self. Note that we cache the
+	 * description in the klass itself.
+	 *
+	 * Also note, that as the GObject class gets inited, it inherrits the fields
+	 * of the parent class. That means, if NMDeviceVethClass was initialized after
+	 * NMDeviceEthernetClass already has the description cached in the class
+	 * (because we already fetched the description for an ethernet device),
+	 * then default_type_description will wrongly contain "ethernet".
+	 * To avoid that, and catch the situation, also cache the klass for
+	 * which the description was cached. If that doesn't match, it was
+	 * inherited and we need to reset it. */
 	klass = NM_DEVICE_GET_CLASS (self);
-	if (G_UNLIKELY (!klass->default_type_description)) {
+	if (G_UNLIKELY (klass->default_type_description_klass != klass)) {
 		const char *typename;
 		gs_free char *s = NULL;
 
@@ -2143,8 +2156,10 @@ get_type_description (NMDevice *self)
 			typename += 8;
 		s = g_ascii_strdown (typename, -1);
 		klass->default_type_description = g_intern_string (s);
+		klass->default_type_description_klass = klass;
 	}
 
+	nm_assert (klass->default_type_description);
 	return klass->default_type_description;
 }
 
@@ -2220,6 +2235,7 @@ nm_device_get_physical_port_id (NMDevice *self)
 
 typedef enum {
 	CONCHECK_SCHEDULE_UPDATE_INTERVAL,
+	CONCHECK_SCHEDULE_UPDATE_INTERVAL_RESTART,
 	CONCHECK_SCHEDULE_CHECK_EXTERNAL,
 	CONCHECK_SCHEDULE_CHECK_PERIODIC,
 	CONCHECK_SCHEDULE_RETURNED_MIN,
@@ -2263,10 +2279,11 @@ concheck_is_possible (NMDevice *self)
 }
 
 static gboolean
-concheck_periodic_schedule_do (NMDevice *self, gint64 interval_ns)
+concheck_periodic_schedule_do (NMDevice *self, gint64 now_ns)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 	gboolean periodic_check_disabled = FALSE;
+	gint64 expiry, tdiff;
 
 	/* we always cancel whatever was pending. */
 	if (nm_clear_g_source (&priv->concheck_p_cur_id))
@@ -2277,18 +2294,25 @@ concheck_periodic_schedule_do (NMDevice *self, gint64 interval_ns)
 		goto out;
 	}
 
-	nm_assert (interval_ns >= 0);
-
 	if (!concheck_is_possible (self))
 		goto out;
 
-	_LOGT (LOGD_CONCHECK, "connectivity: periodic-check: %sscheduled in %u milliseconds (%u seconds interval)",
+	nm_assert (now_ns > 0);
+	nm_assert (priv->concheck_p_cur_interval > 0);
+
+	/* we schedule the timeout based on our current settings cur-interval and cur-basetime.
+	 * Before calling concheck_periodic_schedule_do(), make sure that these properties are
+	 * correct. */
+
+	expiry = priv->concheck_p_cur_basetime_ns + (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND);
+	tdiff = expiry - now_ns;
+
+	_LOGT (LOGD_CONCHECK, "connectivity: periodic-check: %sscheduled in %lld milliseconds (%u seconds interval)",
 	       periodic_check_disabled ? "re-" : "",
-	       (guint) (interval_ns / NM_UTILS_NS_PER_MSEC),
+	       (long long) (tdiff / NM_UTILS_NS_PER_MSEC),
 	       priv->concheck_p_cur_interval);
 
-	nm_assert (priv->concheck_p_cur_interval > 0);
-	priv->concheck_p_cur_id = g_timeout_add (interval_ns / NM_UTILS_NS_PER_MSEC,
+	priv->concheck_p_cur_id = g_timeout_add (NM_MAX ((gint64) 0, tdiff) / NM_UTILS_NS_PER_MSEC,
 	                                         concheck_periodic_timeout_cb,
 	                                         self);
 	return TRUE;
@@ -2316,18 +2340,23 @@ concheck_periodic_schedule_set (NMDevice *self,
 	if (!priv->concheck_p_cur_id) {
 		/* we currently don't have a timeout scheduled. No need to reschedule
 		 * another one... */
-		if (mode == CONCHECK_SCHEDULE_UPDATE_INTERVAL) {
-			/* ... unless, we are initalizing. In this case, setup the current current
-			 * interval and schedule a perform a check right away.  */
-			priv->concheck_p_cur_interval = NM_MIN (priv->concheck_p_max_interval, CONCHECK_P_PROBE_INTERVAL);
-			priv->concheck_p_cur_basetime_ns = nm_utils_get_monotonic_timestamp_ns_cached (&now_ns);
-			if (concheck_periodic_schedule_do (self, priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND))
-				concheck_start (self, NULL, NULL, TRUE);
-		}
-		return;
+		if (NM_IN_SET (mode, CONCHECK_SCHEDULE_UPDATE_INTERVAL,
+		                     CONCHECK_SCHEDULE_UPDATE_INTERVAL_RESTART)) {
+			/* ... unless, we are about to start periodic checks after update-interval.
+			 * In this case, fall through and restart the periodic checks below. */
+			mode = CONCHECK_SCHEDULE_UPDATE_INTERVAL_RESTART;
+		} else
+			return;
 	}
 
 	switch (mode) {
+	case CONCHECK_SCHEDULE_UPDATE_INTERVAL_RESTART:
+		priv->concheck_p_cur_interval = NM_MIN (priv->concheck_p_max_interval, CONCHECK_P_PROBE_INTERVAL);
+		priv->concheck_p_cur_basetime_ns = nm_utils_get_monotonic_timestamp_ns_cached (&now_ns);
+		if (concheck_periodic_schedule_do (self, now_ns))
+			concheck_start (self, NULL, NULL, TRUE);
+		return;
+
 	case CONCHECK_SCHEDULE_UPDATE_INTERVAL:
 		/* called with "UPDATE_INTERVAL" and already have a concheck_p_cur_id scheduled. */
 
@@ -2352,7 +2381,7 @@ concheck_periodic_schedule_set (NMDevice *self,
 			 * new max_interval passed. We need to start a check right away (and
 			 * schedule a timeout in cur-interval in the future). */
 			priv->concheck_p_cur_basetime_ns = now_ns;
-			if (concheck_periodic_schedule_do (self, priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND))
+			if (concheck_periodic_schedule_do (self, now_ns))
 				concheck_start (self, NULL, NULL, TRUE);
 		} else {
 			/* we are reducing the max-interval to a shorter interval that we have currently
@@ -2361,14 +2390,14 @@ concheck_periodic_schedule_set (NMDevice *self,
 			 * However, since the last time we scheduled the check, not even the new max-interval
 			 * expired. All we need to do, is reschedule the timer to expire sooner. The cur_basetime
 			 * is unchanged. */
-			concheck_periodic_schedule_do (self, cur_expiry - now_ns);
+			concheck_periodic_schedule_do (self, now_ns);
 		}
 		return;
 
 	case CONCHECK_SCHEDULE_CHECK_EXTERNAL:
 		/* a external connectivity check delays our periodic check. We reset the counter. */
 		priv->concheck_p_cur_basetime_ns = nm_utils_get_monotonic_timestamp_ns_cached (&now_ns);
-		concheck_periodic_schedule_do (self, priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND);
+		concheck_periodic_schedule_do (self, now_ns);
 		return;
 
 	case CONCHECK_SCHEDULE_CHECK_PERIODIC:
@@ -2401,15 +2430,16 @@ concheck_periodic_schedule_set (NMDevice *self,
 		new_expiry = exp_expiry + (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND);
 		tdiff = NM_MAX (new_expiry - now_ns, 0);
 		priv->concheck_p_cur_basetime_ns = (now_ns + tdiff) - (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND);
-		concheck_periodic_schedule_do (self, tdiff);
-		handle = concheck_start (self, NULL, NULL, TRUE);
-		if (old_interval != priv->concheck_p_cur_interval) {
-			/* we just bumped the interval already when scheduling this check.
-			 * When the handle returns, don't bump a second time.
-			 *
-			 * But if we reach the timeout again before the handle returns (this
-			 * code here) we will still bump the interval. */
-			handle->is_periodic_bump_on_complete = FALSE;
+		if (concheck_periodic_schedule_do (self, now_ns)) {
+			handle = concheck_start (self, NULL, NULL, TRUE);
+			if (old_interval != priv->concheck_p_cur_interval) {
+				/* we just bumped the interval already when scheduling this check.
+				 * When the handle returns, don't bump a second time.
+				 *
+				 * But if we reach the timeout again before the handle returns (this
+				 * code here) we will still bump the interval. */
+				handle->is_periodic_bump_on_complete = FALSE;
+			}
 		}
 		return;
 	}
@@ -2436,11 +2466,11 @@ concheck_periodic_schedule_set (NMDevice *self,
 	new_expiry = priv->concheck_p_cur_basetime_ns + (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND);
 	tdiff = NM_MAX (new_expiry - nm_utils_get_monotonic_timestamp_ns_cached (&now_ns), 0);
 	priv->concheck_p_cur_basetime_ns = now_ns + tdiff - (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND);
-	concheck_periodic_schedule_do (self, tdiff);
+	concheck_periodic_schedule_do (self, now_ns);
 }
 
-void
-nm_device_check_connectivity_update_interval (NMDevice *self)
+static void
+concheck_update_interval (NMDevice *self, gboolean check_now)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 	guint new_interval;
@@ -2455,7 +2485,8 @@ nm_device_check_connectivity_update_interval (NMDevice *self)
 	}
 
 	if (!new_interval) {
-		/* this will cancel any potentially pending timeout. */
+		/* this will cancel any potentially pending timeout because max-interval is zero.
+		 * But it logs a nice message... */
 		concheck_periodic_schedule_do (self, 0);
 
 		/* also update the fake connectivity state. */
@@ -2463,7 +2494,16 @@ nm_device_check_connectivity_update_interval (NMDevice *self)
 		return;
 	}
 
-	concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_UPDATE_INTERVAL);
+	concheck_periodic_schedule_set (self,
+	                                check_now
+	                                  ? CONCHECK_SCHEDULE_UPDATE_INTERVAL_RESTART
+	                                  : CONCHECK_SCHEDULE_UPDATE_INTERVAL);
+}
+
+void
+nm_device_check_connectivity_update_interval (NMDevice *self)
+{
+	concheck_update_interval (self, FALSE);
 }
 
 static void
@@ -3054,12 +3094,12 @@ carrier_changed (NMDevice *self, gboolean carrier)
 			* is restored. */
 			if (priv->state == NM_DEVICE_STATE_ACTIVATED)
 				nm_device_update_dynamic_ip_setup (self);
-			else {
-				if (nm_device_activate_ip4_state_in_wait (self))
-					nm_device_activate_stage3_ip4_start (self);
-				if (nm_device_activate_ip6_state_in_wait (self))
-					nm_device_activate_stage3_ip6_start (self);
-			}
+			/* If needed, also resume IP configuration that is
+			 * waiting for carrier. */
+			if (nm_device_activate_ip4_state_in_wait (self))
+				nm_device_activate_stage3_ip4_start (self);
+			if (nm_device_activate_ip6_state_in_wait (self))
+				nm_device_activate_stage3_ip6_start (self);
 			return;
 		}
 		/* fall-through and change state of device */
@@ -4179,7 +4219,6 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
 	g_return_val_if_fail (priv->iface != NULL, FALSE);
 	g_return_val_if_fail (priv->real, FALSE);
 
-
 	ifindex = nm_device_get_ifindex (self);
 
 	_LOGD (LOGD_DEVICE, "unrealize (ifindex %d)", ifindex > 0 ? ifindex : 0);
@@ -5829,7 +5868,6 @@ activate_stage1_device_prepare (NMDevice *self)
 	nm_device_activate_schedule_stage2_device_config (self);
 }
 
-
 /*
  * nm_device_activate_schedule_stage1_device_prepare
  *
@@ -6031,7 +6069,6 @@ activate_stage2_device_config (NMDevice *self)
 	nm_device_activate_schedule_stage3_ip_config_start (self);
 }
 
-
 /*
  * nm_device_activate_schedule_stage2_device_config
  *
@@ -7036,6 +7073,8 @@ dhcp4_get_client_id (NMDevice *self, NMConnection *connection)
 		guint8 buf[20];
 		gsize buf_size;
 		guint32 salted_header;
+		const guint8 *secret_key;
+		gsize secret_key_len;
 
 		stable_id = _get_stable_id (self, connection, &stable_type);
 		if (!stable_id)
@@ -7043,10 +7082,13 @@ dhcp4_get_client_id (NMDevice *self, NMConnection *connection)
 
 		salted_header = htonl (2011610591 + stable_type);
 
+		nm_utils_secret_key_get (&secret_key, &secret_key_len);
+
 		sum = g_checksum_new (G_CHECKSUM_SHA1);
 
 		g_checksum_update (sum, (const guchar *) &salted_header, sizeof (salted_header));
-		g_checksum_update (sum, (const guchar *) stable_id, strlen (stable_id));
+		g_checksum_update (sum, (const guchar *) stable_id, strlen (stable_id) + 1);
+		g_checksum_update (sum, (const guchar *) secret_key, secret_key_len);
 
 		buf_size = sizeof (buf);
 		g_checksum_get_digest (sum, buf, &buf_size);
@@ -9325,8 +9367,8 @@ arp_cleanup (NMDevice *self)
 	}
 }
 
-static void
-arp_announce (NMDevice *self)
+void
+nm_device_arp_announce (NMDevice *self)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 	NMConnection *connection;
@@ -9425,8 +9467,7 @@ activate_stage5_ip4_config_result (NMDevice *self)
 		                           NULL, NULL, NULL);
 	}
 
-	arp_announce (self);
-
+	nm_device_arp_announce (self);
 	nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP4, FALSE);
 
 	/* Enter the IP_CHECK state if this is the first method to complete */
@@ -10800,23 +10841,37 @@ _carrier_wait_check_act_request_must_queue (NMDevice *self, NMActRequest *req)
 }
 
 void
-nm_device_steal_connection (NMDevice *self, NMSettingsConnection *connection)
+nm_device_disconnect_active_connection (NMActiveConnection *active)
 {
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+	NMDevice *self;
+	NMDevicePrivate *priv;
 
-	_LOGI (LOGD_DEVICE, "disconnecting connection '%s' for new activation request",
-	       nm_settings_connection_get_id (connection));
+	g_return_if_fail (NM_IS_ACTIVE_CONNECTION (active));
 
-	if (   priv->queued_act_request
-	    && connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->queued_act_request)))
-		_clear_queued_act_request (priv);
+	self = nm_active_connection_get_device (active);
 
-	if (   priv->act_request.obj
-	    && connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->act_request.obj))
-	    && priv->state < NM_DEVICE_STATE_DEACTIVATING) {
-		nm_device_state_changed (self,
-		                         NM_DEVICE_STATE_DEACTIVATING,
-		                         NM_DEVICE_STATE_REASON_NEW_ACTIVATION);
+	if (!self) {
+		/* hm, no device? Just fail the active connection. */
+		nm_active_connection_set_state_fail (active,
+		                                     NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN,
+		                                     NULL);
+		return;
+	}
+
+	priv = NM_DEVICE_GET_PRIVATE (self);
+
+	if (NM_ACTIVE_CONNECTION (priv->queued_act_request) == active) {
+		_clear_queued_act_request (priv);
+		return;
+	}
+	if (NM_ACTIVE_CONNECTION (priv->act_request.obj) == active) {
+		if (priv->state < NM_DEVICE_STATE_DEACTIVATING) {
+			nm_device_state_changed (self,
+			                         NM_DEVICE_STATE_DEACTIVATING,
+			                         NM_DEVICE_STATE_REASON_NEW_ACTIVATION);
+		} else {
+			/* it's going down already... */
+		}
 	}
 }
 
@@ -10931,7 +10986,6 @@ nm_device_get_ip4_config (NMDevice *self)
 	return NM_DEVICE_GET_PRIVATE (self)->ip_config_4;
 }
 
-
 static gboolean
 nm_device_set_ip_config (NMDevice *self,
                          int addr_family,
@@ -13887,7 +13941,8 @@ _set_state_full (NMDevice *self,
 	if (ip_config_valid (old_state) && !ip_config_valid (state))
 	    notify_ip_properties (self);
 
-	nm_device_check_connectivity_update_interval (self);
+	concheck_update_interval (self,
+	                          state == NM_DEVICE_STATE_ACTIVATED);
 
 	/* Dispose of the cached activation request */
 	if (req)
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index 66720f01..0d4d5cf8 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -73,7 +73,6 @@ nm_device_state_reason_check (NMDeviceStateReason reason)
 #define NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "queued-state-change-"
 #define NM_PENDING_ACTIONPREFIX_ACTIVATION          "activation-"
 
-
 /* Properties */
 #define NM_DEVICE_UDI              "udi"
 #define NM_DEVICE_IFACE            "interface"
@@ -189,9 +188,10 @@ typedef enum { /*< skip >*/
 	NM_DEVICE_CHECK_DEV_AVAILABLE_ALL                                   = (1L << 1) - 1,
 } NMDeviceCheckDevAvailableFlags;
 
-typedef struct {
+typedef struct _NMDeviceClass {
 	NMDBusObjectClass parent;
 
+	struct _NMDeviceClass *default_type_description_klass;
 	const char *default_type_description;
 
 	const char *connection_type;
@@ -717,7 +717,7 @@ void nm_device_queue_state   (NMDevice *self,
 
 gboolean nm_device_get_firmware_missing (NMDevice *self);
 
-void nm_device_steal_connection (NMDevice *device, NMSettingsConnection *connection);
+void nm_device_disconnect_active_connection (NMActiveConnection *active);
 
 void nm_device_queue_activation (NMDevice *device, NMActRequest *req);
 
diff --git a/src/devices/ovs/meson.build b/src/devices/ovs/meson.build
index 7b1c4617..f4edd57c 100644
--- a/src/devices/ovs/meson.build
+++ b/src/devices/ovs/meson.build
@@ -19,7 +19,7 @@ libnm_device_plugin_ovs = shared_module(
   link_args: ldflags_linker_script_devices,
   link_depends: linker_script_devices,
   install: true,
-  install_dir: nm_pkglibdir
+  install_dir: nm_plugindir
 )
 
 core_plugins += libnm_device_plugin_ovs
diff --git a/src/devices/ovs/nm-device-ovs-port.c b/src/devices/ovs/nm-device-ovs-port.c
index 3f1fe974..91cf4f4d 100644
--- a/src/devices/ovs/nm-device-ovs-port.c
+++ b/src/devices/ovs/nm-device-ovs-port.c
@@ -70,7 +70,6 @@ get_generic_capabilities (NMDevice *device)
 	return NM_DEVICE_CAP_IS_SOFTWARE;
 }
 
-
 static gboolean
 check_connection_compatible (NMDevice *device, NMConnection *connection)
 {
diff --git a/src/devices/ovs/nm-ovsdb.c b/src/devices/ovs/nm-ovsdb.c
index b8f5a935..a9cb5703 100644
--- a/src/devices/ovs/nm-ovsdb.c
+++ b/src/devices/ovs/nm-ovsdb.c
@@ -363,7 +363,7 @@ _insert_interface (json_t *params, NMConnection *interface)
 		json_pack ("{s:s, s:s, s:{s:s, s:s, s:o, s:[s, [[s, s]]]}, s:s}",
 		           "op", "insert", "table", "Interface", "row",
 		           "name", nm_connection_get_interface_name (interface),
-		           "type", type ? type : "",
+		           "type", type ?: "",
 		           "options", options,
 		           "external_ids", "map", "NM.connection.uuid", nm_connection_get_uuid (interface),
 		           "uuid-name", "rowInterface"));
@@ -891,7 +891,7 @@ ovsdb_got_update (NMOvsdb *self, json_t *msg)
 				_LOGT ("removed an '%s' interface: %s%s%s",
 				       ovs_interface->type, ovs_interface->name,
 				       ovs_interface->connection_uuid ? ", " : "",
-				       ovs_interface->connection_uuid ? ovs_interface->connection_uuid : "");
+				       ovs_interface->connection_uuid ?: "");
 				if (g_strcmp0 (ovs_interface->type, "internal") == 0) {
 					/* Currently the factory only creates NMDevices for
 					 * internal interfaces. Ignore the rest. */
@@ -910,14 +910,14 @@ ovsdb_got_update (NMOvsdb *self, json_t *msg)
 			if (old) {
 				_LOGT ("changed an '%s' interface: %s%s%s", type, ovs_interface->name,
 				       ovs_interface->connection_uuid ? ", " : "",
-				       ovs_interface->connection_uuid ? ovs_interface->connection_uuid : "");
+				       ovs_interface->connection_uuid ?: "");
 				g_signal_emit (self, signals[DEVICE_CHANGED], 0,
 				               "ovs-interface", ovs_interface->name);
 			} else {
 				_LOGT ("added an '%s' interface: %s%s%s",
 				       ovs_interface->type, ovs_interface->name,
 				       ovs_interface->connection_uuid ? ", " : "",
-				       ovs_interface->connection_uuid ? ovs_interface->connection_uuid : "");
+				       ovs_interface->connection_uuid ?: "");
 				if (g_strcmp0 (ovs_interface->type, "internal") == 0) {
 					/* Currently the factory only creates NMDevices for
 					 * internal interfaces. Ignore the rest. */
@@ -949,7 +949,7 @@ ovsdb_got_update (NMOvsdb *self, json_t *msg)
 				old = FALSE;
 				_LOGT ("removed a port: %s%s%s", ovs_port->name,
 				       ovs_port->connection_uuid ? ", " : "",
-				       ovs_port->connection_uuid ? ovs_port->connection_uuid : "");
+				       ovs_port->connection_uuid ?: "");
 				g_signal_emit (self, signals[DEVICE_REMOVED], 0,
 				               ovs_port->name, NM_DEVICE_TYPE_OVS_PORT);
 			}
@@ -965,13 +965,13 @@ ovsdb_got_update (NMOvsdb *self, json_t *msg)
 			if (old) {
 				_LOGT ("changed a port: %s%s%s", ovs_port->name,
 				       ovs_port->connection_uuid ? ", " : "",
-				       ovs_port->connection_uuid ? ovs_port->connection_uuid : "");
+				       ovs_port->connection_uuid ?: "");
 				g_signal_emit (self, signals[DEVICE_CHANGED], 0,
 				               NM_SETTING_OVS_PORT_SETTING_NAME, ovs_port->name);
 			} else {
 				_LOGT ("added a port: %s%s%s", ovs_port->name,
 				       ovs_port->connection_uuid ? ", " : "",
-				       ovs_port->connection_uuid ? ovs_port->connection_uuid : "");
+				       ovs_port->connection_uuid ?: "");
 				g_signal_emit (self, signals[DEVICE_ADDED], 0,
 				               ovs_port->name, NM_DEVICE_TYPE_OVS_PORT);
 			}
@@ -999,7 +999,7 @@ ovsdb_got_update (NMOvsdb *self, json_t *msg)
 				old = FALSE;
 				_LOGT ("removed a bridge: %s%s%s", ovs_bridge->name,
 				       ovs_bridge->connection_uuid ? ", " : "",
-				       ovs_bridge->connection_uuid ? ovs_bridge->connection_uuid : "");
+				       ovs_bridge->connection_uuid ?: "");
 				g_signal_emit (self, signals[DEVICE_REMOVED], 0,
 				               ovs_bridge->name, NM_DEVICE_TYPE_OVS_BRIDGE);
 			}
@@ -1015,13 +1015,13 @@ ovsdb_got_update (NMOvsdb *self, json_t *msg)
 			if (old) {
 				_LOGT ("changed a bridge: %s%s%s", ovs_bridge->name,
 				       ovs_bridge->connection_uuid ? ", " : "",
-				       ovs_bridge->connection_uuid ? ovs_bridge->connection_uuid : "");
+				       ovs_bridge->connection_uuid ?: "");
 				g_signal_emit (self, signals[DEVICE_CHANGED], 0,
 				               NM_SETTING_OVS_BRIDGE_SETTING_NAME, ovs_bridge->name);
 			} else {
 				_LOGT ("added a bridge: %s%s%s", ovs_bridge->name,
 				       ovs_bridge->connection_uuid ? ", " : "",
-				       ovs_bridge->connection_uuid ? ovs_bridge->connection_uuid : "");
+				       ovs_bridge->connection_uuid ?: "");
 				g_signal_emit (self, signals[DEVICE_ADDED], 0,
 				               ovs_bridge->name, NM_DEVICE_TYPE_OVS_BRIDGE);
 			}
@@ -1153,7 +1153,6 @@ ovsdb_got_msg (NMOvsdb *self, json_t *msg)
 		return;
 	}
 
-
 	/* This is a message we are not interested in. */
 	_LOGW ("got an unknown message, ignoring");
 }
diff --git a/src/devices/team/meson.build b/src/devices/team/meson.build
index 4a533bc5..159c182a 100644
--- a/src/devices/team/meson.build
+++ b/src/devices/team/meson.build
@@ -16,7 +16,7 @@ libnm_device_plugin_team = shared_module(
   link_args: ldflags_linker_script_devices,
   link_depends: linker_script_devices,
   install: true,
-  install_dir: nm_pkglibdir
+  install_dir: nm_plugindir
 )
 
 core_plugins += libnm_device_plugin_team
diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c
index 5d0625f8..c2ac8e19 100644
--- a/src/devices/tests/test-lldp.c
+++ b/src/devices/tests/test-lldp.c
@@ -169,7 +169,6 @@ _test_recv_data0_check (GMainLoop *loop, NMLldpListener *listener)
 TEST_RECV_DATA_DEFINE (_test_recv_data0,       1, _test_recv_data0_check,  &_test_recv_data0_frame0);
 TEST_RECV_DATA_DEFINE (_test_recv_data0_twice, 1, _test_recv_data0_check,  &_test_recv_data0_frame0, &_test_recv_data0_frame0);
 
-
 TEST_RECV_FRAME_DEFINE (_test_recv_data1_frame0,
 	/* lldp.detailed.pcap from
 	 * https://wiki.wireshark.org/SampleCaptures#Link_Layer_Discovery_Protocol_.28LLDP.29 */
diff --git a/src/devices/wifi/meson.build b/src/devices/wifi/meson.build
index 27eaeea6..a27f8e6a 100644
--- a/src/devices/wifi/meson.build
+++ b/src/devices/wifi/meson.build
@@ -28,7 +28,7 @@ libnm_device_plugin_wifi = shared_module(
   link_args: ldflags_linker_script_devices,
   link_depends: linker_script_devices,
   install: true,
-  install_dir: nm_pkglibdir
+  install_dir: nm_plugindir
 )
 
 core_plugins += libnm_device_plugin_wifi
diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c
index eeff5bd3..d3c5ae9a 100644
--- a/src/devices/wifi/nm-device-iwd.c
+++ b/src/devices/wifi/nm-device-iwd.c
@@ -236,7 +236,7 @@ get_ordered_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data)
 	GVariantIter *networks;
 	const gchar *path, *name, *type;
 	int16_t signal;
-	NMWifiAP *ap, *ap_safe;
+	NMWifiAP *ap, *ap_safe, *new_ap;
 	gboolean changed = FALSE;
 	GHashTableIter ap_iter;
 	gs_unref_hashtable GHashTable *new_aps = NULL;
@@ -309,10 +309,10 @@ get_ordered_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data)
 
 	c_list_for_each_entry_safe (ap, ap_safe, &priv->aps_lst_head, aps_lst) {
 
-		ap = g_hash_table_lookup (new_aps,
-		                          nm_wifi_ap_get_supplicant_path (ap));
-		if (ap) {
-			if (nm_wifi_ap_set_strength (ap, nm_wifi_ap_get_strength (ap))) {
+		new_ap = g_hash_table_lookup (new_aps,
+		                              nm_wifi_ap_get_supplicant_path (ap));
+		if (new_ap) {
+			if (nm_wifi_ap_set_strength (ap, nm_wifi_ap_get_strength (new_ap))) {
 				_ap_dump (self, LOGL_TRACE, ap, "updated", 0);
 				changed = TRUE;
 			}
diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c
index cd2c68af..fd7bf3f7 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.c
+++ b/src/devices/wifi/nm-device-olpc-mesh.c
@@ -177,7 +177,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 		       nm_device_get_iface (priv->companion));
 	}
 
-
 	/* wait with continuing configuration untill the companion device is done scanning */
 	g_object_get (priv->companion, NM_DEVICE_WIFI_SCANNING, &scanning, NULL);
 	if (scanning) {
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index de4af42c..90f94557 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -2147,9 +2147,9 @@ supplicant_iface_notify_current_bss (NMSupplicantInterface *iface,
 		}
 
 		_LOGD (LOGD_WIFI, "roamed from BSSID %s (%s) to %s (%s)",
-		       old_bssid ? old_bssid : "(none)",
+		       old_bssid ?: "(none)",
 		       old_ssid ? nm_utils_escape_ssid (old_ssid->data, old_ssid->len) : "(none)",
-		       new_bssid ? new_bssid : "(none)",
+		       new_bssid ?: "(none)",
 		       new_ssid ? nm_utils_escape_ssid (new_ssid->data, new_ssid->len) : "(none)");
 
 		set_current_ap (self, new_ap, TRUE);
@@ -2833,7 +2833,6 @@ handle_ip_config_timeout (NMDeviceWifi *self,
 	return ret;
 }
 
-
 static NMActStageReturn
 act_stage4_ip4_config_timeout (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 {
diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c
index 450009f0..39db3a04 100644
--- a/src/devices/wifi/nm-iwd-manager.c
+++ b/src/devices/wifi/nm-iwd-manager.c
@@ -157,7 +157,6 @@ return_error:
 	                                               "No PSK available for this connection");
 }
 
-
 static guint
 psk_agent_export (GDBusConnection *connection, gpointer user_data,
                   gchar **agent_path, GError **error)
diff --git a/src/devices/wifi/nm-wifi-common.c b/src/devices/wifi/nm-wifi-common.c
index 47c0ce67..e5e16f03 100644
--- a/src/devices/wifi/nm-wifi-common.c
+++ b/src/devices/wifi/nm-wifi-common.c
@@ -69,6 +69,7 @@ _dispatch_request_scan (NMDevice *device,
 		_nm_device_iwd_request_scan (NM_DEVICE_IWD (device),
 		                             options,
 		                             invocation);
+		return;
 	}
 #endif
 	_nm_device_wifi_request_scan (NM_DEVICE_WIFI (device),
diff --git a/src/devices/wwan/meson.build b/src/devices/wwan/meson.build
index 032b3585..abf58594 100644
--- a/src/devices/wwan/meson.build
+++ b/src/devices/wwan/meson.build
@@ -25,7 +25,7 @@ libnm_wwan = shared_module(
   ],
   link_depends: linker_script,
   install: true,
-  install_dir: nm_pkglibdir
+  install_dir: nm_plugindir
 )
 
 libnm_wwan_dep = declare_dependency(
@@ -54,7 +54,7 @@ libnm_device_plugin_wwan = shared_module(
   link_args: ldflags_linker_script_devices,
   link_depends: linker_script_devices,
   install: true,
-  install_dir: nm_pkglibdir
+  install_dir: nm_plugindir
 )
 
 core_plugins += libnm_device_plugin_wwan
diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c
index 9a3744db..e5678b96 100644
--- a/src/devices/wwan/nm-modem-broadband.c
+++ b/src/devices/wwan/nm-modem-broadband.c
@@ -286,7 +286,7 @@ create_gsm_connect_properties (NMConnection *connection)
 
 	/* Blank APN ("") means the default subscription APN */
 	str = nm_setting_gsm_get_apn (setting);
-	mm_simple_connect_properties_set_apn (properties, str ? str : "");
+	mm_simple_connect_properties_set_apn (properties, str ?: "");
 
 	str = nm_setting_gsm_get_network_id (setting);
 	if (str)
@@ -924,7 +924,6 @@ static_stage3_ip4_done (NMModemBroadband *self)
 
 	_LOGI ("  address %s/%d", address_string, address.plen);
 
-
 	nm_modem_get_route_parameters (NM_MODEM (self),
 	                               &ip4_route_table,
 	                               &ip4_route_metric,
@@ -1283,7 +1282,6 @@ get_sim_ready (MMModem *modem,
 	GError *error = NULL;
 	MMSim *new_sim;
 
-
 	new_sim = mm_modem_get_sim_finish (modem, res, &error);
 	if (new_sim != self->_priv.sim_iface) {
 		g_clear_object (&self->_priv.sim_iface);
diff --git a/src/devices/wwan/nm-modem-ofono.c b/src/devices/wwan/nm-modem-ofono.c
index a1c6aef2..8b81ac41 100644
--- a/src/devices/wwan/nm-modem-ofono.c
+++ b/src/devices/wwan/nm-modem-ofono.c
@@ -278,7 +278,6 @@ deactivate_cleanup (NMModem *modem, NMDevice *device)
 	NM_MODEM_CLASS (nm_modem_ofono_parent_class)->deactivate_cleanup (modem, device);
 }
 
-
 static gboolean
 check_connection_compatible (NMModem *modem,
                              NMConnection *connection)
diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c
index 61b7247e..fbe99cc3 100644
--- a/src/devices/wwan/nm-modem.c
+++ b/src/devices/wwan/nm-modem.c
@@ -205,7 +205,7 @@ nm_modem_set_state (NMModem *self,
 		_LOGI ("modem state changed, '%s' --> '%s' (reason: %s)",
 		       nm_modem_state_to_string (old_state),
 		       nm_modem_state_to_string (new_state),
-		       reason ? reason : "none");
+		       reason ?: "none");
 
 		priv->state = new_state;
 		_notify (self, PROP_STATE);
@@ -1131,6 +1131,7 @@ deactivate_cleanup (NMModem *self, NMDevice *device)
 
 	if (priv->ppp_manager) {
 		g_signal_handlers_disconnect_by_data (priv->ppp_manager, self);
+		nm_ppp_manager_stop (priv->ppp_manager, NULL, NULL);
 		g_clear_object (&priv->ppp_manager);
 	}
 
@@ -1176,11 +1177,19 @@ typedef struct {
 	GSimpleAsyncResult *result;
 	DeactivateContextStep step;
 	NMPPPManager *ppp_manager;
+	NMPPPManagerStopHandle *ppp_stop_handle;
+	gulong ppp_stop_cancellable_id;
 } DeactivateContext;
 
 static void
 deactivate_context_complete (DeactivateContext *ctx)
 {
+	if (ctx->ppp_stop_handle)
+		nm_ppp_manager_stop_cancel (ctx->ppp_stop_handle);
+
+	nm_assert (!ctx->ppp_stop_handle);
+	nm_assert (ctx->ppp_stop_cancellable_id == 0);
+
 	if (ctx->ppp_manager)
 		g_object_unref (ctx->ppp_manager);
 	if (ctx->cancellable)
@@ -1222,26 +1231,37 @@ disconnect_ready (NMModem *self,
 
 static void
 ppp_manager_stop_ready (NMPPPManager *ppp_manager,
-                        GAsyncResult *res,
-                        DeactivateContext *ctx)
+                        NMPPPManagerStopHandle *handle,
+                        gboolean was_cancelled,
+                        gpointer user_data)
 {
-	NMModem *self = ctx->self;
-	GError *error = NULL;
+	DeactivateContext *ctx = user_data;
 
-	if (!nm_ppp_manager_stop_finish (ppp_manager, res, &error)) {
-		_LOGW ("cannot stop PPP manager: %s",
-		       error->message);
-		g_simple_async_result_take_error (ctx->result, error);
-		deactivate_context_complete (ctx);
-		return;
+	nm_assert (ctx->ppp_stop_handle == handle);
+	ctx->ppp_stop_handle = NULL;
+
+	if (ctx->ppp_stop_cancellable_id) {
+		g_cancellable_disconnect (ctx->cancellable,
+		                          nm_steal_int (&ctx->ppp_stop_cancellable_id));
 	}
 
-	/* Go on */
+	if (was_cancelled)
+		return;
+
 	ctx->step++;
 	deactivate_step (ctx);
 }
 
 static void
+ppp_manager_stop_cancelled (GCancellable *cancellable,
+                            gpointer user_data)
+{
+	DeactivateContext *ctx = user_data;
+
+	nm_ppp_manager_stop_cancel (ctx->ppp_stop_handle);
+}
+
+static void
 deactivate_step (DeactivateContext *ctx)
 {
 	NMModem *self = ctx->self;
@@ -1270,10 +1290,16 @@ deactivate_step (DeactivateContext *ctx)
 	case DEACTIVATE_CONTEXT_STEP_PPP_MANAGER_STOP:
 		/* If we have a PPP manager, stop it */
 		if (ctx->ppp_manager) {
-			nm_ppp_manager_stop_async (ctx->ppp_manager,
-			                           ctx->cancellable,
-			                           (GAsyncReadyCallback) ppp_manager_stop_ready,
-			                           ctx);
+			nm_assert (!ctx->ppp_stop_handle);
+			if (ctx->cancellable) {
+				ctx->ppp_stop_cancellable_id = g_cancellable_connect (ctx->cancellable,
+				                                                      G_CALLBACK (ppp_manager_stop_cancelled),
+				                                                      ctx,
+				                                                      NULL);
+			}
+			ctx->ppp_stop_handle = nm_ppp_manager_stop (ctx->ppp_manager,
+			                                            ppp_manager_stop_ready,
+			                                            ctx);
 			return;
 		}
 		ctx->step++;
@@ -1312,7 +1338,9 @@ nm_modem_deactivate_async (NMModem *self,
 	                                         callback,
 	                                         user_data,
 	                                         nm_modem_deactivate_async);
-	ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+	/* FIXME(shutdown): we always require a cancellable, otherwise we cannot
+	 * do a coordinated shutdown. */
+	ctx->cancellable = nm_g_object_ref (cancellable);
 
 	/* Start */
 	ctx->step = DEACTIVATE_CONTEXT_STEP_FIRST;
diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/devices/wwan/nm-wwan-factory.c
index f0aae040..a561b58a 100644
--- a/src/devices/wwan/nm-wwan-factory.c
+++ b/src/devices/wwan/nm-wwan-factory.c
@@ -105,7 +105,6 @@ modem_added_cb (NMModemManager *manager,
 	g_object_unref (device);
 }
 
-
 static NMDevice *
 create_device (NMDeviceFactory *factory,
                const char *iface,