This change adds a new VNIC type to distinguish between virtual and
physical functions in SR-IOV.
The new VNIC type 'direct-physical' deviates from the behavior of
'direct' VNICs for virtual functions. While neutron tracks the resource
as a port, it does not currently perform any management functions.
Future changes may extend the segment mapping functionality that is
currently based on agent configuration to include direct types.
However, the direct-physical VNICs will not have functional parity with
the other SR-IOV VNIC types in that quality of service and port security
functionality is not available.
APIImpact
DocImpact: Add description for new 'direct-physical' VNIC type.
Closes-Bug: #
1500993
Change-Id: If1ab969c2002c649a3d51635ca2765c262e2d37f
VNIC_DIRECT = 'direct'
VNIC_MACVTAP = 'macvtap'
VNIC_BAREMETAL = 'baremetal'
-VNIC_TYPES = [VNIC_NORMAL, VNIC_DIRECT, VNIC_MACVTAP, VNIC_BAREMETAL]
+VNIC_DIRECT_PHYSICAL = 'direct-physical'
+VNIC_TYPES = [VNIC_NORMAL, VNIC_DIRECT, VNIC_MACVTAP, VNIC_BAREMETAL,
+ VNIC_DIRECT_PHYSICAL]
EXTENDED_ATTRIBUTES_2_0 = {
'ports': {
from neutron.common import topics
from neutron.common import utils as n_utils
from neutron import context
+from neutron.extensions import portbindings
from neutron.plugins.ml2.drivers.mech_sriov.agent.common import config
from neutron.plugins.ml2.drivers.mech_sriov.agent.common \
import exceptions as exc
def port_update(self, context, **kwargs):
LOG.debug("port_update received")
port = kwargs.get('port')
+
+ vnic_type = port.get(portbindings.VNIC_TYPE)
+ if vnic_type and vnic_type == portbindings.VNIC_DIRECT_PHYSICAL:
+ LOG.debug("The SR-IOV agent doesn't handle %s ports.",
+ portbindings.VNIC_DIRECT_PHYSICAL)
+ return
+
# Put the port mac address in the updated_devices set.
# Do not store port details, as if they're used for processing
# notifications there is no guarantee the notifications are
vif_type=VIF_TYPE_HW_VEB,
vif_details={portbindings.CAP_PORT_FILTER: False},
supported_vnic_types=[portbindings.VNIC_DIRECT,
- portbindings.VNIC_MACVTAP],
+ portbindings.VNIC_MACVTAP,
+ portbindings.VNIC_DIRECT_PHYSICAL],
supported_pci_vendor_info=None):
"""Initialize base class for SriovNicSwitch L2 agent type.
LOG.debug("Refusing to bind due to unsupported pci_vendor device")
return
+ if vnic_type == portbindings.VNIC_DIRECT_PHYSICAL:
+ # Physical functions don't support things like QoS properties,
+ # spoof checking, etc. so we might as well side-step the agent
+ # for now. The agent also doesn't currently recognize non-VF
+ # PCI devices so we won't get port status change updates
+ # either. This should be changed in the future so physical
+ # functions can use device mapping checks and the plugin can
+ # get port status updates.
+ self.try_to_bind(context, None)
+ return
+
for agent in context.host_agents(self.agent_type):
LOG.debug("Checking agent: %s", agent)
if agent['alive']:
def try_to_bind(self, context, agent):
for segment in context.segments_to_bind:
if self.check_segment(segment, agent):
+ port_status = (constants.PORT_STATUS_ACTIVE if agent is None
+ else constants.PORT_STATUS_DOWN)
context.set_binding(segment[api.ID],
self.vif_type,
self._get_vif_details(segment),
- constants.PORT_STATUS_DOWN)
+ port_status)
LOG.debug("Bound using segment: %s", segment)
return True
return False
from oslo_config import cfg
from oslo_utils import uuidutils
+from neutron.extensions import portbindings
from neutron.plugins.ml2.drivers.mech_sriov.agent.common import config # noqa
from neutron.plugins.ml2.drivers.mech_sriov.agent.common import exceptions
from neutron.plugins.ml2.drivers.mech_sriov.agent import sriov_nic_agent
self.assertEqual(set([(DEVICE_MAC, PCI_SLOT)]),
self.agent.updated_devices)
+ def test_port_update_with_vnic_physical_direct(self):
+ port = self._create_fake_port()
+ port[portbindings.VNIC_TYPE] = portbindings.VNIC_DIRECT_PHYSICAL
+ kwargs = {'context': self.context, 'port': port}
+ self.sriov_rpc_callback.port_update(**kwargs)
+ self.assertEqual(set(), self.agent.updated_devices)
+
def test_port_update_without_pci_slot(self):
port = self._create_fake_port()
port['binding:profile'] = None
self._check_vif_type_for_vnic_type(portbindings.VNIC_MACVTAP,
mech_driver.VIF_TYPE_HW_VEB)
+ def test_vnic_type_direct_physical(self):
+ self._check_vif_type_for_vnic_type(portbindings.VNIC_DIRECT_PHYSICAL,
+ mech_driver.VIF_TYPE_HW_VEB)
+
class SriovSwitchMechProfileTestCase(SriovNicSwitchMechanismBaseTestCase):
def _check_vif_for_pci_info(self, pci_vendor_info, expected_vif_type):
self.driver.bind_port(context)
self.assertEqual(constants.PORT_STATUS_DOWN, context._bound_state)
+ def test_get_vif_details_with_agent_direct_physical(self):
+ context = TestFakePortContext(self.AGENT_TYPE,
+ self.AGENTS,
+ self.VLAN_SEGMENTS,
+ portbindings.VNIC_DIRECT_PHYSICAL)
+
+ self.driver.bind_port(context)
+ self.assertEqual(constants.PORT_STATUS_ACTIVE, context._bound_state)
+
class SriovSwitchMechConfigTestCase(SriovNicSwitchMechanismBaseTestCase):
def _set_config(self, pci_devs=['aa:bb']):
--- /dev/null
+---
+prelude: >
+ Add new VNIC type for SR-IOV physical functions.
+features:
+ - Neutron now supports creation of ports for exposing physical functions
+ as network devices to guests.