From de0f893c14d6f904b66295dc9703f5e6ec3f5add Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 13 Jul 2015 19:15:05 +0200 Subject: [PATCH 1/8] route-manager/trivial: fix naming of local variable (cherry picked from commit b9bc960e974bbf6b26fbd992926e022e61f41950) --- src/nm-route-manager.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c index 975c95b887..a83a0379ae 100644 --- a/src/nm-route-manager.c +++ b/src/nm-route-manager.c @@ -796,7 +796,7 @@ next: * we need to know whether a route is shadowed by another route, and that * requires to look at @ipx_routes. */ for (; cur_ipx_route; cur_ipx_route = _get_next_ipx_route (ipx_routes->index, FALSE, &i_ipx_routes, ifindex)) { - int route_id_dest_result = -1; + int route_dest_cmp_result = -1; if ( (i_type == 0 && !VTABLE_IS_DEVICE_ROUTE (vtable, cur_ipx_route)) || (i_type == 1 && VTABLE_IS_DEVICE_ROUTE (vtable, cur_ipx_route))) { @@ -814,8 +814,8 @@ next: /* skip over @plat_routes that are ordered before our @cur_ipx_route. */ while ( cur_plat_route - && (route_id_dest_result = vtable->route_dest_cmp (cur_plat_route, cur_ipx_route)) <= 0) { - if ( route_id_dest_result == 0 + && (route_dest_cmp_result = vtable->route_dest_cmp (cur_plat_route, cur_ipx_route)) <= 0) { + if ( route_dest_cmp_result == 0 && cur_plat_route->rx.metric >= *p_effective_metric) break; cur_plat_route = _get_next_plat_route (plat_routes_idx, FALSE, &i_plat_routes); @@ -824,7 +824,7 @@ next: /* only add the route if we don't have an identical route in @plat_routes, * i.e. if @cur_plat_route is different from @cur_ipx_route. */ if ( !cur_plat_route - || route_id_dest_result != 0 + || route_dest_cmp_result != 0 || !_route_equals_ignoring_ifindex (vtable, cur_plat_route, cur_ipx_route, *p_effective_metric)) { if (!vtable->vt->route_add (priv->platform, ifindex, cur_ipx_route, *p_effective_metric)) { From b159b668b3b1beb9017ee7d92314010c274ef650 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 13 Jul 2015 19:16:19 +0200 Subject: [PATCH 2/8] route-manager: add argument to to only remove routes that were added by NMRouteManager Add an argument @full_sync to the sync method of NMRouteManager. @full_sync was what we did up to now, meaning, we removed every route on the interface that was no on our internal list of known routes. Now with !@full_sync, only remove routes that were tracked previously. This means, we will only remove routes that were added by us previously. Don't make use of the new option yet. So there is no change of behavior yet. (cherry picked from commit 65f2090cc2341d4287b13751ac7bdd0b15039cac) --- src/nm-ip4-config.c | 2 +- src/nm-ip6-config.c | 2 +- src/nm-route-manager.c | 132 ++++++++++++++++++++++++--------- src/nm-route-manager.h | 4 +- src/tests/test-route-manager.c | 12 +-- 5 files changed, 105 insertions(+), 47 deletions(-) diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index e32f750395..3168abd337 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -323,7 +323,7 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gint64 default_rou nm_route_manager_ip4_route_register_device_route_purge_list (nm_route_manager_get (), device_route_purge_list); - success = nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, default_route_metric < 0); + success = nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, default_route_metric < 0, TRUE); g_array_unref (routes); if (!success) return FALSE; diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 2f3dc3f487..369276a7bd 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -398,7 +398,7 @@ nm_ip6_config_commit (const NMIP6Config *config, int ifindex) g_array_append_vals (routes, route, 1); } - success = nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + success = nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); g_array_unref (routes); } diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c index a83a0379ae..a501bb25fc 100644 --- a/src/nm-route-manager.c +++ b/src/nm-route-manager.c @@ -445,7 +445,7 @@ _sort_indexes_cmp (guint *a, guint *b) /*********************************************************************************************/ static gboolean -_vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes) +_vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes, gboolean full_sync) { NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (self); GArray *plat_routes; @@ -543,6 +543,53 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const cur_known_route = _get_next_known_route (vtable, known_routes_idx, FALSE, &i_known_routes); } + if (!full_sync && to_delete_indexes) { + /*************************************************************************** + * Delete routes in platform, that we are about to remove from @ipx_routes + * + * When doing a non-full_sync, we delete routes from platform that were previously + * known by route-manager, and are now deleted. + ***************************************************************************/ + + /* iterate over @to_delete_indexes and @plat_routes. + * @to_delete_indexes contains the indexes (relative to ipx_routes->index) of items + * we are about to delete. */ + cur_plat_route = _get_next_plat_route (plat_routes_idx, TRUE, &i_plat_routes); + for (i = 0; i < to_delete_indexes->len; i++) { + int route_dest_cmp_result = 0; + i_ipx_routes = g_array_index (to_delete_indexes, guint, i); + cur_ipx_route = ipx_routes->index->entries[i_ipx_routes]; + p_effective_metric = &effective_metrics[i_ipx_routes]; + + nm_assert (cur_ipx_route->rx.ifindex == ifindex); + + if (*p_effective_metric == -1) + continue; + + /* skip over @plat_routes that are ordered before our @cur_ipx_route. */ + while ( cur_plat_route + && (route_dest_cmp_result = vtable->route_dest_cmp (cur_plat_route, cur_ipx_route)) <= 0) { + if ( route_dest_cmp_result == 0 + && cur_plat_route->rx.metric >= *p_effective_metric) + break; + cur_plat_route = _get_next_plat_route (plat_routes_idx, FALSE, &i_plat_routes); + } + + if (!cur_plat_route) { + /* no more platform routes. Break the loop. */ + break; + } + + if ( route_dest_cmp_result == 0 + && cur_plat_route->rx.metric == *p_effective_metric) { + /* we are about to delete cur_ipx_route and we have a matching route + * in platform. Delete it. */ + _LOGT (vtable->vt->addr_family, "%3d: platform rt-rm #%u - %s", ifindex, i_plat_routes, vtable->vt->route_to_string (cur_plat_route)); + vtable->vt->route_delete (priv->platform, ifindex, cur_plat_route); + } + } + } + /* Update @ipx_routes with the just learned changes. */ if (to_delete_indexes || to_add_routes) { if (to_delete_indexes) { @@ -665,42 +712,47 @@ next: } } - /*************************************************************************** - * Delete routes in platform, that no longer exist in @ipx_routes - ***************************************************************************/ + if (full_sync) { + /*************************************************************************** + * Delete all routes in platform, that no longer exist in @ipx_routes + * + * Different from the delete action above, we delete every unknown route on + * the interface. + ***************************************************************************/ - /* iterate over @plat_routes and @ipx_routes */ - cur_plat_route = _get_next_plat_route (plat_routes_idx, TRUE, &i_plat_routes); - cur_ipx_route = _get_next_ipx_route (ipx_routes->index, TRUE, &i_ipx_routes, ifindex); - if (cur_ipx_route) - p_effective_metric = &effective_metrics[i_ipx_routes]; - while (cur_plat_route) { - int route_dest_cmp_result = 0; + /* iterate over @plat_routes and @ipx_routes */ + cur_plat_route = _get_next_plat_route (plat_routes_idx, TRUE, &i_plat_routes); + cur_ipx_route = _get_next_ipx_route (ipx_routes->index, TRUE, &i_ipx_routes, ifindex); + if (cur_ipx_route) + p_effective_metric = &effective_metrics[i_ipx_routes]; + while (cur_plat_route) { + int route_dest_cmp_result = 0; - g_assert (cur_plat_route->rx.ifindex == ifindex); + g_assert (cur_plat_route->rx.ifindex == ifindex); - _LOGT (vtable->vt->addr_family, "%3d: platform rt #%u - %s", ifindex, i_plat_routes, vtable->vt->route_to_string (cur_plat_route)); + _LOGT (vtable->vt->addr_family, "%3d: platform rt #%u - %s", ifindex, i_plat_routes, vtable->vt->route_to_string (cur_plat_route)); - /* skip over @cur_ipx_route that are ordered before @cur_plat_route */ - while ( cur_ipx_route - && ((route_dest_cmp_result = vtable->route_dest_cmp (cur_ipx_route, cur_plat_route)) <= 0)) { - if ( route_dest_cmp_result == 0 - && *p_effective_metric != -1 - && *p_effective_metric >= cur_plat_route->rx.metric) { - break; + /* skip over @cur_ipx_route that are ordered before @cur_plat_route */ + while ( cur_ipx_route + && ((route_dest_cmp_result = vtable->route_dest_cmp (cur_ipx_route, cur_plat_route)) <= 0)) { + if ( route_dest_cmp_result == 0 + && *p_effective_metric != -1 + && *p_effective_metric >= cur_plat_route->rx.metric) { + break; + } + cur_ipx_route = _get_next_ipx_route (ipx_routes->index, FALSE, &i_ipx_routes, ifindex); + if (cur_ipx_route) + p_effective_metric = &effective_metrics[i_ipx_routes]; } - cur_ipx_route = _get_next_ipx_route (ipx_routes->index, FALSE, &i_ipx_routes, ifindex); - if (cur_ipx_route) - p_effective_metric = &effective_metrics[i_ipx_routes]; + + /* if @cur_ipx_route is not equal to @plat_route, the route must be deleted. */ + if ( !cur_ipx_route + || route_dest_cmp_result != 0 + || *p_effective_metric != cur_plat_route->rx.metric) + vtable->vt->route_delete (priv->platform, ifindex, cur_plat_route); + + cur_plat_route = _get_next_plat_route (plat_routes_idx, FALSE, &i_plat_routes); } - - /* if @cur_ipx_route is not equal to @plat_route, the route must be deleted. */ - if ( !cur_ipx_route - || route_dest_cmp_result != 0 - || *p_effective_metric != cur_plat_route->rx.metric) - vtable->vt->route_delete (priv->platform, ifindex, cur_plat_route); - - cur_plat_route = _get_next_plat_route (plat_routes_idx, FALSE, &i_plat_routes); } /*************************************************************************** @@ -855,6 +907,9 @@ next: * @ifindex: Interface index * @known_routes: List of routes * @ignore_kernel_routes: if %TRUE, ignore kernel routes. + * @full_sync: whether to do a full sync and delete routes + * that are configured on the interface but not currently + * tracked by route-manager. * * A convenience function to synchronize routes for a specific interface * with the least possible disturbance. It simply removes routes that are @@ -865,9 +920,9 @@ next: * Returns: %TRUE on success. */ gboolean -nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes) +nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes, gboolean full_sync) { - return _vx_route_sync (&vtable_v4, self, ifindex, known_routes, ignore_kernel_routes); + return _vx_route_sync (&vtable_v4, self, ifindex, known_routes, ignore_kernel_routes, full_sync); } /** @@ -875,6 +930,9 @@ nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray * @ifindex: Interface index * @known_routes: List of routes * @ignore_kernel_routes: if %TRUE, ignore kernel routes. + * @full_sync: whether to do a full sync and delete routes + * that are configured on the interface but not currently + * tracked by route-manager. * * A convenience function to synchronize routes for a specific interface * with the least possible disturbance. It simply removes routes that are @@ -885,16 +943,16 @@ nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray * Returns: %TRUE on success. */ gboolean -nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes) +nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes, gboolean full_sync) { - return _vx_route_sync (&vtable_v6, self, ifindex, known_routes, ignore_kernel_routes); + return _vx_route_sync (&vtable_v6, self, ifindex, known_routes, ignore_kernel_routes, full_sync); } gboolean nm_route_manager_route_flush (NMRouteManager *self, int ifindex) { - return nm_route_manager_ip4_route_sync (self, ifindex, NULL, FALSE) - && nm_route_manager_ip6_route_sync (self, ifindex, NULL, FALSE); + return nm_route_manager_ip4_route_sync (self, ifindex, NULL, FALSE, TRUE) + && nm_route_manager_ip6_route_sync (self, ifindex, NULL, FALSE, TRUE); } /*********************************************************************************************/ diff --git a/src/nm-route-manager.h b/src/nm-route-manager.h index fdd310b73b..1e4ce4840f 100644 --- a/src/nm-route-manager.h +++ b/src/nm-route-manager.h @@ -42,8 +42,8 @@ typedef struct { GType nm_route_manager_get_type (void); -gboolean nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes); -gboolean nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes); +gboolean nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes, gboolean full_sync); +gboolean nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes, gboolean full_sync); gboolean nm_route_manager_route_flush (NMRouteManager *self, int ifindex); void nm_route_manager_ip4_route_register_device_route_purge_list (NMRouteManager *self, GArray *device_route_purge_list); diff --git a/src/tests/test-route-manager.c b/src/tests/test-route-manager.c index 5875e7fc11..0ea515f9ea 100644 --- a/src/tests/test-route-manager.c +++ b/src/tests/test-route-manager.c @@ -61,7 +61,7 @@ setup_dev0_ip4 (int ifindex, guint mss_of_first_route, guint32 metric_of_second_ route.mss = 0; g_array_append_val (routes, route); - nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); g_array_free (routes, TRUE); } @@ -107,7 +107,7 @@ setup_dev1_ip4 (int ifindex) route.metric = 22; g_array_append_val (routes, route); - nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); g_array_free (routes, TRUE); } @@ -134,7 +134,7 @@ update_dev0_ip4 (int ifindex) route.metric = 21; g_array_append_val (routes, route); - nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); g_array_free (routes, TRUE); } @@ -409,7 +409,7 @@ setup_dev0_ip6 (int ifindex) 0); g_array_append_val (routes, *route); - nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); g_array_free (routes, TRUE); } @@ -466,7 +466,7 @@ setup_dev1_ip6 (int ifindex) 0); g_array_append_val (routes, *route); - nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); g_array_free (routes, TRUE); } @@ -513,7 +513,7 @@ update_dev0_ip6 (int ifindex) 0); g_array_append_val (routes, *route); - nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE); + nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); g_array_free (routes, TRUE); } From 49a7418d33ce329475cfc75481b7ad2f58a48e85 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 13 Jul 2015 19:20:08 +0200 Subject: [PATCH 3/8] routes/trival: add argument @routes_full_sync to IP config commit The argument is still unused, so no behavioral change yet. (cherry picked from commit 6124f5b94a7bc471803e8f8e384f182f708d839a) --- src/devices/nm-device.c | 5 ++++- src/nm-iface-helper.c | 4 ++-- src/nm-ip4-config.c | 4 ++-- src/nm-ip4-config.h | 2 +- src/nm-ip6-config.c | 4 ++-- src/nm-ip6-config.h | 2 +- src/vpn-manager/nm-vpn-connection.c | 5 ++++- 7 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 2dd40f7b46..ebba307f15 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -6345,6 +6345,7 @@ nm_device_set_ip4_config (NMDevice *self, * FIXME: this is wrong in case where "assumed" means "take-over-seamlessly". In this * case, we should manage the device route, for example on new DHCP lease. */ success = nm_ip4_config_commit (new_config, ip_ifindex, + TRUE, assumed ? (gint64) -1 : (gint64) default_route_metric); if (!success) reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED; @@ -6471,7 +6472,9 @@ nm_device_set_ip6_config (NMDevice *self, /* Always commit to nm-platform to update lifetimes */ if (commit && new_config) { nm_device_ipv6_set_mtu (self, priv->ip6_mtu); - success = nm_ip6_config_commit (new_config, ip_ifindex); + success = nm_ip6_config_commit (new_config, + ip_ifindex, + TRUE); if (!success) reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED; } diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index 5d5142b851..2192f36ba5 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -104,7 +104,7 @@ dhcp4_state_changed (NMDhcpClient *client, nm_ip4_config_subtract (existing, last_config); nm_ip4_config_merge (existing, ip4_config); - if (!nm_ip4_config_commit (existing, ifindex, global_opt.priority_v4)) + if (!nm_ip4_config_commit (existing, ifindex, TRUE, global_opt.priority_v4)) nm_log_warn (LOGD_DHCP4, "(%s): failed to apply DHCPv4 config", global_opt.ifname); if (last_config) @@ -241,7 +241,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da nm_ip6_config_subtract (existing, last_config); nm_ip6_config_merge (existing, ip6_config); - if (!nm_ip6_config_commit (existing, ifindex)) + if (!nm_ip6_config_commit (existing, ifindex, TRUE)) nm_log_warn (LOGD_IP6, "(%s): failed to apply IPv6 config", global_opt.ifname); if (last_config) diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 3168abd337..db8c4b43e6 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -254,7 +254,7 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf) } gboolean -nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gint64 default_route_metric) +nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_full_sync, gint64 default_route_metric) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); int i; @@ -323,7 +323,7 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gint64 default_rou nm_route_manager_ip4_route_register_device_route_purge_list (nm_route_manager_get (), device_route_purge_list); - success = nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, default_route_metric < 0, TRUE); + success = nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, default_route_metric < 0, routes_full_sync); g_array_unref (routes); if (!success) return FALSE; diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index cd6efcc5c5..463675244e 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -64,7 +64,7 @@ const char * nm_ip4_config_get_dbus_path (const NMIP4Config *config); /* Integration with nm-platform and nm-setting */ NMIP4Config *nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf); -gboolean nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gint64 default_route_metric); +gboolean nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_full_sync, gint64 default_route_metric); void nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, guint32 default_route_metric); NMSetting *nm_ip4_config_create_setting (const NMIP4Config *config); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 369276a7bd..48aeb64aee 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -367,7 +367,7 @@ nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6Co } gboolean -nm_ip6_config_commit (const NMIP6Config *config, int ifindex) +nm_ip6_config_commit (const NMIP6Config *config, int ifindex, gboolean routes_full_sync) { NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); int i; @@ -398,7 +398,7 @@ nm_ip6_config_commit (const NMIP6Config *config, int ifindex) g_array_append_vals (routes, route, 1); } - success = nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, TRUE); + success = nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE, routes_full_sync); g_array_unref (routes); } diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 04c9e00341..66f15888c2 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -64,7 +64,7 @@ const char * nm_ip6_config_get_dbus_path (const NMIP6Config *config); /* Integration with nm-platform and nm-setting */ NMIP6Config *nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6ConfigPrivacy use_temporary); -gboolean nm_ip6_config_commit (const NMIP6Config *config, int ifindex); +gboolean nm_ip6_config_commit (const NMIP6Config *config, int ifindex, gboolean routes_full_sync); void nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, guint32 default_route_metric); NMSetting *nm_ip6_config_create_setting (const NMIP6Config *config); diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 30c2d9fcc9..795a81873c 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -969,12 +969,15 @@ nm_vpn_connection_apply_config (NMVpnConnection *connection) if (priv->ip4_config) { if (!nm_ip4_config_commit (priv->ip4_config, priv->ip_ifindex, + TRUE, nm_vpn_connection_get_ip4_route_metric (connection))) return FALSE; } if (priv->ip6_config) { - if (!nm_ip6_config_commit (priv->ip6_config, priv->ip_ifindex)) + if (!nm_ip6_config_commit (priv->ip6_config, + priv->ip_ifindex, + TRUE)) return FALSE; } } From 150dd2adc63f55c4fd10f2f651175617a5122cb3 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 13 Jul 2015 19:20:08 +0200 Subject: [PATCH 4/8] routes: fix race syncing routes by not doing full-sync In most cases, when syncing routes, we should only remove routes that were configured by us previously. Otherwise, there is a race that we can remove routes added externally. Now, when applying IP configuration for a device, only do a full-sync at the first time when we activate the device. Later on, only remove routes that were added by us. (cherry picked from commit 8b015826e62022ae0a66afb92fd182f77cbb644b) --- src/devices/nm-device.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index ebba307f15..c5d4c20392 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -345,6 +345,7 @@ static gboolean nm_device_set_ip4_config (NMDevice *self, NMIP4Config *config, guint32 default_route_metric, gboolean commit, + gboolean routes_full_sync, NMDeviceStateReason *reason); static gboolean ip4_config_merge_and_apply (NMDevice *self, NMIP4Config *config, @@ -354,6 +355,7 @@ static gboolean ip4_config_merge_and_apply (NMDevice *self, static gboolean nm_device_set_ip6_config (NMDevice *self, NMIP6Config *config, gboolean commit, + gboolean routes_full_sync, NMDeviceStateReason *reason); static gboolean nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure); @@ -3215,6 +3217,7 @@ ip4_config_merge_and_apply (NMDevice *self, const guint32 default_route_metric = nm_device_get_ip4_route_metric (self); guint32 gateway; gboolean connection_has_default_route, connection_is_never_default; + gboolean routes_full_sync; /* Merge all the configs into the composite config */ if (config) { @@ -3279,6 +3282,10 @@ ip4_config_merge_and_apply (NMDevice *self, priv->default_route.v4_has = FALSE; priv->default_route.v4_is_assumed = TRUE; + routes_full_sync = commit + && priv->default_route.v4_configure_first_time + && !nm_device_uses_assumed_connection (self); + if (!commit) { /* during a non-commit event, we always pickup whatever is configured. */ goto END_ADD_DEFAULT_ROUTE; @@ -3358,7 +3365,7 @@ END_ADD_DEFAULT_ROUTE: NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite); } - success = nm_device_set_ip4_config (self, composite, default_route_metric, commit, out_reason); + success = nm_device_set_ip4_config (self, composite, default_route_metric, commit, routes_full_sync, out_reason); g_object_unref (composite); return success; } @@ -3829,6 +3836,7 @@ ip6_config_merge_and_apply (NMDevice *self, gboolean has_direct_route; const struct in6_addr *gateway; gboolean connection_has_default_route, connection_is_never_default; + gboolean routes_full_sync; /* If no config was passed in, create a new one */ composite = nm_ip6_config_new (); @@ -3890,6 +3898,10 @@ ip6_config_merge_and_apply (NMDevice *self, priv->default_route.v6_has = FALSE; priv->default_route.v6_is_assumed = TRUE; + routes_full_sync = commit + && priv->default_route.v6_configure_first_time + && !nm_device_uses_assumed_connection (self); + if (!commit) { /* during a non-commit event, we always pickup whatever is configured. */ goto END_ADD_DEFAULT_ROUTE; @@ -3972,7 +3984,7 @@ END_ADD_DEFAULT_ROUTE: NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit (self, composite); } - success = nm_device_set_ip6_config (self, composite, commit, out_reason); + success = nm_device_set_ip6_config (self, composite, commit, routes_full_sync, out_reason); g_object_unref (composite); return success; } @@ -6317,6 +6329,7 @@ nm_device_set_ip4_config (NMDevice *self, NMIP4Config *new_config, guint32 default_route_metric, gboolean commit, + gboolean routes_full_sync, NMDeviceStateReason *reason) { NMDevicePrivate *priv; @@ -6345,7 +6358,7 @@ nm_device_set_ip4_config (NMDevice *self, * FIXME: this is wrong in case where "assumed" means "take-over-seamlessly". In this * case, we should manage the device route, for example on new DHCP lease. */ success = nm_ip4_config_commit (new_config, ip_ifindex, - TRUE, + routes_full_sync, assumed ? (gint64) -1 : (gint64) default_route_metric); if (!success) reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED; @@ -6451,6 +6464,7 @@ static gboolean nm_device_set_ip6_config (NMDevice *self, NMIP6Config *new_config, gboolean commit, + gboolean routes_full_sync, NMDeviceStateReason *reason) { NMDevicePrivate *priv; @@ -6474,7 +6488,7 @@ nm_device_set_ip6_config (NMDevice *self, nm_device_ipv6_set_mtu (self, priv->ip6_mtu); success = nm_ip6_config_commit (new_config, ip_ifindex, - TRUE); + routes_full_sync); if (!success) reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED; } @@ -7853,8 +7867,8 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) /* Clean up IP configs; this does not actually deconfigure the * interface; the caller must flush routes and addresses explicitly. */ - nm_device_set_ip4_config (self, NULL, 0, TRUE, &ignored); - nm_device_set_ip6_config (self, NULL, TRUE, &ignored); + nm_device_set_ip4_config (self, NULL, 0, TRUE, TRUE, &ignored); + nm_device_set_ip6_config (self, NULL, TRUE, TRUE, &ignored); g_clear_object (&priv->con_ip4_config); g_clear_object (&priv->dev_ip4_config); g_clear_object (&priv->ext_ip4_config); From cf7529b66cdb4ff921eac1afcae88aa598e7e6a1 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 14 Jul 2015 13:34:54 +0200 Subject: [PATCH 5/8] route-manager: align trace logging statement (cherry picked from commit 7bda97092826147f9799f9372e98315637ae17a7) --- src/nm-route-manager.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c index a501bb25fc..5ee6c8654f 100644 --- a/src/nm-route-manager.c +++ b/src/nm-route-manager.c @@ -484,7 +484,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const ifindex, i, vtable->vt->route_to_string (VTABLE_ROUTE_INDEX (vtable, known_routes, i))); } for (i = 0; i < ipx_routes->index->len; i++) - _LOGT (vtable->vt->addr_family, "%3d: STATE: has #%u - %s (%lld)", + _LOGT (vtable->vt->addr_family, "%3d: STATE: has #%u - %s (%lld)", ifindex, i, vtable->vt->route_to_string (ipx_routes->index->entries[i]), (long long) g_array_index (ipx_routes->effective_metrics, gint64, i)); @@ -526,7 +526,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const cur_ipx_route->rx.ifindex = ifindex; cur_ipx_route->rx.metric = vtable->vt->metric_normalize (cur_ipx_route->rx.metric); ipx_routes_changed = TRUE; - _LOGT (vtable->vt->addr_family, "%3d: STATE: update #%u - %s", ifindex, i_ipx_routes, vtable->vt->route_to_string (cur_ipx_route)); + _LOGT (vtable->vt->addr_family, "%3d: STATE: update #%u - %s", ifindex, i_ipx_routes, vtable->vt->route_to_string (cur_ipx_route)); } } else if (cur_known_route) { g_assert (!cur_ipx_route || route_id_cmp_result > 0); @@ -596,7 +596,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const for (i = 0; i < to_delete_indexes->len; i++) { guint idx = g_array_index (to_delete_indexes, guint, i); - _LOGT (vtable->vt->addr_family, "%3d: STATE: delete #%u - %s", ifindex, idx, vtable->vt->route_to_string (ipx_routes->index->entries[idx])); + _LOGT (vtable->vt->addr_family, "%3d: STATE: delete #%u - %s", ifindex, idx, vtable->vt->route_to_string (ipx_routes->index->entries[idx])); g_array_index (to_delete_indexes, guint, i) = _route_index_reverse_idx (vtable, ipx_routes->index, idx, ipx_routes->entries); } g_array_sort (to_delete_indexes, (GCompareFunc) _sort_indexes_cmp); @@ -620,7 +620,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const g_array_index (ipx_routes->effective_metrics_reverse, gint64, j++) = -1; - _LOGT (vtable->vt->addr_family, "%3d: STATE: added #%u - %s", ifindex, ipx_routes->entries->len - 1, vtable->vt->route_to_string (ipx_route)); + _LOGT (vtable->vt->addr_family, "%3d: STATE: added #%u - %s", ifindex, ipx_routes->entries->len - 1, vtable->vt->route_to_string (ipx_route)); } g_ptr_array_unref (to_add_routes); } @@ -705,7 +705,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const break; } next: - _LOGT (vtable->vt->addr_family, "%3d: new metric #%u - %s (%lld)", + _LOGT (vtable->vt->addr_family, "%3d: new metric #%u - %s (%lld)", ifindex, i_ipx_routes, vtable->vt->route_to_string (cur_ipx_route), (long long) *p_effective_metric); @@ -730,7 +730,7 @@ next: g_assert (cur_plat_route->rx.ifindex == ifindex); - _LOGT (vtable->vt->addr_family, "%3d: platform rt #%u - %s", ifindex, i_plat_routes, vtable->vt->route_to_string (cur_plat_route)); + _LOGT (vtable->vt->addr_family, "%3d: platform rt #%u - %s", ifindex, i_plat_routes, vtable->vt->route_to_string (cur_plat_route)); /* skip over @cur_ipx_route that are ordered before @cur_plat_route */ while ( cur_ipx_route From 642c38b26b4a3eb3c87c96a94dac397a47a177ee Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 14 Jul 2015 12:37:58 +0200 Subject: [PATCH 6/8] platform: replace addr/route exists() functions by get() Rename exists() functions to get() and return the cached platform object. (cherry picked from commit 6f8fcd2f47541ff78aa83c584a731fedec6e3a8f) --- src/platform/nm-fake-platform.c | 40 +++++++++----------------- src/platform/nm-linux-platform.c | 48 ++++++++++++++++++++----------- src/platform/nm-platform.c | 30 ++++++++----------- src/platform/nm-platform.h | 16 +++++------ src/platform/tests/platform.c | 20 ++++++------- src/platform/tests/test-address.c | 28 +++++++++--------- src/platform/tests/test-common.c | 2 +- src/platform/tests/test-route.c | 10 +++---- 8 files changed, 96 insertions(+), 98 deletions(-) diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index 147e956167..d5aeb0301f 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -992,8 +992,8 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int return TRUE; } -static gboolean -ip4_address_exists (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) +static const NMPlatformIP4Address * +ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); int i; @@ -1002,14 +1002,14 @@ ip4_address_exists (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) NMPlatformIP4Address *address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i); if (address->ifindex == ifindex && address->plen == plen && address->address == addr) - return TRUE; + return address; } - return FALSE; + return NULL; } -static gboolean -ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) +static const NMPlatformIP6Address * +ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); int i; @@ -1019,10 +1019,10 @@ ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int if (address->ifindex == ifindex && address->plen == plen && IN6_ARE_ADDR_EQUAL (&address->address, &addr)) - return TRUE; + return address; } - return FALSE; + return NULL; } /******************************************************************/ @@ -1271,7 +1271,7 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source, return TRUE; } -static NMPlatformIP4Route * +static const NMPlatformIP4Route * ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); @@ -1290,7 +1290,7 @@ ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, g return NULL; } -static NMPlatformIP6Route * +static const NMPlatformIP6Route * ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); @@ -1311,18 +1311,6 @@ ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int p return NULL; } -static gboolean -ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric) -{ - return !!ip4_route_get (platform, ifindex, network, plen, metric); -} - -static gboolean -ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric) -{ - return !!ip6_route_get (platform, ifindex, network, plen, metric); -} - /******************************************************************/ static void @@ -1453,21 +1441,21 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass) platform_class->mesh_set_channel = mesh_set_channel; platform_class->mesh_set_ssid = mesh_set_ssid; + platform_class->ip4_address_get = ip4_address_get; + platform_class->ip6_address_get = ip6_address_get; platform_class->ip4_address_get_all = ip4_address_get_all; platform_class->ip6_address_get_all = ip6_address_get_all; platform_class->ip4_address_add = ip4_address_add; platform_class->ip6_address_add = ip6_address_add; platform_class->ip4_address_delete = ip4_address_delete; platform_class->ip6_address_delete = ip6_address_delete; - platform_class->ip4_address_exists = ip4_address_exists; - platform_class->ip6_address_exists = ip6_address_exists; + platform_class->ip4_route_get = ip4_route_get; + platform_class->ip6_route_get = ip6_route_get; platform_class->ip4_route_get_all = ip4_route_get_all; platform_class->ip6_route_get_all = ip6_route_get_all; platform_class->ip4_route_add = ip4_route_add; platform_class->ip6_route_add = ip6_route_add; platform_class->ip4_route_delete = ip4_route_delete; platform_class->ip6_route_delete = ip6_route_delete; - platform_class->ip4_route_exists = ip4_route_exists; - platform_class->ip6_route_exists = ip6_route_exists; } diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 677f7add05..80757f4ef9 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -4164,22 +4164,30 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int return do_delete_object (platform, &obj_needle, NULL); } -static gboolean -ip4_address_exists (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) +static const NMPlatformIP4Address * +ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) { NMPObject obj_needle; + const NMPObject *obj; nmp_object_stackinit_id_ip4_address (&obj_needle, ifindex, addr, plen); - return nmp_object_is_visible (nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle)); + obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle); + if (nmp_object_is_visible (obj)) + return &obj->ip4_address; + return NULL; } -static gboolean -ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) +static const NMPlatformIP6Address * +ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) { NMPObject obj_needle; + const NMPObject *obj; nmp_object_stackinit_id_ip6_address (&obj_needle, ifindex, &addr, plen); - return nmp_object_is_visible (nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle)); + obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle); + if (nmp_object_is_visible (obj)) + return &obj->ip6_address; + return NULL; } /******************************************************************/ @@ -4462,24 +4470,32 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, in return do_delete_object (platform, &obj_needle, nlo); } -static gboolean -ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric) +static const NMPlatformIP4Route * +ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric) { NMPObject obj_needle; + const NMPObject *obj; nmp_object_stackinit_id_ip4_route (&obj_needle, ifindex, network, plen, metric); - return nmp_object_is_visible (nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle)); + obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle); + if (nmp_object_is_visible (obj)) + return &obj->ip4_route; + return NULL; } -static gboolean -ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric) +static const NMPlatformIP6Route * +ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric) { NMPObject obj_needle; + const NMPObject *obj; metric = nm_utils_ip6_route_metric_normalize (metric); nmp_object_stackinit_id_ip6_route (&obj_needle, ifindex, &network, plen, metric); - return nmp_object_is_visible (nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle)); + obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle); + if (nmp_object_is_visible (obj)) + return &obj->ip6_route; + return NULL; } /******************************************************************/ @@ -4986,23 +5002,23 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->mesh_set_channel = mesh_set_channel; platform_class->mesh_set_ssid = mesh_set_ssid; + platform_class->ip4_address_get = ip4_address_get; + platform_class->ip6_address_get = ip6_address_get; platform_class->ip4_address_get_all = ip4_address_get_all; platform_class->ip6_address_get_all = ip6_address_get_all; platform_class->ip4_address_add = ip4_address_add; platform_class->ip6_address_add = ip6_address_add; platform_class->ip4_address_delete = ip4_address_delete; platform_class->ip6_address_delete = ip6_address_delete; - platform_class->ip4_address_exists = ip4_address_exists; - platform_class->ip6_address_exists = ip6_address_exists; + platform_class->ip4_route_get = ip4_route_get; + platform_class->ip6_route_get = ip6_route_get; platform_class->ip4_route_get_all = ip4_route_get_all; platform_class->ip6_route_get_all = ip6_route_get_all; platform_class->ip4_route_add = ip4_route_add; platform_class->ip6_route_add = ip6_route_add; platform_class->ip4_route_delete = ip4_route_delete; platform_class->ip6_route_delete = ip6_route_delete; - platform_class->ip4_route_exists = ip4_route_exists; - platform_class->ip6_route_exists = ip6_route_exists; platform_class->check_support_kernel_extended_ifa_flags = check_support_kernel_extended_ifa_flags; platform_class->check_support_user_ipv6ll = check_support_user_ipv6ll; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 2bacdff407..b6d87ff959 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1965,26 +1965,24 @@ nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr a return klass->ip6_address_delete (self, ifindex, address, plen); } -gboolean -nm_platform_ip4_address_exists (NMPlatform *self, int ifindex, in_addr_t address, int plen) +const NMPlatformIP4Address * +nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen) { _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (plen > 0, FALSE); - g_return_val_if_fail (klass->ip4_address_exists, FALSE); - return klass->ip4_address_exists (self, ifindex, address, plen); + return klass->ip4_address_get (self, ifindex, address, plen); } -gboolean -nm_platform_ip6_address_exists (NMPlatform *self, int ifindex, struct in6_addr address, int plen) +const NMPlatformIP6Address * +nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, int plen) { _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (plen > 0, FALSE); - g_return_val_if_fail (klass->ip6_address_exists, FALSE); - return klass->ip6_address_exists (self, ifindex, address, plen); + return klass->ip6_address_get (self, ifindex, address, plen); } static gboolean @@ -2266,24 +2264,20 @@ nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr net return klass->ip6_route_delete (self, ifindex, network, plen, metric); } -gboolean -nm_platform_ip4_route_exists (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric) +const NMPlatformIP4Route * +nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric) { _CHECK_SELF (self, klass, FALSE); - g_return_val_if_fail (klass->ip4_route_exists, FALSE); - - return klass->ip4_route_exists (self ,ifindex, network, plen, metric); + return klass->ip4_route_get (self ,ifindex, network, plen, metric); } -gboolean -nm_platform_ip6_route_exists (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric) +const NMPlatformIP6Route * +nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric) { _CHECK_SELF (self, klass, FALSE); - g_return_val_if_fail (klass->ip6_route_exists, FALSE); - - return klass->ip6_route_exists (self, ifindex, network, plen, metric); + return klass->ip6_route_get (self, ifindex, network, plen, metric); } /******************************************************************/ diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 9892015578..4d25419505 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -517,8 +517,8 @@ typedef struct { guint32 lifetime, guint32 preferred_lft, guint flags); gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen, in_addr_t peer_address); gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, int plen); - gboolean (*ip4_address_exists) (NMPlatform *, int ifindex, in_addr_t address, int plen); - gboolean (*ip6_address_exists) (NMPlatform *, int ifindex, struct in6_addr address, int plen); + const NMPlatformIP4Address *(*ip4_address_get) (NMPlatform *, int ifindex, in_addr_t address, int plen); + const NMPlatformIP6Address *(*ip6_address_get) (NMPlatform *, int ifindex, struct in6_addr address, int plen); GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags); GArray * (*ip6_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags); @@ -530,8 +530,8 @@ typedef struct { guint32 metric, guint32 mss); gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric); gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric); - gboolean (*ip4_route_exists) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric); - gboolean (*ip6_route_exists) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric); + const NMPlatformIP4Route *(*ip4_route_get) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric); + const NMPlatformIP6Route *(*ip6_route_get) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric); gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *); gboolean (*check_support_user_ipv6ll) (NMPlatform *); @@ -691,6 +691,8 @@ guint32 nm_platform_mesh_get_channel (NMPlatform *self, int ifindex); gboolean nm_platform_mesh_set_channel (NMPlatform *self, int ifindex, guint32 channel); gboolean nm_platform_mesh_set_ssid (NMPlatform *self, int ifindex, const guint8 *ssid, gsize len); +const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen); +const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, int plen); GArray *nm_platform_ip4_address_get_all (NMPlatform *self, int ifindex); GArray *nm_platform_ip6_address_get_all (NMPlatform *self, int ifindex); gboolean nm_platform_ip4_address_add (NMPlatform *self, int ifindex, @@ -702,12 +704,12 @@ gboolean nm_platform_ip6_address_add (NMPlatform *self, int ifindex, guint32 lifetime, guint32 preferred_lft, guint flags); gboolean nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, int plen, in_addr_t peer_address); gboolean nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, int plen); -gboolean nm_platform_ip4_address_exists (NMPlatform *self, int ifindex, in_addr_t address, int plen); -gboolean nm_platform_ip6_address_exists (NMPlatform *self, int ifindex, struct in6_addr address, int plen); gboolean nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, GPtrArray **out_added_addresses); gboolean nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, gboolean keep_link_local); gboolean nm_platform_address_flush (NMPlatform *self, int ifindex); +const NMPlatformIP4Route *nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric); +const NMPlatformIP6Route *nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric); GArray *nm_platform_ip4_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags); GArray *nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags); gboolean nm_platform_ip4_route_add (NMPlatform *self, int ifindex, NMIPConfigSource source, @@ -718,8 +720,6 @@ gboolean nm_platform_ip6_route_add (NMPlatform *self, int ifindex, NMIPConfigSou guint32 metric, guint32 mss); gboolean nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric); gboolean nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric); -gboolean nm_platform_ip4_route_exists (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric); -gboolean nm_platform_ip6_route_exists (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric); const char *nm_platform_link_to_string (const NMPlatformLink *link); const char *nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address); diff --git a/src/platform/tests/platform.c b/src/platform/tests/platform.c index 60555414da..24e828c153 100644 --- a/src/platform/tests/platform.c +++ b/src/platform/tests/platform.c @@ -615,7 +615,7 @@ do_ip6_address_add (char **argv) v##_t address; \ int plen; \ if (ifindex && parse_##v##_address (*argv++, &address, &plen)) { \ - gboolean value = nm_platform_##v##_address_##cmdname (NM_PLATFORM_GET, ifindex, address, plen, ##__VA_ARGS__); \ + gboolean value = !!nm_platform_##v##_address_##cmdname (NM_PLATFORM_GET, ifindex, address, plen, ##__VA_ARGS__); \ if (print) { \ print_boolean (value); \ return TRUE; \ @@ -628,7 +628,7 @@ do_ip6_address_add (char **argv) #define ADDR_CMD_PRINT(cmdname) ADDR_CMD_FULL (ip4, cmdname, TRUE) ADDR_CMD_FULL (ip6, cmdname, TRUE) ADDR_CMD (delete) -ADDR_CMD_PRINT (exists) +ADDR_CMD_PRINT (get) static gboolean do_ip4_route_get_all (char **argv) @@ -738,7 +738,7 @@ do_ip6_route_delete (char **argv) } static gboolean -do_ip4_route_exists (char **argv) +do_ip4_route_get (char **argv) { int ifindex = parse_ifindex (*argv++); in_addr_t network; @@ -747,12 +747,12 @@ do_ip4_route_exists (char **argv) parse_ip4_address (*argv++, &network, &plen); metric = strtol (*argv++, NULL, 10); - print_boolean (nm_platform_ip4_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric)); + print_boolean (!!nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric)); return TRUE; } static gboolean -do_ip6_route_exists (char **argv) +do_ip6_route_get (char **argv) { int ifindex = parse_ifindex (*argv++); struct in6_addr network; @@ -761,7 +761,7 @@ do_ip6_route_exists (char **argv) parse_ip6_address (*argv++, &network, &plen); metric = strtol (*argv++, NULL, 10); - print_boolean (nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric)); + print_boolean (!!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric)); return TRUE; } @@ -838,9 +838,9 @@ static const command_t commands[] = { "
/" }, { "ip6-address-delete", "delete IPv6 address", do_ip6_address_delete, 2, "
/" }, - { "ip4-address-exists", "check for existence of IPv4 address", do_ip4_address_exists, 2, + { "ip4-address-exists", "check for existence of IPv4 address", do_ip4_address_get, 2, "
/" }, - { "ip6-address-exists", "check for existence of IPv6 address", do_ip6_address_exists, 2, + { "ip6-address-exists", "check for existence of IPv6 address", do_ip6_address_get, 2, "
/" }, { "ip4-route-get-all", "print all IPv4 routes", do_ip4_route_get_all, 1, "" }, { "ip6-route-get-all", "print all IPv6 routes", do_ip6_route_get_all, 1, "" }, @@ -852,9 +852,9 @@ static const command_t commands[] = { " / " }, { "ip6-route-delete", "delete IPv6 route", do_ip6_route_delete, 3, " / " }, - { "ip4-route-exists", "check for existence of IPv4 route", do_ip4_route_exists, 3, + { "ip4-route-exists", "check for existence of IPv4 route", do_ip4_route_get, 3, " / " }, - { "ip6-route-exists", "check for existence of IPv6 route", do_ip6_route_exists, 3, + { "ip6-route-exists", "check for existence of IPv6 route", do_ip6_route_get, 3, " / " }, { NULL, NULL, NULL, 0, NULL }, }; diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c index bcc38b399b..d6f346b376 100644 --- a/src/platform/tests/test-address.c +++ b/src/platform/tests/test-address.c @@ -64,9 +64,9 @@ test_ip4_address (void) inet_pton (AF_INET, IP4_ADDRESS, &addr); /* Add address */ - g_assert (!nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr, 0, IP4_PLEN, lifetime, preferred, NULL)); - g_assert (nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); accept_signal (address_added); /* Add address again (aka update) */ @@ -85,7 +85,7 @@ test_ip4_address (void) /* Remove address */ g_assert (nm_platform_ip4_address_delete (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0)); - g_assert (!nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); accept_signal (address_removed); /* Remove address again */ @@ -113,9 +113,9 @@ test_ip6_address (void) inet_pton (AF_INET6, IP6_ADDRESS, &addr); /* Add address */ - g_assert (!nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags)); - g_assert (nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); accept_signal (address_added); /* Add address again (aka update) */ @@ -134,7 +134,7 @@ test_ip6_address (void) /* Remove address */ g_assert (nm_platform_ip6_address_delete (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); - g_assert (!nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); accept_signal (address_removed); /* Remove address again */ @@ -167,20 +167,20 @@ test_ip4_address_external (void) run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME, lifetime, preferred); wait_signal (address_added); - g_assert (nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); run_command ("ip address delete %s/%d dev %s", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME); wait_signal (address_removed); - g_assert (!nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); /* Add/delete conflict */ run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME, lifetime, preferred); g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr, 0, IP4_PLEN, lifetime, preferred, NULL)); - g_assert (nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); accept_signal (address_added); /*run_command ("ip address delete %s/%d dev %s", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME); g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN, 0)); - g_assert (!nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); + g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN)); accept_signal (address_removed);*/ free_signal (address_added); @@ -204,20 +204,20 @@ test_ip6_address_external (void) run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME, lifetime, preferred); wait_signal (address_added); - g_assert (nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); run_command ("ip address delete %s/%d dev %s", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME); wait_signal (address_removed); - g_assert (!nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); /* Add/delete conflict */ run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME, lifetime, preferred); g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags)); - g_assert (nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); accept_signal (address_added); /*run_command ("ip address delete %s/%d dev %s", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME); g_assert (nm_platform_ip6_address_delete (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); - g_assert (!nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); wait_signal (address_removed);*/ free_signal (address_added); diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 6c754fecec..b0eae63b77 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -244,7 +244,7 @@ _assert_ip4_route_exists (const char *file, guint line, const char *func, gboole ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, ifname); g_assert (ifindex > 0); - if (!nm_platform_ip4_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric) != !exists) { + if (!nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric) != !exists) { g_error ("[%s:%u] %s(): The ip4 route %s/%d metric %u %s, but platform thinks %s", file, line, func, nm_utils_inet4_ntop (network, NULL), plen, metric, diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index 79d6fce75e..cf322dec6e 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -222,9 +222,9 @@ test_ip6_route (void) accept_signal (route_added); /* Add route */ - g_assert (!nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric)); g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, metric, mss)); - g_assert (nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert (nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric)); accept_signal (route_added); /* Add route again */ @@ -232,9 +232,9 @@ test_ip6_route (void) accept_signals (route_changed, 0, 1); /* Add default route */ - g_assert (!nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); + g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, metric, mss)); - g_assert (nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); + g_assert (nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); accept_signal (route_added); /* Add default route again */ @@ -271,7 +271,7 @@ test_ip6_route (void) /* Remove route */ g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); - g_assert (!nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric)); accept_signal (route_removed); /* Remove route again */ From ba44a92f524d89c6ff321c10101244a837e4c1c9 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 14 Jul 2015 12:12:32 +0200 Subject: [PATCH 7/8] test: add nmtst_platform_ip4_route() utils (cherry picked from commit cf4b1a0c3d05d498d87e30b68246b71f4eaab914) --- include/nm-test-utils.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 4610ee62a6..258d39370b 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -789,6 +789,38 @@ nmtst_platform_ip6_address_full (const char *address, const char *peer_address, return addr; } +inline static NMPlatformIP4Route * +nmtst_platform_ip4_route (const char *network, guint plen, const char *gateway) +{ + static NMPlatformIP4Route route; + + memset (&route, 0, sizeof (route)); + route.network = nmtst_inet4_from_string (network); + route.plen = plen; + route.gateway = nmtst_inet4_from_string (gateway); + + return &route; +} + +inline static NMPlatformIP4Route * +nmtst_platform_ip4_route_full (const char *network, guint plen, const char *gateway, + int ifindex, NMIPConfigSource source, + guint metric, guint mss, + guint8 scope, + const char *pref_src) +{ + NMPlatformIP4Route *route = nmtst_platform_ip4_route (network, plen, gateway); + + route->ifindex = ifindex; + route->source = source; + route->metric = metric; + route->mss = mss; + route->scope_inv = nm_platform_route_scope_inv (scope); + route->pref_src = nmtst_inet4_from_string (pref_src); + + return route; +} + inline static NMPlatformIP6Route * nmtst_platform_ip6_route (const char *network, guint plen, const char *gateway) { From 3cbc8981d600fd7e704713961d7ec5f9b77ab243 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 14 Jul 2015 12:18:58 +0200 Subject: [PATCH 8/8] route-manager/test: add test for full-sync (cherry picked from commit ae721e7f0ae11dea3d757b27c3beb2ac13a810d2) --- src/tests/test-route-manager.c | 89 ++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/tests/test-route-manager.c b/src/tests/test-route-manager.c index 0ea515f9ea..0164930d6c 100644 --- a/src/tests/test-route-manager.c +++ b/src/tests/test-route-manager.c @@ -36,6 +36,8 @@ typedef struct { int ifindex0, ifindex1; } test_fixture; +/*****************************************************************************/ + static void setup_dev0_ip4 (int ifindex, guint mss_of_first_route, guint32 metric_of_second_route) { @@ -779,6 +781,89 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) g_array_free (routes, TRUE); } +/*****************************************************************************/ + +static void +_assert_route_check (const NMPlatformVTableRoute *vtable, gboolean has, const NMPlatformIPXRoute *route) +{ + const NMPlatformIPXRoute *r; + + g_assert (route); + + if (vtable->is_ip4) + r = (const NMPlatformIPXRoute *) nm_platform_ip4_route_get (NM_PLATFORM_GET, route->rx.ifindex, route->r4.network, route->rx.plen, route->rx.metric); + else + r = (const NMPlatformIPXRoute *) nm_platform_ip6_route_get (NM_PLATFORM_GET, route->rx.ifindex, route->r6.network, route->rx.plen, route->rx.metric); + + if (!has) { + g_assert (!r); + } else { + if (!r || vtable->route_cmp (route, r) != 0) + g_error ("Invalid route. Expect %s, has %s", + nmtst_static_1024_01 (vtable->route_to_string (route)), + nmtst_static_1024_02 (vtable->route_to_string (r))); + g_assert (r); + } +} + +static void +test_ip4_full_sync (test_fixture *fixture, gconstpointer user_data) +{ + const NMPlatformVTableRoute *vtable = &nm_platform_vtable_route_v4; + gs_unref_array GArray *routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route)); + NMPlatformIP4Route r01, r02, r03; + + nm_log_dbg (LOGD_CORE, "TEST start test_ip4_full_sync(): start"); + + r01 = *nmtst_platform_ip4_route_full ("12.3.4.0", 24, NULL, + fixture->ifindex0, NM_IP_CONFIG_SOURCE_USER, + 100, 0, RT_SCOPE_LINK, NULL); + r02 = *nmtst_platform_ip4_route_full ("13.4.5.6", 32, "12.3.4.1", + fixture->ifindex0, NM_IP_CONFIG_SOURCE_USER, + 100, 0, RT_SCOPE_UNIVERSE, NULL); + r03 = *nmtst_platform_ip4_route_full ("14.5.6.7", 32, "12.3.4.1", + fixture->ifindex0, NM_IP_CONFIG_SOURCE_USER, + 110, 0, RT_SCOPE_UNIVERSE, NULL); + g_array_set_size (routes, 2); + g_array_index (routes, NMPlatformIP4Route, 0) = r01; + g_array_index (routes, NMPlatformIP4Route, 1) = r02; + nm_route_manager_ip4_route_sync (nm_route_manager_get (), fixture->ifindex0, routes, TRUE, TRUE); + + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01); + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r02); + _assert_route_check (vtable, FALSE, (const NMPlatformIPXRoute *) &r03); + + vtable->route_add (NM_PLATFORM_GET, 0, (const NMPlatformIPXRoute *) &r03, -1); + + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01); + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r02); + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r03); + + nm_route_manager_ip4_route_sync (nm_route_manager_get (), fixture->ifindex0, routes, TRUE, FALSE); + + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01); + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r02); + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r03); + + g_array_set_size (routes, 1); + + nm_route_manager_ip4_route_sync (nm_route_manager_get (), fixture->ifindex0, routes, TRUE, FALSE); + + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01); + _assert_route_check (vtable, FALSE, (const NMPlatformIPXRoute *) &r02); + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r03); + + nm_route_manager_ip4_route_sync (nm_route_manager_get (), fixture->ifindex0, routes, TRUE, TRUE); + + _assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01); + _assert_route_check (vtable, FALSE, (const NMPlatformIPXRoute *) &r02); + _assert_route_check (vtable, FALSE, (const NMPlatformIPXRoute *) &r03); + + nm_log_dbg (LOGD_CORE, "TEST test_ip4_full_sync(): done"); +} + +/*****************************************************************************/ + static void fixture_setup (test_fixture *fixture, gconstpointer user_data) { @@ -814,6 +899,8 @@ fixture_teardown (test_fixture *fixture, gconstpointer user_data) nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex1); } +/*****************************************************************************/ + void init_tests (int *argc, char ***argv) { @@ -825,4 +912,6 @@ setup_tests (void) { g_test_add ("/route-manager/ip4", test_fixture, NULL, fixture_setup, test_ip4, fixture_teardown); g_test_add ("/route-manager/ip6", test_fixture, NULL, fixture_setup, test_ip6, fixture_teardown); + + g_test_add ("/route-manager/ip4-full-sync", test_fixture, NULL, fixture_setup, test_ip4_full_sync, fixture_teardown); }