summaryrefslogtreecommitdiff
path: root/src/nm-route-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-route-manager.c')
-rw-r--r--src/nm-route-manager.c58
1 files changed, 50 insertions, 8 deletions
diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c
index 6c1f78ac96..574493d990 100644
--- a/src/nm-route-manager.c
+++ b/src/nm-route-manager.c
@@ -306,6 +306,50 @@ _route_index_create (const VTableIP *vtable, const GArray *routes)
return index;
}
+static RouteIndex *
+_route_index_create_from_platform (const VTableIP *vtable,
+ NMPlatform *platform,
+ int ifindex,
+ gboolean ignore_kernel_routes,
+ GPtrArray **out_storage)
+{
+ RouteIndex *index;
+ guint i, len;
+ GPtrArray *storage;
+
+ nm_assert (out_storage && !*out_storage);
+
+ storage = nm_platform_lookup_route_visible_clone (platform,
+ vtable->vt->obj_type,
+ ifindex,
+ FALSE,
+ TRUE,
+ NULL,
+ NULL);
+ if (!storage)
+ return _route_index_create (vtable, NULL);
+
+ len = storage->len;
+ index = g_malloc (sizeof (RouteIndex) + len * sizeof (NMPlatformIPXRoute *));
+
+ index->len = len;
+ for (i = 0; i < len; i++) {
+ /* we cast away the const-ness of the NMPObjects. The caller must
+ * ensure not to modify the object via index->entries. */
+ index->entries[i] = NMP_OBJECT_CAST_IPX_ROUTE ((NMPObject *) storage->pdata[i]);
+ }
+ index->entries[i] = NULL;
+
+ /* this is a stable sort, which is very important at this point. */
+ g_qsort_with_data (index->entries,
+ len,
+ sizeof (NMPlatformIPXRoute *),
+ (GCompareDataFunc) _route_index_create_sort,
+ (gpointer) vtable);
+ *out_storage = storage;
+ return index;
+}
+
static int
_vx_route_id_cmp_full (const NMPlatformIPXRoute *r1, const NMPlatformIPXRoute *r2, const VTableIP *vtable)
{
@@ -458,7 +502,7 @@ static gboolean
_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;
+ gs_unref_ptrarray GPtrArray *plat_routes = NULL;
RouteEntries *ipx_routes;
RouteIndex *plat_routes_idx, *known_routes_idx;
gboolean success = TRUE;
@@ -475,16 +519,15 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
nm_platform_process_events (priv->platform);
ipx_routes = vtable->vt->is_ip4 ? &priv->ip4_routes : &priv->ip6_routes;
- plat_routes = vtable->vt->route_get_all (priv->platform, ifindex,
- ignore_kernel_routes
- ? NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT
- : NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_RTPROT_KERNEL);
- plat_routes_idx = _route_index_create (vtable, plat_routes);
+
+ /* the objects referenced by play_routes_idx are shared from the platform cache. They
+ * must not be modified. */
+ plat_routes_idx = _route_index_create_from_platform (vtable, priv->platform, ifindex, ignore_kernel_routes, &plat_routes);
+
known_routes_idx = _route_index_create (vtable, known_routes);
effective_metrics = &g_array_index (ipx_routes->effective_metrics, gint64, 0);
- ASSERT_route_index_valid (vtable, plat_routes, plat_routes_idx, TRUE);
ASSERT_route_index_valid (vtable, known_routes, known_routes_idx, FALSE);
_LOGD (vtable->vt->addr_family, "%3d: sync %u IPv%c routes", ifindex, known_routes_idx->len, vtable->vt->is_ip4 ? '4' : '6');
@@ -918,7 +961,6 @@ next:
g_free (known_routes_idx);
g_free (plat_routes_idx);
- g_array_unref (plat_routes);
return success;
}