]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: add udp interface support
authorJonathan Toppins <jtoppins@cumulusnetworks.com>
Sat, 29 Aug 2015 20:19:10 +0000 (16:19 -0400)
committerJán Tomko <jtomko@redhat.com>
Wed, 2 Sep 2015 08:17:50 +0000 (10:17 +0200)
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>
18 files changed:
docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
src/conf/netdev_bandwidth_conf.h
src/libxl/libxl_conf.c
src/lxc/lxc_controller.c
src/lxc/lxc_process.c
src/qemu/qemu_command.c
src/qemu/qemu_hotplug.c
src/qemu/qemu_interface.c
src/uml/uml_conf.c
src/xenconfig/xen_sxpr.c
tests/qemuxml2argvdata/qemuxml2argv-net-udp.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-net-udp.xml [new file with mode: 0644]
tests/qemuxml2argvtest.c
tests/qemuxml2xmltest.c
tools/virsh-domain.c

index 5ca8edee8b975187a059eff9048513ee54705581..efa485c3fc6fc78b7d3256c1bd418233c3d190bf 100644 (file)
       &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>
index ccc74cceac31f2bc7f98e427a95cc19f2d3925b1..f1961773c81a8d056425b6fdd67859cb83059a2b 100644 (file)
             <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>
index c5e9653c83f89652594ec7d8fbad7e315b9aef14..69225f47f9e2e99362a380096c28a062941a280f 100644 (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:
index 961e4ed6b47eb0ce4ef79e27181190f7073d8a84..f0435545835ebe05743de896d211532566ee0a71 100644 (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;
index 6cbf4aecb3df9f6970c6c76d86b6e35b8ddbb5bf..cdeac09e64e47705e40fbe8955e0b64ac6a964e3 100644 (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:
index e84575910ac52d50cbe2eb357470a3d6dd79eebc..a76ad5a25b331a00e5a32db61d039f684ed0506a 100644 (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:
index d36bc9b957adc33a99df4a4a144f3ab4c897a9dc..0e6a3e111dd344a57f578c441105280ecee73b6e 100644 (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:
index ade0ed7c0aaca0e8141dfe40ecc07e031b88420f..57e3880d3a86252aeb230820d6dee8c434a17e91 100644 (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:
index abc57d762075e8f918d13f9df59bb030c5f5dab8..2a820af6f573d1bab9fe1111e7a787f2bbd07691 100644 (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:
index e71a204bfd5c902e8c03e912d7fe2d456a383af3..ac683adb36a75a8b8cfdc42d0197672812580a47 100644 (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) {
index 01226ac633155a71c8594f62a0a4a2731e2fd66c..4d55e4dfd7b3364958b299399da4b2db027d785a 100644 (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:
index 90deb2a2443353a8c62942fab015e082f4cc3fcd..afc0375d81aa196033fe952f00a4fd2528c239fc 100644 (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");
index 05e938a60edf0c44e1636988a549094ee961e7d9..1d43ec17a309e7fa93f71a8c019376f7a98b0bdf 100644 (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:
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-udp.args b/tests/qemuxml2argvdata/qemuxml2argv-net-udp.args
new file mode 100644 (file)
index 0000000..daf06c2
--- /dev/null
@@ -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
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-udp.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-udp.xml
new file mode 100644 (file)
index 0000000..c19107d
--- /dev/null
@@ -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>
index c2482e61244852b928487a25aec90153c017a6a9..d4432df270a82635691bf62efd66741c8cf47c1a 100644 (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",
index 5c1c2e9b865670d4a381af0253b2c4316e63a23b..d41954e0a08b9c9205981c01f7d45df69d805cd1 100644 (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);
index 8d2700f56182d887c9c48d86dd24fa55b523d682..b029b6577a308f98388a3808ff72aec2046b134f 100644 (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: