diff --git a/neutron/plugins/ml2/drivers/mech_sriov/mech_driver/mech_driver.py b/neutron/plugins/ml2/drivers/mech_sriov/mech_driver/mech_driver.py index ca471b35c04..090c561e7bc 100644 --- a/neutron/plugins/ml2/drivers/mech_sriov/mech_driver/mech_driver.py +++ b/neutron/plugins/ml2/drivers/mech_sriov/mech_driver/mech_driver.py @@ -135,6 +135,22 @@ class SriovNicSwitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase): vnic_type) return + allowed_binding_segments = [] + + subnets = self.get_subnets_from_fixed_ips(context) + if subnets: + # In case that fixed IPs is provided, filter segments per subnet + # that they belong to first. + for segment in context.segments_to_bind: + for subnet in subnets: + seg_id = subnet.get('segment_id') + # If subnet is not attached to any segment, let's use + # default behavior. + if seg_id is None or seg_id == segment[api.ID]: + allowed_binding_segments.append(segment) + else: + allowed_binding_segments = context.segments_to_bind + 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 @@ -143,7 +159,7 @@ class SriovNicSwitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase): # either. This should be changed in the future so physical # functions can use device mapping checks and the plugin can # get port status updates. - for segment in context.segments_to_bind: + for segment in allowed_binding_segments: if self.try_to_bind_segment_for_agent(context, segment, agent=None): break @@ -152,7 +168,7 @@ class SriovNicSwitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase): for agent in context.host_agents(self.agent_type): LOG.debug("Checking agent: %s", agent) if agent['alive']: - for segment in context.segments_to_bind: + for segment in allowed_binding_segments: if self.try_to_bind_segment_for_agent(context, segment, agent): return diff --git a/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/mech_driver/test_mech_sriov_nic_switch.py b/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/mech_driver/test_mech_sriov_nic_switch.py index 7736cf3d239..a24ee351f55 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/mech_driver/test_mech_sriov_nic_switch.py +++ b/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/mech_driver/test_mech_sriov_nic_switch.py @@ -131,10 +131,14 @@ class SriovMechVlanTestCase(SriovNicSwitchMechanismBaseTestCase, base.AgentMechanismBaseTestCase): VLAN_SEGMENTS = [{api.ID: 'unknown_segment_id', api.NETWORK_TYPE: 'no_such_type'}, - {api.ID: 'vlan_segment_id', + {api.ID: 'vlan_segment_id_1', api.NETWORK_TYPE: 'vlan', api.PHYSICAL_NETWORK: 'fake_physical_network', - api.SEGMENTATION_ID: 1234}] + api.SEGMENTATION_ID: 1234}, + {api.ID: 'vlan_segment_id_2', + api.NETWORK_TYPE: 'vlan', + api.PHYSICAL_NETWORK: 'fake_physical_network', + api.SEGMENTATION_ID: 5678}] def test_type_vlan(self): context = TestFakePortContext(self.AGENT_TYPE, @@ -152,6 +156,32 @@ class SriovMechVlanTestCase(SriovNicSwitchMechanismBaseTestCase, self.driver.bind_port(context) self._check_unbound(context) + @mock.patch.object(mech_driver.SriovNicSwitchMechanismDriver, + 'get_subnets_from_fixed_ips') + def test_type_vlan_fixed_ip_l3(self, mocked_subnets_from_fixed_ips): + subnets = [{"segment_id": "vlan_segment_id_2"}] + context = TestFakePortContext(self.AGENT_TYPE, + self.AGENTS, + self.VLAN_SEGMENTS, + portbindings.VNIC_DIRECT) + mocked_subnets_from_fixed_ips.return_value = subnets + self.driver.bind_port(context) + mocked_subnets_from_fixed_ips.assert_called_once_with(context) + self._check_bound(context, self.VLAN_SEGMENTS[2]) + + @mock.patch.object(mech_driver.SriovNicSwitchMechanismDriver, + 'get_subnets_from_fixed_ips') + def test_type_vlan_fixed_ip_l2(self, mocked_subnets_from_fixed_ips): + subnets = [{"segment_id": None}] + context = TestFakePortContext(self.AGENT_TYPE, + self.AGENTS, + self.VLAN_SEGMENTS, + portbindings.VNIC_DIRECT) + mocked_subnets_from_fixed_ips.return_value = subnets + self.driver.bind_port(context) + mocked_subnets_from_fixed_ips.assert_called_once_with(context) + self._check_bound(context, self.VLAN_SEGMENTS[1]) + class SriovSwitchMechVnicTypeTestCase(SriovNicSwitchMechanismBaseTestCase): def _check_vif_type_for_vnic_type(self, vnic_type,