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 ee269b318e)
This commit is contained in:
Thomas Haller
2019-04-17 07:57:29 +02:00
parent 73e32e43c8
commit bf36fa11d2
8 changed files with 152 additions and 217 deletions

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
checked = request_flags & ~priv->support_checked;
nm_assert (checked);
if (klass->check_kernel_support)
response = klass->check_kernel_support (self, checked);
else {
/* fake platform. Pretend no support for anything. */
response = 0;
if (value == 0) {
set_default = TRUE;
value = _nm_platform_kernel_support_info[type].compile_time_default
? 1
: -1;
}
priv->support_checked |= checked;
priv->support_present = (priv->support_present & ~checked) | (response & checked);
nm_assert (NM_IN_SET (value, -1, 1));
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;
}
return priv->support_present & request_flags;
#undef NM_THREAD_SAFE_ON_MAIN_THREAD
#define NM_THREAD_SAFE_ON_MAIN_THREAD 0
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 ");
}
#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;

View File

@@ -818,12 +818,6 @@ typedef enum {
NM_PLATFORM_LINK_DUPLEX_FULL,
} 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),
@@ -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);

View File

@@ -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);

View File

@@ -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);