diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2018-05-23 14:33:24 +0200 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2018-07-11 16:16:22 +0200 |
commit | 8720dd3df1d9970684fca07bc62f3341988a77bd (patch) | |
tree | a746bfd0bb2681cf43e3b67756a5d67819fe01bb | |
parent | 7df33338797fc335c245fed65ac1186284afc357 (diff) | |
download | NetworkManager-8720dd3df1d9970684fca07bc62f3341988a77bd.tar.gz |
platform: add support for changing VF attributes
-rw-r--r-- | src/platform/nm-linux-platform.c | 136 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 71 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 23 |
3 files changed, 230 insertions, 0 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 19821a87c3..641f7d68c0 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -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; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 1146a07309..174d863637 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -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) { diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 01e13f2178..7e49e064a9 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -608,6 +608,26 @@ 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; int parent_ifindex; @@ -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, |