|
|
5c27b6 |
From 458aa8587e750e7b368e1a86208841a082242ce5 Mon Sep 17 00:00:00 2001
|
|
|
5c27b6 |
Message-Id: <458aa8587e750e7b368e1a86208841a082242ce5@dist-git>
|
|
|
5c27b6 |
From: Laine Stump <laine@laine.org>
|
|
|
5c27b6 |
Date: Thu, 13 Apr 2017 14:29:36 -0400
|
|
|
5c27b6 |
Subject: [PATCH] util: if setting admin MAC to 00:00:00:00:00:00 fails, try
|
|
|
5c27b6 |
02:00:00:00:00:00
|
|
|
5c27b6 |
|
|
|
5c27b6 |
Some PF drivers allow setting the admin MAC (that is the MAC address
|
|
|
5c27b6 |
that the VF will be initialized to the next time the VF's driver is
|
|
|
5c27b6 |
loaded) to 00:00:00:00:00:00, and some don't. Multiple drivers
|
|
|
5c27b6 |
initialize the admin MACs to all 0, but don't allow setting it to that
|
|
|
5c27b6 |
very same value. It has been an uphill battle convincing the driver
|
|
|
5c27b6 |
people that it's reasonable to expect The argument that's used is
|
|
|
5c27b6 |
that an all 0 device MAC address on a device is invalid; however, from
|
|
|
5c27b6 |
an outsider's point of view, when the admin MAC is set to 0 at the
|
|
|
5c27b6 |
time the VF driver is loaded, the VF's MAC is *not* set to 0, but to a
|
|
|
5c27b6 |
random non-0 value. But that's beside the point - even if I could
|
|
|
5c27b6 |
convince one or two SRIOV driver maintainers to permit setting the
|
|
|
5c27b6 |
admin MAC to 0, there are still several other drivers.
|
|
|
5c27b6 |
|
|
|
5c27b6 |
So rather than fighting that losing battle, this patch checks for a
|
|
|
5c27b6 |
failure to set the admin MAC due to an all 0 value, and retries it
|
|
|
5c27b6 |
with 02:00:00:00:00:00. That won't result in a random value being set
|
|
|
5c27b6 |
in the VF MAC at next VF driver init, but that's okay, because we
|
|
|
5c27b6 |
always want to set a specific value anyway. Rather, the "almost 0"
|
|
|
5c27b6 |
setting makes it easy to visually detect from the output of "ip link
|
|
|
5c27b6 |
show" which VFs are currently in use and which are free.
|
|
|
5c27b6 |
|
|
|
5c27b6 |
Resolves: https://bugzilla.redhat.com/1442040 (RHEL 7.3.z)
|
|
|
5c27b6 |
Resolves: https://bugzilla.redhat.com/1415609 (RHEL 7.4)
|
|
|
5c27b6 |
|
|
|
5c27b6 |
(cherry picked from commit d5f4abefc231a71e21e33e0d2eb4da8f22552c70)
|
|
|
5c27b6 |
---
|
|
|
5c27b6 |
src/util/virnetdev.c | 42 ++++++++++++++++++++++++++++++++++++++----
|
|
|
5c27b6 |
1 file changed, 38 insertions(+), 4 deletions(-)
|
|
|
5c27b6 |
|
|
|
5c27b6 |
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
|
|
|
5c27b6 |
index 4739f573a..0223877ff 100644
|
|
|
5c27b6 |
--- a/src/util/virnetdev.c
|
|
|
5c27b6 |
+++ b/src/util/virnetdev.c
|
|
|
5c27b6 |
@@ -1391,6 +1391,14 @@ virNetDevSysfsFile(char **pf_sysfs_device_link ATTRIBUTE_UNUSED,
|
|
|
5c27b6 |
#if defined(__linux__) && defined(HAVE_LIBNL) && defined(IFLA_VF_MAX)
|
|
|
5c27b6 |
|
|
|
5c27b6 |
|
|
|
5c27b6 |
+static virMacAddr zeroMAC = { .addr = { 0, 0, 0, 0, 0, 0 } };
|
|
|
5c27b6 |
+
|
|
|
5c27b6 |
+/* if a net driver doesn't allow setting MAC to all 0, try setting
|
|
|
5c27b6 |
+ * to this (the only bit that is set is the "locally administered" bit")
|
|
|
5c27b6 |
+ */
|
|
|
5c27b6 |
+static virMacAddr altZeroMAC = { .addr = { 2, 0, 0, 0, 0, 0 } };
|
|
|
5c27b6 |
+
|
|
|
5c27b6 |
+
|
|
|
5c27b6 |
static struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
|
|
|
5c27b6 |
[IFLA_VF_MAC] = { .type = NLA_UNSPEC,
|
|
|
5c27b6 |
.maxlen = sizeof(struct ifla_vf_mac) },
|
|
|
5c27b6 |
@@ -1401,7 +1409,8 @@ static struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
|
|
|
5c27b6 |
|
|
|
5c27b6 |
static int
|
|
|
5c27b6 |
virNetDevSetVfConfig(const char *ifname, int vf,
|
|
|
5c27b6 |
- const virMacAddr *macaddr, int vlanid)
|
|
|
5c27b6 |
+ const virMacAddr *macaddr, int vlanid,
|
|
|
5c27b6 |
+ bool *allowRetry)
|
|
|
5c27b6 |
{
|
|
|
5c27b6 |
int rc = -1;
|
|
|
5c27b6 |
struct nlmsghdr *resp = NULL;
|
|
|
5c27b6 |
@@ -1478,7 +1487,15 @@ virNetDevSetVfConfig(const char *ifname, int vf,
|
|
|
5c27b6 |
if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
|
|
|
5c27b6 |
goto malformed_resp;
|
|
|
5c27b6 |
|
|
|
5c27b6 |
- if (err->error) {
|
|
|
5c27b6 |
+ /* if allowRetry is true and the error was EINVAL, then
|
|
|
5c27b6 |
+ * silently return a failure so the caller can retry with a
|
|
|
5c27b6 |
+ * different MAC address
|
|
|
5c27b6 |
+ */
|
|
|
5c27b6 |
+ if (err->error == -EINVAL && *allowRetry &&
|
|
|
5c27b6 |
+ macaddr && !virMacAddrCmp(macaddr, &zeroMAC)) {
|
|
|
5c27b6 |
+ goto cleanup;
|
|
|
5c27b6 |
+ } else if (err->error) {
|
|
|
5c27b6 |
+ /* other errors are permanent */
|
|
|
5c27b6 |
char macstr[VIR_MAC_STRING_BUFLEN];
|
|
|
5c27b6 |
|
|
|
5c27b6 |
virReportSystemError(-err->error,
|
|
|
5c27b6 |
@@ -1490,6 +1507,7 @@ virNetDevSetVfConfig(const char *ifname, int vf,
|
|
|
5c27b6 |
vlanid,
|
|
|
5c27b6 |
ifname ? ifname : "(unspecified)",
|
|
|
5c27b6 |
vf);
|
|
|
5c27b6 |
+ *allowRetry = false; /* no use retrying */
|
|
|
5c27b6 |
goto cleanup;
|
|
|
5c27b6 |
}
|
|
|
5c27b6 |
break;
|
|
|
5c27b6 |
@@ -2126,8 +2144,24 @@ virNetDevSetNetConfig(const char *linkdev, int vf,
|
|
|
5c27b6 |
* guest or host). if there is a vlanTag to set, it will take
|
|
|
5c27b6 |
* effect immediately though.
|
|
|
5c27b6 |
*/
|
|
|
5c27b6 |
- if (virNetDevSetVfConfig(pfDevName, vf, adminMAC, vlanTag) < 0)
|
|
|
5c27b6 |
- goto cleanup;
|
|
|
5c27b6 |
+ bool allowRetry = true;
|
|
|
5c27b6 |
+
|
|
|
5c27b6 |
+ if (virNetDevSetVfConfig(pfDevName, vf,
|
|
|
5c27b6 |
+ adminMAC, vlanTag, &allowRetry) < 0) {
|
|
|
5c27b6 |
+ /* allowRetry will still be true if the failure was due to
|
|
|
5c27b6 |
+ * trying to set the MAC address to all 0. In that case,
|
|
|
5c27b6 |
+ * we can retry with "altZeroMAC", which is just an all-0 MAC
|
|
|
5c27b6 |
+ * with the "locally administered" bit set.
|
|
|
5c27b6 |
+ */
|
|
|
5c27b6 |
+ if (!allowRetry)
|
|
|
5c27b6 |
+ goto cleanup;
|
|
|
5c27b6 |
+
|
|
|
5c27b6 |
+ allowRetry = false;
|
|
|
5c27b6 |
+ if (virNetDevSetVfConfig(pfDevName, vf,
|
|
|
5c27b6 |
+ &altZeroMAC, vlanTag, &allowRetry) < 0) {
|
|
|
5c27b6 |
+ goto cleanup;
|
|
|
5c27b6 |
+ }
|
|
|
5c27b6 |
+ }
|
|
|
5c27b6 |
}
|
|
|
5c27b6 |
|
|
|
5c27b6 |
ret = 0;
|
|
|
5c27b6 |
--
|
|
|
5c27b6 |
2.12.2
|
|
|
5c27b6 |
|