libnm-core: add SR-IOV setting

Add a setting containing SR-IOV parameters.
This commit is contained in:
Beniamino Galvani 2018-05-25 12:05:24 +02:00
parent d6483592b8
commit a9b4532fa7
19 changed files with 2109 additions and 1 deletions

View file

@ -432,6 +432,7 @@ libnm_core_lib_h_pub_real = \
libnm-core/nm-setting-pppoe.h \
libnm-core/nm-setting-proxy.h \
libnm-core/nm-setting-serial.h \
libnm-core/nm-setting-sriov.h \
libnm-core/nm-setting-tc-config.h \
libnm-core/nm-setting-team-port.h \
libnm-core/nm-setting-team.h \
@ -502,6 +503,7 @@ libnm_core_lib_c_settings_real = \
libnm-core/nm-setting-pppoe.c \
libnm-core/nm-setting-proxy.c \
libnm-core/nm-setting-serial.c \
libnm-core/nm-setting-sriov.c \
libnm-core/nm-setting-tc-config.c \
libnm-core/nm-setting-team-port.c \
libnm-core/nm-setting-team.c \

View file

@ -323,6 +323,10 @@
#define DESCRIBE_DOC_NM_SETTING_SERIAL_PARITY N_("Parity setting of the serial port.")
#define DESCRIBE_DOC_NM_SETTING_SERIAL_SEND_DELAY N_("Time to delay between each byte sent to the modem, in microseconds.")
#define DESCRIBE_DOC_NM_SETTING_SERIAL_STOPBITS N_("Number of stop bits for communication on the serial port. Either 1 or 2. The 1 in \"8n1\" for example.")
#define DESCRIBE_DOC_NM_SETTING_SRIOV_AUTOPROBE_DRIVERS N_("Whether to autoprobe virtual functions by a compatible driver. If set to NM_TERNARY_TRUE (1), the kernel will try to bind VFs to a compatible driver and if this succeeds a new network interface will be instantiated for each VF. If set to NM_TERNARY_FALSE (0), VFs will not be claimed and no network interfaces will be created for them. When set to NM_TERNARY_DEFAULT (-1), the global default is used; in case the global default is unspecified it is assumed to be NM_TERNARY_TRUE (1).")
#define DESCRIBE_DOC_NM_SETTING_SRIOV_NAME N_("The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
#define DESCRIBE_DOC_NM_SETTING_SRIOV_TOTAL_VFS N_("The total number of virtual functions to create.")
#define DESCRIBE_DOC_NM_SETTING_SRIOV_VFS N_("Array of virtual function descriptors. Each VF descriptor is a dictionary mapping attribute names to GVariant values. The 'index' entry is mandatory for each VF. When represented as string a VF is in the form: \"INDEX [ATTR=VALUE[ ATTR=VALUE]...]\". for example: \"2 mac=00:11:22:33:44:55 spoof-check=true\". The \"vlans\" attribute is represented as a semicolor-separated list of VLAN descriptors, where each descriptor has the form \"ID[.PRIORITY[.PROTO]]\". PROTO can be either 'q' for 802.1Q (the default) or 'ad' for 802.1ad.")
#define DESCRIBE_DOC_NM_SETTING_TC_CONFIG_NAME N_("The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\".")
#define DESCRIBE_DOC_NM_SETTING_TC_CONFIG_QDISCS N_("Array of TC queueing disciplines.")
#define DESCRIBE_DOC_NM_SETTING_TC_CONFIG_TFILTERS N_("Array of TC traffic filters.")

View file

@ -220,6 +220,7 @@ print ("NetworkManager version " + client.get_version())]]></programlisting></in
<xi:include href="xml/nm-setting-ppp.xml"/>
<xi:include href="xml/nm-setting-proxy.xml"/>
<xi:include href="xml/nm-setting-serial.xml"/>
<xi:include href="xml/nm-setting-sriov.xml"/>
<xi:include href="xml/nm-setting-tc-config.xml"/>
<xi:include href="xml/nm-setting-team-port.xml"/>
<xi:include href="xml/nm-setting-team.xml"/>

View file

@ -34,6 +34,7 @@ libnm_core_headers = files(
'nm-setting-pppoe.h',
'nm-setting-proxy.h',
'nm-setting-serial.h',
'nm-setting-sriov.h',
'nm-setting-tc-config.h',
'nm-setting-team-port.h',
'nm-setting-team.h',
@ -86,6 +87,7 @@ libnm_core_settings_sources = files(
'nm-setting-pppoe.c',
'nm-setting-proxy.c',
'nm-setting-serial.c',
'nm-setting-sriov.c',
'nm-setting-tc-config.c',
'nm-setting-team-port.c',
'nm-setting-team.c',

View file

@ -1177,6 +1177,18 @@ _normalize_ip_tunnel_wired_setting (NMConnection *self, GHashTable *parameters)
return FALSE;
}
static gboolean
_normalize_sriov_vf_order (NMConnection *self, GHashTable *parameters)
{
NMSettingSriov *s_sriov;
s_sriov = nm_connection_get_setting_sriov (self);
if (!s_sriov)
return FALSE;
return _nm_setting_sriov_sort_vfs (s_sriov);
}
static gboolean
_normalize_required_settings (NMConnection *self, GHashTable *parameters)
{
@ -1523,6 +1535,7 @@ nm_connection_normalize (NMConnection *connection,
was_modified |= _normalize_bluetooth_type (connection, parameters);
was_modified |= _normalize_ovs_interface_type (connection, parameters);
was_modified |= _normalize_ip_tunnel_wired_setting (connection, parameters);
was_modified |= _normalize_sriov_vf_order (connection, parameters);
/* Verify anew. */
success = _nm_connection_verify (connection, error);
@ -2626,6 +2639,22 @@ nm_connection_get_setting_serial (NMConnection *connection)
return _connection_get_setting_check (connection, NM_TYPE_SETTING_SERIAL);
}
/**
* nm_connection_get_setting_sriov:
* @connection: the #NMConnection
*
* A shortcut to return any #NMSettingSriov the connection might contain.
*
* Returns: (transfer none): an #NMSettingSriov if the connection contains one, otherwise %NULL
*
* Since: 1.14
**/
NMSettingSriov *
nm_connection_get_setting_sriov (NMConnection *connection)
{
return _connection_get_setting_check (connection, NM_TYPE_SETTING_SRIOV);
}
/**
* nm_connection_get_setting_tc_config:
* @connection: the #NMConnection

View file

@ -231,6 +231,8 @@ NMSettingPppoe * nm_connection_get_setting_pppoe (NMConnec
NM_AVAILABLE_IN_1_6
NMSettingProxy * nm_connection_get_setting_proxy (NMConnection *connection);
NMSettingSerial * nm_connection_get_setting_serial (NMConnection *connection);
NM_AVAILABLE_IN_1_14
NMSettingSriov * nm_connection_get_setting_sriov (NMConnection *connection);
NM_AVAILABLE_IN_1_12
NMSettingTCConfig * nm_connection_get_setting_tc_config (NMConnection *connection);
NMSettingTun * nm_connection_get_setting_tun (NMConnection *connection);

View file

@ -65,6 +65,7 @@
#include "nm-setting-ppp.h"
#include "nm-setting-pppoe.h"
#include "nm-setting-serial.h"
#include "nm-setting-sriov.h"
#include "nm-setting-tc-config.h"
#include "nm-setting-team-port.h"
#include "nm-setting-team.h"
@ -226,6 +227,9 @@ gboolean _nm_ip_route_attribute_validate_all (const NMIPRoute *route);
const char **_nm_ip_route_get_attribute_names (const NMIPRoute *route, gboolean sorted, guint *out_length);
GHashTable *_nm_ip_route_get_attributes_direct (NMIPRoute *route);
NMSriovVF *_nm_utils_sriov_vf_from_strparts (const char *index, const char *detail, GError **error);
gboolean _nm_sriov_vf_attribute_validate_all (const NMSriovVF *vf, GError **error);
static inline void
_nm_auto_ip_route_unref (NMIPRoute **v)
{
@ -513,4 +517,7 @@ _nm_connection_type_is_master (const char *type)
gboolean _nm_utils_dhcp_duid_valid (const char *duid, GBytes **out_duid_bin);
/*****************************************************************************/
gboolean _nm_setting_sriov_sort_vfs (NMSettingSriov *setting);
#endif

View file

@ -58,6 +58,7 @@ typedef struct _NMSettingOvsPort NMSettingOvsPort;
typedef struct _NMSettingPpp NMSettingPpp;
typedef struct _NMSettingPppoe NMSettingPppoe;
typedef struct _NMSettingSerial NMSettingSerial;
typedef struct _NMSettingSriov NMSettingSriov;
typedef struct _NMSettingTCConfig NMSettingTCConfig;
typedef struct _NMSettingTeam NMSettingTeam;
typedef struct _NMSettingTeamPort NMSettingTeamPort;

View file

@ -118,6 +118,49 @@ setting_alias_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *k
}
}
static void
sriov_vfs_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
{
const char *setting_name = nm_setting_get_name (setting);
gs_unref_ptrarray GPtrArray *vfs = NULL;
gs_strfreev char **keys = NULL;
gsize n_keys = 0;
int i;
keys = nm_keyfile_plugin_kf_get_keys (info->keyfile, setting_name, &n_keys, NULL);
if (!keys || n_keys == 0)
return;
vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref);
for (i = 0; i < n_keys; i++) {
gs_free char *value = NULL;
NMSriovVF *vf;
const char *rest;
if (!g_str_has_prefix (keys[i], "vf."))
continue;
rest = &keys[i][3];
if (!NM_STRCHAR_ALL (rest, ch, g_ascii_isdigit (ch)))
continue;
value = nm_keyfile_plugin_kf_get_string (info->keyfile,
setting_name,
keys[i],
NULL);
vf = _nm_utils_sriov_vf_from_strparts (rest, value, NULL);
if (vf)
g_ptr_array_add (vfs, vf);
}
g_object_set (G_OBJECT (setting),
key, vfs,
NULL);
}
static void
read_array_of_uint (GKeyFile *file,
NMSetting *setting,
@ -1509,6 +1552,37 @@ setting_alias_writer (KeyfileWriterInfo *info,
alias ?: str);
}
static void
sriov_vfs_writer (KeyfileWriterInfo *info,
NMSetting *setting,
const char *key,
const GValue *value)
{
GPtrArray *vfs;
guint i;
vfs = g_value_get_boxed (value);
if (!vfs)
return;
for (i = 0; i < vfs->len; i++) {
const NMSriovVF *vf = vfs->pdata[i];
gs_free char *kf_value = NULL;
char kf_key[32];
kf_value = nm_utils_sriov_vf_to_str (vf, TRUE, NULL);
if (!kf_value)
continue;
nm_sprintf_buf (kf_key, "vf.%u", nm_sriov_vf_get_index (vf));
nm_keyfile_plugin_kf_set_string (info->keyfile,
nm_setting_get_name (setting),
kf_key,
kf_value);
}
}
static void
write_array_of_uint (GKeyFile *file,
NMSetting *setting,
@ -2189,6 +2263,15 @@ static const ParseInfoSetting parse_infos[] = {
),
),
),
PARSE_INFO_SETTING (NM_SETTING_SRIOV_SETTING_NAME,
PARSE_INFO_PROPERTIES (
PARSE_INFO_PROPERTY (NM_SETTING_SRIOV_VFS,
.parser_no_check_key = TRUE,
.parser = sriov_vfs_parser,
.writer = sriov_vfs_writer,
),
),
),
PARSE_INFO_SETTING (NM_SETTING_TC_CONFIG_SETTING_NAME,
PARSE_INFO_PROPERTIES (
PARSE_INFO_PROPERTY (NM_SETTING_TC_CONFIG_QDISCS,

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,123 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*
* Copyright 2018 Red Hat, Inc.
*/
#ifndef NM_SETTING_SRIOV_H
#define NM_SETTING_SRIOV_H
#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
#error "Only <NetworkManager.h> can be included directly."
#endif
#include "nm-setting.h"
G_BEGIN_DECLS
#define NM_TYPE_SETTING_SRIOV (nm_setting_sriov_get_type ())
#define NM_SETTING_SRIOV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_SRIOV, NMSettingSriov))
#define NM_SETTING_SRIOV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_SRIOV, NMSettingSriovClass))
#define NM_IS_SETTING_SRIOV(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_SRIOV))
#define NM_IS_SETTING_SRIOV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_SRIOV))
#define NM_SETTING_SRIOV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_SRIOV, NMSettingSriovClass))
#define NM_SETTING_SRIOV_SETTING_NAME "sriov"
#define NM_SETTING_SRIOV_TOTAL_VFS "total-vfs"
#define NM_SETTING_SRIOV_VFS "vfs"
#define NM_SETTING_SRIOV_AUTOPROBE_DRIVERS "autoprobe-drivers"
#define NM_SRIOV_VF_ATTRIBUTE_MAC "mac"
#define NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK "spoof-check"
#define NM_SRIOV_VF_ATTRIBUTE_TRUST "trust"
#define NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE "min-tx-rate"
#define NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE "max-tx-rate"
typedef struct _NMSettingSriovClass NMSettingSriovClass;
typedef struct _NMSriovVF NMSriovVF;
/**
* NMSriovVFVlanProtocol:
* @NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q: use 802.1Q
* @NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD: use 802.1ad
*
* #NMSriovVFVlanProtocol indicates the VLAN protocol to use.
*
* Since: 1.14
*/
typedef enum {
NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q = 0,
NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD = 1,
} NMSriovVFVlanProtocol;
NM_AVAILABLE_IN_1_14
GType nm_setting_sriov_get_type (void);
NM_AVAILABLE_IN_1_14
NMSetting *nm_setting_sriov_new (void);
NM_AVAILABLE_IN_1_14
guint nm_setting_sriov_get_total_vfs (NMSettingSriov *setting);
NM_AVAILABLE_IN_1_14
guint nm_setting_sriov_get_num_vfs (NMSettingSriov *setting);
NM_AVAILABLE_IN_1_14
NMSriovVF *nm_setting_sriov_get_vf (NMSettingSriov *setting, guint idx);
NM_AVAILABLE_IN_1_14
void nm_setting_sriov_add_vf (NMSettingSriov *setting, NMSriovVF *vf);
NM_AVAILABLE_IN_1_14
void nm_setting_sriov_remove_vf (NMSettingSriov *setting, guint idx);
NM_AVAILABLE_IN_1_14
gboolean nm_setting_sriov_remove_vf_by_index (NMSettingSriov *setting, guint index);
NM_AVAILABLE_IN_1_14
void nm_setting_sriov_clear_vfs (NMSettingSriov *setting);
NM_AVAILABLE_IN_1_14
NMTernary nm_setting_sriov_get_autoprobe_drivers (NMSettingSriov *setting);
NM_AVAILABLE_IN_1_14
gboolean nm_sriov_vf_add_vlan (NMSriovVF *vf, guint vlan_id);
NM_AVAILABLE_IN_1_14
gboolean nm_sriov_vf_remove_vlan (NMSriovVF *vf, guint vlan_id);
NM_AVAILABLE_IN_1_14
const guint *nm_sriov_vf_get_vlan_ids (const NMSriovVF *vf, guint *length);
NM_AVAILABLE_IN_1_14
void nm_sriov_vf_set_vlan_qos (NMSriovVF *vf, guint vlan_id, guint32 qos);
NM_AVAILABLE_IN_1_14
void nm_sriov_vf_set_vlan_protocol (NMSriovVF *vf, guint vlan_id, NMSriovVFVlanProtocol protocol);
NM_AVAILABLE_IN_1_14
guint32 nm_sriov_vf_get_vlan_qos (const NMSriovVF *vf, guint vlan_id);
NM_AVAILABLE_IN_1_14
NMSriovVFVlanProtocol nm_sriov_vf_get_vlan_protocol (const NMSriovVF *vf, guint vlan_id);
NM_AVAILABLE_IN_1_14
GType nm_sriov_vf_get_type (void);
NM_AVAILABLE_IN_1_14
NMSriovVF *nm_sriov_vf_new (guint index);
NM_AVAILABLE_IN_1_14
void nm_sriov_vf_ref (NMSriovVF *vf);
NM_AVAILABLE_IN_1_14
void nm_sriov_vf_unref (NMSriovVF *vf);
NM_AVAILABLE_IN_1_14
gboolean nm_sriov_vf_equal (const NMSriovVF *vf, const NMSriovVF *other);
NM_AVAILABLE_IN_1_14
NMSriovVF *nm_sriov_vf_dup (const NMSriovVF *vf);
NM_AVAILABLE_IN_1_14
guint nm_sriov_vf_get_index (const NMSriovVF *vf);
NM_AVAILABLE_IN_1_14
void nm_sriov_vf_set_attribute (NMSriovVF *vf, const char *name, GVariant *value);
NM_AVAILABLE_IN_1_14
const char **nm_sriov_vf_get_attribute_names (const NMSriovVF *vf);
NM_AVAILABLE_IN_1_14
GVariant *nm_sriov_vf_get_attribute (const NMSriovVF *vf, const char *name);
NM_AVAILABLE_IN_1_14
gboolean nm_sriov_vf_attribute_validate (const char *name, GVariant *value, gboolean *known, GError **error);
G_END_DECLS
#endif /* NM_SETTING_SRIOV_H */

View file

@ -132,6 +132,7 @@ _register_settings_ensure_types (void)
ENSURE_TYPE (nm_setting_pppoe_get_type);
ENSURE_TYPE (nm_setting_proxy_get_type);
ENSURE_TYPE (nm_setting_serial_get_type);
ENSURE_TYPE (nm_setting_sriov_get_type);
ENSURE_TYPE (nm_setting_tc_config_get_type);
ENSURE_TYPE (nm_setting_team_get_type);
ENSURE_TYPE (nm_setting_team_port_get_type);

View file

@ -88,6 +88,7 @@ void _nm_utils_format_variant_attributes_full (GString *str,
guint num_values,
char attr_separator,
char key_value_separator);
gboolean _nm_sriov_vf_parse_vlans (NMSriovVF *vf, const char *str, GError **error);
/* JSON to GValue conversion macros */

View file

@ -2657,6 +2657,249 @@ nm_utils_tc_tfilter_from_str (const char *str, GError **error)
/*****************************************************************************/
extern const NMVariantAttributeSpec *const _nm_sriov_vf_attribute_spec[];
/**
* nm_utils_sriov_vf_to_str:
* @vf: the %NMSriovVF
* @omit_index: if %TRUE, the VF index will be omitted from output string
* @error: (out) (allow-none): location to store the error on failure
*
* Converts a SR-IOV virtual function object to its string representation.
*
* Returns: a newly allocated string or %NULL on error
*
* Since: 1.14
*/
char *
nm_utils_sriov_vf_to_str (const NMSriovVF *vf, gboolean omit_index, GError **error)
{
gs_free NMUtilsNamedValue *values = NULL;
gs_free const char **names = NULL;
const guint *vlan_ids;
guint num_vlans, num_attrs;
guint i;
GString *str;
str = g_string_new ("");
if (!omit_index)
g_string_append_printf (str, "%u", nm_sriov_vf_get_index (vf));
names = nm_sriov_vf_get_attribute_names (vf);
num_attrs = names ? g_strv_length ((char **) names) : 0;
values = g_new0 (NMUtilsNamedValue, num_attrs);
for (i = 0; i < num_attrs; i++) {
values[i].name = names[i];
values[i].value_ptr = nm_sriov_vf_get_attribute (vf, names[i]);
}
if (num_attrs > 0) {
if (!omit_index)
g_string_append_c (str, ' ');
_nm_utils_format_variant_attributes_full (str, values, num_attrs, ' ', '=');
}
vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num_vlans);
if (num_vlans != 0) {
g_string_append (str, " vlans");
for (i = 0; i < num_vlans; i++) {
guint32 qos;
NMSriovVFVlanProtocol protocol;
qos = nm_sriov_vf_get_vlan_qos (vf, vlan_ids[i]);
protocol = nm_sriov_vf_get_vlan_protocol (vf, vlan_ids[i]);
g_string_append_c (str, i == 0 ? '=' : ';');
g_string_append_printf (str, "%u", vlan_ids[i]);
if ( qos != 0
|| protocol != NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q) {
g_string_append_printf (str,
".%u%s",
(unsigned) qos,
protocol == NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q ? "" : ".ad");
}
}
}
return g_string_free (str, FALSE);
}
gboolean
_nm_sriov_vf_parse_vlans (NMSriovVF *vf, const char *str, GError **error)
{
gs_free const char **vlans = NULL;
guint i;
vlans = nm_utils_strsplit_set (str, ";");
if (!vlans) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_FAILED,
"empty VF VLAN");
return FALSE;
}
for (i = 0; vlans[i]; i++) {
gs_strfreev char **params = NULL;
guint id = G_MAXUINT;
gint64 qos = -1;
/* we accept leading/trailing whitespace around vlans[1]. Hence
* the nm_str_skip_leading_spaces() and g_strchomp() below.
*
* However, we don't accept any whitespace inside the specifier.
* Hence the NM_STRCHAR_ALL() checks. */
params = g_strsplit (nm_str_skip_leading_spaces (vlans[i]), ".", 3);
if (!params || !params[0] || *params[0] == '\0') {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_FAILED,
"empty VF VLAN");
return FALSE;
}
if (!params[1])
g_strchomp (params[0]);
if (NM_STRCHAR_ALL (params[0], ch, ch == 'x' || g_ascii_isdigit (ch)))
id = _nm_utils_ascii_str_to_int64 (params[0], 0, 0, 4095, G_MAXUINT);
if (id == G_MAXUINT) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_FAILED,
"invalid VF VLAN id '%s'",
params[0]);
return FALSE;
}
if (!nm_sriov_vf_add_vlan (vf, id)) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_FAILED,
"duplicate VLAN id %u",
id);
return FALSE;
}
if (!params[1])
continue;
if (!params[2])
g_strchomp (params[1]);
if (NM_STRCHAR_ALL (params[1], ch, ch == 'x' || g_ascii_isdigit (ch)))
qos = _nm_utils_ascii_str_to_int64 (params[1], 0, 0, G_MAXUINT32, -1);
if (qos == -1) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_FAILED,
"invalid VF VLAN QoS '%s'",
params[1]);
return FALSE;
}
nm_sriov_vf_set_vlan_qos (vf, id, qos);
if (!params[2])
continue;
g_strchomp (params[2]);
if (nm_streq (params[2], "ad"))
nm_sriov_vf_set_vlan_protocol (vf, id, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD);
else if (nm_streq (params[2], "q"))
nm_sriov_vf_set_vlan_protocol (vf, id, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
else {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_FAILED,
"invalid VF VLAN protocol '%s'",
params[2]);
return FALSE;
}
}
return TRUE;
}
/**
* nm_utils_sriov_vf_from_str:
* @str: the input string
* @error: (out) (allow-none): location to store the error on failure
*
* Converts a string to a SR-IOV virtual function object.
*
* Returns: (transfer full): the virtual function object
*
* Since: 1.14
*/
NMSriovVF *
nm_utils_sriov_vf_from_str (const char *str, GError **error)
{
gs_free char *index_free = NULL;
const char *detail;
g_return_val_if_fail (str, NULL);
g_return_val_if_fail (!error || !*error, NULL);
while (*str == ' ')
str++;
detail = strchr (str, ' ');
if (detail) {
index_free = g_strndup (str, detail - str);
str = index_free;
detail++;
}
return _nm_utils_sriov_vf_from_strparts (str, detail, error);
}
NMSriovVF *
_nm_utils_sriov_vf_from_strparts (const char *index, const char *detail, GError **error)
{
NMSriovVF *vf;
guint32 n_index;
GHashTableIter iter;
char *key;
GVariant *variant;
gs_unref_hashtable GHashTable *ht = NULL;
n_index = _nm_utils_ascii_str_to_int64 (index, 10, 0, G_MAXUINT32, 0);
if (errno) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_FAILED,
"invalid index");
return NULL;
}
vf = nm_sriov_vf_new (n_index);
if (detail) {
ht = nm_utils_parse_variant_attributes (detail, ' ', '=', TRUE, _nm_sriov_vf_attribute_spec, error);
if (!ht) {
nm_sriov_vf_unref (vf);
return NULL;
}
if ((variant = g_hash_table_lookup (ht, "vlans"))) {
if (!_nm_sriov_vf_parse_vlans (vf, g_variant_get_string (variant, NULL), error)) {
nm_sriov_vf_unref (vf);
return NULL;
}
g_hash_table_remove (ht, "vlans");
}
g_hash_table_iter_init (&iter, ht);
while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &variant))
nm_sriov_vf_set_attribute (vf, key, g_variant_ref_sink (variant));
}
return vf;
}
/*****************************************************************************/
/**
* nm_utils_uuid_generate_buf_:
* @buf: input buffer, must contain at least 37 bytes

View file

@ -34,8 +34,9 @@
#include <linux/if_infiniband.h>
#include "nm-core-enum-types.h"
#include "nm-setting-wireless-security.h"
#include "nm-setting-sriov.h"
#include "nm-setting-tc-config.h"
#include "nm-setting-wireless-security.h"
G_BEGIN_DECLS
@ -250,9 +251,17 @@ char *nm_utils_tc_tfilter_to_str (NMTCTfilter *tfilter, GError **error
/*****************************************************************************/
NM_AVAILABLE_IN_1_14
char *nm_utils_sriov_vf_to_str (const NMSriovVF *vf, gboolean omit_index, GError **error);
NM_AVAILABLE_IN_1_14
NMSriovVF *nm_utils_sriov_vf_from_str (const char *str, GError **error);
/*****************************************************************************/
NM_AVAILABLE_IN_1_12
gint64 nm_utils_get_timestamp_msec (void);
G_END_DECLS
#endif /* __NM_UTILS_H__ */

View file

@ -23,6 +23,8 @@
#include <string.h>
#include "nm-utils.h"
#include "nm-utils-private.h"
#include "nm-core-internal.h"
#include "nm-setting-8021x.h"
#include "nm-setting-bond.h"
#include "nm-setting-dcb.h"
@ -1262,6 +1264,234 @@ test_team_port_full_config (void)
/*****************************************************************************/
static void
test_sriov_vf (void)
{
NMSriovVF *vf1, *vf2;
GError *error = NULL;
char *str;
vf1 = nm_sriov_vf_new (1);
nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MAC, g_variant_new_string ("00:11:22:33:44:55"));
nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean (TRUE));
nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean (FALSE));
nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, g_variant_new_uint32 (100));
nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, g_variant_new_uint32 (500));
str = nm_utils_sriov_vf_to_str (vf1, FALSE, &error);
g_assert_no_error (error);
g_assert_cmpstr (str, ==, "1 mac=00:11:22:33:44:55 max-tx-rate=500 min-tx-rate=100 spoof-check=true trust=false");
g_free (str);
vf2 = nm_utils_sriov_vf_from_str (" 1 mac=00:11:22:33:44:55 max-tx-rate=500 min-tx-rate=100", &error);
nmtst_assert_success (vf2, error);
nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean (FALSE));
nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean (TRUE));
nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean (TRUE));
nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, NULL);
nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean (FALSE));
g_assert (nm_sriov_vf_equal (vf1, vf2));
nm_sriov_vf_unref (vf1);
nm_sriov_vf_unref (vf2);
}
static void
test_sriov_vf_dup (void)
{
NMSriovVF *vf1, *vf2;
vf1 = nm_sriov_vf_new (1);
nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MAC, g_variant_new_string ("foobar"));
nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean (FALSE));
nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, g_variant_new_uint32 (10));
nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, g_variant_new_uint32 (1000));
nm_sriov_vf_add_vlan (vf1, 80);
nm_sriov_vf_set_vlan_qos (vf1, 80, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD);
vf2 = nm_sriov_vf_dup (vf1);
g_assert (nm_sriov_vf_equal (vf1, vf2));
nm_sriov_vf_unref (vf1);
nm_sriov_vf_unref (vf2);
}
static void
test_sriov_vf_vlan (void)
{
NMSriovVF *vf;
const guint *vlan_ids;
guint num;
GError *error = NULL;
gs_free char *str = NULL;
vf = nm_sriov_vf_new (19);
nm_sriov_vf_set_attribute (vf, NM_SRIOV_VF_ATTRIBUTE_MAC, g_variant_new_string ("00:11:22"));
g_assert (nm_sriov_vf_add_vlan (vf, 80));
g_assert (!nm_sriov_vf_add_vlan (vf, 80));
g_assert (nm_sriov_vf_add_vlan (vf, 82));
g_assert (nm_sriov_vf_add_vlan (vf, 83));
g_assert (nm_sriov_vf_add_vlan (vf, 81));
g_assert (!nm_sriov_vf_remove_vlan (vf, 100));
g_assert (nm_sriov_vf_remove_vlan (vf, 82));
nm_sriov_vf_set_vlan_qos (vf, 81, 0xabba);
nm_sriov_vf_set_vlan_protocol (vf, 81, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD);
vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num);
g_assert (vlan_ids);
g_assert_cmpint (num, ==, 3);
g_assert_cmpint (vlan_ids[0], ==, 80);
g_assert_cmpint (vlan_ids[1], ==, 81);
g_assert_cmpint (vlan_ids[2], ==, 83);
g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 80), ==, 0x0);
g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 80), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 81), ==, 0xabba);
g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 81), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD);
nm_sriov_vf_unref (vf);
vf = nm_utils_sriov_vf_from_str ("20 spoof-check=false vlans=85.0.q;4000.0x20.ad;81.10;83", &error);
nmtst_assert_success (vf, error);
vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num);
g_assert (vlan_ids);
g_assert_cmpint (num, ==, 4);
g_assert_cmpint (vlan_ids[0], ==, 81);
g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 81), ==, 10);
g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 81), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
g_assert_cmpint (vlan_ids[1], ==, 83);
g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 83), ==, 0);
g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 83), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
g_assert_cmpint (vlan_ids[2], ==, 85);
g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 85), ==, 0);
g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 85), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
g_assert_cmpint (vlan_ids[3], ==, 4000);
g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 4000), ==, 0x20);
g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 4000), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD);
str = nm_utils_sriov_vf_to_str (vf, FALSE, &error);
nmtst_assert_success (str, error);
g_assert_cmpstr (str, ==, "20 spoof-check=false vlans=81.10;83;85;4000.32.ad");
nm_sriov_vf_unref (vf);
}
static void
test_sriov_setting (void)
{
gs_unref_object NMConnection *con = NULL;
NMSettingConnection *s_con;
NMSettingSriov *s_sriov = NULL;
NMSriovVF *vf1, *vf2, *vf3;
GError *error = NULL;
gboolean success;
con = nm_simple_connection_new ();
s_con = (NMSettingConnection *) nm_setting_connection_new ();
nm_connection_add_setting (con, NM_SETTING (s_con));
g_object_set (s_con,
NM_SETTING_CONNECTION_ID, "Test SR-IOV connection",
NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_a (),
NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
NM_SETTING_CONNECTION_INTERFACE_NAME, "eth0",
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
NULL);
nm_connection_add_setting (con, nm_setting_wired_new ());
s_sriov = (NMSettingSriov *) nm_setting_sriov_new ();
nm_connection_add_setting (con, NM_SETTING (s_sriov));
g_object_set (s_sriov, NM_SETTING_SRIOV_TOTAL_VFS, 16, NULL);
nm_setting_sriov_add_vf (s_sriov, (vf1 = nm_sriov_vf_new (0)));
nm_setting_sriov_add_vf (s_sriov, (vf2 = nm_sriov_vf_new (4)));
nm_setting_sriov_add_vf (s_sriov, (vf3 = nm_sriov_vf_new (10)));
g_assert (nm_setting_sriov_remove_vf_by_index (s_sriov, 4));
nm_sriov_vf_unref (vf2);
nm_setting_sriov_add_vf (s_sriov, (vf2 = nm_sriov_vf_new (2)));
nmtst_assert_connection_verifies_and_normalizable (con);
nmtst_connection_normalize (con);
success = nm_setting_verify ((NMSetting *) s_sriov, con, &error);
nmtst_assert_success (success, error);
g_assert_cmpint (nm_setting_sriov_get_num_vfs (s_sriov), ==, 3);
g_assert_cmpint (nm_sriov_vf_get_index (nm_setting_sriov_get_vf (s_sriov, 0)), ==, 0);
g_assert_cmpint (nm_sriov_vf_get_index (nm_setting_sriov_get_vf (s_sriov, 1)), ==, 2);
g_assert_cmpint (nm_sriov_vf_get_index (nm_setting_sriov_get_vf (s_sriov, 2)), ==, 10);
nm_sriov_vf_unref (vf1);
nm_sriov_vf_unref (vf2);
nm_sriov_vf_unref (vf3);
}
typedef struct {
guint id;
guint qos;
bool proto_ad;
} VlanData;
static void
_test_sriov_parse_vlan_one (const char *string, gboolean exp_res, VlanData *data, guint data_length)
{
NMSriovVF *vf;
gboolean res;
guint i, num_vlans;
const guint *vlan_ids;
vf = nm_sriov_vf_new (1);
g_assert (vf);
res = _nm_sriov_vf_parse_vlans (vf, string, NULL);
g_assert_cmpint (res, ==, exp_res);
if (exp_res) {
vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num_vlans);
g_assert_cmpint (num_vlans, ==, data_length);
for (i = 0; i < num_vlans; i++) {
g_assert_cmpint (vlan_ids[i], ==, data[i].id);
g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, vlan_ids[i]), ==, data[i].qos);
g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, vlan_ids[i]),
==,
data[i].proto_ad ? NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD: NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
}
}
nm_sriov_vf_unref (vf);
}
#define test_sriov_parse_vlan_one(string, result, ...) \
{ \
VlanData _data[] = { __VA_ARGS__ }; \
guint _length = G_N_ELEMENTS (_data); \
\
_test_sriov_parse_vlan_one (string, result, _data, _length); \
}
static void
test_sriov_parse_vlans (void)
{
test_sriov_parse_vlan_one ("", FALSE, {});
test_sriov_parse_vlan_one ("1", TRUE, {1, 0, 0});
test_sriov_parse_vlan_one ("1;2", TRUE, {1, 0, 0}, {2, 0, 0});
test_sriov_parse_vlan_one ("4095;;2", TRUE, {2, 0, 0}, {4095, 0, 0});
test_sriov_parse_vlan_one ("1 2", FALSE, {});
test_sriov_parse_vlan_one ("4096", FALSE, {});
test_sriov_parse_vlan_one ("1.10", TRUE, {1, 10, 0});
test_sriov_parse_vlan_one ("1.20.ad", TRUE, {1, 20, 1});
test_sriov_parse_vlan_one ("1.21.q", TRUE, {1, 21, 0});
test_sriov_parse_vlan_one ("9.20.foo", FALSE, {});
test_sriov_parse_vlan_one ("1.20.ad.12", FALSE, {});
test_sriov_parse_vlan_one ("1;1.10", FALSE, {});
test_sriov_parse_vlan_one ("1..1;2", FALSE, {});
test_sriov_parse_vlan_one ("1..ad;2", FALSE, {});
test_sriov_parse_vlan_one ("1.2.ad;2.0.q;5;3", TRUE, {1, 2, 1}, {2, 0, 0}, {3, 0, 0}, {5, 0, 0});
}
/*****************************************************************************/
static void
test_tc_config_qdisc (void)
{
@ -1669,6 +1899,12 @@ main (int argc, char **argv)
g_test_add_func ("/libnm/settings/dcb/priorities", test_dcb_priorities_valid);
g_test_add_func ("/libnm/settings/dcb/bandwidth-sums", test_dcb_bandwidth_sums);
g_test_add_func ("/libnm/settings/sriov/vf", test_sriov_vf);
g_test_add_func ("/libnm/settings/sriov/vf-dup", test_sriov_vf_dup);
g_test_add_func ("/libnm/settings/sriov/vf-vlan", test_sriov_vf_vlan);
g_test_add_func ("/libnm/settings/sriov/setting", test_sriov_setting);
g_test_add_func ("/libnm/settings/sriov/vlans", test_sriov_parse_vlans);
g_test_add_func ("/libnm/settings/tc_config/qdisc", test_tc_config_qdisc);
g_test_add_func ("/libnm/settings/tc_config/action", test_tc_config_action);
g_test_add_func ("/libnm/settings/tc_config/tfilter", test_tc_config_tfilter);

View file

@ -89,6 +89,7 @@
#include "nm-setting-pppoe.h"
#include "nm-setting-proxy.h"
#include "nm-setting-serial.h"
#include "nm-setting-sriov.h"
#include "nm-setting-tc-config.h"
#include "nm-setting-team.h"
#include "nm-setting-team-port.h"

View file

@ -1381,10 +1381,41 @@ libnm_1_12_2 {
libnm_1_14_0 {
global:
nm_connection_get_setting_6lowpan;
nm_connection_get_setting_sriov;
nm_connection_get_setting_wpan;
nm_device_6lowpan_get_type;
nm_device_wpan_get_type;
nm_setting_6lowpan_get_type;
nm_setting_sriov_add_vf;
nm_setting_sriov_clear_vfs;
nm_setting_sriov_get_autoprobe_drivers;
nm_setting_sriov_get_num_vfs;
nm_setting_sriov_get_total_vfs;
nm_setting_sriov_get_type;
nm_setting_sriov_get_vf;
nm_setting_sriov_new;
nm_setting_sriov_remove_vf;
nm_setting_sriov_remove_vf_by_index;
nm_setting_wpan_get_type;
nm_sriov_vf_add_vlan;
nm_sriov_vf_dup;
nm_sriov_vf_equal;
nm_sriov_vf_get_attribute;
nm_sriov_vf_get_attribute_names;
nm_sriov_vf_get_index;
nm_sriov_vf_get_type;
nm_sriov_vf_get_vlan_ids;
nm_sriov_vf_get_vlan_protocol;
nm_sriov_vf_get_vlan_qos;
nm_sriov_vf_new;
nm_sriov_vf_ref;
nm_sriov_vf_remove_vlan;
nm_sriov_vf_set_attribute;
nm_sriov_vf_set_vlan_protocol;
nm_sriov_vf_set_vlan_qos;
nm_sriov_vf_unref;
nm_sriov_vf_vlan_protocol_get_type;
nm_ternary_get_type;
nm_utils_sriov_vf_from_str;
nm_utils_sriov_vf_to_str;
} libnm_1_12_0;

View file

@ -83,6 +83,7 @@ libnm-core/nm-setting-ovs-bridge.c
libnm-core/nm-setting-ppp.c
libnm-core/nm-setting-pppoe.c
libnm-core/nm-setting-proxy.c
libnm-core/nm-setting-sriov.c
libnm-core/nm-setting-tc-config.c
libnm-core/nm-setting-team.c
libnm-core/nm-setting-team-port.c