]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Enable GRE and VXLAN with the same ID
authorFrancois Eleouet <f.eleouet@gmail.com>
Wed, 7 Aug 2013 09:19:46 +0000 (11:19 +0200)
committerFrancois Eleouet <f.eleouet@gmail.com>
Thu, 22 Aug 2013 16:06:16 +0000 (18:06 +0200)
Current packet processing in br-tun is based on tun-id,
as a consequence, two networks using different tunnel
types but sharing the same tun-id would not be properly isolated.

To ensure proper isolation within a single bridge, NORMAL action
can't be used any more as it floods unknown unicasts on all
bridges ports. It is replaced by a learn action that dynamically
sets-up flows when packets are recieved from tunnel ports. As mac
address are learnt in explicit flows (in table 20), we can use a
default action in that table to flood unknown unicasts to the
right set of ports, like broadcasts and multicasts packets.

See https://wiki.openstack.org/wiki/Ovs-flow-logic for a more
detailled explanation of the flow logic

Another alternative could have been to use distinct bridges for
each tunnel type (whithout modifying the current flow logic),
but previous alternative may be preferable as it paves the way
for new tunneling optimisations (like RPC based mac learning and
partial-mesh flooding proposed in bp/l2-population)

Change-Id: I1dfe74f96680c2c6fe4d8d4aac4821c6b020c005
Closes-Bug: #1196963

neutron/agent/linux/ovs_lib.py
neutron/plugins/openvswitch/agent/ovs_neutron_agent.py
neutron/plugins/openvswitch/common/constants.py
neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py
neutron/tests/unit/openvswitch/test_ovs_tunnel.py

index 9dbadb66645a817254bc0c25314c34245fcf176b..2c2bd9d8b507687c89fa5f8dce47e0ce03585b1f 100644 (file)
@@ -126,6 +126,8 @@ class OVSBridge:
         elif 'priority' in kwargs:
             raise Exception(_("Cannot match priority on flow deletion"))
 
+        table = ('table' in kwargs and ",table=%s" %
+                 kwargs['table'] or '')
         in_port = ('in_port' in kwargs and ",in_port=%s" %
                    kwargs['in_port'] or '')
         dl_type = ('dl_type' in kwargs and ",dl_type=%s" %
@@ -139,14 +141,14 @@ class OVSBridge:
         tun_id = 'tun_id' in kwargs and ",tun_id=%s" % kwargs['tun_id'] or ''
         proto = 'proto' in kwargs and ",%s" % kwargs['proto'] or ''
         ip = ('nw_src' in kwargs or 'nw_dst' in kwargs) and ',ip' or ''
-        match = (in_port + dl_type + dl_vlan + dl_src + dl_dst +
+        match = (table + in_port + dl_type + dl_vlan + dl_src + dl_dst +
                 (ip or proto) + nw_src + nw_dst + tun_id)
         if match:
             match = match[1:]  # strip leading comma
             flow_expr_arr.append(match)
         return flow_expr_arr
 
-    def add_flow(self, **kwargs):
+    def add_or_mod_flow_str(self, **kwargs):
         if "actions" not in kwargs:
             raise Exception(_("Must specify one or more actions"))
         if "priority" not in kwargs:
@@ -155,8 +157,16 @@ class OVSBridge:
         flow_expr_arr = self._build_flow_expr_arr(**kwargs)
         flow_expr_arr.append("actions=%s" % (kwargs["actions"]))
         flow_str = ",".join(flow_expr_arr)
+        return flow_str
+
+    def add_flow(self, **kwargs):
+        flow_str = self.add_or_mod_flow_str(**kwargs)
         self.run_ofctl("add-flow", [flow_str])
 
+    def mod_flow(self, **kwargs):
+        flow_str = self.add_or_mod_flow_str(**kwargs)
+        self.run_ofctl("mod-flows", [flow_str])
+
     def delete_flows(self, **kwargs):
         kwargs['delete'] = True
         flow_expr_arr = self._build_flow_expr_arr(**kwargs)
index 842dda911829d0f4dbb777a5c5e20b9fa0ddaf16..db7b92b0cca118886186cb72ceaf10073f03c239 100644 (file)
@@ -172,6 +172,8 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
         self.int_br = self.setup_integration_br(integ_br)
         self.setup_physical_bridges(bridge_mappings)
         self.local_vlan_map = {}
+        self.tun_br_ofports = {constants.TYPE_GRE: set(),
+                               constants.TYPE_VXLAN: set()}
 
         self.polling_interval = polling_interval
 
@@ -307,8 +309,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
         if tunnel_ip == self.local_ip:
             return
         tun_name = '%s-%s' % (tunnel_type, tunnel_id)
-        self.tun_br.add_tunnel_port(tun_name, tunnel_ip, self.local_ip,
-                                    tunnel_type, self.vxlan_udp_port)
+        self.setup_tunnel_port(tun_name, tunnel_ip, tunnel_type)
 
     def create_rpc_dispatcher(self):
         '''Get the rpc dispatcher for this manager.
@@ -342,18 +343,20 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
 
         if network_type in constants.TUNNEL_NETWORK_TYPES:
             if self.enable_tunneling:
-                # outbound
-                self.tun_br.add_flow(priority=4, in_port=self.patch_int_ofport,
+                # outbound broadcast/multicast
+                ofports = ','.join(self.tun_br_ofports[network_type])
+                self.tun_br.mod_flow(table=constants.FLOOD_TO_TUN,
+                                     priority=1,
                                      dl_vlan=lvid,
-                                     actions="set_tunnel:%s,normal" %
-                                     segmentation_id)
-                # inbound bcast/mcast
-                self.tun_br.add_flow(
-                    priority=3,
-                    tun_id=segmentation_id,
-                    dl_dst="01:00:00:00:00:00/01:00:00:00:00:00",
-                    actions="mod_vlan_vid:%s,output:%s" %
-                    (lvid, self.patch_int_ofport))
+                                     actions="strip_vlan,set_tunnel:%s,"
+                                     "output:%s" % (segmentation_id, ofports))
+                # inbound from tunnels: set lvid in the right table
+                # and resubmit to Table LEARN_FROM_TUN for mac learning
+                self.tun_br.add_flow(table=constants.TUN_TABLE[network_type],
+                                     priority=1,
+                                     tun_id=segmentation_id,
+                                     actions="mod_vlan_vid:%s,resubmit(,%s)" %
+                                     (lvid, constants.LEARN_FROM_TUN))
             else:
                 LOG.error(_("Cannot provision %(network_type)s network for "
                           "net-id=%(net_uuid)s - tunneling disabled"),
@@ -421,7 +424,9 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
 
         if lvm.network_type in constants.TUNNEL_NETWORK_TYPES:
             if self.enable_tunneling:
-                self.tun_br.delete_flows(tun_id=lvm.segmentation_id)
+                self.tun_br.delete_flows(
+                    table=constants.TUN_TABLE[lvm.network_type],
+                    tun_id=lvm.segmentation_id)
                 self.tun_br.delete_flows(dl_vlan=lvm.vlan)
         elif lvm.network_type == constants.TYPE_FLAT:
             if lvm.physical_network in self.phys_brs:
@@ -474,14 +479,6 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
         lvm = self.local_vlan_map[net_uuid]
         lvm.vif_ports[port.vif_id] = port
 
-        if network_type in constants.TUNNEL_NETWORK_TYPES:
-            if self.enable_tunneling:
-                # inbound unicast
-                self.tun_br.add_flow(priority=3, tun_id=segmentation_id,
-                                     dl_dst=port.vif_mac,
-                                     actions="mod_vlan_vid:%s,normal" %
-                                     lvm.vlan)
-
         self.int_br.set_db_attribute("Port", port.port_name, "tag",
                                      str(lvm.vlan))
         if int(port.ofport) != -1:
@@ -503,18 +500,9 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
             LOG.info(_('port_unbound() net_uuid %s not in local_vlan_map'),
                      net_uuid)
             return
-        lvm = self.local_vlan_map[net_uuid]
 
-        vif_port = lvm.vif_ports.pop(vif_id, None)
-        if vif_port:
-            if self.enable_tunneling and lvm.network_type in (
-                    constants.TUNNEL_NETWORK_TYPES):
-                # remove inbound unicast flow
-                self.tun_br.delete_flows(tun_id=lvm.segmentation_id,
-                                         dl_dst=vif_port.vif_mac)
-        else:
-            LOG.info(_('port_unbound: vif_id %s not in local_vlan_map'),
-                     vif_id)
+        lvm = self.local_vlan_map[net_uuid]
+        lvm.vif_ports.pop(vif_id, None)
 
         if not lvm.vif_ports:
             self.reclaim_local_vlan(net_uuid, lvm)
@@ -590,7 +578,58 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
                         "Agent terminated!"))
             exit(1)
         self.tun_br.remove_all_flows()
-        self.tun_br.add_flow(priority=1, actions="drop")
+
+        # Table 0 (default) will sort incoming traffic depending on in_port
+        self.tun_br.add_flow(priority=1,
+                             in_port=self.patch_int_ofport,
+                             actions="resubmit(,%s)" %
+                             constants.PATCH_LV_TO_TUN)
+        self.tun_br.add_flow(priority=0, actions="drop")
+        # PATCH_LV_TO_TUN table will handle packets coming from patch_int
+        # unicasts go to table UCAST_TO_TUN where remote adresses are learnt
+        self.tun_br.add_flow(table=constants.PATCH_LV_TO_TUN,
+                             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.tun_br.add_flow(table=constants.PATCH_LV_TO_TUN,
+                             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 adresses will be learnt
+        for tunnel_type in constants.TUNNEL_NETWORK_TYPES:
+            self.tun_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
+        # adresses (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],"
+                        "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 adresses are learnt, packet is outputed to patch_int
+        self.tun_br.add_flow(table=constants.LEARN_FROM_TUN,
+                             priority=1,
+                             actions="learn(%s),output:%s" %
+                             (learned_flow, self.patch_int_ofport))
+        # Egress unicast will be handled in table UCAST_TO_TUN, where remote
+        # mac adresses 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.tun_br.add_flow(table=constants.UCAST_TO_TUN,
+                             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
+        self.tun_br.add_flow(table=constants.FLOOD_TO_TUN,
+                             priority=0,
+                             actions="drop")
 
     def setup_physical_bridges(self, bridge_mappings):
         '''Setup the physical network bridges.
@@ -685,6 +724,35 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
         else:
             LOG.debug(_("No VIF port for port %s defined on agent."), port_id)
 
+    def setup_tunnel_port(self, port_name, remote_ip, tunnel_type):
+        ofport = self.tun_br.add_tunnel_port(port_name,
+                                             remote_ip,
+                                             self.local_ip,
+                                             tunnel_type,
+                                             self.vxlan_udp_port)
+        if ofport < 0:
+            LOG.error(_("Failed to set-up %(type)s tunnel port to %(ip)s"),
+                      {'type': tunnel_type, 'ip': remote_ip})
+        else:
+            self.tun_br_ofports[tunnel_type].add(ofport)
+            # Add flow in default table to resubmit to the right
+            # tunelling table (lvid will be set in the latter)
+            self.tun_br.add_flow(priority=1,
+                                 in_port=ofport,
+                                 actions="resubmit(,%s)" %
+                                 constants.TUN_TABLE[tunnel_type])
+            # Update flooding flows to include the new tunnel
+            ofports = ','.join(self.tun_br_ofports[tunnel_type])
+            for network_id, vlan_mapping in self.local_vlan_map.iteritems():
+                if vlan_mapping.network_type == tunnel_type:
+                    self.tun_br.mod_flow(table=constants.FLOOD_TO_TUN,
+                                         priority=1,
+                                         dl_vlan=vlan_mapping.vlan,
+                                         actions="strip_vlan,"
+                                         "set_tunnel:%s,output:%s" %
+                                         (vlan_mapping.segmentation_id,
+                                          ofports))
+
     def treat_devices_added(self, devices):
         resync = False
         self.sg_agent.prepare_devices_filter(devices)
@@ -806,11 +874,9 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
                     if self.local_ip != tunnel['ip_address']:
                         tunnel_id = tunnel.get('id', tunnel['ip_address'])
                         tun_name = '%s-%s' % (tunnel_type, tunnel_id)
-                        self.tun_br.add_tunnel_port(tun_name,
-                                                    tunnel['ip_address'],
-                                                    self.local_ip,
-                                                    tunnel_type,
-                                                    self.vxlan_udp_port)
+                        self.setup_tunnel_port(tun_name,
+                                               tunnel['ip_address'],
+                                               tunnel_type)
         except Exception as e:
             LOG.debug(_("Unable to sync tunnel IP %(local_ip)s: %(e)s"),
                       {'local_ip': self.local_ip, 'e': e})
index 7b42fb314d13c951eb8e86e40d509e355703b0b0..01488b447e9ea7ca9e4a58379503869c63f94e90 100644 (file)
@@ -38,3 +38,13 @@ MINIMUM_OVS_VXLAN_VERSION = "1.10"
 
 # The different types of tunnels
 TUNNEL_NETWORK_TYPES = [TYPE_GRE, TYPE_VXLAN]
+
+# Various tables for tunneling flows
+PATCH_LV_TO_TUN = 1
+GRE_TUN_TO_LV = 2
+VXLAN_TUN_TO_LV = 3
+LEARN_FROM_TUN = 10
+UCAST_TO_TUN = 20
+FLOOD_TO_TUN = 21
+# Map tunnel types to tables number
+TUN_TABLE = {TYPE_GRE: GRE_TUN_TO_LV, TYPE_VXLAN: VXLAN_TUN_TO_LV}
index d7c0deb988012fffeed5786296bb06f93890b974..5f6192a382f637776098c2458889d2ba5fd07426 100644 (file)
@@ -331,17 +331,13 @@ class TestOvsNeutronAgent(base.BaseTestCase):
                              "int_ofport")
 
     def test_port_unbound(self):
-        with contextlib.nested(
-            mock.patch.object(self.agent.tun_br, "delete_flows"),
-            mock.patch.object(self.agent, "reclaim_local_vlan")
-        ) as (delfl_fn, reclvl_fn):
+        with mock.patch.object(self.agent, "reclaim_local_vlan") as reclvl_fn:
             self.agent.enable_tunneling = True
             lvm = mock.Mock()
             lvm.network_type = "gre"
             lvm.vif_ports = {"vif1": mock.Mock()}
             self.agent.local_vlan_map["netuid12345"] = lvm
             self.agent.port_unbound("vif1", "netuid12345")
-            self.assertTrue(delfl_fn.called)
             self.assertTrue(reclvl_fn.called)
             reclvl_fn.called = False
 
index 83d585c4f4d416834a04a42184ad46cf8b5e1af0..c9f0f5791b2f58743bf53de4d0870db7cd7978e3 100644 (file)
@@ -37,13 +37,20 @@ VIF_MAC = '3c:09:24:1e:78:23'
 OFPORT_NUM = 1
 VIF_PORT = ovs_lib.VifPort('port', OFPORT_NUM,
                            VIF_ID, VIF_MAC, 'switch')
-VIF_PORTS = {LV_ID: VIF_PORT}
+VIF_PORTS = {VIF_ID: VIF_PORT}
 LVM = ovs_neutron_agent.LocalVLANMapping(LV_ID, 'gre', None, LS_ID, VIF_PORTS)
 LVM_FLAT = ovs_neutron_agent.LocalVLANMapping(
     LV_ID, 'flat', 'net1', LS_ID, VIF_PORTS)
 LVM_VLAN = ovs_neutron_agent.LocalVLANMapping(
     LV_ID, 'vlan', 'net1', LS_ID, VIF_PORTS)
+
+GRE_OFPORTS = set(['11', '12'])
+VXLAN_OFPORTS = set(['13', '14'])
+TUN_OFPORTS = {constants.TYPE_GRE: GRE_OFPORTS,
+               constants.TYPE_VXLAN: VXLAN_OFPORTS}
+
 BCAST_MAC = "01:00:00:00:00:00/01:00:00:00:00:00"
+UCAST_MAC = "00:00:00:00:00:00/01:00:00:00:00:00"
 
 
 class DummyPort:
@@ -108,8 +115,45 @@ class TunnelTest(base.BaseTestCase):
             'patch-tun', 'patch-int').AndReturn(self.TUN_OFPORT)
         self.mock_tun_bridge.add_patch_port(
             'patch-int', 'patch-tun').AndReturn(self.INT_OFPORT)
+
         self.mock_tun_bridge.remove_all_flows()
-        self.mock_tun_bridge.add_flow(priority=1, actions='drop')
+        self.mock_tun_bridge.add_flow(priority=1,
+                                      in_port=self.INT_OFPORT,
+                                      actions="resubmit(,%s)" %
+                                      constants.PATCH_LV_TO_TUN)
+        self.mock_tun_bridge.add_flow(priority=0, actions='drop')
+        self.mock_tun_bridge.add_flow(table=constants.PATCH_LV_TO_TUN,
+                                      dl_dst=UCAST_MAC,
+                                      actions="resubmit(,%s)" %
+                                      constants.UCAST_TO_TUN)
+        self.mock_tun_bridge.add_flow(table=constants.PATCH_LV_TO_TUN,
+                                      dl_dst=BCAST_MAC,
+                                      actions="resubmit(,%s)" %
+                                      constants.FLOOD_TO_TUN)
+        for tunnel_type in constants.TUNNEL_NETWORK_TYPES:
+            self.mock_tun_bridge.add_flow(
+                table=constants.TUN_TABLE[tunnel_type],
+                priority=0,
+                actions="drop")
+        learned_flow = ("table=%s,"
+                        "priority=1,"
+                        "hard_timeout=300,"
+                        "NXM_OF_VLAN_TCI[0..11],"
+                        "load:0->NXM_OF_VLAN_TCI[],"
+                        "load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],"
+                        "output:NXM_OF_IN_PORT[]" %
+                        constants.UCAST_TO_TUN)
+        self.mock_tun_bridge.add_flow(table=constants.LEARN_FROM_TUN,
+                                      priority=1,
+                                      actions="learn(%s),output:%s" %
+                                      (learned_flow, self.INT_OFPORT))
+        self.mock_tun_bridge.add_flow(table=constants.UCAST_TO_TUN,
+                                      priority=0,
+                                      actions="resubmit(,%s)" %
+                                      constants.FLOOD_TO_TUN)
+        self.mock_tun_bridge.add_flow(table=constants.FLOOD_TO_TUN,
+                                      priority=0,
+                                      actions="drop")
 
         self.mox.StubOutWithMock(ip_lib, 'device_exists')
         ip_lib.device_exists('tunnel_bridge_mapping', 'sudo').AndReturn(True)
@@ -153,14 +197,18 @@ class TunnelTest(base.BaseTestCase):
         self.mox.VerifyAll()
 
     def testProvisionLocalVlan(self):
-        action_string = 'set_tunnel:%s,normal' % LS_ID
-        self.mock_tun_bridge.add_flow(priority=4, in_port=self.INT_OFPORT,
-                                      dl_vlan=LV_ID, actions=action_string)
-
-        action_string = 'mod_vlan_vid:%s,output:%s' % (LV_ID, self.INT_OFPORT)
-        self.mock_tun_bridge.add_flow(priority=3, tun_id=LS_ID,
-                                      dl_dst=BCAST_MAC, actions=action_string)
-
+        self.mock_tun_bridge.mod_flow(table=constants.FLOOD_TO_TUN,
+                                      priority=1,
+                                      dl_vlan=LV_ID,
+                                      actions="strip_vlan,"
+                                      "set_tunnel:%s,output:%s" %
+                                      (LS_ID, ','.join(GRE_OFPORTS)))
+
+        self.mock_tun_bridge.add_flow(table=constants.TUN_TABLE['gre'],
+                                      priority=1,
+                                      tun_id=LS_ID,
+                                      actions="mod_vlan_vid:%s,resubmit(,%s)" %
+                                      (LV_ID, constants.LEARN_FROM_TUN))
         self.mox.ReplayAll()
 
         a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
@@ -169,6 +217,7 @@ class TunnelTest(base.BaseTestCase):
                                               'sudo', 2, ['gre'],
                                               self.VETH_MTU)
         a.available_local_vlans = set([LV_ID])
+        a.tun_br_ofports = TUN_OFPORTS
         a.provision_local_vlan(NET_UUID, constants.TYPE_GRE, None, LS_ID)
         self.mox.VerifyAll()
 
@@ -240,8 +289,8 @@ class TunnelTest(base.BaseTestCase):
         self.mox.VerifyAll()
 
     def testReclaimLocalVlan(self):
-        self.mock_tun_bridge.delete_flows(tun_id=LVM.segmentation_id)
-
+        self.mock_tun_bridge.delete_flows(
+            table=constants.TUN_TABLE['gre'], tun_id=LS_ID)
         self.mock_tun_bridge.delete_flows(dl_vlan=LVM.vlan)
 
         self.mox.ReplayAll()
@@ -307,11 +356,6 @@ class TunnelTest(base.BaseTestCase):
                                               'tag', str(LVM.vlan))
         self.mock_int_bridge.delete_flows(in_port=VIF_PORT.ofport)
 
-        action_string = 'mod_vlan_vid:%s,normal' % LV_ID
-        self.mock_tun_bridge.add_flow(priority=3, tun_id=LS_ID,
-                                      dl_dst=VIF_PORT.vif_mac,
-                                      actions=action_string)
-
         self.mox.ReplayAll()
         a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
                                               self.TUN_BRIDGE,
@@ -323,15 +367,10 @@ class TunnelTest(base.BaseTestCase):
         self.mox.VerifyAll()
 
     def testPortUnbound(self):
-        self.mock_int_bridge.set_db_attribute('Port', VIF_PORT.port_name,
-                                              'tag', str(LVM.vlan))
-        self.mock_int_bridge.delete_flows(in_port=VIF_PORT.ofport)
+        self.mox.StubOutWithMock(
+            ovs_neutron_agent.OVSNeutronAgent, 'reclaim_local_vlan')
+        ovs_neutron_agent.OVSNeutronAgent.reclaim_local_vlan(NET_UUID, LVM)
 
-        action_string = 'mod_vlan_vid:%s,normal' % LV_ID
-        self.mock_tun_bridge.add_flow(priority=3, tun_id=LS_ID,
-                                      dl_dst=VIF_PORT.vif_mac,
-                                      actions=action_string)
-        self.mock_tun_bridge.delete_flows(dl_dst=VIF_MAC, tun_id=LS_ID)
         self.mox.ReplayAll()
 
         a = ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
@@ -340,9 +379,6 @@ class TunnelTest(base.BaseTestCase):
                                               'sudo', 2, ['gre'],
                                               self.VETH_MTU)
         a.local_vlan_map[NET_UUID] = LVM
-        a.port_bound(VIF_PORT, NET_UUID, 'gre', None, LS_ID)
-        a.available_local_vlans = set([LV_ID])
-        a.local_vlan_map[NET_UUID] = LVM
         a.port_unbound(VIF_ID, NET_UUID)
         self.mox.VerifyAll()