platform: add support for changing VF attributes

This commit is contained in:
Beniamino Galvani
2018-05-23 14:33:24 +02:00
parent 7df3333879
commit 8720dd3df1
3 changed files with 230 additions and 0 deletions

View File

@@ -215,6 +215,46 @@ G_STATIC_ASSERT (RTA_MAX == (__RTA_MAX - 1));
/*****************************************************************************/
/* Redefine VF enums and structures that are not available on older kernels. */
#define IFLA_VF_UNSPEC 0
#define IFLA_VF_MAC 1
#define IFLA_VF_VLAN 2
#define IFLA_VF_TX_RATE 3
#define IFLA_VF_SPOOFCHK 4
#define IFLA_VF_LINK_STATE 5
#define IFLA_VF_RATE 6
#define IFLA_VF_RSS_QUERY_EN 7
#define IFLA_VF_STATS 8
#define IFLA_VF_TRUST 9
#define IFLA_VF_IB_NODE_GUID 10
#define IFLA_VF_IB_PORT_GUID 11
#define IFLA_VF_VLAN_LIST 12
#define IFLA_VF_VLAN_INFO_UNSPEC 0
#define IFLA_VF_VLAN_INFO 1
/* valid for TRUST, SPOOFCHK, LINK_STATE, RSS_QUERY_EN */
struct _ifla_vf_setting {
guint32 vf;
guint32 setting;
};
struct _ifla_vf_rate {
guint32 vf;
guint32 min_tx_rate;
guint32 max_tx_rate;
};
struct _ifla_vf_vlan_info {
guint32 vf;
guint32 vlan; /* 0 - 4095, 0 disables VLAN filter */
guint32 qos;
guint16 vlan_proto; /* VLAN protocol, either 802.1Q or 802.1ad */
};
/*****************************************************************************/
#define _NMLOG_PREFIX_NAME "platform-linux"
#define _NMLOG_DOMAIN LOGD_PLATFORM
#define _NMLOG2_DOMAIN LOGD_PLATFORM
@@ -5617,6 +5657,101 @@ link_set_sriov_params (NMPlatform *platform,
return TRUE;
}
static gboolean
link_set_sriov_vfs (NMPlatform *platform, int ifindex, const NMPlatformVF *const *vfs)
{
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
struct nlattr *list, *info, *vlan_list;
guint i;
nlmsg = _nl_msg_new_link (RTM_NEWLINK,
0,
ifindex,
NULL,
0,
0);
if (!nlmsg)
g_return_val_if_reached (NM_PLATFORM_ERROR_UNSPECIFIED);
if (!(list = nla_nest_start (nlmsg, IFLA_VFINFO_LIST)))
goto nla_put_failure;
for (i = 0; vfs[i]; i++) {
const NMPlatformVF *vf = vfs[i];
if (!(info = nla_nest_start (nlmsg, IFLA_VF_INFO)))
goto nla_put_failure;
if (vf->spoofchk >= 0) {
struct _ifla_vf_setting ivs = { 0 };
ivs.vf = vf->index;
ivs.setting = vf->spoofchk;
NLA_PUT (nlmsg, IFLA_VF_SPOOFCHK, sizeof (ivs), &ivs);
}
if (vf->trust >= 0) {
struct _ifla_vf_setting ivs = { 0 };
ivs.vf = vf->index;
ivs.setting = vf->trust;
NLA_PUT (nlmsg, IFLA_VF_TRUST, sizeof (ivs), &ivs);
}
if (vf->mac.len) {
struct ifla_vf_mac ivm = { 0 };
ivm.vf = vf->index;
memcpy (ivm.mac, vf->mac.data, vf->mac.len);
NLA_PUT (nlmsg, IFLA_VF_MAC, sizeof (ivm), &ivm);
}
if (vf->min_tx_rate || vf->max_tx_rate) {
struct _ifla_vf_rate ivr = { 0 };
ivr.vf = vf->index;
ivr.min_tx_rate = vf->min_tx_rate;
ivr.max_tx_rate = vf->max_tx_rate;
NLA_PUT (nlmsg, IFLA_VF_RATE, sizeof (ivr), &ivr);
}
/* Kernel only supports one VLAN per VF now. If this
* changes in the future, we need to figure out how to
* clear existing VLANs and set new ones in one message
* with the new API.*/
if (vf->num_vlans > 1) {
_LOGW ("multiple VLANs per VF are not supported at the moment");
return FALSE;
} else {
struct _ifla_vf_vlan_info ivvi = { 0 };
if (!(vlan_list = nla_nest_start (nlmsg, IFLA_VF_VLAN_LIST)))
goto nla_put_failure;
ivvi.vf = vf->index;
if (vf->num_vlans == 1) {
ivvi.vlan = vf->vlans[0].id;
ivvi.qos = vf->vlans[0].qos;
ivvi.vlan_proto = htons (vf->vlans[0].proto_ad ? ETH_P_8021AD : ETH_P_8021Q);
} else {
/* Clear existing VLAN */
ivvi.vlan = 0;
ivvi.qos = 0;
ivvi.vlan_proto = htons (ETH_P_8021Q);
}
NLA_PUT (nlmsg, IFLA_VF_VLAN_INFO, sizeof (ivvi), &ivvi);
nla_nest_end (nlmsg, vlan_list);
}
nla_nest_end (nlmsg, info);
}
nla_nest_end (nlmsg, list);
return do_change_link (platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) == NM_PLATFORM_ERROR_SUCCESS;
nla_put_failure:
g_return_val_if_reached (FALSE);
}
static char *
link_get_physical_port_id (NMPlatform *platform, int ifindex)
{
@@ -7761,6 +7896,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->link_set_mtu = link_set_mtu;
platform_class->link_set_name = link_set_name;
platform_class->link_set_sriov_params = link_set_sriov_params;
platform_class->link_set_sriov_vfs = link_set_sriov_vfs;
platform_class->link_get_physical_port_id = link_get_physical_port_id;
platform_class->link_get_dev_id = link_get_dev_id;

View File

@@ -1490,6 +1490,27 @@ nm_platform_link_set_sriov_params (NMPlatform *self,
return klass->link_set_sriov_params (self, ifindex, num_vfs, autoprobe);
}
gboolean
nm_platform_link_set_sriov_vfs (NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs)
{
guint i;
_CHECK_SELF (self, klass, FALSE);
g_return_val_if_fail (ifindex > 0, FALSE);
_LOGD ("link: setting VFs for \"%s\" (%d):",
nm_platform_link_get_name (self, ifindex),
ifindex);
for (i = 0; vfs[i]; i++) {
const NMPlatformVF *vf = vfs[i];
_LOGD ("link: VF %s", nm_platform_vf_to_string (vf, NULL, 0));
}
return klass->link_set_sriov_vfs (self, ifindex, vfs);
}
/**
* nm_platform_link_set_up:
* @self: platform instance
@@ -6055,6 +6076,56 @@ nm_platform_tfilter_cmp (const NMPlatformTfilter *a, const NMPlatformTfilter *b)
return 0;
}
const char *
nm_platform_vf_to_string (const NMPlatformVF *vf, char *buf, gsize len)
{
char str_mac[128], mac[128];
char str_spoof_check[64];
char str_trust[64];
char str_min_tx_rate[64];
char str_max_tx_rate[64];
nm_auto_free_gstring GString *gstr_vlans = NULL;
guint i;
if (!nm_utils_to_string_buffer_init_null (vf, &buf, &len))
return buf;
if (vf->mac.len) {
nm_utils_hwaddr_ntoa_buf (vf->mac.data, vf->mac.len, TRUE, mac, sizeof (mac));
nm_sprintf_buf (str_mac, " mac %s", mac);
} else
str_mac[0] = '\0';
if (vf->num_vlans) {
gstr_vlans = g_string_new ("");
for (i = 0; i < vf->num_vlans; i++) {
g_string_append_printf (gstr_vlans, " vlan %u", (unsigned) vf->vlans[i].id);
if (vf->vlans[i].qos)
g_string_append_printf (gstr_vlans, " qos %u", (unsigned) vf->vlans[i].qos);
if (vf->vlans[i].proto_ad)
g_string_append (gstr_vlans, " proto 802.1ad");
}
}
g_snprintf (buf, len,
"%u" /* index */
"%s" /* MAC */
"%s" /* spoof check */
"%s" /* trust */
"%s" /* min tx rate */
"%s" /* max tx rate */
"%s", /* VLANs */
vf->index,
str_mac,
vf->spoofchk >= 0 ? nm_sprintf_buf (str_spoof_check, " spoofchk %d", vf->spoofchk) : "",
vf->trust >= 0 ? nm_sprintf_buf (str_trust, " trust %d", vf->trust) : "",
vf->min_tx_rate ? nm_sprintf_buf (str_min_tx_rate, " min_tx_rate %u", (unsigned) vf->min_tx_rate) : "",
vf->max_tx_rate ? nm_sprintf_buf (str_max_tx_rate, " max_tx_rate %u", (unsigned) vf->max_tx_rate) : "",
gstr_vlans ? gstr_vlans->str : "");
return buf;
}
void
nm_platform_link_hash_update (const NMPlatformLink *obj, NMHashState *h)
{

View File

@@ -607,6 +607,26 @@ typedef struct {
extern const NMPlatformVTableRoute nm_platform_vtable_route_v4;
extern const NMPlatformVTableRoute nm_platform_vtable_route_v6;
typedef struct {
guint16 id;
guint32 qos;
bool proto_ad:1;
} NMPlatformVFVlan;
typedef struct {
guint32 index;
guint32 min_tx_rate;
guint32 max_tx_rate;
guint num_vlans;
NMPlatformVFVlan *vlans;
struct {
guint8 data[20]; /* NM_UTILS_HWADDR_LEN_MAX */
guint8 len;
} mac;
gint8 spoofchk;
gint8 trust;
} NMPlatformVF;
typedef struct {
in_addr_t local;
in_addr_t remote;
@@ -803,6 +823,7 @@ typedef struct {
NMPlatformError (*link_set_mtu) (NMPlatform *, int ifindex, guint32 mtu);
gboolean (*link_set_name) (NMPlatform *, int ifindex, const char *name);
gboolean (*link_set_sriov_params) (NMPlatform *, int ifindex, guint num_vfs, int autoprobe);
gboolean (*link_set_sriov_vfs) (NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs);
char * (*link_get_physical_port_id) (NMPlatform *, int ifindex);
guint (*link_get_dev_id) (NMPlatform *, int ifindex);
@@ -1194,6 +1215,7 @@ NMPlatformError nm_platform_link_set_address (NMPlatform *self, int ifindex, con
NMPlatformError nm_platform_link_set_mtu (NMPlatform *self, int ifindex, guint32 mtu);
gboolean nm_platform_link_set_name (NMPlatform *self, int ifindex, const char *name);
gboolean nm_platform_link_set_sriov_params (NMPlatform *self, int ifindex, guint num_vfs, int autoprobe);
gboolean nm_platform_link_set_sriov_vfs (NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs);
char *nm_platform_link_get_physical_port_id (NMPlatform *self, int ifindex);
guint nm_platform_link_get_dev_id (NMPlatform *self, int ifindex);
@@ -1434,6 +1456,7 @@ const char *nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, ch
const char *nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsize len);
const char *nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len);
const char *nm_platform_tfilter_to_string (const NMPlatformTfilter *tfilter, char *buf, gsize len);
const char *nm_platform_vf_to_string (const NMPlatformVF *vf, char *buf, gsize len);
const char *nm_platform_vlan_qos_mapping_to_string (const char *name,
const NMVlanQosMapping *map,