diff options
-rw-r--r-- | src/platform/nm-linux-platform.c | 53 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 1 | ||||
-rw-r--r-- | src/platform/tests/monitor.c | 2 |
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); |