diff options
author | Thomas Haller <thaller@redhat.com> | 2017-03-16 15:58:32 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-03-16 15:58:32 +0100 |
commit | 6197c27f245999c21f5c8cea8983f51631446745 (patch) | |
tree | c7cf8328631038fb7e94f7536ea35b2e1ae4df4a | |
parent | c2dc1c6fa3660d2a4e2500f96ce945cd02efdcb6 (diff) | |
parent | 82bfb6c46d2ff1ca01c7dffd0a812bf53e08ff33 (diff) | |
download | NetworkManager-6197c27f245999c21f5c8cea8983f51631446745.tar.gz |
device,default-route-manager: merge branch 'th/default-route-resync'
-rw-r--r-- | src/devices/nm-device-vlan.c | 2 | ||||
-rw-r--r-- | src/devices/nm-device.c | 53 | ||||
-rw-r--r-- | src/devices/nm-device.h | 6 | ||||
-rw-r--r-- | src/nm-default-route-manager.c | 182 | ||||
-rw-r--r-- | src/nm-default-route-manager.h | 3 |
5 files changed, 158 insertions, 88 deletions
diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 2680353ca0..54d0440960 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -121,7 +121,7 @@ parent_hwaddr_maybe_changed (NMDevice *parent, */ 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 (NM_DEVICE (self), s_ip6, s_ip6, FALSE); } } diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index aabea840ea..cb1cc63707 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -302,6 +302,9 @@ typedef struct _NMDevicePrivate { bool up:1; /* IFF_UP */ + bool v4_commit_first_time:1; + bool v6_commit_first_time:1; + /* Generic DHCP stuff */ guint32 dhcp_timeout; char * dhcp_anycast_address; @@ -332,9 +335,6 @@ typedef struct _NMDevicePrivate { NMPlatformIP6Route v6; } default_route; - bool v4_commit_first_time; - bool v6_commit_first_time; - /* DHCPv4 tracking */ struct { NMDhcpClient * client; @@ -8418,7 +8418,8 @@ _nm_device_hash_check_invalid_keys (GHashTable *hash, const char *setting_name, void nm_device_reactivate_ip4_config (NMDevice *self, NMSettingIPConfig *s_ip4_old, - NMSettingIPConfig *s_ip4_new) + NMSettingIPConfig *s_ip4_new, + gboolean force_restart) { NMDevicePrivate *priv; const char *method_old, *method_new; @@ -8434,14 +8435,17 @@ nm_device_reactivate_ip4_config (NMDevice *self, s_ip4_new, nm_device_get_ip4_route_metric (self)); - method_old = s_ip4_old ? - nm_setting_ip_config_get_method (s_ip4_old) : - NM_SETTING_IP4_CONFIG_METHOD_DISABLED; - method_new = s_ip4_new ? - nm_setting_ip_config_get_method (s_ip4_new) : - NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + if (!force_restart) { + method_old = s_ip4_old + ? nm_setting_ip_config_get_method (s_ip4_old) + : NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + method_new = s_ip4_new + ? nm_setting_ip_config_get_method (s_ip4_new) + : NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + force_restart = !nm_streq0 (method_old, method_new); + } - if (!nm_streq0 (method_old, method_new)) { + if (force_restart) { _cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE); _set_ip_state (self, AF_INET, IP_WAIT); if (!nm_device_activate_stage3_ip4_start (self)) @@ -8456,7 +8460,8 @@ nm_device_reactivate_ip4_config (NMDevice *self, void nm_device_reactivate_ip6_config (NMDevice *self, NMSettingIPConfig *s_ip6_old, - NMSettingIPConfig *s_ip6_new) + NMSettingIPConfig *s_ip6_new, + gboolean force_restart) { NMDevicePrivate *priv; const char *method_old, *method_new; @@ -8472,14 +8477,17 @@ nm_device_reactivate_ip6_config (NMDevice *self, s_ip6_new, nm_device_get_ip6_route_metric (self)); - method_old = s_ip6_old ? - nm_setting_ip_config_get_method (s_ip6_old) : - NM_SETTING_IP6_CONFIG_METHOD_IGNORE; - method_new = s_ip6_new ? - nm_setting_ip_config_get_method (s_ip6_new) : - NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + if (!force_restart) { + method_old = s_ip6_old + ? nm_setting_ip_config_get_method (s_ip6_old) + : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + method_new = s_ip6_new + ? nm_setting_ip_config_get_method (s_ip6_new) + : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; + force_restart = !nm_streq0 (method_old, method_new); + } - if (!nm_streq0 (method_old, method_new)) { + if (force_restart) { _cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE); _set_ip_state (self, AF_INET6, IP_WAIT); if (!nm_device_activate_stage3_ip6_start (self)) @@ -8676,6 +8684,9 @@ check_and_reapply_connection (NMDevice *self, } else con_old = con_new = applied; + priv->v4_commit_first_time = TRUE; + priv->v6_commit_first_time = TRUE; + /************************************************************************** * Reapply changes *************************************************************************/ @@ -8690,8 +8701,8 @@ check_and_reapply_connection (NMDevice *self, s_ip6_old = nm_connection_get_setting_ip6_config (con_old); s_ip6_new = nm_connection_get_setting_ip6_config (con_new); - nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new); - nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new); + nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new, TRUE); + nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new, TRUE); reactivate_proxy_config (self); diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index d1e9a9455a..f98978bdc0 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -657,10 +657,12 @@ void nm_device_update_firewall_zone (NMDevice *self); void nm_device_update_metered (NMDevice *self); void nm_device_reactivate_ip4_config (NMDevice *device, NMSettingIPConfig *s_ip4_old, - NMSettingIPConfig *s_ip4_new); + NMSettingIPConfig *s_ip4_new, + gboolean force_restart); void nm_device_reactivate_ip6_config (NMDevice *device, NMSettingIPConfig *s_ip6_old, - NMSettingIPConfig *s_ip6_new); + NMSettingIPConfig *s_ip6_new, + gboolean force_restart); gboolean nm_device_update_hw_address (NMDevice *self); void nm_device_update_initial_hw_address (NMDevice *self); diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c index 71ca919ec6..44105296ee 100644 --- a/src/nm-default-route-manager.c +++ b/src/nm-default-route-manager.c @@ -124,7 +124,7 @@ NM_DEFINE_SINGLETON_GETTER (NMDefaultRouteManager, nm_default_route_manager_get, const Entry *const __entry = (entry); \ \ _nm_log (__level, __domain, 0, \ - "%s: entry[%u/%s:%p:%s:%c:%csync]: "_NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + "%s: entry[%u/%s:%p:%s:%chas:%csync]: "_NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ self != singleton_instance \ ? nm_sprintf_buf (__prefix_buf, "%s%c[%p]", \ _NMLOG2_PREFIX_NAME, \ @@ -135,7 +135,7 @@ NM_DEFINE_SINGLETON_GETTER (NMDefaultRouteManager, nm_default_route_manager_get, NM_IS_DEVICE (__entry->source.pointer) ? "dev" : "vpn", \ __entry->source.pointer, \ NM_IS_DEVICE (__entry->source.pointer) ? nm_device_get_iface (__entry->source.device) : nm_active_connection_get_settings_connection_id (NM_ACTIVE_CONNECTION (__entry->source.vpn)), \ - (__entry->never_default ? '0' : '1'), \ + (__entry->never_default ? '-' : '+'), \ (__entry->synced ? '+' : '-') \ _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ } \ @@ -480,17 +480,6 @@ _get_assumed_interface_metrics (const VTableIP *vtable, NMDefaultRouteManager *s return result; } -static int -_sort_metrics_ascending_fcn (gconstpointer a, gconstpointer b) -{ - guint32 m_a = *((guint32 *) a); - guint32 m_b = *((guint32 *) b); - - if (m_a < m_b) - return -1; - return m_a == m_b ? 0 : 1; -} - static gboolean _resync_all (const VTableIP *vtable, NMDefaultRouteManager *self, const Entry *changed_entry, const Entry *old_entry, gboolean external_change) { @@ -533,8 +522,6 @@ _resync_all (const VTableIP *vtable, NMDefaultRouteManager *self, const Entry *c for (i = 0; i < entries->len; i++) { entry = g_ptr_array_index (entries, i); - g_assert (entry != old_entry); - if (entry->never_default) continue; @@ -589,12 +576,15 @@ _resync_all (const VTableIP *vtable, NMDefaultRouteManager *self, const Entry *c /* for the changed entry, the previous metric was either old_entry->effective_metric, * or none. Hence, we only have to remember what is going to change. */ g_array_append_val (changed_metrics, expected_metric); - if (old_entry) { + if (!old_entry) { + _LOG2D (vtable, i, entry, "sync:add %s (%u)", + vtable->vt->route_to_string (&entry->route, NULL, 0), (guint) expected_metric); + } else if (old_entry != changed_entry) { _LOG2D (vtable, i, entry, "sync:update %s (%u -> %u)", vtable->vt->route_to_string (&entry->route, NULL, 0), (guint) old_entry->effective_metric, (guint) expected_metric); } else { - _LOG2D (vtable, i, entry, "sync:add %s (%u)", + _LOG2D (vtable, i, entry, "sync:resync %s (%u)", vtable->vt->route_to_string (&entry->route, NULL, 0), (guint) expected_metric); } } else if (entry->effective_metric != expected_metric) { @@ -621,7 +611,7 @@ _resync_all (const VTableIP *vtable, NMDefaultRouteManager *self, const Entry *c g_array_free (routes, TRUE); - g_array_sort (changed_metrics, _sort_metrics_ascending_fcn); + g_array_sort_with_data (changed_metrics, nm_cmp_uint32_p_with_data, NULL); last_metric = -1; for (j = 0; j < changed_metrics->len; j++) { expected_metric = g_array_index (changed_metrics, guint32, j); @@ -672,7 +662,11 @@ _entry_at_idx_update (const VTableIP *vtable, NMDefaultRouteManager *self, guint entry->effective_metric = entry->route.rx.metric; _LOG2D (vtable, entry_idx, entry, "%s %s (%"G_GUINT32_FORMAT")", - old_entry ? "record:update" : "record:add ", + old_entry + ? (entry != old_entry + ? "record:update" + : "record:resync") + : "record:add ", vtable->vt->route_to_string (&entry->route, NULL, 0), entry->effective_metric); @@ -709,7 +703,9 @@ _entry_at_idx_remove (const VTableIP *vtable, NMDefaultRouteManager *self, guint /*****************************************************************************/ static void -_ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self, gpointer source) +_ipx_update_default_route (const VTableIP *vtable, + NMDefaultRouteManager *self, + gpointer source) { NMDefaultRouteManagerPrivate *priv; Entry *entry; @@ -781,9 +777,8 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self, default_route = &rt.rx; never_default = TRUE; - synced = TRUE; - } else - synced = default_route && !is_assumed; + } + synced = !is_assumed; } else { NMConnection *connection = nm_active_connection_get_applied_connection ((NMActiveConnection *) vpn); @@ -875,12 +870,18 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self, new_entry.never_default = never_default; new_entry.synced = synced; - if (memcmp (entry, &new_entry, sizeof (new_entry)) == 0) - return; - - old_entry = *entry; - *entry = new_entry; - _entry_at_idx_update (vtable, self, entry_idx, &old_entry); + if (memcmp (entry, &new_entry, sizeof (new_entry)) == 0) { + if (!synced) { + /* the internal book-keeping doesn't change, so don't do a full + * sync of the configured routes. */ + return; + } + _entry_at_idx_update (vtable, self, entry_idx, entry); + } else { + old_entry = *entry; + *entry = new_entry; + _entry_at_idx_update (vtable, self, entry_idx, &old_entry); + } } else { /* delete */ _entry_at_idx_remove (vtable, self, entry_idx); @@ -888,13 +889,15 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self, } void -nm_default_route_manager_ip4_update_default_route (NMDefaultRouteManager *self, gpointer source) +nm_default_route_manager_ip4_update_default_route (NMDefaultRouteManager *self, + gpointer source) { _ipx_update_default_route (&vtable_ip4, self, source); } void -nm_default_route_manager_ip6_update_default_route (NMDefaultRouteManager *self, gpointer source) +nm_default_route_manager_ip6_update_default_route (NMDefaultRouteManager *self, + gpointer source) { _ipx_update_default_route (&vtable_ip6, self, source); } @@ -1256,7 +1259,7 @@ static const VTableIP vtable_ip6 = { /*****************************************************************************/ static gboolean -_resync_idle_now (NMDefaultRouteManager *self) +_resync_now (NMDefaultRouteManager *self) { gboolean has_v4_changes, has_v6_changes; gboolean changed = FALSE; @@ -1271,7 +1274,7 @@ _resync_idle_now (NMDefaultRouteManager *self) priv->resync.has_v4_changes = FALSE; priv->resync.has_v6_changes = FALSE; - priv->resync.idle_handle = 0; + nm_clear_g_source (&priv->resync.idle_handle); priv->resync.backoff_wait_time_ms = priv->resync.backoff_wait_time_ms == 0 ? 100 @@ -1288,6 +1291,64 @@ _resync_idle_now (NMDefaultRouteManager *self) _resync_idle_cancel (self); } + return changed; +} + +/** + * nm_default_route_manager_resync: + * @self: the #NMDefaultRouteManager instance + * @af_family: the address family to resync, can be + * AF_INET, AF_INET6 or AF_UNSPEC to sync both. + * + * #NMDefaultRouteManager keeps an internal list of configured + * routes. Usually, it configures routes in the system only + * - when that internal list changes due to + * nm_default_route_manager_ip4_update_default_route() or + * nm_default_route_manager_ip6_update_default_route(). + * - when platform notifies about changes, via _resync_idle_now(). + * This forces a resync to update the internal bookkeeping + * with what is currently configured in the system, but also + * reconfigure the system with all non-assumed default routes. + * + * Returns: %TRUE if anything changed during resync. + */ +gboolean +nm_default_route_manager_resync (NMDefaultRouteManager *self, + int af_family) +{ + NMDefaultRouteManagerPrivate *priv; + + g_return_val_if_fail (NM_IS_DEFAULT_ROUTE_MANAGER (self), FALSE); + g_return_val_if_fail (NM_IN_SET (af_family, AF_INET, AF_INET6, AF_UNSPEC), FALSE); + + priv = NM_DEFAULT_ROUTE_MANAGER_GET_PRIVATE (self); + + if (priv->disposed) + return FALSE; + + switch (af_family) { + case AF_INET: + priv->resync.has_v4_changes = TRUE; + break; + case AF_INET6: + priv->resync.has_v6_changes = TRUE; + break; + default: + priv->resync.has_v4_changes = TRUE; + priv->resync.has_v6_changes = TRUE; + break; + } + + return _resync_now (self); +} + +static gboolean +_resync_idle_now (NMDefaultRouteManager *self) +{ + NMDefaultRouteManagerPrivate *priv = NM_DEFAULT_ROUTE_MANAGER_GET_PRIVATE (self); + + priv->resync.idle_handle = 0; + _resync_now (self); return G_SOURCE_REMOVE; } @@ -1333,33 +1394,6 @@ _resync_idle_reschedule (NMDefaultRouteManager *self) } static void -_platform_ipx_route_changed_cb (const VTableIP *vtable, - NMDefaultRouteManager *self, - const NMPlatformIPRoute *route) -{ - NMDefaultRouteManagerPrivate *priv; - - if (route && !NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) { - /* we only care about address changes or changes of default route. */ - return; - } - - priv = NM_DEFAULT_ROUTE_MANAGER_GET_PRIVATE (self); - - if (priv->resync.guard) { - /* callbacks while executing _resync_all() are ignored. */ - return; - } - - if (vtable->vt->is_ip4) - priv->resync.has_v4_changes = TRUE; - else - priv->resync.has_v6_changes = TRUE; - - _resync_idle_reschedule (self); -} - -static void _platform_changed_cb (NMPlatform *platform, int obj_type_i, int ifindex, @@ -1367,24 +1401,44 @@ _platform_changed_cb (NMPlatform *platform, int change_type_i, NMDefaultRouteManager *self) { + NMDefaultRouteManagerPrivate *priv; const NMPObjectType obj_type = obj_type_i; + const VTableIP *vtable; switch (obj_type) { case NMP_OBJECT_TYPE_IP4_ADDRESS: - _platform_ipx_route_changed_cb (&vtable_ip4, self, NULL); + vtable = &vtable_ip4; break; case NMP_OBJECT_TYPE_IP6_ADDRESS: - _platform_ipx_route_changed_cb (&vtable_ip6, self, NULL); + vtable = &vtable_ip6; break; case NMP_OBJECT_TYPE_IP4_ROUTE: - _platform_ipx_route_changed_cb (&vtable_ip4, self, (const NMPlatformIPRoute *) platform_object); + if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT (platform_object)) + return; + vtable = &vtable_ip4; break; case NMP_OBJECT_TYPE_IP6_ROUTE: - _platform_ipx_route_changed_cb (&vtable_ip6, self, (const NMPlatformIPRoute *) platform_object); + if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT (platform_object)) + return; + vtable = &vtable_ip6; break; default: g_return_if_reached (); } + + priv = NM_DEFAULT_ROUTE_MANAGER_GET_PRIVATE (self); + + if (priv->resync.guard) { + /* callbacks while executing _resync_all() are ignored. */ + return; + } + + if (vtable->vt->is_ip4) + priv->resync.has_v4_changes = TRUE; + else + priv->resync.has_v6_changes = TRUE; + + _resync_idle_reschedule (self); } /*****************************************************************************/ diff --git a/src/nm-default-route-manager.h b/src/nm-default-route-manager.h index bd5e873295..cecc9501a9 100644 --- a/src/nm-default-route-manager.h +++ b/src/nm-default-route-manager.h @@ -61,4 +61,7 @@ NMIP6Config *nm_default_route_manager_ip6_get_best_config (NMDefaultRouteManager NMDevice **out_device, NMVpnConnection **out_vpn); +gboolean nm_default_route_manager_resync (NMDefaultRouteManager *self, + int af_family); + #endif /* NM_DEFAULT_ROUTE_MANAGER_H */ |