qemu: add udp interface support

Adds a new interface type using UDP sockets, this seems only applicable
to QEMU but have edited tree-wide to support the new interface type.

The interface type required the addition of a "localaddr" (local
address), this then maps into the following xml and qemu call.

<interface type='udp'>
  <mac address='52:54:00:5c:67:56'/>
  <source address='127.0.0.1' port='11112'>
    <local address='127.0.0.1' port='22222'/>
  </source>
  <model type='virtio'/>
  <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</interface>

QEMU call:
	-net socket,udp=127.0.0.1:11112,localaddr=127.0.0.1:22222

Notice the xml "local" entry becomes the "localaddr" for the qemu call.

reference:
http://lists.gnu.org/archive/html/qemu-devel/2011-11/msg00629.html

Signed-off-by: Jonathan Toppins <jtoppins@cumulusnetworks.com>
Signed-off-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Jonathan Toppins 2015-08-29 16:19:10 -04:00 committed by Ján Tomko
parent b3ea3bab3f
commit 5c668a78d8
18 changed files with 187 additions and 6 deletions

View File

@ -4258,6 +4258,30 @@
&lt;source address='192.168.0.1' port='5558'/&gt;
&lt;/interface&gt;
&lt;/devices&gt;
...</pre>
<h5><a name="elementsNICSUDP">UDP unicast tunnel</a></h5>
<p>
A UDP unicast architecture provides a virtual network which enables
connections between QEMU instances using QEMU's UDP infrastructure.
The xml "source" address is the endpoint address to which the UDP socket
packets will be sent from the host running QEMU.
The xml "local" address is the address of the interface from which the
UDP socket packets will originate from the QEMU host.
<span class="since">Since 1.2.20</span></p>
<pre>
...
&lt;devices&gt;
&lt;interface type='udp'&gt;
&lt;mac address='52:54:00:22:c9:42'/&gt;
&lt;source address='127.0.0.1' port='11115'&gt;
&lt;local address='127.0.0.1' port='11116'/&gt;
&lt;/source&gt;
&lt;/interface&gt;
&lt;/devices&gt;
...</pre>
<h5><a name="elementsNICSModel">Setting the NIC model</a></h5>

View File

@ -2179,6 +2179,33 @@
<ref name="interface-options"/>
</interleave>
</group>
<group>
<attribute name="type">
<choice>
<value>udp</value>
</choice>
</attribute>
<interleave>
<element name="source">
<attribute name="address">
<ref name="ipv4Addr"/>
</attribute>
<attribute name="port">
<ref name="PortNumber"/>
</attribute>
<element name="local">
<attribute name="address">
<ref name="ipv4Addr"/>
</attribute>
<attribute name="port">
<ref name="PortNumber"/>
</attribute>
<empty/>
</element>
</element>
<ref name="interface-options"/>
</interleave>
</group>
<group>
<attribute name="type">
<value>server</value>

View File

@ -397,7 +397,8 @@ VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
"bridge",
"internal",
"direct",
"hostdev")
"hostdev",
"udp")
VIR_ENUM_IMPL(virDomainNetBackend, VIR_DOMAIN_NET_BACKEND_TYPE_LAST,
"default",
@ -1645,7 +1646,9 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
VIR_FREE(def->data.socket.address);
VIR_FREE(def->data.socket.localaddr);
break;
case VIR_DOMAIN_NET_TYPE_NETWORK:
@ -8589,6 +8592,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
char *script = NULL;
char *address = NULL;
char *port = NULL;
char *localaddr = NULL;
char *localport = NULL;
char *model = NULL;
char *backend = NULL;
char *txmode = NULL;
@ -8701,10 +8706,18 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
} else if (!address &&
(def->type == VIR_DOMAIN_NET_TYPE_SERVER ||
def->type == VIR_DOMAIN_NET_TYPE_CLIENT ||
def->type == VIR_DOMAIN_NET_TYPE_MCAST) &&
def->type == VIR_DOMAIN_NET_TYPE_MCAST ||
def->type == VIR_DOMAIN_NET_TYPE_UDP) &&
xmlStrEqual(cur->name, BAD_CAST "source")) {
address = virXMLPropString(cur, "address");
port = virXMLPropString(cur, "port");
if (!localaddr && def->type == VIR_DOMAIN_NET_TYPE_UDP) {
xmlNodePtr tmpnode = ctxt->node;
ctxt->node = cur;
localaddr = virXPathString("string(./local/@address)", ctxt);
localport = virXPathString("string(./local/@port)", ctxt);
ctxt->node = tmpnode;
}
} else if (xmlStrEqual(cur->name, BAD_CAST "ip")) {
virDomainNetIpDefPtr ip = NULL;
@ -8942,6 +8955,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
if (port == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("No <source> 'port' attribute "
@ -8957,7 +8971,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
if (address == NULL) {
if (def->type == VIR_DOMAIN_NET_TYPE_CLIENT ||
def->type == VIR_DOMAIN_NET_TYPE_MCAST) {
def->type == VIR_DOMAIN_NET_TYPE_MCAST ||
def->type == VIR_DOMAIN_NET_TYPE_UDP) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("No <source> 'address' attribute "
"specified with socket interface"));
@ -8967,6 +8982,32 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
def->data.socket.address = address;
address = NULL;
}
if (def->type != VIR_DOMAIN_NET_TYPE_UDP)
break;
if (localport == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("No <local> 'port' attribute "
"specified with socket interface"));
goto error;
}
if (virStrToLong_i(localport, NULL, 10, &def->data.socket.localport) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot parse <local> 'port' attribute "
"with socket interface"));
goto error;
}
if (localaddr == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("No <local> 'address' attribute "
"specified with socket interface"));
goto error;
} else {
def->data.socket.localaddr = localaddr;
localaddr = NULL;
}
break;
case VIR_DOMAIN_NET_TYPE_INTERNAL:
@ -9322,6 +9363,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
VIR_FREE(trustGuestRxFilters);
VIR_FREE(ips);
VIR_FREE(vhost_path);
VIR_FREE(localaddr);
VIR_FREE(localport);
virNWFilterHashTableFree(filterparams);
return def;
@ -19959,13 +20002,29 @@ virDomainNetDefFormat(virBufferPtr buf,
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
if (def->data.socket.address) {
virBufferAsprintf(buf, "<source address='%s' port='%d'/>\n",
def->data.socket.address, def->data.socket.port);
virBufferAsprintf(buf, "<source address='%s' port='%d'",
def->data.socket.address,
def->data.socket.port);
} else {
virBufferAsprintf(buf, "<source port='%d'/>\n",
virBufferAsprintf(buf, "<source port='%d'",
def->data.socket.port);
}
if (def->type != VIR_DOMAIN_NET_TYPE_UDP) {
virBufferAddLit(buf, "/>\n");
break;
}
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2);
virBufferAsprintf(buf, "<local address='%s' port='%d'/>\n",
def->data.socket.localaddr,
def->data.socket.localport);
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</source>\n");
break;
case VIR_DOMAIN_NET_TYPE_INTERNAL:

View File

@ -923,6 +923,7 @@ typedef enum {
VIR_DOMAIN_NET_TYPE_INTERNAL,
VIR_DOMAIN_NET_TYPE_DIRECT,
VIR_DOMAIN_NET_TYPE_HOSTDEV,
VIR_DOMAIN_NET_TYPE_UDP,
VIR_DOMAIN_NET_TYPE_LAST
} virDomainNetType;
@ -1025,6 +1026,8 @@ struct _virDomainNetDef {
struct {
char *address;
int port;
char *localaddr;
int localport;
} socket; /* any of NET_CLIENT or NET_SERVER or NET_MCAST */
struct {
char *name;

View File

@ -53,6 +53,7 @@ static inline bool virNetDevSupportBandwidth(virDomainNetType type)
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_LAST:

View File

@ -1177,6 +1177,7 @@ libxlMakeNic(virDomainDefPtr def,
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_DIRECT:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:

View File

@ -385,6 +385,7 @@ static int virLXCControllerGetNICIndexes(virLXCControllerPtr ctrl)
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_DIRECT:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:

View File

@ -566,6 +566,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_LAST:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:

View File

@ -5594,6 +5594,16 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
type_sep = ',';
break;
case VIR_DOMAIN_NET_TYPE_UDP:
virBufferAsprintf(&buf, "socket%cudp=%s:%d,localaddr=%s:%d",
type_sep,
net->data.socket.address,
net->data.socket.port,
net->data.socket.localaddr,
net->data.socket.localport);
type_sep = ',';
break;
case VIR_DOMAIN_NET_TYPE_USER:
default:
virBufferAddLit(&buf, "user");
@ -8667,6 +8677,7 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_LAST:

View File

@ -2402,6 +2402,7 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
if (STRNEQ_NULLABLE(olddev->data.socket.address,
newdev->data.socket.address) ||
olddev->data.socket.port != newdev->data.socket.port) {

View File

@ -100,6 +100,7 @@ qemuInterfaceStartDevice(virDomainNetDefPtr net)
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_LAST:
@ -187,6 +188,7 @@ qemuInterfaceStopDevice(virDomainNetDefPtr net)
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_LAST:

View File

@ -195,6 +195,11 @@ umlBuildCommandLineNet(virConnectPtr conn,
_("TCP client networking type not supported"));
goto error;
case VIR_DOMAIN_NET_TYPE_UDP:
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("UDP networking type not supported"));
goto error;
case VIR_DOMAIN_NET_TYPE_MCAST:
/* ethNNN=tuntap,macaddr,ipaddr,port */
virBufferAddLit(&buf, "mcast");

View File

@ -1962,6 +1962,7 @@ xenFormatSxprNet(virConnectPtr conn,
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_DIRECT:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:

View File

@ -0,0 +1,7 @@
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
/usr/bin/qemu -S -M \
pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \
-no-acpi -boot c -usb -hda /dev/HostVG/QEMUGuest1 \
-net nic,macaddr=52:54:00:8c:b9:05,vlan=0,model=rtl8139 \
-net socket,udp=192.168.10.1:5555,localaddr=192.168.10.1:5556,\
vlan=0 -serial none -parallel none

View File

@ -0,0 +1,34 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu</emulator>
<disk type='block' device='disk'>
<source dev='/dev/HostVG/QEMUGuest1'/>
<target dev='hda' bus='ide'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<controller type='ide' index='0'/>
<controller type='usb' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<interface type='udp'>
<mac address='52:54:00:8c:b9:05'/>
<source address='192.168.10.1' port='5555'>
<local address='192.168.10.1' port='5556'/>
</source>
<model type='rtl8139'/>
</interface>
<memballoon model='virtio'/>
</devices>
</domain>

View File

@ -1029,6 +1029,7 @@ mymain(void)
DO_TEST("net-client", NONE);
DO_TEST("net-server", NONE);
DO_TEST("net-mcast", NONE);
DO_TEST("net-udp", NONE);
DO_TEST("net-hostdev",
QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
DO_TEST("net-hostdev-multidomain",

View File

@ -628,6 +628,7 @@ mymain(void)
DO_TEST("memory-hotplug");
DO_TEST("memory-hotplug-nonuma");
DO_TEST("memory-hotplug-dimm");
DO_TEST("net-udp");
virObjectUnref(driver.caps);
virObjectUnref(driver.xmlopt);

View File

@ -1005,6 +1005,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_LAST: