diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_tun.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_tun.py index 67c6273e71b..f71d7acd9d4 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_tun.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_tun.py @@ -52,78 +52,83 @@ class OVSTunnelBridge(ovs_bridge.OVSAgentBridge, def setup_default_table(self, patch_int_ofport, arp_responder_enabled): # Table 0 (default) will sort incoming traffic depending on in_port - self.add_flow(priority=1, - in_port=patch_int_ofport, - actions="resubmit(,%s)" % - constants.PATCH_LV_TO_TUN) - self.add_flow(priority=0, actions="drop") + with self.deferred() as deferred_br: + deferred_br.add_flow(priority=1, + in_port=patch_int_ofport, + actions="resubmit(,%s)" % + constants.PATCH_LV_TO_TUN) + deferred_br.add_flow(priority=0, actions="drop") - if arp_responder_enabled: - # ARP broadcast-ed request go to the local ARP_RESPONDER table to - # be locally resolved - # REVISIT(yamamoto): arp_op=arp.ARP_REQUEST - self.add_flow(table=constants.PATCH_LV_TO_TUN, - priority=1, - proto='arp', - dl_dst="ff:ff:ff:ff:ff:ff", - actions=("resubmit(,%s)" % - constants.ARP_RESPONDER)) + if arp_responder_enabled: + # ARP broadcast-ed request go to the local ARP_RESPONDER + # table to be locally resolved + # REVISIT(yamamoto): arp_op=arp.ARP_REQUEST + deferred_br.add_flow(table=constants.PATCH_LV_TO_TUN, + priority=1, + proto='arp', + dl_dst="ff:ff:ff:ff:ff:ff", + actions=("resubmit(,%s)" % + constants.ARP_RESPONDER)) - # PATCH_LV_TO_TUN table will handle packets coming from patch_int - # unicasts go to table UCAST_TO_TUN where remote addresses are learnt - self.add_flow(table=constants.PATCH_LV_TO_TUN, - priority=0, - dl_dst="00:00:00:00:00:00/01:00:00:00:00:00", - actions="resubmit(,%s)" % constants.UCAST_TO_TUN) + # PATCH_LV_TO_TUN table will handle packets coming from patch_int + # unicasts go to table UCAST_TO_TUN where remote addresses are + # learnt + deferred_br.add_flow(table=constants.PATCH_LV_TO_TUN, + priority=0, + dl_dst="00:00:00:00:00:00/01:00:00:00:00:00", + actions=("resubmit(,%s)" % + constants.UCAST_TO_TUN)) - # Broadcasts/multicasts go to table FLOOD_TO_TUN that handles flooding - self.add_flow(table=constants.PATCH_LV_TO_TUN, - priority=0, - dl_dst="01:00:00:00:00:00/01:00:00:00:00:00", - actions="resubmit(,%s)" % constants.FLOOD_TO_TUN) + # Broadcasts/multicasts go to table FLOOD_TO_TUN that handles + # flooding + deferred_br.add_flow(table=constants.PATCH_LV_TO_TUN, + priority=0, + dl_dst="01:00:00:00:00:00/01:00:00:00:00:00", + actions=("resubmit(,%s)" % + constants.FLOOD_TO_TUN)) - # Tables [tunnel_type]_TUN_TO_LV will set lvid depending on tun_id - # for each tunnel type, and resubmit to table LEARN_FROM_TUN where - # remote mac addresses will be learnt - for tunnel_type in constants.TUNNEL_NETWORK_TYPES: - self.add_flow(table=constants.TUN_TABLE[tunnel_type], - priority=0, - actions="drop") + # Tables [tunnel_type]_TUN_TO_LV will set lvid depending on tun_id + # for each tunnel type, and resubmit to table LEARN_FROM_TUN where + # remote mac addresses will be learnt + for tunnel_type in constants.TUNNEL_NETWORK_TYPES: + deferred_br.add_flow(table=constants.TUN_TABLE[tunnel_type], + priority=0, actions="drop") - # LEARN_FROM_TUN table will have a single flow using a learn action to - # dynamically set-up flows in UCAST_TO_TUN corresponding to remote mac - # addresses (assumes that lvid has already been set by a previous flow) - learned_flow = ("table=%s," - "priority=1," - "hard_timeout=300," - "NXM_OF_VLAN_TCI[0..11]," - "NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]," - "load:0->NXM_OF_VLAN_TCI[]," - "load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[]," - "output:NXM_OF_IN_PORT[]" % - constants.UCAST_TO_TUN) - # Once remote mac addresses are learnt, output packet to patch_int - self.add_flow(table=constants.LEARN_FROM_TUN, - priority=1, - actions="learn(%s),output:%s" % - (learned_flow, patch_int_ofport)) + # LEARN_FROM_TUN table will have a single flow using a learn action + # to dynamically set-up flows in UCAST_TO_TUN corresponding to + # remote mac addresses (assumes that lvid has already been set by + # a previous flow) + learned_flow = ("table=%s," + "priority=1," + "hard_timeout=300," + "NXM_OF_VLAN_TCI[0..11]," + "NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]," + "load:0->NXM_OF_VLAN_TCI[]," + "load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[]," + "output:NXM_OF_IN_PORT[]" % + constants.UCAST_TO_TUN) + # Once remote mac addresses are learnt, output packet to patch_int + deferred_br.add_flow(table=constants.LEARN_FROM_TUN, + priority=1, + actions="learn(%s),output:%s" % + (learned_flow, patch_int_ofport)) - # Egress unicast will be handled in table UCAST_TO_TUN, where remote - # mac addresses will be learned. For now, just add a default flow that - # will resubmit unknown unicasts to table FLOOD_TO_TUN to treat them - # as broadcasts/multicasts - self.add_flow(table=constants.UCAST_TO_TUN, - priority=0, - actions="resubmit(,%s)" % - constants.FLOOD_TO_TUN) + # Egress unicast will be handled in table UCAST_TO_TUN, where + # remote mac addresses will be learned. For now, just add a + # default flow that will resubmit unknown unicasts to table + # FLOOD_TO_TUN to treat them as broadcasts/multicasts + deferred_br.add_flow(table=constants.UCAST_TO_TUN, + priority=0, + actions="resubmit(,%s)" % + constants.FLOOD_TO_TUN) - if arp_responder_enabled: - # If none of the ARP entries correspond to the requested IP, the - # broadcast-ed packet is resubmitted to the flooding table - self.add_flow(table=constants.ARP_RESPONDER, - priority=0, - actions="resubmit(,%s)" % - constants.FLOOD_TO_TUN) + if arp_responder_enabled: + # If none of the ARP entries correspond to the requested IP, + # the broadcast-ed packet is resubmitted to the flooding table + deferred_br.add_flow(table=constants.ARP_RESPONDER, + priority=0, + actions="resubmit(,%s)" % + constants.FLOOD_TO_TUN) # FLOOD_TO_TUN will handle flooding in tunnels based on lvid, # for now, add a default drop action diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_tun.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_tun.py index 76769a34fde..485523129e3 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_tun.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_tun.py @@ -37,65 +37,69 @@ class OVSTunnelBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase, def test_setup_default_table(self): patch_int_ofport = 5555 - arp_responder_enabled = False + mock_do_action_flows = mock.patch.object(self.br, + 'do_action_flows').start() + self.mock.attach_mock(mock_do_action_flows, 'do_action_flows') self.br.setup_default_table(patch_int_ofport=patch_int_ofport, - arp_responder_enabled=arp_responder_enabled) - expected = [ - call.add_flow(priority=1, in_port=patch_int_ofport, - actions='resubmit(,2)'), - call.add_flow(priority=0, actions='drop'), - call.add_flow(priority=0, table=2, - dl_dst='00:00:00:00:00:00/01:00:00:00:00:00', - actions='resubmit(,20)'), - call.add_flow(priority=0, table=2, - dl_dst='01:00:00:00:00:00/01:00:00:00:00:00', - actions='resubmit(,22)'), - call.add_flow(priority=0, table=3, actions='drop'), - call.add_flow(priority=0, table=4, actions='drop'), - call.add_flow(priority=1, table=10, - actions='learn(table=20,priority=1,' - 'hard_timeout=300,NXM_OF_VLAN_TCI[0..11],' - 'NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],' - 'load:0->NXM_OF_VLAN_TCI[],' - 'load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],' - 'output:NXM_OF_IN_PORT[]),' - 'output:%s' % patch_int_ofport), - call.add_flow(priority=0, table=20, actions='resubmit(,22)'), - call.add_flow(priority=0, table=22, actions='drop'), - ] + arp_responder_enabled=False) + flow_args = [{'priority': 1, 'in_port': patch_int_ofport, + 'actions': 'resubmit(,2)'}, + {'priority': 0, 'actions': 'drop'}, + {'priority': 0, 'table': 2, + 'dl_dst': '00:00:00:00:00:00/01:00:00:00:00:00', + 'actions': 'resubmit(,20)'}, + {'priority': 0, 'table': 2, + 'dl_dst': '01:00:00:00:00:00/01:00:00:00:00:00', + 'actions': 'resubmit(,22)'}, + {'priority': 0, 'table': 3, 'actions': 'drop'}, + {'priority': 0, 'table': 4, 'actions': 'drop'}, + {'priority': 1, 'table': 10, + 'actions': 'learn(table=20,priority=1,' + 'hard_timeout=300,NXM_OF_VLAN_TCI[0..11],' + 'NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],' + 'load:0->NXM_OF_VLAN_TCI[],' + 'load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],' + 'output:NXM_OF_IN_PORT[]),' + 'output:%s' % patch_int_ofport}, + {'priority': 0, 'table': 20, 'actions': 'resubmit(,22)'} + ] + expected = [call.do_action_flows('add', flow_args), + call.add_flow(priority=0, table=22, actions='drop')] self.assertEqual(expected, self.mock.mock_calls) def test_setup_default_table_arp_responder_enabled(self): patch_int_ofport = 5555 - arp_responder_enabled = True + mock_do_action_flows = mock.patch.object(self.br, + 'do_action_flows').start() + self.mock.attach_mock(mock_do_action_flows, 'do_action_flows') self.br.setup_default_table(patch_int_ofport=patch_int_ofport, - arp_responder_enabled=arp_responder_enabled) - expected = [ - call.add_flow(priority=1, in_port=patch_int_ofport, - actions='resubmit(,2)'), - call.add_flow(priority=0, actions='drop'), - call.add_flow(priority=1, table=2, dl_dst='ff:ff:ff:ff:ff:ff', - actions='resubmit(,21)', proto='arp'), - call.add_flow(priority=0, table=2, - dl_dst='00:00:00:00:00:00/01:00:00:00:00:00', - actions='resubmit(,20)'), - call.add_flow(priority=0, table=2, - dl_dst='01:00:00:00:00:00/01:00:00:00:00:00', - actions='resubmit(,22)'), - call.add_flow(priority=0, table=3, actions='drop'), - call.add_flow(priority=0, table=4, actions='drop'), - call.add_flow(priority=1, table=10, - actions='learn(table=20,priority=1,' - 'hard_timeout=300,NXM_OF_VLAN_TCI[0..11],' - 'NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],' - 'load:0->NXM_OF_VLAN_TCI[],' - 'load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],' - 'output:NXM_OF_IN_PORT[]),' - 'output:%s' % patch_int_ofport), - call.add_flow(priority=0, table=20, actions='resubmit(,22)'), - call.add_flow(priority=0, table=21, actions='resubmit(,22)'), - call.add_flow(priority=0, table=22, actions='drop'), - ] + arp_responder_enabled=True) + flow_args = [{'priority': 1, 'in_port': patch_int_ofport, + 'actions': 'resubmit(,2)'}, + {'priority': 0, 'actions': 'drop'}, + {'priority': 1, 'table': 2, 'dl_dst': 'ff:ff:ff:ff:ff:ff', + 'actions': 'resubmit(,21)', 'proto': 'arp'}, + {'priority': 0, 'table': 2, + 'dl_dst': '00:00:00:00:00:00/01:00:00:00:00:00', + 'actions': 'resubmit(,20)'}, + {'priority': 0, 'table': 2, + 'dl_dst': '01:00:00:00:00:00/01:00:00:00:00:00', + 'actions': 'resubmit(,22)'}, + {'priority': 0, 'table': 3, 'actions': 'drop'}, + {'priority': 0, 'table': 4, 'actions': 'drop'}, + {'priority': 1, 'table': 10, + 'actions': 'learn(table=20,priority=1,' + 'hard_timeout=300,NXM_OF_VLAN_TCI[0..11],' + 'NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],' + 'load:0->NXM_OF_VLAN_TCI[],' + 'load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],' + 'output:NXM_OF_IN_PORT[]),' + 'output:%s' % patch_int_ofport}, + {'priority': 0, 'table': 20, 'actions': 'resubmit(,22)'}, + {'priority': 0, 'table': 21, 'actions': 'resubmit(,22)'} + ] + expected = [call.do_action_flows('add', flow_args), + call.add_flow(priority=0, table=22, actions='drop')] self.assertEqual(expected, self.mock.mock_calls) def test_provision_local_vlan(self):