summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-10-11 09:15:04 +0200
committerThomas Haller <thaller@redhat.com>2017-10-12 10:38:19 +0200
commit0a972a46671aca0cbae29f88dc033172ec76c72a (patch)
treef099d600eb9d0b186b599a450fc8d94b8af80069 /src
parent37ffc8bae9688a2a6fb98c118e194f17267cff96 (diff)
downloadNetworkManager-0a972a46671aca0cbae29f88dc033172ec76c72a.tar.gz
platform: detect kernel support for RTA_PREF to set router preference of IPv6 routes
Diffstat (limited to 'src')
-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);