sriov: set the devlink's eswitch mode

Use the new property sriov.eswitch-mode to select between legacy SRIOV
and switchdev mode.
This commit is contained in:
Íñigo Huguet 2024-02-08 09:46:47 +01:00
parent c61c87f8a6
commit 837549ea94
5 changed files with 55 additions and 4 deletions

View file

@ -139,6 +139,7 @@ typedef struct {
gpointer callback_data; gpointer callback_data;
guint num_vfs; guint num_vfs;
NMOptionBool autoprobe; NMOptionBool autoprobe;
NMSriovEswitchMode eswitch_mode;
} SriovOp; } SriovOp;
typedef enum { typedef enum {
@ -7708,6 +7709,7 @@ sriov_op_start(NMDevice *self, SriovOp *op)
priv->ifindex, priv->ifindex,
op->num_vfs, op->num_vfs,
op->autoprobe, op->autoprobe,
(_NMSriovEswitchMode) op->eswitch_mode,
sriov_op_cb, sriov_op_cb,
op, op,
op->cancellable); op->cancellable);
@ -7771,6 +7773,7 @@ static void
sriov_op_queue(NMDevice *self, sriov_op_queue(NMDevice *self,
guint num_vfs, guint num_vfs,
NMOptionBool autoprobe, NMOptionBool autoprobe,
NMSriovEswitchMode eswitch_mode,
NMPlatformAsyncCallback callback, NMPlatformAsyncCallback callback,
gpointer callback_data) gpointer callback_data)
{ {
@ -7799,6 +7802,7 @@ sriov_op_queue(NMDevice *self,
*op = (SriovOp){ *op = (SriovOp){
.num_vfs = num_vfs, .num_vfs = num_vfs,
.autoprobe = autoprobe, .autoprobe = autoprobe,
.eswitch_mode = eswitch_mode,
.callback = callback, .callback = callback,
.callback_data = callback_data, .callback_data = callback_data,
}; };
@ -7823,7 +7827,12 @@ device_init_static_sriov_num_vfs(NMDevice *self)
-1, -1,
-1); -1);
if (num_vfs >= 0) 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, sriov_op_queue(self,
nm_setting_sriov_get_total_vfs(s_sriov), nm_setting_sriov_get_total_vfs(s_sriov),
NM_TERNARY_TO_OPTION_BOOL(autoprobe), NM_TERNARY_TO_OPTION_BOOL(autoprobe),
nm_setting_sriov_get_eswitch_mode(s_sriov),
sriov_params_cb, sriov_params_cb,
nm_utils_user_data_pack(self, g_steal_pointer(&plat_vfs))); nm_utils_user_data_pack(self, g_steal_pointer(&plat_vfs)));
priv->stage1_sriov_state = NM_DEVICE_STAGE_STATE_PENDING; 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, sriov_op_queue(self,
0, 0,
NM_OPTION_BOOL_TRUE, NM_OPTION_BOOL_TRUE,
NM_SRIOV_ESWITCH_MODE_PRESERVE,
sriov_reset_on_deactivate_cb, sriov_reset_on_deactivate_cb,
nm_utils_user_data_pack(self, GINT_TO_POINTER(reason))); 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 if (priv->ifindex > 0
&& (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV))) { && (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV))) {
priv->sriov_reset_pending++; 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; break;
} }
/* Schedule the transition to DISCONNECTED. The device can't transition /* Schedule the transition to DISCONNECTED. The device can't transition

View file

@ -277,6 +277,13 @@ typedef enum {
| _NM_VLAN_FLAG_LOOSE_BINDING | _NM_VLAN_FLAG_MVRP, | _NM_VLAN_FLAG_LOOSE_BINDING | _NM_VLAN_FLAG_MVRP,
} _NMVlanFlags; } _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 { typedef enum {

View file

@ -41,6 +41,7 @@
#include "libnm-platform/nm-netlink.h" #include "libnm-platform/nm-netlink.h"
#include "libnm-platform/nm-platform-utils.h" #include "libnm-platform/nm-platform-utils.h"
#include "libnm-platform/nmp-netns.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-wext.h"
#include "libnm-platform/wifi/nm-wifi-utils.h" #include "libnm-platform/wifi/nm-wifi-utils.h"
#include "libnm-platform/wpan/nm-wpan-utils.h" #include "libnm-platform/wpan/nm-wpan-utils.h"
@ -8900,10 +8901,12 @@ link_set_sriov_params_async(NMPlatform *platform,
int ifindex, int ifindex,
guint num_vfs, guint num_vfs,
NMOptionBool autoprobe, NMOptionBool autoprobe,
_NMSriovEswitchMode eswitch_mode,
NMPlatformAsyncCallback callback, NMPlatformAsyncCallback callback,
gpointer data, gpointer data,
GCancellable *cancellable) GCancellable *cancellable)
{ {
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform);
nm_auto_pop_netns NMPNetns *netns = NULL; nm_auto_pop_netns NMPNetns *netns = NULL;
gs_free_error GError *error = NULL; gs_free_error GError *error = NULL;
nm_auto_close int dirfd = -1; nm_auto_close int dirfd = -1;
@ -8914,6 +8917,8 @@ link_set_sriov_params_async(NMPlatform *platform,
gpointer packed; gpointer packed;
const char *values[3]; const char *values[3];
char buf[64]; char buf[64];
gs_free NMDevlink *devlink = NULL;
int current_eswitch_mode;
g_return_if_fail(callback || !data); g_return_if_fail(callback || !data);
g_return_if_fail(cancellable); g_return_if_fail(cancellable);
@ -8926,6 +8931,8 @@ link_set_sriov_params_async(NMPlatform *platform,
goto out_idle; goto out_idle;
} }
devlink = nm_devlink_new(platform, priv->sk_genl_sync, ifindex);
dirfd = nm_platform_sysctl_open_netdir(platform, ifindex, ifname); dirfd = nm_platform_sysctl_open_netdir(platform, ifindex, ifname);
if (!dirfd) { if (!dirfd) {
g_set_error_literal(&error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, "couldn't open netdir"); 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, 0,
G_MAXUINT, G_MAXUINT,
-1); -1);
current_autoprobe = nm_platform_sysctl_get_int_checked( current_autoprobe = nm_platform_sysctl_get_int_checked(
platform, platform,
NMP_SYSCTL_PATHID_NETDIR_A(dirfd, ifname, "device/sriov_drivers_autoprobe"), NMP_SYSCTL_PATHID_NETDIR_A(dirfd, ifname, "device/sriov_drivers_autoprobe"),
@ -8964,15 +8972,26 @@ link_set_sriov_params_async(NMPlatform *platform,
0, 0,
1, 1,
-1); -1);
if (current_autoprobe == -1 && errno == ENOENT) { if (current_autoprobe == -1 && errno == ENOENT) {
/* older kernel versions don't have this sysctl. Assume the value is /* older kernel versions don't have this sysctl. Assume the value is
* "1". */ * "1". */
current_autoprobe = 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 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; goto out_idle;
if (NM_IN_SET(autoprobe, NM_OPTION_BOOL_TRUE, NM_OPTION_BOOL_FALSE) 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; 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) if (current_num == 0 && num_vfs == 0)
goto out_idle; goto out_idle;

View file

@ -2024,6 +2024,7 @@ nm_platform_link_set_sriov_params_async(NMPlatform *self,
int ifindex, int ifindex,
guint num_vfs, guint num_vfs,
NMOptionBool autoprobe, NMOptionBool autoprobe,
_NMSriovEswitchMode eswitch_mode,
NMPlatformAsyncCallback callback, NMPlatformAsyncCallback callback,
gpointer callback_data, gpointer callback_data,
GCancellable *cancellable) GCancellable *cancellable)
@ -2037,6 +2038,7 @@ nm_platform_link_set_sriov_params_async(NMPlatform *self,
ifindex, ifindex,
num_vfs, num_vfs,
autoprobe, autoprobe,
eswitch_mode,
callback, callback,
callback_data, callback_data,
cancellable); cancellable);

View file

@ -1174,6 +1174,7 @@ typedef struct {
int ifindex, int ifindex,
guint num_vfs, guint num_vfs,
NMOptionBool autoprobe, NMOptionBool autoprobe,
_NMSriovEswitchMode eswitch_mode,
NMPlatformAsyncCallback callback, NMPlatformAsyncCallback callback,
gpointer callback_data, gpointer callback_data,
GCancellable *cancellable); GCancellable *cancellable);
@ -2037,6 +2038,7 @@ void nm_platform_link_set_sriov_params_async(NMPlatform *self,
int ifindex, int ifindex,
guint num_vfs, guint num_vfs,
NMOptionBool autoprobe, NMOptionBool autoprobe,
_NMSriovEswitchMode eswitch_mode,
NMPlatformAsyncCallback callback, NMPlatformAsyncCallback callback,
gpointer callback_data, gpointer callback_data,
GCancellable *cancellable); GCancellable *cancellable);