summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2019-05-28 10:35:57 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2019-05-28 10:35:57 +0200
commit3a4a09b669b6d3498017fe5773af3e9aef2ae8a5 (patch)
tree2802d1f3bef0cfbffd5e1050a5bedf2e97109fb7
parentd6a51ced40e7276cc281459c662d59c0b5429044 (diff)
parent121c58f0c48de9fb64a87ef02e3e090d90d2e96e (diff)
downloadNetworkManager-3a4a09b669b6d3498017fe5773af3e9aef2ae8a5.tar.gz
core: merge branch 'bg/sriov-async'
https://github.com/NetworkManager/NetworkManager/pull/268
-rw-r--r--src/devices/nm-device.c224
-rw-r--r--src/platform/nm-linux-platform.c362
-rw-r--r--src/platform/nm-platform.c90
-rw-r--r--src/platform/nm-platform.h211
-rw-r--r--src/platform/tests/test-link.c88
5 files changed, 769 insertions, 206 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 493288c197..ca0114f522 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -128,6 +128,15 @@ typedef struct {
int ifindex;
} DeleteOnDeactivateData;
+typedef struct {
+ NMDevice *device;
+ GCancellable *cancellable;
+ NMPlatformAsyncCallback callback;
+ gpointer callback_data;
+ guint num_vfs;
+ NMTernary autoprobe;
+} SriovOp;
+
typedef void (*AcdCallback) (NMDevice *, NMIP4Config **, gboolean);
typedef struct {
@@ -576,12 +585,16 @@ typedef struct _NMDevicePrivate {
guint check_delete_unrealized_id;
struct {
+ SriovOp *pending; /* SR-IOV operation currently running */
+ SriovOp *next; /* next SR-IOV operation scheduled */
+ } sriov;
+
+ struct {
guint timeout_id;
guint refresh_rate_ms;
guint64 tx_bytes;
guint64 rx_bytes;
} stats;
-
} NMDevicePrivate;
G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_DBUS_OBJECT)
@@ -4192,6 +4205,86 @@ nm_device_update_from_platform_link (NMDevice *self, const NMPlatformLink *plink
}
}
+static void sriov_op_cb (GError *error, gpointer user_data);
+
+static void
+sriov_op_start (NMDevice *self, SriovOp *op)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+
+ nm_assert (!priv->sriov.pending);
+
+ op->cancellable = g_cancellable_new ();
+ op->device = g_object_ref (self);
+ priv->sriov.pending = op;
+
+ nm_platform_link_set_sriov_params_async (nm_device_get_platform (self),
+ priv->ifindex,
+ op->num_vfs,
+ op->autoprobe,
+ sriov_op_cb,
+ op,
+ op->cancellable);
+}
+
+static void
+sriov_op_cb (GError *error, gpointer user_data)
+{
+ SriovOp *op = user_data;
+ gs_unref_object NMDevice *self = op->device;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+
+ nm_assert (op == priv->sriov.pending);
+
+ priv->sriov.pending = NULL;
+
+ if (op->callback)
+ op->callback (error, op->callback_data);
+
+ g_clear_object (&op->cancellable);
+ g_slice_free (SriovOp, op);
+
+ if (priv->sriov.next) {
+ sriov_op_start (self,
+ g_steal_pointer (&priv->sriov.next));
+ }
+}
+
+static void
+sriov_op_queue (NMDevice *self,
+ guint num_vfs,
+ NMTernary autoprobe,
+ NMPlatformAsyncCallback callback,
+ gpointer callback_data)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ GError *error = NULL;
+ SriovOp *op;
+
+ op = g_slice_new0 (SriovOp);
+ op->num_vfs = num_vfs;
+ op->autoprobe = autoprobe;
+ op->callback = callback;
+ op->callback_data = callback_data;
+
+ if (priv->sriov.next) {
+ /* Cancel the next operation immediately */
+ if (priv->sriov.next->callback) {
+ nm_utils_error_set_cancelled (&error, FALSE, NULL);
+ priv->sriov.next->callback (error, priv->sriov.next->callback_data);
+ g_clear_error (&error);
+ }
+ g_slice_free (SriovOp, priv->sriov.next);
+ priv->sriov.next = NULL;
+ }
+
+ if (priv->sriov.pending) {
+ priv->sriov.next = op;
+ g_cancellable_cancel (priv->sriov.pending->cancellable);
+ } else
+ sriov_op_start (self, op);
+}
+
static void
device_init_static_sriov_num_vfs (NMDevice *self)
{
@@ -4206,10 +4299,8 @@ device_init_static_sriov_num_vfs (NMDevice *self)
self,
NULL);
num_vfs = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXINT32, -1);
- if (num_vfs >= 0) {
- nm_platform_link_set_sriov_params (nm_device_get_platform (self),
- priv->ifindex, num_vfs, NM_TERNARY_DEFAULT);
- }
+ if (num_vfs >= 0)
+ sriov_op_queue (self, num_vfs, NM_TERNARY_DEFAULT, NULL, NULL);
}
}
@@ -4223,11 +4314,11 @@ config_changed (NMConfig *config,
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
if ( priv->state <= NM_DEVICE_STATE_DISCONNECTED
- || priv->state > NM_DEVICE_STATE_ACTIVATED)
+ || priv->state > NM_DEVICE_STATE_ACTIVATED) {
priv->ignore_carrier = nm_config_data_get_ignore_carrier (config_data, self);
-
- if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_VALUES))
- device_init_static_sriov_num_vfs (self);
+ if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_VALUES))
+ device_init_static_sriov_num_vfs (self);
+ }
}
static void
@@ -6265,6 +6356,41 @@ sriov_vf_config_to_platform (NMDevice *self,
return g_steal_pointer (&plat_vf);
}
+static void
+sriov_params_cb (GError *error, gpointer data)
+{
+ NMDevice *self;
+ NMDevicePrivate *priv;
+ nm_auto_freev NMPlatformVF **plat_vfs = NULL;
+
+ nm_utils_user_data_unpack (data, &self, &plat_vfs);
+
+ if (nm_utils_error_is_cancelled (error, TRUE))
+ return;
+
+ priv = NM_DEVICE_GET_PRIVATE (self);
+
+ if (error) {
+ _LOGE (LOGD_DEVICE, "failed to set SR-IOV parameters: %s", error->message);
+ nm_device_state_changed (self,
+ NM_DEVICE_STATE_FAILED,
+ NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED);
+ return;
+ }
+
+ if (!nm_platform_link_set_sriov_vfs (nm_device_get_platform (self),
+ priv->ifindex,
+ (const NMPlatformVF *const *) plat_vfs)) {
+ _LOGE (LOGD_DEVICE, "failed to apply SR-IOV VFs");
+ nm_device_state_changed (self,
+ NM_DEVICE_STATE_FAILED,
+ NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED);
+ return;
+ }
+
+ nm_device_activate_schedule_stage2_device_config (self);
+}
+
static NMActStageReturn
act_stage1_prepare (NMDevice *self, NMDeviceStateReason *out_failure_reason)
{
@@ -6279,6 +6405,7 @@ act_stage1_prepare (NMDevice *self, NMDeviceStateReason *out_failure_reason)
gs_free_error GError *error = NULL;
NMSriovVF *vf;
NMTernary autoprobe;
+ gpointer *data;
autoprobe = nm_setting_sriov_get_autoprobe_drivers (s_sriov);
if (autoprobe == NM_TERNARY_DEFAULT) {
@@ -6305,24 +6432,19 @@ act_stage1_prepare (NMDevice *self, NMDeviceStateReason *out_failure_reason)
}
}
- if (!nm_platform_link_set_sriov_params (nm_device_get_platform (self),
- priv->ifindex,
- nm_setting_sriov_get_total_vfs (s_sriov),
- autoprobe)) {
- _LOGE (LOGD_DEVICE, "failed to apply SR-IOV parameters");
- NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
-
- if (!nm_platform_link_set_sriov_vfs (nm_device_get_platform (self),
- priv->ifindex,
- (const NMPlatformVF *const *) plat_vfs)) {
- _LOGE (LOGD_DEVICE, "failed to apply SR-IOV VFs");
- NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
+ /* When changing the number of VFs the kernel can block
+ * for very long time in the write to sysfs, especially
+ * if autoprobe-drivers is enabled. Do it asynchronously
+ * to avoid blocking the entire NM process.
+ */
+ data = nm_utils_user_data_pack (self, g_steal_pointer (&plat_vfs));
+ sriov_op_queue (self,
+ nm_setting_sriov_get_total_vfs (s_sriov),
+ autoprobe,
+ sriov_params_cb,
+ data);
+ return NM_ACT_STAGE_RETURN_POSTPONE;
}
-
return NM_ACT_STAGE_RETURN_SUCCESS;
}
@@ -14801,6 +14923,34 @@ ip6_managed_setup (NMDevice *self)
}
static void
+deactivate_ready (NMDevice *self, NMDeviceStateReason reason)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+
+ if (priv->dispatcher.call_id)
+ return;
+
+ if (priv->sriov.pending)
+ return;
+ nm_assert (!priv->sriov.next);
+
+ nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, reason);
+}
+
+static void
+sriov_deactivate_cb (GError *error, gpointer user_data)
+{
+ NMDevice *self;
+ gpointer reason;
+
+ if (nm_utils_error_is_cancelled (error, TRUE))
+ return;
+
+ nm_utils_user_data_unpack (user_data, &self, &reason);
+ deactivate_ready (self, (NMDeviceStateReason) reason);
+}
+
+static void
deactivate_async_ready (NMDevice *self,
GError *error,
gpointer user_data)
@@ -14820,7 +14970,8 @@ deactivate_async_ready (NMDevice *self,
_LOGW (LOGD_DEVICE, "Deactivation failed: %s",
error->message);
}
- nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, reason);
+
+ deactivate_ready (self, reason);
}
static void
@@ -14833,7 +14984,7 @@ deactivate_dispatcher_complete (NMDispatcherCallId *call_id, gpointer user_data)
g_return_if_fail (call_id == priv->dispatcher.call_id);
g_return_if_fail (priv->dispatcher.post_state == NM_DEVICE_STATE_DISCONNECTED);
- reason = priv->dispatcher.post_state_reason;
+ reason = priv->state_reason;
priv->dispatcher.call_id = NULL;
priv->dispatcher.post_state = NM_DEVICE_STATE_UNKNOWN;
@@ -14849,7 +15000,7 @@ deactivate_dispatcher_complete (NMDispatcherCallId *call_id, gpointer user_data)
deactivate_async_ready,
GUINT_TO_POINTER (reason));
} else
- nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, reason);
+ deactivate_ready (self, reason);
}
static void
@@ -15062,12 +15213,6 @@ _set_state_full (NMDevice *self,
}
break;
case NM_DEVICE_STATE_DEACTIVATING:
- if ( (s_sriov = nm_device_get_applied_setting (self, NM_TYPE_SETTING_SRIOV))
- && priv->ifindex > 0) {
- nm_platform_link_set_sriov_params (nm_device_get_platform (self),
- priv->ifindex, 0, NM_TERNARY_TRUE);
- }
-
_cancel_activation (self);
/* We cache the ignore_carrier state to not react on config-reloads while the connection
@@ -15089,6 +15234,15 @@ _set_state_full (NMDevice *self,
/* Just proceed on errors */
deactivate_dispatcher_complete (0, self);
}
+
+ if ( priv->ifindex > 0
+ && (s_sriov = nm_device_get_applied_setting (self, NM_TYPE_SETTING_SRIOV))) {
+ sriov_op_queue (self,
+ 0,
+ NM_TERNARY_TRUE,
+ sriov_deactivate_cb,
+ nm_utils_user_data_pack (self, (gpointer) reason));
+ }
}
nm_pacrunner_manager_remove_clear (&priv->pacrunner_conf_id);
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 13eda83109..ac8e869d8e 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -4375,6 +4375,14 @@ _genl_sock (NMLinuxPlatform *platform)
} \
} G_STMT_END
+/*****************************************************************************/
+
+/* core sysctl-set functions can be called from a non-main thread.
+ * Hence, we require locking from nm-logging. Indicate that by
+ * setting NM_THREAD_SAFE_ON_MAIN_THREAD to zero. */
+#undef NM_THREAD_SAFE_ON_MAIN_THREAD
+#define NM_THREAD_SAFE_ON_MAIN_THREAD 0
+
static void
_log_dbg_sysctl_set_impl (NMPlatform *platform, const char *pathid, int dirfd, const char *path, const char *value)
{
@@ -4385,18 +4393,18 @@ _log_dbg_sysctl_set_impl (NMPlatform *platform, const char *pathid, int dirfd, c
if (nm_utils_file_get_contents (dirfd, path, 1*1024*1024,
NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE,
&contents, NULL, &error) < 0) {
- _LOGD ("sysctl: setting '%s' to '%s' (current value cannot be read: %s)", pathid, value_escaped, error->message);
+ _LOGD ("sysctl: setting '%s' to '%s' (current value cannot be read: %s)", pathid ?: path, value_escaped, error->message);
g_clear_error (&error);
return;
}
g_strstrip (contents);
if (nm_streq (contents, value))
- _LOGD ("sysctl: setting '%s' to '%s' (current value is identical)", pathid, value_escaped);
+ _LOGD ("sysctl: setting '%s' to '%s' (current value is identical)", pathid ?: path, value_escaped);
else {
gs_free char *contents_escaped = g_strescape (contents, NULL);
- _LOGD ("sysctl: setting '%s' to '%s' (current value is '%s')", pathid, value_escaped, contents_escaped);
+ _LOGD ("sysctl: setting '%s' to '%s' (current value is '%s')", pathid ?: path, value_escaped, contents_escaped);
}
g_free (contents);
}
@@ -4409,9 +4417,12 @@ _log_dbg_sysctl_set_impl (NMPlatform *platform, const char *pathid, int dirfd, c
} G_STMT_END
static gboolean
-sysctl_set (NMPlatform *platform, const char *pathid, int dirfd, const char *path, const char *value)
+sysctl_set_internal (NMPlatform *platform,
+ const char *pathid,
+ int dirfd,
+ const char *path,
+ const char *value)
{
- nm_auto_pop_netns NMPNetns *netns = NULL;
int fd, tries;
gssize nwrote;
gssize len;
@@ -4419,17 +4430,7 @@ sysctl_set (NMPlatform *platform, const char *pathid, int dirfd, const char *pat
gs_free char *actual_free = NULL;
int errsv;
- g_return_val_if_fail (path != NULL, FALSE);
- g_return_val_if_fail (value != NULL, FALSE);
-
- ASSERT_SYSCTL_ARGS (pathid, dirfd, path);
-
if (dirfd < 0) {
- if (!nm_platform_netns_push (platform, &netns)) {
- errno = ENETDOWN;
- return FALSE;
- }
-
pathid = path;
fd = open (path, O_WRONLY | O_TRUNC | O_CLOEXEC);
@@ -4529,6 +4530,207 @@ sysctl_set (NMPlatform *platform, const char *pathid, int dirfd, const char *pat
return TRUE;
}
+#undef NM_THREAD_SAFE_ON_MAIN_THREAD
+#define NM_THREAD_SAFE_ON_MAIN_THREAD 1
+
+/*****************************************************************************/
+
+static gboolean
+sysctl_set (NMPlatform *platform,
+ const char *pathid,
+ int dirfd,
+ const char *path,
+ const char *value)
+{
+ nm_auto_pop_netns NMPNetns *netns = NULL;
+
+ g_return_val_if_fail (path, FALSE);
+ g_return_val_if_fail (value, FALSE);
+
+ ASSERT_SYSCTL_ARGS (pathid, dirfd, path);
+
+ if ( dirfd < 0
+ && !nm_platform_netns_push (platform, &netns)) {
+ errno = ENETDOWN;
+ return FALSE;
+ }
+
+ return sysctl_set_internal (platform, pathid, dirfd, path, value);
+}
+
+typedef struct {
+ NMPlatform *platform;
+ char *pathid;
+ int dirfd;
+ char *path;
+ char **values;
+ GCancellable *cancellable;
+ NMPlatformAsyncCallback callback;
+ gpointer callback_data;
+} SysctlAsyncInfo;
+
+static void
+sysctl_async_info_free (SysctlAsyncInfo *info)
+{
+ g_object_unref (info->platform);
+ g_free (info->pathid);
+ if (info->dirfd >= 0)
+ nm_close (info->dirfd);
+ g_free (info->path);
+ g_strfreev (info->values);
+ g_object_unref (info->cancellable);
+ g_slice_free (SysctlAsyncInfo, info);
+}
+
+static void
+sysctl_async_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NMPlatform *platform;
+ GTask *task = G_TASK (res);
+ SysctlAsyncInfo *info;
+ gs_free_error GError *error = NULL;
+ gs_free char *values_str = NULL;
+
+ info = g_task_get_task_data (task);
+
+ if (g_task_propagate_boolean (task, &error)) {
+ platform = info->platform;
+ _LOGD ("sysctl: successfully set-async '%s' to values '%s'",
+ info->pathid ?: info->path,
+ (values_str = g_strjoinv (", ", info->values)));
+ }
+
+ if (info->callback)
+ info->callback (error, info->callback_data);
+}
+
+static void
+sysctl_async_thread_fn (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ nm_auto_pop_netns NMPNetns *netns = NULL;
+ SysctlAsyncInfo *info = task_data;
+ GError *error = NULL;
+ char **value;
+
+ if (g_task_return_error_if_cancelled (task))
+ return;
+
+ if ( info->dirfd < 0
+ && !nm_platform_netns_push (info->platform, &netns)) {
+ g_set_error_literal (&error,
+ NM_UTILS_ERROR,
+ NM_UTILS_ERROR_UNKNOWN,
+ "sysctl: failed changing namespace");
+ g_task_return_error (task, error);
+ return;
+ }
+
+ for (value = info->values; *value; value++) {
+ if (!sysctl_set_internal (info->platform,
+ info->pathid,
+ info->dirfd,
+ info->path,
+ *value)) {
+ g_set_error (&error,
+ NM_UTILS_ERROR,
+ NM_UTILS_ERROR_UNKNOWN,
+ "sysctl: failed setting '%s' to value '%s': %s",
+ info->pathid ?: info->path,
+ *value,
+ nm_strerror_native (errno));
+ g_task_return_error (task, error);
+ return;
+ }
+ if (g_task_return_error_if_cancelled (task))
+ return;
+ }
+ g_task_return_boolean (task, TRUE);
+}
+
+static void
+sysctl_set_async_return_idle (gpointer user_data,
+ GCancellable *cancellable)
+{
+ gs_unref_object NMPlatform *platform = NULL;
+ gs_free_error GError *cancelled_error = NULL;
+ gs_free_error GError *error = NULL;
+ NMPlatformAsyncCallback callback;
+ gpointer callback_data;
+
+ nm_utils_user_data_unpack (user_data, &platform, &callback, &callback_data, &error);
+ g_cancellable_set_error_if_cancelled (cancellable, &cancelled_error);
+ callback (cancelled_error ?: error, callback_data);
+}
+
+static void
+sysctl_set_async (NMPlatform *platform,
+ const char *pathid,
+ int dirfd,
+ const char *path,
+ const char *const *values,
+ NMPlatformAsyncCallback callback,
+ gpointer data,
+ GCancellable *cancellable)
+{
+ SysctlAsyncInfo *info;
+ GTask *task;
+ int dirfd_dup, errsv;
+ gpointer packed;
+ GError *error = NULL;
+
+ g_return_if_fail (platform);
+ g_return_if_fail (path);
+ g_return_if_fail (values && values[0]);
+ g_return_if_fail (cancellable);
+ g_return_if_fail (!data || callback);
+
+ ASSERT_SYSCTL_ARGS (pathid, dirfd, path);
+
+ if (dirfd >= 0) {
+ dirfd_dup = fcntl (dirfd, F_DUPFD_CLOEXEC, 0);
+ if (dirfd_dup < 0) {
+ if (!callback)
+ return;
+ errsv = errno;
+ g_set_error (&error,
+ NM_UTILS_ERROR,
+ NM_UTILS_ERROR_UNKNOWN,
+ "sysctl: failure duplicating directory fd: %s",
+ nm_strerror_native (errsv));
+ packed = nm_utils_user_data_pack (g_object_ref (platform),
+ callback,
+ data,
+ error);
+ nm_utils_invoke_on_idle (sysctl_set_async_return_idle,
+ packed,
+ cancellable);
+ return;
+ }
+ } else
+ dirfd_dup = -1;
+
+ info = g_slice_new0 (SysctlAsyncInfo);
+ info->platform = g_object_ref (platform);
+ info->pathid = g_strdup (pathid);
+ info->dirfd = dirfd_dup;
+ info->path = g_strdup (path);
+ info->values = g_strdupv ((char **) values);
+ info->callback = callback;
+ info->callback_data = data;
+ info->cancellable = g_object_ref (cancellable);
+
+ task = g_task_new (platform, cancellable, sysctl_async_cb, NULL);
+ g_task_set_task_data (task, info, (GDestroyNotify) sysctl_async_info_free);
+ g_task_set_return_on_cancel (task, FALSE);
+ g_task_run_in_thread (task, sysctl_async_thread_fn);
+ g_object_unref (task);
+}
+
static GSList *sysctl_clear_cache_list;
void
@@ -6612,35 +6814,74 @@ nla_put_failure:
g_return_val_if_reached (FALSE);
}
-static gboolean
-link_set_sriov_params (NMPlatform *platform,
- int ifindex,
- guint num_vfs,
- NMTernary autoprobe)
+static void
+sriov_idle_cb (gpointer user_data,
+ GCancellable *cancellable)
+{
+ gs_unref_object NMPlatform *platform = NULL;
+ gs_free_error GError *cancelled_error = NULL;
+ gs_free_error GError *error = NULL;
+ NMPlatformAsyncCallback callback;
+ gpointer callback_data;
+
+ g_cancellable_set_error_if_cancelled (cancellable, &cancelled_error);
+ nm_utils_user_data_unpack (user_data, &platform, &error, &callback, &callback_data);
+ callback (cancelled_error ?: error, callback_data);
+}
+
+static void
+link_set_sriov_params_async (NMPlatform *platform,
+ int ifindex,
+ guint num_vfs,
+ NMTernary autoprobe,
+ NMPlatformAsyncCallback callback,
+ gpointer data,
+ GCancellable *cancellable)
{
nm_auto_pop_netns NMPNetns *netns = NULL;
+ gs_free_error GError *error = NULL;
nm_auto_close int dirfd = -1;
int current_autoprobe;
- guint total;
+ guint i, total;
gint64 current_num;
char ifname[IFNAMSIZ];
+ gpointer packed;
+ const char *values[3];
char buf[64];
- int errsv;
- if (!nm_platform_netns_push (platform, &netns))
- return FALSE;
+ g_return_if_fail (callback || !data);
+ g_return_if_fail (cancellable);
+
+ if (!nm_platform_netns_push (platform, &netns)) {
+ g_set_error_literal (&error,
+ NM_UTILS_ERROR,
+ NM_UTILS_ERROR_UNKNOWN,
+ "couldn't change namespace");
+ goto out_idle;
+ }
dirfd = nm_platform_sysctl_open_netdir (platform, ifindex, ifname);
- if (!dirfd)
- return FALSE;
+ if (!dirfd) {
+ g_set_error_literal (&error,
+ NM_UTILS_ERROR,
+ NM_UTILS_ERROR_UNKNOWN,
+ "couldn't open netdir");
+ goto out_idle;
+ }
total = nm_platform_sysctl_get_int_checked (platform,
NMP_SYSCTL_PATHID_NETDIR (dirfd,
ifname,
"device/sriov_totalvfs"),
10, 0, G_MAXUINT, 0);
- if (errno)
- return FALSE;
+ if (errno) {
+ g_set_error (&error,
+ NM_UTILS_ERROR,
+ NM_UTILS_ERROR_UNKNOWN,
+ "failed reading sriov_totalvfs value: %s",
+ nm_strerror_native (errno));
+ goto out_idle;
+ }
if (num_vfs > total) {
_LOGW ("link: %d only supports %u VFs (requested %u)", ifindex, total, num_vfs);
num_vfs = total;
@@ -6672,23 +6913,7 @@ link_set_sriov_params (NMPlatform *platform,
if ( current_num == num_vfs
&& (autoprobe == NM_TERNARY_DEFAULT || current_autoprobe == autoprobe))
- return TRUE;
-
- if (current_num != 0) {
- /* We need to destroy all other VFs before changing any value */
- if (!nm_platform_sysctl_set (NM_PLATFORM_GET,
- NMP_SYSCTL_PATHID_NETDIR (dirfd,
- ifname,
- "device/sriov_numvfs"),
- "0")) {
- errsv = errno;
- _LOGW ("link: couldn't reset SR-IOV num_vfs: %s", nm_strerror_native (errsv));
- return FALSE;
- }
- }
-
- if (num_vfs == 0)
- return TRUE;
+ goto out_idle;
if ( NM_IN_SET (autoprobe, NM_TERNARY_TRUE, NM_TERNARY_FALSE)
&& current_autoprobe != autoprobe
@@ -6697,22 +6922,40 @@ link_set_sriov_params (NMPlatform *platform,
ifname,
"device/sriov_drivers_autoprobe"),
nm_sprintf_buf (buf, "%d", (int) autoprobe))) {
- errsv = errno;
- _LOGW ("link: couldn't set SR-IOV drivers-autoprobe to %d: %s", (int) autoprobe, nm_strerror_native (errsv));
- return FALSE;
+ g_set_error (&error,
+ NM_UTILS_ERROR,
+ NM_UTILS_ERROR_UNKNOWN,
+ "couldn't set SR-IOV drivers-autoprobe to %d: %s",
+ (int) autoprobe, nm_strerror_native (errno));
+ goto out_idle;
}
- if (!nm_platform_sysctl_set (NM_PLATFORM_GET,
- NMP_SYSCTL_PATHID_NETDIR (dirfd,
- ifname,
- "device/sriov_numvfs"),
- nm_sprintf_buf (buf, "%u", num_vfs))) {
- errsv = errno;
- _LOGW ("link: couldn't set SR-IOV num_vfs to %d: %s", num_vfs, nm_strerror_native (errsv));
- return FALSE;
- }
+ if (current_num == 0 && num_vfs == 0)
+ goto out_idle;
- return TRUE;
+ i = 0;
+ if (current_num != 0)
+ values[i++] = "0";
+ if (num_vfs != 0)
+ values[i++] = nm_sprintf_bufa (32, "%u", num_vfs);
+ values[i++] = NULL;
+
+ sysctl_set_async (platform,
+ NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname, "device/sriov_numvfs"),
+ values,
+ callback,
+ data,
+ cancellable);
+ return;
+
+out_idle:
+ if (callback) {
+ packed = nm_utils_user_data_pack (g_object_ref (platform),
+ g_steal_pointer (&error),
+ callback,
+ data);
+ nm_utils_invoke_on_idle (sriov_idle_cb, packed, cancellable);
+ }
}
static gboolean
@@ -8997,6 +9240,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
object_class->finalize = finalize;
platform_class->sysctl_set = sysctl_set;
+ platform_class->sysctl_set_async = sysctl_set_async;
platform_class->sysctl_get = sysctl_get;
platform_class->link_add = link_add;
@@ -9020,7 +9264,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->link_get_permanent_address = link_get_permanent_address;
platform_class->link_set_mtu = link_set_mtu;
platform_class->link_set_name = link_set_name;
- platform_class->link_set_sriov_params = link_set_sriov_params;
+ platform_class->link_set_sriov_params_async = link_set_sriov_params_async;
platform_class->link_set_sriov_vfs = link_set_sriov_vfs;
platform_class->link_set_bridge_vlans = link_set_bridge_vlans;
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index a2d4116de1..4a98df84e8 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -481,6 +481,40 @@ nm_platform_sysctl_set (NMPlatform *self, const char *pathid, int dirfd, const c
return klass->sysctl_set (self, pathid, dirfd, path, value);
}
+/**
+ * nm_platform_sysctl_set_async:
+ * @self: platform instance
+ * @pathid: if @dirfd is present, this must be the full path that is looked up
+ * @dirfd: optional file descriptor for parent directory for openat()
+ * @path: absolute option path
+ * @values: NULL-terminated array of strings to be written
+ * @callback: function called on termination
+ * @data: data passed to callback function
+ * @cancellable: to cancel the operation
+ *
+ * This function is intended to be used for writing values to sysctl-style
+ * virtual runtime configuration files. This includes not only /proc/sys
+ * but also for example /sys/class. The function does not block and returns
+ * immediately. The callback is always invoked, and asynchronously. The file
+ * is closed after writing each value and reopened to write the next one so
+ * that the function can be used safely on all /proc and /sys files,
+ * independently of how /proc/sys/kernel/sysctl_writes_strict is configured.
+ */
+void nm_platform_sysctl_set_async (NMPlatform *self,
+ const char *pathid,
+ int dirfd,
+ const char *path,
+ const char *const *values,
+ NMPlatformAsyncCallback callback,
+ gpointer data,
+ GCancellable *cancellable)
+{
+ _CHECK_SELF_VOID (self, klass);
+
+ klass->sysctl_set_async (self, pathid, dirfd, path, values, callback, data, cancellable);
+}
+
+
gboolean
nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe (NMPlatform *self,
const char *iface,
@@ -623,14 +657,14 @@ nm_platform_sysctl_get_int_checked (NMPlatform *self,
/*****************************************************************************/
char *
-nm_platform_sysctl_ip_conf_get (NMPlatform *platform,
+nm_platform_sysctl_ip_conf_get (NMPlatform *self,
int addr_family,
const char *ifname,
const char *property)
{
char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
- return nm_platform_sysctl_get (platform,
+ return nm_platform_sysctl_get (self,
NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (addr_family,
buf,
ifname,
@@ -638,7 +672,7 @@ nm_platform_sysctl_ip_conf_get (NMPlatform *platform,
}
gint64
-nm_platform_sysctl_ip_conf_get_int_checked (NMPlatform *platform,
+nm_platform_sysctl_ip_conf_get_int_checked (NMPlatform *self,
int addr_family,
const char *ifname,
const char *property,
@@ -649,7 +683,7 @@ nm_platform_sysctl_ip_conf_get_int_checked (NMPlatform *platform,
{
char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
- return nm_platform_sysctl_get_int_checked (platform,
+ return nm_platform_sysctl_get_int_checked (self,
NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (addr_family,
buf,
ifname,
@@ -661,7 +695,7 @@ nm_platform_sysctl_ip_conf_get_int_checked (NMPlatform *platform,
}
gboolean
-nm_platform_sysctl_ip_conf_set (NMPlatform *platform,
+nm_platform_sysctl_ip_conf_set (NMPlatform *self,
int addr_family,
const char *ifname,
const char *property,
@@ -669,7 +703,7 @@ nm_platform_sysctl_ip_conf_set (NMPlatform *platform,
{
char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
- return nm_platform_sysctl_set (platform,
+ return nm_platform_sysctl_set (self,
NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (addr_family,
buf,
ifname,
@@ -678,7 +712,7 @@ nm_platform_sysctl_ip_conf_set (NMPlatform *platform,
}
gboolean
-nm_platform_sysctl_ip_conf_set_int64 (NMPlatform *platform,
+nm_platform_sysctl_ip_conf_set_int64 (NMPlatform *self,
int addr_family,
const char *ifname,
const char *property,
@@ -687,7 +721,7 @@ nm_platform_sysctl_ip_conf_set_int64 (NMPlatform *platform,
char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
char s[64];
- return nm_platform_sysctl_set (platform,
+ return nm_platform_sysctl_set (self,
NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (addr_family,
buf,
ifname,
@@ -1553,19 +1587,35 @@ nm_platform_link_supports_sriov (NMPlatform *self, int ifindex)
* @num_vfs: the number of VFs to create
* @autoprobe: the new autoprobe-drivers value (pass
* %NM_TERNARY_DEFAULT to keep current value)
+ * @callback: called when the operation finishes
+ * @callback_data: data passed to @callback
+ * @cancellable: cancellable to abort the operation
+ *
+ * Sets SR-IOV parameters asynchronously without
+ * blocking the main thread. The callback function is
+ * always invoked, and asynchronously.
*/
-gboolean
-nm_platform_link_set_sriov_params (NMPlatform *self,
- int ifindex,
- guint num_vfs,
- NMTernary autoprobe)
+void
+nm_platform_link_set_sriov_params_async (NMPlatform *self,
+ int ifindex,
+ guint num_vfs,
+ NMTernary autoprobe,
+ NMPlatformAsyncCallback callback,
+ gpointer callback_data,
+ GCancellable *cancellable)
{
- _CHECK_SELF (self, klass, FALSE);
+ _CHECK_SELF_VOID (self, klass);
- g_return_val_if_fail (ifindex > 0, FALSE);
+ g_return_if_fail (ifindex > 0);
_LOG3D ("link: setting %u total VFs and autoprobe %d", num_vfs, (int) autoprobe);
- return klass->link_set_sriov_params (self, ifindex, num_vfs, autoprobe);
+ klass->link_set_sriov_params_async (self,
+ ifindex,
+ num_vfs,
+ autoprobe,
+ callback,
+ callback_data,
+ cancellable);
}
gboolean
@@ -3402,21 +3452,21 @@ nm_platform_ethtool_set_features (NMPlatform *self,
/*****************************************************************************/
const NMDedupMultiHeadEntry *
-nm_platform_lookup_all (NMPlatform *platform,
+nm_platform_lookup_all (NMPlatform *self,
NMPCacheIdType cache_id_type,
const NMPObject *obj)
{
- return nmp_cache_lookup_all (nm_platform_get_cache (platform),
+ return nmp_cache_lookup_all (nm_platform_get_cache (self),
cache_id_type,
obj);
}
const NMDedupMultiEntry *
-nm_platform_lookup_entry (NMPlatform *platform,
+nm_platform_lookup_entry (NMPlatform *self,
NMPCacheIdType cache_id_type,
const NMPObject *obj)
{
- return nmp_cache_lookup_entry_with_idx_type (nm_platform_get_cache (platform),
+ return nmp_cache_lookup_entry_with_idx_type (nm_platform_get_cache (self),
cache_id_type,
obj);
}
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index a2d8e57ff6..a6b5f2c4c3 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -895,6 +895,8 @@ typedef enum {
} NMPlatformWireGuardChangePeerFlags;
+typedef void (*NMPlatformAsyncCallback) (GError *error, gpointer user_data);
+
/*****************************************************************************/
typedef enum {
@@ -953,64 +955,75 @@ struct _NMPlatform {
typedef struct {
GObjectClass parent;
- gboolean (*sysctl_set) (NMPlatform *, const char *pathid, int dirfd, const char *path, const char *value);
- char * (*sysctl_get) (NMPlatform *, const char *pathid, int dirfd, const char *path);
+ gboolean (*sysctl_set) (NMPlatform *self, const char *pathid, int dirfd, const char *path, const char *value);
+ void (*sysctl_set_async) (NMPlatform *self,
+ const char *pathid,
+ int dirfd,
+ const char *path,
+ const char *const *values,
+ NMPlatformAsyncCallback callback,
+ gpointer data,
+ GCancellable *cancellable);
+ char * (*sysctl_get) (NMPlatform *self, const char *pathid, int dirfd, const char *path);
+
+ void (*refresh_all) (NMPlatform *self, NMPObjectType obj_type);
+ void (*process_events) (NMPlatform *self);
- int (*link_add) (NMPlatform *,
+ int (*link_add) (NMPlatform *self,
const char *name,
NMLinkType type,
const char *veth_peer,
const void *address,
size_t address_len,
const NMPlatformLink **out_link);
-
- gboolean (*link_delete) (NMPlatform *, int ifindex);
-
- gboolean (*link_refresh) (NMPlatform *, int ifindex);
-
- gboolean (*link_set_netns) (NMPlatform *, int ifindex, int netns_fd);
-
- void (*process_events) (NMPlatform *self);
-
- gboolean (*link_set_up) (NMPlatform *, int ifindex, gboolean *out_no_firmware);
- gboolean (*link_set_down) (NMPlatform *, int ifindex);
- gboolean (*link_set_arp) (NMPlatform *, int ifindex);
- gboolean (*link_set_noarp) (NMPlatform *, int ifindex);
+ gboolean (*link_delete) (NMPlatform *self, int ifindex);
+ gboolean (*link_refresh) (NMPlatform *self, int ifindex);
+ gboolean (*link_set_netns) (NMPlatform *self, int ifindex, int netns_fd);
+ gboolean (*link_set_up) (NMPlatform *self, int ifindex, gboolean *out_no_firmware);
+ gboolean (*link_set_down) (NMPlatform *self, int ifindex);
+ gboolean (*link_set_arp) (NMPlatform *self, int ifindex);
+ gboolean (*link_set_noarp) (NMPlatform *self, int ifindex);
const char *(*link_get_udi) (NMPlatform *self, int ifindex);
struct udev_device *(*link_get_udev_device) (NMPlatform *self, int ifindex);
- int (*link_set_user_ipv6ll_enabled) (NMPlatform *, int ifindex, gboolean enabled);
- gboolean (*link_set_token) (NMPlatform *, int ifindex, NMUtilsIPv6IfaceId iid);
+ int (*link_set_user_ipv6ll_enabled) (NMPlatform *self, int ifindex, gboolean enabled);
+ gboolean (*link_set_token) (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid);
- gboolean (*link_get_permanent_address) (NMPlatform *,
+ gboolean (*link_get_permanent_address) (NMPlatform *self,
int ifindex,
guint8 *buf,
size_t *length);
- int (*link_set_address) (NMPlatform *, int ifindex, gconstpointer address, size_t length);
- int (*link_set_mtu) (NMPlatform *, int ifindex, guint32 mtu);
- gboolean (*link_set_name) (NMPlatform *, int ifindex, const char *name);
- gboolean (*link_set_sriov_params) (NMPlatform *, int ifindex, guint num_vfs, int autoprobe);
+ int (*link_set_address) (NMPlatform *self, int ifindex, gconstpointer address, size_t length);
+ int (*link_set_mtu) (NMPlatform *self, int ifindex, guint32 mtu);
+ gboolean (*link_set_name) (NMPlatform *self, int ifindex, const char *name);
+ void (*link_set_sriov_params_async) (NMPlatform *self,
+ int ifindex,
+ guint num_vfs,
+ int autoprobe,
+ NMPlatformAsyncCallback callback,
+ gpointer callback_data,
+ GCancellable *cancellable);
gboolean (*link_set_sriov_vfs) (NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs);
gboolean (*link_set_bridge_vlans) (NMPlatform *self, int ifindex, gboolean on_master, const NMPlatformBridgeVlan *const *vlans);
- char * (*link_get_physical_port_id) (NMPlatform *, int ifindex);
- guint (*link_get_dev_id) (NMPlatform *, int ifindex);
- gboolean (*link_get_wake_on_lan) (NMPlatform *, int ifindex);
- gboolean (*link_get_driver_info) (NMPlatform *,
+ char * (*link_get_physical_port_id) (NMPlatform *self, int ifindex);
+ guint (*link_get_dev_id) (NMPlatform *self, int ifindex);
+ gboolean (*link_get_wake_on_lan) (NMPlatform *self, int ifindex);
+ gboolean (*link_get_driver_info) (NMPlatform *self,
int ifindex,
char **out_driver_name,
char **out_driver_version,
char **out_fw_version);
- gboolean (*link_supports_carrier_detect) (NMPlatform *, int ifindex);
- gboolean (*link_supports_vlans) (NMPlatform *, int ifindex);
- gboolean (*link_supports_sriov) (NMPlatform *, int ifindex);
+ gboolean (*link_supports_carrier_detect) (NMPlatform *self, int ifindex);
+ gboolean (*link_supports_vlans) (NMPlatform *self, int ifindex);
+ gboolean (*link_supports_sriov) (NMPlatform *self, int ifindex);
- gboolean (*link_enslave) (NMPlatform *, int master, int slave);
- gboolean (*link_release) (NMPlatform *, int master, int slave);
+ gboolean (*link_enslave) (NMPlatform *self, int master, int slave);
+ gboolean (*link_release) (NMPlatform *self, int master, int slave);
- gboolean (*link_can_assume) (NMPlatform *, int ifindex);
+ gboolean (*link_can_assume) (NMPlatform *self, int ifindex);
int (*link_wireguard_change) (NMPlatform *self,
int ifindex,
@@ -1020,7 +1033,7 @@ typedef struct {
guint peers_len,
NMPlatformWireGuardChangeFlags change_flags);
- gboolean (*vlan_add) (NMPlatform *, const char *name, int parent, int vlanid, guint32 vlanflags, const NMPlatformLink **out_link);
+ gboolean (*vlan_add) (NMPlatform *self, const char *name, int parent, int vlanid, guint32 vlanflags, const NMPlatformLink **out_link);
gboolean (*link_vlan_change) (NMPlatform *self,
int ifindex,
NMVlanFlags flags_mask,
@@ -1031,81 +1044,79 @@ typedef struct {
gboolean egress_reset_all,
const NMVlanQosMapping *egress_map,
gsize n_egress_map);
- gboolean (*link_vxlan_add) (NMPlatform *,
+ gboolean (*link_vxlan_add) (NMPlatform *self,
const char *name,
const NMPlatformLnkVxlan *props,
const NMPlatformLink **out_link);
- gboolean (*link_gre_add) (NMPlatform *,
+ gboolean (*link_gre_add) (NMPlatform *self,
const char *name,
const NMPlatformLnkGre *props,
const NMPlatformLink **out_link);
- gboolean (*link_ip6tnl_add) (NMPlatform *,
+ gboolean (*link_ip6tnl_add) (NMPlatform *self,
const char *name,
const NMPlatformLnkIp6Tnl *props,
const NMPlatformLink **out_link);
- gboolean (*link_ip6gre_add) (NMPlatform *,
+ gboolean (*link_ip6gre_add) (NMPlatform *self,
const char *name,
const NMPlatformLnkIp6Tnl *props,
const NMPlatformLink **out_link);
- gboolean (*link_ipip_add) (NMPlatform *,
+ gboolean (*link_ipip_add) (NMPlatform *self,
const char *name,
const NMPlatformLnkIpIp *props,
const NMPlatformLink **out_link);
- gboolean (*link_macsec_add) (NMPlatform *,
+ gboolean (*link_macsec_add) (NMPlatform *self,
const char *name,
int parent,
const NMPlatformLnkMacsec *props,
const NMPlatformLink **out_link);
- gboolean (*link_macvlan_add) (NMPlatform *,
+ gboolean (*link_macvlan_add) (NMPlatform *self,
const char *name,
int parent,
const NMPlatformLnkMacvlan *props,
const NMPlatformLink **out_link);
- gboolean (*link_sit_add) (NMPlatform *,
+ gboolean (*link_sit_add) (NMPlatform *self,
const char *name,
const NMPlatformLnkSit *props,
const NMPlatformLink **out_link);
-
- gboolean (*link_tun_add) (NMPlatform *platform,
+ gboolean (*link_tun_add) (NMPlatform *self,
const char *name,
const NMPlatformLnkTun *props,
const NMPlatformLink **out_link,
int *out_fd);
-
- gboolean (*link_6lowpan_add) (NMPlatform *platform,
+ gboolean (*link_6lowpan_add) (NMPlatform *self,
const char *name,
int parent,
const NMPlatformLink **out_link);
- gboolean (*infiniband_partition_add) (NMPlatform *, int parent, int p_key, const NMPlatformLink **out_link);
- gboolean (*infiniband_partition_delete) (NMPlatform *, int parent, int p_key);
-
- gboolean (*wifi_get_capabilities) (NMPlatform *, int ifindex, NMDeviceWifiCapabilities *caps);
- gboolean (*wifi_get_bssid) (NMPlatform *, int ifindex, guint8 *bssid);
- guint32 (*wifi_get_frequency) (NMPlatform *, int ifindex);
- int (*wifi_get_quality) (NMPlatform *, int ifindex);
- guint32 (*wifi_get_rate) (NMPlatform *, int ifindex);
- NM80211Mode (*wifi_get_mode) (NMPlatform *, int ifindex);
- void (*wifi_set_mode) (NMPlatform *, int ifindex, NM80211Mode mode);
- void (*wifi_set_powersave) (NMPlatform *, int ifindex, guint32 powersave);
- guint32 (*wifi_find_frequency) (NMPlatform *, int ifindex, const guint32 *freqs);
- void (*wifi_indicate_addressing_running) (NMPlatform *, int ifindex, gboolean running);
- NMSettingWirelessWakeOnWLan (*wifi_get_wake_on_wlan) (NMPlatform *, int ifindex);
- gboolean (*wifi_set_wake_on_wlan) (NMPlatform *, int ifindex, NMSettingWirelessWakeOnWLan wowl);
-
- guint32 (*mesh_get_channel) (NMPlatform *, int ifindex);
- gboolean (*mesh_set_channel) (NMPlatform *, int ifindex, guint32 channel);
- gboolean (*mesh_set_ssid) (NMPlatform *, int ifindex, const guint8 *ssid, gsize len);
-
- guint16 (*wpan_get_pan_id) (NMPlatform *, int ifindex);
- gboolean (*wpan_set_pan_id) (NMPlatform *, int ifindex, guint16 pan_id);
- guint16 (*wpan_get_short_addr) (NMPlatform *, int ifindex);
- gboolean (*wpan_set_short_addr) (NMPlatform *, int ifindex, guint16 short_addr);
- gboolean (*wpan_set_channel) (NMPlatform *, int ifindex, guint8 page, guint8 channel);
-
- gboolean (*object_delete) (NMPlatform *, const NMPObject *obj);
-
- gboolean (*ip4_address_add) (NMPlatform *,
+ gboolean (*infiniband_partition_add) (NMPlatform *self, int parent, int p_key, const NMPlatformLink **out_link);
+ gboolean (*infiniband_partition_delete) (NMPlatform *self, int parent, int p_key);
+
+ gboolean (*wifi_get_capabilities) (NMPlatform *self, int ifindex, NMDeviceWifiCapabilities *caps);
+ gboolean (*wifi_get_bssid) (NMPlatform *self, int ifindex, guint8 *bssid);
+ guint32 (*wifi_get_frequency) (NMPlatform *self, int ifindex);
+ int (*wifi_get_quality) (NMPlatform *self, int ifindex);
+ guint32 (*wifi_get_rate) (NMPlatform *self, int ifindex);
+ NM80211Mode (*wifi_get_mode) (NMPlatform *self, int ifindex);
+ void (*wifi_set_mode) (NMPlatform *self, int ifindex, NM80211Mode mode);
+ void (*wifi_set_powersave) (NMPlatform *self, int ifindex, guint32 powersave);
+ guint32 (*wifi_find_frequency) (NMPlatform *self, int ifindex, const guint32 *freqs);
+ void (*wifi_indicate_addressing_running) (NMPlatform *self, int ifindex, gboolean running);
+ NMSettingWirelessWakeOnWLan (*wifi_get_wake_on_wlan) (NMPlatform *self, int ifindex);
+ gboolean (*wifi_set_wake_on_wlan) (NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan wowl);
+
+ guint32 (*mesh_get_channel) (NMPlatform *self, int ifindex);
+ gboolean (*mesh_set_channel) (NMPlatform *self, int ifindex, guint32 channel);
+ gboolean (*mesh_set_ssid) (NMPlatform *self, int ifindex, const guint8 *ssid, gsize len);
+
+ guint16 (*wpan_get_pan_id) (NMPlatform *self, int ifindex);
+ gboolean (*wpan_set_pan_id) (NMPlatform *self, int ifindex, guint16 pan_id);
+ guint16 (*wpan_get_short_addr) (NMPlatform *self, int ifindex);
+ gboolean (*wpan_set_short_addr) (NMPlatform *self, int ifindex, guint16 short_addr);
+ gboolean (*wpan_set_channel) (NMPlatform *self, int ifindex, guint8 page, guint8 channel);
+
+ gboolean (*object_delete) (NMPlatform *self, const NMPObject *obj);
+
+ gboolean (*ip4_address_add) (NMPlatform *self,
int ifindex,
in_addr_t address,
guint8 plen,
@@ -1114,7 +1125,7 @@ typedef struct {
guint32 preferred_lft,
guint32 flags,
const char *label);
- gboolean (*ip6_address_add) (NMPlatform *,
+ gboolean (*ip6_address_add) (NMPlatform *self,
int ifindex,
struct in6_addr address,
guint8 plen,
@@ -1122,10 +1133,10 @@ typedef struct {
guint32 lifetime,
guint32 preferred_lft,
guint32 flags);
- gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
- gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, guint8 plen);
+ gboolean (*ip4_address_delete) (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
+ gboolean (*ip6_address_delete) (NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen);
- int (*ip_route_add) (NMPlatform *,
+ int (*ip_route_add) (NMPlatform *self,
NMPNlmFlags flags,
int addr_family,
const NMPlatformIPRoute *route);
@@ -1268,7 +1279,7 @@ gboolean nm_platform_get_use_udev (NMPlatform *self);
gboolean nm_platform_get_log_with_ptr (NMPlatform *self);
NMPNetns *nm_platform_netns_get (NMPlatform *self);
-gboolean nm_platform_netns_push (NMPlatform *platform, NMPNetns **netns);
+gboolean nm_platform_netns_push (NMPlatform *self, NMPNetns **netns);
const char *nm_link_type_to_string (NMLinkType link_type);
@@ -1294,16 +1305,24 @@ const char *nm_link_type_to_string (NMLinkType link_type);
int nm_platform_sysctl_open_netdir (NMPlatform *self, int ifindex, char *out_ifname);
gboolean nm_platform_sysctl_set (NMPlatform *self, const char *pathid, int dirfd, const char *path, const char *value);
+void nm_platform_sysctl_set_async (NMPlatform *self,
+ const char *pathid,
+ int dirfd,
+ const char *path,
+ const char *const *values,
+ NMPlatformAsyncCallback callback,
+ gpointer data,
+ GCancellable *cancellable);
char *nm_platform_sysctl_get (NMPlatform *self, const char *pathid, int dirfd, const char *path);
gint32 nm_platform_sysctl_get_int32 (NMPlatform *self, const char *pathid, int dirfd, const char *path, gint32 fallback);
gint64 nm_platform_sysctl_get_int_checked (NMPlatform *self, const char *pathid, int dirfd, const char *path, guint base, gint64 min, gint64 max, gint64 fallback);
-char *nm_platform_sysctl_ip_conf_get (NMPlatform *platform,
+char *nm_platform_sysctl_ip_conf_get (NMPlatform *self,
int addr_family,
const char *ifname,
const char *property);
-gint64 nm_platform_sysctl_ip_conf_get_int_checked (NMPlatform *platform,
+gint64 nm_platform_sysctl_ip_conf_get_int_checked (NMPlatform *self,
int addr_family,
const char *ifname,
const char *property,
@@ -1312,13 +1331,13 @@ gint64 nm_platform_sysctl_ip_conf_get_int_checked (NMPlatform *platform,
gint64 max,
gint64 fallback);
-gboolean nm_platform_sysctl_ip_conf_set (NMPlatform *platform,
+gboolean nm_platform_sysctl_ip_conf_set (NMPlatform *self,
int addr_family,
const char *ifname,
const char *property,
const char *value);
-gboolean nm_platform_sysctl_ip_conf_set_int64 (NMPlatform *platform,
+gboolean nm_platform_sysctl_ip_conf_set_int64 (NMPlatform *self,
int addr_family,
const char *ifname,
const char *property,
@@ -1351,7 +1370,7 @@ gboolean nm_platform_link_set_netns (NMPlatform *self, int ifindex, int netns_fd
struct _NMDedupMultiHeadEntry;
struct _NMPLookup;
-const struct _NMDedupMultiHeadEntry *nm_platform_lookup (NMPlatform *platform,
+const struct _NMDedupMultiHeadEntry *nm_platform_lookup (NMPlatform *self,
const struct _NMPLookup *lookup);
gboolean nm_platform_lookup_predicate_routes_main (const NMPObject *obj,
@@ -1359,7 +1378,7 @@ gboolean nm_platform_lookup_predicate_routes_main (const NMPObject *obj,
gboolean nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *obj,
gpointer user_data);
-GPtrArray *nm_platform_lookup_clone (NMPlatform *platform,
+GPtrArray *nm_platform_lookup_clone (NMPlatform *self,
const struct _NMPLookup *lookup,
NMPObjectPredicateFunc predicate,
gpointer user_data);
@@ -1421,7 +1440,15 @@ gboolean nm_platform_link_get_permanent_address (NMPlatform *self, int ifindex,
int nm_platform_link_set_address (NMPlatform *self, int ifindex, const void *address, size_t length);
int nm_platform_link_set_mtu (NMPlatform *self, int ifindex, guint32 mtu);
gboolean nm_platform_link_set_name (NMPlatform *self, int ifindex, const char *name);
-gboolean nm_platform_link_set_sriov_params (NMPlatform *self, int ifindex, guint num_vfs, int autoprobe);
+
+void nm_platform_link_set_sriov_params_async (NMPlatform *self,
+ int ifindex,
+ guint num_vfs,
+ int autoprobe,
+ NMPlatformAsyncCallback callback,
+ gpointer callback_data,
+ GCancellable *cancellable);
+
gboolean nm_platform_link_set_sriov_vfs (NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs);
gboolean nm_platform_link_set_bridge_vlans (NMPlatform *self, int ifindex, gboolean on_master, const NMPlatformBridgeVlan *const *vlans);
@@ -1519,11 +1546,11 @@ guint32 nm_platform_mesh_get_channel (NMPlatform *self, int ifindex);
gboolean nm_platform_mesh_set_channel (NMPlatform *self, int ifindex, guint32 channel);
gboolean nm_platform_mesh_set_ssid (NMPlatform *self, int ifindex, const guint8 *ssid, gsize len);
-guint16 nm_platform_wpan_get_pan_id (NMPlatform *platform, int ifindex);
-gboolean nm_platform_wpan_set_pan_id (NMPlatform *platform, int ifindex, guint16 pan_id);
-guint16 nm_platform_wpan_get_short_addr (NMPlatform *platform, int ifindex);
-gboolean nm_platform_wpan_set_short_addr (NMPlatform *platform, int ifindex, guint16 short_addr);
-gboolean nm_platform_wpan_set_channel (NMPlatform *platform, int ifindex, guint8 page, guint8 channel);
+guint16 nm_platform_wpan_get_pan_id (NMPlatform *self, int ifindex);
+gboolean nm_platform_wpan_set_pan_id (NMPlatform *self, int ifindex, guint16 pan_id);
+guint16 nm_platform_wpan_get_short_addr (NMPlatform *self, int ifindex);
+gboolean nm_platform_wpan_set_short_addr (NMPlatform *self, int ifindex, guint16 short_addr);
+gboolean nm_platform_wpan_set_channel (NMPlatform *self, int ifindex, guint8 page, guint8 channel);
void nm_platform_ip4_address_set_addr (NMPlatformIP4Address *addr, in_addr_t address, guint8 plen);
const struct in6_addr *nm_platform_ip6_address_get_peer (const NMPlatformIP6Address *addr);
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index a2e3a6efb1..bff030bfd3 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -3015,6 +3015,92 @@ test_sysctl_netns_switch (void)
nmtstp_link_delete (PL, FALSE, ifindex, NULL, TRUE);
}
+static void
+sysctl_set_async_cb_assert_success (GError *error, gpointer data)
+{
+ g_assert_no_error (error);
+ g_main_loop_quit (data);
+}
+
+static void
+sysctl_set_async_cb_assert_failure (GError *error, gpointer data)
+{
+ g_assert (error);
+ g_main_loop_quit (data);
+}
+
+static void
+test_sysctl_set_async (void)
+{
+ NMPlatform *const PL = NM_PLATFORM_GET;
+ const char *const IFNAME = "nm-dummy-0";
+ const char *const PATH = "/proc/sys/net/ipv4/conf/nm-dummy-0/rp_filter";
+ gs_free GMainLoop *loop = NULL;
+ gs_unref_object GCancellable *cancellable = NULL;
+ int ifindex;
+
+ ifindex = nmtstp_link_dummy_add (PL, -1, IFNAME)->ifindex;
+ loop = g_main_loop_new (NULL, FALSE);
+ cancellable = g_cancellable_new ();
+
+ nm_platform_sysctl_set_async (PL,
+ NMP_SYSCTL_PATHID_ABSOLUTE (PATH),
+ (const char *[]) { "2", NULL},
+ sysctl_set_async_cb_assert_success,
+ loop,
+ cancellable);
+
+ if (!nmtst_main_loop_run (loop, 1000))
+ g_assert_not_reached ();
+
+ g_assert_cmpint (nm_platform_sysctl_get_int32 (PL, NMP_SYSCTL_PATHID_ABSOLUTE (PATH), -1),
+ ==,
+ 2);
+
+ nm_platform_sysctl_set_async (PL,
+ NMP_SYSCTL_PATHID_ABSOLUTE (PATH),
+ (const char *[]) { "2", "0", "1", "0", "1", NULL},
+ sysctl_set_async_cb_assert_success,
+ loop,
+ cancellable);
+
+ if (!nmtst_main_loop_run (loop, 2000))
+ g_assert_not_reached ();
+
+ g_assert_cmpint (nm_platform_sysctl_get_int32 (PL, NMP_SYSCTL_PATHID_ABSOLUTE (PATH), -1),
+ ==,
+ 1);
+
+ nmtstp_link_delete (NULL, -1, ifindex, IFNAME, TRUE);
+}
+
+static void
+test_sysctl_set_async_fail (void)
+{
+ NMPlatform *const PL = NM_PLATFORM_GET;
+ const char *const IFNAME = "nm-dummy-0";
+ const char *const PATH = "/proc/sys/net/ipv4/conf/nm-dummy-0/does-not-exist";
+ gs_free GMainLoop *loop = NULL;
+ gs_unref_object GCancellable *cancellable = NULL;
+ int ifindex;
+
+ ifindex = nmtstp_link_dummy_add (PL, -1, IFNAME)->ifindex;
+ loop = g_main_loop_new (NULL, FALSE);
+ cancellable = g_cancellable_new ();
+
+ nm_platform_sysctl_set_async (PL,
+ NMP_SYSCTL_PATHID_ABSOLUTE (PATH),
+ (const char *[]) { "2", NULL},
+ sysctl_set_async_cb_assert_failure,
+ loop,
+ cancellable);
+
+ if (!nmtst_main_loop_run (loop, 1000))
+ g_assert_not_reached ();
+
+ nmtstp_link_delete (NULL, -1, ifindex, IFNAME, TRUE);
+}
+
/*****************************************************************************/
static gpointer
@@ -3238,6 +3324,8 @@ _nmtstp_setup_tests (void)
g_test_add_func ("/general/sysctl/rename", test_sysctl_rename);
g_test_add_func ("/general/sysctl/netns-switch", test_sysctl_netns_switch);
+ g_test_add_func ("/general/sysctl/set-async", test_sysctl_set_async);
+ g_test_add_func ("/general/sysctl/set-async-fail", test_sysctl_set_async_fail);
g_test_add_func ("/link/ethtool/features/get", test_ethtool_features_get);
}