From b9bc960e974bbf6b26fbd992926e022e61f41950 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 --- 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 65f2090cc2341d4287b13751ac7bdd0b15039cac 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. --- 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 c811e24d34..e140e59e58 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -359,7 +359,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 082f1d2db7..5c060d5399 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -437,7 +437,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 5325b83fae..39d3df54f1 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 6124f5b94a7bc471803e8f8e384f182f708d839a 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. --- 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 48d2004fe6..0fa5bdf9b0 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -6351,6 +6351,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; @@ -6483,7 +6484,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 3cdd165965..cbff221a85 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 e140e59e58..2b137ff73a 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -290,7 +290,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; @@ -359,7 +359,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 0088934a45..0f457217a4 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -71,7 +71,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 5c060d5399..4794a0ae38 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -406,7 +406,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; @@ -437,7 +437,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 799364e4db..e8cbc0e5f9 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -71,7 +71,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 fffc5cabee..8749e3573b 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -961,12 +961,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 8b015826e62022ae0a66afb92fd182f77cbb644b 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. --- 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 0fa5bdf9b0..415465ada2 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -351,6 +351,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, @@ -360,6 +361,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); @@ -3248,6 +3250,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) { @@ -3312,6 +3315,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; @@ -3391,7 +3398,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; } @@ -3864,6 +3871,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 (nm_device_get_ip_ifindex (self)); @@ -3926,6 +3934,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; @@ -4008,7 +4020,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; @@ -6351,7 +6364,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; @@ -6457,6 +6470,7 @@ static gboolean nm_device_set_ip6_config (NMDevice *self, NMIP6Config *new_config, gboolean commit, + gboolean routes_full_sync, NMDeviceStateReason *reason) { NMDevicePrivate *priv; @@ -6486,7 +6500,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; } @@ -7940,8 +7954,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 7bda97092826147f9799f9372e98315637ae17a7 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 --- 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 6f8fcd2f47541ff78aa83c584a731fedec6e3a8f 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. --- 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 efbdbe3351..f3a9254531 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -4163,22 +4163,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; } /******************************************************************/ @@ -4461,24 +4469,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; } /******************************************************************/ @@ -4985,23 +5001,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 2a7945d11d..8803377a5b 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1971,26 +1971,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 @@ -2272,24 +2270,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 1b5bfb1575..16eb351fa1 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -518,8 +518,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); @@ -531,8 +531,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 *); @@ -692,6 +692,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, @@ -703,12 +705,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, @@ -719,8 +721,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 3e43ca57bd..ebf162a98a 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 cf4b1a0c3d05d498d87e30b68246b71f4eaab914 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 --- 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 14d4bb4514..3007674e13 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -812,6 +812,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 ae721e7f0ae11dea3d757b27c3beb2ac13a810d2 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 --- 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 39d3df54f1..9b66c2dd38 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) { @@ -816,6 +901,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) { @@ -827,4 +914,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); }