From 2f2bac45c0a6cc7bcbf937b6e2c0c490f03362ca Mon Sep 17 00:00:00 2001 From: vinayakjeet Date: Fri, 30 Jan 2026 02:23:15 +0530 Subject: [PATCH 1/2] feat: add configurable vhost option for monitors This change adds a 'vhost' configuration option to monitors. When enabled, it allows the use of vhost-net for improved network performance in QEMU. Fixes: #410 Signed-off-by: vinayakjeet --- pkg/unikontainers/hypervisors/qemu.go | 4 ++++ pkg/unikontainers/hypervisors/vmm.go | 28 +++++++++++++++++--------- pkg/unikontainers/types/types.go | 1 + pkg/unikontainers/urunc_config.go | 5 +++++ pkg/unikontainers/urunc_config_test.go | 3 +++ 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/pkg/unikontainers/hypervisors/qemu.go b/pkg/unikontainers/hypervisors/qemu.go index 3283df13..169c6b27 100644 --- a/pkg/unikontainers/hypervisors/qemu.go +++ b/pkg/unikontainers/hypervisors/qemu.go @@ -31,6 +31,7 @@ const ( type Qemu struct { binaryPath string binary string + vhost bool } func (q *Qemu) Stop(pid int) error { @@ -95,6 +96,9 @@ func (q *Qemu) Execve(args types.ExecArgs, ukernel types.Unikernel) error { netcli += args.Net.MAC netcli += " -net tap,script=no,downscript=no,ifname=" netcli += args.Net.TapDev + if q.vhost { + netcli += ",vhost=on" + } } cmdString += netcli } else { diff --git a/pkg/unikontainers/hypervisors/vmm.go b/pkg/unikontainers/hypervisors/vmm.go index 850f7eca..2a097847 100644 --- a/pkg/unikontainers/hypervisors/vmm.go +++ b/pkg/unikontainers/hypervisors/vmm.go @@ -32,25 +32,33 @@ var vmmLog = logrus.WithField("subsystem", "monitors") type VMMFactory struct { binary string - createFunc func(binary, binaryPath string) types.VMM + createFunc func(binary, binaryPath string, config types.MonitorConfig) types.VMM } var vmmFactories = map[VmmType]VMMFactory{ SptVmm: { - binary: SptBinary, - createFunc: func(binary, binaryPath string) types.VMM { return &SPT{binary: binary, binaryPath: binaryPath} }, + binary: SptBinary, + createFunc: func(binary, binaryPath string, config types.MonitorConfig) types.VMM { + return &SPT{binary: binary, binaryPath: binaryPath} + }, }, HvtVmm: { - binary: HvtBinary, - createFunc: func(binary, binaryPath string) types.VMM { return &HVT{binary: binary, binaryPath: binaryPath} }, + binary: HvtBinary, + createFunc: func(binary, binaryPath string, config types.MonitorConfig) types.VMM { + return &HVT{binary: binary, binaryPath: binaryPath} + }, }, QemuVmm: { - binary: QemuBinary, - createFunc: func(binary, binaryPath string) types.VMM { return &Qemu{binary: binary, binaryPath: binaryPath} }, + binary: QemuBinary, + createFunc: func(binary, binaryPath string, config types.MonitorConfig) types.VMM { + return &Qemu{binary: binary, binaryPath: binaryPath, vhost: config.Vhost} + }, }, FirecrackerVmm: { - binary: FirecrackerBinary, - createFunc: func(binary, binaryPath string) types.VMM { return &Firecracker{binary: binary, binaryPath: binaryPath} }, + binary: FirecrackerBinary, + createFunc: func(binary, binaryPath string, config types.MonitorConfig) types.VMM { + return &Firecracker{binary: binary, binaryPath: binaryPath} + }, }, } @@ -80,7 +88,7 @@ func NewVMM(vmmType VmmType, monitors map[string]types.MonitorConfig) (vmm types return nil, err } - return factory.createFunc(factory.binary, vmmPath), nil + return factory.createFunc(factory.binary, vmmPath, monitors[string(vmmType)]), nil } func getVMMPath(vmmType VmmType, binary string, monitors map[string]types.MonitorConfig) (string, error) { diff --git a/pkg/unikontainers/types/types.go b/pkg/unikontainers/types/types.go index 3f434e51..9357b8c6 100644 --- a/pkg/unikontainers/types/types.go +++ b/pkg/unikontainers/types/types.go @@ -123,4 +123,5 @@ type MonitorConfig struct { DefaultVCPUs uint `toml:"default_vcpus"` BinaryPath string `toml:"path,omitempty"` // Optional path to the hypervisor binary DataPath string `toml:"data_path,omitempty"` // Optional path to the hypervisor data files (e.g. qemu bios stuff) + Vhost bool `toml:"vhost,omitempty"` // Optional: enable vhost for network performance optimization } diff --git a/pkg/unikontainers/urunc_config.go b/pkg/unikontainers/urunc_config.go index 8b8686de..b11f47cd 100644 --- a/pkg/unikontainers/urunc_config.go +++ b/pkg/unikontainers/urunc_config.go @@ -125,6 +125,7 @@ func (p *UruncConfig) Map() map[string]string { cfgMap[prefix+"default_vcpus"] = strconv.FormatUint(uint64(hvCfg.DefaultVCPUs), 10) cfgMap[prefix+"binary_path"] = hvCfg.BinaryPath cfgMap[prefix+"data_path"] = hvCfg.DataPath + cfgMap[prefix+"vhost"] = strconv.FormatBool(hvCfg.Vhost) } for eb, ebCfg := range p.ExtraBins { prefix := "urunc_config.extra_binaries." + eb + "." @@ -171,6 +172,10 @@ func UruncConfigFromMap(cfgMap map[string]string) *UruncConfig { hvCfg.BinaryPath = val case "data_path": hvCfg.DataPath = val + case "vhost": + if boolVal, err := strconv.ParseBool(val); err == nil { + hvCfg.Vhost = boolVal + } } cfg.Monitors[hv] = hvCfg } diff --git a/pkg/unikontainers/urunc_config_test.go b/pkg/unikontainers/urunc_config_test.go index 9c2be68a..359e3a29 100644 --- a/pkg/unikontainers/urunc_config_test.go +++ b/pkg/unikontainers/urunc_config_test.go @@ -27,6 +27,7 @@ const ( testQemuVCPUsKey = "urunc_config.monitors.qemu.default_vcpus" testQemuBinaryKey = "urunc_config.monitors.qemu.binary_path" testQemuDataKey = "urunc_config.monitors.qemu.data_path" + testQemuVhostKey = "urunc_config.monitors.qemu.vhost" testHvtMemoryKey = "urunc_config.monitors.hvt.default_memory_mb" testVirtiofsdPathKey = "urunc_config.extra_binaries.virtiofsd.path" testVirtiofsdOptsKey = "urunc_config.extra_binaries.virtiofsd.options" @@ -56,6 +57,7 @@ func TestUruncConfigFromMap(t *testing.T) { testQemuVCPUsKey: "2", testQemuBinaryKey: testQemuBinaryPath, testQemuDataKey: testQemuDataPath, + testQemuVhostKey: "true", } config := UruncConfigFromMap(cfgMap) @@ -67,6 +69,7 @@ func TestUruncConfigFromMap(t *testing.T) { assert.Equal(t, uint(2), qemuConfig.DefaultVCPUs) assert.Equal(t, testQemuBinaryPath, qemuConfig.BinaryPath) assert.Equal(t, testQemuDataPath, qemuConfig.DataPath) + assert.True(t, qemuConfig.Vhost) }) t.Run("multiple monitors", func(t *testing.T) { From ce47b492938567a2cb1a4c9d5114bddeeee6f029 Mon Sep 17 00:00:00 2001 From: vinayakjeet Date: Sun, 1 Feb 2026 02:50:22 +0530 Subject: [PATCH 2/2] fix(lint): rename unused config parameter to _ in VMM factories Signed-off-by: vinayakjeet --- pkg/unikontainers/hypervisors/vmm.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/unikontainers/hypervisors/vmm.go b/pkg/unikontainers/hypervisors/vmm.go index 2a097847..66726869 100644 --- a/pkg/unikontainers/hypervisors/vmm.go +++ b/pkg/unikontainers/hypervisors/vmm.go @@ -38,13 +38,13 @@ type VMMFactory struct { var vmmFactories = map[VmmType]VMMFactory{ SptVmm: { binary: SptBinary, - createFunc: func(binary, binaryPath string, config types.MonitorConfig) types.VMM { + createFunc: func(binary, binaryPath string, _ types.MonitorConfig) types.VMM { return &SPT{binary: binary, binaryPath: binaryPath} }, }, HvtVmm: { binary: HvtBinary, - createFunc: func(binary, binaryPath string, config types.MonitorConfig) types.VMM { + createFunc: func(binary, binaryPath string, _ types.MonitorConfig) types.VMM { return &HVT{binary: binary, binaryPath: binaryPath} }, }, @@ -56,7 +56,7 @@ var vmmFactories = map[VmmType]VMMFactory{ }, FirecrackerVmm: { binary: FirecrackerBinary, - createFunc: func(binary, binaryPath string, config types.MonitorConfig) types.VMM { + createFunc: func(binary, binaryPath string, _ types.MonitorConfig) types.VMM { return &Firecracker{binary: binary, binaryPath: binaryPath} }, },