[PATCH 081/103] qemuBuildInterfaceCommandLine: Generate via JSON

Peter Krempa pkrempa at redhat.com
Thu Oct 7 15:18:09 UTC 2021


virtio-net-pci specific properties and their types according to QEMU:
  tx=<str>
  ioeventfd=<bool>       - on/off (default: true)
  event_idx=<bool>       - on/off (default: true)
  csum=<bool>            - on/off (default: true)
  gso=<bool>             - on/off (default: true)
  host_tso4=<bool>       - on/off (default: true)
  host_tso6=<bool>       - on/off (default: true)
  host_ecn=<bool>        - on/off (default: true)
  host_ufo=<bool>        - on/off (default: true)
  mrg_rxbuf=<bool>       - on/off (default: true)
  guest_csum=<bool>      - on/off (default: true)
  guest_tso4=<bool>      - on/off (default: true)
  guest_tso6=<bool>      - on/off (default: true)
  guest_ecn=<bool>       - on/off (default: true)
  guest_ufo=<bool>       - on/off (default: true)
  mq=<bool>              - on/off (default: false)
  vectors=<uint32>       -  (default: 4294967295)
  rx_queue_size=<uint16> -  (default: 256)
  tx_queue_size=<uint16> -  (default: 256)
  host_mtu=<uint16>      -  (default: 0)
  failover=<bool>        -  (default: false)

properties common for all network interfaces:
  netdev=<str>           - ID of a netdev to use as a backend
  mac=<str>              - Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56
  bootindex=<int32>

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 src/qemu/qemu_command.c | 166 +++++++++++++++++-----------------------
 src/qemu/qemu_command.h |   9 ++-
 src/qemu/qemu_hotplug.c |   6 +-
 3 files changed, 78 insertions(+), 103 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index a8a93274c6..54f50c9a5e 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3859,37 +3859,29 @@ qemuBuildLegacyNicStr(virDomainNetDef *net)
 }


-char *
-qemuBuildNicDevStr(virDomainDef *def,
-                   virDomainNetDef *net,
-                   size_t vhostfdSize,
-                   virQEMUCaps *qemuCaps)
+virJSONValue *
+qemuBuildNicDevProps(virDomainDef *def,
+                     virDomainNetDef *net,
+                     size_t vhostfdSize,
+                     virQEMUCaps *qemuCaps)
 {
-    g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
-    bool usingVirtio = false;
+    g_autoptr(virJSONValue) props = NULL;
     char macaddr[VIR_MAC_STRING_BUFLEN];

     if (virDomainNetIsVirtioModel(net)) {
-        if (qemuBuildVirtioDevStr(&buf, qemuCaps, VIR_DOMAIN_DEVICE_NET, net) < 0) {
-            return NULL;
-        }
-
-        usingVirtio = true;
-    } else {
-        virBufferAddStr(&buf, virDomainNetGetModelString(net));
-    }
+        const char *tx = NULL;
+        virTristateSwitch mq = VIR_TRISTATE_SWITCH_ABSENT;
+        unsigned long long vectors = 0;
+        virTristateSwitch failover = VIR_TRISTATE_SWITCH_ABSENT;

-    if (usingVirtio) {
-        if (net->driver.virtio.txmode &&
-            virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_TX_ALG)) {
-            virBufferAddLit(&buf, ",tx=");
+        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_TX_ALG)) {
             switch (net->driver.virtio.txmode) {
                 case VIR_DOMAIN_NET_VIRTIO_TX_MODE_IOTHREAD:
-                    virBufferAddLit(&buf, "bh");
+                    tx = "bh";
                     break;

                 case VIR_DOMAIN_NET_VIRTIO_TX_MODE_TIMER:
-                    virBufferAddLit(&buf, "timer");
+                    tx = "timer";
                     break;

                 case VIR_DOMAIN_NET_VIRTIO_TX_MODE_DEFAULT:
@@ -3905,100 +3897,80 @@ qemuBuildNicDevStr(virDomainDef *def,
                     return NULL;
             }
         }
-        qemuBuildIoEventFdStr(&buf, net->driver.virtio.ioeventfd, qemuCaps);
-        if (net->driver.virtio.event_idx) {
-            virBufferAsprintf(&buf, ",event_idx=%s",
-                              virTristateSwitchTypeToString(net->driver.virtio.event_idx));
-        }
-        if (net->driver.virtio.host.csum) {
-            virBufferAsprintf(&buf, ",csum=%s",
-                              virTristateSwitchTypeToString(net->driver.virtio.host.csum));
-        }
-        if (net->driver.virtio.host.gso) {
-            virBufferAsprintf(&buf, ",gso=%s",
-                              virTristateSwitchTypeToString(net->driver.virtio.host.gso));
-        }
-        if (net->driver.virtio.host.tso4) {
-            virBufferAsprintf(&buf, ",host_tso4=%s",
-                              virTristateSwitchTypeToString(net->driver.virtio.host.tso4));
-        }
-        if (net->driver.virtio.host.tso6) {
-            virBufferAsprintf(&buf, ",host_tso6=%s",
-                              virTristateSwitchTypeToString(net->driver.virtio.host.tso6));
-        }
-        if (net->driver.virtio.host.ecn) {
-            virBufferAsprintf(&buf, ",host_ecn=%s",
-                              virTristateSwitchTypeToString(net->driver.virtio.host.ecn));
-        }
-        if (net->driver.virtio.host.ufo) {
-            virBufferAsprintf(&buf, ",host_ufo=%s",
-                              virTristateSwitchTypeToString(net->driver.virtio.host.ufo));
-        }
-        if (net->driver.virtio.host.mrg_rxbuf) {
-            virBufferAsprintf(&buf, ",mrg_rxbuf=%s",
-                              virTristateSwitchTypeToString(net->driver.virtio.host.mrg_rxbuf));
-        }
-        if (net->driver.virtio.guest.csum) {
-            virBufferAsprintf(&buf, ",guest_csum=%s",
-                              virTristateSwitchTypeToString(net->driver.virtio.guest.csum));
-        }
-        if (net->driver.virtio.guest.tso4) {
-            virBufferAsprintf(&buf, ",guest_tso4=%s",
-                              virTristateSwitchTypeToString(net->driver.virtio.guest.tso4));
-        }
-        if (net->driver.virtio.guest.tso6) {
-            virBufferAsprintf(&buf, ",guest_tso6=%s",
-                              virTristateSwitchTypeToString(net->driver.virtio.guest.tso6));
-        }
-        if (net->driver.virtio.guest.ecn) {
-            virBufferAsprintf(&buf, ",guest_ecn=%s",
-                              virTristateSwitchTypeToString(net->driver.virtio.guest.ecn));
-        }
-        if (net->driver.virtio.guest.ufo) {
-            virBufferAsprintf(&buf, ",guest_ufo=%s",
-                              virTristateSwitchTypeToString(net->driver.virtio.guest.ufo));
-        }

         if (vhostfdSize > 1) {
             if (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
                 /* ccw provides a one to one relation of fds to queues and
                  * does not support the vectors option
                  */
-                virBufferAddLit(&buf, ",mq=on");
+                mq = VIR_TRISTATE_SWITCH_ON;
             } else {
                 /* As advised at https://www.linux-kvm.org/page/Multiqueue
                  * we should add vectors=2*N+2 where N is the vhostfdSize
                  */
-                virBufferAsprintf(&buf, ",mq=on,vectors=%zu", 2 * vhostfdSize + 2);
+                mq = VIR_TRISTATE_SWITCH_ON;
+                vectors = 2 * vhostfdSize + 2;
             }
         }

-        if (net->driver.virtio.rx_queue_size)
-            virBufferAsprintf(&buf, ",rx_queue_size=%u", net->driver.virtio.rx_queue_size);
-
-        if (net->driver.virtio.tx_queue_size)
-            virBufferAsprintf(&buf, ",tx_queue_size=%u", net->driver.virtio.tx_queue_size);
+        if (net->teaming && net->teaming->type == VIR_DOMAIN_NET_TEAMING_TYPE_PERSISTENT)
+            failover = VIR_TRISTATE_SWITCH_ON;

-        if (net->mtu)
-            virBufferAsprintf(&buf, ",host_mtu=%u", net->mtu);
+        if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_NET, net, qemuCaps)))
+            return NULL;

-        if (net->teaming && net->teaming->type == VIR_DOMAIN_NET_TEAMING_TYPE_PERSISTENT)
-            virBufferAddLit(&buf, ",failover=on");
+        if (virJSONValueObjectAdd(props,
+                                  "S:tx", tx,
+                                  "T:ioeventfd", net->driver.virtio.ioeventfd,
+                                  "T:event_idx", net->driver.virtio.event_idx,
+                                  "T:csum", net->driver.virtio.host.csum,
+                                  "T:gso", net->driver.virtio.host.gso,
+                                  "T:host_tso4", net->driver.virtio.host.tso4,
+                                  "T:host_tso6", net->driver.virtio.host.tso6,
+                                  "T:host_ecn", net->driver.virtio.host.ecn,
+                                  "T:host_ufo", net->driver.virtio.host.ufo,
+                                  "T:mrg_rxbuf", net->driver.virtio.host.mrg_rxbuf,
+                                  "T:guest_csum", net->driver.virtio.guest.csum,
+                                  "T:guest_tso4", net->driver.virtio.guest.tso4,
+                                  "T:guest_tso6", net->driver.virtio.guest.tso6,
+                                  "T:guest_ecn", net->driver.virtio.guest.ecn,
+                                  "T:guest_ufo", net->driver.virtio.guest.ufo,
+                                  "T:mq", mq,
+                                  "P:vectors", vectors,
+                                  "p:rx_queue_size", net->driver.virtio.rx_queue_size,
+                                  "p:tx_queue_size", net->driver.virtio.tx_queue_size,
+                                  "p:host_mtu", net->mtu,
+                                  "T:failover", failover,
+                                  NULL) < 0)
+            return NULL;
+    } else {
+        if (virJSONValueObjectCreate(&props,
+                                     "s:driver", virDomainNetGetModelString(net),
+                                     NULL) < 0)
+            return NULL;
     }

-    virBufferAsprintf(&buf, ",netdev=host%s", net->info.alias);
-    virBufferAsprintf(&buf, ",id=%s", net->info.alias);
-    virBufferAsprintf(&buf, ",mac=%s",
-                      virMacAddrFormat(&net->mac, macaddr));
+    virMacAddrFormat(&net->mac, macaddr);

-    if (qemuBuildDeviceAddressStr(&buf, def, &net->info) < 0)
+    if (virJSONValueObjectAdd(props,
+                              "f:netdev", g_strdup_printf("host%s", net->info.alias),
+                              "s:id", net->info.alias,
+                              "s:mac", macaddr,
+                              NULL) < 0)
         return NULL;
-    if (qemuBuildRomStr(&buf, &net->info) < 0)
+
+    if (qemuBuildDeviceAddressProps(props, def, &net->info) < 0)
         return NULL;
-    if (net->info.effectiveBootIndex > 0)
-        virBufferAsprintf(&buf, ",bootindex=%u", net->info.effectiveBootIndex);

-    return virBufferContentAndReset(&buf);
+    if (qemuBuildRomProps(props, &net->info) < 0)
+        return NULL;
+
+    if (virJSONValueObjectAdd(props,
+                              "p:bootindex", net->info.effectiveBootIndex,
+                              NULL) < 0)
+        return NULL;
+
+    return g_steal_pointer(&props);
 }


@@ -8747,6 +8719,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver,
 {
     virDomainDef *def = vm->def;
     int ret = -1;
+    g_autoptr(virJSONValue) nicprops = NULL;
     g_autofree char *nic = NULL;
     g_autofree char *chardev = NULL;
     int *tapfd = NULL;
@@ -9010,9 +8983,10 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver,
         if (qemuCommandAddExtDevice(cmd, &net->info, qemuCaps) < 0)
             goto cleanup;

-        if (!(nic = qemuBuildNicDevStr(def, net, net->driver.virtio.queues, qemuCaps)))
+        if (!(nicprops = qemuBuildNicDevProps(def, net, net->driver.virtio.queues, qemuCaps)))
+            goto cleanup;
+        if (qemuBuildDeviceCommandlineFromJSON(cmd, nicprops, qemuCaps) < 0)
             goto cleanup;
-        virCommandAddArgList(cmd, "-device", nic, NULL);
     } else if (!requireNicdev) {
         if (qemuCommandAddExtDevice(cmd, &net->info, qemuCaps) < 0)
             goto cleanup;
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 18d4c4130b..29db16e729 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -98,10 +98,11 @@ virJSONValue *qemuBuildHostNetStr(virDomainNetDef *net,
                                     const char *vdpadev);

 /* Current, best practice */
-char *qemuBuildNicDevStr(virDomainDef *def,
-                         virDomainNetDef *net,
-                         size_t vhostfdSize,
-                         virQEMUCaps *qemuCaps);
+virJSONValue *
+qemuBuildNicDevProps(virDomainDef *def,
+                     virDomainNetDef *net,
+                     size_t vhostfdSize,
+                     virQEMUCaps *qemuCaps);

 char *qemuDeviceDriveHostAlias(virDomainDiskDef *disk);
 bool qemuDiskBusIsSD(int bus);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 1b5f63f271..1c0056da16 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1175,7 +1175,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
     int *vhostfd = NULL;
     size_t vhostfdSize = 0;
     size_t queueSize = 0;
-    g_autofree char *nicstr = NULL;
+    g_autoptr(virJSONValue) nicprops = NULL;
     g_autoptr(virJSONValue) netprops = NULL;
     int ret = -1;
     bool releaseaddr = false;
@@ -1484,7 +1484,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
     for (i = 0; i < vhostfdSize; i++)
         VIR_FORCE_CLOSE(vhostfd[i]);

-    if (!(nicstr = qemuBuildNicDevStr(vm->def, net, queueSize, priv->qemuCaps)))
+    if (!(nicprops = qemuBuildNicDevProps(vm->def, net, queueSize, priv->qemuCaps)))
         goto try_remove;

     qemuDomainObjEnterMonitor(driver, vm);
@@ -1495,7 +1495,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
         goto try_remove;
     }

-    if (qemuMonitorAddDevice(priv->mon, nicstr) < 0) {
+    if (qemuMonitorAddDeviceProps(priv->mon, &nicprops) < 0) {
         ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &net->info));
         ignore_value(qemuDomainObjExitMonitor(driver, vm));
         virDomainAuditNet(vm, NULL, net, "attach", false);
-- 
2.31.1




More information about the libvir-list mailing list