summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2017-04-18 23:25:30 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2017-04-18 23:25:30 +0200
commit45e4cc67b33914bb960ceae78ae540739c411651 (patch)
treed8d6d4bc9548732ca68f043574c9cf1b8292756a
parent9e8218f99a2d5a7020703e0fbac1c7c0983930db (diff)
parent264624f91dce43859205faa20303ec2d9cddaa64 (diff)
merge: branch 'bg/sriov-numvfs-rh1398934'
https://bugzilla.redhat.com/show_bug.cgi?id=1398934
-rw-r--r--clients/cli/devices.c2
-rw-r--r--libnm-core/nm-dbus-interface.h3
-rw-r--r--man/NetworkManager.conf.xml10
-rw-r--r--src/devices/nm-device.c51
-rw-r--r--src/nm-config-data.h2
-rw-r--r--src/nm-config.h1
-rw-r--r--src/platform/nm-fake-platform.c24
-rw-r--r--src/platform/nm-linux-platform.c91
-rw-r--r--src/platform/nm-platform.c24
-rw-r--r--src/platform/nm-platform.h4
10 files changed, 200 insertions, 12 deletions
diff --git a/clients/cli/devices.c b/clients/cli/devices.c
index da5650f45e..2b9411e55b 100644
--- a/clients/cli/devices.c
+++ b/clients/cli/devices.c
@@ -95,6 +95,7 @@ const NmcMetaGenericInfo *const nmc_fields_dev_show_cap[] = {
NMC_META_GENERIC ("CARRIER-DETECT"), /* 1 */
NMC_META_GENERIC ("SPEED"), /* 2 */
NMC_META_GENERIC ("IS-SOFTWARE"), /* 3 */
+ NMC_META_GENERIC ("SRIOV"), /* 4 */
NULL,
};
#define NMC_FIELDS_DEV_SHOW_CAP_COMMON "NAME,CARRIER-DETECT,SPEED,IS-SOFTWARE"
@@ -1156,6 +1157,7 @@ show_device_info (NMDevice *device, NmCli *nmc)
set_val_strc (arr, 1, (caps & NM_DEVICE_CAP_CARRIER_DETECT) ? _("yes") : _("no"));
set_val_str (arr, 2, speed_str);
set_val_strc (arr, 3, (caps & NM_DEVICE_CAP_IS_SOFTWARE) ? _("yes") : _("no"));
+ set_val_strc (arr, 4, (caps & NM_DEVICE_CAP_SRIOV) ? _("yes") : _("no"));
g_ptr_array_add (out.output_data, arr);
print_data_prepare_width (out.output_data);
diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h
index 16318b78bc..8abc91bbf8 100644
--- a/libnm-core/nm-dbus-interface.h
+++ b/libnm-core/nm-dbus-interface.h
@@ -239,6 +239,7 @@ typedef enum {
* @NM_DEVICE_CAP_NM_SUPPORTED: NetworkManager supports this device
* @NM_DEVICE_CAP_CARRIER_DETECT: this device can indicate carrier status
* @NM_DEVICE_CAP_IS_SOFTWARE: this device is a software device
+ * @NM_DEVICE_CAP_SRIOV: this device supports single-root I/O virtualization
*
* General device capability flags.
**/
@@ -247,9 +248,9 @@ typedef enum { /*< flags >*/
NM_DEVICE_CAP_NM_SUPPORTED = 0x00000001,
NM_DEVICE_CAP_CARRIER_DETECT = 0x00000002,
NM_DEVICE_CAP_IS_SOFTWARE = 0x00000004,
+ NM_DEVICE_CAP_SRIOV = 0x00000008,
} NMDeviceCapabilities;
-
/**
* NMDeviceWifiCapabilities:
* @NM_WIFI_DEVICE_CAP_NONE: device has no encryption/authentication capabilities
diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml
index 1230347d83..658fd7c2d6 100644
--- a/man/NetworkManager.conf.xml
+++ b/man/NetworkManager.conf.xml
@@ -855,6 +855,16 @@ unmanaged=1
</para>
</listitem>
</varlistentry>
+ <varlistentry id="sriov-num-vfs">
+ <term><varname>sriov-num-vfs</varname></term>
+ <listitem>
+ <para>
+ Specify the number of virtual functions (VF) to enable
+ for a PCI physical device that supports single-root I/O
+ virtualization (SR-IOV).
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</para>
</refsect2>
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 9aeef9a87a..d656d8d7fc 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -296,7 +296,7 @@ typedef struct _NMDevicePrivate {
guint link_disconnected_id;
guint carrier_defer_id;
guint carrier_wait_id;
- gulong ignore_carrier_id;
+ gulong config_changed_id;
guint32 mtu;
guint32 ip6_mtu;
guint32 mtu_initial;
@@ -2815,17 +2815,41 @@ update_device_from_platform_link (NMDevice *self, const NMPlatformLink *plink)
}
static void
-config_changed_update_ignore_carrier (NMConfig *config,
- NMConfigData *config_data,
- NMConfigChangeFlags changes,
- NMConfigData *old_data,
- NMDevice *self)
+device_init_sriov_num_vfs (NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ gs_free char *value = NULL;
+ int num_vfs;
+
+ if ( priv->ifindex > 0
+ && nm_device_has_capability (self, NM_DEVICE_CAP_SRIOV)) {
+ value = nm_config_data_get_device_config (NM_CONFIG_GET_DATA,
+ "sriov-num-vfs",
+ 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_num_vfs (nm_device_get_platform (self),
+ priv->ifindex, num_vfs);
+ }
+ }
+}
+
+static void
+config_changed (NMConfig *config,
+ NMConfigData *config_data,
+ NMConfigChangeFlags changes,
+ NMConfigData *old_data,
+ NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
if ( priv->state <= NM_DEVICE_STATE_DISCONNECTED
|| 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_sriov_num_vfs (self);
}
static void
@@ -2934,6 +2958,9 @@ realize_start_setup (NMDevice *self,
if (nm_platform_check_support_user_ipv6ll (nm_device_get_platform (self)))
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))
+ capabilities |= NM_DEVICE_CAP_SRIOV;
}
if (klass->get_generic_capabilities)
@@ -2957,10 +2984,10 @@ realize_start_setup (NMDevice *self,
/* Note: initial hardware address must be read before calling get_ignore_carrier() */
config = nm_config_get ();
priv->ignore_carrier = nm_config_data_get_ignore_carrier (nm_config_get_data (config), self);
- if (!priv->ignore_carrier_id) {
- priv->ignore_carrier_id = g_signal_connect (config,
+ if (!priv->config_changed_id) {
+ priv->config_changed_id = g_signal_connect (config,
NM_CONFIG_SIGNAL_CONFIG_CHANGED,
- G_CALLBACK (config_changed_update_ignore_carrier),
+ G_CALLBACK (config_changed),
self);
}
@@ -2975,6 +3002,8 @@ realize_start_setup (NMDevice *self,
priv->carrier = TRUE;
}
+ device_init_sriov_num_vfs (self);
+
nm_assert (!priv->stats.timeout_id);
real_rate = _stats_refresh_rate_real (priv->stats.refresh_rate_ms);
if (real_rate)
@@ -3176,7 +3205,7 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self);
_notify (self, PROP_CAPABILITIES);
- nm_clear_g_signal_handler (nm_config_get (), &priv->ignore_carrier_id);
+ nm_clear_g_signal_handler (nm_config_get (), &priv->config_changed_id);
priv->real = FALSE;
_notify (self, PROP_REAL);
@@ -13701,7 +13730,7 @@ dispose (GObject *object)
arp_cleanup (self);
- nm_clear_g_signal_handler (nm_config_get (), &priv->ignore_carrier_id);
+ nm_clear_g_signal_handler (nm_config_get (), &priv->config_changed_id);
dispatcher_cleanup (self);
diff --git a/src/nm-config-data.h b/src/nm-config-data.h
index d7d14a61e9..98c667516c 100644
--- a/src/nm-config-data.h
+++ b/src/nm-config-data.h
@@ -171,6 +171,8 @@ const char *nm_config_data_get_rc_manager (const NMConfigData *self);
gboolean nm_config_data_get_ignore_carrier (const NMConfigData *self, NMDevice *device);
gboolean nm_config_data_get_assume_ipv6ll_only (const NMConfigData *self, NMDevice *device);
+int nm_config_data_get_sriov_num_vfs (const NMConfigData *self, NMDevice *device);
+
NMGlobalDnsConfig *nm_config_data_get_global_dns_config (const NMConfigData *self);
char *nm_config_data_get_connection_default (const NMConfigData *self,
diff --git a/src/nm-config.h b/src/nm-config.h
index f66d44baba..bfb4383a63 100644
--- a/src/nm-config.h
+++ b/src/nm-config.h
@@ -75,6 +75,7 @@
#define NM_CONFIG_KEYFILE_KEY_AUDIT "audit"
#define NM_CONFIG_KEYFILE_KEY_DEVICE_IGNORE_CARRIER "ignore-carrier"
+#define NM_CONFIG_KEYFILE_KEY_DEVICE_SRIOV_NUM_VFS "sriov-num-vfs"
#define NM_CONFIG_KEYFILE_KEYPREFIX_WAS ".was."
#define NM_CONFIG_KEYFILE_KEYPREFIX_SET ".set."
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index 42979ed209..38706f3796 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -573,6 +573,12 @@ link_set_mtu (NMPlatform *platform, int ifindex, guint32 mtu)
return !!device;
}
+static gboolean
+link_set_sriov_num_vfs (NMPlatform *platform, int ifindex, guint num_vfs)
+{
+ return TRUE;
+}
+
static const char *
link_get_udi (NMPlatform *platform, int ifindex)
{
@@ -633,6 +639,22 @@ link_supports_vlans (NMPlatform *platform, int ifindex)
}
static gboolean
+link_supports_sriov (NMPlatform *platform, int ifindex)
+{
+ NMFakePlatformLink *device = link_get (platform, ifindex);
+
+ if (!device)
+ return FALSE;
+
+ switch (device->link.type) {
+ case NM_LINK_TYPE_LOOPBACK:
+ return FALSE;
+ default:
+ return TRUE;
+ }
+}
+
+static gboolean
link_enslave (NMPlatform *platform, int master, int slave)
{
NMFakePlatformLink *device = link_get (platform, slave);
@@ -1470,11 +1492,13 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
platform_class->link_set_address = link_set_address;
platform_class->link_set_mtu = link_set_mtu;
+ platform_class->link_set_sriov_num_vfs = link_set_sriov_num_vfs;
platform_class->link_get_driver_info = link_get_driver_info;
platform_class->link_supports_carrier_detect = link_supports_carrier_detect;
platform_class->link_supports_vlans = link_supports_vlans;
+ platform_class->link_supports_sriov = link_supports_sriov;
platform_class->link_enslave = link_enslave;
platform_class->link_release = link_release;
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 251bc17f92..93264809be 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -4604,6 +4604,30 @@ link_supports_vlans (NMPlatform *platform, int ifindex)
return nmp_utils_ethtool_supports_vlans (ifindex);
}
+static gboolean
+link_supports_sriov (NMPlatform *platform, int ifindex)
+{
+ nm_auto_pop_netns NMPNetns *netns = NULL;
+ nm_auto_close int dirfd = -1;
+ char ifname[IFNAMSIZ];
+ int total = -1;
+
+ if (!nm_platform_netns_push (platform, &netns))
+ return FALSE;
+
+ dirfd = nm_platform_sysctl_open_netdir (platform, ifindex, ifname);
+ if (dirfd < 0)
+ return FALSE;
+
+ total = nm_platform_sysctl_get_int32 (platform,
+ NMP_SYSCTL_PATHID_NETDIR (dirfd,
+ ifname,
+ "device/sriov_totalvfs"),
+ -1);
+
+ return total > 0;
+}
+
static NMPlatformError
link_set_address (NMPlatform *platform, int ifindex, gconstpointer address, size_t length)
{
@@ -4695,6 +4719,71 @@ nla_put_failure:
g_return_val_if_reached (FALSE);
}
+static gboolean
+link_set_sriov_num_vfs (NMPlatform *platform, int ifindex, guint num_vfs)
+{
+ nm_auto_pop_netns NMPNetns *netns = NULL;
+ nm_auto_close int dirfd = -1;
+ int total, current;
+ char ifname[IFNAMSIZ];
+ char buf[64];
+
+ _LOGD ("link: change %d: num VFs: %u", ifindex, num_vfs);
+
+ if (!nm_platform_netns_push (platform, &netns))
+ return FALSE;
+
+ dirfd = nm_platform_sysctl_open_netdir (platform, ifindex, ifname);
+ if (!dirfd)
+ return FALSE;
+
+ total = nm_platform_sysctl_get_int32 (platform,
+ NMP_SYSCTL_PATHID_NETDIR (dirfd,
+ ifname,
+ "device/sriov_totalvfs"),
+ -1);
+ if (total < 1)
+ return FALSE;
+ if (num_vfs > total) {
+ _LOGW ("link: %d only supports %u VFs (requested %u)", ifindex, total, num_vfs);
+ num_vfs = total;
+ }
+
+ current = nm_platform_sysctl_get_int32 (platform,
+ NMP_SYSCTL_PATHID_NETDIR (dirfd,
+ ifname,
+ "device/sriov_numvfs"),
+ -1);
+ if (current == num_vfs)
+ return TRUE;
+
+ if (current != 0) {
+ /* We need to destroy all other VFs before changing the value */
+ if (!nm_platform_sysctl_set (NM_PLATFORM_GET,
+ NMP_SYSCTL_PATHID_NETDIR (dirfd,
+ ifname,
+ "device/sriov_numvfs"),
+ "0")) {
+ _LOGW ("link: couldn't set SR-IOV num_vfs to %d: %s", 0, strerror (errno));
+ return FALSE;
+ }
+ if (num_vfs == 0)
+ return TRUE;
+ }
+
+ /* Finally, set the desired value */
+ if (!nm_platform_sysctl_set (NM_PLATFORM_GET,
+ NMP_SYSCTL_PATHID_NETDIR (dirfd,
+ ifname,
+ "device/sriov_numvfs"),
+ nm_sprintf_buf (buf, "%d", num_vfs))) {
+ _LOGW ("link: couldn't set SR-IOV num_vfs to %d: %s", num_vfs, strerror (errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static char *
link_get_physical_port_id (NMPlatform *platform, int ifindex)
{
@@ -6845,6 +6934,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->link_set_address = link_set_address;
platform_class->link_get_permanent_address = link_get_permanent_address;
platform_class->link_set_mtu = link_set_mtu;
+ platform_class->link_set_sriov_num_vfs = link_set_sriov_num_vfs;
platform_class->link_get_physical_port_id = link_get_physical_port_id;
platform_class->link_get_dev_id = link_get_dev_id;
@@ -6853,6 +6943,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->link_supports_carrier_detect = link_supports_carrier_detect;
platform_class->link_supports_vlans = link_supports_vlans;
+ platform_class->link_supports_sriov = link_supports_sriov;
platform_class->link_enslave = link_enslave;
platform_class->link_release = link_release;
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 334b94d411..7ef22ad5ab 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -1179,6 +1179,30 @@ nm_platform_link_supports_vlans (NMPlatform *self, int ifindex)
return klass->link_supports_vlans (self, ifindex);
}
+gboolean
+nm_platform_link_supports_sriov (NMPlatform *self, int ifindex)
+{
+ _CHECK_SELF (self, klass, FALSE);
+
+ g_return_val_if_fail (ifindex >= 0, FALSE);
+
+ return klass->link_supports_sriov (self, ifindex);
+}
+
+gboolean
+nm_platform_link_set_sriov_num_vfs (NMPlatform *self, int ifindex, guint num_vfs)
+{
+ _CHECK_SELF (self, klass, FALSE);
+
+ g_return_val_if_fail (ifindex > 0, FALSE);
+
+ _LOGD ("link: setting %u VFs for %s (%d)",
+ num_vfs,
+ nm_strquote_a (25, nm_platform_link_get_name (self, ifindex)),
+ ifindex);
+ return klass->link_set_sriov_num_vfs (self, ifindex, num_vfs);
+}
+
/**
* nm_platform_link_set_up:
* @self: platform instance
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 202cbe5c59..f1679fd113 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -575,6 +575,7 @@ typedef struct {
size_t *length);
NMPlatformError (*link_set_address) (NMPlatform *, int ifindex, gconstpointer address, size_t length);
gboolean (*link_set_mtu) (NMPlatform *, int ifindex, guint32 mtu);
+ gboolean (*link_set_sriov_num_vfs) (NMPlatform *, int ifindex, guint num_vfs);
char * (*link_get_physical_port_id) (NMPlatform *, int ifindex);
guint (*link_get_dev_id) (NMPlatform *, int ifindex);
@@ -587,6 +588,7 @@ typedef struct {
gboolean (*link_supports_carrier_detect) (NMPlatform *, int ifindex);
gboolean (*link_supports_vlans) (NMPlatform *, int ifindex);
+ gboolean (*link_supports_sriov) (NMPlatform *, int ifindex);
gboolean (*link_enslave) (NMPlatform *, int master, int slave);
gboolean (*link_release) (NMPlatform *, int master, int slave);
@@ -825,6 +827,7 @@ gboolean nm_platform_link_set_ipv6_token (NMPlatform *self, int ifindex, NMUtils
gboolean nm_platform_link_get_permanent_address (NMPlatform *self, int ifindex, guint8 *buf, size_t *length);
NMPlatformError nm_platform_link_set_address (NMPlatform *self, int ifindex, const void *address, size_t length);
gboolean nm_platform_link_set_mtu (NMPlatform *self, int ifindex, guint32 mtu);
+gboolean nm_platform_link_set_sriov_num_vfs (NMPlatform *self, int ifindex, guint num_vfs);
char *nm_platform_link_get_physical_port_id (NMPlatform *self, int ifindex);
guint nm_platform_link_get_dev_id (NMPlatform *self, int ifindex);
@@ -837,6 +840,7 @@ gboolean nm_platform_link_get_driver_info (NMPlatform *self,
gboolean nm_platform_link_supports_carrier_detect (NMPlatform *self, int ifindex);
gboolean nm_platform_link_supports_vlans (NMPlatform *self, int ifindex);
+gboolean nm_platform_link_supports_sriov (NMPlatform *self, int ifindex);
gboolean nm_platform_link_enslave (NMPlatform *self, int master, int slave);
gboolean nm_platform_link_release (NMPlatform *self, int master, int slave);