Skip to content

Commit f72c9e5

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Allow tap interface with multiqueue"
2 parents e0f088c + 84cfc8e commit f72c9e5

File tree

3 files changed

+111
-18
lines changed

3 files changed

+111
-18
lines changed

nova/tests/unit/virt/libvirt/test_vif.py

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,10 +1057,71 @@ def test_tap_ethernet_vif_driver(self):
10571057
@mock.patch('nova.privsep.linux_net.device_exists', return_value=True)
10581058
@mock.patch('nova.privsep.linux_net.set_device_mtu')
10591059
@mock.patch('nova.privsep.linux_net.create_tap_dev')
1060-
def test_plug_tap(self, mock_create_tap_dev, mock_set_mtu,
1060+
def test_plug_tap_kvm_virtio(self, mock_create_tap_dev, mock_set_mtu,
10611061
mock_device_exists):
1062-
d = vif.LibvirtGenericVIFDriver()
1063-
d.plug(self.instance, self.vif_tap)
1062+
1063+
d1 = vif.LibvirtGenericVIFDriver()
1064+
ins = objects.Instance(
1065+
id=1, uuid='f0000000-0000-0000-0000-000000000001',
1066+
project_id=723, system_metadata={}
1067+
)
1068+
d1.plug(ins, self.vif_tap)
1069+
mock_create_tap_dev.assert_called_once_with('tap-xxx-yyy-zzz', None,
1070+
multiqueue=False)
1071+
1072+
mock_create_tap_dev.reset_mock()
1073+
1074+
d2 = vif.LibvirtGenericVIFDriver()
1075+
mq_ins = objects.Instance(
1076+
id=1, uuid='f0000000-0000-0000-0000-000000000001',
1077+
project_id=723, system_metadata={
1078+
'image_hw_vif_multiqueue_enabled': 'True'
1079+
}
1080+
)
1081+
d2.plug(mq_ins, self.vif_tap)
1082+
mock_create_tap_dev.assert_called_once_with('tap-xxx-yyy-zzz', None,
1083+
multiqueue=True)
1084+
1085+
@mock.patch('nova.privsep.linux_net.device_exists', return_value=True)
1086+
@mock.patch('nova.privsep.linux_net.set_device_mtu')
1087+
@mock.patch('nova.privsep.linux_net.create_tap_dev')
1088+
def test_plug_tap_mq_ignored_virt_type(
1089+
self, mock_create_tap_dev, mock_set_mtu, mock_device_exists):
1090+
1091+
self.flags(use_virtio_for_bridges=True,
1092+
virt_type='xen',
1093+
group='libvirt')
1094+
1095+
d1 = vif.LibvirtGenericVIFDriver()
1096+
ins = objects.Instance(
1097+
id=1, uuid='f0000000-0000-0000-0000-000000000001',
1098+
project_id=723, system_metadata={
1099+
'image_hw_vif_multiqueue_enabled': 'True'
1100+
}
1101+
)
1102+
d1.plug(ins, self.vif_tap)
1103+
mock_create_tap_dev.assert_called_once_with('tap-xxx-yyy-zzz',
1104+
None,
1105+
multiqueue=False)
1106+
1107+
@mock.patch('nova.privsep.linux_net.device_exists', return_value=True)
1108+
@mock.patch('nova.privsep.linux_net.set_device_mtu')
1109+
@mock.patch('nova.privsep.linux_net.create_tap_dev')
1110+
def test_plug_tap_mq_ignored_vif_model(
1111+
self, mock_create_tap_dev, mock_set_mtu, mock_device_exists):
1112+
1113+
d1 = vif.LibvirtGenericVIFDriver()
1114+
ins = objects.Instance(
1115+
id=1, uuid='f0000000-0000-0000-0000-000000000001',
1116+
project_id=723, system_metadata={
1117+
'image_hw_vif_multiqueue_enabled': 'True',
1118+
'image_hw_vif_model': 'e1000',
1119+
}
1120+
)
1121+
d1.plug(ins, self.vif_tap)
1122+
mock_create_tap_dev.assert_called_once_with('tap-xxx-yyy-zzz',
1123+
None,
1124+
multiqueue=False)
10641125

10651126
def test_unplug_tap(self):
10661127
d = vif.LibvirtGenericVIFDriver()

nova/virt/libvirt/vif.py

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,24 @@ def get_vif_devname(self, vif):
157157
return vif['devname']
158158
return ("nic" + vif['id'])[:network_model.NIC_NAME_LEN]
159159

160+
def get_vif_model(self, image_meta=None, vif_model=None):
161+
162+
model = vif_model
163+
164+
# If the user has specified a 'vif_model' against the
165+
# image then honour that model
166+
if image_meta:
167+
model = osinfo.HardwareProperties(image_meta).network_model
168+
169+
# If the virt type is KVM/QEMU/VZ(Parallels), then use virtio according
170+
# to the global config parameter
171+
if (model is None and CONF.libvirt.virt_type in
172+
('kvm', 'qemu', 'parallels') and
173+
CONF.libvirt.use_virtio_for_bridges):
174+
model = network_model.VIF_MODEL_VIRTIO
175+
176+
return model
177+
160178
def get_base_config(self, instance, mac, image_meta,
161179
inst_type, virt_type, vnic_type):
162180
# TODO(sahid): We should rewrite it. This method handles too
@@ -179,16 +197,9 @@ def get_base_config(self, instance, mac, image_meta,
179197

180198
rx_queue_size = CONF.libvirt.rx_queue_size
181199

182-
# If the user has specified a 'vif_model' against the
183-
# image then honour that model
184-
if image_meta:
185-
model = osinfo.HardwareProperties(image_meta).network_model
186-
187-
# If the virt type is KVM/QEMU/VZ(Parallels), then use virtio according
188-
# to the global config parameter
189-
if (model is None and virt_type in ('kvm', 'qemu', 'parallels') and
190-
CONF.libvirt.use_virtio_for_bridges):
191-
model = network_model.VIF_MODEL_VIRTIO
200+
# if model has already been defined,
201+
# image_meta contents will override it
202+
model = self.get_vif_model(image_meta=image_meta, vif_model=model)
192203

193204
if not is_vif_model_valid_for_virt(virt_type, model):
194205
raise exception.UnsupportedHardware(model=model, virt=virt_type)
@@ -244,10 +255,7 @@ def _get_virtio_mq_settings(self, image_meta, flavor):
244255
"""
245256
driver = None
246257
vhost_queues = None
247-
if not isinstance(image_meta, objects.ImageMeta):
248-
image_meta = objects.ImageMeta.from_dict(image_meta)
249-
img_props = image_meta.properties
250-
if img_props.get('hw_vif_multiqueue_enabled'):
258+
if self._requests_multiqueue(image_meta):
251259
driver = 'vhost'
252260
max_tap_queues = self._get_max_tap_queues()
253261
if max_tap_queues:
@@ -258,6 +266,19 @@ def _get_virtio_mq_settings(self, image_meta, flavor):
258266

259267
return (driver, vhost_queues)
260268

269+
def _requests_multiqueue(self, image_meta):
270+
"""Check if multiqueue property is set in the image metadata."""
271+
272+
if not isinstance(image_meta, objects.ImageMeta):
273+
image_meta = objects.ImageMeta.from_dict(image_meta)
274+
275+
img_props = image_meta.properties
276+
277+
if img_props.get('hw_vif_multiqueue_enabled'):
278+
return True
279+
280+
return False
281+
261282
def _get_max_tap_queues(self):
262283
# Note(sean-k-mooney): some linux distros have backported
263284
# changes for newer kernels which make the kernel version
@@ -641,7 +662,13 @@ def plug_tap(self, instance, vif):
641662
"""Plug a VIF_TYPE_TAP virtual interface."""
642663
dev = self.get_vif_devname(vif)
643664
mac = vif['details'].get(network_model.VIF_DETAILS_TAP_MAC_ADDRESS)
644-
nova.privsep.linux_net.create_tap_dev(dev, mac)
665+
image_meta = instance.image_meta
666+
vif_model = self.get_vif_model(image_meta=image_meta)
667+
# TODO(ganso): explore whether multiqueue works for other vif models
668+
# that go through this code path.
669+
multiqueue = (self._requests_multiqueue(image_meta) and
670+
vif_model == network_model.VIF_MODEL_VIRTIO)
671+
nova.privsep.linux_net.create_tap_dev(dev, mac, multiqueue=multiqueue)
645672
network = vif.get('network')
646673
mtu = network.get_meta('mtu') if network else None
647674
nova.privsep.linux_net.set_device_mtu(dev, mtu)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
fixes:
3+
- |
4+
Addressed an issue that prevented instances using multiqueue feature from
5+
being created successfully when their vif_type is TAP.

0 commit comments

Comments
 (0)