Merge "ovs mech: bind only if user request switchdev"
This commit is contained in:
commit
5e9651aeac
@ -76,8 +76,17 @@ class SriovNicSwitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
|
|||||||
"network %(network)s",
|
"network %(network)s",
|
||||||
{'port': context.current['id'],
|
{'port': context.current['id'],
|
||||||
'network': context.network.current['id']})
|
'network': context.network.current['id']})
|
||||||
|
profile = context.current.get(portbindings.PROFILE)
|
||||||
vnic_type = context.current.get(portbindings.VNIC_TYPE,
|
vnic_type = context.current.get(portbindings.VNIC_TYPE,
|
||||||
portbindings.VNIC_NORMAL)
|
portbindings.VNIC_NORMAL)
|
||||||
|
capabilities = []
|
||||||
|
if profile:
|
||||||
|
capabilities = profile.get('capabilities', [])
|
||||||
|
if (vnic_type == portbindings.VNIC_DIRECT and
|
||||||
|
'switchdev' in capabilities):
|
||||||
|
LOG.debug("Refusing to bind due to unsupported vnic_type: %s "
|
||||||
|
"with switchdev capability", portbindings.VNIC_DIRECT)
|
||||||
|
return
|
||||||
if vnic_type not in self.supported_vnic_types:
|
if vnic_type not in self.supported_vnic_types:
|
||||||
LOG.debug("Refusing to bind due to unsupported vnic_type: %s",
|
LOG.debug("Refusing to bind due to unsupported vnic_type: %s",
|
||||||
vnic_type)
|
vnic_type)
|
||||||
|
@ -20,6 +20,7 @@ from neutron_lib.callbacks import events
|
|||||||
from neutron_lib.callbacks import registry
|
from neutron_lib.callbacks import registry
|
||||||
from neutron_lib import constants
|
from neutron_lib import constants
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from oslo_log import log
|
||||||
|
|
||||||
from neutron.agent import securitygroups_rpc
|
from neutron.agent import securitygroups_rpc
|
||||||
from neutron.plugins.common import constants as p_constants
|
from neutron.plugins.common import constants as p_constants
|
||||||
@ -28,6 +29,7 @@ from neutron.plugins.ml2.drivers.openvswitch.agent.common \
|
|||||||
import constants as a_const
|
import constants as a_const
|
||||||
from neutron.services.qos.drivers.openvswitch import driver as ovs_qos_driver
|
from neutron.services.qos.drivers.openvswitch import driver as ovs_qos_driver
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
IPTABLES_FW_DRIVER_FULL = ("neutron.agent.linux.iptables_firewall."
|
IPTABLES_FW_DRIVER_FULL = ("neutron.agent.linux.iptables_firewall."
|
||||||
"OVSHybridIptablesFirewallDriver")
|
"OVSHybridIptablesFirewallDriver")
|
||||||
@ -74,6 +76,20 @@ class OpenvswitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
|
|||||||
"""Currently Openvswitch driver doesn't support vlan transparency."""
|
"""Currently Openvswitch driver doesn't support vlan transparency."""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def bind_port(self, context):
|
||||||
|
vnic_type = context.current.get(portbindings.VNIC_TYPE,
|
||||||
|
portbindings.VNIC_NORMAL)
|
||||||
|
profile = context.current.get(portbindings.PROFILE)
|
||||||
|
capabilities = []
|
||||||
|
if profile:
|
||||||
|
capabilities = profile.get('capabilities', [])
|
||||||
|
if (vnic_type == portbindings.VNIC_DIRECT and
|
||||||
|
'switchdev' not in capabilities):
|
||||||
|
LOG.debug("Refusing to bind due to unsupported vnic_type: %s with "
|
||||||
|
"no switchdev capability", portbindings.VNIC_DIRECT)
|
||||||
|
return
|
||||||
|
super(OpenvswitchMechanismDriver, self).bind_port(context)
|
||||||
|
|
||||||
def get_vif_type(self, context, agent, segment):
|
def get_vif_type(self, context, agent, segment):
|
||||||
caps = agent['configurations'].get('ovs_capabilities', {})
|
caps = agent['configurations'].get('ovs_capabilities', {})
|
||||||
if (any(x in caps.get('iface_types', []) for x
|
if (any(x in caps.get('iface_types', []) for x
|
||||||
|
@ -43,11 +43,12 @@ class FakeNetworkContext(api.NetworkContext):
|
|||||||
class FakePortContext(api.PortContext):
|
class FakePortContext(api.PortContext):
|
||||||
def __init__(self, agent_type, agents, segments,
|
def __init__(self, agent_type, agents, segments,
|
||||||
vnic_type=portbindings.VNIC_NORMAL,
|
vnic_type=portbindings.VNIC_NORMAL,
|
||||||
original=None):
|
original=None, profile=None):
|
||||||
self._agent_type = agent_type
|
self._agent_type = agent_type
|
||||||
self._agents = agents
|
self._agents = agents
|
||||||
self._network_context = FakeNetworkContext(segments)
|
self._network_context = FakeNetworkContext(segments)
|
||||||
self._bound_vnic_type = vnic_type
|
self._bound_vnic_type = vnic_type
|
||||||
|
self._bound_profile = profile
|
||||||
self._bound_segment_id = None
|
self._bound_segment_id = None
|
||||||
self._bound_vif_type = None
|
self._bound_vif_type = None
|
||||||
self._bound_vif_details = None
|
self._bound_vif_details = None
|
||||||
@ -56,7 +57,8 @@ class FakePortContext(api.PortContext):
|
|||||||
@property
|
@property
|
||||||
def current(self):
|
def current(self):
|
||||||
return {'id': PORT_ID,
|
return {'id': PORT_ID,
|
||||||
portbindings.VNIC_TYPE: self._bound_vnic_type}
|
portbindings.VNIC_TYPE: self._bound_vnic_type,
|
||||||
|
portbindings.PROFILE: self._bound_profile}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def original(self):
|
def original(self):
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
from neutron_lib.api.definitions import portbindings
|
from neutron_lib.api.definitions import portbindings
|
||||||
from neutron_lib import constants
|
from neutron_lib import constants
|
||||||
from neutron_lib.plugins.ml2 import api
|
from neutron_lib.plugins.ml2 import api
|
||||||
@ -24,25 +25,16 @@ from neutron.plugins.ml2.drivers.mech_sriov.mech_driver \
|
|||||||
from neutron.plugins.ml2.drivers.mech_sriov.mech_driver import mech_driver
|
from neutron.plugins.ml2.drivers.mech_sriov.mech_driver import mech_driver
|
||||||
from neutron.tests.unit.plugins.ml2 import _test_mech_agent as base
|
from neutron.tests.unit.plugins.ml2 import _test_mech_agent as base
|
||||||
|
|
||||||
MELLANOX_CONNECTX3_PCI_INFO = '15b3:1004'
|
|
||||||
|
|
||||||
|
|
||||||
class TestFakePortContext(base.FakePortContext):
|
class TestFakePortContext(base.FakePortContext):
|
||||||
def __init__(self, agent_type, agents, segments,
|
def __init__(self, agent_type, agents, segments,
|
||||||
vnic_type=portbindings.VNIC_NORMAL,
|
vnic_type=portbindings.VNIC_NORMAL,
|
||||||
profile={'pci_vendor_info':
|
profile=None):
|
||||||
MELLANOX_CONNECTX3_PCI_INFO}):
|
|
||||||
super(TestFakePortContext, self).__init__(agent_type,
|
super(TestFakePortContext, self).__init__(agent_type,
|
||||||
agents,
|
agents,
|
||||||
segments,
|
segments,
|
||||||
vnic_type)
|
vnic_type=vnic_type,
|
||||||
self._bound_profile = profile
|
profile=profile)
|
||||||
|
|
||||||
@property
|
|
||||||
def current(self):
|
|
||||||
return {'id': base.PORT_ID,
|
|
||||||
portbindings.VNIC_TYPE: self._bound_vnic_type,
|
|
||||||
portbindings.PROFILE: self._bound_profile}
|
|
||||||
|
|
||||||
def set_binding(self, segment_id, vif_type, vif_details, state):
|
def set_binding(self, segment_id, vif_type, vif_details, state):
|
||||||
self._bound_segment_id = segment_id
|
self._bound_segment_id = segment_id
|
||||||
@ -145,6 +137,18 @@ class SriovSwitchMechVnicTypeTestCase(SriovNicSwitchMechanismBaseTestCase):
|
|||||||
self._check_vif_type_for_vnic_type(portbindings.VNIC_DIRECT_PHYSICAL,
|
self._check_vif_type_for_vnic_type(portbindings.VNIC_DIRECT_PHYSICAL,
|
||||||
portbindings.VIF_TYPE_HOSTDEV_PHY)
|
portbindings.VIF_TYPE_HOSTDEV_PHY)
|
||||||
|
|
||||||
|
@mock.patch.object(mech_driver.SriovNicSwitchMechanismDriver,
|
||||||
|
'try_to_bind_segment_for_agent')
|
||||||
|
def test_vnic_type_direct_with_switchdev_cap(self, mocked_bind_segment):
|
||||||
|
profile = {'capabilities': ['switchdev']}
|
||||||
|
context = TestFakePortContext(self.AGENT_TYPE,
|
||||||
|
self.AGENTS,
|
||||||
|
self.VLAN_SEGMENTS,
|
||||||
|
portbindings.VNIC_DIRECT,
|
||||||
|
profile)
|
||||||
|
self.driver.bind_port(context)
|
||||||
|
mocked_bind_segment.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
class SriovSwitchMechVifDetailsTestCase(SriovNicSwitchMechanismBaseTestCase):
|
class SriovSwitchMechVifDetailsTestCase(SriovNicSwitchMechanismBaseTestCase):
|
||||||
VLAN_SEGMENTS = [{api.ID: 'vlan_segment_id',
|
VLAN_SEGMENTS = [{api.ID: 'vlan_segment_id',
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
from neutron_lib.api.definitions import portbindings
|
from neutron_lib.api.definitions import portbindings
|
||||||
from neutron_lib.callbacks import events
|
from neutron_lib.callbacks import events
|
||||||
from neutron_lib.callbacks import registry
|
from neutron_lib.callbacks import registry
|
||||||
@ -243,12 +244,23 @@ class OpenvswitchMechanismDPDKTestCase(OpenvswitchMechanismBaseTestCase):
|
|||||||
|
|
||||||
class OpenvswitchMechanismSRIOVTestCase(OpenvswitchMechanismBaseTestCase):
|
class OpenvswitchMechanismSRIOVTestCase(OpenvswitchMechanismBaseTestCase):
|
||||||
|
|
||||||
def _make_port_ctx(self, agents):
|
def _make_port_ctx(self, agents, profile=None):
|
||||||
segments = [{api.ID: 'local_segment_id', api.NETWORK_TYPE: 'local'}]
|
segments = [{api.ID: 'local_segment_id', api.NETWORK_TYPE: 'local'}]
|
||||||
return base.FakePortContext(self.AGENT_TYPE, agents, segments,
|
return base.FakePortContext(self.AGENT_TYPE, agents, segments,
|
||||||
vnic_type=portbindings.VNIC_DIRECT)
|
vnic_type=portbindings.VNIC_DIRECT,
|
||||||
|
profile=profile)
|
||||||
|
|
||||||
def test_get_vif_type(self):
|
@mock.patch('neutron.plugins.ml2.drivers.mech_agent.'
|
||||||
|
'SimpleAgentMechanismDriverBase.bind_port')
|
||||||
|
def test_bind_port_sriov_legacy(self, mocked_bind_port):
|
||||||
context = self._make_port_ctx(self.AGENTS)
|
context = self._make_port_ctx(self.AGENTS)
|
||||||
result = self.driver.get_vif_type(context, self.AGENTS[0], None)
|
self.driver.bind_port(context)
|
||||||
self.assertEqual(self.VIF_TYPE, result)
|
mocked_bind_port.assert_not_called()
|
||||||
|
|
||||||
|
@mock.patch('neutron.plugins.ml2.drivers.mech_agent.'
|
||||||
|
'SimpleAgentMechanismDriverBase.bind_port')
|
||||||
|
def test_bind_port_sriov_switchdev(self, mocked_bind_port):
|
||||||
|
profile = {'capabilities': ['switchdev']}
|
||||||
|
context = self._make_port_ctx(self.AGENTS, profile=profile)
|
||||||
|
self.driver.bind_port(context)
|
||||||
|
mocked_bind_port.assert_called()
|
||||||
|
Loading…
Reference in New Issue
Block a user