diff options
author | Thomas Haller <thaller@redhat.com> | 2019-04-30 14:01:10 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-06-14 08:51:04 +0200 |
commit | 3d371ceb4db2580b62b3597cfa0c0250bc3ea505 (patch) | |
tree | 3a362e64015a46878814992adc19763eb16f84af | |
parent | 091fa920a5136f0c1a8905e62824ef9631ef2bc5 (diff) | |
download | NetworkManager-th/reapply-route-table.tar.gz |
device: support reapplying route-tableth/reapply-route-table
Changing "ipv4.route-table" and "ipv6.route-table" was not allowed
during reapply.
The main difficulty for supporting that is changing the sync-mode.
With route-table 0, we don't sync all tables but only the main table.
So, when reapply changes from full-sync to no-full-sync, it's slightly
more complicated.
But it's probably not too complicated either. The change from
no-full-sync to full-sync is simple: we just start doing a full-sync.
The reverse change is slightly more complicated, because we need to
do one last full-sync, to get rid of routes that we configured on those
other tables.
-rw-r--r-- | src/devices/adsl/nm-device-adsl.c | 4 | ||||
-rw-r--r-- | src/devices/nm-device-ethernet.c | 4 | ||||
-rw-r--r-- | src/devices/nm-device-ppp.c | 4 | ||||
-rw-r--r-- | src/devices/nm-device-wireguard.c | 2 | ||||
-rw-r--r-- | src/devices/nm-device.c | 171 | ||||
-rw-r--r-- | src/devices/nm-device.h | 2 | ||||
-rw-r--r-- | src/devices/wwan/nm-modem.c | 4 |
7 files changed, 107 insertions, 84 deletions
diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c index 2e4dad9fee..59c87851d1 100644 --- a/src/devices/adsl/nm-device-adsl.c +++ b/src/devices/adsl/nm-device-adsl.c @@ -487,9 +487,9 @@ act_stage3_ip4_config_start (NMDevice *device, if (priv->ppp_manager) { nm_ppp_manager_set_route_parameters (priv->ppp_manager, - nm_device_get_route_table (device, AF_INET, TRUE), + nm_device_get_route_table (device, AF_INET), nm_device_get_route_metric (device, AF_INET), - nm_device_get_route_table (device, AF_INET6, TRUE), + nm_device_get_route_table (device, AF_INET6), nm_device_get_route_metric (device, AF_INET6)); } diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index f3c8f9c70a..9b2faf856f 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -1007,9 +1007,9 @@ pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *out_ if (priv->ppp_manager) { nm_ppp_manager_set_route_parameters (priv->ppp_manager, - nm_device_get_route_table (device, AF_INET, TRUE), + nm_device_get_route_table (device, AF_INET), nm_device_get_route_metric (device, AF_INET), - nm_device_get_route_table (device, AF_INET6, TRUE), + nm_device_get_route_table (device, AF_INET6), nm_device_get_route_metric (device, AF_INET6)); } diff --git a/src/devices/nm-device-ppp.c b/src/devices/nm-device-ppp.c index 0bee375c43..7a46c67d64 100644 --- a/src/devices/nm-device-ppp.c +++ b/src/devices/nm-device-ppp.c @@ -139,9 +139,9 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) if (priv->ppp_manager) { nm_ppp_manager_set_route_parameters (priv->ppp_manager, - nm_device_get_route_table (device, AF_INET, TRUE), + nm_device_get_route_table (device, AF_INET), nm_device_get_route_metric (device, AF_INET), - nm_device_get_route_table (device, AF_INET6, TRUE), + nm_device_get_route_table (device, AF_INET6), nm_device_get_route_metric (device, AF_INET6)); } diff --git a/src/devices/nm-device-wireguard.c b/src/devices/nm-device-wireguard.c index b53c6802db..228c8df08f 100644 --- a/src/devices/nm-device-wireguard.c +++ b/src/devices/nm-device-wireguard.c @@ -1301,7 +1301,7 @@ _get_dev2_ip_config (NMDeviceWireGuard *self, route_metric = nm_device_get_route_metric (NM_DEVICE (self), addr_family); - route_table_coerced = nm_platform_route_table_coerce (nm_device_get_route_table (NM_DEVICE (self), addr_family, TRUE)); + route_table_coerced = nm_platform_route_table_coerce (nm_device_get_route_table (NM_DEVICE (self), addr_family)); n_peers = nm_setting_wireguard_get_peers_len (s_wg); for (i = 0; i < n_peers; i++) { diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 2a95efdf9b..ee936d6712 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -388,6 +388,9 @@ typedef struct _NMDevicePrivate { bool v4_route_table_initialized:1; bool v6_route_table_initialized:1; + bool v4_route_table_full_sync_before:1; + bool v6_route_table_full_sync_before:1; + NMDeviceAutoconnectBlockedFlags autoconnect_blocked_flags:5; bool is_enslaved:1; @@ -2257,30 +2260,25 @@ _get_llmnr (NMDevice *self) NM_SETTING_CONNECTION_LLMNR_DEFAULT); } -guint32 -nm_device_get_route_table (NMDevice *self, - int addr_family, - gboolean fallback_main) +static guint32 +_get_route_table (NMDevice *self, + int addr_family) { - NMDevicePrivate *priv; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; NMSettingIPConfig *s_ip; guint32 route_table = 0; nm_assert_addr_family (addr_family); - g_return_val_if_fail (NM_IS_DEVICE (self), RT_TABLE_MAIN); - - priv = NM_DEVICE_GET_PRIVATE (self); - /* the route table setting affects how we sync routes. We shall * not change it while the device is active, hence, cache it. */ if (addr_family == AF_INET) { if (priv->v4_route_table_initialized) - return priv->v4_route_table ?: (fallback_main ? RT_TABLE_MAIN : 0); + return priv->v4_route_table; } else { if (priv->v6_route_table_initialized) - return priv->v6_route_table ?: (fallback_main ? RT_TABLE_MAIN : 0); + return priv->v6_route_table; } connection = nm_device_get_applied_connection (self); @@ -2288,21 +2286,16 @@ nm_device_get_route_table (NMDevice *self, s_ip = nm_connection_get_setting_ip_config (connection, addr_family); if (s_ip) route_table = nm_setting_ip_config_get_route_table (s_ip); - - /* we only lookup the global default if we also have an applied - * connection. Otherwise, the connection is not active, and the - * connection default doesn't matter. */ - if (route_table == 0) { - const char *property; - - property = addr_family == AF_INET - ? NM_CON_DEFAULT ("ipv4.route-table") - : NM_CON_DEFAULT ("ipv6.route-table"); - route_table = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA, - property, - self, - 0, G_MAXUINT32, 0); - } + } + if (route_table == 0u) { + route_table = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA, + addr_family == AF_INET + ? NM_CON_DEFAULT ("ipv4.route-table") + : NM_CON_DEFAULT ("ipv6.route-table"), + self, + 0, + G_MAXUINT32, + 0); } if (addr_family == AF_INET) { @@ -2317,9 +2310,57 @@ nm_device_get_route_table (NMDevice *self, "ipv%c.route-table = %u%s", addr_family == AF_INET ? '4' : '6', (guint) (route_table ?: RT_TABLE_MAIN), - route_table ? "" : " (policy routing not enabled)"); + route_table != 0u ? "" : " (policy routing not enabled)"); - return route_table ?: (fallback_main ? RT_TABLE_MAIN : 0); + return route_table; +} + +guint32 +nm_device_get_route_table (NMDevice *self, + int addr_family) +{ + guint32 route_table; + + g_return_val_if_fail (NM_IS_DEVICE (self), RT_TABLE_MAIN); + + route_table = _get_route_table (self, addr_family); + return route_table ?: (guint32) RT_TABLE_MAIN; +} + +static NMIPRouteTableSyncMode +_get_route_table_sync_mode_stateful (NMDevice *self, + int addr_family) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gboolean full_sync_now; + gboolean full_sync_eff; + + full_sync_now = _get_route_table (self, addr_family) != 0u; + + if (full_sync_now) + full_sync_eff = TRUE; + else { + /* When we change from full-sync to no full-sync, we do a last full-sync one + * more time. For that, we determine the effective full-state based on the + * cached/previous full-sync flag. + * + * The purpose of this is to support reapply of route-table (and thus the + * full-sync mode). If reapply toggles from full-sync to no-full-sync, we must + * sync one last time. */ + if (addr_family == AF_INET) + full_sync_eff = priv->v4_route_table_full_sync_before; + else + full_sync_eff = priv->v6_route_table_full_sync_before; + } + + if (addr_family == AF_INET) + priv->v4_route_table_full_sync_before = full_sync_now; + else + priv->v6_route_table_full_sync_before = full_sync_now; + + return full_sync_eff + ? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL + : NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN; } const NMPObject * @@ -7122,7 +7163,7 @@ ipv4ll_get_ip4_config (NMDevice *self, guint32 lla) route.network = htonl (0xE0000000L); route.plen = 4; route.rt_source = NM_IP_CONFIG_SOURCE_IP4LL; - route.table_coerced = nm_platform_route_table_coerce (nm_device_get_route_table (self, AF_INET, TRUE)); + route.table_coerced = nm_platform_route_table_coerce (nm_device_get_route_table (self, AF_INET)); route.metric = nm_device_get_route_metric (self, AF_INET); nm_ip4_config_add_route (config, &route, NULL); @@ -7291,12 +7332,12 @@ ensure_con_ip_config (NMDevice *self, int addr_family) nm_connection_get_setting_ip4_config (connection), _get_mdns (self), _get_llmnr (self), - nm_device_get_route_table (self, addr_family, TRUE), + nm_device_get_route_table (self, addr_family), nm_device_get_route_metric (self, addr_family)); } else { nm_ip6_config_merge_setting (NM_IP6_CONFIG (con_ip_config), nm_connection_get_setting_ip6_config (connection), - nm_device_get_route_table (self, addr_family, TRUE), + nm_device_get_route_table (self, addr_family), nm_device_get_route_metric (self, addr_family)); } @@ -7513,12 +7554,12 @@ ip_config_merge_and_apply (NMDevice *self, if (commit) { if (IS_IPv4) { nm_ip4_config_add_dependent_routes (NM_IP4_CONFIG (composite), - nm_device_get_route_table (self, addr_family, TRUE), + nm_device_get_route_table (self, addr_family), nm_device_get_route_metric (self, addr_family), &ip4_dev_route_blacklist); } else { nm_ip6_config_add_dependent_routes (NM_IP6_CONFIG (composite), - nm_device_get_route_table (self, addr_family, TRUE), + nm_device_get_route_table (self, addr_family), nm_device_get_route_metric (self, addr_family)); } } @@ -7712,7 +7753,7 @@ dhcp4_state_changed (NMDhcpClient *client, nm_connection_get_setting_ip4_config (connection), NM_SETTING_CONNECTION_MDNS_DEFAULT, NM_SETTING_CONNECTION_LLMNR_DEFAULT, - nm_device_get_route_table (self, AF_INET, TRUE), + nm_device_get_route_table (self, AF_INET), nm_device_get_route_metric (self, AF_INET)); configs = g_new0 (NMIP4Config *, 3); @@ -7944,7 +7985,7 @@ dhcp4_start (NMDevice *self) nm_device_get_ip_ifindex (self), hwaddr, nm_connection_get_uuid (connection), - nm_device_get_route_table (self, AF_INET, TRUE), + nm_device_get_route_table (self, AF_INET), nm_device_get_route_metric (self, AF_INET), nm_setting_ip_config_get_dhcp_send_hostname (s_ip4), nm_setting_ip_config_get_dhcp_hostname (s_ip4), @@ -8752,7 +8793,7 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) hwaddr, &ll_addr->address, nm_connection_get_uuid (connection), - nm_device_get_route_table (self, AF_INET6, TRUE), + nm_device_get_route_table (self, AF_INET6), nm_device_get_route_metric (self, AF_INET6), nm_setting_ip_config_get_dhcp_send_hostname (s_ip6), nm_setting_ip_config_get_dhcp_hostname (s_ip6), @@ -9446,7 +9487,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in rdata->gateways_n, rdata->routes, rdata->routes_n, - nm_device_get_route_table (self, AF_INET6, TRUE), + nm_device_get_route_table (self, AF_INET6), nm_device_get_route_metric (self, AF_INET6), nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF)); if (priv->ac_ip6_config.current) { @@ -9455,7 +9496,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in rdata->gateways_n, rdata->routes, rdata->routes_n, - nm_device_get_route_table (self, AF_INET6, TRUE), + nm_device_get_route_table (self, AF_INET6), nm_device_get_route_metric (self, AF_INET6), nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF)); } @@ -9947,7 +9988,7 @@ act_stage3_ip_config_start (NMDevice *self, nm_connection_get_setting_ip4_config (connection), NM_SETTING_CONNECTION_MDNS_DEFAULT, NM_SETTING_CONNECTION_LLMNR_DEFAULT, - nm_device_get_route_table (self, AF_INET, TRUE), + nm_device_get_route_table (self, AF_INET), nm_device_get_route_metric (self, AF_INET)); configs = g_new0 (NMIP4Config *, 2); configs[0] = config; @@ -11137,7 +11178,7 @@ nm_device_reactivate_ip4_config (NMDevice *self, s_ip4_new, _get_mdns (self), _get_llmnr (self), - nm_device_get_route_table (self, AF_INET, TRUE), + nm_device_get_route_table (self, AF_INET), nm_device_get_route_metric (self, AF_INET)); method_old = s_ip4_old @@ -11211,7 +11252,7 @@ nm_device_reactivate_ip6_config (NMDevice *self, priv->con_ip_config_6 = nm_device_ip6_config_new (self); nm_ip6_config_merge_setting (priv->con_ip_config_6, s_ip6_new, - nm_device_get_route_table (self, AF_INET6, TRUE), + nm_device_get_route_table (self, AF_INET6), nm_device_get_route_metric (self, AF_INET6)); method_old = s_ip6_old @@ -11287,9 +11328,12 @@ reactivate_proxy_config (NMDevice *self) } static gboolean -can_reapply_change (NMDevice *self, const char *setting_name, - NMSetting *s_old, NMSetting *s_new, - GHashTable *diffs, GError **error) +can_reapply_change (NMDevice *self, + const char *setting_name, + NMSetting *s_old, + NMSetting *s_new, + GHashTable *diffs, + GError **error) { if (nm_streq (setting_name, NM_SETTING_CONNECTION_SETTING_NAME)) { /* Whitelist allowed properties from "connection" setting which are @@ -11312,32 +11356,9 @@ can_reapply_change (NMDevice *self, const char *setting_name, NM_SETTING_CONNECTION_MDNS, NM_SETTING_CONNECTION_LLMNR); } else if (NM_IN_STRSET (setting_name, - NM_SETTING_PROXY_SETTING_NAME)) { - return TRUE; - } else if (NM_IN_STRSET (setting_name, + NM_SETTING_PROXY_SETTING_NAME, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_SETTING_NAME)) { - if (g_hash_table_contains (diffs, NM_SETTING_IP_CONFIG_ROUTE_TABLE)) { - /* changing the route-table setting is complicated, because it affects - * how we sync the routes. Don't support changing it without full - * re-activation. - * - * The problem is really that changing the setting also affects the sync - * mode. So, switching from NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN to - * NM_IP_ROUTE_TABLE_SYNC_MODE_FULL would somehow require us to get rid - * of additional routes, but we don't know which routes were added by NM - * and which should be removed. - * - * Note how nm_device_get_route_table() caches the value for the duration of the - * activation. */ - g_set_error (error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, - "Can't reapply changes to '%s.%s' setting", - setting_name, - NM_SETTING_IP_CONFIG_ROUTE_TABLE); - return FALSE; - } return TRUE; } else { g_set_error (error, @@ -11483,6 +11504,9 @@ check_and_reapply_connection (NMDevice *self, priv->v4_commit_first_time = TRUE; priv->v6_commit_first_time = TRUE; + priv->v4_route_table_initialized = FALSE; + priv->v6_route_table_initialized = FALSE; + /************************************************************************** * Reapply changes *************************************************************************/ @@ -12285,9 +12309,7 @@ nm_device_set_ip_config (NMDevice *self, if (IS_IPv4) { success = nm_ip4_config_commit (NM_IP4_CONFIG (new_config), nm_device_get_platform (self), - nm_device_get_route_table (self, addr_family, FALSE) - ? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL - : NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN); + _get_route_table_sync_mode_stateful (self, addr_family)); nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self), nm_ip_config_get_ifindex (new_config), ip4_dev_route_blacklist); @@ -12296,9 +12318,7 @@ nm_device_set_ip_config (NMDevice *self, success = nm_ip6_config_commit (NM_IP6_CONFIG (new_config), nm_device_get_platform (self), - nm_device_get_route_table (self, addr_family, FALSE) - ? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL - : NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN, + _get_route_table_sync_mode_stateful (self, addr_family), &temporary_not_available); if (!_rt6_temporary_not_available_set (self, temporary_not_available)) @@ -14528,6 +14548,9 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) priv->v4_route_table_initialized = FALSE; priv->v6_route_table_initialized = FALSE; + priv->v4_route_table_full_sync_before = FALSE; + priv->v6_route_table_full_sync_before = FALSE; + priv->default_route_metric_penalty_ip4_has = FALSE; priv->default_route_metric_penalty_ip6_has = FALSE; diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index f7b187f7e8..2108b134e9 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -496,7 +496,7 @@ NMDeviceType nm_device_get_device_type (NMDevice *dev); NMLinkType nm_device_get_link_type (NMDevice *dev); NMMetered nm_device_get_metered (NMDevice *dev); -guint32 nm_device_get_route_table (NMDevice *self, int addr_family, gboolean fallback_main); +guint32 nm_device_get_route_table (NMDevice *self, int addr_family); guint32 nm_device_get_route_metric (NMDevice *dev, int addr_family); guint32 nm_device_get_route_metric_default (NMDeviceType device_type); diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index 19e210a726..617096a76a 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -1574,9 +1574,9 @@ nm_modem_set_route_parameters_from_device (NMModem *self, g_return_if_fail (NM_IS_DEVICE (device)); nm_modem_set_route_parameters (self, - nm_device_get_route_table (device, AF_INET, TRUE), + nm_device_get_route_table (device, AF_INET), nm_device_get_route_metric (device, AF_INET), - nm_device_get_route_table (device, AF_INET6, TRUE), + nm_device_get_route_table (device, AF_INET6), nm_device_get_route_metric (device, AF_INET6)); } |