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'/>
...
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(a)cumulusnetworks.com>
---
since v1:
I expect there will be one more round, thanks for the comments thus far. Wanted
to go a head and send this out since it has been a little to long to get to
this point. Some final issues I am seeing:
* there seems to be some trouble with adding a new UDP type interface to a
running VM. Stanley who is CC'ed and helping me test has more details.
* unittests pass even though qemuxml2argvtest still fails, this appears to be
due to disk-drive-network-gluster failing - analysis looks to be the URI is
incorrect, not enough slashes - cuz more is better ;)
* please verify I have added the schema correctly, was kinda confusing
Code Comments:
[Laine Stump]
* [DONE] change to using "local" as a nested element inside the
"source" element
* [DONE] enhance schema to validate the new formatting of the source and local elements
[Ján Tomko]
* [DONE] implement unit tests in tests/qemuxml2argvtest.c and tests/qemuxml2xmltest.c
* [DONE] increase verbosity and note when the feature was added in formatdomain.html.in
docs/formatdomain.html.in | 24 ++++++++
docs/schemas/domaincommon.rng | 27 +++++++++
src/conf/domain_conf.c | 74 ++++++++++++++++++++++--
src/conf/domain_conf.h | 3 +
src/conf/netdev_bandwidth_conf.h | 1 +
src/libxl/libxl_conf.c | 1 +
src/lxc/lxc_controller.c | 1 +
src/lxc/lxc_process.c | 1 +
src/qemu/qemu_command.c | 12 ++++
src/qemu/qemu_hotplug.c | 1 +
src/qemu/qemu_interface.c | 2 +
src/uml/uml_conf.c | 5 ++
src/xenconfig/xen_sxpr.c | 1 +
tests/qemuxml2argvdata/qemuxml2argv-net-udp.args | 6 ++
tests/qemuxml2argvdata/qemuxml2argv-net-udp.xml | 34 +++++++++++
tests/qemuxml2argvtest.c | 1 +
tests/qemuxml2xmltest.c | 1 +
tools/virsh-domain.c | 1 +
18 files changed, 190 insertions(+), 6 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-udp.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-udp.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 5ca8ede..d307d4d 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -4260,6 +4260,30 @@
</devices>
...</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.19</span></p>
+
+<pre>
+ ...
+ <devices>
+ <interface type='udp'>
+ <mac address='52:54:00:22:c9:42'/>
+ <source address='127.0.0.1' port='11115'>
+ <local address='127.0.0.1' port='11116'/>
+ </source>
+ </interface>
+ </devices>
+ ...</pre>
+
<h5><a name="elementsNICSModel">Setting the NIC
model</a></h5>
<pre>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index ccc74cc..f196177 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2181,6 +2181,33 @@
</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>
</attribute>
<interleave>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c5e9653..70e8b39 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -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:
@@ -19959,13 +20000,34 @@ 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);
+
+ if (def->data.socket.localaddr) {
+ virBufferAsprintf(buf, "<local address='%s'
port='%d'/>\n",
+ def->data.socket.localaddr,
+ def->data.socket.localport);
+ } else {
+ virBufferAsprintf(buf, "<local port='%d'/>",
+ def->data.socket.localport);
+ }
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</source>\n");
break;
case VIR_DOMAIN_NET_TYPE_INTERNAL:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 961e4ed..f043554 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -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;
diff --git a/src/conf/netdev_bandwidth_conf.h b/src/conf/netdev_bandwidth_conf.h
index 6cbf4ae..cdeac09 100644
--- a/src/conf/netdev_bandwidth_conf.h
+++ b/src/conf/netdev_bandwidth_conf.h
@@ -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:
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index e845759..a76ad5a 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -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:
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index d36bc9b..0e6a3e1 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -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:
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index ade0ed7..57e3880 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -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:
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index abc57d7..1210fb2 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5594,6 +5594,17 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
type_sep = ',';
break;
+ case VIR_DOMAIN_NET_TYPE_UDP:
+ virBufferAsprintf(&buf, "socket%cudp=%s:%d%clocaladdr=%s:%d",
+ type_sep,
+ net->data.socket.address,
+ net->data.socket.port,
+ type_sep,
+ net->data.socket.localaddr,
+ net->data.socket.localport);
+ type_sep = ',';
+ break;
+
case VIR_DOMAIN_NET_TYPE_USER:
default:
virBufferAddLit(&buf, "user");
@@ -8667,6 +8678,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:
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index e71a204..ac683ad 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -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) {
diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
index 01226ac..4d55e4d 100644
--- a/src/qemu/qemu_interface.c
+++ b/src/qemu/qemu_interface.c
@@ -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:
diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c
index 90deb2a..afc0375 100644
--- a/src/uml/uml_conf.c
+++ b/src/uml/uml_conf.c
@@ -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");
diff --git a/src/xenconfig/xen_sxpr.c b/src/xenconfig/xen_sxpr.c
index 05e938a..1d43ec1 100644
--- a/src/xenconfig/xen_sxpr.c
+++ b/src/xenconfig/xen_sxpr.c
@@ -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:
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-udp.args
b/tests/qemuxml2argvdata/qemuxml2argv-net-udp.args
new file mode 100644
index 0000000..f8d48a8
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-udp.args
@@ -0,0 +1,6 @@
+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
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-udp.xml
b/tests/qemuxml2argvdata/qemuxml2argv-net-udp.xml
new file mode 100644
index 0000000..c19107d
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-udp.xml
@@ -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>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index c2482e6..d4432df 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -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",
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 5c1c2e9..d41954e 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -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);
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 8d2700f..b029b65 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -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:
--
2.1.4