summaryrefslogtreecommitdiff
path: root/src/platform/tests
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 /src/platform/tests
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.
Diffstat (limited to 'src/platform/tests')
-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
5 files changed, 792 insertions, 112 deletions
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;
});