diff options
Diffstat (limited to 'src/nm-route-manager.c')
-rw-r--r-- | src/nm-route-manager.c | 58 |
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; } |