summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/devices/tests/Makefile.am3
-rw-r--r--src/nm-default-route-manager.c5
-rw-r--r--src/nm-route-manager.c3
-rw-r--r--src/platform/nm-fake-platform.c36
-rw-r--r--src/platform/nm-linux-platform.c119
-rw-r--r--src/platform/nm-platform.c133
-rw-r--r--src/platform/nm-platform.h29
-rw-r--r--src/platform/nmp-object.c65
-rw-r--r--src/platform/nmp-object.h4
-rw-r--r--src/platform/tests/test-common.c294
-rw-r--r--src/platform/tests/test-common.h59
-rw-r--r--src/platform/tests/test-link.c173
-rw-r--r--src/platform/tests/test-route.c68
-rw-r--r--src/tests/test-route-manager.c4
14 files changed, 772 insertions, 223 deletions
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..3c5737585f 100644
--- a/src/nm-default-route-manager.c
+++ b/src/nm-default-route-manager.c
@@ -355,7 +355,10 @@ _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_default (priv->platform, route->ifindex, route->metric,
+ vtable->vt->is_ip4
+ ? (NMIPAddr *) &((NMPlatformIP4Route *) route)->gateway
+ : (NMIPAddr *) &((NMPlatformIP6Route *) route)->gateway);
changed = TRUE;
}
}
diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c
index 2d4c7d9595..64b8889a9f 100644
--- a/src/nm-route-manager.c
+++ b/src/nm-route-manager.c
@@ -1002,7 +1002,8 @@ _ip4_device_routes_idle_cb (IP4DeviceRoutePurgeEntry *entry)
entry->obj->ip4_route.ifindex,
entry->obj->ip4_route.network,
entry->obj->ip4_route.plen,
- entry->obj->ip4_route.metric);
+ entry->obj->ip4_route.metric,
+ entry->obj->ip4_route.gateway);
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 39b5f3c080..1971149229 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -1131,7 +1131,7 @@ 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, int ifindex, in_addr_t network, guint8 plen, guint32 metric, guint32 gateway)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@@ -1143,7 +1143,8 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 p
if ( route->ifindex != ifindex
|| route->network != network
|| route->plen != plen
- || route->metric != metric)
+ || route->metric != metric
+ || route->gateway != gateway)
continue;
memcpy (&deleted_route, route, sizeof (deleted_route));
@@ -1155,7 +1156,7 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 p
}
static gboolean
-ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
+ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric, const struct in6_addr *gateway)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@@ -1169,7 +1170,8 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, gu
if ( route->ifindex != ifindex
|| !IN6_ARE_ADDR_EQUAL (&route->network, &network)
|| route->plen != plen
- || route->metric != metric)
+ || route->metric != metric
+ || !IN6_ARE_ADDR_EQUAL (&route->gateway, gateway ?: &nm_ip_addr_zero.addr6))
continue;
memcpy (&deleted_route, route, sizeof (deleted_route));
@@ -1232,7 +1234,7 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
continue;
if (item->ifindex != route.ifindex) {
- ip4_route_delete (platform, item->ifindex, item->network, item->plen, item->metric);
+ ip4_route_delete (platform, item->ifindex, item->network, item->plen, item->metric, item->gateway);
i--;
continue;
}
@@ -1298,7 +1300,7 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
continue;
if (item->ifindex != route.ifindex) {
- ip6_route_delete (platform, item->ifindex, item->network, item->plen, item->metric);
+ ip6_route_delete (platform, item->ifindex, item->network, item->plen, item->metric, &item->gateway);
i--;
continue;
}
@@ -1315,7 +1317,7 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
}
static const NMPlatformIP4Route *
-ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
+ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric, guint32 gateway)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@@ -1323,10 +1325,11 @@ ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen
for (i = 0; i < priv->ip4_routes->len; i++) {
NMPlatformIP4Route *route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
- if (route->ifindex == ifindex
- && route->network == network
- && route->plen == plen
- && route->metric == metric)
+ if ( route->ifindex == ifindex
+ && route->network == network
+ && route->plen == plen
+ && route->metric == metric
+ && route->gateway == gateway)
return route;
}
@@ -1334,7 +1337,7 @@ 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, int ifindex, struct in6_addr network, guint8 plen, guint32 metric, const struct in6_addr *gateway)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@@ -1344,10 +1347,11 @@ ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, guint
for (i = 0; i < priv->ip6_routes->len; i++) {
NMPlatformIP6Route *route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
- if (route->ifindex == ifindex
- && IN6_ARE_ADDR_EQUAL (&route->network, &network)
- && route->plen == plen
- && route->metric == metric)
+ if ( route->ifindex == ifindex
+ && IN6_ARE_ADDR_EQUAL (&route->network, &network)
+ && route->plen == plen
+ && route->metric == metric
+ && IN6_ARE_ADDR_EQUAL (&route->gateway, gateway ?: &nm_ip_addr_zero.addr6))
return route;
}
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 11c2e965b2..885b066b17 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -304,6 +304,16 @@ _support_user_ipv6ll_detect (struct nlattr **tb)
******************************************************************/
static void
+_ip6_route_normalize_metric (const NMPlatformIP6Route **route, NMPlatformIP6Route *r_storage)
+{
+ if ((*route)->metric != nm_utils_ip6_route_metric_normalize ((*route)->metric)) {
+ *r_storage = **route;
+ r_storage->metric = nm_utils_ip6_route_metric_normalize ((*route)->metric);
+ *route = r_storage;
+ }
+}
+
+static void
clear_host_address (int family, const void *network, guint8 plen, void *dst)
{
g_return_if_fail (network);
@@ -3876,6 +3886,16 @@ do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
event_handler_read_netlink (platform, FALSE);
+ if (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_id), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)) {
+ /* for routes, we set the flags to NLM_F_CREATE | NLM_F_APPEND. This will fail with EEXIST
+ * if the route already exists, which is just splendind.
+ *
+ * So, first check the cache whether we expect the route to exist, and if so, set the
+ * flags to REPLACE. */
+ if (nmp_cache_lookup_obj (priv->cache, obj_id))
+ nlmsg_hdr (nlmsg)->nlmsg_flags |= NLM_F_REPLACE;
+ }
+
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
if (nle < 0) {
_LOGE ("do-add-%s[%s]: failure sending netlink request \"%s\" (%d)",
@@ -5548,65 +5568,64 @@ 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;
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
- NLM_F_CREATE | NLM_F_REPLACE,
+ NLM_F_CREATE | NLM_F_APPEND,
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);
+ route->ifindex,
+ route->rt_source,
+ route->gateway ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK,
+ &route->network,
+ route->plen,
+ &route->gateway,
+ route->metric,
+ route->mss,
+ route->pref_src ? &route->pref_src : NULL);
+
+ nmp_object_stackinit_id_ip4_route (&obj_id, route);
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;
+ NMPlatformIP6Route r_storage;
+
+ _ip6_route_normalize_metric (&route, &r_storage);
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
- NLM_F_CREATE | NLM_F_REPLACE,
+ NLM_F_CREATE | NLM_F_APPEND,
AF_INET6,
- ifindex,
- source,
- !IN6_IS_ADDR_UNSPECIFIED (&gateway) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK,
- &network,
- plen,
- &gateway,
- metric,
- mss,
+ route->ifindex,
+ route->rt_source,
+ !IN6_IS_ADDR_UNSPECIFIED (&route->gateway) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK,
+ &route->network,
+ route->plen,
+ &route->gateway,
+ route->metric,
+ route->mss,
NULL);
- nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric);
+ nmp_object_stackinit_id_ip6_route (&obj_id, route);
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);
- if (metric == 0) {
+ if (route->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.
@@ -5638,13 +5657,13 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 p
nlmsg = _nl_msg_new_route (RTM_DELROUTE,
0,
AF_INET,
- ifindex,
+ route->ifindex,
NM_IP_CONFIG_SOURCE_UNKNOWN,
RT_SCOPE_NOWHERE,
- &network,
- plen,
- NULL,
- metric,
+ &route->network,
+ route->plen,
+ &route->gateway,
+ route->metric,
0,
NULL);
if (!nlmsg)
@@ -5654,40 +5673,41 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 p
}
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)
{
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
NMPObject obj_id;
+ NMPlatformIP6Route r_storage;
- metric = nm_utils_ip6_route_metric_normalize (metric);
+ _ip6_route_normalize_metric (&route, &r_storage);
nlmsg = _nl_msg_new_route (RTM_DELROUTE,
0,
AF_INET6,
- ifindex,
+ route->ifindex,
NM_IP_CONFIG_SOURCE_UNKNOWN,
RT_SCOPE_NOWHERE,
- &network,
- plen,
- NULL,
- metric,
+ &route->network,
+ route->plen,
+ &route->gateway,
+ route->metric,
0,
NULL);
if (!nlmsg)
return FALSE;
- nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric);
+ nmp_object_stackinit_id_ip6_route (&obj_id, route);
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);
obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_id);
if (nmp_object_is_visible (obj))
return &obj->ip4_route;
@@ -5695,14 +5715,15 @@ 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;
+ NMPlatformIP6Route r_storage;
- metric = nm_utils_ip6_route_metric_normalize (metric);
+ _ip6_route_normalize_metric (&route, &r_storage);
- nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric);
+ nmp_object_stackinit_id_ip6_route (&obj_id, route);
obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_id);
if (nmp_object_is_visible (obj))
return &obj->ip6_route;
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index afbe5f8263..e382370446 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -2908,45 +2908,49 @@ nm_platform_ip6_route_add (NMPlatform *self,
}
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, int ifindex, in_addr_t network, guint8 plen, guint32 metric, guint32 gateway)
{
char str_dev[TO_STRING_DEV_BUF_SIZE];
+ char str_gateway[NM_UTILS_INET_ADDRSTRLEN];
_CHECK_SELF (self, klass, FALSE);
- _LOGD ("route: deleting IPv4 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s",
+ _LOGD ("route: deleting IPv4 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s, gateway=%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);
+ _to_string_dev (self, ifindex, str_dev, sizeof (str_dev)),
+ nm_utils_inet4_ntop (gateway, str_gateway));
+ return klass->ip4_route_delete (self, ifindex, network, plen, metric, gateway);
}
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, int ifindex, struct in6_addr network, guint8 plen, guint32 metric, const struct in6_addr *gateway)
{
char str_dev[TO_STRING_DEV_BUF_SIZE];
+ char str_gateway[NM_UTILS_INET_ADDRSTRLEN];
_CHECK_SELF (self, klass, FALSE);
- _LOGD ("route: deleting IPv6 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s",
+ _LOGD ("route: deleting IPv6 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s, gateway=%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);
+ _to_string_dev (self, ifindex, str_dev, sizeof (str_dev)),
+ nm_utils_inet6_ntop (gateway ?: &nm_ip_addr_zero.addr6, str_gateway));
+ return klass->ip6_route_delete (self, ifindex, network, plen, metric, gateway);
}
const NMPlatformIP4Route *
-nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
+nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric, guint32 gateway)
{
_CHECK_SELF (self, klass, FALSE);
- return klass->ip4_route_get (self ,ifindex, network, plen, metric);
+ return klass->ip4_route_get (self ,ifindex, network, plen, metric, gateway);
}
const NMPlatformIP6Route *
-nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
+nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric, const struct in6_addr *gateway)
{
_CHECK_SELF (self, klass, FALSE);
- return klass->ip6_route_get (self, ifindex, network, plen, metric);
+ return klass->ip6_route_get (self, ifindex, network, plen, metric, gateway);
}
/******************************************************************/
@@ -3917,6 +3921,9 @@ int
nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b)
{
_CMP_SELF (a, b);
+
+ /* for nmp_object_id_equal(), all fields of the route are considered here. */
+
_CMP_FIELD (a, b, ifindex);
_CMP_FIELD (a, b, network);
_CMP_FIELD (a, b, plen);
@@ -3930,10 +3937,35 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
return 0;
}
+guint
+nm_platform_ip4_route_hash (const NMPlatformIP4Route *a)
+{
+ guint h = 0x8202baf9;
+
+ /* goes together with nm_platform_ip4_route_cmp(). */
+
+ if (a) {
+ h += (h * 33) + ((guint) a->ifindex);
+ h += (h * 33) + ((guint) a->network);
+ h += (h * 33) + ((guint) a->plen);
+ h += (h * 33) + ((guint) a->metric);
+ h += (h * 33) + ((guint) a->gateway);
+ h += (h * 33) + ((guint) a->rt_source);
+ h += (h * 33) + ((guint) a->mss);
+ h += (h * 33) + ((guint) a->scope_inv);
+ h += (h * 33) + ((guint) a->pref_src);
+ h += (h * 33) + ((guint) a->rt_cloned);
+ }
+ return h;
+}
+
int
nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b)
{
_CMP_SELF (a, b);
+
+ /* for nmp_object_id_equal(), all fields of the route are considered here. */
+
_CMP_FIELD (a, b, ifindex);
_CMP_FIELD_MEMCMP (a, b, network);
_CMP_FIELD (a, b, plen);
@@ -3945,6 +3977,32 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
return 0;
}
+guint
+nm_platform_ip6_route_hash (const NMPlatformIP6Route *a)
+{
+ guint h = 0x0569b8f4;
+
+ /* goes together with nm_platform_ip6_route_cmp(). */
+
+ if (a) {
+ h += (h * 33) + ((guint) a->ifindex);
+ 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]);
+ h += (h * 33) + ((guint) a->plen);
+ h += (h * 33) + ((guint) a->metric);
+ 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]);
+ h += (h * 33) + ((guint) a->rt_source);
+ h += (h * 33) + ((guint) a->mss);
+ h += (h * 33) + ((guint) a->rt_cloned);
+ }
+ return h;
+}
+
/**
* nm_platform_ip_address_cmp_expiry:
* @a: a NMPlatformIPAddress to compare
@@ -4072,28 +4130,31 @@ nm_platform_netns_push (NMPlatform *platform, NMPNetns **netns)
static gboolean
_vtr_v4_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, 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
+ || (metric >= 0 && route->metric != 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);
}
static gboolean
_vtr_v6_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, 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
+ || (metric >= 0 && route->metric != 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);
}
static gboolean
@@ -4103,7 +4164,8 @@ _vtr_v4_route_delete (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *r
ifindex > 0 ? ifindex : route->rx.ifindex,
route->r4.network,
route->rx.plen,
- route->rx.metric);
+ route->rx.metric,
+ route->r4.gateway);
}
static gboolean
@@ -4113,7 +4175,8 @@ _vtr_v6_route_delete (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *r
ifindex > 0 ? ifindex : route->rx.ifindex,
route->r6.network,
route->rx.plen,
- route->rx.metric);
+ route->rx.metric,
+ &route->r6.gateway);
}
static guint32
@@ -4123,15 +4186,15 @@ _vtr_v4_metric_normalize (guint32 metric)
}
static gboolean
-_vtr_v4_route_delete_default (NMPlatform *self, int ifindex, guint32 metric)
+_vtr_v4_route_delete_default (NMPlatform *self, int ifindex, guint32 metric, const NMIPAddr *gateway)
{
- return nm_platform_ip4_route_delete (self, ifindex, 0, 0, metric);
+ return nm_platform_ip4_route_delete (self, ifindex, 0, 0, metric, gateway ? gateway->addr4 : 0);
}
static gboolean
-_vtr_v6_route_delete_default (NMPlatform *self, int ifindex, guint32 metric)
+_vtr_v6_route_delete_default (NMPlatform *self, int ifindex, guint32 metric, const NMIPAddr *gateway)
{
- return nm_platform_ip6_route_delete (self, ifindex, in6addr_any, 0, metric);
+ return nm_platform_ip6_route_delete (self, ifindex, in6addr_any, 0, metric, gateway ? &gateway->addr6 : NULL);
}
/******************************************************************/
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 2c1823c21d..ee3d849078 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -374,7 +374,7 @@ typedef struct {
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_delete_default) (NMPlatform *self, int ifindex, guint32 metric, const NMIPAddr *gateway);
guint32 (*metric_normalize) (guint32 metric);
} NMPlatformVTableRoute;
@@ -635,10 +635,10 @@ typedef struct {
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_delete) (NMPlatform *, int ifindex, in_addr_t network, guint8 plen, guint32 metric, guint32 gateway);
+ gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, guint8 plen, guint32 metric, const struct in6_addr *gateway);
+ 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 *);
@@ -903,18 +903,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);
@@ -950,6 +946,9 @@ 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);
+guint nm_platform_ip4_route_hash (const NMPlatformIP4Route *a);
+guint nm_platform_ip6_route_hash (const NMPlatformIP6Route *a);
+
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..50a9a0d860 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)
{
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)
+ obj->ip4_route = *route;
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);
}
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)
{
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)
+ obj->ip6_route = *route;
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);
}
/******************************************************************/
@@ -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;
+ *dst = *src;
});
_vt_cmd_plobj_id_copy (ip6_route, NMPlatformIP6Route, {
- dst->ifindex = src->ifindex;
- dst->plen = src->plen;
- dst->metric = src->metric;
- dst->network = src->network;
+ *dst = *src;
});
/* 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 (obj1, obj2) == 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 (obj1, obj2) == 0);
guint
nmp_object_id_hash (const NMPObject *obj)
@@ -861,20 +842,6 @@ _vt_cmd_plobj_id_hash (ip6_address, NMPlatformIP6Address, {
/* for IPv6 addresses, the prefix length is not part of the primary identifier. */
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);
-})
-_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);
-})
gboolean
nmp_object_is_alive (const NMPObject *obj)
@@ -2171,8 +2138,8 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route,
.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_id_hash = (guint (*) (const NMPlatformObject *obj)) nm_platform_ip4_route_hash,
+ .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,
},
@@ -2191,8 +2158,8 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route,
.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_id_hash = (guint (*) (const NMPlatformObject *obj)) nm_platform_ip6_route_hash,
+ .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 c5241037d5..95d7fab1c1 100644
--- a/src/platform/nmp-object.h
+++ b/src/platform/nmp-object.h
@@ -372,8 +372,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);
+const NMPObject *nmp_object_stackinit_id_ip6_route (NMPObject *obj, const NMPlatformIP6Route *route);
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-common.c b/src/platform/tests/test-common.c
index b1947a6d11..34783c3ea4 100644
--- a/src/platform/tests/test-common.c
+++ b/src/platform/tests/test-common.c
@@ -25,6 +25,8 @@
#include <sys/wait.h>
#include <fcntl.h>
+#include "nm-platform-utils.h"
+
#include "test-common.h"
#define SIGNAL_DATA_FMT "'%s-%s' ifindex %d%s%s%s (%d times received)"
@@ -197,7 +199,7 @@ link_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlat
/*****************************************************************************/
gboolean
-nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric)
+nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric, const guint32 *gateway)
{
gs_free char *arg_network = NULL;
const char *argv[] = {
@@ -216,6 +218,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 +256,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,45 +268,104 @@ 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;
}
- p = strstr (line, metric_pattern);
- if (p && NM_IN_SET (p[strlen (metric_pattern)], ' ', '\0'))
- return TRUE;
+
+ 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;
+ }
+ }
+ 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)
+_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 guint32 *gateway)
{
int ifindex;
gboolean exists_checked;
+ char s_buf[NM_UTILS_INET_ADDRSTRLEN];
+ guint32 g = 0;
+ gboolean found_fuzzy = FALSE;
_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",
+
+ if (gateway)
+ g = *gateway;
+ else {
+ gs_unref_array GArray *routes = NULL;
+ guint i;
+
+ routes = nm_platform_ip4_route_get_all (platform, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_RTPROT_KERNEL);
+ for (i = 0; routes && i < routes->len; i++) {
+ const NMPlatformIP4Route *r = &g_array_index (routes, NMPlatformIP4Route, i);
+
+ g_assert (r->ifindex == ifindex);
+ if ( r->network == network
+ && r->plen == plen
+ && r->metric == metric) {
+ g_assert (!found_fuzzy);
+ found_fuzzy = TRUE;
+ g = r->gateway;
+ }
+ }
+ if (found_fuzzy)
+ goto found;
+ if (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");
+ }
+ return;
+ }
+found:
+ if (!nm_platform_ip4_route_get (platform, ifindex, network, plen, metric, g) != !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, metric,
+ nm_utils_inet4_ntop (network, NULL),
+ plen,
+ nm_utils_inet4_ntop (g, s_buf),
+ metric,
exists ? "exists" : "does not exist",
exists ? "it doesn't" : "it does");
}
+
+ /* when we found the route via fuzzy-match (without gateway), we expect that
+ * exists and nm_platform_ip4_route_get() agree. */
+ g_assert (!found_fuzzy || exists);
}
/*****************************************************************************/
@@ -414,7 +477,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 +506,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 +521,61 @@ 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)
+{
+ const void *plroute = NULL;
+ gint64 now;
+
+ _init_platform (&platform, FALSE);
+
+ while (TRUE) {
+ now = nm_utils_get_monotonic_timestamp_ms ();
+
+ if (is_v4)
+ plroute = nm_platform_ip4_route_get (platform, ifindex, network->addr4, plen, metric, gateway->addr4);
+ else {
+ plroute = nm_platform_ip6_route_get (platform, ifindex,
+ network ? network->addr6 : in6addr_any,
+ plen, metric,
+ gateway ? &gateway->addr6 : &in6addr_any);
+ }
+ if (plroute)
+ return plroute;
+
+ 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)
{
@@ -903,6 +1021,152 @@ nmtstp_ip6_address_del (NMPlatform *platform,
/*****************************************************************************/
+static gconstpointer
+_ip_route_add (NMPlatform *platform,
+ gboolean external_command,
+ gboolean is_v4,
+ int ifindex,
+ NMIPConfigSource source,
+ const NMIPAddr *network,
+ guint8 plen,
+ const NMIPAddr *gateway,
+ guint32 *pref_src,
+ guint32 metric,
+ guint32 mss)
+{
+ 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;
+
+ external_command = nmtstp_run_command_check_external (external_command);
+
+ _init_platform (&platform, external_command);
+
+ pllink = nmtstp_link_get (platform, 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 (network->addr4, s_network);
+ if (gateway->addr4)
+ nm_utils_inet4_ntop (gateway->addr4, s_gateway);
+ if (*pref_src)
+ nm_utils_inet4_ntop (*pref_src, s_pref_src);
+ } else {
+ nm_utils_inet6_ntop (network ? &network->addr6 : &in6addr_any, s_network);
+ if (gateway && !IN6_IS_ADDR_UNSPECIFIED (&gateway->addr6))
+ nm_utils_inet6_ntop (&gateway->addr6, s_gateway);
+ g_assert (!pref_src);
+ }
+
+ nmtstp_run_command_check ("ip route append %s/%u%s dev '%s' metric %u protocol %d%s%s",
+ s_network,
+ plen,
+ s_gateway[0] ? nm_sprintf_bufa (100, " via %s", s_gateway) : "",
+ pllink->name,
+ metric,
+ nmp_utils_ip_config_source_coerce_to_rtprot (source),
+ s_pref_src[0] ? nm_sprintf_bufa (100, " src %s", s_pref_src) : "",
+ mss ? nm_sprintf_bufa (100, " advmss %u", mss) : "");
+ } else {
+ gboolean success;
+
+ if (is_v4) {
+ success = nm_platform_ip4_route_add (platform,
+ ifindex,
+ source,
+ network->addr4,
+ plen,
+ gateway->addr4,
+ *pref_src,
+ metric,
+ mss);
+ } else {
+ g_assert (pref_src == NULL);
+ success = nm_platform_ip6_route_add (platform,
+ ifindex,
+ source,
+ network ? network->addr6 : in6addr_any,
+ plen,
+ gateway ? gateway->addr6 : in6addr_any,
+ metric,
+ mss);
+ }
+ g_assert (success);
+ }
+
+ /* Let's wait until we see the address. */
+ end_time = nm_utils_get_monotonic_timestamp_ms () + 250;
+ do {
+ if (external_command)
+ nm_platform_process_events (platform);
+
+ /* let's wait until we see the address as we added it. */
+ if (is_v4) {
+ const NMPlatformIP4Route *r;
+
+ r = nm_platform_ip4_route_get (platform, ifindex, network->addr4, plen, metric, gateway->addr4);
+ if (r) {
+ g_assert (r->ifindex == ifindex);
+ g_assert (r->network == network->addr4);
+ g_assert (r->plen == plen);
+ g_assert (r->metric == metric);
+ g_assert (r->gateway == gateway->addr4);
+ if ( r->mss == mss
+ && r->pref_src == *pref_src
+ && r->rt_source == nmp_utils_ip_config_source_round_trip_rtprot (source))
+ return r;
+ }
+ } else {
+ const NMPlatformIP6Route *r;
+
+ r = nm_platform_ip6_route_get (platform, ifindex, network ? network->addr6 : in6addr_any, plen, metric, gateway ? &gateway->addr6 : NULL);
+ if (r) {
+ g_assert (r->ifindex == ifindex);
+ g_assert (IN6_ARE_ADDR_EQUAL (&r->network, network ? &network->addr6 : &in6addr_any));
+ g_assert (r->plen == plen);
+ g_assert (r->metric == metric);
+ g_assert (IN6_ARE_ADDR_EQUAL (&r->gateway, gateway ? &gateway->addr6 : &in6addr_any));
+ if ( r->mss == mss
+ && r->rt_source == nmp_utils_ip_config_source_round_trip_rtprot (source))
+ return r;
+ }
+ }
+
+ /* 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,
+ int ifindex, NMIPConfigSource source,
+ guint32 network, guint8 plen,
+ guint32 gateway, guint32 pref_src,
+ guint32 metric, guint32 mss)
+{
+ return _ip_route_add (platform, external_command, TRUE, ifindex, source, (NMIPAddr *) &network, plen, (NMIPAddr *) &gateway, &pref_src, metric, mss);
+}
+
+const NMPlatformIP4Route *
+nmtstp_ip6_route_add (NMPlatform *platform, gboolean external_command,
+ int ifindex, NMIPConfigSource source,
+ const struct in6_addr *network, guint8 plen,
+ const struct in6_addr *gateway,
+ guint32 metric, guint32 mss)
+{
+ return _ip_route_add (platform, external_command, FALSE, ifindex, source, (NMIPAddr *) &network, plen, (NMIPAddr *) &gateway, NULL, metric, mss);
+}
+
+/*****************************************************************************/
+
#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..5a7c8963d1 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,10 @@ gboolean nmtstp_run_command_check_external (int external_command);
/*****************************************************************************/
-gboolean nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric);
+gboolean nmtstp_ip4_route_exists (const char *ifname, guint32 network, int 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)
+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 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)
/*****************************************************************************/
@@ -163,6 +204,18 @@ void nmtstp_ip6_address_del (NMPlatform *platform,
struct in6_addr address,
int plen);
+const NMPlatformIP4Route *nmtstp_ip4_route_add (NMPlatform *platform, gboolean external_command,
+ int ifindex, NMIPConfigSource source,
+ guint32 network, guint8 plen,
+ guint32 gateway, guint32 pref_src,
+ guint32 metric, guint32 mss);
+
+const NMPlatformIP4Route *nmtstp_ip6_route_add (NMPlatform *platform, gboolean external_command,
+ int ifindex, NMIPConfigSource source,
+ const struct in6_addr *network, guint8 plen,
+ const struct in6_addr *gateway,
+ guint32 metric, guint32 mss);
+
/*****************************************************************************/
const NMPlatformLink *nmtstp_link_get_typed (NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type);
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index 9d548aabdb..c834944b97 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -2292,6 +2292,174 @@ 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;;
+
+ 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);
+
+ 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]? */
+ if (nm_platform_ip4_route_get (pl, ifindex[0],
+ nmtst_inet4_from_string ("192.168.200.0"), 24,
+ 423, nmtst_inet4_from_string (gateway[0])))
+ g_assert_not_reached ();
+ } 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 */
+ if (!nm_platform_ip4_route_get (pl, ifindex[0],
+ nmtst_inet4_from_string ("192.168.200.0"), 24,
+ 423, nmtst_inet4_from_string (gateway[0])))
+ g_assert_not_reached ();
+
+ delete_idx = nmtst_get_rand_int () % 2;
+
+ if (!nm_platform_ip4_route_delete (pl, ifindex[delete_idx],
+ nmtst_inet4_from_string ("192.168.200.0"), 24, 423,
+ nmtst_inet4_from_string (gateway[delete_idx])))
+ g_assert_not_reached ();
+ if (nm_platform_ip4_route_get (pl, ifindex[delete_idx],
+ nmtst_inet4_from_string ("192.168.200.0"), 24, 423,
+ nmtst_inet4_from_string (gateway[delete_idx])))
+ g_assert_not_reached ();
+ if (!nm_platform_ip4_route_get (pl, ifindex[!delete_idx],
+ nmtst_inet4_from_string ("192.168.200.0"), 24, 423,
+ nmtst_inet4_from_string (gateway[!delete_idx])))
+ g_assert_not_reached ();
+ }
+
+ 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)
+{
+ 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 ();
+}
+
+/*****************************************************************************/
+
void
_nmtstp_init_tests (int *argc, char ***argv)
{
@@ -2335,6 +2503,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..a0b70c4e89 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -82,50 +82,50 @@ test_ip4_route_metric0 (void)
int mss = 1000;
/* 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));
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, ifindex, network, plen, 0, INADDR_ANY));
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));
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, ifindex, network, plen, 0, INADDR_ANY));
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, ifindex, network, plen, 0, INADDR_ANY));
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, ifindex, network, plen, metric, INADDR_ANY));
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);
@@ -156,9 +156,9 @@ test_ip4_route (void)
accept_signal (route_added);
/* Add route */
- nmtstp_assert_ip4_route_exists (NULL, FALSE, 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, 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, TRUE, DEVICE_NAME, network, plen, metric, NULL);
accept_signal (route_added);
/* Add route again */
@@ -166,9 +166,9 @@ test_ip4_route (void)
accept_signals (route_changed, 0, 1);
/* Add default route */
- nmtstp_assert_ip4_route_exists (NULL, FALSE, 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, 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, TRUE, DEVICE_NAME, 0, 0, metric, NULL);
accept_signal (route_added);
/* Add default route again */
@@ -207,12 +207,12 @@ test_ip4_route (void)
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, ifindex, network, plen, metric, gateway));
+ 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, ifindex, network, plen, metric, gateway));
free_signal (route_added);
free_signal (route_changed);
@@ -243,9 +243,9 @@ test_ip6_route (void)
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_get (NM_PLATFORM_GET, ifindex, network, plen, metric, &gateway));
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, ifindex, network, plen, metric, &gateway));
accept_signal (route_added);
/* Add route again */
@@ -253,9 +253,9 @@ test_ip6_route (void)
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_get (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric, &gateway));
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, ifindex, in6addr_any, 0, metric, &gateway));
accept_signal (route_added);
/* Add default route again */
@@ -291,12 +291,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, ifindex, network, plen, metric, &gateway));
+ g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric, &gateway));
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, ifindex, network, plen, metric, &gateway));
free_signal (route_added);
free_signal (route_changed);
@@ -315,8 +315,8 @@ test_ip4_zero_gateway (void)
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, ifindex, nmtst_inet4_from_string ("1.2.3.1"), 32, 0, 0)
+ && nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.2"), 32, 0, 0))
break;
});
diff --git a/src/tests/test-route-manager.c b/src/tests/test-route-manager.c
index b81c263c08..6fa5d72bff 100644
--- a/src/tests/test-route-manager.c
+++ b/src/tests/test-route-manager.c
@@ -791,9 +791,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->rx.ifindex, route->r4.network, route->rx.plen, route->rx.metric, route->r4.gateway);
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->rx.ifindex, route->r6.network, route->rx.plen, route->rx.metric, &route->r6.gateway);
if (!has) {
g_assert (!r);