Merge pull request #111 from slp/multiple_transports

Refactor code to support multiple virtio transports at runtime
This commit is contained in:
Mark Ryan
2020-02-18 13:51:07 +01:00
committed by GitHub
7 changed files with 566 additions and 383 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,112 +0,0 @@
// +build !s390x
/*
// Copyright contributors to the Virtual Machine Manager for Go project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
package qemu
const (
// Virtio9P is the 9pfs device driver.
Virtio9P DeviceDriver = "virtio-9p-pci"
// VirtioSerial is the serial device driver.
VirtioSerial DeviceDriver = "virtio-serial-pci"
// VirtioNet is the virt-io pci networking device driver.
VirtioNet DeviceDriver = VirtioNetPCI
// Vfio is the vfio driver
Vfio DeviceDriver = "vfio-pci"
// VirtioScsi is the virtio-scsi device
VirtioScsi DeviceDriver = "virtio-scsi-pci"
// VHostVSock is a generic Vsock vhost device
VHostVSock DeviceDriver = "vhost-vsock-pci"
)
// isVirtioPCI is a map indicating if a DeviceDriver is considered as a
// virtio PCI device, which is helpful to determine if the option "romfile"
// applies or not to this specific device.
var isVirtioPCI = map[DeviceDriver]bool{
NVDIMM: false,
Virtio9P: true,
VirtioNetPCI: true,
VirtioSerial: true,
VirtioBlock: true,
VirtioBlockPCI: true,
Console: false,
VirtioSerialPort: false,
VHostVSock: true,
VirtioRng: true,
VirtioBalloon: true,
VhostUserSCSI: true,
VhostUserBlk: true,
Vfio: true,
VirtioScsi: true,
PCIBridgeDriver: true,
PCIePCIBridgeDriver: true,
PCIeRootPort: true,
}
// isVirtioCCW is a dummy map to return always false on no-s390x arch
var isVirtioCCW = map[DeviceDriver]bool{}
// QemuNetdevParam converts to the QEMU -netdev parameter notation
func (n NetDeviceType) QemuNetdevParam() string {
switch n {
case TAP:
return "tap"
case MACVTAP:
return "tap"
case IPVTAP:
return "tap"
case VETHTAP:
return "tap" // -netdev type=tap -device virtio-net-pci
case VFIO:
return "" // -device vfio-pci (no netdev)
case VHOSTUSER:
return "vhost-user" // -netdev type=vhost-user (no device)
default:
return ""
}
}
// QemuDeviceParam converts to the QEMU -device parameter notation
func (n NetDeviceType) QemuDeviceParam() DeviceDriver {
switch n {
case TAP:
return "virtio-net-pci"
case MACVTAP:
return "virtio-net-pci"
case IPVTAP:
return "virtio-net-pci"
case VETHTAP:
return "virtio-net-pci" // -netdev type=tap -device virtio-net-pci
case VFIO:
return "vfio-pci" // -device vfio-pci (no netdev)
case VHOSTUSER:
return "" // -netdev type=vhost-user (no device)
default:
return ""
}
}
func isDimmSupported() bool {
return true
}

View File

@@ -36,7 +36,7 @@ var (
deviceSCSIControllerBusAddrStr = "-device virtio-scsi-pci,id=foo,bus=pci.0,addr=00:04.0,disable-modern=true,iothread=iothread1,romfile=efi-virtio.rom"
deviceVhostUserSCSIString = "-chardev socket,id=char1,path=/tmp/nonexistentsocket.socket -device vhost-user-scsi-pci,id=scsi1,chardev=char1,romfile=efi-virtio.rom"
deviceVhostUserBlkString = "-chardev socket,id=char2,path=/tmp/nonexistentsocket.socket -device vhost-user-blk-pci,logical_block_size=4096,size=512M,chardev=char2,romfile=efi-virtio.rom"
deviceBlockString = "-device virtio-blk,disable-modern=true,drive=hd0,scsi=off,config-wce=off,romfile=efi-virtio.rom -drive id=hd0,file=/var/lib/vm.img,aio=threads,format=qcow2,if=none"
deviceBlockString = "-device virtio-blk-pci,disable-modern=true,drive=hd0,scsi=off,config-wce=off,romfile=efi-virtio.rom -drive id=hd0,file=/var/lib/vm.img,aio=threads,format=qcow2,if=none"
devicePCIBridgeString = "-device pci-bridge,bus=/pci-bus/pcie.0,id=mybridge,chassis_nr=5,shpc=on,addr=ff,romfile=efi-virtio.rom"
devicePCIEBridgeString = "-device pcie-pci-bridge,bus=/pci-bus/pcie.0,id=mybridge,addr=ff,romfile=efi-virtio.rom"
romfile = "efi-virtio.rom"
@@ -81,7 +81,7 @@ func TestAppendVirtioBalloon(t *testing.T) {
ROMFile: romfile,
}
var deviceString = "-device " + string(VirtioBalloon)
var deviceString = "-device " + string(VirtioBalloon) + "-" + string(TransportPCI)
deviceString += ",id=" + balloonDevice.ID + ",romfile=" + balloonDevice.ROMFile
var OnDeflateOnOMM = ",deflate-on-oom=on"
@@ -158,9 +158,6 @@ func TestAppendDeviceVFIOPCIe(t *testing.T) {
BDF: "02:00.0",
Bus: pcieRootPortID,
}
if isVirtioCCW[Vfio] {
vfioDevice.DevNo = DevNo
}
testAppend(vfioDevice, deviceVFIOPCIeSimpleString, t)
// full test
@@ -172,8 +169,5 @@ func TestAppendDeviceVFIOPCIe(t *testing.T) {
VendorID: "0x10de",
DeviceID: "0x15f8",
}
if isVirtioCCW[Vfio] {
vfioDevice.DevNo = DevNo
}
testAppend(vfioDevice, deviceVFIOPCIeFullString, t)
}

View File

@@ -1,140 +0,0 @@
// +build s390x
/*
// Copyright contributors to the Virtual Machine Manager for Go project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
package qemu
import "log"
// IBM Z uses CCW devices intead of PCI devices.
// See https://wiki.qemu.org/Documentation/Platforms/S390X
const (
// Virtio9P is the 9pfs device driver.
Virtio9P DeviceDriver = "virtio-9p-ccw"
// VirtioSerial is the serial device driver.
VirtioSerial DeviceDriver = "virtio-serial-ccw"
// VirtioNet is the virt-io ccw networking device driver.
VirtioNet DeviceDriver = VirtioNetCCW
// Vfio is the vfio driver
Vfio DeviceDriver = "vfio-ccw"
// VirtioScsi is the virtio-scsi device
VirtioScsi DeviceDriver = "virtio-scsi-ccw"
// VHostVSock is a generic Vsock Device
VHostVSock DeviceDriver = "vhost-vsock-ccw"
)
// isVirtioPCI is a fake map on s390x to always avoid the "romfile"
// option
var isVirtioPCI = map[DeviceDriver]bool{
NVDIMM: false,
Virtio9P: false,
VirtioNetCCW: false,
VirtioSerial: false,
VirtioBlock: false,
Console: false,
VirtioSerialPort: false,
VHostVSock: false,
VirtioRng: false,
VirtioBalloon: false,
VhostUserSCSI: false,
VhostUserBlk: false,
Vfio: false,
VirtioScsi: false,
PCIBridgeDriver: false,
PCIePCIBridgeDriver: false,
}
// isVirtioCCW returns if the device is a ccw device
var isVirtioCCW = map[DeviceDriver]bool{
NVDIMM: false,
Virtio9P: true,
VirtioNetCCW: true,
VirtioSerial: true,
VirtioBlock: true,
VirtioBlockCCW: true,
Console: false,
VirtioSerialPort: false,
VHostVSock: true,
VirtioRng: true,
VirtioBalloon: true,
VhostUserSCSI: false,
VhostUserBlk: false,
Vfio: true,
VirtioScsi: true,
PCIBridgeDriver: false,
PCIePCIBridgeDriver: false,
}
// QemuDeviceParam converts to the QEMU -device parameter notation
// This function has been reimplemented for the s390x architecture to deal
// with the VHOSTUSER case. Vhost user devices are not implemented on s390x
// architecture. For further details see issue
// https://github.com/kata-containers/runtime/issues/659
func (n NetDeviceType) QemuDeviceParam() string {
switch n {
case TAP:
return string(VirtioNet)
case MACVTAP:
return string(VirtioNet)
case IPVTAP:
return string(VirtioNet)
case VETHTAP:
return string(VirtioNet)
case VFIO:
return string(Vfio)
case VHOSTUSER:
log.Fatal("vhost-user devices are not supported on IBM Z")
return ""
default:
return ""
}
}
// QemuNetdevParam converts to the QEMU -netdev parameter notation
// This function has been reimplemented for the s390x architecture to deal
// with the VHOSTUSER case. Vhost user devices are not implemented on s390x
// architecture. For further details see issue
// https://github.com/kata-containers/runtime/issues/659
func (n NetDeviceType) QemuNetdevParam() string {
switch n {
case TAP:
return "tap"
case MACVTAP:
return "tap"
case IPVTAP:
return "tap"
case VETHTAP:
return "tap"
case VFIO:
return ""
case VHOSTUSER:
log.Fatal("vhost-user devices are not supported on IBM Z")
return ""
default:
return ""
}
}
func isDimmSupported() bool {
return false
}

View File

@@ -31,7 +31,7 @@ var (
deviceVFIOString = "-device vfio-ccw,host=02:10.0,devno=" + DevNo
deviceSCSIControllerStr = "-device virtio-scsi-ccw,id=foo,devno=" + DevNo
deviceSCSIControllerBusAddrStr = "-device virtio-scsi-ccw,id=foo,bus=pci.0,addr=00:04.0,iothread=iothread1,devno=" + DevNo
deviceBlockString = "-device virtio-blk,drive=hd0,scsi=off,config-wce=off,devno=" + DevNo + " -drive id=hd0,file=/var/lib/vm.img,aio=threads,format=qcow2,if=none"
deviceBlockString = "-device virtio-blk-ccw,drive=hd0,scsi=off,config-wce=off,devno=" + DevNo + " -drive id=hd0,file=/var/lib/vm.img,aio=threads,format=qcow2,if=none"
devicePCIBridgeString = "-device pci-bridge,bus=/pci-bus/pcie.0,id=mybridge,chassis_nr=5,shpc=on,addr=ff"
devicePCIEBridgeString = "-device pcie-pci-bridge,bus=/pci-bus/pcie.0,id=mybridge,addr=ff"
romfile = ""
@@ -42,7 +42,7 @@ func TestAppendVirtioBalloon(t *testing.T) {
ID: "balloon",
}
var deviceString = "-device " + string(VirtioBalloon)
var deviceString = "-device " + string(VirtioBalloon) + "-" + string(TransportCCW)
deviceString += ",id=" + balloonDevice.ID
balloonDevice.DevNo = DevNo
devnoOptios := ",devno=" + DevNo

View File

@@ -143,7 +143,7 @@ func TestAppendDeviceFS(t *testing.T) {
ROMFile: "efi-virtio.rom",
}
if isVirtioCCW[fsdev.Driver] {
if fsdev.Transport.isVirtioCCW(nil) {
fsdev.DevNo = DevNo
}
@@ -164,7 +164,7 @@ func TestAppendDeviceNetwork(t *testing.T) {
ROMFile: "efi-virtio.rom",
}
if isVirtioCCW[netdev.Driver] {
if netdev.Transport.isVirtioCCW(nil) {
netdev.DevNo = DevNo
}
@@ -195,7 +195,7 @@ func TestAppendDeviceNetworkMq(t *testing.T) {
DisableModern: true,
ROMFile: "efi-virtio.rom",
}
if isVirtioCCW[netdev.Driver] {
if netdev.Transport.isVirtioCCW(nil) {
netdev.DevNo = DevNo
}
@@ -219,7 +219,7 @@ func TestAppendDeviceNetworkPCI(t *testing.T) {
ROMFile: romfile,
}
if !isVirtioPCI[netdev.Driver] {
if !netdev.Transport.isVirtioPCI(nil) {
t.Skip("Test valid only for PCI devices")
}
@@ -253,7 +253,7 @@ func TestAppendDeviceNetworkPCIMq(t *testing.T) {
ROMFile: romfile,
}
if !isVirtioPCI[netdev.Driver] {
if !netdev.Transport.isVirtioPCI(nil) {
t.Skip("Test valid only for PCI devices")
}
@@ -267,7 +267,7 @@ func TestAppendDeviceSerial(t *testing.T) {
DisableModern: true,
ROMFile: romfile,
}
if isVirtioCCW[sdev.Driver] {
if sdev.Transport.isVirtioCCW(nil) {
sdev.DevNo = DevNo
}
@@ -285,7 +285,7 @@ func TestAppendDeviceSerialPort(t *testing.T) {
Path: "/tmp/char.sock",
Name: "channel.0",
}
if isVirtioCCW[chardev.Driver] {
if chardev.Transport.isVirtioCCW(nil) {
chardev.DevNo = DevNo
}
testAppend(chardev, deviceSerialPortString, t)
@@ -304,7 +304,7 @@ func TestAppendDeviceBlock(t *testing.T) {
DisableModern: true,
ROMFile: romfile,
}
if isVirtioCCW[blkdev.Driver] {
if blkdev.Transport.isVirtioCCW(nil) {
blkdev.DevNo = DevNo
}
testAppend(blkdev, deviceBlockString, t)
@@ -318,7 +318,7 @@ func TestAppendDeviceVFIO(t *testing.T) {
DeviceID: "0x5678",
}
if isVirtioCCW[Vfio] {
if vfioDevice.Transport.isVirtioCCW(nil) {
vfioDevice.DevNo = DevNo
}
@@ -334,7 +334,7 @@ func TestAppendVSOCK(t *testing.T) {
ROMFile: romfile,
}
if isVirtioCCW[VHostVSock] {
if vsockDevice.Transport.isVirtioCCW(nil) {
vsockDevice.DevNo = DevNo
}
@@ -368,16 +368,19 @@ func TestVSOCKValid(t *testing.T) {
func TestAppendVirtioRng(t *testing.T) {
var objectString = "-object rng-random,id=rng0"
var deviceString = "-device " + string(VirtioRng) + ",rng=rng0"
if romfile != "" {
deviceString = deviceString + ",romfile=efi-virtio.rom"
}
var deviceString = "-device " + string(VirtioRng)
rngDevice := RngDevice{
ID: "rng0",
ROMFile: romfile,
}
if isVirtioCCW[VirtioRng] {
deviceString += "-" + string(rngDevice.Transport.getName(nil)) + ",rng=rng0"
if romfile != "" {
deviceString = deviceString + ",romfile=efi-virtio.rom"
}
if rngDevice.Transport.isVirtioCCW(nil) {
rngDevice.DevNo = DevNo
deviceString += ",devno=" + rngDevice.DevNo
}
@@ -438,7 +441,7 @@ func TestAppendDeviceSCSIController(t *testing.T) {
ROMFile: romfile,
}
if isVirtioCCW[VirtioScsi] {
if scsiCon.Transport.isVirtioCCW(nil) {
scsiCon.DevNo = DevNo
}
@@ -521,7 +524,7 @@ func TestAppendKnobsAllFalse(t *testing.T) {
}
func TestAppendMemoryHugePages(t *testing.T) {
if !isDimmSupported() {
if !isDimmSupported(nil) {
t.Skip("Dimm not supported")
}
@@ -549,7 +552,7 @@ func TestAppendMemoryHugePages(t *testing.T) {
}
func TestAppendMemoryMemPrealloc(t *testing.T) {
if !isDimmSupported() {
if !isDimmSupported(nil) {
t.Skip("Dimm not supported")
}
@@ -575,7 +578,7 @@ func TestAppendMemoryMemPrealloc(t *testing.T) {
}
func TestAppendMemoryMemShared(t *testing.T) {
if !isDimmSupported() {
if !isDimmSupported(nil) {
t.Skip("Dimm not supported")
}
@@ -601,7 +604,7 @@ func TestAppendMemoryMemShared(t *testing.T) {
}
func TestAppendMemoryFileBackedMem(t *testing.T) {
if !isDimmSupported() {
if !isDimmSupported(nil) {
t.Skip("Dimm not supported")
}
@@ -627,7 +630,7 @@ func TestAppendMemoryFileBackedMem(t *testing.T) {
}
func TestAppendMemoryFileBackedMemPrealloc(t *testing.T) {
if !isDimmSupported() {
if !isDimmSupported(nil) {
t.Skip("Dimm not supported")
}

View File

@@ -846,7 +846,9 @@ func (q *QMP) ExecuteDeviceAdd(ctx context.Context, blockdevID, devID, driver, b
"drive": blockdevID,
}
if isVirtioCCW[DeviceDriver(driver)] {
var transport VirtioTransport
if transport.isVirtioCCW(nil) {
args["devno"] = bus
} else if bus != "" {
args["bus"] = bus
@@ -855,7 +857,7 @@ func (q *QMP) ExecuteDeviceAdd(ctx context.Context, blockdevID, devID, driver, b
if shared && (q.version.Major > 2 || (q.version.Major == 2 && q.version.Minor >= 10)) {
args["share-rw"] = "on"
}
if isVirtioPCI[DeviceDriver(driver)] {
if transport.isVirtioPCI(nil) {
args["romfile"] = romfile
if disableModern {
@@ -897,12 +899,7 @@ func (q *QMP) ExecuteSCSIDeviceAdd(ctx context.Context, blockdevID, devID, drive
"id": devID,
"driver": driver,
"drive": blockdevID,
}
if isVirtioCCW[DeviceDriver(driver)] {
args["devno"] = bus
} else {
args["bus"] = bus
"bus": bus,
}
if scsiID >= 0 {
@@ -914,13 +911,6 @@ func (q *QMP) ExecuteSCSIDeviceAdd(ctx context.Context, blockdevID, devID, drive
if shared && (q.version.Major > 2 || (q.version.Major == 2 && q.version.Minor >= 10)) {
args["share-rw"] = "on"
}
if isVirtioPCI[DeviceDriver(driver)] {
args["romfile"] = romfile
if disableModern {
args["disable-modern"] = disableModern
}
}
return q.executeCommand(ctx, "device_add", args, nil)
}
@@ -1124,7 +1114,10 @@ func (q *QMP) ExecutePCIDeviceAdd(ctx context.Context, blockdevID, devID, driver
if queues > 0 {
args["num-queues"] = strconv.Itoa(queues)
}
if isVirtioPCI[DeviceDriver(driver)] {
var transport VirtioTransport
if transport.isVirtioPCI(nil) {
args["romfile"] = romfile
if disableModern {
@@ -1161,9 +1154,18 @@ func (q *QMP) ExecutePCIVhostUserDevAdd(ctx context.Context, driver, devID, char
// bdf is the PCI bus-device-function of the pci device.
// bus is optional. When hot plugging a PCIe device, the bus can be the ID of the pcie-root-port.
func (q *QMP) ExecuteVFIODeviceAdd(ctx context.Context, devID, bdf, bus, romfile string) error {
var driver string
var transport VirtioTransport
if transport.isVirtioCCW(nil) {
driver = string(VfioCCW)
} else {
driver = string(VfioPCI)
}
args := map[string]interface{}{
"id": devID,
"driver": Vfio,
"driver": driver,
"host": bdf,
"romfile": romfile,
}
@@ -1181,7 +1183,7 @@ func (q *QMP) ExecuteVFIODeviceAdd(ctx context.Context, devID, bdf, bus, romfile
func (q *QMP) ExecutePCIVFIODeviceAdd(ctx context.Context, devID, bdf, addr, bus, romfile string) error {
args := map[string]interface{}{
"id": devID,
"driver": Vfio,
"driver": VfioPCI,
"host": bdf,
"addr": addr,
"romfile": romfile,
@@ -1201,7 +1203,7 @@ func (q *QMP) ExecutePCIVFIODeviceAdd(ctx context.Context, devID, bdf, addr, bus
func (q *QMP) ExecutePCIVFIOMediatedDeviceAdd(ctx context.Context, devID, sysfsdev, addr, bus, romfile string) error {
args := map[string]interface{}{
"id": devID,
"driver": Vfio,
"driver": VfioPCI,
"sysfsdev": sysfsdev,
"romfile": romfile,
}
@@ -1265,10 +1267,6 @@ func (q *QMP) ExecuteCPUDeviceAdd(ctx context.Context, driver, cpuID, socketID,
}
}
if isVirtioPCI[DeviceDriver(driver)] {
args["romfile"] = romfile
}
return q.executeCommand(ctx, "device_add", args, nil)
}
@@ -1477,7 +1475,7 @@ func (q *QMP) ExecuteBalloon(ctx context.Context, bytes uint64) error {
// 1.0 in nested environments.
func (q *QMP) ExecutePCIVSockAdd(ctx context.Context, id, guestCID, vhostfd, addr, bus, romfile string, disableModern bool) error {
args := map[string]interface{}{
"driver": VHostVSock,
"driver": VHostVSockPCI,
"id": id,
"guest-cid": guestCID,
"vhostfd": vhostfd,