summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/platform/nm-linux-platform.c53
-rw-r--r--src/platform/nm-platform.h1
-rw-r--r--src/platform/tests/monitor.c2
3 files changed, 53 insertions, 3 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index f53019df34..3b37ca539e 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -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;
}
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 845d79b140..ee08a40f4e 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -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;
/*****************************************************************************/
diff --git a/src/platform/tests/monitor.c b/src/platform/tests/monitor.c
index d0c58aebb0..e122005273 100644
--- a/src/platform/tests/monitor.c
+++ b/src/platform/tests/monitor.c
@@ -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);