aboutgitcodebugslistschat
path: root/libvirt/0001-conf-Introduce-support-for-UNIX-domain-socket-as-qem.patch
blob: 386cc4a8e58768294828d0b831084c159f576ba1 (plain) (tree)
1
2
3
4

                                                                                        
                                         
                                     










                                                                              


                                                                   








                                                                       
                                       

                           
                                                                 





























                                                                                 
                                           



                                                       
                           




















                                                                          
                                       

                                   
                      










                                    
                      





























                                             
                       




























                                                            
                                       

                            
                                                               










                                                
                                                                           






                                        
                                                                           







                                                                       
                                                                           






                                                                          
                                                                            


























                                                                             
                                                                           







                                                                              
                                                                           







                                                                      
                                                                           








                                                                                    
                                                                           







                                                                          
                                                               

























                                                                         
                                                             










                                                                        
                                       

                            

                                                 
            
                                          
















                                                                     
                                       

                             
                                                                 





































































                                                                                              
                                       

                             
                                                                 














                                                                                
      
 
From 7afbbab2ccada16c87e1095e85184bb21c028012 Mon Sep 17 00:00:00 2001
Message-Id: <7afbbab2ccada16c87e1095e85184bb21c028012.1619091487.git.sbrivio@redhat.com>
From: Stefano Brivio <sbrivio@redhat.com>
Date: Wed, 21 Apr 2021 19:29:31 +0200
Subject: [PATCH] conf: Introduce support for UNIX domain socket as qemu netdev
 back-end

Since qemu [TODO], named UNIX domain sockets can be used instead of
TCP to establish a virtual network between VMs.

The obvious difference compared with TCP is that we need pass a path
instead of address and port.

Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
---
SPDX-FileCopyrightText: 2020-2021 Red Hat GmbH <sbrivio@redhat.com>
SPDX-License-Identifier: AGPL-3.0-or-later

 docs/formatdomain.rst         | 41 +++++++++++++++++++------
 docs/schemas/domaincommon.rng | 50 +++++++++++++++++++++++-------
 src/conf/domain_conf.c        | 58 +++++++++++++++++++++++++++--------
 src/conf/domain_conf.h        | 13 +++++---
 src/qemu/qemu_command.c       | 46 ++++++++++++++++++---------
 src/qemu/qemu_hotplug.c       |  8 +++--
 6 files changed, 160 insertions(+), 56 deletions(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 1b9b2216111c..87c3c956fa23 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -5010,18 +5010,20 @@ must be from the multicast address block.
    </devices>
    ...
 
-:anchor:`<a id="elementsNICSTCP"/>`
+:anchor:`<a id="elementsNICSStream"/>`
 
-TCP tunnel
-^^^^^^^^^^
+TCP or UNIX domain socket tunnel
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A stream-oriented client/server architecture provides a virtual network. One VM
+provides the server end of the network, all other VMS are configured as clients.
+All network traffic is routed between the VMs via the server. This mode is also
+available to unprivileged users. There is no default DNS or DHCP support and no
+outgoing network access. To provide outgoing network access, one of the VMs
+should have a 2nd NIC which is connected to one of the first 4 network types and
+do the appropriate routing.
 
-A TCP client/server architecture provides a virtual network. One VM provides the
-server end of the network, all other VMS are configured as clients. All network
-traffic is routed between the VMs via the server. This mode is also available to
-unprivileged users. There is no default DNS or DHCP support and no outgoing
-network access. To provide outgoing network access, one of the VMs should have a
-2nd NIC which is connected to one of the first 4 network types and do the
-appropriate routing.
+TCP endpoints can be specified as follows:
 
 ::
 
@@ -5039,6 +5041,25 @@ appropriate routing.
    </devices>
    ...
 
+Named UNIX domain sockets can be specified as follows:
+:since:`Since 7.3.0, qemu`
+
+::
+
+   ...
+   <devices>
+     <interface type='server'>
+       <mac address='52:54:00:22:c9:42'/>
+       <source path='/tmp/qemu.socket'/>
+     </interface>
+     ...
+     <interface type='client'>
+       <mac address='52:54:00:8b:c9:51'/>
+       <source path='/tmp/qemu.socket'/>
+     </interface>
+   </devices>
+   ...
+
 :anchor:`<a id="elementsNICSUDP"/>`
 
 UDP unicast tunnel
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index a2e5c50c1d77..7c0a90ba199b 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3161,10 +3161,7 @@
         </group>
         <group>
           <attribute name="type">
-            <choice>
-              <value>mcast</value>
-              <value>client</value>
-            </choice>
+            <value>mcast</value>
           </attribute>
           <interleave>
             <element name="source">
@@ -3179,6 +3176,30 @@
             <ref name="interface-options"/>
           </interleave>
         </group>
+        <group>
+          <attribute name="type">
+            <value>client</value>
+          </attribute>
+          <interleave>
+            <element name="source">
+              <choice>
+                <group>
+                  <attribute name="address">
+                    <ref name="ipv4Addr"/>
+                  </attribute>
+                  <attribute name="port">
+                    <ref name="PortNumber"/>
+                  </attribute>
+                </group>
+                <attribute name="path">
+                  <ref name="absFilePath"/>
+                </attribute>
+              </choice>
+              <empty/>
+            </element>
+            <ref name="interface-options"/>
+          </interleave>
+        </group>
         <group>
           <attribute name="type">
             <value>udp</value>
@@ -3210,14 +3231,21 @@
           </attribute>
           <interleave>
             <element name="source">
-              <optional>
-                <attribute name="address">
-                  <ref name="ipv4Addr"/>
+              <choice>
+                <group>
+                  <optional>
+                    <attribute name="address">
+                      <ref name="ipv4Addr"/>
+                    </attribute>
+                  </optional>
+                  <attribute name="port">
+                    <ref name="PortNumber"/>
+                  </attribute>
+                </group>
+                <attribute name="path">
+                  <ref name="absFilePath"/>
                 </attribute>
-              </optional>
-              <attribute name="port">
-                <ref name="PortNumber"/>
-              </attribute>
+              </choice>
               <empty/>
             </element>
             <ref name="interface-options"/>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f8a462fb3b99..8c6a5d4f974e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2562,8 +2562,9 @@ virDomainNetDefFree(virDomainNetDef *def)
     case VIR_DOMAIN_NET_TYPE_CLIENT:
     case VIR_DOMAIN_NET_TYPE_MCAST:
     case VIR_DOMAIN_NET_TYPE_UDP:
-        g_free(def->data.socket.address);
-        g_free(def->data.socket.localaddr);
+        g_free(def->data.socket.net.address);
+        g_free(def->data.socket.net.localaddr);
+        g_free(def->data.socket.path);
         break;
 
     case VIR_DOMAIN_NET_TYPE_NETWORK:
@@ -10555,6 +10556,7 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
     g_autofree char *downscript = NULL;
     g_autofree char *address = NULL;
     g_autofree char *port = NULL;
+    g_autofree char *path = NULL;
     g_autofree char *localaddr = NULL;
     g_autofree char *localport = NULL;
     g_autofree char *model = NULL;
@@ -10699,7 +10701,7 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
                                      " <interface type='%s'>"), type);
                     goto error;
                 }
-            } else if (!address &&
+            } else if (!address && !path &&
                        (def->type == VIR_DOMAIN_NET_TYPE_SERVER ||
                         def->type == VIR_DOMAIN_NET_TYPE_CLIENT ||
                         def->type == VIR_DOMAIN_NET_TYPE_MCAST ||
@@ -10707,6 +10709,7 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
                        virXMLNodeNameEqual(cur, "source")) {
                 address = virXMLPropString(cur, "address");
                 port = virXMLPropString(cur, "port");
+                path = virXMLPropString(cur, "path");
                 if (!localaddr && def->type == VIR_DOMAIN_NET_TYPE_UDP) {
                     xmlNodePtr tmpnode = ctxt->node;
                     ctxt->node = cur;
@@ -10950,6 +10953,27 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
 
     case VIR_DOMAIN_NET_TYPE_CLIENT:
     case VIR_DOMAIN_NET_TYPE_SERVER:
+        if (path != NULL) {
+            if (port != NULL || address != NULL ||
+                localport != NULL || localaddr != NULL) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("<source> 'path' attribute "
+                                 "for socket interface cannot be specified "
+                                 "together with other attributes"));
+                goto error;
+            }
+            def->data.socket.path = g_steal_pointer(&path);
+            break;
+        }
+
+        if (port == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Neither <source> 'port' nor 'path' attribute "
+                             "specified with socket interface"));
+            goto error;
+        }
+
+        G_GNUC_FALLTHROUGH;
     case VIR_DOMAIN_NET_TYPE_MCAST:
     case VIR_DOMAIN_NET_TYPE_UDP:
         if (port == NULL) {
@@ -10958,7 +10982,7 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
                              "specified with socket interface"));
             goto error;
         }
-        if (virStrToLong_i(port, NULL, 10, &def->data.socket.port) < 0) {
+        if (virStrToLong_i(port, NULL, 10, &def->data.socket.net.port) < 0) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("Cannot parse <source> 'port' attribute "
                              "with socket interface"));
@@ -10975,7 +10999,7 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
                 goto error;
             }
         } else {
-            def->data.socket.address = g_steal_pointer(&address);
+            def->data.socket.net.address = g_steal_pointer(&address);
         }
 
         if (def->type != VIR_DOMAIN_NET_TYPE_UDP)
@@ -10987,7 +11011,8 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
                              "specified with socket interface"));
             goto error;
         }
-        if (virStrToLong_i(localport, NULL, 10, &def->data.socket.localport) < 0) {
+        if (virStrToLong_i(localport, NULL, 10,
+                           &def->data.socket.net.localport) < 0) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("Cannot parse <local> 'port' attribute "
                              "with socket interface"));
@@ -11000,7 +11025,7 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
                              "specified with socket interface"));
             goto error;
         } else {
-            def->data.socket.localaddr = g_steal_pointer(&localaddr);
+            def->data.socket.net.localaddr = g_steal_pointer(&localaddr);
         }
         break;
 
@@ -25940,15 +25965,22 @@ virDomainNetDefFormat(virBuffer *buf,
 
         case VIR_DOMAIN_NET_TYPE_SERVER:
         case VIR_DOMAIN_NET_TYPE_CLIENT:
+            if (def->data.socket.path) {
+                virBufferAsprintf(buf, "<source path='%s'",
+                                  def->data.socket.path);
+                sourceLines++;
+                break;
+            }
+            G_GNUC_FALLTHROUGH;
         case VIR_DOMAIN_NET_TYPE_MCAST:
         case VIR_DOMAIN_NET_TYPE_UDP:
-            if (def->data.socket.address) {
+            if (def->data.socket.net.address) {
                 virBufferAsprintf(buf, "<source address='%s' port='%d'",
-                                  def->data.socket.address,
-                                  def->data.socket.port);
+                                  def->data.socket.net.address,
+                                  def->data.socket.net.port);
             } else {
                 virBufferAsprintf(buf, "<source port='%d'",
-                                  def->data.socket.port);
+                                  def->data.socket.net.port);
             }
             sourceLines++;
 
@@ -25960,8 +25992,8 @@ virDomainNetDefFormat(virBuffer *buf,
             virBufferAdjustIndent(buf, 2);
 
             virBufferAsprintf(buf, "<local address='%s' port='%d'/>\n",
-                              def->data.socket.localaddr,
-                              def->data.socket.localport);
+                              def->data.socket.net.localaddr,
+                              def->data.socket.net.localport);
             virBufferAdjustIndent(buf, -2);
             break;
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 7688f17b18cd..054b08330c8c 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1055,11 +1055,14 @@ struct _virDomainNetDef {
     virDomainNetTeamingInfo *teaming;
     union {
         virDomainChrSourceDef *vhostuser;
-        struct {
-            char *address;
-            int port;
-            char *localaddr;
-            int localport;
+        union {
+            struct {
+                char *address;
+                int port;
+                char *localaddr;
+                int localport;
+            } net;
+            char *path;
         } socket; /* any of NET_CLIENT or NET_SERVER or NET_MCAST */
         struct {
             char *name;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2ceff155124e..dbef58f37879 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3713,37 +3713,55 @@ qemuBuildHostNetStr(virDomainNetDef *net,
         break;
 
     case VIR_DOMAIN_NET_TYPE_CLIENT:
-        if (virJSONValueObjectCreate(&netprops, "s:type", "socket", NULL) < 0 ||
-            virJSONValueObjectAppendStringPrintf(netprops, "connect", "%s:%d",
-                                                 net->data.socket.address,
-                                                 net->data.socket.port) < 0)
+        if (virJSONValueObjectCreate(&netprops, "s:type", "socket", NULL) < 0)
+            return NULL;
+
+        if (net->data.socket.path != NULL) {
+            if (virJSONValueObjectAppendStringPrintf(netprops, "connect", "%s",
+                                                     net->data.socket.path) < 0)
+                return NULL;
+            break;
+        }
+
+        if (virJSONValueObjectAppendStringPrintf(netprops, "connect", "%s:%d",
+                                                 net->data.socket.net.address,
+                                                 net->data.socket.net.port) < 0)
             return NULL;
         break;
 
     case VIR_DOMAIN_NET_TYPE_SERVER:
-        if (virJSONValueObjectCreate(&netprops, "s:type", "socket", NULL) < 0 ||
-            virJSONValueObjectAppendStringPrintf(netprops, "listen", "%s:%d",
-                                                 NULLSTR_EMPTY(net->data.socket.address),
-                                                 net->data.socket.port) < 0)
+        if (virJSONValueObjectCreate(&netprops, "s:type", "socket", NULL) < 0)
+            return NULL;
+
+        if (net->data.socket.path != NULL) {
+            if (virJSONValueObjectAppendStringPrintf(netprops, "listen", "%s",
+                                                     net->data.socket.path) < 0)
+                return NULL;
+            break;
+        }
+
+        if (virJSONValueObjectAppendStringPrintf(netprops, "listen", "%s:%d",
+                                                 NULLSTR_EMPTY(net->data.socket.net.address),
+                                                 net->data.socket.net.port) < 0)
             return NULL;
         break;
 
     case VIR_DOMAIN_NET_TYPE_MCAST:
         if (virJSONValueObjectCreate(&netprops, "s:type", "socket", NULL) < 0 ||
             virJSONValueObjectAppendStringPrintf(netprops, "mcast", "%s:%d",
-                                                 net->data.socket.address,
-                                                 net->data.socket.port) < 0)
+                                                 net->data.socket.net.address,
+                                                 net->data.socket.net.port) < 0)
             return NULL;
         break;
 
     case VIR_DOMAIN_NET_TYPE_UDP:
         if (virJSONValueObjectCreate(&netprops, "s:type", "socket", NULL) < 0 ||
             virJSONValueObjectAppendStringPrintf(netprops, "udp", "%s:%d",
-                                                 net->data.socket.address,
-                                                 net->data.socket.port) < 0 ||
+                                                 net->data.socket.net.address,
+                                                 net->data.socket.net.port) < 0 ||
             virJSONValueObjectAppendStringPrintf(netprops, "localaddr", "%s:%d",
-                                                 net->data.socket.localaddr,
-                                                 net->data.socket.localport) < 0)
+                                                 net->data.socket.net.localaddr,
+                                                 net->data.socket.net.localport) < 0)
             return NULL;
         break;
 
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 4344edc75b80..69ef7abd0ee2 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -3741,9 +3741,11 @@ qemuDomainChangeNet(virQEMUDriver *driver,
         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) {
+            if (STRNEQ_NULLABLE(olddev->data.socket.path,
+                                newdev->data.socket.path) ||
+                STRNEQ_NULLABLE(olddev->data.socket.net.address,
+                                newdev->data.socket.net.address) ||
+                olddev->data.socket.net.port != newdev->data.socket.net.port) {
                 needReconnect = true;
             }
             break;
-- 
2.29.2