<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p><font face="monospace">On 24/11/21 6:21 pm, Peter Krempa wrote:<br>
      </font></p>
    <blockquote type="cite" cite="mid:YZ41SB1VPDz7lwjX@angien.pipo.sk">
      <pre class="moz-quote-pre" wrap="">On Wed, Nov 24, 2021 at 07:06:06 -0500, divya wrote:

Hi, just a few quick points, I'm not going to analyze what this does too
deeply at this point.

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">From: root <a class="moz-txt-link-rfc2396E" href="mailto:root@localhost.localdomain"><root@localhost.localdomain></a>
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
Author should be set properly. Also we require a proper commit message
explaining the issue.

Additionally we require that the submitter declares conformance with
the developer certificate of origin:

<a class="moz-txt-link-freetext" href="https://urldefense.proofpoint.com/v2/url?u=https-3A__www.libvirt.org_hacking.html-23developer-2Dcertificate-2Dof-2Dorigin&d=DwIBAg&c=s883GpUCOChKOHiocYtGcg&r=2QGHz-fTCVWImEBKe1ZcSe5t6UfasnhvdzD5DcixwOE&m=IUWwXppAjhBSqGVOlRTyZ70mhLrTUeeQA692o-Q942j1SPk8i8nrvQPV9KtRHOwl&s=23RVgvzwCkcam2r_OcJ3920vDnxkmIm4tY15Bb4LdFY&e=">https://urldefense.proofpoint.com/v2/url?u=https-3A__www.libvirt.org_hacking.html-23developer-2Dcertificate-2Dof-2Dorigin&d=DwIBAg&c=s883GpUCOChKOHiocYtGcg&r=2QGHz-fTCVWImEBKe1ZcSe5t6UfasnhvdzD5DcixwOE&m=IUWwXppAjhBSqGVOlRTyZ70mhLrTUeeQA692o-Q942j1SPk8i8nrvQPV9KtRHOwl&s=23RVgvzwCkcam2r_OcJ3920vDnxkmIm4tY15Bb4LdFY&e=</a> 
</pre>
    </blockquote>
    <font face="monospace">This patch was just for getting the
      understanding of historical reasons of the</font><br>
    <font face="monospace"> port allocation logic we process today and
      if the changes suggested looks good</font><br>
    <font face="monospace">and doesn't violate any convention or if we
      are planning to have a different<br>
    </font><font face="monospace">handling for such cases.</font>
    <blockquote type="cite" cite="mid:YZ41SB1VPDz7lwjX@angien.pipo.sk">
      <pre class="moz-quote-pre" wrap="">
</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">
---
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
[...]

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5cfb2d91eb..edc5e897be 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -65,6 +65,7 @@
 #include "virutil.h"
 
 #define VIR_FROM_THIS VIR_FROM_DOMAIN
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
Firstly I see many problems with coding style:</pre>
    </blockquote>
    <font face="monospace">I am really sorry for that, I didnt give much
      attention to that. It was just to</font><br>
    <font face="monospace"> show how I will be changing the port
      allocation logic for isa-serial devices.</font>
    <blockquote type="cite" cite="mid:YZ41SB1VPDz7lwjX@angien.pipo.sk">
      <pre class="moz-quote-pre" wrap="">

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">+#define max_available_isa_serial_ports 4
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
We usually use uppercase macros

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap=""> 
 VIR_LOG_INIT("conf.domain_conf");
 
@@ -19649,6 +19650,10 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt,
     g_autofree xmlNodePtr *nodes = NULL;
     g_autofree char *tmp = NULL;
     g_autoptr(virDomainDef) def = NULL;
+    uint8_t used_serial_port_buffer = 0;
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
We have virBitmap for such things.</pre>
    </blockquote>
    <font face="monospace">Noted. Thanks.<br>
    </font>
    <blockquote type="cite" cite="mid:YZ41SB1VPDz7lwjX@angien.pipo.sk">
      <pre class="moz-quote-pre" wrap="">

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">+    int isa_serial_count = 0;
+    int next_available_serial_port = 0;
+    int max_serial_port = -1;
 
     if (!(def = virDomainDefNew(xmlopt)))
         return NULL;
@@ -19886,16 +19891,67 @@ 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;
+        def->serials[def->nserials++] = chr;
+
+        // Giving precedence to the isa-serial device since
+        // only limited ports can be used for such devices.
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
We don't use line comments (//) but block comments everywhere /* */</pre>
    </blockquote>
    <font face="monospace">Noted<br>
    </font>
    <blockquote type="cite" cite="mid:YZ41SB1VPDz7lwjX@angien.pipo.sk">
      <pre class="moz-quote-pre" wrap="">

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">+        if (chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL) {
+            // Taking the isa serial devices to start of the array.
+            for (j = def->nserials; j > isa_serial_count; j--)
+                def->serials[j] = def->serials[j-1];
+            def->serials[isa_serial_count++] = chr;
+        }
+
+        // Maintaining the buffer for first max_available_isa_serial_ports unused ports.
+        if (chr->target.port != -1 && chr->target.port <= max_available_isa_serial_ports) {
+            if (used_serial_port_buffer & (1 << chr->target.port)) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                    _("target port [%d] already allocated."),
+                    chr->target.port);
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
This is misaligned.</pre>
    </blockquote>
    <font face="monospace">Noted</font><br>
    <blockquote type="cite" cite="mid:YZ41SB1VPDz7lwjX@angien.pipo.sk">
      <pre class="moz-quote-pre" wrap="">

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">+                return NULL;
             }
-            chr->target.port = maxport + 1;
+            used_serial_port_buffer |= 1 << chr->target.port;
+        }
+
+        // Update max serial port used.
+        if (chr->target.port > max_serial_port)
+            max_serial_port = chr->target.port;
+    }
+
+    // Assign the ports to the devices.
+    for (i = 0; i < n; i++) {
+        if (def->serials[i]->target.port != -1) continue;
+        // Assign one of the unused ports from first max_available_isa_serial_ports ports
+        // to isa-serial device.
+        if (def->serials[i]->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL) {
+
+            // Search for the next available port.
+            while (used_serial_port_buffer & (1 << next_available_serial_port) &&
+                next_available_serial_port <= max_available_isa_serial_ports) {
+                next_available_serial_port++;
+            }
+
+            // qemu doesn't support more than max_available_isa_serial_ports isa devices.
+            if (i > max_available_isa_serial_ports ||
+                next_available_serial_port > max_available_isa_serial_ports) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                    _("Maximum supported number of ISA serial ports is %d."),
+                    max_available_isa_serial_ports);
+                return NULL;
+            }
+
+            used_serial_port_buffer |= 1 << next_available_serial_port;
+            def->serials[i]->target.port = next_available_serial_port;
+
+            // Update max serial port used.
+            if (def->serials[i]->target.port > max_serial_port)
+                max_serial_port = def->serials[i]->target.port;
+
+        } else {
+            def->serials[i]->target.port = ++max_serial_port;
         }
-        def->serials[def->nserials++] = chr;
     }
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
In general, none of this code should be in the parser itself. Not even
the existing code which you are changing actually.

We have code which is meant to adjust and fill defaults for devices. For
your case virDomainChrDefPostParse  or virDomainDefPostParseCommon might
be the right place.

Note that until now the assignment code was rather trivial, but you are
adding a massive amount of logic to this so it definitely doesn't belong
to the parser any more.</pre>
    </blockquote>
    <font face="monospace">Earlier we never checked for repeated ports
      or the max port that can be</font><br>
    <font face="monospace"> assigned to a particular design. Besides we
      used to assign the ports blindly</font><br>
    <font face="monospace"> without considering what kind of device it
      is. Was there any specefic reason</font><br>
    <font face="monospace">for this ?</font><br>
    <font face="monospace"></font>
    <blockquote type="cite" cite="mid:YZ41SB1VPDz7lwjX@angien.pipo.sk">
      <pre class="moz-quote-pre" wrap="">

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">+
     VIR_FREE(nodes);
 
     if ((n = virXPathNodeSet("./devices/console", ctxt, &nodes)) < 0) {
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 7a185061d8..c8f8a27f30 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -10947,11 +10947,21 @@ qemuBuildSerialChrDeviceProps(const virDomainDef *def,
         return NULL;
     }
 
-    if (virJSONValueObjectAdd(&props,
-                              "s:driver", virDomainChrSerialTargetModelTypeToString(serial->targetModel),
-                              "s:chardev", chardev,
-                              "s:id", serial->info.alias,
-                              NULL) < 0)
+    if (serial->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL &&
+                    serial->target.port != -1) {
+            if (virJSONValueObjectAdd(&props,
+                                 "s:driver", virDomainChrSerialTargetModelTypeToString(serial->targetModel),
+                                 "s:chardev", chardev,
+                                 "s:id", serial->info.alias,
+                                 "i:index", serial->target.port,
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
You can use "k:index" which conditionally adds the 'index' field only
when it's 0 or positive ...

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">+                                 NULL) < 0)
+                    return NULL;
+    }
+    else if (virJSONValueObjectAdd(&props,
+                                 "s:driver", virDomainChrSerialTargetModelTypeToString(serial->targetModel),
+                                 "s:chardev", chardev,
+                                 "s:id", serial->info.alias,
+                                 NULL) < 0)
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
... so that you don't have to have this else branch here.</pre>
    </blockquote>
    <font face="monospace">Thanks, but this will be anyhow required to
      check if the device is ISA-serial</font><br>
    <font face="monospace"> or not.</font>
    <blockquote type="cite" cite="mid:YZ41SB1VPDz7lwjX@angien.pipo.sk">
      <pre class="moz-quote-pre" wrap="">

Also all of this new code seems to be badly misalligned.</pre>
    </blockquote>
    <font face="monospace">Will update the allignment.</font><br>
    <blockquote type="cite" cite="mid:YZ41SB1VPDz7lwjX@angien.pipo.sk">
      <pre class="moz-quote-pre" wrap="">

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">         return NULL;
 
     if (qemuBuildDeviceAddressProps(props, def, &serial->info) < 0)
diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c
index 263a92425c..88c9ea0339 100644
--- a/tests/qemuhotplugtest.c
+++ b/tests/qemuhotplugtest.c
@@ -355,7 +355,6 @@ testQemuHotplug(const void *data)
     if (keep) {
         test->vm = vm;
     } else {
-        virObjectUnref(vm);
         test->vm = NULL;
     }
     virDomainDeviceDefFree(dev);
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
This is a very questionable hunk. Was this just for testing?</pre>
    </blockquote>
    <font face="monospace">Hi Peter. This was an RFC and yeah, still not
      finalised. I will be working on</font><br>
    <font face="monospace">formatting and restructure the code once the
      logic goods. Before putting more</font><br>
    <font face="monospace"> efforts in finalising the code I wanted to
      confirm if the changes in the port</font><br>
    <font face="monospace"> allocation logic for isa-serial devices
      looks good or not.</font>
    <p><font face="monospace">Sharing the details :<br>
      </font></p>
    <p><font face="monospace"><u><b>Issue</b></u><br>
        -----<br>
        The port being provided in the xml file of the domain is not
        being used for the<br>
        creation of qemu command.<br>
        <br>
        On adding the serial device :<br>
        <br>
        <serial><br>
        <target type='serial' port='3'/><br>
        </serial><br>
        <br>
        Generated qemu command will look like :<br>
        /usr/libexec/qemu-kvm ...\<br>
            -device isa-serial,chardev=charserial0,id=serial0<br>
        <br>
        Actually it should be : <br>
        /usr/libexec/qemu-kvm ...\<br>
            -device isa-serial,chardev=charserial0,id=serial0,index=3<br>
        <br>
        There is a patch out there already for the correction :<br>
<a class="moz-txt-link-freetext" href="https://listman.redhat.com/archives/libvir-list/2018-April/msg02302.html">https://listman.redhat.com/archives/libvir-list/2018-April/msg02302.html</a><br>
        <br>
        But This patch was not followed up. According to me there are
        multiple reasons<br>
        <br>
        <u><b>Reasons for not following up</b></u><br>
        ----------------------------</font></p>
    <p><font face="monospace">----------------------------</font></p>
    <p><font face="monospace">Index : specifies the index number of a
        connector port. If not specified, the<br>
        index is automatically incremented. This logic exists both on
        qemu as well as<br>
        libvirt.<br>
<a class="moz-txt-link-freetext" href="https://github.com/qemu/qemu/blob/master/hw/char/serial-isa.c#L62">https://github.com/qemu/qemu/blob/master/hw/char/serial-isa.c#L62</a><br>
        <br>
        <u><b>Issue 1:</b></u></font></p>
    <p><font face="monospace">If we want two isa-serial devices and for
        the first one is we mention the port<br>
        to be 3, then for the next device it not automatically assign
        the port number <br>
        4 which will throw the following error :  <br>
        error: internal error: process exited while connecting to
        monitor:<br>
        2021-11-12T11:05:31.169987Z qemu-kvm: -device<br>
        isa-serial,chardev=charserial2,id=serial2,index=5: Max.
        supported number of ISA<br>
        serial ports is 4.<br>
        <br>
        But we are left with 3 ports (0,1,2) which are unused. So
        ideally we should<br>
        have used them.<br>
        <br>
        <u><b>Issue 2:</b></u><b></b><br>
        <br>
        It is possible that two devices get the same port address which
        might lead to a<br>
        lot of ambiguity. Example: we want two devices and for the
        second one we<br>
        provide the index 0. Then from default logic the first device
        will be allotted<br>
        port 0 and the second device will overwrite it and get port 0.<br>
        <br>
        <u><b>Solution :</b></u><br>
        ----------</font></p>
    <p><font face="monospace">----------</font></p>
    <p><font face="monospace"><b><u>Port allocation logic</u></b><br>
        <br>
        1. Precedence should be given to serial devices as we only have
        the first 4<br>
        ports for them.<br>
            1.1. Check the command line/xml file, scan for all the
        devices mentioned<br>
            and then start with the isa-serial devices for port
        allocation.<br>
        2.Maintain a buffer(bitmap) for marking the allocated ports.<br>
        3.While assigning a port to the device<br>
            3.1. If no port is provided by the user : provide the next
        available port.<br>
            3.2. Else check:<br>
                3.2.1. If the port is already allocated : throw the
        error.<br>
                3.2.2. Else allocate the port.<br>
            3.3. If out of ports : throw error -> qemu throws the
        error.<br>
        <br>
      </font></p>
    <font face="monospace">Libvirt also manages the port numbers with
      the auto increment logic but never <br>
      updates the index value using the port number. Hence index should
      be <br>
      assigned with proper port allocation logic.</font>
    <blockquote type="cite" cite="mid:YZ41SB1VPDz7lwjX@angien.pipo.sk">
      <pre class="moz-quote-pre" wrap="">

</pre>
    </blockquote>
  </body>
</html>