Netronome SmartNIC Enablement
These patches enable Netronome Agilio SmartNIC acceleration in Nova. * This patch set adds VIF_TYPE_AGILIO_OVS to hook in the external ML2 plugin. * This patch set adds VNIC_TYPE_VIRTIO_FORWARDER to enable the virtio-forwarder plugging mode. * nova/network/neutronv2/api.py has been modified to pass the bridge in the os-vif objects, similar to other OVS VIF types. * os_vif_util.py has been extended to handle the agilio_ovs os-vif plugin. * VIFPortProfileOVSRepresentor is used to pass the PCI address and vif name to the os-vif plugin. * Note: this enables the external ML2 and OS-VIF plugin, hosted at https://github.com/Netronome/agilio-ovs-openstack-plugin to support the out-of-tree version of Agilio OVS. Consult the Agilio documentation for configuration recommendations. Change-Id: I3da059fb62f085ff04532f8ec05857acfb628b06 Depends-On: Id95a9f311e71b3cefb170704728641a4a1a91144 Signed-off-by: Jan Gutter <jan.gutter@netronome.com>
This commit is contained in:
parent
15500b89be
commit
2bd008ef5c
@ -42,6 +42,7 @@ VIF_TYPE_VROUTER = 'vrouter'
|
||||
VIF_TYPE_OTHER = 'other'
|
||||
VIF_TYPE_TAP = 'tap'
|
||||
VIF_TYPE_MACVTAP = 'macvtap'
|
||||
VIF_TYPE_AGILIO_OVS = 'agilio_ovs'
|
||||
VIF_TYPE_BINDING_FAILED = 'binding_failed'
|
||||
VIF_TYPE_VIF = 'vif'
|
||||
|
||||
@ -97,12 +98,15 @@ VNIC_TYPE_DIRECT = 'direct'
|
||||
VNIC_TYPE_MACVTAP = 'macvtap'
|
||||
VNIC_TYPE_DIRECT_PHYSICAL = 'direct-physical'
|
||||
VNIC_TYPE_BAREMETAL = 'baremetal'
|
||||
VNIC_TYPE_VIRTIO_FORWARDER = 'virtio-forwarder'
|
||||
|
||||
# Define list of ports which needs pci request.
|
||||
# Note: The macvtap port needs a PCI request as it is a tap interface
|
||||
# with VF as the lower physical interface.
|
||||
# Note: Currently, VNIC_TYPE_VIRTIO_FORWARDER assumes a 1:1
|
||||
# relationship with a VF. This is expected to change in the future.
|
||||
VNIC_TYPES_SRIOV = (VNIC_TYPE_DIRECT, VNIC_TYPE_MACVTAP,
|
||||
VNIC_TYPE_DIRECT_PHYSICAL)
|
||||
VNIC_TYPE_DIRECT_PHYSICAL, VNIC_TYPE_VIRTIO_FORWARDER)
|
||||
|
||||
# Define list of ports which are passthrough to the guest
|
||||
# and need a special treatment on snapshot and suspend/resume
|
||||
|
@ -2159,7 +2159,8 @@ class API(base_api.NetworkAPI):
|
||||
should_create_bridge = None
|
||||
vif_type = port.get('binding:vif_type')
|
||||
port_details = port.get('binding:vif_details', {})
|
||||
if vif_type == network_model.VIF_TYPE_OVS:
|
||||
if vif_type in [network_model.VIF_TYPE_OVS,
|
||||
network_model.VIF_TYPE_AGILIO_OVS]:
|
||||
bridge = port_details.get(network_model.VIF_DETAILS_BRIDGE_NAME,
|
||||
CONF.neutron.ovs_bridge)
|
||||
ovs_interfaceid = port['id']
|
||||
|
@ -299,6 +299,49 @@ def _nova_to_osvif_vif_ovs(vif):
|
||||
return obj
|
||||
|
||||
|
||||
# VIF_TYPE_AGILIO_OVS = 'agilio_ovs'
|
||||
def _nova_to_osvif_vif_agilio_ovs(vif):
|
||||
vnic_type = vif.get('vnic_type', model.VNIC_TYPE_NORMAL)
|
||||
# In practice, vif_name gets its value from vif["devname"], passed by
|
||||
# the mechanism driver.
|
||||
vif_name = _get_vif_name(vif)
|
||||
agilio_vnic_types = [model.VNIC_TYPE_DIRECT,
|
||||
model.VNIC_TYPE_VIRTIO_FORWARDER]
|
||||
if vnic_type in agilio_vnic_types:
|
||||
# Note: passing representor_name asks os-vif to rename the
|
||||
# representor, setting this to vif_name is helpful for tracing.
|
||||
# VIF.port_profile.representor_address is used by the os-vif plugin's
|
||||
# plug/unplug, this should be the same as VIF.dev_address in the
|
||||
# VNIC_TYPE_DIRECT case.
|
||||
profile = objects.vif.VIFPortProfileOVSRepresentor(
|
||||
interface_id=vif.get('ovs_interfaceid') or vif['id'],
|
||||
representor_name=vif_name,
|
||||
representor_address=vif["profile"]["pci_slot"])
|
||||
if vnic_type == model.VNIC_TYPE_DIRECT:
|
||||
# VIF.dev_address is used by the hypervisor to plug the instance into
|
||||
# the PCI device.
|
||||
obj = _get_vif_instance(
|
||||
vif,
|
||||
objects.vif.VIFHostDevice,
|
||||
port_profile=profile,
|
||||
plugin="agilio_ovs",
|
||||
dev_address=vif["profile"]["pci_slot"],
|
||||
dev_type=objects.fields.VIFHostDeviceDevType.ETHERNET)
|
||||
if vif["network"]["bridge"] is not None:
|
||||
obj.network.bridge = vif["network"]["bridge"]
|
||||
elif vnic_type == model.VNIC_TYPE_VIRTIO_FORWARDER:
|
||||
obj = _get_vif_instance(vif, objects.vif.VIFVHostUser,
|
||||
port_profile=profile, plugin="agilio_ovs",
|
||||
vif_name=vif_name)
|
||||
_set_vhostuser_settings(vif, obj)
|
||||
if vif["network"]["bridge"] is not None:
|
||||
obj.network.bridge = vif["network"]["bridge"]
|
||||
else:
|
||||
LOG.debug("agilio_ovs falling through to ovs %s", vif)
|
||||
obj = _nova_to_osvif_vif_ovs(vif)
|
||||
return obj
|
||||
|
||||
|
||||
# VIF_TYPE_VHOST_USER = 'vhostuser'
|
||||
def _nova_to_osvif_vif_vhostuser(vif):
|
||||
if vif['details'].get(model.VIF_DETAILS_VHOSTUSER_FP_PLUG, False):
|
||||
|
@ -475,6 +475,126 @@ class OSVIFUtilTestCase(test.NoDBTestCase):
|
||||
|
||||
self.assertObjEqual(expect, actual)
|
||||
|
||||
def test_nova_to_osvif_vif_agilio_ovs_fallthrough(self):
|
||||
vif = model.VIF(
|
||||
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
|
||||
type=model.VIF_TYPE_AGILIO_OVS,
|
||||
address="22:52:25:62:e2:aa",
|
||||
network=model.Network(
|
||||
id="b82c1929-051e-481d-8110-4669916c7915",
|
||||
label="Demo Net",
|
||||
subnets=[]),
|
||||
details={
|
||||
model.VIF_DETAILS_PORT_FILTER: True,
|
||||
}
|
||||
)
|
||||
|
||||
actual = os_vif_util.nova_to_osvif_vif(vif)
|
||||
|
||||
expect = osv_objects.vif.VIFOpenVSwitch(
|
||||
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
|
||||
active=False,
|
||||
address="22:52:25:62:e2:aa",
|
||||
has_traffic_filtering=True,
|
||||
plugin="ovs",
|
||||
port_profile=osv_objects.vif.VIFPortProfileOpenVSwitch(
|
||||
interface_id="dc065497-3c8d-4f44-8fb4-e1d33c16a536"),
|
||||
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_vif_agilio_ovs_direct(self):
|
||||
vif = model.VIF(
|
||||
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
|
||||
type=model.VIF_TYPE_AGILIO_OVS,
|
||||
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="agilio_ovs",
|
||||
port_profile=osv_objects.vif.VIFPortProfileOVSRepresentor(
|
||||
interface_id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
|
||||
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_vif_agilio_ovs_forwarder(self):
|
||||
vif = model.VIF(
|
||||
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
|
||||
type=model.VIF_TYPE_AGILIO_OVS,
|
||||
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_VIRTIO_FORWARDER,
|
||||
details={
|
||||
model.VIF_DETAILS_VHOSTUSER_MODE: 'client',
|
||||
model.VIF_DETAILS_VHOSTUSER_OVS_PLUG: True,
|
||||
model.VIF_DETAILS_VHOSTUSER_SOCKET: '/fake/socket',
|
||||
}
|
||||
)
|
||||
|
||||
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",
|
||||
has_traffic_filtering=False,
|
||||
plugin="agilio_ovs",
|
||||
port_profile=osv_objects.vif.VIFPortProfileOVSRepresentor(
|
||||
interface_id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
|
||||
representor_address="0000:08:08.5",
|
||||
representor_name="nicdc065497-3c",),
|
||||
preserve_on_delete=False,
|
||||
vif_name="nicdc065497-3c",
|
||||
path='/fake/socket',
|
||||
mode='client',
|
||||
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_vif_ovs_plain(self):
|
||||
vif = model.VIF(
|
||||
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
|
||||
|
@ -105,6 +105,35 @@ class LibvirtVifTestCase(test.NoDBTestCase):
|
||||
bridge_interface=None,
|
||||
vlan=99)
|
||||
|
||||
vif_agilio_ovs = network_model.VIF(id='vif-xxx-yyy-zzz',
|
||||
address='ca:fe:de:ad:be:ef',
|
||||
network=network_ovs,
|
||||
type=network_model.VIF_TYPE_AGILIO_OVS,
|
||||
details={'port_filter': False},
|
||||
devname='tap-xxx-yyy-zzz',
|
||||
ovs_interfaceid='aaa-bbb-ccc')
|
||||
|
||||
vif_agilio_ovs_direct = network_model.VIF(id='vif-xxx-yyy-zzz',
|
||||
address='ca:fe:de:ad:be:ef',
|
||||
network=network_ovs,
|
||||
type=network_model.VIF_TYPE_AGILIO_OVS,
|
||||
vnic_type=network_model.VNIC_TYPE_DIRECT,
|
||||
ovs_interfaceid='aaa-bbb-ccc',
|
||||
devname='tap-xxx-yyy-zzz',
|
||||
profile={'pci_slot': '0000:0a:00.1'})
|
||||
|
||||
vif_agilio_ovs_forwarder = network_model.VIF(id='vif-xxx-yyy-zzz',
|
||||
address='ca:fe:de:ad:be:ef',
|
||||
network=network_ovs,
|
||||
type=network_model.VIF_TYPE_AGILIO_OVS,
|
||||
vnic_type=network_model.VNIC_TYPE_VIRTIO_FORWARDER,
|
||||
profile={'pci_slot': '0000:0a:00.1'},
|
||||
details={
|
||||
network_model.VIF_DETAILS_VHOSTUSER_MODE: 'client',
|
||||
network_model.VIF_DETAILS_VHOSTUSER_SOCKET: '/tmp/usv-xxx-yyy-zzz',
|
||||
network_model.VIF_DETAILS_VHOSTUSER_OVS_PLUG: True},
|
||||
ovs_interfaceid='aaa-bbb-ccc', mtu=1500)
|
||||
|
||||
vif_ovs = network_model.VIF(id='vif-xxx-yyy-zzz',
|
||||
address='ca:fe:de:ad:be:ef',
|
||||
network=network_ovs,
|
||||
@ -370,6 +399,41 @@ class LibvirtVifTestCase(test.NoDBTestCase):
|
||||
interface_id="07bd6cea-fb37-4594-b769-90fc51854ee9",
|
||||
profile_id="fishfood")
|
||||
|
||||
self.os_vif_repr_prof = osv_objects.vif.VIFPortProfileOVSRepresentor(
|
||||
interface_id="07bd6cea-fb37-4594-b769-90fc51854ee9",
|
||||
profile_id="fishfood",
|
||||
representor_name='nicdc065497-3c',
|
||||
representor_address='0000:0a:00.1')
|
||||
|
||||
self.os_vif_agilio_ovs = osv_objects.vif.VIFOpenVSwitch(
|
||||
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
|
||||
address="22:52:25:62:e2:aa",
|
||||
plugin="agilio_ovs",
|
||||
vif_name="nicdc065497-3c",
|
||||
bridge_name="br0",
|
||||
port_profile=self.os_vif_ovs_prof,
|
||||
network=self.os_vif_network)
|
||||
|
||||
self.os_vif_agilio_forwarder = osv_objects.vif.VIFVHostUser(
|
||||
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
|
||||
address="22:52:25:62:e2:aa",
|
||||
plugin="agilio_ovs",
|
||||
vif_name="nicdc065497-3c",
|
||||
path='/var/run/openvswitch/vhudc065497-3c',
|
||||
mode='client',
|
||||
port_profile=self.os_vif_repr_prof,
|
||||
network=self.os_vif_network)
|
||||
|
||||
self.os_vif_agilio_direct = osv_objects.vif.VIFHostDevice(
|
||||
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
|
||||
address="22:52:25:62:e2:aa",
|
||||
plugin="agilio_ovs",
|
||||
vif_name="nicdc065497-3c",
|
||||
dev_type=osv_fields.VIFHostDeviceDevType.ETHERNET,
|
||||
dev_address='0000:0a:00.1',
|
||||
port_profile=self.os_vif_repr_prof,
|
||||
network=self.os_vif_network)
|
||||
|
||||
self.os_vif_ovs = osv_objects.vif.VIFOpenVSwitch(
|
||||
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
|
||||
address="22:52:25:62:e2:aa",
|
||||
@ -1416,6 +1480,32 @@ class LibvirtVifTestCase(test.NoDBTestCase):
|
||||
self._assertMacEquals(node, self.vif_vhostuser_ovs)
|
||||
self._assertModel(xml, network_model.VIF_MODEL_VIRTIO)
|
||||
|
||||
def test_agilio_ovs_direct(self):
|
||||
d = vif.LibvirtGenericVIFDriver()
|
||||
xml = self._get_instance_xml(d, self.vif_agilio_ovs_direct)
|
||||
node = self._get_node(xml)
|
||||
self._assertTypeAndPciEquals(node,
|
||||
"hostdev",
|
||||
self.vif_agilio_ovs_direct)
|
||||
self._assertMacEquals(node, self.vif_agilio_ovs_direct)
|
||||
|
||||
def test_agilio_ovs_forwarder(self):
|
||||
d = vif.LibvirtGenericVIFDriver()
|
||||
xml = self._get_instance_xml(d,
|
||||
self.vif_agilio_ovs_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", "client")
|
||||
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_agilio_ovs_forwarder)
|
||||
self._assertModel(xml, network_model.VIF_MODEL_VIRTIO)
|
||||
|
||||
@mock.patch("nova.network.os_vif_util.nova_to_osvif_instance")
|
||||
@mock.patch("nova.network.os_vif_util.nova_to_osvif_vif")
|
||||
@mock.patch.object(os_vif, "plug")
|
||||
@ -1521,6 +1611,86 @@ class LibvirtVifTestCase(test.NoDBTestCase):
|
||||
<target dev="nicdc065497-3c"/>
|
||||
</interface>""", cfg.to_xml())
|
||||
|
||||
@mock.patch("nova.network.os_vif_util.nova_to_osvif_instance")
|
||||
@mock.patch("nova.network.os_vif_util.nova_to_osvif_vif")
|
||||
def test_config_os_vif_agilio_ovs_fallthrough(self, mock_convert_vif,
|
||||
mock_convert_inst):
|
||||
mock_convert_vif.return_value = self.os_vif_agilio_ovs
|
||||
mock_convert_inst.return_value = self.os_vif_inst_info
|
||||
|
||||
d = vif.LibvirtGenericVIFDriver()
|
||||
hostimpl = host.Host("qemu:///system")
|
||||
flavor = objects.Flavor(name='m1.small')
|
||||
image_meta = objects.ImageMeta.from_dict({})
|
||||
d = vif.LibvirtGenericVIFDriver()
|
||||
cfg = d.get_config(self.instance, self.vif_agilio_ovs,
|
||||
image_meta, flavor,
|
||||
CONF.libvirt.virt_type,
|
||||
hostimpl)
|
||||
|
||||
self._assertXmlEqual("""
|
||||
<interface type="bridge">
|
||||
<mac address="22:52:25:62:e2:aa"/>
|
||||
<model type="virtio"/>
|
||||
<source bridge="br0"/>
|
||||
<target dev="nicdc065497-3c"/>
|
||||
<virtualport type="openvswitch">
|
||||
<parameters
|
||||
interfaceid="07bd6cea-fb37-4594-b769-90fc51854ee9"/>
|
||||
</virtualport>
|
||||
</interface>""", cfg.to_xml())
|
||||
|
||||
@mock.patch("nova.network.os_vif_util.nova_to_osvif_instance")
|
||||
@mock.patch("nova.network.os_vif_util.nova_to_osvif_vif")
|
||||
def test_config_os_vif_agilio_ovs_forwarder(self, mock_convert_vif,
|
||||
mock_convert_inst):
|
||||
mock_convert_vif.return_value = self.os_vif_agilio_forwarder
|
||||
mock_convert_inst.return_value = self.os_vif_inst_info
|
||||
|
||||
d = vif.LibvirtGenericVIFDriver()
|
||||
hostimpl = host.Host("qemu:///system")
|
||||
flavor = objects.Flavor(name='m1.small')
|
||||
image_meta = objects.ImageMeta.from_dict({})
|
||||
d = vif.LibvirtGenericVIFDriver()
|
||||
cfg = d.get_config(self.instance, self.vif_agilio_ovs_forwarder,
|
||||
image_meta, flavor,
|
||||
CONF.libvirt.virt_type,
|
||||
hostimpl)
|
||||
|
||||
self._assertXmlEqual("""
|
||||
<interface type="vhostuser">
|
||||
<mac address="22:52:25:62:e2:aa"/>
|
||||
<model type="virtio"/>
|
||||
<source mode="client"
|
||||
path="/var/run/openvswitch/vhudc065497-3c" type="unix"/>
|
||||
</interface>""", cfg.to_xml())
|
||||
|
||||
@mock.patch("nova.network.os_vif_util.nova_to_osvif_instance")
|
||||
@mock.patch("nova.network.os_vif_util.nova_to_osvif_vif")
|
||||
def test_config_os_vif_agilio_ovs_direct(self, mock_convert_vif,
|
||||
mock_convert_inst):
|
||||
mock_convert_vif.return_value = self.os_vif_agilio_direct
|
||||
mock_convert_inst.return_value = self.os_vif_inst_info
|
||||
|
||||
d = vif.LibvirtGenericVIFDriver()
|
||||
hostimpl = host.Host("qemu:///system")
|
||||
flavor = objects.Flavor(name='m1.small')
|
||||
image_meta = objects.ImageMeta.from_dict({})
|
||||
d = vif.LibvirtGenericVIFDriver()
|
||||
cfg = d.get_config(self.instance, self.vif_agilio_ovs_direct,
|
||||
image_meta, flavor,
|
||||
CONF.libvirt.virt_type,
|
||||
hostimpl)
|
||||
|
||||
self._assertXmlEqual("""
|
||||
<interface type="hostdev" managed="yes">
|
||||
<mac address="22:52:25:62:e2:aa"/>
|
||||
<source>
|
||||
<address type="pci" domain="0x0000"
|
||||
bus="0x0a" slot="0x00" function="0x1"/>
|
||||
</source>
|
||||
</interface>""", cfg.to_xml())
|
||||
|
||||
@mock.patch("nova.network.os_vif_util.nova_to_osvif_instance")
|
||||
@mock.patch("nova.network.os_vif_util.nova_to_osvif_vif")
|
||||
def test_config_os_vif_ovs(self, mock_convert_vif, mock_convert_inst):
|
||||
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
features:
|
||||
- This release adds support for Netronome's Agilio OVS VIF type. In order
|
||||
to use the accelerated plugging modes, external Neutron and OS-VIF plugins
|
||||
are required. Consult
|
||||
https://github.com/Netronome/agilio-ovs-openstack-plugin for installation
|
||||
and operation instructions.
|
||||
Consult the Agilio documentation available at
|
||||
https://support.netronome.com/ for more information about the plugin
|
||||
compatibility and support matrix.
|
||||
- The ``virtio-forwarder`` VNIC type has been added to the list of VNICs.
|
||||
This VNIC type is intended to request a low-latency virtio port inside the
|
||||
instance, likely backed by hardware acceleration. Currently the Agilio OVS
|
||||
external Neutron and OS-VIF plugins provide support for this VNIC mode.
|
Loading…
Reference in New Issue
Block a user