Since version 4.1 ESX(i) can expose virtual serial devices over TCP.
Add support in the VMX handling code for this, add test cases to cover
it and add links to some documentation.
ESX supports two additional protocols: TELNETS and TLS. Add them to
the list of serial-over-TCP protocols.
---
docs/formatdomain.html.in | 4 +-
src/conf/domain_conf.c | 18 ++-
src/conf/domain_conf.h | 3 +
src/esx/README | 23 ++-
src/esx/esx_vmx.c | 163 ++++++++++++++++++--
.../vmx2xmldata/vmx2xml-serial-network-client.vmx | 6 +
.../vmx2xmldata/vmx2xml-serial-network-client.xml | 25 +++
.../vmx2xmldata/vmx2xml-serial-network-server.vmx | 6 +
.../vmx2xmldata/vmx2xml-serial-network-server.xml | 25 +++
tests/vmx2xmltest.c | 2 +
.../xml2vmxdata/xml2vmx-serial-network-client.vmx | 14 ++
.../xml2vmxdata/xml2vmx-serial-network-client.xml | 15 ++
.../xml2vmxdata/xml2vmx-serial-network-server.vmx | 14 ++
.../xml2vmxdata/xml2vmx-serial-network-server.xml | 15 ++
tests/xml2vmxtest.c | 2 +
15 files changed, 304 insertions(+), 31 deletions(-)
create mode 100644 tests/vmx2xmldata/vmx2xml-serial-network-client.vmx
create mode 100644 tests/vmx2xmldata/vmx2xml-serial-network-client.xml
create mode 100644 tests/vmx2xmldata/vmx2xml-serial-network-server.vmx
create mode 100644 tests/vmx2xmldata/vmx2xml-serial-network-server.xml
create mode 100644 tests/xml2vmxdata/xml2vmx-serial-network-client.vmx
create mode 100644 tests/xml2vmxdata/xml2vmx-serial-network-client.xml
create mode 100644 tests/xml2vmxdata/xml2vmx-serial-network-server.vmx
create mode 100644 tests/xml2vmxdata/xml2vmx-serial-network-server.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 5e56dae..2f64f8d 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1461,7 +1461,9 @@ qemu-kvm -net nic,model=? /dev/null
...</pre>
<p>
- Alternatively you can use telnet instead of raw TCP.
+ Alternatively you can use <code>telnet</code> instead of
<code>raw</code> TCP.
+ <span class="since">Since 0.8.5</span> you can also use
<code>telnets</code>
+ (secure telnet) and <code>tls</code>.
<p>
<pre>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e05d5d7..92aa3d1 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -203,6 +203,12 @@ VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST,
"tcp",
"unix")
+VIR_ENUM_IMPL(virDomainChrTcpProtocol, VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST,
+ "raw",
+ "telnet",
+ "telnets",
+ "tls")
+
VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST,
"sb16",
"es1370",
@@ -2748,12 +2754,10 @@ virDomainChrDefParseXML(virCapsPtr caps,
def->data.tcp.listen = 1;
}
- if (protocol == NULL ||
- STREQ(protocol, "raw"))
+ if (protocol == NULL)
def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW;
- else if (STREQ(protocol, "telnet"))
- def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
- else {
+ else if ((def->data.tcp.protocol =
+ virDomainChrTcpProtocolTypeFromString(protocol)) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("Unknown protocol '%s'"),
protocol);
goto error;
@@ -5848,9 +5852,7 @@ virDomainChrDefFormat(virBufferPtr buf,
def->data.tcp.host,
def->data.tcp.service);
virBufferVSprintf(buf, " <protocol type='%s'/>\n",
- def->data.tcp.protocol ==
- VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET
- ? "telnet" : "raw");
+
virDomainChrTcpProtocolTypeToString(def->data.tcp.protocol));
break;
case VIR_DOMAIN_CHR_TYPE_UNIX:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 7195c04..9bf13d8 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -357,6 +357,8 @@ enum virDomainChrType {
enum virDomainChrTcpProtocol {
VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW,
VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET,
+ VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNETS, /* secure telnet */
+ VIR_DOMAIN_CHR_TCP_PROTOCOL_TLS,
VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST,
};
@@ -1172,6 +1174,7 @@ VIR_ENUM_DECL(virDomainChrDevice)
VIR_ENUM_DECL(virDomainChrChannelTarget)
VIR_ENUM_DECL(virDomainChrConsoleTarget)
VIR_ENUM_DECL(virDomainChr)
+VIR_ENUM_DECL(virDomainChrTcpProtocol)
VIR_ENUM_DECL(virDomainSoundModel)
VIR_ENUM_DECL(virDomainMemballoonModel)
VIR_ENUM_DECL(virDomainWatchdogModel)
diff --git a/src/esx/README b/src/esx/README
index 7254332..9ae93b1 100644
--- a/src/esx/README
+++ b/src/esx/README
@@ -3,13 +3,24 @@ Some links to relevant documentation
====================================
-VI/vSphere API:
http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/
-
http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/
-VMX config:
http://www.sanbarrow.com/vmx.html
-CPUID:
http://www.sandpile.org/ia32/cpuid.htm
-Memory model:
http://www.vmware.com/pdf/esx3_memory.pdf
-
http://www.vmware.com/pdf/usenix_resource_mgmt.pdf
+VI/vSphere API:
+
http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/
+
http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/
+
http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/
+VMX config:
+
http://www.sanbarrow.com/vmx.html
+
+CPUID:
+
http://www.sandpile.org/ia32/cpuid.htm
+
+Memory model:
+
http://www.vmware.com/pdf/esx3_memory.pdf
+
http://www.vmware.com/pdf/usenix_resource_mgmt.pdf
+
+Virtual serial port (network backed):
+
http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/v...
+
http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/vsp41_usingpro...
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index 59eb3b2..bfebc4a 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -379,6 +379,36 @@ def->serials[0]...
??? <=> serial0.yieldOnMsrRead = "true"
# defaults to "false", FIXME: not representable
+## serials: network, server (since vSphere 4.1) ################################
+
+->type = _CHR_TYPE_TCP <=> serial0.fileType = "network"
+
+->data.tcp.host = <host> <=> serial0.fileName =
"<protocol>://<host>:<service>"
+->data.tcp.service = <service>
# e.g. "telnet://0.0.0.0:42001"
+->data.tcp.protocol = <protocol>
+
+->data.tcp.listen = 1 <=> serial0.network.endPoint =
"server" # defaults to "server"
+
+??? <=> serial0.vspc = "foobar"
# defaults to <not present>, FIXME: not representable
+??? <=> serial0.tryNoRxLoss = "false"
# defaults to "false", FIXME: not representable
+??? <=> serial0.yieldOnMsrRead = "true"
# defaults to "false", FIXME: not representable
+
+
+## serials: network, client (since vSphere 4.1) ################################
+
+->type = _CHR_TYPE_TCP <=> serial0.fileType = "network"
+
+->data.tcp.host = <host> <=> serial0.fileName =
"<protocol>://<host>:<service>"
+->data.tcp.service = <service>
# e.g. "telnet://192.168.0.17:42001"
+->data.tcp.protocol = <protocol>
+
+->data.tcp.listen = 0 <=> serial0.network.endPoint =
"client" # defaults to "server"
+
+??? <=> serial0.vspc = "foobar"
# defaults to <not present>, FIXME: not representable
+??? <=> serial0.tryNoRxLoss = "false"
# defaults to "false", FIXME: not representable
+??? <=> serial0.yieldOnMsrRead = "true"
# defaults to "false", FIXME: not representable
+
+
################################################################################
## parallels ###################################################################
@@ -424,8 +454,11 @@ def->parallels[0]...
#define VIR_FROM_THIS VIR_FROM_ESX
+#define ESX_BUILD_VMX_NAME_EXTRA(_suffix, _extra) \
+ snprintf(_suffix##_name, sizeof(_suffix##_name), "%s."_extra, prefix);
+
#define ESX_BUILD_VMX_NAME(_suffix) \
- snprintf(_suffix##_name, sizeof(_suffix##_name), "%s."#_suffix, prefix);
+ ESX_BUILD_VMX_NAME_EXTRA(_suffix, #_suffix)
/* directly map the virDomainControllerModel to esxVMX_SCSIControllerModel,
* this is good enough for now because all virDomainControllerModel values
@@ -2113,6 +2146,11 @@ esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port,
char fileName_name[48] = "";
char *fileName = NULL;
+ char network_endPoint_name[48] = "";
+ char *network_endPoint = NULL;
+
+ xmlURIPtr parsedUri = NULL;
+
if (def == NULL || *def != NULL) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid
argument"));
return -1;
@@ -2137,6 +2175,7 @@ esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port,
ESX_BUILD_VMX_NAME(startConnected);
ESX_BUILD_VMX_NAME(fileType);
ESX_BUILD_VMX_NAME(fileName);
+ ESX_BUILD_VMX_NAME_EXTRA(network_endPoint, "network.endPoint");
/* vmx:present */
if (esxUtil_GetConfigBoolean(conf, present_name, &present, false,
@@ -2165,6 +2204,12 @@ esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port,
goto cleanup;
}
+ /* vmx:network.endPoint -> def:data.tcp.listen */
+ if (esxUtil_GetConfigString(conf, network_endPoint_name, &network_endPoint,
+ true) < 0) {
+ goto cleanup;
+ }
+
/* Setup virDomainChrDef */
if (STRCASEEQ(fileType, "device")) {
(*def)->target.port = port;
@@ -2190,10 +2235,72 @@ esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int
port,
(*def)->data.file.path = fileName;
fileName = NULL;
+ } else if (STRCASEEQ(fileType, "network")) {
+ (*def)->target.port = port;
+ (*def)->type = VIR_DOMAIN_CHR_TYPE_TCP;
+
+ parsedUri = xmlParseURI(fileName);
+
+ if (parsedUri == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (parsedUri->port == 0) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("VMX entry '%s' doesn't contain a port
part"),
+ fileName_name);
+ goto cleanup;
+ }
+
+ (*def)->data.tcp.host = strdup(parsedUri->server);
+
+ if ((*def)->data.tcp.host == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virAsprintf(&(*def)->data.tcp.service, "%d",
parsedUri->port) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* See vSphere API documentation about VirtualSerialPortURIBackingInfo */
+ if (parsedUri->scheme == NULL ||
+ STRCASEEQ(parsedUri->scheme, "tcp") ||
+ STRCASEEQ(parsedUri->scheme, "tcp4") ||
+ STRCASEEQ(parsedUri->scheme, "tcp6")) {
+ (*def)->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW;
+ } else if (STRCASEEQ(parsedUri->scheme, "telnet")) {
+ (*def)->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
+ } else if (STRCASEEQ(parsedUri->scheme, "telnets")) {
+ (*def)->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNETS;
+ } else if (STRCASEEQ(parsedUri->scheme, "ssl") ||
+ STRCASEEQ(parsedUri->scheme, "tcp+ssl") ||
+ STRCASEEQ(parsedUri->scheme, "tcp4+ssl") ||
+ STRCASEEQ(parsedUri->scheme, "tcp6+ssl")) {
+ (*def)->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TLS;
+ } else {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("VMX entry '%s' contains unsupported scheme
'%s'"),
+ fileName_name, parsedUri->scheme);
+ goto cleanup;
+ }
+
+ if (network_endPoint == NULL || STRCASEEQ(network_endPoint, "server"))
{
+ (*def)->data.tcp.listen = 1;
+ } else if (STRCASEEQ(network_endPoint, "client")) {
+ (*def)->data.tcp.listen = 0;
+ } else {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Expecting VMX entry '%s' to be 'server' or
'client' "
+ "but found '%s'"), network_endPoint_name,
network_endPoint);
+ goto cleanup;
+ }
} else {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VMX entry '%s' to be 'device',
'file' or 'pipe' "
- "but found '%s'"), fileType_name, fileType);
+ "or 'network' but found '%s'"),
fileType_name, fileType);
goto cleanup;
}
@@ -2207,6 +2314,8 @@ esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port,
VIR_FREE(fileType);
VIR_FREE(fileName);
+ VIR_FREE(network_endPoint);
+ xmlFreeURI(parsedUri);
return result;
@@ -3069,6 +3178,7 @@ esxVMX_FormatSerial(esxVMX_Context *ctx, virDomainChrDefPtr def,
virBufferPtr buffer)
{
char *fileName = NULL;
+ const char *protocol;
if (def->target.port < 0 || def->target.port > 3) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
@@ -3077,13 +3187,6 @@ esxVMX_FormatSerial(esxVMX_Context *ctx, virDomainChrDefPtr def,
return -1;
}
- if (def->data.file.path == NULL) {
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Expecting domain XML attribute 'path' of entry "
- "'devices/serial/source' to be present"));
- return -1;
- }
-
virBufferVSprintf(buffer, "serial%d.present = \"true\"\n",
def->target.port);
/* def:type -> vmx:fileType and def:data.file.path -> vmx:fileName */
@@ -3124,6 +3227,41 @@ esxVMX_FormatSerial(esxVMX_Context *ctx, virDomainChrDefPtr def,
def->target.port, def->data.file.path);
break;
+ case VIR_DOMAIN_CHR_TYPE_TCP:
+ switch (def->data.tcp.protocol) {
+ case VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW:
+ protocol = "tcp";
+ break;
+
+ case VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET:
+ protocol = "telnet";
+ break;
+
+ case VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNETS:
+ protocol = "telnets";
+ break;
+
+ case VIR_DOMAIN_CHR_TCP_PROTOCOL_TLS:
+ protocol = "ssl";
+ break;
+
+ default:
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Unsupported character device TCP protocol
'%s'"),
+ virDomainChrTcpProtocolTypeToString(def->data.tcp.protocol));
+ return -1;
+ }
+
+ virBufferVSprintf(buffer, "serial%d.fileType =
\"network\"\n",
+ def->target.port);
+ virBufferVSprintf(buffer, "serial%d.fileName =
\"%s://%s:%s\"\n",
+ def->target.port, protocol, def->data.tcp.host,
+ def->data.tcp.service);
+ virBufferVSprintf(buffer, "serial%d.network.endPoint =
\"%s\"\n",
+ def->target.port,
+ def->data.tcp.listen ? "server" :
"client");
+ break;
+
default:
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Unsupported character device type '%s'"),
@@ -3154,13 +3292,6 @@ esxVMX_FormatParallel(esxVMX_Context *ctx, virDomainChrDefPtr def,
return -1;
}
- if (def->data.file.path == NULL) {
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Expecting domain XML attribute 'path' of entry "
- "'devices/parallel/source' to be present"));
- return -1;
- }
-
virBufferVSprintf(buffer, "parallel%d.present = \"true\"\n",
def->target.port);
diff --git a/tests/vmx2xmldata/vmx2xml-serial-network-client.vmx
b/tests/vmx2xmldata/vmx2xml-serial-network-client.vmx
new file mode 100644
index 0000000..18cfc57
--- /dev/null
+++ b/tests/vmx2xmldata/vmx2xml-serial-network-client.vmx
@@ -0,0 +1,6 @@
+config.version = "8"
+virtualHW.version = "4"
+serial0.present = "true"
+serial0.fileType = "network"
+serial0.fileName = "tcp://192.168.0.17:42001"
+serial0.network.endPoint = "client"
diff --git a/tests/vmx2xmldata/vmx2xml-serial-network-client.xml
b/tests/vmx2xmldata/vmx2xml-serial-network-client.xml
new file mode 100644
index 0000000..b0c0715
--- /dev/null
+++ b/tests/vmx2xmldata/vmx2xml-serial-network-client.xml
@@ -0,0 +1,25 @@
+<domain type='vmware'>
+ <uuid>00000000-0000-0000-0000-000000000000</uuid>
+ <memory>32768</memory>
+ <currentMemory>32768</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686'>hvm</type>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <serial type='tcp'>
+ <source mode='connect' host='192.168.0.17'
service='42001'/>
+ <protocol type='raw'/>
+ <target port='0'/>
+ </serial>
+ <console type='tcp'>
+ <source mode='connect' host='192.168.0.17'
service='42001'/>
+ <protocol type='raw'/>
+ <target type='serial' port='0'/>
+ </console>
+ </devices>
+</domain>
diff --git a/tests/vmx2xmldata/vmx2xml-serial-network-server.vmx
b/tests/vmx2xmldata/vmx2xml-serial-network-server.vmx
new file mode 100644
index 0000000..d4a9c41
--- /dev/null
+++ b/tests/vmx2xmldata/vmx2xml-serial-network-server.vmx
@@ -0,0 +1,6 @@
+config.version = "8"
+virtualHW.version = "4"
+serial0.present = "true"
+serial0.fileType = "network"
+serial0.fileName = "telnets://0.0.0.0:42001"
+serial0.network.endPoint = "server"
diff --git a/tests/vmx2xmldata/vmx2xml-serial-network-server.xml
b/tests/vmx2xmldata/vmx2xml-serial-network-server.xml
new file mode 100644
index 0000000..e151017
--- /dev/null
+++ b/tests/vmx2xmldata/vmx2xml-serial-network-server.xml
@@ -0,0 +1,25 @@
+<domain type='vmware'>
+ <uuid>00000000-0000-0000-0000-000000000000</uuid>
+ <memory>32768</memory>
+ <currentMemory>32768</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686'>hvm</type>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <serial type='tcp'>
+ <source mode='bind' host='0.0.0.0' service='42001'/>
+ <protocol type='telnets'/>
+ <target port='0'/>
+ </serial>
+ <console type='tcp'>
+ <source mode='bind' host='0.0.0.0' service='42001'/>
+ <protocol type='telnets'/>
+ <target type='serial' port='0'/>
+ </console>
+ </devices>
+</domain>
diff --git a/tests/vmx2xmltest.c b/tests/vmx2xmltest.c
index c71f536..2d59297 100644
--- a/tests/vmx2xmltest.c
+++ b/tests/vmx2xmltest.c
@@ -266,6 +266,8 @@ mymain(int argc, char **argv)
DO_TEST("serial-pipe-server-vm", "serial-pipe",
esxVI_ProductVersion_ESX35);
DO_TEST("serial-pipe-client-app", "serial-pipe",
esxVI_ProductVersion_ESX35);
DO_TEST("serial-pipe-server-vm", "serial-pipe",
esxVI_ProductVersion_ESX35);
+ DO_TEST("serial-network-server", "serial-network-server",
esxVI_ProductVersion_ESX41);
+ DO_TEST("serial-network-client", "serial-network-client",
esxVI_ProductVersion_ESX41);
DO_TEST("parallel-file", "parallel-file",
esxVI_ProductVersion_ESX35);
DO_TEST("parallel-device", "parallel-device",
esxVI_ProductVersion_ESX35);
diff --git a/tests/xml2vmxdata/xml2vmx-serial-network-client.vmx
b/tests/xml2vmxdata/xml2vmx-serial-network-client.vmx
new file mode 100644
index 0000000..d10f403
--- /dev/null
+++ b/tests/xml2vmxdata/xml2vmx-serial-network-client.vmx
@@ -0,0 +1,14 @@
+config.version = "8"
+virtualHW.version = "7"
+guestOS = "other"
+uuid.bios = "56 4d 9b ef ac d9 b4 e0-c8 f0 ae a8 b9 10 35 15"
+displayName = "serial-network"
+memsize = "4"
+numvcpus = "1"
+floppy0.present = "false"
+floppy1.present = "false"
+serial0.present = "true"
+serial0.fileType = "network"
+serial0.fileName = "tcp://192.168.0.17:42001"
+serial0.network.endPoint = "client"
+serial0.yieldOnMsrRead = "true"
diff --git a/tests/xml2vmxdata/xml2vmx-serial-network-client.xml
b/tests/xml2vmxdata/xml2vmx-serial-network-client.xml
new file mode 100644
index 0000000..e2a5afe
--- /dev/null
+++ b/tests/xml2vmxdata/xml2vmx-serial-network-client.xml
@@ -0,0 +1,15 @@
+<domain type='vmware'>
+ <name>serial-network</name>
+ <uuid>564d9bef-acd9-b4e0-c8f0-aea8b9103515</uuid>
+ <memory>4096</memory>
+ <os>
+ <type>hvm</type>
+ </os>
+ <devices>
+ <serial type='tcp'>
+ <source mode="connect" host="192.168.0.17"
service="42001"/>
+ <protocol type="raw"/>
+ <target port='0'/>
+ </serial>
+ </devices>
+</domain>
diff --git a/tests/xml2vmxdata/xml2vmx-serial-network-server.vmx
b/tests/xml2vmxdata/xml2vmx-serial-network-server.vmx
new file mode 100644
index 0000000..b5d77f4
--- /dev/null
+++ b/tests/xml2vmxdata/xml2vmx-serial-network-server.vmx
@@ -0,0 +1,14 @@
+config.version = "8"
+virtualHW.version = "7"
+guestOS = "other"
+uuid.bios = "56 4d 9b ef ac d9 b4 e0-c8 f0 ae a8 b9 10 35 15"
+displayName = "serial-network"
+memsize = "4"
+numvcpus = "1"
+floppy0.present = "false"
+floppy1.present = "false"
+serial0.present = "true"
+serial0.fileType = "network"
+serial0.fileName = "ssl://0.0.0.0:42001"
+serial0.network.endPoint = "server"
+serial0.yieldOnMsrRead = "true"
diff --git a/tests/xml2vmxdata/xml2vmx-serial-network-server.xml
b/tests/xml2vmxdata/xml2vmx-serial-network-server.xml
new file mode 100644
index 0000000..a17e2fe
--- /dev/null
+++ b/tests/xml2vmxdata/xml2vmx-serial-network-server.xml
@@ -0,0 +1,15 @@
+<domain type='vmware'>
+ <name>serial-network</name>
+ <uuid>564d9bef-acd9-b4e0-c8f0-aea8b9103515</uuid>
+ <memory>4096</memory>
+ <os>
+ <type>hvm</type>
+ </os>
+ <devices>
+ <serial type='tcp'>
+ <source mode="bind" host="0.0.0.0"
service="42001"/>
+ <protocol type="tls"/>
+ <target port='0'/>
+ </serial>
+ </devices>
+</domain>
diff --git a/tests/xml2vmxtest.c b/tests/xml2vmxtest.c
index 2a457b4..0881ae9 100644
--- a/tests/xml2vmxtest.c
+++ b/tests/xml2vmxtest.c
@@ -259,6 +259,8 @@ mymain(int argc, char **argv)
DO_TEST("serial-file", "serial-file",
esxVI_ProductVersion_ESX35);
DO_TEST("serial-device", "serial-device",
esxVI_ProductVersion_ESX35);
DO_TEST("serial-pipe", "serial-pipe",
esxVI_ProductVersion_ESX35);
+ DO_TEST("serial-network-server", "serial-network-server",
esxVI_ProductVersion_ESX41);
+ DO_TEST("serial-network-client", "serial-network-client",
esxVI_ProductVersion_ESX41);
DO_TEST("parallel-file", "parallel-file",
esxVI_ProductVersion_ESX35);
DO_TEST("parallel-device", "parallel-device",
esxVI_ProductVersion_ESX35);
--
1.7.0.4