qemuBuildInterfaceCommandLine: Generate via JSON

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@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Peter Krempa 2021-10-04 17:52:03 +02:00
parent dc481f11a6
commit ee996fbf7a
3 changed files with 81 additions and 105 deletions

View File

@ -3870,37 +3870,30 @@ 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];
g_autofree char *netdev = g_strdup_printf("host%s", net->info.alias);
if (virDomainNetIsVirtioModel(net)) {
if (qemuBuildVirtioDevStr(&buf, qemuCaps, VIR_DOMAIN_DEVICE_NET, net) < 0) {
return NULL;
}
const char *tx = NULL;
virTristateSwitch mq = VIR_TRISTATE_SWITCH_ABSENT;
unsigned long long vectors = 0;
virTristateSwitch failover = VIR_TRISTATE_SWITCH_ABSENT;
usingVirtio = true;
} else {
virBufferAddStr(&buf, virDomainNetGetModelString(net));
}
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:
@ -3916,100 +3909,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->mtu)
virBufferAsprintf(&buf, ",host_mtu=%u", net->mtu);
if (net->teaming && net->teaming->type == VIR_DOMAIN_NET_TEAMING_TYPE_PERSISTENT)
virBufferAddLit(&buf, ",failover=on");
failover = VIR_TRISTATE_SWITCH_ON;
if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_NET, net, qemuCaps)))
return NULL;
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,
"s:netdev", netdev,
"s:id", net->info.alias,
"s:mac", macaddr,
NULL) < 0)
return NULL;
if (qemuBuildRomStr(&buf, &net->info) < 0)
return NULL;
if (net->info.effectiveBootIndex > 0)
virBufferAsprintf(&buf, ",bootindex=%u", net->info.effectiveBootIndex);
return virBufferContentAndReset(&buf);
if (qemuBuildDeviceAddressProps(props, def, &net->info) < 0)
return NULL;
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);
}
@ -8778,6 +8751,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;
@ -9041,9 +9015,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;

View File

@ -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);

View File

@ -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);