diff --git a/nova/conf/libvirt.py b/nova/conf/libvirt.py index 0ee880af4774..1364c8ed0b48 100644 --- a/nova/conf/libvirt.py +++ b/nova/conf/libvirt.py @@ -1319,6 +1319,14 @@ Configure virtio tx queue size. This option is only usable for virtio-net device with vhost-user backend. Available only with QEMU/KVM. Requires libvirt v3.7 QEMU v2.10."""), + cfg.IntOpt('max_queues', default=None, min=1, help=""" +The maximum number of virtio queue pairs that can be enabled +when creating a multiqueue guest. The number of virtio queues +allocated will be the lesser of the CPUs requested by the guest +and the max value defined. By default, this value is set to none +meaning the legacy limits based on the reported kernel +major version will be used. +"""), ] diff --git a/nova/tests/unit/virt/libvirt/test_vif.py b/nova/tests/unit/virt/libvirt/test_vif.py index 209211c563bf..379948d95e6a 100644 --- a/nova/tests/unit/virt/libvirt/test_vif.py +++ b/nova/tests/unit/virt/libvirt/test_vif.py @@ -657,6 +657,21 @@ class LibvirtVifTestCase(test.NoDBTestCase): def test_virtio_multiqueue_in_kernel_4(self, mock_uname): self._test_virtio_multiqueue(10, '10') + @mock.patch('os.uname', return_value=('Linux', '', '2.6.32-21-generic')) + def test_virtio_multiqueue_in_kernel_2_max_queues(self, mock_uname): + self.flags(max_queues=2, group='libvirt') + self._test_virtio_multiqueue(10, '2') + + @mock.patch('os.uname', return_value=('Linux', '', '3.19.0-47-generic')) + def test_virtio_multiqueue_in_kernel_3_max_queues(self, mock_uname): + self.flags(max_queues=2, group='libvirt') + self._test_virtio_multiqueue(10, '2') + + @mock.patch('os.uname', return_value=('Linux', '', '4.2.0-35-generic')) + def test_virtio_multiqueue_in_kernel_4_max_queues(self, mock_uname): + self.flags(max_queues=2, group='libvirt') + self._test_virtio_multiqueue(10, '2') + def test_vhostuser_os_vif_multiqueue(self): d = vif.LibvirtGenericVIFDriver() hostimpl = host.Host("qemu:///system") diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index d4801ad887fa..c03548d007d0 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -248,6 +248,13 @@ class LibvirtGenericVIFDriver(object): return False def _get_max_tap_queues(self): + # Note(sean-k-mooney): some linux distros have backported + # changes for newer kernels which make the kernel version + # number unreliable to determine the max queues supported + # To address this without making the code distro dependent + # we introduce a new config option and prefer it if set. + if CONF.libvirt.max_queues: + return CONF.libvirt.max_queues # NOTE(kengo.sakai): In kernels prior to 3.0, # multiple queues on a tap interface is not supported. # In kernels 3.x, the number of queues on a tap interface diff --git a/releasenotes/notes/virtio-max-queues-27f73e988c7e66ba.yaml b/releasenotes/notes/virtio-max-queues-27f73e988c7e66ba.yaml new file mode 100644 index 000000000000..845f0c258fde --- /dev/null +++ b/releasenotes/notes/virtio-max-queues-27f73e988c7e66ba.yaml @@ -0,0 +1,15 @@ +--- +other: + - | + The nova libvirt virt driver supports creating instances with multi-queue + virtio network interfaces. In previous releases nova has based the maximum + number of virtio queue pairs that can be allocated on the reported kernel + major version. It has been reported in `bug #1847367`_ that some distros have + backported changes from later major versions that make major version + number no longer suitable to determine the maximum virtio queue pair count. + A new config option has been added to the libvirt section of the nova.conf. + When defined nova will now use the ``[libvirt]/max_queues`` option to + define the max queues that can be configured, if undefined it will + fallback to the previous kernel version approach. + + .. _`bug #1847367`: https://bugs.launchpad.net/nova/+bug/1847367