platform: detect kernel support for RTA_PREF to set router preference of IPv6 routes

This commit is contained in:
Thomas Haller 2017-10-11 09:15:04 +02:00
parent 37ffc8bae9
commit 0a972a4667
3 changed files with 53 additions and 3 deletions

View file

@ -104,6 +104,9 @@
#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
#endif
static const gboolean RTA_PREF_SUPPORTED_AT_COMPILETIME = (RTA_MAX >= 20 /* RTA_PREF */);
G_STATIC_ASSERT (RTA_MAX == (__RTA_MAX - 1));
#define RTA_PREF 20
#undef RTA_MAX
@ -384,6 +387,40 @@ _support_kernel_extended_ifa_flags_get (void)
return _support_kernel_extended_ifa_flags >= 0;
}
/*****************************************************************************
* Support RTA_PREF
*****************************************************************************/
static int _support_rta_pref = 0;
#define _support_rta_pref_still_undecided() (G_UNLIKELY (_support_rta_pref == 0))
static void
_support_rta_pref_detect (struct nlattr **tb)
{
gboolean supported;
nm_assert (_support_rta_pref_still_undecided ());
/* RTA_PREF was added in kernel 4.1, dated 21 June, 2015. */
supported = !!tb[RTA_PREF];
_support_rta_pref = supported ? 1 : -1;
_LOG2D ("kernel-support: RTA_PREF: ability to set router preference for IPv6 routes: %s",
supported ? "detected" : "not detected");
}
static gboolean
_support_rta_pref_get (void)
{
if (_support_rta_pref_still_undecided ()) {
/* if we couldn't detect support, we fallback on compile-time check, whether
* RTA_PREF is present in the kernel headers. */
_support_rta_pref = RTA_PREF_SUPPORTED_AT_COMPILETIME ? 1 : -1;
_LOG2D ("kernel-support: RTA_PREF: ability to set router preference for IPv6 routes: %s",
RTA_PREF_SUPPORTED_AT_COMPILETIME ? "assume support" : "assume no support");
}
return _support_rta_pref >= 0;
}
/******************************************************************
* Various utilities
******************************************************************/
@ -2230,9 +2267,14 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
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 ( !is_v4
&& tb[RTA_PREF])
obj->ip6_route.rt_pref = nla_get_u8 (tb[RTA_PREF]);
if (!is_v4) {
/* Detect support for RTA_PREF by inspecting the netlink message. */
if (_support_rta_pref_still_undecided ())
_support_rta_pref_detect (tb);
if (tb[RTA_PREF])
obj->ip6_route.rt_pref = nla_get_u8 (tb[RTA_PREF]);
}
if (NM_FLAGS_HAS (rtm->rtm_flags, RTM_F_CLONED)) {
/* we must not straight way reject cloned routes, because we might have cached
@ -3106,6 +3148,11 @@ check_kernel_support (NMPlatform *platform,
response |= NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL;
}
if (NM_FLAGS_HAS (request_flags, NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF)) {
if (_support_rta_pref_get ())
response |= NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF;
}
return response;
}

View file

@ -668,6 +668,7 @@ typedef enum {
typedef enum {
NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS = (1LL << 0),
NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL = (1LL << 1),
NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF = (1LL << 2),
} NMPlatformKernelSupportFlags;
/*****************************************************************************/

View file

@ -78,6 +78,8 @@ main (int argc, char **argv)
nm_linux_platform_setup ();
nm_platform_check_kernel_support (NM_PLATFORM_GET, ~((NMPlatformKernelSupportFlags) 0));
if (global_opt.persist)
g_main_loop_run (loop);