diff options
author | Dan Winship <danw@gnome.org> | 2013-06-06 12:43:57 -0300 |
---|---|---|
committer | Dan Winship <danw@gnome.org> | 2013-06-27 14:17:42 -0400 |
commit | 004c5c3df5634af7bdfd9f8ef8d32c34b4340166 (patch) | |
tree | 5d410a2de84030541a86b54874fb0037209e8764 | |
parent | 0d873dc4f563228558b59667c97e1017ccd7ecce (diff) | |
download | NetworkManager-danw/live-reconfig.tar.gz |
live-reconfig [wip]danw/live-reconfig
-rw-r--r-- | src/devices/nm-device-bridge.c | 64 | ||||
-rw-r--r-- | src/devices/nm-device-bt.c | 14 | ||||
-rw-r--r-- | src/devices/nm-device-ethernet.c | 40 | ||||
-rw-r--r-- | src/devices/nm-device-infiniband.c | 82 | ||||
-rw-r--r-- | src/devices/nm-device-vlan.c | 46 | ||||
-rw-r--r-- | src/devices/nm-device-wifi.c | 39 | ||||
-rw-r--r-- | src/devices/nm-device.c | 141 | ||||
-rw-r--r-- | src/devices/nm-device.h | 7 | ||||
-rw-r--r-- | src/devices/wimax/nm-device-wimax.c | 14 |
9 files changed, 411 insertions, 36 deletions
diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index 85986f64ae..94fe5e131d 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -233,6 +233,26 @@ set_sysfs_uint (const char *iface, g_free (s); } +static void +set_bridge_properties (NMDevice *dev, NMConnection *connection) +{ + GObject *s_bridge; + const char *iface; + + s_bridge = (GObject *) nm_connection_get_setting_bridge (connection); + g_assert (s_bridge); + + iface = nm_device_get_ip_iface (dev); + g_assert (iface); + + set_sysfs_uint (iface, s_bridge, NM_SETTING_BRIDGE_STP, "bridge", "stp_state", FALSE, FALSE); + set_sysfs_uint (iface, s_bridge, NM_SETTING_BRIDGE_PRIORITY, "bridge", "priority", TRUE, FALSE); + set_sysfs_uint (iface, s_bridge, NM_SETTING_BRIDGE_FORWARD_DELAY, "bridge", "forward_delay", TRUE, TRUE); + set_sysfs_uint (iface, s_bridge, NM_SETTING_BRIDGE_HELLO_TIME, "bridge", "hello_time", TRUE, TRUE); + set_sysfs_uint (iface, s_bridge, NM_SETTING_BRIDGE_MAX_AGE, "bridge", "max_age", TRUE, TRUE); + set_sysfs_uint (iface, s_bridge, NM_SETTING_BRIDGE_AGEING_TIME, "bridge", "ageing_time", TRUE, TRUE); +} + static NMActStageReturn act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) { @@ -248,18 +268,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) connection = nm_device_get_connection (dev); g_assert (connection); - s_bridge = nm_connection_get_setting_bridge (connection); - g_assert (s_bridge); - - iface = nm_device_get_ip_iface (dev); - g_assert (iface); - - set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_STP, "bridge", "stp_state", FALSE, FALSE); - set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_PRIORITY, "bridge", "priority", TRUE, FALSE); - set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_FORWARD_DELAY, "bridge", "forward_delay", TRUE, TRUE); - set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_HELLO_TIME, "bridge", "hello_time", TRUE, TRUE); - set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_MAX_AGE, "bridge", "max_age", TRUE, TRUE); - set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_AGEING_TIME, "bridge", "ageing_time", TRUE, TRUE); + set_bridge_properties (dev, connection); } return ret; } @@ -309,6 +318,35 @@ release_slave (NMDevice *device, NMDevice *slave) return success; } +static void +test_reconfigure (NMDevice *device, NMConnection *connection, + GHashTable *diff) +{ + GHashTable *bridge_diff; + + bridge_diff = g_hash_table_lookup (diff, NM_SETTING_BRIDGE_SETTING_NAME); + if (bridge_diff) { + g_hash_table_remove (bridge_diff, NM_SETTING_BRIDGE_MTU); + g_hash_table_remove (bridge_diff, NM_SETTING_BRIDGE_STP); + g_hash_table_remove (bridge_diff, NM_SETTING_BRIDGE_PRIORITY); + g_hash_table_remove (bridge_diff, NM_SETTING_BRIDGE_FORWARD_DELAY); + g_hash_table_remove (bridge_diff, NM_SETTING_BRIDGE_HELLO_TIME); + g_hash_table_remove (bridge_diff, NM_SETTING_BRIDGE_MAX_AGE); + g_hash_table_remove (bridge_diff, NM_SETTING_BRIDGE_AGEING_TIME); + } +} + +static gboolean +reconfigure (NMDevice *device, NMConnection *connection, + NMDeviceStateReason *reason) +{ + if (!NM_DEVICE_CLASS (nm_device_bridge_parent_class)->reconfigure (device, connection, reason)) + return FALSE; + + set_bridge_properties (device, connection); + return TRUE; +} + /******************************************************************/ NMDevice * @@ -399,6 +437,8 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass) parent_class->act_stage1_prepare = act_stage1_prepare; parent_class->enslave_slave = enslave_slave; parent_class->release_slave = release_slave; + parent_class->test_reconfigure = test_reconfigure; + parent_class->reconfigure = reconfigure; /* properties */ g_object_class_install_property diff --git a/src/devices/nm-device-bt.c b/src/devices/nm-device-bt.c index 5c87ba9537..47c7ece152 100644 --- a/src/devices/nm-device-bt.c +++ b/src/devices/nm-device-bt.c @@ -1014,6 +1014,19 @@ deactivate (NMDevice *device) NM_DEVICE_CLASS (nm_device_bt_parent_class)->deactivate (device); } +static void +test_reconfigure (NMDevice *device, NMConnection *connection, + GHashTable *diff) +{ + GHashTable *bluetooth_diff; + + bluetooth_diff = g_hash_table_lookup (diff, NM_SETTING_BLUETOOTH_SETTING_NAME); + if (bluetooth_diff) { + /* This only affects matching and has already been taken into account. */ + g_hash_table_remove (bluetooth_diff, NM_SETTING_BLUETOOTH_BDADDR); + } +} + /*****************************************************************************/ static gboolean @@ -1280,6 +1293,7 @@ nm_device_bt_class_init (NMDeviceBtClass *klass) device_class->is_available = is_available; device_class->state_changed = device_state_changed; + device_class->test_reconfigure = test_reconfigure; /* Properties */ g_object_class_install_property diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 22f3e6b319..5961286d3d 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -286,6 +286,44 @@ device_state_changed (NMDevice *device, } static void +test_reconfigure (NMDevice *device, NMConnection *connection, + GHashTable *diff) +{ + GHashTable *wired_diff; + + wired_diff = g_hash_table_lookup (diff, NM_SETTING_WIRED_SETTING_NAME); + if (wired_diff) { + g_hash_table_remove (wired_diff, NM_SETTING_WIRED_MTU); + + /* These only affect matching and have already been taken into account. */ + g_hash_table_remove (wired_diff, NM_SETTING_WIRED_MAC_ADDRESS); + g_hash_table_remove (wired_diff, NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST); + g_hash_table_remove (wired_diff, NM_SETTING_WIRED_S390_SUBCHANNELS); + } +} + +static gboolean +reconfigure (NMDevice *device, NMConnection *connection, + NMDeviceStateReason *reason) +{ + NMSettingWired *s_wired; + guint32 mtu; + + if (!NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->reconfigure (device, connection, reason)) + return FALSE; + + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + mtu = nm_setting_wired_get_mtu (s_wired); + /* FIXME: this is wrong; we need to reset the MTU if it's 0. */ + if (mtu) + nm_platform_link_set_mtu (nm_device_get_ifindex (device), mtu); + } + + return TRUE; +} + +static void nm_device_ethernet_init (NMDeviceEthernet * self) { } @@ -1410,6 +1448,8 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) parent_class->carrier_changed = carrier_changed; parent_class->state_changed = device_state_changed; + parent_class->test_reconfigure = test_reconfigure; + parent_class->reconfigure = reconfigure; /* properties */ g_object_class_install_property diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index f41a8cac93..964edca8ad 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -128,47 +128,55 @@ get_generic_capabilities (NMDevice *dev) return NM_DEVICE_CAP_CARRIER_DETECT; } -static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +static gboolean +set_transport_mode (NMDevice *device, NMConnection *connection, NMDeviceStateReason *reason) { - NMActRequest *req; - NMConnection *connection; NMSettingInfiniband *s_infiniband; const char *transport_mode; char *mode_path; gboolean ok; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - req = nm_device_get_act_request (dev); - g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_connection (req); - g_assert (connection); s_infiniband = nm_connection_get_setting_infiniband (connection); g_assert (s_infiniband); transport_mode = nm_setting_infiniband_get_transport_mode (s_infiniband); - mode_path = g_strdup_printf ("/sys/class/net/%s/mode", nm_device_get_iface (dev)); + mode_path = g_strdup_printf ("/sys/class/net/%s/mode", nm_device_get_iface (device)); if (!g_file_test (mode_path, G_FILE_TEST_EXISTS)) { g_free (mode_path); if (!strcmp (transport_mode, "datagram")) - return NM_ACT_STAGE_RETURN_SUCCESS; + return TRUE; else { *reason = NM_DEVICE_STATE_REASON_INFINIBAND_MODE; - return NM_ACT_STAGE_RETURN_FAILURE; + return FALSE; } } ok = nm_utils_do_sysctl (mode_path, transport_mode); g_free (mode_path); - if (!ok) { + if (!ok) *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + return ok; +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +{ + NMActRequest *req; + NMConnection *connection; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + req = nm_device_get_act_request (dev); + g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + connection = nm_act_request_get_connection (req); + g_assert (connection); + + if (!set_transport_mode (dev, connection, reason)) return NM_ACT_STAGE_RETURN_FAILURE; - } return NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->act_stage1_prepare (dev, reason); } @@ -301,6 +309,46 @@ get_connection_hw_address (NMDevice *device, } static void +test_reconfigure (NMDevice *device, NMConnection *connection, + GHashTable *diff) +{ + GHashTable *infiniband_diff; + + infiniband_diff = g_hash_table_lookup (diff, NM_SETTING_INFINIBAND_SETTING_NAME); + if (infiniband_diff) { + g_hash_table_remove (infiniband_diff, NM_SETTING_INFINIBAND_TRANSPORT_MODE); + g_hash_table_remove (infiniband_diff, NM_SETTING_INFINIBAND_MTU); + + /* This only affects matching and has already been taken into account. */ + g_hash_table_remove (infiniband_diff, NM_SETTING_INFINIBAND_MAC_ADDRESS); + } +} + +static gboolean +reconfigure (NMDevice *device, NMConnection *connection, + NMDeviceStateReason *reason) +{ + NMSettingInfiniband *s_infiniband; + guint32 mtu; + + if (!NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->reconfigure (device, connection, reason)) + return FALSE; + + s_infiniband = nm_connection_get_setting_infiniband (connection); + g_assert (s_infiniband); + + if (!set_transport_mode (device, connection, reason)) + return FALSE; + + mtu = nm_setting_infiniband_get_mtu (s_infiniband); + /* FIXME: this is wrong; we need to reset the MTU if it's 0. */ + if (mtu) + nm_platform_link_set_mtu (nm_device_get_ifindex (device), mtu); + + return TRUE; +} + +static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { @@ -343,6 +391,8 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass) parent_class->ip4_config_pre_commit = ip4_config_pre_commit; parent_class->match_l2_config = match_l2_config; parent_class->get_connection_hw_address = get_connection_hw_address; + parent_class->test_reconfigure = test_reconfigure; + parent_class->reconfigure = reconfigure; /* properties */ diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 19ac76e9f1..2e91935185 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -96,17 +96,13 @@ bring_up (NMDevice *dev, gboolean *no_firmware) return success; } -static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +static void +set_vlan_properties (NMDevice *dev, NMConnection *connection) { - NMConnection *connection; NMSettingVlan *s_vlan; int ifindex = nm_device_get_ifindex (dev), num, i; guint32 from, to; - connection = nm_device_get_connection (dev); - g_assert (connection); - s_vlan = nm_connection_get_setting_vlan (connection); nm_platform_vlan_set_flags (ifindex, nm_setting_vlan_get_flags (s_vlan)); @@ -121,10 +117,46 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_EGRESS_MAP, i, &from, &to)) nm_platform_vlan_set_egress_map (ifindex, from, to); } +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +{ + NMConnection *connection; + + connection = nm_device_get_connection (dev); + g_assert (connection); + + set_vlan_properties (dev, connection); return NM_DEVICE_CLASS (nm_device_vlan_parent_class)->act_stage1_prepare (dev, reason); } +static void +test_reconfigure (NMDevice *device, NMConnection *connection, + GHashTable *diff) +{ + GHashTable *vlan_diff; + + vlan_diff = g_hash_table_lookup (diff, NM_SETTING_VLAN_SETTING_NAME); + if (vlan_diff) { + g_hash_table_remove (vlan_diff, NM_SETTING_VLAN_FLAGS); + g_hash_table_remove (vlan_diff, NM_SETTING_VLAN_INGRESS_PRIORITY_MAP); + g_hash_table_remove (vlan_diff, NM_SETTING_VLAN_EGRESS_PRIORITY_MAP); + } +} + +static gboolean +reconfigure (NMDevice *device, NMConnection *connection, + NMDeviceStateReason *reason) +{ + if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->reconfigure (device, connection, reason)) + return FALSE; + + set_vlan_properties (device, connection); + return TRUE; +} + /******************************************************************/ static gboolean @@ -466,6 +498,8 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass) parent_class->check_connection_compatible = check_connection_compatible; parent_class->complete_connection = complete_connection; parent_class->match_l2_config = match_l2_config; + parent_class->test_reconfigure = test_reconfigure; + parent_class->reconfigure = reconfigure; /* properties */ g_object_class_install_property diff --git a/src/devices/nm-device-wifi.c b/src/devices/nm-device-wifi.c index aae85cd3a4..40aa9879a8 100644 --- a/src/devices/nm-device-wifi.c +++ b/src/devices/nm-device-wifi.c @@ -3408,6 +3408,43 @@ device_state_changed (NMDevice *device, remove_all_aps (self); } +static void +test_reconfigure (NMDevice *device, NMConnection *connection, + GHashTable *diff) +{ + GHashTable *wireless_diff; + + wireless_diff = g_hash_table_lookup (diff, NM_SETTING_WIRELESS_SETTING_NAME); + if (wireless_diff) { + g_hash_table_remove (wireless_diff, NM_SETTING_WIRELESS_MTU); + + /* These only affect matching and have already been taken into account. */ + g_hash_table_remove (wireless_diff, NM_SETTING_WIRELESS_MAC_ADDRESS); + g_hash_table_remove (wireless_diff, NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST); + } +} + +static gboolean +reconfigure (NMDevice *device, NMConnection *connection, + NMDeviceStateReason *reason) +{ + NMSettingWireless *s_wireless; + guint32 mtu; + + if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->reconfigure (device, connection, reason)) + return FALSE; + + s_wireless = nm_connection_get_setting_wireless (connection); + if (s_wireless) { + mtu = nm_setting_wireless_get_mtu (s_wireless); + /* FIXME: this is wrong; we need to reset the MTU if it's 0. */ + if (mtu) + nm_platform_link_set_mtu (nm_device_get_ifindex (device), mtu); + } + + return TRUE; +} + NMAccessPoint * nm_device_wifi_get_activation_ap (NMDeviceWifi *self) { @@ -3634,6 +3671,8 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) parent_class->get_connection_hw_address = get_connection_hw_address; parent_class->state_changed = device_state_changed; + parent_class->test_reconfigure = test_reconfigure; + parent_class->reconfigure = reconfigure; klass->scanning_allowed = scanning_allowed; diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 9cd2271620..84374887ff 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -213,6 +213,7 @@ typedef struct { gpointer act_source6_func; gulong secrets_updated_id; gulong secrets_failed_id; + NMConnection * current_connection; /* Link stuff */ guint link_connected_id; @@ -1604,6 +1605,131 @@ nm_device_can_assume_connections (NMDevice *device) } static void +test_reconfigure (NMDevice *self, NMConnection *connection, + GHashTable *diff) +{ + GHashTable *conn_diff, *ip4_diff, *ip6_diff; + + conn_diff = g_hash_table_lookup (diff, NM_SETTING_CONNECTION_SETTING_NAME); + ip4_diff = g_hash_table_lookup (diff, NM_SETTING_IP4_CONFIG_SETTING_NAME); + ip6_diff = g_hash_table_lookup (diff, NM_SETTING_IP6_CONFIG_SETTING_NAME); + + /* These only affect matching and have already been taken into account. */ + if (conn_diff) + g_hash_table_remove (conn_diff, NM_SETTING_CONNECTION_INTERFACE_NAME); + if (ip4_diff) + g_hash_table_remove (ip4_diff, NM_SETTING_IP4_CONFIG_MAY_FAIL); + if (ip6_diff) + g_hash_table_remove (ip6_diff, NM_SETTING_IP6_CONFIG_MAY_FAIL); + + /* FIXME: remove reconfigurable ip4/ip6 properties */ +} + +static gboolean +nm_device_can_reconfigure (NMDevice *self, NMConnection *connection, + GHashTable *diff) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self); + GHashTableIter iter; + gpointer key, value; + + /* If the changes would make the connection incompatible, then we + * can always "reconfigure" the device (by deactivating the + * connection). + */ + if (!nm_device_check_connection_compatible (self, connection, NULL)) + return TRUE; + if ( (!priv->ip4_config && nm_device_ip_config_should_fail (self, FALSE)) + || (!priv->ip6_config && nm_device_ip_config_should_fail (self, TRUE))) + return TRUE; + + klass->test_reconfigure (self, connection, diff); + + /* test_reconfigure() will have removed any properties it can + * reconfigure; clear out any now-empty settings diffs. + */ + g_hash_table_iter_init (&iter, diff); + while (g_hash_table_iter_next (&iter, &key, &value)) { + if (g_hash_table_size (value) == 0) + g_hash_table_iter_remove (&iter); + } + + /* If the diff is now empty, that means all of the changed + * properties are reconfigurable. + */ + return g_hash_table_size (diff) == 0; +} + +static gboolean +reconfigure (NMDevice *device, NMConnection *connection, + NMDeviceStateReason *reason) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + if (!nm_device_check_connection_compatible (device, connection, NULL)) { + nm_log_info ("(%s): connection '%s' is no longer compatible with device", + nm_device_get_iface (self), nm_connection_get_id (connection)); + *reason = NM_DEVICE_STATE_REASON_CONNECTION_REMOVED; + return FALSE; + } + + if (!priv->ip4_config && nm_device_ip_config_should_fail (device, FALSE)) { + nm_log_info ("(%s): connection '%s' now requires IPv4 connectivity", + nm_device_get_iface (self), nm_connection_get_id (connection)); + *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; + return FALSE; + } + + if (!priv->ip6_config && nm_device_ip_config_should_fail (device, TRUE)) { + nm_log_info ("(%s): connection '%s' now requires IPv6 connectivity", + nm_device_get_iface (self), nm_connection_get_id (connection)); + *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; + return FALSE; + } + + /* FIXME: reconfigure IP4 and IP6 properties, by re-merging the + * settings properties with the DHCP/SLAAC/AIPD/etc-provided + * configs. + */ + + return TRUE; +} + +static void +connection_updated (NMSettingsConnection *settings_connection, gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *connection = NM_CONNECTION (settings_connection); + NMDeviceStateReason reason; + GHashTable *diff = NULL; + + if (!nm_connection_diff (priv->current_connection, connection, + NM_SETTING_COMPARE_FLAG_FUZZY, + &diff)) { + if (nm_device_can_reconfigure (self, connection, diff)) { + if (!NM_DEVICE_GET_CLASS (self)->reconfigure (self, connection, &reason)) { + nm_device_queue_state (self, + NM_DEVICE_STATE_DISCONNECTED, + reason); + } + } else { + nm_log_info ("(%s): connection '%s' changed, but device cannot be updated for those changes while active", + nm_device_get_iface (self), nm_connection_get_id (connection)); + } + + g_hash_table_destroy (diff); + } else { + nm_log_dbg ("(%s): connection '%s' changed, but the changes do not affect the device", + nm_device_get_iface (self), nm_connection_get_id (connection)); + } + + g_clear_object (&priv->current_connection); + priv->current_connection = nm_connection_duplicate (connection); +} + +static void dnsmasq_state_changed_cb (NMDnsMasqManager *manager, guint32 status, gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); @@ -3881,7 +4007,8 @@ nm_device_activate_ip6_state_in_wait (NMDevice *self) static void clear_act_request (NMDevice *self) { - NMDevicePrivate * priv; + NMDevicePrivate *priv; + NMConnection *connection; g_return_if_fail (self != NULL); @@ -3902,6 +4029,10 @@ clear_act_request (NMDevice *self) priv->secrets_failed_id = 0; } + connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (priv->act_request)); + g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_updated), self); + g_clear_object (&priv->current_connection); + nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE); g_object_unref (priv->act_request); @@ -4213,6 +4344,10 @@ nm_device_activate (NMDevice *self, NMActRequest *req) priv->act_request = g_object_ref (req); g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION); + g_signal_connect (connection, NM_SETTINGS_CONNECTION_UPDATED, + G_CALLBACK (connection_updated), self); + priv->current_connection = g_object_ref (connection); + if (nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (req))) { /* If it's an assumed connection, let the device subclass short-circuit * the normal connection process and just copy its IP configs from the @@ -4827,6 +4962,8 @@ dispose (GObject *object) g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ip_changed), self); g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self); + g_clear_object (&priv->current_connection); + out: G_OBJECT_CLASS (nm_device_parent_class)->dispose (object); } @@ -5132,6 +5269,8 @@ nm_device_class_init (NMDeviceClass *klass) klass->carrier_changed = carrier_changed; klass->can_interrupt_activation = can_interrupt_activation; klass->get_hw_address_length = get_hw_address_length; + klass->test_reconfigure = test_reconfigure; + klass->reconfigure = reconfigure; /* Properties */ g_object_class_install_property diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 7fcb768a5b..9f21d25bb6 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -187,7 +187,12 @@ typedef struct { gboolean (* have_any_ready_slaves) (NMDevice *self, const GSList *slaves); - void (* link_changed) (NMDevice *self); + void (* link_changed) (NMDevice *self); + + void (* test_reconfigure) (NMDevice *self, NMConnection *connection, + GHashTable *diff); + gboolean (* reconfigure) (NMDevice *self, NMConnection *connection, + NMDeviceStateReason *reason); } NMDeviceClass; diff --git a/src/devices/wimax/nm-device-wimax.c b/src/devices/wimax/nm-device-wimax.c index 9e9fae2cd1..c6325a5ccf 100644 --- a/src/devices/wimax/nm-device-wimax.c +++ b/src/devices/wimax/nm-device-wimax.c @@ -1205,6 +1205,19 @@ device_state_changed (NMDevice *device, } } +static void +test_reconfigure (NMDevice *device, NMConnection *connection, + GHashTable *diff) +{ + GHashTable *wimax_diff; + + wimax_diff = g_hash_table_lookup (diff, NM_SETTING_WIMAX_SETTING_NAME); + if (wimax_diff) { + /* This only affects matching and has already been taken into account. */ + g_hash_table_remove (wimax_diff, NM_SETTING_WIMAX_MAC_ADDRESS); + } +} + /*************************************************************************/ static gboolean @@ -1395,6 +1408,7 @@ nm_device_wimax_class_init (NMDeviceWimaxClass *klass) device_class->get_connection_hw_address = get_connection_hw_address; device_class->state_changed = device_state_changed; + device_class->test_reconfigure = test_reconfigure; /* Properties */ g_object_class_install_property (object_class, PROP_ACTIVE_NSP, |