platform: track routes in NMFakePlatform via NMPCache

NMPlatform's cache should be directly accessible to the users,
at least the NMPLookup part and the fact that the cache contains
ref-counted, immutable NMPObjects.

This allows users to inspect the cache with zero overhead. Meaning,
they can obtain an NMDedupMultiHeadEntry and iterate the objects
themself. It also means, the are free to take and keep references
of the NMPObject instances (of course, without modifying them!).

NMFakePlatform will use the very same cache. The fake platform should
only differ when modifying the objects.

Another reason why this makes sense is because NMFakePlatform is for one
a test-stup but also tests behavior of platform itself. Using a separate
internal implementation for the caching is a pointless excecise, because
only the real NMPCache's implementation really matters for production.
So, either NMFakePlatform behaves idential, or it is buggy. Reuse it.

Port fake platform's tracking of routes to NMPCache and move duplicate
code from NMLinuxPlatform to the base class.

This commit only ports IP routes, eventually also addresses and links
should be tracked via the NMPCache instance.
This commit is contained in:
Thomas Haller
2017-06-29 13:05:52 +02:00
parent 16aefdd865
commit c9cd6d9954
5 changed files with 218 additions and 342 deletions

View File

@@ -32,6 +32,7 @@
#include "nm-core-utils.h" #include "nm-core-utils.h"
#include "nm-platform-utils.h" #include "nm-platform-utils.h"
#include "nm-platform-private.h"
#include "nmp-object.h" #include "nmp-object.h"
#include "nm-test-utils-core.h" #include "nm-test-utils-core.h"
@@ -51,8 +52,6 @@ typedef struct {
GArray *links; GArray *links;
GArray *ip4_addresses; GArray *ip4_addresses;
GArray *ip6_addresses; GArray *ip6_addresses;
GArray *ip4_routes;
GArray *ip6_routes;
} NMFakePlatformPrivate; } NMFakePlatformPrivate;
struct _NMFakePlatform { struct _NMFakePlatform {
@@ -98,6 +97,13 @@ G_DEFINE_TYPE (NMFakePlatform, nm_fake_platform, NM_TYPE_PLATFORM)
static void link_changed (NMPlatform *platform, NMFakePlatformLink *device, gboolean raise_signal); static void link_changed (NMPlatform *platform, NMFakePlatformLink *device, gboolean raise_signal);
static gboolean ipx_route_delete (NMPlatform *platform,
int addr_family,
int ifindex,
gconstpointer network,
const guint8 *plen,
const guint32 *metric);
static gboolean ip6_address_add (NMPlatform *platform, static gboolean ip6_address_add (NMPlatform *platform,
int ifindex, int ifindex,
struct in6_addr addr, struct in6_addr addr,
@@ -399,18 +405,8 @@ link_delete (NMPlatform *platform, int ifindex)
if (address->ifindex == ifindex) if (address->ifindex == ifindex)
memset (address, 0, sizeof (*address)); memset (address, 0, sizeof (*address));
} }
for (i = 0; i < priv->ip4_routes->len; i++) { ipx_route_delete (platform, AF_INET, ifindex, NULL, NULL, NULL);
NMPlatformIP4Route *route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i); ipx_route_delete (platform, AF_INET6, ifindex, NULL, NULL, NULL);
if (route->ifindex == ifindex)
memset (route, 0, sizeof (*route));
}
for (i = 0; i < priv->ip6_routes->len; i++) {
NMPlatformIP6Route *route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
if (route->ifindex == ifindex)
memset (route, 0, sizeof (*route));
}
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, (int) NMP_OBJECT_TYPE_LINK, ifindex, &deleted_device, (int) NM_PLATFORM_SIGNAL_REMOVED); g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, (int) NMP_OBJECT_TYPE_LINK, ifindex, &deleted_device, (int) NM_PLATFORM_SIGNAL_REMOVED);
@@ -1152,270 +1148,174 @@ ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr)
/*****************************************************************************/ /*****************************************************************************/
static GArray * static gboolean
ip4_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags flags) ipx_route_delete (NMPlatform *platform,
int addr_family,
int ifindex,
gconstpointer network,
const guint8 *plen,
const guint32 *metric)
{ {
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform); gs_unref_ptrarray GPtrArray *objs = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
GArray *routes; NMDedupMultiIter iter;
NMPlatformIP4Route *route; const NMPObject *o = NULL;
guint i; guint i;
routes = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP4Route)); g_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
if (!NM_FLAGS_ANY (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT)) nmp_cache_iter_for_each (&iter,
flags |= NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT; nm_platform_lookup_addrroute (platform,
addr_family == AF_INET
? NMP_OBJECT_TYPE_IP4_ROUTE
: NMP_OBJECT_TYPE_IP6_ROUTE,
0,
FALSE),
&o) {
const NMPObject *obj_old = NULL;
/* Fill routes */ if (addr_family == AF_INET) {
for (i = 0; i < priv->ip4_routes->len; i++) { const NMPlatformIP4Route *route = NMP_OBJECT_CAST_IP4_ROUTE (o);
route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
if (route && (!ifindex || route->ifindex == ifindex)) { if ( route->ifindex != ifindex
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) { || (network && route->network != *((guint32 *) network))
if (NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT)) || (plen && route->plen != *plen)
g_array_append_val (routes, *route); || (metric && route->metric != *metric))
} else { continue;
if (NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT)) } else {
g_array_append_val (routes, *route); const NMPlatformIP6Route *route = NMP_OBJECT_CAST_IP6_ROUTE (o);
}
if ( route->ifindex != ifindex
|| (network && !IN6_ARE_ADDR_EQUAL (&route->network, network))
|| (plen && route->plen != *plen)
|| (metric && route->metric != *metric))
continue;
} }
if (nmp_cache_remove (nm_platform_get_cache (platform),
o,
TRUE,
&obj_old) != NMP_CACHE_OPS_REMOVED)
g_assert_not_reached ();
g_assert (obj_old);
g_ptr_array_add (objs, (gpointer) obj_old);
} }
return routes; for (i = 0; i < objs->len; i++) {
} nm_platform_cache_update_emit_signal (platform,
NMP_CACHE_OPS_REMOVED,
static GArray * objs->pdata[i],
ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags flags) NULL);
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
GArray *routes;
NMPlatformIP6Route *route;
guint i;
routes = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP6Route));
if (!NM_FLAGS_ANY (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT))
flags |= NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT;
/* Fill routes */
for (i = 0; i < priv->ip6_routes->len; i++) {
route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
if (route && (!ifindex || route->ifindex == ifindex)) {
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
if (NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT))
g_array_append_val (routes, *route);
} else {
if (NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT))
g_array_append_val (routes, *route);
}
}
} }
return TRUE;
return routes;
} }
static gboolean static gboolean
ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric) ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
{ {
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform); return ipx_route_delete (platform, AF_INET, ifindex, &network, &plen, &metric);
int i;
for (i = 0; i < priv->ip4_routes->len; i++) {
NMPlatformIP4Route *route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
NMPlatformIP4Route deleted_route;
if ( route->ifindex != ifindex
|| route->network != network
|| route->plen != plen
|| route->metric != metric)
continue;
memcpy (&deleted_route, route, sizeof (deleted_route));
g_array_remove_index (priv->ip4_routes, i);
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP4_ROUTE, ifindex, &deleted_route, (int) NM_PLATFORM_SIGNAL_REMOVED);
}
return TRUE;
} }
static gboolean static gboolean
ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric) ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
{ {
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
int i;
metric = nm_utils_ip6_route_metric_normalize (metric); metric = nm_utils_ip6_route_metric_normalize (metric);
return ipx_route_delete (platform, AF_INET6, ifindex, &network, &plen, &metric);
}
for (i = 0; i < priv->ip6_routes->len; i++) { static gboolean
NMPlatformIP6Route *route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i); ipx_route_add (NMPlatform *platform, int addr_family, const NMPlatformObject *route)
NMPlatformIP6Route deleted_route; {
NMDedupMultiIter iter;
nm_auto_nmpobj NMPObject *obj = NULL;
NMPlatformIPRoute *rt;
NMPCacheOpsType cache_op;
const NMPObject *o = NULL;
nm_auto_nmpobj const NMPObject *obj_old = NULL;
nm_auto_nmpobj const NMPObject *obj_new = NULL;
NMPCache *cache = nm_platform_get_cache (platform);
gboolean has_gateway = FALSE;
NMPlatformIP4Route *rt4 = NULL;
NMPlatformIP6Route *rt6 = NULL;
if ( route->ifindex != ifindex g_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
|| !IN6_ARE_ADDR_EQUAL (&route->network, &network)
|| route->plen != plen
|| route->metric != metric)
continue;
memcpy (&deleted_route, route, sizeof (deleted_route)); obj = nmp_object_new (addr_family == AF_INET
g_array_remove_index (priv->ip6_routes, i); ? NMP_OBJECT_TYPE_IP4_ROUTE
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP6_ROUTE, ifindex, &deleted_route, (int) NM_PLATFORM_SIGNAL_REMOVED); : NMP_OBJECT_TYPE_IP6_ROUTE,
route);
rt = &obj->ip_route;
rt->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (rt->rt_source);
if (addr_family == AF_INET) {
rt4 = NMP_OBJECT_CAST_IP4_ROUTE (obj);
rt4->scope_inv = nm_platform_route_scope_inv (rt4->gateway ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK);
rt4->network = nm_utils_ip4_address_clear_host_address (rt4->network, rt4->plen);
if (rt4->gateway)
has_gateway = TRUE;
} else {
rt6 = NMP_OBJECT_CAST_IP6_ROUTE (obj);
rt->metric = nm_utils_ip6_route_metric_normalize (rt->metric);
nm_utils_ip6_address_clear_host_address (&rt6->network, &rt6->network, rt->plen);
if (!IN6_IS_ADDR_UNSPECIFIED (&rt6->gateway))
has_gateway = TRUE;
} }
if (has_gateway) {
gboolean has_route_to_gw = FALSE;
nmp_cache_iter_for_each (&iter,
nm_platform_lookup_addrroute (platform,
NMP_OBJECT_GET_TYPE (obj),
0,
FALSE),
&o) {
if (addr_family == AF_INET) {
const NMPlatformIP4Route *item = NMP_OBJECT_CAST_IP4_ROUTE (o);
guint32 n = nm_utils_ip4_address_clear_host_address (item->network, item->plen);
guint32 g = nm_utils_ip4_address_clear_host_address (rt4->gateway, item->plen);
if ( rt->ifindex == item->ifindex
&& n == g) {
has_route_to_gw = TRUE;
break;
}
} else {
const NMPlatformIP6Route *item = NMP_OBJECT_CAST_IP6_ROUTE (o);
if ( rt->ifindex == item->ifindex
&& nm_utils_ip6_address_same_prefix (&rt6->gateway, &item->network, item->plen)) {
has_route_to_gw = TRUE;
break;
}
}
}
if (!has_route_to_gw) {
if (addr_family == AF_INET) {
nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip4-route '%d: %s/%d %d': Network Unreachable",
rt->ifindex, nm_utils_inet4_ntop (rt4->network, NULL), rt->plen, rt->metric);
} else {
nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip6-route '%d: %s/%d %d': Network Unreachable",
rt->ifindex, nm_utils_inet6_ntop (&rt6->network, NULL), rt->plen, rt->metric);
}
return FALSE;
}
}
cache_op = nmp_cache_update_netlink (cache, obj, &obj_old, &obj_new);
nm_platform_cache_update_emit_signal (platform, cache_op, obj_old, obj_new);
return TRUE; return TRUE;
} }
static gboolean static gboolean
ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route) ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route)
{ {
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform); return ipx_route_add (platform, AF_INET, (const NMPlatformObject *) route);
NMPlatformIP4Route rt = *route;
guint i;
rt.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (rt.rt_source);
rt.network = nm_utils_ip4_address_clear_host_address (rt.network, rt.plen);
rt.scope_inv = nm_platform_route_scope_inv (rt.gateway ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK);
if (rt.gateway) {
for (i = 0; i < priv->ip4_routes->len; i++) {
NMPlatformIP4Route *item = &g_array_index (priv->ip4_routes,
NMPlatformIP4Route, i);
guint32 gate = ntohl (item->network) >> (32 - item->plen);
guint32 host = ntohl (rt.gateway) >> (32 - item->plen);
if (rt.ifindex == item->ifindex && gate == host)
break;
}
if (i == priv->ip4_routes->len) {
nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip4-route '%d: %s/%d %d': Network Unreachable",
rt.ifindex, nm_utils_inet4_ntop (rt.network, NULL), rt.plen, rt.metric);
return FALSE;
}
}
for (i = 0; i < priv->ip4_routes->len; i++) {
NMPlatformIP4Route *item = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
if (item->network != rt.network)
continue;
if (item->plen != rt.plen)
continue;
if (item->metric != rt.metric)
continue;
if (item->ifindex != rt.ifindex) {
ip4_route_delete (platform, item->ifindex, item->network, item->plen, item->metric);
i--;
continue;
}
memcpy (item, &rt, sizeof (rt));
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP4_ROUTE,
rt.ifindex, &rt, (int) NM_PLATFORM_SIGNAL_CHANGED);
return TRUE;
}
g_array_append_val (priv->ip4_routes, rt);
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP4_ROUTE,
rt.ifindex, &rt, (int) NM_PLATFORM_SIGNAL_ADDED);
return TRUE;
} }
static gboolean static gboolean
ip6_route_add (NMPlatform *platform, const NMPlatformIP6Route *route) ip6_route_add (NMPlatform *platform, const NMPlatformIP6Route *route)
{ {
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform); return ipx_route_add (platform, AF_INET6, (const NMPlatformObject *) route);
NMPlatformIP6Route rt = *route;
guint i;
rt.metric = nm_utils_ip6_route_metric_normalize (rt.metric);
rt.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (rt.rt_source);
nm_utils_ip6_address_clear_host_address (&rt.network, &rt.network, rt.plen);
if (!IN6_IS_ADDR_UNSPECIFIED (&rt.gateway)) {
for (i = 0; i < priv->ip6_routes->len; i++) {
NMPlatformIP6Route *item = &g_array_index (priv->ip6_routes,
NMPlatformIP6Route, i);
guint8 gate_bits = rt.gateway.s6_addr[item->plen / 8] >> (8 - item->plen % 8);
guint8 host_bits = item->network.s6_addr[item->plen / 8] >> (8 - item->plen % 8);
if ( rt.ifindex == item->ifindex
&& memcmp (&rt.gateway, &item->network, item->plen / 8) == 0
&& gate_bits == host_bits)
break;
}
if (i == priv->ip6_routes->len) {
nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip6-route '%d: %s/%d %d': Network Unreachable",
rt.ifindex, nm_utils_inet6_ntop (&rt.network, NULL), rt.plen, rt.metric);
return FALSE;
}
}
for (i = 0; i < priv->ip6_routes->len; i++) {
NMPlatformIP6Route *item = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
if (!IN6_ARE_ADDR_EQUAL (&item->network, &rt.network))
continue;
if (item->plen != rt.plen)
continue;
if (item->metric != rt.metric)
continue;
if (item->ifindex != rt.ifindex) {
ip6_route_delete (platform, item->ifindex, item->network, item->plen, item->metric);
i--;
continue;
}
memcpy (item, &rt, sizeof (rt));
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP6_ROUTE,
rt.ifindex, &rt, (int) NM_PLATFORM_SIGNAL_CHANGED);
return TRUE;
}
g_array_append_val (priv->ip6_routes, rt);
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, (int) NMP_OBJECT_TYPE_IP6_ROUTE,
rt.ifindex, &rt, (int) NM_PLATFORM_SIGNAL_ADDED);
return TRUE;
}
static const NMPlatformIP4Route *
ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
int i;
for (i = 0; i < priv->ip4_routes->len; i++) {
NMPlatformIP4Route *route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
if (route->ifindex == ifindex
&& route->network == network
&& route->plen == plen
&& route->metric == metric)
return route;
}
return NULL;
}
static const NMPlatformIP6Route *
ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
int i;
metric = nm_utils_ip6_route_metric_normalize (metric);
for (i = 0; i < priv->ip6_routes->len; i++) {
NMPlatformIP6Route *route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
if (route->ifindex == ifindex
&& IN6_ARE_ADDR_EQUAL (&route->network, &network)
&& route->plen == plen
&& route->metric == metric)
return route;
}
return NULL;
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -1429,8 +1329,6 @@ nm_fake_platform_init (NMFakePlatform *fake_platform)
priv->links = g_array_new (TRUE, TRUE, sizeof (NMFakePlatformLink)); priv->links = g_array_new (TRUE, TRUE, sizeof (NMFakePlatformLink));
priv->ip4_addresses = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP4Address)); priv->ip4_addresses = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP4Address));
priv->ip6_addresses = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP6Address)); priv->ip6_addresses = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP6Address));
priv->ip4_routes = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP4Route));
priv->ip6_routes = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP6Route));
} }
void void
@@ -1472,8 +1370,6 @@ finalize (GObject *object)
g_array_unref (priv->links); g_array_unref (priv->links);
g_array_unref (priv->ip4_addresses); g_array_unref (priv->ip4_addresses);
g_array_unref (priv->ip6_addresses); g_array_unref (priv->ip6_addresses);
g_array_unref (priv->ip4_routes);
g_array_unref (priv->ip6_routes);
G_OBJECT_CLASS (nm_fake_platform_parent_class)->finalize (object); G_OBJECT_CLASS (nm_fake_platform_parent_class)->finalize (object);
} }
@@ -1550,10 +1446,6 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
platform_class->ip4_address_delete = ip4_address_delete; platform_class->ip4_address_delete = ip4_address_delete;
platform_class->ip6_address_delete = ip6_address_delete; platform_class->ip6_address_delete = ip6_address_delete;
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->ip4_route_add = ip4_route_add;
platform_class->ip6_route_add = ip6_route_add; platform_class->ip6_route_add = ip6_route_add;
platform_class->ip4_route_delete = ip4_route_delete; platform_class->ip4_route_delete = ip4_route_delete;

View File

@@ -5889,58 +5889,6 @@ ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr)
/*****************************************************************************/ /*****************************************************************************/
static GArray *
ipx_route_get_all (NMPlatform *platform, int ifindex, NMPObjectType obj_type, NMPlatformGetRouteFlags flags)
{
NMDedupMultiIter iter;
NMPLookup lookup;
const NMDedupMultiHeadEntry *head_entry;
GArray *array;
const NMPClass *klass;
const NMPObject *o;
gboolean with_rtprot_kernel;
nm_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
if (!NM_FLAGS_ANY (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT))
flags |= NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT;
klass = nmp_class_from_type (obj_type);
head_entry = nmp_cache_lookup (nm_platform_get_cache (platform),
nmp_lookup_init_route_visible (&lookup,
obj_type,
ifindex,
NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT),
NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT)));
array = g_array_sized_new (FALSE, FALSE, klass->sizeof_public, head_entry ? head_entry->len : 0);
with_rtprot_kernel = NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_RTPROT_KERNEL);
nmp_cache_iter_for_each (&iter,
head_entry,
&o) {
nm_assert (NMP_OBJECT_GET_CLASS (o) == klass);
if ( with_rtprot_kernel
|| o->ip_route.rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
g_array_append_vals (array, &o->ip_route, 1);
}
return array;
}
static GArray *
ip4_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags flags)
{
return ipx_route_get_all (platform, ifindex, NMP_OBJECT_TYPE_IP4_ROUTE, flags);
}
static GArray *
ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags flags)
{
return ipx_route_get_all (platform, ifindex, NMP_OBJECT_TYPE_IP6_ROUTE, flags);
}
static guint32 static guint32
ip_route_get_lock_flag (NMPlatformIPRoute *route) ip_route_get_lock_flag (NMPlatformIPRoute *route)
{ {
@@ -6130,34 +6078,6 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, gu
return do_delete_object (platform, &obj_id, nlmsg); return do_delete_object (platform, &obj_id, nlmsg);
} }
static const NMPlatformIP4Route *
ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
{
NMPObject obj_id;
const NMPObject *obj;
nmp_object_stackinit_id_ip4_route (&obj_id, ifindex, network, plen, metric);
obj = nmp_cache_lookup_obj (nm_platform_get_cache (platform), &obj_id);
if (nmp_object_is_visible (obj))
return &obj->ip4_route;
return NULL;
}
static const NMPlatformIP6Route *
ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
{
NMPObject obj_id;
const NMPObject *obj;
metric = nm_utils_ip6_route_metric_normalize (metric);
nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric);
obj = nmp_cache_lookup_obj (nm_platform_get_cache (platform), &obj_id);
if (nmp_object_is_visible (obj))
return &obj->ip6_route;
return NULL;
}
/*****************************************************************************/ /*****************************************************************************/
#define EVENT_CONDITIONS ((GIOCondition) (G_IO_IN | G_IO_PRI)) #define EVENT_CONDITIONS ((GIOCondition) (G_IO_IN | G_IO_PRI))
@@ -6898,10 +6818,6 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->ip4_address_delete = ip4_address_delete; platform_class->ip4_address_delete = ip4_address_delete;
platform_class->ip6_address_delete = ip6_address_delete; platform_class->ip6_address_delete = ip6_address_delete;
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->ip4_route_add = ip4_route_add;
platform_class->ip6_route_add = ip6_route_add; platform_class->ip6_route_add = ip6_route_add;
platform_class->ip4_route_delete = ip4_route_delete; platform_class->ip4_route_delete = ip4_route_delete;

View File

@@ -3160,6 +3160,46 @@ nm_platform_address_flush (NMPlatform *self, int ifindex)
/*****************************************************************************/ /*****************************************************************************/
static GArray *
ipx_route_get_all (NMPlatform *platform, int ifindex, NMPObjectType obj_type, NMPlatformGetRouteFlags flags)
{
NMDedupMultiIter iter;
NMPLookup lookup;
const NMDedupMultiHeadEntry *head_entry;
GArray *array;
const NMPClass *klass;
const NMPObject *o;
gboolean with_rtprot_kernel;
nm_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
if (!NM_FLAGS_ANY (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT))
flags |= NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT;
klass = nmp_class_from_type (obj_type);
head_entry = nmp_cache_lookup (nm_platform_get_cache (platform),
nmp_lookup_init_route_visible (&lookup,
obj_type,
ifindex,
NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT),
NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT)));
array = g_array_sized_new (FALSE, FALSE, klass->sizeof_public, head_entry ? head_entry->len : 0);
with_rtprot_kernel = NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_RTPROT_KERNEL);
nmp_cache_iter_for_each (&iter,
head_entry,
&o) {
nm_assert (NMP_OBJECT_GET_CLASS (o) == klass);
if ( with_rtprot_kernel
|| o->ip_route.rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
g_array_append_vals (array, &o->ip_route, 1);
}
return array;
}
GArray * GArray *
nm_platform_ip4_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags) nm_platform_ip4_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags)
{ {
@@ -3167,7 +3207,7 @@ nm_platform_ip4_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRoute
g_return_val_if_fail (ifindex >= 0, NULL); g_return_val_if_fail (ifindex >= 0, NULL);
return klass->ip4_route_get_all (self, ifindex, flags); return ipx_route_get_all (self, ifindex, NMP_OBJECT_TYPE_IP4_ROUTE, flags);
} }
GArray * GArray *
@@ -3177,7 +3217,7 @@ nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRoute
g_return_val_if_fail (ifindex >= 0, NULL); g_return_val_if_fail (ifindex >= 0, NULL);
return klass->ip6_route_get_all (self, ifindex, flags); return ipx_route_get_all (self, ifindex, NMP_OBJECT_TYPE_IP6_ROUTE, flags);
} }
/** /**
@@ -3258,17 +3298,33 @@ nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr net
const NMPlatformIP4Route * const NMPlatformIP4Route *
nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric) nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
{ {
NMPObject obj_id;
const NMPObject *obj;
_CHECK_SELF (self, klass, FALSE); _CHECK_SELF (self, klass, FALSE);
return klass->ip4_route_get (self ,ifindex, network, plen, metric); nmp_object_stackinit_id_ip4_route (&obj_id, ifindex, network, plen, metric);
obj = nmp_cache_lookup_obj (nm_platform_get_cache (self), &obj_id);
if (nmp_object_is_visible (obj))
return &obj->ip4_route;
return NULL;
} }
const NMPlatformIP6Route * const NMPlatformIP6Route *
nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric) nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
{ {
NMPObject obj_id;
const NMPObject *obj;
_CHECK_SELF (self, klass, FALSE); _CHECK_SELF (self, klass, FALSE);
return klass->ip6_route_get (self, ifindex, network, plen, metric); metric = nm_utils_ip6_route_metric_normalize (metric);
nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric);
obj = nmp_cache_lookup_obj (nm_platform_get_cache (self), &obj_id);
if (nmp_object_is_visible (obj))
return &obj->ip6_route;
return NULL;
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@@ -667,14 +667,10 @@ typedef struct {
const NMPlatformIP4Address *(*ip4_address_get) (NMPlatform *, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address); const NMPlatformIP4Address *(*ip4_address_get) (NMPlatform *, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
const NMPlatformIP6Address *(*ip6_address_get) (NMPlatform *, int ifindex, struct in6_addr address); const NMPlatformIP6Address *(*ip6_address_get) (NMPlatform *, int ifindex, struct in6_addr address);
GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags);
GArray * (*ip6_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags);
gboolean (*ip4_route_add) (NMPlatform *, const NMPlatformIP4Route *route); gboolean (*ip4_route_add) (NMPlatform *, const NMPlatformIP4Route *route);
gboolean (*ip6_route_add) (NMPlatform *, const NMPlatformIP6Route *route); gboolean (*ip6_route_add) (NMPlatform *, const NMPlatformIP6Route *route);
gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, guint8 plen, guint32 metric); gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, guint8 plen, guint32 metric); gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
const NMPlatformIP4Route *(*ip4_route_get) (NMPlatform *, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
const NMPlatformIP6Route *(*ip6_route_get) (NMPlatform *, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *); gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *);
gboolean (*check_support_user_ipv6ll) (NMPlatform *); gboolean (*check_support_user_ipv6ll) (NMPlatform *);

View File

@@ -339,7 +339,23 @@ NMP_OBJECT_GET_TYPE (const NMPObject *obj)
return obj ? obj->_class->obj_type : NMP_OBJECT_TYPE_UNKNOWN; return obj ? obj->_class->obj_type : NMP_OBJECT_TYPE_UNKNOWN;
} }
#define NMP_OBJECT_CAST_IP4_ROUTE(obj) \
({ \
typeof (*(obj)) *_obj = (obj); \
_nm_unused const NMPObject *_obj_type_check = _obj; \
\
nm_assert (NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP4_ROUTE); \
&_obj->ip4_route; \
})
#define NMP_OBJECT_CAST_IP6_ROUTE(obj) \
({ \
typeof (*(obj)) *_obj = (obj); \
_nm_unused const NMPObject *_obj_type_check = _obj; \
\
nm_assert (NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP6_ROUTE); \
&_obj->ip6_route; \
})
const NMPClass *nmp_class_from_type (NMPObjectType obj_type); const NMPClass *nmp_class_from_type (NMPObjectType obj_type);