summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2016-04-05 14:10:51 +0200
committerThomas Haller <thaller@redhat.com>2016-05-13 13:22:56 +0200
commit0c790c222e9e1abfa33d45010c49152628535c93 (patch)
tree32baae77bda119565d25769eb41bffe016517ba9
parentca6f1e7f25daad1b635a1d7b00056bed10316c49 (diff)
downloadNetworkManager-th/platform-route-identity.tar.gz
WIP: platform: properly handle same routes in platform cacheth/platform-route-identity
From kernels point of view, you can add a new routes as long as there is no existing route that is exactly identical. That effectively means, that every field of the route is part of the ID. Currently, we handle that wrong, thus when kernel notifies platform about two such routes, we would wrongly merge them together. For example: ip link add dev0 type dummy ip link add dev1 type dummy ip link set dev0 up ip link set dev1 up ip addr add 192.168.200.4/24 dev dev0 ip addr add 192.168.201.4/24 dev dev1 ip route add 10.132.5.0/24 dev dev0 ip route append 10.132.5.0/24 via 192.168.212.1 dev dev0 ip route append 10.132.5.0/24 via 192.168.212.1 dev dev0 proto 5 ip route show dev dev0 ip route add 1:2:3:4:5::/64 via fe80::1:a dev dev0 ip route append 1:2:3:4:5::/64 via fe80::1:b dev dev0 ip route append 1:2:3:4:5::/64 via fe80::1:b dev dev0 proto 5 ip -6 route show dev dev0 Note the difference here are the netlink flags: `ip route append` (NLM_F_CREATE|NLM_F_APPEND) `ip route prepend` (NLM_F_CREATE) `ip route add` (NLM_F_CREATE|NLM_F_EXCL) `ip route change` (NLM_F_REPLACE) `ip route replace` (NLM_F_CREATE|NLM_F_REPLACE) Extend platform to consider every property of a route to be part of the ID. Also update the API like route_add(), route_get() and route_delete() to accept full route structures as arguments. For delete, that means you can only delete a route that you know about. But that isn't really actually a problem.
-rw-r--r--shared/nm-test-utils.h39
-rw-r--r--src/devices/tests/Makefile.am3
-rw-r--r--src/nm-default-route-manager.c40
-rw-r--r--src/nm-route-manager.c26
-rw-r--r--src/platform/nm-fake-platform.c268
-rw-r--r--src/platform/nm-linux-platform.c243
-rw-r--r--src/platform/nm-platform.c408
-rw-r--r--src/platform/nm-platform.h100
-rw-r--r--src/platform/nmp-object.c59
-rw-r--r--src/platform/nmp-object.h4
-rw-r--r--src/platform/tests/test-cleanup.c33
-rw-r--r--src/platform/tests/test-common.c414
-rw-r--r--src/platform/tests/test-common.h70
-rw-r--r--src/platform/tests/test-link.c187
-rw-r--r--src/platform/tests/test-route.c200
-rw-r--r--src/tests/test-route-manager.c126
16 files changed, 1530 insertions, 690 deletions
diff --git a/shared/nm-test-utils.h b/shared/nm-test-utils.h
index 0875518cdd..e044ae59ac 100644
--- a/shared/nm-test-utils.h
+++ b/shared/nm-test-utils.h
@@ -1177,6 +1177,13 @@ _nmtst_assert_resolve_relative_path_equals (const char *f1, const char *f2, cons
#ifdef __NETWORKMANAGER_PLATFORM_H__
+#define nmtst_ip4_address_to_ptr(addr) \
+ ({ \
+ guint32 *__addr = g_alloca (sizeof (guint32)); \
+ *__addr = (addr); \
+ (const NMIPAddr *) __addr; \
+ })
+
inline static NMPlatformIP4Address *
nmtst_platform_ip4_address (const char *address, const char *peer_address, guint plen)
{
@@ -1251,7 +1258,9 @@ nmtst_platform_ip6_address_full (const char *address, const char *peer_address,
}
inline static NMPlatformIP4Route *
-nmtst_platform_ip4_route (const char *network, guint plen, const char *gateway)
+nmtst_platform_ip4_route (const char *network,
+ guint8 plen,
+ const char *gateway)
{
static NMPlatformIP4Route route;
@@ -1266,10 +1275,15 @@ nmtst_platform_ip4_route (const char *network, guint plen, const char *gateway)
}
inline static NMPlatformIP4Route *
-nmtst_platform_ip4_route_full (const char *network, guint plen, const char *gateway,
- int ifindex, NMIPConfigSource source,
- guint metric, guint mss,
+nmtst_platform_ip4_route_full (int ifindex,
+ const char *network,
+ guint8 plen,
+ const char *gateway,
+ NMIPConfigSource source,
+ guint32 metric,
+ guint32 mss,
guint8 scope,
+ bool scope_is_set,
const char *pref_src)
{
NMPlatformIP4Route *route = nmtst_platform_ip4_route (network, plen, gateway);
@@ -1278,14 +1292,17 @@ nmtst_platform_ip4_route_full (const char *network, guint plen, const char *gate
route->rt_source = source;
route->metric = metric;
route->mss = mss;
- route->scope_inv = nm_platform_route_scope_inv (scope);
+ route->rt_scope = scope;
+ route->rt_scope_is_set = scope_is_set;
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)
+nmtst_platform_ip6_route (const char *network,
+ guint8 plen,
+ const char *gateway)
{
static NMPlatformIP6Route route;
@@ -1300,9 +1317,13 @@ nmtst_platform_ip6_route (const char *network, guint plen, const char *gateway)
}
inline static NMPlatformIP6Route *
-nmtst_platform_ip6_route_full (const char *network, guint plen, const char *gateway,
- int ifindex, NMIPConfigSource source,
- guint metric, guint mss)
+nmtst_platform_ip6_route_full (int ifindex,
+ const char *network,
+ guint8 plen,
+ const char *gateway,
+ NMIPConfigSource source,
+ guint32 metric,
+ guint32 mss)
{
NMPlatformIP6Route *route = nmtst_platform_ip6_route (network, plen, gateway);
diff --git a/src/devices/tests/Makefile.am b/src/devices/tests/Makefile.am
index cd1ef6edd3..6fd5f8f5a3 100644
--- a/src/devices/tests/Makefile.am
+++ b/src/devices/tests/Makefile.am
@@ -12,7 +12,8 @@ AM_CPPFLAGS = \
-I$(top_builddir)/src \
-DG_LOG_DOMAIN=\""NetworkManager"\" \
-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \
- $(GLIB_CFLAGS)
+ $(GLIB_CFLAGS) \
+ $(GUDEV_CFLAGS)
AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
AM_LDFLAGS = $(GLIB_LIBS) $(CODE_COVERAGE_LDFLAGS)
diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c
index a637c6cb88..4e824c7a6d 100644
--- a/src/nm-default-route-manager.c
+++ b/src/nm-default-route-manager.c
@@ -287,24 +287,25 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g
return FALSE;
if (vtable->vt->is_ip4) {
- success = nm_platform_ip4_route_add (priv->platform,
- entry->route.rx.ifindex,
- entry->route.rx.rt_source,
- 0,
- 0,
- entry->route.r4.gateway,
- 0,
- entry->effective_metric,
- entry->route.rx.mss);
+ NMPlatformIP4Route r = {
+ .ifindex = entry->route.rx.ifindex,
+ .rt_source = entry->route.rx.rt_source,
+ .gateway = entry->route.r4.gateway,
+ .metric = entry->effective_metric,
+ .mss = entry->route.rx.mss,
+ };
+
+ success = nm_platform_ip4_route_add (priv->platform, &r);
} else {
- success = nm_platform_ip6_route_add (priv->platform,
- entry->route.rx.ifindex,
- entry->route.rx.rt_source,
- in6addr_any,
- 0,
- entry->route.r6.gateway,
- entry->effective_metric,
- entry->route.rx.mss);
+ NMPlatformIP6Route r = {
+ .ifindex = entry->route.rx.ifindex,
+ .rt_source = entry->route.rx.rt_source,
+ .gateway = entry->route.r6.gateway,
+ .metric = entry->effective_metric,
+ .mss = entry->route.rx.mss,
+ };
+
+ success = nm_platform_ip6_route_add (priv->platform, &r);
}
if (!success) {
_LOGW (vtable->vt->addr_family, "failed to add default route %s with effective metric %u",
@@ -332,6 +333,9 @@ _platform_route_sync_flush (const VTableIP *vtable, NMDefaultRouteManager *self,
route = _vt_route_index (vtable, routes, i);
+ nm_assert (memcmp (route->network_ptr, &nm_ip_addr_zero, vtable->vt->is_ip4 ? sizeof (in_addr_t) : sizeof (struct in6_addr)) == 0);
+ nm_assert (route->plen == 0);
+
/* look at all entries and see if the route for this ifindex pair is
* a known entry. */
for (j = 0; j < entries->len; j++) {
@@ -355,7 +359,7 @@ _platform_route_sync_flush (const VTableIP *vtable, NMDefaultRouteManager *self,
*/
if ( !entry
&& (has_ifindex_synced || ifindex_to_flush == route->ifindex)) {
- vtable->vt->route_delete_default (priv->platform, route->ifindex, route->metric);
+ vtable->vt->route_delete (priv->platform, (NMPlatformIPXRoute *) route);
changed = TRUE;
}
}
diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c
index 2d4c7d9595..54b54b84e3 100644
--- a/src/nm-route-manager.c
+++ b/src/nm-route-manager.c
@@ -574,9 +574,10 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
&& 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. */
+ nm_assert (cur_plat_route->rx.ifindex == ifindex);
_LOGt (vtable->vt->addr_family, "%3d: platform rt-rm #%u - %s", ifindex, i_plat_routes,
vtable->vt->route_to_string (cur_plat_route, NULL, 0));
- vtable->vt->route_delete (priv->platform, ifindex, cur_plat_route);
+ vtable->vt->route_delete (priv->platform, cur_plat_route);
}
}
}
@@ -741,8 +742,10 @@ next:
/* 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);
+ || *p_effective_metric != cur_plat_route->rx.metric) {
+ nm_assert (cur_plat_route->rx.ifindex == ifindex);
+ vtable->vt->route_delete (priv->platform, cur_plat_route);
+ }
cur_plat_route = _get_next_plat_route (plat_routes_idx, FALSE, &i_plat_routes);
}
@@ -815,15 +818,15 @@ next:
gateway_routes = g_array_new (FALSE, FALSE, sizeof (guint));
g_array_append_val (gateway_routes, i_ipx_routes);
} else
- vtable->vt->route_add (priv->platform, 0, cur_ipx_route, *p_effective_metric);
+ vtable->vt->route_add (priv->platform, cur_ipx_route, 0, *p_effective_metric);
}
if (gateway_routes) {
for (i = 0; i < gateway_routes->len; i++) {
i_ipx_routes = g_array_index (gateway_routes, guint, i);
- vtable->vt->route_add (priv->platform, 0,
+ vtable->vt->route_add (priv->platform,
ipx_routes->index->entries[i_ipx_routes],
- effective_metrics[i_ipx_routes]);
+ 0, effective_metrics[i_ipx_routes]);
}
g_array_unref (gateway_routes);
}
@@ -872,7 +875,7 @@ next:
|| 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)) {
+ if (!vtable->vt->route_add (priv->platform, cur_ipx_route, ifindex, *p_effective_metric)) {
if (cur_ipx_route->rx.rt_source < NM_IP_CONFIG_SOURCE_USER) {
_LOGD (vtable->vt->addr_family,
"ignore error adding IPv%c route to kernel: %s",
@@ -986,6 +989,7 @@ _ip4_device_routes_idle_cb (IP4DeviceRoutePurgeEntry *entry)
{
NMRouteManager *self;
NMRouteManagerPrivate *priv;
+ NMPObject obj;
nm_clear_g_source (&entry->idle_id);
@@ -998,11 +1002,9 @@ _ip4_device_routes_idle_cb (IP4DeviceRoutePurgeEntry *entry)
_LOGt (vtable_v4.vt->addr_family, "device-route: delete %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
- nm_platform_ip4_route_delete (priv->platform,
- entry->obj->ip4_route.ifindex,
- entry->obj->ip4_route.network,
- entry->obj->ip4_route.plen,
- entry->obj->ip4_route.metric);
+ nmp_object_stackinit_id_ip4_route (&obj, &entry->obj->ip4_route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
+
+ nm_platform_ip4_route_delete (priv->platform, &obj.ip4_route);
g_hash_table_remove (priv->ip4_device_routes.entries, entry->obj);
_ip4_device_routes_cancel (self);
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index 6582b0cf03..69e4982a78 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -69,8 +69,8 @@ typedef struct {
GArray *links;
GArray *ip4_addresses;
GArray *ip6_addresses;
- GArray *ip4_routes;
- GArray *ip6_routes;
+ GPtrArray *ip4_routes;
+ GPtrArray *ip6_routes;
} NMFakePlatformPrivate;
typedef struct {
@@ -109,6 +109,37 @@ _ip4_address_equal_peer_net (in_addr_t peer1, in_addr_t peer2, guint8 plen)
/******************************************************************/
+static NMPObject *
+_get_at_idx (GPtrArray *array, gsize idx, NMPObjectType expected_type)
+{
+ NMPObject *obj;
+
+ g_assert (array);
+ g_assert (idx < array->len);
+
+ obj = array->pdata[idx];
+
+ g_assert (NMP_OBJECT_IS_VALID (obj));
+ if (expected_type != NMP_OBJECT_TYPE_UNKNOWN)
+ g_assert (expected_type == NMP_OBJECT_GET_TYPE (obj));
+
+ return obj;
+}
+
+static NMPlatformIP4Route *
+_get_at_idx_ip4_route (GPtrArray *array, gsize idx)
+{
+ return &(_get_at_idx (array, idx, NMP_OBJECT_TYPE_IP4_ROUTE))->ip4_route;
+}
+
+static NMPlatformIP6Route *
+_get_at_idx_ip6_route (GPtrArray *array, gsize idx)
+{
+ return &(_get_at_idx (array, idx, NMP_OBJECT_TYPE_IP6_ROUTE))->ip6_route;
+}
+
+/******************************************************************/
+
static gboolean
sysctl_set (NMPlatform *platform, const char *path, const char *value)
{
@@ -352,13 +383,13 @@ link_delete (NMPlatform *platform, int ifindex)
memset (address, 0, sizeof (*address));
}
for (i = 0; i < priv->ip4_routes->len; i++) {
- NMPlatformIP4Route *route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
+ NMPlatformIP4Route *route = _get_at_idx_ip4_route (priv->ip4_routes, i);
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);
+ NMPlatformIP6Route *route = _get_at_idx_ip6_route (priv->ip6_routes, i);
if (route->ifindex == ifindex)
memset (route, 0, sizeof (*route));
@@ -1098,7 +1129,7 @@ ip4_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags fl
/* Fill routes */
for (i = 0; i < priv->ip4_routes->len; i++) {
- route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
+ route = _get_at_idx_ip4_route (priv->ip4_routes, 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))
@@ -1128,7 +1159,7 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags fl
/* Fill routes */
for (i = 0; i < priv->ip6_routes->len; i++) {
- route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
+ route = _get_at_idx_ip6_route (priv->ip6_routes, 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))
@@ -1144,224 +1175,191 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags fl
}
static gboolean
-ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
+ip4_route_delete (NMPlatform *platform, const NMPlatformIP4Route *route)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
- int i;
+ NMPObject obj, o;
+ NMPlatformIP4Route *r;
+ guint i;
+
+ nmp_object_stackinit_id_ip4_route (&obj, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
for (i = 0; i < priv->ip4_routes->len; i++) {
- NMPlatformIP4Route *route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
- NMPlatformIP4Route deleted_route;
+ r = _get_at_idx_ip4_route (priv->ip4_routes, i);
- if ( route->ifindex != ifindex
- || route->network != network
- || route->plen != plen
- || route->metric != metric)
+ nmp_object_stackinit_id_ip4_route (&o, r, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
+ if (!nmp_object_id_equal (&obj, &o))
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, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex, &deleted_route, NM_PLATFORM_SIGNAL_REMOVED);
+ g_ptr_array_remove_index (priv->ip4_routes, i);
+ g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP4_ROUTE, obj.ip_route.ifindex, &obj.ip4_route, NM_PLATFORM_SIGNAL_REMOVED);
}
return TRUE;
}
static gboolean
-ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
+ip6_route_delete (NMPlatform *platform, const NMPlatformIP6Route *route)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
- int i;
+ NMPObject obj, o;
+ NMPlatformIP6Route *r;
+ guint i;
- metric = nm_utils_ip6_route_metric_normalize (metric);
+ nmp_object_stackinit_id_ip6_route (&obj, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
for (i = 0; i < priv->ip6_routes->len; i++) {
- NMPlatformIP6Route *route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
- NMPlatformIP6Route deleted_route;
+ r = _get_at_idx_ip6_route (priv->ip6_routes, i);
- if ( route->ifindex != ifindex
- || !IN6_ARE_ADDR_EQUAL (&route->network, &network)
- || route->plen != plen
- || route->metric != metric)
+ nmp_object_stackinit_id_ip6_route (&o, r, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
+ if (!nmp_object_id_equal (&obj, &o))
continue;
- memcpy (&deleted_route, route, sizeof (deleted_route));
- g_array_remove_index (priv->ip6_routes, i);
- g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP6_ROUTE, ifindex, &deleted_route, NM_PLATFORM_SIGNAL_REMOVED);
+ g_ptr_array_remove_index (priv->ip6_routes, i);
+ g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP6_ROUTE, obj.ip_route.ifindex, &obj.ip6_route, NM_PLATFORM_SIGNAL_REMOVED);
}
return TRUE;
}
static gboolean
-ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
- in_addr_t network, guint8 plen, in_addr_t gateway,
- in_addr_t pref_src, guint32 metric, guint32 mss)
+ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
- NMPlatformIP4Route route;
+ NMPObject obj, o;
+ NMPlatformIP4Route *r;
guint i;
- guint8 scope;
+ NMPlatformSignalChangeType change_type = NM_PLATFORM_SIGNAL_CHANGED;
- g_assert (plen <= 32);
+ g_assert (route && route->plen <= 32);
- scope = gateway == 0 ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
+ nmp_object_stackinit_id_ip4_route (&obj, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
- memset (&route, 0, sizeof (route));
- route.ifindex = ifindex;
- route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (source);
- route.network = nm_utils_ip4_address_clear_host_address (network, plen);
- route.plen = plen;
- route.gateway = gateway;
- route.metric = metric;
- route.mss = mss;
- route.scope_inv = nm_platform_route_scope_inv (scope);
-
- if (gateway) {
+ if (obj.ip4_route.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 (gateway) >> (32 - item->plen);
+ guint32 gate, host;
+
+ r = _get_at_idx_ip4_route (priv->ip4_routes, i);
- if (ifindex == item->ifindex && gate == host)
+ gate = ntohl (r->network) >> (32 - r->plen);
+ host = ntohl (obj.ip4_route.gateway) >> (32 - r->plen);
+
+ if (obj.ip_route.ifindex == r->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",
- route.ifindex, nm_utils_inet4_ntop (route.network, NULL), route.plen, route.metric);
+ nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip4-route '%s': Network Unreachable",
+ nm_platform_ip4_route_to_string (route, NULL, 0));
return FALSE;
}
}
for (i = 0; i < priv->ip4_routes->len; i++) {
- NMPlatformIP4Route *item = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
-
- if (item->network != route.network)
- continue;
- if (item->plen != route.plen)
- continue;
- if (item->metric != metric)
- continue;
+ r = _get_at_idx_ip4_route (priv->ip4_routes, i);
- if (item->ifindex != route.ifindex) {
- ip4_route_delete (platform, item->ifindex, item->network, item->plen, item->metric);
- i--;
+ nmp_object_stackinit_id_ip4_route (&o, r, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
+ if (!nmp_object_id_equal (&obj, &o))
continue;
- }
- memcpy (item, &route, sizeof (route));
- g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex, &route, NM_PLATFORM_SIGNAL_CHANGED);
- return TRUE;
+ *r = obj.ip4_route;
+ goto out;
}
- g_array_append_val (priv->ip4_routes, route);
- g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex, &route, NM_PLATFORM_SIGNAL_ADDED);
-
+ g_ptr_array_add (priv->ip4_routes, nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, &obj.object));
+ r = _get_at_idx_ip4_route (priv->ip4_routes, priv->ip4_routes->len - 1);
+ change_type = NM_PLATFORM_SIGNAL_ADDED;
+out:
+ g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP4_ROUTE, r->ifindex, r, change_type);
return TRUE;
}
static gboolean
-ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
- struct in6_addr network, guint8 plen, struct in6_addr gateway,
- guint32 metric, guint32 mss)
+ip6_route_add (NMPlatform *platform, const NMPlatformIP6Route *route)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
- NMPlatformIP6Route route;
+ NMPObject obj, o;
+ NMPlatformIP6Route *r;
guint i;
+ NMPlatformSignalChangeType change_type = NM_PLATFORM_SIGNAL_CHANGED;
- metric = nm_utils_ip6_route_metric_normalize (metric);
+ g_assert (route && route->plen <= 128);
- memset (&route, 0, sizeof (route));
- route.ifindex = ifindex;
- route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (source);
- nm_utils_ip6_address_clear_host_address (&route.network, &network, plen);
- route.plen = plen;
- route.gateway = gateway;
- route.metric = metric;
- route.mss = mss;
+ nmp_object_stackinit_id_ip6_route (&obj, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
- if (!IN6_IS_ADDR_UNSPECIFIED(&gateway)) {
+ if (!IN6_IS_ADDR_UNSPECIFIED (&obj.ip6_route.gateway)) {
for (i = 0; i < priv->ip6_routes->len; i++) {
- NMPlatformIP6Route *item = &g_array_index (priv->ip6_routes,
- NMPlatformIP6Route, i);
- guint8 gate_bits = 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 ( ifindex == item->ifindex
- && memcmp (&gateway, &item->network, item->plen / 8) == 0
- && gate_bits == host_bits)
+ struct in6_addr a_gateway, a_network;
+
+ r = _get_at_idx_ip6_route (priv->ip6_routes, i);
+ if (obj.ip_route.ifindex != r->ifindex)
+ continue;
+
+ nm_utils_ip6_address_clear_host_address (&a_gateway, &obj.ip6_route.gateway, r->plen);
+ nm_utils_ip6_address_clear_host_address (&a_network, &r->network, r->plen);
+ if (memcmp (&a_gateway, &a_network, sizeof (struct in6_addr)) == 0)
break;
}
if (i == priv->ip6_routes->len) {
- nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip6-route '%d: %s/%d %d': Network Unreachable",
- route.ifindex, nm_utils_inet6_ntop (&route.network, NULL), route.plen, route.metric);
+ nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip6-route '%s': Network Unreachable",
+ nm_platform_ip6_route_to_string (route, NULL, 0));
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, &route.network))
- continue;
- if (item->plen != route.plen)
- continue;
- if (item->metric != metric)
- continue;
+ r = _get_at_idx_ip6_route (priv->ip6_routes, i);
- if (item->ifindex != route.ifindex) {
- ip6_route_delete (platform, item->ifindex, item->network, item->plen, item->metric);
- i--;
+ nmp_object_stackinit_id_ip6_route (&o, r, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
+ if (!nmp_object_id_equal (&obj, &o))
continue;
- }
- memcpy (item, &route, sizeof (route));
- g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP6_ROUTE, ifindex, &route, NM_PLATFORM_SIGNAL_CHANGED);
- return TRUE;
+ *r = obj.ip6_route;
+ goto out;
}
- g_array_append_val (priv->ip6_routes, route);
- g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP6_ROUTE, ifindex, &route, NM_PLATFORM_SIGNAL_ADDED);
-
+ g_ptr_array_add (priv->ip6_routes, nmp_object_new (NMP_OBJECT_TYPE_IP6_ROUTE, &obj.object));
+ r = _get_at_idx_ip6_route (priv->ip6_routes, priv->ip6_routes->len - 1);
+ change_type = NM_PLATFORM_SIGNAL_ADDED;
+out:
+ g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP6_ROUTE, r->ifindex, r, change_type);
return TRUE;
}
static const NMPlatformIP4Route *
-ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
+ip4_route_get (NMPlatform *platform, const NMPlatformIP4Route *route)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
- int i;
+ guint i;
+ NMPObject obj_id, o;
+
+ nmp_object_stackinit_id_ip4_route (&obj_id, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
for (i = 0; i < priv->ip4_routes->len; i++) {
- NMPlatformIP4Route *route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
+ const NMPlatformIP4Route *r = _get_at_idx_ip4_route (priv->ip4_routes, i);
- if (route->ifindex == ifindex
- && route->network == network
- && route->plen == plen
- && route->metric == metric)
- return route;
+ nmp_object_stackinit_id_ip4_route (&o, r, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
+ if (nmp_object_id_equal (&obj_id, &o))
+ return r;
}
return NULL;
}
static const NMPlatformIP6Route *
-ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
+ip6_route_get (NMPlatform *platform, const NMPlatformIP6Route *route)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
- int i;
+ guint i;
+ NMPObject obj_id, o;
- metric = nm_utils_ip6_route_metric_normalize (metric);
+ nmp_object_stackinit_id_ip6_route (&obj_id, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
for (i = 0; i < priv->ip6_routes->len; i++) {
- NMPlatformIP6Route *route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
+ NMPlatformIP6Route *r = _get_at_idx_ip6_route (priv->ip6_routes, i);
- if (route->ifindex == ifindex
- && IN6_ARE_ADDR_EQUAL (&route->network, &network)
- && route->plen == plen
- && route->metric == metric)
- return route;
+ nmp_object_stackinit_id_ip6_route (&o, r, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
+ if (nmp_object_id_equal (&obj_id, &o))
+ return r;
}
return NULL;
@@ -1378,8 +1376,8 @@ nm_fake_platform_init (NMFakePlatform *fake_platform)
priv->links = g_array_new (TRUE, TRUE, sizeof (NMFakePlatformLink));
priv->ip4_addresses = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP4Address));
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));
+ priv->ip4_routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
+ priv->ip6_routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
}
void
@@ -1419,8 +1417,8 @@ nm_fake_platform_finalize (GObject *object)
g_array_unref (priv->links);
g_array_unref (priv->ip4_addresses);
g_array_unref (priv->ip6_addresses);
- g_array_unref (priv->ip4_routes);
- g_array_unref (priv->ip6_routes);
+ g_ptr_array_unref (priv->ip4_routes);
+ g_ptr_array_unref (priv->ip6_routes);
G_OBJECT_CLASS (nm_fake_platform_parent_class)->finalize (object);
}
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 82e673a3c1..baf4d7ccab 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -1864,8 +1864,10 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
else
obj->ip6_route.gateway = nh.gateway.addr6;
- if (is_v4)
- obj->ip4_route.scope_inv = nm_platform_route_scope_inv (rtm->rtm_scope);
+ if (is_v4) {
+ obj->ip4_route.rt_scope = rtm->rtm_scope;
+ obj->ip4_route.rt_scope_is_set = TRUE;
+ }
if (is_v4) {
if (_check_addr_or_errout (tb, RTA_PREFSRC, addr_len))
@@ -2229,77 +2231,79 @@ nla_put_failure:
static struct nl_msg *
_nl_msg_new_route (int nlmsg_type,
int nlmsg_flags,
- int family,
- int ifindex,
- NMIPConfigSource source,
- unsigned char scope,
- gconstpointer network,
- guint8 plen,
- gconstpointer gateway,
- guint32 metric,
- guint32 mss,
- gconstpointer pref_src)
+ const NMPObject *obj)
{
- struct nl_msg *msg;
- struct rtmsg rtmsg = {
- .rtm_family = family,
- .rtm_tos = 0,
- .rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */
- .rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (source),
- .rtm_scope = scope,
- .rtm_type = RTN_UNICAST,
- .rtm_flags = 0,
- .rtm_dst_len = plen,
- .rtm_src_len = 0,
- };
+ int addr_family;
+ gboolean is_v4;
+ const NMIPAddr *gateway;
NMIPAddr network_clean;
-
gsize addr_len;
+ struct nl_msg *msg;
- nm_assert (NM_IN_SET (family, AF_INET, AF_INET6));
+ nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
nm_assert (NM_IN_SET (nlmsg_type, RTM_NEWROUTE, RTM_DELROUTE));
- nm_assert (network);
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
if (!msg)
- g_return_val_if_reached (NULL);
+ return NULL;
- if (nlmsg_append (msg, &rtmsg, sizeof (rtmsg), NLMSG_ALIGNTO) < 0)
- goto nla_put_failure;
+ addr_family = NMP_OBJECT_GET_CLASS (obj)->addr_family;
+ is_v4 = (addr_family == AF_INET);
+ addr_len = is_v4 ? sizeof (in_addr_t) : sizeof (struct in6_addr);
+
+ gateway = is_v4
+ ? (gpointer) &obj->ip4_route.gateway
+ : (gpointer) &obj->ip6_route.gateway;
+
+ {
+ struct rtmsg rtmsg = {
+ .rtm_family = addr_family,
+ .rtm_tos = 0,
+ .rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */
+ .rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (obj->ip_route.rt_source),
+ .rtm_scope = is_v4
+ ? nm_platform_route_scope_from_ip4_route (&obj->ip4_route)
+ : nm_platform_route_scope_for_ip6_gateway (&gateway->addr6),
+ .rtm_type = RTN_UNICAST,
+ .rtm_flags = 0,
+ .rtm_dst_len = obj->ip_route.plen,
+ .rtm_src_len = 0,
+ };
- addr_len = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr);
+ if (nlmsg_append (msg, &rtmsg, sizeof (rtmsg), NLMSG_ALIGNTO) < 0)
+ goto nla_put_failure;
+ }
- nm_utils_ipx_address_clear_host_address (family, &network_clean, network, plen);
+ nm_utils_ipx_address_clear_host_address (addr_family, &network_clean, obj->ip_route.network_ptr, obj->ip_route.plen);
NLA_PUT (msg, RTA_DST, addr_len, &network_clean);
- NLA_PUT_U32 (msg, RTA_PRIORITY, metric);
+ NLA_PUT_U32 (msg, RTA_PRIORITY, obj->ip_route.metric);
- if (pref_src)
- NLA_PUT (msg, RTA_PREFSRC, addr_len, pref_src);
+ if (is_v4 && obj->ip4_route.pref_src)
+ NLA_PUT (msg, RTA_PREFSRC, addr_len, &obj->ip4_route.pref_src);
- if (mss > 0) {
+ if (obj->ip_route.mss > 0) {
struct nlattr *metrics;
metrics = nla_nest_start (msg, RTA_METRICS);
if (!metrics)
goto nla_put_failure;
- NLA_PUT_U32 (msg, RTAX_ADVMSS, mss);
+ NLA_PUT_U32 (msg, RTAX_ADVMSS, obj->ip_route.mss);
nla_nest_end(msg, metrics);
}
/* We currently don't have need for multi-hop routes... */
- if ( gateway
- && memcmp (gateway, &nm_ip_addr_zero, addr_len) != 0)
+ if (memcmp (gateway, &nm_ip_addr_zero, addr_len) != 0)
NLA_PUT (msg, RTA_GATEWAY, addr_len, gateway);
- NLA_PUT_U32 (msg, RTA_OIF, ifindex);
+ NLA_PUT_U32 (msg, RTA_OIF, obj->ip_route.ifindex);
return msg;
nla_put_failure:
nlmsg_free (msg);
- g_return_val_if_reached (NULL);
+ return NULL;
}
/******************************************************************/
@@ -3902,6 +3906,7 @@ do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
+ gboolean success = FALSE;
int nle;
char s_buf[256];
const NMPObject *obj;
@@ -3925,9 +3930,15 @@ do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
nm_assert (seq_result);
- _NMLOG (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK
- ? LOGL_DEBUG
- : LOGL_ERR,
+ if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK)
+ success = TRUE;
+ else if ( (int) seq_result == -EEXIST
+ && NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_id),
+ NMP_OBJECT_TYPE_IP4_ROUTE,
+ NMP_OBJECT_TYPE_IP6_ROUTE))
+ success = TRUE;
+
+ _NMLOG (success ? LOGL_DEBUG : LOGL_ERR,
"do-add-%s[%s]: %s",
NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name,
nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0),
@@ -3950,7 +3961,7 @@ do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
/* Adding is only successful, if kernel reported success *and* we have the
* expected object in cache afterwards. */
- return obj && seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
+ return obj && success;
}
static gboolean
@@ -3963,8 +3974,6 @@ do_delete_object (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
gboolean success = TRUE;
const char *log_detail = "";
- event_handler_read_netlink (platform, FALSE);
-
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
if (nle < 0) {
_LOGE ("do-delete-%s[%s]: failure sending netlink request \"%s\" (%d)",
@@ -4122,6 +4131,8 @@ link_delete (NMPlatform *platform, int ifindex)
NMPObject obj_id;
const NMPObject *obj;
+ delayed_action_handle_all (platform, TRUE);
+
obj = nmp_cache_lookup_link (priv->cache, ifindex);
if (!obj || !obj->_link.netlink.is_in_netlink)
return FALSE;
@@ -4132,6 +4143,8 @@ link_delete (NMPlatform *platform, int ifindex)
NULL,
0,
0);
+ if (!nlmsg)
+ g_return_val_if_reached (FALSE);
nmp_object_stackinit_id_link (&obj_id, ifindex);
return do_delete_object (platform, &obj_id, nlmsg);
@@ -5494,6 +5507,8 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 pl
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
NMPObject obj_id;
+ delayed_action_handle_all (platform, TRUE);
+
nlmsg = _nl_msg_new_address (RTM_DELADDR,
0,
AF_INET,
@@ -5519,6 +5534,8 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, gui
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
NMPObject obj_id;
+ delayed_action_handle_all (platform, TRUE);
+
nlmsg = _nl_msg_new_address (RTM_DELADDR,
0,
AF_INET6,
@@ -5618,146 +5635,93 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags fl
}
static gboolean
-ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
- in_addr_t network, guint8 plen, in_addr_t gateway,
- in_addr_t pref_src, guint32 metric, guint32 mss)
+ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route)
{
NMPObject obj_id;
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
+ nmp_object_stackinit_id_ip4_route (&obj_id, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
+
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
- NLM_F_CREATE | NLM_F_REPLACE,
- AF_INET,
- ifindex,
- source,
- gateway ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK,
- &network,
- plen,
- &gateway,
- metric,
- mss,
- pref_src ? &pref_src : NULL);
-
- nmp_object_stackinit_id_ip4_route (&obj_id, ifindex, network, plen, metric);
+ NLM_F_CREATE | NLM_F_APPEND,
+ &obj_id);
+ if (!nlmsg)
+ g_return_val_if_reached (FALSE);
+
return do_add_addrroute (platform, &obj_id, nlmsg);
}
static gboolean
-ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
- struct in6_addr network, guint8 plen, struct in6_addr gateway,
- guint32 metric, guint32 mss)
+ip6_route_add (NMPlatform *platform, const NMPlatformIP6Route *route)
{
NMPObject obj_id;
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
+ nmp_object_stackinit_id_ip6_route (&obj_id, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
+
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
- NLM_F_CREATE | NLM_F_REPLACE,
- AF_INET6,
- ifindex,
- source,
- !IN6_IS_ADDR_UNSPECIFIED (&gateway) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK,
- &network,
- plen,
- &gateway,
- metric,
- mss,
- NULL);
-
- nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric);
+ NLM_F_CREATE | NLM_F_APPEND,
+ &obj_id);
+ if (!nlmsg)
+ g_return_val_if_reached (FALSE);
+
return do_add_addrroute (platform, &obj_id, nlmsg);
}
static gboolean
-ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
+ip4_route_delete (NMPlatform *platform, const NMPlatformIP4Route *route)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
NMPObject obj_id;
- nmp_object_stackinit_id_ip4_route (&obj_id, ifindex, network, plen, metric);
+ nmp_object_stackinit_id_ip4_route (&obj_id, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
- if (metric == 0) {
- /* Deleting an IPv4 route with metric 0 does not only delete an exectly matching route.
- * If no route with metric 0 exists, it might delete another route to the same destination.
- * For nm_platform_ip4_route_delete() we don't want this semantic.
- *
- * Instead, make sure that we have the most recent state and process all
- * delayed actions (including re-reading data from netlink). */
- delayed_action_handle_all (platform, TRUE);
-
- if (!nmp_cache_lookup_obj (priv->cache, &obj_id)) {
- /* hmm... we are about to delete an IP4 route with metric 0. We must only
- * send the delete request if such a route really exists. Above we refreshed
- * the platform cache, still no such route exists.
- *
- * Be extra careful and reload the routes. We must be sure that such a
- * route doesn't exists, because when we add an IPv4 address, we immediately
- * afterwards try to delete the kernel-added device route with metric 0.
- * It might be, that we didn't yet get the notification about that route.
- *
- * FIXME: once our ip4_address_add() is sure that upon return we have
- * the latest state from in the platform cache, we might save this
- * additional expensive cache-resync. */
- do_request_one_type (platform, NMP_OBJECT_TYPE_IP4_ROUTE);
+ delayed_action_handle_all (platform, TRUE);
- if (!nmp_cache_lookup_obj (priv->cache, &obj_id))
- return TRUE;
- }
- }
+ if (!nmp_cache_lookup_obj (priv->cache, &obj_id))
+ return TRUE;
nlmsg = _nl_msg_new_route (RTM_DELROUTE,
0,
- AF_INET,
- ifindex,
- NM_IP_CONFIG_SOURCE_UNKNOWN,
- RT_SCOPE_NOWHERE,
- &network,
- plen,
- NULL,
- metric,
- 0,
- NULL);
+ &obj_id);
if (!nlmsg)
- return FALSE;
+ g_return_val_if_reached (FALSE);
return do_delete_object (platform, &obj_id, nlmsg);
}
static gboolean
-ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
+ip6_route_delete (NMPlatform *platform, const NMPlatformIP6Route *route)
{
+ NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
NMPObject obj_id;
- metric = nm_utils_ip6_route_metric_normalize (metric);
+ nmp_object_stackinit_id_ip6_route (&obj_id, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
+
+ delayed_action_handle_all (platform, TRUE);
+
+ if (!nmp_cache_lookup_obj (priv->cache, &obj_id))
+ return TRUE;
nlmsg = _nl_msg_new_route (RTM_DELROUTE,
0,
- AF_INET6,
- ifindex,
- NM_IP_CONFIG_SOURCE_UNKNOWN,
- RT_SCOPE_NOWHERE,
- &network,
- plen,
- NULL,
- metric,
- 0,
- NULL);
+ &obj_id);
if (!nlmsg)
- return FALSE;
-
- nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric);
+ g_return_val_if_reached (FALSE);
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)
+ip4_route_get (NMPlatform *platform, const NMPlatformIP4Route *route)
{
NMPObject obj_id;
const NMPObject *obj;
- nmp_object_stackinit_id_ip4_route (&obj_id, ifindex, network, plen, metric);
+ nmp_object_stackinit_id_ip4_route (&obj_id, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
+
obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_id);
if (nmp_object_is_visible (obj))
return &obj->ip4_route;
@@ -5765,14 +5729,13 @@ ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen
}
static const NMPlatformIP6Route *
-ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
+ip6_route_get (NMPlatform *platform, const NMPlatformIP6Route *route)
{
NMPObject obj_id;
const NMPObject *obj;
- metric = nm_utils_ip6_route_metric_normalize (metric);
+ nmp_object_stackinit_id_ip6_route (&obj_id, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
- nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric);
obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_id);
if (nmp_object_is_visible (obj))
return &obj->ip6_route;
@@ -5928,7 +5891,7 @@ continue_reading:
int errsv = e->error > 0 ? e->error : -e->error;
/* Error message reported back from kernel. */
- _LOGD ("netlink: recvmsg: error message from kernel: %s (%d) for request %d",
+ _LOGT ("netlink: recvmsg: error message from kernel: %s (%d) for request %d",
strerror (errsv),
errsv,
nlmsg_hdr (msg)->nlmsg_seq);
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 500db9b621..6fdfda27a2 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -2870,14 +2870,7 @@ nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRoute
/**
* nm_platform_ip4_route_add:
* @self:
- * @ifindex:
- * @source:
- * network:
- * plen:
- * gateway:
- * pref_src:
- * metric:
- * mss:
+ * @route:
*
* For kernel, a gateway can be either explicitly set or left
* at zero (0.0.0.0). In addition, there is the scope of the IPv4
@@ -2898,99 +2891,69 @@ nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRoute
* Returns: %TRUE in case of success.
*/
gboolean
-nm_platform_ip4_route_add (NMPlatform *self,
- int ifindex, NMIPConfigSource source,
- in_addr_t network, guint8 plen,
- in_addr_t gateway, in_addr_t pref_src,
- guint32 metric, guint32 mss)
+nm_platform_ip4_route_add (NMPlatform *self, const NMPlatformIP4Route *route)
{
_CHECK_SELF (self, klass, FALSE);
- g_return_val_if_fail (plen <= 32, FALSE);
+ g_return_val_if_fail (route, FALSE);
+ g_return_val_if_fail (route->plen <= 32, FALSE);
- if (_LOGD_ENABLED ()) {
- NMPlatformIP4Route route = { 0 };
-
- route.ifindex = ifindex;
- route.rt_source = source;
- route.network = network;
- route.plen = plen;
- route.gateway = gateway;
- route.metric = metric;
- route.mss = mss;
- route.pref_src = pref_src;
-
- _LOGD ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (&route, NULL, 0));
- }
- return klass->ip4_route_add (self, ifindex, source, network, plen, gateway, pref_src, metric, mss);
+ _LOGD ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (route, NULL, 0));
+ return klass->ip4_route_add (self, route);
}
gboolean
-nm_platform_ip6_route_add (NMPlatform *self,
- int ifindex, NMIPConfigSource source,
- struct in6_addr network, guint8 plen, struct in6_addr gateway,
- guint32 metric, guint32 mss)
+nm_platform_ip6_route_add (NMPlatform *self, const NMPlatformIP6Route *route)
{
_CHECK_SELF (self, klass, FALSE);
- g_return_val_if_fail (plen <= 128, FALSE);
+ g_return_val_if_fail (route, FALSE);
+ g_return_val_if_fail (route->plen <= 128, FALSE);
- if (_LOGD_ENABLED ()) {
- NMPlatformIP6Route route = { 0 };
-
- route.ifindex = ifindex;
- route.rt_source = source;
- route.network = network;
- route.plen = plen;
- route.gateway = gateway;
- route.metric = metric;
- route.mss = mss;
-
- _LOGD ("route: adding or updating IPv6 route: %s", nm_platform_ip6_route_to_string (&route, NULL, 0));
- }
- return klass->ip6_route_add (self, ifindex, source, network, plen, gateway, metric, mss);
+ _LOGD ("route: adding or updating IPv6 route: %s", nm_platform_ip6_route_to_string (route, NULL, 0));
+ return klass->ip6_route_add (self, route);
}
gboolean
-nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
+nm_platform_ip4_route_delete (NMPlatform *self, const NMPlatformIP4Route *route)
{
- char str_dev[TO_STRING_DEV_BUF_SIZE];
-
_CHECK_SELF (self, klass, FALSE);
- _LOGD ("route: deleting IPv4 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s",
- nm_utils_inet4_ntop (network, NULL), plen, metric, ifindex,
- _to_string_dev (self, ifindex, str_dev, sizeof (str_dev)));
- return klass->ip4_route_delete (self, ifindex, network, plen, metric);
+ g_return_val_if_fail (route, FALSE);
+
+ _LOGD ("route: deleting IPv4 route %s", nm_platform_ip4_route_to_string (route, NULL, 0));
+ return klass->ip4_route_delete (self, route);
}
gboolean
-nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
+nm_platform_ip6_route_delete (NMPlatform *self, const NMPlatformIP6Route *route)
{
- char str_dev[TO_STRING_DEV_BUF_SIZE];
-
_CHECK_SELF (self, klass, FALSE);
- _LOGD ("route: deleting IPv6 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s",
- nm_utils_inet6_ntop (&network, NULL), plen, metric, ifindex,
- _to_string_dev (self, ifindex, str_dev, sizeof (str_dev)));
- return klass->ip6_route_delete (self, ifindex, network, plen, metric);
+ g_return_val_if_fail (route, FALSE);
+
+ _LOGD ("route: deleting IPv6 route %s", nm_platform_ip6_route_to_string (route, NULL, 0));
+ return klass->ip6_route_delete (self, route);
}
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, const NMPlatformIP4Route *route)
{
_CHECK_SELF (self, klass, FALSE);
- return klass->ip4_route_get (self ,ifindex, network, plen, metric);
+ g_return_val_if_fail (route, NULL);
+
+ return klass->ip4_route_get (self, route);
}
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, const NMPlatformIP6Route *route)
{
_CHECK_SELF (self, klass, FALSE);
- return klass->ip6_route_get (self, ifindex, network, plen, metric);
+ g_return_val_if_fail (route, NULL);
+
+ return klass->ip6_route_get (self, route);
}
/******************************************************************/
@@ -3626,6 +3589,8 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
char s_pref_src[INET_ADDRSTRLEN];
char str_dev[TO_STRING_DEV_BUF_SIZE];
char str_scope[30], s_source[50];
+ guint8 scope;
+ gboolean scope_print;
if (!nm_utils_to_string_buffer_init_null (route, &buf, &len))
return buf;
@@ -3635,6 +3600,9 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
_to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev));
+ scope = nm_platform_route_scope_from_ip4_route (route);
+ scope_print = route->rt_scope_is_set || scope != RT_SCOPE_NOWHERE;
+
g_snprintf (buf, len,
"%s/%d"
" via %s"
@@ -3654,8 +3622,8 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
route->mss,
nmp_utils_ip_config_source_to_string (route->rt_source, s_source, sizeof (s_source)),
route->rt_cloned ? " cloned" : "",
- route->scope_inv ? " scope " : "",
- route->scope_inv ? (nm_platform_route_scope2str (nm_platform_route_scope_inv (route->scope_inv), str_scope, sizeof (str_scope))) : "",
+ scope_print ? " scope " : "",
+ scope_print ? nm_platform_route_scope2str (scope, str_scope, sizeof (str_scope)) : "",
route->pref_src ? " pref-src " : "",
route->pref_src ? inet_ntop (AF_INET, &route->pref_src, s_pref_src, sizeof(s_pref_src)) : "");
return buf;
@@ -3960,35 +3928,256 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A
int
nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b)
{
+ return nm_platform_ip4_route_cmp_full (a, b, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
+}
+
+int
+nm_platform_ip4_route_cmp_full (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, NMPlatformIPRouteIdType id_type)
+{
+ guint8 rtprot_a, rtprot_b;
+ guint8 scope_a, scope_b;
+ guint32 network_a, network_b;
+
_CMP_SELF (a, b);
+
_CMP_FIELD (a, b, ifindex);
- _CMP_FIELD (a, b, network);
+
+ network_a = nm_utils_ip4_address_clear_host_address (a->network, a->plen);
+ network_b = nm_utils_ip4_address_clear_host_address (b->network, b->plen);
+ _CMP_DIRECT (network_a, network_b);
+
_CMP_FIELD (a, b, plen);
_CMP_FIELD (a, b, metric);
_CMP_FIELD (a, b, gateway);
- _CMP_FIELD (a, b, rt_source);
+
+ rtprot_a = nmp_utils_ip_config_source_coerce_to_rtprot (a->rt_source);
+ rtprot_b = nmp_utils_ip_config_source_coerce_to_rtprot (b->rt_source);
+ _CMP_DIRECT (rtprot_a, rtprot_b);
+
_CMP_FIELD (a, b, mss);
- _CMP_FIELD (a, b, scope_inv);
+
+ scope_a = nm_platform_route_scope_from_ip4_route (a);
+ scope_b = nm_platform_route_scope_from_ip4_route (b);
+ _CMP_DIRECT (scope_a, scope_b);
+
_CMP_FIELD (a, b, pref_src);
_CMP_FIELD (a, b, rt_cloned);
+
+ /* currently we have two id-types, ID and ALL. Let ALL be a stricter
+ * ordering then ID, but yield the same order. Thus, above we first check
+ * all the ID fields, only if those are all equal, dig deeper. */
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ break;
+ default:
+ _CMP_FIELD (a, b, network);
+ _CMP_FIELD (a, b, rt_source);
+ _CMP_FIELD (a, b, rt_scope);
+ _CMP_FIELD (a, b, rt_scope_is_set);
+ break;
+ }
return 0;
}
+guint
+nm_platform_ip4_route_hash_full (const NMPlatformIP4Route *a, NMPlatformIPRouteIdType id_type)
+{
+ guint h = 0x8202baf9;
+
+ if (!a)
+ return h;
+
+ h += (h * 33) + ((guint) a->ifindex);
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ h += (h * 33) + ((guint) nm_utils_ip4_address_clear_host_address (a->network, a->plen));
+ break;
+ default:
+ h += (h * 33) + ((guint) a->network);
+ break;
+ }
+
+ h += (h * 33) + ((guint) a->plen);
+ h += (h * 33) + ((guint) a->metric);
+ h += (h * 33) + ((guint) a->gateway);
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ h += (h * 33) + ((guint) nmp_utils_ip_config_source_coerce_to_rtprot (a->rt_source));
+ break;
+ default:
+ h += (h * 33) + ((guint) a->rt_source);
+ break;
+ }
+
+ h += (h * 33) + ((guint) a->mss);
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ h += (h * 33) + ((guint) nm_platform_route_scope_from_ip4_route (a));
+ break;
+ default:
+ h += (h * 33) + (((guint) a->rt_scope) + (((guint) a->rt_scope_is_set) << 8));
+ break;
+ }
+
+ h += (h * 33) + ((guint) a->pref_src);
+ h += (h * 33) + ((guint) a->rt_cloned);
+
+ return h;
+}
+
+NMPlatformIP4Route *
+nm_platform_ip4_route_normalize (NMPlatformIP4Route *dst, const NMPlatformIP4Route *src, NMPlatformIPRouteIdType id_type)
+{
+ nm_assert (dst);
+
+ if (src && src != dst)
+ *dst = *src;
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ dst->network = nm_utils_ip4_address_clear_host_address (dst->network, dst->plen);
+ dst->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (dst->rt_source);
+ dst->rt_scope = nm_platform_route_scope_from_ip4_route (dst);
+ dst->rt_scope_is_set = TRUE;
+ break;
+ default:
+ break;
+ }
+ return dst;
+}
+
int
nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b)
{
+ return nm_platform_ip6_route_cmp_full (a, b, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
+}
+
+int
+nm_platform_ip6_route_cmp_full (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, NMPlatformIPRouteIdType id_type)
+{
+ struct in6_addr network_a, network_b;
+ guint32 metric_a, metric_b;
+ guint8 rtprot_a, rtprot_b;
+
_CMP_SELF (a, b);
+
_CMP_FIELD (a, b, ifindex);
- _CMP_FIELD_MEMCMP (a, b, network);
+
+ nm_utils_ip6_address_clear_host_address (&network_a, &a->network, a->plen);
+ nm_utils_ip6_address_clear_host_address (&network_b, &b->network, b->plen);
+ _CMP_DIRECT_MEMCMP (&network_a, &network_b, sizeof (struct in6_addr));
+
_CMP_FIELD (a, b, plen);
- _CMP_FIELD (a, b, metric);
+
+ metric_a = nm_utils_ip6_route_metric_normalize (a->metric);
+ metric_b = nm_utils_ip6_route_metric_normalize (b->metric);
+ _CMP_DIRECT (metric_a, metric_b);
+
_CMP_FIELD_MEMCMP (a, b, gateway);
- _CMP_FIELD (a, b, rt_source);
+
+ rtprot_a = nmp_utils_ip_config_source_coerce_to_rtprot (a->rt_source);
+ rtprot_b = nmp_utils_ip_config_source_coerce_to_rtprot (b->rt_source);
+ _CMP_DIRECT (rtprot_a, rtprot_b);
+
_CMP_FIELD (a, b, mss);
_CMP_FIELD (a, b, rt_cloned);
+
+ /* currently we have two id-types, ID and ALL. Let ALL be a stricter
+ * ordering then ID, but yield the same order. Thus, above we first check
+ * all the ID fields, only if those are all equal, dig deeper. */
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ break;
+ default:
+ _CMP_FIELD_MEMCMP (a, b, network);
+ _CMP_FIELD (a, b, metric);
+ _CMP_FIELD (a, b, rt_source);
+ break;
+ }
return 0;
}
+guint
+nm_platform_ip6_route_hash_full (const NMPlatformIP6Route *a, NMPlatformIPRouteIdType id_type)
+{
+ struct in6_addr network;
+
+ guint h = 0x0569b8f4;
+
+ if (!a)
+ return h;
+
+ h += (h * 33) + ((guint) a->ifindex);
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ nm_utils_ip6_address_clear_host_address (&network, &a->network, a->plen);
+ h += (h * 33) + ((guint) network.s6_addr32[0]);
+ h += (h * 33) + ((guint) network.s6_addr32[1]);
+ h += (h * 33) + ((guint) network.s6_addr32[2]);
+ h += (h * 33) + ((guint) network.s6_addr32[3]);
+ break;
+ default:
+ h += (h * 33) + ((guint) a->network.s6_addr32[0]);
+ h += (h * 33) + ((guint) a->network.s6_addr32[1]);
+ h += (h * 33) + ((guint) a->network.s6_addr32[2]);
+ h += (h * 33) + ((guint) a->network.s6_addr32[3]);
+ break;
+ }
+
+ h += (h * 33) + ((guint) a->plen);
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ h += (h * 33) + ((guint) nm_utils_ip6_route_metric_normalize (a->metric));
+ break;
+ default:
+ h += (h * 33) + ((guint) a->metric);
+ break;
+ }
+
+ h += (h * 33) + ((guint) a->gateway.s6_addr32[0]);
+ h += (h * 33) + ((guint) a->gateway.s6_addr32[1]);
+ h += (h * 33) + ((guint) a->gateway.s6_addr32[2]);
+ h += (h * 33) + ((guint) a->gateway.s6_addr32[3]);
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ h += (h * 33) + ((guint) nmp_utils_ip_config_source_coerce_to_rtprot (a->rt_source));
+ break;
+ default:
+ h += (h * 33) + ((guint) a->rt_source);
+ break;
+ }
+
+ h += (h * 33) + ((guint) a->mss);
+ h += (h * 33) + ((guint) a->rt_cloned);
+ return h;
+}
+
+NMPlatformIP6Route *
+nm_platform_ip6_route_normalize (NMPlatformIP6Route *dst, const NMPlatformIP6Route *src, NMPlatformIPRouteIdType id_type)
+{
+ nm_assert (dst);
+
+ if (src && src != dst)
+ *dst = *src;
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ nm_utils_ip6_address_clear_host_address (&dst->network, &dst->network, dst->plen);
+ dst->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (dst->rt_source);
+ dst->metric = nm_utils_ip6_route_metric_normalize (dst->metric);
+ break;
+ default:
+ break;
+ }
+ return dst;
+}
+
/**
* nm_platform_ip_address_cmp_expiry:
* @a: a NMPlatformIPAddress to compare
@@ -4114,50 +4303,45 @@ nm_platform_netns_push (NMPlatform *platform, NMPNetns **netns)
/******************************************************************/
static gboolean
-_vtr_v4_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, gint64 metric)
+_vtr_v4_route_add (NMPlatform *self, const NMPlatformIPXRoute *route, int ifindex, gint64 metric)
{
- return nm_platform_ip4_route_add (self,
- ifindex > 0 ? ifindex : route->rx.ifindex,
- route->rx.rt_source,
- route->r4.network,
- route->rx.plen,
- route->r4.gateway,
- route->r4.pref_src,
- metric >= 0 ? (guint32) metric : route->rx.metric,
- route->rx.mss);
+ NMPlatformIPXRoute r_storage;
+
+ if ( (ifindex > 0 && ifindex != route->rx.ifindex)
+ || (metric >= 0 && metric != route->rx.metric)) {
+ r_storage.r4 = route->r4;
+ r_storage.rx.ifindex = ifindex;
+ r_storage.rx.metric = metric;
+ route = &r_storage;
+ }
+ return nm_platform_ip4_route_add (self, &route->r4);
}
static gboolean
-_vtr_v6_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, gint64 metric)
+_vtr_v6_route_add (NMPlatform *self, const NMPlatformIPXRoute *route, int ifindex, gint64 metric)
{
- return nm_platform_ip6_route_add (self,
- ifindex > 0 ? ifindex : route->rx.ifindex,
- route->rx.rt_source,
- route->r6.network,
- route->rx.plen,
- route->r6.gateway,
- metric >= 0 ? (guint32) metric : route->rx.metric,
- route->rx.mss);
+ NMPlatformIPXRoute r_storage;
+
+ if ( (ifindex > 0 && ifindex != route->rx.ifindex)
+ || (metric >= 0 && metric != route->rx.metric)) {
+ r_storage.r6 = route->r6;
+ r_storage.rx.ifindex = ifindex;
+ r_storage.rx.metric = nm_utils_ip6_route_metric_normalize (metric);
+ route = &r_storage;
+ }
+ return nm_platform_ip6_route_add (self, &route->r6);
}
static gboolean
-_vtr_v4_route_delete (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route)
+_vtr_v4_route_delete (NMPlatform *self, const NMPlatformIPXRoute *route)
{
- return nm_platform_ip4_route_delete (self,
- ifindex > 0 ? ifindex : route->rx.ifindex,
- route->r4.network,
- route->rx.plen,
- route->rx.metric);
+ return nm_platform_ip4_route_delete (self, &route->r4);
}
static gboolean
-_vtr_v6_route_delete (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route)
+_vtr_v6_route_delete (NMPlatform *self, const NMPlatformIPXRoute *route)
{
- return nm_platform_ip6_route_delete (self,
- ifindex > 0 ? ifindex : route->rx.ifindex,
- route->r6.network,
- route->rx.plen,
- route->rx.metric);
+ return nm_platform_ip6_route_delete (self, &route->r6);
}
static guint32
@@ -4166,18 +4350,6 @@ _vtr_v4_metric_normalize (guint32 metric)
return metric;
}
-static gboolean
-_vtr_v4_route_delete_default (NMPlatform *self, int ifindex, guint32 metric)
-{
- return nm_platform_ip4_route_delete (self, ifindex, 0, 0, metric);
-}
-
-static gboolean
-_vtr_v6_route_delete_default (NMPlatform *self, int ifindex, guint32 metric)
-{
- return nm_platform_ip6_route_delete (self, ifindex, in6addr_any, 0, metric);
-}
-
/******************************************************************/
const NMPlatformVTableRoute nm_platform_vtable_route_v4 = {
@@ -4189,7 +4361,6 @@ const NMPlatformVTableRoute nm_platform_vtable_route_v4 = {
.route_get_all = nm_platform_ip4_route_get_all,
.route_add = _vtr_v4_route_add,
.route_delete = _vtr_v4_route_delete,
- .route_delete_default = _vtr_v4_route_delete_default,
.metric_normalize = _vtr_v4_metric_normalize,
};
@@ -4202,7 +4373,6 @@ const NMPlatformVTableRoute nm_platform_vtable_route_v6 = {
.route_get_all = nm_platform_ip6_route_get_all,
.route_add = _vtr_v6_route_add,
.route_delete = _vtr_v6_route_delete,
- .route_delete_default = _vtr_v6_route_delete_default,
.metric_normalize = nm_utils_ip6_route_metric_normalize,
};
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index ae12aa8e95..28d7b39689 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -338,13 +338,20 @@ struct _NMPlatformIP4Route {
in_addr_t network;
in_addr_t gateway;
- /* The bitwise inverse of the route scope. It is inverted so that the
- * default value (RT_SCOPE_NOWHERE) is nul. */
- guint8 scope_inv;
-
/* RTA_PREFSRC/rtnl_route_get_pref_src(). A value of zero means that
* no pref-src is set. */
in_addr_t pref_src;
+
+ /* The route scope rtm_scope.
+ *
+ * Note, that for IPv4, the scope is part of the ID for a route.
+ * That means, when we receive a route from kernel, we set rt_scope
+ * and rt_scope_is_set=1 to indicate that the scope is fully determined.
+ *
+ * When adding a route, we allow the user to autodetect the scope based
+ * on the gateway. That is controlled by leaving rt_scope_is_set=0. */
+ guint8 rt_scope;
+ bool rt_scope_is_set:1;
};
struct _NMPlatformIP6Route {
@@ -372,9 +379,8 @@ typedef struct {
int (*route_cmp) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b);
const char *(*route_to_string) (const NMPlatformIPXRoute *route, char *buf, gsize len);
GArray *(*route_get_all) (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags);
- gboolean (*route_add) (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, gint64 metric);
- gboolean (*route_delete) (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route);
- gboolean (*route_delete_default) (NMPlatform *self, int ifindex, guint32 metric);
+ gboolean (*route_add) (NMPlatform *self, const NMPlatformIPXRoute *route, int ifindex, gint64 metric);
+ gboolean (*route_delete) (NMPlatform *self, const NMPlatformIPXRoute *route);
guint32 (*metric_normalize) (guint32 metric);
} NMPlatformVTableRoute;
@@ -630,16 +636,12 @@ typedef struct {
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 *, int ifindex, NMIPConfigSource source,
- in_addr_t network, guint8 plen, in_addr_t gateway,
- in_addr_t pref_src, guint32 metric, guint32 mss);
- gboolean (*ip6_route_add) (NMPlatform *, int ifindex, NMIPConfigSource source,
- struct in6_addr network, guint8 plen, struct in6_addr gateway,
- guint32 metric, guint32 mss);
- 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);
- 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 (*ip4_route_add) (NMPlatform *, const NMPlatformIP4Route *route);
+ gboolean (*ip6_route_add) (NMPlatform *, const NMPlatformIP6Route *route);
+ gboolean (*ip4_route_delete) (NMPlatform *, const NMPlatformIP4Route *route);
+ gboolean (*ip6_route_delete) (NMPlatform *, const NMPlatformIP6Route *route);
+ const NMPlatformIP4Route *(*ip4_route_get) (NMPlatform *, const NMPlatformIP4Route *route);
+ const NMPlatformIP6Route *(*ip6_route_get) (NMPlatform *, const NMPlatformIP6Route *route);
gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *);
gboolean (*check_support_user_ipv6ll) (NMPlatform *);
@@ -676,23 +678,37 @@ NMPlatform *nm_platform_try_get (void);
/******************************************************************/
-/**
- * nm_platform_route_scope_inv:
- * @scope: the route scope, either its original value, or its inverse.
- *
- * This function is useful, because the constants such as RT_SCOPE_NOWHERE
- * are 'int', so ~scope also gives an 'int'. This function gets the type
- * casts to guint8 right.
- *
- * Returns: the bitwise inverse of the route scope.
- * */
-#define nm_platform_route_scope_inv _nm_platform_uint8_inv
static inline guint8
_nm_platform_uint8_inv (guint8 scope)
{
return (guint8) ~scope;
}
+static inline guint8
+nm_platform_route_scope_for_ip4_gateway (guint32 gateway)
+{
+ return gateway
+ ? 0 /* RT_SCOPE_UNIVERSE */
+ : 253 /* RT_SCOPE_LINK */;
+}
+
+static inline guint8
+nm_platform_route_scope_for_ip6_gateway (const struct in6_addr *gateway)
+{
+ return gateway && !IN6_IS_ADDR_UNSPECIFIED (gateway)
+ ? 0 /* RT_SCOPE_UNIVERSE */
+ : 253 /* RT_SCOPE_LINK */;
+}
+
+static inline guint8
+nm_platform_route_scope_from_ip4_route (const NMPlatformIP4Route *route)
+{
+ nm_assert (route);
+ return route->rt_scope_is_set
+ ? route->rt_scope
+ : nm_platform_route_scope_for_ip4_gateway (route->gateway);
+}
+
NMPNetns *nm_platform_netns_get (NMPlatform *self);
gboolean nm_platform_netns_push (NMPlatform *platform, NMPNetns **netns);
@@ -907,18 +923,14 @@ gboolean nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArr
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, guint8 plen, guint32 metric);
-const NMPlatformIP6Route *nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
+const NMPlatformIP4Route *nm_platform_ip4_route_get (NMPlatform *self, const NMPlatformIP4Route *route);
+const NMPlatformIP6Route *nm_platform_ip6_route_get (NMPlatform *self, const NMPlatformIP6Route *route);
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,
- in_addr_t network, guint8 plen, in_addr_t gateway,
- in_addr_t pref_src, guint32 metric, guint32 mss);
-gboolean nm_platform_ip6_route_add (NMPlatform *self, int ifindex, NMIPConfigSource source,
- struct in6_addr network, guint8 plen, struct in6_addr gateway,
- guint32 metric, guint32 mss);
-gboolean nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
-gboolean nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
+gboolean nm_platform_ip4_route_add (NMPlatform *self, const NMPlatformIP4Route *route);
+gboolean nm_platform_ip6_route_add (NMPlatform *self, const NMPlatformIP6Route *route);
+gboolean nm_platform_ip4_route_delete (NMPlatform *self, const NMPlatformIP4Route *route);
+gboolean nm_platform_ip6_route_delete (NMPlatform *self, const NMPlatformIP6Route *route);
const char *nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len);
const char *nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len);
@@ -954,6 +966,18 @@ int nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatform
int nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b);
int nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b);
+typedef enum {
+ NM_PLATFORM_IP_ROUTE_ID_TYPE_ID,
+ NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL,
+} NMPlatformIPRouteIdType;
+
+int nm_platform_ip4_route_cmp_full (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, NMPlatformIPRouteIdType id_type);
+int nm_platform_ip6_route_cmp_full (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, NMPlatformIPRouteIdType id_type);
+guint nm_platform_ip4_route_hash_full (const NMPlatformIP4Route *a, NMPlatformIPRouteIdType id_type);
+guint nm_platform_ip6_route_hash_full (const NMPlatformIP6Route *a, NMPlatformIPRouteIdType id_type);
+NMPlatformIP4Route *nm_platform_ip4_route_normalize (NMPlatformIP4Route *dst, const NMPlatformIP4Route *src, NMPlatformIPRouteIdType id_type);
+NMPlatformIP6Route *nm_platform_ip6_route_normalize (NMPlatformIP6Route *dst, const NMPlatformIP6Route *src, NMPlatformIPRouteIdType id_type);
+
gboolean nm_platform_check_support_kernel_extended_ifa_flags (NMPlatform *self);
gboolean nm_platform_check_support_user_ipv6ll (NMPlatform *self);
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index 55ffd7cffb..8902881642 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -377,38 +377,33 @@ _vt_cmd_obj_stackinit_id_ip6_address (NMPObject *obj, const NMPObject *src)
}
const NMPObject *
-nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network, guint8 plen, guint32 metric)
+nmp_object_stackinit_id_ip4_route (NMPObject *obj, const NMPlatformIP4Route *route, NMPlatformIPRouteIdType id_type)
{
nmp_object_stackinit (obj, NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
- obj->ip4_route.ifindex = ifindex;
- obj->ip4_route.network = network;
- obj->ip4_route.plen = plen;
- obj->ip4_route.metric = metric;
+ if (route)
+ nm_platform_ip4_route_normalize (&obj->ip4_route, route, id_type);
return obj;
}
static void
_vt_cmd_obj_stackinit_id_ip4_route (NMPObject *obj, const NMPObject *src)
{
- nmp_object_stackinit_id_ip4_route (obj, src->ip_route.ifindex, src->ip4_route.network, src->ip_route.plen, src->ip_route.metric);
+ nmp_object_stackinit_id_ip4_route (obj, &src->ip4_route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
}
const NMPObject *
-nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6_addr *network, guint8 plen, guint32 metric)
+nmp_object_stackinit_id_ip6_route (NMPObject *obj, const NMPlatformIP6Route *route, NMPlatformIPRouteIdType id_type)
{
nmp_object_stackinit (obj, NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
- obj->ip6_route.ifindex = ifindex;
- if (network)
- obj->ip6_route.network = *network;
- obj->ip6_route.plen = plen;
- obj->ip6_route.metric = metric;
+ if (route)
+ nm_platform_ip6_route_normalize (&obj->ip6_route, route, id_type);
return obj;
}
static void
_vt_cmd_obj_stackinit_id_ip6_route (NMPObject *obj, const NMPObject *src)
{
- nmp_object_stackinit_id_ip6_route (obj, src->ip_route.ifindex, &src->ip6_route.network, src->ip_route.plen, src->ip_route.metric);
+ nmp_object_stackinit_id_ip6_route (obj, &src->ip6_route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
}
/******************************************************************/
@@ -567,8 +562,6 @@ _vt_cmd_plobj_to_string_id (ip4_address, NMPlatformIP4Address, "%d: %s/%d%s%s",
obj->peer_address != obj->address ? "," : "",
obj->peer_address != obj->address ? nm_utils_inet4_ntop (obj->peer_address & nm_utils_ip4_prefix_to_netmask (obj->plen), buf2) : "");
_vt_cmd_plobj_to_string_id (ip6_address, NMPlatformIP6Address, "%d: %s", obj->ifindex, nm_utils_inet6_ntop (&obj->address, buf1));
-_vt_cmd_plobj_to_string_id (ip4_route, NMPlatformIP4Route, "%d: %s/%d %d", obj->ifindex, nm_utils_inet4_ntop ( obj->network, buf1), obj->plen, obj->metric);
-_vt_cmd_plobj_to_string_id (ip6_route, NMPlatformIP6Route, "%d: %s/%d %d", obj->ifindex, nm_utils_inet6_ntop (&obj->network, buf1), obj->plen, obj->metric);
int
nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2)
@@ -733,16 +726,10 @@ _vt_cmd_plobj_id_copy (ip6_address, NMPlatformIP6Address, {
dst->address = src->address;
});
_vt_cmd_plobj_id_copy (ip4_route, NMPlatformIP4Route, {
- dst->ifindex = src->ifindex;
- dst->plen = src->plen;
- dst->metric = src->metric;
- dst->network = src->network;
+ nm_platform_ip4_route_normalize (dst, src, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
});
_vt_cmd_plobj_id_copy (ip6_route, NMPlatformIP6Route, {
- dst->ifindex = src->ifindex;
- dst->plen = src->plen;
- dst->metric = src->metric;
- dst->network = src->network;
+ nm_platform_ip6_route_normalize (dst, src, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
});
/* Uses internally nmp_object_copy(), hence it also violates the const
@@ -804,15 +791,9 @@ _vt_cmd_plobj_id_equal (ip6_address, NMPlatformIP6Address,
/* for IPv6 addresses, the prefix length is not part of the primary identifier. */
&& IN6_ARE_ADDR_EQUAL (&obj1->address, &obj2->address));
_vt_cmd_plobj_id_equal (ip4_route, NMPlatformIP4Route,
- obj1->ifindex == obj2->ifindex
- && obj1->plen == obj2->plen
- && obj1->metric == obj2->metric
- && obj1->network == obj2->network);
+ nm_platform_ip4_route_cmp_full (obj1, obj2, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID) == 0);
_vt_cmd_plobj_id_equal (ip6_route, NMPlatformIP6Route,
- obj1->ifindex == obj2->ifindex
- && obj1->plen == obj2->plen
- && obj1->metric == obj2->metric
- && IN6_ARE_ADDR_EQUAL( &obj1->network, &obj2->network));
+ nm_platform_ip6_route_cmp_full (obj1, obj2, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID) == 0);
guint
nmp_object_id_hash (const NMPObject *obj)
@@ -862,18 +843,10 @@ _vt_cmd_plobj_id_hash (ip6_address, NMPlatformIP6Address, {
hash = hash * 33 + _id_hash_ip6_addr (&obj->address);
})
_vt_cmd_plobj_id_hash (ip4_route, NMPlatformIP4Route, {
- hash = (guint) 2569857221u;
- hash = hash + ((guint) obj->ifindex);
- hash = hash * 33 + ((guint) obj->plen);
- hash = hash * 33 + ((guint) obj->metric);
- hash = hash * 33 + ((guint) obj->network);
+ hash = nm_platform_ip4_route_hash_full (obj, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
})
_vt_cmd_plobj_id_hash (ip6_route, NMPlatformIP6Route, {
- hash = (guint) 3999787007u;
- hash = hash + ((guint) obj->ifindex);
- hash = hash * 33 + ((guint) obj->plen);
- hash = hash * 33 + ((guint) obj->metric);
- hash = hash * 33 + _id_hash_ip6_addr (&obj->network);
+ hash = nm_platform_ip6_route_hash_full (obj, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
})
gboolean
@@ -2172,7 +2145,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip4_route,
.cmd_plobj_id_equal = _vt_cmd_plobj_id_equal_ip4_route,
.cmd_plobj_id_hash = _vt_cmd_plobj_id_hash_ip4_route,
- .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_ip4_route,
+ .cmd_plobj_to_string_id = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_ip4_route_to_string,
.cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_ip4_route_to_string,
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip4_route_cmp,
},
@@ -2192,7 +2165,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_route,
.cmd_plobj_id_equal = _vt_cmd_plobj_id_equal_ip6_route,
.cmd_plobj_id_hash = _vt_cmd_plobj_id_hash_ip6_route,
- .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_ip6_route,
+ .cmd_plobj_to_string_id = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_ip6_route_to_string,
.cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_ip6_route_to_string,
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip6_route_cmp,
},
diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h
index 062d01d29d..55c7d57766 100644
--- a/src/platform/nmp-object.h
+++ b/src/platform/nmp-object.h
@@ -373,8 +373,8 @@ const NMPObject *nmp_object_stackinit_id (NMPObject *obj, const NMPObject *src)
const NMPObject *nmp_object_stackinit_id_link (NMPObject *obj, int ifindex);
const NMPObject *nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, guint8 plen, guint32 peer_address);
const NMPObject *nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address, guint8 plen);
-const NMPObject *nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network, guint8 plen, guint32 metric);
-const NMPObject *nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6_addr *network, guint8 plen, guint32 metric);
+const NMPObject *nmp_object_stackinit_id_ip4_route (NMPObject *obj, const NMPlatformIP4Route *route, NMPlatformIPRouteIdType id_type);
+const NMPObject *nmp_object_stackinit_id_ip6_route (NMPObject *obj, const NMPlatformIP6Route *route, NMPlatformIPRouteIdType id_type);
const char *nmp_object_to_string (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size);
int nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2);
diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c
index 3b52487a56..15af4909c7 100644
--- a/src/platform/tests/test-cleanup.c
+++ b/src/platform/tests/test-cleanup.c
@@ -33,26 +33,21 @@ test_cleanup_internal (void)
GArray *addresses6;
GArray *routes4;
GArray *routes6;
- in_addr_t addr4;
- in_addr_t network4;
int plen4 = 24;
- in_addr_t gateway4;
- struct in6_addr addr6;
- struct in6_addr network6;
int plen6 = 64;
- struct in6_addr gateway6;
int lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
int preferred = NM_PLATFORM_LIFETIME_PERMANENT;
int metric = 20;
int mss = 1000;
guint32 flags = 0;
-
- inet_pton (AF_INET, "192.0.2.1", &addr4);
- inet_pton (AF_INET, "192.0.3.0", &network4);
- inet_pton (AF_INET, "198.51.100.1", &gateway4);
- inet_pton (AF_INET6, "2001:db8:a:b:1:2:3:4", &addr6);
- inet_pton (AF_INET6, "2001:db8:c:d:0:0:0:0", &network6);
- inet_pton (AF_INET6, "2001:db8:e:f:1:2:3:4", &gateway6);
+ const char *const ADDR4 = "192.0.2.1";
+ const char *const NETWORK4 = "192.0.3.0";
+ const char *const GATEWAY4 = "198.51.100.1";
+ const char *const ADDR6 = "2001:db8:a:b:1:2:3:4";
+ const char *const NETWORK6 = "2001:db8:c:d:0:0:0:0";
+ const char *const GATEWAY6 = "2001:db8:e:f:1:2:3:4";
+ const guint32 addr4 = nmtst_inet4_from_string (ADDR4);
+ const struct in6_addr addr6 = *nmtst_inet6_from_string (ADDR6);
/* Create and set up device */
g_assert (nm_platform_link_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL) == NM_PLATFORM_ERROR_SUCCESS);
@@ -65,12 +60,12 @@ test_cleanup_internal (void)
/* Add routes and addresses */
g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr4, plen4, addr4, lifetime, preferred, 0, NULL));
g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr6, plen6, in6addr_any, lifetime, preferred, flags));
- g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway4, 32, INADDR_ANY, 0, metric, mss));
- g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network4, plen4, gateway4, 0, metric, mss));
- g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway4, 0, metric, mss));
- g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway6, 128, in6addr_any, metric, mss));
- g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network6, plen6, gateway6, metric, mss));
- g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway6, metric, mss));
+ g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, nmtst_platform_ip4_route_full (ifindex, GATEWAY4, 32, NULL, NM_IP_CONFIG_SOURCE_USER, metric, mss, 0, FALSE, NULL)));
+ g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, nmtst_platform_ip4_route_full (ifindex, NETWORK4, plen4, GATEWAY4, NM_IP_CONFIG_SOURCE_USER, metric, mss, 0, FALSE, NULL)));
+ g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, nmtst_platform_ip4_route_full (ifindex, NULL, 0, GATEWAY4, NM_IP_CONFIG_SOURCE_USER, metric, mss, 0, FALSE, NULL)));
+ g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, nmtst_platform_ip6_route_full (ifindex, GATEWAY6, 128, NULL, NM_IP_CONFIG_SOURCE_USER, metric, mss)));
+ g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, nmtst_platform_ip6_route_full (ifindex, NETWORK6, plen6, GATEWAY6, NM_IP_CONFIG_SOURCE_USER, metric, mss)));
+ g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, nmtst_platform_ip6_route_full (ifindex, NULL, 0, GATEWAY6, NM_IP_CONFIG_SOURCE_USER, metric, mss)));
addresses4 = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
addresses6 = nm_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex);
diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c
index b1947a6d11..2177d58252 100644
--- a/src/platform/tests/test-common.c
+++ b/src/platform/tests/test-common.c
@@ -25,6 +25,9 @@
#include <sys/wait.h>
#include <fcntl.h>
+#include "nm-platform-utils.h"
+#include "nmp-object.h"
+
#include "test-common.h"
#define SIGNAL_DATA_FMT "'%s-%s' ifindex %d%s%s%s (%d times received)"
@@ -196,8 +199,156 @@ link_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlat
/*****************************************************************************/
+static int
+_sort_routes (gconstpointer p_a, gconstpointer p_b, gpointer user_data)
+{
+ gboolean is_v4 = GPOINTER_TO_INT (user_data);
+
+ if (is_v4)
+ return nm_platform_ip4_route_cmp (p_a, p_b);
+ else
+ return nm_platform_ip6_route_cmp (p_a, p_b);
+}
+
+const NMPlatformIPXRoute **
+nmtstp_ip_route_get_by_destination (NMPlatform *platform,
+ gboolean is_v4,
+ int ifindex,
+ const NMIPAddr *network,
+ guint8 plen,
+ guint32 metric,
+ const NMIPAddr *gateway,
+ guint *out_len)
+{
+ gs_unref_array GArray *routes = NULL;
+ GPtrArray *result = NULL;
+ gs_unref_hashtable GHashTable *check_dupes = NULL;
+ NMIPAddr network_clean;
+ guint i;
+
+ g_assert (ifindex >= 0);
+ g_assert (plen >= 0 && plen <= (is_v4 ? 32 : 128));
+
+ NM_SET_OUT (out_len, 0);
+
+ _init_platform (&platform, FALSE);
+
+ check_dupes = g_hash_table_new ((GHashFunc) nmp_object_id_hash, (GEqualFunc) nmp_object_id_equal);
+ result = g_ptr_array_new ();
+
+ network = nm_utils_ipx_address_clear_host_address (is_v4 ? AF_INET : AF_INET6,
+ &network_clean,
+ network ?: &nm_ip_addr_zero,
+ plen);
+
+ if (!is_v4)
+ metric = nm_utils_ip6_route_metric_normalize (metric);
+
+ if (is_v4)
+ routes = nm_platform_ip4_route_get_all (platform, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_RTPROT_KERNEL);
+ else
+ routes = nm_platform_ip6_route_get_all (platform, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_RTPROT_KERNEL);
+
+ for (i = 0; routes && i < routes->len; i++) {
+ const NMPlatformIPXRoute *r_i = is_v4
+ ? (NMPlatformIPXRoute *) &g_array_index (routes, NMPlatformIP4Route, i)
+ : (NMPlatformIPXRoute *) &g_array_index (routes, NMPlatformIP6Route, i);
+ const NMPlatformIPXRoute *r_2;
+ const NMPObject *o_2;
+
+ g_assert (r_i->rx.ifindex == ifindex);
+
+ if ( r_i->rx.plen != plen
+ || r_i->rx.metric != metric)
+ continue;
+
+ if (is_v4) {
+ if (r_i->r4.network != *((guint32 *) network))
+ continue;
+ if ( gateway
+ && r_i->r4.gateway != *((guint32 *) gateway))
+ continue;
+ } else {
+ if (!IN6_ARE_ADDR_EQUAL (&r_i->r6.network, network))
+ continue;
+ if ( gateway
+ && !IN6_ARE_ADDR_EQUAL (&r_i->r6.gateway, gateway))
+ continue;
+ }
+
+ r_2 = is_v4
+ ? (NMPlatformIPXRoute *) nm_platform_ip4_route_get (platform, &r_i->r4)
+ : (NMPlatformIPXRoute *) nm_platform_ip6_route_get (platform, &r_i->r6);
+ g_assert (r_2);
+ g_assert ( ( is_v4 && nm_platform_ip4_route_cmp (&r_i->r4, &r_2->r4) == 0)
+ || (!is_v4 && nm_platform_ip6_route_cmp (&r_i->r6, &r_2->r6) == 0));
+
+ o_2 = NMP_OBJECT_UP_CAST (r_2);
+ g_assert (NMP_OBJECT_IS_VALID (o_2));
+ g_assert (NMP_OBJECT_GET_TYPE (o_2) == (is_v4 ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE));
+
+ g_ptr_array_add (result, (gpointer) r_2);
+ if (!nm_g_hash_table_add (check_dupes, (gpointer) o_2))
+ g_assert_not_reached ();
+ }
+
+ /* check whether the multi-index of the platform cache agrees... */
+ if (NM_IS_LINUX_PLATFORM (platform)) {
+ const NMPlatformObject *const *routes_cached;
+ NMPCacheId cache_id;
+ guint len;
+
+ if (is_v4)
+ nmp_cache_id_init_routes_by_destination_ip4 (&cache_id, network->addr4, plen, metric);
+ else
+ nmp_cache_id_init_routes_by_destination_ip6 (&cache_id, &network->addr6, plen, metric);
+
+ routes_cached = nm_linux_platform_lookup (platform, &cache_id, &len);
+
+ if (len)
+ g_assert (routes_cached && routes_cached[len] == NULL);
+ else
+ g_assert (!routes_cached);
+
+ for (i =0; routes_cached && i < len; i++) {
+ const NMPObject *o;
+ const NMPObject *o_2;
+
+ g_assert (routes_cached [i]);
+ o = NMP_OBJECT_UP_CAST (routes_cached [i]);
+ g_assert (NMP_OBJECT_IS_VALID (o));
+ g_assert (NMP_OBJECT_GET_TYPE (o) == (is_v4 ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE));
+
+ if (gateway) {
+ if ( ( is_v4 && o->ip4_route.gateway != *((guint32 *) gateway))
+ || (!is_v4 && !IN6_ARE_ADDR_EQUAL (&o->ip6_route.gateway, gateway)))
+ continue;
+ }
+
+ o_2 = g_hash_table_lookup (check_dupes, o);
+ g_assert (o_2);
+ g_assert (o_2 == o);
+
+ if (!g_hash_table_remove (check_dupes, o))
+ g_assert_not_reached ();
+ }
+
+ g_assert (g_hash_table_size (check_dupes) == 0);
+ }
+
+ if (result->len > 0) {
+ g_ptr_array_sort_with_data (result, _sort_routes, GINT_TO_POINTER (!!is_v4));
+ NM_SET_OUT (out_len, result->len);
+ g_ptr_array_add (result, NULL);
+ return (gpointer) g_ptr_array_free (result, FALSE);
+ }
+ g_ptr_array_unref (result);
+ return NULL;
+}
+
+
gboolean
-nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric)
+nmtstp_ip4_route_exists (const char *ifname, guint32 network, guint8 plen, guint32 metric, const guint32 *gateway)
{
gs_free char *arg_network = NULL;
const char *argv[] = {
@@ -216,6 +367,7 @@ nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32
gboolean success;
gs_free_error GError *error = NULL;
gs_free char *metric_pattern = NULL;
+ gs_free char *via_pattern = NULL;
g_assert (ifname && nm_utils_iface_valid_name (ifname));
g_assert (!strstr (ifname, " metric "));
@@ -253,6 +405,7 @@ nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32
g_assert (std_out);
metric_pattern = g_strdup_printf (" metric %u", metric);
+ via_pattern = gateway ? g_strdup_printf (" via %s", nm_utils_inet4_ntop (*gateway, NULL)) : NULL;
out = std_out;
while (out) {
char *eol = strchr (out, '\n');
@@ -264,44 +417,93 @@ nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32
continue;
if (metric == 0) {
- if (!strstr (line, " metric "))
- return TRUE;
+ if (strstr (line, " metric "))
+ continue;
+ } else {
+ p = strstr (line, metric_pattern);
+ if (!p || !NM_IN_SET (p[strlen (metric_pattern)], ' ', '\0'))
+ continue;
+ }
+
+ if (gateway) {
+ if (*gateway == 0) {
+ if (strstr (line, " via "))
+ continue;
+ } else {
+ p = strstr (line, via_pattern);
+ if (!p || !NM_IN_SET (p[strlen (via_pattern)], ' ', '\0'))
+ continue;
+ }
}
- p = strstr (line, metric_pattern);
- if (p && NM_IN_SET (p[strlen (metric_pattern)], ' ', '\0'))
- return TRUE;
+ return TRUE;
}
return FALSE;
}
-void
-_nmtstp_assert_ip4_route_exists (const char *file, guint line, const char *func, NMPlatform *platform, gboolean exists, const char *ifname, guint32 network, int plen, guint32 metric)
+const NMPlatformIP4Route *
+_nmtstp_assert_ip4_route_exists (const char *file,
+ guint line,
+ const char *func,
+ NMPlatform *platform,
+ gboolean exists,
+ const char *ifname,
+ guint32 network,
+ guint8 plen,
+ guint32 metric,
+ const guint32 *gateway)
{
int ifindex;
gboolean exists_checked;
+ char s_buf[NM_UTILS_INET_ADDRSTRLEN];
+ gs_free const NMPlatformIP4Route **routes = NULL;
+ guint len;
_init_platform (&platform, FALSE);
/* Check for existance of the route by spawning iproute2. Do this because platform
* code might be entirely borked, but we expect ip-route to give a correct result.
* If the ip command cannot be found, we accept this as success. */
- exists_checked = nmtstp_ip4_route_exists (ifname, network, plen, metric);
+ exists_checked = nmtstp_ip4_route_exists (ifname, network, plen, metric, gateway);
if (exists_checked != -1 && !exists_checked != !exists) {
- g_error ("[%s:%u] %s(): We expect the ip4 route %s/%d metric %u %s, but it %s",
+ g_error ("[%s:%u] %s(): We expect the ip4 route %s/%d%s metric %u %s, but it %s",
file, line, func,
- nm_utils_inet4_ntop (network, NULL), plen, metric,
+ nm_utils_inet4_ntop (network, NULL), plen,
+ gateway ? nm_sprintf_bufa (100, " gateway %s", nm_utils_inet4_ntop (*gateway, s_buf)) : " no-gateway",
+ metric,
exists ? "to exist" : "not to exist",
exists ? "doesn't" : "does");
}
ifindex = nm_platform_link_get_ifindex (platform, ifname);
g_assert (ifindex > 0);
- if (!nm_platform_ip4_route_get (platform, 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,
- exists ? "exists" : "does not exist",
- exists ? "it doesn't" : "it does");
+
+ routes = (gpointer) nmtstp_ip_route_get_by_destination (platform, TRUE, ifindex, (NMIPAddr *) &network,
+ plen, metric, (NMIPAddr *) gateway, &len);
+ if (routes) {
+ if (!exists) {
+ g_error ("[%s:%u] %s(): The ip4 route %s/%d via %s metric %u %s, but platform thinks %s",
+ file, line, func,
+ nm_utils_inet4_ntop (network, NULL),
+ plen,
+ nm_utils_inet4_ntop (gateway ? *gateway : 0, s_buf),
+ metric,
+ exists ? "exists" : "does not exist",
+ exists ? "it doesn't" : "it does");
+ }
+ g_assert (len == 1);
+ return routes[0];
+ } else {
+ if (exists) {
+ g_error ("[%s:%u] %s(): The ip4 route %s/%d via %s metric %u %s, but platform thinks %s",
+ file, line, func,
+ nm_utils_inet4_ntop (network, NULL),
+ plen,
+ nm_utils_inet4_ntop (gateway ? *gateway : 0, s_buf),
+ metric,
+ exists ? "exists" : "does not exist",
+ exists ? "it doesn't" : "it does");
+ }
+ return NULL;
}
}
@@ -414,7 +616,7 @@ nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms)
const NMPlatformLink *
nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms)
{
- return nmtstp_wait_for_link_until (platform, ifname, expected_link_type, nm_utils_get_monotonic_timestamp_ms () + timeout_ms);
+ return nmtstp_wait_for_link_until (platform, ifname, expected_link_type, nm_utils_get_monotonic_timestamp_ms () + (gint64) timeout_ms);
}
const NMPlatformLink *
@@ -443,7 +645,7 @@ nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType
const NMPlatformLink *
nmtstp_assert_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms)
{
- return nmtstp_assert_wait_for_link_until (platform, ifname, expected_link_type, nm_utils_get_monotonic_timestamp_ms () + timeout_ms);
+ return nmtstp_assert_wait_for_link_until (platform, ifname, expected_link_type, nm_utils_get_monotonic_timestamp_ms () + (gint64) timeout_ms);
}
const NMPlatformLink *
@@ -458,6 +660,55 @@ nmtstp_assert_wait_for_link_until (NMPlatform *platform, const char *ifname, NML
/*****************************************************************************/
+static const void *
+_wait_for_ip_route_until (NMPlatform *platform, int is_v4, int ifindex, const NMIPAddr *network, guint8 plen, guint32 metric, const NMIPAddr *gateway, gint64 until_ms)
+{
+ gint64 now;
+
+ _init_platform (&platform, FALSE);
+
+ while (TRUE) {
+ gs_free const NMPlatformIPXRoute **routes = NULL;
+
+ now = nm_utils_get_monotonic_timestamp_ms ();
+
+ routes = nmtstp_ip_route_get_by_destination (platform, is_v4, ifindex, network, plen, metric, gateway, NULL);
+ if (routes)
+ return routes[0];
+
+ if (until_ms < now)
+ return NULL;
+
+ nmtstp_wait_for_signal (platform, MAX (1, until_ms - now));
+ }
+}
+
+const NMPlatformIP4Route *
+nmtstp_wait_for_ip4_route (NMPlatform *platform, int ifindex, guint32 network, guint8 plen, guint32 metric, guint32 gateway, guint timeout_ms)
+{
+ return _wait_for_ip_route_until (platform, TRUE, ifindex, (NMIPAddr *) &network, plen, metric, (NMIPAddr *) &gateway, nm_utils_get_monotonic_timestamp_ms () + (gint64) timeout_ms);
+}
+
+const NMPlatformIP4Route *
+nmtstp_wait_for_ip4_route_until (NMPlatform *platform, int ifindex, guint32 network, guint8 plen, guint32 metric, guint32 gateway, gint64 until_ms)
+{
+ return _wait_for_ip_route_until (platform, TRUE, ifindex, (NMIPAddr *) &network, plen, metric, (NMIPAddr *) &gateway, until_ms);
+}
+
+const NMPlatformIP6Route *
+nmtstp_wait_for_ip6_route (NMPlatform *platform, int ifindex, const struct in6_addr *network, guint8 plen, guint32 metric, const struct in6_addr *gateway, guint timeout_ms)
+{
+ return _wait_for_ip_route_until (platform, FALSE, ifindex, (NMIPAddr *) network, plen, metric, (NMIPAddr *) gateway, nm_utils_get_monotonic_timestamp_ms () + (gint64) timeout_ms);
+}
+
+const NMPlatformIP6Route *
+nmtstp_wait_for_ip6_route_until (NMPlatform *platform, int ifindex, const struct in6_addr *network, guint8 plen, guint32 metric, const struct in6_addr *gateway, gint64 until_ms)
+{
+ return _wait_for_ip_route_until (platform, FALSE, ifindex, (NMIPAddr *) network, plen, metric, (NMIPAddr *) gateway, until_ms);
+}
+
+/*****************************************************************************/
+
int
nmtstp_run_command_check_external_global (void)
{
@@ -592,7 +843,7 @@ _ip_address_add (NMPlatform *platform,
gboolean is_v4,
int ifindex,
const NMIPAddr *address,
- int plen,
+ guint8 plen,
const NMIPAddr *peer_address,
guint32 lifetime,
guint32 preferred,
@@ -730,7 +981,7 @@ nmtstp_ip4_address_add (NMPlatform *platform,
gboolean external_command,
int ifindex,
in_addr_t address,
- int plen,
+ guint8 plen,
in_addr_t peer_address,
guint32 lifetime,
guint32 preferred,
@@ -755,7 +1006,7 @@ nmtstp_ip6_address_add (NMPlatform *platform,
gboolean external_command,
int ifindex,
struct in6_addr address,
- int plen,
+ guint8 plen,
struct in6_addr peer_address,
guint32 lifetime,
guint32 preferred,
@@ -782,7 +1033,7 @@ _ip_address_del (NMPlatform *platform,
gboolean is_v4,
int ifindex,
const NMIPAddr *address,
- int plen,
+ guint8 plen,
const NMIPAddr *peer_address)
{
gint64 end_time;
@@ -873,7 +1124,7 @@ nmtstp_ip4_address_del (NMPlatform *platform,
gboolean external_command,
int ifindex,
in_addr_t address,
- int plen,
+ guint8 plen,
in_addr_t peer_address)
{
_ip_address_del (platform,
@@ -890,7 +1141,7 @@ nmtstp_ip6_address_del (NMPlatform *platform,
gboolean external_command,
int ifindex,
struct in6_addr address,
- int plen)
+ guint8 plen)
{
_ip_address_del (platform,
external_command,
@@ -903,6 +1154,119 @@ nmtstp_ip6_address_del (NMPlatform *platform,
/*****************************************************************************/
+static gconstpointer
+_ip_route_add (NMPlatform *platform,
+ gboolean external_command,
+ gboolean is_v4,
+ const NMPlatformIPXRoute *route)
+{
+ gint64 end_time;
+ char s_network[NM_UTILS_INET_ADDRSTRLEN];
+ char s_gateway[NM_UTILS_INET_ADDRSTRLEN];
+ char s_pref_src[NM_UTILS_INET_ADDRSTRLEN];
+ const NMPlatformLink *pllink;
+ NMPObject obj_normalized;
+ const NMPlatformIPXRoute *route_orig;
+ guint i, len;
+
+ g_assert (route);
+ g_assert (route->rx.ifindex > 0);
+
+ external_command = nmtstp_run_command_check_external (external_command);
+
+ _init_platform (&platform, external_command);
+
+ route_orig = route;
+ if (is_v4)
+ nmp_object_stackinit_id_ip4_route (&obj_normalized, &route->r4, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
+ else
+ nmp_object_stackinit_id_ip6_route (&obj_normalized, &route->r6, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
+ route = &obj_normalized.ipx_route;
+
+ pllink = nmtstp_link_get (platform, route->rx.ifindex, NULL);
+ g_assert (pllink);
+
+ if (external_command) {
+ s_network[0] = '\0';
+ s_gateway[0] = '\0';
+ s_pref_src[0] = '\0';
+ if (is_v4) {
+ nm_utils_inet4_ntop (route->r4.network, s_network);
+ if (route->r4.gateway)
+ nm_utils_inet4_ntop (route->r4.gateway, s_gateway);
+ if (route->r4.pref_src)
+ nm_utils_inet4_ntop (route->r4.pref_src, s_pref_src);
+ } else {
+ nm_utils_inet6_ntop (&route->r6.network, s_network);
+ if (!IN6_IS_ADDR_UNSPECIFIED (&route->r6.gateway))
+ nm_utils_inet6_ntop (&route->r6.gateway, s_gateway);
+ }
+
+ nmtstp_run_command_check ("ip route append %s/%u%s dev '%s' metric %u proto %u%s%s",
+ s_network,
+ route->rx.plen,
+ s_gateway[0] ? nm_sprintf_bufa (100, " via %s", s_gateway) : "",
+ pllink->name,
+ route->rx.metric,
+ nmp_utils_ip_config_source_coerce_to_rtprot (route->r4.rt_source),
+ s_pref_src[0] ? nm_sprintf_bufa (100, " src %s", s_pref_src) : "",
+ route->rx.mss ? nm_sprintf_bufa (100, " advmss %u", route->rx.mss) : "");
+ } else {
+ gboolean success;
+
+ if (is_v4)
+ success = nm_platform_ip4_route_add (platform, &route_orig->r4);
+ else
+ success = nm_platform_ip6_route_add (platform, &route_orig->r6);
+ g_assert (success);
+ }
+
+ /* Let's wait until we see the address. */
+ end_time = nm_utils_get_monotonic_timestamp_ms () + 250;
+ do {
+ gs_free const NMPlatformIPXRoute **routes = NULL;
+
+ if (external_command)
+ nm_platform_process_events (platform);
+
+ /* let's wait until we see the address as we added it. */
+ routes = nmtstp_ip_route_get_by_destination (platform, is_v4, route->rx.ifindex,
+ (NMIPAddr *) route->rx.network_ptr,
+ route->rx.plen,
+ route->rx.metric,
+ is_v4 ? (NMIPAddr *) &route->r4.gateway : (NMIPAddr *) &route->r6.gateway,
+ &len);
+ for (i = 0; i < len; i++) {
+ const NMPObject *o2;
+
+ o2 = NMP_OBJECT_UP_CAST (routes[i]);
+ if (nmp_object_equal (o2, &obj_normalized))
+ return &o2->ipx_route;
+ }
+
+ /* for internal command, we expect not to reach this line.*/
+ g_assert (external_command);
+
+ nmtstp_assert_wait_for_signal_until (platform, end_time);
+ } while (TRUE);
+}
+
+const NMPlatformIP4Route *
+nmtstp_ip4_route_add (NMPlatform *platform, gboolean external_command,
+ const NMPlatformIP4Route *route)
+{
+ return _ip_route_add (platform, external_command, TRUE, (const NMPlatformIPXRoute *) route);
+}
+
+const NMPlatformIP6Route *
+nmtstp_ip6_route_add (NMPlatform *platform, gboolean external_command,
+ const NMPlatformIP6Route *route)
+{
+ return _ip_route_add (platform, external_command, FALSE, (const NMPlatformIPXRoute *) route);
+}
+
+/*****************************************************************************/
+
#define _assert_pllink(platform, success, pllink, name, type) \
G_STMT_START { \
const NMPlatformLink *_pllink = (pllink); \
diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h
index 0e3cf10ba4..c4c0e4abd7 100644
--- a/src/platform/tests/test-common.h
+++ b/src/platform/tests/test-common.h
@@ -109,6 +109,47 @@ const NMPlatformLink *nmtstp_wait_for_link_until (NMPlatform *platform, const ch
const NMPlatformLink *nmtstp_assert_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms);
const NMPlatformLink *nmtstp_assert_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms);
+const NMPlatformIP4Route *nmtstp_wait_for_ip4_route (NMPlatform *platform, int ifindex, guint32 network, guint8 plen, guint32 metric, guint32 gateway, guint timeout_ms);
+const NMPlatformIP4Route *nmtstp_wait_for_ip4_route_until (NMPlatform *platform, int ifindex, guint32 network, guint8 plen, guint32 metric, guint32 gateway, gint64 until_ms);
+const NMPlatformIP6Route *nmtstp_wait_for_ip6_route (NMPlatform *platform, int ifindex, const struct in6_addr *network, guint8 plen, guint32 metric, const struct in6_addr *gateway, guint timeout_ms);
+const NMPlatformIP6Route *nmtstp_wait_for_ip6_route_until (NMPlatform *platform, int ifindex, const struct in6_addr *network, guint8 plen, guint32 metric, const struct in6_addr *gateway, gint64 until_ms);
+
+#define nmtstp_assert_wait_for_ip4_route(platform, ifindex, network, plen, metric, gateway, timeout_ms) \
+ ({ \
+ const NMPlatformIP4Route *_plroute; \
+ \
+ _plroute = nmtstp_wait_for_ip4_route (platform, ifindex, network, plen, metric, gateway, timeout_ms); \
+ g_assert (_plroute); \
+ _plroute; \
+ })
+
+#define nmtstp_assert_wait_for_ip4_route_until(platform, ifindex, network, plen, metric, gateway, until_ms) \
+ ({ \
+ const NMPlatformIP4Route *_plroute; \
+ \
+ _plroute = nmtstp_wait_for_ip4_route_until (platform, ifindex, network, plen, metric, gateway, until_ms); \
+ g_assert (_plroute); \
+ _plroute; \
+ })
+
+#define nmtstp_assert_wait_for_ip6_route(platform, ifindex, network, plen, metric, gateway, timeout_ms) \
+ ({ \
+ const NMPlatformIP6Route *_plroute; \
+ \
+ _plroute = nmtstp_wait_for_ip6_route (platform, ifindex, network, plen, metric, gateway, timeout_ms); \
+ g_assert (_plroute); \
+ _plroute; \
+ })
+
+#define nmtstp_assert_wait_for_ip6_route_until(platform, ifindex, network, plen, metric, gateway, until_ms) \
+ ({ \
+ const NMPlatformIP6Route *_plroute; \
+ \
+ _plroute = nmtstp_wait_for_ip6_route_until (platform, ifindex, network, plen, metric, gateway, until_ms); \
+ g_assert (_plroute); \
+ _plroute; \
+ })
+
/*****************************************************************************/
int nmtstp_run_command_check_external_global (void);
@@ -116,10 +157,19 @@ gboolean nmtstp_run_command_check_external (int external_command);
/*****************************************************************************/
-gboolean nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric);
+const NMPlatformIPXRoute **nmtstp_ip_route_get_by_destination (NMPlatform *platform,
+ gboolean is_v4,
+ int ifindex,
+ const NMIPAddr *network,
+ guint8 plen,
+ guint32 metric,
+ const NMIPAddr *gateway,
+ guint *out_len);
+
+gboolean nmtstp_ip4_route_exists (const char *ifname, guint32 network, guint8 plen, guint32 metric, const guint32 *gateway);
-void _nmtstp_assert_ip4_route_exists (const char *file, guint line, const char *func, NMPlatform *platform, gboolean exists, const char *ifname, guint32 network, int plen, guint32 metric);
-#define nmtstp_assert_ip4_route_exists(platform, exists, ifname, network, plen, metric) _nmtstp_assert_ip4_route_exists (__FILE__, __LINE__, G_STRFUNC, platform, exists, ifname, network, plen, metric)
+const NMPlatformIP4Route *_nmtstp_assert_ip4_route_exists (const char *file, guint line, const char *func, NMPlatform *platform, gboolean exists, const char *ifname, guint32 network, guint8 plen, guint32 metric, const guint32 *gateway);
+#define nmtstp_assert_ip4_route_exists(platform, exists, ifname, network, plen, metric, gateway) _nmtstp_assert_ip4_route_exists (__FILE__, __LINE__, G_STRFUNC, platform, exists, ifname, network, plen, metric, gateway)
/*****************************************************************************/
@@ -136,7 +186,7 @@ void nmtstp_ip4_address_add (NMPlatform *platform,
gboolean external_command,
int ifindex,
in_addr_t address,
- int plen,
+ guint8 plen,
in_addr_t peer_address,
guint32 lifetime,
guint32 preferred,
@@ -146,7 +196,7 @@ void nmtstp_ip6_address_add (NMPlatform *platform,
gboolean external_command,
int ifindex,
struct in6_addr address,
- int plen,
+ guint8 plen,
struct in6_addr peer_address,
guint32 lifetime,
guint32 preferred,
@@ -155,13 +205,19 @@ void nmtstp_ip4_address_del (NMPlatform *platform,
gboolean external_command,
int ifindex,
in_addr_t address,
- int plen,
+ guint8 plen,
in_addr_t peer_address);
void nmtstp_ip6_address_del (NMPlatform *platform,
gboolean external_command,
int ifindex,
struct in6_addr address,
- int plen);
+ guint8 plen);
+
+const NMPlatformIP4Route *nmtstp_ip4_route_add (NMPlatform *platform, gboolean external_command,
+ const NMPlatformIP4Route *route);
+
+const NMPlatformIP6Route *nmtstp_ip6_route_add (NMPlatform *platform, gboolean external_command,
+ const NMPlatformIP6Route *route);
/*****************************************************************************/
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index 9d548aabdb..258b6f3476 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -2292,6 +2292,188 @@ test_netns_bind_to_path (gpointer fixture, gconstpointer test_data)
/*****************************************************************************/
+static void
+test_route_external (gconstpointer user_data)
+{
+ const gboolean EX = (nmtst_get_rand_int () % 3) - 1;
+ const char *const MODE = user_data;
+ const char *IF[2] = { "IF0", "IF1" };
+ int ifindex[2];
+ const char *gateway[2] = {
+ "192.168.171.1",
+ "192.168.172.1",
+ };
+ gs_unref_object NMPlatform *pl = NULL;
+ int delete_idx;
+ gs_free const NMPlatformIPXRoute **routes = NULL;
+ guint routes_len;
+
+ g_object_unref (NM_PLATFORM_GET);
+
+ g_assert (NM_IN_STRSET (MODE, "change", "append"));
+
+ pl = nm_linux_platform_new (NM_PLATFORM_NETNS_SUPPORT_DEFAULT);
+
+ ifindex[0] = nmtstp_link_dummy_add (pl, EX, IF[0])->ifindex;
+ ifindex[1] = nmtstp_link_dummy_add (pl, EX, IF[1])->ifindex;
+ nmtstp_link_set_updown (pl, EX, ifindex[0], TRUE);
+ nmtstp_link_set_updown (pl, EX, ifindex[1], TRUE);
+
+ nmtstp_ip4_address_add (pl, EX, ifindex[0],
+ nmtst_inet4_from_string ("192.168.171.5"), 24,
+ nmtst_inet4_from_string ("192.168.171.5"),
+ NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0, NULL);
+ nmtstp_ip4_address_add (pl, EX, ifindex[1],
+ nmtst_inet4_from_string ("192.168.172.5"), 24,
+ nmtst_inet4_from_string ("192.168.172.5"),
+ NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0, NULL);
+
+#define ADDR4(addr_str) (nmtst_ip4_address_to_ptr (nmtst_inet4_from_string (addr_str)))
+
+ nmtstp_run_command_check ("ip route add 192.168.200.0/24 via %s metric 423", gateway[0]);
+ nmtstp_assert_wait_for_ip4_route (pl, ifindex[0], nmtst_inet4_from_string ("192.168.200.0"), 24,
+ 423, nmtst_inet4_from_string (gateway[0]), 100);
+
+ nmtstp_run_command_check ("ip route %s 192.168.200.0/24 via 192.168.172.1 metric 423", MODE);
+
+ if (NM_IN_STRSET (MODE, "changed")) {
+
+ nmtstp_assert_wait_for_ip4_route (pl, ifindex[1], nmtst_inet4_from_string ("192.168.200.0"), 24,
+ 423, nmtst_inet4_from_string (gateway[1]), 100);
+ /* is the route still on ifindex[0]? */
+ routes = nmtstp_ip_route_get_by_destination (pl, TRUE, ifindex[0],
+ ADDR4 ("192.168.200.0"), 24, 423,
+ ADDR4 (gateway[0]), NULL);
+ g_assert (!routes);
+ } else if (NM_IN_STRSET (MODE, "append")) {
+ nmtstp_assert_wait_for_ip4_route (pl, ifindex[1], nmtst_inet4_from_string ("192.168.200.0"), 24,
+ 423, nmtst_inet4_from_string (gateway[1]), 100);
+ /* the route on ifindex[0] should continue to exist */
+ routes = nmtstp_ip_route_get_by_destination (pl, TRUE, ifindex[0],
+ ADDR4 ("192.168.200.0"), 24, 423,
+ ADDR4 (gateway[0]), &routes_len);
+ g_assert (routes_len == 1);
+ g_clear_pointer (&routes, g_free);
+
+ delete_idx = nmtst_get_rand_int () % 2;
+
+ routes = nmtstp_ip_route_get_by_destination (pl, TRUE, ifindex[delete_idx],
+ ADDR4 ("192.168.200.0"), 24, 423,
+ ADDR4 (gateway[delete_idx]), &routes_len);
+ g_assert (routes_len == 1);
+ if (!nm_platform_ip4_route_delete (pl, &routes[0]->r4))
+ g_assert_not_reached ();
+ g_clear_pointer (&routes, g_free);
+
+ routes = nmtstp_ip_route_get_by_destination (pl, TRUE, ifindex[delete_idx],
+ ADDR4 ("192.168.200.0"), 24, 423,
+ ADDR4 (gateway[delete_idx]), &routes_len);
+ g_assert (!routes);
+
+ routes = nmtstp_ip_route_get_by_destination (pl, TRUE, ifindex[!delete_idx],
+ ADDR4 ("192.168.200.0"), 24, 423,
+ ADDR4 (gateway[!delete_idx]), &routes_len);
+ g_assert (routes_len == 1);
+ g_clear_pointer (&routes, g_free);
+ }
+
+ nmtstp_link_del (pl, EX, ifindex[0], IF[0]);
+ nmtstp_link_del (pl, EX, ifindex[1], IF[1]);
+
+ SETUP ();
+}
+
+/*****************************************************************************/
+
+static void
+test_route_modify (gconstpointer test_data)
+{
+#if 0
+ const char *const MODE = test_data;
+ const gboolean EX = (nmtst_get_rand_int () % 3) - 1;
+ const char *IF = "IF0";
+ int ifindex;
+ const char *gateway[2] = {
+ "192.168.181.1",
+ "192.168.181.2",
+ };
+ guint idx[2] = { 0, 1, };
+ guint i;
+ gs_unref_object NMPlatform *pl = NULL;
+
+ g_assert (NM_IN_STRSET (MODE, "delete", "update"));
+
+ g_object_unref (NM_PLATFORM_GET);
+
+ pl = nm_linux_platform_new (NM_PLATFORM_NETNS_SUPPORT_DEFAULT);
+
+ nmtst_rand_perm (NULL, idx, idx, sizeof (idx[0]), G_N_ELEMENTS (idx));
+
+ ifindex = nmtstp_link_dummy_add (pl, EX, IF)->ifindex;
+ nmtstp_link_set_updown (pl, EX, ifindex, TRUE);
+
+ nmtstp_ip4_address_add (pl, EX, ifindex,
+ nmtst_inet4_from_string ("192.168.181.5"), 24,
+ nmtst_inet4_from_string ("192.168.181.5"),
+ NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0, NULL);
+
+ nmtstp_run_command_check ("ip route add 192.168.213.0/24 via %s metric 423", gateway[idx[0]]);
+ if (nmtst_get_rand_int () % 2) {
+ nmtstp_assert_wait_for_ip4_route (pl, ifindex, nmtst_inet4_from_string ("192.168.213.0"), 24,
+ 423, nmtst_inet4_from_string (gateway[idx[0]]), 100);
+ }
+
+ if (nmtst_get_rand_int () % 2) {
+ nmtstp_run_command_check ("ip route append 192.168.213.0/24 via %s metric 423", gateway[idx[1]]);
+ nmtstp_assert_wait_for_ip4_route (pl, ifindex, nmtst_inet4_from_string ("192.168.213.0"), 24,
+ 423, nmtst_inet4_from_string (gateway[idx[1]]), 100);
+ } else {
+ nmtstp_ip4_route_add (pl, EX, ifindex, NM_IP_CONFIG_SOURCE_RTPROT_BOOT,
+ nmtst_inet4_from_string ("192.168.213.0"), 24,
+ nmtst_inet4_from_string (gateway[idx[1]]), 0,
+ 423, 0);
+ }
+
+ g_assert (nm_platform_ip4_route_get (pl, ifindex,
+ nmtst_inet4_from_string ("192.168.213.0"), 24, 423,
+ nmtst_inet4_from_string (gateway[idx[0]])));
+ g_assert (nm_platform_ip4_route_get (pl, ifindex,
+ nmtst_inet4_from_string ("192.168.213.0"), 24, 423,
+ nmtst_inet4_from_string (gateway[idx[1]])));
+
+ nmtst_rand_perm (NULL, idx, idx, sizeof (idx[0]), G_N_ELEMENTS (idx));
+
+ for (i = 0; i < G_N_ELEMENTS (idx); i++) {
+ const NMPlatformIP4Route *plroute;
+
+ if (NM_IN_STRSET (MODE, "delete")) {
+ g_assert (nm_platform_ip4_route_delete (pl, ifindex,
+ nmtst_inet4_from_string ("192.168.213.0"), 24, 423,
+ nmtst_inet4_from_string (gateway[idx[i]])));
+ g_assert (!nm_platform_ip4_route_get (pl, ifindex,
+ nmtst_inet4_from_string ("192.168.213.0"), 24, 423,
+ nmtst_inet4_from_string (gateway[idx[i]])));
+
+ plroute = nm_platform_ip4_route_get (pl, ifindex,
+ nmtst_inet4_from_string ("192.168.213.0"), 24, 423,
+ nmtst_inet4_from_string (gateway[idx[!i]]));
+ g_assert ((i == 0 && plroute) || (i == 1 && !plroute));
+ } else if (NM_IN_STRSET (MODE, "update")) {
+ plroute = nmtstp_ip4_route_add (pl, FALSE, ifindex, NM_IP_CONFIG_SOURCE_USER,
+ nmtst_inet4_from_string ("192.168.213.0"), 24,
+ nmtst_inet4_from_string (gateway[idx[i]]), 0,
+ 423, 1400);
+ }
+ }
+
+ nmtstp_link_del (pl, EX, ifindex, IF);
+
+ SETUP ();
+#endif
+}
+
+/*****************************************************************************/
+
void
_nmtstp_init_tests (int *argc, char ***argv)
{
@@ -2335,6 +2517,11 @@ _nmtstp_setup_tests (void)
g_test_add_data_func ("/link/create-many-links/20", GUINT_TO_POINTER (20), test_create_many_links);
g_test_add_data_func ("/link/create-many-links/1000", GUINT_TO_POINTER (1000), test_create_many_links);
+ g_test_add_data_func ("/route/external/change", "change", test_route_external);
+ g_test_add_data_func ("/route/external/append", "append", test_route_external);
+ g_test_add_data_func ("/route/modify/delete", "delete", test_route_modify);
+ g_test_add_data_func ("/route/modify/update", "update", test_route_modify);
+
g_test_add_func ("/link/nl-bugs/veth", test_nl_bugs_veth);
g_test_add_func ("/link/nl-bugs/spurious-newlink", test_nl_bugs_spuroius_newlink);
g_test_add_func ("/link/nl-bugs/spurious-dellink", test_nl_bugs_spuroius_dellink);
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
index 360404e944..781d6d922b 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -76,56 +76,70 @@ test_ip4_route_metric0 (void)
SignalData *route_added = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip4_route_callback);
SignalData *route_changed = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, ip4_route_callback);
SignalData *route_removed = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip4_route_callback);
- in_addr_t network = nmtst_inet4_from_string ("192.0.2.5"); /* from 192.0.2.0/24 (TEST-NET-1) (rfc5737) */
+ const char *const NETWORK = "192.0.2.5"; /* from 192.0.2.0/24 (TEST-NET-1) (rfc5737) */
+ const guint32 network = nmtst_inet4_from_string (NETWORK);
int plen = 32;
int metric = 22987;
int mss = 1000;
+ NMPlatformIP4Route r = {
+ .ifindex = ifindex,
+ .network = network,
+ .plen = plen,
+ .rt_source = NM_IP_CONFIG_SOURCE_USER,
+ .metric = metric,
+ .mss = mss,
+ };
+ NMPlatformIP4Route r_metric0;
+
+ r_metric0 = r;
+ r_metric0.metric = 0;
/* No routes initially */
- nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
- nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
+ nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0, NULL);
+ nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric, NULL);
/* add the first route */
- g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, metric, mss));
+
+ g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, &r));
accept_signal (route_added);
- nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
- nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
+ nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0, NULL);
+ nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric, NULL);
/* Deleting route with metric 0 does nothing */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
+ g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, &r_metric0));
ensure_no_signal (route_removed);
- nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
- nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
+ nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0, NULL);
+ nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric, NULL);
/* add the second route */
- g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, 0, mss));
+ g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, &r_metric0));
accept_signal (route_added);
- nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, 0);
- nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
+ nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, 0, NULL);
+ nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric, NULL);
/* Delete route with metric 0 */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
+ g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, &r_metric0));
accept_signal (route_removed);
- nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
- nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
+ nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0, NULL);
+ nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric, NULL);
/* Delete route with metric 0 again (we expect nothing to happen) */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
+ g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, &r_metric0));
ensure_no_signal (route_removed);
- nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
- nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
+ nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0, NULL);
+ nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric, NULL);
/* Delete the other route */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
+ g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, &r));
accept_signal (route_removed);
- nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
- nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
+ nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0, NULL);
+ nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric, NULL);
free_signal (route_added);
free_signal (route_changed);
@@ -141,38 +155,61 @@ test_ip4_route (void)
SignalData *route_removed = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip4_route_callback);
GArray *routes;
NMPlatformIP4Route rts[3];
- in_addr_t network;
guint8 plen = 24;
- in_addr_t gateway;
/* Choose a high metric so that we hopefully don't conflict. */
int metric = 22986;
int mss = 1000;
-
- inet_pton (AF_INET, "192.0.3.0", &network);
- inet_pton (AF_INET, "198.51.100.1", &gateway);
+ const char *const NETWORK = "192.0.3.0";
+ const char *const GATEWAY = "198.51.100.1";
+ const guint32 network = nmtst_inet4_from_string (NETWORK);
+ const guint32 gateway = nmtst_inet4_from_string (GATEWAY);
+ NMPlatformIP4Route r = {
+ .ifindex = ifindex,
+ .network = network,
+ .plen = plen,
+ .gateway = gateway,
+ .metric = metric,
+ .mss = mss,
+ .rt_source = NM_IP_CONFIG_SOURCE_USER,
+ };
+ NMPlatformIP4Route r_gateway = {
+ .ifindex = ifindex,
+ .network = gateway,
+ .plen = 32,
+ .metric = metric,
+ .mss = mss,
+ .rt_source = NM_IP_CONFIG_SOURCE_USER,
+ };
+ NMPlatformIP4Route r_default = {
+ .ifindex = ifindex,
+ .gateway = gateway,
+ .metric = metric,
+ .mss = mss,
+ .rt_source = NM_IP_CONFIG_SOURCE_USER,
+ };
/* Add route to gateway */
- g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 32, INADDR_ANY, 0, metric, mss));
+ g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, &r_gateway));
accept_signal (route_added);
/* Add route */
- nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
- g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss));
- nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
+ nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric, NULL);
+ g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, &r));
+ nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric, NULL);
accept_signal (route_added);
/* Add route again */
- g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss));
+ g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, &r));
accept_signals (route_changed, 0, 1);
/* Add default route */
- nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, 0, 0, metric);
- g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss));
- nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, 0, 0, metric);
+ nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, 0, 0, metric, NULL);
+ g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, &r_default));
+ nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, 0, 0, metric, NULL);
accept_signal (route_added);
/* Add default route again */
- g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss));
+ g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, &r_default));
accept_signals (route_changed, 0, 1);
/* Test route listing */
@@ -185,7 +222,8 @@ test_ip4_route (void)
rts[0].gateway = INADDR_ANY;
rts[0].metric = metric;
rts[0].mss = mss;
- rts[0].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK);
+ rts[0].rt_scope = RT_SCOPE_LINK;
+ rts[0].rt_scope_is_set = TRUE;
rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
rts[1].network = network;
rts[1].plen = plen;
@@ -193,7 +231,8 @@ test_ip4_route (void)
rts[1].gateway = gateway;
rts[1].metric = metric;
rts[1].mss = mss;
- rts[1].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE);
+ rts[1].rt_scope = RT_SCOPE_UNIVERSE;
+ rts[1].rt_scope_is_set = TRUE;
rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
rts[2].network = 0;
rts[2].plen = 0;
@@ -201,18 +240,19 @@ test_ip4_route (void)
rts[2].gateway = gateway;
rts[2].metric = metric;
rts[2].mss = mss;
- rts[2].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE);
+ rts[2].rt_scope = RT_SCOPE_UNIVERSE;
+ rts[2].rt_scope_is_set = TRUE;
g_assert_cmpint (routes->len, ==, 3);
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, rts, routes->len, TRUE);
g_array_unref (routes);
/* Remove route */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
- nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
+ g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, &r));
+ nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric, NULL);
accept_signal (route_removed);
/* Remove route again */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
+ g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, &r));
free_signal (route_added);
free_signal (route_changed);
@@ -228,38 +268,60 @@ test_ip6_route (void)
SignalData *route_removed = add_signal (NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip6_route_callback);
GArray *routes;
NMPlatformIP6Route rts[3];
- struct in6_addr network;
+ const char *const NETWORK = "2001:db8:a:b:0:0:0:0";
+ const char *const GATEWAY = "2001:db8:c:d:1:2:3:4";
+ const struct in6_addr network = *nmtst_inet6_from_string (NETWORK);
+ const struct in6_addr gateway = *nmtst_inet6_from_string (GATEWAY);
guint8 plen = 64;
- struct in6_addr gateway;
- /* Choose a high metric so that we hopefully don't conflict. */
int metric = 22987;
int mss = 1000;
-
- inet_pton (AF_INET6, "2001:db8:a:b:0:0:0:0", &network);
- inet_pton (AF_INET6, "2001:db8:c:d:1:2:3:4", &gateway);
+ NMPlatformIP6Route r = {
+ .ifindex = ifindex,
+ .network = network,
+ .plen = plen,
+ .gateway = gateway,
+ .metric = metric,
+ .mss = mss,
+ .rt_source = NM_IP_CONFIG_SOURCE_USER,
+ };
+ NMPlatformIP6Route r_gateway = {
+ .ifindex = ifindex,
+ .network = gateway,
+ .plen = 128,
+ .metric = metric,
+ .mss = mss,
+ .rt_source = NM_IP_CONFIG_SOURCE_USER,
+ };
+ NMPlatformIP6Route r_default = {
+ .ifindex = ifindex,
+ .gateway = gateway,
+ .metric = metric,
+ .mss = mss,
+ .rt_source = NM_IP_CONFIG_SOURCE_USER,
+ };
/* Add route to gateway */
- g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 128, in6addr_any, metric, mss));
+ g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, &r_gateway));
accept_signal (route_added);
/* Add route */
- 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_get (NM_PLATFORM_GET, ifindex, network, plen, metric));
+ g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, &r));
+ g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, &r));
+ g_assert (nm_platform_ip6_route_get (NM_PLATFORM_GET, &r));
accept_signal (route_added);
/* Add route again */
- 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_add (NM_PLATFORM_GET, &r));
accept_signals (route_changed, 0, 1);
/* Add default route */
- 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_get (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric));
+ g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, &r_default));
+ g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, &r_default));
+ g_assert (nm_platform_ip6_route_get (NM_PLATFORM_GET, &r_default));
accept_signal (route_added);
/* Add default route again */
- 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_add (NM_PLATFORM_GET, &r_default));
accept_signals (route_changed, 0, 1);
/* Test route listing */
@@ -291,12 +353,12 @@ test_ip6_route (void)
g_array_unref (routes);
/* Remove route */
- g_assert (nm_platform_ip6_route_delete (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_delete (NM_PLATFORM_GET, &r));
+ g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, &r));
accept_signal (route_removed);
/* Remove route again */
- g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
+ g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, &r));
free_signal (route_added);
free_signal (route_changed);
@@ -309,14 +371,30 @@ static void
test_ip4_zero_gateway (void)
{
int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
+ NMPlatformIP4Route r_global = {
+ .ifindex = ifindex,
+ .network = nmtst_inet4_from_string ("1.2.3.1"),
+ .plen = 32,
+ .rt_source = NM_IP_CONFIG_SOURCE_RTPROT_BOOT,
+ .rt_scope = RT_SCOPE_UNIVERSE,
+ .rt_scope_is_set = TRUE,
+ };
+ NMPlatformIP4Route r_local = {
+ .ifindex = ifindex,
+ .network = nmtst_inet4_from_string ("1.2.3.2"),
+ .plen = 32,
+ .rt_source = NM_IP_CONFIG_SOURCE_RTPROT_BOOT,
+ .rt_scope = RT_SCOPE_LINK,
+ .rt_scope_is_set = TRUE,
+ };
nmtstp_run_command_check ("ip route add 1.2.3.1/32 via 0.0.0.0 dev %s", DEVICE_NAME);
nmtstp_run_command_check ("ip route add 1.2.3.2/32 dev %s", DEVICE_NAME);
NMTST_WAIT_ASSERT (100, {
nmtstp_wait_for_signal (NM_PLATFORM_GET, 10);
- if ( nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.1"), 32, 0)
- && nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.2"), 32, 0))
+ if ( nm_platform_ip4_route_get (NM_PLATFORM_GET, &r_global)
+ && nm_platform_ip4_route_get (NM_PLATFORM_GET, &r_local))
break;
});
diff --git a/src/tests/test-route-manager.c b/src/tests/test-route-manager.c
index b81c263c08..d79dcd2bd7 100644
--- a/src/tests/test-route-manager.c
+++ b/src/tests/test-route-manager.c
@@ -76,14 +76,9 @@ setup_dev1_ip4 (int ifindex)
/* Add some route outside of route manager. The route manager
* should get rid of it upon sync. */
if (!nm_platform_ip4_route_add (NM_PLATFORM_GET,
- route.ifindex,
- NM_IP_CONFIG_SOURCE_USER,
- nmtst_inet4_from_string ("9.0.0.0"),
- 8,
- INADDR_ANY,
- 0,
- 10,
- route.mss))
+ nmtst_platform_ip4_route_full (route.ifindex, "9.0.0.0", 8, NULL,
+ NM_IP_CONFIG_SOURCE_USER, 10, route.mss,
+ 0, FALSE, NULL)))
g_assert_not_reached ();
route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
@@ -169,7 +164,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
.gateway = INADDR_ANY,
.metric = 20,
.mss = 1000,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
+ .rt_scope = RT_SCOPE_LINK,
+ .rt_scope_is_set = TRUE,
},
{
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
@@ -179,7 +175,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
.gateway = nmtst_inet4_from_string ("6.6.6.1"),
.metric = 21021,
.mss = 0,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE),
+ .rt_scope = RT_SCOPE_UNIVERSE,
+ .rt_scope_is_set = TRUE,
},
{
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
@@ -189,7 +186,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
.gateway = INADDR_ANY,
.metric = 22,
.mss = 0,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
+ .rt_scope = RT_SCOPE_LINK,
+ .rt_scope_is_set = TRUE,
},
{
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
@@ -199,7 +197,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
.gateway = INADDR_ANY,
.metric = 21,
.mss = 0,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
+ .rt_scope = RT_SCOPE_LINK,
+ .rt_scope_is_set = TRUE,
},
{
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
@@ -209,7 +208,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
.gateway = nmtst_inet4_from_string ("6.6.6.2"),
.metric = 22,
.mss = 0,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE),
+ .rt_scope = RT_SCOPE_UNIVERSE,
+ .rt_scope_is_set = TRUE,
},
};
@@ -222,7 +222,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
.gateway = INADDR_ANY,
.metric = 20,
.mss = 0,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
+ .rt_scope = RT_SCOPE_LINK,
+ .rt_scope_is_set = TRUE,
},
{
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
@@ -232,7 +233,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
.gateway = INADDR_ANY,
.metric = 21,
.mss = 0,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
+ .rt_scope = RT_SCOPE_LINK,
+ .rt_scope_is_set = TRUE,
},
{
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
@@ -242,7 +244,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
.gateway = INADDR_ANY,
.metric = 22,
.mss = 0,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
+ .rt_scope = RT_SCOPE_LINK,
+ .rt_scope_is_set = TRUE,
},
{
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
@@ -252,7 +255,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
.gateway = INADDR_ANY,
.metric = 21,
.mss = 0,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
+ .rt_scope = RT_SCOPE_LINK,
+ .rt_scope_is_set = TRUE,
},
{
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
@@ -262,7 +266,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
.gateway = nmtst_inet4_from_string ("6.6.6.2"),
.metric = 22,
.mss = 0,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE),
+ .rt_scope = RT_SCOPE_UNIVERSE,
+ .rt_scope_is_set = TRUE,
},
};
@@ -275,7 +280,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
.gateway = INADDR_ANY,
.metric = 22,
.mss = 0,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
+ .rt_scope = RT_SCOPE_LINK,
+ .rt_scope_is_set = TRUE,
},
{
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
@@ -285,7 +291,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
.gateway = INADDR_ANY,
.metric = 20,
.mss = 0,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
+ .rt_scope = RT_SCOPE_LINK,
+ .rt_scope_is_set = TRUE,
},
{
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
@@ -295,7 +302,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
.gateway = nmtst_inet4_from_string ("6.6.6.2"),
.metric = 22,
.mss = 0,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE),
+ .rt_scope = RT_SCOPE_UNIVERSE,
+ .rt_scope_is_set = TRUE,
},
{
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
@@ -307,7 +315,8 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
* with metric 20 (above). But we don't remove the metric 21. */
.metric = 21,
.mss = 0,
- .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
+ .rt_scope = RT_SCOPE_LINK,
+ .rt_scope_is_set = TRUE,
},
};
@@ -382,28 +391,28 @@ setup_dev0_ip6 (int ifindex)
3600,
0);
- route = nmtst_platform_ip6_route_full ("2001:db8:8086::",
+ route = nmtst_platform_ip6_route_full (ifindex,
+ "2001:db8:8086::",
48,
NULL,
- ifindex,
NM_IP_CONFIG_SOURCE_USER,
20,
0);
g_array_append_val (routes, *route);
- route = nmtst_platform_ip6_route_full ("2001:db8:1337::",
+ route = nmtst_platform_ip6_route_full (ifindex,
+ "2001:db8:1337::",
48,
NULL,
- ifindex,
NM_IP_CONFIG_SOURCE_USER,
0,
0);
g_array_append_val (routes, *route);
- route = nmtst_platform_ip6_route_full ("2001:db8:abad:c0de::",
+ route = nmtst_platform_ip6_route_full (ifindex,
+ "2001:db8:abad:c0de::",
64,
"2001:db8:8086::1",
- ifindex,
NM_IP_CONFIG_SOURCE_USER,
21,
0);
@@ -422,46 +431,41 @@ setup_dev1_ip6 (int ifindex)
/* Add some route outside of route manager. The route manager
* should get rid of it upon sync. */
if (!nm_platform_ip6_route_add (NM_PLATFORM_GET,
- ifindex,
- NM_IP_CONFIG_SOURCE_USER,
- *nmtst_inet6_from_string ("2001:db8:8088::"),
- 48,
- in6addr_any,
- 10,
- 0))
+ nmtst_platform_ip6_route_full (ifindex, "2001:db8:8088::", 48, NULL,
+ NM_IP_CONFIG_SOURCE_USER, 10, 0)))
g_assert_not_reached ();
- route = nmtst_platform_ip6_route_full ("2001:db8:8086::",
+ route = nmtst_platform_ip6_route_full (ifindex,
+ "2001:db8:8086::",
48,
NULL,
- ifindex,
NM_IP_CONFIG_SOURCE_USER,
20,
0);
g_array_append_val (routes, *route);
- route = nmtst_platform_ip6_route_full ("2001:db8:1337::",
+ route = nmtst_platform_ip6_route_full (ifindex,
+ "2001:db8:1337::",
48,
NULL,
- ifindex,
NM_IP_CONFIG_SOURCE_USER,
1024,
0);
g_array_append_val (routes, *route);
- route = nmtst_platform_ip6_route_full ("2001:db8:d34d::",
+ route = nmtst_platform_ip6_route_full (ifindex,
+ "2001:db8:d34d::",
64,
"2001:db8:8086::2",
- ifindex,
NM_IP_CONFIG_SOURCE_USER,
20,
0);
g_array_append_val (routes, *route);
- route = nmtst_platform_ip6_route_full ("2001:db8:abad:c0de::",
+ route = nmtst_platform_ip6_route_full (ifindex,
+ "2001:db8:abad:c0de::",
64,
NULL,
- ifindex,
NM_IP_CONFIG_SOURCE_USER,
22,
0);
@@ -487,28 +491,28 @@ update_dev0_ip6 (int ifindex)
3600,
0);
- route = nmtst_platform_ip6_route_full ("2001:db8:8086::",
+ route = nmtst_platform_ip6_route_full (ifindex,
+ "2001:db8:8086::",
48,
NULL,
- ifindex,
NM_IP_CONFIG_SOURCE_USER,
20,
0);
g_array_append_val (routes, *route);
- route = nmtst_platform_ip6_route_full ("2001:db8:1337::",
+ route = nmtst_platform_ip6_route_full (ifindex,
+ "2001:db8:1337::",
48,
NULL,
- ifindex,
NM_IP_CONFIG_SOURCE_USER,
0,
0);
g_array_append_val (routes, *route);
- route = nmtst_platform_ip6_route_full ("2001:db8:abad:c0de::",
+ route = nmtst_platform_ip6_route_full (ifindex,
+ "2001:db8:abad:c0de::",
64,
NULL,
- ifindex,
NM_IP_CONFIG_SOURCE_USER,
21,
0);
@@ -791,9 +795,9 @@ _assert_route_check (const NMPlatformVTableRoute *vtable, gboolean has, const NM
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);
+ r = (const NMPlatformIPXRoute *) nm_platform_ip4_route_get (NM_PLATFORM_GET, &route->r4);
else
- r = (const NMPlatformIPXRoute *) nm_platform_ip6_route_get (NM_PLATFORM_GET, route->rx.ifindex, route->r6.network, route->rx.plen, route->rx.metric);
+ r = (const NMPlatformIPXRoute *) nm_platform_ip6_route_get (NM_PLATFORM_GET, &route->r6);
if (!has) {
g_assert (!r);
@@ -824,15 +828,15 @@ test_ip4_full_sync (test_fixture *fixture, gconstpointer user_data)
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);
+ r01 = *nmtst_platform_ip4_route_full (fixture->ifindex0, "12.3.4.0", 24, NULL,
+ NM_IP_CONFIG_SOURCE_USER,
+ 100, 0, RT_SCOPE_LINK, TRUE, NULL);
+ r02 = *nmtst_platform_ip4_route_full (fixture->ifindex0, "13.4.5.6", 32, "12.3.4.1",
+ NM_IP_CONFIG_SOURCE_USER,
+ 100, 0, RT_SCOPE_UNIVERSE, TRUE, NULL);
+ r03 = *nmtst_platform_ip4_route_full (fixture->ifindex0, "14.5.6.7", 32, "12.3.4.1",
+ NM_IP_CONFIG_SOURCE_USER,
+ 110, 0, RT_SCOPE_UNIVERSE, TRUE, NULL);
g_array_set_size (routes, 2);
g_array_index (routes, NMPlatformIP4Route, 0) = r01;
g_array_index (routes, NMPlatformIP4Route, 1) = r02;
@@ -842,7 +846,7 @@ test_ip4_full_sync (test_fixture *fixture, gconstpointer user_data)
_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);
+ vtable->route_add (NM_PLATFORM_GET, (const NMPlatformIPXRoute *) &r03, 0, -1);
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01);
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r02);