summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÍñigo Huguet <ihuguet@redhat.com>2024-02-08 09:46:47 +0100
committerÍñigo Huguet <ihuguet@redhat.com>2024-02-20 16:01:25 +0100
commit837549ea94b4e6d627b64e32e76a65b4b8b9c68d (patch)
tree1d0e6296c32ad775eaae57ce4dba64839fbffad7
parentc61c87f8a6b6e49a4912521aa91562f299f539a7 (diff)
sriov: set the devlink's eswitch mode
Use the new property sriov.eswitch-mode to select between legacy SRIOV and switchdev mode.
-rw-r--r--src/core/devices/nm-device.c20
-rw-r--r--src/libnm-base/nm-base.h7
-rw-r--r--src/libnm-platform/nm-linux-platform.c28
-rw-r--r--src/libnm-platform/nm-platform.c2
-rw-r--r--src/libnm-platform/nm-platform.h2
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);