From d83dba3e3d3e3c6a14c28e63912a7a1ae87a54b6 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Fri, 20 Jul 2018 16:32:10 +0200 Subject: [PATCH 1/2] dhcp: allowing changing route metric and route table (cherry picked from commit 9ca56089ebdb09e4f30e277164cfa03746892e6b) --- src/dhcp/nm-dhcp-client.c | 33 ++++++++++++++++++++++++++++----- src/dhcp/nm-dhcp-client.h | 4 ++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c index 360bd36767..e53c8d8703 100644 --- a/src/dhcp/nm-dhcp-client.c +++ b/src/dhcp/nm-dhcp-client.c @@ -51,7 +51,7 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( +NM_GOBJECT_PROPERTIES_DEFINE (NMDhcpClient, PROP_ADDR_FAMILY, PROP_FLAGS, PROP_HWADDR, @@ -163,6 +163,17 @@ nm_dhcp_client_get_route_table (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->route_table; } +void +nm_dhcp_client_set_route_table (NMDhcpClient *self, guint32 route_table) +{ + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + + if (route_table != priv->route_table) { + priv->route_table = route_table; + _notify (self, PROP_ROUTE_TABLE); + } +} + guint32 nm_dhcp_client_get_route_metric (NMDhcpClient *self) { @@ -171,6 +182,17 @@ nm_dhcp_client_get_route_metric (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->route_metric; } +void +nm_dhcp_client_set_route_metric (NMDhcpClient *self, guint32 route_metric) +{ + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + + if (route_metric != priv->route_metric) { + priv->route_metric = route_metric; + _notify (self, PROP_ROUTE_METRIC); + } +} + guint32 nm_dhcp_client_get_timeout (NMDhcpClient *self) { @@ -834,6 +856,9 @@ get_property (GObject *object, guint prop_id, case PROP_ROUTE_METRIC: g_value_set_uint (value, priv->route_metric); break; + case PROP_ROUTE_TABLE: + g_value_set_uint (value, priv->route_table); + break; case PROP_TIMEOUT: g_value_set_uint (value, priv->timeout); break; @@ -889,11 +914,9 @@ set_property (GObject *object, guint prop_id, priv->uuid = g_value_dup_string (value); break; case PROP_ROUTE_TABLE: - /* construct-only */ priv->route_table = g_value_get_uint (value); break; case PROP_ROUTE_METRIC: - /* construct-only */ priv->route_metric = g_value_get_uint (value); break; case PROP_TIMEOUT: @@ -1002,13 +1025,13 @@ nm_dhcp_client_class_init (NMDhcpClientClass *client_class) obj_properties[PROP_ROUTE_TABLE] = g_param_spec_uint (NM_DHCP_CLIENT_ROUTE_TABLE, "", "", 0, G_MAXUINT32, RT_TABLE_MAIN, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); obj_properties[PROP_ROUTE_METRIC] = g_param_spec_uint (NM_DHCP_CLIENT_ROUTE_METRIC, "", "", 0, G_MAXUINT32, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); obj_properties[PROP_TIMEOUT] = diff --git a/src/dhcp/nm-dhcp-client.h b/src/dhcp/nm-dhcp-client.h index f3d0b7d184..4c196045e6 100644 --- a/src/dhcp/nm-dhcp-client.h +++ b/src/dhcp/nm-dhcp-client.h @@ -131,8 +131,12 @@ GBytes *nm_dhcp_client_get_hw_addr (NMDhcpClient *self); guint32 nm_dhcp_client_get_route_table (NMDhcpClient *self); +void nm_dhcp_client_set_route_table (NMDhcpClient *self, guint32 route_table); + guint32 nm_dhcp_client_get_route_metric (NMDhcpClient *self); +void nm_dhcp_client_set_route_metric (NMDhcpClient *self, guint32 route_metric); + guint32 nm_dhcp_client_get_timeout (NMDhcpClient *self); GBytes *nm_dhcp_client_get_client_id (NMDhcpClient *self); From ca0f147bf45e291914b4ec3c6afbc812dd8010b1 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Sat, 21 Jul 2018 10:42:04 +0200 Subject: [PATCH 2/2] core: handle route metric when reapplying dynamic IP methods For dynamic IP methods (DHCP, IPv4LL, WWAN) the route metric is set at activation/renewal time using the value from static configuration. To support runtime change we need to update the dynamic configuration in place and tell the DHCP client the new value to use for future renewals. https://bugzilla.redhat.com/show_bug.cgi?id=1528071 (cherry picked from commit b9e6433a024c13631c984797c964f1863de83113) --- src/devices/nm-device.c | 65 +++++++++++++++++++++++++++++++++++++---- src/nm-ip4-config.c | 31 ++++++++++++++++++++ src/nm-ip4-config.h | 1 + src/nm-ip6-config.c | 31 ++++++++++++++++++++ src/nm-ip6-config.h | 2 ++ 5 files changed, 124 insertions(+), 6 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 52ed227179..a7597f4f0a 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -10340,10 +10340,37 @@ nm_device_reactivate_ip4_config (NMDevice *self, _set_ip_state (self, AF_INET, IP_WAIT); if (!nm_device_activate_stage3_ip4_start (self)) _LOGW (LOGD_IP4, "Failed to apply IPv4 configuration"); - } else { - if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) - _LOGW (LOGD_IP4, "Failed to reapply IPv4 configuration"); + return; } + + if (s_ip4_old && s_ip4_new) { + gint64 metric_old, metric_new; + + /* For dynamic IP methods (DHCP, IPv4LL, WWAN) the route metric is + * set at activation/renewal time using the value from static + * configuration. To support runtime change we need to update the + * dynamic configuration in place and tell the DHCP client the new + * value to use for future renewals. + */ + metric_old = nm_setting_ip_config_get_route_metric (s_ip4_old); + metric_new = nm_setting_ip_config_get_route_metric (s_ip4_new); + + if (metric_old != metric_new) { + if (priv->dev_ip4_config.orig) { + nm_ip4_config_update_routes_metric ((NMIP4Config *) priv->dev_ip4_config.orig, + nm_device_get_route_metric (self, AF_INET)); + } + if (priv->wwan_ip_config_4.orig) { + nm_ip4_config_update_routes_metric ((NMIP4Config *) priv->wwan_ip_config_4.orig, + nm_device_get_route_metric (self, AF_INET)); + } + if (priv->dhcp4.client) + nm_dhcp_client_set_route_metric (priv->dhcp4.client, metric_new); + } + } + + if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) + _LOGW (LOGD_IP4, "Failed to reapply IPv4 configuration"); } } @@ -10385,10 +10412,36 @@ nm_device_reactivate_ip6_config (NMDevice *self, _set_ip_state (self, AF_INET6, IP_WAIT); if (!nm_device_activate_stage3_ip6_start (self)) _LOGW (LOGD_IP6, "Failed to apply IPv6 configuration"); - } else { - if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) - _LOGW (LOGD_IP4, "Failed to reapply IPv6 configuration"); + return; } + + if (s_ip6_old && s_ip6_new) { + gint64 metric_old, metric_new; + + /* See comment in nm_device_reactivate_ip6_config() */ + metric_old = nm_setting_ip_config_get_route_metric (s_ip6_old); + metric_new = nm_setting_ip_config_get_route_metric (s_ip6_new); + + if (metric_old != metric_new) { + if (priv->ac_ip6_config.orig) { + nm_ip6_config_update_routes_metric ((NMIP6Config *) priv->ac_ip6_config.orig, + nm_device_get_route_metric (self, AF_INET6)); + } + if (priv->dhcp6.ip6_config.orig) { + nm_ip6_config_update_routes_metric ((NMIP6Config *) priv->dhcp6.ip6_config.orig, + nm_device_get_route_metric (self, AF_INET6)); + } + if (priv->wwan_ip_config_6.orig) { + nm_ip6_config_update_routes_metric ((NMIP6Config *) priv->wwan_ip_config_6.orig, + nm_device_get_route_metric (self, AF_INET6)); + } + if (priv->dhcp6.client) + nm_dhcp_client_set_route_metric (priv->dhcp6.client, metric_new); + } + } + + if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) + _LOGW (LOGD_IP4, "Failed to reapply IPv6 configuration"); } } diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 6ae81b5730..657ebfc0b2 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -645,6 +645,37 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i return self; } +void +nm_ip4_config_update_routes_metric (NMIP4Config *self, gint64 metric) +{ + gs_free NMPlatformIP4Route *routes = NULL; + gboolean need_update = FALSE; + const NMPlatformIP4Route *r; + NMDedupMultiIter iter; + guint num = 0, i = 0; + + nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) { + if (r->metric != metric) + need_update = TRUE; + num++; + } + if (!need_update) + return; + + routes = g_new (NMPlatformIP4Route, num); + nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) { + routes[i] = *r; + routes[i].metric = metric; + i++; + } + + g_object_freeze_notify (G_OBJECT (self)); + nm_ip4_config_reset_routes (self); + for (i = 0; i < num; i++) + nm_ip4_config_add_route (self, &routes[i], NULL); + g_object_thaw_notify (G_OBJECT (self)); +} + void nm_ip4_config_add_dependent_routes (NMIP4Config *self, guint32 route_table, diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 78aca14e43..45c1fa3faa 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -223,6 +223,7 @@ const NMPlatformIP4Route *_nmtst_ip4_config_get_route (const NMIP4Config *self, const NMPlatformIP4Route *nm_ip4_config_get_direct_route_for_host (const NMIP4Config *self, in_addr_t host, guint32 route_table); +void nm_ip4_config_update_routes_metric (NMIP4Config *self, gint64 metric); void nm_ip4_config_reset_nameservers (NMIP4Config *self); void nm_ip4_config_add_nameserver (NMIP4Config *self, guint32 nameserver); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 9807d3882c..3869fee81b 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -427,6 +427,37 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i return self; } +void +nm_ip6_config_update_routes_metric (NMIP6Config *self, gint64 metric) +{ + gs_free NMPlatformIP6Route *routes = NULL; + gboolean need_update = FALSE; + const NMPlatformIP6Route *r; + NMDedupMultiIter iter; + guint num = 0, i = 0; + + nm_ip_config_iter_ip6_route_for_each (&iter, self, &r) { + if (r->metric != metric) + need_update = TRUE; + num++; + } + if (!need_update) + return; + + routes = g_new (NMPlatformIP6Route, num); + nm_ip_config_iter_ip6_route_for_each (&iter, self, &r) { + routes[i] = *r; + routes[i].metric = metric; + i++; + } + + g_object_freeze_notify (G_OBJECT (self)); + nm_ip6_config_reset_routes (self); + for (i = 0; i < num; i++) + nm_ip6_config_add_route (self, &routes[i], NULL); + g_object_thaw_notify (G_OBJECT (self)); +} + void nm_ip6_config_add_dependent_routes (NMIP6Config *self, guint32 route_table, diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 9762ef48be..b8e80410ab 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -224,4 +224,6 @@ void nm_ip6_config_reset_routes_ndisc (NMIP6Config *self, guint32 route_metric, gboolean kernel_support_rta_pref); +void nm_ip6_config_update_routes_metric (NMIP6Config *self, gint64 metric); + #endif /* __NETWORKMANAGER_IP6_CONFIG_H__ */