]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Add the port allocation logic for isa-serial devices.
authorDivya Garg <divya.garg@nutanix.com>
Thu, 13 Jan 2022 07:33:40 +0000 (23:33 -0800)
committerMichal Privoznik <mprivozn@redhat.com>
Fri, 14 Jan 2022 14:41:57 +0000 (15:41 +0100)
This commit takes care of following cases:
-> Check availability of requested ports.
  ->The total number of requested ports should not be more than
    VIR_MAX_ISA_SERIAL_PORTS.
  ->The ports requested should be less than VIR_MAX_ISA_SERIAL_PORTS.
  ->VIR_MAX_ISA_SERIAL_PORTS should correspond to MAX_ISA_SERIAL_PORTS
    specified in QEMU code commit def337ffda34d331404bd7f1a42726b71500df22.
-> Prevent duplicate device assignments to the same port.
-> In case no ports are provided in the XML, this patch scans the list of unused
   isa-serial indices to automatically assign available ports for this VM.

Signed-off-by: Divya Garg <divya.garg@nutanix.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/conf/domain_conf.c
src/conf/domain_conf.h
tests/qemuhotplugtestdomains/qemuhotplug-console-compat-2-live+console-virtio.xml
tests/qemuhotplugtestdomains/qemuhotplug-console-compat-2-live.xml
tests/qemuxml2argvdata/serial-tcp-tlsx509-chardev-notls.xml
tests/qemuxml2argvdata/serial-tcp-tlsx509-chardev-verify.xml
tests/qemuxml2argvdata/serial-tcp-tlsx509-chardev.xml
tests/qemuxml2argvdata/serial-tcp-tlsx509-secret-chardev.xml
tests/qemuxml2xmloutdata/serial-tcp-tlsx509-chardev.xml

index 5691b8d2d5894d36b82f2b42784cca9f2641f82e..a805f7f6a3412f779281853a72fb0af1f8b8b074 100644 (file)
@@ -5330,6 +5330,58 @@ virDomainHostdevDefPostParse(virDomainHostdevDef *dev,
 }
 
 
+static int
+virDomainChrIsaSerialDefPostParse(virDomainDef *def)
+{
+    size_t i;
+    size_t isa_serial_count = 0;
+    bool used_serial_port[VIR_MAX_ISA_SERIAL_PORTS] = { false };
+
+    /* Perform all the required checks. */
+    for (i = 0; i < def->nserials; i++) {
+        if (def->serials[i]->targetType != VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL)
+            continue;
+
+        if (isa_serial_count++ >= VIR_MAX_ISA_SERIAL_PORTS ||
+            def->serials[i]->target.port >= VIR_MAX_ISA_SERIAL_PORTS) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Maximum supported number of ISA serial ports is '%d'"),
+                           VIR_MAX_ISA_SERIAL_PORTS);
+            return -1;
+        }
+
+        if (def->serials[i]->target.port != -1) {
+            if (used_serial_port[def->serials[i]->target.port]) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("target port '%d' already allocated"),
+                               def->serials[i]->target.port);
+                return -1;
+            }
+            used_serial_port[def->serials[i]->target.port] = true;
+        }
+    }
+
+    /* Assign the ports to the devices. */
+    for (i = 0; i < def->nserials; i++) {
+        size_t j;
+
+        if (def->serials[i]->targetType != VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL ||
+            def->serials[i]->target.port != -1)
+            continue;
+
+        for (j = 0; j < VIR_MAX_ISA_SERIAL_PORTS; j++) {
+            if (!used_serial_port[j]) {
+                def->serials[i]->target.port = j;
+                used_serial_port[j] = true;
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+
+
 static void
 virDomainChrDefPostParse(virDomainChrDef *chr,
                          const virDomainDef *def)
@@ -6197,6 +6249,9 @@ virDomainDefPostParse(virDomainDef *def,
             goto cleanup;
     }
 
+    if (virDomainChrIsaSerialDefPostParse(def) < 0)
+            return -1;
+
     /* iterate the devices */
     ret = virDomainDeviceInfoIterateFlags(def,
                                           virDomainDefPostParseDeviceIterator,
@@ -19929,14 +19984,6 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt,
         if (!chr)
             return NULL;
 
-        if (chr->target.port == -1) {
-            int maxport = -1;
-            for (j = 0; j < i; j++) {
-                if (def->serials[j]->target.port > maxport)
-                    maxport = def->serials[j]->target.port;
-            }
-            chr->target.port = maxport + 1;
-        }
         def->serials[def->nserials++] = chr;
     }
     VIR_FREE(nodes);
index 144ba4dd1211f80e391464e9adf17deb087894e8..3cd0617c0fcae0335249bda354d6f6ac0f3f79ad 100644 (file)
@@ -1187,6 +1187,12 @@ typedef enum {
     VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LAST
 } virDomainChrConsoleTargetType;
 
+/*
+ * The value of VIR_MAX_ISA_SERIAL_PORTS corresponds to MAX_ISA_SERIAL_PORTS
+ * set in QEMU code base.
+ */
+#define VIR_MAX_ISA_SERIAL_PORTS 4
+
 typedef enum {
     VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_NONE = 0,
     VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL,
index 38311b188c2dd76f33d076fa7f500b18b958bbe7..72516555a0befc874ba5e9c5137081d5adac6e20 100644 (file)
@@ -74,7 +74,7 @@
       <alias name='serial0'/>
     </serial>
     <serial type='pty'>
-      <target type='isa-serial' port='0'>
+      <target type='isa-serial' port='1'>
         <model name='isa-serial'/>
       </target>
       <alias name='serial1'/>
@@ -82,7 +82,7 @@
     <serial type='tcp'>
       <source mode='bind' host='0.0.0.0' service='2445'/>
       <protocol type='raw'/>
-      <target type='isa-serial' port='1'>
+      <target type='isa-serial' port='2'>
         <model name='isa-serial'/>
       </target>
       <alias name='serial2'/>
index 3fe205430c08a755af5e69eb3bcf6c157cfac57f..6197a2bfe319d3ac50e607b56aeea4fea5941343 100644 (file)
@@ -74,7 +74,7 @@
       <alias name='serial0'/>
     </serial>
     <serial type='pty'>
-      <target type='isa-serial' port='0'>
+      <target type='isa-serial' port='1'>
         <model name='isa-serial'/>
       </target>
       <alias name='serial1'/>
@@ -82,7 +82,7 @@
     <serial type='tcp'>
       <source mode='bind' host='0.0.0.0' service='2445'/>
       <protocol type='raw'/>
-      <target type='isa-serial' port='1'>
+      <target type='isa-serial' port='2'>
         <model name='isa-serial'/>
       </target>
       <alias name='serial2'/>
index f27b119270db699a8fac64fb9eb81c138337c86d..16734d9cceeeb16f2dacbbd0e0f3cda5f835ebc4 100644 (file)
@@ -37,7 +37,7 @@
     <serial type='tcp'>
       <source mode='connect' host='127.0.0.1' service='5555' tls='no'/>
       <protocol type='raw'/>
-      <target type='isa-serial' port='0'>
+      <target type='isa-serial' port='1'>
         <model name='isa-serial'/>
       </target>
     </serial>
index be58ccc1da5a23c8f5be2140fa4045162fddb3c2..15ce29c67d2bf14af5b357bac354f8c5ed879136 100644 (file)
@@ -29,7 +29,7 @@
     <serial type='tcp'>
       <source mode='connect' host='127.0.0.1' service='5555'/>
       <protocol type='raw'/>
-      <target port='0'/>
+      <target port='1'/>
     </serial>
     <console type='udp'>
       <source mode='bind' host='127.0.0.1' service='1111'/>
index be58ccc1da5a23c8f5be2140fa4045162fddb3c2..15ce29c67d2bf14af5b357bac354f8c5ed879136 100644 (file)
@@ -29,7 +29,7 @@
     <serial type='tcp'>
       <source mode='connect' host='127.0.0.1' service='5555'/>
       <protocol type='raw'/>
-      <target port='0'/>
+      <target port='1'/>
     </serial>
     <console type='udp'>
       <source mode='bind' host='127.0.0.1' service='1111'/>
index 8e44dea3654ab417d4f361877669ef09830fe1c1..8bb7cbefae880f0b275bda9e2fd04268a93ef5f7 100644 (file)
@@ -34,7 +34,7 @@
     <serial type='tcp'>
       <source mode='connect' host='127.0.0.1' service='5555'/>
       <protocol type='raw'/>
-      <target port='0'/>
+      <target port='1'/>
     </serial>
     <console type='udp'>
       <source mode='bind' host='127.0.0.1' service='1111'/>
index aefd3513ce32064524b46f8d7827382ddd4e278a..4cdefed63d00bc67e8e4760ffc63ed4eda95baf6 100644 (file)
@@ -37,7 +37,7 @@
     <serial type='tcp'>
       <source mode='connect' host='127.0.0.1' service='5555'/>
       <protocol type='raw'/>
-      <target type='isa-serial' port='0'>
+      <target type='isa-serial' port='1'>
         <model name='isa-serial'/>
       </target>
     </serial>