summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-04-17 07:57:29 +0200
committerThomas Haller <thaller@redhat.com>2019-04-18 11:19:26 +0200
commitbf36fa11d23e667de9bfe97306b4a7d752a4932d (patch)
tree5dcf936c171d2bddf70088580ea8df132d3f530c
parent73e32e43c8ca08adc3500d603eacb9133e40ed3c (diff)
platform: refactor detecting kernel features
Next we will need to detect more kernel features. First refactor the handling of these to require less code changes and be more efficient. A plain nm_platform_kernel_support_get() only reqiures to access an array in the common case. The other important change is that the function no longer requires a NMPlatform instance. This allows us to check kernel support from anywhere. The only thing is that we require kernel support to be initialized before calling this function. That means, an NMPlatform instance must have detected support before. (cherry picked from commit ee269b318ef7f2cedfdb2e62af89fab7218edfba)
-rw-r--r--src/devices/nm-device.c21
-rw-r--r--src/nm-iface-helper.c6
-rw-r--r--src/platform/nm-fake-platform.c4
-rw-r--r--src/platform/nm-linux-platform.c186
-rw-r--r--src/platform/nm-platform.c92
-rw-r--r--src/platform/nm-platform.h49
-rw-r--r--src/platform/tests/monitor.c2
-rw-r--r--src/platform/tests/test-link.c3
8 files changed, 149 insertions, 214 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index d85393eb7a..253740a225 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -1546,8 +1546,7 @@ _set_ip_ifindex (NMDevice *self,
priv->ip_ifindex,
priv->ip_iface);
- if (nm_platform_check_kernel_support (platform,
- NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL))
+ if (nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL))
nm_platform_link_set_user_ipv6ll_enabled (platform, priv->ip_ifindex, TRUE);
if (!nm_platform_link_is_up (platform, priv->ip_ifindex))
@@ -4330,8 +4329,7 @@ realize_start_setup (NMDevice *self,
if (priv->firmware_version)
_notify (self, PROP_FIRMWARE_VERSION);
- if (nm_platform_check_kernel_support (nm_device_get_platform (self),
- NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL))
+ if (nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL))
priv->ipv6ll_handle = nm_platform_link_get_user_ipv6ll_enabled (nm_device_get_platform (self), priv->ifindex);
if (nm_platform_link_supports_sriov (nm_device_get_platform (self), priv->ifindex))
@@ -9234,8 +9232,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
* addresses as /128. The reason for the /128 is to prevent the kernel
* from adding a prefix route for this address. */
ifa_flags = 0;
- if (nm_platform_check_kernel_support (nm_device_get_platform (self),
- NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS)) {
+ if (nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS)) {
ifa_flags |= IFA_F_NOPREFIXROUTE;
if (NM_IN_SET (priv->ndisc_use_tempaddr, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR))
@@ -9267,8 +9264,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
rdata->routes_n,
nm_device_get_route_table (self, AF_INET6, TRUE),
nm_device_get_route_metric (self, AF_INET6),
- nm_platform_check_kernel_support (nm_device_get_platform (self),
- NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF));
+ nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF));
if (priv->ac_ip6_config.current) {
nm_ip6_config_reset_routes_ndisc ((NMIP6Config *) priv->ac_ip6_config.current,
rdata->gateways,
@@ -9277,8 +9273,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
rdata->routes_n,
nm_device_get_route_table (self, AF_INET6, TRUE),
nm_device_get_route_metric (self, AF_INET6),
- nm_platform_check_kernel_support (nm_device_get_platform (self),
- NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF));
+ nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF));
}
}
@@ -9466,8 +9461,7 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
priv->ndisc_use_tempaddr = use_tempaddr;
if ( NM_IN_SET (use_tempaddr, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)
- && !nm_platform_check_kernel_support (nm_device_get_platform (self),
- NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS)) {
+ && !nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS)) {
_LOGW (LOGD_IP6, "The kernel does not support extended IFA_FLAGS needed by NM for "
"IPv6 private addresses. This feature is not available");
}
@@ -9574,8 +9568,7 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable)
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
int ifindex = nm_device_get_ip_ifindex (self);
- if (!nm_platform_check_kernel_support (nm_device_get_platform (self),
- NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL))
+ if (!nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL))
return;
priv->ipv6ll_handle = enable;
diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c
index 1ef9f5aea6..e53b446e3b 100644
--- a/src/nm-iface-helper.c
+++ b/src/nm-iface-helper.c
@@ -186,8 +186,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
* addresses as /128. The reason for the /128 is to prevent the kernel
* from adding a prefix route for this address. */
ifa_flags = 0;
- if (nm_platform_check_kernel_support (NM_PLATFORM_GET,
- NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS)) {
+ if (nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS)) {
ifa_flags |= IFA_F_NOPREFIXROUTE;
if (NM_IN_SET (global_opt.tempaddr, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR))
@@ -212,8 +211,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
rdata->routes_n,
RT_TABLE_MAIN,
global_opt.priority_v6,
- nm_platform_check_kernel_support (NM_PLATFORM_GET,
- NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF));
+ nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF));
}
if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) {
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index 05f9667e97..40a85390b6 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -1401,6 +1401,10 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMPlatformClass *platform_class = NM_PLATFORM_CLASS (klass);
+ NMPlatformKernelSupportType kernel_support;
+
+ for (kernel_support = 0; kernel_support < _NM_PLATFORM_KERNEL_SUPPORT_NUM; kernel_support++)
+ _nm_platform_kernel_support_init (kernel_support, -1);
object_class->finalize = finalize;
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 460b321bf6..0e84f99f4c 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -142,8 +142,6 @@ enum {
#define __IFLA_TUN_MAX 10
#define IFLA_TUN_MAX (__IFLA_TUN_MAX - 1)
-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
@@ -582,119 +580,6 @@ wait_for_nl_response_to_string (WaitForNlResponseResult seq_result,
return buf0;
}
-/*****************************************************************************
- * Support IFLA_INET6_ADDR_GEN_MODE
- *****************************************************************************/
-
-static int _support_user_ipv6ll = 0;
-#define _support_user_ipv6ll_still_undecided() (G_UNLIKELY (_support_user_ipv6ll == 0))
-
-static void
-_support_user_ipv6ll_detect (struct nlattr **tb)
-{
- gboolean supported;
-
- nm_assert (_support_user_ipv6ll_still_undecided ());
-
- /* IFLA_INET6_ADDR_GEN_MODE was added in kernel 3.17, dated 5 October, 2014. */
- supported = !!tb[IFLA_INET6_ADDR_GEN_MODE];
- _support_user_ipv6ll = supported ? 1 : -1;
- _LOG2D ("kernel-support: IFLA_INET6_ADDR_GEN_MODE: %s",
- supported ? "detected" : "not detected");
-}
-
-static gboolean
-_support_user_ipv6ll_get (void)
-{
- if (_support_user_ipv6ll_still_undecided ()) {
- _support_user_ipv6ll = 1;
- _LOG2D ("kernel-support: IFLA_INET6_ADDR_GEN_MODE: %s", "failed to detect; assume support");
- }
- return _support_user_ipv6ll >= 0;
-}
-
-/*****************************************************************************
- * extended IFA_FLAGS support
- *****************************************************************************/
-
-static int _support_kernel_extended_ifa_flags = 0;
-
-#define _support_kernel_extended_ifa_flags_still_undecided() (G_UNLIKELY (_support_kernel_extended_ifa_flags == 0))
-
-static void
-_support_kernel_extended_ifa_flags_detect (struct nl_msg *msg)
-{
- struct nlmsghdr *msg_hdr;
- gboolean support;
-
- nm_assert (_support_kernel_extended_ifa_flags_still_undecided ());
- nm_assert (msg);
-
- msg_hdr = nlmsg_hdr (msg);
-
- nm_assert (msg_hdr && msg_hdr->nlmsg_type == RTM_NEWADDR);
-
- /* IFA_FLAGS is set for IPv4 and IPv6 addresses. It was added first to IPv6,
- * but if we encounter an IPv4 address with IFA_FLAGS, we surely have support. */
- if (!NM_IN_SET (((struct ifaddrmsg *) nlmsg_data (msg_hdr))->ifa_family, AF_INET, AF_INET6))
- return;
-
- /* see if the nl_msg contains the IFA_FLAGS attribute. If it does,
- * we assume, that the kernel supports extended flags, IFA_F_MANAGETEMPADDR
- * and IFA_F_NOPREFIXROUTE for IPv6. They were added together in kernel 3.14,
- * dated 30 March, 2014.
- *
- * For IPv4, IFA_F_NOPREFIXROUTE was added later, but there is no easy
- * way to detect kernel support. */
- support = !!nlmsg_find_attr (msg_hdr, sizeof (struct ifaddrmsg), IFA_FLAGS);
- _support_kernel_extended_ifa_flags = support ? 1 : -1;
- _LOG2D ("kernel-support: extended-ifa-flags: %s", support ? "detected" : "not detected");
-}
-
-static gboolean
-_support_kernel_extended_ifa_flags_get (void)
-{
- if (_support_kernel_extended_ifa_flags_still_undecided ()) {
- _LOG2D ("kernel-support: extended-ifa-flags: %s", "unable to detect kernel support for handling IPv6 temporary addresses. Assume support");
- _support_kernel_extended_ifa_flags = 1;
- }
- 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
******************************************************************/
@@ -1246,8 +1131,11 @@ _parse_af_inet6 (NMPlatform *platform,
/* Hack to detect support addrgenmode of the kernel. We only parse
* netlink messages that we receive from kernel, hence this check
* is valid. */
- if (_support_user_ipv6ll_still_undecided ())
- _support_user_ipv6ll_detect (tb);
+ if (!_nm_platform_kernel_support_detected (NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) {
+ /* IFLA_INET6_ADDR_GEN_MODE was added in kernel 3.17, dated 5 October, 2014. */
+ _nm_platform_kernel_support_init (NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL,
+ tb[IFLA_INET6_ADDR_GEN_MODE] ? 1 : -1);
+ }
if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
i6_addr_gen_mode_inv = _nm_platform_uint8_inv (nla_get_u8 (tb[IFLA_INET6_ADDR_GEN_MODE]));
@@ -3371,9 +3259,13 @@ rta_multipath_done:
obj->ip_route.lock_mtu = NM_FLAGS_HAS (lock, 1 << RTAX_MTU);
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 (!_nm_platform_kernel_support_detected (NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF)) {
+ /* Detect support for RTA_PREF by inspecting the netlink message.
+ * RTA_PREF was added in kernel 4.1, dated 21 June, 2015. */
+ _nm_platform_kernel_support_init (NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF,
+ tb[RTA_PREF] ? 1 : -1);
+ }
if (tb[RTA_PREF])
obj->ip6_route.rt_pref = nla_get_u8 (tb[RTA_PREF]);
@@ -4654,32 +4546,6 @@ sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *pat
/*****************************************************************************/
-static NMPlatformKernelSupportFlags
-check_kernel_support (NMPlatform *platform,
- NMPlatformKernelSupportFlags request_flags)
-{
- NMPlatformKernelSupportFlags response = 0;
-
- nm_assert (NM_IS_LINUX_PLATFORM (platform));
-
- if (NM_FLAGS_HAS (request_flags, NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS)) {
- if (_support_kernel_extended_ifa_flags_get ())
- response |= NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS;
- }
-
- if (NM_FLAGS_HAS (request_flags, NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL)) {
- if (_support_user_ipv6ll_get ())
- 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;
-}
-
static void
process_events (NMPlatform *platform)
{
@@ -5849,9 +5715,27 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
msghdr = nlmsg_hdr (msg);
- if ( _support_kernel_extended_ifa_flags_still_undecided ()
- && msghdr->nlmsg_type == RTM_NEWADDR)
- _support_kernel_extended_ifa_flags_detect (msg);
+ if ( !_nm_platform_kernel_support_detected (NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS)
+ && msghdr->nlmsg_type == RTM_NEWADDR) {
+ /* IFA_FLAGS is set for IPv4 and IPv6 addresses. It was added first to IPv6,
+ * but if we encounter an IPv4 address with IFA_FLAGS, we surely have support. */
+ if ( nlmsg_valid_hdr (msghdr, sizeof (struct ifaddrmsg))
+ && NM_IN_SET (((struct ifaddrmsg *) nlmsg_data (msghdr))->ifa_family,
+ AF_INET,
+ AF_INET6)) {
+ /* see if the nl_msg contains the IFA_FLAGS attribute. If it does,
+ * we assume, that the kernel supports extended flags, IFA_F_MANAGETEMPADDR
+ * and IFA_F_NOPREFIXROUTE for IPv6. They were added together in kernel 3.14,
+ * dated 30 March, 2014.
+ *
+ * For IPv4, IFA_F_NOPREFIXROUTE was added later, but there is no easy
+ * way to detect kernel support. */
+ _nm_platform_kernel_support_init (NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS,
+ !!nlmsg_find_attr (msghdr, sizeof (struct ifaddrmsg), IFA_FLAGS)
+ ? 1
+ : -1);
+ }
+ }
if (!handle_events)
return;
@@ -6441,7 +6325,7 @@ link_set_user_ipv6ll_enabled (NMPlatform *platform, int ifindex, gboolean enable
ifindex,
nm_platform_link_inet6_addrgenmode2str (mode, NULL, 0));
- if (!_support_user_ipv6ll_get ()) {
+ if (!nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) {
_LOGD ("link: change %d: user-ipv6ll: not supported", ifindex);
return -NME_PL_OPNOTSUPP;
}
@@ -9085,8 +8969,6 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->qdisc_add = qdisc_add;
platform_class->tfilter_add = tfilter_add;
- platform_class->check_kernel_support = check_kernel_support;
-
platform_class->process_events = process_events;
}
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 53ad78caf0..88f2b0decf 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -119,9 +119,6 @@ typedef struct _NMPlatformPrivate {
bool use_udev:1;
bool log_with_ptr:1;
- NMPlatformKernelSupportFlags support_checked;
- NMPlatformKernelSupportFlags support_present;
-
guint ip4_dev_route_blacklist_check_id;
guint ip4_dev_route_blacklist_gc_timeout_id;
GHashTable *ip4_dev_route_blacklist_hash;
@@ -277,40 +274,79 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_nmp_nlm_flag_to_string_lookup, NMPNlmFlags,
/*****************************************************************************/
-NMPlatformKernelSupportFlags
-nm_platform_check_kernel_support (NMPlatform *self,
- NMPlatformKernelSupportFlags request_flags)
+volatile int _nm_platform_kernel_support_state[_NM_PLATFORM_KERNEL_SUPPORT_NUM] = { };
+
+static const struct {
+ bool compile_time_default;
+ const char *name;
+ const char *desc;
+} _nm_platform_kernel_support_info[_NM_PLATFORM_KERNEL_SUPPORT_NUM] = {
+ [NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS] = {
+ .compile_time_default = TRUE,
+ .name = "EXTENDED_IFA_FLAGS",
+ .desc = "IPv6 temporary addresses support",
+ },
+ [NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL] = {
+ .compile_time_default = TRUE,
+ .name = "USER_IPV6LL",
+ .desc = "IFLA_INET6_ADDR_GEN_MODE support",
+ },
+ [NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF] = {
+ .compile_time_default = (RTA_MAX >= 20 /* RTA_PREF */),
+ .name = "RTA_PREF",
+ .desc = "ability to set router preference for IPv6 routes",
+ },
+};
+
+int
+_nm_platform_kernel_support_init (NMPlatformKernelSupportType type,
+ int value)
{
- NMPlatformPrivate *priv;
+ volatile int *p_state;
+ gboolean set_default = FALSE;
- _CHECK_SELF (self, klass, TRUE);
+ nm_assert (_NM_INT_NOT_NEGATIVE (type) && type < G_N_ELEMENTS (_nm_platform_kernel_support_state));
- priv = NM_PLATFORM_GET_PRIVATE (self);
+ p_state = &_nm_platform_kernel_support_state[type];
- /* we cache the response from subclasses and only request it once.
- * This probably gives better performance, but more importantly,
- * we are guaranteed that the answer for a certain request_flag
- * is always the same. */
- if (G_UNLIKELY (!NM_FLAGS_ALL (priv->support_checked, request_flags))) {
- NMPlatformKernelSupportFlags checked, response;
+ if (value == 0) {
+ set_default = TRUE;
+ value = _nm_platform_kernel_support_info[type].compile_time_default
+ ? 1
+ : -1;
+ }
- checked = request_flags & ~priv->support_checked;
- nm_assert (checked);
+ nm_assert (NM_IN_SET (value, -1, 1));
- if (klass->check_kernel_support)
- response = klass->check_kernel_support (self, checked);
- else {
- /* fake platform. Pretend no support for anything. */
- response = 0;
- }
+ if (!g_atomic_int_compare_and_exchange (p_state, 0, value)) {
+ value = g_atomic_int_get (p_state);
+ nm_assert (NM_IN_SET (value, -1, 1));
+ return value;
+ }
+
+#undef NM_THREAD_SAFE_ON_MAIN_THREAD
+#define NM_THREAD_SAFE_ON_MAIN_THREAD 0
- priv->support_checked |= checked;
- priv->support_present = (priv->support_present & ~checked) | (response & checked);
+ if (set_default) {
+ nm_log_dbg (LOGD_PLATFORM, "platform: kernel-support for %s (%s) not detected: assume %ssupported",
+ _nm_platform_kernel_support_info[type].name,
+ _nm_platform_kernel_support_info[type].desc,
+ value >= 0 ? "" : "not ");
+ } else {
+ nm_log_dbg (LOGD_PLATFORM, "platform: kernel-support for %s (%s) detected: %ssupported",
+ _nm_platform_kernel_support_info[type].name,
+ _nm_platform_kernel_support_info[type].desc,
+ value >= 0 ? "" : "not ");
}
- return priv->support_present & request_flags;
+#undef NM_THREAD_SAFE_ON_MAIN_THREAD
+#define NM_THREAD_SAFE_ON_MAIN_THREAD 1
+
+ return value;
}
+/*****************************************************************************/
+
/**
* nm_platform_process_events:
* @self: platform instance
@@ -3912,7 +3948,7 @@ nm_platform_ip4_address_sync (NMPlatform *self,
if (!known_addresses)
return TRUE;
- ifa_flags = nm_platform_check_kernel_support (self, NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS)
+ ifa_flags = nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS)
? IFA_F_NOPREFIXROUTE
: 0;
@@ -4112,7 +4148,7 @@ next_plat:
if (!known_addresses)
return TRUE;
- ifa_flags = nm_platform_check_kernel_support (self, NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS)
+ ifa_flags = nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS)
? IFA_F_NOPREFIXROUTE
: 0;
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index fa8200e68b..d5a7a2d182 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -819,12 +819,6 @@ typedef enum {
} NMPlatformLinkDuplexType;
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;
-
-typedef enum {
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE = 0,
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS = (1LL << 0),
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY = (1LL << 1),
@@ -850,6 +844,43 @@ typedef enum {
/*****************************************************************************/
+typedef enum {
+ NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS,
+ NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL,
+ NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF,
+ _NM_PLATFORM_KERNEL_SUPPORT_NUM,
+} NMPlatformKernelSupportType;
+
+extern volatile int _nm_platform_kernel_support_state[_NM_PLATFORM_KERNEL_SUPPORT_NUM];
+
+int _nm_platform_kernel_support_init (NMPlatformKernelSupportType type,
+ int value);
+
+#define _nm_platform_kernel_support_detected(type) \
+ G_LIKELY (({ \
+ const NMPlatformKernelSupportType _type = (type); \
+ \
+ nm_assert (_NM_INT_NOT_NEGATIVE (_type) && _type < G_N_ELEMENTS (_nm_platform_kernel_support_state)); \
+ \
+ (_nm_platform_kernel_support_state[_type] != 0); \
+ }))
+
+#define nm_platform_kernel_support_get(type) \
+ ({ \
+ const NMPlatformKernelSupportType _type = (type); \
+ int _v; \
+ \
+ nm_assert (_NM_INT_NOT_NEGATIVE (_type) && _type < G_N_ELEMENTS (_nm_platform_kernel_support_state)); \
+ \
+ _v = _nm_platform_kernel_support_state[_type]; \
+ if (G_UNLIKELY (_v == 0)) \
+ _v = _nm_platform_kernel_support_init (_type, 0); \
+ \
+ (_v >= 0); \
+ })
+
+/*****************************************************************************/
+
struct _NMPlatformPrivate;
struct _NMPlatform {
@@ -1054,9 +1085,6 @@ typedef struct {
int (*tfilter_add) (NMPlatform *self,
NMPNlmFlags flags,
const NMPlatformTfilter *tfilter);
-
- NMPlatformKernelSupportFlags (*check_kernel_support) (NMPlatform * self,
- NMPlatformKernelSupportFlags request_flags);
} NMPlatformClass;
/* NMPlatform signals
@@ -1668,9 +1696,6 @@ void nm_platform_lnk_wireguard_hash_update (const NMPlatformLnkWireGuard *obj, N
void nm_platform_qdisc_hash_update (const NMPlatformQdisc *obj, NMHashState *h);
void nm_platform_tfilter_hash_update (const NMPlatformTfilter *obj, NMHashState *h);
-NMPlatformKernelSupportFlags nm_platform_check_kernel_support (NMPlatform *self,
- NMPlatformKernelSupportFlags request_flags);
-
const char *nm_platform_link_flags2str (unsigned flags, char *buf, gsize len);
const char *nm_platform_link_inet6_addrgenmode2str (guint8 mode, char *buf, gsize len);
const char *nm_platform_addr_flags2str (unsigned flags, char *buf, gsize len);
diff --git a/src/platform/tests/monitor.c b/src/platform/tests/monitor.c
index f0e3e6cfd0..fff5967be9 100644
--- a/src/platform/tests/monitor.c
+++ b/src/platform/tests/monitor.c
@@ -77,8 +77,6 @@ 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);
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index 03999fede3..eb41813b2f 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -521,8 +521,7 @@ test_bridge_addr (void)
plink = nm_platform_link_get (NM_PLATFORM_GET, link.ifindex);
g_assert (plink);
- if (nm_platform_check_kernel_support (NM_PLATFORM_GET,
- NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL)) {
+ if (nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) {
g_assert (!nm_platform_link_get_user_ipv6ll_enabled (NM_PLATFORM_GET, link.ifindex));
g_assert_cmpint (_nm_platform_uint8_inv (plink->inet6_addr_gen_mode_inv), ==, NM_IN6_ADDR_GEN_MODE_EUI64);