network: update pci request spec to handle trusted tags
Read port info to extract the trusted tag from binding profile then set it in the request spec. The test_create_pci_requests_for_sriov_ports test is updated and re-written in mock. Implements blueprint sriov-trusted-vfs Signed-off-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com> Change-Id: Iaea17b7a02d53463d2b815bdc5f4e83e422188eb
This commit is contained in:
committed by
Matt Riedemann
parent
f9ddddc358
commit
88e21d8e5e
@@ -92,7 +92,7 @@ Possible values:
|
|||||||
* "devname": Device name of the device (for e.g. interface name). Not all
|
* "devname": Device name of the device (for e.g. interface name). Not all
|
||||||
PCI devices have a name.
|
PCI devices have a name.
|
||||||
* "<tag>": Additional <tag> and <tag_value> used for matching PCI devices.
|
* "<tag>": Additional <tag> and <tag_value> used for matching PCI devices.
|
||||||
Supported <tag>: "physical_network".
|
Supported <tag>: "physical_network", "trusted".
|
||||||
|
|
||||||
The address key supports traditional glob style and regular expression
|
The address key supports traditional glob style and regular expression
|
||||||
syntax. Valid examples are:
|
syntax. Valid examples are:
|
||||||
@@ -116,6 +116,8 @@ Possible values:
|
|||||||
"bus": "02", "slot": "0[1-2]",
|
"bus": "02", "slot": "0[1-2]",
|
||||||
"function": ".*"},
|
"function": ".*"},
|
||||||
"physical_network":"physnet1"}
|
"physical_network":"physnet1"}
|
||||||
|
passthrough_whitelist = {"devname": "eth0", "physical_network":"physnet1",
|
||||||
|
"trusted": "true"}
|
||||||
|
|
||||||
The following are invalid, as they specify mutually exclusive options:
|
The following are invalid, as they specify mutually exclusive options:
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from neutronclient.common import exceptions as neutron_client_exc
|
|||||||
from neutronclient.v2_0 import client as clientv20
|
from neutronclient.v2_0 import client as clientv20
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
|
from oslo_utils import strutils
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
import six
|
import six
|
||||||
|
|
||||||
@@ -1552,21 +1553,44 @@ class API(base_api.NetworkAPI):
|
|||||||
phynet_name = net.get('provider:physical_network')
|
phynet_name = net.get('provider:physical_network')
|
||||||
return phynet_name
|
return phynet_name
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_trusted_mode_from_port(port):
|
||||||
|
"""Returns whether trusted mode is requested
|
||||||
|
|
||||||
|
If port binding does not provide any information about trusted
|
||||||
|
status this function is returning None
|
||||||
|
"""
|
||||||
|
value = _get_binding_profile(port).get('trusted')
|
||||||
|
if value is not None:
|
||||||
|
# This allows the user to specify things like '1' and 'yes' in
|
||||||
|
# the port binding profile and we can handle it as a boolean.
|
||||||
|
return strutils.bool_from_string(value)
|
||||||
|
|
||||||
def _get_port_vnic_info(self, context, neutron, port_id):
|
def _get_port_vnic_info(self, context, neutron, port_id):
|
||||||
"""Retrieve port vnic info
|
"""Retrieve port vnic info
|
||||||
|
|
||||||
Invoked with a valid port_id.
|
:param context: The request context
|
||||||
Return vnic type and the attached physical network name.
|
:param neutron: The Neutron client
|
||||||
|
:param port_id: The id of port to be queried
|
||||||
|
|
||||||
|
:return: A triplet composed of the VNIC type (see:
|
||||||
|
network_model.VNIC_TYPES_*), the attached physical
|
||||||
|
network name, for SR-IOV whether the port should be
|
||||||
|
considered as trusted or None for other VNIC types.
|
||||||
"""
|
"""
|
||||||
|
trusted = None
|
||||||
phynet_name = None
|
phynet_name = None
|
||||||
port = self._show_port(context, port_id, neutron_client=neutron,
|
port = self._show_port(context, port_id, neutron_client=neutron,
|
||||||
fields=['binding:vnic_type', 'network_id'])
|
fields=['binding:vnic_type', 'network_id',
|
||||||
|
BINDING_PROFILE])
|
||||||
vnic_type = port.get('binding:vnic_type',
|
vnic_type = port.get('binding:vnic_type',
|
||||||
network_model.VNIC_TYPE_NORMAL)
|
network_model.VNIC_TYPE_NORMAL)
|
||||||
if vnic_type in network_model.VNIC_TYPES_SRIOV:
|
if vnic_type in network_model.VNIC_TYPES_SRIOV:
|
||||||
net_id = port['network_id']
|
net_id = port['network_id']
|
||||||
phynet_name = self._get_phynet_info(context, neutron, net_id)
|
phynet_name = self._get_phynet_info(context, neutron, net_id)
|
||||||
return vnic_type, phynet_name
|
trusted = self._get_trusted_mode_from_port(port)
|
||||||
|
|
||||||
|
return vnic_type, phynet_name, trusted
|
||||||
|
|
||||||
def create_pci_requests_for_sriov_ports(self, context, pci_requests,
|
def create_pci_requests_for_sriov_ports(self, context, pci_requests,
|
||||||
requested_networks):
|
requested_networks):
|
||||||
@@ -1581,11 +1605,16 @@ class API(base_api.NetworkAPI):
|
|||||||
neutron = get_client(context, admin=True)
|
neutron = get_client(context, admin=True)
|
||||||
for request_net in requested_networks:
|
for request_net in requested_networks:
|
||||||
phynet_name = None
|
phynet_name = None
|
||||||
|
trusted = None
|
||||||
vnic_type = network_model.VNIC_TYPE_NORMAL
|
vnic_type = network_model.VNIC_TYPE_NORMAL
|
||||||
|
|
||||||
if request_net.port_id:
|
if request_net.port_id:
|
||||||
vnic_type, phynet_name = self._get_port_vnic_info(
|
vnic_type, phynet_name, trusted = self._get_port_vnic_info(
|
||||||
context, neutron, request_net.port_id)
|
context, neutron, request_net.port_id)
|
||||||
|
LOG.debug("Creating PCI device request for port_id=%s, "
|
||||||
|
"vnic_type=%s, phynet_name=%s, trusted=%s",
|
||||||
|
request_net.port_id, vnic_type, phynet_name,
|
||||||
|
trusted)
|
||||||
pci_request_id = None
|
pci_request_id = None
|
||||||
if vnic_type in network_model.VNIC_TYPES_SRIOV:
|
if vnic_type in network_model.VNIC_TYPES_SRIOV:
|
||||||
# TODO(moshele): To differentiate between the SR-IOV legacy
|
# TODO(moshele): To differentiate between the SR-IOV legacy
|
||||||
@@ -1598,6 +1627,12 @@ class API(base_api.NetworkAPI):
|
|||||||
dev_type = pci_request.DEVICE_TYPE_FOR_VNIC_TYPE.get(vnic_type)
|
dev_type = pci_request.DEVICE_TYPE_FOR_VNIC_TYPE.get(vnic_type)
|
||||||
if dev_type:
|
if dev_type:
|
||||||
spec[pci_request.PCI_DEVICE_TYPE_TAG] = dev_type
|
spec[pci_request.PCI_DEVICE_TYPE_TAG] = dev_type
|
||||||
|
if trusted is not None:
|
||||||
|
# We specifically have requested device on a pool
|
||||||
|
# with a tag trusted set to true or false. We
|
||||||
|
# convert the value to string since tags are
|
||||||
|
# compared in that way.
|
||||||
|
spec[pci_request.PCI_TRUSTED_TAG] = str(trusted)
|
||||||
request = objects.InstancePCIRequest(
|
request = objects.InstancePCIRequest(
|
||||||
count=1,
|
count=1,
|
||||||
spec=[spec],
|
spec=[spec],
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ from nova.objects import fields as obj_fields
|
|||||||
from nova.pci import utils
|
from nova.pci import utils
|
||||||
|
|
||||||
PCI_NET_TAG = 'physical_network'
|
PCI_NET_TAG = 'physical_network'
|
||||||
|
PCI_TRUSTED_TAG = 'trusted'
|
||||||
PCI_DEVICE_TYPE_TAG = 'dev_type'
|
PCI_DEVICE_TYPE_TAG = 'dev_type'
|
||||||
|
|
||||||
DEVICE_TYPE_FOR_VNIC_TYPE = {
|
DEVICE_TYPE_FOR_VNIC_TYPE = {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ from nova.network.neutronv2 import constants
|
|||||||
from nova import objects
|
from nova import objects
|
||||||
from nova.objects import network_request as net_req_obj
|
from nova.objects import network_request as net_req_obj
|
||||||
from nova.pci import manager as pci_manager
|
from nova.pci import manager as pci_manager
|
||||||
|
from nova.pci import request as pci_request
|
||||||
from nova.pci import utils as pci_utils
|
from nova.pci import utils as pci_utils
|
||||||
from nova.pci import whitelist as pci_whitelist
|
from nova.pci import whitelist as pci_whitelist
|
||||||
from nova import policy
|
from nova import policy
|
||||||
@@ -3146,7 +3147,7 @@ class TestNeutronv2(TestNeutronv2Base):
|
|||||||
mock_client.show_port.return_value = test_port
|
mock_client.show_port.return_value = test_port
|
||||||
mock_client.list_extensions.return_value = test_ext_list
|
mock_client.list_extensions.return_value = test_ext_list
|
||||||
mock_client.show_network.return_value = test_net
|
mock_client.show_network.return_value = test_net
|
||||||
vnic_type, phynet_name = api._get_port_vnic_info(
|
vnic_type, phynet_name, trusted = api._get_port_vnic_info(
|
||||||
self.context, mock_client, test_port['port']['id'])
|
self.context, mock_client, test_port['port']['id'])
|
||||||
|
|
||||||
mock_client.show_network.assert_called_once_with(
|
mock_client.show_network.assert_called_once_with(
|
||||||
@@ -3176,7 +3177,7 @@ class TestNeutronv2(TestNeutronv2Base):
|
|||||||
mock_client.show_port.return_value = test_port
|
mock_client.show_port.return_value = test_port
|
||||||
mock_client.list_extensions.return_value = test_ext_list
|
mock_client.list_extensions.return_value = test_ext_list
|
||||||
mock_client.show_network.return_value = test_net
|
mock_client.show_network.return_value = test_net
|
||||||
vnic_type, phynet_name = api._get_port_vnic_info(
|
vnic_type, phynet_name, trusted = api._get_port_vnic_info(
|
||||||
self.context, mock_client, test_port['port']['id'])
|
self.context, mock_client, test_port['port']['id'])
|
||||||
|
|
||||||
mock_client.show_network.assert_called_with(
|
mock_client.show_network.assert_called_with(
|
||||||
@@ -3228,16 +3229,17 @@ class TestNeutronv2(TestNeutronv2Base):
|
|||||||
mock_client = mock_get_client()
|
mock_client = mock_get_client()
|
||||||
mock_client.show_port.return_value = test_port
|
mock_client.show_port.return_value = test_port
|
||||||
mock_client.show_network.return_value = test_net
|
mock_client.show_network.return_value = test_net
|
||||||
vnic_type, phynet_name = api._get_port_vnic_info(
|
vnic_type, phynet_name, trusted = api._get_port_vnic_info(
|
||||||
self.context, mock_client, test_port['port']['id'])
|
self.context, mock_client, test_port['port']['id'])
|
||||||
|
|
||||||
mock_client.show_port.assert_called_once_with(test_port['port']['id'],
|
mock_client.show_port.assert_called_once_with(test_port['port']['id'],
|
||||||
fields=['binding:vnic_type', 'network_id'])
|
fields=['binding:vnic_type', 'network_id', 'binding:profile'])
|
||||||
mock_client.show_network.assert_called_once_with(
|
mock_client.show_network.assert_called_once_with(
|
||||||
test_port['port']['network_id'],
|
test_port['port']['network_id'],
|
||||||
fields='provider:physical_network')
|
fields='provider:physical_network')
|
||||||
self.assertEqual(model.VNIC_TYPE_DIRECT, vnic_type)
|
self.assertEqual(model.VNIC_TYPE_DIRECT, vnic_type)
|
||||||
self.assertEqual('phynet1', phynet_name)
|
self.assertEqual('phynet1', phynet_name)
|
||||||
|
self.assertIsNone(trusted)
|
||||||
|
|
||||||
def _test_get_port_vnic_info(self, mock_get_client,
|
def _test_get_port_vnic_info(self, mock_get_client,
|
||||||
binding_vnic_type=None):
|
binding_vnic_type=None):
|
||||||
@@ -3255,13 +3257,14 @@ class TestNeutronv2(TestNeutronv2Base):
|
|||||||
mock_get_client.reset_mock()
|
mock_get_client.reset_mock()
|
||||||
mock_client = mock_get_client()
|
mock_client = mock_get_client()
|
||||||
mock_client.show_port.return_value = test_port
|
mock_client.show_port.return_value = test_port
|
||||||
vnic_type, phynet_name = api._get_port_vnic_info(
|
vnic_type, phynet_name, trusted = api._get_port_vnic_info(
|
||||||
self.context, mock_client, test_port['port']['id'])
|
self.context, mock_client, test_port['port']['id'])
|
||||||
|
|
||||||
mock_client.show_port.assert_called_once_with(test_port['port']['id'],
|
mock_client.show_port.assert_called_once_with(test_port['port']['id'],
|
||||||
fields=['binding:vnic_type', 'network_id'])
|
fields=['binding:vnic_type', 'network_id', 'binding:profile'])
|
||||||
self.assertEqual(model.VNIC_TYPE_NORMAL, vnic_type)
|
self.assertEqual(model.VNIC_TYPE_NORMAL, vnic_type)
|
||||||
self.assertFalse(phynet_name)
|
self.assertFalse(phynet_name)
|
||||||
|
self.assertIsNone(trusted)
|
||||||
|
|
||||||
@mock.patch.object(neutronapi, 'get_client', return_value=mock.Mock())
|
@mock.patch.object(neutronapi, 'get_client', return_value=mock.Mock())
|
||||||
def test_get_port_vnic_info_2(self, mock_get_client):
|
def test_get_port_vnic_info_2(self, mock_get_client):
|
||||||
@@ -3272,38 +3275,6 @@ class TestNeutronv2(TestNeutronv2Base):
|
|||||||
def test_get_port_vnic_info_3(self, mock_get_client):
|
def test_get_port_vnic_info_3(self, mock_get_client):
|
||||||
self._test_get_port_vnic_info(mock_get_client)
|
self._test_get_port_vnic_info(mock_get_client)
|
||||||
|
|
||||||
@mock.patch.object(neutronapi.API, "_get_port_vnic_info")
|
|
||||||
@mock.patch.object(neutronapi, 'get_client', return_value=mock.Mock())
|
|
||||||
def test_create_pci_requests_for_sriov_ports(self, mock_get_client,
|
|
||||||
mock_get_port_vnic_info):
|
|
||||||
api = neutronapi.API()
|
|
||||||
self.mox.ResetAll()
|
|
||||||
requested_networks = objects.NetworkRequestList(
|
|
||||||
objects = [
|
|
||||||
objects.NetworkRequest(port_id=uuids.portid_1),
|
|
||||||
objects.NetworkRequest(network_id='net1'),
|
|
||||||
objects.NetworkRequest(port_id=uuids.portid_2),
|
|
||||||
objects.NetworkRequest(port_id=uuids.portid_3),
|
|
||||||
objects.NetworkRequest(port_id=uuids.portid_4),
|
|
||||||
objects.NetworkRequest(port_id=uuids.portid_5)])
|
|
||||||
pci_requests = objects.InstancePCIRequests(requests=[])
|
|
||||||
mock_get_port_vnic_info.side_effect = [
|
|
||||||
(model.VNIC_TYPE_DIRECT, 'phynet1'),
|
|
||||||
(model.VNIC_TYPE_NORMAL, ''),
|
|
||||||
(model.VNIC_TYPE_MACVTAP, 'phynet1'),
|
|
||||||
(model.VNIC_TYPE_MACVTAP, 'phynet2'),
|
|
||||||
(model.VNIC_TYPE_DIRECT_PHYSICAL, 'phynet3')
|
|
||||||
]
|
|
||||||
api.create_pci_requests_for_sriov_ports(
|
|
||||||
None, pci_requests, requested_networks)
|
|
||||||
self.assertEqual(4, len(pci_requests.requests))
|
|
||||||
has_pci_request_id = [net.pci_request_id is not None for net in
|
|
||||||
requested_networks.objects]
|
|
||||||
self.assertEqual(pci_requests.requests[3].spec[0]["dev_type"],
|
|
||||||
"type-PF")
|
|
||||||
expected_results = [True, False, False, True, True, True]
|
|
||||||
self.assertEqual(expected_results, has_pci_request_id)
|
|
||||||
|
|
||||||
|
|
||||||
class TestNeutronv2WithMock(test.TestCase):
|
class TestNeutronv2WithMock(test.TestCase):
|
||||||
"""Used to test Neutron V2 API with mock."""
|
"""Used to test Neutron V2 API with mock."""
|
||||||
@@ -3315,6 +3286,34 @@ class TestNeutronv2WithMock(test.TestCase):
|
|||||||
'fake-user', 'fake-project',
|
'fake-user', 'fake-project',
|
||||||
auth_token='bff4a5a6b9eb4ea2a6efec6eefb77936')
|
auth_token='bff4a5a6b9eb4ea2a6efec6eefb77936')
|
||||||
|
|
||||||
|
@mock.patch.object(neutronapi, 'get_client', return_value=mock.Mock())
|
||||||
|
def test_get_port_vnic_info_trusted(self, mock_get_client):
|
||||||
|
test_port = {
|
||||||
|
'port': {'id': 'my_port_id1',
|
||||||
|
'network_id': 'net-id',
|
||||||
|
'binding:vnic_type': model.VNIC_TYPE_DIRECT,
|
||||||
|
'binding:profile': {"trusted": "Yes"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
test_net = {'network': {'provider:physical_network': 'phynet1'}}
|
||||||
|
test_ext_list = {'extensions': []}
|
||||||
|
|
||||||
|
mock_client = mock_get_client()
|
||||||
|
mock_client.show_port.return_value = test_port
|
||||||
|
mock_client.list_extensions.return_value = test_ext_list
|
||||||
|
mock_client.show_network.return_value = test_net
|
||||||
|
vnic_type, phynet_name, trusted = self.api._get_port_vnic_info(
|
||||||
|
self.context, mock_client, test_port['port']['id'])
|
||||||
|
|
||||||
|
mock_client.show_port.assert_called_once_with(test_port['port']['id'],
|
||||||
|
fields=['binding:vnic_type', 'network_id', 'binding:profile'])
|
||||||
|
mock_client.show_network.assert_called_once_with(
|
||||||
|
test_port['port']['network_id'],
|
||||||
|
fields='provider:physical_network')
|
||||||
|
self.assertEqual(model.VNIC_TYPE_DIRECT, vnic_type)
|
||||||
|
self.assertEqual('phynet1', phynet_name)
|
||||||
|
self.assertTrue(trusted)
|
||||||
|
|
||||||
@mock.patch('nova.network.neutronv2.api.API._show_port')
|
@mock.patch('nova.network.neutronv2.api.API._show_port')
|
||||||
def test_deferred_ip_port_immediate_allocation(self, mock_show):
|
def test_deferred_ip_port_immediate_allocation(self, mock_show):
|
||||||
port = {'network_id': 'my_netid1',
|
port = {'network_id': 'my_netid1',
|
||||||
@@ -4962,6 +4961,48 @@ class TestNeutronv2WithMock(test.TestCase):
|
|||||||
self.context, pci_requests, requested_networks)
|
self.context, pci_requests, requested_networks)
|
||||||
self.assertFalse(getclient.called)
|
self.assertFalse(getclient.called)
|
||||||
|
|
||||||
|
@mock.patch.object(neutronapi.API, "_get_port_vnic_info")
|
||||||
|
@mock.patch.object(neutronapi, 'get_client')
|
||||||
|
def test_create_pci_requests_for_sriov_ports(self, getclient,
|
||||||
|
mock_get_port_vnic_info):
|
||||||
|
requested_networks = objects.NetworkRequestList(
|
||||||
|
objects = [
|
||||||
|
objects.NetworkRequest(port_id=uuids.portid_1),
|
||||||
|
objects.NetworkRequest(network_id='net1'),
|
||||||
|
objects.NetworkRequest(port_id=uuids.portid_2),
|
||||||
|
objects.NetworkRequest(port_id=uuids.portid_3),
|
||||||
|
objects.NetworkRequest(port_id=uuids.portid_4),
|
||||||
|
objects.NetworkRequest(port_id=uuids.portid_5),
|
||||||
|
objects.NetworkRequest(port_id=uuids.trusted_port)])
|
||||||
|
pci_requests = objects.InstancePCIRequests(requests=[])
|
||||||
|
mock_get_port_vnic_info.side_effect = [
|
||||||
|
(model.VNIC_TYPE_DIRECT, 'phynet1', None),
|
||||||
|
(model.VNIC_TYPE_NORMAL, '', None),
|
||||||
|
(model.VNIC_TYPE_MACVTAP, 'phynet1', None),
|
||||||
|
(model.VNIC_TYPE_MACVTAP, 'phynet2', None),
|
||||||
|
(model.VNIC_TYPE_DIRECT_PHYSICAL, 'phynet3', None),
|
||||||
|
(model.VNIC_TYPE_DIRECT, 'phynet4', True)
|
||||||
|
]
|
||||||
|
api = neutronapi.API()
|
||||||
|
api.create_pci_requests_for_sriov_ports(
|
||||||
|
self.context, pci_requests, requested_networks)
|
||||||
|
self.assertEqual(5, len(pci_requests.requests))
|
||||||
|
has_pci_request_id = [net.pci_request_id is not None for net in
|
||||||
|
requested_networks.objects]
|
||||||
|
self.assertEqual(pci_requests.requests[3].spec[0]["dev_type"],
|
||||||
|
"type-PF")
|
||||||
|
expected_results = [True, False, False, True, True, True, True]
|
||||||
|
self.assertEqual(expected_results, has_pci_request_id)
|
||||||
|
# Make sure only the trusted VF has the 'trusted' tag set in the spec.
|
||||||
|
for pci_req in pci_requests.requests:
|
||||||
|
spec = pci_req.spec[0]
|
||||||
|
if spec[pci_request.PCI_NET_TAG] == 'phynet4':
|
||||||
|
# trusted should be true in the spec for this request
|
||||||
|
self.assertIn(pci_request.PCI_TRUSTED_TAG, spec)
|
||||||
|
self.assertEqual('True', spec[pci_request.PCI_TRUSTED_TAG])
|
||||||
|
else:
|
||||||
|
self.assertNotIn(pci_request.PCI_TRUSTED_TAG, spec)
|
||||||
|
|
||||||
@mock.patch.object(neutronapi, 'get_client')
|
@mock.patch.object(neutronapi, 'get_client')
|
||||||
def test_associate_floating_ip_conflict(self, mock_get_client):
|
def test_associate_floating_ip_conflict(self, mock_get_client):
|
||||||
"""Tests that if Neutron raises a Conflict we handle it and re-raise
|
"""Tests that if Neutron raises a Conflict we handle it and re-raise
|
||||||
|
|||||||
32
releasenotes/notes/trusted-vfs-abee6dff7c9b6940.yaml
Normal file
32
releasenotes/notes/trusted-vfs-abee6dff7c9b6940.yaml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
features:
|
||||||
|
- |
|
||||||
|
The libvirt compute driver now allows users to create instances
|
||||||
|
with SR-IOV virtual functions which will be configured as trusted.
|
||||||
|
|
||||||
|
The operator will have to create pools of devices with tag
|
||||||
|
trusted=true.
|
||||||
|
|
||||||
|
For example, modify ``/etc/nova/nova.conf`` and set:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[pci]
|
||||||
|
passthrough_whitelist = {"devname": "eth0", "trusted": "true",
|
||||||
|
"physical_network":"sriovnet1"}
|
||||||
|
|
||||||
|
Where "eth0" is the interface name related to the physical
|
||||||
|
function.
|
||||||
|
|
||||||
|
Ensure that the version of ``ip-link`` on the compute host supports setting
|
||||||
|
the trust mode on the device.
|
||||||
|
|
||||||
|
Ports from the physical network will have to be created with a
|
||||||
|
binding profile to match the trusted tag. Only ports with
|
||||||
|
``binding:vif_type=hw_veb`` and ``binding:vnic_type=direct`` are supported.
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
$ neutron port-create <net-id> \
|
||||||
|
--name sriov_port \
|
||||||
|
--vnic-type direct \
|
||||||
|
--binding:profile type=dict trusted=true
|
||||||
Reference in New Issue
Block a user