platform: add support for some route options

Add support for new route options: window, cwnd, initcwnd, initrwnd,
mtu (and their related *-lock flag), tos and src (RTA_SRC).
This commit is contained in:
Beniamino Galvani 2017-02-15 14:00:44 +01:00
parent 63951cad7f
commit 45dc2feded
4 changed files with 352 additions and 26 deletions

View file

@ -1833,6 +1833,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
NMIPAddr gateway;
} nh;
guint32 mss;
guint32 window = 0, cwnd = 0, initcwnd = 0, initrwnd = 0, mtu = 0, lock = 0;
guint32 table;
if (!nlmsg_valid_hdr (nlh, sizeof (*rtm)))
@ -1846,8 +1847,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
if (!NM_IN_SET (rtm->rtm_family, AF_INET, AF_INET6))
goto errout;
if ( rtm->rtm_type != RTN_UNICAST
|| rtm->rtm_tos != 0)
if (rtm->rtm_type != RTN_UNICAST)
goto errout;
err = nlmsg_parse (nlh, sizeof (struct rtmsg), tb, RTA_MAX, policy);
@ -1941,21 +1941,34 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
mss = 0;
if (tb[RTA_METRICS]) {
struct nlattr *mtb[RTAX_MAX + 1];
int i;
static struct nla_policy rtax_policy[RTAX_MAX + 1] = {
[RTAX_LOCK] = { .type = NLA_U32 },
[RTAX_ADVMSS] = { .type = NLA_U32 },
[RTAX_WINDOW] = { .type = NLA_U32 },
[RTAX_CWND] = { .type = NLA_U32 },
[RTAX_INITCWND] = { .type = NLA_U32 },
[RTAX_INITRWND] = { .type = NLA_U32 },
[RTAX_MTU] = { .type = NLA_U32 },
};
err = nla_parse_nested(mtb, RTAX_MAX, tb[RTA_METRICS], NULL);
err = nla_parse_nested (mtb, RTAX_MAX, tb[RTA_METRICS], rtax_policy);
if (err < 0)
goto errout;
for (i = 1; i <= RTAX_MAX; i++) {
if (mtb[i]) {
if (i == RTAX_ADVMSS) {
if (nla_len (mtb[i]) >= sizeof (uint32_t))
mss = nla_get_u32(mtb[i]);
break;
}
}
}
if (mtb[RTAX_LOCK])
lock = nla_get_u32 (mtb[RTAX_LOCK]);
if (mtb[RTAX_ADVMSS])
mss = nla_get_u32 (mtb[RTAX_ADVMSS]);
if (mtb[RTAX_WINDOW])
window = nla_get_u32 (mtb[RTAX_WINDOW]);
if (mtb[RTAX_CWND])
cwnd = nla_get_u32 (mtb[RTAX_CWND]);
if (mtb[RTAX_INITCWND])
initcwnd = nla_get_u32 (mtb[RTAX_INITCWND]);
if (mtb[RTAX_INITRWND])
initrwnd = nla_get_u32 (mtb[RTAX_INITRWND]);
if (mtb[RTAX_MTU])
mtu = nla_get_u32 (mtb[RTAX_MTU]);
}
/*****************************************************************/
@ -1987,7 +2000,24 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
memcpy (&obj->ip6_route.pref_src, nla_data (tb[RTA_PREFSRC]), addr_len);
}
if (!is_v4 && tb[RTA_SRC]) {
_check_addr_or_errout (tb, RTA_SRC, addr_len);
memcpy (&obj->ip6_route.src, nla_data (tb[RTA_SRC]), addr_len);
obj->ip6_route.src_plen = rtm->rtm_src_len;
}
obj->ip_route.mss = mss;
obj->ip_route.window = window;
obj->ip_route.cwnd = cwnd;
obj->ip_route.initcwnd = initcwnd;
obj->ip_route.initrwnd = initrwnd;
obj->ip_route.mtu = mtu;
obj->ip_route.tos = rtm->rtm_tos;
obj->ip_route.lock_window = NM_FLAGS_HAS (lock, 1 << RTAX_WINDOW);
obj->ip_route.lock_cwnd = NM_FLAGS_HAS (lock, 1 << RTAX_CWND);
obj->ip_route.lock_initcwnd = NM_FLAGS_HAS (lock, 1 << RTAX_INITCWND);
obj->ip_route.lock_initrwnd = NM_FLAGS_HAS (lock, 1 << RTAX_INITRWND);
obj->ip_route.lock_mtu = NM_FLAGS_HAS (lock, 1 << RTAX_MTU);
if (NM_FLAGS_HAS (rtm->rtm_flags, RTM_F_CLONED)) {
/* we must not straight way reject cloned routes, because we might have cached
@ -2362,19 +2392,28 @@ _nl_msg_new_route (int nlmsg_type,
gconstpointer gateway,
guint32 metric,
guint32 mss,
gconstpointer pref_src)
gconstpointer pref_src,
gconstpointer src,
guint8 src_plen,
guint8 tos,
guint32 window,
guint32 cwnd,
guint32 initcwnd,
guint32 initrwnd,
guint32 mtu,
guint32 lock)
{
struct nl_msg *msg;
struct rtmsg rtmsg = {
.rtm_family = family,
.rtm_tos = 0,
.rtm_tos = tos,
.rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */
.rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (source),
.rtm_scope = scope,
.rtm_type = RTN_UNICAST,
.rtm_flags = 0,
.rtm_dst_len = plen,
.rtm_src_len = 0,
.rtm_src_len = src ? src_plen : 0,
};
NMIPAddr network_clean;
@ -2396,19 +2435,35 @@ _nl_msg_new_route (int nlmsg_type,
nm_utils_ipx_address_clear_host_address (family, &network_clean, network, plen);
NLA_PUT (msg, RTA_DST, addr_len, &network_clean);
if (src)
NLA_PUT (msg, RTA_SRC, addr_len, src);
NLA_PUT_U32 (msg, RTA_PRIORITY, metric);
if (pref_src)
NLA_PUT (msg, RTA_PREFSRC, addr_len, pref_src);
if (mss > 0) {
if (mss || window || cwnd || initcwnd || initrwnd || mtu || lock) {
struct nlattr *metrics;
metrics = nla_nest_start (msg, RTA_METRICS);
if (!metrics)
goto nla_put_failure;
NLA_PUT_U32 (msg, RTAX_ADVMSS, mss);
if (mss)
NLA_PUT_U32 (msg, RTAX_ADVMSS, mss);
if (window)
NLA_PUT_U32 (msg, RTAX_WINDOW, window);
if (cwnd)
NLA_PUT_U32 (msg, RTAX_CWND, cwnd);
if (initcwnd)
NLA_PUT_U32 (msg, RTAX_INITCWND, initcwnd);
if (initrwnd)
NLA_PUT_U32 (msg, RTAX_INITRWND, initrwnd);
if (mtu)
NLA_PUT_U32 (msg, RTAX_MTU, mtu);
if (lock)
NLA_PUT_U32 (msg, RTAX_LOCK, lock);
nla_nest_end(msg, metrics);
}
@ -5903,6 +5958,16 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags fl
return ipx_route_get_all (platform, ifindex, NMP_OBJECT_TYPE_IP6_ROUTE, flags);
}
static guint32
ip_route_get_lock_flag (NMPlatformIPRoute *route)
{
return (((guint32) route->lock_window) << RTAX_WINDOW)
| (((guint32) route->lock_cwnd) << RTAX_CWND)
| (((guint32) route->lock_initcwnd) << RTAX_INITCWND)
| (((guint32) route->lock_initrwnd) << RTAX_INITRWND)
| (((guint32) route->lock_mtu) << RTAX_MTU);
}
static gboolean
ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route)
{
@ -5924,7 +5989,16 @@ ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route)
&route->gateway,
route->metric,
route->mss,
route->pref_src ? &route->pref_src : NULL);
route->pref_src ? &route->pref_src : NULL,
NULL,
0,
route->tos,
route->window,
route->cwnd,
route->initcwnd,
route->initrwnd,
route->mtu,
ip_route_get_lock_flag ((NMPlatformIPRoute *) route));
nmp_object_stackinit_id_ip4_route (&obj_id, route->ifindex, network, route->plen, route->metric);
return do_add_addrroute (platform, &obj_id, nlmsg);
@ -5951,7 +6025,16 @@ ip6_route_add (NMPlatform *platform, const NMPlatformIP6Route *route)
&route->gateway,
route->metric,
route->mss,
!IN6_IS_ADDR_UNSPECIFIED (&route->pref_src) ? &route->pref_src : NULL);
!IN6_IS_ADDR_UNSPECIFIED (&route->pref_src) ? &route->pref_src : NULL,
!IN6_IS_ADDR_UNSPECIFIED (&route->src) ? &route->src : NULL,
route->src_plen,
route->tos,
route->window,
route->cwnd,
route->initcwnd,
route->initrwnd,
route->mtu,
ip_route_get_lock_flag ((NMPlatformIPRoute *) route));
nmp_object_stackinit_id_ip6_route (&obj_id, route->ifindex, &network, route->plen, route->metric);
return do_add_addrroute (platform, &obj_id, nlmsg);
@ -6006,7 +6089,16 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 p
NULL,
metric,
0,
NULL);
NULL,
NULL,
0,
0,
0,
0,
0,
0,
0,
0);
if (!nlmsg)
return FALSE;
@ -6032,7 +6124,16 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, gu
NULL,
metric,
0,
NULL);
NULL,
NULL,
0,
0,
0,
0,
0,
0,
0,
0);
if (!nlmsg)
return FALSE;

View file

@ -3865,6 +3865,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
char s_pref_src[INET_ADDRSTRLEN];
char str_dev[TO_STRING_DEV_BUF_SIZE];
char str_scope[30], s_source[50];
char str_tos[32], str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32];
if (!nm_utils_to_string_buffer_init_null (route, &buf, &len))
return buf;
@ -3874,16 +3875,35 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
_to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev));
if (route->tos)
nm_sprintf_buf (str_tos, " tos 0x%x", (unsigned) route->tos);
if (route->window)
nm_sprintf_buf (str_window, " window %s%"G_GUINT32_FORMAT, route->lock_window ? "lock " : "", route->window);
if (route->cwnd)
nm_sprintf_buf (str_cwnd, " cwnd %s%"G_GUINT32_FORMAT, route->lock_cwnd ? "lock " : "", route->cwnd);
if (route->initcwnd)
nm_sprintf_buf (str_initcwnd, " initcwnd %s%"G_GUINT32_FORMAT, route->lock_initcwnd ? "lock " : "", route->initcwnd);
if (route->initrwnd)
nm_sprintf_buf (str_initrwnd, " initrwnd %s%"G_GUINT32_FORMAT, route->lock_initrwnd ? "lock " : "", route->initrwnd);
if (route->mtu)
nm_sprintf_buf (str_mtu, " mtu %s%"G_GUINT32_FORMAT, route->lock_mtu ? "lock " : "", route->mtu);
g_snprintf (buf, len,
"%s/%d"
" via %s"
"%s"
" metric %"G_GUINT32_FORMAT
" mss %"G_GUINT32_FORMAT
" src %s" /* source */
" rt-src %s" /* protocol */
"%s" /* cloned */
"%s%s" /* scope */
"%s%s" /* pref-src */
"%s" /* tos */
"%s" /* window */
"%s" /* cwnd */
"%s" /* initcwnd */
"%s" /* initrwnd */
"%s" /* mtu */
"",
s_network,
route->plen,
@ -3896,7 +3916,13 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
route->scope_inv ? " scope " : "",
route->scope_inv ? (nm_platform_route_scope2str (nm_platform_route_scope_inv (route->scope_inv), str_scope, sizeof (str_scope))) : "",
route->pref_src ? " pref-src " : "",
route->pref_src ? inet_ntop (AF_INET, &route->pref_src, s_pref_src, sizeof(s_pref_src)) : "");
route->pref_src ? inet_ntop (AF_INET, &route->pref_src, s_pref_src, sizeof(s_pref_src)) : "",
route->tos ? str_tos : "",
route->window ? str_window : "",
route->cwnd ? str_cwnd : "",
route->initcwnd ? str_initcwnd : "",
route->initrwnd ? str_initrwnd : "",
route->mtu ? str_mtu : "");
return buf;
}
@ -3916,13 +3942,16 @@ const char *
nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsize len)
{
char s_network[INET6_ADDRSTRLEN], s_gateway[INET6_ADDRSTRLEN], s_pref_src[INET6_ADDRSTRLEN];
char s_src[INET6_ADDRSTRLEN];
char str_dev[TO_STRING_DEV_BUF_SIZE], s_source[50];
char str_tos[32], str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32];
if (!nm_utils_to_string_buffer_init_null (route, &buf, &len))
return buf;
inet_ntop (AF_INET6, &route->network, s_network, sizeof (s_network));
inet_ntop (AF_INET6, &route->gateway, s_gateway, sizeof (s_gateway));
inet_ntop (AF_INET6, &route->src, s_src, sizeof (s_src));
if (IN6_IS_ADDR_UNSPECIFIED (&route->pref_src))
s_pref_src[0] = 0;
@ -3931,15 +3960,35 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
_to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev));
if (route->tos)
nm_sprintf_buf (str_tos, " tos 0x%x", (unsigned) route->tos);
if (route->window)
nm_sprintf_buf (str_window, " window %s%"G_GUINT32_FORMAT, route->lock_window ? "lock " : "", route->window);
if (route->cwnd)
nm_sprintf_buf (str_cwnd, " cwnd %s%"G_GUINT32_FORMAT, route->lock_cwnd ? "lock " : "", route->cwnd);
if (route->initcwnd)
nm_sprintf_buf (str_initcwnd, " initcwnd %s%"G_GUINT32_FORMAT, route->lock_initcwnd ? "lock " : "", route->initcwnd);
if (route->initrwnd)
nm_sprintf_buf (str_initrwnd, " initrwnd %s%"G_GUINT32_FORMAT, route->lock_initrwnd ? "lock " : "", route->initrwnd);
if (route->mtu)
nm_sprintf_buf (str_mtu, " mtu %s%"G_GUINT32_FORMAT, route->lock_mtu ? "lock " : "", route->mtu);
g_snprintf (buf, len,
"%s/%d"
" via %s"
"%s"
" metric %"G_GUINT32_FORMAT
" mss %"G_GUINT32_FORMAT
" src %s" /* source */
" rt-src %s" /* protocol */
" src %s/%u" /* source */
"%s" /* cloned */
"%s%s" /* pref-src */
"%s" /* tos */
"%s" /* window */
"%s" /* cwnd */
"%s" /* initcwnd */
"%s" /* initrwnd */
"%s" /* mtu */
"",
s_network,
route->plen,
@ -3948,9 +3997,17 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
route->metric,
route->mss,
nmp_utils_ip_config_source_to_string (route->rt_source, s_source, sizeof (s_source)),
s_src, route->src_plen,
route->rt_cloned ? " cloned" : "",
s_pref_src[0] ? " pref-src " : "",
s_pref_src[0] ? s_pref_src : "");
s_pref_src[0] ? s_pref_src : "",
route->tos ? str_tos : "",
route->window ? str_window : "",
route->cwnd ? str_cwnd : "",
route->initcwnd ? str_initcwnd : "",
route->initrwnd ? str_initrwnd : "",
route->mtu ? str_mtu : "");
return buf;
}
@ -4239,6 +4296,17 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
_CMP_FIELD (a, b, scope_inv);
_CMP_FIELD (a, b, pref_src);
_CMP_FIELD (a, b, rt_cloned);
_CMP_FIELD (a, b, tos);
_CMP_FIELD (a, b, lock_window);
_CMP_FIELD (a, b, lock_cwnd);
_CMP_FIELD (a, b, lock_initcwnd);
_CMP_FIELD (a, b, lock_initrwnd);
_CMP_FIELD (a, b, lock_mtu);
_CMP_FIELD (a, b, window);
_CMP_FIELD (a, b, cwnd);
_CMP_FIELD (a, b, initcwnd);
_CMP_FIELD (a, b, initrwnd);
_CMP_FIELD (a, b, mtu);
return 0;
}
@ -4252,9 +4320,22 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
_CMP_FIELD (a, b, metric);
_CMP_FIELD_MEMCMP (a, b, gateway);
_CMP_FIELD_MEMCMP (a, b, pref_src);
_CMP_FIELD_MEMCMP (a, b, src);
_CMP_FIELD (a, b, src_plen);
_CMP_FIELD (a, b, rt_source);
_CMP_FIELD (a, b, mss);
_CMP_FIELD (a, b, rt_cloned);
_CMP_FIELD (a, b, tos);
_CMP_FIELD (a, b, lock_window);
_CMP_FIELD (a, b, lock_cwnd);
_CMP_FIELD (a, b, lock_initcwnd);
_CMP_FIELD (a, b, lock_initrwnd);
_CMP_FIELD (a, b, lock_mtu);
_CMP_FIELD (a, b, window);
_CMP_FIELD (a, b, cwnd);
_CMP_FIELD (a, b, initcwnd);
_CMP_FIELD (a, b, initrwnd);
_CMP_FIELD (a, b, mtu);
return 0;
}

View file

@ -324,9 +324,20 @@ typedef union {
* of platform users. This flag is internal to track those hidden
* routes. Such a route is not alive, according to nmp_object_is_alive(). */ \
bool rt_cloned:1; \
bool lock_window:1; \
bool lock_cwnd:1; \
bool lock_initcwnd:1; \
bool lock_initrwnd:1; \
bool lock_mtu:1; \
\
guint32 metric; \
guint32 mss; \
guint32 tos; \
guint32 window; \
guint32 cwnd; \
guint32 initcwnd; \
guint32 initrwnd; \
guint32 mtu; \
;
typedef struct {
@ -359,6 +370,8 @@ struct _NMPlatformIP6Route {
struct in6_addr network;
struct in6_addr gateway;
struct in6_addr pref_src;
struct in6_addr src;
guint8 src_plen;
};
typedef union {

View file

@ -222,6 +222,14 @@ test_ip4_route (void)
/* Remove route again */
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
/* Remove default route */
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, 0, 0, metric));
accept_signal (route_removed);
/* Remove route to gateway */
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, gateway, 32, metric));
accept_signal (route_removed);
free_signal (route_added);
free_signal (route_changed);
free_signal (route_removed);
@ -314,6 +322,14 @@ test_ip6_route (void)
/* Remove route again */
g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
/* Remove default route */
g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric));
accept_signal (route_removed);
/* Remove route to gateway */
g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, gateway, 128, metric));
accept_signal (route_removed);
free_signal (route_added);
free_signal (route_changed);
free_signal (route_removed);
@ -342,6 +358,119 @@ test_ip4_zero_gateway (void)
nm_platform_process_events (NM_PLATFORM_GET);
}
static void
test_ip4_route_options (void)
{
int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
NMPlatformIP4Route route = { };
in_addr_t network;
GArray *routes;
NMPlatformIP4Route rts[1];
inet_pton (AF_INET, "172.16.1.0", &network);
route.ifindex = ifindex;
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
route.network = network;
route.plen = 24;
route.metric = 20;
route.tos = 0x28;
route.window = 10000;
route.cwnd = 16;
route.initcwnd = 30;
route.initrwnd = 50;
route.mtu = 1350;
route.lock_cwnd = TRUE;
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, &route));
/* Test route listing */
routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex,
NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT |
NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
memset (rts, 0, sizeof (rts));
rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
rts[0].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK);
rts[0].network = network;
rts[0].plen = 24;
rts[0].ifindex = ifindex;
rts[0].metric = 20;
rts[0].tos = 0x28;
rts[0].window = 10000;
rts[0].cwnd = 16;
rts[0].initcwnd = 30;
rts[0].initrwnd = 50;
rts[0].mtu = 1350;
rts[0].lock_cwnd = TRUE;
g_assert_cmpint (routes->len, ==, 1);
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, rts, routes->len, TRUE);
/* Remove route */
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, 24, 20));
g_array_unref (routes);
}
static void
test_ip6_route_options (void)
{
int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
NMPlatformIP6Route route = { };
struct in6_addr network, src;
GArray *routes;
NMPlatformIP6Route rts[3];
inet_pton (AF_INET6, "2001:db8:a:b:0:0:0:0", &network);
inet_pton (AF_INET6, "2001:db8:e:0:0:0:0:0", &src);
route.ifindex = ifindex;
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
route.network = network;
route.plen = 64;
route.gateway = in6addr_any;
route.src = src;
route.src_plen = 48;
route.metric = 1024;
route.window = 20000;
route.cwnd = 8;
route.initcwnd = 22;
route.initrwnd = 33;
route.mtu = 1300;
route.lock_mtu = TRUE;
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, &route));
/* Test route listing */
routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex,
NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT |
NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
memset (rts, 0, sizeof (rts));
rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
rts[0].network = network;
rts[0].plen = 64;
rts[0].ifindex = ifindex;
rts[0].gateway = in6addr_any;
rts[0].src = src;
rts[0].src_plen = 48;
rts[0].metric = 1024;
rts[0].window = 20000;
rts[0].cwnd = 8;
rts[0].initcwnd = 22;
rts[0].initrwnd = 33;
rts[0].mtu = 1300;
rts[0].lock_mtu = TRUE;
g_assert_cmpint (routes->len, ==, 1);
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, rts, routes->len, TRUE);
/* Remove route */
g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, 64, 1024));
g_array_unref (routes);
}
/*****************************************************************************/
NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP;
@ -368,6 +497,8 @@ _nmtstp_setup_tests (void)
g_test_add_func ("/route/ip4", test_ip4_route);
g_test_add_func ("/route/ip6", test_ip6_route);
g_test_add_func ("/route/ip4_metric0", test_ip4_route_metric0);
g_test_add_func ("/route/ip4_options", test_ip4_route_options);
g_test_add_func ("/route/ip6_options", test_ip6_route_options);
if (nmtstp_is_root_test ())
g_test_add_func ("/route/ip4_zero_gateway", test_ip4_zero_gateway);