From 1ba2b774023c7ca2f8d5094ad6278b9eefa59671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Thu, 8 Feb 2024 09:46:47 +0100 Subject: [PATCH] sriov: set the devlink's eswitch mode Use the new property sriov.eswitch-mode to select between legacy SRIOV and switchdev mode. (cherry picked from commit 837549ea94b4e6d627b64e32e76a65b4b8b9c68d) --- src/core/devices/nm-device.c | 20 ++++++++++++++++-- src/libnm-base/nm-base.h | 7 +++++++ src/libnm-platform/nm-linux-platform.c | 28 ++++++++++++++++++++++++-- src/libnm-platform/nm-platform.c | 2 ++ src/libnm-platform/nm-platform.h | 2 ++ 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 35011a3db9..07a763429e 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -139,6 +139,7 @@ typedef struct { gpointer callback_data; guint num_vfs; NMOptionBool autoprobe; + NMSriovEswitchMode eswitch_mode; } SriovOp; typedef enum { @@ -7708,6 +7709,7 @@ sriov_op_start(NMDevice *self, SriovOp *op) priv->ifindex, op->num_vfs, op->autoprobe, + (_NMSriovEswitchMode) op->eswitch_mode, sriov_op_cb, op, op->cancellable); @@ -7771,6 +7773,7 @@ static void sriov_op_queue(NMDevice *self, guint num_vfs, NMOptionBool autoprobe, + NMSriovEswitchMode eswitch_mode, NMPlatformAsyncCallback callback, gpointer callback_data) { @@ -7799,6 +7802,7 @@ sriov_op_queue(NMDevice *self, *op = (SriovOp){ .num_vfs = num_vfs, .autoprobe = autoprobe, + .eswitch_mode = eswitch_mode, .callback = callback, .callback_data = callback_data, }; @@ -7823,7 +7827,12 @@ device_init_static_sriov_num_vfs(NMDevice *self) -1, -1); if (num_vfs >= 0) - sriov_op_queue(self, num_vfs, NM_OPTION_BOOL_DEFAULT, NULL, NULL); + sriov_op_queue(self, + num_vfs, + NM_OPTION_BOOL_DEFAULT, + NM_SRIOV_ESWITCH_MODE_PRESERVE, + NULL, + NULL); } } @@ -10004,6 +10013,7 @@ activate_stage1_device_prepare(NMDevice *self) sriov_op_queue(self, nm_setting_sriov_get_total_vfs(s_sriov), NM_TERNARY_TO_OPTION_BOOL(autoprobe), + nm_setting_sriov_get_eswitch_mode(s_sriov), sriov_params_cb, nm_utils_user_data_pack(self, g_steal_pointer(&plat_vfs))); priv->stage1_sriov_state = NM_DEVICE_STAGE_STATE_PENDING; @@ -16720,6 +16730,7 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, sriov_op_queue(self, 0, NM_OPTION_BOOL_TRUE, + NM_SRIOV_ESWITCH_MODE_PRESERVE, sriov_reset_on_deactivate_cb, nm_utils_user_data_pack(self, GINT_TO_POINTER(reason))); } @@ -16769,7 +16780,12 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, if (priv->ifindex > 0 && (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV))) { priv->sriov_reset_pending++; - sriov_op_queue(self, 0, NM_OPTION_BOOL_TRUE, sriov_reset_on_failure_cb, self); + sriov_op_queue(self, + 0, + NM_OPTION_BOOL_TRUE, + NM_SRIOV_ESWITCH_MODE_PRESERVE, + sriov_reset_on_failure_cb, + self); break; } /* Schedule the transition to DISCONNECTED. The device can't transition diff --git a/src/libnm-base/nm-base.h b/src/libnm-base/nm-base.h index 34944408ca..c313bccf6e 100644 --- a/src/libnm-base/nm-base.h +++ b/src/libnm-base/nm-base.h @@ -277,6 +277,13 @@ typedef enum { | _NM_VLAN_FLAG_LOOSE_BINDING | _NM_VLAN_FLAG_MVRP, } _NMVlanFlags; +typedef enum { + /* Mirrors libnm's NMSriovEswitchMode */ + _NM_SRIOV_ESWITCH_MODE_PRESERVE = -1, + _NM_SRIOV_ESWITCH_MODE_LEGACY = 0, + _NM_SRIOV_ESWITCH_MODE_SWITCHDEV = 1, +} _NMSriovEswitchMode; + /*****************************************************************************/ typedef enum { diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index a70782808c..28eafc837e 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -41,6 +41,7 @@ #include "libnm-platform/nm-netlink.h" #include "libnm-platform/nm-platform-utils.h" #include "libnm-platform/nmp-netns.h" +#include "libnm-platform/devlink/nm-devlink.h" #include "libnm-platform/wifi/nm-wifi-utils-wext.h" #include "libnm-platform/wifi/nm-wifi-utils.h" #include "libnm-platform/wpan/nm-wpan-utils.h" @@ -8900,10 +8901,12 @@ link_set_sriov_params_async(NMPlatform *platform, int ifindex, guint num_vfs, NMOptionBool autoprobe, + _NMSriovEswitchMode eswitch_mode, NMPlatformAsyncCallback callback, gpointer data, GCancellable *cancellable) { + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); nm_auto_pop_netns NMPNetns *netns = NULL; gs_free_error GError *error = NULL; nm_auto_close int dirfd = -1; @@ -8914,6 +8917,8 @@ link_set_sriov_params_async(NMPlatform *platform, gpointer packed; const char *values[3]; char buf[64]; + gs_free NMDevlink *devlink = NULL; + int current_eswitch_mode; g_return_if_fail(callback || !data); g_return_if_fail(cancellable); @@ -8926,6 +8931,8 @@ link_set_sriov_params_async(NMPlatform *platform, goto out_idle; } + devlink = nm_devlink_new(platform, priv->sk_genl_sync, ifindex); + dirfd = nm_platform_sysctl_open_netdir(platform, ifindex, ifname); if (!dirfd) { g_set_error_literal(&error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, "couldn't open netdir"); @@ -8957,6 +8964,7 @@ link_set_sriov_params_async(NMPlatform *platform, 0, G_MAXUINT, -1); + current_autoprobe = nm_platform_sysctl_get_int_checked( platform, NMP_SYSCTL_PATHID_NETDIR_A(dirfd, ifname, "device/sriov_drivers_autoprobe"), @@ -8964,15 +8972,26 @@ link_set_sriov_params_async(NMPlatform *platform, 0, 1, -1); - if (current_autoprobe == -1 && errno == ENOENT) { /* older kernel versions don't have this sysctl. Assume the value is * "1". */ current_autoprobe = 1; } + current_eswitch_mode = nm_devlink_get_eswitch_mode(devlink, &error); + if (current_eswitch_mode < 0) { + /* We can proceed if eswith-mode is "preserve", otherwise propagate the error */ + if (eswitch_mode != _NM_SRIOV_ESWITCH_MODE_PRESERVE) + goto out_idle; + + _LOGD("%s", error->message); + g_clear_error(&error); + } + if (current_num == num_vfs - && (autoprobe == NM_OPTION_BOOL_DEFAULT || current_autoprobe == autoprobe)) + && (autoprobe == NM_OPTION_BOOL_DEFAULT || current_autoprobe == autoprobe) + && (eswitch_mode == _NM_SRIOV_ESWITCH_MODE_PRESERVE + || current_eswitch_mode == eswitch_mode)) goto out_idle; if (NM_IN_SET(autoprobe, NM_OPTION_BOOL_TRUE, NM_OPTION_BOOL_FALSE) @@ -8990,6 +9009,11 @@ link_set_sriov_params_async(NMPlatform *platform, goto out_idle; } + if (eswitch_mode != _NM_SRIOV_ESWITCH_MODE_PRESERVE && current_eswitch_mode != eswitch_mode) { + if (!nm_devlink_set_eswitch_mode(devlink, (enum devlink_eswitch_mode) eswitch_mode, &error)) + goto out_idle; + } + if (current_num == 0 && num_vfs == 0) goto out_idle; diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index acd8675ceb..7fb2a2e2e7 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -2024,6 +2024,7 @@ nm_platform_link_set_sriov_params_async(NMPlatform *self, int ifindex, guint num_vfs, NMOptionBool autoprobe, + _NMSriovEswitchMode eswitch_mode, NMPlatformAsyncCallback callback, gpointer callback_data, GCancellable *cancellable) @@ -2037,6 +2038,7 @@ nm_platform_link_set_sriov_params_async(NMPlatform *self, ifindex, num_vfs, autoprobe, + eswitch_mode, callback, callback_data, cancellable); diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index cc8d524bf6..8aba0e5c11 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -1174,6 +1174,7 @@ typedef struct { int ifindex, guint num_vfs, NMOptionBool autoprobe, + _NMSriovEswitchMode eswitch_mode, NMPlatformAsyncCallback callback, gpointer callback_data, GCancellable *cancellable); @@ -2037,6 +2038,7 @@ void nm_platform_link_set_sriov_params_async(NMPlatform *self, int ifindex, guint num_vfs, NMOptionBool autoprobe, + _NMSriovEswitchMode eswitch_mode, NMPlatformAsyncCallback callback, gpointer callback_data, GCancellable *cancellable);