To ensure that the device addressing scheme is stable across hotplug/unplug, all virtio serial channels needs to have an associated port number in their address. This is then specified to QEMU using the nr=NNN parameter * src/conf/domain_conf.c, src/conf/domain_conf.h: Parsing for port number in vioserial address types. * src/qemu/qemu_conf.c: Set 'nr=NNN' parameter with virtio serial port number * tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args, tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml: Expand data set to ensure coverage of port addressing --- src/conf/domain_conf.c | 30 ++++++++++++++++++-- src/conf/domain_conf.h | 1 + src/qemu/qemu_conf.c | 3 ++ .../qemuxml2argv-channel-virtio.args | 2 +- .../qemuxml2argv-channel-virtio.xml | 14 ++++++++- 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 312a6c0..a9b01d5 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1055,9 +1055,10 @@ static int virDomainDeviceInfoFormat(virBufferPtr buf, break; case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL: - virBufferVSprintf(buf, " controller='%d' bus='%d'", + virBufferVSprintf(buf, " controller='%d' bus='%d' port='%d'", info->addr.vioserial.controller, - info->addr.vioserial.bus); + info->addr.vioserial.bus, + info->addr.vioserial.port); break; default: @@ -1190,13 +1191,14 @@ virDomainDeviceVirtioSerialAddressParseXML( virDomainDeviceVirtioSerialAddressPtr addr ) { - char *controller, *bus; + char *controller, *bus, *port; int ret = -1; memset(addr, 0, sizeof(*addr)); controller = virXMLPropString(node, "controller"); bus = virXMLPropString(node, "bus"); + port = virXMLPropString(node, "port"); if (controller && virStrToLong_ui(controller, NULL, 10, &addr->controller) < 0) { @@ -1212,6 +1214,13 @@ virDomainDeviceVirtioSerialAddressParseXML( goto cleanup; } + if (port && + virStrToLong_ui(port, NULL, 10, &addr->port) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'port' attribute")); + goto cleanup; + } + if (!virDomainDeviceVirtioSerialAddressIsValid(addr)) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Insufficient specification for " @@ -4375,6 +4384,21 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, goto error; def->channels[def->nchannels++] = chr; + + if (chr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL && + chr->info.addr.vioserial.port == 0) { + int maxport = -1; + int j; + for (j = 0 ; j < i ; j++) { + virDomainChrDefPtr thischr = def->channels[j]; + if (thischr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL && + thischr->info.addr.vioserial.controller == chr->info.addr.vioserial.controller && + thischr->info.addr.vioserial.bus == chr->info.addr.vioserial.bus && + (int)thischr->info.addr.vioserial.port > maxport) + maxport = thischr->info.addr.vioserial.port; + } + chr->info.addr.vioserial.port = maxport + 1; + } } VIR_FREE(nodes); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f87f6c8..f83de83 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -98,6 +98,7 @@ typedef virDomainDeviceVirtioSerialAddress *virDomainDeviceVirtioSerialAddressPt struct _virDomainDeviceVirtioSerialAddress { unsigned int controller; unsigned int bus; + unsigned int port; }; typedef struct _virDomainDeviceInfo virDomainDeviceInfo; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 511b9de..5521dbe 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -3312,6 +3312,9 @@ qemuBuildVirtioSerialPortDevStr(virDomainChrDefPtr dev) ",bus=" QEMU_VIRTIO_SERIAL_PREFIX "%d.%d", dev->info.addr.vioserial.controller, dev->info.addr.vioserial.bus); + virBufferVSprintf(&buf, + ",nr=%d", + dev->info.addr.vioserial.port); } virBufferVSprintf(&buf, ",chardev=%s", dev->info.alias); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args index 4097065..8e5fbe2 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args @@ -1 +1 @@ -LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device virtio-serial-pci,id=virtio-serial0,max_ports=16,vectors=4,bus=pci.0,addr=0x4 -device virtio-serial-pci,id=virtio-serial1,bus=pci.0,addr=0xa -hda /dev/HostVG/QEMUGuest1 -chardev pty,id=channel0 -device virtserialport,chardev=channel0,name=org.linux-kvm.port.0 -chardev pty,id=channel1 -device virtserialport,bus=virtio-serial1.0,chardev=channel1,name=org.linux-kvm.port.1 -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device virtio-serial-pci,id=virtio-serial0,max_ports=16,vectors=4,bus=pci.0,addr=0x4 -device virtio-serial-pci,id=virtio-serial1,bus=pci.0,addr=0xa -hda /dev/HostVG/QEMUGuest1 -chardev pty,id=channel0 -device virtserialport,chardev=channel0,name=org.linux-kvm.port.0 -chardev pty,id=channel1 -device virtserialport,bus=virtio-serial1.0,nr=0,chardev=channel1,name=org.linux-kvm.port.foo -chardev pty,id=channel2 -device virtserialport,bus=virtio-serial1.0,nr=3,chardev=channel2,name=org.linux-kvm.port.bar -chardev pty,id=channel3 -device virtserialport,bus=virtio-serial0.0,nr=0,chardev=channel3,name=org.linux-kvm.port.wizz -chardev pty,id=channel4 -device virtserialport,bus=virtio-serial1.0,nr=4,chardev=channel4,name=org.linux-kvm.port.ooh -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml index 6c3317b..04a3e1c 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml @@ -28,7 +28,19 @@ <target type='virtio' name='org.linux-kvm.port.0'/> </channel> <channel type='pty'> - <target type='virtio' name='org.linux-kvm.port.1'/> + <target type='virtio' name='org.linux-kvm.port.foo'/> + <address type='virtio-serial' controller='1' bus='0'/> + </channel> + <channel type='pty'> + <target type='virtio' name='org.linux-kvm.port.bar'/> + <address type='virtio-serial' controller='1' bus='0' port='3'/> + </channel> + <channel type='pty'> + <target type='virtio' name='org.linux-kvm.port.wizz'/> + <address type='virtio-serial' controller='0' bus='0'/> + </channel> + <channel type='pty'> + <target type='virtio' name='org.linux-kvm.port.ooh'/> <address type='virtio-serial' controller='1' bus='0'/> </channel> </devices> -- 1.6.6.1 -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list