diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_int.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_int.py index 515ebd3441..407f1f5916 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_int.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_int.py @@ -140,6 +140,11 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge): return ofpp.OFPMatch(vlan_vid=vlan_tag | ofp.OFPVID_PRESENT, eth_dst=dst_mac) + @staticmethod + def _dvr_trans_match(ofp, ofpp, vlan_tag, dst_mac, gateway_mac): + return ofpp.OFPMatch(vlan_vid=vlan_tag | ofp.OFPVID_PRESENT, + eth_dst=dst_mac, eth_src=gateway_mac) + @staticmethod def _dvr_to_src_mac_table_id(network_type): if network_type == p_const.TYPE_VLAN: @@ -168,19 +173,26 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge): ofpp.OFPActionPopVlan(), ofpp.OFPActionOutput(dst_port, 0), ] + match = self._dvr_trans_match(ofp, ofpp, vlan_tag=vlan_tag, + dst_mac=dst_mac, gateway_mac=gateway_mac) self.install_apply_actions(table_id=constants.TRANSIENT_TABLE, priority=20, match=match, actions=actions) - def delete_dvr_to_src_mac(self, network_type, vlan_tag, dst_mac): + def delete_dvr_to_src_mac(self, network_type, vlan_tag, gateway_mac, + dst_mac): table_id = self._dvr_to_src_mac_table_id(network_type) (_dp, ofp, ofpp) = self._get_dp() match = self._dvr_to_src_mac_match(ofp, ofpp, vlan_tag=vlan_tag, dst_mac=dst_mac) - for table in (table_id, constants.TRANSIENT_TABLE): - self.uninstall_flows( - strict=True, priority=20, table_id=table, match=match) + self.uninstall_flows(strict=True, priority=20, + table_id=table_id, match=match) + + match = self._dvr_trans_match(ofp, ofpp, vlan_tag=vlan_tag, + dst_mac=dst_mac, gateway_mac=gateway_mac) + self.uninstall_flows(strict=True, priority=20, + table_id=constants.TRANSIENT_TABLE, match=match) def add_dvr_mac_vlan(self, mac, port): self.install_goto(table_id=constants.LOCAL_SWITCHING, 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 357dab158f..bd8988959d 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 @@ -637,7 +637,9 @@ class OVSDVRNeutronAgent(object): comp_port = self.local_ports[vif_id] self.int_br.delete_dvr_to_src_mac( network_type=network_type, - vlan_tag=vlan_to_use, dst_mac=comp_port.get_mac()) + vlan_tag=vlan_to_use, + gateway_mac=subnet_info['gateway_mac'], + dst_mac=comp_port.get_mac()) ldm.remove_all_compute_ofports() self.int_br.delete_dvr_dst_mac_for_arp( network_type=network_type, @@ -691,12 +693,15 @@ class OVSDVRNeutronAgent(object): ldm = self.local_dvr_map[sub_uuid] ldm.remove_compute_ofport(port.vif_id) vlan_to_use = lvm.vlan + subnet_info = ldm.get_subnet_info() if lvm.network_type == n_const.TYPE_VLAN: vlan_to_use = lvm.segmentation_id # first remove this vm port rule self.int_br.delete_dvr_to_src_mac( network_type=lvm.network_type, - vlan_tag=vlan_to_use, dst_mac=ovsport.get_mac()) + vlan_tag=vlan_to_use, + gateway_mac=subnet_info['gateway_mac'], + dst_mac=ovsport.get_mac()) # release port state self.local_ports.pop(port.vif_id, None) @@ -712,12 +717,15 @@ class OVSDVRNeutronAgent(object): ldm = self.local_dvr_map[sub_uuid] ldm.set_csnat_ofport(constants.OFPORT_INVALID) vlan_to_use = lvm.vlan + subnet_info = ldm.get_subnet_info() if lvm.network_type == n_const.TYPE_VLAN: vlan_to_use = lvm.segmentation_id # then remove csnat port rule self.int_br.delete_dvr_to_src_mac( network_type=lvm.network_type, - vlan_tag=vlan_to_use, dst_mac=ovsport.get_mac()) + vlan_tag=vlan_to_use, + gateway_mac=subnet_info['gateway_mac'], + dst_mac=ovsport.get_mac()) if not ldm.is_dvr_owned(): # if not owned by DVR (only used for csnat), remove this # subnet state altogether