platform: add support for changing VF attributes
This commit is contained in:
@@ -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;
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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,
|
||||
|
Reference in New Issue
Block a user