diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_tun.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_tun.py index 921254e6fe9..3af64bd1012 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_tun.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_tun.py @@ -33,13 +33,19 @@ class OVSTunnelBridge(ovs_bridge.OVSAgentBridge, dvr_process_next_table_id = constants.PATCH_LV_TO_TUN of_tables = constants.TUN_BR_ALL_TABLES - def setup_default_table(self, patch_int_ofport, arp_responder_enabled): + def setup_default_table( + self, patch_int_ofport, arp_responder_enabled, dvr_enabled): (dp, ofp, ofpp) = self._get_dp() - # Table 0 (default) will sort incoming traffic depending on in_port - self.install_goto(dest_table_id=constants.PATCH_LV_TO_TUN, - priority=1, - in_port=patch_int_ofport) + if not dvr_enabled: + # Table 0 (default) will sort incoming traffic depending on in_port + # This table is needed only for non-dvr environment because + # OVSDVRProcessMixin overwrites this flow in its + # install_dvr_process() method. + self.install_goto(dest_table_id=constants.PATCH_LV_TO_TUN, + priority=1, + in_port=patch_int_ofport) + self.install_drop() # default drop if arp_responder_enabled: diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py index 7b8c7b19a3e..971ca122506 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py @@ -264,16 +264,20 @@ class OVSDVRNeutronAgent(object): if not self.enable_tunneling: return - self.tun_br.install_goto(dest_table_id=ovs_constants.DVR_PROCESS, - priority=1, - in_port=self.patch_int_ofport) + self._setup_dvr_flows_on_tun_br(self.tun_br, self.patch_int_ofport) + + @staticmethod + def _setup_dvr_flows_on_tun_br(tun_br, patch_int_ofport): + tun_br.install_goto(dest_table_id=ovs_constants.DVR_PROCESS, + priority=1, + in_port=patch_int_ofport) # table-miss should be sent to learning table - self.tun_br.install_goto(table_id=ovs_constants.DVR_NOT_LEARN, - dest_table_id=ovs_constants.LEARN_FROM_TUN) + tun_br.install_goto(table_id=ovs_constants.DVR_NOT_LEARN, + dest_table_id=ovs_constants.LEARN_FROM_TUN) - self.tun_br.install_goto(table_id=ovs_constants.DVR_PROCESS, - dest_table_id=ovs_constants.PATCH_LV_TO_TUN) + tun_br.install_goto(table_id=ovs_constants.DVR_PROCESS, + dest_table_id=ovs_constants.PATCH_LV_TO_TUN) def setup_dvr_flows_on_phys_br(self, bridge_mappings=None): '''Setup up initial dvr flows into br-phys''' diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py index 724a050451d..ad8603bceba 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -1563,7 +1563,8 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, Add all flows to the tunnel bridge. ''' self.tun_br.setup_default_table(self.patch_int_ofport, - self.arp_responder_enabled) + self.arp_responder_enabled, + self.enable_distributed_routing) def _reconfigure_physical_bridges(self, bridges): try: diff --git a/neutron/tests/functional/agent/test_ovs_flows.py b/neutron/tests/functional/agent/test_ovs_flows.py index d11c23cd960..130ef426e93 100644 --- a/neutron/tests/functional/agent/test_ovs_flows.py +++ b/neutron/tests/functional/agent/test_ovs_flows.py @@ -24,6 +24,8 @@ from neutron.agent.common import utils from neutron.agent.linux import ip_lib from neutron.cmd.sanity import checks from neutron.common import utils as common_utils +from neutron.plugins.ml2.drivers.openvswitch.agent \ + import ovs_dvr_neutron_agent as ovsdvragt from neutron.plugins.ml2.drivers.openvswitch.agent \ import ovs_neutron_agent as ovsagt from neutron.tests.common import base as common_base @@ -311,8 +313,9 @@ class OVSFlowTestCase(OVSAgentTestBase): """ def setUp(self): + dvr_enabled = True cfg.CONF.set_override('enable_distributed_routing', - True, + dvr_enabled, group='AGENT') super(OVSFlowTestCase, self).setUp() self.phys_br = self.useFixture(net_helpers.OVSBridgeFixture()).bridge @@ -334,7 +337,9 @@ class OVSFlowTestCase(OVSAgentTestBase): prefix=cfg.CONF.OVS.tun_peer_patch_port), common_utils.get_rand_device_name( prefix=cfg.CONF.OVS.int_peer_patch_port)) - self.br_tun.setup_default_table(self.tun_p, True) + self.br_tun.setup_default_table(self.tun_p, True, dvr_enabled) + ovsdvragt.OVSDVRNeutronAgent._setup_dvr_flows_on_tun_br(self.br_tun, + self.tun_p) def test_provision_local_vlan(self): kwargs = {'port': 123, 'lvid': 888, 'segmentation_id': 777} diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/native/test_br_tun.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/native/test_br_tun.py index 0b3ab1c894c..45da220cd39 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/native/test_br_tun.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/native/test_br_tun.py @@ -52,7 +52,8 @@ class OVSTunnelBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase, patch_int_ofport = 5555 arp_responder_enabled = False self.br.setup_default_table(patch_int_ofport=patch_int_ofport, - arp_responder_enabled=arp_responder_enabled) + arp_responder_enabled=arp_responder_enabled, + dvr_enabled=False) (dp, ofp, ofpp) = self._get_dp() expected = [ call._send_msg(ofpp.OFPFlowMod(dp, @@ -160,7 +161,8 @@ class OVSTunnelBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase, patch_int_ofport = 5555 arp_responder_enabled = True self.br.setup_default_table(patch_int_ofport=patch_int_ofport, - arp_responder_enabled=arp_responder_enabled) + arp_responder_enabled=arp_responder_enabled, + dvr_enabled=False) (dp, ofp, ofpp) = self._get_dp() expected = [ call._send_msg(ofpp.OFPFlowMod(dp, @@ -280,6 +282,33 @@ class OVSTunnelBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase, ] self.assertEqual(expected, self.mock.mock_calls) + def _test_setup_default_table_dvr_helper(self, dvr_enabled): + patch_int_ofport = 5555 + arp_responder_enabled = True + self.br.setup_default_table(patch_int_ofport=patch_int_ofport, + arp_responder_enabled=arp_responder_enabled, + dvr_enabled=dvr_enabled) + (dp, ofp, ofpp) = self._get_dp() + non_dvr_specific_call = call._send_msg( + ofpp.OFPFlowMod( + dp, + cookie=self.stamp, + instructions=[ofpp.OFPInstructionGotoTable(table_id=2)], + match=ofpp.OFPMatch(in_port=patch_int_ofport), + priority=1, table_id=0), + active_bundle=None) + + if dvr_enabled: + self.assertNotIn(non_dvr_specific_call, self.mock.mock_calls) + else: + self.assertIn(non_dvr_specific_call, self.mock.mock_calls) + + def test_setup_default_table_dvr_enabled(self): + self._test_setup_default_table_dvr_helper(dvr_enabled=True) + + def test_setup_default_table_dvr_disabled(self): + self._test_setup_default_table_dvr_helper(dvr_enabled=False) + def test_provision_local_vlan(self): network_type = 'vxlan' lvid = 888 diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py index 5ee8357834f..aedd89d852c 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py @@ -188,7 +188,8 @@ class TunnelTest(object): '_check_bridge_datapath_id').start() self._define_expected_calls() - def _define_expected_calls(self, arp_responder=False, igmp_snooping=False): + def _define_expected_calls( + self, arp_responder=False, igmp_snooping=False): self.mock_int_bridge_cls_expected = [ mock.call(self.INT_BRIDGE, datapath_type=mock.ANY), @@ -268,7 +269,11 @@ class TunnelTest(object): ] self.mock_tun_bridge_expected += [ - mock.call.setup_default_table(self.INT_OFPORT, arp_responder), + # NOTE: Parameters passed to setup_default_table() method are named + # in the production code. That's why we can't use keyword parameter + # here. The last parameter passed below is dvr_enabled set to False + mock.call.setup_default_table( + self.INT_OFPORT, arp_responder, False), ] self.ipdevice_expected = []