summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-03-16 15:58:32 +0100
committerThomas Haller <thaller@redhat.com>2017-03-16 15:58:32 +0100
commit6197c27f245999c21f5c8cea8983f51631446745 (patch)
treec7cf8328631038fb7e94f7536ea35b2e1ae4df4a
parentc2dc1c6fa3660d2a4e2500f96ce945cd02efdcb6 (diff)
parent82bfb6c46d2ff1ca01c7dffd0a812bf53e08ff33 (diff)
downloadNetworkManager-6197c27f245999c21f5c8cea8983f51631446745.tar.gz
device,default-route-manager: merge branch 'th/default-route-resync'
-rw-r--r--src/devices/nm-device-vlan.c2
-rw-r--r--src/devices/nm-device.c53
-rw-r--r--src/devices/nm-device.h6
-rw-r--r--src/nm-default-route-manager.c182
-rw-r--r--src/nm-default-route-manager.h3
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 */