[libvirt] [PATCH v3] network: bridge: Don't start network if it collides with host routing
by Cole Robinson
Fedora bug https://bugzilla.redhat.com/show_bug.cgi?id=235961
If using the default virtual network, an easy way to lose guest network
connectivity is to install libvirt inside the VM. The autostarted
default network inside the guest collides with host virtual network
routing. This is a long standing issue that has caused users quite a
bit of pain and confusion.
On network startup, parse /proc/net/route and compare the requested
IP+netmask against host routing destinations: if any matches are found,
refuse to start the network.
v2: Drop sscanf, fix a comment typo, comment that function could use
libnl instead of /proc
v3: Consider route netmask. Compare binary data rather than convert to
string.
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
src/network/bridge_driver.c | 108 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 108 insertions(+), 0 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 5d7ef19..7105a58 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -42,6 +42,8 @@
#include <stdio.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include "virterror_internal.h"
#include "datatypes.h"
@@ -908,6 +910,108 @@ cleanup:
return ret;
}
+#define PROC_NET_ROUTE "/proc/net/route"
+
+/* XXX: This function can be a lot more exhaustive, there are certainly
+ * other scenarios where we can ruin host network connectivity.
+ * XXX: Using a proper library is preferred over parsing /proc
+ */
+static int networkCheckRouteCollision(virNetworkObjPtr network)
+{
+ int ret = -1, len;
+ char *cur, *buf = NULL;
+ enum {MAX_ROUTE_SIZE = 1024*64};
+ struct in_addr inaddress, innetmask;
+ char netaddr[32];
+
+ if (!network->def->ipAddress || !network->def->netmask)
+ return 0;
+
+ if (inet_pton(AF_INET, network->def->ipAddress, &inaddress) <= 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse IP address '%s'"),
+ network->def->ipAddress);
+ goto error;
+ }
+ if (inet_pton(AF_INET, network->def->netmask, &innetmask) <= 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse netmask '%s'"),
+ network->def->netmask);
+ goto error;
+ }
+
+ inaddress.s_addr &= innetmask.s_addr;
+ if (!inet_ntop(AF_INET, &inaddress, netaddr, sizeof(netaddr))) {
+ virReportSystemError(errno, "%s",
+ _("failed to format network address"));
+ goto error;
+ }
+
+ /* Read whole routing table into memory */
+ if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
+ goto error;
+
+ /* Dropping the last character shouldn't hurt */
+ buf[len-1] = '\0';
+
+ /* First line is just headings, skip it */
+ cur = strchr(buf, '\n');
+
+ while (cur) {
+ char *data[8];
+ char *dest, *iface, *mask;
+ unsigned int addr_val, mask_val;
+ int i;
+
+ cur++;
+
+ /* Delimit interface field */
+ for (i = 0; i < sizeof(data); ++i) {
+ data[i] = cur;
+
+ /* Parse fields and delimit */
+ while(*cur > ' ') {
+ cur++;
+ }
+ *cur++ = '\0';
+ }
+
+ iface = data[0];
+ dest = data[1];
+ mask = data[7];
+
+ if (virStrToLong_ui(dest, NULL, 16, &addr_val) < 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to convert network address %s"),
+ dest);
+ goto error;
+ }
+
+ if (virStrToLong_ui(mask, NULL, 16, &mask_val) < 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to convert network mask %s"),
+ mask);
+ goto error;
+ }
+
+ addr_val &= mask_val;
+
+ if ((inaddress.s_addr == addr_val) && (innetmask.s_addr == mask_val)) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Network %s is already in use by "
+ "interface %s"), netaddr, iface);
+ goto error;
+ }
+
+ cur = strchr(cur, '\n');
+ }
+
+ ret = 0;
+error:
+ VIR_FREE(buf);
+ return ret;
+}
+
static int networkStartNetworkDaemon(struct network_driver *driver,
virNetworkObjPtr network)
{
@@ -919,6 +1023,10 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
return -1;
}
+ /* Check to see if network collides with an existing route */
+ if (networkCheckRouteCollision(network) < 0)
+ return -1;
+
if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
virReportSystemError(err,
_("cannot create bridge '%s'"),
--
1.6.6.1
14 years, 7 months
[libvirt] [PATCH] xen: Remove unused function
by Cole Robinson
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
src/xen/xend_internal.c | 223 -----------------------------------------------
src/xen/xend_internal.h | 6 --
2 files changed, 0 insertions(+), 229 deletions(-)
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index a203a8d..a99cc7b 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -1204,229 +1204,6 @@ no_memory:
return -1;
}
-
-int
-xend_parse_sexp_desc_char(virBufferPtr buf,
- const char *devtype,
- int portNum,
- const char *value,
- const char *tty)
-{
- const char *type;
- int telnet = 0;
- char *bindPort = NULL;
- char *bindHost = NULL;
- char *connectPort = NULL;
- char *connectHost = NULL;
- char *path = NULL;
- int ret = -1;
-
- if (value[0] == '/') {
- type = "dev";
- } else if (STRPREFIX(value, "null")) {
- type = "null";
- value = NULL;
- } else if (STRPREFIX(value, "vc")) {
- type = "vc";
- value = NULL;
- } else if (STRPREFIX(value, "pty")) {
- type = "pty";
- value = NULL;
- } else if (STRPREFIX(value, "stdio")) {
- type = "stdio";
- value = NULL;
- } else if (STRPREFIX(value, "file:")) {
- type = "file";
- value += sizeof("file:")-1;
- } else if (STRPREFIX(value, "pipe:")) {
- type = "pipe";
- value += sizeof("pipe:")-1;
- } else if (STRPREFIX(value, "tcp:")) {
- type = "tcp";
- value += sizeof("tcp:")-1;
- } else if (STRPREFIX(value, "telnet:")) {
- type = "tcp";
- value += sizeof("telnet:")-1;
- telnet = 1;
- } else if (STRPREFIX(value, "udp:")) {
- type = "udp";
- value += sizeof("udp:")-1;
- } else if (STRPREFIX(value, "unix:")) {
- type = "unix";
- value += sizeof("unix:")-1;
- } else {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("Unknown char device type"));
- return -1;
- }
-
- /* Compat with legacy <console tty='/dev/pts/5'/> syntax */
- if (STREQ(devtype, "console") &&
- STREQ(type, "pty") &&
- tty != NULL) {
- virBufferVSprintf(buf, " <%s type='%s' tty='%s'>\n",
- devtype, type, tty);
- } else {
- virBufferVSprintf(buf, " <%s type='%s'>\n",
- devtype, type);
- }
-
- if (STREQ(type, "null") ||
- STREQ(type, "vc") ||
- STREQ(type, "stdio")) {
- /* no source needed */
- } else if (STREQ(type, "pty")) {
- if (tty)
- virBufferVSprintf(buf, " <source path='%s'/>\n",
- tty);
- } else if (STREQ(type, "file") ||
- STREQ(type, "pipe")) {
- virBufferVSprintf(buf, " <source path='%s'/>\n",
- value);
- } else if (STREQ(type, "tcp")) {
- sa_assert (value);
- const char *offset = strchr(value, ':');
- const char *offset2;
- const char *mode, *protocol;
-
- if (offset == NULL) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed char device string"));
- goto error;
- }
-
- if (offset != value &&
- (bindHost = strndup(value, offset - value)) == NULL)
- goto no_memory;
-
- offset2 = strchr(offset, ',');
- if (offset2 == NULL)
- bindPort = strdup(offset+1);
- else
- bindPort = strndup(offset+1, offset2-(offset+1));
- if (bindPort == NULL)
- goto no_memory;
-
- if (offset2 && strstr(offset2, ",listen"))
- mode = "bind";
- else
- mode = "connect";
- protocol = telnet ? "telnet":"raw";
-
- if (bindHost) {
- virBufferVSprintf(buf,
- " <source mode='%s' host='%s' service='%s'/>\n",
- mode, bindHost, bindPort);
- } else {
- virBufferVSprintf(buf,
- " <source mode='%s' service='%s'/>\n",
- mode, bindPort);
- }
- virBufferVSprintf(buf,
- " <protocol type='%s'/>\n",
- protocol);
- } else if (STREQ(type, "udp")) {
- sa_assert (value);
- const char *offset = strchr(value, ':');
- const char *offset2, *offset3;
-
- if (offset == NULL) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed char device string"));
- goto error;
- }
-
- if (offset != value &&
- (connectHost = strndup(value, offset - value)) == NULL)
- goto no_memory;
-
- offset2 = strchr(offset, '@');
- if (offset2 != NULL) {
- if ((connectPort = strndup(offset + 1, offset2-(offset+1))) == NULL)
- goto no_memory;
-
- offset3 = strchr(offset2, ':');
- if (offset3 == NULL) {
- virXendError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed char device string"));
- goto error;
- }
-
- if (offset3 > (offset2 + 1) &&
- (bindHost = strndup(offset2 + 1, offset3 - (offset2+1))) == NULL)
- goto no_memory;
-
- if ((bindPort = strdup(offset3 + 1)) == NULL)
- goto no_memory;
- } else {
- if ((connectPort = strdup(offset + 1)) == NULL)
- goto no_memory;
- }
-
- if (connectHost) {
- virBufferVSprintf(buf,
- " <source mode='connect' host='%s' service='%s'/>\n",
- connectHost, connectPort);
- } else {
- virBufferVSprintf(buf,
- " <source mode='connect' service='%s'/>\n",
- connectPort);
- }
- if (bindPort) {
- if (bindHost) {
- virBufferVSprintf(buf,
- " <source mode='bind' host='%s' service='%s'/>\n",
- bindHost, bindPort);
- } else {
- virBufferVSprintf(buf,
- " <source mode='bind' service='%s'/>\n",
- bindPort);
- }
- }
-
- } else if (STREQ(type, "unix")) {
- sa_assert (value);
- const char *offset = strchr(value, ',');
- int dolisten = 0;
- if (offset)
- path = strndup(value, (offset - value));
- else
- path = strdup(value);
- if (path == NULL)
- goto no_memory;
-
- if (offset != NULL &&
- strstr(offset, ",listen") != NULL)
- dolisten = 1;
-
- virBufferVSprintf(buf, " <source mode='%s' path='%s'/>\n",
- dolisten ? "bind" : "connect", path);
- }
-
- virBufferVSprintf(buf, " <target port='%d'/>\n",
- portNum);
-
- virBufferVSprintf(buf, " </%s>\n",
- devtype);
-
- ret = 0;
-
- if (ret == -1) {
-no_memory:
- virReportOOMError();
- }
-
-error:
-
- VIR_FREE(path);
- VIR_FREE(bindHost);
- VIR_FREE(bindPort);
- VIR_FREE(connectHost);
- VIR_FREE(connectPort);
-
- return ret;
-}
-
virDomainChrDefPtr
xenDaemonParseSxprChar(const char *value,
const char *tty)
diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h
index 25a5421..c757716 100644
--- a/src/xen/xend_internal.h
+++ b/src/xen/xend_internal.h
@@ -96,12 +96,6 @@ xenDaemonDomainFetch(virConnectPtr xend,
const char *name,
const char *cpus);
-int xend_parse_sexp_desc_char(virBufferPtr buf,
- const char *devtype,
- int portNum,
- const char *value,
- const char *tty);
-
virDomainDefPtr
xenDaemonParseSxprString(virConnectPtr conn,
const char *sexpr,
--
1.6.6.1
14 years, 7 months
[libvirt] [PATCH] xen: Fix chardev listen sexpr formatting
by Cole Robinson
'listen' isn't a valid qemu-dm option, as reported a long time ago here:
https://bugzilla.redhat.com/show_bug.cgi?id=492958
Matches the near identical logic in qemu_conf.c
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
src/xen/xend_internal.c | 8 ++++----
.../sexpr2xml-fv-serial-tcp-telnet.sexpr | 2 +-
tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.sexpr | 2 +-
tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.sexpr | 2 +-
.../test-fullvirt-serial-tcp-telnet.cfg | 2 +-
tests/xmconfigdata/test-fullvirt-serial-unix.cfg | 2 +-
.../xml2sexpr-fv-serial-tcp-telnet.sexpr | 2 +-
tests/xml2sexprdata/xml2sexpr-fv-serial-tcp.sexpr | 2 +-
tests/xml2sexprdata/xml2sexpr-fv-serial-unix.sexpr | 2 +-
9 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index a99cc7b..e12bac7 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -1276,7 +1276,7 @@ xenDaemonParseSxprChar(const char *value,
if (def->data.tcp.service == NULL)
goto no_memory;
- if (offset2 && strstr(offset2, ",listen"))
+ if (offset2 && strstr(offset2, ",server,nowait"))
def->data.tcp.listen = 1;
}
break;
@@ -1332,7 +1332,7 @@ xenDaemonParseSxprChar(const char *value,
goto no_memory;
if (offset != NULL &&
- strstr(offset, ",listen") != NULL)
+ strstr(offset, ",server,nowait") != NULL)
def->data.nix.listen = 1;
}
break;
@@ -5209,7 +5209,7 @@ xenDaemonFormatSxprChr(virDomainChrDefPtr def,
"tcp" : "telnet"),
(def->data.tcp.host ? def->data.tcp.host : ""),
(def->data.tcp.service ? def->data.tcp.service : ""),
- (def->data.tcp.listen ? ",listen" : ""));
+ (def->data.tcp.listen ? ",server,nowait" : ""));
break;
case VIR_DOMAIN_CHR_TYPE_UDP:
@@ -5223,7 +5223,7 @@ xenDaemonFormatSxprChr(virDomainChrDefPtr def,
case VIR_DOMAIN_CHR_TYPE_UNIX:
virBufferVSprintf(buf, "%s:%s%s", type,
def->data.nix.path,
- def->data.nix.listen ? ",listen" : "");
+ def->data.nix.listen ? ",server,nowait" : "");
break;
}
diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.sexpr b/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.sexpr
index 605f3c8..ed914f7 100644
--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.sexpr
+++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.sexpr
@@ -1 +1 @@
-(domain (domid 1)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial telnet:localhost:9999,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(domain (domid 1)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial telnet:localhost:9999,server,nowait)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.sexpr b/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.sexpr
index aa20310..5d49158 100644
--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.sexpr
+++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.sexpr
@@ -1 +1 @@
-(domain (domid 1)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial tcp:localhost:9999,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(domain (domid 1)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial tcp:localhost:9999,server,nowait)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.sexpr b/tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.sexpr
index 3825ab7..ff46c64 100644
--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.sexpr
+++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.sexpr
@@ -1 +1 @@
-(domain (domid 1)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial unix:/tmp/serial.sock,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(domain (domid 1)(name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd275cdaca517769660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial unix:/tmp/serial.sock,server,nowait)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
diff --git a/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.cfg b/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.cfg
index c759f3d..54bc84d 100755
--- a/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.cfg
+++ b/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.cfg
@@ -22,4 +22,4 @@ vncpasswd = "123poi"
disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ]
vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,type=ioemu" ]
parallel = "none"
-serial = "telnet:127.0.0.1:9999,listen"
+serial = "telnet:127.0.0.1:9999,server,nowait"
diff --git a/tests/xmconfigdata/test-fullvirt-serial-unix.cfg b/tests/xmconfigdata/test-fullvirt-serial-unix.cfg
index 3cdb22b..bcd7d11 100755
--- a/tests/xmconfigdata/test-fullvirt-serial-unix.cfg
+++ b/tests/xmconfigdata/test-fullvirt-serial-unix.cfg
@@ -22,4 +22,4 @@ vncpasswd = "123poi"
disk = [ "phy:/dev/HostVG/XenGuest2,hda,w", "file:/root/boot.iso,hdc:cdrom,r" ]
vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,type=ioemu" ]
parallel = "none"
-serial = "unix:/tmp/serial.sock,listen"
+serial = "unix:/tmp/serial.sock,server,nowait"
diff --git a/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp-telnet.sexpr b/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp-telnet.sexpr
index 46413c8..78295db 100644
--- a/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp-telnet.sexpr
+++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp-telnet.sexpr
@@ -1 +1 @@
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial telnet:localhost:9999,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial telnet:localhost:9999,server,nowait)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
diff --git a/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp.sexpr b/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp.sexpr
index 6c17207..841fdbe 100644
--- a/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp.sexpr
+++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-tcp.sexpr
@@ -1 +1 @@
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial tcp:localhost:9999,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial tcp:localhost:9999,server,nowait)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
diff --git a/tests/xml2sexprdata/xml2sexpr-fv-serial-unix.sexpr b/tests/xml2sexprdata/xml2sexpr-fv-serial-unix.sexpr
index 352b29b..14da597 100644
--- a/tests/xml2sexprdata/xml2sexpr-fv-serial-unix.sexpr
+++ b/tests/xml2sexprdata/xml2sexpr-fv-serial-unix.sexpr
@@ -1 +1 @@
-(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial unix:/tmp/serial.sock,listen)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
+(vm (name 'fvtest')(memory 400)(maxmem 400)(vcpus 1)(uuid 'b5d70dd2-75cd-aca5-1776-9660b059d8bc')(on_poweroff 'destroy')(on_reboot 'restart')(on_crash 'restart')(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot c)(cdrom '/root/boot.iso')(acpi 1)(usb 1)(parallel none)(serial unix:/tmp/serial.sock,server,nowait)(device_model '/usr/lib64/xen/bin/qemu-dm')(vnc 1)))(device (vbd (dev 'ioemu:hda')(uname 'file:/root/foo.img')(mode 'w')))(device (vif (mac '00:16:3e:1b:b1:47')(bridge 'xenbr0')(script 'vif-bridge')(type ioemu))))
\ No newline at end of file
--
1.6.6.1
14 years, 7 months
[libvirt] [PATCH] nodedev: udev: Fix handling of wireless NIC
by Cole Robinson
Wireless NICs were being ignored because we weren't correctly handling
device type. Fix this, as well as wireless NIC net subtype.
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
src/node_device/node_device_udev.c | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index f0485f1..4915d4e 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -597,8 +597,16 @@ static int udevProcessNetworkInterface(struct udev_device *device,
virNodeDeviceDefPtr def)
{
int ret = -1;
+ const char *devtype = NULL;
union _virNodeDevCapData *data = &def->caps->data;
+ devtype = udev_device_get_devtype(device);
+ if (devtype && STREQ(devtype, "wlan")) {
+ data->net.subtype = VIR_NODE_DEV_CAP_NET_80211;
+ } else {
+ data->net.subtype = VIR_NODE_DEV_CAP_NET_80203;
+ }
+
if (udevGetStringProperty(device,
"INTERFACE",
&data->net.ifname) == PROPERTY_ERROR) {
@@ -1074,6 +1082,8 @@ static int udevGetDeviceType(struct udev_device *device,
int ret = 0;
devtype = udev_device_get_devtype(device);
+ VIR_DEBUG("Found device type '%s' for device '%s'",
+ devtype, udev_device_get_sysname(device));
if (devtype != NULL && STREQ(devtype, "usb_device")) {
*type = VIR_NODE_DEV_CAP_USB_DEV;
@@ -1112,7 +1122,7 @@ static int udevGetDeviceType(struct udev_device *device,
/* It does not appear that network interfaces set the device type
* property. */
- if (devtype == NULL &&
+ if ((devtype == NULL || STREQ(devtype, "wlan")) &&
udevGetStringProperty(device,
"INTERFACE",
&tmp_string) == PROPERTY_FOUND) {
--
1.6.6.1
14 years, 7 months
[libvirt] [PATCH v10] add 802.1Qbh and 802.1Qbg handling
by Stefan Berger
This is now V10 of the patch. I do accept patches on top of (hint) :-)
V10:
- never sending nor parsing IFLA_PORT_SELF type of messages in the
802.1Qbg case
- iterating over the elements in a IFLA_VF_PORTS to pick the right
IFLA_VF_PORT by either IFLA_PORT_PROFILE and given profileId
(802.1Qbh) or IFLA_PORT_INSTANCE_UUID and given instanceId (802.1Qbg)
and reading the current status in IFLA_PORT_RESPONSE.
V9:
- recycling a previous patch that adds functionality to interface.c to
- get the vlan identifier on an interface
- get the flags of an interface and some convenience function to
check whether an interface is 'up' or not (not currently used here)
- adding function to determine the root physical interface of an
interface. For example if a macvtap is linked to eth0.100, it will
find eth0. Also adding a function that finds the vlan on the 'way to
the root physical interface'
- conveying the root physical interface name and index in case of 802.1Qbg
- conveying mac address of macvlan device and vlan identifier in
IFLA_VFINFO_LIST[ IFLA_VF_INFO[ IFLA_VF_MAC(mac), IFLA_VF_VLAN(vlan) ] ]
to (future) lldpad via netlink
V8:
- To enable build with --without-macvtap rename the
[dis|]associatePortProfileId functions, prepend 'vp' before their
name and make them non-static functions.
- Renaming variable multicast to nltarget_kernel and inverting
the logic
V7:
- Addressing Jim Meyering's comments; this also touches existing
code for example for correcting indentation of break statements or
simplification of switch statements.
Changes from v5 to v6:
- Renamed occurrencvirVirtualPortProfileDef to
virVirtualPortProfileParamses
- 802.1Qbg part prepared for sending a RTM_SETLINK and getting
processing status back plus a subsequent RTM_GETLINK to
get IFLA_PORT_RESPONSE.
Note: This interface for 802.1Qbg may still change
Changes from v4 to v5:
- [David Allan] move getPhysfn inside IFLA_VF_PORT_MAX to avoid
compiler
warning when latest if_link.h isn't available
Changes from v3 to v4:
- move from Stefan's 802.1Qb{g|h} XML v8 to v9
- move hostuuid and vf index calcs to inside doPortProfileOp8021Qbh
Changes from v2 to v3:
- remove debug fprintfs
- use virGetHostUUID (thanks Stefan!)
- fix compile issue when latest if_link.h isn't available
- change poll timeout to 10s, at 1/8 intervals
- if polling times out, log msg and return -ETIMEDOUT
Changes from v1 to v2:
- Add Stefan's code for getPortProfileStatus
- Poll for up to 2 secs for port-profile status, at 1/8 sec intervals:
- if status indicates error, abort openMacvtapTap
- if status indicates success, exit polling
- if status is "in-progress" after 2 secs of polling, exit
polling loop silently, without error
My patch finishes out the 802.1Qbh parts, which Stefan had mostly complete.
I've tested using the recent kernel updates for VF_PORT netlink msgs and
enic for Cisco's 10G Ethernet NIC. I tested many VMs, each with several
direct interfaces, each configured with a port-profile per the XML. VM-to-VM,
and VM-to-external work as expected. VM-to-VM on same host (using same NIC)
works same as VM-to-VM where VMs are on diff hosts. I'm able to change
settings on the port-profile while the VM is running to change the virtual
port behaviour. For example, adjusting a QoS setting like rate limit. All
VMs with interfaces using that port-profile immediatly see the effect of the
change to the port-profile.
I don't have a SR-IOV device to test so source dev is a non-SR-IOV device,
but most of the code paths include support for specifing the source dev and
VF index. We'll need to complete this by discovering the PF given the VF
linkdev. Once we have the PF, we'll also have the VF index. All this info-
mation is available from sysfs.
Signed-off-by: Scott Feldman <scofeldm(a)cisco.com>
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
---
configure.ac | 17
src/libvirt_private.syms | 3
src/qemu/qemu_conf.c | 2
src/qemu/qemu_driver.c | 4
src/util/interface.c | 141 +++++-
src/util/interface.h | 5
src/util/macvtap.c | 1098 +++++++++++++++++++++++++++++++++++++++++++----
src/util/macvtap.h | 10
8 files changed, 1177 insertions(+), 103 deletions(-)
Index: libvirt-acl/configure.ac
===================================================================
--- libvirt-acl.orig/configure.ac
+++ libvirt-acl/configure.ac
@@ -2005,13 +2005,27 @@ if test "$with_macvtap" != "no" ; then
fi
AM_CONDITIONAL([WITH_MACVTAP], [test "$with_macvtap" = "yes"])
+AC_TRY_COMPILE([ #include <sys/socket.h>
+ #include <linux/rtnetlink.h> ],
+ [ int x = IFLA_PORT_MAX; ],
+ [ with_virtualport=yes ],
+ [ with_virtualport=no ])
+if test "$with_virtualport" = "yes"; then
+ val=1
+else
+ val=0
+fi
+AC_DEFINE_UNQUOTED([WITH_VIRTUALPORT], $val,
+ [whether vsi vepa support is enabled])
+AM_CONDITIONAL([WITH_VIRTUALPORT], [test "$with_virtualport" = "yes"])
+
dnl netlink library
LIBNL_CFLAGS=""
LIBNL_LIBS=""
-if test "$with_macvtap" = "yes"; then
+if test "$with_macvtap" = "yes" || test "$with_virtualport" = "yes"; then
PKG_CHECK_MODULES([LIBNL], [libnl-1 >= $LIBNL_REQUIRED], [
], [
AC_MSG_ERROR([libnl >= $LIBNL_REQUIRED is required for macvtap support])
@@ -2084,6 +2098,7 @@ AC_MSG_NOTICE([ Network: $with_network])
AC_MSG_NOTICE([Libvirtd: $with_libvirtd])
AC_MSG_NOTICE([ netcf: $with_netcf])
AC_MSG_NOTICE([ macvtap: $with_macvtap])
+AC_MSG_NOTICE([virtport: $with_virtualport])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([Storage Drivers])
AC_MSG_NOTICE([])
Index: libvirt-acl/src/qemu/qemu_conf.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_conf.c
+++ libvirt-acl/src/qemu/qemu_conf.c
@@ -1554,7 +1554,7 @@ qemudPhysIfaceConnect(virConnectPtr conn
if (err) {
close(rc);
rc = -1;
- delMacvtap(net->ifname,
+ delMacvtap(net->ifname, net->data.direct.linkdev,
&net->data.direct.virtPortProfile);
}
}
Index: libvirt-acl/src/qemu/qemu_driver.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_driver.c
+++ libvirt-acl/src/qemu/qemu_driver.c
@@ -3709,7 +3709,7 @@ static void qemudShutdownVMDaemon(struct
for (i = 0; i < def->nnets; i++) {
virDomainNetDefPtr net = def->nets[i];
if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT)
- delMacvtap(net->ifname,
+ delMacvtap(net->ifname, net->data.direct.linkdev,
&net->data.direct.virtPortProfile);
}
#endif
@@ -8546,7 +8546,7 @@ qemudDomainDetachNetDevice(struct qemud_
#if WITH_MACVTAP
if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT)
- delMacvtap(detach->ifname,
+ delMacvtap(detach->ifname, detach->data.direct.linkdev,
&detach->data.direct.virtPortProfile);
#endif
Index: libvirt-acl/src/util/macvtap.c
===================================================================
--- libvirt-acl.orig/src/util/macvtap.c
+++ libvirt-acl/src/util/macvtap.c
@@ -27,7 +27,7 @@
#include <config.h>
-#if WITH_MACVTAP
+#if WITH_MACVTAP || WITH_VIRTUALPORT
# include <stdio.h>
# include <errno.h>
@@ -41,6 +41,8 @@
# include <linux/rtnetlink.h>
# include <linux/if_tun.h>
+# include <netlink/msg.h>
+
# include "util.h"
# include "memory.h"
# include "logging.h"
@@ -48,6 +50,7 @@
# include "interface.h"
# include "conf/domain_conf.h"
# include "virterror_internal.h"
+# include "uuid.h"
# define VIR_FROM_THIS VIR_FROM_NET
@@ -58,14 +61,22 @@
# define MACVTAP_NAME_PREFIX "macvtap"
# define MACVTAP_NAME_PATTERN "macvtap%d"
+# define MICROSEC_PER_SEC (1000 * 1000)
+
+# define NLMSGBUF_SIZE 256
+# define RATTBUF_SIZE 64
+
+
+# define STATUS_POLL_TIMEOUT_USEC (10 * MICROSEC_PER_SEC)
+# define STATUS_POLL_INTERVL_USEC (MICROSEC_PER_SEC / 8)
-static int associatePortProfileId(const char *macvtap_ifname,
- const virVirtualPortProfileParamsPtr virtPort,
- int vf,
- const unsigned char *vmuuid);
-static int disassociatePortProfileId(const char *macvtap_ifname,
- const virVirtualPortProfileParamsPtr virtPort);
+
+
+enum virVirtualPortOp {
+ ASSOCIATE = 0x1,
+ DISASSOCIATE = 0x2,
+};
static int nlOpen(void)
@@ -97,7 +108,7 @@ static void nlClose(int fd)
*/
static
int nlComm(struct nlmsghdr *nlmsg,
- char **respbuf, int *respbuflen)
+ char **respbuf, unsigned int *respbuflen)
{
int rc = 0;
struct sockaddr_nl nladdr = {
@@ -159,6 +170,162 @@ err_exit:
}
+# ifdef IFLA_VF_PORT_MAX
+
+/**
+ * nlCommWaitSuccess:
+ *
+ * @nlmsg: pointer to netlink message
+ * @nl_grousp: the netlink multicast groups to send to
+ * @respbuf: pointer to pointer where response buffer will be allocated
+ * @respbuflen: pointer to integer holding the size of the response buffer
+ * on return of the function.
+ * @timeout_usecs: timeout in microseconds to wait for a success message
+ * to be returned
+ *
+ * Send the given message to the netlink multicast group and receive
+ * responses. Skip responses indicating an error and keep on receiving
+ * responses until a success response is returned.
+ * Returns 0 on success, -1 on error. In case of error, no response
+ * buffer will be returned.
+ */
+static int
+nlCommWaitSuccess(struct nlmsghdr *nlmsg, uint32_t nl_groups,
+ char **respbuf, unsigned int *respbuflen,
+ unsigned long long timeout_usecs)
+{
+ int rc = 0;
+ struct sockaddr_nl nladdr = {
+ .nl_family = AF_NETLINK,
+ .nl_pid = getpid(),
+ .nl_groups = nl_groups,
+ };
+ int rcvChunkSize = 1024; // expecting less than that
+ size_t rcv_offset = 0;
+ ssize_t nbytes;
+ struct timeval tv = {
+ .tv_sec = timeout_usecs / MICROSEC_PER_SEC,
+ .tv_usec = timeout_usecs % MICROSEC_PER_SEC,
+ };
+ bool got_valid = false;
+ int fd = nlOpen();
+ static uint32_t seq = 0x1234;
+ uint32_t myseq = seq++;
+ uint32_t mypid = getpid();
+
+ if (fd < 0)
+ return -1;
+
+ nlmsg->nlmsg_pid = mypid;
+ nlmsg->nlmsg_seq = myseq;
+ nlmsg->nlmsg_flags |= NLM_F_ACK;
+
+ nbytes = sendto(fd, (void *)nlmsg, nlmsg->nlmsg_len, 0,
+ (struct sockaddr *)&nladdr, sizeof(nladdr));
+ if (nbytes < 0) {
+ virReportSystemError(errno,
+ "%s", _("cannot send to netlink socket"));
+ rc = -1;
+ goto err_exit;
+ }
+
+ while (!got_valid) {
+
+ rcv_offset = 0;
+
+ while (1) {
+ int n;
+ fd_set rfds;
+ socklen_t addrlen = sizeof(nladdr);
+
+ if (VIR_REALLOC_N(*respbuf, rcv_offset + rcvChunkSize) < 0) {
+ virReportOOMError();
+ rc = -1;
+ goto err_exit;
+ }
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ n = select(fd + 1, &rfds, NULL, NULL, &tv);
+ if (n <= 0) {
+ if (n < 0)
+ virReportSystemError(errno, "%s",
+ _("error in select call"));
+ if (n == 0)
+ virReportSystemError(ETIMEDOUT, "%s",
+ _("no valid netlink response was received"));
+ rc = -1;
+ goto err_exit;
+ }
+
+ nbytes = recvfrom(fd, &((*respbuf)[rcv_offset]), rcvChunkSize, 0,
+ (struct sockaddr *)&nladdr, &addrlen);
+ if (nbytes < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ virReportSystemError(errno, "%s",
+ _("error receiving from netlink socket"));
+ rc = -1;
+ goto err_exit;
+ }
+ rcv_offset += nbytes;
+ break;
+ }
+ *respbuflen = rcv_offset;
+
+ /* check message for error */
+ if (*respbuflen > NLMSG_LENGTH(0) && *respbuf != NULL) {
+ struct nlmsghdr *resp = (struct nlmsghdr *)*respbuf;
+ struct nlmsgerr *err;
+
+ if (resp->nlmsg_pid != mypid ||
+ resp->nlmsg_seq != myseq)
+ continue;
+
+ /* skip reflected message */
+ if (resp->nlmsg_type & 0x10)
+ continue;
+
+ switch (resp->nlmsg_type) {
+ case NLMSG_ERROR:
+ err = (struct nlmsgerr *)NLMSG_DATA(resp);
+ if (resp->nlmsg_len >= NLMSG_LENGTH(sizeof(*err))) {
+ if (err->error != -EOPNOTSUPP) {
+ /* assuming error msg from daemon */
+ got_valid = true;
+ break;
+ }
+ }
+ /* whatever this is, skip it */
+ VIR_FREE(*respbuf);
+ *respbuflen = 0;
+ break;
+
+ case NLMSG_DONE:
+ got_valid = true;
+ break;
+
+ default:
+ VIR_FREE(*respbuf);
+ *respbuflen = 0;
+ break;
+ }
+ }
+ }
+
+err_exit:
+ if (rc == -1) {
+ VIR_FREE(*respbuf);
+ *respbuflen = 0;
+ }
+
+ nlClose(fd);
+ return rc;
+}
+
+# endif /* IFLA_VF_PORT_MAX */
+
static struct rtattr *
rtattrCreate(char *buffer, int bufsize, int type,
const void *data, int datalen)
@@ -204,6 +371,8 @@ nlAppend(struct nlmsghdr *nlm, int totle
}
+# if WITH_MACVTAP
+
static int
link_add(const char *type,
const unsigned char *macaddress, int macaddrsize,
@@ -213,15 +382,15 @@ link_add(const char *type,
int *retry)
{
int rc = 0;
- char nlmsgbuf[256];
+ char nlmsgbuf[NLMSGBUF_SIZE];
struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp;
struct nlmsgerr *err;
- char rtattbuf[64];
+ char rtattbuf[RATTBUF_SIZE];
struct rtattr *rta, *rta1, *li;
- struct ifinfomsg i = { .ifi_family = AF_UNSPEC };
+ struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
int ifindex;
char *recvbuf = NULL;
- int recvbuflen;
+ unsigned int recvbuflen;
if (ifaceGetIndex(true, srcdev, &ifindex) != 0)
return -1;
@@ -232,65 +401,46 @@ link_add(const char *type,
nlInit(nlm, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL, RTM_NEWLINK);
- if (!nlAppend(nlm, sizeof(nlmsgbuf), &i, sizeof(i)))
+ if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo, sizeof(ifinfo)))
goto buffer_too_small;
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_LINK,
&ifindex, sizeof(ifindex));
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_ADDRESS,
macaddress, macaddrsize);
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
if (ifname) {
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME,
ifname, strlen(ifname) + 1);
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
}
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_LINKINFO, NULL, 0);
- if (!rta)
- goto buffer_too_small;
-
- if (!(li = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
+ if (!rta ||
+ !(li = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
goto buffer_too_small;
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_INFO_KIND,
type, strlen(type));
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
if (macvlan_mode > 0) {
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_INFO_DATA,
NULL, 0);
- if (!rta)
- goto buffer_too_small;
-
- if (!(rta1 = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
+ if (!rta ||
+ !(rta1 = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
goto buffer_too_small;
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_MACVLAN_MODE,
&macvlan_mode, sizeof(macvlan_mode));
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
rta1->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)rta1;
@@ -312,15 +462,15 @@ link_add(const char *type,
if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
goto malformed_resp;
- switch (-err->error) {
+ switch (err->error) {
case 0:
- break;
+ break;
- case EEXIST:
+ case -EEXIST:
*retry = 1;
rc = -1;
- break;
+ break;
default:
virReportSystemError(-err->error,
@@ -328,10 +478,10 @@ link_add(const char *type,
type);
rc = -1;
}
- break;
+ break;
case NLMSG_DONE:
- break;
+ break;
default:
goto malformed_resp;
@@ -358,14 +508,14 @@ static int
link_del(const char *name)
{
int rc = 0;
- char nlmsgbuf[256];
+ char nlmsgbuf[NLMSGBUF_SIZE];
struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp;
struct nlmsgerr *err;
- char rtattbuf[64];
+ char rtattbuf[RATTBUF_SIZE];
struct rtattr *rta;
struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
char *recvbuf = NULL;
- int recvbuflen;
+ unsigned int recvbuflen;
memset(&nlmsgbuf, 0, sizeof(nlmsgbuf));
@@ -376,10 +526,7 @@ link_del(const char *name)
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME,
name, strlen(name)+1);
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
if (nlComm(nlm, &recvbuf, &recvbuflen) < 0)
@@ -396,20 +543,16 @@ link_del(const char *name)
if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
goto malformed_resp;
- switch (-err->error) {
- case 0:
- break;
-
- default:
+ if (err->error) {
virReportSystemError(-err->error,
_("error destroying %s interface"),
name);
rc = -1;
}
- break;
+ break;
case NLMSG_DONE:
- break;
+ break;
default:
goto malformed_resp;
@@ -509,11 +652,9 @@ macvtapModeFromInt(enum virDomainNetdevM
switch (mode) {
case VIR_DOMAIN_NETDEV_MACVTAP_MODE_PRIVATE:
return MACVLAN_MODE_PRIVATE;
- break;
case VIR_DOMAIN_NETDEV_MACVTAP_MODE_BRIDGE:
return MACVLAN_MODE_BRIDGE;
- break;
case VIR_DOMAIN_NETDEV_MACVTAP_MODE_VEPA:
default:
@@ -654,10 +795,11 @@ create_name:
cr_ifname = ifname;
}
- if (associatePortProfileId(cr_ifname,
- virtPortProfile,
- -1,
- vmuuid) != 0) {
+ if (vpAssociatePortProfileId(cr_ifname,
+ macaddress,
+ linkdev,
+ virtPortProfile,
+ vmuuid) != 0) {
rc = -1;
goto link_del_exit;
}
@@ -688,8 +830,9 @@ create_name:
return rc;
disassociate_exit:
- disassociatePortProfileId(cr_ifname,
- virtPortProfile);
+ vpDisassociatePortProfileId(cr_ifname,
+ linkdev,
+ virtPortProfile);
link_del_exit:
link_del(cr_ifname);
@@ -701,6 +844,7 @@ link_del_exit:
/**
* delMacvtap:
* @ifname : The name of the macvtap interface
+ * @linkdev: The interface name of the NIC to connect to the external bridge
* @virtPortProfile: pointer to object holding the virtual port profile data
*
* Delete an interface given its name. Disassociate
@@ -709,22 +853,789 @@ link_del_exit:
*/
void
delMacvtap(const char *ifname,
+ const char *linkdev,
virVirtualPortProfileParamsPtr virtPortProfile)
{
if (ifname) {
- disassociatePortProfileId(ifname,
- virtPortProfile);
+ vpDisassociatePortProfileId(ifname,
+ linkdev,
+ virtPortProfile);
link_del(ifname);
}
}
+# endif /* WITH_MACVTAP */
+
+# ifdef IFLA_PORT_MAX
+
+static struct nla_policy ifla_policy[IFLA_MAX + 1] =
+{
+ [IFLA_VF_PORTS] = { .type = NLA_NESTED },
+};
+
+static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] =
+{
+ [IFLA_PORT_RESPONSE] = { .type = NLA_U16 },
+};
+
+
+static int
+link_dump(bool nltarget_kernel, const char *ifname, int ifindex,
+ struct nlattr **tb, char **recvbuf)
+{
+ int rc = 0;
+ char nlmsgbuf[NLMSGBUF_SIZE] = { 0, };
+ struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp;
+ struct nlmsgerr *err;
+ char rtattbuf[RATTBUF_SIZE];
+ struct rtattr *rta;
+ struct ifinfomsg ifinfo = {
+ .ifi_family = AF_UNSPEC,
+ .ifi_index = ifindex
+ };
+ unsigned int recvbuflen;
+
+ *recvbuf = NULL;
+
+ nlInit(nlm, NLM_F_REQUEST, RTM_GETLINK);
+
+ if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo, sizeof(ifinfo)))
+ goto buffer_too_small;
+
+ if (ifindex < 0 && ifname) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME,
+ ifname, strlen(ifname) + 1);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (nltarget_kernel) {
+ if (nlComm(nlm, recvbuf, &recvbuflen) < 0)
+ return -1;
+ } else {
+ if (nlCommWaitSuccess(nlm, RTMGRP_LINK, recvbuf, &recvbuflen,
+ 5 * MICROSEC_PER_SEC) < 0)
+ return -1;
+ }
+
+ if (recvbuflen < NLMSG_LENGTH(0) || *recvbuf == NULL)
+ goto malformed_resp;
+
+ resp = (struct nlmsghdr *)*recvbuf;
+
+ switch (resp->nlmsg_type) {
+ case NLMSG_ERROR:
+ err = (struct nlmsgerr *)NLMSG_DATA(resp);
+ if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
+ goto malformed_resp;
+
+ if (err->error) {
+ virReportSystemError(-err->error,
+ _("error dumping %d interface"),
+ ifindex);
+ rc = -1;
+ }
+ break;
+
+ case GENL_ID_CTRL:
+ case NLMSG_DONE:
+ if (nlmsg_parse(resp, sizeof(struct ifinfomsg),
+ tb, IFLA_MAX, ifla_policy)) {
+ goto malformed_resp;
+ }
+ break;
+
+ default:
+ goto malformed_resp;
+ }
+
+ if (rc != 0)
+ VIR_FREE(*recvbuf);
+
+ return rc;
+
+malformed_resp:
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed netlink response message"));
+ VIR_FREE(*recvbuf);
+ return -1;
+
+buffer_too_small:
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("internal buffer is too small"));
+ return -1;
+}
+
+
+/**
+ * ifaceGetNthParent
+ *
+ * @ifindex : the index of the interface or -1 if ifname is given
+ * @ifname : the name of the interface; ignored if ifindex is valid
+ * @nthParent : the nth parent interface to get
+ * @parent_ifindex : pointer to int
+ * @parent_ifname : pointer to buffer of size IFNAMSIZ
+ * @nth : the nth parent that is actually returned; if for example eth0.100
+ * was given and the 100th parent is to be returned, then eth0 will
+ * most likely be returned with nth set to 1 since the chain does
+ * not have more interfaces
+ *
+ * Get the nth parent interface of the given interface. 0 is the interface
+ * itself.
+ *
+ * Return 0 on success, != 0 otherwise
+ */
+static int
+ifaceGetNthParent(int ifindex, const char *ifname, unsigned int nthParent,
+ int *parent_ifindex, char *parent_ifname,
+ unsigned int *nth)
+{
+ int rc;
+ struct nlattr *tb[IFLA_MAX + 1];
+ char *recvbuf = NULL;
+ bool end = false;
+ unsigned int i = 0;
+
+ *nth = 0;
+
+ while (!end && i <= nthParent) {
+ rc = link_dump(true, ifname, ifindex, tb, &recvbuf);
+ if (rc)
+ break;
+
+ if (tb[IFLA_IFNAME]) {
+ if (!virStrcpy(parent_ifname, (char*)RTA_DATA(tb[IFLA_IFNAME]),
+ IFNAMSIZ)) {
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("buffer for root interface name is too small"));
+ VIR_FREE(recvbuf);
+ return 1;
+ }
+ *parent_ifindex = ifindex;
+ }
+
+ if (tb[IFLA_LINK]) {
+ ifindex = *(int *)RTA_DATA(tb[IFLA_LINK]);
+ ifname = NULL;
+ } else
+ end = true;
+
+ VIR_FREE(recvbuf);
+
+ i++;
+ }
+
+ if (nth)
+ *nth = i - 1;
+
+ return rc;
+}
/**
- * associatePortProfile
+ * getPortProfileStatus
+ *
+ * tb: top level netlink response attributes + values
+ * vf: The virtual function used in the request
+ * profileId : 802.1Qbh must pass the profileId , 8021Qbg must pass NULL
+ * instanceId: 802.1Qbg must pass the instanceId, 8021Qbh must pass NULL
+ * status: pointer to a uint16 where the status will be written into
+ *
+ * Get the status from the IFLA_PORT_RESPONSE field; Returns 0 in
+ * case of success, != 0 otherwise with error having been reported
+ */
+static int
+getPortProfileStatus(struct nlattr **tb, int32_t vf,
+ const char *profileId,
+ const unsigned char *instanceId,
+ uint16_t *status)
+{
+ int rc = 1;
+ const char *msg = NULL;
+ struct nlattr *tb_port[IFLA_PORT_MAX+1];
+ bool is8021Qbh = (profileId != NULL);
+
+ if (vf == PORT_SELF_VF && is8021Qbh) {
+ if (tb[IFLA_PORT_SELF]) {
+ if (nla_parse_nested(tb_port, IFLA_PORT_MAX, tb[IFLA_PORT_SELF],
+ ifla_port_policy)) {
+ msg = _("error parsing IFLA_VF_SELF part");
+ goto err_exit;
+ }
+ } else {
+ msg = _("IFLA_VF_SELF is missing");
+ goto err_exit;
+ }
+ } else {
+ if (tb[IFLA_VF_PORTS]) {
+ int rem;
+ bool found = false;
+ struct nlattr *tb_vf_ports;
+
+ nla_for_each_nested(tb_vf_ports, tb[IFLA_VF_PORTS], rem) {
+
+ if (nla_type(tb_vf_ports) != IFLA_VF_PORT) {
+ msg = _("error while iterating over IFLA_VF_PORTS part");
+ goto err_exit;
+ }
+
+ if (nla_parse_nested(tb_port, IFLA_PORT_MAX, tb_vf_ports,
+ ifla_port_policy)) {
+ msg = _("error parsing IFLA_VF_PORT part");
+ goto err_exit;
+ }
+
+ if (profileId &&
+ tb_port[IFLA_PORT_PROFILE] &&
+ STREQ(profileId,
+ (char *)tb_port[IFLA_PORT_PROFILE])) {
+ found = true;
+ break;
+ }
+
+ if (instanceId &&
+ tb_port[IFLA_PORT_INSTANCE_UUID] &&
+ !memcmp(instanceId,
+ (unsigned char *)tb_port[IFLA_PORT_INSTANCE_UUID],
+ VIR_UUID_BUFLEN)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ msg = _("Could not find netlink response with "
+ "expected parameters");
+ goto err_exit;
+ }
+ } else {
+ msg = _("IFLA_VF_PORTS is missing");
+ goto err_exit;
+ }
+ }
+
+ if (tb_port[IFLA_PORT_RESPONSE]) {
+ *status = *(uint16_t *)RTA_DATA(tb_port[IFLA_PORT_RESPONSE]);
+ rc = 0;
+ } else {
+ msg = _("no IFLA_PORT_RESPONSE found in netlink message");
+ goto err_exit;
+ }
+
+err_exit:
+ if (msg)
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", msg);
+
+ return rc;
+}
+
+
+static int
+doPortProfileOpSetLink(bool nltarget_kernel,
+ const char *ifname, int ifindex,
+ const unsigned char *macaddr,
+ int vlanid,
+ const char *profileId,
+ struct ifla_port_vsi *portVsi,
+ const unsigned char *instanceId,
+ const unsigned char *hostUUID,
+ int32_t vf,
+ uint8_t op)
+{
+ int rc = 0;
+ char nlmsgbuf[NLMSGBUF_SIZE];
+ struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp;
+ struct nlmsgerr *err;
+ char rtattbuf[RATTBUF_SIZE];
+ struct rtattr *rta, *vfports = NULL, *vfport;
+ struct ifinfomsg ifinfo = {
+ .ifi_family = AF_UNSPEC,
+ .ifi_index = ifindex,
+ };
+ char *recvbuf = NULL;
+ unsigned int recvbuflen = 0;
+ bool is8021Qbh = (profileId != NULL);
+
+ memset(&nlmsgbuf, 0, sizeof(nlmsgbuf));
+
+ nlInit(nlm, NLM_F_REQUEST, RTM_SETLINK);
+
+ if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo, sizeof(ifinfo)))
+ goto buffer_too_small;
+
+
+ if (ifname) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME,
+ ifname, strlen(ifname) + 1);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (macaddr && vlanid >= 0) {
+ struct rtattr *vfinfolist, *vfinfo;
+ struct ifla_vf_mac ifla_vf_mac = {
+ .vf = vf,
+ .mac = { 0, },
+ };
+ struct ifla_vf_vlan ifla_vf_vlan = {
+ .vf = vf,
+ .vlan = vlanid,
+ .qos = 0,
+ };
+
+ memcpy(ifla_vf_mac.mac, macaddr, 6);
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VFINFO_LIST,
+ NULL, 0);
+ if (!rta ||
+ !(vfinfolist = nlAppend(nlm, sizeof(nlmsgbuf),
+ rtattbuf, rta->rta_len)))
+ goto buffer_too_small;
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_INFO,
+ NULL, 0);
+ if (!rta ||
+ !(vfinfo = nlAppend(nlm, sizeof(nlmsgbuf),
+ rtattbuf, rta->rta_len)))
+ goto buffer_too_small;
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_MAC,
+ &ifla_vf_mac, sizeof(ifla_vf_mac));
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_VLAN,
+ &ifla_vf_vlan, sizeof(ifla_vf_vlan));
+
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+
+ vfinfo->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)vfinfo;
+
+ vfinfolist->rta_len = (char *)nlm + nlm->nlmsg_len -
+ (char *)vfinfolist;
+ }
+
+ if (vf == PORT_SELF_VF && is8021Qbh) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_SELF, NULL, 0);
+ } else {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_PORTS, NULL, 0);
+ if (!rta ||
+ !(vfports = nlAppend(nlm, sizeof(nlmsgbuf),
+ rtattbuf, rta->rta_len)))
+ goto buffer_too_small;
+
+ /* begin nesting vfports */
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_PORT, NULL, 0);
+ }
+
+ if (!rta ||
+ !(vfport = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
+ goto buffer_too_small;
+
+ if (profileId) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_PROFILE,
+ profileId, strlen(profileId) + 1);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (portVsi) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_VSI_TYPE,
+ portVsi, sizeof(*portVsi));
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (instanceId) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_INSTANCE_UUID,
+ instanceId, VIR_UUID_BUFLEN);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (hostUUID) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_HOST_UUID,
+ hostUUID, VIR_UUID_BUFLEN);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (vf != PORT_SELF_VF) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_VF,
+ &vf, sizeof(vf));
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_REQUEST,
+ &op, sizeof(op));
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+
+ /* end nesting of vport */
+ vfport->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)vfport;
+
+ if (vf != PORT_SELF_VF) {
+ /* end nesting of vfports */
+ vfports->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)vfports;
+ }
+
+ if (nltarget_kernel) {
+ if (nlComm(nlm, &recvbuf, &recvbuflen) < 0)
+ return -1;
+ } else {
+ if (nlCommWaitSuccess(nlm, RTMGRP_LINK, &recvbuf, &recvbuflen,
+ 5 * MICROSEC_PER_SEC) < 0)
+ return -1;
+ }
+
+ if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL)
+ goto malformed_resp;
+
+ resp = (struct nlmsghdr *)recvbuf;
+
+ switch (resp->nlmsg_type) {
+ case NLMSG_ERROR:
+ err = (struct nlmsgerr *)NLMSG_DATA(resp);
+ if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
+ goto malformed_resp;
+
+ if (err->error) {
+ virReportSystemError(-err->error,
+ _("error during virtual port configuration of ifindex %d"),
+ ifindex);
+ rc = -1;
+ }
+ break;
+
+ case NLMSG_DONE:
+ break;
+
+ default:
+ goto malformed_resp;
+ }
+
+ VIR_FREE(recvbuf);
+
+ return rc;
+
+malformed_resp:
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed netlink response message"));
+ VIR_FREE(recvbuf);
+ return -1;
+
+buffer_too_small:
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("internal buffer is too small"));
+ return -1;
+}
+
+
+static int
+doPortProfileOpCommon(bool nltarget_kernel,
+ const char *ifname, int ifindex,
+ const unsigned char *macaddr,
+ int vlanid,
+ const char *profileId,
+ struct ifla_port_vsi *portVsi,
+ const unsigned char *instanceId,
+ const unsigned char *hostUUID,
+ int32_t vf,
+ uint8_t op)
+{
+ int rc;
+ char *recvbuf = NULL;
+ struct nlattr *tb[IFLA_MAX + 1];
+ int repeats = STATUS_POLL_TIMEOUT_USEC / STATUS_POLL_INTERVL_USEC;
+ uint16_t status = 0;
+
+ rc = doPortProfileOpSetLink(nltarget_kernel,
+ ifname, ifindex,
+ macaddr,
+ vlanid,
+ profileId,
+ portVsi,
+ instanceId,
+ hostUUID,
+ vf,
+ op);
+
+ if (rc != 0) {
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("sending of PortProfileRequest failed."));
+ return rc;
+ }
+
+ while (--repeats >= 0) {
+ rc = link_dump(nltarget_kernel, NULL, ifindex, tb, &recvbuf);
+ if (rc)
+ goto err_exit;
+ rc = getPortProfileStatus(tb, vf, profileId, instanceId, &status);
+ if (rc == 0) {
+ if (status == PORT_PROFILE_RESPONSE_SUCCESS ||
+ status == PORT_VDP_RESPONSE_SUCCESS) {
+ break;
+ } else if (status == PORT_PROFILE_RESPONSE_INPROGRESS) {
+ // keep trying...
+ } else {
+ virReportSystemError(EINVAL,
+ _("error %d during port-profile setlink on ifindex %d"),
+ status, ifindex);
+ rc = 1;
+ break;
+ }
+ } else
+ goto err_exit;
+
+ usleep(STATUS_POLL_INTERVL_USEC);
+
+ VIR_FREE(recvbuf);
+ }
+
+ if (status == PORT_PROFILE_RESPONSE_INPROGRESS) {
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("port-profile setlink timed out"));
+ rc = -ETIMEDOUT;
+ }
+
+err_exit:
+ VIR_FREE(recvbuf);
+
+ return rc;
+}
+
+# endif /* IFLA_PORT_MAX */
+
+
+# ifdef IFLA_VF_PORT_MAX
+
+static int
+getPhysdevAndVlan(const char *ifname, int *root_ifindex, char *root_ifname,
+ int *vlanid)
+{
+ int ret;
+ unsigned int nth;
+ int ifindex = -1;
+
+ *vlanid = -1;
+ while (1) {
+ if ((ret = ifaceGetNthParent(ifindex, ifname, 1,
+ root_ifindex, root_ifname, &nth)))
+ return ret;
+ if (nth == 0)
+ break;
+ if (*vlanid == -1) {
+ if (ifaceGetVlanID(root_ifname, vlanid))
+ *vlanid = -1;
+ }
+
+ ifindex = *root_ifindex;
+ ifname = NULL;
+ }
+
+ return 0;
+}
+
+# endif
+
+static int
+doPortProfileOp8021Qbg(const char *ifname,
+ const unsigned char *macaddr,
+ const virVirtualPortProfileParamsPtr virtPort,
+ enum virVirtualPortOp virtPortOp)
+{
+ int rc;
+
+# ifndef IFLA_VF_PORT_MAX
+
+ (void)ifname;
+ (void)macaddr;
+ (void)virtPort;
+ (void)virtPortOp;
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Kernel VF Port support was missing at compile time."));
+ rc = 1;
+
+# else /* IFLA_VF_PORT_MAX */
+
+ int op = PORT_REQUEST_ASSOCIATE;
+ struct ifla_port_vsi portVsi = {
+ .vsi_mgr_id = virtPort->u.virtPort8021Qbg.managerID,
+ .vsi_type_version = virtPort->u.virtPort8021Qbg.typeIDVersion,
+ };
+ bool nltarget_kernel = false;
+ int vlanid;
+ int physdev_ifindex = 0;
+ char physdev_ifname[IFNAMSIZ] = { 0, };
+ int vf = PORT_SELF_VF;
+
+ if (getPhysdevAndVlan(ifname, &physdev_ifindex, physdev_ifname,
+ &vlanid) != 0) {
+ rc = 1;
+ goto err_exit;
+ }
+
+ if (vlanid < 0)
+ vlanid = 0;
+
+ portVsi.vsi_type_id[2] = virtPort->u.virtPort8021Qbg.typeID >> 16;
+ portVsi.vsi_type_id[1] = virtPort->u.virtPort8021Qbg.typeID >> 8;
+ portVsi.vsi_type_id[0] = virtPort->u.virtPort8021Qbg.typeID;
+
+ switch (virtPortOp) {
+ case ASSOCIATE:
+ op = PORT_REQUEST_ASSOCIATE;
+ break;
+ case DISASSOCIATE:
+ op = PORT_REQUEST_DISASSOCIATE;
+ break;
+ default:
+ macvtapError(VIR_ERR_INTERNAL_ERROR,
+ _("operation type %d not supported"), op);
+ rc = 1;
+ goto err_exit;
+ }
+
+ rc = doPortProfileOpCommon(nltarget_kernel,
+ physdev_ifname, physdev_ifindex,
+ macaddr,
+ vlanid,
+ NULL,
+ &portVsi,
+ virtPort->u.virtPort8021Qbg.instanceID,
+ NULL,
+ vf,
+ op);
+
+err_exit:
+
+# endif /* IFLA_VF_PORT_MAX */
+
+ return rc;
+}
+
+
+# ifdef IFLA_VF_PORT_MAX
+static int
+getPhysfn(const char *linkdev,
+ int32_t *vf,
+ char **physfndev)
+{
+ int rc = 0;
+ bool virtfn = false;
+
+ if (virtfn) {
+
+ // XXX: if linkdev is SR-IOV VF, then set vf = VF index
+ // XXX: and set linkdev = PF device
+ // XXX: need to use get_physical_function_linux() or
+ // XXX: something like that to get PF
+ // XXX: device and figure out VF index
+
+ rc = 1;
+
+ } else {
+
+ /* Not SR-IOV VF: physfndev is linkdev and VF index
+ * refers to linkdev self
+ */
+
+ *vf = PORT_SELF_VF;
+ *physfndev = (char *)linkdev;
+ }
+
+ return rc;
+}
+# endif /* IFLA_VF_PORT_MAX */
+
+static int
+doPortProfileOp8021Qbh(const char *ifname,
+ const virVirtualPortProfileParamsPtr virtPort,
+ const unsigned char *vm_uuid,
+ enum virVirtualPortOp virtPortOp)
+{
+ int rc;
+
+# ifndef IFLA_VF_PORT_MAX
+
+ (void)ifname;
+ (void)virtPort;
+ (void)vm_uuid;
+ (void)virtPortOp;
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Kernel VF Port support was missing at compile time."));
+ rc = 1;
+
+# else /* IFLA_VF_PORT_MAX */
+
+ char *physfndev;
+ unsigned char hostuuid[VIR_UUID_BUFLEN];
+ int32_t vf;
+ int op = PORT_REQUEST_ASSOCIATE;
+ bool nltarget_kernel = true;
+ int ifindex;
+ int vlanid = -1;
+ const unsigned char *macaddr = NULL;
+
+ rc = virGetHostUUID(hostuuid);
+ if (rc)
+ goto err_exit;
+
+ rc = getPhysfn(ifname, &vf, &physfndev);
+ if (rc)
+ goto err_exit;
+
+ if (ifaceGetIndex(true, physfndev, &ifindex) != 0) {
+ rc = 1;
+ goto err_exit;
+ }
+
+ switch (virtPortOp) {
+ case ASSOCIATE:
+ op = PORT_REQUEST_ASSOCIATE;
+ break;
+ case DISASSOCIATE:
+ op = PORT_REQUEST_DISASSOCIATE;
+ break;
+ default:
+ macvtapError(VIR_ERR_INTERNAL_ERROR,
+ _("operation type %d not supported"), op);
+ rc = 1;
+ goto err_exit;
+ }
+
+ rc = doPortProfileOpCommon(nltarget_kernel, NULL, ifindex,
+ macaddr,
+ vlanid,
+ virtPort->u.virtPort8021Qbh.profileID,
+ NULL,
+ vm_uuid,
+ hostuuid,
+ vf,
+ op);
+
+ switch (virtPortOp) {
+ case ASSOCIATE:
+ ifaceUp(ifname);
+ break;
+ case DISASSOCIATE:
+ ifaceDown(ifname);
+ break;
+ }
+
+err_exit:
+
+# endif /* IFLA_VF_PORT_MAX */
+
+ return rc;
+}
+
+/**
+ * vpAssociatePortProfile
*
* @macvtap_ifname: The name of the macvtap device
* @virtPort: pointer to the object holding port profile parameters
- * @vf: virtual function number, -1 if to be ignored
* @vmuuid : the UUID of the virtual machine
*
* Associate a port on a swtich with a profile. This function
@@ -736,17 +1647,17 @@ delMacvtap(const char *ifname,
* Returns 0 in case of success, != 0 otherwise with error
* having been reported.
*/
-static int
-associatePortProfileId(const char *macvtap_ifname,
- const virVirtualPortProfileParamsPtr virtPort,
- int vf,
- const unsigned char *vmuuid)
+int
+vpAssociatePortProfileId(const char *macvtap_ifname,
+ const unsigned char *macvtap_macaddr,
+ const char *linkdev,
+ const virVirtualPortProfileParamsPtr virtPort,
+ const unsigned char *vmuuid)
{
int rc = 0;
+
VIR_DEBUG("Associating port profile '%p' on link device '%s'",
virtPort, macvtap_ifname);
- (void)vf;
- (void)vmuuid;
switch (virtPort->virtPortType) {
case VIR_VIRTUALPORT_NONE:
@@ -754,11 +1665,14 @@ associatePortProfileId(const char *macvt
break;
case VIR_VIRTUALPORT_8021QBG:
-
+ rc = doPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr,
+ virtPort, ASSOCIATE);
break;
case VIR_VIRTUALPORT_8021QBH:
-
+ rc = doPortProfileOp8021Qbh(linkdev, virtPort,
+ vmuuid,
+ ASSOCIATE);
break;
}
@@ -767,19 +1681,22 @@ associatePortProfileId(const char *macvt
/**
- * disassociatePortProfile
+ * vpDisassociatePortProfile
*
* @macvtap_ifname: The name of the macvtap device
+ * @linkdev: The link device in case of macvtap
* @virtPort: point to object holding port profile parameters
*
* Returns 0 in case of success, != 0 otherwise with error
* having been reported.
*/
-static int
-disassociatePortProfileId(const char *macvtap_ifname,
- const virVirtualPortProfileParamsPtr virtPort)
+int
+vpDisassociatePortProfileId(const char *macvtap_ifname,
+ const char *linkdev,
+ const virVirtualPortProfileParamsPtr virtPort)
{
int rc = 0;
+
VIR_DEBUG("Disassociating port profile id '%p' on link device '%s' ",
virtPort, macvtap_ifname);
@@ -789,15 +1706,18 @@ disassociatePortProfileId(const char *ma
break;
case VIR_VIRTUALPORT_8021QBG:
-
+ rc = doPortProfileOp8021Qbg(macvtap_ifname, NULL, virtPort,
+ DISASSOCIATE);
break;
case VIR_VIRTUALPORT_8021QBH:
-
+ rc = doPortProfileOp8021Qbh(linkdev, virtPort,
+ NULL,
+ DISASSOCIATE);
break;
}
return rc;
}
-#endif /* WITH_MACVTAP */
+#endif /* WITH_MACVTAP || WITH_VIRTUALPORT */
Index: libvirt-acl/src/util/macvtap.h
===================================================================
--- libvirt-acl.orig/src/util/macvtap.h
+++ libvirt-acl/src/util/macvtap.h
@@ -72,6 +72,7 @@ int openMacvtapTap(const char *ifname,
char **res_ifname);
void delMacvtap(const char *ifname,
+ const char *linkdev,
virVirtualPortProfileParamsPtr virtPortProfile);
# endif /* WITH_MACVTAP */
@@ -80,6 +81,15 @@ void delMacvtap(const char *ifname,
# define MACVTAP_MODE_VEPA_STR "vepa"
# define MACVTAP_MODE_BRIDGE_STR "bridge"
+int vpAssociatePortProfileId(const char *macvtap_ifname,
+ const unsigned char *macvtap_macaddr,
+ const char *linkdev,
+ const virVirtualPortProfileParamsPtr virtPort,
+ const unsigned char *vmuuid);
+
+int vpDisassociatePortProfileId(const char *macvtap_ifname,
+ const char *linkdev,
+ const virVirtualPortProfileParamsPtr virtPort);
VIR_ENUM_DECL(virVirtualPort)
Index: libvirt-acl/src/libvirt_private.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_private.syms
+++ libvirt-acl/src/libvirt_private.syms
@@ -695,6 +695,9 @@ virArgvToString;
ifaceCtrl;
ifaceCheck;
ifaceGetIndex;
+ifaceGetFlags;
+ifaceIsUp;
+ifaceGetVlanID;
# usb.h
usbGetDevice;
Index: libvirt-acl/src/util/interface.c
===================================================================
--- libvirt-acl.orig/src/util/interface.c
+++ libvirt-acl/src/util/interface.c
@@ -30,6 +30,8 @@
#ifdef __linux__
# include <linux/if.h>
+# include <linux/sockios.h>
+# include <linux/if_vlan.h>
#endif
#include "internal.h"
@@ -42,6 +44,85 @@
virReportErrorHelper(NULL, VIR_FROM_NET, code, __FILE__, \
__FUNCTION__, __LINE__, __VA_ARGS__)
+#if __linux__
+static int
+getFlags(int fd, const char *ifname, struct ifreq *ifr) {
+
+ memset(ifr, 0, sizeof(*ifr));
+
+ if (virStrncpy(ifr->ifr_name,
+ ifname, strlen(ifname), sizeof(ifr->ifr_name)) == NULL)
+ return ENODEV;
+
+ if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0)
+ return errno;
+
+ return 0;
+}
+
+
+/**
+ * ifaceGetFlags
+ *
+ * @ifname : name of the interface
+ * @flags : pointer to short holding the flags on success
+ *
+ * Get the flags of the interface. Returns 0 on success, error code on failure.
+ */
+int
+ifaceGetFlags(const char *ifname, short *flags) {
+ struct ifreq ifr;
+ int rc;
+ int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
+
+ if (fd < 0)
+ return errno;
+
+ rc = getFlags(fd, ifname, &ifr);
+
+ *flags = ifr.ifr_flags;
+
+ close(fd);
+
+ return rc;
+}
+
+
+int
+ifaceIsUp(const char *ifname, bool *up) {
+ short flags;
+ int rc = ifaceGetFlags(ifname, &flags);
+
+ if (rc)
+ return rc;
+
+ *up = ((flags & IFF_UP) == IFF_UP);
+
+ return 0;
+}
+#else
+
+/* Note: Showstopper on cygwin is only missing PF_PACKET */
+
+int
+ifaceGetFlags(const char *ifname ATTRIBUTE_UNUSED,
+ short *flags ATTRIBUTE_UNUSED) {
+ ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("ifaceGetFlags is not supported on non-linux platforms"));
+ return ENOSYS;
+}
+
+int
+ifaceIsUp(const char *ifname ATTRIBUTE_UNUSED,
+ bool *up ATTRIBUTE_UNUSED) {
+
+ ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("ifaceIsUp is not supported on non-linux platforms"));
+ return ENOSYS;
+}
+
+#endif /* __linux__ */
+
/*
* chgIfaceFlags: Change flags on an interface
*
@@ -59,23 +140,16 @@
static int chgIfaceFlags(const char *ifname, short flagclear, short flagset) {
struct ifreq ifr;
int rc = 0;
- int flags;
+ short flags;
short flagmask = (~0 ^ flagclear);
int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
if (fd < 0)
return errno;
- if (virStrncpy(ifr.ifr_name,
- ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) {
- rc = ENODEV;
+ rc = getFlags(fd, ifname, &ifr);
+ if (rc != 0)
goto err_exit;
- }
-
- if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
- rc = errno;
- goto err_exit;
- }
flags = (ifr.ifr_flags & flagmask) | flagset;
@@ -151,6 +225,8 @@ ifaceCheck(bool reportError, const char
if (fd < 0)
return errno;
+ memset(&ifr, 0, sizeof(ifr));
+
if (virStrncpy(ifr.ifr_name,
ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) {
if (reportError)
@@ -227,6 +303,8 @@ ifaceGetIndex(bool reportError, const ch
if (fd < 0)
return errno;
+ memset(&ifreq, 0, sizeof(ifreq));
+
if (virStrncpy(ifreq.ifr_name, ifname, strlen(ifname),
sizeof(ifreq.ifr_name)) == NULL) {
if (reportError)
@@ -269,3 +347,46 @@ ifaceGetIndex(bool reportError,
}
#endif /* __linux__ */
+
+#ifdef __linux__
+int
+ifaceGetVlanID(const char *vlanifname, int *vlanid) {
+ struct vlan_ioctl_args vlanargs = {
+ .cmd = GET_VLAN_VID_CMD,
+ };
+ int rc = 0;
+ int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
+
+ if (fd < 0)
+ return errno;
+
+ if (virStrcpyStatic(vlanargs.device1, vlanifname) == NULL) {
+ rc = EINVAL;
+ goto err_exit;
+ }
+
+ if (ioctl(fd, SIOCGIFVLAN, &vlanargs) != 0) {
+ rc = errno;
+ goto err_exit;
+ }
+
+ *vlanid = vlanargs.u.VID;
+
+ err_exit:
+ close(fd);
+
+ return rc;
+}
+
+#else
+
+int
+ifaceGetVlanID(const char *vlanifname ATTRIBUTE_UNUSED,
+ int *vlanid ATTRIBUTE_UNUSED) {
+
+ ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("ifaceGetVlanID is not supported on non-linux platforms"));
+
+ return ENOSYS;
+}
+#endif /* __linux__ */
Index: libvirt-acl/src/util/interface.h
===================================================================
--- libvirt-acl.orig/src/util/interface.h
+++ libvirt-acl/src/util/interface.h
@@ -12,6 +12,9 @@
# include "datatypes.h"
+int ifaceGetFlags(const char *name, short *flags);
+int ifaceIsUp(const char *name, bool *up);
+
int ifaceCtrl(const char *name, bool up);
static inline int ifaceUp(const char *name) {
@@ -27,4 +30,6 @@ int ifaceCheck(bool reportError, const c
int ifaceGetIndex(bool reportError, const char *ifname, int *ifindex);
+int ifaceGetVlanID(const char *vlanifname, int *vlanid);
+
#endif /* __VIR_INTERFACE_H__ */
14 years, 7 months
Re: [libvirt] How to obtain rights to extend libvirt documentation pages
by Daniel P. Berrange
On Thu, May 27, 2010 at 12:26:35PM +0600, ???? ????????? wrote:
> 2010/5/25 Daniel P. Berrange <berrange(a)redhat.com>:
> > On Tue, May 25, 2010 at 01:07:50PM +0600, ???? ????????? wrote:
> >> For example, http://libvirt.org/formatdomain.html#elementsDisks
> >> does not contain <serial>xxxx</serial> tag.
> >> (https://bugzilla.redhat.com/show_bug.cgi?id=593266)
> >>
> >> I wrote to community (users and developers). No one has added this
> >> information to the site...
> >
> > The website is all stored in the main GIT repository
> >
> > http://libvirt.org/git/?p=libvirt.git;a=summary
> >
> > under the 'docs/' subdirectory. If you want to contribute, just send a patch
> > for the .html.in file in docs/
>
> Huge thanks. Patch attached. I will create more patches to
> documentation. Where to send them ?
Thanks, I have just pushed your patch to the repo. It'll appear on the website
within the hour.
commit dafd354d12e5f16844342ebbeb345fadd22fba69
Author: ÐаÑк ÐоÑенбеÑг <socketpair gmail com>
Date: Thu May 27 12:44:41 2010 +0100
Add docs on drive <serial> element
* docs/formatdomain.html.in: Document <serial> element within
<disk> and fix typo on <driver/> element
Daniel
> diff -ur docs/formatdomain.html.in docs.new/formatdomain.html.in
> --- docs/formatdomain.html.in 2010-05-27 11:35:33.995122526 +0600
> +++ docs.new/formatdomain.html.in 2010-05-27 12:20:07.574622370 +0600
> @@ -477,13 +477,16 @@
> ...
> <devices>
> <disk type='file'>
> - <driver name="tap" type="aio" cache="default">
> + <driver name="tap" type="aio" cache="default"/>
> <source file='/var/lib/xen/images/fv0'/>
> <target dev='hda' bus='ide'/>
> <encryption type='...'>
> ...
> </encryption>
> <shareable/>
> + <serial>
> + ...
> + </serial>
> </disk>
> </devices>
> ...</pre>
> @@ -532,6 +535,11 @@
> between domains (assuming the hypervisor and OS support this),
> which means that caching should be deactivated for that device.
> </dd>
> + <dt><code>serial</code></dt>
> + <dd>If present, this specify serial number of virtual hard drive.
> + For example, it may look as <code><serial>WD-WMAP9A966149</serial></code>.
> + <span class="since">Since 0.7.1</span>
> + </dd>
> </dl>
>
> <h4><a name="elementsUSB">USB and PCI devices</a></h4>
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
14 years, 7 months
[libvirt] [PATCH v2] network: bridge: Don't start network if it collides with host routing
by Cole Robinson
Fedora bug https://bugzilla.redhat.com/show_bug.cgi?id=235961
If using the default virtual network, an easy way to lose guest network
connectivity is to install libvirt inside the VM. The autostarted
default network inside the guest collides with host virtual network
routing. This is a long standing issue that has caused users quite a
bit of pain and confusion.
On network startup, parse /proc/net/route and compare the requested
IP+netmask against host routing destinations: if any matches are found,
refuse to start the network.
v2: Drop sscanf, fix a comment typo, comment that function could use
libnl instead of /proc
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
src/network/bridge_driver.c | 102 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 102 insertions(+), 0 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 5d7ef19..090bed7 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -42,6 +42,8 @@
#include <stdio.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include "virterror_internal.h"
#include "datatypes.h"
@@ -908,6 +910,102 @@ cleanup:
return ret;
}
+#define PROC_NET_ROUTE "/proc/net/route"
+
+/* XXX: This function can be a lot more exhaustive, there are certainly
+ * other scenarios where we can ruin host network connectivity.
+ * XXX: Using a proper library is preferred over parsing /proc
+ */
+static int networkCheckRouteCollision(virNetworkObjPtr network)
+{
+ int ret = -1, len;
+ char *cur, *buf = NULL;
+ enum {MAX_ROUTE_SIZE = 1024*64};
+ struct in_addr inaddress, innetmask;
+ char *netaddr = NULL;
+
+ if (!network->def->ipAddress || !network->def->netmask)
+ return 0;
+
+ if (inet_pton(AF_INET, network->def->ipAddress, &inaddress) <= 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse IP address '%s'"),
+ network->def->ipAddress);
+ goto error;
+ }
+ if (inet_pton(AF_INET, network->def->netmask, &innetmask) <= 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse netmask '%s'"),
+ network->def->netmask);
+ goto error;
+ }
+
+ inaddress.s_addr &= innetmask.s_addr;
+ netaddr = strdup(inet_ntoa(inaddress));
+ if (!netaddr) {
+ virReportOOMError();
+ goto error;
+ }
+
+ /* Read whole routing table into memory */
+ if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
+ goto error;
+
+ /* Dropping the last character shouldn't hurt */
+ buf[len-1] = '\0';
+
+ /* First line is just headings, skip it */
+ cur = strchr(buf, '\n');
+
+ while (cur) {
+ char *iface, *dest_raw;
+ char *dest_ip;
+ struct in_addr in;
+ unsigned int addr_val;
+
+ cur++;
+
+ /* Delimit interface field */
+ iface = cur;
+ while(*cur > ' ') {
+ cur++;
+ }
+ *cur++ = '\0';
+
+ /* Delimit destination field */
+ dest_raw = cur;
+ while(*cur > ' ') {
+ cur++;
+ }
+ *cur++ = '\0';
+
+ if (virStrToLong_ui(dest_raw, NULL, 16, &addr_val) < 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to convert network address %s"),
+ dest_raw);
+ goto error;
+ }
+
+ in.s_addr = addr_val;
+ dest_ip = inet_ntoa(in);
+
+ if (STREQ(netaddr, dest_ip)) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Network destination %s is already in use "
+ "by interface %s"), netaddr, iface);
+ goto error;
+ }
+
+ cur = strchr(cur, '\n');
+ }
+
+ ret = 0;
+error:
+ VIR_FREE(buf);
+ VIR_FREE(netaddr);
+ return ret;
+}
+
static int networkStartNetworkDaemon(struct network_driver *driver,
virNetworkObjPtr network)
{
@@ -919,6 +1017,10 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
return -1;
}
+ /* Check to see if network collides with an existing route */
+ if (networkCheckRouteCollision(network) < 0)
+ return -1;
+
if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
virReportSystemError(err,
_("cannot create bridge '%s'"),
--
1.6.6.1
14 years, 7 months
[libvirt] Status and future releases suggestion
by Daniel Veillard
Hi everybody,
as you may have noticed I went silent some time ago, reason is that
I'm in vacation, far away from home, so not in an ideal setting to
follow and suggest a release.
I didn't see any significant feature being pushed in git since 0.8.1,
but I may have missed things so please correct me if you think I'm
wrong :-), the main thing seems to be Vepa support and not yet 100%
cooked up.
So I'm suggesting to skip this month release and plan for a 0.8.2
at the end of June, sonmething like entering feature freeze around
Friday 18th and releasing on the 25 or by June end. But this is just
a suggestion, I could try to push a release earlier, but we would need
to plan the feature freeze week and try to make sure Vepa is ready by
then,
thanks !
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
14 years, 7 months
[libvirt] [PATCH v9] add 802.1Qbh and 802.1Qbg handling
by Stefan Berger
After Arnd's comments to v8 I had to take the patient back for a
revision surgery. Now here's the outcome, which may again be revised for
802.1Qbg for which we currently only have a dummy server to test
against.
V9:
- recycling a previous patch that adds functionality to interface.c to
- get the vlan identifier on an interface
- get the flags of an interface and some convenience function to
check whether an interface is 'up' or not (not currently used here)
- adding function to determine the root physical interface of an
interface. For example if a macvtap is linked to eth0.100, it will
find eth0. Also adding a function that finds the vlan on the 'way to
the root physical interface'
- conveying the root physical interface name and index in case of 802.1Qbg
- conveying mac address of macvlan device and vlan identifier in
IFLA_VFINFO_LIST[ IFLA_VF_INFO[ IFLA_VF_MAC(mac), IFLA_VF_VLAN(vlan) ] ]
to (future) lldpad via netlink
V8:
- To enable build with --without-macvtap rename the
[dis|]associatePortProfileId functions, prepend 'vp' before their
name and make them non-static functions.
- Renaming variable multicast to nltarget_kernel and inverting
the logic
V7:
- Addressing Jim Meyering's comments; this also touches existing
code for example for correcting indentation of break statements or
simplification of switch statements.
Changes from v5 to v6:
- Renamed occurrencvirVirtualPortProfileDef to
virVirtualPortProfileParamses
- 802.1Qbg part prepared for sending a RTM_SETLINK and getting
processing status back plus a subsequent RTM_GETLINK to
get IFLA_PORT_RESPONSE.
Note: This interface for 802.1Qbg may still change
Changes from v4 to v5:
- [David Allan] move getPhysfn inside IFLA_VF_PORT_MAX to avoid
compiler
warning when latest if_link.h isn't available
Changes from v3 to v4:
- move from Stefan's 802.1Qb{g|h} XML v8 to v9
- move hostuuid and vf index calcs to inside doPortProfileOp8021Qbh
Changes from v2 to v3:
- remove debug fprintfs
- use virGetHostUUID (thanks Stefan!)
- fix compile issue when latest if_link.h isn't available
- change poll timeout to 10s, at 1/8 intervals
- if polling times out, log msg and return -ETIMEDOUT
Changes from v1 to v2:
- Add Stefan's code for getPortProfileStatus
- Poll for up to 2 secs for port-profile status, at 1/8 sec intervals:
- if status indicates error, abort openMacvtapTap
- if status indicates success, exit polling
- if status is "in-progress" after 2 secs of polling, exit
polling loop silently, without error
My patch finishes out the 802.1Qbh parts, which Stefan had mostly complete.
I've tested using the recent kernel updates for VF_PORT netlink msgs and
enic for Cisco's 10G Ethernet NIC. I tested many VMs, each with several
direct interfaces, each configured with a port-profile per the XML. VM-to-VM,
and VM-to-external work as expected. VM-to-VM on same host (using same NIC)
works same as VM-to-VM where VMs are on diff hosts. I'm able to change
settings on the port-profile while the VM is running to change the virtual
port behaviour. For example, adjusting a QoS setting like rate limit. All
VMs with interfaces using that port-profile immediatly see the effect of the
change to the port-profile.
I don't have a SR-IOV device to test so source dev is a non-SR-IOV device,
but most of the code paths include support for specifing the source dev and
VF index. We'll need to complete this by discovering the PF given the VF
linkdev. Once we have the PF, we'll also have the VF index. All this info-
mation is available from sysfs.
Signed-off-by: Scott Feldman <scofeldm(a)cisco.com>
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
---
configure.ac | 17
src/libvirt_private.syms | 3
src/qemu/qemu_conf.c | 2
src/qemu/qemu_driver.c | 4
src/util/interface.c | 141 +++++-
src/util/interface.h | 5
src/util/macvtap.c | 1053 +++++++++++++++++++++++++++++++++++++++++++----
src/util/macvtap.h | 10
8 files changed, 1132 insertions(+), 103 deletions(-)
Index: libvirt-acl/configure.ac
===================================================================
--- libvirt-acl.orig/configure.ac
+++ libvirt-acl/configure.ac
@@ -2005,13 +2005,27 @@ if test "$with_macvtap" != "no" ; then
fi
AM_CONDITIONAL([WITH_MACVTAP], [test "$with_macvtap" = "yes"])
+AC_TRY_COMPILE([ #include <sys/socket.h>
+ #include <linux/rtnetlink.h> ],
+ [ int x = IFLA_PORT_MAX; ],
+ [ with_virtualport=yes ],
+ [ with_virtualport=no ])
+if test "$with_virtualport" = "yes"; then
+ val=1
+else
+ val=0
+fi
+AC_DEFINE_UNQUOTED([WITH_VIRTUALPORT], $val,
+ [whether vsi vepa support is enabled])
+AM_CONDITIONAL([WITH_VIRTUALPORT], [test "$with_virtualport" = "yes"])
+
dnl netlink library
LIBNL_CFLAGS=""
LIBNL_LIBS=""
-if test "$with_macvtap" = "yes"; then
+if test "$with_macvtap" = "yes" || test "$with_virtualport" = "yes"; then
PKG_CHECK_MODULES([LIBNL], [libnl-1 >= $LIBNL_REQUIRED], [
], [
AC_MSG_ERROR([libnl >= $LIBNL_REQUIRED is required for macvtap support])
@@ -2084,6 +2098,7 @@ AC_MSG_NOTICE([ Network: $with_network])
AC_MSG_NOTICE([Libvirtd: $with_libvirtd])
AC_MSG_NOTICE([ netcf: $with_netcf])
AC_MSG_NOTICE([ macvtap: $with_macvtap])
+AC_MSG_NOTICE([virtport: $with_virtualport])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([Storage Drivers])
AC_MSG_NOTICE([])
Index: libvirt-acl/src/qemu/qemu_conf.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_conf.c
+++ libvirt-acl/src/qemu/qemu_conf.c
@@ -1554,7 +1554,7 @@ qemudPhysIfaceConnect(virConnectPtr conn
if (err) {
close(rc);
rc = -1;
- delMacvtap(net->ifname,
+ delMacvtap(net->ifname, net->data.direct.linkdev,
&net->data.direct.virtPortProfile);
}
}
Index: libvirt-acl/src/qemu/qemu_driver.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_driver.c
+++ libvirt-acl/src/qemu/qemu_driver.c
@@ -3709,7 +3709,7 @@ static void qemudShutdownVMDaemon(struct
for (i = 0; i < def->nnets; i++) {
virDomainNetDefPtr net = def->nets[i];
if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT)
- delMacvtap(net->ifname,
+ delMacvtap(net->ifname, net->data.direct.linkdev,
&net->data.direct.virtPortProfile);
}
#endif
@@ -8546,7 +8546,7 @@ qemudDomainDetachNetDevice(struct qemud_
#if WITH_MACVTAP
if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT)
- delMacvtap(detach->ifname,
+ delMacvtap(detach->ifname, detach->data.direct.linkdev,
&detach->data.direct.virtPortProfile);
#endif
Index: libvirt-acl/src/util/macvtap.c
===================================================================
--- libvirt-acl.orig/src/util/macvtap.c
+++ libvirt-acl/src/util/macvtap.c
@@ -27,7 +27,7 @@
#include <config.h>
-#if WITH_MACVTAP
+#if WITH_MACVTAP || WITH_VIRTUALPORT
# include <stdio.h>
# include <errno.h>
@@ -41,6 +41,8 @@
# include <linux/rtnetlink.h>
# include <linux/if_tun.h>
+# include <netlink/msg.h>
+
# include "util.h"
# include "memory.h"
# include "logging.h"
@@ -48,6 +50,7 @@
# include "interface.h"
# include "conf/domain_conf.h"
# include "virterror_internal.h"
+# include "uuid.h"
# define VIR_FROM_THIS VIR_FROM_NET
@@ -58,14 +61,22 @@
# define MACVTAP_NAME_PREFIX "macvtap"
# define MACVTAP_NAME_PATTERN "macvtap%d"
+# define MICROSEC_PER_SEC (1000 * 1000)
+
+# define NLMSGBUF_SIZE 256
+# define RATTBUF_SIZE 64
+
+
+# define STATUS_POLL_TIMEOUT_USEC (10 * MICROSEC_PER_SEC)
+# define STATUS_POLL_INTERVL_USEC (MICROSEC_PER_SEC / 8)
-static int associatePortProfileId(const char *macvtap_ifname,
- const virVirtualPortProfileParamsPtr virtPort,
- int vf,
- const unsigned char *vmuuid);
-static int disassociatePortProfileId(const char *macvtap_ifname,
- const virVirtualPortProfileParamsPtr virtPort);
+
+
+enum virVirtualPortOp {
+ ASSOCIATE = 0x1,
+ DISASSOCIATE = 0x2,
+};
static int nlOpen(void)
@@ -97,7 +108,7 @@ static void nlClose(int fd)
*/
static
int nlComm(struct nlmsghdr *nlmsg,
- char **respbuf, int *respbuflen)
+ char **respbuf, unsigned int *respbuflen)
{
int rc = 0;
struct sockaddr_nl nladdr = {
@@ -159,6 +170,162 @@ err_exit:
}
+# ifdef IFLA_VF_PORT_MAX
+
+/**
+ * nlCommWaitSuccess:
+ *
+ * @nlmsg: pointer to netlink message
+ * @nl_grousp: the netlink multicast groups to send to
+ * @respbuf: pointer to pointer where response buffer will be allocated
+ * @respbuflen: pointer to integer holding the size of the response buffer
+ * on return of the function.
+ * @timeout_usecs: timeout in microseconds to wait for a success message
+ * to be returned
+ *
+ * Send the given message to the netlink multicast group and receive
+ * responses. Skip responses indicating an error and keep on receiving
+ * responses until a success response is returned.
+ * Returns 0 on success, -1 on error. In case of error, no response
+ * buffer will be returned.
+ */
+static int
+nlCommWaitSuccess(struct nlmsghdr *nlmsg, uint32_t nl_groups,
+ char **respbuf, unsigned int *respbuflen,
+ unsigned long long timeout_usecs)
+{
+ int rc = 0;
+ struct sockaddr_nl nladdr = {
+ .nl_family = AF_NETLINK,
+ .nl_pid = getpid(),
+ .nl_groups = nl_groups,
+ };
+ int rcvChunkSize = 1024; // expecting less than that
+ size_t rcv_offset = 0;
+ ssize_t nbytes;
+ struct timeval tv = {
+ .tv_sec = timeout_usecs / MICROSEC_PER_SEC,
+ .tv_usec = timeout_usecs % MICROSEC_PER_SEC,
+ };
+ bool got_valid = false;
+ int fd = nlOpen();
+ static uint32_t seq = 0x1234;
+ uint32_t myseq = seq++;
+ uint32_t mypid = getpid();
+
+ if (fd < 0)
+ return -1;
+
+ nlmsg->nlmsg_pid = mypid;
+ nlmsg->nlmsg_seq = myseq;
+ nlmsg->nlmsg_flags |= NLM_F_ACK;
+
+ nbytes = sendto(fd, (void *)nlmsg, nlmsg->nlmsg_len, 0,
+ (struct sockaddr *)&nladdr, sizeof(nladdr));
+ if (nbytes < 0) {
+ virReportSystemError(errno,
+ "%s", _("cannot send to netlink socket"));
+ rc = -1;
+ goto err_exit;
+ }
+
+ while (!got_valid) {
+
+ rcv_offset = 0;
+
+ while (1) {
+ int n;
+ fd_set rfds;
+ socklen_t addrlen = sizeof(nladdr);
+
+ if (VIR_REALLOC_N(*respbuf, rcv_offset + rcvChunkSize) < 0) {
+ virReportOOMError();
+ rc = -1;
+ goto err_exit;
+ }
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ n = select(fd + 1, &rfds, NULL, NULL, &tv);
+ if (n <= 0) {
+ if (n < 0)
+ virReportSystemError(errno, "%s",
+ _("error in select call"));
+ if (n == 0)
+ virReportSystemError(ETIMEDOUT, "%s",
+ _("no valid netlink response was received"));
+ rc = -1;
+ goto err_exit;
+ }
+
+ nbytes = recvfrom(fd, &((*respbuf)[rcv_offset]), rcvChunkSize, 0,
+ (struct sockaddr *)&nladdr, &addrlen);
+ if (nbytes < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ virReportSystemError(errno, "%s",
+ _("error receiving from netlink socket"));
+ rc = -1;
+ goto err_exit;
+ }
+ rcv_offset += nbytes;
+ break;
+ }
+ *respbuflen = rcv_offset;
+
+ /* check message for error */
+ if (*respbuflen > NLMSG_LENGTH(0) && *respbuf != NULL) {
+ struct nlmsghdr *resp = (struct nlmsghdr *)*respbuf;
+ struct nlmsgerr *err;
+
+ if (resp->nlmsg_pid != mypid ||
+ resp->nlmsg_seq != myseq)
+ continue;
+
+ /* skip reflected message */
+ if (resp->nlmsg_type & 0x10)
+ continue;
+
+ switch (resp->nlmsg_type) {
+ case NLMSG_ERROR:
+ err = (struct nlmsgerr *)NLMSG_DATA(resp);
+ if (resp->nlmsg_len >= NLMSG_LENGTH(sizeof(*err))) {
+ if (err->error != -EOPNOTSUPP) {
+ /* assuming error msg from daemon */
+ got_valid = true;
+ break;
+ }
+ }
+ /* whatever this is, skip it */
+ VIR_FREE(*respbuf);
+ *respbuflen = 0;
+ break;
+
+ case NLMSG_DONE:
+ got_valid = true;
+ break;
+
+ default:
+ VIR_FREE(*respbuf);
+ *respbuflen = 0;
+ break;
+ }
+ }
+ }
+
+err_exit:
+ if (rc == -1) {
+ VIR_FREE(*respbuf);
+ *respbuflen = 0;
+ }
+
+ nlClose(fd);
+ return rc;
+}
+
+# endif /* IFLA_VF_PORT_MAX */
+
static struct rtattr *
rtattrCreate(char *buffer, int bufsize, int type,
const void *data, int datalen)
@@ -204,6 +371,8 @@ nlAppend(struct nlmsghdr *nlm, int totle
}
+# if WITH_MACVTAP
+
static int
link_add(const char *type,
const unsigned char *macaddress, int macaddrsize,
@@ -213,15 +382,15 @@ link_add(const char *type,
int *retry)
{
int rc = 0;
- char nlmsgbuf[256];
+ char nlmsgbuf[NLMSGBUF_SIZE];
struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp;
struct nlmsgerr *err;
- char rtattbuf[64];
+ char rtattbuf[RATTBUF_SIZE];
struct rtattr *rta, *rta1, *li;
- struct ifinfomsg i = { .ifi_family = AF_UNSPEC };
+ struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
int ifindex;
char *recvbuf = NULL;
- int recvbuflen;
+ unsigned int recvbuflen;
if (ifaceGetIndex(true, srcdev, &ifindex) != 0)
return -1;
@@ -232,65 +401,46 @@ link_add(const char *type,
nlInit(nlm, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL, RTM_NEWLINK);
- if (!nlAppend(nlm, sizeof(nlmsgbuf), &i, sizeof(i)))
+ if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo, sizeof(ifinfo)))
goto buffer_too_small;
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_LINK,
&ifindex, sizeof(ifindex));
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_ADDRESS,
macaddress, macaddrsize);
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
if (ifname) {
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME,
ifname, strlen(ifname) + 1);
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
}
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_LINKINFO, NULL, 0);
- if (!rta)
- goto buffer_too_small;
-
- if (!(li = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
+ if (!rta ||
+ !(li = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
goto buffer_too_small;
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_INFO_KIND,
type, strlen(type));
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
if (macvlan_mode > 0) {
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_INFO_DATA,
NULL, 0);
- if (!rta)
- goto buffer_too_small;
-
- if (!(rta1 = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
+ if (!rta ||
+ !(rta1 = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
goto buffer_too_small;
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_MACVLAN_MODE,
&macvlan_mode, sizeof(macvlan_mode));
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
rta1->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)rta1;
@@ -312,15 +462,15 @@ link_add(const char *type,
if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
goto malformed_resp;
- switch (-err->error) {
+ switch (err->error) {
case 0:
- break;
+ break;
- case EEXIST:
+ case -EEXIST:
*retry = 1;
rc = -1;
- break;
+ break;
default:
virReportSystemError(-err->error,
@@ -328,10 +478,10 @@ link_add(const char *type,
type);
rc = -1;
}
- break;
+ break;
case NLMSG_DONE:
- break;
+ break;
default:
goto malformed_resp;
@@ -358,14 +508,14 @@ static int
link_del(const char *name)
{
int rc = 0;
- char nlmsgbuf[256];
+ char nlmsgbuf[NLMSGBUF_SIZE];
struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp;
struct nlmsgerr *err;
- char rtattbuf[64];
+ char rtattbuf[RATTBUF_SIZE];
struct rtattr *rta;
struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
char *recvbuf = NULL;
- int recvbuflen;
+ unsigned int recvbuflen;
memset(&nlmsgbuf, 0, sizeof(nlmsgbuf));
@@ -376,10 +526,7 @@ link_del(const char *name)
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME,
name, strlen(name)+1);
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
if (nlComm(nlm, &recvbuf, &recvbuflen) < 0)
@@ -396,20 +543,16 @@ link_del(const char *name)
if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
goto malformed_resp;
- switch (-err->error) {
- case 0:
- break;
-
- default:
+ if (err->error) {
virReportSystemError(-err->error,
_("error destroying %s interface"),
name);
rc = -1;
}
- break;
+ break;
case NLMSG_DONE:
- break;
+ break;
default:
goto malformed_resp;
@@ -509,11 +652,9 @@ macvtapModeFromInt(enum virDomainNetdevM
switch (mode) {
case VIR_DOMAIN_NETDEV_MACVTAP_MODE_PRIVATE:
return MACVLAN_MODE_PRIVATE;
- break;
case VIR_DOMAIN_NETDEV_MACVTAP_MODE_BRIDGE:
return MACVLAN_MODE_BRIDGE;
- break;
case VIR_DOMAIN_NETDEV_MACVTAP_MODE_VEPA:
default:
@@ -654,10 +795,11 @@ create_name:
cr_ifname = ifname;
}
- if (associatePortProfileId(cr_ifname,
- virtPortProfile,
- -1,
- vmuuid) != 0) {
+ if (vpAssociatePortProfileId(cr_ifname,
+ macaddress,
+ linkdev,
+ virtPortProfile,
+ vmuuid) != 0) {
rc = -1;
goto link_del_exit;
}
@@ -688,8 +830,9 @@ create_name:
return rc;
disassociate_exit:
- disassociatePortProfileId(cr_ifname,
- virtPortProfile);
+ vpDisassociatePortProfileId(cr_ifname,
+ linkdev,
+ virtPortProfile);
link_del_exit:
link_del(cr_ifname);
@@ -701,6 +844,7 @@ link_del_exit:
/**
* delMacvtap:
* @ifname : The name of the macvtap interface
+ * @linkdev: The interface name of the NIC to connect to the external bridge
* @virtPortProfile: pointer to object holding the virtual port profile data
*
* Delete an interface given its name. Disassociate
@@ -709,22 +853,744 @@ link_del_exit:
*/
void
delMacvtap(const char *ifname,
+ const char *linkdev,
virVirtualPortProfileParamsPtr virtPortProfile)
{
if (ifname) {
- disassociatePortProfileId(ifname,
- virtPortProfile);
+ vpDisassociatePortProfileId(ifname,
+ linkdev,
+ virtPortProfile);
link_del(ifname);
}
}
+# endif /* WITH_MACVTAP */
+
+# ifdef IFLA_PORT_MAX
+
+static struct nla_policy ifla_policy[IFLA_MAX + 1] =
+{
+ [IFLA_VF_PORTS] = { .type = NLA_NESTED },
+};
+
+static struct nla_policy ifla_vf_ports_policy[IFLA_VF_PORT_MAX + 1] =
+{
+ [IFLA_VF_PORT] = { .type = NLA_NESTED },
+};
+
+static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] =
+{
+ [IFLA_PORT_RESPONSE] = { .type = NLA_U16 },
+};
+
+
+static int
+link_dump(bool nltarget_kernel, const char *ifname, int ifindex,
+ struct nlattr **tb, char **recvbuf)
+{
+ int rc = 0;
+ char nlmsgbuf[NLMSGBUF_SIZE] = { 0, };
+ struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp;
+ struct nlmsgerr *err;
+ char rtattbuf[RATTBUF_SIZE];
+ struct rtattr *rta;
+ struct ifinfomsg ifinfo = {
+ .ifi_family = AF_UNSPEC,
+ .ifi_index = ifindex
+ };
+ unsigned int recvbuflen;
+
+ *recvbuf = NULL;
+
+ nlInit(nlm, NLM_F_REQUEST, RTM_GETLINK);
+
+ if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo, sizeof(ifinfo)))
+ goto buffer_too_small;
+
+ if (ifindex < 0 && ifname) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME,
+ ifname, strlen(ifname) + 1);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (nltarget_kernel) {
+ if (nlComm(nlm, recvbuf, &recvbuflen) < 0)
+ return -1;
+ } else {
+ if (nlCommWaitSuccess(nlm, RTMGRP_LINK, recvbuf, &recvbuflen,
+ 5 * MICROSEC_PER_SEC) < 0)
+ return -1;
+ }
+
+ if (recvbuflen < NLMSG_LENGTH(0) || *recvbuf == NULL)
+ goto malformed_resp;
+
+ resp = (struct nlmsghdr *)*recvbuf;
+
+ switch (resp->nlmsg_type) {
+ case NLMSG_ERROR:
+ err = (struct nlmsgerr *)NLMSG_DATA(resp);
+ if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
+ goto malformed_resp;
+
+ if (err->error) {
+ virReportSystemError(-err->error,
+ _("error dumping %d interface"),
+ ifindex);
+ rc = -1;
+ }
+ break;
+
+ case GENL_ID_CTRL:
+ case NLMSG_DONE:
+ if (nlmsg_parse(resp, sizeof(struct ifinfomsg),
+ tb, IFLA_MAX, ifla_policy)) {
+ goto malformed_resp;
+ }
+ break;
+
+ default:
+ goto malformed_resp;
+ }
+
+ if (rc != 0)
+ VIR_FREE(*recvbuf);
+
+ return rc;
+
+malformed_resp:
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed netlink response message"));
+ VIR_FREE(*recvbuf);
+ return -1;
+
+buffer_too_small:
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("internal buffer is too small"));
+ return -1;
+}
+
+
+/**
+ * ifaceGetNthParent
+ *
+ * @ifindex : the index of the interface or -1 if ifname is given
+ * @ifname : the name of the interface; ignored if ifindex is valid
+ * @nthParent : the nth parent interface to get
+ * @parent_ifindex : pointer to int
+ * @parent_ifname : pointer to buffer of size IFNAMSIZ
+ * @nth : the nth parent that is actually returned; if for example eth0.100
+ * was given and the 100th parent is to be returned, then eth0 will
+ * most likely be returned with nth set to 1 since the chain does
+ * not have more interfaces
+ *
+ * Get the nth parent interface of the given interface. 0 is the interface
+ * itself.
+ *
+ * Return 0 on success, != 0 otherwise
+ */
+static int
+ifaceGetNthParent(int ifindex, const char *ifname, unsigned int nthParent,
+ int *parent_ifindex, char *parent_ifname,
+ unsigned int *nth)
+{
+ int rc;
+ struct nlattr *tb[IFLA_MAX + 1];
+ char *recvbuf = NULL;
+ bool end = false;
+ unsigned int i = 0;
+
+ *nth = 0;
+
+ while (!end && i <= nthParent) {
+ rc = link_dump(true, ifname, ifindex, tb, &recvbuf);
+ if (rc)
+ break;
+
+ if (tb[IFLA_IFNAME]) {
+ if (!virStrcpy(parent_ifname, (char*)RTA_DATA(tb[IFLA_IFNAME]),
+ IFNAMSIZ)) {
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("buffer for root interface name is too small"));
+ VIR_FREE(recvbuf);
+ return 1;
+ }
+ *parent_ifindex = ifindex;
+ }
+
+ if (tb[IFLA_LINK]) {
+ ifindex = *(int *)RTA_DATA(tb[IFLA_LINK]);
+ ifname = NULL;
+ } else
+ end = true;
+
+ VIR_FREE(recvbuf);
+
+ i++;
+ }
+
+ if (nth)
+ *nth = i - 1;
+
+ return rc;
+}
+
+
+static int
+getPortProfileStatus(struct nlattr **tb, int32_t vf, uint16_t *status)
+{
+ int rc = 1;
+ const char *msg = NULL;
+ struct nlattr *tb2[IFLA_VF_PORT_MAX + 1],
+ *tb3[IFLA_PORT_MAX+1];
+
+ if (vf == PORT_SELF_VF) {
+ if (tb[IFLA_PORT_SELF]) {
+ if (nla_parse_nested(tb3, IFLA_PORT_MAX, tb[IFLA_PORT_SELF],
+ ifla_port_policy)) {
+ msg = _("error parsing nested IFLA_VF_PORT part");
+ goto err_exit;
+ }
+ }
+ } else {
+ if (tb[IFLA_VF_PORTS]) {
+ if (nla_parse_nested(tb2, IFLA_VF_PORT_MAX, tb[IFLA_VF_PORTS],
+ ifla_vf_ports_policy)) {
+ msg = _("error parsing nested IFLA_VF_PORTS part");
+ goto err_exit;
+ }
+ if (tb2[IFLA_VF_PORT]) {
+ if (nla_parse_nested(tb3, IFLA_PORT_MAX, tb2[IFLA_VF_PORT],
+ ifla_port_policy)) {
+ msg = _("error parsing nested IFLA_VF_PORT part");
+ goto err_exit;
+ }
+ }
+ }
+ }
+
+ if (tb3[IFLA_PORT_RESPONSE]) {
+ *status = *(uint16_t *)RTA_DATA(tb3[IFLA_PORT_RESPONSE]);
+ rc = 0;
+ } else {
+ msg = _("no IFLA_PORT_RESPONSE found in netlink message");
+ goto err_exit;
+ }
+
+err_exit:
+ if (msg)
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", msg);
+
+ return rc;
+}
+
+
+static int
+doPortProfileOpSetLink(bool nltarget_kernel,
+ const char *ifname, int ifindex,
+ const unsigned char *macaddr,
+ int vlanid,
+ const char *profileId,
+ struct ifla_port_vsi *portVsi,
+ const unsigned char *instanceId,
+ const unsigned char *hostUUID,
+ int32_t vf,
+ uint8_t op)
+{
+ int rc = 0;
+ char nlmsgbuf[NLMSGBUF_SIZE];
+ struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp;
+ struct nlmsgerr *err;
+ char rtattbuf[RATTBUF_SIZE];
+ struct rtattr *rta, *vfports = NULL, *vfport;
+ struct ifinfomsg ifinfo = {
+ .ifi_family = AF_UNSPEC,
+ .ifi_index = ifindex,
+ };
+ char *recvbuf = NULL;
+ unsigned int recvbuflen = 0;
+
+ memset(&nlmsgbuf, 0, sizeof(nlmsgbuf));
+
+ nlInit(nlm, NLM_F_REQUEST, RTM_SETLINK);
+
+ if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo, sizeof(ifinfo)))
+ goto buffer_too_small;
+
+
+ if (ifname) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME,
+ ifname, strlen(ifname) + 1);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (macaddr && vlanid >= 0) {
+ struct rtattr *vfinfolist, *vfinfo;
+ struct ifla_vf_mac ifla_vf_mac = {
+ .vf = vf,
+ .mac = { 0, },
+ };
+ struct ifla_vf_vlan ifla_vf_vlan = {
+ .vf = vf,
+ .vlan = vlanid,
+ .qos = 0,
+ };
+
+ memcpy(ifla_vf_mac.mac, macaddr, 6);
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VFINFO_LIST,
+ NULL, 0);
+ if (!rta ||
+ !(vfinfolist = nlAppend(nlm, sizeof(nlmsgbuf),
+ rtattbuf, rta->rta_len)))
+ goto buffer_too_small;
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_INFO,
+ NULL, 0);
+ if (!rta ||
+ !(vfinfo = nlAppend(nlm, sizeof(nlmsgbuf),
+ rtattbuf, rta->rta_len)))
+ goto buffer_too_small;
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_MAC,
+ &ifla_vf_mac, sizeof(ifla_vf_mac));
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_VLAN,
+ &ifla_vf_vlan, sizeof(ifla_vf_vlan));
+
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+
+ vfinfo->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)vfinfo;
+
+ vfinfolist->rta_len = (char *)nlm + nlm->nlmsg_len -
+ (char *)vfinfolist;
+ }
+
+ if (vf == PORT_SELF_VF) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_SELF, NULL, 0);
+ } else {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_PORTS, NULL, 0);
+ if (!rta ||
+ !(vfports = nlAppend(nlm, sizeof(nlmsgbuf),
+ rtattbuf, rta->rta_len)))
+ goto buffer_too_small;
+
+ /* begin nesting vfports */
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_PORT, NULL, 0);
+ }
+
+ if (!rta ||
+ !(vfport = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
+ goto buffer_too_small;
+
+ if (profileId) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_PROFILE,
+ profileId, strlen(profileId) + 1);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (portVsi) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_VSI_TYPE,
+ portVsi, sizeof(*portVsi));
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (instanceId) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_INSTANCE_UUID,
+ instanceId, VIR_UUID_BUFLEN);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (hostUUID) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_HOST_UUID,
+ hostUUID, VIR_UUID_BUFLEN);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (vf != PORT_SELF_VF) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_VF,
+ &vf, sizeof(vf));
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_REQUEST,
+ &op, sizeof(op));
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+
+ /* end nesting of vport */
+ vfport->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)vfport;
+
+ if (vf != PORT_SELF_VF) {
+ /* end nesting of vfports */
+ vfports->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)vfports;
+ }
+
+ if (nltarget_kernel) {
+ if (nlComm(nlm, &recvbuf, &recvbuflen) < 0)
+ return -1;
+ } else {
+ if (nlCommWaitSuccess(nlm, RTMGRP_LINK, &recvbuf, &recvbuflen,
+ 5 * MICROSEC_PER_SEC) < 0)
+ return -1;
+ }
+
+ if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL)
+ goto malformed_resp;
+
+ resp = (struct nlmsghdr *)recvbuf;
+
+ switch (resp->nlmsg_type) {
+ case NLMSG_ERROR:
+ err = (struct nlmsgerr *)NLMSG_DATA(resp);
+ if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
+ goto malformed_resp;
+
+ if (err->error) {
+ virReportSystemError(-err->error,
+ _("error during virtual port configuration of ifindex %d"),
+ ifindex);
+ rc = -1;
+ }
+ break;
+
+ case NLMSG_DONE:
+ break;
+
+ default:
+ goto malformed_resp;
+ }
+
+ VIR_FREE(recvbuf);
+
+ return rc;
+
+malformed_resp:
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed netlink response message"));
+ VIR_FREE(recvbuf);
+ return -1;
+
+buffer_too_small:
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("internal buffer is too small"));
+ return -1;
+}
+
+
+static int
+doPortProfileOpCommon(bool nltarget_kernel,
+ const char *ifname, int ifindex,
+ const unsigned char *macaddr,
+ int vlanid,
+ const char *profileId,
+ struct ifla_port_vsi *portVsi,
+ const unsigned char *instanceId,
+ const unsigned char *hostUUID,
+ int32_t vf,
+ uint8_t op)
+{
+ int rc;
+ char *recvbuf = NULL;
+ struct nlattr *tb[IFLA_MAX + 1];
+ int repeats = STATUS_POLL_TIMEOUT_USEC / STATUS_POLL_INTERVL_USEC;
+ uint16_t status = 0;
+
+ rc = doPortProfileOpSetLink(nltarget_kernel,
+ ifname, ifindex,
+ macaddr,
+ vlanid,
+ profileId,
+ portVsi,
+ instanceId,
+ hostUUID,
+ vf,
+ op);
+
+ if (rc != 0) {
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("sending of PortProfileRequest failed."));
+ return rc;
+ }
+
+ while (--repeats >= 0) {
+ rc = link_dump(nltarget_kernel, NULL, ifindex, tb, &recvbuf);
+ if (rc)
+ goto err_exit;
+ rc = getPortProfileStatus(tb, vf, &status);
+ if (rc == 0) {
+ if (status == PORT_PROFILE_RESPONSE_SUCCESS ||
+ status == PORT_VDP_RESPONSE_SUCCESS) {
+ break;
+ } else if (status == PORT_PROFILE_RESPONSE_INPROGRESS) {
+ // keep trying...
+ } else {
+ virReportSystemError(EINVAL,
+ _("error %d during port-profile setlink on ifindex %d"),
+ status, ifindex);
+ rc = 1;
+ break;
+ }
+ } else
+ goto err_exit;
+
+ usleep(STATUS_POLL_INTERVL_USEC);
+
+ VIR_FREE(recvbuf);
+ }
+
+ if (status == PORT_PROFILE_RESPONSE_INPROGRESS) {
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("port-profile setlink timed out"));
+ rc = -ETIMEDOUT;
+ }
+
+err_exit:
+ VIR_FREE(recvbuf);
+
+ return rc;
+}
+
+# endif /* IFLA_PORT_MAX */
+
+
+# ifdef IFLA_VF_PORT_MAX
+
+static int
+getPhysdevAndVlan(const char *ifname, int *root_ifindex, char *root_ifname,
+ int *vlanid)
+{
+ int ret;
+ unsigned int nth;
+ int ifindex = -1;
+
+ *vlanid = -1;
+ while (1) {
+ if ((ret = ifaceGetNthParent(ifindex, ifname, 1,
+ root_ifindex, root_ifname, &nth)))
+ return ret;
+ if (nth == 0)
+ break;
+ if (*vlanid == -1) {
+ if (ifaceGetVlanID(root_ifname, vlanid))
+ *vlanid = -1;
+ }
+
+ ifindex = *root_ifindex;
+ ifname = NULL;
+ }
+
+ return 0;
+}
+
+# endif
+
+static int
+doPortProfileOp8021Qbg(const char *ifname,
+ const unsigned char *macaddr,
+ const virVirtualPortProfileParamsPtr virtPort,
+ enum virVirtualPortOp virtPortOp)
+{
+ int rc;
+
+# ifndef IFLA_VF_PORT_MAX
+
+ (void)ifname;
+ (void)virtPort;
+ (void)virtPortOp;
+ (void)macaddr;
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Kernel VF Port support was missing at compile time."));
+ rc = 1;
+
+# else /* IFLA_VF_PORT_MAX */
+
+ int op = PORT_REQUEST_ASSOCIATE;
+ struct ifla_port_vsi portVsi = {
+ .vsi_mgr_id = virtPort->u.virtPort8021Qbg.managerID,
+ .vsi_type_version = virtPort->u.virtPort8021Qbg.typeIDVersion,
+ };
+ bool nltarget_kernel = false;
+ int vlanid;
+ int physdev_ifindex = 0;
+ char physdev_ifname[IFNAMSIZ] = { 0, };
+
+ if (getPhysdevAndVlan(ifname, &physdev_ifindex, physdev_ifname,
+ &vlanid) != 0) {
+ rc = 1;
+ goto err_exit;
+ }
+
+ if (vlanid < 0)
+ vlanid = 0;
+
+ portVsi.vsi_type_id[2] = virtPort->u.virtPort8021Qbg.typeID >> 16;
+ portVsi.vsi_type_id[1] = virtPort->u.virtPort8021Qbg.typeID >> 8;
+ portVsi.vsi_type_id[0] = virtPort->u.virtPort8021Qbg.typeID;
+
+ switch (virtPortOp) {
+ case ASSOCIATE:
+ op = PORT_REQUEST_ASSOCIATE;
+ break;
+ case DISASSOCIATE:
+ op = PORT_REQUEST_DISASSOCIATE;
+ break;
+ default:
+ macvtapError(VIR_ERR_INTERNAL_ERROR,
+ _("operation type %d not supported"), op);
+ rc = 1;
+ goto err_exit;
+ }
+
+ rc = doPortProfileOpCommon(nltarget_kernel,
+ physdev_ifname, physdev_ifindex,
+ macaddr,
+ vlanid,
+ NULL,
+ &portVsi,
+ virtPort->u.virtPort8021Qbg.instanceID,
+ NULL,
+ PORT_SELF_VF,
+ op);
+
+err_exit:
+
+# endif /* IFLA_VF_PORT_MAX */
+
+ return rc;
+}
+
+
+# ifdef IFLA_VF_PORT_MAX
+static int
+getPhysfn(const char *linkdev,
+ int32_t *vf,
+ char **physfndev)
+{
+ int rc = 0;
+ bool virtfn = false;
+
+ if (virtfn) {
+
+ // XXX: if linkdev is SR-IOV VF, then set vf = VF index
+ // XXX: and set linkdev = PF device
+ // XXX: need to use get_physical_function_linux() or
+ // XXX: something like that to get PF
+ // XXX: device and figure out VF index
+
+ rc = 1;
+
+ } else {
+
+ /* Not SR-IOV VF: physfndev is linkdev and VF index
+ * refers to linkdev self
+ */
+
+ *vf = PORT_SELF_VF;
+ *physfndev = (char *)linkdev;
+ }
+
+ return rc;
+}
+# endif /* IFLA_VF_PORT_MAX */
+
+static int
+doPortProfileOp8021Qbh(const char *ifname,
+ const virVirtualPortProfileParamsPtr virtPort,
+ const unsigned char *vm_uuid,
+ enum virVirtualPortOp virtPortOp)
+{
+ int rc;
+
+# ifndef IFLA_VF_PORT_MAX
+
+ (void)ifname;
+ (void)virtPort;
+ (void)vm_uuid;
+ (void)virtPortOp;
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Kernel VF Port support was missing at compile time."));
+ rc = 1;
+
+# else /* IFLA_VF_PORT_MAX */
+
+ char *physfndev;
+ unsigned char hostuuid[VIR_UUID_BUFLEN];
+ int32_t vf;
+ int op = PORT_REQUEST_ASSOCIATE;
+ bool nltarget_kernel = true;
+ int ifindex;
+ int vlanid = -1;
+ const unsigned char *macaddr = NULL;
+
+ rc = virGetHostUUID(hostuuid);
+ if (rc)
+ goto err_exit;
+
+ rc = getPhysfn(ifname, &vf, &physfndev);
+ if (rc)
+ goto err_exit;
+
+ if (ifaceGetIndex(true, physfndev, &ifindex) != 0) {
+ rc = 1;
+ goto err_exit;
+ }
+
+ switch (virtPortOp) {
+ case ASSOCIATE:
+ op = PORT_REQUEST_ASSOCIATE;
+ break;
+ case DISASSOCIATE:
+ op = PORT_REQUEST_DISASSOCIATE;
+ break;
+ default:
+ macvtapError(VIR_ERR_INTERNAL_ERROR,
+ _("operation type %d not supported"), op);
+ rc = 1;
+ goto err_exit;
+ }
+
+ rc = doPortProfileOpCommon(nltarget_kernel, NULL, ifindex,
+ macaddr,
+ vlanid,
+ virtPort->u.virtPort8021Qbh.profileID,
+ NULL,
+ vm_uuid,
+ hostuuid,
+ vf,
+ op);
+
+ switch (virtPortOp) {
+ case ASSOCIATE:
+ ifaceUp(ifname);
+ break;
+ case DISASSOCIATE:
+ ifaceDown(ifname);
+ break;
+ }
+
+err_exit:
+
+# endif /* IFLA_VF_PORT_MAX */
+
+ return rc;
+}
/**
- * associatePortProfile
+ * vpAssociatePortProfile
*
* @macvtap_ifname: The name of the macvtap device
* @virtPort: pointer to the object holding port profile parameters
- * @vf: virtual function number, -1 if to be ignored
* @vmuuid : the UUID of the virtual machine
*
* Associate a port on a swtich with a profile. This function
@@ -736,17 +1602,17 @@ delMacvtap(const char *ifname,
* Returns 0 in case of success, != 0 otherwise with error
* having been reported.
*/
-static int
-associatePortProfileId(const char *macvtap_ifname,
- const virVirtualPortProfileParamsPtr virtPort,
- int vf,
- const unsigned char *vmuuid)
+int
+vpAssociatePortProfileId(const char *macvtap_ifname,
+ const unsigned char *macvtap_macaddr,
+ const char *linkdev,
+ const virVirtualPortProfileParamsPtr virtPort,
+ const unsigned char *vmuuid)
{
int rc = 0;
+
VIR_DEBUG("Associating port profile '%p' on link device '%s'",
virtPort, macvtap_ifname);
- (void)vf;
- (void)vmuuid;
switch (virtPort->virtPortType) {
case VIR_VIRTUALPORT_NONE:
@@ -754,11 +1620,14 @@ associatePortProfileId(const char *macvt
break;
case VIR_VIRTUALPORT_8021QBG:
-
+ rc = doPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr,
+ virtPort, ASSOCIATE);
break;
case VIR_VIRTUALPORT_8021QBH:
-
+ rc = doPortProfileOp8021Qbh(linkdev, virtPort,
+ vmuuid,
+ ASSOCIATE);
break;
}
@@ -767,19 +1636,22 @@ associatePortProfileId(const char *macvt
/**
- * disassociatePortProfile
+ * vpDisassociatePortProfile
*
* @macvtap_ifname: The name of the macvtap device
+ * @linkdev: The link device in case of macvtap
* @virtPort: point to object holding port profile parameters
*
* Returns 0 in case of success, != 0 otherwise with error
* having been reported.
*/
-static int
-disassociatePortProfileId(const char *macvtap_ifname,
- const virVirtualPortProfileParamsPtr virtPort)
+int
+vpDisassociatePortProfileId(const char *macvtap_ifname,
+ const char *linkdev,
+ const virVirtualPortProfileParamsPtr virtPort)
{
int rc = 0;
+
VIR_DEBUG("Disassociating port profile id '%p' on link device '%s' ",
virtPort, macvtap_ifname);
@@ -789,15 +1661,18 @@ disassociatePortProfileId(const char *ma
break;
case VIR_VIRTUALPORT_8021QBG:
-
+ rc = doPortProfileOp8021Qbg(macvtap_ifname, NULL, virtPort,
+ DISASSOCIATE);
break;
case VIR_VIRTUALPORT_8021QBH:
-
+ rc = doPortProfileOp8021Qbh(linkdev, virtPort,
+ NULL,
+ DISASSOCIATE);
break;
}
return rc;
}
-#endif /* WITH_MACVTAP */
+#endif /* WITH_MACVTAP || WITH_VIRTUALPORT */
Index: libvirt-acl/src/util/macvtap.h
===================================================================
--- libvirt-acl.orig/src/util/macvtap.h
+++ libvirt-acl/src/util/macvtap.h
@@ -72,6 +72,7 @@ int openMacvtapTap(const char *ifname,
char **res_ifname);
void delMacvtap(const char *ifname,
+ const char *linkdev,
virVirtualPortProfileParamsPtr virtPortProfile);
# endif /* WITH_MACVTAP */
@@ -80,6 +81,15 @@ void delMacvtap(const char *ifname,
# define MACVTAP_MODE_VEPA_STR "vepa"
# define MACVTAP_MODE_BRIDGE_STR "bridge"
+int vpAssociatePortProfileId(const char *macvtap_ifname,
+ const unsigned char *macvtap_macaddr,
+ const char *linkdev,
+ const virVirtualPortProfileParamsPtr virtPort,
+ const unsigned char *vmuuid);
+
+int vpDisassociatePortProfileId(const char *macvtap_ifname,
+ const char *linkdev,
+ const virVirtualPortProfileParamsPtr virtPort);
VIR_ENUM_DECL(virVirtualPort)
Index: libvirt-acl/src/libvirt_private.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_private.syms
+++ libvirt-acl/src/libvirt_private.syms
@@ -695,6 +695,9 @@ virArgvToString;
ifaceCtrl;
ifaceCheck;
ifaceGetIndex;
+ifaceGetFlags;
+ifaceIsUp;
+ifaceGetVlanID;
# usb.h
usbGetDevice;
Index: libvirt-acl/src/util/interface.c
===================================================================
--- libvirt-acl.orig/src/util/interface.c
+++ libvirt-acl/src/util/interface.c
@@ -30,6 +30,8 @@
#ifdef __linux__
# include <linux/if.h>
+# include <linux/sockios.h>
+# include <linux/if_vlan.h>
#endif
#include "internal.h"
@@ -42,6 +44,85 @@
virReportErrorHelper(NULL, VIR_FROM_NET, code, __FILE__, \
__FUNCTION__, __LINE__, __VA_ARGS__)
+#if __linux__
+static int
+getFlags(int fd, const char *ifname, struct ifreq *ifr) {
+
+ memset(ifr, 0, sizeof(*ifr));
+
+ if (virStrncpy(ifr->ifr_name,
+ ifname, strlen(ifname), sizeof(ifr->ifr_name)) == NULL)
+ return ENODEV;
+
+ if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0)
+ return errno;
+
+ return 0;
+}
+
+
+/**
+ * ifaceGetFlags
+ *
+ * @ifname : name of the interface
+ * @flags : pointer to short holding the flags on success
+ *
+ * Get the flags of the interface. Returns 0 on success, error code on failure.
+ */
+int
+ifaceGetFlags(const char *ifname, short *flags) {
+ struct ifreq ifr;
+ int rc;
+ int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
+
+ if (fd < 0)
+ return errno;
+
+ rc = getFlags(fd, ifname, &ifr);
+
+ *flags = ifr.ifr_flags;
+
+ close(fd);
+
+ return rc;
+}
+
+
+int
+ifaceIsUp(const char *ifname, bool *up) {
+ short flags;
+ int rc = ifaceGetFlags(ifname, &flags);
+
+ if (rc)
+ return rc;
+
+ *up = ((flags & IFF_UP) == IFF_UP);
+
+ return 0;
+}
+#else
+
+/* Note: Showstopper on cygwin is only missing PF_PACKET */
+
+int
+ifaceGetFlags(const char *ifname ATTRIBUTE_UNUSED,
+ short *flags ATTRIBUTE_UNUSED) {
+ ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("ifaceGetFlags is not supported on non-linux platforms"));
+ return ENOSYS;
+}
+
+int
+ifaceIsUp(const char *ifname ATTRIBUTE_UNUSED,
+ bool *up ATTRIBUTE_UNUSED) {
+
+ ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("ifaceIsUp is not supported on non-linux platforms"));
+ return ENOSYS;
+}
+
+#endif /* __linux__ */
+
/*
* chgIfaceFlags: Change flags on an interface
*
@@ -59,23 +140,16 @@
static int chgIfaceFlags(const char *ifname, short flagclear, short flagset) {
struct ifreq ifr;
int rc = 0;
- int flags;
+ short flags;
short flagmask = (~0 ^ flagclear);
int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
if (fd < 0)
return errno;
- if (virStrncpy(ifr.ifr_name,
- ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) {
- rc = ENODEV;
+ rc = getFlags(fd, ifname, &ifr);
+ if (rc != 0)
goto err_exit;
- }
-
- if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
- rc = errno;
- goto err_exit;
- }
flags = (ifr.ifr_flags & flagmask) | flagset;
@@ -151,6 +225,8 @@ ifaceCheck(bool reportError, const char
if (fd < 0)
return errno;
+ memset(&ifr, 0, sizeof(ifr));
+
if (virStrncpy(ifr.ifr_name,
ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) {
if (reportError)
@@ -227,6 +303,8 @@ ifaceGetIndex(bool reportError, const ch
if (fd < 0)
return errno;
+ memset(&ifreq, 0, sizeof(ifreq));
+
if (virStrncpy(ifreq.ifr_name, ifname, strlen(ifname),
sizeof(ifreq.ifr_name)) == NULL) {
if (reportError)
@@ -269,3 +347,46 @@ ifaceGetIndex(bool reportError,
}
#endif /* __linux__ */
+
+#ifdef __linux__
+int
+ifaceGetVlanID(const char *vlanifname, int *vlanid) {
+ struct vlan_ioctl_args vlanargs = {
+ .cmd = GET_VLAN_VID_CMD,
+ };
+ int rc = 0;
+ int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
+
+ if (fd < 0)
+ return errno;
+
+ if (virStrcpyStatic(vlanargs.device1, vlanifname) == NULL) {
+ rc = EINVAL;
+ goto err_exit;
+ }
+
+ if (ioctl(fd, SIOCGIFVLAN, &vlanargs) != 0) {
+ rc = errno;
+ goto err_exit;
+ }
+
+ *vlanid = vlanargs.u.VID;
+
+ err_exit:
+ close(fd);
+
+ return rc;
+}
+
+#else
+
+int
+ifaceGetVlanID(const char *vlanifname ATTRIBUTE_UNUSED,
+ int *vlanid ATTRIBUTE_UNUSED) {
+
+ ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("ifaceGetVlanID is not supported on non-linux platforms"));
+
+ return ENOSYS;
+}
+#endif /* __linux__ */
Index: libvirt-acl/src/util/interface.h
===================================================================
--- libvirt-acl.orig/src/util/interface.h
+++ libvirt-acl/src/util/interface.h
@@ -12,6 +12,9 @@
# include "datatypes.h"
+int ifaceGetFlags(const char *name, short *flags);
+int ifaceIsUp(const char *name, bool *up);
+
int ifaceCtrl(const char *name, bool up);
static inline int ifaceUp(const char *name) {
@@ -27,4 +30,6 @@ int ifaceCheck(bool reportError, const c
int ifaceGetIndex(bool reportError, const char *ifname, int *ifindex);
+int ifaceGetVlanID(const char *vlanifname, int *vlanid);
+
#endif /* __VIR_INTERFACE_H__ */
14 years, 7 months
[libvirt] [PATCH] esx: Simplify goto usage (part 2/2)
by Matthias Bolte
Eliminate almost all backward jumps by replacing this common pattern:
int
some_random_function(void)
{
int result = 0;
...
cleanup:
<unconditional cleanup code>
return result;
failure:
<cleanup code in case of an error>
result = -1;
goto cleanup
}
with this simpler pattern:
int
some_random_function(void)
{
int result = -1;
...
result = 0;
cleanup:
if (result < 0) {
<cleanup code in case of an error>
}
<unconditional cleanup code>
return result;
}
Add a bool success variable in functions that don't have a int result
that can be used for the new pattern.
Also remove some unnecessary memsets in error paths.
---
I've split this 200kb patch into two 100kb parts.
Part 1:
src/esx/esx_driver.c | 840 ++++++++++++++++++------------------------
src/esx/esx_storage_driver.c | 4 -
src/esx/esx_util.c | 74 ++--
Part 2:
src/esx/esx_vi.c | 488 +++++++++++--------------
src/esx/esx_vi_methods.c | 44 +--
src/esx/esx_vi_types.c | 23 +-
src/esx/esx_vmx.c | 298 ++++++++-------
7 files changed, 793 insertions(+), 978 deletions(-)
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 1483f05..c535dbb 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -279,7 +279,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
const char *ipAddress, const char *username,
const char *password, int noVerify)
{
- int result = 0;
+ int result = -1;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *datacenterList = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
@@ -288,12 +288,12 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
password == NULL || ctx->url != NULL || ctx->service != NULL ||
ctx->curl_handle != NULL || ctx->curl_headers != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
- goto failure;
+ return -1;
}
if (esxVI_String_DeepCopyValue(&ctx->url, url) < 0 ||
esxVI_String_DeepCopyValue(&ctx->ipAddress, ipAddress) < 0) {
- goto failure;
+ goto cleanup;
}
ctx->curl_handle = curl_easy_init();
@@ -301,7 +301,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
if (ctx->curl_handle == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not initialize CURL"));
- goto failure;
+ goto cleanup;
}
ctx->curl_headers = curl_slist_append(ctx->curl_headers, "Content-Type: "
@@ -321,7 +321,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
if (ctx->curl_headers == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not build CURL header list"));
- goto failure;
+ goto cleanup;
}
curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, ctx->url);
@@ -346,7 +346,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
if (virMutexInit(&ctx->curl_lock) < 0) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not initialize CURL mutex"));
- goto failure;
+ goto cleanup;
}
ctx->username = strdup(username);
@@ -354,11 +354,11 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
if (ctx->username == NULL || ctx->password == NULL) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
if (esxVI_RetrieveServiceContent(ctx, &ctx->service) < 0) {
- goto failure;
+ goto cleanup;
}
if (STREQ(ctx->service->about->apiType, "HostAgent") ||
@@ -371,7 +371,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VI API major/minor version '2.5' or '4.0' "
"but found '%s'"), ctx->service->about->apiVersion);
- goto failure;
+ goto cleanup;
}
if (STREQ(ctx->service->about->productLineId, "gsx")) {
@@ -381,7 +381,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting GSX major/minor version '2.0' but "
"found '%s'"), ctx->service->about->version);
- goto failure;
+ goto cleanup;
}
} else if (STREQ(ctx->service->about->productLineId, "esx") ||
STREQ(ctx->service->about->productLineId, "embeddedEsx")) {
@@ -394,7 +394,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
_("Expecting ESX major/minor version '3.5' or "
"'4.0' but found '%s'"),
ctx->service->about->version);
- goto failure;
+ goto cleanup;
}
} else if (STREQ(ctx->service->about->productLineId, "vpx")) {
if (STRPREFIX(ctx->service->about->version, "2.5")) {
@@ -405,24 +405,24 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VPX major/minor version '2.5' or '4.0' "
"but found '%s'"), ctx->service->about->version);
- goto failure;
+ goto cleanup;
}
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting product 'gsx' or 'esx' or 'embeddedEsx' "
"or 'vpx' but found '%s'"),
ctx->service->about->productLineId);
- goto failure;
+ goto cleanup;
}
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VI API type 'HostAgent' or 'VirtualCenter' "
"but found '%s'"), ctx->service->about->apiType);
- goto failure;
+ goto cleanup;
}
if (esxVI_Login(ctx, username, password, NULL, &ctx->session) < 0) {
- goto failure;
+ goto cleanup;
}
esxVI_BuildFullTraversalSpecList(&ctx->fullTraversalSpecList);
@@ -430,7 +430,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
if (esxVI_String_AppendValueListToList(&propertyNameList,
"vmFolder\0"
"hostFolder\0") < 0) {
- goto failure;
+ goto cleanup;
}
/* Get pointer to Datacenter for later use */
@@ -438,14 +438,14 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
"Datacenter", propertyNameList,
esxVI_Boolean_True,
&datacenterList) < 0) {
- goto failure;
+ goto cleanup;
}
if (datacenterList == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve the 'datacenter' object from the "
"VI host/center"));
- goto failure;
+ goto cleanup;
}
ctx->datacenter = datacenterList->obj;
@@ -457,12 +457,12 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
if (STREQ(dynamicProperty->name, "vmFolder")) {
if (esxVI_ManagedObjectReference_CastFromAnyType
(dynamicProperty->val, &ctx->vmFolder)) {
- goto failure;
+ goto cleanup;
}
} else if (STREQ(dynamicProperty->name, "hostFolder")) {
if (esxVI_ManagedObjectReference_CastFromAnyType
(dynamicProperty->val, &ctx->hostFolder)) {
- goto failure;
+ goto cleanup;
}
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
@@ -473,19 +473,16 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("The 'datacenter' object is missing the "
"'vmFolder'/'hostFolder' property"));
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&datacenterList);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
int
@@ -496,7 +493,7 @@ esxVI_Context_DownloadFile(esxVI_Context *ctx, const char *url, char **content)
if (content == NULL || *content != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
- goto failure;
+ return -1;
}
virMutexLock(&ctx->curl_lock);
@@ -511,27 +508,28 @@ esxVI_Context_DownloadFile(esxVI_Context *ctx, const char *url, char **content)
virMutexUnlock(&ctx->curl_lock);
if (responseCode < 0) {
- goto failure;
+ goto cleanup;
} else if (responseCode != 200) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("HTTP response code %d for download from '%s'"),
responseCode, url);
- goto failure;
+ goto cleanup;
}
if (virBufferError(&buffer)) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
*content = virBufferContentAndReset(&buffer);
- return 0;
-
- failure:
- virBufferFreeAndReset(&buffer);
+ cleanup:
+ if (*content == NULL) {
+ virBufferFreeAndReset(&buffer);
+ return -1;
+ }
- return -1;
+ return 0;
}
int
@@ -573,7 +571,7 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
const char *request, esxVI_Response **response,
esxVI_Occurrence occurrence)
{
- int result = 0;
+ int result = -1;
virBuffer buffer = VIR_BUFFER_INITIALIZER;
esxVI_Fault *fault = NULL;
char *xpathExpression = NULL;
@@ -582,11 +580,11 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
if (request == NULL || response == NULL || *response != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
- goto failure;
+ return -1;
}
if (esxVI_Response_Alloc(response) < 0) {
- goto failure;
+ return -1;
}
virMutexLock(&ctx->curl_lock);
@@ -602,12 +600,12 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
virMutexUnlock(&ctx->curl_lock);
if ((*response)->responseCode < 0) {
- goto failure;
+ goto cleanup;
}
if (virBufferError(&buffer)) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
(*response)->content = virBufferContentAndReset(&buffer);
@@ -620,14 +618,14 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Response for call to '%s' could not be parsed"),
methodName);
- goto failure;
+ goto cleanup;
}
if (xmlDocGetRootElement((*response)->document) == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Response for call to '%s' is an empty XML document"),
methodName);
- goto failure;
+ goto cleanup;
}
xpathContext = xmlXPathNewContext((*response)->document);
@@ -635,7 +633,7 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
if (xpathContext == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not create XPath context"));
- goto failure;
+ goto cleanup;
}
xmlXPathRegisterNs(xpathContext, BAD_CAST "soapenv",
@@ -652,7 +650,7 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
_("HTTP response code %d for call to '%s'. "
"Fault is unknown, XPath evaluation failed"),
(*response)->responseCode, methodName);
- goto failure;
+ goto cleanup;
}
if (esxVI_Fault_Deserialize((*response)->node, &fault) < 0) {
@@ -660,7 +658,7 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
_("HTTP response code %d for call to '%s'. "
"Fault is unknown, deserialization failed"),
(*response)->responseCode, methodName);
- goto failure;
+ goto cleanup;
}
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
@@ -673,13 +671,13 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
(*response)->responseCode, methodName,
(*response)->content);
- goto failure;
+ goto cleanup;
} else {
if (virAsprintf(&xpathExpression,
"/soapenv:Envelope/soapenv:Body/vim:%sResponse",
methodName) < 0) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
responseNode = virXPathNode(xpathExpression, xpathContext);
@@ -688,7 +686,7 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("XPath evaluation of response for call to '%s' "
"failed"), methodName);
- goto failure;
+ goto cleanup;
}
xpathContext->node = responseNode;
@@ -700,12 +698,12 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Call to '%s' returned an empty result, "
"expecting a non-empty result"), methodName);
- goto failure;
+ goto cleanup;
} else if ((*response)->node->next != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Call to '%s' returned a list, expecting "
"exactly one item"), methodName);
- goto failure;
+ goto cleanup;
}
break;
@@ -715,7 +713,7 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Call to '%s' returned an empty result, "
"expecting a non-empty result"), methodName);
- goto failure;
+ goto cleanup;
}
break;
@@ -726,7 +724,7 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Call to '%s' returned a list, expecting "
"exactly one item"), methodName);
- goto failure;
+ goto cleanup;
}
break;
@@ -740,7 +738,7 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Call to '%s' returned something, expecting "
"an empty result"), methodName);
- goto failure;
+ goto cleanup;
}
break;
@@ -748,30 +746,29 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
default:
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Invalid argument (occurrence)"));
- goto failure;
+ goto cleanup;
}
}
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("HTTP response code %d for call to '%s'"),
(*response)->responseCode, methodName);
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
+ if (result < 0) {
+ virBufferFreeAndReset(&buffer);
+ esxVI_Response_Free(response);
+ esxVI_Fault_Free(&fault);
+ }
+
VIR_FREE(xpathExpression);
xmlXPathFreeContext(xpathContext);
return result;
-
- failure:
- virBufferFreeAndReset(&buffer);
- esxVI_Response_Free(response);
- esxVI_Fault_Free(&fault);
-
- result = -1;
-
- goto cleanup;
}
@@ -877,39 +874,36 @@ esxVI_Enumeration_Deserialize(const esxVI_Enumeration *enumeration,
xmlNodePtr node, int *value)
{
int i;
- int result = 0;
+ int result = -1;
char *name = NULL;
if (value == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
- goto failure;
+ return -1;
}
*value = 0; /* undefined */
if (esxVI_String_DeserializeValue(node, &name) < 0) {
- goto failure;
+ return -1;
}
for (i = 0; enumeration->values[i].name != NULL; ++i) {
if (STREQ(name, enumeration->values[i].name)) {
*value = enumeration->values[i].value;
- goto cleanup;
+ result = 0;
+ break;
}
}
- ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, _("Unknown value '%s' for %s"),
- name, esxVI_Type_ToString(enumeration->type));
+ if (result < 0) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, _("Unknown value '%s' for %s"),
+ name, esxVI_Type_ToString(enumeration->type));
+ }
- cleanup:
VIR_FREE(name);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
@@ -954,7 +948,7 @@ esxVI_List_DeepCopy(esxVI_List **destList, esxVI_List *srcList,
if (destList == NULL || *destList != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
- goto failure;
+ return -1;
}
for (src = srcList; src != NULL; src = src->_next) {
@@ -980,7 +974,7 @@ esxVI_List_CastFromAnyType(esxVI_AnyType *anyType, esxVI_List **list,
esxVI_List_CastFromAnyTypeFunc castFromAnyTypeFunc,
esxVI_List_FreeFunc freeFunc)
{
- int result = 0;
+ int result = -1;
xmlNodePtr childNode = NULL;
esxVI_AnyType *childAnyType = NULL;
esxVI_List *item = NULL;
@@ -1007,7 +1001,7 @@ esxVI_List_CastFromAnyType(esxVI_AnyType *anyType, esxVI_List **list,
if (childNode->type != XML_ELEMENT_NODE) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Wrong XML element type %d"), childNode->type);
- goto failure;
+ goto cleanup;
}
esxVI_AnyType_Free(&childAnyType);
@@ -1015,24 +1009,23 @@ esxVI_List_CastFromAnyType(esxVI_AnyType *anyType, esxVI_List **list,
if (esxVI_AnyType_Deserialize(childNode, &childAnyType) < 0 ||
castFromAnyTypeFunc(childAnyType, &item) < 0 ||
esxVI_List_Append(list, item) < 0) {
- goto failure;
+ goto cleanup;
}
item = NULL;
}
+ result = 0;
+
cleanup:
+ if (result < 0) {
+ freeFunc(&item);
+ freeFunc(list);
+ }
+
esxVI_AnyType_Free(&childAnyType);
return result;
-
- failure:
- freeFunc(&item);
- freeFunc(list);
-
- result = -1;
-
- goto cleanup;
}
int
@@ -1300,7 +1293,7 @@ esxVI_EnsureSession(esxVI_Context *ctx)
#if ESX_VI_USE_SESSION_IS_ACTIVE
esxVI_Boolean active = esxVI_Boolean_Undefined;
#else
- int result = 0;
+ int result = -1;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *sessionManager = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
@@ -1335,7 +1328,7 @@ esxVI_EnsureSession(esxVI_Context *ctx)
"SessionManager", propertyNameList,
esxVI_Boolean_False,
&sessionManager) < 0) {
- goto failure;
+ goto cleanup;
}
for (dynamicProperty = sessionManager->propSet; dynamicProperty != NULL;
@@ -1343,7 +1336,7 @@ esxVI_EnsureSession(esxVI_Context *ctx)
if (STREQ(dynamicProperty->name, "currentSession")) {
if (esxVI_UserSession_CastFromAnyType(dynamicProperty->val,
¤tSession) < 0) {
- goto failure;
+ goto cleanup;
}
break;
@@ -1357,26 +1350,23 @@ esxVI_EnsureSession(esxVI_Context *ctx)
if (esxVI_Login(ctx, ctx->username, ctx->password, NULL,
&ctx->session) < 0) {
- goto failure;
+ goto cleanup;
}
} else if (STRNEQ(ctx->session->key, currentSession->key)) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Key of the current session differs from the key at "
"last login"));
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&sessionManager);
esxVI_UserSession_Free(¤tSession);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
#endif
}
@@ -1390,7 +1380,7 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx,
esxVI_Boolean recurse,
esxVI_ObjectContent **objectContentList)
{
- int result = 0;
+ int result = -1;
esxVI_ObjectSpec *objectSpec = NULL;
esxVI_PropertySpec *propertySpec = NULL;
esxVI_PropertyFilterSpec *propertyFilterSpec = NULL;
@@ -1401,7 +1391,7 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx,
}
if (esxVI_ObjectSpec_Alloc(&objectSpec) < 0) {
- goto failure;
+ return -1;
}
objectSpec->obj = root;
@@ -1412,7 +1402,7 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx,
}
if (esxVI_PropertySpec_Alloc(&propertySpec) < 0) {
- goto failure;
+ goto cleanup;
}
propertySpec->type = (char *)type;
@@ -1423,7 +1413,7 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx,
propertySpec) < 0 ||
esxVI_ObjectSpec_AppendToList(&propertyFilterSpec->objectSet,
objectSpec) < 0) {
- goto failure;
+ goto cleanup;
}
result = esxVI_RetrieveProperties(ctx, propertyFilterSpec,
@@ -1447,11 +1437,6 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx,
esxVI_PropertyFilterSpec_Free(&propertyFilterSpec);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
@@ -1642,19 +1627,20 @@ esxVI_LookupNumberOfDomainsByPowerState(esxVI_Context *ctx,
esxVI_VirtualMachinePowerState powerState,
esxVI_Boolean inverse)
{
+ bool success = false;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *virtualMachineList = NULL;
esxVI_ObjectContent *virtualMachine = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
esxVI_VirtualMachinePowerState powerState_;
- int numberOfDomains = 0;
+ int count = 0;
if (esxVI_String_AppendValueToList(&propertyNameList,
"runtime.powerState") < 0 ||
esxVI_LookupObjectContentByType(ctx, ctx->vmFolder, "VirtualMachine",
propertyNameList, esxVI_Boolean_True,
&virtualMachineList) < 0) {
- goto failure;
+ goto cleanup;
}
for (virtualMachine = virtualMachineList; virtualMachine != NULL;
@@ -1665,14 +1651,14 @@ esxVI_LookupNumberOfDomainsByPowerState(esxVI_Context *ctx,
if (STREQ(dynamicProperty->name, "runtime.powerState")) {
if (esxVI_VirtualMachinePowerState_CastFromAnyType
(dynamicProperty->val, &powerState_) < 0) {
- goto failure;
+ goto cleanup;
}
if ((inverse != esxVI_Boolean_True &&
powerState_ == powerState) ||
(inverse == esxVI_Boolean_True &&
powerState_ != powerState)) {
- numberOfDomains++;
+ count++;
}
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
@@ -1680,16 +1666,13 @@ esxVI_LookupNumberOfDomainsByPowerState(esxVI_Context *ctx,
}
}
+ success = true;
+
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&virtualMachineList);
- return numberOfDomains;
-
- failure:
- numberOfDomains = -1;
-
- goto cleanup;
+ return success ? count : -1;
}
@@ -1955,7 +1938,7 @@ esxVI_LookupResourcePoolByHostSystem
(esxVI_Context *ctx, esxVI_ObjectContent *hostSystem,
esxVI_ManagedObjectReference **resourcePool)
{
- int result = 0;
+ int result = -1;
esxVI_String *propertyNameList = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
esxVI_ManagedObjectReference *managedObjectReference = NULL;
@@ -1971,7 +1954,7 @@ esxVI_LookupResourcePoolByHostSystem
if (STREQ(dynamicProperty->name, "parent")) {
if (esxVI_ManagedObjectReference_CastFromAnyType
(dynamicProperty->val, &managedObjectReference) < 0) {
- goto failure;
+ goto cleanup;
}
break;
@@ -1983,7 +1966,7 @@ esxVI_LookupResourcePoolByHostSystem
if (managedObjectReference == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve compute resource of host system"));
- goto failure;
+ goto cleanup;
}
if (esxVI_String_AppendValueToList(&propertyNameList, "resourcePool") < 0 ||
@@ -1991,13 +1974,13 @@ esxVI_LookupResourcePoolByHostSystem
"ComputeResource", propertyNameList,
esxVI_Boolean_False,
&computeResource) < 0) {
- goto failure;
+ goto cleanup;
}
if (computeResource == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve compute resource of host system"));
- goto failure;
+ goto cleanup;
}
for (dynamicProperty = computeResource->propSet; dynamicProperty != NULL;
@@ -2005,7 +1988,7 @@ esxVI_LookupResourcePoolByHostSystem
if (STREQ(dynamicProperty->name, "resourcePool")) {
if (esxVI_ManagedObjectReference_CastFromAnyType
(dynamicProperty->val, resourcePool) < 0) {
- goto failure;
+ goto cleanup;
}
break;
@@ -2017,20 +2000,17 @@ esxVI_LookupResourcePoolByHostSystem
if ((*resourcePool) == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not retrieve resource pool of compute resource"));
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ManagedObjectReference_Free(&managedObjectReference);
esxVI_ObjectContent_Free(&computeResource);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
@@ -2040,7 +2020,7 @@ esxVI_LookupHostSystemByIp(esxVI_Context *ctx, const char *ipAddress,
esxVI_String *propertyNameList,
esxVI_ObjectContent **hostSystem)
{
- int result = 0;
+ int result = -1;
esxVI_ManagedObjectReference *managedObjectReference = NULL;
if (hostSystem == NULL || *hostSystem != NULL) {
@@ -2050,31 +2030,28 @@ esxVI_LookupHostSystemByIp(esxVI_Context *ctx, const char *ipAddress,
if (esxVI_FindByIp(ctx, ctx->datacenter, ipAddress, esxVI_Boolean_False,
&managedObjectReference) < 0) {
- goto failure;
+ return -1;
}
if (managedObjectReference == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Could not find host system with IP address '%s'"),
ipAddress);
- goto failure;
+ goto cleanup;
}
if (esxVI_LookupObjectContentByType(ctx, managedObjectReference,
"HostSystem", propertyNameList,
esxVI_Boolean_False, hostSystem) < 0) {
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
esxVI_ManagedObjectReference_Free(&managedObjectReference);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
@@ -2085,7 +2062,7 @@ esxVI_LookupVirtualMachineByUuid(esxVI_Context *ctx, const unsigned char *uuid,
esxVI_ObjectContent **virtualMachine,
esxVI_Occurrence occurrence)
{
- int result = 0;
+ int result = -1;
esxVI_ManagedObjectReference *managedObjectReference = NULL;
char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
@@ -2098,7 +2075,7 @@ esxVI_LookupVirtualMachineByUuid(esxVI_Context *ctx, const unsigned char *uuid,
if (esxVI_FindByUuid(ctx, ctx->datacenter, uuid_string, esxVI_Boolean_True,
&managedObjectReference) < 0) {
- goto failure;
+ return -1;
}
if (managedObjectReference == NULL) {
@@ -2108,7 +2085,7 @@ esxVI_LookupVirtualMachineByUuid(esxVI_Context *ctx, const unsigned char *uuid,
ESX_VI_ERROR(VIR_ERR_NO_DOMAIN,
_("Could not find domain with UUID '%s'"),
uuid_string);
- goto failure;
+ goto cleanup;
}
}
@@ -2116,18 +2093,15 @@ esxVI_LookupVirtualMachineByUuid(esxVI_Context *ctx, const unsigned char *uuid,
"VirtualMachine", propertyNameList,
esxVI_Boolean_False,
virtualMachine) < 0) {
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
esxVI_ManagedObjectReference_Free(&managedObjectReference);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
@@ -2138,7 +2112,7 @@ esxVI_LookupVirtualMachineByName(esxVI_Context *ctx, const char *name,
esxVI_ObjectContent **virtualMachine,
esxVI_Occurrence occurrence)
{
- int result = 0;
+ int result = -1;
esxVI_String *completePropertyNameList = NULL;
esxVI_ObjectContent *virtualMachineList = NULL;
esxVI_ObjectContent *candidate = NULL;
@@ -2156,7 +2130,7 @@ esxVI_LookupVirtualMachineByName(esxVI_Context *ctx, const char *name,
completePropertyNameList,
esxVI_Boolean_True,
&virtualMachineList) < 0) {
- goto failure;
+ goto cleanup;
}
for (candidate = virtualMachineList; candidate != NULL;
@@ -2165,7 +2139,7 @@ esxVI_LookupVirtualMachineByName(esxVI_Context *ctx, const char *name,
if (esxVI_GetVirtualMachineIdentity(candidate, NULL, &name_candidate,
NULL) < 0) {
- goto failure;
+ goto cleanup;
}
if (STRNEQ(name, name_candidate)) {
@@ -2173,7 +2147,7 @@ esxVI_LookupVirtualMachineByName(esxVI_Context *ctx, const char *name,
}
if (esxVI_ObjectContent_DeepCopy(virtualMachine, candidate) < 0) {
- goto failure;
+ goto cleanup;
}
break;
@@ -2185,21 +2159,18 @@ esxVI_LookupVirtualMachineByName(esxVI_Context *ctx, const char *name,
} else {
ESX_VI_ERROR(VIR_ERR_NO_DOMAIN,
_("Could not find domain with name '%s'"), name);
- goto failure;
+ goto cleanup;
}
}
+ result = 0;
+
cleanup:
esxVI_String_Free(&completePropertyNameList);
esxVI_ObjectContent_Free(&virtualMachineList);
VIR_FREE(name_candidate);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
@@ -2210,7 +2181,7 @@ esxVI_LookupVirtualMachineByUuidAndPrepareForTask
esxVI_String *propertyNameList, esxVI_ObjectContent **virtualMachine,
esxVI_Boolean autoAnswer)
{
- int result = 0;
+ int result = -1;
esxVI_String *completePropertyNameList = NULL;
esxVI_VirtualMachineQuestionInfo *questionInfo = NULL;
esxVI_TaskInfo *pendingTaskInfoList = NULL;
@@ -2227,32 +2198,29 @@ esxVI_LookupVirtualMachineByUuidAndPrepareForTask
&questionInfo) < 0 ||
esxVI_LookupPendingTaskInfoListByVirtualMachine
(ctx, *virtualMachine, &pendingTaskInfoList) < 0) {
- goto failure;
+ goto cleanup;
}
if (questionInfo != NULL &&
esxVI_HandleVirtualMachineQuestion(ctx, (*virtualMachine)->obj,
questionInfo, autoAnswer) < 0) {
- goto failure;
+ goto cleanup;
}
if (pendingTaskInfoList != NULL) {
ESX_VI_ERROR(VIR_ERR_OPERATION_INVALID, "%s",
_("Other tasks are pending for this domain"));
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
esxVI_String_Free(&completePropertyNameList);
esxVI_VirtualMachineQuestionInfo_Free(&questionInfo);
esxVI_TaskInfo_Free(&pendingTaskInfoList);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
@@ -2263,7 +2231,7 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
esxVI_ObjectContent **datastore,
esxVI_Occurrence occurrence)
{
- int result = 0;
+ int result = -1;
esxVI_String *completePropertyNameList = NULL;
esxVI_ObjectContent *datastoreList = NULL;
esxVI_ObjectContent *candidate = NULL;
@@ -2284,23 +2252,23 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
"summary.accessible\0"
"summary.name\0"
"summary.url\0") < 0) {
- goto failure;
+ goto cleanup;
}
if (esxVI_LookupObjectContentByType(ctx, ctx->datacenter, "Datastore",
completePropertyNameList,
esxVI_Boolean_True,
&datastoreList) < 0) {
- goto failure;
+ goto cleanup;
}
if (datastoreList == NULL) {
if (occurrence == esxVI_Occurrence_OptionalItem) {
- goto cleanup;
+ goto success;
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("No datastores available"));
- goto failure;
+ goto cleanup;
}
}
@@ -2314,7 +2282,7 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
if (STREQ(dynamicProperty->name, "summary.accessible")) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_Boolean) < 0) {
- goto failure;
+ goto cleanup;
}
accessible = dynamicProperty->val->boolean;
@@ -2326,7 +2294,7 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Got incomplete response while querying for the "
"datastore 'summary.accessible' property"));
- goto failure;
+ goto cleanup;
}
if (accessible == esxVI_Boolean_False) {
@@ -2338,17 +2306,17 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
if (STREQ(dynamicProperty->name, "summary.name")) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_String) < 0) {
- goto failure;
+ goto cleanup;
}
if (STREQ(dynamicProperty->val->string, name)) {
if (esxVI_ObjectContent_DeepCopy(datastore,
candidate) < 0) {
- goto failure;
+ goto cleanup;
}
/* Found datastore with matching name */
- goto cleanup;
+ goto success;
}
} else if (STREQ(dynamicProperty->name, "summary.url") &&
ctx->productVersion & esxVI_ProductVersion_ESX) {
@@ -2362,7 +2330,7 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_String) < 0) {
- goto failure;
+ goto cleanup;
}
if (! STRPREFIX(dynamicProperty->val->string,
@@ -2371,17 +2339,17 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
_("Datastore URL '%s' has unexpected prefix, "
"expecting '/vmfs/volumes/' prefix"),
dynamicProperty->val->string);
- goto failure;
+ goto cleanup;
}
if (STREQ(dynamicProperty->val->string + offset, name)) {
if (esxVI_ObjectContent_DeepCopy(datastore,
candidate) < 0) {
- goto failure;
+ goto cleanup;
}
/* Found datastore with matching URL suffix */
- goto cleanup;
+ goto success;
}
}
}
@@ -2397,19 +2365,17 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
_("Could not find datastore '%s'"), name);
}
- goto failure;
+ goto cleanup;
}
+ success:
+ result = 0;
+
cleanup:
esxVI_String_Free(&completePropertyNameList);
esxVI_ObjectContent_Free(&datastoreList);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
@@ -2419,7 +2385,7 @@ esxVI_LookupTaskInfoByTask(esxVI_Context *ctx,
esxVI_ManagedObjectReference *task,
esxVI_TaskInfo **taskInfo)
{
- int result = 0;
+ int result = -1;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *objectContent = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
@@ -2433,7 +2399,7 @@ esxVI_LookupTaskInfoByTask(esxVI_Context *ctx,
esxVI_LookupObjectContentByType(ctx, task, "Task", propertyNameList,
esxVI_Boolean_False,
&objectContent) < 0) {
- goto failure;
+ goto cleanup;
}
for (dynamicProperty = objectContent->propSet; dynamicProperty != NULL;
@@ -2441,7 +2407,7 @@ esxVI_LookupTaskInfoByTask(esxVI_Context *ctx,
if (STREQ(dynamicProperty->name, "info")) {
if (esxVI_TaskInfo_CastFromAnyType(dynamicProperty->val,
taskInfo) < 0) {
- goto failure;
+ goto cleanup;
}
break;
@@ -2450,16 +2416,13 @@ esxVI_LookupTaskInfoByTask(esxVI_Context *ctx,
}
}
+ result = 0;
+
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&objectContent);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
@@ -2469,7 +2432,7 @@ esxVI_LookupPendingTaskInfoListByVirtualMachine
(esxVI_Context *ctx, esxVI_ObjectContent *virtualMachine,
esxVI_TaskInfo **pendingTaskInfoList)
{
- int result = 0;
+ int result = -1;
esxVI_String *propertyNameList = NULL;
esxVI_ManagedObjectReference *recentTaskList = NULL;
esxVI_ManagedObjectReference *recentTask = NULL;
@@ -2487,7 +2450,7 @@ esxVI_LookupPendingTaskInfoListByVirtualMachine
if (STREQ(dynamicProperty->name, "recentTask")) {
if (esxVI_ManagedObjectReference_CastListFromAnyType
(dynamicProperty->val, &recentTaskList) < 0) {
- goto failure;
+ goto cleanup;
}
break;
@@ -2498,14 +2461,14 @@ esxVI_LookupPendingTaskInfoListByVirtualMachine
for (recentTask = recentTaskList; recentTask != NULL;
recentTask = recentTask->_next) {
if (esxVI_LookupTaskInfoByTask(ctx, recentTask, &taskInfo) < 0) {
- goto failure;
+ goto cleanup;
}
if (taskInfo->state == esxVI_TaskInfoState_Queued ||
taskInfo->state == esxVI_TaskInfoState_Running) {
if (esxVI_TaskInfo_AppendToList(pendingTaskInfoList,
taskInfo) < 0) {
- goto failure;
+ goto cleanup;
}
taskInfo = NULL;
@@ -2514,19 +2477,18 @@ esxVI_LookupPendingTaskInfoListByVirtualMachine
}
}
+ result = 0;
+
cleanup:
+ if (result < 0) {
+ esxVI_TaskInfo_Free(pendingTaskInfoList);
+ }
+
esxVI_String_Free(&propertyNameList);
esxVI_ManagedObjectReference_Free(&recentTaskList);
esxVI_TaskInfo_Free(&taskInfo);
return result;
-
- failure:
- esxVI_TaskInfo_Free(pendingTaskInfoList);
-
- result = -1;
-
- goto cleanup;
}
@@ -2536,7 +2498,7 @@ esxVI_LookupAndHandleVirtualMachineQuestion(esxVI_Context *ctx,
const unsigned char *uuid,
esxVI_Boolean autoAnswer)
{
- int result = 0;
+ int result = -1;
esxVI_ObjectContent *virtualMachine = NULL;
esxVI_String *propertyNameList = NULL;
esxVI_VirtualMachineQuestionInfo *questionInfo = NULL;
@@ -2548,26 +2510,23 @@ esxVI_LookupAndHandleVirtualMachineQuestion(esxVI_Context *ctx,
esxVI_Occurrence_RequiredItem) < 0 ||
esxVI_GetVirtualMachineQuestionInfo(virtualMachine,
&questionInfo) < 0) {
- goto failure;
+ goto cleanup;
}
if (questionInfo != NULL &&
esxVI_HandleVirtualMachineQuestion(ctx, virtualMachine->obj,
questionInfo, autoAnswer) < 0) {
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
esxVI_ObjectContent_Free(&virtualMachine);
esxVI_String_Free(&propertyNameList);
esxVI_VirtualMachineQuestionInfo_Free(&questionInfo);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
@@ -2577,7 +2536,7 @@ esxVI_LookupRootSnapshotTreeList
(esxVI_Context *ctx, const unsigned char *virtualMachineUuid,
esxVI_VirtualMachineSnapshotTree **rootSnapshotTreeList)
{
- int result = 0;
+ int result = -1;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *virtualMachine = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
@@ -2592,7 +2551,7 @@ esxVI_LookupRootSnapshotTreeList
esxVI_LookupVirtualMachineByUuid(ctx, virtualMachineUuid,
propertyNameList, &virtualMachine,
esxVI_Occurrence_RequiredItem) < 0) {
- goto failure;
+ goto cleanup;
}
for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL;
@@ -2600,7 +2559,7 @@ esxVI_LookupRootSnapshotTreeList
if (STREQ(dynamicProperty->name, "snapshot.rootSnapshotList")) {
if (esxVI_VirtualMachineSnapshotTree_CastListFromAnyType
(dynamicProperty->val, rootSnapshotTreeList) < 0) {
- goto failure;
+ goto cleanup;
}
break;
@@ -2609,18 +2568,17 @@ esxVI_LookupRootSnapshotTreeList
}
}
+ result = 0;
+
cleanup:
+ if (result < 0) {
+ esxVI_VirtualMachineSnapshotTree_Free(rootSnapshotTreeList);
+ }
+
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&virtualMachine);
return result;
-
- failure:
- esxVI_VirtualMachineSnapshotTree_Free(rootSnapshotTreeList);
-
- result = -1;
-
- goto cleanup;
}
@@ -2631,7 +2589,7 @@ esxVI_LookupCurrentSnapshotTree
esxVI_VirtualMachineSnapshotTree **currentSnapshotTree,
esxVI_Occurrence occurrence)
{
- int result = 0;
+ int result = -1;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *virtualMachine = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
@@ -2650,7 +2608,7 @@ esxVI_LookupCurrentSnapshotTree
esxVI_LookupVirtualMachineByUuid(ctx, virtualMachineUuid,
propertyNameList, &virtualMachine,
esxVI_Occurrence_RequiredItem) < 0) {
- goto failure;
+ goto cleanup;
}
for (dynamicProperty = virtualMachine->propSet; dynamicProperty != NULL;
@@ -2658,12 +2616,12 @@ esxVI_LookupCurrentSnapshotTree
if (STREQ(dynamicProperty->name, "snapshot.currentSnapshot")) {
if (esxVI_ManagedObjectReference_CastFromAnyType
(dynamicProperty->val, ¤tSnapshot) < 0) {
- goto failure;
+ goto cleanup;
}
} else if (STREQ(dynamicProperty->name, "snapshot.rootSnapshotList")) {
if (esxVI_VirtualMachineSnapshotTree_CastListFromAnyType
(dynamicProperty->val, &rootSnapshotTreeList) < 0) {
- goto failure;
+ goto cleanup;
}
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
@@ -2676,23 +2634,25 @@ esxVI_LookupCurrentSnapshotTree
} else {
ESX_VI_ERROR(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s",
_("Domain has no current snapshot"));
- goto failure;
+ goto cleanup;
}
}
if (rootSnapshotTreeList == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not lookup root snapshot list"));
- goto failure;
+ goto cleanup;
}
if (esxVI_GetSnapshotTreeBySnapshot(rootSnapshotTreeList, currentSnapshot,
&snapshotTree) < 0 ||
esxVI_VirtualMachineSnapshotTree_DeepCopy(currentSnapshotTree,
snapshotTree) < 0) {
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&virtualMachine);
@@ -2700,11 +2660,6 @@ esxVI_LookupCurrentSnapshotTree
esxVI_VirtualMachineSnapshotTree_Free(&rootSnapshotTreeList);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
@@ -2715,7 +2670,7 @@ esxVI_HandleVirtualMachineQuestion
esxVI_VirtualMachineQuestionInfo *questionInfo,
esxVI_Boolean autoAnswer)
{
- int result = 0;
+ int result = -1;
esxVI_ElementDescription *elementDescription = NULL;
virBuffer buffer = VIR_BUFFER_INITIALIZER;
esxVI_ElementDescription *answerChoice = NULL;
@@ -2743,7 +2698,7 @@ esxVI_HandleVirtualMachineQuestion
if (virBufferError(&buffer)) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
possibleAnswers = virBufferContentAndReset(&buffer);
@@ -2755,14 +2710,14 @@ esxVI_HandleVirtualMachineQuestion
_("Pending question blocks virtual machine execution, "
"question is '%s', no possible answers"),
questionInfo->text);
- goto failure;
+ goto cleanup;
} else if (answerChoice == NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Pending question blocks virtual machine execution, "
"question is '%s', possible answers are %s, but no "
"default answer is specified"), questionInfo->text,
possibleAnswers);
- goto failure;
+ goto cleanup;
}
VIR_INFO("Pending question blocks virtual machine execution, "
@@ -2772,7 +2727,7 @@ esxVI_HandleVirtualMachineQuestion
if (esxVI_AnswerVM(ctx, virtualMachine, questionInfo->id,
answerChoice->key) < 0) {
- goto failure;
+ goto cleanup;
}
} else {
if (possibleAnswers != NULL) {
@@ -2787,20 +2742,19 @@ esxVI_HandleVirtualMachineQuestion
questionInfo->text);
}
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
+ if (result < 0) {
+ virBufferFreeAndReset(&buffer);
+ }
+
VIR_FREE(possibleAnswers);
return result;
-
- failure:
- virBufferFreeAndReset(&buffer);
-
- result = -1;
-
- goto cleanup;
}
@@ -2812,7 +2766,7 @@ esxVI_WaitForTaskCompletion(esxVI_Context *ctx,
esxVI_Boolean autoAnswer,
esxVI_TaskInfoState *finalState)
{
- int result = 0;
+ int result = -1;
esxVI_ObjectSpec *objectSpec = NULL;
esxVI_PropertySpec *propertySpec = NULL;
esxVI_PropertyFilterSpec *propertyFilterSpec = NULL;
@@ -2830,18 +2784,18 @@ esxVI_WaitForTaskCompletion(esxVI_Context *ctx,
if (version == NULL) {
virReportOOMError();
- goto failure;
+ return -1;
}
if (esxVI_ObjectSpec_Alloc(&objectSpec) < 0) {
- goto failure;
+ goto cleanup;
}
objectSpec->obj = task;
objectSpec->skip = esxVI_Boolean_False;
if (esxVI_PropertySpec_Alloc(&propertySpec) < 0) {
- goto failure;
+ goto cleanup;
}
propertySpec->type = task->type;
@@ -2855,7 +2809,7 @@ esxVI_WaitForTaskCompletion(esxVI_Context *ctx,
objectSpec) < 0 ||
esxVI_CreateFilter(ctx, propertyFilterSpec, esxVI_Boolean_True,
&propertyFilter) < 0) {
- goto failure;
+ goto cleanup;
}
while (state != esxVI_TaskInfoState_Success &&
@@ -2871,7 +2825,7 @@ esxVI_WaitForTaskCompletion(esxVI_Context *ctx,
* don't overwrite the actual error
*/
if (esxVI_LookupTaskInfoByTask(ctx, task, &taskInfo)) {
- goto failure;
+ goto cleanup;
}
if (taskInfo->cancelable == esxVI_Boolean_True) {
@@ -2887,12 +2841,12 @@ esxVI_WaitForTaskCompletion(esxVI_Context *ctx,
/* FIXME: Enable error reporting here again */
- goto failure;
+ goto cleanup;
}
}
if (esxVI_WaitForUpdates(ctx, version, &updateSet) < 0) {
- goto failure;
+ goto cleanup;
}
VIR_FREE(version);
@@ -2900,7 +2854,7 @@ esxVI_WaitForTaskCompletion(esxVI_Context *ctx,
if (version == NULL) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
if (updateSet->filterSet == NULL) {
@@ -2932,7 +2886,7 @@ esxVI_WaitForTaskCompletion(esxVI_Context *ctx,
}
if (esxVI_TaskInfoState_CastFromAnyType(propertyValue, &state) < 0) {
- goto failure;
+ goto cleanup;
}
}
@@ -2941,9 +2895,11 @@ esxVI_WaitForTaskCompletion(esxVI_Context *ctx,
}
if (esxVI_TaskInfoState_CastFromAnyType(propertyValue, finalState) < 0) {
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
/*
* Remove values given by the caller from the data structures to prevent
@@ -2964,11 +2920,6 @@ esxVI_WaitForTaskCompletion(esxVI_Context *ctx,
esxVI_TaskInfo_Free(&taskInfo);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
@@ -2994,7 +2945,7 @@ esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedHostCpuIdInfo,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("HostCpuIdInfo register '%s' has an unexpected length"),
name[r]);
- goto failure;
+ return -1;
}
/* Strip the ':' and invert the "bit" order from 31..0 to 0..31 */
@@ -3008,15 +2959,10 @@ esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedHostCpuIdInfo,
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("HostCpuIdInfo register '%s' has an unexpected format"),
name[r]);
- goto failure;
+ return -1;
}
}
}
return 0;
-
- failure:
- memset(parsedHostCpuIdInfo, 0, sizeof (*parsedHostCpuIdInfo));
-
- return -1;
}
diff --git a/src/esx/esx_vi_methods.c b/src/esx/esx_vi_methods.c
index 8f841e3..56d2e58 100644
--- a/src/esx/esx_vi_methods.c
+++ b/src/esx/esx_vi_methods.c
@@ -74,14 +74,14 @@
#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__RequiredItem(_type) \
if (esxVI_##_type##_Deserialize(response->node, output) < 0) { \
- goto failure; \
+ goto cleanup; \
}
#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__RequiredList(_type) \
if (esxVI_##_type##_DeserializeList(response->node, output) < 0) { \
- goto failure; \
+ goto cleanup; \
}
@@ -89,7 +89,7 @@
#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__OptionalItem(_type) \
if (response->node != NULL && \
esxVI_##_type##_Deserialize(response->node, output) < 0) { \
- goto failure; \
+ goto cleanup; \
}
@@ -97,7 +97,7 @@
#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__OptionalList(_type) \
if (response->node != NULL && \
esxVI_##_type##_DeserializeList(response->node, output) < 0) { \
- goto failure; \
+ goto cleanup; \
}
@@ -107,7 +107,7 @@
int \
esxVI_##_name _parameters \
{ \
- int result = 0; \
+ int result = -1; \
const char *methodName = #_name; \
virBuffer buffer = VIR_BUFFER_INITIALIZER; \
char *request = NULL; \
@@ -129,30 +129,29 @@
\
if (virBufferError(&buffer)) { \
virReportOOMError(); \
- goto failure; \
+ goto cleanup; \
} \
\
request = virBufferContentAndReset(&buffer); \
\
if (esxVI_Context_Execute(ctx, methodName, request, &response, \
esxVI_Occurrence_##_occurrence) < 0) { \
- goto failure; \
+ goto cleanup; \
} \
\
ESX_VI__METHOD__DESERIALIZE_OUTPUT__##_occurrence(_output_type) \
\
+ result = 0; \
+ \
cleanup: \
+ if (result < 0) { \
+ virBufferFreeAndReset(&buffer); \
+ } \
+ \
VIR_FREE(request); \
esxVI_Response_Free(&response); \
\
return result; \
- \
- failure: \
- virBufferFreeAndReset(&buffer); \
- \
- result = -1; \
- \
- goto cleanup; \
}
@@ -216,21 +215,21 @@
#define ESX_VI__METHOD__PARAMETER__SERIALIZE(_type, _name) \
if (esxVI_##_type##_Serialize(_name, #_name, &buffer) < 0) { \
- goto failure; \
+ goto cleanup; \
}
#define ESX_VI__METHOD__PARAMETER__SERIALIZE_LIST(_type, _name) \
if (esxVI_##_type##_SerializeList(_name, #_name, &buffer) < 0) { \
- goto failure; \
+ goto cleanup; \
}
#define ESX_VI__METHOD__PARAMETER__SERIALIZE_VALUE(_type, _name) \
if (esxVI_##_type##_SerializeValue(_name, #_name, &buffer) < 0) { \
- goto failure; \
+ goto cleanup; \
}
@@ -243,7 +242,7 @@ int
esxVI_RetrieveServiceContent(esxVI_Context *ctx,
esxVI_ServiceContent **serviceContent)
{
- int result = 0;
+ int result = -1;
const char *request = ESX_VI__SOAP__REQUEST_HEADER
"<RetrieveServiceContent xmlns=\"urn:vim25\">"
"<_this xmlns=\"urn:vim25\" "
@@ -263,18 +262,15 @@ esxVI_RetrieveServiceContent(esxVI_Context *ctx,
if (esxVI_Context_Execute(ctx, "RetrieveServiceContent", request,
&response, esxVI_Occurrence_RequiredItem) < 0 ||
esxVI_ServiceContent_Deserialize(response->node, serviceContent) < 0) {
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
esxVI_Response_Free(&response);
return result;
-
- failure:
- result = -1;
-
- goto cleanup;
}
diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c
index 8334efd..3f34fee 100644
--- a/src/esx/esx_vi_types.c
+++ b/src/esx/esx_vi_types.c
@@ -297,7 +297,7 @@
int \
esxVI_##_type##_Deserialize(xmlNodePtr node, esxVI_##_type **number) \
{ \
- int result = 0; \
+ int result = -1; \
char *string; \
long long value; \
\
@@ -317,35 +317,34 @@
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \
"XML node doesn't contain text, expecting an " \
_xsdType" value"); \
- goto failure; \
+ goto cleanup; \
} \
\
if (virStrToLong_ll(string, NULL, 10, &value) < 0) { \
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \
"Unknown value '%s' for "_xsdType, string); \
- goto failure; \
+ goto cleanup; \
} \
\
if (value < (_min) || value > (_max)) { \
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \
"Value '%s' is not representable as "_xsdType, \
(const char *)string); \
- goto failure; \
+ goto cleanup; \
} \
\
(*number)->value = value; \
\
+ result = 0; \
+ \
cleanup: \
+ if (result < 0) { \
+ esxVI_##_type##_Free(number); \
+ } \
+ \
VIR_FREE(string); \
\
return result; \
- \
- failure: \
- esxVI_##_type##_Free(number); \
- \
- result = -1; \
- \
- goto cleanup; \
}
@@ -930,7 +929,7 @@ esxVI_String_AppendValueToList(esxVI_String **stringList, const char *value)
esxVI_String *string = NULL;
if (esxVI_String_Alloc(&string) < 0) {
- goto failure;
+ return -1;
}
string->value = strdup(value);
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index 142f2f7..c09989b 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -590,6 +590,7 @@ char *
esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
const char *absolutePath)
{
+ bool success = false;
char *copyOfAbsolutePath = NULL;
char *tmp = NULL;
char *saveptr = NULL;
@@ -601,7 +602,7 @@ esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
const char *datastoreName = NULL;
if (esxVI_String_DeepCopyValue(©OfAbsolutePath, absolutePath) < 0) {
- goto failure;
+ return NULL;
}
/* Expected format: '/vmfs/volumes/<datastore>/<path>' */
@@ -611,14 +612,14 @@ esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Absolute path '%s' doesn't have expected format "
"'/vmfs/volumes/<datastore>/<path>'"), absolutePath);
- goto failure;
+ goto cleanup;
}
if (ctx != NULL) {
if (esxVI_LookupDatastoreByName(ctx, preliminaryDatastoreName,
NULL, &datastore,
esxVI_Occurrence_OptionalItem) < 0) {
- goto failure;
+ goto cleanup;
}
if (datastore != NULL) {
@@ -629,7 +630,7 @@ esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
} else if (STREQ(dynamicProperty->name, "summary.name")) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_String) < 0) {
- goto failure;
+ goto cleanup;
}
datastoreName = dynamicProperty->val->string;
@@ -656,21 +657,22 @@ esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
if (virAsprintf(&datastoreRelatedPath, "[%s] %s", datastoreName,
directoryAndFileName) < 0) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
/* FIXME: Check if referenced path/file really exists */
+ success = true;
+
cleanup:
+ if (! success) {
+ VIR_FREE(datastoreRelatedPath);
+ }
+
VIR_FREE(copyOfAbsolutePath);
esxVI_ObjectContent_Free(&datastore);
return datastoreRelatedPath;
-
- failure:
- VIR_FREE(datastoreRelatedPath);
-
- goto cleanup;
}
@@ -727,6 +729,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
const char *datastoreName, const char *directoryName,
esxVI_ProductVersion productVersion)
{
+ bool success = false;
virConfPtr conf = NULL;
virDomainDefPtr def = NULL;
long long config_version = 0;
@@ -750,7 +753,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
- goto failure;
+ return NULL;
}
def->virtType = VIR_DOMAIN_VIRT_VMWARE; /* FIXME: maybe add VIR_DOMAIN_VIRT_ESX ? */
@@ -759,20 +762,20 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
/* vmx:config.version */
if (esxUtil_GetConfigLong(conf, "config.version", &config_version, 0,
0) < 0) {
- goto failure;
+ goto cleanup;
}
if (config_version != 8) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VMX entry 'config.version' to be 8 but found "
"%lld"), config_version);
- goto failure;
+ goto cleanup;
}
/* vmx:virtualHW.version */
if (esxUtil_GetConfigLong(conf, "virtualHW.version", &virtualHW_version, 0,
0) < 0) {
- goto failure;
+ goto cleanup;
}
/*
@@ -790,7 +793,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
_("Expecting VMX entry 'virtualHW.version' to be 4 "
"but found %lld"),
virtualHW_version);
- goto failure;
+ goto cleanup;
}
break;
@@ -802,7 +805,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
_("Expecting VMX entry 'virtualHW.version' to be 4 or 7 "
"but found %lld"),
virtualHW_version);
- goto failure;
+ goto cleanup;
}
break;
@@ -810,37 +813,37 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
default:
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unexpected product version"));
- goto failure;
+ goto cleanup;
}
/* vmx:uuid.bios -> def:uuid */
/* FIXME: Need to handle 'uuid.action = "create"' */
if (esxUtil_GetConfigUUID(conf, "uuid.bios", def->uuid, 1) < 0) {
- goto failure;
+ goto cleanup;
}
/* vmx:displayName -> def:name */
if (esxUtil_GetConfigString(conf, "displayName", &def->name, 1) < 0) {
- goto failure;
+ goto cleanup;
}
/* vmx:memsize -> def:maxmem */
if (esxUtil_GetConfigLong(conf, "memsize", &memsize, 32, 1) < 0) {
- goto failure;
+ goto cleanup;
}
if (memsize <= 0 || memsize % 4 != 0) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VMX entry 'memsize' to be an unsigned "
"integer (multiple of 4) but found %lld"), memsize);
- goto failure;
+ goto cleanup;
}
def->maxmem = memsize * 1024; /* Scale from megabytes to kilobytes */
/* vmx:sched.mem.max -> def:memory */
if (esxUtil_GetConfigLong(conf, "sched.mem.max", &memory, memsize, 1) < 0) {
- goto failure;
+ goto cleanup;
}
if (memory < 0) {
@@ -855,14 +858,14 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
/* vmx:numvcpus -> def:vcpus */
if (esxUtil_GetConfigLong(conf, "numvcpus", &numvcpus, 1, 1) < 0) {
- goto failure;
+ goto cleanup;
}
if (numvcpus <= 0 || (numvcpus % 2 != 0 && numvcpus != 1)) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VMX entry 'numvcpus' to be an unsigned "
"integer (1 or a multiple of 2) but found %lld"), numvcpus);
- goto failure;
+ goto cleanup;
}
def->vcpus = numvcpus;
@@ -871,7 +874,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
// VirtualMachine:config.cpuAffinity.affinitySet
if (esxUtil_GetConfigString(conf, "sched.cpu.affinity", &sched_cpu_affinity,
1) < 0) {
- goto failure;
+ goto cleanup;
}
if (sched_cpu_affinity != NULL && STRNEQ(sched_cpu_affinity, "all")) {
@@ -882,7 +885,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
if (VIR_ALLOC_N(def->cpumask, VIR_DOMAIN_CPUMASK_LEN) < 0) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
while (*current != '\0') {
@@ -895,14 +898,14 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
_("Expecting VMX entry 'sched.cpu.affinity' to be "
"a comma separated list of unsigned integers but "
"found '%s'"), sched_cpu_affinity);
- goto failure;
+ goto cleanup;
}
if (number >= VIR_DOMAIN_CPUMASK_LEN) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("VMX entry 'sched.cpu.affinity' contains a %d, "
"this value is too large"), number);
- goto failure;
+ goto cleanup;
}
if (number + 1 > def->cpumasklen) {
@@ -923,7 +926,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
_("Expecting VMX entry 'sched.cpu.affinity' to be "
"a comma separated list of unsigned integers but "
"found '%s'"), sched_cpu_affinity);
- goto failure;
+ goto cleanup;
}
virSkipSpaces(¤t);
@@ -934,7 +937,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
_("Expecting VMX entry 'sched.cpu.affinity' to contain "
"at least as many values as 'numvcpus' (%lld) but "
"found only %d value(s)"), numvcpus, count);
- goto failure;
+ goto cleanup;
}
}
@@ -948,12 +951,12 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
if (def->os.type == NULL) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
/* vmx:guestOS -> def:os.arch */
if (esxUtil_GetConfigString(conf, "guestOS", &guestOS, 1) < 0) {
- goto failure;
+ goto cleanup;
}
if (guestOS != NULL && virFileHasSuffix(guestOS, "-64")) {
@@ -964,7 +967,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
if (def->os.arch == NULL) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
/*
@@ -977,13 +980,13 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
/* def:graphics */
if (VIR_ALLOC_N(def->graphics, 1) < 0) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
def->ngraphics = 0;
if (esxVMX_ParseVNC(conf, &def->graphics[def->ngraphics]) < 0) {
- goto failure;
+ goto cleanup;
}
if (def->graphics[def->ngraphics] != NULL) {
@@ -993,7 +996,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
/* def:disks: 4 * 15 scsi + 2 * 2 ide + 2 floppy = 66 */
if (VIR_ALLOC_N(def->disks, 66) < 0) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
def->ndisks = 0;
@@ -1004,7 +1007,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
if (esxVMX_ParseSCSIController(conf, controller, &present,
&scsi_virtualDev) < 0) {
- goto failure;
+ goto cleanup;
}
if (! present) {
@@ -1024,7 +1027,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
VIR_DOMAIN_DISK_BUS_SCSI, controller, id,
scsi_virtualDev, datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
- goto failure;
+ goto cleanup;
}
if (def->disks[def->ndisks] != NULL) {
@@ -1036,7 +1039,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
VIR_DOMAIN_DISK_BUS_SCSI, controller, id,
scsi_virtualDev, datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
- goto failure;
+ goto cleanup;
}
if (def->disks[def->ndisks] != NULL) {
@@ -1052,7 +1055,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
VIR_DOMAIN_DISK_BUS_IDE, controller, id,
NULL, datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
- goto failure;
+ goto cleanup;
}
if (def->disks[def->ndisks] != NULL) {
@@ -1064,7 +1067,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
VIR_DOMAIN_DISK_BUS_IDE, controller, id,
NULL, datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
- goto failure;
+ goto cleanup;
}
if (def->disks[def->ndisks] != NULL) {
@@ -1079,7 +1082,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
VIR_DOMAIN_DISK_BUS_FDC, controller, -1, NULL,
datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
- goto failure;
+ goto cleanup;
}
if (def->disks[def->ndisks] != NULL) {
@@ -1093,7 +1096,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
/* def:nets */
if (VIR_ALLOC_N(def->nets, 4) < 0) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
def->nnets = 0;
@@ -1101,7 +1104,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
for (controller = 0; controller < 4; ++controller) {
if (esxVMX_ParseEthernet(conf, controller,
&def->nets[def->nnets]) < 0) {
- goto failure;
+ goto cleanup;
}
if (def->nets[def->nnets] != NULL) {
@@ -1121,7 +1124,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
/* def:serials */
if (VIR_ALLOC_N(def->serials, 4) < 0) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
def->nserials = 0;
@@ -1130,7 +1133,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
if (esxVMX_ParseSerial(ctx, conf, port, datastoreName,
directoryName,
&def->serials[def->nserials]) < 0) {
- goto failure;
+ goto cleanup;
}
if (def->serials[def->nserials] != NULL) {
@@ -1141,7 +1144,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
/* def:parallels */
if (VIR_ALLOC_N(def->parallels, 3) < 0) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
def->nparallels = 0;
@@ -1150,7 +1153,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
if (esxVMX_ParseParallel(ctx, conf, port, datastoreName,
directoryName,
&def->parallels[def->nparallels]) < 0) {
- goto failure;
+ goto cleanup;
}
if (def->parallels[def->nparallels] != NULL) {
@@ -1158,19 +1161,20 @@ esxVMX_ParseConfig(esxVI_Context *ctx, const char *vmx,
}
}
+ success = true;
+
cleanup:
+ if (! success) {
+ virDomainDefFree(def);
+ def = NULL;
+ }
+
virConfFree(conf);
VIR_FREE(sched_cpu_affinity);
VIR_FREE(guestOS);
VIR_FREE(scsi_virtualDev);
return def;
-
- failure:
- virDomainDefFree(def);
- def = NULL;
-
- goto cleanup;
}
@@ -1335,7 +1339,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
* virtualDev = NULL
*/
- int result = 0;
+ int result = -1;
char *prefix = NULL;
char present_name[32] = "";
@@ -1366,7 +1370,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
if (VIR_ALLOC(*def) < 0) {
virReportOOMError();
- goto failure;
+ return -1;
}
(*def)->device = device;
@@ -1380,18 +1384,18 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("SCSI controller index %d out of [0..3] range"),
controller);
- goto failure;
+ goto cleanup;
}
if (id < 0 || id > 15 || id == 7) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("SCSI ID %d out of [0..6,8..15] range"), id);
- goto failure;
+ goto cleanup;
}
if (virAsprintf(&prefix, "scsi%d:%d", controller, id) < 0) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
(*def)->dst =
@@ -1399,7 +1403,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
(controller * 15 + (id < 7 ? id : id - 1), "sd");
if ((*def)->dst == NULL) {
- goto failure;
+ goto cleanup;
}
if (virtualDev != NULL) {
@@ -1407,7 +1411,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
if ((*def)->driverName == NULL) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
}
} else if (bus == VIR_DOMAIN_DISK_BUS_IDE) {
@@ -1415,31 +1419,31 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("IDE controller index %d out of [0..1] range"),
controller);
- goto failure;
+ goto cleanup;
}
if (id < 0 || id > 1) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("IDE ID %d out of [0..1] range"), id);
- goto failure;
+ goto cleanup;
}
if (virAsprintf(&prefix, "ide%d:%d", controller, id) < 0) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
(*def)->dst = virIndexToDiskName(controller * 2 + id, "hd");
if ((*def)->dst == NULL) {
- goto failure;
+ goto cleanup;
}
} else {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Unsupported bus type '%s' for device type '%s'"),
virDomainDiskBusTypeToString(bus),
virDomainDiskDeviceTypeToString(device));
- goto failure;
+ goto cleanup;
}
} else if (device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
if (bus == VIR_DOMAIN_DISK_BUS_FDC) {
@@ -1447,31 +1451,31 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Floppy controller index %d out of [0..1] range"),
controller);
- goto failure;
+ goto cleanup;
}
if (virAsprintf(&prefix, "floppy%d", controller) < 0) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
(*def)->dst = virIndexToDiskName(controller, "fd");
if ((*def)->dst == NULL) {
- goto failure;
+ goto cleanup;
}
} else {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Unsupported bus type '%s' for device type '%s'"),
virDomainDiskBusTypeToString(bus),
virDomainDiskDeviceTypeToString(device));
- goto failure;
+ goto cleanup;
}
} else {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Unsupported device type '%s'"),
virDomainDiskDeviceTypeToString(device));
- goto failure;
+ goto cleanup;
}
ESX_BUILD_VMX_NAME(present);
@@ -1484,13 +1488,13 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
/* vmx:present */
if (esxUtil_GetConfigBoolean(conf, present_name, &present, 0, 1) < 0) {
- goto failure;
+ goto cleanup;
}
/* vmx:startConnected */
if (esxUtil_GetConfigBoolean(conf, startConnected_name, &startConnected,
1, 1) < 0) {
- goto failure;
+ goto cleanup;
}
/* FIXME: Need to distiguish between active and inactive domains here */
@@ -1500,13 +1504,13 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
/* vmx:deviceType -> def:type */
if (esxUtil_GetConfigString(conf, deviceType_name, &deviceType, 1) < 0) {
- goto failure;
+ goto cleanup;
}
/* vmx:clientDevice */
if (esxUtil_GetConfigBoolean(conf, clientDevice_name, &clientDevice, 0,
1) < 0) {
- goto failure;
+ goto cleanup;
}
if (clientDevice) {
@@ -1519,18 +1523,18 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
/* vmx:fileType -> def:type */
if (esxUtil_GetConfigString(conf, fileType_name, &fileType, 1) < 0) {
- goto failure;
+ goto cleanup;
}
/* vmx:fileName -> def:src, def:type */
if (esxUtil_GetConfigString(conf, fileName_name, &fileName, 0) < 0) {
- goto failure;
+ goto cleanup;
}
/* vmx:writeThrough -> def:cachemode */
if (esxUtil_GetConfigBoolean(conf, writeThrough_name, &writeThrough, 0,
1) < 0) {
- goto failure;
+ goto cleanup;
}
/* Setup virDomainDiskDef */
@@ -1542,13 +1546,13 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VMX entry '%s' to be 'scsi-hardDisk' "
"but found '%s'"), deviceType_name, deviceType);
- goto failure;
+ goto cleanup;
} else if (bus == VIR_DOMAIN_DISK_BUS_IDE &&
STRCASENEQ(deviceType, "ata-hardDisk")) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VMX entry '%s' to be 'ata-hardDisk' "
"but found '%s'"), deviceType_name, deviceType);
- goto failure;
+ goto cleanup;
}
}
@@ -1569,7 +1573,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
: VIR_DOMAIN_DISK_CACHE_DEFAULT;
if ((*def)->src == NULL) {
- goto failure;
+ goto cleanup;
}
} else if (virFileHasSuffix(fileName, ".iso") ||
STREQ(deviceType, "atapi-cdrom")) {
@@ -1584,7 +1588,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Invalid or not yet handled value '%s' for VMX entry "
"'%s'"), fileName, fileName_name);
- goto failure;
+ goto cleanup;
}
} else if (device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
if (virFileHasSuffix(fileName, ".iso")) {
@@ -1593,7 +1597,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VMX entry '%s' to be 'cdrom-image' "
"but found '%s'"), deviceType_name, deviceType);
- goto failure;
+ goto cleanup;
}
}
@@ -1602,7 +1606,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
directoryName);
if ((*def)->src == NULL) {
- goto failure;
+ goto cleanup;
}
} else if (virFileHasSuffix(fileName, ".vmdk")) {
/*
@@ -1621,7 +1625,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Invalid or not yet handled value '%s' for VMX entry "
"'%s'"), fileName, fileName_name);
- goto failure;
+ goto cleanup;
}
} else if (device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
if (virFileHasSuffix(fileName, ".flp")) {
@@ -1630,7 +1634,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VMX entry '%s' to be 'file' but "
"found '%s'"), fileType_name, fileType);
- goto failure;
+ goto cleanup;
}
}
@@ -1639,7 +1643,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
directoryName);
if ((*def)->src == NULL) {
- goto failure;
+ goto cleanup;
}
} else if (fileType != NULL && STREQ(fileType, "device")) {
(*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
@@ -1650,14 +1654,16 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Invalid or not yet handled value '%s' for VMX entry "
"'%s'"), fileName, fileName_name);
- goto failure;
+ goto cleanup;
}
} else {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, _("Unsupported device type '%s'"),
virDomainDiskDeviceTypeToString(device));
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
VIR_FREE(prefix);
VIR_FREE(deviceType);
@@ -1666,13 +1672,12 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
return result;
- failure:
- result = -1;
-
ignore:
virDomainDiskDefFree(*def);
*def = NULL;
+ result = 0;
+
goto cleanup;
}
@@ -1681,7 +1686,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virConfPtr conf, int device, int bus,
int
esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
{
- int result = 0;
+ int result = -1;
char prefix[48] = "";
char present_name[48] = "";
@@ -1728,7 +1733,7 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
if (VIR_ALLOC(*def) < 0) {
virReportOOMError();
- goto failure;
+ return -1;
}
snprintf(prefix, sizeof(prefix), "ethernet%d", controller);
@@ -1746,13 +1751,13 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
/* vmx:present */
if (esxUtil_GetConfigBoolean(conf, present_name, &present, 0, 1) < 0) {
- goto failure;
+ goto cleanup;
}
/* vmx:startConnected */
if (esxUtil_GetConfigBoolean(conf, startConnected_name, &startConnected, 1,
1) < 0) {
- goto failure;
+ goto cleanup;
}
/* FIXME: Need to distiguish between active and inactive domains here */
@@ -1763,7 +1768,7 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
/* vmx:connectionType -> def:type */
if (esxUtil_GetConfigString(conf, connectionType_name, &connectionType,
1) < 0) {
- goto failure;
+ goto cleanup;
}
/* vmx:addressType, vmx:generatedAddress, vmx:address -> def:mac */
@@ -1771,7 +1776,7 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
esxUtil_GetConfigString(conf, generatedAddress_name, &generatedAddress,
1) < 0 ||
esxUtil_GetConfigString(conf, address_name, &address, 1) < 0) {
- goto failure;
+ goto cleanup;
}
if (addressType == NULL || STRCASEEQ(addressType, "generated") ||
@@ -1782,7 +1787,7 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
_("Expecting VMX entry '%s' to be MAC address but "
"found '%s'"), generatedAddress_name,
generatedAddress);
- goto failure;
+ goto cleanup;
}
}
} else if (STRCASEEQ(addressType, "static")) {
@@ -1791,20 +1796,20 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VMX entry '%s' to be MAC address but "
"found '%s'"), address_name, address);
- goto failure;
+ goto cleanup;
}
}
} else {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VMX entry '%s' to be 'generated' or 'static' or "
"'vpx' but found '%s'"), addressType_name, addressType);
- goto failure;
+ goto cleanup;
}
/* vmx:virtualDev, vmx:features -> def:model */
if (esxUtil_GetConfigString(conf, virtualDev_name, &virtualDev, 1) < 0 ||
esxUtil_GetConfigLong(conf, features_name, &features, 0, 1) < 0) {
- goto failure;
+ goto cleanup;
}
if (virtualDev != NULL) {
@@ -1816,7 +1821,7 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
_("Expecting VMX entry '%s' to be 'vlance' or 'vmxnet' or "
"'vmxnet3' or 'e1000' but found '%s'"), virtualDev_name,
virtualDev);
- goto failure;
+ goto cleanup;
}
if (STRCASEEQ(virtualDev, "vmxnet") && features == 15) {
@@ -1826,7 +1831,7 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
if (virtualDev == NULL) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
}
}
@@ -1836,13 +1841,13 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
STRCASEEQ(connectionType, "bridged") ||
STRCASEEQ(connectionType, "custom")) &&
esxUtil_GetConfigString(conf, networkName_name, &networkName, 0) < 0) {
- goto failure;
+ goto cleanup;
}
/* vmx:vnet -> def:data.ifname */
if (connectionType != NULL && STRCASEEQ(connectionType, "custom") &&
esxUtil_GetConfigString(conf, vnet_name, &vnet, 0) < 0) {
- goto failure;
+ goto cleanup;
}
/* Setup virDomainNetDef */
@@ -1858,13 +1863,13 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("No yet handled value '%s' for VMX entry '%s'"),
connectionType, connectionType_name);
- goto failure;
+ goto cleanup;
} else if (STRCASEEQ(connectionType, "nat")) {
/* FIXME */
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("No yet handled value '%s' for VMX entry '%s'"),
connectionType, connectionType_name);
- goto failure;
+ goto cleanup;
} else if (STRCASEEQ(connectionType, "custom")) {
(*def)->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
(*def)->model = virtualDev;
@@ -1878,9 +1883,11 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Invalid value '%s' for VMX entry '%s'"), connectionType,
connectionType_name);
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
VIR_FREE(connectionType);
VIR_FREE(addressType);
@@ -1891,13 +1898,12 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
return result;
- failure:
- result = -1;
-
ignore:
virDomainNetDefFree(*def);
*def = NULL;
+ result = 0;
+
goto cleanup;
}
@@ -1908,7 +1914,7 @@ esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
const char *datastoreName, const char *directoryName,
virDomainChrDefPtr *def)
{
- int result = 0;
+ int result = -1;
char prefix[48] = "";
char present_name[48] = "";
@@ -1936,7 +1942,7 @@ esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
if (VIR_ALLOC(*def) < 0) {
virReportOOMError();
- goto failure;
+ return -1;
}
(*def)->targetType = VIR_DOMAIN_CHR_TARGET_TYPE_SERIAL;
@@ -1950,13 +1956,13 @@ esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
/* vmx:present */
if (esxUtil_GetConfigBoolean(conf, present_name, &present, 0, 1) < 0) {
- goto failure;
+ goto cleanup;
}
/* vmx:startConnected */
if (esxUtil_GetConfigBoolean(conf, startConnected_name, &startConnected, 1,
1) < 0) {
- goto failure;
+ goto cleanup;
}
/* FIXME: Need to distiguish between active and inactive domains here */
@@ -1966,12 +1972,12 @@ esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
/* vmx:fileType -> def:type */
if (esxUtil_GetConfigString(conf, fileType_name, &fileType, 0) < 0) {
- goto failure;
+ goto cleanup;
}
/* vmx:fileName -> def:data.file.path */
if (esxUtil_GetConfigString(conf, fileName_name, &fileName, 0) < 0) {
- goto failure;
+ goto cleanup;
}
/* Setup virDomainChrDef */
@@ -1989,7 +1995,7 @@ esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
directoryName);
if ((*def)->data.file.path == NULL) {
- goto failure;
+ goto cleanup;
}
} else if (STRCASEEQ(fileType, "pipe")) {
/*
@@ -2005,22 +2011,23 @@ esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VMX entry '%s' to be 'device', 'file' or 'pipe' "
"but found '%s'"), fileType_name, fileType);
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
VIR_FREE(fileType);
VIR_FREE(fileName);
return result;
- failure:
- result = -1;
-
ignore:
virDomainChrDefFree(*def);
*def = NULL;
+ result = 0;
+
goto cleanup;
}
@@ -2031,7 +2038,7 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
const char *datastoreName, const char *directoryName,
virDomainChrDefPtr *def)
{
- int result = 0;
+ int result = -1;
char prefix[48] = "";
char present_name[48] = "";
@@ -2059,7 +2066,7 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
if (VIR_ALLOC(*def) < 0) {
virReportOOMError();
- goto failure;
+ return -1;
}
(*def)->targetType = VIR_DOMAIN_CHR_TARGET_TYPE_PARALLEL;
@@ -2073,13 +2080,13 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
/* vmx:present */
if (esxUtil_GetConfigBoolean(conf, present_name, &present, 0, 1) < 0) {
- goto failure;
+ goto cleanup;
}
/* vmx:startConnected */
if (esxUtil_GetConfigBoolean(conf, startConnected_name, &startConnected, 1,
1) < 0) {
- goto failure;
+ goto cleanup;
}
/* FIXME: Need to distiguish between active and inactive domains here */
@@ -2089,12 +2096,12 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
/* vmx:fileType -> def:type */
if (esxUtil_GetConfigString(conf, fileType_name, &fileType, 0) < 0) {
- goto failure;
+ goto cleanup;
}
/* vmx:fileName -> def:data.file.path */
if (esxUtil_GetConfigString(conf, fileName_name, &fileName, 0) < 0) {
- goto failure;
+ goto cleanup;
}
/* Setup virDomainChrDef */
@@ -2112,28 +2119,29 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
directoryName);
if ((*def)->data.file.path == NULL) {
- goto failure;
+ goto cleanup;
}
} else {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VMX entry '%s' to be 'device' or 'file' but "
"found '%s'"), fileType_name, fileType);
- goto failure;
+ goto cleanup;
}
+ result = 0;
+
cleanup:
VIR_FREE(fileType);
VIR_FREE(fileName);
return result;
- failure:
- result = -1;
-
ignore:
virDomainChrDefFree(*def);
*def = NULL;
+ result = 0;
+
goto cleanup;
}
@@ -2146,6 +2154,7 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
char *
esxVMX_FormatFileName(esxVI_Context *ctx ATTRIBUTE_UNUSED, const char *src)
{
+ bool success = false;
char *datastoreName = NULL;
char *directoryName = NULL;
char *fileName = NULL;
@@ -2155,20 +2164,20 @@ esxVMX_FormatFileName(esxVI_Context *ctx ATTRIBUTE_UNUSED, const char *src)
/* Found potential datastore related path */
if (esxUtil_ParseDatastoreRelatedPath(src, &datastoreName,
&directoryName, &fileName) < 0) {
- goto failure;
+ goto cleanup;
}
if (directoryName == NULL) {
if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s",
datastoreName, fileName) < 0) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
} else {
if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s/%s",
datastoreName, directoryName, fileName) < 0) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
}
} else if (STRPREFIX(src, "/")) {
@@ -2177,29 +2186,30 @@ esxVMX_FormatFileName(esxVI_Context *ctx ATTRIBUTE_UNUSED, const char *src)
if (absolutePath == NULL) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
} else {
/* Found relative path, this is not supported */
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Found relative path '%s' in domain XML, this is not "
"supported"), src);
- goto failure;
+ goto cleanup;
}
/* FIXME: Check if referenced path/file really exists */
+ success = true;
+
cleanup:
+ if (! success) {
+ VIR_FREE(absolutePath);
+ }
+
VIR_FREE(datastoreName);
VIR_FREE(directoryName);
VIR_FREE(fileName);
return absolutePath;
-
- failure:
- VIR_FREE(absolutePath);
-
- goto cleanup;
}
--
1.7.0.4
14 years, 7 months