diff --git a/lower-constraints.txt b/lower-constraints.txt index 9f0a6359f7c5..fcb8f308e9b6 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -70,7 +70,7 @@ os-brick==2.6.1 os-client-config==1.29.0 os-service-types==1.2.0 os-traits==0.4.0 -os-vif==1.7.0 +os-vif==1.14.0 os-win==3.0.0 os-xenapi==0.3.3 osc-lib==1.10.0 diff --git a/nova/network/os_vif_util.py b/nova/network/os_vif_util.py index a2aa46243268..207ba4182570 100644 --- a/nova/network/os_vif_util.py +++ b/nova/network/os_vif_util.py @@ -436,6 +436,38 @@ def _nova_to_osvif_vif_vrouter(vif): plugin="vrouter", vif_name=_get_vif_name(vif) ) + elif vnic_type == model.VNIC_TYPE_DIRECT: + datapath_offload = objects.vif.DatapathOffloadRepresentor( + representor_name=_get_vif_name(vif), + representor_address=vif["profile"]["pci_slot"] + ) + profile = objects.vif.VIFPortProfileBase( + datapath_offload=datapath_offload + ) + obj = _get_vif_instance( + vif, + objects.vif.VIFHostDevice, + port_profile=profile, + plugin="vrouter", + dev_address=vif["profile"]["pci_slot"], + dev_type=objects.fields.VIFHostDeviceDevType.ETHERNET + ) + elif vnic_type == model.VNIC_TYPE_VIRTIO_FORWARDER: + datapath_offload = objects.vif.DatapathOffloadRepresentor( + representor_name=_get_vif_name(vif), + representor_address=vif["profile"]["pci_slot"] + ) + profile = objects.vif.VIFPortProfileBase( + datapath_offload=datapath_offload + ) + obj = _get_vif_instance( + vif, + objects.vif.VIFVHostUser, + port_profile=profile, + plugin="vrouter", + vif_name=_get_vif_name(vif) + ) + _set_vhostuser_settings(vif, obj) else: raise NotImplementedError() return obj diff --git a/nova/tests/unit/network/test_os_vif_util.py b/nova/tests/unit/network/test_os_vif_util.py index f25415c6dc2a..6825ee486531 100644 --- a/nova/tests/unit/network/test_os_vif_util.py +++ b/nova/tests/unit/network/test_os_vif_util.py @@ -1128,3 +1128,91 @@ class OSVIFUtilTestCase(test.NoDBTestCase): objects=[]))) self.assertObjEqual(expect, actual) + + def test_nova_to_osvif_vrouter_direct(self): + """Test for Contrail / Tungsten Fabric direct offloaded datapath.""" + vif = model.VIF( + id="dc065497-3c8d-4f44-8fb4-e1d33c16a536", + type=model.VIF_TYPE_VROUTER, + address="22:52:25:62:e2:aa", + profile={ + "pci_slot": "0000:08:08.5", + }, + network=model.Network( + id="b82c1929-051e-481d-8110-4669916c7915", + label="Demo Net", + subnets=[]), + vnic_type=model.VNIC_TYPE_DIRECT, + ) + + actual = os_vif_util.nova_to_osvif_vif(vif) + + expect = osv_objects.vif.VIFHostDevice( + id="dc065497-3c8d-4f44-8fb4-e1d33c16a536", + active=False, + has_traffic_filtering=False, + address="22:52:25:62:e2:aa", + dev_type=osv_objects.fields.VIFHostDeviceDevType.ETHERNET, + dev_address="0000:08:08.5", + plugin="vrouter", + port_profile=osv_objects.vif.VIFPortProfileBase( + datapath_offload=osv_objects.vif.DatapathOffloadRepresentor( + representor_name="nicdc065497-3c", + representor_address="0000:08:08.5") + ), + preserve_on_delete=False, + vif_name="nicdc065497-3c", + network=osv_objects.network.Network( + id="b82c1929-051e-481d-8110-4669916c7915", + bridge_interface=None, + label="Demo Net", + subnets=osv_objects.subnet.SubnetList( + objects=[]))) + + self.assertObjEqual(expect, actual) + + def test_nova_to_osvif_vrouter_forwarder(self): + """Test for Contrail / Tungsten Fabric indirect offloaded datapath.""" + vif = model.VIF( + id="dc065497-3c8d-4f44-8fb4-e1d33c16a536", + type=model.VIF_TYPE_VROUTER, + address="22:52:25:62:e2:aa", + profile={ + "pci_slot": "0000:08:08.5", + }, + network=model.Network( + id="b82c1929-051e-481d-8110-4669916c7915", + label="Demo Net", + subnets=[]), + details={ + model.VIF_DETAILS_VHOSTUSER_MODE: 'client', + model.VIF_DETAILS_VHOSTUSER_SOCKET: '/fake/socket', + }, + vnic_type=model.VNIC_TYPE_VIRTIO_FORWARDER, + ) + + actual = os_vif_util.nova_to_osvif_vif(vif) + + expect = osv_objects.vif.VIFVHostUser( + id="dc065497-3c8d-4f44-8fb4-e1d33c16a536", + active=False, + address="22:52:25:62:e2:aa", + plugin="vrouter", + vif_name="nicdc065497-3c", + path='/fake/socket', + mode='client', + has_traffic_filtering=False, + port_profile=osv_objects.vif.VIFPortProfileBase( + datapath_offload=osv_objects.vif.DatapathOffloadRepresentor( + representor_address="0000:08:08.5", + representor_name="nicdc065497-3c") + ), + preserve_on_delete=False, + network=osv_objects.network.Network( + id="b82c1929-051e-481d-8110-4669916c7915", + bridge_interface=None, + label="Demo Net", + subnets=osv_objects.subnet.SubnetList( + objects=[]))) + + self.assertObjEqual(expect, actual) diff --git a/nova/tests/unit/virt/libvirt/test_vif.py b/nova/tests/unit/virt/libvirt/test_vif.py index 2e9c9e5dcb06..741e56525387 100644 --- a/nova/tests/unit/virt/libvirt/test_vif.py +++ b/nova/tests/unit/virt/libvirt/test_vif.py @@ -273,6 +273,25 @@ class LibvirtVifTestCase(test.NoDBTestCase): type=network_model.VIF_TYPE_VROUTER, devname='tap-xxx-yyy-zzz') + vif_vrouter_direct = network_model.VIF(id=uuids.vif, + address='ca:fe:de:ad:be:ef', + network=network_vrouter, + type=network_model.VIF_TYPE_VROUTER, + vnic_type=network_model.VNIC_TYPE_DIRECT, + profile={'pci_slot': '0000:0a:00.1'}, + devname='tap-xxx-yyy-zzz') + + vif_vrouter_forwarder = network_model.VIF(id=uuids.vif, + address='ca:fe:de:ad:be:ef', + network=network_vrouter, + type=network_model.VIF_TYPE_VROUTER, + vnic_type=network_model.VNIC_TYPE_VIRTIO_FORWARDER, + profile={'pci_slot': '0000:0a:00.1'}, + details={ + network_model.VIF_DETAILS_VHOSTUSER_MODE: 'server', + network_model.VIF_DETAILS_VHOSTUSER_SOCKET: '/tmp/usv-xxx-yyy-zzz', + network_model.VIF_DETAILS_VHOSTUSER_VROUTER_PLUG: True}) + vif_contrail_vrouter = network_model.VIF(id=uuids.vif, address='ca:fe:de:ad:be:ef', network=network_vrouter, @@ -1400,6 +1419,34 @@ class LibvirtVifTestCase(test.NoDBTestCase): self._assertTypeAndMacEquals(node, "ethernet", "target", "dev", self.vif_vrouter, dev_want) + def test_vrouter_direct(self): + """Test for Contrail / Tungsten Fabric direct offloaded datapath.""" + d = vif.LibvirtGenericVIFDriver() + xml = self._get_instance_xml(d, self.vif_vrouter_direct) + node = self._get_node(xml) + self._assertTypeAndPciEquals(node, + "hostdev", + self.vif_vrouter_direct) + self._assertMacEquals(node, self.vif_vrouter_direct) + + def test_vrouter_forwarder(self): + """Test for Contrail / Tungsten Fabric indirect offloaded datapath.""" + d = vif.LibvirtGenericVIFDriver() + xml = self._get_instance_xml(d, + self.vif_vrouter_forwarder) + node = self._get_node(xml) + self.assertEqual(node.get("type"), + network_model.VIF_TYPE_VHOSTUSER) + + self._assertTypeEquals(node, network_model.VIF_TYPE_VHOSTUSER, + "source", "mode", "server") + self._assertTypeEquals(node, network_model.VIF_TYPE_VHOSTUSER, + "source", "path", "/tmp/usv-xxx-yyy-zzz") + self._assertTypeEquals(node, network_model.VIF_TYPE_VHOSTUSER, + "source", "type", "unix") + self._assertMacEquals(node, self.vif_vrouter_forwarder) + self._assertModel(xml, network_model.VIF_MODEL_VIRTIO) + def test_contrail_vrouter(self): """Test for the Contrail / Tungsten Fabric DPDK datapath.""" d = vif.LibvirtGenericVIFDriver() diff --git a/releasenotes/notes/vrouter-hw-offloads-38257f49ac1d3a60.yaml b/releasenotes/notes/vrouter-hw-offloads-38257f49ac1d3a60.yaml new file mode 100644 index 000000000000..417d82367d16 --- /dev/null +++ b/releasenotes/notes/vrouter-hw-offloads-38257f49ac1d3a60.yaml @@ -0,0 +1,14 @@ +--- +features: + - | + This release adds support for ``direct`` and ``virtio-forwarder`` VNIC + types to the ``vrouter`` VIF type. In order to use these VNIC types, + support is required from the version of OpenContrail, Contrail or Tungsten + Fabric that is installed, as well the required hardware. At this time, the + reference os-vif plugin is hosted on OpenContrail at + https://github.com/Juniper/contrail-nova-vif-driver but is expected to + transition to Tungsten Fabric in the future. Version 5.1 or later of the + plugin is required to use these new VNIC types. Consult the `Tungsten + Fabric documentation `_ for + release notes, when available, about hardware support. For commercial + support, consult the release notes from a downstream vendor. diff --git a/requirements.txt b/requirements.txt index acacf0af5e05..ff22d4dfefc8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -57,7 +57,7 @@ psutil>=3.2.2 # BSD oslo.versionedobjects>=1.33.3 # Apache-2.0 os-brick>=2.6.1 # Apache-2.0 os-traits>=0.4.0 # Apache-2.0 -os-vif!=1.8.0,>=1.7.0 # Apache-2.0 +os-vif>=1.14.0 # Apache-2.0 os-win>=3.0.0 # Apache-2.0 castellan>=0.16.0 # Apache-2.0 microversion-parse>=0.2.1 # Apache-2.0