Commit 5b0745e7 authored by Thomas Haller's avatar Thomas Haller
Browse files

platform: refactor detecting kernel support

We are going to add another parameter to check. Instead of adding multiple
virtual functions, add a NMPlatformKernelSupportFlags flags enum.
parent 5b507d57
......@@ -1203,7 +1203,8 @@ nm_device_set_ip_iface (NMDevice *self, const char *iface)
}
if (priv->ip_ifindex > 0) {
if (nm_platform_check_support_user_ipv6ll (nm_device_get_platform (self)))
if (nm_platform_check_kernel_support (nm_device_get_platform (self),
NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL))
nm_platform_link_set_user_ipv6ll_enabled (nm_device_get_platform (self), priv->ip_ifindex, TRUE);
if (!nm_platform_link_is_up (nm_device_get_platform (self), priv->ip_ifindex))
......@@ -3308,7 +3309,8 @@ realize_start_setup (NMDevice *self,
if (priv->firmware_version)
_notify (self, PROP_FIRMWARE_VERSION);
if (nm_platform_check_support_user_ipv6ll (nm_device_get_platform (self)))
if (nm_platform_check_kernel_support (nm_device_get_platform (self),
NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL))
priv->nm_ipv6ll = 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))
......@@ -7370,7 +7372,8 @@ 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_support_kernel_extended_ifa_flags (nm_device_get_platform (self))) {
if (nm_platform_check_kernel_support (nm_device_get_platform (self),
NM_PLATFORM_KERNEL_SUPPORT_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))
......@@ -7586,7 +7589,8 @@ 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_support_kernel_extended_ifa_flags (nm_device_get_platform (self))) {
&& !nm_platform_check_kernel_support (nm_device_get_platform (self),
NM_PLATFORM_KERNEL_SUPPORT_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");
}
......@@ -7686,7 +7690,8 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable)
int ifindex = nm_device_get_ip_ifindex (self);
char *value;
if (!nm_platform_check_support_user_ipv6ll (nm_device_get_platform (self)))
if (!nm_platform_check_kernel_support (nm_device_get_platform (self),
NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL))
return;
priv->nm_ipv6ll = enable;
......
......@@ -183,7 +183,8 @@ 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_support_kernel_extended_ifa_flags (NM_PLATFORM_GET)) {
if (nm_platform_check_kernel_support (NM_PLATFORM_GET,
NM_PLATFORM_KERNEL_SUPPORT_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))
......
......@@ -3074,20 +3074,25 @@ sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *pat
/*****************************************************************************/
static gboolean
check_support_kernel_extended_ifa_flags (NMPlatform *platform)
static NMPlatformKernelSupportFlags
check_kernel_support (NMPlatform *platform,
NMPlatformKernelSupportFlags request_flags)
{
NMPlatformKernelSupportFlags response = 0;
nm_assert (NM_IS_LINUX_PLATFORM (platform));
return _support_kernel_extended_ifa_flags_get ();
}
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;
}
static gboolean
check_support_user_ipv6ll (NMPlatform *platform)
{
nm_assert (NM_IS_LINUX_PLATFORM (platform));
if (NM_FLAGS_HAS (request_flags, NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL)) {
if (_support_user_ipv6ll_get ())
response |= NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL;
}
return _support_user_ipv6ll_get ();
return response;
}
static void
......@@ -6864,8 +6869,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->ip_route_delete = ip_route_delete;
platform_class->ip_route_get = ip_route_get;
platform_class->check_support_kernel_extended_ifa_flags = check_support_kernel_extended_ifa_flags;
platform_class->check_support_user_ipv6ll = check_support_user_ipv6ll;
platform_class->check_kernel_support = check_kernel_support;
platform_class->process_events = process_events;
}
......
......@@ -92,8 +92,8 @@ typedef struct _NMPlatformPrivate {
bool use_udev:1;
bool log_with_ptr:1;
gint8 check_support_kernel_extended_ifa_flags_cached;
gint8 check_support_user_ipv6ll_cached;
NMPlatformKernelSupportFlags support_checked;
NMPlatformKernelSupportFlags support_present;
guint ip4_dev_route_blacklist_check_id;
guint ip4_dev_route_blacklist_gc_timeout_id;
......@@ -301,8 +301,9 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_nmp_nlm_flag_to_string_lookup, NMPNlmFlags,
/*****************************************************************************/
gboolean
nm_platform_check_support_kernel_extended_ifa_flags (NMPlatform *self)
NMPlatformKernelSupportFlags
nm_platform_check_kernel_support (NMPlatform *self,
NMPlatformKernelSupportFlags request_flags)
{
NMPlatformPrivate *priv;
......@@ -310,29 +311,28 @@ nm_platform_check_support_kernel_extended_ifa_flags (NMPlatform *self)
priv = NM_PLATFORM_GET_PRIVATE (self);
if (G_UNLIKELY (priv->check_support_kernel_extended_ifa_flags_cached == 0)) {
priv->check_support_kernel_extended_ifa_flags_cached = ( klass->check_support_kernel_extended_ifa_flags
&& klass->check_support_kernel_extended_ifa_flags (self))
? 1 : -1;
}
return priv->check_support_kernel_extended_ifa_flags_cached >= 0;
}
gboolean
nm_platform_check_support_user_ipv6ll (NMPlatform *self)
{
NMPlatformPrivate *priv;
_CHECK_SELF (self, klass, TRUE);
priv = NM_PLATFORM_GET_PRIVATE (self);
/* 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 (G_UNLIKELY (priv->check_support_user_ipv6ll_cached == 0)) {
priv->check_support_user_ipv6ll_cached = ( klass->check_support_user_ipv6ll
&& klass->check_support_user_ipv6ll (self))
? 1 : -1;
priv->support_checked |= checked;
priv->support_present = (priv->support_present & ~checked) | (response & checked);
}
return priv->check_support_user_ipv6ll_cached >= 0;
return priv->support_present & request_flags;
}
/**
......@@ -3421,7 +3421,7 @@ delete_and_next:
if (!known_addresses)
return TRUE;
ifa_flags = nm_platform_check_support_kernel_extended_ifa_flags (self)
ifa_flags = nm_platform_check_kernel_support (self, NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS)
? IFA_F_NOPREFIXROUTE
: 0;
......@@ -3503,7 +3503,7 @@ nm_platform_ip6_address_sync (NMPlatform *self,
if (!known_addresses)
return TRUE;
ifa_flags = nm_platform_check_support_kernel_extended_ifa_flags (self)
ifa_flags = nm_platform_check_kernel_support (self, NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS)
? IFA_F_NOPREFIXROUTE
: 0;
......
......@@ -659,6 +659,11 @@ 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),
} NMPlatformKernelSupportFlags;
/*****************************************************************************/
struct _NMPlatformPrivate;
......@@ -824,8 +829,8 @@ typedef struct {
int oif_ifindex,
NMPObject **out_route);
gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *);
gboolean (*check_support_user_ipv6ll) (NMPlatform *);
NMPlatformKernelSupportFlags (*check_kernel_support) (NMPlatform * self,
NMPlatformKernelSupportFlags request_flags);
} NMPlatformClass;
/* NMPlatform signals
......@@ -1315,8 +1320,8 @@ nm_platform_ip6_route_hash_full (const NMPlatformIP6Route *obj)
return nm_platform_ip6_route_hash (obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL);
}
gboolean nm_platform_check_support_kernel_extended_ifa_flags (NMPlatform *self);
gboolean nm_platform_check_support_user_ipv6ll (NMPlatform *self);
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);
......
......@@ -512,7 +512,8 @@ test_bridge_addr (void)
plink = nm_platform_link_get (NM_PLATFORM_GET, link.ifindex);
g_assert (plink);
if (nm_platform_check_support_user_ipv6ll (NM_PLATFORM_GET)) {
if (nm_platform_check_kernel_support (NM_PLATFORM_GET,
NM_PLATFORM_KERNEL_SUPPORT_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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment